hv_netvsc: Fix unwanted rx_table reset
authorHaiyang Zhang <haiyangz@microsoft.com>
Fri, 20 Dec 2019 02:28:10 +0000 (18:28 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 21 Dec 2019 05:50:38 +0000 (21:50 -0800)
In existing code, the receive indirection table, rx_table, is in
struct rndis_device, which will be reset when changing MTU, ringparam,
etc. User configured receive indirection table values will be lost.

To fix this, move rx_table to struct net_device_context, and check
netif_is_rxfh_configured(), so rx_table will be set to default only
if no user configured value.

Fixes: ff4a44199012 ("netvsc: allow get/set of RSS indirection table")
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c

index 9caa876..dc44819 100644 (file)
@@ -169,7 +169,6 @@ struct rndis_device {
 
        u8 hw_mac_adr[ETH_ALEN];
        u8 rss_key[NETVSC_HASH_KEYLEN];
-       u16 rx_table[ITAB_NUM];
 };
 
 
@@ -940,6 +939,8 @@ struct net_device_context {
 
        u32 tx_table[VRSS_SEND_TAB_SIZE];
 
+       u16 rx_table[ITAB_NUM];
+
        /* Ethtool settings */
        u8 duplex;
        u32 speed;
index eff8fef..68bf671 100644 (file)
@@ -1662,7 +1662,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
        rndis_dev = ndev->extension;
        if (indir) {
                for (i = 0; i < ITAB_NUM; i++)
-                       indir[i] = rndis_dev->rx_table[i];
+                       indir[i] = ndc->rx_table[i];
        }
 
        if (key)
@@ -1692,7 +1692,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
                                return -EINVAL;
 
                for (i = 0; i < ITAB_NUM; i++)
-                       rndis_dev->rx_table[i] = indir[i];
+                       ndc->rx_table[i] = indir[i];
        }
 
        if (!key) {
index 05bc5ec..857c4be 100644 (file)
@@ -773,6 +773,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
                                   const u8 *rss_key, u16 flag)
 {
        struct net_device *ndev = rdev->ndev;
+       struct net_device_context *ndc = netdev_priv(ndev);
        struct rndis_request *request;
        struct rndis_set_request *set;
        struct rndis_set_complete *set_complete;
@@ -812,7 +813,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
        /* Set indirection table entries */
        itab = (u32 *)(rssp + 1);
        for (i = 0; i < ITAB_NUM; i++)
-               itab[i] = rdev->rx_table[i];
+               itab[i] = ndc->rx_table[i];
 
        /* Set hask key values */
        keyp = (u8 *)((unsigned long)rssp + rssp->hashkey_offset);
@@ -1312,6 +1313,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
                                      struct netvsc_device_info *device_info)
 {
        struct net_device *net = hv_get_drvdata(dev);
+       struct net_device_context *ndc = netdev_priv(net);
        struct netvsc_device *net_device;
        struct rndis_device *rndis_device;
        struct ndis_recv_scale_cap rsscap;
@@ -1398,9 +1400,11 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
        /* We will use the given number of channels if available. */
        net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
 
-       for (i = 0; i < ITAB_NUM; i++)
-               rndis_device->rx_table[i] = ethtool_rxfh_indir_default(
+       if (!netif_is_rxfh_configured(net)) {
+               for (i = 0; i < ITAB_NUM; i++)
+                       ndc->rx_table[i] = ethtool_rxfh_indir_default(
                                                i, net_device->num_chn);
+       }
 
        atomic_set(&net_device->open_chn, 1);
        vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);