net/bnxt: support generic hash table
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_gen_tbl.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include "tf_core.h"
9 #include "tfp.h"
10 #include "ulp_mapper.h"
11 #include "ulp_flow_db.h"
12
13 /* Retrieve the generic table  initialization parameters for the tbl_idx */
14 static struct bnxt_ulp_generic_tbl_params*
15 ulp_mapper_gen_tbl_params_get(uint32_t tbl_idx)
16 {
17         if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ)
18                 return NULL;
19
20         return &ulp_generic_tbl_params[tbl_idx];
21 }
22
23 /*
24  * Initialize the generic table list
25  *
26  * mapper_data [in] Pointer to the mapper data and the generic table is
27  * part of it
28  *
29  * returns 0 on success
30  */
31 int32_t
32 ulp_mapper_generic_tbl_list_init(struct bnxt_ulp_mapper_data *mapper_data)
33 {
34         struct bnxt_ulp_generic_tbl_params *tbl;
35         struct ulp_mapper_gen_tbl_list *entry;
36         struct ulp_hash_create_params cparams;
37         uint32_t idx, size;
38
39         /* Allocate the generic tables. */
40         for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) {
41                 tbl = ulp_mapper_gen_tbl_params_get(idx);
42                 if (!tbl) {
43                         BNXT_TF_DBG(ERR, "Failed to get gen table parms %d\n",
44                                     idx);
45                         return -EINVAL;
46                 }
47                 entry = &mapper_data->gen_tbl_list[idx];
48                 if (tbl->result_num_entries != 0) {
49                         /* assign the name */
50                         entry->gen_tbl_name = tbl->name;
51                         /* add 4 bytes for reference count */
52                         entry->mem_data_size = (tbl->result_num_entries + 1) *
53                                 (tbl->result_num_bytes + sizeof(uint32_t));
54
55                         /* allocate the big chunk of memory */
56                         entry->mem_data = rte_zmalloc("ulp mapper gen tbl",
57                                                       entry->mem_data_size, 0);
58                         if (!entry->mem_data) {
59                                 BNXT_TF_DBG(ERR,
60                                             "%s:Failed to alloc gen table %d\n",
61                                             tbl->name, idx);
62                                 return -ENOMEM;
63                         }
64                         /* Populate the generic table container */
65                         entry->container.num_elem = tbl->result_num_entries;
66                         entry->container.byte_data_size = tbl->result_num_bytes;
67                         entry->container.ref_count =
68                                 (uint32_t *)entry->mem_data;
69                         size = sizeof(uint32_t) * (tbl->result_num_entries + 1);
70                         entry->container.byte_data = &entry->mem_data[size];
71                         entry->container.byte_order = tbl->result_byte_order;
72                 } else {
73                         BNXT_TF_DBG(ERR, "%s:Invalid gen table num of ent %d\n",
74                                     tbl->name, idx);
75                         return -EINVAL;
76                 }
77                 if (tbl->hash_tbl_entries) {
78                         cparams.key_size = tbl->key_num_bytes;
79                         cparams.num_buckets = tbl->num_buckets;
80                         cparams.num_hash_tbl_entries = tbl->hash_tbl_entries;
81                         cparams.num_key_entries = tbl->result_num_entries;
82                         if (ulp_gen_hash_tbl_list_init(&cparams,
83                                                        &entry->hash_tbl)) {
84                                 BNXT_TF_DBG(ERR,
85                                             "%s: Failed to alloc hash tbl %d\n",
86                                             tbl->name, idx);
87                                 return -ENOMEM;
88                         }
89                 }
90         }
91         /* success */
92         return 0;
93 }
94
95 /*
96  * Free the generic table list
97  *
98  * mapper_data [in] Pointer to the mapper data and the generic table is
99  * part of it
100  *
101  * returns 0 on success
102  */
103 int32_t
104 ulp_mapper_generic_tbl_list_deinit(struct bnxt_ulp_mapper_data *mapper_data)
105 {
106         struct ulp_mapper_gen_tbl_list *tbl_list;
107         uint32_t idx;
108
109         /* iterate the generic table. */
110         for (idx = 0; idx < BNXT_ULP_GEN_TBL_MAX_SZ; idx++) {
111                 tbl_list = &mapper_data->gen_tbl_list[idx];
112                 if (tbl_list->mem_data) {
113                         rte_free(tbl_list->mem_data);
114                         tbl_list->mem_data = NULL;
115                 }
116                 if (tbl_list->hash_tbl) {
117                         ulp_gen_hash_tbl_list_deinit(tbl_list->hash_tbl);
118                         tbl_list->hash_tbl = NULL;
119                 }
120         }
121         /* success */
122         return 0;
123 }
124
125 /*
126  * Get the generic table list entry
127  *
128  * tbl_list [in] - Ptr to generic table
129  * key [in] - Key index to the table
130  * entry [out] - output will include the entry if found
131  *
132  * returns 0 on success.
133  */
134 int32_t
135 ulp_mapper_gen_tbl_entry_get(struct ulp_mapper_gen_tbl_list *tbl_list,
136                              uint32_t key,
137                              struct ulp_mapper_gen_tbl_entry *entry)
138 {
139         /* populate the output and return the values */
140         if (key > tbl_list->container.num_elem) {
141                 BNXT_TF_DBG(ERR, "%s: invalid key %x:%x\n",
142                             tbl_list->gen_tbl_name, key,
143                             tbl_list->container.num_elem);
144                 return -EINVAL;
145         }
146         entry->ref_count = &tbl_list->container.ref_count[key];
147         entry->byte_data_size = tbl_list->container.byte_data_size;
148         entry->byte_data = &tbl_list->container.byte_data[key *
149                 entry->byte_data_size];
150         entry->byte_order = tbl_list->container.byte_order;
151         return 0;
152 }
153
154 /*
155  * utility function to calculate the table idx
156  *
157  * res_sub_type [in] - Resource sub type
158  * dir [in] - Direction
159  *
160  * returns None
161  */
162 int32_t
163 ulp_mapper_gen_tbl_idx_calculate(uint32_t res_sub_type, uint32_t dir)
164 {
165         int32_t tbl_idx;
166
167         /* Validate for direction */
168         if (dir >= TF_DIR_MAX) {
169                 BNXT_TF_DBG(ERR, "invalid argument %x\n", dir);
170                 return -EINVAL;
171         }
172         tbl_idx = (res_sub_type << 1) | (dir & 0x1);
173         if (tbl_idx >= BNXT_ULP_GEN_TBL_MAX_SZ) {
174                 BNXT_TF_DBG(ERR, "invalid table index %x\n", tbl_idx);
175                 return -EINVAL;
176         }
177         return tbl_idx;
178 }
179
180 /*
181  * Set the data in the generic table entry, Data is in Big endian format
182  *
183  * entry [in] - generic table entry
184  * len [in] - The length of the data in bits to be set
185  * data [in] - pointer to the data to be used for setting the value.
186  * data_size [in] - length of the data pointer in bytes.
187  *
188  * returns 0 on success
189  */
190 int32_t
191 ulp_mapper_gen_tbl_entry_data_set(struct ulp_mapper_gen_tbl_entry *entry,
192                                   uint32_t len, uint8_t *data,
193                                   uint32_t data_size)
194 {
195         /* validate the null arguments */
196         if (!entry || !data) {
197                 BNXT_TF_DBG(ERR, "invalid argument\n");
198                 return -EINVAL;
199         }
200
201         /* check the size of the buffer for validation */
202         if (len > ULP_BYTE_2_BITS(entry->byte_data_size) ||
203             data_size < ULP_BITS_2_BYTE(len)) {
204                 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x\n",
205                             len, entry->byte_data_size);
206                 return -EINVAL;
207         }
208         memcpy(entry->byte_data, data, ULP_BITS_2_BYTE(len));
209         return 0;
210 }
211
212 /*
213  * Get the data in the generic table entry, Data is in Big endian format
214  *
215  * entry [in] - generic table entry
216  * offset [in] - The offset in bits where the data has to get
217  * len [in] - The length of the data in bits to be get
218  * data [out] - pointer to the data to be used for setting the value.
219  * data_size [in] - The size of data in bytes
220  *
221  * returns 0 on success
222  */
223 int32_t
224 ulp_mapper_gen_tbl_entry_data_get(struct ulp_mapper_gen_tbl_entry *entry,
225                                   uint32_t offset, uint32_t len, uint8_t *data,
226                                   uint32_t data_size)
227 {
228         /* validate the null arguments */
229         if (!entry || !data) {
230                 BNXT_TF_DBG(ERR, "invalid argument\n");
231                 return -EINVAL;
232         }
233
234         /* check the size of the buffer for validation */
235         if ((offset + len) > ULP_BYTE_2_BITS(entry->byte_data_size) ||
236             len > ULP_BYTE_2_BITS(data_size)) {
237                 BNXT_TF_DBG(ERR, "invalid offset or length %x:%x:%x\n",
238                             offset, len, entry->byte_data_size);
239                 return -EINVAL;
240         }
241         if (entry->byte_order == BNXT_ULP_BYTE_ORDER_LE)
242                 ulp_bs_pull_lsb(entry->byte_data, data, data_size, offset, len);
243         else
244                 ulp_bs_pull_msb(entry->byte_data, data, offset, len);
245
246         return 0;
247 }
248
249 /*
250  * Free the generic table list entry
251  *
252  * ulp_ctx [in] - Pointer to the ulp context
253  * res [in] - Pointer to flow db resource entry
254  *
255  * returns 0 on success
256  */
257 int32_t
258 ulp_mapper_gen_tbl_res_free(struct bnxt_ulp_context *ulp_ctx,
259                             struct ulp_flow_db_res_params *res)
260 {
261         struct bnxt_ulp_mapper_data *mapper_data;
262         struct ulp_mapper_gen_tbl_list *gen_tbl_list;
263         struct ulp_mapper_gen_tbl_entry entry;
264         struct ulp_gen_hash_entry_params hash_entry;
265         int32_t tbl_idx;
266         uint32_t fid = 0;
267         uint32_t key_idx;
268
269         /* Extract the resource sub type and direction */
270         tbl_idx = ulp_mapper_gen_tbl_idx_calculate(res->resource_sub_type,
271                                                    res->direction);
272         if (tbl_idx < 0) {
273                 BNXT_TF_DBG(ERR, "invalid argument %x:%x\n",
274                             res->resource_sub_type, res->direction);
275                 return -EINVAL;
276         }
277
278         mapper_data = bnxt_ulp_cntxt_ptr2_mapper_data_get(ulp_ctx);
279         if (!mapper_data) {
280                 BNXT_TF_DBG(ERR, "invalid ulp context %x\n", tbl_idx);
281                 return -EINVAL;
282         }
283         /* get the generic table  */
284         gen_tbl_list = &mapper_data->gen_tbl_list[tbl_idx];
285
286         /* Get the generic table entry*/
287         if (gen_tbl_list->hash_tbl) {
288                 /* use the hash index to get the value */
289                 hash_entry.hash_index = (uint32_t)res->resource_hndl;
290                 if (ulp_gen_hash_tbl_list_index_search(gen_tbl_list->hash_tbl,
291                                                        &hash_entry)) {
292                         BNXT_TF_DBG(ERR, "Unable to find has entry %x:%x\n",
293                                     tbl_idx, hash_entry.hash_index);
294                         return -EINVAL;
295                 }
296                 key_idx = hash_entry.key_idx;
297
298         } else {
299                 key_idx =  (uint32_t)res->resource_hndl;
300         }
301         if (ulp_mapper_gen_tbl_entry_get(gen_tbl_list, key_idx, &entry)) {
302                 BNXT_TF_DBG(ERR, "Gen tbl entry get failed %x:%" PRIX64 "\n",
303                             tbl_idx, res->resource_hndl);
304                 return -EINVAL;
305         }
306
307         /* Decrement the reference count */
308         if (!ULP_GEN_TBL_REF_CNT(&entry)) {
309                 BNXT_TF_DBG(ERR, "generic table corrupt %x:%" PRIX64 "\n",
310                             tbl_idx, res->resource_hndl);
311                 return -EINVAL;
312         }
313         ULP_GEN_TBL_REF_CNT_DEC(&entry);
314
315         /* retain the details since there are other users */
316         if (ULP_GEN_TBL_REF_CNT(&entry))
317                 return 0;
318
319         /* Delete the generic table entry. First extract the fid */
320         if (ulp_mapper_gen_tbl_entry_data_get(&entry, ULP_GEN_TBL_FID_OFFSET,
321                                               ULP_GEN_TBL_FID_SIZE_BITS,
322                                               (uint8_t *)&fid,
323                                               sizeof(fid))) {
324                 BNXT_TF_DBG(ERR, "Unable to get fid %x:%" PRIX64 "\n",
325                             tbl_idx, res->resource_hndl);
326                 return -EINVAL;
327         }
328         fid = tfp_be_to_cpu_32(fid);
329
330         /* Destroy the flow associated with the shared flow id */
331         if (ulp_mapper_flow_destroy(ulp_ctx, BNXT_ULP_FDB_TYPE_RID,
332                                     fid))
333                 BNXT_TF_DBG(ERR, "Error in deleting shared flow id %x\n", fid);
334
335         /* Delete the entry from the hash table */
336         if (gen_tbl_list->hash_tbl)
337                 ulp_gen_hash_tbl_list_del(gen_tbl_list->hash_tbl, &hash_entry);
338
339         /* clear the byte data of the generic table entry */
340         memset(entry.byte_data, 0, entry.byte_data_size);
341
342         return 0;
343 }
344
345 /*
346  * Write the generic table list hash entry
347  *
348  * tbl_list [in] - pointer to the generic table list
349  * hash_entry [in] -  Hash table entry
350  * gen_tbl_ent [out] - generic table entry
351  *
352  * returns 0 on success.
353  */
354 int32_t
355 ulp_mapper_gen_tbl_hash_entry_add(struct ulp_mapper_gen_tbl_list *tbl_list,
356                                   struct ulp_gen_hash_entry_params *hash_entry,
357                                   struct ulp_mapper_gen_tbl_entry *gen_tbl_ent)
358 {
359         uint32_t key;
360         int32_t rc = 0;
361
362         switch (hash_entry->search_flag) {
363         case ULP_GEN_HASH_SEARCH_FOUND:
364                 BNXT_TF_DBG(ERR, "%s: gen hash entry already present\n",
365                             tbl_list->gen_tbl_name);
366                 return -EINVAL;
367         case ULP_GEN_HASH_SEARCH_FULL:
368                 BNXT_TF_DBG(ERR, "%s: gen hash table is full\n",
369                             tbl_list->gen_tbl_name);
370                 return -EINVAL;
371         case ULP_GEN_HASH_SEARCH_MISSED:
372                 rc = ulp_gen_hash_tbl_list_add(tbl_list->hash_tbl, hash_entry);
373                 if (rc) {
374                         BNXT_TF_DBG(ERR, "%s: gen hash table add failed\n",
375                                     tbl_list->gen_tbl_name);
376                         return -EINVAL;
377                 }
378                 key = hash_entry->key_idx;
379                 gen_tbl_ent->ref_count = &tbl_list->container.ref_count[key];
380                 gen_tbl_ent->byte_data_size =
381                         tbl_list->container.byte_data_size;
382                 gen_tbl_ent->byte_data = &tbl_list->container.byte_data[key *
383                         gen_tbl_ent->byte_data_size];
384                 gen_tbl_ent->byte_order = tbl_list->container.byte_order;
385                 break;
386         default:
387                 BNXT_TF_DBG(ERR, "%s: invalid search flag\n",
388                             tbl_list->gen_tbl_name);
389                 return -EINVAL;
390         }
391
392         return rc;
393 }