From f97790a06e40cfb36fbb6af69cc5b34dffa2996c Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Tue, 2 Sep 2025 20:15:01 +0800 Subject: [PATCH] soc: rockchip: aoa_middleware: remove global variables as much as possible to avoid multi-core racing issues Signed-off-by: Xing Zheng Change-Id: If08e2f68a86c61fc94f58371f2b9e78ffbf8fc3c --- drivers/soc/rockchip/aoa_middleware/aoa_drv.c | 6 +- drivers/soc/rockchip/aoa_middleware/aoa_drv.h | 2 +- .../rockchip/aoa_middleware/aoa_middleware.c | 124 +++++++++++++----- .../rockchip/aoa_middleware/aoa_middleware.h | 4 +- .../soc/rockchip/aoa_middleware/lp_rkdma.c | 6 +- .../soc/rockchip/aoa_middleware/lp_rkdma.h | 2 +- 6 files changed, 102 insertions(+), 42 deletions(-) diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_drv.c b/drivers/soc/rockchip/aoa_middleware/aoa_drv.c index aa3dc7ec699d..397e39bf9387 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_drv.c +++ b/drivers/soc/rockchip/aoa_middleware/aoa_drv.c @@ -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; diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_drv.h b/drivers/soc/rockchip/aoa_middleware/aoa_drv.h index 697ad36f28c8..859b582abbc1 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_drv.h +++ b/drivers/soc/rockchip/aoa_middleware/aoa_drv.h @@ -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__ */ diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c index dab1f7697d5e..1e59829f698a 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c +++ b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.c @@ -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; diff --git a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h index 5c51d6028899..a0a4d1aefacb 100644 --- a/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h +++ b/drivers/soc/rockchip/aoa_middleware/aoa_middleware.h @@ -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__ */ diff --git a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c index 2bc1c871d040..5447f792f027 100644 --- a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c +++ b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.c @@ -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) diff --git a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h index e79bcf1d4db5..b439966fcf10 100644 --- a/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h +++ b/drivers/soc/rockchip/aoa_middleware/lp_rkdma.h @@ -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__ */