From: t_jeang Date: Tue, 6 Jan 2009 12:06:02 +0000 (+0000) Subject: Arrange that netback waits for the hotplug scripts to complete before X-Git-Tag: netback-watch-csum-offload X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=58044159611761f8168295d567f19849f6725c15;p=xenclient%2Fkernel.git Arrange that netback waits for the hotplug scripts to complete before going to state Connected. WHQL gets quite upset if it sends packets which don't arrive, and that can happen if our hotplug scripts are slow and don't hook the network interface up to the bridge in time. --- diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h index 84c5033c..869c032d 100644 --- a/drivers/xen/netback/common.h +++ b/drivers/xen/netback/common.h @@ -149,7 +149,9 @@ struct backend_info { enum xenbus_state frontend_state; struct xenbus_watch csum_offload_watch; int have_csum_offload:1; + struct xenbus_watch hotplug_status_watch; int have_csum_offload_watch:1; + int have_hotplug_status_watch:1; /* State relating to the netback accelerator */ void *netback_accel_priv; diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c index d30230cb..173b276c 100644 --- a/drivers/xen/netback/xenbus.c +++ b/drivers/xen/netback/xenbus.c @@ -34,6 +34,7 @@ static void connect(struct backend_info *); static void backend_create_netif(struct backend_info *be); static int register_csum_offload_watch(struct backend_info *be); static void unregister_csum_offload_watch(struct backend_info *be); +static void unregister_hotplug_status_watch(struct backend_info *be); static int netback_remove(struct xenbus_device *dev) { @@ -42,8 +43,10 @@ static int netback_remove(struct xenbus_device *dev) netback_remove_accelerators(be, dev); unregister_csum_offload_watch(be); + unregister_hotplug_status_watch(be); if (be->netif) { kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); + xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); netif_disconnect(be->netif); be->netif = NULL; } @@ -237,6 +240,7 @@ static void disconnect_backend(struct xenbus_device *dev) if (be->netif) { unregister_csum_offload_watch(be); + xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); netif_disconnect(be->netif); be->netif = NULL; } @@ -357,6 +361,36 @@ static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[]) return 0; } +static void unregister_hotplug_status_watch(struct backend_info *be) +{ + if (be->have_hotplug_status_watch) { + unregister_xenbus_watch(&be->hotplug_status_watch); + kfree(be->hotplug_status_watch.node); + } + be->have_hotplug_status_watch = 0; +} + +static void hotplug_status_changed(struct xenbus_watch *watch, + const char **vec, + unsigned int vec_size) +{ + struct backend_info *be = container_of(watch, + struct backend_info, + hotplug_status_watch); + char *str; + unsigned int len; + + str = xenbus_read(XBT_NIL, be->dev->nodename, "hotplug-status", &len); + if ( IS_ERR(str) ) + return; + if ( len == sizeof("connected")-1 && !memcmp(str, "connected", len) ) { + xenbus_switch_state(be->dev, XenbusStateConnected); + /* Not interested in this watch anymore. */ + unregister_hotplug_status_watch(be); + } + kfree(str); +} + static void connect(struct backend_info *be) { int err; @@ -376,7 +410,16 @@ static void connect(struct backend_info *be) &be->netif->credit_usec); be->netif->remaining_credit = be->netif->credit_bytes; - xenbus_switch_state(dev, XenbusStateConnected); + unregister_hotplug_status_watch(be); + err = xenbus_watch_path2(dev, dev->nodename, "hotplug-status", + &be->hotplug_status_watch, + hotplug_status_changed); + if (err) { + /* Switch now, since we can't do a watch. */ + xenbus_switch_state(dev, XenbusStateConnected); + } else { + be->have_hotplug_status_watch = 1; + } netif_wake_queue(be->netif->dev); }