Merge branch 'idle-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 29 May 2011 18:18:09 +0000 (11:18 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 29 May 2011 18:18:09 +0000 (11:18 -0700)
* 'idle-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-idle-2.6:
  x86 idle: deprecate mwait_idle() and "idle=mwait" cmdline param
  x86 idle: deprecate "no-hlt" cmdline param
  x86 idle APM: deprecate CONFIG_APM_CPU_IDLE
  x86 idle floppy: deprecate disable_hlt()
  x86 idle: EXPORT_SYMBOL(default_idle, pm_idle) only when APM demands it
  x86 idle: clarify AMD erratum 400 workaround
  idle governor: Avoid lock acquisition to read pm_qos before entering idle
  cpuidle: menu: fixed wrapping timers at 4.294 seconds

14 files changed:
Documentation/feature-removal-schedule.txt
arch/x86/include/asm/acpi.h
arch/x86/include/asm/idle.h
arch/x86/include/asm/processor.h
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/process.c
arch/x86/kernel/smpboot.c
drivers/acpi/processor_idle.c
drivers/block/floppy.c
drivers/cpuidle/governors/menu.c
include/linux/pm_qos_params.h
kernel/pm_qos_params.c

index ff31b1c..1a9446b 100644 (file)
@@ -6,6 +6,42 @@ be removed from this file.
 
 ---------------------------
 
+What:  x86 floppy disable_hlt
+When:  2012
+Why:   ancient workaround of dubious utility clutters the
+       code used by everybody else.
+Who:   Len Brown <len.brown@intel.com>
+
+---------------------------
+
+What:  CONFIG_APM_CPU_IDLE, and its ability to call APM BIOS in idle
+When:  2012
+Why:   This optional sub-feature of APM is of dubious reliability,
+       and ancient APM laptops are likely better served by calling HLT.
+       Deleting CONFIG_APM_CPU_IDLE allows x86 to stop exporting
+       the pm_idle function pointer to modules.
+Who:   Len Brown <len.brown@intel.com>
+
+----------------------------
+
+What:  x86_32 "no-hlt" cmdline param
+When:  2012
+Why:   remove a branch from idle path, simplify code used by everybody.
+       This option disabled the use of HLT in idle and machine_halt()
+       for hardware that was flakey 15-years ago.  Today we have
+       "idle=poll" that removed HLT from idle, and so if such a machine
+       is still running the upstream kernel, "idle=poll" is likely sufficient.
+Who:   Len Brown <len.brown@intel.com>
+
+----------------------------
+
+What:  x86 "idle=mwait" cmdline param
+When:  2012
+Why:   simplify x86 idle code
+Who:   Len Brown <len.brown@intel.com>
+
+----------------------------
+
 What:  PRISM54
 When:  2.6.34
 
index 416d865..610001d 100644 (file)
@@ -139,7 +139,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate)
            boot_cpu_data.x86_model <= 0x05 &&
            boot_cpu_data.x86_mask < 0x0A)
                return 1;
-       else if (c1e_detected)
+       else if (amd_e400_c1e_detected)
                return 1;
        else
                return max_cstate;
index 38d8737..f49253d 100644 (file)
@@ -16,6 +16,6 @@ static inline void enter_idle(void) { }
 static inline void exit_idle(void) { }
 #endif /* CONFIG_X86_64 */
 
-void c1e_remove_cpu(int cpu);
+void amd_e400_remove_cpu(int cpu);
 
 #endif /* _ASM_X86_IDLE_H */
index 4c25ab4..2193715 100644 (file)
@@ -754,10 +754,10 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
 extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
 
 extern void select_idle_routine(const struct cpuinfo_x86 *c);
-extern void init_c1e_mask(void);
+extern void init_amd_e400_c1e_mask(void);
 
 extern unsigned long           boot_option_idle_override;
