Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 0/2] wifi: mt76: fix NAT performance degradation on MT799x
From: Dmitry Gomzyakov @ 2026-05-10 10:29 UTC (permalink / raw)
  To: linux-wireless; +Cc: Dmitry Gomzyakov

From: Dmitry Gomzyakov <nicerok11@gmail.com>

This series fixes severe IPv4 NAT download performance degradation
(30-40 Mbps limit) observed on MT799x platforms (MT7987A+MT7991A,
MT7992, MT7996).

Patch 1 adds MT7991A (0x7991) to is_mt7996() to ensure correct
chip-specific settings are used.

Patch 2 restores host-driven TXWI filling for all packets, fixing
firmware misinterpretation of NAT-modified IPv4 packets.

Dmitry Gomzyakov (2):
  wifi: mt76: connac: add MT7991A (0x7991) to is_mt7996()
  wifi: mt76: mt7996: always fill txwi for 802.3 packets

 mt76_connac.h |  3 ++-
 mt7996/mac.c  | 12 +++++-------
 2 files changed, 7 insertions(+), 8 deletions(-)

--
2.54.0

^ permalink raw reply

* [PATCH 3/3] Fix PERR frame processing
From: Masashi Honma @ 2026-05-09 23:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Masashi Honma
In-Reply-To: <20260509234143.101237-1-masashi.honma@gmail.com>

There are no issues with the PERR processing itself; however, to maintain
consistency with the previous PREQ/PREP code modifications, I will create a new
mesh_path_parse_error_frame() function to separately implement the frame format
validation and the "not supported" check.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
 include/linux/ieee80211-mesh.h | 38 ++++++++++++++++++++++++++++++++++
 net/mac80211/mesh_hwmp.c       | 11 ++++++++--
 net/mac80211/parse.c           |  9 ++++++--
 3 files changed, 54 insertions(+), 4 deletions(-)

diff --git a/include/linux/ieee80211-mesh.h b/include/linux/ieee80211-mesh.h
index ddbf475c1cc8..1bca65e49309 100644
--- a/include/linux/ieee80211-mesh.h
+++ b/include/linux/ieee80211-mesh.h
@@ -61,6 +61,7 @@ struct ieee80211s_hdr {
 #define PREP_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
 
 #define PERR_IE_TTL(x)			(*(x))
+#define PERR_IE_NUMBER_OF_DST(x)	(*(x + 1))
 #define PERR_IE_TARGET_FLAGS(x)		(*(x + 2))
 #define PERR_IE_TARGET_ADDR(x)		(x + 3)
 #define PERR_IE_TARGET_SN(x)		u32_field_get(x, 9, 0)
@@ -301,4 +302,41 @@ static inline bool ieee80211_mesh_prep_size_ok(const u8 *pos, u8 elen)
 	return true;
 }
 
+/* IEEE Std 802.11-2016 9.4.2.115 PERR element */
+static inline bool ieee80211_mesh_perr_size_ok(const u8 *pos, u8 elen)
+{
+	u8 number_of_dst;
+	u8 needed;
+	const u8 *start;
+	int i;
+
+	number_of_dst = PERR_IE_NUMBER_OF_DST(pos);
+	if (number_of_dst < 1 || number_of_dst > 19)
+		return false;
+
+	start = pos;
+	needed = 1 /* Element TTL */ + 1 /* Number of Destinations */;
+	pos += 2;
+
+	for (i = 0; i < number_of_dst; i++) {
+		u8 dst_len;
+
+		if (pos - start >= elen)
+			return false;
+
+		dst_len = 1 /* Flags */ + 6 /* Destination Address */ +
+			  4 /* HWMP Sequence Number */ +
+			  (AE_F_SET(pos) ? 6 : 0)
+			  /* Destination External Address */ +
+			  2 /* Reason Code */;
+		needed += dst_len;
+		pos += dst_len;
+	}
+
+	if (elen != needed)
+		return false;
+
+	return true;
+}
+
 #endif /* LINUX_IEEE80211_MESH_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c70cfc2d6299..d2295aa54bb4 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -902,6 +902,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 	u32 path_metric;
 	struct sta_info *sta;
 	u8 target_count;
+	u8 number_of_dst;
 
 	/* need action_code */
 	if (len < IEEE80211_MIN_ACTION_SIZE(mesh_action))
@@ -952,9 +953,15 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 						path_metric);
 	}
 	if (elems->perr) {
-		if (elems->perr_len != 15)
-			/* Right now we support only one destination per PERR */
+		/* Right now we support only one destination per PERR */
+		number_of_dst = PERR_IE_NUMBER_OF_DST(elems->perr);
+		if (number_of_dst != 1)
 			goto free;
+
+		/* Right now we do not support AE (Address Extension) */
+		if (PERR_IE_TARGET_FLAGS(elems->perr) & AE_F)
+			goto free;
+
 		hwmp_perr_frame_process(sdata, mgmt, elems->perr);
 	}
 	if (elems->rann)
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index bbd1e1bc77b4..d84e5e12ad24 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -565,8 +565,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 			}
 			break;
 		case WLAN_EID_PERR:
-			elems->perr = pos;
-			elems->perr_len = elen;
+			if (ieee80211_mesh_perr_size_ok(pos, elen)) {
+				elems->perr = pos;
+				elems->perr_len = elen;
+			} else {
+				elem_parse_failed =
+					IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+			}
 			break;
 		case WLAN_EID_RANN:
 			if (elen >= sizeof(struct ieee80211_rann_ie))
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/3] Fix overread in PREP frame processing
From: Masashi Honma @ 2026-05-09 23:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Masashi Honma
In-Reply-To: <20260509234143.101237-1-masashi.honma@gmail.com>

When the AF flag is enabled, hwmp_prep_frame_process() overreads orig_addr
by 2 bytes. Since this occurs within the socket buffer, it does not read across
memory boundaries and therefore poses no security risk; however, we will fix it
as a precaution.

In this fix, a new function mesh_path_parse_reply_frame() is established to
separate the implementation of frame format validation and the check for
unsupported features. This is intended to facilitate future work when
implementing the currently unsupported parts.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
 include/linux/ieee80211-mesh.h | 18 ++++++++++++++++++
 net/mac80211/mesh_hwmp.c       |  5 +++--
 net/mac80211/parse.c           |  9 +++++++--
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/include/linux/ieee80211-mesh.h b/include/linux/ieee80211-mesh.h
index 8ff68cf539ff..ddbf475c1cc8 100644
--- a/include/linux/ieee80211-mesh.h
+++ b/include/linux/ieee80211-mesh.h
@@ -283,4 +283,22 @@ static inline bool ieee80211_mesh_preq_size_ok(const u8 *pos, u8 elen)
 	return true;
 }
 
+/* IEEE Std 802.11-2016 9.4.2.114 PREP element */
+static inline bool ieee80211_mesh_prep_size_ok(const u8 *pos, u8 elen)
+{
+	u8 needed;
+
+	needed = 1 /* Flags */ + 1 /* Hop Count */ + 1 /* Element TTL */ +
+		 6 /* Target Mesh STA Address */ +
+		 4 /* Target HWMP Sequence Number */ +
+		 (AE_F_SET(pos) ? 6 : 0) /* Target External Address */ +
+		 4 /* Lifetime */ + 4 /* Metric */ +
+		 6 /* Originator Mesh STA Address */ +
+		 4 /* Originator HWMP Sequence Number */;
+	if (elen != needed)
+		return false;
+
+	return true;
+}
+
 #endif /* LINUX_IEEE80211_MESH_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index a4984b015995..c70cfc2d6299 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -941,9 +941,10 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 						path_metric);
 	}
 	if (elems->prep) {
-		if (elems->prep_len != 31)
-			/* Right now we support no AE */
+		/* Right now we do not support AE (Address Extension) */
+		if (AE_F_SET(elems->prep))
 			goto free;
+
 		path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep,
 						  MPATH_PREP);
 		if (path_metric)
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index 9e52cc48fc18..bbd1e1bc77b4 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -556,8 +556,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 			}
 			break;
 		case WLAN_EID_PREP:
-			elems->prep = pos;
-			elems->prep_len = elen;
+			if (ieee80211_mesh_prep_size_ok(pos, elen)) {
+				elems->prep = pos;
+				elems->prep_len = elen;
+			} else {
+				elem_parse_failed =
+					IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+			}
 			break;
 		case WLAN_EID_PERR:
 			elems->perr = pos;
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/3] Fix overread in PREQ frame processing
From: Masashi Honma @ 2026-05-09 23:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Masashi Honma
In-Reply-To: <db11380dfbe7fff538a1a052fdfc5905202981a4.camel@sipsolutions.net>

When the AF flag is enabled, hwmp_preq_frame_process() overreads target_addr
by 2 bytes. Since this occurs within the socket buffer, it does not read across
memory boundaries and therefore poses no security risk; however, we will fix it
as a precaution.

In this fix, a new function mesh_path_parse_request_frame() is established to
separate the implementation of frame format validation and the check for
unsupported features. This is intended to facilitate future work when
implementing the currently unsupported parts.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
 include/linux/ieee80211-mesh.h | 56 ++++++++++++++++++++++++++++++++++
 net/mac80211/mesh_hwmp.c       | 42 ++++++-------------------
 net/mac80211/parse.c           |  9 ++++--
 3 files changed, 72 insertions(+), 35 deletions(-)

