diff mbox series

[2/2] wifi: mac80211: handle netif carrier up/down with link AP during MLO

Message ID 20240227042251.1511122-3-quic_adisi@quicinc.com (mailing list archive)
State Accepted
Delegated to: Johannes Berg
Headers show
Series wifi: mac80211: keys and netif indication fixes for MLD AP | expand

Commit Message

Aditya Kumar Singh Feb. 27, 2024, 4:22 a.m. UTC
Currently whenever link AP is started, netif_carrier_up() function is
called and whenever it is brought down, netif_carrier_down() function is
called. However, with MLO, all the links of the same MLD would use the
same netdev. Hence there is no need to indicate for each link up/down.
Also, calling it down when only one of the links went down is not
desirable.

Add changes to call the netif_carrier_up() function only when first link
is brought up. Similarly, add changes to call the netif_carrier_down()
function only when last link is brought down.

In order to check the number of beaconing links in the given interface,
introduce a new helper function ieee80211_num_beaconing_links().

Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com>
---
 net/mac80211/cfg.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9989f4a6c0ff..1c2aac1733b8 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1241,6 +1241,30 @@  ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	return 0;
 }
 
+static u8 ieee80211_num_beaconing_links(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_link_data *link;
+	u8 link_id, num = 0;
+
+	if (sdata->vif.type != NL80211_IFTYPE_AP &&
+	    sdata->vif.type != NL80211_IFTYPE_P2P_GO)
+		return num;
+
+	if (!sdata->vif.valid_links)
+		return num;
+
+	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+		link = sdata_dereference(sdata->link[link_id], sdata);
+		if (!link)
+			continue;
+
+		if (sdata_dereference(link->u.ap.beacon, sdata))
+			num++;
+	}
+
+	return num;
+}
+
 static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 			      struct cfg80211_ap_settings *params)
 {
@@ -1470,7 +1494,9 @@  static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID);
 	ieee80211_link_info_change_notify(sdata, link, changed);
 
-	netif_carrier_on(dev);
+	if (ieee80211_num_beaconing_links(sdata) <= 1)
+		netif_carrier_on(dev);
+
 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
 		netif_carrier_on(vlan->dev);
 
@@ -1592,7 +1618,9 @@  static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 	/* turn off carrier for this interface and dependent VLANs */
 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
 		netif_carrier_off(vlan->dev);
-	netif_carrier_off(dev);
+
+	if (ieee80211_num_beaconing_links(sdata) <= 1)
+		netif_carrier_off(dev);
 
 	/* remove beacon and probe response */
 	sdata->u.ap.active = false;