| From 3cae727c4207e996f7760afaf242ea31255290ad Mon Sep 17 00:00:00 2001 |
| From: Haiyang Zhang <haiyangz@microsoft.com> |
| Date: Thu, 19 Dec 2019 18:28:10 -0800 |
| Subject: [PATCH] hv_netvsc: Fix unwanted rx_table reset |
| |
| commit b0689faa8efc5a3391402d7ae93bd373b7248e51 upstream. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h |
| index ecc9af050387..bb38a59bf468 100644 |
| --- a/drivers/net/hyperv/hyperv_net.h |
| +++ b/drivers/net/hyperv/hyperv_net.h |
| @@ -169,7 +169,6 @@ struct rndis_device { |
| |
| u8 hw_mac_adr[ETH_ALEN]; |
| u8 rss_key[NETVSC_HASH_KEYLEN]; |
| - u16 rx_table[ITAB_NUM]; |
| }; |
| |
| |
| @@ -937,6 +936,8 @@ struct net_device_context { |
| |
| u32 tx_table[VRSS_SEND_TAB_SIZE]; |
| |
| + u16 rx_table[ITAB_NUM]; |
| + |
| /* Ethtool settings */ |
| u8 duplex; |
| u32 speed; |
| diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c |
| index 8ed79b418d88..080e071eb7c7 100644 |
| --- a/drivers/net/hyperv/netvsc_drv.c |
| +++ b/drivers/net/hyperv/netvsc_drv.c |
| @@ -1659,7 +1659,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) |
| @@ -1689,7 +1689,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) { |
| diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c |
| index c0c2934552e4..e32014841fa6 100644 |
| --- a/drivers/net/hyperv/rndis_filter.c |
| +++ b/drivers/net/hyperv/rndis_filter.c |
| @@ -767,6 +767,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; |
| @@ -806,7 +807,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); |
| @@ -1304,6 +1305,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; |
| @@ -1390,9 +1392,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); |
| -- |
| 2.7.4 |
| |