diff options
author | Stefan Sperling <stsp@cvs.openbsd.org> | 2019-11-08 16:42:12 +0000 |
---|---|---|
committer | Stefan Sperling <stsp@cvs.openbsd.org> | 2019-11-08 16:42:12 +0000 |
commit | 47a3d9093cddc470ff7af3784a92ae2acacc64cb (patch) | |
tree | 4dcedfae5943df04a6a8d0c5c1c6efd47d18d6a3 | |
parent | 2500f9f7e01ddcb2e853e073281dec28d71e4646 (diff) |
Add support to iwm(4) for new umac scan API in newer firmware versions.
Tested by phessler@, Tracey Emery, and myself on 8260 and 8265.
-rw-r--r-- | sys/dev/pci/if_iwm.c | 234 | ||||
-rw-r--r-- | sys/dev/pci/if_iwmreg.h | 188 |
2 files changed, 352 insertions, 70 deletions
diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c index 8398ffed599..2250acb0afe 100644 --- a/sys/dev/pci/if_iwm.c +++ b/sys/dev/pci/if_iwm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwm.c,v 1.278 2019/11/08 16:41:14 stsp Exp $ */ +/* $OpenBSD: if_iwm.c,v 1.279 2019/11/08 16:42:11 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh <info@genua.de> @@ -546,7 +546,9 @@ iwm_firmware_store_section(struct iwm_softc *sc, enum iwm_ucode_type type, return 0; } -#define IWM_DEFAULT_SCAN_CHANNELS 40 +#define IWM_DEFAULT_SCAN_CHANNELS 40 +/* Newer firmware might support more channels. Raise this value if needed. */ +#define IWM_MAX_SCAN_CHANNELS 52 /* as of 8265-34 firmware image */ struct iwm_tlv_calib_data { uint32_t ucode_type; @@ -837,6 +839,10 @@ iwm_read_firmware(struct iwm_softc *sc, enum iwm_ucode_type ucode_type) } sc->sc_capa_n_scan_channels = le32toh(*(uint32_t *)tlv_data); + if (sc->sc_capa_n_scan_channels > IWM_MAX_SCAN_CHANNELS) { + err = ERANGE; + goto parse_out; + } break; case IWM_UCODE_TLV_FW_VERSION: @@ -4943,6 +4949,24 @@ iwm_umac_scan_fill_channels(struct iwm_softc *sc, } int +iwm_fill_probe_req_v1(struct iwm_softc *sc, struct iwm_scan_probe_req_v1 *preq1) +{ + struct iwm_scan_probe_req preq2; + int err, i; + + err = iwm_fill_probe_req(sc, &preq2); + if (err) + return err; + + preq1->mac_header = preq2.mac_header; + for (i = 0; i < nitems(preq1->band_data); i++) + preq1->band_data[i] = preq2.band_data[i]; + preq1->common_data = preq2.common_data; + memcpy(preq1->buf, preq2.buf, sizeof(preq1->buf)); + return 0; +} + +int iwm_fill_probe_req(struct iwm_softc *sc, struct iwm_scan_probe_req *preq) { struct ieee80211com *ic = &sc->sc_ic; @@ -5046,12 +5070,13 @@ iwm_lmac_scan(struct iwm_softc *sc, int bgscan) .flags = 0, }; struct iwm_scan_req_lmac *req; + struct iwm_scan_probe_req_v1 *preq; size_t req_len; int err, async = bgscan; 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->sc_capa_n_scan_channels) + sizeof(struct iwm_scan_probe_req_v1); if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE) return ENOMEM; req = malloc(req_len, M_DEVBUF, @@ -5124,10 +5149,10 @@ iwm_lmac_scan(struct iwm_softc *sc, int bgscan) (struct iwm_scan_channel_cfg_lmac *)req->data, ic->ic_des_esslen != 0, bgscan); - err = iwm_fill_probe_req(sc, - (struct iwm_scan_probe_req *)(req->data + - (sizeof(struct iwm_scan_channel_cfg_lmac) * - sc->sc_capa_n_scan_channels))); + preq = (struct iwm_scan_probe_req_v1 *)(req->data + + (sizeof(struct iwm_scan_channel_cfg_lmac) * + sc->sc_capa_n_scan_channels)); + err = iwm_fill_probe_req_v1(sc, preq); if (err) { free(req, M_DEVBUF, req_len); return err; @@ -5188,9 +5213,7 @@ iwm_config_umac_scan(struct iwm_softc *sc) IEEE80211_ADDR_COPY(scan_config->mac_addr, sc->sc_ic.ic_myaddr); scan_config->bcast_sta_id = IWM_AUX_STA_ID; - scan_config->channel_flags = IWM_CHANNEL_FLAG_EBS | - IWM_CHANNEL_FLAG_ACCURATE_EBS | IWM_CHANNEL_FLAG_EBS_ADD | - IWM_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE; + scan_config->channel_flags = 0; for (c = &ic->ic_channels[1], nchan = 0; c <= &ic->ic_channels[IEEE80211_CHAN_MAX] && @@ -5222,6 +5245,72 @@ iwm_config_umac_scan(struct iwm_softc *sc) } int +iwm_umac_scan_size(struct iwm_softc *sc) +{ + int base_size = IWM_SCAN_REQ_UMAC_SIZE_V1; + int tail_size; + + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) + base_size = IWM_SCAN_REQ_UMAC_SIZE_V8; + else if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) + base_size = IWM_SCAN_REQ_UMAC_SIZE_V7; +#ifdef notyet + else if (sc->sc_device_family >= IWM_DEVICE_FAMILY_22000) + base_size = IWM_SCAN_REQ_UMAC_SIZE_V6; +#endif + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) + tail_size = sizeof(struct iwm_scan_req_umac_tail_v2); + else + tail_size = sizeof(struct iwm_scan_req_umac_tail_v1); + + return base_size + sizeof(struct iwm_scan_channel_cfg_umac) * + sc->sc_capa_n_scan_channels + tail_size; +} + +struct iwm_scan_umac_chan_param * +iwm_get_scan_req_umac_chan_param(struct iwm_softc *sc, + struct iwm_scan_req_umac *req) +{ + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) + return &req->v8.channel; + + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) + return &req->v7.channel; +#ifdef notyet + if (sc->sc_device_family >= IWM_DEVICE_FAMILY_22000) + return &req->v6.channel; +#endif + return &req->v1.channel; +} + +void * +iwm_get_scan_req_umac_data(struct iwm_softc *sc, struct iwm_scan_req_umac *req) +{ + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) + return (void *)&req->v8.data; + + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) + return (void *)&req->v7.data; +#ifdef notyet + if (sc->sc_device_family >= IWM_DEVICE_FAMILY_22000) + return (void *)&req->v6.data; +#endif + return (void *)&req->v1.data; + +} + +/* adaptive dwell max budget time [TU] for full scan */ +#define IWM_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300 +/* adaptive dwell max budget time [TU] for directed scan */ +#define IWM_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100 +/* adaptive dwell default high band APs number */ +#define IWM_SCAN_ADWELL_DEFAULT_HB_N_APS 8 +/* adaptive dwell default low band APs number */ +#define IWM_SCAN_ADWELL_DEFAULT_LB_N_APS 2 +/* adaptive dwell default APs number in social channels (1, 6, 11) */ +#define IWM_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10 + +int iwm_umac_scan(struct iwm_softc *sc, int bgscan) { struct ieee80211com *ic = &sc->sc_ic; @@ -5229,19 +5318,21 @@ iwm_umac_scan(struct iwm_softc *sc, int bgscan) .id = iwm_cmd_id(IWM_SCAN_REQ_UMAC, IWM_LONG_GROUP, 0), .len = { 0, }, .data = { NULL, }, - .flags =0, + .flags = 0, }; struct iwm_scan_req_umac *req; - struct iwm_scan_req_umac_tail *tail; + void *cmd_data, *tail_data; + struct iwm_scan_req_umac_tail_v2 *tail; + struct iwm_scan_req_umac_tail_v1 *tailv1; + struct iwm_scan_umac_chan_param *chanparam; size_t req_len; int err, async = bgscan; - req_len = sizeof(struct iwm_scan_req_umac) + - (sizeof(struct iwm_scan_channel_cfg_umac) * - sc->sc_capa_n_scan_channels) + - sizeof(struct iwm_scan_req_umac_tail); - if (req_len > IWM_MAX_CMD_PAYLOAD_SIZE) - return ENOMEM; + req_len = iwm_umac_scan_size(sc); + if ((req_len < IWM_SCAN_REQ_UMAC_SIZE_V1 + + sizeof(struct iwm_scan_req_umac_tail_v1)) || + req_len > IWM_MAX_CMD_PAYLOAD_SIZE) + return ERANGE; req = malloc(req_len, M_DEVBUF, (async ? M_NOWAIT : M_WAIT) | M_CANFAIL | M_ZERO); if (req == NULL) @@ -5251,40 +5342,88 @@ iwm_umac_scan(struct iwm_softc *sc, int bgscan) hcmd.data[0] = (void *)req; hcmd.flags |= async ? IWM_CMD_ASYNC : 0; - /* These timings correspond to iwlwifi's UNASSOC scan. */ - req->active_dwell = 10; - req->passive_dwell = 110; - req->fragmented_dwell = 44; - req->extended_dwell = 90; - if (bgscan) { - req->max_out_time = htole32(120); - req->suspend_time = htole32(120); + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) { + req->v7.adwell_default_n_aps_social = + IWM_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL; + req->v7.adwell_default_n_aps = + IWM_SCAN_ADWELL_DEFAULT_LB_N_APS; + + if (ic->ic_des_esslen != 0) + req->v7.adwell_max_budget = + htole16(IWM_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN); + else + req->v7.adwell_max_budget = + htole16(IWM_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN); + + req->v7.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); + req->v7.max_out_time[IWM_SCAN_LB_LMAC_IDX] = 0; + req->v7.suspend_time[IWM_SCAN_LB_LMAC_IDX] = 0; + + if (isset(sc->sc_ucode_api, + IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) { + req->v8.active_dwell[IWM_SCAN_LB_LMAC_IDX] = 10; + req->v8.passive_dwell[IWM_SCAN_LB_LMAC_IDX] = 110; + } else { + req->v7.active_dwell = 10; + req->v7.passive_dwell = 110; + req->v7.fragmented_dwell = 44; + } } else { - req->max_out_time = htole32(0); - req->suspend_time = htole32(0); + /* These timings correspond to iwlwifi's UNASSOC scan. */ + req->v1.active_dwell = 10; + req->v1.passive_dwell = 110; + req->v1.fragmented_dwell = 44; + req->v1.extended_dwell = 90; } - req->scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); + if (bgscan) { + const uint32_t timeout = htole32(120); + if (isset(sc->sc_ucode_api, + IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2)) { + req->v8.max_out_time[IWM_SCAN_LB_LMAC_IDX] = timeout; + req->v8.suspend_time[IWM_SCAN_LB_LMAC_IDX] = timeout; + } else if (isset(sc->sc_ucode_api, + IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) { + req->v7.max_out_time[IWM_SCAN_LB_LMAC_IDX] = timeout; + req->v7.suspend_time[IWM_SCAN_LB_LMAC_IDX] = timeout; + } else { + req->v1.max_out_time = timeout; + req->v1.suspend_time = timeout; + } + } + + req->v1.scan_priority = htole32(IWM_SCAN_PRIORITY_HIGH); req->ooc_priority = htole32(IWM_SCAN_PRIORITY_HIGH); - req->n_channels = iwm_umac_scan_fill_channels(sc, - (struct iwm_scan_channel_cfg_umac *)req->data, + cmd_data = iwm_get_scan_req_umac_data(sc, req); + chanparam = iwm_get_scan_req_umac_chan_param(sc, req); + chanparam->count = iwm_umac_scan_fill_channels(sc, + (struct iwm_scan_channel_cfg_umac *)cmd_data, ic->ic_des_esslen != 0, bgscan); + chanparam->flags = 0; - req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL | - IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE | - IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL); + tail_data = cmd_data + sizeof(struct iwm_scan_channel_cfg_umac) * + sc->sc_capa_n_scan_channels; + tail = tail_data; + /* tail v1 layout differs in preq and direct_scan member fields. */ + tailv1 = tail_data; - tail = (void *)&req->data + - sizeof(struct iwm_scan_channel_cfg_umac) * - sc->sc_capa_n_scan_channels; + req->general_flags = htole32(IWM_UMAC_SCAN_GEN_FLAGS_PASS_ALL | + IWM_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE); /* Check if we're doing an active directed scan. */ if (ic->ic_des_esslen != 0) { - tail->direct_scan[0].id = IEEE80211_ELEMID_SSID; - tail->direct_scan[0].len = ic->ic_des_esslen; - memcpy(tail->direct_scan[0].ssid, ic->ic_des_essid, - ic->ic_des_esslen); + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) { + tail->direct_scan[0].id = IEEE80211_ELEMID_SSID; + tail->direct_scan[0].len = ic->ic_des_esslen; + memcpy(tail->direct_scan[0].ssid, ic->ic_des_essid, + ic->ic_des_esslen); + } else { + tailv1->direct_scan[0].id = IEEE80211_ELEMID_SSID; + tailv1->direct_scan[0].len = ic->ic_des_esslen; + memcpy(tailv1->direct_scan[0].ssid, ic->ic_des_essid, + ic->ic_des_esslen); + } req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT); } else @@ -5295,7 +5434,18 @@ iwm_umac_scan(struct iwm_softc *sc, int bgscan) req->general_flags |= htole32(IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED); - err = iwm_fill_probe_req(sc, &tail->preq); + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_ADAPTIVE_DWELL)) { + req->general_flags |= + htole32(IWM_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL); + } else { + req->general_flags |= + htole32(IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL); + } + + if (isset(sc->sc_ucode_api, IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER)) + err = iwm_fill_probe_req(sc, &tail->preq); + else + err = iwm_fill_probe_req_v1(sc, &tailv1->preq); if (err) { free(req, M_DEVBUF, req_len); return err; diff --git a/sys/dev/pci/if_iwmreg.h b/sys/dev/pci/if_iwmreg.h index 30f25f2f149..ebdbb2114ca 100644 --- a/sys/dev/pci/if_iwmreg.h +++ b/sys/dev/pci/if_iwmreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwmreg.h,v 1.41 2019/11/08 16:41:15 stsp Exp $ */ +/* $OpenBSD: if_iwmreg.h,v 1.42 2019/11/08 16:42:11 stsp Exp $ */ /****************************************************************************** * @@ -639,6 +639,8 @@ #define IWM_UCODE_TLV_API_NAN2_VER2 31 #define IWM_UCODE_TLV_API_ADAPTIVE_DWELL 32 #define IWM_UCODE_TLV_API_NEW_RX_STATS 35 +#define IWM_UCODE_TLV_API_ADAPTIVE_DWELL_V2 42 +#define IWM_UCODE_TLV_API_SCAN_EXT_CHAN_VER 58 #define IWM_NUM_UCODE_TLV_API 128 #define IWM_UCODE_TLV_API_BITS \ @@ -4863,13 +4865,27 @@ struct iwm_scan_probe_segment { * @common_data: last (and common) part of the probe * @buf: raw data block */ -struct iwm_scan_probe_req { +struct iwm_scan_probe_req_v1 { struct iwm_scan_probe_segment mac_header; struct iwm_scan_probe_segment band_data[2]; struct iwm_scan_probe_segment common_data; uint8_t buf[IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE]; } __packed; +/* iwl_scan_probe_req - PROBE_REQUEST_FRAME_API_S_VER_v2 + * @mac_header: first (and common) part of the probe + * @band_data: band specific data + * @common_data: last (and common) part of the probe + * @buf: raw data block + */ +struct iwm_scan_probe_req { + struct iwm_scan_probe_segment mac_header; + struct iwm_scan_probe_segment band_data[3]; + struct iwm_scan_probe_segment common_data; + uint8_t buf[IWM_SCAN_OFFLOAD_PROBE_REQ_SIZE]; +} __packed; + + #define IWM_SCAN_CHANNEL_FLAG_EBS (1 << 0) #define IWM_SCAN_CHANNEL_FLAG_EBS_ACCURATE (1 << 1) #define IWM_SCAN_CHANNEL_FLAG_CACHE_ADD (1 << 2) @@ -5205,6 +5221,14 @@ struct iwm_scan_config { #define IWM_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED (1 << 8) #define IWM_UMAC_SCAN_GEN_FLAGS_MATCH (1 << 9) #define IWM_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL (1 << 10) +/* Extended dwell is obselete when adaptive dwell is used, making this + * bit reusable. Hence, probe request defer is used only when adaptive + * dwell is supported. */ +#define IWM_UMAC_SCAN_GEN_FLAGS_PROB_REQ_DEFER_SUPP (1 << 10) +#define IWM_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED (1 << 11) +#define IWM_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL (1 << 13) +#define IWM_UMAC_SCAN_GEN_FLAGS_MAX_CHNL_TIME (1 << 14) +#define IWM_UMAC_SCAN_GEN_FLAGS_PROB_REQ_HIGH_TX_RATE (1 << 15) /** * struct iwm_scan_channel_cfg_umac @@ -5241,32 +5265,77 @@ struct iwm_scan_umac_schedule { * @preq: probe request with IEs blocks * @direct_scan: list of SSIDs for directed active scan */ -struct iwm_scan_req_umac_tail { +struct iwm_scan_req_umac_tail_v1 { /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ struct iwm_scan_umac_schedule schedule[IWM_MAX_SCHED_SCAN_PLANS]; uint16_t delay; uint16_t reserved; /* SCAN_PROBE_PARAMS_API_S_VER_1 */ + struct iwm_scan_probe_req_v1 preq; + struct iwm_ssid_ie direct_scan[IWM_PROBE_OPTION_MAX]; +} __packed; + +/** + * struct iwm_scan_req_umac_tail - the rest of the UMAC scan request command + * parameters following channels configuration array. + * @schedule: two scheduling plans. + * @delay: delay in TUs before starting the first scan iteration + * @reserved: for future use and alignment + * @preq: probe request with IEs blocks + * @direct_scan: list of SSIDs for directed active scan + */ +struct iwm_scan_req_umac_tail_v2 { + /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ + struct iwm_scan_umac_schedule schedule[IWM_MAX_SCHED_SCAN_PLANS]; + uint16_t delay; + uint16_t reserved; + /* SCAN_PROBE_PARAMS_API_S_VER_2 */ struct iwm_scan_probe_req preq; struct iwm_ssid_ie direct_scan[IWM_PROBE_OPTION_MAX]; } __packed; /** + * struct iwm_scan_umac_chan_param + * @flags: channel flags &enum iwl_scan_channel_flags + * @count: num of channels in scan request + * @reserved: for future use and alignment + */ +struct iwm_scan_umac_chan_param { + uint8_t flags; + uint8_t count; + uint16_t reserved; +} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */ + +#define IWM_SCAN_LB_LMAC_IDX 0 +#define IWM_SCAN_HB_LMAC_IDX 1 + +/** * struct iwm_scan_req_umac - * @flags: &enum iwm_umac_scan_flags - * @uid: scan id, &enum iwm_umac_scan_uid_offsets - * @ooc_priority: out of channel priority - &enum iwm_scan_priority - * @general_flags: &enum iwm_umac_scan_general_flags + * @flags: &enum iwl_umac_scan_flags + * @uid: scan id, &enum iwl_umac_scan_uid_offsets + * @ooc_priority: out of channel priority - &enum iwl_scan_priority + * @general_flags: &enum iwl_umac_scan_general_flags + * @scan_start_mac_id: report the scan start TSF time according to this mac TSF * @extended_dwell: dwell time for channels 1, 6 and 11 - * @active_dwell: dwell time for active scan - * @passive_dwell: dwell time for passive scan + * @active_dwell: dwell time for active scan per LMAC + * @passive_dwell: dwell time for passive scan per LMAC * @fragmented_dwell: dwell time for fragmented passive scan - * @max_out_time: max out of serving channel time - * @suspend_time: max suspend time - * @scan_priority: scan internal prioritization &enum iwm_scan_priority - * @channel_flags: &enum iwm_scan_channel_flags - * @n_channels: num of channels in scan request + * @adwell_default_n_aps: for adaptive dwell the default number of APs + * per channel + * @adwell_default_n_aps_social: for adaptive dwell the default + * number of APs per social (1,6,11) channel + * @general_flags2: &enum iwl_umac_scan_general_flags2 + * @adwell_max_budget: for adaptive dwell the maximal budget of TU to be added + * to total scan time + * @max_out_time: max out of serving channel time, per LMAC - for CDB there + * are 2 LMACs (high band and low band) + * @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs + * @scan_priority: scan internal prioritization &enum iwl_scan_priority + * @num_of_fragments: Number of fragments needed for full coverage per band. + * Relevant only for fragmented scan. + * @channel: &struct iwm_scan_umac_chan_param * @reserved: for future use and alignment + * @reserved3: for future use and alignment * @data: &struct iwm_scan_channel_cfg_umac and * &struct iwm_scan_req_umac_tail */ @@ -5275,20 +5344,83 @@ struct iwm_scan_req_umac { uint32_t uid; uint32_t ooc_priority; /* SCAN_GENERAL_PARAMS_API_S_VER_1 */ - uint32_t general_flags; - uint8_t extended_dwell; - uint8_t active_dwell; - uint8_t passive_dwell; - uint8_t fragmented_dwell; - uint32_t max_out_time; - uint32_t suspend_time; - uint32_t scan_priority; - /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */ - uint8_t channel_flags; - uint8_t n_channels; - uint16_t reserved; - uint8_t data[]; -} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */ + uint16_t general_flags; + uint8_t reserved; + uint8_t scan_start_mac_id; + union { + struct { + uint8_t extended_dwell; + uint8_t active_dwell; + uint8_t passive_dwell; + uint8_t fragmented_dwell; + uint32_t max_out_time; + uint32_t suspend_time; + uint32_t scan_priority; + struct iwm_scan_umac_chan_param channel; + uint8_t data[]; + } v1; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */ + struct { + uint8_t extended_dwell; + uint8_t active_dwell; + uint8_t passive_dwell; + uint8_t fragmented_dwell; + uint32_t max_out_time[2]; + uint32_t suspend_time[2]; + uint32_t scan_priority; + struct iwm_scan_umac_chan_param channel; + uint8_t data[]; + } v6; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_6 */ + struct { + uint8_t active_dwell; + uint8_t passive_dwell; + uint8_t fragmented_dwell; + uint8_t adwell_default_n_aps; + uint8_t adwell_default_n_aps_social; + uint8_t reserved3; + uint16_t adwell_max_budget; + uint32_t max_out_time[2]; + uint32_t suspend_time[2]; + uint32_t scan_priority; + struct iwm_scan_umac_chan_param channel; + uint8_t data[]; + } v7; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_7 */ + struct { + uint8_t active_dwell[2]; + uint8_t reserved2; + uint8_t adwell_default_n_aps; + uint8_t adwell_default_n_aps_social; + uint8_t general_flags2; + uint16_t adwell_max_budget; + uint32_t max_out_time[2]; + uint32_t suspend_time[2]; + uint32_t scan_priority; + uint8_t passive_dwell[2]; + uint8_t num_of_fragments[2]; + struct iwm_scan_umac_chan_param channel; + uint8_t data[]; + } v8; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_8 */ + struct { + uint8_t active_dwell[2]; + uint8_t adwell_default_hb_n_aps; + uint8_t adwell_default_lb_n_aps; + uint8_t adwell_default_n_aps_social; + uint8_t general_flags2; + uint16_t adwell_max_budget; + uint32_t max_out_time[2]; + uint32_t suspend_time[2]; + uint32_t scan_priority; + uint8_t passive_dwell[2]; + uint8_t num_of_fragments[2]; + struct iwm_scan_umac_chan_param channel; + uint8_t data[]; + } v9; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_9 */ + }; +} __packed; + +#define IWM_SCAN_REQ_UMAC_SIZE_V8 sizeof(struct iwm_scan_req_umac) +#define IWM_SCAN_REQ_UMAC_SIZE_V7 48 +#define IWM_SCAN_REQ_UMAC_SIZE_V6 44 +#define IWM_SCAN_REQ_UMAC_SIZE_V1 36 /** * struct iwm_umac_scan_abort |