Merge Official Source
This commit is contained in:
@@ -4,11 +4,10 @@
|
|||||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||||
if (!wdev->netdev)
|
if (!wdev->netdev)
|
||||||
continue;
|
continue;
|
||||||
- wdev->netdev->netns_immutable = false;
|
|
||||||
+#if LINUX_VERSION_IS_GEQ(6,15,0)
|
+#if LINUX_VERSION_IS_GEQ(6,15,0)
|
||||||
+ wdev->netdev->netns_immutable = true;
|
wdev->netdev->netns_immutable = false;
|
||||||
+#elif LINUX_VERSION_IS_GEQ(6,12,0)
|
+#elif LINUX_VERSION_IS_GEQ(6,12,0)
|
||||||
+ wdev->netdev->netns_local = true;
|
+ wdev->netdev->netns_local = false;
|
||||||
+#endif
|
+#endif
|
||||||
err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
|
err = dev_change_net_namespace(wdev->netdev, net, "wlan%d");
|
||||||
if (err)
|
if (err)
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
From f4e661a75cdfa7eb88ac0fa832edd4a90775805d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pawel Dembicki <paweldembicki@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@hotmail.com>
|
||||||
|
Signed-off-by: Pawel Dembicki <paweldembicki@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);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
--- a/drivers/net/wireless/marvell/mwl8k.c
|
--- a/drivers/net/wireless/marvell/mwl8k.c
|
||||||
+++ b/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));
|
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
|
||||||
|
|
||||||
static const struct pci_device_id mwl8k_pci_id_table[] = {
|
static const struct pci_device_id mwl8k_pci_id_table[] = {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
--- a/drivers/net/wireless/marvell/mwl8k.c
|
--- a/drivers/net/wireless/marvell/mwl8k.c
|
||||||
+++ b/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;
|
priv->running_bsses = 0;
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
err_stop_firmware:
|
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;
|
return;
|
||||||
priv = hw->priv;
|
priv = hw->priv;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user