Skip to content

Commit 5003d0c

Browse files
jbrun3tbroonie
authored andcommitted
ASoC: meson: axg-fifo: fix irq scheduling issue with PREEMPT_RT
With PREEMPT_RT enabled a spinlock_t becomes a sleeping lock. This is usually not a problem with spinlocks used in IRQ context since IRQ handlers get threaded. However, if IRQF_ONESHOT is set, the primary handler won't be force-threaded and runs always in hardirq context. This is a problem because spinlock_t requires a preemptible context on PREEMPT_RT. In this particular instance, regmap mmio uses spinlock_t to protect the register access and IRQF_ONESHOT is set on the IRQ. In this case, it is actually better to do everything in threaded handler and it solves the problem with PREEMPT_RT. Reported-by: Arseniy Krasnov <[email protected]> Closes: https://lore.kernel.org/linux-amlogic/[email protected] Suggested-by: Sebastian Andrzej Siewior <[email protected]> Fixes: b11d266 ("ASoC: meson: axg-fifo: use threaded irq to check periods") Signed-off-by: Jerome Brunet <[email protected]> Reviewed-by: Sebastian Andrzej Siewior <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 2f11f61 commit 5003d0c

File tree

1 file changed

+10
-16
lines changed

1 file changed

+10
-16
lines changed

sound/soc/meson/axg-fifo.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -207,25 +207,18 @@ static irqreturn_t axg_fifo_pcm_irq_block(int irq, void *dev_id)
207207
status = FIELD_GET(STATUS1_INT_STS, status);
208208
axg_fifo_ack_irq(fifo, status);
209209

210-
/* Use the thread to call period elapsed on nonatomic links */
211-
if (status & FIFO_INT_COUNT_REPEAT)
212-
return IRQ_WAKE_THREAD;
210+
if (status & ~FIFO_INT_COUNT_REPEAT)
211+
dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
212+
status);
213213

214-
dev_dbg(axg_fifo_dev(ss), "unexpected irq - STS 0x%02x\n",
215-
status);
214+
if (status & FIFO_INT_COUNT_REPEAT) {
215+
snd_pcm_period_elapsed(ss);
216+
return IRQ_HANDLED;
217+
}
216218

217219
return IRQ_NONE;
218220
}
219221

220-
static irqreturn_t axg_fifo_pcm_irq_block_thread(int irq, void *dev_id)
221-
{
222-
struct snd_pcm_substream *ss = dev_id;
223-
224-
snd_pcm_period_elapsed(ss);
225-
226-
return IRQ_HANDLED;
227-
}
228-
229222
int axg_fifo_pcm_open(struct snd_soc_component *component,
230223
struct snd_pcm_substream *ss)
231224
{
@@ -251,8 +244,9 @@ int axg_fifo_pcm_open(struct snd_soc_component *component,
251244
if (ret)
252245
return ret;
253246

254-
ret = request_threaded_irq(fifo->irq, axg_fifo_pcm_irq_block,
255-
axg_fifo_pcm_irq_block_thread,
247+
/* Use the threaded irq handler only with non-atomic links */
248+
ret = request_threaded_irq(fifo->irq, NULL,
249+
axg_fifo_pcm_irq_block,
256250
IRQF_ONESHOT, dev_name(dev), ss);
257251
if (ret)
258252
return ret;

0 commit comments

Comments
 (0)