Commit b0689faa authored by Haiyang Zhang's avatar Haiyang Zhang Committed by David S. Miller
Browse files

hv_netvsc: Fix unwanted rx_table reset



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: ff4a4419 ("netvsc: allow get/set of RSS indirection table")
Signed-off-by: default avatarHaiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d49a32a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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) {
+7 −3
Original line number Diff line number Diff line
@@ -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);

	if (!netif_is_rxfh_configured(net)) {
		for (i = 0; i < ITAB_NUM; i++)
		rndis_device->rx_table[i] = ethtool_rxfh_indir_default(
			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);