diff options
| -rw-r--r-- | drivers/base/cpu.c | 25 | 
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index d8c7f3ee6e1..3d48fc887ef 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -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;  |