diff options
Diffstat (limited to 'drivers/base/cpu.c')
-rw-r--r-- | drivers/base/cpu.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c new file mode 100644 index 000000000000..6ef3069b5710 --- /dev/null +++ b/drivers/base/cpu.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * drivers/base/cpu.c - basic CPU class support | ||
3 | */ | ||
4 | |||
5 | #include <linux/sysdev.h> | ||
6 | #include <linux/module.h> | ||
7 | #include <linux/init.h> | ||
8 | #include <linux/cpu.h> | ||
9 | #include <linux/topology.h> | ||
10 | #include <linux/device.h> | ||
11 | |||
12 | |||
13 | struct sysdev_class cpu_sysdev_class = { | ||
14 | set_kset_name("cpu"), | ||
15 | }; | ||
16 | EXPORT_SYMBOL(cpu_sysdev_class); | ||
17 | |||
18 | #ifdef CONFIG_HOTPLUG_CPU | ||
19 | static ssize_t show_online(struct sys_device *dev, char *buf) | ||
20 | { | ||
21 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | ||
22 | |||
23 | return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); | ||
24 | } | ||
25 | |||
26 | static ssize_t store_online(struct sys_device *dev, const char *buf, | ||
27 | size_t count) | ||
28 | { | ||
29 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | ||
30 | ssize_t ret; | ||
31 | |||
32 | switch (buf[0]) { | ||
33 | case '0': | ||
34 | ret = cpu_down(cpu->sysdev.id); | ||
35 | if (!ret) | ||
36 | kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); | ||
37 | break; | ||
38 | case '1': | ||
39 | ret = cpu_up(cpu->sysdev.id); | ||
40 | break; | ||
41 | default: | ||
42 | ret = -EINVAL; | ||
43 | } | ||
44 | |||
45 | if (ret >= 0) | ||
46 | ret = count; | ||
47 | return ret; | ||
48 | } | ||
49 | static SYSDEV_ATTR(online, 0600, show_online, store_online); | ||
50 | |||
51 | static void __devinit register_cpu_control(struct cpu *cpu) | ||
52 | { | ||
53 | sysdev_create_file(&cpu->sysdev, &attr_online); | ||
54 | } | ||
55 | void unregister_cpu(struct cpu *cpu, struct node *root) | ||
56 | { | ||
57 | |||
58 | if (root) | ||
59 | sysfs_remove_link(&root->sysdev.kobj, | ||
60 | kobject_name(&cpu->sysdev.kobj)); | ||
61 | sysdev_remove_file(&cpu->sysdev, &attr_online); | ||
62 | |||
63 | sysdev_unregister(&cpu->sysdev); | ||
64 | |||
65 | return; | ||
66 | } | ||
67 | #else /* ... !CONFIG_HOTPLUG_CPU */ | ||
68 | static inline void register_cpu_control(struct cpu *cpu) | ||
69 | { | ||
70 | } | ||
71 | #endif /* CONFIG_HOTPLUG_CPU */ | ||
72 | |||
73 | /* | ||
74 | * register_cpu - Setup a driverfs device for a CPU. | ||
75 | * @cpu - Callers can set the cpu->no_control field to 1, to indicate not to | ||
76 | * generate a control file in sysfs for this CPU. | ||
77 | * @num - CPU number to use when creating the device. | ||
78 | * | ||
79 | * Initialize and register the CPU device. | ||
80 | */ | ||
81 | int __devinit register_cpu(struct cpu *cpu, int num, struct node *root) | ||
82 | { | ||
83 | int error; | ||
84 | |||
85 | cpu->node_id = cpu_to_node(num); | ||
86 | cpu->sysdev.id = num; | ||
87 | cpu->sysdev.cls = &cpu_sysdev_class; | ||
88 | |||
89 | error = sysdev_register(&cpu->sysdev); | ||
90 | if (!error && root) | ||
91 | error = sysfs_create_link(&root->sysdev.kobj, | ||
92 | &cpu->sysdev.kobj, | ||
93 | kobject_name(&cpu->sysdev.kobj)); | ||
94 | if (!error && !cpu->no_control) | ||
95 | register_cpu_control(cpu); | ||
96 | return error; | ||
97 | } | ||
98 | |||
99 | |||
100 | |||
101 | int __init cpu_dev_init(void) | ||
102 | { | ||
103 | return sysdev_class_register(&cpu_sysdev_class); | ||
104 | } | ||