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