From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3EA1CC43602 for ; Mon, 6 Jul 2026 13:45:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id: Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-ID:Date :Subject:To:From:Reply-To:Content-Type:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=gG/WUa/LLyrYEO5dRMckgWvREtz+5RqT0GWLdz37tZU=; b=QxiGfleCwx0HWq j1rdPS653x1vtipIFHUWuoYHxsfRPWKq3sIk0+5HN9gG/Esit9tuMnBGmXleroKBCqKIPrMLFdg8M xyDUSMY7FvX19v5arDTBxo6aUkjs4TQgg7q8vsrlZ9zF80LZ3BAFjIg8mzPv9qv3ycGJ54TeEJcZd LP2aGnsl+ggPLKEUSKG/BQ/9Jov+R6XsXkVZOyHVFN6iSF1vtvcpX1ISj290mYK+HPR3ixbTrEenp kmwWzL++9hOeyNxjNZ3QuBYp1qn+w0P4x1TYeIP/e51/bhqj8zlyvbspuDDe396fchosqIWLKCUt0 QPS3eCC5lnYnGCeCoLiA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wgjdT-0000000Ce9I-022w; Mon, 06 Jul 2026 13:45:23 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wgjdP-0000000Ce6d-27XM for linux-arm-kernel@lists.infradead.org; Mon, 06 Jul 2026 13:45:20 +0000 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 AAA202BCC; Mon, 6 Jul 2026 06:45:13 -0700 (PDT) Received: from e142021.fritz.box (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 7E7623F7B4; Mon, 6 Jul 2026 06:45:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1783345518; bh=POox4qbkE74yIcqXR1VgcDZ11yTazsxmpE95jNPW06o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Qd2peJPrBaTRGpdG5cS0qjKHbOqQqYOpVbm6O/IP21OHVVo5iQBdHIC2CNh6aJebk zc7KKcCvdTHhkyl7o1CIgMvV8lYc4SjdtHUMFJYjQYXQYREUv/Hq2gDcO05NI1zrzN FrHiONVzgkWyct9oPWkWGMv1ldYydVEmCYE5dfeU= From: Andre Przywara To: Mark Rutland , Lorenzo Pieralisi , Sudeep Holla Subject: [PATCH v3 4/8] firmware: smccc: lfa: Register ACPI notification Date: Mon, 6 Jul 2026 15:44:44 +0200 Message-ID: <20260706134455.132091-5-andre.przywara@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260706134455.132091-1-andre.przywara@arm.com> References: <20260706134455.132091-1-andre.przywara@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260706_064519_624437_33B386BA X-CRM114-Status: GOOD ( 20.80 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Conor Dooley , vsethi@nvidia.com, Salman Nabi , Rob Herring , linux-kernel@vger.kernel.org, Varun Wadekar , Trilok Soni , devicetree@vger.kernel.org, Nirmoy Das , Krzysztof Kozlowski , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Vedashree Vidwans The Arm LFA spec describes an ACPI notification mechanism, where the platform (firmware) can notify an LFA client about newly available firmware imag updates ("pending images" in LFA terms). Add a faux device after discovering the existence of an LFA agent via the SMCCC discovery mechnism, and use that device to check for the ACPI notification description. Register this when one is provided. The notification just conveys the fact that at least one firmware image has now a pending update, it doesn't say which, also there could be more than one pending. Loop through all images to find every which needs to be activated, and trigger the activation. We need to do this is a loop, since an activation might change the number and the status of available images. Signed-off-by: Vedashree Vidwans [Andre: convert from platform driver to smccc bus] Signed-off-by: Andre Przywara --- drivers/firmware/smccc/lfa_fw.c | 123 +++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/smccc/lfa_fw.c b/drivers/firmware/smccc/lfa_fw.c index 357e41f95206..5b7f9b07f6c8 100644 --- a/drivers/firmware/smccc/lfa_fw.c +++ b/drivers/firmware/smccc/lfa_fw.c @@ -3,12 +3,14 @@ * Copyright (C) 2025 Arm Limited */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -18,11 +20,13 @@ #include #include #include +#include #include #include #include +#define DRIVER_NAME "ARM_LFA" #undef pr_fmt #define pr_fmt(fmt) "Arm LFA: " fmt @@ -694,6 +698,112 @@ static int update_fw_images_tree(void) return 0; } +/* + * Go through all FW images in a loop and trigger activation + * of all activatible and pending images. + * We have to restart enumeration after every triggered activation, + * since the firmware images might have changed during the activation. + */ +static int activate_pending_image(void) +{ + struct kobject *kobj; + bool found_pending = false; + struct fw_image *image; + int ret; + + spin_lock(&lfa_kset->list_lock); + list_for_each_entry(kobj, &lfa_kset->list, entry) { + image = kobj_to_fw_image(kobj); + + if (image->fw_seq_id == -1) + continue; /* Invalid FW component */ + + update_fw_image_pending(image); + if (image->activation_capable && image->activation_pending) { + found_pending = true; + break; + } + } + spin_unlock(&lfa_kset->list_lock); + + if (!found_pending) + return -ENOENT; + + ret = prime_fw_image(image); + if (ret) + return ret; + + ret = activate_fw_image(image); + if (ret) + return ret; + + pr_info("%s: automatic activation succeeded\n", get_image_name(image)); + + return 0; +} + +#ifdef CONFIG_ACPI +static void lfa_acpi_notify_handler(acpi_handle handle, u32 event, void *data) +{ + int ret; + + while (!(ret = activate_pending_image())) + ; + + if (ret != -ENOENT) + pr_warn("notified image activation failed: %d\n", ret); +} + +static int lfa_register_acpi(struct device *dev) +{ + struct acpi_device *acpi_dev; + acpi_handle handle; + acpi_status status; + + acpi_dev = acpi_dev_get_first_match_dev("ARML0003", NULL, -1); + if (!acpi_dev) + return -ENODEV; + handle = acpi_device_handle(acpi_dev); + if (!handle) { + acpi_dev_put(acpi_dev); + return -ENODEV; + } + + /* Register notify handler that indicates LFA updates are available */ + status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY, + lfa_acpi_notify_handler, NULL); + if (ACPI_FAILURE(status)) { + acpi_dev_put(acpi_dev); + return -EIO; + } + + ACPI_COMPANION_SET(dev, acpi_dev); + + return 0; +} + +static void lfa_remove_acpi(struct device *dev) +{ + struct acpi_device *acpi_dev = ACPI_COMPANION(dev); + acpi_handle handle = acpi_device_handle(acpi_dev); + + if (handle) + acpi_remove_notify_handler(handle, + ACPI_DEVICE_NOTIFY, + lfa_acpi_notify_handler); + acpi_dev_put(acpi_dev); +} +#else /* !CONFIG_ACPI */ +static int lfa_register_acpi(struct device *dev) +{ + return -ENODEV; +} + +static void lfa_remove_acpi(struct device *dev) +{ +} +#endif + static int lfa_smccc_probe(struct arm_smccc_device *sdev) { struct arm_smccc_1_2_regs reg = { 0 }; @@ -730,11 +840,22 @@ static int lfa_smccc_probe(struct arm_smccc_device *sdev) destroy_workqueue(fw_images_update_wq); } - return err; + if (!acpi_disabled) { + err = lfa_register_acpi(&sdev->dev); + if (err != -ENODEV) { + if (!err) + pr_info("registered LFA ACPI notification\n"); + return err; + } + } + + return 0; } static void lfa_smccc_remove(struct arm_smccc_device *sdev) { + if (!acpi_disabled) + lfa_remove_acpi(&sdev->dev); flush_workqueue(fw_images_update_wq); destroy_workqueue(fw_images_update_wq); clean_fw_images_tree(); -- 2.43.0