net/ice/base: add inner VLAN protocol type for QinQ filter
[dpdk.git] / drivers / net / bnxt / hcapi / hcapi_cfa_p4.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5 #include <inttypes.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <stdbool.h>
9 #include <string.h>
10 #include "lookup3.h"
11 #include "rand.h"
12
13 #include "hcapi_cfa_defs.h"
14
15 #define HCAPI_CFA_LKUP_SEED_MEM_SIZE 512
16 uint32_t hcapi_cfa_lkup_lkup3_init_cfg;
17 uint32_t hcapi_cfa_lkup_em_seed_mem[HCAPI_CFA_LKUP_SEED_MEM_SIZE];
18 bool hcapi_cfa_lkup_init;
19
20 static inline uint32_t SWAP_WORDS32(uint32_t val32)
21 {
22         return (((val32 & 0x0000ffff) << 16) |
23                 ((val32 & 0xffff0000) >> 16));
24 }
25
26 static void hcapi_cfa_seeds_init(void)
27 {
28         int i;
29         uint32_t r;
30
31         if (hcapi_cfa_lkup_init)
32                 return;
33
34         hcapi_cfa_lkup_init = true;
35
36         /* Initialize the lfsr */
37         rand_init();
38
39         /* RX and TX use the same seed values */
40         hcapi_cfa_lkup_lkup3_init_cfg = SWAP_WORDS32(rand32());
41
42         for (i = 0; i < HCAPI_CFA_LKUP_SEED_MEM_SIZE / 2; i++) {
43                 r = SWAP_WORDS32(rand32());
44                 hcapi_cfa_lkup_em_seed_mem[i * 2] = r;
45                 r = SWAP_WORDS32(rand32());
46                 hcapi_cfa_lkup_em_seed_mem[i * 2 + 1] = (r & 0x1);
47         }
48 }
49
50 /* CRC32i support for Key0 hash */
51 #define ucrc32(ch, crc) (crc32tbl[((crc) ^ (ch)) & 0xff] ^ ((crc) >> 8))
52 #define crc32(x, y) crc32i(~0, x, y)
53
54 static const uint32_t crc32tbl[] = {    /* CRC polynomial 0xedb88320 */
55 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
56 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
57 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
58 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
59 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
60 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
61 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
62 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
63 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
64 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
65 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
66 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
67 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
68 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
69 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
70 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
71 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
72 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
73 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
74 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
75 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
76 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
77 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
78 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
79 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
80 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
81 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
82 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
83 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
84 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
85 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
86 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
87 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
88 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
89 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
90 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
91 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
92 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
93 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
94 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
95 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
96 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
97 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
98 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
99 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
100 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
101 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
102 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
103 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
104 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
105 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
106 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
107 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
108 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
109 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
110 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
111 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
112 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
113 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
114 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
115 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
116 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
117 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
118 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
119 };
120
121 static uint32_t hcapi_cfa_crc32i(uint32_t crc, const uint8_t *buf, size_t len)
122 {
123         int l;
124
125 #ifdef TF_EEM_DEBUG
126         TFP_DRV_LOG(DEBUG, "CRC2:");
127 #endif
128         for (l = (len - 1); l >= 0; l--) {
129                 crc = ucrc32(buf[l], crc);
130 #ifdef TF_EEM_DEBUG
131                 TFP_DRV_LOG(DEBUG,
132                             "%02X %08X %08X\n",
133                             (buf[l] & 0xff),
134                             crc,
135                             ~crc);
136 #endif
137         }
138
139 #ifdef TF_EEM_DEBUG
140         TFP_DRV_LOG(DEBUG, "\n");
141 #endif
142
143         return ~crc;
144 }
145
146 static uint32_t hcapi_cfa_crc32_hash(uint8_t *key)
147 {
148         int i;
149         uint32_t index;
150         uint32_t val1, val2;
151         uint8_t temp[4];
152         uint8_t *kptr = key;
153
154         /* Do byte-wise XOR of the 52-byte HASH key first. */
155         index = *key;
156         kptr--;
157
158         for (i = CFA_P4_EEM_KEY_MAX_SIZE - 2; i >= 0; i--) {
159                 index = index ^ *kptr;
160                 kptr--;
161         }
162
163         /* Get seeds */
164         val1 = hcapi_cfa_lkup_em_seed_mem[index * 2];
165         val2 = hcapi_cfa_lkup_em_seed_mem[index * 2 + 1];
166
167         temp[3] = (uint8_t)(val1 >> 24);
168         temp[2] = (uint8_t)(val1 >> 16);
169         temp[1] = (uint8_t)(val1 >> 8);
170         temp[0] = (uint8_t)(val1 & 0xff);
171         val1 = 0;
172
173         /* Start with seed */
174         if (!(val2 & 0x1))
175                 val1 = hcapi_cfa_crc32i(~val1, temp, 4);
176
177         val1 = hcapi_cfa_crc32i(~val1,
178                       (key - (CFA_P4_EEM_KEY_MAX_SIZE - 1)),
179                       CFA_P4_EEM_KEY_MAX_SIZE);
180
181         /* End with seed */
182         if (val2 & 0x1)
183                 val1 = hcapi_cfa_crc32i(~val1, temp, 4);
184
185         return val1;
186 }
187
188 static uint32_t hcapi_cfa_lookup3_hash(uint8_t *in_key)
189 {
190         uint32_t val1;
191
192         val1 = hashword(((const uint32_t *)(uintptr_t *)in_key) + 1,
193                          CFA_P4_EEM_KEY_MAX_SIZE / (sizeof(uint32_t)),
194                          hcapi_cfa_lkup_lkup3_init_cfg);
195
196         return val1;
197 }
198
199
200 uint64_t hcapi_get_table_page(struct hcapi_cfa_em_table *mem,
201                               uint32_t page)
202 {
203         int level = 0;
204         uint64_t addr;
205
206         if (mem == NULL)
207                 return 0;
208
209         /*
210          * Use the level according to the num_level of page table
211          */
212         level = mem->num_lvl - 1;
213
214         addr = (uintptr_t)mem->pg_tbl[level].pg_va_tbl[page];
215
216         return addr;
217 }
218
219 /** Approximation of HCAPI hcapi_cfa_key_hash()
220  *
221  * Return:
222  *
223  */
224 uint64_t hcapi_cfa_key_hash(uint64_t *key_data,
225                             uint16_t bitlen)
226 {
227         uint32_t key0_hash;
228         uint32_t key1_hash;
229
230         /*
231          * Init the seeds if needed
232          */
233         if (!hcapi_cfa_lkup_init)
234                 hcapi_cfa_seeds_init();
235
236         key0_hash = hcapi_cfa_crc32_hash(((uint8_t *)key_data) +
237                                               (bitlen / 8) - 1);
238
239         key1_hash = hcapi_cfa_lookup3_hash((uint8_t *)key_data);
240
241         return ((uint64_t)key0_hash) << 32 | (uint64_t)key1_hash;
242 }
243
244 static int hcapi_cfa_key_hw_op_put(struct hcapi_cfa_hwop *op,
245                                    struct hcapi_cfa_key_data *key_obj)
246 {
247         int rc = 0;
248
249         memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
250                key_obj->offset,
251                key_obj->data,
252                key_obj->size);
253
254         return rc;
255 }
256
257 static int hcapi_cfa_key_hw_op_get(struct hcapi_cfa_hwop *op,
258                                    struct hcapi_cfa_key_data *key_obj)
259 {
260         int rc = 0;
261
262         memcpy(key_obj->data,
263                (uint8_t *)(uintptr_t)op->hw.base_addr +
264                key_obj->offset,
265                key_obj->size);
266
267         return rc;
268 }
269
270 static int hcapi_cfa_key_hw_op_add(struct hcapi_cfa_hwop *op,
271                                    struct hcapi_cfa_key_data *key_obj)
272 {
273         int rc = 0;
274         struct cfa_p4_eem_64b_entry table_entry;
275
276         /*
277          * Is entry free?
278          */
279         memcpy(&table_entry,
280                (uint8_t *)(uintptr_t)op->hw.base_addr +
281                key_obj->offset,
282                key_obj->size);
283
284         /*
285          * If this is entry is valid then report failure
286          */
287         if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT))
288                 return -1;
289
290         memcpy((uint8_t *)(uintptr_t)op->hw.base_addr +
291                key_obj->offset,
292                key_obj->data,
293                key_obj->size);
294
295         return rc;
296 }
297
298 static int hcapi_cfa_key_hw_op_del(struct hcapi_cfa_hwop *op,
299                                    struct hcapi_cfa_key_data *key_obj)
300 {
301         int rc = 0;
302         struct cfa_p4_eem_64b_entry table_entry;
303
304         /*
305          * Read entry
306          */
307         memcpy(&table_entry,
308                (uint8_t *)(uintptr_t)op->hw.base_addr +
309                key_obj->offset,
310                key_obj->size);
311
312         /*
313          * If this is not a valid entry then report failure.
314          */
315         if (table_entry.hdr.word1 & (1 << CFA_P4_EEM_ENTRY_VALID_SHIFT)) {
316                 /*
317                  * If a key has been provided then verify the key matches
318                  * before deleting the entry.
319                  */
320                 if (key_obj->data != NULL) {
321                         if (memcmp(&table_entry,
322                                    key_obj->data,
323                                    key_obj->size) != 0)
324                                 return -1;
325                 }
326         } else {
327                 return -1;
328         }
329
330
331         /*
332          * Delete entry
333          */
334         memset((uint8_t *)(uintptr_t)op->hw.base_addr +
335                key_obj->offset,
336                0,
337                key_obj->size);
338
339         return rc;
340 }
341
342
343 /** Apporiximation of hcapi_cfa_key_hw_op()
344  *
345  *
346  */
347 int hcapi_cfa_key_hw_op(struct hcapi_cfa_hwop *op,
348                         struct hcapi_cfa_key_tbl *key_tbl,
349                         struct hcapi_cfa_key_data *key_obj,
350                         struct hcapi_cfa_key_loc *key_loc)
351 {
352         int rc = 0;
353
354         if (op == NULL ||
355             key_tbl == NULL ||
356             key_obj == NULL ||
357             key_loc == NULL)
358                 return -1;
359
360         op->hw.base_addr =
361                 hcapi_get_table_page((struct hcapi_cfa_em_table *)
362                                      key_tbl->base0,
363                                      key_obj->offset / key_tbl->page_size);
364         /* Offset is adjusted to be the offset into the page */
365         key_obj->offset = key_obj->offset % key_tbl->page_size;
366
367         if (op->hw.base_addr == 0)
368                 return -1;
369
370         switch (op->opcode) {
371         case HCAPI_CFA_HWOPS_PUT: /**< Write to HW operation */
372                 rc = hcapi_cfa_key_hw_op_put(op, key_obj);
373                 break;
374         case HCAPI_CFA_HWOPS_GET: /**< Read from HW operation */
375                 rc = hcapi_cfa_key_hw_op_get(op, key_obj);
376                 break;
377         case HCAPI_CFA_HWOPS_ADD:
378                 /**< For operations which require more than
379                  * simple writes to HW, this operation is used. The
380                  * distinction with this operation when compared
381                  * to the PUT ops is that this operation is used
382                  * in conjunction with the HCAPI_CFA_HWOPS_DEL
383                  * op to remove the operations issued by the
384                  * ADD OP.
385                  */
386
387                 rc = hcapi_cfa_key_hw_op_add(op, key_obj);
388
389                 break;
390         case HCAPI_CFA_HWOPS_DEL:
391                 rc = hcapi_cfa_key_hw_op_del(op, key_obj);
392                 break;
393         default:
394                 rc = -1;
395                 break;
396         }
397
398         return rc;
399 }