#include <rte_common.h>
#include <rte_log.h>
#include <rte_debug.h>
-#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
#include <rte_ethdev_pci.h>
#include <rte_dev.h>
#include <rte_ether.h>
static uint16_t nfp_net_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
uint16_t nb_pkts);
+static int nfp_net_rss_config_default(struct rte_eth_dev *dev);
+static int nfp_net_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+static int nfp_net_rss_reta_write(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size);
+static int nfp_net_rss_hash_write(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf);
+
/*
* The offset of the queue controller queues in the PCIe Target. These
* happen to be at the same offset on the NFP6000 and the NFP3200 so
nn_writeq(rte_cpu_to_le_64(val), hw->ctrl_bar + off);
}
-/*
- * Atomically reads link status information from global structure rte_eth_dev.
- *
- * @param dev
- * - Pointer to the structure rte_eth_dev to read from.
- * - Pointer to the buffer to be saved with the link status.
- *
- * @return
- * - On success, zero.
- * - On failure, negative value.
- */
-static inline int
-nfp_net_dev_atomic_read_link_status(struct rte_eth_dev *dev,
- struct rte_eth_link *link)
-{
- struct rte_eth_link *dst = link;
- struct rte_eth_link *src = &dev->data->dev_link;
-
- if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
- *(uint64_t *)src) == 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Atomically writes the link status information into global
- * structure rte_eth_dev.
- *
- * @param dev
- * - Pointer to the structure rte_eth_dev to read from.
- * - Pointer to the buffer to be saved with the link status.
- *
- * @return
- * - On success, zero.
- * - On failure, negative value.
- */
-static inline int
-nfp_net_dev_atomic_write_link_status(struct rte_eth_dev *dev,
- struct rte_eth_link *link)
-{
- struct rte_eth_link *dst = &dev->data->dev_link;
- struct rte_eth_link *src = link;
-
- if (rte_atomic64_cmpset((uint64_t *)dst, *(uint64_t *)dst,
- *(uint64_t *)src) == 0)
- return -1;
-
- return 0;
-}
-
static void
nfp_net_rx_queue_release_mbufs(struct nfp_net_rxq *rxq)
{
}
if (rxmode->jumbo_frame)
- /* this is handled in rte_eth_dev_configure */
+ hw->mtu = rxmode->max_rx_pkt_len;
- if (rxmode->hw_strip_crc) {
- PMD_INIT_LOG(INFO, "strip CRC not supported");
- return -EINVAL;
- }
+ if (!rxmode->hw_strip_crc)
+ PMD_INIT_LOG(INFO, "HW does strip CRC and it is not configurable");
if (rxmode->enable_scatter) {
PMD_INIT_LOG(INFO, "Scatter not supported");
{
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
+ struct rte_eth_conf *dev_conf;
+ struct rte_eth_rxmode *rxmode;
uint32_t new_ctrl, update = 0;
struct nfp_net_hw *hw;
uint32_t intr_vector;
rte_intr_enable(intr_handle);
+ dev_conf = &dev->data->dev_conf;
+ rxmode = &dev_conf->rxmode;
+
+ /* Checking RX mode */
+ if (rxmode->mq_mode & ETH_MQ_RX_RSS) {
+ if (hw->cap & NFP_NET_CFG_CTRL_RSS) {
+ if (!nfp_net_rss_config_default(dev))
+ update |= NFP_NET_CFG_UPDATE_RSS;
+ } else {
+ PMD_INIT_LOG(INFO, "RSS not supported");
+ return -EINVAL;
+ }
+ }
/* Enable device */
new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_ENABLE;
nfp_net_link_update(struct rte_eth_dev *dev, __rte_unused int wait_to_complete)
{
struct nfp_net_hw *hw;
- struct rte_eth_link link, old;
+ struct rte_eth_link link;
uint32_t nn_link_status;
+ int ret;
static const uint32_t ls_to_ethtool[] = {
[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = ETH_SPEED_NUM_NONE,
hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- memset(&old, 0, sizeof(old));
- nfp_net_dev_atomic_read_link_status(dev, &old);
-
nn_link_status = nn_cfg_readl(hw, NFP_NET_CFG_STS);
memset(&link, 0, sizeof(struct rte_eth_link));
else
link.link_speed = ls_to_ethtool[nn_link_status];
- if (old.link_status != link.link_status) {
- nfp_net_dev_atomic_write_link_status(dev, &link);
+ ret = rte_eth_linkstatus_set(dev, &link);
+ if (ret == 0) {
if (link.link_status)
PMD_DRV_LOG(INFO, "NIC Link is Up\n");
else
PMD_DRV_LOG(INFO, "NIC Link is Down\n");
- return 0;
}
-
- return -1;
+ return ret;
}
static int
dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
- dev_info->speed_capa = ETH_SPEED_NUM_1G | ETH_LINK_SPEED_10G |
- ETH_SPEED_NUM_25G | ETH_SPEED_NUM_40G |
- ETH_SPEED_NUM_50G | ETH_LINK_SPEED_100G;
+ dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G |
+ ETH_LINK_SPEED_25G | ETH_LINK_SPEED_40G |
+ ETH_LINK_SPEED_50G | ETH_LINK_SPEED_100G;
if (hw->cap & NFP_NET_CFG_CTRL_LSO)
dev_info->tx_offload_capa |= DEV_TX_OFFLOAD_TCP_TSO;
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_eth_link link;
- memset(&link, 0, sizeof(link));
- nfp_net_dev_atomic_read_link_status(dev, &link);
+ rte_eth_linkstatus_get(dev, &link);
if (link.link_status)
RTE_LOG(INFO, PMD, "Port %d: Link Up - speed %u Mbps - %s\n",
dev->data->port_id, link.link_speed,
PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!\n");
- /* get the link status */
- memset(&link, 0, sizeof(link));
- nfp_net_dev_atomic_read_link_status(dev, &link);
+ rte_eth_linkstatus_get(dev, &link);
nfp_net_link_update(dev, 0);
struct rte_eth_dev *dev = (struct rte_eth_dev *)param;
nfp_net_link_update(dev, 0);
- _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL, NULL);
+ _rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
nfp_net_dev_link_status_print(dev);
if ((mtu < ETHER_MIN_MTU) || ((uint32_t)mtu > hw->max_mtu))
return -EINVAL;
+ /* mtu setting is forbidden if port is started */
+ if (dev->data->dev_started) {
+ PMD_DRV_LOG(ERR, "port %d must be stopped before configuration",
+ dev->data->port_id);
+ return -EBUSY;
+ }
+
/* switch to jumbo mode if needed */
if ((uint32_t)mtu > ETHER_MAX_LEN)
dev->data->dev_conf.rxmode.jumbo_frame = 1;
break;
}
+ rxds = &rxq->rxds[rxq->rd_p];
+ if ((rxds->rxd.meta_len_dd & PCIE_DESC_RX_DD) == 0)
+ break;
+
/*
* Memory barrier to ensure that we won't do other
* reads before the DD bit.
*/
rte_rmb();
- rxds = &rxq->rxds[rxq->rd_p];
- if ((rxds->rxd.meta_len_dd & PCIE_DESC_RX_DD) == 0)
- break;
-
/*
* We got a packet. Let's alloc a new mbuff for refilling the
* free descriptor ring as soon as possible
mb->nb_segs = 1;
mb->next = NULL;
+ mb->port = rxq->port_id;
+
/* Checking the RSS flag */
nfp_net_set_hash(rxq, rxds, mb);
return ret;
}
-/* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
static int
-nfp_net_reta_update(struct rte_eth_dev *dev,
+nfp_net_rss_reta_write(struct rte_eth_dev *dev,
struct rte_eth_rss_reta_entry64 *reta_conf,
uint16_t reta_size)
{
uint32_t reta, mask;
int i, j;
int idx, shift;
- uint32_t update;
struct nfp_net_hw *hw =
NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- if (!(hw->ctrl & NFP_NET_CFG_CTRL_RSS))
- return -EINVAL;
-
if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
RTE_LOG(ERR, PMD, "The size of hash lookup table configured "
"(%d) doesn't match the number hardware can supported "
nn_cfg_writel(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift,
reta);
}
+ return 0;
+}
+
+/* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
+static int
+nfp_net_reta_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_reta_entry64 *reta_conf,
+ uint16_t reta_size)
+{
+ struct nfp_net_hw *hw =
+ NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ uint32_t update;
+ int ret;
+
+ if (!(hw->ctrl & NFP_NET_CFG_CTRL_RSS))
+ return -EINVAL;
+
+ ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size);
+ if (ret != 0)
+ return ret;
update = NFP_NET_CFG_UPDATE_RSS;
}
static int
-nfp_net_rss_hash_update(struct rte_eth_dev *dev,
+nfp_net_rss_hash_write(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf)
{
- uint32_t update;
+ struct nfp_net_hw *hw;
+ uint64_t rss_hf;
uint32_t cfg_rss_ctrl = 0;
uint8_t key;
- uint64_t rss_hf;
int i;
- struct nfp_net_hw *hw;
hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- rss_hf = rss_conf->rss_hf;
-
- /* Checking if RSS is enabled */
- if (!(hw->ctrl & NFP_NET_CFG_CTRL_RSS)) {
- if (rss_hf != 0) { /* Enable RSS? */
- RTE_LOG(ERR, PMD, "RSS unsupported\n");
- return -EINVAL;
- }
- return 0; /* Nothing to do */
+ /* Writing the key byte a byte */
+ for (i = 0; i < rss_conf->rss_key_len; i++) {
+ memcpy(&key, &rss_conf->rss_key[i], 1);
+ nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY + i, key);
}
- if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) {
- RTE_LOG(ERR, PMD, "hash key too long\n");
- return -EINVAL;
- }
+ rss_hf = rss_conf->rss_hf;
if (rss_hf & ETH_RSS_IPV4)
cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4 |
/* configuring where to apply the RSS hash */
nn_cfg_writel(hw, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl);
- /* Writing the key byte a byte */
- for (i = 0; i < rss_conf->rss_key_len; i++) {
- memcpy(&key, &rss_conf->rss_key[i], 1);
- nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY + i, key);
- }
-
/* Writing the key size */
nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len);
+ return 0;
+}
+
+static int
+nfp_net_rss_hash_update(struct rte_eth_dev *dev,
+ struct rte_eth_rss_conf *rss_conf)
+{
+ uint32_t update;
+ uint64_t rss_hf;
+ struct nfp_net_hw *hw;
+
+ hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ rss_hf = rss_conf->rss_hf;
+
+ /* Checking if RSS is enabled */
+ if (!(hw->ctrl & NFP_NET_CFG_CTRL_RSS)) {
+ if (rss_hf != 0) { /* Enable RSS? */
+ RTE_LOG(ERR, PMD, "RSS unsupported\n");
+ return -EINVAL;
+ }
+ return 0; /* Nothing to do */
+ }
+
+ if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) {
+ RTE_LOG(ERR, PMD, "hash key too long\n");
+ return -EINVAL;
+ }
+
+ nfp_net_rss_hash_write(dev, rss_conf);
+
update = NFP_NET_CFG_UPDATE_RSS;
if (nfp_net_reconfig(hw, hw->ctrl, update) < 0)
return 0;
}
+static int
+nfp_net_rss_config_default(struct rte_eth_dev *dev)
+{
+ struct rte_eth_conf *dev_conf;
+ struct rte_eth_rss_conf rss_conf;
+ struct rte_eth_rss_reta_entry64 nfp_reta_conf[2];
+ uint16_t rx_queues = dev->data->nb_rx_queues;
+ uint16_t queue;
+ int i, j, ret;
+
+ RTE_LOG(INFO, PMD, "setting default RSS conf for %u queues\n",
+ rx_queues);
+
+ nfp_reta_conf[0].mask = ~0x0;
+ nfp_reta_conf[1].mask = ~0x0;
+
+ queue = 0;
+ for (i = 0; i < 0x40; i += 8) {
+ for (j = i; j < (i + 8); j++) {
+ nfp_reta_conf[0].reta[j] = queue;
+ nfp_reta_conf[1].reta[j] = queue++;
+ queue %= rx_queues;
+ }
+ }
+ ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80);
+ if (ret != 0)
+ return ret;
+
+ dev_conf = &dev->data->dev_conf;
+ if (!dev_conf) {
+ RTE_LOG(INFO, PMD, "wrong rss conf");
+ return -EINVAL;
+ }
+ rss_conf = dev_conf->rx_adv_conf.rss_conf;
+
+ ret = nfp_net_rss_hash_write(dev, &rss_conf);
+
+ return ret;
+}
+
+
/* Initialise and register driver with DPDK Application */
static const struct eth_dev_ops nfp_net_eth_dev_ops = {
.dev_configure = nfp_net_configure,
return ret;
}
+int nfp_logtype_init;
+int nfp_logtype_driver;
+
static const struct rte_pci_id pci_id_nfp_pf_net_map[] = {
{
RTE_PCI_DEVICE(PCI_VENDOR_ID_NETRONOME,
RTE_PMD_REGISTER_KMOD_DEP(net_nfp_pf, "* igb_uio | uio_pci_generic | vfio");
RTE_PMD_REGISTER_KMOD_DEP(net_nfp_vf, "* igb_uio | uio_pci_generic | vfio");
+RTE_INIT(nfp_init_log);
+static void
+nfp_init_log(void)
+{
+ nfp_logtype_init = rte_log_register("pmd.net.nfp.init");
+ if (nfp_logtype_init >= 0)
+ rte_log_set_level(nfp_logtype_init, RTE_LOG_NOTICE);
+ nfp_logtype_driver = rte_log_register("pmd.net.nfp.driver");
+ if (nfp_logtype_driver >= 0)
+ rte_log_set_level(nfp_logtype_driver, RTE_LOG_NOTICE);
+}
/*
* Local variables:
* c-file-style: "Linux"