diff options
149 files changed, 2983 insertions, 1690 deletions
diff --git a/Documentation/ABI/testing/sysfs-devices-soc b/Documentation/ABI/testing/sysfs-devices-soc new file mode 100644 index 000000000000..6d9cc253f2b2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-devices-soc | |||
@@ -0,0 +1,58 @@ | |||
1 | What: /sys/devices/socX | ||
2 | Date: January 2012 | ||
3 | contact: Lee Jones <lee.jones@linaro.org> | ||
4 | Description: | ||
5 | The /sys/devices/ directory contains a sub-directory for each | ||
6 | System-on-Chip (SoC) device on a running platform. Information | ||
7 | regarding each SoC can be obtained by reading sysfs files. This | ||
8 | functionality is only available if implemented by the platform. | ||
9 | |||
10 | The directory created for each SoC will also house information | ||
11 | about devices which are commonly contained in /sys/devices/platform. | ||
12 | It has been agreed that if an SoC device exists, its supported | ||
13 | devices would be better suited to appear as children of that SoC. | ||
14 | |||
15 | What: /sys/devices/socX/machine | ||
16 | Date: January 2012 | ||
17 | contact: Lee Jones <lee.jones@linaro.org> | ||
18 | Description: | ||
19 | Read-only attribute common to all SoCs. Contains the SoC machine | ||
20 | name (e.g. Ux500). | ||
21 | |||
22 | What: /sys/devices/socX/family | ||
23 | Date: January 2012 | ||
24 | contact: Lee Jones <lee.jones@linaro.org> | ||
25 | Description: | ||
26 | Read-only attribute common to all SoCs. Contains SoC family name | ||
27 | (e.g. DB8500). | ||
28 | |||
29 | What: /sys/devices/socX/soc_id | ||
30 | Date: January 2012 | ||
31 | contact: Lee Jones <lee.jones@linaro.org> | ||
32 | Description: | ||
33 | Read-only attribute supported by most SoCs. In the case of | ||
34 | ST-Ericsson's chips this contains the SoC serial number. | ||
35 | |||
36 | What: /sys/devices/socX/revision | ||
37 | Date: January 2012 | ||
38 | contact: Lee Jones <lee.jones@linaro.org> | ||
39 | Description: | ||
40 | Read-only attribute supported by most SoCs. Contains the SoC's | ||
41 | manufacturing revision number. | ||
42 | |||
43 | What: /sys/devices/socX/process | ||
44 | Date: January 2012 | ||
45 | contact: Lee Jones <lee.jones@linaro.org> | ||
46 | Description: | ||
47 | Read-only attribute supported ST-Ericsson's silicon. Contains the | ||
48 | the process by which the silicon chip was manufactured. | ||
49 | |||
50 | What: /sys/bus/soc | ||
51 | Date: January 2012 | ||
52 | contact: Lee Jones <lee.jones@linaro.org> | ||
53 | Description: | ||
54 | The /sys/bus/soc/ directory contains the usual sub-folders | ||
55 | expected under most buses. /sys/bus/soc/devices is of particular | ||
56 | interest, as it contains a symlink for each SoC device found on | ||
57 | the system. Each symlink points back into the aforementioned | ||
58 | /sys/devices/socX devices. | ||
diff --git a/Documentation/devicetree/bindings/arm/twd.txt b/Documentation/devicetree/bindings/arm/twd.txt new file mode 100644 index 000000000000..75b8610939fa --- /dev/null +++ b/Documentation/devicetree/bindings/arm/twd.txt | |||
@@ -0,0 +1,48 @@ | |||
1 | * ARM Timer Watchdog | ||
2 | |||
3 | ARM 11MP, Cortex-A5 and Cortex-A9 are often associated with a per-core | ||
4 | Timer-Watchdog (aka TWD), which provides both a per-cpu local timer | ||
5 | and watchdog. | ||
6 | |||
7 | The TWD is usually attached to a GIC to deliver its two per-processor | ||
8 | interrupts. | ||
9 | |||
10 | ** Timer node required properties: | ||
11 | |||
12 | - compatible : Should be one of: | ||
13 | "arm,cortex-a9-twd-timer" | ||
14 | "arm,cortex-a5-twd-timer" | ||
15 | "arm,arm11mp-twd-timer" | ||
16 | |||
17 | - interrupts : One interrupt to each core | ||
18 | |||
19 | - reg : Specify the base address and the size of the TWD timer | ||
20 | register window. | ||
21 | |||
22 | Example: | ||
23 | |||
24 | twd-timer@2c000600 { | ||
25 | compatible = "arm,arm11mp-twd-timer""; | ||
26 | reg = <0x2c000600 0x20>; | ||
27 | interrupts = <1 13 0xf01>; | ||
28 | }; | ||
29 | |||
30 | ** Watchdog node properties: | ||
31 | |||
32 | - compatible : Should be one of: | ||
33 | "arm,cortex-a9-twd-wdt" | ||
34 | "arm,cortex-a5-twd-wdt" | ||
35 | "arm,arm11mp-twd-wdt" | ||
36 | |||
37 | - interrupts : One interrupt to each core | ||
38 | |||
39 | - reg : Specify the base address and the size of the TWD watchdog | ||
40 | register window. | ||
41 | |||
42 | Example: | ||
43 | |||
44 | twd-watchdog@2c000620 { | ||
45 | compatible = "arm,arm11mp-twd-wdt"; | ||
46 | reg = <0x2c000620 0x20>; | ||
47 | interrupts = <1 14 0xf01>; | ||
48 | }; | ||
diff --git a/Documentation/dynamic-debug-howto.txt b/Documentation/dynamic-debug-howto.txt index f959909d7154..74e6c7782678 100644 --- a/Documentation/dynamic-debug-howto.txt +++ b/Documentation/dynamic-debug-howto.txt | |||
@@ -12,7 +12,7 @@ dynamically enabled per-callsite. | |||
12 | Dynamic debug has even more useful features: | 12 | Dynamic debug has even more useful features: |
13 | 13 | ||
14 | * Simple query language allows turning on and off debugging statements by | 14 | * Simple query language allows turning on and off debugging statements by |
15 | matching any combination of: | 15 | matching any combination of 0 or 1 of: |
16 | 16 | ||
17 | - source filename | 17 | - source filename |
18 | - function name | 18 | - function name |
@@ -79,31 +79,24 @@ Command Language Reference | |||
79 | ========================== | 79 | ========================== |
80 | 80 | ||
81 | At the lexical level, a command comprises a sequence of words separated | 81 | At the lexical level, a command comprises a sequence of words separated |
82 | by whitespace characters. Note that newlines are treated as word | 82 | by spaces or tabs. So these are all equivalent: |
83 | separators and do *not* end a command or allow multiple commands to | ||
84 | be done together. So these are all equivalent: | ||
85 | 83 | ||
86 | nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' > | 84 | nullarbor:~ # echo -c 'file svcsock.c line 1603 +p' > |
87 | <debugfs>/dynamic_debug/control | 85 | <debugfs>/dynamic_debug/control |
88 | nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' > | 86 | nullarbor:~ # echo -c ' file svcsock.c line 1603 +p ' > |
89 | <debugfs>/dynamic_debug/control | 87 | <debugfs>/dynamic_debug/control |
90 | nullarbor:~ # echo -c 'file svcsock.c\nline 1603 +p' > | ||
91 | <debugfs>/dynamic_debug/control | ||
92 | nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > | 88 | nullarbor:~ # echo -n 'file svcsock.c line 1603 +p' > |
93 | <debugfs>/dynamic_debug/control | 89 | <debugfs>/dynamic_debug/control |
94 | 90 | ||
95 | Commands are bounded by a write() system call. If you want to do | 91 | Command submissions are bounded by a write() system call. |
96 | multiple commands you need to do a separate "echo" for each, like: | 92 | Multiple commands can be written together, separated by ';' or '\n'. |
97 | 93 | ||
98 | nullarbor:~ # echo 'file svcsock.c line 1603 +p' > /proc/dprintk ;\ | 94 | ~# echo "func pnpacpi_get_resources +p; func pnp_assign_mem +p" \ |
99 | > echo 'file svcsock.c line 1563 +p' > /proc/dprintk | 95 | > <debugfs>/dynamic_debug/control |
100 | 96 | ||
101 | or even like: | 97 | If your query set is big, you can batch them too: |
102 | 98 | ||
103 | nullarbor:~ # ( | 99 | ~# cat query-batch-file > <debugfs>/dynamic_debug/control |
104 | > echo 'file svcsock.c line 1603 +p' ;\ | ||
105 | > echo 'file svcsock.c line 1563 +p' ;\ | ||
106 | > ) > /proc/dprintk | ||
107 | 100 | ||
108 | At the syntactical level, a command comprises a sequence of match | 101 | At the syntactical level, a command comprises a sequence of match |
109 | specifications, followed by a flags change specification. | 102 | specifications, followed by a flags change specification. |
@@ -144,11 +137,12 @@ func | |||
144 | func svc_tcp_accept | 137 | func svc_tcp_accept |
145 | 138 | ||
146 | file | 139 | file |
147 | The given string is compared against either the full | 140 | The given string is compared against either the full pathname, the |
148 | pathname or the basename of the source file of each | 141 | src-root relative pathname, or the basename of the source file of |
149 | callsite. Examples: | 142 | each callsite. Examples: |
150 | 143 | ||
151 | file svcsock.c | 144 | file svcsock.c |
145 | file kernel/freezer.c | ||
152 | file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c | 146 | file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c |
153 | 147 | ||
154 | module | 148 | module |
diff --git a/Documentation/filesystems/debugfs.txt b/Documentation/filesystems/debugfs.txt index 6872c91bce35..4e2575873187 100644 --- a/Documentation/filesystems/debugfs.txt +++ b/Documentation/filesystems/debugfs.txt | |||
@@ -14,7 +14,10 @@ Debugfs is typically mounted with a command like: | |||
14 | 14 | ||
15 | mount -t debugfs none /sys/kernel/debug | 15 | mount -t debugfs none /sys/kernel/debug |
16 | 16 | ||
17 | (Or an equivalent /etc/fstab line). | 17 | (Or an equivalent /etc/fstab line). |
18 | The debugfs root directory is accessible by anyone by default. To | ||
19 | restrict access to the tree the "uid", "gid" and "mode" mount | ||
20 | options can be used. | ||
18 | 21 | ||
19 | Note that the debugfs API is exported GPL-only to modules. | 22 | Note that the debugfs API is exported GPL-only to modules. |
20 | 23 | ||
diff --git a/arch/arm/boot/dts/db8500.dtsi b/arch/arm/boot/dts/db8500.dtsi new file mode 100644 index 000000000000..d73dce645667 --- /dev/null +++ b/arch/arm/boot/dts/db8500.dtsi | |||
@@ -0,0 +1,275 @@ | |||
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/ "skeleton.dtsi" | ||
13 | |||
14 | / { | ||
15 | soc-u9500 { | ||
16 | #address-cells = <1>; | ||
17 | #size-cells = <1>; | ||
18 | compatible = "stericsson,db8500"; | ||
19 | interrupt-parent = <&intc>; | ||
20 | ranges; | ||
21 | |||
22 | intc: interrupt-controller@a0411000 { | ||
23 | compatible = "arm,cortex-a9-gic"; | ||
24 | #interrupt-cells = <3>; | ||
25 | #address-cells = <1>; | ||
26 | interrupt-controller; | ||
27 | interrupt-parent; | ||
28 | reg = <0xa0411000 0x1000>, | ||
29 | <0xa0410100 0x100>; | ||
30 | }; | ||
31 | |||
32 | L2: l2-cache { | ||
33 | compatible = "arm,pl310-cache"; | ||
34 | reg = <0xa0412000 0x1000>; | ||
35 | interrupts = <0 13 4>; | ||
36 | cache-unified; | ||
37 | cache-level = <2>; | ||
38 | }; | ||
39 | |||
40 | pmu { | ||
41 | compatible = "arm,cortex-a9-pmu"; | ||
42 | interrupts = <0 7 0x4>; | ||
43 | }; | ||
44 | |||
45 | timer@a0410600 { | ||
46 | compatible = "arm,cortex-a9-twd-timer"; | ||
47 | reg = <0xa0410600 0x20>; | ||
48 | interrupts = <1 13 0x304>; | ||
49 | }; | ||
50 | |||
51 | rtc@80154000 { | ||
52 | compatible = "stericsson,db8500-rtc"; | ||
53 | reg = <0x80154000 0x1000>; | ||
54 | interrupts = <0 18 0x4>; | ||
55 | }; | ||
56 | |||
57 | gpio0: gpio@8012e000 { | ||
58 | compatible = "stericsson,db8500-gpio", | ||
59 | "stmicroelectronics,nomadik-gpio"; | ||
60 | reg = <0x8012e000 0x80>; | ||
61 | interrupts = <0 119 0x4>; | ||
62 | supports-sleepmode; | ||
63 | gpio-controller; | ||
64 | }; | ||
65 | |||
66 | gpio1: gpio@8012e080 { | ||
67 | compatible = "stericsson,db8500-gpio", | ||
68 | "stmicroelectronics,nomadik-gpio"; | ||
69 | reg = <0x8012e080 0x80>; | ||
70 | interrupts = <0 120 0x4>; | ||
71 | supports-sleepmode; | ||
72 | gpio-controller; | ||
73 | }; | ||
74 | |||
75 | gpio2: gpio@8000e000 { | ||
76 | compatible = "stericsson,db8500-gpio", | ||
77 | "stmicroelectronics,nomadik-gpio"; | ||
78 | reg = <0x8000e000 0x80>; | ||
79 | interrupts = <0 121 0x4>; | ||
80 | supports-sleepmode; | ||
81 | gpio-controller; | ||
82 | }; | ||
83 | |||
84 | gpio3: gpio@8000e080 { | ||
85 | compatible = "stericsson,db8500-gpio", | ||
86 | "stmicroelectronics,nomadik-gpio"; | ||
87 | reg = <0x8000e080 0x80>; | ||
88 | interrupts = <0 122 0x4>; | ||
89 | supports-sleepmode; | ||
90 | gpio-controller; | ||
91 | }; | ||
92 | |||
93 | gpio4: gpio@8000e100 { | ||
94 | compatible = "stericsson,db8500-gpio", | ||
95 | "stmicroelectronics,nomadik-gpio"; | ||
96 | reg = <0x8000e100 0x80>; | ||
97 | interrupts = <0 123 0x4>; | ||
98 | supports-sleepmode; | ||
99 | gpio-controller; | ||
100 | }; | ||
101 | |||
102 | gpio5: gpio@8000e180 { | ||
103 | compatible = "stericsson,db8500-gpio", | ||
104 | "stmicroelectronics,nomadik-gpio"; | ||
105 | reg = <0x8000e180 0x80>; | ||
106 | interrupts = <0 124 0x4>; | ||
107 | supports-sleepmode; | ||
108 | gpio-controller; | ||
109 | }; | ||
110 | |||
111 | gpio6: gpio@8011e000 { | ||
112 | compatible = "stericsson,db8500-gpio", | ||
113 | "stmicroelectronics,nomadik-gpio"; | ||
114 | reg = <0x8011e000 0x80>; | ||
115 | interrupts = <0 125 0x4>; | ||
116 | supports-sleepmode; | ||
117 | gpio-controller; | ||
118 | }; | ||
119 | |||
120 | gpio7: gpio@8011e080 { | ||
121 | compatible = "stericsson,db8500-gpio", | ||
122 | "stmicroelectronics,nomadik-gpio"; | ||
123 | reg = <0x8011e080 0x80>; | ||
124 | interrupts = <0 126 0x4>; | ||
125 | supports-sleepmode; | ||
126 | gpio-controller; | ||
127 | }; | ||
128 | |||
129 | gpio8: gpio@a03fe000 { | ||
130 | compatible = "stericsson,db8500-gpio", | ||
131 | "stmicroelectronics,nomadik-gpio"; | ||
132 | reg = <0xa03fe000 0x80>; | ||
133 | interrupts = <0 127 0x4>; | ||
134 | supports-sleepmode; | ||
135 | gpio-controller; | ||
136 | }; | ||
137 | |||
138 | usb@a03e0000 { | ||
139 | compatible = "stericsson,db8500-musb", | ||
140 | "mentor,musb"; | ||
141 | reg = <0xa03e0000 0x10000>; | ||
142 | interrupts = <0 23 0x4>; | ||
143 | }; | ||
144 | |||
145 | dma-controller@801C0000 { | ||
146 | compatible = "stericsson,db8500-dma40", | ||
147 | "stericsson,dma40"; | ||
148 | reg = <0x801C0000 0x1000 0x40010000 0x800>; | ||
149 | interrupts = <0 25 0x4>; | ||
150 | }; | ||
151 | |||
152 | prcmu@80157000 { | ||
153 | compatible = "stericsson,db8500-prcmu"; | ||
154 | reg = <0x80157000 0x1000>; | ||
155 | interrupts = <46 47>; | ||
156 | #address-cells = <1>; | ||
157 | #size-cells = <0>; | ||
158 | |||
159 | ab8500@5 { | ||
160 | compatible = "stericsson,ab8500"; | ||
161 | reg = <5>; /* mailbox 5 is i2c */ | ||
162 | interrupts = <0 40 0x4>; | ||
163 | }; | ||
164 | }; | ||
165 | |||
166 | i2c@80004000 { | ||
167 | compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c"; | ||
168 | reg = <0x80004000 0x1000>; | ||
169 | interrupts = <0 21 0x4>; | ||
170 | #address-cells = <1>; | ||
171 | #size-cells = <0>; | ||
172 | }; | ||
173 | |||
174 | i2c@80122000 { | ||
175 | compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c"; | ||
176 | reg = <0x80122000 0x1000>; | ||
177 | interrupts = <0 22 0x4>; | ||
178 | #address-cells = <1>; | ||
179 | #size-cells = <0>; | ||
180 | }; | ||
181 | |||
182 | i2c@80128000 { | ||
183 | compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c"; | ||
184 | reg = <0x80128000 0x1000>; | ||
185 | interrupts = <0 55 0x4>; | ||
186 | #address-cells = <1>; | ||
187 | #size-cells = <0>; | ||
188 | }; | ||
189 | |||
190 | i2c@80110000 { | ||
191 | compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c"; | ||
192 | reg = <0x80110000 0x1000>; | ||
193 | interrupts = <0 12 0x4>; | ||
194 | #address-cells = <1>; | ||
195 | #size-cells = <0>; | ||
196 | }; | ||
197 | |||
198 | i2c@8012a000 { | ||
199 | compatible = "stericsson,db8500-i2c", "stmicroelectronics,nomadik-i2c"; | ||
200 | reg = <0x8012a000 0x1000>; | ||
201 | interrupts = <0 51 0x4>; | ||
202 | #address-cells = <1>; | ||
203 | #size-cells = <0>; | ||
204 | }; | ||
205 | |||
206 | ssp@80002000 { | ||
207 | compatible = "arm,pl022", "arm,primecell"; | ||
208 | reg = <80002000 0x1000>; | ||
209 | interrupts = <0 14 0x4>; | ||
210 | #address-cells = <1>; | ||
211 | #size-cells = <0>; | ||
212 | status = "disabled"; | ||
213 | |||
214 | // Add one of these for each child device | ||
215 | cs-gpios = <&gpio0 31 &gpio4 14 &gpio4 16 &gpio6 22 &gpio7 0>; | ||
216 | |||
217 | }; | ||
218 | |||
219 | uart@80120000 { | ||
220 | compatible = "arm,pl011", "arm,primecell"; | ||
221 | reg = <0x80120000 0x1000>; | ||
222 | interrupts = <0 11 0x4>; | ||
223 | status = "disabled"; | ||
224 | }; | ||
225 | uart@80121000 { | ||
226 | compatible = "arm,pl011", "arm,primecell"; | ||
227 | reg = <0x80121000 0x1000>; | ||
228 | interrupts = <0 19 0x4>; | ||
229 | status = "disabled"; | ||
230 | }; | ||
231 | uart@80007000 { | ||
232 | compatible = "arm,pl011", "arm,primecell"; | ||
233 | reg = <0x80007000 0x1000>; | ||
234 | interrupts = <0 26 0x4>; | ||
235 | status = "disabled"; | ||
236 | }; | ||
237 | |||
238 | sdi@80126000 { | ||
239 | compatible = "arm,pl18x", "arm,primecell"; | ||
240 | reg = <0x80126000 0x1000>; | ||
241 | interrupts = <0 60 0x4>; | ||
242 | status = "disabled"; | ||
243 | }; | ||
244 | sdi@80118000 { | ||
245 | compatible = "arm,pl18x", "arm,primecell"; | ||
246 | reg = <0x80118000 0x1000>; | ||
247 | interrupts = <0 50 0x4>; | ||
248 | status = "disabled"; | ||
249 | }; | ||
250 | sdi@80005000 { | ||
251 | compatible = "arm,pl18x", "arm,primecell"; | ||
252 | reg = <0x80005000 0x1000>; | ||
253 | interrupts = <0 41 0x4>; | ||
254 | status = "disabled"; | ||
255 | }; | ||
256 | sdi@80119000 { | ||
257 | compatible = "arm,pl18x", "arm,primecell"; | ||
258 | reg = <0x80119000 0x1000>; | ||
259 | interrupts = <0 59 0x4>; | ||
260 | status = "disabled"; | ||
261 | }; | ||
262 | sdi@80114000 { | ||
263 | compatible = "arm,pl18x", "arm,primecell"; | ||
264 | reg = <0x80114000 0x1000>; | ||
265 | interrupts = <0 99 0x4>; | ||
266 | status = "disabled"; | ||
267 | }; | ||
268 | sdi@80008000 { | ||
269 | compatible = "arm,pl18x", "arm,primecell"; | ||
270 | reg = <0x80114000 0x1000>; | ||
271 | interrupts = <0 100 0x4>; | ||
272 | status = "disabled"; | ||
273 | }; | ||
274 | }; | ||
275 | }; | ||
diff --git a/arch/arm/boot/dts/highbank.dts b/arch/arm/boot/dts/highbank.dts index 305635bd45c0..37c0ff9c8b90 100644 --- a/arch/arm/boot/dts/highbank.dts +++ b/arch/arm/boot/dts/highbank.dts | |||
@@ -72,15 +72,15 @@ | |||
72 | ranges; | 72 | ranges; |
73 | 73 | ||
74 | timer@fff10600 { | 74 | timer@fff10600 { |
75 | compatible = "arm,smp-twd"; | 75 | compatible = "arm,cortex-a9-twd-timer"; |
76 | reg = <0xfff10600 0x20>; | 76 | reg = <0xfff10600 0x20>; |
77 | interrupts = <1 13 0xf04>; | 77 | interrupts = <1 13 0xf01>; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | watchdog@fff10620 { | 80 | watchdog@fff10620 { |
81 | compatible = "arm,cortex-a9-wdt"; | 81 | compatible = "arm,cortex-a9-twd-wdt"; |
82 | reg = <0xfff10620 0x20>; | 82 | reg = <0xfff10620 0x20>; |
83 | interrupts = <1 14 0xf04>; | 83 | interrupts = <1 14 0xf01>; |
84 | }; | 84 | }; |
85 | 85 | ||
86 | intc: interrupt-controller@fff11000 { | 86 | intc: interrupt-controller@fff11000 { |
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi index 263e8f3664b5..4905f51a106f 100644 --- a/arch/arm/boot/dts/imx6q.dtsi +++ b/arch/arm/boot/dts/imx6q.dtsi | |||
@@ -88,9 +88,9 @@ | |||
88 | ranges; | 88 | ranges; |
89 | 89 | ||
90 | timer@00a00600 { | 90 | timer@00a00600 { |
91 | compatible = "arm,smp-twd"; | 91 | compatible = "arm,cortex-a9-twd-timer"; |
92 | reg = <0x00a00600 0x100>; | 92 | reg = <0x00a00600 0x20>; |
93 | interrupts = <1 13 0xf4>; | 93 | interrupts = <1 13 0xf01>; |
94 | }; | 94 | }; |
95 | 95 | ||
96 | L2: l2-cache@00a02000 { | 96 | L2: l2-cache@00a02000 { |
diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts new file mode 100644 index 000000000000..359c6d679156 --- /dev/null +++ b/arch/arm/boot/dts/snowball.dts | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Copyright 2011 ST-Ericsson AB | ||
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 | /dts-v1/; | ||
13 | /include/ "db8500.dtsi" | ||
14 | |||
15 | / { | ||
16 | model = "Calao Systems Snowball platform with device tree"; | ||
17 | compatible = "calaosystems,snowball-a9500"; | ||
18 | |||
19 | memory { | ||
20 | reg = <0x00000000 0x20000000>; | ||
21 | }; | ||
22 | |||
23 | gpio_keys { | ||
24 | compatible = "gpio-keys"; | ||
25 | #address-cells = <1>; | ||
26 | #size-cells = <0>; | ||
27 | |||
28 | button@1 { | ||
29 | debounce_interval = <50>; | ||
30 | wakeup = <1>; | ||
31 | linux,code = <2>; | ||
32 | label = "userpb"; | ||
33 | gpios = <&gpio1 0>; | ||
34 | }; | ||
35 | button@2 { | ||
36 | debounce_interval = <50>; | ||
37 | wakeup = <1>; | ||
38 | linux,code = <3>; | ||
39 | label = "userpb"; | ||
40 | gpios = <&gpio4 23>; | ||
41 | }; | ||
42 | button@3 { | ||
43 | debounce_interval = <50>; | ||
44 | wakeup = <1>; | ||
45 | linux,code = <4>; | ||
46 | label = "userpb"; | ||
47 | gpios = <&gpio4 23>; | ||
48 | }; | ||
49 | button@4 { | ||
50 | debounce_interval = <50>; | ||
51 | wakeup = <1>; | ||
52 | linux,code = <5>; | ||
53 | label = "userpb"; | ||
54 | gpios = <&gpio5 1>; | ||
55 | }; | ||
56 | button@5 { | ||
57 | debounce_interval = <50>; | ||
58 | wakeup = <1>; | ||
59 | linux,code = <6>; | ||
60 | label = "userpb"; | ||
61 | gpios = <&gpio5 2>; | ||
62 | }; | ||
63 | }; | ||
64 | |||
65 | leds { | ||
66 | compatible = "gpio-leds"; | ||
67 | used-led { | ||
68 | label = "user_led"; | ||
69 | gpios = <&gpio4 14>; | ||
70 | }; | ||
71 | }; | ||
72 | |||
73 | soc-u9500 { | ||
74 | |||
75 | external-bus@50000000 { | ||
76 | compatible = "simple-bus"; | ||
77 | reg = <0x50000000 0x10000000>; | ||
78 | #address-cells = <1>; | ||
79 | #size-cells = <1>; | ||
80 | ranges; | ||
81 | |||
82 | ethernet@50000000 { | ||
83 | compatible = "smsc,9111"; | ||
84 | reg = <0x50000000 0x10000>; | ||
85 | interrupts = <12>; | ||
86 | interrupt-parent = <&gpio4>; | ||
87 | }; | ||
88 | }; | ||
89 | |||
90 | sdi@80126000 { | ||
91 | status = "enabled"; | ||
92 | cd-gpios = <&gpio6 26>; | ||
93 | }; | ||
94 | |||
95 | sdi@80114000 { | ||
96 | status = "enabled"; | ||
97 | }; | ||
98 | |||
99 | uart@80120000 { | ||
100 | status = "okay"; | ||
101 | }; | ||
102 | |||
103 | uart@80121000 { | ||
104 | status = "okay"; | ||
105 | }; | ||
106 | |||
107 | uart@80007000 { | ||
108 | status = "okay"; | ||
109 | }; | ||
110 | |||
111 | i2c@80004000 { | ||
112 | tc3589x@42 { | ||
113 | //compatible = "tc3589x"; | ||
114 | reg = <0x42>; | ||
115 | interrupts = <25>; | ||
116 | interrupt-parent = <&gpio6>; | ||
117 | }; | ||
118 | tps61052@33 { | ||
119 | //compatible = "tps61052"; | ||
120 | reg = <0x33>; | ||
121 | }; | ||
122 | }; | ||
123 | |||
124 | i2c@80128000 { | ||
125 | lp5521@0x33 { | ||
126 | // compatible = "lp5521"; | ||
127 | reg = <0x33>; | ||
128 | }; | ||
129 | lp5521@0x34 { | ||
130 | // compatible = "lp5521"; | ||
131 | reg = <0x34>; | ||
132 | }; | ||
133 | bh1780@0x29 { | ||
134 | // compatible = "rohm,bh1780gli"; | ||
135 | reg = <0x33>; | ||
136 | }; | ||
137 | }; | ||
138 | }; | ||
139 | }; | ||
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 2d7b6e7b7271..889d73ac1ae1 100644 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig | |||
@@ -13,6 +13,7 @@ CONFIG_UX500_SOC_DB8500=y | |||
13 | CONFIG_MACH_HREFV60=y | 13 | CONFIG_MACH_HREFV60=y |
14 | CONFIG_MACH_SNOWBALL=y | 14 | CONFIG_MACH_SNOWBALL=y |
15 | CONFIG_MACH_U5500=y | 15 | CONFIG_MACH_U5500=y |
16 | CONFIG_MACH_UX500_DT=y | ||
16 | CONFIG_NO_HZ=y | 17 | CONFIG_NO_HZ=y |
17 | CONFIG_HIGH_RES_TIMERS=y | 18 | CONFIG_HIGH_RES_TIMERS=y |
18 | CONFIG_SMP=y | 19 | CONFIG_SMP=y |
diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h index c6a18424888e..f77ffc1eb0c2 100644 --- a/arch/arm/include/asm/localtimer.h +++ b/arch/arm/include/asm/localtimer.h | |||
@@ -11,47 +11,24 @@ | |||
11 | #define __ASM_ARM_LOCALTIMER_H | 11 | #define __ASM_ARM_LOCALTIMER_H |
12 | 12 | ||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/interrupt.h> | ||
15 | 14 | ||
16 | struct clock_event_device; | 15 | struct clock_event_device; |
17 | 16 | ||
18 | /* | 17 | struct local_timer_ops { |
19 | * Setup a per-cpu timer, whether it be a local timer or dummy broadcast | 18 | int (*setup)(struct clock_event_device *); |
20 | */ | 19 | void (*stop)(struct clock_event_device *); |
21 | void percpu_timer_setup(void); | 20 | }; |
22 | 21 | ||
23 | #ifdef CONFIG_LOCAL_TIMERS | 22 | #ifdef CONFIG_LOCAL_TIMERS |
24 | |||
25 | #ifdef CONFIG_HAVE_ARM_TWD | ||
26 | |||
27 | #include "smp_twd.h" | ||
28 | |||
29 | #define local_timer_stop(c) twd_timer_stop((c)) | ||
30 | |||
31 | #else | ||
32 | |||
33 | /* | ||
34 | * Stop the local timer | ||
35 | */ | ||
36 | void local_timer_stop(struct clock_event_device *); | ||
37 | |||
38 | #endif | ||
39 | |||
40 | /* | 23 | /* |
41 | * Setup a local timer interrupt for a CPU. | 24 | * Register a local timer driver |
42 | */ | 25 | */ |
43 | int local_timer_setup(struct clock_event_device *); | 26 | int local_timer_register(struct local_timer_ops *); |
44 | |||
45 | #else | 27 | #else |
46 | 28 | static inline int local_timer_register(struct local_timer_ops *ops) | |
47 | static inline int local_timer_setup(struct clock_event_device *evt) | ||
48 | { | 29 | { |
49 | return -ENXIO; | 30 | return -ENXIO; |
50 | } | 31 | } |
51 | |||
52 | static inline void local_timer_stop(struct clock_event_device *evt) | ||
53 | { | ||
54 | } | ||
55 | #endif | 32 | #endif |
56 | 33 | ||
57 | #endif | 34 | #endif |
diff --git a/arch/arm/include/asm/smp_twd.h b/arch/arm/include/asm/smp_twd.h index ef9ffba97ad8..0f01f4677bd2 100644 --- a/arch/arm/include/asm/smp_twd.h +++ b/arch/arm/include/asm/smp_twd.h | |||
@@ -18,11 +18,28 @@ | |||
18 | #define TWD_TIMER_CONTROL_PERIODIC (1 << 1) | 18 | #define TWD_TIMER_CONTROL_PERIODIC (1 << 1) |
19 | #define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) | 19 | #define TWD_TIMER_CONTROL_IT_ENABLE (1 << 2) |
20 | 20 | ||
21 | struct clock_event_device; | 21 | #include <linux/ioport.h> |
22 | 22 | ||
23 | extern void __iomem *twd_base; | 23 | struct twd_local_timer { |
24 | struct resource res[2]; | ||
25 | }; | ||
24 | 26 | ||
25 | void twd_timer_setup(struct clock_event_device *); | 27 | #define DEFINE_TWD_LOCAL_TIMER(name,base,irq) \ |
26 | void twd_timer_stop(struct clock_event_device *); | 28 | struct twd_local_timer name __initdata = { \ |
29 | .res = { \ | ||
30 | DEFINE_RES_MEM(base, 0x10), \ | ||
31 | DEFINE_RES_IRQ(irq), \ | ||
32 | }, \ | ||
33 | }; | ||
34 | |||
35 | int twd_local_timer_register(struct twd_local_timer *); | ||
36 | |||
37 | #ifdef CONFIG_HAVE_ARM_TWD | ||
38 | void twd_local_timer_of_register(void); | ||
39 | #else | ||
40 | static inline void twd_local_timer_of_register(void) | ||
41 | { | ||
42 | } | ||
43 | #endif | ||
27 | 44 | ||
28 | #endif | 45 | #endif |
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index cdeb727527d3..1ad84a6c9bfb 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c | |||
@@ -246,6 +246,8 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) | |||
246 | store_cpu_topology(cpuid); | 246 | store_cpu_topology(cpuid); |
247 | } | 247 | } |
248 | 248 | ||
249 | static void percpu_timer_setup(void); | ||
250 | |||
249 | /* | 251 | /* |
250 | * This is the secondary CPU boot entry. We're using this CPUs | 252 | * This is the secondary CPU boot entry. We're using this CPUs |
251 | * idle thread stack, but a set of temporary page tables. | 253 | * idle thread stack, but a set of temporary page tables. |
@@ -459,7 +461,20 @@ static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt) | |||
459 | clockevents_register_device(evt); | 461 | clockevents_register_device(evt); |
460 | } | 462 | } |
461 | 463 | ||
462 | void __cpuinit percpu_timer_setup(void) | 464 | static struct local_timer_ops *lt_ops; |
465 | |||
466 | #ifdef CONFIG_LOCAL_TIMERS | ||
467 | int local_timer_register(struct local_timer_ops *ops) | ||
468 | { | ||
469 | if (lt_ops) | ||
470 | return -EBUSY; | ||
471 | |||
472 | lt_ops = ops; | ||
473 | return 0; | ||
474 | } | ||
475 | #endif | ||
476 | |||
477 | static void __cpuinit percpu_timer_setup(void) | ||
463 | { | 478 | { |
464 | unsigned int cpu = smp_processor_id(); | 479 | unsigned int cpu = smp_processor_id(); |
465 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | 480 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); |
@@ -467,7 +482,7 @@ void __cpuinit percpu_timer_setup(void) | |||
467 | evt->cpumask = cpumask_of(cpu); | 482 | evt->cpumask = cpumask_of(cpu); |
468 | evt->broadcast = smp_timer_broadcast; | 483 | evt->broadcast = smp_timer_broadcast; |
469 | 484 | ||
470 | if (local_timer_setup(evt)) | 485 | if (!lt_ops || lt_ops->setup(evt)) |
471 | broadcast_timer_setup(evt); | 486 | broadcast_timer_setup(evt); |
472 | } | 487 | } |
473 | 488 | ||
@@ -482,7 +497,8 @@ static void percpu_timer_stop(void) | |||
482 | unsigned int cpu = smp_processor_id(); | 497 | unsigned int cpu = smp_processor_id(); |
483 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); | 498 | struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); |
484 | 499 | ||
485 | local_timer_stop(evt); | 500 | if (lt_ops) |
501 | lt_ops->stop(evt); | ||
486 | } | 502 | } |
487 | #endif | 503 | #endif |
488 | 504 | ||
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index 7a79b24597b2..fef42b21cecb 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c | |||
@@ -18,20 +18,23 @@ | |||
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
20 | #include <linux/clockchips.h> | 20 | #include <linux/clockchips.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
23 | #include <linux/of_irq.h> | ||
24 | #include <linux/of_address.h> | ||
23 | 25 | ||
24 | #include <asm/smp_twd.h> | 26 | #include <asm/smp_twd.h> |
25 | #include <asm/localtimer.h> | 27 | #include <asm/localtimer.h> |
26 | #include <asm/hardware/gic.h> | 28 | #include <asm/hardware/gic.h> |
27 | 29 | ||
28 | /* set up by the platform code */ | 30 | /* set up by the platform code */ |
29 | void __iomem *twd_base; | 31 | static void __iomem *twd_base; |
30 | 32 | ||
31 | static struct clk *twd_clk; | 33 | static struct clk *twd_clk; |
32 | static unsigned long twd_timer_rate; | 34 | static unsigned long twd_timer_rate; |
33 | 35 | ||
34 | static struct clock_event_device __percpu **twd_evt; | 36 | static struct clock_event_device __percpu **twd_evt; |
37 | static int twd_ppi; | ||
35 | 38 | ||
36 | static void twd_set_mode(enum clock_event_mode mode, | 39 | static void twd_set_mode(enum clock_event_mode mode, |
37 | struct clock_event_device *clk) | 40 | struct clock_event_device *clk) |
@@ -77,7 +80,7 @@ static int twd_set_next_event(unsigned long evt, | |||
77 | * If a local timer interrupt has occurred, acknowledge and return 1. | 80 | * If a local timer interrupt has occurred, acknowledge and return 1. |
78 | * Otherwise, return 0. | 81 | * Otherwise, return 0. |
79 | */ | 82 | */ |
80 | int twd_timer_ack(void) | 83 | static int twd_timer_ack(void) |
81 | { | 84 | { |
82 | if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { | 85 | if (__raw_readl(twd_base + TWD_TIMER_INTSTAT)) { |
83 | __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); | 86 | __raw_writel(1, twd_base + TWD_TIMER_INTSTAT); |
@@ -87,7 +90,7 @@ int twd_timer_ack(void) | |||
87 | return 0; | 90 | return 0; |
88 | } | 91 | } |
89 | 92 | ||
90 | void twd_timer_stop(struct clock_event_device *clk) | 93 | static void twd_timer_stop(struct clock_event_device *clk) |
91 | { | 94 | { |
92 | twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); | 95 | twd_set_mode(CLOCK_EVT_MODE_UNUSED, clk); |
93 | disable_percpu_irq(clk->irq); | 96 | disable_percpu_irq(clk->irq); |
@@ -222,28 +225,10 @@ static struct clk *twd_get_clock(void) | |||
222 | /* | 225 | /* |
223 | * Setup the local clock events for a CPU. | 226 | * Setup the local clock events for a CPU. |
224 | */ | 227 | */ |
225 | void __cpuinit twd_timer_setup(struct clock_event_device *clk) | 228 | static int __cpuinit twd_timer_setup(struct clock_event_device *clk) |
226 | { | 229 | { |
227 | struct clock_event_device **this_cpu_clk; | 230 | struct clock_event_device **this_cpu_clk; |
228 | 231 | ||
229 | if (!twd_evt) { | ||
230 | int err; | ||
231 | |||
232 | twd_evt = alloc_percpu(struct clock_event_device *); | ||
233 | if (!twd_evt) { | ||
234 | pr_err("twd: can't allocate memory\n"); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | err = request_percpu_irq(clk->irq, twd_handler, | ||
239 | "twd", twd_evt); | ||
240 | if (err) { | ||
241 | pr_err("twd: can't register interrupt %d (%d)\n", | ||
242 | clk->irq, err); | ||
243 | return; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | if (!twd_clk) | 232 | if (!twd_clk) |
248 | twd_clk = twd_get_clock(); | 233 | twd_clk = twd_get_clock(); |
249 | 234 | ||
@@ -260,6 +245,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
260 | clk->rating = 350; | 245 | clk->rating = 350; |
261 | clk->set_mode = twd_set_mode; | 246 | clk->set_mode = twd_set_mode; |
262 | clk->set_next_event = twd_set_next_event; | 247 | clk->set_next_event = twd_set_next_event; |
248 | clk->irq = twd_ppi; | ||
263 | 249 | ||
264 | this_cpu_clk = __this_cpu_ptr(twd_evt); | 250 | this_cpu_clk = __this_cpu_ptr(twd_evt); |
265 | *this_cpu_clk = clk; | 251 | *this_cpu_clk = clk; |
@@ -267,4 +253,95 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk) | |||
267 | clockevents_config_and_register(clk, twd_timer_rate, | 253 | clockevents_config_and_register(clk, twd_timer_rate, |
268 | 0xf, 0xffffffff); | 254 | 0xf, 0xffffffff); |
269 | enable_percpu_irq(clk->irq, 0); | 255 | enable_percpu_irq(clk->irq, 0); |
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static struct local_timer_ops twd_lt_ops __cpuinitdata = { | ||
261 | .setup = twd_timer_setup, | ||
262 | .stop = twd_timer_stop, | ||
263 | }; | ||
264 | |||
265 | static int __init twd_local_timer_common_register(void) | ||
266 | { | ||
267 | int err; | ||
268 | |||
269 | twd_evt = alloc_percpu(struct clock_event_device *); | ||
270 | if (!twd_evt) { | ||
271 | err = -ENOMEM; | ||
272 | goto out_free; | ||
273 | } | ||
274 | |||
275 | err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt); | ||
276 | if (err) { | ||
277 | pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err); | ||
278 | goto out_free; | ||
279 | } | ||
280 | |||
281 | err = local_timer_register(&twd_lt_ops); | ||
282 | if (err) | ||
283 | goto out_irq; | ||
284 | |||
285 | return 0; | ||
286 | |||
287 | out_irq: | ||
288 | free_percpu_irq(twd_ppi, twd_evt); | ||
289 | out_free: | ||
290 | iounmap(twd_base); | ||
291 | twd_base = NULL; | ||
292 | free_percpu(twd_evt); | ||
293 | |||
294 | return err; | ||
270 | } | 295 | } |
296 | |||
297 | int __init twd_local_timer_register(struct twd_local_timer *tlt) | ||
298 | { | ||
299 | if (twd_base || twd_evt) | ||
300 | return -EBUSY; | ||
301 | |||
302 | twd_ppi = tlt->res[1].start; | ||
303 | |||
304 | twd_base = ioremap(tlt->res[0].start, resource_size(&tlt->res[0])); | ||
305 | if (!twd_base) | ||
306 | return -ENOMEM; | ||
307 | |||
308 | return twd_local_timer_common_register(); | ||
309 | } | ||
310 | |||
311 | #ifdef CONFIG_OF | ||
312 | const static struct of_device_id twd_of_match[] __initconst = { | ||
313 | { .compatible = "arm,cortex-a9-twd-timer", }, | ||
314 | { .compatible = "arm,cortex-a5-twd-timer", }, | ||
315 | { .compatible = "arm,arm11mp-twd-timer", }, | ||
316 | { }, | ||
317 | }; | ||
318 | |||
319 | void __init twd_local_timer_of_register(void) | ||
320 | { | ||
321 | struct device_node *np; | ||
322 | int err; | ||
323 | |||
324 | np = of_find_matching_node(NULL, twd_of_match); | ||
325 | if (!np) { | ||
326 | err = -ENODEV; | ||
327 | goto out; | ||
328 | } | ||
329 | |||
330 | twd_ppi = irq_of_parse_and_map(np, 0); | ||
331 | if (!twd_ppi) { | ||
332 | err = -EINVAL; | ||
333 | goto out; | ||
334 | } | ||
335 | |||
336 | twd_base = of_iomap(np, 0); | ||
337 | if (!twd_base) { | ||
338 | err = -ENOMEM; | ||
339 | goto out; | ||
340 | } | ||
341 | |||
342 | err = twd_local_timer_common_register(); | ||
343 | |||
344 | out: | ||
345 | WARN(err, "twd_local_timer_of_register failed (%d)\n", err); | ||
346 | } | ||
347 | #endif | ||
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 85b5527d0918..edc4b9488f2f 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/percpu.h> | 21 | #include <linux/percpu.h> |
22 | 22 | ||
23 | #include <asm/hardware/gic.h> | 23 | #include <asm/hardware/gic.h> |
24 | #include <asm/localtimer.h> | ||
24 | 25 | ||
25 | #include <plat/cpu.h> | 26 | #include <plat/cpu.h> |
26 | 27 | ||
@@ -375,7 +376,7 @@ static struct irqaction mct_tick1_event_irq = { | |||
375 | .handler = exynos4_mct_tick_isr, | 376 | .handler = exynos4_mct_tick_isr, |
376 | }; | 377 | }; |
377 | 378 | ||
378 | static void exynos4_mct_tick_init(struct clock_event_device *evt) | 379 | static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) |
379 | { | 380 | { |
380 | struct mct_clock_event_device *mevt; | 381 | struct mct_clock_event_device *mevt; |
381 | unsigned int cpu = smp_processor_id(); | 382 | unsigned int cpu = smp_processor_id(); |
@@ -417,17 +418,11 @@ static void exynos4_mct_tick_init(struct clock_event_device *evt) | |||
417 | } else { | 418 | } else { |
418 | enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0); | 419 | enable_percpu_irq(IRQ_MCT_LOCALTIMER, 0); |
419 | } | 420 | } |
420 | } | ||
421 | |||
422 | /* Setup the local clock events for a CPU */ | ||
423 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
424 | { | ||
425 | exynos4_mct_tick_init(evt); | ||
426 | 421 | ||
427 | return 0; | 422 | return 0; |
428 | } | 423 | } |
429 | 424 | ||
430 | void local_timer_stop(struct clock_event_device *evt) | 425 | static void exynos4_local_timer_stop(struct clock_event_device *evt) |
431 | { | 426 | { |
432 | unsigned int cpu = smp_processor_id(); | 427 | unsigned int cpu = smp_processor_id(); |
433 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | 428 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); |
@@ -439,6 +434,11 @@ void local_timer_stop(struct clock_event_device *evt) | |||
439 | else | 434 | else |
440 | disable_percpu_irq(IRQ_MCT_LOCALTIMER); | 435 | disable_percpu_irq(IRQ_MCT_LOCALTIMER); |
441 | } | 436 | } |
437 | |||
438 | static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { | ||
439 | .setup = exynos4_local_timer_setup, | ||
440 | .stop = exynos4_local_timer_stop, | ||
441 | }; | ||
442 | #endif /* CONFIG_LOCAL_TIMERS */ | 442 | #endif /* CONFIG_LOCAL_TIMERS */ |
443 | 443 | ||
444 | static void __init exynos4_timer_resources(void) | 444 | static void __init exynos4_timer_resources(void) |
@@ -458,6 +458,8 @@ static void __init exynos4_timer_resources(void) | |||
458 | WARN(err, "MCT: can't request IRQ %d (%d)\n", | 458 | WARN(err, "MCT: can't request IRQ %d (%d)\n", |
459 | IRQ_MCT_LOCALTIMER, err); | 459 | IRQ_MCT_LOCALTIMER, err); |
460 | } | 460 | } |
461 | |||
462 | local_timer_register(&exynos4_mct_tick_ops); | ||
461 | #endif /* CONFIG_LOCAL_TIMERS */ | 463 | #endif /* CONFIG_LOCAL_TIMERS */ |
462 | } | 464 | } |
463 | 465 | ||
diff --git a/arch/arm/mach-highbank/Makefile b/arch/arm/mach-highbank/Makefile index 986958a5a720..f8437dd238c2 100644 --- a/arch/arm/mach-highbank/Makefile +++ b/arch/arm/mach-highbank/Makefile | |||
@@ -1,6 +1,5 @@ | |||
1 | obj-y := clock.o highbank.o system.o | 1 | obj-y := clock.o highbank.o system.o |
2 | obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o | 2 | obj-$(CONFIG_DEBUG_HIGHBANK_UART) += lluart.o |
3 | obj-$(CONFIG_SMP) += platsmp.o | 3 | obj-$(CONFIG_SMP) += platsmp.o |
4 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
5 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 4 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
6 | obj-$(CONFIG_PM_SLEEP) += pm.o | 5 | obj-$(CONFIG_PM_SLEEP) += pm.o |
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c index 8394d512a402..bb1684f9b68b 100644 --- a/arch/arm/mach-highbank/highbank.c +++ b/arch/arm/mach-highbank/highbank.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/cacheflush.h> | 27 | #include <asm/cacheflush.h> |
28 | #include <asm/smp_plat.h> | 28 | #include <asm/smp_plat.h> |
29 | #include <asm/smp_scu.h> | 29 | #include <asm/smp_scu.h> |
30 | #include <asm/smp_twd.h> | ||
30 | #include <asm/hardware/arm_timer.h> | 31 | #include <asm/hardware/arm_timer.h> |
31 | #include <asm/hardware/timer-sp.h> | 32 | #include <asm/hardware/timer-sp.h> |
32 | #include <asm/hardware/gic.h> | 33 | #include <asm/hardware/gic.h> |
@@ -111,6 +112,8 @@ static void __init highbank_timer_init(void) | |||
111 | 112 | ||
112 | sp804_clocksource_init(timer_base + 0x20, "timer1"); | 113 | sp804_clocksource_init(timer_base + 0x20, "timer1"); |
113 | sp804_clockevents_init(timer_base, irq, "timer0"); | 114 | sp804_clockevents_init(timer_base, irq, "timer0"); |
115 | |||
116 | twd_local_timer_of_register(); | ||
114 | } | 117 | } |
115 | 118 | ||
116 | static struct sys_timer highbank_timer = { | 119 | static struct sys_timer highbank_timer = { |
diff --git a/arch/arm/mach-highbank/localtimer.c b/arch/arm/mach-highbank/localtimer.c deleted file mode 100644 index 5a00e7945fdf..000000000000 --- a/arch/arm/mach-highbank/localtimer.c +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2010-2011 Calxeda, Inc. | ||
3 | * Based on localtimer.c, Copyright (C) 2002 ARM Ltd. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/clockchips.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_address.h> | ||
21 | #include <linux/of_irq.h> | ||
22 | |||
23 | #include <asm/smp_twd.h> | ||
24 | |||
25 | /* | ||
26 | * Setup the local clock events for a CPU. | ||
27 | */ | ||
28 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
29 | { | ||
30 | struct device_node *np; | ||
31 | |||
32 | np = of_find_compatible_node(NULL, NULL, "arm,smp-twd"); | ||
33 | if (!twd_base) { | ||
34 | twd_base = of_iomap(np, 0); | ||
35 | WARN_ON(!twd_base); | ||
36 | } | ||
37 | evt->irq = irq_of_parse_and_map(np, 0); | ||
38 | twd_timer_setup(evt); | ||
39 | return 0; | ||
40 | } | ||
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 4ffeca7ee25e..8f57daf5e798 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile | |||
@@ -72,7 +72,6 @@ obj-$(CONFIG_CPU_V7) += head-v7.o | |||
72 | AFLAGS_head-v7.o :=-Wa,-march=armv7-a | 72 | AFLAGS_head-v7.o :=-Wa,-march=armv7-a |
73 | obj-$(CONFIG_SMP) += platsmp.o | 73 | obj-$(CONFIG_SMP) += platsmp.o |
74 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 74 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
75 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
76 | obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o | 75 | obj-$(CONFIG_SOC_IMX6Q) += clock-imx6q.o mach-imx6q.o |
77 | 76 | ||
78 | ifeq ($(CONFIG_PM),y) | 77 | ifeq ($(CONFIG_PM),y) |
diff --git a/arch/arm/mach-imx/localtimer.c b/arch/arm/mach-imx/localtimer.c deleted file mode 100644 index 3a163515d41f..000000000000 --- a/arch/arm/mach-imx/localtimer.c +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2011 Freescale Semiconductor, Inc. | ||
3 | * Copyright 2011 Linaro Ltd. | ||
4 | * | ||
5 | * The code contained herein is licensed under the GNU General Public | ||
6 | * License. You may obtain a copy of the GNU General Public License | ||
7 | * Version 2 or later at the following locations: | ||
8 | * | ||
9 | * http://www.opensource.org/licenses/gpl-license.html | ||
10 | * http://www.gnu.org/copyleft/gpl.html | ||
11 | */ | ||
12 | |||
13 | #include <linux/init.h> | ||
14 | #include <linux/clockchips.h> | ||
15 | #include <linux/of_address.h> | ||
16 | #include <linux/of_irq.h> | ||
17 | #include <asm/smp_twd.h> | ||
18 | |||
19 | /* | ||
20 | * Setup the local clock events for a CPU. | ||
21 | */ | ||
22 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
23 | { | ||
24 | struct device_node *np; | ||
25 | |||
26 | np = of_find_compatible_node(NULL, NULL, "arm,smp-twd"); | ||
27 | if (!twd_base) { | ||
28 | twd_base = of_iomap(np, 0); | ||
29 | WARN_ON(!twd_base); | ||
30 | } | ||
31 | evt->irq = irq_of_parse_and_map(np, 0); | ||
32 | twd_timer_setup(evt); | ||
33 | |||
34 | return 0; | ||
35 | } | ||
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 379b1a9cd22b..7696dfa2bdba 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/of_platform.h> | 21 | #include <linux/of_platform.h> |
22 | #include <linux/phy.h> | 22 | #include <linux/phy.h> |
23 | #include <linux/micrel_phy.h> | 23 | #include <linux/micrel_phy.h> |
24 | #include <asm/smp_twd.h> | ||
24 | #include <asm/hardware/cache-l2x0.h> | 25 | #include <asm/hardware/cache-l2x0.h> |
25 | #include <asm/hardware/gic.h> | 26 | #include <asm/hardware/gic.h> |
26 | #include <asm/mach/arch.h> | 27 | #include <asm/mach/arch.h> |
@@ -120,6 +121,7 @@ static void __init imx6q_init_irq(void) | |||
120 | static void __init imx6q_timer_init(void) | 121 | static void __init imx6q_timer_init(void) |
121 | { | 122 | { |
122 | mx6q_clocks_init(); | 123 | mx6q_clocks_init(); |
124 | twd_local_timer_of_register(); | ||
123 | } | 125 | } |
124 | 126 | ||
125 | static struct sys_timer imx6q_timer = { | 127 | static struct sys_timer imx6q_timer = { |
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 11d0d8f2656c..75f4be40b3e5 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c | |||
@@ -127,6 +127,45 @@ static struct clocksource msm_clocksource = { | |||
127 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 127 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
128 | }; | 128 | }; |
129 | 129 | ||
130 | #ifdef CONFIG_LOCAL_TIMERS | ||
131 | static int __cpuinit msm_local_timer_setup(struct clock_event_device *evt) | ||
132 | { | ||
133 | /* Use existing clock_event for cpu 0 */ | ||
134 | if (!smp_processor_id()) | ||
135 | return 0; | ||
136 | |||
137 | writel_relaxed(0, event_base + TIMER_ENABLE); | ||
138 | writel_relaxed(0, event_base + TIMER_CLEAR); | ||
139 | writel_relaxed(~0, event_base + TIMER_MATCH_VAL); | ||
140 | evt->irq = msm_clockevent.irq; | ||
141 | evt->name = "local_timer"; | ||
142 | evt->features = msm_clockevent.features; | ||
143 | evt->rating = msm_clockevent.rating; | ||
144 | evt->set_mode = msm_timer_set_mode; | ||
145 | evt->set_next_event = msm_timer_set_next_event; | ||
146 | evt->shift = msm_clockevent.shift; | ||
147 | evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift); | ||
148 | evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt); | ||
149 | evt->min_delta_ns = clockevent_delta2ns(4, evt); | ||
150 | |||
151 | *__this_cpu_ptr(msm_evt.percpu_evt) = evt; | ||
152 | clockevents_register_device(evt); | ||
153 | enable_percpu_irq(evt->irq, 0); | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static void msm_local_timer_stop(struct clock_event_device *evt) | ||
158 | { | ||
159 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | ||
160 | disable_percpu_irq(evt->irq); | ||
161 | } | ||
162 | |||
163 | static struct local_timer_ops msm_local_timer_ops __cpuinitdata = { | ||
164 | .setup = msm_local_timer_setup, | ||
165 | .stop = msm_local_timer_stop, | ||
166 | }; | ||
167 | #endif /* CONFIG_LOCAL_TIMERS */ | ||
168 | |||
130 | static void __init msm_timer_init(void) | 169 | static void __init msm_timer_init(void) |
131 | { | 170 | { |
132 | struct clock_event_device *ce = &msm_clockevent; | 171 | struct clock_event_device *ce = &msm_clockevent; |
@@ -173,8 +212,12 @@ static void __init msm_timer_init(void) | |||
173 | *__this_cpu_ptr(msm_evt.percpu_evt) = ce; | 212 | *__this_cpu_ptr(msm_evt.percpu_evt) = ce; |
174 | res = request_percpu_irq(ce->irq, msm_timer_interrupt, | 213 | res = request_percpu_irq(ce->irq, msm_timer_interrupt, |
175 | ce->name, msm_evt.percpu_evt); | 214 | ce->name, msm_evt.percpu_evt); |
176 | if (!res) | 215 | if (!res) { |
177 | enable_percpu_irq(ce->irq, 0); | 216 | enable_percpu_irq(ce->irq, 0); |
217 | #ifdef CONFIG_LOCAL_TIMERS | ||
218 | local_timer_register(&msm_local_timer_ops); | ||
219 | #endif | ||
220 | } | ||
178 | } else { | 221 | } else { |
179 | msm_evt.evt = ce; | 222 | msm_evt.evt = ce; |
180 | res = request_irq(ce->irq, msm_timer_interrupt, | 223 | res = request_irq(ce->irq, msm_timer_interrupt, |
@@ -191,40 +234,6 @@ err: | |||
191 | pr_err("clocksource_register failed\n"); | 234 | pr_err("clocksource_register failed\n"); |
192 | } | 235 | } |
193 | 236 | ||
194 | #ifdef CONFIG_LOCAL_TIMERS | ||
195 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
196 | { | ||
197 | /* Use existing clock_event for cpu 0 */ | ||
198 | if (!smp_processor_id()) | ||
199 | return 0; | ||
200 | |||
201 | writel_relaxed(0, event_base + TIMER_ENABLE); | ||
202 | writel_relaxed(0, event_base + TIMER_CLEAR); | ||
203 | writel_relaxed(~0, event_base + TIMER_MATCH_VAL); | ||
204 | evt->irq = msm_clockevent.irq; | ||
205 | evt->name = "local_timer"; | ||
206 | evt->features = msm_clockevent.features; | ||
207 | evt->rating = msm_clockevent.rating; | ||
208 | evt->set_mode = msm_timer_set_mode; | ||
209 | evt->set_next_event = msm_timer_set_next_event; | ||
210 | evt->shift = msm_clockevent.shift; | ||
211 | evt->mult = div_sc(GPT_HZ, NSEC_PER_SEC, evt->shift); | ||
212 | evt->max_delta_ns = clockevent_delta2ns(0xf0000000, evt); | ||
213 | evt->min_delta_ns = clockevent_delta2ns(4, evt); | ||
214 | |||
215 | *__this_cpu_ptr(msm_evt.percpu_evt) = evt; | ||
216 | clockevents_register_device(evt); | ||
217 | enable_percpu_irq(evt->irq, 0); | ||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | void local_timer_stop(struct clock_event_device *evt) | ||
222 | { | ||
223 | evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt); | ||
224 | disable_percpu_irq(evt->irq); | ||
225 | } | ||
226 | #endif /* CONFIG_LOCAL_TIMERS */ | ||
227 | |||
228 | struct sys_timer msm_timer = { | 237 | struct sys_timer msm_timer = { |
229 | .init = msm_timer_init | 238 | .init = msm_timer_init |
230 | }; | 239 | }; |
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index f6f74adbe8c4..58cacafcf662 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c | |||
@@ -27,11 +27,11 @@ | |||
27 | #include <asm/mach/arch.h> | 27 | #include <asm/mach/arch.h> |
28 | #include <asm/mach/irq.h> | 28 | #include <asm/mach/irq.h> |
29 | #include <asm/mach/flash.h> | 29 | #include <asm/mach/flash.h> |
30 | #include <asm/mach/time.h> | ||
30 | 31 | ||
31 | #include <plat/gpio-nomadik.h> | 32 | #include <plat/gpio-nomadik.h> |
32 | #include <plat/mtu.h> | 33 | #include <plat/mtu.h> |
33 | 34 | ||
34 | #include <mach/setup.h> | ||
35 | #include <mach/nand.h> | 35 | #include <mach/nand.h> |
36 | #include <mach/fsmc.h> | 36 | #include <mach/fsmc.h> |
37 | 37 | ||
@@ -246,10 +246,7 @@ static void __init nomadik_timer_init(void) | |||
246 | src_cr |= SRC_CR_INIT_VAL; | 246 | src_cr |= SRC_CR_INIT_VAL; |
247 | writel(src_cr, io_p2v(NOMADIK_SRC_BASE)); | 247 | writel(src_cr, io_p2v(NOMADIK_SRC_BASE)); |
248 | 248 | ||
249 | /* Save global pointer to mtu, used by platform timer code */ | 249 | nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE)); |
250 | mtu_base = io_p2v(NOMADIK_MTU0_BASE); | ||
251 | |||
252 | nmdk_timer_init(); | ||
253 | } | 250 | } |
254 | 251 | ||
255 | static struct sys_timer nomadik_timer = { | 252 | static struct sys_timer nomadik_timer = { |
diff --git a/arch/arm/mach-nomadik/include/mach/setup.h b/arch/arm/mach-nomadik/include/mach/setup.h deleted file mode 100644 index bcaeaf41c053..000000000000 --- a/arch/arm/mach-nomadik/include/mach/setup.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | |||
2 | /* | ||
3 | * These symbols are needed for board-specific files to call their | ||
4 | * own cpu-specific files | ||
5 | */ | ||
6 | |||
7 | #ifndef __ASM_ARCH_SETUP_H | ||
8 | #define __ASM_ARCH_SETUP_H | ||
9 | |||
10 | #include <asm/mach/time.h> | ||
11 | #include <linux/init.h> | ||
12 | |||
13 | #ifdef CONFIG_NOMADIK_8815 | ||
14 | |||
15 | extern void nmdk_timer_init(void); | ||
16 | |||
17 | #endif /* NOMADIK_8815 */ | ||
18 | |||
19 | #endif /* __ASM_ARCH_SETUP_H */ | ||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index bd76394ccaf8..05c2ffc1030a 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile | |||
@@ -23,7 +23,6 @@ obj-$(CONFIG_TWL4030_CORE) += omap_twl.o | |||
23 | 23 | ||
24 | # SMP support ONLY available for OMAP4 | 24 | # SMP support ONLY available for OMAP4 |
25 | obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o | 25 | obj-$(CONFIG_SMP) += omap-smp.o omap-headsmp.o |
26 | obj-$(CONFIG_LOCAL_TIMERS) += timer-mpu.o | ||
27 | obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o | 26 | obj-$(CONFIG_HOTPLUG_CPU) += omap-hotplug.o |
28 | obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o \ | 27 | obj-$(CONFIG_ARCH_OMAP4) += omap4-common.o omap-wakeupgen.o \ |
29 | sleep44xx.o | 28 | sleep44xx.o |
diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c deleted file mode 100644 index 31c0ac4cd66a..000000000000 --- a/arch/arm/mach-omap2/timer-mpu.c +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | /* | ||
2 | * The MPU local timer source file. In OMAP4, both cortex-a9 cores have | ||
3 | * own timer in it's MPU domain. These timers will be driving the | ||
4 | * linux kernel SMP tick framework when active. These timers are not | ||
5 | * part of the wake up domain. | ||
6 | * | ||
7 | * Copyright (C) 2009 Texas Instruments, Inc. | ||
8 | * | ||
9 | * Author: | ||
10 | * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
11 | * | ||
12 | * This file is based on arm realview smp platform file. | ||
13 | * Copyright (C) 2002 ARM Ltd. | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License version 2 as | ||
17 | * published by the Free Software Foundation. | ||
18 | */ | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/smp.h> | ||
21 | #include <linux/clockchips.h> | ||
22 | #include <asm/irq.h> | ||
23 | #include <asm/smp_twd.h> | ||
24 | #include <asm/localtimer.h> | ||
25 | |||
26 | /* | ||
27 | * Setup the local clock events for a CPU. | ||
28 | */ | ||
29 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
30 | { | ||
31 | /* Local timers are not supprted on OMAP4430 ES1.0 */ | ||
32 | if (omap_rev() == OMAP4430_REV_ES1_0) | ||
33 | return -ENXIO; | ||
34 | |||
35 | evt->irq = OMAP44XX_IRQ_LOCALTIMER; | ||
36 | twd_timer_setup(evt); | ||
37 | return 0; | ||
38 | } | ||
39 | |||
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index 5c9acea95761..c512bac69ec5 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | #include <asm/mach/time.h> | 40 | #include <asm/mach/time.h> |
41 | #include <plat/dmtimer.h> | 41 | #include <plat/dmtimer.h> |
42 | #include <asm/localtimer.h> | 42 | #include <asm/smp_twd.h> |
43 | #include <asm/sched_clock.h> | 43 | #include <asm/sched_clock.h> |
44 | #include "common.h" | 44 | #include "common.h" |
45 | #include <plat/omap_hwmod.h> | 45 | #include <plat/omap_hwmod.h> |
@@ -324,14 +324,26 @@ OMAP_SYS_TIMER(3_secure) | |||
324 | #endif | 324 | #endif |
325 | 325 | ||
326 | #ifdef CONFIG_ARCH_OMAP4 | 326 | #ifdef CONFIG_ARCH_OMAP4 |
327 | static void __init omap4_timer_init(void) | ||
328 | { | ||
329 | #ifdef CONFIG_LOCAL_TIMERS | 327 | #ifdef CONFIG_LOCAL_TIMERS |
330 | twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256); | 328 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, |
331 | BUG_ON(!twd_base); | 329 | OMAP44XX_LOCAL_TWD_BASE, |
330 | OMAP44XX_IRQ_LOCALTIMER); | ||
332 | #endif | 331 | #endif |
332 | |||
333 | static void __init omap4_timer_init(void) | ||
334 | { | ||
333 | omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); | 335 | omap2_gp_clockevent_init(1, OMAP4_CLKEV_SOURCE); |
334 | omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE); | 336 | omap2_gp_clocksource_init(2, OMAP4_MPU_SOURCE); |
337 | #ifdef CONFIG_LOCAL_TIMERS | ||
338 | /* Local timers are not supprted on OMAP4430 ES1.0 */ | ||
339 | if (omap_rev() != OMAP4430_REV_ES1_0) { | ||
340 | int err; | ||
341 | |||
342 | err = twd_local_timer_register(&twd_local_timer); | ||
343 | if (err) | ||
344 | pr_err("twd_local_timer_register failed %d\n", err); | ||
345 | } | ||
346 | #endif | ||
335 | } | 347 | } |
336 | OMAP_SYS_TIMER(4) | 348 | OMAP_SYS_TIMER(4) |
337 | #endif | 349 | #endif |
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c index 157e1bc6e83c..baf382c5e776 100644 --- a/arch/arm/mach-realview/realview_eb.c +++ b/arch/arm/mach-realview/realview_eb.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
37 | #include <asm/hardware/gic.h> | 37 | #include <asm/hardware/gic.h> |
38 | #include <asm/hardware/cache-l2x0.h> | 38 | #include <asm/hardware/cache-l2x0.h> |
39 | #include <asm/localtimer.h> | 39 | #include <asm/smp_twd.h> |
40 | 40 | ||
41 | #include <asm/mach/arch.h> | 41 | #include <asm/mach/arch.h> |
42 | #include <asm/mach/map.h> | 42 | #include <asm/mach/map.h> |
@@ -383,6 +383,23 @@ static void realview_eb11mp_fixup(void) | |||
383 | realview_eb_isp1761_resources[1].end = IRQ_EB11MP_USB; | 383 | realview_eb_isp1761_resources[1].end = IRQ_EB11MP_USB; |
384 | } | 384 | } |
385 | 385 | ||
386 | #ifdef CONFIG_HAVE_ARM_TWD | ||
387 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, | ||
388 | REALVIEW_EB11MP_TWD_BASE, | ||
389 | IRQ_LOCALTIMER); | ||
390 | |||
391 | static void __init realview_eb_twd_init(void) | ||
392 | { | ||
393 | if (core_tile_eb11mp() || core_tile_a9mp()) { | ||
394 | int err = twd_local_timer_register(&twd_local_timer); | ||
395 | if (err) | ||
396 | pr_err("twd_local_timer_register failed %d\n", err); | ||
397 | } | ||
398 | } | ||
399 | #else | ||
400 | #define realview_eb_twd_init() do { } while(0) | ||
401 | #endif | ||
402 | |||
386 | static void __init realview_eb_timer_init(void) | 403 | static void __init realview_eb_timer_init(void) |
387 | { | 404 | { |
388 | unsigned int timer_irq; | 405 | unsigned int timer_irq; |
@@ -392,15 +409,13 @@ static void __init realview_eb_timer_init(void) | |||
392 | timer2_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE); | 409 | timer2_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE); |
393 | timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20; | 410 | timer3_va_base = __io_address(REALVIEW_EB_TIMER2_3_BASE) + 0x20; |
394 | 411 | ||
395 | if (core_tile_eb11mp() || core_tile_a9mp()) { | 412 | if (core_tile_eb11mp() || core_tile_a9mp()) |
396 | #ifdef CONFIG_LOCAL_TIMERS | ||
397 | twd_base = __io_address(REALVIEW_EB11MP_TWD_BASE); | ||
398 | #endif | ||
399 | timer_irq = IRQ_EB11MP_TIMER0_1; | 413 | timer_irq = IRQ_EB11MP_TIMER0_1; |
400 | } else | 414 | else |
401 | timer_irq = IRQ_EB_TIMER0_1; | 415 | timer_irq = IRQ_EB_TIMER0_1; |
402 | 416 | ||
403 | realview_timer_init(timer_irq); | 417 | realview_timer_init(timer_irq); |
418 | realview_eb_twd_init(); | ||
404 | } | 419 | } |
405 | 420 | ||
406 | static struct sys_timer realview_eb_timer = { | 421 | static struct sys_timer realview_eb_timer = { |
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c index ae7fe54f6eb6..a98c536e3327 100644 --- a/arch/arm/mach-realview/realview_pb11mp.c +++ b/arch/arm/mach-realview/realview_pb11mp.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
37 | #include <asm/hardware/gic.h> | 37 | #include <asm/hardware/gic.h> |
38 | #include <asm/hardware/cache-l2x0.h> | 38 | #include <asm/hardware/cache-l2x0.h> |
39 | #include <asm/localtimer.h> | 39 | #include <asm/smp_twd.h> |
40 | 40 | ||
41 | #include <asm/mach/arch.h> | 41 | #include <asm/mach/arch.h> |
42 | #include <asm/mach/flash.h> | 42 | #include <asm/mach/flash.h> |
@@ -290,6 +290,21 @@ static void __init gic_init_irq(void) | |||
290 | gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1); | 290 | gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1); |
291 | } | 291 | } |
292 | 292 | ||
293 | #ifdef CONFIG_HAVE_ARM_TWD | ||
294 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, | ||
295 | REALVIEW_TC11MP_TWD_BASE, | ||
296 | IRQ_LOCALTIMER); | ||
297 | |||
298 | static void __init realview_pb11mp_twd_init(void) | ||
299 | { | ||
300 | int err = twd_local_timer_register(&twd_local_timer); | ||
301 | if (err) | ||
302 | pr_err("twd_local_timer_register failed %d\n", err); | ||
303 | } | ||
304 | #else | ||
305 | #define realview_pb11mp_twd_init() do {} while(0) | ||
306 | #endif | ||
307 | |||
293 | static void __init realview_pb11mp_timer_init(void) | 308 | static void __init realview_pb11mp_timer_init(void) |
294 | { | 309 | { |
295 | timer0_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE); | 310 | timer0_va_base = __io_address(REALVIEW_PB11MP_TIMER0_1_BASE); |
@@ -297,10 +312,8 @@ static void __init realview_pb11mp_timer_init(void) | |||
297 | timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE); | 312 | timer2_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE); |
298 | timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20; | 313 | timer3_va_base = __io_address(REALVIEW_PB11MP_TIMER2_3_BASE) + 0x20; |
299 | 314 | ||
300 | #ifdef CONFIG_LOCAL_TIMERS | ||
301 | twd_base = __io_address(REALVIEW_TC11MP_TWD_BASE); | ||
302 | #endif | ||
303 | realview_timer_init(IRQ_TC11MP_TIMER0_1); | 315 | realview_timer_init(IRQ_TC11MP_TIMER0_1); |
316 | realview_pb11mp_twd_init(); | ||
304 | } | 317 | } |
305 | 318 | ||
306 | static struct sys_timer realview_pb11mp_timer = { | 319 | static struct sys_timer realview_pb11mp_timer = { |
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c index 1cd9956f5875..3f2f605624e9 100644 --- a/arch/arm/mach-realview/realview_pbx.c +++ b/arch/arm/mach-realview/realview_pbx.c | |||
@@ -298,6 +298,21 @@ static void __init gic_init_irq(void) | |||
298 | } | 298 | } |
299 | } | 299 | } |
300 | 300 | ||
301 | #ifdef CONFIG_HAVE_ARM_TWD | ||
302 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, | ||
303 | REALVIEW_PBX_TILE_TWD_BASE, | ||
304 | IRQ_LOCALTIMER); | ||
305 | |||
306 | static void __init realview_pbx_twd_init(void) | ||
307 | { | ||
308 | int err = twd_local_timer_register(&twd_local_timer); | ||
309 | if (err) | ||
310 | pr_err("twd_local_timer_register failed %d\n", err); | ||
311 | } | ||
312 | #else | ||
313 | #define realview_pbx_twd_init() do { } while(0) | ||
314 | #endif | ||
315 | |||
301 | static void __init realview_pbx_timer_init(void) | 316 | static void __init realview_pbx_timer_init(void) |
302 | { | 317 | { |
303 | timer0_va_base = __io_address(REALVIEW_PBX_TIMER0_1_BASE); | 318 | timer0_va_base = __io_address(REALVIEW_PBX_TIMER0_1_BASE); |
@@ -305,11 +320,8 @@ static void __init realview_pbx_timer_init(void) | |||
305 | timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE); | 320 | timer2_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE); |
306 | timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20; | 321 | timer3_va_base = __io_address(REALVIEW_PBX_TIMER2_3_BASE) + 0x20; |
307 | 322 | ||
308 | #ifdef CONFIG_LOCAL_TIMERS | ||
309 | if (core_tile_pbx11mp() || core_tile_pbxa9mp()) | ||
310 | twd_base = __io_address(REALVIEW_PBX_TILE_TWD_BASE); | ||
311 | #endif | ||
312 | realview_timer_init(IRQ_PBX_TIMER0_1); | 323 | realview_timer_init(IRQ_PBX_TIMER0_1); |
324 | realview_pbx_twd_init(); | ||
313 | } | 325 | } |
314 | 326 | ||
315 | static struct sys_timer realview_pbx_timer = { | 327 | static struct sys_timer realview_pbx_timer = { |
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile index 7ad6954c46cd..e7c2590b75d9 100644 --- a/arch/arm/mach-shmobile/Makefile +++ b/arch/arm/mach-shmobile/Makefile | |||
@@ -16,7 +16,6 @@ obj-$(CONFIG_ARCH_R8A7779) += setup-r8a7779.o clock-r8a7779.o intc-r8a7779.o | |||
16 | # SMP objects | 16 | # SMP objects |
17 | smp-y := platsmp.o headsmp.o | 17 | smp-y := platsmp.o headsmp.o |
18 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 18 | smp-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
19 | smp-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
20 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o | 19 | smp-$(CONFIG_ARCH_SH73A0) += smp-sh73a0.o |
21 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o | 20 | smp-$(CONFIG_ARCH_R8A7779) += smp-r8a7779.o |
22 | 21 | ||
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h index e4b945e271e7..9fde3eb686a6 100644 --- a/arch/arm/mach-shmobile/include/mach/common.h +++ b/arch/arm/mach-shmobile/include/mach/common.h | |||
@@ -2,6 +2,8 @@ | |||
2 | #define __ARCH_MACH_COMMON_H | 2 | #define __ARCH_MACH_COMMON_H |
3 | 3 | ||
4 | extern struct sys_timer shmobile_timer; | 4 | extern struct sys_timer shmobile_timer; |
5 | struct twd_local_timer; | ||
6 | void shmobile_twd_init(struct twd_local_timer *twd_local_timer); | ||
5 | extern void shmobile_setup_console(void); | 7 | extern void shmobile_setup_console(void); |
6 | extern void shmobile_secondary_vector(void); | 8 | extern void shmobile_secondary_vector(void); |
7 | extern int shmobile_platform_cpu_kill(unsigned int cpu); | 9 | extern int shmobile_platform_cpu_kill(unsigned int cpu); |
diff --git a/arch/arm/mach-shmobile/localtimer.c b/arch/arm/mach-shmobile/localtimer.c deleted file mode 100644 index ad9ccc9900c8..000000000000 --- a/arch/arm/mach-shmobile/localtimer.c +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * SMP support for R-Mobile / SH-Mobile - local timer portion | ||
3 | * | ||
4 | * Copyright (C) 2010 Magnus Damm | ||
5 | * | ||
6 | * Based on vexpress, Copyright (C) 2002 ARM Ltd, All Rights Reserved | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/smp.h> | ||
14 | #include <linux/clockchips.h> | ||
15 | #include <asm/smp_twd.h> | ||
16 | #include <asm/localtimer.h> | ||
17 | |||
18 | /* | ||
19 | * Setup the local clock events for a CPU. | ||
20 | */ | ||
21 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
22 | { | ||
23 | evt->irq = 29; | ||
24 | twd_timer_setup(evt); | ||
25 | return 0; | ||
26 | } | ||
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 993381257f69..45fa3924c6a1 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/smp.h> | 17 | #include <linux/smp.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <asm/hardware/gic.h> | 19 | #include <asm/hardware/gic.h> |
20 | #include <asm/localtimer.h> | ||
21 | #include <asm/mach-types.h> | 20 | #include <asm/mach-types.h> |
22 | #include <mach/common.h> | 21 | #include <mach/common.h> |
23 | 22 | ||
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 4fe2e9eaf501..9bb7b8575a1f 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c | |||
@@ -64,6 +64,8 @@ static void __iomem *scu_base_addr(void) | |||
64 | static DEFINE_SPINLOCK(scu_lock); | 64 | static DEFINE_SPINLOCK(scu_lock); |
65 | static unsigned long tmp; | 65 | static unsigned long tmp; |
66 | 66 | ||
67 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); | ||
68 | |||
67 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) | 69 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) |
68 | { | 70 | { |
69 | void __iomem *scu_base = scu_base_addr(); | 71 | void __iomem *scu_base = scu_base_addr(); |
@@ -82,11 +84,7 @@ unsigned int __init r8a7779_get_core_count(void) | |||
82 | { | 84 | { |
83 | void __iomem *scu_base = scu_base_addr(); | 85 | void __iomem *scu_base = scu_base_addr(); |
84 | 86 | ||
85 | #ifdef CONFIG_HAVE_ARM_TWD | 87 | shmobile_twd_init(&twd_local_timer); |
86 | /* twd_base needs to be initialized before percpu_timer_setup() */ | ||
87 | twd_base = (void __iomem *)0xf0000600; | ||
88 | #endif | ||
89 | |||
90 | return scu_get_core_count(scu_base); | 88 | return scu_get_core_count(scu_base); |
91 | } | 89 | } |
92 | 90 | ||
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index 2d0d4212be41..c0a9093ba3a8 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c | |||
@@ -42,6 +42,8 @@ static void __iomem *scu_base_addr(void) | |||
42 | static DEFINE_SPINLOCK(scu_lock); | 42 | static DEFINE_SPINLOCK(scu_lock); |
43 | static unsigned long tmp; | 43 | static unsigned long tmp; |
44 | 44 | ||
45 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29); | ||
46 | |||
45 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) | 47 | static void modify_scu_cpu_psr(unsigned long set, unsigned long clr) |
46 | { | 48 | { |
47 | void __iomem *scu_base = scu_base_addr(); | 49 | void __iomem *scu_base = scu_base_addr(); |
@@ -60,11 +62,7 @@ unsigned int __init sh73a0_get_core_count(void) | |||
60 | { | 62 | { |
61 | void __iomem *scu_base = scu_base_addr(); | 63 | void __iomem *scu_base = scu_base_addr(); |
62 | 64 | ||
63 | #ifdef CONFIG_HAVE_ARM_TWD | 65 | shmobile_twd_init(&twd_local_timer); |
64 | /* twd_base needs to be initialized before percpu_timer_setup() */ | ||
65 | twd_base = (void __iomem *)0xf0000600; | ||
66 | #endif | ||
67 | |||
68 | return scu_get_core_count(scu_base); | 66 | return scu_get_core_count(scu_base); |
69 | } | 67 | } |
70 | 68 | ||
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c index 895794b543cd..be16231e86fc 100644 --- a/arch/arm/mach-shmobile/timer.c +++ b/arch/arm/mach-shmobile/timer.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <asm/mach/time.h> | 22 | #include <asm/mach/time.h> |
23 | #include <asm/smp_twd.h> | ||
23 | 24 | ||
24 | static void __init shmobile_late_time_init(void) | 25 | static void __init shmobile_late_time_init(void) |
25 | { | 26 | { |
@@ -41,6 +42,15 @@ static void __init shmobile_timer_init(void) | |||
41 | late_time_init = shmobile_late_time_init; | 42 | late_time_init = shmobile_late_time_init; |
42 | } | 43 | } |
43 | 44 | ||
45 | void __init shmobile_twd_init(struct twd_local_timer *twd_local_timer) | ||
46 | { | ||
47 | #ifdef CONFIG_HAVE_ARM_TWD | ||
48 | int err = twd_local_timer_register(twd_local_timer); | ||
49 | if (err) | ||
50 | pr_err("twd_local_timer_register failed %d\n", err); | ||
51 | #endif | ||
52 | } | ||
53 | |||
44 | struct sys_timer shmobile_timer = { | 54 | struct sys_timer shmobile_timer = { |
45 | .init = shmobile_timer_init, | 55 | .init = shmobile_timer_init, |
46 | }; | 56 | }; |
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index e120ff54f663..f7d044369ed5 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile | |||
@@ -13,7 +13,7 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o | |||
13 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-tegra20-tables.o | 13 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-tegra20-tables.o |
14 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o | 14 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += pinmux-tegra30-tables.o |
15 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o | 15 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o |
16 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o | 16 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
17 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 17 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
18 | obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o | 18 | obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o |
19 | obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o | 19 | obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o |
diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c deleted file mode 100644 index e91d681d45a2..000000000000 --- a/arch/arm/mach-tegra/localtimer.c +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/localtimer.c | ||
3 | * | ||
4 | * Copyright (C) 2002 ARM Ltd. | ||
5 | * All Rights Reserved | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/clockchips.h> | ||
14 | #include <asm/irq.h> | ||
15 | #include <asm/smp_twd.h> | ||
16 | #include <asm/localtimer.h> | ||
17 | |||
18 | /* | ||
19 | * Setup the local clock events for a CPU. | ||
20 | */ | ||
21 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
22 | { | ||
23 | evt->irq = IRQ_LOCALTIMER; | ||
24 | twd_timer_setup(evt); | ||
25 | return 0; | ||
26 | } | ||
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 1d1acda4f3e0..1eed8d4a80ef 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | 29 | ||
30 | #include <asm/mach/time.h> | 30 | #include <asm/mach/time.h> |
31 | #include <asm/localtimer.h> | 31 | #include <asm/smp_twd.h> |
32 | #include <asm/sched_clock.h> | 32 | #include <asm/sched_clock.h> |
33 | 33 | ||
34 | #include <mach/iomap.h> | 34 | #include <mach/iomap.h> |
@@ -162,6 +162,21 @@ static struct irqaction tegra_timer_irq = { | |||
162 | .irq = INT_TMR3, | 162 | .irq = INT_TMR3, |
163 | }; | 163 | }; |
164 | 164 | ||
165 | #ifdef CONFIG_HAVE_ARM_TWD | ||
166 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, | ||
167 | TEGRA_ARM_PERIF_BASE + 0x600, | ||
168 | IRQ_LOCALTIMER); | ||
169 | |||
170 | static void __init tegra_twd_init(void) | ||
171 | { | ||
172 | int err = twd_local_timer_register(&twd_local_timer); | ||
173 | if (err) | ||
174 | pr_err("twd_local_timer_register failed %d\n", err); | ||
175 | } | ||
176 | #else | ||
177 | #define tegra_twd_init() do {} while(0) | ||
178 | #endif | ||
179 | |||
165 | static void __init tegra_init_timer(void) | 180 | static void __init tegra_init_timer(void) |
166 | { | 181 | { |
167 | struct clk *clk; | 182 | struct clk *clk; |
@@ -188,10 +203,6 @@ static void __init tegra_init_timer(void) | |||
188 | else | 203 | else |
189 | clk_enable(clk); | 204 | clk_enable(clk); |
190 | 205 | ||
191 | #ifdef CONFIG_HAVE_ARM_TWD | ||
192 | twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600); | ||
193 | #endif | ||
194 | |||
195 | switch (rate) { | 206 | switch (rate) { |
196 | case 12000000: | 207 | case 12000000: |
197 | timer_writel(0x000b, TIMERUS_USEC_CFG); | 208 | timer_writel(0x000b, TIMERUS_USEC_CFG); |
@@ -231,6 +242,7 @@ static void __init tegra_init_timer(void) | |||
231 | tegra_clockevent.cpumask = cpu_all_mask; | 242 | tegra_clockevent.cpumask = cpu_all_mask; |
232 | tegra_clockevent.irq = tegra_timer_irq.irq; | 243 | tegra_clockevent.irq = tegra_timer_irq.irq; |
233 | clockevents_register_device(&tegra_clockevent); | 244 | clockevents_register_device(&tegra_clockevent); |
245 | tegra_twd_init(); | ||
234 | } | 246 | } |
235 | 247 | ||
236 | struct sys_timer tegra_timer = { | 248 | struct sys_timer tegra_timer = { |
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 52af00446a63..afb3706bab2a 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig | |||
@@ -28,6 +28,7 @@ config MACH_U8500 | |||
28 | bool "U8500 Development platform" | 28 | bool "U8500 Development platform" |
29 | depends on UX500_SOC_DB8500 | 29 | depends on UX500_SOC_DB8500 |
30 | select TPS6105X | 30 | select TPS6105X |
31 | select SOC_BUS | ||
31 | help | 32 | help |
32 | Include support for the mop500 development platform. | 33 | Include support for the mop500 development platform. |
33 | 34 | ||
@@ -49,6 +50,12 @@ config MACH_U5500 | |||
49 | depends on UX500_SOC_DB5500 | 50 | depends on UX500_SOC_DB5500 |
50 | help | 51 | help |
51 | Include support for the U5500 development platform. | 52 | Include support for the U5500 development platform. |
53 | |||
54 | config MACH_UX500_DT | ||
55 | bool "Generic U8500 support using device tree" | ||
56 | depends on MACH_U8500 | ||
57 | select USE_OF | ||
58 | |||
52 | endmenu | 59 | endmenu |
53 | 60 | ||
54 | config UX500_DEBUG_UART | 61 | config UX500_DEBUG_UART |
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile index 6bd2f451c185..35b389442afe 100644 --- a/arch/arm/mach-ux500/Makefile +++ b/arch/arm/mach-ux500/Makefile | |||
@@ -15,7 +15,6 @@ obj-$(CONFIG_MACH_U8500) += board-mop500.o board-mop500-sdi.o \ | |||
15 | obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o | 15 | obj-$(CONFIG_MACH_U5500) += board-u5500.o board-u5500-sdi.o |
16 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o | 16 | obj-$(CONFIG_SMP) += platsmp.o headsmp.o |
17 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 17 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
18 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
19 | obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o | 18 | obj-$(CONFIG_U5500_MODEM_IRQ) += modem-irq-db5500.o |
20 | obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o | 19 | obj-$(CONFIG_U5500_MBOX) += mbox-db5500.o |
21 | 20 | ||
diff --git a/arch/arm/mach-ux500/Makefile.boot b/arch/arm/mach-ux500/Makefile.boot index ff0a4b5b0a82..dd5cd00e2554 100644 --- a/arch/arm/mach-ux500/Makefile.boot +++ b/arch/arm/mach-ux500/Makefile.boot | |||
@@ -2,3 +2,4 @@ | |||
2 | params_phys-y := 0x00000100 | 2 | params_phys-y := 0x00000100 |
3 | initrd_phys-y := 0x00800000 | 3 | initrd_phys-y := 0x00800000 |
4 | 4 | ||
5 | dtb-$(CONFIG_MACH_SNOWBALL) += snowball.dtb | ||
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 5dde4d4ebe88..479ebe04cf9c 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c | |||
@@ -104,7 +104,7 @@ static struct mmci_platform_data mop500_sdi0_data = { | |||
104 | #endif | 104 | #endif |
105 | }; | 105 | }; |
106 | 106 | ||
107 | static void sdi0_configure(void) | 107 | static void sdi0_configure(struct device *parent) |
108 | { | 108 | { |
109 | int ret; | 109 | int ret; |
110 | 110 | ||
@@ -123,15 +123,15 @@ static void sdi0_configure(void) | |||
123 | gpio_direction_output(sdi0_en, 1); | 123 | gpio_direction_output(sdi0_en, 1); |
124 | 124 | ||
125 | /* Add the device, force v2 to subrevision 1 */ | 125 | /* Add the device, force v2 to subrevision 1 */ |
126 | db8500_add_sdi0(&mop500_sdi0_data, U8500_SDI_V2_PERIPHID); | 126 | db8500_add_sdi0(parent, &mop500_sdi0_data, U8500_SDI_V2_PERIPHID); |
127 | } | 127 | } |
128 | 128 | ||
129 | void mop500_sdi_tc35892_init(void) | 129 | void mop500_sdi_tc35892_init(struct device *parent) |
130 | { | 130 | { |
131 | mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; | 131 | mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD; |
132 | sdi0_en = GPIO_SDMMC_EN; | 132 | sdi0_en = GPIO_SDMMC_EN; |
133 | sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; | 133 | sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL; |
134 | sdi0_configure(); | 134 | sdi0_configure(parent); |
135 | } | 135 | } |
136 | 136 | ||
137 | /* | 137 | /* |
@@ -246,12 +246,13 @@ static struct mmci_platform_data mop500_sdi4_data = { | |||
246 | #endif | 246 | #endif |
247 | }; | 247 | }; |
248 | 248 | ||
249 | void __init mop500_sdi_init(void) | 249 | void __init mop500_sdi_init(struct device *parent) |
250 | { | 250 | { |
251 | /* PoP:ed eMMC */ | 251 | /* PoP:ed eMMC */ |
252 | db8500_add_sdi2(&mop500_sdi2_data, U8500_SDI_V2_PERIPHID); | 252 | db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); |
253 | /* On-board eMMC */ | 253 | /* On-board eMMC */ |
254 | db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); | 254 | db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); |
255 | |||
255 | /* | 256 | /* |
256 | * On boards with the TC35892 GPIO expander, sdi0 will finally | 257 | * On boards with the TC35892 GPIO expander, sdi0 will finally |
257 | * be added when the TC35892 initializes and calls | 258 | * be added when the TC35892 initializes and calls |
@@ -259,31 +260,31 @@ void __init mop500_sdi_init(void) | |||
259 | */ | 260 | */ |
260 | } | 261 | } |
261 | 262 | ||
262 | void __init snowball_sdi_init(void) | 263 | void __init snowball_sdi_init(struct device *parent) |
263 | { | 264 | { |
264 | /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */ | 265 | /* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */ |
265 | mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED; | 266 | mop500_sdi0_data.capabilities &= ~MMC_CAP_SD_HIGHSPEED; |
266 | /* On-board eMMC */ | 267 | /* On-board eMMC */ |
267 | db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); | 268 | db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); |
268 | /* External Micro SD slot */ | 269 | /* External Micro SD slot */ |
269 | mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO; | 270 | mop500_sdi0_data.gpio_cd = SNOWBALL_SDMMC_CD_GPIO; |
270 | mop500_sdi0_data.cd_invert = true; | 271 | mop500_sdi0_data.cd_invert = true; |
271 | sdi0_en = SNOWBALL_SDMMC_EN_GPIO; | 272 | sdi0_en = SNOWBALL_SDMMC_EN_GPIO; |
272 | sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO; | 273 | sdi0_vsel = SNOWBALL_SDMMC_1V8_3V_GPIO; |
273 | sdi0_configure(); | 274 | sdi0_configure(parent); |
274 | } | 275 | } |
275 | 276 | ||
276 | void __init hrefv60_sdi_init(void) | 277 | void __init hrefv60_sdi_init(struct device *parent) |
277 | { | 278 | { |
278 | /* PoP:ed eMMC */ | 279 | /* PoP:ed eMMC */ |
279 | db8500_add_sdi2(&mop500_sdi2_data, U8500_SDI_V2_PERIPHID); | 280 | db8500_add_sdi2(parent, &mop500_sdi2_data, U8500_SDI_V2_PERIPHID); |
280 | /* On-board eMMC */ | 281 | /* On-board eMMC */ |
281 | db8500_add_sdi4(&mop500_sdi4_data, U8500_SDI_V2_PERIPHID); | 282 | db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID); |
282 | /* External Micro SD slot */ | 283 | /* External Micro SD slot */ |
283 | mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO; | 284 | mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO; |
284 | sdi0_en = HREFV60_SDMMC_EN_GPIO; | 285 | sdi0_en = HREFV60_SDMMC_EN_GPIO; |
285 | sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO; | 286 | sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO; |
286 | sdi0_configure(); | 287 | sdi0_configure(parent); |
287 | /* WLAN SDIO channel */ | 288 | /* WLAN SDIO channel */ |
288 | db8500_add_sdi1(&mop500_sdi1_data, U8500_SDI_V2_PERIPHID); | 289 | db8500_add_sdi1(parent, &mop500_sdi1_data, U8500_SDI_V2_PERIPHID); |
289 | } | 290 | } |
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 5c00712907d1..d0799d592218 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c | |||
@@ -30,6 +30,9 @@ | |||
30 | #include <linux/gpio_keys.h> | 30 | #include <linux/gpio_keys.h> |
31 | #include <linux/delay.h> | 31 | #include <linux/delay.h> |
32 | 32 | ||
33 | #include <linux/of.h> | ||
34 | #include <linux/of_platform.h> | ||
35 | |||
33 | #include <linux/leds.h> | 36 | #include <linux/leds.h> |
34 | #include <asm/mach-types.h> | 37 | #include <asm/mach-types.h> |
35 | #include <asm/mach/arch.h> | 38 | #include <asm/mach/arch.h> |
@@ -226,7 +229,12 @@ static struct tps6105x_platform_data mop500_tps61052_data = { | |||
226 | 229 | ||
227 | static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) | 230 | static void mop500_tc35892_init(struct tc3589x *tc3589x, unsigned int base) |
228 | { | 231 | { |
229 | mop500_sdi_tc35892_init(); | 232 | struct device *parent = NULL; |
233 | #if 0 | ||
234 | /* FIXME: Is the sdi actually part of tc3589x? */ | ||
235 | parent = tc3589x->dev; | ||
236 | #endif | ||
237 | mop500_sdi_tc35892_init(parent); | ||
230 | } | 238 | } |
231 | 239 | ||
232 | static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { | 240 | static struct tc3589x_gpio_platform_data mop500_tc35892_gpio_data = { |
@@ -353,12 +361,12 @@ U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); | |||
353 | U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); | 361 | U8500_I2C_CONTROLLER(2, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); |
354 | U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); | 362 | U8500_I2C_CONTROLLER(3, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST); |
355 | 363 | ||
356 | static void __init mop500_i2c_init(void) | 364 | static void __init mop500_i2c_init(struct device *parent) |
357 | { | 365 | { |
358 | db8500_add_i2c0(&u8500_i2c0_data); | 366 | db8500_add_i2c0(parent, &u8500_i2c0_data); |
359 | db8500_add_i2c1(&u8500_i2c1_data); | 367 | db8500_add_i2c1(parent, &u8500_i2c1_data); |
360 | db8500_add_i2c2(&u8500_i2c2_data); | 368 | db8500_add_i2c2(parent, &u8500_i2c2_data); |
361 | db8500_add_i2c3(&u8500_i2c3_data); | 369 | db8500_add_i2c3(parent, &u8500_i2c3_data); |
362 | } | 370 | } |
363 | 371 | ||
364 | static struct gpio_keys_button mop500_gpio_keys[] = { | 372 | static struct gpio_keys_button mop500_gpio_keys[] = { |
@@ -435,7 +443,7 @@ static struct stedma40_chan_cfg ssp0_dma_cfg_tx = { | |||
435 | }; | 443 | }; |
436 | #endif | 444 | #endif |
437 | 445 | ||
438 | static struct pl022_ssp_controller ssp0_platform_data = { | 446 | static struct pl022_ssp_controller ssp0_plat = { |
439 | .bus_id = 0, | 447 | .bus_id = 0, |
440 | #ifdef CONFIG_STE_DMA40 | 448 | #ifdef CONFIG_STE_DMA40 |
441 | .enable_dma = 1, | 449 | .enable_dma = 1, |
@@ -451,9 +459,9 @@ static struct pl022_ssp_controller ssp0_platform_data = { | |||
451 | .num_chipselect = 5, | 459 | .num_chipselect = 5, |
452 | }; | 460 | }; |
453 | 461 | ||
454 | static void __init mop500_spi_init(void) | 462 | static void __init mop500_spi_init(struct device *parent) |
455 | { | 463 | { |
456 | db8500_add_ssp0(&ssp0_platform_data); | 464 | db8500_add_ssp0(parent, &ssp0_plat); |
457 | } | 465 | } |
458 | 466 | ||
459 | #ifdef CONFIG_STE_DMA40 | 467 | #ifdef CONFIG_STE_DMA40 |
@@ -587,11 +595,11 @@ static struct amba_pl011_data uart2_plat = { | |||
587 | #endif | 595 | #endif |
588 | }; | 596 | }; |
589 | 597 | ||
590 | static void __init mop500_uart_init(void) | 598 | static void __init mop500_uart_init(struct device *parent) |
591 | { | 599 | { |
592 | db8500_add_uart0(&uart0_plat); | 600 | db8500_add_uart0(parent, &uart0_plat); |
593 | db8500_add_uart1(&uart1_plat); | 601 | db8500_add_uart1(parent, &uart1_plat); |
594 | db8500_add_uart2(&uart2_plat); | 602 | db8500_add_uart2(parent, &uart2_plat); |
595 | } | 603 | } |
596 | 604 | ||
597 | static struct platform_device *snowball_platform_devs[] __initdata = { | 605 | static struct platform_device *snowball_platform_devs[] __initdata = { |
@@ -603,21 +611,27 @@ static struct platform_device *snowball_platform_devs[] __initdata = { | |||
603 | 611 | ||
604 | static void __init mop500_init_machine(void) | 612 | static void __init mop500_init_machine(void) |
605 | { | 613 | { |
614 | struct device *parent = NULL; | ||
606 | int i2c0_devs; | 615 | int i2c0_devs; |
616 | int i; | ||
607 | 617 | ||
608 | mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; | 618 | mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; |
609 | 619 | ||
610 | u8500_init_devices(); | 620 | parent = u8500_init_devices(); |
611 | 621 | ||
612 | mop500_pins_init(); | 622 | mop500_pins_init(); |
613 | 623 | ||
624 | /* FIXME: parent of ab8500 should be prcmu */ | ||
625 | for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) | ||
626 | mop500_platform_devs[i]->dev.parent = parent; | ||
627 | |||
614 | platform_add_devices(mop500_platform_devs, | 628 | platform_add_devices(mop500_platform_devs, |
615 | ARRAY_SIZE(mop500_platform_devs)); | 629 | ARRAY_SIZE(mop500_platform_devs)); |
616 | 630 | ||
617 | mop500_i2c_init(); | 631 | mop500_i2c_init(parent); |
618 | mop500_sdi_init(); | 632 | mop500_sdi_init(parent); |
619 | mop500_spi_init(); | 633 | mop500_spi_init(parent); |
620 | mop500_uart_init(); | 634 | mop500_uart_init(parent); |
621 | 635 | ||
622 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); | 636 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); |
623 | 637 | ||
@@ -631,19 +645,24 @@ static void __init mop500_init_machine(void) | |||
631 | 645 | ||
632 | static void __init snowball_init_machine(void) | 646 | static void __init snowball_init_machine(void) |
633 | { | 647 | { |
648 | struct device *parent = NULL; | ||
634 | int i2c0_devs; | 649 | int i2c0_devs; |
650 | int i; | ||
635 | 651 | ||
636 | u8500_init_devices(); | 652 | parent = u8500_init_devices(); |
637 | 653 | ||
638 | snowball_pins_init(); | 654 | snowball_pins_init(); |
639 | 655 | ||
656 | for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++) | ||
657 | snowball_platform_devs[i]->dev.parent = parent; | ||
658 | |||
640 | platform_add_devices(snowball_platform_devs, | 659 | platform_add_devices(snowball_platform_devs, |
641 | ARRAY_SIZE(snowball_platform_devs)); | 660 | ARRAY_SIZE(snowball_platform_devs)); |
642 | 661 | ||
643 | mop500_i2c_init(); | 662 | mop500_i2c_init(parent); |
644 | snowball_sdi_init(); | 663 | snowball_sdi_init(parent); |
645 | mop500_spi_init(); | 664 | mop500_spi_init(parent); |
646 | mop500_uart_init(); | 665 | mop500_uart_init(parent); |
647 | 666 | ||
648 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); | 667 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); |
649 | i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); | 668 | i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); |
@@ -656,7 +675,9 @@ static void __init snowball_init_machine(void) | |||
656 | 675 | ||
657 | static void __init hrefv60_init_machine(void) | 676 | static void __init hrefv60_init_machine(void) |
658 | { | 677 | { |
678 | struct device *parent = NULL; | ||
659 | int i2c0_devs; | 679 | int i2c0_devs; |
680 | int i; | ||
660 | 681 | ||
661 | /* | 682 | /* |
662 | * The HREFv60 board removed a GPIO expander and routed | 683 | * The HREFv60 board removed a GPIO expander and routed |
@@ -665,17 +686,20 @@ static void __init hrefv60_init_machine(void) | |||
665 | */ | 686 | */ |
666 | mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; | 687 | mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; |
667 | 688 | ||
668 | u8500_init_devices(); | 689 | parent = u8500_init_devices(); |
669 | 690 | ||
670 | hrefv60_pins_init(); | 691 | hrefv60_pins_init(); |
671 | 692 | ||
693 | for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) | ||
694 | mop500_platform_devs[i]->dev.parent = parent; | ||
695 | |||
672 | platform_add_devices(mop500_platform_devs, | 696 | platform_add_devices(mop500_platform_devs, |
673 | ARRAY_SIZE(mop500_platform_devs)); | 697 | ARRAY_SIZE(mop500_platform_devs)); |
674 | 698 | ||
675 | mop500_i2c_init(); | 699 | mop500_i2c_init(parent); |
676 | hrefv60_sdi_init(); | 700 | hrefv60_sdi_init(parent); |
677 | mop500_spi_init(); | 701 | mop500_spi_init(parent); |
678 | mop500_uart_init(); | 702 | mop500_uart_init(parent); |
679 | 703 | ||
680 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); | 704 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); |
681 | 705 | ||
@@ -718,3 +742,94 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform") | |||
718 | .handle_irq = gic_handle_irq, | 742 | .handle_irq = gic_handle_irq, |
719 | .init_machine = snowball_init_machine, | 743 | .init_machine = snowball_init_machine, |
720 | MACHINE_END | 744 | MACHINE_END |
745 | |||
746 | #ifdef CONFIG_MACH_UX500_DT | ||
747 | |||
748 | struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = { | ||
749 | OF_DEV_AUXDATA("arm,pl011", 0x80120000, "uart0", &uart0_plat), | ||
750 | OF_DEV_AUXDATA("arm,pl011", 0x80121000, "uart1", &uart1_plat), | ||
751 | OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat), | ||
752 | OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0", &ssp0_plat), | ||
753 | {}, | ||
754 | }; | ||
755 | |||
756 | static const struct of_device_id u8500_soc_node[] = { | ||
757 | /* only create devices below soc node */ | ||
758 | { .compatible = "stericsson,db8500", }, | ||
759 | { }, | ||
760 | }; | ||
761 | |||
762 | static void __init u8500_init_machine(void) | ||
763 | { | ||
764 | struct device *parent = NULL; | ||
765 | int i2c0_devs; | ||
766 | int i; | ||
767 | |||
768 | parent = u8500_init_devices(); | ||
769 | i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices); | ||
770 | |||
771 | for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++) | ||
772 | mop500_platform_devs[i]->dev.parent = parent; | ||
773 | for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++) | ||
774 | snowball_platform_devs[i]->dev.parent = parent; | ||
775 | |||
776 | /* automatically probe child nodes of db8500 device */ | ||
777 | of_platform_populate(NULL, u8500_soc_node, u8500_auxdata_lookup, parent); | ||
778 | |||
779 | if (of_machine_is_compatible("st-ericsson,mop500")) { | ||
780 | mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR; | ||
781 | mop500_pins_init(); | ||
782 | |||
783 | platform_add_devices(mop500_platform_devs, | ||
784 | ARRAY_SIZE(mop500_platform_devs)); | ||
785 | |||
786 | mop500_sdi_init(parent); | ||
787 | } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) { | ||
788 | snowball_pins_init(); | ||
789 | platform_add_devices(snowball_platform_devs, | ||
790 | ARRAY_SIZE(snowball_platform_devs)); | ||
791 | |||
792 | snowball_sdi_init(parent); | ||
793 | } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) { | ||
794 | /* | ||
795 | * The HREFv60 board removed a GPIO expander and routed | ||
796 | * all these GPIO pins to the internal GPIO controller | ||
797 | * instead. | ||
798 | */ | ||
799 | mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO; | ||
800 | i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES; | ||
801 | hrefv60_pins_init(); | ||
802 | platform_add_devices(mop500_platform_devs, | ||
803 | ARRAY_SIZE(mop500_platform_devs)); | ||
804 | |||
805 | hrefv60_sdi_init(parent); | ||
806 | } | ||
807 | mop500_i2c_init(parent); | ||
808 | |||
809 | i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs); | ||
810 | i2c_register_board_info(2, mop500_i2c2_devices, | ||
811 | ARRAY_SIZE(mop500_i2c2_devices)); | ||
812 | |||
813 | /* This board has full regulator constraints */ | ||
814 | regulator_has_full_constraints(); | ||
815 | } | ||
816 | |||
817 | static const char * u8500_dt_board_compat[] = { | ||
818 | "calaosystems,snowball-a9500", | ||
819 | "st-ericsson,hrefv60+", | ||
820 | "st-ericsson,u8500", | ||
821 | "st-ericsson,mop500", | ||
822 | NULL, | ||
823 | }; | ||
824 | |||
825 | |||
826 | DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)") | ||
827 | .map_io = u8500_map_io, | ||
828 | .init_irq = ux500_init_irq, | ||
829 | /* we re-use nomadik timer here */ | ||
830 | .timer = &ux500_timer, | ||
831 | .handle_irq = gic_handle_irq, | ||
832 | .init_machine = u8500_init_machine, | ||
833 | .dt_compat = u8500_dt_board_compat, | ||
834 | MACHINE_END | ||
835 | #endif | ||
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h index f926d3db6207..3d594c24bfee 100644 --- a/arch/arm/mach-ux500/board-mop500.h +++ b/arch/arm/mach-ux500/board-mop500.h | |||
@@ -75,10 +75,10 @@ | |||
75 | 75 | ||
76 | struct i2c_board_info; | 76 | struct i2c_board_info; |
77 | 77 | ||
78 | extern void mop500_sdi_init(void); | 78 | extern void mop500_sdi_init(struct device *parent); |
79 | extern void snowball_sdi_init(void); | 79 | extern void snowball_sdi_init(struct device *parent); |
80 | extern void hrefv60_sdi_init(void); | 80 | extern void hrefv60_sdi_init(struct device *parent); |
81 | extern void mop500_sdi_tc35892_init(void); | 81 | extern void mop500_sdi_tc35892_init(struct device *parent); |
82 | void __init mop500_u8500uib_init(void); | 82 | void __init mop500_u8500uib_init(void); |
83 | void __init mop500_stuib_init(void); | 83 | void __init mop500_stuib_init(void); |
84 | void __init mop500_pins_init(void); | 84 | void __init mop500_pins_init(void); |
diff --git a/arch/arm/mach-ux500/board-u5500-sdi.c b/arch/arm/mach-ux500/board-u5500-sdi.c index 63c3f8058ffc..836112eedde7 100644 --- a/arch/arm/mach-ux500/board-u5500-sdi.c +++ b/arch/arm/mach-ux500/board-u5500-sdi.c | |||
@@ -66,9 +66,9 @@ static struct mmci_platform_data u5500_sdi0_data = { | |||
66 | #endif | 66 | #endif |
67 | }; | 67 | }; |
68 | 68 | ||
69 | void __init u5500_sdi_init(void) | 69 | void __init u5500_sdi_init(struct device *parent) |
70 | { | 70 | { |
71 | nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins)); | 71 | nmk_config_pins(u5500_sdi_pins, ARRAY_SIZE(u5500_sdi_pins)); |
72 | 72 | ||
73 | db5500_add_sdi0(&u5500_sdi0_data); | 73 | db5500_add_sdi0(parent, &u5500_sdi0_data); |
74 | } | 74 | } |
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 9de9e9c4dbbb..0ff4be72a809 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c | |||
@@ -97,9 +97,9 @@ static struct i2c_board_info __initdata u5500_i2c2_devices[] = { | |||
97 | }, | 97 | }, |
98 | }; | 98 | }; |
99 | 99 | ||
100 | static void __init u5500_i2c_init(void) | 100 | static void __init u5500_i2c_init(struct device *parent) |
101 | { | 101 | { |
102 | db5500_add_i2c2(&u5500_i2c2_data); | 102 | db5500_add_i2c2(parent, &u5500_i2c2_data); |
103 | i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); | 103 | i2c_register_board_info(2, ARRAY_AND_SIZE(u5500_i2c2_devices)); |
104 | } | 104 | } |
105 | 105 | ||
@@ -126,20 +126,27 @@ static struct platform_device *u5500_platform_devices[] __initdata = { | |||
126 | &ab5500_device, | 126 | &ab5500_device, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | static void __init u5500_uart_init(void) | 129 | static void __init u5500_uart_init(struct device *parent) |
130 | { | 130 | { |
131 | db5500_add_uart0(NULL); | 131 | db5500_add_uart0(parent, NULL); |
132 | db5500_add_uart1(NULL); | 132 | db5500_add_uart1(parent, NULL); |
133 | db5500_add_uart2(NULL); | 133 | db5500_add_uart2(parent, NULL); |
134 | } | 134 | } |
135 | 135 | ||
136 | static void __init u5500_init_machine(void) | 136 | static void __init u5500_init_machine(void) |
137 | { | 137 | { |
138 | u5500_init_devices(); | 138 | struct device *parent = NULL; |
139 | int i; | ||
140 | |||
141 | parent = u5500_init_devices(); | ||
139 | nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); | 142 | nmk_config_pins(u5500_pins, ARRAY_SIZE(u5500_pins)); |
140 | u5500_i2c_init(); | 143 | |
141 | u5500_sdi_init(); | 144 | u5500_i2c_init(parent); |
142 | u5500_uart_init(); | 145 | u5500_sdi_init(parent); |
146 | u5500_uart_init(parent); | ||
147 | |||
148 | for (i = 0; i < ARRAY_SIZE(u5500_platform_devices); i++) | ||
149 | u5500_platform_devices[i]->dev.parent = parent; | ||
143 | 150 | ||
144 | platform_add_devices(u5500_platform_devices, | 151 | platform_add_devices(u5500_platform_devices, |
145 | ARRAY_SIZE(u5500_platform_devices)); | 152 | ARRAY_SIZE(u5500_platform_devices)); |
diff --git a/arch/arm/mach-ux500/cache-l2x0.c b/arch/arm/mach-ux500/cache-l2x0.c index da5569d83d58..77a75ed0df67 100644 --- a/arch/arm/mach-ux500/cache-l2x0.c +++ b/arch/arm/mach-ux500/cache-l2x0.c | |||
@@ -5,6 +5,8 @@ | |||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/io.h> | 7 | #include <linux/io.h> |
8 | #include <linux/of.h> | ||
9 | |||
8 | #include <asm/cacheflush.h> | 10 | #include <asm/cacheflush.h> |
9 | #include <asm/hardware/cache-l2x0.h> | 11 | #include <asm/hardware/cache-l2x0.h> |
10 | #include <mach/hardware.h> | 12 | #include <mach/hardware.h> |
@@ -45,7 +47,10 @@ static int __init ux500_l2x0_init(void) | |||
45 | ux500_l2x0_unlock(); | 47 | ux500_l2x0_unlock(); |
46 | 48 | ||
47 | /* 64KB way size, 8 way associativity, force WA */ | 49 | /* 64KB way size, 8 way associativity, force WA */ |
48 | l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); | 50 | if (of_have_populated_dt()) |
51 | l2x0_of_init(0x3e060000, 0xc0000fff); | ||
52 | else | ||
53 | l2x0_init(l2x0_base, 0x3e060000, 0xc0000fff); | ||
49 | 54 | ||
50 | /* | 55 | /* |
51 | * We can't disable l2 as we are in non secure mode, currently | 56 | * We can't disable l2 as we are in non secure mode, currently |
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c index 18aa5c05c69e..bca47f32082f 100644 --- a/arch/arm/mach-ux500/cpu-db5500.c +++ b/arch/arm/mach-ux500/cpu-db5500.c | |||
@@ -147,13 +147,13 @@ static resource_size_t __initdata db5500_gpio_base[] = { | |||
147 | U5500_GPIOBANK7_BASE, | 147 | U5500_GPIOBANK7_BASE, |
148 | }; | 148 | }; |
149 | 149 | ||
150 | static void __init db5500_add_gpios(void) | 150 | static void __init db5500_add_gpios(struct device *parent) |
151 | { | 151 | { |
152 | struct nmk_gpio_platform_data pdata = { | 152 | struct nmk_gpio_platform_data pdata = { |
153 | /* No custom data yet */ | 153 | /* No custom data yet */ |
154 | }; | 154 | }; |
155 | 155 | ||
156 | dbx500_add_gpios(ARRAY_AND_SIZE(db5500_gpio_base), | 156 | dbx500_add_gpios(parent, ARRAY_AND_SIZE(db5500_gpio_base), |
157 | IRQ_DB5500_GPIO0, &pdata); | 157 | IRQ_DB5500_GPIO0, &pdata); |
158 | } | 158 | } |
159 | 159 | ||
@@ -212,14 +212,36 @@ static int usb_db5500_tx_dma_cfg[] = { | |||
212 | DB5500_DMA_DEV38_USB_OTG_OEP_8 | 212 | DB5500_DMA_DEV38_USB_OTG_OEP_8 |
213 | }; | 213 | }; |
214 | 214 | ||
215 | void __init u5500_init_devices(void) | 215 | static const char *db5500_read_soc_id(void) |
216 | { | 216 | { |
217 | db5500_add_gpios(); | 217 | return kasprintf(GFP_KERNEL, "u5500 currently unsupported\n"); |
218 | } | ||
219 | |||
220 | static struct device * __init db5500_soc_device_init(void) | ||
221 | { | ||
222 | const char *soc_id = db5500_read_soc_id(); | ||
223 | |||
224 | return ux500_soc_device_init(soc_id); | ||
225 | } | ||
226 | |||
227 | struct device * __init u5500_init_devices(void) | ||
228 | { | ||
229 | struct device *parent; | ||
230 | int i; | ||
231 | |||
232 | parent = db5500_soc_device_init(); | ||
233 | |||
234 | db5500_add_gpios(parent); | ||
218 | db5500_pmu_init(); | 235 | db5500_pmu_init(); |
219 | db5500_dma_init(); | 236 | db5500_dma_init(parent); |
220 | db5500_add_rtc(); | 237 | db5500_add_rtc(parent); |
221 | db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); | 238 | db5500_add_usb(parent, usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg); |
239 | |||
240 | for (i = 0; i < ARRAY_SIZE(db5500_platform_devs); i++) | ||
241 | db5500_platform_devs[i]->dev.parent = parent; | ||
222 | 242 | ||
223 | platform_add_devices(db5500_platform_devs, | 243 | platform_add_devices(db5500_platform_devs, |
224 | ARRAY_SIZE(db5500_platform_devs)); | 244 | ARRAY_SIZE(db5500_platform_devs)); |
245 | |||
246 | return parent; | ||
225 | } | 247 | } |
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index 7176ee7491ab..9bd8163896cf 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <mach/setup.h> | 24 | #include <mach/setup.h> |
25 | #include <mach/devices.h> | 25 | #include <mach/devices.h> |
26 | #include <mach/usb.h> | 26 | #include <mach/usb.h> |
27 | #include <mach/db8500-regs.h> | ||
27 | 28 | ||
28 | #include "devices-db8500.h" | 29 | #include "devices-db8500.h" |
29 | #include "ste-dma40-db8500.h" | 30 | #include "ste-dma40-db8500.h" |
@@ -132,13 +133,13 @@ static resource_size_t __initdata db8500_gpio_base[] = { | |||
132 | U8500_GPIOBANK8_BASE, | 133 | U8500_GPIOBANK8_BASE, |
133 | }; | 134 | }; |
134 | 135 | ||
135 | static void __init db8500_add_gpios(void) | 136 | static void __init db8500_add_gpios(struct device *parent) |
136 | { | 137 | { |
137 | struct nmk_gpio_platform_data pdata = { | 138 | struct nmk_gpio_platform_data pdata = { |
138 | .supports_sleepmode = true, | 139 | .supports_sleepmode = true, |
139 | }; | 140 | }; |
140 | 141 | ||
141 | dbx500_add_gpios(ARRAY_AND_SIZE(db8500_gpio_base), | 142 | dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base), |
142 | IRQ_DB8500_GPIO0, &pdata); | 143 | IRQ_DB8500_GPIO0, &pdata); |
143 | } | 144 | } |
144 | 145 | ||
@@ -164,17 +165,44 @@ static int usb_db8500_tx_dma_cfg[] = { | |||
164 | DB8500_DMA_DEV39_USB_OTG_OEP_8 | 165 | DB8500_DMA_DEV39_USB_OTG_OEP_8 |
165 | }; | 166 | }; |
166 | 167 | ||
168 | static const char *db8500_read_soc_id(void) | ||
169 | { | ||
170 | void __iomem *uid = __io_address(U8500_BB_UID_BASE); | ||
171 | |||
172 | return kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x", | ||
173 | readl((u32 *)uid+1), | ||
174 | readl((u32 *)uid+1), readl((u32 *)uid+2), | ||
175 | readl((u32 *)uid+3), readl((u32 *)uid+4)); | ||
176 | } | ||
177 | |||
178 | static struct device * __init db8500_soc_device_init(void) | ||
179 | { | ||
180 | const char *soc_id = db8500_read_soc_id(); | ||
181 | |||
182 | return ux500_soc_device_init(soc_id); | ||
183 | } | ||
184 | |||
167 | /* | 185 | /* |
168 | * This function is called from the board init | 186 | * This function is called from the board init |
169 | */ | 187 | */ |
170 | void __init u8500_init_devices(void) | 188 | struct device * __init u8500_init_devices(void) |
171 | { | 189 | { |
172 | db8500_add_rtc(); | 190 | struct device *parent; |
173 | db8500_add_gpios(); | 191 | int i; |
174 | db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); | 192 | |
193 | parent = db8500_soc_device_init(); | ||
194 | |||
195 | db8500_add_rtc(parent); | ||
196 | db8500_add_gpios(parent); | ||
197 | db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg); | ||
198 | |||
199 | platform_device_register_data(parent, | ||
200 | "cpufreq-u8500", -1, NULL, 0); | ||
201 | |||
202 | for (i = 0; i < ARRAY_SIZE(platform_devs); i++) | ||
203 | platform_devs[i]->dev.parent = parent; | ||
175 | 204 | ||
176 | platform_device_register_simple("cpufreq-u8500", -1, NULL, 0); | ||
177 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); | 205 | platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs)); |
178 | 206 | ||
179 | return ; | 207 | return parent; |
180 | } | 208 | } |
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c index f41857494375..d11f3892a27d 100644 --- a/arch/arm/mach-ux500/cpu.c +++ b/arch/arm/mach-ux500/cpu.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * Copyright (C) ST-Ericsson SA 2010 | 2 | * Copyright (C) ST-Ericsson SA 2010 |
3 | * | 3 | * |
4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | 4 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson |
5 | * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson | ||
5 | * License terms: GNU General Public License (GPL) version 2 | 6 | * License terms: GNU General Public License (GPL) version 2 |
6 | */ | 7 | */ |
7 | 8 | ||
@@ -11,10 +12,15 @@ | |||
11 | #include <linux/mfd/db8500-prcmu.h> | 12 | #include <linux/mfd/db8500-prcmu.h> |
12 | #include <linux/mfd/db5500-prcmu.h> | 13 | #include <linux/mfd/db5500-prcmu.h> |
13 | #include <linux/clksrc-dbx500-prcmu.h> | 14 | #include <linux/clksrc-dbx500-prcmu.h> |
15 | #include <linux/sys_soc.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/stat.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/of_irq.h> | ||
14 | 21 | ||
15 | #include <asm/hardware/gic.h> | 22 | #include <asm/hardware/gic.h> |
16 | #include <asm/mach/map.h> | 23 | #include <asm/mach/map.h> |
17 | #include <asm/localtimer.h> | ||
18 | 24 | ||
19 | #include <mach/hardware.h> | 25 | #include <mach/hardware.h> |
20 | #include <mach/setup.h> | 26 | #include <mach/setup.h> |
@@ -24,6 +30,11 @@ | |||
24 | 30 | ||
25 | void __iomem *_PRCMU_BASE; | 31 | void __iomem *_PRCMU_BASE; |
26 | 32 | ||
33 | static const struct of_device_id ux500_dt_irq_match[] = { | ||
34 | { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, }, | ||
35 | {}, | ||
36 | }; | ||
37 | |||
27 | void __init ux500_init_irq(void) | 38 | void __init ux500_init_irq(void) |
28 | { | 39 | { |
29 | void __iomem *dist_base; | 40 | void __iomem *dist_base; |
@@ -38,7 +49,12 @@ void __init ux500_init_irq(void) | |||
38 | } else | 49 | } else |
39 | ux500_unknown_soc(); | 50 | ux500_unknown_soc(); |
40 | 51 | ||
41 | gic_init(0, 29, dist_base, cpu_base); | 52 | #ifdef CONFIG_OF |
53 | if (of_have_populated_dt()) | ||
54 | of_irq_init(ux500_dt_irq_match); | ||
55 | else | ||
56 | #endif | ||
57 | gic_init(0, 29, dist_base, cpu_base); | ||
42 | 58 | ||
43 | /* | 59 | /* |
44 | * Init clocks here so that they are available for system timer | 60 | * Init clocks here so that they are available for system timer |
@@ -50,3 +66,73 @@ void __init ux500_init_irq(void) | |||
50 | db8500_prcmu_early_init(); | 66 | db8500_prcmu_early_init(); |
51 | clk_init(); | 67 | clk_init(); |
52 | } | 68 | } |
69 | |||
70 | static const char * __init ux500_get_machine(void) | ||
71 | { | ||
72 | return kasprintf(GFP_KERNEL, "DB%4x", dbx500_partnumber()); | ||
73 | } | ||
74 | |||
75 | static const char * __init ux500_get_family(void) | ||
76 | { | ||
77 | return kasprintf(GFP_KERNEL, "ux500"); | ||
78 | } | ||
79 | |||
80 | static const char * __init ux500_get_revision(void) | ||
81 | { | ||
82 | unsigned int rev = dbx500_revision(); | ||
83 | |||
84 | if (rev == 0x01) | ||
85 | return kasprintf(GFP_KERNEL, "%s", "ED"); | ||
86 | else if (rev >= 0xA0) | ||
87 | return kasprintf(GFP_KERNEL, "%d.%d", | ||
88 | (rev >> 4) - 0xA + 1, rev & 0xf); | ||
89 | |||
90 | return kasprintf(GFP_KERNEL, "%s", "Unknown"); | ||
91 | } | ||
92 | |||
93 | static ssize_t ux500_get_process(struct device *dev, | ||
94 | struct device_attribute *attr, | ||
95 | char *buf) | ||
96 | { | ||
97 | if (dbx500_id.process == 0x00) | ||
98 | return sprintf(buf, "Standard\n"); | ||
99 | |||
100 | return sprintf(buf, "%02xnm\n", dbx500_id.process); | ||
101 | } | ||
102 | |||
103 | static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr, | ||
104 | const char *soc_id) | ||
105 | { | ||
106 | soc_dev_attr->soc_id = soc_id; | ||
107 | soc_dev_attr->machine = ux500_get_machine(); | ||
108 | soc_dev_attr->family = ux500_get_family(); | ||
109 | soc_dev_attr->revision = ux500_get_revision(); | ||
110 | } | ||
111 | |||
112 | struct device_attribute ux500_soc_attr = | ||
113 | __ATTR(process, S_IRUGO, ux500_get_process, NULL); | ||
114 | |||
115 | struct device * __init ux500_soc_device_init(const char *soc_id) | ||
116 | { | ||
117 | struct device *parent; | ||
118 | struct soc_device *soc_dev; | ||
119 | struct soc_device_attribute *soc_dev_attr; | ||
120 | |||
121 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
122 | if (!soc_dev_attr) | ||
123 | return ERR_PTR(-ENOMEM); | ||
124 | |||
125 | soc_info_populate(soc_dev_attr, soc_id); | ||
126 | |||
127 | soc_dev = soc_device_register(soc_dev_attr); | ||
128 | if (IS_ERR_OR_NULL(soc_dev)) { | ||
129 | kfree(soc_dev_attr); | ||
130 | return NULL; | ||
131 | } | ||
132 | |||
133 | parent = soc_device_to_device(soc_dev); | ||
134 | if (!IS_ERR_OR_NULL(parent)) | ||
135 | device_create_file(parent, &ux500_soc_attr); | ||
136 | |||
137 | return parent; | ||
138 | } | ||
diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index 898a64517b09..c5312a4b49f5 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c | |||
@@ -20,8 +20,9 @@ | |||
20 | #include "devices-common.h" | 20 | #include "devices-common.h" |
21 | 21 | ||
22 | struct amba_device * | 22 | struct amba_device * |
23 | dbx500_add_amba_device(const char *name, resource_size_t base, | 23 | dbx500_add_amba_device(struct device *parent, const char *name, |
24 | int irq, void *pdata, unsigned int periphid) | 24 | resource_size_t base, int irq, void *pdata, |
25 | unsigned int periphid) | ||
25 | { | 26 | { |
26 | struct amba_device *dev; | 27 | struct amba_device *dev; |
27 | int ret; | 28 | int ret; |
@@ -39,6 +40,8 @@ dbx500_add_amba_device(const char *name, resource_size_t base, | |||
39 | 40 | ||
40 | dev->dev.platform_data = pdata; | 41 | dev->dev.platform_data = pdata; |
41 | 42 | ||
43 | dev->dev.parent = parent; | ||
44 | |||
42 | ret = amba_device_add(dev, &iomem_resource); | 45 | ret = amba_device_add(dev, &iomem_resource); |
43 | if (ret) { | 46 | if (ret) { |
44 | amba_device_put(dev); | 47 | amba_device_put(dev); |
@@ -49,60 +52,7 @@ dbx500_add_amba_device(const char *name, resource_size_t base, | |||
49 | } | 52 | } |
50 | 53 | ||
51 | static struct platform_device * | 54 | static struct platform_device * |
52 | dbx500_add_platform_device(const char *name, int id, void *pdata, | 55 | dbx500_add_gpio(struct device *parent, int id, resource_size_t addr, int irq, |
53 | struct resource *res, int resnum) | ||
54 | { | ||
55 | struct platform_device *dev; | ||
56 | int ret; | ||
57 | |||
58 | dev = platform_device_alloc(name, id); | ||
59 | if (!dev) | ||
60 | return ERR_PTR(-ENOMEM); | ||
61 | |||
62 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
63 | dev->dev.dma_mask = &dev->dev.coherent_dma_mask; | ||
64 | |||
65 | ret = platform_device_add_resources(dev, res, resnum); | ||
66 | if (ret) | ||
67 | goto out_free; | ||
68 | |||
69 | dev->dev.platform_data = pdata; | ||
70 | |||
71 | ret = platform_device_add(dev); | ||
72 | if (ret) | ||
73 | goto out_free; | ||
74 | |||
75 | return dev; | ||
76 | |||
77 | out_free: | ||
78 | platform_device_put(dev); | ||
79 | return ERR_PTR(ret); | ||
80 | } | ||
81 | |||
82 | struct platform_device * | ||
83 | dbx500_add_platform_device_4k1irq(const char *name, int id, | ||
84 | resource_size_t base, | ||
85 | int irq, void *pdata) | ||
86 | { | ||
87 | struct resource resources[] = { | ||
88 | [0] = { | ||
89 | .start = base, | ||
90 | .end = base + SZ_4K - 1, | ||
91 | .flags = IORESOURCE_MEM, | ||
92 | }, | ||
93 | [1] = { | ||
94 | .start = irq, | ||
95 | .end = irq, | ||
96 | .flags = IORESOURCE_IRQ, | ||
97 | } | ||
98 | }; | ||
99 | |||
100 | return dbx500_add_platform_device(name, id, pdata, resources, | ||
101 | ARRAY_SIZE(resources)); | ||
102 | } | ||
103 | |||
104 | static struct platform_device * | ||
105 | dbx500_add_gpio(int id, resource_size_t addr, int irq, | ||
106 | struct nmk_gpio_platform_data *pdata) | 56 | struct nmk_gpio_platform_data *pdata) |
107 | { | 57 | { |
108 | struct resource resources[] = { | 58 | struct resource resources[] = { |
@@ -118,13 +68,18 @@ dbx500_add_gpio(int id, resource_size_t addr, int irq, | |||
118 | } | 68 | } |
119 | }; | 69 | }; |
120 | 70 | ||
121 | return platform_device_register_resndata(NULL, "gpio", id, | 71 | return platform_device_register_resndata( |
122 | resources, ARRAY_SIZE(resources), | 72 | parent, |
123 | pdata, sizeof(*pdata)); | 73 | "gpio", |
74 | id, | ||
75 | resources, | ||
76 | ARRAY_SIZE(resources), | ||
77 | pdata, | ||
78 | sizeof(*pdata)); | ||
124 | } | 79 | } |
125 | 80 | ||
126 | void dbx500_add_gpios(resource_size_t *base, int num, int irq, | 81 | void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, |
127 | struct nmk_gpio_platform_data *pdata) | 82 | int irq, struct nmk_gpio_platform_data *pdata) |
128 | { | 83 | { |
129 | int first = 0; | 84 | int first = 0; |
130 | int i; | 85 | int i; |
@@ -134,6 +89,6 @@ void dbx500_add_gpios(resource_size_t *base, int num, int irq, | |||
134 | pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); | 89 | pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first); |
135 | pdata->num_gpio = 32; | 90 | pdata->num_gpio = 32; |
136 | 91 | ||
137 | dbx500_add_gpio(i, base[i], irq, pdata); | 92 | dbx500_add_gpio(parent, i, base[i], irq, pdata); |
138 | } | 93 | } |
139 | } | 94 | } |
diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 7825705033bf..39c74ec82add 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h | |||
@@ -8,80 +8,89 @@ | |||
8 | #ifndef __DEVICES_COMMON_H | 8 | #ifndef __DEVICES_COMMON_H |
9 | #define __DEVICES_COMMON_H | 9 | #define __DEVICES_COMMON_H |
10 | 10 | ||
11 | extern struct amba_device * | 11 | #include <linux/platform_device.h> |
12 | dbx500_add_amba_device(const char *name, resource_size_t base, | 12 | #include <linux/dma-mapping.h> |
13 | int irq, void *pdata, unsigned int periphid); | 13 | #include <linux/sys_soc.h> |
14 | #include <plat/i2c.h> | ||
14 | 15 | ||
15 | extern struct platform_device * | 16 | extern struct amba_device * |
16 | dbx500_add_platform_device_4k1irq(const char *name, int id, | 17 | dbx500_add_amba_device(struct device *parent, const char *name, |
17 | resource_size_t base, | 18 | resource_size_t base, int irq, void *pdata, |
18 | int irq, void *pdata); | 19 | unsigned int periphid); |
19 | 20 | ||
20 | struct spi_master_cntlr; | 21 | struct spi_master_cntlr; |
21 | 22 | ||
22 | static inline struct amba_device * | 23 | static inline struct amba_device * |
23 | dbx500_add_msp_spi(const char *name, resource_size_t base, int irq, | 24 | dbx500_add_msp_spi(struct device *parent, const char *name, |
25 | resource_size_t base, int irq, | ||
24 | struct spi_master_cntlr *pdata) | 26 | struct spi_master_cntlr *pdata) |
25 | { | 27 | { |
26 | return dbx500_add_amba_device(name, base, irq, pdata, 0); | 28 | return dbx500_add_amba_device(parent, name, base, irq, |
29 | pdata, 0); | ||
27 | } | 30 | } |
28 | 31 | ||
29 | static inline struct amba_device * | 32 | static inline struct amba_device * |
30 | dbx500_add_spi(const char *name, resource_size_t base, int irq, | 33 | dbx500_add_spi(struct device *parent, const char *name, resource_size_t base, |
31 | struct spi_master_cntlr *pdata, | 34 | int irq, struct spi_master_cntlr *pdata, |
32 | u32 periphid) | 35 | u32 periphid) |
33 | { | 36 | { |
34 | return dbx500_add_amba_device(name, base, irq, pdata, periphid); | 37 | return dbx500_add_amba_device(parent, name, base, irq, |
38 | pdata, periphid); | ||
35 | } | 39 | } |
36 | 40 | ||
37 | struct mmci_platform_data; | 41 | struct mmci_platform_data; |
38 | 42 | ||
39 | static inline struct amba_device * | 43 | static inline struct amba_device * |
40 | dbx500_add_sdi(const char *name, resource_size_t base, int irq, | 44 | dbx500_add_sdi(struct device *parent, const char *name, resource_size_t base, |
41 | struct mmci_platform_data *pdata, | 45 | int irq, struct mmci_platform_data *pdata, u32 periphid) |
42 | u32 periphid) | ||
43 | { | 46 | { |
44 | return dbx500_add_amba_device(name, base, irq, pdata, periphid); | 47 | return dbx500_add_amba_device(parent, name, base, irq, |
48 | pdata, periphid); | ||
45 | } | 49 | } |
46 | 50 | ||
47 | struct amba_pl011_data; | 51 | struct amba_pl011_data; |
48 | 52 | ||
49 | static inline struct amba_device * | 53 | static inline struct amba_device * |
50 | dbx500_add_uart(const char *name, resource_size_t base, int irq, | 54 | dbx500_add_uart(struct device *parent, const char *name, resource_size_t base, |
51 | struct amba_pl011_data *pdata) | 55 | int irq, struct amba_pl011_data *pdata) |
52 | { | 56 | { |
53 | return dbx500_add_amba_device(name, base, irq, pdata, 0); | 57 | return dbx500_add_amba_device(parent, name, base, irq, pdata, 0); |
54 | } | 58 | } |
55 | 59 | ||
56 | struct nmk_i2c_controller; | 60 | struct nmk_i2c_controller; |
57 | 61 | ||
58 | static inline struct platform_device * | 62 | static inline struct platform_device * |
59 | dbx500_add_i2c(int id, resource_size_t base, int irq, | 63 | dbx500_add_i2c(struct device *parent, int id, resource_size_t base, int irq, |
60 | struct nmk_i2c_controller *pdata) | 64 | struct nmk_i2c_controller *data) |
61 | { | ||
62 | return dbx500_add_platform_device_4k1irq("nmk-i2c", id, base, irq, | ||
63 | pdata); | ||
64 | } | ||
65 | |||
66 | struct msp_i2s_platform_data; | ||
67 | |||
68 | static inline struct platform_device * | ||
69 | dbx500_add_msp_i2s(int id, resource_size_t base, int irq, | ||
70 | struct msp_i2s_platform_data *pdata) | ||
71 | { | 65 | { |
72 | return dbx500_add_platform_device_4k1irq("MSP_I2S", id, base, irq, | 66 | struct resource res[] = { |
73 | pdata); | 67 | DEFINE_RES_MEM(base, SZ_4K), |
68 | DEFINE_RES_IRQ(irq), | ||
69 | }; | ||
70 | |||
71 | struct platform_device_info pdevinfo = { | ||
72 | .parent = parent, | ||
73 | .name = "nmk-i2c", | ||
74 | .id = id, | ||
75 | .res = res, | ||
76 | .num_res = ARRAY_SIZE(res), | ||
77 | .data = data, | ||
78 | .size_data = sizeof(*data), | ||
79 | .dma_mask = DMA_BIT_MASK(32), | ||
80 | }; | ||
81 | |||
82 | return platform_device_register_full(&pdevinfo); | ||
74 | } | 83 | } |
75 | 84 | ||
76 | static inline struct amba_device * | 85 | static inline struct amba_device * |
77 | dbx500_add_rtc(resource_size_t base, int irq) | 86 | dbx500_add_rtc(struct device *parent, resource_size_t base, int irq) |
78 | { | 87 | { |
79 | return dbx500_add_amba_device("rtc-pl031", base, irq, NULL, 0); | 88 | return dbx500_add_amba_device(parent, "rtc-pl031", base, irq, NULL, 0); |
80 | } | 89 | } |
81 | 90 | ||
82 | struct nmk_gpio_platform_data; | 91 | struct nmk_gpio_platform_data; |
83 | 92 | ||
84 | void dbx500_add_gpios(resource_size_t *base, int num, int irq, | 93 | void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, |
85 | struct nmk_gpio_platform_data *pdata); | 94 | int irq, struct nmk_gpio_platform_data *pdata); |
86 | 95 | ||
87 | #endif | 96 | #endif |
diff --git a/arch/arm/mach-ux500/devices-db5500.h b/arch/arm/mach-ux500/devices-db5500.h index 0c4bccd02b90..e70955502c35 100644 --- a/arch/arm/mach-ux500/devices-db5500.h +++ b/arch/arm/mach-ux500/devices-db5500.h | |||
@@ -10,70 +10,90 @@ | |||
10 | 10 | ||
11 | #include "devices-common.h" | 11 | #include "devices-common.h" |
12 | 12 | ||
13 | #define db5500_add_i2c1(pdata) \ | 13 | #define db5500_add_i2c1(parent, pdata) \ |
14 | dbx500_add_i2c(1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata) | 14 | dbx500_add_i2c(parent, 1, U5500_I2C1_BASE, IRQ_DB5500_I2C1, pdata) |
15 | #define db5500_add_i2c2(pdata) \ | 15 | #define db5500_add_i2c2(parent, pdata) \ |
16 | dbx500_add_i2c(2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata) | 16 | dbx500_add_i2c(parent, 2, U5500_I2C2_BASE, IRQ_DB5500_I2C2, pdata) |
17 | #define db5500_add_i2c3(pdata) \ | 17 | #define db5500_add_i2c3(parent, pdata) \ |
18 | dbx500_add_i2c(3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) | 18 | dbx500_add_i2c(parent, 3, U5500_I2C3_BASE, IRQ_DB5500_I2C3, pdata) |
19 | 19 | ||
20 | #define db5500_add_msp0_i2s(pdata) \ | 20 | #define db5500_add_msp0_spi(parent, pdata) \ |
21 | dbx500_add_msp_i2s(0, U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) | 21 | dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \ |
22 | #define db5500_add_msp1_i2s(pdata) \ | 22 | IRQ_DB5500_MSP0, pdata) |
23 | dbx500_add_msp_i2s(1, U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) | 23 | #define db5500_add_msp1_spi(parent, pdata) \ |
24 | #define db5500_add_msp2_i2s(pdata) \ | 24 | dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \ |
25 | dbx500_add_msp_i2s(2, U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) | 25 | IRQ_DB5500_MSP1, pdata) |
26 | #define db5500_add_msp2_spi(parent, pdata) \ | ||
27 | dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \ | ||
28 | IRQ_DB5500_MSP2, pdata) | ||
26 | 29 | ||
27 | #define db5500_add_msp0_spi(pdata) \ | 30 | #define db5500_add_msp0_spi(parent, pdata) \ |
28 | dbx500_add_msp_spi("msp0", U5500_MSP0_BASE, IRQ_DB5500_MSP0, pdata) | 31 | dbx500_add_msp_spi(parent, "msp0", U5500_MSP0_BASE, \ |
29 | #define db5500_add_msp1_spi(pdata) \ | 32 | IRQ_DB5500_MSP0, pdata) |
30 | dbx500_add_msp_spi("msp1", U5500_MSP1_BASE, IRQ_DB5500_MSP1, pdata) | 33 | #define db5500_add_msp1_spi(parent, pdata) \ |
31 | #define db5500_add_msp2_spi(pdata) \ | 34 | dbx500_add_msp_spi(parent, "msp1", U5500_MSP1_BASE, \ |
32 | dbx500_add_msp_spi("msp2", U5500_MSP2_BASE, IRQ_DB5500_MSP2, pdata) | 35 | IRQ_DB5500_MSP1, pdata) |
36 | #define db5500_add_msp2_spi(parent, pdata) \ | ||
37 | dbx500_add_msp_spi(parent, "msp2", U5500_MSP2_BASE, \ | ||
38 | IRQ_DB5500_MSP2, pdata) | ||
33 | 39 | ||
34 | #define db5500_add_rtc() \ | 40 | #define db5500_add_rtc(parent) \ |
35 | dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC); | 41 | dbx500_add_rtc(parent, U5500_RTC_BASE, IRQ_DB5500_RTC); |
36 | 42 | ||
37 | #define db5500_add_usb(rx_cfg, tx_cfg) \ | 43 | #define db5500_add_usb(parent, rx_cfg, tx_cfg) \ |
38 | ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) | 44 | ux500_add_usb(parent, U5500_USBOTG_BASE, \ |
45 | IRQ_DB5500_USBOTG, rx_cfg, tx_cfg) | ||
39 | 46 | ||
40 | #define db5500_add_sdi0(pdata) \ | 47 | #define db5500_add_sdi0(parent, pdata) \ |
41 | dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata, \ | 48 | dbx500_add_sdi(parent, "sdi0", U5500_SDI0_BASE, \ |
49 | IRQ_DB5500_SDMMC0, pdata, \ | ||
42 | 0x10480180) | 50 | 0x10480180) |
43 | #define db5500_add_sdi1(pdata) \ | 51 | #define db5500_add_sdi1(parent, pdata) \ |
44 | dbx500_add_sdi("sdi1", U5500_SDI1_BASE, IRQ_DB5500_SDMMC1, pdata, \ | 52 | dbx500_add_sdi(parent, "sdi1", U5500_SDI1_BASE, \ |
53 | IRQ_DB5500_SDMMC1, pdata, \ | ||
45 | 0x10480180) | 54 | 0x10480180) |
46 | #define db5500_add_sdi2(pdata) \ | 55 | #define db5500_add_sdi2(parent, pdata) \ |
47 | dbx500_add_sdi("sdi2", U5500_SDI2_BASE, IRQ_DB5500_SDMMC2, pdata \ | 56 | dbx500_add_sdi(parent, "sdi2", U5500_SDI2_BASE, \ |
57 | IRQ_DB5500_SDMMC2, pdata \ | ||
48 | 0x10480180) | 58 | 0x10480180) |
49 | #define db5500_add_sdi3(pdata) \ | 59 | #define db5500_add_sdi3(parent, pdata) \ |
50 | dbx500_add_sdi("sdi3", U5500_SDI3_BASE, IRQ_DB5500_SDMMC3, pdata \ | 60 | dbx500_add_sdi(parent, "sdi3", U5500_SDI3_BASE, \ |
61 | IRQ_DB5500_SDMMC3, pdata \ | ||
51 | 0x10480180) | 62 | 0x10480180) |
52 | #define db5500_add_sdi4(pdata) \ | 63 | #define db5500_add_sdi4(parent, pdata) \ |
53 | dbx500_add_sdi("sdi4", U5500_SDI4_BASE, IRQ_DB5500_SDMMC4, pdata \ | 64 | dbx500_add_sdi(parent, "sdi4", U5500_SDI4_BASE, \ |
65 | IRQ_DB5500_SDMMC4, pdata \ | ||
54 | 0x10480180) | 66 | 0x10480180) |
55 | 67 | ||
56 | /* This one has a bad peripheral ID in the U5500 silicon */ | 68 | /* This one has a bad peripheral ID in the U5500 silicon */ |
57 | #define db5500_add_spi0(pdata) \ | 69 | #define db5500_add_spi0(parent, pdata) \ |
58 | dbx500_add_spi("spi0", U5500_SPI0_BASE, IRQ_DB5500_SPI0, pdata, \ | 70 | dbx500_add_spi(parent, "spi0", U5500_SPI0_BASE, \ |
71 | IRQ_DB5500_SPI0, pdata, \ | ||
59 | 0x10080023) | 72 | 0x10080023) |
60 | #define db5500_add_spi1(pdata) \ | 73 | #define db5500_add_spi1(parent, pdata) \ |
61 | dbx500_add_spi("spi1", U5500_SPI1_BASE, IRQ_DB5500_SPI1, pdata, \ | 74 | dbx500_add_spi(parent, "spi1", U5500_SPI1_BASE, \ |
75 | IRQ_DB5500_SPI1, pdata, \ | ||
62 | 0x10080023) | 76 | 0x10080023) |
63 | #define db5500_add_spi2(pdata) \ | 77 | #define db5500_add_spi2(parent, pdata) \ |
64 | dbx500_add_spi("spi2", U5500_SPI2_BASE, IRQ_DB5500_SPI2, pdata \ | 78 | dbx500_add_spi(parent, "spi2", U5500_SPI2_BASE, \ |
79 | IRQ_DB5500_SPI2, pdata \ | ||
65 | 0x10080023) | 80 | 0x10080023) |
66 | #define db5500_add_spi3(pdata) \ | 81 | #define db5500_add_spi3(parent, pdata) \ |
67 | dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata \ | 82 | dbx500_add_spi(parent, "spi3", U5500_SPI3_BASE, \ |
83 | IRQ_DB5500_SPI3, pdata \ | ||
68 | 0x10080023) | 84 | 0x10080023) |
69 | 85 | ||
70 | #define db5500_add_uart0(plat) \ | 86 | #define db5500_add_uart0(parent, plat) \ |
71 | dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat) | 87 | dbx500_add_uart(parent, "uart0", U5500_UART0_BASE, \ |
72 | #define db5500_add_uart1(plat) \ | 88 | IRQ_DB5500_UART0, plat) |
73 | dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat) | 89 | #define db5500_add_uart1(parent, plat) \ |
74 | #define db5500_add_uart2(plat) \ | 90 | dbx500_add_uart(parent, "uart1", U5500_UART1_BASE, \ |
75 | dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat) | 91 | IRQ_DB5500_UART1, plat) |
76 | #define db5500_add_uart3(plat) \ | 92 | #define db5500_add_uart2(parent, plat) \ |
77 | dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat) | 93 | dbx500_add_uart(parent, "uart2", U5500_UART2_BASE, \ |
94 | IRQ_DB5500_UART2, plat) | ||
95 | #define db5500_add_uart3(parent, plat) \ | ||
96 | dbx500_add_uart(parent, "uart3", U5500_UART3_BASE, \ | ||
97 | IRQ_DB5500_UART3, plat) | ||
78 | 98 | ||
79 | #endif | 99 | #endif |
diff --git a/arch/arm/mach-ux500/devices-db8500.h b/arch/arm/mach-ux500/devices-db8500.h index cbd4a9ae8109..9fd93e9da529 100644 --- a/arch/arm/mach-ux500/devices-db8500.h +++ b/arch/arm/mach-ux500/devices-db8500.h | |||
@@ -14,88 +14,114 @@ struct ske_keypad_platform_data; | |||
14 | struct pl022_ssp_controller; | 14 | struct pl022_ssp_controller; |
15 | 15 | ||
16 | static inline struct platform_device * | 16 | static inline struct platform_device * |
17 | db8500_add_ske_keypad(struct ske_keypad_platform_data *pdata) | 17 | db8500_add_ske_keypad(struct device *parent, |
18 | struct ske_keypad_platform_data *pdata, | ||
19 | size_t size) | ||
18 | { | 20 | { |
19 | return dbx500_add_platform_device_4k1irq("nmk-ske-keypad", -1, | 21 | struct resource resources[] = { |
20 | U8500_SKE_BASE, | 22 | DEFINE_RES_MEM(U8500_SKE_BASE, SZ_4K), |
21 | IRQ_DB8500_KB, pdata); | 23 | DEFINE_RES_IRQ(IRQ_DB8500_KB), |
24 | }; | ||
25 | |||
26 | return platform_device_register_resndata(parent, "nmk-ske-keypad", -1, | ||
27 | resources, 2, pdata, size); | ||
22 | } | 28 | } |
23 | 29 | ||
24 | static inline struct amba_device * | 30 | static inline struct amba_device * |
25 | db8500_add_ssp(const char *name, resource_size_t base, int irq, | 31 | db8500_add_ssp(struct device *parent, const char *name, resource_size_t base, |
26 | struct pl022_ssp_controller *pdata) | 32 | int irq, struct pl022_ssp_controller *pdata) |
27 | { | 33 | { |
28 | return dbx500_add_amba_device(name, base, irq, pdata, 0); | 34 | return dbx500_add_amba_device(parent, name, base, irq, pdata, 0); |
29 | } | 35 | } |
30 | 36 | ||
31 | 37 | ||
32 | #define db8500_add_i2c0(pdata) \ | 38 | #define db8500_add_i2c0(parent, pdata) \ |
33 | dbx500_add_i2c(0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) | 39 | dbx500_add_i2c(parent, 0, U8500_I2C0_BASE, IRQ_DB8500_I2C0, pdata) |
34 | #define db8500_add_i2c1(pdata) \ | 40 | #define db8500_add_i2c1(parent, pdata) \ |
35 | dbx500_add_i2c(1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata) | 41 | dbx500_add_i2c(parent, 1, U8500_I2C1_BASE, IRQ_DB8500_I2C1, pdata) |
36 | #define db8500_add_i2c2(pdata) \ | 42 | #define db8500_add_i2c2(parent, pdata) \ |
37 | dbx500_add_i2c(2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata) | 43 | dbx500_add_i2c(parent, 2, U8500_I2C2_BASE, IRQ_DB8500_I2C2, pdata) |
38 | #define db8500_add_i2c3(pdata) \ | 44 | #define db8500_add_i2c3(parent, pdata) \ |
39 | dbx500_add_i2c(3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata) | 45 | dbx500_add_i2c(parent, 3, U8500_I2C3_BASE, IRQ_DB8500_I2C3, pdata) |
40 | #define db8500_add_i2c4(pdata) \ | 46 | #define db8500_add_i2c4(parent, pdata) \ |
41 | dbx500_add_i2c(4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) | 47 | dbx500_add_i2c(parent, 4, U8500_I2C4_BASE, IRQ_DB8500_I2C4, pdata) |
42 | 48 | ||
43 | #define db8500_add_msp0_i2s(pdata) \ | 49 | #define db8500_add_msp0_i2s(parent, pdata) \ |
44 | dbx500_add_msp_i2s(0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) | 50 | dbx500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) |
45 | #define db8500_add_msp1_i2s(pdata) \ | 51 | #define db8500_add_msp1_i2s(parent, pdata) \ |
46 | dbx500_add_msp_i2s(1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) | 52 | dbx500_add_msp_i2s(parent, 1, U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) |
47 | #define db8500_add_msp2_i2s(pdata) \ | 53 | #define db8500_add_msp2_i2s(parent, pdata) \ |
48 | dbx500_add_msp_i2s(2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) | 54 | dbx500_add_msp_i2s(parent, 2, U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) |
49 | #define db8500_add_msp3_i2s(pdata) \ | 55 | #define db8500_add_msp3_i2s(parent, pdata) \ |
50 | dbx500_add_msp_i2s(3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) | 56 | dbx500_add_msp_i2s(parent, 3, U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) |
51 | 57 | ||
52 | #define db8500_add_msp0_spi(pdata) \ | 58 | #define db8500_add_msp0_spi(parent, pdata) \ |
53 | dbx500_add_msp_spi("msp0", U8500_MSP0_BASE, IRQ_DB8500_MSP0, pdata) | 59 | dbx500_add_msp_spi(parent, "msp0", U8500_MSP0_BASE, \ |
54 | #define db8500_add_msp1_spi(pdata) \ | 60 | IRQ_DB8500_MSP0, pdata) |
55 | dbx500_add_msp_spi("msp1", U8500_MSP1_BASE, IRQ_DB8500_MSP1, pdata) | 61 | #define db8500_add_msp1_spi(parent, pdata) \ |
56 | #define db8500_add_msp2_spi(pdata) \ | 62 | dbx500_add_msp_spi(parent, "msp1", U8500_MSP1_BASE, \ |
57 | dbx500_add_msp_spi("msp2", U8500_MSP2_BASE, IRQ_DB8500_MSP2, pdata) | 63 | IRQ_DB8500_MSP1, pdata) |
58 | #define db8500_add_msp3_spi(pdata) \ | 64 | #define db8500_add_msp2_spi(parent, pdata) \ |
59 | dbx500_add_msp_spi("msp3", U8500_MSP3_BASE, IRQ_DB8500_MSP1, pdata) | 65 | dbx500_add_msp_spi(parent, "msp2", U8500_MSP2_BASE, \ |
60 | 66 | IRQ_DB8500_MSP2, pdata) | |
61 | #define db8500_add_rtc() \ | 67 | #define db8500_add_msp3_spi(parent, pdata) \ |
62 | dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC); | 68 | dbx500_add_msp_spi(parent, "msp3", U8500_MSP3_BASE, \ |
63 | 69 | IRQ_DB8500_MSP1, pdata) | |
64 | #define db8500_add_usb(rx_cfg, tx_cfg) \ | 70 | |
65 | ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg) | 71 | #define db8500_add_rtc(parent) \ |
66 | 72 | dbx500_add_rtc(parent, U8500_RTC_BASE, IRQ_DB8500_RTC); | |
67 | #define db8500_add_sdi0(pdata, pid) \ | 73 | |
68 | dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata, pid) | 74 | #define db8500_add_usb(parent, rx_cfg, tx_cfg) \ |
69 | #define db8500_add_sdi1(pdata, pid) \ | 75 | ux500_add_usb(parent, U8500_USBOTG_BASE, \ |
70 | dbx500_add_sdi("sdi1", U8500_SDI1_BASE, IRQ_DB8500_SDMMC1, pdata, pid) | 76 | IRQ_DB8500_USBOTG, rx_cfg, tx_cfg) |
71 | #define db8500_add_sdi2(pdata, pid) \ | 77 | |
72 | dbx500_add_sdi("sdi2", U8500_SDI2_BASE, IRQ_DB8500_SDMMC2, pdata, pid) | 78 | #define db8500_add_sdi0(parent, pdata, pid) \ |
73 | #define db8500_add_sdi3(pdata, pid) \ | 79 | dbx500_add_sdi(parent, "sdi0", U8500_SDI0_BASE, \ |
74 | dbx500_add_sdi("sdi3", U8500_SDI3_BASE, IRQ_DB8500_SDMMC3, pdata, pid) | 80 | IRQ_DB8500_SDMMC0, pdata, pid) |
75 | #define db8500_add_sdi4(pdata, pid) \ | 81 | #define db8500_add_sdi1(parent, pdata, pid) \ |
76 | dbx500_add_sdi("sdi4", U8500_SDI4_BASE, IRQ_DB8500_SDMMC4, pdata, pid) | 82 | dbx500_add_sdi(parent, "sdi1", U8500_SDI1_BASE, \ |
77 | #define db8500_add_sdi5(pdata, pid) \ | 83 | IRQ_DB8500_SDMMC1, pdata, pid) |
78 | dbx500_add_sdi("sdi5", U8500_SDI5_BASE, IRQ_DB8500_SDMMC5, pdata, pid) | 84 | #define db8500_add_sdi2(parent, pdata, pid) \ |
79 | 85 | dbx500_add_sdi(parent, "sdi2", U8500_SDI2_BASE, \ | |
80 | #define db8500_add_ssp0(pdata) \ | 86 | IRQ_DB8500_SDMMC2, pdata, pid) |
81 | db8500_add_ssp("ssp0", U8500_SSP0_BASE, IRQ_DB8500_SSP0, pdata) | 87 | #define db8500_add_sdi3(parent, pdata, pid) \ |
82 | #define db8500_add_ssp1(pdata) \ | 88 | dbx500_add_sdi(parent, "sdi3", U8500_SDI3_BASE, \ |
83 | db8500_add_ssp("ssp1", U8500_SSP1_BASE, IRQ_DB8500_SSP1, pdata) | 89 | IRQ_DB8500_SDMMC3, pdata, pid) |
84 | 90 | #define db8500_add_sdi4(parent, pdata, pid) \ | |
85 | #define db8500_add_spi0(pdata) \ | 91 | dbx500_add_sdi(parent, "sdi4", U8500_SDI4_BASE, \ |
86 | dbx500_add_spi("spi0", U8500_SPI0_BASE, IRQ_DB8500_SPI0, pdata, 0) | 92 | IRQ_DB8500_SDMMC4, pdata, pid) |
87 | #define db8500_add_spi1(pdata) \ | 93 | #define db8500_add_sdi5(parent, pdata, pid) \ |
88 | dbx500_add_spi("spi1", U8500_SPI1_BASE, IRQ_DB8500_SPI1, pdata, 0) | 94 | dbx500_add_sdi(parent, "sdi5", U8500_SDI5_BASE, \ |
89 | #define db8500_add_spi2(pdata) \ | 95 | IRQ_DB8500_SDMMC5, pdata, pid) |
90 | dbx500_add_spi("spi2", U8500_SPI2_BASE, IRQ_DB8500_SPI2, pdata, 0) | 96 | |
91 | #define db8500_add_spi3(pdata) \ | 97 | #define db8500_add_ssp0(parent, pdata) \ |
92 | dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata, 0) | 98 | db8500_add_ssp(parent, "ssp0", U8500_SSP0_BASE, \ |
93 | 99 | IRQ_DB8500_SSP0, pdata) | |
94 | #define db8500_add_uart0(pdata) \ | 100 | #define db8500_add_ssp1(parent, pdata) \ |
95 | dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata) | 101 | db8500_add_ssp(parent, "ssp1", U8500_SSP1_BASE, \ |
96 | #define db8500_add_uart1(pdata) \ | 102 | IRQ_DB8500_SSP1, pdata) |
97 | dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata) | 103 | |
98 | #define db8500_add_uart2(pdata) \ | 104 | #define db8500_add_spi0(parent, pdata) \ |
99 | dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata) | 105 | dbx500_add_spi(parent, "spi0", U8500_SPI0_BASE, \ |
106 | IRQ_DB8500_SPI0, pdata, 0) | ||
107 | #define db8500_add_spi1(parent, pdata) \ | ||
108 | dbx500_add_spi(parent, "spi1", U8500_SPI1_BASE, \ | ||
109 | IRQ_DB8500_SPI1, pdata, 0) | ||
110 | #define db8500_add_spi2(parent, pdata) \ | ||
111 | dbx500_add_spi(parent, "spi2", U8500_SPI2_BASE, \ | ||
112 | IRQ_DB8500_SPI2, pdata, 0) | ||
113 | #define db8500_add_spi3(parent, pdata) \ | ||
114 | dbx500_add_spi(parent, "spi3", U8500_SPI3_BASE, \ | ||
115 | IRQ_DB8500_SPI3, pdata, 0) | ||
116 | |||
117 | #define db8500_add_uart0(parent, pdata) \ | ||
118 | dbx500_add_uart(parent, "uart0", U8500_UART0_BASE, \ | ||
119 | IRQ_DB8500_UART0, pdata) | ||
120 | #define db8500_add_uart1(parent, pdata) \ | ||
121 | dbx500_add_uart(parent, "uart1", U8500_UART1_BASE, \ | ||
122 | IRQ_DB8500_UART1, pdata) | ||
123 | #define db8500_add_uart2(parent, pdata) \ | ||
124 | dbx500_add_uart(parent, "uart2", U8500_UART2_BASE, \ | ||
125 | IRQ_DB8500_UART2, pdata) | ||
100 | 126 | ||
101 | #endif | 127 | #endif |
diff --git a/arch/arm/mach-ux500/dma-db5500.c b/arch/arm/mach-ux500/dma-db5500.c index 1cfab68ae417..41e9470fa0e6 100644 --- a/arch/arm/mach-ux500/dma-db5500.c +++ b/arch/arm/mach-ux500/dma-db5500.c | |||
@@ -125,10 +125,11 @@ static struct platform_device dma40_device = { | |||
125 | .resource = dma40_resources | 125 | .resource = dma40_resources |
126 | }; | 126 | }; |
127 | 127 | ||
128 | void __init db5500_dma_init(void) | 128 | void __init db5500_dma_init(struct device *parent) |
129 | { | 129 | { |
130 | int ret; | 130 | int ret; |
131 | 131 | ||
132 | dma40_device.dev.parent = parent; | ||
132 | ret = platform_device_register(&dma40_device); | 133 | ret = platform_device_register(&dma40_device); |
133 | if (ret) | 134 | if (ret) |
134 | dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); | 135 | dev_err(&dma40_device.dev, "unable to register device: %d\n", ret); |
diff --git a/arch/arm/mach-ux500/include/mach/db8500-regs.h b/arch/arm/mach-ux500/include/mach/db8500-regs.h index 80e10f50282e..9ec20b96d8f2 100644 --- a/arch/arm/mach-ux500/include/mach/db8500-regs.h +++ b/arch/arm/mach-ux500/include/mach/db8500-regs.h | |||
@@ -161,4 +161,7 @@ | |||
161 | #define U8500_MODEM_BASE 0xe000000 | 161 | #define U8500_MODEM_BASE 0xe000000 |
162 | #define U8500_APE_BASE 0x6000000 | 162 | #define U8500_APE_BASE 0x6000000 |
163 | 163 | ||
164 | /* SoC identification number information */ | ||
165 | #define U8500_BB_UID_BASE (U8500_BACKUPRAM1_BASE + 0xFC0) | ||
166 | |||
164 | #endif | 167 | #endif |
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h index a7d363fdb4cd..3dc00ffa7bfa 100644 --- a/arch/arm/mach-ux500/include/mach/setup.h +++ b/arch/arm/mach-ux500/include/mach/setup.h | |||
@@ -18,17 +18,16 @@ void __init ux500_map_io(void); | |||
18 | extern void __init u5500_map_io(void); | 18 | extern void __init u5500_map_io(void); |
19 | extern void __init u8500_map_io(void); | 19 | extern void __init u8500_map_io(void); |
20 | 20 | ||
21 | extern void __init u5500_init_devices(void); | 21 | extern struct device * __init u5500_init_devices(void); |
22 | extern void __init u8500_init_devices(void); | 22 | extern struct device * __init u8500_init_devices(void); |
23 | 23 | ||
24 | extern void __init ux500_init_irq(void); | 24 | extern void __init ux500_init_irq(void); |
25 | 25 | ||
26 | extern void __init u5500_sdi_init(void); | 26 | extern void __init u5500_sdi_init(struct device *parent); |
27 | 27 | ||
28 | extern void __init db5500_dma_init(void); | 28 | extern void __init db5500_dma_init(struct device *parent); |
29 | 29 | ||
30 | /* We re-use nomadik_timer for this platform */ | 30 | extern struct device *ux500_soc_device_init(const char *soc_id); |
31 | extern void nmdk_timer_init(void); | ||
32 | 31 | ||
33 | struct amba_device; | 32 | struct amba_device; |
34 | extern void __init amba_add_devices(struct amba_device *devs[], int num); | 33 | extern void __init amba_add_devices(struct amba_device *devs[], int num); |
diff --git a/arch/arm/mach-ux500/include/mach/usb.h b/arch/arm/mach-ux500/include/mach/usb.h index d3739d418813..4c1cc50a595a 100644 --- a/arch/arm/mach-ux500/include/mach/usb.h +++ b/arch/arm/mach-ux500/include/mach/usb.h | |||
@@ -20,6 +20,6 @@ struct ux500_musb_board_data { | |||
20 | bool (*dma_filter)(struct dma_chan *chan, void *filter_param); | 20 | bool (*dma_filter)(struct dma_chan *chan, void *filter_param); |
21 | }; | 21 | }; |
22 | 22 | ||
23 | void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, | 23 | void ux500_add_usb(struct device *parent, resource_size_t base, |
24 | int *dma_tx_cfg); | 24 | int irq, int *dma_rx_cfg, int *dma_tx_cfg); |
25 | #endif | 25 | #endif |
diff --git a/arch/arm/mach-ux500/localtimer.c b/arch/arm/mach-ux500/localtimer.c deleted file mode 100644 index 5ba113309a0b..000000000000 --- a/arch/arm/mach-ux500/localtimer.c +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008-2009 ST-Ericsson | ||
3 | * Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | ||
4 | * | ||
5 | * This file is heavily based on relaview platform, almost a copy. | ||
6 | * | ||
7 | * Copyright (C) 2002 ARM Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/clockchips.h> | ||
16 | |||
17 | #include <asm/irq.h> | ||
18 | #include <asm/smp_twd.h> | ||
19 | #include <asm/localtimer.h> | ||
20 | |||
21 | /* | ||
22 | * Setup the local clock events for a CPU. | ||
23 | */ | ||
24 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
25 | { | ||
26 | evt->irq = IRQ_LOCALTIMER; | ||
27 | twd_timer_setup(evt); | ||
28 | return 0; | ||
29 | } | ||
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c index aea467d04ff7..d37df98b5c32 100644 --- a/arch/arm/mach-ux500/timer.c +++ b/arch/arm/mach-ux500/timer.c | |||
@@ -7,29 +7,52 @@ | |||
7 | #include <linux/io.h> | 7 | #include <linux/io.h> |
8 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
9 | #include <linux/clksrc-dbx500-prcmu.h> | 9 | #include <linux/clksrc-dbx500-prcmu.h> |
10 | #include <linux/of.h> | ||
10 | 11 | ||
11 | #include <asm/localtimer.h> | 12 | #include <asm/smp_twd.h> |
12 | 13 | ||
13 | #include <plat/mtu.h> | 14 | #include <plat/mtu.h> |
14 | 15 | ||
15 | #include <mach/setup.h> | 16 | #include <mach/setup.h> |
16 | #include <mach/hardware.h> | 17 | #include <mach/hardware.h> |
18 | #include <mach/irqs.h> | ||
19 | |||
20 | #ifdef CONFIG_HAVE_ARM_TWD | ||
21 | static DEFINE_TWD_LOCAL_TIMER(u5500_twd_local_timer, | ||
22 | U5500_TWD_BASE, IRQ_LOCALTIMER); | ||
23 | static DEFINE_TWD_LOCAL_TIMER(u8500_twd_local_timer, | ||
24 | U8500_TWD_BASE, IRQ_LOCALTIMER); | ||
25 | |||
26 | static void __init ux500_twd_init(void) | ||
27 | { | ||
28 | struct twd_local_timer *twd_local_timer; | ||
29 | int err; | ||
30 | |||
31 | twd_local_timer = cpu_is_u5500() ? &u5500_twd_local_timer : | ||
32 | &u8500_twd_local_timer; | ||
33 | |||
34 | if (of_have_populated_dt()) | ||
35 | twd_local_timer_of_register(); | ||
36 | else { | ||
37 | err = twd_local_timer_register(twd_local_timer); | ||
38 | if (err) | ||
39 | pr_err("twd_local_timer_register failed %d\n", err); | ||
40 | } | ||
41 | } | ||
42 | #else | ||
43 | #define ux500_twd_init() do { } while(0) | ||
44 | #endif | ||
17 | 45 | ||
18 | static void __init ux500_timer_init(void) | 46 | static void __init ux500_timer_init(void) |
19 | { | 47 | { |
48 | void __iomem *mtu_timer_base; | ||
20 | void __iomem *prcmu_timer_base; | 49 | void __iomem *prcmu_timer_base; |
21 | 50 | ||
22 | if (cpu_is_u5500()) { | 51 | if (cpu_is_u5500()) { |
23 | #ifdef CONFIG_LOCAL_TIMERS | 52 | mtu_timer_base = __io_address(U5500_MTU0_BASE); |
24 | twd_base = __io_address(U5500_TWD_BASE); | ||
25 | #endif | ||
26 | mtu_base = __io_address(U5500_MTU0_BASE); | ||
27 | prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE); | 53 | prcmu_timer_base = __io_address(U5500_PRCMU_TIMER_3_BASE); |
28 | } else if (cpu_is_u8500()) { | 54 | } else if (cpu_is_u8500()) { |
29 | #ifdef CONFIG_LOCAL_TIMERS | 55 | mtu_timer_base = __io_address(U8500_MTU0_BASE); |
30 | twd_base = __io_address(U8500_TWD_BASE); | ||
31 | #endif | ||
32 | mtu_base = __io_address(U8500_MTU0_BASE); | ||
33 | prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); | 56 | prcmu_timer_base = __io_address(U8500_PRCMU_TIMER_4_BASE); |
34 | } else { | 57 | } else { |
35 | ux500_unknown_soc(); | 58 | ux500_unknown_soc(); |
@@ -52,8 +75,9 @@ static void __init ux500_timer_init(void) | |||
52 | * | 75 | * |
53 | */ | 76 | */ |
54 | 77 | ||
55 | nmdk_timer_init(); | 78 | nmdk_timer_init(mtu_timer_base); |
56 | clksrc_dbx500_prcmu_init(prcmu_timer_base); | 79 | clksrc_dbx500_prcmu_init(prcmu_timer_base); |
80 | ux500_twd_init(); | ||
57 | } | 81 | } |
58 | 82 | ||
59 | static void ux500_timer_reset(void) | 83 | static void ux500_timer_reset(void) |
diff --git a/arch/arm/mach-ux500/usb.c b/arch/arm/mach-ux500/usb.c index 9f9e1c203061..a74af389bc63 100644 --- a/arch/arm/mach-ux500/usb.c +++ b/arch/arm/mach-ux500/usb.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/platform_device.h> | 7 | #include <linux/platform_device.h> |
8 | #include <linux/usb/musb.h> | 8 | #include <linux/usb/musb.h> |
9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
10 | |||
10 | #include <plat/ste_dma40.h> | 11 | #include <plat/ste_dma40.h> |
11 | #include <mach/hardware.h> | 12 | #include <mach/hardware.h> |
12 | #include <mach/usb.h> | 13 | #include <mach/usb.h> |
@@ -140,8 +141,8 @@ static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type) | |||
140 | musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx]; | 141 | musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx]; |
141 | } | 142 | } |
142 | 143 | ||
143 | void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, | 144 | void ux500_add_usb(struct device *parent, resource_size_t base, int irq, |
144 | int *dma_tx_cfg) | 145 | int *dma_rx_cfg, int *dma_tx_cfg) |
145 | { | 146 | { |
146 | ux500_musb_device.resource[0].start = base; | 147 | ux500_musb_device.resource[0].start = base; |
147 | ux500_musb_device.resource[0].end = base + SZ_64K - 1; | 148 | ux500_musb_device.resource[0].end = base + SZ_64K - 1; |
@@ -151,5 +152,7 @@ void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg, | |||
151 | ux500_usb_dma_update_rx_ch_config(dma_rx_cfg); | 152 | ux500_usb_dma_update_rx_ch_config(dma_rx_cfg); |
152 | ux500_usb_dma_update_tx_ch_config(dma_tx_cfg); | 153 | ux500_usb_dma_update_tx_ch_config(dma_tx_cfg); |
153 | 154 | ||
155 | ux500_musb_device.dev.parent = parent; | ||
156 | |||
154 | platform_device_register(&ux500_musb_device); | 157 | platform_device_register(&ux500_musb_device); |
155 | } | 158 | } |
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c index 73791f010297..c65cc3b462a5 100644 --- a/arch/arm/mach-vexpress/ct-ca9x4.c +++ b/arch/arm/mach-vexpress/ct-ca9x4.c | |||
@@ -42,15 +42,26 @@ static struct map_desc ct_ca9x4_io_desc[] __initdata = { | |||
42 | static void __init ct_ca9x4_map_io(void) | 42 | static void __init ct_ca9x4_map_io(void) |
43 | { | 43 | { |
44 | iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); | 44 | iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc)); |
45 | #ifdef CONFIG_LOCAL_TIMERS | ||
46 | twd_base = ioremap(A9_MPCORE_TWD, SZ_32); | ||
47 | #endif | ||
48 | } | 45 | } |
49 | 46 | ||
47 | #ifdef CONFIG_HAVE_ARM_TWD | ||
48 | static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, A9_MPCORE_TWD, IRQ_LOCALTIMER); | ||
49 | |||
50 | static void __init ca9x4_twd_init(void) | ||
51 | { | ||
52 | int err = twd_local_timer_register(&twd_local_timer); | ||
53 | if (err) | ||
54 | pr_err("twd_local_timer_register failed %d\n", err); | ||
55 | } | ||
56 | #else | ||
57 | #define ca9x4_twd_init() do {} while(0) | ||
58 | #endif | ||
59 | |||
50 | static void __init ct_ca9x4_init_irq(void) | 60 | static void __init ct_ca9x4_init_irq(void) |
51 | { | 61 | { |
52 | gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K), | 62 | gic_init(0, 29, ioremap(A9_MPCORE_GIC_DIST, SZ_4K), |
53 | ioremap(A9_MPCORE_GIC_CPU, SZ_256)); | 63 | ioremap(A9_MPCORE_GIC_CPU, SZ_256)); |
64 | ca9x4_twd_init(); | ||
54 | } | 65 | } |
55 | 66 | ||
56 | static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) | 67 | static void ct_ca9x4_clcd_enable(struct clcd_fb *fb) |
diff --git a/arch/arm/plat-nomadik/include/plat/mtu.h b/arch/arm/plat-nomadik/include/plat/mtu.h index 6508e7694a4b..582641f3dc01 100644 --- a/arch/arm/plat-nomadik/include/plat/mtu.h +++ b/arch/arm/plat-nomadik/include/plat/mtu.h | |||
@@ -1,9 +1,7 @@ | |||
1 | #ifndef __PLAT_MTU_H | 1 | #ifndef __PLAT_MTU_H |
2 | #define __PLAT_MTU_H | 2 | #define __PLAT_MTU_H |
3 | 3 | ||
4 | /* should be set by the platform code */ | 4 | void nmdk_timer_init(void __iomem *base); |
5 | extern void __iomem *mtu_base; | ||
6 | |||
7 | void nmdk_clkevt_reset(void); | 5 | void nmdk_clkevt_reset(void); |
8 | void nmdk_clksrc_reset(void); | 6 | void nmdk_clksrc_reset(void); |
9 | 7 | ||
diff --git a/arch/arm/plat-nomadik/timer.c b/arch/arm/plat-nomadik/timer.c index ad1b45b605a4..9222e5522a43 100644 --- a/arch/arm/plat-nomadik/timer.c +++ b/arch/arm/plat-nomadik/timer.c | |||
@@ -21,12 +21,6 @@ | |||
21 | #include <asm/sched_clock.h> | 21 | #include <asm/sched_clock.h> |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * Guaranteed runtime conversion range in seconds for | ||
25 | * the clocksource and clockevent. | ||
26 | */ | ||
27 | #define MTU_MIN_RANGE 4 | ||
28 | |||
29 | /* | ||
30 | * The MTU device hosts four different counters, with 4 set of | 24 | * The MTU device hosts four different counters, with 4 set of |
31 | * registers. These are register names. | 25 | * registers. These are register names. |
32 | */ | 26 | */ |
@@ -66,12 +60,11 @@ | |||
66 | #define MTU_PCELL2 0xff8 | 60 | #define MTU_PCELL2 0xff8 |
67 | #define MTU_PCELL3 0xffC | 61 | #define MTU_PCELL3 0xffC |
68 | 62 | ||
63 | static void __iomem *mtu_base; | ||
69 | static bool clkevt_periodic; | 64 | static bool clkevt_periodic; |
70 | static u32 clk_prescale; | 65 | static u32 clk_prescale; |
71 | static u32 nmdk_cycle; /* write-once */ | 66 | static u32 nmdk_cycle; /* write-once */ |
72 | 67 | ||
73 | void __iomem *mtu_base; /* Assigned by machine code */ | ||
74 | |||
75 | #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK | 68 | #ifdef CONFIG_NOMADIK_MTU_SCHED_CLOCK |
76 | /* | 69 | /* |
77 | * Override the global weak sched_clock symbol with this | 70 | * Override the global weak sched_clock symbol with this |
@@ -103,7 +96,6 @@ static int nmdk_clkevt_next(unsigned long evt, struct clock_event_device *ev) | |||
103 | void nmdk_clkevt_reset(void) | 96 | void nmdk_clkevt_reset(void) |
104 | { | 97 | { |
105 | if (clkevt_periodic) { | 98 | if (clkevt_periodic) { |
106 | |||
107 | /* Timer: configure load and background-load, and fire it up */ | 99 | /* Timer: configure load and background-load, and fire it up */ |
108 | writel(nmdk_cycle, mtu_base + MTU_LR(1)); | 100 | writel(nmdk_cycle, mtu_base + MTU_LR(1)); |
109 | writel(nmdk_cycle, mtu_base + MTU_BGLR(1)); | 101 | writel(nmdk_cycle, mtu_base + MTU_BGLR(1)); |
@@ -121,7 +113,6 @@ void nmdk_clkevt_reset(void) | |||
121 | static void nmdk_clkevt_mode(enum clock_event_mode mode, | 113 | static void nmdk_clkevt_mode(enum clock_event_mode mode, |
122 | struct clock_event_device *dev) | 114 | struct clock_event_device *dev) |
123 | { | 115 | { |
124 | |||
125 | switch (mode) { | 116 | switch (mode) { |
126 | case CLOCK_EVT_MODE_PERIODIC: | 117 | case CLOCK_EVT_MODE_PERIODIC: |
127 | clkevt_periodic = true; | 118 | clkevt_periodic = true; |
@@ -183,15 +174,16 @@ void nmdk_clksrc_reset(void) | |||
183 | mtu_base + MTU_CR(0)); | 174 | mtu_base + MTU_CR(0)); |
184 | } | 175 | } |
185 | 176 | ||
186 | void __init nmdk_timer_init(void) | 177 | void __init nmdk_timer_init(void __iomem *base) |
187 | { | 178 | { |
188 | unsigned long rate; | 179 | unsigned long rate; |
189 | struct clk *clk0; | 180 | struct clk *clk0; |
190 | 181 | ||
182 | mtu_base = base; | ||
191 | clk0 = clk_get_sys("mtu0", NULL); | 183 | clk0 = clk_get_sys("mtu0", NULL); |
192 | BUG_ON(IS_ERR(clk0)); | 184 | BUG_ON(IS_ERR(clk0)); |
193 | 185 | BUG_ON(clk_prepare(clk0) < 0); | |
194 | clk_enable(clk0); | 186 | BUG_ON(clk_enable(clk0) < 0); |
195 | 187 | ||
196 | /* | 188 | /* |
197 | * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz | 189 | * Tick rate is 2.4MHz for Nomadik and 2.4Mhz, 100MHz or 133 MHz |
@@ -224,17 +216,8 @@ void __init nmdk_timer_init(void) | |||
224 | setup_sched_clock(nomadik_read_sched_clock, 32, rate); | 216 | setup_sched_clock(nomadik_read_sched_clock, 32, rate); |
225 | #endif | 217 | #endif |
226 | 218 | ||
227 | /* Timer 1 is used for events */ | 219 | /* Timer 1 is used for events, register irq and clockevents */ |
228 | |||
229 | clockevents_calc_mult_shift(&nmdk_clkevt, rate, MTU_MIN_RANGE); | ||
230 | |||
231 | nmdk_clkevt.max_delta_ns = | ||
232 | clockevent_delta2ns(0xffffffff, &nmdk_clkevt); | ||
233 | nmdk_clkevt.min_delta_ns = | ||
234 | clockevent_delta2ns(0x00000002, &nmdk_clkevt); | ||
235 | nmdk_clkevt.cpumask = cpumask_of(0); | ||
236 | |||
237 | /* Register irq and clockevents */ | ||
238 | setup_irq(IRQ_MTU0, &nmdk_timer_irq); | 220 | setup_irq(IRQ_MTU0, &nmdk_timer_irq); |
239 | clockevents_register_device(&nmdk_clkevt); | 221 | nmdk_clkevt.cpumask = cpumask_of(0); |
222 | clockevents_config_and_register(&nmdk_clkevt, rate, 2, 0xffffffffU); | ||
240 | } | 223 | } |
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile index 69714db47c33..a5cb1945bdcc 100644 --- a/arch/arm/plat-versatile/Makefile +++ b/arch/arm/plat-versatile/Makefile | |||
@@ -1,5 +1,4 @@ | |||
1 | obj-y := clock.o | 1 | obj-y := clock.o |
2 | obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o | ||
3 | obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o | 2 | obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o |
4 | obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o | 3 | obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o |
5 | obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o | 4 | obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o |
diff --git a/arch/arm/plat-versatile/localtimer.c b/arch/arm/plat-versatile/localtimer.c deleted file mode 100644 index e15668793159..000000000000 --- a/arch/arm/plat-versatile/localtimer.c +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/plat-versatile/localtimer.c | ||
3 | * | ||
4 | * Copyright (C) 2002 ARM Ltd. | ||
5 | * All Rights Reserved | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/clockchips.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_address.h> | ||
16 | |||
17 | #include <asm/smp_twd.h> | ||
18 | #include <asm/localtimer.h> | ||
19 | #include <mach/irqs.h> | ||
20 | |||
21 | const static struct of_device_id twd_of_match[] __initconst = { | ||
22 | { .compatible = "arm,cortex-a9-twd-timer", }, | ||
23 | { .compatible = "arm,cortex-a5-twd-timer", }, | ||
24 | { .compatible = "arm,arm11mp-twd-timer", }, | ||
25 | { }, | ||
26 | }; | ||
27 | |||
28 | /* | ||
29 | * Setup the local clock events for a CPU. | ||
30 | */ | ||
31 | int __cpuinit local_timer_setup(struct clock_event_device *evt) | ||
32 | { | ||
33 | #if defined(CONFIG_OF) | ||
34 | static int dt_node_probed; | ||
35 | |||
36 | /* Look for TWD node only once */ | ||
37 | if (!dt_node_probed) { | ||
38 | struct device_node *node = of_find_matching_node(NULL, | ||
39 | twd_of_match); | ||
40 | |||
41 | if (node) | ||
42 | twd_base = of_iomap(node, 0); | ||
43 | |||
44 | dt_node_probed = 1; | ||
45 | } | ||
46 | #endif | ||
47 | if (!twd_base) | ||
48 | return -ENXIO; | ||
49 | |||
50 | evt->irq = IRQ_LOCALTIMER; | ||
51 | twd_timer_setup(evt); | ||
52 | return 0; | ||
53 | } | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e0829a6a4660..ab39bb20a424 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -179,6 +179,9 @@ config ARCH_HAS_DEFAULT_IDLE | |||
179 | config ARCH_HAS_CACHE_LINE_SIZE | 179 | config ARCH_HAS_CACHE_LINE_SIZE |
180 | def_bool y | 180 | def_bool y |
181 | 181 | ||
182 | config ARCH_HAS_CPU_AUTOPROBE | ||
183 | def_bool y | ||
184 | |||
182 | config HAVE_SETUP_PER_CPU_AREA | 185 | config HAVE_SETUP_PER_CPU_AREA |
183 | def_bool y | 186 | def_bool y |
184 | 187 | ||
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c index 545d0ce59818..b3350bd32c60 100644 --- a/arch/x86/crypto/aesni-intel_glue.c +++ b/arch/x86/crypto/aesni-intel_glue.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <crypto/aes.h> | 28 | #include <crypto/aes.h> |
29 | #include <crypto/cryptd.h> | 29 | #include <crypto/cryptd.h> |
30 | #include <crypto/ctr.h> | 30 | #include <crypto/ctr.h> |
31 | #include <asm/cpu_device_id.h> | ||
31 | #include <asm/i387.h> | 32 | #include <asm/i387.h> |
32 | #include <asm/aes.h> | 33 | #include <asm/aes.h> |
33 | #include <crypto/scatterwalk.h> | 34 | #include <crypto/scatterwalk.h> |
@@ -1253,14 +1254,19 @@ static struct crypto_alg __rfc4106_alg = { | |||
1253 | }; | 1254 | }; |
1254 | #endif | 1255 | #endif |
1255 | 1256 | ||
1257 | |||
1258 | static const struct x86_cpu_id aesni_cpu_id[] = { | ||
1259 | X86_FEATURE_MATCH(X86_FEATURE_AES), | ||
1260 | {} | ||
1261 | }; | ||
1262 | MODULE_DEVICE_TABLE(x86cpu, aesni_cpu_id); | ||
1263 | |||
1256 | static int __init aesni_init(void) | 1264 | static int __init aesni_init(void) |
1257 | { | 1265 | { |
1258 | int err; | 1266 | int err; |
1259 | 1267 | ||
1260 | if (!cpu_has_aes) { | 1268 | if (!x86_match_cpu(aesni_cpu_id)) |
1261 | printk(KERN_INFO "Intel AES-NI instructions are not detected.\n"); | ||
1262 | return -ENODEV; | 1269 | return -ENODEV; |
1263 | } | ||
1264 | 1270 | ||
1265 | if ((err = crypto_fpu_init())) | 1271 | if ((err = crypto_fpu_init())) |
1266 | goto fpu_err; | 1272 | goto fpu_err; |
diff --git a/arch/x86/crypto/crc32c-intel.c b/arch/x86/crypto/crc32c-intel.c index b9d00261703c..493f959261f7 100644 --- a/arch/x86/crypto/crc32c-intel.c +++ b/arch/x86/crypto/crc32c-intel.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <crypto/internal/hash.h> | 31 | #include <crypto/internal/hash.h> |
32 | 32 | ||
33 | #include <asm/cpufeature.h> | 33 | #include <asm/cpufeature.h> |
34 | #include <asm/cpu_device_id.h> | ||
34 | 35 | ||
35 | #define CHKSUM_BLOCK_SIZE 1 | 36 | #define CHKSUM_BLOCK_SIZE 1 |
36 | #define CHKSUM_DIGEST_SIZE 4 | 37 | #define CHKSUM_DIGEST_SIZE 4 |
@@ -173,13 +174,17 @@ static struct shash_alg alg = { | |||
173 | } | 174 | } |
174 | }; | 175 | }; |
175 | 176 | ||
177 | static const struct x86_cpu_id crc32c_cpu_id[] = { | ||
178 | X86_FEATURE_MATCH(X86_FEATURE_XMM4_2), | ||
179 | {} | ||
180 | }; | ||
181 | MODULE_DEVICE_TABLE(x86cpu, crc32c_cpu_id); | ||
176 | 182 | ||
177 | static int __init crc32c_intel_mod_init(void) | 183 | static int __init crc32c_intel_mod_init(void) |
178 | { | 184 | { |
179 | if (cpu_has_xmm4_2) | 185 | if (!x86_match_cpu(crc32c_cpu_id)) |
180 | return crypto_register_shash(&alg); | ||
181 | else | ||
182 | return -ENODEV; | 186 | return -ENODEV; |
187 | return crypto_register_shash(&alg); | ||
183 | } | 188 | } |
184 | 189 | ||
185 | static void __exit crc32c_intel_mod_fini(void) | 190 | static void __exit crc32c_intel_mod_fini(void) |
diff --git a/arch/x86/crypto/ghash-clmulni-intel_glue.c b/arch/x86/crypto/ghash-clmulni-intel_glue.c index 976aa64d9a20..b4bf0a63b520 100644 --- a/arch/x86/crypto/ghash-clmulni-intel_glue.c +++ b/arch/x86/crypto/ghash-clmulni-intel_glue.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <crypto/gf128mul.h> | 20 | #include <crypto/gf128mul.h> |
21 | #include <crypto/internal/hash.h> | 21 | #include <crypto/internal/hash.h> |
22 | #include <asm/i387.h> | 22 | #include <asm/i387.h> |
23 | #include <asm/cpu_device_id.h> | ||
23 | 24 | ||
24 | #define GHASH_BLOCK_SIZE 16 | 25 | #define GHASH_BLOCK_SIZE 16 |
25 | #define GHASH_DIGEST_SIZE 16 | 26 | #define GHASH_DIGEST_SIZE 16 |
@@ -294,15 +295,18 @@ static struct ahash_alg ghash_async_alg = { | |||
294 | }, | 295 | }, |
295 | }; | 296 | }; |
296 | 297 | ||
298 | static const struct x86_cpu_id pcmul_cpu_id[] = { | ||
299 | X86_FEATURE_MATCH(X86_FEATURE_PCLMULQDQ), /* Pickle-Mickle-Duck */ | ||
300 | {} | ||
301 | }; | ||
302 | MODULE_DEVICE_TABLE(x86cpu, pcmul_cpu_id); | ||
303 | |||
297 | static int __init ghash_pclmulqdqni_mod_init(void) | 304 | static int __init ghash_pclmulqdqni_mod_init(void) |
298 | { | 305 | { |
299 | int err; | 306 | int err; |
300 | 307 | ||
301 | if (!cpu_has_pclmulqdq) { | 308 | if (!x86_match_cpu(pcmul_cpu_id)) |
302 | printk(KERN_INFO "Intel PCLMULQDQ-NI instructions are not" | ||
303 | " detected.\n"); | ||
304 | return -ENODEV; | 309 | return -ENODEV; |
305 | } | ||
306 | 310 | ||
307 | err = crypto_register_shash(&ghash_alg); | 311 | err = crypto_register_shash(&ghash_alg); |
308 | if (err) | 312 | if (err) |
diff --git a/arch/x86/include/asm/cpu_device_id.h b/arch/x86/include/asm/cpu_device_id.h new file mode 100644 index 000000000000..ff501e511d91 --- /dev/null +++ b/arch/x86/include/asm/cpu_device_id.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef _CPU_DEVICE_ID | ||
2 | #define _CPU_DEVICE_ID 1 | ||
3 | |||
4 | /* | ||
5 | * Declare drivers belonging to specific x86 CPUs | ||
6 | * Similar in spirit to pci_device_id and related PCI functions | ||
7 | */ | ||
8 | |||
9 | #include <linux/mod_devicetable.h> | ||
10 | |||
11 | extern const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match); | ||
12 | |||
13 | #endif | ||
diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 8d67d428b0f9..dcb839eebc76 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h | |||
@@ -177,6 +177,7 @@ | |||
177 | #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ | 177 | #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ |
178 | #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ | 178 | #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ |
179 | #define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */ | 179 | #define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */ |
180 | #define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ | ||
180 | 181 | ||
181 | /* Virtualization flags: Linux defined, word 8 */ | 182 | /* Virtualization flags: Linux defined, word 8 */ |
182 | #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ | 183 | #define X86_FEATURE_TPR_SHADOW (8*32+ 0) /* Intel TPR Shadow */ |
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 25f24dccdcfa..6ab6aa2fdfdd 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile | |||
@@ -16,6 +16,7 @@ obj-y := intel_cacheinfo.o scattered.o topology.o | |||
16 | obj-y += proc.o capflags.o powerflags.o common.o | 16 | obj-y += proc.o capflags.o powerflags.o common.o |
17 | obj-y += vmware.o hypervisor.o sched.o mshyperv.o | 17 | obj-y += vmware.o hypervisor.o sched.o mshyperv.o |
18 | obj-y += rdrand.o | 18 | obj-y += rdrand.o |
19 | obj-y += match.o | ||
19 | 20 | ||
20 | obj-$(CONFIG_X86_32) += bugs.o | 21 | obj-$(CONFIG_X86_32) += bugs.o |
21 | obj-$(CONFIG_X86_64) += bugs_64.o | 22 | obj-$(CONFIG_X86_64) += bugs_64.o |
diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c new file mode 100644 index 000000000000..940e2d483076 --- /dev/null +++ b/arch/x86/kernel/cpu/match.c | |||
@@ -0,0 +1,92 @@ | |||
1 | #include <asm/cpu_device_id.h> | ||
2 | #include <asm/processor.h> | ||
3 | #include <linux/cpu.h> | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/slab.h> | ||
6 | |||
7 | /** | ||
8 | * x86_match_cpu - match current CPU again an array of x86_cpu_ids | ||
9 | * @match: Pointer to array of x86_cpu_ids. Last entry terminated with | ||
10 | * {}. | ||
11 | * | ||
12 | * Return the entry if the current CPU matches the entries in the | ||
13 | * passed x86_cpu_id match table. Otherwise NULL. The match table | ||
14 | * contains vendor (X86_VENDOR_*), family, model and feature bits or | ||
15 | * respective wildcard entries. | ||
16 | * | ||
17 | * A typical table entry would be to match a specific CPU | ||
18 | * { X86_VENDOR_INTEL, 6, 0x12 } | ||
19 | * or to match a specific CPU feature | ||
20 | * { X86_FEATURE_MATCH(X86_FEATURE_FOOBAR) } | ||
21 | * | ||
22 | * Fields can be wildcarded with %X86_VENDOR_ANY, %X86_FAMILY_ANY, | ||
23 | * %X86_MODEL_ANY, %X86_FEATURE_ANY or 0 (except for vendor) | ||
24 | * | ||
25 | * Arrays used to match for this should also be declared using | ||
26 | * MODULE_DEVICE_TABLE(x86_cpu, ...) | ||
27 | * | ||
28 | * This always matches against the boot cpu, assuming models and features are | ||
29 | * consistent over all CPUs. | ||
30 | */ | ||
31 | const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) | ||
32 | { | ||
33 | const struct x86_cpu_id *m; | ||
34 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
35 | |||
36 | for (m = match; m->vendor | m->family | m->model | m->feature; m++) { | ||
37 | if (m->vendor != X86_VENDOR_ANY && c->x86_vendor != m->vendor) | ||
38 | continue; | ||
39 | if (m->family != X86_FAMILY_ANY && c->x86 != m->family) | ||
40 | continue; | ||
41 | if (m->model != X86_MODEL_ANY && c->x86_model != m->model) | ||
42 | continue; | ||
43 | if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature)) | ||
44 | continue; | ||
45 | return m; | ||
46 | } | ||
47 | return NULL; | ||
48 | } | ||
49 | EXPORT_SYMBOL(x86_match_cpu); | ||
50 | |||
51 | ssize_t arch_print_cpu_modalias(struct device *dev, | ||
52 | struct device_attribute *attr, | ||
53 | char *bufptr) | ||
54 | { | ||
55 | int size = PAGE_SIZE; | ||
56 | int i, n; | ||
57 | char *buf = bufptr; | ||
58 | |||
59 | n = snprintf(buf, size, "x86cpu:vendor:%04X:family:%04X:" | ||
60 | "model:%04X:feature:", | ||
61 | boot_cpu_data.x86_vendor, | ||
62 | boot_cpu_data.x86, | ||
63 | boot_cpu_data.x86_model); | ||
64 | size -= n; | ||
65 | buf += n; | ||
66 | size -= 2; | ||
67 | for (i = 0; i < NCAPINTS*32; i++) { | ||
68 | if (boot_cpu_has(i)) { | ||
69 | n = snprintf(buf, size, ",%04X", i); | ||
70 | if (n < 0) { | ||
71 | WARN(1, "x86 features overflow page\n"); | ||
72 | break; | ||
73 | } | ||
74 | size -= n; | ||
75 | buf += n; | ||
76 | } | ||
77 | } | ||
78 | *buf++ = ','; | ||
79 | *buf++ = '\n'; | ||
80 | return buf - bufptr; | ||
81 | } | ||
82 | |||
83 | int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
84 | { | ||
85 | char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
86 | if (buf) { | ||
87 | arch_print_cpu_modalias(NULL, NULL, buf); | ||
88 | add_uevent_var(env, "MODALIAS=%s", buf); | ||
89 | kfree(buf); | ||
90 | } | ||
91 | return 0; | ||
92 | } | ||
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index c7f64e6f537a..addf9e82a7f2 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c | |||
@@ -40,6 +40,7 @@ void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) | |||
40 | { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, | 40 | { X86_FEATURE_EPB, CR_ECX, 3, 0x00000006, 0 }, |
41 | { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, | 41 | { X86_FEATURE_XSAVEOPT, CR_EAX, 0, 0x0000000d, 1 }, |
42 | { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, | 42 | { X86_FEATURE_CPB, CR_EDX, 9, 0x80000007, 0 }, |
43 | { X86_FEATURE_HW_PSTATE, CR_EDX, 7, 0x80000007, 0 }, | ||
43 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, | 44 | { X86_FEATURE_NPT, CR_EDX, 0, 0x8000000a, 0 }, |
44 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, | 45 | { X86_FEATURE_LBRV, CR_EDX, 1, 0x8000000a, 0 }, |
45 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, | 46 | { X86_FEATURE_SVML, CR_EDX, 2, 0x8000000a, 0 }, |
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index fda91c307104..87a0f8688301 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
@@ -86,6 +86,7 @@ | |||
86 | 86 | ||
87 | #include <asm/microcode.h> | 87 | #include <asm/microcode.h> |
88 | #include <asm/processor.h> | 88 | #include <asm/processor.h> |
89 | #include <asm/cpu_device_id.h> | ||
89 | 90 | ||
90 | MODULE_DESCRIPTION("Microcode Update Driver"); | 91 | MODULE_DESCRIPTION("Microcode Update Driver"); |
91 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); | 92 | MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>"); |
@@ -504,6 +505,20 @@ static struct notifier_block __refdata mc_cpu_notifier = { | |||
504 | .notifier_call = mc_cpu_callback, | 505 | .notifier_call = mc_cpu_callback, |
505 | }; | 506 | }; |
506 | 507 | ||
508 | #ifdef MODULE | ||
509 | /* Autoload on Intel and AMD systems */ | ||
510 | static const struct x86_cpu_id microcode_id[] = { | ||
511 | #ifdef CONFIG_MICROCODE_INTEL | ||
512 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, }, | ||
513 | #endif | ||
514 | #ifdef CONFIG_MICROCODE_AMD | ||
515 | { X86_VENDOR_AMD, X86_FAMILY_ANY, X86_MODEL_ANY, }, | ||
516 | #endif | ||
517 | {} | ||
518 | }; | ||
519 | MODULE_DEVICE_TABLE(x86cpu, microcode_id); | ||
520 | #endif | ||
521 | |||
507 | static int __init microcode_init(void) | 522 | static int __init microcode_init(void) |
508 | { | 523 | { |
509 | struct cpuinfo_x86 *c = &cpu_data(0); | 524 | struct cpuinfo_x86 *c = &cpu_data(0); |
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 8ae05ce18500..2801b418d7bb 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -474,6 +474,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) | |||
474 | 474 | ||
475 | #ifdef CONFIG_CPU_FREQ | 475 | #ifdef CONFIG_CPU_FREQ |
476 | acpi_processor_ppc_has_changed(pr, 0); | 476 | acpi_processor_ppc_has_changed(pr, 0); |
477 | acpi_processor_load_module(pr); | ||
477 | #endif | 478 | #endif |
478 | acpi_processor_get_throttling_info(pr); | 479 | acpi_processor_get_throttling_info(pr); |
479 | acpi_processor_get_limit_info(pr); | 480 | acpi_processor_get_limit_info(pr); |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 85b32376dad7..0af48a8554cd 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -240,6 +240,28 @@ void acpi_processor_ppc_exit(void) | |||
240 | acpi_processor_ppc_status &= ~PPC_REGISTERED; | 240 | acpi_processor_ppc_status &= ~PPC_REGISTERED; |
241 | } | 241 | } |
242 | 242 | ||
243 | /* | ||
244 | * Do a quick check if the systems looks like it should use ACPI | ||
245 | * cpufreq. We look at a _PCT method being available, but don't | ||
246 | * do a whole lot of sanity checks. | ||
247 | */ | ||
248 | void acpi_processor_load_module(struct acpi_processor *pr) | ||
249 | { | ||
250 | static int requested; | ||
251 | acpi_status status = 0; | ||
252 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
253 | |||
254 | if (!arch_has_acpi_pdc() || requested) | ||
255 | return; | ||
256 | status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); | ||
257 | if (!ACPI_FAILURE(status)) { | ||
258 | printk(KERN_INFO PREFIX "Requesting acpi_cpufreq\n"); | ||
259 | request_module_nowait("acpi_cpufreq"); | ||
260 | requested = 1; | ||
261 | } | ||
262 | kfree(buffer.pointer); | ||
263 | } | ||
264 | |||
243 | static int acpi_processor_get_performance_control(struct acpi_processor *pr) | 265 | static int acpi_processor_get_performance_control(struct acpi_processor *pr) |
244 | { | 266 | { |
245 | int result = 0; | 267 | int result = 0; |
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 7be9f79018e9..9aa618acfe97 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -176,6 +176,9 @@ config GENERIC_CPU_DEVICES | |||
176 | bool | 176 | bool |
177 | default n | 177 | default n |
178 | 178 | ||
179 | config SOC_BUS | ||
180 | bool | ||
181 | |||
179 | source "drivers/base/regmap/Kconfig" | 182 | source "drivers/base/regmap/Kconfig" |
180 | 183 | ||
181 | config DMA_SHARED_BUFFER | 184 | config DMA_SHARED_BUFFER |
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 610f9997a403..b6d1b9c4200c 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_MODULES) += module.o | |||
19 | endif | 19 | endif |
20 | obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o | 20 | obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o |
21 | obj-$(CONFIG_REGMAP) += regmap/ | 21 | obj-$(CONFIG_REGMAP) += regmap/ |
22 | obj-$(CONFIG_SOC_BUS) += soc.o | ||
22 | 23 | ||
23 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG | 24 | ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG |
24 | 25 | ||
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 40fb12288ce2..26a06b801b5b 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -1194,13 +1194,15 @@ EXPORT_SYMBOL_GPL(subsys_interface_register); | |||
1194 | 1194 | ||
1195 | void subsys_interface_unregister(struct subsys_interface *sif) | 1195 | void subsys_interface_unregister(struct subsys_interface *sif) |
1196 | { | 1196 | { |
1197 | struct bus_type *subsys = sif->subsys; | 1197 | struct bus_type *subsys; |
1198 | struct subsys_dev_iter iter; | 1198 | struct subsys_dev_iter iter; |
1199 | struct device *dev; | 1199 | struct device *dev; |
1200 | 1200 | ||
1201 | if (!sif) | 1201 | if (!sif || !sif->subsys) |
1202 | return; | 1202 | return; |
1203 | 1203 | ||
1204 | subsys = sif->subsys; | ||
1205 | |||
1204 | mutex_lock(&subsys->p->mutex); | 1206 | mutex_lock(&subsys->p->mutex); |
1205 | list_del_init(&sif->node); | 1207 | list_del_init(&sif->node); |
1206 | if (sif->remove_dev) { | 1208 | if (sif->remove_dev) { |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 4dabf5077c48..adf937bf4091 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/device.h> | 11 | #include <linux/device.h> |
12 | #include <linux/node.h> | 12 | #include <linux/node.h> |
13 | #include <linux/gfp.h> | 13 | #include <linux/gfp.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/percpu.h> | 15 | #include <linux/percpu.h> |
15 | 16 | ||
16 | #include "base.h" | 17 | #include "base.h" |
@@ -244,6 +245,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num) | |||
244 | cpu->dev.id = num; | 245 | cpu->dev.id = num; |
245 | cpu->dev.bus = &cpu_subsys; | 246 | cpu->dev.bus = &cpu_subsys; |
246 | cpu->dev.release = cpu_device_release; | 247 | cpu->dev.release = cpu_device_release; |
248 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
249 | cpu->dev.bus->uevent = arch_cpu_uevent; | ||
250 | #endif | ||
247 | error = device_register(&cpu->dev); | 251 | error = device_register(&cpu->dev); |
248 | if (!error && cpu->hotpluggable) | 252 | if (!error && cpu->hotpluggable) |
249 | register_cpu_control(cpu); | 253 | register_cpu_control(cpu); |
@@ -268,6 +272,10 @@ struct device *get_cpu_device(unsigned cpu) | |||
268 | } | 272 | } |
269 | EXPORT_SYMBOL_GPL(get_cpu_device); | 273 | EXPORT_SYMBOL_GPL(get_cpu_device); |
270 | 274 | ||
275 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
276 | static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); | ||
277 | #endif | ||
278 | |||
271 | static struct attribute *cpu_root_attrs[] = { | 279 | static struct attribute *cpu_root_attrs[] = { |
272 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | 280 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE |
273 | &dev_attr_probe.attr, | 281 | &dev_attr_probe.attr, |
@@ -278,6 +286,9 @@ static struct attribute *cpu_root_attrs[] = { | |||
278 | &cpu_attrs[2].attr.attr, | 286 | &cpu_attrs[2].attr.attr, |
279 | &dev_attr_kernel_max.attr, | 287 | &dev_attr_kernel_max.attr, |
280 | &dev_attr_offline.attr, | 288 | &dev_attr_offline.attr, |
289 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
290 | &dev_attr_modalias.attr, | ||
291 | #endif | ||
281 | NULL | 292 | NULL |
282 | }; | 293 | }; |
283 | 294 | ||
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index b631f7c59453..60e4f77ca662 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -153,34 +153,6 @@ int driver_add_kobj(struct device_driver *drv, struct kobject *kobj, | |||
153 | } | 153 | } |
154 | EXPORT_SYMBOL_GPL(driver_add_kobj); | 154 | EXPORT_SYMBOL_GPL(driver_add_kobj); |
155 | 155 | ||
156 | /** | ||
157 | * get_driver - increment driver reference count. | ||
158 | * @drv: driver. | ||
159 | */ | ||
160 | struct device_driver *get_driver(struct device_driver *drv) | ||
161 | { | ||
162 | if (drv) { | ||
163 | struct driver_private *priv; | ||
164 | struct kobject *kobj; | ||
165 | |||
166 | kobj = kobject_get(&drv->p->kobj); | ||
167 | priv = to_driver(kobj); | ||
168 | return priv->driver; | ||
169 | } | ||
170 | return NULL; | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(get_driver); | ||
173 | |||
174 | /** | ||
175 | * put_driver - decrement driver's refcount. | ||
176 | * @drv: driver. | ||
177 | */ | ||
178 | void put_driver(struct device_driver *drv) | ||
179 | { | ||
180 | kobject_put(&drv->p->kobj); | ||
181 | } | ||
182 | EXPORT_SYMBOL_GPL(put_driver); | ||
183 | |||
184 | static int driver_add_groups(struct device_driver *drv, | 156 | static int driver_add_groups(struct device_driver *drv, |
185 | const struct attribute_group **groups) | 157 | const struct attribute_group **groups) |
186 | { | 158 | { |
@@ -234,7 +206,6 @@ int driver_register(struct device_driver *drv) | |||
234 | 206 | ||
235 | other = driver_find(drv->name, drv->bus); | 207 | other = driver_find(drv->name, drv->bus); |
236 | if (other) { | 208 | if (other) { |
237 | put_driver(other); | ||
238 | printk(KERN_ERR "Error: Driver '%s' is already registered, " | 209 | printk(KERN_ERR "Error: Driver '%s' is already registered, " |
239 | "aborting...\n", drv->name); | 210 | "aborting...\n", drv->name); |
240 | return -EBUSY; | 211 | return -EBUSY; |
@@ -275,7 +246,9 @@ EXPORT_SYMBOL_GPL(driver_unregister); | |||
275 | * Call kset_find_obj() to iterate over list of drivers on | 246 | * Call kset_find_obj() to iterate over list of drivers on |
276 | * a bus to find driver by name. Return driver if found. | 247 | * a bus to find driver by name. Return driver if found. |
277 | * | 248 | * |
278 | * Note that kset_find_obj increments driver's reference count. | 249 | * This routine provides no locking to prevent the driver it returns |
250 | * from being unregistered or unloaded while the caller is using it. | ||
251 | * The caller is responsible for preventing this. | ||
279 | */ | 252 | */ |
280 | struct device_driver *driver_find(const char *name, struct bus_type *bus) | 253 | struct device_driver *driver_find(const char *name, struct bus_type *bus) |
281 | { | 254 | { |
@@ -283,6 +256,8 @@ struct device_driver *driver_find(const char *name, struct bus_type *bus) | |||
283 | struct driver_private *priv; | 256 | struct driver_private *priv; |
284 | 257 | ||
285 | if (k) { | 258 | if (k) { |
259 | /* Drop reference added by kset_find_obj() */ | ||
260 | kobject_put(k); | ||
286 | priv = to_driver(k); | 261 | priv = to_driver(k); |
287 | return priv->driver; | 262 | return priv->driver; |
288 | } | 263 | } |
diff --git a/drivers/base/soc.c b/drivers/base/soc.c new file mode 100644 index 000000000000..05f150382da8 --- /dev/null +++ b/drivers/base/soc.c | |||
@@ -0,0 +1,183 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2011 | ||
3 | * | ||
4 | * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson. | ||
5 | * License terms: GNU General Public License (GPL), version 2 | ||
6 | */ | ||
7 | |||
8 | #include <linux/sysfs.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/stat.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/idr.h> | ||
14 | #include <linux/spinlock.h> | ||
15 | #include <linux/sys_soc.h> | ||
16 | #include <linux/err.h> | ||
17 | |||
18 | static DEFINE_IDR(soc_ida); | ||
19 | static DEFINE_SPINLOCK(soc_lock); | ||
20 | |||
21 | static ssize_t soc_info_get(struct device *dev, | ||
22 | struct device_attribute *attr, | ||
23 | char *buf); | ||
24 | |||
25 | struct soc_device { | ||
26 | struct device dev; | ||
27 | struct soc_device_attribute *attr; | ||
28 | int soc_dev_num; | ||
29 | }; | ||
30 | |||
31 | static struct bus_type soc_bus_type = { | ||
32 | .name = "soc", | ||
33 | }; | ||
34 | |||
35 | static DEVICE_ATTR(machine, S_IRUGO, soc_info_get, NULL); | ||
36 | static DEVICE_ATTR(family, S_IRUGO, soc_info_get, NULL); | ||
37 | static DEVICE_ATTR(soc_id, S_IRUGO, soc_info_get, NULL); | ||
38 | static DEVICE_ATTR(revision, S_IRUGO, soc_info_get, NULL); | ||
39 | |||
40 | struct device *soc_device_to_device(struct soc_device *soc_dev) | ||
41 | { | ||
42 | return &soc_dev->dev; | ||
43 | } | ||
44 | |||
45 | static mode_t soc_attribute_mode(struct kobject *kobj, | ||
46 | struct attribute *attr, | ||
47 | int index) | ||
48 | { | ||
49 | struct device *dev = container_of(kobj, struct device, kobj); | ||
50 | struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); | ||
51 | |||
52 | if ((attr == &dev_attr_machine.attr) | ||
53 | && (soc_dev->attr->machine != NULL)) | ||
54 | return attr->mode; | ||
55 | if ((attr == &dev_attr_family.attr) | ||
56 | && (soc_dev->attr->family != NULL)) | ||
57 | return attr->mode; | ||
58 | if ((attr == &dev_attr_revision.attr) | ||
59 | && (soc_dev->attr->revision != NULL)) | ||
60 | return attr->mode; | ||
61 | if ((attr == &dev_attr_soc_id.attr) | ||
62 | && (soc_dev->attr->soc_id != NULL)) | ||
63 | return attr->mode; | ||
64 | |||
65 | /* Unknown or unfilled attribute. */ | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static ssize_t soc_info_get(struct device *dev, | ||
70 | struct device_attribute *attr, | ||
71 | char *buf) | ||
72 | { | ||
73 | struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); | ||
74 | |||
75 | if (attr == &dev_attr_machine) | ||
76 | return sprintf(buf, "%s\n", soc_dev->attr->machine); | ||
77 | if (attr == &dev_attr_family) | ||
78 | return sprintf(buf, "%s\n", soc_dev->attr->family); | ||
79 | if (attr == &dev_attr_revision) | ||
80 | return sprintf(buf, "%s\n", soc_dev->attr->revision); | ||
81 | if (attr == &dev_attr_soc_id) | ||
82 | return sprintf(buf, "%s\n", soc_dev->attr->soc_id); | ||
83 | |||
84 | return -EINVAL; | ||
85 | |||
86 | } | ||
87 | |||
88 | static struct attribute *soc_attr[] = { | ||
89 | &dev_attr_machine.attr, | ||
90 | &dev_attr_family.attr, | ||
91 | &dev_attr_soc_id.attr, | ||
92 | &dev_attr_revision.attr, | ||
93 | NULL, | ||
94 | }; | ||
95 | |||
96 | static const struct attribute_group soc_attr_group = { | ||
97 | .attrs = soc_attr, | ||
98 | .is_visible = soc_attribute_mode, | ||
99 | }; | ||
100 | |||
101 | static const struct attribute_group *soc_attr_groups[] = { | ||
102 | &soc_attr_group, | ||
103 | NULL, | ||
104 | }; | ||
105 | |||
106 | static void soc_release(struct device *dev) | ||
107 | { | ||
108 | struct soc_device *soc_dev = container_of(dev, struct soc_device, dev); | ||
109 | |||
110 | kfree(soc_dev); | ||
111 | } | ||
112 | |||
113 | struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr) | ||
114 | { | ||
115 | struct soc_device *soc_dev; | ||
116 | int ret; | ||
117 | |||
118 | soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL); | ||
119 | if (!soc_dev) { | ||
120 | ret = -ENOMEM; | ||
121 | goto out1; | ||
122 | } | ||
123 | |||
124 | /* Fetch a unique (reclaimable) SOC ID. */ | ||
125 | do { | ||
126 | if (!ida_pre_get(&soc_ida, GFP_KERNEL)) { | ||
127 | ret = -ENOMEM; | ||
128 | goto out2; | ||
129 | } | ||
130 | |||
131 | spin_lock(&soc_lock); | ||
132 | ret = ida_get_new(&soc_ida, &soc_dev->soc_dev_num); | ||
133 | spin_unlock(&soc_lock); | ||
134 | |||
135 | } while (ret == -EAGAIN); | ||
136 | |||
137 | if (ret) | ||
138 | goto out2; | ||
139 | |||
140 | soc_dev->attr = soc_dev_attr; | ||
141 | soc_dev->dev.bus = &soc_bus_type; | ||
142 | soc_dev->dev.groups = soc_attr_groups; | ||
143 | soc_dev->dev.release = soc_release; | ||
144 | |||
145 | dev_set_name(&soc_dev->dev, "soc%d", soc_dev->soc_dev_num); | ||
146 | |||
147 | ret = device_register(&soc_dev->dev); | ||
148 | if (ret) | ||
149 | goto out3; | ||
150 | |||
151 | return soc_dev; | ||
152 | |||
153 | out3: | ||
154 | ida_remove(&soc_ida, soc_dev->soc_dev_num); | ||
155 | out2: | ||
156 | kfree(soc_dev); | ||
157 | out1: | ||
158 | return ERR_PTR(ret); | ||
159 | } | ||
160 | |||
161 | /* Ensure soc_dev->attr is freed prior to calling soc_device_unregister. */ | ||
162 | void soc_device_unregister(struct soc_device *soc_dev) | ||
163 | { | ||
164 | ida_remove(&soc_ida, soc_dev->soc_dev_num); | ||
165 | |||
166 | device_unregister(&soc_dev->dev); | ||
167 | } | ||
168 | |||
169 | static int __init soc_bus_register(void) | ||
170 | { | ||
171 | spin_lock_init(&soc_lock); | ||
172 | |||
173 | return bus_register(&soc_bus_type); | ||
174 | } | ||
175 | core_initcall(soc_bus_register); | ||
176 | |||
177 | static void __exit soc_bus_unregister(void) | ||
178 | { | ||
179 | ida_destroy(&soc_ida); | ||
180 | |||
181 | bus_unregister(&soc_bus_type); | ||
182 | } | ||
183 | module_exit(soc_bus_unregister); | ||
diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index 7bac808804f3..13d311ee08b3 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c | |||
@@ -385,6 +385,14 @@ static struct cpufreq_driver nforce2_driver = { | |||
385 | .owner = THIS_MODULE, | 385 | .owner = THIS_MODULE, |
386 | }; | 386 | }; |
387 | 387 | ||
388 | #ifdef MODULE | ||
389 | static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { | ||
390 | { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2 }, | ||
391 | {} | ||
392 | }; | ||
393 | MODULE_DEVICE_TABLE(pci, nforce2_ids); | ||
394 | #endif | ||
395 | |||
388 | /** | 396 | /** |
389 | * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic | 397 | * nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic |
390 | * | 398 | * |
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 4bd6815d317b..3fffbe6025cd 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | 18 | ||
19 | #include <asm/cpu_device_id.h> | ||
19 | #include <asm/msr.h> | 20 | #include <asm/msr.h> |
20 | #include <asm/tsc.h> | 21 | #include <asm/tsc.h> |
21 | 22 | ||
@@ -437,18 +438,19 @@ static struct cpufreq_driver eps_driver = { | |||
437 | .attr = eps_attr, | 438 | .attr = eps_attr, |
438 | }; | 439 | }; |
439 | 440 | ||
441 | |||
442 | /* This driver will work only on Centaur C7 processors with | ||
443 | * Enhanced SpeedStep/PowerSaver registers */ | ||
444 | static const struct x86_cpu_id eps_cpu_id[] = { | ||
445 | { X86_VENDOR_CENTAUR, 6, X86_MODEL_ANY, X86_FEATURE_EST }, | ||
446 | {} | ||
447 | }; | ||
448 | MODULE_DEVICE_TABLE(x86cpu, eps_cpu_id); | ||
449 | |||
440 | static int __init eps_init(void) | 450 | static int __init eps_init(void) |
441 | { | 451 | { |
442 | struct cpuinfo_x86 *c = &cpu_data(0); | 452 | if (!x86_match_cpu(eps_cpu_id) || boot_cpu_data.x86_model < 10) |
443 | |||
444 | /* This driver will work only on Centaur C7 processors with | ||
445 | * Enhanced SpeedStep/PowerSaver registers */ | ||
446 | if (c->x86_vendor != X86_VENDOR_CENTAUR | ||
447 | || c->x86 != 6 || c->x86_model < 10) | ||
448 | return -ENODEV; | ||
449 | if (!cpu_has(c, X86_FEATURE_EST)) | ||
450 | return -ENODEV; | 453 | return -ENODEV; |
451 | |||
452 | if (cpufreq_register_driver(&eps_driver)) | 454 | if (cpufreq_register_driver(&eps_driver)) |
453 | return -EINVAL; | 455 | return -EINVAL; |
454 | return 0; | 456 | return 0; |
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index c587db472a75..960671fd3d7e 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/cpufreq.h> | 24 | #include <linux/cpufreq.h> |
25 | 25 | ||
26 | #include <asm/cpu_device_id.h> | ||
26 | #include <asm/msr.h> | 27 | #include <asm/msr.h> |
27 | #include <linux/timex.h> | 28 | #include <linux/timex.h> |
28 | #include <linux/io.h> | 29 | #include <linux/io.h> |
@@ -277,17 +278,16 @@ static struct cpufreq_driver elanfreq_driver = { | |||
277 | .attr = elanfreq_attr, | 278 | .attr = elanfreq_attr, |
278 | }; | 279 | }; |
279 | 280 | ||
281 | static const struct x86_cpu_id elan_id[] = { | ||
282 | { X86_VENDOR_AMD, 4, 10, }, | ||
283 | {} | ||
284 | }; | ||
285 | MODULE_DEVICE_TABLE(x86cpu, elan_id); | ||
280 | 286 | ||
281 | static int __init elanfreq_init(void) | 287 | static int __init elanfreq_init(void) |
282 | { | 288 | { |
283 | struct cpuinfo_x86 *c = &cpu_data(0); | 289 | if (!x86_match_cpu(elan_id)) |
284 | |||
285 | /* Test if we have the right hardware */ | ||
286 | if ((c->x86_vendor != X86_VENDOR_AMD) || | ||
287 | (c->x86 != 4) || (c->x86_model != 10)) { | ||
288 | printk(KERN_INFO "elanfreq: error: no Elan processor found!\n"); | ||
289 | return -ENODEV; | 290 | return -ENODEV; |
290 | } | ||
291 | return cpufreq_register_driver(&elanfreq_driver); | 291 | return cpufreq_register_driver(&elanfreq_driver); |
292 | } | 292 | } |
293 | 293 | ||
diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c index ffe1f2c92ed3..456bee058fe6 100644 --- a/drivers/cpufreq/gx-suspmod.c +++ b/drivers/cpufreq/gx-suspmod.c | |||
@@ -82,6 +82,7 @@ | |||
82 | #include <linux/errno.h> | 82 | #include <linux/errno.h> |
83 | #include <linux/slab.h> | 83 | #include <linux/slab.h> |
84 | 84 | ||
85 | #include <asm/cpu_device_id.h> | ||
85 | #include <asm/processor-cyrix.h> | 86 | #include <asm/processor-cyrix.h> |
86 | 87 | ||
87 | /* PCI config registers, all at F0 */ | 88 | /* PCI config registers, all at F0 */ |
@@ -171,6 +172,7 @@ static struct pci_device_id gx_chipset_tbl[] __initdata = { | |||
171 | { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, | 172 | { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5510), }, |
172 | { 0, }, | 173 | { 0, }, |
173 | }; | 174 | }; |
175 | MODULE_DEVICE_TABLE(pci, gx_chipset_tbl); | ||
174 | 176 | ||
175 | static void gx_write_byte(int reg, int value) | 177 | static void gx_write_byte(int reg, int value) |
176 | { | 178 | { |
@@ -185,13 +187,6 @@ static __init struct pci_dev *gx_detect_chipset(void) | |||
185 | { | 187 | { |
186 | struct pci_dev *gx_pci = NULL; | 188 | struct pci_dev *gx_pci = NULL; |
187 | 189 | ||
188 | /* check if CPU is a MediaGX or a Geode. */ | ||
189 | if ((boot_cpu_data.x86_vendor != X86_VENDOR_NSC) && | ||
190 | (boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX)) { | ||
191 | pr_debug("error: no MediaGX/Geode processor found!\n"); | ||
192 | return NULL; | ||
193 | } | ||
194 | |||
195 | /* detect which companion chip is used */ | 190 | /* detect which companion chip is used */ |
196 | for_each_pci_dev(gx_pci) { | 191 | for_each_pci_dev(gx_pci) { |
197 | if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) | 192 | if ((pci_match_id(gx_chipset_tbl, gx_pci)) != NULL) |
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index f47d26e2a135..53ddbc760af7 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/acpi.h> | 35 | #include <linux/acpi.h> |
36 | 36 | ||
37 | #include <asm/msr.h> | 37 | #include <asm/msr.h> |
38 | #include <asm/cpu_device_id.h> | ||
38 | #include <acpi/processor.h> | 39 | #include <acpi/processor.h> |
39 | 40 | ||
40 | #include "longhaul.h" | 41 | #include "longhaul.h" |
@@ -951,12 +952,17 @@ static struct cpufreq_driver longhaul_driver = { | |||
951 | .attr = longhaul_attr, | 952 | .attr = longhaul_attr, |
952 | }; | 953 | }; |
953 | 954 | ||
955 | static const struct x86_cpu_id longhaul_id[] = { | ||
956 | { X86_VENDOR_CENTAUR, 6 }, | ||
957 | {} | ||
958 | }; | ||
959 | MODULE_DEVICE_TABLE(x86cpu, longhaul_id); | ||
954 | 960 | ||
955 | static int __init longhaul_init(void) | 961 | static int __init longhaul_init(void) |
956 | { | 962 | { |
957 | struct cpuinfo_x86 *c = &cpu_data(0); | 963 | struct cpuinfo_x86 *c = &cpu_data(0); |
958 | 964 | ||
959 | if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) | 965 | if (!x86_match_cpu(longhaul_id)) |
960 | return -ENODEV; | 966 | return -ENODEV; |
961 | 967 | ||
962 | #ifdef CONFIG_SMP | 968 | #ifdef CONFIG_SMP |
diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 34ea359b370e..8bc9f5fbbaeb 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <asm/msr.h> | 15 | #include <asm/msr.h> |
16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
17 | #include <asm/cpu_device_id.h> | ||
17 | 18 | ||
18 | static struct cpufreq_driver longrun_driver; | 19 | static struct cpufreq_driver longrun_driver; |
19 | 20 | ||
@@ -288,6 +289,12 @@ static struct cpufreq_driver longrun_driver = { | |||
288 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
289 | }; | 290 | }; |
290 | 291 | ||
292 | static const struct x86_cpu_id longrun_ids[] = { | ||
293 | { X86_VENDOR_TRANSMETA, X86_FAMILY_ANY, X86_MODEL_ANY, | ||
294 | X86_FEATURE_LONGRUN }, | ||
295 | {} | ||
296 | }; | ||
297 | MODULE_DEVICE_TABLE(x86cpu, longrun_ids); | ||
291 | 298 | ||
292 | /** | 299 | /** |
293 | * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver | 300 | * longrun_init - initializes the Transmeta Crusoe LongRun CPUFreq driver |
@@ -296,12 +303,8 @@ static struct cpufreq_driver longrun_driver = { | |||
296 | */ | 303 | */ |
297 | static int __init longrun_init(void) | 304 | static int __init longrun_init(void) |
298 | { | 305 | { |
299 | struct cpuinfo_x86 *c = &cpu_data(0); | 306 | if (!x86_match_cpu(longrun_ids)) |
300 | |||
301 | if (c->x86_vendor != X86_VENDOR_TRANSMETA || | ||
302 | !cpu_has(c, X86_FEATURE_LONGRUN)) | ||
303 | return -ENODEV; | 307 | return -ENODEV; |
304 | |||
305 | return cpufreq_register_driver(&longrun_driver); | 308 | return cpufreq_register_driver(&longrun_driver); |
306 | } | 309 | } |
307 | 310 | ||
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 6be3e0760c26..827629c9aad7 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/processor.h> | 31 | #include <asm/processor.h> |
32 | #include <asm/msr.h> | 32 | #include <asm/msr.h> |
33 | #include <asm/timer.h> | 33 | #include <asm/timer.h> |
34 | #include <asm/cpu_device_id.h> | ||
34 | 35 | ||
35 | #include "speedstep-lib.h" | 36 | #include "speedstep-lib.h" |
36 | 37 | ||
@@ -289,21 +290,25 @@ static struct cpufreq_driver p4clockmod_driver = { | |||
289 | .attr = p4clockmod_attr, | 290 | .attr = p4clockmod_attr, |
290 | }; | 291 | }; |
291 | 292 | ||
293 | static const struct x86_cpu_id cpufreq_p4_id[] = { | ||
294 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ACC }, | ||
295 | {} | ||
296 | }; | ||
297 | |||
298 | /* | ||
299 | * Intentionally no MODULE_DEVICE_TABLE here: this driver should not | ||
300 | * be auto loaded. Please don't add one. | ||
301 | */ | ||
292 | 302 | ||
293 | static int __init cpufreq_p4_init(void) | 303 | static int __init cpufreq_p4_init(void) |
294 | { | 304 | { |
295 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
296 | int ret; | 305 | int ret; |
297 | 306 | ||
298 | /* | 307 | /* |
299 | * THERM_CONTROL is architectural for IA32 now, so | 308 | * THERM_CONTROL is architectural for IA32 now, so |
300 | * we can rely on the capability checks | 309 | * we can rely on the capability checks |
301 | */ | 310 | */ |
302 | if (c->x86_vendor != X86_VENDOR_INTEL) | 311 | if (!x86_match_cpu(cpufreq_p4_id) || !boot_cpu_has(X86_FEATURE_ACPI)) |
303 | return -ENODEV; | ||
304 | |||
305 | if (!test_cpu_cap(c, X86_FEATURE_ACPI) || | ||
306 | !test_cpu_cap(c, X86_FEATURE_ACC)) | ||
307 | return -ENODEV; | 312 | return -ENODEV; |
308 | 313 | ||
309 | ret = cpufreq_register_driver(&p4clockmod_driver); | 314 | ret = cpufreq_register_driver(&p4clockmod_driver); |
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index b3379d6a5c57..54dd031394f6 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/timex.h> | 16 | #include <linux/timex.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | 18 | ||
19 | #include <asm/cpu_device_id.h> | ||
19 | #include <asm/msr.h> | 20 | #include <asm/msr.h> |
20 | 21 | ||
21 | #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long | 22 | #define POWERNOW_IOPORT 0xfff0 /* it doesn't matter where, as long |
@@ -210,6 +211,12 @@ static struct cpufreq_driver powernow_k6_driver = { | |||
210 | .attr = powernow_k6_attr, | 211 | .attr = powernow_k6_attr, |
211 | }; | 212 | }; |
212 | 213 | ||
214 | static const struct x86_cpu_id powernow_k6_ids[] = { | ||
215 | { X86_VENDOR_AMD, 5, 12 }, | ||
216 | { X86_VENDOR_AMD, 5, 13 }, | ||
217 | {} | ||
218 | }; | ||
219 | |||
213 | 220 | ||
214 | /** | 221 | /** |
215 | * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver | 222 | * powernow_k6_init - initializes the k6 PowerNow! CPUFreq driver |
@@ -220,10 +227,7 @@ static struct cpufreq_driver powernow_k6_driver = { | |||
220 | */ | 227 | */ |
221 | static int __init powernow_k6_init(void) | 228 | static int __init powernow_k6_init(void) |
222 | { | 229 | { |
223 | struct cpuinfo_x86 *c = &cpu_data(0); | 230 | if (!x86_match_cpu(powernow_k6_ids)) |
224 | |||
225 | if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 5) || | ||
226 | ((c->x86_model != 12) && (c->x86_model != 13))) | ||
227 | return -ENODEV; | 231 | return -ENODEV; |
228 | 232 | ||
229 | if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { | 233 | if (!request_region(POWERNOW_IOPORT, 16, "PowerNow!")) { |
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index d71d9f372359..501d167368d2 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */ | 28 | #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */ |
29 | #include <asm/msr.h> | 29 | #include <asm/msr.h> |
30 | #include <asm/system.h> | 30 | #include <asm/system.h> |
31 | #include <asm/cpu_device_id.h> | ||
31 | 32 | ||
32 | #ifdef CONFIG_X86_POWERNOW_K7_ACPI | 33 | #ifdef CONFIG_X86_POWERNOW_K7_ACPI |
33 | #include <linux/acpi.h> | 34 | #include <linux/acpi.h> |
@@ -110,18 +111,19 @@ static int check_fsb(unsigned int fsbspeed) | |||
110 | return delta < 5; | 111 | return delta < 5; |
111 | } | 112 | } |
112 | 113 | ||
114 | static const struct x86_cpu_id powernow_k7_cpuids[] = { | ||
115 | { X86_VENDOR_AMD, 7, }, | ||
116 | {} | ||
117 | }; | ||
118 | MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids); | ||
119 | |||
113 | static int check_powernow(void) | 120 | static int check_powernow(void) |
114 | { | 121 | { |
115 | struct cpuinfo_x86 *c = &cpu_data(0); | 122 | struct cpuinfo_x86 *c = &cpu_data(0); |
116 | unsigned int maxei, eax, ebx, ecx, edx; | 123 | unsigned int maxei, eax, ebx, ecx, edx; |
117 | 124 | ||
118 | if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 != 6)) { | 125 | if (!x86_match_cpu(powernow_k7_cpuids)) |
119 | #ifdef MODULE | ||
120 | printk(KERN_INFO PFX "This module only works with " | ||
121 | "AMD K7 CPUs\n"); | ||
122 | #endif | ||
123 | return 0; | 126 | return 0; |
124 | } | ||
125 | 127 | ||
126 | /* Get maximum capabilities */ | 128 | /* Get maximum capabilities */ |
127 | maxei = cpuid_eax(0x80000000); | 129 | maxei = cpuid_eax(0x80000000); |
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 8f9b2ceeec85..c0e816468e30 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/delay.h> | 40 | #include <linux/delay.h> |
41 | 41 | ||
42 | #include <asm/msr.h> | 42 | #include <asm/msr.h> |
43 | #include <asm/cpu_device_id.h> | ||
43 | 44 | ||
44 | #include <linux/acpi.h> | 45 | #include <linux/acpi.h> |
45 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
@@ -520,6 +521,15 @@ static int core_voltage_post_transition(struct powernow_k8_data *data, | |||
520 | return 0; | 521 | return 0; |
521 | } | 522 | } |
522 | 523 | ||
524 | static const struct x86_cpu_id powernow_k8_ids[] = { | ||
525 | /* IO based frequency switching */ | ||
526 | { X86_VENDOR_AMD, 0xf }, | ||
527 | /* MSR based frequency switching supported */ | ||
528 | X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), | ||
529 | {} | ||
530 | }; | ||
531 | MODULE_DEVICE_TABLE(x86cpu, powernow_k8_ids); | ||
532 | |||
523 | static void check_supported_cpu(void *_rc) | 533 | static void check_supported_cpu(void *_rc) |
524 | { | 534 | { |
525 | u32 eax, ebx, ecx, edx; | 535 | u32 eax, ebx, ecx, edx; |
@@ -527,13 +537,7 @@ static void check_supported_cpu(void *_rc) | |||
527 | 537 | ||
528 | *rc = -ENODEV; | 538 | *rc = -ENODEV; |
529 | 539 | ||
530 | if (__this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_AMD) | ||
531 | return; | ||
532 | |||
533 | eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); | 540 | eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); |
534 | if (((eax & CPUID_XFAM) != CPUID_XFAM_K8) && | ||
535 | ((eax & CPUID_XFAM) < CPUID_XFAM_10H)) | ||
536 | return; | ||
537 | 541 | ||
538 | if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { | 542 | if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { |
539 | if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || | 543 | if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || |
@@ -1553,6 +1557,9 @@ static int __cpuinit powernowk8_init(void) | |||
1553 | unsigned int i, supported_cpus = 0, cpu; | 1557 | unsigned int i, supported_cpus = 0, cpu; |
1554 | int rv; | 1558 | int rv; |
1555 | 1559 | ||
1560 | if (!x86_match_cpu(powernow_k8_ids)) | ||
1561 | return -ENODEV; | ||
1562 | |||
1556 | for_each_online_cpu(i) { | 1563 | for_each_online_cpu(i) { |
1557 | int rc; | 1564 | int rc; |
1558 | smp_call_function_single(i, check_supported_cpu, &rc, 1); | 1565 | smp_call_function_single(i, check_supported_cpu, &rc, 1); |
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 1e205e6b1727..e42e073cd9b8 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/timex.h> | 22 | #include <linux/timex.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | 24 | ||
25 | #include <asm/cpu_device_id.h> | ||
25 | #include <asm/msr.h> | 26 | #include <asm/msr.h> |
26 | 27 | ||
27 | #define MMCR_BASE 0xfffef000 /* The default base address */ | 28 | #define MMCR_BASE 0xfffef000 /* The default base address */ |
@@ -150,18 +151,19 @@ static struct cpufreq_driver sc520_freq_driver = { | |||
150 | .attr = sc520_freq_attr, | 151 | .attr = sc520_freq_attr, |
151 | }; | 152 | }; |
152 | 153 | ||
154 | static const struct x86_cpu_id sc520_ids[] = { | ||
155 | { X86_VENDOR_AMD, 4, 9 }, | ||
156 | {} | ||
157 | }; | ||
158 | MODULE_DEVICE_TABLE(x86cpu, sc520_ids); | ||
153 | 159 | ||
154 | static int __init sc520_freq_init(void) | 160 | static int __init sc520_freq_init(void) |
155 | { | 161 | { |
156 | struct cpuinfo_x86 *c = &cpu_data(0); | ||
157 | int err; | 162 | int err; |
158 | 163 | ||
159 | /* Test if we have the right hardware */ | 164 | if (!x86_match_cpu(sc520_ids)) |
160 | if (c->x86_vendor != X86_VENDOR_AMD || | ||
161 | c->x86 != 4 || c->x86_model != 9) { | ||
162 | pr_debug("no Elan SC520 processor found!\n"); | ||
163 | return -ENODEV; | 165 | return -ENODEV; |
164 | } | 166 | |
165 | cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); | 167 | cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1); |
166 | if (!cpuctl) { | 168 | if (!cpuctl) { |
167 | printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); | 169 | printk(KERN_ERR "sc520_freq: error: failed to remap memory\n"); |
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 6ea3455def21..3a953d519f46 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/msr.h> | 25 | #include <asm/msr.h> |
26 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
27 | #include <asm/cpufeature.h> | 27 | #include <asm/cpufeature.h> |
28 | #include <asm/cpu_device_id.h> | ||
28 | 29 | ||
29 | #define PFX "speedstep-centrino: " | 30 | #define PFX "speedstep-centrino: " |
30 | #define MAINTAINER "cpufreq@vger.kernel.org" | 31 | #define MAINTAINER "cpufreq@vger.kernel.org" |
@@ -595,6 +596,24 @@ static struct cpufreq_driver centrino_driver = { | |||
595 | .owner = THIS_MODULE, | 596 | .owner = THIS_MODULE, |
596 | }; | 597 | }; |
597 | 598 | ||
599 | /* | ||
600 | * This doesn't replace the detailed checks above because | ||
601 | * the generic CPU IDs don't have a way to match for steppings | ||
602 | * or ASCII model IDs. | ||
603 | */ | ||
604 | static const struct x86_cpu_id centrino_ids[] = { | ||
605 | { X86_VENDOR_INTEL, 6, 9, X86_FEATURE_EST }, | ||
606 | { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, | ||
607 | { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, | ||
608 | { X86_VENDOR_INTEL, 6, 13, X86_FEATURE_EST }, | ||
609 | { X86_VENDOR_INTEL, 15, 3, X86_FEATURE_EST }, | ||
610 | { X86_VENDOR_INTEL, 15, 4, X86_FEATURE_EST }, | ||
611 | {} | ||
612 | }; | ||
613 | #if 0 | ||
614 | /* Autoload or not? Do not for now. */ | ||
615 | MODULE_DEVICE_TABLE(x86cpu, centrino_ids); | ||
616 | #endif | ||
598 | 617 | ||
599 | /** | 618 | /** |
600 | * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver | 619 | * centrino_init - initializes the Enhanced SpeedStep CPUFreq driver |
@@ -612,11 +631,8 @@ static struct cpufreq_driver centrino_driver = { | |||
612 | */ | 631 | */ |
613 | static int __init centrino_init(void) | 632 | static int __init centrino_init(void) |
614 | { | 633 | { |
615 | struct cpuinfo_x86 *cpu = &cpu_data(0); | 634 | if (!x86_match_cpu(centrino_ids)) |
616 | |||
617 | if (!cpu_has(cpu, X86_FEATURE_EST)) | ||
618 | return -ENODEV; | 635 | return -ENODEV; |
619 | |||
620 | return cpufreq_register_driver(¢rino_driver); | 636 | return cpufreq_register_driver(¢rino_driver); |
621 | } | 637 | } |
622 | 638 | ||
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index a748ce782fee..7432b3a72cd4 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/pci.h> | 25 | #include <linux/pci.h> |
26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
27 | 27 | ||
28 | #include <asm/cpu_device_id.h> | ||
29 | |||
28 | #include "speedstep-lib.h" | 30 | #include "speedstep-lib.h" |
29 | 31 | ||
30 | 32 | ||
@@ -388,6 +390,16 @@ static struct cpufreq_driver speedstep_driver = { | |||
388 | .attr = speedstep_attr, | 390 | .attr = speedstep_attr, |
389 | }; | 391 | }; |
390 | 392 | ||
393 | static const struct x86_cpu_id ss_smi_ids[] = { | ||
394 | { X86_VENDOR_INTEL, 6, 0xb, }, | ||
395 | { X86_VENDOR_INTEL, 6, 0x8, }, | ||
396 | { X86_VENDOR_INTEL, 15, 2 }, | ||
397 | {} | ||
398 | }; | ||
399 | #if 0 | ||
400 | /* Autoload or not? Do not for now. */ | ||
401 | MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); | ||
402 | #endif | ||
391 | 403 | ||
392 | /** | 404 | /** |
393 | * speedstep_init - initializes the SpeedStep CPUFreq driver | 405 | * speedstep_init - initializes the SpeedStep CPUFreq driver |
@@ -398,6 +410,9 @@ static struct cpufreq_driver speedstep_driver = { | |||
398 | */ | 410 | */ |
399 | static int __init speedstep_init(void) | 411 | static int __init speedstep_init(void) |
400 | { | 412 | { |
413 | if (!x86_match_cpu(ss_smi_ids)) | ||
414 | return -ENODEV; | ||
415 | |||
401 | /* detect processor */ | 416 | /* detect processor */ |
402 | speedstep_processor = speedstep_detect_processor(); | 417 | speedstep_processor = speedstep_detect_processor(); |
403 | if (!speedstep_processor) { | 418 | if (!speedstep_processor) { |
diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index 8af2d2fd9d51..7047821a7f8a 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c | |||
@@ -249,6 +249,7 @@ EXPORT_SYMBOL_GPL(speedstep_get_frequency); | |||
249 | * DETECT SPEEDSTEP-CAPABLE PROCESSOR * | 249 | * DETECT SPEEDSTEP-CAPABLE PROCESSOR * |
250 | *********************************************************************/ | 250 | *********************************************************************/ |
251 | 251 | ||
252 | /* Keep in sync with the x86_cpu_id tables in the different modules */ | ||
252 | unsigned int speedstep_detect_processor(void) | 253 | unsigned int speedstep_detect_processor(void) |
253 | { | 254 | { |
254 | struct cpuinfo_x86 *c = &cpu_data(0); | 255 | struct cpuinfo_x86 *c = &cpu_data(0); |
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index c76ead3490bf..6a457fcaaad5 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <asm/ist.h> | 22 | #include <asm/ist.h> |
23 | #include <asm/cpu_device_id.h> | ||
23 | 24 | ||
24 | #include "speedstep-lib.h" | 25 | #include "speedstep-lib.h" |
25 | 26 | ||
@@ -379,6 +380,17 @@ static struct cpufreq_driver speedstep_driver = { | |||
379 | .attr = speedstep_attr, | 380 | .attr = speedstep_attr, |
380 | }; | 381 | }; |
381 | 382 | ||
383 | static const struct x86_cpu_id ss_smi_ids[] = { | ||
384 | { X86_VENDOR_INTEL, 6, 0xb, }, | ||
385 | { X86_VENDOR_INTEL, 6, 0x8, }, | ||
386 | { X86_VENDOR_INTEL, 15, 2 }, | ||
387 | {} | ||
388 | }; | ||
389 | #if 0 | ||
390 | /* Not auto loaded currently */ | ||
391 | MODULE_DEVICE_TABLE(x86cpu, ss_smi_ids); | ||
392 | #endif | ||
393 | |||
382 | /** | 394 | /** |
383 | * speedstep_init - initializes the SpeedStep CPUFreq driver | 395 | * speedstep_init - initializes the SpeedStep CPUFreq driver |
384 | * | 396 | * |
@@ -388,6 +400,9 @@ static struct cpufreq_driver speedstep_driver = { | |||
388 | */ | 400 | */ |
389 | static int __init speedstep_init(void) | 401 | static int __init speedstep_init(void) |
390 | { | 402 | { |
403 | if (!x86_match_cpu(ss_smi_ids)) | ||
404 | return -ENODEV; | ||
405 | |||
391 | speedstep_processor = speedstep_detect_processor(); | 406 | speedstep_processor = speedstep_detect_processor(); |
392 | 407 | ||
393 | switch (speedstep_processor) { | 408 | switch (speedstep_processor) { |
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index 29b9469f8378..37b2e9406af6 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/percpu.h> | 19 | #include <linux/percpu.h> |
20 | #include <linux/smp.h> | 20 | #include <linux/smp.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <asm/cpu_device_id.h> | ||
22 | #include <asm/byteorder.h> | 23 | #include <asm/byteorder.h> |
23 | #include <asm/processor.h> | 24 | #include <asm/processor.h> |
24 | #include <asm/i387.h> | 25 | #include <asm/i387.h> |
@@ -503,12 +504,18 @@ static struct crypto_alg cbc_aes_alg = { | |||
503 | } | 504 | } |
504 | }; | 505 | }; |
505 | 506 | ||
507 | static struct x86_cpu_id padlock_cpu_id[] = { | ||
508 | X86_FEATURE_MATCH(X86_FEATURE_XCRYPT), | ||
509 | {} | ||
510 | }; | ||
511 | MODULE_DEVICE_TABLE(x86cpu, padlock_cpu_id); | ||
512 | |||
506 | static int __init padlock_init(void) | 513 | static int __init padlock_init(void) |
507 | { | 514 | { |
508 | int ret; | 515 | int ret; |
509 | struct cpuinfo_x86 *c = &cpu_data(0); | 516 | struct cpuinfo_x86 *c = &cpu_data(0); |
510 | 517 | ||
511 | if (!cpu_has_xcrypt) | 518 | if (!x86_match_cpu(padlock_cpu_id)) |
512 | return -ENODEV; | 519 | return -ENODEV; |
513 | 520 | ||
514 | if (!cpu_has_xcrypt_enabled) { | 521 | if (!cpu_has_xcrypt_enabled) { |
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c index 06bdb4b2c6a6..9266c0e25492 100644 --- a/drivers/crypto/padlock-sha.c +++ b/drivers/crypto/padlock-sha.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/scatterlist.h> | 24 | #include <linux/scatterlist.h> |
25 | #include <asm/cpu_device_id.h> | ||
25 | #include <asm/i387.h> | 26 | #include <asm/i387.h> |
26 | 27 | ||
27 | struct padlock_sha_desc { | 28 | struct padlock_sha_desc { |
@@ -526,6 +527,12 @@ static struct shash_alg sha256_alg_nano = { | |||
526 | } | 527 | } |
527 | }; | 528 | }; |
528 | 529 | ||
530 | static struct x86_cpu_id padlock_sha_ids[] = { | ||
531 | X86_FEATURE_MATCH(X86_FEATURE_PHE), | ||
532 | {} | ||
533 | }; | ||
534 | MODULE_DEVICE_TABLE(x86cpu, padlock_sha_ids); | ||
535 | |||
529 | static int __init padlock_init(void) | 536 | static int __init padlock_init(void) |
530 | { | 537 | { |
531 | int rc = -ENODEV; | 538 | int rc = -ENODEV; |
@@ -533,15 +540,8 @@ static int __init padlock_init(void) | |||
533 | struct shash_alg *sha1; | 540 | struct shash_alg *sha1; |
534 | struct shash_alg *sha256; | 541 | struct shash_alg *sha256; |
535 | 542 | ||
536 | if (!cpu_has_phe) { | 543 | if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled) |
537 | printk(KERN_NOTICE PFX "VIA PadLock Hash Engine not detected.\n"); | ||
538 | return -ENODEV; | ||
539 | } | ||
540 | |||
541 | if (!cpu_has_phe_enabled) { | ||
542 | printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n"); | ||
543 | return -ENODEV; | 544 | return -ENODEV; |
544 | } | ||
545 | 545 | ||
546 | /* Register the newly added algorithm module if on * | 546 | /* Register the newly added algorithm module if on * |
547 | * VIA Nano processor, or else just do as before */ | 547 | * VIA Nano processor, or else just do as before */ |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index af08ce7207d9..bce53fa0e166 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1619,11 +1619,7 @@ static ssize_t store_new_id(struct device_driver *drv, const char *buf, | |||
1619 | list_add_tail(&dynid->list, &hdrv->dyn_list); | 1619 | list_add_tail(&dynid->list, &hdrv->dyn_list); |
1620 | spin_unlock(&hdrv->dyn_lock); | 1620 | spin_unlock(&hdrv->dyn_lock); |
1621 | 1621 | ||
1622 | ret = 0; | 1622 | ret = driver_attach(&hdrv->driver); |
1623 | if (get_driver(&hdrv->driver)) { | ||
1624 | ret = driver_attach(&hdrv->driver); | ||
1625 | put_driver(&hdrv->driver); | ||
1626 | } | ||
1627 | 1623 | ||
1628 | return ret ? : count; | 1624 | return ret ? : count; |
1629 | } | 1625 | } |
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 36484db36baf..9ffbfc575a0c 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c | |||
@@ -37,81 +37,6 @@ struct vmbus_channel_message_table_entry { | |||
37 | void (*message_handler)(struct vmbus_channel_message_header *msg); | 37 | void (*message_handler)(struct vmbus_channel_message_header *msg); |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #define MAX_MSG_TYPES 4 | ||
41 | #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 | ||
42 | |||
43 | static const uuid_le | ||
44 | supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { | ||
45 | /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ | ||
46 | /* Storage - SCSI */ | ||
47 | { | ||
48 | .b = { | ||
49 | 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, | ||
50 | 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f | ||
51 | } | ||
52 | }, | ||
53 | |||
54 | /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ | ||
55 | /* Network */ | ||
56 | { | ||
57 | .b = { | ||
58 | 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, | ||
59 | 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E | ||
60 | } | ||
61 | }, | ||
62 | |||
63 | /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ | ||
64 | /* Input */ | ||
65 | { | ||
66 | .b = { | ||
67 | 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, | ||
68 | 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A | ||
69 | } | ||
70 | }, | ||
71 | |||
72 | /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ | ||
73 | /* IDE */ | ||
74 | { | ||
75 | .b = { | ||
76 | 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, | ||
77 | 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 | ||
78 | } | ||
79 | }, | ||
80 | /* 0E0B6031-5213-4934-818B-38D90CED39DB */ | ||
81 | /* Shutdown */ | ||
82 | { | ||
83 | .b = { | ||
84 | 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, | ||
85 | 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB | ||
86 | } | ||
87 | }, | ||
88 | /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ | ||
89 | /* TimeSync */ | ||
90 | { | ||
91 | .b = { | ||
92 | 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, | ||
93 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf | ||
94 | } | ||
95 | }, | ||
96 | /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ | ||
97 | /* Heartbeat */ | ||
98 | { | ||
99 | .b = { | ||
100 | 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, | ||
101 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d | ||
102 | } | ||
103 | }, | ||
104 | /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ | ||
105 | /* KVP */ | ||
106 | { | ||
107 | .b = { | ||
108 | 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, | ||
109 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 | ||
110 | } | ||
111 | }, | ||
112 | |||
113 | }; | ||
114 | |||
115 | 40 | ||
116 | /** | 41 | /** |
117 | * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message | 42 | * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message |
@@ -321,20 +246,8 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) | |||
321 | struct vmbus_channel *newchannel; | 246 | struct vmbus_channel *newchannel; |
322 | uuid_le *guidtype; | 247 | uuid_le *guidtype; |
323 | uuid_le *guidinstance; | 248 | uuid_le *guidinstance; |
324 | int i; | ||
325 | int fsupported = 0; | ||
326 | 249 | ||
327 | offer = (struct vmbus_channel_offer_channel *)hdr; | 250 | offer = (struct vmbus_channel_offer_channel *)hdr; |
328 | for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { | ||
329 | if (!uuid_le_cmp(offer->offer.if_type, | ||
330 | supported_device_classes[i])) { | ||
331 | fsupported = 1; | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | if (!fsupported) | ||
337 | return; | ||
338 | 251 | ||
339 | guidtype = &offer->offer.if_type; | 252 | guidtype = &offer->offer.if_type; |
340 | guidinstance = &offer->offer.if_instance; | 253 | guidinstance = &offer->offer.if_instance; |
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c index 12aa97f31f93..15956bd48b48 100644 --- a/drivers/hv/hv.c +++ b/drivers/hv/hv.c | |||
@@ -155,9 +155,9 @@ int hv_init(void) | |||
155 | union hv_x64_msr_hypercall_contents hypercall_msr; | 155 | union hv_x64_msr_hypercall_contents hypercall_msr; |
156 | void *virtaddr = NULL; | 156 | void *virtaddr = NULL; |
157 | 157 | ||
158 | memset(hv_context.synic_event_page, 0, sizeof(void *) * MAX_NUM_CPUS); | 158 | memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS); |
159 | memset(hv_context.synic_message_page, 0, | 159 | memset(hv_context.synic_message_page, 0, |
160 | sizeof(void *) * MAX_NUM_CPUS); | 160 | sizeof(void *) * NR_CPUS); |
161 | 161 | ||
162 | if (!query_hypervisor_presence()) | 162 | if (!query_hypervisor_presence()) |
163 | goto cleanup; | 163 | goto cleanup; |
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index 0e8343f585bb..0ef4c1f6ca54 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c | |||
@@ -28,8 +28,6 @@ | |||
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | #include "hv_kvp.h" | ||
32 | |||
33 | 31 | ||
34 | 32 | ||
35 | /* | 33 | /* |
@@ -73,15 +71,20 @@ kvp_register(void) | |||
73 | { | 71 | { |
74 | 72 | ||
75 | struct cn_msg *msg; | 73 | struct cn_msg *msg; |
74 | struct hv_kvp_msg *kvp_msg; | ||
75 | char *version; | ||
76 | 76 | ||
77 | msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC); | 77 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg), GFP_ATOMIC); |
78 | 78 | ||
79 | if (msg) { | 79 | if (msg) { |
80 | kvp_msg = (struct hv_kvp_msg *)msg->data; | ||
81 | version = kvp_msg->body.kvp_version; | ||
80 | msg->id.idx = CN_KVP_IDX; | 82 | msg->id.idx = CN_KVP_IDX; |
81 | msg->id.val = CN_KVP_VAL; | 83 | msg->id.val = CN_KVP_VAL; |
82 | msg->seq = KVP_REGISTER; | 84 | |
83 | strcpy(msg->data, HV_DRV_VERSION); | 85 | kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER; |
84 | msg->len = strlen(HV_DRV_VERSION) + 1; | 86 | strcpy(version, HV_DRV_VERSION); |
87 | msg->len = sizeof(struct hv_kvp_msg); | ||
85 | cn_netlink_send(msg, 0, GFP_ATOMIC); | 88 | cn_netlink_send(msg, 0, GFP_ATOMIC); |
86 | kfree(msg); | 89 | kfree(msg); |
87 | } | 90 | } |
@@ -103,23 +106,24 @@ kvp_work_func(struct work_struct *dummy) | |||
103 | static void | 106 | static void |
104 | kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) | 107 | kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) |
105 | { | 108 | { |
106 | struct hv_ku_msg *message; | 109 | struct hv_kvp_msg *message; |
110 | struct hv_kvp_msg_enumerate *data; | ||
107 | 111 | ||
108 | message = (struct hv_ku_msg *)msg->data; | 112 | message = (struct hv_kvp_msg *)msg->data; |
109 | if (msg->seq == KVP_REGISTER) { | 113 | if (message->kvp_hdr.operation == KVP_OP_REGISTER) { |
110 | pr_info("KVP: user-mode registering done.\n"); | 114 | pr_info("KVP: user-mode registering done.\n"); |
111 | kvp_register(); | 115 | kvp_register(); |
112 | } | 116 | } |
113 | 117 | ||
114 | if (msg->seq == KVP_USER_SET) { | 118 | if (message->kvp_hdr.operation == KVP_OP_ENUMERATE) { |
119 | data = &message->body.kvp_enum_data; | ||
115 | /* | 120 | /* |
116 | * Complete the transaction by forwarding the key value | 121 | * Complete the transaction by forwarding the key value |
117 | * to the host. But first, cancel the timeout. | 122 | * to the host. But first, cancel the timeout. |
118 | */ | 123 | */ |
119 | if (cancel_delayed_work_sync(&kvp_work)) | 124 | if (cancel_delayed_work_sync(&kvp_work)) |
120 | kvp_respond_to_host(message->kvp_key, | 125 | kvp_respond_to_host(data->data.key, data->data.value, |
121 | message->kvp_value, | 126 | !strlen(data->data.key)); |
122 | !strlen(message->kvp_key)); | ||
123 | } | 127 | } |
124 | } | 128 | } |
125 | 129 | ||
@@ -127,6 +131,7 @@ static void | |||
127 | kvp_send_key(struct work_struct *dummy) | 131 | kvp_send_key(struct work_struct *dummy) |
128 | { | 132 | { |
129 | struct cn_msg *msg; | 133 | struct cn_msg *msg; |
134 | struct hv_kvp_msg *message; | ||
130 | int index = kvp_transaction.index; | 135 | int index = kvp_transaction.index; |
131 | 136 | ||
132 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); | 137 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); |
@@ -134,9 +139,11 @@ kvp_send_key(struct work_struct *dummy) | |||
134 | if (msg) { | 139 | if (msg) { |
135 | msg->id.idx = CN_KVP_IDX; | 140 | msg->id.idx = CN_KVP_IDX; |
136 | msg->id.val = CN_KVP_VAL; | 141 | msg->id.val = CN_KVP_VAL; |
137 | msg->seq = KVP_KERNEL_GET; | 142 | |
138 | ((struct hv_ku_msg *)msg->data)->kvp_index = index; | 143 | message = (struct hv_kvp_msg *)msg->data; |
139 | msg->len = sizeof(struct hv_ku_msg); | 144 | message->kvp_hdr.operation = KVP_OP_ENUMERATE; |
145 | message->body.kvp_enum_data.index = index; | ||
146 | msg->len = sizeof(struct hv_kvp_msg); | ||
140 | cn_netlink_send(msg, 0, GFP_ATOMIC); | 147 | cn_netlink_send(msg, 0, GFP_ATOMIC); |
141 | kfree(msg); | 148 | kfree(msg); |
142 | } | 149 | } |
@@ -193,7 +200,7 @@ kvp_respond_to_host(char *key, char *value, int error) | |||
193 | kvp_msg = (struct hv_kvp_msg *) | 200 | kvp_msg = (struct hv_kvp_msg *) |
194 | &recv_buffer[sizeof(struct vmbuspipe_hdr) + | 201 | &recv_buffer[sizeof(struct vmbuspipe_hdr) + |
195 | sizeof(struct icmsg_hdr)]; | 202 | sizeof(struct icmsg_hdr)]; |
196 | kvp_data = &kvp_msg->kvp_data; | 203 | kvp_data = &kvp_msg->body.kvp_enum_data; |
197 | key_name = key; | 204 | key_name = key; |
198 | 205 | ||
199 | /* | 206 | /* |
@@ -268,7 +275,7 @@ void hv_kvp_onchannelcallback(void *context) | |||
268 | sizeof(struct vmbuspipe_hdr) + | 275 | sizeof(struct vmbuspipe_hdr) + |
269 | sizeof(struct icmsg_hdr)]; | 276 | sizeof(struct icmsg_hdr)]; |
270 | 277 | ||
271 | kvp_data = &kvp_msg->kvp_data; | 278 | kvp_data = &kvp_msg->body.kvp_enum_data; |
272 | 279 | ||
273 | /* | 280 | /* |
274 | * We only support the "get" operation on | 281 | * We only support the "get" operation on |
diff --git a/drivers/hv/hv_kvp.h b/drivers/hv/hv_kvp.h deleted file mode 100644 index 9b765d7df838..000000000000 --- a/drivers/hv/hv_kvp.h +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | /* | ||
2 | * An implementation of HyperV key value pair (KVP) functionality for Linux. | ||
3 | * | ||
4 | * | ||
5 | * Copyright (C) 2010, Novell, Inc. | ||
6 | * Author : K. Y. Srinivasan <ksrinivasan@novell.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License version 2 as published | ||
10 | * by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
15 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
16 | * details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | ||
21 | * | ||
22 | */ | ||
23 | #ifndef _KVP_H | ||
24 | #define _KVP_H_ | ||
25 | |||
26 | /* | ||
27 | * Maximum value size - used for both key names and value data, and includes | ||
28 | * any applicable NULL terminators. | ||
29 | * | ||
30 | * Note: This limit is somewhat arbitrary, but falls easily within what is | ||
31 | * supported for all native guests (back to Win 2000) and what is reasonable | ||
32 | * for the IC KVP exchange functionality. Note that Windows Me/98/95 are | ||
33 | * limited to 255 character key names. | ||
34 | * | ||
35 | * MSDN recommends not storing data values larger than 2048 bytes in the | ||
36 | * registry. | ||
37 | * | ||
38 | * Note: This value is used in defining the KVP exchange message - this value | ||
39 | * cannot be modified without affecting the message size and compatibility. | ||
40 | */ | ||
41 | |||
42 | /* | ||
43 | * bytes, including any null terminators | ||
44 | */ | ||
45 | #define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) | ||
46 | |||
47 | |||
48 | /* | ||
49 | * Maximum key size - the registry limit for the length of an entry name | ||
50 | * is 256 characters, including the null terminator | ||
51 | */ | ||
52 | |||
53 | #define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) | ||
54 | |||
55 | /* | ||
56 | * In Linux, we implement the KVP functionality in two components: | ||
57 | * 1) The kernel component which is packaged as part of the hv_utils driver | ||
58 | * is responsible for communicating with the host and responsible for | ||
59 | * implementing the host/guest protocol. 2) A user level daemon that is | ||
60 | * responsible for data gathering. | ||
61 | * | ||
62 | * Host/Guest Protocol: The host iterates over an index and expects the guest | ||
63 | * to assign a key name to the index and also return the value corresponding to | ||
64 | * the key. The host will have atmost one KVP transaction outstanding at any | ||
65 | * given point in time. The host side iteration stops when the guest returns | ||
66 | * an error. Microsoft has specified the following mapping of key names to | ||
67 | * host specified index: | ||
68 | * | ||
69 | * Index Key Name | ||
70 | * 0 FullyQualifiedDomainName | ||
71 | * 1 IntegrationServicesVersion | ||
72 | * 2 NetworkAddressIPv4 | ||
73 | * 3 NetworkAddressIPv6 | ||
74 | * 4 OSBuildNumber | ||
75 | * 5 OSName | ||
76 | * 6 OSMajorVersion | ||
77 | * 7 OSMinorVersion | ||
78 | * 8 OSVersion | ||
79 | * 9 ProcessorArchitecture | ||
80 | * | ||
81 | * The Windows host expects the Key Name and Key Value to be encoded in utf16. | ||
82 | * | ||
83 | * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the | ||
84 | * data gathering functionality in a user mode daemon. The user level daemon | ||
85 | * is also responsible for binding the key name to the index as well. The | ||
86 | * kernel and user-level daemon communicate using a connector channel. | ||
87 | * | ||
88 | * The user mode component first registers with the | ||
89 | * the kernel component. Subsequently, the kernel component requests, data | ||
90 | * for the specified keys. In response to this message the user mode component | ||
91 | * fills in the value corresponding to the specified key. We overload the | ||
92 | * sequence field in the cn_msg header to define our KVP message types. | ||
93 | * | ||
94 | * | ||
95 | * The kernel component simply acts as a conduit for communication between the | ||
96 | * Windows host and the user-level daemon. The kernel component passes up the | ||
97 | * index received from the Host to the user-level daemon. If the index is | ||
98 | * valid (supported), the corresponding key as well as its | ||
99 | * value (both are strings) is returned. If the index is invalid | ||
100 | * (not supported), a NULL key string is returned. | ||
101 | */ | ||
102 | |||
103 | /* | ||
104 | * | ||
105 | * The following definitions are shared with the user-mode component; do not | ||
106 | * change any of this without making the corresponding changes in | ||
107 | * the KVP user-mode component. | ||
108 | */ | ||
109 | |||
110 | #define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ | ||
111 | #define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ | ||
112 | |||
113 | enum hv_ku_op { | ||
114 | KVP_REGISTER = 0, /* Register the user mode component */ | ||
115 | KVP_KERNEL_GET, /* Kernel is requesting the value */ | ||
116 | KVP_KERNEL_SET, /* Kernel is providing the value */ | ||
117 | KVP_USER_GET, /* User is requesting the value */ | ||
118 | KVP_USER_SET /* User is providing the value */ | ||
119 | }; | ||
120 | |||
121 | struct hv_ku_msg { | ||
122 | __u32 kvp_index; /* Key index */ | ||
123 | __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ | ||
124 | __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ | ||
125 | }; | ||
126 | |||
127 | |||
128 | |||
129 | |||
130 | #ifdef __KERNEL__ | ||
131 | |||
132 | /* | ||
133 | * Registry value types. | ||
134 | */ | ||
135 | |||
136 | #define REG_SZ 1 | ||
137 | |||
138 | enum hv_kvp_exchg_op { | ||
139 | KVP_OP_GET = 0, | ||
140 | KVP_OP_SET, | ||
141 | KVP_OP_DELETE, | ||
142 | KVP_OP_ENUMERATE, | ||
143 | KVP_OP_COUNT /* Number of operations, must be last. */ | ||
144 | }; | ||
145 | |||
146 | enum hv_kvp_exchg_pool { | ||
147 | KVP_POOL_EXTERNAL = 0, | ||
148 | KVP_POOL_GUEST, | ||
149 | KVP_POOL_AUTO, | ||
150 | KVP_POOL_AUTO_EXTERNAL, | ||
151 | KVP_POOL_AUTO_INTERNAL, | ||
152 | KVP_POOL_COUNT /* Number of pools, must be last. */ | ||
153 | }; | ||
154 | |||
155 | struct hv_kvp_hdr { | ||
156 | u8 operation; | ||
157 | u8 pool; | ||
158 | }; | ||
159 | |||
160 | struct hv_kvp_exchg_msg_value { | ||
161 | u32 value_type; | ||
162 | u32 key_size; | ||
163 | u32 value_size; | ||
164 | u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; | ||
165 | u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; | ||
166 | }; | ||
167 | |||
168 | struct hv_kvp_msg_enumerate { | ||
169 | u32 index; | ||
170 | struct hv_kvp_exchg_msg_value data; | ||
171 | }; | ||
172 | |||
173 | struct hv_kvp_msg { | ||
174 | struct hv_kvp_hdr kvp_hdr; | ||
175 | struct hv_kvp_msg_enumerate kvp_data; | ||
176 | }; | ||
177 | |||
178 | int hv_kvp_init(struct hv_util_service *); | ||
179 | void hv_kvp_deinit(void); | ||
180 | void hv_kvp_onchannelcallback(void *); | ||
181 | |||
182 | #endif /* __KERNEL__ */ | ||
183 | #endif /* _KVP_H */ | ||
184 | |||
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 55d58f21e6d4..dbb8b8eec210 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c | |||
@@ -28,9 +28,6 @@ | |||
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/hyperv.h> | 29 | #include <linux/hyperv.h> |
30 | 30 | ||
31 | #include "hv_kvp.h" | ||
32 | |||
33 | |||
34 | static void shutdown_onchannelcallback(void *context); | 31 | static void shutdown_onchannelcallback(void *context); |
35 | static struct hv_util_service util_shutdown = { | 32 | static struct hv_util_service util_shutdown = { |
36 | .util_cb = shutdown_onchannelcallback, | 33 | .util_cb = shutdown_onchannelcallback, |
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h index 6d7d286d5440..699f0d8e59ed 100644 --- a/drivers/hv/hyperv_vmbus.h +++ b/drivers/hv/hyperv_vmbus.h | |||
@@ -457,7 +457,6 @@ static const uuid_le VMBUS_SERVICE_ID = { | |||
457 | }, | 457 | }, |
458 | }; | 458 | }; |
459 | 459 | ||
460 | #define MAX_NUM_CPUS 32 | ||
461 | 460 | ||
462 | 461 | ||
463 | struct hv_input_signal_event_buffer { | 462 | struct hv_input_signal_event_buffer { |
@@ -483,8 +482,8 @@ struct hv_context { | |||
483 | /* 8-bytes aligned of the buffer above */ | 482 | /* 8-bytes aligned of the buffer above */ |
484 | struct hv_input_signal_event *signal_event_param; | 483 | struct hv_input_signal_event *signal_event_param; |
485 | 484 | ||
486 | void *synic_message_page[MAX_NUM_CPUS]; | 485 | void *synic_message_page[NR_CPUS]; |
487 | void *synic_event_page[MAX_NUM_CPUS]; | 486 | void *synic_event_page[NR_CPUS]; |
488 | }; | 487 | }; |
489 | 488 | ||
490 | extern struct hv_context hv_context; | 489 | extern struct hv_context hv_context; |
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index a6c6ec36615e..249ac460e3d9 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/moduleparam.h> | 39 | #include <linux/moduleparam.h> |
40 | #include <asm/msr.h> | 40 | #include <asm/msr.h> |
41 | #include <asm/processor.h> | 41 | #include <asm/processor.h> |
42 | #include <asm/cpu_device_id.h> | ||
42 | 43 | ||
43 | #define DRVNAME "coretemp" | 44 | #define DRVNAME "coretemp" |
44 | 45 | ||
@@ -759,13 +760,23 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { | |||
759 | .notifier_call = coretemp_cpu_callback, | 760 | .notifier_call = coretemp_cpu_callback, |
760 | }; | 761 | }; |
761 | 762 | ||
763 | static const struct x86_cpu_id coretemp_ids[] = { | ||
764 | { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTS }, | ||
765 | {} | ||
766 | }; | ||
767 | MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); | ||
768 | |||
762 | static int __init coretemp_init(void) | 769 | static int __init coretemp_init(void) |
763 | { | 770 | { |
764 | int i, err = -ENODEV; | 771 | int i, err = -ENODEV; |
765 | 772 | ||
766 | /* quick check if we run Intel */ | 773 | /* |
767 | if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL) | 774 | * CPUID.06H.EAX[0] indicates whether the CPU has thermal |
768 | goto exit; | 775 | * sensors. We check this bit only, all the early CPUs |
776 | * without thermal sensors will be filtered out. | ||
777 | */ | ||
778 | if (!x86_match_cpu(coretemp_ids)) | ||
779 | return -ENODEV; | ||
769 | 780 | ||
770 | err = platform_driver_register(&coretemp_driver); | 781 | err = platform_driver_register(&coretemp_driver); |
771 | if (err) | 782 | if (err) |
diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 8eac67d769fa..8689664ef03c 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/cpu.h> | 37 | #include <linux/cpu.h> |
38 | #include <asm/msr.h> | 38 | #include <asm/msr.h> |
39 | #include <asm/processor.h> | 39 | #include <asm/processor.h> |
40 | #include <asm/cpu_device_id.h> | ||
40 | 41 | ||
41 | #define DRVNAME "via_cputemp" | 42 | #define DRVNAME "via_cputemp" |
42 | 43 | ||
@@ -308,15 +309,20 @@ static struct notifier_block via_cputemp_cpu_notifier __refdata = { | |||
308 | .notifier_call = via_cputemp_cpu_callback, | 309 | .notifier_call = via_cputemp_cpu_callback, |
309 | }; | 310 | }; |
310 | 311 | ||
312 | static const struct x86_cpu_id cputemp_ids[] = { | ||
313 | { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */ | ||
314 | { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */ | ||
315 | { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */ | ||
316 | {} | ||
317 | }; | ||
318 | MODULE_DEVICE_TABLE(x86cpu, cputemp_ids); | ||
319 | |||
311 | static int __init via_cputemp_init(void) | 320 | static int __init via_cputemp_init(void) |
312 | { | 321 | { |
313 | int i, err; | 322 | int i, err; |
314 | 323 | ||
315 | if (cpu_data(0).x86_vendor != X86_VENDOR_CENTAUR) { | 324 | if (!x86_match_cpu(cputemp_ids)) |
316 | printk(KERN_DEBUG DRVNAME ": Not a VIA CPU\n"); | 325 | return -ENODEV; |
317 | err = -ENODEV; | ||
318 | goto exit; | ||
319 | } | ||
320 | 326 | ||
321 | err = platform_driver_register(&via_cputemp_driver); | 327 | err = platform_driver_register(&via_cputemp_driver); |
322 | if (err) | 328 | if (err) |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 54ab97bae042..237fe5785f01 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/notifier.h> | 62 | #include <linux/notifier.h> |
63 | #include <linux/cpu.h> | 63 | #include <linux/cpu.h> |
64 | #include <linux/module.h> | 64 | #include <linux/module.h> |
65 | #include <asm/cpu_device_id.h> | ||
65 | #include <asm/mwait.h> | 66 | #include <asm/mwait.h> |
66 | #include <asm/msr.h> | 67 | #include <asm/msr.h> |
67 | 68 | ||
@@ -81,6 +82,17 @@ static unsigned int mwait_substates; | |||
81 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ | 82 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ |
82 | static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ | 83 | static unsigned int lapic_timer_reliable_states = (1 << 1); /* Default to only C1 */ |
83 | 84 | ||
85 | struct idle_cpu { | ||
86 | struct cpuidle_state *state_table; | ||
87 | |||
88 | /* | ||
89 | * Hardware C-state auto-demotion may not always be optimal. | ||
90 | * Indicate which enable bits to clear here. | ||
91 | */ | ||
92 | unsigned long auto_demotion_disable_flags; | ||
93 | }; | ||
94 | |||
95 | static const struct idle_cpu *icpu; | ||
84 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; | 96 | static struct cpuidle_device __percpu *intel_idle_cpuidle_devices; |
85 | static int intel_idle(struct cpuidle_device *dev, | 97 | static int intel_idle(struct cpuidle_device *dev, |
86 | struct cpuidle_driver *drv, int index); | 98 | struct cpuidle_driver *drv, int index); |
@@ -88,12 +100,6 @@ static int intel_idle(struct cpuidle_device *dev, | |||
88 | static struct cpuidle_state *cpuidle_state_table; | 100 | static struct cpuidle_state *cpuidle_state_table; |
89 | 101 | ||
90 | /* | 102 | /* |
91 | * Hardware C-state auto-demotion may not always be optimal. | ||
92 | * Indicate which enable bits to clear here. | ||
93 | */ | ||
94 | static unsigned long long auto_demotion_disable_flags; | ||
95 | |||
96 | /* | ||
97 | * Set this flag for states where the HW flushes the TLB for us | 103 | * Set this flag for states where the HW flushes the TLB for us |
98 | * and so we don't need cross-calls to keep it consistent. | 104 | * and so we don't need cross-calls to keep it consistent. |
99 | * If this flag is set, SW flushes the TLB, so even if the | 105 | * If this flag is set, SW flushes the TLB, so even if the |
@@ -319,27 +325,72 @@ static void auto_demotion_disable(void *dummy) | |||
319 | unsigned long long msr_bits; | 325 | unsigned long long msr_bits; |
320 | 326 | ||
321 | rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); | 327 | rdmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
322 | msr_bits &= ~auto_demotion_disable_flags; | 328 | msr_bits &= ~(icpu->auto_demotion_disable_flags); |
323 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); | 329 | wrmsrl(MSR_NHM_SNB_PKG_CST_CFG_CTL, msr_bits); |
324 | } | 330 | } |
325 | 331 | ||
332 | static const struct idle_cpu idle_cpu_nehalem = { | ||
333 | .state_table = nehalem_cstates, | ||
334 | }; | ||
335 | |||
336 | static const struct idle_cpu idle_cpu_westmere = { | ||
337 | .state_table = nehalem_cstates, | ||
338 | .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE, | ||
339 | }; | ||
340 | |||
341 | static const struct idle_cpu idle_cpu_atom = { | ||
342 | .state_table = atom_cstates, | ||
343 | }; | ||
344 | |||
345 | static const struct idle_cpu idle_cpu_lincroft = { | ||
346 | .state_table = atom_cstates, | ||
347 | .auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE, | ||
348 | }; | ||
349 | |||
350 | static const struct idle_cpu idle_cpu_snb = { | ||
351 | .state_table = snb_cstates, | ||
352 | }; | ||
353 | |||
354 | #define ICPU(model, cpu) \ | ||
355 | { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } | ||
356 | |||
357 | static const struct x86_cpu_id intel_idle_ids[] = { | ||
358 | ICPU(0x1a, idle_cpu_nehalem), | ||
359 | ICPU(0x1e, idle_cpu_nehalem), | ||
360 | ICPU(0x1f, idle_cpu_nehalem), | ||
361 | ICPU(0x25, idle_cpu_westmere), | ||
362 | ICPU(0x2c, idle_cpu_westmere), | ||
363 | ICPU(0x2f, idle_cpu_westmere), | ||
364 | ICPU(0x1c, idle_cpu_atom), | ||
365 | ICPU(0x26, idle_cpu_lincroft), | ||
366 | ICPU(0x2f, idle_cpu_westmere), | ||
367 | ICPU(0x2a, idle_cpu_snb), | ||
368 | ICPU(0x2d, idle_cpu_snb), | ||
369 | {} | ||
370 | }; | ||
371 | MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); | ||
372 | |||
326 | /* | 373 | /* |
327 | * intel_idle_probe() | 374 | * intel_idle_probe() |
328 | */ | 375 | */ |
329 | static int intel_idle_probe(void) | 376 | static int intel_idle_probe(void) |
330 | { | 377 | { |
331 | unsigned int eax, ebx, ecx; | 378 | unsigned int eax, ebx, ecx; |
379 | const struct x86_cpu_id *id; | ||
332 | 380 | ||
333 | if (max_cstate == 0) { | 381 | if (max_cstate == 0) { |
334 | pr_debug(PREFIX "disabled\n"); | 382 | pr_debug(PREFIX "disabled\n"); |
335 | return -EPERM; | 383 | return -EPERM; |
336 | } | 384 | } |
337 | 385 | ||
338 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | 386 | id = x86_match_cpu(intel_idle_ids); |
339 | return -ENODEV; | 387 | if (!id) { |
340 | 388 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | |
341 | if (!boot_cpu_has(X86_FEATURE_MWAIT)) | 389 | boot_cpu_data.x86 == 6) |
390 | pr_debug(PREFIX "does not run on family %d model %d\n", | ||
391 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
342 | return -ENODEV; | 392 | return -ENODEV; |
393 | } | ||
343 | 394 | ||
344 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) | 395 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) |
345 | return -ENODEV; | 396 | return -ENODEV; |
@@ -353,43 +404,8 @@ static int intel_idle_probe(void) | |||
353 | 404 | ||
354 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); | 405 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", mwait_substates); |
355 | 406 | ||
356 | 407 | icpu = (const struct idle_cpu *)id->driver_data; | |
357 | if (boot_cpu_data.x86 != 6) /* family 6 */ | 408 | cpuidle_state_table = icpu->state_table; |
358 | return -ENODEV; | ||
359 | |||
360 | switch (boot_cpu_data.x86_model) { | ||
361 | |||
362 | case 0x1A: /* Core i7, Xeon 5500 series */ | ||
363 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ | ||
364 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ | ||
365 | case 0x2E: /* Nehalem-EX Xeon */ | ||
366 | case 0x2F: /* Westmere-EX Xeon */ | ||
367 | case 0x25: /* Westmere */ | ||
368 | case 0x2C: /* Westmere */ | ||
369 | cpuidle_state_table = nehalem_cstates; | ||
370 | auto_demotion_disable_flags = | ||
371 | (NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE); | ||
372 | break; | ||
373 | |||
374 | case 0x1C: /* 28 - Atom Processor */ | ||
375 | cpuidle_state_table = atom_cstates; | ||
376 | break; | ||
377 | |||
378 | case 0x26: /* 38 - Lincroft Atom Processor */ | ||
379 | cpuidle_state_table = atom_cstates; | ||
380 | auto_demotion_disable_flags = ATM_LNC_C6_AUTO_DEMOTE; | ||
381 | break; | ||
382 | |||
383 | case 0x2A: /* SNB */ | ||
384 | case 0x2D: /* SNB Xeon */ | ||
385 | cpuidle_state_table = snb_cstates; | ||
386 | break; | ||
387 | |||
388 | default: | ||
389 | pr_debug(PREFIX "does not run on family %d model %d\n", | ||
390 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
391 | return -ENODEV; | ||
392 | } | ||
393 | 409 | ||
394 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ | 410 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ |
395 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; | 411 | lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE; |
@@ -470,7 +486,7 @@ static int intel_idle_cpuidle_driver_init(void) | |||
470 | drv->state_count += 1; | 486 | drv->state_count += 1; |
471 | } | 487 | } |
472 | 488 | ||
473 | if (auto_demotion_disable_flags) | 489 | if (icpu->auto_demotion_disable_flags) |
474 | on_each_cpu(auto_demotion_disable, NULL, 1); | 490 | on_each_cpu(auto_demotion_disable, NULL, 1); |
475 | 491 | ||
476 | return 0; | 492 | return 0; |
@@ -522,7 +538,7 @@ int intel_idle_cpu_init(int cpu) | |||
522 | return -EIO; | 538 | return -EIO; |
523 | } | 539 | } |
524 | 540 | ||
525 | if (auto_demotion_disable_flags) | 541 | if (icpu->auto_demotion_disable_flags) |
526 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); | 542 | smp_call_function_single(cpu, auto_demotion_disable, NULL, 1); |
527 | 543 | ||
528 | return 0; | 544 | return 0; |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index c351aa421f8f..da739d9d1905 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -449,7 +449,6 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut | |||
449 | } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { | 449 | } else if ((drv = driver_find(buf, &gameport_bus)) != NULL) { |
450 | gameport_disconnect_port(gameport); | 450 | gameport_disconnect_port(gameport); |
451 | error = gameport_bind_driver(gameport, to_gameport_driver(drv)); | 451 | error = gameport_bind_driver(gameport, to_gameport_driver(drv)); |
452 | put_driver(drv); | ||
453 | } else { | 452 | } else { |
454 | error = -EINVAL; | 453 | error = -EINVAL; |
455 | } | 454 | } |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index ba70058e2be3..d0f7533dbf88 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -441,7 +441,6 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * | |||
441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { | 441 | } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { |
442 | serio_disconnect_port(serio); | 442 | serio_disconnect_port(serio); |
443 | error = serio_bind_driver(serio, to_serio_driver(drv)); | 443 | error = serio_bind_driver(serio, to_serio_driver(drv)); |
444 | put_driver(drv); | ||
445 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); | 444 | serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); |
446 | } else { | 445 | } else { |
447 | error = -EINVAL; | 446 | error = -EINVAL; |
diff --git a/drivers/media/video/cx18/cx18-alsa-main.c b/drivers/media/video/cx18/cx18-alsa-main.c index a1e6c2a32478..e118361c2e7b 100644 --- a/drivers/media/video/cx18/cx18-alsa-main.c +++ b/drivers/media/video/cx18/cx18-alsa-main.c | |||
@@ -285,7 +285,6 @@ static void __exit cx18_alsa_exit(void) | |||
285 | 285 | ||
286 | drv = driver_find("cx18", &pci_bus_type); | 286 | drv = driver_find("cx18", &pci_bus_type); |
287 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); | 287 | ret = driver_for_each_device(drv, NULL, NULL, cx18_alsa_exit_callback); |
288 | put_driver(drv); | ||
289 | 288 | ||
290 | cx18_ext_init = NULL; | 289 | cx18_ext_init = NULL; |
291 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); | 290 | printk(KERN_INFO "cx18-alsa: module unload complete\n"); |
diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index d0fbfcf7133d..e5e7fa9e737b 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c | |||
@@ -1293,7 +1293,6 @@ static int __init ivtvfb_init(void) | |||
1293 | 1293 | ||
1294 | drv = driver_find("ivtv", &pci_bus_type); | 1294 | drv = driver_find("ivtv", &pci_bus_type); |
1295 | err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); | 1295 | err = driver_for_each_device(drv, NULL, ®istered, ivtvfb_callback_init); |
1296 | put_driver(drv); | ||
1297 | if (!registered) { | 1296 | if (!registered) { |
1298 | printk(KERN_ERR "ivtvfb: no cards found\n"); | 1297 | printk(KERN_ERR "ivtvfb: no cards found\n"); |
1299 | return -ENODEV; | 1298 | return -ENODEV; |
@@ -1310,7 +1309,6 @@ static void ivtvfb_cleanup(void) | |||
1310 | 1309 | ||
1311 | drv = driver_find("ivtv", &pci_bus_type); | 1310 | drv = driver_find("ivtv", &pci_bus_type); |
1312 | err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); | 1311 | err = driver_for_each_device(drv, NULL, NULL, ivtvfb_callback_cleanup); |
1313 | put_driver(drv); | ||
1314 | } | 1312 | } |
1315 | 1313 | ||
1316 | module_init(ivtvfb_init); | 1314 | module_init(ivtvfb_init); |
diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 8ea4ee116e46..63eccb55728f 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c | |||
@@ -344,16 +344,13 @@ static int fimc_md_register_platform_entities(struct fimc_md *fmd) | |||
344 | return -ENODEV; | 344 | return -ENODEV; |
345 | ret = driver_for_each_device(driver, NULL, fmd, | 345 | ret = driver_for_each_device(driver, NULL, fmd, |
346 | fimc_register_callback); | 346 | fimc_register_callback); |
347 | put_driver(driver); | ||
348 | if (ret) | 347 | if (ret) |
349 | return ret; | 348 | return ret; |
350 | 349 | ||
351 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); | 350 | driver = driver_find(CSIS_DRIVER_NAME, &platform_bus_type); |
352 | if (driver) { | 351 | if (driver) |
353 | ret = driver_for_each_device(driver, NULL, fmd, | 352 | ret = driver_for_each_device(driver, NULL, fmd, |
354 | csis_register_callback); | 353 | csis_register_callback); |
355 | put_driver(driver); | ||
356 | } | ||
357 | return ret; | 354 | return ret; |
358 | } | 355 | } |
359 | 356 | ||
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index 7884baeff76a..f7ca5cc143c6 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c | |||
@@ -58,7 +58,6 @@ static struct v4l2_subdev *find_and_register_subdev( | |||
58 | } | 58 | } |
59 | 59 | ||
60 | done: | 60 | done: |
61 | put_driver(drv); | ||
62 | return sd; | 61 | return sd; |
63 | } | 62 | } |
64 | 63 | ||
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index f320f466f03b..e8c42d6a7d1c 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -915,9 +915,7 @@ static int phy_probe(struct device *dev) | |||
915 | 915 | ||
916 | phydev = to_phy_device(dev); | 916 | phydev = to_phy_device(dev); |
917 | 917 | ||
918 | /* Make sure the driver is held. | 918 | drv = phydev->dev.driver; |
919 | * XXX -- Is this correct? */ | ||
920 | drv = get_driver(phydev->dev.driver); | ||
921 | phydrv = to_phy_driver(drv); | 919 | phydrv = to_phy_driver(drv); |
922 | phydev->drv = phydrv; | 920 | phydev->drv = phydrv; |
923 | 921 | ||
@@ -957,8 +955,6 @@ static int phy_remove(struct device *dev) | |||
957 | 955 | ||
958 | if (phydev->drv->remove) | 956 | if (phydev->drv->remove) |
959 | phydev->drv->remove(phydev); | 957 | phydev->drv->remove(phydev); |
960 | |||
961 | put_driver(dev->driver); | ||
962 | phydev->drv = NULL; | 958 | phydev->drv = NULL; |
963 | 959 | ||
964 | return 0; | 960 | return 0; |
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 3623d65f8b86..8d9616b821ca 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -72,9 +72,7 @@ int pci_add_dynid(struct pci_driver *drv, | |||
72 | list_add_tail(&dynid->node, &drv->dynids.list); | 72 | list_add_tail(&dynid->node, &drv->dynids.list); |
73 | spin_unlock(&drv->dynids.lock); | 73 | spin_unlock(&drv->dynids.lock); |
74 | 74 | ||
75 | get_driver(&drv->driver); | ||
76 | retval = driver_attach(&drv->driver); | 75 | retval = driver_attach(&drv->driver); |
77 | put_driver(&drv->driver); | ||
78 | 76 | ||
79 | return retval; | 77 | return retval; |
80 | } | 78 | } |
@@ -190,43 +188,34 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) | |||
190 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | 188 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); |
191 | 189 | ||
192 | static int | 190 | static int |
193 | pci_create_newid_file(struct pci_driver *drv) | 191 | pci_create_newid_files(struct pci_driver *drv) |
194 | { | 192 | { |
195 | int error = 0; | 193 | int error = 0; |
196 | if (drv->probe != NULL) | ||
197 | error = driver_create_file(&drv->driver, &driver_attr_new_id); | ||
198 | return error; | ||
199 | } | ||
200 | |||
201 | static void pci_remove_newid_file(struct pci_driver *drv) | ||
202 | { | ||
203 | driver_remove_file(&drv->driver, &driver_attr_new_id); | ||
204 | } | ||
205 | 194 | ||
206 | static int | 195 | if (drv->probe != NULL) { |
207 | pci_create_removeid_file(struct pci_driver *drv) | 196 | error = driver_create_file(&drv->driver, &driver_attr_new_id); |
208 | { | 197 | if (error == 0) { |
209 | int error = 0; | 198 | error = driver_create_file(&drv->driver, |
210 | if (drv->probe != NULL) | 199 | &driver_attr_remove_id); |
211 | error = driver_create_file(&drv->driver,&driver_attr_remove_id); | 200 | if (error) |
201 | driver_remove_file(&drv->driver, | ||
202 | &driver_attr_new_id); | ||
203 | } | ||
204 | } | ||
212 | return error; | 205 | return error; |
213 | } | 206 | } |
214 | 207 | ||
215 | static void pci_remove_removeid_file(struct pci_driver *drv) | 208 | static void pci_remove_newid_files(struct pci_driver *drv) |
216 | { | 209 | { |
217 | driver_remove_file(&drv->driver, &driver_attr_remove_id); | 210 | driver_remove_file(&drv->driver, &driver_attr_remove_id); |
211 | driver_remove_file(&drv->driver, &driver_attr_new_id); | ||
218 | } | 212 | } |
219 | #else /* !CONFIG_HOTPLUG */ | 213 | #else /* !CONFIG_HOTPLUG */ |
220 | static inline int pci_create_newid_file(struct pci_driver *drv) | 214 | static inline int pci_create_newid_files(struct pci_driver *drv) |
221 | { | 215 | { |
222 | return 0; | 216 | return 0; |
223 | } | 217 | } |
224 | static inline void pci_remove_newid_file(struct pci_driver *drv) {} | 218 | static inline void pci_remove_newid_files(struct pci_driver *drv) {} |
225 | static inline int pci_create_removeid_file(struct pci_driver *drv) | ||
226 | { | ||
227 | return 0; | ||
228 | } | ||
229 | static inline void pci_remove_removeid_file(struct pci_driver *drv) {} | ||
230 | #endif | 219 | #endif |
231 | 220 | ||
232 | /** | 221 | /** |
@@ -1138,18 +1127,12 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner, | |||
1138 | if (error) | 1127 | if (error) |
1139 | goto out; | 1128 | goto out; |
1140 | 1129 | ||
1141 | error = pci_create_newid_file(drv); | 1130 | error = pci_create_newid_files(drv); |
1142 | if (error) | 1131 | if (error) |
1143 | goto out_newid; | 1132 | goto out_newid; |
1144 | |||
1145 | error = pci_create_removeid_file(drv); | ||
1146 | if (error) | ||
1147 | goto out_removeid; | ||
1148 | out: | 1133 | out: |
1149 | return error; | 1134 | return error; |
1150 | 1135 | ||
1151 | out_removeid: | ||
1152 | pci_remove_newid_file(drv); | ||
1153 | out_newid: | 1136 | out_newid: |
1154 | driver_unregister(&drv->driver); | 1137 | driver_unregister(&drv->driver); |
1155 | goto out; | 1138 | goto out; |
@@ -1168,8 +1151,7 @@ out_newid: | |||
1168 | void | 1151 | void |
1169 | pci_unregister_driver(struct pci_driver *drv) | 1152 | pci_unregister_driver(struct pci_driver *drv) |
1170 | { | 1153 | { |
1171 | pci_remove_removeid_file(drv); | 1154 | pci_remove_newid_files(drv); |
1172 | pci_remove_newid_file(drv); | ||
1173 | driver_unregister(&drv->driver); | 1155 | driver_unregister(&drv->driver); |
1174 | pci_free_dynids(drv); | 1156 | pci_free_dynids(drv); |
1175 | } | 1157 | } |
diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 1620088a0e7e..401090110922 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c | |||
@@ -593,7 +593,7 @@ static pci_ers_result_t pcifront_common_process(int cmd, | |||
593 | } | 593 | } |
594 | pdrv = pcidev->driver; | 594 | pdrv = pcidev->driver; |
595 | 595 | ||
596 | if (get_driver(&pdrv->driver)) { | 596 | if (pdrv) { |
597 | if (pdrv->err_handler && pdrv->err_handler->error_detected) { | 597 | if (pdrv->err_handler && pdrv->err_handler->error_detected) { |
598 | dev_dbg(&pcidev->dev, | 598 | dev_dbg(&pcidev->dev, |
599 | "trying to call AER service\n"); | 599 | "trying to call AER service\n"); |
@@ -623,7 +623,6 @@ static pci_ers_result_t pcifront_common_process(int cmd, | |||
623 | } | 623 | } |
624 | } | 624 | } |
625 | } | 625 | } |
626 | put_driver(&pdrv->driver); | ||
627 | } | 626 | } |
628 | if (!flag) | 627 | if (!flag) |
629 | result = PCI_ERS_RESULT_NONE; | 628 | result = PCI_ERS_RESULT_NONE; |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 1932029de48d..079629bff957 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -127,10 +127,7 @@ pcmcia_store_new_id(struct device_driver *driver, const char *buf, size_t count) | |||
127 | list_add_tail(&dynid->node, &pdrv->dynids.list); | 127 | list_add_tail(&dynid->node, &pdrv->dynids.list); |
128 | mutex_unlock(&pdrv->dynids.lock); | 128 | mutex_unlock(&pdrv->dynids.lock); |
129 | 129 | ||
130 | if (get_driver(&pdrv->drv)) { | 130 | retval = driver_attach(&pdrv->drv); |
131 | retval = driver_attach(&pdrv->drv); | ||
132 | put_driver(&pdrv->drv); | ||
133 | } | ||
134 | 131 | ||
135 | if (retval) | 132 | if (retval) |
136 | return retval; | 133 | return retval; |
@@ -160,6 +157,11 @@ pcmcia_create_newid_file(struct pcmcia_driver *drv) | |||
160 | return error; | 157 | return error; |
161 | } | 158 | } |
162 | 159 | ||
160 | static void | ||
161 | pcmcia_remove_newid_file(struct pcmcia_driver *drv) | ||
162 | { | ||
163 | driver_remove_file(&drv->drv, &driver_attr_new_id); | ||
164 | } | ||
163 | 165 | ||
164 | /** | 166 | /** |
165 | * pcmcia_register_driver - register a PCMCIA driver with the bus core | 167 | * pcmcia_register_driver - register a PCMCIA driver with the bus core |
@@ -204,6 +206,7 @@ EXPORT_SYMBOL(pcmcia_register_driver); | |||
204 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) | 206 | void pcmcia_unregister_driver(struct pcmcia_driver *driver) |
205 | { | 207 | { |
206 | pr_debug("unregistering driver %s\n", driver->name); | 208 | pr_debug("unregistering driver %s\n", driver->name); |
209 | pcmcia_remove_newid_file(driver); | ||
207 | driver_unregister(&driver->drv); | 210 | driver_unregister(&driver->drv); |
208 | pcmcia_free_dynids(driver); | 211 | pcmcia_free_dynids(driver); |
209 | } | 212 | } |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 4f1989d27b1f..5f1dc6fb5708 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -580,7 +580,6 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | |||
580 | struct device *dev; | 580 | struct device *dev; |
581 | 581 | ||
582 | /* We don't want ccwgroup devices to live longer than their driver. */ | 582 | /* We don't want ccwgroup devices to live longer than their driver. */ |
583 | get_driver(&cdriver->driver); | ||
584 | while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, | 583 | while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, |
585 | __ccwgroup_match_all))) { | 584 | __ccwgroup_match_all))) { |
586 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 585 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
@@ -592,7 +591,6 @@ void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | |||
592 | mutex_unlock(&gdev->reg_mutex); | 591 | mutex_unlock(&gdev->reg_mutex); |
593 | put_device(dev); | 592 | put_device(dev); |
594 | } | 593 | } |
595 | put_driver(&cdriver->driver); | ||
596 | driver_unregister(&cdriver->driver); | 594 | driver_unregister(&cdriver->driver); |
597 | } | 595 | } |
598 | EXPORT_SYMBOL(ccwgroup_driver_unregister); | 596 | EXPORT_SYMBOL(ccwgroup_driver_unregister); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 47269858ecb6..02d015259461 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -1676,15 +1676,9 @@ struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, | |||
1676 | const char *bus_id) | 1676 | const char *bus_id) |
1677 | { | 1677 | { |
1678 | struct device *dev; | 1678 | struct device *dev; |
1679 | struct device_driver *drv; | ||
1680 | 1679 | ||
1681 | drv = get_driver(&cdrv->driver); | 1680 | dev = driver_find_device(&cdrv->driver, NULL, (void *)bus_id, |
1682 | if (!drv) | ||
1683 | return NULL; | ||
1684 | |||
1685 | dev = driver_find_device(drv, NULL, (void *)bus_id, | ||
1686 | __ccwdev_check_busid); | 1681 | __ccwdev_check_busid); |
1687 | put_driver(drv); | ||
1688 | 1682 | ||
1689 | return dev ? to_ccwdev(dev) : NULL; | 1683 | return dev ? to_ccwdev(dev) : NULL; |
1690 | } | 1684 | } |
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c index 4d2ea4000422..32515a201bbc 100644 --- a/drivers/s390/net/smsgiucv_app.c +++ b/drivers/s390/net/smsgiucv_app.c | |||
@@ -168,7 +168,7 @@ static int __init smsgiucv_app_init(void) | |||
168 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); | 168 | rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT); |
169 | if (rc) { | 169 | if (rc) { |
170 | kfree(smsg_app_dev); | 170 | kfree(smsg_app_dev); |
171 | goto fail_put_driver; | 171 | goto fail; |
172 | } | 172 | } |
173 | smsg_app_dev->bus = &iucv_bus; | 173 | smsg_app_dev->bus = &iucv_bus; |
174 | smsg_app_dev->parent = iucv_root; | 174 | smsg_app_dev->parent = iucv_root; |
@@ -177,7 +177,7 @@ static int __init smsgiucv_app_init(void) | |||
177 | rc = device_register(smsg_app_dev); | 177 | rc = device_register(smsg_app_dev); |
178 | if (rc) { | 178 | if (rc) { |
179 | put_device(smsg_app_dev); | 179 | put_device(smsg_app_dev); |
180 | goto fail_put_driver; | 180 | goto fail; |
181 | } | 181 | } |
182 | 182 | ||
183 | /* convert sender to uppercase characters */ | 183 | /* convert sender to uppercase characters */ |
@@ -191,12 +191,11 @@ static int __init smsgiucv_app_init(void) | |||
191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); | 191 | rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback); |
192 | if (rc) { | 192 | if (rc) { |
193 | device_unregister(smsg_app_dev); | 193 | device_unregister(smsg_app_dev); |
194 | goto fail_put_driver; | 194 | goto fail; |
195 | } | 195 | } |
196 | 196 | ||
197 | rc = 0; | 197 | rc = 0; |
198 | fail_put_driver: | 198 | fail: |
199 | put_driver(smsgiucv_drv); | ||
200 | return rc; | 199 | return rc; |
201 | } | 200 | } |
202 | module_init(smsgiucv_app_init); | 201 | module_init(smsgiucv_app_init); |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index bb6317fb925c..ff109ae94767 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -140,19 +140,6 @@ static void ssb_device_put(struct ssb_device *dev) | |||
140 | put_device(dev->dev); | 140 | put_device(dev->dev); |
141 | } | 141 | } |
142 | 142 | ||
143 | static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv) | ||
144 | { | ||
145 | if (drv) | ||
146 | get_driver(&drv->drv); | ||
147 | return drv; | ||
148 | } | ||
149 | |||
150 | static inline void ssb_driver_put(struct ssb_driver *drv) | ||
151 | { | ||
152 | if (drv) | ||
153 | put_driver(&drv->drv); | ||
154 | } | ||
155 | |||
156 | static int ssb_device_resume(struct device *dev) | 143 | static int ssb_device_resume(struct device *dev) |
157 | { | 144 | { |
158 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 145 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
@@ -250,11 +237,9 @@ int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) | |||
250 | ssb_device_put(sdev); | 237 | ssb_device_put(sdev); |
251 | continue; | 238 | continue; |
252 | } | 239 | } |
253 | sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver)); | 240 | sdrv = drv_to_ssb_drv(sdev->dev->driver); |
254 | if (!sdrv || SSB_WARN_ON(!sdrv->remove)) { | 241 | if (SSB_WARN_ON(!sdrv->remove)) |
255 | ssb_device_put(sdev); | ||
256 | continue; | 242 | continue; |
257 | } | ||
258 | sdrv->remove(sdev); | 243 | sdrv->remove(sdev); |
259 | ctx->device_frozen[i] = 1; | 244 | ctx->device_frozen[i] = 1; |
260 | } | 245 | } |
@@ -293,7 +278,6 @@ int ssb_devices_thaw(struct ssb_freeze_context *ctx) | |||
293 | dev_name(sdev->dev)); | 278 | dev_name(sdev->dev)); |
294 | result = err; | 279 | result = err; |
295 | } | 280 | } |
296 | ssb_driver_put(sdrv); | ||
297 | ssb_device_put(sdev); | 281 | ssb_device_put(sdev); |
298 | } | 282 | } |
299 | 283 | ||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index d40ff9568813..4fee024ecc9b 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -71,10 +71,7 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids, | |||
71 | list_add_tail(&dynid->node, &dynids->list); | 71 | list_add_tail(&dynid->node, &dynids->list); |
72 | spin_unlock(&dynids->lock); | 72 | spin_unlock(&dynids->lock); |
73 | 73 | ||
74 | if (get_driver(driver)) { | 74 | retval = driver_attach(driver); |
75 | retval = driver_attach(driver); | ||
76 | put_driver(driver); | ||
77 | } | ||
78 | 75 | ||
79 | if (retval) | 76 | if (retval) |
80 | return retval; | 77 | return retval; |
@@ -132,43 +129,39 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) | |||
132 | } | 129 | } |
133 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); | 130 | static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); |
134 | 131 | ||
135 | static int usb_create_newid_file(struct usb_driver *usb_drv) | 132 | static int usb_create_newid_files(struct usb_driver *usb_drv) |
136 | { | 133 | { |
137 | int error = 0; | 134 | int error = 0; |
138 | 135 | ||
139 | if (usb_drv->no_dynamic_id) | 136 | if (usb_drv->no_dynamic_id) |
140 | goto exit; | 137 | goto exit; |
141 | 138 | ||
142 | if (usb_drv->probe != NULL) | 139 | if (usb_drv->probe != NULL) { |
143 | error = driver_create_file(&usb_drv->drvwrap.driver, | 140 | error = driver_create_file(&usb_drv->drvwrap.driver, |
144 | &driver_attr_new_id); | 141 | &driver_attr_new_id); |
142 | if (error == 0) { | ||
143 | error = driver_create_file(&usb_drv->drvwrap.driver, | ||
144 | &driver_attr_remove_id); | ||
145 | if (error) | ||
146 | driver_remove_file(&usb_drv->drvwrap.driver, | ||
147 | &driver_attr_new_id); | ||
148 | } | ||
149 | } | ||
145 | exit: | 150 | exit: |
146 | return error; | 151 | return error; |
147 | } | 152 | } |
148 | 153 | ||
149 | static void usb_remove_newid_file(struct usb_driver *usb_drv) | 154 | static void usb_remove_newid_files(struct usb_driver *usb_drv) |
150 | { | 155 | { |
151 | if (usb_drv->no_dynamic_id) | 156 | if (usb_drv->no_dynamic_id) |
152 | return; | 157 | return; |
153 | 158 | ||
154 | if (usb_drv->probe != NULL) | 159 | if (usb_drv->probe != NULL) { |
155 | driver_remove_file(&usb_drv->drvwrap.driver, | 160 | driver_remove_file(&usb_drv->drvwrap.driver, |
156 | &driver_attr_new_id); | ||
157 | } | ||
158 | |||
159 | static int | ||
160 | usb_create_removeid_file(struct usb_driver *drv) | ||
161 | { | ||
162 | int error = 0; | ||
163 | if (drv->probe != NULL) | ||
164 | error = driver_create_file(&drv->drvwrap.driver, | ||
165 | &driver_attr_remove_id); | 161 | &driver_attr_remove_id); |
166 | return error; | 162 | driver_remove_file(&usb_drv->drvwrap.driver, |
167 | } | 163 | &driver_attr_new_id); |
168 | 164 | } | |
169 | static void usb_remove_removeid_file(struct usb_driver *drv) | ||
170 | { | ||
171 | driver_remove_file(&drv->drvwrap.driver, &driver_attr_remove_id); | ||
172 | } | 165 | } |
173 | 166 | ||
174 | static void usb_free_dynids(struct usb_driver *usb_drv) | 167 | static void usb_free_dynids(struct usb_driver *usb_drv) |
@@ -183,22 +176,12 @@ static void usb_free_dynids(struct usb_driver *usb_drv) | |||
183 | spin_unlock(&usb_drv->dynids.lock); | 176 | spin_unlock(&usb_drv->dynids.lock); |
184 | } | 177 | } |
185 | #else | 178 | #else |
186 | static inline int usb_create_newid_file(struct usb_driver *usb_drv) | 179 | static inline int usb_create_newid_files(struct usb_driver *usb_drv) |
187 | { | 180 | { |
188 | return 0; | 181 | return 0; |
189 | } | 182 | } |
190 | 183 | ||
191 | static void usb_remove_newid_file(struct usb_driver *usb_drv) | 184 | static void usb_remove_newid_files(struct usb_driver *usb_drv) |
192 | { | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | usb_create_removeid_file(struct usb_driver *drv) | ||
197 | { | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static void usb_remove_removeid_file(struct usb_driver *drv) | ||
202 | { | 185 | { |
203 | } | 186 | } |
204 | 187 | ||
@@ -875,22 +858,16 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner, | |||
875 | 858 | ||
876 | usbfs_update_special(); | 859 | usbfs_update_special(); |
877 | 860 | ||
878 | retval = usb_create_newid_file(new_driver); | 861 | retval = usb_create_newid_files(new_driver); |
879 | if (retval) | 862 | if (retval) |
880 | goto out_newid; | 863 | goto out_newid; |
881 | 864 | ||
882 | retval = usb_create_removeid_file(new_driver); | ||
883 | if (retval) | ||
884 | goto out_removeid; | ||
885 | |||
886 | pr_info("%s: registered new interface driver %s\n", | 865 | pr_info("%s: registered new interface driver %s\n", |
887 | usbcore_name, new_driver->name); | 866 | usbcore_name, new_driver->name); |
888 | 867 | ||
889 | out: | 868 | out: |
890 | return retval; | 869 | return retval; |
891 | 870 | ||
892 | out_removeid: | ||
893 | usb_remove_newid_file(new_driver); | ||
894 | out_newid: | 871 | out_newid: |
895 | driver_unregister(&new_driver->drvwrap.driver); | 872 | driver_unregister(&new_driver->drvwrap.driver); |
896 | 873 | ||
@@ -917,10 +894,9 @@ void usb_deregister(struct usb_driver *driver) | |||
917 | pr_info("%s: deregistering interface driver %s\n", | 894 | pr_info("%s: deregistering interface driver %s\n", |
918 | usbcore_name, driver->name); | 895 | usbcore_name, driver->name); |
919 | 896 | ||
920 | usb_remove_removeid_file(driver); | 897 | usb_remove_newid_files(driver); |
921 | usb_remove_newid_file(driver); | ||
922 | usb_free_dynids(driver); | ||
923 | driver_unregister(&driver->drvwrap.driver); | 898 | driver_unregister(&driver->drvwrap.driver); |
899 | usb_free_dynids(driver); | ||
924 | 900 | ||
925 | usbfs_update_special(); | 901 | usbfs_update_special(); |
926 | } | 902 | } |
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 64e1f7c67b08..c68e4270457a 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c | |||
@@ -171,14 +171,4 @@ MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>"); | |||
171 | MODULE_LICENSE("Dual BSD/GPL"); | 171 | MODULE_LICENSE("Dual BSD/GPL"); |
172 | MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); | 172 | MODULE_DESCRIPTION("DesignWare USB3 PCI Glue Layer"); |
173 | 173 | ||
174 | static int __devinit dwc3_pci_init(void) | 174 | module_pci_driver(dwc3_pci_driver); |
175 | { | ||
176 | return pci_register_driver(&dwc3_pci_driver); | ||
177 | } | ||
178 | module_init(dwc3_pci_init); | ||
179 | |||
180 | static void __exit dwc3_pci_exit(void) | ||
181 | { | ||
182 | pci_unregister_driver(&dwc3_pci_driver); | ||
183 | } | ||
184 | module_exit(dwc3_pci_exit); | ||
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index fcbe742188a5..df600d14974d 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c | |||
@@ -13,12 +13,11 @@ | |||
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/w1-gpio.h> | 15 | #include <linux/w1-gpio.h> |
16 | #include <linux/gpio.h> | ||
16 | 17 | ||
17 | #include "../w1.h" | 18 | #include "../w1.h" |
18 | #include "../w1_int.h" | 19 | #include "../w1_int.h" |
19 | 20 | ||
20 | #include <asm/gpio.h> | ||
21 | |||
22 | static void w1_gpio_write_bit_dir(void *data, u8 bit) | 21 | static void w1_gpio_write_bit_dir(void *data, u8 bit) |
23 | { | 22 | { |
24 | struct w1_gpio_platform_data *pdata = data; | 23 | struct w1_gpio_platform_data *pdata = data; |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index 956d5ddddf6e..b80bc846a15a 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -23,9 +23,13 @@ | |||
23 | #include <linux/debugfs.h> | 23 | #include <linux/debugfs.h> |
24 | #include <linux/fsnotify.h> | 24 | #include <linux/fsnotify.h> |
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/parser.h> | ||
26 | #include <linux/magic.h> | 28 | #include <linux/magic.h> |
27 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
28 | 30 | ||
31 | #define DEBUGFS_DEFAULT_MODE 0755 | ||
32 | |||
29 | static struct vfsmount *debugfs_mount; | 33 | static struct vfsmount *debugfs_mount; |
30 | static int debugfs_mount_count; | 34 | static int debugfs_mount_count; |
31 | static bool debugfs_registered; | 35 | static bool debugfs_registered; |
@@ -125,11 +129,154 @@ static inline int debugfs_positive(struct dentry *dentry) | |||
125 | return dentry->d_inode && !d_unhashed(dentry); | 129 | return dentry->d_inode && !d_unhashed(dentry); |
126 | } | 130 | } |
127 | 131 | ||
132 | struct debugfs_mount_opts { | ||
133 | uid_t uid; | ||
134 | gid_t gid; | ||
135 | umode_t mode; | ||
136 | }; | ||
137 | |||
138 | enum { | ||
139 | Opt_uid, | ||
140 | Opt_gid, | ||
141 | Opt_mode, | ||
142 | Opt_err | ||
143 | }; | ||
144 | |||
145 | static const match_table_t tokens = { | ||
146 | {Opt_uid, "uid=%u"}, | ||
147 | {Opt_gid, "gid=%u"}, | ||
148 | {Opt_mode, "mode=%o"}, | ||
149 | {Opt_err, NULL} | ||
150 | }; | ||
151 | |||
152 | struct debugfs_fs_info { | ||
153 | struct debugfs_mount_opts mount_opts; | ||
154 | }; | ||
155 | |||
156 | static int debugfs_parse_options(char *data, struct debugfs_mount_opts *opts) | ||
157 | { | ||
158 | substring_t args[MAX_OPT_ARGS]; | ||
159 | int option; | ||
160 | int token; | ||
161 | char *p; | ||
162 | |||
163 | opts->mode = DEBUGFS_DEFAULT_MODE; | ||
164 | |||
165 | while ((p = strsep(&data, ",")) != NULL) { | ||
166 | if (!*p) | ||
167 | continue; | ||
168 | |||
169 | token = match_token(p, tokens, args); | ||
170 | switch (token) { | ||
171 | case Opt_uid: | ||
172 | if (match_int(&args[0], &option)) | ||
173 | return -EINVAL; | ||
174 | opts->uid = option; | ||
175 | break; | ||
176 | case Opt_gid: | ||
177 | if (match_octal(&args[0], &option)) | ||
178 | return -EINVAL; | ||
179 | opts->gid = option; | ||
180 | break; | ||
181 | case Opt_mode: | ||
182 | if (match_octal(&args[0], &option)) | ||
183 | return -EINVAL; | ||
184 | opts->mode = option & S_IALLUGO; | ||
185 | break; | ||
186 | /* | ||
187 | * We might like to report bad mount options here; | ||
188 | * but traditionally debugfs has ignored all mount options | ||
189 | */ | ||
190 | } | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static int debugfs_apply_options(struct super_block *sb) | ||
197 | { | ||
198 | struct debugfs_fs_info *fsi = sb->s_fs_info; | ||
199 | struct inode *inode = sb->s_root->d_inode; | ||
200 | struct debugfs_mount_opts *opts = &fsi->mount_opts; | ||
201 | |||
202 | inode->i_mode &= ~S_IALLUGO; | ||
203 | inode->i_mode |= opts->mode; | ||
204 | |||
205 | inode->i_uid = opts->uid; | ||
206 | inode->i_gid = opts->gid; | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int debugfs_remount(struct super_block *sb, int *flags, char *data) | ||
212 | { | ||
213 | int err; | ||
214 | struct debugfs_fs_info *fsi = sb->s_fs_info; | ||
215 | |||
216 | err = debugfs_parse_options(data, &fsi->mount_opts); | ||
217 | if (err) | ||
218 | goto fail; | ||
219 | |||
220 | debugfs_apply_options(sb); | ||
221 | |||
222 | fail: | ||
223 | return err; | ||
224 | } | ||
225 | |||
226 | static int debugfs_show_options(struct seq_file *m, struct dentry *root) | ||
227 | { | ||
228 | struct debugfs_fs_info *fsi = root->d_sb->s_fs_info; | ||
229 | struct debugfs_mount_opts *opts = &fsi->mount_opts; | ||
230 | |||
231 | if (opts->uid != 0) | ||
232 | seq_printf(m, ",uid=%u", opts->uid); | ||
233 | if (opts->gid != 0) | ||
234 | seq_printf(m, ",gid=%u", opts->gid); | ||
235 | if (opts->mode != DEBUGFS_DEFAULT_MODE) | ||
236 | seq_printf(m, ",mode=%o", opts->mode); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static const struct super_operations debugfs_super_operations = { | ||
242 | .statfs = simple_statfs, | ||
243 | .remount_fs = debugfs_remount, | ||
244 | .show_options = debugfs_show_options, | ||
245 | }; | ||
246 | |||
128 | static int debug_fill_super(struct super_block *sb, void *data, int silent) | 247 | static int debug_fill_super(struct super_block *sb, void *data, int silent) |
129 | { | 248 | { |
130 | static struct tree_descr debug_files[] = {{""}}; | 249 | static struct tree_descr debug_files[] = {{""}}; |
250 | struct debugfs_fs_info *fsi; | ||
251 | int err; | ||
252 | |||
253 | save_mount_options(sb, data); | ||
254 | |||
255 | fsi = kzalloc(sizeof(struct debugfs_fs_info), GFP_KERNEL); | ||
256 | sb->s_fs_info = fsi; | ||
257 | if (!fsi) { | ||
258 | err = -ENOMEM; | ||
259 | goto fail; | ||
260 | } | ||
261 | |||
262 | err = debugfs_parse_options(data, &fsi->mount_opts); | ||
263 | if (err) | ||
264 | goto fail; | ||
265 | |||
266 | err = simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); | ||
267 | if (err) | ||
268 | goto fail; | ||
269 | |||
270 | sb->s_op = &debugfs_super_operations; | ||
271 | |||
272 | debugfs_apply_options(sb); | ||
273 | |||
274 | return 0; | ||
131 | 275 | ||
132 | return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); | 276 | fail: |
277 | kfree(fsi); | ||
278 | sb->s_fs_info = NULL; | ||
279 | return err; | ||
133 | } | 280 | } |
134 | 281 | ||
135 | static struct dentry *debug_mount(struct file_system_type *fs_type, | 282 | static struct dentry *debug_mount(struct file_system_type *fs_type, |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 7fdf6a7b7436..dd3779cf3a3b 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
@@ -22,76 +22,100 @@ | |||
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/security.h> | 24 | #include <linux/security.h> |
25 | #include <linux/hash.h> | ||
25 | #include "sysfs.h" | 26 | #include "sysfs.h" |
26 | 27 | ||
27 | DEFINE_MUTEX(sysfs_mutex); | 28 | DEFINE_MUTEX(sysfs_mutex); |
28 | DEFINE_SPINLOCK(sysfs_assoc_lock); | 29 | DEFINE_SPINLOCK(sysfs_assoc_lock); |
29 | 30 | ||
31 | #define to_sysfs_dirent(X) rb_entry((X), struct sysfs_dirent, s_rb); | ||
32 | |||
30 | static DEFINE_SPINLOCK(sysfs_ino_lock); | 33 | static DEFINE_SPINLOCK(sysfs_ino_lock); |
31 | static DEFINE_IDA(sysfs_ino_ida); | 34 | static DEFINE_IDA(sysfs_ino_ida); |
32 | 35 | ||
33 | /** | 36 | /** |
34 | * sysfs_link_sibling - link sysfs_dirent into sibling list | 37 | * sysfs_name_hash |
38 | * @ns: Namespace tag to hash | ||
39 | * @name: Null terminated string to hash | ||
40 | * | ||
41 | * Returns 31 bit hash of ns + name (so it fits in an off_t ) | ||
42 | */ | ||
43 | static unsigned int sysfs_name_hash(const void *ns, const char *name) | ||
44 | { | ||
45 | unsigned long hash = init_name_hash(); | ||
46 | unsigned int len = strlen(name); | ||
47 | while (len--) | ||
48 | hash = partial_name_hash(*name++, hash); | ||
49 | hash = ( end_name_hash(hash) ^ hash_ptr( (void *)ns, 31 ) ); | ||
50 | hash &= 0x7fffffffU; | ||
51 | /* Reserve hash numbers 0, 1 and INT_MAX for magic directory entries */ | ||
52 | if (hash < 1) | ||
53 | hash += 2; | ||
54 | if (hash >= INT_MAX) | ||
55 | hash = INT_MAX - 1; | ||
56 | return hash; | ||
57 | } | ||
58 | |||
59 | static int sysfs_name_compare(unsigned int hash, const void *ns, | ||
60 | const char *name, const struct sysfs_dirent *sd) | ||
61 | { | ||
62 | if (hash != sd->s_hash) | ||
63 | return hash - sd->s_hash; | ||
64 | if (ns != sd->s_ns) | ||
65 | return ns - sd->s_ns; | ||
66 | return strcmp(name, sd->s_name); | ||
67 | } | ||
68 | |||
69 | static int sysfs_sd_compare(const struct sysfs_dirent *left, | ||
70 | const struct sysfs_dirent *right) | ||
71 | { | ||
72 | return sysfs_name_compare(left->s_hash, left->s_ns, left->s_name, | ||
73 | right); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * sysfs_link_subling - link sysfs_dirent into sibling rbtree | ||
35 | * @sd: sysfs_dirent of interest | 78 | * @sd: sysfs_dirent of interest |
36 | * | 79 | * |
37 | * Link @sd into its sibling list which starts from | 80 | * Link @sd into its sibling rbtree which starts from |
38 | * sd->s_parent->s_dir.children. | 81 | * sd->s_parent->s_dir.children. |
39 | * | 82 | * |
40 | * Locking: | 83 | * Locking: |
41 | * mutex_lock(sysfs_mutex) | 84 | * mutex_lock(sysfs_mutex) |
85 | * | ||
86 | * RETURNS: | ||
87 | * 0 on susccess -EEXIST on failure. | ||
42 | */ | 88 | */ |
43 | static void sysfs_link_sibling(struct sysfs_dirent *sd) | 89 | static int sysfs_link_sibling(struct sysfs_dirent *sd) |
44 | { | 90 | { |
45 | struct sysfs_dirent *parent_sd = sd->s_parent; | 91 | struct rb_node **node = &sd->s_parent->s_dir.children.rb_node; |
46 | 92 | struct rb_node *parent = NULL; | |
47 | struct rb_node **p; | 93 | |
48 | struct rb_node *parent; | 94 | while (*node) { |
49 | 95 | struct sysfs_dirent *pos; | |
50 | if (sysfs_type(sd) == SYSFS_DIR) | 96 | int result; |
51 | parent_sd->s_dir.subdirs++; | 97 | |
52 | 98 | pos = to_sysfs_dirent(*node); | |
53 | p = &parent_sd->s_dir.inode_tree.rb_node; | 99 | parent = *node; |
54 | parent = NULL; | 100 | result = sysfs_sd_compare(sd, pos); |
55 | while (*p) { | 101 | if (result < 0) |
56 | parent = *p; | 102 | node = &pos->s_rb.rb_left; |
57 | #define node rb_entry(parent, struct sysfs_dirent, inode_node) | 103 | else if (result > 0) |
58 | if (sd->s_ino < node->s_ino) { | 104 | node = &pos->s_rb.rb_right; |
59 | p = &node->inode_node.rb_left; | 105 | else |
60 | } else if (sd->s_ino > node->s_ino) { | 106 | return -EEXIST; |
61 | p = &node->inode_node.rb_right; | ||
62 | } else { | ||
63 | printk(KERN_CRIT "sysfs: inserting duplicate inode '%lx'\n", | ||
64 | (unsigned long) sd->s_ino); | ||
65 | BUG(); | ||
66 | } | ||
67 | #undef node | ||
68 | } | ||
69 | rb_link_node(&sd->inode_node, parent, p); | ||
70 | rb_insert_color(&sd->inode_node, &parent_sd->s_dir.inode_tree); | ||
71 | |||
72 | p = &parent_sd->s_dir.name_tree.rb_node; | ||
73 | parent = NULL; | ||
74 | while (*p) { | ||
75 | int c; | ||
76 | parent = *p; | ||
77 | #define node rb_entry(parent, struct sysfs_dirent, name_node) | ||
78 | c = strcmp(sd->s_name, node->s_name); | ||
79 | if (c < 0) { | ||
80 | p = &node->name_node.rb_left; | ||
81 | } else { | ||
82 | p = &node->name_node.rb_right; | ||
83 | } | ||
84 | #undef node | ||
85 | } | 107 | } |
86 | rb_link_node(&sd->name_node, parent, p); | 108 | /* add new node and rebalance the tree */ |
87 | rb_insert_color(&sd->name_node, &parent_sd->s_dir.name_tree); | 109 | rb_link_node(&sd->s_rb, parent, node); |
110 | rb_insert_color(&sd->s_rb, &sd->s_parent->s_dir.children); | ||
111 | return 0; | ||
88 | } | 112 | } |
89 | 113 | ||
90 | /** | 114 | /** |
91 | * sysfs_unlink_sibling - unlink sysfs_dirent from sibling list | 115 | * sysfs_unlink_sibling - unlink sysfs_dirent from sibling rbtree |
92 | * @sd: sysfs_dirent of interest | 116 | * @sd: sysfs_dirent of interest |
93 | * | 117 | * |
94 | * Unlink @sd from its sibling list which starts from | 118 | * Unlink @sd from its sibling rbtree which starts from |
95 | * sd->s_parent->s_dir.children. | 119 | * sd->s_parent->s_dir.children. |
96 | * | 120 | * |
97 | * Locking: | 121 | * Locking: |
@@ -99,11 +123,7 @@ static void sysfs_link_sibling(struct sysfs_dirent *sd) | |||
99 | */ | 123 | */ |
100 | static void sysfs_unlink_sibling(struct sysfs_dirent *sd) | 124 | static void sysfs_unlink_sibling(struct sysfs_dirent *sd) |
101 | { | 125 | { |
102 | if (sysfs_type(sd) == SYSFS_DIR) | 126 | rb_erase(&sd->s_rb, &sd->s_parent->s_dir.children); |
103 | sd->s_parent->s_dir.subdirs--; | ||
104 | |||
105 | rb_erase(&sd->inode_node, &sd->s_parent->s_dir.inode_tree); | ||
106 | rb_erase(&sd->name_node, &sd->s_parent->s_dir.name_tree); | ||
107 | } | 127 | } |
108 | 128 | ||
109 | /** | 129 | /** |
@@ -198,7 +218,7 @@ static void sysfs_deactivate(struct sysfs_dirent *sd) | |||
198 | rwsem_release(&sd->dep_map, 1, _RET_IP_); | 218 | rwsem_release(&sd->dep_map, 1, _RET_IP_); |
199 | } | 219 | } |
200 | 220 | ||
201 | static int sysfs_alloc_ino(ino_t *pino) | 221 | static int sysfs_alloc_ino(unsigned int *pino) |
202 | { | 222 | { |
203 | int ino, rc; | 223 | int ino, rc; |
204 | 224 | ||
@@ -217,7 +237,7 @@ static int sysfs_alloc_ino(ino_t *pino) | |||
217 | return rc; | 237 | return rc; |
218 | } | 238 | } |
219 | 239 | ||
220 | static void sysfs_free_ino(ino_t ino) | 240 | static void sysfs_free_ino(unsigned int ino) |
221 | { | 241 | { |
222 | spin_lock(&sysfs_ino_lock); | 242 | spin_lock(&sysfs_ino_lock); |
223 | ida_remove(&sysfs_ino_ida, ino); | 243 | ida_remove(&sysfs_ino_ida, ino); |
@@ -402,6 +422,7 @@ void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt, | |||
402 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | 422 | int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) |
403 | { | 423 | { |
404 | struct sysfs_inode_attrs *ps_iattr; | 424 | struct sysfs_inode_attrs *ps_iattr; |
425 | int ret; | ||
405 | 426 | ||
406 | if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) { | 427 | if (!!sysfs_ns_type(acxt->parent_sd) != !!sd->s_ns) { |
407 | WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", | 428 | WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", |
@@ -410,12 +431,12 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
410 | return -EINVAL; | 431 | return -EINVAL; |
411 | } | 432 | } |
412 | 433 | ||
413 | if (sysfs_find_dirent(acxt->parent_sd, sd->s_ns, sd->s_name)) | 434 | sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name); |
414 | return -EEXIST; | ||
415 | |||
416 | sd->s_parent = sysfs_get(acxt->parent_sd); | 435 | sd->s_parent = sysfs_get(acxt->parent_sd); |
417 | 436 | ||
418 | sysfs_link_sibling(sd); | 437 | ret = sysfs_link_sibling(sd); |
438 | if (ret) | ||
439 | return ret; | ||
419 | 440 | ||
420 | /* Update timestamps on the parent */ | 441 | /* Update timestamps on the parent */ |
421 | ps_iattr = acxt->parent_sd->s_iattr; | 442 | ps_iattr = acxt->parent_sd->s_iattr; |
@@ -565,8 +586,8 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | |||
565 | const void *ns, | 586 | const void *ns, |
566 | const unsigned char *name) | 587 | const unsigned char *name) |
567 | { | 588 | { |
568 | struct rb_node *p = parent_sd->s_dir.name_tree.rb_node; | 589 | struct rb_node *node = parent_sd->s_dir.children.rb_node; |
569 | struct sysfs_dirent *found = NULL; | 590 | unsigned int hash; |
570 | 591 | ||
571 | if (!!sysfs_ns_type(parent_sd) != !!ns) { | 592 | if (!!sysfs_ns_type(parent_sd) != !!ns) { |
572 | WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", | 593 | WARN(1, KERN_WARNING "sysfs: ns %s in '%s' for '%s'\n", |
@@ -575,33 +596,21 @@ struct sysfs_dirent *sysfs_find_dirent(struct sysfs_dirent *parent_sd, | |||
575 | return NULL; | 596 | return NULL; |
576 | } | 597 | } |
577 | 598 | ||
578 | while (p) { | 599 | hash = sysfs_name_hash(ns, name); |
579 | int c; | 600 | while (node) { |
580 | #define node rb_entry(p, struct sysfs_dirent, name_node) | 601 | struct sysfs_dirent *sd; |
581 | c = strcmp(name, node->s_name); | 602 | int result; |
582 | if (c < 0) { | 603 | |
583 | p = node->name_node.rb_left; | 604 | sd = to_sysfs_dirent(node); |
584 | } else if (c > 0) { | 605 | result = sysfs_name_compare(hash, ns, name, sd); |
585 | p = node->name_node.rb_right; | 606 | if (result < 0) |
586 | } else { | 607 | node = node->rb_left; |
587 | found = node; | 608 | else if (result > 0) |
588 | p = node->name_node.rb_left; | 609 | node = node->rb_right; |
589 | } | 610 | else |
590 | #undef node | 611 | return sd; |
591 | } | ||
592 | |||
593 | if (found) { | ||
594 | while (found->s_ns != ns) { | ||
595 | p = rb_next(&found->name_node); | ||
596 | if (!p) | ||
597 | return NULL; | ||
598 | found = rb_entry(p, struct sysfs_dirent, name_node); | ||
599 | if (strcmp(name, found->s_name)) | ||
600 | return NULL; | ||
601 | } | ||
602 | } | 612 | } |
603 | 613 | return NULL; | |
604 | return found; | ||
605 | } | 614 | } |
606 | 615 | ||
607 | /** | 616 | /** |
@@ -804,9 +813,9 @@ static void __sysfs_remove_dir(struct sysfs_dirent *dir_sd) | |||
804 | 813 | ||
805 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); | 814 | pr_debug("sysfs %s: removing dir\n", dir_sd->s_name); |
806 | sysfs_addrm_start(&acxt, dir_sd); | 815 | sysfs_addrm_start(&acxt, dir_sd); |
807 | pos = rb_first(&dir_sd->s_dir.inode_tree); | 816 | pos = rb_first(&dir_sd->s_dir.children); |
808 | while (pos) { | 817 | while (pos) { |
809 | struct sysfs_dirent *sd = rb_entry(pos, struct sysfs_dirent, inode_node); | 818 | struct sysfs_dirent *sd = to_sysfs_dirent(pos); |
810 | pos = rb_next(pos); | 819 | pos = rb_next(pos); |
811 | if (sysfs_type(sd) != SYSFS_DIR) | 820 | if (sysfs_type(sd) != SYSFS_DIR) |
812 | sysfs_remove_one(&acxt, sd); | 821 | sysfs_remove_one(&acxt, sd); |
@@ -863,6 +872,7 @@ int sysfs_rename(struct sysfs_dirent *sd, | |||
863 | 872 | ||
864 | dup_name = sd->s_name; | 873 | dup_name = sd->s_name; |
865 | sd->s_name = new_name; | 874 | sd->s_name = new_name; |
875 | sd->s_hash = sysfs_name_hash(sd->s_ns, sd->s_name); | ||
866 | } | 876 | } |
867 | 877 | ||
868 | /* Move to the appropriate place in the appropriate directories rbtree. */ | 878 | /* Move to the appropriate place in the appropriate directories rbtree. */ |
@@ -919,38 +929,36 @@ static int sysfs_dir_release(struct inode *inode, struct file *filp) | |||
919 | } | 929 | } |
920 | 930 | ||
921 | static struct sysfs_dirent *sysfs_dir_pos(const void *ns, | 931 | static struct sysfs_dirent *sysfs_dir_pos(const void *ns, |
922 | struct sysfs_dirent *parent_sd, ino_t ino, struct sysfs_dirent *pos) | 932 | struct sysfs_dirent *parent_sd, loff_t hash, struct sysfs_dirent *pos) |
923 | { | 933 | { |
924 | if (pos) { | 934 | if (pos) { |
925 | int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && | 935 | int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) && |
926 | pos->s_parent == parent_sd && | 936 | pos->s_parent == parent_sd && |
927 | ino == pos->s_ino; | 937 | hash == pos->s_hash; |
928 | sysfs_put(pos); | 938 | sysfs_put(pos); |
929 | if (!valid) | 939 | if (!valid) |
930 | pos = NULL; | 940 | pos = NULL; |
931 | } | 941 | } |
932 | if (!pos && (ino > 1) && (ino < INT_MAX)) { | 942 | if (!pos && (hash > 1) && (hash < INT_MAX)) { |
933 | struct rb_node *p = parent_sd->s_dir.inode_tree.rb_node; | 943 | struct rb_node *node = parent_sd->s_dir.children.rb_node; |
934 | while (p) { | 944 | while (node) { |
935 | #define node rb_entry(p, struct sysfs_dirent, inode_node) | 945 | pos = to_sysfs_dirent(node); |
936 | if (ino < node->s_ino) { | 946 | |
937 | pos = node; | 947 | if (hash < pos->s_hash) |
938 | p = node->inode_node.rb_left; | 948 | node = node->rb_left; |
939 | } else if (ino > node->s_ino) { | 949 | else if (hash > pos->s_hash) |
940 | p = node->inode_node.rb_right; | 950 | node = node->rb_right; |
941 | } else { | 951 | else |
942 | pos = node; | ||
943 | break; | 952 | break; |
944 | } | ||
945 | #undef node | ||
946 | } | 953 | } |
947 | } | 954 | } |
955 | /* Skip over entries in the wrong namespace */ | ||
948 | while (pos && pos->s_ns != ns) { | 956 | while (pos && pos->s_ns != ns) { |
949 | struct rb_node *p = rb_next(&pos->inode_node); | 957 | struct rb_node *node = rb_next(&pos->s_rb); |
950 | if (!p) | 958 | if (!node) |
951 | pos = NULL; | 959 | pos = NULL; |
952 | else | 960 | else |
953 | pos = rb_entry(p, struct sysfs_dirent, inode_node); | 961 | pos = to_sysfs_dirent(node); |
954 | } | 962 | } |
955 | return pos; | 963 | return pos; |
956 | } | 964 | } |
@@ -960,11 +968,11 @@ static struct sysfs_dirent *sysfs_dir_next_pos(const void *ns, | |||
960 | { | 968 | { |
961 | pos = sysfs_dir_pos(ns, parent_sd, ino, pos); | 969 | pos = sysfs_dir_pos(ns, parent_sd, ino, pos); |
962 | if (pos) do { | 970 | if (pos) do { |
963 | struct rb_node *p = rb_next(&pos->inode_node); | 971 | struct rb_node *node = rb_next(&pos->s_rb); |
964 | if (!p) | 972 | if (!node) |
965 | pos = NULL; | 973 | pos = NULL; |
966 | else | 974 | else |
967 | pos = rb_entry(p, struct sysfs_dirent, inode_node); | 975 | pos = to_sysfs_dirent(node); |
968 | } while (pos && pos->s_ns != ns); | 976 | } while (pos && pos->s_ns != ns); |
969 | return pos; | 977 | return pos; |
970 | } | 978 | } |
@@ -1006,7 +1014,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) | |||
1006 | len = strlen(name); | 1014 | len = strlen(name); |
1007 | ino = pos->s_ino; | 1015 | ino = pos->s_ino; |
1008 | type = dt_type(pos); | 1016 | type = dt_type(pos); |
1009 | filp->f_pos = ino; | 1017 | filp->f_pos = pos->s_hash; |
1010 | filp->private_data = sysfs_get(pos); | 1018 | filp->private_data = sysfs_get(pos); |
1011 | 1019 | ||
1012 | mutex_unlock(&sysfs_mutex); | 1020 | mutex_unlock(&sysfs_mutex); |
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c index 85eb81683a29..4291fd1617ab 100644 --- a/fs/sysfs/inode.c +++ b/fs/sysfs/inode.c | |||
@@ -216,9 +216,6 @@ static void sysfs_refresh_inode(struct sysfs_dirent *sd, struct inode *inode) | |||
216 | iattrs->ia_secdata, | 216 | iattrs->ia_secdata, |
217 | iattrs->ia_secdata_len); | 217 | iattrs->ia_secdata_len); |
218 | } | 218 | } |
219 | |||
220 | if (sysfs_type(sd) == SYSFS_DIR) | ||
221 | set_nlink(inode, sd->s_dir.subdirs + 2); | ||
222 | } | 219 | } |
223 | 220 | ||
224 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 221 | int sysfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index e34f0d99ea4e..140f26a34288 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -36,7 +36,7 @@ struct sysfs_dirent sysfs_root = { | |||
36 | .s_name = "", | 36 | .s_name = "", |
37 | .s_count = ATOMIC_INIT(1), | 37 | .s_count = ATOMIC_INIT(1), |
38 | .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), | 38 | .s_flags = SYSFS_DIR | (KOBJ_NS_TYPE_NONE << SYSFS_NS_TYPE_SHIFT), |
39 | .s_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO, | 39 | .s_mode = S_IFDIR | S_IRUGO | S_IXUGO, |
40 | .s_ino = 1, | 40 | .s_ino = 1, |
41 | }; | 41 | }; |
42 | 42 | ||
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 7484a36ee678..6289a00287db 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
@@ -19,10 +19,8 @@ struct sysfs_open_dirent; | |||
19 | struct sysfs_elem_dir { | 19 | struct sysfs_elem_dir { |
20 | struct kobject *kobj; | 20 | struct kobject *kobj; |
21 | 21 | ||
22 | unsigned long subdirs; | 22 | /* children rbtree starts here and goes through sd->s_rb */ |
23 | 23 | struct rb_root children; | |
24 | struct rb_root inode_tree; | ||
25 | struct rb_root name_tree; | ||
26 | }; | 24 | }; |
27 | 25 | ||
28 | struct sysfs_elem_symlink { | 26 | struct sysfs_elem_symlink { |
@@ -62,8 +60,7 @@ struct sysfs_dirent { | |||
62 | struct sysfs_dirent *s_parent; | 60 | struct sysfs_dirent *s_parent; |
63 | const char *s_name; | 61 | const char *s_name; |
64 | 62 | ||
65 | struct rb_node inode_node; | 63 | struct rb_node s_rb; |
66 | struct rb_node name_node; | ||
67 | 64 | ||
68 | union { | 65 | union { |
69 | struct completion *completion; | 66 | struct completion *completion; |
@@ -71,6 +68,7 @@ struct sysfs_dirent { | |||
71 | } u; | 68 | } u; |
72 | 69 | ||
73 | const void *s_ns; /* namespace tag */ | 70 | const void *s_ns; /* namespace tag */ |
71 | unsigned int s_hash; /* ns + name hash */ | ||
74 | union { | 72 | union { |
75 | struct sysfs_elem_dir s_dir; | 73 | struct sysfs_elem_dir s_dir; |
76 | struct sysfs_elem_symlink s_symlink; | 74 | struct sysfs_elem_symlink s_symlink; |
@@ -78,9 +76,9 @@ struct sysfs_dirent { | |||
78 | struct sysfs_elem_bin_attr s_bin_attr; | 76 | struct sysfs_elem_bin_attr s_bin_attr; |
79 | }; | 77 | }; |
80 | 78 | ||
81 | unsigned int s_flags; | 79 | unsigned short s_flags; |
82 | umode_t s_mode; | 80 | umode_t s_mode; |
83 | ino_t s_ino; | 81 | unsigned int s_ino; |
84 | struct sysfs_inode_attrs *s_iattr; | 82 | struct sysfs_inode_attrs *s_iattr; |
85 | }; | 83 | }; |
86 | 84 | ||
@@ -95,11 +93,11 @@ struct sysfs_dirent { | |||
95 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) | 93 | #define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR) |
96 | 94 | ||
97 | /* identify any namespace tag on sysfs_dirents */ | 95 | /* identify any namespace tag on sysfs_dirents */ |
98 | #define SYSFS_NS_TYPE_MASK 0xff00 | 96 | #define SYSFS_NS_TYPE_MASK 0xf00 |
99 | #define SYSFS_NS_TYPE_SHIFT 8 | 97 | #define SYSFS_NS_TYPE_SHIFT 8 |
100 | 98 | ||
101 | #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) | 99 | #define SYSFS_FLAG_MASK ~(SYSFS_NS_TYPE_MASK|SYSFS_TYPE_MASK) |
102 | #define SYSFS_FLAG_REMOVED 0x020000 | 100 | #define SYSFS_FLAG_REMOVED 0x02000 |
103 | 101 | ||
104 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) | 102 | static inline unsigned int sysfs_type(struct sysfs_dirent *sd) |
105 | { | 103 | { |
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 8cf7e98a2c7b..9d650476d5dc 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
@@ -225,6 +225,7 @@ struct acpi_processor_errata { | |||
225 | } piix4; | 225 | } piix4; |
226 | }; | 226 | }; |
227 | 227 | ||
228 | extern void acpi_processor_load_module(struct acpi_processor *pr); | ||
228 | extern int acpi_processor_preregister_performance(struct | 229 | extern int acpi_processor_preregister_performance(struct |
229 | acpi_processor_performance | 230 | acpi_processor_performance |
230 | __percpu *performance); | 231 | __percpu *performance); |
diff --git a/include/linux/connector.h b/include/linux/connector.h index 3c9c54fd5690..76384074262d 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h | |||
@@ -43,6 +43,7 @@ | |||
43 | #define CN_IDX_DRBD 0x8 | 43 | #define CN_IDX_DRBD 0x8 |
44 | #define CN_VAL_DRBD 0x1 | 44 | #define CN_VAL_DRBD 0x1 |
45 | #define CN_KVP_IDX 0x9 /* HyperV KVP */ | 45 | #define CN_KVP_IDX 0x9 /* HyperV KVP */ |
46 | #define CN_KVP_VAL 0x1 /* queries from the kernel */ | ||
46 | 47 | ||
47 | #define CN_NETLINK_USERS 10 /* Highest index + 1 */ | 48 | #define CN_NETLINK_USERS 10 /* Highest index + 1 */ |
48 | 49 | ||
diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 1f6587590a1a..6e53b4823d7f 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h | |||
@@ -44,6 +44,13 @@ extern ssize_t arch_cpu_release(const char *, size_t); | |||
44 | #endif | 44 | #endif |
45 | struct notifier_block; | 45 | struct notifier_block; |
46 | 46 | ||
47 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
48 | extern int arch_cpu_uevent(struct device *dev, struct kobj_uevent_env *env); | ||
49 | extern ssize_t arch_print_cpu_modalias(struct device *dev, | ||
50 | struct device_attribute *attr, | ||
51 | char *bufptr); | ||
52 | #endif | ||
53 | |||
47 | /* | 54 | /* |
48 | * CPU notifier priorities. | 55 | * CPU notifier priorities. |
49 | */ | 56 | */ |
diff --git a/include/linux/device.h b/include/linux/device.h index b63fb393aa58..f62e21689fdd 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -238,8 +238,6 @@ struct device_driver { | |||
238 | extern int __must_check driver_register(struct device_driver *drv); | 238 | extern int __must_check driver_register(struct device_driver *drv); |
239 | extern void driver_unregister(struct device_driver *drv); | 239 | extern void driver_unregister(struct device_driver *drv); |
240 | 240 | ||
241 | extern struct device_driver *get_driver(struct device_driver *drv); | ||
242 | extern void put_driver(struct device_driver *drv); | ||
243 | extern struct device_driver *driver_find(const char *name, | 241 | extern struct device_driver *driver_find(const char *name, |
244 | struct bus_type *bus); | 242 | struct bus_type *bus); |
245 | extern int driver_probe_done(void); | 243 | extern int driver_probe_done(void); |
@@ -946,14 +944,14 @@ int _dev_info(const struct device *dev, const char *fmt, ...) | |||
946 | 944 | ||
947 | #define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg) | 945 | #define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg) |
948 | 946 | ||
949 | #if defined(DEBUG) | 947 | #if defined(CONFIG_DYNAMIC_DEBUG) |
950 | #define dev_dbg(dev, format, arg...) \ | ||
951 | dev_printk(KERN_DEBUG, dev, format, ##arg) | ||
952 | #elif defined(CONFIG_DYNAMIC_DEBUG) | ||
953 | #define dev_dbg(dev, format, ...) \ | 948 | #define dev_dbg(dev, format, ...) \ |
954 | do { \ | 949 | do { \ |
955 | dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ | 950 | dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \ |
956 | } while (0) | 951 | } while (0) |
952 | #elif defined(DEBUG) | ||
953 | #define dev_dbg(dev, format, arg...) \ | ||
954 | dev_printk(KERN_DEBUG, dev, format, ##arg) | ||
957 | #else | 955 | #else |
958 | #define dev_dbg(dev, format, arg...) \ | 956 | #define dev_dbg(dev, format, arg...) \ |
959 | ({ \ | 957 | ({ \ |
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index 0564e3c39882..7e3c53a900d8 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h | |||
@@ -15,20 +15,24 @@ struct _ddebug { | |||
15 | const char *function; | 15 | const char *function; |
16 | const char *filename; | 16 | const char *filename; |
17 | const char *format; | 17 | const char *format; |
18 | unsigned int lineno:24; | 18 | unsigned int lineno:18; |
19 | /* | 19 | /* |
20 | * The flags field controls the behaviour at the callsite. | 20 | * The flags field controls the behaviour at the callsite. |
21 | * The bits here are changed dynamically when the user | 21 | * The bits here are changed dynamically when the user |
22 | * writes commands to <debugfs>/dynamic_debug/control | 22 | * writes commands to <debugfs>/dynamic_debug/control |
23 | */ | 23 | */ |
24 | #define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */ | 24 | #define _DPRINTK_FLAGS_NONE 0 |
25 | #define _DPRINTK_FLAGS_PRINT (1<<0) /* printk() a message using the format */ | ||
25 | #define _DPRINTK_FLAGS_INCL_MODNAME (1<<1) | 26 | #define _DPRINTK_FLAGS_INCL_MODNAME (1<<1) |
26 | #define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2) | 27 | #define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2) |
27 | #define _DPRINTK_FLAGS_INCL_LINENO (1<<3) | 28 | #define _DPRINTK_FLAGS_INCL_LINENO (1<<3) |
28 | #define _DPRINTK_FLAGS_INCL_TID (1<<4) | 29 | #define _DPRINTK_FLAGS_INCL_TID (1<<4) |
30 | #if defined DEBUG | ||
31 | #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT | ||
32 | #else | ||
29 | #define _DPRINTK_FLAGS_DEFAULT 0 | 33 | #define _DPRINTK_FLAGS_DEFAULT 0 |
34 | #endif | ||
30 | unsigned int flags:8; | 35 | unsigned int flags:8; |
31 | char enabled; | ||
32 | } __attribute__((aligned(8))); | 36 | } __attribute__((aligned(8))); |
33 | 37 | ||
34 | 38 | ||
@@ -62,21 +66,20 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor, | |||
62 | .format = (fmt), \ | 66 | .format = (fmt), \ |
63 | .lineno = __LINE__, \ | 67 | .lineno = __LINE__, \ |
64 | .flags = _DPRINTK_FLAGS_DEFAULT, \ | 68 | .flags = _DPRINTK_FLAGS_DEFAULT, \ |
65 | .enabled = false, \ | ||
66 | } | 69 | } |
67 | 70 | ||
68 | #define dynamic_pr_debug(fmt, ...) \ | 71 | #define dynamic_pr_debug(fmt, ...) \ |
69 | do { \ | 72 | do { \ |
70 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ | 73 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ |
71 | if (unlikely(descriptor.enabled)) \ | 74 | if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ |
72 | __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \ | 75 | __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \ |
73 | ##__VA_ARGS__); \ | 76 | ##__VA_ARGS__); \ |
74 | } while (0) | 77 | } while (0) |
75 | 78 | ||
76 | #define dynamic_dev_dbg(dev, fmt, ...) \ | 79 | #define dynamic_dev_dbg(dev, fmt, ...) \ |
77 | do { \ | 80 | do { \ |
78 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ | 81 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ |
79 | if (unlikely(descriptor.enabled)) \ | 82 | if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ |
80 | __dynamic_dev_dbg(&descriptor, dev, fmt, \ | 83 | __dynamic_dev_dbg(&descriptor, dev, fmt, \ |
81 | ##__VA_ARGS__); \ | 84 | ##__VA_ARGS__); \ |
82 | } while (0) | 85 | } while (0) |
@@ -84,7 +87,7 @@ do { \ | |||
84 | #define dynamic_netdev_dbg(dev, fmt, ...) \ | 87 | #define dynamic_netdev_dbg(dev, fmt, ...) \ |
85 | do { \ | 88 | do { \ |
86 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ | 89 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \ |
87 | if (unlikely(descriptor.enabled)) \ | 90 | if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ |
88 | __dynamic_netdev_dbg(&descriptor, dev, fmt, \ | 91 | __dynamic_netdev_dbg(&descriptor, dev, fmt, \ |
89 | ##__VA_ARGS__); \ | 92 | ##__VA_ARGS__); \ |
90 | } while (0) | 93 | } while (0) |
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 0ae065a5fcb2..e57a6c6ee0e8 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h | |||
@@ -25,6 +25,147 @@ | |||
25 | #ifndef _HYPERV_H | 25 | #ifndef _HYPERV_H |
26 | #define _HYPERV_H | 26 | #define _HYPERV_H |
27 | 27 | ||
28 | #include <linux/types.h> | ||
29 | |||
30 | /* | ||
31 | * An implementation of HyperV key value pair (KVP) functionality for Linux. | ||
32 | * | ||
33 | * | ||
34 | * Copyright (C) 2010, Novell, Inc. | ||
35 | * Author : K. Y. Srinivasan <ksrinivasan@novell.com> | ||
36 | * | ||
37 | */ | ||
38 | |||
39 | /* | ||
40 | * Maximum value size - used for both key names and value data, and includes | ||
41 | * any applicable NULL terminators. | ||
42 | * | ||
43 | * Note: This limit is somewhat arbitrary, but falls easily within what is | ||
44 | * supported for all native guests (back to Win 2000) and what is reasonable | ||
45 | * for the IC KVP exchange functionality. Note that Windows Me/98/95 are | ||
46 | * limited to 255 character key names. | ||
47 | * | ||
48 | * MSDN recommends not storing data values larger than 2048 bytes in the | ||
49 | * registry. | ||
50 | * | ||
51 | * Note: This value is used in defining the KVP exchange message - this value | ||
52 | * cannot be modified without affecting the message size and compatibility. | ||
53 | */ | ||
54 | |||
55 | /* | ||
56 | * bytes, including any null terminators | ||
57 | */ | ||
58 | #define HV_KVP_EXCHANGE_MAX_VALUE_SIZE (2048) | ||
59 | |||
60 | |||
61 | /* | ||
62 | * Maximum key size - the registry limit for the length of an entry name | ||
63 | * is 256 characters, including the null terminator | ||
64 | */ | ||
65 | |||
66 | #define HV_KVP_EXCHANGE_MAX_KEY_SIZE (512) | ||
67 | |||
68 | /* | ||
69 | * In Linux, we implement the KVP functionality in two components: | ||
70 | * 1) The kernel component which is packaged as part of the hv_utils driver | ||
71 | * is responsible for communicating with the host and responsible for | ||
72 | * implementing the host/guest protocol. 2) A user level daemon that is | ||
73 | * responsible for data gathering. | ||
74 | * | ||
75 | * Host/Guest Protocol: The host iterates over an index and expects the guest | ||
76 | * to assign a key name to the index and also return the value corresponding to | ||
77 | * the key. The host will have atmost one KVP transaction outstanding at any | ||
78 | * given point in time. The host side iteration stops when the guest returns | ||
79 | * an error. Microsoft has specified the following mapping of key names to | ||
80 | * host specified index: | ||
81 | * | ||
82 | * Index Key Name | ||
83 | * 0 FullyQualifiedDomainName | ||
84 | * 1 IntegrationServicesVersion | ||
85 | * 2 NetworkAddressIPv4 | ||
86 | * 3 NetworkAddressIPv6 | ||
87 | * 4 OSBuildNumber | ||
88 | * 5 OSName | ||
89 | * 6 OSMajorVersion | ||
90 | * 7 OSMinorVersion | ||
91 | * 8 OSVersion | ||
92 | * 9 ProcessorArchitecture | ||
93 | * | ||
94 | * The Windows host expects the Key Name and Key Value to be encoded in utf16. | ||
95 | * | ||
96 | * Guest Kernel/KVP Daemon Protocol: As noted earlier, we implement all of the | ||
97 | * data gathering functionality in a user mode daemon. The user level daemon | ||
98 | * is also responsible for binding the key name to the index as well. The | ||
99 | * kernel and user-level daemon communicate using a connector channel. | ||
100 | * | ||
101 | * The user mode component first registers with the | ||
102 | * the kernel component. Subsequently, the kernel component requests, data | ||
103 | * for the specified keys. In response to this message the user mode component | ||
104 | * fills in the value corresponding to the specified key. We overload the | ||
105 | * sequence field in the cn_msg header to define our KVP message types. | ||
106 | * | ||
107 | * | ||
108 | * The kernel component simply acts as a conduit for communication between the | ||
109 | * Windows host and the user-level daemon. The kernel component passes up the | ||
110 | * index received from the Host to the user-level daemon. If the index is | ||
111 | * valid (supported), the corresponding key as well as its | ||
112 | * value (both are strings) is returned. If the index is invalid | ||
113 | * (not supported), a NULL key string is returned. | ||
114 | */ | ||
115 | |||
116 | |||
117 | /* | ||
118 | * Registry value types. | ||
119 | */ | ||
120 | |||
121 | #define REG_SZ 1 | ||
122 | |||
123 | enum hv_kvp_exchg_op { | ||
124 | KVP_OP_GET = 0, | ||
125 | KVP_OP_SET, | ||
126 | KVP_OP_DELETE, | ||
127 | KVP_OP_ENUMERATE, | ||
128 | KVP_OP_REGISTER, | ||
129 | KVP_OP_COUNT /* Number of operations, must be last. */ | ||
130 | }; | ||
131 | |||
132 | enum hv_kvp_exchg_pool { | ||
133 | KVP_POOL_EXTERNAL = 0, | ||
134 | KVP_POOL_GUEST, | ||
135 | KVP_POOL_AUTO, | ||
136 | KVP_POOL_AUTO_EXTERNAL, | ||
137 | KVP_POOL_AUTO_INTERNAL, | ||
138 | KVP_POOL_COUNT /* Number of pools, must be last. */ | ||
139 | }; | ||
140 | |||
141 | struct hv_kvp_hdr { | ||
142 | __u8 operation; | ||
143 | __u8 pool; | ||
144 | __u16 pad; | ||
145 | } __attribute__((packed)); | ||
146 | |||
147 | struct hv_kvp_exchg_msg_value { | ||
148 | __u32 value_type; | ||
149 | __u32 key_size; | ||
150 | __u32 value_size; | ||
151 | __u8 key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; | ||
152 | __u8 value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; | ||
153 | } __attribute__((packed)); | ||
154 | |||
155 | struct hv_kvp_msg_enumerate { | ||
156 | __u32 index; | ||
157 | struct hv_kvp_exchg_msg_value data; | ||
158 | } __attribute__((packed)); | ||
159 | |||
160 | struct hv_kvp_msg { | ||
161 | struct hv_kvp_hdr kvp_hdr; | ||
162 | union { | ||
163 | struct hv_kvp_msg_enumerate kvp_enum_data; | ||
164 | char kvp_version[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; | ||
165 | } body; | ||
166 | } __attribute__((packed)); | ||
167 | |||
168 | #ifdef __KERNEL__ | ||
28 | #include <linux/scatterlist.h> | 169 | #include <linux/scatterlist.h> |
29 | #include <linux/list.h> | 170 | #include <linux/list.h> |
30 | #include <linux/uuid.h> | 171 | #include <linux/uuid.h> |
@@ -870,4 +1011,9 @@ struct hyperv_service_callback { | |||
870 | extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, | 1011 | extern void vmbus_prep_negotiate_resp(struct icmsg_hdr *, |
871 | struct icmsg_negotiate *, u8 *); | 1012 | struct icmsg_negotiate *, u8 *); |
872 | 1013 | ||
1014 | int hv_kvp_init(struct hv_util_service *); | ||
1015 | void hv_kvp_deinit(void); | ||
1016 | void hv_kvp_onchannelcallback(void *); | ||
1017 | |||
1018 | #endif /* __KERNEL__ */ | ||
873 | #endif /* _HYPERV_H */ | 1019 | #endif /* _HYPERV_H */ |
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 83ac0713ed0a..fb69ad191ad7 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -560,4 +560,25 @@ struct amba_id { | |||
560 | #endif | 560 | #endif |
561 | }; | 561 | }; |
562 | 562 | ||
563 | /* | ||
564 | * Match x86 CPUs for CPU specific drivers. | ||
565 | * See documentation of "x86_match_cpu" for details. | ||
566 | */ | ||
567 | |||
568 | struct x86_cpu_id { | ||
569 | __u16 vendor; | ||
570 | __u16 family; | ||
571 | __u16 model; | ||
572 | __u16 feature; /* bit index */ | ||
573 | kernel_ulong_t driver_data; | ||
574 | }; | ||
575 | |||
576 | #define X86_FEATURE_MATCH(x) \ | ||
577 | { X86_VENDOR_ANY, X86_FAMILY_ANY, X86_MODEL_ANY, x } | ||
578 | |||
579 | #define X86_VENDOR_ANY 0xffff | ||
580 | #define X86_FAMILY_ANY 0 | ||
581 | #define X86_MODEL_ANY 0 | ||
582 | #define X86_FEATURE_ANY 0 /* Same as FPU, you can't test for that */ | ||
583 | |||
563 | #endif /* LINUX_MOD_DEVICETABLE_H */ | 584 | #endif /* LINUX_MOD_DEVICETABLE_H */ |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0eac07c95255..f486f635e7b5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -2687,14 +2687,14 @@ int netdev_info(const struct net_device *dev, const char *format, ...); | |||
2687 | #define MODULE_ALIAS_NETDEV(device) \ | 2687 | #define MODULE_ALIAS_NETDEV(device) \ |
2688 | MODULE_ALIAS("netdev-" device) | 2688 | MODULE_ALIAS("netdev-" device) |
2689 | 2689 | ||
2690 | #if defined(DEBUG) | 2690 | #if defined(CONFIG_DYNAMIC_DEBUG) |
2691 | #define netdev_dbg(__dev, format, args...) \ | ||
2692 | netdev_printk(KERN_DEBUG, __dev, format, ##args) | ||
2693 | #elif defined(CONFIG_DYNAMIC_DEBUG) | ||
2694 | #define netdev_dbg(__dev, format, args...) \ | 2691 | #define netdev_dbg(__dev, format, args...) \ |
2695 | do { \ | 2692 | do { \ |
2696 | dynamic_netdev_dbg(__dev, format, ##args); \ | 2693 | dynamic_netdev_dbg(__dev, format, ##args); \ |
2697 | } while (0) | 2694 | } while (0) |
2695 | #elif defined(DEBUG) | ||
2696 | #define netdev_dbg(__dev, format, args...) \ | ||
2697 | netdev_printk(KERN_DEBUG, __dev, format, ##args) | ||
2698 | #else | 2698 | #else |
2699 | #define netdev_dbg(__dev, format, args...) \ | 2699 | #define netdev_dbg(__dev, format, args...) \ |
2700 | ({ \ | 2700 | ({ \ |
diff --git a/include/linux/pci.h b/include/linux/pci.h index a16b1df3deff..d4afd703e948 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -946,6 +946,19 @@ int __must_check __pci_register_driver(struct pci_driver *, struct module *, | |||
946 | __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) | 946 | __pci_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) |
947 | 947 | ||
948 | void pci_unregister_driver(struct pci_driver *dev); | 948 | void pci_unregister_driver(struct pci_driver *dev); |
949 | |||
950 | /** | ||
951 | * module_pci_driver() - Helper macro for registering a PCI driver | ||
952 | * @__pci_driver: pci_driver struct | ||
953 | * | ||
954 | * Helper macro for PCI drivers which do not do anything special in module | ||
955 | * init/exit. This eliminates a lot of boilerplate. Each module may only | ||
956 | * use this macro once, and calling it replaces module_init() and module_exit() | ||
957 | */ | ||
958 | #define module_pci_driver(__pci_driver) \ | ||
959 | module_driver(__pci_driver, pci_register_driver, \ | ||
960 | pci_unregister_driver) | ||
961 | |||
949 | void pci_remove_behind_bridge(struct pci_dev *dev); | 962 | void pci_remove_behind_bridge(struct pci_dev *dev); |
950 | struct pci_driver *pci_dev_driver(const struct pci_dev *dev); | 963 | struct pci_driver *pci_dev_driver(const struct pci_dev *dev); |
951 | int pci_add_dynid(struct pci_driver *drv, | 964 | int pci_add_dynid(struct pci_driver *drv, |
diff --git a/include/linux/printk.h b/include/linux/printk.h index f0e22f75143f..f9abd9357a0c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h | |||
@@ -180,13 +180,13 @@ extern void dump_stack(void) __cold; | |||
180 | #endif | 180 | #endif |
181 | 181 | ||
182 | /* If you are writing a driver, please use dev_dbg instead */ | 182 | /* If you are writing a driver, please use dev_dbg instead */ |
183 | #if defined(DEBUG) | 183 | #if defined(CONFIG_DYNAMIC_DEBUG) |
184 | #define pr_debug(fmt, ...) \ | ||
185 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | ||
186 | #elif defined(CONFIG_DYNAMIC_DEBUG) | ||
187 | /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ | 184 | /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ |
188 | #define pr_debug(fmt, ...) \ | 185 | #define pr_debug(fmt, ...) \ |
189 | dynamic_pr_debug(fmt, ##__VA_ARGS__) | 186 | dynamic_pr_debug(fmt, ##__VA_ARGS__) |
187 | #elif defined(DEBUG) | ||
188 | #define pr_debug(fmt, ...) \ | ||
189 | printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | ||
190 | #else | 190 | #else |
191 | #define pr_debug(fmt, ...) \ | 191 | #define pr_debug(fmt, ...) \ |
192 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) | 192 | no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) |
diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h new file mode 100644 index 000000000000..2739ccb69571 --- /dev/null +++ b/include/linux/sys_soc.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2011 | ||
3 | * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson. | ||
4 | * License terms: GNU General Public License (GPL), version 2 | ||
5 | */ | ||
6 | #ifndef __SOC_BUS_H | ||
7 | #define __SOC_BUS_H | ||
8 | |||
9 | #include <linux/device.h> | ||
10 | |||
11 | struct soc_device_attribute { | ||
12 | const char *machine; | ||
13 | const char *family; | ||
14 | const char *revision; | ||
15 | const char *soc_id; | ||
16 | }; | ||
17 | |||
18 | /** | ||
19 | * soc_device_register - register SoC as a device | ||
20 | * @soc_plat_dev_attr: Attributes passed from platform to be attributed to a SoC | ||
21 | */ | ||
22 | struct soc_device *soc_device_register( | ||
23 | struct soc_device_attribute *soc_plat_dev_attr); | ||
24 | |||
25 | /** | ||
26 | * soc_device_unregister - unregister SoC device | ||
27 | * @dev: SoC device to be unregistered | ||
28 | */ | ||
29 | void soc_device_unregister(struct soc_device *soc_dev); | ||
30 | |||
31 | /** | ||
32 | * soc_device_to_device - helper function to fetch struct device | ||
33 | * @soc: Previously registered SoC device container | ||
34 | */ | ||
35 | struct device *soc_device_to_device(struct soc_device *soc); | ||
36 | |||
37 | #endif /* __SOC_BUS_H */ | ||
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index fea790a2b176..13ef2338be41 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -170,7 +170,7 @@ static bool driver_filter(struct device *dev) | |||
170 | return false; | 170 | return false; |
171 | 171 | ||
172 | /* driver filter on but not yet initialized */ | 172 | /* driver filter on but not yet initialized */ |
173 | drv = get_driver(dev->driver); | 173 | drv = dev->driver; |
174 | if (!drv) | 174 | if (!drv) |
175 | return false; | 175 | return false; |
176 | 176 | ||
@@ -185,7 +185,6 @@ static bool driver_filter(struct device *dev) | |||
185 | } | 185 | } |
186 | 186 | ||
187 | read_unlock_irqrestore(&driver_name_lock, flags); | 187 | read_unlock_irqrestore(&driver_name_lock, flags); |
188 | put_driver(drv); | ||
189 | 188 | ||
190 | return ret; | 189 | return ret; |
191 | } | 190 | } |
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index dcdade39e47f..310c753cf83e 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c | |||
@@ -60,6 +60,7 @@ struct ddebug_iter { | |||
60 | static DEFINE_MUTEX(ddebug_lock); | 60 | static DEFINE_MUTEX(ddebug_lock); |
61 | static LIST_HEAD(ddebug_tables); | 61 | static LIST_HEAD(ddebug_tables); |
62 | static int verbose = 0; | 62 | static int verbose = 0; |
63 | module_param(verbose, int, 0644); | ||
63 | 64 | ||
64 | /* Return the last part of a pathname */ | 65 | /* Return the last part of a pathname */ |
65 | static inline const char *basename(const char *path) | 66 | static inline const char *basename(const char *path) |
@@ -68,12 +69,24 @@ static inline const char *basename(const char *path) | |||
68 | return tail ? tail+1 : path; | 69 | return tail ? tail+1 : path; |
69 | } | 70 | } |
70 | 71 | ||
72 | /* Return the path relative to source root */ | ||
73 | static inline const char *trim_prefix(const char *path) | ||
74 | { | ||
75 | int skip = strlen(__FILE__) - strlen("lib/dynamic_debug.c"); | ||
76 | |||
77 | if (strncmp(path, __FILE__, skip)) | ||
78 | skip = 0; /* prefix mismatch, don't skip */ | ||
79 | |||
80 | return path + skip; | ||
81 | } | ||
82 | |||
71 | static struct { unsigned flag:8; char opt_char; } opt_array[] = { | 83 | static struct { unsigned flag:8; char opt_char; } opt_array[] = { |
72 | { _DPRINTK_FLAGS_PRINT, 'p' }, | 84 | { _DPRINTK_FLAGS_PRINT, 'p' }, |
73 | { _DPRINTK_FLAGS_INCL_MODNAME, 'm' }, | 85 | { _DPRINTK_FLAGS_INCL_MODNAME, 'm' }, |
74 | { _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' }, | 86 | { _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' }, |
75 | { _DPRINTK_FLAGS_INCL_LINENO, 'l' }, | 87 | { _DPRINTK_FLAGS_INCL_LINENO, 'l' }, |
76 | { _DPRINTK_FLAGS_INCL_TID, 't' }, | 88 | { _DPRINTK_FLAGS_INCL_TID, 't' }, |
89 | { _DPRINTK_FLAGS_NONE, '_' }, | ||
77 | }; | 90 | }; |
78 | 91 | ||
79 | /* format a string into buf[] which describes the _ddebug's flags */ | 92 | /* format a string into buf[] which describes the _ddebug's flags */ |
@@ -83,58 +96,74 @@ static char *ddebug_describe_flags(struct _ddebug *dp, char *buf, | |||
83 | char *p = buf; | 96 | char *p = buf; |
84 | int i; | 97 | int i; |
85 | 98 | ||
86 | BUG_ON(maxlen < 4); | 99 | BUG_ON(maxlen < 6); |
87 | for (i = 0; i < ARRAY_SIZE(opt_array); ++i) | 100 | for (i = 0; i < ARRAY_SIZE(opt_array); ++i) |
88 | if (dp->flags & opt_array[i].flag) | 101 | if (dp->flags & opt_array[i].flag) |
89 | *p++ = opt_array[i].opt_char; | 102 | *p++ = opt_array[i].opt_char; |
90 | if (p == buf) | 103 | if (p == buf) |
91 | *p++ = '-'; | 104 | *p++ = '_'; |
92 | *p = '\0'; | 105 | *p = '\0'; |
93 | 106 | ||
94 | return buf; | 107 | return buf; |
95 | } | 108 | } |
96 | 109 | ||
110 | #define vpr_info_dq(q, msg) \ | ||
111 | do { \ | ||
112 | if (verbose) \ | ||
113 | /* trim last char off format print */ \ | ||
114 | pr_info("%s: func=\"%s\" file=\"%s\" " \ | ||
115 | "module=\"%s\" format=\"%.*s\" " \ | ||
116 | "lineno=%u-%u", \ | ||
117 | msg, \ | ||
118 | q->function ? q->function : "", \ | ||
119 | q->filename ? q->filename : "", \ | ||
120 | q->module ? q->module : "", \ | ||
121 | (int)(q->format ? strlen(q->format) - 1 : 0), \ | ||
122 | q->format ? q->format : "", \ | ||
123 | q->first_lineno, q->last_lineno); \ | ||
124 | } while (0) | ||
125 | |||
97 | /* | 126 | /* |
98 | * Search the tables for _ddebug's which match the given | 127 | * Search the tables for _ddebug's which match the given `query' and |
99 | * `query' and apply the `flags' and `mask' to them. Tells | 128 | * apply the `flags' and `mask' to them. Returns number of matching |
100 | * the user which ddebug's were changed, or whether none | 129 | * callsites, normally the same as number of changes. If verbose, |
101 | * were matched. | 130 | * logs the changes. Takes ddebug_lock. |
102 | */ | 131 | */ |
103 | static void ddebug_change(const struct ddebug_query *query, | 132 | static int ddebug_change(const struct ddebug_query *query, |
104 | unsigned int flags, unsigned int mask) | 133 | unsigned int flags, unsigned int mask) |
105 | { | 134 | { |
106 | int i; | 135 | int i; |
107 | struct ddebug_table *dt; | 136 | struct ddebug_table *dt; |
108 | unsigned int newflags; | 137 | unsigned int newflags; |
109 | unsigned int nfound = 0; | 138 | unsigned int nfound = 0; |
110 | char flagbuf[8]; | 139 | char flagbuf[10]; |
111 | 140 | ||
112 | /* search for matching ddebugs */ | 141 | /* search for matching ddebugs */ |
113 | mutex_lock(&ddebug_lock); | 142 | mutex_lock(&ddebug_lock); |
114 | list_for_each_entry(dt, &ddebug_tables, link) { | 143 | list_for_each_entry(dt, &ddebug_tables, link) { |
115 | 144 | ||
116 | /* match against the module name */ | 145 | /* match against the module name */ |
117 | if (query->module != NULL && | 146 | if (query->module && strcmp(query->module, dt->mod_name)) |
118 | strcmp(query->module, dt->mod_name)) | ||
119 | continue; | 147 | continue; |
120 | 148 | ||
121 | for (i = 0 ; i < dt->num_ddebugs ; i++) { | 149 | for (i = 0 ; i < dt->num_ddebugs ; i++) { |
122 | struct _ddebug *dp = &dt->ddebugs[i]; | 150 | struct _ddebug *dp = &dt->ddebugs[i]; |
123 | 151 | ||
124 | /* match against the source filename */ | 152 | /* match against the source filename */ |
125 | if (query->filename != NULL && | 153 | if (query->filename && |
126 | strcmp(query->filename, dp->filename) && | 154 | strcmp(query->filename, dp->filename) && |
127 | strcmp(query->filename, basename(dp->filename))) | 155 | strcmp(query->filename, basename(dp->filename)) && |
156 | strcmp(query->filename, trim_prefix(dp->filename))) | ||
128 | continue; | 157 | continue; |
129 | 158 | ||
130 | /* match against the function */ | 159 | /* match against the function */ |
131 | if (query->function != NULL && | 160 | if (query->function && |
132 | strcmp(query->function, dp->function)) | 161 | strcmp(query->function, dp->function)) |
133 | continue; | 162 | continue; |
134 | 163 | ||
135 | /* match against the format */ | 164 | /* match against the format */ |
136 | if (query->format != NULL && | 165 | if (query->format && |
137 | strstr(dp->format, query->format) == NULL) | 166 | !strstr(dp->format, query->format)) |
138 | continue; | 167 | continue; |
139 | 168 | ||
140 | /* match against the line number range */ | 169 | /* match against the line number range */ |
@@ -151,13 +180,9 @@ static void ddebug_change(const struct ddebug_query *query, | |||
151 | if (newflags == dp->flags) | 180 | if (newflags == dp->flags) |
152 | continue; | 181 | continue; |
153 | dp->flags = newflags; | 182 | dp->flags = newflags; |
154 | if (newflags) | ||
155 | dp->enabled = 1; | ||
156 | else | ||
157 | dp->enabled = 0; | ||
158 | if (verbose) | 183 | if (verbose) |
159 | pr_info("changed %s:%d [%s]%s %s\n", | 184 | pr_info("changed %s:%d [%s]%s =%s\n", |
160 | dp->filename, dp->lineno, | 185 | trim_prefix(dp->filename), dp->lineno, |
161 | dt->mod_name, dp->function, | 186 | dt->mod_name, dp->function, |
162 | ddebug_describe_flags(dp, flagbuf, | 187 | ddebug_describe_flags(dp, flagbuf, |
163 | sizeof(flagbuf))); | 188 | sizeof(flagbuf))); |
@@ -167,6 +192,8 @@ static void ddebug_change(const struct ddebug_query *query, | |||
167 | 192 | ||
168 | if (!nfound && verbose) | 193 | if (!nfound && verbose) |
169 | pr_info("no matches for query\n"); | 194 | pr_info("no matches for query\n"); |
195 | |||
196 | return nfound; | ||
170 | } | 197 | } |
171 | 198 | ||
172 | /* | 199 | /* |
@@ -186,8 +213,10 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords) | |||
186 | buf = skip_spaces(buf); | 213 | buf = skip_spaces(buf); |
187 | if (!*buf) | 214 | if (!*buf) |
188 | break; /* oh, it was trailing whitespace */ | 215 | break; /* oh, it was trailing whitespace */ |
216 | if (*buf == '#') | ||
217 | break; /* token starts comment, skip rest of line */ | ||
189 | 218 | ||
190 | /* Run `end' over a word, either whitespace separated or quoted */ | 219 | /* find `end' of word, whitespace separated or quoted */ |
191 | if (*buf == '"' || *buf == '\'') { | 220 | if (*buf == '"' || *buf == '\'') { |
192 | int quote = *buf++; | 221 | int quote = *buf++; |
193 | for (end = buf ; *end && *end != quote ; end++) | 222 | for (end = buf ; *end && *end != quote ; end++) |
@@ -199,8 +228,8 @@ static int ddebug_tokenize(char *buf, char *words[], int maxwords) | |||
199 | ; | 228 | ; |
200 | BUG_ON(end == buf); | 229 | BUG_ON(end == buf); |
201 | } | 230 | } |
202 | /* Here `buf' is the start of the word, `end' is one past the end */ | ||
203 | 231 | ||
232 | /* `buf' is start of word, `end' is one past its end */ | ||
204 | if (nwords == maxwords) | 233 | if (nwords == maxwords) |
205 | return -EINVAL; /* ran out of words[] before bytes */ | 234 | return -EINVAL; /* ran out of words[] before bytes */ |
206 | if (*end) | 235 | if (*end) |
@@ -279,6 +308,19 @@ static char *unescape(char *str) | |||
279 | return str; | 308 | return str; |
280 | } | 309 | } |
281 | 310 | ||
311 | static int check_set(const char **dest, char *src, char *name) | ||
312 | { | ||
313 | int rc = 0; | ||
314 | |||
315 | if (*dest) { | ||
316 | rc = -EINVAL; | ||
317 | pr_err("match-spec:%s val:%s overridden by %s", | ||
318 | name, *dest, src); | ||
319 | } | ||
320 | *dest = src; | ||
321 | return rc; | ||
322 | } | ||
323 | |||
282 | /* | 324 | /* |
283 | * Parse words[] as a ddebug query specification, which is a series | 325 | * Parse words[] as a ddebug query specification, which is a series |
284 | * of (keyword, value) pairs chosen from these possibilities: | 326 | * of (keyword, value) pairs chosen from these possibilities: |
@@ -290,11 +332,15 @@ static char *unescape(char *str) | |||
290 | * format <escaped-string-to-find-in-format> | 332 | * format <escaped-string-to-find-in-format> |
291 | * line <lineno> | 333 | * line <lineno> |
292 | * line <first-lineno>-<last-lineno> // where either may be empty | 334 | * line <first-lineno>-<last-lineno> // where either may be empty |
335 | * | ||
336 | * Only 1 of each type is allowed. | ||
337 | * Returns 0 on success, <0 on error. | ||
293 | */ | 338 | */ |
294 | static int ddebug_parse_query(char *words[], int nwords, | 339 | static int ddebug_parse_query(char *words[], int nwords, |
295 | struct ddebug_query *query) | 340 | struct ddebug_query *query) |
296 | { | 341 | { |
297 | unsigned int i; | 342 | unsigned int i; |
343 | int rc; | ||
298 | 344 | ||
299 | /* check we have an even number of words */ | 345 | /* check we have an even number of words */ |
300 | if (nwords % 2 != 0) | 346 | if (nwords % 2 != 0) |
@@ -303,41 +349,43 @@ static int ddebug_parse_query(char *words[], int nwords, | |||
303 | 349 | ||
304 | for (i = 0 ; i < nwords ; i += 2) { | 350 | for (i = 0 ; i < nwords ; i += 2) { |
305 | if (!strcmp(words[i], "func")) | 351 | if (!strcmp(words[i], "func")) |
306 | query->function = words[i+1]; | 352 | rc = check_set(&query->function, words[i+1], "func"); |
307 | else if (!strcmp(words[i], "file")) | 353 | else if (!strcmp(words[i], "file")) |
308 | query->filename = words[i+1]; | 354 | rc = check_set(&query->filename, words[i+1], "file"); |
309 | else if (!strcmp(words[i], "module")) | 355 | else if (!strcmp(words[i], "module")) |
310 | query->module = words[i+1]; | 356 | rc = check_set(&query->module, words[i+1], "module"); |
311 | else if (!strcmp(words[i], "format")) | 357 | else if (!strcmp(words[i], "format")) |
312 | query->format = unescape(words[i+1]); | 358 | rc = check_set(&query->format, unescape(words[i+1]), |
359 | "format"); | ||
313 | else if (!strcmp(words[i], "line")) { | 360 | else if (!strcmp(words[i], "line")) { |
314 | char *first = words[i+1]; | 361 | char *first = words[i+1]; |
315 | char *last = strchr(first, '-'); | 362 | char *last = strchr(first, '-'); |
363 | if (query->first_lineno || query->last_lineno) { | ||
364 | pr_err("match-spec:line given 2 times\n"); | ||
365 | return -EINVAL; | ||
366 | } | ||
316 | if (last) | 367 | if (last) |
317 | *last++ = '\0'; | 368 | *last++ = '\0'; |
318 | if (parse_lineno(first, &query->first_lineno) < 0) | 369 | if (parse_lineno(first, &query->first_lineno) < 0) |
319 | return -EINVAL; | 370 | return -EINVAL; |
320 | if (last != NULL) { | 371 | if (last) { |
321 | /* range <first>-<last> */ | 372 | /* range <first>-<last> */ |
322 | if (parse_lineno(last, &query->last_lineno) < 0) | 373 | if (parse_lineno(last, &query->last_lineno) |
374 | < query->first_lineno) { | ||
375 | pr_err("last-line < 1st-line\n"); | ||
323 | return -EINVAL; | 376 | return -EINVAL; |
377 | } | ||
324 | } else { | 378 | } else { |
325 | query->last_lineno = query->first_lineno; | 379 | query->last_lineno = query->first_lineno; |
326 | } | 380 | } |
327 | } else { | 381 | } else { |
328 | if (verbose) | 382 | pr_err("unknown keyword \"%s\"\n", words[i]); |
329 | pr_err("unknown keyword \"%s\"\n", words[i]); | ||
330 | return -EINVAL; | 383 | return -EINVAL; |
331 | } | 384 | } |
385 | if (rc) | ||
386 | return rc; | ||
332 | } | 387 | } |
333 | 388 | vpr_info_dq(query, "parsed"); | |
334 | if (verbose) | ||
335 | pr_info("q->function=\"%s\" q->filename=\"%s\" " | ||
336 | "q->module=\"%s\" q->format=\"%s\" q->lineno=%u-%u\n", | ||
337 | query->function, query->filename, | ||
338 | query->module, query->format, query->first_lineno, | ||
339 | query->last_lineno); | ||
340 | |||
341 | return 0; | 389 | return 0; |
342 | } | 390 | } |
343 | 391 | ||
@@ -375,8 +423,6 @@ static int ddebug_parse_flags(const char *str, unsigned int *flagsp, | |||
375 | if (i < 0) | 423 | if (i < 0) |
376 | return -EINVAL; | 424 | return -EINVAL; |
377 | } | 425 | } |
378 | if (flags == 0) | ||
379 | return -EINVAL; | ||
380 | if (verbose) | 426 | if (verbose) |
381 | pr_info("flags=0x%x\n", flags); | 427 | pr_info("flags=0x%x\n", flags); |
382 | 428 | ||
@@ -405,7 +451,7 @@ static int ddebug_exec_query(char *query_string) | |||
405 | unsigned int flags = 0, mask = 0; | 451 | unsigned int flags = 0, mask = 0; |
406 | struct ddebug_query query; | 452 | struct ddebug_query query; |
407 | #define MAXWORDS 9 | 453 | #define MAXWORDS 9 |
408 | int nwords; | 454 | int nwords, nfound; |
409 | char *words[MAXWORDS]; | 455 | char *words[MAXWORDS]; |
410 | 456 | ||
411 | nwords = ddebug_tokenize(query_string, words, MAXWORDS); | 457 | nwords = ddebug_tokenize(query_string, words, MAXWORDS); |
@@ -417,8 +463,47 @@ static int ddebug_exec_query(char *query_string) | |||
417 | return -EINVAL; | 463 | return -EINVAL; |
418 | 464 | ||
419 | /* actually go and implement the change */ | 465 | /* actually go and implement the change */ |
420 | ddebug_change(&query, flags, mask); | 466 | nfound = ddebug_change(&query, flags, mask); |
421 | return 0; | 467 | vpr_info_dq((&query), (nfound) ? "applied" : "no-match"); |
468 | |||
469 | return nfound; | ||
470 | } | ||
471 | |||
472 | /* handle multiple queries in query string, continue on error, return | ||
473 | last error or number of matching callsites. Module name is either | ||
474 | in param (for boot arg) or perhaps in query string. | ||
475 | */ | ||
476 | static int ddebug_exec_queries(char *query) | ||
477 | { | ||
478 | char *split; | ||
479 | int i, errs = 0, exitcode = 0, rc, nfound = 0; | ||
480 | |||
481 | for (i = 0; query; query = split) { | ||
482 | split = strpbrk(query, ";\n"); | ||
483 | if (split) | ||
484 | *split++ = '\0'; | ||
485 | |||
486 | query = skip_spaces(query); | ||
487 | if (!query || !*query || *query == '#') | ||
488 | continue; | ||
489 | |||
490 | if (verbose) | ||
491 | pr_info("query %d: \"%s\"\n", i, query); | ||
492 | |||
493 | rc = ddebug_exec_query(query); | ||
494 | if (rc < 0) { | ||
495 | errs++; | ||
496 | exitcode = rc; | ||
497 | } else | ||
498 | nfound += rc; | ||
499 | i++; | ||
500 | } | ||
501 | pr_info("processed %d queries, with %d matches, %d errs\n", | ||
502 | i, nfound, errs); | ||
503 | |||
504 | if (exitcode) | ||
505 | return exitcode; | ||
506 | return nfound; | ||
422 | } | 507 | } |
423 | 508 | ||
424 | #define PREFIX_SIZE 64 | 509 | #define PREFIX_SIZE 64 |
@@ -452,7 +537,8 @@ static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf) | |||
452 | pos += snprintf(buf + pos, remaining(pos), "%s:", | 537 | pos += snprintf(buf + pos, remaining(pos), "%s:", |
453 | desc->function); | 538 | desc->function); |
454 | if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO) | 539 | if (desc->flags & _DPRINTK_FLAGS_INCL_LINENO) |
455 | pos += snprintf(buf + pos, remaining(pos), "%d:", desc->lineno); | 540 | pos += snprintf(buf + pos, remaining(pos), "%d:", |
541 | desc->lineno); | ||
456 | if (pos - pos_after_tid) | 542 | if (pos - pos_after_tid) |
457 | pos += snprintf(buf + pos, remaining(pos), " "); | 543 | pos += snprintf(buf + pos, remaining(pos), " "); |
458 | if (pos >= PREFIX_SIZE) | 544 | if (pos >= PREFIX_SIZE) |
@@ -527,14 +613,16 @@ EXPORT_SYMBOL(__dynamic_netdev_dbg); | |||
527 | 613 | ||
528 | #endif | 614 | #endif |
529 | 615 | ||
530 | static __initdata char ddebug_setup_string[1024]; | 616 | #define DDEBUG_STRING_SIZE 1024 |
617 | static __initdata char ddebug_setup_string[DDEBUG_STRING_SIZE]; | ||
618 | |||
531 | static __init int ddebug_setup_query(char *str) | 619 | static __init int ddebug_setup_query(char *str) |
532 | { | 620 | { |
533 | if (strlen(str) >= 1024) { | 621 | if (strlen(str) >= DDEBUG_STRING_SIZE) { |
534 | pr_warn("ddebug boot param string too large\n"); | 622 | pr_warn("ddebug boot param string too large\n"); |
535 | return 0; | 623 | return 0; |
536 | } | 624 | } |
537 | strcpy(ddebug_setup_string, str); | 625 | strlcpy(ddebug_setup_string, str, DDEBUG_STRING_SIZE); |
538 | return 1; | 626 | return 1; |
539 | } | 627 | } |
540 | 628 | ||
@@ -544,25 +632,33 @@ __setup("ddebug_query=", ddebug_setup_query); | |||
544 | * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the | 632 | * File_ops->write method for <debugfs>/dynamic_debug/conrol. Gathers the |
545 | * command text from userspace, parses and executes it. | 633 | * command text from userspace, parses and executes it. |
546 | */ | 634 | */ |
635 | #define USER_BUF_PAGE 4096 | ||
547 | static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, | 636 | static ssize_t ddebug_proc_write(struct file *file, const char __user *ubuf, |
548 | size_t len, loff_t *offp) | 637 | size_t len, loff_t *offp) |
549 | { | 638 | { |
550 | char tmpbuf[256]; | 639 | char *tmpbuf; |
551 | int ret; | 640 | int ret; |
552 | 641 | ||
553 | if (len == 0) | 642 | if (len == 0) |
554 | return 0; | 643 | return 0; |
555 | /* we don't check *offp -- multiple writes() are allowed */ | 644 | if (len > USER_BUF_PAGE - 1) { |
556 | if (len > sizeof(tmpbuf)-1) | 645 | pr_warn("expected <%d bytes into control\n", USER_BUF_PAGE); |
557 | return -E2BIG; | 646 | return -E2BIG; |
558 | if (copy_from_user(tmpbuf, ubuf, len)) | 647 | } |
648 | tmpbuf = kmalloc(len + 1, GFP_KERNEL); | ||
649 | if (!tmpbuf) | ||
650 | return -ENOMEM; | ||
651 | if (copy_from_user(tmpbuf, ubuf, len)) { | ||
652 | kfree(tmpbuf); | ||
559 | return -EFAULT; | 653 | return -EFAULT; |
654 | } | ||
560 | tmpbuf[len] = '\0'; | 655 | tmpbuf[len] = '\0'; |
561 | if (verbose) | 656 | if (verbose) |
562 | pr_info("read %d bytes from userspace\n", (int)len); | 657 | pr_info("read %d bytes from userspace\n", (int)len); |
563 | 658 | ||
564 | ret = ddebug_exec_query(tmpbuf); | 659 | ret = ddebug_exec_queries(tmpbuf); |
565 | if (ret) | 660 | kfree(tmpbuf); |
661 | if (ret < 0) | ||
566 | return ret; | 662 | return ret; |
567 | 663 | ||
568 | *offp += len; | 664 | *offp += len; |
@@ -668,7 +764,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) | |||
668 | { | 764 | { |
669 | struct ddebug_iter *iter = m->private; | 765 | struct ddebug_iter *iter = m->private; |
670 | struct _ddebug *dp = p; | 766 | struct _ddebug *dp = p; |
671 | char flagsbuf[8]; | 767 | char flagsbuf[10]; |
672 | 768 | ||
673 | if (verbose) | 769 | if (verbose) |
674 | pr_info("called m=%p p=%p\n", m, p); | 770 | pr_info("called m=%p p=%p\n", m, p); |
@@ -679,10 +775,10 @@ static int ddebug_proc_show(struct seq_file *m, void *p) | |||
679 | return 0; | 775 | return 0; |
680 | } | 776 | } |
681 | 777 | ||
682 | seq_printf(m, "%s:%u [%s]%s %s \"", | 778 | seq_printf(m, "%s:%u [%s]%s =%s \"", |
683 | dp->filename, dp->lineno, | 779 | trim_prefix(dp->filename), dp->lineno, |
684 | iter->table->mod_name, dp->function, | 780 | iter->table->mod_name, dp->function, |
685 | ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf))); | 781 | ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf))); |
686 | seq_escape(m, dp->format, "\t\r\n\""); | 782 | seq_escape(m, dp->format, "\t\r\n\""); |
687 | seq_puts(m, "\"\n"); | 783 | seq_puts(m, "\"\n"); |
688 | 784 | ||
@@ -708,10 +804,11 @@ static const struct seq_operations ddebug_proc_seqops = { | |||
708 | }; | 804 | }; |
709 | 805 | ||
710 | /* | 806 | /* |
711 | * File_ops->open method for <debugfs>/dynamic_debug/control. Does the seq_file | 807 | * File_ops->open method for <debugfs>/dynamic_debug/control. Does |
712 | * setup dance, and also creates an iterator to walk the _ddebugs. | 808 | * the seq_file setup dance, and also creates an iterator to walk the |
713 | * Note that we create a seq_file always, even for O_WRONLY files | 809 | * _ddebugs. Note that we create a seq_file always, even for O_WRONLY |
714 | * where it's not needed, as doing so simplifies the ->release method. | 810 | * files where it's not needed, as doing so simplifies the ->release |
811 | * method. | ||
715 | */ | 812 | */ |
716 | static int ddebug_proc_open(struct inode *inode, struct file *file) | 813 | static int ddebug_proc_open(struct inode *inode, struct file *file) |
717 | { | 814 | { |
@@ -846,33 +943,40 @@ static int __init dynamic_debug_init(void) | |||
846 | int ret = 0; | 943 | int ret = 0; |
847 | int n = 0; | 944 | int n = 0; |
848 | 945 | ||
849 | if (__start___verbose != __stop___verbose) { | 946 | if (__start___verbose == __stop___verbose) { |
850 | iter = __start___verbose; | 947 | pr_warn("_ddebug table is empty in a " |
851 | modname = iter->modname; | 948 | "CONFIG_DYNAMIC_DEBUG build"); |
852 | iter_start = iter; | 949 | return 1; |
853 | for (; iter < __stop___verbose; iter++) { | 950 | } |
854 | if (strcmp(modname, iter->modname)) { | 951 | iter = __start___verbose; |
855 | ret = ddebug_add_module(iter_start, n, modname); | 952 | modname = iter->modname; |
856 | if (ret) | 953 | iter_start = iter; |
857 | goto out_free; | 954 | for (; iter < __stop___verbose; iter++) { |
858 | n = 0; | 955 | if (strcmp(modname, iter->modname)) { |
859 | modname = iter->modname; | 956 | ret = ddebug_add_module(iter_start, n, modname); |
860 | iter_start = iter; | 957 | if (ret) |
861 | } | 958 | goto out_free; |
862 | n++; | 959 | n = 0; |
960 | modname = iter->modname; | ||
961 | iter_start = iter; | ||
863 | } | 962 | } |
864 | ret = ddebug_add_module(iter_start, n, modname); | 963 | n++; |
865 | } | 964 | } |
965 | ret = ddebug_add_module(iter_start, n, modname); | ||
966 | if (ret) | ||
967 | goto out_free; | ||
866 | 968 | ||
867 | /* ddebug_query boot param got passed -> set it up */ | 969 | /* ddebug_query boot param got passed -> set it up */ |
868 | if (ddebug_setup_string[0] != '\0') { | 970 | if (ddebug_setup_string[0] != '\0') { |
869 | ret = ddebug_exec_query(ddebug_setup_string); | 971 | ret = ddebug_exec_queries(ddebug_setup_string); |
870 | if (ret) | 972 | if (ret < 0) |
871 | pr_warn("Invalid ddebug boot param %s", | 973 | pr_warn("Invalid ddebug boot param %s", |
872 | ddebug_setup_string); | 974 | ddebug_setup_string); |
873 | else | 975 | else |
874 | pr_info("ddebug initialized with string %s", | 976 | pr_info("%d changes by ddebug_query\n", ret); |
875 | ddebug_setup_string); | 977 | |
978 | /* keep tables even on ddebug_query parse error */ | ||
979 | ret = 0; | ||
876 | } | 980 | } |
877 | 981 | ||
878 | out_free: | 982 | out_free: |
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index b89efe6e4c85..71839eb3375d 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -1029,6 +1029,30 @@ static int do_amba_entry(const char *filename, | |||
1029 | } | 1029 | } |
1030 | ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry); | 1030 | ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry); |
1031 | 1031 | ||
1032 | /* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,* | ||
1033 | * All fields are numbers. It would be nicer to use strings for vendor | ||
1034 | * and feature, but getting those out of the build system here is too | ||
1035 | * complicated. | ||
1036 | */ | ||
1037 | |||
1038 | static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id, | ||
1039 | char *alias) | ||
1040 | { | ||
1041 | id->feature = TO_NATIVE(id->feature); | ||
1042 | id->family = TO_NATIVE(id->family); | ||
1043 | id->model = TO_NATIVE(id->model); | ||
1044 | id->vendor = TO_NATIVE(id->vendor); | ||
1045 | |||
1046 | strcpy(alias, "x86cpu:"); | ||
1047 | ADD(alias, "vendor:", id->vendor != X86_VENDOR_ANY, id->vendor); | ||
1048 | ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family); | ||
1049 | ADD(alias, ":model:", id->model != X86_MODEL_ANY, id->model); | ||
1050 | ADD(alias, ":feature:*,", id->feature != X86_FEATURE_ANY, id->feature); | ||
1051 | strcat(alias, ",*"); | ||
1052 | return 1; | ||
1053 | } | ||
1054 | ADD_TO_DEVTABLE("x86cpu", struct x86_cpu_id, do_x86cpu_entry); | ||
1055 | |||
1032 | /* Does namelen bytes of name exactly match the symbol? */ | 1056 | /* Does namelen bytes of name exactly match the symbol? */ |
1033 | static bool sym_is(const char *name, unsigned namelen, const char *symbol) | 1057 | static bool sym_is(const char *name, unsigned namelen, const char *symbol) |
1034 | { | 1058 | { |
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 11224eddcdc2..4ebf70380582 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c | |||
@@ -34,21 +34,12 @@ | |||
34 | #include <errno.h> | 34 | #include <errno.h> |
35 | #include <arpa/inet.h> | 35 | #include <arpa/inet.h> |
36 | #include <linux/connector.h> | 36 | #include <linux/connector.h> |
37 | #include <linux/hyperv.h> | ||
37 | #include <linux/netlink.h> | 38 | #include <linux/netlink.h> |
38 | #include <ifaddrs.h> | 39 | #include <ifaddrs.h> |
39 | #include <netdb.h> | 40 | #include <netdb.h> |
40 | #include <syslog.h> | 41 | #include <syslog.h> |
41 | 42 | ||
42 | /* | ||
43 | * KYS: TODO. Need to register these in the kernel. | ||
44 | * | ||
45 | * The following definitions are shared with the in-kernel component; do not | ||
46 | * change any of this without making the corresponding changes in | ||
47 | * the KVP kernel component. | ||
48 | */ | ||
49 | #define CN_KVP_IDX 0x9 /* MSFT KVP functionality */ | ||
50 | #define CN_KVP_VAL 0x1 /* This supports queries from the kernel */ | ||
51 | #define CN_KVP_USER_VAL 0x2 /* This supports queries from the user */ | ||
52 | 43 | ||
53 | /* | 44 | /* |
54 | * KVP protocol: The user mode component first registers with the | 45 | * KVP protocol: The user mode component first registers with the |
@@ -60,25 +51,8 @@ | |||
60 | * We use this infrastructure for also supporting queries from user mode | 51 | * We use this infrastructure for also supporting queries from user mode |
61 | * application for state that may be maintained in the KVP kernel component. | 52 | * application for state that may be maintained in the KVP kernel component. |
62 | * | 53 | * |
63 | * XXXKYS: Have a shared header file between the user and kernel (TODO) | ||
64 | */ | 54 | */ |
65 | 55 | ||
66 | enum kvp_op { | ||
67 | KVP_REGISTER = 0, /* Register the user mode component*/ | ||
68 | KVP_KERNEL_GET, /*Kernel is requesting the value for the specified key*/ | ||
69 | KVP_KERNEL_SET, /*Kernel is providing the value for the specified key*/ | ||
70 | KVP_USER_GET, /*User is requesting the value for the specified key*/ | ||
71 | KVP_USER_SET /*User is providing the value for the specified key*/ | ||
72 | }; | ||
73 | |||
74 | #define HV_KVP_EXCHANGE_MAX_KEY_SIZE 512 | ||
75 | #define HV_KVP_EXCHANGE_MAX_VALUE_SIZE 2048 | ||
76 | |||
77 | struct hv_ku_msg { | ||
78 | __u32 kvp_index; | ||
79 | __u8 kvp_key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; /* Key name */ | ||
80 | __u8 kvp_value[HV_KVP_EXCHANGE_MAX_VALUE_SIZE]; /* Key value */ | ||
81 | }; | ||
82 | 56 | ||
83 | enum key_index { | 57 | enum key_index { |
84 | FullyQualifiedDomainName = 0, | 58 | FullyQualifiedDomainName = 0, |
@@ -93,10 +67,6 @@ enum key_index { | |||
93 | ProcessorArchitecture | 67 | ProcessorArchitecture |
94 | }; | 68 | }; |
95 | 69 | ||
96 | /* | ||
97 | * End of shared definitions. | ||
98 | */ | ||
99 | |||
100 | static char kvp_send_buffer[4096]; | 70 | static char kvp_send_buffer[4096]; |
101 | static char kvp_recv_buffer[4096]; | 71 | static char kvp_recv_buffer[4096]; |
102 | static struct sockaddr_nl addr; | 72 | static struct sockaddr_nl addr; |
@@ -332,7 +302,7 @@ int main(void) | |||
332 | struct pollfd pfd; | 302 | struct pollfd pfd; |
333 | struct nlmsghdr *incoming_msg; | 303 | struct nlmsghdr *incoming_msg; |
334 | struct cn_msg *incoming_cn_msg; | 304 | struct cn_msg *incoming_cn_msg; |
335 | struct hv_ku_msg *hv_msg; | 305 | struct hv_kvp_msg *hv_msg; |
336 | char *p; | 306 | char *p; |
337 | char *key_value; | 307 | char *key_value; |
338 | char *key_name; | 308 | char *key_name; |
@@ -370,9 +340,11 @@ int main(void) | |||
370 | message = (struct cn_msg *)kvp_send_buffer; | 340 | message = (struct cn_msg *)kvp_send_buffer; |
371 | message->id.idx = CN_KVP_IDX; | 341 | message->id.idx = CN_KVP_IDX; |
372 | message->id.val = CN_KVP_VAL; | 342 | message->id.val = CN_KVP_VAL; |
373 | message->seq = KVP_REGISTER; | 343 | |
344 | hv_msg = (struct hv_kvp_msg *)message->data; | ||
345 | hv_msg->kvp_hdr.operation = KVP_OP_REGISTER; | ||
374 | message->ack = 0; | 346 | message->ack = 0; |
375 | message->len = 0; | 347 | message->len = sizeof(struct hv_kvp_msg); |
376 | 348 | ||
377 | len = netlink_send(fd, message); | 349 | len = netlink_send(fd, message); |
378 | if (len < 0) { | 350 | if (len < 0) { |
@@ -398,14 +370,15 @@ int main(void) | |||
398 | 370 | ||
399 | incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; | 371 | incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; |
400 | incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); | 372 | incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); |
373 | hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; | ||
401 | 374 | ||
402 | switch (incoming_cn_msg->seq) { | 375 | switch (hv_msg->kvp_hdr.operation) { |
403 | case KVP_REGISTER: | 376 | case KVP_OP_REGISTER: |
404 | /* | 377 | /* |
405 | * Driver is registering with us; stash away the version | 378 | * Driver is registering with us; stash away the version |
406 | * information. | 379 | * information. |
407 | */ | 380 | */ |
408 | p = (char *)incoming_cn_msg->data; | 381 | p = (char *)hv_msg->body.kvp_version; |
409 | lic_version = malloc(strlen(p) + 1); | 382 | lic_version = malloc(strlen(p) + 1); |
410 | if (lic_version) { | 383 | if (lic_version) { |
411 | strcpy(lic_version, p); | 384 | strcpy(lic_version, p); |
@@ -416,17 +389,15 @@ int main(void) | |||
416 | } | 389 | } |
417 | continue; | 390 | continue; |
418 | 391 | ||
419 | case KVP_KERNEL_GET: | ||
420 | break; | ||
421 | default: | 392 | default: |
422 | continue; | 393 | break; |
423 | } | 394 | } |
424 | 395 | ||
425 | hv_msg = (struct hv_ku_msg *)incoming_cn_msg->data; | 396 | hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; |
426 | key_name = (char *)hv_msg->kvp_key; | 397 | key_name = (char *)hv_msg->body.kvp_enum_data.data.key; |
427 | key_value = (char *)hv_msg->kvp_value; | 398 | key_value = (char *)hv_msg->body.kvp_enum_data.data.value; |
428 | 399 | ||
429 | switch (hv_msg->kvp_index) { | 400 | switch (hv_msg->body.kvp_enum_data.index) { |
430 | case FullyQualifiedDomainName: | 401 | case FullyQualifiedDomainName: |
431 | kvp_get_domain_name(key_value, | 402 | kvp_get_domain_name(key_value, |
432 | HV_KVP_EXCHANGE_MAX_VALUE_SIZE); | 403 | HV_KVP_EXCHANGE_MAX_VALUE_SIZE); |
@@ -486,9 +457,8 @@ int main(void) | |||
486 | 457 | ||
487 | incoming_cn_msg->id.idx = CN_KVP_IDX; | 458 | incoming_cn_msg->id.idx = CN_KVP_IDX; |
488 | incoming_cn_msg->id.val = CN_KVP_VAL; | 459 | incoming_cn_msg->id.val = CN_KVP_VAL; |
489 | incoming_cn_msg->seq = KVP_USER_SET; | ||
490 | incoming_cn_msg->ack = 0; | 460 | incoming_cn_msg->ack = 0; |
491 | incoming_cn_msg->len = sizeof(struct hv_ku_msg); | 461 | incoming_cn_msg->len = sizeof(struct hv_kvp_msg); |
492 | 462 | ||
493 | len = netlink_send(fd, incoming_cn_msg); | 463 | len = netlink_send(fd, incoming_cn_msg); |
494 | if (len < 0) { | 464 | if (len < 0) { |