soc: rockchip: aoa_middleware: remove global variables as much as possible to avoid multi-core racing issues

Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
Change-Id: If08e2f68a86c61fc94f58371f2b9e78ffbf8fc3c
This commit is contained in:
Xing Zheng
2025-09-02 20:15:01 +08:00
parent 5806024db1
commit f97790a06e
6 changed files with 102 additions and 42 deletions

View File

@@ -20,6 +20,7 @@ struct rk_aoa_dev {
struct reset_control *rst;
void __iomem *base;
int irq;
void *data;
};
static const struct of_device_id rockchip_aoa_match[] __maybe_unused = {
@@ -36,13 +37,13 @@ static irqreturn_t rockchip_aoa_isr(int irq, void *devid)
writel(st, aoa->base + AOA_AAD_IRQ_ST);
for (s = 1; s < 8; s++) {
if (st & (1 << s))
aoa_middleware_aoa_notifier(s);
aoa_middleware_aoa_notifier(s, aoa->data);
}
return IRQ_HANDLED;
}
int rockchip_aoa_probe(struct platform_device *pdev)
int rockchip_aoa_probe(struct platform_device *pdev, void *data)
{
struct device_node *node = pdev->dev.of_node;
struct rk_aoa_dev *aoa;
@@ -83,6 +84,7 @@ int rockchip_aoa_probe(struct platform_device *pdev)
}
}
aoa->irq = irq;
aoa->data = data;
dev_set_drvdata(&pdev->dev, aoa);
return 0;

View File

@@ -9,7 +9,7 @@
#ifndef __AOA_DRV_H__
#define __AOA_DRV_H__
int rockchip_aoa_probe(struct platform_device *pdev);
int rockchip_aoa_probe(struct platform_device *pdev, void *data);
int rockchip_aoa_remove(struct platform_device *pdev);
#endif /* __AOA_DRV_H__ */

View File

