wifi: mac80211: Fix SMPS handling in the context of MLO
authorIlan Peer <ilan.peer@intel.com>
Mon, 28 Aug 2023 13:09:25 +0000 (15:09 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 11 Sep 2023 09:27:18 +0000 (11:27 +0200)
When the connection is a MLO connection, a SMPS request should be
sent on a specific link, as SMPS is BSS specific, and the DA and BSSID
used for the action frame transmission should be the AP MLD address, as
the underlying driver is expected to perform the address translation
(based on the link ID).

Fix the SMPS request handling to use the AP MLD address and provide the
link ID for the request processing during Tx.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h

index 29a6da5ee77f084f5ca65048309227909b83c146..fa20a260f9c84b4cf28949ed703a61a239e989c7 100644 (file)
@@ -3178,6 +3178,10 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
        if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
                return -EINVAL;
 
+       if (ieee80211_vif_is_mld(&sdata->vif) &&
+           !(sdata->vif.active_links & BIT(link->link_id)))
+               return 0;
+
        old_req = link->u.mgd.req_smps;
        link->u.mgd.req_smps = smps_mode;
 
@@ -3194,7 +3198,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
            link->conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
                return 0;
 
-       ap = link->u.mgd.bssid;
+       ap = sdata->vif.cfg.ap_addr;
 
        rcu_read_lock();
        list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
@@ -3216,7 +3220,9 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
 
        /* send SM PS frame to AP */
        err = ieee80211_send_smps_action(sdata, smps_mode,
-                                        ap, ap);
+                                        ap, ap,
+                                        ieee80211_vif_is_mld(&sdata->vif) ?
+                                        link->link_id : -1);
        if (err)
                link->u.mgd.req_smps = old_req;
        else if (smps_mode != IEEE80211_SMPS_OFF && tdls_peer_found)
index 33729870ad8a3734d1cfe8efed76dc96b8f74e6c..802b0e738696a0d71b72be5a00f8556c0ac63e26 100644 (file)
@@ -538,7 +538,7 @@ ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps)
 
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
                               enum ieee80211_smps_mode smps, const u8 *da,
-                              const u8 *bssid)
+                              const u8 *bssid, int link_id)
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
@@ -579,7 +579,7 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
 
        /* we'll do more on status of this frame */
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
-       ieee80211_tx_skb(sdata, skb);
+       ieee80211_tx_skb_tid(sdata, skb, 7, link_id);
 
        return 0;
 }
index 7b74cf96ee0a17e1230943764d322beb6db18487..1df2101d8eeb481e23669e25eacaccb47214579d 100644 (file)
@@ -2098,7 +2098,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
                          u16 initiator, u16 reason_code);
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
                               enum ieee80211_smps_mode smps, const u8 *da,
-                              const u8 *bssid);
+                              const u8 *bssid, int link_id);
 bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
                                   enum ieee80211_smps_mode smps_mode_new);