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