Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+31 -56
+31 -56
drivers/base/cpu.c
··· 16 16 17 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 19 static DEFINE_PER_CPU(struct device *, cpu_sys_devices); 26 20 27 21 #ifdef CONFIG_HOTPLUG_CPU ··· 28 34 cpu->node_id = to_nid; 29 35 } 30 36 31 - static ssize_t show_online(struct device *dev, 32 - struct device_attribute *attr, 33 - char *buf) 37 + static int __ref cpu_subsys_online(struct device *dev) 34 38 { 35 39 struct cpu *cpu = container_of(dev, struct cpu, dev); 36 - 37 - return sprintf(buf, "%u\n", !!cpu_online(cpu->dev.id)); 38 - } 39 - 40 - static ssize_t __ref store_online(struct device *dev, 41 - struct device_attribute *attr, 42 - const char *buf, size_t count) 43 - { 44 - struct cpu *cpu = container_of(dev, struct cpu, dev); 45 - int cpuid = cpu->dev.id; 40 + int cpuid = dev->id; 46 41 int from_nid, to_nid; 47 - ssize_t ret; 42 + int ret; 48 43 49 44 cpu_hotplug_driver_lock(); 50 - switch (buf[0]) { 51 - case '0': 52 - ret = cpu_down(cpuid); 53 - if (!ret) 54 - kobject_uevent(&dev->kobj, KOBJ_OFFLINE); 55 - break; 56 - case '1': 57 - from_nid = cpu_to_node(cpuid); 58 - ret = cpu_up(cpuid); 59 45 60 - /* 61 - * When hot adding memory to memoryless node and enabling a cpu 62 - * on the node, node number of the cpu may internally change. 63 - */ 64 - to_nid = cpu_to_node(cpuid); 65 - if (from_nid != to_nid) 66 - change_cpu_under_node(cpu, from_nid, to_nid); 46 + from_nid = cpu_to_node(cpuid); 47 + ret = cpu_up(cpuid); 48 + /* 49 + * When hot adding memory to memoryless node and enabling a cpu 50 + * on the node, node number of the cpu may internally change. 51 + */ 52 + to_nid = cpu_to_node(cpuid); 53 + if (from_nid != to_nid) 54 + change_cpu_under_node(cpu, from_nid, to_nid); 67 55 68 - if (!ret) 69 - kobject_uevent(&dev->kobj, KOBJ_ONLINE); 70 - break; 71 - default: 72 - ret = -EINVAL; 73 - } 74 56 cpu_hotplug_driver_unlock(); 75 - 76 - if (ret >= 0) 77 - ret = count; 78 57 return ret; 79 58 } 80 - static DEVICE_ATTR(online, 0644, show_online, store_online); 81 59 82 - static void __cpuinit register_cpu_control(struct cpu *cpu) 60 + static int cpu_subsys_offline(struct device *dev) 83 61 { 84 - device_create_file(&cpu->dev, &dev_attr_online); 62 + int ret; 63 + 64 + cpu_hotplug_driver_lock(); 65 + ret = cpu_down(dev->id); 66 + cpu_hotplug_driver_unlock(); 67 + return ret; 85 68 } 69 + 86 70 void unregister_cpu(struct cpu *cpu) 87 71 { 88 72 int logical_cpu = cpu->dev.id; 89 73 90 74 unregister_cpu_under_node(logical_cpu, cpu_to_node(logical_cpu)); 91 - 92 - device_remove_file(&cpu->dev, &dev_attr_online); 93 75 94 76 device_unregister(&cpu->dev); 95 77 per_cpu(cpu_sys_devices, logical_cpu) = NULL; ··· 93 123 static DEVICE_ATTR(release, S_IWUSR, NULL, cpu_release_store); 94 124 #endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */ 95 125 96 - #else /* ... !CONFIG_HOTPLUG_CPU */ 97 - static inline void register_cpu_control(struct cpu *cpu) 98 - { 99 - } 100 126 #endif /* CONFIG_HOTPLUG_CPU */ 127 + 128 + struct bus_type cpu_subsys = { 129 + .name = "cpu", 130 + .dev_name = "cpu", 131 + #ifdef CONFIG_HOTPLUG_CPU 132 + .online = cpu_subsys_online, 133 + .offline = cpu_subsys_offline, 134 + #endif 135 + }; 136 + EXPORT_SYMBOL_GPL(cpu_subsys); 101 137 102 138 #ifdef CONFIG_KEXEC 103 139 #include <linux/kexec.h> ··· 253 277 cpu->dev.id = num; 254 278 cpu->dev.bus = &cpu_subsys; 255 279 cpu->dev.release = cpu_device_release; 280 + cpu->dev.offline_disabled = !cpu->hotpluggable; 256 281 #ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE 257 282 cpu->dev.bus->uevent = arch_cpu_uevent; 258 283 #endif 259 284 error = device_register(&cpu->dev); 260 - if (!error && cpu->hotpluggable) 261 - register_cpu_control(cpu); 262 285 if (!error) 263 286 per_cpu(cpu_sys_devices, num) = &cpu->dev; 264 287 if (!error)