Source-Changes-HG archive

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

[src/trunk]: src In pmf(9), improve the implementation of device self-suspension



details:   https://anonhg.NetBSD.org/src/rev/55e1b1539110
branches:  trunk
changeset: 747471:55e1b1539110
user:      dyoung <dyoung%NetBSD.org@localhost>
date:      Wed Sep 16 16:34:49 2009 +0000

description:
In pmf(9), improve the implementation of device self-suspension
and make suspension by self, by drvctl(8), and by ACPI system sleep
play nice together.  Start solidifying some temporary API changes.

1. Extract a new header file, <sys/device_if.h>, from <sys/device.h> and
   #include it from <sys/pmf.h> instead of <sys/device.h> to break the
   circular dependency between <sys/device.h> and <sys/pmf.h>.

2. Introduce pmf_qual_t, an aggregate of qualifications on a PMF
   suspend/resume call.  Start to replace instances of PMF_FN_PROTO,
   PMF_FN_ARGS, et cetera, with a pmf_qual_t.

3. Introduce the notion of a "suspensor," an entity that holds a
   device in suspension.  More than one suspensor may hold a device
   at once.  A device stays suspended as long as at least one
   suspensor holds it.  A device resumes when the last suspensor
   releases it.

   Currently, the kernel defines three suspensors,

   3a the system-suspensor: for system suspension, initiated
      by 'sysctl -w machdep.sleep_state=3', by lid closure, by
      power-button press, et cetera,

   3b the drvctl-suspensor: for device suspension by /dev/drvctl
      ioctl, e.g., drvctl -S sip0.

   3c the system self-suspensor: for device drivers that suspend
      themselves and their children.  Several drivers for network
      interfaces put the network device to sleep while it is not
      administratively up, that is, after the kernel calls if_stop(,
      1).  The self-suspensor should not be used directly.  See
      the description of suspensor delegates, below.

   A suspensor can have one or more "delegates".  A suspensor can
   release devices that its delegates hold suspended.  Right now,
   only the system self-suspensor has delegates.  For each device
   that a self-suspending driver attaches, it creates the device's
   self-suspensor, a delegate of the system self-suspensor.

   Suspensors stop a system-wide suspend/resume cycle from waking
   devices that the operator put to sleep with drvctl before the cycle.
   They also help self-suspension to work more simply, safely, and in
   accord with expectations.

4. Add the notion of device activation level, devact_level_t,
   and a routine for checking the current activation level,
   device_activation().  Current activation levels are DEVACT_LEVEL_BUS,
   DEVACT_LEVEL_DRIVER, and DEVACT_LEVEL_CLASS, which respectively
   indicate that the device's bus is active, that the bus and device are
   active, and that the bus, device, and the functions of the device's
   class (network, audio) are active.

   Suspend/resume calls can be qualified with a devact_level_t.
   The power-management framework treats a devact_level_t that
   qualifies a device suspension as the device's current activation
   level; it only runs hooks to reduce the activation level from
   the presumed current level to the fully suspended state.  The
   framework treats a devact_level_t qualifying device resumption
   as the target activation level; it only runs hooks to raise the
   activation level to the target.

5. Use pmf_qual_t, devact_level_t, and self-suspensors in several
   drivers.

6. Temporarily add an unused power-management workqueue that I will
   remove or replace, soon.

diffstat:

 distrib/sets/lists/comp/mi       |    3 +-
 sys/dev/acpi/acpi.c              |   10 +-
 sys/dev/apm/apm.c                |   10 +-
 sys/dev/audio.c                  |   14 +-
 sys/dev/cardbus/if_ath_cardbus.c |    6 +-
 sys/dev/cardbus/if_atw_cardbus.c |   72 ++---
 sys/dev/cardbus/if_rtw_cardbus.c |   10 +-
 sys/dev/ic/ath.c                 |   30 +-
 sys/dev/ic/athvar.h              |    4 +-
 sys/dev/ic/atw.c                 |  148 +++++-------
 sys/dev/ic/atwvar.h              |   12 +-
 sys/dev/ic/rtw.c                 |   32 +-
 sys/dev/ic/rtwvar.h              |    5 +-
 sys/dev/pci/if_ath_pci.c         |   11 +-
 sys/dev/pci/if_atw_pci.c         |   51 ++-
 sys/dev/pci/if_rtw_pci.c         |   10 +-
 sys/dev/pci/if_sip.c             |   19 +-
 sys/kern/kern_drvctl.c           |   10 +-
 sys/kern/kern_pmf.c              |  447 +++++++++++++++++++++++++++++++++++---
 sys/kern/subr_autoconf.c         |  108 +++-----
 sys/sys/Makefile                 |    8 +-
 sys/sys/device.h                 |   20 +-
 sys/sys/device_if.h              |   23 ++
 sys/sys/pmf.h                    |   63 ++++-
 24 files changed, 774 insertions(+), 352 deletions(-)

diffs (truncated from 2322 to 300 lines):

diff -r b6efb768d90d -r 55e1b1539110 distrib/sets/lists/comp/mi
--- a/distrib/sets/lists/comp/mi        Wed Sep 16 15:23:04 2009 +0000
+++ b/distrib/sets/lists/comp/mi        Wed Sep 16 16:34:49 2009 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: mi,v 1.1308 2009/09/12 10:33:44 phx Exp $
+#      $NetBSD: mi,v 1.1309 2009/09/16 16:34:49 dyoung Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -1953,6 +1953,7 @@
 ./usr/include/sys/cpu_data.h                   comp-obsolete           obsolete
 ./usr/include/sys/cpuio.h                      comp-c-include
 ./usr/include/sys/device.h                     comp-c-include
+./usr/include/sys/device_if.h                  comp-c-include
 ./usr/include/sys/dir.h                                comp-c-include
 ./usr/include/sys/dirent.h                     comp-c-include
 ./usr/include/sys/disk.h                       comp-c-include
diff -r b6efb768d90d -r 55e1b1539110 sys/dev/acpi/acpi.c
--- a/sys/dev/acpi/acpi.c       Wed Sep 16 15:23:04 2009 +0000
+++ b/sys/dev/acpi/acpi.c       Wed Sep 16 16:34:49 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpi.c,v 1.132 2009/09/16 10:47:54 mlelstv Exp $       */
+/*     $NetBSD: acpi.c,v 1.133 2009/09/16 16:34:49 dyoung Exp $        */
 
 /*-
  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.132 2009/09/16 10:47:54 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.133 2009/09/16 16:34:49 dyoung Exp $");
 
 #include "opt_acpi.h"
 #include "opt_pcifixup.h"
@@ -1416,7 +1416,7 @@
 
                acpi_wakedev_commit(sc);
 
-               if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_F_NONE)) {
+               if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_Q_NONE)) {
                        aprint_error_dev(sc->sc_dev, "aborting suspend\n");
                        break;
                }
@@ -1443,9 +1443,9 @@
                        err = acpi_md_sleep(state);
                        if (state == ACPI_STATE_S4)
                                AcpiEnable();
-                       pmf_system_bus_resume(PMF_F_NONE);
+                       pmf_system_bus_resume(PMF_Q_NONE);
                        AcpiLeaveSleepState((UINT8)state);
-                       pmf_system_resume(PMF_F_NONE);
+                       pmf_system_resume(PMF_Q_NONE);
                }
 
                break;
diff -r b6efb768d90d -r 55e1b1539110 sys/dev/apm/apm.c
--- a/sys/dev/apm/apm.c Wed Sep 16 15:23:04 2009 +0000
+++ b/sys/dev/apm/apm.c Wed Sep 16 16:34:49 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: apm.c,v 1.23 2009/04/03 04:25:40 uwe Exp $ */
+/*     $NetBSD: apm.c,v 1.24 2009/09/16 16:34:49 dyoung Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.23 2009/04/03 04:25:40 uwe Exp $");
+__KERNEL_RCSID(0, "$NetBSD: apm.c,v 1.24 2009/09/16 16:34:49 dyoung Exp $");
 
 #include "opt_apm.h"
 
@@ -309,7 +309,7 @@
        sc->sc_power_state = PWR_SUSPEND;
  
        if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) {
-               pmf_system_suspend(PMF_F_NONE);
+               pmf_system_suspend(PMF_Q_NONE);
                apm_spl = splhigh();
        }
 
@@ -335,7 +335,7 @@
        sc->sc_power_state = PWR_STANDBY;
 
        if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) {
-               pmf_system_suspend(PMF_F_NONE);
+               pmf_system_suspend(PMF_Q_NONE);
                apm_spl = splhigh();
        }
        error = (*sc->sc_ops->aa_set_powstate)(sc->sc_cookie, APM_DEV_ALLDEVS,
@@ -366,7 +366,7 @@
        inittodr(time_second);
        if (!(sc->sc_hwflags & APM_F_DONT_RUN_HOOKS)) {
                splx(apm_spl);
-               pmf_system_resume(PMF_F_NONE);
+               pmf_system_resume(PMF_Q_NONE);
        }
 
        apm_record_event(sc, event_type);
diff -r b6efb768d90d -r 55e1b1539110 sys/dev/audio.c
--- a/sys/dev/audio.c   Wed Sep 16 15:23:04 2009 +0000
+++ b/sys/dev/audio.c   Wed Sep 16 16:34:49 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.244 2009/04/17 20:04:35 dyoung Exp $       */
+/*     $NetBSD: audio.c,v 1.245 2009/09/16 16:34:50 dyoung Exp $       */
 
 /*
  * Copyright (c) 1991-1993 Regents of the University of California.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.244 2009/04/17 20:04:35 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.245 2009/09/16 16:34:50 dyoung Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
@@ -3998,11 +3998,11 @@
        sc->sc_idle = true;
 
        /* XXX joerg Make pmf_device_suspend handle children? */
