Commit ec67d6e0 authored by Aditya Kumar Singh's avatar Aditya Kumar Singh Committed by Johannes Berg

wifi: mac80211: flush only stations using requests links

Whenever sta_flush() function is invoked, all STAs present in that
interface are flushed. In case of MLO, it is desirable to only flush such
STAs that are at least using a given link id as one of their links.

Add support for this by making change in the __sta_info_flush API argument
to accept a link ID. And then, only if the STA is using the given link as
one of its links, it would be flushed.
Signed-off-by: default avatarAditya Kumar Singh <quic_adisi@quicinc.com>
Link: https://msgid.link/20240205162952.1697646-3-quic_adisi@quicinc.com
[reword commit message, in particular this isn't about "active" links]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent f6ca96aa
...@@ -1616,7 +1616,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -1616,7 +1616,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
link_conf->ema_ap = false; link_conf->ema_ap = false;
link_conf->bssid_indicator = 0; link_conf->bssid_indicator = 0;
__sta_info_flush(sdata, true); __sta_info_flush(sdata, true, -1);
ieee80211_free_keys(sdata, true); ieee80211_free_keys(sdata, true);
link_conf->enable_beacon = false; link_conf->enable_beacon = false;
...@@ -2096,7 +2096,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev, ...@@ -2096,7 +2096,7 @@ static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
if (params->mac) if (params->mac)
return sta_info_destroy_addr_bss(sdata, params->mac); return sta_info_destroy_addr_bss(sdata, params->mac);
sta_info_flush(sdata); sta_info_flush(sdata, params->link_id);
return 0; return 0;
} }
......
...@@ -237,7 +237,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -237,7 +237,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
drv_reset_tsf(local, sdata); drv_reset_tsf(local, sdata);
if (!ether_addr_equal(ifibss->bssid, bssid)) if (!ether_addr_equal(ifibss->bssid, bssid))
sta_info_flush(sdata); sta_info_flush(sdata, -1);
/* if merging, indicate to driver that we leave the old IBSS */ /* if merging, indicate to driver that we leave the old IBSS */
if (sdata->vif.cfg.ibss_joined) { if (sdata->vif.cfg.ibss_joined) {
...@@ -682,7 +682,7 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata) ...@@ -682,7 +682,7 @@ static void ieee80211_ibss_disconnect(struct ieee80211_sub_if_data *sdata)
ifibss->state = IEEE80211_IBSS_MLME_SEARCH; ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
sta_info_flush(sdata); sta_info_flush(sdata, -1);
spin_lock_bh(&ifibss->incomplete_lock); spin_lock_bh(&ifibss->incomplete_lock);
while (!list_empty(&ifibss->incomplete_stations)) { while (!list_empty(&ifibss->incomplete_stations)) {
......
...@@ -511,7 +511,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do ...@@ -511,7 +511,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
* would have removed them, but in other modes there shouldn't * would have removed them, but in other modes there shouldn't
* be any stations. * be any stations.
*/ */
flushed = sta_info_flush(sdata); flushed = sta_info_flush(sdata, -1);
WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && flushed > 0); WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN && flushed > 0);
/* don't count this interface for allmulti while it is down */ /* don't count this interface for allmulti while it is down */
......
...@@ -1214,7 +1214,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -1214,7 +1214,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
netif_carrier_off(sdata->dev); netif_carrier_off(sdata->dev);
/* flush STAs and mpaths on this iface */ /* flush STAs and mpaths on this iface */
sta_info_flush(sdata); sta_info_flush(sdata, -1);
ieee80211_free_keys(sdata, true); ieee80211_free_keys(sdata, true);
mesh_path_flush_by_iface(sdata); mesh_path_flush_by_iface(sdata);
......
...@@ -3151,7 +3151,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ...@@ -3151,7 +3151,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
sdata->vif.cfg.ssid_len = 0; sdata->vif.cfg.ssid_len = 0;
/* remove AP and TDLS peers */ /* remove AP and TDLS peers */
sta_info_flush(sdata); sta_info_flush(sdata, -1);
/* finally reset all BSS / config parameters */ /* finally reset all BSS / config parameters */
if (!ieee80211_vif_is_mld(&sdata->vif)) if (!ieee80211_vif_is_mld(&sdata->vif))
......
...@@ -208,7 +208,7 @@ int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata) ...@@ -208,7 +208,7 @@ int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
lockdep_assert_wiphy(sdata->local->hw.wiphy); lockdep_assert_wiphy(sdata->local->hw.wiphy);
ifocb->joined = false; ifocb->joined = false;
sta_info_flush(sdata); sta_info_flush(sdata, -1);
spin_lock_bh(&ifocb->incomplete_lock); spin_lock_bh(&ifocb->incomplete_lock);
while (!list_empty(&ifocb->incomplete_stations)) { while (!list_empty(&ifocb->incomplete_stations)) {
......
...@@ -1566,7 +1566,8 @@ void sta_info_stop(struct ieee80211_local *local) ...@@ -1566,7 +1566,8 @@ void sta_info_stop(struct ieee80211_local *local)
} }
int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans) int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans,
int link_id)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sta_info *sta, *tmp; struct sta_info *sta, *tmp;
...@@ -1580,13 +1581,19 @@ int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans) ...@@ -1580,13 +1581,19 @@ int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans)
WARN_ON(vlans && !sdata->bss); WARN_ON(vlans && !sdata->bss);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list) { list_for_each_entry_safe(sta, tmp, &local->sta_list, list) {
if (sdata == sta->sdata || if (sdata != sta->sdata &&
(vlans && sdata->bss == sta->sdata->bss)) { (!vlans || sdata->bss != sta->sdata->bss))
continue;
if (link_id >= 0 && sta->sta.valid_links &&
!(sta->sta.valid_links & BIT(link_id)))
continue;
if (!WARN_ON(__sta_info_destroy_part1(sta))) if (!WARN_ON(__sta_info_destroy_part1(sta)))
list_add(&sta->free_list, &free_list); list_add(&sta->free_list, &free_list);
ret++; ret++;
} }
}
if (!list_empty(&free_list)) { if (!list_empty(&free_list)) {
bool support_p2p_ps = true; bool support_p2p_ps = true;
......
...@@ -886,8 +886,12 @@ void sta_info_stop(struct ieee80211_local *local); ...@@ -886,8 +886,12 @@ void sta_info_stop(struct ieee80211_local *local);
* *
* @sdata: sdata to remove all stations from * @sdata: sdata to remove all stations from
* @vlans: if the given interface is an AP interface, also flush VLANs * @vlans: if the given interface is an AP interface, also flush VLANs
* @link_id: if given (>=0), all those STA entries using @link_id only
* will be removed. If -1 is passed, all STA entries will be
* removed.
*/ */
int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans); int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans,
int link_id);
/** /**
* sta_info_flush - flush matching STA entries from the STA table * sta_info_flush - flush matching STA entries from the STA table
...@@ -895,10 +899,14 @@ int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans); ...@@ -895,10 +899,14 @@ int __sta_info_flush(struct ieee80211_sub_if_data *sdata, bool vlans);
* Returns the number of removed STA entries. * Returns the number of removed STA entries.
* *
* @sdata: sdata to remove all stations from * @sdata: sdata to remove all stations from
* @link_id: if given (>=0), all those STA entries using @link_id only
* will be removed. If -1 is passed, all STA entries will be
* removed.
*/ */
static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata) static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata,
int link_id)
{ {
return __sta_info_flush(sdata, false); return __sta_info_flush(sdata, false, link_id);
} }
void sta_set_rate_info_tx(struct sta_info *sta, void sta_set_rate_info_tx(struct sta_info *sta,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment