Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 367
schedule: dma_multi_chan: do not skip tasks for dma_domain scheduler#3803
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -176,6 +176,9 @@ int platform_init(struct sof *sof) | ||
| sof->platform_dma_domain = dma_multi_chan_domain_init | ||
| (&sof->dma_info->dma_array[0], 1, | ||
| PLATFORM_DEFAULT_CLOCK, false); | ||
| /* i.MX platform DMA domain will be full synchronous, no time dependent */ | ||
| sof->platform_dma_domain->full_sync = true; | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like this should be an argument or flag to dma_multi_chan_domain_init() ContributorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you agree to add these changes under, the current, synchronous attribute we won't need to modify the function signature(s). Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lgirdwood so one reason for adding a new mode ( @slawblauciak@keyonjie can you guys have a look as I've seen you've experimented a little bit with scheduling code. Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, I think this is a topology scheduler type now. | ||
| scheduler_init_ll(sof->platform_dma_domain); | ||
| /* initialize the host IPC mechanims */ | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -280,6 +280,7 @@ static bool dma_multi_chan_domain_is_pending(struct ll_schedule_domain *domain, | ||
| struct dma_domain *dma_domain = ll_sch_domain_get_pdata(domain); | ||
| struct pipeline_task *pipe_task = pipeline_task_get(task); | ||
| struct dma *dmas = dma_domain->dma_array; | ||
| struct ll_task_pdata *pdata; | ||
| uint32_t status; | ||
| int i; | ||
| int j; | ||
| @@ -303,11 +304,29 @@ static bool dma_multi_chan_domain_is_pending(struct ll_schedule_domain *domain, | ||
| pipe_task->sched_comp) | ||
| continue; | ||
| /* it's too soon for this task */ | ||
| if (!pipe_task->registrable && | ||
| pipe_task->task.start > | ||
| platform_timer_get_atomic(timer_get())) | ||
| continue; | ||
| /* Schedule task based on the frequency they | ||
| * were configured with, not time (task.start) | ||
| * | ||
| * There are cases when a DMA transfer from a DAI | ||
| * is finished earlier than task.start and, | ||
| * without full_sync mode, this task will not | ||
| * be scheduled | ||
| */ | ||
| if (domain->full_sync) { | ||
iuliana-prodan marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| pdata = ll_sch_get_pdata(&pipe_task->task); | ||
| pdata->skip_cnt++; | ||
| if (pdata->skip_cnt == pdata->ratio) | ||
| pdata->skip_cnt = 0; | ||
| if (pdata->skip_cnt != 0) | ||
| continue; | ||
| } else { | ||
| /* it's too soon for this task */ | ||
| if (!pipe_task->registrable && | ||
| pipe_task->task.start > | ||
| platform_timer_get_atomic(timer_get())) | ||
| continue; | ||
| } | ||
| notifier_event(&dmas[i].chan[j], NOTIFIER_ID_DMA_IRQ, | ||
| NOTIFIER_TARGET_CORE_LOCAL, | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -324,8 +324,11 @@ static int schedule_ll_task(void *data, struct task *task, uint64_t start, | ||
| { | ||
| struct ll_schedule_data *sch = data; | ||
| struct ll_task_pdata *pdata; | ||
| struct ll_task_pdata *reg_pdata; | ||
| struct list_item *tlist; | ||
| struct task *curr_task; | ||
| struct task *registrable_task = NULL; | ||
| struct pipeline_task *pipe_task; | ||
| uint32_t flags; | ||
| int ret = 0; | ||
| @@ -353,6 +356,47 @@ static int schedule_ll_task(void *data, struct task *task, uint64_t start, | ||
| pdata->period = period; | ||
| /* for full synchronous domain, calculate ratio and initialize skip_cnt for task */ | ||
| if (sch->domain->full_sync) { | ||
| pdata->ratio = 1; | ||
| pdata->skip_cnt = (uint16_t)SOF_TASK_SKIP_COUNT; | ||
| /* get the registrable task */ | ||
| list_for_item(tlist, &sch->tasks) { | ||
| curr_task = container_of(tlist, struct task, list); | ||
| pipe_task = pipeline_task_get(curr_task); | ||
| /* registrable task found */ | ||
| if (pipe_task->registrable) { | ||
| registrable_task = curr_task; | ||
| break; | ||
| } | ||
| } | ||
| /* we found a registrable task */ | ||
| if (registrable_task) { | ||
iuliana-prodan marked this conversation as resolved.
Outdated
Uh oh!There was an error while loading. Please reload this page. | ||
| reg_pdata = ll_sch_get_pdata(registrable_task); | ||
| /* update ratio for all tasks */ | ||
| list_for_item(tlist, &sch->tasks) { | ||
| curr_task = container_of(tlist, struct task, list); | ||
| pdata = ll_sch_get_pdata(curr_task); | ||
| /* the assumption is that the registrable | ||
| * task has the smallest period | ||
| */ | ||
| if (pdata->period >= reg_pdata->period) { | ||
| pdata->ratio = period / reg_pdata->period; | ||
| } else { | ||
| tr_err(&ll_tr, | ||
| "schedule_ll_task(): registrable task has a period longer than current task"); | ||
| ret = -EINVAL; | ||
| goto out; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| /* insert task into the list */ | ||
| schedule_ll_task_insert(task, &sch->tasks); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iuliana-prodan the patch looks good to me. I understand the reasons behind it. Is it possible at our current level of understanding to specify what is the difference between synchronous and full_sync?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iuliana-prodan also can you enhance the commit message in order to better describe what is the current problem.
This
is fine.
We need to include in the commit message along the lines the scenario we are using and facing issues:
e.g
In the case we are using a mixer topology there will be 3 pipelines for playback scenario:
Each of these pipelines correspond to a task.
As far as I understood one of the task0 or task1 sometimes starves thus resulting in timeouts on Host.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ack, I'm not fully following the difference between DMA and full sync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dbaluta@lgirdwood The difference is that now, the DMA synchronous is still time dependent: the task->start is used to schedule a task.
The full synchronous is not using the time anymore - is based on the period of each task.
I could have put all these changes on synchronous attribute, but I wanted it to have a small impact on the other targets that use dma_multi_chan domain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here’s an example of the issue we see on imx.
In the case of a mixer topology there will be 3 pipelines for playback scenario:
Task 2 is the registrable task and this is always scheduled.
The other tasks (task 0 and task 1) are scheduled based on task->start.
The problem we see is that, at some point, the DMA transfer from DAI is finished earlier than task->start for one of the task 0 or task 1 and this is not scheduled anymore (based on the check from https://github.com/thesofproject/sof/blob/master/src/schedule/dma_multi_chan_domain.c#L308).
And, task 2 ends up depleting one of the source buffers, thus blocking the entire data flow.
So, task 0 and task 1 should be run at the frequency they were configured with.
@dbaluta I'll add a part of this in the commit message, as you suggested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@iuliana-prodan thanks got you now. Can we have this as scheduling type for topology too as a subsequent PR as it seems something we should be specifying at that level along side the other pipeline scheduling config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lgirdwood I've created #3817 for your proposal. Let's continue the discussion there. Thanks!