net: mvpp2: RSS indirection table support
authorAntoine Tenart <antoine.tenart@bootlin.com>
Thu, 12 Jul 2018 11:54:20 +0000 (13:54 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 13 Jul 2018 00:30:48 +0000 (17:30 -0700)
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>
drivers/net/ethernet/marvell/mvpp2/mvpp2.h
drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.h
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

index e6b182d8be5b8ed33cc8cda01be74ef293a71461..2afbbf5e71e2cdab87f028a1ad06dfe6c1424a4c 100644 (file)
@@ -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
index c8cf3db85ffed2c1e746ae0dff7e1d290e6bafdd..c80a1a5492243284db34df60d56517e96f592521 100644 (file)
@@ -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);
 }
index e571238a83cc93375b12fa42688e90f3ac0d1919..4c7be7469a92a608eaa572ebb5db5d934bd3d96c 100644 (file)
@@ -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);
index 4bc0b893b02694fb2877866181507cbf8f0dc0da..f0b5fb78cd679505117ac7e4e2441edfc5ec79e4 100644 (file)
@@ -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