diff options
-rw-r--r-- | arch/x86/Kconfig | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/match.c | 44 | ||||
-rw-r--r-- | arch/x86/kernel/cpuid.c | 59 | ||||
-rw-r--r-- | drivers/base/cpu.c | 11 | ||||
-rw-r--r-- | include/linux/cpu.h | 7 |
5 files changed, 66 insertions, 58 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 864cc6e6ac8e..6baa1e66e1bc 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/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index 7acc961422e7..940e2d483076 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <asm/processor.h> | 2 | #include <asm/processor.h> |
3 | #include <linux/cpu.h> | 3 | #include <linux/cpu.h> |
4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
5 | #include <linux/slab.h> | ||
5 | 6 | ||
6 | /** | 7 | /** |
7 | * x86_match_cpu - match current CPU again an array of x86_cpu_ids | 8 | * x86_match_cpu - match current CPU again an array of x86_cpu_ids |
@@ -46,3 +47,46 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) | |||
46 | return NULL; | 47 | return NULL; |
47 | } | 48 | } |
48 | EXPORT_SYMBOL(x86_match_cpu); | 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/cpuid.c b/arch/x86/kernel/cpuid.c index 7c89880eefd0..a524353d93f2 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c | |||
@@ -40,7 +40,6 @@ | |||
40 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
41 | #include <linux/uaccess.h> | 41 | #include <linux/uaccess.h> |
42 | #include <linux/gfp.h> | 42 | #include <linux/gfp.h> |
43 | #include <linux/slab.h> | ||
44 | 43 | ||
45 | #include <asm/processor.h> | 44 | #include <asm/processor.h> |
46 | #include <asm/msr.h> | 45 | #include <asm/msr.h> |
@@ -139,57 +138,13 @@ static const struct file_operations cpuid_fops = { | |||
139 | .open = cpuid_open, | 138 | .open = cpuid_open, |
140 | }; | 139 | }; |
141 | 140 | ||
142 | static ssize_t print_cpu_modalias(struct device *dev, | ||
143 | struct device_attribute *attr, | ||
144 | char *bufptr) | ||
145 | { | ||
146 | int size = PAGE_SIZE; | ||
147 | int i, n; | ||
148 | char *buf = bufptr; | ||
149 | |||
150 | n = snprintf(buf, size, "x86cpu:vendor:%04X:family:" | ||
151 | "%04X:model:%04X:feature:", | ||
152 | boot_cpu_data.x86_vendor, | ||
153 | boot_cpu_data.x86, | ||
154 | boot_cpu_data.x86_model); | ||
155 | size -= n; | ||
156 | buf += n; | ||
157 | size -= 2; | ||
158 | for (i = 0; i < NCAPINTS*32; i++) { | ||
159 | if (boot_cpu_has(i)) { | ||
160 | n = snprintf(buf, size, ",%04X", i); | ||
161 | if (n < 0) { | ||
162 | WARN(1, "x86 features overflow page\n"); | ||
163 | break; | ||
164 | } | ||
165 | size -= n; | ||
166 | buf += n; | ||
167 | } | ||
168 | } | ||
169 | *buf++ = ','; | ||
170 | *buf++ = '\n'; | ||
171 | return buf - bufptr; | ||
172 | } | ||
173 | |||
174 | static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL); | ||
175 | |||
176 | static __cpuinit int cpuid_device_create(int cpu) | 141 | static __cpuinit int cpuid_device_create(int cpu) |
177 | { | 142 | { |
178 | struct device *dev; | 143 | struct device *dev; |
179 | int err; | ||
180 | 144 | ||
181 | dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL, | 145 | dev = device_create(cpuid_class, NULL, MKDEV(CPUID_MAJOR, cpu), NULL, |
182 | "cpu%d", cpu); | 146 | "cpu%d", cpu); |
183 | if (IS_ERR(dev)) | 147 | return IS_ERR(dev) ? PTR_ERR(dev) : 0; |
184 | return PTR_ERR(dev); | ||
185 | |||
186 | err = device_create_file(dev, &dev_attr_modalias); | ||
187 | if (err) { | ||
188 | /* keep device around on error. attribute is optional. */ | ||
189 | err = 0; | ||
190 | } | ||
191 | |||
192 | return 0; | ||
193 | } | 148 | } |
194 | 149 | ||
195 | static void cpuid_device_destroy(int cpu) | 150 | static void cpuid_device_destroy(int cpu) |
@@ -227,17 +182,6 @@ static char *cpuid_devnode(struct device *dev, umode_t *mode) | |||
227 | return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt)); | 182 | return kasprintf(GFP_KERNEL, "cpu/%u/cpuid", MINOR(dev->devt)); |
228 | } | 183 | } |
229 | 184 | ||
230 | static int cpuid_dev_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
231 | { | ||
232 | char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
233 | if (buf) { | ||
234 | print_cpu_modalias(NULL, NULL, buf); | ||
235 | add_uevent_var(env, "MODALIAS=%s", buf); | ||
236 | kfree(buf); | ||
237 | } | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | static int __init cpuid_init(void) | 185 | static int __init cpuid_init(void) |
242 | { | 186 | { |
243 | int i, err = 0; | 187 | int i, err = 0; |
@@ -256,7 +200,6 @@ static int __init cpuid_init(void) | |||
256 | goto out_chrdev; | 200 | goto out_chrdev; |
257 | } | 201 | } |
258 | cpuid_class->devnode = cpuid_devnode; | 202 | cpuid_class->devnode = cpuid_devnode; |
259 | cpuid_class->dev_uevent = cpuid_dev_uevent; | ||
260 | for_each_online_cpu(i) { | 203 | for_each_online_cpu(i) { |
261 | err = cpuid_device_create(i); | 204 | err = cpuid_device_create(i); |
262 | if (err != 0) | 205 | if (err != 0) |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index db87e78d7459..2a0c670c281d 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" |
@@ -223,6 +224,9 @@ int __cpuinit register_cpu(struct cpu *cpu, int num) | |||
223 | cpu->node_id = cpu_to_node(num); | 224 | cpu->node_id = cpu_to_node(num); |
224 | cpu->dev.id = num; | 225 | cpu->dev.id = num; |
225 | cpu->dev.bus = &cpu_subsys; | 226 | cpu->dev.bus = &cpu_subsys; |
227 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
228 | cpu->dev.bus->uevent = arch_cpu_uevent; | ||
229 | #endif | ||
226 | error = device_register(&cpu->dev); | 230 | error = device_register(&cpu->dev); |
227 | if (!error && cpu->hotpluggable) | 231 | if (!error && cpu->hotpluggable) |
228 | register_cpu_control(cpu); | 232 | register_cpu_control(cpu); |
@@ -247,6 +251,10 @@ struct device *get_cpu_device(unsigned cpu) | |||
247 | } | 251 | } |
248 | EXPORT_SYMBOL_GPL(get_cpu_device); | 252 | EXPORT_SYMBOL_GPL(get_cpu_device); |
249 | 253 | ||
254 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
255 | static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL); | ||
256 | #endif | ||
257 | |||
250 | static struct attribute *cpu_root_attrs[] = { | 258 | static struct attribute *cpu_root_attrs[] = { |
251 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE | 259 | #ifdef CONFIG_ARCH_CPU_PROBE_RELEASE |
252 | &dev_attr_probe.attr, | 260 | &dev_attr_probe.attr, |
@@ -257,6 +265,9 @@ static struct attribute *cpu_root_attrs[] = { | |||
257 | &cpu_attrs[2].attr.attr, | 265 | &cpu_attrs[2].attr.attr, |
258 | &dev_attr_kernel_max.attr, | 266 | &dev_attr_kernel_max.attr, |
259 | &dev_attr_offline.attr, | 267 | &dev_attr_offline.attr, |
268 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | ||
269 | &dev_attr_modalias.attr, | ||
270 | #endif | ||
260 | NULL | 271 | NULL |
261 | }; | 272 | }; |
262 | 273 | ||
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 | */ |