]> git.itanic.dy.fi Git - linux-stable/commitdiff
firmware: arm_ffa: Fix FFA notifications cleanup path
authorSudeep Holla <sudeep.holla@arm.com>
Tue, 24 Oct 2023 10:56:20 +0000 (11:56 +0100)
committerSudeep Holla <sudeep.holla@arm.com>
Mon, 13 Nov 2023 11:51:26 +0000 (11:51 +0000)
We allow the FF-A to be initialised successfully even when notification
fails. When the notification fails, ffa_notifications_cleanup() gets
called on the failure path.

However, the driver information about the notifications like the irq,
workqueues and cpu hotplug state for enabling and disabling percpu IRQ
are not cleared. This may result in unexpected behaviour during CPU
hotplug because of percpu IRQ being enabled and disabled or during the
driver removal when ffa_notifications_cleanup() gets executed again.

Fix the FFA notifications cleanup path by clearing all the notification
related driver information.

Link: https://lore.kernel.org/r/20231024-ffa-notification-fixes-v1-4-d552c0ec260d@arm.com
Tested-by: Jens Wiklander <jens.wiklander@linaro.org>
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_ffa/driver.c

index 1724a0cbb2cf9bc1a85dc2ddad81daae26c47baa..49ebdc2775ddc9532e656a8cfb61b5cc7c59e58b 100644 (file)
@@ -1326,8 +1326,10 @@ static int ffa_sched_recv_irq_map(void)
 
 static void ffa_sched_recv_irq_unmap(void)
 {
-       if (drv_info->sched_recv_irq)
+       if (drv_info->sched_recv_irq) {
                irq_dispose_mapping(drv_info->sched_recv_irq);
+               drv_info->sched_recv_irq = 0;
+       }
 }
 
 static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
@@ -1344,17 +1346,23 @@ static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu)
 
 static void ffa_uninit_pcpu_irq(void)
 {
-       if (drv_info->cpuhp_state)
+       if (drv_info->cpuhp_state) {
                cpuhp_remove_state(drv_info->cpuhp_state);
+               drv_info->cpuhp_state = 0;
+       }
 
-       if (drv_info->notif_pcpu_wq)
+       if (drv_info->notif_pcpu_wq) {
                destroy_workqueue(drv_info->notif_pcpu_wq);
+               drv_info->notif_pcpu_wq = NULL;
+       }
 
        if (drv_info->sched_recv_irq)
                free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu);
 
-       if (drv_info->irq_pcpu)
+       if (drv_info->irq_pcpu) {
                free_percpu(drv_info->irq_pcpu);
+               drv_info->irq_pcpu = NULL;
+       }
 }
 
 static int ffa_init_pcpu_irq(unsigned int irq)