diff options
Diffstat (limited to 'drivers/staging/hv/netvsc_drv.c')
-rw-r--r-- | drivers/staging/hv/netvsc_drv.c | 42 |
1 files changed, 13 insertions, 29 deletions
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c index 7b9c229..33cab9c 100644 --- a/drivers/staging/hv/netvsc_drv.c +++ b/drivers/staging/hv/netvsc_drv.c @@ -46,7 +46,7 @@ struct net_device_context { /* point back to our device context */ struct hv_device *device_ctx; unsigned long avail; - struct work_struct work; + struct delayed_work dwork; }; @@ -156,9 +156,6 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) /* Setup the rndis header */ packet->page_buf_cnt = num_pages; - /* TODO: Flush all write buffers/ memory fence ??? */ - /* wmb(); */ - /* Initialize it from the skb */ packet->total_data_buflen = skb->len; @@ -220,7 +217,7 @@ void netvsc_linkstatus_callback(struct hv_device *device_obj, netif_wake_queue(net); netif_notify_peers(net); ndev_ctx = netdev_priv(net); - schedule_work(&ndev_ctx->work); + schedule_delayed_work(&ndev_ctx->dwork, msecs_to_jiffies(20)); } else { netif_carrier_off(net); netif_stop_queue(net); @@ -318,7 +315,7 @@ static const struct net_device_ops device_ops = { * Send GARP packet to network peers after migrations. * After Quick Migration, the network is not immediately operational in the * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add - * another netif_notify_peers() into a scheduled work, otherwise GARP packet + * another netif_notify_peers() into a delayed work, otherwise GARP packet * will not be sent after quick migration, and cause network disconnection. */ static void netvsc_send_garp(struct work_struct *w) @@ -326,8 +323,7 @@ static void netvsc_send_garp(struct work_struct *w) struct net_device_context *ndev_ctx; struct net_device *net; - msleep(20); - ndev_ctx = container_of(w, struct net_device_context, work); + ndev_ctx = container_of(w, struct net_device_context, dwork.work); net = dev_get_drvdata(&ndev_ctx->device_ctx->device); netif_notify_peers(net); } @@ -351,11 +347,11 @@ static int netvsc_probe(struct hv_device *dev) net_device_ctx->device_ctx = dev; net_device_ctx->avail = ring_size; dev_set_drvdata(&dev->device, net); - INIT_WORK(&net_device_ctx->work, netvsc_send_garp); + INIT_DELAYED_WORK(&net_device_ctx->dwork, netvsc_send_garp); /* Notify the netvsc driver of the new device */ device_info.ring_size = ring_size; - ret = rndis_filte_device_add(dev, &device_info); + ret = rndis_filter_device_add(dev, &device_info); if (ret != 0) { free_netdev(net); dev_set_drvdata(&dev->device, NULL); @@ -364,17 +360,7 @@ static int netvsc_probe(struct hv_device *dev) return ret; } - /* - * If carrier is still off ie we did not get a link status callback, - * update it if necessary - */ - /* - * FIXME: We should use a atomic or test/set instead to avoid getting - * out of sync with the device's link status - */ - if (!netif_carrier_ok(net)) - if (!device_info.link_state) - netif_carrier_on(net); + netif_carrier_on(net); memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN); @@ -400,16 +386,18 @@ static int netvsc_probe(struct hv_device *dev) static int netvsc_remove(struct hv_device *dev) { struct net_device *net = dev_get_drvdata(&dev->device); - int ret; + struct net_device_context *ndev_ctx; if (net == NULL) { dev_err(&dev->device, "No net device to remove\n"); return 0; } + ndev_ctx = netdev_priv(net); + cancel_delayed_work_sync(&ndev_ctx->dwork); + /* Stop outbound asap */ netif_stop_queue(net); - /* netif_carrier_off(net); */ unregister_netdev(net); @@ -417,14 +405,10 @@ static int netvsc_remove(struct hv_device *dev) * Call to the vsc driver to let it know that the device is being * removed */ - ret = rndis_filter_device_remove(dev); - if (ret != 0) { - /* TODO: */ - netdev_err(net, "unable to remove vsc device (ret %d)\n", ret); - } + rndis_filter_device_remove(dev); free_netdev(net); - return ret; + return 0; } /* The one and only one */ |