Message ID | 20200929133040.RESEND.1.Ideabf6dcdfc577cf39ce3d95b0e4aa1ac8b38f0c@changeid (mailing list archive) |
---|---|
State | Accepted |
Commit | fc3e62e25c3896855b7c3d72df19ca6be3459c9f |
Headers | show |
Series | [RESEND] soc: qcom: smp2p: Safely acquire spinlock without IRQs | expand |
Quoting Evan Green (2020-09-29 13:30:57) > smp2p_update_bits() should disable interrupts when it acquires its > spinlock. This is important because without the _irqsave, a priority > inversion can occur. > > This function is called both with interrupts enabled in > qcom_q6v5_request_stop(), and with interrupts disabled in > ipa_smp2p_panic_notifier(). IRQ handling of spinlocks should be > consistent to avoid the panic notifier deadlocking because it's > sitting on the thread that's already got the lock via _request_stop(). > > Found via lockdep. > > Fixes: 50e99641413e7 ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point") > Signed-off-by: Evan Green <evgreen@chromium.org> > --- Reviewed-by: Stephen Boyd <swboyd@chromium.org>
On Tue 29 Sep 15:30 CDT 2020, Evan Green wrote: > smp2p_update_bits() should disable interrupts when it acquires its > spinlock. This is important because without the _irqsave, a priority > inversion can occur. > > This function is called both with interrupts enabled in > qcom_q6v5_request_stop(), and with interrupts disabled in > ipa_smp2p_panic_notifier(). IRQ handling of spinlocks should be > consistent to avoid the panic notifier deadlocking because it's > sitting on the thread that's already got the lock via _request_stop(). > > Found via lockdep. > > Fixes: 50e99641413e7 ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point") > Signed-off-by: Evan Green <evgreen@chromium.org> Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> Regards, Bjorn > --- > > drivers/soc/qcom/smp2p.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c > index 07183d731d747..a9709aae54abb 100644 > --- a/drivers/soc/qcom/smp2p.c > +++ b/drivers/soc/qcom/smp2p.c > @@ -318,15 +318,16 @@ static int qcom_smp2p_inbound_entry(struct qcom_smp2p *smp2p, > static int smp2p_update_bits(void *data, u32 mask, u32 value) > { > struct smp2p_entry *entry = data; > + unsigned long flags; > u32 orig; > u32 val; > > - spin_lock(&entry->lock); > + spin_lock_irqsave(&entry->lock, flags); > val = orig = readl(entry->value); > val &= ~mask; > val |= value; > writel(val, entry->value); > - spin_unlock(&entry->lock); > + spin_unlock_irqrestore(&entry->lock, flags); > > if (val != orig) > qcom_smp2p_kick(entry->smp2p); > -- > 2.26.2 >
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index 07183d731d747..a9709aae54abb 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -318,15 +318,16 @@ static int qcom_smp2p_inbound_entry(struct qcom_smp2p *smp2p, static int smp2p_update_bits(void *data, u32 mask, u32 value) { struct smp2p_entry *entry = data; + unsigned long flags; u32 orig; u32 val; - spin_lock(&entry->lock); + spin_lock_irqsave(&entry->lock, flags); val = orig = readl(entry->value); val &= ~mask; val |= value; writel(val, entry->value); - spin_unlock(&entry->lock); + spin_unlock_irqrestore(&entry->lock, flags); if (val != orig) qcom_smp2p_kick(entry->smp2p);
smp2p_update_bits() should disable interrupts when it acquires its spinlock. This is important because without the _irqsave, a priority inversion can occur. This function is called both with interrupts enabled in qcom_q6v5_request_stop(), and with interrupts disabled in ipa_smp2p_panic_notifier(). IRQ handling of spinlocks should be consistent to avoid the panic notifier deadlocking because it's sitting on the thread that's already got the lock via _request_stop(). Found via lockdep. Fixes: 50e99641413e7 ("soc: qcom: smp2p: Qualcomm Shared Memory Point to Point") Signed-off-by: Evan Green <evgreen@chromium.org> --- drivers/soc/qcom/smp2p.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)