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