This patch implements checking if Multiport E-Switch is enabled on a given PCI device using Devlink Linux kernel interface. This facility will be used in follow up commits, which add support for such configuration to mlx5 PMD.
If mlx5_core Linux kernel module supports Multiport E-Switch, then it can be configured through a Devlink boolean parameter "esw_multiport". Checking the value of this parameter is implemented in mlx5_nl_devlink_esw_multiport_get() function. If such parameter does not exist, this function returns -EINVAL. To manually check if mlx5_core kernel module supports "esw_multiport" parameter, and check if Multiport E-Switch is enabled, one can use the following command: # <pci-dbdf> should be substituted with PCI device address # in format <domain>:<bus>:<device>:<function>. $ devlink dev param show pci/0000:08:00.0 name esw_multiport pci/0000:08:00.0: name esw_multiport type driver-specific values: cmode runtime value true If parameter is not supported, Devlink command fails with "Invalid argument" error. Signed-off-by: Dariusz Sosnowski <dsosnow...@nvidia.com> Acked-by: Viacheslav Ovsiienko <viachesl...@nvidia.com> --- drivers/common/mlx5/linux/mlx5_nl.c | 70 +++++++++++++++++++++++++++++ drivers/common/mlx5/linux/mlx5_nl.h | 5 +++ drivers/common/mlx5/version.map | 2 + 3 files changed, 77 insertions(+) diff --git a/drivers/common/mlx5/linux/mlx5_nl.c b/drivers/common/mlx5/linux/mlx5_nl.c index 33670bb5c8..28a1f56dba 100644 --- a/drivers/common/mlx5/linux/mlx5_nl.c +++ b/drivers/common/mlx5/linux/mlx5_nl.c @@ -1962,3 +1962,73 @@ mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg) } return 0; } + +static int +mlx5_nl_esw_multiport_cb(struct nlmsghdr *nh, void *arg) +{ + + int ret = -EINVAL; + int *enable = arg; + struct nlattr *tail = RTE_PTR_ADD(nh, nh->nlmsg_len); + struct nlattr *nla = RTE_PTR_ADD(nh, NLMSG_ALIGN(sizeof(*nh)) + + NLMSG_ALIGN(sizeof(struct genlmsghdr))); + + while (nla->nla_len && nla < tail) { + switch (nla->nla_type) { + /* Expected nested attributes case. */ + case DEVLINK_ATTR_PARAM: + case DEVLINK_ATTR_PARAM_VALUES_LIST: + case DEVLINK_ATTR_PARAM_VALUE: + ret = 0; + nla += 1; + break; + case DEVLINK_ATTR_PARAM_VALUE_DATA: + *enable = 1; + return 0; + default: + nla = RTE_PTR_ADD(nla, NLMSG_ALIGN(nla->nla_len)); + } + } + *enable = 0; + return ret; +} + +#define NL_ESW_MULTIPORT_PARAM "esw_multiport" + +int +mlx5_nl_devlink_esw_multiport_get(int nlsk_fd, int family_id, const char *pci_addr, int *enable) +{ + struct nlmsghdr *nlh; + struct genlmsghdr *genl; + uint32_t sn = MLX5_NL_SN_GENERATE; + int ret; + uint8_t buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + + NLMSG_ALIGN(sizeof(struct genlmsghdr)) + + NLMSG_ALIGN(sizeof(struct nlattr)) * 4 + + NLMSG_ALIGN(MLX5_NL_MAX_ATTR_SIZE) * 4]; + + memset(buf, 0, sizeof(buf)); + nlh = (struct nlmsghdr *)buf; + nlh->nlmsg_len = sizeof(struct nlmsghdr); + nlh->nlmsg_type = family_id; + nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; + genl = (struct genlmsghdr *)nl_msg_tail(nlh); + nlh->nlmsg_len += sizeof(struct genlmsghdr); + genl->cmd = DEVLINK_CMD_PARAM_GET; + genl->version = DEVLINK_GENL_VERSION; + nl_attr_put(nlh, DEVLINK_ATTR_BUS_NAME, "pci", 4); + nl_attr_put(nlh, DEVLINK_ATTR_DEV_NAME, pci_addr, strlen(pci_addr) + 1); + nl_attr_put(nlh, DEVLINK_ATTR_PARAM_NAME, + NL_ESW_MULTIPORT_PARAM, sizeof(NL_ESW_MULTIPORT_PARAM)); + ret = mlx5_nl_send(nlsk_fd, nlh, sn); + if (ret >= 0) + ret = mlx5_nl_recv(nlsk_fd, sn, mlx5_nl_esw_multiport_cb, enable); + if (ret < 0) { + DRV_LOG(DEBUG, "Failed to get Multiport E-Switch enable on device %s: %d.", + pci_addr, ret); + return ret; + } + DRV_LOG(DEBUG, "Multiport E-Switch is %sabled for device \"%s\".", + *enable ? "en" : "dis", pci_addr); + return ret; +} diff --git a/drivers/common/mlx5/linux/mlx5_nl.h b/drivers/common/mlx5/linux/mlx5_nl.h index db01d7323e..580de3b769 100644 --- a/drivers/common/mlx5/linux/mlx5_nl.h +++ b/drivers/common/mlx5/linux/mlx5_nl.h @@ -71,6 +71,7 @@ __rte_internal uint32_t mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa, uint32_t ifindex, uint16_t tag); +__rte_internal int mlx5_nl_devlink_family_id_get(int nlsk_fd); int mlx5_nl_enable_roce_get(int nlsk_fd, int family_id, const char *pci_addr, int *enable); @@ -82,4 +83,8 @@ int mlx5_nl_read_events(int nlsk_fd, mlx5_nl_event_cb *cb, void *cb_arg); __rte_internal int mlx5_nl_parse_link_status_update(struct nlmsghdr *hdr, uint32_t *ifindex); +__rte_internal +int mlx5_nl_devlink_esw_multiport_get(int nlsk_fd, int family_id, + const char *pci_addr, int *enable); + #endif /* RTE_PMD_MLX5_NL_H_ */ diff --git a/drivers/common/mlx5/version.map b/drivers/common/mlx5/version.map index 0758ba76de..074eed46fd 100644 --- a/drivers/common/mlx5/version.map +++ b/drivers/common/mlx5/version.map @@ -125,6 +125,8 @@ INTERNAL { mlx5_mr_addr2mr_bh; mlx5_nl_allmulti; # WINDOWS_NO_EXPORT + mlx5_nl_devlink_esw_multiport_get; # WINDOWS_NO_EXPORT + mlx5_nl_devlink_family_id_get; # WINDOWS_NO_EXPORT mlx5_nl_ifindex; # WINDOWS_NO_EXPORT mlx5_nl_init; # WINDOWS_NO_EXPORT mlx5_nl_mac_addr_add; # WINDOWS_NO_EXPORT -- 2.25.1