* [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements
@ 2026-08-27 5:49 Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 1/8] wifi: mm81x: move beacon work and init below the tx op Lachlan Hodges
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
Some improvements to the multicast handling and tx bw selection.
lachlan
Lachlan Hodges (8):
wifi: mm81x: move beacon work and init below the tx op
wifi: mm81x: release buffered broadcast frames after DTIM
wifi: mm81x: do not drop PS filtered frames in AP mode
wifi: mm81x: implement .tx_frames_pending() mac op
wifi: mm81x: factor out tx width selection
wifi: mm81x: tx EAPOLs at primary width
wifi: mm81x: clamp tx width to stas max supported width
wifi: mm81x: tx multicast frames from AP at primary width
drivers/net/wireless/morsemicro/mm81x/core.h | 7 +-
drivers/net/wireless/morsemicro/mm81x/mac.c | 181 ++++++++++++-------
drivers/net/wireless/morsemicro/mm81x/skbq.c | 7 +-
3 files changed, 123 insertions(+), 72 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH wireless-next 1/8] wifi: mm81x: move beacon work and init below the tx op
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 2/8] wifi: mm81x: release buffered broadcast frames after DTIM Lachlan Hodges
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
Move mm81x_mac_beacon_work() and mm81x_mac_beacon_init() to below
mm81x_mac_ops_tx() to prepare for future multicast handling such that
we avoid a forward declaration. No functional change.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/mac.c | 84 ++++++++++-----------
1 file changed, 42 insertions(+), 42 deletions(-)
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index 08ca116a68b4..4d0131246710 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -445,39 +445,6 @@ static void mm81x_beacon_h_fill_tx_info(struct mm81x *mors,
cpu_to_le32(MM81X_TX_CONF_FLAGS_IMMEDIATE_REPORT);
}
-static void mm81x_mac_beacon_work(struct work_struct *work)
-{
- struct mm81x_vif *mors_vif =
- from_work(mors_vif, work, u.ap.beacon_work);
- struct mm81x *mors = mm81x_vif_to_mors(mors_vif);
- struct mm81x_skbq *mq;
- struct sk_buff *beacon;
- struct ieee80211_vif *vif = mm81x_vif_to_ieee80211_vif(mors_vif);
- struct mm81x_skb_tx_info tx_info = { 0 };
- int num_bcn_vifs = atomic_read(&mors->num_bcn_vifs);
-
- mq = mm81x_hif_get_tx_beacon_queue(mors);
- if (!mq) {
- dev_err(mors->dev, "no matching beacon Q found");
- return;
- }
-
- if (mm81x_skbq_count(mq) >= num_bcn_vifs) {
- dev_err(mors->dev,
- "previous beacon not consumed, dropping req [id:%d]",
- mors_vif->id);
- return;
- }
-
- beacon = ieee80211_beacon_get(mors->hw, vif, false);
- if (!beacon)
- return;
-
- mm81x_beacon_h_fill_tx_info(mors, &tx_info, mors_vif,
- cfg80211_chandef_s1g_pri_width(&mors->chandef));
- mm81x_skbq_skb_tx(mq, &beacon, &tx_info, MM81X_SKB_CHAN_BEACON);
-}
-
void mm81x_mac_beacon_irq_handle(struct mm81x *mors, u32 status)
{
int vif_id;
@@ -497,15 +464,6 @@ void mm81x_mac_beacon_irq_handle(struct mm81x *mors, u32 status)
}
}
-static void mm81x_mac_beacon_init(struct mm81x_vif *mors_vif)
-{
- struct mm81x *mors = mm81x_vif_to_mors(mors_vif);
-
- INIT_WORK(&mors_vif->u.ap.beacon_work, mm81x_mac_beacon_work);
- mm81x_mac_beacon_irq_enable(mors_vif, true);
- atomic_inc(&mors->num_bcn_vifs);
-}
-
static struct hw_scan_tlv_hdr mm81x_hw_scan_h_pack_tlv_hdr(u16 tag, u16 len)
{
struct hw_scan_tlv_hdr hdr = { .tag = cpu_to_le16(tag),
@@ -1329,6 +1287,48 @@ static void mm81x_mac_ops_tx(struct ieee80211_hw *hw,
MM81X_SKB_CHAN_DATA);
}
+static void mm81x_mac_beacon_work(struct work_struct *work)
+{
+ struct mm81x_vif *mors_vif =
+ from_work(mors_vif, work, u.ap.beacon_work);
+ struct mm81x *mors = mm81x_vif_to_mors(mors_vif);
+ struct mm81x_skbq *mq;
+ struct sk_buff *beacon;
+ struct ieee80211_vif *vif = mm81x_vif_to_ieee80211_vif(mors_vif);
+ struct mm81x_skb_tx_info tx_info = { 0 };
+ int num_bcn_vifs = atomic_read(&mors->num_bcn_vifs);
+
+ mq = mm81x_hif_get_tx_beacon_queue(mors);
+ if (!mq) {
+ dev_err(mors->dev, "no matching beacon Q found");
+ return;
+ }
+
+ if (mm81x_skbq_count(mq) >= num_bcn_vifs) {
+ dev_err(mors->dev,
+ "previous beacon not consumed, dropping req [id:%d]",
+ mors_vif->id);
+ return;
+ }
+
+ beacon = ieee80211_beacon_get(mors->hw, vif, false);
+ if (!beacon)
+ return;
+
+ mm81x_beacon_h_fill_tx_info(mors, &tx_info, mors_vif,
+ cfg80211_chandef_s1g_pri_width(&mors->chandef));
+ mm81x_skbq_skb_tx(mq, &beacon, &tx_info, MM81X_SKB_CHAN_BEACON);
+}
+
+static void mm81x_mac_beacon_init(struct mm81x_vif *mors_vif)
+{
+ struct mm81x *mors = mm81x_vif_to_mors(mors_vif);
+
+ INIT_WORK(&mors_vif->u.ap.beacon_work, mm81x_mac_beacon_work);
+ mm81x_mac_beacon_irq_enable(mors_vif, true);
+ atomic_inc(&mors->num_bcn_vifs);
+}
+
static void mm81x_mac_ops_stop(struct ieee80211_hw *hw, bool suspend)
{
struct mm81x *mors = hw->priv;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 2/8] wifi: mm81x: release buffered broadcast frames after DTIM
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 1/8] wifi: mm81x: move beacon work and init below the tx op Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 3/8] wifi: mm81x: do not drop PS filtered frames in AP mode Lachlan Hodges
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
Since we set the HOST_BROADCAST_PS_BUFFERING, mac80211 handles the
buffering of broadcast frames. Make sure after each beacon we call
ieee80211_get_buffered_bc() to release buffered broadcast frames
after each DTIM beacon.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/mac.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index 4d0131246710..0bbedcdd0b3d 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -66,6 +66,9 @@
/* HW restart delay time before terminating hardware IF work items */
#define MM81X_HW_RESTART_DELAY_MS 20
+/* Maximum number of multicast frames to release after a DTIM beacon */
+#define MM81X_MAX_MC_FRAMES_AFTER_DTIM 4
+
/* clang-format off */
/* mm81x chips do not support 16MHz */
@@ -1287,6 +1290,20 @@ static void mm81x_mac_ops_tx(struct ieee80211_hw *hw,
MM81X_SKB_CHAN_DATA);
}
+static void mm81x_mac_send_buffered_bc(struct mm81x *mors,
+ struct ieee80211_vif *vif)
+{
+ int count = MM81X_MAX_MC_FRAMES_AFTER_DTIM;
+ struct ieee80211_tx_control control = { 0 };
+ struct sk_buff *bc_frame;
+
+ while (count-- &&
+ (bc_frame = ieee80211_get_buffered_bc(mors->hw, vif))) {
+ IEEE80211_SKB_CB(bc_frame)->control.vif = vif;
+ mm81x_mac_ops_tx(mors->hw, &control, bc_frame);
+ }
+}
+
static void mm81x_mac_beacon_work(struct work_struct *work)
{
struct mm81x_vif *mors_vif =
@@ -1318,6 +1335,9 @@ static void mm81x_mac_beacon_work(struct work_struct *work)
mm81x_beacon_h_fill_tx_info(mors, &tx_info, mors_vif,
cfg80211_chandef_s1g_pri_width(&mors->chandef));
mm81x_skbq_skb_tx(mq, &beacon, &tx_info, MM81X_SKB_CHAN_BEACON);
+
+ if (!test_bit(MM81X_STATE_DATA_QS_STOPPED, &mors->state_flags))
+ mm81x_mac_send_buffered_bc(mors, vif);
}
static void mm81x_mac_beacon_init(struct mm81x_vif *mors_vif)
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 3/8] wifi: mm81x: do not drop PS filtered frames in AP mode
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 1/8] wifi: mm81x: move beacon work and init below the tx op Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 2/8] wifi: mm81x: release buffered broadcast frames after DTIM Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 4/8] wifi: mm81x: implement .tx_frames_pending() mac op Lachlan Hodges
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
When the firmware reports a frame as filtered because the station has
entered power save, the AP-mode path dropped the frame and returned
"handled". In AP mode mac80211 owns the per-station power-save
re-buffering, so the frame must instead be reported with
IEEE80211_TX_STAT_TX_FILTERED and left for mac80211 to re-queue once
the station wakes.
Return false for AP interfaces so the tx-status path flags the frame as
filtered rather than silently dropping it.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/skbq.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/morsemicro/mm81x/skbq.c b/drivers/net/wireless/morsemicro/mm81x/skbq.c
index 25655bd56d14..3bf15e7c38d8 100644
--- a/drivers/net/wireless/morsemicro/mm81x/skbq.c
+++ b/drivers/net/wireless/morsemicro/mm81x/skbq.c
@@ -231,10 +231,9 @@ static bool mm81x_tx_h_is_ps_filtered(struct mm81x_skbq *mq,
WARN_ON_ONCE(!(le32_to_cpu(tx_sts->flags) &
MM81X_TX_STATUS_FLAGS_PS_FILTERED));
- if (vif->type == NL80211_IFTYPE_AP) {
- __mm81x_skbq_drop_pending_skb(mq, skb);
- return true;
- }
+ /* mac80211 buffers frames in AP mode */
+ if (vif->type == NL80211_IFTYPE_AP)
+ return false;
if (vif->type == NL80211_IFTYPE_STATION) {
mm81x_skbq_insert_pending(mq, skb, tx_sts->pkt_id);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 4/8] wifi: mm81x: implement .tx_frames_pending() mac op
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
` (2 preceding siblings ...)
2026-08-27 5:49 ` [PATCH wireless-next 3/8] wifi: mm81x: do not drop PS filtered frames in AP mode Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 5/8] wifi: mm81x: factor out tx width selection Lachlan Hodges
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
Implement .tx_frames_pending() to assist mac80211 when deciding whether
we should enter powersave such that we don't enter when there are
pending tx frames.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/mac.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index 0bbedcdd0b3d..5bae7c6251df 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -2035,6 +2035,13 @@ static void mm81x_mac_ops_flush(struct ieee80211_hw *hw,
mm81x_mac_wait_queues(mors);
}
+static bool mm81x_mac_ops_tx_frames_pending(struct ieee80211_hw *hw)
+{
+ struct mm81x *mors = hw->priv;
+
+ return mm81x_mac_has_tx_pending(mors);
+}
+
static int mm81x_mac_ops_set_rts_threshold(struct ieee80211_hw *hw,
int radio_idx, u32 value)
{
@@ -2260,6 +2267,7 @@ static const struct ieee80211_ops mm81x_ops = {
.configure_filter = mm81x_mac_ops_configure_filter,
.sta_state = mm81x_mac_ops_sta_state,
.flush = mm81x_mac_ops_flush,
+ .tx_frames_pending = mm81x_mac_ops_tx_frames_pending,
.set_frag_threshold = mm81x_mac_set_frag_threshold,
.set_rts_threshold = mm81x_mac_ops_set_rts_threshold,
.sta_statistics = mm81x_mac_ops_sta_statistics,
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 5/8] wifi: mm81x: factor out tx width selection
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
` (3 preceding siblings ...)
2026-08-27 5:49 ` [PATCH wireless-next 4/8] wifi: mm81x: implement .tx_frames_pending() mac op Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 6/8] wifi: mm81x: tx EAPOLs at primary width Lachlan Hodges
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
The tx mac op is getting busy, lets factor out tx width selection to
prepare for some future tx width selection fixes.
No functional changes.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/mac.c | 54 ++++++++++++---------
1 file changed, 30 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index 5bae7c6251df..1444db98351b 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -1243,38 +1243,44 @@ static void mm81x_tx_h_fill_info(struct mm81x *mors,
}
}
+static int mm81x_tx_h_get_bw(struct mm81x *mors, struct ieee80211_sta *sta,
+ struct sk_buff *skb, bool is_mgmt)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct mm81x_sta *mors_sta = NULL;
+ int tx_bw_mhz;
+
+ if (ieee80211_is_probe_resp(hdr->frame_control))
+ return 1;
+
+ if (is_mgmt)
+ return cfg80211_chandef_s1g_pri_width(&mors->chandef);
+
+ if (sta)
+ mors_sta = (struct mm81x_sta *)sta->drv_priv;
+
+ tx_bw_mhz = min(mm81x_tx_h_get_max_bw(mors),
+ cfg80211_chandef_get_width(&mors->chandef));
+ if (mors_sta && mors_sta->max_bw_mhz)
+ tx_bw_mhz = min(tx_bw_mhz, mors_sta->max_bw_mhz);
+
+ return tx_bw_mhz;
+}
+
static void mm81x_mac_ops_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
{
- struct mm81x *mors = hw->priv;
- struct mm81x_skbq *mq = NULL;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_vif *vif = info->control.vif;
- struct mm81x_skb_tx_info tx_info = { 0 };
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool is_mgmt = ieee80211_is_mgmt(hdr->frame_control);
- int tx_bw_mhz = cfg80211_chandef_get_width(&mors->chandef);
struct ieee80211_sta *sta = control->sta;
- int max_tx_bw = 0, sta_max_bw_mhz = 0;
-
- if (sta) {
- struct mm81x_sta *mors_sta = (struct mm81x_sta *)sta->drv_priv;
-
- sta_max_bw_mhz = mors_sta->max_bw_mhz;
- }
-
- max_tx_bw = mm81x_tx_h_get_max_bw(mors);
- tx_bw_mhz = min(max_tx_bw, tx_bw_mhz);
-
- if (is_mgmt)
- tx_bw_mhz = cfg80211_chandef_s1g_pri_width(&mors->chandef);
- if (sta_max_bw_mhz)
- tx_bw_mhz = min(tx_bw_mhz, sta_max_bw_mhz);
- if (ieee80211_is_probe_resp(hdr->frame_control))
- tx_bw_mhz = 1;
+ struct mm81x_skb_tx_info tx_info = { 0 };
+ struct mm81x *mors = hw->priv;
+ struct mm81x_skbq *mq;
- mm81x_tx_h_fill_info(mors, &tx_info, skb, vif, tx_bw_mhz, sta);
+ mm81x_tx_h_fill_info(mors, &tx_info, skb, info->control.vif,
+ mm81x_tx_h_get_bw(mors, sta, skb, is_mgmt), sta);
if (mm81x_tx_h_ps_filtered_for_sta(mors, skb, sta))
return;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 6/8] wifi: mm81x: tx EAPOLs at primary width
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
` (4 preceding siblings ...)
2026-08-27 5:49 ` [PATCH wireless-next 5/8] wifi: mm81x: factor out tx width selection Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 7/8] wifi: mm81x: clamp tx width to stas max supported width Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 8/8] wifi: mm81x: tx multicast frames from AP at primary width Lachlan Hodges
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
Right now port control frames such as EAPOLs are sent at the operating
width which, within noisier environments, can lead to increased
association times and at higher attenuation potentially prevent
association from occurring altogether. Make sure we send EAPOLs and
any other port control frames at the primary width.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/mac.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index 1444db98351b..fa3b0cfccffe 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -1247,13 +1247,14 @@ static int mm81x_tx_h_get_bw(struct mm81x *mors, struct ieee80211_sta *sta,
struct sk_buff *skb, bool is_mgmt)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct mm81x_sta *mors_sta = NULL;
int tx_bw_mhz;
if (ieee80211_is_probe_resp(hdr->frame_control))
return 1;
- if (is_mgmt)
+ if (is_mgmt || info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)
return cfg80211_chandef_s1g_pri_width(&mors->chandef);
if (sta)
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 7/8] wifi: mm81x: clamp tx width to stas max supported width
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
` (5 preceding siblings ...)
2026-08-27 5:49 ` [PATCH wireless-next 6/8] wifi: mm81x: tx EAPOLs at primary width Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 8/8] wifi: mm81x: tx multicast frames from AP at primary width Lachlan Hodges
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
max_bw_mhz is not populated with the stas maximum supported width
during association. This means data frames are sent at the operating
width, regardless of whether the sta can support the operating width.
For example a STA that supports up to 4MHz receiving frames from an AP
running on an 8MHz operating channel will be sent frames at 8MHz which
it cannot receive.
Make sure we initialise the stas maximum support bandwidth and while
we are here rename it to max_rx_bw_mhz to indicate its the maximum
bandwidth the sta can receive frames from.
Note: This should be conveyed via ieee80211_link_sta::bandwidth, but
the ieee80211_sta_rx_bandwidth enum does not support S1G widths as of
now and will require some non-trivial work to support in the future.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/core.h | 7 ++++++-
drivers/net/wireless/morsemicro/mm81x/mac.c | 11 +++++++----
2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/morsemicro/mm81x/core.h b/drivers/net/wireless/morsemicro/mm81x/core.h
index 2fd4b4786e77..75e998e8e324 100644
--- a/drivers/net/wireless/morsemicro/mm81x/core.h
+++ b/drivers/net/wireless/morsemicro/mm81x/core.h
@@ -192,7 +192,12 @@ struct mm81x_sta {
bool tid_tx[IEEE80211_NUM_TIDS];
bool tid_start_tx[IEEE80211_NUM_TIDS];
u8 tid_params[IEEE80211_NUM_TIDS];
- int max_bw_mhz;
+
+ /*
+ * We really should be using link_sta::bandwidth but
+ * that requires non-trivial work.
+ */
+ int max_rx_bw_mhz;
struct mm81x_rc_sta rc;
struct mmrc_rate last_sta_tx_rate;
s16 avg_rssi;
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index fa3b0cfccffe..d77df6e9af85 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -325,7 +325,7 @@ static int mm81x_mac_ops_start(struct ieee80211_hw *hw)
return 0;
}
-static int mm81x_tx_h_get_max_bw(struct mm81x *mors)
+static int mm81x_tx_h_get_max_tx_bw(struct mm81x *mors)
{
return MM81X_FW_SUPP(&mors->fw_caps, 8MHZ) ? 8 :
MM81X_FW_SUPP(&mors->fw_caps, 4MHZ) ? 4 :
@@ -1260,10 +1260,10 @@ static int mm81x_tx_h_get_bw(struct mm81x *mors, struct ieee80211_sta *sta,
if (sta)
mors_sta = (struct mm81x_sta *)sta->drv_priv;
- tx_bw_mhz = min(mm81x_tx_h_get_max_bw(mors),
+ tx_bw_mhz = min(mm81x_tx_h_get_max_tx_bw(mors),
cfg80211_chandef_get_width(&mors->chandef));
- if (mors_sta && mors_sta->max_bw_mhz)
- tx_bw_mhz = min(tx_bw_mhz, mors_sta->max_bw_mhz);
+ if (mors_sta && mors_sta->max_rx_bw_mhz)
+ tx_bw_mhz = min(tx_bw_mhz, mors_sta->max_rx_bw_mhz);
return tx_bw_mhz;
}
@@ -1718,6 +1718,9 @@ static int mm81x_mac_ops_sta_state(struct ieee80211_hw *hw,
mors_vif->u.ap.num_stas++;
else if (vif->type == NL80211_IFTYPE_STATION)
mors_vif->u.sta.is_assoc = true;
+
+ mors_sta->max_rx_bw_mhz =
+ S1G_SUPP_CH_WIDTH_MAX(sta->deflink.s1g_cap.cap);
}
if (new_state < old_state && new_state == IEEE80211_STA_NONE) {
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH wireless-next 8/8] wifi: mm81x: tx multicast frames from AP at primary width
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
` (6 preceding siblings ...)
2026-08-27 5:49 ` [PATCH wireless-next 7/8] wifi: mm81x: clamp tx width to stas max supported width Lachlan Hodges
@ 2026-08-27 5:49 ` Lachlan Hodges
7 siblings, 0 replies; 9+ messages in thread
From: Lachlan Hodges @ 2026-08-27 5:49 UTC (permalink / raw)
To: lachlan.hodges, dan.callaghan; +Cc: linux-wireless, arien.judge
If an AP has stations that are operating on a sub-primary (i.e using
the 4MHz primary of the 8MHz operating) multicast frames sent on the
operating width will be lost. Make sure we tx them on the primary width
to ensure all stations are capabile of receiving them.
Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
---
drivers/net/wireless/morsemicro/mm81x/mac.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/net/wireless/morsemicro/mm81x/mac.c b/drivers/net/wireless/morsemicro/mm81x/mac.c
index d77df6e9af85..4485748518b4 100644
--- a/drivers/net/wireless/morsemicro/mm81x/mac.c
+++ b/drivers/net/wireless/morsemicro/mm81x/mac.c
@@ -1257,6 +1257,15 @@ static int mm81x_tx_h_get_bw(struct mm81x *mors, struct ieee80211_sta *sta,
if (is_mgmt || info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)
return cfg80211_chandef_s1g_pri_width(&mors->chandef);
+ /*
+ * In AP mode group addressed frames go out at the primary width so
+ * that every associated STA can receive them, including any that
+ * cannot support the operating width.
+ */
+ if (info->control.vif->type == NL80211_IFTYPE_AP &&
+ is_multicast_ether_addr(ieee80211_get_DA(hdr)))
+ return cfg80211_chandef_s1g_pri_width(&mors->chandef);
+
if (sta)
mors_sta = (struct mm81x_sta *)sta->drv_priv;
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-08-27 5:50 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 5:49 [PATCH wireless-next 0/8] wifi: mm81x: mcast and tx bw improvements Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 1/8] wifi: mm81x: move beacon work and init below the tx op Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 2/8] wifi: mm81x: release buffered broadcast frames after DTIM Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 3/8] wifi: mm81x: do not drop PS filtered frames in AP mode Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 4/8] wifi: mm81x: implement .tx_frames_pending() mac op Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 5/8] wifi: mm81x: factor out tx width selection Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 6/8] wifi: mm81x: tx EAPOLs at primary width Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 7/8] wifi: mm81x: clamp tx width to stas max supported width Lachlan Hodges
2026-08-27 5:49 ` [PATCH wireless-next 8/8] wifi: mm81x: tx multicast frames from AP at primary width Lachlan Hodges
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox