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/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++; } 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 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 diff --git a/src/ipc/handler.c b/src/ipc/handler.c index bb403666dcbd..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); } @@ -635,14 +636,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 +682,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 +716,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); } 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/apollolake/include/platform/platform.h b/src/platform/apollolake/include/platform/platform.h index 374134e1c7d6..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 5 +#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 c1230e7f60c7..8869763f77a3 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 100 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000 @@ -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) { diff --git a/src/platform/cannonlake/include/platform/platform.h b/src/platform/cannonlake/include/platform/platform.h index b8198857561f..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 5 +#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 fd2a5230ac7d..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 5 +#define DMA_TRACE_RESCHEDULE_TIME 100 /* DSP should be idle in this time frame */ #define PLATFORM_IDLE_TIME 750000