From: stsp Date: Thu, 29 Jul 2021 11:57:59 +0000 (+0000) Subject: Add support for iwx(4) umac scan command version 14. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=80a2d57832d29728892186ca293e7c6fcbaf1d03;p=openbsd Add support for iwx(4) umac scan command version 14. ok kevlo@ --- diff --git a/sys/dev/pci/if_iwx.c b/sys/dev/pci/if_iwx.c index e56dd6f643d..46017d37cda 100644 --- a/sys/dev/pci/if_iwx.c +++ b/sys/dev/pci/if_iwx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwx.c,v 1.80 2021/07/29 11:57:33 stsp Exp $ */ +/* $OpenBSD: if_iwx.c,v 1.81 2021/07/29 11:57:59 stsp Exp $ */ /* * Copyright (c) 2014, 2016 genua gmbh @@ -394,6 +394,14 @@ int iwx_rm_sta_cmd(struct iwx_softc *, struct iwx_node *); int iwx_fill_probe_req(struct iwx_softc *, struct iwx_scan_probe_req *); int iwx_config_umac_scan_reduced(struct iwx_softc *); int iwx_config_umac_scan(struct iwx_softc *); +uint16_t iwx_scan_umac_flags_v2(struct iwx_softc *, int); +void iwx_scan_umac_dwell_v10(struct iwx_softc *, + struct iwx_scan_general_params_v10 *, int); +void iwx_scan_umac_fill_general_p_v10(struct iwx_softc *, + struct iwx_scan_general_params_v10 *, uint16_t, int); +void iwx_scan_umac_fill_ch_p_v6(struct iwx_softc *, + struct iwx_scan_channel_params_v6 *, uint32_t, int, int); +int iwx_umac_scan_v14(struct iwx_softc *, int); int iwx_umac_scan(struct iwx_softc *, int); void iwx_mcc_update(struct iwx_softc *, struct iwx_mcc_chub_notif *); uint8_t iwx_ridx2rate(struct ieee80211_rateset *, int); @@ -5438,7 +5446,8 @@ iwx_rm_sta_cmd(struct iwx_softc *sc, struct iwx_node *in) uint8_t iwx_umac_scan_fill_channels(struct iwx_softc *sc, - struct iwx_scan_channel_cfg_umac *chan, int n_ssids, int bgscan) + struct iwx_scan_channel_cfg_umac *chan, size_t chan_nitems, + int n_ssids, int bgscan) { struct ieee80211com *ic = &sc->sc_ic; struct ieee80211_channel *c; @@ -5446,6 +5455,7 @@ iwx_umac_scan_fill_channels(struct iwx_softc *sc, for (nchan = 0, c = &ic->ic_channels[1]; c <= &ic->ic_channels[IEEE80211_CHAN_MAX] && + nchan < chan_nitems && nchan < sc->sc_capa_n_scan_channels; c++) { uint8_t channel_num; @@ -5764,6 +5774,25 @@ iwx_get_scan_req_umac_data(struct iwx_softc *sc, struct iwx_scan_req_umac *req) } +uint16_t +iwx_scan_umac_flags_v2(struct iwx_softc *sc, int bgscan) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint16_t flags = 0; + + if (ic->ic_des_esslen == 0) + flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_FORCE_PASSIVE; + + flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_PASS_ALL; + flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_NTFY_ITER_COMPLETE; + flags |= IWX_UMAC_SCAN_GEN_FLAGS_V2_ADAPTIVE_DWELL; + + return flags; +} + +#define IWX_SCAN_DWELL_ACTIVE 10 +#define IWX_SCAN_DWELL_PASSIVE 110 + /* adaptive dwell max budget time [TU] for full scan */ #define IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300 /* adaptive dwell max budget time [TU] for directed scan */ @@ -5774,6 +5803,143 @@ iwx_get_scan_req_umac_data(struct iwx_softc *sc, struct iwx_scan_req_umac *req) #define IWX_SCAN_ADWELL_DEFAULT_LB_N_APS 2 /* adaptive dwell default APs number in social channels (1, 6, 11) */ #define IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10 +/* adaptive dwell number of APs override for p2p friendly GO channels */ +#define IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY 10 +/* adaptive dwell number of APs override for social channels */ +#define IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS 2 + +void +iwx_scan_umac_dwell_v10(struct iwx_softc *sc, + struct iwx_scan_general_params_v10 *general_params, int bgscan) +{ + uint32_t suspend_time, max_out_time; + uint8_t active_dwell, passive_dwell; + + active_dwell = IWX_SCAN_DWELL_ACTIVE; + passive_dwell = IWX_SCAN_DWELL_PASSIVE; + + general_params->adwell_default_social_chn = + IWX_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL; + general_params->adwell_default_2g = IWX_SCAN_ADWELL_DEFAULT_LB_N_APS; + general_params->adwell_default_5g = IWX_SCAN_ADWELL_DEFAULT_HB_N_APS; + + if (bgscan) + general_params->adwell_max_budget = + htole16(IWX_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN); + else + general_params->adwell_max_budget = + htole16(IWX_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN); + + general_params->scan_priority = htole32(IWX_SCAN_PRIORITY_EXT_6); + if (bgscan) { + max_out_time = htole32(120); + suspend_time = htole32(120); + } else { + max_out_time = htole32(0); + suspend_time = htole32(0); + } + general_params->max_out_of_time[IWX_SCAN_LB_LMAC_IDX] = + htole32(max_out_time); + general_params->suspend_time[IWX_SCAN_LB_LMAC_IDX] = + htole32(suspend_time); + general_params->max_out_of_time[IWX_SCAN_HB_LMAC_IDX] = + htole32(max_out_time); + general_params->suspend_time[IWX_SCAN_HB_LMAC_IDX] = + htole32(suspend_time); + + general_params->active_dwell[IWX_SCAN_LB_LMAC_IDX] = active_dwell; + general_params->passive_dwell[IWX_SCAN_LB_LMAC_IDX] = passive_dwell; + general_params->active_dwell[IWX_SCAN_HB_LMAC_IDX] = active_dwell; + general_params->passive_dwell[IWX_SCAN_HB_LMAC_IDX] = passive_dwell; +} + +void +iwx_scan_umac_fill_general_p_v10(struct iwx_softc *sc, + struct iwx_scan_general_params_v10 *gp, uint16_t gen_flags, int bgscan) +{ + iwx_scan_umac_dwell_v10(sc, gp, bgscan); + + gp->flags = htole16(gen_flags); + + if (gen_flags & IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC1) + gp->num_of_fragments[IWX_SCAN_LB_LMAC_IDX] = 3; + if (gen_flags & IWX_UMAC_SCAN_GEN_FLAGS_V2_FRAGMENTED_LMAC2) + gp->num_of_fragments[IWX_SCAN_HB_LMAC_IDX] = 3; + + gp->scan_start_mac_id = 0; +} + +void +iwx_scan_umac_fill_ch_p_v6(struct iwx_softc *sc, + struct iwx_scan_channel_params_v6 *cp, uint32_t channel_cfg_flags, + int n_ssid, int bgscan) +{ + cp->flags = IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER; + + cp->count = iwx_umac_scan_fill_channels(sc, cp->channel_config, + nitems(cp->channel_config), n_ssid, bgscan); + + cp->n_aps_override[0] = IWX_SCAN_ADWELL_N_APS_GO_FRIENDLY; + cp->n_aps_override[1] = IWX_SCAN_ADWELL_N_APS_SOCIAL_CHS; +} + +int +iwx_umac_scan_v14(struct iwx_softc *sc, int bgscan) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct iwx_host_cmd hcmd = { + .id = iwx_cmd_id(IWX_SCAN_REQ_UMAC, IWX_LONG_GROUP, 0), + .len = { 0, }, + .data = { NULL, }, + .flags = 0, + }; + struct iwx_scan_req_umac_v14 *cmd; + struct iwx_scan_req_params_v14 *scan_p; + int err, async = bgscan, n_ssid = 0; + uint16_t gen_flags; + uint32_t bitmap_ssid = 0; + + cmd = malloc(sizeof(*cmd), M_DEVBUF, + (async ? M_NOWAIT : M_WAIT) | M_CANFAIL | M_ZERO); + if (cmd == NULL) + return ENOMEM; + + scan_p = &cmd->scan_params; + + cmd->ooc_priority = htole32(IWX_SCAN_PRIORITY_EXT_6); + cmd->uid = htole32(0); + + gen_flags = iwx_scan_umac_flags_v2(sc, bgscan); + iwx_scan_umac_fill_general_p_v10(sc, &scan_p->general_params, + gen_flags, bgscan); + + scan_p->periodic_params.schedule[0].interval = htole16(0); + scan_p->periodic_params.schedule[0].iter_count = 1; + + err = iwx_fill_probe_req(sc, &scan_p->probe_params.preq); + if (err) + return err; + + if (ic->ic_des_esslen != 0) { + scan_p->probe_params.direct_scan[0].id = IEEE80211_ELEMID_SSID; + scan_p->probe_params.direct_scan[0].len = ic->ic_des_esslen; + memcpy(scan_p->probe_params.direct_scan[0].ssid, + ic->ic_des_essid, ic->ic_des_esslen); + bitmap_ssid |= (1 << 0); + n_ssid = 1; + } + + iwx_scan_umac_fill_ch_p_v6(sc, &scan_p->channel_params, bitmap_ssid, + n_ssid, bgscan); + + hcmd.len[0] = sizeof(*cmd); + hcmd.data[0] = (void *)cmd; + hcmd.flags |= async ? IWX_CMD_ASYNC : 0; + + err = iwx_send_cmd(sc, &hcmd); + free(cmd, M_DEVBUF, sizeof(*cmd)); + return err; +} int iwx_umac_scan(struct iwx_softc *sc, int bgscan) @@ -5792,6 +5958,11 @@ iwx_umac_scan(struct iwx_softc *sc, int bgscan) struct iwx_scan_umac_chan_param *chanparam; size_t req_len; int err, async = bgscan; + int cmdver; + + cmdver = iwx_lookup_cmd_ver(sc, IWX_LONG_GROUP, IWX_SCAN_REQ_UMAC); + if (cmdver == 14) + return iwx_umac_scan_v14(sc, bgscan); req_len = iwx_umac_scan_size(sc); if ((req_len < IWX_SCAN_REQ_UMAC_SIZE_V1 + @@ -5865,6 +6036,7 @@ iwx_umac_scan(struct iwx_softc *sc, int bgscan) chanparam = iwx_get_scan_req_umac_chan_param(sc, req); chanparam->count = iwx_umac_scan_fill_channels(sc, (struct iwx_scan_channel_cfg_umac *)cmd_data, + sc->sc_capa_n_scan_channels, ic->ic_des_esslen != 0, bgscan); chanparam->flags = 0; diff --git a/sys/dev/pci/if_iwxreg.h b/sys/dev/pci/if_iwxreg.h index 36be0639010..eaaff8ec6fa 100644 --- a/sys/dev/pci/if_iwxreg.h +++ b/sys/dev/pci/if_iwxreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_iwxreg.h,v 1.25 2021/07/29 11:57:33 stsp Exp $ */ +/* $OpenBSD: if_iwxreg.h,v 1.26 2021/07/29 11:57:59 stsp Exp $ */ /*- * Based on BSD-licensed source modules in the Linux iwlwifi driver, @@ -5412,6 +5412,10 @@ struct iwx_scan_probe_req { #define IWX_SCAN_CHANNEL_FLAG_EBS (1 << 0) #define IWX_SCAN_CHANNEL_FLAG_EBS_ACCURATE (1 << 1) #define IWX_SCAN_CHANNEL_FLAG_CACHE_ADD (1 << 2) +#define IWX_SCAN_CHANNEL_FLAG_EBS_FRAG (1 << 3) +#define IWX_SCAN_CHANNEL_FLAG_FORCE_EBS (1 << 4) +#define IWX_SCAN_CHANNEL_FLAG_ENABLE_CHAN_ORDER (1 << 5) +#define IWX_SCAN_CHANNEL_FLAG_6G_PSC_NO_FILTER (1 << 6) /* iwx_scan_channel_opt - CHANNEL_OPTIMIZATION_API_S * @flags: enum iwx_scan_channel_flags @@ -5429,6 +5433,17 @@ struct iwx_scan_channel_opt { #define IWX_SCAN_PRIORITY_MEDIUM 1 #define IWX_SCAN_PRIORITY_HIGH 2 +enum iwx_scan_priority_ext { + IWX_SCAN_PRIORITY_EXT_0_LOWEST, + IWX_SCAN_PRIORITY_EXT_1, + IWX_SCAN_PRIORITY_EXT_2, + IWX_SCAN_PRIORITY_EXT_3, + IWX_SCAN_PRIORITY_EXT_4, + IWX_SCAN_PRIORITY_EXT_5, + IWX_SCAN_PRIORITY_EXT_6, + IWX_SCAN_PRIORITY_EXT_7_HIGHEST, +}; + /** * iwx_scan_offload_complete - PERIODIC_SCAN_COMPLETE_NTF_API_S_VER_2 * @last_schedule_line: last schedule line executed (fast or regular) @@ -5934,6 +5949,125 @@ struct iwx_scan_req_umac { #define IWX_SCAN_REQ_UMAC_SIZE_V6 44 #define IWX_SCAN_REQ_UMAC_SIZE_V1 36 +/** + * struct iwx_scan_general_params_v10 + * @flags: &enum iwx_umac_scan_flags + * @reserved: reserved for future + * @scan_start_mac_id: report the scan start TSF time according to this mac TSF + * @active_dwell: dwell time for active scan per LMAC + * @adwell_default_2g: adaptive dwell default number of APs + * for 2.4GHz channel + * @adwell_default_5g: adaptive dwell default number of APs + * for 5GHz channels + * @adwell_default_social_chn: adaptive dwell default number of + * APs per social channel + * @reserved1: reserved for future + * @adwell_max_budget: the maximal number of TUs that adaptive dwell + * can add to the total scan time + * @max_out_of_time: max out of serving channel time, per LMAC + * @suspend_time: max suspend time, per LMAC + * @scan_priority: priority of the request + * @passive_dwell: continues dwell time for passive channel + * (without adaptive dwell) + * @num_of_fragments: number of fragments needed for full fragmented + * scan coverage. + */ +struct iwx_scan_general_params_v10 { + uint16_t flags; + uint8_t reserved; + uint8_t scan_start_mac_id; + uint8_t active_dwell[IWX_SCAN_TWO_LMACS]; + uint8_t adwell_default_2g; + uint8_t adwell_default_5g; + uint8_t adwell_default_social_chn; + uint8_t reserved1; + uint16_t adwell_max_budget; + uint32_t max_out_of_time[IWX_SCAN_TWO_LMACS]; + uint32_t suspend_time[IWX_SCAN_TWO_LMACS]; + uint32_t scan_priority; + uint8_t passive_dwell[IWX_SCAN_TWO_LMACS]; + uint8_t num_of_fragments[IWX_SCAN_TWO_LMACS]; +} __packed; /* SCAN_GENERAL_PARAMS_API_S_VER_10 */ + +/** + * struct iwx_scan_channel_params_v6 + * @flags: channel flags &enum iwl_scan_channel_flags + * @count: num of channels in scan request + * @n_aps_override: override the number of APs the FW uses to calculate dwell + * time when adaptive dwell is used. + * Channel k will use n_aps_override[i] when BIT(20 + i) is set in + * channel_config[k].flags + * @channel_config: array of explicit channel configurations + * for 2.4Ghz and 5.2Ghz bands + */ +struct iwx_scan_channel_params_v6 { + uint8_t flags; + uint8_t count; + uint8_t n_aps_override[2]; + struct iwx_scan_channel_cfg_umac channel_config[67]; +} __packed; /* SCAN_CHANNEL_PARAMS_API_S_VER_6 */ + +/** + * struct iwx_scan_periodic_parms_v1 + * @schedule: can scheduling parameter + * @delay: initial delay of the periodic scan in seconds + * @reserved: reserved for future + */ +struct iwx_scan_periodic_parms_v1 { + struct iwx_scan_umac_schedule schedule[IWX_MAX_SCHED_SCAN_PLANS]; + uint16_t delay; + uint16_t reserved; +} __packed; /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */ + +#define IWX_SCAN_SHORT_SSID_MAX_SIZE 8 +#define IWX_SCAN_BSSID_MAX_SIZE 16 + +/** + * struct iwx_scan_probe_params_v4 + * @preq: scan probe request params + * @short_ssid_num: number of valid short SSIDs in short ssid array + * @bssid_num: number of valid bssid in bssids array + * @reserved: reserved + * @direct_scan: list of ssids + * @short_ssid: array of short ssids + * @bssid_array: array of bssids + */ +struct iwx_scan_probe_params_v4 { + struct iwx_scan_probe_req preq; + uint8_t short_ssid_num; + uint8_t bssid_num; + uint16_t reserved; + struct iwx_ssid_ie direct_scan[IWX_PROBE_OPTION_MAX]; + uint32_t short_ssid[IWX_SCAN_SHORT_SSID_MAX_SIZE]; + uint8_t bssid_array[IWX_SCAN_BSSID_MAX_SIZE][ETHER_ADDR_LEN]; +} __packed; /* SCAN_PROBE_PARAMS_API_S_VER_4 */ + +/** + * struct iwx_scan_req_params_v14 + * @general_params: &struct iwx_scan_general_params_v10 + * @channel_params: &struct iwx_scan_channel_params_v6 + * @periodic_params: &struct iwx_scan_periodic_parms_v1 + * @probe_params: &struct iwx_scan_probe_params_v4 + */ +struct iwx_scan_req_params_v14 { + struct iwx_scan_general_params_v10 general_params; + struct iwx_scan_channel_params_v6 channel_params; + struct iwx_scan_periodic_parms_v1 periodic_params; + struct iwx_scan_probe_params_v4 probe_params; +} __packed; /* SCAN_REQUEST_PARAMS_API_S_VER_14 */ + +/** + * struct iwx_scan_req_umac_v14 + * @uid: scan id, &enum iwl_umac_scan_uid_offsets + * @ooc_priority: out of channel priority - &enum iwx_scan_priority + * @scan_params: scan parameters + */ +struct iwx_scan_req_umac_v14 { + uint32_t uid; + uint32_t ooc_priority; + struct iwx_scan_req_params_v14 scan_params; +} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_14 */ + /** * struct iwx_umac_scan_abort * @uid: scan id, &enum iwx_umac_scan_uid_offsets