aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/cpu.c
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2011-12-21 17:29:42 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-12-21 17:29:42 -0500
commit8a25a2fd126c621f44f3aeaef80d51f00fc11639 (patch)
tree41694ab1a9c82a7a02d9cd33c929fd039c98c815 /drivers/base/cpu.c
parentcb0c05c5fae12eeb7c85c205578df277bd706155 (diff)
cpu: convert 'cpu' and 'machinecheck' sysdev_class to a regular subsystem
This moves the 'cpu sysdev_class' over to a regular 'cpu' subsystem and converts the devices to regular devices. The sysdev drivers are implemented as subsystem interfaces now. After all sysdev classes are ported to regular driver core entities, the sysdev implementation will be entirely removed from the kernel. Userspace relies on events and generic sysfs subsystem infrastructure from sysdev devices, which are made available with this conversion. Cc: Haavard Skinnemoen <hskinnemoen@gmail.com> Cc: Hans-Christian Egtvedt <egtvedt@samfundet.no> Cc: Tony Luck <tony.luck@intel.com> Cc: Fenghua Yu <fenghua.yu@intel.com> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Heiko Carstens <heiko.carstens@de.ibm.com> Cc: Paul Mundt <lethal@linux-sh.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Chris Metcalf <cmetcalf@tilera.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Borislav Petkov <bp@amd64.org> Cc: Tigran Aivazian <tigran@aivazian.fsnet.co.uk> Cc: Len Brown <lenb@kernel.org> Cc: Zhang Rui <rui.zhang@intel.com> Cc: Dave Jones <davej@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Russell King <rmk+kernel@arm.linux.org.uk> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: "Rafael J. Wysocki" <rjw@sisk.pl> Cc: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com> Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/cpu.c')
-rw-r--r--drivers/base/cpu.c146
1 files changed, 77 insertions, 69 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 251acea3d359..5bb0298fbcc0 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -1,8 +1,7 @@
1/* 1/*
2 * drivers/base/cpu.c - basic CPU class support 2 * CPU subsystem support
3 */ 3 */
4 4
5#include <linux/sysdev.h>
6#include <linux/module.h> 5#include <linux/module.h>
7#include <linux/init.h> 6#include <linux/init.h>
8#include <linux/sched.h> 7#include <linux/sched.h>
@@ -14,40 +13,40 @@
14 13
15#include "base.h" 14#include "base.h"
16 15
17static struct sysdev_class_attribute *cpu_sysdev_class_attrs[]; 16struct bus_type cpu_subsys = {
18
19struct sysdev_class cpu_sysdev_class = {
20 .name = "cpu", 17 .name = "cpu",
21 .attrs = cpu_sysdev_class_attrs, 18 .dev_name = "cpu",
22}; 19};
23EXPORT_SYMBOL(cpu_sysdev_class); 20EXPORT_SYMBOL_GPL(cpu_subsys);
24 21
25static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); 22static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
26 23
27#ifdef CONFIG_HOTPLUG_CPU 24#ifdef CONFIG_HOTPLUG_CPU
28static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr, 25static ssize_t show_online(struct device *dev,
26 struct device_attribute *attr,
29 char *buf) 27 char *buf)
30{ 28{
31 struct cpu *cpu = container_of(dev, struct cpu, sysdev); 29 struct cpu *cpu = container_of(dev, struct cpu, dev);
32 30
33 return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); 31 return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id));
34} 32}
35 33
36static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr, 34static ssize_t __ref store_online(struct device *dev,
37 const char *buf, size_t count) 35 struct device_attribute *attr,
36 const char *buf, size_t count)
38{ 37{
39 struct cpu *cpu = container_of(dev, struct cpu, sysdev); 38 struct cpu *cpu = container_of(dev, struct cpu, dev);
40 ssize_t ret; 39 ssize_t ret;
41 40
42 cpu_hotplug_driver_lock(); 41 cpu_hotplug_driver_lock();
43 switch (buf[0]) { 42 switch (buf[0]) {
44 case '0': 43 case '0':
45 ret = cpu_down(cpu->sysdev.id); 44 ret = cpu_down(cpu->dev.id);
46 if (!ret) 45 if (!ret)
47 kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 46 kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
48 break; 47 break;
49 case '1': 48 case '1':
50 ret = cpu_up(cpu->sysdev.id); 49 ret = cpu_up(cpu->dev.id);
51 if (!ret) 50 if (!ret)
52 kobject_uevent(&dev->kobj, KOBJ_ONLINE); 51 kobject_uevent(&dev->kobj, KOBJ_ONLINE);
53 break; 52 break;
@@ -60,44 +59,44 @@ static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribut
60 ret = count; 59 ret = count;
61 return ret; 60 return ret;
62} 61}
63static SYSDEV_ATTR(online, 0644, show_online, store_online); 62static DEVICE_ATTR(online, 0644, show_online, store_online);
64 63
65static void __cpuinit register_cpu_control(struct cpu *cpu) 64static void __cpuinit register_cpu_control(struct cpu *cpu)
66{ 65{
67 sysdev_create_file(&cpu->sysdev, &attr_online); 66 device_create_file(&cpu->dev, &dev_attr_online);
68} 67}
69void unregister_cpu(struct cpu *cpu) 68void unregister_cpu(struct cpu *cpu)
70{ 69{
71 int logical_cpu = cpu->sysdev.id; 70 int logical_cpu = cpu->dev.id;
72 71
73 unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); 72 unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu));
74 73
75 sysdev_remove_file(&cpu->sysdev, &attr_online); 74 device_remove_file(&cpu->dev, &dev_attr_online);
76 75
77 sysdev_unregister(&cpu->sysdev); 76 device_unregister(&cpu->dev);
78 per_cpu(cpu_sys_devices, logical_cpu) = NULL; 77 per_cpu(cpu_sys_devices, logical_cpu) = NULL;
79 return; 78 return;
80} 79}
81 80
82#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE 81#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
83static ssize_t cpu_probe_store(struct sysdev_class *class, 82static ssize_t cpu_probe_store(struct device *dev,
84 struct sysdev_class_attribute *attr, 83 struct device_attribute *attr,
85 const char *buf, 84 const char *buf,
86 size_t count) 85 size_t count)
87{ 86{
88 return arch_cpu_probe(buf, count); 87 return arch_cpu_probe(buf, count);
89} 88}
90 89
91static ssize_t cpu_release_store(struct sysdev_class *class, 90static ssize_t cpu_release_store(struct device *dev,
92 struct sysdev_class_attribute *attr, 91 struct device_attribute *attr,
93 const char *buf, 92 const char *buf,
94 size_t count) 93 size_t count)
95{ 94{
96 return arch_cpu_release(buf, count); 95 return arch_cpu_release(buf, count);
97} 96}
98 97
99static SYSDEV_CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); 98static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
100static SYSDEV_CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store); 99static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store);
101#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ 100#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
102 101
103#else /* ... !CONFIG_HOTPLUG_CPU */ 102#else /* ... !CONFIG_HOTPLUG_CPU */
@@ -109,15 +108,15 @@ static inline void register_cpu_control(struct cpu *cpu)
109#ifdef CONFIG_KEXEC 108#ifdef CONFIG_KEXEC
110#include <linux/kexec.h> 109#include <linux/kexec.h>
111 110
112static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr, 111static ssize_t show_crash_notes(struct device *dev, struct device_attribute *attr,
113 char *buf) 112 char *buf)
114{ 113{
115 struct cpu *cpu = container_of(dev, struct cpu, sysdev); 114 struct cpu *cpu = container_of(dev, struct cpu, dev);
116 ssize_t rc; 115 ssize_t rc;
117 unsigned long long addr; 116 unsigned long long addr;
118 int cpunum; 117 int cpunum;
119 118
120 cpunum = cpu->sysdev.id; 119 cpunum = cpu->dev.id;
121 120
122 /* 121 /*
123 * Might be reading other cpu's data based on which cpu read thread 122 * Might be reading other cpu's data based on which cpu read thread
@@ -129,7 +128,7 @@ static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute
129 rc = sprintf(buf, "%Lx\n", addr); 128 rc = sprintf(buf, "%Lx\n", addr);
130 return rc; 129 return rc;
131} 130}
132static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL); 131static DEVICE_ATTR(crash_notes, 0400, show_crash_notes, NULL);
133#endif 132#endif
134 133
135/* 134/*
@@ -137,12 +136,12 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
137 */ 136 */
138 137
139struct cpu_attr { 138struct cpu_attr {
140 struct sysdev_class_attribute attr; 139 struct device_attribute attr;
141 const struct cpumask *const * const map; 140 const struct cpumask *const * const map;
142}; 141};
143 142
144static ssize_t show_cpus_attr(struct sysdev_class *class, 143static ssize_t show_cpus_attr(struct device *dev,
145 struct sysdev_class_attribute *attr, 144 struct device_attribute *attr,
146 char *buf) 145 char *buf)
147{ 146{
148 struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr); 147 struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
@@ -153,10 +152,10 @@ static ssize_t show_cpus_attr(struct sysdev_class *class,
153 return n; 152 return n;
154} 153}
155 154
156#define _CPU_ATTR(name, map) \ 155#define _CPU_ATTR(name, map) \
157 { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map } 156 { __ATTR(name, 0444, show_cpus_attr, NULL), map }
158 157
159/* Keep in sync with cpu_sysdev_class_attrs */ 158/* Keep in sync with cpu_subsys_attrs */
160static struct cpu_attr cpu_attrs[] = { 159static struct cpu_attr cpu_attrs[] = {
161 _CPU_ATTR(online, &cpu_online_mask), 160 _CPU_ATTR(online, &cpu_online_mask),
162 _CPU_ATTR(possible, &cpu_possible_mask), 161 _CPU_ATTR(possible, &cpu_possible_mask),
@@ -166,19 +165,19 @@ static struct cpu_attr cpu_attrs[] = {
166/* 165/*
167 * Print values for NR_CPUS and offlined cpus 166 * Print values for NR_CPUS and offlined cpus
168 */ 167 */
169static ssize_t print_cpus_kernel_max(struct sysdev_class *class, 168static ssize_t print_cpus_kernel_max(struct device *dev,
170 struct sysdev_class_attribute *attr, char *buf) 169 struct device_attribute *attr, char *buf)
171{ 170{
172 int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1); 171 int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
173 return n; 172 return n;
174} 173}
175static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL); 174static DEVICE_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
176 175
177/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */ 176/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
178unsigned int total_cpus; 177unsigned int total_cpus;
179 178
180static ssize_t print_cpus_offline(struct sysdev_class *class, 179static ssize_t print_cpus_offline(struct device *dev,
181 struct sysdev_class_attribute *attr, char *buf) 180 struct device_attribute *attr, char *buf)
182{ 181{
183 int n = 0, len = PAGE_SIZE-2; 182 int n = 0, len = PAGE_SIZE-2;
184 cpumask_var_t offline; 183 cpumask_var_t offline;
@@ -205,7 +204,7 @@ static ssize_t print_cpus_offline(struct sysdev_class *class,
205 n += snprintf(&buf[n], len - n, "\n"); 204 n += snprintf(&buf[n], len - n, "\n");
206 return n; 205 return n;
207} 206}
208static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL); 207static DEVICE_ATTR(offline, 0444, print_cpus_offline, NULL);
209 208
210/* 209/*
211 * register_cpu - Setup a sysfs device for a CPU. 210 * register_cpu - Setup a sysfs device for a CPU.
@@ -218,57 +217,66 @@ static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
218int __cpuinit register_cpu(struct cpu *cpu, int num) 217int __cpuinit register_cpu(struct cpu *cpu, int num)
219{ 218{
220 int error; 219 int error;
221 cpu->node_id = cpu_to_node(num);
222 cpu->sysdev.id = num;
223 cpu->sysdev.cls = &cpu_sysdev_class;
224
225 error = sysdev_register(&cpu->sysdev);
226 220
221 cpu->node_id = cpu_to_node(num);
222 cpu->dev.id = num;
223 cpu->dev.bus = &cpu_subsys;
224 error = device_register(&cpu->dev);
227 if (!error && cpu->hotpluggable) 225 if (!error && cpu->hotpluggable)
228 register_cpu_control(cpu); 226 register_cpu_control(cpu);
229 if (!error) 227 if (!error)
230 per_cpu(cpu_sys_devices, num) = &cpu->sysdev; 228 per_cpu(cpu_sys_devices, num) = &cpu->dev;
231 if (!error) 229 if (!error)
232 register_cpu_under_node(num, cpu_to_node(num)); 230 register_cpu_under_node(num, cpu_to_node(num));
233 231
234#ifdef CONFIG_KEXEC 232#ifdef CONFIG_KEXEC
235 if (!error) 233 if (!error)
236 error = sysdev_create_file(&cpu->sysdev, &attr_crash_notes); 234 error = device_create_file(&cpu->dev, &dev_attr_crash_notes);
237#endif 235#endif
238 return error; 236 return error;
239} 237}
240 238
241struct sys_device *get_cpu_sysdev(unsigned cpu) 239struct device *get_cpu_device(unsigned cpu)
242{ 240{
243 if (cpu < nr_cpu_ids && cpu_possible(cpu)) 241 if (cpu < nr_cpu_ids && cpu_possible(cpu))
244 return per_cpu(cpu_sys_devices, cpu); 242 return per_cpu(cpu_sys_devices, cpu);
245 else 243 else
246 return NULL; 244 return NULL;
247} 245}
248EXPORT_SYMBOL_GPL(get_cpu_sysdev); 246EXPORT_SYMBOL_GPL(get_cpu_device);
247
248static struct attribute *cpu_root_attrs[] = {
249#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
250 &dev_attr_probe.attr,
251 &dev_attr_release.attr,
252#endif
253 &cpu_attrs[0].attr.attr,
254 &cpu_attrs[1].attr.attr,
255 &cpu_attrs[2].attr.attr,
256 &dev_attr_kernel_max.attr,
257 &dev_attr_offline.attr,
258 NULL
259};
260
261static struct attribute_group cpu_root_attr_group = {
262 .attrs = cpu_root_attrs,
263};
264
265static const struct attribute_group *cpu_root_attr_groups[] = {
266 &cpu_root_attr_group,
267 NULL,
268};
249 269
250int __init cpu_dev_init(void) 270int __init cpu_dev_init(void)
251{ 271{
252 int err; 272 int err;
253 273
254 err = sysdev_class_register(&cpu_sysdev_class); 274 err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
275 if (err)
276 return err;
277
255#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT) 278#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
256 if (!err) 279 err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
257 err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
258#endif 280#endif
259
260 return err; 281 return err;
261} 282}
262
263static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = {
264#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
265 &attr_probe,
266 &attr_release,
267#endif
268 &cpu_attrs[0].attr,
269 &cpu_attrs[1].attr,
270 &cpu_attrs[2].attr,
271 &attr_kernel_max,
272 &attr_offline,
273 NULL
274};