svn commit: r343375 - head/sys/dev/iwm

Kyle Evans kevans at FreeBSD.org
Thu Jan 24 03:42:25 UTC 2019


Author: kevans
Date: Thu Jan 24 03:42:23 2019
New Revision: 343375
URL: https://svnweb.freebsd.org/changeset/base/343375

Log:
  if_iwm - Move iwm_read_firmware() call into iwm_attach().
  
  * We should load the firmware exactly once before the driver really
  initializes the hardware the first time, and unload it at detach time.
  There is no need to retrieve the firmware during execution of
  iwm_mvm_load_ucode_wait_alive(), we should make sure we already have the
  firmware data at hand before that.
  
  * The existing sc_preinit_hook code fails to deal with the case where
  if_iwm is loaded by the loader (or is statically linked) and the
  firmware needs to be loaded from disk. So we can just call
  iwm_read_firmware() from iwm_attach() directly.
  
  * A separate solution will have to be added to properly defer the firmware
  loading during bootup, until the necessary filesystem is mounted.
  
  Submitted by:	Augustin Cavalier <waddlesplash at gmail.com> (Haiku)
  Obtained from:	DragonFlyBSD (0104ee1f4cb6a2313c00c2526c6ae98d42e5041d)

Modified:
  head/sys/dev/iwm/if_iwm.c
  head/sys/dev/iwm/if_iwmvar.h

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c	Thu Jan 24 03:41:44 2019	(r343374)
+++ head/sys/dev/iwm/if_iwm.c	Thu Jan 24 03:42:23 2019	(r343375)
@@ -245,7 +245,7 @@ static int	iwm_firmware_store_section(struct iwm_softc
                                            const uint8_t *, size_t);
 static int	iwm_set_default_calib(struct iwm_softc *, const void *);
 static void	iwm_fw_info_free(struct iwm_fw_info *);
-static int	iwm_read_firmware(struct iwm_softc *, enum iwm_ucode_type);
+static int	iwm_read_firmware(struct iwm_softc *);
 static int	iwm_alloc_fwmem(struct iwm_softc *);
 static int	iwm_alloc_sched(struct iwm_softc *);
 static int	iwm_alloc_kw(struct iwm_softc *);
@@ -536,12 +536,11 @@ iwm_fw_info_free(struct iwm_fw_info *fw)
 {
 	firmware_put(fw->fw_fp, FIRMWARE_UNLOAD);
 	fw->fw_fp = NULL;
-	/* don't touch fw->fw_status */
 	memset(fw->fw_sects, 0, sizeof(fw->fw_sects));
 }
 
 static int
-iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
+iwm_read_firmware(struct iwm_softc *sc)
 {
 	struct iwm_fw_info *fw = &sc->sc_fw;
 	const struct iwm_tlv_ucode_header *uhdr;
@@ -558,24 +557,11 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 	int error = 0;
 	size_t len;
 
-	if (fw->fw_status == IWM_FW_STATUS_DONE &&
-	    ucode_type != IWM_UCODE_INIT)
-		return 0;
-
-	while (fw->fw_status == IWM_FW_STATUS_INPROGRESS)
-		msleep(&sc->sc_fw, &sc->sc_mtx, 0, "iwmfwp", 0);
-	fw->fw_status = IWM_FW_STATUS_INPROGRESS;
-
-	if (fw->fw_fp != NULL)
-		iwm_fw_info_free(fw);
-
 	/*
 	 * Load firmware into driver memory.
 	 * fw_fp will be set.
 	 */
-	IWM_UNLOCK(sc);
 	fwp = firmware_get(sc->cfg->fw_name);
-	IWM_LOCK(sc);
 	if (fwp == NULL) {
 		device_printf(sc->sc_dev,
 		    "could not read firmware %s (error %d)\n",
@@ -634,9 +620,8 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 		case IWM_UCODE_TLV_PROBE_MAX_LEN:
 			if (tlv_len != sizeof(uint32_t)) {
 				device_printf(sc->sc_dev,
-				    "%s: PROBE_MAX_LEN (%d) != sizeof(uint32_t)\n",
-				    __func__,
-				    (int) tlv_len);
+				    "%s: PROBE_MAX_LEN (%u) != sizeof(uint32_t)\n",
+				    __func__, tlv_len);
 				error = EINVAL;
 				goto parse_out;
 			}
@@ -655,9 +640,8 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 		case IWM_UCODE_TLV_PAN:
 			if (tlv_len) {
 				device_printf(sc->sc_dev,
-				    "%s: IWM_UCODE_TLV_PAN: tlv_len (%d) > 0\n",
-				    __func__,
-				    (int) tlv_len);
+				    "%s: IWM_UCODE_TLV_PAN: tlv_len (%u) > 0\n",
+				    __func__, tlv_len);
 				error = EINVAL;
 				goto parse_out;
 			}
@@ -666,17 +650,15 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 		case IWM_UCODE_TLV_FLAGS:
 			if (tlv_len < sizeof(uint32_t)) {
 				device_printf(sc->sc_dev,
-				    "%s: IWM_UCODE_TLV_FLAGS: tlv_len (%d) < sizeof(uint32_t)\n",
-				    __func__,
-				    (int) tlv_len);
+				    "%s: IWM_UCODE_TLV_FLAGS: tlv_len (%u) < sizeof(uint32_t)\n",
+				    __func__, tlv_len);
 				error = EINVAL;
 				goto parse_out;
 			}
 			if (tlv_len % sizeof(uint32_t)) {
 				device_printf(sc->sc_dev,
-				    "%s: IWM_UCODE_TLV_FLAGS: tlv_len (%d) %% sizeof(uint32_t)\n",
-				    __func__,
-				    (int) tlv_len);
+				    "%s: IWM_UCODE_TLV_FLAGS: tlv_len (%u) %% sizeof(uint32_t)\n",
+				    __func__, tlv_len);
 				error = EINVAL;
 				goto parse_out;
 			}
