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