svn commit: r225704 - in head/sys: dev/xen/control xen/xenbus xen/xenstore

Justin T. Gibbs gibbs at FreeBSD.org
Tue Sep 20 23:44:35 UTC 2011


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);
 }
 


More information about the svn-src-all mailing list