diff options
45 files changed, 1212 insertions, 491 deletions
diff --git a/Documentation/ABI/testing/sysfs-firmware-acpi b/Documentation/ABI/testing/sysfs-firmware-acpi index 4f9ba3c2fca7..dd930c8db41f 100644 --- a/Documentation/ABI/testing/sysfs-firmware-acpi +++ b/Documentation/ABI/testing/sysfs-firmware-acpi | |||
@@ -1,3 +1,23 @@ | |||
1 | What: /sys/firmware/acpi/bgrt/ | ||
2 | Date: January 2012 | ||
3 | Contact: Matthew Garrett <mjg@redhat.com> | ||
4 | Description: | ||
5 | The BGRT is an ACPI 5.0 feature that allows the OS | ||
6 | to obtain a copy of the firmware boot splash and | ||
7 | some associated metadata. This is intended to be used | ||
8 | by boot splash applications in order to interact with | ||
9 | the firmware boot splash in order to avoid jarring | ||
10 | transitions. | ||
11 | |||
12 | image: The image bitmap. Currently a 32-bit BMP. | ||
13 | status: 1 if the image is valid, 0 if firmware invalidated it. | ||
14 | type: 0 indicates image is in BMP format. | ||
15 | version: The version of the BGRT. Currently 1. | ||
16 | xoffset: The number of pixels between the left of the screen | ||
17 | and the left edge of the image. | ||
18 | yoffset: The number of pixels between the top of the screen | ||
19 | and the top edge of the image. | ||
20 | |||
1 | What: /sys/firmware/acpi/interrupts/ | 21 | What: /sys/firmware/acpi/interrupts/ |
2 | Date: February 2008 | 22 | Date: February 2008 |
3 | Contact: Len Brown <lenb@kernel.org> | 23 | Contact: Len Brown <lenb@kernel.org> |
diff --git a/Documentation/cpuidle/sysfs.txt b/Documentation/cpuidle/sysfs.txt index 50d7b1642759..9d28a3406e74 100644 --- a/Documentation/cpuidle/sysfs.txt +++ b/Documentation/cpuidle/sysfs.txt | |||
@@ -36,6 +36,7 @@ drwxr-xr-x 2 root root 0 Feb 8 10:42 state3 | |||
36 | /sys/devices/system/cpu/cpu0/cpuidle/state0: | 36 | /sys/devices/system/cpu/cpu0/cpuidle/state0: |
37 | total 0 | 37 | total 0 |
38 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 38 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
39 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
39 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 40 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
40 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 41 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
41 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 42 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
@@ -45,6 +46,7 @@ total 0 | |||
45 | /sys/devices/system/cpu/cpu0/cpuidle/state1: | 46 | /sys/devices/system/cpu/cpu0/cpuidle/state1: |
46 | total 0 | 47 | total 0 |
47 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 48 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
49 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
48 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 50 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
49 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 51 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
50 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 52 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
@@ -54,6 +56,7 @@ total 0 | |||
54 | /sys/devices/system/cpu/cpu0/cpuidle/state2: | 56 | /sys/devices/system/cpu/cpu0/cpuidle/state2: |
55 | total 0 | 57 | total 0 |
56 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 58 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
59 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
57 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 60 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
58 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 61 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
59 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 62 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
@@ -63,6 +66,7 @@ total 0 | |||
63 | /sys/devices/system/cpu/cpu0/cpuidle/state3: | 66 | /sys/devices/system/cpu/cpu0/cpuidle/state3: |
64 | total 0 | 67 | total 0 |
65 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc | 68 | -r--r--r-- 1 root root 4096 Feb 8 10:42 desc |
69 | -rw-r--r-- 1 root root 4096 Feb 8 10:42 disable | ||
66 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency | 70 | -r--r--r-- 1 root root 4096 Feb 8 10:42 latency |
67 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name | 71 | -r--r--r-- 1 root root 4096 Feb 8 10:42 name |
68 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power | 72 | -r--r--r-- 1 root root 4096 Feb 8 10:42 power |
@@ -72,6 +76,7 @@ total 0 | |||
72 | 76 | ||
73 | 77 | ||
74 | * desc : Small description about the idle state (string) | 78 | * desc : Small description about the idle state (string) |
79 | * disable : Option to disable this idle state (bool) | ||
75 | * latency : Latency to exit out of this idle state (in microseconds) | 80 | * latency : Latency to exit out of this idle state (in microseconds) |
76 | * name : Name of the idle state (string) | 81 | * name : Name of the idle state (string) |
77 | * power : Power consumed while in this idle state (in milliwatts) | 82 | * power : Power consumed while in this idle state (in milliwatts) |
diff --git a/arch/arm/include/asm/cpuidle.h b/arch/arm/include/asm/cpuidle.h new file mode 100644 index 000000000000..2fca60ab513a --- /dev/null +++ b/arch/arm/include/asm/cpuidle.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __ASM_ARM_CPUIDLE_H | ||
2 | #define __ASM_ARM_CPUIDLE_H | ||
3 | |||
4 | #ifdef CONFIG_CPU_IDLE | ||
5 | extern int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | ||
6 | struct cpuidle_driver *drv, int index); | ||
7 | #else | ||
8 | static inline int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | ||
9 | struct cpuidle_driver *drv, int index) { return -ENODEV; } | ||
10 | #endif | ||
11 | |||
12 | /* Common ARM WFI state */ | ||
13 | #define ARM_CPUIDLE_WFI_STATE_PWR(p) {\ | ||
14 | .enter = arm_cpuidle_simple_enter,\ | ||
15 | .exit_latency = 1,\ | ||
16 | .target_residency = 1,\ | ||
17 | .power_usage = p,\ | ||
18 | .flags = CPUIDLE_FLAG_TIME_VALID,\ | ||
19 | .name = "WFI",\ | ||
20 | .desc = "ARM WFI",\ | ||
21 | } | ||
22 | |||
23 | /* | ||
24 | * in case power_specified == 1, give a default WFI power value needed | ||
25 | * by some governors | ||
26 | */ | ||
27 | #define ARM_CPUIDLE_WFI_STATE ARM_CPUIDLE_WFI_STATE_PWR(UINT_MAX) | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 43b740d0e374..940c27fde498 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile | |||
@@ -21,7 +21,7 @@ obj-$(CONFIG_DEPRECATED_PARAM_STRUCT) += compat.o | |||
21 | 21 | ||
22 | obj-$(CONFIG_LEDS) += leds.o | 22 | obj-$(CONFIG_LEDS) += leds.o |
23 | obj-$(CONFIG_OC_ETM) += etm.o | 23 | obj-$(CONFIG_OC_ETM) += etm.o |
24 | 24 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | |
25 | obj-$(CONFIG_ISA_DMA_API) += dma.o | 25 | obj-$(CONFIG_ISA_DMA_API) += dma.o |
26 | obj-$(CONFIG_ARCH_ACORN) += ecard.o | 26 | obj-$(CONFIG_ARCH_ACORN) += ecard.o |
27 | obj-$(CONFIG_FIQ) += fiq.o fiqasm.o | 27 | obj-$(CONFIG_FIQ) += fiq.o fiqasm.o |
diff --git a/arch/arm/kernel/cpuidle.c b/arch/arm/kernel/cpuidle.c new file mode 100644 index 000000000000..89545f6c8403 --- /dev/null +++ b/arch/arm/kernel/cpuidle.c | |||
@@ -0,0 +1,21 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Linaro Ltd. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/cpuidle.h> | ||
13 | #include <asm/proc-fns.h> | ||
14 | |||
15 | int arm_cpuidle_simple_enter(struct cpuidle_device *dev, | ||
16 | struct cpuidle_driver *drv, int index) | ||
17 | { | ||
18 | cpu_do_idle(); | ||
19 | |||
20 | return index; | ||
21 | } | ||
diff --git a/arch/arm/mach-at91/cpuidle.c b/arch/arm/mach-at91/cpuidle.c index a851e6c98421..d40b3f317f7f 100644 --- a/arch/arm/mach-at91/cpuidle.c +++ b/arch/arm/mach-at91/cpuidle.c | |||
@@ -17,9 +17,10 @@ | |||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/cpuidle.h> | 19 | #include <linux/cpuidle.h> |
20 | #include <asm/proc-fns.h> | ||
21 | #include <linux/io.h> | 20 | #include <linux/io.h> |
22 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <asm/proc-fns.h> | ||
23 | #include <asm/cpuidle.h> | ||
23 | 24 | ||
24 | #include "pm.h" | 25 | #include "pm.h" |
25 | 26 | ||
@@ -27,66 +28,46 @@ | |||
27 | 28 | ||
28 | static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device); | 29 | static DEFINE_PER_CPU(struct cpuidle_device, at91_cpuidle_device); |
29 | 30 | ||
30 | static struct cpuidle_driver at91_idle_driver = { | ||
31 | .name = "at91_idle", | ||
32 | .owner = THIS_MODULE, | ||
33 | }; | ||
34 | |||
35 | /* Actual code that puts the SoC in different idle states */ | 31 | /* Actual code that puts the SoC in different idle states */ |
36 | static int at91_enter_idle(struct cpuidle_device *dev, | 32 | static int at91_enter_idle(struct cpuidle_device *dev, |
37 | struct cpuidle_driver *drv, | 33 | struct cpuidle_driver *drv, |
38 | int index) | 34 | int index) |
39 | { | 35 | { |
40 | struct timeval before, after; | ||
41 | int idle_time; | ||
42 | u32 saved_lpr; | 36 | u32 saved_lpr; |
43 | 37 | ||
44 | local_irq_disable(); | 38 | __asm__("b 1f; .align 5; 1:\n" |
45 | do_gettimeofday(&before); | 39 | " mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ |
46 | if (index == 0) | 40 | |
47 | /* Wait for interrupt state */ | 41 | saved_lpr = sdram_selfrefresh_enable(); |
48 | cpu_do_idle(); | 42 | cpu_do_idle(); |
49 | else if (index == 1) { | 43 | sdram_selfrefresh_disable(saved_lpr); |
50 | asm("b 1f; .align 5; 1:"); | ||
51 | asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ | ||
52 | saved_lpr = sdram_selfrefresh_enable(); | ||
53 | cpu_do_idle(); | ||
54 | sdram_selfrefresh_disable(saved_lpr); | ||
55 | } | ||
56 | do_gettimeofday(&after); | ||
57 | local_irq_enable(); | ||
58 | idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + | ||
59 | (after.tv_usec - before.tv_usec); | ||
60 | 44 | ||
61 | dev->last_residency = idle_time; | ||
62 | return index; | 45 | return index; |
63 | } | 46 | } |
64 | 47 | ||
48 | static struct cpuidle_driver at91_idle_driver = { | ||
49 | .name = "at91_idle", | ||
50 | .owner = THIS_MODULE, | ||
51 | .en_core_tk_irqen = 1, | ||
52 | .states[0] = ARM_CPUIDLE_WFI_STATE, | ||
53 | .states[1] = { | ||
54 | .enter = at91_enter_idle, | ||
55 | .exit_latency = 10, | ||
56 | .target_residency = 100000, | ||
57 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
58 | .name = "RAM_SR", | ||
59 | .desc = "WFI and DDR Self Refresh", | ||
60 | }, | ||
61 | .state_count = AT91_MAX_STATES, | ||
62 | }; | ||
63 | |||
65 | /* Initialize CPU idle by registering the idle states */ | 64 | /* Initialize CPU idle by registering the idle states */ |
66 | static int at91_init_cpuidle(void) | 65 | static int at91_init_cpuidle(void) |
67 | { | 66 | { |
68 | struct cpuidle_device *device; | 67 | struct cpuidle_device *device; |
69 | struct cpuidle_driver *driver = &at91_idle_driver; | ||
70 | 68 | ||
71 | device = &per_cpu(at91_cpuidle_device, smp_processor_id()); | 69 | device = &per_cpu(at91_cpuidle_device, smp_processor_id()); |
72 | device->state_count = AT91_MAX_STATES; | 70 | device->state_count = AT91_MAX_STATES; |
73 | driver->state_count = AT91_MAX_STATES; | ||
74 | |||
75 | /* Wait for interrupt state */ | ||
76 | driver->states[0].enter = at91_enter_idle; | ||
77 | driver->states[0].exit_latency = 1; | ||
78 | driver->states[0].target_residency = 10000; | ||
79 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | ||
80 | strcpy(driver->states[0].name, "WFI"); | ||
81 | strcpy(driver->states[0].desc, "Wait for interrupt"); | ||
82 | |||
83 | /* Wait for interrupt and RAM self refresh state */ | ||
84 | driver->states[1].enter = at91_enter_idle; | ||
85 | driver->states[1].exit_latency = 10; | ||
86 | driver->states[1].target_residency = 10000; | ||
87 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | ||
88 | strcpy(driver->states[1].name, "RAM_SR"); | ||
89 | strcpy(driver->states[1].desc, "WFI and RAM Self Refresh"); | ||
90 | 71 | ||
91 | cpuidle_register_driver(&at91_idle_driver); | 72 | cpuidle_register_driver(&at91_idle_driver); |
92 | 73 | ||
diff --git a/arch/arm/mach-davinci/cpuidle.c b/arch/arm/mach-davinci/cpuidle.c index a30c7c5a6d83..9107691adbdb 100644 --- a/arch/arm/mach-davinci/cpuidle.c +++ b/arch/arm/mach-davinci/cpuidle.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <asm/proc-fns.h> | 20 | #include <asm/proc-fns.h> |
21 | #include <asm/cpuidle.h> | ||
21 | 22 | ||
22 | #include <mach/cpuidle.h> | 23 | #include <mach/cpuidle.h> |
23 | #include <mach/ddr2.h> | 24 | #include <mach/ddr2.h> |
@@ -30,12 +31,43 @@ struct davinci_ops { | |||
30 | u32 flags; | 31 | u32 flags; |
31 | }; | 32 | }; |
32 | 33 | ||
34 | /* Actual code that puts the SoC in different idle states */ | ||
35 | static int davinci_enter_idle(struct cpuidle_device *dev, | ||
36 | struct cpuidle_driver *drv, | ||
37 | int index) | ||
38 | { | ||
39 | struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; | ||
40 | struct davinci_ops *ops = cpuidle_get_statedata(state_usage); | ||
41 | |||
42 | if (ops && ops->enter) | ||
43 | ops->enter(ops->flags); | ||
44 | |||
45 | index = cpuidle_wrap_enter(dev, drv, index, | ||
46 | arm_cpuidle_simple_enter); | ||
47 | |||
48 | if (ops && ops->exit) | ||
49 | ops->exit(ops->flags); | ||
50 | |||
51 | return index; | ||
52 | } | ||
53 | |||
33 | /* fields in davinci_ops.flags */ | 54 | /* fields in davinci_ops.flags */ |
34 | #define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) | 55 | #define DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN BIT(0) |
35 | 56 | ||
36 | static struct cpuidle_driver davinci_idle_driver = { | 57 | static struct cpuidle_driver davinci_idle_driver = { |
37 | .name = "cpuidle-davinci", | 58 | .name = "cpuidle-davinci", |
38 | .owner = THIS_MODULE, | 59 | .owner = THIS_MODULE, |
60 | .en_core_tk_irqen = 1, | ||
61 | .states[0] = ARM_CPUIDLE_WFI_STATE, | ||
62 | .states[1] = { | ||
63 | .enter = davinci_enter_idle, | ||
64 | .exit_latency = 10, | ||
65 | .target_residency = 100000, | ||
66 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
67 | .name = "DDR SR", | ||
68 | .desc = "WFI and DDR Self Refresh", | ||
69 | }, | ||
70 | .state_count = DAVINCI_CPUIDLE_MAX_STATES, | ||
39 | }; | 71 | }; |
40 | 72 | ||
41 | static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); | 73 | static DEFINE_PER_CPU(struct cpuidle_device, davinci_cpuidle_device); |
@@ -77,41 +109,10 @@ static struct davinci_ops davinci_states[DAVINCI_CPUIDLE_MAX_STATES] = { | |||
77 | }, | 109 | }, |
78 | }; | 110 | }; |
79 | 111 | ||
80 | /* Actual code that puts the SoC in different idle states */ | ||
81 | static int davinci_enter_idle(struct cpuidle_device *dev, | ||
82 | struct cpuidle_driver *drv, | ||
83 | int index) | ||
84 | { | ||
85 | struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; | ||
86 | struct davinci_ops *ops = cpuidle_get_statedata(state_usage); | ||
87 | struct timeval before, after; | ||
88 | int idle_time; | ||
89 | |||
90 | local_irq_disable(); | ||
91 | do_gettimeofday(&before); | ||
92 | |||
93 | if (ops && ops->enter) | ||
94 | ops->enter(ops->flags); | ||
95 | /* Wait for interrupt state */ | ||
96 | cpu_do_idle(); | ||
97 | if (ops && ops->exit) | ||
98 | ops->exit(ops->flags); | ||
99 | |||
100 | do_gettimeofday(&after); | ||
101 | local_irq_enable(); | ||
102 | idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + | ||
103 | (after.tv_usec - before.tv_usec); | ||
104 | |||
105 | dev->last_residency = idle_time; | ||
106 | |||
107 | return index; | ||
108 | } | ||
109 | |||
110 | static int __init davinci_cpuidle_probe(struct platform_device *pdev) | 112 | static int __init davinci_cpuidle_probe(struct platform_device *pdev) |
111 | { | 113 | { |
112 | int ret; | 114 | int ret; |
113 | struct cpuidle_device *device; | 115 | struct cpuidle_device *device; |
114 | struct cpuidle_driver *driver = &davinci_idle_driver; | ||
115 | struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; | 116 | struct davinci_cpuidle_config *pdata = pdev->dev.platform_data; |
116 | 117 | ||
117 | device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); | 118 | device = &per_cpu(davinci_cpuidle_device, smp_processor_id()); |
@@ -123,27 +124,11 @@ static int __init davinci_cpuidle_probe(struct platform_device *pdev) | |||
123 | 124 | ||
124 | ddr2_reg_base = pdata->ddr2_ctlr_base; | 125 | ddr2_reg_base = pdata->ddr2_ctlr_base; |
125 | 126 | ||
126 | /* Wait for interrupt state */ | ||
127 | driver->states[0].enter = davinci_enter_idle; | ||
128 | driver->states[0].exit_latency = 1; | ||
129 | driver->states[0].target_residency = 10000; | ||
130 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | ||
131 | strcpy(driver->states[0].name, "WFI"); | ||
132 | strcpy(driver->states[0].desc, "Wait for interrupt"); | ||
133 | |||
134 | /* Wait for interrupt and DDR self refresh state */ | ||
135 | driver->states[1].enter = davinci_enter_idle; | ||
136 | driver->states[1].exit_latency = 10; | ||
137 | driver->states[1].target_residency = 10000; | ||
138 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | ||
139 | strcpy(driver->states[1].name, "DDR SR"); | ||
140 | strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); | ||
141 | if (pdata->ddr2_pdown) | 127 | if (pdata->ddr2_pdown) |
142 | davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; | 128 | davinci_states[1].flags |= DAVINCI_CPUIDLE_FLAGS_DDR2_PWDN; |
143 | cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); | 129 | cpuidle_set_statedata(&device->states_usage[1], &davinci_states[1]); |
144 | 130 | ||
145 | device->state_count = DAVINCI_CPUIDLE_MAX_STATES; | 131 | device->state_count = DAVINCI_CPUIDLE_MAX_STATES; |
146 | driver->state_count = DAVINCI_CPUIDLE_MAX_STATES; | ||
147 | 132 | ||
148 | ret = cpuidle_register_driver(&davinci_idle_driver); | 133 | ret = cpuidle_register_driver(&davinci_idle_driver); |
149 | if (ret) { | 134 | if (ret) { |
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/arch/arm/mach-kirkwood/cpuidle.c index 7088180b018b..0f1710941878 100644 --- a/arch/arm/mach-kirkwood/cpuidle.c +++ b/arch/arm/mach-kirkwood/cpuidle.c | |||
@@ -20,77 +20,47 @@ | |||
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/export.h> | 21 | #include <linux/export.h> |
22 | #include <asm/proc-fns.h> | 22 | #include <asm/proc-fns.h> |
23 | #include <asm/cpuidle.h> | ||
23 | #include <mach/kirkwood.h> | 24 | #include <mach/kirkwood.h> |
24 | 25 | ||
25 | #define KIRKWOOD_MAX_STATES 2 | 26 | #define KIRKWOOD_MAX_STATES 2 |
26 | 27 | ||
27 | static struct cpuidle_driver kirkwood_idle_driver = { | ||
28 | .name = "kirkwood_idle", | ||
29 | .owner = THIS_MODULE, | ||
30 | }; | ||
31 | |||
32 | static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); | ||
33 | |||
34 | /* Actual code that puts the SoC in different idle states */ | 28 | /* Actual code that puts the SoC in different idle states */ |
35 | static int kirkwood_enter_idle(struct cpuidle_device *dev, | 29 | static int kirkwood_enter_idle(struct cpuidle_device *dev, |
36 | struct cpuidle_driver *drv, | 30 | struct cpuidle_driver *drv, |
37 | int index) | 31 | int index) |
38 | { | 32 | { |
39 | struct timeval before, after; | 33 | writel(0x7, DDR_OPERATION_BASE); |
40 | int idle_time; | 34 | cpu_do_idle(); |
41 | |||
42 | local_irq_disable(); | ||
43 | do_gettimeofday(&before); | ||
44 | if (index == 0) | ||
45 | /* Wait for interrupt state */ | ||
46 | cpu_do_idle(); | ||
47 | else if (index == 1) { | ||
48 | /* | ||
49 | * Following write will put DDR in self refresh. | ||
50 | * Note that we have 256 cycles before DDR puts it | ||
51 | * self in self-refresh, so the wait-for-interrupt | ||
52 | * call afterwards won't get the DDR from self refresh | ||
53 | * mode. | ||
54 | */ | ||
55 | writel(0x7, DDR_OPERATION_BASE); | ||
56 | cpu_do_idle(); | ||
57 | } | ||
58 | do_gettimeofday(&after); | ||
59 | local_irq_enable(); | ||
60 | idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + | ||
61 | (after.tv_usec - before.tv_usec); | ||
62 | |||
63 | /* Update last residency */ | ||
64 | dev->last_residency = idle_time; | ||
65 | 35 | ||
66 | return index; | 36 | return index; |
67 | } | 37 | } |
68 | 38 | ||
39 | static struct cpuidle_driver kirkwood_idle_driver = { | ||
40 | .name = "kirkwood_idle", | ||
41 | .owner = THIS_MODULE, | ||
42 | .en_core_tk_irqen = 1, | ||
43 | .states[0] = ARM_CPUIDLE_WFI_STATE, | ||
44 | .states[1] = { | ||
45 | .enter = kirkwood_enter_idle, | ||
46 | .exit_latency = 10, | ||
47 | .target_residency = 100000, | ||
48 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
49 | .name = "DDR SR", | ||
50 | .desc = "WFI and DDR Self Refresh", | ||
51 | }, | ||
52 | .state_count = KIRKWOOD_MAX_STATES, | ||
53 | }; | ||
54 | |||
55 | static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device); | ||
56 | |||
69 | /* Initialize CPU idle by registering the idle states */ | 57 | /* Initialize CPU idle by registering the idle states */ |
70 | static int kirkwood_init_cpuidle(void) | 58 | static int kirkwood_init_cpuidle(void) |
71 | { | 59 | { |
72 | struct cpuidle_device *device; | 60 | struct cpuidle_device *device; |
73 | struct cpuidle_driver *driver = &kirkwood_idle_driver; | ||
74 | 61 | ||
75 | device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); | 62 | device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id()); |
76 | device->state_count = KIRKWOOD_MAX_STATES; | 63 | device->state_count = KIRKWOOD_MAX_STATES; |
77 | driver->state_count = KIRKWOOD_MAX_STATES; | ||
78 | |||
79 | /* Wait for interrupt state */ | ||
80 | driver->states[0].enter = kirkwood_enter_idle; | ||
81 | driver->states[0].exit_latency = 1; | ||
82 | driver->states[0].target_residency = 10000; | ||
83 | driver->states[0].flags = CPUIDLE_FLAG_TIME_VALID; | ||
84 | strcpy(driver->states[0].name, "WFI"); | ||
85 | strcpy(driver->states[0].desc, "Wait for interrupt"); | ||
86 | |||
87 | /* Wait for interrupt and DDR self refresh state */ | ||
88 | driver->states[1].enter = kirkwood_enter_idle; | ||
89 | driver->states[1].exit_latency = 10; | ||
90 | driver->states[1].target_residency = 10000; | ||
91 | driver->states[1].flags = CPUIDLE_FLAG_TIME_VALID; | ||
92 | strcpy(driver->states[1].name, "DDR SR"); | ||
93 | strcpy(driver->states[1].desc, "WFI and DDR Self Refresh"); | ||
94 | 64 | ||
95 | cpuidle_register_driver(&kirkwood_idle_driver); | 65 | cpuidle_register_driver(&kirkwood_idle_driver); |
96 | if (cpuidle_register_device(device)) { | 66 | if (cpuidle_register_device(device)) { |
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c index 464cffde58fe..535866489ce3 100644 --- a/arch/arm/mach-omap2/cpuidle34xx.c +++ b/arch/arm/mach-omap2/cpuidle34xx.c | |||
@@ -87,29 +87,14 @@ static int _cpuidle_deny_idle(struct powerdomain *pwrdm, | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | /** | 90 | static int __omap3_enter_idle(struct cpuidle_device *dev, |
91 | * omap3_enter_idle - Programs OMAP3 to enter the specified state | ||
92 | * @dev: cpuidle device | ||
93 | * @drv: cpuidle driver | ||
94 | * @index: the index of state to be entered | ||
95 | * | ||
96 | * Called from the CPUidle framework to program the device to the | ||
97 | * specified target state selected by the governor. | ||
98 | */ | ||
99 | static int omap3_enter_idle(struct cpuidle_device *dev, | ||
100 | struct cpuidle_driver *drv, | 91 | struct cpuidle_driver *drv, |
101 | int index) | 92 | int index) |
102 | { | 93 | { |
103 | struct omap3_idle_statedata *cx = | 94 | struct omap3_idle_statedata *cx = |
104 | cpuidle_get_statedata(&dev->states_usage[index]); | 95 | cpuidle_get_statedata(&dev->states_usage[index]); |
105 | struct timespec ts_preidle, ts_postidle, ts_idle; | ||
106 | u32 mpu_state = cx->mpu_state, core_state = cx->core_state; | 96 | u32 mpu_state = cx->mpu_state, core_state = cx->core_state; |
107 | int idle_time; | ||
108 | |||
109 | /* Used to keep track of the total time in idle */ | ||
110 | getnstimeofday(&ts_preidle); | ||
111 | 97 | ||
112 | local_irq_disable(); | ||
113 | local_fiq_disable(); | 98 | local_fiq_disable(); |
114 | 99 | ||
115 | pwrdm_set_next_pwrst(mpu_pd, mpu_state); | 100 | pwrdm_set_next_pwrst(mpu_pd, mpu_state); |
@@ -148,22 +133,29 @@ static int omap3_enter_idle(struct cpuidle_device *dev, | |||
148 | } | 133 | } |
149 | 134 | ||
150 | return_sleep_time: | 135 | return_sleep_time: |
151 | getnstimeofday(&ts_postidle); | ||
152 | ts_idle = timespec_sub(ts_postidle, ts_preidle); | ||
153 | 136 | ||
154 | local_irq_enable(); | ||
155 | local_fiq_enable(); | 137 | local_fiq_enable(); |
156 | 138 | ||
157 | idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ | ||
158 | USEC_PER_SEC; | ||
159 | |||
160 | /* Update cpuidle counters */ | ||
161 | dev->last_residency = idle_time; | ||
162 | |||
163 | return index; | 139 | return index; |
164 | } | 140 | } |
165 | 141 | ||
166 | /** | 142 | /** |
143 | * omap3_enter_idle - Programs OMAP3 to enter the specified state | ||
144 | * @dev: cpuidle device | ||
145 | * @drv: cpuidle driver | ||
146 | * @index: the index of state to be entered | ||
147 | * | ||
148 | * Called from the CPUidle framework to program the device to the | ||
149 | * specified target state selected by the governor. | ||
150 | */ | ||
151 | static inline int omap3_enter_idle(struct cpuidle_device *dev, | ||
152 | struct cpuidle_driver *drv, | ||
153 | int index) | ||
154 | { | ||
155 | return cpuidle_wrap_enter(dev, drv, index, __omap3_enter_idle); | ||
156 | } | ||
157 | |||
158 | /** | ||
167 | * next_valid_state - Find next valid C-state | 159 | * next_valid_state - Find next valid C-state |
168 | * @dev: cpuidle device | 160 | * @dev: cpuidle device |
169 | * @drv: cpuidle driver | 161 | * @drv: cpuidle driver |
diff --git a/arch/arm/mach-omap2/cpuidle44xx.c b/arch/arm/mach-omap2/cpuidle44xx.c index 72e018b9b260..f386cbe9c889 100644 --- a/arch/arm/mach-omap2/cpuidle44xx.c +++ b/arch/arm/mach-omap2/cpuidle44xx.c | |||
@@ -62,15 +62,9 @@ static int omap4_enter_idle(struct cpuidle_device *dev, | |||
62 | { | 62 | { |
63 | struct omap4_idle_statedata *cx = | 63 | struct omap4_idle_statedata *cx = |
64 | cpuidle_get_statedata(&dev->states_usage[index]); | 64 | cpuidle_get_statedata(&dev->states_usage[index]); |
65 | struct timespec ts_preidle, ts_postidle, ts_idle; | ||
66 | u32 cpu1_state; | 65 | u32 cpu1_state; |
67 | int idle_time; | ||
68 | int cpu_id = smp_processor_id(); | 66 | int cpu_id = smp_processor_id(); |
69 | 67 | ||
70 | /* Used to keep track of the total time in idle */ | ||
71 | getnstimeofday(&ts_preidle); | ||
72 | |||
73 | local_irq_disable(); | ||
74 | local_fiq_disable(); | 68 | local_fiq_disable(); |
75 | 69 | ||
76 | /* | 70 | /* |
@@ -128,26 +122,17 @@ static int omap4_enter_idle(struct cpuidle_device *dev, | |||
128 | if (index > 0) | 122 | if (index > 0) |
129 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); | 123 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu_id); |
130 | 124 | ||
131 | getnstimeofday(&ts_postidle); | ||
132 | ts_idle = timespec_sub(ts_postidle, ts_preidle); | ||
133 | |||
134 | local_irq_enable(); | ||
135 | local_fiq_enable(); | 125 | local_fiq_enable(); |
136 | 126 | ||
137 | idle_time = ts_idle.tv_nsec / NSEC_PER_USEC + ts_idle.tv_sec * \ | ||
138 | USEC_PER_SEC; | ||
139 | |||
140 | /* Update cpuidle counters */ | ||
141 | dev->last_residency = idle_time; | ||
142 | |||
143 | return index; | 127 | return index; |
144 | } | 128 | } |
145 | 129 | ||
146 | DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); | 130 | DEFINE_PER_CPU(struct cpuidle_device, omap4_idle_dev); |
147 | 131 | ||
148 | struct cpuidle_driver omap4_idle_driver = { | 132 | struct cpuidle_driver omap4_idle_driver = { |
149 | .name = "omap4_idle", | 133 | .name = "omap4_idle", |
150 | .owner = THIS_MODULE, | 134 | .owner = THIS_MODULE, |
135 | .en_core_tk_irqen = 1, | ||
151 | }; | 136 | }; |
152 | 137 | ||
153 | static inline void _fill_cstate(struct cpuidle_driver *drv, | 138 | static inline void _fill_cstate(struct cpuidle_driver *drv, |
diff --git a/arch/arm/mach-shmobile/cpuidle.c b/arch/arm/mach-shmobile/cpuidle.c index 1b2334277e85..ca23b202b02d 100644 --- a/arch/arm/mach-shmobile/cpuidle.c +++ b/arch/arm/mach-shmobile/cpuidle.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <asm/system.h> | 16 | #include <asm/system.h> |
17 | #include <asm/cpuidle.h> | ||
17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
18 | 19 | ||
19 | static void shmobile_enter_wfi(void) | 20 | static void shmobile_enter_wfi(void) |
@@ -29,37 +30,19 @@ static int shmobile_cpuidle_enter(struct cpuidle_device *dev, | |||
29 | struct cpuidle_driver *drv, | 30 | struct cpuidle_driver *drv, |
30 | int index) | 31 | int index) |
31 | { | 32 | { |
32 | ktime_t before, after; | ||
33 | |||
34 | before = ktime_get(); | ||
35 | |||
36 | local_irq_disable(); | ||
37 | local_fiq_disable(); | ||
38 | |||
39 | shmobile_cpuidle_modes[index](); | 33 | shmobile_cpuidle_modes[index](); |
40 | 34 | ||
41 | local_irq_enable(); | ||
42 | local_fiq_enable(); | ||
43 | |||
44 | after = ktime_get(); | ||
45 | dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10; | ||
46 | |||
47 | return index; | 35 | return index; |
48 | } | 36 | } |
49 | 37 | ||
50 | static struct cpuidle_device shmobile_cpuidle_dev; | 38 | static struct cpuidle_device shmobile_cpuidle_dev; |
51 | static struct cpuidle_driver shmobile_cpuidle_driver = { | 39 | static struct cpuidle_driver shmobile_cpuidle_driver = { |
52 | .name = "shmobile_cpuidle", | 40 | .name = "shmobile_cpuidle", |
53 | .owner = THIS_MODULE, | 41 | .owner = THIS_MODULE, |
54 | .states[0] = { | 42 | .en_core_tk_irqen = 1, |
55 | .name = "C1", | 43 | .states[0] = ARM_CPUIDLE_WFI_STATE, |
56 | .desc = "WFI", | 44 | .safe_state_index = 0, /* C1 */ |
57 | .exit_latency = 1, | 45 | .state_count = 1, |
58 | .target_residency = 1 * 2, | ||
59 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
60 | }, | ||
61 | .safe_state_index = 0, /* C1 */ | ||
62 | .state_count = 1, | ||
63 | }; | 46 | }; |
64 | 47 | ||
65 | void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); | 48 | void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv); |
diff --git a/arch/sh/kernel/cpu/shmobile/cpuidle.c b/arch/sh/kernel/cpu/shmobile/cpuidle.c index 6d62eb40e750..1ddc876d3b26 100644 --- a/arch/sh/kernel/cpu/shmobile/cpuidle.c +++ b/arch/sh/kernel/cpu/shmobile/cpuidle.c | |||
@@ -29,7 +29,6 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev, | |||
29 | int index) | 29 | int index) |
30 | { | 30 | { |
31 | unsigned long allowed_mode = SUSP_SH_SLEEP; | 31 | unsigned long allowed_mode = SUSP_SH_SLEEP; |
32 | ktime_t before, after; | ||
33 | int requested_state = index; | 32 | int requested_state = index; |
34 | int allowed_state; | 33 | int allowed_state; |
35 | int k; | 34 | int k; |
@@ -47,19 +46,16 @@ static int cpuidle_sleep_enter(struct cpuidle_device *dev, | |||
47 | */ | 46 | */ |
48 | k = min_t(int, allowed_state, requested_state); | 47 | k = min_t(int, allowed_state, requested_state); |
49 | 48 | ||
50 | before = ktime_get(); | ||
51 | sh_mobile_call_standby(cpuidle_mode[k]); | 49 | sh_mobile_call_standby(cpuidle_mode[k]); |
52 | after = ktime_get(); | ||
53 | |||
54 | dev->last_residency = (int)ktime_to_ns(ktime_sub(after, before)) >> 10; | ||
55 | 50 | ||
56 | return k; | 51 | return k; |
57 | } | 52 | } |
58 | 53 | ||
59 | static struct cpuidle_device cpuidle_dev; | 54 | static struct cpuidle_device cpuidle_dev; |
60 | static struct cpuidle_driver cpuidle_driver = { | 55 | static struct cpuidle_driver cpuidle_driver = { |
61 | .name = "sh_idle", | 56 | .name = "sh_idle", |
62 | .owner = THIS_MODULE, | 57 | .owner = THIS_MODULE, |
58 | .en_core_tk_irqen = 1, | ||
63 | }; | 59 | }; |
64 | 60 | ||
65 | void sh_mobile_setup_cpuidle(void) | 61 | void sh_mobile_setup_cpuidle(void) |
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index ce664f33ea8e..bbcc2c389ade 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c | |||
@@ -642,6 +642,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
642 | kfree(buffer.pointer); | 642 | kfree(buffer.pointer); |
643 | buffer.length = ACPI_ALLOCATE_BUFFER; | 643 | buffer.length = ACPI_ALLOCATE_BUFFER; |
644 | buffer.pointer = NULL; | 644 | buffer.pointer = NULL; |
645 | lapic = NULL; | ||
645 | 646 | ||
646 | if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) | 647 | if (!alloc_cpumask_var(&tmp_map, GFP_KERNEL)) |
647 | goto out; | 648 | goto out; |
@@ -650,7 +651,7 @@ static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) | |||
650 | goto free_tmp_map; | 651 | goto free_tmp_map; |
651 | 652 | ||
652 | cpumask_copy(tmp_map, cpu_present_mask); | 653 | cpumask_copy(tmp_map, cpu_present_mask); |
653 | acpi_register_lapic(physid, lapic->lapic_flags & ACPI_MADT_ENABLED); | 654 | acpi_register_lapic(physid, ACPI_MADT_ENABLED); |
654 | 655 | ||
655 | /* | 656 | /* |
656 | * If mp_register_lapic successfully generates a new logical cpu | 657 | * If mp_register_lapic successfully generates a new logical cpu |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 66d250c00d11..93a2a0932b51 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/tboot.h> | 50 | #include <linux/tboot.h> |
51 | #include <linux/stackprotector.h> | 51 | #include <linux/stackprotector.h> |
52 | #include <linux/gfp.h> | 52 | #include <linux/gfp.h> |
53 | #include <linux/cpuidle.h> | ||
53 | 54 | ||
54 | #include <asm/acpi.h> | 55 | #include <asm/acpi.h> |
55 | #include <asm/desc.h> | 56 | #include <asm/desc.h> |
@@ -1422,7 +1423,8 @@ void native_play_dead(void) | |||
1422 | tboot_shutdown(TB_SHUTDOWN_WFS); | 1423 | tboot_shutdown(TB_SHUTDOWN_WFS); |
1423 | 1424 | ||
1424 | mwait_play_dead(); /* Only returns on failure */ | 1425 | mwait_play_dead(); /* Only returns on failure */ |
1425 | hlt_play_dead(); | 1426 | if (cpuidle_play_dead()) |
1427 | hlt_play_dead(); | ||
1426 | } | 1428 | } |
1427 | 1429 | ||
1428 | #else /* ... !CONFIG_HOTPLUG_CPU */ | 1430 | #else /* ... !CONFIG_HOTPLUG_CPU */ |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7556913aba45..47768ff87343 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -384,6 +384,15 @@ config ACPI_CUSTOM_METHOD | |||
384 | load additional kernel modules after boot, this feature may be used | 384 | load additional kernel modules after boot, this feature may be used |
385 | to override that restriction). | 385 | to override that restriction). |
386 | 386 | ||
387 | config ACPI_BGRT | ||
388 | tristate "Boottime Graphics Resource Table support" | ||
389 | default n | ||
390 | help | ||
391 | This driver adds support for exposing the ACPI Boottime Graphics | ||
392 | Resource Table, which allows the operating system to obtain | ||
393 | data from the firmware boot splash. It will appear under | ||
394 | /sys/firmware/acpi/bgrt/ . | ||
395 | |||
387 | source "drivers/acpi/apei/Kconfig" | 396 | source "drivers/acpi/apei/Kconfig" |
388 | 397 | ||
389 | endif # ACPI | 398 | endif # ACPI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 1567028d2038..47199e2a9130 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -62,6 +62,7 @@ obj-$(CONFIG_ACPI_SBS) += sbs.o | |||
62 | obj-$(CONFIG_ACPI_HED) += hed.o | 62 | obj-$(CONFIG_ACPI_HED) += hed.o |
63 | obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o | 63 | obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o |
64 | obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o | 64 | obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o |
65 | obj-$(CONFIG_ACPI_BGRT) += bgrt.o | ||
65 | 66 | ||
66 | # processor has its own "processor." module_param namespace | 67 | # processor has its own "processor." module_param namespace |
67 | processor-y := processor_driver.o processor_throttling.o | 68 | processor-y := processor_driver.o processor_throttling.o |
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index a716fede4f25..ab513a972c95 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c | |||
@@ -74,8 +74,7 @@ acpi_status acpi_reset(void) | |||
74 | 74 | ||
75 | /* Check if the reset register is supported */ | 75 | /* Check if the reset register is supported */ |
76 | 76 | ||
77 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) || | 77 | if (!reset_reg->address) { |
78 | !reset_reg->address) { | ||
79 | return_ACPI_STATUS(AE_NOT_EXIST); | 78 | return_ACPI_STATUS(AE_NOT_EXIST); |
80 | } | 79 | } |
81 | 80 | ||
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index c5d870406f41..4c9c760db4a4 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c | |||
@@ -363,10 +363,6 @@ static void acpi_tb_convert_fadt(void) | |||
363 | u32 address32; | 363 | u32 address32; |
364 | u32 i; | 364 | u32 i; |
365 | 365 | ||
366 | /* Update the local FADT table header length */ | ||
367 | |||
368 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); | ||
369 | |||
370 | /* | 366 | /* |
371 | * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. | 367 | * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary. |
372 | * Later code will always use the X 64-bit field. Also, check for an | 368 | * Later code will always use the X 64-bit field. Also, check for an |
@@ -408,6 +404,10 @@ static void acpi_tb_convert_fadt(void) | |||
408 | acpi_gbl_FADT.boot_flags = 0; | 404 | acpi_gbl_FADT.boot_flags = 0; |
409 | } | 405 | } |
410 | 406 | ||
407 | /* Update the local FADT table header length */ | ||
408 | |||
409 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); | ||
410 | |||
411 | /* | 411 | /* |
412 | * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" | 412 | * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" |
413 | * generic address structures as necessary. Later code will always use | 413 | * generic address structures as necessary. Later code will always use |
diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c new file mode 100644 index 000000000000..8cf6c46e99fb --- /dev/null +++ b/drivers/acpi/bgrt.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Red Hat, Inc <mjg@redhat.com> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/sysfs.h> | ||
14 | #include <acpi/acpi.h> | ||
15 | #include <acpi/acpi_bus.h> | ||
16 | |||
17 | static struct acpi_table_bgrt *bgrt_tab; | ||
18 | static struct kobject *bgrt_kobj; | ||
19 | |||
20 | struct bmp_header { | ||
21 | u16 id; | ||
22 | u32 size; | ||
23 | } __attribute ((packed)); | ||
24 | |||
25 | static struct bmp_header bmp_header; | ||
26 | |||
27 | static ssize_t show_version(struct device *dev, | ||
28 | struct device_attribute *attr, char *buf) | ||
29 | { | ||
30 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->version); | ||
31 | } | ||
32 | static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); | ||
33 | |||
34 | static ssize_t show_status(struct device *dev, | ||
35 | struct device_attribute *attr, char *buf) | ||
36 | { | ||
37 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->status); | ||
38 | } | ||
39 | static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); | ||
40 | |||
41 | static ssize_t show_type(struct device *dev, | ||
42 | struct device_attribute *attr, char *buf) | ||
43 | { | ||
44 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_type); | ||
45 | } | ||
46 | static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | ||
47 | |||
48 | static ssize_t show_xoffset(struct device *dev, | ||
49 | struct device_attribute *attr, char *buf) | ||
50 | { | ||
51 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_x); | ||
52 | } | ||
53 | static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL); | ||
54 | |||
55 | static ssize_t show_yoffset(struct device *dev, | ||
56 | struct device_attribute *attr, char *buf) | ||
57 | { | ||
58 | return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab->image_offset_y); | ||
59 | } | ||
60 | static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); | ||
61 | |||
62 | static ssize_t show_image(struct file *file, struct kobject *kobj, | ||
63 | struct bin_attribute *attr, char *buf, loff_t off, size_t count) | ||
64 | { | ||
65 | int size = attr->size; | ||
66 | void __iomem *image = attr->private; | ||
67 | |||
68 | if (off >= size) { | ||
69 | count = 0; | ||
70 | } else { | ||
71 | if (off + count > size) | ||
72 | count = size - off; | ||
73 | |||
74 | memcpy_fromio(buf, image+off, count); | ||
75 | } | ||
76 | |||
77 | return count; | ||
78 | } | ||
79 | |||
80 | static struct bin_attribute image_attr = { | ||
81 | .attr = { | ||
82 | .name = "image", | ||
83 | .mode = S_IRUGO, | ||
84 | }, | ||
85 | .read = show_image, | ||
86 | }; | ||
87 | |||
88 | static struct attribute *bgrt_attributes[] = { | ||
89 | &dev_attr_version.attr, | ||
90 | &dev_attr_status.attr, | ||
91 | &dev_attr_type.attr, | ||
92 | &dev_attr_xoffset.attr, | ||
93 | &dev_attr_yoffset.attr, | ||
94 | NULL, | ||
95 | }; | ||
96 | |||
97 | static struct attribute_group bgrt_attribute_group = { | ||
98 | .attrs = bgrt_attributes, | ||
99 | }; | ||
100 | |||
101 | static int __init bgrt_init(void) | ||
102 | { | ||
103 | acpi_status status; | ||
104 | int ret; | ||
105 | void __iomem *bgrt; | ||
106 | |||
107 | if (acpi_disabled) | ||
108 | return -ENODEV; | ||
109 | |||
110 | status = acpi_get_table("BGRT", 0, | ||
111 | (struct acpi_table_header **)&bgrt_tab); | ||
112 | |||
113 | if (ACPI_FAILURE(status)) | ||
114 | return -ENODEV; | ||
115 | |||
116 | sysfs_bin_attr_init(&image_attr); | ||
117 | |||
118 | bgrt = ioremap(bgrt_tab->image_address, sizeof(struct bmp_header)); | ||
119 | |||
120 | if (!bgrt) { | ||
121 | ret = -EINVAL; | ||
122 | goto out_err; | ||
123 | } | ||
124 | |||
125 | memcpy_fromio(&bmp_header, bgrt, sizeof(bmp_header)); | ||
126 | image_attr.size = bmp_header.size; | ||
127 | iounmap(bgrt); | ||
128 | |||
129 | image_attr.private = ioremap(bgrt_tab->image_address, image_attr.size); | ||
130 | |||
131 | if (!image_attr.private) { | ||
132 | ret = -EINVAL; | ||
133 | goto out_err; | ||
134 | } | ||
135 | |||
136 | |||
137 | bgrt_kobj = kobject_create_and_add("bgrt", acpi_kobj); | ||
138 | if (!bgrt_kobj) { | ||
139 | ret = -EINVAL; | ||
140 | goto out_iounmap; | ||
141 | } | ||
142 | |||
143 | ret = sysfs_create_group(bgrt_kobj, &bgrt_attribute_group); | ||
144 | if (ret) | ||
145 | goto out_kobject; | ||
146 | |||
147 | ret = sysfs_create_bin_file(bgrt_kobj, &image_attr); | ||
148 | if (ret) | ||
149 | goto out_group; | ||
150 | |||
151 | return 0; | ||
152 | |||
153 | out_group: | ||
154 | sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); | ||
155 | out_kobject: | ||
156 | kobject_put(bgrt_kobj); | ||
157 | out_iounmap: | ||
158 | iounmap(image_attr.private); | ||
159 | out_err: | ||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static void __exit bgrt_exit(void) | ||
164 | { | ||
165 | iounmap(image_attr.private); | ||
166 | sysfs_remove_group(bgrt_kobj, &bgrt_attribute_group); | ||
167 | sysfs_remove_bin_file(bgrt_kobj, &image_attr); | ||
168 | } | ||
169 | |||
170 | module_init(bgrt_init); | ||
171 | module_exit(bgrt_exit); | ||
172 | |||
173 | MODULE_AUTHOR("Matthew Garrett"); | ||
174 | MODULE_DESCRIPTION("BGRT boot graphic support"); | ||
175 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9ecec98bc76e..3263b68cdfa3 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -1010,6 +1010,7 @@ static int __init acpi_bus_init(void) | |||
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | struct kobject *acpi_kobj; | 1012 | struct kobject *acpi_kobj; |
1013 | EXPORT_SYMBOL_GPL(acpi_kobj); | ||
1013 | 1014 | ||
1014 | static int __init acpi_init(void) | 1015 | static int __init acpi_init(void) |
1015 | { | 1016 | { |
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index b19a18dd994f..3268dcfbaa9b 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -812,10 +812,10 @@ static int acpi_ec_add(struct acpi_device *device) | |||
812 | first_ec = ec; | 812 | first_ec = ec; |
813 | device->driver_data = ec; | 813 | device->driver_data = ec; |
814 | 814 | ||
815 | WARN(!request_region(ec->data_addr, 1, "EC data"), | 815 | ret = !!request_region(ec->data_addr, 1, "EC data"); |
816 | "Could not request EC data io port 0x%lx", ec->data_addr); | 816 | WARN(!ret, "Could not request EC data io port 0x%lx", ec->data_addr); |
817 | WARN(!request_region(ec->command_addr, 1, "EC cmd"), | 817 | ret = !!request_region(ec->command_addr, 1, "EC cmd"); |
818 | "Could not request EC cmd io port 0x%lx", ec->command_addr); | 818 | WARN(!ret, "Could not request EC cmd io port 0x%lx", ec->command_addr); |
819 | 819 | ||
820 | pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", | 820 | pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", |
821 | ec->gpe, ec->command_addr, ec->data_addr); | 821 | ec->gpe, ec->command_addr, ec->data_addr); |
diff --git a/drivers/acpi/nvs.c b/drivers/acpi/nvs.c index 7a2035fa8c71..266bc58ce0ce 100644 --- a/drivers/acpi/nvs.c +++ b/drivers/acpi/nvs.c | |||
@@ -95,8 +95,8 @@ static int suspend_nvs_register(unsigned long start, unsigned long size) | |||
95 | { | 95 | { |
96 | struct nvs_page *entry, *next; | 96 | struct nvs_page *entry, *next; |
97 | 97 | ||
98 | pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n", | 98 | pr_info("PM: Registering ACPI NVS region [mem %#010lx-%#010lx] (%ld bytes)\n", |
99 | start, size); | 99 | start, start + size - 1, size); |
100 | 100 | ||
101 | while (size > 0) { | 101 | while (size > 0) { |
102 | unsigned int nr_bytes; | 102 | unsigned int nr_bytes; |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 07d426425b59..9fddb55764f3 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -347,7 +347,7 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) | |||
347 | unsigned long pfn; | 347 | unsigned long pfn; |
348 | 348 | ||
349 | pfn = pg_off >> PAGE_SHIFT; | 349 | pfn = pg_off >> PAGE_SHIFT; |
350 | if (page_is_ram(pfn)) | 350 | if (should_use_kmap(pfn)) |
351 | kunmap(pfn_to_page(pfn)); | 351 | kunmap(pfn_to_page(pfn)); |
352 | else | 352 | else |
353 | iounmap(vaddr); | 353 | iounmap(vaddr); |
@@ -604,7 +604,8 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, | |||
604 | 604 | ||
605 | acpi_irq_handler = handler; | 605 | acpi_irq_handler = handler; |
606 | acpi_irq_context = context; | 606 | acpi_irq_context = context; |
607 | if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) { | 607 | if (request_threaded_irq(irq, NULL, acpi_irq, IRQF_SHARED, "acpi", |
608 | acpi_irq)) { | ||
608 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); | 609 | printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); |
609 | acpi_irq_handler = NULL; | 610 | acpi_irq_handler = NULL; |
610 | return AE_NOT_ACQUIRED; | 611 | return AE_NOT_ACQUIRED; |
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 8ae05ce18500..41de1355edcd 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 | 68 | #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 |
69 | #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 | 69 | #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 |
70 | #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 | 70 | #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 |
71 | #define ACPI_PROCESSOR_DEVICE_HID "ACPI0007" | ||
71 | 72 | ||
72 | #define ACPI_PROCESSOR_LIMIT_USER 0 | 73 | #define ACPI_PROCESSOR_LIMIT_USER 0 |
73 | #define ACPI_PROCESSOR_LIMIT_THERMAL 1 | 74 | #define ACPI_PROCESSOR_LIMIT_THERMAL 1 |
@@ -88,7 +89,7 @@ static int acpi_processor_start(struct acpi_processor *pr); | |||
88 | 89 | ||
89 | static const struct acpi_device_id processor_device_ids[] = { | 90 | static const struct acpi_device_id processor_device_ids[] = { |
90 | {ACPI_PROCESSOR_OBJECT_HID, 0}, | 91 | {ACPI_PROCESSOR_OBJECT_HID, 0}, |
91 | {"ACPI0007", 0}, | 92 | {ACPI_PROCESSOR_DEVICE_HID, 0}, |
92 | {"", 0}, | 93 | {"", 0}, |
93 | }; | 94 | }; |
94 | MODULE_DEVICE_TABLE(acpi, processor_device_ids); | 95 | MODULE_DEVICE_TABLE(acpi, processor_device_ids); |
@@ -535,8 +536,8 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
535 | return -ENOMEM; | 536 | return -ENOMEM; |
536 | 537 | ||
537 | if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { | 538 | if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { |
538 | kfree(pr); | 539 | result = -ENOMEM; |
539 | return -ENOMEM; | 540 | goto err_free_pr; |
540 | } | 541 | } |
541 | 542 | ||
542 | pr->handle = device->handle; | 543 | pr->handle = device->handle; |
@@ -576,7 +577,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
576 | dev = get_cpu_device(pr->id); | 577 | dev = get_cpu_device(pr->id); |
577 | if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) { | 578 | if (sysfs_create_link(&device->dev.kobj, &dev->kobj, "sysdev")) { |
578 | result = -EFAULT; | 579 | result = -EFAULT; |
579 | goto err_free_cpumask; | 580 | goto err_clear_processor; |
580 | } | 581 | } |
581 | 582 | ||
582 | /* | 583 | /* |
@@ -594,9 +595,15 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
594 | 595 | ||
595 | err_remove_sysfs: | 596 | err_remove_sysfs: |
596 | sysfs_remove_link(&device->dev.kobj, "sysdev"); | 597 | sysfs_remove_link(&device->dev.kobj, "sysdev"); |
598 | err_clear_processor: | ||
599 | /* | ||
600 | * processor_device_array is not cleared to allow checks for buggy BIOS | ||
601 | */ | ||
602 | per_cpu(processors, pr->id) = NULL; | ||
597 | err_free_cpumask: | 603 | err_free_cpumask: |
598 | free_cpumask_var(pr->throttling.shared_cpu_map); | 604 | free_cpumask_var(pr->throttling.shared_cpu_map); |
599 | 605 | err_free_pr: | |
606 | kfree(pr); | ||
600 | return result; | 607 | return result; |
601 | } | 608 | } |
602 | 609 | ||
@@ -741,20 +748,46 @@ static void acpi_processor_hotplug_notify(acpi_handle handle, | |||
741 | return; | 748 | return; |
742 | } | 749 | } |
743 | 750 | ||
751 | static acpi_status is_processor_device(acpi_handle handle) | ||
752 | { | ||
753 | struct acpi_device_info *info; | ||
754 | char *hid; | ||
755 | acpi_status status; | ||
756 | |||
757 | status = acpi_get_object_info(handle, &info); | ||
758 | if (ACPI_FAILURE(status)) | ||
759 | return status; | ||
760 | |||
761 | if (info->type == ACPI_TYPE_PROCESSOR) { | ||
762 | kfree(info); | ||
763 | return AE_OK; /* found a processor object */ | ||
764 | } | ||
765 | |||
766 | if (!(info->valid & ACPI_VALID_HID)) { | ||
767 | kfree(info); | ||
768 | return AE_ERROR; | ||
769 | } | ||
770 | |||
771 | hid = info->hardware_id.string; | ||
772 | if ((hid == NULL) || strcmp(hid, ACPI_PROCESSOR_DEVICE_HID)) { | ||
773 | kfree(info); | ||
774 | return AE_ERROR; | ||
775 | } | ||
776 | |||
777 | kfree(info); | ||
778 | return AE_OK; /* found a processor device object */ | ||
779 | } | ||
780 | |||
744 | static acpi_status | 781 | static acpi_status |
745 | processor_walk_namespace_cb(acpi_handle handle, | 782 | processor_walk_namespace_cb(acpi_handle handle, |
746 | u32 lvl, void *context, void **rv) | 783 | u32 lvl, void *context, void **rv) |
747 | { | 784 | { |
748 | acpi_status status; | 785 | acpi_status status; |
749 | int *action = context; | 786 | int *action = context; |
750 | acpi_object_type type = 0; | ||
751 | 787 | ||
752 | status = acpi_get_type(handle, &type); | 788 | status = is_processor_device(handle); |
753 | if (ACPI_FAILURE(status)) | 789 | if (ACPI_FAILURE(status)) |
754 | return (AE_OK); | 790 | return AE_OK; /* not a processor; continue to walk */ |
755 | |||
756 | if (type != ACPI_TYPE_PROCESSOR) | ||
757 | return (AE_OK); | ||
758 | 791 | ||
759 | switch (*action) { | 792 | switch (*action) { |
760 | case INSTALL_NOTIFY_HANDLER: | 793 | case INSTALL_NOTIFY_HANDLER: |
@@ -772,7 +805,8 @@ processor_walk_namespace_cb(acpi_handle handle, | |||
772 | break; | 805 | break; |
773 | } | 806 | } |
774 | 807 | ||
775 | return (AE_OK); | 808 | /* found a processor; skip walking underneath */ |
809 | return AE_CTRL_DEPTH; | ||
776 | } | 810 | } |
777 | 811 | ||
778 | static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr) | 812 | static acpi_status acpi_processor_hotadd_init(struct acpi_processor *pr) |
@@ -830,7 +864,7 @@ void acpi_processor_install_hotplug_notify(void) | |||
830 | { | 864 | { |
831 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | 865 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
832 | int action = INSTALL_NOTIFY_HANDLER; | 866 | int action = INSTALL_NOTIFY_HANDLER; |
833 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, | 867 | acpi_walk_namespace(ACPI_TYPE_ANY, |
834 | ACPI_ROOT_OBJECT, | 868 | ACPI_ROOT_OBJECT, |
835 | ACPI_UINT32_MAX, | 869 | ACPI_UINT32_MAX, |
836 | processor_walk_namespace_cb, NULL, &action, NULL); | 870 | processor_walk_namespace_cb, NULL, &action, NULL); |
@@ -843,7 +877,7 @@ void acpi_processor_uninstall_hotplug_notify(void) | |||
843 | { | 877 | { |
844 | #ifdef CONFIG_ACPI_HOTPLUG_CPU | 878 | #ifdef CONFIG_ACPI_HOTPLUG_CPU |
845 | int action = UNINSTALL_NOTIFY_HANDLER; | 879 | int action = UNINSTALL_NOTIFY_HANDLER; |
846 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, | 880 | acpi_walk_namespace(ACPI_TYPE_ANY, |
847 | ACPI_ROOT_OBJECT, | 881 | ACPI_ROOT_OBJECT, |
848 | ACPI_UINT32_MAX, | 882 | ACPI_UINT32_MAX, |
849 | processor_walk_namespace_cb, NULL, &action, NULL); | 883 | processor_walk_namespace_cb, NULL, &action, NULL); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 0e8e2de2ed3e..b3447f63e46b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -770,6 +770,35 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
770 | return index; | 770 | return index; |
771 | } | 771 | } |
772 | 772 | ||
773 | |||
774 | /** | ||
775 | * acpi_idle_play_dead - enters an ACPI state for long-term idle (i.e. off-lining) | ||
776 | * @dev: the target CPU | ||
777 | * @index: the index of suggested state | ||
778 | */ | ||
779 | static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) | ||
780 | { | ||
781 | struct cpuidle_state_usage *state_usage = &dev->states_usage[index]; | ||
782 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state_usage); | ||
783 | |||
784 | ACPI_FLUSH_CPU_CACHE(); | ||
785 | |||
786 | while (1) { | ||
787 | |||
788 | if (cx->entry_method == ACPI_CSTATE_HALT) | ||
789 | halt(); | ||
790 | else if (cx->entry_method == ACPI_CSTATE_SYSTEMIO) { | ||
791 | inb(cx->address); | ||
792 | /* See comment in acpi_idle_do_entry() */ | ||
793 | inl(acpi_gbl_FADT.xpm_timer_block.address); | ||
794 | } else | ||
795 | return -ENODEV; | ||
796 | } | ||
797 | |||
798 | /* Never reached */ | ||
799 | return 0; | ||
800 | } | ||
801 | |||
773 | /** | 802 | /** |
774 | * acpi_idle_enter_simple - enters an ACPI state without BM handling | 803 | * acpi_idle_enter_simple - enters an ACPI state without BM handling |
775 | * @dev: the target CPU | 804 | * @dev: the target CPU |
@@ -1077,12 +1106,14 @@ static int acpi_processor_setup_cpuidle_states(struct acpi_processor *pr) | |||
1077 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 1106 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
1078 | 1107 | ||
1079 | state->enter = acpi_idle_enter_c1; | 1108 | state->enter = acpi_idle_enter_c1; |
1109 | state->enter_dead = acpi_idle_play_dead; | ||
1080 | drv->safe_state_index = count; | 1110 | drv->safe_state_index = count; |
1081 | break; | 1111 | break; |
1082 | 1112 | ||
1083 | case ACPI_STATE_C2: | 1113 | case ACPI_STATE_C2: |
1084 | state->flags |= CPUIDLE_FLAG_TIME_VALID; | 1114 | state->flags |= CPUIDLE_FLAG_TIME_VALID; |
1085 | state->enter = acpi_idle_enter_simple; | 1115 | state->enter = acpi_idle_enter_simple; |
1116 | state->enter_dead = acpi_idle_play_dead; | ||
1086 | drv->safe_state_index = count; | 1117 | drv->safe_state_index = count; |
1087 | break; | 1118 | break; |
1088 | 1119 | ||
@@ -1159,8 +1190,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1159 | * to make the code that updates C-States be called once. | 1190 | * to make the code that updates C-States be called once. |
1160 | */ | 1191 | */ |
1161 | 1192 | ||
1162 | if (smp_processor_id() == 0 && | 1193 | if (pr->id == 0 && cpuidle_get_driver() == &acpi_idle_driver) { |
1163 | cpuidle_get_driver() == &acpi_idle_driver) { | ||
1164 | 1194 | ||
1165 | cpuidle_pause_and_lock(); | 1195 | cpuidle_pause_and_lock(); |
1166 | /* Protect against cpu-hotplug */ | 1196 | /* Protect against cpu-hotplug */ |
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 3b599abf2b40..641b5450a0db 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c | |||
@@ -57,6 +57,27 @@ ACPI_MODULE_NAME("processor_thermal"); | |||
57 | static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); | 57 | static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); |
58 | static unsigned int acpi_thermal_cpufreq_is_init = 0; | 58 | static unsigned int acpi_thermal_cpufreq_is_init = 0; |
59 | 59 | ||
60 | #define reduction_pctg(cpu) \ | ||
61 | per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu)) | ||
62 | |||
63 | /* | ||
64 | * Emulate "per package data" using per cpu data (which should really be | ||
65 | * provided elsewhere) | ||
66 | * | ||
67 | * Note we can lose a CPU on cpu hotunplug, in this case we forget the state | ||
68 | * temporarily. Fortunately that's not a big issue here (I hope) | ||
69 | */ | ||
70 | static int phys_package_first_cpu(int cpu) | ||
71 | { | ||
72 | int i; | ||
73 | int id = topology_physical_package_id(cpu); | ||
74 | |||
75 | for_each_online_cpu(i) | ||
76 | if (topology_physical_package_id(i) == id) | ||
77 | return i; | ||
78 | return 0; | ||
79 | } | ||
80 | |||
60 | static int cpu_has_cpufreq(unsigned int cpu) | 81 | static int cpu_has_cpufreq(unsigned int cpu) |
61 | { | 82 | { |
62 | struct cpufreq_policy policy; | 83 | struct cpufreq_policy policy; |
@@ -76,7 +97,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, | |||
76 | 97 | ||
77 | max_freq = ( | 98 | max_freq = ( |
78 | policy->cpuinfo.max_freq * | 99 | policy->cpuinfo.max_freq * |
79 | (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) | 100 | (100 - reduction_pctg(policy->cpu) * 20) |
80 | ) / 100; | 101 | ) / 100; |
81 | 102 | ||
82 | cpufreq_verify_within_limits(policy, 0, max_freq); | 103 | cpufreq_verify_within_limits(policy, 0, max_freq); |
@@ -102,16 +123,28 @@ static int cpufreq_get_cur_state(unsigned int cpu) | |||
102 | if (!cpu_has_cpufreq(cpu)) | 123 | if (!cpu_has_cpufreq(cpu)) |
103 | return 0; | 124 | return 0; |
104 | 125 | ||
105 | return per_cpu(cpufreq_thermal_reduction_pctg, cpu); | 126 | return reduction_pctg(cpu); |
106 | } | 127 | } |
107 | 128 | ||
108 | static int cpufreq_set_cur_state(unsigned int cpu, int state) | 129 | static int cpufreq_set_cur_state(unsigned int cpu, int state) |
109 | { | 130 | { |
131 | int i; | ||
132 | |||
110 | if (!cpu_has_cpufreq(cpu)) | 133 | if (!cpu_has_cpufreq(cpu)) |
111 | return 0; | 134 | return 0; |
112 | 135 | ||
113 | per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; | 136 | reduction_pctg(cpu) = state; |
114 | cpufreq_update_policy(cpu); | 137 | |
138 | /* | ||
139 | * Update all the CPUs in the same package because they all | ||
140 | * contribute to the temperature and often share the same | ||
141 | * frequency. | ||
142 | */ | ||
143 | for_each_online_cpu(i) { | ||
144 | if (topology_physical_package_id(i) == | ||
145 | topology_physical_package_id(cpu)) | ||
146 | cpufreq_update_policy(i); | ||
147 | } | ||
115 | return 0; | 148 | return 0; |
116 | } | 149 | } |
117 | 150 | ||
@@ -119,10 +152,6 @@ void acpi_thermal_cpufreq_init(void) | |||
119 | { | 152 | { |
120 | int i; | 153 | int i; |
121 | 154 | ||
122 | for (i = 0; i < nr_cpu_ids; i++) | ||
123 | if (cpu_present(i)) | ||
124 | per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; | ||
125 | |||
126 | i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, | 155 | i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, |
127 | CPUFREQ_POLICY_NOTIFIER); | 156 | CPUFREQ_POLICY_NOTIFIER); |
128 | if (!i) | 157 | if (!i) |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 605a2954ef17..1d02b7b5ade0 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
@@ -769,7 +769,7 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, | |||
769 | u64 *value) | 769 | u64 *value) |
770 | { | 770 | { |
771 | u32 bit_width, bit_offset; | 771 | u32 bit_width, bit_offset; |
772 | u64 ptc_value; | 772 | u32 ptc_value; |
773 | u64 ptc_mask; | 773 | u64 ptc_mask; |
774 | struct acpi_processor_throttling *throttling; | 774 | struct acpi_processor_throttling *throttling; |
775 | int ret = -1; | 775 | int ret = -1; |
@@ -777,12 +777,11 @@ static int acpi_read_throttling_status(struct acpi_processor *pr, | |||
777 | throttling = &pr->throttling; | 777 | throttling = &pr->throttling; |
778 | switch (throttling->status_register.space_id) { | 778 | switch (throttling->status_register.space_id) { |
779 | case ACPI_ADR_SPACE_SYSTEM_IO: | 779 | case ACPI_ADR_SPACE_SYSTEM_IO: |
780 | ptc_value = 0; | ||
781 | bit_width = throttling->status_register.bit_width; | 780 | bit_width = throttling->status_register.bit_width; |
782 | bit_offset = throttling->status_register.bit_offset; | 781 | bit_offset = throttling->status_register.bit_offset; |
783 | 782 | ||
784 | acpi_os_read_port((acpi_io_address) throttling->status_register. | 783 | acpi_os_read_port((acpi_io_address) throttling->status_register. |
785 | address, (u32 *) &ptc_value, | 784 | address, &ptc_value, |
786 | (u32) (bit_width + bit_offset)); | 785 | (u32) (bit_width + bit_offset)); |
787 | ptc_mask = (1 << bit_width) - 1; | 786 | ptc_mask = (1 << bit_width) - 1; |
788 | *value = (u64) ((ptc_value >> bit_offset) & ptc_mask); | 787 | *value = (u64) ((ptc_value >> bit_offset) & ptc_mask); |
diff --git a/drivers/acpi/reboot.c b/drivers/acpi/reboot.c index a6c77e8b37bd..c1d612435939 100644 --- a/drivers/acpi/reboot.c +++ b/drivers/acpi/reboot.c | |||
@@ -23,8 +23,7 @@ void acpi_reboot(void) | |||
23 | /* Is the reset register supported? The spec says we should be | 23 | /* Is the reset register supported? The spec says we should be |
24 | * checking the bit width and bit offset, but Windows ignores | 24 | * checking the bit width and bit offset, but Windows ignores |
25 | * these fields */ | 25 | * these fields */ |
26 | if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER)) | 26 | /* Ignore also acpi_gbl_FADT.flags.ACPI_FADT_RESET_REGISTER */ |
27 | return; | ||
28 | 27 | ||
29 | reset_value = acpi_gbl_FADT.reset_value; | 28 | reset_value = acpi_gbl_FADT.reset_value; |
30 | 29 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 8ab80bafe3f1..5d24a17aa854 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -880,7 +880,6 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
880 | int j; | 880 | int j; |
881 | 881 | ||
882 | device->power.flags.power_resources = 1; | 882 | device->power.flags.power_resources = 1; |
883 | ps->flags.valid = 1; | ||
884 | for (j = 0; j < ps->resources.count; j++) | 883 | for (j = 0; j < ps->resources.count; j++) |
885 | acpi_bus_add_power_resource(ps->resources.handles[j]); | 884 | acpi_bus_add_power_resource(ps->resources.handles[j]); |
886 | } | 885 | } |
@@ -888,10 +887,8 @@ static int acpi_bus_get_power_flags(struct acpi_device *device) | |||
888 | /* Evaluate "_PSx" to see if we can do explicit sets */ | 887 | /* Evaluate "_PSx" to see if we can do explicit sets */ |
889 | object_name[2] = 'S'; | 888 | object_name[2] = 'S'; |
890 | status = acpi_get_handle(device->handle, object_name, &handle); | 889 | status = acpi_get_handle(device->handle, object_name, &handle); |
891 | if (ACPI_SUCCESS(status)) { | 890 | if (ACPI_SUCCESS(status)) |
892 | ps->flags.explicit_set = 1; | 891 | ps->flags.explicit_set = 1; |
893 | ps->flags.valid = 1; | ||
894 | } | ||
895 | 892 | ||
896 | /* State is valid if we have some power control */ | 893 | /* State is valid if we have some power control */ |
897 | if (ps->resources.count || ps->flags.explicit_set) | 894 | if (ps->resources.count || ps->flags.explicit_set) |
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 48fbc647b178..7dbebea1ec31 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c | |||
@@ -941,13 +941,13 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) | |||
941 | if (!tz) | 941 | if (!tz) |
942 | return -EINVAL; | 942 | return -EINVAL; |
943 | 943 | ||
944 | /* Get temperature [_TMP] (required) */ | 944 | /* Get trip points [_CRT, _PSV, etc.] (required) */ |
945 | result = acpi_thermal_get_temperature(tz); | 945 | result = acpi_thermal_get_trip_points(tz); |
946 | if (result) | 946 | if (result) |
947 | return result; | 947 | return result; |
948 | 948 | ||
949 | /* Get trip points [_CRT, _PSV, etc.] (required) */ | 949 | /* Get temperature [_TMP] (required) */ |
950 | result = acpi_thermal_get_trip_points(tz); | 950 | result = acpi_thermal_get_temperature(tz); |
951 | if (result) | 951 | if (result) |
952 | return result; | 952 | return result; |
953 | 953 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index eaef02afc7cf..9577b6fa2650 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -548,27 +548,27 @@ acpi_video_device_EDID(struct acpi_video_device *device, | |||
548 | * 1. The system BIOS should NOT automatically control the brightness | 548 | * 1. The system BIOS should NOT automatically control the brightness |
549 | * level of the LCD when the power changes from AC to DC. | 549 | * level of the LCD when the power changes from AC to DC. |
550 | * Return Value: | 550 | * Return Value: |
551 | * -1 wrong arg. | 551 | * -EINVAL wrong arg. |
552 | */ | 552 | */ |
553 | 553 | ||
554 | static int | 554 | static int |
555 | acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) | 555 | acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) |
556 | { | 556 | { |
557 | u64 status = 0; | 557 | acpi_status status; |
558 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 558 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
559 | struct acpi_object_list args = { 1, &arg0 }; | 559 | struct acpi_object_list args = { 1, &arg0 }; |
560 | 560 | ||
561 | 561 | ||
562 | if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) { | 562 | if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) |
563 | status = -1; | 563 | return -EINVAL; |
564 | goto Failed; | ||
565 | } | ||
566 | arg0.integer.value = (lcd_flag << 2) | bios_flag; | 564 | arg0.integer.value = (lcd_flag << 2) | bios_flag; |
567 | video->dos_setting = arg0.integer.value; | 565 | video->dos_setting = arg0.integer.value; |
568 | acpi_evaluate_object(video->device->handle, "_DOS", &args, NULL); | 566 | status = acpi_evaluate_object(video->device->handle, "_DOS", |
567 | &args, NULL); | ||
568 | if (ACPI_FAILURE(status)) | ||
569 | return -EIO; | ||
569 | 570 | ||
570 | Failed: | 571 | return 0; |
571 | return status; | ||
572 | } | 572 | } |
573 | 573 | ||
574 | /* | 574 | /* |
@@ -1343,15 +1343,17 @@ static int | |||
1343 | acpi_video_bus_get_devices(struct acpi_video_bus *video, | 1343 | acpi_video_bus_get_devices(struct acpi_video_bus *video, |
1344 | struct acpi_device *device) | 1344 | struct acpi_device *device) |
1345 | { | 1345 | { |
1346 | int status = 0; | 1346 | int status; |
1347 | struct acpi_device *dev; | 1347 | struct acpi_device *dev; |
1348 | 1348 | ||
1349 | acpi_video_device_enumerate(video); | 1349 | status = acpi_video_device_enumerate(video); |
1350 | if (status) | ||
1351 | return status; | ||
1350 | 1352 | ||
1351 | list_for_each_entry(dev, &device->children, node) { | 1353 | list_for_each_entry(dev, &device->children, node) { |
1352 | 1354 | ||
1353 | status = acpi_video_bus_get_one_device(dev, video); | 1355 | status = acpi_video_bus_get_one_device(dev, video); |
1354 | if (ACPI_FAILURE(status)) { | 1356 | if (status) { |
1355 | printk(KERN_WARNING PREFIX | 1357 | printk(KERN_WARNING PREFIX |
1356 | "Can't attach device\n"); | 1358 | "Can't attach device\n"); |
1357 | continue; | 1359 | continue; |
@@ -1653,15 +1655,20 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1653 | mutex_init(&video->device_list_lock); | 1655 | mutex_init(&video->device_list_lock); |
1654 | INIT_LIST_HEAD(&video->video_device_list); | 1656 | INIT_LIST_HEAD(&video->video_device_list); |
1655 | 1657 | ||
1656 | acpi_video_bus_get_devices(video, device); | 1658 | error = acpi_video_bus_get_devices(video, device); |
1657 | acpi_video_bus_start_devices(video); | 1659 | if (error) |
1660 | goto err_free_video; | ||
1658 | 1661 | ||
1659 | video->input = input = input_allocate_device(); | 1662 | video->input = input = input_allocate_device(); |
1660 | if (!input) { | 1663 | if (!input) { |
1661 | error = -ENOMEM; | 1664 | error = -ENOMEM; |
1662 | goto err_stop_video; | 1665 | goto err_put_video; |
1663 | } | 1666 | } |
1664 | 1667 | ||
1668 | error = acpi_video_bus_start_devices(video); | ||
1669 | if (error) | ||
1670 | goto err_free_input_dev; | ||
1671 | |||
1665 | snprintf(video->phys, sizeof(video->phys), | 1672 | snprintf(video->phys, sizeof(video->phys), |
1666 | "%s/video/input0", acpi_device_hid(video->device)); | 1673 | "%s/video/input0", acpi_device_hid(video->device)); |
1667 | 1674 | ||
@@ -1682,7 +1689,7 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1682 | 1689 | ||
1683 | error = input_register_device(input); | 1690 | error = input_register_device(input); |
1684 | if (error) | 1691 | if (error) |
1685 | goto err_free_input_dev; | 1692 | goto err_stop_video; |
1686 | 1693 | ||
1687 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", | 1694 | printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", |
1688 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), | 1695 | ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), |
@@ -1692,14 +1699,19 @@ static int acpi_video_bus_add(struct acpi_device *device) | |||
1692 | 1699 | ||
1693 | video->pm_nb.notifier_call = acpi_video_resume; | 1700 | video->pm_nb.notifier_call = acpi_video_resume; |
1694 | video->pm_nb.priority = 0; | 1701 | video->pm_nb.priority = 0; |
1695 | register_pm_notifier(&video->pm_nb); | 1702 | error = register_pm_notifier(&video->pm_nb); |
1703 | if (error) | ||
1704 | goto err_unregister_input_dev; | ||
1696 | 1705 | ||
1697 | return 0; | 1706 | return 0; |
1698 | 1707 | ||
1699 | err_free_input_dev: | 1708 | err_unregister_input_dev: |
1700 | input_free_device(input); | 1709 | input_unregister_device(input); |
1701 | err_stop_video: | 1710 | err_stop_video: |
1702 | acpi_video_bus_stop_devices(video); | 1711 | acpi_video_bus_stop_devices(video); |
1712 | err_free_input_dev: | ||
1713 | input_free_device(input); | ||
1714 | err_put_video: | ||
1703 | acpi_video_bus_put_devices(video); | 1715 | acpi_video_bus_put_devices(video); |
1704 | kfree(video->attached_array); | 1716 | kfree(video->attached_array); |
1705 | err_free_video: | 1717 | err_free_video: |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 59f4261c753a..3e146b2ada4a 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -53,6 +53,52 @@ static void cpuidle_kick_cpus(void) {} | |||
53 | 53 | ||
54 | static int __cpuidle_register_device(struct cpuidle_device *dev); | 54 | static int __cpuidle_register_device(struct cpuidle_device *dev); |
55 | 55 | ||
56 | static inline int cpuidle_enter(struct cpuidle_device *dev, | ||
57 | struct cpuidle_driver *drv, int index) | ||
58 | { | ||
59 | struct cpuidle_state *target_state = &drv->states[index]; | ||
60 | return target_state->enter(dev, drv, index); | ||
61 | } | ||
62 | |||
63 | static inline int cpuidle_enter_tk(struct cpuidle_device *dev, | ||
64 | struct cpuidle_driver *drv, int index) | ||
65 | { | ||
66 | return cpuidle_wrap_enter(dev, drv, index, cpuidle_enter); | ||
67 | } | ||
68 | |||
69 | typedef int (*cpuidle_enter_t)(struct cpuidle_device *dev, | ||
70 | struct cpuidle_driver *drv, int index); | ||
71 | |||
72 | static cpuidle_enter_t cpuidle_enter_ops; | ||
73 | |||
74 | /** | ||
75 | * cpuidle_play_dead - cpu off-lining | ||
76 | * | ||
77 | * Only returns in case of an error | ||
78 | */ | ||
79 | int cpuidle_play_dead(void) | ||
80 | { | ||
81 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | ||
82 | struct cpuidle_driver *drv = cpuidle_get_driver(); | ||
83 | int i, dead_state = -1; | ||
84 | int power_usage = -1; | ||
85 | |||
86 | /* Find lowest-power state that supports long-term idle */ | ||
87 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | ||
88 | struct cpuidle_state *s = &drv->states[i]; | ||
89 | |||
90 | if (s->power_usage < power_usage && s->enter_dead) { | ||
91 | power_usage = s->power_usage; | ||
92 | dead_state = i; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | if (dead_state != -1) | ||
97 | return drv->states[dead_state].enter_dead(dev, dead_state); | ||
98 | |||
99 | return -ENODEV; | ||
100 | } | ||
101 | |||
56 | /** | 102 | /** |
57 | * cpuidle_idle_call - the main idle loop | 103 | * cpuidle_idle_call - the main idle loop |
58 | * | 104 | * |
@@ -63,7 +109,6 @@ int cpuidle_idle_call(void) | |||
63 | { | 109 | { |
64 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | 110 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); |
65 | struct cpuidle_driver *drv = cpuidle_get_driver(); | 111 | struct cpuidle_driver *drv = cpuidle_get_driver(); |
66 | struct cpuidle_state *target_state; | ||
67 | int next_state, entered_state; | 112 | int next_state, entered_state; |
68 | 113 | ||
69 | if (off) | 114 | if (off) |
@@ -92,12 +137,10 @@ int cpuidle_idle_call(void) | |||
92 | return 0; | 137 | return 0; |
93 | } | 138 | } |
94 | 139 | ||
95 | target_state = &drv->states[next_state]; | ||
96 | |||
97 | trace_power_start(POWER_CSTATE, next_state, dev->cpu); | 140 | trace_power_start(POWER_CSTATE, next_state, dev->cpu); |
98 | trace_cpu_idle(next_state, dev->cpu); | 141 | trace_cpu_idle(next_state, dev->cpu); |
99 | 142 | ||
100 | entered_state = target_state->enter(dev, drv, next_state); | 143 | entered_state = cpuidle_enter_ops(dev, drv, next_state); |
101 | 144 | ||
102 | trace_power_end(dev->cpu); | 145 | trace_power_end(dev->cpu); |
103 | trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); | 146 | trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu); |
@@ -110,6 +153,8 @@ int cpuidle_idle_call(void) | |||
110 | dev->states_usage[entered_state].time += | 153 | dev->states_usage[entered_state].time += |
111 | (unsigned long long)dev->last_residency; | 154 | (unsigned long long)dev->last_residency; |
112 | dev->states_usage[entered_state].usage++; | 155 | dev->states_usage[entered_state].usage++; |
156 | } else { | ||
157 | dev->last_residency = 0; | ||
113 | } | 158 | } |
114 | 159 | ||
115 | /* give the governor an opportunity to reflect on the outcome */ | 160 | /* give the governor an opportunity to reflect on the outcome */ |
@@ -164,6 +209,37 @@ void cpuidle_resume_and_unlock(void) | |||
164 | 209 | ||
165 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); | 210 | EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock); |
166 | 211 | ||
212 | /** | ||
213 | * cpuidle_wrap_enter - performs timekeeping and irqen around enter function | ||
214 | * @dev: pointer to a valid cpuidle_device object | ||
215 | * @drv: pointer to a valid cpuidle_driver object | ||
216 | * @index: index of the target cpuidle state. | ||
217 | */ | ||
218 | int cpuidle_wrap_enter(struct cpuidle_device *dev, | ||
219 | struct cpuidle_driver *drv, int index, | ||
220 | int (*enter)(struct cpuidle_device *dev, | ||
221 | struct cpuidle_driver *drv, int index)) | ||
222 | { | ||
223 | ktime_t time_start, time_end; | ||
224 | s64 diff; | ||
225 | |||
226 | time_start = ktime_get(); | ||
227 | |||
228 | index = enter(dev, drv, index); | ||
229 | |||
230 | time_end = ktime_get(); | ||
231 | |||
232 | local_irq_enable(); | ||
233 | |||
234 | diff = ktime_to_us(ktime_sub(time_end, time_start)); | ||
235 | if (diff > INT_MAX) | ||
236 | diff = INT_MAX; | ||
237 | |||
238 | dev->last_residency = (int) diff; | ||
239 | |||
240 | return index; | ||
241 | } | ||
242 | |||
167 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX | 243 | #ifdef CONFIG_ARCH_HAS_CPU_RELAX |
168 | static int poll_idle(struct cpuidle_device *dev, | 244 | static int poll_idle(struct cpuidle_device *dev, |
169 | struct cpuidle_driver *drv, int index) | 245 | struct cpuidle_driver *drv, int index) |
@@ -197,6 +273,7 @@ static void poll_idle_init(struct cpuidle_driver *drv) | |||
197 | state->power_usage = -1; | 273 | state->power_usage = -1; |
198 | state->flags = 0; | 274 | state->flags = 0; |
199 | state->enter = poll_idle; | 275 | state->enter = poll_idle; |
276 | state->disable = 0; | ||
200 | } | 277 | } |
201 | #else | 278 | #else |
202 | static void poll_idle_init(struct cpuidle_driver *drv) {} | 279 | static void poll_idle_init(struct cpuidle_driver *drv) {} |
@@ -212,13 +289,14 @@ static void poll_idle_init(struct cpuidle_driver *drv) {} | |||
212 | int cpuidle_enable_device(struct cpuidle_device *dev) | 289 | int cpuidle_enable_device(struct cpuidle_device *dev) |
213 | { | 290 | { |
214 | int ret, i; | 291 | int ret, i; |
292 | struct cpuidle_driver *drv = cpuidle_get_driver(); | ||
215 | 293 | ||
216 | if (dev->enabled) | 294 | if (dev->enabled) |
217 | return 0; | 295 | return 0; |
218 | if (!cpuidle_get_driver() || !cpuidle_curr_governor) | 296 | if (!drv || !cpuidle_curr_governor) |
219 | return -EIO; | 297 | return -EIO; |
220 | if (!dev->state_count) | 298 | if (!dev->state_count) |
221 | return -EINVAL; | 299 | dev->state_count = drv->state_count; |
222 | 300 | ||
223 | if (dev->registered == 0) { | 301 | if (dev->registered == 0) { |
224 | ret = __cpuidle_register_device(dev); | 302 | ret = __cpuidle_register_device(dev); |
@@ -226,13 +304,16 @@ int cpuidle_enable_device(struct cpuidle_device *dev) | |||
226 | return ret; | 304 | return ret; |
227 | } | 305 | } |
228 | 306 | ||
229 | poll_idle_init(cpuidle_get_driver()); | 307 | cpuidle_enter_ops = drv->en_core_tk_irqen ? |
308 | cpuidle_enter_tk : cpuidle_enter; | ||
309 | |||
310 | poll_idle_init(drv); | ||
230 | 311 | ||
231 | if ((ret = cpuidle_add_state_sysfs(dev))) | 312 | if ((ret = cpuidle_add_state_sysfs(dev))) |
232 | return ret; | 313 | return ret; |
233 | 314 | ||
234 | if (cpuidle_curr_governor->enable && | 315 | if (cpuidle_curr_governor->enable && |
235 | (ret = cpuidle_curr_governor->enable(cpuidle_get_driver(), dev))) | 316 | (ret = cpuidle_curr_governor->enable(drv, dev))) |
236 | goto fail_sysfs; | 317 | goto fail_sysfs; |
237 | 318 | ||
238 | for (i = 0; i < dev->state_count; i++) { | 319 | for (i = 0; i < dev->state_count; i++) { |
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 284d7af5a9c8..40cd3f3024df 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -47,7 +47,7 @@ static void __cpuidle_register_driver(struct cpuidle_driver *drv) | |||
47 | */ | 47 | */ |
48 | int cpuidle_register_driver(struct cpuidle_driver *drv) | 48 | int cpuidle_register_driver(struct cpuidle_driver *drv) |
49 | { | 49 | { |
50 | if (!drv) | 50 | if (!drv || !drv->state_count) |
51 | return -EINVAL; | 51 | return -EINVAL; |
52 | 52 | ||
53 | if (cpuidle_disabled()) | 53 | if (cpuidle_disabled()) |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ad0952601ae2..06335756ea14 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -236,7 +236,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
236 | { | 236 | { |
237 | struct menu_device *data = &__get_cpu_var(menu_devices); | 237 | struct menu_device *data = &__get_cpu_var(menu_devices); |
238 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 238 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
239 | unsigned int power_usage = -1; | 239 | int power_usage = -1; |
240 | int i; | 240 | int i; |
241 | int multiplier; | 241 | int multiplier; |
242 | struct timespec t; | 242 | struct timespec t; |
@@ -280,7 +280,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
280 | * We want to default to C1 (hlt), not to busy polling | 280 | * We want to default to C1 (hlt), not to busy polling |
281 | * unless the timer is happening really really soon. | 281 | * unless the timer is happening really really soon. |
282 | */ | 282 | */ |
283 | if (data->expected_us > 5) | 283 | if (data->expected_us > 5 && |
284 | drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) | ||
284 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; | 285 | data->last_state_idx = CPUIDLE_DRIVER_STATE_START; |
285 | 286 | ||
286 | /* | 287 | /* |
@@ -290,6 +291,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
290 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | 291 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { |
291 | struct cpuidle_state *s = &drv->states[i]; | 292 | struct cpuidle_state *s = &drv->states[i]; |
292 | 293 | ||
294 | if (s->disable) | ||
295 | continue; | ||
293 | if (s->target_residency > data->predicted_us) | 296 | if (s->target_residency > data->predicted_us) |
294 | continue; | 297 | continue; |
295 | if (s->exit_latency > latency_req) | 298 | if (s->exit_latency > latency_req) |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 3fe41fe4851a..88032b4dc6d2 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/sysfs.h> | 11 | #include <linux/sysfs.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/cpu.h> | 13 | #include <linux/cpu.h> |
14 | #include <linux/capability.h> | ||
14 | 15 | ||
15 | #include "cpuidle.h" | 16 | #include "cpuidle.h" |
16 | 17 | ||
@@ -222,6 +223,9 @@ struct cpuidle_state_attr { | |||
222 | #define define_one_state_ro(_name, show) \ | 223 | #define define_one_state_ro(_name, show) \ |
223 | static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL) | 224 | static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0444, show, NULL) |
224 | 225 | ||
226 | #define define_one_state_rw(_name, show, store) \ | ||
227 | static struct cpuidle_state_attr attr_##_name = __ATTR(_name, 0644, show, store) | ||
228 | |||
225 | #define define_show_state_function(_name) \ | 229 | #define define_show_state_function(_name) \ |
226 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ | 230 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ |
227 | struct cpuidle_state_usage *state_usage, char *buf) \ | 231 | struct cpuidle_state_usage *state_usage, char *buf) \ |
@@ -229,6 +233,24 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ | |||
229 | return sprintf(buf, "%u\n", state->_name);\ | 233 | return sprintf(buf, "%u\n", state->_name);\ |
230 | } | 234 | } |
231 | 235 | ||
236 | #define define_store_state_function(_name) \ | ||
237 | static ssize_t store_state_##_name(struct cpuidle_state *state, \ | ||
238 | const char *buf, size_t size) \ | ||
239 | { \ | ||
240 | long value; \ | ||
241 | int err; \ | ||
242 | if (!capable(CAP_SYS_ADMIN)) \ | ||
243 | return -EPERM; \ | ||
244 | err = kstrtol(buf, 0, &value); \ | ||
245 | if (err) \ | ||
246 | return err; \ | ||
247 | if (value) \ | ||
248 | state->disable = 1; \ | ||
249 | else \ | ||
250 | state->disable = 0; \ | ||
251 | return size; \ | ||
252 | } | ||
253 | |||
232 | #define define_show_state_ull_function(_name) \ | 254 | #define define_show_state_ull_function(_name) \ |
233 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ | 255 | static ssize_t show_state_##_name(struct cpuidle_state *state, \ |
234 | struct cpuidle_state_usage *state_usage, char *buf) \ | 256 | struct cpuidle_state_usage *state_usage, char *buf) \ |
@@ -251,6 +273,8 @@ define_show_state_ull_function(usage) | |||
251 | define_show_state_ull_function(time) | 273 | define_show_state_ull_function(time) |
252 | define_show_state_str_function(name) | 274 | define_show_state_str_function(name) |
253 | define_show_state_str_function(desc) | 275 | define_show_state_str_function(desc) |
276 | define_show_state_function(disable) | ||
277 | define_store_state_function(disable) | ||
254 | 278 | ||
255 | define_one_state_ro(name, show_state_name); | 279 | define_one_state_ro(name, show_state_name); |
256 | define_one_state_ro(desc, show_state_desc); | 280 | define_one_state_ro(desc, show_state_desc); |
@@ -258,6 +282,7 @@ define_one_state_ro(latency, show_state_exit_latency); | |||
258 | define_one_state_ro(power, show_state_power_usage); | 282 | define_one_state_ro(power, show_state_power_usage); |
259 | define_one_state_ro(usage, show_state_usage); | 283 | define_one_state_ro(usage, show_state_usage); |
260 | define_one_state_ro(time, show_state_time); | 284 | define_one_state_ro(time, show_state_time); |
285 | define_one_state_rw(disable, show_state_disable, store_state_disable); | ||
261 | 286 | ||
262 | static struct attribute *cpuidle_state_default_attrs[] = { | 287 | static struct attribute *cpuidle_state_default_attrs[] = { |
263 | &attr_name.attr, | 288 | &attr_name.attr, |
@@ -266,6 +291,7 @@ static struct attribute *cpuidle_state_default_attrs[] = { | |||
266 | &attr_power.attr, | 291 | &attr_power.attr, |
267 | &attr_usage.attr, | 292 | &attr_usage.attr, |
268 | &attr_time.attr, | 293 | &attr_time.attr, |
294 | &attr_disable.attr, | ||
269 | NULL | 295 | NULL |
270 | }; | 296 | }; |
271 | 297 | ||
@@ -287,8 +313,22 @@ static ssize_t cpuidle_state_show(struct kobject * kobj, | |||
287 | return ret; | 313 | return ret; |
288 | } | 314 | } |
289 | 315 | ||
316 | static ssize_t cpuidle_state_store(struct kobject *kobj, | ||
317 | struct attribute *attr, const char *buf, size_t size) | ||
318 | { | ||
319 | int ret = -EIO; | ||
320 | struct cpuidle_state *state = kobj_to_state(kobj); | ||
321 | struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); | ||
322 | |||
323 | if (cattr->store) | ||
324 | ret = cattr->store(state, buf, size); | ||
325 | |||
326 | return ret; | ||
327 | } | ||
328 | |||
290 | static const struct sysfs_ops cpuidle_state_sysfs_ops = { | 329 | static const struct sysfs_ops cpuidle_state_sysfs_ops = { |
291 | .show = cpuidle_state_show, | 330 | .show = cpuidle_state_show, |
331 | .store = cpuidle_state_store, | ||
292 | }; | 332 | }; |
293 | 333 | ||
294 | static void cpuidle_state_sysfs_release(struct kobject *kobj) | 334 | static void cpuidle_state_sysfs_release(struct kobject *kobj) |
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 88a98cff5a44..f7ba316e0ed6 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c | |||
@@ -609,25 +609,16 @@ static bool mcp_exceeded(struct ips_driver *ips) | |||
609 | bool ret = false; | 609 | bool ret = false; |
610 | u32 temp_limit; | 610 | u32 temp_limit; |
611 | u32 avg_power; | 611 | u32 avg_power; |
612 | const char *msg = "MCP limit exceeded: "; | ||
613 | 612 | ||
614 | spin_lock_irqsave(&ips->turbo_status_lock, flags); | 613 | spin_lock_irqsave(&ips->turbo_status_lock, flags); |
615 | 614 | ||
616 | temp_limit = ips->mcp_temp_limit * 100; | 615 | temp_limit = ips->mcp_temp_limit * 100; |
617 | if (ips->mcp_avg_temp > temp_limit) { | 616 | if (ips->mcp_avg_temp > temp_limit) |
618 | dev_info(&ips->dev->dev, | ||
619 | "%sAvg temp %u, limit %u\n", msg, ips->mcp_avg_temp, | ||
620 | temp_limit); | ||
621 | ret = true; | 617 | ret = true; |
622 | } | ||
623 | 618 | ||
624 | avg_power = ips->cpu_avg_power + ips->mch_avg_power; | 619 | avg_power = ips->cpu_avg_power + ips->mch_avg_power; |
625 | if (avg_power > ips->mcp_power_limit) { | 620 | if (avg_power > ips->mcp_power_limit) |
626 | dev_info(&ips->dev->dev, | ||
627 | "%sAvg power %u, limit %u\n", msg, avg_power, | ||
628 | ips->mcp_power_limit); | ||
629 | ret = true; | 621 | ret = true; |
630 | } | ||
631 | 622 | ||
632 | spin_unlock_irqrestore(&ips->turbo_status_lock, flags); | 623 | spin_unlock_irqrestore(&ips->turbo_status_lock, flags); |
633 | 624 | ||
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index b00c17612a89..d21e8f59c84e 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -321,9 +321,14 @@ static int __init acpi_pnp_match(struct device *dev, void *_pnp) | |||
321 | { | 321 | { |
322 | struct acpi_device *acpi = to_acpi_device(dev); | 322 | struct acpi_device *acpi = to_acpi_device(dev); |
323 | struct pnp_dev *pnp = _pnp; | 323 | struct pnp_dev *pnp = _pnp; |
324 | struct device *physical_device; | ||
325 | |||
326 | physical_device = acpi_get_physical_device(acpi->handle); | ||
327 | if (physical_device) | ||
328 | put_device(physical_device); | ||
324 | 329 | ||
325 | /* true means it matched */ | 330 | /* true means it matched */ |
326 | return !acpi_get_physical_device(acpi->handle) | 331 | return !physical_device |
327 | && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); | 332 | && compare_pnp_id(pnp->id, acpi_device_hid(acpi)); |
328 | } | 333 | } |
329 | 334 | ||
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index f7f71b2d3101..514a691abea0 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -18,3 +18,11 @@ config THERMAL_HWMON | |||
18 | depends on THERMAL | 18 | depends on THERMAL |
19 | depends on HWMON=y || HWMON=THERMAL | 19 | depends on HWMON=y || HWMON=THERMAL |
20 | default y | 20 | default y |
21 | |||
22 | config SPEAR_THERMAL | ||
23 | bool "SPEAr thermal sensor driver" | ||
24 | depends on THERMAL | ||
25 | depends on PLAT_SPEAR | ||
26 | help | ||
27 | Enable this to plug the SPEAr thermal sensor driver into the Linux | ||
28 | thermal framework | ||
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 31108a01c22e..a9fff0bf4b14 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile | |||
@@ -3,3 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_THERMAL) += thermal_sys.o | 5 | obj-$(CONFIG_THERMAL) += thermal_sys.o |
6 | obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o \ No newline at end of file | ||
diff --git a/drivers/thermal/spear_thermal.c b/drivers/thermal/spear_thermal.c new file mode 100644 index 000000000000..c2e32df3b164 --- /dev/null +++ b/drivers/thermal/spear_thermal.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* | ||
2 | * SPEAr thermal driver. | ||
3 | * | ||
4 | * Copyright (C) 2011-2012 ST Microelectronics | ||
5 | * Author: Vincenzo Frascino <vincenzo.frascino@st.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/platform_data/spear_thermal.h> | ||
26 | #include <linux/thermal.h> | ||
27 | |||
28 | #define MD_FACTOR 1000 | ||
29 | |||
30 | /* SPEAr Thermal Sensor Dev Structure */ | ||
31 | struct spear_thermal_dev { | ||
32 | /* pointer to base address of the thermal sensor */ | ||
33 | void __iomem *thermal_base; | ||
34 | /* clk structure */ | ||
35 | struct clk *clk; | ||
36 | /* pointer to thermal flags */ | ||
37 | unsigned int flags; | ||
38 | }; | ||
39 | |||
40 | static inline int thermal_get_temp(struct thermal_zone_device *thermal, | ||
41 | unsigned long *temp) | ||
42 | { | ||
43 | struct spear_thermal_dev *stdev = thermal->devdata; | ||
44 | |||
45 | /* | ||
46 | * Data are ready to be read after 628 usec from POWERDOWN signal | ||
47 | * (PDN) = 1 | ||
48 | */ | ||
49 | *temp = (readl_relaxed(stdev->thermal_base) & 0x7F) * MD_FACTOR; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static struct thermal_zone_device_ops ops = { | ||
54 | .get_temp = thermal_get_temp, | ||
55 | }; | ||
56 | |||
57 | #ifdef CONFIG_PM | ||
58 | static int spear_thermal_suspend(struct device *dev) | ||
59 | { | ||
60 | struct platform_device *pdev = to_platform_device(dev); | ||
61 | struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); | ||
62 | struct spear_thermal_dev *stdev = spear_thermal->devdata; | ||
63 | unsigned int actual_mask = 0; | ||
64 | |||
65 | /* Disable SPEAr Thermal Sensor */ | ||
66 | actual_mask = readl_relaxed(stdev->thermal_base); | ||
67 | writel_relaxed(actual_mask & ~stdev->flags, stdev->thermal_base); | ||
68 | |||
69 | clk_disable(stdev->clk); | ||
70 | dev_info(dev, "Suspended.\n"); | ||
71 | |||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int spear_thermal_resume(struct device *dev) | ||
76 | { | ||
77 | struct platform_device *pdev = to_platform_device(dev); | ||
78 | struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); | ||
79 | struct spear_thermal_dev *stdev = spear_thermal->devdata; | ||
80 | unsigned int actual_mask = 0; | ||
81 | int ret = 0; | ||
82 | |||
83 | ret = clk_enable(stdev->clk); | ||
84 | if (ret) { | ||
85 | dev_err(&pdev->dev, "Can't enable clock\n"); | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | /* Enable SPEAr Thermal Sensor */ | ||
90 | actual_mask = readl_relaxed(stdev->thermal_base); | ||
91 | writel_relaxed(actual_mask | stdev->flags, stdev->thermal_base); | ||
92 | |||
93 | dev_info(dev, "Resumed.\n"); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | #endif | ||
98 | |||
99 | static SIMPLE_DEV_PM_OPS(spear_thermal_pm_ops, spear_thermal_suspend, | ||
100 | spear_thermal_resume); | ||
101 | |||
102 | static int spear_thermal_probe(struct platform_device *pdev) | ||
103 | { | ||
104 | struct thermal_zone_device *spear_thermal = NULL; | ||
105 | struct spear_thermal_dev *stdev; | ||
106 | struct spear_thermal_pdata *pdata; | ||
107 | int ret = 0; | ||
108 | struct resource *stres = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
109 | |||
110 | if (!stres) { | ||
111 | dev_err(&pdev->dev, "memory resource missing\n"); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | |||
115 | pdata = dev_get_platdata(&pdev->dev); | ||
116 | if (!pdata) { | ||
117 | dev_err(&pdev->dev, "platform data is NULL\n"); | ||
118 | return -EINVAL; | ||
119 | } | ||
120 | |||
121 | stdev = devm_kzalloc(&pdev->dev, sizeof(*stdev), GFP_KERNEL); | ||
122 | if (!stdev) { | ||
123 | dev_err(&pdev->dev, "kzalloc fail\n"); | ||
124 | return -ENOMEM; | ||
125 | } | ||
126 | |||
127 | /* Enable thermal sensor */ | ||
128 | stdev->thermal_base = devm_ioremap(&pdev->dev, stres->start, | ||
129 | resource_size(stres)); | ||
130 | if (!stdev->thermal_base) { | ||
131 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
132 | return -ENOMEM; | ||
133 | } | ||
134 | |||
135 | stdev->clk = clk_get(&pdev->dev, NULL); | ||
136 | if (IS_ERR(stdev->clk)) { | ||
137 | dev_err(&pdev->dev, "Can't get clock\n"); | ||
138 | return PTR_ERR(stdev->clk); | ||
139 | } | ||
140 | |||
141 | ret = clk_enable(stdev->clk); | ||
142 | if (ret) { | ||
143 | dev_err(&pdev->dev, "Can't enable clock\n"); | ||
144 | goto put_clk; | ||
145 | } | ||
146 | |||
147 | stdev->flags = pdata->thermal_flags; | ||
148 | writel_relaxed(stdev->flags, stdev->thermal_base); | ||
149 | |||
150 | spear_thermal = thermal_zone_device_register("spear_thermal", 0, | ||
151 | stdev, &ops, 0, 0, 0, 0); | ||
152 | if (IS_ERR(spear_thermal)) { | ||
153 | dev_err(&pdev->dev, "thermal zone device is NULL\n"); | ||
154 | ret = PTR_ERR(spear_thermal); | ||
155 | goto disable_clk; | ||
156 | } | ||
157 | |||
158 | platform_set_drvdata(pdev, spear_thermal); | ||
159 | |||
160 | dev_info(&spear_thermal->device, "Thermal Sensor Loaded at: 0x%p.\n", | ||
161 | stdev->thermal_base); | ||
162 | |||
163 | return 0; | ||
164 | |||
165 | disable_clk: | ||
166 | clk_disable(stdev->clk); | ||
167 | put_clk: | ||
168 | clk_put(stdev->clk); | ||
169 | |||
170 | return ret; | ||
171 | } | ||
172 | |||
173 | static int spear_thermal_exit(struct platform_device *pdev) | ||
174 | { | ||
175 | unsigned int actual_mask = 0; | ||
176 | struct thermal_zone_device *spear_thermal = platform_get_drvdata(pdev); | ||
177 | struct spear_thermal_dev *stdev = spear_thermal->devdata; | ||
178 | |||
179 | thermal_zone_device_unregister(spear_thermal); | ||
180 | platform_set_drvdata(pdev, NULL); | ||
181 | |||
182 | /* Disable SPEAr Thermal Sensor */ | ||
183 | actual_mask = readl_relaxed(stdev->thermal_base); | ||
184 | writel_relaxed(actual_mask & ~stdev->flags, stdev->thermal_base); | ||
185 | |||
186 | clk_disable(stdev->clk); | ||
187 | clk_put(stdev->clk); | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
192 | static struct platform_driver spear_thermal_driver = { | ||
193 | .probe = spear_thermal_probe, | ||
194 | .remove = spear_thermal_exit, | ||
195 | .driver = { | ||
196 | .name = "spear_thermal", | ||
197 | .owner = THIS_MODULE, | ||
198 | .pm = &spear_thermal_pm_ops, | ||
199 | }, | ||
200 | }; | ||
201 | |||
202 | module_platform_driver(spear_thermal_driver); | ||
203 | |||
204 | MODULE_AUTHOR("Vincenzo Frascino <vincenzo.frascino@st.com>"); | ||
205 | MODULE_DESCRIPTION("SPEAr thermal driver"); | ||
206 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index 220ce7e31cf5..022bacb71a7e 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -23,6 +23,8 @@ | |||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
27 | |||
26 | #include <linux/module.h> | 28 | #include <linux/module.h> |
27 | #include <linux/device.h> | 29 | #include <linux/device.h> |
28 | #include <linux/err.h> | 30 | #include <linux/err.h> |
@@ -39,8 +41,6 @@ MODULE_AUTHOR("Zhang Rui"); | |||
39 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); | 41 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); |
40 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
41 | 43 | ||
42 | #define PREFIX "Thermal: " | ||
43 | |||
44 | struct thermal_cooling_device_instance { | 44 | struct thermal_cooling_device_instance { |
45 | int id; | 45 | int id; |
46 | char name[THERMAL_NAME_LENGTH]; | 46 | char name[THERMAL_NAME_LENGTH]; |
@@ -60,13 +60,11 @@ static LIST_HEAD(thermal_tz_list); | |||
60 | static LIST_HEAD(thermal_cdev_list); | 60 | static LIST_HEAD(thermal_cdev_list); |
61 | static DEFINE_MUTEX(thermal_list_lock); | 61 | static DEFINE_MUTEX(thermal_list_lock); |
62 | 62 | ||
63 | static unsigned int thermal_event_seqnum; | ||
64 | |||
65 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) | 63 | static int get_idr(struct idr *idr, struct mutex *lock, int *id) |
66 | { | 64 | { |
67 | int err; | 65 | int err; |
68 | 66 | ||
69 | again: | 67 | again: |
70 | if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) | 68 | if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) |
71 | return -ENOMEM; | 69 | return -ENOMEM; |
72 | 70 | ||
@@ -152,9 +150,9 @@ mode_store(struct device *dev, struct device_attribute *attr, | |||
152 | if (!tz->ops->set_mode) | 150 | if (!tz->ops->set_mode) |
153 | return -EPERM; | 151 | return -EPERM; |
154 | 152 | ||
155 | if (!strncmp(buf, "enabled", sizeof("enabled"))) | 153 | if (!strncmp(buf, "enabled", sizeof("enabled") - 1)) |
156 | result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); | 154 | result = tz->ops->set_mode(tz, THERMAL_DEVICE_ENABLED); |
157 | else if (!strncmp(buf, "disabled", sizeof("disabled"))) | 155 | else if (!strncmp(buf, "disabled", sizeof("disabled") - 1)) |
158 | result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); | 156 | result = tz->ops->set_mode(tz, THERMAL_DEVICE_DISABLED); |
159 | else | 157 | else |
160 | result = -EINVAL; | 158 | result = -EINVAL; |
@@ -283,8 +281,7 @@ passive_show(struct device *dev, struct device_attribute *attr, | |||
283 | static DEVICE_ATTR(type, 0444, type_show, NULL); | 281 | static DEVICE_ATTR(type, 0444, type_show, NULL); |
284 | static DEVICE_ATTR(temp, 0444, temp_show, NULL); | 282 | static DEVICE_ATTR(temp, 0444, temp_show, NULL); |
285 | static DEVICE_ATTR(mode, 0644, mode_show, mode_store); | 283 | static DEVICE_ATTR(mode, 0644, mode_show, mode_store); |
286 | static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, \ | 284 | static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store); |
287 | passive_store); | ||
288 | 285 | ||
289 | static struct device_attribute trip_point_attrs[] = { | 286 | static struct device_attribute trip_point_attrs[] = { |
290 | __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), | 287 | __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), |
@@ -313,22 +310,6 @@ static struct device_attribute trip_point_attrs[] = { | |||
313 | __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), | 310 | __ATTR(trip_point_11_temp, 0444, trip_point_temp_show, NULL), |
314 | }; | 311 | }; |
315 | 312 | ||
316 | #define TRIP_POINT_ATTR_ADD(_dev, _index, result) \ | ||
317 | do { \ | ||
318 | result = device_create_file(_dev, \ | ||
319 | &trip_point_attrs[_index * 2]); \ | ||
320 | if (result) \ | ||
321 | break; \ | ||
322 | result = device_create_file(_dev, \ | ||
323 | &trip_point_attrs[_index * 2 + 1]); \ | ||
324 | } while (0) | ||
325 | |||
326 | #define TRIP_POINT_ATTR_REMOVE(_dev, _index) \ | ||
327 | do { \ | ||
328 | device_remove_file(_dev, &trip_point_attrs[_index * 2]); \ | ||
329 | device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ | ||
330 | } while (0) | ||
331 | |||
332 | /* sys I/F for cooling device */ | 313 | /* sys I/F for cooling device */ |
333 | #define to_cooling_device(_dev) \ | 314 | #define to_cooling_device(_dev) \ |
334 | container_of(_dev, struct thermal_cooling_device, device) | 315 | container_of(_dev, struct thermal_cooling_device, device) |
@@ -835,15 +816,14 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
835 | return 0; | 816 | return 0; |
836 | 817 | ||
837 | device_remove_file(&tz->device, &dev->attr); | 818 | device_remove_file(&tz->device, &dev->attr); |
838 | remove_symbol_link: | 819 | remove_symbol_link: |
839 | sysfs_remove_link(&tz->device.kobj, dev->name); | 820 | sysfs_remove_link(&tz->device.kobj, dev->name); |
840 | release_idr: | 821 | release_idr: |
841 | release_idr(&tz->idr, &tz->lock, dev->id); | 822 | release_idr(&tz->idr, &tz->lock, dev->id); |
842 | free_mem: | 823 | free_mem: |
843 | kfree(dev); | 824 | kfree(dev); |
844 | return result; | 825 | return result; |
845 | } | 826 | } |
846 | |||
847 | EXPORT_SYMBOL(thermal_zone_bind_cooling_device); | 827 | EXPORT_SYMBOL(thermal_zone_bind_cooling_device); |
848 | 828 | ||
849 | /** | 829 | /** |
@@ -873,14 +853,13 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, | |||
873 | 853 | ||
874 | return -ENODEV; | 854 | return -ENODEV; |
875 | 855 | ||
876 | unbind: | 856 | unbind: |
877 | device_remove_file(&tz->device, &pos->attr); | 857 | device_remove_file(&tz->device, &pos->attr); |
878 | sysfs_remove_link(&tz->device.kobj, pos->name); | 858 | sysfs_remove_link(&tz->device.kobj, pos->name); |
879 | release_idr(&tz->idr, &tz->lock, pos->id); | 859 | release_idr(&tz->idr, &tz->lock, pos->id); |
880 | kfree(pos); | 860 | kfree(pos); |
881 | return 0; | 861 | return 0; |
882 | } | 862 | } |
883 | |||
884 | EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); | 863 | EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); |
885 | 864 | ||
886 | static void thermal_release(struct device *dev) | 865 | static void thermal_release(struct device *dev) |
@@ -888,7 +867,8 @@ static void thermal_release(struct device *dev) | |||
888 | struct thermal_zone_device *tz; | 867 | struct thermal_zone_device *tz; |
889 | struct thermal_cooling_device *cdev; | 868 | struct thermal_cooling_device *cdev; |
890 | 869 | ||
891 | if (!strncmp(dev_name(dev), "thermal_zone", sizeof "thermal_zone" - 1)) { | 870 | if (!strncmp(dev_name(dev), "thermal_zone", |
871 | sizeof("thermal_zone") - 1)) { | ||
892 | tz = to_thermal_zone(dev); | 872 | tz = to_thermal_zone(dev); |
893 | kfree(tz); | 873 | kfree(tz); |
894 | } else { | 874 | } else { |
@@ -908,8 +888,9 @@ static struct class thermal_class = { | |||
908 | * @devdata: device private data. | 888 | * @devdata: device private data. |
909 | * @ops: standard thermal cooling devices callbacks. | 889 | * @ops: standard thermal cooling devices callbacks. |
910 | */ | 890 | */ |
911 | struct thermal_cooling_device *thermal_cooling_device_register( | 891 | struct thermal_cooling_device * |
912 | char *type, void *devdata, const struct thermal_cooling_device_ops *ops) | 892 | thermal_cooling_device_register(char *type, void *devdata, |
893 | const struct thermal_cooling_device_ops *ops) | ||
913 | { | 894 | { |
914 | struct thermal_cooling_device *cdev; | 895 | struct thermal_cooling_device *cdev; |
915 | struct thermal_zone_device *pos; | 896 | struct thermal_zone_device *pos; |
@@ -974,12 +955,11 @@ struct thermal_cooling_device *thermal_cooling_device_register( | |||
974 | if (!result) | 955 | if (!result) |
975 | return cdev; | 956 | return cdev; |
976 | 957 | ||
977 | unregister: | 958 | unregister: |
978 | release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); | 959 | release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); |
979 | device_unregister(&cdev->device); | 960 | device_unregister(&cdev->device); |
980 | return ERR_PTR(result); | 961 | return ERR_PTR(result); |
981 | } | 962 | } |
982 | |||
983 | EXPORT_SYMBOL(thermal_cooling_device_register); | 963 | EXPORT_SYMBOL(thermal_cooling_device_register); |
984 | 964 | ||
985 | /** | 965 | /** |
@@ -1024,7 +1004,6 @@ void thermal_cooling_device_unregister(struct | |||
1024 | device_unregister(&cdev->device); | 1004 | device_unregister(&cdev->device); |
1025 | return; | 1005 | return; |
1026 | } | 1006 | } |
1027 | |||
1028 | EXPORT_SYMBOL(thermal_cooling_device_unregister); | 1007 | EXPORT_SYMBOL(thermal_cooling_device_unregister); |
1029 | 1008 | ||
1030 | /** | 1009 | /** |
@@ -1044,8 +1023,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1044 | 1023 | ||
1045 | if (tz->ops->get_temp(tz, &temp)) { | 1024 | if (tz->ops->get_temp(tz, &temp)) { |
1046 | /* get_temp failed - retry it later */ | 1025 | /* get_temp failed - retry it later */ |
1047 | printk(KERN_WARNING PREFIX "failed to read out thermal zone " | 1026 | pr_warn("failed to read out thermal zone %d\n", tz->id); |
1048 | "%d\n", tz->id); | ||
1049 | goto leave; | 1027 | goto leave; |
1050 | } | 1028 | } |
1051 | 1029 | ||
@@ -1060,9 +1038,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1060 | ret = tz->ops->notify(tz, count, | 1038 | ret = tz->ops->notify(tz, count, |
1061 | trip_type); | 1039 | trip_type); |
1062 | if (!ret) { | 1040 | if (!ret) { |
1063 | printk(KERN_EMERG | 1041 | pr_emerg("Critical temperature reached (%ld C), shutting down\n", |
1064 | "Critical temperature reached (%ld C), shutting down.\n", | 1042 | temp/1000); |
1065 | temp/1000); | ||
1066 | orderly_poweroff(true); | 1043 | orderly_poweroff(true); |
1067 | } | 1044 | } |
1068 | } | 1045 | } |
@@ -1100,7 +1077,7 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1100 | 1077 | ||
1101 | tz->last_temperature = temp; | 1078 | tz->last_temperature = temp; |
1102 | 1079 | ||
1103 | leave: | 1080 | leave: |
1104 | if (tz->passive) | 1081 | if (tz->passive) |
1105 | thermal_zone_device_set_polling(tz, tz->passive_delay); | 1082 | thermal_zone_device_set_polling(tz, tz->passive_delay); |
1106 | else if (tz->polling_delay) | 1083 | else if (tz->polling_delay) |
@@ -1199,7 +1176,12 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, | |||
1199 | } | 1176 | } |
1200 | 1177 | ||
1201 | for (count = 0; count < trips; count++) { | 1178 | for (count = 0; count < trips; count++) { |
1202 | TRIP_POINT_ATTR_ADD(&tz->device, count, result); | 1179 | result = device_create_file(&tz->device, |
1180 | &trip_point_attrs[count * 2]); | ||
1181 | if (result) | ||
1182 | break; | ||
1183 | result = device_create_file(&tz->device, | ||
1184 | &trip_point_attrs[count * 2 + 1]); | ||
1203 | if (result) | 1185 | if (result) |
1204 | goto unregister; | 1186 | goto unregister; |
1205 | tz->ops->get_trip_type(tz, count, &trip_type); | 1187 | tz->ops->get_trip_type(tz, count, &trip_type); |
@@ -1235,12 +1217,11 @@ struct thermal_zone_device *thermal_zone_device_register(char *type, | |||
1235 | if (!result) | 1217 | if (!result) |
1236 | return tz; | 1218 | return tz; |
1237 | 1219 | ||
1238 | unregister: | 1220 | unregister: |
1239 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 1221 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); |
1240 | device_unregister(&tz->device); | 1222 | device_unregister(&tz->device); |
1241 | return ERR_PTR(result); | 1223 | return ERR_PTR(result); |
1242 | } | 1224 | } |
1243 | |||
1244 | EXPORT_SYMBOL(thermal_zone_device_register); | 1225 | EXPORT_SYMBOL(thermal_zone_device_register); |
1245 | 1226 | ||
1246 | /** | 1227 | /** |
@@ -1279,9 +1260,12 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
1279 | if (tz->ops->get_mode) | 1260 | if (tz->ops->get_mode) |
1280 | device_remove_file(&tz->device, &dev_attr_mode); | 1261 | device_remove_file(&tz->device, &dev_attr_mode); |
1281 | 1262 | ||
1282 | for (count = 0; count < tz->trips; count++) | 1263 | for (count = 0; count < tz->trips; count++) { |
1283 | TRIP_POINT_ATTR_REMOVE(&tz->device, count); | 1264 | device_remove_file(&tz->device, |
1284 | 1265 | &trip_point_attrs[count * 2]); | |
1266 | device_remove_file(&tz->device, | ||
1267 | &trip_point_attrs[count * 2 + 1]); | ||
1268 | } | ||
1285 | thermal_remove_hwmon_sysfs(tz); | 1269 | thermal_remove_hwmon_sysfs(tz); |
1286 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); | 1270 | release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); |
1287 | idr_destroy(&tz->idr); | 1271 | idr_destroy(&tz->idr); |
@@ -1289,7 +1273,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) | |||
1289 | device_unregister(&tz->device); | 1273 | device_unregister(&tz->device); |
1290 | return; | 1274 | return; |
1291 | } | 1275 | } |
1292 | |||
1293 | EXPORT_SYMBOL(thermal_zone_device_unregister); | 1276 | EXPORT_SYMBOL(thermal_zone_device_unregister); |
1294 | 1277 | ||
1295 | #ifdef CONFIG_NET | 1278 | #ifdef CONFIG_NET |
@@ -1312,10 +1295,11 @@ int thermal_generate_netlink_event(u32 orig, enum events event) | |||
1312 | void *msg_header; | 1295 | void *msg_header; |
1313 | int size; | 1296 | int size; |
1314 | int result; | 1297 | int result; |
1298 | static unsigned int thermal_event_seqnum; | ||
1315 | 1299 | ||
1316 | /* allocate memory */ | 1300 | /* allocate memory */ |
1317 | size = nla_total_size(sizeof(struct thermal_genl_event)) + \ | 1301 | size = nla_total_size(sizeof(struct thermal_genl_event)) + |
1318 | nla_total_size(0); | 1302 | nla_total_size(0); |
1319 | 1303 | ||
1320 | skb = genlmsg_new(size, GFP_ATOMIC); | 1304 | skb = genlmsg_new(size, GFP_ATOMIC); |
1321 | if (!skb) | 1305 | if (!skb) |
@@ -1331,8 +1315,8 @@ int thermal_generate_netlink_event(u32 orig, enum events event) | |||
1331 | } | 1315 | } |
1332 | 1316 | ||
1333 | /* fill the data */ | 1317 | /* fill the data */ |
1334 | attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, \ | 1318 | attr = nla_reserve(skb, THERMAL_GENL_ATTR_EVENT, |
1335 | sizeof(struct thermal_genl_event)); | 1319 | sizeof(struct thermal_genl_event)); |
1336 | 1320 | ||
1337 | if (!attr) { | 1321 | if (!attr) { |
1338 | nlmsg_free(skb); | 1322 | nlmsg_free(skb); |
@@ -1359,7 +1343,7 @@ int thermal_generate_netlink_event(u32 orig, enum events event) | |||
1359 | 1343 | ||
1360 | result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC); | 1344 | result = genlmsg_multicast(skb, 0, thermal_event_mcgrp.id, GFP_ATOMIC); |
1361 | if (result) | 1345 | if (result) |
1362 | printk(KERN_INFO "failed to send netlink event:%d", result); | 1346 | pr_info("failed to send netlink event:%d\n", result); |
1363 | 1347 | ||
1364 | return result; | 1348 | return result; |
1365 | } | 1349 | } |
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 712abcc205ae..6c26a3da0e03 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/kobject.h> | 16 | #include <linux/kobject.h> |
17 | #include <linux/completion.h> | 17 | #include <linux/completion.h> |
18 | #include <linux/hrtimer.h> | ||
18 | 19 | ||
19 | #define CPUIDLE_STATE_MAX 8 | 20 | #define CPUIDLE_STATE_MAX 8 |
20 | #define CPUIDLE_NAME_LEN 16 | 21 | #define CPUIDLE_NAME_LEN 16 |
@@ -43,12 +44,15 @@ struct cpuidle_state { | |||
43 | 44 | ||
44 | unsigned int flags; | 45 | unsigned int flags; |
45 | unsigned int exit_latency; /* in US */ | 46 | unsigned int exit_latency; /* in US */ |
46 | unsigned int power_usage; /* in mW */ | 47 | int power_usage; /* in mW */ |
47 | unsigned int target_residency; /* in US */ | 48 | unsigned int target_residency; /* in US */ |
49 | unsigned int disable; | ||
48 | 50 | ||
49 | int (*enter) (struct cpuidle_device *dev, | 51 | int (*enter) (struct cpuidle_device *dev, |
50 | struct cpuidle_driver *drv, | 52 | struct cpuidle_driver *drv, |
51 | int index); | 53 | int index); |
54 | |||
55 | int (*enter_dead) (struct cpuidle_device *dev, int index); | ||
52 | }; | 56 | }; |
53 | 57 | ||
54 | /* Idle State Flags */ | 58 | /* Idle State Flags */ |
@@ -96,7 +100,6 @@ struct cpuidle_device { | |||
96 | struct list_head device_list; | 100 | struct list_head device_list; |
97 | struct kobject kobj; | 101 | struct kobject kobj; |
98 | struct completion kobj_unregister; | 102 | struct completion kobj_unregister; |
99 | void *governor_data; | ||
100 | }; | 103 | }; |
101 | 104 | ||
102 | DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); | 105 | DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); |
@@ -118,10 +121,12 @@ static inline int cpuidle_get_last_residency(struct cpuidle_device *dev) | |||
118 | ****************************/ | 121 | ****************************/ |
119 | 122 | ||
120 | struct cpuidle_driver { | 123 | struct cpuidle_driver { |
121 | char name[CPUIDLE_NAME_LEN]; | 124 | const char *name; |
122 | struct module *owner; | 125 | struct module *owner; |
123 | 126 | ||
124 | unsigned int power_specified:1; | 127 | unsigned int power_specified:1; |
128 | /* set to 1 to use the core cpuidle time keeping (for all states). */ | ||
129 | unsigned int en_core_tk_irqen:1; | ||
125 | struct cpuidle_state states[CPUIDLE_STATE_MAX]; | 130 | struct cpuidle_state states[CPUIDLE_STATE_MAX]; |
126 | int state_count; | 131 | int state_count; |
127 | int safe_state_index; | 132 | int safe_state_index; |
@@ -140,6 +145,11 @@ extern void cpuidle_pause_and_lock(void); | |||
140 | extern void cpuidle_resume_and_unlock(void); | 145 | extern void cpuidle_resume_and_unlock(void); |
141 | extern int cpuidle_enable_device(struct cpuidle_device *dev); | 146 | extern int cpuidle_enable_device(struct cpuidle_device *dev); |
142 | extern void cpuidle_disable_device(struct cpuidle_device *dev); | 147 | extern void cpuidle_disable_device(struct cpuidle_device *dev); |
148 | extern int cpuidle_wrap_enter(struct cpuidle_device *dev, | ||
149 | struct cpuidle_driver *drv, int index, | ||
150 | int (*enter)(struct cpuidle_device *dev, | ||
151 | struct cpuidle_driver *drv, int index)); | ||
152 | extern int cpuidle_play_dead(void); | ||
143 | 153 | ||
144 | #else | 154 | #else |
145 | static inline void disable_cpuidle(void) { } | 155 | static inline void disable_cpuidle(void) { } |
@@ -157,6 +167,12 @@ static inline void cpuidle_resume_and_unlock(void) { } | |||
157 | static inline int cpuidle_enable_device(struct cpuidle_device *dev) | 167 | static inline int cpuidle_enable_device(struct cpuidle_device *dev) |
158 | {return -ENODEV; } | 168 | {return -ENODEV; } |
159 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } | 169 | static inline void cpuidle_disable_device(struct cpuidle_device *dev) { } |
170 | static inline int cpuidle_wrap_enter(struct cpuidle_device *dev, | ||
171 | struct cpuidle_driver *drv, int index, | ||
172 | int (*enter)(struct cpuidle_device *dev, | ||
173 | struct cpuidle_driver *drv, int index)) | ||
174 | { return -ENODEV; } | ||
175 | static inline int cpuidle_play_dead(void) {return -ENODEV; } | ||
160 | 176 | ||
161 | #endif | 177 | #endif |
162 | 178 | ||
diff --git a/include/linux/platform_data/spear_thermal.h b/include/linux/platform_data/spear_thermal.h new file mode 100644 index 000000000000..724f2e1cbbcb --- /dev/null +++ b/include/linux/platform_data/spear_thermal.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * SPEAr thermal driver platform data. | ||
3 | * | ||
4 | * Copyright (C) 2011-2012 ST Microelectronics | ||
5 | * Author: Vincenzo Frascino <vincenzo.frascino@st.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | #ifndef SPEAR_THERMAL_H | ||
18 | #define SPEAR_THERMAL_H | ||
19 | |||
20 | /* SPEAr Thermal Sensor Platform Data */ | ||
21 | struct spear_thermal_pdata { | ||
22 | /* flags used to enable thermal sensor */ | ||
23 | unsigned int thermal_flags; | ||
24 | }; | ||
25 | |||
26 | #endif /* SPEAR_THERMAL_H */ | ||
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 555c69a5592a..adf175f61496 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 | |||
@@ -4,11 +4,13 @@ turbostat \- Report processor frequency and idle statistics | |||
4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
5 | .ft B | 5 | .ft B |
6 | .B turbostat | 6 | .B turbostat |
7 | .RB [ "\-s" ] | ||
7 | .RB [ "\-v" ] | 8 | .RB [ "\-v" ] |
8 | .RB [ "\-M MSR#" ] | 9 | .RB [ "\-M MSR#" ] |
9 | .RB command | 10 | .RB command |
10 | .br | 11 | .br |
11 | .B turbostat | 12 | .B turbostat |
13 | .RB [ "\-s" ] | ||
12 | .RB [ "\-v" ] | 14 | .RB [ "\-v" ] |
13 | .RB [ "\-M MSR#" ] | 15 | .RB [ "\-M MSR#" ] |
14 | .RB [ "\-i interval_sec" ] | 16 | .RB [ "\-i interval_sec" ] |
@@ -25,6 +27,8 @@ supports an "invariant" TSC, plus the APERF and MPERF MSRs. | |||
25 | on processors that additionally support C-state residency counters. | 27 | on processors that additionally support C-state residency counters. |
26 | 28 | ||
27 | .SS Options | 29 | .SS Options |
30 | The \fB-s\fP option prints only a 1-line summary for each sample interval. | ||
31 | .PP | ||
28 | The \fB-v\fP option increases verbosity. | 32 | The \fB-v\fP option increases verbosity. |
29 | .PP | 33 | .PP |
30 | The \fB-M MSR#\fP option dumps the specified MSR, | 34 | The \fB-M MSR#\fP option dumps the specified MSR, |
@@ -39,13 +43,14 @@ displays the statistics gathered since it was forked. | |||
39 | .SH FIELD DESCRIPTIONS | 43 | .SH FIELD DESCRIPTIONS |
40 | .nf | 44 | .nf |
41 | \fBpk\fP processor package number. | 45 | \fBpk\fP processor package number. |
42 | \fBcr\fP processor core number. | 46 | \fBcor\fP processor core number. |
43 | \fBCPU\fP Linux CPU (logical processor) number. | 47 | \fBCPU\fP Linux CPU (logical processor) number. |
48 | Note that multiple CPUs per core indicate support for Intel(R) Hyper-Threading Technology. | ||
44 | \fB%c0\fP percent of the interval that the CPU retired instructions. | 49 | \fB%c0\fP percent of the interval that the CPU retired instructions. |
45 | \fBGHz\fP average clock rate while the CPU was in c0 state. | 50 | \fBGHz\fP average clock rate while the CPU was in c0 state. |
46 | \fBTSC\fP average GHz that the TSC ran during the entire interval. | 51 | \fBTSC\fP average GHz that the TSC ran during the entire interval. |
47 | \fB%c1, %c3, %c6\fP show the percentage residency in hardware core idle states. | 52 | \fB%c1, %c3, %c6, %c7\fP show the percentage residency in hardware core idle states. |
48 | \fB%pc3, %pc6\fP percentage residency in hardware package idle states. | 53 | \fB%pc2, %pc3, %pc6, %pc7\fP percentage residency in hardware package idle states. |
49 | .fi | 54 | .fi |
50 | .PP | 55 | .PP |
51 | .SH EXAMPLE | 56 | .SH EXAMPLE |
@@ -53,25 +58,37 @@ Without any parameters, turbostat prints out counters ever 5 seconds. | |||
53 | (override interval with "-i sec" option, or specify a command | 58 | (override interval with "-i sec" option, or specify a command |
54 | for turbostat to fork). | 59 | for turbostat to fork). |
55 | 60 | ||
56 | The first row of statistics reflect the average for the entire system. | 61 | The first row of statistics is a summary for the entire system. |
62 | Note that the summary is a weighted average. | ||
57 | Subsequent rows show per-CPU statistics. | 63 | Subsequent rows show per-CPU statistics. |
58 | 64 | ||
59 | .nf | 65 | .nf |
60 | [root@x980]# ./turbostat | 66 | [root@x980]# ./turbostat |
61 | cr CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 | 67 | cor CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 |
62 | 0.04 1.62 3.38 0.11 0.00 99.85 0.00 95.07 | 68 | 0.60 1.63 3.38 2.91 0.00 96.49 0.00 76.64 |
63 | 0 0 0.04 1.62 3.38 0.06 0.00 99.90 0.00 95.07 | 69 | 0 0 0.59 1.62 3.38 4.51 0.00 94.90 0.00 76.64 |
64 | 0 6 0.02 1.62 3.38 0.08 0.00 99.90 0.00 95.07 | 70 | 0 6 1.13 1.64 3.38 3.97 0.00 94.90 0.00 76.64 |
65 | 1 2 0.10 1.62 3.38 0.29 0.00 99.61 0.00 95.07 | 71 | 1 2 0.08 1.62 3.38 0.07 0.00 99.85 0.00 76.64 |
66 | 1 8 0.11 1.62 3.38 0.28 0.00 99.61 0.00 95.07 | 72 | 1 8 0.03 1.62 3.38 0.12 0.00 99.85 0.00 76.64 |
67 | 2 4 0.01 1.62 3.38 0.01 0.00 99.98 0.00 95.07 | 73 | 2 4 0.01 1.62 3.38 0.06 0.00 99.93 0.00 76.64 |
68 | 2 10 0.01 1.61 3.38 0.02 0.00 99.98 0.00 95.07 | 74 | 2 10 0.04 1.62 3.38 0.02 0.00 99.93 0.00 76.64 |
69 | 8 1 0.07 1.62 3.38 0.15 0.00 99.78 0.00 95.07 | 75 | 8 1 2.85 1.62 3.38 11.71 0.00 85.44 0.00 76.64 |
70 | 8 7 0.03 1.62 3.38 0.19 0.00 99.78 0.00 95.07 | 76 | 8 7 1.98 1.62 3.38 12.58 0.00 85.44 0.00 76.64 |
71 | 9 3 0.01 1.62 3.38 0.02 0.00 99.98 0.00 95.07 | 77 | 9 3 0.36 1.62 3.38 0.71 0.00 98.93 0.00 76.64 |
72 | 9 9 0.01 1.62 3.38 0.02 0.00 99.98 0.00 95.07 | 78 | 9 9 0.09 1.62 3.38 0.98 0.00 98.93 0.00 76.64 |
73 | 10 5 0.01 1.62 3.38 0.13 0.00 99.86 0.00 95.07 | 79 | 10 5 0.03 1.62 3.38 0.09 0.00 99.87 0.00 76.64 |
74 | 10 11 0.08 1.62 3.38 0.05 0.00 99.86 0.00 95.07 | 80 | 10 11 0.07 1.62 3.38 0.06 0.00 99.87 0.00 76.64 |
81 | .fi | ||
82 | .SH SUMMARY EXAMPLE | ||
83 | The "-s" option prints the column headers just once, | ||
84 | and then the one line system summary for each sample interval. | ||
85 | |||
86 | .nf | ||
87 | [root@x980]# ./turbostat -s | ||
88 | %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 | ||
89 | 0.61 1.89 3.38 5.95 0.00 93.44 0.00 66.33 | ||
90 | 0.52 1.62 3.38 6.83 0.00 92.65 0.00 61.11 | ||
91 | 0.62 1.92 3.38 5.47 0.00 93.91 0.00 67.31 | ||
75 | .fi | 92 | .fi |
76 | .SH VERBOSE EXAMPLE | 93 | .SH VERBOSE EXAMPLE |
77 | The "-v" option adds verbosity to the output: | 94 | The "-v" option adds verbosity to the output: |
@@ -101,33 +118,33 @@ until ^C while the other CPUs are mostly idle: | |||
101 | 118 | ||
102 | .nf | 119 | .nf |
103 | [root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null | 120 | [root@x980 lenb]# ./turbostat cat /dev/zero > /dev/null |
104 | 121 | ^C | |
105 | ^Ccr CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 | 122 | cor CPU %c0 GHz TSC %c1 %c3 %c6 %pc3 %pc6 |
106 | 8.49 3.63 3.38 16.23 0.66 74.63 0.00 0.00 | 123 | 8.63 3.64 3.38 14.46 0.49 76.42 0.00 0.00 |
107 | 0 0 1.22 3.62 3.38 32.18 0.00 66.60 0.00 0.00 | 124 | 0 0 0.34 3.36 3.38 99.66 0.00 0.00 0.00 0.00 |
108 | 0 6 0.40 3.61 3.38 33.00 0.00 66.60 0.00 0.00 | 125 | 0 6 99.96 3.64 3.38 0.04 0.00 0.00 0.00 0.00 |
109 | 1 2 0.11 3.14 3.38 0.19 3.95 95.75 0.00 0.00 | 126 | 1 2 0.14 3.50 3.38 1.75 2.04 96.07 0.00 0.00 |
110 | 1 8 0.05 2.88 3.38 0.25 3.95 95.75 0.00 0.00 | 127 | 1 8 0.38 3.57 3.38 1.51 2.04 96.07 0.00 0.00 |
111 | 2 4 0.00 3.13 3.38 0.02 0.00 99.98 0.00 0.00 | 128 | 2 4 0.01 2.65 3.38 0.06 0.00 99.93 0.00 0.00 |
112 | 2 10 0.00 3.09 3.38 0.02 0.00 99.98 0.00 0.00 | 129 | 2 10 0.03 2.12 3.38 0.04 0.00 99.93 0.00 0.00 |
113 | 8 1 0.04 3.50 3.38 14.43 0.00 85.54 0.00 0.00 | 130 | 8 1 0.91 3.59 3.38 35.27 0.92 62.90 0.00 0.00 |
114 | 8 7 0.03 2.98 3.38 14.43 0.00 85.54 0.00 0.00 | 131 | 8 7 1.61 3.63 3.38 34.57 0.92 62.90 0.00 0.00 |
115 | 9 3 0.00 3.16 3.38 100.00 0.00 0.00 0.00 0.00 | 132 | 9 3 0.04 3.38 3.38 0.20 0.00 99.76 0.00 0.00 |
116 | 9 9 99.93 3.63 3.38 0.06 0.00 0.00 0.00 0.00 | 133 | 9 9 0.04 3.29 3.38 0.20 0.00 99.76 0.00 0.00 |
117 | 10 5 0.01 2.82 3.38 0.08 0.00 99.91 0.00 0.00 | 134 | 10 5 0.03 3.08 3.38 0.12 0.00 99.85 0.00 0.00 |
118 | 10 11 0.02 3.36 3.38 0.06 0.00 99.91 0.00 0.00 | 135 | 10 11 0.05 3.07 3.38 0.10 0.00 99.85 0.00 0.00 |
119 | 6.950866 sec | 136 | 4.907015 sec |
120 | 137 | ||
121 | .fi | 138 | .fi |
122 | Above the cycle soaker drives cpu9 up 3.6 Ghz turbo limit | 139 | Above the cycle soaker drives cpu6 up 3.6 Ghz turbo limit |
123 | while the other processors are generally in various states of idle. | 140 | while the other processors are generally in various states of idle. |
124 | 141 | ||
125 | Note that cpu3 is an HT sibling sharing core9 | 142 | Note that cpu0 is an HT sibling sharing core0 |
126 | with cpu9, and thus it is unable to get to an idle state | 143 | with cpu6, and thus it is unable to get to an idle state |
127 | deeper than c1 while cpu9 is busy. | 144 | deeper than c1 while cpu6 is busy. |
128 | 145 | ||
129 | Note that turbostat reports average GHz of 3.61, while | 146 | Note that turbostat reports average GHz of 3.64, while |
130 | the arithmetic average of the GHz column above is 3.24. | 147 | the arithmetic average of the GHz column above is lower. |
131 | This is a weighted average, where the weight is %c0. ie. it is the total number of | 148 | This is a weighted average, where the weight is %c0. ie. it is the total number of |
132 | un-halted cycles elapsed per time divided by the number of CPUs. | 149 | un-halted cycles elapsed per time divided by the number of CPUs. |
133 | .SH NOTES | 150 | .SH NOTES |
@@ -167,6 +184,6 @@ http://www.intel.com/products/processor/manuals/ | |||
167 | .SH "SEE ALSO" | 184 | .SH "SEE ALSO" |
168 | msr(4), vmstat(8) | 185 | msr(4), vmstat(8) |
169 | .PP | 186 | .PP |
170 | .SH AUTHORS | 187 | .SH AUTHOR |
171 | .nf | 188 | .nf |
172 | Written by Len Brown <len.brown@intel.com> | 189 | Written by Len Brown <len.brown@intel.com> |
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 310d3dd5e547..ab2f682fd44c 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * turbostat -- show CPU frequency and C-state residency | 2 | * turbostat -- show CPU frequency and C-state residency |
3 | * on modern Intel turbo-capable processors. | 3 | * on modern Intel turbo-capable processors. |
4 | * | 4 | * |
5 | * Copyright (c) 2010, Intel Corporation. | 5 | * Copyright (c) 2012 Intel Corporation. |
6 | * Len Brown <len.brown@intel.com> | 6 | * Len Brown <len.brown@intel.com> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
@@ -19,6 +19,7 @@ | |||
19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 19 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define _GNU_SOURCE | ||
22 | #include <stdio.h> | 23 | #include <stdio.h> |
23 | #include <unistd.h> | 24 | #include <unistd.h> |
24 | #include <sys/types.h> | 25 | #include <sys/types.h> |
@@ -32,6 +33,7 @@ | |||
32 | #include <dirent.h> | 33 | #include <dirent.h> |
33 | #include <string.h> | 34 | #include <string.h> |
34 | #include <ctype.h> | 35 | #include <ctype.h> |
36 | #include <sched.h> | ||
35 | 37 | ||
36 | #define MSR_TSC 0x10 | 38 | #define MSR_TSC 0x10 |
37 | #define MSR_NEHALEM_PLATFORM_INFO 0xCE | 39 | #define MSR_NEHALEM_PLATFORM_INFO 0xCE |
@@ -49,6 +51,7 @@ | |||
49 | char *proc_stat = "/proc/stat"; | 51 | char *proc_stat = "/proc/stat"; |
50 | unsigned int interval_sec = 5; /* set with -i interval_sec */ | 52 | unsigned int interval_sec = 5; /* set with -i interval_sec */ |
51 | unsigned int verbose; /* set with -v */ | 53 | unsigned int verbose; /* set with -v */ |
54 | unsigned int summary_only; /* set with -s */ | ||
52 | unsigned int skip_c0; | 55 | unsigned int skip_c0; |
53 | unsigned int skip_c1; | 56 | unsigned int skip_c1; |
54 | unsigned int do_nhm_cstates; | 57 | unsigned int do_nhm_cstates; |
@@ -68,9 +71,10 @@ unsigned int show_cpu; | |||
68 | int aperf_mperf_unstable; | 71 | int aperf_mperf_unstable; |
69 | int backwards_count; | 72 | int backwards_count; |
70 | char *progname; | 73 | char *progname; |
71 | int need_reinitialize; | ||
72 | 74 | ||
73 | int num_cpus; | 75 | int num_cpus; |
76 | cpu_set_t *cpu_mask; | ||
77 | size_t cpu_mask_size; | ||
74 | 78 | ||
75 | struct counters { | 79 | struct counters { |
76 | unsigned long long tsc; /* per thread */ | 80 | unsigned long long tsc; /* per thread */ |
@@ -99,44 +103,76 @@ struct timeval tv_even; | |||
99 | struct timeval tv_odd; | 103 | struct timeval tv_odd; |
100 | struct timeval tv_delta; | 104 | struct timeval tv_delta; |
101 | 105 | ||
102 | unsigned long long get_msr(int cpu, off_t offset) | 106 | /* |
107 | * cpu_mask_init(ncpus) | ||
108 | * | ||
109 | * allocate and clear cpu_mask | ||
110 | * set cpu_mask_size | ||
111 | */ | ||
112 | void cpu_mask_init(int ncpus) | ||
113 | { | ||
114 | cpu_mask = CPU_ALLOC(ncpus); | ||
115 | if (cpu_mask == NULL) { | ||
116 | perror("CPU_ALLOC"); | ||
117 | exit(3); | ||
118 | } | ||
119 | cpu_mask_size = CPU_ALLOC_SIZE(ncpus); | ||
120 | CPU_ZERO_S(cpu_mask_size, cpu_mask); | ||
121 | } | ||
122 | |||
123 | void cpu_mask_uninit() | ||
124 | { | ||
125 | CPU_FREE(cpu_mask); | ||
126 | cpu_mask = NULL; | ||
127 | cpu_mask_size = 0; | ||
128 | } | ||
129 | |||
130 | int cpu_migrate(int cpu) | ||
131 | { | ||
132 | CPU_ZERO_S(cpu_mask_size, cpu_mask); | ||
133 | CPU_SET_S(cpu, cpu_mask_size, cpu_mask); | ||
134 | if (sched_setaffinity(0, cpu_mask_size, cpu_mask) == -1) | ||
135 | return -1; | ||
136 | else | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | int get_msr(int cpu, off_t offset, unsigned long long *msr) | ||
103 | { | 141 | { |
104 | ssize_t retval; | 142 | ssize_t retval; |
105 | unsigned long long msr; | ||
106 | char pathname[32]; | 143 | char pathname[32]; |
107 | int fd; | 144 | int fd; |
108 | 145 | ||
109 | sprintf(pathname, "/dev/cpu/%d/msr", cpu); | 146 | sprintf(pathname, "/dev/cpu/%d/msr", cpu); |
110 | fd = open(pathname, O_RDONLY); | 147 | fd = open(pathname, O_RDONLY); |
111 | if (fd < 0) { | 148 | if (fd < 0) |
112 | perror(pathname); | 149 | return -1; |
113 | need_reinitialize = 1; | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | retval = pread(fd, &msr, sizeof msr, offset); | ||
118 | if (retval != sizeof msr) { | ||
119 | fprintf(stderr, "cpu%d pread(..., 0x%zx) = %jd\n", | ||
120 | cpu, offset, retval); | ||
121 | exit(-2); | ||
122 | } | ||
123 | 150 | ||
151 | retval = pread(fd, msr, sizeof *msr, offset); | ||
124 | close(fd); | 152 | close(fd); |
125 | return msr; | 153 | |
154 | if (retval != sizeof *msr) | ||
155 | return -1; | ||
156 | |||
157 | return 0; | ||
126 | } | 158 | } |
127 | 159 | ||
128 | void print_header(void) | 160 | void print_header(void) |
129 | { | 161 | { |
130 | if (show_pkg) | 162 | if (show_pkg) |
131 | fprintf(stderr, "pk"); | 163 | fprintf(stderr, "pk"); |
164 | if (show_pkg) | ||
165 | fprintf(stderr, " "); | ||
132 | if (show_core) | 166 | if (show_core) |
133 | fprintf(stderr, " cr"); | 167 | fprintf(stderr, "cor"); |
134 | if (show_cpu) | 168 | if (show_cpu) |
135 | fprintf(stderr, " CPU"); | 169 | fprintf(stderr, " CPU"); |
170 | if (show_pkg || show_core || show_cpu) | ||
171 | fprintf(stderr, " "); | ||
136 | if (do_nhm_cstates) | 172 | if (do_nhm_cstates) |
137 | fprintf(stderr, " %%c0 "); | 173 | fprintf(stderr, " %%c0"); |
138 | if (has_aperf) | 174 | if (has_aperf) |
139 | fprintf(stderr, " GHz"); | 175 | fprintf(stderr, " GHz"); |
140 | fprintf(stderr, " TSC"); | 176 | fprintf(stderr, " TSC"); |
141 | if (do_nhm_cstates) | 177 | if (do_nhm_cstates) |
142 | fprintf(stderr, " %%c1"); | 178 | fprintf(stderr, " %%c1"); |
@@ -147,13 +183,13 @@ void print_header(void) | |||
147 | if (do_snb_cstates) | 183 | if (do_snb_cstates) |
148 | fprintf(stderr, " %%c7"); | 184 | fprintf(stderr, " %%c7"); |
149 | if (do_snb_cstates) | 185 | if (do_snb_cstates) |
150 | fprintf(stderr, " %%pc2"); | 186 | fprintf(stderr, " %%pc2"); |
151 | if (do_nhm_cstates) | 187 | if (do_nhm_cstates) |
152 | fprintf(stderr, " %%pc3"); | 188 | fprintf(stderr, " %%pc3"); |
153 | if (do_nhm_cstates) | 189 | if (do_nhm_cstates) |
154 | fprintf(stderr, " %%pc6"); | 190 | fprintf(stderr, " %%pc6"); |
155 | if (do_snb_cstates) | 191 | if (do_snb_cstates) |
156 | fprintf(stderr, " %%pc7"); | 192 | fprintf(stderr, " %%pc7"); |
157 | if (extra_msr_offset) | 193 | if (extra_msr_offset) |
158 | fprintf(stderr, " MSR 0x%x ", extra_msr_offset); | 194 | fprintf(stderr, " MSR 0x%x ", extra_msr_offset); |
159 | 195 | ||
@@ -187,6 +223,15 @@ void dump_list(struct counters *cnt) | |||
187 | dump_cnt(cnt); | 223 | dump_cnt(cnt); |
188 | } | 224 | } |
189 | 225 | ||
226 | /* | ||
227 | * column formatting convention & formats | ||
228 | * package: "pk" 2 columns %2d | ||
229 | * core: "cor" 3 columns %3d | ||
230 | * CPU: "CPU" 3 columns %3d | ||
231 | * GHz: "GHz" 3 columns %3.2 | ||
232 | * TSC: "TSC" 3 columns %3.2 | ||
233 | * percentage " %pc3" %6.2 | ||
234 | */ | ||
190 | void print_cnt(struct counters *p) | 235 | void print_cnt(struct counters *p) |
191 | { | 236 | { |
192 | double interval_float; | 237 | double interval_float; |
@@ -196,39 +241,45 @@ void print_cnt(struct counters *p) | |||
196 | /* topology columns, print blanks on 1st (average) line */ | 241 | /* topology columns, print blanks on 1st (average) line */ |
197 | if (p == cnt_average) { | 242 | if (p == cnt_average) { |
198 | if (show_pkg) | 243 | if (show_pkg) |
244 | fprintf(stderr, " "); | ||
245 | if (show_pkg && show_core) | ||
199 | fprintf(stderr, " "); | 246 | fprintf(stderr, " "); |
200 | if (show_core) | 247 | if (show_core) |
201 | fprintf(stderr, " "); | 248 | fprintf(stderr, " "); |
202 | if (show_cpu) | 249 | if (show_cpu) |
203 | fprintf(stderr, " "); | 250 | fprintf(stderr, " " " "); |
204 | } else { | 251 | } else { |
205 | if (show_pkg) | 252 | if (show_pkg) |
206 | fprintf(stderr, "%d", p->pkg); | 253 | fprintf(stderr, "%2d", p->pkg); |
254 | if (show_pkg && show_core) | ||
255 | fprintf(stderr, " "); | ||
207 | if (show_core) | 256 | if (show_core) |
208 | fprintf(stderr, "%4d", p->core); | 257 | fprintf(stderr, "%3d", p->core); |
209 | if (show_cpu) | 258 | if (show_cpu) |
210 | fprintf(stderr, "%4d", p->cpu); | 259 | fprintf(stderr, " %3d", p->cpu); |
211 | } | 260 | } |
212 | 261 | ||
213 | /* %c0 */ | 262 | /* %c0 */ |
214 | if (do_nhm_cstates) { | 263 | if (do_nhm_cstates) { |
264 | if (show_pkg || show_core || show_cpu) | ||
265 | fprintf(stderr, " "); | ||
215 | if (!skip_c0) | 266 | if (!skip_c0) |
216 | fprintf(stderr, "%7.2f", 100.0 * p->mperf/p->tsc); | 267 | fprintf(stderr, "%6.2f", 100.0 * p->mperf/p->tsc); |
217 | else | 268 | else |
218 | fprintf(stderr, " ****"); | 269 | fprintf(stderr, " ****"); |
219 | } | 270 | } |
220 | 271 | ||
221 | /* GHz */ | 272 | /* GHz */ |
222 | if (has_aperf) { | 273 | if (has_aperf) { |
223 | if (!aperf_mperf_unstable) { | 274 | if (!aperf_mperf_unstable) { |
224 | fprintf(stderr, "%5.2f", | 275 | fprintf(stderr, " %3.2f", |
225 | 1.0 * p->tsc / units * p->aperf / | 276 | 1.0 * p->tsc / units * p->aperf / |
226 | p->mperf / interval_float); | 277 | p->mperf / interval_float); |
227 | } else { | 278 | } else { |
228 | if (p->aperf > p->tsc || p->mperf > p->tsc) { | 279 | if (p->aperf > p->tsc || p->mperf > p->tsc) { |
229 | fprintf(stderr, " ****"); | 280 | fprintf(stderr, " ***"); |
230 | } else { | 281 | } else { |
231 | fprintf(stderr, "%4.1f*", | 282 | fprintf(stderr, "%3.1f*", |
232 | 1.0 * p->tsc / | 283 | 1.0 * p->tsc / |
233 | units * p->aperf / | 284 | units * p->aperf / |
234 | p->mperf / interval_float); | 285 | p->mperf / interval_float); |
@@ -241,7 +292,7 @@ void print_cnt(struct counters *p) | |||
241 | 292 | ||
242 | if (do_nhm_cstates) { | 293 | if (do_nhm_cstates) { |
243 | if (!skip_c1) | 294 | if (!skip_c1) |
244 | fprintf(stderr, "%7.2f", 100.0 * p->c1/p->tsc); | 295 | fprintf(stderr, " %6.2f", 100.0 * p->c1/p->tsc); |
245 | else | 296 | else |
246 | fprintf(stderr, " ****"); | 297 | fprintf(stderr, " ****"); |
247 | } | 298 | } |
@@ -252,13 +303,13 @@ void print_cnt(struct counters *p) | |||
252 | if (do_snb_cstates) | 303 | if (do_snb_cstates) |
253 | fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc); | 304 | fprintf(stderr, " %6.2f", 100.0 * p->c7/p->tsc); |
254 | if (do_snb_cstates) | 305 | if (do_snb_cstates) |
255 | fprintf(stderr, " %5.2f", 100.0 * p->pc2/p->tsc); | 306 | fprintf(stderr, " %6.2f", 100.0 * p->pc2/p->tsc); |
256 | if (do_nhm_cstates) | 307 | if (do_nhm_cstates) |
257 | fprintf(stderr, " %5.2f", 100.0 * p->pc3/p->tsc); | 308 | fprintf(stderr, " %6.2f", 100.0 * p->pc3/p->tsc); |
258 | if (do_nhm_cstates) | 309 | if (do_nhm_cstates) |
259 | fprintf(stderr, " %5.2f", 100.0 * p->pc6/p->tsc); | 310 | fprintf(stderr, " %6.2f", 100.0 * p->pc6/p->tsc); |
260 | if (do_snb_cstates) | 311 | if (do_snb_cstates) |
261 | fprintf(stderr, " %5.2f", 100.0 * p->pc7/p->tsc); | 312 | fprintf(stderr, " %6.2f", 100.0 * p->pc7/p->tsc); |
262 | if (extra_msr_offset) | 313 | if (extra_msr_offset) |
263 | fprintf(stderr, " 0x%016llx", p->extra_msr); | 314 | fprintf(stderr, " 0x%016llx", p->extra_msr); |
264 | putc('\n', stderr); | 315 | putc('\n', stderr); |
@@ -267,12 +318,20 @@ void print_cnt(struct counters *p) | |||
267 | void print_counters(struct counters *counters) | 318 | void print_counters(struct counters *counters) |
268 | { | 319 | { |
269 | struct counters *cnt; | 320 | struct counters *cnt; |
321 | static int printed; | ||
322 | |||
270 | 323 | ||
271 | print_header(); | 324 | if (!printed || !summary_only) |
325 | print_header(); | ||
272 | 326 | ||
273 | if (num_cpus > 1) | 327 | if (num_cpus > 1) |
274 | print_cnt(cnt_average); | 328 | print_cnt(cnt_average); |
275 | 329 | ||
330 | printed = 1; | ||
331 | |||
332 | if (summary_only) | ||
333 | return; | ||
334 | |||
276 | for (cnt = counters; cnt != NULL; cnt = cnt->next) | 335 | for (cnt = counters; cnt != NULL; cnt = cnt->next) |
277 | print_cnt(cnt); | 336 | print_cnt(cnt); |
278 | 337 | ||
@@ -440,31 +499,51 @@ void compute_average(struct counters *delta, struct counters *avg) | |||
440 | free(sum); | 499 | free(sum); |
441 | } | 500 | } |
442 | 501 | ||
443 | void get_counters(struct counters *cnt) | 502 | int get_counters(struct counters *cnt) |
444 | { | 503 | { |
445 | for ( ; cnt; cnt = cnt->next) { | 504 | for ( ; cnt; cnt = cnt->next) { |
446 | cnt->tsc = get_msr(cnt->cpu, MSR_TSC); | 505 | |
447 | if (do_nhm_cstates) | 506 | if (cpu_migrate(cnt->cpu)) |
448 | cnt->c3 = get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY); | 507 | return -1; |
449 | if (do_nhm_cstates) | 508 | |
450 | cnt->c6 = get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY); | 509 | if (get_msr(cnt->cpu, MSR_TSC, &cnt->tsc)) |
451 | if (do_snb_cstates) | 510 | return -1; |
452 | cnt->c7 = get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY); | 511 | |
453 | if (has_aperf) | 512 | if (has_aperf) { |
454 | cnt->aperf = get_msr(cnt->cpu, MSR_APERF); | 513 | if (get_msr(cnt->cpu, MSR_APERF, &cnt->aperf)) |
455 | if (has_aperf) | 514 | return -1; |
456 | cnt->mperf = get_msr(cnt->cpu, MSR_MPERF); | 515 | if (get_msr(cnt->cpu, MSR_MPERF, &cnt->mperf)) |
457 | if (do_snb_cstates) | 516 | return -1; |
458 | cnt->pc2 = get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY); | 517 | } |
459 | if (do_nhm_cstates) | 518 | |
460 | cnt->pc3 = get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY); | 519 | if (do_nhm_cstates) { |
461 | if (do_nhm_cstates) | 520 | if (get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY, &cnt->c3)) |
462 | cnt->pc6 = get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY); | 521 | return -1; |
522 | if (get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY, &cnt->c6)) | ||
523 | return -1; | ||
524 | } | ||
525 | |||
463 | if (do_snb_cstates) | 526 | if (do_snb_cstates) |
464 | cnt->pc7 = get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY); | 527 | if (get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY, &cnt->c7)) |
528 | return -1; | ||
529 | |||
530 | if (do_nhm_cstates) { | ||
531 | if (get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY, &cnt->pc3)) | ||
532 | return -1; | ||
533 | if (get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY, &cnt->pc6)) | ||
534 | return -1; | ||
535 | } | ||
536 | if (do_snb_cstates) { | ||
537 | if (get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY, &cnt->pc2)) | ||
538 | return -1; | ||
539 | if (get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY, &cnt->pc7)) | ||
540 | return -1; | ||
541 | } | ||
465 | if (extra_msr_offset) | 542 | if (extra_msr_offset) |
466 | cnt->extra_msr = get_msr(cnt->cpu, extra_msr_offset); | 543 | if (get_msr(cnt->cpu, extra_msr_offset, &cnt->extra_msr)) |
544 | return -1; | ||
467 | } | 545 | } |
546 | return 0; | ||
468 | } | 547 | } |
469 | 548 | ||
470 | void print_nehalem_info(void) | 549 | void print_nehalem_info(void) |
@@ -475,7 +554,7 @@ void print_nehalem_info(void) | |||
475 | if (!do_nehalem_platform_info) | 554 | if (!do_nehalem_platform_info) |
476 | return; | 555 | return; |
477 | 556 | ||
478 | msr = get_msr(0, MSR_NEHALEM_PLATFORM_INFO); | 557 | get_msr(0, MSR_NEHALEM_PLATFORM_INFO, &msr); |
479 | 558 | ||
480 | ratio = (msr >> 40) & 0xFF; | 559 | ratio = (msr >> 40) & 0xFF; |
481 | fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", | 560 | fprintf(stderr, "%d * %.0f = %.0f MHz max efficiency\n", |
@@ -491,7 +570,7 @@ void print_nehalem_info(void) | |||
491 | if (!do_nehalem_turbo_ratio_limit) | 570 | if (!do_nehalem_turbo_ratio_limit) |
492 | return; | 571 | return; |
493 | 572 | ||
494 | msr = get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT); | 573 | get_msr(0, MSR_NEHALEM_TURBO_RATIO_LIMIT, &msr); |
495 | 574 | ||
496 | ratio = (msr >> 24) & 0xFF; | 575 | ratio = (msr >> 24) & 0xFF; |
497 | if (ratio) | 576 | if (ratio) |
@@ -557,7 +636,8 @@ void insert_counters(struct counters **list, | |||
557 | return; | 636 | return; |
558 | } | 637 | } |
559 | 638 | ||
560 | show_cpu = 1; /* there is more than one CPU */ | 639 | if (!summary_only) |
640 | show_cpu = 1; /* there is more than one CPU */ | ||
561 | 641 | ||
562 | /* | 642 | /* |
563 | * insert on front of list. | 643 | * insert on front of list. |
@@ -575,13 +655,15 @@ void insert_counters(struct counters **list, | |||
575 | 655 | ||
576 | while (prev->next && (prev->next->pkg < new->pkg)) { | 656 | while (prev->next && (prev->next->pkg < new->pkg)) { |
577 | prev = prev->next; | 657 | prev = prev->next; |
578 | show_pkg = 1; /* there is more than 1 package */ | 658 | if (!summary_only) |
659 | show_pkg = 1; /* there is more than 1 package */ | ||
579 | } | 660 | } |
580 | 661 | ||
581 | while (prev->next && (prev->next->pkg == new->pkg) | 662 | while (prev->next && (prev->next->pkg == new->pkg) |
582 | && (prev->next->core < new->core)) { | 663 | && (prev->next->core < new->core)) { |
583 | prev = prev->next; | 664 | prev = prev->next; |
584 | show_core = 1; /* there is more than 1 core */ | 665 | if (!summary_only) |
666 | show_core = 1; /* there is more than 1 core */ | ||
585 | } | 667 | } |
586 | 668 | ||
587 | while (prev->next && (prev->next->pkg == new->pkg) | 669 | while (prev->next && (prev->next->pkg == new->pkg) |
@@ -681,7 +763,7 @@ int get_core_id(int cpu) | |||
681 | } | 763 | } |
682 | 764 | ||
683 | /* | 765 | /* |
684 | * run func(index, cpu) on every cpu in /proc/stat | 766 | * run func(pkg, core, cpu) on every cpu in /proc/stat |
685 | */ | 767 | */ |
686 | 768 | ||
687 | int for_all_cpus(void (func)(int, int, int)) | 769 | int for_all_cpus(void (func)(int, int, int)) |
@@ -717,18 +799,18 @@ int for_all_cpus(void (func)(int, int, int)) | |||
717 | 799 | ||
718 | void re_initialize(void) | 800 | void re_initialize(void) |
719 | { | 801 | { |
720 | printf("turbostat: topology changed, re-initializing.\n"); | ||
721 | free_all_counters(); | 802 | free_all_counters(); |
722 | num_cpus = for_all_cpus(alloc_new_counters); | 803 | num_cpus = for_all_cpus(alloc_new_counters); |
723 | need_reinitialize = 0; | 804 | cpu_mask_uninit(); |
724 | printf("num_cpus is now %d\n", num_cpus); | 805 | cpu_mask_init(num_cpus); |
806 | printf("turbostat: re-initialized with num_cpus %d\n", num_cpus); | ||
725 | } | 807 | } |
726 | 808 | ||
727 | void dummy(int pkg, int core, int cpu) { return; } | 809 | void dummy(int pkg, int core, int cpu) { return; } |
728 | /* | 810 | /* |
729 | * check to see if a cpu came on-line | 811 | * check to see if a cpu came on-line |
730 | */ | 812 | */ |
731 | void verify_num_cpus(void) | 813 | int verify_num_cpus(void) |
732 | { | 814 | { |
733 | int new_num_cpus; | 815 | int new_num_cpus; |
734 | 816 | ||
@@ -738,8 +820,9 @@ void verify_num_cpus(void) | |||
738 | if (verbose) | 820 | if (verbose) |
739 | printf("num_cpus was %d, is now %d\n", | 821 | printf("num_cpus was %d, is now %d\n", |
740 | num_cpus, new_num_cpus); | 822 | num_cpus, new_num_cpus); |
741 | need_reinitialize = 1; | 823 | return -1; |
742 | } | 824 | } |
825 | return 0; | ||
743 | } | 826 | } |
744 | 827 | ||
745 | void turbostat_loop() | 828 | void turbostat_loop() |
@@ -749,25 +832,25 @@ restart: | |||
749 | gettimeofday(&tv_even, (struct timezone *)NULL); | 832 | gettimeofday(&tv_even, (struct timezone *)NULL); |
750 | 833 | ||
751 | while (1) { | 834 | while (1) { |
752 | verify_num_cpus(); | 835 | if (verify_num_cpus()) { |
753 | if (need_reinitialize) { | ||
754 | re_initialize(); | 836 | re_initialize(); |
755 | goto restart; | 837 | goto restart; |
756 | } | 838 | } |
757 | sleep(interval_sec); | 839 | sleep(interval_sec); |
758 | get_counters(cnt_odd); | 840 | if (get_counters(cnt_odd)) { |
841 | re_initialize(); | ||
842 | goto restart; | ||
843 | } | ||
759 | gettimeofday(&tv_odd, (struct timezone *)NULL); | 844 | gettimeofday(&tv_odd, (struct timezone *)NULL); |
760 | |||
761 | compute_delta(cnt_odd, cnt_even, cnt_delta); | 845 | compute_delta(cnt_odd, cnt_even, cnt_delta); |
762 | timersub(&tv_odd, &tv_even, &tv_delta); | 846 | timersub(&tv_odd, &tv_even, &tv_delta); |
763 | compute_average(cnt_delta, cnt_average); | 847 | compute_average(cnt_delta, cnt_average); |
764 | print_counters(cnt_delta); | 848 | print_counters(cnt_delta); |
765 | if (need_reinitialize) { | 849 | sleep(interval_sec); |
850 | if (get_counters(cnt_even)) { | ||
766 | re_initialize(); | 851 | re_initialize(); |
767 | goto restart; | 852 | goto restart; |
768 | } | 853 | } |
769 | sleep(interval_sec); | ||
770 | get_counters(cnt_even); | ||
771 | gettimeofday(&tv_even, (struct timezone *)NULL); | 854 | gettimeofday(&tv_even, (struct timezone *)NULL); |
772 | compute_delta(cnt_even, cnt_odd, cnt_delta); | 855 | compute_delta(cnt_even, cnt_odd, cnt_delta); |
773 | timersub(&tv_even, &tv_odd, &tv_delta); | 856 | timersub(&tv_even, &tv_odd, &tv_delta); |
@@ -953,6 +1036,7 @@ void turbostat_init() | |||
953 | check_super_user(); | 1036 | check_super_user(); |
954 | 1037 | ||
955 | num_cpus = for_all_cpus(alloc_new_counters); | 1038 | num_cpus = for_all_cpus(alloc_new_counters); |
1039 | cpu_mask_init(num_cpus); | ||
956 | 1040 | ||
957 | if (verbose) | 1041 | if (verbose) |
958 | print_nehalem_info(); | 1042 | print_nehalem_info(); |
@@ -1005,8 +1089,11 @@ void cmdline(int argc, char **argv) | |||
1005 | 1089 | ||
1006 | progname = argv[0]; | 1090 | progname = argv[0]; |
1007 | 1091 | ||
1008 | while ((opt = getopt(argc, argv, "+vi:M:")) != -1) { | 1092 | while ((opt = getopt(argc, argv, "+svi:M:")) != -1) { |
1009 | switch (opt) { | 1093 | switch (opt) { |
1094 | case 's': | ||
1095 | summary_only++; | ||
1096 | break; | ||
1010 | case 'v': | 1097 | case 'v': |
1011 | verbose++; | 1098 | verbose++; |
1012 | break; | 1099 | break; |