summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpica/acpi.c4
-rw-r--r--sys/dev/acpica/acpi_pcib.c11
-rw-r--r--sys/dev/acpica/acpi_pcib_acpi.c1
-rw-r--r--sys/dev/acpica/acpi_pcib_pci.c1
-rw-r--r--sys/dev/acpica/acpi_pcibvar.h2
-rw-r--r--sys/dev/acpica/acpivar.h2
-rw-r--r--sys/dev/pci/pci.c53
-rw-r--r--sys/dev/pci/pci_pci.c41
-rw-r--r--sys/dev/pci/pci_private.h2
-rw-r--r--sys/dev/pci/pcib_if.m10
10 files changed, 72 insertions, 55 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index f173dc3..feef2cc 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -129,8 +129,6 @@ static char *acpi_device_id_probe(device_t bus, device_t dev, char **ids);
static ACPI_STATUS acpi_device_eval_obj(device_t bus, device_t dev,
ACPI_STRING pathname, ACPI_OBJECT_LIST *parameters,
ACPI_BUFFER *ret);
-static int acpi_device_pwr_for_sleep(device_t bus, device_t dev,
- int *dstate);
static ACPI_STATUS acpi_device_scan_cb(ACPI_HANDLE h, UINT32 level,
void *context, void **retval);
static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev,
@@ -1415,7 +1413,7 @@ acpi_device_eval_obj(device_t bus, device_t dev, ACPI_STRING pathname,
return (AcpiEvaluateObject(h, pathname, parameters, ret));
}
-static int
+int
acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate)
{
struct acpi_softc *sc;
diff --git a/sys/dev/acpica/acpi_pcib.c b/sys/dev/acpica/acpi_pcib.c
index 65996f5..1b26b4f 100644
--- a/sys/dev/acpica/acpi_pcib.c
+++ b/sys/dev/acpica/acpi_pcib.c
@@ -275,3 +275,14 @@ out:
return_VALUE (interrupt);
}
+
+int
+acpi_pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate)
+{
+ device_t acpi_dev;
+
+ acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
+ acpi_device_pwr_for_sleep(acpi_dev, dev, pstate);
+ return (0);
+}
+
diff --git a/sys/dev/acpica/acpi_pcib_acpi.c b/sys/dev/acpica/acpi_pcib_acpi.c
index 7275330..2ea9f2c 100644
--- a/sys/dev/acpica/acpi_pcib_acpi.c
+++ b/sys/dev/acpica/acpi_pcib_acpi.c
@@ -116,6 +116,7 @@ static device_method_t acpi_pcib_acpi_methods[] = {
DEVMETHOD(pcib_alloc_msix, acpi_pcib_alloc_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, acpi_pcib_map_msi),
+ DEVMETHOD(pcib_power_for_sleep, acpi_pcib_power_for_sleep),
{0, 0}
};
diff --git a/sys/dev/acpica/acpi_pcib_pci.c b/sys/dev/acpica/acpi_pcib_pci.c
index 2196940..a766981 100644
--- a/sys/dev/acpica/acpi_pcib_pci.c
+++ b/sys/dev/acpica/acpi_pcib_pci.c
@@ -80,6 +80,7 @@ static device_method_t acpi_pcib_pci_methods[] = {
/* pcib interface */
DEVMETHOD(pcib_route_interrupt, acpi_pcib_pci_route_interrupt),
+ DEVMETHOD(pcib_power_for_sleep, acpi_pcib_power_for_sleep),
{0, 0}
};
diff --git a/sys/dev/acpica/acpi_pcibvar.h b/sys/dev/acpica/acpi_pcibvar.h
index 00e03fa..9a4be07 100644
--- a/sys/dev/acpica/acpi_pcibvar.h
+++ b/sys/dev/acpica/acpi_pcibvar.h
@@ -38,6 +38,8 @@ int acpi_pci_link_route_interrupt(device_t dev, int index);
int acpi_pcib_attach(device_t bus, ACPI_BUFFER *prt, int busno);
int acpi_pcib_route_interrupt(device_t pcib, device_t dev, int pin,
ACPI_BUFFER *prtbuf);
+int acpi_pcib_power_for_sleep(device_t pcib, device_t dev,
+ int *pstate);
#endif /* _KERNEL */
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index adc9d6e..34284d5 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -393,6 +393,8 @@ EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t);
/* Device power control. */
ACPI_STATUS acpi_pwr_wake_enable(ACPI_HANDLE consumer, int enable);
ACPI_STATUS acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state);
+int acpi_device_pwr_for_sleep(device_t bus, device_t dev,
+ int *dstate);
/* Misc. */
static __inline struct acpi_softc *
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index e1c7645..071f257 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -69,13 +69,6 @@ __FBSDID("$FreeBSD$");
#include "pcib_if.h"
#include "pci_if.h"
-#ifdef __HAVE_ACPI
-#include <contrib/dev/acpica/include/acpi.h>
-#include "acpi_if.h"
-#else
-#define ACPI_PWR_FOR_SLEEP(x, y, z)
-#endif
-
static pci_addr_t pci_mapbase(uint64_t mapreg);
static const char *pci_maptype(uint64_t mapreg);
static int pci_mapsize(uint64_t testval);
@@ -2914,16 +2907,13 @@ int
pci_suspend(device_t dev)
{
int dstate, error, i, numdevs;
- device_t acpi_dev, child, *devlist;
+ device_t child, *devlist, pcib;
struct pci_devinfo *dinfo;
/*
* Save the PCI configuration space for each child and set the
* device in the appropriate power state for this sleep state.
*/
- acpi_dev = NULL;
- if (pci_do_power_resume)
- acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
if ((error = device_get_children(dev, &devlist, &numdevs)) != 0)
return (error);
for (i = 0; i < numdevs; i++) {
@@ -2940,22 +2930,23 @@ pci_suspend(device_t dev)
}
/*
- * Always set the device to D3. If ACPI suggests a different
- * power state, use it instead. If ACPI is not present, the
- * firmware is responsible for managing device power. Skip
- * children who aren't attached since they are powered down
- * separately. Only manage type 0 devices for now.
+ * Always set the device to D3. If the firmware suggests a
+ * different power state, use it instead. If power management
+ * is not present, the firmware is responsible for managing
+ * device power. Skip children who aren't attached since they
+ * are powered down separately. Only manage type 0 devices
+ * for now.
*/
- for (i = 0; acpi_dev && i < numdevs; i++) {
+ pcib = device_get_parent(dev);
+ for (i = 0; pci_do_power_resume && i < numdevs; i++) {
child = devlist[i];
dinfo = (struct pci_devinfo *) device_get_ivars(child);
+ dstate = PCI_POWERSTATE_D3;
if (device_is_attached(child) &&
(dinfo->cfg.hdrtype & PCIM_HDRTYPE) ==
- PCIM_HDRTYPE_NORMAL) {
- dstate = PCI_POWERSTATE_D3;
- ACPI_PWR_FOR_SLEEP(acpi_dev, child, &dstate);
+ PCIM_HDRTYPE_NORMAL &&
+ PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
pci_set_powerstate(child, dstate);
- }
}
free(devlist, M_TEMP);
return (0);
@@ -2965,31 +2956,29 @@ int
pci_resume(device_t dev)
{
int i, numdevs, error;
- device_t acpi_dev, child, *devlist;
+ device_t child, *devlist, pcib;
struct pci_devinfo *dinfo;
/*
* Set each child to D0 and restore its PCI configuration space.
*/
- acpi_dev = NULL;
- if (pci_do_power_resume)
- acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
if ((error = device_get_children(dev, &devlist, &numdevs)) != 0)
return (error);
+ pcib = device_get_parent(dev);
for (i = 0; i < numdevs; i++) {
/*
- * Notify ACPI we're going to D0 but ignore the result. If
- * ACPI is not present, the firmware is responsible for
- * managing device power. Only manage type 0 devices for now.
+ * Notify power managment we're going to D0 but ignore
+ * the result. If power management is not present,
+ * the firmware is responsible for managing device
+ * power. Only manage type 0 devices for now.
*/
child = devlist[i];
dinfo = (struct pci_devinfo *) device_get_ivars(child);
- if (acpi_dev && device_is_attached(child) &&
+ if (device_is_attached(child) &&
(dinfo->cfg.hdrtype & PCIM_HDRTYPE) ==
- PCIM_HDRTYPE_NORMAL) {
- ACPI_PWR_FOR_SLEEP(acpi_dev, child, NULL);
+ PCIM_HDRTYPE_NORMAL &&
+ PCIB_POWER_FOR_SLEEP(pcib, dev, NULL) == 0)
pci_set_powerstate(child, PCI_POWERSTATE_D0);
- }
/* Now the device is powered up, restore its config space. */
pci_cfg_restore(child, dinfo);
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 996d274..9992b81 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -48,22 +48,16 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pci_private.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
-#ifdef __HAVE_ACPI
-#include <contrib/dev/acpica/include/acpi.h>
-#include "acpi_if.h"
-#else
-#define ACPI_PWR_FOR_SLEEP(x, y, z)
-#endif
-
-extern int pci_do_power_resume;
-
static int pcib_probe(device_t dev);
static int pcib_suspend(device_t dev);
static int pcib_resume(device_t dev);
+static int pcib_power_for_sleep(device_t pcib, device_t dev,
+ int *pstate);
static device_method_t pcib_methods[] = {
/* Device interface */
@@ -95,6 +89,7 @@ static device_method_t pcib_methods[] = {
DEVMETHOD(pcib_alloc_msix, pcib_alloc_msix),
DEVMETHOD(pcib_release_msix, pcib_release_msix),
DEVMETHOD(pcib_map_msi, pcib_map_msi),
+ DEVMETHOD(pcib_power_for_sleep, pcib_power_for_sleep),
{ 0, 0 }
};
@@ -447,18 +442,16 @@ pcib_attach(device_t dev)
int
pcib_suspend(device_t dev)
{
- device_t acpi_dev;
+ device_t pcib;
int dstate, error;
pcib_cfg_save(device_get_softc(dev));
error = bus_generic_suspend(dev);
if (error == 0 && pci_do_power_resume) {
- acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
- if (acpi_dev != NULL) {
- dstate = PCI_POWERSTATE_D3;
- ACPI_PWR_FOR_SLEEP(acpi_dev, dev, &dstate);
+ dstate = PCI_POWERSTATE_D3;
+ pcib = device_get_parent(device_get_parent(dev));
+ if (PCIB_POWER_FOR_SLEEP(pcib, dev, &dstate) == 0)
pci_set_powerstate(dev, dstate);
- }
}
return (error);
}
@@ -466,14 +459,12 @@ pcib_suspend(device_t dev)
int
pcib_resume(device_t dev)
{
- device_t acpi_dev;
+ device_t pcib;
if (pci_do_power_resume) {
- acpi_dev = devclass_get_device(devclass_find("acpi"), 0);
- if (acpi_dev != NULL) {
- ACPI_PWR_FOR_SLEEP(acpi_dev, dev, NULL);
+ pcib = device_get_parent(device_get_parent(dev));
+ if (PCIB_POWER_FOR_SLEEP(pcib, dev, NULL) == 0)
pci_set_powerstate(dev, PCI_POWERSTATE_D0);
- }
}
pcib_cfg_restore(device_get_softc(dev));
return (bus_generic_resume(dev));
@@ -790,6 +781,16 @@ pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
return (0);
}
+/* Pass request for device power state up to parent bridge. */
+int
+pcib_power_for_sleep(device_t pcib, device_t dev, int *pstate)
+{
+ device_t bus;
+
+ bus = device_get_parent(pcib);
+ return (PCIB_POWER_FOR_SLEEP(bus, dev, pstate));
+}
+
/*
* Try to read the bus number of a host-PCI bridge using appropriate config
* registers.
diff --git a/sys/dev/pci/pci_private.h b/sys/dev/pci/pci_private.h
index 2240b4f..70d887b 100644
--- a/sys/dev/pci/pci_private.h
+++ b/sys/dev/pci/pci_private.h
@@ -38,6 +38,8 @@
*/
DECLARE_CLASS(pci_driver);
+extern int pci_do_power_resume;
+
void pci_add_children(device_t dev, int domain, int busno,
size_t dinfo_size);
void pci_add_child(device_t bus, struct pci_devinfo *dinfo);
diff --git a/sys/dev/pci/pcib_if.m b/sys/dev/pci/pcib_if.m
index 0b7e8bc..b946c0f 100644
--- a/sys/dev/pci/pcib_if.m
+++ b/sys/dev/pci/pcib_if.m
@@ -144,3 +144,13 @@ METHOD int map_msi {
uint64_t *addr;
uint32_t *data;
};
+
+#
+# Return the device power state to be used during a system sleep state
+# transition such as suspend and resume.
+#
+METHOD int power_for_sleep {
+ device_t pcib;
+ device_t dev;
+ int *pstate;
+};
OpenPOWER on IntegriCloud