From eb4b4c11665e0e1f50d05380c30bf93e1ddf8b56 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 27 Feb 2020 09:40:51 +0100 Subject: [PATCH 1/6] ipc: add is_notification_pending parameter Adds additional parameter to control whether upstream IPC channel is currently free or not. It's helpful in case for some reason checking IPC bits is not enough. Signed-off-by: Tomasz Lauda --- src/drivers/imx/ipc.c | 8 +++++++- src/drivers/intel/baytrail/ipc.c | 8 +++++++- src/drivers/intel/cavs/ipc.c | 10 ++++++++-- src/drivers/intel/haswell/ipc.c | 8 +++++++- src/include/sof/drivers/ipc.h | 1 + 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/drivers/imx/ipc.c b/src/drivers/imx/ipc.c index 8590bc8a351b..b5559ada2961 100644 --- a/src/drivers/imx/ipc.c +++ b/src/drivers/imx/ipc.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,8 @@ static void irq_handler(void *arg) interrupt_clear(PLATFORM_IPC_INTERRUPT); + ipc->is_notification_pending = false; + /* unmask GP interrupt #1 */ imx_mu_xcr_rmw(IMX_MU_xCR_GIEn(1), 0); } @@ -114,7 +117,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) spin_lock_irq(&ipc->lock, flags); /* can't send notification when one is in progress */ - if (imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) + if (ipc->is_notification_pending || + imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) goto out; /* now send the message */ @@ -122,6 +126,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) list_item_del(&msg->list); tracev_ipc("ipc: msg tx -> 0x%x", msg->header); + ipc->is_notification_pending = true; + /* now interrupt host to tell it we have sent a message */ imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0); diff --git a/src/drivers/intel/baytrail/ipc.c b/src/drivers/intel/baytrail/ipc.c index 62edd9885117..b1ff7ed7b860 100644 --- a/src/drivers/intel/baytrail/ipc.c +++ b/src/drivers/intel/baytrail/ipc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /* private data for IPC */ @@ -50,6 +51,8 @@ static void irq_handler(void *arg) shim_write(SHIM_IPCDH, shim_read(SHIM_IPCDH) & ~SHIM_IPCDH_DONE); + ipc->is_notification_pending = false; + /* unmask Done interrupt */ shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE); } @@ -102,7 +105,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) spin_lock_irq(&ipc->lock, flags); /* can't send notification when one is in progress */ - if (shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) + if (ipc->is_notification_pending || + shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) goto out; /* now send the message */ @@ -110,6 +114,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) list_item_del(&msg->list); tracev_ipc("ipc: msg tx -> 0x%x", msg->header); + ipc->is_notification_pending = true; + /* now interrupt host to tell it we have message sent */ shim_write(SHIM_IPCDL, msg->header); shim_write(SHIM_IPCDH, SHIM_IPCDH_BUSY); diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index ec98f8b7e354..c1ec43c5e7af 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -25,6 +25,7 @@ #include #endif #include +#include #include #include @@ -119,6 +120,8 @@ static void ipc_irq_handler(void *arg) ipc_read(IPC_DIPCIDA) | IPC_DIPCIDA_DONE); #endif + ipc->is_notification_pending = false; + /* unmask Done interrupt */ ipc_write(IPC_DIPCCTL, ipc_read(IPC_DIPCCTL) | IPC_DIPCCTL_IPCIDIE); @@ -247,10 +250,11 @@ void ipc_platform_send_msg(struct ipc_msg *msg) spin_lock_irq(&ipc->lock, flags); + if (ipc->is_notification_pending || #if CAVS_VERSION == CAVS_VERSION_1_5 - if (ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) + ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) #else - if (ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY || + ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY || ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE) #endif goto out; @@ -260,6 +264,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) list_item_del(&msg->list); tracev_ipc("ipc: msg tx -> 0x%x", msg->header); + ipc->is_notification_pending = true; + /* now interrupt host to tell it we have message sent */ #if CAVS_VERSION == CAVS_VERSION_1_5 ipc_write(IPC_DIPCIE, 0); diff --git a/src/drivers/intel/haswell/ipc.c b/src/drivers/intel/haswell/ipc.c index ac48338c0b03..3c9918a5324c 100644 --- a/src/drivers/intel/haswell/ipc.c +++ b/src/drivers/intel/haswell/ipc.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /* private data for IPC */ @@ -46,6 +47,8 @@ static void irq_handler(void *arg) /* clear DONE bit - tell Host we have completed */ shim_write(SHIM_IPCD, 0); + ipc->is_notification_pending = false; + /* unmask Done interrupt */ shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_DONE); } @@ -104,7 +107,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) spin_lock_irq(&ipc->lock, flags); /* can't send nofication when one is in progress */ - if (shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) + if (ipc->is_notification_pending || + shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) goto out; /* now send the message */ @@ -112,6 +116,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) list_item_del(&msg->list); tracev_ipc("ipc: msg tx -> 0x%x", msg->header); + ipc->is_notification_pending = true; + /* now interrupt host to tell it we have message sent */ shim_write(SHIM_IPCD, SHIM_IPCD_BUSY); diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h index fa5ad7935aa9..f1731357182d 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -92,6 +92,7 @@ struct ipc { struct list_item msg_list; /* queue of messages to be sent */ struct list_item empty_list; /* queue of empty messages */ + bool is_notification_pending; /* notification is being sent to host */ struct list_item comp_list; /* list of component devices */ From 48c93c3b89c76cc8047d789e8bac530a1afabc7b Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 27 Feb 2020 09:47:48 +0100 Subject: [PATCH 2/6] ipc: return status on notification sending Returns status -EBUSY, when IPC upstream channel is currently busy and notification cannot be sent. Signed-off-by: Tomasz Lauda --- src/drivers/imx/ipc.c | 9 +++++++-- src/drivers/intel/baytrail/ipc.c | 9 +++++++-- src/drivers/intel/cavs/ipc.c | 11 ++++++++--- src/drivers/intel/cavs/sue-ipc.c | 4 +++- src/drivers/intel/haswell/ipc.c | 9 +++++++-- src/include/sof/drivers/ipc.h | 2 +- src/platform/library/include/platform/platform.h | 2 +- 7 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/drivers/imx/ipc.c b/src/drivers/imx/ipc.c index b5559ada2961..748688f44465 100644 --- a/src/drivers/imx/ipc.c +++ b/src/drivers/imx/ipc.c @@ -109,17 +109,20 @@ void ipc_platform_complete_cmd(void *data) platform_shared_commit(ipc, sizeof(*ipc)); } -void ipc_platform_send_msg(struct ipc_msg *msg) +int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); uint32_t flags; + int ret = 0; spin_lock_irq(&ipc->lock, flags); /* can't send notification when one is in progress */ if (ipc->is_notification_pending || - imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) + imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) { + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); @@ -139,6 +142,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) platform_shared_commit(ipc, sizeof(*ipc)); spin_unlock_irq(&ipc->lock, flags); + + return ret; } #if CONFIG_HOST_PTABLE diff --git a/src/drivers/intel/baytrail/ipc.c b/src/drivers/intel/baytrail/ipc.c index b1ff7ed7b860..3ad61e189979 100644 --- a/src/drivers/intel/baytrail/ipc.c +++ b/src/drivers/intel/baytrail/ipc.c @@ -97,17 +97,20 @@ void ipc_platform_complete_cmd(void *data) shim_write(SHIM_IMRD, shim_read(SHIM_IMRD) & ~SHIM_IMRD_BUSY); } -void ipc_platform_send_msg(struct ipc_msg *msg) +int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); uint32_t flags; + int ret = 0; spin_lock_irq(&ipc->lock, flags); /* can't send notification when one is in progress */ if (ipc->is_notification_pending || - shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) + shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) { + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); @@ -128,6 +131,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) platform_shared_commit(ipc, sizeof(*ipc)); spin_unlock_irq(&ipc->lock, flags); + + return ret; } struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index c1ec43c5e7af..ef88274ba413 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -243,21 +243,24 @@ void ipc_platform_complete_cmd(void *data) #endif } -void ipc_platform_send_msg(struct ipc_msg *msg) +int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); uint32_t flags; + int ret = 0; spin_lock_irq(&ipc->lock, flags); if (ipc->is_notification_pending || #if CAVS_VERSION == CAVS_VERSION_1_5 - ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) + ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) { #else ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY || - ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE) + ipc_read(IPC_DIPCIDA) & IPC_DIPCIDA_DONE) { #endif + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); @@ -283,6 +286,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) platform_shared_commit(ipc, sizeof(*ipc)); spin_unlock_irq(&ipc->lock, flags); + + return ret; } int platform_ipc_init(struct ipc *ipc) diff --git a/src/drivers/intel/cavs/sue-ipc.c b/src/drivers/intel/cavs/sue-ipc.c index bfd021aa6c44..73663aaf0765 100644 --- a/src/drivers/intel/cavs/sue-ipc.c +++ b/src/drivers/intel/cavs/sue-ipc.c @@ -51,7 +51,7 @@ void ipc_platform_complete_cmd(void *data) { } -void ipc_platform_send_msg(struct ipc_msg *msg) +int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); uint32_t flags; @@ -70,6 +70,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) platform_shared_commit(ipc, sizeof(*ipc)); spin_unlock_irq(&ipc->lock, flags); + + return 0; } int platform_ipc_init(struct ipc *ipc) diff --git a/src/drivers/intel/haswell/ipc.c b/src/drivers/intel/haswell/ipc.c index 3c9918a5324c..1a68820fedb6 100644 --- a/src/drivers/intel/haswell/ipc.c +++ b/src/drivers/intel/haswell/ipc.c @@ -99,17 +99,20 @@ void ipc_platform_complete_cmd(void *data) platform_shared_commit(ipc, sizeof(*ipc)); } -void ipc_platform_send_msg(struct ipc_msg *msg) +int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); uint32_t flags; + int ret = 0; spin_lock_irq(&ipc->lock, flags); /* can't send nofication when one is in progress */ if (ipc->is_notification_pending || - shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) + shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) { + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); @@ -129,6 +132,8 @@ void ipc_platform_send_msg(struct ipc_msg *msg) platform_shared_commit(ipc, sizeof(*ipc)); spin_unlock_irq(&ipc->lock, flags); + + return ret; } struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h index f1731357182d..5f692ed0383e 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -166,7 +166,7 @@ void ipc_prepare_host_message(struct ipc_msg *msg, uint32_t header, int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, size_t tx_bytes, bool replace); -void ipc_platform_send_msg(struct ipc_msg *msg); +int ipc_platform_send_msg(struct ipc_msg *msg); void ipc_send_queued_msg(void); diff --git a/src/platform/library/include/platform/platform.h b/src/platform/library/include/platform/platform.h index 451bd8b4210f..03b985d0cc63 100644 --- a/src/platform/library/include/platform/platform.h +++ b/src/platform/library/include/platform/platform.h @@ -52,7 +52,7 @@ static inline void platform_wait_for_interrupt(int level) arch_wait_for_interrupt(level); } -static inline void ipc_platform_send_msg(struct ipc_msg *msg) { } +static inline int ipc_platform_send_msg(struct ipc_msg *msg) { return 0; } #endif /* __PLATFORM_PLATFORM_H__ */ From 36ec05997ccc685c34c4463cc3ee6fd9d333b5b1 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Thu, 27 Feb 2020 09:58:55 +0100 Subject: [PATCH 3/6] ipc: add improved functions to sending notifications Adds improved implementation for sending IPC notifications to host. New function takes ipc_msg directly and adds it to message queue if message is not already there. Also critical notifications will be sent right away or added to the beginning of the queue if sending fails. Signed-off-by: Tomasz Lauda --- src/include/sof/drivers/ipc.h | 2 ++ src/ipc/handler.c | 37 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h index 5f692ed0383e..9ea3f4f1fd52 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -170,6 +170,8 @@ int ipc_platform_send_msg(struct ipc_msg *msg); void ipc_send_queued_msg(void); +void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority); + /** * \brief Data provided by the platform which use ipc...page_descriptors(). * diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 76c00e7e1d16..74fc3dbfe833 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -1525,6 +1525,43 @@ int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, return ret; } +void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) +{ + struct ipc *ipc = ipc_get(); + uint32_t flags; + int ret; + + spin_lock_irq(&ipc->lock, flags); + + /* copy mailbox data to message */ + if (msg->tx_size > 0 && msg->tx_size < SOF_IPC_MSG_MAX_SIZE) { + ret = memcpy_s(msg->tx_data, msg->tx_size, data, msg->tx_size); + assert(!ret); + } + + /* try to send critical notifications right away */ + if (high_priority) { + ret = ipc_platform_send_msg(msg); + if (!ret) + goto out; + } + + /* add to queue unless already there */ + if (list_is_empty(&msg->list)) { + if (high_priority) + list_item_prepend(&msg->list, &ipc->msg_list); + else + list_item_append(&msg->list, &ipc->msg_list); + } + +out: + platform_shared_commit(msg->tx_data, msg->tx_size); + platform_shared_commit(msg, sizeof(*msg)); + platform_shared_commit(ipc, sizeof(*ipc)); + + spin_unlock_irq(&ipc->lock, flags); +} + void ipc_schedule_process(struct ipc *ipc) { schedule_task(&ipc->ipc_task, 0, 100); From 12c07c14e3f9a4aa706ea06091efb1f011450f28 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Fri, 28 Feb 2020 09:05:25 +0100 Subject: [PATCH 4/6] ipc: add helper methods for building notifications Adds helper methods for initial building of IPC notifications. Signed-off-by: Tomasz Lauda --- src/audio/detect_test.c | 2 +- src/audio/host.c | 3 ++- src/audio/pipeline.c | 2 ++ src/include/sof/drivers/ipc.h | 28 ++++++++++++++++++++++++++++ src/include/sof/trace/dma-trace.h | 5 ++--- src/ipc/handler.c | 6 +++--- src/trace/dma-trace.c | 25 +++++++++++++------------ 7 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/audio/detect_test.c b/src/audio/detect_test.c index 5e7be6595909..8601d60a7979 100644 --- a/src/audio/detect_test.c +++ b/src/audio/detect_test.c @@ -112,7 +112,7 @@ static void notify_host(const struct comp_dev *dev) event.event_type = SOF_CTRL_EVENT_KD; event.num_elems = 0; - ipc_build_comp_notification(dev, &event); + ipc_build_comp_event(&event, dev_comp_type(dev), dev_comp_id(dev)); ipc_prepare_host_message(&cd->msg, event.rhdr.hdr.cmd, &event, sizeof(event)); diff --git a/src/audio/host.c b/src/audio/host.c index af6fedbf6b9f..76cf60fdc7fc 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -362,9 +362,10 @@ static struct comp_dev *host_new(const struct comp_driver *drv, dma_sg_init(&hd->host.elem_array); dma_sg_init(&hd->local.elem_array); + ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, comp->id); + hd->chan = NULL; hd->copy_type = COMP_COPY_NORMAL; - hd->posn.comp_id = comp->id; dev->state = COMP_STATE_READY; return dev; diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index 383661f9ce18..a918655b06a7 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -859,6 +859,8 @@ void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, ret); memset(&posn, 0, sizeof(posn)); + ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN, + dev_comp_id(dev)); p->xrun_bytes = bytes; posn.xrun_size = bytes; posn.xrun_comp_id = dev_comp_id(dev); diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h index 9ea3f4f1fd52..758371619781 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -15,7 +15,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -125,6 +128,31 @@ static inline uint64_t ipc_task_deadline(void *data) return SOF_TASK_DEADLINE_NOW; } +static inline void ipc_build_stream_posn(struct sof_ipc_stream_posn *posn, + uint32_t type, uint32_t id) +{ + posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | type | id; + posn->rhdr.hdr.size = sizeof(*posn); + posn->comp_id = id; +} + +static inline void ipc_build_comp_event(struct sof_ipc_comp_event *event, + uint32_t type, uint32_t id) +{ + event->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | SOF_IPC_COMP_NOTIFICATION | + id; + event->rhdr.hdr.size = sizeof(*event); + event->src_comp_type = type; + event->src_comp_id = id; +} + +static inline void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn) +{ + posn->rhdr.hdr.cmd = SOF_IPC_GLB_TRACE_MSG | + SOF_IPC_TRACE_DMA_POSITION; + posn->rhdr.hdr.size = sizeof(*posn); +} + int ipc_init(struct sof *sof); /** diff --git a/src/include/sof/trace/dma-trace.h b/src/include/sof/trace/dma-trace.h index 8a20353308dd..b10b0b91df5f 100644 --- a/src/include/sof/trace/dma-trace.h +++ b/src/include/sof/trace/dma-trace.h @@ -12,6 +12,7 @@ #include #include #include +#include #include struct sof; @@ -29,10 +30,8 @@ struct dma_trace_data { struct dma_sg_config config; struct dma_trace_buf dmatb; struct dma_copy dc; + struct sof_ipc_dma_trace_posn posn; uint32_t old_host_offset; - uint32_t host_offset; - uint32_t overflow; - uint32_t messages; uint32_t host_size; struct task dmat_work; uint32_t enabled; diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 74fc3dbfe833..07688ef23048 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -791,9 +791,9 @@ int ipc_dma_trace_send_position(void) struct sof_ipc_dma_trace_posn posn; posn.rhdr.hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_POSITION; - posn.host_offset = dmat->host_offset; - posn.overflow = dmat->overflow; - posn.messages = dmat->messages; + posn.host_offset = dmat->posn.host_offset; + posn.overflow = dmat->posn.overflow; + posn.messages = dmat->posn.messages; posn.rhdr.hdr.size = sizeof(posn); return ipc_queue_host_message(ipc_get(), posn.rhdr.hdr.cmd, &posn, diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index 255ad31fcdc3..7e322b136f68 100644 --- a/src/trace/dma-trace.c +++ b/src/trace/dma-trace.c @@ -60,14 +60,14 @@ static enum task_state trace_work(void *data) return SOF_TASK_STATE_RESCHEDULE; } - d->overflow = overflow; + d->posn.overflow = overflow; /* DMA trace copying is working */ d->copy_in_progress = 1; /* copy this section to host */ - size = dma_copy_to_host_nowait(&d->dc, config, d->host_offset, - buffer->r_ptr, size); + size = dma_copy_to_host_nowait(&d->dc, config, d->posn.host_offset, + buffer->r_ptr, size); if (size < 0) { trace_buffer_error("trace_work() error: " "dma_copy_to_host_nowait() failed"); @@ -75,9 +75,9 @@ static enum task_state trace_work(void *data) } /* update host pointer and check for wrap */ - d->host_offset += size; - if (d->host_offset >= d->host_size) - d->host_offset -= d->host_size; + d->posn.host_offset += size; + if (d->posn.host_offset >= d->host_size) + d->posn.host_offset -= d->host_size; /* update local pointer and check for wrap */ buffer->r_ptr = (char *)buffer->r_ptr + size; @@ -89,7 +89,7 @@ static enum task_state trace_work(void *data) /* disregard any old messages and don't resend them if we overflow */ if (size > 0) { - if (d->overflow) + if (d->posn.overflow) buffer->avail = DMA_TRACE_LOCAL_SIZE - size; else buffer->avail -= size; @@ -112,6 +112,7 @@ int dma_trace_init_early(struct sof *sof) SOF_MEM_CAPS_RAM, sizeof(*sof->dmat)); dma_sg_init(&sof->dmat->config.elem_array); spinlock_init(&sof->dmat->lock); + ipc_build_trace_posn(&sof->dmat->posn); platform_shared_commit(sof->dmat, sizeof(*sof->dmat)); @@ -249,9 +250,9 @@ static int dma_trace_get_avail_data(struct dma_trace_data *d, * This function will be called once every 500ms at least even * if no new trace is filled. */ - if (d->old_host_offset != d->host_offset) { + if (d->old_host_offset != d->posn.host_offset) { ipc_dma_trace_send_position(); - d->old_host_offset = d->host_offset; + d->old_host_offset = d->posn.host_offset; } /* align data to HD-DMA burst size */ @@ -274,8 +275,8 @@ static int dma_trace_get_avail_data(struct dma_trace_data *d, return 0; /* host buffer wrap ? */ - if (d->host_offset + avail > d->host_size) - hsize = d->host_size - d->host_offset; + if (d->posn.host_offset + avail > d->host_size) + hsize = d->host_size - d->posn.host_offset; /* local buffer wrap ? */ if ((char *)buffer->r_ptr + avail > (char *)buffer->end_addr) @@ -499,7 +500,7 @@ static void dtrace_add_event(const char *e, uint32_t length) } buffer->avail += length; - trace_data->messages++; + trace_data->posn.messages++; } else { /* if there is not enough memory for new log, we drop it */ trace_data->dropped_entries++; From 176af653e02369314396781fa01808123df302d3 Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Fri, 28 Feb 2020 09:16:33 +0100 Subject: [PATCH 5/6] ipc: add helper methods for notification allocation Adds helper methods for IPC notifications allocation and free. This way we can allocate only the size we need without preallocating the maximum size. Free operation automatically handles synchronization. Signed-off-by: Tomasz Lauda --- src/include/sof/drivers/ipc.h | 49 ++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h index 758371619781..70ecda456d3b 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -9,6 +9,8 @@ #ifndef __SOF_DRIVERS_IPC_H__ #define __SOF_DRIVERS_IPC_H__ +#include +#include #include #include #include @@ -18,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -82,7 +85,7 @@ struct ipc_comp_dev { struct ipc_msg { uint32_t header; /* specific to platform */ uint32_t tx_size; /* payload size in bytes */ - uint8_t tx_data[SOF_IPC_MSG_MAX_SIZE]; /* pointer to payload data */ + void *tx_data; /* pointer to payload data */ struct list_item list; }; @@ -153,6 +156,50 @@ static inline void ipc_build_trace_posn(struct sof_ipc_dma_trace_posn *posn) posn->rhdr.hdr.size = sizeof(*posn); } +static inline struct ipc_msg *ipc_msg_init(uint32_t header, uint32_t size) +{ + struct ipc_msg *msg; + + msg = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, + SOF_MEM_CAPS_RAM, size); + if (!msg) + return NULL; + + msg->tx_data = rzalloc(SOF_MEM_ZONE_RUNTIME, SOF_MEM_FLAG_SHARED, + SOF_MEM_CAPS_RAM, size); + if (!msg->tx_data) { + rfree(msg); + return NULL; + } + + msg->header = header; + msg->tx_size = size; + list_init(&msg->list); + + platform_shared_commit(msg, sizeof(*msg)); + + return msg; +} + +static inline void ipc_msg_free(struct ipc_msg *msg) +{ + if (!msg) + return; + + struct ipc *ipc = ipc_get(); + uint32_t flags; + + spin_lock_irq(&ipc->lock, flags); + + list_item_del(&msg->list); + rfree(msg->tx_data); + rfree(msg); + + platform_shared_commit(ipc, sizeof(*ipc)); + + spin_unlock_irq(&ipc->lock, flags); +} + int ipc_init(struct sof *sof); /** From ecdc7e62f97c81f9ae7a701c125c18fd6debddea Mon Sep 17 00:00:00 2001 From: Tomasz Lauda Date: Fri, 28 Feb 2020 12:19:46 +0100 Subject: [PATCH 6/6] ipc: use notifications allocated by sources Changes implementation of notifications allocation. Instead of using common empty list of messages let's switch to allocating message per source of notification. This way we won't have problem with memory and lack of empty messages and also we will be able to optimize memory. Signed-off-by: Tomasz Lauda --- src/audio/detect_test.c | 26 ++- src/audio/host.c | 16 +- src/audio/pipeline.c | 21 +- src/drivers/imx/ipc.c | 7 - src/drivers/intel/baytrail/ipc.c | 7 - src/drivers/intel/cavs/ipc.c | 7 - src/drivers/intel/cavs/sue-ipc.c | 7 - src/drivers/intel/haswell/ipc.c | 7 - src/include/sof/audio/pipeline.h | 2 + src/include/sof/drivers/ipc.h | 18 -- src/include/sof/trace/dma-trace.h | 2 + src/ipc/dma-copy.c | 6 +- src/ipc/handler.c | 219 ------------------ src/ipc/ipc.c | 19 +- src/trace/dma-trace.c | 8 +- test/cmocka/src/audio/pipeline/CMakeLists.txt | 8 - .../src/audio/pipeline/pipeline_mocks.c | 13 ++ .../audio/pipeline/pipeline_new_allocation.c | 51 ---- .../pipeline/pipeline_new_allocation_mocks.c | 26 --- tools/testbench/ipc.c | 12 +- 20 files changed, 84 insertions(+), 398 deletions(-) delete mode 100644 test/cmocka/src/audio/pipeline/pipeline_new_allocation.c delete mode 100644 test/cmocka/src/audio/pipeline/pipeline_new_allocation_mocks.c diff --git a/src/audio/detect_test.c b/src/audio/detect_test.c index 8601d60a7979..f1ddb82573b9 100644 --- a/src/audio/detect_test.c +++ b/src/audio/detect_test.c @@ -69,7 +69,8 @@ struct comp_data { struct kpb_event_data event_data; struct kpb_client client_data; - struct ipc_msg msg; /**< host notification */ + struct sof_ipc_comp_event event; + struct ipc_msg *msg; /**< host notification */ void (*detect_func)(struct comp_dev *dev, const struct audio_stream *source, uint32_t frames); @@ -105,19 +106,10 @@ static inline bool detector_is_sample_width_supported(enum sof_ipc_frame sf) static void notify_host(const struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); - struct sof_ipc_comp_event event; comp_info(dev, "notify_host()"); - event.event_type = SOF_CTRL_EVENT_KD; - event.num_elems = 0; - - ipc_build_comp_event(&event, dev_comp_type(dev), dev_comp_id(dev)); - ipc_prepare_host_message(&cd->msg, event.rhdr.hdr.cmd, &event, - sizeof(event)); - - /* Send IPC message right away to wake host up ASAP */ - ipc_platform_send_msg(&cd->msg); + ipc_msg_send(cd->msg, &cd->event, true); } static void notify_kpb(const struct comp_dev *dev) @@ -346,6 +338,17 @@ static struct comp_dev *test_keyword_new(const struct comp_driver *drv, goto fail; } + /* build component event */ + ipc_build_comp_event(&cd->event, comp->type, comp->id); + cd->event.event_type = SOF_CTRL_EVENT_KD; + cd->event.num_elems = 0; + + cd->msg = ipc_msg_init(cd->event.rhdr.hdr.cmd, sizeof(cd->event)); + if (!cd->msg) { + comp_err(dev, "test_keyword_new() error: ipc notification init failed"); + goto fail; + } + dev->state = COMP_STATE_READY; return dev; @@ -362,6 +365,7 @@ static void test_keyword_free(struct comp_dev *dev) comp_info(dev, "test_keyword_free()"); + ipc_msg_free(cd->msg); free_mem_load(cd); rfree(cd); rfree(dev); diff --git a/src/audio/host.c b/src/audio/host.c index 76cf60fdc7fc..34b7df1e5acb 100644 --- a/src/audio/host.c +++ b/src/audio/host.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ struct host_data { /* stream info */ struct sof_ipc_stream_posn posn; /* TODO: update this */ + struct ipc_msg *msg; /**< host notification */ }; static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) @@ -155,7 +157,9 @@ static void host_update_position(struct comp_dev *dev, uint32_t bytes) * (updates position first, by calling ops.position()) */ pipeline_get_timestamp(dev->pipeline, dev, &hd->posn); - ipc_stream_send_position(dev, &hd->posn); + mailbox_stream_write(dev->pipeline->posn_offset, + &hd->posn, sizeof(hd->posn)); + ipc_msg_send(hd->msg, &hd->posn, false); } } } @@ -364,6 +368,15 @@ static struct comp_dev *host_new(const struct comp_driver *drv, ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, comp->id); + hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, sizeof(hd->posn)); + if (!hd->msg) { + comp_err(dev, "host_new() error: ipc_msg_init failed"); + dma_put(hd->dma); + rfree(hd); + rfree(dev); + return NULL; + } + hd->chan = NULL; hd->copy_type = COMP_COPY_NORMAL; dev->state = COMP_STATE_READY; @@ -379,6 +392,7 @@ static void host_free(struct comp_dev *dev) dma_put(hd->dma); + ipc_msg_free(hd->msg); dma_sg_free(&hd->config.elem_array); rfree(hd); rfree(dev); diff --git a/src/audio/pipeline.c b/src/audio/pipeline.c index a918655b06a7..16f925a8828b 100644 --- a/src/audio/pipeline.c +++ b/src/audio/pipeline.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +43,7 @@ static enum task_state pipeline_task(void *arg); struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc, struct comp_dev *cd) { + struct sof_ipc_stream_posn posn; struct pipeline *p; int ret; @@ -63,6 +66,17 @@ struct pipeline *pipeline_new(struct sof_ipc_pipe_new *pipe_desc, pipe_desc, sizeof(*pipe_desc)); assert(!ret); + /* just for retrieving valid ipc_msg header */ + ipc_build_stream_posn(&posn, SOF_IPC_STREAM_TRIG_XRUN, + p->ipc_pipe.comp_id); + + p->msg = ipc_msg_init(posn.rhdr.hdr.cmd, sizeof(posn)); + if (!p->msg) { + pipe_cl_err("pipeline_new() error: ipc_msg_init failed"); + rfree(p); + return NULL; + } + return p; } @@ -241,6 +255,8 @@ int pipeline_free(struct pipeline *p) rfree(p->pipe_task); } + ipc_msg_free(p->msg); + /* now free the pipeline */ rfree(p); @@ -829,7 +845,9 @@ static int pipeline_comp_xrun(struct comp_dev *current, platform_host_timestamp(current, ppl_data->posn); /* send XRUN to host */ - ipc_stream_send_xrun(current, ppl_data->posn); + mailbox_stream_write(ppl_data->p->posn_offset, ppl_data->posn, + sizeof(*ppl_data->posn)); + ipc_msg_send(ppl_data->p->msg, ppl_data->posn, true); } return pipeline_for_each_comp(current, &pipeline_comp_xrun, data, NULL, @@ -865,6 +883,7 @@ void pipeline_xrun(struct pipeline *p, struct comp_dev *dev, posn.xrun_size = bytes; posn.xrun_comp_id = dev_comp_id(dev); data.posn = &posn; + data.p = p; pipeline_comp_xrun(dev, NULL, &data, dev->direction); } diff --git a/src/drivers/imx/ipc.c b/src/drivers/imx/ipc.c index 748688f44465..45430c2cc28f 100644 --- a/src/drivers/imx/ipc.c +++ b/src/drivers/imx/ipc.c @@ -112,11 +112,8 @@ void ipc_platform_complete_cmd(void *data) int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); - uint32_t flags; int ret = 0; - spin_lock_irq(&ipc->lock, flags); - /* can't send notification when one is in progress */ if (ipc->is_notification_pending || imx_mu_read(IMX_MU_xCR) & IMX_MU_xCR_GIRn(1)) { @@ -134,15 +131,11 @@ int ipc_platform_send_msg(struct ipc_msg *msg) /* now interrupt host to tell it we have sent a message */ imx_mu_xcr_rmw(IMX_MU_xCR_GIRn(1), 0); - list_item_append(&msg->list, &ipc->empty_list); - platform_shared_commit(msg, sizeof(*msg)); out: platform_shared_commit(ipc, sizeof(*ipc)); - spin_unlock_irq(&ipc->lock, flags); - return ret; } diff --git a/src/drivers/intel/baytrail/ipc.c b/src/drivers/intel/baytrail/ipc.c index 3ad61e189979..ec8edc975c0c 100644 --- a/src/drivers/intel/baytrail/ipc.c +++ b/src/drivers/intel/baytrail/ipc.c @@ -100,11 +100,8 @@ void ipc_platform_complete_cmd(void *data) int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); - uint32_t flags; int ret = 0; - spin_lock_irq(&ipc->lock, flags); - /* can't send notification when one is in progress */ if (ipc->is_notification_pending || shim_read(SHIM_IPCDH) & (SHIM_IPCDH_BUSY | SHIM_IPCDH_DONE)) { @@ -123,15 +120,11 @@ int ipc_platform_send_msg(struct ipc_msg *msg) shim_write(SHIM_IPCDL, msg->header); shim_write(SHIM_IPCDH, SHIM_IPCDH_BUSY); - list_item_append(&msg->list, &ipc->empty_list); - platform_shared_commit(msg, sizeof(*msg)); out: platform_shared_commit(ipc, sizeof(*ipc)); - spin_unlock_irq(&ipc->lock, flags); - return ret; } diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index ef88274ba413..c3a459d302e1 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -246,11 +246,8 @@ void ipc_platform_complete_cmd(void *data) int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); - uint32_t flags; int ret = 0; - spin_lock_irq(&ipc->lock, flags); - if (ipc->is_notification_pending || #if CAVS_VERSION == CAVS_VERSION_1_5 ipc_read(IPC_DIPCI) & IPC_DIPCI_BUSY) { @@ -278,15 +275,11 @@ int ipc_platform_send_msg(struct ipc_msg *msg) ipc_write(IPC_DIPCIDR, 0x80000000 | msg->header); #endif - list_item_append(&msg->list, &ipc->empty_list); - platform_shared_commit(msg, sizeof(*msg)); out: platform_shared_commit(ipc, sizeof(*ipc)); - spin_unlock_irq(&ipc->lock, flags); - return ret; } diff --git a/src/drivers/intel/cavs/sue-ipc.c b/src/drivers/intel/cavs/sue-ipc.c index 73663aaf0765..2d7c78871b46 100644 --- a/src/drivers/intel/cavs/sue-ipc.c +++ b/src/drivers/intel/cavs/sue-ipc.c @@ -54,9 +54,6 @@ void ipc_platform_complete_cmd(void *data) int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); - uint32_t flags; - - spin_lock_irq(&ipc->lock, flags); /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); @@ -65,12 +62,8 @@ int ipc_platform_send_msg(struct ipc_msg *msg) /* now interrupt host to tell it we have message sent */ - list_item_append(&msg->list, &ipc->empty_list); - platform_shared_commit(ipc, sizeof(*ipc)); - spin_unlock_irq(&ipc->lock, flags); - return 0; } diff --git a/src/drivers/intel/haswell/ipc.c b/src/drivers/intel/haswell/ipc.c index 1a68820fedb6..136c5ece1a94 100644 --- a/src/drivers/intel/haswell/ipc.c +++ b/src/drivers/intel/haswell/ipc.c @@ -102,11 +102,8 @@ void ipc_platform_complete_cmd(void *data) int ipc_platform_send_msg(struct ipc_msg *msg) { struct ipc *ipc = ipc_get(); - uint32_t flags; int ret = 0; - spin_lock_irq(&ipc->lock, flags); - /* can't send nofication when one is in progress */ if (ipc->is_notification_pending || shim_read(SHIM_IPCD) & (SHIM_IPCD_BUSY | SHIM_IPCD_DONE)) { @@ -124,15 +121,11 @@ int ipc_platform_send_msg(struct ipc_msg *msg) /* now interrupt host to tell it we have message sent */ shim_write(SHIM_IPCD, SHIM_IPCD_BUSY); - list_item_append(&msg->list, &ipc->empty_list); - platform_shared_commit(msg, sizeof(*msg)); out: platform_shared_commit(ipc, sizeof(*ipc)); - spin_unlock_irq(&ipc->lock, flags); - return ret; } diff --git a/src/include/sof/audio/pipeline.h b/src/include/sof/audio/pipeline.h index 5960ef73bd3f..d81d15c30997 100644 --- a/src/include/sof/audio/pipeline.h +++ b/src/include/sof/audio/pipeline.h @@ -8,6 +8,7 @@ #ifndef __SOF_AUDIO_PIPELINE_H__ #define __SOF_AUDIO_PIPELINE_H__ +#include #include #include #include @@ -92,6 +93,7 @@ struct pipeline { /* position update */ uint32_t posn_offset; /* position update array offset*/ + struct ipc_msg *msg; }; /* static pipeline */ diff --git a/src/include/sof/drivers/ipc.h b/src/include/sof/drivers/ipc.h index 70ecda456d3b..0d7bf3ec5d05 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -50,8 +50,6 @@ struct ipc_msg; #define trace_ipc_error(format, ...) \ trace_error(TRACE_CLASS_IPC, format, ##__VA_ARGS__) -#define MSG_QUEUE_SIZE 12 - #define COMP_TYPE_COMPONENT 1 #define COMP_TYPE_BUFFER 2 #define COMP_TYPE_PIPELINE 3 @@ -97,7 +95,6 @@ struct ipc { int pm_prepare_D3; /* do we need to prepare for D3 */ struct list_item msg_list; /* queue of messages to be sent */ - struct list_item empty_list; /* queue of empty messages */ bool is_notification_pending; /* notification is being sent to host */ struct list_item comp_list; /* list of component devices */ @@ -226,21 +223,6 @@ void ipc_free(struct ipc *ipc); void ipc_schedule_process(struct ipc *ipc); -int ipc_stream_send_position(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn); -void ipc_build_comp_notification(const struct comp_dev *cdev, - struct sof_ipc_comp_event *event); -int ipc_send_comp_notification(const struct comp_dev *cdev, - struct sof_ipc_comp_event *event); -int ipc_stream_send_xrun(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn); - -void ipc_prepare_host_message(struct ipc_msg *msg, uint32_t header, - void *tx_data, size_t tx_bytes); - -int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, - size_t tx_bytes, bool replace); - int ipc_platform_send_msg(struct ipc_msg *msg); void ipc_send_queued_msg(void); diff --git a/src/include/sof/trace/dma-trace.h b/src/include/sof/trace/dma-trace.h index b10b0b91df5f..947aeb6cce67 100644 --- a/src/include/sof/trace/dma-trace.h +++ b/src/include/sof/trace/dma-trace.h @@ -15,6 +15,7 @@ #include #include +struct ipc_msg; struct sof; struct dma_trace_buf { @@ -31,6 +32,7 @@ struct dma_trace_data { struct dma_trace_buf dmatb; struct dma_copy dc; struct sof_ipc_dma_trace_posn posn; + struct ipc_msg *msg; uint32_t old_host_offset; uint32_t host_size; struct task dmat_work; diff --git a/src/ipc/dma-copy.c b/src/ipc/dma-copy.c index 619e7919fffe..21b9affd46d8 100644 --- a/src/ipc/dma-copy.c +++ b/src/ipc/dma-copy.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, int32_t host_offset, void *local_ptr, int32_t size) { + struct dma_trace_data *dmat = dma_trace_data_get(); struct dma_sg_config config; struct dma_sg_elem *host_sg_elem; struct dma_sg_elem local_sg_elem; @@ -117,7 +119,9 @@ int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg, if (err < 0) return err; - ipc_dma_trace_send_position(); + ipc_msg_send(dmat->msg, &dmat->posn, false); + + platform_shared_commit(dmat, sizeof(*dmat)); /* bytes copied */ return local_sg_elem.size; diff --git a/src/ipc/handler.c b/src/ipc/handler.c index 07688ef23048..b907722d2ff6 100644 --- a/src/ipc/handler.c +++ b/src/ipc/handler.c @@ -415,55 +415,6 @@ static int ipc_stream_position(uint32_t header) return 1; } -/* send stream position */ -int ipc_stream_send_position(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn) -{ - posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_POSITION | - dev_comp_id(cdev); - posn->rhdr.hdr.size = sizeof(*posn); - posn->comp_id = dev_comp_id(cdev); - - mailbox_stream_write(cdev->pipeline->posn_offset, posn, sizeof(*posn)); - return ipc_queue_host_message(ipc_get(), posn->rhdr.hdr.cmd, posn, - sizeof(*posn), false); -} - -void ipc_build_comp_notification(const struct comp_dev *cdev, - struct sof_ipc_comp_event *event) -{ - event->rhdr.hdr.cmd = SOF_IPC_GLB_COMP_MSG | - SOF_IPC_COMP_NOTIFICATION | dev_comp_id(cdev); - event->rhdr.hdr.size = sizeof(*event); - event->src_comp_type = dev_comp_type(cdev); - event->src_comp_id = dev_comp_id(cdev); -} - -/* send component notification */ -int ipc_send_comp_notification(const struct comp_dev *cdev, - struct sof_ipc_comp_event *event) -{ - ipc_build_comp_notification(cdev, event); - - return ipc_queue_host_message(ipc_get(), event->rhdr.hdr.cmd, event, - sizeof(*event), false); -} - -/* send stream position TODO: send compound message */ -int ipc_stream_send_xrun(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn) -{ - posn->rhdr.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | - SOF_IPC_STREAM_TRIG_XRUN | - dev_comp_id(cdev); - posn->rhdr.hdr.size = sizeof(*posn); - posn->comp_id = dev_comp_id(cdev); - - mailbox_stream_write(cdev->pipeline->posn_offset, posn, sizeof(*posn)); - return ipc_queue_host_message(ipc_get(), posn->rhdr.hdr.cmd, posn, - sizeof(*posn), false); -} - static int ipc_stream_trigger(uint32_t header) { struct ipc *ipc = ipc_get(); @@ -784,22 +735,6 @@ static int ipc_dma_trace_config(uint32_t header) return err; } -/* send DMA trace host buffer position to host */ -int ipc_dma_trace_send_position(void) -{ - struct dma_trace_data *dmat = dma_trace_data_get(); - struct sof_ipc_dma_trace_posn posn; - - posn.rhdr.hdr.cmd = SOF_IPC_GLB_TRACE_MSG | SOF_IPC_TRACE_DMA_POSITION; - posn.host_offset = dmat->posn.host_offset; - posn.overflow = dmat->posn.overflow; - posn.messages = dmat->posn.messages; - posn.rhdr.hdr.size = sizeof(posn); - - return ipc_queue_host_message(ipc_get(), posn.rhdr.hdr.cmd, &posn, - sizeof(posn), true); -} - static int ipc_glb_debug_message(uint32_t header) { uint32_t cmd = iCS(header); @@ -1371,160 +1306,6 @@ void ipc_cmd(struct sof_ipc_cmd_hdr *hdr) } } -/* locks held by caller */ -static inline struct ipc_msg *msg_get_empty(struct ipc *ipc) -{ - struct ipc_msg *msg = NULL; - - if (!list_is_empty(&ipc->empty_list)) { - msg = list_first_item(&ipc->empty_list, struct ipc_msg, list); - list_item_del(&msg->list); - } - - return msg; -} - -static inline struct ipc_msg *ipc_glb_stream_message_find(struct ipc *ipc, - struct sof_ipc_stream_posn *posn) -{ - struct list_item *plist; - struct ipc_msg *msg = NULL; - struct sof_ipc_stream_posn *old_posn = NULL; - uint32_t cmd; - - /* Check whether the command is expected */ - cmd = iCS(posn->rhdr.hdr.cmd); - - switch (cmd) { - case SOF_IPC_STREAM_TRIG_XRUN: - case SOF_IPC_STREAM_POSITION: - - /* iterate host message list for searching */ - list_for_item(plist, &ipc->msg_list) { - msg = container_of(plist, struct ipc_msg, list); - if (msg->header == posn->rhdr.hdr.cmd) { - old_posn = (struct sof_ipc_stream_posn *) - msg->tx_data; - if (old_posn->comp_id == posn->comp_id) - return msg; - } - platform_shared_commit(msg, sizeof(*msg)); - } - break; - default: - break; - } - - /* no match */ - return NULL; -} - -static inline struct ipc_msg *ipc_glb_trace_message_find(struct ipc *ipc, - struct sof_ipc_dma_trace_posn *posn) -{ - struct list_item *plist; - struct ipc_msg *msg = NULL; - uint32_t cmd; - - /* Check whether the command is expected */ - cmd = iCS(posn->rhdr.hdr.cmd); - - switch (cmd) { - case SOF_IPC_TRACE_DMA_POSITION: - /* iterate host message list for searching */ - list_for_item(plist, &ipc->msg_list) { - msg = container_of(plist, struct ipc_msg, list); - if (msg->header == posn->rhdr.hdr.cmd) - return msg; - platform_shared_commit(msg, sizeof(*msg)); - } - break; - default: - break; - } - - /* no match */ - return NULL; -} - -static inline struct ipc_msg *msg_find(struct ipc *ipc, uint32_t header, - void *tx_data) -{ - uint32_t type; - - /* use different sub function for different global message type */ - type = iGS(header); - - switch (type) { - case SOF_IPC_GLB_STREAM_MSG: - return ipc_glb_stream_message_find(ipc, - (struct sof_ipc_stream_posn *)tx_data); - case SOF_IPC_GLB_TRACE_MSG: - return ipc_glb_trace_message_find(ipc, - (struct sof_ipc_dma_trace_posn *)tx_data); - default: - /* not found */ - return NULL; - } -} - -void ipc_prepare_host_message(struct ipc_msg *msg, uint32_t header, - void *tx_data, size_t tx_bytes) -{ - int ret; - - msg->header = header; - msg->tx_size = tx_bytes; - - /* copy mailbox data to message */ - if (tx_bytes > 0 && tx_bytes < SOF_IPC_MSG_MAX_SIZE) { - ret = memcpy_s(msg->tx_data, msg->tx_size, tx_data, tx_bytes); - assert(!ret); - } -} - -int ipc_queue_host_message(struct ipc *ipc, uint32_t header, void *tx_data, - size_t tx_bytes, bool replace) -{ - struct ipc_msg *msg = NULL; - bool found = false; - uint32_t flags; - int ret = 0; - - spin_lock_irq(&ipc->lock, flags); - - /* do we need to replace an existing message? */ - if (replace) - msg = msg_find(ipc, header, tx_data); - - /* do we need to use a new empty message? */ - if (msg) - found = true; - else - msg = msg_get_empty(ipc); - - if (!msg) { - trace_ipc_error( - "ipc_queue_host_message() error: msg hdr for 0x%08x not found", - header); - ret = -EBUSY; - goto out; - } - - /* prepare the message */ - ipc_prepare_host_message(msg, header, tx_data, tx_bytes); - - /* queue new message if it's not replacement */ - if (!found) - list_item_append(&msg->list, &ipc->msg_list); - - platform_shared_commit(msg, sizeof(*msg)); - -out: - spin_unlock_irq(&ipc->lock, flags); - return ret; -} - void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) { struct ipc *ipc = ipc_get(); diff --git a/src/ipc/ipc.c b/src/ipc/ipc.c index ab7e4920e01f..d6d01e3a56fb 100644 --- a/src/ipc/ipc.c +++ b/src/ipc/ipc.c @@ -646,27 +646,22 @@ void ipc_send_queued_msg(void) spin_lock_irq(&ipc->lock, flags); /* any messages to send ? */ - if (list_is_empty(&ipc->msg_list)) { - spin_unlock_irq(&ipc->lock, flags); + if (list_is_empty(&ipc->msg_list)) goto out; - } msg = list_first_item(&ipc->msg_list, struct ipc_msg, list); - spin_unlock_irq(&ipc->lock, flags); - ipc_platform_send_msg(msg); out: platform_shared_commit(ipc, sizeof(*ipc)); + + spin_unlock_irq(&ipc->lock, flags); } int ipc_init(struct sof *sof) { - struct ipc_msg *msg; - int i; - trace_ipc("ipc_init()"); /* init ipc data */ @@ -676,17 +671,9 @@ int ipc_init(struct sof *sof) SOF_MEM_CAPS_RAM, SOF_IPC_MSG_MAX_SIZE); spinlock_init(&sof->ipc->lock); - list_init(&sof->ipc->empty_list); list_init(&sof->ipc->msg_list); list_init(&sof->ipc->comp_list); - for (i = 0; i < MSG_QUEUE_SIZE; i++) { - msg = rzalloc(SOF_MEM_ZONE_SYS, SOF_MEM_FLAG_SHARED, - SOF_MEM_CAPS_RAM, sizeof(*msg)); - list_item_prepend(&msg->list, &sof->ipc->empty_list); - platform_shared_commit(msg, sizeof(*msg)); - } - return platform_ipc_init(sof->ipc); } diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index 7e322b136f68..4fb92b57c815 100644 --- a/src/trace/dma-trace.c +++ b/src/trace/dma-trace.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -112,7 +113,12 @@ int dma_trace_init_early(struct sof *sof) SOF_MEM_CAPS_RAM, sizeof(*sof->dmat)); dma_sg_init(&sof->dmat->config.elem_array); spinlock_init(&sof->dmat->lock); + ipc_build_trace_posn(&sof->dmat->posn); + sof->dmat->msg = ipc_msg_init(sof->dmat->posn.rhdr.hdr.cmd, + sizeof(sof->dmat->posn)); + if (!sof->dmat->msg) + return -ENOMEM; platform_shared_commit(sof->dmat, sizeof(*sof->dmat)); @@ -251,7 +257,7 @@ static int dma_trace_get_avail_data(struct dma_trace_data *d, * if no new trace is filled. */ if (d->old_host_offset != d->posn.host_offset) { - ipc_dma_trace_send_position(); + ipc_msg_send(d->msg, &d->posn, false); d->old_host_offset = d->posn.host_offset; } diff --git a/test/cmocka/src/audio/pipeline/CMakeLists.txt b/test/cmocka/src/audio/pipeline/CMakeLists.txt index ea7a9450c3ac..b9f51384e985 100644 --- a/test/cmocka/src/audio/pipeline/CMakeLists.txt +++ b/test/cmocka/src/audio/pipeline/CMakeLists.txt @@ -25,14 +25,6 @@ cmocka_test(pipeline_new ${PROJECT_SOURCE_DIR}/src/audio/pipeline.c ) -cmocka_test(pipeline_new_allocation - pipeline_new_allocation.c - pipeline_mocks.c - pipeline_new_allocation_mocks.c - ${PROJECT_SOURCE_DIR}/test/cmocka/src/notifier_mocks.c - ${PROJECT_SOURCE_DIR}/src/audio/pipeline.c -) - cmocka_test(pipeline_connect_upstream pipeline_connect_upstream.c pipeline_mocks.c diff --git a/test/cmocka/src/audio/pipeline/pipeline_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_mocks.c index 3457a3877301..d506803c331a 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_mocks.c +++ b/test/cmocka/src/audio/pipeline/pipeline_mocks.c @@ -13,6 +13,12 @@ TRACE_IMPL() struct ipc *_ipc; struct timer *platform_timer; struct schedulers *schedulers; +static struct sof sof; + +struct sof *sof_get(void) +{ + return &sof; +} struct schedulers **arch_schedulers_get(void) { @@ -107,3 +113,10 @@ uint64_t clock_ms_to_ticks(int clock, uint64_t ms) return 0; } + +void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) +{ + (void)msg; + (void)data; + (void)high_priority; +} diff --git a/test/cmocka/src/audio/pipeline/pipeline_new_allocation.c b/test/cmocka/src/audio/pipeline/pipeline_new_allocation.c deleted file mode 100644 index 72cf36998294..000000000000 --- a/test/cmocka/src/audio/pipeline/pipeline_new_allocation.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Jakub Dabek - -#include -#include -#include -#include -#include "pipeline_mocks.h" -#include -#include -#include -#include -#include - -static void test_audio_pipeline_pipeline_new_memory_allocation( - void **state) -{ - (void)state; - - /*Initialize structs for arguments*/ - struct sof_ipc_pipe_new pipe_desc = {.core = 1, .priority = 2}; - struct comp_dev *cd = malloc(sizeof(cd)); - struct pipeline *result; - - /*Memmory allocation values check. Pipeline can have those changed - *in future so expect errors here if any change to pipeline memory - *capabilities or memmory space was made - */ - expect_value(_zalloc, zone, SOF_MEM_ZONE_RUNTIME); - expect_value(_zalloc, flags, 0); - expect_value(_zalloc, caps, SOF_MEM_CAPS_RAM); - expect_value(_zalloc, bytes, sizeof(struct pipeline)); - - /*Testing component*/ - result = pipeline_new(&pipe_desc, cd); -} - -int main(void) -{ - const struct CMUnitTest tests[] = { - cmocka_unit_test( - test_audio_pipeline_pipeline_new_memory_allocation), - }; - - cmocka_set_message_output(CM_OUTPUT_TAP); - - return cmocka_run_group_tests(tests, NULL, NULL); -} diff --git a/test/cmocka/src/audio/pipeline/pipeline_new_allocation_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_new_allocation_mocks.c deleted file mode 100644 index b760dbd27f99..000000000000 --- a/test/cmocka/src/audio/pipeline/pipeline_new_allocation_mocks.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2018 Intel Corporation. All rights reserved. -// -// Author: Jakub Dabek - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void *_zalloc(enum mem_zone zone, uint32_t flags, uint32_t caps, size_t bytes) -{ - check_expected(zone); - check_expected(flags); - check_expected(caps); - check_expected(bytes); - (void)zone; - (void)caps; - return calloc(bytes, 1); -} diff --git a/tools/testbench/ipc.c b/tools/testbench/ipc.c index 7981f7128c11..3c237bebd63c 100644 --- a/tools/testbench/ipc.c +++ b/tools/testbench/ipc.c @@ -46,16 +46,8 @@ int platform_ipc_init(struct ipc *ipc) return 0; } -/* The following definitions are to satisfy libsof linker errors */ +/* The following definition is to satisfy libsof linker errors */ -int ipc_stream_send_position(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn) +void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) { - return 0; -} - -int ipc_stream_send_xrun(struct comp_dev *cdev, - struct sof_ipc_stream_posn *posn) -{ - return 0; }