net/bnxt: add core changes for EM and EEM lookups
[dpdk.git] / drivers / net / bnxt / tf_core / tf_em.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2020 Broadcom
3  * All rights reserved.
4  */
5
6 #include <string.h>
7 #include <rte_common.h>
8 #include <rte_errno.h>
9 #include <rte_log.h>
10
11 #include "tf_core.h"
12 #include "tf_em.h"
13 #include "tf_msg.h"
14 #include "tfp.h"
15 #include "lookup3.h"
16 #include "tf_ext_flow_handle.h"
17
18 #include "bnxt.h"
19
20
21 static uint32_t tf_em_get_key_mask(int num_entries)
22 {
23         uint32_t mask = num_entries - 1;
24
25         if (num_entries & 0x7FFF)
26                 return 0;
27
28         if (num_entries > (128 * 1024 * 1024))
29                 return 0;
30
31         return mask;
32 }
33
34 static void tf_em_create_key_entry(struct cfa_p4_eem_entry_hdr *result,
35                                    uint8_t             *in_key,
36                                    struct cfa_p4_eem_64b_entry *key_entry)
37 {
38         key_entry->hdr.word1 = result->word1;
39
40         if (result->word1 & CFA_P4_EEM_ENTRY_ACT_REC_INT_MASK)
41                 key_entry->hdr.pointer = result->pointer;
42         else
43                 key_entry->hdr.pointer = result->pointer;
44
45         memcpy(key_entry->key, in_key, TF_HW_EM_KEY_MAX_SIZE + 4);
46
47 #ifdef TF_EEM_DEBUG
48         dump_raw((uint8_t *)key_entry, TF_EM_KEY_RECORD_SIZE, "Create raw:");
49 #endif
50 }
51
52 /** insert EEM entry API
53  *
54  * returns:
55  *  0
56  *  TF_ERR          - unable to get lock
57  *
58  * insert callback returns:
59  *   0
60  *   TF_ERR_EM_DUP  - key is already in table
61  */
62 static int tf_insert_eem_entry(struct tf_tbl_scope_cb      *tbl_scope_cb,
63                                struct tf_insert_em_entry_parms *parms)
64 {
65         uint32_t           mask;
66         uint32_t           key0_hash;
67         uint32_t           key1_hash;
68         uint32_t           key0_index;
69         uint32_t           key1_index;
70         struct cfa_p4_eem_64b_entry key_entry;
71         uint32_t           index;
72         enum hcapi_cfa_em_table_type table_type;
73         uint32_t           gfid;
74         struct hcapi_cfa_hwop op;
75         struct hcapi_cfa_key_tbl key_tbl;
76         struct hcapi_cfa_key_data key_obj;
77         struct hcapi_cfa_key_loc key_loc;
78         uint64_t big_hash;
79         int rc;
80
81         /* Get mask to use on hash */
82         mask = tf_em_get_key_mask(tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE].num_entries);
83
84         if (!mask)
85                 return -EINVAL;
86
87 #ifdef TF_EEM_DEBUG
88         dump_raw((uint8_t *)parms->key, TF_HW_EM_KEY_MAX_SIZE + 4, "In Key");
89 #endif
90
91         big_hash = hcapi_cfa_key_hash((uint64_t *)parms->key,
92                                       (TF_HW_EM_KEY_MAX_SIZE + 4) * 8);
93         key0_hash = (uint32_t)(big_hash >> 32);
94         key1_hash = (uint32_t)(big_hash & 0xFFFFFFFF);
95
96         key0_index = key0_hash & mask;
97         key1_index = key1_hash & mask;
98
99 #ifdef TF_EEM_DEBUG
100         TFP_DRV_LOG(DEBUG, "Key0 hash:0x%08x\n", key0_hash);
101         TFP_DRV_LOG(DEBUG, "Key1 hash:0x%08x\n", key1_hash);
102 #endif
103         /*
104          * Use the "result" arg to populate all of the key entry then
105          * store the byte swapped "raw" entry in a local copy ready
106          * for insertion in to the table.
107          */
108         tf_em_create_key_entry((struct cfa_p4_eem_entry_hdr *)parms->em_record,
109                                 ((uint8_t *)parms->key),
110                                 &key_entry);
111
112         /*
113          * Try to add to Key0 table, if that does not work then
114          * try the key1 table.
115          */
116         index = key0_index;
117         op.opcode = HCAPI_CFA_HWOPS_ADD;
118         key_tbl.base0 = (uint8_t *)
119         &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY0_TABLE];
120         key_obj.offset = (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
121         key_obj.data = (uint8_t *)&key_entry;
122         key_obj.size = TF_EM_KEY_RECORD_SIZE;
123
124         rc = hcapi_cfa_key_hw_op(&op,
125                                  &key_tbl,
126                                  &key_obj,
127                                  &key_loc);
128
129         if (rc == 0) {
130                 table_type = TF_KEY0_TABLE;
131         } else {
132                 index = key1_index;
133
134                 key_tbl.base0 = (uint8_t *)
135                 &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[TF_KEY1_TABLE];
136                 key_obj.offset =
137                         (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
138
139                 rc = hcapi_cfa_key_hw_op(&op,
140                                          &key_tbl,
141                                          &key_obj,
142                                          &key_loc);
143                 if (rc != 0)
144                         return rc;
145
146                 table_type = TF_KEY1_TABLE;
147         }
148
149         TF_SET_GFID(gfid,
150                     index,
151                     table_type);
152         TF_SET_FLOW_ID(parms->flow_id,
153                        gfid,
154                        TF_GFID_TABLE_EXTERNAL,
155                        parms->dir);
156         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
157                                      0,
158                                      0,
159                                      0,
160                                      index,
161                                      0,
162                                      table_type);
163
164         return 0;
165 }
166
167 /**
168  * Insert EM internal entry API
169  *
170  *  returns:
171  *     0 - Success
172  */
173 static int tf_insert_em_internal_entry(struct tf                       *tfp,
174                                        struct tf_insert_em_entry_parms *parms)
175 {
176         int       rc;
177         uint32_t  gfid;
178         uint16_t  rptr_index = 0;
179         uint8_t   rptr_entry = 0;
180         uint8_t   num_of_entries = 0;
181         struct tf_session *session =
182                 (struct tf_session *)(tfp->session->core_data);
183         struct stack *pool = &session->em_pool[parms->dir];
184         uint32_t index;
185
186         rc = stack_pop(pool, &index);
187
188         if (rc != 0) {
189                 TFP_DRV_LOG(ERR,
190                    "dir:%d, EM entry index allocation failed\n",
191                    parms->dir);
192                 return rc;
193         }
194
195         rptr_index = index * TF_SESSION_EM_ENTRY_SIZE;
196         rc = tf_msg_insert_em_internal_entry(tfp,
197                                              parms,
198                                              &rptr_index,
199                                              &rptr_entry,
200                                              &num_of_entries);
201         if (rc != 0)
202                 return -1;
203
204         PMD_DRV_LOG(ERR,
205                    "Internal entry @ Index:%d rptr_index:0x%x rptr_entry:0x%x num_of_entries:%d\n",
206                    index * TF_SESSION_EM_ENTRY_SIZE,
207                    rptr_index,
208                    rptr_entry,
209                    num_of_entries);
210
211         TF_SET_GFID(gfid,
212                     ((rptr_index << TF_EM_INTERNAL_INDEX_SHIFT) |
213                      rptr_entry),
214                     0); /* N/A for internal table */
215
216         TF_SET_FLOW_ID(parms->flow_id,
217                        gfid,
218                        TF_GFID_TABLE_INTERNAL,
219                        parms->dir);
220
221         TF_SET_FIELDS_IN_FLOW_HANDLE(parms->flow_handle,
222                                      num_of_entries,
223                                      0,
224                                      0,
225                                      rptr_index,
226                                      rptr_entry,
227                                      0);
228         return 0;
229 }
230
231 /** Delete EM internal entry API
232  *
233  * returns:
234  * 0
235  * -EINVAL
236  */
237 static int tf_delete_em_internal_entry(struct tf                       *tfp,
238                                        struct tf_delete_em_entry_parms *parms)
239 {
240         int rc;
241         struct tf_session *session =
242                 (struct tf_session *)(tfp->session->core_data);
243         struct stack *pool = &session->em_pool[parms->dir];
244
245         rc = tf_msg_delete_em_entry(tfp, parms);
246
247         /* Return resource to pool */
248         if (rc == 0)
249                 stack_push(pool, parms->index / TF_SESSION_EM_ENTRY_SIZE);
250
251         return rc;
252 }
253
254
255 /** delete EEM hash entry API
256  *
257  * returns:
258  *   0
259  *   -EINVAL      - parameter error
260  *   TF_NO_SESSION    - bad session ID
261  *   TF_ERR_TBL_SCOPE - invalid table scope
262  *   TF_ERR_TBL_IF    - invalid table interface
263  *
264  * insert callback returns
265  *   0
266  *   TF_NO_EM_MATCH - entry not found
267  */
268 static int tf_delete_eem_entry(struct tf_tbl_scope_cb *tbl_scope_cb,
269                                struct tf_delete_em_entry_parms *parms)
270 {
271         enum hcapi_cfa_em_table_type hash_type;
272         uint32_t index;
273         struct hcapi_cfa_hwop op;
274         struct hcapi_cfa_key_tbl key_tbl;
275         struct hcapi_cfa_key_data key_obj;
276         struct hcapi_cfa_key_loc key_loc;
277         int rc;
278
279         if (parms->flow_handle == 0)
280                 return -EINVAL;
281
282         TF_GET_HASH_TYPE_FROM_FLOW_HANDLE(parms->flow_handle, hash_type);
283         TF_GET_INDEX_FROM_FLOW_HANDLE(parms->flow_handle, index);
284
285         op.opcode = HCAPI_CFA_HWOPS_DEL;
286         key_tbl.base0 = (uint8_t *)
287         &tbl_scope_cb->em_ctx_info[parms->dir].em_tables[(hash_type == 0 ?
288                                                           TF_KEY0_TABLE :
289                                                           TF_KEY1_TABLE)];
290         key_obj.offset = (index * TF_EM_KEY_RECORD_SIZE) % TF_EM_PAGE_SIZE;
291         key_obj.data = NULL;
292         key_obj.size = TF_EM_KEY_RECORD_SIZE;
293
294         rc = hcapi_cfa_key_hw_op(&op,
295                                  &key_tbl,
296                                  &key_obj,
297                                  &key_loc);
298
299         if (!rc)
300                 return rc;
301
302         return 0;
303 }
304
305 /** insert EM hash entry API
306  *
307  *    returns:
308  *    0       - Success
309  *    -EINVAL - Error
310  */
311 int tf_em_insert_entry(struct tf *tfp,
312                        struct tf_insert_em_entry_parms *parms)
313 {
314         struct tf_tbl_scope_cb *tbl_scope_cb;
315
316         tbl_scope_cb = tbl_scope_cb_find
317                 ((struct tf_session *)(tfp->session->core_data),
318                 parms->tbl_scope_id);
319         if (tbl_scope_cb == NULL) {
320                 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
321                 return -EINVAL;
322         }
323
324         /* Process the EM entry per Table Scope type */
325         if (parms->mem == TF_MEM_EXTERNAL)
326                 /* External EEM */
327                 return tf_insert_eem_entry
328                         (tbl_scope_cb, parms);
329         else if (parms->mem == TF_MEM_INTERNAL)
330                 /* Internal EM */
331                 return tf_insert_em_internal_entry(tfp, parms);
332
333         return -EINVAL;
334 }
335
336 /** Delete EM hash entry API
337  *
338  *    returns:
339  *    0       - Success
340  *    -EINVAL - Error
341  */
342 int tf_em_delete_entry(struct tf *tfp,
343                        struct tf_delete_em_entry_parms *parms)
344 {
345         struct tf_tbl_scope_cb *tbl_scope_cb;
346
347         tbl_scope_cb = tbl_scope_cb_find
348                 ((struct tf_session *)(tfp->session->core_data),
349                 parms->tbl_scope_id);
350         if (tbl_scope_cb == NULL) {
351                 TFP_DRV_LOG(ERR, "Invalid tbl_scope_cb\n");
352                 return -EINVAL;
353         }
354         if (parms->mem == TF_MEM_EXTERNAL)
355                 return tf_delete_eem_entry(tbl_scope_cb, parms);
356         else if (parms->mem == TF_MEM_INTERNAL)
357                 return tf_delete_em_internal_entry(tfp, parms);
358
359         return -EINVAL;
360 }