git: 1ff77e61c64e - stable/14 - iwlwifi: avoid (hard) hang on loading module

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Mon, 10 Feb 2025 14:52:30 UTC
The branch stable/14 has been updated by bz:

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

commit 1ff77e61c64e80d4532f8433ccdad656e969d62f
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2024-12-08 20:24:10 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-02-10 14:52:07 +0000

    iwlwifi: avoid (hard) hang on loading module
    
    For certain users or chipsets (reports were for CNVi devices but
    we are not sure if this is limited or specific to them) loading
    if_iwlwifi hangs.
    
    The reason for this is that a SYSINIT (module_load_order()) has not
    yet run in this case and the Linux driver tries to load the
    chipsets-specific module.  On FreeBSD all supported sub-modules are
    part of if_iwlwifi so we do not have to load them separately but
    calling into kern_kldload via LinuxKPI request_module while loading
    the module gives us a hard hang.
    
    iwlwifi calls request_module_nowait() so we can simply skip over this
    and continue and the SYSINIT will do the job later if no other
    dependencies fail.
    
    Sponsored by:   The FreeBSD Foundation
    PR:             282789
    Tested by:      Ruslan Makhmatkhanov, Pete Wright
    Differential Revision: https://reviews.freebsd.org/D47994
    
    (cherry picked from commit 87e140a5c6f89eea7ea6320d1ae34566492abfc0)
    (cherry picked from commit 5d09d1070737c43738e433b547af1a90c0f10bf1)
---
 sys/contrib/dev/iwlwifi/iwl-drv.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/sys/contrib/dev/iwlwifi/iwl-drv.c b/sys/contrib/dev/iwlwifi/iwl-drv.c
index 7f4746e5591e..b99204d87283 100644
--- a/sys/contrib/dev/iwlwifi/iwl-drv.c
+++ b/sys/contrib/dev/iwlwifi/iwl-drv.c
@@ -1749,7 +1749,20 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
 			goto out_unbind;
 		}
 	} else {
+#if defined(__linux__)
 		request_module_nowait("%s", op->name);
+#elif defined(__FreeBSD__)
+		/*
+		 * In FreeBSD if_iwlwifi contains all drv modules in a single
+		 * module.  SYSINIT will do the job later.  We cannot call
+		 * into kern_kldload() while being called from kern_kldload():
+		 * LinuxKPI request_module[_nowait] will hang hard.
+		 * Given this is request_module_nowait() we can simply skip it.
+		 */
+		if (bootverbose)
+			printf("%s: module '%s' not yet available; will be initialized in a moment\n",
+			    __func__, op->name);
+#endif
 	}
 	mutex_unlock(&iwlwifi_opmode_table_mtx);