Skip to content

Commit 4e84092

Browse files
committed
firmware: arm_ffa: Add support for handling notification pending interrupt(NPI)
JIRA: https://issues.redhat.com/browse/RHEL-102691 commit 08530a2 Author: Jens Wiklander <jens.wiklander@linaro.org> Date: Thu, 11 Apr 2024 13:57:34 +0100 The FF-A uses the notification pending interrupt to inform the receiver that it has a pending notification. This is a virtual interrupt and is used by the following type of receivers: 1. A guest/VM running under a hypervisor. 2. An S-EL1 SP running under a S-EL2 SPMC. The rules that govern the properties of the NPI are the same as the rules for the SRI with couple of exceptions. Both SRI and NPI can be supported simultaneously. The handling of NPI is also same as the handling of notification for the self/primary VM with ID 0 except the absence of global notification. Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org> Link: https://lore.kernel.org/r/20240411-ffa_npi_support-v2-3-927a670254e6@arm.com Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Marcin Juszkiewicz <mjuszkiewicz@redhat.com>
1 parent a321db0 commit 4e84092

File tree

1 file changed

+55
-16
lines changed

1 file changed

+55
-16
lines changed

drivers/firmware/arm_ffa/driver.c

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ struct ffa_drv_info {
101101
bool bitmap_created;
102102
bool notif_enabled;
103103
unsigned int sched_recv_irq;
104+
unsigned int notif_pend_irq;
104105
unsigned int cpuhp_state;
105106
struct ffa_pcpu_irq __percpu *irq_pcpu;
106107
struct workqueue_struct *notif_pcpu_wq;
@@ -1301,6 +1302,15 @@ static irqreturn_t ffa_sched_recv_irq_handler(int irq, void *irq_data)
13011302
return IRQ_HANDLED;
13021303
}
13031304

1305+
static irqreturn_t notif_pend_irq_handler(int irq, void *irq_data)
1306+
{
1307+
struct ffa_pcpu_irq *pcpu = irq_data;
1308+
1309+
ffa_self_notif_handle(smp_processor_id(), true, pcpu->info);
1310+
1311+
return IRQ_HANDLED;
1312+
}
1313+
13041314
static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
13051315
{
13061316
ffa_notification_info_get();
@@ -1364,13 +1374,19 @@ static void ffa_irq_unmap(unsigned int irq)
13641374

13651375
static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
13661376
{
1367-
enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE);
1377+
if (drv_info->sched_recv_irq)
1378+
enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE);
1379+
if (drv_info->notif_pend_irq)
1380+
enable_percpu_irq(drv_info->notif_pend_irq, IRQ_TYPE_NONE);
13681381
return 0;
13691382
}
13701383

13711384
static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu)
13721385
{
1373-
disable_percpu_irq(drv_info->sched_recv_irq);
1386+
if (drv_info->sched_recv_irq)
1387+
disable_percpu_irq(drv_info->sched_recv_irq);
1388+
if (drv_info->notif_pend_irq)
1389+
disable_percpu_irq(drv_info->notif_pend_irq);
13741390
return 0;
13751391
}
13761392

@@ -1389,13 +1405,16 @@ static void ffa_uninit_pcpu_irq(void)
13891405
if (drv_info->sched_recv_irq)
13901406
free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu);
13911407

1408+
if (drv_info->notif_pend_irq)
1409+
free_percpu_irq(drv_info->notif_pend_irq, drv_info->irq_pcpu);
1410+
13921411
if (drv_info->irq_pcpu) {
13931412
free_percpu(drv_info->irq_pcpu);
13941413
drv_info->irq_pcpu = NULL;
13951414
}
13961415
}
13971416

1398-
static int ffa_init_pcpu_irq(unsigned int irq)
1417+
static int ffa_init_pcpu_irq(void)
13991418
{
14001419
struct ffa_pcpu_irq __percpu *irq_pcpu;
14011420
int ret, cpu;
@@ -1409,11 +1428,26 @@ static int ffa_init_pcpu_irq(unsigned int irq)
14091428

14101429
drv_info->irq_pcpu = irq_pcpu;
14111430

1412-
ret = request_percpu_irq(irq, ffa_sched_recv_irq_handler, "ARM-FFA-SRI",
1413-
irq_pcpu);
1414-
if (ret) {
1415-
pr_err("Error registering notification IRQ %d: %d\n", irq, ret);
1416-
return ret;
1431+
if (drv_info->sched_recv_irq) {
1432+
ret = request_percpu_irq(drv_info->sched_recv_irq,
1433+
ffa_sched_recv_irq_handler,
1434+
"ARM-FFA-SRI", irq_pcpu);
1435+
if (ret) {
1436+
pr_err("Error registering percpu SRI nIRQ %d : %d\n",
1437+
drv_info->sched_recv_irq, ret);
1438+
return ret;
1439+
}
1440+
}
1441+
1442+
if (drv_info->notif_pend_irq) {
1443+
ret = request_percpu_irq(drv_info->notif_pend_irq,
1444+
notif_pend_irq_handler,
1445+
"ARM-FFA-NPI", irq_pcpu);
1446+
if (ret) {
1447+
pr_err("Error registering percpu NPI nIRQ %d : %d\n",
1448+
drv_info->notif_pend_irq, ret);
1449+
return ret;
1450+
}
14171451
}
14181452

14191453
INIT_WORK(&drv_info->sched_recv_irq_work, ffa_sched_recv_irq_work_fn);
@@ -1438,6 +1472,8 @@ static void ffa_notifications_cleanup(void)
14381472
ffa_uninit_pcpu_irq();
14391473
ffa_irq_unmap(drv_info->sched_recv_irq);
14401474
drv_info->sched_recv_irq = 0;
1475+
ffa_irq_unmap(drv_info->notif_pend_irq);
1476+
drv_info->notif_pend_irq = 0;
14411477

14421478
if (drv_info->bitmap_created) {
14431479
ffa_notification_bitmap_destroy();
@@ -1448,7 +1484,7 @@ static void ffa_notifications_cleanup(void)
14481484

14491485
static void ffa_notifications_setup(void)
14501486
{
1451-
int ret, irq;
1487+
int ret;
14521488

14531489
ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL);
14541490
if (!ret) {
@@ -1461,15 +1497,18 @@ static void ffa_notifications_setup(void)
14611497
drv_info->bitmap_created = true;
14621498
}
14631499

1464-
irq = ffa_irq_map(FFA_FEAT_SCHEDULE_RECEIVER_INT);
1465-
if (irq <= 0) {
1466-
ret = irq;
1467-
goto cleanup;
1468-
}
1500+
ret = ffa_irq_map(FFA_FEAT_SCHEDULE_RECEIVER_INT);
1501+
if (ret > 0)
1502+
drv_info->sched_recv_irq = ret;
1503+
1504+
ret = ffa_irq_map(FFA_FEAT_NOTIFICATION_PENDING_INT);
1505+
if (ret > 0)
1506+
drv_info->notif_pend_irq = ret;
14691507

1470-
drv_info->sched_recv_irq = irq;
1508+
if (!drv_info->sched_recv_irq && !drv_info->notif_pend_irq)
1509+
goto cleanup;
14711510

1472-
ret = ffa_init_pcpu_irq(irq);
1511+
ret = ffa_init_pcpu_irq();
14731512
if (ret)
14741513
goto cleanup;
14751514

0 commit comments

Comments
 (0)