diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-05-02 18:25:49 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-05-12 08:14:17 -0400 |
commit | 0902a9044fa5b7a0456ea4daacec2c2b3189ba8c (patch) | |
tree | 7161c5cbf23ec6b8ef42f5655340be38e5f0e1a8 /drivers/base | |
parent | 4f3549d72d1b5c90ecc7e673402f38f4486d22c2 (diff) |
Driver core: Use generic offline/online for CPU offline/online
Rework the CPU hotplug code in drivers/base/cpu.c to use the
generic offline/online support introduced previously instead of
its own CPU-specific code.
For this purpose, modify cpu_subsys to provide offline and online
callbacks for CONFIG_HOTPLUG_CPU set and remove the code handling
the CPU-specific 'online' sysfs attribute.
This modification is not supposed to change the user-observable
behavior of the kernel (i.e. the 'online' attribute will be present
in exactly the same place in sysfs and should trigger exactly the
same actions as before).
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/cpu.c | 89 |
1 files changed, 32 insertions, 57 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 3d48fc887ef4..25c8768172e9 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -16,12 +16,6 @@ | |||
16 | 16 | ||
17 | #include "base.h" | 17 | #include "base.h" |
18 | 18 | ||
19 | struct bus_type cpu_subsys = { | ||
20 | .name = "cpu", | ||
21 | .dev_name = "cpu", | ||
22 | }; | ||
23 | EXPORT_SYMBOL_GPL(cpu_subsys); | ||
24 | |||
25 | static DEFINE_PER_CPU(struct device *, cpu_sys_devices); | 19 | static DEFINE_PER_CPU(struct device *, cpu_sys_devices); |
26 | 20 | ||
27 | #ifdef CONFIG_HOTPLUG_CPU | 21 | #ifdef CONFIG_HOTPLUG_CPU |
@@ -34,69 +28,45 @@ static void change_cpu_under_node(struct cpu *cpu, | |||
34 | cpu->node_id = to_nid; | 28 | cpu->node_id = to_nid; |
35 | } | 29 | } |
36 | 30 | ||
37 | static ssize_t show_online(struct device *dev, | 31 | static int __ref cpu_subsys_online(struct device *dev) |
38 | struct device_attribute *attr, | ||
39 | char *buf) | ||
40 | { | 32 | { |
41 | struct cpu *cpu = container_of(dev, struct cpu, dev); | 33 | struct cpu *cpu = container_of(dev, struct cpu, dev); |
34 | int cpuid = dev->id; | ||
35 | int from_nid, to_nid; | ||
36 | int ret; | ||
37 | |||
38 | cpu_hotplug_driver_lock(); | ||
39 | |||
40 | from_nid = cpu_to_node(cpuid); | ||
41 | ret = cpu_up(cpuid); | ||
42 | /* | ||
43 | * When hot adding memory to memoryless node and enabling a cpu | ||
44 | * on the node, node number of the cpu may internally change. | ||
45 | */ | ||
46 | to_nid = cpu_to_node(cpuid); | ||
47 | if (from_nid != to_nid) | ||
48 | change_cpu_under_node(cpu, from_nid, to_nid); | ||
42 | 49 | ||
43 | return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id)); | 50 | cpu_hotplug_driver_unlock(); |
51 | return ret; | ||
44 | } | 52 | } |
45 | 53 | ||
46 | static ssize_t __ref store_online(struct device *dev, | 54 | static int cpu_subsys_offline(struct device *dev) |
47 | struct device_attribute *attr, | ||
48 | const char *buf, size_t count) | ||
49 | { | 55 | { |
50 | struct cpu *cpu = container_of(dev, struct cpu, dev); | 56 | int ret; |
51 | int cpuid = cpu->dev.id; | ||
52 | int from_nid, to_nid; | ||
53 | ssize_t ret; | ||
54 | 57 | ||
55 | cpu_hotplug_driver_lock(); | 58 | cpu_hotplug_driver_lock(); |
56 | switch (buf[0]) { | 59 | ret = cpu_down(dev->id); |
57 | case '0': | ||
58 | ret = cpu_down(cpuid); | ||
59 | if (!ret) | ||
60 | kobject_uevent(&dev->kobj, KOBJ_OFFLINE); | ||
61 | break; | ||
62 | case '1': | ||
63 | from_nid = cpu_to_node(cpuid); | ||
64 | ret = cpu_up(cpuid); | ||
65 | |||
66 | /* | ||
67 | * When hot adding memory to memoryless node and enabling a cpu | ||
68 | * on the node, node number of the cpu may internally change. | ||
69 | */ | ||
70 | to_nid = cpu_to_node(cpuid); | ||
71 | if (from_nid != to_nid) | ||
72 | change_cpu_under_node(cpu, from_nid, to_nid); | ||
73 | |||
74 | if (!ret) | ||
75 | kobject_uevent(&dev->kobj, KOBJ_ONLINE); | ||
76 | break; | ||
77 | default: | ||
78 | ret = -EINVAL; | ||
79 | } | ||
80 | cpu_hotplug_driver_unlock(); | 60 | cpu_hotplug_driver_unlock(); |
81 | |||
82 | if (ret >= 0) | ||
83 | ret = count; | ||
84 | return ret; | 61 | return ret; |
85 | } | 62 | } |
86 | static DEVICE_ATTR(online, 0644, show_online, store_online); | ||
87 | 63 | ||
88 | static void __cpuinit register_cpu_control(struct cpu *cpu) | ||
89 | { | ||
90 | device_create_file(&cpu->dev, &dev_attr_online); | ||
91 | } | ||
92 | void unregister_cpu(struct cpu *cpu) | 64 | void unregister_cpu(struct cpu *cpu) |
93 | { | 65 | { |
94 | int logical_cpu = cpu->dev.id; | 66 | int logical_cpu = cpu->dev.id; |
95 | 67 | ||
96 | unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); | 68 | unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); |
97 | 69 | ||
98 | device_remove_file(&cpu->dev, &dev_attr_online); | ||
99 | |||
100 | device_unregister(&cpu->dev); | 70 | device_unregister(&cpu->dev); |
101 | per_cpu(cpu_sys_devices, logical_cpu) = NULL; | 71 | per_cpu(cpu_sys_devices, logical_cpu) = NULL; |
102 | return; | 72 | return; |
@@ -123,12 +93,18 @@ static DEVICE_ATTR(probe, S_IWUSR, NULL, cpu_probe_store); | |||
123 | static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); | 93 | static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); |
124 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ | 94 | #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ |
125 | 95 | ||
126 | #else /* ... !CONFIG_HOTPLUG_CPU */ | ||
127 | static inline void register_cpu_control(struct cpu *cpu) | ||
128 | { | ||
129 | } | ||
130 | #endif /* CONFIG_HOTPLUG_CPU */ | 96 | #endif /* CONFIG_HOTPLUG_CPU */ |
131 | 97 | ||
98 | struct bus_type cpu_subsys = { | ||
99 | .name = "cpu", | ||
100 | .dev_name = "cpu", | ||
101 | #ifdef CONFIG_HOTPLUG_CPU | ||
102 | .online = cpu_subsys_online, | ||
103 | .offline = cpu_subsys_offline, | ||
104 | #endif | ||
105 | }; | ||
106 | EXPORT_SYMBOL_GPL(cpu_subsys); | ||
107 | |||
132 | #ifdef CONFIG_KEXEC | 108 | #ifdef CONFIG_KEXEC |
133 | #include <linux/kexec.h> | 109 | #include <linux/kexec.h> |
134 | 110 | ||
@@ -277,12 +253,11 @@ int __cpuinit register_cpu(struct cpu *cpu, int num) | |||
277 | cpu->dev.id = num; | 253 | cpu->dev.id = num; |
278 | cpu->dev.bus = &cpu_subsys; | 254 | cpu->dev.bus = &cpu_subsys; |
279 | cpu->dev.release = cpu_device_release; | 255 | cpu->dev.release = cpu_device_release; |
256 | cpu->dev.offline_disabled = !cpu->hotpluggable; | ||
280 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE | 257 | #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE |
281 | cpu->dev.bus->uevent = arch_cpu_uevent; | 258 | cpu->dev.bus->uevent = arch_cpu_uevent; |
282 | #endif | 259 | #endif |
283 | error = device_register(&cpu->dev); | 260 | error = device_register(&cpu->dev); |
284 | if (!error && cpu->hotpluggable) | ||
285 | register_cpu_control(cpu); | ||
286 | if (!error) | 261 | if (!error) |
287 | per_cpu(cpu_sys_devices, num) = &cpu->dev; | 262 | per_cpu(cpu_sys_devices, num) = &cpu->dev; |
288 | if (!error) | 263 | if (!error) |