4c1a1c44c8e6b912b6c399f0d389737e9952791d
[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_ulp.h"
13 #include "bnxt_tf_common.h"
14 #include "bnxt.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_flow_db.h"
22 #include "ulp_mapper.h"
23 #include "ulp_port_db.h"
24
25 /* Linked list of all TF sessions. */
26 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
27                         STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
28
29 /* Mutex to synchronize bnxt_ulp_session_list operations. */
30 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
31
32 /*
33  * Allow the deletion of context only for the bnxt device that
34  * created the session
35  * TBD - The implementation of the function should change to
36  * using the reference count once tf_session_attach functionality
37  * is fixed.
38  */
39 bool
40 ulp_ctx_deinit_allowed(void *ptr)
41 {
42         struct bnxt *bp = (struct bnxt *)ptr;
43
44         if (!bp)
45                 return 0;
46
47         if (&bp->tfp == bp->ulp_ctx->g_tfp)
48                 return 1;
49
50         return 0;
51 }
52
53 /*
54  * Initialize an ULP session.
55  * An ULP session will contain all the resources needed to support rte flow
56  * offloads. A session is initialized as part of rte_eth_device start.
57  * A single vswitch instance can have multiple uplinks which means
58  * rte_eth_device start will be called for each of these devices.
59  * ULP session manager will make sure that a single ULP session is only
60  * initialized once. Apart from this, it also initializes MARK database,
61  * EEM table & flow database. ULP session manager also manages a list of
62  * all opened ULP sessions.
63  */
64 static int32_t
65 ulp_ctx_session_open(struct bnxt *bp,
66                      struct bnxt_ulp_session_state *session)
67 {
68         struct rte_eth_dev              *ethdev = bp->eth_dev;
69         int32_t                         rc = 0;
70         struct tf_open_session_parms    params;
71         struct tf_session_resources     *resources;
72
73         memset(&params, 0, sizeof(params));
74
75         rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
76                                           params.ctrl_chan_name);
77         if (rc) {
78                 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
79                             ethdev->data->port_id, rc);
80                 return rc;
81         }
82
83         params.shadow_copy = false;
84         params.device_type = TF_DEVICE_TYPE_WH;
85         resources = &params.resources;
86         /** RX **/
87         /* Identifiers */
88         resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT] = 16;
89         resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 8;
90         resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 8;
91         resources->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 8;
92
93         /* Table Types */
94         resources->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 720;
95         resources->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 720;
96
97         /* TCAMs */
98         resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM] = 16;
99         resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 8;
100         resources->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 416;
101
102         /* EM */
103         resources->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 2048;
104
105         /** TX **/
106         /* Identifiers */
107         resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT] = 8;
108         resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 8;
109         resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 8;
110         resources->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 8;
111
112         /* Table Types */
113         resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 16;
114         resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16;
115
116         /* ENCAP */
117         resources->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 16;
118
119         /* TCAMs */
120         resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM] = 8;
121         resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 8;
122         resources->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 8;
123
124         /* EM */
125         resources->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 8;
126
127         /* EEM */
128         resources->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
129         resources->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
130
131         rc = tf_open_session(&bp->tfp, &params);
132         if (rc) {
133                 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
134                             params.ctrl_chan_name, rc);
135                 return -EINVAL;
136         }
137         session->session_opened = 1;
138         session->g_tfp = &bp->tfp;
139         return rc;
140 }
141
142 /*
143  * Close the ULP session.
144  * It takes the ulp context pointer.
145  */
146 static void
147 ulp_ctx_session_close(struct bnxt *bp,
148                       struct bnxt_ulp_session_state *session)
149 {
150         /* close the session in the hardware */
151         if (session->session_opened)
152                 tf_close_session(&bp->tfp);
153         session->session_opened = 0;
154         session->g_tfp = NULL;
155         bp->ulp_ctx->g_tfp = NULL;
156 }
157
158 static void
159 bnxt_init_tbl_scope_parms(struct bnxt *bp,
160                           struct tf_alloc_tbl_scope_parms *params)
161 {
162         struct bnxt_ulp_device_params   *dparms;
163         uint32_t dev_id;
164         int rc;
165
166         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
167         if (rc)
168                 /* TBD: For now, just use default. */
169                 dparms = 0;
170         else
171                 dparms = bnxt_ulp_device_params_get(dev_id);
172
173         /*
174          * Set the flush timer for EEM entries. The value is in 100ms intervals,
175          * so 100 is 10s.
176          */
177         params->hw_flow_cache_flush_timer = 100;
178
179         if (!dparms) {
180                 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
181                 params->rx_max_action_entry_sz_in_bits =
182                         BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
183                 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
184                 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS;
185                 params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
186
187                 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
188                 params->tx_max_action_entry_sz_in_bits =
189                         BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
190                 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
191                 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS;
192                 params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
193         } else {
194                 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
195                 params->rx_max_action_entry_sz_in_bits =
196                         BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
197                 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
198                 params->rx_num_flows_in_k = dparms->flow_db_num_entries / 1024;
199                 params->rx_tbl_if_id = BNXT_ULP_RX_TBL_IF_ID;
200
201                 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
202                 params->tx_max_action_entry_sz_in_bits =
203                         BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
204                 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
205                 params->tx_num_flows_in_k = dparms->flow_db_num_entries / 1024;
206                 params->tx_tbl_if_id = BNXT_ULP_TX_TBL_IF_ID;
207         }
208 }
209
210 /* Initialize Extended Exact Match host memory. */
211 static int32_t
212 ulp_eem_tbl_scope_init(struct bnxt *bp)
213 {
214         struct tf_alloc_tbl_scope_parms params = {0};
215         int rc;
216
217         bnxt_init_tbl_scope_parms(bp, &params);
218
219         rc = tf_alloc_tbl_scope(&bp->tfp, &params);
220         if (rc) {
221                 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n",
222                             rc);
223                 return rc;
224         }
225
226         rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id);
227         if (rc) {
228                 BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
229                 return rc;
230         }
231
232         return 0;
233 }
234
235 /* Free Extended Exact Match host memory */
236 static int32_t
237 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
238 {
239         struct tf_free_tbl_scope_parms  params = {0};
240         struct tf                       *tfp;
241         int32_t                         rc = 0;
242
243         if (!ulp_ctx || !ulp_ctx->cfg_data)
244                 return -EINVAL;
245
246         /* Free the resources for the last device */
247         if (!ulp_ctx_deinit_allowed(bp))
248                 return rc;
249
250         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
251         if (!tfp) {
252                 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n");
253                 return -EINVAL;
254         }
255
256         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &params.tbl_scope_id);
257         if (rc) {
258                 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n");
259                 return -EINVAL;
260         }
261
262         rc = tf_free_tbl_scope(tfp, &params);
263         if (rc) {
264                 BNXT_TF_DBG(ERR, "Unable to free table scope\n");
265                 return -EINVAL;
266         }
267         return rc;
268 }
269
270 /* The function to free and deinit the ulp context data. */
271 static int32_t
272 ulp_ctx_deinit(struct bnxt *bp,
273                struct bnxt_ulp_session_state *session)
274 {
275         if (!session || !bp) {
276                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
277                 return -EINVAL;
278         }
279
280         /* close the tf session */
281         ulp_ctx_session_close(bp, session);
282
283         /* Free the contents */
284         if (session->cfg_data) {
285                 rte_free(session->cfg_data);
286                 bp->ulp_ctx->cfg_data = NULL;
287                 session->cfg_data = NULL;
288         }
289         return 0;
290 }
291
292 /* The function to allocate and initialize the ulp context data. */
293 static int32_t
294 ulp_ctx_init(struct bnxt *bp,
295              struct bnxt_ulp_session_state *session)
296 {
297         struct bnxt_ulp_data    *ulp_data;
298         int32_t                 rc = 0;
299
300         if (!session || !bp) {
301                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
302                 return -EINVAL;
303         }
304
305         /* Allocate memory to hold ulp context data. */
306         ulp_data = rte_zmalloc("bnxt_ulp_data",
307                                sizeof(struct bnxt_ulp_data), 0);
308         if (!ulp_data) {
309                 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n");
310                 return -ENOMEM;
311         }
312
313         /* Increment the ulp context data reference count usage. */
314         bp->ulp_ctx->cfg_data = ulp_data;
315         session->cfg_data = ulp_data;
316         ulp_data->ref_cnt++;
317
318         /* Open the ulp session. */
319         rc = ulp_ctx_session_open(bp, session);
320         if (rc) {
321                 (void)ulp_ctx_deinit(bp, session);
322                 return rc;
323         }
324         bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session->g_tfp);
325         return rc;
326 }
327
328 /* The function to initialize ulp dparms with devargs */
329 static int32_t
330 ulp_dparms_init(struct bnxt *bp,
331                 struct bnxt_ulp_context *ulp_ctx)
332 {
333         struct bnxt_ulp_device_params *dparms;
334         uint32_t dev_id;
335
336         if (!bp->max_num_kflows)
337                 return -EINVAL;
338
339         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
340                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
341                 return -EINVAL;
342         }
343
344         dparms = bnxt_ulp_device_params_get(dev_id);
345         if (!dparms) {
346                 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
347                 return -EINVAL;
348         }
349
350         /* num_flows = max_num_kflows * 1024 */
351         dparms->flow_db_num_entries = bp->max_num_kflows * 1024;
352         /* GFID =  2 * num_flows */
353         dparms->mark_db_gfid_entries = dparms->flow_db_num_entries * 2;
354         BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n",
355                     dparms->flow_db_num_entries);
356
357         return 0;
358 }
359
360 /* The function to initialize bp flags with truflow features */
361 static int32_t
362 ulp_dparms_dev_port_intf_update(struct bnxt *bp,
363                                 struct bnxt_ulp_context *ulp_ctx)
364 {
365         struct bnxt_ulp_device_params *dparms;
366         uint32_t dev_id;
367
368         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
369                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
370                 return -EINVAL;
371         }
372
373         dparms = bnxt_ulp_device_params_get(dev_id);
374         if (!dparms) {
375                 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
376                 return -EINVAL;
377         }
378
379         /* Update the bp flag with gfid flag */
380         if (dparms->flow_mem_type == BNXT_ULP_FLOW_MEM_TYPE_EXT)
381                 bp->flags |= BNXT_FLAG_GFID_ENABLE;
382
383         return 0;
384 }
385
386 static int32_t
387 ulp_ctx_attach(struct bnxt_ulp_context *ulp_ctx,
388                struct bnxt_ulp_session_state *session)
389 {
390         if (!ulp_ctx || !session) {
391                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
392                 return -EINVAL;
393         }
394
395         /* Increment the ulp context data reference count usage. */
396         ulp_ctx->cfg_data = session->cfg_data;
397         ulp_ctx->cfg_data->ref_cnt++;
398
399         /* TBD call TF_session_attach. */
400         ulp_ctx->g_tfp = session->g_tfp;
401         return 0;
402 }
403
404 static int32_t
405 ulp_ctx_detach(struct bnxt *bp,
406                struct bnxt_ulp_session_state *session)
407 {
408         struct bnxt_ulp_context *ulp_ctx;
409
410         if (!bp || !session) {
411                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
412                 return -EINVAL;
413         }
414         ulp_ctx = bp->ulp_ctx;
415
416         if (!ulp_ctx->cfg_data)
417                 return 0;
418
419         /* TBD call TF_session_detach */
420
421         /* Increment the ulp context data reference count usage. */
422         if (ulp_ctx->cfg_data->ref_cnt >= 1) {
423                 ulp_ctx->cfg_data->ref_cnt--;
424                 if (ulp_ctx_deinit_allowed(bp))
425                         ulp_ctx_deinit(bp, session);
426                 ulp_ctx->cfg_data = NULL;
427                 ulp_ctx->g_tfp = NULL;
428                 return 0;
429         }
430         BNXT_TF_DBG(ERR, "context deatach on invalid data\n");
431         return 0;
432 }
433
434 /*
435  * Initialize the state of an ULP session.
436  * If the state of an ULP session is not initialized, set it's state to
437  * initialized. If the state is already initialized, do nothing.
438  */
439 static void
440 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
441 {
442         pthread_mutex_lock(&session->bnxt_ulp_mutex);
443
444         if (!session->bnxt_ulp_init) {
445                 session->bnxt_ulp_init = true;
446                 *init = false;
447         } else {
448                 *init = true;
449         }
450
451         pthread_mutex_unlock(&session->bnxt_ulp_mutex);
452 }
453
454 /*
455  * Check if an ULP session is already allocated for a specific PCI
456  * domain & bus. If it is already allocated simply return the session
457  * pointer, otherwise allocate a new session.
458  */
459 static struct bnxt_ulp_session_state *
460 ulp_get_session(struct rte_pci_addr *pci_addr)
461 {
462         struct bnxt_ulp_session_state *session;
463
464         STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
465                 if (session->pci_info.domain == pci_addr->domain &&
466                     session->pci_info.bus == pci_addr->bus) {
467                         return session;
468                 }
469         }
470         return NULL;
471 }
472
473 /*
474  * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
475  * If it's already initialized simply return the already existing session.
476  */
477 static struct bnxt_ulp_session_state *
478 ulp_session_init(struct bnxt *bp,
479                  bool *init)
480 {
481         struct rte_pci_device           *pci_dev;
482         struct rte_pci_addr             *pci_addr;
483         struct bnxt_ulp_session_state   *session;
484
485         if (!bp)
486                 return NULL;
487
488         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
489         pci_addr = &pci_dev->addr;
490
491         pthread_mutex_lock(&bnxt_ulp_global_mutex);
492
493         session = ulp_get_session(pci_addr);
494         if (!session) {
495                 /* Not Found the session  Allocate a new one */
496                 session = rte_zmalloc("bnxt_ulp_session",
497                                       sizeof(struct bnxt_ulp_session_state),
498                                       0);
499                 if (!session) {
500                         BNXT_TF_DBG(ERR,
501                                     "Allocation failed for bnxt_ulp_session\n");
502                         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
503                         return NULL;
504
505                 } else {
506                         /* Add it to the queue */
507                         session->pci_info.domain = pci_addr->domain;
508                         session->pci_info.bus = pci_addr->bus;
509                         pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
510                         STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
511                                            session, next);
512                 }
513         }
514         ulp_context_initialized(session, init);
515         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
516         return session;
517 }
518
519 /*
520  * When a device is closed, remove it's associated session from the global
521  * session list.
522  */
523 static void
524 ulp_session_deinit(struct bnxt_ulp_session_state *session)
525 {
526         if (!session)
527                 return;
528
529         if (!session->cfg_data) {
530                 pthread_mutex_lock(&bnxt_ulp_global_mutex);
531                 STAILQ_REMOVE(&bnxt_ulp_session_list, session,
532                               bnxt_ulp_session_state, next);
533                 pthread_mutex_destroy(&session->bnxt_ulp_mutex);
534                 rte_free(session);
535                 pthread_mutex_unlock(&bnxt_ulp_global_mutex);
536         }
537 }
538
539 /*
540  * When a port is initialized by dpdk. This functions is called
541  * and this function initializes the ULP context and rest of the
542  * infrastructure associated with it.
543  */
544 int32_t
545 bnxt_ulp_init(struct bnxt *bp)
546 {
547         struct bnxt_ulp_session_state *session;
548         bool init;
549         int rc;
550
551         if (bp->ulp_ctx) {
552                 BNXT_TF_DBG(ERR, "ulp ctx already allocated\n");
553                 return -EINVAL;
554         }
555
556         /*
557          * Multiple uplink ports can be associated with a single vswitch.
558          * Make sure only the port that is started first will initialize
559          * the TF session.
560          */
561         session = ulp_session_init(bp, &init);
562         if (!session) {
563                 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
564                 return -EINVAL;
565         }
566
567         bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
568                                   sizeof(struct bnxt_ulp_context), 0);
569         if (!bp->ulp_ctx) {
570                 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
571                 ulp_session_deinit(session);
572                 return -ENOMEM;
573         }
574
575         /*
576          * If ULP is already initialized for a specific domain then simply
577          * assign the ulp context to this rte_eth_dev.
578          */
579         if (init) {
580                 rc = ulp_ctx_attach(bp->ulp_ctx, session);
581                 if (rc) {
582                         BNXT_TF_DBG(ERR,
583                                     "Failed to attach the ulp context\n");
584                         ulp_session_deinit(session);
585                         rte_free(bp->ulp_ctx);
586                         return rc;
587                 }
588
589                 /* Update bnxt driver flags */
590                 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
591                 if (rc) {
592                         BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
593                         ulp_ctx_detach(bp, session);
594                         ulp_session_deinit(session);
595                         rte_free(bp->ulp_ctx);
596                         return rc;
597                 }
598
599                 /* update the port database */
600                 rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
601                 if (rc) {
602                         BNXT_TF_DBG(ERR,
603                                     "Failed to update port database\n");
604                         ulp_ctx_detach(bp, session);
605                         ulp_session_deinit(session);
606                         rte_free(bp->ulp_ctx);
607                 }
608                 return rc;
609         }
610
611         /* Allocate and Initialize the ulp context. */
612         rc = ulp_ctx_init(bp, session);
613         if (rc) {
614                 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
615                 goto jump_to_error;
616         }
617
618         /* Initialize ulp dparms with values devargs passed */
619         rc = ulp_dparms_init(bp, bp->ulp_ctx);
620
621         /* create the port database */
622         rc = ulp_port_db_init(bp->ulp_ctx);
623         if (rc) {
624                 BNXT_TF_DBG(ERR, "Failed to create the port database\n");
625                 goto jump_to_error;
626         }
627
628         /* Update bnxt driver flags */
629         rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
630         if (rc) {
631                 BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
632                 goto jump_to_error;
633         }
634
635         /* update the port database */
636         rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
637         if (rc) {
638                 BNXT_TF_DBG(ERR, "Failed to update port database\n");
639                 goto jump_to_error;
640         }
641
642         /* Create the Mark database. */
643         rc = ulp_mark_db_init(bp->ulp_ctx);
644         if (rc) {
645                 BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
646                 goto jump_to_error;
647         }
648
649         /* Create the flow database. */
650         rc = ulp_flow_db_init(bp->ulp_ctx);
651         if (rc) {
652                 BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
653                 goto jump_to_error;
654         }
655
656         /* Create the eem table scope. */
657         rc = ulp_eem_tbl_scope_init(bp);
658         if (rc) {
659                 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
660                 goto jump_to_error;
661         }
662
663         rc = ulp_mapper_init(bp->ulp_ctx);
664         if (rc) {
665                 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
666                 goto jump_to_error;
667         }
668
669         return rc;
670
671 jump_to_error:
672         bnxt_ulp_deinit(bp);
673         return -ENOMEM;
674 }
675
676 /* Below are the access functions to access internal data of ulp context. */
677
678 /*
679  * When a port is deinit'ed by dpdk. This function is called
680  * and this function clears the ULP context and rest of the
681  * infrastructure associated with it.
682  */
683 void
684 bnxt_ulp_deinit(struct bnxt *bp)
685 {
686         struct bnxt_ulp_session_state   *session;
687         struct rte_pci_device           *pci_dev;
688         struct rte_pci_addr             *pci_addr;
689
690         /* Get the session first */
691         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
692         pci_addr = &pci_dev->addr;
693         pthread_mutex_lock(&bnxt_ulp_global_mutex);
694         session = ulp_get_session(pci_addr);
695         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
696
697         /* session not found then just exit */
698         if (!session)
699                 return;
700
701         /* clean up regular flows */
702         ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
703
704         /* cleanup the eem table scope */
705         ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
706
707         /* cleanup the flow database */
708         ulp_flow_db_deinit(bp->ulp_ctx);
709
710         /* Delete the Mark database */
711         ulp_mark_db_deinit(bp->ulp_ctx);
712
713         /* cleanup the ulp mapper */
714         ulp_mapper_deinit(bp->ulp_ctx);
715
716         /* Delete the Port database */
717         ulp_port_db_deinit(bp->ulp_ctx);
718
719         /* Delete the ulp context and tf session */
720         ulp_ctx_detach(bp, session);
721
722         /* Finally delete the bnxt session*/
723         ulp_session_deinit(session);
724
725         rte_free(bp->ulp_ctx);
726 }
727
728 /* Function to set the Mark DB into the context */
729 int32_t
730 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
731                                 struct bnxt_ulp_mark_tbl *mark_tbl)
732 {
733         if (!ulp_ctx || !ulp_ctx->cfg_data) {
734                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
735                 return -EINVAL;
736         }
737
738         ulp_ctx->cfg_data->mark_tbl = mark_tbl;
739
740         return 0;
741 }
742
743 /* Function to retrieve the Mark DB from the context. */
744 struct bnxt_ulp_mark_tbl *
745 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
746 {
747         if (!ulp_ctx || !ulp_ctx->cfg_data)
748                 return NULL;
749
750         return ulp_ctx->cfg_data->mark_tbl;
751 }
752
753 /* Function to set the device id of the hardware. */
754 int32_t
755 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
756                           uint32_t dev_id)
757 {
758         if (ulp_ctx && ulp_ctx->cfg_data) {
759                 ulp_ctx->cfg_data->dev_id = dev_id;
760                 return 0;
761         }
762
763         return -EINVAL;
764 }
765
766 /* Function to get the device id of the hardware. */
767 int32_t
768 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
769                           uint32_t *dev_id)
770 {
771         if (ulp_ctx && ulp_ctx->cfg_data) {
772                 *dev_id = ulp_ctx->cfg_data->dev_id;
773                 return 0;
774         }
775
776         return -EINVAL;
777 }
778
779 /* Function to get the table scope id of the EEM table. */
780 int32_t
781 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
782                                 uint32_t *tbl_scope_id)
783 {
784         if (ulp_ctx && ulp_ctx->cfg_data) {
785                 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
786                 return 0;
787         }
788
789         return -EINVAL;
790 }
791
792 /* Function to set the table scope id of the EEM table. */
793 int32_t
794 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
795                                 uint32_t tbl_scope_id)
796 {
797         if (ulp_ctx && ulp_ctx->cfg_data) {
798                 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
799                 return 0;
800         }
801
802         return -EINVAL;
803 }
804
805 /* Function to set the tfp session details from the ulp context. */
806 int32_t
807 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
808 {
809         if (!ulp) {
810                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
811                 return -EINVAL;
812         }
813
814         /* TBD The tfp should be removed once tf_attach is implemented. */
815         ulp->g_tfp = tfp;
816         return 0;
817 }
818
819 /* Function to get the tfp session details from the ulp context. */
820 struct tf *
821 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp)
822 {
823         if (!ulp) {
824                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
825                 return NULL;
826         }
827         /* TBD The tfp should be removed once tf_attach is implemented. */
828         return ulp->g_tfp;
829 }
830
831 /*
832  * Get the device table entry based on the device id.
833  *
834  * dev_id [in] The device id of the hardware
835  *
836  * Returns the pointer to the device parameters.
837  */
838 struct bnxt_ulp_device_params *
839 bnxt_ulp_device_params_get(uint32_t dev_id)
840 {
841         if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
842                 return &ulp_device_params[dev_id];
843         return NULL;
844 }
845
846 /* Function to set the flow database to the ulp context. */
847 int32_t
848 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx,
849                                 struct bnxt_ulp_flow_db *flow_db)
850 {
851         if (!ulp_ctx || !ulp_ctx->cfg_data)
852                 return -EINVAL;
853
854         ulp_ctx->cfg_data->flow_db = flow_db;
855         return 0;
856 }
857
858 /* Function to get the flow database from the ulp context. */
859 struct bnxt_ulp_flow_db *
860 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx)
861 {
862         if (!ulp_ctx || !ulp_ctx->cfg_data)
863                 return NULL;
864
865         return ulp_ctx->cfg_data->flow_db;
866 }
867
868 /* Function to get the ulp context from eth device. */
869 struct bnxt_ulp_context *
870 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev      *dev)
871 {
872         struct bnxt     *bp;
873
874         bp = (struct bnxt *)dev->data->dev_private;
875         if (!bp) {
876                 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
877                 return NULL;
878         }
879         return bp->ulp_ctx;
880 }
881
882 int32_t
883 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
884                                     void *mapper_data)
885 {
886         if (!ulp_ctx || !ulp_ctx->cfg_data) {
887                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
888                 return -EINVAL;
889         }
890
891         ulp_ctx->cfg_data->mapper_data = mapper_data;
892         return 0;
893 }
894
895 void *
896 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
897 {
898         if (!ulp_ctx || !ulp_ctx->cfg_data) {
899                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
900                 return NULL;
901         }
902
903         return ulp_ctx->cfg_data->mapper_data;
904 }
905
906 /* Function to set the port database to the ulp context. */
907 int32_t
908 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx,
909                                 struct bnxt_ulp_port_db *port_db)
910 {
911         if (!ulp_ctx || !ulp_ctx->cfg_data)
912                 return -EINVAL;
913
914         ulp_ctx->cfg_data->port_db = port_db;
915         return 0;
916 }
917
918 /* Function to get the port database from the ulp context. */
919 struct bnxt_ulp_port_db *
920 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx)
921 {
922         if (!ulp_ctx || !ulp_ctx->cfg_data)
923                 return NULL;
924
925         return ulp_ctx->cfg_data->port_db;
926 }