Author: avg
Date: Tue Jun 26 08:56:34 2018
New Revision: 335658
URL: https://svnweb.freebsd.org/changeset/base/335658

Log:
  MFC r333268: for bus suspend, detach and shutdown iterate children in reverse 
order

Modified:
  stable/11/sys/kern/subr_bus.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/kern/subr_bus.c
==============================================================================
--- stable/11/sys/kern/subr_bus.c       Tue Jun 26 08:35:58 2018        
(r335657)
+++ stable/11/sys/kern/subr_bus.c       Tue Jun 26 08:56:34 2018        
(r335658)
@@ -3697,7 +3697,11 @@ bus_generic_detach(device_t dev)
        if (dev->state != DS_ATTACHED)
                return (EBUSY);
 
-       TAILQ_FOREACH(child, &dev->children, link) {
+       /*
+        * Detach children in the reverse order.
+        * See bus_generic_suspend for details.
+        */
+       TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
                if ((error = device_detach(child)) != 0)
                        return (error);
        }
@@ -3717,7 +3721,11 @@ bus_generic_shutdown(device_t dev)
 {
        device_t child;
 
-       TAILQ_FOREACH(child, &dev->children, link) {
+       /*
+        * Shut down children in the reverse order.
+        * See bus_generic_suspend for details.
+        */
+       TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
                device_shutdown(child);
        }
 
@@ -3770,15 +3778,23 @@ int
 bus_generic_suspend(device_t dev)
 {
        int             error;
-       device_t        child, child2;
+       device_t        child;
 
-       TAILQ_FOREACH(child, &dev->children, link) {
+       /*
+        * Suspend children in the reverse order.
+        * For most buses all children are equal, so the order does not matter.
+        * Other buses, such as acpi, carefully order their child devices to
+        * express implicit dependencies between them.  For such buses it is
+        * safer to bring down devices in the reverse order.
+        */
+       TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
                error = BUS_SUSPEND_CHILD(dev, child);
-               if (error) {
-                       for (child2 = TAILQ_FIRST(&dev->children);
-                            child2 && child2 != child;
-                            child2 = TAILQ_NEXT(child2, link))
-                               BUS_RESUME_CHILD(dev, child2);
+               if (error != 0) {
+                       child = TAILQ_NEXT(child, link);
+                       if (child != NULL) {
+                               TAILQ_FOREACH_FROM(child, &dev->children, link)
+                                       BUS_RESUME_CHILD(dev, child);
+                       }
                        return (error);
                }
        }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to