@@ -698,17 +680,15 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 			    tlv_data, tlv_len)) != 0) {
 				device_printf(sc->sc_dev,
 				    "%s: iwm_store_cscheme(): returned %d\n",
-				    __func__,
-				    error);
+				    __func__, error);
 				goto parse_out;
 			}
 			break;
 		case IWM_UCODE_TLV_NUM_OF_CPU:
 			if (tlv_len != sizeof(uint32_t)) {
 				device_printf(sc->sc_dev,
-				    "%s: IWM_UCODE_TLV_NUM_OF_CPU: tlv_len (%d) != sizeof(uint32_t)\n",
-				    __func__,
-				    (int) tlv_len);
+				    "%s: IWM_UCODE_TLV_NUM_OF_CPU: tlv_len (%u) != sizeof(uint32_t)\n",
+				    __func__, tlv_len);
 				error = EINVAL;
 				goto parse_out;
 			}
@@ -733,8 +713,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 			    IWM_UCODE_REGULAR, tlv_data, tlv_len)) != 0) {
 				device_printf(sc->sc_dev,
 				    "%s: IWM_UCODE_REGULAR: iwm_firmware_store_section() failed; %d\n",
-				    __func__,
-				    error);
+				    __func__, error);
 				goto parse_out;
 			}
 			break;
@@ -743,8 +722,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 			    IWM_UCODE_INIT, tlv_data, tlv_len)) != 0) {
 				device_printf(sc->sc_dev,
 				    "%s: IWM_UCODE_INIT: iwm_firmware_store_section() failed; %d\n",
-				    __func__,
-				    error);
+				    __func__, error);
 				goto parse_out;
 			}
 			break;
@@ -753,26 +731,23 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 			    IWM_UCODE_WOWLAN, tlv_data, tlv_len)) != 0) {
 				device_printf(sc->sc_dev,
 				    "%s: IWM_UCODE_WOWLAN: iwm_firmware_store_section() failed; %d\n",
-				    __func__,
-				    error);
+				    __func__, error);
 				goto parse_out;
 			}
 			break;
 		case IWM_UCODE_TLV_DEF_CALIB:
 			if (tlv_len != sizeof(struct iwm_tlv_calib_data)) {
 				device_printf(sc->sc_dev,
-				    "%s: IWM_UCODE_TLV_DEV_CALIB: tlv_len (%d) < sizeof(iwm_tlv_calib_data) (%d)\n",
-				    __func__,
-				    (int) tlv_len,
-				    (int) sizeof(struct iwm_tlv_calib_data));
+				    "%s: IWM_UCODE_TLV_DEV_CALIB: tlv_len (%u) < sizeof(iwm_tlv_calib_data) (%zu)\n",
+				    __func__, tlv_len,
+				    sizeof(struct iwm_tlv_calib_data));
 				error = EINVAL;
 				goto parse_out;
 			}
 			if ((error = iwm_set_default_calib(sc, tlv_data)) != 0) {
 				device_printf(sc->sc_dev,
 				    "%s: iwm_set_default_calib() failed: %d\n",
-				    __func__,
-				    error);
+				    __func__, error);
 				goto parse_out;
 			}
 			break;
