aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iwm
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2017-05-12 05:28:49 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2017-05-12 05:28:49 +0000
commita88f1dbf421a965573bdefb627839f4981a5c9ab (patch)
tree72786dde60f4bc7d5b3fb76083f191177e5fdd7f /sys/dev/iwm
parentb72d4b835b6133dbb185f671393abb9ac473eb87 (diff)
downloadsrc-a88f1dbf421a965573bdefb627839f4981a5c9ab.tar.gz
src-a88f1dbf421a965573bdefb627839f4981a5c9ab.zip
[iwm] Sync iwm_read_firmware()'s loop to iwlwifi's code.
Obtained from: dragonflybsd.git d1c10ccfcf2d6d2a664f17197add0b4f93333181
Notes
Notes: svn path=/head/; revision=318216
Diffstat (limited to 'sys/dev/iwm')
-rw-r--r--sys/dev/iwm/if_iwm.c51
1 files changed, 28 insertions, 23 deletions
diff --git a/sys/dev/iwm/if_iwm.c b/sys/dev/iwm/if_iwm.c
index 8096c17df729..c93d33bcf748 100644
--- a/sys/dev/iwm/if_iwm.c
+++ b/sys/dev/iwm/if_iwm.c
@@ -549,12 +549,14 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
{
struct iwm_fw_info *fw = &sc->sc_fw;
const struct iwm_tlv_ucode_header *uhdr;
- struct iwm_ucode_tlv tlv;
+ const 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;
+ uint32_t tlv_len;
uint32_t usniffer_img;
+ const uint8_t *tlv_data;
uint32_t paging_mem_size;
int num_of_cpus;
int error = 0;
@@ -607,24 +609,20 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto out;
}
- snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%d.%d (API ver %d)",
+ snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%u.%u (API ver %u)",
IWM_UCODE_MAJOR(le32toh(uhdr->ver)),
IWM_UCODE_MINOR(le32toh(uhdr->ver)),
IWM_UCODE_API(le32toh(uhdr->ver)));
data = uhdr->data;
len = fw->fw_fp->datasize - sizeof(*uhdr);
- while (len >= sizeof(tlv)) {
- size_t tlv_len;
- const void *tlv_data;
+ while (len >= sizeof(*tlv)) {
+ len -= sizeof(*tlv);
+ tlv = (const void *)data;
- memcpy(&tlv, data, sizeof(tlv));
- tlv_len = le32toh(tlv.length);
- tlv_type = le32toh(tlv.type);
-
- len -= sizeof(tlv);
- data += sizeof(tlv);
- tlv_data = data;
+ tlv_len = le32toh(tlv->length);
+ tlv_type = le32toh(tlv->type);
+ tlv_data = tlv->data;
if (len < tlv_len) {
device_printf(sc->sc_dev,
@@ -633,19 +631,21 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL;
goto parse_out;
}
+ len -= roundup2(tlv_len, 4);
+ data += sizeof(tlv) + roundup2(tlv_len, 4);
switch ((int)tlv_type) {
case IWM_UCODE_TLV_PROBE_MAX_LEN:
- if (tlv_len < sizeof(uint32_t)) {
+ if (tlv_len != sizeof(uint32_t)) {
device_printf(sc->sc_dev,
- "%s: PROBE_MAX_LEN (%d) < sizeof(uint32_t)\n",
+ "%s: PROBE_MAX_LEN (%d) != sizeof(uint32_t)\n",
__func__,
(int) tlv_len);
error = EINVAL;
goto parse_out;
}
capa->max_probe_length =
- le32toh(*(const uint32_t *)tlv_data);
+ le32_to_cpup((const uint32_t *)tlv_data);
/* limit it to something sensible */
if (capa->max_probe_length >
IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
@@ -676,6 +676,14 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
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);
+ error = EINVAL;
+ goto parse_out;
+ }
/*
* Apparently there can be many flags, but Linux driver
* parses only the first one, and so do we.
@@ -687,7 +695,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
* 2) TLV_FLAGS contains TLV_FLAGS_PAN
* ==> this resets TLV_PAN to itself... hnnnk
*/
- capa->flags = le32toh(*(const uint32_t *)tlv_data);
+ capa->flags = le32_to_cpup((const uint32_t *)tlv_data);
break;
case IWM_UCODE_TLV_CSCHEME:
if ((error = iwm_store_cscheme(sc,
@@ -708,7 +716,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL;
goto parse_out;
}
- num_of_cpus = le32toh(*(const uint32_t *)tlv_data);
+ num_of_cpus = le32_to_cpup((const uint32_t *)tlv_data);
if (num_of_cpus == 2) {
fw->fw_sects[IWM_UCODE_REGULAR].is_dual_cpus =
TRUE;
@@ -782,7 +790,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto parse_out;
}
sc->sc_fw.phy_config =
- le32toh(*(const uint32_t *)tlv_data);
+ le32_to_cpup((const uint32_t *)tlv_data);
sc->sc_fw.valid_tx_ant = (sc->sc_fw.phy_config &
IWM_FW_PHY_CFG_TX_CHAIN) >>
IWM_FW_PHY_CFG_TX_CHAIN_POS;
@@ -833,7 +841,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL;
goto parse_out;
}
- paging_mem_size = le32toh(*(const uint32_t *)tlv_data);
+ paging_mem_size = le32_to_cpup((const uint32_t *)tlv_data);
IWM_DPRINTF(sc, IWM_DEBUG_FIRMWARE_TLV,
"%s: Paging: paging enabled (size = %u bytes)\n",
@@ -866,7 +874,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
goto parse_out;
}
capa->n_scan_channels =
- le32toh(*(const uint32_t *)tlv_data);
+ le32_to_cpup((const uint32_t *)tlv_data);
break;
case IWM_UCODE_TLV_FW_VERSION:
@@ -891,9 +899,6 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type)
error = EINVAL;
goto parse_out;
}
-
- len -= roundup(tlv_len, 4);
- data += roundup(tlv_len, 4);
}
KASSERT(error == 0, ("unhandled error"));