Skip to content

Commit

Permalink
firmware: arm_ffa: Refactor SRI handling in prepartion to add NPI sup…
Browse files Browse the repository at this point in the history
…port

In preparation to support handling of Notification Pending Interrupt(NPI)
in addition to the existing support for Schedule Receiver Interrupt(SRI),
refactor the code around SRI handling so that NPI support can reuse some
of it. This change shouldn't have any functionality impact. It neither
adds the support for NPIs nor changes any SRI support.

Tested-by: Jens Wiklander <jens.wiklander@linaro.org>
Link: https://lore.kernel.org/r/20240411-ffa_npi_support-v2-2-927a670254e6@arm.com
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
  • Loading branch information
sudeep-holla committed Apr 15, 2024
1 parent 2b9c66d commit f936c24
Showing 1 changed file with 28 additions and 19 deletions.
47 changes: 28 additions & 19 deletions drivers/firmware/arm_ffa/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ struct ffa_drv_info {
struct ffa_pcpu_irq __percpu *irq_pcpu;
struct workqueue_struct *notif_pcpu_wq;
struct work_struct notif_pcpu_work;
struct work_struct irq_work;
struct work_struct sched_recv_irq_work;
struct xarray partition_info;
DECLARE_HASHTABLE(notifier_hash, ilog2(FFA_MAX_NOTIFICATIONS));
struct mutex notify_lock; /* lock to protect notifier hashtable */
Expand Down Expand Up @@ -1291,12 +1291,12 @@ static void ffa_partitions_cleanup(void)
#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2)
#define FFA_FEAT_MANAGED_EXIT_INT (3)

static irqreturn_t irq_handler(int irq, void *irq_data)
static irqreturn_t ffa_sched_recv_irq_handler(int irq, void *irq_data)
{
struct ffa_pcpu_irq *pcpu = irq_data;
struct ffa_drv_info *info = pcpu->info;

queue_work(info->notif_pcpu_wq, &info->irq_work);
queue_work(info->notif_pcpu_wq, &info->sched_recv_irq_work);

return IRQ_HANDLED;
}
Expand All @@ -1306,15 +1306,23 @@ static void ffa_sched_recv_irq_work_fn(struct work_struct *work)
ffa_notification_info_get();
}

static int ffa_sched_recv_irq_map(void)
static int ffa_irq_map(u32 id)
{
int ret, irq, sr_intid;
char *err_str;
int ret, irq, intid;

/* The returned sr_intid is assumed to be SGI donated to NS world */
ret = ffa_features(FFA_FEAT_SCHEDULE_RECEIVER_INT, 0, &sr_intid, NULL);
if (id == FFA_FEAT_NOTIFICATION_PENDING_INT)
err_str = "Notification Pending Interrupt";
else if (id == FFA_FEAT_SCHEDULE_RECEIVER_INT)
err_str = "Schedule Receiver Interrupt";
else
err_str = "Unknown ID";

/* The returned intid is assumed to be SGI donated to NS world */
ret = ffa_features(id, 0, &intid, NULL);
if (ret < 0) {
if (ret != -EOPNOTSUPP)
pr_err("Failed to retrieve scheduler Rx interrupt\n");
pr_err("Failed to retrieve FF-A %s %u\n", err_str, id);
return ret;
}

Expand All @@ -1329,12 +1337,12 @@ static int ffa_sched_recv_irq_map(void)

oirq.np = gic;
oirq.args_count = 1;
oirq.args[0] = sr_intid;
oirq.args[0] = intid;
irq = irq_create_of_mapping(&oirq);
of_node_put(gic);
#ifdef CONFIG_ACPI
} else {
irq = acpi_register_gsi(NULL, sr_intid, ACPI_EDGE_SENSITIVE,
irq = acpi_register_gsi(NULL, intid, ACPI_EDGE_SENSITIVE,
ACPI_ACTIVE_HIGH);
#endif
}
Expand All @@ -1347,12 +1355,11 @@ static int ffa_sched_recv_irq_map(void)
return irq;
}

static void ffa_sched_recv_irq_unmap(void)
static void ffa_irq_unmap(unsigned int irq)
{
if (drv_info->sched_recv_irq) {
irq_dispose_mapping(drv_info->sched_recv_irq);
drv_info->sched_recv_irq = 0;
}
if (!irq)
return;
irq_dispose_mapping(irq);
}

static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu)
Expand Down Expand Up @@ -1402,13 +1409,14 @@ static int ffa_init_pcpu_irq(unsigned int irq)

drv_info->irq_pcpu = irq_pcpu;

ret = request_percpu_irq(irq, irq_handler, "ARM-FFA", irq_pcpu);
ret = request_percpu_irq(irq, ffa_sched_recv_irq_handler, "ARM-FFA-SRI",
irq_pcpu);
if (ret) {
pr_err("Error registering notification IRQ %d: %d\n", irq, ret);
return ret;
}

INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn);
INIT_WORK(&drv_info->sched_recv_irq_work, ffa_sched_recv_irq_work_fn);
INIT_WORK(&drv_info->notif_pcpu_work, notif_pcpu_irq_work_fn);
drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification");
if (!drv_info->notif_pcpu_wq)
Expand All @@ -1428,7 +1436,8 @@ static int ffa_init_pcpu_irq(unsigned int irq)
static void ffa_notifications_cleanup(void)
{
ffa_uninit_pcpu_irq();
ffa_sched_recv_irq_unmap();
ffa_irq_unmap(drv_info->sched_recv_irq);
drv_info->sched_recv_irq = 0;

if (drv_info->bitmap_created) {
ffa_notification_bitmap_destroy();
Expand All @@ -1452,7 +1461,7 @@ static void ffa_notifications_setup(void)
drv_info->bitmap_created = true;
}

irq = ffa_sched_recv_irq_map();
irq = ffa_irq_map(FFA_FEAT_SCHEDULE_RECEIVER_INT);
if (irq <= 0) {
ret = irq;
goto cleanup;
Expand Down

0 comments on commit f936c24

Please sign in to comment.