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