Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'release', 'cpuidle-2.6.25' and 'idle' into release

Len Brown acf63867 c64768a7

+111 -18
+6
arch/x86/Kconfig
··· 98 98 config ARCH_HAS_ILOG2_U64 99 99 def_bool n 100 100 101 + config ARCH_HAS_CPU_IDLE_WAIT 102 + def_bool y 103 + 101 104 config GENERIC_CALIBRATE_DELAY 102 105 def_bool y 103 106 104 107 config GENERIC_TIME_VSYSCALL 105 108 bool 106 109 default X86_64 110 + 111 + config ARCH_HAS_CPU_RELAX 112 + def_bool y 107 113 108 114 config HAVE_SETUP_PER_CPU_AREA 109 115 def_bool X86_64
+36 -11
drivers/acpi/processor_idle.c
··· 98 98 99 99 static int acpi_processor_set_power_policy(struct acpi_processor *pr); 100 100 101 + #else /* CONFIG_CPU_IDLE */ 102 + static unsigned int latency_factor __read_mostly = 2; 103 + module_param(latency_factor, uint, 0644); 101 104 #endif 102 105 103 106 /* ··· 204 201 return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); 205 202 } 206 203 204 + /* 205 + * Callers should disable interrupts before the call and enable 206 + * interrupts after return. 207 + */ 207 208 static void acpi_safe_halt(void) 208 209 { 209 210 current_thread_info()->status &= ~TS_POLLING; ··· 268 261 /* Common C-state entry for C2, C3, .. */ 269 262 static void acpi_cstate_enter(struct acpi_processor_cx *cstate) 270 263 { 271 - if (cstate->space_id == ACPI_CSTATE_FFH) { 264 + if (cstate->entry_method == ACPI_CSTATE_FFH) { 272 265 /* Call into architectural FFH based C-state */ 273 266 acpi_processor_ffh_cstate_enter(cstate); 274 267 } else { ··· 420 413 pm_idle_save(); 421 414 else 422 415 acpi_safe_halt(); 416 + 417 + local_irq_enable(); 423 418 return; 424 419 } 425 420 ··· 530 521 * skew otherwise. 531 522 */ 532 523 sleep_ticks = 0xFFFFFFFF; 524 + local_irq_enable(); 533 525 break; 534 526 535 527 case ACPI_STATE_C2: ··· 932 922 cx.address = reg->address; 933 923 cx.index = current_count + 1; 934 924 935 - cx.space_id = ACPI_CSTATE_SYSTEMIO; 925 + cx.entry_method = ACPI_CSTATE_SYSTEMIO; 936 926 if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { 937 927 if (acpi_processor_ffh_cstate_probe 938 928 (pr->id, &cx, reg) == 0) { 939 - cx.space_id = ACPI_CSTATE_FFH; 940 - } else if (cx.type != ACPI_STATE_C1) { 929 + cx.entry_method = ACPI_CSTATE_FFH; 930 + } else if (cx.type == ACPI_STATE_C1) { 941 931 /* 942 932 * C1 is a special case where FIXED_HARDWARE 943 933 * can be handled in non-MWAIT way as well. 944 934 * In that case, save this _CST entry info. 945 - * That is, we retain space_id of SYSTEM_IO for 946 - * halt based C1. 947 935 * Otherwise, ignore this info and continue. 948 936 */ 937 + cx.entry_method = ACPI_CSTATE_HALT; 938 + } else { 949 939 continue; 950 940 } 951 941 } ··· 1379 1369 /** 1380 1370 * acpi_idle_do_entry - a helper function that does C2 and C3 type entry 1381 1371 * @cx: cstate data 1372 + * 1373 + * Caller disables interrupt before call and enables interrupt after return. 1382 1374 */ 1383 1375 static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) 1384 1376 { 1385 - if (cx->space_id == ACPI_CSTATE_FFH) { 1377 + if (cx->entry_method == ACPI_CSTATE_FFH) { 1386 1378 /* Call into architectural FFH based C-state */ 1387 1379 acpi_processor_ffh_cstate_enter(cx); 1380 + } else if (cx->entry_method == ACPI_CSTATE_HALT) { 1381 + acpi_safe_halt(); 1388 1382 } else { 1389 1383 int unused; 1390 1384 /* IO port based C-state */ ··· 1410 1396 static int acpi_idle_enter_c1(struct cpuidle_device *dev, 1411 1397 struct cpuidle_state *state) 1412 1398 { 1399 + u32 t1, t2; 1413 1400 struct acpi_processor *pr; 1414 1401 struct acpi_processor_cx *cx = cpuidle_get_statedata(state); 1402 + 1415 1403 pr = processors[smp_processor_id()]; 1416 1404 1417 1405 if (unlikely(!pr)) 1418 1406 return 0; 1419 1407 1408 + local_irq_disable(); 1420 1409 if (pr->flags.bm_check) 1421 1410 acpi_idle_update_bm_rld(pr, cx); 1422 1411 1423 - acpi_safe_halt(); 1412 + t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); 1413 + acpi_idle_do_entry(cx); 1414 + t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 1424 1415 1416 + local_irq_enable(); 1425 1417 cx->usage++; 1426 1418 1427 - return 0; 1419 + return ticks_elapsed_in_us(t1, t2); 1428 1420 } 1429 1421 1430 1422 /** ··· 1537 1517 if (dev->safe_state) { 1538 1518 return dev->safe_state->enter(dev, dev->safe_state); 1539 1519 } else { 1520 + local_irq_disable(); 1540 1521 acpi_safe_halt(); 1522 + local_irq_enable(); 1541 1523 return 0; 1542 1524 } 1543 1525 } ··· 1631 1609 */ 1632 1610 static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) 1633 1611 { 1634 - int i, count = 0; 1612 + int i, count = CPUIDLE_DRIVER_STATE_START; 1635 1613 struct acpi_processor_cx *cx; 1636 1614 struct cpuidle_state *state; 1637 1615 struct cpuidle_device *dev = &pr->power.dev; ··· 1660 1638 1661 1639 snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); 1662 1640 state->exit_latency = cx->latency; 1663 - state->target_residency = cx->latency * 6; 1641 + state->target_residency = cx->latency * latency_factor; 1664 1642 state->power_usage = cx->power; 1665 1643 1666 1644 state->flags = 0; 1667 1645 switch (cx->type) { 1668 1646 case ACPI_STATE_C1: 1669 1647 state->flags |= CPUIDLE_FLAG_SHALLOW; 1648 + state->flags |= CPUIDLE_FLAG_TIME_VALID; 1670 1649 state->enter = acpi_idle_enter_c1; 1671 1650 dev->safe_state = state; 1672 1651 break; ··· 1690 1667 } 1691 1668 1692 1669 count++; 1670 + if (count == CPUIDLE_STATE_MAX) 1671 + break; 1693 1672 } 1694 1673 1695 1674 dev->state_count = count;
+2 -2
drivers/cpuidle/Kconfig
··· 1 1 2 2 config CPU_IDLE 3 3 bool "CPU idle PM support" 4 + default ACPI 4 5 help 5 6 CPU idle is a generic framework for supporting software-controlled 6 7 idle processor power management. It includes modular cross-platform 7 8 governors that can be swapped during runtime. 8 9 9 - If you're using a mobile platform that supports CPU idle PM (e.g. 10 - an ACPI-capable notebook), you should say Y here. 10 + If you're using an ACPI-enabled platform, you should say Y here. 11 11 12 12 config CPU_IDLE_GOV_LADDER 13 13 bool
+42 -1
drivers/cpuidle/cpuidle.c
··· 15 15 #include <linux/pm_qos_params.h> 16 16 #include <linux/cpu.h> 17 17 #include <linux/cpuidle.h> 18 + #include <linux/ktime.h> 18 19 19 20 #include "cpuidle.h" 20 21 ··· 83 82 { 84 83 if (enabled_devices && (pm_idle != pm_idle_old)) { 85 84 pm_idle = pm_idle_old; 86 - cpu_idle_wait(); 85 + cpuidle_kick_cpus(); 87 86 } 88 87 } 89 88 ··· 181 180 182 181 EXPORT_SYMBOL_GPL(cpuidle_disable_device); 183 182 183 + #ifdef CONFIG_ARCH_HAS_CPU_RELAX 184 + static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) 185 + { 186 + ktime_t t1, t2; 187 + s64 diff; 188 + int ret; 189 + 190 + t1 = ktime_get(); 191 + local_irq_enable(); 192 + while (!need_resched()) 193 + cpu_relax(); 194 + 195 + t2 = ktime_get(); 196 + diff = ktime_to_us(ktime_sub(t2, t1)); 197 + if (diff > INT_MAX) 198 + diff = INT_MAX; 199 + 200 + ret = (int) diff; 201 + return ret; 202 + } 203 + 204 + static void poll_idle_init(struct cpuidle_device *dev) 205 + { 206 + struct cpuidle_state *state = &dev->states[0]; 207 + 208 + cpuidle_set_statedata(state, NULL); 209 + 210 + snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); 211 + state->exit_latency = 0; 212 + state->target_residency = 0; 213 + state->power_usage = -1; 214 + state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID; 215 + state->enter = poll_idle; 216 + } 217 + #else 218 + static void poll_idle_init(struct cpuidle_device *dev) {} 219 + #endif /* CONFIG_ARCH_HAS_CPU_RELAX */ 220 + 184 221 /** 185 222 * cpuidle_register_device - registers a CPU's idle PM feature 186 223 * @dev: the cpu ··· 236 197 init_completion(&dev->kobj_unregister); 237 198 238 199 mutex_lock(&cpuidle_lock); 200 + 201 + poll_idle_init(dev); 239 202 240 203 per_cpu(cpuidle_devices, dev->cpu) = dev; 241 204 list_add(&dev->device_list, &cpuidle_detected_devices);
+2 -1
include/acpi/processor.h
··· 34 34 35 35 #define ACPI_CSTATE_SYSTEMIO (0) 36 36 #define ACPI_CSTATE_FFH (1) 37 + #define ACPI_CSTATE_HALT (2) 37 38 38 39 /* Power Management */ 39 40 ··· 65 64 u8 valid; 66 65 u8 type; 67 66 u32 address; 68 - u8 space_id; 67 + u8 entry_method; 69 68 u8 index; 70 69 u32 latency; 71 70 u32 latency_ticks;
+23 -3
include/linux/cpuidle.h
··· 46 46 /* Idle State Flags */ 47 47 #define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ 48 48 #define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */ 49 - #define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */ 50 - #define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */ 51 - #define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */ 49 + #define CPUIDLE_FLAG_POLL (0x10) /* no latency, no savings */ 50 + #define CPUIDLE_FLAG_SHALLOW (0x20) /* low latency, minimal savings */ 51 + #define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */ 52 + #define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */ 52 53 53 54 #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) 54 55 ··· 72 71 { 73 72 state->driver_data = data; 74 73 } 74 + 75 + #ifdef CONFIG_SMP 76 + #ifdef CONFIG_ARCH_HAS_CPU_IDLE_WAIT 77 + static inline void cpuidle_kick_cpus(void) 78 + { 79 + cpu_idle_wait(); 80 + } 81 + #else /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT */ 82 + #error "Arch needs cpu_idle_wait() equivalent here" 83 + #endif /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT */ 84 + #else /* !CONFIG_SMP */ 85 + static inline void cpuidle_kick_cpus(void) {} 86 + #endif /* !CONFIG_SMP */ 75 87 76 88 struct cpuidle_state_kobj { 77 89 struct cpuidle_state *state; ··· 190 176 {return 0;} 191 177 static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } 192 178 179 + #endif 180 + 181 + #ifdef CONFIG_ARCH_HAS_CPU_RELAX 182 + #define CPUIDLE_DRIVER_STATE_START 1 183 + #else 184 + #define CPUIDLE_DRIVER_STATE_START 0 193 185 #endif 194 186 195 187 #endif /* _LINUX_CPUIDLE_H */