diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-08 13:39:59 +0200 | 
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-08 13:39:59 +0200 | 
| commit | 5e13a0c5ec05d382b488a691dfb8af015b1dea1e (patch) | |
| tree | 7a06dfa1f7661f8908193f2437b32452520221d3 /drivers/net/hyperv | |
| parent | b615b57a124a4af7b68196bc2fb8acc236041fa2 (diff) | |
| parent | 4f256e8aa3eda15c11c3cec3ec5336e1fc579cbd (diff) | |
| download | olio-linux-3.10-5e13a0c5ec05d382b488a691dfb8af015b1dea1e.tar.xz olio-linux-3.10-5e13a0c5ec05d382b488a691dfb8af015b1dea1e.zip  | |
Merge remote-tracking branch 'airlied/drm-core-next' into drm-intel-next-queued
Backmerge of drm-next to resolve a few ugly conflicts and to get a few
fixes from 3.4-rc6 (which drm-next has already merged). Note that this
merge also restricts the stencil cache lra evict policy workaround to
snb (as it should) - I had to frob the code anyway because the
CM0_MASK_SHIFT define died in the masked bit cleanups.
We need the backmerge to get Paulo Zanoni's infoframe regression fix
for gm45 - further bugfixes from him touch the same area and would
needlessly conflict.
Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/net/hyperv')
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 38 | 
1 files changed, 14 insertions, 24 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index dd294783b5c..2d59138db7f 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -44,6 +44,7 @@ struct net_device_context {  	/* point back to our device context */  	struct hv_device *device_ctx;  	struct delayed_work dwork; +	struct work_struct work;  }; @@ -51,30 +52,22 @@ static int ring_size = 128;  module_param(ring_size, int, S_IRUGO);  MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); -struct set_multicast_work { -	struct work_struct work; -	struct net_device *net; -}; -  static void do_set_multicast(struct work_struct *w)  { -	struct set_multicast_work *swk = -		container_of(w, struct set_multicast_work, work); -	struct net_device *net = swk->net; - -	struct net_device_context *ndevctx = netdev_priv(net); +	struct net_device_context *ndevctx = +		container_of(w, struct net_device_context, work);  	struct netvsc_device *nvdev;  	struct rndis_device *rdev;  	nvdev = hv_get_drvdata(ndevctx->device_ctx); -	if (nvdev == NULL) -		goto out; +	if (nvdev == NULL || nvdev->ndev == NULL) +		return;  	rdev = nvdev->extension;  	if (rdev == NULL) -		goto out; +		return; -	if (net->flags & IFF_PROMISC) +	if (nvdev->ndev->flags & IFF_PROMISC)  		rndis_filter_set_packet_filter(rdev,  			NDIS_PACKET_TYPE_PROMISCUOUS);  	else @@ -82,21 +75,13 @@ static void do_set_multicast(struct work_struct *w)  			NDIS_PACKET_TYPE_BROADCAST |  			NDIS_PACKET_TYPE_ALL_MULTICAST |  			NDIS_PACKET_TYPE_DIRECTED); - -out: -	kfree(w);  }  static void netvsc_set_multicast_list(struct net_device *net)  { -	struct set_multicast_work *swk = -		kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC); -	if (swk == NULL) -		return; +	struct net_device_context *net_device_ctx = netdev_priv(net); -	swk->net = net; -	INIT_WORK(&swk->work, do_set_multicast); -	schedule_work(&swk->work); +	schedule_work(&net_device_ctx->work);  }  static int netvsc_open(struct net_device *net) @@ -125,6 +110,8 @@ static int netvsc_close(struct net_device *net)  	netif_tx_disable(net); +	/* Make sure netvsc_set_multicast_list doesn't re-enable filter! */ +	cancel_work_sync(&net_device_ctx->work);  	ret = rndis_filter_close(device_obj);  	if (ret != 0)  		netdev_err(net, "unable to close device (ret %d).\n", ret); @@ -335,6 +322,7 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)  	nvdev->start_remove = true;  	cancel_delayed_work_sync(&ndevctx->dwork); +	cancel_work_sync(&ndevctx->work);  	netif_tx_disable(ndev);  	rndis_filter_device_remove(hdev); @@ -403,6 +391,7 @@ static int netvsc_probe(struct hv_device *dev,  	net_device_ctx->device_ctx = dev;  	hv_set_drvdata(dev, net);  	INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); +	INIT_WORK(&net_device_ctx->work, do_set_multicast);  	net->netdev_ops = &device_ops; @@ -456,6 +445,7 @@ static int netvsc_remove(struct hv_device *dev)  	ndev_ctx = netdev_priv(net);  	cancel_delayed_work_sync(&ndev_ctx->dwork); +	cancel_work_sync(&ndev_ctx->work);  	/* Stop outbound asap */  	netif_tx_disable(net);  |