Commit e67e02a5 authored by Michael Bringmann's avatar Michael Bringmann Committed by Michael Ellerman

powerpc/pseries: Fix cpu hotplug crash with memoryless nodes

On powerpc systems with shared configurations of CPUs and memory and
memoryless nodes at boot, an event ordering problem was observed on a
SLES12 build platforms with the hot-add of CPUs to the memoryless
nodes.

* The most common error occurred when the memory SLAB driver attempted
  to reference the memoryless node to which a CPU was being added
  before the kernel had finished initializing all of the data
  structures for the CPU and exited 'device_online' under
  DLPAR/hot-add.

  Normally the memoryless node would be initialized through the call
  path device_online ... arch_update_cpu_topology ... find_cpu_nid ...
  try_online_node. This patch ensures that the powerpc node will be
  initialized as early as possible, even if it was memoryless and
  CPU-less at the point when we are trying to hot-add a new CPU to it.
Signed-off-by: default avatarMichael Bringmann <mwb@linux.vnet.ibm.com>
Reviewed-by: default avatarNathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent ea05ba7c
...@@ -1198,7 +1198,7 @@ static long vphn_get_associativity(unsigned long cpu, ...@@ -1198,7 +1198,7 @@ static long vphn_get_associativity(unsigned long cpu,
return rc; return rc;
} }
static inline int find_and_online_cpu_nid(int cpu) int find_and_online_cpu_nid(int cpu)
{ {
__be32 associativity[VPHN_ASSOC_BUFSIZE] = {0}; __be32 associativity[VPHN_ASSOC_BUFSIZE] = {0};
int new_nid; int new_nid;
...@@ -1229,6 +1229,8 @@ static inline int find_and_online_cpu_nid(int cpu) ...@@ -1229,6 +1229,8 @@ static inline int find_and_online_cpu_nid(int cpu)
#endif #endif
} }
pr_debug("%s:%d cpu %d nid %d\n", __FUNCTION__, __LINE__,
cpu, new_nid);
return new_nid; return new_nid;
} }
......
...@@ -340,6 +340,8 @@ static void pseries_remove_processor(struct device_node *np) ...@@ -340,6 +340,8 @@ static void pseries_remove_processor(struct device_node *np)
cpu_maps_update_done(); cpu_maps_update_done();
} }
extern int find_and_online_cpu_nid(int cpu);
static int dlpar_online_cpu(struct device_node *dn) static int dlpar_online_cpu(struct device_node *dn)
{ {
int rc = 0; int rc = 0;
...@@ -364,6 +366,7 @@ static int dlpar_online_cpu(struct device_node *dn) ...@@ -364,6 +366,7 @@ static int dlpar_online_cpu(struct device_node *dn)
!= CPU_STATE_OFFLINE); != CPU_STATE_OFFLINE);
cpu_maps_update_done(); cpu_maps_update_done();
timed_topology_update(1); timed_topology_update(1);
find_and_online_cpu_nid(cpu);
rc = device_online(get_cpu_device(cpu)); rc = device_online(get_cpu_device(cpu));
if (rc) if (rc)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment