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;
 
_______________________________________________
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