aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2011-04-06 18:18:00 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-04-06 18:44:05 -0400
commitc996edcf1c451b81740abbcca5257ed7e353fcc6 (patch)
treecb01c7e8c50eb3b8c380ff890c024c4f2a56f102 /drivers
parent6a6ec6233403ecdad0c042276e4479ca23716b1c (diff)
staging: hv: Fix GARP not sent after Quick Migration
After Quick Migration, the network is not immediately operational in the current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, I added another netif_notify_peers() into a scheduled work, otherwise GARP packet will not be sent after quick migration, and cause network disconnection. Thanks to Mike Surcouf <mike@surcouf.co.uk> for reporting the bug and testing the patch. Reported-by: Mike Surcouf <mike@surcouf.co.uk> Tested-by: Mike Surcouf <mike@surcouf.co.uk> Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com> Signed-off-by: Hank Janssen <hjanssen@microsoft.com> Signed-off-by: Abhishek Kane <v-abkane@microsoft.com> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/hv/netvsc_drv.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 2d40f5f86b24..33973568214f 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -46,6 +46,7 @@ struct net_device_context {
46 /* point back to our device context */ 46 /* point back to our device context */
47 struct hv_device *device_ctx; 47 struct hv_device *device_ctx;
48 unsigned long avail; 48 unsigned long avail;
49 struct work_struct work;
49}; 50};
50 51
51 52
@@ -219,6 +220,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
219 unsigned int status) 220 unsigned int status)
220{ 221{
221 struct net_device *net = dev_get_drvdata(&device_obj->device); 222 struct net_device *net = dev_get_drvdata(&device_obj->device);
223 struct net_device_context *ndev_ctx;
222 224
223 if (!net) { 225 if (!net) {
224 DPRINT_ERR(NETVSC_DRV, "got link status but net device " 226 DPRINT_ERR(NETVSC_DRV, "got link status but net device "
@@ -230,6 +232,8 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
230 netif_carrier_on(net); 232 netif_carrier_on(net);
231 netif_wake_queue(net); 233 netif_wake_queue(net);
232 netif_notify_peers(net); 234 netif_notify_peers(net);
235 ndev_ctx = netdev_priv(net);
236 schedule_work(&ndev_ctx->work);
233 } else { 237 } else {
234 netif_carrier_off(net); 238 netif_carrier_off(net);
235 netif_stop_queue(net); 239 netif_stop_queue(net);
@@ -328,6 +332,25 @@ static const struct net_device_ops device_ops = {
328 .ndo_set_mac_address = eth_mac_addr, 332 .ndo_set_mac_address = eth_mac_addr,
329}; 333};
330 334
335/*
336 * Send GARP packet to network peers after migrations.
337 * After Quick Migration, the network is not immediately operational in the
338 * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
339 * another netif_notify_peers() into a scheduled work, otherwise GARP packet
340 * will not be sent after quick migration, and cause network disconnection.
341 */
342static void netvsc_send_garp(struct work_struct *w)
343{
344 struct net_device_context *ndev_ctx;
345 struct net_device *net;
346
347 msleep(20);
348 ndev_ctx = container_of(w, struct net_device_context, work);
349 net = dev_get_drvdata(&ndev_ctx->device_ctx->device);
350 netif_notify_peers(net);
351}
352
353
331static int netvsc_probe(struct device *device) 354static int netvsc_probe(struct device *device)
332{ 355{
333 struct hv_driver *drv = 356 struct hv_driver *drv =
@@ -353,6 +376,7 @@ static int netvsc_probe(struct device *device)
353 net_device_ctx->device_ctx = device_obj; 376 net_device_ctx->device_ctx = device_obj;
354 net_device_ctx->avail = ring_size; 377 net_device_ctx->avail = ring_size;
355 dev_set_drvdata(device, net); 378 dev_set_drvdata(device, net);
379 INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
356 380
357 /* Notify the netvsc driver of the new device */ 381 /* Notify the netvsc driver of the new device */
358 ret = net_drv_obj->base.dev_add(device_obj, &device_info); 382 ret = net_drv_obj->base.dev_add(device_obj, &device_info);