net/bnxt: identify duplicate flows
[dpdk.git] / drivers / net / bnxt / tf_ulp / ulp_port_db.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2021 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_malloc.h>
7 #include "bnxt.h"
8 #include "bnxt_vnic.h"
9 #include "bnxt_tf_common.h"
10 #include "ulp_port_db.h"
11
12 static uint32_t
13 ulp_port_db_allocate_ifindex(struct bnxt_ulp_port_db *port_db)
14 {
15         uint32_t idx = 1;
16
17         while (idx < port_db->ulp_intf_list_size &&
18                port_db->ulp_intf_list[idx].type != BNXT_ULP_INTF_TYPE_INVALID)
19                 idx++;
20
21         if (idx >= port_db->ulp_intf_list_size) {
22                 BNXT_TF_DBG(ERR, "Port DB interface list is full\n");
23                 return 0;
24         }
25         return idx;
26 }
27
28 /*
29  * Initialize the port database. Memory is allocated in this
30  * call and assigned to the port database.
31  *
32  * ulp_ctxt [in] Ptr to ulp context
33  *
34  * Returns 0 on success or negative number on failure.
35  */
36 int32_t ulp_port_db_init(struct bnxt_ulp_context *ulp_ctxt, uint8_t port_cnt)
37 {
38         struct bnxt_ulp_port_db *port_db;
39
40         port_db = rte_zmalloc("bnxt_ulp_port_db",
41                               sizeof(struct bnxt_ulp_port_db), 0);
42         if (!port_db) {
43                 BNXT_TF_DBG(ERR,
44                             "Failed to allocate memory for port db\n");
45                 return -ENOMEM;
46         }
47
48         /* Attach the port database to the ulp context. */
49         bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, port_db);
50
51         /* index 0 is not being used hence add 1 to size */
52         port_db->ulp_intf_list_size = BNXT_PORT_DB_MAX_INTF_LIST + 1;
53         /* Allocate the port tables */
54         port_db->ulp_intf_list = rte_zmalloc("bnxt_ulp_port_db_intf_list",
55                                              port_db->ulp_intf_list_size *
56                                              sizeof(struct ulp_interface_info),
57                                              0);
58         if (!port_db->ulp_intf_list) {
59                 BNXT_TF_DBG(ERR,
60                             "Failed to allocate mem for port interface list\n");
61                 goto error_free;
62         }
63
64         /* Allocate the phy port list */
65         port_db->phy_port_list = rte_zmalloc("bnxt_ulp_phy_port_list",
66                                              port_cnt *
67                                              sizeof(struct ulp_phy_port_info),
68                                              0);
69         if (!port_db->phy_port_list) {
70                 BNXT_TF_DBG(ERR,
71                             "Failed to allocate mem for phy port list\n");
72                 goto error_free;
73         }
74         port_db->phy_port_cnt = port_cnt;
75         return 0;
76
77 error_free:
78         ulp_port_db_deinit(ulp_ctxt);
79         return -ENOMEM;
80 }
81
82 /*
83  * Deinitialize the port database. Memory is deallocated in
84  * this call.
85  *
86  * ulp_ctxt [in] Ptr to ulp context
87  *
88  * Returns 0 on success.
89  */
90 int32_t ulp_port_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
91 {
92         struct bnxt_ulp_port_db *port_db;
93
94         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
95         if (!port_db) {
96                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
97                 return -EINVAL;
98         }
99
100         /* Detach the flow database from the ulp context. */
101         bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, NULL);
102
103         /* Free up all the memory. */
104         rte_free(port_db->phy_port_list);
105         rte_free(port_db->ulp_intf_list);
106         rte_free(port_db);
107         return 0;
108 }
109
110 /*
111  * Update the port database.This api is called when the port
112  * details are available during the startup.
113  *
114  * ulp_ctxt [in] Ptr to ulp context
115  * bp [in]. ptr to the device function.
116  *
117  * Returns 0 on success or negative number on failure.
118  */
119 int32_t ulp_port_db_dev_port_intf_update(struct bnxt_ulp_context *ulp_ctxt,
120                                          struct rte_eth_dev *eth_dev)
121 {
122         uint32_t port_id = eth_dev->data->port_id;
123         struct ulp_phy_port_info *port_data;
124         struct bnxt_ulp_port_db *port_db;
125         struct ulp_interface_info *intf;
126         struct ulp_func_if_info *func;
127         uint32_t ifindex;
128         int32_t rc;
129
130         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
131         if (!port_db) {
132                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
133                 return -EINVAL;
134         }
135
136         rc = ulp_port_db_dev_port_to_ulp_index(ulp_ctxt, port_id, &ifindex);
137         if (rc == -ENOENT) {
138                 /* port not found, allocate one */
139                 ifindex = ulp_port_db_allocate_ifindex(port_db);
140                 if (!ifindex)
141                         return -ENOMEM;
142                 port_db->dev_port_list[port_id] = ifindex;
143         } else if (rc == -EINVAL) {
144                 return -EINVAL;
145         }
146
147         /* update the interface details */
148         intf = &port_db->ulp_intf_list[ifindex];
149
150         intf->type = bnxt_get_interface_type(port_id);
151         intf->drv_func_id = bnxt_get_fw_func_id(port_id,
152                                                 BNXT_ULP_INTF_TYPE_INVALID);
153
154         func = &port_db->ulp_func_id_tbl[intf->drv_func_id];
155         if (!func->func_valid) {
156                 func->func_svif = bnxt_get_svif(port_id, true,
157                                                 BNXT_ULP_INTF_TYPE_INVALID);
158                 func->func_spif = bnxt_get_phy_port_id(port_id);
159                 func->func_parif =
160                         bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
161                 func->func_vnic =
162                         bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_INVALID);
163                 func->phy_port_id = bnxt_get_phy_port_id(port_id);
164                 func->func_valid = true;
165                 func->ifindex = ifindex;
166         }
167
168         if (intf->type == BNXT_ULP_INTF_TYPE_VF_REP) {
169                 intf->vf_func_id =
170                         bnxt_get_fw_func_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
171
172                 func = &port_db->ulp_func_id_tbl[intf->vf_func_id];
173                 func->func_svif =
174                         bnxt_get_svif(port_id, true, BNXT_ULP_INTF_TYPE_VF_REP);
175                 func->func_spif =
176                         bnxt_get_phy_port_id(port_id);
177                 func->func_parif =
178                         bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
179                 func->func_vnic =
180                         bnxt_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
181                 func->phy_port_id = bnxt_get_phy_port_id(port_id);
182                 func->ifindex = ifindex;
183         }
184
185         port_data = &port_db->phy_port_list[func->phy_port_id];
186         if (!port_data->port_valid) {
187                 port_data->port_svif =
188                         bnxt_get_svif(port_id, false, BNXT_ULP_INTF_TYPE_INVALID);
189                 port_data->port_spif = bnxt_get_phy_port_id(port_id);
190                 port_data->port_parif =
191                         bnxt_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
192                 port_data->port_vport = bnxt_get_vport(port_id);
193                 port_data->port_valid = true;
194         }
195         return 0;
196 }
197
198 /*
199  * Api to get the ulp ifindex for a given device port.
200  *
201  * ulp_ctxt [in] Ptr to ulp context
202  * port_id [in].device port id
203  * ifindex [out] ulp ifindex
204  *
205  * Returns 0 on success or negative number on failure.
206  */
207 int32_t
208 ulp_port_db_dev_port_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
209                                   uint32_t port_id,
210                                   uint32_t *ifindex)
211 {
212         struct bnxt_ulp_port_db *port_db;
213
214         *ifindex = 0;
215         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
216         if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
217                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
218                 return -EINVAL;
219         }
220         if (!port_db->dev_port_list[port_id])
221                 return -ENOENT;
222
223         *ifindex = port_db->dev_port_list[port_id];
224         return 0;
225 }
226
227 /*
228  * Api to get the function id for a given ulp ifindex.
229  *
230  * ulp_ctxt [in] Ptr to ulp context
231  * ifindex [in] ulp ifindex
232  * func_id [out] the function id of the given ifindex.
233  *
234  * Returns 0 on success or negative number on failure.
235  */
236 int32_t
237 ulp_port_db_function_id_get(struct bnxt_ulp_context *ulp_ctxt,
238                             uint32_t ifindex,
239                             uint32_t fid_type,
240                             uint16_t *func_id)
241 {
242         struct bnxt_ulp_port_db *port_db;
243
244         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
245         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
246                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
247                 return -EINVAL;
248         }
249
250         if (fid_type == BNXT_ULP_DRV_FUNC_FID)
251                 *func_id =  port_db->ulp_intf_list[ifindex].drv_func_id;
252         else
253                 *func_id =  port_db->ulp_intf_list[ifindex].vf_func_id;
254
255         return 0;
256 }
257
258 /*
259  * Api to get the svif for a given ulp ifindex.
260  *
261  * ulp_ctxt [in] Ptr to ulp context
262  * ifindex [in] ulp ifindex
263  * svif_type [in] the svif type of the given ifindex.
264  * svif [out] the svif of the given ifindex.
265  *
266  * Returns 0 on success or negative number on failure.
267  */
268 int32_t
269 ulp_port_db_svif_get(struct bnxt_ulp_context *ulp_ctxt,
270                      uint32_t ifindex,
271                      uint32_t svif_type,
272                      uint16_t *svif)
273 {
274         struct bnxt_ulp_port_db *port_db;
275         uint16_t phy_port_id, func_id;
276
277         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
278         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
279                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
280                 return -EINVAL;
281         }
282
283         if (svif_type == BNXT_ULP_DRV_FUNC_SVIF) {
284                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
285                 *svif = port_db->ulp_func_id_tbl[func_id].func_svif;
286         } else if (svif_type == BNXT_ULP_VF_FUNC_SVIF) {
287                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
288                 *svif = port_db->ulp_func_id_tbl[func_id].func_svif;
289         } else {
290                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
291                 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
292                 *svif = port_db->phy_port_list[phy_port_id].port_svif;
293         }
294
295         return 0;
296 }
297
298 /*
299  * Api to get the spif for a given ulp ifindex.
300  *
301  * ulp_ctxt [in] Ptr to ulp context
302  * ifindex [in] ulp ifindex
303  * spif_type [in] the spif type of the given ifindex.
304  * spif [out] the spif of the given ifindex.
305  *
306  * Returns 0 on success or negative number on failure.
307  */
308 int32_t
309 ulp_port_db_spif_get(struct bnxt_ulp_context *ulp_ctxt,
310                      uint32_t ifindex,
311                      uint32_t spif_type,
312                      uint16_t *spif)
313 {
314         struct bnxt_ulp_port_db *port_db;
315         uint16_t phy_port_id, func_id;
316
317         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
318         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
319                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
320                 return -EINVAL;
321         }
322
323         if (spif_type == BNXT_ULP_DRV_FUNC_SPIF) {
324                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
325                 *spif = port_db->ulp_func_id_tbl[func_id].func_spif;
326         } else if (spif_type == BNXT_ULP_VF_FUNC_SPIF) {
327                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
328                 *spif = port_db->ulp_func_id_tbl[func_id].func_spif;
329         } else {
330                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
331                 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
332                 *spif = port_db->phy_port_list[phy_port_id].port_spif;
333         }
334
335         return 0;
336 }
337
338 /*
339  * Api to get the parif for a given ulp ifindex.
340  *
341  * ulp_ctxt [in] Ptr to ulp context
342  * ifindex [in] ulp ifindex
343  * parif_type [in] the parif type of the given ifindex.
344  * parif [out] the parif of the given ifindex.
345  *
346  * Returns 0 on success or negative number on failure.
347  */
348 int32_t
349 ulp_port_db_parif_get(struct bnxt_ulp_context *ulp_ctxt,
350                      uint32_t ifindex,
351                      uint32_t parif_type,
352                      uint16_t *parif)
353 {
354         struct bnxt_ulp_port_db *port_db;
355         uint16_t phy_port_id, func_id;
356
357         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
358         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
359                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
360                 return -EINVAL;
361         }
362         if (parif_type == BNXT_ULP_DRV_FUNC_PARIF) {
363                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
364                 *parif = port_db->ulp_func_id_tbl[func_id].func_parif;
365         } else if (parif_type == BNXT_ULP_VF_FUNC_PARIF) {
366                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
367                 *parif = port_db->ulp_func_id_tbl[func_id].func_parif;
368         } else {
369                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
370                 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
371                 *parif = port_db->phy_port_list[phy_port_id].port_parif;
372         }
373         /* Parif needs to be reset to a free partition */
374         *parif += BNXT_ULP_FREE_PARIF_BASE;
375
376         return 0;
377 }
378
379 /*
380  * Api to get the vnic id for a given ulp ifindex.
381  *
382  * ulp_ctxt [in] Ptr to ulp context
383  * ifindex [in] ulp ifindex
384  * vnic [out] the vnic of the given ifindex.
385  *
386  * Returns 0 on success or negative number on failure.
387  */
388 int32_t
389 ulp_port_db_default_vnic_get(struct bnxt_ulp_context *ulp_ctxt,
390                              uint32_t ifindex,
391                              uint32_t vnic_type,
392                              uint16_t *vnic)
393 {
394         struct bnxt_ulp_port_db *port_db;
395         uint16_t func_id;
396
397         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
398         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
399                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
400                 return -EINVAL;
401         }
402
403         if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) {
404                 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
405                 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
406         } else {
407                 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
408                 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
409         }
410
411         return 0;
412 }
413
414 /*
415  * Api to get the vport id for a given ulp ifindex.
416  *
417  * ulp_ctxt [in] Ptr to ulp context
418  * ifindex [in] ulp ifindex
419  * vport [out] the port of the given ifindex.
420  *
421  * Returns 0 on success or negative number on failure.
422  */
423 int32_t
424 ulp_port_db_vport_get(struct bnxt_ulp_context *ulp_ctxt,
425                       uint32_t ifindex, uint16_t *vport)
426 {
427         struct bnxt_ulp_port_db *port_db;
428         uint16_t phy_port_id, func_id;
429
430         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
431         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
432                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
433                 return -EINVAL;
434         }
435
436         func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
437         phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
438         *vport = port_db->phy_port_list[phy_port_id].port_vport;
439         return 0;
440 }
441
442 /*
443  * Api to get the vport for a given physical port.
444  *
445  * ulp_ctxt [in] Ptr to ulp context
446  * phy_port [in] physical port index
447  * out_port [out] the port of the given physical index
448  *
449  * Returns 0 on success or negative number on failure.
450  */
451 int32_t
452 ulp_port_db_phy_port_vport_get(struct bnxt_ulp_context *ulp_ctxt,
453                                uint32_t phy_port,
454                                uint16_t *out_port)
455 {
456         struct bnxt_ulp_port_db *port_db;
457
458         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
459         if (!port_db || phy_port >= port_db->phy_port_cnt) {
460                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
461                 return -EINVAL;
462         }
463         *out_port = port_db->phy_port_list[phy_port].port_vport;
464         return 0;
465 }
466
467 /*
468  * Api to get the svif for a given physical port.
469  *
470  * ulp_ctxt [in] Ptr to ulp context
471  * phy_port [in] physical port index
472  * svif [out] the svif of the given physical index
473  *
474  * Returns 0 on success or negative number on failure.
475  */
476 int32_t
477 ulp_port_db_phy_port_svif_get(struct bnxt_ulp_context *ulp_ctxt,
478                               uint32_t phy_port,
479                               uint16_t *svif)
480 {
481         struct bnxt_ulp_port_db *port_db;
482
483         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
484         if (!port_db || phy_port >= port_db->phy_port_cnt) {
485                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
486                 return -EINVAL;
487         }
488         *svif = port_db->phy_port_list[phy_port].port_svif;
489         return 0;
490 }
491
492 /*
493  * Api to get the port type for a given ulp ifindex.
494  *
495  * ulp_ctxt [in] Ptr to ulp context
496  * ifindex [in] ulp ifindex
497  *
498  * Returns port type.
499  */
500 enum bnxt_ulp_intf_type
501 ulp_port_db_port_type_get(struct bnxt_ulp_context *ulp_ctxt,
502                           uint32_t ifindex)
503 {
504         struct bnxt_ulp_port_db *port_db;
505
506         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
507         if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
508                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
509                 return BNXT_ULP_INTF_TYPE_INVALID;
510         }
511         return port_db->ulp_intf_list[ifindex].type;
512 }
513
514 /*
515  * Api to get the ulp ifindex for a given function id.
516  *
517  * ulp_ctxt [in] Ptr to ulp context
518  * func_id [in].device func id
519  * ifindex [out] ulp ifindex
520  *
521  * Returns 0 on success or negative number on failure.
522  */
523 int32_t
524 ulp_port_db_dev_func_id_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
525                                      uint32_t func_id, uint32_t *ifindex)
526 {
527         struct bnxt_ulp_port_db *port_db;
528
529         *ifindex = 0;
530         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
531         if (!port_db || func_id >= BNXT_PORT_DB_MAX_FUNC) {
532                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
533                 return -EINVAL;
534         }
535         if (!port_db->ulp_func_id_tbl[func_id].func_valid)
536                 return -ENOENT;
537
538         *ifindex = port_db->ulp_func_id_tbl[func_id].ifindex;
539         return 0;
540 }
541
542 /*
543  * Api to get the function id for a given port id.
544  *
545  * ulp_ctxt [in] Ptr to ulp context
546  * port_id [in] dpdk port id
547  * func_id [out] the function id of the given ifindex.
548  *
549  * Returns 0 on success or negative number on failure.
550  */
551 int32_t
552 ulp_port_db_port_func_id_get(struct bnxt_ulp_context *ulp_ctxt,
553                              uint16_t port_id, uint16_t *func_id)
554 {
555         struct bnxt_ulp_port_db *port_db;
556         uint32_t ifindex;
557
558         port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
559         if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
560                 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
561                 return -EINVAL;
562         }
563         ifindex = port_db->dev_port_list[port_id];
564         if (!ifindex)
565                 return -ENOENT;
566
567         switch (port_db->ulp_intf_list[ifindex].type) {
568         case BNXT_ULP_INTF_TYPE_TRUSTED_VF:
569         case BNXT_ULP_INTF_TYPE_PF:
570                 *func_id =  port_db->ulp_intf_list[ifindex].drv_func_id;
571                 break;
572         case BNXT_ULP_INTF_TYPE_VF:
573         case BNXT_ULP_INTF_TYPE_VF_REP:
574                 *func_id =  port_db->ulp_intf_list[ifindex].vf_func_id;
575                 break;
576         default:
577                 *func_id = 0;
578                 break;
579         }
580         return 0;
581 }