diff --git a/src/audio/detect_test.c b/src/audio/detect_test.c index 5e7be6595909..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_notification(dev, &event); - 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 af6fedbf6b9f..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); } } } @@ -362,9 +366,19 @@ 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->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; - hd->posn.comp_id = comp->id; dev->state = COMP_STATE_READY; return dev; @@ -378,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 383661f9ce18..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, @@ -859,10 +877,13 @@ 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); 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 8590bc8a351b..45430c2cc28f 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); } @@ -106,33 +109,34 @@ 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; - - spin_lock_irq(&ipc->lock, flags); + int ret = 0; /* 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)) { + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); 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); - 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; } #if CONFIG_HOST_PTABLE diff --git a/src/drivers/intel/baytrail/ipc.c b/src/drivers/intel/baytrail/ipc.c index 62edd9885117..ec8edc975c0c 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); } @@ -94,34 +97,35 @@ 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; - - spin_lock_irq(&ipc->lock, flags); + int ret = 0; /* 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)) { + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); 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); - 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; } 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 ec98f8b7e354..c3a459d302e1 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); @@ -240,26 +243,29 @@ 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; - - spin_lock_irq(&ipc->lock, flags); + int ret = 0; + 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_DIPCIDA) & IPC_DIPCIDA_DONE) + ipc_read(IPC_DIPCIDR) & IPC_DIPCIDR_BUSY || + 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); 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); @@ -269,14 +275,12 @@ void 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; } 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..2d7c78871b46 100644 --- a/src/drivers/intel/cavs/sue-ipc.c +++ b/src/drivers/intel/cavs/sue-ipc.c @@ -51,12 +51,9 @@ 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; - - spin_lock_irq(&ipc->lock, flags); /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); @@ -65,11 +62,9 @@ void 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; } int platform_ipc_init(struct ipc *ipc) diff --git a/src/drivers/intel/haswell/ipc.c b/src/drivers/intel/haswell/ipc.c index ac48338c0b03..136c5ece1a94 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); } @@ -96,33 +99,34 @@ 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; - - spin_lock_irq(&ipc->lock, flags); + int ret = 0; /* 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)) { + ret = -EBUSY; goto out; + } /* now send the message */ mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); 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); - 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; } struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) 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 fa5ad7935aa9..0d7bf3ec5d05 100644 --- a/src/include/sof/drivers/ipc.h +++ b/src/include/sof/drivers/ipc.h @@ -9,13 +9,19 @@ #ifndef __SOF_DRIVERS_IPC_H__ #define __SOF_DRIVERS_IPC_H__ +#include +#include #include #include #include #include #include #include +#include #include +#include +#include +#include #include #include #include @@ -44,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 @@ -79,7 +83,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; }; @@ -91,7 +95,7 @@ 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 */ @@ -124,6 +128,75 @@ 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); +} + +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); /** @@ -150,25 +223,12 @@ 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); - -void ipc_platform_send_msg(struct ipc_msg *msg); +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/include/sof/trace/dma-trace.h b/src/include/sof/trace/dma-trace.h index 8a20353308dd..947aeb6cce67 100644 --- a/src/include/sof/trace/dma-trace.h +++ b/src/include/sof/trace/dma-trace.h @@ -12,8 +12,10 @@ #include #include #include +#include #include +struct ipc_msg; struct sof; struct dma_trace_buf { @@ -29,10 +31,9 @@ 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; + struct ipc_msg *msg; 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/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 76c00e7e1d16..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->host_offset; - posn.overflow = dmat->overflow; - posn.messages = dmat->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,158 +1306,41 @@ 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) +void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) { + struct ipc *ipc = ipc_get(); + uint32_t flags; int ret; - msg->header = header; - msg->tx_size = tx_bytes; + spin_lock_irq(&ipc->lock, flags); /* 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); + 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); } -} - -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; + /* try to send critical notifications right away */ + if (high_priority) { + ret = ipc_platform_send_msg(msg); + if (!ret) + 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); + /* 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)); -out: spin_unlock_irq(&ipc->lock, flags); - return ret; } void ipc_schedule_process(struct ipc *ipc) 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/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__ */ diff --git a/src/trace/dma-trace.c b/src/trace/dma-trace.c index 255ad31fcdc3..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 @@ -60,14 +61,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 +76,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 +90,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; @@ -113,6 +114,12 @@ int dma_trace_init_early(struct sof *sof) 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)); return 0; @@ -249,9 +256,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) { - ipc_dma_trace_send_position(); - d->old_host_offset = d->host_offset; + if (d->old_host_offset != d->posn.host_offset) { + ipc_msg_send(d->msg, &d->posn, false); + d->old_host_offset = d->posn.host_offset; } /* align data to HD-DMA burst size */ @@ -274,8 +281,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 +506,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++; 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; }