diff options
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 26 |
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); } |