* [PATCH] firmware: maintain a firmware list
@ 2026-07-15 13:13 Corentin Labbe
2026-07-15 17:23 ` Danilo Krummrich
0 siblings, 1 reply; 3+ messages in thread
From: Corentin Labbe @ 2026-07-15 13:13 UTC (permalink / raw)
To: dakr, gregkh, mcgrof, rafael, russ.weight; +Cc: linux-kernel, Corentin LABBE
From: Corentin LABBE <clabbe@baylibre.com>
Checking if some firmware is missing need to check dmesg for error message,
and on some machine this information could be lost since dmesg uses a ring buffer.
Having the list of all firmware requests is useful in many situations,
like selecting the minimal list when doing some buildroot config
or reducing the size of linux-firmware on gentoo via saveconfig.
So for letting thoses tasks to be automated easily, it is better to have all
loaded firmware in one place.
This patch adds a debugfs with all firmware that was tried to be loaded and the
result of those actions.
Signed-off-by: Corentin LABBE <clabbe@baylibre.com>
---
Hello
I believe the list could setup more appropriate elsewhere in /sys, but
without idea, I used debugfs.
If you have better idea, let me know it.
Regards
drivers/base/firmware_loader/main.c | 100 ++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 24213a0ea831..786d9b2b096e 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -11,7 +11,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/capability.h>
+#include <linux/debugfs.h>
#include <linux/device.h>
+#include <linux/errname.h>
#include <linux/kernel_read_file.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -35,6 +37,7 @@
#include <linux/syscore_ops.h>
#include <linux/reboot.h>
#include <linux/security.h>
+#include <linux/seq_file.h>
#include <linux/zstd.h>
#include <linux/xz.h>
@@ -48,6 +51,95 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
MODULE_DESCRIPTION("Multi purpose firmware loading support");
MODULE_LICENSE("GPL");
+struct fw_loaded_entry {
+ struct list_head node;
+ const char *driver;
+ const char *fw_name;
+ int result;
+};
+
+static LIST_HEAD(fw_loaded_list);
+static DEFINE_MUTEX(fw_loaded_lock);
+static struct dentry *fw_debugfs_dir;
+
+static void fw_record_request(struct device *device, const char *name, int ret)
+{
+ const char *driver = device ? dev_driver_string(device) : "(none)";
+ struct fw_loaded_entry *entry;
+
+ if (!name || name[0] == '\0')
+ return;
+
+ guard(mutex)(&fw_loaded_lock);
+
+ /* Update in place if we have already seen this request. */
+ list_for_each_entry(entry, &fw_loaded_list, node) {
+ if (!strcmp(entry->driver, driver) &&
+ !strcmp(entry->fw_name, name)) {
+ entry->result = ret;
+ return;
+ }
+ }
+
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return;
+
+ entry->driver = kstrdup(driver, GFP_KERNEL);
+ entry->fw_name = kstrdup(name, GFP_KERNEL);
+ if (!entry->driver || !entry->fw_name) {
+ kfree(entry->driver);
+ kfree(entry->fw_name);
+ kfree(entry);
+ return;
+ }
+
+ entry->result = ret;
+ list_add_tail(&entry->node, &fw_loaded_list);
+}
+
+static int fw_list_show(struct seq_file *m, void *v)
+{
+ struct fw_loaded_entry *entry;
+
+ guard(mutex)(&fw_loaded_lock);
+
+ list_for_each_entry(entry, &fw_loaded_list, node) {
+ const char *name;
+
+ if (entry->result >= 0) {
+ seq_printf(m, "%s %s OK\n",
+ entry->driver, entry->fw_name);
+ continue;
+ }
+
+ name = errname(-entry->result);
+ if (name)
+ seq_printf(m, "%s %s %s\n",
+ entry->driver, entry->fw_name, name);
+ else
+ seq_printf(m, "%s %s %d\n",
+ entry->driver, entry->fw_name, entry->result);
+ }
+
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(fw_list);
+
+static void fw_loaded_list_free(void)
+{
+ struct fw_loaded_entry *entry, *tmp;
+
+ guard(mutex)(&fw_loaded_lock);
+
+ list_for_each_entry_safe(entry, tmp, &fw_loaded_list, node) {
+ list_del(&entry->node);
+ kfree(entry->driver);
+ kfree(entry->fw_name);
+ kfree(entry);
+ }
+}
+
struct firmware_cache {
/* firmware_buf instance will be added into the below list */
spinlock_t lock;
@@ -911,6 +1003,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
fw_log_firmware_info(fw, name, device);
}
+ fw_record_request(device, name, ret);
+
*firmware_p = fw;
return ret;
}
@@ -1727,6 +1821,10 @@ static int __init firmware_class_init(void)
if (ret)
goto out;
+ fw_debugfs_dir = debugfs_create_dir("firmware_loader", NULL);
+ debugfs_create_file("firmware_list", 0444, fw_debugfs_dir, NULL,
+ &fw_list_fops);
+
return register_sysfs_loader();
out:
@@ -1739,6 +1837,8 @@ static void __exit firmware_class_exit(void)
unregister_fw_pm_ops();
unregister_reboot_notifier(&fw_shutdown_nb);
unregister_sysfs_loader();
+ debugfs_remove_recursive(fw_debugfs_dir);
+ fw_loaded_list_free();
}
fs_initcall(firmware_class_init);
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] firmware: maintain a firmware list
2026-07-15 13:13 [PATCH] firmware: maintain a firmware list Corentin Labbe
@ 2026-07-15 17:23 ` Danilo Krummrich
2026-07-16 9:29 ` Corentin LABBE
0 siblings, 1 reply; 3+ messages in thread
From: Danilo Krummrich @ 2026-07-15 17:23 UTC (permalink / raw)
To: Corentin Labbe
Cc: gregkh, mcgrof, rafael, russ.weight, linux-kernel, driver-core
(Cc: driver-core; please make sure to Cc all relevant mailing lists)
On Wed Jul 15, 2026 at 3:13 PM CEST, Corentin Labbe wrote:
> From: Corentin LABBE <clabbe@baylibre.com>
>
> Checking if some firmware is missing need to check dmesg for error message,
> and on some machine this information could be lost since dmesg uses a ring buffer.
> Having the list of all firmware requests is useful in many situations,
> like selecting the minimal list when doing some buildroot config
> or reducing the size of linux-firmware on gentoo via saveconfig.
The proposed implementation aside, I don't see why this needs a new kernel
interface.
- Why can't you use 'modinfo -F firmware' for all compiled modules?
- Don't you have a journal persisting the dmesg logs?
- Why can't you use kprobe_event on the kernel command line if you really need
a runtime trace?
Untested, but something like
kprobe_event=p:fw_req,_request_firmware,name=+0(%si):string
should work I think.
Thanks,
Danilo
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] firmware: maintain a firmware list
2026-07-15 17:23 ` Danilo Krummrich
@ 2026-07-16 9:29 ` Corentin LABBE
0 siblings, 0 replies; 3+ messages in thread
From: Corentin LABBE @ 2026-07-16 9:29 UTC (permalink / raw)
To: Danilo Krummrich
Cc: gregkh, mcgrof, rafael, russ.weight, linux-kernel, driver-core
Le Wed, Jul 15, 2026 at 07:23:25PM +0200, Danilo Krummrich a écrit :
> (Cc: driver-core; please make sure to Cc all relevant mailing lists)
>
> On Wed Jul 15, 2026 at 3:13 PM CEST, Corentin Labbe wrote:
> > From: Corentin LABBE <clabbe@baylibre.com>
> >
> > Checking if some firmware is missing need to check dmesg for error message,
> > and on some machine this information could be lost since dmesg uses a ring buffer.
> > Having the list of all firmware requests is useful in many situations,
> > like selecting the minimal list when doing some buildroot config
> > or reducing the size of linux-firmware on gentoo via saveconfig.
>
> The proposed implementation aside, I don't see why this needs a new kernel
> interface.
Hello
You miss the point that I propose an easy way to know.
All your proposals imply scripting, grepping in difference place.
I propose a unique easy way to know the list, without any requirement
>
> - Why can't you use 'modinfo -F firmware' for all compiled modules?
Because it display all possible firmware for each module, I want only required/tried module for the host system
> - Don't you have a journal persisting the dmesg logs?
>
I propose something that work with embeded devices without storage and/or without syslog/journald.
> - Why can't you use kprobe_event on the kernel command line if you really need
> a runtime trace?
>
> Untested, but something like
>
> kprobe_event=p:fw_req,_request_firmware,name=+0(%si):string
>
> should work I think.
This imply command line hacking, something I prefer to avoid, it is better when it just works without change.
Thanks
Regards
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-16 9:29 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-15 13:13 [PATCH] firmware: maintain a firmware list Corentin Labbe
2026-07-15 17:23 ` Danilo Krummrich
2026-07-16 9:29 ` Corentin LABBE
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.