mac80211: support max channel switch time element
authorSara Sharon <sara.sharon@intel.com>
Wed, 6 Feb 2019 11:17:09 +0000 (13:17 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 22 Feb 2019 12:42:54 +0000 (13:42 +0100)
2018 REVmd of the spec introduces the max channel switch time
element which is optionally included in beacons/probes when there
is a channel switch / extended channel switch element.
The value represents the maximum delay between the time the AP
transmitted the last beacon in current channel and the expected
time of the first beacon in the new channel, in TU.

Parse the value and pass it to the driver.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/linux/ieee80211.h
include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/spectmgmt.c
net/mac80211/util.c

index 6cbaed4d7a6b3c0005843d9acb94ee74c98e77a7..d9650ae2b4f7f374b9c39dc4f594a68d45f449db 100644 (file)
@@ -2475,6 +2475,7 @@ enum ieee80211_eid_ext {
        WLAN_EID_EXT_HE_OPERATION = 36,
        WLAN_EID_EXT_UORA = 37,
        WLAN_EID_EXT_HE_MU_EDCA = 38,
+       WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME = 52,
        WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION = 55,
 };
 
index 97aed7b1ba5da5c84379b970d645fd03bce09ee7..3fb38d2bdb4fc4456c8da0b45673256e309fd55b 100644 (file)
@@ -1519,6 +1519,9 @@ struct ieee80211_conf {
  *     scheduled channel switch, as indicated by the AP.
  * @chandef: the new channel to switch to
  * @count: the number of TBTT's until the channel switch event
+ * @delay: maximum delay between the time the AP transmitted the last beacon in
+  *    current channel and the expected time of the first beacon in the new
+  *    channel, expressed in TU.
  */
 struct ieee80211_channel_switch {
        u64 timestamp;
@@ -1526,6 +1529,7 @@ struct ieee80211_channel_switch {
        bool block_tx;
        struct cfg80211_chan_def chandef;
        u8 count;
+       u32 delay;
 };
 
 /**
index afce50da6fd6f59e133d39b47b772f4e23a1c671..e170f986d226891542bb351d6d3ea30dde44fb7b 100644 (file)
@@ -1453,6 +1453,7 @@ struct ieee80211_csa_ie {
        u8 ttl;
        u16 pre_value;
        u16 reason_code;
+       u32 max_switch_time;
 };
 
 /* Parsed Information Elements */
@@ -1493,6 +1494,7 @@ struct ieee802_11_elems {
        const struct ieee80211_channel_sw_ie *ch_switch_ie;
        const struct ieee80211_ext_chansw_ie *ext_chansw_ie;
        const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
+       const u8 *max_channel_switch_time;
        const u8 *country_elem;
        const u8 *pwr_constr_elem;
        const u8 *cisco_dtpc_elem;
index df5d4b90616db430e0253109b8ad5e698f9c7b49..1b4938d100d548aba3422a2a4b33c8bcf2d5f364 100644 (file)
@@ -1352,6 +1352,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
        ch_switch.block_tx = csa_ie.mode;
        ch_switch.chandef = csa_ie.chandef;
        ch_switch.count = csa_ie.count;
+       ch_switch.delay = csa_ie.max_switch_time;
 
        if (drv_pre_channel_switch(sdata, &ch_switch)) {
                sdata_info(sdata,
index 4e4902bdbef8c38f4bb97487f12b1225fca612bb..3c644f14dd5915d49e21384d5577bb879ea763fe 100644 (file)
@@ -177,6 +177,12 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
                csa_ie->chandef = new_vht_chandef;
        }
 
+       if (elems->max_channel_switch_time)
+               csa_ie->max_switch_time =
+                       (elems->max_channel_switch_time[0] << 0) |
+                       (elems->max_channel_switch_time[1] <<  8) |
+                       (elems->max_channel_switch_time[2] << 16);
+
        return 0;
 }
 
index 8349c91250ef4119580c20c27971de2d238b9ca9..3f5a704d1ab01c696597b7769bdcfb732b96955f 100644 (file)
@@ -1274,6 +1274,10 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
                                elems->he_operation = (void *)&pos[1];
                        } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
                                elems->uora_element = (void *)&pos[1];
+                       } else if (pos[0] ==
+                                  WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME &&
+                                  elen == 4) {
+                               elems->max_channel_switch_time = pos + 1;
                        } else if (pos[0] ==
                                   WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
                                   elen == 3) {