diff --git a/include/linux/ieee80211-mesh.h b/include/linux/ieee80211-mesh.h
index 4b829bcb38b6..8ff68cf539ff 100644
--- a/include/linux/ieee80211-mesh.h
+++ b/include/linux/ieee80211-mesh.h
@@ -34,6 +34,38 @@ struct ieee80211s_hdr {
 #define MESH_FLAGS_AE		0x3
 #define MESH_FLAGS_PS_DEEP	0x4
 
+/* HWMP IE processing macros */
+#define AE_F			(1<<6)
+#define AE_F_SET(x)		(*x & AE_F)
+#define PREQ_IE_FLAGS(x)	(*(x))
+#define PREQ_IE_HOPCOUNT(x)	(*(x + 1))
+#define PREQ_IE_TTL(x)		(*(x + 2))
+#define PREQ_IE_PREQ_ID(x)	u32_field_get(x, 3, 0)
+#define PREQ_IE_ORIG_ADDR(x)	(x + 7)
+#define PREQ_IE_ORIG_SN(x)	u32_field_get(x, 13, 0)
+#define PREQ_IE_LIFETIME(x)	u32_field_get(x, 17, AE_F_SET(x))
+#define PREQ_IE_METRIC(x) 	u32_field_get(x, 21, AE_F_SET(x))
+#define PREQ_IE_TARGET_COUNT(x)	(*(AE_F_SET(x) ? x + 31 : x + 25))
+#define PREQ_IE_TARGET_F(x)	(*(AE_F_SET(x) ? x + 32 : x + 26))
+#define PREQ_IE_TARGET_ADDR(x) 	(AE_F_SET(x) ? x + 33 : x + 27)
+#define PREQ_IE_TARGET_SN(x) 	u32_field_get(x, 33, AE_F_SET(x))
+
+#define PREP_IE_FLAGS(x)	PREQ_IE_FLAGS(x)
+#define PREP_IE_HOPCOUNT(x)	PREQ_IE_HOPCOUNT(x)
+#define PREP_IE_TTL(x)		PREQ_IE_TTL(x)
+#define PREP_IE_ORIG_ADDR(x)	(AE_F_SET(x) ? x + 27 : x + 21)
+#define PREP_IE_ORIG_SN(x)	u32_field_get(x, 27, AE_F_SET(x))
+#define PREP_IE_LIFETIME(x)	u32_field_get(x, 13, AE_F_SET(x))
+#define PREP_IE_METRIC(x)	u32_field_get(x, 17, AE_F_SET(x))
+#define PREP_IE_TARGET_ADDR(x)	(x + 3)
+#define PREP_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
+
+#define PERR_IE_TTL(x)			(*(x))
+#define PERR_IE_TARGET_FLAGS(x)		(*(x + 2))
+#define PERR_IE_TARGET_ADDR(x)		(x + 3)
+#define PERR_IE_TARGET_SN(x)		u32_field_get(x, 9, 0)
+#define PERR_IE_TARGET_RCODE(x)		u16_field_get(x, 13, 0)
+
 /**
  * enum ieee80211_preq_flags - mesh PREQ element flags
  *
@@ -227,4 +259,28 @@ enum ieee80211_root_mode_identifier {
 	IEEE80211_PROACTIVE_RANN = 4,
 };
 
+/* IEEE Std 802.11-2016 9.4.2.113 PREQ element */
+static inline bool ieee80211_mesh_preq_size_ok(const u8 *pos, u8 elen)
+{
+	u8 target_count;
+	u8 needed;
+
+	target_count = PREQ_IE_TARGET_COUNT(pos);
+	if (target_count < 1 || target_count > 20)
+		return false;
+
+	needed = 1 /* Flags */ + 1 /* Hop Count */ + 1 /* Element TTL */ +
+		 4 /* Path Discovery ID */ +
+		 6 /* Originator Mesh STA Address */ +
+		 4 /* Originator HWMP Sequence Number */ +
+		 (AE_F_SET(pos) ? 6 : 0) /* Originator External Address */ +
+		 4 /* Lifetime */ + 4 /* Metric */ + 1 + /* Target Count */ +
+		 target_count * (1 /* Per Target Flags */ +
+		 6 /* Target Address */ + 4 /* Target HWMP Sequence Number */);
+	if (elen != needed)
+		return false;
+
+	return true;
+}
+
 #endif /* LINUX_IEEE80211_MESH_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 9d89ebcce1c1..a4984b015995 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -35,37 +35,6 @@ static inline u16 u16_field_get(const u8 *preq_elem, int offset, bool ae)
 }
 
 /* HWMP IE processing macros */
-#define AE_F			(1<<6)
-#define AE_F_SET(x)		(*x & AE_F)
-#define PREQ_IE_FLAGS(x)	(*(x))
-#define PREQ_IE_HOPCOUNT(x)	(*(x + 1))
-#define PREQ_IE_TTL(x)		(*(x + 2))
-#define PREQ_IE_PREQ_ID(x)	u32_field_get(x, 3, 0)
-#define PREQ_IE_ORIG_ADDR(x)	(x + 7)
-#define PREQ_IE_ORIG_SN(x)	u32_field_get(x, 13, 0)
-#define PREQ_IE_LIFETIME(x)	u32_field_get(x, 17, AE_F_SET(x))
-#define PREQ_IE_METRIC(x) 	u32_field_get(x, 21, AE_F_SET(x))
-#define PREQ_IE_TARGET_F(x)	(*(AE_F_SET(x) ? x + 32 : x + 26))
-#define PREQ_IE_TARGET_ADDR(x) 	(AE_F_SET(x) ? x + 33 : x + 27)
-#define PREQ_IE_TARGET_SN(x) 	u32_field_get(x, 33, AE_F_SET(x))
-
-
-#define PREP_IE_FLAGS(x)	PREQ_IE_FLAGS(x)
-#define PREP_IE_HOPCOUNT(x)	PREQ_IE_HOPCOUNT(x)
-#define PREP_IE_TTL(x)		PREQ_IE_TTL(x)
-#define PREP_IE_ORIG_ADDR(x)	(AE_F_SET(x) ? x + 27 : x + 21)
-#define PREP_IE_ORIG_SN(x)	u32_field_get(x, 27, AE_F_SET(x))
-#define PREP_IE_LIFETIME(x)	u32_field_get(x, 13, AE_F_SET(x))
-#define PREP_IE_METRIC(x)	u32_field_get(x, 17, AE_F_SET(x))
-#define PREP_IE_TARGET_ADDR(x)	(x + 3)
-#define PREP_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
-
-#define PERR_IE_TTL(x)		(*(x))
-#define PERR_IE_TARGET_FLAGS(x)	(*(x + 2))
-#define PERR_IE_TARGET_ADDR(x)	(x + 3)
-#define PERR_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
-#define PERR_IE_TARGET_RCODE(x)	u16_field_get(x, 13, 0)
-
 #define MSEC_TO_TU(x) (x*1000/1024)
 #define SN_GT(x, y) ((s32)(y - x) < 0)
 #define SN_LT(x, y) ((s32)(x - y) < 0)
@@ -932,6 +901,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 	size_t baselen;
 	u32 path_metric;
 	struct sta_info *sta;
+	u8 target_count;
 
 	/* need action_code */
 	if (len < IEEE80211_MIN_ACTION_SIZE(mesh_action))
@@ -955,9 +925,15 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 		return;
 
 	if (elems->preq) {
-		if (elems->preq_len != 37)
-			/* Right now we support just 1 destination and no AE */
+		/* Right now we do not support AE (Address Extension) */
+		if (AE_F_SET(elems->preq))
+			goto free;
+
+		/* Right now we only supports 1 target */
+		target_count = PREQ_IE_TARGET_COUNT(elems->preq);
+		if (target_count != 1)
 			goto free;
+
 		path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq,
 						  MPATH_PREQ);
 		if (path_metric)
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index 5e61457be0f3..9e52cc48fc18 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -547,8 +547,13 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 				elems->awake_window = (void *)pos;
 			break;
 		case WLAN_EID_PREQ:
-			elems->preq = pos;
-			elems->preq_len = elen;
+			if (ieee80211_mesh_preq_size_ok(pos, elen)) {
+				elems->preq = pos;
+				elems->preq_len = elen;
+			} else {
+				elem_parse_failed =
+					IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+			}
 			break;
 		case WLAN_EID_PREP:
 			elems->prep = pos;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH wireless-next] wifi: rt2x00: allocate anchor with rt2x00dev
From: Rosen Penev @ 2026-05-09 21:18 UTC (permalink / raw)
  To: Stanislaw Gruszka; +Cc: linux-wireless, open list
In-Reply-To: <20260509101326.GA2170@wp.pl>

On Sat, May 9, 2026 at 3:13 AM Stanislaw Gruszka <stf_xl@wp.pl> wrote:
>
> Hi,
>
> On Thu, Apr 30, 2026 at 04:22:06PM -0700, Rosen Penev wrote:
> > Instead of being creative with devm, allocate with rt2x00dev by using a
> > flexible array member. Simplifies code slightly.
>
> I think this patch is more creative. Using a flexible array member
> is less conventional than the current approach of allocating separately
> and storing a pointer. But OK, lets get rid of 9 LOC.
I don't see how a FAM is more creative. It's a single allocation. It
also takes up less struct space as the pointer gets removed. The other
usage of ieee80211_alloc_hw and struct_size is in ath12k:

