From f20f7c80fc10e873bb258abf8e5a2bb4d52b4088 Mon Sep 17 00:00:00 2001 From: Sven-Ola Tuecke Date: Fri, 23 Jan 2026 15:15:33 +0100 Subject: [PATCH] Spacemit: copy kernel thread handling from Xunlong/Ky Background: have a non-working rpmsg connection to the realtime CPU kernels that handle e.g. the ADMA required for HDMI audio. Signed-off-by: Sven-Ola Tuecke --- drivers/remoteproc/k1x-rproc.c | 58 ++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/drivers/remoteproc/k1x-rproc.c b/drivers/remoteproc/k1x-rproc.c index ddad600246..fbd7ca8f76 100644 --- a/drivers/remoteproc/k1x-rproc.c +++ b/drivers/remoteproc/k1x-rproc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,8 @@ struct spacemit_mbox { const char name[10]; struct mbox_chan *chan; struct mbox_client client; + struct task_struct *mb_thread; + bool kthread_running; struct completion mb_comp; int vq_id; }; @@ -302,6 +305,29 @@ static struct rproc_ops spacemit_rproc_ops = { .get_boot_addr = spacemit_get_boot_addr, }; +static int __process_theread(void *arg) +{ + int ret; + struct mbox_client *cl = arg; + struct rproc *rproc = dev_get_drvdata(cl->dev); + struct spacemit_mbox *mb = container_of(cl, struct spacemit_mbox, client); + struct sched_param param = {.sched_priority = 0 }; + + mb->kthread_running = true; + ret = sched_setscheduler(current, SCHED_FIFO, ¶m); + set_freezable(); + + do { + try_to_freeze(); + wait_for_completion_timeout(&mb->mb_comp, 10); + if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE) + dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id); + } while (!kthread_should_stop()); + + mb->kthread_running = false; + + return 0; +} static void k1x_rproc_mb_callback(struct mbox_client *cl, void *data) { struct spacemit_mbox *mb = container_of(cl, struct spacemit_mbox, client); @@ -316,9 +342,6 @@ static struct spacemit_mbox k1x_rpoc_mbox[] = { .client = { .rx_callback = k1x_rproc_mb_callback, .tx_block = true, - .tx_done = NULL, - .tx_tout = 500, - .knows_txdone = false, }, }, { @@ -327,10 +350,7 @@ static struct spacemit_mbox k1x_rpoc_mbox[] = { .client = { .rx_callback = k1x_rproc_mb_callback, .tx_block = true, - .tx_done = NULL, - .tx_tout = 500, - .knows_txdone = false, - }, + }, }, }; @@ -687,6 +707,14 @@ static int spacemit_rproc_probe(struct platform_device *pdev) ret = -EINVAL; goto err_1; } + + if (priv->mb[i].vq_id >= 0) { + priv->mb[i].mb_thread = kthread_run(__process_theread, (void *)cl, name); + if (IS_ERR(priv->mb[i].mb_thread)) { + ret = PTR_ERR(priv->mb[i].mb_thread); + goto err_1; + } + } } #ifdef CONFIG_PM_SLEEP @@ -769,6 +797,8 @@ static int spacemit_rproc_probe(struct platform_device *pdev) while (--i >= 0) { if (priv->mb[i].chan) mbox_free_channel(priv->mb[i].chan); + if (priv->mb[i].mb_thread) + kthread_stop(priv->mb[i].mb_thread); } err_0: rproc_free(rproc); @@ -790,9 +820,14 @@ static void k1x_rproc_free_mbox(struct rproc *rproc) static int spacemit_rproc_remove(struct platform_device *pdev) { + int i = 0; struct rproc *rproc = platform_get_drvdata(pdev); struct spacemit_rproc *ddata = rproc->priv; + for (i = 0; i < MAX_MBOX; ++i) + if (ddata->mb[i].kthread_running) + kthread_stop(ddata->mb[i].mb_thread); + rproc_del(rproc); k1x_rproc_free_mbox(rproc); rproc_free(rproc); @@ -825,6 +860,15 @@ static void spacemit_rproc_shutdown(struct platform_device *pdev) rproc = dev_get_drvdata(&pdev->dev); priv = rproc->priv; + + for (i = 0; i < MAX_MBOX; ++i) { + /* release the resource of rt thread */ + if (priv->mb[i].kthread_running) { + if (!frozen((priv->mb[i].mb_thread))) + kthread_stop(priv->mb[i].mb_thread); + } + /* mbox_free_channel(priv->mb[i].chan); */ + } } static struct platform_driver spacemit_rproc_driver = { -- 2.34.1