[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20240703163250.47887-1-shenwei.wang@nxp.com>
Date: Wed, 3 Jul 2024 11:32:50 -0500
From: Shenwei Wang <shenwei.wang@....com>
To: Thomas Gleixner <tglx@...utronix.de>,
Shawn Guo <shawnguo@...nel.org>,
Sascha Hauer <s.hauer@...gutronix.de>
Cc: Pengutronix Kernel Team <kernel@...gutronix.de>,
Fabio Estevam <festevam@...il.com>,
linux-kernel@...r.kernel.org,
imx@...ts.linux.dev,
linux-imx@....com,
Shenwei Wang <shenwei.wang@....com>
Subject: [PATCH] irqchip/imx-irqsteer: Add irq_bus_lock/sync_unlock handlers
Add irq_bus_lock/sync_unlock handlers.
Without these handlers, the power domain is automatically activated during
clk_prepare. However, on certain platforms like i.MX8QM and i.MX8QXP, the
power-on phase may involve sleep function calls, which can lead to random
system dumps during driver probes at system boot.
By adding these handlers, the actual power-on actions are moved to occur
before clk_prepare, thus resolving the system dump issue.
The following is the example of system dump on i.MX8QM MEK.
[ 3.135799] BUG: scheduling while atomic: kworker/u13:1/48/0x00000002
[ 3.142270] Modules linked in:
[ 3.145349] CPU: 0 PID: 48 Comm: kworker/u13:1 Not tainted 6.6.3-lts-next-g5a913c7fc95d #1
[ 3.153616] Hardware name: Freescale i.MX8QM MEK (DT)
[ 3.158678] Workqueue: events_unbound deferred_probe_work_func
[ 3.164529] Call trace:
[ 3.166981] dump_backtrace+0x90/0xe8
[ 3.170652] show_stack+0x18/0x24
[ 3.173971] dump_stack_lvl+0x48/0x60
[ 3.177644] dump_stack+0x18/0x24
[ 3.180964] __schedule_bug+0x54/0x6c
[ 3.184628] __schedule+0x7f0/0xa94
[ 3.188121] schedule+0x5c/0xc4
[ 3.191266] schedule_preempt_disabled+0x24/0x40
[ 3.195887] __mutex_lock.constprop.0+0x2c0/0x540
[ 3.200596] __mutex_lock_slowpath+0x14/0x20
[ 3.204870] mutex_lock+0x48/0x54
[ 3.208189] clk_prepare_lock+0x44/0xa0
[ 3.212040] clk_prepare+0x20/0x44
[ 3.215452] imx_irqsteer_resume+0x28/0xe0
[ 3.219552] pm_generic_runtime_resume+0x2c/0x44
[ 3.224174] __genpd_runtime_resume+0x30/0x80
[ 3.228535] genpd_runtime_resume+0xc8/0x2c0
[ 3.232809] __rpm_callback+0x48/0x1d8
[ 3.236562] rpm_callback+0x6c/0x78
[ 3.240055] rpm_resume+0x490/0x6b4
[ 3.243549] __pm_runtime_resume+0x50/0x94
[ 3.247648] irq_chip_pm_get+0x2c/0xa0
[ 3.251401] __irq_do_set_handler+0x178/0x24c
[ 3.255762] irq_set_chained_handler_and_data+0x60/0xa4
[ 3.260992] mxc_gpio_probe+0x160/0x4b0
[ 3.264840] platform_probe+0x68/0xc8
[ 3.268506] really_probe+0x148/0x2b0
[ 3.272172] __driver_probe_device+0x78/0x12c
[ 3.276536] driver_probe_device+0xd8/0x15c
[ 3.280721] __device_attach_driver+0xb8/0x134
[ 3.285169] bus_for_each_drv+0x88/0xe8
[ 3.289009] __device_attach+0xa0/0x190
[ 3.292849] device_initial_probe+0x14/0x20
[ 3.297036] bus_probe_device+0xac/0xb0
[ 3.300876] deferred_probe_work_func+0x80/0xb8
[ 3.305411] process_one_work+0x138/0x248
[ 3.309427] worker_thread+0x320/0x438
[ 3.313177] kthread+0x110/0x114
[ 3.316409] ret_from_fork+0x10/0x20
Signed-off-by: Shenwei Wang <shenwei.wang@....com>
---
drivers/irqchip/irq-imx-irqsteer.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 20cf7a9e9ece..f81e4ff3aec3 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -36,6 +36,7 @@ struct irqsteer_data {
int channel;
struct irq_domain *domain;
u32 *saved_reg;
+ struct device *dev;
};
static int imx_irqsteer_get_reg_index(struct irqsteer_data *data,
@@ -72,10 +73,26 @@ static void imx_irqsteer_irq_mask(struct irq_data *d)
raw_spin_unlock_irqrestore(&data->lock, flags);
}
+static void imx_irqsteer_irq_bus_lock(struct irq_data *d)
+{
+ struct irqsteer_data *data = d->chip_data;
+
+ pm_runtime_get_sync(data->dev);
+}
+
+static void imx_irqsteer_irq_bus_sync_unlock(struct irq_data *d)
+{
+ struct irqsteer_data *data = d->chip_data;
+
+ pm_runtime_put_autosuspend(data->dev);
+}
+
static const struct irq_chip imx_irqsteer_irq_chip = {
.name = "irqsteer",
.irq_mask = imx_irqsteer_irq_mask,
.irq_unmask = imx_irqsteer_irq_unmask,
+ .irq_bus_lock = imx_irqsteer_irq_bus_lock,
+ .irq_bus_sync_unlock = imx_irqsteer_irq_bus_sync_unlock,
};
static int imx_irqsteer_irq_map(struct irq_domain *h, unsigned int irq,
@@ -150,6 +167,7 @@ static int imx_irqsteer_probe(struct platform_device *pdev)
if (!data)
return -ENOMEM;
+ data->dev = &pdev->dev;
data->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(data->regs)) {
dev_err(&pdev->dev, "failed to initialize reg\n");
--
2.34.1
Powered by blists - more mailing lists