mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 23:51:37 +00:00
ionic: Add RSS support
Add code to manipulate through ethtool the RSS configuration used by the NIC. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e470355bd9
commit
aa3198819b
@ -482,6 +482,74 @@ static int ionic_set_priv_flags(struct net_device *netdev, u32 priv_flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ionic_get_rxnfc(struct net_device *netdev,
|
||||
struct ethtool_rxnfc *info, u32 *rules)
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
int err = 0;
|
||||
|
||||
switch (info->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
info->data = lif->nxqs;
|
||||
break;
|
||||
default:
|
||||
netdev_err(netdev, "Command parameter %d is not supported\n",
|
||||
info->cmd);
|
||||
err = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32 ionic_get_rxfh_indir_size(struct net_device *netdev)
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
|
||||
return le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
|
||||
}
|
||||
|
||||
static u32 ionic_get_rxfh_key_size(struct net_device *netdev)
|
||||
{
|
||||
return IONIC_RSS_HASH_KEY_SIZE;
|
||||
}
|
||||
|
||||
static int ionic_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
unsigned int i, tbl_sz;
|
||||
|
||||
if (indir) {
|
||||
tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
|
||||
for (i = 0; i < tbl_sz; i++)
|
||||
indir[i] = lif->rss_ind_tbl[i];
|
||||
}
|
||||
|
||||
if (key)
|
||||
memcpy(key, lif->rss_hash_key, IONIC_RSS_HASH_KEY_SIZE);
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_TOP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ionic_set_rxfh(struct net_device *netdev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct ionic_lif *lif = netdev_priv(netdev);
|
||||
int err;
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = ionic_lif_rss_config(lif, lif->rss_types, key, indir);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ionic_get_module_info(struct net_device *netdev,
|
||||
struct ethtool_modinfo *modinfo)
|
||||
|
||||
@ -584,6 +652,11 @@ static const struct ethtool_ops ionic_ethtool_ops = {
|
||||
.get_sset_count = ionic_get_sset_count,
|
||||
.get_priv_flags = ionic_get_priv_flags,
|
||||
.set_priv_flags = ionic_set_priv_flags,
|
||||
.get_rxnfc = ionic_get_rxnfc,
|
||||
.get_rxfh_indir_size = ionic_get_rxfh_indir_size,
|
||||
.get_rxfh_key_size = ionic_get_rxfh_key_size,
|
||||
.get_rxfh = ionic_get_rxfh,
|
||||
.set_rxfh = ionic_set_rxfh,
|
||||
.get_module_info = ionic_get_module_info,
|
||||
.get_module_eeprom = ionic_get_module_eeprom,
|
||||
.get_pauseparam = ionic_get_pauseparam,
|
||||
|
@ -1315,6 +1315,65 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto,
|
||||
return ionic_adminq_post_wait(lif, &ctx);
|
||||
}
|
||||
|
||||
int ionic_lif_rss_config(struct ionic_lif *lif, const u16 types,
|
||||
const u8 *key, const u32 *indir)
|
||||
{
|
||||
struct ionic_admin_ctx ctx = {
|
||||
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
|
||||
.cmd.lif_setattr = {
|
||||
.opcode = IONIC_CMD_LIF_SETATTR,
|
||||
.attr = IONIC_LIF_ATTR_RSS,
|
||||
.rss.types = cpu_to_le16(types),
|
||||
.rss.addr = cpu_to_le64(lif->rss_ind_tbl_pa),
|
||||
},
|
||||
};
|
||||
unsigned int i, tbl_sz;
|
||||
|
||||
lif->rss_types = types;
|
||||
|
||||
if (key)
|
||||
memcpy(lif->rss_hash_key, key, IONIC_RSS_HASH_KEY_SIZE);
|
||||
|
||||
if (indir) {
|
||||
tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
|
||||
for (i = 0; i < tbl_sz; i++)
|
||||
lif->rss_ind_tbl[i] = indir[i];
|
||||
}
|
||||
|
||||
memcpy(ctx.cmd.lif_setattr.rss.key, lif->rss_hash_key,
|
||||
IONIC_RSS_HASH_KEY_SIZE);
|
||||
|
||||
return ionic_adminq_post_wait(lif, &ctx);
|
||||
}
|
||||
|
||||
static int ionic_lif_rss_init(struct ionic_lif *lif)
|
||||
{
|
||||
u8 rss_key[IONIC_RSS_HASH_KEY_SIZE];
|
||||
unsigned int tbl_sz;
|
||||
unsigned int i;
|
||||
|
||||
netdev_rss_key_fill(rss_key, IONIC_RSS_HASH_KEY_SIZE);
|
||||
|
||||
lif->rss_types = IONIC_RSS_TYPE_IPV4 |
|
||||
IONIC_RSS_TYPE_IPV4_TCP |
|
||||
IONIC_RSS_TYPE_IPV4_UDP |
|
||||
IONIC_RSS_TYPE_IPV6 |
|
||||
IONIC_RSS_TYPE_IPV6_TCP |
|
||||
IONIC_RSS_TYPE_IPV6_UDP;
|
||||
|
||||
/* Fill indirection table with 'default' values */
|
||||
tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
|
||||
for (i = 0; i < tbl_sz; i++)
|
||||
lif->rss_ind_tbl[i] = ethtool_rxfh_indir_default(i, lif->nxqs);
|
||||
|
||||
return ionic_lif_rss_config(lif, lif->rss_types, rss_key, NULL);
|
||||
}
|
||||
|
||||
static int ionic_lif_rss_deinit(struct ionic_lif *lif)
|
||||
{
|
||||
return ionic_lif_rss_config(lif, 0x0, NULL, NULL);
|
||||
}
|
||||
|
||||
static void ionic_txrx_disable(struct ionic_lif *lif)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -1413,6 +1472,9 @@ static int ionic_txrx_init(struct ionic_lif *lif)
|
||||
}
|
||||
}
|
||||
|
||||
if (lif->netdev->features & NETIF_F_RXHASH)
|
||||
ionic_lif_rss_init(lif);
|
||||
|
||||
ionic_set_rx_mode(lif->netdev);
|
||||
|
||||
return 0;
|
||||
@ -1558,6 +1620,7 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
|
||||
struct device *dev = ionic->dev;
|
||||
struct net_device *netdev;
|
||||
struct ionic_lif *lif;
|
||||
int tbl_sz;
|
||||
int err;
|
||||
|
||||
netdev = alloc_etherdev_mqs(sizeof(*lif),
|
||||
@ -1610,10 +1673,24 @@ static struct ionic_lif *ionic_lif_alloc(struct ionic *ionic, unsigned int index
|
||||
if (err)
|
||||
goto err_out_free_lif_info;
|
||||
|
||||
/* allocate rss indirection table */
|
||||
tbl_sz = le16_to_cpu(lif->ionic->ident.lif.eth.rss_ind_tbl_sz);
|
||||
lif->rss_ind_tbl_sz = sizeof(*lif->rss_ind_tbl) * tbl_sz;
|
||||
lif->rss_ind_tbl = dma_alloc_coherent(dev, lif->rss_ind_tbl_sz,
|
||||
&lif->rss_ind_tbl_pa,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!lif->rss_ind_tbl) {
|
||||
dev_err(dev, "Failed to allocate rss indirection table, aborting\n");
|
||||
goto err_out_free_qcqs;
|
||||
}
|
||||
|
||||
list_add_tail(&lif->list, &ionic->lifs);
|
||||
|
||||
return lif;
|
||||
|
||||
err_out_free_qcqs:
|
||||
ionic_qcqs_free(lif);
|
||||
err_out_free_lif_info:
|
||||
dma_free_coherent(dev, lif->info_sz, lif->info, lif->info_pa);
|
||||
lif->info = NULL;
|
||||
@ -1652,6 +1729,12 @@ static void ionic_lif_free(struct ionic_lif *lif)
|
||||
{
|
||||
struct device *dev = lif->ionic->dev;
|
||||
|
||||
/* free rss indirection table */
|
||||
dma_free_coherent(dev, lif->rss_ind_tbl_sz, lif->rss_ind_tbl,
|
||||
lif->rss_ind_tbl_pa);
|
||||
lif->rss_ind_tbl = NULL;
|
||||
lif->rss_ind_tbl_pa = 0;
|
||||
|
||||
/* free queues */
|
||||
ionic_qcqs_free(lif);
|
||||
ionic_lif_reset(lif);
|
||||
@ -1693,6 +1776,7 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
|
||||
clear_bit(IONIC_LIF_INITED, lif->state);
|
||||
|
||||
ionic_rx_filters_deinit(lif);
|
||||
ionic_lif_rss_deinit(lif);
|
||||
|
||||
napi_disable(&lif->adminqcq->napi);
|
||||
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
|
||||
|
@ -164,6 +164,12 @@ struct ionic_lif {
|
||||
dma_addr_t info_pa;
|
||||
u32 info_sz;
|
||||
|
||||
u16 rss_types;
|
||||
u8 rss_hash_key[IONIC_RSS_HASH_KEY_SIZE];
|
||||
u8 *rss_ind_tbl;
|
||||
dma_addr_t rss_ind_tbl_pa;
|
||||
u32 rss_ind_tbl_sz;
|
||||
|
||||
struct ionic_rx_filters rx_filters;
|
||||
struct ionic_deferred deferred;
|
||||
unsigned long *dbid_inuse;
|
||||
@ -198,6 +204,8 @@ void ionic_lifs_unregister(struct ionic *ionic);
|
||||
int ionic_lif_identify(struct ionic *ionic, u8 lif_type,
|
||||
union ionic_lif_identity *lif_ident);
|
||||
int ionic_lifs_size(struct ionic *ionic);
|
||||
int ionic_lif_rss_config(struct ionic_lif *lif, u16 types,
|
||||
const u8 *key, const u32 *indir);
|
||||
|
||||
int ionic_open(struct net_device *netdev);
|
||||
int ionic_stop(struct net_device *netdev);
|
||||
|
Loading…
Reference in New Issue
Block a user