Received: by 2002:a05:7412:518d:b0:e2:908c:2ebd with SMTP id fn13csp403642rdb; Thu, 5 Oct 2023 09:07:38 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEezuy9otnOr/pSow6W2PzxJ61zbHv05qvZx3P8FlDJNy8tbjRXZON2kNBfk5cB/UkhHT6t X-Received: by 2002:a17:902:ec88:b0:1c4:4f01:d18f with SMTP id x8-20020a170902ec8800b001c44f01d18fmr7122803plg.14.1696522057874; Thu, 05 Oct 2023 09:07:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1696522057; cv=none; d=google.com; s=arc-20160816; b=khtE3tTVm1SZYWLORYRusBrYrNPEyFbtZxMUbPU76DOjD5ND2L1lj85CVBphe0zjPz EoyO1d1utZQ10bigbnuNigobqoVMW3ci2i7S848zN1uk9JDjNC4jZ7dnafrs4KHPgMU9 rSD7RjPDsqNcusZFwaqEt7zgAB1pCom27BVh7zWH3NYScKydmUIaQ0b45vm4C4X7ciUZ E/yccwlaK6fcybqfNE4ZJDPrdA5DDuWwllXqpe64aQtU3xm9o0fOdKRJIj0qTLEt7dET 8xmc9cia+FCGJC2BIwnabMEQc7HXLhjJ767REnz/XuDcB7JoVURSHEGOgU6j6y5EWxmf wJcA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from; bh=ubEGYm0fSNWXXAVNSrCwS64/XhIzzKe2PlHQroq6/+c=; fh=iZJRvoZuVJp3Jcg3UWu0imuTLbH0nKChof8pDyzNHj4=; b=qSvwi7eltZtd8OAgdrP6kiKS5aen99Mr6tmlEHQ1IHR37t4LQo9MlXl8NelV0Ua7a+ 0PZmtmvBo+uv/opg5geE8PgdeSJ/jaiwrEyQ1GQTXvf1yiYMyjwz9+MTzHw9ZDLWKYbF MvAKlU45zBdOo1yXIwj6AOFllv4aMg6dIjzNX49WF2oMgjmWpPx0GxACyqKu+thkdGV2 fd5k9P6nQBjGgBwbNLDFp5CUbhijGFUWq0CZDTkybqdO25vc3dPPWQFo2SVB0cVTpF8b K+17oMsXfLFq4Fjc8SWLDGv3R0b8wwIkOmcUuUhm6250qXuNxZO1yIfb7nI3EaYiVwaF +Djw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.35 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from groat.vger.email (groat.vger.email. [23.128.96.35]) by mx.google.com with ESMTPS id d12-20020a170902654c00b001c72476ca30si1680925pln.281.2023.10.05.09.07.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 05 Oct 2023 09:07:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.35 as permitted sender) client-ip=23.128.96.35; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.35 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by groat.vger.email (Postfix) with ESMTP id 19D1083C1F15; Thu, 5 Oct 2023 09:07:04 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at groat.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240117AbjJEQFY (ORCPT + 99 others); Thu, 5 Oct 2023 12:05:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34520 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234632AbjJEQDY (ORCPT ); Thu, 5 Oct 2023 12:03:24 -0400 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 50D719EFA for ; Thu, 5 Oct 2023 07:45:38 -0700 (PDT) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 275C01570; Thu, 5 Oct 2023 07:45:57 -0700 (PDT) Received: from e103737-lin.cambridge.arm.com (e103737-lin.cambridge.arm.com [10.1.197.49]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 719143F641; Thu, 5 Oct 2023 07:45:17 -0700 (PDT) From: Sudeep Holla Date: Thu, 05 Oct 2023 15:45:01 +0100 Subject: [PATCH v4 08/17] firmware: arm_ffa: Initial support for scheduler receiver interrupt MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit Message-Id: <20231005-ffa_v1-1_notif-v4-8-cddd3237809c@arm.com> References: <20231005-ffa_v1-1_notif-v4-0-cddd3237809c@arm.com> In-Reply-To: <20231005-ffa_v1-1_notif-v4-0-cddd3237809c@arm.com> To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Sudeep Holla , Marc Bonnici , Jens Wiklander , Coboy Chen , Lorenzo Pieralisi , Olivier Deprez X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=7668; i=sudeep.holla@arm.com; h=from:subject:message-id; bh=yU+hWtBWbLNiVtAMPUpIWeJRLZY4AERdKc+TThgbkq8=; b=owEBbQKS/ZANAwAIAQBBurwxfuKYAcsmYgBlHsvxPVH0CxF7HA2KS9+I8Bsy1VybqF81R5Ap0 SepshdLeK+JAjMEAAEIAB0WIQS6ceUSBvMeskPdk+EAQbq8MX7imAUCZR7L8QAKCRAAQbq8MX7i mOFID/4yQcSmODzazuTJAo2qCM/wRZ1K9colo9iGkyq2Bvf+QlxB71uQbOiwTIUzecMhAAnawZm mdrYi2an/rCfTkPO3SUUTEeBofdZzw7HmIQ1MaFnmEAMzPg7xa9B+DRZd3u3cdvbk0ixmz3btL9 v7RB4Uf+6/aulhX6sZ6m4PpIP/sarkjLNPg7kIsJsYW1oMeQ9DcgYXVCubSRcamdb+kDH+wdwbc rzCs2/5qXsiCIvNZ7DrchAl8GZztkphtUs/scloQcVP70N/TwaO04rspoOpoiQCBaVvWlNk79mp 2ZhfoEBcb5ekI3kxnTG6ej5tRiU2yd37IqKm4rVUIraF8+LJqKJh72HSeSethCmFK0xiRz1dD+s px0VefwJn52EgylDgmgRn/DF2Y4tRfFnzRrJ38GBsRtswEyKr6JIpjKZ4ytzkzY5gLLLCkFwtIT s6t2xlculC6/zXk8Ftbce+ie/HDOitgPWjL/wvc1mM7UE/aZv7OffunAAvLDCGmwBPyLB/MeTaI 9IBqMCFQPjEx7dQPaDd+zk9sjElWRKBtNRLh68rs6U7JLZcbk4O9ifRmb3hKxDgCqAD7XfAVZPX pSPW2/ij0UD8pC3IeHiO3CdXVLxu+OlVmOcEsI88juRU21Khq11M4Lg7O52PL0Aedtj7kK1j2KL KQoTgS+6nEN3SRA== X-Developer-Key: i=sudeep.holla@arm.com; a=openpgp; fpr=7360A21742ADF5A11767C1C139CFD4755FE2D5B4 X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on groat.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (groat.vger.email [0.0.0.0]); Thu, 05 Oct 2023 09:07:04 -0700 (PDT) The Framework uses the schedule receiver interrupt to inform the receiver’s scheduler that the receiver must be run to handle a pending notification. A receiver’s scheduler can obtain the description of the schedule receiver interrupt by invoking the FFA_FEATURES interface. The delivery of the physical schedule receiver interrupt from the secure state to the non-secure state depends upon the state of the interrupt controller as configured by the hypervisor. The schedule seceiver interrupt is assumed to be a SGI. The Arm GIC specification defines 16 SGIs. It recommends that they are equally divided between the non-secure and secure states. OS like Linux kernel in the non-secure state typically do not have SGIs to spare. The usage of SGIs in the secure state is however limited. It is more likely that software in the Secure world does not use all the SGIs allocated to it. It is recommended that the secure world software donates an unused SGI to the normal world for use as the schedule receiver interrupt. This implies that secure world software must configure the SGI in the GIC as a non-secure interrupt before presenting it to the normal world. Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 186 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 176 insertions(+), 10 deletions(-) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index b1dd8539ab0d..f8d01840f5ec 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -22,15 +22,20 @@ #define DRIVER_NAME "ARM FF-A" #define pr_fmt(fmt) DRIVER_NAME ": " fmt +#include #include #include +#include #include +#include #include #include #include #include +#include #include #include +#include #include #include "common.h" @@ -76,6 +81,10 @@ static inline int ffa_to_linux_errno(int errno) return -EINVAL; } +struct ffa_pcpu_irq { + struct ffa_drv_info *info; +}; + struct ffa_drv_info { u32 version; u16 vm_id; @@ -85,6 +94,11 @@ struct ffa_drv_info { void *tx_buffer; bool mem_ops_native; bool bitmap_created; + unsigned int sched_recv_irq; + unsigned int cpuhp_state; + struct ffa_pcpu_irq __percpu *irq_pcpu; + struct workqueue_struct *notif_pcpu_wq; + struct work_struct irq_work; }; static struct ffa_drv_info *drv_info; @@ -917,34 +931,182 @@ static void ffa_setup_partitions(void) kfree(pbuf); } -static int ffa_notifications_setup(void) +/* FFA FEATURE IDs */ +#define FFA_FEAT_NOTIFICATION_PENDING_INT (1) +#define FFA_FEAT_SCHEDULE_RECEIVER_INT (2) +#define FFA_FEAT_MANAGED_EXIT_INT (3) + +static irqreturn_t irq_handler(int irq, void *irq_data) { - int ret; + struct ffa_pcpu_irq *pcpu = irq_data; + struct ffa_drv_info *info = pcpu->info; - ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL); - if (ret) { - pr_err("Notifications not supported, continuing with it ..\n"); - return 0; + queue_work(info->notif_pcpu_wq, &info->irq_work); + + return IRQ_HANDLED; +} + +static void ffa_sched_recv_irq_work_fn(struct work_struct *work) +{ + ffa_notification_info_get(); +} + +static int ffa_sched_recv_irq_map(void) +{ + int ret, irq, sr_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 (ret < 0) { + if (ret != -EOPNOTSUPP) + pr_err("Failed to retrieve scheduler Rx interrupt\n"); + return ret; } - ret = ffa_notification_bitmap_create(); + if (acpi_disabled) { + struct of_phandle_args oirq = {}; + struct device_node *gic; + + /* Only GICv3 supported currently with the device tree */ + gic = of_find_compatible_node(NULL, NULL, "arm,gic-v3"); + if (!gic) + return -ENXIO; + + oirq.np = gic; + oirq.args_count = 1; + oirq.args[0] = sr_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, + ACPI_ACTIVE_HIGH); +#endif + } + + if (irq <= 0) { + pr_err("Failed to create IRQ mapping!\n"); + return -ENODATA; + } + + return irq; +} + +static void ffa_sched_recv_irq_unmap(void) +{ + if (drv_info->sched_recv_irq) + irq_dispose_mapping(drv_info->sched_recv_irq); +} + +static int ffa_cpuhp_pcpu_irq_enable(unsigned int cpu) +{ + enable_percpu_irq(drv_info->sched_recv_irq, IRQ_TYPE_NONE); + return 0; +} + +static int ffa_cpuhp_pcpu_irq_disable(unsigned int cpu) +{ + disable_percpu_irq(drv_info->sched_recv_irq); + return 0; +} + +static void ffa_uninit_pcpu_irq(void) +{ + if (drv_info->cpuhp_state) + cpuhp_remove_state(drv_info->cpuhp_state); + + if (drv_info->notif_pcpu_wq) + destroy_workqueue(drv_info->notif_pcpu_wq); + + if (drv_info->sched_recv_irq) + free_percpu_irq(drv_info->sched_recv_irq, drv_info->irq_pcpu); + + if (drv_info->irq_pcpu) + free_percpu(drv_info->irq_pcpu); +} + +static int ffa_init_pcpu_irq(unsigned int irq) +{ + struct ffa_pcpu_irq __percpu *irq_pcpu; + int ret, cpu; + + irq_pcpu = alloc_percpu(struct ffa_pcpu_irq); + if (!irq_pcpu) + return -ENOMEM; + + for_each_present_cpu(cpu) + per_cpu_ptr(irq_pcpu, cpu)->info = drv_info; + + drv_info->irq_pcpu = irq_pcpu; + + ret = request_percpu_irq(irq, irq_handler, "ARM-FFA", irq_pcpu); if (ret) { - pr_err("notification_bitmap_create error %d\n", ret); + pr_err("Error registering notification IRQ %d: %d\n", irq, ret); return ret; } - drv_info->bitmap_created = true; + INIT_WORK(&drv_info->irq_work, ffa_sched_recv_irq_work_fn); + drv_info->notif_pcpu_wq = create_workqueue("ffa_pcpu_irq_notification"); + if (!drv_info->notif_pcpu_wq) + return -EINVAL; + + ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "ffa/pcpu-irq:starting", + ffa_cpuhp_pcpu_irq_enable, + ffa_cpuhp_pcpu_irq_disable); + + if (ret < 0) + return ret; + + drv_info->cpuhp_state = ret; return 0; } static void ffa_notifications_cleanup(void) { + ffa_uninit_pcpu_irq(); + ffa_sched_recv_irq_unmap(); + if (drv_info->bitmap_created) { ffa_notification_bitmap_destroy(); drv_info->bitmap_created = false; } } +static int ffa_notifications_setup(void) +{ + int ret, irq; + + ret = ffa_features(FFA_NOTIFICATION_BITMAP_CREATE, 0, NULL, NULL); + if (ret) { + pr_err("Notifications not supported, continuing with it ..\n"); + return 0; + } + + ret = ffa_notification_bitmap_create(); + if (ret) { + pr_err("notification_bitmap_create error %d\n", ret); + return ret; + } + drv_info->bitmap_created = true; + + irq = ffa_sched_recv_irq_map(); + if (irq <= 0) { + ret = irq; + goto cleanup; + } + + drv_info->sched_recv_irq = irq; + + ret = ffa_init_pcpu_irq(irq); + if (ret) + goto cleanup; + + return 0; +cleanup: + ffa_notifications_cleanup(); + return ret; +} + static int __init ffa_init(void) { int ret; @@ -1000,7 +1162,11 @@ static int __init ffa_init(void) ffa_set_up_mem_ops_native_flag(); - return ffa_notifications_setup(); + ret = ffa_notifications_setup(); + if (ret) + goto free_pages; + + return 0; free_pages: if (drv_info->tx_buffer) free_pages_exact(drv_info->tx_buffer, RXTX_BUFFER_SIZE); -- 2.42.0