Author: gibbs
Date: Tue Sep 20 23:44:34 2011
New Revision: 225704
URL: http://svn.freebsd.org/changeset/base/225704

Log:
  Properly handle suspend/resume events in the Xen device
  framework.
  
  Sponsored by: BQ Internet
  
  sys/xen/xenbus/xenbusb.c:
        o In xenbusb_resume(), publish the state transition of the
          resuming device into XenbusStateIntiailising so that the
          remote peer can see it.  Recording the state locally is
          not sufficient to trigger a re-connect sequence.
        o In xenbusb_resume(), defer new-bus resume processing until
          after the remote peer's XenStore address has been updated.
          The drivers may need to refer to this information during
          resume processing.
  
  sys/xen/xenbus/xenbusb_back.c:
  sys/xen/xenbus/xenbusb_front.c:
        Register xenbusb_resume() rather than bus_generic_resume()
        as the handler for device_resume events.
  
  sys/xen/xenstore/xenstore.c:
        o Fix grammer in a comment.
        o In xs_suspend(), pass suspend events on to the child
          devices (e.g. xenbusb_front/back, that are attached
          to the XenStore.
  
  Approved by:  re
  MFC after:    1 week

Modified:
  head/sys/dev/xen/control/control.c
  head/sys/xen/xenbus/xenbusb.c
  head/sys/xen/xenbus/xenbusb_back.c
  head/sys/xen/xenbus/xenbusb_front.c
  head/sys/xen/xenstore/xenstore.c

Modified: head/sys/dev/xen/control/control.c
==============================================================================
--- head/sys/dev/xen/control/control.c  Tue Sep 20 23:22:58 2011        
(r225703)
+++ head/sys/dev/xen/control/control.c  Tue Sep 20 23:44:34 2011        
(r225704)
@@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/reboot.h>
 #include <sys/rman.h>
+#include <sys/sched.h>
 #include <sys/taskqueue.h>
 #include <sys/types.h>
 #include <sys/vnode.h>
@@ -201,6 +202,8 @@ xctrl_suspend()
        int i, j, k, fpp;
        unsigned long max_pfn, start_info_mfn;
 
+       EVENTHANDLER_INVOKE(power_suspend);
+
 #ifdef SMP
        struct thread *td;
        cpuset_t map;
@@ -221,7 +224,13 @@ xctrl_suspend()
                stop_cpus(map);
 #endif
 
+       /*
+        * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE
+        * drivers need this.
+        */
+       mtx_lock(&Giant);
        if (DEVICE_SUSPEND(root_bus) != 0) {
+               mtx_unlock(&Giant);
                printf("xen_suspend: device_suspend failed\n");
 #ifdef SMP
                if (!CPU_EMPTY(&map))
@@ -229,6 +238,7 @@ xctrl_suspend()
 #endif
                return;
        }
+       mtx_unlock(&Giant);
 
        local_irq_disable();
 
@@ -283,11 +293,14 @@ xctrl_suspend()
                vcpu_prepare(i);
 
 #endif
+
        /* 
         * Only resume xenbus /after/ we've prepared our VCPUs; otherwise
         * the VCPU hotplug callback can race with our vcpu_prepare
         */
+       mtx_lock(&Giant);
        DEVICE_RESUME(root_bus);
+       mtx_unlock(&Giant);
 
 #ifdef SMP
        thread_lock(curthread);
@@ -296,6 +309,7 @@ xctrl_suspend()
        if (!CPU_EMPTY(&map))
                restart_cpus(map);
 #endif
+       EVENTHANDLER_INVOKE(power_resume);
 }
 
 static void
@@ -322,39 +336,47 @@ xctrl_suspend()
 {
        int suspend_cancelled;
 
+       EVENTHANDLER_INVOKE(power_suspend);
+
+       /*
+        * Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE
+        * drivers need this.
+        */
+       mtx_lock(&Giant);
        if (DEVICE_SUSPEND(root_bus)) {
+               mtx_unlock(&Giant);
                printf("xen_suspend: device_suspend failed\n");
                return;
        }
-
-       /*
-        * Make sure we don't change cpus or switch to some other
-        * thread. for the duration.
-        */
-       critical_enter();
+       mtx_unlock(&Giant);
 
        /*
         * Prevent any races with evtchn_interrupt() handler.
         */
-       irq_suspend();
        disable_intr();
+       irq_suspend();
 
        suspend_cancelled = HYPERVISOR_suspend(0);
-       if (!suspend_cancelled)
+       if (suspend_cancelled)
+               irq_resume();
+       else
                xenpci_resume();
 
        /*
         * Re-enable interrupts and put the scheduler back to normal.
         */
        enable_intr();
-       critical_exit();
 
        /*
         * FreeBSD really needs to add DEVICE_SUSPEND_CANCEL or
         * similar.
         */
+       mtx_lock(&Giant);
        if (!suspend_cancelled)
                DEVICE_RESUME(root_bus);
+       mtx_unlock(&Giant);
+
+       EVENTHANDLER_INVOKE(power_resume);
 }
 #endif
 

