wifi: mac80211: handle TPE element during CSA
authorJohannes Berg <johannes.berg@intel.com>
Mon, 6 May 2024 19:54:51 +0000 (21:54 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 23 May 2024 09:28:56 +0000 (11:28 +0200)
Handle the transmit power envelope (TPE) element during
channel switch, applying it when the channel switch is
done.

Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://msgid.link/20240506215543.486c33157d18.Idf971ad801b6961c177bdf42cc323fd1a4ca8165@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/parse.c

index cba1c2c3d9f1d329e51256b915e6f272643cea5f..76965d64a0faee2a8374c82a51c969aa453c17bc 100644 (file)
@@ -977,6 +977,8 @@ struct ieee80211_link_data_managed {
 
        struct {
                struct wiphy_delayed_work switch_work;
+               struct cfg80211_chan_def ap_chandef;
+               struct ieee80211_parsed_tpe tpe;
                unsigned long time;
                bool waiting_bcn;
                bool ignored_same_chan;
@@ -1754,6 +1756,7 @@ struct ieee802_11_elems {
 
        /* not the order in the psd values is per element, not per chandef */
        struct ieee80211_parsed_tpe tpe;
+       struct ieee80211_parsed_tpe csa_tpe;
 
        /* length of them, respectively */
        u8 ext_capab_len;
index 1d0b414619a4baf25e62ca22f69d46370fe1801b..18793f2fb91ce2dbc60709ac86b1124e51a5ea6f 100644 (file)
@@ -2129,6 +2129,20 @@ static void ieee80211_csa_switch_work(struct wiphy *wiphy,
 
        link->u.mgd.csa.waiting_bcn = true;
 
+       /* apply new TPE restrictions immediately on the new channel */
+       if (link->u.mgd.csa.ap_chandef.chan->band == NL80211_BAND_6GHZ &&
+           link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HE) {
+               ieee80211_rearrange_tpe(&link->u.mgd.csa.tpe,
+                                       &link->u.mgd.csa.ap_chandef,
+                                       &link->conf->chanreq.oper);
+               if (memcmp(&link->conf->tpe, &link->u.mgd.csa.tpe,
+                          sizeof(link->u.mgd.csa.tpe))) {
+                       link->conf->tpe = link->u.mgd.csa.tpe;
+                       ieee80211_link_info_change_notify(sdata, link,
+                                                         BSS_CHANGED_TPE);
+               }
+       }
+
        ieee80211_sta_reset_beacon_monitor(sdata);
        ieee80211_sta_reset_conn_monitor(sdata);
 }
@@ -2379,6 +2393,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
                        ch_switch.count = csa_ie.count;
                        ch_switch.delay = csa_ie.max_switch_time;
                }
+
+               link->u.mgd.csa.tpe = csa_elems->csa_tpe;
        } else {
                /*
                 * If there was no per-STA profile for this link, we
@@ -2517,6 +2533,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
                goto drop_connection;
        }
 
+       link->u.mgd.csa.ap_chandef = csa_ie.chanreq.ap;
+
        link->csa.chanreq = csa_ie.chanreq;
        if (link->u.mgd.conn.mode < IEEE80211_CONN_MODE_EHT ||
            sdata->vif.driver_flags & IEEE80211_VIF_IGNORE_OFDMA_WIDER_BW)
index 6efeb977f8e55351e13c2343a7104517959bee0f..5c5c21ecb2b77cef904d2ae704ca9a5c2157d98c 100644 (file)
@@ -607,6 +607,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
                                        elem_parse_failed =
                                                IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
                        }
+
+                       subelem = cfg80211_find_ext_elem(WLAN_EID_TX_POWER_ENVELOPE,
+                                                        pos, elen);
+                       if (subelem)
+                               ieee80211_parse_tpe(&elems->csa_tpe,
+                                                   subelem->data + 1,
+                                                   subelem->datalen - 1);
                        break;
                case WLAN_EID_COUNTRY:
                        elems->country_elem = pos;
@@ -962,6 +969,7 @@ ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params)
 
        /* set all TPE entries to unlimited (but invalid) */
        ieee80211_clear_tpe(&elems->tpe);
+       ieee80211_clear_tpe(&elems->csa_tpe);
 
        nontransmitted_profile = elems_parse->scratch_pos;
        nontransmitted_profile_len =