Skip to content

Commit

Permalink
netvsc: avoid race with callback
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
stephen hemminger authored and David S. Miller committed Mar 17, 2017
1 parent 3a70418 commit 6de38af
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 18 deletions.
18 changes: 5 additions & 13 deletions drivers/net/hyperv/netvsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/*
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 10 additions & 5 deletions drivers/net/hyperv/rndis_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -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--;
Expand Down

0 comments on commit 6de38af

Please sign in to comment.