hv_netvsc: Fix hash key value reset after other ops
[ Upstream commit 17d91256898402daf4425cc541ac9cbf64574d9a ]
Changing mtu, channels, or buffer sizes ops call to netvsc_attach(),
rndis_set_subchannel(), which always reset the hash key to default
value. That will override hash key changed previously. This patch
fixes the problem by save the hash key, then restore it when we re-
add the netvsc device.
Fixes: ff4a441990
("netvsc: allow get/set of RSS indirection table")
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
[sl: fix up subject line]
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
d2ce8e1bd3
commit
bbbb9874a9
4 changed files with 19 additions and 7 deletions
|
@ -144,6 +144,8 @@ struct hv_netvsc_packet {
|
|||
u32 total_data_buflen;
|
||||
};
|
||||
|
||||
#define NETVSC_HASH_KEYLEN 40
|
||||
|
||||
struct netvsc_device_info {
|
||||
unsigned char mac_adr[ETH_ALEN];
|
||||
u32 num_chn;
|
||||
|
@ -151,6 +153,8 @@ struct netvsc_device_info {
|
|||
u32 recv_sections;
|
||||
u32 send_section_size;
|
||||
u32 recv_section_size;
|
||||
|
||||
u8 rss_key[NETVSC_HASH_KEYLEN];
|
||||
};
|
||||
|
||||
enum rndis_device_state {
|
||||
|
@ -160,8 +164,6 @@ enum rndis_device_state {
|
|||
RNDIS_DEV_DATAINITIALIZED,
|
||||
};
|
||||
|
||||
#define NETVSC_HASH_KEYLEN 40
|
||||
|
||||
struct rndis_device {
|
||||
struct net_device *ndev;
|
||||
|
||||
|
@ -210,7 +212,9 @@ int netvsc_recv_callback(struct net_device *net,
|
|||
void netvsc_channel_cb(void *context);
|
||||
int netvsc_poll(struct napi_struct *napi, int budget);
|
||||
|
||||
int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
|
||||
int rndis_set_subchannel(struct net_device *ndev,
|
||||
struct netvsc_device *nvdev,
|
||||
struct netvsc_device_info *dev_info);
|
||||
int rndis_filter_open(struct netvsc_device *nvdev);
|
||||
int rndis_filter_close(struct netvsc_device *nvdev);
|
||||
struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
|
||||
|
|
|
@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)
|
|||
|
||||
rdev = nvdev->extension;
|
||||
if (rdev) {
|
||||
ret = rndis_set_subchannel(rdev->ndev, nvdev);
|
||||
ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
|
||||
if (ret == 0) {
|
||||
netif_device_attach(rdev->ndev);
|
||||
} else {
|
||||
|
|
|
@ -875,6 +875,9 @@ static struct netvsc_device_info *netvsc_devinfo_get
|
|||
dev_info->send_section_size = nvdev->send_section_size;
|
||||
dev_info->recv_sections = nvdev->recv_section_cnt;
|
||||
dev_info->recv_section_size = nvdev->recv_section_size;
|
||||
|
||||
memcpy(dev_info->rss_key, nvdev->extension->rss_key,
|
||||
NETVSC_HASH_KEYLEN);
|
||||
} else {
|
||||
dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
|
||||
dev_info->send_sections = NETVSC_DEFAULT_TX;
|
||||
|
@ -937,7 +940,7 @@ static int netvsc_attach(struct net_device *ndev,
|
|||
return PTR_ERR(nvdev);
|
||||
|
||||
if (nvdev->num_chn > 1) {
|
||||
ret = rndis_set_subchannel(ndev, nvdev);
|
||||
ret = rndis_set_subchannel(ndev, nvdev, dev_info);
|
||||
|
||||
/* if unavailable, just proceed with one queue */
|
||||
if (ret) {
|
||||
|
|
|
@ -1075,7 +1075,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
|
|||
* This breaks overlap of processing the host message for the
|
||||
* new primary channel with the initialization of sub-channels.
|
||||
*/
|
||||
int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
|
||||
int rndis_set_subchannel(struct net_device *ndev,
|
||||
struct netvsc_device *nvdev,
|
||||
struct netvsc_device_info *dev_info)
|
||||
{
|
||||
struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
|
||||
struct net_device_context *ndev_ctx = netdev_priv(ndev);
|
||||
|
@ -1116,7 +1118,10 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
|
|||
atomic_read(&nvdev->open_chn) == nvdev->num_chn);
|
||||
|
||||
/* ignore failues from setting rss parameters, still have channels */
|
||||
rndis_filter_set_rss_param(rdev, netvsc_hash_key);
|
||||
if (dev_info)
|
||||
rndis_filter_set_rss_param(rdev, dev_info->rss_key);
|
||||
else
|
||||
rndis_filter_set_rss_param(rdev, netvsc_hash_key);
|
||||
|
||||
netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
|
||||
netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
|
||||
|
|
Loading…
Reference in a new issue