net/mlx5: probe all port representors
Probe existing port representors in addition to their master device and associate them automatically. To avoid collision between Ethernet devices, they are named as follows: - "{DBDF}" for master/switch devices. - "{DBDF}_representor_{rep}" with "rep" starting from 0 for port representors. (Patch based on prior work from Yuanhan Liu) Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com> Reviewed-by: Xueming Li <xuemingl@mellanox.com>
This commit is contained in:
parent
26c08b979d
commit
2b73026388
@ -307,7 +307,27 @@ mlx5_dev_close(struct rte_eth_dev *dev)
|
|||||||
if (ret)
|
if (ret)
|
||||||
DRV_LOG(WARNING, "port %u some flows still remain",
|
DRV_LOG(WARNING, "port %u some flows still remain",
|
||||||
dev->data->port_id);
|
dev->data->port_id);
|
||||||
|
if (priv->domain_id != RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
|
||||||
|
unsigned int c = 0;
|
||||||
|
unsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0);
|
||||||
|
uint16_t port_id[i];
|
||||||
|
|
||||||
|
i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);
|
||||||
|
while (i--) {
|
||||||
|
struct priv *opriv =
|
||||||
|
rte_eth_devices[port_id[i]].data->dev_private;
|
||||||
|
|
||||||
|
if (!opriv ||
|
||||||
|
opriv->domain_id != priv->domain_id ||
|
||||||
|
&rte_eth_devices[port_id[i]] == dev)
|
||||||
|
continue;
|
||||||
|
++c;
|
||||||
|
}
|
||||||
|
if (!c)
|
||||||
|
claim_zero(rte_eth_switch_domain_free(priv->domain_id));
|
||||||
|
}
|
||||||
memset(priv, 0, sizeof(*priv));
|
memset(priv, 0, sizeof(*priv));
|
||||||
|
priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct eth_dev_ops mlx5_dev_ops = {
|
const struct eth_dev_ops mlx5_dev_ops = {
|
||||||
@ -647,6 +667,8 @@ mlx5_uar_init_secondary(struct rte_eth_dev *dev)
|
|||||||
* Verbs device.
|
* Verbs device.
|
||||||
* @param vf
|
* @param vf
|
||||||
* If nonzero, enable VF-specific features.
|
* If nonzero, enable VF-specific features.
|
||||||
|
* @param[in] switch_info
|
||||||
|
* Switch properties of Ethernet device.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* A valid Ethernet device object on success, NULL otherwise and rte_errno
|
* A valid Ethernet device object on success, NULL otherwise and rte_errno
|
||||||
@ -655,7 +677,8 @@ mlx5_uar_init_secondary(struct rte_eth_dev *dev)
|
|||||||
static struct rte_eth_dev *
|
static struct rte_eth_dev *
|
||||||
mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
||||||
struct ibv_device *ibv_dev,
|
struct ibv_device *ibv_dev,
|
||||||
int vf)
|
int vf,
|
||||||
|
const struct mlx5_switch_info *switch_info)
|
||||||
{
|
{
|
||||||
struct ibv_context *ctx;
|
struct ibv_context *ctx;
|
||||||
struct ibv_device_attr_ex attr;
|
struct ibv_device_attr_ex attr;
|
||||||
@ -697,6 +720,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
|||||||
#endif
|
#endif
|
||||||
struct ether_addr mac;
|
struct ether_addr mac;
|
||||||
char name[RTE_ETH_NAME_MAX_LEN];
|
char name[RTE_ETH_NAME_MAX_LEN];
|
||||||
|
int own_domain_id = 0;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
/* Prepare shared data between primary and secondary process. */
|
/* Prepare shared data between primary and secondary process. */
|
||||||
mlx5_prepare_shared_data();
|
mlx5_prepare_shared_data();
|
||||||
@ -805,7 +830,12 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
|||||||
DEBUG("ibv_query_device_ex() failed");
|
DEBUG("ibv_query_device_ex() failed");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rte_strlcpy(name, dpdk_dev->name, sizeof(name));
|
if (!switch_info->representor)
|
||||||
|
rte_strlcpy(name, dpdk_dev->name, sizeof(name));
|
||||||
|
else
|
||||||
|
snprintf(name, sizeof(name), "%s_representor_%u",
|
||||||
|
dpdk_dev->name, switch_info->port_name);
|
||||||
|
DRV_LOG(DEBUG, "naming Ethernet device \"%s\"", name);
|
||||||
if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
|
if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
|
||||||
eth_dev = rte_eth_dev_attach_secondary(name);
|
eth_dev = rte_eth_dev_attach_secondary(name);
|
||||||
if (eth_dev == NULL) {
|
if (eth_dev == NULL) {
|
||||||
@ -874,6 +904,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
priv->ctx = ctx;
|
priv->ctx = ctx;
|
||||||
|
strncpy(priv->ibdev_name, priv->ctx->device->name,
|
||||||
|
sizeof(priv->ibdev_name));
|
||||||
strncpy(priv->ibdev_path, priv->ctx->device->ibdev_path,
|
strncpy(priv->ibdev_path, priv->ctx->device->ibdev_path,
|
||||||
sizeof(priv->ibdev_path));
|
sizeof(priv->ibdev_path));
|
||||||
priv->device_attr = attr;
|
priv->device_attr = attr;
|
||||||
@ -883,6 +915,41 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
|||||||
priv->nl_socket_rdma = mlx5_nl_init(0, NETLINK_RDMA);
|
priv->nl_socket_rdma = mlx5_nl_init(0, NETLINK_RDMA);
|
||||||
priv->nl_socket_route = mlx5_nl_init(RTMGRP_LINK, NETLINK_ROUTE);
|
priv->nl_socket_route = mlx5_nl_init(RTMGRP_LINK, NETLINK_ROUTE);
|
||||||
priv->nl_sn = 0;
|
priv->nl_sn = 0;
|
||||||
|
priv->representor = !!switch_info->representor;
|
||||||
|
priv->domain_id = RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID;
|
||||||
|
priv->representor_id =
|
||||||
|
switch_info->representor ? switch_info->port_name : -1;
|
||||||
|
/*
|
||||||
|
* Look for sibling devices in order to reuse their switch domain
|
||||||
|
* if any, otherwise allocate one.
|
||||||
|
*/
|
||||||
|
i = mlx5_dev_to_port_id(dpdk_dev, NULL, 0);
|
||||||
|
if (i > 0) {
|
||||||
|
uint16_t port_id[i];
|
||||||
|
|
||||||
|
i = RTE_MIN(mlx5_dev_to_port_id(dpdk_dev, port_id, i), i);
|
||||||
|
while (i--) {
|
||||||
|
const struct priv *opriv =
|
||||||
|
rte_eth_devices[port_id[i]].data->dev_private;
|
||||||
|
|
||||||
|
if (!opriv ||
|
||||||
|
opriv->domain_id ==
|
||||||
|
RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID)
|
||||||
|
continue;
|
||||||
|
priv->domain_id = opriv->domain_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (priv->domain_id == RTE_ETH_DEV_SWITCH_DOMAIN_ID_INVALID) {
|
||||||
|
err = rte_eth_switch_domain_alloc(&priv->domain_id);
|
||||||
|
if (err) {
|
||||||
|
err = rte_errno;
|
||||||
|
DRV_LOG(ERR, "unable to allocate switch domain: %s",
|
||||||
|
strerror(rte_errno));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
own_domain_id = 1;
|
||||||
|
}
|
||||||
err = mlx5_args(&config, dpdk_dev->devargs);
|
err = mlx5_args(&config, dpdk_dev->devargs);
|
||||||
if (err) {
|
if (err) {
|
||||||
err = rte_errno;
|
err = rte_errno;
|
||||||
@ -966,6 +1033,8 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev,
|
|||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (priv->representor)
|
||||||
|
eth_dev->data->dev_flags |= RTE_ETH_DEV_REPRESENTOR;
|
||||||
eth_dev->data->dev_private = priv;
|
eth_dev->data->dev_private = priv;
|
||||||
priv->dev_data = eth_dev->data;
|
priv->dev_data = eth_dev->data;
|
||||||
eth_dev->data->mac_addrs = priv->mac;
|
eth_dev->data->mac_addrs = priv->mac;
|
||||||
@ -1084,6 +1153,8 @@ error:
|
|||||||
close(priv->nl_socket_route);
|
close(priv->nl_socket_route);
|
||||||
if (priv->nl_socket_rdma >= 0)
|
if (priv->nl_socket_rdma >= 0)
|
||||||
close(priv->nl_socket_rdma);
|
close(priv->nl_socket_rdma);
|
||||||
|
if (own_domain_id)
|
||||||
|
claim_zero(rte_eth_switch_domain_free(priv->domain_id));
|
||||||
rte_free(priv);
|
rte_free(priv);
|
||||||
}
|
}
|
||||||
if (pd)
|
if (pd)
|
||||||
@ -1100,7 +1171,7 @@ error:
|
|||||||
/**
|
/**
|
||||||
* DPDK callback to register a PCI device.
|
* DPDK callback to register a PCI device.
|
||||||
*
|
*
|
||||||
* This function spawns an Ethernet device out of a given PCI device.
|
* This function spawns Ethernet devices out of a given PCI device.
|
||||||
*
|
*
|
||||||
* @param[in] pci_drv
|
* @param[in] pci_drv
|
||||||
* PCI driver structure (mlx5_driver).
|
* PCI driver structure (mlx5_driver).
|
||||||
@ -1115,7 +1186,6 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|||||||
struct rte_pci_device *pci_dev)
|
struct rte_pci_device *pci_dev)
|
||||||
{
|
{
|
||||||
struct ibv_device **ibv_list;
|
struct ibv_device **ibv_list;
|
||||||
struct rte_eth_dev *eth_dev = NULL;
|
|
||||||
unsigned int n = 0;
|
unsigned int n = 0;
|
||||||
int vf;
|
int vf;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1150,9 +1220,11 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|||||||
|
|
||||||
unsigned int ifindex[n];
|
unsigned int ifindex[n];
|
||||||
struct mlx5_switch_info info[n];
|
struct mlx5_switch_info info[n];
|
||||||
|
struct rte_eth_dev *eth_list[n];
|
||||||
int nl_route = n ? mlx5_nl_init(0, NETLINK_ROUTE) : -1;
|
int nl_route = n ? mlx5_nl_init(0, NETLINK_ROUTE) : -1;
|
||||||
int nl_rdma = n ? mlx5_nl_init(0, NETLINK_RDMA) : -1;
|
int nl_rdma = n ? mlx5_nl_init(0, NETLINK_RDMA) : -1;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
unsigned int u;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The existence of several matching entries (n > 1) means port
|
* The existence of several matching entries (n > 1) means port
|
||||||
@ -1187,28 +1259,14 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|||||||
close(nl_rdma);
|
close(nl_rdma);
|
||||||
if (nl_route >= 0)
|
if (nl_route >= 0)
|
||||||
close(nl_route);
|
close(nl_route);
|
||||||
/* Look for master device. */
|
/* Count unidentified devices. */
|
||||||
for (i = 0; i != n; ++i) {
|
for (u = 0, i = 0; i != n; ++i)
|
||||||
if (!info[i].master)
|
if (!info[i].master && !info[i].representor)
|
||||||
continue;
|
++u;
|
||||||
/* Make it the first entry. */
|
if (u) {
|
||||||
if (i == 0)
|
if (n == 1 && u == 1) {
|
||||||
break;
|
|
||||||
ibv_match[n] = ibv_match[0];
|
|
||||||
ibv_match[0] = ibv_match[i];
|
|
||||||
ibv_match[n] = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (n && i == n) {
|
|
||||||
if (n == 1 && !info[0].representor) {
|
|
||||||
/* Case #2. */
|
/* Case #2. */
|
||||||
DRV_LOG(INFO, "no switch support detected");
|
DRV_LOG(INFO, "no switch support detected");
|
||||||
} else if (n == 1) {
|
|
||||||
/* Case #3. */
|
|
||||||
DRV_LOG(ERR,
|
|
||||||
"device looks like a port representor, this is"
|
|
||||||
" not supported yet");
|
|
||||||
n = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* Case #3. */
|
/* Case #3. */
|
||||||
DRV_LOG(ERR,
|
DRV_LOG(ERR,
|
||||||
@ -1227,8 +1285,19 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|||||||
default:
|
default:
|
||||||
vf = 0;
|
vf = 0;
|
||||||
}
|
}
|
||||||
if (n)
|
for (i = 0; i != n; ++i) {
|
||||||
eth_dev = mlx5_dev_spawn(&pci_dev->device, ibv_match[0], vf);
|
uint32_t restore;
|
||||||
|
|
||||||
|
eth_list[i] = mlx5_dev_spawn(&pci_dev->device, ibv_match[i],
|
||||||
|
vf, &info[i]);
|
||||||
|
if (!eth_list[i])
|
||||||
|
break;
|
||||||
|
restore = eth_list[i]->data->dev_flags;
|
||||||
|
rte_eth_copy_pci_info(eth_list[i], pci_dev);
|
||||||
|
/* Restore non-PCI flags cleared by the above call. */
|
||||||
|
eth_list[i]->data->dev_flags |= restore;
|
||||||
|
rte_eth_dev_probing_finish(eth_list[i]);
|
||||||
|
}
|
||||||
mlx5_glue->free_device_list(ibv_list);
|
mlx5_glue->free_device_list(ibv_list);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
DRV_LOG(WARNING,
|
DRV_LOG(WARNING,
|
||||||
@ -1238,7 +1307,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|||||||
pci_dev->addr.devid, pci_dev->addr.function);
|
pci_dev->addr.devid, pci_dev->addr.function);
|
||||||
rte_errno = ENOENT;
|
rte_errno = ENOENT;
|
||||||
ret = -rte_errno;
|
ret = -rte_errno;
|
||||||
} else if (!eth_dev) {
|
} else if (i != n) {
|
||||||
DRV_LOG(ERR,
|
DRV_LOG(ERR,
|
||||||
"probe of PCI device " PCI_PRI_FMT " aborted after"
|
"probe of PCI device " PCI_PRI_FMT " aborted after"
|
||||||
" encountering an error: %s",
|
" encountering an error: %s",
|
||||||
@ -1246,9 +1315,16 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|||||||
pci_dev->addr.devid, pci_dev->addr.function,
|
pci_dev->addr.devid, pci_dev->addr.function,
|
||||||
strerror(rte_errno));
|
strerror(rte_errno));
|
||||||
ret = -rte_errno;
|
ret = -rte_errno;
|
||||||
|
/* Roll back. */
|
||||||
|
while (i--) {
|
||||||
|
mlx5_dev_close(eth_list[i]);
|
||||||
|
if (rte_eal_process_type() == RTE_PROC_PRIMARY)
|
||||||
|
rte_free(eth_list[i]->data->dev_private);
|
||||||
|
claim_zero(rte_eth_dev_release_port(eth_list[i]));
|
||||||
|
}
|
||||||
|
/* Restore original error. */
|
||||||
|
rte_errno = -ret;
|
||||||
} else {
|
} else {
|
||||||
rte_eth_copy_pci_info(eth_dev, pci_dev);
|
|
||||||
rte_eth_dev_probing_finish(eth_dev);
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -159,6 +159,7 @@ struct priv {
|
|||||||
struct ibv_context *ctx; /* Verbs context. */
|
struct ibv_context *ctx; /* Verbs context. */
|
||||||
struct ibv_device_attr_ex device_attr; /* Device properties. */
|
struct ibv_device_attr_ex device_attr; /* Device properties. */
|
||||||
struct ibv_pd *pd; /* Protection Domain. */
|
struct ibv_pd *pd; /* Protection Domain. */
|
||||||
|
char ibdev_name[IBV_SYSFS_NAME_MAX]; /* IB device name. */
|
||||||
char ibdev_path[IBV_SYSFS_PATH_MAX]; /* IB device path for secondary */
|
char ibdev_path[IBV_SYSFS_PATH_MAX]; /* IB device path for secondary */
|
||||||
struct ether_addr mac[MLX5_MAX_MAC_ADDRESSES]; /* MAC addresses. */
|
struct ether_addr mac[MLX5_MAX_MAC_ADDRESSES]; /* MAC addresses. */
|
||||||
BITFIELD_DECLARE(mac_own, uint64_t, MLX5_MAX_MAC_ADDRESSES);
|
BITFIELD_DECLARE(mac_own, uint64_t, MLX5_MAX_MAC_ADDRESSES);
|
||||||
@ -168,6 +169,9 @@ struct priv {
|
|||||||
/* Device properties. */
|
/* Device properties. */
|
||||||
uint16_t mtu; /* Configured MTU. */
|
uint16_t mtu; /* Configured MTU. */
|
||||||
unsigned int isolated:1; /* Whether isolated mode is enabled. */
|
unsigned int isolated:1; /* Whether isolated mode is enabled. */
|
||||||
|
unsigned int representor:1; /* Device is a port representor. */
|
||||||
|
uint16_t domain_id; /* Switch domain identifier. */
|
||||||
|
int32_t representor_id; /* Port representor identifier. */
|
||||||
/* RX/TX queues. */
|
/* RX/TX queues. */
|
||||||
unsigned int rxqs_n; /* RX queues array size. */
|
unsigned int rxqs_n; /* RX queues array size. */
|
||||||
unsigned int txqs_n; /* TX queues array size. */
|
unsigned int txqs_n; /* TX queues array size. */
|
||||||
@ -217,9 +221,12 @@ int mlx5_getenv_int(const char *);
|
|||||||
|
|
||||||
/* mlx5_ethdev.c */
|
/* mlx5_ethdev.c */
|
||||||
|
|
||||||
|
int mlx5_get_master_ifname(const struct rte_eth_dev *dev,
|
||||||
|
char (*ifname)[IF_NAMESIZE]);
|
||||||
int mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]);
|
int mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE]);
|
||||||
int mlx5_ifindex(const struct rte_eth_dev *dev);
|
int mlx5_ifindex(const struct rte_eth_dev *dev);
|
||||||
int mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr);
|
int mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr,
|
||||||
|
int master);
|
||||||
int mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu);
|
int mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu);
|
||||||
int mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep,
|
int mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
@ -244,6 +251,9 @@ int mlx5_set_link_up(struct rte_eth_dev *dev);
|
|||||||
int mlx5_is_removed(struct rte_eth_dev *dev);
|
int mlx5_is_removed(struct rte_eth_dev *dev);
|
||||||
eth_tx_burst_t mlx5_select_tx_function(struct rte_eth_dev *dev);
|
eth_tx_burst_t mlx5_select_tx_function(struct rte_eth_dev *dev);
|
||||||
eth_rx_burst_t mlx5_select_rx_function(struct rte_eth_dev *dev);
|
eth_rx_burst_t mlx5_select_rx_function(struct rte_eth_dev *dev);
|
||||||
|
unsigned int mlx5_dev_to_port_id(const struct rte_device *dev,
|
||||||
|
uint16_t *port_list,
|
||||||
|
unsigned int port_list_n);
|
||||||
|
|
||||||
/* mlx5_mac.c */
|
/* mlx5_mac.c */
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ struct ethtool_link_settings {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get interface name from private structure.
|
* Get master interface name from private structure.
|
||||||
*
|
*
|
||||||
* @param[in] dev
|
* @param[in] dev
|
||||||
* Pointer to Ethernet device.
|
* Pointer to Ethernet device.
|
||||||
@ -104,7 +104,8 @@ struct ethtool_link_settings {
|
|||||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
|
mlx5_get_master_ifname(const struct rte_eth_dev *dev,
|
||||||
|
char (*ifname)[IF_NAMESIZE])
|
||||||
{
|
{
|
||||||
struct priv *priv = dev->data->dev_private;
|
struct priv *priv = dev->data->dev_private;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
@ -178,6 +179,39 @@ try_dev_id:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get interface name from private structure.
|
||||||
|
*
|
||||||
|
* This is a port representor-aware version of mlx5_get_master_ifname().
|
||||||
|
*
|
||||||
|
* @param[in] dev
|
||||||
|
* Pointer to Ethernet device.
|
||||||
|
* @param[out] ifname
|
||||||
|
* Interface name output buffer.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mlx5_get_ifname(const struct rte_eth_dev *dev, char (*ifname)[IF_NAMESIZE])
|
||||||
|
{
|
||||||
|
struct priv *priv = dev->data->dev_private;
|
||||||
|
unsigned int ifindex =
|
||||||
|
priv->nl_socket_rdma >= 0 ?
|
||||||
|
mlx5_nl_ifindex(priv->nl_socket_rdma, priv->ibdev_name) : 0;
|
||||||
|
|
||||||
|
if (!ifindex) {
|
||||||
|
if (!priv->representor)
|
||||||
|
return mlx5_get_master_ifname(dev, ifname);
|
||||||
|
rte_errno = ENXIO;
|
||||||
|
return -rte_errno;
|
||||||
|
}
|
||||||
|
if (if_indextoname(ifindex, &(*ifname)[0]))
|
||||||
|
return 0;
|
||||||
|
rte_errno = errno;
|
||||||
|
return -rte_errno;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the interface index from device name.
|
* Get the interface index from device name.
|
||||||
*
|
*
|
||||||
@ -214,12 +248,16 @@ mlx5_ifindex(const struct rte_eth_dev *dev)
|
|||||||
* Request number to pass to ioctl().
|
* Request number to pass to ioctl().
|
||||||
* @param[out] ifr
|
* @param[out] ifr
|
||||||
* Interface request structure output buffer.
|
* Interface request structure output buffer.
|
||||||
|
* @param master
|
||||||
|
* When device is a port representor, perform request on master device
|
||||||
|
* instead.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
* 0 on success, a negative errno value otherwise and rte_errno is set.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
|
mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr,
|
||||||
|
int master)
|
||||||
{
|
{
|
||||||
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
int sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -228,7 +266,10 @@ mlx5_ifreq(const struct rte_eth_dev *dev, int req, struct ifreq *ifr)
|
|||||||
rte_errno = errno;
|
rte_errno = errno;
|
||||||
return -rte_errno;
|
return -rte_errno;
|
||||||
}
|
}
|
||||||
ret = mlx5_get_ifname(dev, &ifr->ifr_name);
|
if (master)
|
||||||
|
ret = mlx5_get_master_ifname(dev, &ifr->ifr_name);
|
||||||
|
else
|
||||||
|
ret = mlx5_get_ifname(dev, &ifr->ifr_name);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto error;
|
goto error;
|
||||||
ret = ioctl(sock, req, ifr);
|
ret = ioctl(sock, req, ifr);
|
||||||
@ -258,7 +299,7 @@ int
|
|||||||
mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
|
mlx5_get_mtu(struct rte_eth_dev *dev, uint16_t *mtu)
|
||||||
{
|
{
|
||||||
struct ifreq request;
|
struct ifreq request;
|
||||||
int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request);
|
int ret = mlx5_ifreq(dev, SIOCGIFMTU, &request, 0);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
@ -282,7 +323,7 @@ mlx5_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
|
|||||||
{
|
{
|
||||||
struct ifreq request = { .ifr_mtu = mtu, };
|
struct ifreq request = { .ifr_mtu = mtu, };
|
||||||
|
|
||||||
return mlx5_ifreq(dev, SIOCSIFMTU, &request);
|
return mlx5_ifreq(dev, SIOCSIFMTU, &request, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,13 +343,13 @@ int
|
|||||||
mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
|
mlx5_set_flags(struct rte_eth_dev *dev, unsigned int keep, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct ifreq request;
|
struct ifreq request;
|
||||||
int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request);
|
int ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &request, 0);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
request.ifr_flags &= keep;
|
request.ifr_flags &= keep;
|
||||||
request.ifr_flags |= flags & ~keep;
|
request.ifr_flags |= flags & ~keep;
|
||||||
return mlx5_ifreq(dev, SIOCSIFFLAGS, &request);
|
return mlx5_ifreq(dev, SIOCSIFFLAGS, &request, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -477,6 +518,30 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
|
|||||||
info->speed_capa = priv->link_speed_capa;
|
info->speed_capa = priv->link_speed_capa;
|
||||||
info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
|
info->flow_type_rss_offloads = ~MLX5_RSS_HF_MASK;
|
||||||
mlx5_set_default_params(dev, info);
|
mlx5_set_default_params(dev, info);
|
||||||
|
info->switch_info.name = dev->data->name;
|
||||||
|
info->switch_info.domain_id = priv->domain_id;
|
||||||
|
info->switch_info.port_id = priv->representor_id;
|
||||||
|
if (priv->representor) {
|
||||||
|
unsigned int i = mlx5_dev_to_port_id(dev->device, NULL, 0);
|
||||||
|
uint16_t port_id[i];
|
||||||
|
|
||||||
|
i = RTE_MIN(mlx5_dev_to_port_id(dev->device, port_id, i), i);
|
||||||
|
while (i--) {
|
||||||
|
struct priv *opriv =
|
||||||
|
rte_eth_devices[port_id[i]].data->dev_private;
|
||||||
|
|
||||||
|
if (!opriv ||
|
||||||
|
opriv->representor ||
|
||||||
|
opriv->domain_id != priv->domain_id)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
* Override switch name with that of the master
|
||||||
|
* device.
|
||||||
|
*/
|
||||||
|
info->switch_info.name = opriv->dev_data->name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -540,7 +605,7 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
|
|||||||
int link_speed = 0;
|
int link_speed = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
|
ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
|
DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
|
||||||
dev->data->port_id, strerror(rte_errno));
|
dev->data->port_id, strerror(rte_errno));
|
||||||
@ -550,7 +615,7 @@ mlx5_link_update_unlocked_gset(struct rte_eth_dev *dev,
|
|||||||
dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
|
dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
|
||||||
(ifr.ifr_flags & IFF_RUNNING));
|
(ifr.ifr_flags & IFF_RUNNING));
|
||||||
ifr.ifr_data = (void *)&edata;
|
ifr.ifr_data = (void *)&edata;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING,
|
DRV_LOG(WARNING,
|
||||||
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
|
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GSET) failed: %s",
|
||||||
@ -611,7 +676,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
|
|||||||
uint64_t sc;
|
uint64_t sc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr);
|
ret = mlx5_ifreq(dev, SIOCGIFFLAGS, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
|
DRV_LOG(WARNING, "port %u ioctl(SIOCGIFFLAGS) failed: %s",
|
||||||
dev->data->port_id, strerror(rte_errno));
|
dev->data->port_id, strerror(rte_errno));
|
||||||
@ -621,7 +686,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
|
|||||||
dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
|
dev_link.link_status = ((ifr.ifr_flags & IFF_UP) &&
|
||||||
(ifr.ifr_flags & IFF_RUNNING));
|
(ifr.ifr_flags & IFF_RUNNING));
|
||||||
ifr.ifr_data = (void *)&gcmd;
|
ifr.ifr_data = (void *)&gcmd;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(DEBUG,
|
DRV_LOG(DEBUG,
|
||||||
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
|
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
|
||||||
@ -638,7 +703,7 @@ mlx5_link_update_unlocked_gs(struct rte_eth_dev *dev,
|
|||||||
|
|
||||||
*ecmd = gcmd;
|
*ecmd = gcmd;
|
||||||
ifr.ifr_data = (void *)ecmd;
|
ifr.ifr_data = (void *)ecmd;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(DEBUG,
|
DRV_LOG(DEBUG,
|
||||||
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
|
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GLINKSETTINGS)"
|
||||||
@ -801,7 +866,7 @@ mlx5_dev_get_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ifr.ifr_data = (void *)ðpause;
|
ifr.ifr_data = (void *)ðpause;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING,
|
DRV_LOG(WARNING,
|
||||||
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
|
"port %u ioctl(SIOCETHTOOL, ETHTOOL_GPAUSEPARAM) failed:"
|
||||||
@ -854,7 +919,7 @@ mlx5_dev_set_flow_ctrl(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
|
|||||||
ethpause.tx_pause = 1;
|
ethpause.tx_pause = 1;
|
||||||
else
|
else
|
||||||
ethpause.tx_pause = 0;
|
ethpause.tx_pause = 0;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING,
|
DRV_LOG(WARNING,
|
||||||
"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
|
"port %u ioctl(SIOCETHTOOL, ETHTOOL_SPAUSEPARAM)"
|
||||||
@ -1193,3 +1258,40 @@ mlx5_is_removed(struct rte_eth_dev *dev)
|
|||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get port ID list of mlx5 instances sharing a common device.
|
||||||
|
*
|
||||||
|
* @param[in] dev
|
||||||
|
* Device to look for.
|
||||||
|
* @param[out] port_list
|
||||||
|
* Result buffer for collected port IDs.
|
||||||
|
* @param port_list_n
|
||||||
|
* Maximum number of entries in result buffer. If 0, @p port_list can be
|
||||||
|
* NULL.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Number of matching instances regardless of the @p port_list_n
|
||||||
|
* parameter, 0 if none were found.
|
||||||
|
*/
|
||||||
|
unsigned int
|
||||||
|
mlx5_dev_to_port_id(const struct rte_device *dev, uint16_t *port_list,
|
||||||
|
unsigned int port_list_n)
|
||||||
|
{
|
||||||
|
uint16_t id;
|
||||||
|
unsigned int n = 0;
|
||||||
|
|
||||||
|
RTE_ETH_FOREACH_DEV(id) {
|
||||||
|
struct rte_eth_dev *ldev = &rte_eth_devices[id];
|
||||||
|
|
||||||
|
if (!ldev->device ||
|
||||||
|
!ldev->device->driver ||
|
||||||
|
strcmp(ldev->device->driver->name, MLX5_DRIVER_NAME) ||
|
||||||
|
ldev->device != dev)
|
||||||
|
continue;
|
||||||
|
if (n < port_list_n)
|
||||||
|
port_list[n] = id;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
@ -49,7 +49,7 @@ mlx5_get_mac(struct rte_eth_dev *dev, uint8_t (*mac)[ETHER_ADDR_LEN])
|
|||||||
struct ifreq request;
|
struct ifreq request;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request);
|
ret = mlx5_ifreq(dev, SIOCGIFHWADDR, &request, 0);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
|
memcpy(mac, request.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
|
||||||
|
@ -146,7 +146,7 @@ mlx5_read_dev_counters(struct rte_eth_dev *dev, uint64_t *stats)
|
|||||||
et_stats->cmd = ETHTOOL_GSTATS;
|
et_stats->cmd = ETHTOOL_GSTATS;
|
||||||
et_stats->n_stats = xstats_ctrl->stats_n;
|
et_stats->n_stats = xstats_ctrl->stats_n;
|
||||||
ifr.ifr_data = (caddr_t)et_stats;
|
ifr.ifr_data = (caddr_t)et_stats;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING,
|
DRV_LOG(WARNING,
|
||||||
"port %u unable to read statistic values from device",
|
"port %u unable to read statistic values from device",
|
||||||
@ -194,7 +194,7 @@ mlx5_ethtool_get_stats_n(struct rte_eth_dev *dev) {
|
|||||||
|
|
||||||
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
drvinfo.cmd = ETHTOOL_GDRVINFO;
|
||||||
ifr.ifr_data = (caddr_t)&drvinfo;
|
ifr.ifr_data = (caddr_t)&drvinfo;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING, "port %u unable to query number of statistics",
|
DRV_LOG(WARNING, "port %u unable to query number of statistics",
|
||||||
dev->data->port_id);
|
dev->data->port_id);
|
||||||
@ -244,7 +244,7 @@ mlx5_xstats_init(struct rte_eth_dev *dev)
|
|||||||
strings->string_set = ETH_SS_STATS;
|
strings->string_set = ETH_SS_STATS;
|
||||||
strings->len = dev_stats_n;
|
strings->len = dev_stats_n;
|
||||||
ifr.ifr_data = (caddr_t)strings;
|
ifr.ifr_data = (caddr_t)strings;
|
||||||
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr);
|
ret = mlx5_ifreq(dev, SIOCETHTOOL, &ifr, 1);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRV_LOG(WARNING, "port %u unable to get statistic names",
|
DRV_LOG(WARNING, "port %u unable to get statistic names",
|
||||||
dev->data->port_id);
|
dev->data->port_id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user