net/bnxt: refactor flow parser in ULP
[dpdk.git] / drivers / net / bnxt / tf_ulp / bnxt_ulp.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019-2021 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.h"
13 #include "bnxt_ulp.h"
14 #include "bnxt_tf_common.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 #include "ulp_tun.h"
26
27 /* Linked list of all TF sessions. */
28 STAILQ_HEAD(, bnxt_ulp_session_state) bnxt_ulp_session_list =
29                         STAILQ_HEAD_INITIALIZER(bnxt_ulp_session_list);
30
31 /* Mutex to synchronize bnxt_ulp_session_list operations. */
32 static pthread_mutex_t bnxt_ulp_global_mutex = PTHREAD_MUTEX_INITIALIZER;
33
34 /*
35  * Allow the deletion of context only for the bnxt device that
36  * created the session.
37  */
38 bool
39 ulp_ctx_deinit_allowed(struct bnxt_ulp_context *ulp_ctx)
40 {
41         if (!ulp_ctx || !ulp_ctx->cfg_data)
42                 return false;
43
44         if (!ulp_ctx->cfg_data->ref_cnt) {
45                 BNXT_TF_DBG(DEBUG, "ulp ctx shall initiate deinit\n");
46                 return true;
47         }
48
49         return false;
50 }
51
52 static int32_t
53 bnxt_ulp_devid_get(struct bnxt *bp,
54                    enum bnxt_ulp_device_id  *ulp_dev_id)
55 {
56         if (BNXT_CHIP_P5(bp)) {
57                 /* TBD: needs to accommodate even SR2 */
58                 *ulp_dev_id = BNXT_ULP_DEVICE_ID_THOR;
59                 return 0;
60         }
61
62         if (BNXT_STINGRAY(bp))
63                 *ulp_dev_id = BNXT_ULP_DEVICE_ID_STINGRAY;
64         else
65                 /* Assuming Whitney */
66                 *ulp_dev_id = BNXT_ULP_DEVICE_ID_WH_PLUS;
67
68         return 0;
69 }
70
71 static int32_t
72 bnxt_ulp_tf_session_resources_get(struct bnxt *bp,
73                                   struct tf_session_resources *res)
74 {
75         uint32_t dev_id;
76         int32_t rc;
77         uint16_t *tmp_cnt;
78
79         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
80         if (rc) {
81                 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
82                 return -EINVAL;
83         }
84
85         switch (dev_id) {
86         case BNXT_ULP_DEVICE_ID_WH_PLUS:
87                 /** RX **/
88                 /* Identifiers */
89                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 422;
90                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6;
91                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
92                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
93                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
94
95                 /* Table Types */
96                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
97                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 8192;
98                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
99
100                 /* ENCAP */
101                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 511;
102                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 63;
103
104                 /* TCAMs */
105                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
106                         422;
107                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
108                         6;
109                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
110                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 88;
111
112                 /* EM */
113                 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13168;
114
115                 /* EEM */
116                 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
117
118                 /* SP */
119                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC] = 255;
120
121                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_MIRROR_CONFIG] = 1;
122
123                 /** TX **/
124                 /* Identifiers */
125                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 292;
126                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 148;
127                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
128                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
129                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
130
131                 /* Table Types */
132                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
133                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 8192;
134                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
135
136                 /* ENCAP */
137                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 511;
138                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 223;
139                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 255;
140
141                 /* TCAMs */
142                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
143                         292;
144                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
145                         144;
146                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
147                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 928;
148
149                 /* EM */
150                 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232;
151
152                 /* EEM */
153                 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
154
155                 /* SP */
156                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 488;
157                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = 511;
158
159                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_MIRROR_CONFIG] = 1;
160
161                 break;
162         case BNXT_ULP_DEVICE_ID_STINGRAY:
163                 /** RX **/
164                 /* Identifiers */
165                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 315;
166                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6;
167                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
168                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
169                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
170
171                 /* Table Types */
172                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
173                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384;
174                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
175
176                 /* ENCAP */
177                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 511;
178                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 63;
179
180                 /* TCAMs */
181                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
182                         315;
183                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
184                         6;
185                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
186                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 112;
187
188                 /* EM */
189                 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13200;
190
191                 /* EEM */
192                 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
193
194                 /* SP */
195                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC] = 256;
196
197                 /** TX **/
198                 /* Identifiers */
199                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 292;
200                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 127;
201                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 192;
202                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 64;
203                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 192;
204
205                 /* Table Types */
206                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 8192;
207                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 16384;
208                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_MODIFY_IPV4] = 1023;
209
210                 /* ENCAP */
211                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 367;
212                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_16B] = 223;
213                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_8B] = 255;
214
215                 /* TCAMs */
216                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] =
217                         292;
218                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] =
219                         127;
220                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 960;
221                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 928;
222
223                 /* EM */
224                 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232;
225
226                 /* EEM */
227                 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_TBL_SCOPE] = 1;
228
229                 /* SP */
230                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 488;
231                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV6] = 512;
232                 break;
233         case BNXT_ULP_DEVICE_ID_THOR:
234                 /** RX **/
235                 /* Identifiers */
236                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 26;
237                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 6;
238                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_WC_PROF] = 32;
239                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 32;
240                 res->ident_cnt[TF_DIR_RX].cnt[TF_IDENT_TYPE_EM_PROF] = 32;
241
242                 /* Table Types */
243                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 1024;
244                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 512;
245                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_MIRROR_CONFIG] = 14;
246                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_EM_FKB] = 32;
247                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_WC_FKB] = 32;
248
249                 /* ENCAP */
250                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 64;
251
252                 /* TCAMs */
253                 tmp_cnt = &res->tcam_cnt[TF_DIR_RX].cnt[0];
254                 tmp_cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = 300;
255                 tmp_cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = 6;
256                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 128;
257                 res->tcam_cnt[TF_DIR_RX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 112;
258
259                 /* EM */
260                 res->em_cnt[TF_DIR_RX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 13200;
261
262                 /* SP */
263                 res->tbl_cnt[TF_DIR_RX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 64;
264
265                 /** TX **/
266                 /* Identifiers */
267                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_HIGH] = 26;
268                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_L2_CTXT_LOW] = 26;
269                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_WC_PROF] = 32;
270                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_PROF_FUNC] = 63;
271                 res->ident_cnt[TF_DIR_TX].cnt[TF_IDENT_TYPE_EM_PROF] = 32;
272
273                 /* Table Types */
274                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_FULL_ACT_RECORD] = 1024;
275                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_STATS_64] = 512;
276                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_MIRROR_CONFIG] = 14;
277                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_EM_FKB] = 32;
278                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_WC_FKB] = 32;
279
280                 /* ENCAP */
281                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_ENCAP_64B] = 64;
282
283                 /* TCAMs */
284                 tmp_cnt = &res->tcam_cnt[TF_DIR_TX].cnt[0];
285
286                 tmp_cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_HIGH] = 200;
287                 tmp_cnt[TF_TCAM_TBL_TYPE_L2_CTXT_TCAM_LOW] = 110;
288                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_PROF_TCAM] = 128;
289                 res->tcam_cnt[TF_DIR_TX].cnt[TF_TCAM_TBL_TYPE_WC_TCAM] = 128;
290
291                 /* EM */
292                 res->em_cnt[TF_DIR_TX].cnt[TF_EM_TBL_TYPE_EM_RECORD] = 15232;
293
294                 /* SP */
295                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_ACT_SP_SMAC_IPV4] = 100;
296
297                 res->tbl_cnt[TF_DIR_TX].cnt[TF_TBL_TYPE_MIRROR_CONFIG] = 1;
298
299                 break;
300         default:
301                 return -EINVAL;
302         }
303
304         return 0;
305 }
306
307 /*
308  * Initialize an ULP session.
309  * An ULP session will contain all the resources needed to support rte flow
310  * offloads. A session is initialized as part of rte_eth_device start.
311  * A single vswitch instance can have multiple uplinks which means
312  * rte_eth_device start will be called for each of these devices.
313  * ULP session manager will make sure that a single ULP session is only
314  * initialized once. Apart from this, it also initializes MARK database,
315  * EEM table & flow database. ULP session manager also manages a list of
316  * all opened ULP sessions.
317  */
318 static int32_t
319 ulp_ctx_session_open(struct bnxt *bp,
320                      struct bnxt_ulp_session_state *session)
321 {
322         struct rte_eth_dev              *ethdev = bp->eth_dev;
323         int32_t                         rc = 0;
324         struct tf_open_session_parms    params;
325         struct tf_session_resources     *resources;
326         uint32_t                        ulp_dev_id;
327
328         memset(&params, 0, sizeof(params));
329
330         rc = rte_eth_dev_get_name_by_port(ethdev->data->port_id,
331                                           params.ctrl_chan_name);
332         if (rc) {
333                 BNXT_TF_DBG(ERR, "Invalid port %d, rc = %d\n",
334                             ethdev->data->port_id, rc);
335                 return rc;
336         }
337
338         params.shadow_copy = true;
339
340         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &ulp_dev_id);
341         if (rc) {
342                 BNXT_TF_DBG(ERR, "Unable to get device id from ulp.\n");
343                 return rc;
344         }
345
346         switch (ulp_dev_id) {
347         case BNXT_ULP_DEVICE_ID_WH_PLUS:
348                 params.device_type = TF_DEVICE_TYPE_WH;
349                 break;
350         case BNXT_ULP_DEVICE_ID_STINGRAY:
351                 params.device_type = TF_DEVICE_TYPE_SR;
352                 break;
353         case BNXT_ULP_DEVICE_ID_THOR:
354                 params.device_type = TF_DEVICE_TYPE_THOR;
355                 break;
356         default:
357                 BNXT_TF_DBG(ERR, "Unable to determine device for "
358                             "opening session.\n");
359                 return rc;
360         }
361
362         resources = &params.resources;
363         rc = bnxt_ulp_tf_session_resources_get(bp, resources);
364         if (rc) {
365                 BNXT_TF_DBG(ERR, "Unable to determine tf resources for "
366                             "session open.\n");
367                 return rc;
368         }
369
370         params.bp = bp;
371         rc = tf_open_session(&bp->tfp, &params);
372         if (rc) {
373                 BNXT_TF_DBG(ERR, "Failed to open TF session - %s, rc = %d\n",
374                             params.ctrl_chan_name, rc);
375                 return -EINVAL;
376         }
377         if (!session->session_opened) {
378                 session->session_opened = 1;
379                 session->g_tfp = rte_zmalloc("bnxt_ulp_session_tfp",
380                                              sizeof(struct tf), 0);
381                 session->g_tfp->session = bp->tfp.session;
382         }
383         return rc;
384 }
385
386 /*
387  * Close the ULP session.
388  * It takes the ulp context pointer.
389  */
390 static void
391 ulp_ctx_session_close(struct bnxt *bp,
392                       struct bnxt_ulp_session_state *session)
393 {
394         /* close the session in the hardware */
395         if (session->session_opened)
396                 tf_close_session(&bp->tfp);
397         session->session_opened = 0;
398         rte_free(session->g_tfp);
399         session->g_tfp = NULL;
400 }
401
402 static void
403 bnxt_init_tbl_scope_parms(struct bnxt *bp,
404                           struct tf_alloc_tbl_scope_parms *params)
405 {
406         struct bnxt_ulp_device_params   *dparms;
407         uint32_t dev_id;
408         int rc;
409
410         rc = bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id);
411         if (rc)
412                 /* TBD: For now, just use default. */
413                 dparms = 0;
414         else
415                 dparms = bnxt_ulp_device_params_get(dev_id);
416
417         /*
418          * Set the flush timer for EEM entries. The value is in 100ms intervals,
419          * so 100 is 10s.
420          */
421         params->hw_flow_cache_flush_timer = 100;
422
423         if (!dparms) {
424                 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
425                 params->rx_max_action_entry_sz_in_bits =
426                         BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
427                 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
428                 params->rx_num_flows_in_k = BNXT_ULP_RX_NUM_FLOWS;
429
430                 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
431                 params->tx_max_action_entry_sz_in_bits =
432                         BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
433                 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
434                 params->tx_num_flows_in_k = BNXT_ULP_TX_NUM_FLOWS;
435         } else {
436                 params->rx_max_key_sz_in_bits = BNXT_ULP_DFLT_RX_MAX_KEY;
437                 params->rx_max_action_entry_sz_in_bits =
438                         BNXT_ULP_DFLT_RX_MAX_ACTN_ENTRY;
439                 params->rx_mem_size_in_mb = BNXT_ULP_DFLT_RX_MEM;
440                 params->rx_num_flows_in_k =
441                         dparms->ext_flow_db_num_entries / 1024;
442
443                 params->tx_max_key_sz_in_bits = BNXT_ULP_DFLT_TX_MAX_KEY;
444                 params->tx_max_action_entry_sz_in_bits =
445                         BNXT_ULP_DFLT_TX_MAX_ACTN_ENTRY;
446                 params->tx_mem_size_in_mb = BNXT_ULP_DFLT_TX_MEM;
447                 params->tx_num_flows_in_k =
448                         dparms->ext_flow_db_num_entries / 1024;
449         }
450         BNXT_TF_DBG(INFO, "Table Scope initialized with %uK flows.\n",
451                     params->rx_num_flows_in_k);
452 }
453
454 /* Initialize Extended Exact Match host memory. */
455 static int32_t
456 ulp_eem_tbl_scope_init(struct bnxt *bp)
457 {
458         struct tf_alloc_tbl_scope_parms params = {0};
459         struct bnxt_ulp_device_params *dparms;
460         enum bnxt_ulp_flow_mem_type mtype;
461         uint32_t dev_id;
462         int rc;
463
464         /* Get the dev specific number of flows that needed to be supported. */
465         if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
466                 BNXT_TF_DBG(ERR, "Invalid device id\n");
467                 return -EINVAL;
468         }
469
470         dparms = bnxt_ulp_device_params_get(dev_id);
471         if (!dparms) {
472                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
473                 return -ENODEV;
474         }
475
476         if (bnxt_ulp_cntxt_mem_type_get(bp->ulp_ctx, &mtype))
477                 return -EINVAL;
478         if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
479                 BNXT_TF_DBG(INFO, "Table Scope alloc is not required\n");
480                 return 0;
481         }
482
483         bnxt_init_tbl_scope_parms(bp, &params);
484         rc = tf_alloc_tbl_scope(&bp->tfp, &params);
485         if (rc) {
486                 BNXT_TF_DBG(ERR, "Unable to allocate eem table scope rc = %d\n",
487                             rc);
488                 return rc;
489         }
490         rc = bnxt_ulp_cntxt_tbl_scope_id_set(bp->ulp_ctx, params.tbl_scope_id);
491         if (rc) {
492                 BNXT_TF_DBG(ERR, "Unable to set table scope id\n");
493                 return rc;
494         }
495
496         return 0;
497 }
498
499 /* Free Extended Exact Match host memory */
500 static int32_t
501 ulp_eem_tbl_scope_deinit(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
502 {
503         struct tf_free_tbl_scope_parms  params = {0};
504         struct tf                       *tfp;
505         int32_t                         rc = 0;
506         struct bnxt_ulp_device_params *dparms;
507         enum bnxt_ulp_flow_mem_type mtype;
508         uint32_t dev_id;
509
510         if (!ulp_ctx || !ulp_ctx->cfg_data)
511                 return -EINVAL;
512
513         tfp = bnxt_ulp_cntxt_tfp_get(ulp_ctx);
514         if (!tfp) {
515                 BNXT_TF_DBG(ERR, "Failed to get the truflow pointer\n");
516                 return -EINVAL;
517         }
518
519         /* Get the dev specific number of flows that needed to be supported. */
520         if (bnxt_ulp_cntxt_dev_id_get(bp->ulp_ctx, &dev_id)) {
521                 BNXT_TF_DBG(ERR, "Invalid device id\n");
522                 return -EINVAL;
523         }
524
525         dparms = bnxt_ulp_device_params_get(dev_id);
526         if (!dparms) {
527                 BNXT_TF_DBG(ERR, "could not fetch the device params\n");
528                 return -ENODEV;
529         }
530
531         if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
532                 return -EINVAL;
533         if (mtype != BNXT_ULP_FLOW_MEM_TYPE_EXT) {
534                 BNXT_TF_DBG(INFO, "Table Scope free is not required\n");
535                 return 0;
536         }
537
538         rc = bnxt_ulp_cntxt_tbl_scope_id_get(ulp_ctx, &params.tbl_scope_id);
539         if (rc) {
540                 BNXT_TF_DBG(ERR, "Failed to get the table scope id\n");
541                 return -EINVAL;
542         }
543
544         rc = tf_free_tbl_scope(tfp, &params);
545         if (rc) {
546                 BNXT_TF_DBG(ERR, "Unable to free table scope\n");
547                 return -EINVAL;
548         }
549         return rc;
550 }
551
552 /* The function to free and deinit the ulp context data. */
553 static int32_t
554 ulp_ctx_deinit(struct bnxt *bp,
555                struct bnxt_ulp_session_state *session)
556 {
557         /* close the tf session */
558         ulp_ctx_session_close(bp, session);
559
560         /* Free the contents */
561         if (session->cfg_data) {
562                 rte_free(session->cfg_data);
563                 bp->ulp_ctx->cfg_data = NULL;
564                 session->cfg_data = NULL;
565         }
566         return 0;
567 }
568
569 /* The function to allocate and initialize the ulp context data. */
570 static int32_t
571 ulp_ctx_init(struct bnxt *bp,
572              struct bnxt_ulp_session_state *session)
573 {
574         struct bnxt_ulp_data    *ulp_data;
575         int32_t                 rc = 0;
576         enum bnxt_ulp_device_id devid;
577
578         /* Allocate memory to hold ulp context data. */
579         ulp_data = rte_zmalloc("bnxt_ulp_data",
580                                sizeof(struct bnxt_ulp_data), 0);
581         if (!ulp_data) {
582                 BNXT_TF_DBG(ERR, "Failed to allocate memory for ulp data\n");
583                 return -ENOMEM;
584         }
585
586         /* Increment the ulp context data reference count usage. */
587         bp->ulp_ctx->cfg_data = ulp_data;
588         session->cfg_data = ulp_data;
589         ulp_data->ref_cnt++;
590         ulp_data->ulp_flags |= BNXT_ULP_VF_REP_ENABLED;
591
592         rc = bnxt_ulp_devid_get(bp, &devid);
593         if (rc) {
594                 BNXT_TF_DBG(ERR, "Unable to determine device for ULP init.\n");
595                 goto error_deinit;
596         }
597
598         rc = bnxt_ulp_cntxt_dev_id_set(bp->ulp_ctx, devid);
599         if (rc) {
600                 BNXT_TF_DBG(ERR, "Unable to set device for ULP init.\n");
601                 goto error_deinit;
602         }
603
604         /* Open the ulp session. */
605         rc = ulp_ctx_session_open(bp, session);
606         if (rc)
607                 goto error_deinit;
608
609         ulp_tun_tbl_init(ulp_data->tun_tbl);
610
611         bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp);
612         return rc;
613
614 error_deinit:
615         session->session_opened = 1;
616         (void)ulp_ctx_deinit(bp, session);
617         return rc;
618 }
619
620 /* The function to initialize ulp dparms with devargs */
621 static int32_t
622 ulp_dparms_init(struct bnxt *bp, struct bnxt_ulp_context *ulp_ctx)
623 {
624         struct bnxt_ulp_device_params *dparms;
625         uint32_t dev_id;
626
627         if (!bp->max_num_kflows) {
628                 /* Defaults to Internal */
629                 bnxt_ulp_cntxt_mem_type_set(ulp_ctx,
630                                             BNXT_ULP_FLOW_MEM_TYPE_INT);
631                 return 0;
632         }
633
634         /* The max_num_kflows were set, so move to external */
635         if (bnxt_ulp_cntxt_mem_type_set(ulp_ctx, BNXT_ULP_FLOW_MEM_TYPE_EXT))
636                 return -EINVAL;
637
638         if (bnxt_ulp_cntxt_dev_id_get(ulp_ctx, &dev_id)) {
639                 BNXT_TF_DBG(DEBUG, "Failed to get device id\n");
640                 return -EINVAL;
641         }
642
643         dparms = bnxt_ulp_device_params_get(dev_id);
644         if (!dparms) {
645                 BNXT_TF_DBG(DEBUG, "Failed to get device parms\n");
646                 return -EINVAL;
647         }
648
649         /* num_flows = max_num_kflows * 1024 */
650         dparms->ext_flow_db_num_entries = bp->max_num_kflows * 1024;
651         /* GFID =  2 * num_flows */
652         dparms->mark_db_gfid_entries = dparms->ext_flow_db_num_entries * 2;
653         BNXT_TF_DBG(DEBUG, "Set the number of flows = %"PRIu64"\n",
654                     dparms->ext_flow_db_num_entries);
655
656         return 0;
657 }
658
659 /* The function to initialize bp flags with truflow features */
660 static int32_t
661 ulp_dparms_dev_port_intf_update(struct bnxt *bp,
662                                 struct bnxt_ulp_context *ulp_ctx)
663 {
664         enum bnxt_ulp_flow_mem_type mtype;
665
666         if (bnxt_ulp_cntxt_mem_type_get(ulp_ctx, &mtype))
667                 return -EINVAL;
668         /* Update the bp flag with gfid flag */
669         if (mtype == BNXT_ULP_FLOW_MEM_TYPE_EXT)
670                 bp->flags |= BNXT_FLAG_GFID_ENABLE;
671
672         return 0;
673 }
674
675 static int32_t
676 ulp_ctx_attach(struct bnxt *bp,
677                struct bnxt_ulp_session_state *session)
678 {
679         int32_t rc = 0;
680
681         /* Increment the ulp context data reference count usage. */
682         bp->ulp_ctx->cfg_data = session->cfg_data;
683         bp->ulp_ctx->cfg_data->ref_cnt++;
684
685         /* update the session details in bnxt tfp */
686         bp->tfp.session = session->g_tfp->session;
687
688         /* Create a TF Client */
689         rc = ulp_ctx_session_open(bp, session);
690         if (rc) {
691                 PMD_DRV_LOG(ERR, "Failed to open ctxt session, rc:%d\n", rc);
692                 bp->tfp.session = NULL;
693                 return rc;
694         }
695
696         bnxt_ulp_cntxt_tfp_set(bp->ulp_ctx, &bp->tfp);
697         return rc;
698 }
699
700 static void
701 ulp_ctx_detach(struct bnxt *bp)
702 {
703         if (bp->tfp.session) {
704                 tf_close_session(&bp->tfp);
705                 bp->tfp.session = NULL;
706         }
707 }
708
709 /*
710  * Initialize the state of an ULP session.
711  * If the state of an ULP session is not initialized, set it's state to
712  * initialized. If the state is already initialized, do nothing.
713  */
714 static void
715 ulp_context_initialized(struct bnxt_ulp_session_state *session, bool *init)
716 {
717         pthread_mutex_lock(&session->bnxt_ulp_mutex);
718
719         if (!session->bnxt_ulp_init) {
720                 session->bnxt_ulp_init = true;
721                 *init = false;
722         } else {
723                 *init = true;
724         }
725
726         pthread_mutex_unlock(&session->bnxt_ulp_mutex);
727 }
728
729 /*
730  * Check if an ULP session is already allocated for a specific PCI
731  * domain & bus. If it is already allocated simply return the session
732  * pointer, otherwise allocate a new session.
733  */
734 static struct bnxt_ulp_session_state *
735 ulp_get_session(struct rte_pci_addr *pci_addr)
736 {
737         struct bnxt_ulp_session_state *session;
738
739         STAILQ_FOREACH(session, &bnxt_ulp_session_list, next) {
740                 if (session->pci_info.domain == pci_addr->domain &&
741                     session->pci_info.bus == pci_addr->bus) {
742                         return session;
743                 }
744         }
745         return NULL;
746 }
747
748 /*
749  * Allocate and Initialize an ULP session and set it's state to INITIALIZED.
750  * If it's already initialized simply return the already existing session.
751  */
752 static struct bnxt_ulp_session_state *
753 ulp_session_init(struct bnxt *bp,
754                  bool *init)
755 {
756         struct rte_pci_device           *pci_dev;
757         struct rte_pci_addr             *pci_addr;
758         struct bnxt_ulp_session_state   *session;
759         int rc = 0;
760
761         if (!bp)
762                 return NULL;
763
764         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
765         pci_addr = &pci_dev->addr;
766
767         pthread_mutex_lock(&bnxt_ulp_global_mutex);
768
769         session = ulp_get_session(pci_addr);
770         if (!session) {
771                 /* Not Found the session  Allocate a new one */
772                 session = rte_zmalloc("bnxt_ulp_session",
773                                       sizeof(struct bnxt_ulp_session_state),
774                                       0);
775                 if (!session) {
776                         BNXT_TF_DBG(ERR,
777                                     "Allocation failed for bnxt_ulp_session\n");
778                         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
779                         return NULL;
780
781                 } else {
782                         /* Add it to the queue */
783                         session->pci_info.domain = pci_addr->domain;
784                         session->pci_info.bus = pci_addr->bus;
785                         rc = pthread_mutex_init(&session->bnxt_ulp_mutex, NULL);
786                         if (rc) {
787                                 BNXT_TF_DBG(ERR, "mutex create failed\n");
788                                 pthread_mutex_unlock(&bnxt_ulp_global_mutex);
789                                 return NULL;
790                         }
791                         STAILQ_INSERT_TAIL(&bnxt_ulp_session_list,
792                                            session, next);
793                 }
794         }
795         ulp_context_initialized(session, init);
796         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
797         return session;
798 }
799
800 /*
801  * When a device is closed, remove it's associated session from the global
802  * session list.
803  */
804 static void
805 ulp_session_deinit(struct bnxt_ulp_session_state *session)
806 {
807         if (!session)
808                 return;
809
810         if (!session->cfg_data) {
811                 pthread_mutex_lock(&bnxt_ulp_global_mutex);
812                 STAILQ_REMOVE(&bnxt_ulp_session_list, session,
813                               bnxt_ulp_session_state, next);
814                 pthread_mutex_destroy(&session->bnxt_ulp_mutex);
815                 rte_free(session);
816                 pthread_mutex_unlock(&bnxt_ulp_global_mutex);
817         }
818 }
819
820 /*
821  * Internal api to enable NAT feature.
822  * Set set_flag to 1 to set the value or zero to reset the value.
823  * returns 0 on success.
824  */
825 static int32_t
826 bnxt_ulp_global_cfg_update(struct bnxt *bp,
827                            enum tf_dir dir,
828                            enum tf_global_config_type type,
829                            uint32_t offset,
830                            uint32_t value,
831                            uint32_t set_flag)
832 {
833         uint32_t global_cfg = 0;
834         int rc;
835         struct tf_global_cfg_parms parms = { 0 };
836
837         /* Initialize the params */
838         parms.dir = dir,
839         parms.type = type,
840         parms.offset = offset,
841         parms.config = (uint8_t *)&global_cfg,
842         parms.config_sz_in_bytes = sizeof(global_cfg);
843
844         rc = tf_get_global_cfg(&bp->tfp, &parms);
845         if (rc) {
846                 BNXT_TF_DBG(ERR, "Failed to get global cfg 0x%x rc:%d\n",
847                             type, rc);
848                 return rc;
849         }
850
851         if (set_flag)
852                 global_cfg |= value;
853         else
854                 global_cfg &= ~value;
855
856         /* SET the register RE_CFA_REG_ACT_TECT */
857         rc = tf_set_global_cfg(&bp->tfp, &parms);
858         if (rc) {
859                 BNXT_TF_DBG(ERR, "Failed to set global cfg 0x%x rc:%d\n",
860                             type, rc);
861                 return rc;
862         }
863         return rc;
864 }
865
866 /* Internal function to delete all the flows belonging to the given port */
867 static void
868 bnxt_ulp_flush_port_flows(struct bnxt *bp)
869 {
870         uint16_t func_id;
871
872         /* it is assumed that port is either TVF or PF */
873         if (ulp_port_db_port_func_id_get(bp->ulp_ctx,
874                                          bp->eth_dev->data->port_id,
875                                          &func_id)) {
876                 BNXT_TF_DBG(ERR, "Invalid argument\n");
877                 return;
878         }
879         (void)ulp_flow_db_function_flow_flush(bp->ulp_ctx, func_id);
880 }
881
882 /* Internal function to delete the VFR default flows */
883 static void
884 bnxt_ulp_destroy_vfr_default_rules(struct bnxt *bp, bool global)
885 {
886         struct bnxt_ulp_vfr_rule_info *info;
887         uint16_t port_id;
888         struct rte_eth_dev *vfr_eth_dev;
889         struct bnxt_representor *vfr_bp;
890
891         if (!BNXT_TRUFLOW_EN(bp) || BNXT_ETH_DEV_IS_REPRESENTOR(bp->eth_dev))
892                 return;
893
894         if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
895                 return;
896
897         /* Delete default rules for all ports */
898         for (port_id = 0; port_id < RTE_MAX_ETHPORTS; port_id++) {
899                 info = &bp->ulp_ctx->cfg_data->vfr_rule_info[port_id];
900                 if (!info->valid)
901                         continue;
902
903                 if (!global && info->parent_port_id !=
904                     bp->eth_dev->data->port_id)
905                         continue;
906
907                 /* Destroy the flows */
908                 ulp_default_flow_destroy(bp->eth_dev, info->vfr_flow_id);
909                 /* Clean up the tx action pointer */
910                 vfr_eth_dev = &rte_eth_devices[port_id];
911                 if (vfr_eth_dev) {
912                         vfr_bp = vfr_eth_dev->data->dev_private;
913                         vfr_bp->vfr_tx_cfa_action = 0;
914                 }
915                 memset(info, 0, sizeof(struct bnxt_ulp_vfr_rule_info));
916         }
917 }
918
919 /*
920  * When a port is deinit'ed by dpdk. This function is called
921  * and this function clears the ULP context and rest of the
922  * infrastructure associated with it.
923  */
924 static void
925 bnxt_ulp_deinit(struct bnxt *bp,
926                 struct bnxt_ulp_session_state *session)
927 {
928         if (!bp->ulp_ctx || !bp->ulp_ctx->cfg_data)
929                 return;
930
931         /* clean up default flows */
932         bnxt_ulp_destroy_df_rules(bp, true);
933
934         /* clean up default VFR flows */
935         bnxt_ulp_destroy_vfr_default_rules(bp, true);
936
937         /* clean up regular flows */
938         ulp_flow_db_flush_flows(bp->ulp_ctx, BNXT_ULP_FDB_TYPE_REGULAR);
939
940         /* cleanup the eem table scope */
941         ulp_eem_tbl_scope_deinit(bp, bp->ulp_ctx);
942
943         /* cleanup the flow database */
944         ulp_flow_db_deinit(bp->ulp_ctx);
945
946         /* Delete the Mark database */
947         ulp_mark_db_deinit(bp->ulp_ctx);
948
949         /* cleanup the ulp mapper */
950         ulp_mapper_deinit(bp->ulp_ctx);
951
952         /* Delete the Flow Counter Manager */
953         ulp_fc_mgr_deinit(bp->ulp_ctx);
954
955         /* Delete the Port database */
956         ulp_port_db_deinit(bp->ulp_ctx);
957
958         /* Disable NAT feature */
959         (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
960                                          TF_TUNNEL_ENCAP_NAT,
961                                          BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
962
963         (void)bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
964                                          TF_TUNNEL_ENCAP_NAT,
965                                          BNXT_ULP_NAT_OUTER_MOST_FLAGS, 0);
966
967         /* free the flow db lock */
968         pthread_mutex_destroy(&bp->ulp_ctx->cfg_data->flow_db_lock);
969
970         /* Delete the ulp context and tf session and free the ulp context */
971         ulp_ctx_deinit(bp, session);
972         BNXT_TF_DBG(DEBUG, "ulp ctx has been deinitialized\n");
973 }
974
975 /*
976  * When a port is initialized by dpdk. This functions is called
977  * and this function initializes the ULP context and rest of the
978  * infrastructure associated with it.
979  */
980 static int32_t
981 bnxt_ulp_init(struct bnxt *bp,
982               struct bnxt_ulp_session_state *session)
983 {
984         int rc;
985
986         /* Allocate and Initialize the ulp context. */
987         rc = ulp_ctx_init(bp, session);
988         if (rc) {
989                 BNXT_TF_DBG(ERR, "Failed to create the ulp context\n");
990                 goto jump_to_error;
991         }
992
993         rc = pthread_mutex_init(&bp->ulp_ctx->cfg_data->flow_db_lock, NULL);
994         if (rc) {
995                 BNXT_TF_DBG(ERR, "Unable to initialize flow db lock\n");
996                 goto jump_to_error;
997         }
998
999         /* Initialize ulp dparms with values devargs passed */
1000         rc = ulp_dparms_init(bp, bp->ulp_ctx);
1001         if (rc) {
1002                 BNXT_TF_DBG(ERR, "Failed to initialize the dparms\n");
1003                 goto jump_to_error;
1004         }
1005
1006         /* create the port database */
1007         rc = ulp_port_db_init(bp->ulp_ctx, bp->port_cnt);
1008         if (rc) {
1009                 BNXT_TF_DBG(ERR, "Failed to create the port database\n");
1010                 goto jump_to_error;
1011         }
1012
1013         /* Create the Mark database. */
1014         rc = ulp_mark_db_init(bp->ulp_ctx);
1015         if (rc) {
1016                 BNXT_TF_DBG(ERR, "Failed to create the mark database\n");
1017                 goto jump_to_error;
1018         }
1019
1020         /* Create the flow database. */
1021         rc = ulp_flow_db_init(bp->ulp_ctx);
1022         if (rc) {
1023                 BNXT_TF_DBG(ERR, "Failed to create the flow database\n");
1024                 goto jump_to_error;
1025         }
1026
1027         /* Create the eem table scope. */
1028         rc = ulp_eem_tbl_scope_init(bp);
1029         if (rc) {
1030                 BNXT_TF_DBG(ERR, "Failed to create the eem scope table\n");
1031                 goto jump_to_error;
1032         }
1033
1034         rc = ulp_mapper_init(bp->ulp_ctx);
1035         if (rc) {
1036                 BNXT_TF_DBG(ERR, "Failed to initialize ulp mapper\n");
1037                 goto jump_to_error;
1038         }
1039
1040         rc = ulp_fc_mgr_init(bp->ulp_ctx);
1041         if (rc) {
1042                 BNXT_TF_DBG(ERR, "Failed to initialize ulp flow counter mgr\n");
1043                 goto jump_to_error;
1044         }
1045
1046         /*
1047          * Enable NAT feature. Set the global configuration register
1048          * Tunnel encap to enable NAT with the reuse of existing inner
1049          * L2 header smac and dmac
1050          */
1051         rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_RX, TF_TUNNEL_ENCAP,
1052                                         TF_TUNNEL_ENCAP_NAT,
1053                                         BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
1054         if (rc) {
1055                 BNXT_TF_DBG(ERR, "Failed to set rx global configuration\n");
1056                 goto jump_to_error;
1057         }
1058
1059         rc = bnxt_ulp_global_cfg_update(bp, TF_DIR_TX, TF_TUNNEL_ENCAP,
1060                                         TF_TUNNEL_ENCAP_NAT,
1061                                         BNXT_ULP_NAT_OUTER_MOST_FLAGS, 1);
1062         if (rc) {
1063                 BNXT_TF_DBG(ERR, "Failed to set tx global configuration\n");
1064                 goto jump_to_error;
1065         }
1066         BNXT_TF_DBG(DEBUG, "ulp ctx has been initialized\n");
1067         return rc;
1068
1069 jump_to_error:
1070         bnxt_ulp_deinit(bp, session);
1071         return rc;
1072 }
1073
1074 /*
1075  * When a port is initialized by dpdk. This functions sets up
1076  * the port specific details.
1077  */
1078 int32_t
1079 bnxt_ulp_port_init(struct bnxt *bp)
1080 {
1081         struct bnxt_ulp_session_state *session;
1082         bool initialized;
1083         int32_t rc = 0;
1084
1085         if (!bp || !BNXT_TRUFLOW_EN(bp))
1086                 return rc;
1087
1088         if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1089                 BNXT_TF_DBG(ERR,
1090                             "Skip ulp init for port: %d, not a TVF or PF\n",
1091                         bp->eth_dev->data->port_id);
1092                 return rc;
1093         }
1094
1095         if (bp->ulp_ctx) {
1096                 BNXT_TF_DBG(DEBUG, "ulp ctx already allocated\n");
1097                 return rc;
1098         }
1099
1100         bp->ulp_ctx = rte_zmalloc("bnxt_ulp_ctx",
1101                                   sizeof(struct bnxt_ulp_context), 0);
1102         if (!bp->ulp_ctx) {
1103                 BNXT_TF_DBG(ERR, "Failed to allocate ulp ctx\n");
1104                 return -ENOMEM;
1105         }
1106
1107         /*
1108          * Multiple uplink ports can be associated with a single vswitch.
1109          * Make sure only the port that is started first will initialize
1110          * the TF session.
1111          */
1112         session = ulp_session_init(bp, &initialized);
1113         if (!session) {
1114                 BNXT_TF_DBG(ERR, "Failed to initialize the tf session\n");
1115                 rc = -EIO;
1116                 goto jump_to_error;
1117         }
1118
1119         if (initialized) {
1120                 /*
1121                  * If ULP is already initialized for a specific domain then
1122                  * simply assign the ulp context to this rte_eth_dev.
1123                  */
1124                 rc = ulp_ctx_attach(bp, session);
1125                 if (rc) {
1126                         BNXT_TF_DBG(ERR, "Failed to attach the ulp context\n");
1127                         goto jump_to_error;
1128                 }
1129         } else {
1130                 rc = bnxt_ulp_init(bp, session);
1131                 if (rc) {
1132                         BNXT_TF_DBG(ERR, "Failed to initialize the ulp init\n");
1133                         goto jump_to_error;
1134                 }
1135         }
1136
1137         /* Update bnxt driver flags */
1138         rc = ulp_dparms_dev_port_intf_update(bp, bp->ulp_ctx);
1139         if (rc) {
1140                 BNXT_TF_DBG(ERR, "Failed to update driver flags\n");
1141                 goto jump_to_error;
1142         }
1143
1144         /* update the port database for the given interface */
1145         rc = ulp_port_db_dev_port_intf_update(bp->ulp_ctx, bp->eth_dev);
1146         if (rc) {
1147                 BNXT_TF_DBG(ERR, "Failed to update port database\n");
1148                 goto jump_to_error;
1149         }
1150         /* create the default rules */
1151         rc = bnxt_ulp_create_df_rules(bp);
1152         if (rc) {
1153                 BNXT_TF_DBG(ERR, "Failed to create default flow\n");
1154                 goto jump_to_error;
1155         }
1156
1157         if (BNXT_ACCUM_STATS_EN(bp))
1158                 bp->ulp_ctx->cfg_data->accum_stats = true;
1159
1160         BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port init\n",
1161                     bp->eth_dev->data->port_id);
1162         return rc;
1163
1164 jump_to_error:
1165         bnxt_ulp_port_deinit(bp);
1166         return rc;
1167 }
1168
1169 /*
1170  * When a port is de-initialized by dpdk. This functions clears up
1171  * the port specific details.
1172  */
1173 void
1174 bnxt_ulp_port_deinit(struct bnxt *bp)
1175 {
1176         struct bnxt_ulp_session_state *session;
1177         struct rte_pci_device *pci_dev;
1178         struct rte_pci_addr *pci_addr;
1179
1180         if (!BNXT_TRUFLOW_EN(bp))
1181                 return;
1182
1183         if (!BNXT_PF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
1184                 BNXT_TF_DBG(ERR,
1185                             "Skip ULP deinit port:%d, not a TVF or PF\n",
1186                             bp->eth_dev->data->port_id);
1187                 return;
1188         }
1189
1190         if (!bp->ulp_ctx) {
1191                 BNXT_TF_DBG(DEBUG, "ulp ctx already de-allocated\n");
1192                 return;
1193         }
1194
1195         BNXT_TF_DBG(DEBUG, "BNXT Port:%d ULP port deinit\n",
1196                     bp->eth_dev->data->port_id);
1197
1198         /* Get the session details  */
1199         pci_dev = RTE_DEV_TO_PCI(bp->eth_dev->device);
1200         pci_addr = &pci_dev->addr;
1201         pthread_mutex_lock(&bnxt_ulp_global_mutex);
1202         session = ulp_get_session(pci_addr);
1203         pthread_mutex_unlock(&bnxt_ulp_global_mutex);
1204
1205         /* session not found then just exit */
1206         if (!session) {
1207                 /* Free the ulp context */
1208                 rte_free(bp->ulp_ctx);
1209                 bp->ulp_ctx = NULL;
1210                 return;
1211         }
1212
1213         /* Check the reference count to deinit or deattach*/
1214         if (bp->ulp_ctx->cfg_data && bp->ulp_ctx->cfg_data->ref_cnt) {
1215                 bp->ulp_ctx->cfg_data->ref_cnt--;
1216                 if (bp->ulp_ctx->cfg_data->ref_cnt) {
1217                         /* free the port details */
1218                         /* Free the default flow rule associated to this port */
1219                         bnxt_ulp_destroy_df_rules(bp, false);
1220                         bnxt_ulp_destroy_vfr_default_rules(bp, false);
1221
1222                         /* free flows associated with this port */
1223                         bnxt_ulp_flush_port_flows(bp);
1224
1225                         /* close the session associated with this port */
1226                         ulp_ctx_detach(bp);
1227                 } else {
1228                         /* Perform ulp ctx deinit */
1229                         bnxt_ulp_deinit(bp, session);
1230                 }
1231         }
1232
1233         /* clean up the session */
1234         ulp_session_deinit(session);
1235
1236         /* Free the ulp context */
1237         rte_free(bp->ulp_ctx);
1238         bp->ulp_ctx = NULL;
1239 }
1240
1241 /* Below are the access functions to access internal data of ulp context. */
1242 /* Function to set the Mark DB into the context */
1243 int32_t
1244 bnxt_ulp_cntxt_ptr2_mark_db_set(struct bnxt_ulp_context *ulp_ctx,
1245                                 struct bnxt_ulp_mark_tbl *mark_tbl)
1246 {
1247         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1248                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1249                 return -EINVAL;
1250         }
1251
1252         ulp_ctx->cfg_data->mark_tbl = mark_tbl;
1253
1254         return 0;
1255 }
1256
1257 /* Function to retrieve the Mark DB from the context. */
1258 struct bnxt_ulp_mark_tbl *
1259 bnxt_ulp_cntxt_ptr2_mark_db_get(struct bnxt_ulp_context *ulp_ctx)
1260 {
1261         if (!ulp_ctx || !ulp_ctx->cfg_data)
1262                 return NULL;
1263
1264         return ulp_ctx->cfg_data->mark_tbl;
1265 }
1266
1267 /* Function to set the device id of the hardware. */
1268 int32_t
1269 bnxt_ulp_cntxt_dev_id_set(struct bnxt_ulp_context *ulp_ctx,
1270                           uint32_t dev_id)
1271 {
1272         if (ulp_ctx && ulp_ctx->cfg_data) {
1273                 ulp_ctx->cfg_data->dev_id = dev_id;
1274                 return 0;
1275         }
1276
1277         return -EINVAL;
1278 }
1279
1280 /* Function to get the device id of the hardware. */
1281 int32_t
1282 bnxt_ulp_cntxt_dev_id_get(struct bnxt_ulp_context *ulp_ctx,
1283                           uint32_t *dev_id)
1284 {
1285         if (ulp_ctx && ulp_ctx->cfg_data) {
1286                 *dev_id = ulp_ctx->cfg_data->dev_id;
1287                 return 0;
1288         }
1289
1290         BNXT_TF_DBG(ERR, "Failed to read dev_id from ulp ctxt\n");
1291         return -EINVAL;
1292 }
1293
1294 int32_t
1295 bnxt_ulp_cntxt_mem_type_set(struct bnxt_ulp_context *ulp_ctx,
1296                             enum bnxt_ulp_flow_mem_type mem_type)
1297 {
1298         if (ulp_ctx && ulp_ctx->cfg_data) {
1299                 ulp_ctx->cfg_data->mem_type = mem_type;
1300                 return 0;
1301         }
1302         BNXT_TF_DBG(ERR, "Failed to write mem_type in ulp ctxt\n");
1303         return -EINVAL;
1304 }
1305
1306 int32_t
1307 bnxt_ulp_cntxt_mem_type_get(struct bnxt_ulp_context *ulp_ctx,
1308                             enum bnxt_ulp_flow_mem_type *mem_type)
1309 {
1310         if (ulp_ctx && ulp_ctx->cfg_data) {
1311                 *mem_type = ulp_ctx->cfg_data->mem_type;
1312                 return 0;
1313         }
1314         BNXT_TF_DBG(ERR, "Failed to read mem_type in ulp ctxt\n");
1315         return -EINVAL;
1316 }
1317
1318 /* Function to get the table scope id of the EEM table. */
1319 int32_t
1320 bnxt_ulp_cntxt_tbl_scope_id_get(struct bnxt_ulp_context *ulp_ctx,
1321                                 uint32_t *tbl_scope_id)
1322 {
1323         if (ulp_ctx && ulp_ctx->cfg_data) {
1324                 *tbl_scope_id = ulp_ctx->cfg_data->tbl_scope_id;
1325                 return 0;
1326         }
1327
1328         return -EINVAL;
1329 }
1330
1331 /* Function to set the table scope id of the EEM table. */
1332 int32_t
1333 bnxt_ulp_cntxt_tbl_scope_id_set(struct bnxt_ulp_context *ulp_ctx,
1334                                 uint32_t tbl_scope_id)
1335 {
1336         if (ulp_ctx && ulp_ctx->cfg_data) {
1337                 ulp_ctx->cfg_data->tbl_scope_id = tbl_scope_id;
1338                 return 0;
1339         }
1340
1341         return -EINVAL;
1342 }
1343
1344 /* Function to set the tfp session details from the ulp context. */
1345 int32_t
1346 bnxt_ulp_cntxt_tfp_set(struct bnxt_ulp_context *ulp, struct tf *tfp)
1347 {
1348         if (!ulp) {
1349                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1350                 return -EINVAL;
1351         }
1352
1353         ulp->g_tfp = tfp;
1354         return 0;
1355 }
1356
1357 /* Function to get the tfp session details from the ulp context. */
1358 struct tf *
1359 bnxt_ulp_cntxt_tfp_get(struct bnxt_ulp_context *ulp)
1360 {
1361         if (!ulp) {
1362                 BNXT_TF_DBG(ERR, "Invalid arguments\n");
1363                 return NULL;
1364         }
1365         return ulp->g_tfp;
1366 }
1367
1368 /*
1369  * Get the device table entry based on the device id.
1370  *
1371  * dev_id [in] The device id of the hardware
1372  *
1373  * Returns the pointer to the device parameters.
1374  */
1375 struct bnxt_ulp_device_params *
1376 bnxt_ulp_device_params_get(uint32_t dev_id)
1377 {
1378         if (dev_id < BNXT_ULP_MAX_NUM_DEVICES)
1379                 return &ulp_device_params[dev_id];
1380         return NULL;
1381 }
1382
1383 /* Function to set the flow database to the ulp context. */
1384 int32_t
1385 bnxt_ulp_cntxt_ptr2_flow_db_set(struct bnxt_ulp_context *ulp_ctx,
1386                                 struct bnxt_ulp_flow_db *flow_db)
1387 {
1388         if (!ulp_ctx || !ulp_ctx->cfg_data)
1389                 return -EINVAL;
1390
1391         ulp_ctx->cfg_data->flow_db = flow_db;
1392         return 0;
1393 }
1394
1395 /* Function to get the flow database from the ulp context. */
1396 struct bnxt_ulp_flow_db *
1397 bnxt_ulp_cntxt_ptr2_flow_db_get(struct bnxt_ulp_context *ulp_ctx)
1398 {
1399         if (!ulp_ctx || !ulp_ctx->cfg_data)
1400                 return NULL;
1401
1402         return ulp_ctx->cfg_data->flow_db;
1403 }
1404
1405 /* Function to get the tunnel cache table info from the ulp context. */
1406 struct bnxt_tun_cache_entry *
1407 bnxt_ulp_cntxt_ptr2_tun_tbl_get(struct bnxt_ulp_context *ulp_ctx)
1408 {
1409         if (!ulp_ctx || !ulp_ctx->cfg_data)
1410                 return NULL;
1411
1412         return ulp_ctx->cfg_data->tun_tbl;
1413 }
1414
1415 /* Function to get the ulp context from eth device. */
1416 struct bnxt_ulp_context *
1417 bnxt_ulp_eth_dev_ptr2_cntxt_get(struct rte_eth_dev      *dev)
1418 {
1419         struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
1420
1421         if (BNXT_ETH_DEV_IS_REPRESENTOR(dev)) {
1422                 struct bnxt_representor *vfr = dev->data->dev_private;
1423
1424                 bp = vfr->parent_dev->data->dev_private;
1425         }
1426
1427         if (!bp) {
1428                 BNXT_TF_DBG(ERR, "Bnxt private data is not initialized\n");
1429                 return NULL;
1430         }
1431         return bp->ulp_ctx;
1432 }
1433
1434 int32_t
1435 bnxt_ulp_cntxt_ptr2_mapper_data_set(struct bnxt_ulp_context *ulp_ctx,
1436                                     void *mapper_data)
1437 {
1438         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1439                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1440                 return -EINVAL;
1441         }
1442
1443         ulp_ctx->cfg_data->mapper_data = mapper_data;
1444         return 0;
1445 }
1446
1447 void *
1448 bnxt_ulp_cntxt_ptr2_mapper_data_get(struct bnxt_ulp_context *ulp_ctx)
1449 {
1450         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1451                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1452                 return NULL;
1453         }
1454
1455         return ulp_ctx->cfg_data->mapper_data;
1456 }
1457
1458 /* Function to set the port database to the ulp context. */
1459 int32_t
1460 bnxt_ulp_cntxt_ptr2_port_db_set(struct bnxt_ulp_context *ulp_ctx,
1461                                 struct bnxt_ulp_port_db *port_db)
1462 {
1463         if (!ulp_ctx || !ulp_ctx->cfg_data)
1464                 return -EINVAL;
1465
1466         ulp_ctx->cfg_data->port_db = port_db;
1467         return 0;
1468 }
1469
1470 /* Function to get the port database from the ulp context. */
1471 struct bnxt_ulp_port_db *
1472 bnxt_ulp_cntxt_ptr2_port_db_get(struct bnxt_ulp_context *ulp_ctx)
1473 {
1474         if (!ulp_ctx || !ulp_ctx->cfg_data)
1475                 return NULL;
1476
1477         return ulp_ctx->cfg_data->port_db;
1478 }
1479
1480 /* Function to set the flow counter info into the context */
1481 int32_t
1482 bnxt_ulp_cntxt_ptr2_fc_info_set(struct bnxt_ulp_context *ulp_ctx,
1483                                 struct bnxt_ulp_fc_info *ulp_fc_info)
1484 {
1485         if (!ulp_ctx || !ulp_ctx->cfg_data) {
1486                 BNXT_TF_DBG(ERR, "Invalid ulp context data\n");
1487                 return -EINVAL;
1488         }
1489
1490         ulp_ctx->cfg_data->fc_info = ulp_fc_info;
1491
1492         return 0;
1493 }
1494
1495 /* Function to retrieve the flow counter info from the context. */
1496 struct bnxt_ulp_fc_info *
1497 bnxt_ulp_cntxt_ptr2_fc_info_get(struct bnxt_ulp_context *ulp_ctx)
1498 {
1499         if (!ulp_ctx || !ulp_ctx->cfg_data)
1500                 return NULL;
1501
1502         return ulp_ctx->cfg_data->fc_info;
1503 }
1504
1505 /* Function to get the ulp flags from the ulp context. */
1506 int32_t
1507 bnxt_ulp_cntxt_ptr2_ulp_flags_get(struct bnxt_ulp_context *ulp_ctx,
1508                                   uint32_t *flags)
1509 {
1510         if (!ulp_ctx || !ulp_ctx->cfg_data)
1511                 return -1;
1512
1513         *flags =  ulp_ctx->cfg_data->ulp_flags;
1514         return 0;
1515 }
1516
1517 /* Function to get the ulp vfr info from the ulp context. */
1518 struct bnxt_ulp_vfr_rule_info*
1519 bnxt_ulp_cntxt_ptr2_ulp_vfr_info_get(struct bnxt_ulp_context *ulp_ctx,
1520                                      uint32_t port_id)
1521 {
1522         if (!ulp_ctx || !ulp_ctx->cfg_data || port_id >= RTE_MAX_ETHPORTS)
1523                 return NULL;
1524
1525         return &ulp_ctx->cfg_data->vfr_rule_info[port_id];
1526 }
1527
1528 /* Function to acquire the flow database lock from the ulp context. */
1529 int32_t
1530 bnxt_ulp_cntxt_acquire_fdb_lock(struct bnxt_ulp_context *ulp_ctx)
1531 {
1532         if (!ulp_ctx || !ulp_ctx->cfg_data)
1533                 return -1;
1534
1535         if (pthread_mutex_lock(&ulp_ctx->cfg_data->flow_db_lock)) {
1536                 BNXT_TF_DBG(ERR, "unable to acquire fdb lock\n");
1537                 return -1;
1538         }
1539         return 0;
1540 }
1541
1542 /* Function to release the flow database lock from the ulp context. */
1543 void
1544 bnxt_ulp_cntxt_release_fdb_lock(struct bnxt_ulp_context *ulp_ctx)
1545 {
1546         if (!ulp_ctx || !ulp_ctx->cfg_data)
1547                 return;
1548
1549         pthread_mutex_unlock(&ulp_ctx->cfg_data->flow_db_lock);
1550 }