Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Mar 2017 04:50:39 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r315784 - head/sys/dev/iwm
Message-ID:  <201703230450.v2N4odKB006314@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Thu Mar 23 04:50:38 2017
New Revision: 315784
URL: https://svnweb.freebsd.org/changeset/base/315784

Log:
  [iwm] Make ucode capabilities and api flags handling more like iwlwifi.
  
  Obtained from:	dragonflybsd.git 757eecf0e6c92745aa2eee95811e573c8300850e

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

Modified: head/sys/dev/iwm/if_iwm.c
==============================================================================
--- head/sys/dev/iwm/if_iwm.c	Thu Mar 23 04:49:33 2017	(r315783)
+++ head/sys/dev/iwm/if_iwm.c	Thu Mar 23 04:50:38 2017	(r315784)
@@ -484,6 +484,56 @@ iwm_set_default_calib(struct iwm_softc *
 	return 0;
 }
 
+static int
+iwm_set_ucode_api_flags(struct iwm_softc *sc, const uint8_t *data,
+			struct iwm_ucode_capabilities *capa)
+{
+	const struct iwm_ucode_api *ucode_api = (const void *)data;
+	uint32_t api_index = le32toh(ucode_api->api_index);
+	uint32_t api_flags = le32toh(ucode_api->api_flags);
+	int i;
+
+	if (api_index >= howmany(IWM_NUM_UCODE_TLV_API, 32)) {
+		device_printf(sc->sc_dev,
+		    "api flags index %d larger than supported by driver\n",
+		    api_index);
+		/* don't return an error so we can load FW that has more bits */
+		return 0;
+	}
+
+	for (i = 0; i < 32; i++) {
+		if (api_flags & (1U << i))
+			setbit(capa->enabled_api, i + 32 * api_index);
+	}
+
+	return 0;
+}
+
+static int
+iwm_set_ucode_capabilities(struct iwm_softc *sc, const uint8_t *data,
+			   struct iwm_ucode_capabilities *capa)
+{
+	const struct iwm_ucode_capa *ucode_capa = (const void *)data;
+	uint32_t api_index = le32toh(ucode_capa->api_index);
+	uint32_t api_flags = le32toh(ucode_capa->api_capa);
+	int i;
+
+	if (api_index >= howmany(IWM_NUM_UCODE_TLV_CAPA, 32)) {
+		device_printf(sc->sc_dev,
+		    "capa flags index %d larger than supported by driver\n",
+		    api_index);
+		/* don't return an error so we can load FW that has more bits */
+		return 0;
+	}
+
+	for (i = 0; i < 32; i++) {
+		if (api_flags & (1U << i))
+			setbit(capa->enabled_capa, i + 32 * api_index);
+	}
+
+	return 0;
+}
+
 static void
 iwm_fw_info_free(struct iwm_fw_info *fw)
 {
@@ -499,6 +549,7 @@ iwm_read_firmware(struct iwm_softc *sc, 
 	struct iwm_fw_info *fw = &sc->sc_fw;
 	const struct iwm_tlv_ucode_header *uhdr;
 	struct iwm_ucode_tlv tlv;
+	struct iwm_ucode_capabilities *capa = &sc->ucode_capa;
 	enum iwm_ucode_tlv_type tlv_type;
 	const struct firmware *fwp;
 	const uint8_t *data;
@@ -535,9 +586,11 @@ iwm_read_firmware(struct iwm_softc *sc, 
 	fw->fw_fp = fwp;
 
 	/* (Re-)Initialize default values. */
-	sc->sc_capaflags = 0;
-	sc->sc_capa_n_scan_channels = IWM_DEFAULT_SCAN_CHANNELS;
-	memset(sc->sc_enabled_capa, 0, sizeof(sc->sc_enabled_capa));
+	capa->flags = 0;
+	capa->max_probe_length = IWM_DEFAULT_MAX_PROBE_LENGTH;
+	capa->n_scan_channels = IWM_DEFAULT_SCAN_CHANNELS;
+	memset(capa->enabled_capa, 0, sizeof(capa->enabled_capa));
+	memset(capa->enabled_api, 0, sizeof(capa->enabled_api));
 	memset(sc->sc_fw_mcc, 0, sizeof(sc->sc_fw_mcc));
 
 	/*
@@ -590,10 +643,10 @@ iwm_read_firmware(struct iwm_softc *sc, 
 				error = EINVAL;
 				goto parse_out;
 			}
-			sc->sc_capa_max_probe_len
-			    = le32toh(*(const uint32_t *)tlv_data);
+			capa->max_probe_length =
+			    le32toh(*(const uint32_t *)tlv_data);
 			/* limit it to something sensible */
-			if (sc->sc_capa_max_probe_len >
+			if (capa->max_probe_length >
 			    IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
 				IWM_DPRINTF(sc, IWM_DEBUG_FIRMWARE_TLV,
 				    "%s: IWM_UCODE_TLV_PROBE_MAX_LEN "
@@ -611,7 +664,7 @@ iwm_read_firmware(struct iwm_softc *sc, 
 				error = EINVAL;
 				goto parse_out;
 			}
-			sc->sc_capaflags |= IWM_UCODE_TLV_FLAGS_PAN;
+			capa->flags |= IWM_UCODE_TLV_FLAGS_PAN;
 			break;
 		case IWM_UCODE_TLV_FLAGS:
 			if (tlv_len < sizeof(uint32_t)) {
@@ -633,7 +686,7 @@ iwm_read_firmware(struct iwm_softc *sc, 
 			 *  2) TLV_FLAGS contains TLV_FLAGS_PAN
 			 * ==> this resets TLV_PAN to itself... hnnnk
 			 */
-			sc->sc_capaflags = le32toh(*(const uint32_t *)tlv_data);
+			capa->flags = le32toh(*(const uint32_t *)tlv_data);
 			break;
 		case IWM_UCODE_TLV_CSCHEME:
 			if ((error = iwm_store_cscheme(sc,
@@ -738,42 +791,26 @@ iwm_read_firmware(struct iwm_softc *sc, 
 			break;
 
 		case IWM_UCODE_TLV_API_CHANGES_SET: {
-			const struct iwm_ucode_api *api;
-			if (tlv_len != sizeof(*api)) {
+			if (tlv_len != sizeof(struct iwm_ucode_api)) {
 				error = EINVAL;
 				goto parse_out;
 			}
-			api = (const struct iwm_ucode_api *)tlv_data;
-			/* Flags may exceed 32 bits in future firmware. */
-			if (le32toh(api->api_index) > 0) {
-				device_printf(sc->sc_dev,
-				    "unsupported API index %d\n",
-				    le32toh(api->api_index));
+			if (iwm_set_ucode_api_flags(sc, tlv_data, capa)) {
+				error = EINVAL;
 				goto parse_out;
 			}
-			sc->sc_ucode_api = le32toh(api->api_flags);
 			break;
 		}
 
 		case IWM_UCODE_TLV_ENABLED_CAPABILITIES: {
-			const struct iwm_ucode_capa *capa;
-			int idx, i;
-			if (tlv_len != sizeof(*capa)) {
+			if (tlv_len != sizeof(struct iwm_ucode_capa)) {
 				error = EINVAL;
 				goto parse_out;
 			}
-			capa = (const struct iwm_ucode_capa *)tlv_data;
-			idx = le32toh(capa->api_index);
-			if (idx >= howmany(IWM_NUM_UCODE_TLV_CAPA, 32)) {
-				device_printf(sc->sc_dev,
-				    "unsupported API index %d\n", idx);
+			if (iwm_set_ucode_capabilities(sc, tlv_data, capa)) {
+				error = EINVAL;
 				goto parse_out;
 			}
-			for (i = 0; i < 32; i++) {
-				if ((le32toh(capa->api_capa) & (1U << i)) == 0)
-					continue;
-				setbit(sc->sc_enabled_capa, i + (32 * idx));
-			}
 			break;
 		}
 
@@ -827,8 +864,8 @@ iwm_read_firmware(struct iwm_softc *sc, 
 				error = EINVAL;
 				goto parse_out;
 			}
-			sc->sc_capa_n_scan_channels =
-			  le32toh(*(const uint32_t *)tlv_data);
+			capa->n_scan_channels =
+			    le32toh(*(const uint32_t *)tlv_data);
 			break;
 
 		case IWM_UCODE_TLV_FW_VERSION:
@@ -4713,13 +4750,13 @@ iwm_send_update_mcc_cmd(struct iwm_softc
 	int n_channels;
 	uint16_t mcc;
 #endif
-	int resp_v2 = isset(sc->sc_enabled_capa,
+	int resp_v2 = fw_has_capa(&sc->ucode_capa,
 	    IWM_UCODE_TLV_CAPA_LAR_SUPPORT_V2);
 
 	memset(&mcc_cmd, 0, sizeof(mcc_cmd));
 	mcc_cmd.mcc = htole16(alpha2[0] << 8 | alpha2[1]);
-	if ((sc->sc_ucode_api & IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
-	    isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC))
+	if (fw_has_api(&sc->ucode_capa, IWM_UCODE_TLV_API_WIFI_MCC_UPDATE) ||
+	    fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_LAR_MULTI_MCC))
 		mcc_cmd.source_id = IWM_MCC_SOURCE_GET_CURRENT;
 	else
 		mcc_cmd.source_id = IWM_MCC_SOURCE_OLD_FW;
@@ -4857,12 +4894,12 @@ iwm_init_hw(struct iwm_softc *sc)
 	if (error)
 		goto error;
 
-	if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_LAR_SUPPORT)) {
+	if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_LAR_SUPPORT)) {
 		if ((error = iwm_send_update_mcc_cmd(sc, "ZZ")) != 0)
 			goto error;
 	}
 
-	if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
+	if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN)) {
 		if ((error = iwm_mvm_config_umac_scan(sc)) != 0)
 			goto error;
 	}
@@ -6263,7 +6300,7 @@ iwm_scan_start(struct ieee80211com *ic)
 		device_printf(sc->sc_dev,
 		    "%s: Previous scan not completed yet\n", __func__);
 	}
-	if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))
+	if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))
 		error = iwm_mvm_umac_scan(sc);
 	else
 		error = iwm_mvm_lmac_scan(sc);

Modified: head/sys/dev/iwm/if_iwm_scan.c
==============================================================================
--- head/sys/dev/iwm/if_iwm_scan.c	Thu Mar 23 04:49:33 2017	(r315783)
+++ head/sys/dev/iwm/if_iwm_scan.c	Thu Mar 23 04:50:38 2017	(r315784)
@@ -272,7 +272,7 @@ iwm_mvm_lmac_scan_fill_channels(struct i
 	int j;
 
 	for (nchan = j = 0;
-	    j < ic->ic_nchans && nchan < sc->sc_capa_n_scan_channels; j++) {
+	    j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) {
 		c = &ic->ic_channels[j];
 		/* For 2GHz, only populate 11b channels */
 		/* For 5GHz, only populate 11a channels */
@@ -316,7 +316,7 @@ iwm_mvm_umac_scan_fill_channels(struct i
 	int j;
 
 	for (nchan = j = 0;
-	    j < ic->ic_nchans && nchan < sc->sc_capa_n_scan_channels; j++) {
+	    j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) {
 		c = &ic->ic_channels[j];
 		/* For 2GHz, only populate 11b channels */
 		/* For 5GHz, only populate 11a channels */
@@ -398,7 +398,7 @@ iwm_mvm_fill_probe_req(struct iwm_softc 
 	preq->band_data[0].len = htole16(frm - pos);
 	remain -= frm - pos;
 
-	if (isset(sc->sc_enabled_capa,
+	if (fw_has_capa(&sc->ucode_capa,
 	    IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT)) {
 		if (remain < 3)
 			return ENOBUFS;
@@ -464,7 +464,7 @@ iwm_mvm_config_umac_scan(struct iwm_soft
 	    IWM_SCAN_CONFIG_RATE_36M | IWM_SCAN_CONFIG_RATE_48M |
 	    IWM_SCAN_CONFIG_RATE_54M);
 
-	cmd_size = sizeof(*scan_config) + sc->sc_capa_n_scan_channels;
+	cmd_size = sizeof(*scan_config) + sc->ucode_capa.n_scan_channels;
 
 	scan_config = malloc(cmd_size, M_DEVBUF, M_NOWAIT | M_ZERO);
 	if (scan_config == NULL)
@@ -492,7 +492,7 @@ iwm_mvm_config_umac_scan(struct iwm_soft
 	    IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
 
 	for (nchan = j = 0;
-	    j < ic->ic_nchans && nchan < sc->sc_capa_n_scan_channels; j++) {
+	    j < ic->ic_nchans && nchan < sc->ucode_capa.n_scan_channels; j++) {
 		c = &ic->ic_channels[j];
 		/* For 2GHz, only populate 11b channels */
 		/* For 5GHz, only populate 11a channels */
@@ -550,7 +550,7 @@ iwm_mvm_umac_scan(struct iwm_softc *sc)
 
 	req_len = sizeof(struct iwm_scan_req_umac) +
 	    (sizeof(struct iwm_scan_channel_cfg_umac) *
-	    sc->sc_capa_n_scan_channels) +
+	    sc->ucode_capa.n_scan_channels) +
 	    sizeof(struct iwm_scan_req_umac_tail);
 	if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
 		return ENOMEM;
@@ -584,7 +584,7 @@ iwm_mvm_umac_scan(struct iwm_softc *sc)
 
 	tail = (void *)((char *)&req->data +
 		sizeof(struct iwm_scan_channel_cfg_umac) *
-			sc->sc_capa_n_scan_channels);
+			sc->ucode_capa.n_scan_channels);
 
 	/* Check if we're doing an active directed scan. */
 	for (i = 0; i < nssid; i++) {
@@ -601,7 +601,7 @@ iwm_mvm_umac_scan(struct iwm_softc *sc)
 	} else
 		req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASSIVE);
 
-	if (isset(sc->sc_enabled_capa,
+	if (fw_has_capa(&sc->ucode_capa,
 	    IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
 		req->general_flags |=
 		    htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED);
@@ -644,7 +644,7 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc)
 
 	req_len = sizeof(struct iwm_scan_req_lmac) +
 	    (sizeof(struct iwm_scan_channel_cfg_lmac) *
-	    sc->sc_capa_n_scan_channels) + sizeof(struct iwm_scan_probe_req);
+	    sc->ucode_capa.n_scan_channels) + sizeof(struct iwm_scan_probe_req);
 	if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE)
 		return ENOMEM;
 	req = malloc(req_len, M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -670,7 +670,7 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc)
 	req->scan_flags = htole32(IWM_MVM_LMAC_SCAN_FLAG_PASS_ALL |
 	    IWM_MVM_LMAC_SCAN_FLAG_ITER_COMPLETE |
 	    IWM_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL);
-	if (isset(sc->sc_enabled_capa,
+	if (fw_has_capa(&sc->ucode_capa,
 	    IWM_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT))
 		req->scan_flags |= htole32(IWM_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED);
 
@@ -716,7 +716,7 @@ iwm_mvm_lmac_scan(struct iwm_softc *sc)
 	ret = iwm_mvm_fill_probe_req(sc,
 			    (struct iwm_scan_probe_req *)(req->data +
 			    (sizeof(struct iwm_scan_channel_cfg_lmac) *
-			    sc->sc_capa_n_scan_channels)));
+			    sc->ucode_capa.n_scan_channels)));
 	if (ret) {
 		free(req, M_DEVBUF);
 		return ret;
@@ -804,7 +804,7 @@ iwm_mvm_scan_stop_wait(struct iwm_softc 
 
 	IWM_DPRINTF(sc, IWM_DEBUG_SCAN, "Preparing to stop scan\n");
 
-	if (isset(sc->sc_enabled_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))
+	if (fw_has_capa(&sc->ucode_capa, IWM_UCODE_TLV_CAPA_UMAC_SCAN))
 		ret = iwm_mvm_umac_scan_abort(sc);
 	else
 		ret = iwm_mvm_lmac_scan_abort(sc);

Modified: head/sys/dev/iwm/if_iwmvar.h
==============================================================================
--- head/sys/dev/iwm/if_iwmvar.h	Thu Mar 23 04:49:33 2017	(r315783)
+++ head/sys/dev/iwm/if_iwmvar.h	Thu Mar 23 04:50:38 2017	(r315784)
@@ -166,6 +166,28 @@ enum iwm_ucode_type {
 	IWM_UCODE_TYPE_MAX
 };
 
+struct iwm_ucode_capabilities {
+	uint32_t max_probe_length;
+	uint32_t n_scan_channels;
+	uint32_t flags;
+	uint8_t enabled_api[howmany(IWM_NUM_UCODE_TLV_API, NBBY)];
+	uint8_t enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)];
+};
+
+static inline int
+fw_has_api(const struct iwm_ucode_capabilities *capabilities,
+	   unsigned int api)
+{
+	return isset(capabilities->enabled_api, api);
+}
+
+static inline int
+fw_has_capa(const struct iwm_ucode_capabilities *capabilities,
+	    unsigned int capa)
+{
+	return isset(capabilities->enabled_capa, capa);
+}
+
 /* one for each uCode image (inst/data, init/runtime/wowlan) */
 struct iwm_fw_desc {
 	const void *data;	/* vmalloc'ed data */
@@ -440,12 +462,8 @@ struct iwm_softc {
 	int			ucode_loaded;
 	char			sc_fwver[32];
 
-	int			sc_capaflags;
-	int			sc_capa_max_probe_len;
-	int sc_capa_n_scan_channels;
-	uint32_t sc_ucode_api;
-	uint8_t sc_enabled_capa[howmany(IWM_NUM_UCODE_TLV_CAPA, NBBY)];
-	char sc_fw_mcc[3];
+	struct iwm_ucode_capabilities ucode_capa;
+	char			sc_fw_mcc[3];
 
 	int			sc_intmask;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703230450.v2N4odKB006314>