From f8bf97ad19c48f5e66cf99bd390356ffa1189d62 Mon Sep 17 00:00:00 2001 From: Lachlan Hodges Date: Thu, 17 Jul 2025 17:42:05 +1000 Subject: [PATCH] wifi: mac80211: support returning the S1G short beacon skb When short beaconing is enabled, check the value of the sb_count to determine whether we are to send a long beacon or short beacon. sb_count represents the number of short beacons until the next long beacon, where if its value is 0 we are to send a long beacon. The value is then reset to the long beacon period, which represents the number of beacon intervals between each long beacon. The decrement process follows the same cadence as the decrement of the DTIM count value. Signed-off-by: Lachlan Hodges Link: https://patch.msgid.link/20250717074205.312577-5-lachlan.hodges@morsemicro.com Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 95 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6fa883a9250d9..f3a065313a31a 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -5290,14 +5290,14 @@ ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon, } static struct sk_buff * -ieee80211_beacon_get_ap(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_link_data *link, - struct ieee80211_mutable_offsets *offs, - bool is_template, - struct beacon_data *beacon, - struct ieee80211_chanctx_conf *chanctx_conf, - u8 ema_index) +__ieee80211_beacon_get_ap(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_data *link, + struct ieee80211_mutable_offsets *offs, + bool is_template, + struct beacon_data *beacon, + struct ieee80211_chanctx_conf *chanctx_conf, + u8 ema_index) { struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); @@ -5358,6 +5358,71 @@ ieee80211_beacon_get_ap(struct ieee80211_hw *hw, return skb; } +static bool ieee80211_s1g_need_long_beacon(struct ieee80211_sub_if_data *sdata, + struct ieee80211_link_data *link) +{ + struct ps_data *ps = &sdata->u.ap.ps; + + if (ps->sb_count == 0) + ps->sb_count = link->conf->s1g_long_beacon_period - 1; + else + ps->sb_count--; + + return ps->sb_count == 0; +} + +static struct sk_buff * +ieee80211_s1g_short_beacon_get(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_link_data *link, + struct ieee80211_chanctx_conf *chanctx_conf, + struct s1g_short_beacon_data *sb, + bool is_template) +{ + struct ieee80211_local *local = hw_to_local(hw); + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_if_ap *ap = &sdata->u.ap; + struct sk_buff *skb; + + skb = dev_alloc_skb(local->tx_headroom + sb->short_head_len + + sb->short_tail_len + 256 + + local->hw.extra_beacon_tailroom); + if (!skb) + return NULL; + + skb_reserve(skb, local->tx_headroom); + skb_put_data(skb, sb->short_head, sb->short_head_len); + + ieee80211_beacon_add_tim(sdata, link, &ap->ps, skb, is_template); + + if (sb->short_tail) + skb_put_data(skb, sb->short_tail, sb->short_tail_len); + + ieee80211_beacon_get_finish(hw, vif, link, NULL, NULL, skb, + chanctx_conf, 0); + return skb; +} + +static struct sk_buff * +ieee80211_beacon_get_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_link_data *link, + struct ieee80211_mutable_offsets *offs, + bool is_template, struct beacon_data *beacon, + struct ieee80211_chanctx_conf *chanctx_conf, + u8 ema_index, struct s1g_short_beacon_data *s1g_sb) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + + if (!sdata->vif.cfg.s1g || !s1g_sb || + ieee80211_s1g_need_long_beacon(sdata, link)) + return __ieee80211_beacon_get_ap(hw, vif, link, offs, + is_template, beacon, + chanctx_conf, ema_index); + + return ieee80211_s1g_short_beacon_get(hw, vif, link, chanctx_conf, + s1g_sb, is_template); +} + static struct ieee80211_ema_beacons * ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -5381,7 +5446,7 @@ ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw, ieee80211_beacon_get_ap(hw, vif, link, &ema->bcn[ema->cnt].offs, is_template, beacon, - chanctx_conf, ema->cnt); + chanctx_conf, ema->cnt, NULL); if (!ema->bcn[ema->cnt].skb) break; } @@ -5410,6 +5475,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata = NULL; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_link_data *link; + struct s1g_short_beacon_data *s1g_short_bcn = NULL; rcu_read_lock(); @@ -5431,6 +5497,13 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, if (!beacon) goto out; + if (vif->cfg.s1g && link->u.ap.s1g_short_beacon) { + s1g_short_bcn = + rcu_dereference(link->u.ap.s1g_short_beacon); + if (!s1g_short_bcn) + goto out; + } + if (ema_beacons) { *ema_beacons = ieee80211_beacon_get_ap_ema_list(hw, vif, link, @@ -5451,8 +5524,8 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, skb = ieee80211_beacon_get_ap(hw, vif, link, offs, is_template, beacon, - chanctx_conf, - ema_index); + chanctx_conf, ema_index, + s1g_short_bcn); } } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; -- 2.47.2