From owner-svn-src-head@freebsd.org Thu Mar 23 04:50:40 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 65E25D19196; Thu, 23 Mar 2017 04:50:40 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 3534D1528; Thu, 23 Mar 2017 04:50:40 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v2N4od1T006317; Thu, 23 Mar 2017 04:50:39 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v2N4odKB006314; Thu, 23 Mar 2017 04:50:39 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201703230450.v2N4odKB006314@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Thu, 23 Mar 2017 04:50:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r315784 - head/sys/dev/iwm X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Mar 2017 04:50:40 -0000 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;