Add support for iwx(4) umac scan command version 14.
authorstsp <stsp@openbsd.org>
Thu, 29 Jul 2021 11:57:59 +0000 (11:57 +0000)
committerstsp <stsp@openbsd.org>
Thu, 29 Jul 2021 11:57:59 +0000 (11:57 +0000)
ok kevlo@

sys/dev/pci/if_iwx.c
sys/dev/pci/if_iwxreg.h

index e56dd6f..46017d3 100644 (file)
@@ -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 <info@genua.de>
@@ -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;
 
index 36be063..eaaff8e 100644 (file)
@@ -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