mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
ASoC: stm32: spdifrx: fix inconsistent lock state
In current spdifrx driver locks may be requested as follows:
- request lock on iec capture control, when starting synchronization.
- request lock in interrupt context, when spdifrx stop is called
from IRQ handler.
Take lock with IRQs disabled, to avoid the possible deadlock.
Lockdep report:
[ 74.278059] ================================
[ 74.282306] WARNING: inconsistent lock state
[ 74.290120] --------------------------------
...
[ 74.314373] CPU0
[ 74.314377] ----
[ 74.314381] lock(&(&spdifrx->lock)->rlock);
[ 74.314396] <Interrupt>
[ 74.314400] lock(&(&spdifrx->lock)->rlock);
Fixes: 03e4d5d56f
("ASoC: stm32: Add SPDIFRX support")
Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Link: https://lore.kernel.org/r/20191204154333.7152-2-olivier.moysan@st.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
07d22a9bb6
commit
2859b17840
@ -320,6 +320,7 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx)
|
||||
static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
|
||||
{
|
||||
int cr, cr_mask, imr, ret;
|
||||
unsigned long flags;
|
||||
|
||||
/* Enable IRQs */
|
||||
imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE;
|
||||
@ -327,7 +328,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock(&spdifrx->lock);
|
||||
spin_lock_irqsave(&spdifrx->lock, flags);
|
||||
|
||||
spdifrx->refcount++;
|
||||
|
||||
@ -362,7 +363,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
|
||||
"Failed to start synchronization\n");
|
||||
}
|
||||
|
||||
spin_unlock(&spdifrx->lock);
|
||||
spin_unlock_irqrestore(&spdifrx->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -370,11 +371,12 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
|
||||
static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
|
||||
{
|
||||
int cr, cr_mask, reg;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock(&spdifrx->lock);
|
||||
spin_lock_irqsave(&spdifrx->lock, flags);
|
||||
|
||||
if (--spdifrx->refcount) {
|
||||
spin_unlock(&spdifrx->lock);
|
||||
spin_unlock_irqrestore(&spdifrx->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -393,7 +395,7 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
|
||||
regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, ®);
|
||||
regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, ®);
|
||||
|
||||
spin_unlock(&spdifrx->lock);
|
||||
spin_unlock_irqrestore(&spdifrx->lock, flags);
|
||||
}
|
||||
|
||||
static int stm32_spdifrx_dma_ctrl_register(struct device *dev,
|
||||
|
Loading…
Reference in New Issue
Block a user