netvsc: avoid race with callback
authorstephen hemminger <stephen@networkplumber.org>
Thu, 16 Mar 2017 23:12:37 +0000 (16:12 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 17 Mar 2017 04:39:50 +0000 (21:39 -0700)
Change the argument to channel callback from the channel pointer
to the internal data structure containing per-channel info.
This avoids any possible races when callback happens during
initialization and makes IRQ code simpler.

Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/hyperv/netvsc.c
drivers/net/hyperv/rndis_filter.c

index 0e71164849dd47fd8800792031851f55aecfe0c1..0a2e9bd98d2ce39ea0095c1422655f7a54a5cb20 100644 (file)
@@ -1250,21 +1250,12 @@ int netvsc_poll(struct napi_struct *napi, int budget)
 
 void netvsc_channel_cb(void *context)
 {
-       struct vmbus_channel *channel = context;
-       struct hv_device *device = netvsc_channel_to_device(channel);
-       u16 q_idx = channel->offermsg.offer.sub_channel_index;
-       struct netvsc_device *net_device;
-       struct net_device *ndev;
-
-       ndev = hv_get_drvdata(device);
-       if (unlikely(!ndev))
-               return;
+       struct netvsc_channel *nvchan = context;
 
        /* disable interupts from host */
-       hv_begin_read(&channel->inbound);
+       hv_begin_read(&nvchan->channel->inbound);
 
-       net_device = net_device_to_netvsc_device(ndev);
-       napi_schedule(&net_device->chan_table[q_idx].napi);
+       napi_schedule(&nvchan->napi);
 }
 
 /*
@@ -1294,7 +1285,8 @@ int netvsc_device_add(struct hv_device *device,
        /* Open the channel */
        ret = vmbus_open(device->channel, ring_size * PAGE_SIZE,
                         ring_size * PAGE_SIZE, NULL, 0,
-                        netvsc_channel_cb, device->channel);
+                        netvsc_channel_cb,
+                        net_device->chan_table);
 
        if (ret != 0) {
                netdev_err(ndev, "unable to open channel: %d\n", ret);
index d7b6311e6c195d7815106518c5b5774f05e86648..382b9a62e3c4ae9189b951e4bb4401864d409c97 100644 (file)
@@ -996,23 +996,28 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
                hv_get_drvdata(new_sc->primary_channel->device_obj);
        struct netvsc_device *nvscdev = net_device_to_netvsc_device(ndev);
        u16 chn_index = new_sc->offermsg.offer.sub_channel_index;
-       int ret;
+       struct netvsc_channel *nvchan;
        unsigned long flags;
+       int ret;
 
        if (chn_index >= nvscdev->num_chn)
                return;
 
-       nvscdev->chan_table[chn_index].mrc.buf
+       nvchan = nvscdev->chan_table + chn_index;
+       nvchan->mrc.buf
                = vzalloc(NETVSC_RECVSLOT_MAX * sizeof(struct recv_comp_data));
 
+       if (!nvchan->mrc.buf)
+               return;
+
        ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
                         nvscdev->ring_size * PAGE_SIZE, NULL, 0,
-                        netvsc_channel_cb, new_sc);
+                        netvsc_channel_cb, nvchan);
 
        if (ret == 0)
-               nvscdev->chan_table[chn_index].channel = new_sc;
+               nvchan->channel = new_sc;
 
-       napi_enable(&nvscdev->chan_table[chn_index].napi);
+       napi_enable(&nvchan->napi);
 
        spin_lock_irqsave(&nvscdev->sc_lock, flags);
        nvscdev->num_sc_offered--;