]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: make bss_param_ch_cnt available for the low level driver
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Mon, 7 Oct 2024 12:00:48 +0000 (15:00 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 23 Oct 2024 14:43:12 +0000 (16:43 +0200)
Drivers may need to track this. Make it available for them, and maintain
the value when beacons are received.
When link X receives a beacon, iterate the RNR elements and update all
the links with their respective data.
Track the link id that updated the data so that each link can know
whether the update came from its own beacon or from another link.
In case, the update came from the link's own beacon, always update the
updater link id.
The purpose is to let the low level driver know if a link is losing its
beacons. If link X is losing its beacons, it can still track the
bss_param_ch_cnt and know where the update came from.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241007144851.e2d8d1a722ad.I04b883daba2cd48e5730659eb62ca1614c899cbb@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c

index c42ad5a0c303bf674e86fe78c31bdf27ccabd666..20562676e9cd2c06fe5c4cc097cef27bd0865ac2 100644 (file)
@@ -740,6 +740,19 @@ struct ieee80211_parsed_tpe {
  * @eht_80mhz_full_bw_ul_mumimo: in AP-mode, does this BSS support the
  *     reception of an EHT TB PPDU on an RU that spans the entire PPDU
  *     bandwidth
+ * @bss_param_ch_cnt: in BSS-mode, the BSS params change count. This
+ *     information is the latest known value. It can come from this link's
+ *     beacon or from a beacon sent by another link.
+ * @bss_param_ch_cnt_link_id: in BSS-mode, the link_id to which the beacon
+ *     that updated &bss_param_ch_cnt belongs. E.g. if link 1 doesn't hear
+ *     its beacons, and link 2 sent a beacon with an RNR element that updated
+ *     link 1's BSS params change count, then, link 1's
+ *     bss_param_ch_cnt_link_id will be 2. That means that link 1 knows that
+ *     link 2 was the link that updated its bss_param_ch_cnt value.
+ *     In case link 1 hears its beacon again, bss_param_ch_cnt_link_id will
+ *     be updated to 1, even if bss_param_ch_cnt didn't change. This allows
+ *     the link to know that it heard the latest value from its own beacon
+ *     (as opposed to hearing its value from another link's beacon).
  */
 struct ieee80211_bss_conf {
        struct ieee80211_vif *vif;
@@ -834,6 +847,8 @@ struct ieee80211_bss_conf {
        bool eht_su_beamformee;
        bool eht_mu_beamformer;
        bool eht_80mhz_full_bw_ul_mumimo;
+       u8 bss_param_ch_cnt;
+       u8 bss_param_ch_cnt_link_id;
 };
 
 /**
index afb867dc6b2460dc93948d387ea3c9357f62d09b..d884d05826d36acdc13f21652a123ec060245dce 100644 (file)
@@ -1015,8 +1015,6 @@ struct ieee80211_link_data_managed {
 
        int wmm_last_param_set;
        int mu_edca_last_param_set;
-
-       u8 bss_param_ch_cnt;
 };
 
 struct ieee80211_link_data_ap {
index 0303972c23e4cb4e8778929eb68c6a75f0f7ad6a..93a11a59339cbcc7893ddbe787aad9fef763c051 100644 (file)
@@ -2643,6 +2643,89 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
                         &ifmgd->csa_connection_drop_work);
 }
 
+struct sta_bss_param_ch_cnt_data {
+       struct ieee80211_sub_if_data *sdata;
+       u8 reporting_link_id;
+       u8 mld_id;
+};
+
+static enum cfg80211_rnr_iter_ret
+ieee80211_sta_bss_param_ch_cnt_iter(void *_data, u8 type,
+                                   const struct ieee80211_neighbor_ap_info *info,
+                                   const u8 *tbtt_info, u8 tbtt_info_len)
+{
+       struct sta_bss_param_ch_cnt_data *data = _data;
+       struct ieee80211_sub_if_data *sdata = data->sdata;
+       const struct ieee80211_tbtt_info_ge_11 *ti;
+       u8 bss_param_ch_cnt;
+       int link_id;
+
+       if (type != IEEE80211_TBTT_INFO_TYPE_TBTT)
+               return RNR_ITER_CONTINUE;
+
+       if (tbtt_info_len < sizeof(*ti))
+               return RNR_ITER_CONTINUE;
+
+       ti = (const void *)tbtt_info;
+
+       if (ti->mld_params.mld_id != data->mld_id)
+               return RNR_ITER_CONTINUE;
+
+       link_id = le16_get_bits(ti->mld_params.params,
+                               IEEE80211_RNR_MLD_PARAMS_LINK_ID);
+       bss_param_ch_cnt =
+               le16_get_bits(ti->mld_params.params,
+                             IEEE80211_RNR_MLD_PARAMS_BSS_CHANGE_COUNT);
+
+       if (bss_param_ch_cnt != 255 &&
+           link_id < ARRAY_SIZE(sdata->link)) {
+               struct ieee80211_link_data *link =
+                       sdata_dereference(sdata->link[link_id], sdata);
+
+               if (link && link->conf->bss_param_ch_cnt != bss_param_ch_cnt) {
+                       link->conf->bss_param_ch_cnt = bss_param_ch_cnt;
+                       link->conf->bss_param_ch_cnt_link_id =
+                               data->reporting_link_id;
+               }
+       }
+
+       return RNR_ITER_CONTINUE;
+}
+
+static void
+ieee80211_mgd_update_bss_param_ch_cnt(struct ieee80211_sub_if_data *sdata,
+                                     struct ieee80211_bss_conf *bss_conf,
+                                     struct ieee802_11_elems *elems)
+{
+       struct sta_bss_param_ch_cnt_data data = {
+               .reporting_link_id = bss_conf->link_id,
+               .sdata = sdata,
+       };
+       int bss_param_ch_cnt;
+
+       if (!elems->ml_basic)
+               return;
+
+       data.mld_id = ieee80211_mle_get_mld_id((const void *)elems->ml_basic);
+
+       cfg80211_iter_rnr(elems->ie_start, elems->total_len,
+                         ieee80211_sta_bss_param_ch_cnt_iter, &data);
+
+       bss_param_ch_cnt =
+               ieee80211_mle_get_bss_param_ch_cnt((const void *)elems->ml_basic);
+
+       /*
+        * Update bss_param_ch_cnt_link_id even if bss_param_ch_cnt
+        * didn't change to indicate that we got a beacon on our own
+        * link.
+        */
+       if (bss_param_ch_cnt >= 0 && bss_param_ch_cnt != 255) {
+               bss_conf->bss_param_ch_cnt = bss_param_ch_cnt;
+               bss_conf->bss_param_ch_cnt_link_id =
+                       bss_conf->link_id;
+       }
+}
+
 static bool
 ieee80211_find_80211h_pwr_constr(struct ieee80211_sub_if_data *sdata,
                                 struct ieee80211_channel *channel,
@@ -4667,7 +4750,8 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
                                ret = false;
                                goto out;
                        }
-                       link->u.mgd.bss_param_ch_cnt = bss_param_ch_cnt;
+                       bss_conf->bss_param_ch_cnt = bss_param_ch_cnt;
+                       bss_conf->bss_param_ch_cnt_link_id = link_id;
                }
        } else if (elems->parse_error & IEEE80211_PARSE_ERR_DUP_NEST_ML_BASIC ||
                   !elems->prof ||
@@ -4677,6 +4761,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
        } else {
                const u8 *ptr = elems->prof->variable +
                                elems->prof->sta_info_len - 1;
+               int bss_param_ch_cnt;
 
                /*
                 * During parsing, we validated that these fields exist,
@@ -4684,8 +4769,10 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
                 */
                capab_info = get_unaligned_le16(ptr);
                assoc_data->link[link_id].status = get_unaligned_le16(ptr + 2);
-               link->u.mgd.bss_param_ch_cnt =
+               bss_param_ch_cnt =
                        ieee80211_mle_basic_sta_prof_bss_param_ch_cnt(elems->prof);
+               bss_conf->bss_param_ch_cnt = bss_param_ch_cnt;
+               bss_conf->bss_param_ch_cnt_link_id = link_id;
 
                if (assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS) {
                        link_info(link, "association response status code=%u\n",
@@ -6913,6 +7000,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
        /* note that after this elems->ml_basic can no longer be used fully */
        ieee80211_mgd_check_cross_link_csa(sdata, rx_status->link_id, elems);
 
+       ieee80211_mgd_update_bss_param_ch_cnt(sdata, bss_conf, elems);
+
        if (!link->u.mgd.disable_wmm_tracking &&
            ieee80211_sta_wmm_params(local, link, elems->wmm_param,
                                     elems->wmm_param_len,