@@ -38,36 +38,60 @@ struct aoa_middleware_devs {
struct platform_device *pdev_aoa;
struct platform_device *pdev_dma;
void *am_d;
struct notify_rkdma *nty_rkdma;
struct notify_ns *nty_ns;
struct miscdevice misc_notifier_aoa;
struct miscdevice misc_notifier_dma;
struct fasync_struct *rk_aoa_fasync_queue;
struct fasync_struct *rk_dma_fasync_queue;
};
static struct fasync_struct *rk_aoa_fasync_queue;
static struct fasync_struct *rk_dma_fasync_queue;
static struct notify_rkdma g_notify;
static struct notify_ns g_dma_ns;
int aoa_middleware_aoa_notifier(s32 status)
int aoa_middleware_aoa_notifier(s32 status, void *data)
{
struct aoa_middleware_devs *amw_d = data;
if (!amw_d) {
pr_err("%s: amw_d pointer is null\n", __func__);
return -EINVAL;
}
/* AOA Notify starting from SIGRTMIN + 1 */
kill_fasync(&rk_aoa_fasync_queue, SIGRTMIN + status, POLL_IN);
kill_fasync(&amw_d->rk_aoa_fasync_queue, SIGRTMIN + status, POLL_IN);
return 0;
}
EXPORT_SYMBOL(aoa_middleware_aoa_notifier);
int aoa_middleware_dma_notifier(s32 dma_count)
int aoa_middleware_dma_notifier(s32 dma_count, void *data)
{
struct notify_rkdma *n_rkdma = &g_notify;
struct notify_ns *n_ns = &g_dma_ns;
struct aoa_middleware_devs *amw_d = data;
struct notify_rkdma *n_rkdma;
struct notify_ns *n_ns;
struct timespec64 ts;
s32 delta_id;
if (!amw_d) {
pr_err("%s: amw_d pointer is null\n", __func__);
return -EINVAL;
}
if (!amw_d->nty_rkdma) {
pr_err("%s: nty_rkdma pointer is null\n", __func__);
return -EINVAL;
}
if (!amw_d->nty_ns) {
pr_err("%s: nty_ns pointer is null\n", __func__);
return -EINVAL;
}
n_rkdma = amw_d->nty_rkdma;
n_ns = amw_d->nty_ns;
ktime_get_boottime_ts64(&ts);
n_ns->ns = timespec64_to_ns(&ts);
kill_fasync(&rk_dma_fasync_queue, SIGRTMIN + 0, POLL_IN);
kill_fasync(&amw_d->rk_dma_fasync_queue, SIGRTMIN + 0, POLL_IN);
/* ns_id: start from 1, range: 0 ~ (periods-1) */
if (dma_count < 0 || dma_count >= n_rkdma->periods) {
pr_err("Invalid dma_count: %d\n", dma_count);
pr_err("Invalid dma_count: %d >= periods: %d\n", dma_count, n_rkdma->periods);
return -EINVAL;
}
dma_count = array_index_nospec(dma_count, n_rkdma->periods);
@@ -98,32 +122,56 @@ int aoa_middleware_dma_notifier(s32 dma_count)
}
EXPORT_SYMBOL(aoa_middleware_dma_notifier);
static int rk_aoa_notifier_open(struct inode *inode, struct file *file)
{
struct miscdevice *misc = file->private_data;
struct aoa_middleware_devs *amw_d = container_of(misc, struct aoa_middleware_devs, misc_notifier_aoa);
file->private_data = amw_d;
return 0;
}
static int rk_aoa_notifier_fasync(int fd, struct file *file, int mode)
{
return fasync_helper(fd, file, mode, &rk_aoa_fasync_queue);
struct aoa_middleware_devs *amw_d = file->private_data;
return fasync_helper(fd, file, mode, &amw_d->rk_aoa_fasync_queue);
}
static const struct file_operations rk_aoa_notifier_fops = {
.owner = THIS_MODULE,
.open = rk_aoa_notifier_open,
.fasync = rk_aoa_notifier_fasync,
};
static struct miscdevice rk_aoa_notifier_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "rk-aoa-notifier",
.fops = &rk_aoa_notifier_fops,
};
static int rk_dma_notifier_open(struct inode *inode, struct file *file)
{
struct miscdevice *misc = file->private_data;
struct aoa_middleware_devs *amw_d = container_of(misc, struct aoa_middleware_devs, misc_notifier_dma);
file->private_data = amw_d;
return 0;
}
static int rk_dma_notifier_fasync(int fd, struct file *file, int mode)
{
return fasync_helper(fd, file, mode, &rk_dma_fasync_queue);
struct aoa_middleware_devs *amw_d = file->private_data;
return fasync_helper(fd, file, mode, &amw_d->rk_dma_fasync_queue);
}
static long rk_dma_notifier_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct notify_rkdma *n_rkdma = &g_notify;
struct aoa_middleware_devs *amw_d = file->private_data;
struct notify_rkdma *n_rkdma;
struct notify_ns n_ns_user;
if (IS_ERR_OR_NULL(amw_d))
return -EINVAL;
if (IS_ERR_OR_NULL(amw_d->nty_rkdma))
return -EINVAL;
n_rkdma = amw_d->nty_rkdma;
switch (cmd) {
case NOTIFY_RKDMA_SET_PERIODS:
n_rkdma->periods = arg;
@@ -154,17 +202,12 @@ static long rk_dma_notifier_ioctl(struct file *file, unsigned int cmd, unsigned
static const struct file_operations rk_dma_notifier_fops = {
.owner = THIS_MODULE,
.open = rk_dma_notifier_open,
.fasync = rk_dma_notifier_fasync,
.compat_ioctl = rk_dma_notifier_ioctl,
.unlocked_ioctl = rk_dma_notifier_ioctl,
};
static struct miscdevice rk_dma_notifier_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "rk-dma-notifier",
.fops = &rk_dma_notifier_fops,
};
static int aoa_middleware_probe(struct platform_device *pdev)
{
struct aoa_middleware_devs *amw_d;
@@ -176,6 +219,12 @@ static int aoa_middleware_probe(struct platform_device *pdev)
amw_d = devm_kzalloc(&pdev->dev, sizeof(*amw_d), GFP_KERNEL);
if (!amw_d)
return -ENOMEM;
amw_d->nty_rkdma = devm_kzalloc(&pdev->dev, sizeof(*amw_d->nty_rkdma), GFP_KERNEL);
if (!amw_d->nty_rkdma)
return -ENOMEM;
amw_d->nty_ns = devm_kzalloc(&pdev->dev, sizeof(*amw_d->nty_ns), GFP_KERNEL);
if (!amw_d->nty_ns)
return -ENOMEM;
amw_d->dev = &pdev->dev;
amw_d->pdev_aoa = NULL;
amw_d->pdev_dma = NULL;
@@ -197,7 +246,7 @@ static int aoa_middleware_probe(struct platform_device *pdev)
goto err_out;
}
ret = rockchip_aoa_probe(pdev_slave);
ret = rockchip_aoa_probe(pdev_slave, (void *)amw_d);
if (ret) {
dev_err(&pdev->dev, "probe rockchip aoa failed: %d\n", ret);
goto err_put_aoa;
@@ -221,7 +270,7 @@ static int aoa_middleware_probe(struct platform_device *pdev)
goto err_unprobe_aoa;
}
ret = lp_rkdma_probe(pdev_slave);
ret = lp_rkdma_probe(pdev_slave, (void *)amw_d);
if (ret) {
dev_err(&pdev->dev, "probe rockchip dma failed: %d\n", ret);
goto err_put_dma;
@@ -240,13 +289,20 @@ static int aoa_middleware_probe(struct platform_device *pdev)
}
amw_d->am_d = am_map;
ret = misc_register(&rk_aoa_notifier_misc);
/* prepare aoa/dma notifiers */
amw_d->misc_notifier_aoa.minor = MISC_DYNAMIC_MINOR;
amw_d->misc_notifier_aoa.name = "rk-aoa-notifier";
amw_d->misc_notifier_aoa.fops = &rk_aoa_notifier_fops;
ret = misc_register(&amw_d->misc_notifier_aoa);
if (ret) {
dev_err(&pdev->dev, "%s: aoa notifier misc register failed (%d)\n", __func__, ret);
goto err_mmap_remove;
}
ret = misc_register(&rk_dma_notifier_misc);
amw_d->misc_notifier_dma.minor = MISC_DYNAMIC_MINOR;
amw_d->misc_notifier_dma.name = "rk-dma-notifier";
amw_d->misc_notifier_dma.fops = &rk_dma_notifier_fops;
ret = misc_register(&amw_d->misc_notifier_dma);
if (ret) {
dev_err(&pdev->dev, "%s: dma notifier misc register failed (%d)\n", __func__, ret);
goto err_unregister_aoa_misc;
@@ -257,7 +313,7 @@ static int aoa_middleware_probe(struct platform_device *pdev)
return 0;
err_unregister_aoa_misc:
misc_deregister(&rk_aoa_notifier_misc);
misc_deregister(&amw_d->misc_notifier_aoa);
err_mmap_remove:
if (amw_d->am_d) {
aoa_mmap_remove(pdev, amw_d->am_d);
@@ -306,8 +362,8 @@ static int aoa_middleware_remove(struct platform_device *pdev)
aoa_mmap_remove(pdev, amw_d->am_d);
misc_deregister(&rk_dma_notifier_misc);
misc_deregister(&rk_aoa_notifier_misc);
misc_deregister(&amw_d->misc_notifier_aoa);
misc_deregister(&amw_d->misc_notifier_dma);
dev_info(&pdev->dev, "%s: all aoa middlewares are unregistered\n", __func__);
return 0;

View File

@@ -9,7 +9,7 @@
#ifndef __AOA_MIDDLEWARE_H__
#define __AOA_MIDDLEWARE_H__
int aoa_middleware_aoa_notifier(s32 status);
int aoa_middleware_dma_notifier(s32 dma_count);
int aoa_middleware_aoa_notifier(s32 status, void *data);
int aoa_middleware_dma_notifier(s32 dma_count, void *data);
#endif /* __AOA_MIDDLEWARE_H__ */

View File

@@ -102,6 +102,7 @@ struct lp_rkdma_dev {
u32 dma_channels;
u32 dma_requests;
u32 version;
void *data;
};
static int lp_rkdma_init(struct lp_rkdma_dev *d)
@@ -142,7 +143,7 @@ static irqreturn_t lp_rkdma_irq_handler(int irq, void *dev_id)
u64 is = 0, is_raw = 0;
u32 i = 0;
aoa_middleware_dma_notifier(readl(RK_DMA_LCH_LLI_CNT));
aoa_middleware_dma_notifier(readl(RK_DMA_LCH_LLI_CNT), d->data);
is = readq(RK_DMA_CMN_IS0);
is_raw = is;
@@ -158,7 +159,7 @@ static irqreturn_t lp_rkdma_irq_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
int lp_rkdma_probe(struct platform_device *pdev)
int lp_rkdma_probe(struct platform_device *pdev, void *data)
{
struct lp_rkdma_dev *d;
struct resource *res;
@@ -218,6 +219,7 @@ int lp_rkdma_probe(struct platform_device *pdev)
l->id = i;
l->base = RK_DMA_LCHn_REG(i, 0);
}
d->data = data;
ret = request_irq(d->irq, lp_rkdma_irq_handler, 0, dev_name(&pdev->dev), d);
if (ret)

View File

@@ -9,7 +9,7 @@
#ifndef __LP_RKDMA_H__
#define __LP_RKDMA_H__
int lp_rkdma_probe(struct platform_device *pdev);
int lp_rkdma_probe(struct platform_device *pdev, void *data);
int lp_rkdma_remove(struct platform_device *pdev);
#endif /* __LP_RKDMA_H__ */