summaryrefslogtreecommitdiff
path: root/drivers/firmware/arm_ffa/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware/arm_ffa/driver.c')
-rw-r--r--drivers/firmware/arm_ffa/driver.c47
1 files changed, 28 insertions, 19 deletions
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index a2818b69c8aa..58cc017332c9 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -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;