pipeline: refactor whole pipeline component

Refactor the whole pipeline component:
- one method to handle both upstream and downstream walk
  across the pipeline graph,
- code deduplication,
- cuts pipeline implementation size by half.

Signed-off-by: Tomasz Lauda <tomasz.lauda@linux.intel.com>
This commit is contained in:
Tomasz Lauda 2019-01-15 13:03:02 +01:00 committed by Liam Girdwood
parent e300861d4a
commit d918f1b3d0
7 changed files with 525 additions and 1052 deletions

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@
#include <sof/audio/component.h>
#include <sof/trace.h>
#include <sof/schedule.h>
#include <sof/cache.h>
#include <uapi/ipc/topology.h>
/* pipeline tracing */
@ -78,6 +79,15 @@ struct comp_buffer {
((dir) == PPL_DIR_DOWNSTREAM ? &buffer->source_list : \
&buffer->sink_list)
#define buffer_from_list(ptr, type, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? \
container_of(ptr, type, source_list) : \
container_of(ptr, type, sink_list))
#define buffer_get_comp(buffer, dir) \
((dir) == PPL_DIR_DOWNSTREAM ? buffer->sink : \
buffer->source)
#define buffer_set_comp(buffer, comp, dir) \
do { \
if (dir == PPL_CONN_DIR_COMP_TO_BUFFER) \
@ -86,6 +96,8 @@ struct comp_buffer {
buffer->sink = comp; \
} while (0) \
typedef void (*cache_buff_op)(struct comp_buffer *);
/* pipeline buffer creation and destruction */
struct comp_buffer *buffer_new(struct sof_ipc_buffer *desc);
void buffer_free(struct comp_buffer *buffer);
@ -131,6 +143,30 @@ static inline uint32_t comp_buffer_get_copy_bytes(struct comp_buffer *source,
return source->avail;
}
static inline void comp_buffer_cache_wtb_inv(struct comp_buffer *buffer)
{
dcache_writeback_invalidate_region(buffer, sizeof(*buffer));
}
static inline void comp_buffer_cache_inv(struct comp_buffer *buffer)
{
dcache_invalidate_region(buffer, sizeof(*buffer));
}
static inline cache_buff_op comp_buffer_cache_op(int cmd)
{
switch (cmd) {
case CACHE_WRITEBACK_INV:
return &comp_buffer_cache_wtb_inv;
case CACHE_INVALIDATE:
return &comp_buffer_cache_inv;
default:
trace_buffer_error("comp_buffer_cache_op() error: "
"invalid cmd = %u", cmd);
return NULL;
}
}
static inline void buffer_reset_pos(struct comp_buffer *buffer)
{
/* reset read and write pointer to buffer bas */

View File

@ -118,15 +118,6 @@
#define COMP_CMD_IPC_MMAP_VOL(chan) (216 + chan) /* Volume */
/* component operations */
#define COMP_OPS_PARAMS 0
#define COMP_OPS_TRIGGER 1
#define COMP_OPS_PREPARE 2
#define COMP_OPS_COPY 3
#define COMP_OPS_BUFFER 4
#define COMP_OPS_RESET 5
#define COMP_OPS_CACHE 6
#define trace_comp(__e, ...) trace_event(TRACE_CLASS_COMP, __e, ##__VA_ARGS__)
#define trace_comp_error(__e, ...) trace_error(TRACE_CLASS_COMP, __e, ##__VA_ARGS__)
#define tracev_comp(__e, ...) tracev_event(TRACE_CLASS_COMP, __e, ##__VA_ARGS__)
@ -241,8 +232,6 @@ struct comp_dev {
((dir) == PPL_DIR_DOWNSTREAM ? &comp->bsink_list : \
&comp->bsource_list)
typedef void (*cache_command)(void *, size_t);
void sys_comp_init(void);
/* component registration */
@ -359,18 +348,15 @@ void sys_comp_tone_init(void);
void sys_comp_eq_iir_init(void);
void sys_comp_eq_fir_init(void);
/*
* Convenience functions to install upstream/downstream common params. Only
* applicable to single upstream source. Components with > 1 source or sink
* must do this manually.
*
* This allows params to propagate from the host PCM component downstream on
* playback and upstream on capture.
*/
static inline void comp_install_params(struct comp_dev *dev,
struct comp_dev *previous)
static inline int comp_is_single_pipeline(struct comp_dev *current,
struct comp_dev *previous)
{
dev->params = previous->params;
return current->comp.pipeline_id == previous->comp.pipeline_id;
}
static inline int comp_is_active(struct comp_dev *current)
{
return current->state == COMP_STATE_ACTIVE;
}
static inline uint32_t comp_frame_bytes(struct comp_dev *dev)
@ -426,18 +412,4 @@ static inline void comp_overrun(struct comp_dev *dev, struct comp_buffer *sink,
pipeline_xrun(dev->pipeline, dev, (int32_t)copy_bytes - sink->free);
}
static inline cache_command comp_get_cache_command(int cmd)
{
switch (cmd) {
case CACHE_WRITEBACK_INV:
return &dcache_writeback_invalidate_region;
case CACHE_INVALIDATE:
return &dcache_invalidate_region;
default:
trace_comp_error("comp_get_cache_command() error: "
"invalid cmd = %u", cmd);
return NULL;
}
}
#endif

View File

@ -61,7 +61,7 @@ static void test_audio_pipeline_complete_wrong_status(void **state)
result.status = COMP_STATE_READY;
/*Testing component*/
int error_code = pipeline_complete(&result);
int error_code = pipeline_complete(&result, test_data->first);
assert_int_equal(error_code, -EINVAL);
}
@ -74,7 +74,7 @@ static void test_audio_pipeline_complete_ready_state(void **state)
cleanup_test_data(test_data);
/*Testing component*/
int error_code = pipeline_complete(&result);
int error_code = pipeline_complete(&result, test_data->first);
assert_int_equal(error_code, 0);
assert_int_equal(result.status, COMP_STATE_READY);
@ -89,10 +89,10 @@ static void test_audio_pipeline_complete_connect_is_endpoint(void **state)
cleanup_test_data(test_data);
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
/*Was not marked as endpoint (bsink and bsource lists empty)*/
assert_int_equal(result.sched_comp->is_endpoint, 1);
assert_true(list_is_empty(&result.sched_comp->bsource_list));
}
static void test_audio_pipeline_complete_connect_downstream_variable_set
@ -104,7 +104,7 @@ static void test_audio_pipeline_complete_connect_downstream_variable_set
cleanup_test_data(test_data);
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
assert_int_equal
(
@ -125,8 +125,6 @@ static void test_audio_pipeline_complete_connect_downstream_ignore_sink
/*Connecting first comp to second while second is from other pipeline
*and first has no upstream components
*/
test_data->first->is_endpoint = 0;
test_data->second->is_endpoint = 0;
list_item_append(&result.sched_comp->bsink_list,
&test_data->b1->source_list);
list_item_append(&test_data->b1->source_list,
@ -135,10 +133,10 @@ static void test_audio_pipeline_complete_connect_downstream_ignore_sink
&test_data->second->bsource_list);
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
assert_int_equal(test_data->first->is_endpoint, 1);
assert_int_equal(test_data->second->is_endpoint, 0);
assert_true(list_is_empty(&test_data->first->bsource_list));
assert_false(list_is_empty(&test_data->second->bsource_list));
}
/*Test going downstream ignoring source from other pipeline*/
@ -153,8 +151,6 @@ static void test_audio_pipeline_complete_connect_upstream_ignore_source
/*Connecting first comp to second while second is from other pipeline
*and first has no downstream components
*/
test_data->first->is_endpoint = 0;
test_data->second->is_endpoint = 0;
list_item_append(&result.sched_comp->bsource_list,
&test_data->b1->sink_list);
test_data->b1->sink = result.sched_comp;
@ -166,10 +162,10 @@ static void test_audio_pipeline_complete_connect_upstream_ignore_source
test_data->b2->sink = test_data->second;
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
assert_int_equal(test_data->first->is_endpoint, 1);
assert_int_equal(test_data->second->is_endpoint, 0);
assert_true(list_is_empty(&test_data->first->bsink_list));
assert_false(list_is_empty(&test_data->second->bsink_list));
}
/*Test going downstream all the way*/
@ -181,8 +177,6 @@ static void test_audio_pipeline_complete_connect_downstream_full(void **state)
cleanup_test_data(test_data);
/*Connecting first comp to second*/
test_data->first->is_endpoint = 0;
test_data->second->is_endpoint = 0;
test_data->second->comp.pipeline_id = PIPELINE_ID_SAME;
list_item_append(&result.sched_comp->bsink_list,
&test_data->b1->source_list);
@ -197,7 +191,7 @@ static void test_audio_pipeline_complete_connect_downstream_full(void **state)
test_data->second->frames = 0;
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
assert_int_equal(test_data->first->frames,
result.ipc_pipe.frames_per_sched);
@ -214,8 +208,6 @@ static void test_audio_pipeline_complete_connect_upstream_full(void **state)
cleanup_test_data(test_data);
/*Connecting first comp to second*/
test_data->first->is_endpoint = 0;
test_data->second->is_endpoint = 0;
test_data->second->comp.pipeline_id = PIPELINE_ID_SAME;
list_item_append(&result.sched_comp->bsource_list,
&test_data->b1->sink_list);
@ -223,7 +215,7 @@ static void test_audio_pipeline_complete_connect_upstream_full(void **state)
test_data->b1->source = test_data->second;
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
assert_int_equal(test_data->first->frames,
result.ipc_pipe.frames_per_sched);
@ -241,8 +233,6 @@ static void test_audio_pipeline_complete_connect_upstream_other_pipeline
cleanup_test_data(test_data);
/*Connecting first comp to second*/
test_data->first->is_endpoint = 0;
test_data->second->is_endpoint = 0;
test_data->second->comp.pipeline_id = PIPELINE_ID_DIFFERENT;
list_item_append(&result.sched_comp->bsource_list,
&test_data->b1->sink_list);
@ -252,7 +242,7 @@ static void test_audio_pipeline_complete_connect_upstream_other_pipeline
&test_data->b1->source_list);
/*Testing component*/
pipeline_complete(&result);
pipeline_complete(&result, test_data->first);
assert_ptr_equal(test_data->first, result.source_comp);
}

View File

@ -58,19 +58,15 @@ struct pipeline_connect_data *get_standard_connect_objects(void)
struct comp_dev *first = calloc(sizeof(struct comp_dev), 1);
first->is_endpoint = 0;
first->comp.id = 3;
first->comp.pipeline_id = PIPELINE_ID_SAME;
list_init(&first->bsink_list);
list_init(&first->bsource_list);
list_init(&pipe->comp_list);
list_init(&pipe->buffer_list);
pipeline_connect_data->first = first;
pipe->sched_comp = first;
struct comp_dev *second = calloc(sizeof(struct comp_dev), 1);
second->is_endpoint = 0;
second->comp.id = 4;
second->comp.pipeline_id = PIPELINE_ID_DIFFERENT;
list_init(&second->bsink_list);

View File

@ -58,7 +58,9 @@ static void test_audio_pipeline_free_comp_busy(void **state)
cleanup_test_data(test_data);
result.source_comp = test_data->first;
result.sched_comp->state = 3;
/*Testing component*/
int err = pipeline_free(&result);
@ -72,7 +74,9 @@ static void test_audio_pipeline_free_return_value(void **state)
cleanup_test_data(test_data);
result.source_comp = test_data->first;
result.sched_comp->state = COMP_STATE_READY;
/*Testing component*/
int err = pipeline_free(&result);
@ -86,6 +90,8 @@ static void test_audio_pipeline_free_sheduler_task_free(void **state)
cleanup_test_data(test_data);
result.source_comp = test_data->first;
/*Testing component*/
pipeline_free(&result);
@ -94,51 +100,7 @@ static void test_audio_pipeline_free_sheduler_task_free(void **state)
assert_ptr_equal(NULL, result.pipe_task.func);
}
static void test_audio_pipeline_free_disconnect_upstream_full(void **state)
{
struct pipeline_connect_data *test_data = *state;
struct pipeline result = test_data->p;
cleanup_test_data(test_data);
/*Set pipeline to check that is null later*/
test_data->first->pipeline = &result;
test_data->second->pipeline = &result;
test_data->second->comp.pipeline_id = PIPELINE_ID_SAME;
test_data->first->comp.pipeline_id = PIPELINE_ID_SAME;
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;
/*Testing component*/
pipeline_free(&result);
assert_ptr_equal(NULL, test_data->second->pipeline);
assert_ptr_equal(NULL, test_data->first->pipeline);
}
static void test_audio_pipeline_free_disconnect_upstream_list_delete
(void **state)
{
struct pipeline_connect_data *test_data = *state;
struct pipeline result = test_data->p;
cleanup_test_data(test_data);
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;
/*Testing component*/
pipeline_free(&result);
assert_true(list_is_empty(&test_data->second->bsource_list));
assert_true(list_is_empty(&test_data->first->bsource_list));
}
static void test_audio_pipeline_free_disconnect_downstream_full(void **state)
static void test_audio_pipeline_free_disconnect_full(void **state)
{
struct pipeline_connect_data *test_data = *state;
struct pipeline result = test_data->p;
@ -146,6 +108,7 @@ static void test_audio_pipeline_free_disconnect_downstream_full(void **state)
cleanup_test_data(test_data);
/*Set pipeline to check that is null later*/
result.source_comp = test_data->first;
test_data->first->pipeline = &result;
test_data->second->pipeline = &result;
test_data->second->comp.pipeline_id = PIPELINE_ID_SAME;
@ -162,7 +125,7 @@ static void test_audio_pipeline_free_disconnect_downstream_full(void **state)
assert_ptr_equal(NULL, test_data->first->pipeline);
}
static void test_audio_pipeline_free_disconnect_downstream_list_del
static void test_audio_pipeline_free_disconnect_list_del
(void **state)
{
struct pipeline_connect_data *test_data = *state;
@ -170,6 +133,7 @@ static void test_audio_pipeline_free_disconnect_downstream_list_del
cleanup_test_data(test_data);
result.source_comp = test_data->first;
test_data->b1->source = test_data->first;
list_item_append(&result.sched_comp->bsink_list,
&test_data->b1->source_list);
@ -195,16 +159,10 @@ int main(void)
test_audio_pipeline_free_sheduler_task_free
),
cmocka_unit_test(
test_audio_pipeline_free_disconnect_upstream_full
test_audio_pipeline_free_disconnect_full
),
cmocka_unit_test(
test_audio_pipeline_free_disconnect_upstream_list_delete
),
cmocka_unit_test(
test_audio_pipeline_free_disconnect_downstream_full
),
cmocka_unit_test(
test_audio_pipeline_free_disconnect_downstream_list_del
test_audio_pipeline_free_disconnect_list_del
),
};

View File

@ -72,19 +72,6 @@ static void test_audio_pipeline_pipeline_new_creation(void **state)
assert_non_null(result);
}
static void test_audio_pipeline_new_list_initialization(void **state)
{
struct pipeline_new_setup_data *test_data = *state;
/*Testing component*/
struct pipeline *result = pipeline_new(&test_data->ipc_data,
test_data->comp_data);
/*Check list initialization*/
assert_ptr_equal(&result->comp_list, result->comp_list.next);
assert_ptr_equal(&result->buffer_list, result->buffer_list.next);
}
static void test_audio_pipeline_new_sheduler_init(void **state)
{
struct pipeline_new_setup_data *test_data = *state;
@ -131,7 +118,6 @@ int main(void)
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_audio_pipeline_pipeline_new_creation),
cmocka_unit_test(test_audio_pipeline_new_list_initialization),
cmocka_unit_test(test_audio_pipeline_new_sheduler_init),
cmocka_unit_test(test_audio_pipeline_new_sheduler_config),
cmocka_unit_test(test_audio_pipeline_new_ipc_data_coppy),