-extern bool                    c1e_detected;
+extern bool                    amd_e400_c1e_detected;
 
 enum idle_boot_override {IDLE_NO_OVERRIDE=0, IDLE_HALT, IDLE_NOMWAIT,
                         IDLE_POLL, IDLE_FORCE_MWAIT};
index 3bfa022..965a766 100644 (file)
@@ -361,6 +361,7 @@ struct apm_user {
  * idle percentage above which bios idle calls are done
  */
 #ifdef CONFIG_APM_CPU_IDLE
+#warning deprecated CONFIG_APM_CPU_IDLE will be deleted in 2012
 #define DEFAULT_IDLE_THRESHOLD 95
 #else
 #define DEFAULT_IDLE_THRESHOLD 100
@@ -904,6 +905,7 @@ static void apm_cpu_idle(void)
        unsigned int jiffies_since_last_check = jiffies - last_jiffies;
        unsigned int bucket;
 
+       WARN_ONCE(1, "deprecated apm_cpu_idle will be deleted in 2012");
 recalc:
        if (jiffies_since_last_check > IDLE_CALC_LIMIT) {
                use_apm_idle = 0;
index c39576c..525514c 100644 (file)
@@ -19,6 +19,7 @@
 
 static int __init no_halt(char *s)
 {
+       WARN_ONCE(1, "\"no-hlt\" is deprecated, please use \"idle=poll\"\n");
        boot_cpu_data.hlt_works_ok = 0;
        return 1;
 }
index 53f02f5..22a073d 100644 (file)
@@ -902,7 +902,7 @@ static void vgetcpu_set_mode(void)
 void __init identify_boot_cpu(void)
 {
        identify_cpu(&boot_cpu_data);
-       init_c1e_mask();
+       init_amd_e400_c1e_mask();
 #ifdef CONFIG_X86_32
        sysenter_setup();
        enable_sep_cpu();
index 88a90a9..426a5b6 100644 (file)
@@ -337,7 +337,9 @@ EXPORT_SYMBOL(boot_option_idle_override);
  * Powermanagement idle function, if any..
  */
 void (*pm_idle)(void);
+#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE)
 EXPORT_SYMBOL(pm_idle);
+#endif
 
 #ifdef CONFIG_X86_32
 /*
@@ -397,7 +399,7 @@ void default_idle(void)
                cpu_relax();
        }
 }
-#ifdef CONFIG_APM_MODULE
+#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE)
 EXPORT_SYMBOL(default_idle);
 #endif
 
@@ -535,45 +537,45 @@ int mwait_usable(const struct cpuinfo_x86 *c)
        return (edx & MWAIT_EDX_C1);
 }
 
-bool c1e_detected;
-EXPORT_SYMBOL(c1e_detected);
+bool amd_e400_c1e_detected;
+EXPORT_SYMBOL(amd_e400_c1e_detected);
 
-static cpumask_var_t c1e_mask;
+static cpumask_var_t amd_e400_c1e_mask;
 
-void c1e_remove_cpu(int cpu)
+void amd_e400_remove_cpu(int cpu)
 {
-       if (c1e_mask != NULL)
-               cpumask_clear_cpu(cpu, c1e_mask);
+       if (amd_e400_c1e_mask != NULL)
+               cpumask_clear_cpu(cpu, amd_e400_c1e_mask);
 }
 
 /*
- * C1E aware idle routine. We check for C1E active in the interrupt
+ * AMD Erratum 400 aware idle routine. We check for C1E active in the interrupt
  * pending message MSR. If we detect C1E, then we handle it the same
  * way as C3 power states (local apic timer and TSC stop)
  */
-static void c1e_idle(void)
+static void amd_e400_idle(void)
 {
        if (need_resched())
                return;
 
-       if (!c1e_detected) {
+       if (!amd_e400_c1e_detected) {
                u32 lo, hi;
 
                rdmsr(MSR_K8_INT_PENDING_MSG, lo, hi);
 
                if (lo & K8_INTP_C1E_ACTIVE_MASK) {
-                       c1e_detected = true;
+                       amd_e400_c1e_detected = true;
                        if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
                                mark_tsc_unstable("TSC halt in AMD C1E");
                        printk(KERN_INFO "System has AMD C1E enabled\n");
                }
        }
 
-       if (c1e_detected) {
+       if (amd_e400_c1e_detected) {
                int cpu = smp_processor_id();
 
-               if (!cpumask_test_cpu(cpu, c1e_mask)) {
-                       cpumask_set_cpu(cpu, c1e_mask);
+               if (!cpumask_test_cpu(cpu, amd_e400_c1e_mask)) {
+                       cpumask_set_cpu(cpu, amd_e400_c1e_mask);
                        /*
                         * Force broadcast so ACPI can not interfere.
                         */
@@ -616,17 +618,17 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
                pm_idle = mwait_idle;
        } else if (cpu_has_amd_erratum(amd_erratum_400)) {
                /* E400: APIC timer interrupt does not wake up CPU from C1e */
-               printk(KERN_INFO "using C1E aware idle routine\n");
-               pm_idle = c1e_idle;
+               printk(KERN_INFO "using AMD E400 aware idle routine\n");
+               pm_idle = amd_e400_idle;
        } else
                pm_idle = default_idle;
 }
 
-void __init init_c1e_mask(void)
+void __init init_amd_e400_c1e_mask(void)
 {
-       /* If we're using c1e_idle, we need to allocate c1e_mask. */
-       if (pm_idle == c1e_idle)
-               zalloc_cpumask_var(&c1e_mask, GFP_KERNEL);
+       /* If we're using amd_e400_idle, we need to allocate amd_e400_c1e_mask. */
+       if (pm_idle == amd_e400_idle)
+               zalloc_cpumask_var(&amd_e400_c1e_mask, GFP_KERNEL);
 }
 
 static int __init idle_setup(char *str)
@@ -640,6 +642,7 @@ static int __init idle_setup(char *str)
                boot_option_idle_override = IDLE_POLL;
        } else if (!strcmp(str, "mwait")) {
                boot_option_idle_override = IDLE_FORCE_MWAIT;
+               WARN_ONCE(1, "\idle=mwait\" will be removed in 2012\"\n");
        } else if (!strcmp(str, "halt")) {
                /*
                 * When the boot option of idle=halt is added, halt is
index a3c430b..eefd967 100644 (file)
@@ -1307,7 +1307,7 @@ void play_dead_common(void)
 {
        idle_task_exit();
        reset_lazy_tlbstate();
-       c1e_remove_cpu(raw_smp_processor_id());
+       amd_e400_remove_cpu(raw_smp_processor_id());
 
        mb();
        /* Ack it */
index d615b7d..431ab11 100644 (file)
@@ -161,7 +161,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
        if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT))
                return;
 
-       if (c1e_detected)
+       if (amd_e400_c1e_detected)
                type = ACPI_STATE_C1;
 
        /*
index db8f885..98de8f4 100644 (file)
@@ -1038,6 +1038,7 @@ static void floppy_disable_hlt(void)
 {
        unsigned long flags;
 
+       WARN_ONCE(1, "floppy_disable_hlt() scheduled for removal in 2012");
        spin_lock_irqsave(&floppy_hlt_lock, flags);
        if (!hlt_disabled) {
                hlt_disabled = 1;
index f508690..c47f3d0 100644 (file)
@@ -237,6 +237,7 @@ static int menu_select(struct cpuidle_device *dev)
        unsigned int power_usage = -1;
        int i;
        int multiplier;
+       struct timespec t;
 
        if (data->needs_update) {
                menu_update(dev);
@@ -251,8 +252,9 @@ static int menu_select(struct cpuidle_device *dev)
                return 0;
 
        /* determine the expected residency time, round up */
+       t = ktime_to_timespec(tick_nohz_get_sleep_length());
        data->expected_us =
-           DIV_ROUND_UP((u32)ktime_to_ns(tick_nohz_get_sleep_length()), 1000);
+               t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;
 
 
        data->bucket = which_bucket(data->expected_us);
index 77cbddb..a7d87f9 100644 (file)
 #define PM_QOS_NUM_CLASSES 4
 #define PM_QOS_DEFAULT_VALUE -1
 
+#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE       (2000 * USEC_PER_SEC)
+#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE       (2000 * USEC_PER_SEC)
+#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE        0
+
 struct pm_qos_request_list {
        struct plist_node list;
        int pm_qos_class;
index fd8d1e0..6824ca7 100644 (file)
@@ -54,11 +54,17 @@ enum pm_qos_type {
        PM_QOS_MIN              /* return the smallest value */
 };
 
+/*
+ * Note: The lockless read path depends on the CPU accessing
+ * target_value atomically.  Atomic access is only guaranteed on all CPU
+ * types linux supports for 32 bit quantites
+ */
 struct pm_qos_object {
        struct plist_head requests;
        struct blocking_notifier_head *notifiers;
        struct miscdevice pm_qos_power_miscdev;
        char *name;
+       s32 target_value;       /* Do not change to 64 bit */
        s32 default_value;
        enum pm_qos_type type;
 };
@@ -71,7 +77,8 @@ static struct pm_qos_object cpu_dma_pm_qos = {
        .requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests, pm_qos_lock),
        .notifiers = &cpu_dma_lat_notifier,
        .name = "cpu_dma_latency",
-       .default_value = 2000 * USEC_PER_SEC,
+       .target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
+       .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
        .type = PM_QOS_MIN,
 };
 
@@ -80,7 +87,8 @@ static struct pm_qos_object network_lat_pm_qos = {
        .requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests, pm_qos_lock),
        .notifiers = &network_lat_notifier,
        .name = "network_latency",
-       .default_value = 2000 * USEC_PER_SEC,
+       .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
+       .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
        .type = PM_QOS_MIN
 };
 
@@ -90,7 +98,8 @@ static struct pm_qos_object network_throughput_pm_qos = {
        .requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests, pm_qos_lock),
        .notifiers = &network_throughput_notifier,
        .name = "network_throughput",
-       .default_value = 0,
+       .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
+       .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
        .type = PM_QOS_MAX,
 };
 
@@ -136,6 +145,16 @@ static inline int pm_qos_get_value(struct pm_qos_object *o)
        }
 }
 
+static inline s32 pm_qos_read_value(struct pm_qos_object *o)
+{
+       return o->target_value;
+}
+
+static inline void pm_qos_set_value(struct pm_qos_object *o, s32 value)
+{
+       o->target_value = value;
+}
+
 static void update_target(struct pm_qos_object *o, struct plist_node *node,
                          int del, int value)
 {
@@ -160,6 +179,7 @@ static void update_target(struct pm_qos_object *o, struct plist_node *node,
                plist_add(node, &o->requests);
        }
        curr_value = pm_qos_get_value(o);
+       pm_qos_set_value(o, curr_value);
        spin_unlock_irqrestore(&pm_qos_lock, flags);
 
        if (prev_value != curr_value)
@@ -194,18 +214,11 @@ static int find_pm_qos_object_by_minor(int minor)
  * pm_qos_request - returns current system wide qos expectation
  * @pm_qos_class: identification of which qos value is requested
  *
- * This function returns the current target value in an atomic manner.
+ * This function returns the current target value.
  */
 int pm_qos_request(int pm_qos_class)
 {
-       unsigned long flags;
-       int value;
-
-       spin_lock_irqsave(&pm_qos_lock, flags);
-       value = pm_qos_get_value(pm_qos_array[pm_qos_class]);
-       spin_unlock_irqrestore(&pm_qos_lock, flags);
-
-       return value;
+       return pm_qos_read_value(pm_qos_array[pm_qos_class]);
 }
 EXPORT_SYMBOL_GPL(pm_qos_request);