drivers/net/wireless/ath/ath12k/mac.c: hw =
ieee80211_alloc_hw(struct_size(ah, radio, num_pdev_map),

Actually there are more but instead of struct_size they use manual addition.
>
> Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
>
> > It's worth noting that in 25369b22223d1c56e42a0cd4ac9137349d5a898e , the
> > proper device was set to the devm call as it seems there was confusion
> > there.
> >
> > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> >
> > ---
> >  drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  3 ++-
> >  drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 11 +----------
> >  2 files changed, 3 insertions(+), 11 deletions(-)
> >
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> > index 665887e9b118..7d313e86d3f2 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> > @@ -1009,11 +1009,12 @@ struct rt2x00_dev {
> >       /* Extra TX headroom required for alignment purposes. */
> >       unsigned int extra_tx_headroom;
> >
> > -     struct usb_anchor *anchor;
> >       unsigned int num_proto_errs;
> >
> >       /* Clock for System On Chip devices. */
> >       struct clk *clk;
> > +
> > +     struct usb_anchor anchor[];
> >  };
> >
> >  struct rt2x00_bar_list_entry {
> > diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
> > index 174d89b0b1d7..47e427ea8622 100644
> > --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
> > +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
> > @@ -804,7 +804,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
> >
> >       usb_reset_device(usb_dev);
> >
> > -     hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
> > +     hw = ieee80211_alloc_hw(struct_size(rt2x00dev, anchor, 1), ops->hw);
> >       if (!hw) {
> >               rt2x00_probe_err("Failed to allocate hardware\n");
> >               return -ENOMEM;
> > @@ -826,13 +826,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
> >       if (retval)
> >               goto exit_free_device;
> >
> > -     rt2x00dev->anchor = devm_kmalloc(&usb_intf->dev,
> > -                                     sizeof(struct usb_anchor),
> > -                                     GFP_KERNEL);
> > -     if (!rt2x00dev->anchor) {
> > -             retval = -ENOMEM;
> > -             goto exit_free_reg;
> > -     }
> >       init_usb_anchor(rt2x00dev->anchor);
> >
> >       retval = rt2x00lib_probe_dev(rt2x00dev);
> > @@ -843,8 +836,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
> >
> >  exit_free_anchor:
> >       usb_kill_anchored_urbs(rt2x00dev->anchor);
> > -
> > -exit_free_reg:
> >       rt2x00usb_free_reg(rt2x00dev);
> >
> >  exit_free_device:
> > --
> > 2.54.0
> >

^ permalink raw reply

* Re: [PATCH wireless-next] wifi: rt2x00: allocate anchor with rt2x00dev
From: Stanislaw Gruszka @ 2026-05-09 10:13 UTC (permalink / raw)
  To: Rosen Penev; +Cc: linux-wireless, open list
In-Reply-To: <20260430232206.141461-1-rosenp@gmail.com>

Hi,

On Thu, Apr 30, 2026 at 04:22:06PM -0700, Rosen Penev wrote:
> Instead of being creative with devm, allocate with rt2x00dev by using a
> flexible array member. Simplifies code slightly.

I think this patch is more creative. Using a flexible array member
is less conventional than the current approach of allocating separately
and storing a pointer. But OK, lets get rid of 9 LOC.

Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>

> It's worth noting that in 25369b22223d1c56e42a0cd4ac9137349d5a898e , the
> proper device was set to the devm call as it seems there was confusion
> there.
> 
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
>
> ---
>  drivers/net/wireless/ralink/rt2x00/rt2x00.h    |  3 ++-
>  drivers/net/wireless/ralink/rt2x00/rt2x00usb.c | 11 +----------
>  2 files changed, 3 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> index 665887e9b118..7d313e86d3f2 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h
> @@ -1009,11 +1009,12 @@ struct rt2x00_dev {
>  	/* Extra TX headroom required for alignment purposes. */
>  	unsigned int extra_tx_headroom;
> 
> -	struct usb_anchor *anchor;
>  	unsigned int num_proto_errs;
> 
>  	/* Clock for System On Chip devices. */
>  	struct clk *clk;
> +
> +	struct usb_anchor anchor[];
>  };
> 
>  struct rt2x00_bar_list_entry {
> diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
> index 174d89b0b1d7..47e427ea8622 100644
> --- a/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
> +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00usb.c
> @@ -804,7 +804,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
> 
>  	usb_reset_device(usb_dev);
> 
> -	hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
> +	hw = ieee80211_alloc_hw(struct_size(rt2x00dev, anchor, 1), ops->hw);
>  	if (!hw) {
>  		rt2x00_probe_err("Failed to allocate hardware\n");
>  		return -ENOMEM;
> @@ -826,13 +826,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
>  	if (retval)
>  		goto exit_free_device;
> 
> -	rt2x00dev->anchor = devm_kmalloc(&usb_intf->dev,
> -					sizeof(struct usb_anchor),
> -					GFP_KERNEL);
> -	if (!rt2x00dev->anchor) {
> -		retval = -ENOMEM;
> -		goto exit_free_reg;
> -	}
>  	init_usb_anchor(rt2x00dev->anchor);
> 
>  	retval = rt2x00lib_probe_dev(rt2x00dev);
> @@ -843,8 +836,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
> 
>  exit_free_anchor:
>  	usb_kill_anchored_urbs(rt2x00dev->anchor);
> -
> -exit_free_reg:
>  	rt2x00usb_free_reg(rt2x00dev);
> 
>  exit_free_device:
> --
> 2.54.0
> 

^ permalink raw reply

* Re: [PATCH] wifi: mt76: mt792x: fix NULL dereference during CSA beacon handling
From: Bongani Hlope @ 2026-05-09  8:23 UTC (permalink / raw)
  To: Sean Wang
  Cc: Felix Fietkau, Lorenzo Bianconi, linux-wireless, linux-mediatek,
	Sean Wang
In-Reply-To: <20260503004613.17903-1-sean.wang@kernel.org>

Sorry I had some down time on my mail server. I can confirm this patch
works for me, I have been running with it since you sent it through.

Regards

On Sat,  2 May 2026 19:46:13 -0500
Sean Wang <sean.wang@kernel.org> wrote:

> From: Sean Wang <sean.wang@mediatek.com>
> 
> mac80211 may call channel_switch_rx_beacon() while CSA is active, but
> mt76's cached dev->new_ctx is not guaranteed to be valid at that
> point.
> 
> Avoid dereferencing dev->new_ctx when the target channel context is
> not available and leave the existing CSA timer unchanged.
> 
> kernel: Workqueue: events_unbound cfg80211_wiphy_work [cfg80211]
> kernel: RIP: 0010:mt7921_channel_switch_rx_beacon+0x1f/0x100
> [mt7921_common]
> kernel: RAX: 0000000000000000
> kernel: CR2: 0000000000000000
> kernel: Call Trace:
> kernel:  <TASK>
> kernel:  ieee80211_sta_process_chanswitch+0x67c/0xee0 [mac80211]
> kernel:  ieee80211_rx_mgmt_beacon+0x842/0x22a0 [mac80211]
> kernel:  ieee80211_sta_rx_queued_mgmt+0xa7/0xbb0 [mac80211]
> kernel:  ieee80211_iface_work+0x62e/0x890 [mac80211]
> kernel:  cfg80211_wiphy_work+0x1ee/0x280 [cfg80211]
> kernel:  process_scheduled_works+0x180/0x680
> kernel:  worker_thread+0x1aa/0x450
> kernel:  kthread+0x181/0x1e0
> kernel:  ret_from_fork+0x405/0x600
> kernel:  ret_from_fork_asm+0x11/0x20
> kernel:  </TASK>
> kernel: CR2: 0000000000000000
> kernel: ---[ end trace 0000000000000000 ]---
> 
> mt7925 has the same unsafe dev->new_ctx dereference in its CSA beacon
> handling path, so guard both drivers against the missing target
> channel context and leave the existing CSA timer unchanged.
> 
> Reported-by: Bongani Hlope <developer@hlope.org.za>
> Closes:
> https://lore.kernel.org/linux-wireless/20260502140616.7672da98@bongani-mini.home.org.za/
> Fixes: 8aa2f59260eb ("wifi: mt76: mt7921: introduce CSA support")
> Fixes: 7900da40e315 ("wifi: mt76: mt7925: introduce CSA support in
> non-MLO mode") Signed-off-by: Sean Wang <sean.wang@mediatek.com> ---
>  drivers/net/wireless/mediatek/mt76/mt7921/main.c | 3 +++
>  drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++
>  2 files changed, 6 insertions(+)
> 
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
> b/drivers/net/wireless/mediatek/mt76/mt7921/main.c index
> 3d74fabe7408..a326f4c95c7c 100644 ---
> a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++
> b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -1508,6 +1508,9
> @@ static void mt7921_channel_switch_rx_beacon(struct ieee80211_hw
> *hw, struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
> u16 beacon_interval = vif->bss_conf.beacon_int; 
> +	if (!dev->new_ctx)
> +		return;
> +
>  	if (cfg80211_chandef_identical(&chsw->chandef,
>  				       &dev->new_ctx->def) &&
>  				       chsw->count) {
> diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
> b/drivers/net/wireless/mediatek/mt76/mt7925/main.c index
> 73d3722739d0..b96a8e2efcbc 100644 ---
> a/drivers/net/wireless/mediatek/mt76/mt7925/main.c +++
> b/drivers/net/wireless/mediatek/mt76/mt7925/main.c @@ -2402,6 +2402,9
> @@ static void mt7925_channel_switch_rx_beacon(struct ieee80211_hw
> *hw, beacon_interval = vif->bss_conf.beacon_int;
>  
> +	if (!dev->new_ctx)
> +		return;
> +
>  	if (cfg80211_chandef_identical(&chsw->chandef,
>  				       &dev->new_ctx->def) &&
>  				       chsw->count) {


^ permalink raw reply

* Re: [PATCH 1/3] Fix overread in PREQ frame processing
From: Johannes Berg @ 2026-05-09  9:17 UTC (permalink / raw)
  To: Masashi Honma, linux-wireless
In-Reply-To: <20260508225905.29998-1-masashi.honma@gmail.com>

On Sat, 2026-05-09 at 07:59 +0900, Masashi Honma wrote:
>  
> +/* IEEE Std 802.11-2016 9.4.2.113 PREQ element */
> +u8 mesh_path_parse_request_frame(const u8 *pos, u8 elen)
> +{
> +	u8 target_count;
> +	u8 expected_len;
> +
> +	target_count = PREQ_IE_TARGET_COUNT(pos);
> +	if (unlikely(target_count < 1 || target_count > 20))
> +		return IEEE80211_PARSE_ERR_UNEXPECTED_ELEM;

not sure the likely/unlikely really is worth anything there - we don't
process *that* many frames.

> +
> +	expected_len = 1 /* Flags */ + 1 /* Hop Count */ + 1 /* Element TTL */ +
> +		       4 /* Path Discovery ID */ +
> +		       6 /* Originator Mesh STA Address */ +
> +		       4 /* Originator HWMP Sequence Number */ +
> +		       (AE_F_SET(pos) ? 6 : 0) /* Originator External Address */ +
> +		       4 /* Lifetime */ + 4 /* Metric */ + 1 + /* Target Count */ +
> +		       target_count * (1 /* Per Target Flags */ +
> +		       6 /* Target Address */ + 4 /* Target HWMP Sequence Number */);
> +	if (unlikely(elen != expected_len))
> +		return IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;

I think there's a case to be made for doing this like many others, in an
inline in ieee80211-mesh.h, and calling it ..._size_ok() with a bool
return.

> +++ b/net/mac80211/parse.c
> @@ -547,8 +547,11 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
>  				elems->awake_window = (void *)pos;
>  			break;
>  		case WLAN_EID_PREQ:
> -			elems->preq = pos;
> -			elems->preq_len = elen;
> +			elem_parse_failed = mesh_path_parse_request_frame(pos, elen);
> +			if (likely(!elem_parse_failed)) {

that would also fix the build issue here if mesh isn't compiled in.

(and also here, not sure about likely/unlikely, doesn't really seem
worth it, and under attack maybe the failure becomes likely?)

johannes

^ permalink raw reply

* Re: [PATCH net-next v2 0/2] Rework pci_device_id initialisation
From: Uwe Kleine-König (The Capable Hub) @ 2026-05-09  6:42 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Michael Grzeschik, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Marc Kleine-Budde, Vincent Mailhol, Krzysztof Halasa,
	Johannes Berg, Steffen Klassert, David Dillow, Ion Badulescu,
	Mark Einon, Rasesh Mody, GR-Linux-NIC-Dev, Manish Chopra,
	Potnuri Bharat Teja, Denis Kirjanov, Jijie Shao, Jian Shen,
	Cai Huoqing, Fan Gong, Tony Nguyen, Przemek Kitszel, Tariq Toukan,
	Saeed Mahameed, Leon Romanovsky, Mark Bloch, Ido Schimmel,
	Petr Machata, Yibo Dong, Heiner Kallweit, nic_swsd, Jiri Pirko,
	Francois Romieu, Daniele Venzano, Samuel Chessman, Jiawen Wu,
	Mengyuan Lou, Kevin Curtis, Arend van Spriel, Stanislav Yakovlev,
	Richard Cochran, Kees Cook, Aleksandr Loktionov, Thomas Gleixner,
	Jacob Keller, Thomas Fourier, Ingo Molnar, Kory Maincent,
	Zilin Guan, Vadim Fedorenko, Marco Crivellari, Bjorn Helgaas,
	David Arinzon, Yeounsu Moon, Denis Benato, Yonglong Liu,
	Andy Shevchenko, Randy Dunlap, Yicong Hui, MD Danish Anwar,
	Nathan Chancellor, Ethan Nelson-Moore, Larysa Zaremba, Ian Lin,
	Colin Ian King, Double Lo, Markus Schneider-Pargmann,
	Simon Horman, netdev, linux-kernel, linux-can, linux-parisc,
	intel-wired-lan, linux-rdma, oss-drivers, linux-wireless,
	brcm80211, brcm80211-dev-list.pdl
In-Reply-To: <20260508153452.6a1a9044@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 606 bytes --]

On Fri, May 08, 2026 at 03:34:52PM -0700, Jakub Kicinski wrote:
> On Thu,  7 May 2026 12:50:18 +0200 Uwe Kleine-König (The Capable Hub)
> wrote:
> >   net: Consistently define pci_device_ids using named initializers
> >   net: nfp: Drop PCI class entries with .class_mask = 0
> 
> There's a transient build failure between these two patches,
> you should probably reorder them?

I did build test with the first patch only, using gcc on x86 and arm64.
I guess this is about the ambiguity I mentioned in the cover letter and
maybe using clang? I'll try to reproduce and fix.

Best regards
Uwe

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* [PATCH] wifi: mac80211: capture fast-RX rate before mesh reuses skb->cb
From: Zhao Li @ 2026-05-09  4:34 UTC (permalink / raw)
  To: linux-wireless
  Cc: Johannes Berg, Felix Fietkau, Ryder Lee, Jeff Johnson,
	linux-kernel, stable

ieee80211_invoke_fast_rx() reads RX status through
IEEE80211_SKB_RXCB(skb), which aliases the same skb->cb storage
that ieee80211_rx_mesh_data() reuses as IEEE80211_TX_INFO.  In the
unicast forward path, mesh_data does:

	info = IEEE80211_SKB_CB(fwd_skb);
	memset(info, 0, sizeof(*info));

on the same skb the caller still names via rx->skb, then either
queues the skb for TX (success) or kfree_skb()'s it (no-route)
before returning RX_QUEUED.  The caller's RX_QUEUED arm then
calls sta_stats_encode_rate(status) on memory that is either
zeroed (success path) or freed (no-route path).  The latter is
KASAN slab-use-after-free in ieee80211_prepare_and_rx_handle.

Fix by encoding the rate from status before invoking
ieee80211_rx_mesh_data(), so the RX_QUEUED arm consumes a value
captured while status was still backed by valid memory.

Fixes: 3468e1e0c639 ("wifi: mac80211: add mesh fast-rx support")
Cc: stable@vger.kernel.org
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
---
 net/mac80211/rx.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4984,6 +4984,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
 		u8 sa[ETH_ALEN];
 	} addrs __aligned(2);
 	struct ieee80211_sta_rx_stats *stats;
+	u32 encoded_rate;

 	/* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
 	 * to a common data structure; drivers can implement that per queue
@@ -5090,11 +5091,14 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
 	/* push the addresses in front */
 	memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs));

+	/* capture before mesh forward may memset or free skb->cb */
+	encoded_rate = sta_stats_encode_rate(status);
+
 	res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb);
 	switch (res) {
 	case RX_QUEUED:
 		stats->last_rx = jiffies;
-		stats->last_rate = sta_stats_encode_rate(status);
+		stats->last_rate = encoded_rate;
 		return true;
 	case RX_CONTINUE:
 		break;
--
2.50.1


^ permalink raw reply

* [PATCH ath-next 5/5] wifi: ath12k: tighten RX monitor TLV bounds check
From: Miaoqing Pan @ 2026-05-09  2:58 UTC (permalink / raw)
  To: jjohnson; +Cc: ath12k, linux-wireless, linux-kernel, Miaoqing Pan
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>

Validate the pointer to the next RX monitor TLV more strictly by
ensuring that at least a full TLV header is available within the
status buffer before continuing TLV parsing.

Prevent potential out-of-bounds access when handling malformed
or truncated RX monitor status data.

Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
index 4266bd1d0d3d..23ba0cc824a7 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
@@ -3006,9 +3006,9 @@ ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev,
 
 		tlv = PTR_ALIGN(tlv + tlv_len + tlv_hdr_len, tlv_hdr_len);
 
-		if ((tlv - skb->data) > skb->len)
+		if (unlikely(tlv - skb->data > skb->len ||
+			     skb->len - (tlv - skb->data) < tlv_hdr_len))
 			break;
-
 	} while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) ||
 		 (hal_status == HAL_RX_MON_STATUS_BUF_ADDR) ||
 		 (hal_status == HAL_RX_MON_STATUS_MPDU_START) ||
-- 
2.34.1


^ permalink raw reply related

* [PATCH ath-next 4/5] wifi: ath12k: add dp_mon support 32-bit TLV headers
From: Miaoqing Pan @ 2026-05-09  2:58 UTC (permalink / raw)
  To: jjohnson; +Cc: ath12k, linux-wireless, linux-kernel, Miaoqing Pan
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>

Wi-Fi 7 monitor status parsing in dp_mon currently assumes a 64-bit TLV
header and directly decodes tag/len/userid from struct hal_tlv_64_hdr.
On chips using a 32-bit TLV header (e.g. QCC2072), this causes monitor RX
status packets to be dropped during TLV parsing.

Introduce HAL helpers to decode TLV header fields (tag/len/userid/value)
for both 32-bit and 64-bit header layouts. Without changing the actual TLV
parsing logic.

Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---
 .../net/wireless/ath/ath12k/wifi7/dp_mon.c    | 57 ++++++++++---------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
index 77f5d23be78d..4266bd1d0d3d 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_mon.c
@@ -1565,16 +1565,17 @@ ath12k_wifi7_dp_mon_parse_status_msdu_end(struct ath12k_mon_data *pmon,
 static enum hal_rx_mon_status
 ath12k_wifi7_dp_mon_rx_parse_status_tlv(struct ath12k_pdev_dp *dp_pdev,
 					struct ath12k_mon_data *pmon,
-					const struct hal_tlv_64_hdr *tlv)
+					const void *tlv)
 {
 	struct hal_rx_mon_ppdu_info *ppdu_info = &pmon->mon_ppdu_info;
-	const void *tlv_data = tlv->value;
-	u32 info[7], userid;
-	u16 tlv_tag, tlv_len;
+	struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
+	struct ath12k_hal *hal = &ar->ab->hal;
+	u16 tlv_tag, tlv_len, userid;
+	void *tlv_data;
+	u32 info[7];
 
-	tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
-	tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
-	userid = le64_get_bits(tlv->tl, HAL_TLV_64_USR_ID);
+	tlv_data = hal->ops->mon_rx_status_dec_tlv_hdr((void *)tlv, &tlv_tag,
+						       &tlv_len, &userid);
 
 	if (ppdu_info->tlv_aggr.in_progress && ppdu_info->tlv_aggr.tlv_tag != tlv_tag) {
 		ath12k_wifi7_dp_mon_parse_eht_sig_hdr(ppdu_info,
@@ -2931,11 +2932,12 @@ static enum dp_mon_status_buf_state
 ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
 				struct dp_rxdma_mon_ring *rx_ring)
 {
+	struct ath12k_hal *hal = &ab->hal;
 	struct ath12k_skb_rxcb *rxcb;
-	struct hal_tlv_64_hdr *tlv;
 	struct sk_buff *skb;
 	void *status_desc;
 	dma_addr_t paddr;
+	u16 tlv_tag;
 	u32 cookie;
 	int buf_id;
 	u8 rbm;
@@ -2960,8 +2962,8 @@ ath12k_wifi7_dp_rx_mon_buf_done(struct ath12k_base *ab, struct hal_srng *srng,
 				skb->len + skb_tailroom(skb),
 				DMA_FROM_DEVICE);
 
-	tlv = (struct hal_tlv_64_hdr *)skb->data;
-	if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) != HAL_RX_STATUS_BUFFER_DONE)
+	hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag, NULL, NULL);
+	if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE)
 		return DP_MON_STATUS_NO_DMA;
 
 	return DP_MON_STATUS_REPLINISH;
@@ -2973,39 +2975,38 @@ ath12k_wifi7_dp_mon_parse_rx_dest(struct ath12k_pdev_dp *dp_pdev,
 				  struct sk_buff *skb)
 {
 	struct ath12k *ar = ath12k_pdev_dp_to_ar(dp_pdev);
-	struct hal_tlv_64_hdr *tlv;
+	struct ath12k_hal *hal = &ar->ab->hal;
+	u8 *tlv_value, *tlv = skb->data;
 	struct ath12k_skb_rxcb *rxcb;
 	enum hal_rx_mon_status hal_status;
 	u16 tlv_tag, tlv_len;
-	u8 *ptr = skb->data;
+	u32 tlv_hdr_len;
+
+	tlv_hdr_len = hal->ops->get_tlv_hdr_align();
 
 	do {
-		tlv = (struct hal_tlv_64_hdr *)ptr;
-		tlv_tag = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_TAG);
+		tlv_value = hal->ops->mon_rx_status_dec_tlv_hdr(tlv, &tlv_tag,
+								&tlv_len, NULL);
 
 		/* The actual length of PPDU_END is the combined length of many PHY
 		 * TLVs that follow. Skip the TLV header and
 		 * rx_rxpcu_classification_overview that follows the header to get to
 		 * next TLV.
 		 */
-
 		if (tlv_tag == HAL_RX_PPDU_END)
 			tlv_len = sizeof(struct hal_rx_rxpcu_classification_overview);
-		else
-			tlv_len = le64_get_bits(tlv->tl, HAL_TLV_64_HDR_LEN);
 
 		hal_status = ath12k_wifi7_dp_mon_rx_parse_status_tlv(dp_pdev, pmon,
 								     tlv);
 
 		if (ar->monitor_started && ar->ab->hw_params->rxdma1_enable &&
 		    ath12k_wifi7_dp_mon_parse_rx_dest_tlv(dp_pdev, pmon, hal_status,
-							  tlv->value))
+							  tlv_value))
 			return HAL_RX_MON_STATUS_PPDU_DONE;
 
-		ptr += sizeof(*tlv) + tlv_len;
-		ptr = PTR_ALIGN(ptr, HAL_TLV_64_ALIGN);
+		tlv = PTR_ALIGN(tlv + tlv_len + tlv_hdr_len, tlv_hdr_len);
 
-		if ((ptr - skb->data) > skb->len)
+		if ((tlv - skb->data) > skb->len)
 			break;
 
 	} while ((hal_status == HAL_RX_MON_STATUS_PPDU_NOT_DONE) ||
@@ -3057,15 +3058,16 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
 	int buf_id, srng_id, num_buffs_reaped = 0;
 	enum dp_mon_status_buf_state reap_status;
 	struct dp_rxdma_mon_ring *rx_ring;
+	struct ath12k_hal *hal = &ab->hal;
 	struct ath12k_mon_data *pmon;
 	struct ath12k_skb_rxcb *rxcb;
-	struct hal_tlv_64_hdr *tlv;
 	void *rx_mon_status_desc;
 	struct hal_srng *srng;
 	struct ath12k_dp *dp;
 	struct sk_buff *skb;
 	struct ath12k *ar;
 	dma_addr_t paddr;
+	u16 tlv_tag;
 	u32 cookie;
 	u8 rbm;
 
@@ -3110,14 +3112,13 @@ ath12k_wifi7_dp_rx_reap_mon_status_ring(struct ath12k_base *ab, int mac_id,
 						skb->len + skb_tailroom(skb),
 						DMA_FROM_DEVICE);
 
-			tlv = (struct hal_tlv_64_hdr *)skb->data;
-			if (le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG) !=
-					HAL_RX_STATUS_BUFFER_DONE) {
+			hal->ops->mon_rx_status_dec_tlv_hdr(skb->data, &tlv_tag,
+							    NULL, NULL);
+			if (tlv_tag != HAL_RX_STATUS_BUFFER_DONE) {
 				pmon->buf_state = DP_MON_STATUS_NO_DMA;
 				ath12k_warn(ab,
-					    "mon status DONE not set %llx, buf_id %d\n",
-					    le64_get_bits(tlv->tl, HAL_TLV_HDR_TAG),
-					    buf_id);
+					    "mon status DONE not set %x, buf_id %d\n",
+					    tlv_tag, buf_id);
 				/* RxDMA status done bit might not be set even
 				 * though tp is moved by HW.
 				 */
-- 
2.34.1


^ permalink raw reply related

* [PATCH ath-next 3/5] wifi: ath12k: add HAL ops for monitor TLV header decode and alignment
From: Miaoqing Pan @ 2026-05-09  2:58 UTC (permalink / raw)
  To: jjohnson; +Cc: ath12k, linux-wireless, linux-kernel, Miaoqing Pan
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>

Wi-Fi 7 monitor RX status TLV parsing needs to decode TLV headers and
advance the pointer with the correct header alignment. Different targets
use different TLV header layouts (32-bit vs 64-bit), but the HAL ops for
dp_mon RX status header decode and header alignment were not populated
for all wifi7 targets.

Add dp_mon RX status TLV header decode callbacks and TLV header alignment
helpers to the wifi7 HAL ops for QCC2072, QCN9274 and WCN7850. Export
helpers to query the required TLV header alignment for 32-bit and 64-bit
TLV headers so the caller can align the TLV walk correctly across targets.

Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/hal.c               | 12 ++++++++++++
 drivers/net/wireless/ath/ath12k/hal.h               |  4 ++++
 drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c |  2 ++
 drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c |  2 ++
 drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c |  2 ++
 5 files changed, 22 insertions(+)

diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index d940f83cd92f..c0c3d2f047ef 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -875,3 +875,15 @@ void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid)
 	return tlv32->value;
 }
 EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr);
+
+u32 ath12k_hal_get_tlv64_hdr_align(void)
+{
+	return HAL_TLV_64_ALIGN;
+}
+EXPORT_SYMBOL(ath12k_hal_get_tlv64_hdr_align);
+
+u32 ath12k_hal_get_tlv32_hdr_align(void)
+{
+	return HAL_TLV_ALIGN;
+}
+EXPORT_SYMBOL(ath12k_hal_get_tlv32_hdr_align);
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index 3158c1881c76..312993d3d5d4 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1439,6 +1439,8 @@ struct hal_ops {
 					 u8 *rbm, u32 *msdu_cnt);
 	void *(*reo_cmd_enc_tlv_hdr)(void *tlv, u64 tag, u64 len);
 	u16 (*reo_status_dec_tlv_hdr)(void *tlv, void **desc);
+	void *(*mon_rx_status_dec_tlv_hdr)(void *tlv, u16 *tag, u16 *len, u16 *usrid);
+	u32 (*get_tlv_hdr_align)(void);
 };
 
 #define HAL_TLV_HDR_TAG		GENMASK(9, 1)
@@ -1553,4 +1555,6 @@ void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len);
 void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len);
 void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid);
 void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid);
+u32 ath12k_hal_get_tlv64_hdr_align(void);
+u32 ath12k_hal_get_tlv32_hdr_align(void);
 #endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
index c0583c3a2191..80ffadc47d48 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
@@ -490,6 +490,8 @@ const struct hal_ops hal_qcc2072_ops = {
 	.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
 	.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv32_hdr,
 	.reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcc2072,
+	.mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv32_hdr,
+	.get_tlv_hdr_align = ath12k_hal_get_tlv32_hdr_align,
 };
 
 u32 ath12k_hal_rx_desc_get_mpdu_start_offset_qcc2072(void)
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
index 8d8d1a9c05d3..129f6b1919e3 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
@@ -1132,4 +1132,6 @@ const struct hal_ops hal_qcn9274_ops = {
 	.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
 	.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
 	.reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcn9274,
+	.mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
+	.get_tlv_hdr_align = ath12k_hal_get_tlv64_hdr_align,
 };
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
index 4bef64ac9150..881986075548 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
@@ -815,4 +815,6 @@ const struct hal_ops hal_wcn7850_ops = {
 	.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
 	.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
 	.reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_wcn7850,
+	.mon_rx_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
+	.get_tlv_hdr_align = ath12k_hal_get_tlv64_hdr_align,
 };
