summaryrefslogtreecommitdiff
path: root/drivers/staging/hv/netvsc_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/hv/netvsc_drv.c')
-rw-r--r--drivers/staging/hv/netvsc_drv.c42
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 */