Commit 5cd1f5c3 authored by Pardha Saradhi K's avatar Pardha Saradhi K Committed by Mark Brown

ASoC: Intel: Skylake: Fix IPC rx_list corruption

In SKL+ platforms, all IPC commands are serialised, i.e. the driver sends
a new IPC to DSP, only after receiving a reply from the firmware for the
current IPC.

Hence it seems apparent that there is only a single modifier of the IPC RX
List. However, during an IPC timeout case in a multithreaded environment,
there is a possibility of the list element being deleted two times if not
properly protected.

So, use spin lock save/restore to prevent rx_list corruption.
Signed-off-by: default avatarPardha Saradhi K <pardha.saradhi.kesapragada@intel.com>
Signed-off-by: default avatarSubhransu S. Prusty <subhransu.s.prusty@intel.com>
Acked-by: default avatarVinod Koul <vinod.koul@intel.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent ab1b732d
...@@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, ...@@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
u64 *ipc_header = (u64 *)(&header); u64 *ipc_header = (u64 *)(&header);
struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
unsigned long flags;
spin_lock_irqsave(&ipc->dsp->spinlock, flags);
msg = skl_ipc_reply_get_msg(ipc, *ipc_header); msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
if (msg == NULL) { if (msg == NULL) {
dev_dbg(ipc->dev, "ipc: rx list is empty\n"); dev_dbg(ipc->dev, "ipc: rx list is empty\n");
return; return;
...@@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc, ...@@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
} }
} }
spin_lock_irqsave(&ipc->dsp->spinlock, flags);
list_del(&msg->list); list_del(&msg->list);
sst_ipc_tx_msg_reply_complete(ipc, msg); sst_ipc_tx_msg_reply_complete(ipc, msg);
spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
} }
irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment