[openwrt/openwrt] mac80211: mwl8k: inject DSSS Parameter Set element into beacons if missing

LEDE Commits lede-commits at lists.infradead.org
Sat Nov 15 13:12:21 PST 2025


hauke pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/38ed1510dbe80a37fd35b9a47e937a32a5a673bd

commit 38ed1510dbe80a37fd35b9a47e937a32a5a673bd
Author: Pawel Dembicki <paweldembicki at gmail.com>
AuthorDate: Wed Nov 12 22:33:24 2025 +0100

    mac80211: mwl8k: inject DSSS Parameter Set element into beacons if missing
    
    Some Marvell AP firmware used with mwl8k misbehaves when beacons do not
    contain the DSSS Parameter Set (WLAN_EID_DS_PARAMS) with the current
    channel. When hostapd/mac80211 omits this element (which is valid on
    some bands), the firmware may report bogus RX channel information and AP
    mode becomes unusable.
    
    Backport the upstream fix that ensures beacons always carry the DSSS
    Parameter Set for mwl8k: when setting the beacon, detect if the element
    is missing and inject it after SSID and Supported Rates (per spec
    ordering). This mirrors behaviour in newer Marvell drivers and restores
    stable operation.
    
    Tested on Linksys EA4500 (88W8366).
    
    Fixes: openwrt/openwrt#19088
    Link: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git/commit/?id=c4e1ac09ee1c750890e36cb1f841f25518f23589
    
    Signed-off-by: Pawel Dembicki <paweldembicki at gmail.com>
    Link: https://github.com/openwrt/openwrt/pull/20757
    Signed-off-by: Hauke Mehrtens <hauke at hauke-m.de>
---
 ...ject-DS-Params-IE-into-beacons-if-missing.patch | 116 +++++++++++++++++++++
 .../mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch |   2 +-
 .../mwl/940-mwl8k_init_devices_synchronously.patch |   4 +-
 3 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/package/kernel/mac80211/patches/mwl/001-mwl8k-inject-DS-Params-IE-into-beacons-if-missing.patch b/package/kernel/mac80211/patches/mwl/001-mwl8k-inject-DS-Params-IE-into-beacons-if-missing.patch
new file mode 100644
index 0000000000..ca66c9c302
--- /dev/null
+++ b/package/kernel/mac80211/patches/mwl/001-mwl8k-inject-DS-Params-IE-into-beacons-if-missing.patch
@@ -0,0 +1,116 @@
+From f4e661a75cdfa7eb88ac0fa832edd4a90775805d Mon Sep 17 00:00:00 2001
+From: Pawel Dembicki <paweldembicki at gmail.com>
+Date: Fri, 7 Nov 2025 23:05:56 +0100
+Subject: [PATCH] mwl8k: inject DS Params IE into beacons if missing
+
+Some Marvell AP firmware used with mwl8k misbehaves when beacon frames
+do not contain a WLAN_EID_DS_PARAMS information element with the current
+channel. It was reported on OpenWrt Github issues [0].
+
+When hostapd/mac80211 omits DS Params from the beacon (which is valid on
+some bands), the firmware stops transmitting sane frames and RX status
+starts reporting bogus channel information. This makes AP mode unusable.
+
+Newer Marvell drivers (mwlwifi [1]) hard-code DS Params IE into AP beacons
+for all chips, which suggests this is a firmware requirement rather than
+a mwl8k-specific quirk.
+
+Mirror that behaviour in mwl8k: when setting the beacon, check if
+WLAN_EID_DS_PARAMS is present, and if not, extend the beacon and inject
+a DS Params IE at the beginning of the IE list, using the current
+channel from hw->conf.chandef.chan.
+
+Tested on Linksys EA4500 (88W8366).
+
+[0] https://github.com/openwrt/openwrt/issues/19088
+[1] https://github.com/kaloz/mwlwifi/blob/db97edf20fadea2617805006f5230665fadc6a8c/hif/fwcmd.c#L675
+
+Tested-by: Antony Kolitsos <zeusomighty at hotmail.com>
+Signed-off-by: Pawel Dembicki <paweldembicki at gmail.com>
+---
+ drivers/net/wireless/marvell/mwl8k.c | 61 +++++++++++++++++++++++++---
+ 1 file changed, 56 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/marvell/mwl8k.c
++++ b/drivers/net/wireless/marvell/mwl8k.c
+@@ -2962,6 +2962,42 @@ mwl8k_cmd_rf_antenna(struct ieee80211_hw
+ /*
+  * CMD_SET_BEACON.
+  */
++
++static bool mwl8k_beacon_has_ds_params(const u8 *buf, int len)
++{
++	const struct ieee80211_mgmt *mgmt = (const void *)buf;
++	int ies_len;
++
++	if (len <= offsetof(struct ieee80211_mgmt, u.beacon.variable))
++		return false;
++
++	ies_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
++
++	return cfg80211_find_ie(WLAN_EID_DS_PARAMS, mgmt->u.beacon.variable,
++				ies_len) != NULL;
++}
++
++static void mwl8k_beacon_copy_inject_ds_params(struct ieee80211_hw *hw,
++					       u8 *buf_dst, const u8 *buf_src,
++					       int src_len)
++{
++	const struct ieee80211_mgmt *mgmt = (const void *)buf_src;
++	const u8 *ies;
++	int hdr_len, left;
++
++	ies = mgmt->u.beacon.variable;
++	hdr_len = ies - buf_src;
++	left = src_len - hdr_len;
++
++	memcpy(buf_dst, buf_src, hdr_len);
++
++	/* Inject a DS Params IE at the beginning of the IE list */
++	buf_dst[hdr_len + 0] = WLAN_EID_DS_PARAMS;
++	buf_dst[hdr_len + 1] = 1;
++	buf_dst[hdr_len + 2] = hw->conf.chandef.chan->hw_value;
++
++	memcpy(buf_dst + hdr_len + 3, buf_src + hdr_len, left);
++}
+ struct mwl8k_cmd_set_beacon {
+ 	struct mwl8k_cmd_pkt_hdr header;
+ 	__le16 beacon_len;
+@@ -2971,17 +3007,32 @@ struct mwl8k_cmd_set_beacon {
+ static int mwl8k_cmd_set_beacon(struct ieee80211_hw *hw,
+ 				struct ieee80211_vif *vif, u8 *beacon, int len)
+ {
++	bool ds_params_present = mwl8k_beacon_has_ds_params(beacon, len);
+ 	struct mwl8k_cmd_set_beacon *cmd;
+-	int rc;
++	int rc, final_len = len;
++
++	if (!ds_params_present)
++		/*
++		 * mwl8k firmware requires a DS Params IE with the current
++		 * channel in AP beacons. If mac80211/hostapd does not
++		 * include it, inject one here. IE ID + length + channel
++		 * number = 3 bytes.
++		 */
++		final_len += 3;
+ 
+-	cmd = kzalloc(sizeof(*cmd) + len, GFP_KERNEL);
++	cmd = kzalloc(sizeof(*cmd) + final_len, GFP_KERNEL);
+ 	if (cmd == NULL)
+ 		return -ENOMEM;
+ 
+ 	cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_BEACON);
+-	cmd->header.length = cpu_to_le16(sizeof(*cmd) + len);
+-	cmd->beacon_len = cpu_to_le16(len);
+-	memcpy(cmd->beacon, beacon, len);
++	cmd->header.length = cpu_to_le16(sizeof(*cmd) + final_len);
++	cmd->beacon_len = cpu_to_le16(final_len);
++
++	if (ds_params_present)
++		memcpy(cmd->beacon, beacon, len);
++	else
++		mwl8k_beacon_copy_inject_ds_params(hw, cmd->beacon, beacon,
++						   len);
+ 
+ 	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+ 	kfree(cmd);
diff --git a/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch b/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch
index cfb7dcf738..3998afcfbc 100644
--- a/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch
+++ b/package/kernel/mac80211/patches/mwl/700-mwl8k-missing-pci-id-for-WNR854T.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/marvell/mwl8k.c
 +++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -5712,6 +5712,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
+@@ -5763,6 +5763,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
  MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
  
  static const struct pci_device_id mwl8k_pci_id_table[] = {
diff --git a/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch b/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch
index d09cfac448..a229be9961 100644
--- a/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch
+++ b/package/kernel/mac80211/patches/mwl/940-mwl8k_init_devices_synchronously.patch
@@ -1,6 +1,6 @@
 --- a/drivers/net/wireless/marvell/mwl8k.c
 +++ b/drivers/net/wireless/marvell/mwl8k.c
-@@ -6298,6 +6298,8 @@ static int mwl8k_probe(struct pci_dev *p
+@@ -6349,6 +6349,8 @@ static int mwl8k_probe(struct pci_dev *p
  
  	priv->running_bsses = 0;
  
@@ -9,7 +9,7 @@
  	return rc;
  
  err_stop_firmware:
-@@ -6331,8 +6333,6 @@ static void mwl8k_remove(struct pci_dev
+@@ -6382,8 +6384,6 @@ static void mwl8k_remove(struct pci_dev
  		return;
  	priv = hw->priv;
  




More information about the lede-commits mailing list