-- 
2.34.1


^ permalink raw reply related

* [PATCH ath-next 2/5] wifi: ath12k: refactor HAL TLV32/64 decode helpers
From: Miaoqing Pan @ 2026-05-09  2:58 UTC (permalink / raw)
  To: jjohnson; +Cc: ath12k, linux-wireless, linux-kernel, Miaoqing Pan
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>

Change TLV decode helpers to return the TLV value pointer and optionally
decode tag/len/usrid via out parameters. This allows reusing the helpers
for DP monitor RX status header TLV parsing and avoids duplicated header
decoding in callers.

No functional change intended.

Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/hal.c         | 26 ++++++++++++-------
 drivers/net/wireless/ath/ath12k/hal.h         |  4 +--
 .../wireless/ath/ath12k/wifi7/hal_qcc2072.c   |  2 +-
 .../wireless/ath/ath12k/wifi7/hal_qcn9274.c   | 11 +++++++-
 .../wireless/ath/ath12k/wifi7/hal_wcn7850.c   | 11 +++++++-
 5 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index f03817b2fbc5..d940f83cd92f 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -846,26 +846,32 @@ void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len)
 }
 EXPORT_SYMBOL(ath12k_hal_encode_tlv32_hdr);
 
-u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc)
+void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid)
 {
 	struct hal_tlv_64_hdr *tlv64 = tlv;
-	u16 tag;
 
-	tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG);
-	*desc = tlv64->value;
+	if (tag)
+		*tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG);
+	if (len)
+		*len = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_LEN);
+	if (usrid)
+		*usrid = le64_get_bits(tlv64->tl, HAL_TLV_64_USR_ID);
 
-	return tag;
+	return tlv64->value;
 }
 EXPORT_SYMBOL(ath12k_hal_decode_tlv64_hdr);
 
-u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc)
+void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid)
 {
 	struct hal_tlv_hdr *tlv32 = tlv;
-	u16 tag;
 
-	tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG);
-	*desc = tlv32->value;
+	if (tag)
+		*tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG);
+	if (len)
+		*len = le32_get_bits(tlv32->tl, HAL_TLV_HDR_LEN);
+	if (usrid)
+		*usrid = le32_get_bits(tlv32->tl, HAL_TLV_USR_ID);
 
-	return tag;
+	return tlv32->value;
 }
 EXPORT_SYMBOL(ath12k_hal_decode_tlv32_hdr);
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index b3a89ace5a97..3158c1881c76 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1551,6 +1551,6 @@ void ath12k_hal_rx_reo_ent_buf_paddr_get(struct ath12k_hal *hal, void *rx_desc,
 					 u8 *rbm, u32 *msdu_cnt);
 void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len);
 void *ath12k_hal_encode_tlv32_hdr(void *tlv, u64 tag, u64 len);
-u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc);
-u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc);
+void *ath12k_hal_decode_tlv64_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid);
+void *ath12k_hal_decode_tlv32_hdr(void *tlv, u16 *tag, u16 *len, u16 *usrid);
 #endif
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
index 1eefb931a853..c0583c3a2191 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcc2072.c
@@ -439,7 +439,7 @@ static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcc2072(void *tlv, void **desc)
 	struct hal_reo_get_queue_stats_status_qcc2072 *status_tlv;
 	u16 tag;
 
