Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753485AbdFWHjZ (ORCPT ); Fri, 23 Jun 2017 03:39:25 -0400 Received: from terminus.zytor.com ([65.50.211.136]:55515 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751182AbdFWHjX (ORCPT ); Fri, 23 Jun 2017 03:39:23 -0400 Date: Fri, 23 Jun 2017 00:37:09 -0700 From: tip-bot for Thiago Jung Bauermann Message-ID: Cc: mwb@linux.vnet.ibm.com, nfont@linux.vnet.ibm.com, jallen@linux.vnet.ibm.com, tglx@linutronix.de, bauerman@linux.vnet.ibm.com, mingo@kernel.org, mpe@ellerman.id.au, hpa@zytor.com, linux-kernel@vger.kernel.org Reply-To: bauerman@linux.vnet.ibm.com, mwb@linux.vnet.ibm.com, nfont@linux.vnet.ibm.com, jallen@linux.vnet.ibm.com, tglx@linutronix.de, linux-kernel@vger.kernel.org, mingo@kernel.org, mpe@ellerman.id.au, hpa@zytor.com In-Reply-To: <1497996510-4032-1-git-send-email-bauerman@linux.vnet.ibm.com> References: <1497996510-4032-1-git-send-email-bauerman@linux.vnet.ibm.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:smp/hotplug] powerpc: Only obtain cpu_hotplug_lock if called by rtasd Git-Commit-ID: 3e401f7a2e5199151f735aee6a5c6b4776e6a35e X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4622 Lines: 129 Commit-ID: 3e401f7a2e5199151f735aee6a5c6b4776e6a35e Gitweb: http://git.kernel.org/tip/3e401f7a2e5199151f735aee6a5c6b4776e6a35e Author: Thiago Jung Bauermann AuthorDate: Tue, 20 Jun 2017 19:08:30 -0300 Committer: Thomas Gleixner CommitDate: Fri, 23 Jun 2017 09:32:11 +0200 powerpc: Only obtain cpu_hotplug_lock if called by rtasd Calling arch_update_cpu_topology from a CPU hotplug state machine callback hits a deadlock because the function tries to get a read lock on cpu_hotplug_lock while the state machine still holds a write lock on it. Since all callers of arch_update_cpu_topology except rtasd already hold cpu_hotplug_lock, this patch changes the function to use stop_machine_cpuslocked and creates a separate function for rtasd which still tries to obtain the lock. Michael Bringmann investigated the bug and provided a detailed analysis of the deadlock on this previous RFC for an alternate solution: Signed-off-by: Thiago Jung Bauermann Signed-off-by: Thomas Gleixner Acked-by: Michael Ellerman Cc: John Allen Cc: Michael Bringmann Cc: Nathan Fontenot Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1497996510-4032-1-git-send-email-bauerman@linux.vnet.ibm.com Link: https://patchwork.ozlabs.org/patch/771293/ --- arch/powerpc/include/asm/topology.h | 6 ++++++ arch/powerpc/kernel/rtasd.c | 2 +- arch/powerpc/mm/numa.c | 22 +++++++++++++++++++--- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h index 8b3b46b..a2d36b7 100644 --- a/arch/powerpc/include/asm/topology.h +++ b/arch/powerpc/include/asm/topology.h @@ -43,6 +43,7 @@ extern void __init dump_numa_cpu_topology(void); extern int sysfs_add_device_to_node(struct device *dev, int nid); extern void sysfs_remove_device_from_node(struct device *dev, int nid); +extern int numa_update_cpu_topology(bool cpus_locked); #else @@ -57,6 +58,11 @@ static inline void sysfs_remove_device_from_node(struct device *dev, int nid) { } + +static inline int numa_update_cpu_topology(bool cpus_locked) +{ + return 0; +} #endif /* CONFIG_NUMA */ #if defined(CONFIG_NUMA) && defined(CONFIG_PPC_SPLPAR) diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 3650732..0f0b1b2 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -283,7 +283,7 @@ static void prrn_work_fn(struct work_struct *work) * the RTAS event. */ pseries_devicetree_update(-prrn_update_scope); - arch_update_cpu_topology(); + numa_update_cpu_topology(false); } static DECLARE_WORK(prrn_work, prrn_work_fn); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 371792e..b95c584 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1311,8 +1311,10 @@ static int update_lookup_table(void *data) /* * Update the node maps and sysfs entries for each cpu whose home node * has changed. Returns 1 when the topology has changed, and 0 otherwise. + * + * cpus_locked says whether we already hold cpu_hotplug_lock. */ -int arch_update_cpu_topology(void) +int numa_update_cpu_topology(bool cpus_locked) { unsigned int cpu, sibling, changed = 0; struct topology_update_data *updates, *ud; @@ -1400,15 +1402,23 @@ int arch_update_cpu_topology(void) if (!cpumask_weight(&updated_cpus)) goto out; - stop_machine(update_cpu_topology, &updates[0], &updated_cpus); + if (cpus_locked) + stop_machine_cpuslocked(update_cpu_topology, &updates[0], + &updated_cpus); + else + stop_machine(update_cpu_topology, &updates[0], &updated_cpus); /* * Update the numa-cpu lookup table with the new mappings, even for * offline CPUs. It is best to perform this update from the stop- * machine context. */ - stop_machine(update_lookup_table, &updates[0], + if (cpus_locked) + stop_machine_cpuslocked(update_lookup_table, &updates[0], cpumask_of(raw_smp_processor_id())); + else + stop_machine(update_lookup_table, &updates[0], + cpumask_of(raw_smp_processor_id())); for (ud = &updates[0]; ud; ud = ud->next) { unregister_cpu_under_node(ud->cpu, ud->old_nid); @@ -1426,6 +1436,12 @@ out: return changed; } +int arch_update_cpu_topology(void) +{ + lockdep_assert_cpus_held(); + return numa_update_cpu_topology(true); +} + static void topology_work_fn(struct work_struct *work) { rebuild_sched_domains();