mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
remoteproc: stm32: use workqueue to treat mailbox callback
The mailbox callback is under interrupt context. A consequence is that RPMsg Callbacks are also in interrupt context. Create workqueue to treat the callbacks in normal context. Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
parent
99cf0361e7
commit
714cf5e384
1 changed files with 33 additions and 5 deletions
|
@ -18,6 +18,7 @@
|
||||||
#include <linux/regmap.h>
|
#include <linux/regmap.h>
|
||||||
#include <linux/remoteproc.h>
|
#include <linux/remoteproc.h>
|
||||||
#include <linux/reset.h>
|
#include <linux/reset.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
#include "remoteproc_internal.h"
|
#include "remoteproc_internal.h"
|
||||||
|
|
||||||
|
@ -31,7 +32,9 @@
|
||||||
#define STM32_SMC_REG_WRITE 0x1
|
#define STM32_SMC_REG_WRITE 0x1
|
||||||
|
|
||||||
#define STM32_MBX_VQ0 "vq0"
|
#define STM32_MBX_VQ0 "vq0"
|
||||||
|
#define STM32_MBX_VQ0_ID 0
|
||||||
#define STM32_MBX_VQ1 "vq1"
|
#define STM32_MBX_VQ1 "vq1"
|
||||||
|
#define STM32_MBX_VQ1_ID 1
|
||||||
#define STM32_MBX_SHUTDOWN "shutdown"
|
#define STM32_MBX_SHUTDOWN "shutdown"
|
||||||
|
|
||||||
struct stm32_syscon {
|
struct stm32_syscon {
|
||||||
|
@ -58,6 +61,7 @@ struct stm32_mbox {
|
||||||
const unsigned char name[10];
|
const unsigned char name[10];
|
||||||
struct mbox_chan *chan;
|
struct mbox_chan *chan;
|
||||||
struct mbox_client client;
|
struct mbox_client client;
|
||||||
|
struct work_struct vq_work;
|
||||||
int vq_id;
|
int vq_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -68,6 +72,7 @@ struct stm32_rproc {
|
||||||
u32 nb_rmems;
|
u32 nb_rmems;
|
||||||
struct stm32_rproc_mem *rmems;
|
struct stm32_rproc_mem *rmems;
|
||||||
struct stm32_mbox mb[MBOX_NB_MBX];
|
struct stm32_mbox mb[MBOX_NB_MBX];
|
||||||
|
struct workqueue_struct *workqueue;
|
||||||
bool secured_soc;
|
bool secured_soc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -261,13 +266,22 @@ static irqreturn_t stm32_rproc_wdg(int irq, void *data)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stm32_rproc_mb_vq_work(struct work_struct *work)
|
||||||
|
{
|
||||||
|
struct stm32_mbox *mb = container_of(work, struct stm32_mbox, vq_work);
|
||||||
|
struct rproc *rproc = dev_get_drvdata(mb->client.dev);
|
||||||
|
|
||||||
|
if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
|
||||||
|
dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data)
|
static void stm32_rproc_mb_callback(struct mbox_client *cl, void *data)
|
||||||
{
|
{
|
||||||
struct rproc *rproc = dev_get_drvdata(cl->dev);
|
struct rproc *rproc = dev_get_drvdata(cl->dev);
|
||||||
struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client);
|
struct stm32_mbox *mb = container_of(cl, struct stm32_mbox, client);
|
||||||
|
struct stm32_rproc *ddata = rproc->priv;
|
||||||
|
|
||||||
if (rproc_vq_interrupt(rproc, mb->vq_id) == IRQ_NONE)
|
queue_work(ddata->workqueue, &mb->vq_work);
|
||||||
dev_dbg(&rproc->dev, "no message found in vq%d\n", mb->vq_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stm32_rproc_free_mbox(struct rproc *rproc)
|
static void stm32_rproc_free_mbox(struct rproc *rproc)
|
||||||
|
@ -285,7 +299,7 @@ static void stm32_rproc_free_mbox(struct rproc *rproc)
|
||||||
static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = {
|
static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = {
|
||||||
{
|
{
|
||||||
.name = STM32_MBX_VQ0,
|
.name = STM32_MBX_VQ0,
|
||||||
.vq_id = 0,
|
.vq_id = STM32_MBX_VQ0_ID,
|
||||||
.client = {
|
.client = {
|
||||||
.rx_callback = stm32_rproc_mb_callback,
|
.rx_callback = stm32_rproc_mb_callback,
|
||||||
.tx_block = false,
|
.tx_block = false,
|
||||||
|
@ -293,7 +307,7 @@ static const struct stm32_mbox stm32_rproc_mbox[MBOX_NB_MBX] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = STM32_MBX_VQ1,
|
.name = STM32_MBX_VQ1,
|
||||||
.vq_id = 1,
|
.vq_id = STM32_MBX_VQ1_ID,
|
||||||
.client = {
|
.client = {
|
||||||
.rx_callback = stm32_rproc_mb_callback,
|
.rx_callback = stm32_rproc_mb_callback,
|
||||||
.tx_block = false,
|
.tx_block = false,
|
||||||
|
@ -332,6 +346,10 @@ static void stm32_rproc_request_mbox(struct rproc *rproc)
|
||||||
dev_warn(dev, "cannot get %s mbox\n", name);
|
dev_warn(dev, "cannot get %s mbox\n", name);
|
||||||
ddata->mb[i].chan = NULL;
|
ddata->mb[i].chan = NULL;
|
||||||
}
|
}
|
||||||
|
if (ddata->mb[i].vq_id >= 0) {
|
||||||
|
INIT_WORK(&ddata->mb[i].vq_work,
|
||||||
|
stm32_rproc_mb_vq_work);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -589,12 +607,18 @@ static int stm32_rproc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
rproc->has_iommu = false;
|
rproc->has_iommu = false;
|
||||||
ddata = rproc->priv;
|
ddata = rproc->priv;
|
||||||
|
ddata->workqueue = create_workqueue(dev_name(dev));
|
||||||
|
if (!ddata->workqueue) {
|
||||||
|
dev_err(dev, "cannot create workqueue\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto free_rproc;
|
||||||
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, rproc);
|
platform_set_drvdata(pdev, rproc);
|
||||||
|
|
||||||
ret = stm32_rproc_parse_dt(pdev);
|
ret = stm32_rproc_parse_dt(pdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto free_rproc;
|
goto free_wkq;
|
||||||
|
|
||||||
stm32_rproc_request_mbox(rproc);
|
stm32_rproc_request_mbox(rproc);
|
||||||
|
|
||||||
|
@ -606,6 +630,8 @@ static int stm32_rproc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
free_mb:
|
free_mb:
|
||||||
stm32_rproc_free_mbox(rproc);
|
stm32_rproc_free_mbox(rproc);
|
||||||
|
free_wkq:
|
||||||
|
destroy_workqueue(ddata->workqueue);
|
||||||
free_rproc:
|
free_rproc:
|
||||||
rproc_free(rproc);
|
rproc_free(rproc);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -614,12 +640,14 @@ free_rproc:
|
||||||
static int stm32_rproc_remove(struct platform_device *pdev)
|
static int stm32_rproc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct rproc *rproc = platform_get_drvdata(pdev);
|
struct rproc *rproc = platform_get_drvdata(pdev);
|
||||||
|
struct stm32_rproc *ddata = rproc->priv;
|
||||||
|
|
||||||
if (atomic_read(&rproc->power) > 0)
|
if (atomic_read(&rproc->power) > 0)
|
||||||
rproc_shutdown(rproc);
|
rproc_shutdown(rproc);
|
||||||
|
|
||||||
rproc_del(rproc);
|
rproc_del(rproc);
|
||||||
stm32_rproc_free_mbox(rproc);
|
stm32_rproc_free_mbox(rproc);
|
||||||
|
destroy_workqueue(ddata->workqueue);
|
||||||
rproc_free(rproc);
|
rproc_free(rproc);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue