fd211bbc3fda58db858b8aa3da6ec490b08b5445
[dpdk.git] / drivers / net / bnxt / tf_ulp / bnxt_ulp.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_log.h>
7 #include <rte_malloc.h>
8 #include <rte_flow.h>
9 #include <rte_flow_driver.h>
10 #include <rte_tailq.h>
11 #include <rte_spinlock.h>
12
13 #include "bnxt.h"
14 #include "bnxt_ulp.h"
15 #include "bnxt_tf_common.h"
16 #include "tf_core.h"
17 #include "tf_ext_flow_handle.h"
18
19 #include "ulp_template_db_enum.h"
20 #include "ulp_template_struct.h"
21 #include "ulp_mark_mgr.h"
22 #include "ulp_fc_mgr.h"
23 #include "ulp_flow_db.h"
24 #include "ulp_mapper.h"
25 #include "ulp_port_db.h"
26 #include "ulp_tun.h"
27 #include "ulp_ha_mgr.h"
28 #include "bnxt_tf_pmd_shim.h"
29
30 /* Linked list of all TF sessions. */
31 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
32                         STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
33
34 /* Mutex to synchronize bnxt_ulp_session_list operations. */
35 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
36
37 /* Spin lock to protect context global list */
38 rte_spinlock_t bnxt_ulp_ctxt_lock;
39 TAILQ_HEAD(cntx_list_entry_list, ulp_context_list_entry);
40 static struct cntx_list_entry_list ulp_cntx_list =
41         TAILQ_HEAD_INITIALIZER(ulp_cntx_list);
42
43 /* Static function declarations */
44 static int32_t bnxt_ulp_cntxt_list_init(void);
45 static int32_t bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx);
46 static void bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx);
47
48 /*
49  * Allow the deletion of context only for the bnxt device that
50  * created the session.
51  */
52 bool
53 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx)
54 {
55         if (!ulp_ctx || !ulp_ctx->cfg_data)
56                 return false;
57
58         if (!ulp_ctx->cfg_data->ref_cnt) {
59                 BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n");
60                 return true;
61         }
62
63         return false;
64 }
65
66 static int32_t
67 bnxt_ulp_devid_get(struct bnxt *bp,
68                    enum bnxt_ulp_device_id  *ulp_dev_id)
69 {
70         if (BNXT_CHIP_P5(bp)) {
71                 *ulp_dev_id = BNXT_ULP_DEVICE_ID_THOR;
72                 return 0;
73         }
74
75         if (BNXT_STINGRAY(bp))
76                 *ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY;
77         else
78                 /* Assuming Whitney */
79                 *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS;
80
81         return 0;
82 }
83
84 struct bnxt_ulp_app_capabilities_info *
85 bnxt_ulp_app_cap_list_get(uint32_t *num_entries)
86 {
87         if (!num_entries)
88                 return NULL;
89         *num_entries = BNXT_ULP_APP_CAP_TBL_MAX_SZ;
90         return ulp_app_cap_info_list;
91 }
92
93 static struct bnxt_ulp_resource_resv_info *
94 bnxt_ulp_app_resource_resv_list_get(uint32_t *num_entries)
95 {
96         if (num_entries == NULL)
97                 return NULL;
98         *num_entries = BNXT_ULP_APP_RESOURCE_RESV_LIST_MAX_SZ;
99         return ulp_app_resource_resv_list;
100 }
101
102 struct bnxt_ulp_resource_resv_info *
103 bnxt_ulp_resource_resv_list_get(uint32_t *num_entries)
104 {
105         if (!num_entries)
106                 return NULL;
107         *num_entries = BNXT_ULP_RESOURCE_RESV_LIST_MAX_SZ;
108         return ulp_resource_resv_list;
109 }
110
111 struct bnxt_ulp_glb_resource_info *
112 bnxt_ulp_app_glb_resource_info_list_get(uint32_t *num_entries)
113 {
114         if (!num_entries)
115                 return NULL;
116         *num_entries = BNXT_ULP_APP_GLB_RESOURCE_TBL_MAX_SZ;
117         return ulp_app_glb_resource_tbl;
118 }
119
120 static int32_t
121 bnxt_ulp_named_resources_calc(struct bnxt_ulp_context *ulp_ctx,
122                               struct bnxt_ulp_glb_resource_info *info,
123                               uint32_t num,
124                               struct tf_session_resources *res)
125 {
126         uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST, res_type, i;
127         enum tf_dir dir;
128         uint8_t app_id;
129         int32_t rc = 0;
130
131         if (ulp_ctx == NULL || info == NULL || res == NULL || num == 0) {
132                 BNXT_TF_DBG(ERR, "Invalid parms to named resources calc.\n");
133                 return -EINVAL;
134         }
135
136         rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
137         if (rc) {
138                 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
139                 return -EINVAL;
140         }
141
142         rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
143         if (rc) {
144                 BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
145                 return -EINVAL;
146         }
147
148         for (i = 0; i < num; i++) {
149                 if (dev_id != info[i].device_id || app_id != info[i].app_id)
150                         continue;
151                 dir = info[i].direction;
152                 res_type = info[i].resource_type;
153
154                 switch (info[i].resource_func) {
155                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
156                         res->ident_cnt[dir].cnt[res_type]++;
157                         break;
158                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
159                         res->tbl_cnt[dir].cnt[res_type]++;
160                         break;
161                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
162                         res->tcam_cnt[dir].cnt[res_type]++;
163                         break;
164                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
165                         res->em_cnt[dir].cnt[res_type]++;
166                         break;
167                 default:
168                         BNXT_TF_DBG(ERR, "Unknown resource func (0x%x)\n,",
169                                     info[i].resource_func);
170                         continue;
171                 }
172         }
173
174         return 0;
175 }
176
177 static int32_t
178 bnxt_ulp_unnamed_resources_calc(struct bnxt_ulp_context *ulp_ctx,
179                                 struct bnxt_ulp_resource_resv_info *info,
180                                 uint32_t num,
181                                 struct tf_session_resources *res)
182 {
183         uint32_t dev_id, res_type, i;
184         enum tf_dir dir;
185         uint8_t app_id;
186         int32_t rc = 0;
187
188         if (ulp_ctx == NULL || res == NULL || info == NULL || num == 0) {
189                 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
190                 return -EINVAL;
191         }
192
193         rc = bnxt_ulp_cntxt_app_id_get(ulp_ctx, &app_id);
194         if (rc) {
195                 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
196                 return -EINVAL;
197         }
198
199         rc = bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id);
200         if (rc) {
201                 BNXT_TF_DBG(ERR, "Unable to get the dev id from ulp.\n");
202                 return -EINVAL;
203         }
204
205         for (i = 0; i < num; i++) {
206                 if (app_id != info[i].app_id || dev_id != info[i].device_id)
207                         continue;
208                 dir = info[i].direction;
209                 res_type = info[i].resource_type;
210
211                 switch (info[i].resource_func) {
212                 case BNXT_ULP_RESOURCE_FUNC_IDENTIFIER:
213                         res->ident_cnt[dir].cnt[res_type] = info[i].count;
214                         break;
215                 case BNXT_ULP_RESOURCE_FUNC_INDEX_TABLE:
216                         res->tbl_cnt[dir].cnt[res_type] = info[i].count;
217                         break;
218                 case BNXT_ULP_RESOURCE_FUNC_TCAM_TABLE:
219                         res->tcam_cnt[dir].cnt[res_type] = info[i].count;
220                         break;
221                 case BNXT_ULP_RESOURCE_FUNC_EM_TABLE:
222                         res->em_cnt[dir].cnt[res_type] = info[i].count;
223                         break;
224                 default:
225                         break;
226                 }
227         }
228         return 0;
229 }
230
231 static int32_t
232 bnxt_ulp_tf_resources_get(struct bnxt_ulp_context *ulp_ctx,
233                           struct tf_session_resources *res)
234 {
235         struct bnxt_ulp_resource_resv_info *unnamed = NULL;
236         uint32_t unum;
237         int32_t rc = 0;
238
239         if (ulp_ctx == NULL || res == NULL) {
240                 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
241                 return -EINVAL;
242         }
243
244         unnamed = bnxt_ulp_resource_resv_list_get(&unum);
245         if (unnamed == NULL) {
246                 BNXT_TF_DBG(ERR, "Unable to get resource resv list.\n");
247                 return -EINVAL;
248         }
249
250         rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, res);
251         if (rc)
252                 BNXT_TF_DBG(ERR, "Unable to calc resources for session.\n");
253
254         return rc;
255 }
256
257 static int32_t
258 bnxt_ulp_tf_shared_session_resources_get(struct bnxt_ulp_context *ulp_ctx,
259                                          struct tf_session_resources *res)
260 {
261         struct bnxt_ulp_resource_resv_info *unnamed;
262         struct bnxt_ulp_glb_resource_info *named;
263         uint32_t unum, nnum;
264         int32_t rc;
265
266         if (ulp_ctx == NULL || res == NULL) {
267                 BNXT_TF_DBG(ERR, "Invalid arguments to get resources.\n");
268                 return -EINVAL;
269         }
270
271         /* Make sure the resources are zero before accumulating. */
272         memset(res, 0, sizeof(struct tf_session_resources));
273
274         /*
275          * Shared resources are comprised of both named and unnamed resources.
276          * First get the unnamed counts, and then add the named to the result.
277          */
278         /* Get the baseline counts */
279         unnamed = bnxt_ulp_app_resource_resv_list_get(&unum);
280         if (unnamed == NULL) {
281                 BNXT_TF_DBG(ERR, "Unable to get shared resource resv list.\n");
282                 return -EINVAL;
283         }
284         rc = bnxt_ulp_unnamed_resources_calc(ulp_ctx, unnamed, unum, res);
285         if (rc) {
286                 BNXT_TF_DBG(ERR, "Unable to calc resources for shared session.\n");
287                 return -EINVAL;
288         }
289
290         /* Get the named list and add the totals */
291         named = bnxt_ulp_app_glb_resource_info_list_get(&nnum);
292         if (named == NULL) {
293                 BNXT_TF_DBG(ERR, "Unable to get app global resource list\n");
294                 return -EINVAL;
295         }
296         rc = bnxt_ulp_named_resources_calc(ulp_ctx, named, nnum, res);
297         if (rc)
298                 BNXT_TF_DBG(ERR, "Unable to calc named resources\n");
299
300         return rc;
301 }
302
303 int32_t
304 bnxt_ulp_cntxt_app_caps_init(struct bnxt *bp,
305                              uint8_t app_id, uint32_t dev_id)
306 {
307         struct bnxt_ulp_app_capabilities_info *info;
308         uint32_t num = 0;
309         uint16_t i;
310         bool found = false;
311         struct bnxt_ulp_context *ulp_ctx = bp->ulp_ctx;
312
313         if (ULP_APP_DEV_UNSUPPORTED_ENABLED(ulp_ctx->cfg_data->ulp_flags)) {
314                 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
315                             app_id, dev_id);
316                 return -EINVAL;
317         }
318
319         info = bnxt_ulp_app_cap_list_get(&num);
320         if (!info || !num) {
321                 BNXT_TF_DBG(ERR, "Failed to get app capabilities.\n");
322                 return -EINVAL;
323         }
324
325         for (i = 0; i < num; i++) {
326                 if (info[i].app_id != app_id || info[i].device_id != dev_id)
327                         continue;
328                 found = true;
329                 if (info[i].flags & BNXT_ULP_APP_CAP_SHARED_EN)
330                         ulp_ctx->cfg_data->ulp_flags |=
331                                 BNXT_ULP_SHARED_SESSION_ENABLED;
332                 if (info[i].flags & BNXT_ULP_APP_CAP_HOT_UPGRADE_EN)
333                         ulp_ctx->cfg_data->ulp_flags |=
334                                 BNXT_ULP_HIGH_AVAIL_ENABLED;
335                 if (info[i].flags & BNXT_ULP_APP_CAP_UNICAST_ONLY)
336                         ulp_ctx->cfg_data->ulp_flags |=
337                                 BNXT_ULP_APP_UNICAST_ONLY;
338                 if (info[i].flags & BNXT_ULP_APP_CAP_SOCKET_DIRECT) {
339                         /* Enable socket direction only if MR is enabled in fw*/
340                         if (BNXT_MULTIROOT_EN(bp)) {
341                                 ulp_ctx->cfg_data->ulp_flags |=
342                                         BNXT_ULP_APP_SOCKET_DIRECT;
343                                 BNXT_TF_DBG(DEBUG,
344                                             "Socket Direct feature is enabled");
345                         }
346                 }
347         }
348         if (!found) {
349                 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
350                             app_id, dev_id);
351                 ulp_ctx->cfg_data->ulp_flags |= BNXT_ULP_APP_DEV_UNSUPPORTED;
352                 return -EINVAL;
353         }
354
355         return 0;
356 }
357
358 static void
359 ulp_ctx_shared_session_close(struct bnxt *bp,
360                              struct bnxt_ulp_session_state *session)
361 {
362         struct tf *tfp;
363         int32_t rc;
364
365         if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx))
366                 return;
367
368         tfp = bnxt_ulp_cntxt_shared_tfp_get(bp->ulp_ctx);
369         if (!tfp) {
370                 /*
371                  * Log it under debug since this is likely a case of the
372                  * shared session not being created.  For example, a failed
373                  * initialization.
374                  */
375                 BNXT_TF_DBG(DEBUG, "Failed to get shared tfp on close.\n");
376                 return;
377         }
378         rc = tf_close_session(tfp);
379         if (rc)
380                 BNXT_TF_DBG(ERR, "Failed to close the shared session rc=%d.\n",
381                             rc);
382         (void)bnxt_ulp_cntxt_shared_tfp_set(bp->ulp_ctx, NULL);
383
384         session->g_shared_tfp.session = NULL;
385 }
386
387 static int32_t
388 ulp_ctx_shared_session_open(struct bnxt *bp,
389                             struct bnxt_ulp_session_state *session)
390 {
391         struct rte_eth_dev *ethdev = bp->eth_dev;
392         struct tf_session_resources *resources;
393         struct tf_open_session_parms parms;
394         size_t copy_nbytes;
395         uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
396         int32_t rc = 0;
397         uint8_t app_id;
398
399         /* only perform this if shared session is enabled. */
400         if (!bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx))
401                 return 0;
402
403         memset(&parms, 0, sizeof(parms));
404
405         rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
406                                           parms.ctrl_chan_name);
407         if (rc) {
408                 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
409                             ethdev->data->port_id, rc);
410                 return rc;
411         }
412         resources = &parms.resources;
413
414         /*
415          * Need to account for size of ctrl_chan_name and 1 extra for Null
416          * terminator
417          */
418         copy_nbytes = sizeof(parms.ctrl_chan_name) -
419                 strlen(parms.ctrl_chan_name) - 1;
420
421         /*
422          * Build the ctrl_chan_name with shared token.
423          * When HA is enabled, the WC TCAM needs extra management by the core,
424          * so add the wc_tcam string to the control channel.
425          */
426         if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx))
427                 strncat(parms.ctrl_chan_name, "-tf_shared-wc_tcam",
428                         copy_nbytes);
429         else
430                 strncat(parms.ctrl_chan_name, "-tf_shared", copy_nbytes);
431
432         rc = bnxt_ulp_tf_shared_session_resources_get(bp->ulp_ctx, resources);
433         if (rc)
434                 return rc;
435
436         rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
437         if (rc) {
438                 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
439                 return -EINVAL;
440         }
441
442         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
443         if (rc) {
444                 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
445                 return rc;
446         }
447
448         switch (ulp_dev_id) {
449         case BNXT_ULP_DEVICE_ID_WH_PLUS:
450                 parms.device_type = TF_DEVICE_TYPE_WH;
451                 break;
452         case BNXT_ULP_DEVICE_ID_STINGRAY:
453                 parms.device_type = TF_DEVICE_TYPE_SR;
454                 break;
455         case BNXT_ULP_DEVICE_ID_THOR:
456                 parms.device_type = TF_DEVICE_TYPE_THOR;
457                 break;
458         default:
459                 BNXT_TF_DBG(ERR, "Unable to determine dev for opening session.\n");
460                 return rc;
461         }
462
463         parms.shadow_copy = true;
464         parms.bp = bp;
465         if (app_id == 0)
466                 parms.wc_num_slices = TF_WC_TCAM_2_SLICE_PER_ROW;
467         else
468                 parms.wc_num_slices = TF_WC_TCAM_1_SLICE_PER_ROW;
469
470         /*
471          * Open the session here, but the collect the resources during the
472          * mapper initialization.
473          */
474         rc = tf_open_session(&bp->tfp_shared, &parms);
475         if (rc)
476                 return rc;
477
478         if (parms.shared_session_creator)
479                 BNXT_TF_DBG(DEBUG, "Shared session creator.\n");
480         else
481                 BNXT_TF_DBG(DEBUG, "Shared session attached.\n");
482
483         /* Save the shared session in global data */
484         if (!session->g_shared_tfp.session)
485                 session->g_shared_tfp.session = bp->tfp_shared.session;
486
487         rc = bnxt_ulp_cntxt_shared_tfp_set(bp->ulp_ctx, &bp->tfp_shared);
488         if (rc)
489                 BNXT_TF_DBG(ERR, "Failed to add shared tfp to ulp (%d)\n", rc);
490
491         return rc;
492 }
493
494 static int32_t
495 ulp_ctx_shared_session_attach(struct bnxt *bp,
496                               struct bnxt_ulp_session_state *session)
497 {
498         int32_t rc = 0;
499
500         /* Simply return success if shared session not enabled */
501         if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
502                 bp->tfp_shared.session = session->g_shared_tfp.session;
503                 rc = ulp_ctx_shared_session_open(bp, session);
504         }
505
506         return rc;
507 }
508
509 static void
510 ulp_ctx_shared_session_detach(struct bnxt *bp)
511 {
512         if (bnxt_ulp_cntxt_shared_session_enabled(bp->ulp_ctx)) {
513                 if (bp->tfp_shared.session) {
514                         tf_close_session(&bp->tfp_shared);
515                         bp->tfp_shared.session = NULL;
516                 }
517         }
518 }
519
520 /*
521  * Initialize an ULP session.
522  * An ULP session will contain all the resources needed to support rte flow
523  * offloads. A session is initialized as part of rte_eth_device start.
524  * A single vswitch instance can have multiple uplinks which means
525  * rte_eth_device start will be called for each of these devices.
526  * ULP session manager will make sure that a single ULP session is only
527  * initialized once. Apart from this, it also initializes MARK database,
528  * EEM table & flow database. ULP session manager also manages a list of
529  * all opened ULP sessions.
530  */
531 static int32_t
532 ulp_ctx_session_open(struct bnxt *bp,
533                      struct bnxt_ulp_session_state *session)
534 {
535         struct rte_eth_dev              *ethdev = bp->eth_dev;
536         int32_t                         rc = 0;
537         struct tf_open_session_parms    params;
538         struct tf_session_resources     *resources;
539         uint32_t ulp_dev_id = BNXT_ULP_DEVICE_ID_LAST;
540         uint8_t app_id;
541
542         memset(&params, 0, sizeof(params));
543
544         rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
545                                           params.ctrl_chan_name);
546         if (rc) {
547                 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
548                             ethdev->data->port_id, rc);
549                 return rc;
550         }
551
552         params.shadow_copy = true;
553
554         rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
555         if (rc) {
556                 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
557                 return -EINVAL;
558         }
559
560         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
561         if (rc) {
562                 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
563                 return rc;
564         }
565
566         switch (ulp_dev_id) {
567         case BNXT_ULP_DEVICE_ID_WH_PLUS:
568                 params.device_type = TF_DEVICE_TYPE_WH;
569                 break;
570         case BNXT_ULP_DEVICE_ID_STINGRAY:
571                 params.device_type = TF_DEVICE_TYPE_SR;
572                 break;
573         case BNXT_ULP_DEVICE_ID_THOR:
574                 params.device_type = TF_DEVICE_TYPE_THOR;
575                 break;
576         default:
577                 BNXT_TF_DBG(ERR, "Unable to determine device for opening session.\n");
578                 return rc;
579         }
580
581         resources = &params.resources;
582         rc = bnxt_ulp_tf_resources_get(bp->ulp_ctx, resources);
583         if (rc)
584                 return rc;
585
586         params.bp = bp;
587         if (app_id == 0)
588                 params.wc_num_slices = TF_WC_TCAM_2_SLICE_PER_ROW;
589         else
590                 params.wc_num_slices = TF_WC_TCAM_1_SLICE_PER_ROW;
591
592         rc = tf_open_session(&bp->tfp, &params);
593         if (rc) {
594                 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
595                             params.ctrl_chan_name, rc);
596                 return -EINVAL;
597         }
598         if (!session->session_opened) {
599                 session->session_opened = 1;
600                 session->g_tfp = rte_zmalloc("bnxt_ulp_session_tfp",
601                                              sizeof(struct tf), 0);
602                 session->g_tfp->session = bp->tfp.session;
603         }
604         return rc;
605 }
606
607 /*
608  * Close the ULP session.
609  * It takes the ulp context pointer.
610  */
611 static void
612 ulp_ctx_session_close(struct bnxt *bp,
613                       struct bnxt_ulp_session_state *session)
614 {
615         /* close the session in the hardware */
616         if (session->session_opened)
617                 tf_close_session(&bp->tfp);
618         session->session_opened = 0;
619         rte_free(session->g_tfp);
620         session->g_tfp = NULL;
621 }
622
623 static void
624 bnxt_init_tbl_scope_parms(struct bnxt *bp,
625                           struct tf_alloc_tbl_scope_parms *params)
626 {
627         struct bnxt_ulp_device_params   *dparms;
628         uint32_t dev_id;
629         int rc;
630
631         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
632         if (rc)
633                 /* TBD: For now, just use default. */
634                 dparms = 0;
635         else
636                 dparms = bnxt_ulp_device_params_get(dev_id);
637
638         /*
639          * Set the flush timer for EEM entries. The value is in 100ms intervals,
640          * so 100 is 10s.
641          */
642         params->hw_flow_cache_flush_timer = 100;
643
644         if (!dparms) {
645                 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
646                 params->rx_max_action_entry_sz_in_bits =
647                         BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
648                 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
649                 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS;
650
651                 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
652                 params->tx_max_action_entry_sz_in_bits =
653                         BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
654                 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
655                 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS;
656         } else {
657                 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
658                 params->rx_max_action_entry_sz_in_bits =
659                         BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
660                 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
661                 params->rx_num_flows_in_k =
662                         dparms->ext_flow_db_num_entries / 1024;
663
664                 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
665                 params->tx_max_action_entry_sz_in_bits =
666                         BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
667                 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
668                 params->tx_num_flows_in_k =
669                         dparms->ext_flow_db_num_entries / 1024;
670         }
671         BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n",
672                     params->rx_num_flows_in_k);
673 }
674
675 /* Initialize Extended Exact Match host memory. */
676 static int32_t
677 ulp_eem_tbl_scope_init(struct bnxt *bp)
678 {
679         struct tf_alloc_tbl_scope_parms params = {0};
680         struct bnxt_ulp_device_params *dparms;
681         enum bnxt_ulp_flow_mem_type mtype;
682         uint32_t dev_id;
683         int rc;
684
685         /* Get the dev specific number of flows that needed to be supported. */
686         if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
687                 BNXT_TF_DBG(ERR, "Invalid device id\n");
688                 return -EINVAL;
689         }
690
691         dparms = bnxt_ulp_device_params_get(dev_id);
692         if (!dparms) {
693                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
694                 return -ENODEV;
695         }
696
697         if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype))
698                 return -EINVAL;
699         if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
700                 BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n");
701                 return 0;
702         }
703
704         bnxt_init_tbl_scope_parms(bp, &params);
705         rc = tf_alloc_tbl_scope(&bp->tfp, &params);
706         if (rc) {
707                 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n",
708                             rc);
709                 return rc;
710         }
711         rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id);
712         if (rc) {
713                 BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
714                 return rc;
715         }
716
717         return 0;
718 }
719
720 /* Free Extended Exact Match host memory */
721 static int32_t
722 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
723 {
724         struct tf_free_tbl_scope_parms  params = {0};
725         struct tf                       *tfp;
726         int32_t                         rc = 0;
727         struct bnxt_ulp_device_params *dparms;
728         enum bnxt_ulp_flow_mem_type mtype;
729         uint32_t dev_id;
730
731         if (!ulp_ctx || !ulp_ctx->cfg_data)
732                 return -EINVAL;
733
734         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx, BNXT_ULP_SHARED_SESSION_NO);
735         if (!tfp) {
736                 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n");
737                 return -EINVAL;
738         }
739
740         /* Get the dev specific number of flows that needed to be supported. */
741         if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
742                 BNXT_TF_DBG(ERR, "Invalid device id\n");
743                 return -EINVAL;
744         }
745
746         dparms = bnxt_ulp_device_params_get(dev_id);
747         if (!dparms) {
748                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
749                 return -ENODEV;
750         }
751
752         if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
753                 return -EINVAL;
754         if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
755                 BNXT_TF_DBG(INFO, "Table Scope free is not required\n");
756                 return 0;
757         }
758
759         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &params.tbl_scope_id);
760         if (rc) {
761                 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n");
762                 return -EINVAL;
763         }
764
765         rc = tf_free_tbl_scope(tfp, &params);
766         if (rc) {
767                 BNXT_TF_DBG(ERR, "Unable to free table scope\n");
768                 return -EINVAL;
769         }
770         return rc;
771 }
772
773 /* The function to free and deinit the ulp context data. */
774 static int32_t
775 ulp_ctx_deinit(struct bnxt *bp,
776                struct bnxt_ulp_session_state *session)
777 {
778         /* close the tf session */
779         ulp_ctx_session_close(bp, session);
780
781         /* The shared session must be closed last. */
782         ulp_ctx_shared_session_close(bp, session);
783
784         /* Free the contents */
785         if (session->cfg_data) {
786                 rte_free(session->cfg_data);
787                 bp->ulp_ctx->cfg_data = NULL;
788                 session->cfg_data = NULL;
789         }
790         return 0;
791 }
792
793 /* The function to allocate and initialize the ulp context data. */
794 static int32_t
795 ulp_ctx_init(struct bnxt *bp,
796              struct bnxt_ulp_session_state *session)
797 {
798         struct bnxt_ulp_data    *ulp_data;
799         int32_t                 rc = 0;
800         enum bnxt_ulp_device_id devid;
801
802         /* Initialize the context entries list */
803         bnxt_ulp_cntxt_list_init();
804
805         /* Add the context to the context entries list */
806         rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx);
807         if (rc) {
808                 BNXT_TF_DBG(ERR, "Failed to add the context list entry\n");
809                 return -ENOMEM;
810         }
811
812         /* Allocate memory to hold ulp context data. */
813         ulp_data = rte_zmalloc("bnxt_ulp_data",
814                                sizeof(struct bnxt_ulp_data), 0);
815         if (!ulp_data) {
816                 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n");
817                 return -ENOMEM;
818         }
819
820         /* Increment the ulp context data reference count usage. */
821         bp->ulp_ctx->cfg_data = ulp_data;
822         session->cfg_data = ulp_data;
823         ulp_data->ref_cnt++;
824         ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED;
825
826         rc = bnxt_ulp_devid_get(bp, &devid);
827         if (rc) {
828                 BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n");
829                 goto error_deinit;
830         }
831
832         rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid);
833         if (rc) {
834                 BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n");
835                 goto error_deinit;
836         }
837
838         rc = bnxt_ulp_cntxt_app_id_set(bp->ulp_ctx, bp->app_id);
839         if (rc) {
840                 BNXT_TF_DBG(ERR, "Unable to set app_id for ULP init.\n");
841                 goto error_deinit;
842         }
843         BNXT_TF_DBG(DEBUG, "Ulp initialized with app id %d\n", bp->app_id);
844
845         rc = bnxt_ulp_cntxt_app_caps_init(bp, bp->app_id, devid);
846         if (rc) {
847                 BNXT_TF_DBG(ERR, "Unable to set caps for app(%x)/dev(%x)\n",
848                             bp->app_id, devid);
849                 goto error_deinit;
850         }
851
852         /*
853          * Shared session must be created before first regular session but after
854          * the ulp_ctx is valid.
855          */
856         rc = ulp_ctx_shared_session_open(bp, session);
857         if (rc) {
858                 BNXT_TF_DBG(ERR, "Unable to open shared session (%d)\n", rc);
859                 goto error_deinit;
860         }
861
862         /* Open the ulp session. */
863         rc = ulp_ctx_session_open(bp, session);
864         if (rc)
865                 goto error_deinit;
866
867         bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp);
868         return rc;
869
870 error_deinit:
871         session->session_opened = 1;
872         (void)ulp_ctx_deinit(bp, session);
873         return rc;
874 }
875
876 /* The function to initialize ulp dparms with devargs */
877 static int32_t
878 ulp_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
879 {
880         struct bnxt_ulp_device_params *dparms;
881         uint32_t dev_id = BNXT_ULP_DEVICE_ID_LAST;
882
883         if (!bp->max_num_kflows) {
884                 /* Defaults to Internal */
885                 bnxt_ulp_cntxt_mem_type_set(ulp_ctx,
886                                             BNXT_ULP_FLOW_MEM_TYPE_INT);
887                 return 0;
888         }
889
890         /* The max_num_kflows were set, so move to external */
891         if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT))
892                 return -EINVAL;
893
894         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
895                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
896                 return -EINVAL;
897         }
898
899         dparms = bnxt_ulp_device_params_get(dev_id);
900         if (!dparms) {
901                 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
902                 return -EINVAL;
903         }
904
905         /* num_flows = max_num_kflows * 1024 */
906         dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024;
907         /* GFID =  2 * num_flows */
908         dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2;
909         BNXT_TF_DBG(DEBUG, "Set the number of flows = %" PRIu64 "\n",
910                     dparms->ext_flow_db_num_entries);
911
912         return 0;
913 }
914
915 /* The function to initialize bp flags with truflow features */
916 static int32_t
917 ulp_dparms_dev_port_intf_update(struct bnxt *bp,
918                                 struct bnxt_ulp_context *ulp_ctx)
919 {
920         enum bnxt_ulp_flow_mem_type mtype;
921
922         if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
923                 return -EINVAL;
924         /* Update the bp flag with gfid flag */
925         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
926                 bp->flags |= BNXT_FLAG_GFID_ENABLE;
927
928         return 0;
929 }
930
931 static int32_t
932 ulp_ctx_attach(struct bnxt *bp,
933                struct bnxt_ulp_session_state *session)
934 {
935         int32_t rc = 0;
936         uint32_t flags, dev_id = BNXT_ULP_DEVICE_ID_LAST;
937         uint8_t app_id;
938
939         /* Increment the ulp context data reference count usage. */
940         bp->ulp_ctx->cfg_data = session->cfg_data;
941         bp->ulp_ctx->cfg_data->ref_cnt++;
942
943         /* update the session details in bnxt tfp */
944         bp->tfp.session = session->g_tfp->session;
945
946         /* Add the context to the context entries list */
947         rc = bnxt_ulp_cntxt_list_add(bp->ulp_ctx);
948         if (rc) {
949                 BNXT_TF_DBG(ERR, "Failed to add the context list entry\n");
950                 return -EINVAL;
951         }
952
953         /*
954          * The supported flag will be set during the init. Use it now to
955          * know if we should go through the attach.
956          */
957         rc = bnxt_ulp_cntxt_app_id_get(bp->ulp_ctx, &app_id);
958         if (rc) {
959                 BNXT_TF_DBG(ERR, "Unable to get the app id from ulp.\n");
960                 return -EINVAL;
961         }
962
963         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
964         if (rc) {
965                 BNXT_TF_DBG(ERR, "Unable do get the dev_id.\n");
966                 return -EINVAL;
967         }
968
969         flags = bp->ulp_ctx->cfg_data->ulp_flags;
970         if (ULP_APP_DEV_UNSUPPORTED_ENABLED(flags)) {
971                 BNXT_TF_DBG(ERR, "APP ID %d, Device ID: 0x%x not supported.\n",
972                             app_id, dev_id);
973                 return -EINVAL;
974         }
975
976         /* Create a TF Client */
977         rc = ulp_ctx_session_open(bp, session);
978         if (rc) {
979                 PMD_DRV_LOG(ERR, "Failed to open ctxt session, rc:%d\n", rc);
980                 bp->tfp.session = NULL;
981                 return rc;
982         }
983
984         bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp);
985         return rc;
986 }
987
988 static void
989 ulp_ctx_detach(struct bnxt *bp)
990 {
991         if (bp->tfp.session) {
992                 tf_close_session(&bp->tfp);
993                 bp->tfp.session = NULL;
994         }
995 }
996
997 /*
998  * Initialize the state of an ULP session.
999  * If the state of an ULP session is not initialized, set it's state to
1000  * initialized. If the state is already initialized, do nothing.
1001  */
1002 static void
1003 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
1004 {
1005         pthread_mutex_lock(&session->bnxt_ulp_mutex);
1006
1007         if (!session->bnxt_ulp_init) {
1008                 session->bnxt_ulp_init = true;
1009                 *init = false;
1010         } else {
1011                 *init = true;
1012         }
1013
1014         pthread_mutex_unlock(&session->bnxt_ulp_mutex);
1015 }
1016
1017 /*
1018  * Check if an ULP session is already allocated for a specific PCI
1019  * domain & bus. If it is already allocated simply return the session
1020  * pointer, otherwise allocate a new session.
1021  */
1022 static struct bnxt_ulp_session_state *
1023 ulp_get_session(struct bnxt *bp, struct rte_pci_addr *pci_addr)
1024 {
1025         struct bnxt_ulp_session_state *session;
1026
1027         /* if multi root capability is enabled, then ignore the pci bus id */
1028         STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
1029                 if (session->pci_info.domain == pci_addr->domain &&
1030                     (BNXT_MULTIROOT_EN(bp) ||
1031                     session->pci_info.bus == pci_addr->bus)) {
1032                         return session;
1033                 }
1034         }
1035         return NULL;
1036 }
1037
1038 /*
1039  * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
1040  * If it's already initialized simply return the already existing session.
1041  */
1042 static struct bnxt_ulp_session_state *
1043 ulp_session_init(struct bnxt *bp,
1044                  bool *init)
1045 {
1046         struct rte_pci_device           *pci_dev;
1047         struct rte_pci_addr             *pci_addr;
1048         struct bnxt_ulp_session_state   *session;
1049         int rc = 0;
1050
1051         if (!bp)
1052                 return NULL;
1053
1054         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
1055         pci_addr = &pci_dev->addr;
1056
1057         pthread_mutex_lock(&bnxt_ulp_global_mutex);
1058
1059         session = ulp_get_session(bp, pci_addr);
1060         if (!session) {
1061                 /* Not Found the session  Allocate a new one */
1062                 session = rte_zmalloc("bnxt_ulp_session",
1063                                       sizeof(struct bnxt_ulp_session_state),
1064                                       0);
1065                 if (!session) {
1066                         BNXT_TF_DBG(ERR,
1067                                     "Allocation failed for bnxt_ulp_session\n");
1068                         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1069                         return NULL;
1070
1071                 } else {
1072                         /* Add it to the queue */
1073                         session->pci_info.domain = pci_addr->domain;
1074                         session->pci_info.bus = pci_addr->bus;
1075                         rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
1076                         if (rc) {
1077                                 BNXT_TF_DBG(ERR, "mutex create failed\n");
1078                                 pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1079                                 return NULL;
1080                         }
1081                         STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
1082                                            session, next);
1083                 }
1084         }
1085         ulp_context_initialized(session, init);
1086         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1087         return session;
1088 }
1089
1090 /*
1091  * When a device is closed, remove it's associated session from the global
1092  * session list.
1093  */
1094 static void
1095 ulp_session_deinit(struct bnxt_ulp_session_state *session)
1096 {
1097         if (!session)
1098                 return;
1099
1100         if (!session->cfg_data) {
1101                 pthread_mutex_lock(&bnxt_ulp_global_mutex);
1102                 STAILQ_REMOVE(&bnxt_ulp_session_list, session,
1103                               bnxt_ulp_session_state, next);
1104                 pthread_mutex_destroy(&session->bnxt_ulp_mutex);
1105                 rte_free(session);
1106                 pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1107         }
1108 }
1109
1110 /*
1111  * Internal api to enable NAT feature.
1112  * Set set_flag to 1 to set the value or zero to reset the value.
1113  * returns 0 on success.
1114  */
1115 static int32_t
1116 bnxt_ulp_global_cfg_update(struct bnxt *bp,
1117                            enum tf_dir dir,
1118                            enum tf_global_config_type type,
1119                            uint32_t offset,
1120                            uint32_t value,
1121                            uint32_t set_flag)
1122 {
1123         uint32_t global_cfg = 0;
1124         int rc;
1125         struct tf_global_cfg_parms parms = { 0 };
1126
1127         /* Initialize the params */
1128         parms.dir = dir,
1129         parms.type = type,
1130         parms.offset = offset,
1131         parms.config = (uint8_t *)&global_cfg,
1132         parms.config_sz_in_bytes = sizeof(global_cfg);
1133
1134         rc = tf_get_global_cfg(&bp->tfp, &parms);
1135         if (rc) {
1136                 BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n",
1137                             type, rc);
1138                 return rc;
1139         }
1140
1141         if (set_flag)
1142                 global_cfg |= value;
1143         else
1144                 global_cfg &= ~value;
1145
1146         /* SET the register RE_CFA_REG_ACT_TECT */
1147         rc = tf_set_global_cfg(&bp->tfp, &parms);
1148         if (rc) {
1149                 BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n",
1150                             type, rc);
1151                 return rc;
1152         }
1153         return rc;
1154 }
1155
1156 /* Internal function to delete all the flows belonging to the given port */
1157 static void
1158 bnxt_ulp_flush_port_flows(struct bnxt *bp)
1159 {
1160         uint16_t func_id;
1161
1162         /* it is assumed that port is either TVF or PF */
1163         if (ulp_port_db_port_func_id_get(bp->ulp_ctx,
1164                                          bp->eth_dev->data->port_id,
1165                                          &func_id)) {
1166                 BNXT_TF_DBG(ERR, "Invalid argument\n");
1167                 return;
1168         }
1169         (void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id);
1170 }
1171
1172 /* Internal function to delete the VFR default flows */
1173 static void
1174 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global)
1175 {
1176         struct bnxt_ulp_vfr_rule_info *info;
1177         uint16_t port_id;
1178         struct rte_eth_dev *vfr_eth_dev;
1179         struct bnxt_representor *vfr_bp;
1180
1181         if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev))
1182                 return;
1183
1184         if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
1185                 return;
1186
1187         /* Delete default rules for all ports */
1188         for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
1189                 info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id];
1190                 if (!info->valid)
1191                         continue;
1192
1193                 if (!global && info->parent_port_id !=
1194                     bp->eth_dev->data->port_id)
1195                         continue;
1196
1197                 /* Destroy the flows */
1198                 ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id);
1199                 /* Clean up the tx action pointer */
1200                 vfr_eth_dev = &rte_eth_devices[port_id];
1201                 if (vfr_eth_dev) {
1202                         vfr_bp = vfr_eth_dev->data->dev_private;
1203                         vfr_bp->vfr_tx_cfa_action = 0;
1204                 }
1205                 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info));
1206         }
1207 }
1208
1209 /*
1210  * When a port is deinit'ed by dpdk. This function is called
1211  * and this function clears the ULP context and rest of the
1212  * infrastructure associated with it.
1213  */
1214 static void
1215 bnxt_ulp_deinit(struct bnxt *bp,
1216                 struct bnxt_ulp_session_state *session)
1217 {
1218         bool ha_enabled;
1219
1220         if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
1221                 return;
1222
1223         ha_enabled = bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx);
1224         if (ha_enabled && session->session_opened) {
1225                 int32_t rc = ulp_ha_mgr_close(bp->ulp_ctx);
1226                 if (rc)
1227                         BNXT_TF_DBG(ERR, "Failed to close HA (%d)\n", rc);
1228         }
1229
1230         /* clean up default flows */
1231         bnxt_ulp_destroy_df_rules(bp, true);
1232
1233         /* clean up default VFR flows */
1234         bnxt_ulp_destroy_vfr_default_rules(bp, true);
1235
1236         /* clean up regular flows */
1237         ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
1238
1239         /* cleanup the eem table scope */
1240         ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
1241
1242         /* cleanup the flow database */
1243         ulp_flow_db_deinit(bp->ulp_ctx);
1244
1245         /* Delete the Mark database */
1246         ulp_mark_db_deinit(bp->ulp_ctx);
1247
1248         /* cleanup the ulp mapper */
1249         ulp_mapper_deinit(bp->ulp_ctx);
1250
1251         /* Delete the Flow Counter Manager */
1252         ulp_fc_mgr_deinit(bp->ulp_ctx);
1253
1254         /* Delete the Port database */
1255         ulp_port_db_deinit(bp->ulp_ctx);
1256
1257         /* Disable NAT feature */
1258         (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
1259                                          TF_TUNNEL_ENCAP_NAT,
1260                                          BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
1261
1262         (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
1263                                          TF_TUNNEL_ENCAP_NAT,
1264                                          BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
1265
1266         /* free the flow db lock */
1267         pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
1268
1269         if (ha_enabled)
1270                 ulp_ha_mgr_deinit(bp->ulp_ctx);
1271
1272         /* Delete the ulp context and tf session and free the ulp context */
1273         ulp_ctx_deinit(bp, session);
1274         BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n");
1275 }
1276
1277 /*
1278  * When a port is initialized by dpdk. This functions is called
1279  * and this function initializes the ULP context and rest of the
1280  * infrastructure associated with it.
1281  */
1282 static int32_t
1283 bnxt_ulp_init(struct bnxt *bp,
1284               struct bnxt_ulp_session_state *session)
1285 {
1286         int rc;
1287
1288         /* Allocate and Initialize the ulp context. */
1289         rc = ulp_ctx_init(bp, session);
1290         if (rc) {
1291                 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
1292                 goto jump_to_error;
1293         }
1294
1295         rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
1296         if (rc) {
1297                 BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
1298                 goto jump_to_error;
1299         }
1300
1301         /* Initialize ulp dparms with values devargs passed */
1302         rc = ulp_dparms_init(bp, bp->ulp_ctx);
1303         if (rc) {
1304                 BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n");
1305                 goto jump_to_error;
1306         }
1307
1308         /* create the port database */
1309         rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt);
1310         if (rc) {
1311                 BNXT_TF_DBG(ERR, "Failed to create the port database\n");
1312                 goto jump_to_error;
1313         }
1314
1315         /* Create the Mark database. */
1316         rc = ulp_mark_db_init(bp->ulp_ctx);
1317         if (rc) {
1318                 BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
1319                 goto jump_to_error;
1320         }
1321
1322         /* Create the flow database. */
1323         rc = ulp_flow_db_init(bp->ulp_ctx);
1324         if (rc) {
1325                 BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
1326                 goto jump_to_error;
1327         }
1328
1329         /* Create the eem table scope. */
1330         rc = ulp_eem_tbl_scope_init(bp);
1331         if (rc) {
1332                 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
1333                 goto jump_to_error;
1334         }
1335
1336         rc = ulp_mapper_init(bp->ulp_ctx);
1337         if (rc) {
1338                 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
1339                 goto jump_to_error;
1340         }
1341
1342         rc = ulp_fc_mgr_init(bp->ulp_ctx);
1343         if (rc) {
1344                 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n");
1345                 goto jump_to_error;
1346         }
1347
1348         /*
1349          * Enable NAT feature. Set the global configuration register
1350          * Tunnel encap to enable NAT with the reuse of existing inner
1351          * L2 header smac and dmac
1352          */
1353         rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
1354                                         TF_TUNNEL_ENCAP_NAT,
1355                                         BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
1356         if (rc) {
1357                 BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n");
1358                 goto jump_to_error;
1359         }
1360
1361         rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
1362                                         TF_TUNNEL_ENCAP_NAT,
1363                                         BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
1364         if (rc) {
1365                 BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n");
1366                 goto jump_to_error;
1367         }
1368
1369         if (bnxt_ulp_cntxt_ha_enabled(bp->ulp_ctx)) {
1370                 rc = ulp_ha_mgr_init(bp->ulp_ctx);
1371                 if (rc) {
1372                         BNXT_TF_DBG(ERR, "Failed to initialize HA %d\n", rc);
1373                         goto jump_to_error;
1374                 }
1375                 rc = ulp_ha_mgr_open(bp->ulp_ctx);
1376                 if (rc) {
1377                         BNXT_TF_DBG(ERR, "Failed to Process HA Open %d\n", rc);
1378                         goto jump_to_error;
1379                 }
1380         }
1381         BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n");
1382         return rc;
1383
1384 jump_to_error:
1385         bnxt_ulp_deinit(bp, session);
1386         return rc;
1387 }
1388
1389 /*
1390  * When a port is initialized by dpdk. This functions sets up
1391  * the port specific details.
1392  */
1393 int32_t
1394 bnxt_ulp_port_init(struct bnxt *bp)
1395 {
1396         struct bnxt_ulp_session_state *session;
1397         bool initialized;
1398         enum bnxt_ulp_device_id devid = BNXT_ULP_DEVICE_ID_LAST;
1399         uint32_t ulp_flags;
1400         int32_t rc = 0;
1401
1402         if (!BNXT_TRUFLOW_EN(bp)) {
1403                 BNXT_TF_DBG(DEBUG,
1404                             "Skip ulp init for port: %d, TF is not enabled\n",
1405                             bp->eth_dev->data->port_id);
1406                 return rc;
1407         }
1408
1409         if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1410                 BNXT_TF_DBG(DEBUG,
1411                             "Skip ulp init for port: %d, not a TVF or PF\n",
1412                             bp->eth_dev->data->port_id);
1413                 return rc;
1414         }
1415
1416         if (bp->ulp_ctx) {
1417                 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n");
1418                 return rc;
1419         }
1420
1421         bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
1422                                   sizeof(struct bnxt_ulp_context), 0);
1423         if (!bp->ulp_ctx) {
1424                 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
1425                 return -ENOMEM;
1426         }
1427
1428         /*
1429          * Multiple uplink ports can be associated with a single vswitch.
1430          * Make sure only the port that is started first will initialize
1431          * the TF session.
1432          */
1433         session = ulp_session_init(bp, &initialized);
1434         if (!session) {
1435                 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
1436                 rc = -EIO;
1437                 goto jump_to_error;
1438         }
1439
1440         if (initialized) {
1441                 /*
1442                  * If ULP is already initialized for a specific domain then
1443                  * simply assign the ulp context to this rte_eth_dev.
1444                  */
1445                 rc = ulp_ctx_attach(bp, session);
1446                 if (rc) {
1447                         BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n");
1448                         goto jump_to_error;
1449                 }
1450
1451                 /*
1452                  * Attach to the shared session, must be called after the
1453                  * ulp_ctx_attach in order to ensure that ulp data is available
1454                  * for attaching.
1455                  */
1456                 rc = ulp_ctx_shared_session_attach(bp, session);
1457                 if (rc) {
1458                         BNXT_TF_DBG(ERR,
1459                                     "Failed attach to shared session (%d)", rc);
1460                         goto jump_to_error;
1461                 }
1462         } else {
1463                 rc = bnxt_ulp_init(bp, session);
1464                 if (rc) {
1465                         BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n");
1466                         goto jump_to_error;
1467                 }
1468         }
1469
1470         /* Update bnxt driver flags */
1471         rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
1472         if (rc) {
1473                 BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
1474                 goto jump_to_error;
1475         }
1476
1477         /* update the port database for the given interface */
1478         rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
1479         if (rc) {
1480                 BNXT_TF_DBG(ERR, "Failed to update port database\n");
1481                 goto jump_to_error;
1482         }
1483         /* create the default rules */
1484         rc = bnxt_ulp_create_df_rules(bp);
1485         if (rc) {
1486                 BNXT_TF_DBG(ERR, "Failed to create default flow\n");
1487                 goto jump_to_error;
1488         }
1489
1490         rc = bnxt_ulp_devid_get(bp, &devid);
1491         if (rc) {
1492                 BNXT_TF_DBG(ERR, "Unable to determine device for ULP port init.\n");
1493                 goto jump_to_error;
1494         }
1495
1496         /* set the unicast mode */
1497         if (bnxt_ulp_cntxt_ptr2_ulp_flags_get(bp->ulp_ctx, &ulp_flags)) {
1498                 BNXT_TF_DBG(ERR, "Error in getting ULP context flags\n");
1499                 goto jump_to_error;
1500         }
1501         if (ulp_flags & BNXT_ULP_APP_UNICAST_ONLY) {
1502                 if (bnxt_pmd_set_unicast_rxmask(bp->eth_dev)) {
1503                         BNXT_TF_DBG(ERR, "Error in setting unicast rxmode\n");
1504                         goto jump_to_error;
1505                 }
1506         }
1507
1508         return rc;
1509
1510 jump_to_error:
1511         bnxt_ulp_port_deinit(bp);
1512         return rc;
1513 }
1514
1515 /*
1516  * When a port is de-initialized by dpdk. This functions clears up
1517  * the port specific details.
1518  */
1519 void
1520 bnxt_ulp_port_deinit(struct bnxt *bp)
1521 {
1522         struct bnxt_ulp_session_state *session;
1523         struct rte_pci_device *pci_dev;
1524         struct rte_pci_addr *pci_addr;
1525
1526         if (!BNXT_TRUFLOW_EN(bp)) {
1527                 BNXT_TF_DBG(DEBUG,
1528                             "Skip ULP deinit for port:%d, TF is not enabled\n",
1529                             bp->eth_dev->data->port_id);
1530                 return;
1531         }
1532
1533         if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1534                 BNXT_TF_DBG(DEBUG,
1535                             "Skip ULP deinit port:%d, not a TVF or PF\n",
1536                             bp->eth_dev->data->port_id);
1537                 return;
1538         }
1539
1540         if (!bp->ulp_ctx) {
1541                 BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n");
1542                 return;
1543         }
1544
1545         BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n",
1546                     bp->eth_dev->data->port_id);
1547
1548         /* Free the ulp context in the context entry list */
1549         bnxt_ulp_cntxt_list_del(bp->ulp_ctx);
1550
1551         /* Get the session details  */
1552         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
1553         pci_addr = &pci_dev->addr;
1554         pthread_mutex_lock(&bnxt_ulp_global_mutex);
1555         session = ulp_get_session(bp, pci_addr);
1556         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1557
1558         /* session not found then just exit */
1559         if (!session) {
1560                 /* Free the ulp context */
1561                 rte_free(bp->ulp_ctx);
1562                 bp->ulp_ctx = NULL;
1563                 return;
1564         }
1565
1566         /* Check the reference count to deinit or deattach*/
1567         if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) {
1568                 bp->ulp_ctx->cfg_data->ref_cnt--;
1569                 if (bp->ulp_ctx->cfg_data->ref_cnt) {
1570                         /* free the port details */
1571                         /* Free the default flow rule associated to this port */
1572                         bnxt_ulp_destroy_df_rules(bp, false);
1573                         bnxt_ulp_destroy_vfr_default_rules(bp, false);
1574
1575                         /* free flows associated with this port */
1576                         bnxt_ulp_flush_port_flows(bp);
1577
1578                         /* close the session associated with this port */
1579                         ulp_ctx_detach(bp);
1580
1581                         /* always detach/close shared after the session. */
1582                         ulp_ctx_shared_session_detach(bp);
1583                 } else {
1584                         /* Perform ulp ctx deinit */
1585                         bnxt_ulp_deinit(bp, session);
1586                 }
1587         }
1588
1589         /* clean up the session */
1590         ulp_session_deinit(session);
1591
1592         /* Free the ulp context */
1593         rte_free(bp->ulp_ctx);
1594         bp->ulp_ctx = NULL;
1595 }
1596
1597 /* Below are the access functions to access internal data of ulp context. */
1598 /* Function to set the Mark DB into the context */
1599 int32_t
1600 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
1601                                 struct bnxt_ulp_mark_tbl *mark_tbl)
1602 {
1603         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1604                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1605                 return -EINVAL;
1606         }
1607
1608         ulp_ctx->cfg_data->mark_tbl = mark_tbl;
1609
1610         return 0;
1611 }
1612
1613 /* Function to retrieve the Mark DB from the context. */
1614 struct bnxt_ulp_mark_tbl *
1615 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
1616 {
1617         if (!ulp_ctx || !ulp_ctx->cfg_data)
1618                 return NULL;
1619
1620         return ulp_ctx->cfg_data->mark_tbl;
1621 }
1622
1623 bool
1624 bnxt_ulp_cntxt_shared_session_enabled(struct bnxt_ulp_context *ulp_ctx)
1625 {
1626         return ULP_SHARED_SESSION_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags);
1627 }
1628
1629 int32_t
1630 bnxt_ulp_cntxt_app_id_set(struct bnxt_ulp_context *ulp_ctx, uint8_t app_id)
1631 {
1632         if (!ulp_ctx)
1633                 return -EINVAL;
1634         ulp_ctx->cfg_data->app_id = app_id;
1635         return 0;
1636 }
1637
1638 int32_t
1639 bnxt_ulp_cntxt_app_id_get(struct bnxt_ulp_context *ulp_ctx, uint8_t *app_id)
1640 {
1641         /* Default APP id is zero */
1642         if (!ulp_ctx || !app_id)
1643                 return -EINVAL;
1644         *app_id = ulp_ctx->cfg_data->app_id;
1645         return 0;
1646 }
1647
1648 /* Function to set the device id of the hardware. */
1649 int32_t
1650 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
1651                           uint32_t dev_id)
1652 {
1653         if (ulp_ctx && ulp_ctx->cfg_data) {
1654                 ulp_ctx->cfg_data->dev_id = dev_id;
1655                 return 0;
1656         }
1657
1658         return -EINVAL;
1659 }
1660
1661 /* Function to get the device id of the hardware. */
1662 int32_t
1663 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
1664                           uint32_t *dev_id)
1665 {
1666         if (ulp_ctx && ulp_ctx->cfg_data) {
1667                 *dev_id = ulp_ctx->cfg_data->dev_id;
1668                 return 0;
1669         }
1670         *dev_id = BNXT_ULP_DEVICE_ID_LAST;
1671         BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n");
1672         return -EINVAL;
1673 }
1674
1675 int32_t
1676 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx,
1677                             enum bnxt_ulp_flow_mem_type mem_type)
1678 {
1679         if (ulp_ctx && ulp_ctx->cfg_data) {
1680                 ulp_ctx->cfg_data->mem_type = mem_type;
1681                 return 0;
1682         }
1683         BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n");
1684         return -EINVAL;
1685 }
1686
1687 int32_t
1688 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx,
1689                             enum bnxt_ulp_flow_mem_type *mem_type)
1690 {
1691         if (ulp_ctx && ulp_ctx->cfg_data) {
1692                 *mem_type = ulp_ctx->cfg_data->mem_type;
1693                 return 0;
1694         }
1695         *mem_type = BNXT_ULP_FLOW_MEM_TYPE_LAST;
1696         BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n");
1697         return -EINVAL;
1698 }
1699
1700 /* Function to get the table scope id of the EEM table. */
1701 int32_t
1702 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
1703                                 uint32_t *tbl_scope_id)
1704 {
1705         if (ulp_ctx && ulp_ctx->cfg_data) {
1706                 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
1707                 return 0;
1708         }
1709
1710         return -EINVAL;
1711 }
1712
1713 /* Function to set the table scope id of the EEM table. */
1714 int32_t
1715 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
1716                                 uint32_t tbl_scope_id)
1717 {
1718         if (ulp_ctx && ulp_ctx->cfg_data) {
1719                 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
1720                 return 0;
1721         }
1722
1723         return -EINVAL;
1724 }
1725
1726 /* Function to set the shared tfp session details from the ulp context. */
1727 int32_t
1728 bnxt_ulp_cntxt_shared_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
1729 {
1730         if (!ulp) {
1731                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1732                 return -EINVAL;
1733         }
1734
1735         if (tfp == NULL) {
1736                 if (ulp->cfg_data->num_shared_clients > 0)
1737                         ulp->cfg_data->num_shared_clients--;
1738         } else {
1739                 ulp->cfg_data->num_shared_clients++;
1740         }
1741
1742         ulp->g_shared_tfp = tfp;
1743         return 0;
1744 }
1745
1746 /* Function to get the shared tfp session details from the ulp context. */
1747 struct tf *
1748 bnxt_ulp_cntxt_shared_tfp_get(struct bnxt_ulp_context *ulp)
1749 {
1750         if (!ulp) {
1751                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1752                 return NULL;
1753         }
1754         return ulp->g_shared_tfp;
1755 }
1756
1757 /* Function to get the number of shared clients attached */
1758 uint8_t
1759 bnxt_ulp_cntxt_num_shared_clients_get(struct bnxt_ulp_context *ulp)
1760 {
1761         if (ulp == NULL || ulp->cfg_data == NULL) {
1762                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1763                 return 0;
1764         }
1765         return ulp->cfg_data->num_shared_clients;
1766 }
1767
1768 /* Function to set the tfp session details from the ulp context. */
1769 int32_t
1770 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
1771 {
1772         if (!ulp) {
1773                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1774                 return -EINVAL;
1775         }
1776
1777         ulp->g_tfp = tfp;
1778         return 0;
1779 }
1780
1781 /* Function to get the tfp session details from the ulp context. */
1782 struct tf *
1783 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp,
1784                        enum bnxt_ulp_shared_session shared)
1785 {
1786         if (!ulp) {
1787                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1788                 return NULL;
1789         }
1790         if (shared)
1791                 return ulp->g_shared_tfp;
1792         else
1793                 return ulp->g_tfp;
1794 }
1795
1796 /*
1797  * Get the device table entry based on the device id.
1798  *
1799  * dev_id [in] The device id of the hardware
1800  *
1801  * Returns the pointer to the device parameters.
1802  */
1803 struct bnxt_ulp_device_params *
1804 bnxt_ulp_device_params_get(uint32_t dev_id)
1805 {
1806         if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
1807                 return &ulp_device_params[dev_id];
1808         return NULL;
1809 }
1810
1811 /* Function to set the flow database to the ulp context. */
1812 int32_t
1813 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx,
1814                                 struct bnxt_ulp_flow_db *flow_db)
1815 {
1816         if (!ulp_ctx || !ulp_ctx->cfg_data)
1817                 return -EINVAL;
1818
1819         ulp_ctx->cfg_data->flow_db = flow_db;
1820         return 0;
1821 }
1822
1823 /* Function to get the flow database from the ulp context. */
1824 struct bnxt_ulp_flow_db *
1825 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx)
1826 {
1827         if (!ulp_ctx || !ulp_ctx->cfg_data)
1828                 return NULL;
1829
1830         return ulp_ctx->cfg_data->flow_db;
1831 }
1832
1833 /* Function to get the tunnel cache table info from the ulp context. */
1834 struct bnxt_tun_cache_entry *
1835 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx)
1836 {
1837         if (!ulp_ctx || !ulp_ctx->cfg_data)
1838                 return NULL;
1839
1840         return ulp_ctx->cfg_data->tun_tbl;
1841 }
1842
1843 /* Function to get the ulp context from eth device. */
1844 struct bnxt_ulp_context *
1845 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev      *dev)
1846 {
1847         struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
1848
1849         if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) {
1850                 struct bnxt_representor *vfr = dev->data->dev_private;
1851
1852                 bp = vfr->parent_dev->data->dev_private;
1853         }
1854
1855         if (!bp) {
1856                 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
1857                 return NULL;
1858         }
1859         return bp->ulp_ctx;
1860 }
1861
1862 int32_t
1863 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
1864                                     void *mapper_data)
1865 {
1866         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1867                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1868                 return -EINVAL;
1869         }
1870
1871         ulp_ctx->cfg_data->mapper_data = mapper_data;
1872         return 0;
1873 }
1874
1875 void *
1876 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
1877 {
1878         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1879                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1880                 return NULL;
1881         }
1882
1883         return ulp_ctx->cfg_data->mapper_data;
1884 }
1885
1886 /* Function to set the port database to the ulp context. */
1887 int32_t
1888 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx,
1889                                 struct bnxt_ulp_port_db *port_db)
1890 {
1891         if (!ulp_ctx || !ulp_ctx->cfg_data)
1892                 return -EINVAL;
1893
1894         ulp_ctx->cfg_data->port_db = port_db;
1895         return 0;
1896 }
1897
1898 /* Function to get the port database from the ulp context. */
1899 struct bnxt_ulp_port_db *
1900 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx)
1901 {
1902         if (!ulp_ctx || !ulp_ctx->cfg_data)
1903                 return NULL;
1904
1905         return ulp_ctx->cfg_data->port_db;
1906 }
1907
1908 /* Function to set the flow counter info into the context */
1909 int32_t
1910 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx,
1911                                 struct bnxt_ulp_fc_info *ulp_fc_info)
1912 {
1913         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1914                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1915                 return -EINVAL;
1916         }
1917
1918         ulp_ctx->cfg_data->fc_info = ulp_fc_info;
1919
1920         return 0;
1921 }
1922
1923 /* Function to retrieve the flow counter info from the context. */
1924 struct bnxt_ulp_fc_info *
1925 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx)
1926 {
1927         if (!ulp_ctx || !ulp_ctx->cfg_data)
1928                 return NULL;
1929
1930         return ulp_ctx->cfg_data->fc_info;
1931 }
1932
1933 /* Function to get the ulp flags from the ulp context. */
1934 int32_t
1935 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx,
1936                                   uint32_t *flags)
1937 {
1938         if (!ulp_ctx || !ulp_ctx->cfg_data)
1939                 return -1;
1940
1941         *flags =  ulp_ctx->cfg_data->ulp_flags;
1942         return 0;
1943 }
1944
1945 /* Function to get the ulp vfr info from the ulp context. */
1946 struct bnxt_ulp_vfr_rule_info*
1947 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx,
1948                                      uint32_t port_id)
1949 {
1950         if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS)
1951                 return NULL;
1952
1953         return &ulp_ctx->cfg_data->vfr_rule_info[port_id];
1954 }
1955
1956 /* Function to acquire the flow database lock from the ulp context. */
1957 int32_t
1958 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context *ulp_ctx)
1959 {
1960         if (!ulp_ctx || !ulp_ctx->cfg_data)
1961                 return -1;
1962
1963         if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
1964                 BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
1965                 return -1;
1966         }
1967         return 0;
1968 }
1969
1970 /* Function to release the flow database lock from the ulp context. */
1971 void
1972 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context *ulp_ctx)
1973 {
1974         if (!ulp_ctx || !ulp_ctx->cfg_data)
1975                 return;
1976
1977         pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
1978 }
1979
1980 /* Function to set the ha info into the context */
1981 int32_t
1982 bnxt_ulp_cntxt_ptr2_ha_info_set(struct bnxt_ulp_context *ulp_ctx,
1983                                 struct bnxt_ulp_ha_mgr_info *ulp_ha_info)
1984 {
1985         if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL) {
1986                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1987                 return -EINVAL;
1988         }
1989         ulp_ctx->cfg_data->ha_info = ulp_ha_info;
1990         return 0;
1991 }
1992
1993 /* Function to retrieve the ha info from the context. */
1994 struct bnxt_ulp_ha_mgr_info *
1995 bnxt_ulp_cntxt_ptr2_ha_info_get(struct bnxt_ulp_context *ulp_ctx)
1996 {
1997         if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL)
1998                 return NULL;
1999         return ulp_ctx->cfg_data->ha_info;
2000 }
2001
2002 bool
2003 bnxt_ulp_cntxt_ha_enabled(struct bnxt_ulp_context *ulp_ctx)
2004 {
2005         if (ulp_ctx == NULL || ulp_ctx->cfg_data == NULL)
2006                 return false;
2007         return !!ULP_HIGH_AVAIL_IS_ENABLED(ulp_ctx->cfg_data->ulp_flags);
2008 }
2009
2010 static int32_t
2011 bnxt_ulp_cntxt_list_init(void)
2012 {
2013         /* Create the cntxt spin lock */
2014         rte_spinlock_init(&bnxt_ulp_ctxt_lock);
2015
2016         return 0;
2017 }
2018
2019 static int32_t
2020 bnxt_ulp_cntxt_list_add(struct bnxt_ulp_context *ulp_ctx)
2021 {
2022         struct ulp_context_list_entry   *entry;
2023
2024         entry = rte_zmalloc(NULL, sizeof(struct ulp_context_list_entry), 0);
2025         if (entry == NULL) {
2026                 BNXT_TF_DBG(ERR, "unable to allocate memory\n");
2027                 return -ENOMEM;
2028         }
2029
2030         rte_spinlock_lock(&bnxt_ulp_ctxt_lock);
2031         entry->ulp_ctx = ulp_ctx;
2032         TAILQ_INSERT_TAIL(&ulp_cntx_list, entry, next);
2033         rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2034         return 0;
2035 }
2036
2037 static void
2038 bnxt_ulp_cntxt_list_del(struct bnxt_ulp_context *ulp_ctx)
2039 {
2040         struct ulp_context_list_entry   *entry, *temp;
2041
2042         rte_spinlock_lock(&bnxt_ulp_ctxt_lock);
2043         RTE_TAILQ_FOREACH_SAFE(entry, &ulp_cntx_list, next, temp) {
2044                 if (entry->ulp_ctx == ulp_ctx) {
2045                         TAILQ_REMOVE(&ulp_cntx_list, entry, next);
2046                         rte_free(entry);
2047                         break;
2048                 }
2049         }
2050         rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2051 }
2052
2053 struct bnxt_ulp_context *
2054 bnxt_ulp_cntxt_entry_acquire(void)
2055 {
2056         struct ulp_context_list_entry   *entry;
2057
2058         /* take a lock and get the first ulp context available */
2059         if (rte_spinlock_trylock(&bnxt_ulp_ctxt_lock)) {
2060                 TAILQ_FOREACH(entry, &ulp_cntx_list, next)
2061                         if (entry->ulp_ctx)
2062                                 return entry->ulp_ctx;
2063         }
2064         return NULL;
2065 }
2066
2067 void
2068 bnxt_ulp_cntxt_entry_release(void)
2069 {
2070         rte_spinlock_unlock(&bnxt_ulp_ctxt_lock);
2071 }
2072
2073 /* Function to get the app tunnel details from the ulp context. */
2074 struct bnxt_flow_app_tun_ent *
2075 bnxt_ulp_cntxt_ptr2_app_tun_list_get(struct bnxt_ulp_context *ulp)
2076 {
2077         if (!ulp || !ulp->cfg_data)
2078                 return NULL;
2079
2080         return ulp->cfg_data->app_tun;
2081 }