From 9ebd1bce8849b85401d1d333d0efa23f7a080b8f Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 3 Sep 2018 15:21:03 +0800 Subject: [PATCH 1/8] dw-dma: refine dw_dma_stop to clear done bit in all lli The initialization of lli should be out of loop Signed-off-by: Rander Wang --- src/drivers/intel/dw-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/intel/dw-dma.c b/src/drivers/intel/dw-dma.c index da875b4992a1..b94917ec5ec4 100644 --- a/src/drivers/intel/dw-dma.c +++ b/src/drivers/intel/dw-dma.c @@ -508,8 +508,8 @@ static int dw_dma_stop(struct dma *dma, int channel) dw_write(dma, DW_DMA_CHAN_EN, CHAN_DISABLE(channel)); #if DW_USE_HW_LLI + lli = p->chan[channel].lli; for (i = 0; i < p->chan[channel].desc_count; i++) { - lli = p->chan[channel].lli; lli->ctrl_hi &= ~DW_CTLH_DONE(1); lli++; } From 734a5bfe70dc9a30ba0d5318958d9b19786f0b04 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Thu, 6 Sep 2018 15:23:39 +0800 Subject: [PATCH 2/8] wait: add check for waiti waiti can only work with interrupt level 0, check if the level is 0 and set SOF_IPC_PANIC_WFI panic. Signed-off-by: Liam Girdwood Signed-off-by: Pan Xiuli --- src/arch/xtensa/include/arch/wait.h | 13 ++++++++++++- src/include/uapi/ipc.h | 21 +++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/arch/xtensa/include/arch/wait.h b/src/arch/xtensa/include/arch/wait.h index e1cca01c32d8..857b50e09560 100644 --- a/src/arch/xtensa/include/arch/wait.h +++ b/src/arch/xtensa/include/arch/wait.h @@ -29,6 +29,9 @@ */ #include +#include +#include + #if defined(PLATFORM_WAITI_DELAY) @@ -36,6 +39,10 @@ static inline void arch_wait_for_interrupt(int level) { int i; + /* can only eneter WFI when at runlevel 0 i.e. not IRQ level */ + if (arch_interrupt_get_level() > 0) + panic(SOF_IPC_PANIC_WFI); + /* this sequnce must be atomic on LX6 */ XTOS_SET_INTLEVEL(5); @@ -55,7 +62,11 @@ static inline void arch_wait_for_interrupt(int level) static inline void arch_wait_for_interrupt(int level) { - asm volatile("waiti 0"); + /* can only eneter WFI when at runlevel 0 i.e. not IRQ level */ + if (arch_interrupt_get_level() > 0) + panic(SOF_IPC_PANIC_WFI); + + asm volatile("waiti 0"); } #endif diff --git a/src/include/uapi/ipc.h b/src/include/uapi/ipc.h index 7b9c85fed2c4..23118cbceef5 100644 --- a/src/include/uapi/ipc.h +++ b/src/include/uapi/ipc.h @@ -144,16 +144,17 @@ #define SOF_IPC_PANIC_MAGIC 0x0dead000 #define SOF_IPC_PANIC_MAGIC_MASK 0x0ffff000 #define SOF_IPC_PANIC_CODE_MASK 0x00000fff -#define SOF_IPC_PANIC_MEM (SOF_IPC_PANIC_MAGIC | 0) -#define SOF_IPC_PANIC_WORK (SOF_IPC_PANIC_MAGIC | 1) -#define SOF_IPC_PANIC_IPC (SOF_IPC_PANIC_MAGIC | 2) -#define SOF_IPC_PANIC_ARCH (SOF_IPC_PANIC_MAGIC | 3) -#define SOF_IPC_PANIC_PLATFORM (SOF_IPC_PANIC_MAGIC | 4) -#define SOF_IPC_PANIC_TASK (SOF_IPC_PANIC_MAGIC | 5) -#define SOF_IPC_PANIC_EXCEPTION (SOF_IPC_PANIC_MAGIC | 6) -#define SOF_IPC_PANIC_DEADLOCK (SOF_IPC_PANIC_MAGIC | 7) -#define SOF_IPC_PANIC_STACK (SOF_IPC_PANIC_MAGIC | 8) -#define SOF_IPC_PANIC_IDLE (SOF_IPC_PANIC_MAGIC | 9) +#define SOF_IPC_PANIC_MEM (SOF_IPC_PANIC_MAGIC | 0x0) +#define SOF_IPC_PANIC_WORK (SOF_IPC_PANIC_MAGIC | 0x1) +#define SOF_IPC_PANIC_IPC (SOF_IPC_PANIC_MAGIC | 0x2) +#define SOF_IPC_PANIC_ARCH (SOF_IPC_PANIC_MAGIC | 0x3) +#define SOF_IPC_PANIC_PLATFORM (SOF_IPC_PANIC_MAGIC | 0x4) +#define SOF_IPC_PANIC_TASK (SOF_IPC_PANIC_MAGIC | 0x5) +#define SOF_IPC_PANIC_EXCEPTION (SOF_IPC_PANIC_MAGIC | 0x6) +#define SOF_IPC_PANIC_DEADLOCK (SOF_IPC_PANIC_MAGIC | 0x7) +#define SOF_IPC_PANIC_STACK (SOF_IPC_PANIC_MAGIC | 0x8) +#define SOF_IPC_PANIC_IDLE (SOF_IPC_PANIC_MAGIC | 0x9) +#define SOF_IPC_PANIC_WFI (SOF_IPC_PANIC_MAGIC | 0xa) /* * SOF memory capabilities, add new ones at the end From c0c720a6cb6a0c8c09c2d97d780a13f668ef9642 Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Mon, 3 Sep 2018 15:54:32 +0800 Subject: [PATCH 3/8] dma-trace: workaround reschedule work fail If reschedule work timeout is too small. The reschedule will fail. Workaround this issue by increace the reschedule timeout. Signed-off-by: Pan Xiuli --- src/platform/apollolake/include/platform/platform.h | 2 +- src/platform/baytrail/include/platform/platform.h | 2 +- src/platform/cannonlake/include/platform/platform.h | 2 +- src/platform/haswell/include/platform/platform.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index 374134e1c7d6..c3457d7f0537 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -107,7 +107,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 5 +#define DMA_TRACE_RESCHEDULE_TIME 500 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index c1230e7f60c7..1d03e64f95a6 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -94,7 +94,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 5 +#define DMA_TRACE_RESCHEDULE_TIME 500 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index b8198857561f..c66ab9f76c83 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -113,7 +113,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 5 +#define DMA_TRACE_RESCHEDULE_TIME 500 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 diff --git a/src/platform/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h index fd2a5230ac7d..136292ce510c 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -93,7 +93,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 5 +#define DMA_TRACE_RESCHEDULE_TIME 500 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 From be0b05897432bc6b9c17e46c6ed9eac6a5e9e5b2 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Thu, 6 Sep 2018 16:13:54 +0800 Subject: [PATCH 4/8] dma-trace: tune the dma trace reschedule time 500us woulld cause dma trace buffer overflow at the boot up time. Now refine it to 100us to make both scheduler and dma trace happy Signed-off-by: Rander Wang --- src/platform/apollolake/include/platform/platform.h | 2 +- src/platform/baytrail/include/platform/platform.h | 2 +- src/platform/cannonlake/include/platform/platform.h | 2 +- src/platform/haswell/include/platform/platform.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platform/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index c3457d7f0537..89e99936f9e1 100644 --- a/src/platform/apollolake/include/platform/platform.h +++ b/src/platform/apollolake/include/platform/platform.h @@ -107,7 +107,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 500 +#define DMA_TRACE_RESCHEDULE_TIME 100 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index 1d03e64f95a6..2bd5d0577c73 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -94,7 +94,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 500 +#define DMA_TRACE_RESCHEDULE_TIME 100 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index c66ab9f76c83..5315dd1cd8d6 100644 --- a/src/platform/cannonlake/include/platform/platform.h +++ b/src/platform/cannonlake/include/platform/platform.h @@ -113,7 +113,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 500 +#define DMA_TRACE_RESCHEDULE_TIME 100 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 diff --git a/src/platform/haswell/include/platform/platform.h b/src/platform/haswell/include/platform/platform.h index 136292ce510c..938bb8a8417e 100644 --- a/src/platform/haswell/include/platform/platform.h +++ b/src/platform/haswell/include/platform/platform.h @@ -93,7 +93,7 @@ struct sof; * the interval of reschedule DMA trace copying in special case like half * fullness of local DMA trace buffer */ -#define DMA_TRACE_RESCHEDULE_TIME 500 +#define DMA_TRACE_RESCHEDULE_TIME 100 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 From 0df634e8a987feb50699a77c7050c1d0985a8cad Mon Sep 17 00:00:00 2001 From: Pan Xiuli Date: Mon, 3 Sep 2018 17:02:09 +0800 Subject: [PATCH 5/8] list: refine list_item_del to avoid make list chaos There are possible that we call list_item_del to same list item twice. This will cause the list be into chaos. Reset the next and prev pointer to 0 to avoid risk. Signed-off-by: Pan Xiuli --- src/include/sof/list.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/include/sof/list.h b/src/include/sof/list.h index 3174377ee19e..e91309cb33ba 100644 --- a/src/include/sof/list.h +++ b/src/include/sof/list.h @@ -79,6 +79,7 @@ static inline void list_item_del(struct list_item *item) { item->next->prev = item->prev; item->prev->next = item->next; + list_init(item); } /* delete item from the list list iteam will be reinitialised From 7c400d0f7f8f1e868e7a576c2526513bb32dc97a Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Fri, 7 Sep 2018 17:55:15 +0800 Subject: [PATCH 6/8] byt: remove waiti on byt waiti would cause FW panic if it is called in irq level higher than passive level. Signed-off-by: Rander Wang --- src/ipc/pmc-ipc.c | 21 ++++++++++--------- .../baytrail/include/platform/platform.h | 3 +++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/ipc/pmc-ipc.c b/src/ipc/pmc-ipc.c index 9a305555c893..8c2602b000cc 100644 --- a/src/ipc/pmc-ipc.c +++ b/src/ipc/pmc-ipc.c @@ -126,7 +126,7 @@ static void irq_handler(void *arg) int ipc_pmc_send_msg(uint32_t message) { uint32_t ipclpesch; - uint32_t irq_mask; + int try = 0; trace_ipc("SMs"); @@ -138,22 +138,23 @@ int ipc_pmc_send_msg(uint32_t message) return -EAGAIN; } - /* disable all interrupts except for SCU */ - irq_mask = arch_interrupt_disable_mask(~(1 << IRQ_NUM_EXT_PMC)); - /* send the new message */ shim_write(SHIM_IPCLPESCL, 0); shim_write(SHIM_IPCLPESCH, SHIM_IPCLPESCH_BUSY | message); - /* now wait for clock change */ - wait_for_interrupt(0); - - /* enable other IRQs */ - arch_interrupt_enable_mask(irq_mask); - /* check status */ ipclpesch = shim_read(SHIM_IPCLPESCH); + while (ipclpesch & SHIM_IPCLPESCH_BUSY) { + /* now wait for clock change */ + idelay(PLATFORM_LPE_DELAY); + ipclpesch = shim_read(SHIM_IPCLPESCH); + + try++; + if (try > 10) + break; + } + /* did command succeed */ if (ipclpesch & SHIM_IPCLPESCH_BUSY) { trace_ipc_error("ePf"); diff --git a/src/platform/baytrail/include/platform/platform.h b/src/platform/baytrail/include/platform/platform.h index 2bd5d0577c73..8869763f77a3 100644 --- a/src/platform/baytrail/include/platform/platform.h +++ b/src/platform/baytrail/include/platform/platform.h @@ -102,6 +102,9 @@ struct sof; /* DSP default delay in cycles */ #define PLATFORM_DEFAULT_DELAY 12 +/* DSP LPE delay in cycles */ +#define PLATFORM_LPE_DELAY 2000 + /* Platform defined panic code */ static inline void platform_panic(uint32_t p) { From bc96f88e659ae941b62c6cfe0f789d362552c27f Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 10 Sep 2018 12:28:29 +0800 Subject: [PATCH 7/8] dma-trace: kill a infinite loop in dma_trace_config Don't delete item with list_for_item. with list_for_item, a item is deleted from list but the next of this item is used to visit the list. Signed-off-by: Rander Wang --- src/ipc/handler.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ipc/handler.c b/src/ipc/handler.c index bb403666dcbd..0affb4fb7fe3 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -635,14 +635,14 @@ static int ipc_glb_pm_message(uint32_t header) /* * Debug IPC Operations. */ - static int ipc_dma_trace_config(uint32_t header) { #ifdef CONFIG_HOST_PTABLE struct intel_ipc_data *iipc = ipc_get_drvdata(_ipc); struct list_item elem_list; struct dma_sg_elem *elem; - struct list_item *plist; + struct list_item *clist; + struct list_item *tlist; uint32_t ring_size; #endif struct sof_ipc_dma_trace_params *params = _ipc->comp_data; @@ -681,8 +681,8 @@ static int ipc_dma_trace_config(uint32_t header) goto error; } - list_for_item(plist, &elem_list) { - elem = container_of(plist, struct dma_sg_elem, list); + list_for_item_safe(clist, tlist, &elem_list) { + elem = container_of(clist, struct dma_sg_elem, list); err = dma_trace_host_buffer(_ipc->dmat, elem, ring_size); if (err < 0) { @@ -715,8 +715,8 @@ static int ipc_dma_trace_config(uint32_t header) error: #ifdef CONFIG_HOST_PTABLE - list_for_item(plist, &elem_list) { - elem = container_of(plist, struct dma_sg_elem, list); + list_for_item_safe(clist, tlist, &elem_list) { + elem = container_of(clist, struct dma_sg_elem, list); list_item_del(&elem->list); rfree(elem); } From 1ff4a9df32844b7ef58007ee83ef1759ffe43ae2 Mon Sep 17 00:00:00 2001 From: Rander Wang Date: Mon, 10 Sep 2018 12:55:36 +0800 Subject: [PATCH 8/8] playback: kill a infinite loop in pcm_param Don't delete item with list_for_item. with list_for_item, a item is deleted from list but the next of this item is used to visit the list. Signed-off-by: Rander Wang --- src/ipc/handler.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 0affb4fb7fe3..92aef8a845e0 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -167,7 +167,8 @@ static int ipc_stream_pcm_params(uint32_t stream) struct sof_ipc_comp_host *host = NULL; struct list_item elem_list; struct dma_sg_elem *elem; - struct list_item *plist; + struct list_item *clist; + struct list_item *tlist; uint32_t ring_size; #endif struct sof_ipc_pcm_params *pcm_params = _ipc->comp_data; @@ -233,8 +234,8 @@ static int ipc_stream_pcm_params(uint32_t stream) goto error; } - list_for_item(plist, &elem_list) { - elem = container_of(plist, struct dma_sg_elem, list); + list_for_item_safe(clist, tlist, &elem_list) { + elem = container_of(clist, struct dma_sg_elem, list); err = comp_host_buffer(cd, elem, ring_size); if (err < 0) { @@ -279,8 +280,8 @@ static int ipc_stream_pcm_params(uint32_t stream) error: #ifdef CONFIG_HOST_PTABLE - list_for_item(plist, &elem_list) { - elem = container_of(plist, struct dma_sg_elem, list); + list_for_item_safe(clist, tlist, &elem_list) { + elem = container_of(clist, struct dma_sg_elem, list); list_item_del(&elem->list); rfree(elem); }