Skip to content

Commit 8849969

Browse files
Dennis YC HsiehJassiBrar
authored andcommitted
mailbox: mediatek: cmdq: clear task in channel before shutdown
Do success callback in channel when shutdown. For those task not finish, callback with error code thus client has chance to cleanup or reset. Signed-off-by: Dennis YC Hsieh <[email protected]> Reviewed-by: CK Hu <[email protected]> Reviewed-by: Bibby Hsieh <[email protected]> Signed-off-by: Jassi Brar <[email protected]>
1 parent bb2b06e commit 8849969

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

drivers/mailbox/mtk-cmdq-mailbox.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,12 @@ static int cmdq_mbox_send_data(struct mbox_chan *chan, void *data)
349349

350350
if (list_empty(&thread->task_busy_list)) {
351351
WARN_ON(clk_enable(cmdq->clock) < 0);
352+
/*
353+
* The thread reset will clear thread related register to 0,
354+
* including pc, end, priority, irq, suspend and enable. Thus
355+
* set CMDQ_THR_ENABLED to CMDQ_THR_ENABLE_TASK will enable
356+
* thread and make it running.
357+
*/
352358
WARN_ON(cmdq_thread_reset(cmdq, thread) < 0);
353359

354360
writel(task->pa_base >> cmdq->shift_pa,
@@ -391,6 +397,38 @@ static int cmdq_mbox_startup(struct mbox_chan *chan)
391397

392398
static void cmdq_mbox_shutdown(struct mbox_chan *chan)
393399
{
400+
struct cmdq_thread *thread = (struct cmdq_thread *)chan->con_priv;
401+
struct cmdq *cmdq = dev_get_drvdata(chan->mbox->dev);
402+
struct cmdq_task *task, *tmp;
403+
unsigned long flags;
404+
405+
spin_lock_irqsave(&thread->chan->lock, flags);
406+
if (list_empty(&thread->task_busy_list))
407+
goto done;
408+
409+
WARN_ON(cmdq_thread_suspend(cmdq, thread) < 0);
410+
411+
/* make sure executed tasks have success callback */
412+
cmdq_thread_irq_handler(cmdq, thread);
413+
if (list_empty(&thread->task_busy_list))
414+
goto done;
415+
416+
list_for_each_entry_safe(task, tmp, &thread->task_busy_list,
417+
list_entry) {
418+
cmdq_task_exec_done(task, CMDQ_CB_ERROR);
419+
kfree(task);
420+
}
421+
422+
cmdq_thread_disable(cmdq, thread);
423+
clk_disable(cmdq->clock);
424+
done:
425+
/*
426+
* The thread->task_busy_list empty means thread already disable. The
427+
* cmdq_mbox_send_data() always reset thread which clear disable and
428+
* suspend statue when first pkt send to channel, so there is no need
429+
* to do any operation here, only unlock and leave.
430+
*/
431+
spin_unlock_irqrestore(&thread->chan->lock, flags);
394432
}
395433

396434
static int cmdq_mbox_flush(struct mbox_chan *chan, unsigned long timeout)

0 commit comments

Comments
 (0)