-	tag = ath12k_hal_decode_tlv32_hdr(tlv, (void **)&status_tlv);
+	status_tlv = ath12k_hal_decode_tlv32_hdr(tlv, &tag, NULL, NULL);
 	/*
 	 * actual desc of REO status entry starts after tlv32_padding,
 	 * see hal_reo_get_queue_stats_status_qcc2072
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
index ba9ce1e718e8..8d8d1a9c05d3 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_qcn9274.c
@@ -934,6 +934,15 @@ void ath12k_hal_extract_rx_desc_data_qcn9274(struct hal_rx_desc_data *rx_desc_da
 	rx_desc_data->err_bitmap = ath12k_hal_rx_h_mpdu_err_qcn9274(rx_desc);
 }
 
+static u16 ath12k_hal_reo_status_dec_tlv_hdr_qcn9274(void *tlv, void **desc)
+{
+	u16 tag;
+
+	*desc = ath12k_hal_decode_tlv64_hdr(tlv, &tag, NULL, NULL);
+
+	return tag;
+}
+
 const struct ath12k_hw_hal_params ath12k_hw_hal_params_qcn9274 = {
 	.rx_buf_rbm = HAL_RX_BUF_RBM_SW3_BM,
 	.wbm2sw_cc_enable = HAL_WBM_SW_COOKIE_CONV_CFG_WBM2SW0_EN |
@@ -1122,5 +1131,5 @@ const struct hal_ops hal_qcn9274_ops = {
 	.rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
 	.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
 	.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
-	.reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
+	.reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_qcn9274,
 };
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
index e64e512cac7d..4bef64ac9150 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_wcn7850.c
@@ -740,6 +740,15 @@ int ath12k_hal_srng_create_config_wcn7850(struct ath12k_hal *hal)
 	return 0;
 }
 
+static u16 ath12k_hal_reo_status_dec_tlv_hdr_wcn7850(void *tlv, void **desc)
+{
+	u16 tag;
+
+	*desc = ath12k_hal_decode_tlv64_hdr(tlv, &tag, NULL, NULL);
+
+	return tag;
+}
+
 const struct ath12k_hal_tcl_to_wbm_rbm_map
 ath12k_hal_tcl_to_wbm_rbm_map_wcn7850[DP_TCL_NUM_RING_MAX] = {
 	{
@@ -805,5 +814,5 @@ const struct hal_ops hal_wcn7850_ops = {
 	.rx_msdu_list_get = ath12k_wifi7_hal_rx_msdu_list_get,
 	.rx_reo_ent_buf_paddr_get = ath12k_wifi7_hal_rx_reo_ent_buf_paddr_get,
 	.reo_cmd_enc_tlv_hdr = ath12k_hal_encode_tlv64_hdr,
-	.reo_status_dec_tlv_hdr = ath12k_hal_decode_tlv64_hdr,
+	.reo_status_dec_tlv_hdr = ath12k_hal_reo_status_dec_tlv_hdr_wcn7850,
 };
-- 
2.34.1


^ permalink raw reply related

* [PATCH ath-next 1/5] wifi: ath12k: fix TLV32 length mask
From: Miaoqing Pan @ 2026-05-09  2:58 UTC (permalink / raw)
  To: jjohnson; +Cc: ath12k, linux-wireless, linux-kernel, Miaoqing Pan
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>

HAL_TLV_HDR_LEN was using the wrong bitmask; fix it to cover
bits [21:10]. Also drop HAL_SRNG_TLV_HDR_{TAG,LEN} and use the
generic TLV header bit definitions for TLV32/TLV64 encode/decode
to avoid redundant macros.

Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/hal.c | 8 ++++----
 drivers/net/wireless/ath/ath12k/hal.h | 5 +----
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/ath/ath12k/hal.c b/drivers/net/wireless/ath/ath12k/hal.c
index a164563fff28..f03817b2fbc5 100644
--- a/drivers/net/wireless/ath/ath12k/hal.c
+++ b/drivers/net/wireless/ath/ath12k/hal.c
@@ -828,8 +828,8 @@ void *ath12k_hal_encode_tlv64_hdr(void *tlv, u64 tag, u64 len)
 {
 	struct hal_tlv_64_hdr *tlv64 = tlv;
 
-	tlv64->tl = le64_encode_bits(tag, HAL_TLV_HDR_TAG) |
-		    le64_encode_bits(len, HAL_TLV_HDR_LEN);
+	tlv64->tl = le64_encode_bits(tag, HAL_TLV_64_HDR_TAG) |
+		    le64_encode_bits(len, HAL_TLV_64_HDR_LEN);
 
 	return tlv64->value;
 }
@@ -851,7 +851,7 @@ u16 ath12k_hal_decode_tlv64_hdr(void *tlv, void **desc)
 	struct hal_tlv_64_hdr *tlv64 = tlv;
 	u16 tag;
 
-	tag = le64_get_bits(tlv64->tl, HAL_SRNG_TLV_HDR_TAG);
+	tag = le64_get_bits(tlv64->tl, HAL_TLV_64_HDR_TAG);
 	*desc = tlv64->value;
 
 	return tag;
@@ -863,7 +863,7 @@ u16 ath12k_hal_decode_tlv32_hdr(void *tlv, void **desc)
 	struct hal_tlv_hdr *tlv32 = tlv;
 	u16 tag;
 
-	tag = le32_get_bits(tlv32->tl, HAL_SRNG_TLV_HDR_TAG);
+	tag = le32_get_bits(tlv32->tl, HAL_TLV_HDR_TAG);
 	*desc = tlv32->value;
 
 	return tag;
diff --git a/drivers/net/wireless/ath/ath12k/hal.h b/drivers/net/wireless/ath/ath12k/hal.h
index bf4f7dbae866..b3a89ace5a97 100644
--- a/drivers/net/wireless/ath/ath12k/hal.h
+++ b/drivers/net/wireless/ath/ath12k/hal.h
@@ -1442,7 +1442,7 @@ struct hal_ops {
 };
 
 #define HAL_TLV_HDR_TAG		GENMASK(9, 1)
-#define HAL_TLV_HDR_LEN		GENMASK(25, 10)
+#define HAL_TLV_HDR_LEN		GENMASK(21, 10)
 #define HAL_TLV_USR_ID		GENMASK(31, 26)
 
 #define HAL_TLV_ALIGN	4
@@ -1462,9 +1462,6 @@ struct hal_tlv_64_hdr {
 	u8 value[];
 } __packed;
 
-#define HAL_SRNG_TLV_HDR_TAG		GENMASK(9, 1)
-#define HAL_SRNG_TLV_HDR_LEN		GENMASK(25, 10)
-
 dma_addr_t ath12k_hal_srng_get_tp_addr(struct ath12k_base *ab,
 				       struct hal_srng *srng);
 dma_addr_t ath12k_hal_srng_get_hp_addr(struct ath12k_base *ab,
-- 
2.34.1


^ permalink raw reply related

* [PATCH ath-next 0/5] wifi: ath12k: fix dp_mon RX parsing for 32-bit TLV
From: Miaoqing Pan @ 2026-05-09  2:58 UTC (permalink / raw)
  To: jjohnson; +Cc: ath12k, linux-wireless, linux-kernel, Miaoqing Pan

This series fixes RX monitor status parsing issues on platforms using
32-bit TLV headers (e.g. QCC2072), and tightens TLV decoding robustness
in ath12k datapath monitor handling.

Signed-off-by: Miaoqing Pan <miaoqing.pan@oss.qualcomm.com>
---

Miaoqing Pan (5):
  wifi: ath12k: fix TLV32 length mask
  wifi: ath12k: refactor HAL TLV32/64 decode helpers
  wifi: ath12k: add HAL ops for monitor TLV header decode and alignment
  wifi: ath12k: add dp_mon support 32-bit TLV headers
  wifi: ath12k: tighten RX monitor TLV bounds check

 drivers/net/wireless/ath/ath12k/hal.c         | 42 +++++++++----
 drivers/net/wireless/ath/ath12k/hal.h         | 13 ++--
 .../net/wireless/ath/ath12k/wifi7/dp_mon.c    | 59 ++++++++++---------
 .../wireless/ath/ath12k/wifi7/hal_qcc2072.c   |  4 +-
 .../wireless/ath/ath12k/wifi7/hal_qcn9274.c   | 13 +++-
 .../wireless/ath/ath12k/wifi7/hal_wcn7850.c   | 13 +++-
 6 files changed, 94 insertions(+), 50 deletions(-)


base-commit: 14d99bd40a8e3a80398dc597375fc7516ca488dd
-- 
2.34.1


^ permalink raw reply

* [wireless:for-next] BUILD SUCCESS 7666dbb1bacc4ba522b96740cba7283d243d16e1
From: kernel test robot @ 2026-05-09  2:51 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless.git for-next
branch HEAD: 7666dbb1bacc4ba522b96740cba7283d243d16e1  wifi: cfg80211: advance loop vars in cfg80211_merge_profile()

elapsed time: 753m

configs tested: 219
configs skipped: 4

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260509    gcc-9.5.0
arc                   randconfig-002-20260509    gcc-9.5.0
arm                               allnoconfig    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260509    gcc-9.5.0
arm                   randconfig-002-20260509    gcc-9.5.0
arm                   randconfig-003-20260509    gcc-9.5.0
arm                   randconfig-004-20260509    gcc-9.5.0
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260509    gcc-10.5.0
arm64                 randconfig-002-20260509    gcc-10.5.0
arm64                 randconfig-003-20260509    gcc-10.5.0
arm64                 randconfig-004-20260509    gcc-10.5.0
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260509    gcc-10.5.0
csky                  randconfig-002-20260509    gcc-10.5.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    clang-23
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260509    clang-17
hexagon               randconfig-002-20260509    clang-17
i386                             allmodconfig    clang-20
i386                             allmodconfig    gcc-14
i386                              allnoconfig    gcc-14
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386                             allyesconfig    gcc-14
i386        buildonly-randconfig-001-20260509    gcc-14
i386        buildonly-randconfig-002-20260509    gcc-14
i386        buildonly-randconfig-003-20260509    gcc-14
i386        buildonly-randconfig-004-20260509    gcc-14
i386        buildonly-randconfig-005-20260509    gcc-14
i386        buildonly-randconfig-006-20260509    gcc-14
i386                                defconfig    gcc-15.2.0
i386                  randconfig-001-20260509    clang-20
i386                  randconfig-002-20260509    clang-20
i386                  randconfig-003-20260509    clang-20
i386                  randconfig-004-20260509    clang-20
i386                  randconfig-005-20260509    clang-20
i386                  randconfig-006-20260509    clang-20
i386                  randconfig-007-20260509    clang-20
i386                  randconfig-011-20260509    gcc-14
i386                  randconfig-012-20260509    gcc-14
i386                  randconfig-013-20260509    gcc-14
i386                  randconfig-014-20260509    gcc-14
i386                  randconfig-015-20260509    gcc-14
i386                  randconfig-016-20260509    gcc-14
i386                  randconfig-017-20260509    gcc-14
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260509    clang-17
loongarch             randconfig-002-20260509    clang-17
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            allmodconfig    clang-23
nios2                            allmodconfig    gcc-11.5.0
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260509    clang-17
nios2                 randconfig-002-20260509    clang-17
openrisc                         allmodconfig    clang-23
openrisc                         allmodconfig    gcc-15.2.0
openrisc                          allnoconfig    clang-23
openrisc                            defconfig    gcc-15.2.0
openrisc                 simple_smp_defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                           allyesconfig    clang-19
parisc                           allyesconfig    gcc-15.2.0
parisc                              defconfig    gcc-15.2.0
parisc                randconfig-001-20260508    gcc-9.5.0
parisc                randconfig-001-20260509    gcc-11.5.0
parisc                randconfig-002-20260508    gcc-9.5.0
parisc                randconfig-002-20260509    gcc-11.5.0
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc               randconfig-001-20260508    gcc-9.5.0
powerpc               randconfig-001-20260509    gcc-11.5.0
powerpc               randconfig-002-20260508    gcc-9.5.0
powerpc               randconfig-002-20260509    gcc-11.5.0
powerpc64             randconfig-001-20260508    gcc-9.5.0
powerpc64             randconfig-001-20260509    gcc-11.5.0
powerpc64             randconfig-002-20260508    gcc-9.5.0
powerpc64             randconfig-002-20260509    gcc-11.5.0
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260508    clang-23
riscv                 randconfig-001-20260509    clang-23
riscv                 randconfig-002-20260508    clang-23
riscv                 randconfig-002-20260509    clang-23
s390                             allmodconfig    clang-18
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260508    clang-23
s390                  randconfig-001-20260509    clang-23
s390                  randconfig-002-20260508    clang-23
s390                  randconfig-002-20260509    clang-23
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-19
sh                               allyesconfig    gcc-15.2.0
sh                                  defconfig    gcc-14
sh                     magicpanelr2_defconfig    gcc-15.2.0
sh                    randconfig-001-20260508    clang-23
sh                    randconfig-001-20260509    clang-23
sh                    randconfig-002-20260508    clang-23
sh                    randconfig-002-20260509    clang-23
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260509    clang-23
sparc                 randconfig-002-20260509    clang-23
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260509    clang-23
sparc64               randconfig-002-20260509    clang-23
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-14
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260509    clang-23
um                    randconfig-002-20260509    clang-23
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260508    gcc-14
x86_64      buildonly-randconfig-001-20260509    clang-20
x86_64      buildonly-randconfig-002-20260508    gcc-14
x86_64      buildonly-randconfig-002-20260509    clang-20
x86_64      buildonly-randconfig-003-20260508    gcc-14
x86_64      buildonly-randconfig-003-20260509    clang-20
x86_64      buildonly-randconfig-004-20260508    gcc-14
x86_64      buildonly-randconfig-004-20260509    clang-20
x86_64      buildonly-randconfig-005-20260508    gcc-14
x86_64      buildonly-randconfig-005-20260509    clang-20
x86_64      buildonly-randconfig-006-20260508    gcc-14
x86_64      buildonly-randconfig-006-20260509    clang-20
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                         randconfig-001    clang-20
x86_64                randconfig-001-20260508    clang-20
x86_64                randconfig-001-20260509    gcc-14
x86_64                         randconfig-002    clang-20
x86_64                randconfig-002-20260508    clang-20
x86_64                randconfig-002-20260509    gcc-14
x86_64                         randconfig-003    clang-20
x86_64                randconfig-003-20260508    clang-20
x86_64                randconfig-003-20260509    gcc-14
x86_64                         randconfig-004    clang-20
x86_64                randconfig-004-20260508    clang-20
x86_64                randconfig-004-20260509    gcc-14
x86_64                         randconfig-005    clang-20
x86_64                randconfig-005-20260508    clang-20
x86_64                randconfig-005-20260509    gcc-14
x86_64                         randconfig-006    clang-20
x86_64                randconfig-006-20260508    clang-20
x86_64                randconfig-006-20260509    gcc-14
x86_64                randconfig-011-20260508    gcc-14
x86_64                randconfig-011-20260509    gcc-14
x86_64                randconfig-012-20260508    gcc-14
x86_64                randconfig-012-20260509    gcc-14
x86_64                randconfig-013-20260508    gcc-14
x86_64                randconfig-013-20260509    gcc-14
x86_64                randconfig-014-20260508    gcc-14
x86_64                randconfig-014-20260509    gcc-14
x86_64                randconfig-015-20260508    gcc-14
x86_64                randconfig-015-20260509    gcc-14
x86_64                randconfig-016-20260508    gcc-14
x86_64                randconfig-016-20260509    gcc-14
x86_64                randconfig-071-20260509    clang-20
x86_64                randconfig-072-20260509    clang-20
x86_64                randconfig-073-20260509    clang-20
x86_64                randconfig-074-20260509    clang-20
x86_64                randconfig-075-20260509    clang-20
x86_64                randconfig-076-20260509    clang-20
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                           allyesconfig    clang-23
xtensa                           allyesconfig    gcc-15.2.0
xtensa                randconfig-001-20260509    clang-23
xtensa                randconfig-002-20260509    clang-23

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* [PATCH] wifi: mac80211_hwsim: reject NAN on multi-radio wiphys
From: Deepanshu Kartikey @ 2026-05-09  0:46 UTC (permalink / raw)
  To: johannes
  Cc: daniel.gabay, miriam.rachel.korenblit, linux-wireless,
	linux-kernel, Deepanshu Kartikey, syzbot+2002864e6c6895cb0ac3

When userspace creates a new hwsim radio with both
HWSIM_ATTR_MULTI_RADIO and HWSIM_ATTR_SUPPORT_NAN_DEVICE,
hwsim_new_radio_nl() sets BIT(NL80211_IFTYPE_NAN_DATA) in
wiphy->interface_modes while configuring the wiphy with
n_radio > 1. This violates the invariant checked in
wiphy_register():

    (interface_modes & BIT(NL80211_IFTYPE_NAN_DATA)) &&
    (!nan_capa.phy.ht.ht_supported || n_radio > 1)

triggering a WARN reachable from userspace via genetlink.
With panic_on_warn this becomes a denial of service.

Refuse the combination at parse time with -EINVAL and an
extack message, matching the cfg80211 constraint that NAN
is not supported on multi-radio wiphys.

Reported-by: syzbot+2002864e6c6895cb0ac3@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=2002864e6c6895cb0ac3
Fixes: 2c7c70ee7cee ("wifi: mac80211_hwsim: enable NAN_DATA interface simulation support")
Tested-by: syzbot+2002864e6c6895cb0ac3@syzkaller.appspotmail.com
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 drivers/net/wireless/virtual/mac80211_hwsim_main.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/virtual/mac80211_hwsim_main.c b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
index dc9775cd9f54..a625a9e3caa7 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim_main.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim_main.c
@@ -6766,9 +6766,15 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
 		param.p2p_device = true;
 	}
 
-	if (param.nan_device)
+	if (param.nan_device) {
+		if (param.multi_radio) {
+			NL_SET_ERR_MSG(info->extack,
+				       "NAN is not supported on multi-radio wiphys");
+			return -EINVAL;
+		}
 		param.iftypes |= BIT(NL80211_IFTYPE_NAN) |
 				 BIT(NL80211_IFTYPE_NAN_DATA);
+	}
 
 	if (info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]) {
 		u32 len = nla_len(info->attrs[HWSIM_ATTR_CIPHER_SUPPORT]);
-- 
2.43.0


^ permalink raw reply related

* [PATCH 3/3] Fix PERR frame processing
From: Masashi Honma @ 2026-05-08 22:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Masashi Honma
In-Reply-To: <20260508225905.29998-1-masashi.honma@gmail.com>

There are no issues with the PERR processing itself; however, to maintain
consistency with the previous PREQ/PREP code modifications, I will create a new
mesh_path_parse_error_frame() function to separately implement the frame format
validation and the "not supported" check.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
 net/mac80211/mesh.h      |  1 +
 net/mac80211/mesh_hwmp.c | 48 ++++++++++++++++++++++++++++++++++++++--
 net/mac80211/parse.c     |  7 ++++--
 3 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index aba7ef59195a..610c34e35e64 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -319,6 +319,7 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
 u8 mesh_path_parse_request_frame(const u8 *pos, u8 elen);
 u8 mesh_path_parse_reply_frame(const u8 *pos, u8 elen);
+u8 mesh_path_parse_error_frame(const u8 *pos, u8 elen);
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 			    struct ieee80211_mgmt *mgmt, size_t len);
 struct mesh_path *
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 9f903a2408f7..2a293b771f79 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -62,6 +62,7 @@ static inline u16 u16_field_get(const u8 *preq_elem, int offset, bool ae)
 #define PREP_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
 
 #define PERR_IE_TTL(x)		(*(x))
+#define PERR_IE_NUMBER_OF_DST(x)	(*(x + 1))
 #define PERR_IE_TARGET_FLAGS(x)	(*(x + 2))
 #define PERR_IE_TARGET_ADDR(x)	(x + 3)
 #define PERR_IE_TARGET_SN(x)	u32_field_get(x, 9, 0)
@@ -968,6 +969,42 @@ u8 mesh_path_parse_reply_frame(const u8 *pos, u8 elen)
 	return 0;
 }
 
+/* IEEE Std 802.11-2016 9.4.2.115 PERR element */
+u8 mesh_path_parse_error_frame(const u8 *pos, u8 elen)
+{
+	u8 number_of_dst;
+	u8 expected_len;
+	const u8 *start;
+	int i;
+
+	number_of_dst = PERR_IE_NUMBER_OF_DST(pos);
+	if (unlikely(number_of_dst < 1 || number_of_dst > 19))
+		return IEEE80211_PARSE_ERR_UNEXPECTED_ELEM;
+
+	start = pos;
+	expected_len = 1 /* Element TTL */ + 1 /* Number of Destinations */;
+	pos += 2;
+
+	for (i = 0; i < number_of_dst; i++) {
+		u8 dst_len;
+
+		if (unlikely(pos - start >= elen))
+			return IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+
+		dst_len = 1 /* Flags */ + 6 /* Destination Address */ +
+			  4 /* HWMP Sequence Number */ +
+			  (AE_F_SET(pos) ? 6 : 0) /* Destination External Address */ +
+			  2 /* Reason Code */;
+		expected_len += dst_len;
+		pos += dst_len;
+	}
+
+	if (unlikely(elen != expected_len))
+		return IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+
+	return 0;
+}
+
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 			    struct ieee80211_mgmt *mgmt, size_t len)
 {
@@ -976,6 +1013,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 	u32 path_metric;
 	struct sta_info *sta;
 	u8 target_count;
+	u8 number_of_dst;
 
 	/* need action_code */
 	if (len < IEEE80211_MIN_ACTION_SIZE(mesh_action))
@@ -1026,9 +1064,15 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 						path_metric);
 	}
 	if (elems->perr) {
-		if (elems->perr_len != 15)
-			/* Right now we support only one destination per PERR */
+		/* Right now we support only one destination per PERR */
+		number_of_dst = PERR_IE_NUMBER_OF_DST(elems->perr);
+		if (number_of_dst != 1)
 			goto free;
+
+		/* Right now we do not support AE (Address Extension) */
+		if (PERR_IE_TARGET_FLAGS(elems->perr) & AE_F)
+			goto free;
+
 		hwmp_perr_frame_process(sdata, mgmt, elems->perr);
 	}
 	if (elems->rann)
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index cdc549055242..dfc326db0471 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -561,8 +561,11 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 			}
 			break;
 		case WLAN_EID_PERR:
