]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - drivers/base/cpu.c
numa, cpu hotplug: change links of CPU and node when changing node number by onlining CPU
[linux-imx.git] / drivers / base / cpu.c
index d8c7f3ee6e192b0b6a5c0abde3714c2e86735dd1..3d48fc887ef4b3a3da1aadefaf9129578e3d1ef2 100644 (file)
@@ -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;