1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-29 12:03:03 +00:00

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.
This commit is contained in:
Nate Lawson 2004-10-11 06:06:42 +00:00
parent 7f35f90eae
commit 18ececa0b8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=136368

View File

@ -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. */