-/* $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 <info@genua.de>
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);
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;
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;
}
+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 */
#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)
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 +
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;
-/* $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,
#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
#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)
#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