| From 2bb34cb05062f9f53252c5a15304a75141e02660 Mon Sep 17 00:00:00 2001 |
| From: "fancy.liu" <fancy.liu@mediatek.com> |
| Date: Thu, 30 Nov 2023 16:42:59 +0800 |
| Subject: [PATCH 36/37] mtk: mac80211: Add CSA action frame tx when channel |
| switch on AP |
| |
| Description: |
| To meet spec requirement. |
| |
| 802.11-2020 |
| 11.8.8.2 Selecting and advertising a new channel in a non-DMG infrastructure BSS |
| 11.8.8.6 Selecting and advertising a new channel in a DMG BSS |
| - |
| An AP shall inform associated STAs that the AP is moving to a new channel and shall maintain the association by advertising the switch using Channel Switch Announcement elements in Beacon frames, Probe Response frames, and Channel Switch Announcement frames until the intended channel switch time. |
| |
| Signed-off-by: fancy.liu <fancy.liu@mediatek.com> |
| --- |
| net/mac80211/cfg.c | 28 ++++++++++++++-------------- |
| net/mac80211/util.c | 10 +++++++--- |
| 2 files changed, 21 insertions(+), 17 deletions(-) |
| |
| diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c |
| index cf694bc..a2d1688 100644 |
| --- a/net/mac80211/cfg.c |
| +++ b/net/mac80211/cfg.c |
| @@ -3798,15 +3798,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| * immediately too. If we would delay the switch |
| * until the next TBTT, we would have to set the probe |
| * response here. |
| - * |
| - * TODO: A channel switch with count <= 1 without |
| - * sending a CSA action frame is kind of useless, |
| - * because the clients won't know we're changing |
| - * channels. The action frame must be implemented |
| - * either here or in the userspace. |
| */ |
| - if (params->count <= 1) |
| - break; |
| |
| if ((params->n_counter_offsets_beacon > |
| IEEE80211_MAX_CNTDWN_COUNTERS_NUM) || |
| @@ -3822,14 +3814,20 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| csa.n_counter_offsets_presp = params->n_counter_offsets_presp; |
| csa.count = params->count; |
| |
| - err = ieee80211_assign_beacon(sdata, &sdata->deflink, |
| - ¶ms->beacon_csa, &csa, |
| - NULL, changed); |
| - if (err < 0) { |
| - ieee80211_free_next_beacon(&sdata->deflink); |
| - return err; |
| + /* see comments in the NL80211_IFTYPE_AP block */ |
| + if (params->count > 1) { |
| + err = ieee80211_assign_beacon(sdata, &sdata->deflink, |
| + ¶ms->beacon_csa, &csa, |
| + NULL, changed); |
| + |
| + if (err < 0) { |
| + ieee80211_free_next_beacon(&sdata->deflink); |
| + return err; |
| + } |
| } |
| |
| + ieee80211_send_action_csa(sdata, params); |
| + |
| break; |
| case NL80211_IFTYPE_ADHOC: |
| if (!sdata->vif.cfg.ibss_joined) |
| @@ -3901,6 +3899,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| } |
| #endif |
| default: |
| + sdata_info(sdata, "Won't send CSA for vif.type:%d.\n", sdata->vif.type); |
| return -EOPNOTSUPP; |
| } |
| |
| @@ -3990,6 +3989,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
| |
| err = ieee80211_set_csa_beacon(sdata, params, &changed); |
| if (err) { |
| + sdata_info(sdata, "failed to set csa in beacon.\n"); |
| ieee80211_link_unreserve_chanctx(&sdata->deflink); |
| goto out; |
| } |
| diff --git a/net/mac80211/util.c b/net/mac80211/util.c |
| index f0bb4e8..00a20a6 100644 |
| --- a/net/mac80211/util.c |
| +++ b/net/mac80211/util.c |
| @@ -4514,8 +4514,11 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, |
| u8 *pos; |
| |
| if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
| - sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
| + sdata->vif.type != NL80211_IFTYPE_MESH_POINT && |
| + sdata->vif.type != NL80211_IFTYPE_AP) { |
| + sdata_info(sdata, "Not allow csa action on vif.type:%d.\n", sdata->vif.type); |
| return -EOPNOTSUPP; |
| + } |
| |
| skb = dev_alloc_skb(local->tx_headroom + hdr_len + |
| 5 + /* channel switch announcement element */ |
| @@ -4532,9 +4535,10 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, |
| |
| eth_broadcast_addr(mgmt->da); |
| memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
| - if (ieee80211_vif_is_mesh(&sdata->vif)) { |
| + if (sdata->vif.type == NL80211_IFTYPE_AP || |
| + sdata->vif.type == NL80211_IFTYPE_MESH_POINT) { |
| memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
| - } else { |
| + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
| struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); |
| } |
| -- |
| 2.18.0 |
| |