net/bnxt: add shadow table capability with search
[dpdk.git] / drivers / net / bnxt / tf_core / tf_shadow_tbl.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include "tf_common.h"
7 #include "tf_util.h"
8 #include "tfp.h"
9 #include "tf_core.h"
10 #include "tf_shadow_tbl.h"
11 #include "tf_hash.h"
12
13 /**
14  * The implementation includes 3 tables per table table type.
15  * - hash table
16  *   - sized so that a minimum of 4 slots per shadow entry are available to
17  *   minimize the likelihood of collisions.
18  * - shadow key table
19  *   - sized to the number of entries requested and is directly indexed
20  *   - the index is zero based and is the table index - the base address
21  *   - the data associated with the entry is stored in the key table.
22  *   - The stored key is actually the data associated with the entry.
23  * - shadow result table
24  *   - the result table is stored separately since it only needs to be accessed
25  *   when the key matches.
26  *   - the result has a back pointer to the hash table via the hb handle.  The
27  *   hb handle is a 32 bit represention of the hash with a valid bit, bucket
28  *   element index, and the hash index.  It is necessary to store the hb handle
29  *   with the result since subsequent removes only provide the table index.
30  *
31  * - Max entries is limited in the current implementation since bit 15 is the
32  *   valid bit in the hash table.
33  * - A 16bit hash is calculated and masked based on the number of entries
34  * - 64b wide bucket is used and broken into 4x16bit elements.
35  *   This decision is based on quicker bucket scanning to determine if any
36  *   elements are in use.
37  * - bit 15 of each bucket element is the valid, this is done to prevent having
38  *   to read the larger key/result data for determining VALID.  It also aids
39  *   in the more efficient scanning of the bucket for slot usage.
40  */
41
42 /*
43  * The maximum number of shadow entries supported.  The value also doubles as
44  * the maximum number of hash buckets.  There are only 15 bits of data per
45  * bucket to point to the shadow tables.
46  */
47 #define TF_SHADOW_ENTRIES_MAX (1 << 15)
48
49 /* The number of elements(BE) per hash bucket (HB) */
50 #define TF_SHADOW_HB_NUM_ELEM (4)
51 #define TF_SHADOW_BE_VALID (1 << 15)
52 #define TF_SHADOW_BE_IS_VALID(be) (((be) & TF_SHADOW_BE_VALID) != 0)
53
54 /**
55  * The hash bucket handle is 32b
56  * - bit 31, the Valid bit
57  * - bit 29-30, the element
58  * - bits 0-15, the hash idx (is masked based on the allocated size)
59  */
60 #define TF_SHADOW_HB_HANDLE_IS_VALID(hndl) (((hndl) & (1 << 31)) != 0)
61 #define TF_SHADOW_HB_HANDLE_CREATE(idx, be) ((1 << 31) | \
62                                              ((be) << 29) | (idx))
63
64 #define TF_SHADOW_HB_HANDLE_BE_GET(hdl) (((hdl) >> 29) & \
65                                          (TF_SHADOW_HB_NUM_ELEM - 1))
66
67 #define TF_SHADOW_HB_HANDLE_HASH_GET(ctxt, hdl)((hdl) & \
68                                                 (ctxt)->hash_ctxt.hid_mask)
69
70 /**
71  * The idx provided by the caller is within a region, so currently the base is
72  * either added or subtracted from the idx to ensure it can be used as a
73  * compressed index
74  */
75
76 /* Convert the table index to a shadow index */
77 #define TF_SHADOW_IDX_TO_SHIDX(ctxt, idx) ((idx) - \
78                                            (ctxt)->shadow_ctxt.base_addr)
79
80 /* Convert the shadow index to a tbl index */
81 #define TF_SHADOW_SHIDX_TO_IDX(ctxt, idx) ((idx) + \
82                                            (ctxt)->shadow_ctxt.base_addr)
83
84 /* Simple helper masks for clearing en element from the bucket */
85 #define TF_SHADOW_BE0_MASK_CLEAR(hb) ((hb) & 0xffffffffffff0000ull)
86 #define TF_SHADOW_BE1_MASK_CLEAR(hb) ((hb) & 0xffffffff0000ffffull)
87 #define TF_SHADOW_BE2_MASK_CLEAR(hb) ((hb) & 0xffff0000ffffffffull)
88 #define TF_SHADOW_BE3_MASK_CLEAR(hb) ((hb) & 0x0000ffffffffffffull)
89
90 /**
91  * This should be coming from external, but for now it is assumed that no key
92  * is greater than 512 bits (64B).  This makes allocation of the key table
93  * easier without having to allocate on the fly.
94  */
95 #define TF_SHADOW_MAX_KEY_SZ 64
96
97 /*
98  * Local only defines for the internal data.
99  */
100
101 /**
102  * tf_shadow_tbl_shadow_key_entry is the key entry of the key table.
103  * The key stored in the table is the result data of the index table.
104  */
105 struct tf_shadow_tbl_shadow_key_entry {
106         uint8_t key[TF_SHADOW_MAX_KEY_SZ];
107 };
108
109 /**
110  * tf_shadow_tbl_shadow_result_entry is the result table entry.
111  * The result table writes are broken into two phases:
112  * - The search phase, which stores the hb_handle and key size and
113  * - The set phase, which writes the refcnt
114  */
115 struct tf_shadow_tbl_shadow_result_entry {
116         uint16_t key_size;
117         uint32_t refcnt;
118         uint32_t hb_handle;
119 };
120
121 /**
122  * tf_shadow_tbl_shadow_ctxt holds all information for accessing the key and
123  * result tables.
124  */
125 struct tf_shadow_tbl_shadow_ctxt {
126         struct tf_shadow_tbl_shadow_key_entry *sh_key_tbl;
127         struct tf_shadow_tbl_shadow_result_entry *sh_res_tbl;
128         uint32_t base_addr;
129         uint16_t num_entries;
130         uint16_t alloc_idx;
131 };
132
133 /**
134  * tf_shadow_tbl_hash_ctxt holds all information related to accessing the hash
135  * table.
136  */
137 struct tf_shadow_tbl_hash_ctxt {
138         uint64_t *hashtbl;
139         uint16_t hid_mask;
140         uint16_t hash_entries;
141 };
142
143 /**
144  * tf_shadow_tbl_ctxt holds the hash and shadow tables for the current shadow
145  * table db.  This structure is per table table type as each table table has
146  * it's own shadow and hash table.
147  */
148 struct tf_shadow_tbl_ctxt {
149         struct tf_shadow_tbl_shadow_ctxt shadow_ctxt;
150         struct tf_shadow_tbl_hash_ctxt hash_ctxt;
151 };
152
153 /**
154  * tf_shadow_tbl_db is the allocated db structure returned as an opaque
155  * void * pointer to the caller during create db.  It holds the pointers for
156  * each table associated with the db.
157  */
158 struct tf_shadow_tbl_db {
159         /* Each context holds the shadow and hash table information */
160         struct tf_shadow_tbl_ctxt *ctxt[TF_TBL_TYPE_MAX];
161 };
162
163 /**
164  * Simple routine that decides what table types can be searchable.
165  *
166  */
167 static int tf_shadow_tbl_is_searchable(enum tf_tbl_type type)
168 {
169         int rc = 0;
170
171         switch (type) {
172         case TF_TBL_TYPE_ACT_ENCAP_8B:
173         case TF_TBL_TYPE_ACT_ENCAP_16B:
174         case TF_TBL_TYPE_ACT_ENCAP_32B:
175         case TF_TBL_TYPE_ACT_ENCAP_64B:
176         case TF_TBL_TYPE_ACT_SP_SMAC:
177         case TF_TBL_TYPE_ACT_SP_SMAC_IPV4:
178         case TF_TBL_TYPE_ACT_SP_SMAC_IPV6:
179         case TF_TBL_TYPE_ACT_MODIFY_IPV4:
180         case TF_TBL_TYPE_ACT_MODIFY_SPORT:
181         case TF_TBL_TYPE_ACT_MODIFY_DPORT:
182                 rc = 1;
183                 break;
184         default:
185                 rc = 0;
186                 break;
187         };
188
189         return rc;
190 }
191
192 /**
193  * Returns the number of entries in the contexts shadow table.
194  */
195 static inline uint16_t
196 tf_shadow_tbl_sh_num_entries_get(struct tf_shadow_tbl_ctxt *ctxt)
197 {
198         return ctxt->shadow_ctxt.num_entries;
199 }
200
201 /**
202  * Compare the give key with the key in the shadow table.
203  *
204  * Returns 0 if the keys match
205  */
206 static int
207 tf_shadow_tbl_key_cmp(struct tf_shadow_tbl_ctxt *ctxt,
208                       uint8_t *key,
209                       uint16_t sh_idx,
210                       uint16_t size)
211 {
212         if (size != ctxt->shadow_ctxt.sh_res_tbl[sh_idx].key_size ||
213             sh_idx >= tf_shadow_tbl_sh_num_entries_get(ctxt) || !key)
214                 return -1;
215
216         return memcmp(key, ctxt->shadow_ctxt.sh_key_tbl[sh_idx].key, size);
217 }
218
219 /**
220  * Free the memory associated with the context.
221  */
222 static void
223 tf_shadow_tbl_ctxt_delete(struct tf_shadow_tbl_ctxt *ctxt)
224 {
225         if (!ctxt)
226                 return;
227
228         tfp_free(ctxt->hash_ctxt.hashtbl);
229         tfp_free(ctxt->shadow_ctxt.sh_key_tbl);
230         tfp_free(ctxt->shadow_ctxt.sh_res_tbl);
231 }
232
233 /**
234  * The TF Shadow TBL context is per TBL and holds all information relating to
235  * managing the shadow and search capability.  This routine allocated data that
236  * needs to be deallocated by the tf_shadow_tbl_ctxt_delete prior when deleting
237  * the shadow db.
238  */
239 static int
240 tf_shadow_tbl_ctxt_create(struct tf_shadow_tbl_ctxt *ctxt,
241                           uint16_t num_entries,
242                           uint16_t base_addr)
243 {
244         struct tfp_calloc_parms cparms;
245         uint16_t hash_size = 1;
246         uint16_t hash_mask;
247         int rc;
248
249         /* Hash table is a power of two that holds the number of entries */
250         if (num_entries > TF_SHADOW_ENTRIES_MAX) {
251                 TFP_DRV_LOG(ERR, "Too many entries for shadow %d > %d\n",
252                             num_entries,
253                             TF_SHADOW_ENTRIES_MAX);
254                 return -ENOMEM;
255         }
256
257         while (hash_size < num_entries)
258                 hash_size = hash_size << 1;
259
260         hash_mask = hash_size - 1;
261
262         /* Allocate the hash table */
263         cparms.nitems = hash_size;
264         cparms.size = sizeof(uint64_t);
265         cparms.alignment = 0;
266         rc = tfp_calloc(&cparms);
267         if (rc)
268                 goto error;
269         ctxt->hash_ctxt.hashtbl = cparms.mem_va;
270         ctxt->hash_ctxt.hid_mask = hash_mask;
271         ctxt->hash_ctxt.hash_entries = hash_size;
272
273         /* allocate the shadow tables */
274         /* allocate the shadow key table */
275         cparms.nitems = num_entries;
276         cparms.size = sizeof(struct tf_shadow_tbl_shadow_key_entry);
277         cparms.alignment = 0;
278         rc = tfp_calloc(&cparms);
279         if (rc)
280                 goto error;
281         ctxt->shadow_ctxt.sh_key_tbl = cparms.mem_va;
282
283         /* allocate the shadow result table */
284         cparms.nitems = num_entries;
285         cparms.size = sizeof(struct tf_shadow_tbl_shadow_result_entry);
286         cparms.alignment = 0;
287         rc = tfp_calloc(&cparms);
288         if (rc)
289                 goto error;
290         ctxt->shadow_ctxt.sh_res_tbl = cparms.mem_va;
291
292         ctxt->shadow_ctxt.num_entries = num_entries;
293         ctxt->shadow_ctxt.base_addr = base_addr;
294
295         return 0;
296 error:
297         tf_shadow_tbl_ctxt_delete(ctxt);
298
299         return -ENOMEM;
300 }
301
302 /**
303  * Get a shadow table context given the db and the table type
304  */
305 static struct tf_shadow_tbl_ctxt *
306 tf_shadow_tbl_ctxt_get(struct tf_shadow_tbl_db *shadow_db,
307                        enum tf_tbl_type type)
308 {
309         if (type >= TF_TBL_TYPE_MAX ||
310             !shadow_db ||
311             !shadow_db->ctxt[type])
312                 return NULL;
313
314         return shadow_db->ctxt[type];
315 }
316
317 /**
318  * Sets the hash entry into the table given the table context, hash bucket
319  * handle, and shadow index.
320  */
321 static inline int
322 tf_shadow_tbl_set_hash_entry(struct tf_shadow_tbl_ctxt *ctxt,
323                              uint32_t hb_handle,
324                              uint16_t sh_idx)
325 {
326         uint16_t hid = TF_SHADOW_HB_HANDLE_HASH_GET(ctxt, hb_handle);
327         uint16_t be = TF_SHADOW_HB_HANDLE_BE_GET(hb_handle);
328         uint64_t entry = sh_idx | TF_SHADOW_BE_VALID;
329
330         if (hid >= ctxt->hash_ctxt.hash_entries)
331                 return -EINVAL;
332
333         ctxt->hash_ctxt.hashtbl[hid] |= entry << (be * 16);
334         return 0;
335 }
336
337 /**
338  * Clears the hash entry given the TBL context and hash bucket handle.
339  */
340 static inline void
341 tf_shadow_tbl_clear_hash_entry(struct tf_shadow_tbl_ctxt *ctxt,
342                                uint32_t hb_handle)
343 {
344         uint16_t hid, be;
345         uint64_t *bucket;
346
347         if (!TF_SHADOW_HB_HANDLE_IS_VALID(hb_handle))
348                 return;
349
350         hid = TF_SHADOW_HB_HANDLE_HASH_GET(ctxt, hb_handle);
351         be = TF_SHADOW_HB_HANDLE_BE_GET(hb_handle);
352         bucket = &ctxt->hash_ctxt.hashtbl[hid];
353
354         switch (be) {
355         case 0:
356                 *bucket = TF_SHADOW_BE0_MASK_CLEAR(*bucket);
357                 break;
358         case 1:
359                 *bucket = TF_SHADOW_BE1_MASK_CLEAR(*bucket);
360                 break;
361         case 2:
362                 *bucket = TF_SHADOW_BE2_MASK_CLEAR(*bucket);
363                 break;
364         case 3:
365                 *bucket = TF_SHADOW_BE2_MASK_CLEAR(*bucket);
366                 break;
367         default:
368                 /*
369                  * Since the BE_GET masks non-inclusive bits, this will not
370                  * happen.
371                  */
372                 break;
373         }
374 }
375
376 /**
377  * Clears the shadow key and result entries given the table context and
378  * shadow index.
379  */
380 static void
381 tf_shadow_tbl_clear_sh_entry(struct tf_shadow_tbl_ctxt *ctxt,
382                              uint16_t sh_idx)
383 {
384         struct tf_shadow_tbl_shadow_key_entry *sk_entry;
385         struct tf_shadow_tbl_shadow_result_entry *sr_entry;
386
387         if (sh_idx >= tf_shadow_tbl_sh_num_entries_get(ctxt))
388                 return;
389
390         sk_entry = &ctxt->shadow_ctxt.sh_key_tbl[sh_idx];
391         sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[sh_idx];
392
393         /*
394          * memset key/result to zero for now, possibly leave the data alone
395          * in the future and rely on the valid bit in the hash table.
396          */
397         memset(sk_entry, 0, sizeof(struct tf_shadow_tbl_shadow_key_entry));
398         memset(sr_entry, 0, sizeof(struct tf_shadow_tbl_shadow_result_entry));
399 }
400
401 /**
402  * Binds the allocated tbl index with the hash and shadow tables.
403  * The entry will be incomplete until the set has happened with the result
404  * data.
405  */
406 int
407 tf_shadow_tbl_bind_index(struct tf_shadow_tbl_bind_index_parms *parms)
408 {
409         int rc;
410         uint16_t idx, len;
411         struct tf_shadow_tbl_ctxt *ctxt;
412         struct tf_shadow_tbl_db *shadow_db;
413         struct tf_shadow_tbl_shadow_key_entry *sk_entry;
414         struct tf_shadow_tbl_shadow_result_entry *sr_entry;
415
416         if (!parms || !TF_SHADOW_HB_HANDLE_IS_VALID(parms->hb_handle) ||
417             !parms->data) {
418                 TFP_DRV_LOG(ERR, "Invalid parms\n");
419                 return -EINVAL;
420         }
421
422         shadow_db = (struct tf_shadow_tbl_db *)parms->shadow_db;
423         ctxt = tf_shadow_tbl_ctxt_get(shadow_db, parms->type);
424         if (!ctxt) {
425                 TFP_DRV_LOG(DEBUG, "%s no ctxt for table\n",
426                             tf_tbl_type_2_str(parms->type));
427                 return -EINVAL;
428         }
429
430         idx = TF_SHADOW_IDX_TO_SHIDX(ctxt, parms->idx);
431         len = parms->data_sz_in_bytes;
432         if (idx >= tf_shadow_tbl_sh_num_entries_get(ctxt) ||
433             len > TF_SHADOW_MAX_KEY_SZ) {
434                 TFP_DRV_LOG(ERR, "%s:%s Invalid len (%d) > %d || oob idx %d\n",
435                             tf_dir_2_str(parms->dir),
436                             tf_tbl_type_2_str(parms->type),
437                             len,
438                             TF_SHADOW_MAX_KEY_SZ, idx);
439
440                 return -EINVAL;
441         }
442
443         rc = tf_shadow_tbl_set_hash_entry(ctxt, parms->hb_handle, idx);
444         if (rc)
445                 return -EINVAL;
446
447         sk_entry = &ctxt->shadow_ctxt.sh_key_tbl[idx];
448         sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[idx];
449
450         /* For tables, the data is the key */
451         memcpy(sk_entry->key, parms->data, len);
452
453         /* Write the result table */
454         sr_entry->key_size = len;
455         sr_entry->hb_handle = parms->hb_handle;
456         sr_entry->refcnt = 1;
457
458         return 0;
459 }
460
461 /**
462  * Deletes hash/shadow information if no more references.
463  *
464  * Returns 0 - The caller should delete the table entry in hardware.
465  * Returns non-zero - The number of references to the entry
466  */
467 int
468 tf_shadow_tbl_remove(struct tf_shadow_tbl_remove_parms *parms)
469 {
470         uint16_t idx;
471         uint32_t hb_handle;
472         struct tf_shadow_tbl_ctxt *ctxt;
473         struct tf_shadow_tbl_db *shadow_db;
474         struct tf_tbl_free_parms *fparms;
475         struct tf_shadow_tbl_shadow_result_entry *sr_entry;
476
477         if (!parms || !parms->fparms) {
478                 TFP_DRV_LOG(ERR, "Invalid parms\n");
479                 return -EINVAL;
480         }
481
482         fparms = parms->fparms;
483         if (!tf_shadow_tbl_is_searchable(fparms->type))
484                 return 0;
485         /*
486          * Initialize the ref count to zero.  The default would be to remove
487          * the entry.
488          */
489         fparms->ref_cnt = 0;
490
491         shadow_db = (struct tf_shadow_tbl_db *)parms->shadow_db;
492         ctxt = tf_shadow_tbl_ctxt_get(shadow_db, fparms->type);
493         if (!ctxt) {
494                 TFP_DRV_LOG(DEBUG, "%s no ctxt for table\n",
495                             tf_tbl_type_2_str(fparms->type));
496                 return 0;
497         }
498
499         idx = TF_SHADOW_IDX_TO_SHIDX(ctxt, fparms->idx);
500         if (idx >= tf_shadow_tbl_sh_num_entries_get(ctxt)) {
501                 TFP_DRV_LOG(DEBUG, "%s %d >= %d\n",
502                             tf_tbl_type_2_str(fparms->type),
503                             fparms->idx,
504                             tf_shadow_tbl_sh_num_entries_get(ctxt));
505                 return 0;
506         }
507
508         sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[idx];
509         if (sr_entry->refcnt <= 1) {
510                 hb_handle = sr_entry->hb_handle;
511                 tf_shadow_tbl_clear_hash_entry(ctxt, hb_handle);
512                 tf_shadow_tbl_clear_sh_entry(ctxt, idx);
513         } else {
514                 sr_entry->refcnt--;
515                 fparms->ref_cnt = sr_entry->refcnt;
516         }
517
518         return 0;
519 }
520
521 int
522 tf_shadow_tbl_search(struct tf_shadow_tbl_search_parms *parms)
523 {
524         uint16_t len;
525         uint64_t bucket;
526         uint32_t i, hid32;
527         struct tf_shadow_tbl_ctxt *ctxt;
528         struct tf_shadow_tbl_db *shadow_db;
529         uint16_t hid16, hb_idx, hid_mask, shtbl_idx, shtbl_key, be_valid;
530         struct tf_tbl_alloc_search_parms *sparms;
531         uint32_t be_avail = TF_SHADOW_HB_NUM_ELEM;
532
533         if (!parms || !parms->sparms) {
534                 TFP_DRV_LOG(ERR, "tbl search with invalid parms\n");
535                 return -EINVAL;
536         }
537
538         sparms = parms->sparms;
539         /* Check that caller was supposed to call search */
540         if (!tf_shadow_tbl_is_searchable(sparms->type))
541                 return -EINVAL;
542
543         /* Initialize return values to invalid */
544         sparms->hit = 0;
545         sparms->search_status = REJECT;
546         parms->hb_handle = 0;
547         sparms->ref_cnt = 0;
548
549         shadow_db = (struct tf_shadow_tbl_db *)parms->shadow_db;
550         ctxt = tf_shadow_tbl_ctxt_get(shadow_db, sparms->type);
551         if (!ctxt) {
552                 TFP_DRV_LOG(ERR, "%s Unable to get tbl mgr context\n",
553                             tf_tbl_type_2_str(sparms->type));
554                 return -EINVAL;
555         }
556
557         len = sparms->result_sz_in_bytes;
558         if (len > TF_SHADOW_MAX_KEY_SZ || !sparms->result || !len) {
559                 TFP_DRV_LOG(ERR, "%s:%s Invalid parms %d : %p\n",
560                             tf_dir_2_str(sparms->dir),
561                             tf_tbl_type_2_str(sparms->type),
562                             len,
563                             sparms->result);
564                 return -EINVAL;
565         }
566
567         /*
568          * Calculate the crc32
569          * Fold it to create a 16b value
570          * Reduce it to fit the table
571          */
572         hid32 = tf_hash_calc_crc32(sparms->result, len);
573         hid16 = (uint16_t)(((hid32 >> 16) & 0xffff) ^ (hid32 & 0xffff));
574         hid_mask = ctxt->hash_ctxt.hid_mask;
575         hb_idx = hid16 & hid_mask;
576
577         bucket = ctxt->hash_ctxt.hashtbl[hb_idx];
578         if (!bucket) {
579                 /* empty bucket means a miss and available entry */
580                 sparms->search_status = MISS;
581                 parms->hb_handle = TF_SHADOW_HB_HANDLE_CREATE(hb_idx, 0);
582                 sparms->idx = 0;
583                 return 0;
584         }
585
586         /* Set the avail to max so we can detect when there is an avail entry */
587         be_avail = TF_SHADOW_HB_NUM_ELEM;
588         for (i = 0; i < TF_SHADOW_HB_NUM_ELEM; i++) {
589                 shtbl_idx = (uint16_t)((bucket >> (i * 16)) & 0xffff);
590                 be_valid = TF_SHADOW_BE_IS_VALID(shtbl_idx);
591                 if (!be_valid) {
592                         /* The element is avail, keep going */
593                         be_avail = i;
594                         continue;
595                 }
596                 /* There is a valid entry, compare it */
597                 shtbl_key = shtbl_idx & ~TF_SHADOW_BE_VALID;
598                 if (!tf_shadow_tbl_key_cmp(ctxt,
599                                            sparms->result,
600                                            shtbl_key,
601                                            len)) {
602                         /*
603                          * It matches, increment the ref count if the caller
604                          * requested allocation and return the info
605                          */
606                         if (sparms->alloc)
607                                 ctxt->shadow_ctxt.sh_res_tbl[shtbl_key].refcnt =
608                         ctxt->shadow_ctxt.sh_res_tbl[shtbl_key].refcnt + 1;
609
610                         sparms->hit = 1;
611                         sparms->search_status = HIT;
612                         parms->hb_handle =
613                                 TF_SHADOW_HB_HANDLE_CREATE(hb_idx, i);
614                         sparms->idx = TF_SHADOW_SHIDX_TO_IDX(ctxt, shtbl_key);
615                         sparms->ref_cnt =
616                                 ctxt->shadow_ctxt.sh_res_tbl[shtbl_key].refcnt;
617
618                         return 0;
619                 }
620         }
621
622         /* No hits, return avail entry if exists */
623         if (be_avail < TF_SHADOW_HB_NUM_ELEM) {
624                 /*
625                  * There is an available hash entry, so return MISS and the
626                  * hash handle for the subsequent bind.
627                  */
628                 parms->hb_handle = TF_SHADOW_HB_HANDLE_CREATE(hb_idx, be_avail);
629                 sparms->search_status = MISS;
630                 sparms->hit = 0;
631                 sparms->idx = 0;
632         } else {
633                 /* No room for the entry in the hash table, must REJECT */
634                 sparms->search_status = REJECT;
635         }
636
637         return 0;
638 }
639
640 int
641 tf_shadow_tbl_insert(struct tf_shadow_tbl_insert_parms *parms)
642 {
643         uint16_t idx;
644         struct tf_shadow_tbl_ctxt *ctxt;
645         struct tf_tbl_set_parms *sparms;
646         struct tf_shadow_tbl_db *shadow_db;
647         struct tf_shadow_tbl_shadow_result_entry *sr_entry;
648
649         if (!parms || !parms->sparms) {
650                 TFP_DRV_LOG(ERR, "Null parms\n");
651                 return -EINVAL;
652         }
653
654         sparms = parms->sparms;
655         if (!sparms->data || !sparms->data_sz_in_bytes) {
656                 TFP_DRV_LOG(ERR, "%s:%s No result to set.\n",
657                             tf_dir_2_str(sparms->dir),
658                             tf_tbl_type_2_str(sparms->type));
659                 return -EINVAL;
660         }
661
662         shadow_db = (struct tf_shadow_tbl_db *)parms->shadow_db;
663         ctxt = tf_shadow_tbl_ctxt_get(shadow_db, sparms->type);
664         if (!ctxt) {
665                 /* We aren't tracking this table, so return success */
666                 TFP_DRV_LOG(DEBUG, "%s Unable to get tbl mgr context\n",
667                             tf_tbl_type_2_str(sparms->type));
668                 return 0;
669         }
670
671         idx = TF_SHADOW_IDX_TO_SHIDX(ctxt, sparms->idx);
672         if (idx >= tf_shadow_tbl_sh_num_entries_get(ctxt)) {
673                 TFP_DRV_LOG(ERR, "%s:%s Invalid idx(0x%x)\n",
674                             tf_dir_2_str(sparms->dir),
675                             tf_tbl_type_2_str(sparms->type),
676                             sparms->idx);
677                 return -EINVAL;
678         }
679
680         /* Write the result table, the key/hash has been written already */
681         sr_entry = &ctxt->shadow_ctxt.sh_res_tbl[idx];
682
683         /*
684          * If the handle is not valid, the bind was never called.  We aren't
685          * tracking this entry.
686          */
687         if (!TF_SHADOW_HB_HANDLE_IS_VALID(sr_entry->hb_handle))
688                 return 0;
689
690         return 0;
691 }
692
693 int
694 tf_shadow_tbl_free_db(struct tf_shadow_tbl_free_db_parms *parms)
695 {
696         struct tf_shadow_tbl_db *shadow_db;
697         int i;
698
699         TF_CHECK_PARMS1(parms);
700
701         shadow_db = (struct tf_shadow_tbl_db *)parms->shadow_db;
702         if (!shadow_db) {
703                 TFP_DRV_LOG(DEBUG, "Shadow db is NULL cannot be freed\n");
704                 return -EINVAL;
705         }
706
707         for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
708                 if (shadow_db->ctxt[i]) {
709                         tf_shadow_tbl_ctxt_delete(shadow_db->ctxt[i]);
710                         tfp_free(shadow_db->ctxt[i]);
711                 }
712         }
713
714         tfp_free(shadow_db);
715
716         return 0;
717 }
718
719 /**
720  * Allocate the table resources for search and allocate
721  *
722  */
723 int tf_shadow_tbl_create_db(struct tf_shadow_tbl_create_db_parms *parms)
724 {
725         int rc;
726         int i;
727         uint16_t base;
728         struct tfp_calloc_parms cparms;
729         struct tf_shadow_tbl_db *shadow_db = NULL;
730
731         TF_CHECK_PARMS1(parms);
732
733         /* Build the shadow DB per the request */
734         cparms.nitems = 1;
735         cparms.size = sizeof(struct tf_shadow_tbl_db);
736         cparms.alignment = 0;
737         rc = tfp_calloc(&cparms);
738         if (rc)
739                 return rc;
740         shadow_db = (void *)cparms.mem_va;
741
742         for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
743                 /* If the element didn't request an allocation no need
744                  * to create a pool nor verify if we got a reservation.
745                  */
746                 if (!parms->cfg->alloc_cnt[i] ||
747                     !tf_shadow_tbl_is_searchable(i)) {
748                         shadow_db->ctxt[i] = NULL;
749                         continue;
750                 }
751
752                 cparms.nitems = 1;
753                 cparms.size = sizeof(struct tf_shadow_tbl_ctxt);
754                 cparms.alignment = 0;
755                 rc = tfp_calloc(&cparms);
756                 if (rc)
757                         goto error;
758
759                 shadow_db->ctxt[i] = cparms.mem_va;
760                 base = parms->cfg->base_addr[i];
761                 rc = tf_shadow_tbl_ctxt_create(shadow_db->ctxt[i],
762                                                 parms->cfg->alloc_cnt[i],
763                                                 base);
764                 if (rc)
765                         goto error;
766         }
767
768         *parms->shadow_db = (void *)shadow_db;
769
770         TFP_DRV_LOG(INFO,
771                     "TF SHADOW TABLE - initialized\n");
772
773         return 0;
774 error:
775         for (i = 0; i < TF_TBL_TYPE_MAX; i++) {
776                 if (shadow_db->ctxt[i]) {
777                         tf_shadow_tbl_ctxt_delete(shadow_db->ctxt[i]);
778                         tfp_free(shadow_db->ctxt[i]);
779                 }
780         }
781
782         tfp_free(shadow_db);
783
784         return -ENOMEM;
785 }