git: b760436e1381 - stable/13 - firmware(9): extend firmware_get() by a "no warn" flag.

Bjoern A. Zeeb bz at FreeBSD.org
Mon Feb 1 07:22:58 UTC 2021


The branch stable/13 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=b760436e1381bc43368db9252a3da1427c5a4885

commit b760436e1381bc43368db9252a3da1427c5a4885
Author:     Bjoern A. Zeeb <bz at FreeBSD.org>
AuthorDate: 2021-01-25 22:41:50 +0000
Commit:     Bjoern A. Zeeb <bz at FreeBSD.org>
CommitDate: 2021-02-01 07:15:29 +0000

    firmware(9): extend firmware_get() by a "no warn" flag.
    
    With the upcoming usage from LinuxKPI but also from drivers
    ported natively we are seeing more probing of various
    firmware (names).
    
    Add the ability to firmware(9) to silence the
    "firmware image loading/registering errors" by adding a new
    firmware_get_flags() functions extending firmware_get() and
    taking a flags argument as firmware_put() already does.
    
    Requested-by:   zeising (for future LinuxKPI/DRM)
    Sponsored-by:   The FreeBSD Foundation
    Sponsored-by:   Rubicon Communications, LLC ("Netgate")
    MFC after:      3 days
    Reviewed-by:    markj
    Differential Revision:  https://reviews.freebsd.org/D27413
    
    (cherry picked from commit 6f65b505468aa8cedc57235604bd8df540d42735)
---
 share/man/man9/firmware.9 | 40 +++++++++++++++++++++++++++++++++-------
 sys/kern/subr_firmware.c  | 45 +++++++++++++++++++++++++++++++--------------
 sys/sys/firmware.h        |  5 +++++
 3 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/share/man/man9/firmware.9 b/share/man/man9/firmware.9
index b0d429573cf6..6d91beb3ddd1 100644
--- a/share/man/man9/firmware.9
+++ b/share/man/man9/firmware.9
@@ -23,13 +23,14 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 14, 2019
+.Dd January 27, 2021
 .Dt FIRMWARE 9
 .Os
 .Sh NAME
 .Nm firmware_register ,
 .Nm firmware_unregister ,
 .Nm firmware_get ,
+.Nm firmware_get_flags ,
 .Nm firmware_put
 .Nd firmware image loading and management
 .Sh SYNOPSIS
@@ -57,6 +58,8 @@ struct firmware {
 .Fn firmware_unregister "const char *imagename"
 .Ft "const struct firmware *"
 .Fn firmware_get "const char *imagename"
+.Ft "const struct firmware *"
+.Fn firmware_get_flags "const char *imagename" "uint32_t flags"
 .Ft void
 .Fn firmware_put "const struct firmware *fp" "int flags"
 .Sh DESCRIPTION
@@ -97,7 +100,13 @@ by calling the function
 .Fn firmware_get
 with the
 .Nm imagename
-they want as an argument.
+they want as an argument, or by calling
+.Fn firmware_get_flags
+with the
+.Nm imagename
+and
+.Nm flags
+they want as an arguments.
 If a matching image is not already registered,
 the firmware subsystem will try to load it using the
 mechanisms specified below (typically, a kernel module
@@ -134,11 +143,22 @@ if there are no pending references to the image, otherwise
 it does not unregister the image and returns EBUSY.
 .Pp
 .Fn firmware_get
-returns the requested firmware image.
+and
+.Fn firmware_get_flags
+return the requested firmware image.
+The
+.Fa flags
+argument may be set to
+.Dv FIRMWARE_GET_NOWARN
+to indicate that errors on firmware load or registration should
+only be logged in case of
+.Nm booverbose .
 If the image is not yet registered with the system,
-the function tries to load it.
+the functions try to load it.
 This involves the linker subsystem and disk access, so
 .Fn firmware_get
+or
+.Fn firmware_get_flags
 must not be called with any locks (except for
 .Va Giant ) .
 Note also that if the firmware image is loaded from a filesystem
@@ -149,9 +169,11 @@ already mounted.
 .Pp
 On success,
 .Fn firmware_get
-returns a pointer to the image description and increases the reference count
+and
+.Fn firmware_get_flags
+return a pointer to the image description and increase the reference count
 for this image.
-On failure, the function returns NULL.
+On failure, the functions return NULL.
 .Pp
 .Fn firmware_put
 drops a reference to a firmware image.
@@ -183,10 +205,12 @@ these images in memory before calling
 .Pp
 When
 .Fn firmware_get
+or
+.Fn firmware_get_flags
 does not find the requested image, it tries to load it using
 one of the available loading mechanisms.
 At the moment, there is only one, namely
-.Nm Loadable kernel modules :
+.Nm Loadable kernel modules .
 .Pp
 A firmware image named
 .Nm foo
@@ -203,6 +227,8 @@ which on most systems defaults to
 Note that in case a module contains multiple images,
 the caller should first request a
 .Fn firmware_get
+or
+.Fn firmware_get_flags
 for the first image contained in the module, followed by requests
 for the other images.
 .Sh BUILDING FIRMWARE LOADABLE MODULES
diff --git a/sys/kern/subr_firmware.c b/sys/kern/subr_firmware.c
index db262c121918..0465f2a88483 100644
--- a/sys/kern/subr_firmware.c
+++ b/sys/kern/subr_firmware.c
@@ -238,36 +238,42 @@ firmware_unregister(const char *imagename)
 	return (err);
 }
 
+struct fw_loadimage {
+	const char	*imagename;
+	uint32_t	flags;
+};
+
 static void
-loadimage(void *arg, int npending)
+loadimage(void *arg, int npending __unused)
 {
-	char *imagename = arg;
+	struct fw_loadimage *fwli = arg;
 	struct priv_fw *fp;
 	linker_file_t result;
 	int error;
 
-	error = linker_reference_module(imagename, NULL, &result);
+	error = linker_reference_module(fwli->imagename, NULL, &result);
 	if (error != 0) {
-		printf("%s: could not load firmware image, error %d\n",
-		    imagename, error);
+		if (bootverbose || (fwli->flags & FIRMWARE_GET_NOWARN) == 0)
+			printf("%s: could not load firmware image, error %d\n",
+			    fwli->imagename, error);
 		mtx_lock(&firmware_mtx);
 		goto done;
 	}
 
 	mtx_lock(&firmware_mtx);
-	fp = lookup(imagename);
+	fp = lookup(fwli->imagename);
 	if (fp == NULL || fp->file != NULL) {
 		mtx_unlock(&firmware_mtx);
 		if (fp == NULL)
 			printf("%s: firmware image loaded, "
-			    "but did not register\n", imagename);
-		(void) linker_release_module(imagename, NULL, NULL);
+			    "but did not register\n", fwli->imagename);
+		(void) linker_release_module(fwli->imagename, NULL, NULL);
 		mtx_lock(&firmware_mtx);
 		goto done;
 	}
 	fp->file = result;	/* record the module identity */
 done:
-	wakeup_one(imagename);
+	wakeup_one(arg);
 	mtx_unlock(&firmware_mtx);
 }
 
