summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-10-11 21:15:10 +0000
committernjl <njl@FreeBSD.org>2004-10-11 21:15:10 +0000
commitd8f09c05804da00573488f3cc2a887fda779a3e4 (patch)
treea0c4affe40f665a08572ef7c9c6cba63d803a527 /sys/dev/acpica
parenta5e0614f34f29e67a8b559dffa47509af8bdeb31 (diff)
downloadFreeBSD-src-d8f09c05804da00573488f3cc2a887fda779a3e4.zip
FreeBSD-src-d8f09c05804da00573488f3cc2a887fda779a3e4.tar.gz
Update C3 support when BM control is not present.
* Fix a bug where caches were flushed on non-C3 transitions. * Be sure a working flush cache instruction is present before using it. * Disable C3 completely if it isn't present.
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r--sys/dev/acpica/acpi_cpu.c44
1 files changed, 28 insertions, 16 deletions
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index 92c8ca4..23d20d8 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -464,14 +464,22 @@ acpi_cpu_cx_probe(struct acpi_cpu_softc *sc)
/*
* 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.
+ * while sleeping in C3. If it's not present but a working flush cache
+ * instruction is present, flush the caches before entering C3 instead.
+ * Otherwise, just disable C3 completely.
*/
if (AcpiGbl_FADT->V1_Pm2CntBlk == 0 || AcpiGbl_FADT->Pm2CntLen == 0) {
- cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
- ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "acpi_cpu%d: no BM control, using flush cache method\n",
- device_get_unit(sc->cpu_dev)));
+ if (AcpiGbl_FADT->WbInvd && AcpiGbl_FADT->WbInvdFlush == 0) {
+ cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "acpi_cpu%d: no BM control, using flush cache method\n",
+ device_get_unit(sc->cpu_dev)));
+ } else {
+ cpu_quirks |= CPU_QUIRK_NO_C3;
+ ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+ "acpi_cpu%d: no BM control, C3 not available\n",
+ device_get_unit(sc->cpu_dev)));
+ }
}
/*
@@ -857,9 +865,7 @@ 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. 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.
+ * time if USB is loaded.
*/
if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
AcpiGetRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active,
@@ -869,8 +875,7 @@ acpi_cpu_idle()
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];
@@ -888,10 +893,17 @@ acpi_cpu_idle()
return;
}
- /* For C3, disable bus master arbitration and enable bus master wake. */
+ /*
+ * For C3, disable bus master arbitration and enable bus master wake
+ * if BM control is available, otherwise flush the CPU cache.
+ */
if (cx_next->type == ACPI_STATE_C3) {
- AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
- AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK);
+ if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) {
+ AcpiSetRegister(ACPI_BITREG_ARB_DISABLE, 1, ACPI_MTX_DO_NOT_LOCK);
+ AcpiSetRegister(ACPI_BITREG_BUS_MASTER_RLD, 1,
+ ACPI_MTX_DO_NOT_LOCK);
+ } else
+ ACPI_FLUSH_CPU_CACHE();
}
/*
@@ -956,8 +968,8 @@ acpi_cpu_quirks(struct acpi_cpu_softc *sc)
{
/*
- * C3 is not supported on multiple CPUs since this would require
- * flushing all caches which is currently too expensive.
+ * C3 on multiple CPUs requires using the expensive flush cache
+ * instruction.
*/
if (mp_ncpus > 1)
cpu_quirks |= CPU_QUIRK_NO_BM_CTRL;
OpenPOWER on IntegriCloud