amd-xgbe: Add receive side scaling ethtool support
authorLendacky, Thomas <Thomas.Lendacky@amd.com>
Tue, 4 Nov 2014 22:07:23 +0000 (16:07 -0600)
committerDavid S. Miller <davem@davemloft.net>
Thu, 6 Nov 2014 02:50:12 +0000 (21:50 -0500)
This patch adds support for ethtool receive side scaling (RSS) commands.
Support is added to get/set the RSS hash key and the RSS lookup table.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
drivers/net/ethernet/amd/xgbe/xgbe.h

index 551794c29d09e05e33ff5e2b505d9dbf7f7bb541..7daa2cd9af5f23ca460a712bcb150d00410315ca 100644 (file)
@@ -419,6 +419,24 @@ static int xgbe_write_rss_lookup_table(struct xgbe_prv_data *pdata)
        return 0;
 }
 
+static int xgbe_set_rss_hash_key(struct xgbe_prv_data *pdata, const u8 *key)
+{
+       memcpy(pdata->rss_key, key, sizeof(pdata->rss_key));
+
+       return xgbe_write_rss_hash_key(pdata);
+}
+
+static int xgbe_set_rss_lookup_table(struct xgbe_prv_data *pdata,
+                                    const u32 *table)
+{
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++)
+               XGMAC_SET_BITS(pdata->rss_table[i], MAC_RSSDR, DMCH, table[i]);
+
+       return xgbe_write_rss_lookup_table(pdata);
+}
+
 static int xgbe_enable_rss(struct xgbe_prv_data *pdata)
 {
        int ret;
@@ -2759,6 +2777,8 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if)
        /* For Receive Side Scaling */
        hw_if->enable_rss = xgbe_enable_rss;
        hw_if->disable_rss = xgbe_disable_rss;
+       hw_if->set_rss_hash_key = xgbe_set_rss_hash_key;
+       hw_if->set_rss_lookup_table = xgbe_set_rss_lookup_table;
 
        DBGPR("<--xgbe_init_function_ptrs\n");
 }
index 47022fb00b7942f2fc28d5f4907e9dd84a23057c..95d44538357fbb1dcd53969eeb25aca48eb2b31e 100644 (file)
@@ -481,6 +481,75 @@ static int xgbe_set_coalesce(struct net_device *netdev,
        return 0;
 }
 
+static int xgbe_get_rxnfc(struct net_device *netdev,
+                         struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
+{
+       struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+       switch (rxnfc->cmd) {
+       case ETHTOOL_GRXRINGS:
+               rxnfc->data = pdata->rx_ring_count;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static u32 xgbe_get_rxfh_key_size(struct net_device *netdev)
+{
+       struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+       return sizeof(pdata->rss_key);
+}
+
+static u32 xgbe_get_rxfh_indir_size(struct net_device *netdev)
+{
+       struct xgbe_prv_data *pdata = netdev_priv(netdev);
+
+       return ARRAY_SIZE(pdata->rss_table);
+}
+
+static int xgbe_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
+{
+       struct xgbe_prv_data *pdata = netdev_priv(netdev);
+       unsigned int i;
+
+       if (indir) {
+               for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++)
+                       indir[i] = XGMAC_GET_BITS(pdata->rss_table[i],
+                                                 MAC_RSSDR, DMCH);
+       }
+
+       if (key)
+               memcpy(key, pdata->rss_key, sizeof(pdata->rss_key));
+
+       return 0;
+}
+
+static int xgbe_set_rxfh(struct net_device *netdev, const u32 *indir,
+                        const u8 *key)
+{
+       struct xgbe_prv_data *pdata = netdev_priv(netdev);
+       struct xgbe_hw_if *hw_if = &pdata->hw_if;
+       unsigned int ret;
+
+       if (indir) {
+               ret = hw_if->set_rss_lookup_table(pdata, indir);
+               if (ret)
+                       return ret;
+       }
+
+       if (key) {
+               ret = hw_if->set_rss_hash_key(pdata, key);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 static int xgbe_get_ts_info(struct net_device *netdev,
                            struct ethtool_ts_info *ts_info)
 {
@@ -526,6 +595,11 @@ static const struct ethtool_ops xgbe_ethtool_ops = {
        .get_strings = xgbe_get_strings,
        .get_ethtool_stats = xgbe_get_ethtool_stats,
        .get_sset_count = xgbe_get_sset_count,
+       .get_rxnfc = xgbe_get_rxnfc,
+       .get_rxfh_key_size = xgbe_get_rxfh_key_size,
+       .get_rxfh_indir_size = xgbe_get_rxfh_indir_size,
+       .get_rxfh = xgbe_get_rxfh,
+       .set_rxfh = xgbe_set_rxfh,
        .get_ts_info = xgbe_get_ts_info,
 };
 
index 2ac4f176ad88cbda46280aedb96d47b18062c0b6..aa8da9f4f1f9ff874a4fb67a6285b77497c426b2 100644 (file)
@@ -557,6 +557,8 @@ struct xgbe_hw_if {
        /* For Receive Side Scaling */
        int (*enable_rss)(struct xgbe_prv_data *);
        int (*disable_rss)(struct xgbe_prv_data *);
+       int (*set_rss_hash_key)(struct xgbe_prv_data *, const u8 *);
+       int (*set_rss_lookup_table)(struct xgbe_prv_data *, const u32 *);
 };
 
 struct xgbe_desc_if {