The branch main has been updated by imp:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=aa52c6bdd7b157b7c5d9612e4feac5c94f376df6

commit aa52c6bdd7b157b7c5d9612e4feac5c94f376df6
Author:     Warner Losh <i...@freebsd.org>
AuthorDate: 2022-12-04 23:20:24 +0000
Commit:     Warner Losh <i...@freebsd.org>
CommitDate: 2022-12-04 23:20:24 +0000

    newbus: Create a knob to disable devices that fail to attach.
    
    Normally, when a device fails to attach, we tear down the newbus state
    for that device so that future driver loads can try again (maybe with a
    different driver, or maybe with a re-loaded and fixed kld).
    
    Sometimes, however, it is desirable to have the device fail
    permanantly. We do this by calling device_disable() on a failed
    attached, as well as keeping the device in DS_ATTACHING forever. This
    prevents retries on that device. This is enabled via
    hw.bus.disable_failed_devices=1 in either a hint via the loader, or at
    runtime with a sysctl setting. Setting from 1 -> 0 at runtime will not
    affect previously disabled devices, however: they remain disabled.
    They can be re-enabled manually with devctl enable, however.
    
    Sponsored by:           Netflix
    
    Reviewed by:    gallatin, hselasky, jhb
    Differential Revision:  https://reviews.freebsd.org/D37517
---
 sys/kern/subr_bus.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 739484ad849a..b9615b033007 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -69,6 +69,10 @@ SYSCTL_NODE(_hw, OID_AUTO, bus, CTLFLAG_RW | CTLFLAG_MPSAFE, 
NULL,
 SYSCTL_ROOT_NODE(OID_AUTO, dev, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
     NULL);
 
+static bool disable_failed_devs = false;
+SYSCTL_BOOL(_hw_bus, OID_AUTO, disable_failed_devices, CTLFLAG_RWTUN, 
&disable_failed_devs,
+    0, "Do not retry attaching devices that return an error from DEVICE_ATTACH 
the first time");
+
 /*
  * Used to attach drivers to devclasses.
  */
@@ -2533,12 +2537,29 @@ device_attach(device_t dev)
        if ((error = DEVICE_ATTACH(dev)) != 0) {
                printf("device_attach: %s%d attach returned %d\n",
                    dev->driver->name, dev->unit, error);
-               if (!(dev->flags & DF_FIXEDCLASS))
-                       devclass_delete_device(dev->devclass, dev);
-               (void)device_set_driver(dev, NULL);
-               device_sysctl_fini(dev);
-               KASSERT(dev->busy == 0, ("attach failed but busy"));
-               dev->state = DS_NOTPRESENT;
+               if (disable_failed_devs) {
+                       /*
+                        * When the user has asked to disable failed devices, we
+                        * directly disable the device, but leave it in the
+                        * attaching state. It will not try to probe/attach the
+                        * device further. This leaves the device numbering
+                        * intact for other similar devices in the system. It
+                        * can be removed from this state with devctl.
+                        */
+                       device_disable(dev);
+               } else {
+                       /*
+                        * Otherwise, when attach fails, tear down the state
+                        * around that so we can retry when, for example, new
+                        * drivers are loaded.
+                        */
+                       if (!(dev->flags & DF_FIXEDCLASS))
+                               devclass_delete_device(dev->devclass, dev);
+                       (void)device_set_driver(dev, NULL);
+                       device_sysctl_fini(dev);
+                       KASSERT(dev->busy == 0, ("attach failed but busy"));
+                       dev->state = DS_NOTPRESENT;
+               }
                return (error);
        }
        dev->flags |= DF_ATTACHED_ONCE;

Reply via email to