summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-10-11 06:06:42 +0000
committernjl <njl@FreeBSD.org>2004-10-11 06:06:42 +0000
commit46eb5d68144e7fa25d3740a018a87ede3e5816f7 (patch)
treea113d5fc8bfa5f7c5ce7ed8b0cfdadb7210bcdb5 /sys/dev/acpica
parent21bb12fa0a6b8bf204c7b0f599e629f580ee313b (diff)
downloadFreeBSD-src-46eb5d68144e7fa25d3740a018a87ede3e5816f7.zip
FreeBSD-src-46eb5d68144e7fa25d3740a018a87ede3e5816f7.tar.gz
If bus mastering control is not available (PM2_BLK), don't just disable
C3. Instead, flush caches before entering C3. This may be slower but provides good power savings.
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r--sys/dev/acpica/acpi_cpu.c43
1 files changed, 27 insertions, 16 deletions
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index e6da6b9..92c8ca4 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -103,8 +103,9 @@ static uint32_t cpu_duty_width;
#define ACPI_CPU_NOTIFY_PERF_STATES 0x80 /* _PSS changed. */
#define ACPI_CPU_NOTIFY_CX_STATES 0x81 /* _CST changed. */
-#define CPU_QUIRK_NO_C3 0x0001 /* C3-type states are not usable. */
-#define CPU_QUIRK_NO_THROTTLE 0x0002 /* Throttling is not usable. */
+#define CPU_QUIRK_NO_C3 (1<<0) /* C3-type states are not usable. */
+#define CPU_QUIRK_NO_THROTTLE (1<<1) /* Throttling is not usable. */
+#define CPU_QUIRK_NO_BM_CTRL (1<<2) /* No bus mastering control. */
#define PCI_VENDOR_INTEL 0x8086
#define PCI_DEVICE_82371AB_3 0x7113 /* PIIX4 chipset for quirks. */
@@ -461,12 +462,16 @@ acpi_cpu_cx_probe(struct acpi_cpu_softc *sc)
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
- /* Bus mastering arbitration control is needed for C3. */
+ /*
+ * Bus mastering arbitration control is needed to keep caches coherent
+ * while sleeping in C3. If it's not present, we flush the caches before
+ * entering C3 instead.
+ */
if (AcpiGbl_FADT->V1_Pm2CntBlk == 0 || AcpiGbl_FADT->Pm2CntLen == 0) {
- cpu_quirks |= CPU_QUIRK_NO_C3;
+ cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "acpi_cpu%d: No BM control, C3 disabled\n",
- device_get_unit(sc->cpu_dev)));
+ "acpi_cpu%d: no BM control, using flush cache method\n",
+ device_get_unit(sc->cpu_dev)));
}
/*
@@ -852,15 +857,20 @@ acpi_cpu_idle()
* Check for bus master activity. If there was activity, clear
* the bit and use the lowest non-C3 state. Note that the USB
* driver polling for new devices keeps this bit set all the
- * time if USB is loaded.
+ * time if USB is loaded. If bus mastering control is not available,
+ * flush caches. This can be quite slow but may be useful since not
+ * all systems support BM control.
*/
- AcpiGetRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active,
- ACPI_MTX_DO_NOT_LOCK);
- if (bm_active != 0) {
- AcpiSetRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1,
- ACPI_MTX_DO_NOT_LOCK);
- cx_next_idx = min(cx_next_idx, cpu_non_c3);
- }
+ if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
+ AcpiGetRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active,
+ ACPI_MTX_DO_NOT_LOCK);
+ if (bm_active != 0) {
+ AcpiSetRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1,
+ ACPI_MTX_DO_NOT_LOCK);
+ cx_next_idx = min(cx_next_idx, cpu_non_c3);
+ }
+ } else
+ ACPI_FLUSH_CPU_CACHE();
/* Select the next state and update statistics. */
cx_next = &sc->cpu_cx_states[cx_next_idx];
@@ -903,7 +913,8 @@ acpi_cpu_idle()
AcpiHwLowLevelRead(32, &end_time, &AcpiGbl_FADT->XPmTmrBlk);
/* Enable bus master arbitration and disable bus master wakeup. */
- if (cx_next->type == ACPI_STATE_C3) {
+ if (cx_next->type == ACPI_STATE_C3 &&
+ (cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK);
AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK);
}
@@ -949,7 +960,7 @@ acpi_cpu_quirks(struct acpi_cpu_softc *sc)
* flushing all caches which is currently too expensive.
*/
if (mp_ncpus > 1)
- cpu_quirks |= CPU_QUIRK_NO_C3;
+ cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
#ifdef notyet
/* Look for various quirks of the PIIX4 part. */
OpenPOWER on IntegriCloud