Commit f936c242 authored by Sudeep Holla's avatar Sudeep Holla

firmware: arm_ffa: Refactor SRI handling in prepartion to add NPI support

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: default avatarJens Wiklander <jens.wiklander@linaro.org>
Link: https://lore.kernel.org/r/20240411-ffa_npi_support-v2-2-927a670254e6@arm.comSigned-off-by: default avatarSudeep Holla <sudeep.holla@arm.com>
parent 2b9c66d1
......@@ -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 */
......@@ -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;
}
......@@ -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;
}
......@@ -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
}
......@@ -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)
......@@ -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)
......@@ -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();
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment