Olaf Hering ca7cb7
From: Haiyang Zhang <haiyangz@microsoft.com>
Olaf Hering ca7cb7
Date: Thu, 19 Dec 2019 18:28:10 -0800
Olaf Hering ca7cb7
Patch-mainline: v5.5-rc3
Olaf Hering ca7cb7
Subject: hv_netvsc: Fix unwanted rx_table reset
Olaf Hering ca7cb7
Git-commit: b0689faa8efc5a3391402d7ae93bd373b7248e51
Olaf Hering ca7cb7
References: bsc#1164598
Olaf Hering ca7cb7
Olaf Hering ca7cb7
In existing code, the receive indirection table, rx_table, is in
Olaf Hering ca7cb7
struct rndis_device, which will be reset when changing MTU, ringparam,
Olaf Hering ca7cb7
etc. User configured receive indirection table values will be lost.
Olaf Hering ca7cb7
Olaf Hering ca7cb7
To fix this, move rx_table to struct net_device_context, and check
Olaf Hering ca7cb7
netif_is_rxfh_configured(), so rx_table will be set to default only
Olaf Hering ca7cb7
if no user configured value.
Olaf Hering ca7cb7
Olaf Hering ca7cb7
Fixes: ff4a44199012 ("netvsc: allow get/set of RSS indirection table")
Olaf Hering ca7cb7
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Olaf Hering ca7cb7
Signed-off-by: David S. Miller <davem@davemloft.net>
Olaf Hering ca7cb7
Acked-by: Olaf Hering <ohering@suse.de>
Olaf Hering ca7cb7
---
Olaf Hering ca7cb7
 drivers/net/hyperv/hyperv_net.h   |  3 ++-
Olaf Hering ca7cb7
 drivers/net/hyperv/netvsc_drv.c   |  4 ++--
Olaf Hering ca7cb7
 drivers/net/hyperv/rndis_filter.c | 10 +++++++---
Olaf Hering ca7cb7
 3 files changed, 11 insertions(+), 6 deletions(-)
Olaf Hering ca7cb7
Olaf Hering ca7cb7
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
Olaf Hering ca7cb7
--- a/drivers/net/hyperv/hyperv_net.h
Olaf Hering ca7cb7
+++ b/drivers/net/hyperv/hyperv_net.h
Olaf Hering ca7cb7
@@ -169,7 +169,6 @@ struct rndis_device {
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 	u8 hw_mac_adr[ETH_ALEN];
Olaf Hering ca7cb7
 	u8 rss_key[NETVSC_HASH_KEYLEN];
Olaf Hering ca7cb7
-	u16 rx_table[ITAB_NUM];
Olaf Hering ca7cb7
 };
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
@@ -940,6 +939,8 @@ struct net_device_context {
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 	u32 tx_table[VRSS_SEND_TAB_SIZE];
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
+	u16 rx_table[ITAB_NUM];
Olaf Hering ca7cb7
+
Olaf Hering ca7cb7
 	/* Ethtool settings */
Olaf Hering ca7cb7
 	u8 duplex;
Olaf Hering ca7cb7
 	u32 speed;
Olaf Hering ca7cb7
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
Olaf Hering ca7cb7
--- a/drivers/net/hyperv/netvsc_drv.c
Olaf Hering ca7cb7
+++ b/drivers/net/hyperv/netvsc_drv.c
Olaf Hering ca7cb7
@@ -1662,7 +1662,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
Olaf Hering ca7cb7
 	rndis_dev = ndev->extension;
Olaf Hering ca7cb7
 	if (indir) {
Olaf Hering ca7cb7
 		for (i = 0; i < ITAB_NUM; i++)
Olaf Hering ca7cb7
-			indir[i] = rndis_dev->rx_table[i];
Olaf Hering ca7cb7
+			indir[i] = ndc->rx_table[i];
Olaf Hering ca7cb7
 	}
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 	if (key)
Olaf Hering ca7cb7
@@ -1692,7 +1692,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
Olaf Hering ca7cb7
 				return -EINVAL;
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 		for (i = 0; i < ITAB_NUM; i++)
Olaf Hering ca7cb7
-			rndis_dev->rx_table[i] = indir[i];
Olaf Hering ca7cb7
+			ndc->rx_table[i] = indir[i];
Olaf Hering ca7cb7
 	}
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 	if (!key) {
Olaf Hering ca7cb7
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
Olaf Hering ca7cb7
--- a/drivers/net/hyperv/rndis_filter.c
Olaf Hering ca7cb7
+++ b/drivers/net/hyperv/rndis_filter.c
Olaf Hering ca7cb7
@@ -773,6 +773,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
Olaf Hering ca7cb7
 				   const u8 *rss_key, u16 flag)
Olaf Hering ca7cb7
 {
Olaf Hering ca7cb7
 	struct net_device *ndev = rdev->ndev;
Olaf Hering ca7cb7
+	struct net_device_context *ndc = netdev_priv(ndev);
Olaf Hering ca7cb7
 	struct rndis_request *request;
Olaf Hering ca7cb7
 	struct rndis_set_request *set;
Olaf Hering ca7cb7
 	struct rndis_set_complete *set_complete;
Olaf Hering ca7cb7
@@ -812,7 +813,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
Olaf Hering ca7cb7
 	/* Set indirection table entries */
Olaf Hering ca7cb7
 	itab = (u32 *)(rssp + 1);
Olaf Hering ca7cb7
 	for (i = 0; i < ITAB_NUM; i++)
Olaf Hering ca7cb7
-		itab[i] = rdev->rx_table[i];
Olaf Hering ca7cb7
+		itab[i] = ndc->rx_table[i];
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 	/* Set hask key values */
Olaf Hering ca7cb7
 	keyp = (u8 *)((unsigned long)rssp + rssp->hashkey_offset);
Olaf Hering ca7cb7
@@ -1312,6 +1313,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
Olaf Hering ca7cb7
 				      struct netvsc_device_info *device_info)
Olaf Hering ca7cb7
 {
Olaf Hering ca7cb7
 	struct net_device *net = hv_get_drvdata(dev);
Olaf Hering ca7cb7
+	struct net_device_context *ndc = netdev_priv(net);
Olaf Hering ca7cb7
 	struct netvsc_device *net_device;
Olaf Hering ca7cb7
 	struct rndis_device *rndis_device;
Olaf Hering ca7cb7
 	struct ndis_recv_scale_cap rsscap;
Olaf Hering ca7cb7
@@ -1398,9 +1400,11 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
Olaf Hering ca7cb7
 	/* We will use the given number of channels if available. */
Olaf Hering ca7cb7
 	net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
-	for (i = 0; i < ITAB_NUM; i++)
Olaf Hering ca7cb7
-		rndis_device->rx_table[i] = ethtool_rxfh_indir_default(
Olaf Hering ca7cb7
+	if (!netif_is_rxfh_configured(net)) {
Olaf Hering ca7cb7
+		for (i = 0; i < ITAB_NUM; i++)
Olaf Hering ca7cb7
+			ndc->rx_table[i] = ethtool_rxfh_indir_default(
Olaf Hering ca7cb7
 						i, net_device->num_chn);
Olaf Hering ca7cb7
+	}
Olaf Hering ca7cb7
 
Olaf Hering ca7cb7
 	atomic_set(&net_device->open_chn, 1);
Olaf Hering ca7cb7
 	vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);