-			elems->perr = pos;
-			elems->perr_len = elen;
+			elem_parse_failed = mesh_path_parse_error_frame(pos, elen);
+			if (likely(!elem_parse_failed)) {
+				elems->perr = pos;
+				elems->perr_len = elen;
+			}
 			break;
 		case WLAN_EID_RANN:
 			if (elen >= sizeof(struct ieee80211_rann_ie))
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/3] Fix overread in PREP frame processing
From: Masashi Honma @ 2026-05-08 22:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Masashi Honma
In-Reply-To: <20260508225905.29998-1-masashi.honma@gmail.com>

When the AF flag is enabled, hwmp_prep_frame_process() overreads orig_addr
by 2 bytes. Since this occurs within the socket buffer, it does not read across
memory boundaries and therefore poses no security risk; however, we will fix it
as a precaution.

In this fix, a new function mesh_path_parse_reply_frame() is established to
separate the implementation of frame format validation and the check for
unsupported features. This is intended to facilitate future work when
implementing the currently unsupported parts.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
 net/mac80211/mesh.h      |  1 +
 net/mac80211/mesh_hwmp.c | 24 ++++++++++++++++++++++--
 net/mac80211/parse.c     |  7 +++++--
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 331d2d774196..aba7ef59195a 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -318,6 +318,7 @@ mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
 void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
 u8 mesh_path_parse_request_frame(const u8 *pos, u8 elen);
+u8 mesh_path_parse_reply_frame(const u8 *pos, u8 elen);
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 			    struct ieee80211_mgmt *mgmt, size_t len);
 struct mesh_path *
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 4239412d12c7..9f903a2408f7 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -949,6 +949,25 @@ u8 mesh_path_parse_request_frame(const u8 *pos, u8 elen)
 	return 0;
 }
 
+/* IEEE Std 802.11-2016 9.4.2.114 PREP element */
+u8 mesh_path_parse_reply_frame(const u8 *pos, u8 elen)
+{
+	u8 expected_len;
+
+	expected_len = 1 /* Flags */ + 1 /* Hop Count */ + 1 /* Element TTL */ +
+		       6 /* Target Mesh STA Address */ +
+		       4 /* Target HWMP Sequence Number */ +
+		       (AE_F_SET(pos) ? 6 : 0) /* Target External Address */ +
+		       4 /* Lifetime */ + 4 /* Metric */ +
+		       6 /* Originator Mesh STA Address */ +
+		       4 /* Originator HWMP Sequence Number */;
+
+	if (unlikely(elen != expected_len))
+		return IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+
+	return 0;
+}
+
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 			    struct ieee80211_mgmt *mgmt, size_t len)
 {
@@ -996,9 +1015,10 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 						path_metric);
 	}
 	if (elems->prep) {
-		if (elems->prep_len != 31)
-			/* Right now we support no AE */
+		/* Right now we do not support AE (Address Extension) */
+		if (AE_F_SET(elems->prep))
 			goto free;
+
 		path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep,
 						  MPATH_PREP);
 		if (path_metric)
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index 7a2abe676361..cdc549055242 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -554,8 +554,11 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 			}
 			break;
 		case WLAN_EID_PREP:
-			elems->prep = pos;
-			elems->prep_len = elen;
+			elem_parse_failed = mesh_path_parse_reply_frame(pos, elen);
+			if (likely(!elem_parse_failed)) {
+				elems->prep = pos;
+				elems->prep_len = elen;
+			}
 			break;
 		case WLAN_EID_PERR:
 			elems->perr = pos;
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/3] Fix overread in PREQ frame processing
From: Masashi Honma @ 2026-05-08 22:59 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Masashi Honma
In-Reply-To: <8f0a2488540f4a65ea4d837a06225a27a10cc305.camel@sipsolutions.net>

When the AF flag is enabled, hwmp_preq_frame_process() overreads target_addr
by 2 bytes. Since this occurs within the socket buffer, it does not read across
memory boundaries and therefore poses no security risk; however, we will fix it
as a precaution.

In this fix, a new function mesh_path_parse_request_frame() is established to
separate the implementation of frame format validation and the check for
unsupported features. This is intended to facilitate future work when
implementing the currently unsupported parts.

Assisted-by: Claude:Sonnet 4.6
Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
---
 net/mac80211/mesh.h      |  1 +
 net/mac80211/mesh_hwmp.c | 35 +++++++++++++++++++++++++++++++++--
 net/mac80211/parse.c     |  7 +++++--
 3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 3f9664e4e00c..331d2d774196 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -317,6 +317,7 @@ struct mesh_path *
 mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
 void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
+u8 mesh_path_parse_request_frame(const u8 *pos, u8 elen);
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 			    struct ieee80211_mgmt *mgmt, size_t len);
 struct mesh_path *
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 9d89ebcce1c1..4239412d12c7 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -45,6 +45,7 @@ static inline u16 u16_field_get(const u8 *preq_elem, int offset, bool ae)
 #define PREQ_IE_ORIG_SN(x)	u32_field_get(x, 13, 0)
 #define PREQ_IE_LIFETIME(x)	u32_field_get(x, 17, AE_F_SET(x))
 #define PREQ_IE_METRIC(x) 	u32_field_get(x, 21, AE_F_SET(x))
