summaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv/netvsc_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
-rw-r--r--drivers/net/hyperv/netvsc_drv.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index ead472150742..a09602e59cf5 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1035,7 +1035,7 @@ static u32 netvsc_get_rxfh_key_size(struct net_device *dev)
static u32 netvsc_rss_indir_size(struct net_device *dev)
{
- return 0;
+ return ITAB_NUM;
}
static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
@@ -1044,10 +1044,16 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
struct net_device_context *ndc = netdev_priv(dev);
struct netvsc_device *ndev = ndc->nvdev;
struct rndis_device *rndis_dev = ndev->extension;
+ int i;
if (hfunc)
*hfunc = ETH_RSS_HASH_TOP; /* Toeplitz */
+ if (indir) {
+ for (i = 0; i < ITAB_NUM; i++)
+ indir[i] = rndis_dev->ind_table[i];
+ }
+
if (key)
memcpy(key, rndis_dev->rss_key, NETVSC_HASH_KEYLEN);
@@ -1060,12 +1066,26 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
struct net_device_context *ndc = netdev_priv(dev);
struct netvsc_device *ndev = ndc->nvdev;
struct rndis_device *rndis_dev = ndev->extension;
+ int i;
if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
return -EOPNOTSUPP;
- if (!key || memcmp(key, rndis_dev->rss_key, NETVSC_HASH_KEYLEN) == 0)
- return 0; /* no change */
+ if (indir) {
+ for (i = 0; i < ITAB_NUM; i++)
+ if (indir[i] >= dev->num_rx_queues)
+ return -EINVAL;
+
+ for (i = 0; i < ITAB_NUM; i++)
+ rndis_dev->ind_table[i] = indir[i];
+ }
+
+ if (!key) {
+ if (!indir)
+ return 0;
+
+ key = rndis_dev->rss_key;
+ }
return rndis_filter_set_rss_param(rndis_dev, key, ndev->num_chn);
}