diff --git a/src/audio/buffers/comp_buffer.c b/src/audio/buffers/comp_buffer.c index 62f90bd2b5c9..02b44e5dcdce 100644 --- a/src/audio/buffers/comp_buffer.c +++ b/src/audio/buffers/comp_buffer.c @@ -212,8 +212,8 @@ static struct comp_buffer *buffer_alloc_struct(void *stream_addr, size_t size, u audio_stream_set_underrun(&buffer->stream, !!(flags & SOF_BUF_UNDERRUN_PERMITTED)); audio_stream_set_overrun(&buffer->stream, !!(flags & SOF_BUF_OVERRUN_PERMITTED)); - list_init(&buffer->source_list); - list_init(&buffer->sink_list); + comp_buffer_reset_source_list(buffer); + comp_buffer_reset_sink_list(buffer); return buffer; } @@ -534,6 +534,13 @@ void comp_update_buffer_consume(struct comp_buffer *buffer, uint32_t bytes) #endif } +static inline struct list_item *buffer_comp_list(struct comp_buffer *buffer, + int dir) +{ + return dir == PPL_DIR_DOWNSTREAM ? + &buffer->source_list : &buffer->sink_list; +} + /* * Locking: must be called with interrupts disabled! Serialized IPCs protect us * from racing attach / detach calls, but the scheduler can interrupt the IPC diff --git a/src/audio/module_adapter/module/cadence.c b/src/audio/module_adapter/module/cadence.c index 02e95d429bfa..c78fb2bf1d89 100644 --- a/src/audio/module_adapter/module/cadence.c +++ b/src/audio/module_adapter/module/cadence.c @@ -778,7 +778,7 @@ cadence_codec_process(struct processing_module *mod, } /* do not proceed with processing if not enough free space left in the local buffer */ - local_buff = list_first_item(&mod->sink_buffer_list, struct comp_buffer, sink_list); + local_buff = list_first_item(&mod->raw_data_buffers_list, struct comp_buffer, buffers_list); free_bytes = audio_stream_get_free(&local_buff->stream); if (free_bytes < output_bytes) return -ENOSPC; diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 116a744c4113..f8eebb609a35 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -81,7 +81,7 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv, mod->dev = dev; dev->mod = mod; - list_init(&mod->sink_buffer_list); + list_init(&mod->raw_data_buffers_list); ret = module_adapter_init_data(dev, dst, config, spec); if (ret) { @@ -230,7 +230,7 @@ int module_adapter_prepare(struct comp_dev *dev) /* Get period_bytes first on prepare(). At this point it is guaranteed that the stream * parameter from sink buffer is settled, and still prior to all references to period_bytes. */ - sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + sink = comp_dev_get_first_data_consumer(dev); mod->period_bytes = audio_stream_period_bytes(&sink->stream, dev->frames); comp_dbg(dev, "module_adapter_prepare(): got period_bytes = %u", mod->period_bytes); @@ -367,7 +367,7 @@ int module_adapter_prepare(struct comp_dev *dev) } /* allocate buffer for all sinks */ - if (list_is_empty(&mod->sink_buffer_list)) { + if (list_is_empty(&mod->raw_data_buffers_list)) { for (i = 0; i < mod->num_of_sinks; i++) { /* allocate not shared buffer */ struct comp_buffer *buffer = buffer_alloc(buff_size, SOF_MEM_CAPS_RAM, @@ -381,16 +381,16 @@ int module_adapter_prepare(struct comp_dev *dev) } irq_local_disable(flags); - buffer_attach(buffer, &mod->sink_buffer_list, PPL_DIR_UPSTREAM); + list_item_prepend(&buffer->buffers_list, &mod->raw_data_buffers_list); irq_local_enable(flags); buffer_set_params(buffer, mod->stream_params, BUFFER_UPDATE_FORCE); audio_buffer_reset(&buffer->audio_buffer); } } else { - list_for_item(blist, &mod->sink_buffer_list) { + list_for_item(blist, &mod->raw_data_buffers_list) { struct comp_buffer *buffer = container_of(blist, struct comp_buffer, - sink_list); + buffers_list); ret = buffer_set_size(buffer, buff_size, 0); if (ret < 0) { @@ -409,13 +409,13 @@ int module_adapter_prepare(struct comp_dev *dev) return 0; free: - list_for_item_safe(blist, _blist, &mod->sink_buffer_list) { + list_for_item_safe(blist, _blist, &mod->raw_data_buffers_list) { struct comp_buffer *buffer = container_of(blist, struct comp_buffer, - sink_list); + buffers_list); uint32_t flags; irq_local_disable(flags); - buffer_detach(buffer, &mod->sink_buffer_list, PPL_DIR_UPSTREAM); + list_item_del(&buffer->buffers_list); irq_local_enable(flags); buffer_free(buffer); } @@ -606,11 +606,11 @@ static void module_adapter_process_output(struct comp_dev *dev) * copy all produced output samples to output buffers. This loop will do nothing when * there are no samples produced. */ - list_for_item(blist, &mod->sink_buffer_list) { + list_for_item(blist, &mod->raw_data_buffers_list) { if (mod->output_buffers[i].size > 0) { struct comp_buffer *buffer; - buffer = container_of(blist, struct comp_buffer, sink_list); + buffer = container_of(blist, struct comp_buffer, buffers_list); ca_copy_from_module_to_sink(&buffer->stream, mod->output_buffers[i].data, mod->output_buffers[i].size); @@ -621,17 +621,14 @@ static void module_adapter_process_output(struct comp_dev *dev) /* copy from all output local buffers to sink buffers */ i = 0; - list_for_item(blist, &dev->bsink_list) { - struct list_item *_blist; + comp_dev_for_each_consumer(dev, sink) { int j = 0; - list_for_item(_blist, &mod->sink_buffer_list) { + list_for_item(blist, &mod->raw_data_buffers_list) { if (i == j) { struct comp_buffer *source; - sink = container_of(blist, struct comp_buffer, source_list); - source = container_of(_blist, struct comp_buffer, sink_list); - + source = container_of(blist, struct comp_buffer, buffers_list); module_copy_samples(dev, source, sink, mod->output_buffers[i].size); @@ -756,7 +753,7 @@ static int module_adapter_audio_stream_copy_1to1(struct comp_dev *dev) /* Note: Source buffer state is not checked to enable mixout to generate zero * PCM codes when source is not active. */ - if (mod->sink_comp_buffer->sink->state == dev->state) + if (comp_buffer_get_sink_state(mod->sink_comp_buffer) == dev->state) num_output_buffers = 1; ret = module_process_legacy(mod, mod->input_buffers, 1, @@ -783,10 +780,11 @@ static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) { struct comp_buffer *sources[PLATFORM_MAX_STREAMS]; struct comp_buffer *sinks[PLATFORM_MAX_STREAMS]; + struct comp_buffer *sink; + struct comp_buffer *source; struct processing_module *mod = comp_mod(dev); - struct list_item *blist; uint32_t num_input_buffers, num_output_buffers; - int ret, i = 0; + int ret, i; /* handle special case of HOST/DAI type components */ if (dev->ipc_config.type == SOF_COMP_HOST || dev->ipc_config.type == SOF_COMP_DAI) @@ -796,12 +794,9 @@ static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) return module_adapter_audio_stream_copy_1to1(dev); /* acquire all sink and source buffers */ - list_for_item(blist, &dev->bsink_list) { - struct comp_buffer *sink; - - sink = container_of(blist, struct comp_buffer, source_list); + i = 0; + comp_dev_for_each_consumer(dev, sink) sinks[i++] = sink; - } num_output_buffers = i; if (num_output_buffers > mod->max_sinks) { comp_err(dev, "Invalid number of sinks %d\n", num_output_buffers); @@ -809,12 +804,8 @@ static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) } i = 0; - list_for_item(blist, &dev->bsource_list) { - struct comp_buffer *source; - - source = container_of(blist, struct comp_buffer, sink_list); + comp_dev_for_each_producer(dev, source) sources[i++] = source; - } num_input_buffers = i; if (num_input_buffers > mod->max_sources) { comp_err(dev, "Invalid number of sources %d\n", num_input_buffers); @@ -824,11 +815,11 @@ static int module_adapter_audio_stream_type_copy(struct comp_dev *dev) /* setup active input/output buffers for processing */ if (num_output_buffers == 1) { module_single_sink_setup(dev, sources, sinks); - if (sinks[0]->sink->state != dev->state) + if (comp_buffer_get_sink_state(sinks[0]) != dev->state) num_output_buffers = 0; } else if (num_input_buffers == 1) { module_single_source_setup(dev, sources, sinks); - if (sources[0]->source->state != dev->state) { + if (comp_buffer_get_source_state(sources[0]) != dev->state) { num_input_buffers = 0; } } else { @@ -910,15 +901,13 @@ static int module_adapter_copy_ring_buffers(struct comp_dev *dev) * This is an adapter, to be removed when pipeline2.0 is ready */ struct processing_module *mod = comp_mod(dev); - struct list_item *blist; + struct comp_buffer *buffer; int err; - list_for_item(blist, &dev->bsource_list) { + comp_dev_for_each_producer(dev, buffer) { /* input - we need to copy data from audio_stream (as source) * to ring_buffer (as sink) */ - struct comp_buffer *buffer = - container_of(blist, struct comp_buffer, sink_list); err = audio_buffer_sync_secondary_buffer(&buffer->audio_buffer, UINT_MAX); if (err) { @@ -930,7 +919,7 @@ static int module_adapter_copy_ring_buffers(struct comp_dev *dev) if (mod->dp_startup_delay) return 0; - list_for_item(blist, &dev->bsink_list) { + comp_dev_for_each_consumer(dev, buffer) { /* output - we need to copy data from ring_buffer (as source) * to audio_stream (as sink) * @@ -943,8 +932,6 @@ static int module_adapter_copy_ring_buffers(struct comp_dev *dev) * * FIX: copy only the following module's IBS in each LL cycle */ - struct comp_buffer *buffer = - container_of(blist, struct comp_buffer, source_list); struct sof_source *following_mod_data_source = audio_buffer_get_source(&buffer->audio_buffer); @@ -1013,22 +1000,20 @@ static int module_adapter_raw_data_type_copy(struct comp_dev *dev) comp_dbg(dev, "module_adapter_raw_data_type_copy(): start"); - list_for_item(blist, &mod->sink_buffer_list) { - sink = container_of(blist, struct comp_buffer, sink_list); + list_for_item(blist, &mod->raw_data_buffers_list) { + sink = container_of(blist, struct comp_buffer, buffers_list); min_free_frames = MIN(min_free_frames, audio_stream_get_free_frames(&sink->stream)); } /* copy source samples into input buffer */ - list_for_item(blist, &dev->bsource_list) { + comp_dev_for_each_producer(dev, source) { uint32_t bytes_to_process; int frames, source_frame_bytes; - source = container_of(blist, struct comp_buffer, sink_list); - /* check if the source dev is in the same state as the dev */ - if (!source->source || source->source->state != dev->state) + if (comp_buffer_get_source_state(source) != dev->state) continue; frames = MIN(min_free_frames, @@ -1061,10 +1046,7 @@ static int module_adapter_raw_data_type_copy(struct comp_dev *dev) i = 0; /* consume from all input buffers */ - list_for_item(blist, &dev->bsource_list) { - - source = container_of(blist, struct comp_buffer, sink_list); - + comp_dev_for_each_producer(dev, source) { comp_update_buffer_consume(source, mod->input_buffers[i].consumed); bzero((__sparse_force void *)mod->input_buffers[i].data, size); @@ -1179,9 +1161,9 @@ int module_adapter_reset(struct comp_dev *dev) mod->total_data_consumed = 0; mod->total_data_produced = 0; - list_for_item(blist, &mod->sink_buffer_list) { + list_for_item(blist, &mod->raw_data_buffers_list) { struct comp_buffer *buffer = container_of(blist, struct comp_buffer, - sink_list); + buffers_list); buffer_zero(buffer); } @@ -1206,13 +1188,13 @@ void module_adapter_free(struct comp_dev *dev) if (ret) comp_err(dev, "module_adapter_free(): failed with error: %d", ret); - list_for_item_safe(blist, _blist, &mod->sink_buffer_list) { + list_for_item_safe(blist, _blist, &mod->raw_data_buffers_list) { struct comp_buffer *buffer = container_of(blist, struct comp_buffer, - sink_list); + buffers_list); uint32_t flags; irq_local_disable(flags); - buffer_detach(buffer, &mod->sink_buffer_list, PPL_DIR_UPSTREAM); + list_item_del(&buffer->buffers_list); irq_local_enable(flags); buffer_free(buffer); } diff --git a/src/audio/module_adapter/module_adapter_ipc3.c b/src/audio/module_adapter/module_adapter_ipc3.c index 5adc3079708c..b54b0f41388e 100644 --- a/src/audio/module_adapter/module_adapter_ipc3.c +++ b/src/audio/module_adapter/module_adapter_ipc3.c @@ -121,8 +121,7 @@ void module_adapter_check_data(struct processing_module *mod, struct comp_dev *d */ if (IS_PROCESSING_MODE_AUDIO_STREAM(mod) && mod->num_of_sources == 1 && mod->num_of_sinks == 1) { - mod->source_comp_buffer = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); + mod->source_comp_buffer = comp_dev_get_first_data_producer(dev); mod->sink_comp_buffer = sink; mod->stream_copy_single_to_single = true; } @@ -132,13 +131,13 @@ void module_adapter_set_params(struct processing_module *mod, struct sof_ipc_str { } -static int module_source_status_count(struct comp_dev *dev, uint32_t status) +static int module_source_state_count(struct comp_dev *dev, uint32_t state) { - struct list_item *blist; int count = 0; + struct comp_buffer *source; /* count source with state == status */ - list_for_item(blist, &dev->bsource_list) { + comp_dev_for_each_producer(dev, source) /* * FIXME: this is racy, state can be changed by another core. * This is implicitly protected by serialised IPCs. Even when @@ -146,12 +145,8 @@ static int module_source_status_count(struct comp_dev *dev, uint32_t status) * not be sent until the thread has processed and replied to the * current one. */ - struct comp_buffer *source = container_of(blist, struct comp_buffer, - sink_list); - - if (source->source && source->source->state == status) + if (comp_buffer_get_source_state(source) == state) count++; - } return count; } @@ -163,8 +158,8 @@ int module_adapter_set_state(struct processing_module *mod, struct comp_dev *dev bool sources_active; int ret; - sources_active = module_source_status_count(dev, COMP_STATE_ACTIVE) || - module_source_status_count(dev, COMP_STATE_PAUSED); + sources_active = module_source_state_count(dev, COMP_STATE_ACTIVE) || + module_source_state_count(dev, COMP_STATE_PAUSED); /* don't stop/start module if one of the sources is active/paused */ if ((cmd == COMP_TRIGGER_STOP || cmd == COMP_TRIGGER_PRE_START) && sources_active) { @@ -324,25 +319,21 @@ int module_adapter_cmd(struct comp_dev *dev, int cmd, void *data, int max_data_s int module_adapter_sink_src_prepare(struct comp_dev *dev) { struct processing_module *mod = comp_mod(dev); - struct list_item *blist; + struct comp_buffer *sink_buffer; + struct comp_buffer *source_buffer; int ret; int i; /* acquire all sink and source buffers, get handlers to sink/source API */ i = 0; - list_for_item(blist, &dev->bsink_list) { - struct comp_buffer *sink_buffer = - container_of(blist, struct comp_buffer, source_list); + comp_dev_for_each_consumer(dev, sink_buffer) { mod->sinks[i] = audio_buffer_get_sink(&sink_buffer->audio_buffer); i++; } mod->num_of_sinks = i; i = 0; - list_for_item(blist, &dev->bsource_list) { - struct comp_buffer *source_buffer = - container_of(blist, struct comp_buffer, sink_list); - + comp_dev_for_each_producer(dev, source_buffer) { mod->sources[i] = audio_buffer_get_source(&source_buffer->audio_buffer); i++; } diff --git a/src/audio/module_adapter/module_adapter_ipc4.c b/src/audio/module_adapter/module_adapter_ipc4.c index 060cef446f73..00ba4696f639 100644 --- a/src/audio/module_adapter/module_adapter_ipc4.c +++ b/src/audio/module_adapter/module_adapter_ipc4.c @@ -187,24 +187,20 @@ EXPORT_SYMBOL(module_adapter_get_attribute); static bool module_adapter_multi_sink_source_prepare(struct comp_dev *dev) { struct processing_module *mod = comp_mod(dev); - struct list_item *blist; + struct comp_buffer *sink_buffer; + struct comp_buffer *source_buffer; int i; /* acquire all sink and source buffers, get handlers to sink/source API */ i = 0; - list_for_item(blist, &dev->bsink_list) { - struct comp_buffer *sink_buffer = - container_of(blist, struct comp_buffer, source_list); + comp_dev_for_each_consumer(dev, sink_buffer) { mod->sinks[i] = audio_buffer_get_sink(&sink_buffer->audio_buffer); i++; } mod->num_of_sinks = i; i = 0; - list_for_item(blist, &dev->bsource_list) { - struct comp_buffer *source_buffer = - container_of(blist, struct comp_buffer, sink_list); - + comp_dev_for_each_producer(dev, source_buffer) { mod->sources[i] = audio_buffer_get_source(&source_buffer->audio_buffer); i++; } @@ -216,9 +212,8 @@ static bool module_adapter_multi_sink_source_prepare(struct comp_dev *dev) return true; /* re-assign the source/sink modules */ - mod->sink_comp_buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - mod->source_comp_buffer = list_first_item(&dev->bsource_list, - struct comp_buffer, sink_list); + mod->sink_comp_buffer = comp_dev_get_first_data_consumer(dev); + mod->source_comp_buffer = comp_dev_get_first_data_producer(dev); return false; } diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index f30731fa4874..15ae9d84c2eb 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -167,9 +167,9 @@ static void buffer_set_comp(struct comp_buffer *buffer, struct comp_dev *comp, int dir) { if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) - buffer->source = comp; + comp_buffer_set_source_component(buffer, comp); else - buffer->sink = comp; + comp_buffer_set_sink_component(buffer, comp); } int pipeline_connect(struct comp_dev *comp, struct comp_buffer *buffer, diff --git a/src/audio/smart_amp/smart_amp.c b/src/audio/smart_amp/smart_amp.c index 1b72ef4a65f8..6cb396a4c153 100644 --- a/src/audio/smart_amp/smart_amp.c +++ b/src/audio/smart_amp/smart_amp.c @@ -746,7 +746,8 @@ static int smart_amp_prepare(struct comp_dev *dev) struct comp_buffer *source_buffer; comp_dev_for_each_producer(dev, source_buffer) { - if (source_buffer->source->ipc_config.type == SOF_COMP_DEMUX) + if (comp_buffer_get_source_component(source_buffer)->ipc_config.type + == SOF_COMP_DEMUX) sad->feedback_buf = source_buffer; else sad->source_buf = source_buffer; diff --git a/src/audio/tone.c b/src/audio/tone.c index c07be0302b8c..05389a3f4b1b 100644 --- a/src/audio/tone.c +++ b/src/audio/tone.c @@ -632,9 +632,7 @@ static int tone_copy(struct comp_dev *dev) comp_dbg(dev, "tone_copy()"); /* tone component sink buffer */ - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - + sink = comp_dev_get_first_data_consumer(dev); free = audio_stream_get_free_bytes(&sink->stream); /* Test that sink has enough free frames. Then run once to maintain diff --git a/src/include/module/module/base.h b/src/include/module/module/base.h index d3f912957791..59fb2b854df0 100644 --- a/src/include/module/module/base.h +++ b/src/include/module/module/base.h @@ -86,7 +86,10 @@ struct processing_module { */ #ifdef SOF_MODULE_API_PRIVATE struct sof_ipc_stream_params *stream_params; - struct list_item sink_buffer_list; /* list of sink buffers to save produced output */ + /* list of sink buffers to save produced output, to be used in Raw data + * processing mode + */ + struct list_item raw_data_buffers_list; /* * This is a temporary change in order to support the trace messages in the modules. This diff --git a/src/include/sof/audio/buffer.h b/src/include/sof/audio/buffer.h index eafe9d1cd190..8dbef5cc4654 100644 --- a/src/include/sof/audio/buffer.h +++ b/src/include/sof/audio/buffer.h @@ -141,6 +141,9 @@ struct comp_buffer { /* lists */ struct list_item source_list; /* list in comp buffers */ struct list_item sink_list; /* list in comp buffers */ + + /* list of buffers, to be used i.e. in raw data processing mode*/ + struct list_item buffers_list; }; /* @@ -159,6 +162,28 @@ static inline struct comp_dev *comp_buffer_get_sink_component(const struct comp_ return buffer->sink; } +static inline +void comp_buffer_set_source_component(struct comp_buffer *buffer, struct comp_dev *comp) +{ + buffer->source = comp; +} + +static inline +void comp_buffer_set_sink_component(struct comp_buffer *buffer, struct comp_dev *comp) +{ + buffer->sink = comp; +} + +static inline void comp_buffer_reset_source_list(struct comp_buffer *buffer) +{ + list_init(&buffer->source_list); +} + +static inline void comp_buffer_reset_sink_list(struct comp_buffer *buffer) +{ + list_init(&buffer->sink_list); +} + /* Only to be used for synchronous same-core notifications! */ struct buffer_cb_transact { struct comp_buffer *buffer; @@ -170,10 +195,6 @@ struct buffer_cb_free { struct comp_buffer *buffer; }; -#define buffer_comp_list(buffer, dir) \ - ((dir) == PPL_DIR_DOWNSTREAM ? &buffer->source_list : \ - &buffer->sink_list) - #define buffer_from_list(ptr, dir) \ ((dir) == PPL_DIR_DOWNSTREAM ? \ container_of(ptr, struct comp_buffer, source_list) : \ diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 03f37ac884ad..4531d7691f74 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -649,6 +649,7 @@ static inline struct comp_buffer *comp_dev_get_first_data_producer(struct comp_d /** * Get a pointer to the next comp_buffer object providing data to the component * The function will return NULL if there're no more data providers + * _save version also checks if producer != NULL */ static inline struct comp_buffer *comp_dev_get_next_data_producer(struct comp_dev *component, struct comp_buffer *producer) @@ -657,6 +658,12 @@ static inline struct comp_buffer *comp_dev_get_next_data_producer(struct comp_de list_item(producer->sink_list.next, struct comp_buffer, sink_list); } +static inline struct comp_buffer *comp_dev_get_next_data_producer_safe(struct comp_dev *component, + struct comp_buffer *producer) +{ + return producer ? comp_dev_get_next_data_producer(component, producer) : NULL; +} + /** * Get a pointer to the first comp_buffer object receiving data from the component * The function will return NULL if there's no data consumers @@ -670,6 +677,7 @@ static inline struct comp_buffer *comp_dev_get_first_data_consumer(struct comp_d /** * Get a pointer to the next comp_buffer object receiving data from the component * The function will return NULL if there're no more data consumers + * _safe version also checks if consumer is != NULL */ static inline struct comp_buffer *comp_dev_get_next_data_consumer(struct comp_dev *component, struct comp_buffer *consumer) @@ -678,6 +686,12 @@ static inline struct comp_buffer *comp_dev_get_next_data_consumer(struct comp_de list_item(consumer->source_list.next, struct comp_buffer, source_list); } +static inline struct comp_buffer *comp_dev_get_next_data_consumer_safe(struct comp_dev *component, + struct comp_buffer *consumer) +{ + return consumer ? comp_dev_get_next_data_consumer(component, consumer) : NULL; +} + /* * a macro for easy iteration through component's list of producers */ @@ -686,13 +700,39 @@ static inline struct comp_buffer *comp_dev_get_next_data_consumer(struct comp_de _producer != NULL; \ _producer = comp_dev_get_next_data_producer(_dev, _producer)) +/* + * a macro for easy iteration through component's list of producers + * allowing deletion of a buffer during iteration + * + * additional "safe storage" pointer to struct comp_buffer must be provided + */ +#define comp_dev_for_each_producer_safe(_dev, _producer, _next_producer) \ + for (_producer = comp_dev_get_first_data_producer(_dev), \ + _next_producer = comp_dev_get_next_data_producer_safe(_dev, _producer); \ + _producer != NULL; \ + _producer = _next_producer, \ + _next_producer = comp_dev_get_next_data_producer_safe(_dev, _producer)) + +/* + * a macro for easy iteration through component's list of consumers + */ +#define comp_dev_for_each_consumer(_dev, _consumer) \ + for (_consumer = comp_dev_get_first_data_consumer(_dev); \ + _consumer != NULL; \ + _consumer = comp_dev_get_next_data_consumer(_dev, _consumer)) \ + /* * a macro for easy iteration through component's list of consumers + * allowing deletion of a buffer during iteration + * + * additional "safe storage" pointer to struct comp_buffer must be provided */ -#define comp_dev_for_each_consumer(_dev, _consumer) \ - for (_consumer = comp_dev_get_first_data_consumer(_dev); \ - _consumer != NULL; \ - _consumer = comp_dev_get_next_data_consumer(_dev, _consumer)) +#define comp_dev_for_each_consumer_safe(_dev, _consumer, _next_consumer) \ + for (_consumer = comp_dev_get_first_data_consumer(_dev), \ + _next_consumer = comp_dev_get_next_data_consumer_safe(_dev, _consumer); \ + _consumer != NULL; \ + _consumer = _next_consumer, \ + _next_consumer = comp_dev_get_next_data_consumer_safe(_dev, _consumer)) /** @}*/ diff --git a/src/ipc/ipc-helper.c b/src/ipc/ipc-helper.c index 1e27c701899f..1d1b651d1c49 100644 --- a/src/ipc/ipc-helper.c +++ b/src/ipc/ipc-helper.c @@ -115,10 +115,8 @@ static void comp_update_params(uint32_t flag, int comp_verify_params(struct comp_dev *dev, uint32_t flag, struct sof_ipc_stream_params *params) { - struct list_item *buffer_list; struct list_item *source_list; struct list_item *sink_list; - struct list_item *clist; struct comp_buffer *sinkb; struct comp_buffer *buf; int dir = dev->direction; @@ -136,13 +134,9 @@ int comp_verify_params(struct comp_dev *dev, uint32_t flag, */ if (list_is_empty(source_list) != list_is_empty(sink_list)) { if (list_is_empty(sink_list)) - buf = list_first_item(source_list, - struct comp_buffer, - sink_list); + buf = comp_dev_get_first_data_producer(dev); else - buf = list_first_item(sink_list, - struct comp_buffer, - source_list); + buf = comp_dev_get_first_data_consumer(dev); /* update specific pcm parameter with buffer parameter if * specific flag is set. @@ -160,18 +154,22 @@ int comp_verify_params(struct comp_dev *dev, uint32_t flag, /* for other components we iterate over all downstream buffers * (for playback) or upstream buffers (for capture). */ - buffer_list = comp_buffer_list(dev, dir); - - list_for_item(clist, buffer_list) { - buf = buffer_from_list(clist, dir); - comp_update_params(flag, params, buf); - buffer_set_params(buf, params, BUFFER_UPDATE_FORCE); + if (dir == PPL_DIR_DOWNSTREAM) { + comp_dev_for_each_consumer(dev, buf) { + comp_update_params(flag, params, buf); + buffer_set_params(buf, params, + BUFFER_UPDATE_FORCE); + } + } else { + comp_dev_for_each_producer(dev, buf) { + comp_update_params(flag, params, buf); + buffer_set_params(buf, params, + BUFFER_UPDATE_FORCE); + } } /* fetch sink buffer in order to calculate period frames */ - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - + sinkb = comp_dev_get_first_data_consumer(dev); component_set_nearest_period_frames(dev, audio_stream_get_rate(&sinkb->stream)); } @@ -263,7 +261,8 @@ int ipc_pipeline_complete(struct ipc *ipc, uint32_t comp_id) int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) { struct ipc_comp_dev *icd; - struct list_item *clist, *tmp; + struct comp_buffer *buffer; + struct comp_buffer *safe; uint32_t flags; /* check whether component exists */ @@ -305,27 +304,18 @@ int ipc_comp_free(struct ipc *ipc, uint32_t comp_id) } irq_local_disable(flags); - list_for_item_safe(clist, tmp, &icd->cd->bsource_list) { - struct comp_buffer *buffer = container_of(clist, struct comp_buffer, sink_list); - - buffer->sink = NULL; - /* Also if it isn't shared - we are about to modify uncached data */ - dcache_writeback_invalidate_region(uncache_to_cache(buffer), - sizeof(*buffer)); + comp_dev_for_each_producer_safe(icd->cd, buffer, safe) { + comp_buffer_set_sink_component(buffer, NULL); /* This breaks the list, but we anyway delete all buffers */ - list_init(clist); + comp_buffer_reset_sink_list(buffer); } - list_for_item_safe(clist, tmp, &icd->cd->bsink_list) { - struct comp_buffer *buffer = container_of(clist, struct comp_buffer, source_list); - - buffer->source = NULL; - /* Also if it isn't shared - we are about to modify uncached data */ - dcache_writeback_invalidate_region(uncache_to_cache(buffer), - sizeof(*buffer)); + comp_dev_for_each_consumer_safe(icd->cd, buffer, safe) { + comp_buffer_set_source_component(buffer, NULL); /* This breaks the list, but we anyway delete all buffers */ - list_init(clist); + comp_buffer_reset_source_list(buffer); } + irq_local_enable(flags); /* free component and remove from list */ diff --git a/src/ipc/ipc3/handler.c b/src/ipc/ipc3/handler.c index 12f2ba3a34a4..eb812e58fce2 100644 --- a/src/ipc/ipc3/handler.c +++ b/src/ipc/ipc3/handler.c @@ -137,7 +137,7 @@ struct ipc_cmd_hdr *mailbox_validate(void) /* check if a pipeline is hostless when walking downstream */ static bool is_hostless_downstream(struct comp_dev *current) { - struct list_item *clist; + struct comp_buffer *buffer; /* check if current is a HOST comp */ if (current->ipc_config.type == SOF_COMP_HOST || @@ -145,22 +145,18 @@ static bool is_hostless_downstream(struct comp_dev *current) return false; /* check if the pipeline has a HOST comp downstream */ - list_for_item(clist, ¤t->bsink_list) { - struct comp_buffer *buffer; - - buffer = container_of(clist, struct comp_buffer, source_list); - + comp_dev_for_each_consumer(current, buffer) { /* don't go downstream if this component is not connected */ - if (!buffer->sink) + if (!comp_buffer_get_sink_component(buffer)) continue; /* dont go downstream if this comp belongs to another pipe */ - if (buffer->sink->ipc_config.pipeline_id != + if (comp_buffer_get_sink_component(buffer)->ipc_config.pipeline_id != current->ipc_config.pipeline_id) continue; /* return if there's a host comp downstream */ - if (!is_hostless_downstream(buffer->sink)) + if (!is_hostless_downstream(comp_buffer_get_sink_component(buffer))) return false; } @@ -170,7 +166,7 @@ static bool is_hostless_downstream(struct comp_dev *current) /* check if a pipeline is hostless when walking upstream */ static bool is_hostless_upstream(struct comp_dev *current) { - struct list_item *clist; + struct comp_buffer *buffer; /* check if current is a HOST comp */ if (current->ipc_config.type == SOF_COMP_HOST || @@ -178,22 +174,18 @@ static bool is_hostless_upstream(struct comp_dev *current) return false; /* check if the pipeline has a HOST comp upstream */ - list_for_item(clist, ¤t->bsource_list) { - struct comp_buffer *buffer; - - buffer = container_of(clist, struct comp_buffer, sink_list); - + comp_dev_for_each_producer(current, buffer) { /* don't go upstream if this component is not connected */ - if (!buffer->source) + if (!comp_buffer_get_source_component(buffer)) continue; /* dont go upstream if this comp belongs to another pipeline */ - if (buffer->source->ipc_config.pipeline_id != + if (comp_buffer_get_source_component(buffer)->ipc_config.pipeline_id != current->ipc_config.pipeline_id) continue; /* return if there is a host comp upstream */ - if (!is_hostless_upstream(buffer->source)) + if (!is_hostless_upstream(comp_buffer_get_source_component(buffer))) return false; } diff --git a/src/ipc/ipc3/helper.c b/src/ipc/ipc3/helper.c index 678d3306e4b1..adb4d7ec1f16 100644 --- a/src/ipc/ipc3/helper.c +++ b/src/ipc/ipc3/helper.c @@ -535,15 +535,15 @@ int ipc_buffer_free(struct ipc *ipc, uint32_t buffer_id) continue; /* check comp state if sink and source are valid */ - if (ibd->cb->sink == icd->cd) { - sink = ibd->cb->sink; - if (ibd->cb->sink->state != COMP_STATE_READY) + if (comp_buffer_get_sink_component(ibd->cb) == icd->cd) { + sink = comp_buffer_get_sink_component(ibd->cb); + if (comp_buffer_get_sink_state(ibd->cb) != COMP_STATE_READY) sink_active = true; } - if (ibd->cb->source == icd->cd) { - source = ibd->cb->source; - if (ibd->cb->source->state != COMP_STATE_READY) + if (comp_buffer_get_source_component(ibd->cb) == icd->cd) { + source = comp_buffer_get_source_component(ibd->cb); + if (comp_buffer_get_source_state(ibd->cb) != COMP_STATE_READY) source_active = true; } } diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index 0dfb4bc73fc2..c63b7fc00392 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -296,16 +296,12 @@ static int ipc_pipeline_module_free(uint32_t pipeline_id) icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_COMPONENT, pipeline_id, IPC_COMP_ALL); while (icd) { - struct list_item *list, *_list; struct comp_buffer *buffer; + struct comp_buffer *safe; /* free sink buffer allocated by current component in bind function */ - list_for_item_safe(list, _list, &icd->cd->bsink_list) { - struct comp_dev *sink; - - buffer = container_of(list, struct comp_buffer, source_list); - pipeline_disconnect(icd->cd, buffer, PPL_CONN_DIR_COMP_TO_BUFFER); - sink = buffer->sink; + comp_dev_for_each_consumer_safe(icd->cd, buffer, safe) { + struct comp_dev *sink = comp_buffer_get_sink_component(buffer); /* free the buffer only when the sink module has also been disconnected */ if (!sink) @@ -313,12 +309,9 @@ static int ipc_pipeline_module_free(uint32_t pipeline_id) } /* free source buffer allocated by current component in bind function */ - list_for_item_safe(list, _list, &icd->cd->bsource_list) { - struct comp_dev *source; - - buffer = container_of(list, struct comp_buffer, sink_list); + comp_dev_for_each_producer_safe(icd->cd, buffer, safe) { pipeline_disconnect(icd->cd, buffer, PPL_CONN_DIR_BUFFER_TO_COMP); - source = buffer->source; + struct comp_dev *source = comp_buffer_get_source_component(buffer); /* free the buffer only when the source module has also been disconnected */ if (!source) @@ -677,8 +670,8 @@ int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) { struct ipc4_module_bind_unbind *bu; struct comp_buffer *buffer = NULL; + struct comp_buffer *buf; struct comp_dev *src, *sink; - struct list_item *sink_list; uint32_t src_id, sink_id, buffer_id; uint32_t flags = 0; int ret, ret1; @@ -708,10 +701,8 @@ int ipc_comp_disconnect(struct ipc *ipc, ipc_pipe_comp_connect *_connect) return ipc4_process_on_core(src->ipc_config.core, false); buffer_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue); - list_for_item(sink_list, &src->bsink_list) { - struct comp_buffer *buf = container_of(sink_list, struct comp_buffer, source_list); + comp_dev_for_each_consumer(src, buf) { bool found = buf_get_id(buf) == buffer_id; - if (found) { buffer = buf; break; @@ -851,9 +842,9 @@ static int ipc4_update_comps_direction(struct ipc *ipc, uint32_t ppl_id) if (list_is_empty(&icd->cd->bsource_list)) continue; - src_buf = list_first_item(&icd->cd->bsource_list, struct comp_buffer, sink_list); - if (src_buf->source->direction_set) { - icd->cd->direction = src_buf->source->direction; + src_buf = comp_dev_get_first_data_producer(icd->cd); + if (comp_buffer_get_source_component(src_buf)->direction_set) { + icd->cd->direction = comp_buffer_get_source_component(src_buf)->direction; icd->cd->direction_set = true; continue; } diff --git a/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c b/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c index 2a3b14bf2dfe..dea28ce65401 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c +++ b/test/cmocka/src/audio/pipeline/pipeline_connect_upstream.c @@ -129,13 +129,13 @@ static void test_audio_pipeline_complete_connect_upstream_ignore_source */ list_item_append(&result.sched_comp->bsource_list, &test_data->b1->sink_list); - test_data->b1->sink = result.sched_comp; - test_data->b1->source = test_data->second; + comp_buffer_set_sink_component(test_data->b1, result.sched_comp); + comp_buffer_set_source_component(test_data->b1, test_data->second); list_item_append(&test_data->b1->source_list, &test_data->second->bsink_list); list_item_append(&test_data->second->bsource_list, &test_data->b2->sink_list); - test_data->b2->sink = test_data->second; + comp_buffer_set_sink_component(test_data->b2, test_data->second); /*Testing component*/ pipeline_complete(&result, test_data->first, test_data->second); @@ -156,14 +156,11 @@ static void test_audio_pipeline_complete_connect_downstream_full(void **state) /*Connecting first comp to second*/ comp = &test_data->second->ipc_config; comp->pipeline_id = PIPELINE_ID_SAME; - list_item_append(&result.sched_comp->bsink_list, - &test_data->b1->source_list); - test_data->b1->source = result.sched_comp; - list_item_append(&test_data->b1->source_list, - &result.sched_comp->bsink_list); - test_data->b1->sink = test_data->second; - list_item_append(&test_data->b1->sink_list, - &test_data->second->bsource_list); + list_item_append(&result.sched_comp->bsink_list, &test_data->b1->source_list); + comp_buffer_set_source_component(test_data->b1, result.sched_comp); + list_item_append(&test_data->b1->source_list, &result.sched_comp->bsink_list); + comp_buffer_set_sink_component(test_data->b1, test_data->second); + list_item_append(&test_data->b1->sink_list, &test_data->second->bsource_list); test_data->first->frames = 0; test_data->second->frames = 0; @@ -189,8 +186,8 @@ static void test_audio_pipeline_complete_connect_upstream_full(void **state) comp->pipeline_id = PIPELINE_ID_SAME; list_item_append(&result.sched_comp->bsource_list, &test_data->b1->sink_list); - test_data->b1->sink = test_data->first; - test_data->b1->source = test_data->second; + comp_buffer_set_sink_component(test_data->b1, test_data->first); + comp_buffer_set_source_component(test_data->b1, test_data->second); /*Testing component*/ pipeline_complete(&result, test_data->first, test_data->second); @@ -212,12 +209,10 @@ static void test_audio_pipeline_complete_connect_upstream_other_pipeline /*Connecting first comp to second*/ comp = &test_data->second->ipc_config; comp->pipeline_id = PIPELINE_ID_DIFFERENT; - list_item_append(&result.sched_comp->bsource_list, - &test_data->b1->sink_list); - test_data->b1->sink = test_data->first; - test_data->b1->source = test_data->second; - list_item_append(&test_data->second->bsource_list, - &test_data->b1->source_list); + list_item_append(&result.sched_comp->bsource_list, &test_data->b1->sink_list); + comp_buffer_set_sink_component(test_data->b1, test_data->first); + comp_buffer_set_source_component(test_data->b1, test_data->second); + list_item_append(&test_data->second->bsource_list, &test_data->b1->source_list); /*Testing component*/ pipeline_complete(&result, test_data->first, test_data->second); diff --git a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c index af811d74df64..35899b14b297 100644 --- a/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c +++ b/test/cmocka/src/audio/pipeline/pipeline_connection_mocks.c @@ -17,12 +17,12 @@ void cleanup_test_data(struct pipeline_connect_data *data) { list_init(&data->first->bsource_list); list_init(&data->second->bsource_list); - list_init(&data->b1->sink_list); - list_init(&data->b1->source_list); + comp_buffer_reset_sink_list(data->b1); + comp_buffer_reset_source_list(data->b1); list_init(&data->first->bsink_list); list_init(&data->second->bsink_list); - list_init(&data->b2->sink_list); - list_init(&data->b2->source_list); + comp_buffer_reset_sink_list(data->b2); + comp_buffer_reset_source_list(data->b2); } struct pipeline_connect_data *get_standard_connect_objects(void) @@ -70,17 +70,17 @@ struct pipeline_connect_data *get_standard_connect_objects(void) struct comp_buffer *buffer = calloc(sizeof(struct comp_buffer), 1); - buffer->source = first; - buffer->sink = second; - list_init(&buffer->sink_list); - list_init(&buffer->source_list); + comp_buffer_set_source_component(buffer, first); + comp_buffer_set_sink_component(buffer, second); + comp_buffer_reset_sink_list(buffer); + comp_buffer_reset_source_list(buffer); pipeline_connect_data->b1 = buffer; struct comp_buffer *buffer_2 = calloc(sizeof(struct comp_buffer), 1); - buffer_2->source = second; - list_init(&buffer_2->sink_list); - list_init(&buffer_2->source_list); + comp_buffer_set_source_component(buffer_2, second); + comp_buffer_reset_sink_list(buffer_2); + comp_buffer_reset_source_list(buffer_2); pipeline_connect_data->b2 = buffer_2; pipeline_connect_data->p = *pipe; diff --git a/test/cmocka/src/util.h b/test/cmocka/src/util.h index 5ef231ceba64..58529ac5c422 100644 --- a/test/cmocka/src/util.h +++ b/test/cmocka/src/util.h @@ -42,7 +42,7 @@ static inline struct comp_buffer *create_test_sink(struct comp_dev *dev, static inline void free_test_sink(struct comp_buffer *buffer) { - free(buffer->sink); + free(comp_buffer_get_sink_component(buffer)); buffer_free(buffer); }