+#define PREQ_IE_TARGET_COUNT(x)	(*(AE_F_SET(x) ? x + 31 : x + 25))
 #define PREQ_IE_TARGET_F(x)	(*(AE_F_SET(x) ? x + 32 : x + 26))
 #define PREQ_IE_TARGET_ADDR(x) 	(AE_F_SET(x) ? x + 33 : x + 27)
 #define PREQ_IE_TARGET_SN(x) 	u32_field_get(x, 33, AE_F_SET(x))
@@ -924,6 +925,29 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata,
 	rcu_read_unlock();
 }
 
+/* IEEE Std 802.11-2016 9.4.2.113 PREQ element */
+u8 mesh_path_parse_request_frame(const u8 *pos, u8 elen)
+{
+	u8 target_count;
+	u8 expected_len;
+
+	target_count = PREQ_IE_TARGET_COUNT(pos);
+	if (unlikely(target_count < 1 || target_count > 20))
+		return IEEE80211_PARSE_ERR_UNEXPECTED_ELEM;
+
+	expected_len = 1 /* Flags */ + 1 /* Hop Count */ + 1 /* Element TTL */ +
+		       4 /* Path Discovery ID */ +
+		       6 /* Originator Mesh STA Address */ +
+		       4 /* Originator HWMP Sequence Number */ +
+		       (AE_F_SET(pos) ? 6 : 0) /* Originator External Address */ +
+		       4 /* Lifetime */ + 4 /* Metric */ + 1 + /* Target Count */ +
+		       target_count * (1 /* Per Target Flags */ +
+		       6 /* Target Address */ + 4 /* Target HWMP Sequence Number */);
+	if (unlikely(elen != expected_len))
+		return IEEE80211_PARSE_ERR_BAD_ELEM_SIZE;
+
+	return 0;
+}
 
 void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 			    struct ieee80211_mgmt *mgmt, size_t len)
@@ -932,6 +956,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 	size_t baselen;
 	u32 path_metric;
 	struct sta_info *sta;
+	u8 target_count;
 
 	/* need action_code */
 	if (len < IEEE80211_MIN_ACTION_SIZE(mesh_action))
@@ -955,9 +980,15 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 		return;
 
 	if (elems->preq) {
-		if (elems->preq_len != 37)
-			/* Right now we support just 1 destination and no AE */
+		/* Right now we do not support AE (Address Extension) */
+		if (AE_F_SET(elems->preq))
 			goto free;
+
+		/* Right now we only supports 1 target */
+		target_count = PREQ_IE_TARGET_COUNT(elems->preq);
+		if (target_count != 1)
+			goto free;
+
 		path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq,
 						  MPATH_PREQ);
 		if (path_metric)
diff --git a/net/mac80211/parse.c b/net/mac80211/parse.c
index 5e61457be0f3..7a2abe676361 100644
--- a/net/mac80211/parse.c
+++ b/net/mac80211/parse.c
@@ -547,8 +547,11 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
 				elems->awake_window = (void *)pos;
 			break;
 		case WLAN_EID_PREQ:
-			elems->preq = pos;
-			elems->preq_len = elen;
+			elem_parse_failed = mesh_path_parse_request_frame(pos, elen);
+			if (likely(!elem_parse_failed)) {
+				elems->preq = pos;
+				elems->preq_len = elen;
+			}
 			break;
 		case WLAN_EID_PREP:
 			elems->prep = pos;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH net-next v2 0/2] Rework pci_device_id initialisation
From: Jakub Kicinski @ 2026-05-08 22:34 UTC (permalink / raw)
  To: Uwe Kleine-König (The Capable Hub)
  Cc: Michael Grzeschik, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Marc Kleine-Budde, Vincent Mailhol, Krzysztof Halasa,
	Johannes Berg, Steffen Klassert, David Dillow, Ion Badulescu,
	Mark Einon, Rasesh Mody, GR-Linux-NIC-Dev, Manish Chopra,
	Potnuri Bharat Teja, Denis Kirjanov, Jijie Shao, Jian Shen,
	Cai Huoqing, Fan Gong, Tony Nguyen, Przemek Kitszel, Tariq Toukan,
	Saeed Mahameed, Leon Romanovsky, Mark Bloch, Ido Schimmel,
	Petr Machata, Yibo Dong, Heiner Kallweit, nic_swsd, Jiri Pirko,
	Francois Romieu, Daniele Venzano, Samuel Chessman, Jiawen Wu,
	Mengyuan Lou, Kevin Curtis, Arend van Spriel, Stanislav Yakovlev,
	Richard Cochran, Kees Cook, Aleksandr Loktionov, Thomas Gleixner,
	Jacob Keller, Thomas Fourier, Ingo Molnar, Kory Maincent,
	Zilin Guan, Vadim Fedorenko, Marco Crivellari, Bjorn Helgaas,
	David Arinzon, Yeounsu Moon, Denis Benato, Yonglong Liu,
	Andy Shevchenko, Randy Dunlap, Yicong Hui, MD Danish Anwar,
	Nathan Chancellor, Ethan Nelson-Moore, Larysa Zaremba, Ian Lin,
	Colin Ian King, Double Lo, Markus Schneider-Pargmann,
	Simon Horman, netdev, linux-kernel, linux-can, linux-parisc,
	intel-wired-lan, linux-rdma, oss-drivers, linux-wireless,
	brcm80211, brcm80211-dev-list.pdl
In-Reply-To: <cover.1778149923.git.u.kleine-koenig@baylibre.com>

On Thu,  7 May 2026 12:50:18 +0200 Uwe Kleine-König (The Capable Hub)
wrote:
>   net: Consistently define pci_device_ids using named initializers
>   net: nfp: Drop PCI class entries with .class_mask = 0

There's a transient build failure between these two patches,
you should probably reorder them?
-- 
pw-bot: cr

^ permalink raw reply

* pull-request: iwlwifi-fixes-2026-05-08
From: Korenblit, Miriam Rachel @ 2026-05-08 15:10 UTC (permalink / raw)
  To: linux-wireless

Hi,

The pull request I sent yesterday was based on wireless-next and not on wireless, resending.

Miri
---

The following changes since commit fcee7d82f27d6a8b1ddc5bbefda59b4e441e9bc0:

  Merge tag 'net-7.1-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net (2026-05-07 10:32:03 -0700)

are available in the Git repository at:

  https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git/ tags/iwlwifi-fixes-2026-05-08

for you to fetch changes up to 069e85e7f89df35c0fb2eea0e98d5c9a2afa0e03:

  wifi: iwlwifi: mld: stop TX during firmware restart (2026-05-08 13:14:51 +0300)

----------------------------------------------------------------
iwlwifi-fixes-2026-05-08

- wifi: iwlwifi: mld: stop TX during firmware restart
- wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is disabled

----------------------------------------------------------------
Cole Leavitt (1):
      wifi: iwlwifi: mld: fix TSO segmentation explosion when AMSDU is disabled

Sheroz Juraev (1):
      wifi: iwlwifi: mld: stop TX during firmware restart

 drivers/net/wireless/intel/iwlwifi/mld/tx.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

^ permalink raw reply

* Re: [PATCH 1/3] [v5 net-next] dt-bindings: net: add st,stlc4560/p54spi binding
From: Conor Dooley @ 2026-05-08 15:05 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: netdev, Arnd Bergmann, Aaro Koskinen, Andreas Kemnade,
	Bartosz Golaszewski, Benoît Cousson, David S. Miller,
	Dmitry Torokhov, Eric Dumazet, Felipe Balbi, Jakub Kicinski,
	Johannes Berg, Kevin Hilman, Krzysztof Kozlowski, Linus Walleij,
	Paolo Abeni, Rob Herring, Roger Quadros, Tony Lindgren,
	linux-wireless, devicetree, linux-kernel, linux-arm-kernel,
	linux-gpio, linux-omap, Christian Lamparter
In-Reply-To: <20260507212451.3333185-2-arnd@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 766 bytes --]

On Thu, May 07, 2026 at 11:24:49PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
> 
> The SPI version of Prism54 was sold under a couple of different
> names and supported by the Linux p54spi driver, but there was
> never a DT binding for it.
> 
> Document the four known names of this device and the properties
> that are sufficient for its use on the Nokia N8x0 tablet.
> 
> As I don't have this hardware or documentation for it, this is
> purely based on existing usage in the driver.
> 
> Link: https://lore.kernel.org/all/e8dc9acb-6f85-e0a9-a145-d101ca6da201@gmail.com/
> Acked-by: Christian Lamparter <chunkeey@gmail.com>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>

Acked-by: Conor Dooley <conor.dooley@microchip.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH] wifi: wlcore: Add support for IGTK key
From: Peter Åstrand @ 2026-05-08 13:55 UTC (permalink / raw)
  To: Andreas Kemnade; +Cc: linux-wireless
In-Reply-To: <20260508102403.4e2fb1bc@kemnade.info>

[-- Attachment #1: Type: text/plain, Size: 1814 bytes --]

On Fri, 8 May 2026, Andreas Kemnade wrote:

> Hi,
> 
> On Fri, 16 Jan 2026 18:58:58 +0100 (CET)
> Peter Åstrand <astrand@lysator.liu.se> wrote:
> 
> > This change re-applies commit 2b7aadd3b9e1 ("wlcore: Adding suppoprt for IGTK key in
> > wlcore driver") (sic), but only enables WLAN_CIPHER_SUITE_AES_CMAC with modern
> > firmware. This patch is required to support WPA3 connections.
> > 
> 
> I have seen this after this patch:
> [  484.113311] wlcore: WARNING could not set keys
> [  484.117828] wlcore: ERROR Could not add or replace key
> [  484.123016] wlan0: failed to set key (5, ff:ff:ff:ff:ff:ff) to hardware (-5)
> [  484.123046] wlcore: Hardware recovery in progress. FW ver: Rev 7.3.10.0.142
> [  484.139923] wlcore: pc: 0x0, hint_sts: 0x00000048 count: 1
> [  484.145721] wlcore: down
> [  484.148986] ieee80211 phy0: Hardware restart was requested
> [  484.610473] wlcore: firmware booted (Rev 7.3.10.0.142)
> [  484.633758] wlcore: Association completed.
> [  484.690490] wlcore: ERROR command execute failure 14
> [  484.690490] ------------[ cut here ]------------
> [  484.700195] WARNING: drivers/net/wireless/ti/wlcore/main.c:872 at wl12xx_queue_recovery_work+0x64/0x74 [wlcore], CPU#0: kworker/0:0/892
> 
> This repeats endlessly.
> As soon as I set pmf to 1 in wpa_supplciant, once per second. Reverting this patch helps. Seen this
> on the Epson Moverio BT-200.

Thanks for this feedback. From the firmware version, I assume that this is 
not wl18xx but probably wl12xx? Unfortunately I have no experience with 
that module. So, while my patch is an improvement over the original patch 
because it checks firmware version, it did not consider non-wl18xx 
modules. 

I guess we need to throw in something like:

strcmp(pdev_data->family->name, "wl18xx")

...in the if statement. 

Br,
Peter

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox