nfp: add RSS

Signed-off-by: Alejandro Lucero <alejandro.lucero@netronome.com>
Signed-off-by: Rolf Neugebauer <rolf.neugebauer@netronome.com>
This commit is contained in:
Alejandro Lucero 2015-11-30 10:25:37 +00:00 committed by Thomas Monjalon
parent b812daadad
commit 934e4c60fb

View File

@ -1501,12 +1501,230 @@ nfp_net_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
return i; return i;
} }
/* 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)
{
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 "
"(%d)\n", reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
return -EINVAL;
}
/*
* Update Redirection Table. There are 128 8bit-entries which can be
* manage as 32 32bit-entries
*/
for (i = 0; i < reta_size; i += 4) {
/* Handling 4 RSS entries per loop */
idx = i / RTE_RETA_GROUP_SIZE;
shift = i % RTE_RETA_GROUP_SIZE;
mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF);
if (!mask)
continue;
reta = 0;
/* If all 4 entries were set, don't need read RETA register */
if (mask != 0xF)
reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + i);
for (j = 0; j < 4; j++) {
if (!(mask & (0x1 << j)))
continue;
if (mask != 0xF)
/* Clearing the entry bits */
reta &= ~(0xFF << (8 * j));
reta |= reta_conf[idx].reta[shift + j] << (8 * j);
}
nn_cfg_writel(hw, NFP_NET_CFG_RSS_ITBL + shift, reta);
}
update = NFP_NET_CFG_UPDATE_RSS;
if (nfp_net_reconfig(hw, hw->ctrl, update) < 0)
return -EIO;
return 0;
}
/* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */
static int
nfp_net_reta_query(struct rte_eth_dev *dev,
struct rte_eth_rss_reta_entry64 *reta_conf,
uint16_t reta_size)
{
uint8_t i, j, mask;
int idx, shift;
uint32_t reta;
struct nfp_net_hw *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 "
"(%d)\n", reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
return -EINVAL;
}
/*
* Reading Redirection Table. There are 128 8bit-entries which can be
* manage as 32 32bit-entries
*/
for (i = 0; i < reta_size; i += 4) {
/* Handling 4 RSS entries per loop */
idx = i / RTE_RETA_GROUP_SIZE;
shift = i % RTE_RETA_GROUP_SIZE;
mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF);
if (!mask)
continue;
reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + shift);
for (j = 0; j < 4; j++) {
if (!(mask & (0x1 << j)))
continue;
reta_conf->reta[shift + j] =
(uint8_t)((reta >> (8 * j)) & 0xF);
}
}
return 0;
}
static int
nfp_net_rss_hash_update(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf)
{
uint32_t update;
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 */
}
if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) {
RTE_LOG(ERR, PMD, "hash key too long\n");
return -EINVAL;
}
if (rss_hf & ETH_RSS_IPV4)
cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4 |
NFP_NET_CFG_RSS_IPV4_TCP |
NFP_NET_CFG_RSS_IPV4_UDP;
if (rss_hf & ETH_RSS_IPV6)
cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6 |
NFP_NET_CFG_RSS_IPV6_TCP |
NFP_NET_CFG_RSS_IPV6_UDP;
/* 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);
update = NFP_NET_CFG_UPDATE_RSS;
if (nfp_net_reconfig(hw, hw->ctrl, update) < 0)
return -EIO;
return 0;
}
static int
nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev,
struct rte_eth_rss_conf *rss_conf)
{
uint64_t rss_hf;
uint32_t cfg_rss_ctrl;
uint8_t key;
int i;
struct nfp_net_hw *hw;
hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!(hw->ctrl & NFP_NET_CFG_CTRL_RSS))
return -EINVAL;
rss_hf = rss_conf->rss_hf;
cfg_rss_ctrl = nn_cfg_readl(hw, NFP_NET_CFG_RSS_CTRL);
if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4)
rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP | ETH_RSS_NONFRAG_IPV4_UDP;
if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP)
rss_hf |= ETH_RSS_NONFRAG_IPV4_TCP;
if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP)
rss_hf |= ETH_RSS_NONFRAG_IPV6_TCP;
if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP)
rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP;
if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP)
rss_hf |= ETH_RSS_NONFRAG_IPV6_UDP;
if (cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6)
rss_hf |= ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP;
/* Reading the key size */
rss_conf->rss_key_len = nn_cfg_readl(hw, NFP_NET_CFG_RSS_KEY_SZ);
/* Reading the key byte a byte */
for (i = 0; i < rss_conf->rss_key_len; i++) {
key = nn_cfg_readb(hw, NFP_NET_CFG_RSS_KEY + i);
memcpy(&rss_conf->rss_key[i], &key, 1);
}
return 0;
}
/* Initialise and register driver with DPDK Application */ /* Initialise and register driver with DPDK Application */
static struct eth_dev_ops nfp_net_eth_dev_ops = { static struct eth_dev_ops nfp_net_eth_dev_ops = {
.dev_configure = nfp_net_configure, .dev_configure = nfp_net_configure,
.dev_start = nfp_net_start, .dev_start = nfp_net_start,
.dev_stop = nfp_net_stop, .dev_stop = nfp_net_stop,
.dev_close = nfp_net_close, .dev_close = nfp_net_close,
.reta_update = nfp_net_reta_update,
.reta_query = nfp_net_reta_query,
.rss_hash_update = nfp_net_rss_hash_update,
.rss_hash_conf_get = nfp_net_rss_hash_conf_get,
.rx_queue_setup = nfp_net_rx_queue_setup, .rx_queue_setup = nfp_net_rx_queue_setup,
.rx_queue_release = nfp_net_rx_queue_release, .rx_queue_release = nfp_net_rx_queue_release,
.rx_queue_count = nfp_net_rx_queue_count, .rx_queue_count = nfp_net_rx_queue_count,