In non-SRIOV environment, VMDq RSS could be enabled by MRQC register. In theory, the queue number per pool could be 2 or 4, but only 2 queues are available due to HW limitation, the same limit also exist in Linux ixgbe driver.
Signed-off-by: Changchun Ouyang <changchun.ouyang at intel.com> --- lib/librte_ether/rte_ethdev.c | 40 +++++++++++++++++++ lib/librte_pmd_ixgbe/ixgbe_rxtx.c | 82 +++++++++++++++++++++++++++++++++------ 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index 024fe8b..6535715 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -933,6 +933,16 @@ rte_eth_dev_check_vf_rss_rxq_num(uint8_t port_id, uint16_t nb_rx_q) return 0; } +#define VMDQ_RSS_RX_QUEUE_NUM_MAX 4 + +static int +rte_eth_dev_check_vmdq_rss_rxq_num(__rte_unused uint8_t port_id, uint16_t nb_rx_q) +{ + if (nb_rx_q > VMDQ_RSS_RX_QUEUE_NUM_MAX) + return -EINVAL; + return 0; +} + static int rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, const struct rte_eth_conf *dev_conf) @@ -1093,6 +1103,36 @@ rte_eth_dev_check_mq_mode(uint8_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_q, return -EINVAL; } } + + if (dev_conf->rxmode.mq_mode == ETH_MQ_RX_VMDQ_RSS) { + uint32_t nb_queue_pools = + dev_conf->rx_adv_conf.vmdq_rx_conf.nb_queue_pools; + struct rte_eth_dev_info dev_info; + + rte_eth_dev_info_get(port_id, &dev_info); + dev->data->dev_conf.rxmode.mq_mode = ETH_MQ_RX_VMDQ_RSS; + if (nb_queue_pools == ETH_32_POOLS || nb_queue_pools == ETH_64_POOLS) + RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = + dev_info.max_rx_queues/nb_queue_pools; + else { + PMD_DEBUG_TRACE("ethdev port_id=%d VMDQ " + "nb_queue_pools=%d invalid " + "in VMDQ RSS\n" + port_id, + nb_queue_pools); + return -EINVAL; + } + + if (rte_eth_dev_check_vmdq_rss_rxq_num(port_id, + RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool) != 0) { + PMD_DEBUG_TRACE("ethdev port_id=%d" + " SRIOV active, invalid queue" + " number for VMDQ RSS, allowed" + " value are 1, 2 or 4\n", + port_id); + return -EINVAL; + } + } } return 0; } diff --git a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c index 57c9430..8eb0151 100644 --- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c +++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c @@ -3312,15 +3312,15 @@ void ixgbe_configure_dcb(struct rte_eth_dev *dev) } /* - * VMDq only support for 10 GbE NIC. + * Config pool for VMDq on 10 GbE NIC. */ static void -ixgbe_vmdq_rx_hw_configure(struct rte_eth_dev *dev) +ixgbe_vmdq_pool_configure(struct rte_eth_dev *dev) { struct rte_eth_vmdq_rx_conf *cfg; struct ixgbe_hw *hw; enum rte_eth_nb_pools num_pools; - uint32_t mrqc, vt_ctl, vlanctrl; + uint32_t vt_ctl, vlanctrl; uint32_t vmolr = 0; int i; @@ -3329,12 +3329,6 @@ ixgbe_vmdq_rx_hw_configure(struct rte_eth_dev *dev) cfg = &dev->data->dev_conf.rx_adv_conf.vmdq_rx_conf; num_pools = cfg->nb_queue_pools; - ixgbe_rss_disable(dev); - - /* MRQC: enable vmdq */ - mrqc = IXGBE_MRQC_VMDQEN; - IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); - /* PFVTCTL: turn on virtualisation and set the default pool */ vt_ctl = IXGBE_VT_CTL_VT_ENABLE | IXGBE_VT_CTL_REPLEN; if (cfg->enable_default_pool) @@ -3401,6 +3395,28 @@ ixgbe_vmdq_rx_hw_configure(struct rte_eth_dev *dev) } /* + * VMDq only support for 10 GbE NIC. + */ +static void +ixgbe_vmdq_rx_hw_configure(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw; + uint32_t mrqc; + + PMD_INIT_FUNC_TRACE(); + hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + ixgbe_rss_disable(dev); + + /* MRQC: enable vmdq */ + mrqc = IXGBE_MRQC_VMDQEN; + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + IXGBE_WRITE_FLUSH(hw); + + ixgbe_vmdq_pool_configure(dev); +} + +/* * ixgbe_dcb_config_tx_hw_config - Configure general VMDq TX parameters * @hw: pointer to hardware structure */ @@ -3505,6 +3521,41 @@ ixgbe_config_vf_rss(struct rte_eth_dev *dev) } static int +ixgbe_config_vmdq_rss(struct rte_eth_dev *dev) +{ + struct ixgbe_hw *hw; + uint32_t mrqc; + + ixgbe_rss_configure(dev); + + hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); + + /* MRQC: enable VMDQ RSS */ + mrqc = IXGBE_READ_REG(hw, IXGBE_MRQC); + mrqc &= ~IXGBE_MRQC_MRQE_MASK; + + switch (RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool) { + case 2: + mrqc |= IXGBE_MRQC_VMDQRSS64EN; + break; + + case 4: + mrqc |= IXGBE_MRQC_VMDQRSS32EN; + break; + + default: + PMD_INIT_LOG(ERR, "Invalid pool number in non-IOV mode with VMDQ RSS"); + return -EINVAL; + } + + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); + + ixgbe_vmdq_pool_configure(dev); + + return 0; +} + +static int ixgbe_config_vf_default(struct rte_eth_dev *dev) { struct ixgbe_hw *hw = @@ -3560,6 +3611,10 @@ ixgbe_dev_mq_rx_configure(struct rte_eth_dev *dev) ixgbe_vmdq_rx_hw_configure(dev); break; + case ETH_MQ_RX_VMDQ_RSS: + ixgbe_config_vmdq_rss(dev); + break; + case ETH_MQ_RX_NONE: /* if mq_mode is none, disable rss mode.*/ default: ixgbe_rss_disable(dev); @@ -4038,6 +4093,8 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) /* Setup RX queues */ for (i = 0; i < dev->data->nb_rx_queues; i++) { + uint32_t psrtype = 0; + rxq = dev->data->rx_queues[i]; /* @@ -4065,12 +4122,10 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) if (rx_conf->header_split) { if (hw->mac.type == ixgbe_mac_82599EB) { /* Must setup the PSRTYPE register */ - uint32_t psrtype; psrtype = IXGBE_PSRTYPE_TCPHDR | IXGBE_PSRTYPE_UDPHDR | IXGBE_PSRTYPE_IPV4HDR | IXGBE_PSRTYPE_IPV6HDR; - IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx), psrtype); } srrctl = ((rx_conf->split_hdr_size << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT) & @@ -4080,6 +4135,11 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) #endif srrctl = IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF; + /* Set RQPL for VMDQ RSS according to max Rx queue */ + psrtype |= (RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool >> 1) << + IXGBE_PSRTYPE_RQPL_SHIFT; + IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(rxq->reg_idx), psrtype); + /* Set if packets are dropped when no descriptors available */ if (rxq->drop_en) srrctl |= IXGBE_SRRCTL_DROP_EN; -- 1.8.4.2