tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: [drochner%netbsd.org@localhost: CVS commit: src/sys/kern]



M.Drochner%fz-juelich.de@localhost said:
> I've got some ideas how to seperate the shutdown functions from
> suspend while using the pmf structures for ordering. Please give me an
> hour to two to formulate this in C. 

Ok it is straightforward, and has passed some testing.
Here is it, the "wd" shutdownhook is converted as an example.

My intention is mainly to allow the drivers to sort out
the actions needed for system suspend vs. shutdown, without
breaking API compatibility.
As a bonus, disabling DMA of PCI devices on shutdown is ensured,
whether the individual drivers care or not.

best regards
Matthias

(I'll be unavailable for the weekend, so take your time
to comment:-)





-------------------------------------------------------------------
-------------------------------------------------------------------
Forschungszentrum Juelich GmbH
52425 Juelich

Sitz der Gesellschaft: Juelich
Eingetragen im Handelsregister des Amtsgerichts Dueren Nr. HR B 3498
Vorsitzende des Aufsichtsrats: MinDir'in Baerbel Brumme-Bothe
Geschaeftsfuehrung: Prof. Dr. Achim Bachem (Vorsitzender),
Dr. Ulrich Krafft (stellv. Vorsitzender), Prof. Dr. Harald Bolt,
Dr. Sebastian M. Schmidt
-------------------------------------------------------------------
-------------------------------------------------------------------
#
# old_revision [08c89761b78a89cfe820ff73f0de234af2720548]
#
# patch "sys/dev/ata/wd.c"
#  from [6bee0a76d876e0c20723f818be484c0675170b63]
#    to [d9f7961e451ba27253e54baccb8bfe8283db2451]
# 
# patch "sys/dev/ata/wdvar.h"
#  from [0b8a56a70bba89fbdc6e61acba6cb4a440a157a8]
#    to [2e28e22eec82cb32b11d597a98c11e857e7929ba]
# 
# patch "sys/dev/pci/pci.c"
#  from [21c8d60ef747b0027db8405f3d9012f9eda73b88]
#    to [b2de66d581a6d1a2a431b6835b92c294f1583902]
# 
# patch "sys/kern/kern_pmf.c"
#  from [588065989f69c940a45cc9834ef626a11b87d594]
#    to [52d14868f17de54af4a0b46726e8c45c447a27cd]
# 
# patch "sys/kern/kern_subr.c"
#  from [1bb7c6949a1a3715bf89614dd7bb79d4a0415c4b]
#    to [470f6adcff74c6be3130fba5131233e369cc4b1e]
# 
# patch "sys/kern/subr_autoconf.c"
#  from [c12a649533928ec237fa70592d34cc86ac8e91fe]
#    to [2b56f8546fd90d34724370d493d43592f18ec2b5]
# 
# patch "sys/sys/device.h"
#  from [9fa05caad7bd02c45d2005964ec7a0ae2ebe9b6c]
#    to [6a1f524647cfc2671e4d81f829d795e0d545fef8]
# 
# patch "sys/sys/pmf.h"
#  from [74e5ca388e62c84e2b1d7b077ebaaf3b4de3bbb9]
#    to [e610ac3c4191daf85afe0c91588af20fa9ba7c79]
#
============================================================
--- sys/dev/ata/wd.c    6bee0a76d876e0c20723f818be484c0675170b63
+++ sys/dev/ata/wd.c    d9f7961e451ba27253e54baccb8bfe8283db2451
@@ -194,7 +194,7 @@ int   wd_flushcache(struct wd_softc *, i
 void  wddone(void *);
 int   wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *);
 int   wd_flushcache(struct wd_softc *, int);
-void  wd_shutdown(void *);
+bool  wd_shutdown(device_t, int);
 
 int   wd_getcache(struct wd_softc *, int *);
 int   wd_setcache(struct wd_softc *, int);
@@ -417,10 +417,6 @@ wdattach(struct device *parent, struct d
        disk_init(&wd->sc_dk, wd->sc_dev.dv_xname, &wddkdriver);
        disk_attach(&wd->sc_dk);
        wd->sc_wdc_bio.lp = wd->sc_dk.dk_label;
-       wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd);
-       if (wd->sc_sdhook == NULL)
-               aprint_error("%s: WARNING: unable to establish shutdown hook\n",
-                       wd->sc_dev.dv_xname);
 #if NRND > 0
        rnd_attach_source(&wd->rnd_source, wd->sc_dev.dv_xname,
                          RND_TYPE_DISK, 0);
@@ -429,7 +425,7 @@ wdattach(struct device *parent, struct d
        /* Discover wedges on this disk. */
        dkwedge_discover(&wd->sc_dk);
 
-       if (!pmf_device_register(self, wd_suspend, NULL))
+       if (!pmf_device_register1(self, wd_suspend, NULL, wd_shutdown))
                aprint_error_dev(self, "couldn't establish power handler\n");
 }
 
