net: mvpp2: RSS indirection table support
This patch adds the RSS indirection table support, allowing to use the ethtool -x and -X options to dump and set this table. Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com> [Maxime: Small warning fixes, use one table per port] Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
a27a254c26
commit
8179642b52
|
@ -801,6 +801,9 @@ struct mvpp2_port {
|
|||
bool has_tx_irqs;
|
||||
|
||||
u32 tx_time_coal;
|
||||
|
||||
/* RSS indirection table */
|
||||
u32 indir[MVPP22_RSS_TABLE_ENTRIES];
|
||||
};
|
||||
|
||||
/* The mvpp2_tx_desc and mvpp2_rx_desc structures describe the
|
||||
|
|
|
@ -107,6 +107,20 @@ void mvpp2_cls_oversize_rxq_set(struct mvpp2_port *port)
|
|||
mvpp2_write(port->priv, MVPP2_CLS_SWFWD_PCTRL_REG, val);
|
||||
}
|
||||
|
||||
void mvpp22_rss_fill_table(struct mvpp2_port *port, u32 table)
|
||||
{
|
||||
struct mvpp2 *priv = port->priv;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
|
||||
u32 sel = MVPP22_RSS_INDEX_TABLE(table) |
|
||||
MVPP22_RSS_INDEX_TABLE_ENTRY(i);
|
||||
mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
|
||||
|
||||
mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY, port->indir[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void mvpp22_init_rss(struct mvpp2_port *port)
|
||||
{
|
||||
struct mvpp2 *priv = port->priv;
|
||||
|
@ -129,12 +143,8 @@ void mvpp22_init_rss(struct mvpp2_port *port)
|
|||
/* Configure the first table to evenly distribute the packets across
|
||||
* real Rx Queues. The table entries map a hash to a port Rx Queue.
|
||||
*/
|
||||
for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++) {
|
||||
u32 sel = MVPP22_RSS_INDEX_TABLE(port->id) |
|
||||
MVPP22_RSS_INDEX_TABLE_ENTRY(i);
|
||||
mvpp2_write(priv, MVPP22_RSS_INDEX, sel);
|
||||
|
||||
mvpp2_write(priv, MVPP22_RSS_TABLE_ENTRY, i % port->nrxqs);
|
||||
}
|
||||
for (i = 0; i < MVPP22_RSS_TABLE_ENTRIES; i++)
|
||||
port->indir[i] = ethtool_rxfh_indir_default(i, port->nrxqs);
|
||||
|
||||
mvpp22_rss_fill_table(port, port->id);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,8 @@ struct mvpp2_cls_lookup_entry {
|
|||
u32 data;
|
||||
};
|
||||
|
||||
void mvpp22_rss_fill_table(struct mvpp2_port *port, u32 table);
|
||||
|
||||
void mvpp22_init_rss(struct mvpp2_port *port);
|
||||
|
||||
void mvpp2_cls_init(struct mvpp2 *priv);
|
||||
|
|
|
@ -3821,6 +3821,71 @@ static int mvpp2_ethtool_set_link_ksettings(struct net_device *dev,
|
|||
return phylink_ethtool_ksettings_set(port->phylink, cmd);
|
||||
}
|
||||
|
||||
static int mvpp2_ethtool_get_rxnfc(struct net_device *dev,
|
||||
struct ethtool_rxnfc *info, u32 *rules)
|
||||
{
|
||||
struct mvpp2_port *port = netdev_priv(dev);
|
||||
|
||||
if (!mvpp22_rss_is_supported())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (info->cmd) {
|
||||
case ETHTOOL_GRXRINGS:
|
||||
info->data = port->nrxqs;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 mvpp2_ethtool_get_rxfh_indir_size(struct net_device *dev)
|
||||
{
|
||||
return mvpp22_rss_is_supported() ? MVPP22_RSS_TABLE_ENTRIES : 0;
|
||||
}
|
||||
|
||||
static int mvpp2_ethtool_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
|
||||
u8 *hfunc)
|
||||
{
|
||||
struct mvpp2_port *port = netdev_priv(dev);
|
||||
|
||||
if (!mvpp22_rss_is_supported())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (indir)
|
||||
memcpy(indir, port->indir,
|
||||
ARRAY_SIZE(port->indir) * sizeof(port->indir[0]));
|
||||
|
||||
if (hfunc)
|
||||
*hfunc = ETH_RSS_HASH_CRC32;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mvpp2_ethtool_set_rxfh(struct net_device *dev, const u32 *indir,
|
||||
const u8 *key, const u8 hfunc)
|
||||
{
|
||||
struct mvpp2_port *port = netdev_priv(dev);
|
||||
|
||||
if (!mvpp22_rss_is_supported())
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_CRC32)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (key)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (indir) {
|
||||
memcpy(port->indir, indir,
|
||||
ARRAY_SIZE(port->indir) * sizeof(port->indir[0]));
|
||||
mvpp22_rss_fill_table(port, port->id);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Device ops */
|
||||
|
||||
static const struct net_device_ops mvpp2_netdev_ops = {
|
||||
|
@ -3852,6 +3917,11 @@ static const struct ethtool_ops mvpp2_eth_tool_ops = {
|
|||
.set_pauseparam = mvpp2_ethtool_set_pause_param,
|
||||
.get_link_ksettings = mvpp2_ethtool_get_link_ksettings,
|
||||
.set_link_ksettings = mvpp2_ethtool_set_link_ksettings,
|
||||
.get_rxnfc = mvpp2_ethtool_get_rxnfc,
|
||||
.get_rxfh_indir_size = mvpp2_ethtool_get_rxfh_indir_size,
|
||||
.get_rxfh = mvpp2_ethtool_get_rxfh,
|
||||
.set_rxfh = mvpp2_ethtool_set_rxfh,
|
||||
|
||||
};
|
||||
|
||||
/* Used for PPv2.1, or PPv2.2 with the old Device Tree binding that
|
||||
|
|
Loading…
Reference in New Issue