Re: [PATCH 1/1] firmware: smccc: add support for Live Firmware Activation (LFA)

From: Andre Przywara

Date: Fri Mar 13 2026 - 10:42:47 EST


Hi Nirmoy,

On 3/13/26 10:46, Nirmoy Das wrote:
Hi Salman and Andre,


We found an bug while testing LFA. See below:

On 19.01.26 14:27, Salman Nabi wrote:
The Arm Live Firmware Activation (LFA) is a specification [1] to describe
activating firmware components without a reboot. Those components
(like TF-A's BL31, EDK-II, TF-RMM, secure paylods) would be updated the
usual way: via fwupd, FF-A or other secure storage methods, or via some
IMPDEF Out-Of-Bound method. The user can then activate this new firmware,
at system runtime, without requiring a reboot.
The specification covers the SMCCC interface to list and query available
components and eventually trigger the activation.

[ .... ]

+
+    update_fw_images_tree();
+
+    /*
+     * Removing non-valid image directories at the end of an activation.
+     * We can't remove the sysfs attributes while in the respective
+     * _store() handler, so have to postpone the list removal to a
+     * workqueue.
+     */
+    INIT_WORK(&fw_images_update_work, remove_invalid_fw_images);


This can get invoke multiple times so re-initializing a work item that may already be queued or running

is unsafe. This should be moved to lfa_init() so it is only called once. I suggest:

Ah, good point, thanks for spotting and reporting. Will fold this into the next post!

Cheers,
Andre


diff --git a/drivers/firmware/smccc/lfa_fw.c b/drivers/firmware/smccc/ lfa_fw.c
index 90727a66e49a5..135358113104c 100644
--- a/drivers/firmware/smccc/lfa_fw.c
+++ b/drivers/firmware/smccc/lfa_fw.c
@@ -653,7 +653,6 @@ static int update_fw_images_tree(void)
         * _store() handler, so have to postpone the list removal to a
         * workqueue.
         */
-       INIT_WORK(&fw_images_update_work, remove_invalid_fw_images);
        queue_work(fw_images_update_wq, &fw_images_update_work);

        return 0;
@@ -680,7 +679,7 @@ static void lfa_notify_handler(acpi_handle handle, u32 event, void *data)
         * of all activable and pending images.
         */
        do {
-               /* Reset activable image flag */
+               flush_workqueue(fw_images_update_wq);
                found_activable_image = false;
                list_for_each_entry(attrs, &lfa_fw_images, image_node) {
                        if (attrs->fw_seq_id == -1)
@@ -782,6 +781,8 @@ static int __init lfa_init(void)
                return -ENOMEM;
        }

+       INIT_WORK(&fw_images_update_work, remove_invalid_fw_images);
+
        pr_info("Live Firmware Activation: detected v%ld.%ld\n",
                reg.a0 >> 16, reg.a0 & 0xffff);


Regards,

Nirmoy

+    queue_work(fw_images_update_wq, &fw_images_update_work);
+    mutex_unlock(&lfa_lock);
+
+    return ret;
+}
+