@@ -505,10 +501,6 @@ wddetach(struct device *self, int flags)
        sc->sc_bscount = 0;
 #endif
 
-       /* Get rid of the shutdown hook. */
-       if (sc->sc_sdhook != NULL)
-               shutdownhook_disestablish(sc->sc_sdhook);
-
        pmf_device_deregister(self);
 
 #if NRND > 0
@@ -1948,14 +1940,15 @@ wd_flushcache(struct wd_softc *wd, int f
        return 0;
 }
 
-void
-wd_shutdown(void *arg)
+bool
+wd_shutdown(device_t dev, int how)
 {
 
-       struct wd_softc *wd = arg;
+       struct wd_softc *wd = device_private(dev);
        wd_flushcache(wd, AT_POLL);
-       if ((boothowto & RB_POWERDOWN) == RB_POWERDOWN)
+       if ((how & RB_POWERDOWN) == RB_POWERDOWN)
                wd_standby(wd, AT_POLL);
+       return true;
 }
 
 /*
============================================================
--- sys/dev/ata/wdvar.h 0b8a56a70bba89fbdc6e61acba6cb4a440a157a8
+++ sys/dev/ata/wdvar.h 2e28e22eec82cb32b11d597a98c11e857e7929ba
@@ -66,8 +66,6 @@ struct wd_softc {
 
        int retries; /* number of xfer retry */
 
-       void *sc_sdhook;                /* our shutdown hook */
-
 #ifdef WD_SOFTBADSECT
        SLIST_HEAD(, disk_badsectors)   sc_bslist;
        u_int sc_bscount;
============================================================
--- sys/dev/pci/pci.c   21c8d60ef747b0027db8405f3d9012f9eda73b88
+++ sys/dev/pci/pci.c   b2de66d581a6d1a2a431b6835b92c294f1583902
@@ -898,6 +898,19 @@ pci_child_resume(device_t dv)
        return true;
 }
 
+static bool
+pci_child_shutdown(device_t dv, int how)
+{
+       struct pci_child_power *priv = device_pmf_bus_private(dv);
+       pcireg_t csr;
+
+       /* disable busmastering */
+       csr = pci_conf_read(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG);
+       csr &= ~PCI_COMMAND_MASTER_ENABLE;
+       pci_conf_write(priv->p_pc, priv->p_tag, PCI_COMMAND_STATUS_REG, csr);
+       return true;
+}
+
 static void
 pci_child_deregister(device_t dv)
 {
@@ -936,7 +949,7 @@ pci_child_register(device_t child)
        }
 
        device_pmf_bus_register(child, priv, pci_child_suspend,
-           pci_child_resume, pci_child_deregister);
+           pci_child_resume, pci_child_shutdown, pci_child_deregister);
 
        return true;
 }
============================================================
--- sys/kern/kern_pmf.c 588065989f69c940a45cc9834ef626a11b87d594
+++ sys/kern/kern_pmf.c 52d14868f17de54af4a0b46726e8c45c447a27cd
@@ -284,7 +284,7 @@ void
 }
 
 void
-pmf_system_shutdown(void)
+pmf_system_shutdown(int how)
 {
        int depth, maxdepth;
        device_t curdev;
@@ -308,14 +308,20 @@ pmf_system_shutdown(void)
 
                        if (!device_pmf_is_registered(curdev))
                                continue;
-                       if (!device_pmf_class_suspend(curdev)) {
+#if 0 /* needed? */
+                       if (!device_pmf_class_shutdown(curdev, how)) {
                                aprint_debug("(failed)");
                                continue;
                        }
-                       if (!device_pmf_driver_suspend(curdev)) {
+#endif
+                       if (!device_pmf_driver_shutdown(curdev, how)) {
                                aprint_debug("(failed)");
                                continue;
                        }
+                       if (!device_pmf_bus_shutdown(curdev, how)) {
+                               aprint_debug("(failed)");
+                               continue;
+                       }
                }
        }
 
@@ -348,10 +354,11 @@ bool
 }
 
 bool