-       if (!pmf_device_suspend(dv, PMF_F_SELF))
+       if (!pmf_device_suspend(dv, PMF_Q_SELF))
                return;
 
-       if (!pmf_device_suspend(sc->sc_dev, PMF_F_SELF))
-               pmf_device_resume(dv, PMF_F_SELF);
+       if (!pmf_device_suspend(sc->sc_dev, PMF_Q_SELF))
+               pmf_device_resume(dv, PMF_Q_SELF);
 }
 
 static void
@@ -4018,8 +4018,8 @@
        sc->sc_idle = false;
        if (!device_is_active(dv)) {
                /* XXX joerg How to deal with a failing resume... */
-               pmf_device_resume(sc->sc_dev, PMF_F_SELF);
-               pmf_device_resume(dv, PMF_F_SELF);
+               pmf_device_resume(sc->sc_dev, PMF_Q_SELF);
+               pmf_device_resume(dv, PMF_Q_SELF);
        }
 }
 #endif
diff -r b6efb768d90d -r 55e1b1539110 sys/dev/cardbus/if_ath_cardbus.c
--- a/sys/dev/cardbus/if_ath_cardbus.c  Wed Sep 16 15:23:04 2009 +0000
+++ b/sys/dev/cardbus/if_ath_cardbus.c  Wed Sep 16 16:34:49 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_ath_cardbus.c,v 1.34 2009/09/05 14:50:10 tsutsui Exp $ */
+/*     $NetBSD: if_ath_cardbus.c,v 1.35 2009/09/16 16:34:50 dyoung Exp $ */
 /*
  * Copyright (c) 2003
  *     Ichiro FUKUHARA <ichiro%ichiro.org@localhost>.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ath_cardbus.c,v 1.34 2009/09/05 14:50:10 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ath_cardbus.c,v 1.35 2009/09/16 16:34:50 dyoung Exp $");
 
 #include "opt_inet.h"
 #include "bpfilter.h"
@@ -218,7 +218,7 @@
        if (pmf_device_register(self,
            ath_cardbus_suspend, ath_cardbus_resume)) {
                pmf_class_network_register(self, &sc->sc_if);
-               pmf_device_suspend_self(self);
+               pmf_device_suspend(self, &sc->sc_qual);
        } else
                aprint_error_dev(self, "couldn't establish power handler\n");
 }
diff -r b6efb768d90d -r 55e1b1539110 sys/dev/cardbus/if_atw_cardbus.c
--- a/sys/dev/cardbus/if_atw_cardbus.c  Wed Sep 16 15:23:04 2009 +0000
+++ b/sys/dev/cardbus/if_atw_cardbus.c  Wed Sep 16 16:34:49 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_atw_cardbus.c,v 1.26 2009/04/02 00:09:33 dyoung Exp $ */
+/* $NetBSD: if_atw_cardbus.c,v 1.27 2009/09/16 16:34:50 dyoung Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2003 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.26 2009/04/02 00:09:33 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_atw_cardbus.c,v 1.27 2009/09/16 16:34:50 dyoung Exp $");
 
 #include "opt_inet.h"
 #include "bpfilter.h"
@@ -122,8 +122,8 @@
 
 static void    atw_cardbus_setup(struct atw_cardbus_softc *);
 
-static int     atw_cardbus_enable(struct atw_softc *);
-static void    atw_cardbus_disable(struct atw_softc *);
+static bool    atw_cardbus_suspend(device_t PMF_FN_PROTO);
+static bool    atw_cardbus_resume(device_t PMF_FN_PROTO);
 
 static const struct atw_cardbus_product *atw_cardbus_lookup
    (const struct cardbus_attach_args *);
@@ -196,12 +196,6 @@
                panic("atw_cardbus_attach: impossible");
        }
 
-       /*
-        * Power management hooks.
-        */
-       sc->sc_enable = atw_cardbus_enable;
-       sc->sc_disable = atw_cardbus_disable;
-
        /* Get revision info. */
        sc->sc_rev = PCI_REVISION(ca->ca_class);
 
