// SPDX-License-Identifier: GPL-2.0-or-later/* * processor_idle - idle state submodule to the ACPI processor driver * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de> * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> * - Added processor hotplug support * Copyright (C) 2005 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> * - Added support for C3 on SMP */#define pr_fmt(fmt) "ACPI: " fmt #include <linux/module.h>#include <linux/acpi.h>#include <linux/dmi.h>#include <linux/sched.h> /* need_resched() */#include <linux/tick.h>#include <linux/cpuidle.h>#include <linux/cpu.h>#include <linux/minmax.h>#include <linux/perf_event.h>#include <acpi/processor.h>#include <linux/context_tracking.h> #include "internal.h" /* * Include the apic definitions for x86 to have the APIC timer related defines * available also for UP (on SMP it gets magically included via linux/smp.h). * asm/acpi.h is not an option, as it would require more include magic. Also * creating an empty asm-ia64/apic.h would just trade pest vs. cholera. */#ifdef CONFIG_X86#include <asm/apic.h>#include <asm/cpu.h>#endif #define ACPI_IDLE_STATE_START (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX) ? 1 : 0) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER;module_param(max_cstate, uint, 0400);static bool nocst __read_mostly;module_param(nocst, bool, 0400);static bool bm_check_disable __read_mostly;module_param(bm_check_disable, bool, 0400); static unsigned int latency_factor __read_mostly = 2;module_param(latency_factor, uint, 0644); static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); static struct cpuidle_driver acpi_idle_driver = { .name = "acpi_idle", .owner = THIS_MODULE,}; #ifdef CONFIG_ACPI_PROCESSOR_CSTATEvoid acpi_idle_rescan_dead_smt_siblings(void){ if (cpuidle_get_driver() == &acpi_idle_driver) arch_cpu_rescan_dead_smt_siblings();} staticDEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); static int disabled_by_idle_boot_param(void){ return boot_option_idle_override == IDLE_POLL || boot_option_idle_override == IDLE_HALT;} /* * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. * For now disable this. Probably a bug somewhere else. * * To skip this limit, boot/load with a large max_cstate limit. */static int set_max_cstate(const struct dmi_system_id *id){ if (max_cstate > ACPI_PROCESSOR_MAX_POWER) return 0; pr_notice("%s detected - limiting to C%ld max_cstate." " Override with \"processor.max_cstate=%d\"\n", id->ident, (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); max_cstate = (long)id->driver_data; return 0;} static const struct dmi_system_id processor_power_dmi_table[] = { { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, (void *)2}, { set_max_cstate, "Pavilion zv5000", { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")}, (void *)1}, { set_max_cstate, "Asus L8400B", { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, (void *)1}, {},}; /* * Callers should disable interrupts before the call and enable * interrupts after return. */static void __cpuidle acpi_safe_halt(void){ if (!tif_need_resched()) { raw_safe_halt(); raw_local_irq_disable(); }} #ifdef ARCH_APICTIMER_STOPS_ON_C3 /* * Some BIOS implementations switch to C3 in the published C2 state. * This seems to be a common problem on AMD boxen, but other vendors * are affected too. We pick the most conservative approach: we assume * that the local APIC stops in both C2 and C3. */static void lapic_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cx){ struct acpi_processor_power *pwr = &pr->power; u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2; if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) return; if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) type = ACPI_STATE_C1; /* * Check, if one of the previous states already marked the lapic * unstable */ if (pwr->timer_broadcast_on_state < state) return; if (cx->type >= type) pr->power.timer_broadcast_on_state = state;} static void __lapic_timer_propagate_broadcast(void *arg){ struct acpi_processor *pr = arg; if (pr->power.timer_broadcast_on_state < INT_MAX) tick_broadcast_enable(); else tick_broadcast_disable();} static void lapic_timer_propagate_broadcast(struct acpi_processor *pr){ smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast, (void *)pr, 1);} /* Power(C) State timer broadcast control */static bool lapic_timer_needs_broadcast(struct acpi_processor *pr, struct acpi_processor_cx *cx){ return cx - pr->power.states >= pr->power.timer_broadcast_on_state;} #else static void lapic_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cstate) { }static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } static bool lapic_timer_needs_broadcast(struct acpi_processor *pr, struct acpi_processor_cx *cx){ return false;} #endif #if defined(CONFIG_X86)static void tsc_check_state(int state){ switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_HYGON: case X86_VENDOR_AMD: case X86_VENDOR_INTEL: case X86_VENDOR_CENTAUR: case X86_VENDOR_ZHAOXIN: /* * AMD Fam10h TSC will tick in all * C/P/S0/S1 states when this bit is set. */ if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) return; fallthrough; default: /* TSC could halt in idle, so notify users */ if (state > ACPI_STATE_C1) mark_tsc_unstable("TSC halts in idle"); }}#elsestatic void tsc_check_state(int state) { return; }#endif static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr){ if (!pr->pblk) return -ENODEV; /* if info is obtained from pblk/fadt, type equals state */ pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; #ifndef CONFIG_HOTPLUG_CPU /* * Check for P_LVL2_UP flag before entering C2 and above on * an SMP system. */ if ((num_online_cpus() > 1) && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) return -ENODEV;#endif /* determine C2 and C3 address from pblk */ pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4; pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; /* determine latencies from FADT */ pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.c2_latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.c3_latency; /* * FADT specified C2 latency must be less than or equal to * 100 microseconds. */ if (acpi_gbl_FADT.c2_latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { acpi_handle_debug(pr->handle, "C2 latency too large [%d]\n", acpi_gbl_FADT.c2_latency); /* invalidate C2 */ pr->power.states[ACPI_STATE_C2].address = 0; } /* * FADT supplied C3 latency must be less than or equal to * 1000 microseconds. */ if (acpi_gbl_FADT.c3_latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { acpi_handle_debug(pr->handle, "C3 latency too large [%d]\n", acpi_gbl_FADT.c3_latency); /* invalidate C3 */ pr->power.states[ACPI_STATE_C3].address = 0; } acpi_handle_debug(pr->handle, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, pr->power.states[ACPI_STATE_C3].address); snprintf(pr->power.states[ACPI_STATE_C2].desc, ACPI_CX_DESC_LEN, "ACPI P_LVL2 IOPORT 0x%x", pr->power.states[ACPI_STATE_C2].address); snprintf(pr->power.states[ACPI_STATE_C3].desc, ACPI_CX_DESC_LEN, "ACPI P_LVL3 IOPORT 0x%x", pr->power.states[ACPI_STATE_C3].address); if (!pr->power.states[ACPI_STATE_C2].address && !pr->power.states[ACPI_STATE_C3].address) return -ENODEV; return 0;} static int acpi_processor_get_power_info_default(struct acpi_processor *pr){ if (!pr->power.states[ACPI_STATE_C1].valid) { /* set the first C-State to C1 */ /* all processors need to support C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; snprintf(pr->power.states[ACPI_STATE_C1].desc, ACPI_CX_DESC_LEN, "ACPI HLT"); } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; return 0;} static int acpi_processor_get_power_info_cst(struct acpi_processor *pr){ int ret; if (nocst) return -ENODEV; ret = acpi_processor_evaluate_cst(pr->handle, pr->id, &pr->power); if (ret) return ret; if (!pr->power.count) return -EFAULT; pr->flags.has_cst = 1; return 0;} static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx){ static int bm_check_flag = -1; static int bm_control_flag = -1; if (!cx->address) return; /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. * Note that we could disable Type-F DMA (as recommended by * the erratum), but this is known to disrupt certain ISA * devices thus we take the conservative approach. */ if (errata.piix4.fdma) { acpi_handle_debug(pr->handle, "C3 not supported on PIIX4 with Type-F DMA\n"); return; } /* All the logic here assumes flags.bm_check is same across all CPUs */ if (bm_check_flag == -1) { /* Determine whether bm_check is needed based on CPU */ acpi_processor_power_init_bm_check(&(pr->flags), pr->id); bm_check_flag = pr->flags.bm_check; bm_control_flag = pr->flags.bm_control; } else { pr->flags.bm_check = bm_check_flag; pr->flags.bm_control = bm_control_flag; } if (pr->flags.bm_check) { if (!pr->flags.bm_control) { if (pr->flags.has_cst != 1) { /* bus mastering control is necessary */ acpi_handle_debug(pr->handle, "C3 support requires BM control\n"); return; } else { /* Here we enter C3 without bus mastering */ acpi_handle_debug(pr->handle, "C3 support without BM control\n"); } } } else { /* * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. */ if (!(acpi_gbl_FADT.flags & ACPI_FADT_WBINVD)) { acpi_handle_debug(pr->handle, "Cache invalidation should work properly" " for C3 to be enabled on SMP systems\n"); return; } } /* * Otherwise we've met all of our C3 requirements. * Normalize the C3 latency to expidite policy. Enable * checking of bus mastering status (bm_check) so we can * use this in our C3 policy */ cx->valid = 1; /* * On older chipsets, BM_RLD needs to be set * in order for Bus Master activity to wake the * system from C3. Newer chipsets handle DMA * during C3 automatically and BM_RLD is a NOP. * In either case, the proper way to * handle BM_RLD is to set it and leave it set. */ acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1);} static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length){ int i, j, k; for (i = 1; i < length; i++) { if (!states[i].valid) continue; for (j = i - 1, k = i; j >= 0; j--) { if (!states[j].valid) continue; if (states[j].latency > states[k].latency) swap(states[j].latency, states[k].latency); k = j; } }} static int acpi_processor_power_verify(struct acpi_processor *pr){ unsigned int i; unsigned int working = 0; unsigned int last_latency = 0; unsigned int last_type = 0; bool buggy_latency = false; pr->power.timer_broadcast_on_state = INT_MAX; for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { struct acpi_processor_cx *cx = &pr->power.states[i]; switch (cx->type) { case ACPI_STATE_C1: cx->valid = 1; break; case ACPI_STATE_C2: if (!cx->address) break; cx->valid = 1; break; case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); break; } if (!cx->valid) continue; if (cx->type >= last_type && cx->latency < last_latency) buggy_latency = true; last_latency = cx->latency; last_type = cx->type; lapic_timer_check_state(i, pr, cx); tsc_check_state(cx->type); working++; } if (buggy_latency) { pr_notice("FW issue: working around C-state latencies out of order\n"); acpi_cst_latency_sort(&pr->power.states[1], max_cstate); } lapic_timer_propagate_broadcast(pr); return working;} static int acpi_processor_get_cstate_info(struct acpi_processor *pr){ int result; /* NOTE: the idle thread may not be running while calling * this function */ /* Zero initialize all the C-states info. */ memset(pr->power.states, 0, sizeof(pr->power.states)); result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) result = acpi_processor_get_power_info_fadt(pr); if (result) return result; acpi_processor_get_power_info_default(pr); pr->power.count = acpi_processor_power_verify(pr); pr->flags.power = 1; return 0;} /** * acpi_idle_bm_check - checks if bus master activity was detected */static int acpi_idle_bm_check(void){ u32 bm_status = 0;Lines 1–500 of 1205. Load more
// SPDX-License-Identifier: GPL-2.0-or-later /* * processor_idle - idle state submodule to the ACPI processor driver * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de> * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> * - Added processor hotplug support * Copyright (C) 2005 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> * - Added support for C3 on SMP */ #define pr_fmt(fmt) "ACPI: " fmt #include <linux/module.h> #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/sched.h> /* need_resched() */ #include <linux/tick.h> #include <linux/cpuidle.h> #include <linux/cpu.h> #include <linux/minmax.h> #include <linux/perf_event.h> #include <acpi/processor.h> #include <linux/context_tracking.h> #include "internal.h" /* * Include the apic definitions for x86 to have the APIC timer related defines * available also for UP (on SMP it gets magically included via linux/smp.h). * asm/acpi.h is not an option, as it would require more include magic. Also * creating an empty asm-ia64/apic.h would just trade pest vs. cholera. */ #ifdef CONFIG_X86 #include <asm/apic.h> #include <asm/cpu.h> #endif #define ACPI_IDLE_STATE_START (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX) ? 1 : 0) static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; module_param(max_cstate, uint, 0400); static bool nocst __read_mostly; module_param(nocst, bool, 0400); static bool bm_check_disable __read_mostly; module_param(bm_check_disable, bool, 0400); static unsigned int latency_factor __read_mostly = 2; module_param(latency_factor, uint, 0644); static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); static struct cpuidle_driver acpi_idle_driver = { .name = "acpi_idle", .owner = THIS_MODULE, }; #ifdef CONFIG_ACPI_PROCESSOR_CSTATE void acpi_idle_rescan_dead_smt_siblings(void) { if (cpuidle_get_driver() == &acpi_idle_driver) arch_cpu_rescan_dead_smt_siblings(); } static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); static int disabled_by_idle_boot_param(void) { return boot_option_idle_override == IDLE_POLL || boot_option_idle_override == IDLE_HALT; } /* * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. * For now disable this. Probably a bug somewhere else. * * To skip this limit, boot/load with a large max_cstate limit. */ static int set_max_cstate(const struct dmi_system_id *id) { if (max_cstate > ACPI_PROCESSOR_MAX_POWER) return 0; pr_notice("%s detected - limiting to C%ld max_cstate." " Override with \"processor.max_cstate=%d\"\n", id->ident, (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); max_cstate = (long)id->driver_data; return 0; } static const struct dmi_system_id processor_power_dmi_table[] = { { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, (void *)2}, { set_max_cstate, "Pavilion zv5000", { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")}, (void *)1}, { set_max_cstate, "Asus L8400B", { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, (void *)1}, {}, }; /* * Callers should disable interrupts before the call and enable * interrupts after return. */ static void __cpuidle acpi_safe_halt(void) { if (!tif_need_resched()) { raw_safe_halt(); raw_local_irq_disable(); } } #ifdef ARCH_APICTIMER_STOPS_ON_C3 /* * Some BIOS implementations switch to C3 in the published C2 state. * This seems to be a common problem on AMD boxen, but other vendors * are affected too. We pick the most conservative approach: we assume * that the local APIC stops in both C2 and C3. */ static void lapic_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cx) { struct acpi_processor_power *pwr = &pr->power; u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2; if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) return; if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) type = ACPI_STATE_C1; /* * Check, if one of the previous states already marked the lapic * unstable */ if (pwr->timer_broadcast_on_state < state) return; if (cx->type >= type) pr->power.timer_broadcast_on_state = state; } static void __lapic_timer_propagate_broadcast(void *arg) { struct acpi_processor *pr = arg; if (pr->power.timer_broadcast_on_state < INT_MAX) tick_broadcast_enable(); else tick_broadcast_disable(); } static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast, (void *)pr, 1); } /* Power(C) State timer broadcast control */ static bool lapic_timer_needs_broadcast(struct acpi_processor *pr, struct acpi_processor_cx *cx) { return cx - pr->power.states >= pr->power.timer_broadcast_on_state; } #else static void lapic_timer_check_state(int state, struct acpi_processor *pr, struct acpi_processor_cx *cstate) { } static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } static bool lapic_timer_needs_broadcast(struct acpi_processor *pr, struct acpi_processor_cx *cx) { return false; } #endif #if defined(CONFIG_X86) static void tsc_check_state(int state) { switch (boot_cpu_data.x86_vendor) { case X86_VENDOR_HYGON: case X86_VENDOR_AMD: case X86_VENDOR_INTEL: case X86_VENDOR_CENTAUR: case X86_VENDOR_ZHAOXIN: /* * AMD Fam10h TSC will tick in all * C/P/S0/S1 states when this bit is set. */ if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) return; fallthrough; default: /* TSC could halt in idle, so notify users */ if (state > ACPI_STATE_C1) mark_tsc_unstable("TSC halts in idle"); } } #else static void tsc_check_state(int state) { return; } #endif static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) { if (!pr->pblk) return -ENODEV; /* if info is obtained from pblk/fadt, type equals state */ pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; #ifndef CONFIG_HOTPLUG_CPU /* * Check for P_LVL2_UP flag before entering C2 and above on * an SMP system. */ if ((num_online_cpus() > 1) && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) return -ENODEV; #endif /* determine C2 and C3 address from pblk */ pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4; pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; /* determine latencies from FADT */ pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.c2_latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.c3_latency; /* * FADT specified C2 latency must be less than or equal to * 100 microseconds. */ if (acpi_gbl_FADT.c2_latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { acpi_handle_debug(pr->handle, "C2 latency too large [%d]\n", acpi_gbl_FADT.c2_latency); /* invalidate C2 */ pr->power.states[ACPI_STATE_C2].address = 0; } /* * FADT supplied C3 latency must be less than or equal to * 1000 microseconds. */ if (acpi_gbl_FADT.c3_latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { acpi_handle_debug(pr->handle, "C3 latency too large [%d]\n", acpi_gbl_FADT.c3_latency); /* invalidate C3 */ pr->power.states[ACPI_STATE_C3].address = 0; } acpi_handle_debug(pr->handle, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, pr->power.states[ACPI_STATE_C3].address); snprintf(pr->power.states[ACPI_STATE_C2].desc, ACPI_CX_DESC_LEN, "ACPI P_LVL2 IOPORT 0x%x", pr->power.states[ACPI_STATE_C2].address); snprintf(pr->power.states[ACPI_STATE_C3].desc, ACPI_CX_DESC_LEN, "ACPI P_LVL3 IOPORT 0x%x", pr->power.states[ACPI_STATE_C3].address); if (!pr->power.states[ACPI_STATE_C2].address && !pr->power.states[ACPI_STATE_C3].address) return -ENODEV; return 0; } static int acpi_processor_get_power_info_default(struct acpi_processor *pr) { if (!pr->power.states[ACPI_STATE_C1].valid) { /* set the first C-State to C1 */ /* all processors need to support C1 */ pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; snprintf(pr->power.states[ACPI_STATE_C1].desc, ACPI_CX_DESC_LEN, "ACPI HLT"); } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; return 0; } static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) { int ret; if (nocst) return -ENODEV; ret = acpi_processor_evaluate_cst(pr->handle, pr->id, &pr->power); if (ret) return ret; if (!pr->power.count) return -EFAULT; pr->flags.has_cst = 1; return 0; } static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx) { static int bm_check_flag = -1; static int bm_control_flag = -1; if (!cx->address) return; /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. * Note that we could disable Type-F DMA (as recommended by * the erratum), but this is known to disrupt certain ISA * devices thus we take the conservative approach. */ if (errata.piix4.fdma) { acpi_handle_debug(pr->handle, "C3 not supported on PIIX4 with Type-F DMA\n"); return; } /* All the logic here assumes flags.bm_check is same across all CPUs */ if (bm_check_flag == -1) { /* Determine whether bm_check is needed based on CPU */ acpi_processor_power_init_bm_check(&(pr->flags), pr->id); bm_check_flag = pr->flags.bm_check; bm_control_flag = pr->flags.bm_control; } else { pr->flags.bm_check = bm_check_flag; pr->flags.bm_control = bm_control_flag; } if (pr->flags.bm_check) { if (!pr->flags.bm_control) { if (pr->flags.has_cst != 1) { /* bus mastering control is necessary */ acpi_handle_debug(pr->handle, "C3 support requires BM control\n"); return; } else { /* Here we enter C3 without bus mastering */ acpi_handle_debug(pr->handle, "C3 support without BM control\n"); } } } else { /* * WBINVD should be set in fadt, for C3 state to be * supported on when bm_check is not required. */ if (!(acpi_gbl_FADT.flags & ACPI_FADT_WBINVD)) { acpi_handle_debug(pr->handle, "Cache invalidation should work properly" " for C3 to be enabled on SMP systems\n"); return; } } /* * Otherwise we've met all of our C3 requirements. * Normalize the C3 latency to expidite policy. Enable * checking of bus mastering status (bm_check) so we can * use this in our C3 policy */ cx->valid = 1; /* * On older chipsets, BM_RLD needs to be set * in order for Bus Master activity to wake the * system from C3. Newer chipsets handle DMA * during C3 automatically and BM_RLD is a NOP. * In either case, the proper way to * handle BM_RLD is to set it and leave it set. */ acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1); } static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length) { int i, j, k; for (i = 1; i < length; i++) { if (!states[i].valid) continue; for (j = i - 1, k = i; j >= 0; j--) { if (!states[j].valid) continue; if (states[j].latency > states[k].latency) swap(states[j].latency, states[k].latency); k = j; } } } static int acpi_processor_power_verify(struct acpi_processor *pr) { unsigned int i; unsigned int working = 0; unsigned int last_latency = 0; unsigned int last_type = 0; bool buggy_latency = false; pr->power.timer_broadcast_on_state = INT_MAX; for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { struct acpi_processor_cx *cx = &pr->power.states[i]; switch (cx->type) { case ACPI_STATE_C1: cx->valid = 1; break; case ACPI_STATE_C2: if (!cx->address) break; cx->valid = 1; break; case ACPI_STATE_C3: acpi_processor_power_verify_c3(pr, cx); break; } if (!cx->valid) continue; if (cx->type >= last_type && cx->latency < last_latency) buggy_latency = true; last_latency = cx->latency; last_type = cx->type; lapic_timer_check_state(i, pr, cx); tsc_check_state(cx->type); working++; } if (buggy_latency) { pr_notice("FW issue: working around C-state latencies out of order\n"); acpi_cst_latency_sort(&pr->power.states[1], max_cstate); } lapic_timer_propagate_broadcast(pr); return working; } static int acpi_processor_get_cstate_info(struct acpi_processor *pr) { int result; /* NOTE: the idle thread may not be running while calling * this function */ /* Zero initialize all the C-states info. */ memset(pr->power.states, 0, sizeof(pr->power.states)); result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) result = acpi_processor_get_power_info_fadt(pr); if (result) return result; acpi_processor_get_power_info_default(pr); pr->power.count = acpi_processor_power_verify(pr); pr->flags.power = 1; return 0; } /** * acpi_idle_bm_check - checks if bus master activity was detected */ static int acpi_idle_bm_check(void) { u32 bm_status = 0;