|
@@ -25,6 +25,15 @@ EXPORT_SYMBOL_GPL(cpu_subsys);
|
|
|
static DEFINE_PER_CPU(struct device *, cpu_sys_devices);
|
|
|
|
|
|
#ifdef CONFIG_HOTPLUG_CPU
|
|
|
+static void change_cpu_under_node(struct cpu *cpu,
|
|
|
+ unsigned int from_nid, unsigned int to_nid)
|
|
|
+{
|
|
|
+ int cpuid = cpu->dev.id;
|
|
|
+ unregister_cpu_under_node(cpuid, from_nid);
|
|
|
+ register_cpu_under_node(cpuid, to_nid);
|
|
|
+ cpu->node_id = to_nid;
|
|
|
+}
|
|
|
+
|
|
|
static ssize_t show_online(struct device *dev,
|
|
|
struct device_attribute *attr,
|
|
|
char *buf)
|
|
@@ -39,17 +48,29 @@ static ssize_t __ref store_online(struct device *dev,
|
|
|
const char *buf, size_t count)
|
|
|
{
|
|
|
struct cpu *cpu = container_of(dev, struct cpu, dev);
|
|
|
+ int cpuid = cpu->dev.id;
|
|
|
+ int from_nid, to_nid;
|
|
|
ssize_t ret;
|
|
|
|
|
|
cpu_hotplug_driver_lock();
|
|
|
switch (buf[0]) {
|
|
|
case '0':
|
|
|
- ret = cpu_down(cpu->dev.id);
|
|
|
+ ret = cpu_down(cpuid);
|
|
|
if (!ret)
|
|
|
kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
|
|
|
break;
|
|
|
case '1':
|
|
|
- ret = cpu_up(cpu->dev.id);
|
|
|
+ from_nid = cpu_to_node(cpuid);
|
|
|
+ ret = cpu_up(cpuid);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * When hot adding memory to memoryless node and enabling a cpu
|
|
|
+ * on the node, node number of the cpu may internally change.
|
|
|
+ */
|
|
|
+ to_nid = cpu_to_node(cpuid);
|
|
|
+ if (from_nid != to_nid)
|
|
|
+ change_cpu_under_node(cpu, from_nid, to_nid);
|
|
|
+
|
|
|
if (!ret)
|
|
|
kobject_uevent(&dev->kobj, KOBJ_ONLINE);
|
|
|
break;
|