Author: kib
Date: Fri Apr 19 12:57:37 2019
New Revision: 346381
URL: https://svnweb.freebsd.org/changeset/base/346381

Log:
  MFC r345960:
  Provide newbus infrastructure for initiating device reset.

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

Modified: stable/11/sys/kern/bus_if.m
==============================================================================
--- stable/11/sys/kern/bus_if.m Fri Apr 19 12:54:05 2019        (r346380)
+++ stable/11/sys/kern/bus_if.m Fri Apr 19 12:57:37 2019        (r346381)
@@ -66,6 +66,16 @@ CODE {
 
                panic("bus_add_child is not implemented");
        }
+
+       static int null_reset_post(device_t bus, device_t dev)
+       {
+               return (0);
+       }
+
+       static int null_reset_prepare(device_t bus, device_t dev)
+       {
+               return (0);
+       }
 };
 
 /**
@@ -810,3 +820,48 @@ METHOD int get_cpus {
        size_t          _setsize;
        cpuset_t        *_cpuset;
 } DEFAULT bus_generic_get_cpus;
+
+/**
+ * @brief Prepares the given child of the bus for reset
+ *
+ * Typically bus detaches or suspends children' drivers, and then
+ * calls this method to save bus-specific information, for instance,
+ * PCI config space, which is damaged by reset.
+ *
+ * The bus_helper_reset_prepare() helper is provided to ease
+ * implementing bus reset methods.
+ *
+ * @param _dev         the bus device
+ * @param _child       the child device
+ */
+METHOD int reset_prepare {
+       device_t _dev;
+       device_t _child;
+} DEFAULT null_reset_prepare;
+
+/**
+ * @brief Restores the child operations after the reset
+ *
+ * The bus_helper_reset_post() helper is provided to ease
+ * implementing bus reset methods.
+ *
+ * @param _dev         the bus device
+ * @param _child       the child device
+ */
+METHOD int reset_post {
+       device_t _dev;
+       device_t _child;
+} DEFAULT null_reset_post;
+
+/**
+ * @brief Performs reset of the child
+ *
+ * @param _dev         the bus device
+ * @param _child       the child device
+ * @param _flags       DEVF_RESET_ flags
+ */
+METHOD int reset_child {
+       device_t _dev;
+       device_t _child;
+       int _flags;
+};

Modified: stable/11/sys/kern/subr_bus.c
==============================================================================
--- stable/11/sys/kern/subr_bus.c       Fri Apr 19 12:54:05 2019        
(r346380)
+++ stable/11/sys/kern/subr_bus.c       Fri Apr 19 12:57:37 2019        
(r346381)
@@ -3822,6 +3822,96 @@ bus_generic_resume(device_t dev)
        return (0);
 }
 
+
+/**
+ * @brief Helper function for implementing BUS_RESET_POST
+ *
+ * Bus can use this function to implement common operations of
+ * re-attaching or resuming the children after the bus itself was
+ * reset, and after restoring bus-unique state of children.
+ *
+ * @param dev  The bus
+ * #param flags        DEVF_RESET_*
+ */
+int
+bus_helper_reset_post(device_t dev, int flags)
+{
+       device_t child;
+       int error, error1;
+
+       error = 0;
+       TAILQ_FOREACH(child, &dev->children,link) {
+               BUS_RESET_POST(dev, child);
+               error1 = (flags & DEVF_RESET_DETACH) != 0 ?
+                   device_probe_and_attach(child) :
+                   BUS_RESUME_CHILD(dev, child);
+               if (error == 0 && error1 != 0)
+                       error = error1;
+       }
+       return (error);
+}
+
+static void
+bus_helper_reset_prepare_rollback(device_t dev, device_t child, int flags)
+{
+
+       child = TAILQ_NEXT(child, link);
+       if (child == NULL)
+               return;
+       TAILQ_FOREACH_FROM(child, &dev->children,link) {
+               BUS_RESET_POST(dev, child);
+               if ((flags & DEVF_RESET_DETACH) != 0)
+                       device_probe_and_attach(child);
+               else
+                       BUS_RESUME_CHILD(dev, child);
+       }
+}
+
+/**
+ * @brief Helper function for implementing BUS_RESET_PREPARE
+ *
+ * Bus can use this function to implement common operations of
+ * detaching or suspending the children before the bus itself is
+ * reset, and then save bus-unique state of children that must
+ * persists around reset.
+ *
+ * @param dev  The bus
+ * #param flags        DEVF_RESET_*
+ */
+int
+bus_helper_reset_prepare(device_t dev, int flags)
+{
+       device_t child;
+       int error;
+
+       if (dev->state != DS_ATTACHED)
+               return (EBUSY);
+
+       TAILQ_FOREACH_REVERSE(child, &dev->children, device_list, link) {
+               if ((flags & DEVF_RESET_DETACH) != 0) {
+                       error = device_get_state(child) == DS_ATTACHED ?
+                           device_detach(child) : 0;
+               } else {
+                       error = BUS_SUSPEND_CHILD(dev, child);
+               }
+               if (error == 0) {
+                       error = BUS_RESET_PREPARE(dev, child);
+                       if (error != 0) {
+                               if ((flags & DEVF_RESET_DETACH) != 0)
+                                       device_probe_and_attach(child);
+                               else
+                                       BUS_RESUME_CHILD(dev, child);
+                       }
+               }
+               if (error != 0) {
+                       bus_helper_reset_prepare_rollback(dev, child, flags);
+                       return (error);
+               }
+       }
+       return (0);
+}
+
+
 /**
  * @brief Helper function for implementing BUS_PRINT_CHILD().
  *

Modified: stable/11/sys/sys/bus.h
==============================================================================
--- stable/11/sys/sys/bus.h     Fri Apr 19 12:54:05 2019        (r346380)
+++ stable/11/sys/sys/bus.h     Fri Apr 19 12:57:37 2019        (r346381)
@@ -133,6 +133,10 @@ struct devreq {
 /* Flags for DEV_DELETE. */
 #define        DEVF_FORCE_DELETE       0x0000001
 
+/* Flags for DEV_RESET */
+#define        DEVF_RESET_DETACH       0x0000001       /* Detach drivers vs 
suspend
+                                                  device */
+
 #ifdef _KERNEL
 
 #include <sys/eventhandler.h>
@@ -479,6 +483,8 @@ int bus_generic_unmap_resource(device_t dev, device_t 
                                   struct resource_map *map);
 int    bus_generic_write_ivar(device_t dev, device_t child, int which,
                               uintptr_t value);
+int    bus_helper_reset_post(device_t dev, int flags);
+int    bus_helper_reset_prepare(device_t dev, int flags);
 int    bus_null_rescan(device_t dev);
 
 /*
_______________________________________________
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