diff options
| -rw-r--r-- | arch/x86/kernel/cpu/mcheck/therm_throt.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 63a56d147e4a..db80b577f601 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
| @@ -34,20 +34,30 @@ | |||
| 34 | /* How long to wait between reporting thermal events */ | 34 | /* How long to wait between reporting thermal events */ |
| 35 | #define CHECK_INTERVAL (300 * HZ) | 35 | #define CHECK_INTERVAL (300 * HZ) |
| 36 | 36 | ||
| 37 | static DEFINE_PER_CPU(__u64, next_check) = INITIAL_JIFFIES; | 37 | /* |
| 38 | static DEFINE_PER_CPU(unsigned long, thermal_throttle_count); | 38 | * Current thermal throttling state: |
| 39 | static DEFINE_PER_CPU(bool, thermal_throttle_active); | 39 | */ |
| 40 | struct thermal_state { | ||
| 41 | bool is_throttled; | ||
| 42 | |||
| 43 | u64 next_check; | ||
| 44 | unsigned long throttle_count; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static DEFINE_PER_CPU(struct thermal_state, thermal_state); | ||
| 40 | 48 | ||
| 41 | static atomic_t therm_throt_en = ATOMIC_INIT(0); | 49 | static atomic_t therm_throt_en = ATOMIC_INIT(0); |
| 42 | 50 | ||
| 43 | #ifdef CONFIG_SYSFS | 51 | #ifdef CONFIG_SYSFS |
| 44 | #define define_therm_throt_sysdev_one_ro(_name) \ | 52 | #define define_therm_throt_sysdev_one_ro(_name) \ |
| 45 | static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) | 53 | static SYSDEV_ATTR(_name, 0444, therm_throt_sysdev_show_##_name, NULL) |
| 46 | 54 | ||
| 47 | #define define_therm_throt_sysdev_show_func(name) \ | 55 | #define define_therm_throt_sysdev_show_func(name) \ |
| 48 | static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | 56 | \ |
| 49 | struct sysdev_attribute *attr, \ | 57 | static ssize_t therm_throt_sysdev_show_##name( \ |
| 50 | char *buf) \ | 58 | struct sys_device *dev, \ |
| 59 | struct sysdev_attribute *attr, \ | ||
| 60 | char *buf) \ | ||
| 51 | { \ | 61 | { \ |
| 52 | unsigned int cpu = dev->id; \ | 62 | unsigned int cpu = dev->id; \ |
| 53 | ssize_t ret; \ | 63 | ssize_t ret; \ |
| @@ -55,7 +65,7 @@ static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | |||
| 55 | preempt_disable(); /* CPU hotplug */ \ | 65 | preempt_disable(); /* CPU hotplug */ \ |
| 56 | if (cpu_online(cpu)) \ | 66 | if (cpu_online(cpu)) \ |
| 57 | ret = sprintf(buf, "%lu\n", \ | 67 | ret = sprintf(buf, "%lu\n", \ |
| 58 | per_cpu(thermal_throttle_##name, cpu)); \ | 68 | per_cpu(thermal_state, cpu).name); \ |
| 59 | else \ | 69 | else \ |
| 60 | ret = 0; \ | 70 | ret = 0; \ |
| 61 | preempt_enable(); \ | 71 | preempt_enable(); \ |
| @@ -63,11 +73,11 @@ static ssize_t therm_throt_sysdev_show_##name(struct sys_device *dev, \ | |||
| 63 | return ret; \ | 73 | return ret; \ |
| 64 | } | 74 | } |
| 65 | 75 | ||
| 66 | define_therm_throt_sysdev_show_func(count); | 76 | define_therm_throt_sysdev_show_func(throttle_count); |
| 67 | define_therm_throt_sysdev_one_ro(count); | 77 | define_therm_throt_sysdev_one_ro(throttle_count); |
| 68 | 78 | ||
| 69 | static struct attribute *thermal_throttle_attrs[] = { | 79 | static struct attribute *thermal_throttle_attrs[] = { |
| 70 | &attr_count.attr, | 80 | &attr_throttle_count.attr, |
| 71 | NULL | 81 | NULL |
| 72 | }; | 82 | }; |
| 73 | 83 | ||
| @@ -93,33 +103,38 @@ static struct attribute_group thermal_throttle_attr_group = { | |||
| 93 | * 1 : Event should be logged further, and a message has been | 103 | * 1 : Event should be logged further, and a message has been |
| 94 | * printed to the syslog. | 104 | * printed to the syslog. |
| 95 | */ | 105 | */ |
| 96 | static int therm_throt_process(int curr) | 106 | static int therm_throt_process(bool is_throttled) |
| 97 | { | 107 | { |
| 98 | unsigned int cpu = smp_processor_id(); | 108 | struct thermal_state *state; |
| 99 | __u64 tmp_jiffs = get_jiffies_64(); | 109 | unsigned int this_cpu; |
| 100 | bool was_throttled = __get_cpu_var(thermal_throttle_active); | 110 | bool was_throttled; |
| 101 | bool is_throttled = __get_cpu_var(thermal_throttle_active) = curr; | 111 | u64 now; |
| 112 | |||
| 113 | this_cpu = smp_processor_id(); | ||
| 114 | now = get_jiffies_64(); | ||
| 115 | state = &per_cpu(thermal_state, this_cpu); | ||
| 116 | |||
| 117 | was_throttled = state->is_throttled; | ||
| 118 | state->is_throttled = is_throttled; | ||
| 102 | 119 | ||
| 103 | if (is_throttled) | 120 | if (is_throttled) |
| 104 | __get_cpu_var(thermal_throttle_count)++; | 121 | state->throttle_count++; |
| 105 | 122 | ||
| 106 | if (!(was_throttled ^ is_throttled) && | 123 | if (!(was_throttled ^ is_throttled) && |
| 107 | time_before64(tmp_jiffs, __get_cpu_var(next_check))) | 124 | time_before64(now, state->next_check)) |
| 108 | return 0; | 125 | return 0; |
| 109 | 126 | ||
| 110 | __get_cpu_var(next_check) = tmp_jiffs + CHECK_INTERVAL; | 127 | state->next_check = now + CHECK_INTERVAL; |
| 111 | 128 | ||
| 112 | /* if we just entered the thermal event */ | 129 | /* if we just entered the thermal event */ |
| 113 | if (is_throttled) { | 130 | if (is_throttled) { |
| 114 | printk(KERN_CRIT "CPU%d: Temperature above threshold, " | 131 | printk(KERN_CRIT "CPU%d: Temperature above threshold, cpu clock throttled (total events = %lu)\n", this_cpu, state->throttle_count); |
| 115 | "cpu clock throttled (total events = %lu)\n", | ||
| 116 | cpu, __get_cpu_var(thermal_throttle_count)); | ||
| 117 | 132 | ||
| 118 | add_taint(TAINT_MACHINE_CHECK); | 133 | add_taint(TAINT_MACHINE_CHECK); |
| 119 | return 1; | 134 | return 1; |
| 120 | } | 135 | } |
| 121 | if (was_throttled) { | 136 | if (was_throttled) { |
| 122 | printk(KERN_INFO "CPU%d: Temperature/speed normal\n", cpu); | 137 | printk(KERN_INFO "CPU%d: Temperature/speed normal\n", this_cpu); |
| 123 | return 1; | 138 | return 1; |
| 124 | } | 139 | } |
| 125 | 140 | ||
| @@ -213,7 +228,7 @@ static void intel_thermal_interrupt(void) | |||
| 213 | __u64 msr_val; | 228 | __u64 msr_val; |
| 214 | 229 | ||
| 215 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); | 230 | rdmsrl(MSR_IA32_THERM_STATUS, msr_val); |
| 216 | if (therm_throt_process(msr_val & THERM_STATUS_PROCHOT)) | 231 | if (therm_throt_process((msr_val & THERM_STATUS_PROCHOT) != 0)) |
| 217 | mce_log_therm_throt_event(msr_val); | 232 | mce_log_therm_throt_event(msr_val); |
| 218 | } | 233 | } |
| 219 | 234 | ||
