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