]> xenbits.xensource.com Git - xenclient/kernel.git/commitdiff
Arrange that netback waits for the hotplug scripts to complete before netback-watch-csum-offload
authort_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:02 +0000 (12:06 +0000)
committert_jeang <devnull@localhost>
Tue, 6 Jan 2009 12:06:02 +0000 (12:06 +0000)
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.

drivers/xen/netback/common.h
drivers/xen/netback/xenbus.c

index 84c5033ca1fafcf120131eedbef7f3ff544e9ecf..869c032d11633bf432c99b3d2c91058037036990 100644 (file)
@@ -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;
index d30230cbb58e6b9a77cac67e184501c852507238..173b276c05cbec4ca60b8705894310b4ba60d757 100644 (file)
@@ -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);
 }