]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ASoC: SOF: amd: Use semaphore register to synchronize ipc's irq
authorAjit Kumar Pandey <AjitKumar.Pandey@amd.com>
Fri, 4 Mar 2022 20:57:28 +0000 (14:57 -0600)
committerMark Brown <broonie@kernel.org>
Mon, 7 Mar 2022 13:12:49 +0000 (13:12 +0000)
Add lock and unlock around ipc irq handling code using hw semaphore
register that exhibit special property for register read calls. As
host and DSP firmware uses few shared registers, there is a possible
race condition around those shared registers values. This lock ensure
synchronization between Firmware and host ipc interrupts.

Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Signed-off-by: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20220304205733.62233-6-pierre-louis.bossart@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/amd/acp-dsp-offset.h
sound/soc/sof/amd/acp-ipc.c
sound/soc/sof/amd/acp.c
sound/soc/sof/amd/acp.h

index 63f13c111b241390018dbc8dca3dc9400613adeb..40fbf11facba5536779b618e6313f87c9edb81f0 100644 (file)
@@ -61,6 +61,7 @@
 #define ACP_DSP_SW_INTR_STAT                    0x1818
 #define ACP_SW_INTR_TRIG                        0x181C
 #define ACP_ERROR_STATUS                       0x18C4
+#define ACP_AXI2DAGB_SEM_0                     0x1880
 
 /* Registers from ACP_SHA block */
 #define ACP_SHA_DSP_FW_QUALIFIER               0x1C70
index cd5af3d85002353ba289ee96cfa7507a54fb294f..9fcd2535fd3b1ea8fe75de5c26d9867d0077af6a 100644 (file)
@@ -62,12 +62,26 @@ int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
 {
        struct acp_dev_data *adata = sdev->pdata->hw_pdata;
        unsigned int offset = offsetof(struct scratch_ipc_conf, sof_in_box);
+       unsigned int count = ACP_HW_SEM_RETRY_COUNT;
+
+       while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0)) {
+               /* Wait until acquired HW Semaphore Lock or timeout*/
+               count--;
+               if (!count) {
+                       dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
+                       return -EINVAL;
+               }
+       };
 
        acp_mailbox_write(sdev, offset, msg->msg_data, msg->msg_size);
        acp_ipc_host_msg_set(sdev);
 
        /* Trigger host to dsp interrupt for the msg */
        acpbus_trigger_host_to_dsp_swintr(adata);
+
+       /* Unlock or Release HW Semaphore */
+       snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0, 0x0);
+
        return 0;
 }
 EXPORT_SYMBOL_NS(acp_sof_ipc_send_msg, SND_SOC_SOF_AMD_COMMON);
index fe9b7dc5bc8669ccf20a83b8d6a1f47bfe3df953..ba8b6427b59f13909dde480f00e849a3c04e1230 100644 (file)
@@ -273,7 +273,7 @@ static int acp_memory_init(struct snd_sof_dev *sdev)
 static irqreturn_t acp_irq_thread(int irq, void *context)
 {
        struct snd_sof_dev *sdev = context;
-       unsigned int val;
+       unsigned int val, count = ACP_HW_SEM_RETRY_COUNT;
 
        val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_EXTERNAL_INTR_STAT);
        if (val & ACP_SHA_STAT) {
@@ -284,9 +284,22 @@ static irqreturn_t acp_irq_thread(int irq, void *context)
 
        val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_DSP_SW_INTR_STAT);
        if (val & ACP_DSP_TO_HOST_IRQ) {
+               while (snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0)) {
+                       /* Wait until acquired HW Semaphore lock or timeout */
+                       count--;
+                       if (!count) {
+                               dev_err(sdev->dev, "%s: Failed to acquire HW lock\n", __func__);
+                               return IRQ_NONE;
+                       }
+               };
+
                sof_ops(sdev)->irq_thread(irq, sdev);
                val |= ACP_DSP_TO_HOST_IRQ;
                snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_DSP_SW_INTR_STAT, val);
+
+               /* Unlock or Release HW Semaphore */
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_AXI2DAGB_SEM_0, 0x0);
+
                return IRQ_HANDLED;
        }
 
index 8ed4e338467f70cc4cf00d95a327c4324f85b312..db1030d36811dbaa713a18e42bca0a56dbea1877 100644 (file)
@@ -17,6 +17,7 @@
 
 #define ACP_DSP_BAR    0
 
+#define ACP_HW_SEM_RETRY_COUNT                 10
 #define ACP_REG_POLL_INTERVAL                   500
 #define ACP_REG_POLL_TIMEOUT_US                 2000
 #define ACP_DMA_COMPLETE_TIMEOUT_US            5000