[PATCH] powerpc/imc-pmu: Revert nest_init_lock to being a mutex
kajoljain
kjain at linux.ibm.com
Mon Jan 30 22:06:16 AEDT 2023
On 1/30/23 07:14, Michael Ellerman wrote:
> The recent commit 76d588dddc45 ("powerpc/imc-pmu: Fix use of mutex in
> IRQs disabled section") fixed warnings (and possible deadlocks) in the
> IMC PMU driver by converting the locking to use spinlocks.
>
> It also converted the init-time nest_init_lock to a spinlock, even
> though it's not used at runtime in IRQ disabled sections or while
> holding other spinlocks.
>
> This leads to warnings such as:
>
> BUG: sleeping function called from invalid context at include/linux/percpu-rwsem.h:49
> in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper/0
> preempt_count: 1, expected: 0
> CPU: 7 PID: 1 Comm: swapper/0 Not tainted 6.2.0-rc2-14719-gf12cd06109f4-dirty #1
> Hardware name: Mambo,Simulated-System POWER9 0x4e1203 opal:v6.6.6 PowerNV
> Call Trace:
> dump_stack_lvl+0x74/0xa8 (unreliable)
> __might_resched+0x178/0x1a0
> __cpuhp_setup_state+0x64/0x1e0
> init_imc_pmu+0xe48/0x1250
> opal_imc_counters_probe+0x30c/0x6a0
> platform_probe+0x78/0x110
> really_probe+0x104/0x420
> __driver_probe_device+0xb0/0x170
> driver_probe_device+0x58/0x180
> __driver_attach+0xd8/0x250
> bus_for_each_dev+0xb4/0x140
> driver_attach+0x34/0x50
> bus_add_driver+0x1e8/0x2d0
> driver_register+0xb4/0x1c0
> __platform_driver_register+0x38/0x50
> opal_imc_driver_init+0x2c/0x40
> do_one_initcall+0x80/0x360
> kernel_init_freeable+0x310/0x3b8
> kernel_init+0x30/0x1a0
> ret_from_kernel_thread+0x5c/0x64
>
> Fix it by converting nest_init_lock back to a mutex, so that we can call
> sleeping functions while holding it. There is no interaction between
> nest_init_lock and the runtime spinlocks used by the actual PMU routines.
Thanks for the patch. Patch looks good to me.
Reviewed-by: Kajol Jain<kjain at linux.ibm.com>
Tested-by: Kajol Jain<kjain at linux.ibm.com>
Thanks,
Kajol Jain
>
> Fixes: 76d588dddc45 ("powerpc/imc-pmu: Fix use of mutex in IRQs disabled section")
> Signed-off-by: Michael Ellerman <mpe at ellerman.id.au>
> ---
> arch/powerpc/perf/imc-pmu.c | 14 +++++++-------
> 1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
> index 100e97daf76b..9d229ef7f86e 100644
> --- a/arch/powerpc/perf/imc-pmu.c
> +++ b/arch/powerpc/perf/imc-pmu.c
> @@ -22,7 +22,7 @@
> * Used to avoid races in counting the nest-pmu units during hotplug
> * register and unregister
> */
> -static DEFINE_SPINLOCK(nest_init_lock);
> +static DEFINE_MUTEX(nest_init_lock);
> static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc);
> static struct imc_pmu **per_nest_pmu_arr;
> static cpumask_t nest_imc_cpumask;
> @@ -1629,7 +1629,7 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr)
> static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
> {
> if (pmu_ptr->domain == IMC_DOMAIN_NEST) {
> - spin_lock(&nest_init_lock);
> + mutex_lock(&nest_init_lock);
> if (nest_pmus == 1) {
> cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
> kfree(nest_imc_refc);
> @@ -1639,7 +1639,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
>
> if (nest_pmus > 0)
> nest_pmus--;
> - spin_unlock(&nest_init_lock);
> + mutex_unlock(&nest_init_lock);
> }
>
> /* Free core_imc memory */
> @@ -1796,11 +1796,11 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
> * rest. To handle the cpuhotplug callback unregister, we track
> * the number of nest pmus in "nest_pmus".
> */
> - spin_lock(&nest_init_lock);
> + mutex_lock(&nest_init_lock);
> if (nest_pmus == 0) {
> ret = init_nest_pmu_ref();
> if (ret) {
> - spin_unlock(&nest_init_lock);
> + mutex_unlock(&nest_init_lock);
> kfree(per_nest_pmu_arr);
> per_nest_pmu_arr = NULL;
> goto err_free_mem;
> @@ -1808,7 +1808,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
> /* Register for cpu hotplug notification. */
> ret = nest_pmu_cpumask_init();
> if (ret) {
> - spin_unlock(&nest_init_lock);
> + mutex_unlock(&nest_init_lock);
> kfree(nest_imc_refc);
> kfree(per_nest_pmu_arr);
> per_nest_pmu_arr = NULL;
> @@ -1816,7 +1816,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
> }
> }
> nest_pmus++;
> - spin_unlock(&nest_init_lock);
> + mutex_unlock(&nest_init_lock);
> break;
> case IMC_DOMAIN_CORE:
> ret = core_imc_pmu_cpumask_init();
More information about the Linuxppc-dev
mailing list