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