Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: qcom: rpmh-rsc: Ensure irqs aren't disabled by rpmh_rsc_send_data() callers

Dan pointed out that Smatch is concerned about this code because it uses
spin_lock_irqsave() and then calls wait_event_lock_irq() which enables
irqs before going to sleep. The comment above the function says it
should be called with interrupts enabled, but we simply hope that's true
without really confirming that. Let's add a might_sleep() here to
confirm that interrupts and preemption aren't disabled. Once we do that,
we can change the lock to be non-saving, spin_lock_irq(), to clarify
that we don't expect irqs to be disabled. If irqs are disabled by
callers they're going to be enabled anyway in the wait_event_lock_irq()
call which would be bad.

This should make Smatch happier and find bad callers faster with the
might_sleep(). We can drop the WARN_ON() in the caller because we have
the might_sleep() now, simplifying the code.

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/r/911181ed-c430-4592-ad26-4dc948834e08@moroto.mountain
Fixes: 2bc20f3c8487 ("soc: qcom: rpmh-rsc: Sleep waiting for tcs slots to be free")
Cc: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Link: https://lore.kernel.org/r/20240509184129.3924422-1-swboyd@chromium.org
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Stephen Boyd and committed by
Bjorn Andersson
e43111f5 0780c836

+4 -4
+4 -3
drivers/soc/qcom/rpmh-rsc.c
··· 646 646 { 647 647 struct tcs_group *tcs; 648 648 int tcs_id; 649 - unsigned long flags; 649 + 650 + might_sleep(); 650 651 651 652 tcs = get_tcs_for_msg(drv, msg); 652 653 if (IS_ERR(tcs)) 653 654 return PTR_ERR(tcs); 654 655 655 - spin_lock_irqsave(&drv->lock, flags); 656 + spin_lock_irq(&drv->lock); 656 657 657 658 /* Wait forever for a free tcs. It better be there eventually! */ 658 659 wait_event_lock_irq(drv->tcs_wait, ··· 671 670 write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0); 672 671 enable_tcs_irq(drv, tcs_id, true); 673 672 } 674 - spin_unlock_irqrestore(&drv->lock, flags); 673 + spin_unlock_irq(&drv->lock); 675 674 676 675 /* 677 676 * These two can be done after the lock is released because:
-1
drivers/soc/qcom/rpmh.c
··· 183 183 } 184 184 185 185 if (state == RPMH_ACTIVE_ONLY_STATE) { 186 - WARN_ON(irqs_disabled()); 187 186 ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), &rpm_msg->msg); 188 187 } else { 189 188 /* Clean up our call by spoofing tx_done */