Modified: head/sys/xen/xenbus/xenbusb.c
==============================================================================
--- head/sys/xen/xenbus/xenbusb.c       Tue Sep 20 23:22:58 2011        
(r225703)
+++ head/sys/xen/xenbus/xenbusb.c       Tue Sep 20 23:44:34 2011        
(r225704)
@@ -773,7 +773,7 @@ xenbusb_resume(device_t dev)
                        ivars = device_get_ivars(kids[i]);
 
                        xs_unregister_watch(&ivars->xd_otherend_watch);
-                       ivars->xd_state = XenbusStateInitialising;
+                       xenbus_set_state(kids[i], XenbusStateInitialising);
 
                        /*
                         * Find the new backend details and
@@ -783,16 +783,16 @@ xenbusb_resume(device_t dev)
                        if (error)
                                return (error);
 
-                       DEVICE_RESUME(kids[i]);
-
                        statepath = malloc(ivars->xd_otherend_path_len
                            + strlen("/state") + 1, M_XENBUS, M_WAITOK);
                        sprintf(statepath, "%s/state", ivars->xd_otherend_path);
 
                        free(ivars->xd_otherend_watch.node, M_XENBUS);
                        ivars->xd_otherend_watch.node = statepath;
-                       xs_register_watch(&ivars->xd_otherend_watch);
 
+                       DEVICE_RESUME(kids[i]);
+
+                       xs_register_watch(&ivars->xd_otherend_watch);
 #if 0
                        /*
                         * Can't do this yet since we are running in

Modified: head/sys/xen/xenbus/xenbusb_back.c
==============================================================================
--- head/sys/xen/xenbus/xenbusb_back.c  Tue Sep 20 23:22:58 2011        
(r225703)
+++ head/sys/xen/xenbus/xenbusb_back.c  Tue Sep 20 23:44:34 2011        
(r225704)
@@ -292,7 +292,7 @@ static device_method_t xenbusb_back_meth
        DEVMETHOD(device_detach,        bus_generic_detach), 
        DEVMETHOD(device_shutdown,      bus_generic_shutdown), 
        DEVMETHOD(device_suspend,       bus_generic_suspend), 
-       DEVMETHOD(device_resume,        bus_generic_resume), 
+       DEVMETHOD(device_resume,        xenbusb_resume), 
  
        /* Bus Interface */ 
        DEVMETHOD(bus_print_child,      xenbusb_print_child),

Modified: head/sys/xen/xenbus/xenbusb_front.c
==============================================================================
--- head/sys/xen/xenbus/xenbusb_front.c Tue Sep 20 23:22:58 2011        
(r225703)
+++ head/sys/xen/xenbus/xenbusb_front.c Tue Sep 20 23:44:34 2011        
(r225704)
@@ -171,7 +171,7 @@ static device_method_t xenbusb_front_met
        DEVMETHOD(device_detach,        bus_generic_detach), 
        DEVMETHOD(device_shutdown,      bus_generic_shutdown), 
        DEVMETHOD(device_suspend,       bus_generic_suspend), 
-       DEVMETHOD(device_resume,        bus_generic_resume), 
+       DEVMETHOD(device_resume,        xenbusb_resume), 
  
        /* Bus Interface */ 
        DEVMETHOD(bus_print_child,      xenbusb_print_child),

Modified: head/sys/xen/xenstore/xenstore.c
==============================================================================
--- head/sys/xen/xenstore/xenstore.c    Tue Sep 20 23:22:58 2011        
(r225703)
+++ head/sys/xen/xenstore/xenstore.c    Tue Sep 20 23:44:34 2011        
(r225704)
@@ -721,8 +721,8 @@ xs_reply_filter(uint32_t request_msg_typ
        /*
         * The count of transactions drops if we attempted
         * to end a transaction (even if that attempt fails
-        * in error), we receive a transaction end acknowledgement
-        * or if our attempt to begin a transactionfails.
+        * in error), we receive a transaction end acknowledgement,
+        * or if our attempt to begin a transaction fails.
         */
        if (request_msg_type == XS_TRANSACTION_END
         || (request_reply_error == 0 && reply_msg_type == XS_TRANSACTION_END)
@@ -1194,8 +1194,14 @@ xs_attach(device_t dev)
  * all transactions and individual requests have completed.
  */
 static int
-xs_suspend(device_t dev __unused)
+xs_suspend(device_t dev)
 {
+       int error;
+
+       /* Suspend child Xen devices. */
+       error = bus_generic_suspend(dev);
+       if (error != 0)
+               return (error);
 
        sx_xlock(&xs.suspend_mutex);
        sx_xlock(&xs.request_mutex);
@@ -1227,6 +1233,9 @@ xs_resume(device_t dev __unused)
 
        sx_xunlock(&xs.suspend_mutex);
 
+       /* Resume child Xen devices. */
+       bus_generic_resume(dev);
+
        return (0);
 }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to