-pmf_device_register(device_t dev,
-    bool (*suspend)(device_t), bool (*resume)(device_t))
+pmf_device_register1(device_t dev,
+    bool (*suspend)(device_t), bool (*resume)(device_t),
+    bool (*shutdown)(device_t, int))
 {
-       device_pmf_driver_register(dev, suspend, resume);
+       device_pmf_driver_register(dev, suspend, resume, shutdown);
 
        if (!device_pmf_driver_child_register(dev)) {
                device_pmf_driver_deregister(dev);
============================================================
--- sys/kern/kern_subr.c        1bb7c6949a1a3715bf89614dd7bb79d4a0415c4b
+++ sys/kern/kern_subr.c        470f6adcff74c6be3130fba5131233e369cc4b1e
@@ -496,6 +496,8 @@ doshutdownhooks(void)
                free(dp, M_DEVBUF);
 #endif
        }
+
+       pmf_system_shutdown(boothowto);
 }
 
 /*
============================================================
--- sys/kern/subr_autoconf.c    c12a649533928ec237fa70592d34cc86ac8e91fe
+++ sys/kern/subr_autoconf.c    2b56f8546fd90d34724370d493d43592f18ec2b5
@@ -1876,12 +1876,24 @@ device_pmf_driver_resume(device_t dev)
        return true;
 }
 
+bool
+device_pmf_driver_shutdown(device_t dev, int how)
+{
+
+       if (*dev->dv_driver_shutdown != NULL &&
+           !(*dev->dv_driver_shutdown)(dev, how))
+               return false;
+       return true;
+}
+
 void
 device_pmf_driver_register(device_t dev,
-    bool (*suspend)(device_t), bool (*resume)(device_t))
+    bool (*suspend)(device_t), bool (*resume)(device_t),
+    bool (*shutdown)(device_t, int))
 {
        dev->dv_driver_suspend = suspend;
        dev->dv_driver_resume = resume;
+       dev->dv_driver_shutdown = shutdown;
        dev->dv_flags |= DVF_POWER_HANDLERS;
 }
 
@@ -1945,14 +1957,25 @@ device_pmf_bus_resume(device_t dev)
        return true;
 }
 
+bool
+device_pmf_bus_shutdown(device_t dev, int how)
+{
+
+       if (*dev->dv_bus_shutdown != NULL &&
+           !(*dev->dv_bus_shutdown)(dev, how))
+               return false;
+       return true;
+}
+
 void
 device_pmf_bus_register(device_t dev, void *priv,
     bool (*suspend)(device_t), bool (*resume)(device_t),
-    void (*deregister)(device_t))
+    bool (*shutdown)(device_t, int), void (*deregister)(device_t))
 {
        dev->dv_bus_private = priv;
        dev->dv_bus_resume = resume;
        dev->dv_bus_suspend = suspend;
+       dev->dv_bus_shutdown = shutdown;
        dev->dv_bus_deregister = deregister;
 }
 
============================================================
--- sys/sys/device.h    9fa05caad7bd02c45d2005964ec7a0ae2ebe9b6c
+++ sys/sys/device.h    6a1f524647cfc2671e4d81f829d795e0d545fef8
@@ -142,11 +142,13 @@ struct device {
 
        bool            (*dv_driver_suspend)(device_t);
        bool            (*dv_driver_resume)(device_t);
+       bool            (*dv_driver_shutdown)(device_t, int);
        bool            (*dv_driver_child_register)(device_t);
 
        void            *dv_bus_private;
        bool            (*dv_bus_suspend)(device_t);
        bool            (*dv_bus_resume)(device_t);
+       bool            (*dv_bus_shutdown)(device_t, int);
        void            (*dv_bus_deregister)(device_t);
 
        void            *dv_class_private;
@@ -450,9 +452,11 @@ bool               device_pmf_driver_resume(device_t)
 
 bool           device_pmf_driver_suspend(device_t);
 bool           device_pmf_driver_resume(device_t);
+bool           device_pmf_driver_shutdown(device_t, int);
 
 void           device_pmf_driver_register(device_t,
-                   bool (*)(device_t), bool (*)(device_t));
+                   bool (*)(device_t), bool (*)(device_t),
+                   bool (*)(device_t, int));
 void           device_pmf_driver_deregister(device_t);
 
 bool           device_pmf_driver_child_register(device_t);
@@ -462,9 +466,11 @@ bool               device_pmf_bus_resume(device_t);
 void           *device_pmf_bus_private(device_t);
 bool           device_pmf_bus_suspend(device_t);
 bool           device_pmf_bus_resume(device_t);
+bool           device_pmf_bus_shutdown(device_t, int);
 
 void           device_pmf_bus_register(device_t, void *,
                    bool (*)(device_t), bool (*)(device_t),
+                   bool (*)(device_t, int),
                    void (*)(device_t));
 void           device_pmf_bus_deregister(device_t);
 
============================================================
--- sys/sys/pmf.h       74e5ca388e62c84e2b1d7b077ebaaf3b4de3bbb9
+++ sys/sys/pmf.h       e610ac3c4191daf85afe0c91588af20fa9ba7c79
@@ -68,11 +68,15 @@ bool                pmf_system_suspend(void);
 bool           pmf_system_resume(void);
 bool           pmf_system_bus_resume(void);
 bool           pmf_system_suspend(void);
-void           pmf_system_shutdown(void);
+void           pmf_system_shutdown(int);
 
-bool           pmf_device_register(device_t,
+bool           pmf_device_register1(device_t,
                    bool (*)(device_t),
-                   bool (*)(device_t));
+                   bool (*)(device_t),
+                   bool (*)(device_t, int));
+/* compatibility */
+#define pmf_device_register(d, s, r) pmf_device_register1((d), (s), (r), 0)
+
 void           pmf_device_deregister(device_t);
 bool           pmf_device_suspend(device_t);
 bool           pmf_device_resume(device_t);


Home | Main Index | Thread Index | Old Index