@@ -279,7 +285,7 @@ done:
  * release this reference for the image to be eligible for removal/unload.
  */
 const struct firmware *
-firmware_get(const char *imagename)
+firmware_get_flags(const char *imagename, uint32_t flags)
 {
 	struct task fwload_task;
 	struct thread *td;
@@ -306,11 +312,15 @@ firmware_get(const char *imagename)
 	 * Also we must not hold any mtx's over this call which is problematic.
 	 */
 	if (!cold) {
-		TASK_INIT(&fwload_task, 0, loadimage, __DECONST(void *,
-		    imagename));
+		struct fw_loadimage fwli;
+
+		fwli.imagename = imagename;
+		fwli.flags = flags;
+		TASK_INIT(&fwload_task, 0, loadimage, (void *)&fwli);
 		taskqueue_enqueue(firmware_tq, &fwload_task);
-		msleep(__DECONST(void *, imagename), &firmware_mtx, 0,
-		    "fwload", 0);
+		PHOLD(curproc);
+		msleep((void *)&fwli, &firmware_mtx, 0, "fwload", 0);
+		PRELE(curproc);
 	}
 	/*
 	 * After attempting to load the module, see if the image is registered.
@@ -328,6 +338,13 @@ found:				/* common exit point on success */
 	return &fp->fw;
 }
 
+const struct firmware *
+firmware_get(const char *imagename)
+{
+
+	return (firmware_get_flags(imagename, 0));
+}
+
 /*
  * Release a reference to a firmware image returned by firmware_get.
  * The caller may specify, with the FIRMWARE_UNLOAD flag, its desire
diff --git a/sys/sys/firmware.h b/sys/sys/firmware.h
index 8a9b2cf23bd7..0d74a749f4fc 100644
--- a/sys/sys/firmware.h
+++ b/sys/sys/firmware.h
@@ -60,7 +60,12 @@ struct firmware {
 const struct firmware	*firmware_register(const char *,
 	const void *, size_t, unsigned int, const struct firmware *);
 int	 firmware_unregister(const char *);
+
+#define	FIRMWARE_GET_NOWARN	0x0001	/* Do not warn if firmware not found. */
+const struct firmware *firmware_get_flags(const char *, uint32_t flags);
 const struct firmware *firmware_get(const char *);
+
 #define	FIRMWARE_UNLOAD		0x0001	/* unload if unreferenced */
 void		 firmware_put(const struct firmware *, int);
+
 #endif /* _SYS_FIRMWARE_H_ */


More information about the dev-commits-src-all mailing list