Author: eadler
Date: Sun Mar 11 22:49:46 2018
New Revision: 330784
URL: https://svnweb.freebsd.org/changeset/base/330784

Log:
  Revert r324434
  
  Some users are reporting that it is causing issues for their hardware.
  In the interest of not breaking stable, revert while we investigate.

Modified:
  stable/11/sys/dev/iwm/if_iwm.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/iwm/if_iwm.c
==============================================================================
--- stable/11/sys/dev/iwm/if_iwm.c      Sun Mar 11 20:13:15 2018        
(r330783)
+++ stable/11/sys/dev/iwm/if_iwm.c      Sun Mar 11 22:49:46 2018        
(r330784)
@@ -547,14 +547,12 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
 {
        struct iwm_fw_info *fw = &sc->sc_fw;
        const struct iwm_tlv_ucode_header *uhdr;
-       const struct iwm_ucode_tlv *tlv;
+       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,21 +605,25 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                goto out;
        }
 
-       snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%u.%u (API ver %u)",
+       snprintf(sc->sc_fwver, sizeof(sc->sc_fwver), "%d.%d (API ver %d)",
            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)) {
-               len -= sizeof(*tlv);
-               tlv = (const void *)data;
+       while (len >= sizeof(tlv)) {
+               size_t tlv_len;
+               const void *tlv_data;
 
-               tlv_len = le32toh(tlv->length);
-               tlv_type = le32toh(tlv->type);
-               tlv_data = tlv->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;
+
                if (len < tlv_len) {
                        device_printf(sc->sc_dev,
                            "firmware too short: %zu bytes\n",
@@ -629,21 +631,19 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                        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 =
-                           le32_to_cpup((const uint32_t *)tlv_data);
+                           le32toh(*(const uint32_t *)tlv_data);
                        /* limit it to something sensible */
                        if (capa->max_probe_length >
                            IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE) {
@@ -674,14 +674,6 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                                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.
@@ -693,7 +685,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                         *  2) TLV_FLAGS contains TLV_FLAGS_PAN
                         * ==> this resets TLV_PAN to itself... hnnnk
                         */
-                       capa->flags = le32_to_cpup((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,
@@ -714,7 +706,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                                error = EINVAL;
                                goto parse_out;
                        }
-                       num_of_cpus = le32_to_cpup((const uint32_t *)tlv_data);
+                       num_of_cpus = le32toh(*(const uint32_t *)tlv_data);
                        if (num_of_cpus == 2) {
                                fw->fw_sects[IWM_UCODE_REGULAR].is_dual_cpus =
                                        TRUE;
@@ -788,7 +780,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                                goto parse_out;
                        }
                        sc->sc_fw.phy_config =
-                           le32_to_cpup((const uint32_t *)tlv_data);
+                           le32toh(*(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;
@@ -839,7 +831,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                                error = EINVAL;
                                goto parse_out;
                        }
-                       paging_mem_size = le32_to_cpup((const uint32_t 
*)tlv_data);
+                       paging_mem_size = le32toh(*(const uint32_t *)tlv_data);
 
                        IWM_DPRINTF(sc, IWM_DEBUG_FIRMWARE_TLV,
                            "%s: Paging: paging enabled (size = %u bytes)\n",
@@ -872,7 +864,7 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                                goto parse_out;
                        }
                        capa->n_scan_channels =
-                           le32_to_cpup((const uint32_t *)tlv_data);
+                           le32toh(*(const uint32_t *)tlv_data);
                        break;
 
                case IWM_UCODE_TLV_FW_VERSION:
@@ -897,6 +889,9 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode
                        error = EINVAL;
                        goto parse_out;
                }
+
+               len -= roundup(tlv_len, 4);
+               data += roundup(tlv_len, 4);
        }
 
        KASSERT(error == 0, ("unhandled error"));
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to