summaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv
diff options
context:
space:
mode:
authorK. Y. Srinivasan <kys@microsoft.com>2017-04-06 14:59:21 -0700
committerDavid S. Miller <davem@davemloft.net>2017-04-08 08:33:03 -0700
commitbffb184247bcc783a40a0e123a9a2de3c5b28157 (patch)
tree9402b553070dd07e75761562d488070510ad8959 /drivers/net/hyperv
parent54a88e4cfc0dfaf12b2569b82cc5c5b43f5cde71 (diff)
downloadlinux-stable-bffb184247bcc783a40a0e123a9a2de3c5b28157.tar.gz
linux-stable-bffb184247bcc783a40a0e123a9a2de3c5b28157.tar.bz2
linux-stable-bffb184247bcc783a40a0e123a9a2de3c5b28157.zip
netvsc: Initialize all channel related state prior to opening the channel
Prior to opening the channel we should have all the state setup to handle interrupts. The current code does not do that; fix the bug. This bug can result in faults in the interrupt path. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/hyperv')
-rw-r--r--drivers/net/hyperv/netvsc.c27
-rw-r--r--drivers/net/hyperv/rndis_filter.c5
2 files changed, 18 insertions, 14 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index e998e2f7a619..7ab06b338a14 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -1289,6 +1289,21 @@ int netvsc_device_add(struct hv_device *device,
*/
set_channel_read_mode(device->channel, HV_CALL_ISR);
+ /* If we're reopening the device we may have multiple queues, fill the
+ * chn_table with the default channel to use it before subchannels are
+ * opened.
+ * Initialize the channel state before we open;
+ * we can be interrupted as soon as we open the channel.
+ */
+
+ for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
+ struct netvsc_channel *nvchan = &net_device->chan_table[i];
+
+ nvchan->channel = device->channel;
+ netif_napi_add(ndev, &nvchan->napi,
+ netvsc_poll, NAPI_POLL_WEIGHT);
+ }
+
/* Open the channel */
ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
ring_size * PAGE_SIZE, NULL, 0,
@@ -1303,18 +1318,6 @@ int netvsc_device_add(struct hv_device *device,
/* Channel is opened */
netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");
- /* If we're reopening the device we may have multiple queues, fill the
- * chn_table with the default channel to use it before subchannels are
- * opened.
- */
- for (i = 0; i < VRSS_CHANNEL_MAX; i++) {
- struct netvsc_channel *nvchan = &net_device->chan_table[i];
-
- nvchan->channel = device->channel;
- netif_napi_add(ndev, &nvchan->napi,
- netvsc_poll, NAPI_POLL_WEIGHT);
- }
-
/* Enable NAPI handler for init callbacks */
napi_enable(&net_device->chan_table[0].napi);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 983582526b37..1e9445bc4539 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1007,12 +1007,13 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
*/
set_channel_read_mode(new_sc, HV_CALL_ISR);
+ /* Set the channel before opening.*/
+ nvchan->channel = new_sc;
+
ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
nvscdev->ring_size * PAGE_SIZE, NULL, 0,
netvsc_channel_cb, nvchan);
- if (ret == 0)
- nvchan->channel = new_sc;
napi_enable(&nvchan->napi);