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