1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2014-2021 Broadcom
6 #include <rte_malloc.h>
9 #include "bnxt_tf_common.h"
10 #include "bnxt_tf_pmd_shim.h"
11 #include "ulp_port_db.h"
14 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
15 #include "ulp_tf_debug.h"
19 ulp_port_db_allocate_ifindex(struct bnxt_ulp_port_db *port_db)
23 while (idx < port_db->ulp_intf_list_size &&
24 port_db->ulp_intf_list[idx].type != BNXT_ULP_INTF_TYPE_INVALID)
27 if (idx >= port_db->ulp_intf_list_size) {
28 BNXT_TF_DBG(ERR, "Port DB interface list is full\n");
35 * Initialize the port database. Memory is allocated in this
36 * call and assigned to the port database.
38 * ulp_ctxt [in] Ptr to ulp context
40 * Returns 0 on success or negative number on failure.
42 int32_t ulp_port_db_init(struct bnxt_ulp_context *ulp_ctxt, uint8_t port_cnt)
44 struct bnxt_ulp_port_db *port_db;
46 port_db = rte_zmalloc("bnxt_ulp_port_db",
47 sizeof(struct bnxt_ulp_port_db), 0);
50 "Failed to allocate memory for port db\n");
54 /* Attach the port database to the ulp context. */
55 bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, port_db);
57 /* index 0 is not being used hence add 1 to size */
58 port_db->ulp_intf_list_size = BNXT_PORT_DB_MAX_INTF_LIST + 1;
59 /* Allocate the port tables */
60 port_db->ulp_intf_list = rte_zmalloc("bnxt_ulp_port_db_intf_list",
61 port_db->ulp_intf_list_size *
62 sizeof(struct ulp_interface_info),
64 if (!port_db->ulp_intf_list) {
66 "Failed to allocate mem for port interface list\n");
70 /* Allocate the phy port list */
71 port_db->phy_port_list = rte_zmalloc("bnxt_ulp_phy_port_list",
73 sizeof(struct ulp_phy_port_info),
75 if (!port_db->phy_port_list) {
77 "Failed to allocate mem for phy port list\n");
80 port_db->phy_port_cnt = port_cnt;
84 ulp_port_db_deinit(ulp_ctxt);
89 * Deinitialize the port database. Memory is deallocated in
92 * ulp_ctxt [in] Ptr to ulp context
94 * Returns 0 on success.
96 int32_t ulp_port_db_deinit(struct bnxt_ulp_context *ulp_ctxt)
98 struct bnxt_ulp_port_db *port_db;
100 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
102 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
106 /* Detach the flow database from the ulp context. */
107 bnxt_ulp_cntxt_ptr2_port_db_set(ulp_ctxt, NULL);
109 /* Free up all the memory. */
110 rte_free(port_db->phy_port_list);
111 rte_free(port_db->ulp_intf_list);
117 * Update the port database.This api is called when the port
118 * details are available during the startup.
120 * ulp_ctxt [in] Ptr to ulp context
121 * bp [in]. ptr to the device function.
123 * Returns 0 on success or negative number on failure.
125 int32_t ulp_port_db_dev_port_intf_update(struct bnxt_ulp_context *ulp_ctxt,
126 struct rte_eth_dev *eth_dev)
128 uint32_t port_id = eth_dev->data->port_id;
129 struct ulp_phy_port_info *port_data;
130 struct bnxt_ulp_port_db *port_db;
131 struct ulp_interface_info *intf;
132 struct ulp_func_if_info *func;
136 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
138 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
142 rc = ulp_port_db_dev_port_to_ulp_index(ulp_ctxt, port_id, &ifindex);
144 /* port not found, allocate one */
145 ifindex = ulp_port_db_allocate_ifindex(port_db);
148 port_db->dev_port_list[port_id] = ifindex;
149 } else if (rc == -EINVAL) {
153 /* update the interface details */
154 intf = &port_db->ulp_intf_list[ifindex];
156 intf->type = bnxt_pmd_get_interface_type(port_id);
157 intf->drv_func_id = bnxt_pmd_get_fw_func_id(port_id,
158 BNXT_ULP_INTF_TYPE_INVALID);
160 func = &port_db->ulp_func_id_tbl[intf->drv_func_id];
161 if (!func->func_valid) {
162 func->func_svif = bnxt_pmd_get_svif(port_id, true,
163 BNXT_ULP_INTF_TYPE_INVALID);
164 func->func_spif = bnxt_pmd_get_phy_port_id(port_id);
166 bnxt_pmd_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
168 bnxt_pmd_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_INVALID);
169 func->phy_port_id = bnxt_pmd_get_phy_port_id(port_id);
170 func->func_valid = true;
171 func->ifindex = ifindex;
174 if (intf->type == BNXT_ULP_INTF_TYPE_VF_REP) {
176 bnxt_pmd_get_fw_func_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
178 func = &port_db->ulp_func_id_tbl[intf->vf_func_id];
180 bnxt_pmd_get_svif(port_id, true, BNXT_ULP_INTF_TYPE_VF_REP);
182 bnxt_pmd_get_phy_port_id(port_id);
184 bnxt_pmd_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
186 bnxt_pmd_get_vnic_id(port_id, BNXT_ULP_INTF_TYPE_VF_REP);
187 func->phy_port_id = bnxt_pmd_get_phy_port_id(port_id);
188 func->ifindex = ifindex;
191 /* When there is no match, the default action is to send the packet to
192 * the kernel. And to send it to the kernel, we need the PF's vnic id.
194 func->func_parent_vnic = bnxt_pmd_get_parent_vnic_id(port_id, intf->type);
195 func->func_parent_vnic = tfp_cpu_to_be_16(func->func_parent_vnic);
196 bnxt_pmd_get_iface_mac(port_id, intf->type, func->func_mac,
197 func->func_parent_mac);
199 port_data = &port_db->phy_port_list[func->phy_port_id];
200 if (!port_data->port_valid) {
201 port_data->port_svif =
202 bnxt_pmd_get_svif(port_id, false, BNXT_ULP_INTF_TYPE_INVALID);
203 port_data->port_spif = bnxt_pmd_get_phy_port_id(port_id);
204 port_data->port_parif =
205 bnxt_pmd_get_parif(port_id, BNXT_ULP_INTF_TYPE_INVALID);
206 port_data->port_vport = bnxt_pmd_get_vport(port_id);
207 port_data->port_valid = true;
209 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG
210 #ifdef RTE_LIBRTE_BNXT_TRUFLOW_DEBUG_PORT
211 ulp_port_db_dump(port_db, intf, port_id);
218 * Api to get the ulp ifindex for a given device port.
220 * ulp_ctxt [in] Ptr to ulp context
221 * port_id [in].device port id
222 * ifindex [out] ulp ifindex
224 * Returns 0 on success or negative number on failure.
227 ulp_port_db_dev_port_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
231 struct bnxt_ulp_port_db *port_db;
234 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
235 if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
236 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
239 if (!port_db->dev_port_list[port_id])
242 *ifindex = port_db->dev_port_list[port_id];
247 * Api to get the function id for a given ulp ifindex.
249 * ulp_ctxt [in] Ptr to ulp context
250 * ifindex [in] ulp ifindex
251 * func_id [out] the function id of the given ifindex.
253 * Returns 0 on success or negative number on failure.
256 ulp_port_db_function_id_get(struct bnxt_ulp_context *ulp_ctxt,
261 struct bnxt_ulp_port_db *port_db;
263 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
264 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
265 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
269 if (fid_type == BNXT_ULP_DRV_FUNC_FID)
270 *func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
272 *func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
278 * Api to get the svif for a given ulp ifindex.
280 * ulp_ctxt [in] Ptr to ulp context
281 * ifindex [in] ulp ifindex
282 * svif_type [in] the svif type of the given ifindex.
283 * svif [out] the svif of the given ifindex.
285 * Returns 0 on success or negative number on failure.
288 ulp_port_db_svif_get(struct bnxt_ulp_context *ulp_ctxt,
293 struct bnxt_ulp_port_db *port_db;
294 uint16_t phy_port_id, func_id;
296 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
297 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
298 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
302 if (svif_type == BNXT_ULP_DRV_FUNC_SVIF) {
303 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
304 *svif = port_db->ulp_func_id_tbl[func_id].func_svif;
305 } else if (svif_type == BNXT_ULP_VF_FUNC_SVIF) {
306 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
307 *svif = port_db->ulp_func_id_tbl[func_id].func_svif;
309 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
310 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
311 *svif = port_db->phy_port_list[phy_port_id].port_svif;
318 * Api to get the spif for a given ulp ifindex.
320 * ulp_ctxt [in] Ptr to ulp context
321 * ifindex [in] ulp ifindex
322 * spif_type [in] the spif type of the given ifindex.
323 * spif [out] the spif of the given ifindex.
325 * Returns 0 on success or negative number on failure.
328 ulp_port_db_spif_get(struct bnxt_ulp_context *ulp_ctxt,
333 struct bnxt_ulp_port_db *port_db;
334 uint16_t phy_port_id, func_id;
336 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
337 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
338 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
342 if (spif_type == BNXT_ULP_DRV_FUNC_SPIF) {
343 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
344 *spif = port_db->ulp_func_id_tbl[func_id].func_spif;
345 } else if (spif_type == BNXT_ULP_VF_FUNC_SPIF) {
346 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
347 *spif = port_db->ulp_func_id_tbl[func_id].func_spif;
349 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
350 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
351 *spif = port_db->phy_port_list[phy_port_id].port_spif;
358 * Api to get the parif for a given ulp ifindex.
360 * ulp_ctxt [in] Ptr to ulp context
361 * ifindex [in] ulp ifindex
362 * parif_type [in] the parif type of the given ifindex.
363 * parif [out] the parif of the given ifindex.
365 * Returns 0 on success or negative number on failure.
368 ulp_port_db_parif_get(struct bnxt_ulp_context *ulp_ctxt,
373 struct bnxt_ulp_port_db *port_db;
374 uint16_t phy_port_id, func_id;
376 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
377 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
378 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
381 if (parif_type == BNXT_ULP_DRV_FUNC_PARIF) {
382 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
383 *parif = port_db->ulp_func_id_tbl[func_id].func_parif;
384 } else if (parif_type == BNXT_ULP_VF_FUNC_PARIF) {
385 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
386 *parif = port_db->ulp_func_id_tbl[func_id].func_parif;
388 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
389 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
390 *parif = port_db->phy_port_list[phy_port_id].port_parif;
392 /* Parif needs to be reset to a free partition */
393 *parif += BNXT_ULP_FREE_PARIF_BASE;
399 * Api to get the vnic id for a given ulp ifindex.
401 * ulp_ctxt [in] Ptr to ulp context
402 * ifindex [in] ulp ifindex
403 * vnic [out] the vnic of the given ifindex.
405 * Returns 0 on success or negative number on failure.
408 ulp_port_db_default_vnic_get(struct bnxt_ulp_context *ulp_ctxt,
413 struct bnxt_ulp_port_db *port_db;
416 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
417 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
418 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
422 if (vnic_type == BNXT_ULP_DRV_FUNC_VNIC) {
423 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
424 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
426 func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
427 *vnic = port_db->ulp_func_id_tbl[func_id].func_vnic;
434 * Api to get the vport id for a given ulp ifindex.
436 * ulp_ctxt [in] Ptr to ulp context
437 * ifindex [in] ulp ifindex
438 * vport [out] the port of the given ifindex.
440 * Returns 0 on success or negative number on failure.
443 ulp_port_db_vport_get(struct bnxt_ulp_context *ulp_ctxt,
444 uint32_t ifindex, uint16_t *vport)
446 struct bnxt_ulp_port_db *port_db;
447 uint16_t phy_port_id, func_id;
449 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
450 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
451 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
455 func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
456 phy_port_id = port_db->ulp_func_id_tbl[func_id].phy_port_id;
457 *vport = port_db->phy_port_list[phy_port_id].port_vport;
462 * Api to get the vport for a given physical port.
464 * ulp_ctxt [in] Ptr to ulp context
465 * phy_port [in] physical port index
466 * out_port [out] the port of the given physical index
468 * Returns 0 on success or negative number on failure.
471 ulp_port_db_phy_port_vport_get(struct bnxt_ulp_context *ulp_ctxt,
475 struct bnxt_ulp_port_db *port_db;
477 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
478 if (!port_db || phy_port >= port_db->phy_port_cnt) {
479 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
482 *out_port = port_db->phy_port_list[phy_port].port_vport;
487 * Api to get the svif for a given physical port.
489 * ulp_ctxt [in] Ptr to ulp context
490 * phy_port [in] physical port index
491 * svif [out] the svif of the given physical index
493 * Returns 0 on success or negative number on failure.
496 ulp_port_db_phy_port_svif_get(struct bnxt_ulp_context *ulp_ctxt,
500 struct bnxt_ulp_port_db *port_db;
502 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
503 if (!port_db || phy_port >= port_db->phy_port_cnt) {
504 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
507 *svif = port_db->phy_port_list[phy_port].port_svif;
512 * Api to get the port type for a given ulp ifindex.
514 * ulp_ctxt [in] Ptr to ulp context
515 * ifindex [in] ulp ifindex
519 enum bnxt_ulp_intf_type
520 ulp_port_db_port_type_get(struct bnxt_ulp_context *ulp_ctxt,
523 struct bnxt_ulp_port_db *port_db;
525 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
526 if (!port_db || ifindex >= port_db->ulp_intf_list_size || !ifindex) {
527 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
528 return BNXT_ULP_INTF_TYPE_INVALID;
530 return port_db->ulp_intf_list[ifindex].type;
534 * Api to get the ulp ifindex for a given function id.
536 * ulp_ctxt [in] Ptr to ulp context
537 * func_id [in].device func id
538 * ifindex [out] ulp ifindex
540 * Returns 0 on success or negative number on failure.
543 ulp_port_db_dev_func_id_to_ulp_index(struct bnxt_ulp_context *ulp_ctxt,
544 uint32_t func_id, uint32_t *ifindex)
546 struct bnxt_ulp_port_db *port_db;
549 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
550 if (!port_db || func_id >= BNXT_PORT_DB_MAX_FUNC) {
551 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
554 if (!port_db->ulp_func_id_tbl[func_id].func_valid)
557 *ifindex = port_db->ulp_func_id_tbl[func_id].ifindex;
562 * Api to get the function id for a given port id.
564 * ulp_ctxt [in] Ptr to ulp context
565 * port_id [in] dpdk port id
566 * func_id [out] the function id of the given ifindex.
568 * Returns 0 on success or negative number on failure.
571 ulp_port_db_port_func_id_get(struct bnxt_ulp_context *ulp_ctxt,
572 uint16_t port_id, uint16_t *func_id)
574 struct bnxt_ulp_port_db *port_db;
577 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
578 if (!port_db || port_id >= RTE_MAX_ETHPORTS) {
579 BNXT_TF_DBG(ERR, "Invalid Arguments\n");
582 ifindex = port_db->dev_port_list[port_id];
586 switch (port_db->ulp_intf_list[ifindex].type) {
587 case BNXT_ULP_INTF_TYPE_TRUSTED_VF:
588 case BNXT_ULP_INTF_TYPE_PF:
589 *func_id = port_db->ulp_intf_list[ifindex].drv_func_id;
591 case BNXT_ULP_INTF_TYPE_VF:
592 case BNXT_ULP_INTF_TYPE_VF_REP:
593 *func_id = port_db->ulp_intf_list[ifindex].vf_func_id;
602 /* internal function to get the */
603 static struct ulp_func_if_info*
604 ulp_port_db_func_if_info_get(struct bnxt_ulp_context *ulp_ctxt,
607 struct bnxt_ulp_port_db *port_db;
610 port_db = bnxt_ulp_cntxt_ptr2_port_db_get(ulp_ctxt);
611 if (ulp_port_db_port_func_id_get(ulp_ctxt, port_id, &func_id)) {
612 BNXT_TF_DBG(ERR, "Invalid port_id %x\n", port_id);
616 if (!port_db->ulp_func_id_tbl[func_id].func_valid) {
617 BNXT_TF_DBG(ERR, "Invalid func_id %x\n", func_id);
620 return &port_db->ulp_func_id_tbl[func_id];
624 * Api to get the parent mac address for a given port id.
626 * ulp_ctxt [in] Ptr to ulp context
627 * port_id [in] device port id
628 * mac_addr [out] mac address
630 * Returns 0 on success or negative number on failure.
633 ulp_port_db_parent_mac_addr_get(struct bnxt_ulp_context *ulp_ctxt,
634 uint32_t port_id, uint8_t **mac_addr)
636 struct ulp_func_if_info *info;
638 info = ulp_port_db_func_if_info_get(ulp_ctxt, port_id);
640 *mac_addr = info->func_parent_mac;
647 * Api to get the mac address for a given port id.
649 * ulp_ctxt [in] Ptr to ulp context
650 * port_id [in] device port id
651 * mac_addr [out] mac address
653 * Returns 0 on success or negative number on failure.
656 ulp_port_db_drv_mac_addr_get(struct bnxt_ulp_context *ulp_ctxt,
657 uint32_t port_id, uint8_t **mac_addr)
659 struct ulp_func_if_info *info;
661 info = ulp_port_db_func_if_info_get(ulp_ctxt, port_id);
663 *mac_addr = info->func_mac;
670 * Api to get the parent vnic for a given port id.
672 * ulp_ctxt [in] Ptr to ulp context
673 * port_id [in] device port id
674 * vnic [out] parent vnic
676 * Returns 0 on success or negative number on failure.
679 ulp_port_db_parent_vnic_get(struct bnxt_ulp_context *ulp_ctxt,
680 uint32_t port_id, uint8_t **vnic)
682 struct ulp_func_if_info *info;
684 info = ulp_port_db_func_if_info_get(ulp_ctxt, port_id);
686 *vnic = (uint8_t *)&info->func_parent_vnic;