@@ -780,9 +755,8 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 			if (tlv_len != sizeof(uint32_t)) {
 				error = EINVAL;
 				device_printf(sc->sc_dev,
-				    "%s: IWM_UCODE_TLV_PHY_SKU: tlv_len (%d) < sizeof(uint32_t)\n",
-				    __func__,
-				    (int) tlv_len);
+				    "%s: IWM_UCODE_TLV_PHY_SKU: tlv_len (%u) < sizeof(uint32_t)\n",
+				    __func__, tlv_len);
 				goto parse_out;
 			}
 			sc->sc_fw.phy_config =
@@ -907,12 +881,9 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 
  out:
 	if (error) {
-		fw->fw_status = IWM_FW_STATUS_NONE;
 		if (fw->fw_fp != NULL)
 			iwm_fw_info_free(fw);
-	} else
-		fw->fw_status = IWM_FW_STATUS_DONE;
-	wakeup(&sc->sc_fw);
+	}
 
 	return error;
 }
@@ -2858,11 +2829,6 @@ iwm_mvm_load_ucode_wait_alive(struct iwm_softc *sc,
 	int error;
 	static const uint16_t alive_cmd[] = { IWM_MVM_ALIVE };
 
-	if ((error = iwm_read_firmware(sc, ucode_type)) != 0) {
-		device_printf(sc->sc_dev, "iwm_read_firmware: failed %d\n",
-			error);
-		return error;
-	}
 	fw = &sc->sc_fw.fw_sects[ucode_type];
 	sc->cur_ucode = ucode_type;
 	sc->ucode_loaded = FALSE;
@@ -5849,7 +5815,7 @@ iwm_attach(device_t dev)
 
 	sc->sc_wantresp = -1;
 
-	/* Check device type */
+	/* Match device id */
 	error = iwm_dev_check(dev);
 	if (error != 0)
 		goto fail;
@@ -5987,18 +5953,30 @@ iwm_attach(device_t dev)
 	/* Max RSSI */
 	sc->sc_max_rssi = IWM_MAX_DBM - IWM_MIN_DBM;
 
-	sc->sc_preinit_hook.ich_func = iwm_preinit;
-	sc->sc_preinit_hook.ich_arg = sc;
-	if (config_intrhook_establish(&sc->sc_preinit_hook) != 0) {
-		device_printf(dev, "config_intrhook_establish failed\n");
-		goto fail;
-	}
-
 #ifdef IWM_DEBUG
 	SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
 	    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "debug",
 	    CTLFLAG_RW, &sc->sc_debug, 0, "control debugging");
 #endif
+
+	error = iwm_read_firmware(sc);
+	if (error) {
+		goto fail;
+	} else if (sc->sc_fw.fw_fp == NULL) {
+		/*
+		 * XXX Add a solution for properly deferring firmware load
+		 *     during bootup.
+		 */
+		goto fail;
+	} else {
+		sc->sc_preinit_hook.ich_func = iwm_preinit;
+		sc->sc_preinit_hook.ich_arg = sc;
+		if (config_intrhook_establish(&sc->sc_preinit_hook) != 0) {
+			device_printf(dev,
+			    "config_intrhook_establish failed\n");
+			goto fail;
+		}
+	}
 
 	IWM_DPRINTF(sc, IWM_DEBUG_RESET | IWM_DEBUG_TRACE,
 	    "<-%s\n", __func__);

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h	Thu Jan 24 03:41:44 2019	(r343374)
+++ head/sys/dev/iwm/if_iwmvar.h	Thu Jan 24 03:42:23 2019	(r343375)
@@ -139,15 +139,6 @@ struct iwm_tx_radiotap_header {
 
 #define IWM_UCODE_SECTION_MAX 16
 
-/*
- * fw_status is used to determine if we've already parsed the firmware file
- *
- * In addition to the following, status < 0 ==> -error
- */
-#define IWM_FW_STATUS_NONE		0
-#define IWM_FW_STATUS_INPROGRESS	1
-#define IWM_FW_STATUS_DONE		2
-
 /**
  * enum iwm_ucode_type
  *
@@ -197,7 +188,6 @@ struct iwm_fw_desc {
 
 struct iwm_fw_info {
 	const struct firmware *fw_fp;
-	int fw_status;
 
 	struct iwm_fw_sects {
 		struct iwm_fw_desc fw_sect[IWM_UCODE_SECTION_MAX];


More information about the svn-src-all mailing list