mlx5: add device configure/start/stop
This commit adds the remaining missing callbacks to make mlx5 usable. Like mlx4, device start and stop are implemented on top of MAC RX flows. Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com> Signed-off-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com> Signed-off-by: Francesco Santoro <francesco.santoro@6wind.com> Signed-off-by: Didier Pallard <didier.pallard@6wind.com>
This commit is contained in:
parent
3318aef7e7
commit
e60fbd5b24
@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5.c
|
|||||||
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rxq.c
|
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rxq.c
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_txq.c
|
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_txq.c
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rxtx.c
|
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_rxtx.c
|
||||||
|
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_trigger.c
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_ethdev.c
|
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_ethdev.c
|
||||||
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mac.c
|
SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5_mac.c
|
||||||
|
|
||||||
|
@ -129,7 +129,11 @@ mlx5_dev_close(struct rte_eth_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const struct eth_dev_ops mlx5_dev_ops = {
|
static const struct eth_dev_ops mlx5_dev_ops = {
|
||||||
|
.dev_configure = mlx5_dev_configure,
|
||||||
|
.dev_start = mlx5_dev_start,
|
||||||
|
.dev_stop = mlx5_dev_stop,
|
||||||
.dev_close = mlx5_dev_close,
|
.dev_close = mlx5_dev_close,
|
||||||
|
.dev_infos_get = mlx5_dev_infos_get,
|
||||||
.rx_queue_setup = mlx5_rx_queue_setup,
|
.rx_queue_setup = mlx5_rx_queue_setup,
|
||||||
.tx_queue_setup = mlx5_tx_queue_setup,
|
.tx_queue_setup = mlx5_tx_queue_setup,
|
||||||
.rx_queue_release = mlx5_rx_queue_release,
|
.rx_queue_release = mlx5_rx_queue_release,
|
||||||
|
@ -160,6 +160,8 @@ int priv_get_ifname(const struct priv *, char (*)[IF_NAMESIZE]);
|
|||||||
int priv_ifreq(const struct priv *, int req, struct ifreq *);
|
int priv_ifreq(const struct priv *, int req, struct ifreq *);
|
||||||
int priv_get_mtu(struct priv *, uint16_t *);
|
int priv_get_mtu(struct priv *, uint16_t *);
|
||||||
int priv_set_flags(struct priv *, unsigned int, unsigned int);
|
int priv_set_flags(struct priv *, unsigned int, unsigned int);
|
||||||
|
int mlx5_dev_configure(struct rte_eth_dev *);
|
||||||
|
void mlx5_dev_infos_get(struct rte_eth_dev *, struct rte_eth_dev_info *);
|
||||||
int mlx5_ibv_device_to_pci_addr(const struct ibv_device *,
|
int mlx5_ibv_device_to_pci_addr(const struct ibv_device *,
|
||||||
struct rte_pci_addr *);
|
struct rte_pci_addr *);
|
||||||
|
|
||||||
@ -174,4 +176,9 @@ int priv_mac_addr_add(struct priv *, unsigned int,
|
|||||||
void mlx5_mac_addr_add(struct rte_eth_dev *, struct ether_addr *, uint32_t,
|
void mlx5_mac_addr_add(struct rte_eth_dev *, struct ether_addr *, uint32_t,
|
||||||
uint32_t);
|
uint32_t);
|
||||||
|
|
||||||
|
/* mlx5_trigger.c */
|
||||||
|
|
||||||
|
int mlx5_dev_start(struct rte_eth_dev *);
|
||||||
|
void mlx5_dev_stop(struct rte_eth_dev *);
|
||||||
|
|
||||||
#endif /* RTE_PMD_MLX5_H_ */
|
#endif /* RTE_PMD_MLX5_H_ */
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -58,6 +59,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mlx5.h"
|
#include "mlx5.h"
|
||||||
|
#include "mlx5_rxtx.h"
|
||||||
#include "mlx5_utils.h"
|
#include "mlx5_utils.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -369,6 +371,152 @@ priv_set_flags(struct priv *priv, unsigned int keep, unsigned int flags)
|
|||||||
return priv_set_sysfs_ulong(priv, "flags", tmp);
|
return priv_set_sysfs_ulong(priv, "flags", tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ethernet device configuration.
|
||||||
|
*
|
||||||
|
* Prepare the driver for a given number of TX and RX queues.
|
||||||
|
* Allocate parent RSS queue when several RX queues are requested.
|
||||||
|
*
|
||||||
|
* @param dev
|
||||||
|
* Pointer to Ethernet device structure.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 0 on success, errno value on failure.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
dev_configure(struct rte_eth_dev *dev)
|
||||||
|
{
|
||||||
|
struct priv *priv = dev->data->dev_private;
|
||||||
|
unsigned int rxqs_n = dev->data->nb_rx_queues;
|
||||||
|
unsigned int txqs_n = dev->data->nb_tx_queues;
|
||||||
|
unsigned int tmp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
priv->rxqs = (void *)dev->data->rx_queues;
|
||||||
|
priv->txqs = (void *)dev->data->tx_queues;
|
||||||
|
if (txqs_n != priv->txqs_n) {
|
||||||
|
INFO("%p: TX queues number update: %u -> %u",
|
||||||
|
(void *)dev, priv->txqs_n, txqs_n);
|
||||||
|
priv->txqs_n = txqs_n;
|
||||||
|
}
|
||||||
|
if (rxqs_n == priv->rxqs_n)
|
||||||
|
return 0;
|
||||||
|
INFO("%p: RX queues number update: %u -> %u",
|
||||||
|
(void *)dev, priv->rxqs_n, rxqs_n);
|
||||||
|
/* If RSS is enabled, disable it first. */
|
||||||
|
if (priv->rss) {
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
/* Only if there are no remaining child RX queues. */
|
||||||
|
for (i = 0; (i != priv->rxqs_n); ++i)
|
||||||
|
if ((*priv->rxqs)[i] != NULL)
|
||||||
|
return EINVAL;
|
||||||
|
rxq_cleanup(&priv->rxq_parent);
|
||||||
|
priv->rss = 0;
|
||||||
|
priv->rxqs_n = 0;
|
||||||
|
}
|
||||||
|
if (rxqs_n <= 1) {
|
||||||
|
/* Nothing else to do. */
|
||||||
|
priv->rxqs_n = rxqs_n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Allocate a new RSS parent queue if supported by hardware. */
|
||||||
|
if (!priv->hw_rss) {
|
||||||
|
ERROR("%p: only a single RX queue can be configured when"
|
||||||
|
" hardware doesn't support RSS",
|
||||||
|
(void *)dev);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
/* Fail if hardware doesn't support that many RSS queues. */
|
||||||
|
if (rxqs_n >= priv->max_rss_tbl_sz) {
|
||||||
|
ERROR("%p: only %u RX queues can be configured for RSS",
|
||||||
|
(void *)dev, priv->max_rss_tbl_sz);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
priv->rss = 1;
|
||||||
|
tmp = priv->rxqs_n;
|
||||||
|
priv->rxqs_n = rxqs_n;
|
||||||
|
ret = rxq_setup(dev, &priv->rxq_parent, 0, 0, NULL, NULL);
|
||||||
|
if (!ret)
|
||||||
|
return 0;
|
||||||
|
/* Failure, rollback. */
|
||||||
|
priv->rss = 0;
|
||||||
|
priv->rxqs_n = tmp;
|
||||||
|
assert(ret > 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DPDK callback for Ethernet device configuration.
|
||||||
|
*
|
||||||
|
* @param dev
|
||||||
|
* Pointer to Ethernet device structure.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 0 on success, negative errno value on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mlx5_dev_configure(struct rte_eth_dev *dev)
|
||||||
|
{
|
||||||
|
struct priv *priv = dev->data->dev_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
priv_lock(priv);
|
||||||
|
ret = dev_configure(dev);
|
||||||
|
assert(ret >= 0);
|
||||||
|
priv_unlock(priv);
|
||||||
|
return -ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DPDK callback to get information about the device.
|
||||||
|
*
|
||||||
|
* @param dev
|
||||||
|
* Pointer to Ethernet device structure.
|
||||||
|
* @param[out] info
|
||||||
|
* Info structure output buffer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
|
||||||
|
{
|
||||||
|
struct priv *priv = dev->data->dev_private;
|
||||||
|
unsigned int max;
|
||||||
|
char ifname[IF_NAMESIZE];
|
||||||
|
|
||||||
|
priv_lock(priv);
|
||||||
|
/* FIXME: we should ask the device for these values. */
|
||||||
|
info->min_rx_bufsize = 32;
|
||||||
|
info->max_rx_pktlen = 65536;
|
||||||
|
/*
|
||||||
|
* Since we need one CQ per QP, the limit is the minimum number
|
||||||
|
* between the two values.
|
||||||
|
*/
|
||||||
|
max = ((priv->device_attr.max_cq > priv->device_attr.max_qp) ?
|
||||||
|
priv->device_attr.max_qp : priv->device_attr.max_cq);
|
||||||
|
/* If max >= 65535 then max = 0, max_rx_queues is uint16_t. */
|
||||||
|
if (max >= 65535)
|
||||||
|
max = 65535;
|
||||||
|
info->max_rx_queues = max;
|
||||||
|
info->max_tx_queues = max;
|
||||||
|
/* Last array entry is reserved for broadcast. */
|
||||||
|
info->max_mac_addrs = (RTE_DIM(priv->mac) - 1);
|
||||||
|
info->rx_offload_capa =
|
||||||
|
(priv->hw_csum ?
|
||||||
|
(DEV_RX_OFFLOAD_IPV4_CKSUM |
|
||||||
|
DEV_RX_OFFLOAD_UDP_CKSUM |
|
||||||
|
DEV_RX_OFFLOAD_TCP_CKSUM) :
|
||||||
|
0);
|
||||||
|
info->tx_offload_capa =
|
||||||
|
(priv->hw_csum ?
|
||||||
|
(DEV_TX_OFFLOAD_IPV4_CKSUM |
|
||||||
|
DEV_TX_OFFLOAD_UDP_CKSUM |
|
||||||
|
DEV_TX_OFFLOAD_TCP_CKSUM) :
|
||||||
|
0);
|
||||||
|
if (priv_get_ifname(priv, &ifname) == 0)
|
||||||
|
info->if_index = if_nametoindex(ifname);
|
||||||
|
priv_unlock(priv);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get PCI information from struct ibv_device.
|
* Get PCI information from struct ibv_device.
|
||||||
*
|
*
|
||||||
|
146
drivers/net/mlx5/mlx5_trigger.c
Normal file
146
drivers/net/mlx5/mlx5_trigger.c
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*-
|
||||||
|
* BSD LICENSE
|
||||||
|
*
|
||||||
|
* Copyright 2015 6WIND S.A.
|
||||||
|
* Copyright 2015 Mellanox.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
* * Neither the name of 6WIND S.A. nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* DPDK headers don't like -pedantic. */
|
||||||
|
#ifdef PEDANTIC
|
||||||
|
#pragma GCC diagnostic ignored "-pedantic"
|
||||||
|
#endif
|
||||||
|
#include <rte_ether.h>
|
||||||
|
#include <rte_ethdev.h>
|
||||||
|
#ifdef PEDANTIC
|
||||||
|
#pragma GCC diagnostic error "-pedantic"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mlx5.h"
|
||||||
|
#include "mlx5_rxtx.h"
|
||||||
|
#include "mlx5_utils.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DPDK callback to start the device.
|
||||||
|
*
|
||||||
|
* Simulate device start by attaching all configured flows.
|
||||||
|
*
|
||||||
|
* @param dev
|
||||||
|
* Pointer to Ethernet device structure.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* 0 on success, negative errno value on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
mlx5_dev_start(struct rte_eth_dev *dev)
|
||||||
|
{
|
||||||
|
struct priv *priv = dev->data->dev_private;
|
||||||
|
unsigned int i = 0;
|
||||||
|
unsigned int r;
|
||||||
|
struct rxq *rxq;
|
||||||
|
|
||||||
|
priv_lock(priv);
|
||||||
|
if (priv->started) {
|
||||||
|
priv_unlock(priv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
DEBUG("%p: attaching configured flows to all RX queues", (void *)dev);
|
||||||
|
priv->started = 1;
|
||||||
|
if (priv->rss) {
|
||||||
|
rxq = &priv->rxq_parent;
|
||||||
|
r = 1;
|
||||||
|
} else {
|
||||||
|
rxq = (*priv->rxqs)[0];
|
||||||
|
r = priv->rxqs_n;
|
||||||
|
}
|
||||||
|
/* Iterate only once when RSS is enabled. */
|
||||||
|
do {
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Ignore nonexistent RX queues. */
|
||||||
|
if (rxq == NULL)
|
||||||
|
continue;
|
||||||
|
ret = rxq_mac_addrs_add(rxq);
|
||||||
|
if (!ret)
|
||||||
|
continue;
|
||||||
|
WARN("%p: QP flow attachment failed: %s",
|
||||||
|
(void *)dev, strerror(ret));
|
||||||
|
/* Rollback. */
|
||||||
|
while (i != 0) {
|
||||||
|
rxq = (*priv->rxqs)[--i];
|
||||||
|
if (rxq != NULL) {
|
||||||
|
rxq_mac_addrs_del(rxq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
priv->started = 0;
|
||||||
|
priv_unlock(priv);
|
||||||
|
return -ret;
|
||||||
|
} while ((--r) && ((rxq = (*priv->rxqs)[++i]), i));
|
||||||
|
priv_unlock(priv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DPDK callback to stop the device.
|
||||||
|
*
|
||||||
|
* Simulate device stop by detaching all configured flows.
|
||||||
|
*
|
||||||
|
* @param dev
|
||||||
|
* Pointer to Ethernet device structure.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
mlx5_dev_stop(struct rte_eth_dev *dev)
|
||||||
|
{
|
||||||
|
struct priv *priv = dev->data->dev_private;
|
||||||
|
unsigned int i = 0;
|
||||||
|
unsigned int r;
|
||||||
|
struct rxq *rxq;
|
||||||
|
|
||||||
|
priv_lock(priv);
|
||||||
|
if (!priv->started) {
|
||||||
|
priv_unlock(priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DEBUG("%p: detaching flows from all RX queues", (void *)dev);
|
||||||
|
priv->started = 0;
|
||||||
|
if (priv->rss) {
|
||||||
|
rxq = &priv->rxq_parent;
|
||||||
|
r = 1;
|
||||||
|
} else {
|
||||||
|
rxq = (*priv->rxqs)[0];
|
||||||
|
r = priv->rxqs_n;
|
||||||
|
}
|
||||||
|
/* Iterate only once when RSS is enabled. */
|
||||||
|
do {
|
||||||
|
/* Ignore nonexistent RX queues. */
|
||||||
|
if (rxq == NULL)
|
||||||
|
continue;
|
||||||
|
rxq_mac_addrs_del(rxq);
|
||||||
|
} while ((--r) && ((rxq = (*priv->rxqs)[++i]), i));
|
||||||
|
priv_unlock(priv);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user