@@ -271,24 +265,32 @@
        sc->sc_txthresh = 3; /* TBD name constant */
 #endif
 
-       /*
-        * Finish off the attach.
-        */
-       atw_attach(sc);
-
 #if 0
        for (i = 0; i < __arraycount(funcregs); i++) {
                aprint_error_dev(sc->sc_dev, "%s %" PRIx32 "\n",
                    funcregs[i].name, ATW_READ(sc, funcregs[i].ofs));
        }
 #endif
+
        ATW_WRITE(sc, ATW_FEMR, 0);
        ATW_WRITE(sc, ATW_FER, ATW_READ(sc, ATW_FER));
 
        /*
+        * Bus-independent attach.
+        */
+       atw_attach(sc);
+
+       if (pmf_device_register1(sc->sc_dev, atw_cardbus_suspend,
+           atw_cardbus_resume, atw_shutdown))
+               pmf_class_network_register(sc->sc_dev, &sc->sc_if);
+       else
+               aprint_error_dev(sc->sc_dev,
+                   "couldn't establish power handler\n");
+
+       /*
         * Power down the socket.
         */
-       Cardbus_function_disable(csc->sc_ct);
+       pmf_device_suspend(sc->sc_dev, &sc->sc_qual);
 }
 
 static int
@@ -324,43 +326,32 @@
        return 0;
 }
 
-static int
-atw_cardbus_enable(struct atw_softc *sc)
+static bool
+atw_cardbus_resume(device_t self PMF_FN_ARGS)
 {
-       struct atw_cardbus_softc *csc = (struct atw_cardbus_softc *)sc;
+       struct atw_cardbus_softc *csc = device_private(self);
+       struct atw_softc *sc = &csc->sc_atw;
        cardbus_devfunc_t ct = csc->sc_ct;
        cardbus_chipset_tag_t cc = ct->ct_cc;
        cardbus_function_tag_t cf = ct->ct_cf;
 
        /*
-        * Power on the socket.
-        */
-       Cardbus_function_enable(ct);
-
-       /*
-        * Set up the PCI configuration registers.
-        */
-       atw_cardbus_setup(csc);
-
-       /*
         * Map and establish the interrupt.
         */
        csc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET,
            atw_intr, sc);
        if (csc->sc_ih == NULL) {
-               aprint_error_dev(sc->sc_dev,
-                                "unable to establish interrupt\n");
-               Cardbus_function_disable(csc->sc_ct);
-               return 1;
+               aprint_error_dev(sc->sc_dev, "unable to establish interrupt\n");
+               return false;
        }
 
-       return 0;
+       return true;
 }
 
-static void
-atw_cardbus_disable(struct atw_softc *sc)
+static bool



Home | Main Index | Thread Index | Old Index