1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * processor_idle - idle state submodule to the ACPI processor driver 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 61da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 7c5ab81caSDominik Brodowski * Copyright (C) 2004, 2005 Dominik Brodowski <linux@brodo.de> 81da177e4SLinus Torvalds * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 91da177e4SLinus Torvalds * - Added processor hotplug support 1002df8b93SVenkatesh Pallipadi * Copyright (C) 2005 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> 1102df8b93SVenkatesh Pallipadi * - Added support for C3 on SMP 121da177e4SLinus Torvalds */ 13b6ec26fbSSudeep Holla #define pr_fmt(fmt) "ACPI: " fmt 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds #include <linux/module.h> 161da177e4SLinus Torvalds #include <linux/acpi.h> 171da177e4SLinus Torvalds #include <linux/dmi.h> 184e57b681STim Schmielau #include <linux/sched.h> /* need_resched() */ 19ee41eebfSThomas Gleixner #include <linux/tick.h> 204f86d3a8SLen Brown #include <linux/cpuidle.h> 216727ad9eSChris Metcalf #include <linux/cpu.h> 228b48463fSLv Zheng #include <acpi/processor.h> 231da177e4SLinus Torvalds 243434933bSThomas Gleixner /* 253434933bSThomas Gleixner * Include the apic definitions for x86 to have the APIC timer related defines 263434933bSThomas Gleixner * available also for UP (on SMP it gets magically included via linux/smp.h). 273434933bSThomas Gleixner * asm/acpi.h is not an option, as it would require more include magic. Also 283434933bSThomas Gleixner * creating an empty asm-ia64/apic.h would just trade pest vs. cholera. 293434933bSThomas Gleixner */ 303434933bSThomas Gleixner #ifdef CONFIG_X86 313434933bSThomas Gleixner #include <asm/apic.h> 323434933bSThomas Gleixner #endif 333434933bSThomas Gleixner 341da177e4SLinus Torvalds #define ACPI_PROCESSOR_CLASS "processor" 351da177e4SLinus Torvalds #define _COMPONENT ACPI_PROCESSOR_COMPONENT 36f52fd66dSLen Brown ACPI_MODULE_NAME("processor_idle"); 371da177e4SLinus Torvalds 38dc2251bfSRafael J. Wysocki #define ACPI_IDLE_STATE_START (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX) ? 1 : 0) 39dc2251bfSRafael J. Wysocki 404f86d3a8SLen Brown static unsigned int max_cstate __read_mostly = ACPI_PROCESSOR_MAX_POWER; 414f86d3a8SLen Brown module_param(max_cstate, uint, 0000); 42b6835052SAndreas Mohr static unsigned int nocst __read_mostly; 431da177e4SLinus Torvalds module_param(nocst, uint, 0000); 44d3e7e99fSLen Brown static int bm_check_disable __read_mostly; 45d3e7e99fSLen Brown module_param(bm_check_disable, uint, 0000); 461da177e4SLinus Torvalds 4725de5718SLen Brown static unsigned int latency_factor __read_mostly = 2; 484963f620SLen Brown module_param(latency_factor, uint, 0644); 491da177e4SLinus Torvalds 503d339dcbSDaniel Lezcano static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); 513d339dcbSDaniel Lezcano 5235ae7133SSudeep Holla struct cpuidle_driver acpi_idle_driver = { 5335ae7133SSudeep Holla .name = "acpi_idle", 5435ae7133SSudeep Holla .owner = THIS_MODULE, 5535ae7133SSudeep Holla }; 5635ae7133SSudeep Holla 5735ae7133SSudeep Holla #ifdef CONFIG_ACPI_PROCESSOR_CSTATE 5825528213SPeter Zijlstra static 5925528213SPeter Zijlstra DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX], acpi_cstate); 60ac3ebafaSDaniel Lezcano 61d1896049SThomas Renninger static int disabled_by_idle_boot_param(void) 62d1896049SThomas Renninger { 63d1896049SThomas Renninger return boot_option_idle_override == IDLE_POLL || 64d1896049SThomas Renninger boot_option_idle_override == IDLE_HALT; 65d1896049SThomas Renninger } 66d1896049SThomas Renninger 671da177e4SLinus Torvalds /* 681da177e4SLinus Torvalds * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. 691da177e4SLinus Torvalds * For now disable this. Probably a bug somewhere else. 701da177e4SLinus Torvalds * 711da177e4SLinus Torvalds * To skip this limit, boot/load with a large max_cstate limit. 721da177e4SLinus Torvalds */ 731855256cSJeff Garzik static int set_max_cstate(const struct dmi_system_id *id) 741da177e4SLinus Torvalds { 751da177e4SLinus Torvalds if (max_cstate > ACPI_PROCESSOR_MAX_POWER) 761da177e4SLinus Torvalds return 0; 771da177e4SLinus Torvalds 78b6ec26fbSSudeep Holla pr_notice("%s detected - limiting to C%ld max_cstate." 791da177e4SLinus Torvalds " Override with \"processor.max_cstate=%d\"\n", id->ident, 803d35600aSLen Brown (long)id->driver_data, ACPI_PROCESSOR_MAX_POWER + 1); 811da177e4SLinus Torvalds 823d35600aSLen Brown max_cstate = (long)id->driver_data; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds return 0; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 87b0346688SMathias Krause static const struct dmi_system_id processor_power_dmi_table[] = { 88335f16beSDavid Shaohua Li { set_max_cstate, "Clevo 5600D", { 89876c184bSThomas Rosner DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), 90876c184bSThomas Rosner DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, 91335f16beSDavid Shaohua Li (void *)2}, 92370d5cd8SArjan van de Ven { set_max_cstate, "Pavilion zv5000", { 93370d5cd8SArjan van de Ven DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), 94370d5cd8SArjan van de Ven DMI_MATCH(DMI_PRODUCT_NAME,"Pavilion zv5000 (DS502A#ABA)")}, 95370d5cd8SArjan van de Ven (void *)1}, 96370d5cd8SArjan van de Ven { set_max_cstate, "Asus L8400B", { 97370d5cd8SArjan van de Ven DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), 98370d5cd8SArjan van de Ven DMI_MATCH(DMI_PRODUCT_NAME,"L8400B series Notebook PC")}, 99370d5cd8SArjan van de Ven (void *)1}, 1001da177e4SLinus Torvalds {}, 1011da177e4SLinus Torvalds }; 1021da177e4SLinus Torvalds 1034f86d3a8SLen Brown 1042e906655Svenkatesh.pallipadi@intel.com /* 1052e906655Svenkatesh.pallipadi@intel.com * Callers should disable interrupts before the call and enable 1062e906655Svenkatesh.pallipadi@intel.com * interrupts after return. 1072e906655Svenkatesh.pallipadi@intel.com */ 1086727ad9eSChris Metcalf static void __cpuidle acpi_safe_halt(void) 109ddc081a1SVenkatesh Pallipadi { 110ea811747SPeter Zijlstra if (!tif_need_resched()) { 111ddc081a1SVenkatesh Pallipadi safe_halt(); 11271e93d15SVenki Pallipadi local_irq_disable(); 11371e93d15SVenki Pallipadi } 114ddc081a1SVenkatesh Pallipadi } 115ddc081a1SVenkatesh Pallipadi 116169a0abbSThomas Gleixner #ifdef ARCH_APICTIMER_STOPS_ON_C3 117169a0abbSThomas Gleixner 118169a0abbSThomas Gleixner /* 119169a0abbSThomas Gleixner * Some BIOS implementations switch to C3 in the published C2 state. 120296d93cdSLinus Torvalds * This seems to be a common problem on AMD boxen, but other vendors 121296d93cdSLinus Torvalds * are affected too. We pick the most conservative approach: we assume 122296d93cdSLinus Torvalds * that the local APIC stops in both C2 and C3. 123169a0abbSThomas Gleixner */ 1247e275cc4SLen Brown static void lapic_timer_check_state(int state, struct acpi_processor *pr, 125169a0abbSThomas Gleixner struct acpi_processor_cx *cx) 126169a0abbSThomas Gleixner { 127169a0abbSThomas Gleixner struct acpi_processor_power *pwr = &pr->power; 128e585bef8SThomas Gleixner u8 type = local_apic_timer_c2_ok ? ACPI_STATE_C3 : ACPI_STATE_C2; 129169a0abbSThomas Gleixner 130db954b58SVenkatesh Pallipadi if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) 131db954b58SVenkatesh Pallipadi return; 132db954b58SVenkatesh Pallipadi 13307c94a38SBorislav Petkov if (boot_cpu_has_bug(X86_BUG_AMD_APIC_C1E)) 13487ad57baSShaohua Li type = ACPI_STATE_C1; 13587ad57baSShaohua Li 136169a0abbSThomas Gleixner /* 137169a0abbSThomas Gleixner * Check, if one of the previous states already marked the lapic 138169a0abbSThomas Gleixner * unstable 139169a0abbSThomas Gleixner */ 140169a0abbSThomas Gleixner if (pwr->timer_broadcast_on_state < state) 141169a0abbSThomas Gleixner return; 142169a0abbSThomas Gleixner 143e585bef8SThomas Gleixner if (cx->type >= type) 144169a0abbSThomas Gleixner pr->power.timer_broadcast_on_state = state; 145169a0abbSThomas Gleixner } 146169a0abbSThomas Gleixner 147918aae42SHidetoshi Seto static void __lapic_timer_propagate_broadcast(void *arg) 148169a0abbSThomas Gleixner { 149f833bab8SSuresh Siddha struct acpi_processor *pr = (struct acpi_processor *) arg; 150e9e2cdb4SThomas Gleixner 151ee41eebfSThomas Gleixner if (pr->power.timer_broadcast_on_state < INT_MAX) 152ee41eebfSThomas Gleixner tick_broadcast_enable(); 153ee41eebfSThomas Gleixner else 154ee41eebfSThomas Gleixner tick_broadcast_disable(); 155e9e2cdb4SThomas Gleixner } 156e9e2cdb4SThomas Gleixner 157918aae42SHidetoshi Seto static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) 158918aae42SHidetoshi Seto { 159918aae42SHidetoshi Seto smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast, 160918aae42SHidetoshi Seto (void *)pr, 1); 161918aae42SHidetoshi Seto } 162918aae42SHidetoshi Seto 163e9e2cdb4SThomas Gleixner /* Power(C) State timer broadcast control */ 1647e275cc4SLen Brown static void lapic_timer_state_broadcast(struct acpi_processor *pr, 165e9e2cdb4SThomas Gleixner struct acpi_processor_cx *cx, 166e9e2cdb4SThomas Gleixner int broadcast) 167e9e2cdb4SThomas Gleixner { 168e9e2cdb4SThomas Gleixner int state = cx - pr->power.states; 169e9e2cdb4SThomas Gleixner 170e9e2cdb4SThomas Gleixner if (state >= pr->power.timer_broadcast_on_state) { 1717815701cSThomas Gleixner if (broadcast) 1727815701cSThomas Gleixner tick_broadcast_enter(); 1737815701cSThomas Gleixner else 1747815701cSThomas Gleixner tick_broadcast_exit(); 175e9e2cdb4SThomas Gleixner } 176169a0abbSThomas Gleixner } 177169a0abbSThomas Gleixner 178169a0abbSThomas Gleixner #else 179169a0abbSThomas Gleixner 1807e275cc4SLen Brown static void lapic_timer_check_state(int state, struct acpi_processor *pr, 181169a0abbSThomas Gleixner struct acpi_processor_cx *cstate) { } 1827e275cc4SLen Brown static void lapic_timer_propagate_broadcast(struct acpi_processor *pr) { } 1837e275cc4SLen Brown static void lapic_timer_state_broadcast(struct acpi_processor *pr, 184e9e2cdb4SThomas Gleixner struct acpi_processor_cx *cx, 185e9e2cdb4SThomas Gleixner int broadcast) 186e9e2cdb4SThomas Gleixner { 187e9e2cdb4SThomas Gleixner } 188169a0abbSThomas Gleixner 189169a0abbSThomas Gleixner #endif 190169a0abbSThomas Gleixner 191592913ecSJohn Stultz #if defined(CONFIG_X86) 192520daf72SLen Brown static void tsc_check_state(int state) 193ddb25f9aSAndi Kleen { 194ddb25f9aSAndi Kleen switch (boot_cpu_data.x86_vendor) { 1957377ed4bSPu Wen case X86_VENDOR_HYGON: 196ddb25f9aSAndi Kleen case X86_VENDOR_AMD: 19740fb1715SVenki Pallipadi case X86_VENDOR_INTEL: 198fe6daab1Sdavidwang case X86_VENDOR_CENTAUR: 199773b2f30STony W Wang-oc case X86_VENDOR_ZHAOXIN: 200ddb25f9aSAndi Kleen /* 201ddb25f9aSAndi Kleen * AMD Fam10h TSC will tick in all 202ddb25f9aSAndi Kleen * C/P/S0/S1 states when this bit is set. 203ddb25f9aSAndi Kleen */ 20440fb1715SVenki Pallipadi if (boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) 205520daf72SLen Brown return; 20640fb1715SVenki Pallipadi 207ddb25f9aSAndi Kleen /*FALL THROUGH*/ 208ddb25f9aSAndi Kleen default: 209520daf72SLen Brown /* TSC could halt in idle, so notify users */ 210520daf72SLen Brown if (state > ACPI_STATE_C1) 211520daf72SLen Brown mark_tsc_unstable("TSC halts in idle"); 212ddb25f9aSAndi Kleen } 213ddb25f9aSAndi Kleen } 214520daf72SLen Brown #else 215520daf72SLen Brown static void tsc_check_state(int state) { return; } 216ddb25f9aSAndi Kleen #endif 217ddb25f9aSAndi Kleen 2181da177e4SLinus Torvalds static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) 2191da177e4SLinus Torvalds { 2201da177e4SLinus Torvalds 2211da177e4SLinus Torvalds if (!pr->pblk) 222d550d98dSPatrick Mochel return -ENODEV; 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds /* if info is obtained from pblk/fadt, type equals state */ 2251da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; 2261da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; 2271da177e4SLinus Torvalds 2284c033552SVenkatesh Pallipadi #ifndef CONFIG_HOTPLUG_CPU 2294c033552SVenkatesh Pallipadi /* 2304c033552SVenkatesh Pallipadi * Check for P_LVL2_UP flag before entering C2 and above on 2314c033552SVenkatesh Pallipadi * an SMP system. 2324c033552SVenkatesh Pallipadi */ 233ad71860aSAlexey Starikovskiy if ((num_online_cpus() > 1) && 234cee324b1SAlexey Starikovskiy !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) 235d550d98dSPatrick Mochel return -ENODEV; 2364c033552SVenkatesh Pallipadi #endif 2374c033552SVenkatesh Pallipadi 2381da177e4SLinus Torvalds /* determine C2 and C3 address from pblk */ 2391da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4; 2401da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds /* determine latencies from FADT */ 243ba494beeSBob Moore pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.c2_latency; 244ba494beeSBob Moore pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.c3_latency; 2451da177e4SLinus Torvalds 2465d76b6f6SLen Brown /* 2475d76b6f6SLen Brown * FADT specified C2 latency must be less than or equal to 2485d76b6f6SLen Brown * 100 microseconds. 2495d76b6f6SLen Brown */ 250ba494beeSBob Moore if (acpi_gbl_FADT.c2_latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { 2515d76b6f6SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 252ba494beeSBob Moore "C2 latency too large [%d]\n", acpi_gbl_FADT.c2_latency)); 2535d76b6f6SLen Brown /* invalidate C2 */ 2545d76b6f6SLen Brown pr->power.states[ACPI_STATE_C2].address = 0; 2555d76b6f6SLen Brown } 2565d76b6f6SLen Brown 257a6d72c18SLen Brown /* 258a6d72c18SLen Brown * FADT supplied C3 latency must be less than or equal to 259a6d72c18SLen Brown * 1000 microseconds. 260a6d72c18SLen Brown */ 261ba494beeSBob Moore if (acpi_gbl_FADT.c3_latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { 262a6d72c18SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 263ba494beeSBob Moore "C3 latency too large [%d]\n", acpi_gbl_FADT.c3_latency)); 264a6d72c18SLen Brown /* invalidate C3 */ 265a6d72c18SLen Brown pr->power.states[ACPI_STATE_C3].address = 0; 266a6d72c18SLen Brown } 267a6d72c18SLen Brown 2681da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 2691da177e4SLinus Torvalds "lvl2[0x%08x] lvl3[0x%08x]\n", 2701da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].address, 2711da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].address)); 2721da177e4SLinus Torvalds 27334a62cd0SYazen Ghannam snprintf(pr->power.states[ACPI_STATE_C2].desc, 27434a62cd0SYazen Ghannam ACPI_CX_DESC_LEN, "ACPI P_LVL2 IOPORT 0x%x", 27534a62cd0SYazen Ghannam pr->power.states[ACPI_STATE_C2].address); 27634a62cd0SYazen Ghannam snprintf(pr->power.states[ACPI_STATE_C3].desc, 27734a62cd0SYazen Ghannam ACPI_CX_DESC_LEN, "ACPI P_LVL3 IOPORT 0x%x", 27834a62cd0SYazen Ghannam pr->power.states[ACPI_STATE_C3].address); 27934a62cd0SYazen Ghannam 280d550d98dSPatrick Mochel return 0; 2811da177e4SLinus Torvalds } 2821da177e4SLinus Torvalds 283991528d7SVenkatesh Pallipadi static int acpi_processor_get_power_info_default(struct acpi_processor *pr) 284acf05f4bSVenkatesh Pallipadi { 285991528d7SVenkatesh Pallipadi if (!pr->power.states[ACPI_STATE_C1].valid) { 286cf824788SJanosch Machowinski /* set the first C-State to C1 */ 287991528d7SVenkatesh Pallipadi /* all processors need to support C1 */ 288acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; 289acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C1].valid = 1; 2900fda6b40SVenkatesh Pallipadi pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; 291248e8841SYazen Ghannam 292248e8841SYazen Ghannam snprintf(pr->power.states[ACPI_STATE_C1].desc, 293248e8841SYazen Ghannam ACPI_CX_DESC_LEN, "ACPI HLT"); 294991528d7SVenkatesh Pallipadi } 295991528d7SVenkatesh Pallipadi /* the C0 state only exists as a filler in our array */ 296991528d7SVenkatesh Pallipadi pr->power.states[ACPI_STATE_C0].valid = 1; 297d550d98dSPatrick Mochel return 0; 298acf05f4bSVenkatesh Pallipadi } 299acf05f4bSVenkatesh Pallipadi 3001da177e4SLinus Torvalds static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) 3011da177e4SLinus Torvalds { 3026fd8050aSSudeep Holla acpi_status status; 303439913ffSLin Ming u64 count; 304cf824788SJanosch Machowinski int current_count; 3056fd8050aSSudeep Holla int i, ret = 0; 3061da177e4SLinus Torvalds struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 3071da177e4SLinus Torvalds union acpi_object *cst; 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds if (nocst) 310d550d98dSPatrick Mochel return -ENODEV; 3111da177e4SLinus Torvalds 312991528d7SVenkatesh Pallipadi current_count = 0; 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); 3151da177e4SLinus Torvalds if (ACPI_FAILURE(status)) { 3161da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _CST, giving up\n")); 317d550d98dSPatrick Mochel return -ENODEV; 3181da177e4SLinus Torvalds } 3191da177e4SLinus Torvalds 32050dd0969SJan Engelhardt cst = buffer.pointer; 3211da177e4SLinus Torvalds 3221da177e4SLinus Torvalds /* There must be at least 2 elements */ 3231da177e4SLinus Torvalds if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) { 324b6ec26fbSSudeep Holla pr_err("not enough elements in _CST\n"); 3256fd8050aSSudeep Holla ret = -EFAULT; 3261da177e4SLinus Torvalds goto end; 3271da177e4SLinus Torvalds } 3281da177e4SLinus Torvalds 3291da177e4SLinus Torvalds count = cst->package.elements[0].integer.value; 3301da177e4SLinus Torvalds 3311da177e4SLinus Torvalds /* Validate number of power states. */ 3321da177e4SLinus Torvalds if (count < 1 || count != cst->package.count - 1) { 333b6ec26fbSSudeep Holla pr_err("count given by _CST is not valid\n"); 3346fd8050aSSudeep Holla ret = -EFAULT; 3351da177e4SLinus Torvalds goto end; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3381da177e4SLinus Torvalds /* Tell driver that at least _CST is supported. */ 3391da177e4SLinus Torvalds pr->flags.has_cst = 1; 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds for (i = 1; i <= count; i++) { 3421da177e4SLinus Torvalds union acpi_object *element; 3431da177e4SLinus Torvalds union acpi_object *obj; 3441da177e4SLinus Torvalds struct acpi_power_register *reg; 3451da177e4SLinus Torvalds struct acpi_processor_cx cx; 3461da177e4SLinus Torvalds 3471da177e4SLinus Torvalds memset(&cx, 0, sizeof(cx)); 3481da177e4SLinus Torvalds 34950dd0969SJan Engelhardt element = &(cst->package.elements[i]); 3501da177e4SLinus Torvalds if (element->type != ACPI_TYPE_PACKAGE) 3511da177e4SLinus Torvalds continue; 3521da177e4SLinus Torvalds 3531da177e4SLinus Torvalds if (element->package.count != 4) 3541da177e4SLinus Torvalds continue; 3551da177e4SLinus Torvalds 35650dd0969SJan Engelhardt obj = &(element->package.elements[0]); 3571da177e4SLinus Torvalds 3581da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_BUFFER) 3591da177e4SLinus Torvalds continue; 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds reg = (struct acpi_power_register *)obj->buffer.pointer; 3621da177e4SLinus Torvalds 3631da177e4SLinus Torvalds if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO && 3641da177e4SLinus Torvalds (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) 3651da177e4SLinus Torvalds continue; 3661da177e4SLinus Torvalds 3671da177e4SLinus Torvalds /* There should be an easy way to extract an integer... */ 36850dd0969SJan Engelhardt obj = &(element->package.elements[1]); 3691da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_INTEGER) 3701da177e4SLinus Torvalds continue; 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds cx.type = obj->integer.value; 373991528d7SVenkatesh Pallipadi /* 374991528d7SVenkatesh Pallipadi * Some buggy BIOSes won't list C1 in _CST - 375991528d7SVenkatesh Pallipadi * Let acpi_processor_get_power_info_default() handle them later 376991528d7SVenkatesh Pallipadi */ 377991528d7SVenkatesh Pallipadi if (i == 1 && cx.type != ACPI_STATE_C1) 378991528d7SVenkatesh Pallipadi current_count++; 3791da177e4SLinus Torvalds 380991528d7SVenkatesh Pallipadi cx.address = reg->address; 381991528d7SVenkatesh Pallipadi cx.index = current_count + 1; 3821da177e4SLinus Torvalds 383bc71bec9Svenkatesh.pallipadi@intel.com cx.entry_method = ACPI_CSTATE_SYSTEMIO; 384991528d7SVenkatesh Pallipadi if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { 385991528d7SVenkatesh Pallipadi if (acpi_processor_ffh_cstate_probe 386991528d7SVenkatesh Pallipadi (pr->id, &cx, reg) == 0) { 387bc71bec9Svenkatesh.pallipadi@intel.com cx.entry_method = ACPI_CSTATE_FFH; 388bc71bec9Svenkatesh.pallipadi@intel.com } else if (cx.type == ACPI_STATE_C1) { 389991528d7SVenkatesh Pallipadi /* 390991528d7SVenkatesh Pallipadi * C1 is a special case where FIXED_HARDWARE 391991528d7SVenkatesh Pallipadi * can be handled in non-MWAIT way as well. 392991528d7SVenkatesh Pallipadi * In that case, save this _CST entry info. 393991528d7SVenkatesh Pallipadi * Otherwise, ignore this info and continue. 394991528d7SVenkatesh Pallipadi */ 395bc71bec9Svenkatesh.pallipadi@intel.com cx.entry_method = ACPI_CSTATE_HALT; 3964fcb2fcdSVenkatesh Pallipadi snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); 397bc71bec9Svenkatesh.pallipadi@intel.com } else { 3981da177e4SLinus Torvalds continue; 399991528d7SVenkatesh Pallipadi } 400da5e09a1SZhao Yakui if (cx.type == ACPI_STATE_C1 && 401d1896049SThomas Renninger (boot_option_idle_override == IDLE_NOMWAIT)) { 402c1e3b377SZhao Yakui /* 403c1e3b377SZhao Yakui * In most cases the C1 space_id obtained from 404c1e3b377SZhao Yakui * _CST object is FIXED_HARDWARE access mode. 405c1e3b377SZhao Yakui * But when the option of idle=halt is added, 406c1e3b377SZhao Yakui * the entry_method type should be changed from 407c1e3b377SZhao Yakui * CSTATE_FFH to CSTATE_HALT. 408da5e09a1SZhao Yakui * When the option of idle=nomwait is added, 409da5e09a1SZhao Yakui * the C1 entry_method type should be 410da5e09a1SZhao Yakui * CSTATE_HALT. 411c1e3b377SZhao Yakui */ 412c1e3b377SZhao Yakui cx.entry_method = ACPI_CSTATE_HALT; 413c1e3b377SZhao Yakui snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI HLT"); 414c1e3b377SZhao Yakui } 4154fcb2fcdSVenkatesh Pallipadi } else { 4164fcb2fcdSVenkatesh Pallipadi snprintf(cx.desc, ACPI_CX_DESC_LEN, "ACPI IOPORT 0x%x", 4174fcb2fcdSVenkatesh Pallipadi cx.address); 418991528d7SVenkatesh Pallipadi } 4191da177e4SLinus Torvalds 4200fda6b40SVenkatesh Pallipadi if (cx.type == ACPI_STATE_C1) { 4210fda6b40SVenkatesh Pallipadi cx.valid = 1; 4220fda6b40SVenkatesh Pallipadi } 4234fcb2fcdSVenkatesh Pallipadi 42450dd0969SJan Engelhardt obj = &(element->package.elements[2]); 4251da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_INTEGER) 4261da177e4SLinus Torvalds continue; 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds cx.latency = obj->integer.value; 4291da177e4SLinus Torvalds 43050dd0969SJan Engelhardt obj = &(element->package.elements[3]); 4311da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_INTEGER) 4321da177e4SLinus Torvalds continue; 4331da177e4SLinus Torvalds 434cf824788SJanosch Machowinski current_count++; 435cf824788SJanosch Machowinski memcpy(&(pr->power.states[current_count]), &cx, sizeof(cx)); 436cf824788SJanosch Machowinski 437cf824788SJanosch Machowinski /* 438cf824788SJanosch Machowinski * We support total ACPI_PROCESSOR_MAX_POWER - 1 439cf824788SJanosch Machowinski * (From 1 through ACPI_PROCESSOR_MAX_POWER - 1) 440cf824788SJanosch Machowinski */ 441cf824788SJanosch Machowinski if (current_count >= (ACPI_PROCESSOR_MAX_POWER - 1)) { 442b6ec26fbSSudeep Holla pr_warn("Limiting number of power states to max (%d)\n", 443cf824788SJanosch Machowinski ACPI_PROCESSOR_MAX_POWER); 444b6ec26fbSSudeep Holla pr_warn("Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n"); 445cf824788SJanosch Machowinski break; 446cf824788SJanosch Machowinski } 4471da177e4SLinus Torvalds } 4481da177e4SLinus Torvalds 4494be44fcdSLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", 450cf824788SJanosch Machowinski current_count)); 4511da177e4SLinus Torvalds 4521da177e4SLinus Torvalds /* Validate number of power states discovered */ 453cf824788SJanosch Machowinski if (current_count < 2) 4546fd8050aSSudeep Holla ret = -EFAULT; 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds end: 45702438d87SLen Brown kfree(buffer.pointer); 4581da177e4SLinus Torvalds 4596fd8050aSSudeep Holla return ret; 4601da177e4SLinus Torvalds } 4611da177e4SLinus Torvalds 4624be44fcdSLen Brown static void acpi_processor_power_verify_c3(struct acpi_processor *pr, 4631da177e4SLinus Torvalds struct acpi_processor_cx *cx) 4641da177e4SLinus Torvalds { 465ee1ca48fSPallipadi, Venkatesh static int bm_check_flag = -1; 466ee1ca48fSPallipadi, Venkatesh static int bm_control_flag = -1; 46702df8b93SVenkatesh Pallipadi 4681da177e4SLinus Torvalds 4691da177e4SLinus Torvalds if (!cx->address) 470d550d98dSPatrick Mochel return; 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds /* 4731da177e4SLinus Torvalds * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) 4741da177e4SLinus Torvalds * DMA transfers are used by any ISA device to avoid livelock. 4751da177e4SLinus Torvalds * Note that we could disable Type-F DMA (as recommended by 4761da177e4SLinus Torvalds * the erratum), but this is known to disrupt certain ISA 4771da177e4SLinus Torvalds * devices thus we take the conservative approach. 4781da177e4SLinus Torvalds */ 4791da177e4SLinus Torvalds else if (errata.piix4.fdma) { 4801da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 4811da177e4SLinus Torvalds "C3 not supported on PIIX4 with Type-F DMA\n")); 482d550d98dSPatrick Mochel return; 4831da177e4SLinus Torvalds } 4841da177e4SLinus Torvalds 48502df8b93SVenkatesh Pallipadi /* All the logic here assumes flags.bm_check is same across all CPUs */ 486ee1ca48fSPallipadi, Venkatesh if (bm_check_flag == -1) { 48702df8b93SVenkatesh Pallipadi /* Determine whether bm_check is needed based on CPU */ 48802df8b93SVenkatesh Pallipadi acpi_processor_power_init_bm_check(&(pr->flags), pr->id); 48902df8b93SVenkatesh Pallipadi bm_check_flag = pr->flags.bm_check; 490ee1ca48fSPallipadi, Venkatesh bm_control_flag = pr->flags.bm_control; 49102df8b93SVenkatesh Pallipadi } else { 49202df8b93SVenkatesh Pallipadi pr->flags.bm_check = bm_check_flag; 493ee1ca48fSPallipadi, Venkatesh pr->flags.bm_control = bm_control_flag; 49402df8b93SVenkatesh Pallipadi } 49502df8b93SVenkatesh Pallipadi 49602df8b93SVenkatesh Pallipadi if (pr->flags.bm_check) { 49702df8b93SVenkatesh Pallipadi if (!pr->flags.bm_control) { 498ed3110efSVenki Pallipadi if (pr->flags.has_cst != 1) { 499ed3110efSVenki Pallipadi /* bus mastering control is necessary */ 50002df8b93SVenkatesh Pallipadi ACPI_DEBUG_PRINT((ACPI_DB_INFO, 501ed3110efSVenki Pallipadi "C3 support requires BM control\n")); 502ed3110efSVenki Pallipadi return; 503ed3110efSVenki Pallipadi } else { 504ed3110efSVenki Pallipadi /* Here we enter C3 without bus mastering */ 505ed3110efSVenki Pallipadi ACPI_DEBUG_PRINT((ACPI_DB_INFO, 506ed3110efSVenki Pallipadi "C3 support without BM control\n")); 507ed3110efSVenki Pallipadi } 50802df8b93SVenkatesh Pallipadi } 50902df8b93SVenkatesh Pallipadi } else { 51002df8b93SVenkatesh Pallipadi /* 51102df8b93SVenkatesh Pallipadi * WBINVD should be set in fadt, for C3 state to be 51202df8b93SVenkatesh Pallipadi * supported on when bm_check is not required. 51302df8b93SVenkatesh Pallipadi */ 514cee324b1SAlexey Starikovskiy if (!(acpi_gbl_FADT.flags & ACPI_FADT_WBINVD)) { 51502df8b93SVenkatesh Pallipadi ACPI_DEBUG_PRINT((ACPI_DB_INFO, 51602df8b93SVenkatesh Pallipadi "Cache invalidation should work properly" 51702df8b93SVenkatesh Pallipadi " for C3 to be enabled on SMP systems\n")); 518d550d98dSPatrick Mochel return; 51902df8b93SVenkatesh Pallipadi } 52002df8b93SVenkatesh Pallipadi } 52102df8b93SVenkatesh Pallipadi 5221da177e4SLinus Torvalds /* 5231da177e4SLinus Torvalds * Otherwise we've met all of our C3 requirements. 5241da177e4SLinus Torvalds * Normalize the C3 latency to expidite policy. Enable 5251da177e4SLinus Torvalds * checking of bus mastering status (bm_check) so we can 5261da177e4SLinus Torvalds * use this in our C3 policy 5271da177e4SLinus Torvalds */ 5281da177e4SLinus Torvalds cx->valid = 1; 5294f86d3a8SLen Brown 53031878dd8SLen Brown /* 53131878dd8SLen Brown * On older chipsets, BM_RLD needs to be set 53231878dd8SLen Brown * in order for Bus Master activity to wake the 53331878dd8SLen Brown * system from C3. Newer chipsets handle DMA 53431878dd8SLen Brown * during C3 automatically and BM_RLD is a NOP. 53531878dd8SLen Brown * In either case, the proper way to 53631878dd8SLen Brown * handle BM_RLD is to set it and leave it set. 53731878dd8SLen Brown */ 53850ffba1bSBob Moore acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1); 5391da177e4SLinus Torvalds 540d550d98dSPatrick Mochel return; 5411da177e4SLinus Torvalds } 5421da177e4SLinus Torvalds 5431da177e4SLinus Torvalds static int acpi_processor_power_verify(struct acpi_processor *pr) 5441da177e4SLinus Torvalds { 5451da177e4SLinus Torvalds unsigned int i; 5461da177e4SLinus Torvalds unsigned int working = 0; 5476eb0a0fdSVenkatesh Pallipadi 548169a0abbSThomas Gleixner pr->power.timer_broadcast_on_state = INT_MAX; 5496eb0a0fdSVenkatesh Pallipadi 550a0bf284bSLen Brown for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { 5511da177e4SLinus Torvalds struct acpi_processor_cx *cx = &pr->power.states[i]; 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds switch (cx->type) { 5541da177e4SLinus Torvalds case ACPI_STATE_C1: 5551da177e4SLinus Torvalds cx->valid = 1; 5561da177e4SLinus Torvalds break; 5571da177e4SLinus Torvalds 5581da177e4SLinus Torvalds case ACPI_STATE_C2: 559d22edd29SLen Brown if (!cx->address) 560d22edd29SLen Brown break; 561d22edd29SLen Brown cx->valid = 1; 5621da177e4SLinus Torvalds break; 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds case ACPI_STATE_C3: 5651da177e4SLinus Torvalds acpi_processor_power_verify_c3(pr, cx); 5661da177e4SLinus Torvalds break; 5671da177e4SLinus Torvalds } 5687e275cc4SLen Brown if (!cx->valid) 5697e275cc4SLen Brown continue; 5701da177e4SLinus Torvalds 5717e275cc4SLen Brown lapic_timer_check_state(i, pr, cx); 5727e275cc4SLen Brown tsc_check_state(cx->type); 5731da177e4SLinus Torvalds working++; 5741da177e4SLinus Torvalds } 5751da177e4SLinus Torvalds 576918aae42SHidetoshi Seto lapic_timer_propagate_broadcast(pr); 577bd663347SAndi Kleen 5781da177e4SLinus Torvalds return (working); 5791da177e4SLinus Torvalds } 5801da177e4SLinus Torvalds 581a36a7fecSSudeep Holla static int acpi_processor_get_cstate_info(struct acpi_processor *pr) 5821da177e4SLinus Torvalds { 5831da177e4SLinus Torvalds unsigned int i; 5841da177e4SLinus Torvalds int result; 5851da177e4SLinus Torvalds 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds /* NOTE: the idle thread may not be running while calling 5881da177e4SLinus Torvalds * this function */ 5891da177e4SLinus Torvalds 590991528d7SVenkatesh Pallipadi /* Zero initialize all the C-states info. */ 591991528d7SVenkatesh Pallipadi memset(pr->power.states, 0, sizeof(pr->power.states)); 592991528d7SVenkatesh Pallipadi 5931da177e4SLinus Torvalds result = acpi_processor_get_power_info_cst(pr); 5946d93c648SVenkatesh Pallipadi if (result == -ENODEV) 595c5a114f1SDarrick J. Wong result = acpi_processor_get_power_info_fadt(pr); 5966d93c648SVenkatesh Pallipadi 597991528d7SVenkatesh Pallipadi if (result) 598991528d7SVenkatesh Pallipadi return result; 599991528d7SVenkatesh Pallipadi 600991528d7SVenkatesh Pallipadi acpi_processor_get_power_info_default(pr); 601991528d7SVenkatesh Pallipadi 602cf824788SJanosch Machowinski pr->power.count = acpi_processor_power_verify(pr); 6031da177e4SLinus Torvalds 6041da177e4SLinus Torvalds /* 6051da177e4SLinus Torvalds * if one state of type C2 or C3 is available, mark this 6061da177e4SLinus Torvalds * CPU as being "idle manageable" 6071da177e4SLinus Torvalds */ 6081da177e4SLinus Torvalds for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { 609acf05f4bSVenkatesh Pallipadi if (pr->power.states[i].valid) { 6101da177e4SLinus Torvalds pr->power.count = i; 6112203d6edSLinus Torvalds if (pr->power.states[i].type >= ACPI_STATE_C2) 6121da177e4SLinus Torvalds pr->flags.power = 1; 6131da177e4SLinus Torvalds } 614acf05f4bSVenkatesh Pallipadi } 6151da177e4SLinus Torvalds 616d550d98dSPatrick Mochel return 0; 6171da177e4SLinus Torvalds } 6181da177e4SLinus Torvalds 6194f86d3a8SLen Brown /** 6204f86d3a8SLen Brown * acpi_idle_bm_check - checks if bus master activity was detected 6214f86d3a8SLen Brown */ 6224f86d3a8SLen Brown static int acpi_idle_bm_check(void) 6234f86d3a8SLen Brown { 6244f86d3a8SLen Brown u32 bm_status = 0; 6254f86d3a8SLen Brown 626d3e7e99fSLen Brown if (bm_check_disable) 627d3e7e99fSLen Brown return 0; 628d3e7e99fSLen Brown 62950ffba1bSBob Moore acpi_read_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, &bm_status); 6304f86d3a8SLen Brown if (bm_status) 63150ffba1bSBob Moore acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_STATUS, 1); 6324f86d3a8SLen Brown /* 6334f86d3a8SLen Brown * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect 6344f86d3a8SLen Brown * the true state of bus mastering activity; forcing us to 6354f86d3a8SLen Brown * manually check the BMIDEA bit of each IDE channel. 6364f86d3a8SLen Brown */ 6374f86d3a8SLen Brown else if (errata.piix4.bmisx) { 6384f86d3a8SLen Brown if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) 6394f86d3a8SLen Brown || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01)) 6404f86d3a8SLen Brown bm_status = 1; 6414f86d3a8SLen Brown } 6424f86d3a8SLen Brown return bm_status; 6434f86d3a8SLen Brown } 6444f86d3a8SLen Brown 645fa583f71SYin Fengwei static void wait_for_freeze(void) 646fa583f71SYin Fengwei { 647fa583f71SYin Fengwei #ifdef CONFIG_X86 648fa583f71SYin Fengwei /* No delay is needed if we are in guest */ 649fa583f71SYin Fengwei if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) 650fa583f71SYin Fengwei return; 651fa583f71SYin Fengwei #endif 652fa583f71SYin Fengwei /* Dummy wait op - must do something useless after P_LVL2 read 653fa583f71SYin Fengwei because chipsets cannot guarantee that STPCLK# signal 654fa583f71SYin Fengwei gets asserted in time to freeze execution properly. */ 655fa583f71SYin Fengwei inl(acpi_gbl_FADT.xpm_timer_block.address); 656fa583f71SYin Fengwei } 657fa583f71SYin Fengwei 6584f86d3a8SLen Brown /** 659b00783fdSRafael J. Wysocki * acpi_idle_do_entry - enter idle state using the appropriate method 6604f86d3a8SLen Brown * @cx: cstate data 661bc71bec9Svenkatesh.pallipadi@intel.com * 662bc71bec9Svenkatesh.pallipadi@intel.com * Caller disables interrupt before call and enables interrupt after return. 6634f86d3a8SLen Brown */ 6646727ad9eSChris Metcalf static void __cpuidle acpi_idle_do_entry(struct acpi_processor_cx *cx) 6654f86d3a8SLen Brown { 666bc71bec9Svenkatesh.pallipadi@intel.com if (cx->entry_method == ACPI_CSTATE_FFH) { 6674f86d3a8SLen Brown /* Call into architectural FFH based C-state */ 6684f86d3a8SLen Brown acpi_processor_ffh_cstate_enter(cx); 669bc71bec9Svenkatesh.pallipadi@intel.com } else if (cx->entry_method == ACPI_CSTATE_HALT) { 670bc71bec9Svenkatesh.pallipadi@intel.com acpi_safe_halt(); 6714f86d3a8SLen Brown } else { 6724f86d3a8SLen Brown /* IO port based C-state */ 6734f86d3a8SLen Brown inb(cx->address); 674fa583f71SYin Fengwei wait_for_freeze(); 6754f86d3a8SLen Brown } 6764f86d3a8SLen Brown } 6774f86d3a8SLen Brown 6784f86d3a8SLen Brown /** 6791a022e3fSBoris Ostrovsky * acpi_idle_play_dead - enters an ACPI state for long-term idle (i.e. off-lining) 6801a022e3fSBoris Ostrovsky * @dev: the target CPU 6811a022e3fSBoris Ostrovsky * @index: the index of suggested state 6821a022e3fSBoris Ostrovsky */ 6831a022e3fSBoris Ostrovsky static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) 6841a022e3fSBoris Ostrovsky { 6856240a10dSAlex Shi struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); 6861a022e3fSBoris Ostrovsky 6871a022e3fSBoris Ostrovsky ACPI_FLUSH_CPU_CACHE(); 6881a022e3fSBoris Ostrovsky 6891a022e3fSBoris Ostrovsky while (1) { 6901a022e3fSBoris Ostrovsky 6911a022e3fSBoris Ostrovsky if (cx->entry_method == ACPI_CSTATE_HALT) 69254f70077SLuck, Tony safe_halt(); 6931a022e3fSBoris Ostrovsky else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) { 6941a022e3fSBoris Ostrovsky inb(cx->address); 695fa583f71SYin Fengwei wait_for_freeze(); 6961a022e3fSBoris Ostrovsky } else 6971a022e3fSBoris Ostrovsky return -ENODEV; 6981a022e3fSBoris Ostrovsky } 6991a022e3fSBoris Ostrovsky 7001a022e3fSBoris Ostrovsky /* Never reached */ 7011a022e3fSBoris Ostrovsky return 0; 7021a022e3fSBoris Ostrovsky } 7031a022e3fSBoris Ostrovsky 704adcb2623SRafael J. Wysocki static bool acpi_idle_fallback_to_c1(struct acpi_processor *pr) 705adcb2623SRafael J. Wysocki { 7065f508185SRafael J. Wysocki return IS_ENABLED(CONFIG_HOTPLUG_CPU) && !pr->flags.has_cst && 7075f508185SRafael J. Wysocki !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED); 708adcb2623SRafael J. Wysocki } 709adcb2623SRafael J. Wysocki 7104f86d3a8SLen Brown static int c3_cpu_count; 711e12f65f7SThomas Gleixner static DEFINE_RAW_SPINLOCK(c3_lock); 7124f86d3a8SLen Brown 7134f86d3a8SLen Brown /** 7144f86d3a8SLen Brown * acpi_idle_enter_bm - enters C3 with proper BM handling 7156491bc0cSRafael J. Wysocki * @pr: Target processor 7166491bc0cSRafael J. Wysocki * @cx: Target state context 7175f508185SRafael J. Wysocki * @timer_bc: Whether or not to change timer mode to broadcast 7184f86d3a8SLen Brown */ 7196491bc0cSRafael J. Wysocki static void acpi_idle_enter_bm(struct acpi_processor *pr, 7205f508185SRafael J. Wysocki struct acpi_processor_cx *cx, bool timer_bc) 7214f86d3a8SLen Brown { 72267535736SAndy Lutomirski acpi_unlazy_tlb(smp_processor_id()); 72367535736SAndy Lutomirski 7244f86d3a8SLen Brown /* 7254f86d3a8SLen Brown * Must be done before busmaster disable as we might need to 7264f86d3a8SLen Brown * access HPET ! 7274f86d3a8SLen Brown */ 7285f508185SRafael J. Wysocki if (timer_bc) 7297e275cc4SLen Brown lapic_timer_state_broadcast(pr, cx, 1); 7304f86d3a8SLen Brown 731c9c860e5SVenkatesh Pallipadi /* 732c9c860e5SVenkatesh Pallipadi * disable bus master 733c9c860e5SVenkatesh Pallipadi * bm_check implies we need ARB_DIS 734c9c860e5SVenkatesh Pallipadi * bm_control implies whether we can do ARB_DIS 735c9c860e5SVenkatesh Pallipadi * 736c9c860e5SVenkatesh Pallipadi * That leaves a case where bm_check is set and bm_control is 737c9c860e5SVenkatesh Pallipadi * not set. In that case we cannot do much, we enter C3 738c9c860e5SVenkatesh Pallipadi * without doing anything. 739c9c860e5SVenkatesh Pallipadi */ 7402a738352SRafael J. Wysocki if (pr->flags.bm_control) { 741e12f65f7SThomas Gleixner raw_spin_lock(&c3_lock); 7424f86d3a8SLen Brown c3_cpu_count++; 7434f86d3a8SLen Brown /* Disable bus master arbitration when all CPUs are in C3 */ 7444f86d3a8SLen Brown if (c3_cpu_count == num_online_cpus()) 74550ffba1bSBob Moore acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); 746e12f65f7SThomas Gleixner raw_spin_unlock(&c3_lock); 747c9c860e5SVenkatesh Pallipadi } 7484f86d3a8SLen Brown 7494f86d3a8SLen Brown acpi_idle_do_entry(cx); 7504f86d3a8SLen Brown 7514f86d3a8SLen Brown /* Re-enable bus master arbitration */ 7522a738352SRafael J. Wysocki if (pr->flags.bm_control) { 753e12f65f7SThomas Gleixner raw_spin_lock(&c3_lock); 75450ffba1bSBob Moore acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); 7554f86d3a8SLen Brown c3_cpu_count--; 756e12f65f7SThomas Gleixner raw_spin_unlock(&c3_lock); 7574f86d3a8SLen Brown } 7584f86d3a8SLen Brown 7595f508185SRafael J. Wysocki if (timer_bc) 7607e275cc4SLen Brown lapic_timer_state_broadcast(pr, cx, 0); 7616491bc0cSRafael J. Wysocki } 7626491bc0cSRafael J. Wysocki 7636491bc0cSRafael J. Wysocki static int acpi_idle_enter(struct cpuidle_device *dev, 7646491bc0cSRafael J. Wysocki struct cpuidle_driver *drv, int index) 7656491bc0cSRafael J. Wysocki { 7666491bc0cSRafael J. Wysocki struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); 7676491bc0cSRafael J. Wysocki struct acpi_processor *pr; 7686491bc0cSRafael J. Wysocki 7696491bc0cSRafael J. Wysocki pr = __this_cpu_read(processors); 7706491bc0cSRafael J. Wysocki if (unlikely(!pr)) 7716491bc0cSRafael J. Wysocki return -EINVAL; 7726491bc0cSRafael J. Wysocki 7736491bc0cSRafael J. Wysocki if (cx->type != ACPI_STATE_C1) { 7745f508185SRafael J. Wysocki if (acpi_idle_fallback_to_c1(pr) && num_online_cpus() > 1) { 775dc2251bfSRafael J. Wysocki index = ACPI_IDLE_STATE_START; 7766491bc0cSRafael J. Wysocki cx = per_cpu(acpi_cstate[index], dev->cpu); 7776491bc0cSRafael J. Wysocki } else if (cx->type == ACPI_STATE_C3 && pr->flags.bm_check) { 7786491bc0cSRafael J. Wysocki if (cx->bm_sts_skip || !acpi_idle_bm_check()) { 7795f508185SRafael J. Wysocki acpi_idle_enter_bm(pr, cx, true); 7806491bc0cSRafael J. Wysocki return index; 7816491bc0cSRafael J. Wysocki } else if (drv->safe_state_index >= 0) { 7826491bc0cSRafael J. Wysocki index = drv->safe_state_index; 7836491bc0cSRafael J. Wysocki cx = per_cpu(acpi_cstate[index], dev->cpu); 7846491bc0cSRafael J. Wysocki } else { 7856491bc0cSRafael J. Wysocki acpi_safe_halt(); 7866491bc0cSRafael J. Wysocki return -EBUSY; 7876491bc0cSRafael J. Wysocki } 7886491bc0cSRafael J. Wysocki } 7896491bc0cSRafael J. Wysocki } 7906491bc0cSRafael J. Wysocki 7916491bc0cSRafael J. Wysocki lapic_timer_state_broadcast(pr, cx, 1); 7926491bc0cSRafael J. Wysocki 7936491bc0cSRafael J. Wysocki if (cx->type == ACPI_STATE_C3) 7946491bc0cSRafael J. Wysocki ACPI_FLUSH_CPU_CACHE(); 7956491bc0cSRafael J. Wysocki 7966491bc0cSRafael J. Wysocki acpi_idle_do_entry(cx); 7976491bc0cSRafael J. Wysocki 7986491bc0cSRafael J. Wysocki lapic_timer_state_broadcast(pr, cx, 0); 7996491bc0cSRafael J. Wysocki 800e978aa7dSDeepthi Dharwar return index; 8014f86d3a8SLen Brown } 8024f86d3a8SLen Brown 80328ba086eSRafael J. Wysocki static void acpi_idle_enter_s2idle(struct cpuidle_device *dev, 8045f508185SRafael J. Wysocki struct cpuidle_driver *drv, int index) 8055f508185SRafael J. Wysocki { 8065f508185SRafael J. Wysocki struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); 8075f508185SRafael J. Wysocki 8085f508185SRafael J. Wysocki if (cx->type == ACPI_STATE_C3) { 8095f508185SRafael J. Wysocki struct acpi_processor *pr = __this_cpu_read(processors); 8105f508185SRafael J. Wysocki 8115f508185SRafael J. Wysocki if (unlikely(!pr)) 8125f508185SRafael J. Wysocki return; 8135f508185SRafael J. Wysocki 8145f508185SRafael J. Wysocki if (pr->flags.bm_check) { 8155f508185SRafael J. Wysocki acpi_idle_enter_bm(pr, cx, false); 8165f508185SRafael J. Wysocki return; 8175f508185SRafael J. Wysocki } else { 8185f508185SRafael J. Wysocki ACPI_FLUSH_CPU_CACHE(); 8195f508185SRafael J. Wysocki } 8205f508185SRafael J. Wysocki } 8215f508185SRafael J. Wysocki acpi_idle_do_entry(cx); 8225f508185SRafael J. Wysocki } 8235f508185SRafael J. Wysocki 8246ef0f086SDaniel Lezcano static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, 8256ef0f086SDaniel Lezcano struct cpuidle_device *dev) 8264f86d3a8SLen Brown { 827dc2251bfSRafael J. Wysocki int i, count = ACPI_IDLE_STATE_START; 8284f86d3a8SLen Brown struct acpi_processor_cx *cx; 8294f86d3a8SLen Brown 830615dfd93SLen Brown if (max_cstate == 0) 831615dfd93SLen Brown max_cstate = 1; 832615dfd93SLen Brown 8334f86d3a8SLen Brown for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { 8344f86d3a8SLen Brown cx = &pr->power.states[i]; 8354f86d3a8SLen Brown 8364f86d3a8SLen Brown if (!cx->valid) 8374f86d3a8SLen Brown continue; 8384f86d3a8SLen Brown 8396240a10dSAlex Shi per_cpu(acpi_cstate[count], dev->cpu) = cx; 8404f86d3a8SLen Brown 84146bcfad7SDeepthi Dharwar count++; 84246bcfad7SDeepthi Dharwar if (count == CPUIDLE_STATE_MAX) 84346bcfad7SDeepthi Dharwar break; 84446bcfad7SDeepthi Dharwar } 84546bcfad7SDeepthi Dharwar 84646bcfad7SDeepthi Dharwar if (!count) 84746bcfad7SDeepthi Dharwar return -EINVAL; 84846bcfad7SDeepthi Dharwar 84946bcfad7SDeepthi Dharwar return 0; 85046bcfad7SDeepthi Dharwar } 85146bcfad7SDeepthi Dharwar 852a36a7fecSSudeep Holla static int acpi_processor_setup_cstates(struct acpi_processor *pr) 85346bcfad7SDeepthi Dharwar { 8541b39e3f8SRafael J. Wysocki int i, count; 85546bcfad7SDeepthi Dharwar struct acpi_processor_cx *cx; 85646bcfad7SDeepthi Dharwar struct cpuidle_state *state; 85746bcfad7SDeepthi Dharwar struct cpuidle_driver *drv = &acpi_idle_driver; 85846bcfad7SDeepthi Dharwar 85946bcfad7SDeepthi Dharwar if (max_cstate == 0) 86046bcfad7SDeepthi Dharwar max_cstate = 1; 86146bcfad7SDeepthi Dharwar 8621b39e3f8SRafael J. Wysocki if (IS_ENABLED(CONFIG_ARCH_HAS_CPU_RELAX)) { 8631b39e3f8SRafael J. Wysocki cpuidle_poll_state_init(drv); 8641b39e3f8SRafael J. Wysocki count = 1; 8651b39e3f8SRafael J. Wysocki } else { 8661b39e3f8SRafael J. Wysocki count = 0; 8671b39e3f8SRafael J. Wysocki } 8681b39e3f8SRafael J. Wysocki 86946bcfad7SDeepthi Dharwar for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { 87046bcfad7SDeepthi Dharwar cx = &pr->power.states[i]; 87146bcfad7SDeepthi Dharwar 87246bcfad7SDeepthi Dharwar if (!cx->valid) 87346bcfad7SDeepthi Dharwar continue; 87446bcfad7SDeepthi Dharwar 87546bcfad7SDeepthi Dharwar state = &drv->states[count]; 8764f86d3a8SLen Brown snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); 877a36a7fecSSudeep Holla strlcpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); 8784f86d3a8SLen Brown state->exit_latency = cx->latency; 8794963f620SLen Brown state->target_residency = cx->latency * latency_factor; 8806491bc0cSRafael J. Wysocki state->enter = acpi_idle_enter; 8814f86d3a8SLen Brown 8824f86d3a8SLen Brown state->flags = 0; 8836491bc0cSRafael J. Wysocki if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2) { 8841a022e3fSBoris Ostrovsky state->enter_dead = acpi_idle_play_dead; 88546bcfad7SDeepthi Dharwar drv->safe_state_index = count; 8864f86d3a8SLen Brown } 8875f508185SRafael J. Wysocki /* 88828ba086eSRafael J. Wysocki * Halt-induced C1 is not good for ->enter_s2idle, because it 8895f508185SRafael J. Wysocki * re-enables interrupts on exit. Moreover, C1 is generally not 8905f508185SRafael J. Wysocki * particularly interesting from the suspend-to-idle angle, so 8915f508185SRafael J. Wysocki * avoid C1 and the situations in which we may need to fall back 8925f508185SRafael J. Wysocki * to it altogether. 8935f508185SRafael J. Wysocki */ 8945f508185SRafael J. Wysocki if (cx->type != ACPI_STATE_C1 && !acpi_idle_fallback_to_c1(pr)) 89528ba086eSRafael J. Wysocki state->enter_s2idle = acpi_idle_enter_s2idle; 8964f86d3a8SLen Brown 8974f86d3a8SLen Brown count++; 8989a0b8415Svenkatesh.pallipadi@intel.com if (count == CPUIDLE_STATE_MAX) 8999a0b8415Svenkatesh.pallipadi@intel.com break; 9004f86d3a8SLen Brown } 9014f86d3a8SLen Brown 90246bcfad7SDeepthi Dharwar drv->state_count = count; 9034f86d3a8SLen Brown 9044f86d3a8SLen Brown if (!count) 9054f86d3a8SLen Brown return -EINVAL; 9064f86d3a8SLen Brown 9074f86d3a8SLen Brown return 0; 9084f86d3a8SLen Brown } 9094f86d3a8SLen Brown 91035ae7133SSudeep Holla static inline void acpi_processor_cstate_first_run_checks(void) 91135ae7133SSudeep Holla { 91235ae7133SSudeep Holla acpi_status status; 91335ae7133SSudeep Holla static int first_run; 91435ae7133SSudeep Holla 91535ae7133SSudeep Holla if (first_run) 91635ae7133SSudeep Holla return; 91735ae7133SSudeep Holla dmi_check_system(processor_power_dmi_table); 91835ae7133SSudeep Holla max_cstate = acpi_processor_cstate_check(max_cstate); 91935ae7133SSudeep Holla if (max_cstate < ACPI_C_STATES_MAX) 92035ae7133SSudeep Holla pr_notice("ACPI: processor limited to max C-state %d\n", 92135ae7133SSudeep Holla max_cstate); 92235ae7133SSudeep Holla first_run++; 92335ae7133SSudeep Holla 92435ae7133SSudeep Holla if (acpi_gbl_FADT.cst_control && !nocst) { 92535ae7133SSudeep Holla status = acpi_os_write_port(acpi_gbl_FADT.smi_command, 92635ae7133SSudeep Holla acpi_gbl_FADT.cst_control, 8); 92735ae7133SSudeep Holla if (ACPI_FAILURE(status)) 92835ae7133SSudeep Holla ACPI_EXCEPTION((AE_INFO, status, 92935ae7133SSudeep Holla "Notifying BIOS of _CST ability failed")); 93035ae7133SSudeep Holla } 93135ae7133SSudeep Holla } 93235ae7133SSudeep Holla #else 93335ae7133SSudeep Holla 93435ae7133SSudeep Holla static inline int disabled_by_idle_boot_param(void) { return 0; } 93535ae7133SSudeep Holla static inline void acpi_processor_cstate_first_run_checks(void) { } 936a36a7fecSSudeep Holla static int acpi_processor_get_cstate_info(struct acpi_processor *pr) 93735ae7133SSudeep Holla { 93835ae7133SSudeep Holla return -ENODEV; 93935ae7133SSudeep Holla } 94035ae7133SSudeep Holla 94135ae7133SSudeep Holla static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr, 94235ae7133SSudeep Holla struct cpuidle_device *dev) 94335ae7133SSudeep Holla { 94435ae7133SSudeep Holla return -EINVAL; 94535ae7133SSudeep Holla } 94635ae7133SSudeep Holla 947a36a7fecSSudeep Holla static int acpi_processor_setup_cstates(struct acpi_processor *pr) 94835ae7133SSudeep Holla { 94935ae7133SSudeep Holla return -EINVAL; 95035ae7133SSudeep Holla } 95135ae7133SSudeep Holla 95235ae7133SSudeep Holla #endif /* CONFIG_ACPI_PROCESSOR_CSTATE */ 95335ae7133SSudeep Holla 954a36a7fecSSudeep Holla struct acpi_lpi_states_array { 955a36a7fecSSudeep Holla unsigned int size; 956a36a7fecSSudeep Holla unsigned int composite_states_size; 957a36a7fecSSudeep Holla struct acpi_lpi_state *entries; 958a36a7fecSSudeep Holla struct acpi_lpi_state *composite_states[ACPI_PROCESSOR_MAX_POWER]; 959a36a7fecSSudeep Holla }; 960a36a7fecSSudeep Holla 961a36a7fecSSudeep Holla static int obj_get_integer(union acpi_object *obj, u32 *value) 962a36a7fecSSudeep Holla { 963a36a7fecSSudeep Holla if (obj->type != ACPI_TYPE_INTEGER) 964a36a7fecSSudeep Holla return -EINVAL; 965a36a7fecSSudeep Holla 966a36a7fecSSudeep Holla *value = obj->integer.value; 967a36a7fecSSudeep Holla return 0; 968a36a7fecSSudeep Holla } 969a36a7fecSSudeep Holla 970a36a7fecSSudeep Holla static int acpi_processor_evaluate_lpi(acpi_handle handle, 971a36a7fecSSudeep Holla struct acpi_lpi_states_array *info) 972a36a7fecSSudeep Holla { 973a36a7fecSSudeep Holla acpi_status status; 974a36a7fecSSudeep Holla int ret = 0; 975a36a7fecSSudeep Holla int pkg_count, state_idx = 1, loop; 976a36a7fecSSudeep Holla struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 977a36a7fecSSudeep Holla union acpi_object *lpi_data; 978a36a7fecSSudeep Holla struct acpi_lpi_state *lpi_state; 979a36a7fecSSudeep Holla 980a36a7fecSSudeep Holla status = acpi_evaluate_object(handle, "_LPI", NULL, &buffer); 981a36a7fecSSudeep Holla if (ACPI_FAILURE(status)) { 982a36a7fecSSudeep Holla ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _LPI, giving up\n")); 983a36a7fecSSudeep Holla return -ENODEV; 984a36a7fecSSudeep Holla } 985a36a7fecSSudeep Holla 986a36a7fecSSudeep Holla lpi_data = buffer.pointer; 987a36a7fecSSudeep Holla 988a36a7fecSSudeep Holla /* There must be at least 4 elements = 3 elements + 1 package */ 989a36a7fecSSudeep Holla if (!lpi_data || lpi_data->type != ACPI_TYPE_PACKAGE || 990a36a7fecSSudeep Holla lpi_data->package.count < 4) { 991a36a7fecSSudeep Holla pr_debug("not enough elements in _LPI\n"); 992a36a7fecSSudeep Holla ret = -ENODATA; 993a36a7fecSSudeep Holla goto end; 994a36a7fecSSudeep Holla } 995a36a7fecSSudeep Holla 996a36a7fecSSudeep Holla pkg_count = lpi_data->package.elements[2].integer.value; 997a36a7fecSSudeep Holla 998a36a7fecSSudeep Holla /* Validate number of power states. */ 999a36a7fecSSudeep Holla if (pkg_count < 1 || pkg_count != lpi_data->package.count - 3) { 1000a36a7fecSSudeep Holla pr_debug("count given by _LPI is not valid\n"); 1001a36a7fecSSudeep Holla ret = -ENODATA; 1002a36a7fecSSudeep Holla goto end; 1003a36a7fecSSudeep Holla } 1004a36a7fecSSudeep Holla 1005a36a7fecSSudeep Holla lpi_state = kcalloc(pkg_count, sizeof(*lpi_state), GFP_KERNEL); 1006a36a7fecSSudeep Holla if (!lpi_state) { 1007a36a7fecSSudeep Holla ret = -ENOMEM; 1008a36a7fecSSudeep Holla goto end; 1009a36a7fecSSudeep Holla } 1010a36a7fecSSudeep Holla 1011a36a7fecSSudeep Holla info->size = pkg_count; 1012a36a7fecSSudeep Holla info->entries = lpi_state; 1013a36a7fecSSudeep Holla 1014a36a7fecSSudeep Holla /* LPI States start at index 3 */ 1015a36a7fecSSudeep Holla for (loop = 3; state_idx <= pkg_count; loop++, state_idx++, lpi_state++) { 1016a36a7fecSSudeep Holla union acpi_object *element, *pkg_elem, *obj; 1017a36a7fecSSudeep Holla 1018a36a7fecSSudeep Holla element = &lpi_data->package.elements[loop]; 1019a36a7fecSSudeep Holla if (element->type != ACPI_TYPE_PACKAGE || element->package.count < 7) 1020a36a7fecSSudeep Holla continue; 1021a36a7fecSSudeep Holla 1022a36a7fecSSudeep Holla pkg_elem = element->package.elements; 1023a36a7fecSSudeep Holla 1024a36a7fecSSudeep Holla obj = pkg_elem + 6; 1025a36a7fecSSudeep Holla if (obj->type == ACPI_TYPE_BUFFER) { 1026a36a7fecSSudeep Holla struct acpi_power_register *reg; 1027a36a7fecSSudeep Holla 1028a36a7fecSSudeep Holla reg = (struct acpi_power_register *)obj->buffer.pointer; 1029a36a7fecSSudeep Holla if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO && 1030a36a7fecSSudeep Holla reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE) 1031a36a7fecSSudeep Holla continue; 1032a36a7fecSSudeep Holla 1033a36a7fecSSudeep Holla lpi_state->address = reg->address; 1034a36a7fecSSudeep Holla lpi_state->entry_method = 1035a36a7fecSSudeep Holla reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE ? 1036a36a7fecSSudeep Holla ACPI_CSTATE_FFH : ACPI_CSTATE_SYSTEMIO; 1037a36a7fecSSudeep Holla } else if (obj->type == ACPI_TYPE_INTEGER) { 1038a36a7fecSSudeep Holla lpi_state->entry_method = ACPI_CSTATE_INTEGER; 1039a36a7fecSSudeep Holla lpi_state->address = obj->integer.value; 1040a36a7fecSSudeep Holla } else { 1041a36a7fecSSudeep Holla continue; 1042a36a7fecSSudeep Holla } 1043a36a7fecSSudeep Holla 1044a36a7fecSSudeep Holla /* elements[7,8] skipped for now i.e. Residency/Usage counter*/ 1045a36a7fecSSudeep Holla 1046a36a7fecSSudeep Holla obj = pkg_elem + 9; 1047a36a7fecSSudeep Holla if (obj->type == ACPI_TYPE_STRING) 1048a36a7fecSSudeep Holla strlcpy(lpi_state->desc, obj->string.pointer, 1049a36a7fecSSudeep Holla ACPI_CX_DESC_LEN); 1050a36a7fecSSudeep Holla 1051a36a7fecSSudeep Holla lpi_state->index = state_idx; 1052a36a7fecSSudeep Holla if (obj_get_integer(pkg_elem + 0, &lpi_state->min_residency)) { 1053a36a7fecSSudeep Holla pr_debug("No min. residency found, assuming 10 us\n"); 1054a36a7fecSSudeep Holla lpi_state->min_residency = 10; 1055a36a7fecSSudeep Holla } 1056a36a7fecSSudeep Holla 1057a36a7fecSSudeep Holla if (obj_get_integer(pkg_elem + 1, &lpi_state->wake_latency)) { 1058a36a7fecSSudeep Holla pr_debug("No wakeup residency found, assuming 10 us\n"); 1059a36a7fecSSudeep Holla lpi_state->wake_latency = 10; 1060a36a7fecSSudeep Holla } 1061a36a7fecSSudeep Holla 1062a36a7fecSSudeep Holla if (obj_get_integer(pkg_elem + 2, &lpi_state->flags)) 1063a36a7fecSSudeep Holla lpi_state->flags = 0; 1064a36a7fecSSudeep Holla 1065a36a7fecSSudeep Holla if (obj_get_integer(pkg_elem + 3, &lpi_state->arch_flags)) 1066a36a7fecSSudeep Holla lpi_state->arch_flags = 0; 1067a36a7fecSSudeep Holla 1068a36a7fecSSudeep Holla if (obj_get_integer(pkg_elem + 4, &lpi_state->res_cnt_freq)) 1069a36a7fecSSudeep Holla lpi_state->res_cnt_freq = 1; 1070a36a7fecSSudeep Holla 1071a36a7fecSSudeep Holla if (obj_get_integer(pkg_elem + 5, &lpi_state->enable_parent_state)) 1072a36a7fecSSudeep Holla lpi_state->enable_parent_state = 0; 1073a36a7fecSSudeep Holla } 1074a36a7fecSSudeep Holla 1075a36a7fecSSudeep Holla acpi_handle_debug(handle, "Found %d power states\n", state_idx); 1076a36a7fecSSudeep Holla end: 1077a36a7fecSSudeep Holla kfree(buffer.pointer); 1078a36a7fecSSudeep Holla return ret; 1079a36a7fecSSudeep Holla } 1080a36a7fecSSudeep Holla 1081a36a7fecSSudeep Holla /* 1082a36a7fecSSudeep Holla * flat_state_cnt - the number of composite LPI states after the process of flattening 1083a36a7fecSSudeep Holla */ 1084a36a7fecSSudeep Holla static int flat_state_cnt; 1085a36a7fecSSudeep Holla 1086a36a7fecSSudeep Holla /** 1087a36a7fecSSudeep Holla * combine_lpi_states - combine local and parent LPI states to form a composite LPI state 1088a36a7fecSSudeep Holla * 1089a36a7fecSSudeep Holla * @local: local LPI state 1090a36a7fecSSudeep Holla * @parent: parent LPI state 1091a36a7fecSSudeep Holla * @result: composite LPI state 1092a36a7fecSSudeep Holla */ 1093a36a7fecSSudeep Holla static bool combine_lpi_states(struct acpi_lpi_state *local, 1094a36a7fecSSudeep Holla struct acpi_lpi_state *parent, 1095a36a7fecSSudeep Holla struct acpi_lpi_state *result) 1096a36a7fecSSudeep Holla { 1097a36a7fecSSudeep Holla if (parent->entry_method == ACPI_CSTATE_INTEGER) { 1098a36a7fecSSudeep Holla if (!parent->address) /* 0 means autopromotable */ 1099a36a7fecSSudeep Holla return false; 1100a36a7fecSSudeep Holla result->address = local->address + parent->address; 1101a36a7fecSSudeep Holla } else { 1102a36a7fecSSudeep Holla result->address = parent->address; 1103a36a7fecSSudeep Holla } 1104a36a7fecSSudeep Holla 1105a36a7fecSSudeep Holla result->min_residency = max(local->min_residency, parent->min_residency); 1106a36a7fecSSudeep Holla result->wake_latency = local->wake_latency + parent->wake_latency; 1107a36a7fecSSudeep Holla result->enable_parent_state = parent->enable_parent_state; 1108a36a7fecSSudeep Holla result->entry_method = local->entry_method; 1109a36a7fecSSudeep Holla 1110a36a7fecSSudeep Holla result->flags = parent->flags; 1111a36a7fecSSudeep Holla result->arch_flags = parent->arch_flags; 1112a36a7fecSSudeep Holla result->index = parent->index; 1113a36a7fecSSudeep Holla 1114a36a7fecSSudeep Holla strlcpy(result->desc, local->desc, ACPI_CX_DESC_LEN); 1115a36a7fecSSudeep Holla strlcat(result->desc, "+", ACPI_CX_DESC_LEN); 1116a36a7fecSSudeep Holla strlcat(result->desc, parent->desc, ACPI_CX_DESC_LEN); 1117a36a7fecSSudeep Holla return true; 1118a36a7fecSSudeep Holla } 1119a36a7fecSSudeep Holla 1120a36a7fecSSudeep Holla #define ACPI_LPI_STATE_FLAGS_ENABLED BIT(0) 1121a36a7fecSSudeep Holla 1122a36a7fecSSudeep Holla static void stash_composite_state(struct acpi_lpi_states_array *curr_level, 1123a36a7fecSSudeep Holla struct acpi_lpi_state *t) 1124a36a7fecSSudeep Holla { 1125a36a7fecSSudeep Holla curr_level->composite_states[curr_level->composite_states_size++] = t; 1126a36a7fecSSudeep Holla } 1127a36a7fecSSudeep Holla 1128a36a7fecSSudeep Holla static int flatten_lpi_states(struct acpi_processor *pr, 1129a36a7fecSSudeep Holla struct acpi_lpi_states_array *curr_level, 1130a36a7fecSSudeep Holla struct acpi_lpi_states_array *prev_level) 1131a36a7fecSSudeep Holla { 1132a36a7fecSSudeep Holla int i, j, state_count = curr_level->size; 1133a36a7fecSSudeep Holla struct acpi_lpi_state *p, *t = curr_level->entries; 1134a36a7fecSSudeep Holla 1135a36a7fecSSudeep Holla curr_level->composite_states_size = 0; 1136a36a7fecSSudeep Holla for (j = 0; j < state_count; j++, t++) { 1137a36a7fecSSudeep Holla struct acpi_lpi_state *flpi; 1138a36a7fecSSudeep Holla 1139a36a7fecSSudeep Holla if (!(t->flags & ACPI_LPI_STATE_FLAGS_ENABLED)) 1140a36a7fecSSudeep Holla continue; 1141a36a7fecSSudeep Holla 1142a36a7fecSSudeep Holla if (flat_state_cnt >= ACPI_PROCESSOR_MAX_POWER) { 1143a36a7fecSSudeep Holla pr_warn("Limiting number of LPI states to max (%d)\n", 1144a36a7fecSSudeep Holla ACPI_PROCESSOR_MAX_POWER); 1145a36a7fecSSudeep Holla pr_warn("Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n"); 1146a36a7fecSSudeep Holla break; 1147a36a7fecSSudeep Holla } 1148a36a7fecSSudeep Holla 1149a36a7fecSSudeep Holla flpi = &pr->power.lpi_states[flat_state_cnt]; 1150a36a7fecSSudeep Holla 1151a36a7fecSSudeep Holla if (!prev_level) { /* leaf/processor node */ 1152a36a7fecSSudeep Holla memcpy(flpi, t, sizeof(*t)); 1153a36a7fecSSudeep Holla stash_composite_state(curr_level, flpi); 1154a36a7fecSSudeep Holla flat_state_cnt++; 1155a36a7fecSSudeep Holla continue; 1156a36a7fecSSudeep Holla } 1157a36a7fecSSudeep Holla 1158a36a7fecSSudeep Holla for (i = 0; i < prev_level->composite_states_size; i++) { 1159a36a7fecSSudeep Holla p = prev_level->composite_states[i]; 1160a36a7fecSSudeep Holla if (t->index <= p->enable_parent_state && 1161a36a7fecSSudeep Holla combine_lpi_states(p, t, flpi)) { 1162a36a7fecSSudeep Holla stash_composite_state(curr_level, flpi); 1163a36a7fecSSudeep Holla flat_state_cnt++; 1164a36a7fecSSudeep Holla flpi++; 1165a36a7fecSSudeep Holla } 1166a36a7fecSSudeep Holla } 1167a36a7fecSSudeep Holla } 1168a36a7fecSSudeep Holla 1169a36a7fecSSudeep Holla kfree(curr_level->entries); 1170a36a7fecSSudeep Holla return 0; 1171a36a7fecSSudeep Holla } 1172a36a7fecSSudeep Holla 1173a36a7fecSSudeep Holla static int acpi_processor_get_lpi_info(struct acpi_processor *pr) 1174a36a7fecSSudeep Holla { 1175a36a7fecSSudeep Holla int ret, i; 1176a36a7fecSSudeep Holla acpi_status status; 1177a36a7fecSSudeep Holla acpi_handle handle = pr->handle, pr_ahandle; 1178a36a7fecSSudeep Holla struct acpi_device *d = NULL; 1179a36a7fecSSudeep Holla struct acpi_lpi_states_array info[2], *tmp, *prev, *curr; 1180a36a7fecSSudeep Holla 1181a36a7fecSSudeep Holla if (!osc_pc_lpi_support_confirmed) 1182a36a7fecSSudeep Holla return -EOPNOTSUPP; 1183a36a7fecSSudeep Holla 1184a36a7fecSSudeep Holla if (!acpi_has_method(handle, "_LPI")) 1185a36a7fecSSudeep Holla return -EINVAL; 1186a36a7fecSSudeep Holla 1187a36a7fecSSudeep Holla flat_state_cnt = 0; 1188a36a7fecSSudeep Holla prev = &info[0]; 1189a36a7fecSSudeep Holla curr = &info[1]; 1190a36a7fecSSudeep Holla handle = pr->handle; 1191a36a7fecSSudeep Holla ret = acpi_processor_evaluate_lpi(handle, prev); 1192a36a7fecSSudeep Holla if (ret) 1193a36a7fecSSudeep Holla return ret; 1194a36a7fecSSudeep Holla flatten_lpi_states(pr, prev, NULL); 1195a36a7fecSSudeep Holla 1196a36a7fecSSudeep Holla status = acpi_get_parent(handle, &pr_ahandle); 1197a36a7fecSSudeep Holla while (ACPI_SUCCESS(status)) { 1198a36a7fecSSudeep Holla acpi_bus_get_device(pr_ahandle, &d); 1199a36a7fecSSudeep Holla handle = pr_ahandle; 1200a36a7fecSSudeep Holla 1201a36a7fecSSudeep Holla if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID)) 1202a36a7fecSSudeep Holla break; 1203a36a7fecSSudeep Holla 1204a36a7fecSSudeep Holla /* can be optional ? */ 1205a36a7fecSSudeep Holla if (!acpi_has_method(handle, "_LPI")) 1206a36a7fecSSudeep Holla break; 1207a36a7fecSSudeep Holla 1208a36a7fecSSudeep Holla ret = acpi_processor_evaluate_lpi(handle, curr); 1209a36a7fecSSudeep Holla if (ret) 1210a36a7fecSSudeep Holla break; 1211a36a7fecSSudeep Holla 1212a36a7fecSSudeep Holla /* flatten all the LPI states in this level of hierarchy */ 1213a36a7fecSSudeep Holla flatten_lpi_states(pr, curr, prev); 1214a36a7fecSSudeep Holla 1215a36a7fecSSudeep Holla tmp = prev, prev = curr, curr = tmp; 1216a36a7fecSSudeep Holla 1217a36a7fecSSudeep Holla status = acpi_get_parent(handle, &pr_ahandle); 1218a36a7fecSSudeep Holla } 1219a36a7fecSSudeep Holla 1220a36a7fecSSudeep Holla pr->power.count = flat_state_cnt; 1221a36a7fecSSudeep Holla /* reset the index after flattening */ 1222a36a7fecSSudeep Holla for (i = 0; i < pr->power.count; i++) 1223a36a7fecSSudeep Holla pr->power.lpi_states[i].index = i; 1224a36a7fecSSudeep Holla 1225a36a7fecSSudeep Holla /* Tell driver that _LPI is supported. */ 1226a36a7fecSSudeep Holla pr->flags.has_lpi = 1; 1227a36a7fecSSudeep Holla pr->flags.power = 1; 1228a36a7fecSSudeep Holla 1229a36a7fecSSudeep Holla return 0; 1230a36a7fecSSudeep Holla } 1231a36a7fecSSudeep Holla 1232a36a7fecSSudeep Holla int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu) 1233a36a7fecSSudeep Holla { 1234a36a7fecSSudeep Holla return -ENODEV; 1235a36a7fecSSudeep Holla } 1236a36a7fecSSudeep Holla 1237a36a7fecSSudeep Holla int __weak acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi) 1238a36a7fecSSudeep Holla { 1239a36a7fecSSudeep Holla return -ENODEV; 1240a36a7fecSSudeep Holla } 1241a36a7fecSSudeep Holla 1242a36a7fecSSudeep Holla /** 1243a36a7fecSSudeep Holla * acpi_idle_lpi_enter - enters an ACPI any LPI state 1244a36a7fecSSudeep Holla * @dev: the target CPU 1245a36a7fecSSudeep Holla * @drv: cpuidle driver containing cpuidle state info 1246a36a7fecSSudeep Holla * @index: index of target state 1247a36a7fecSSudeep Holla * 1248a36a7fecSSudeep Holla * Return: 0 for success or negative value for error 1249a36a7fecSSudeep Holla */ 1250a36a7fecSSudeep Holla static int acpi_idle_lpi_enter(struct cpuidle_device *dev, 1251a36a7fecSSudeep Holla struct cpuidle_driver *drv, int index) 1252a36a7fecSSudeep Holla { 1253a36a7fecSSudeep Holla struct acpi_processor *pr; 1254a36a7fecSSudeep Holla struct acpi_lpi_state *lpi; 1255a36a7fecSSudeep Holla 1256a36a7fecSSudeep Holla pr = __this_cpu_read(processors); 1257a36a7fecSSudeep Holla 1258a36a7fecSSudeep Holla if (unlikely(!pr)) 1259a36a7fecSSudeep Holla return -EINVAL; 1260a36a7fecSSudeep Holla 1261a36a7fecSSudeep Holla lpi = &pr->power.lpi_states[index]; 1262a36a7fecSSudeep Holla if (lpi->entry_method == ACPI_CSTATE_FFH) 1263a36a7fecSSudeep Holla return acpi_processor_ffh_lpi_enter(lpi); 1264a36a7fecSSudeep Holla 1265a36a7fecSSudeep Holla return -EINVAL; 1266a36a7fecSSudeep Holla } 1267a36a7fecSSudeep Holla 1268a36a7fecSSudeep Holla static int acpi_processor_setup_lpi_states(struct acpi_processor *pr) 1269a36a7fecSSudeep Holla { 1270a36a7fecSSudeep Holla int i; 1271a36a7fecSSudeep Holla struct acpi_lpi_state *lpi; 1272a36a7fecSSudeep Holla struct cpuidle_state *state; 1273a36a7fecSSudeep Holla struct cpuidle_driver *drv = &acpi_idle_driver; 1274a36a7fecSSudeep Holla 1275a36a7fecSSudeep Holla if (!pr->flags.has_lpi) 1276a36a7fecSSudeep Holla return -EOPNOTSUPP; 1277a36a7fecSSudeep Holla 1278a36a7fecSSudeep Holla for (i = 0; i < pr->power.count && i < CPUIDLE_STATE_MAX; i++) { 1279a36a7fecSSudeep Holla lpi = &pr->power.lpi_states[i]; 1280a36a7fecSSudeep Holla 1281a36a7fecSSudeep Holla state = &drv->states[i]; 1282a36a7fecSSudeep Holla snprintf(state->name, CPUIDLE_NAME_LEN, "LPI-%d", i); 1283a36a7fecSSudeep Holla strlcpy(state->desc, lpi->desc, CPUIDLE_DESC_LEN); 1284a36a7fecSSudeep Holla state->exit_latency = lpi->wake_latency; 1285a36a7fecSSudeep Holla state->target_residency = lpi->min_residency; 1286a36a7fecSSudeep Holla if (lpi->arch_flags) 1287a36a7fecSSudeep Holla state->flags |= CPUIDLE_FLAG_TIMER_STOP; 1288a36a7fecSSudeep Holla state->enter = acpi_idle_lpi_enter; 1289a36a7fecSSudeep Holla drv->safe_state_index = i; 1290a36a7fecSSudeep Holla } 1291a36a7fecSSudeep Holla 1292a36a7fecSSudeep Holla drv->state_count = i; 1293a36a7fecSSudeep Holla 1294a36a7fecSSudeep Holla return 0; 1295a36a7fecSSudeep Holla } 1296a36a7fecSSudeep Holla 1297a36a7fecSSudeep Holla /** 1298a36a7fecSSudeep Holla * acpi_processor_setup_cpuidle_states- prepares and configures cpuidle 1299a36a7fecSSudeep Holla * global state data i.e. idle routines 1300a36a7fecSSudeep Holla * 1301a36a7fecSSudeep Holla * @pr: the ACPI processor 1302a36a7fecSSudeep Holla */ 1303a36a7fecSSudeep Holla static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) 1304a36a7fecSSudeep Holla { 1305a36a7fecSSudeep Holla int i; 1306a36a7fecSSudeep Holla struct cpuidle_driver *drv = &acpi_idle_driver; 1307a36a7fecSSudeep Holla 1308a36a7fecSSudeep Holla if (!pr->flags.power_setup_done || !pr->flags.power) 1309a36a7fecSSudeep Holla return -EINVAL; 1310a36a7fecSSudeep Holla 1311a36a7fecSSudeep Holla drv->safe_state_index = -1; 1312dc2251bfSRafael J. Wysocki for (i = ACPI_IDLE_STATE_START; i < CPUIDLE_STATE_MAX; i++) { 1313a36a7fecSSudeep Holla drv->states[i].name[0] = '\0'; 1314a36a7fecSSudeep Holla drv->states[i].desc[0] = '\0'; 1315a36a7fecSSudeep Holla } 1316a36a7fecSSudeep Holla 1317a36a7fecSSudeep Holla if (pr->flags.has_lpi) 1318a36a7fecSSudeep Holla return acpi_processor_setup_lpi_states(pr); 1319a36a7fecSSudeep Holla 1320a36a7fecSSudeep Holla return acpi_processor_setup_cstates(pr); 1321a36a7fecSSudeep Holla } 1322a36a7fecSSudeep Holla 1323a36a7fecSSudeep Holla /** 1324a36a7fecSSudeep Holla * acpi_processor_setup_cpuidle_dev - prepares and configures CPUIDLE 1325a36a7fecSSudeep Holla * device i.e. per-cpu data 1326a36a7fecSSudeep Holla * 1327a36a7fecSSudeep Holla * @pr: the ACPI processor 1328a36a7fecSSudeep Holla * @dev : the cpuidle device 1329a36a7fecSSudeep Holla */ 1330a36a7fecSSudeep Holla static int acpi_processor_setup_cpuidle_dev(struct acpi_processor *pr, 1331a36a7fecSSudeep Holla struct cpuidle_device *dev) 1332a36a7fecSSudeep Holla { 1333a36a7fecSSudeep Holla if (!pr->flags.power_setup_done || !pr->flags.power || !dev) 1334a36a7fecSSudeep Holla return -EINVAL; 1335a36a7fecSSudeep Holla 1336a36a7fecSSudeep Holla dev->cpu = pr->id; 1337a36a7fecSSudeep Holla if (pr->flags.has_lpi) 1338a36a7fecSSudeep Holla return acpi_processor_ffh_lpi_probe(pr->id); 1339a36a7fecSSudeep Holla 1340a36a7fecSSudeep Holla return acpi_processor_setup_cpuidle_cx(pr, dev); 1341a36a7fecSSudeep Holla } 1342a36a7fecSSudeep Holla 1343a36a7fecSSudeep Holla static int acpi_processor_get_power_info(struct acpi_processor *pr) 1344a36a7fecSSudeep Holla { 1345a36a7fecSSudeep Holla int ret; 1346a36a7fecSSudeep Holla 1347a36a7fecSSudeep Holla ret = acpi_processor_get_lpi_info(pr); 1348a36a7fecSSudeep Holla if (ret) 1349a36a7fecSSudeep Holla ret = acpi_processor_get_cstate_info(pr); 1350a36a7fecSSudeep Holla 1351a36a7fecSSudeep Holla return ret; 1352a36a7fecSSudeep Holla } 1353a36a7fecSSudeep Holla 135446bcfad7SDeepthi Dharwar int acpi_processor_hotplug(struct acpi_processor *pr) 13554f86d3a8SLen Brown { 1356dcb84f33SVenkatesh Pallipadi int ret = 0; 1357e8b1b59dSWei Yongjun struct cpuidle_device *dev; 13584f86d3a8SLen Brown 1359d1896049SThomas Renninger if (disabled_by_idle_boot_param()) 136036a91358SVenkatesh Pallipadi return 0; 136136a91358SVenkatesh Pallipadi 13624f86d3a8SLen Brown if (!pr->flags.power_setup_done) 13634f86d3a8SLen Brown return -ENODEV; 13644f86d3a8SLen Brown 1365e8b1b59dSWei Yongjun dev = per_cpu(acpi_cpuidle_device, pr->id); 13664f86d3a8SLen Brown cpuidle_pause_and_lock(); 13673d339dcbSDaniel Lezcano cpuidle_disable_device(dev); 1368a36a7fecSSudeep Holla ret = acpi_processor_get_power_info(pr); 1369a36a7fecSSudeep Holla if (!ret && pr->flags.power) { 1370a36a7fecSSudeep Holla acpi_processor_setup_cpuidle_dev(pr, dev); 13713d339dcbSDaniel Lezcano ret = cpuidle_enable_device(dev); 1372dcb84f33SVenkatesh Pallipadi } 13734f86d3a8SLen Brown cpuidle_resume_and_unlock(); 13744f86d3a8SLen Brown 13754f86d3a8SLen Brown return ret; 13764f86d3a8SLen Brown } 13774f86d3a8SLen Brown 1378a36a7fecSSudeep Holla int acpi_processor_power_state_has_changed(struct acpi_processor *pr) 137946bcfad7SDeepthi Dharwar { 138046bcfad7SDeepthi Dharwar int cpu; 138146bcfad7SDeepthi Dharwar struct acpi_processor *_pr; 13823d339dcbSDaniel Lezcano struct cpuidle_device *dev; 138346bcfad7SDeepthi Dharwar 138446bcfad7SDeepthi Dharwar if (disabled_by_idle_boot_param()) 138546bcfad7SDeepthi Dharwar return 0; 138646bcfad7SDeepthi Dharwar 138746bcfad7SDeepthi Dharwar if (!pr->flags.power_setup_done) 138846bcfad7SDeepthi Dharwar return -ENODEV; 138946bcfad7SDeepthi Dharwar 139046bcfad7SDeepthi Dharwar /* 139146bcfad7SDeepthi Dharwar * FIXME: Design the ACPI notification to make it once per 139246bcfad7SDeepthi Dharwar * system instead of once per-cpu. This condition is a hack 139346bcfad7SDeepthi Dharwar * to make the code that updates C-States be called once. 139446bcfad7SDeepthi Dharwar */ 139546bcfad7SDeepthi Dharwar 13969505626dSPaul E. McKenney if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) { 139746bcfad7SDeepthi Dharwar 139846bcfad7SDeepthi Dharwar /* Protect against cpu-hotplug */ 139946bcfad7SDeepthi Dharwar get_online_cpus(); 14006726655dSJiri Kosina cpuidle_pause_and_lock(); 140146bcfad7SDeepthi Dharwar 140246bcfad7SDeepthi Dharwar /* Disable all cpuidle devices */ 140346bcfad7SDeepthi Dharwar for_each_online_cpu(cpu) { 140446bcfad7SDeepthi Dharwar _pr = per_cpu(processors, cpu); 140546bcfad7SDeepthi Dharwar if (!_pr || !_pr->flags.power_setup_done) 140646bcfad7SDeepthi Dharwar continue; 14073d339dcbSDaniel Lezcano dev = per_cpu(acpi_cpuidle_device, cpu); 14083d339dcbSDaniel Lezcano cpuidle_disable_device(dev); 140946bcfad7SDeepthi Dharwar } 141046bcfad7SDeepthi Dharwar 141146bcfad7SDeepthi Dharwar /* Populate Updated C-state information */ 1412f427e5f1SThomas Schlichter acpi_processor_get_power_info(pr); 141346bcfad7SDeepthi Dharwar acpi_processor_setup_cpuidle_states(pr); 141446bcfad7SDeepthi Dharwar 141546bcfad7SDeepthi Dharwar /* Enable all cpuidle devices */ 141646bcfad7SDeepthi Dharwar for_each_online_cpu(cpu) { 141746bcfad7SDeepthi Dharwar _pr = per_cpu(processors, cpu); 141846bcfad7SDeepthi Dharwar if (!_pr || !_pr->flags.power_setup_done) 141946bcfad7SDeepthi Dharwar continue; 142046bcfad7SDeepthi Dharwar acpi_processor_get_power_info(_pr); 142146bcfad7SDeepthi Dharwar if (_pr->flags.power) { 14223d339dcbSDaniel Lezcano dev = per_cpu(acpi_cpuidle_device, cpu); 1423a36a7fecSSudeep Holla acpi_processor_setup_cpuidle_dev(_pr, dev); 14243d339dcbSDaniel Lezcano cpuidle_enable_device(dev); 142546bcfad7SDeepthi Dharwar } 142646bcfad7SDeepthi Dharwar } 142746bcfad7SDeepthi Dharwar cpuidle_resume_and_unlock(); 14286726655dSJiri Kosina put_online_cpus(); 142946bcfad7SDeepthi Dharwar } 143046bcfad7SDeepthi Dharwar 143146bcfad7SDeepthi Dharwar return 0; 143246bcfad7SDeepthi Dharwar } 143346bcfad7SDeepthi Dharwar 143446bcfad7SDeepthi Dharwar static int acpi_processor_registered; 143546bcfad7SDeepthi Dharwar 1436fe7bf106SPaul Gortmaker int acpi_processor_power_init(struct acpi_processor *pr) 14371da177e4SLinus Torvalds { 143846bcfad7SDeepthi Dharwar int retval; 14393d339dcbSDaniel Lezcano struct cpuidle_device *dev; 14401da177e4SLinus Torvalds 1441d1896049SThomas Renninger if (disabled_by_idle_boot_param()) 144236a91358SVenkatesh Pallipadi return 0; 14431da177e4SLinus Torvalds 144435ae7133SSudeep Holla acpi_processor_cstate_first_run_checks(); 14451da177e4SLinus Torvalds 144635ae7133SSudeep Holla if (!acpi_processor_get_power_info(pr)) 14474f86d3a8SLen Brown pr->flags.power_setup_done = 1; 14481da177e4SLinus Torvalds 14491da177e4SLinus Torvalds /* 14501da177e4SLinus Torvalds * Install the idle handler if processor power management is supported. 14511da177e4SLinus Torvalds * Note that we use previously set idle handler will be used on 14521da177e4SLinus Torvalds * platforms that only support C1. 14531da177e4SLinus Torvalds */ 145436a91358SVenkatesh Pallipadi if (pr->flags.power) { 145546bcfad7SDeepthi Dharwar /* Register acpi_idle_driver if not already registered */ 145646bcfad7SDeepthi Dharwar if (!acpi_processor_registered) { 145746bcfad7SDeepthi Dharwar acpi_processor_setup_cpuidle_states(pr); 145846bcfad7SDeepthi Dharwar retval = cpuidle_register_driver(&acpi_idle_driver); 145946bcfad7SDeepthi Dharwar if (retval) 146046bcfad7SDeepthi Dharwar return retval; 1461b6ec26fbSSudeep Holla pr_debug("%s registered with cpuidle\n", 146246bcfad7SDeepthi Dharwar acpi_idle_driver.name); 146346bcfad7SDeepthi Dharwar } 14643d339dcbSDaniel Lezcano 14653d339dcbSDaniel Lezcano dev = kzalloc(sizeof(*dev), GFP_KERNEL); 14663d339dcbSDaniel Lezcano if (!dev) 14673d339dcbSDaniel Lezcano return -ENOMEM; 14683d339dcbSDaniel Lezcano per_cpu(acpi_cpuidle_device, pr->id) = dev; 14693d339dcbSDaniel Lezcano 1470a36a7fecSSudeep Holla acpi_processor_setup_cpuidle_dev(pr, dev); 14713d339dcbSDaniel Lezcano 147246bcfad7SDeepthi Dharwar /* Register per-cpu cpuidle_device. Cpuidle driver 147346bcfad7SDeepthi Dharwar * must already be registered before registering device 147446bcfad7SDeepthi Dharwar */ 14753d339dcbSDaniel Lezcano retval = cpuidle_register_device(dev); 147646bcfad7SDeepthi Dharwar if (retval) { 147746bcfad7SDeepthi Dharwar if (acpi_processor_registered == 0) 147846bcfad7SDeepthi Dharwar cpuidle_unregister_driver(&acpi_idle_driver); 147946bcfad7SDeepthi Dharwar return retval; 148046bcfad7SDeepthi Dharwar } 148146bcfad7SDeepthi Dharwar acpi_processor_registered++; 14821da177e4SLinus Torvalds } 1483d550d98dSPatrick Mochel return 0; 14841da177e4SLinus Torvalds } 14851da177e4SLinus Torvalds 148638a991b6SDaniel Lezcano int acpi_processor_power_exit(struct acpi_processor *pr) 14871da177e4SLinus Torvalds { 14883d339dcbSDaniel Lezcano struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); 14893d339dcbSDaniel Lezcano 1490d1896049SThomas Renninger if (disabled_by_idle_boot_param()) 149136a91358SVenkatesh Pallipadi return 0; 149236a91358SVenkatesh Pallipadi 149346bcfad7SDeepthi Dharwar if (pr->flags.power) { 14943d339dcbSDaniel Lezcano cpuidle_unregister_device(dev); 149546bcfad7SDeepthi Dharwar acpi_processor_registered--; 149646bcfad7SDeepthi Dharwar if (acpi_processor_registered == 0) 149746bcfad7SDeepthi Dharwar cpuidle_unregister_driver(&acpi_idle_driver); 149846bcfad7SDeepthi Dharwar } 14991da177e4SLinus Torvalds 150046bcfad7SDeepthi Dharwar pr->flags.power_setup_done = 0; 1501d550d98dSPatrick Mochel return 0; 15021da177e4SLinus Torvalds } 1503