From 9808bbc01bcd32dc599abc8c8961aed79600c771 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 15 Nov 2019 07:01:40 +0800 Subject: [PATCH] ASoC: SOF: Intel: BYT: refine the IPC interrupt handling We should mask interrupt once we got it in the handler, otherwise, we may get interrupt storm in case where the irq thread has no chance to be scheduled. Signed-off-by: Keyon Jie --- sound/soc/sof/intel/byt.c | 44 ++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 2abf80b3eb52fe..80f18bbd3049ae 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -184,13 +184,31 @@ static void byt_dump(struct snd_sof_dev *sdev, u32 flags) static irqreturn_t byt_irq_handler(int irq, void *context) { struct snd_sof_dev *sdev = context; + u64 ipcx, ipcd; u64 isr; int ret = IRQ_NONE; - /* Interrupt arrived, check src */ isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX); - if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY)) + ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX); + ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); + + if ((isr & SHIM_ISRX_DONE) && (ipcx & SHIM_BYT_IPCX_DONE)) { + /* reply message from DSP, Mask Done interrupt first */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, + SHIM_IMRX, + SHIM_IMRX_DONE, + SHIM_IMRX_DONE); + ret = IRQ_WAKE_THREAD; + } + + if ((isr & SHIM_ISRX_BUSY) && (ipcd & SHIM_BYT_IPCD_BUSY)) { + /* new message from DSP, Mask Busy interrupt first */ + snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, + SHIM_IMRX, + SHIM_IMRX_BUSY, + SHIM_IMRX_BUSY); ret = IRQ_WAKE_THREAD; + } return ret; } @@ -203,16 +221,11 @@ static irqreturn_t byt_irq_thread(int irq, void *context) imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX); ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX); + ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); /* reply message from DSP */ - if (ipcx & SHIM_BYT_IPCX_DONE && - !(imrx & SHIM_IMRX_DONE)) { - /* Mask Done interrupt before first */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_DONE, - SHIM_IMRX_DONE); - + if ((ipcx & SHIM_BYT_IPCX_DONE) && + (imrx & SHIM_IMRX_DONE)) { spin_lock_irq(&sdev->ipc_lock); /* @@ -231,15 +244,8 @@ static irqreturn_t byt_irq_thread(int irq, void *context) } /* new message from DSP */ - ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD); - if (ipcd & SHIM_BYT_IPCD_BUSY && - !(imrx & SHIM_IMRX_BUSY)) { - /* Mask Busy interrupt before return */ - snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, - SHIM_IMRX, - SHIM_IMRX_BUSY, - SHIM_IMRX_BUSY); - + if ((ipcd & SHIM_BYT_IPCD_BUSY) && + (imrx & SHIM_IMRX_BUSY)) { /* Handle messages from DSP Core */ if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) { snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +