Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firmware: imx: scu-irq: fix RCU complaint after M4 partition reset

Use blocking_notifier_chain instead of atomic_notifier_chain, otherwise
there will be RCU complaint, because unregister/register_virtio_device()
will issue mbox message.

mbox_send_message() is blocking again after received M4 partition reset.

Actually, no need atomic notifier for scu irq notification since this
notifier is called in worker instead of interrupt handler.

[ 389.706645] i2c-rpmsg virtio0.rpmsg-i2c-channel.-1.2: i2c rpmsg driver is removed
[ 389.767362] Wait for remote ready timeout, use first_notify.
[ 389.774084] ------------[ cut here ]------------
[ 389.778729] WARNING: CPU: 0 PID: 397 at kernel/rcu/tree_plugin.h:293 rcu_note_context_switch+0x34/0x338
[ 389.788131] Modules linked in:
[ 389.791195] CPU: 0 PID: 397 Comm: kworker/0:13 Not tainted 5.4.0-rc5-02977-g08f78722f07b #26
[ 389.799633] Hardware name: Freescale i.MX8DXL MEK (DT)
[ 389.805481] Workqueue: events imx_scu_irq_work_handler

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
Reviewed-by: Dong Aisheng <aisheng.dong@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>

authored by

Robin Gong and committed by
Shawn Guo
19a72e0c 8314aa8a

+4 -4
+4 -4
drivers/firmware/imx/imx-scu-irq.c
··· 42 42 43 43 static struct imx_sc_ipc *imx_sc_irq_ipc_handle; 44 44 static struct work_struct imx_sc_irq_work; 45 - static ATOMIC_NOTIFIER_HEAD(imx_scu_irq_notifier_chain); 45 + static BLOCKING_NOTIFIER_HEAD(imx_scu_irq_notifier_chain); 46 46 47 47 int imx_scu_irq_register_notifier(struct notifier_block *nb) 48 48 { 49 - return atomic_notifier_chain_register( 49 + return blocking_notifier_chain_register( 50 50 &imx_scu_irq_notifier_chain, nb); 51 51 } 52 52 EXPORT_SYMBOL(imx_scu_irq_register_notifier); 53 53 54 54 int imx_scu_irq_unregister_notifier(struct notifier_block *nb) 55 55 { 56 - return atomic_notifier_chain_unregister( 56 + return blocking_notifier_chain_unregister( 57 57 &imx_scu_irq_notifier_chain, nb); 58 58 } 59 59 EXPORT_SYMBOL(imx_scu_irq_unregister_notifier); 60 60 61 61 static int imx_scu_irq_notifier_call_chain(unsigned long status, u8 *group) 62 62 { 63 - return atomic_notifier_call_chain(&imx_scu_irq_notifier_chain, 63 + return blocking_notifier_call_chain(&imx_scu_irq_notifier_chain, 64 64 status, (void *)group); 65 65 } 66 66