11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * processor_idle - idle state submodule to the ACPI processor driver 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 51da177e4SLinus Torvalds * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 61da177e4SLinus Torvalds * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> 71da177e4SLinus Torvalds * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 81da177e4SLinus Torvalds * - Added processor hotplug support 902df8b93SVenkatesh Pallipadi * Copyright (C) 2005 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> 1002df8b93SVenkatesh Pallipadi * - Added support for C3 on SMP 111da177e4SLinus Torvalds * 121da177e4SLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 151da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 161da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or (at 171da177e4SLinus Torvalds * your option) any later version. 181da177e4SLinus Torvalds * 191da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, but 201da177e4SLinus Torvalds * WITHOUT ANY WARRANTY; without even the implied warranty of 211da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 221da177e4SLinus Torvalds * General Public License for more details. 231da177e4SLinus Torvalds * 241da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License along 251da177e4SLinus Torvalds * with this program; if not, write to the Free Software Foundation, Inc., 261da177e4SLinus Torvalds * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 271da177e4SLinus Torvalds * 281da177e4SLinus Torvalds * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 291da177e4SLinus Torvalds */ 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds #include <linux/kernel.h> 321da177e4SLinus Torvalds #include <linux/module.h> 331da177e4SLinus Torvalds #include <linux/init.h> 341da177e4SLinus Torvalds #include <linux/cpufreq.h> 351da177e4SLinus Torvalds #include <linux/proc_fs.h> 361da177e4SLinus Torvalds #include <linux/seq_file.h> 371da177e4SLinus Torvalds #include <linux/acpi.h> 381da177e4SLinus Torvalds #include <linux/dmi.h> 391da177e4SLinus Torvalds #include <linux/moduleparam.h> 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds #include <asm/io.h> 421da177e4SLinus Torvalds #include <asm/uaccess.h> 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds #include <acpi/acpi_bus.h> 451da177e4SLinus Torvalds #include <acpi/processor.h> 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds #define ACPI_PROCESSOR_COMPONENT 0x01000000 481da177e4SLinus Torvalds #define ACPI_PROCESSOR_CLASS "processor" 491da177e4SLinus Torvalds #define ACPI_PROCESSOR_DRIVER_NAME "ACPI Processor Driver" 501da177e4SLinus Torvalds #define _COMPONENT ACPI_PROCESSOR_COMPONENT 511da177e4SLinus Torvalds ACPI_MODULE_NAME ("acpi_processor") 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds #define ACPI_PROCESSOR_FILE_POWER "power" 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #define US_TO_PM_TIMER_TICKS(t) ((t * (PM_TIMER_FREQUENCY/1000)) / 1000) 561da177e4SLinus Torvalds #define C2_OVERHEAD 4 /* 1us (3.579 ticks per us) */ 571da177e4SLinus Torvalds #define C3_OVERHEAD 4 /* 1us (3.579 ticks per us) */ 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds static void (*pm_idle_save)(void); 601da177e4SLinus Torvalds module_param(max_cstate, uint, 0644); 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds static unsigned int nocst = 0; 631da177e4SLinus Torvalds module_param(nocst, uint, 0000); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds /* 661da177e4SLinus Torvalds * bm_history -- bit-mask with a bit per jiffy of bus-master activity 671da177e4SLinus Torvalds * 1000 HZ: 0xFFFFFFFF: 32 jiffies = 32ms 681da177e4SLinus Torvalds * 800 HZ: 0xFFFFFFFF: 32 jiffies = 40ms 691da177e4SLinus Torvalds * 100 HZ: 0x0000000F: 4 jiffies = 40ms 701da177e4SLinus Torvalds * reduce history for more aggressive entry into C3 711da177e4SLinus Torvalds */ 721da177e4SLinus Torvalds static unsigned int bm_history = (HZ >= 800 ? 0xFFFFFFFF : ((1U << (HZ / 25)) - 1)); 731da177e4SLinus Torvalds module_param(bm_history, uint, 0644); 741da177e4SLinus Torvalds /* -------------------------------------------------------------------------- 751da177e4SLinus Torvalds Power Management 761da177e4SLinus Torvalds -------------------------------------------------------------------------- */ 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds /* 791da177e4SLinus Torvalds * IBM ThinkPad R40e crashes mysteriously when going into C2 or C3. 801da177e4SLinus Torvalds * For now disable this. Probably a bug somewhere else. 811da177e4SLinus Torvalds * 821da177e4SLinus Torvalds * To skip this limit, boot/load with a large max_cstate limit. 831da177e4SLinus Torvalds */ 841da177e4SLinus Torvalds static int no_c2c3(struct dmi_system_id *id) 851da177e4SLinus Torvalds { 861da177e4SLinus Torvalds if (max_cstate > ACPI_PROCESSOR_MAX_POWER) 871da177e4SLinus Torvalds return 0; 881da177e4SLinus Torvalds 891da177e4SLinus Torvalds printk(KERN_NOTICE PREFIX "%s detected - C2,C3 disabled." 901da177e4SLinus Torvalds " Override with \"processor.max_cstate=%d\"\n", id->ident, 911da177e4SLinus Torvalds ACPI_PROCESSOR_MAX_POWER + 1); 921da177e4SLinus Torvalds 931da177e4SLinus Torvalds max_cstate = 1; 941da177e4SLinus Torvalds 951da177e4SLinus Torvalds return 0; 961da177e4SLinus Torvalds } 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds static struct dmi_system_id __initdata processor_power_dmi_table[] = { 1021da177e4SLinus Torvalds { no_c2c3, "IBM ThinkPad R40e", { 1031da177e4SLinus Torvalds DMI_MATCH(DMI_BIOS_VENDOR,"IBM"), 1041da177e4SLinus Torvalds DMI_MATCH(DMI_BIOS_VERSION,"1SET60WW") }}, 1051da177e4SLinus Torvalds { no_c2c3, "Medion 41700", { 1061da177e4SLinus Torvalds DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), 1071da177e4SLinus Torvalds DMI_MATCH(DMI_BIOS_VERSION,"R01-A1J") }}, 1081da177e4SLinus Torvalds {}, 1091da177e4SLinus Torvalds }; 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds 1121da177e4SLinus Torvalds static inline u32 1131da177e4SLinus Torvalds ticks_elapsed ( 1141da177e4SLinus Torvalds u32 t1, 1151da177e4SLinus Torvalds u32 t2) 1161da177e4SLinus Torvalds { 1171da177e4SLinus Torvalds if (t2 >= t1) 1181da177e4SLinus Torvalds return (t2 - t1); 1191da177e4SLinus Torvalds else if (!acpi_fadt.tmr_val_ext) 1201da177e4SLinus Torvalds return (((0x00FFFFFF - t1) + t2) & 0x00FFFFFF); 1211da177e4SLinus Torvalds else 1221da177e4SLinus Torvalds return ((0xFFFFFFFF - t1) + t2); 1231da177e4SLinus Torvalds } 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds static void 1271da177e4SLinus Torvalds acpi_processor_power_activate ( 1281da177e4SLinus Torvalds struct acpi_processor *pr, 1291da177e4SLinus Torvalds struct acpi_processor_cx *new) 1301da177e4SLinus Torvalds { 1311da177e4SLinus Torvalds struct acpi_processor_cx *old; 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds if (!pr || !new) 1341da177e4SLinus Torvalds return; 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds old = pr->power.state; 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds if (old) 1391da177e4SLinus Torvalds old->promotion.count = 0; 1401da177e4SLinus Torvalds new->demotion.count = 0; 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds /* Cleanup from old state. */ 1431da177e4SLinus Torvalds if (old) { 1441da177e4SLinus Torvalds switch (old->type) { 1451da177e4SLinus Torvalds case ACPI_STATE_C3: 1461da177e4SLinus Torvalds /* Disable bus master reload */ 14702df8b93SVenkatesh Pallipadi if (new->type != ACPI_STATE_C3 && pr->flags.bm_check) 1481da177e4SLinus Torvalds acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0, ACPI_MTX_DO_NOT_LOCK); 1491da177e4SLinus Torvalds break; 1501da177e4SLinus Torvalds } 1511da177e4SLinus Torvalds } 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds /* Prepare to use new state. */ 1541da177e4SLinus Torvalds switch (new->type) { 1551da177e4SLinus Torvalds case ACPI_STATE_C3: 1561da177e4SLinus Torvalds /* Enable bus master reload */ 15702df8b93SVenkatesh Pallipadi if (old->type != ACPI_STATE_C3 && pr->flags.bm_check) 1581da177e4SLinus Torvalds acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 1, ACPI_MTX_DO_NOT_LOCK); 1591da177e4SLinus Torvalds break; 1601da177e4SLinus Torvalds } 1611da177e4SLinus Torvalds 1621da177e4SLinus Torvalds pr->power.state = new; 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds return; 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds 16802df8b93SVenkatesh Pallipadi static atomic_t c3_cpu_count; 16902df8b93SVenkatesh Pallipadi 17002df8b93SVenkatesh Pallipadi 1711da177e4SLinus Torvalds static void acpi_processor_idle (void) 1721da177e4SLinus Torvalds { 1731da177e4SLinus Torvalds struct acpi_processor *pr = NULL; 1741da177e4SLinus Torvalds struct acpi_processor_cx *cx = NULL; 1751da177e4SLinus Torvalds struct acpi_processor_cx *next_state = NULL; 1761da177e4SLinus Torvalds int sleep_ticks = 0; 1771da177e4SLinus Torvalds u32 t1, t2 = 0; 1781da177e4SLinus Torvalds 1791da177e4SLinus Torvalds pr = processors[_smp_processor_id()]; 1801da177e4SLinus Torvalds if (!pr) 1811da177e4SLinus Torvalds return; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds /* 1841da177e4SLinus Torvalds * Interrupts must be disabled during bus mastering calculations and 1851da177e4SLinus Torvalds * for C2/C3 transitions. 1861da177e4SLinus Torvalds */ 1871da177e4SLinus Torvalds local_irq_disable(); 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds /* 1901da177e4SLinus Torvalds * Check whether we truly need to go idle, or should 1911da177e4SLinus Torvalds * reschedule: 1921da177e4SLinus Torvalds */ 1931da177e4SLinus Torvalds if (unlikely(need_resched())) { 1941da177e4SLinus Torvalds local_irq_enable(); 1951da177e4SLinus Torvalds return; 1961da177e4SLinus Torvalds } 1971da177e4SLinus Torvalds 1981da177e4SLinus Torvalds cx = pr->power.state; 1991da177e4SLinus Torvalds if (!cx) 2001da177e4SLinus Torvalds goto easy_out; 2011da177e4SLinus Torvalds 2021da177e4SLinus Torvalds /* 2031da177e4SLinus Torvalds * Check BM Activity 2041da177e4SLinus Torvalds * ----------------- 2051da177e4SLinus Torvalds * Check for bus mastering activity (if required), record, and check 2061da177e4SLinus Torvalds * for demotion. 2071da177e4SLinus Torvalds */ 2081da177e4SLinus Torvalds if (pr->flags.bm_check) { 2091da177e4SLinus Torvalds u32 bm_status = 0; 2101da177e4SLinus Torvalds unsigned long diff = jiffies - pr->power.bm_check_timestamp; 2111da177e4SLinus Torvalds 2121da177e4SLinus Torvalds if (diff > 32) 2131da177e4SLinus Torvalds diff = 32; 2141da177e4SLinus Torvalds 2151da177e4SLinus Torvalds while (diff) { 2161da177e4SLinus Torvalds /* if we didn't get called, assume there was busmaster activity */ 2171da177e4SLinus Torvalds diff--; 2181da177e4SLinus Torvalds if (diff) 2191da177e4SLinus Torvalds pr->power.bm_activity |= 0x1; 2201da177e4SLinus Torvalds pr->power.bm_activity <<= 1; 2211da177e4SLinus Torvalds } 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds acpi_get_register(ACPI_BITREG_BUS_MASTER_STATUS, 2241da177e4SLinus Torvalds &bm_status, ACPI_MTX_DO_NOT_LOCK); 2251da177e4SLinus Torvalds if (bm_status) { 2261da177e4SLinus Torvalds pr->power.bm_activity++; 2271da177e4SLinus Torvalds acpi_set_register(ACPI_BITREG_BUS_MASTER_STATUS, 2281da177e4SLinus Torvalds 1, ACPI_MTX_DO_NOT_LOCK); 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds /* 2311da177e4SLinus Torvalds * PIIX4 Erratum #18: Note that BM_STS doesn't always reflect 2321da177e4SLinus Torvalds * the true state of bus mastering activity; forcing us to 2331da177e4SLinus Torvalds * manually check the BMIDEA bit of each IDE channel. 2341da177e4SLinus Torvalds */ 2351da177e4SLinus Torvalds else if (errata.piix4.bmisx) { 2361da177e4SLinus Torvalds if ((inb_p(errata.piix4.bmisx + 0x02) & 0x01) 2371da177e4SLinus Torvalds || (inb_p(errata.piix4.bmisx + 0x0A) & 0x01)) 2381da177e4SLinus Torvalds pr->power.bm_activity++; 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds 2411da177e4SLinus Torvalds pr->power.bm_check_timestamp = jiffies; 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds /* 2441da177e4SLinus Torvalds * Apply bus mastering demotion policy. Automatically demote 2451da177e4SLinus Torvalds * to avoid a faulty transition. Note that the processor 2461da177e4SLinus Torvalds * won't enter a low-power state during this call (to this 2471da177e4SLinus Torvalds * funciton) but should upon the next. 2481da177e4SLinus Torvalds * 2491da177e4SLinus Torvalds * TBD: A better policy might be to fallback to the demotion 2501da177e4SLinus Torvalds * state (use it for this quantum only) istead of 2511da177e4SLinus Torvalds * demoting -- and rely on duration as our sole demotion 2521da177e4SLinus Torvalds * qualification. This may, however, introduce DMA 2531da177e4SLinus Torvalds * issues (e.g. floppy DMA transfer overrun/underrun). 2541da177e4SLinus Torvalds */ 2551da177e4SLinus Torvalds if (pr->power.bm_activity & cx->demotion.threshold.bm) { 2561da177e4SLinus Torvalds local_irq_enable(); 2571da177e4SLinus Torvalds next_state = cx->demotion.state; 2581da177e4SLinus Torvalds goto end; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds } 2611da177e4SLinus Torvalds 2621da177e4SLinus Torvalds cx->usage++; 2631da177e4SLinus Torvalds 2641da177e4SLinus Torvalds /* 2651da177e4SLinus Torvalds * Sleep: 2661da177e4SLinus Torvalds * ------ 2671da177e4SLinus Torvalds * Invoke the current Cx state to put the processor to sleep. 2681da177e4SLinus Torvalds */ 2691da177e4SLinus Torvalds switch (cx->type) { 2701da177e4SLinus Torvalds 2711da177e4SLinus Torvalds case ACPI_STATE_C1: 2721da177e4SLinus Torvalds /* 2731da177e4SLinus Torvalds * Invoke C1. 2741da177e4SLinus Torvalds * Use the appropriate idle routine, the one that would 2751da177e4SLinus Torvalds * be used without acpi C-states. 2761da177e4SLinus Torvalds */ 2771da177e4SLinus Torvalds if (pm_idle_save) 2781da177e4SLinus Torvalds pm_idle_save(); 2791da177e4SLinus Torvalds else 2801da177e4SLinus Torvalds safe_halt(); 2811da177e4SLinus Torvalds /* 2821da177e4SLinus Torvalds * TBD: Can't get time duration while in C1, as resumes 2831da177e4SLinus Torvalds * go to an ISR rather than here. Need to instrument 2841da177e4SLinus Torvalds * base interrupt handler. 2851da177e4SLinus Torvalds */ 2861da177e4SLinus Torvalds sleep_ticks = 0xFFFFFFFF; 2871da177e4SLinus Torvalds break; 2881da177e4SLinus Torvalds 2891da177e4SLinus Torvalds case ACPI_STATE_C2: 2901da177e4SLinus Torvalds /* Get start time (ticks) */ 2911da177e4SLinus Torvalds t1 = inl(acpi_fadt.xpm_tmr_blk.address); 2921da177e4SLinus Torvalds /* Invoke C2 */ 2931da177e4SLinus Torvalds inb(cx->address); 2941da177e4SLinus Torvalds /* Dummy op - must do something useless after P_LVL2 read */ 2951da177e4SLinus Torvalds t2 = inl(acpi_fadt.xpm_tmr_blk.address); 2961da177e4SLinus Torvalds /* Get end time (ticks) */ 2971da177e4SLinus Torvalds t2 = inl(acpi_fadt.xpm_tmr_blk.address); 2981da177e4SLinus Torvalds /* Re-enable interrupts */ 2991da177e4SLinus Torvalds local_irq_enable(); 3001da177e4SLinus Torvalds /* Compute time (ticks) that we were actually asleep */ 3011da177e4SLinus Torvalds sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; 3021da177e4SLinus Torvalds break; 3031da177e4SLinus Torvalds 3041da177e4SLinus Torvalds case ACPI_STATE_C3: 30502df8b93SVenkatesh Pallipadi 30602df8b93SVenkatesh Pallipadi if (pr->flags.bm_check) { 30702df8b93SVenkatesh Pallipadi if (atomic_inc_return(&c3_cpu_count) == 30802df8b93SVenkatesh Pallipadi num_online_cpus()) { 30902df8b93SVenkatesh Pallipadi /* 31002df8b93SVenkatesh Pallipadi * All CPUs are trying to go to C3 31102df8b93SVenkatesh Pallipadi * Disable bus master arbitration 31202df8b93SVenkatesh Pallipadi */ 31302df8b93SVenkatesh Pallipadi acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, 31402df8b93SVenkatesh Pallipadi ACPI_MTX_DO_NOT_LOCK); 31502df8b93SVenkatesh Pallipadi } 31602df8b93SVenkatesh Pallipadi } else { 31702df8b93SVenkatesh Pallipadi /* SMP with no shared cache... Invalidate cache */ 31802df8b93SVenkatesh Pallipadi ACPI_FLUSH_CPU_CACHE(); 31902df8b93SVenkatesh Pallipadi } 32002df8b93SVenkatesh Pallipadi 3211da177e4SLinus Torvalds /* Get start time (ticks) */ 3221da177e4SLinus Torvalds t1 = inl(acpi_fadt.xpm_tmr_blk.address); 3231da177e4SLinus Torvalds /* Invoke C3 */ 3241da177e4SLinus Torvalds inb(cx->address); 3251da177e4SLinus Torvalds /* Dummy op - must do something useless after P_LVL3 read */ 3261da177e4SLinus Torvalds t2 = inl(acpi_fadt.xpm_tmr_blk.address); 3271da177e4SLinus Torvalds /* Get end time (ticks) */ 3281da177e4SLinus Torvalds t2 = inl(acpi_fadt.xpm_tmr_blk.address); 32902df8b93SVenkatesh Pallipadi if (pr->flags.bm_check) { 3301da177e4SLinus Torvalds /* Enable bus master arbitration */ 33102df8b93SVenkatesh Pallipadi atomic_dec(&c3_cpu_count); 3321da177e4SLinus Torvalds acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, ACPI_MTX_DO_NOT_LOCK); 33302df8b93SVenkatesh Pallipadi } 33402df8b93SVenkatesh Pallipadi 3351da177e4SLinus Torvalds /* Re-enable interrupts */ 3361da177e4SLinus Torvalds local_irq_enable(); 3371da177e4SLinus Torvalds /* Compute time (ticks) that we were actually asleep */ 3381da177e4SLinus Torvalds sleep_ticks = ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; 3391da177e4SLinus Torvalds break; 3401da177e4SLinus Torvalds 3411da177e4SLinus Torvalds default: 3421da177e4SLinus Torvalds local_irq_enable(); 3431da177e4SLinus Torvalds return; 3441da177e4SLinus Torvalds } 3451da177e4SLinus Torvalds 3461da177e4SLinus Torvalds next_state = pr->power.state; 3471da177e4SLinus Torvalds 3481da177e4SLinus Torvalds /* 3491da177e4SLinus Torvalds * Promotion? 3501da177e4SLinus Torvalds * ---------- 3511da177e4SLinus Torvalds * Track the number of longs (time asleep is greater than threshold) 3521da177e4SLinus Torvalds * and promote when the count threshold is reached. Note that bus 3531da177e4SLinus Torvalds * mastering activity may prevent promotions. 3541da177e4SLinus Torvalds * Do not promote above max_cstate. 3551da177e4SLinus Torvalds */ 3561da177e4SLinus Torvalds if (cx->promotion.state && 3571da177e4SLinus Torvalds ((cx->promotion.state - pr->power.states) <= max_cstate)) { 3581da177e4SLinus Torvalds if (sleep_ticks > cx->promotion.threshold.ticks) { 3591da177e4SLinus Torvalds cx->promotion.count++; 3601da177e4SLinus Torvalds cx->demotion.count = 0; 3611da177e4SLinus Torvalds if (cx->promotion.count >= cx->promotion.threshold.count) { 3621da177e4SLinus Torvalds if (pr->flags.bm_check) { 3631da177e4SLinus Torvalds if (!(pr->power.bm_activity & cx->promotion.threshold.bm)) { 3641da177e4SLinus Torvalds next_state = cx->promotion.state; 3651da177e4SLinus Torvalds goto end; 3661da177e4SLinus Torvalds } 3671da177e4SLinus Torvalds } 3681da177e4SLinus Torvalds else { 3691da177e4SLinus Torvalds next_state = cx->promotion.state; 3701da177e4SLinus Torvalds goto end; 3711da177e4SLinus Torvalds } 3721da177e4SLinus Torvalds } 3731da177e4SLinus Torvalds } 3741da177e4SLinus Torvalds } 3751da177e4SLinus Torvalds 3761da177e4SLinus Torvalds /* 3771da177e4SLinus Torvalds * Demotion? 3781da177e4SLinus Torvalds * --------- 3791da177e4SLinus Torvalds * Track the number of shorts (time asleep is less than time threshold) 3801da177e4SLinus Torvalds * and demote when the usage threshold is reached. 3811da177e4SLinus Torvalds */ 3821da177e4SLinus Torvalds if (cx->demotion.state) { 3831da177e4SLinus Torvalds if (sleep_ticks < cx->demotion.threshold.ticks) { 3841da177e4SLinus Torvalds cx->demotion.count++; 3851da177e4SLinus Torvalds cx->promotion.count = 0; 3861da177e4SLinus Torvalds if (cx->demotion.count >= cx->demotion.threshold.count) { 3871da177e4SLinus Torvalds next_state = cx->demotion.state; 3881da177e4SLinus Torvalds goto end; 3891da177e4SLinus Torvalds } 3901da177e4SLinus Torvalds } 3911da177e4SLinus Torvalds } 3921da177e4SLinus Torvalds 3931da177e4SLinus Torvalds end: 3941da177e4SLinus Torvalds /* 3951da177e4SLinus Torvalds * Demote if current state exceeds max_cstate 3961da177e4SLinus Torvalds */ 3971da177e4SLinus Torvalds if ((pr->power.state - pr->power.states) > max_cstate) { 3981da177e4SLinus Torvalds if (cx->demotion.state) 3991da177e4SLinus Torvalds next_state = cx->demotion.state; 4001da177e4SLinus Torvalds } 4011da177e4SLinus Torvalds 4021da177e4SLinus Torvalds /* 4031da177e4SLinus Torvalds * New Cx State? 4041da177e4SLinus Torvalds * ------------- 4051da177e4SLinus Torvalds * If we're going to start using a new Cx state we must clean up 4061da177e4SLinus Torvalds * from the previous and prepare to use the new. 4071da177e4SLinus Torvalds */ 4081da177e4SLinus Torvalds if (next_state != pr->power.state) 4091da177e4SLinus Torvalds acpi_processor_power_activate(pr, next_state); 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds return; 4121da177e4SLinus Torvalds 4131da177e4SLinus Torvalds easy_out: 4141da177e4SLinus Torvalds /* do C1 instead of busy loop */ 4151da177e4SLinus Torvalds if (pm_idle_save) 4161da177e4SLinus Torvalds pm_idle_save(); 4171da177e4SLinus Torvalds else 4181da177e4SLinus Torvalds safe_halt(); 4191da177e4SLinus Torvalds return; 4201da177e4SLinus Torvalds } 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds 4231da177e4SLinus Torvalds static int 4241da177e4SLinus Torvalds acpi_processor_set_power_policy ( 4251da177e4SLinus Torvalds struct acpi_processor *pr) 4261da177e4SLinus Torvalds { 4271da177e4SLinus Torvalds unsigned int i; 4281da177e4SLinus Torvalds unsigned int state_is_set = 0; 4291da177e4SLinus Torvalds struct acpi_processor_cx *lower = NULL; 4301da177e4SLinus Torvalds struct acpi_processor_cx *higher = NULL; 4311da177e4SLinus Torvalds struct acpi_processor_cx *cx; 4321da177e4SLinus Torvalds 4331da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_set_power_policy"); 4341da177e4SLinus Torvalds 4351da177e4SLinus Torvalds if (!pr) 4361da177e4SLinus Torvalds return_VALUE(-EINVAL); 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds /* 4391da177e4SLinus Torvalds * This function sets the default Cx state policy (OS idle handler). 4401da177e4SLinus Torvalds * Our scheme is to promote quickly to C2 but more conservatively 4411da177e4SLinus Torvalds * to C3. We're favoring C2 for its characteristics of low latency 4421da177e4SLinus Torvalds * (quick response), good power savings, and ability to allow bus 4431da177e4SLinus Torvalds * mastering activity. Note that the Cx state policy is completely 4441da177e4SLinus Torvalds * customizable and can be altered dynamically. 4451da177e4SLinus Torvalds */ 4461da177e4SLinus Torvalds 4471da177e4SLinus Torvalds /* startup state */ 4481da177e4SLinus Torvalds for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) { 4491da177e4SLinus Torvalds cx = &pr->power.states[i]; 4501da177e4SLinus Torvalds if (!cx->valid) 4511da177e4SLinus Torvalds continue; 4521da177e4SLinus Torvalds 4531da177e4SLinus Torvalds if (!state_is_set) 4541da177e4SLinus Torvalds pr->power.state = cx; 4551da177e4SLinus Torvalds state_is_set++; 4561da177e4SLinus Torvalds break; 4571da177e4SLinus Torvalds } 4581da177e4SLinus Torvalds 4591da177e4SLinus Torvalds if (!state_is_set) 4601da177e4SLinus Torvalds return_VALUE(-ENODEV); 4611da177e4SLinus Torvalds 4621da177e4SLinus Torvalds /* demotion */ 4631da177e4SLinus Torvalds for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) { 4641da177e4SLinus Torvalds cx = &pr->power.states[i]; 4651da177e4SLinus Torvalds if (!cx->valid) 4661da177e4SLinus Torvalds continue; 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds if (lower) { 4691da177e4SLinus Torvalds cx->demotion.state = lower; 4701da177e4SLinus Torvalds cx->demotion.threshold.ticks = cx->latency_ticks; 4711da177e4SLinus Torvalds cx->demotion.threshold.count = 1; 4721da177e4SLinus Torvalds if (cx->type == ACPI_STATE_C3) 4731da177e4SLinus Torvalds cx->demotion.threshold.bm = bm_history; 4741da177e4SLinus Torvalds } 4751da177e4SLinus Torvalds 4761da177e4SLinus Torvalds lower = cx; 4771da177e4SLinus Torvalds } 4781da177e4SLinus Torvalds 4791da177e4SLinus Torvalds /* promotion */ 4801da177e4SLinus Torvalds for (i = (ACPI_PROCESSOR_MAX_POWER - 1); i > 0; i--) { 4811da177e4SLinus Torvalds cx = &pr->power.states[i]; 4821da177e4SLinus Torvalds if (!cx->valid) 4831da177e4SLinus Torvalds continue; 4841da177e4SLinus Torvalds 4851da177e4SLinus Torvalds if (higher) { 4861da177e4SLinus Torvalds cx->promotion.state = higher; 4871da177e4SLinus Torvalds cx->promotion.threshold.ticks = cx->latency_ticks; 4881da177e4SLinus Torvalds if (cx->type >= ACPI_STATE_C2) 4891da177e4SLinus Torvalds cx->promotion.threshold.count = 4; 4901da177e4SLinus Torvalds else 4911da177e4SLinus Torvalds cx->promotion.threshold.count = 10; 4921da177e4SLinus Torvalds if (higher->type == ACPI_STATE_C3) 4931da177e4SLinus Torvalds cx->promotion.threshold.bm = bm_history; 4941da177e4SLinus Torvalds } 4951da177e4SLinus Torvalds 4961da177e4SLinus Torvalds higher = cx; 4971da177e4SLinus Torvalds } 4981da177e4SLinus Torvalds 4991da177e4SLinus Torvalds return_VALUE(0); 5001da177e4SLinus Torvalds } 5011da177e4SLinus Torvalds 5021da177e4SLinus Torvalds 5031da177e4SLinus Torvalds static int acpi_processor_get_power_info_fadt (struct acpi_processor *pr) 5041da177e4SLinus Torvalds { 5051da177e4SLinus Torvalds int i; 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_fadt"); 5081da177e4SLinus Torvalds 5091da177e4SLinus Torvalds if (!pr) 5101da177e4SLinus Torvalds return_VALUE(-EINVAL); 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds if (!pr->pblk) 5131da177e4SLinus Torvalds return_VALUE(-ENODEV); 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) 5161da177e4SLinus Torvalds memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); 5171da177e4SLinus Torvalds 5181da177e4SLinus Torvalds /* if info is obtained from pblk/fadt, type equals state */ 5191da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; 5201da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; 5211da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; 5221da177e4SLinus Torvalds 5231da177e4SLinus Torvalds /* the C0 state only exists as a filler in our array, 5241da177e4SLinus Torvalds * and all processors need to support C1 */ 5251da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C0].valid = 1; 5261da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C1].valid = 1; 5271da177e4SLinus Torvalds 5281da177e4SLinus Torvalds /* determine C2 and C3 address from pblk */ 5291da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].address = pr->pblk + 4; 5301da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].address = pr->pblk + 5; 5311da177e4SLinus Torvalds 5321da177e4SLinus Torvalds /* determine latencies from FADT */ 5331da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].latency = acpi_fadt.plvl2_lat; 5341da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].latency = acpi_fadt.plvl3_lat; 5351da177e4SLinus Torvalds 5361da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 5371da177e4SLinus Torvalds "lvl2[0x%08x] lvl3[0x%08x]\n", 5381da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C2].address, 5391da177e4SLinus Torvalds pr->power.states[ACPI_STATE_C3].address)); 5401da177e4SLinus Torvalds 5411da177e4SLinus Torvalds return_VALUE(0); 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds 545acf05f4bSVenkatesh Pallipadi static int acpi_processor_get_power_info_default_c1 (struct acpi_processor *pr) 546acf05f4bSVenkatesh Pallipadi { 547acf05f4bSVenkatesh Pallipadi int i; 548acf05f4bSVenkatesh Pallipadi 549acf05f4bSVenkatesh Pallipadi ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_default_c1"); 550acf05f4bSVenkatesh Pallipadi 551acf05f4bSVenkatesh Pallipadi for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) 552acf05f4bSVenkatesh Pallipadi memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); 553acf05f4bSVenkatesh Pallipadi 554acf05f4bSVenkatesh Pallipadi /* if info is obtained from pblk/fadt, type equals state */ 555acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; 556acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C2].type = ACPI_STATE_C2; 557acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C3].type = ACPI_STATE_C3; 558acf05f4bSVenkatesh Pallipadi 559acf05f4bSVenkatesh Pallipadi /* the C0 state only exists as a filler in our array, 560acf05f4bSVenkatesh Pallipadi * and all processors need to support C1 */ 561acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C0].valid = 1; 562acf05f4bSVenkatesh Pallipadi pr->power.states[ACPI_STATE_C1].valid = 1; 563acf05f4bSVenkatesh Pallipadi 564acf05f4bSVenkatesh Pallipadi return_VALUE(0); 565acf05f4bSVenkatesh Pallipadi } 566acf05f4bSVenkatesh Pallipadi 567acf05f4bSVenkatesh Pallipadi 5681da177e4SLinus Torvalds static int acpi_processor_get_power_info_cst (struct acpi_processor *pr) 5691da177e4SLinus Torvalds { 5701da177e4SLinus Torvalds acpi_status status = 0; 5711da177e4SLinus Torvalds acpi_integer count; 5721da177e4SLinus Torvalds int i; 5731da177e4SLinus Torvalds struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 5741da177e4SLinus Torvalds union acpi_object *cst; 5751da177e4SLinus Torvalds 5761da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_get_power_info_cst"); 5771da177e4SLinus Torvalds 5781da177e4SLinus Torvalds if (nocst) 5791da177e4SLinus Torvalds return_VALUE(-ENODEV); 5801da177e4SLinus Torvalds 5811da177e4SLinus Torvalds pr->power.count = 0; 5821da177e4SLinus Torvalds for (i = 0; i < ACPI_PROCESSOR_MAX_POWER; i++) 5831da177e4SLinus Torvalds memset(pr->power.states, 0, sizeof(struct acpi_processor_cx)); 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); 5861da177e4SLinus Torvalds if (ACPI_FAILURE(status)) { 5871da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No _CST, giving up\n")); 5881da177e4SLinus Torvalds return_VALUE(-ENODEV); 5891da177e4SLinus Torvalds } 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds cst = (union acpi_object *) buffer.pointer; 5921da177e4SLinus Torvalds 5931da177e4SLinus Torvalds /* There must be at least 2 elements */ 5941da177e4SLinus Torvalds if (!cst || (cst->type != ACPI_TYPE_PACKAGE) || cst->package.count < 2) { 5951da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "not enough elements in _CST\n")); 5961da177e4SLinus Torvalds status = -EFAULT; 5971da177e4SLinus Torvalds goto end; 5981da177e4SLinus Torvalds } 5991da177e4SLinus Torvalds 6001da177e4SLinus Torvalds count = cst->package.elements[0].integer.value; 6011da177e4SLinus Torvalds 6021da177e4SLinus Torvalds /* Validate number of power states. */ 6031da177e4SLinus Torvalds if (count < 1 || count != cst->package.count - 1) { 6041da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "count given by _CST is not valid\n")); 6051da177e4SLinus Torvalds status = -EFAULT; 6061da177e4SLinus Torvalds goto end; 6071da177e4SLinus Torvalds } 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds /* We support up to ACPI_PROCESSOR_MAX_POWER. */ 6101da177e4SLinus Torvalds if (count > ACPI_PROCESSOR_MAX_POWER) { 6111da177e4SLinus Torvalds printk(KERN_WARNING "Limiting number of power states to max (%d)\n", ACPI_PROCESSOR_MAX_POWER); 6121da177e4SLinus Torvalds printk(KERN_WARNING "Please increase ACPI_PROCESSOR_MAX_POWER if needed.\n"); 6131da177e4SLinus Torvalds count = ACPI_PROCESSOR_MAX_POWER; 6141da177e4SLinus Torvalds } 6151da177e4SLinus Torvalds 6161da177e4SLinus Torvalds /* Tell driver that at least _CST is supported. */ 6171da177e4SLinus Torvalds pr->flags.has_cst = 1; 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds for (i = 1; i <= count; i++) { 6201da177e4SLinus Torvalds union acpi_object *element; 6211da177e4SLinus Torvalds union acpi_object *obj; 6221da177e4SLinus Torvalds struct acpi_power_register *reg; 6231da177e4SLinus Torvalds struct acpi_processor_cx cx; 6241da177e4SLinus Torvalds 6251da177e4SLinus Torvalds memset(&cx, 0, sizeof(cx)); 6261da177e4SLinus Torvalds 6271da177e4SLinus Torvalds element = (union acpi_object *) &(cst->package.elements[i]); 6281da177e4SLinus Torvalds if (element->type != ACPI_TYPE_PACKAGE) 6291da177e4SLinus Torvalds continue; 6301da177e4SLinus Torvalds 6311da177e4SLinus Torvalds if (element->package.count != 4) 6321da177e4SLinus Torvalds continue; 6331da177e4SLinus Torvalds 6341da177e4SLinus Torvalds obj = (union acpi_object *) &(element->package.elements[0]); 6351da177e4SLinus Torvalds 6361da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_BUFFER) 6371da177e4SLinus Torvalds continue; 6381da177e4SLinus Torvalds 6391da177e4SLinus Torvalds reg = (struct acpi_power_register *) obj->buffer.pointer; 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO && 6421da177e4SLinus Torvalds (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) 6431da177e4SLinus Torvalds continue; 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ? 6461da177e4SLinus Torvalds 0 : reg->address; 6471da177e4SLinus Torvalds 6481da177e4SLinus Torvalds /* There should be an easy way to extract an integer... */ 6491da177e4SLinus Torvalds obj = (union acpi_object *) &(element->package.elements[1]); 6501da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_INTEGER) 6511da177e4SLinus Torvalds continue; 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds cx.type = obj->integer.value; 6541da177e4SLinus Torvalds 6551da177e4SLinus Torvalds if ((cx.type != ACPI_STATE_C1) && 6561da177e4SLinus Torvalds (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) 6571da177e4SLinus Torvalds continue; 6581da177e4SLinus Torvalds 6591da177e4SLinus Torvalds if ((cx.type < ACPI_STATE_C1) || 6601da177e4SLinus Torvalds (cx.type > ACPI_STATE_C3)) 6611da177e4SLinus Torvalds continue; 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds obj = (union acpi_object *) &(element->package.elements[2]); 6641da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_INTEGER) 6651da177e4SLinus Torvalds continue; 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds cx.latency = obj->integer.value; 6681da177e4SLinus Torvalds 6691da177e4SLinus Torvalds obj = (union acpi_object *) &(element->package.elements[3]); 6701da177e4SLinus Torvalds if (obj->type != ACPI_TYPE_INTEGER) 6711da177e4SLinus Torvalds continue; 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds cx.power = obj->integer.value; 6741da177e4SLinus Torvalds 6751da177e4SLinus Torvalds (pr->power.count)++; 6761da177e4SLinus Torvalds memcpy(&(pr->power.states[pr->power.count]), &cx, sizeof(cx)); 6771da177e4SLinus Torvalds } 6781da177e4SLinus Torvalds 6791da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d power states\n", pr->power.count)); 6801da177e4SLinus Torvalds 6811da177e4SLinus Torvalds /* Validate number of power states discovered */ 6821da177e4SLinus Torvalds if (pr->power.count < 2) 6831da177e4SLinus Torvalds status = -ENODEV; 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds end: 6861da177e4SLinus Torvalds acpi_os_free(buffer.pointer); 6871da177e4SLinus Torvalds 6881da177e4SLinus Torvalds return_VALUE(status); 6891da177e4SLinus Torvalds } 6901da177e4SLinus Torvalds 6911da177e4SLinus Torvalds 6921da177e4SLinus Torvalds static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) 6931da177e4SLinus Torvalds { 6941da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c2"); 6951da177e4SLinus Torvalds 6961da177e4SLinus Torvalds if (!cx->address) 6971da177e4SLinus Torvalds return_VOID; 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds /* 7001da177e4SLinus Torvalds * C2 latency must be less than or equal to 100 7011da177e4SLinus Torvalds * microseconds. 7021da177e4SLinus Torvalds */ 7031da177e4SLinus Torvalds else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { 7041da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 7051da177e4SLinus Torvalds "latency too large [%d]\n", 7061da177e4SLinus Torvalds cx->latency)); 7071da177e4SLinus Torvalds return_VOID; 7081da177e4SLinus Torvalds } 7091da177e4SLinus Torvalds 7101da177e4SLinus Torvalds /* 7111da177e4SLinus Torvalds * Otherwise we've met all of our C2 requirements. 7121da177e4SLinus Torvalds * Normalize the C2 latency to expidite policy 7131da177e4SLinus Torvalds */ 7141da177e4SLinus Torvalds cx->valid = 1; 7151da177e4SLinus Torvalds cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); 7161da177e4SLinus Torvalds 7171da177e4SLinus Torvalds return_VOID; 7181da177e4SLinus Torvalds } 7191da177e4SLinus Torvalds 7201da177e4SLinus Torvalds 7211da177e4SLinus Torvalds static void acpi_processor_power_verify_c3( 7221da177e4SLinus Torvalds struct acpi_processor *pr, 7231da177e4SLinus Torvalds struct acpi_processor_cx *cx) 7241da177e4SLinus Torvalds { 72502df8b93SVenkatesh Pallipadi static int bm_check_flag; 72602df8b93SVenkatesh Pallipadi 7271da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_get_power_verify_c3"); 7281da177e4SLinus Torvalds 7291da177e4SLinus Torvalds if (!cx->address) 7301da177e4SLinus Torvalds return_VOID; 7311da177e4SLinus Torvalds 7321da177e4SLinus Torvalds /* 7331da177e4SLinus Torvalds * C3 latency must be less than or equal to 1000 7341da177e4SLinus Torvalds * microseconds. 7351da177e4SLinus Torvalds */ 7361da177e4SLinus Torvalds else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { 7371da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 7381da177e4SLinus Torvalds "latency too large [%d]\n", 7391da177e4SLinus Torvalds cx->latency)); 7401da177e4SLinus Torvalds return_VOID; 7411da177e4SLinus Torvalds } 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds /* 7441da177e4SLinus Torvalds * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) 7451da177e4SLinus Torvalds * DMA transfers are used by any ISA device to avoid livelock. 7461da177e4SLinus Torvalds * Note that we could disable Type-F DMA (as recommended by 7471da177e4SLinus Torvalds * the erratum), but this is known to disrupt certain ISA 7481da177e4SLinus Torvalds * devices thus we take the conservative approach. 7491da177e4SLinus Torvalds */ 7501da177e4SLinus Torvalds else if (errata.piix4.fdma) { 7511da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_INFO, 7521da177e4SLinus Torvalds "C3 not supported on PIIX4 with Type-F DMA\n")); 7531da177e4SLinus Torvalds return_VOID; 7541da177e4SLinus Torvalds } 7551da177e4SLinus Torvalds 75602df8b93SVenkatesh Pallipadi /* All the logic here assumes flags.bm_check is same across all CPUs */ 75702df8b93SVenkatesh Pallipadi if (!bm_check_flag) { 75802df8b93SVenkatesh Pallipadi /* Determine whether bm_check is needed based on CPU */ 75902df8b93SVenkatesh Pallipadi acpi_processor_power_init_bm_check(&(pr->flags), pr->id); 76002df8b93SVenkatesh Pallipadi bm_check_flag = pr->flags.bm_check; 76102df8b93SVenkatesh Pallipadi } else { 76202df8b93SVenkatesh Pallipadi pr->flags.bm_check = bm_check_flag; 76302df8b93SVenkatesh Pallipadi } 76402df8b93SVenkatesh Pallipadi 76502df8b93SVenkatesh Pallipadi if (pr->flags.bm_check) { 76602df8b93SVenkatesh Pallipadi printk("Disabling BM access before entering C3\n"); 76702df8b93SVenkatesh Pallipadi /* bus mastering control is necessary */ 76802df8b93SVenkatesh Pallipadi if (!pr->flags.bm_control) { 76902df8b93SVenkatesh Pallipadi ACPI_DEBUG_PRINT((ACPI_DB_INFO, 77002df8b93SVenkatesh Pallipadi "C3 support requires bus mastering control\n")); 77102df8b93SVenkatesh Pallipadi return_VOID; 77202df8b93SVenkatesh Pallipadi } 77302df8b93SVenkatesh Pallipadi } else { 77402df8b93SVenkatesh Pallipadi printk("Invalidating cache before entering C3\n"); 77502df8b93SVenkatesh Pallipadi /* 77602df8b93SVenkatesh Pallipadi * WBINVD should be set in fadt, for C3 state to be 77702df8b93SVenkatesh Pallipadi * supported on when bm_check is not required. 77802df8b93SVenkatesh Pallipadi */ 77902df8b93SVenkatesh Pallipadi if (acpi_fadt.wb_invd != 1) { 78002df8b93SVenkatesh Pallipadi ACPI_DEBUG_PRINT((ACPI_DB_INFO, 78102df8b93SVenkatesh Pallipadi "Cache invalidation should work properly" 78202df8b93SVenkatesh Pallipadi " for C3 to be enabled on SMP systems\n")); 78302df8b93SVenkatesh Pallipadi return_VOID; 78402df8b93SVenkatesh Pallipadi } 78502df8b93SVenkatesh Pallipadi acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 78602df8b93SVenkatesh Pallipadi 0, ACPI_MTX_DO_NOT_LOCK); 78702df8b93SVenkatesh Pallipadi } 78802df8b93SVenkatesh Pallipadi 7891da177e4SLinus Torvalds /* 7901da177e4SLinus Torvalds * Otherwise we've met all of our C3 requirements. 7911da177e4SLinus Torvalds * Normalize the C3 latency to expidite policy. Enable 7921da177e4SLinus Torvalds * checking of bus mastering status (bm_check) so we can 7931da177e4SLinus Torvalds * use this in our C3 policy 7941da177e4SLinus Torvalds */ 7951da177e4SLinus Torvalds cx->valid = 1; 7961da177e4SLinus Torvalds cx->latency_ticks = US_TO_PM_TIMER_TICKS(cx->latency); 7971da177e4SLinus Torvalds 7981da177e4SLinus Torvalds return_VOID; 7991da177e4SLinus Torvalds } 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds 8021da177e4SLinus Torvalds static int acpi_processor_power_verify(struct acpi_processor *pr) 8031da177e4SLinus Torvalds { 8041da177e4SLinus Torvalds unsigned int i; 8051da177e4SLinus Torvalds unsigned int working = 0; 8061da177e4SLinus Torvalds 8071da177e4SLinus Torvalds for (i=1; i < ACPI_PROCESSOR_MAX_POWER; i++) { 8081da177e4SLinus Torvalds struct acpi_processor_cx *cx = &pr->power.states[i]; 8091da177e4SLinus Torvalds 8101da177e4SLinus Torvalds switch (cx->type) { 8111da177e4SLinus Torvalds case ACPI_STATE_C1: 8121da177e4SLinus Torvalds cx->valid = 1; 8131da177e4SLinus Torvalds break; 8141da177e4SLinus Torvalds 8151da177e4SLinus Torvalds case ACPI_STATE_C2: 8161da177e4SLinus Torvalds acpi_processor_power_verify_c2(cx); 8171da177e4SLinus Torvalds break; 8181da177e4SLinus Torvalds 8191da177e4SLinus Torvalds case ACPI_STATE_C3: 8201da177e4SLinus Torvalds acpi_processor_power_verify_c3(pr, cx); 8211da177e4SLinus Torvalds break; 8221da177e4SLinus Torvalds } 8231da177e4SLinus Torvalds 8241da177e4SLinus Torvalds if (cx->valid) 8251da177e4SLinus Torvalds working++; 8261da177e4SLinus Torvalds } 8271da177e4SLinus Torvalds 8281da177e4SLinus Torvalds return (working); 8291da177e4SLinus Torvalds } 8301da177e4SLinus Torvalds 8311da177e4SLinus Torvalds static int acpi_processor_get_power_info ( 8321da177e4SLinus Torvalds struct acpi_processor *pr) 8331da177e4SLinus Torvalds { 8341da177e4SLinus Torvalds unsigned int i; 8351da177e4SLinus Torvalds int result; 8361da177e4SLinus Torvalds 8371da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_get_power_info"); 8381da177e4SLinus Torvalds 8391da177e4SLinus Torvalds /* NOTE: the idle thread may not be running while calling 8401da177e4SLinus Torvalds * this function */ 8411da177e4SLinus Torvalds 8421da177e4SLinus Torvalds result = acpi_processor_get_power_info_cst(pr); 8431da177e4SLinus Torvalds if ((result) || (acpi_processor_power_verify(pr) < 2)) { 8441da177e4SLinus Torvalds result = acpi_processor_get_power_info_fadt(pr); 8451da177e4SLinus Torvalds if (result) 846acf05f4bSVenkatesh Pallipadi result = acpi_processor_get_power_info_default_c1(pr); 8471da177e4SLinus Torvalds } 8481da177e4SLinus Torvalds 8491da177e4SLinus Torvalds /* 8501da177e4SLinus Torvalds * Set Default Policy 8511da177e4SLinus Torvalds * ------------------ 8521da177e4SLinus Torvalds * Now that we know which states are supported, set the default 8531da177e4SLinus Torvalds * policy. Note that this policy can be changed dynamically 8541da177e4SLinus Torvalds * (e.g. encourage deeper sleeps to conserve battery life when 8551da177e4SLinus Torvalds * not on AC). 8561da177e4SLinus Torvalds */ 8571da177e4SLinus Torvalds result = acpi_processor_set_power_policy(pr); 8581da177e4SLinus Torvalds if (result) 8591da177e4SLinus Torvalds return_VALUE(result); 8601da177e4SLinus Torvalds 8611da177e4SLinus Torvalds /* 8621da177e4SLinus Torvalds * if one state of type C2 or C3 is available, mark this 8631da177e4SLinus Torvalds * CPU as being "idle manageable" 8641da177e4SLinus Torvalds */ 8651da177e4SLinus Torvalds for (i = 1; i < ACPI_PROCESSOR_MAX_POWER; i++) { 866acf05f4bSVenkatesh Pallipadi if (pr->power.states[i].valid) { 8671da177e4SLinus Torvalds pr->power.count = i; 8681da177e4SLinus Torvalds pr->flags.power = 1; 8691da177e4SLinus Torvalds } 870acf05f4bSVenkatesh Pallipadi } 8711da177e4SLinus Torvalds 8721da177e4SLinus Torvalds return_VALUE(0); 8731da177e4SLinus Torvalds } 8741da177e4SLinus Torvalds 8751da177e4SLinus Torvalds int acpi_processor_cst_has_changed (struct acpi_processor *pr) 8761da177e4SLinus Torvalds { 8771da177e4SLinus Torvalds int result = 0; 8781da177e4SLinus Torvalds 8791da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_cst_has_changed"); 8801da177e4SLinus Torvalds 8811da177e4SLinus Torvalds if (!pr) 8821da177e4SLinus Torvalds return_VALUE(-EINVAL); 8831da177e4SLinus Torvalds 88402df8b93SVenkatesh Pallipadi if ( nocst) { 8851da177e4SLinus Torvalds return_VALUE(-ENODEV); 8861da177e4SLinus Torvalds } 8871da177e4SLinus Torvalds 8881da177e4SLinus Torvalds if (!pr->flags.power_setup_done) 8891da177e4SLinus Torvalds return_VALUE(-ENODEV); 8901da177e4SLinus Torvalds 8911da177e4SLinus Torvalds /* Fall back to the default idle loop */ 8921da177e4SLinus Torvalds pm_idle = pm_idle_save; 893fbd568a3SPaul E. McKenney synchronize_sched(); /* Relies on interrupts forcing exit from idle. */ 8941da177e4SLinus Torvalds 8951da177e4SLinus Torvalds pr->flags.power = 0; 8961da177e4SLinus Torvalds result = acpi_processor_get_power_info(pr); 8971da177e4SLinus Torvalds if ((pr->flags.power == 1) && (pr->flags.power_setup_done)) 8981da177e4SLinus Torvalds pm_idle = acpi_processor_idle; 8991da177e4SLinus Torvalds 9001da177e4SLinus Torvalds return_VALUE(result); 9011da177e4SLinus Torvalds } 9021da177e4SLinus Torvalds 9031da177e4SLinus Torvalds /* proc interface */ 9041da177e4SLinus Torvalds 9051da177e4SLinus Torvalds static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) 9061da177e4SLinus Torvalds { 9071da177e4SLinus Torvalds struct acpi_processor *pr = (struct acpi_processor *)seq->private; 9081da177e4SLinus Torvalds unsigned int i; 9091da177e4SLinus Torvalds 9101da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_power_seq_show"); 9111da177e4SLinus Torvalds 9121da177e4SLinus Torvalds if (!pr) 9131da177e4SLinus Torvalds goto end; 9141da177e4SLinus Torvalds 9151da177e4SLinus Torvalds seq_printf(seq, "active state: C%zd\n" 9161da177e4SLinus Torvalds "max_cstate: C%d\n" 9171da177e4SLinus Torvalds "bus master activity: %08x\n", 9181da177e4SLinus Torvalds pr->power.state ? pr->power.state - pr->power.states : 0, 9191da177e4SLinus Torvalds max_cstate, 9201da177e4SLinus Torvalds (unsigned)pr->power.bm_activity); 9211da177e4SLinus Torvalds 9221da177e4SLinus Torvalds seq_puts(seq, "states:\n"); 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds for (i = 1; i <= pr->power.count; i++) { 9251da177e4SLinus Torvalds seq_printf(seq, " %cC%d: ", 9261da177e4SLinus Torvalds (&pr->power.states[i] == pr->power.state?'*':' '), i); 9271da177e4SLinus Torvalds 9281da177e4SLinus Torvalds if (!pr->power.states[i].valid) { 9291da177e4SLinus Torvalds seq_puts(seq, "<not supported>\n"); 9301da177e4SLinus Torvalds continue; 9311da177e4SLinus Torvalds } 9321da177e4SLinus Torvalds 9331da177e4SLinus Torvalds switch (pr->power.states[i].type) { 9341da177e4SLinus Torvalds case ACPI_STATE_C1: 9351da177e4SLinus Torvalds seq_printf(seq, "type[C1] "); 9361da177e4SLinus Torvalds break; 9371da177e4SLinus Torvalds case ACPI_STATE_C2: 9381da177e4SLinus Torvalds seq_printf(seq, "type[C2] "); 9391da177e4SLinus Torvalds break; 9401da177e4SLinus Torvalds case ACPI_STATE_C3: 9411da177e4SLinus Torvalds seq_printf(seq, "type[C3] "); 9421da177e4SLinus Torvalds break; 9431da177e4SLinus Torvalds default: 9441da177e4SLinus Torvalds seq_printf(seq, "type[--] "); 9451da177e4SLinus Torvalds break; 9461da177e4SLinus Torvalds } 9471da177e4SLinus Torvalds 9481da177e4SLinus Torvalds if (pr->power.states[i].promotion.state) 9491da177e4SLinus Torvalds seq_printf(seq, "promotion[C%zd] ", 9501da177e4SLinus Torvalds (pr->power.states[i].promotion.state - 9511da177e4SLinus Torvalds pr->power.states)); 9521da177e4SLinus Torvalds else 9531da177e4SLinus Torvalds seq_puts(seq, "promotion[--] "); 9541da177e4SLinus Torvalds 9551da177e4SLinus Torvalds if (pr->power.states[i].demotion.state) 9561da177e4SLinus Torvalds seq_printf(seq, "demotion[C%zd] ", 9571da177e4SLinus Torvalds (pr->power.states[i].demotion.state - 9581da177e4SLinus Torvalds pr->power.states)); 9591da177e4SLinus Torvalds else 9601da177e4SLinus Torvalds seq_puts(seq, "demotion[--] "); 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds seq_printf(seq, "latency[%03d] usage[%08d]\n", 9631da177e4SLinus Torvalds pr->power.states[i].latency, 9641da177e4SLinus Torvalds pr->power.states[i].usage); 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds 9671da177e4SLinus Torvalds end: 9681da177e4SLinus Torvalds return_VALUE(0); 9691da177e4SLinus Torvalds } 9701da177e4SLinus Torvalds 9711da177e4SLinus Torvalds static int acpi_processor_power_open_fs(struct inode *inode, struct file *file) 9721da177e4SLinus Torvalds { 9731da177e4SLinus Torvalds return single_open(file, acpi_processor_power_seq_show, 9741da177e4SLinus Torvalds PDE(inode)->data); 9751da177e4SLinus Torvalds } 9761da177e4SLinus Torvalds 9771da177e4SLinus Torvalds static struct file_operations acpi_processor_power_fops = { 9781da177e4SLinus Torvalds .open = acpi_processor_power_open_fs, 9791da177e4SLinus Torvalds .read = seq_read, 9801da177e4SLinus Torvalds .llseek = seq_lseek, 9811da177e4SLinus Torvalds .release = single_release, 9821da177e4SLinus Torvalds }; 9831da177e4SLinus Torvalds 9841da177e4SLinus Torvalds int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) 9851da177e4SLinus Torvalds { 9861da177e4SLinus Torvalds acpi_status status = 0; 9871da177e4SLinus Torvalds static int first_run = 0; 9881da177e4SLinus Torvalds struct proc_dir_entry *entry = NULL; 9891da177e4SLinus Torvalds unsigned int i; 9901da177e4SLinus Torvalds 9911da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_power_init"); 9921da177e4SLinus Torvalds 9931da177e4SLinus Torvalds if (!first_run) { 9941da177e4SLinus Torvalds dmi_check_system(processor_power_dmi_table); 9951da177e4SLinus Torvalds if (max_cstate < ACPI_C_STATES_MAX) 9961da177e4SLinus Torvalds printk(KERN_NOTICE "ACPI: processor limited to max C-state %d\n", max_cstate); 9971da177e4SLinus Torvalds first_run++; 9981da177e4SLinus Torvalds } 9991da177e4SLinus Torvalds 100002df8b93SVenkatesh Pallipadi if (!pr) 100102df8b93SVenkatesh Pallipadi return_VALUE(-EINVAL); 100202df8b93SVenkatesh Pallipadi 100302df8b93SVenkatesh Pallipadi if (acpi_fadt.cst_cnt && !nocst) { 10041da177e4SLinus Torvalds status = acpi_os_write_port(acpi_fadt.smi_cmd, acpi_fadt.cst_cnt, 8); 10051da177e4SLinus Torvalds if (ACPI_FAILURE(status)) { 10061da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 10071da177e4SLinus Torvalds "Notifying BIOS of _CST ability failed\n")); 10081da177e4SLinus Torvalds } 10091da177e4SLinus Torvalds } 10101da177e4SLinus Torvalds 101102df8b93SVenkatesh Pallipadi acpi_processor_power_init_pdc(&(pr->power), pr->id); 101202df8b93SVenkatesh Pallipadi acpi_processor_set_pdc(pr, pr->power.pdc); 10131da177e4SLinus Torvalds acpi_processor_get_power_info(pr); 10141da177e4SLinus Torvalds 10151da177e4SLinus Torvalds /* 10161da177e4SLinus Torvalds * Install the idle handler if processor power management is supported. 10171da177e4SLinus Torvalds * Note that we use previously set idle handler will be used on 10181da177e4SLinus Torvalds * platforms that only support C1. 10191da177e4SLinus Torvalds */ 10201da177e4SLinus Torvalds if ((pr->flags.power) && (!boot_option_idle_override)) { 10211da177e4SLinus Torvalds printk(KERN_INFO PREFIX "CPU%d (power states:", pr->id); 10221da177e4SLinus Torvalds for (i = 1; i <= pr->power.count; i++) 10231da177e4SLinus Torvalds if (pr->power.states[i].valid) 10241da177e4SLinus Torvalds printk(" C%d[C%d]", i, pr->power.states[i].type); 10251da177e4SLinus Torvalds printk(")\n"); 10261da177e4SLinus Torvalds 10271da177e4SLinus Torvalds if (pr->id == 0) { 10281da177e4SLinus Torvalds pm_idle_save = pm_idle; 10291da177e4SLinus Torvalds pm_idle = acpi_processor_idle; 10301da177e4SLinus Torvalds } 10311da177e4SLinus Torvalds } 10321da177e4SLinus Torvalds 10331da177e4SLinus Torvalds /* 'power' [R] */ 10341da177e4SLinus Torvalds entry = create_proc_entry(ACPI_PROCESSOR_FILE_POWER, 10351da177e4SLinus Torvalds S_IRUGO, acpi_device_dir(device)); 10361da177e4SLinus Torvalds if (!entry) 10371da177e4SLinus Torvalds ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 10381da177e4SLinus Torvalds "Unable to create '%s' fs entry\n", 10391da177e4SLinus Torvalds ACPI_PROCESSOR_FILE_POWER)); 10401da177e4SLinus Torvalds else { 10411da177e4SLinus Torvalds entry->proc_fops = &acpi_processor_power_fops; 10421da177e4SLinus Torvalds entry->data = acpi_driver_data(device); 10431da177e4SLinus Torvalds entry->owner = THIS_MODULE; 10441da177e4SLinus Torvalds } 10451da177e4SLinus Torvalds 10461da177e4SLinus Torvalds pr->flags.power_setup_done = 1; 10471da177e4SLinus Torvalds 10481da177e4SLinus Torvalds return_VALUE(0); 10491da177e4SLinus Torvalds } 10501da177e4SLinus Torvalds 10511da177e4SLinus Torvalds int acpi_processor_power_exit(struct acpi_processor *pr, struct acpi_device *device) 10521da177e4SLinus Torvalds { 10531da177e4SLinus Torvalds ACPI_FUNCTION_TRACE("acpi_processor_power_exit"); 10541da177e4SLinus Torvalds 10551da177e4SLinus Torvalds pr->flags.power_setup_done = 0; 10561da177e4SLinus Torvalds 10571da177e4SLinus Torvalds if (acpi_device_dir(device)) 10581da177e4SLinus Torvalds remove_proc_entry(ACPI_PROCESSOR_FILE_POWER,acpi_device_dir(device)); 10591da177e4SLinus Torvalds 10601da177e4SLinus Torvalds /* Unregister the idle handler when processor #0 is removed. */ 10611da177e4SLinus Torvalds if (pr->id == 0) { 10621da177e4SLinus Torvalds pm_idle = pm_idle_save; 10631da177e4SLinus Torvalds 10641da177e4SLinus Torvalds /* 10651da177e4SLinus Torvalds * We are about to unload the current idle thread pm callback 10661da177e4SLinus Torvalds * (pm_idle), Wait for all processors to update cached/local 10671da177e4SLinus Torvalds * copies of pm_idle before proceeding. 10681da177e4SLinus Torvalds */ 10691da177e4SLinus Torvalds cpu_idle_wait(); 10701da177e4SLinus Torvalds } 10711da177e4SLinus Torvalds 10721da177e4SLinus Torvalds return_VALUE(0); 10731da177e4SLinus Torvalds } 1074