net/bnxt: modify resource management scheme
[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
365         /* Open the ulp session. */
366         rc = ulp_ctx_session_open(bp, session);
367         if (rc) {
368                 (void)ulp_ctx_deinit(bp, session);
369                 return rc;
370         }
371         bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, session->g_tfp);
372         return rc;
373 }
374
375 /* The function to initialize ulp dparms with devargs */
376 static int32_t
377 ulp_dparms_init(struct bnxt *bp,
378                 struct bnxt_ulp_context *ulp_ctx)
379 {
380         struct bnxt_ulp_device_params *dparms;
381         uint32_t dev_id;
382
383         if (!bp->max_num_kflows)
384                 return -EINVAL;
385
386         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
387                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
388                 return -EINVAL;
389         }
390
391         dparms = bnxt_ulp_device_params_get(dev_id);
392         if (!dparms) {
393                 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
394                 return -EINVAL;
395         }
396
397         /* num_flows = max_num_kflows * 1024 */
398         dparms->flow_db_num_entries = bp->max_num_kflows * 1024;
399         /* GFID =  2 * num_flows */
400         dparms->mark_db_gfid_entries = dparms->flow_db_num_entries * 2;
401         BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n",
402                     dparms->flow_db_num_entries);
403
404         return 0;
405 }
406
407 /* The function to initialize bp flags with truflow features */
408 static int32_t
409 ulp_dparms_dev_port_intf_update(struct bnxt *bp,
410                                 struct bnxt_ulp_context *ulp_ctx)
411 {
412         struct bnxt_ulp_device_params *dparms;
413         uint32_t dev_id;
414
415         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
416                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
417                 return -EINVAL;
418         }
419
420         dparms = bnxt_ulp_device_params_get(dev_id);
421         if (!dparms) {
422                 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
423                 return -EINVAL;
424         }
425
426         /* Update the bp flag with gfid flag */
427         if (dparms->flow_mem_type == BNXT_ULP_FLOW_MEM_TYPE_EXT)
428                 bp->flags |= BNXT_FLAG_GFID_ENABLE;
429
430         return 0;
431 }
432
433 static int32_t
434 ulp_ctx_attach(struct bnxt_ulp_context *ulp_ctx,
435                struct bnxt_ulp_session_state *session)
436 {
437         if (!ulp_ctx || !session) {
438                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
439                 return -EINVAL;
440         }
441
442         /* Increment the ulp context data reference count usage. */
443         ulp_ctx->cfg_data = session->cfg_data;
444         ulp_ctx->cfg_data->ref_cnt++;
445
446         /* TBD call TF_session_attach. */
447         ulp_ctx->g_tfp = session->g_tfp;
448         return 0;
449 }
450
451 static int32_t
452 ulp_ctx_detach(struct bnxt *bp,
453                struct bnxt_ulp_session_state *session)
454 {
455         struct bnxt_ulp_context *ulp_ctx;
456
457         if (!bp || !session) {
458                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
459                 return -EINVAL;
460         }
461         ulp_ctx = bp->ulp_ctx;
462
463         if (!ulp_ctx->cfg_data)
464                 return 0;
465
466         /* TBD call TF_session_detach */
467
468         /* Increment the ulp context data reference count usage. */
469         if (ulp_ctx->cfg_data->ref_cnt >= 1) {
470                 ulp_ctx->cfg_data->ref_cnt--;
471                 if (ulp_ctx_deinit_allowed(bp))
472                         ulp_ctx_deinit(bp, session);
473                 ulp_ctx->cfg_data = NULL;
474                 ulp_ctx->g_tfp = NULL;
475                 return 0;
476         }
477         BNXT_TF_DBG(ERR, "context deatach on invalid data\n");
478         return 0;
479 }
480
481 /*
482  * Initialize the state of an ULP session.
483  * If the state of an ULP session is not initialized, set it's state to
484  * initialized. If the state is already initialized, do nothing.
485  */
486 static void
487 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
488 {
489         pthread_mutex_lock(&session->bnxt_ulp_mutex);
490
491         if (!session->bnxt_ulp_init) {
492                 session->bnxt_ulp_init = true;
493                 *init = false;
494         } else {
495                 *init = true;
496         }
497
498         pthread_mutex_unlock(&session->bnxt_ulp_mutex);
499 }
500
501 /*
502  * Check if an ULP session is already allocated for a specific PCI
503  * domain & bus. If it is already allocated simply return the session
504  * pointer, otherwise allocate a new session.
505  */
506 static struct bnxt_ulp_session_state *
507 ulp_get_session(struct rte_pci_addr *pci_addr)
508 {
509         struct bnxt_ulp_session_state *session;
510
511         STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
512                 if (session->pci_info.domain == pci_addr->domain &&
513                     session->pci_info.bus == pci_addr->bus) {
514                         return session;
515                 }
516         }
517         return NULL;
518 }
519
520 /*
521  * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
522  * If it's already initialized simply return the already existing session.
523  */
524 static struct bnxt_ulp_session_state *
525 ulp_session_init(struct bnxt *bp,
526                  bool *init)
527 {
528         struct rte_pci_device           *pci_dev;
529         struct rte_pci_addr             *pci_addr;
530         struct bnxt_ulp_session_state   *session;
531
532         if (!bp)
533                 return NULL;
534
535         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
536         pci_addr = &pci_dev->addr;
537
538         pthread_mutex_lock(&bnxt_ulp_global_mutex);
539
540         session = ulp_get_session(pci_addr);
541         if (!session) {
542                 /* Not Found the session  Allocate a new one */
543                 session = rte_zmalloc("bnxt_ulp_session",
544                                       sizeof(struct bnxt_ulp_session_state),
545                                       0);
546                 if (!session) {
547                         BNXT_TF_DBG(ERR,
548                                     "Allocation failed for bnxt_ulp_session\n");
549                         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
550                         return NULL;
551
552                 } else {
553                         /* Add it to the queue */
554                         session->pci_info.domain = pci_addr->domain;
555                         session->pci_info.bus = pci_addr->bus;
556                         pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
557                         STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
558                                            session, next);
559                 }
560         }
561         ulp_context_initialized(session, init);
562         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
563         return session;
564 }
565
566 /*
567  * When a device is closed, remove it's associated session from the global
568  * session list.
569  */
570 static void
571 ulp_session_deinit(struct bnxt_ulp_session_state *session)
572 {
573         if (!session)
574                 return;
575
576         if (!session->cfg_data) {
577                 pthread_mutex_lock(&bnxt_ulp_global_mutex);
578                 STAILQ_REMOVE(&bnxt_ulp_session_list, session,
579                               bnxt_ulp_session_state, next);
580                 pthread_mutex_destroy(&session->bnxt_ulp_mutex);
581                 rte_free(session);
582                 pthread_mutex_unlock(&bnxt_ulp_global_mutex);
583         }
584 }
585
586 /*
587  * When a port is initialized by dpdk. This functions is called
588  * and this function initializes the ULP context and rest of the
589  * infrastructure associated with it.
590  */
591 int32_t
592 bnxt_ulp_init(struct bnxt *bp)
593 {
594         struct bnxt_ulp_session_state *session;
595         bool init;
596         int rc;
597
598         if (bp->ulp_ctx) {
599                 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n");
600                 return -EINVAL;
601         }
602
603         /*
604          * Multiple uplink ports can be associated with a single vswitch.
605          * Make sure only the port that is started first will initialize
606          * the TF session.
607          */
608         session = ulp_session_init(bp, &init);
609         if (!session) {
610                 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
611                 return -EINVAL;
612         }
613
614         bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
615                                   sizeof(struct bnxt_ulp_context), 0);
616         if (!bp->ulp_ctx) {
617                 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
618                 ulp_session_deinit(session);
619                 return -ENOMEM;
620         }
621
622         /*
623          * If ULP is already initialized for a specific domain then simply
624          * assign the ulp context to this rte_eth_dev.
625          */
626         if (init) {
627                 rc = ulp_ctx_attach(bp->ulp_ctx, session);
628                 if (rc) {
629                         BNXT_TF_DBG(ERR,
630                                     "Failed to attach the ulp context\n");
631                         ulp_session_deinit(session);
632                         rte_free(bp->ulp_ctx);
633                         return rc;
634                 }
635
636                 /* Update bnxt driver flags */
637                 rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
638                 if (rc) {
639                         BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
640                         ulp_ctx_detach(bp, session);
641                         ulp_session_deinit(session);
642                         rte_free(bp->ulp_ctx);
643                         return rc;
644                 }
645
646                 /* update the port database */
647                 rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
648                 if (rc) {
649                         BNXT_TF_DBG(ERR,
650                                     "Failed to update port database\n");
651                         ulp_ctx_detach(bp, session);
652                         ulp_session_deinit(session);
653                         rte_free(bp->ulp_ctx);
654                 }
655                 return rc;
656         }
657
658         /* Allocate and Initialize the ulp context. */
659         rc = ulp_ctx_init(bp, session);
660         if (rc) {
661                 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
662                 goto jump_to_error;
663         }
664
665         /* Initialize ulp dparms with values devargs passed */
666         rc = ulp_dparms_init(bp, bp->ulp_ctx);
667
668         /* create the port database */
669         rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt);
670         if (rc) {
671                 BNXT_TF_DBG(ERR, "Failed to create the port database\n");
672                 goto jump_to_error;
673         }
674
675         /* Update bnxt driver flags */
676         rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
677         if (rc) {
678                 BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
679                 goto jump_to_error;
680         }
681
682         /* update the port database */
683         rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
684         if (rc) {
685                 BNXT_TF_DBG(ERR, "Failed to update port database\n");
686                 goto jump_to_error;
687         }
688
689         /* Create the Mark database. */
690         rc = ulp_mark_db_init(bp->ulp_ctx);
691         if (rc) {
692                 BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
693                 goto jump_to_error;
694         }
695
696         /* Create the flow database. */
697         rc = ulp_flow_db_init(bp->ulp_ctx);
698         if (rc) {
699                 BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
700                 goto jump_to_error;
701         }
702
703         /* Create the eem table scope. */
704         rc = ulp_eem_tbl_scope_init(bp);
705         if (rc) {
706                 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
707                 goto jump_to_error;
708         }
709
710         rc = ulp_mapper_init(bp->ulp_ctx);
711         if (rc) {
712                 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
713                 goto jump_to_error;
714         }
715
716         rc = ulp_fc_mgr_init(bp->ulp_ctx);
717         if (rc) {
718                 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n");
719                 goto jump_to_error;
720         }
721
722         return rc;
723
724 jump_to_error:
725         bnxt_ulp_deinit(bp);
726         return -ENOMEM;
727 }
728
729 /* Below are the access functions to access internal data of ulp context. */
730
731 /*
732  * When a port is deinit'ed by dpdk. This function is called
733  * and this function clears the ULP context and rest of the
734  * infrastructure associated with it.
735  */
736 void
737 bnxt_ulp_deinit(struct bnxt *bp)
738 {
739         struct bnxt_ulp_session_state   *session;
740         struct rte_pci_device           *pci_dev;
741         struct rte_pci_addr             *pci_addr;
742
743         /* Get the session first */
744         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
745         pci_addr = &pci_dev->addr;
746         pthread_mutex_lock(&bnxt_ulp_global_mutex);
747         session = ulp_get_session(pci_addr);
748         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
749
750         /* session not found then just exit */
751         if (!session)
752                 return;
753
754         /* clean up regular flows */
755         ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_REGULAR_FLOW_TABLE);
756
757         /* cleanup the eem table scope */
758         ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
759
760         /* cleanup the flow database */
761         ulp_flow_db_deinit(bp->ulp_ctx);
762
763         /* Delete the Mark database */
764         ulp_mark_db_deinit(bp->ulp_ctx);
765
766         /* cleanup the ulp mapper */
767         ulp_mapper_deinit(bp->ulp_ctx);
768
769         /* Delete the Flow Counter Manager */
770         ulp_fc_mgr_deinit(bp->ulp_ctx);
771
772         /* Delete the Port database */
773         ulp_port_db_deinit(bp->ulp_ctx);
774
775         /* Delete the ulp context and tf session */
776         ulp_ctx_detach(bp, session);
777
778         /* Finally delete the bnxt session*/
779         ulp_session_deinit(session);
780
781         rte_free(bp->ulp_ctx);
782 }
783
784 /* Function to set the Mark DB into the context */
785 int32_t
786 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
787                                 struct bnxt_ulp_mark_tbl *mark_tbl)
788 {
789         if (!ulp_ctx || !ulp_ctx->cfg_data) {
790                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
791                 return -EINVAL;
792         }
793
794         ulp_ctx->cfg_data->mark_tbl = mark_tbl;
795
796         return 0;
797 }
798
799 /* Function to retrieve the Mark DB from the context. */
800 struct bnxt_ulp_mark_tbl *
801 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
802 {
803         if (!ulp_ctx || !ulp_ctx->cfg_data)
804                 return NULL;
805
806         return ulp_ctx->cfg_data->mark_tbl;
807 }
808
809 /* Function to set the device id of the hardware. */
810 int32_t
811 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
812                           uint32_t dev_id)
813 {
814         if (ulp_ctx && ulp_ctx->cfg_data) {
815                 ulp_ctx->cfg_data->dev_id = dev_id;
816                 return 0;
817         }
818
819         return -EINVAL;
820 }
821
822 /* Function to get the device id of the hardware. */
823 int32_t
824 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
825                           uint32_t *dev_id)
826 {
827         if (ulp_ctx && ulp_ctx->cfg_data) {
828                 *dev_id = ulp_ctx->cfg_data->dev_id;
829                 return 0;
830         }
831
832         return -EINVAL;
833 }
834
835 /* Function to get the table scope id of the EEM table. */
836 int32_t
837 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
838                                 uint32_t *tbl_scope_id)
839 {
840         if (ulp_ctx && ulp_ctx->cfg_data) {
841                 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
842                 return 0;
843         }
844
845         return -EINVAL;
846 }
847
848 /* Function to set the table scope id of the EEM table. */
849 int32_t
850 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
851                                 uint32_t tbl_scope_id)
852 {
853         if (ulp_ctx && ulp_ctx->cfg_data) {
854                 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
855                 return 0;
856         }
857
858         return -EINVAL;
859 }
860
861 /* Function to set the tfp session details from the ulp context. */
862 int32_t
863 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
864 {
865         if (!ulp) {
866                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
867                 return -EINVAL;
868         }
869
870         /* TBD The tfp should be removed once tf_attach is implemented. */
871         ulp->g_tfp = tfp;
872         return 0;
873 }
874
875 /* Function to get the tfp session details from the ulp context. */
876 struct tf *
877 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp)
878 {
879         if (!ulp) {
880                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
881                 return NULL;
882         }
883         /* TBD The tfp should be removed once tf_attach is implemented. */
884         return ulp->g_tfp;
885 }
886
887 /*
888  * Get the device table entry based on the device id.
889  *
890  * dev_id [in] The device id of the hardware
891  *
892  * Returns the pointer to the device parameters.
893  */
894 struct bnxt_ulp_device_params *
895 bnxt_ulp_device_params_get(uint32_t dev_id)
896 {
897         if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
898                 return &ulp_device_params[dev_id];
899         return NULL;
900 }
901
902 /* Function to set the flow database to the ulp context. */
903 int32_t
904 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx,
905                                 struct bnxt_ulp_flow_db *flow_db)
906 {
907         if (!ulp_ctx || !ulp_ctx->cfg_data)
908                 return -EINVAL;
909
910         ulp_ctx->cfg_data->flow_db = flow_db;
911         return 0;
912 }
913
914 /* Function to get the flow database from the ulp context. */
915 struct bnxt_ulp_flow_db *
916 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx)
917 {
918         if (!ulp_ctx || !ulp_ctx->cfg_data)
919                 return NULL;
920
921         return ulp_ctx->cfg_data->flow_db;
922 }
923
924 /* Function to get the ulp context from eth device. */
925 struct bnxt_ulp_context *
926 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev      *dev)
927 {
928         struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
929
930         if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) {
931                 struct bnxt_vf_representor *vfr = dev->data->dev_private;
932                 bp = vfr->parent_dev->data->dev_private;
933         }
934
935         if (!bp) {
936                 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
937                 return NULL;
938         }
939         return bp->ulp_ctx;
940 }
941
942 int32_t
943 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
944                                     void *mapper_data)
945 {
946         if (!ulp_ctx || !ulp_ctx->cfg_data) {
947                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
948                 return -EINVAL;
949         }
950
951         ulp_ctx->cfg_data->mapper_data = mapper_data;
952         return 0;
953 }
954
955 void *
956 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
957 {
958         if (!ulp_ctx || !ulp_ctx->cfg_data) {
959                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
960                 return NULL;
961         }
962
963         return ulp_ctx->cfg_data->mapper_data;
964 }
965
966 /* Function to set the port database to the ulp context. */
967 int32_t
968 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx,
969                                 struct bnxt_ulp_port_db *port_db)
970 {
971         if (!ulp_ctx || !ulp_ctx->cfg_data)
972                 return -EINVAL;
973
974         ulp_ctx->cfg_data->port_db = port_db;
975         return 0;
976 }
977
978 /* Function to get the port database from the ulp context. */
979 struct bnxt_ulp_port_db *
980 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx)
981 {
982         if (!ulp_ctx || !ulp_ctx->cfg_data)
983                 return NULL;
984
985         return ulp_ctx->cfg_data->port_db;
986 }
987
988 /* Function to set the flow counter info into the context */
989 int32_t
990 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx,
991                                 struct bnxt_ulp_fc_info *ulp_fc_info)
992 {
993         if (!ulp_ctx || !ulp_ctx->cfg_data) {
994                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
995                 return -EINVAL;
996         }
997
998         ulp_ctx->cfg_data->fc_info = ulp_fc_info;
999
1000         return 0;
1001 }
1002
1003 /* Function to retrieve the flow counter info from the context. */
1004 struct bnxt_ulp_fc_info *
1005 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx)
1006 {
1007         if (!ulp_ctx || !ulp_ctx->cfg_data)
1008                 return NULL;
1009
1010         return ulp_ctx->cfg_data->fc_info;
1011 }