Merge branch 'asoc-5.4' into asoc-5.5
[platform/kernel/linux-starfive.git] / sound / soc / sof / intel / bdw.c
index e282179..f395d06 100644 (file)
@@ -37,6 +37,7 @@
 #define MBOX_SIZE       0x1000
 #define MBOX_DUMP_SIZE 0x30
 #define EXCEPT_OFFSET  0x800
+#define EXCEPT_MAX_HDR_SIZE    0x400
 
 /* DSP peripherals */
 #define DMAC0_OFFSET    0xFE000
@@ -228,6 +229,11 @@ static void bdw_get_registers(struct snd_sof_dev *sdev,
        /* note: variable AR register array is not read */
 
        /* then get panic info */
+       if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
+               dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
+                       xoops->arch_hdr.totalsize);
+               return;
+       }
        offset += xoops->arch_hdr.totalsize;
        sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
 
@@ -241,7 +247,7 @@ static void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
        struct sof_ipc_dsp_oops_xtensa xoops;
        struct sof_ipc_panic_info panic_info;
        u32 stack[BDW_STACK_DUMP_SIZE];
-       u32 status, panic;
+       u32 status, panic, imrx, imrd;
 
        /* now try generic SOF status messages */
        status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
@@ -250,6 +256,26 @@ static void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
                          BDW_STACK_DUMP_SIZE);
        snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
                           BDW_STACK_DUMP_SIZE);
+
+       /* provide some context for firmware debug */
+       imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);
+       imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);
+       dev_err(sdev->dev,
+               "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
+               panic & SHIM_IPCX_BUSY ? "yes" : "no",
+               panic & SHIM_IPCX_DONE ? "yes" : "no", panic);
+       dev_err(sdev->dev,
+               "error: mask host: pending %s complete %s raw 0x%8.8x\n",
+               imrx & SHIM_IMRX_BUSY ? "yes" : "no",
+               imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx);
+       dev_err(sdev->dev,
+               "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
+               status & SHIM_IPCD_BUSY ? "yes" : "no",
+               status & SHIM_IPCD_DONE ? "yes" : "no", status);
+       dev_err(sdev->dev,
+               "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
+               imrd & SHIM_IMRD_BUSY ? "yes" : "no",
+               imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd);
 }
 
 /*
@@ -451,6 +477,7 @@ static int bdw_probe(struct snd_sof_dev *sdev)
        /* TODO: add offsets */
        sdev->mmio_bar = BDW_DSP_BAR;
        sdev->mailbox_bar = BDW_DSP_BAR;
+       sdev->dsp_oops_offset = MBOX_OFFSET;
 
        /* PCI base */
        mmio = platform_get_resource(pdev, IORESOURCE_MEM,