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