aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPardha Saradhi K <pardha.saradhi.kesapragada@intel.com>2017-05-15 10:14:29 -0400
committerMark Brown <broonie@kernel.org>2017-05-24 13:25:12 -0400
commit5cd1f5c32132101955d7f0e1955249a84f9b6fd9 (patch)
tree49661588fbe3b0e3b083b45bda00e654f21c6e5c
parentab1b732d53c18f26f51cad49371be3244fe67504 (diff)
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: Pardha Saradhi K <pardha.saradhi.kesapragada@intel.com> Signed-off-by: Subhransu S. Prusty <subhransu.s.prusty@intel.com> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--sound/soc/intel/skylake/skl-sst-ipc.c5
1 files changed, 5 insertions, 0 deletions
diff --git a/sound/soc/intel/skylake/skl-sst-ipc.c b/sound/soc/intel/skylake/skl-sst-ipc.c
index 58c525096a7c..498b15345b1a 100644
--- a/sound/soc/intel/skylake/skl-sst-ipc.c
+++ b/sound/soc/intel/skylake/skl-sst-ipc.c
@@ -413,8 +413,11 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
413 u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK; 413 u32 reply = header.primary & IPC_GLB_REPLY_STATUS_MASK;
414 u64 *ipc_header = (u64 *)(&header); 414 u64 *ipc_header = (u64 *)(&header);
415 struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc); 415 struct skl_sst *skl = container_of(ipc, struct skl_sst, ipc);
416 unsigned long flags;
416 417
418 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
417 msg = skl_ipc_reply_get_msg(ipc, *ipc_header); 419 msg = skl_ipc_reply_get_msg(ipc, *ipc_header);
420 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
418 if (msg == NULL) { 421 if (msg == NULL) {
419 dev_dbg(ipc->dev, "ipc: rx list is empty\n"); 422 dev_dbg(ipc->dev, "ipc: rx list is empty\n");
420 return; 423 return;
@@ -456,8 +459,10 @@ static void skl_ipc_process_reply(struct sst_generic_ipc *ipc,
456 } 459 }
457 } 460 }
458 461
462 spin_lock_irqsave(&ipc->dsp->spinlock, flags);
459 list_del(&msg->list); 463 list_del(&msg->list);
460 sst_ipc_tx_msg_reply_complete(ipc, msg); 464 sst_ipc_tx_msg_reply_complete(ipc, msg);
465 spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
461} 466}
462 467
463irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context) 468irqreturn_t skl_dsp_irq_thread_handler(int irq, void *context)