Skip to content

Commit 9b5597a

Browse files
author
Sudeep Holla
committed
firmware: arm_ffa: Avoid collapsing NPI work from different CPUs
Notification pending interrupts are registered as per-CPU IRQs, but the driver queues all NPI handling through a single shared work_struct. That allows queue_work_on() calls from different CPUs to collapse onto a single pending work item even though the work function uses the CPU it runs on to fetch and handle per-CPU notifications. Move notif_pcpu_work into the per-CPU ffa_pcpu_irq state and initialize one work item per CPU. This keeps NPI handling independent per CPU and avoids losing notifications when multiple CPUs queue work concurrently. Link: https://patch.msgid.link/20260428-ffa_fixes-v2-3-8595ae450034@kernel.org Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
1 parent 09527e2 commit 9b5597a

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

drivers/firmware/arm_ffa/driver.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ static inline int ffa_to_linux_errno(int errno)
8787

8888
struct ffa_pcpu_irq {
8989
struct ffa_drv_info *info;
90+
struct work_struct notif_pcpu_work;
9091
};
9192

9293
struct ffa_drv_info {
@@ -106,7 +107,6 @@ struct ffa_drv_info {
106107
unsigned int cpuhp_state;
107108
struct ffa_pcpu_irq __percpu *irq_pcpu;
108109
struct workqueue_struct *notif_pcpu_wq;
109-
struct work_struct notif_pcpu_work;
110110
struct work_struct sched_recv_irq_work;
111111
struct xarray partition_info;
112112
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
@@ -1539,8 +1539,9 @@ ffa_self_notif_handle(u16 vcpu, bool is_per_vcpu, void *cb_data)
15391539

15401540
static void notif_pcpu_irq_work_fn(struct work_struct *work)
15411541
{
1542-
struct ffa_drv_info *info = container_of(work, struct ffa_drv_info,
1542+
struct ffa_pcpu_irq *pcpu = container_of(work, struct ffa_pcpu_irq,
15431543
notif_pcpu_work);
1544+
struct ffa_drv_info *info = pcpu->info;
15441545

15451546
ffa_self_notif_handle(smp_processor_id(), true, info);
15461547
}
@@ -1811,7 +1812,7 @@ static irqreturn_t notif_pend_irq_handler(int irq, void *irq_data)
18111812
struct ffa_drv_info *info = pcpu->info;
18121813

18131814
queue_work_on(smp_processor_id(), info->notif_pcpu_wq,
1814-
&info->notif_pcpu_work);
1815+
&pcpu->notif_pcpu_work);
18151816

18161817
return IRQ_HANDLED;
18171818
}
@@ -1928,8 +1929,11 @@ static int ffa_init_pcpu_irq(void)
19281929
if (!irq_pcpu)
19291930
return -ENOMEM;
19301931

1931-
for_each_present_cpu(cpu)
1932+
for_each_present_cpu(cpu) {
19321933
per_cpu_ptr(irq_pcpu, cpu)->info = drv_info;
1934+
INIT_WORK(&per_cpu_ptr(irq_pcpu, cpu)->notif_pcpu_work,
1935+
notif_pcpu_irq_work_fn);
1936+
}
19331937

19341938
drv_info->irq_pcpu = irq_pcpu;
19351939

@@ -1958,7 +1962,6 @@ static int ffa_init_pcpu_irq(void)
19581962
}
19591963

19601964
INIT_WORK(&drv_info->sched_recv_irq_work, ffa_sched_recv_irq_work_fn);
1961-
INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
19621965
drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
19631966
if (!drv_info->notif_pcpu_wq)
19641967
return -EINVAL;

0 commit comments

Comments
 (0)