* Re: [PATCH v9] PCI: Add device-specific reset for Qualcomm devices
From: Manivannan Sadhasivam @ 2026-06-17 14:47 UTC (permalink / raw)
To: Jose Ignacio Tornos Martinez
Cc: bhelgaas, alex, jjohnson, linux-pci, linux-wireless, ath11k,
ath12k, mhi, linux-kernel
In-Reply-To: <20260612142638.1243895-1-jtornosm@redhat.com>
On Fri, Jun 12, 2026 at 04:26:38PM +0200, Jose Ignacio Tornos Martinez wrote:
> Some Qualcomm PCIe devices (WCN6855/WCN7850 WiFi cards, SDX62/SDX65 modems)
> lack working reset methods for VFIO passthrough scenarios. These devices
> have no FLR capability, advertise NoSoftRst+ (blocking PM reset), and have
> broken bus reset.
>
> The problem manifests in VFIO passthrough scenarios:
>
> - WCN6855 WiFi card (17cb:1103): Normal VM operation works fine, including
> clean shutdown/reboot. However, when the VM terminates uncleanly
> (crash, force-off), VFIO attempts to reset the device before it can
> be assigned to another VM. Without a working reset method, the device
> remains in an undefined state, preventing reuse.
>
> - WCN7850 WiFi card (17cb:1107): Same behavior as WCN6855.
>
> - SDX62/SDX65 5G modems (17cb:0308): Never successfully initialize even
> on first VM assignment without proper reset capability.
>
> Add device-specific reset entries for these Qualcomm devices using D3hot
> power cycling. Testing shows that despite advertising NoSoftRst+, D3hot
> transition provides sufficient reset for VFIO reuse, particularly after
> unexpected VM termination. While not a complete reset (BARs preserved),
> it provides the only viable reset mechanism for these devices.
>
I checked internally within Qcom and I was told that these PCIe devices retain
the context during D3Hot to D0 transition and that's why they advertise
No_Soft_Reset.
The partial reset behavior you are seeing might be due to firmware handling the
transition as an error state. All these devices use MHI bus and when the MHI
state doesn't match the PCIe device state, then the firmware will treat it as an
error and will try to torn down resources. This could be the reason why you are
seeing partial reset.
Nevertheless, these devices do not support any form of Soft Reset and only way
to reset them would be by doing D3Cold. But that depends on platform support
though. So it would be inaccurate/wrong to assume that these devices support
Soft Reset during D3Hot to D0 transition.
- Mani
--
மணிவண்ணன் சதாசிவம்
^ permalink raw reply
* Re: [PATCH v1 1/2] overflow: Allow to sum a few arguments at once
From: Johannes Berg @ 2026-06-17 12:56 UTC (permalink / raw)
To: Andy Shevchenko, linux-hardening, linux-kernel, linux-wireless
Cc: Kees Cook, Gustavo A. R. Silva
In-Reply-To: <20260617112250.2791461-2-andriy.shevchenko@linux.intel.com>
On Wed, 2026-06-17 at 13:12 +0200, Andy Shevchenko wrote:
> Convert size_add() to take variadic argument, so we can simplify users
> with using a macro only once.
> +#define __size_add3(addend1, addend2, addend3, addend4, ...) \
> + __size_add(__size_add2(addend1, addend2, addend3), addend4)
> +#define __size_add4(addend1, addend2, addend3, addend4, addend5, ...) \
> + __size_add(__size_add3(addend1, addend2, addend3, addend4), addend5)
I guess it's not going to really matter, but it would generate fewer
calls to have something more like
#define __size_add3(a1, a2, a3, a4) \
size_add(size_add(a1, a2), size_add(a3, a4))
#define __size_add4(a1, a2, a3, a4, a5) \
size_add(size_add(a1, a2), size_add(a3, a4, a5))
as a binary tree, rather than only cutting one off every time. Not sure
that results in hugely different code though - maybe fewer overflow
checks?
Although your version make it really completely equivalent to the
nl80211.c code, clearly it doesn't matter if all the values are "good",
and I believe the overflow behaviour means it doesn't matter for the
overflow case either?
johannes
^ permalink raw reply
* [rfc, PATCH v1 0/2] overflow: Convert size_add() to take variadic arguments
From: Andy Shevchenko @ 2026-06-17 11:12 UTC (permalink / raw)
To: Johannes Berg, linux-hardening, linux-kernel, linux-wireless
Cc: Kees Cook, Gustavo A. R. Silva, Johannes Berg, Andy Shevchenko
This is an RFC!
We have already users that want add sizes of up to 5 arguments and
I know about at least one that also wants 3 or 4.
This is brave move to make size_add() to take variadic arguments.
The second patch is an example of use.
The implementation includes a case with a single argument on a purpose.
In the future it might be extended to take an array as an argument,
something like
int sizes[21];
size_add(sizes);
where the first element is amount of entries in the array (the same format
as used in get_options() call) or other possible variants. This can be
distinguished by _Generic().
But it may be dropped and we require always two arguments at minimum.
The RFC just to collect opinions and perception. Note, array3*(), min3()/max3()
and all like that also can use similar approach.
Andy Shevchenko (2):
overflow: Allow to sum a few arguments at once
wifi: nl80211: Call size_add() only once
include/linux/overflow.h | 37 ++++++++++++++++++++++++++-----------
net/wireless/nl80211.c | 11 ++++-------
2 files changed, 30 insertions(+), 18 deletions(-)
--
2.50.1
^ permalink raw reply
* [PATCH v1 1/2] overflow: Allow to sum a few arguments at once
From: Andy Shevchenko @ 2026-06-17 11:12 UTC (permalink / raw)
To: Johannes Berg, linux-hardening, linux-kernel, linux-wireless
Cc: Kees Cook, Gustavo A. R. Silva, Johannes Berg, Andy Shevchenko
In-Reply-To: <20260617112250.2791461-1-andriy.shevchenko@linux.intel.com>
Convert size_add() to take variadic argument, so we can simplify users
with using a macro only once.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
include/linux/overflow.h | 37 ++++++++++++++++++++++++++-----------
1 file changed, 26 insertions(+), 11 deletions(-)
diff --git a/include/linux/overflow.h b/include/linux/overflow.h
index a8cb6319b4fb..a8b0325e73f3 100644
--- a/include/linux/overflow.h
+++ b/include/linux/overflow.h
@@ -2,9 +2,10 @@
#ifndef __LINUX_OVERFLOW_H
#define __LINUX_OVERFLOW_H
+#include <linux/args.h>
#include <linux/compiler.h>
-#include <linux/limits.h>
#include <linux/const.h>
+#include <linux/limits.h>
/*
* We need to compute the minimum and maximum values representable in a given
@@ -337,16 +338,7 @@ static __always_inline size_t __must_check size_mul(size_t factor1, size_t facto
return bytes;
}
-/**
- * size_add() - Calculate size_t addition with saturation at SIZE_MAX
- * @addend1: first addend
- * @addend2: second addend
- *
- * Returns: calculate @addend1 + @addend2, both promoted to size_t,
- * with any overflow causing the return value to be SIZE_MAX. The
- * lvalue must be size_t to avoid implicit type conversion.
- */
-static __always_inline size_t __must_check size_add(size_t addend1, size_t addend2)
+static __always_inline size_t __must_check __size_add(size_t addend1, size_t addend2)
{
size_t bytes;
@@ -356,6 +348,29 @@ static __always_inline size_t __must_check size_add(size_t addend1, size_t adden
return bytes;
}
+#define __size_add0(addend1, ...) \
+ __size_add(addend1, 0)
+#define __size_add1(addend1, addend2, ...) \
+ __size_add(addend1, addend2)
+#define __size_add2(addend1, addend2, addend3, ...) \
+ __size_add(__size_add(addend1, addend2), addend3)
+#define __size_add3(addend1, addend2, addend3, addend4, ...) \
+ __size_add(__size_add2(addend1, addend2, addend3), addend4)
+#define __size_add4(addend1, addend2, addend3, addend4, addend5, ...) \
+ __size_add(__size_add3(addend1, addend2, addend3, addend4), addend5)
+
+/**
+ * size_add() - Calculate size_t addition with saturation at SIZE_MAX
+ * @addend1: first addend
+ * @...: more to add (optional)
+ *
+ * Returns: calculate @addend1 + @addend2, both promoted to size_t,
+ * with any overflow causing the return value to be SIZE_MAX. The
+ * lvalue must be size_t to avoid implicit type conversion.
+ */
+#define size_add(addend1, ...) \
+ CONCATENATE(__size_add, COUNT_ARGS(__VA_ARGS__))(addend1, __VA_ARGS__)
+
/**
* size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX
* @minuend: value to subtract from
--
2.50.1
^ permalink raw reply related
* [PATCH v1 2/2] wifi: nl80211: Call size_add() only once
From: Andy Shevchenko @ 2026-06-17 11:12 UTC (permalink / raw)
To: Johannes Berg, linux-hardening, linux-kernel, linux-wireless
Cc: Kees Cook, Gustavo A. R. Silva, Johannes Berg, Andy Shevchenko
In-Reply-To: <20260617112250.2791461-1-andriy.shevchenko@linux.intel.com>
Since size_add() may take a few arguments at once, call it only once.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
---
net/wireless/nl80211.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 53b4b3f76697..98f92c268944 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -11560,13 +11560,10 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
attrs[NL80211_ATTR_SCHED_SCAN_RSSI_ADJUST]))
return ERR_PTR(-EINVAL);
- size = struct_size(request, channels, n_channels);
- size = size_add(size, array_size(sizeof(*request->ssids), n_ssids));
- size = size_add(size, array_size(sizeof(*request->match_sets),
- n_match_sets));
- size = size_add(size, array_size(sizeof(*request->scan_plans),
- n_plans));
- size = size_add(size, ie_len);
+ size = size_add(struct_size(request, channels, n_channels), ie_len,
+ array_size(sizeof(*request->ssids), n_ssids),
+ array_size(sizeof(*request->match_sets), n_match_sets),
+ array_size(sizeof(*request->scan_plans), n_plans));
request = kzalloc(size, GFP_KERNEL);
if (!request)
return ERR_PTR(-ENOMEM);
--
2.50.1
^ permalink raw reply related
* Re: [PATCH 7/7] arm64: dts: qcom: sm8350-hdk: describe WiFi/BT chip
From: Konrad Dybcio @ 2026-06-17 10:46 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Manivannan Sadhasivam, Lorenzo Pieralisi,
Krzysztof Wilczyński, Rob Herring, Bjorn Helgaas, Qiang Yu,
Jeff Johnson, Liam Girdwood, Mark Brown, Krzysztof Kozlowski,
Conor Dooley, Bartosz Golaszewski, Marcel Holtmann,
Luiz Augusto von Dentz, Balakrishna Godavarthi, Rocky Liao,
Bjorn Andersson, Konrad Dybcio, linux-arm-msm, linux-pci,
linux-kernel, linux-wireless, ath11k, devicetree,
Bartosz Golaszewski, linux-bluetooth
In-Reply-To: <dz4qovpquxgynnzviqg6g23oa2o3trlkznremnmlqfnlj3b62x@oqgcuvalfcph>
On 6/11/26 9:44 PM, Dmitry Baryshkov wrote:
> On Thu, Jun 11, 2026 at 02:09:27PM +0200, Konrad Dybcio wrote:
>> On 6/1/26 11:46 AM, Dmitry Baryshkov wrote:
>>> The SM8350 HDK has onboard WiFi/BT chip, WCN6851. It is an earlier
>>> version of well-known WCN6855 WiFI/BT SoC. Describe the PMU, BT and WiFI
>>> parts of the device.
>>
>> [...]
>>
>>> + wcn6855-pmu {
>>> + compatible = "qcom,wcn6851-pmu", "qcom,wcn6855-pmu";
>>> +
>>> + pinctrl-0 = <&bt_en>, <&wlan_en>, <&swctrl>;
>>> + pinctrl-names = "default";
>>> +
>>> + wlan-enable-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
>>> + bt-enable-gpios = <&tlmm 65 GPIO_ACTIVE_HIGH>;
>>> + swctrl-gpios = <&tlmm 153 GPIO_ACTIVE_HIGH>;
>>> +
>>> + vddio-supply = <&vreg_s10b_1p8>;
>>> + vddaon-supply = <&vreg_s11b_0p95>;
>>> + vddpmu-supply = <&vreg_s11b_0p95>;
>>> + vddpmumx-supply = <&vreg_s2e_0p85>;
>>> + vddpmucx-supply = <&vreg_s11b_0p95>;
>>> + vddrfa0p95-supply = <&vreg_s11b_0p95>;
>>> + vddrfa1p3-supply = <&vreg_s12b_1p25>;
>>> + vddrfa1p9-supply = <&vreg_s1c_1p86>;
>>> + vddpcie1p3-supply = <&vreg_s12b_1p25>;
>>> + vddpcie1p9-supply = <&vreg_s1c_1p86>;
>>
>> [...]
>>
>>> @@ -373,6 +437,13 @@ vreg_l7e_2p8: ldo7 {
>>> regulator-name = "vreg_l7e_2p8";
>>> regulator-min-microvolt = <2800000>;
>>> regulator-max-microvolt = <2800000>;
>>> +
>>> + /*
>>> + * This is used by the RF front-end for which there is
>>> + * no way to represent it in DT (yet?).
>>> + */
>>> + regulator-boot-on;
>>> + regulator-always-on;
>>
>> msm-5.4 maps this to bt-vdd-asd-supply (asd being a keyboard smash,
>> perhaps?) - what is its actual use?
>
> WiFI/BT RF front-end, a separate chip containing amplifiers, couplers,
> etc.
>
> It is a separate chip (or a module), it is not powered on by the PMU,
> etc.
Ah, that thing.. yeah I don't really know. Although it'd be a shame to
keep it powered forever, so maybe one day someone will revisit this
Konrad
^ permalink raw reply
* [PATCH] wifi: ath12k: fix survey indexing across bands
From: Matthew Leach @ 2026-06-17 10:18 UTC (permalink / raw)
To: Jeff Johnson, Vasanthakumar Thiagarajan, Baochen Qiang,
Ramya Gnanasekar, Karthikeyan Periyasamy
Cc: Kalle Valo, Pradeep Kumar Chitrapu, P Praneesh, Sriram R,
linux-wireless, ath12k, linux-kernel, kernel, Matthew Leach
When running 'iw dev wlan0 survey dump' the values for the channel busy
time have the same sequence across bands. This is caused by indexing
into the ath12k survey array using a band-local index rather than the
global index passed by mac80211. This results in surveys for 5 GHz and 6
GHz channels returning values from 2.4 GHz slots, making the survey
unusable on those bands.
Fix by indexing into ar->survey[] using the original index passed by
mac80211.
Band busy-times Before this fix:
2.4 GHz: 9, 2, 2, 2, 4, 2, 10, 16, 4, 12, 5
5 GHz: 9, 2, 2, 2, 4, 2, 10, 16, 4, 12, 5
6 GHz: 9, 2, 2, 2, 4, 2, 10, 16, 4, 12, 5
After this fix, times are independent:
2.4 GHz: 23, 5, 5, 12, 2, 12, 26, 5, 3, 1, 27
5 GHz: 30, 40, 29, 27, 118, 118, 112, 120, 11, 11, 11
6 GHz: 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
Tested-on: wcn7850 hw2.0 PCI WLAN.IOE_HMT.1.1-00018-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Matthew Leach <matthew.leach@collabora.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 2cff9485c95a..9474d7e70823 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -13351,6 +13351,7 @@ int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
struct ath12k *ar;
struct ieee80211_supported_band *sband;
struct survey_info *ar_survey;
+ int survey_index = idx;
lockdep_assert_wiphy(hw->wiphy);
@@ -13385,7 +13386,7 @@ int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
return -ENOENT;
}
- ar_survey = &ar->survey[idx];
+ ar_survey = &ar->survey[survey_index];
ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260617-ath12-survey-band-fix-4b5e78579379
Best regards,
--
Matt
^ permalink raw reply related
* [PATCH] wifi: rtw89: regd: fix ww domain blocking on 6GHz
From: Matthew Leach @ 2026-06-17 10:13 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, kernel, Matthew Leach
The current code keeps a separate instance for the ww reg domain outside
the static map, and treats rtw89_regd_get_index() returning
RTW89_REGD_MAX_COUNTRY_NUM as the index for the ww domain. This
conflates the "not found" sentinel with a real index and causes the
block_* bitmap lookups to skip ww entirely, explicitly blocking 6GHz on
the ww domain rather than deferring to the kernel regulatory policy.
Fold the standalone rtw89_ww_regd into rtw89_regd_map[0] and drop the
special case in rtw89_regd_get_index() that returned
RTW89_REGD_MAX_COUNTRY_NUM for ww. rtw89_regd_find_reg_by_name() now
returns NULL on miss, and its callers either translate that into the
RTW89_REGD_MAX_COUNTRY_NUM sentinel (rtw89_regd_get_index_by_name()) or
fall back to the ww entry explicitly (rtw89_regd_notifier_apply()). With
ww living at a real index, the block-list checks apply and 6GHz is no
longer unconditionally blocked for ww.
Signed-off-by: Matthew Leach <matthew.leach@collabora.com>
---
drivers/net/wireless/realtek/rtw89/regd.c | 28 ++++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index 28466cb35ea2..698b8b7f6129 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -21,10 +21,8 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
static_assert(BITS_PER_TYPE(unsigned long) >= NUM_OF_RTW89_REGD_FUNC);
-static const struct rtw89_regd rtw89_ww_regd =
- COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW, 0x0);
-
static const struct rtw89_regd rtw89_regd_map[] = {
+ COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW, 0x0),
COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC, 0x0),
COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA, 0x0),
COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC, 0x0),
@@ -316,12 +314,13 @@ static const struct rtw89_regd *rtw89_regd_find_reg_by_name(struct rtw89_dev *rt
return ®d_ctrl->map[i];
}
- return &rtw89_ww_regd;
+ return NULL;
}
static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
{
- return regd == &rtw89_ww_regd;
+ /* Index 0 in the static map contains the WW domain entry. */
+ return regd == &rtw89_regd_map[0];
}
static u8 rtw89_regd_get_index(struct rtw89_dev *rtwdev, const struct rtw89_regd *regd)
@@ -331,9 +330,6 @@ static u8 rtw89_regd_get_index(struct rtw89_dev *rtwdev, const struct rtw89_regd
BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM);
- if (rtw89_regd_is_ww(regd))
- return RTW89_REGD_MAX_COUNTRY_NUM;
-
return regd - regd_ctrl->map;
}
@@ -342,6 +338,10 @@ static u8 rtw89_regd_get_index_by_name(struct rtw89_dev *rtwdev, const char *alp
const struct rtw89_regd *regd;
regd = rtw89_regd_find_reg_by_name(rtwdev, alpha2);
+
+ if (!regd)
+ return RTW89_REGD_MAX_COUNTRY_NUM;
+
return rtw89_regd_get_index(rtwdev, regd);
}
@@ -721,7 +721,7 @@ int rtw89_regd_init_hint(struct rtw89_dev *rtwdev)
return -EINVAL;
chip_regd = rtw89_regd_find_reg_by_name(rtwdev, rtwdev->efuse.country_code);
- if (!rtw89_regd_is_ww(chip_regd)) {
+ if (chip_regd && !rtw89_regd_is_ww(chip_regd)) {
rtwdev->regulatory.regd = chip_regd;
rtwdev->regulatory.programmed = true;
@@ -859,7 +859,15 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
struct wiphy *wiphy,
struct regulatory_request *request)
{
- rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
+ const struct rtw89_regd *regd = rtw89_regd_find_reg_by_name(rtwdev, request->alpha2);
+
+ if (!regd) {
+ /* Fallback to WW domain if name not found. */
+ regd = &rtw89_regd_map[0];
+ }
+
+ rtwdev->regulatory.regd = regd;
+
/* This notification might be set from the system of distros,
* and it does not expect the regulatory will be modified by
* connecting to an AP (i.e. country ie).
---
base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6
change-id: 20260616-rtw89-6ghz-regd-fixes-d8f816880bd0
Best regards,
--
Matt
^ permalink raw reply related
* [PATCH ath-next 2/2] wifi: ath12k: fix MLO peer delete race
From: Baochen Qiang @ 2026-06-17 9:28 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
In-Reply-To: <20260617-ath12k-mlo-peer-delete-race-v1-0-ab3c4f455dfb@oss.qualcomm.com>
ath12k_peer_mlo_link_peers_delete() sends WMI peer_delete for every
link before waiting for any peer_unmap / peer_delete_resp event. The
shared per-radio completion ar->peer_delete_done could not
disambiguate which peer a response was for: every call to
ath12k_peer_delete_send() did
reinit_completion(&ar->peer_delete_done), so when an event for the
first link arrived between two sends it raised the count to 1 and
the second send promptly cleared it; the wait for the second link
then timed out with
Timeout in receiving peer delete response
Replace the shared completion with a per-radio waiter list, with
each pending ath12k_peer_delete() caller queueing an
ath12k_peer_delete_wait carrying its (vdev_id, addr) and a private
struct completion. ath12k_peer_delete_resp_event() matches the
response against the list under ar->data_lock and signals the
matching waiter.
Also correct the endian conversion in ath12k_peer_delete_resp_event()
logging, and add the missing \n in some logging.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3
Fixes: 8e6f8bc28603 ("wifi: ath12k: Add MLO station state change handling")
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/core.c | 2 +-
drivers/net/wireless/ath/ath12k/core.h | 5 +-
drivers/net/wireless/ath/ath12k/mac.c | 2 +-
drivers/net/wireless/ath/ath12k/peer.c | 130 ++++++++++++++++++++++++++-------
drivers/net/wireless/ath/ath12k/peer.h | 19 ++++-
drivers/net/wireless/ath/ath12k/wmi.c | 16 ++--
6 files changed, 136 insertions(+), 38 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 742d4fd1b598..f71650039292 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1524,7 +1524,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
complete_all(&ar->scan.completed);
complete(&ar->scan.on_channel);
complete(&ar->peer_assoc_done);
- complete(&ar->peer_delete_done);
+ ath12k_peer_delete_wait_flush(ar);
complete(&ar->install_key_done);
complete(&ar->vdev_setup_done);
complete(&ar->vdev_delete_done);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index fc5127b5c1a3..1436ff4316e7 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -665,7 +665,8 @@ struct ath12k {
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
* vdev_stop_status info, scan data, ath12k_sta info, ath12k_link_vif info,
- * channel context data, survey info, test mode data, regd_channel_update_queue.
+ * channel context data, survey info, test mode data, regd_channel_update_queue,
+ * peer_delete_waits.
*/
spinlock_t data_lock;
@@ -687,7 +688,7 @@ struct ath12k {
u8 radio_idx;
struct completion peer_assoc_done;
- struct completion peer_delete_done;
+ struct list_head peer_delete_waits;
int install_key_status;
struct completion install_key_done;
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 2e5a075191ae..4c86a8eb5841 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -15040,11 +15040,11 @@ static void ath12k_mac_setup(struct ath12k *ar)
spin_lock_init(&ar->dp.ppdu_list_lock);
INIT_LIST_HEAD(&ar->arvifs);
INIT_LIST_HEAD(&ar->dp.ppdu_stats_info);
+ INIT_LIST_HEAD(&ar->peer_delete_waits);
init_completion(&ar->vdev_setup_done);
init_completion(&ar->vdev_delete_done);
init_completion(&ar->peer_assoc_done);
- init_completion(&ar->peer_delete_done);
init_completion(&ar->install_key_done);
init_completion(&ar->bss_survey_done);
init_completion(&ar->scan.started);
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index c222bdaa333c..98509c63c580 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -9,6 +9,55 @@
#include "debug.h"
#include "debugfs.h"
+void ath12k_peer_delete_wait_register(struct ath12k *ar,
+ struct ath12k_peer_delete_wait *wait,
+ u32 vdev_id, const u8 *addr)
+{
+ wait->vdev_id = vdev_id;
+ ether_addr_copy(wait->addr, addr);
+ init_completion(&wait->done);
+
+ spin_lock_bh(&ar->data_lock);
+ list_add(&wait->list, &ar->peer_delete_waits);
+ spin_unlock_bh(&ar->data_lock);
+}
+
+void ath12k_peer_delete_wait_unregister(struct ath12k *ar,
+ struct ath12k_peer_delete_wait *wait)
+{
+ spin_lock_bh(&ar->data_lock);
+ list_del(&wait->list);
+ spin_unlock_bh(&ar->data_lock);
+}
+
+void ath12k_peer_delete_resp_signal(struct ath12k *ar, u32 vdev_id, const u8 *addr)
+{
+ struct ath12k_peer_delete_wait *wait;
+
+ guard(spinlock_bh)(&ar->data_lock);
+
+ list_for_each_entry(wait, &ar->peer_delete_waits, list) {
+ if (wait->vdev_id == vdev_id &&
+ ether_addr_equal(wait->addr, addr)) {
+ complete(&wait->done);
+ return;
+ }
+ }
+
+ ath12k_warn(ar->ab, "failed to find link peer with vdev id %u addr %pM\n",
+ vdev_id, addr);
+}
+
+void ath12k_peer_delete_wait_flush(struct ath12k *ar)
+{
+ struct ath12k_peer_delete_wait *wait;
+
+ spin_lock_bh(&ar->data_lock);
+ list_for_each_entry(wait, &ar->peer_delete_waits, list)
+ complete(&wait->done);
+ spin_unlock_bh(&ar->data_lock);
+}
+
static int ath12k_wait_for_dp_link_peer_common(struct ath12k_base *ab, int vdev_id,
const u8 *addr, bool expect_mapped)
{
@@ -62,20 +111,19 @@ static int ath12k_wait_for_peer_deleted(struct ath12k *ar, int vdev_id, const u8
return ath12k_wait_for_dp_link_peer_common(ar->ab, vdev_id, addr, false);
}
-int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
- const u8 *addr)
+int ath12k_wait_for_peer_delete_done(struct ath12k *ar,
+ struct ath12k_peer_delete_wait *wait)
{
- int ret;
unsigned long time_left;
+ int ret;
- ret = ath12k_wait_for_peer_deleted(ar, vdev_id, addr);
+ ret = ath12k_wait_for_peer_deleted(ar, wait->vdev_id, wait->addr);
if (ret) {
- ath12k_warn(ar->ab, "failed wait for peer deleted");
+ ath12k_warn(ar->ab, "failed wait for peer deleted\n");
return ret;
}
- time_left = wait_for_completion_timeout(&ar->peer_delete_done,
- 3 * HZ);
+ time_left = wait_for_completion_timeout(&wait->done, 3 * HZ);
if (time_left == 0) {
ath12k_warn(ar->ab, "Timeout in receiving peer delete response\n");
return -ETIMEDOUT;
@@ -91,8 +139,6 @@ static int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, const u8 *add
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- reinit_completion(&ar->peer_delete_done);
-
ret = ath12k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
if (ret) {
ath12k_warn(ab,
@@ -106,6 +152,7 @@ static int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, const u8 *add
int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
{
+ struct ath12k_peer_delete_wait wait;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -114,17 +161,25 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
&(ath12k_ar_to_ah(ar)->dp_hw), vdev_id,
addr, ar->hw_link_id);
+ /*
+ * Register the stack waiter before sending so the resp_event for
+ * this peer cannot arrive while no waiter is queued.
+ */
+ ath12k_peer_delete_wait_register(ar, &wait, vdev_id, addr);
+
ret = ath12k_peer_delete_send(ar, vdev_id, addr);
if (ret)
- return ret;
+ goto out;
- ret = ath12k_wait_for_peer_delete_done(ar, vdev_id, addr);
+ ret = ath12k_wait_for_peer_delete_done(ar, &wait);
if (ret)
- return ret;
+ goto out;
ar->num_peers--;
- return 0;
+out:
+ ath12k_peer_delete_wait_unregister(ar, &wait);
+ return ret;
}
static int ath12k_wait_for_peer_created(struct ath12k *ar, int vdev_id, const u8 *addr)
@@ -184,22 +239,26 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, arg->vdev_id,
arg->peer_addr);
if (!peer) {
+ struct ath12k_peer_delete_wait wait;
+
spin_unlock_bh(&dp->dp_lock);
ath12k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n",
arg->peer_addr, arg->vdev_id);
- reinit_completion(&ar->peer_delete_done);
+ ath12k_peer_delete_wait_register(ar, &wait, arg->vdev_id,
+ arg->peer_addr);
ret = ath12k_wmi_send_peer_delete_cmd(ar, arg->peer_addr,
arg->vdev_id);
if (ret) {
ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
arg->vdev_id, arg->peer_addr);
+ ath12k_peer_delete_wait_unregister(ar, &wait);
return ret;
}
- ret = ath12k_wait_for_peer_delete_done(ar, arg->vdev_id,
- arg->peer_addr);
+ ret = ath12k_wait_for_peer_delete_done(ar, &wait);
+ ath12k_peer_delete_wait_unregister(ar, &wait);
if (ret)
return ret;
@@ -283,13 +342,14 @@ u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)
{
+ DECLARE_BITMAP(registered, IEEE80211_MLD_MAX_NUM_LINKS);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
struct ath12k_hw *ah = ahvif->ah;
struct ath12k_link_vif *arvif;
struct ath12k_link_sta *arsta;
+ int ret, err_ret = 0;
unsigned long links;
struct ath12k *ar;
- int ret, err_ret = 0;
u8 link_id;
lockdep_assert_wiphy(ah->hw->wiphy);
@@ -297,8 +357,19 @@ int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_st
if (!sta->mlo)
return -EINVAL;
- /* FW expects delete of all link peers at once before waiting for reception
- * of peer unmap or delete responses
+ struct ath12k_peer_delete_wait *waits __free(kfree) =
+ kzalloc_objs(*waits, IEEE80211_MLD_MAX_NUM_LINKS);
+ if (!waits)
+ return -ENOMEM;
+
+ bitmap_zero(registered, IEEE80211_MLD_MAX_NUM_LINKS);
+
+ /*
+ * Firmware expects delete of all link peers at once before waiting
+ * for reception of peer unmap or delete responses. Phase 1 registers
+ * a per-link stack waiter and sends WMI peer delete for every
+ * link; the resp_event handler matches each response to its
+ * (vdev_id, addr) waiter on ar->peer_delete_waits.
*/
links = ahsta->links_map;
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
@@ -318,29 +389,36 @@ int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_st
arvif->vdev_id, arsta->addr,
ar->hw_link_id);
+ ath12k_peer_delete_wait_register(ar, &waits[link_id],
+ arvif->vdev_id, arsta->addr);
+
ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr);
if (ret) {
ath12k_warn(ar->ab,
"failed to delete peer vdev_id %d addr %pM ret %d\n",
arvif->vdev_id, arsta->addr, ret);
err_ret = ret;
+ ath12k_peer_delete_wait_unregister(ar, &waits[link_id]);
continue;
}
+
+ set_bit(link_id, registered);
}
- /* Ensure all link peers are deleted and unmapped */
+ /*
+ * Phase 2: wait for unmap + delete_resp on each registered link
+ * and tear down the waiter.
+ */
links = ahsta->links_map;
for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
- arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
- arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
- if (!arvif || !arsta)
+ if (!test_bit(link_id, registered))
continue;
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
ar = arvif->ar;
- if (!ar)
- continue;
- ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr);
+ ret = ath12k_wait_for_peer_delete_done(ar, &waits[link_id]);
+ ath12k_peer_delete_wait_unregister(ar, &waits[link_id]);
if (ret) {
err_ret = ret;
continue;
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 49d89796bc46..3dc720a3dc12 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -9,13 +9,28 @@
#include "dp_peer.h"
+struct ath12k_peer_delete_wait {
+ struct list_head list;
+ u32 vdev_id;
+ u8 addr[ETH_ALEN];
+ struct completion done;
+};
+
+void ath12k_peer_delete_wait_register(struct ath12k *ar,
+ struct ath12k_peer_delete_wait *wait,
+ u32 vdev_id, const u8 *addr);
+void ath12k_peer_delete_wait_unregister(struct ath12k *ar,
+ struct ath12k_peer_delete_wait *wait);
+void ath12k_peer_delete_resp_signal(struct ath12k *ar, u32 vdev_id, const u8 *addr);
+void ath12k_peer_delete_wait_flush(struct ath12k *ar);
+
void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id);
int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr);
int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ieee80211_sta *sta,
struct ath12k_wmi_peer_create_arg *arg);
-int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
- const u8 *addr);
+int ath12k_wait_for_peer_delete_done(struct ath12k *ar,
+ struct ath12k_peer_delete_wait *wait);
int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta);
struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah,
const u8 *addr);
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 84a31b953db8..6066ca8d9fc4 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -7072,25 +7072,29 @@ static void ath12k_peer_delete_resp_event(struct ath12k_base *ab, struct sk_buff
{
struct wmi_peer_delete_resp_event peer_del_resp;
struct ath12k *ar;
+ u32 vdev_id;
if (ath12k_pull_peer_del_resp_ev(ab, skb, &peer_del_resp) != 0) {
- ath12k_warn(ab, "failed to extract peer delete resp");
+ ath12k_warn(ab, "failed to extract peer delete resp\n");
return;
}
+ vdev_id = le32_to_cpu(peer_del_resp.vdev_id);
+
rcu_read_lock();
- ar = ath12k_mac_get_ar_by_vdev_id(ab, le32_to_cpu(peer_del_resp.vdev_id));
+ ar = ath12k_mac_get_ar_by_vdev_id(ab, vdev_id);
if (!ar) {
- ath12k_warn(ab, "invalid vdev id in peer delete resp ev %d",
- peer_del_resp.vdev_id);
+ ath12k_warn(ab, "invalid vdev id in peer delete resp ev %d\n",
+ vdev_id);
rcu_read_unlock();
return;
}
- complete(&ar->peer_delete_done);
+ ath12k_peer_delete_resp_signal(ar, vdev_id,
+ peer_del_resp.peer_macaddr.addr);
rcu_read_unlock();
ath12k_dbg(ab, ATH12K_DBG_WMI, "peer delete resp for vdev id %d addr %pM\n",
- peer_del_resp.vdev_id, peer_del_resp.peer_macaddr.addr);
+ vdev_id, peer_del_resp.peer_macaddr.addr);
}
static void ath12k_vdev_delete_resp_event(struct ath12k_base *ab,
--
2.25.1
^ permalink raw reply related
* [PATCH ath-next 1/2] wifi: ath12k: fix dp_link_peer dangling references on AP vdev rollback
From: Baochen Qiang @ 2026-06-17 9:28 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
In-Reply-To: <20260617-ath12k-mlo-peer-delete-race-v1-0-ab3c4f455dfb@oss.qualcomm.com>
ath12k_mac_vdev_create() for an AP vdev creates the bss self-peer via
ath12k_peer_create(), which finishes by calling
ath12k_dp_link_peer_assign() to publish the dp_link_peer in the
dp_hw->dp_peers[peerid_index] RCU table, in the dp_peer's
link_peers[] array, and in the per-addr rhashtable.
If a step after ath12k_peer_create() fails the function jumps to
err_peer_del, which open-codes a WMI peer_delete and waits for the
unmap / delete_resp events. The wait_for_peer_delete_done() path
relies on ath12k_dp_link_peer_unmap_event() freeing the dp_link_peer
when the unmap arrives, but err_peer_del never calls
ath12k_dp_link_peer_unassign() first. The published references in
the dp_hw RCU table, dp_peer->link_peers[] and the rhashtable are
left pointing at the dp_link_peer that unmap_event then frees,
producing dangling pointers and use-after-free on subsequent
lookups.
Replace the open-coded sequence with a call to ath12k_peer_delete(),
which already does ath12k_dp_link_peer_unassign() before sending the
WMI command. This drops the published references before the
dp_link_peer is freed, in the same order as the normal teardown path
in ath12k_mac_remove_link_interface().
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3
Fixes: 5525f12fa671 ("wifi: ath12k: Attach and detach ath12k_dp_link_peer to ath12k_dp_peer")
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index af354bef5c0d..2e5a075191ae 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10564,22 +10564,8 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
err_peer_del:
if (ahvif->vdev_type == WMI_VDEV_TYPE_AP) {
- reinit_completion(&ar->peer_delete_done);
-
- ret = ath12k_wmi_send_peer_delete_cmd(ar, arvif->bssid,
- arvif->vdev_id);
- if (ret) {
- ath12k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n",
- arvif->vdev_id, arvif->bssid);
- goto err_dp_peer_del;
- }
-
- ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
- arvif->bssid);
- if (ret)
- goto err_dp_peer_del;
-
- ar->num_peers--;
+ /* ignore return value: propagate the original error */
+ ath12k_peer_delete(ar, arvif->vdev_id, arvif->bssid);
}
err_dp_peer_del:
--
2.25.1
^ permalink raw reply related
* [PATCH ath-next 0/2] wifi: ath12k: fix peer delete race in MLO scenario
From: Baochen Qiang @ 2026-06-17 9:28 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
Patch 1 fixes a pre-existing UAF in ath12k_mac_vdev_create()'s
err_peer_del rollback path.
Patch 2 fixes "Timeout in receiving peer delete response" on MLO
disconnect, caused by a per-radio shared completion that gets
clobbered between back-to-back WMI peer_delete sends.
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
Baochen Qiang (2):
wifi: ath12k: fix dp_link_peer dangling references on AP vdev rollback
wifi: ath12k: fix MLO peer delete race
drivers/net/wireless/ath/ath12k/core.c | 2 +-
drivers/net/wireless/ath/ath12k/core.h | 5 +-
drivers/net/wireless/ath/ath12k/mac.c | 20 +----
drivers/net/wireless/ath/ath12k/peer.c | 130 ++++++++++++++++++++++++++-------
drivers/net/wireless/ath/ath12k/peer.h | 19 ++++-
drivers/net/wireless/ath/ath12k/wmi.c | 16 ++--
6 files changed, 138 insertions(+), 54 deletions(-)
---
base-commit: 4987a85fb0475defee458fa11af877c8e02f764a
change-id: 20260602-ath12k-mlo-peer-delete-race-74fdaf880017
Best regards,
--
Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply
* [PATCH RESEND v3] wifi: mt76: mt7921: fix resource leak in probe error path
From: Hongling Zeng @ 2026-06-17 8:58 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, xiong.huang, madhurkumar004
Cc: linux-wireless, linux-kernel, linux-arm-kernel, linux-mediatek,
zhongling0719, Hongling Zeng
When pcim_iomap_region() or devm_kmemdup() fail, the code returns
directly without cleaning up previously allocated resources:
- mt76_device allocated by mt76_alloc_device()
- pci irq vectors allocated by pci_alloc_irq_vectors()
Fix this by jumping to the existing error cleanup path instead of
returning directly.
To avoid using an uninitialized variable in the error path, move the
dev initialization before the error checks.
Fixes: ee5bb35d2b83 ("wifi: mt76: mt7921: Replace deprecated PCI function")
Fixes: 222606f43b58 ("wifi: mt76: mt7921: handle MT7902 irq_map quirk with mutable copy")
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
---
Change in v3
- Fix incorrect Fixes: tag as pointed out by Sean
- Correct tag from unrelated phy/ti-pipe3 commit to the actual mt76 commit
that introduced the resource leak
---
drivers/net/wireless/mediatek/mt76/mt7921/pci.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
index 7a790ddf43bb..49a37185f056 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/pci.c
@@ -343,11 +343,14 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, mdev);
+ dev = container_of(mdev, struct mt792x_dev, mt76);
+
regs = pcim_iomap_region(pdev, 0, pci_name(pdev));
- if (IS_ERR(regs))
- return PTR_ERR(regs);
+ if (IS_ERR(regs)) {
+ ret = PTR_ERR(regs);
+ goto err_free_dev;
+ }
- dev = container_of(mdev, struct mt792x_dev, mt76);
dev->fw_features = features;
dev->hif_ops = &mt7921_pcie_ops;
dev->irq_map = &irq_map;
@@ -359,8 +362,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
/* MT7902 needs a mutable copy because wm2_complete_mask differs */
map = devm_kmemdup(&pdev->dev, &irq_map,
sizeof(irq_map), GFP_KERNEL);
- if (!map)
- return -ENOMEM;
+ if (!map) {
+ ret = -ENOMEM;
+ goto err_free_dev;
+ }
map->rx.wm2_complete_mask = 0;
dev->irq_map = map;
--
2.25.1
^ permalink raw reply related
* Re: [PATCH ath-next 0/5] wifi: ath12k: fix dp_mon RX parsing for 32-bit TLV
From: Baochen Qiang @ 2026-06-17 8:57 UTC (permalink / raw)
To: Miaoqing Pan, jjohnson; +Cc: ath12k, linux-wireless, linux-kernel
In-Reply-To: <20260509025819.1641630-1-miaoqing.pan@oss.qualcomm.com>
On 5/9/2026 10:58 AM, Miaoqing Pan wrote:
> 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
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next v2] wifi: ath12k: avoid setting 320MHZ support on non 6GHz band
From: Nicolas Escande @ 2026-06-17 8:45 UTC (permalink / raw)
To: Rameshkumar Sundaram, ath12k; +Cc: linux-wireless
In-Reply-To: <3fb00a3b-2092-43d2-a8f8-9f934505dcee@oss.qualcomm.com>
On Wed Jun 17, 2026 at 7:03 AM CEST, Rameshkumar Sundaram wrote:
> On 6/11/2026 2:14 PM, Nicolas Escande wrote:
>> On a split phy qcn9274 (2.4GHz + 5GHz low), "iw phy" reports 320MHz
>> realated features on the 5GHz band while it should not:
>
>
> s/realated/related
sure
>
>>
>> Wiphy phy1
>> [...]
>> Band 2:
>> [...]
>> EHT Iftypes: managed
>> [...]
>> EHT PHY Capabilities: (0xe2ffdbe018778000):
>> 320MHz in 6GHz Supported
>> [...]
>> Beamformee SS (320MHz): 7
>> [...]
>> Number Of Sounding Dimensions (320MHz): 3
>> [...]
>> EHT MCS/NSS: (0x22222222222222222200000000):
>>
>> This is also reflected in the beacons sent by a mesh interface started on
>> that band. They erroneously advertise 320MHZ support too.
>
> s/320MHZ/320MHz
sure
>
>>
>> This should not happen as the spec at section 9.4.2.323.3 says we should
>
> Reword the spec citation to: IEEE Std 802.11-2024, subclause 9.4.2.323.3 ...
>
>
>> not set the 320MHz related fields when not operating on a 6GHz band.
>> For example it says about Bit 0 "Support For 320 MHz In 6 GHz"
>>
>> "Reserved if the EHT Capabilities element is indicating capabilities for
>> the 2.4 GHz or 5 GHz bands."
>>
>> Fix this by clearing the related bits when converting from WMI eht phy
>> capabilities to mac80211 phy capabilities, for bands other than 6GHz.
>>
>> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1
>>
>
> The commit log mentions wrong `iw phy` output and wrong mesh beacon
> advertisement, so this appears user visible. If that is the intended bug
> being fixed, please add a Fixes tag.
>
Well I did not put a fixes tag as this does not create any real problems
per say. It does not impede any sta to connect in any way. Only
people explicitely parsing the beacons IE see an unexpected value.
So unless you guys really insist, I'd just skip it. Otherwise the 2
candidates are are:
- 1476014fadb6 ("wifi: ath12k: WMI support to process EHT capabilities")
It added the EHT caps parsing but lacked any logic to handle 6G so
that means backporting would imply a different patch than this one
- d4e244c85e45 ("wifi: ath12k: enable 320 MHz bandwidth for 6 GHz band
in EHT PHY capability for WCN7850"). This one added 6GHz support and
is the one I'm fixing but for a different chipset in mind than mine.
>> Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
>> ---
>> Changes from v1:
>> - rebased on ath-next
>> - clear all 6GHz / 320MHz related phy capabilities fields from the firmware
>> ---
>> drivers/net/wireless/ath/ath12k/wmi.c | 17 ++++++++++++++++-
>> 1 file changed, 16 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
>> index 84a31b953db8..a8a4654c4f34 100644
>> --- a/drivers/net/wireless/ath/ath12k/wmi.c
>> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
>> @@ -5154,6 +5154,7 @@ static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,
>> __le32 cap_info_internal)
>> {
>> struct ath12k_band_cap *cap_band = &pdev->cap.band[band];
>> + u8 *phy_cap = (u8 *)&cap_band->eht_cap_phy_info[0];
>> u32 support_320mhz;
>> u8 i;
>>
>> @@ -5167,8 +5168,22 @@ static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,
>> for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++)
>> cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]);
>>
>> - if (band == NL80211_BAND_6GHZ)
>> + if (band == NL80211_BAND_6GHZ) {
>> cap_band->eht_cap_phy_info[0] |= support_320mhz;
>> + } else {
>> + /*
>> + * It seems the firmware can report capabilities specific to
>> + * 6GHz also for 5GHz, so lets explicitely clear them out.
>
> The code comment should be less tentative, how about:
>
> /*
> * Firmware may report 6 GHz/320 MHz specific capabilities for
> * non-6 GHz bands, so explicitly clear them.
> */
>
sure
>
>> + */
>> + phy_cap[0] &= ~IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
>> + phy_cap[1] &= ~IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK;
>> + phy_cap[2] &= ~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
>> + phy_cap[3] &= ~IEEE80211_EHT_PHY_CAP3_SOUNDING_DIM_320MHZ_MASK;
>> + phy_cap[6] &= ~IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_320MHZ;
>> + phy_cap[6] &= ~IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP;
>> + phy_cap[7] &= ~IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ;
>> + phy_cap[7] &= ~IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; ;
>> + }
>>
>> cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]);
>> cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]);
>
>
> checkpatch warnings:
> ERROR: trailing whitespace
> #61: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5171:
> +^Iif (band == NL80211_BAND_6GHZ) {^I$
>
> WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
> #66: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5176:
> + * 6GHz also for 5GHz, so lets explicitely clear them out.
> ^^^^^^^^^^^
>
> WARNING: space prohibited before semicolon
> #75: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5185:
> + phy_cap[7] &=
> ~IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; ;
>
> WARNING: Statements terminations use 1 semicolon
> #75: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5185:
> + phy_cap[7] &=
> ~IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; ;
And all that will be fixed obviously
Thanks for the review
^ permalink raw reply
* RE: [PATCH wireless] wifi: rtw88: pci: fix resource leak on failed NAPI setup
From: Ping-Ke Shih @ 2026-06-17 8:33 UTC (permalink / raw)
To: Dawei Feng
Cc: leitao@debian.org, linux-wireless@vger.kernel.org,
linux-kernel@vger.kernel.org, jianhao.xu@seu.edu.cn,
zilin@seu.edu.cn, stable@vger.kernel.org
In-Reply-To: <20260617013502.114057-1-dawei.feng@seu.edu.cn>
Dawei Feng <dawei.feng@seu.edu.cn> wrote:
> rtw_pci_probe() allocates PCI resources through
> rtw_pci_setup_resource() before it sets up NAPI. If
> rtw_pci_napi_init() fails, the error path jumps straight to
> err_pci_declaim and skips rtw_pci_destroy(), leaving the PCI
> resources allocated by rtw_pci_setup_resource() behind.
>
> Add a dedicated cleanup label for the NAPI setup failure path so probe
> destroys the PCI resources.
>
> The bug was first flagged by an experimental analysis tool we are
> developing for kernel memory-management bugs while analyzing current
> mainline kernels. The tool is still under development and is not yet
> publicly available. Manual inspection confirms that the bug is still
> present in v7.1-rc7.
>
> An x86_64 allyesconfig build showed no new warnings. As we do not have a
> suitable rtw88 PCI board to test with, no runtime testing was able to be
> performed.
>
> Fixes: d0bcb10e7b94 ("wifi: rtw88: Un-embed dummy device")
> Cc: stable@vger.kernel.org
> Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
^ permalink raw reply
* Re: [PATCH rtw-next 2/3] wifi: rtlwifi: convert pci ID if-statement to table
From: Uwe Kleine-König @ 2026-06-17 8:26 UTC (permalink / raw)
To: William Hansen-Baird; +Cc: pkshih, linux-wireless, linux-kernel
In-Reply-To: <20260614135508.70307-3-william.hansen.baird@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1164 bytes --]
On Sun, Jun 14, 2026 at 03:55:07PM +0200, William Hansen-Baird wrote:
> Refactor the ASUSTek quirk logic from an if-statement to a standard
> pci_device_id table. This allows future devices with the same quirk
> to be added more easily and avoiding a large if-chain.
>
> Signed-off-by: William Hansen-Baird <william.hansen.baird@gmail.com>
> ---
> drivers/net/wireless/realtek/rtlwifi/pci.c | 11 +++++++----
> 1 file changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
> index 4ef1faf649e9..03b743809258 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/pci.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
> @@ -31,6 +31,11 @@ static const u8 ac_to_hwq[] = {
> BK_QUEUE
> };
>
> +static const struct pci_device_id rtl8723be_aspm_quirks[] = {
> + { PCI_DEVICE_SUB(PCI_ANY_ID, PCI_ANY_ID, 0x11ad, 0x1723) },
> + { 0 }
I recently reworked many pci_device_id arrays and en passant made the
terminator an empty initializer with a single space (i.e. `{ }`).
If you resend, adapting to that style would be nice.
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* RE: [PATCH rtw-next v2 3/3] wifi: rtlwifi: disable ASPM for RTL8723BE with subsystem ID 17aa:b736
From: Ping-Ke Shih @ 2026-06-17 8:24 UTC (permalink / raw)
To: William Hansen-Baird
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260616141620.91081-4-william.hansen.baird@gmail.com>
William Hansen-Baird <william.hansen.baird@gmail.com> wrote:
> RTL8723BE outputs a large amount of PCIe AER errors during and
> after boot, even before probe and when driver is never loaded.
> This causes significant system slowdown.
>
> The errors are the same as reported by
> commit 77a6407c6ab2 ("wifi: rtlwifi: disable ASPM for RTL8723BE with subsystem ID 11ad:1723")
>
> Add the RTL8723BE with subsystem ID 17aa:b736 to the rtl_aspm_quirks
> table to stop the AER errors. AER errors can still be present prior to
> pci probe, as the device by default may have ASPM enabled.
>
> Testing on a Razer Blade 14 2017 which shipped from the
> OEM equipped with an RTL8723BE card with this subsystem ID
> confirms that this patch resolves the AER flood and allows the
> wireless card to function normally once the driver takes over.
>
> Signed-off-by: William Hansen-Baird <william.hansen.baird@gmail.com>
Only minor suggestion, so
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
> ---
> drivers/net/wireless/realtek/rtlwifi/pci.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c
> b/drivers/net/wireless/realtek/rtlwifi/pci.c
> index 9de396879806..9919c8588cbd 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/pci.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
> @@ -33,6 +33,7 @@ static const u8 ac_to_hwq[] = {
>
> static const struct pci_device_id rtl_aspm_quirks[] = {
> { PCI_DEVICE_SUB(PCI_VENDOR_ID_REALTEK, 0xb723, 0x11ad, 0x1723) },
> + { PCI_DEVICE_SUB(PCI_VENDOR_ID_REALTEK, 0xb723, 0x17aa, 0xb736) },
Would you like a comment "Razer Blade 14 2017"?
> { 0 }
> };
>
> --
> 2.54.0
^ permalink raw reply
* RE: [PATCH rtw-next v2 2/3] wifi: rtlwifi: convert pci if-statement to ID table
From: Ping-Ke Shih @ 2026-06-17 8:22 UTC (permalink / raw)
To: William Hansen-Baird
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260616141620.91081-3-william.hansen.baird@gmail.com>
William Hansen-Baird <william.hansen.baird@gmail.com> wrote:
> Refactor the ASUSTek quirk logic from an if-statement to a standard
> rtl_aspm_quirks pci_device_id table. This allows future devices with
> the same quirk to be added more easily while avoiding a large if-chain.
>
> Signed-off-by: William Hansen-Baird <william.hansen.baird@gmail.com>
> ---
> drivers/net/wireless/realtek/rtlwifi/pci.c | 15 ++++++++-------
> 1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c
> b/drivers/net/wireless/realtek/rtlwifi/pci.c
> index a5bab06f2b61..9de396879806 100644
> --- a/drivers/net/wireless/realtek/rtlwifi/pci.c
> +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
> @@ -31,6 +31,11 @@ static const u8 ac_to_hwq[] = {
> BK_QUEUE
> };
>
> +static const struct pci_device_id rtl_aspm_quirks[] = {
> + { PCI_DEVICE_SUB(PCI_VENDOR_ID_REALTEK, 0xb723, 0x11ad, 0x1723) },
Would you leave a comment ASUSTek F441U/X555UQ?
> + { 0 }
Just "{}"
> +};
> +
> static u8 _rtl_mac_to_hwqueue(struct ieee80211_hw *hw, struct sk_buff *skb)
> {
> struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
> @@ -328,21 +333,17 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
>
> static void rtl_pci_init_aspm(struct ieee80211_hw *hw)
> {
> - struct rtl_priv *rtlpriv = rtl_priv(hw);
> struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
> struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
>
> _rtl_pci_update_default_setting(hw);
>
> - /* RTL8723BE found on some ASUSTek laptops, such as F441U and
> - * X555UQ with subsystem ID 11ad:1723 are known to output large
> + /* Certain pci devices are known to output large
Now we don't use net specific comment. Use below style:
/*
* (first line)
*/
(we should apply this style to patch 1/3 as well)
> * amounts of PCIe AER errors during and after boot up, causing
> * heavy lags, poor network throughput, and occasional lock-ups.
> */
> - if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8723BE &&
> - (rtlpci->pdev->subsystem_vendor == 0x11ad &&
> - rtlpci->pdev->subsystem_device == 0x1723)) {
> + if (pci_match_id(rtl_aspm_quirks, rtlpci->pdev)) {
> __rtl_pci_disable_aspm(hw);
> ppsc->support_aspm = false;
> }
>
> --
> 2.54.0
^ permalink raw reply
* RE: [PATCH rtw-next v2 1/3] wifi: rtlwifi: fix disabling of ASPM for RTL8723BE with AER flooding
From: Ping-Ke Shih @ 2026-06-17 8:18 UTC (permalink / raw)
To: William Hansen-Baird
Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260616141620.91081-2-william.hansen.baird@gmail.com>
William Hansen-Baird <william.hansen.baird@gmail.com> wrote:
> commit 77a6407c6ab2 ("wifi: rtlwifi: disable ASPM for RTL8723BE with subsystem ID 11ad:1723")
> adds code which sets ppsc->support_aspm to false in
> _rtl_pci_update_default_setting() in order to disable ASPM.
> This does not, however, disable ASPM. Rather, it disables driver
> control of ASPM, and blocks calls to rtl_pci_enable_aspm()
> and rtl_pci_disable_aspm().
>
> In some cases, the pci device supplied to the probe function has
> ASPM enabled. The code would therefore not disable ASPM, as it means to,
> but rather just leave it enabled.
> This was discovered through testing on a Razer Blade 14 2017.
>
> Implement a new __rtl_pci_disable_aspm(hw) function which does not check
> ppsc->support_aspm before disabling and call it from
> rtl_pci_disable_aspm().
>
> Then move the code added in the previous commit to rtl_pci_init_aspm() to
> allow adding a call to __rtl_pci_disable_aspm(hw).
> This makes sure ASPM is disabled while still disabling
> driver control of ASPM to block it from being enabled later.
>
> Fixes: 77a6407c6ab2 ("wifi: rtlwifi: disable ASPM for RTL8723BE with subsystem ID 11ad:1723")
The commit can resolve problem from original report, so it seems like
this patch to refactor to resolve your case as well.
I'd remove this Fixes. How about you?
[...]
> @@ -330,10 +328,24 @@ static void rtl_pci_parse_configuration(struct pci_dev *pdev,
>
> static void rtl_pci_init_aspm(struct ieee80211_hw *hw)
> {
> + struct rtl_priv *rtlpriv = rtl_priv(hw);
> struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
> + struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
In reverse X'mas order.
>
> _rtl_pci_update_default_setting(hw);
>
> + /* RTL8723BE found on some ASUSTek laptops, such as F441U and
> + * X555UQ with subsystem ID 11ad:1723 are known to output large
> + * amounts of PCIe AER errors during and after boot up, causing
> + * heavy lags, poor network throughput, and occasional lock-ups.
> + */
> + if (rtlpriv->rtlhal.hw_type == HARDWARE_TYPE_RTL8723BE &&
> + (rtlpci->pdev->subsystem_vendor == 0x11ad &&
> + rtlpci->pdev->subsystem_device == 0x1723)) {
> + __rtl_pci_disable_aspm(hw);
> + ppsc->support_aspm = false;
> + }
> +
> if (ppsc->reg_rfps_level & RT_RF_PS_LEVEL_ALWAYS_ASPM) {
> /*Always enable ASPM & Clock Req. */
> rtl_pci_enable_aspm(hw);
> --
> 2.54.0
^ permalink raw reply
* [PATCH] wifi: mt76: mt7925: fix msg len mismatch between driver and firmware
From: JB Tsai @ 2026-06-17 7:13 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, jared.huang, jb.tsai
From: "Jared.Huang" <jared.huang@mediatek.com>
The mt7925_tx_power_limit_tlv struct begins with a 4-byte rsv[] field
that acts as a UNI command header prefix. The firmware dispatcher did
not use the 4-byte rsv[] and will only check the payloads after the
4-byte rsv[] As a result, the total message length minus the 4-byte
prefix. Fix this by setting len to msg_len - 4.
Fixes: ccb1863 ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Signed-off-by: Jared.Huang <jared.huang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index e94fa544ff20..7d9b8ebf2889 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -3827,7 +3827,7 @@ mt7925_mcu_rate_txpower_band(struct mt76_phy *phy,
memcpy(tx_power_tlv->alpha2, dev->alpha2, sizeof(dev->alpha2));
tx_power_tlv->n_chan = num_ch;
tx_power_tlv->tag = cpu_to_le16(0x1);
- tx_power_tlv->len = cpu_to_le16(msg_len);
+ tx_power_tlv->len = cpu_to_le16(msg_len - 4);
switch (band) {
case NL80211_BAND_2GHZ:
--
2.45.2
^ permalink raw reply related
* [PATCH] wifi: mt76: mt7925: update clc before setting sar power table
From: JB Tsai @ 2026-06-17 7:13 UTC (permalink / raw)
To: nbd, lorenzo
Cc: linux-wireless, linux-mediatek, Deren.Wu, Sean.Wang, Quan.Zhou,
Ryder.Lee, Leon.Yen, litien.chang, jared.huang, jb.tsai
From: "Jared.Huang" <jared.huang@mediatek.com>
Fix the power table update sequence to ensure CLC is loaded before
setting SAR power table.
The firmware requires CLC baseline to be established first
to properly calculate the final power limit as min(clc_limit, rate_limit,sar_limit).
Fixes: 9557b6fe0c8b ("wifi: mt76: mt7925: refine the txpower initialization flow")
Signed-off-by: Jared.Huang <jared.huang@mediatek.com>
---
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index a9059866b701..afb2b473bef7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1824,9 +1824,15 @@ static int mt7925_set_sar_specs(struct ieee80211_hw *hw,
int err;
mt792x_mutex_acquire(dev);
+ err = mt7925_mcu_set_clc(dev, dev->mt76.alpha2,
+ dev->country_ie_env);
+ if (err < 0)
+ goto out;
+
err = mt7925_set_tx_sar_pwr(hw, sar);
- mt792x_mutex_release(dev);
+out:
+ mt792x_mutex_release(dev);
return err;
}
--
2.45.2
^ permalink raw reply related
* Re: [PATCH ath-next] wifi: ath12k: expand UserPD ID mask to support up to 8 PDs
From: Baochen Qiang @ 2026-06-17 6:48 UTC (permalink / raw)
To: Aaradhana Sahu, ath12k; +Cc: linux-wireless
In-Reply-To: <20260604031551.4178754-1-aaradhana.sahu@oss.qualcomm.com>
On 6/4/2026 11:15 AM, Aaradhana Sahu wrote:
> Currently ATH12K_USERPD_ID_MASK uses GENMASK(9, 8), which defines a
> 2-bit field and limits supported UserPD IDs to values 0-3.
>
> Future IPQ5332 multi-PD platform variants support more than three
> UserPDs. Expand ATH12K_USERPD_ID_MASK to GENMASK(10, 8), increasing
> the field width to 3 bits and allowing UserPD IDs from 0-7.
>
> ATH12K_USERPD_ID_MASK is currently used only while constructing the
> ath12k AHB PAS ID, so this change does not affect existing platforms.
>
> Also remove the unused ATH12K_MAX_UPDS definition.
>
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.6-01275-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath9k: drop static from local pdadc and vpdTable arrays
From: kernel test robot @ 2026-06-17 6:00 UTC (permalink / raw)
To: Rosen Penev, linux-wireless
Cc: oe-kbuild-all, Toke Høiland-Jørgensen, linux-kernel
In-Reply-To: <20260616030828.655310-1-rosenp@gmail.com>
Hi Rosen,
kernel test robot noticed the following build warnings:
[auto build test WARNING on ath/ath-next]
[also build test WARNING on wireless/main wireless-next/main linus/master v7.1 next-20260616]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Rosen-Penev/wifi-ath9k-drop-static-from-local-pdadc-and-vpdTable-arrays/20260616-114515
base: https://git.kernel.org/pub/scm/linux/kernel/git/ath/ath.git ath-next
patch link: https://lore.kernel.org/r/20260616030828.655310-1-rosenp%40gmail.com
patch subject: [PATCH ath-next] wifi: ath9k: drop static from local pdadc and vpdTable arrays
config: arm-allyesconfig (https://download.01.org/0day-ci/archive/20260617/202606171341.zUckYxVR-lkp@intel.com/config)
compiler: arm-linux-gnueabi-gcc (GCC) 16.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260617/202606171341.zUckYxVR-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202606171341.zUckYxVR-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/net/wireless/ath/ath9k/eeprom.c: In function 'ath9k_hw_get_gain_boundaries_pdadcs':
>> drivers/net/wireless/ath/ath9k/eeprom.c:657:1: warning: the frame size of 1360 bytes is larger than 1280 bytes [-Wframe-larger-than=]
657 | }
| ^
vim +657 drivers/net/wireless/ath/ath9k/eeprom.c
a55f858852e4345 Sujith 2010-06-01 451
115277a3bc0683d Felix Fietkau 2010-12-12 452 void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
115277a3bc0683d Felix Fietkau 2010-12-12 453 struct ath9k_channel *chan,
115277a3bc0683d Felix Fietkau 2010-12-12 454 void *pRawDataSet,
115277a3bc0683d Felix Fietkau 2010-12-12 455 u8 *bChans, u16 availPiers,
115277a3bc0683d Felix Fietkau 2010-12-12 456 u16 tPdGainOverlap,
115277a3bc0683d Felix Fietkau 2010-12-12 457 u16 *pPdGainBoundaries, u8 *pPDADCValues,
115277a3bc0683d Felix Fietkau 2010-12-12 458 u16 numXpdGains)
115277a3bc0683d Felix Fietkau 2010-12-12 459 {
115277a3bc0683d Felix Fietkau 2010-12-12 460 int i, j, k;
115277a3bc0683d Felix Fietkau 2010-12-12 461 int16_t ss;
115277a3bc0683d Felix Fietkau 2010-12-12 462 u16 idxL = 0, idxR = 0, numPiers;
8e792d8755eaf1a Rosen Penev 2026-06-15 463 u8 vpdTableL[AR5416_NUM_PD_GAINS]
115277a3bc0683d Felix Fietkau 2010-12-12 464 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
8e792d8755eaf1a Rosen Penev 2026-06-15 465 u8 vpdTableR[AR5416_NUM_PD_GAINS]
115277a3bc0683d Felix Fietkau 2010-12-12 466 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
8e792d8755eaf1a Rosen Penev 2026-06-15 467 u8 vpdTableI[AR5416_NUM_PD_GAINS]
115277a3bc0683d Felix Fietkau 2010-12-12 468 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
115277a3bc0683d Felix Fietkau 2010-12-12 469
115277a3bc0683d Felix Fietkau 2010-12-12 470 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
115277a3bc0683d Felix Fietkau 2010-12-12 471 u8 minPwrT4[AR5416_NUM_PD_GAINS];
115277a3bc0683d Felix Fietkau 2010-12-12 472 u8 maxPwrT4[AR5416_NUM_PD_GAINS];
115277a3bc0683d Felix Fietkau 2010-12-12 473 int16_t vpdStep;
115277a3bc0683d Felix Fietkau 2010-12-12 474 int16_t tmpVal;
115277a3bc0683d Felix Fietkau 2010-12-12 475 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
115277a3bc0683d Felix Fietkau 2010-12-12 476 bool match;
115277a3bc0683d Felix Fietkau 2010-12-12 477 int16_t minDelta = 0;
115277a3bc0683d Felix Fietkau 2010-12-12 478 struct chan_centers centers;
115277a3bc0683d Felix Fietkau 2010-12-12 479 int pdgain_boundary_default;
115277a3bc0683d Felix Fietkau 2010-12-12 480 struct cal_data_per_freq *data_def = pRawDataSet;
115277a3bc0683d Felix Fietkau 2010-12-12 481 struct cal_data_per_freq_4k *data_4k = pRawDataSet;
940cd2c12ebff68 Felix Fietkau 2010-12-12 482 struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
115277a3bc0683d Felix Fietkau 2010-12-12 483 bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
940cd2c12ebff68 Felix Fietkau 2010-12-12 484 int intercepts;
940cd2c12ebff68 Felix Fietkau 2010-12-12 485
940cd2c12ebff68 Felix Fietkau 2010-12-12 486 if (AR_SREV_9287(ah))
940cd2c12ebff68 Felix Fietkau 2010-12-12 487 intercepts = AR9287_PD_GAIN_ICEPTS;
940cd2c12ebff68 Felix Fietkau 2010-12-12 488 else
940cd2c12ebff68 Felix Fietkau 2010-12-12 489 intercepts = AR5416_PD_GAIN_ICEPTS;
115277a3bc0683d Felix Fietkau 2010-12-12 490
115277a3bc0683d Felix Fietkau 2010-12-12 491 memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
115277a3bc0683d Felix Fietkau 2010-12-12 492 ath9k_hw_get_channel_centers(ah, chan, ¢ers);
115277a3bc0683d Felix Fietkau 2010-12-12 493
115277a3bc0683d Felix Fietkau 2010-12-12 494 for (numPiers = 0; numPiers < availPiers; numPiers++) {
115277a3bc0683d Felix Fietkau 2010-12-12 495 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
115277a3bc0683d Felix Fietkau 2010-12-12 496 break;
115277a3bc0683d Felix Fietkau 2010-12-12 497 }
115277a3bc0683d Felix Fietkau 2010-12-12 498
115277a3bc0683d Felix Fietkau 2010-12-12 499 match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
115277a3bc0683d Felix Fietkau 2010-12-12 500 IS_CHAN_2GHZ(chan)),
115277a3bc0683d Felix Fietkau 2010-12-12 501 bChans, numPiers, &idxL, &idxR);
115277a3bc0683d Felix Fietkau 2010-12-12 502
115277a3bc0683d Felix Fietkau 2010-12-12 503 if (match) {
940cd2c12ebff68 Felix Fietkau 2010-12-12 504 if (AR_SREV_9287(ah)) {
940cd2c12ebff68 Felix Fietkau 2010-12-12 505 for (i = 0; i < numXpdGains; i++) {
940cd2c12ebff68 Felix Fietkau 2010-12-12 506 minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
83d6f1f15f8cce8 Arnd Bergmann 2016-03-14 507 maxPwrT4[i] = data_9287[idxL].pwrPdg[i][intercepts - 1];
940cd2c12ebff68 Felix Fietkau 2010-12-12 508 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
940cd2c12ebff68 Felix Fietkau 2010-12-12 509 data_9287[idxL].pwrPdg[i],
940cd2c12ebff68 Felix Fietkau 2010-12-12 510 data_9287[idxL].vpdPdg[i],
940cd2c12ebff68 Felix Fietkau 2010-12-12 511 intercepts,
940cd2c12ebff68 Felix Fietkau 2010-12-12 512 vpdTableI[i]);
940cd2c12ebff68 Felix Fietkau 2010-12-12 513 }
940cd2c12ebff68 Felix Fietkau 2010-12-12 514 } else if (eeprom_4k) {
115277a3bc0683d Felix Fietkau 2010-12-12 515 for (i = 0; i < numXpdGains; i++) {
115277a3bc0683d Felix Fietkau 2010-12-12 516 minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
83d6f1f15f8cce8 Arnd Bergmann 2016-03-14 517 maxPwrT4[i] = data_4k[idxL].pwrPdg[i][intercepts - 1];
115277a3bc0683d Felix Fietkau 2010-12-12 518 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
115277a3bc0683d Felix Fietkau 2010-12-12 519 data_4k[idxL].pwrPdg[i],
115277a3bc0683d Felix Fietkau 2010-12-12 520 data_4k[idxL].vpdPdg[i],
940cd2c12ebff68 Felix Fietkau 2010-12-12 521 intercepts,
115277a3bc0683d Felix Fietkau 2010-12-12 522 vpdTableI[i]);
115277a3bc0683d Felix Fietkau 2010-12-12 523 }
115277a3bc0683d Felix Fietkau 2010-12-12 524 } else {
115277a3bc0683d Felix Fietkau 2010-12-12 525 for (i = 0; i < numXpdGains; i++) {
115277a3bc0683d Felix Fietkau 2010-12-12 526 minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
83d6f1f15f8cce8 Arnd Bergmann 2016-03-14 527 maxPwrT4[i] = data_def[idxL].pwrPdg[i][intercepts - 1];
115277a3bc0683d Felix Fietkau 2010-12-12 528 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
115277a3bc0683d Felix Fietkau 2010-12-12 529 data_def[idxL].pwrPdg[i],
115277a3bc0683d Felix Fietkau 2010-12-12 530 data_def[idxL].vpdPdg[i],
940cd2c12ebff68 Felix Fietkau 2010-12-12 531 intercepts,
115277a3bc0683d Felix Fietkau 2010-12-12 532 vpdTableI[i]);
115277a3bc0683d Felix Fietkau 2010-12-12 533 }
115277a3bc0683d Felix Fietkau 2010-12-12 534 }
115277a3bc0683d Felix Fietkau 2010-12-12 535 } else {
115277a3bc0683d Felix Fietkau 2010-12-12 536 for (i = 0; i < numXpdGains; i++) {
940cd2c12ebff68 Felix Fietkau 2010-12-12 537 if (AR_SREV_9287(ah)) {
940cd2c12ebff68 Felix Fietkau 2010-12-12 538 pVpdL = data_9287[idxL].vpdPdg[i];
940cd2c12ebff68 Felix Fietkau 2010-12-12 539 pPwrL = data_9287[idxL].pwrPdg[i];
940cd2c12ebff68 Felix Fietkau 2010-12-12 540 pVpdR = data_9287[idxR].vpdPdg[i];
940cd2c12ebff68 Felix Fietkau 2010-12-12 541 pPwrR = data_9287[idxR].pwrPdg[i];
940cd2c12ebff68 Felix Fietkau 2010-12-12 542 } else if (eeprom_4k) {
115277a3bc0683d Felix Fietkau 2010-12-12 543 pVpdL = data_4k[idxL].vpdPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 544 pPwrL = data_4k[idxL].pwrPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 545 pVpdR = data_4k[idxR].vpdPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 546 pPwrR = data_4k[idxR].pwrPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 547 } else {
115277a3bc0683d Felix Fietkau 2010-12-12 548 pVpdL = data_def[idxL].vpdPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 549 pPwrL = data_def[idxL].pwrPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 550 pVpdR = data_def[idxR].vpdPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 551 pPwrR = data_def[idxR].pwrPdg[i];
115277a3bc0683d Felix Fietkau 2010-12-12 552 }
115277a3bc0683d Felix Fietkau 2010-12-12 553
115277a3bc0683d Felix Fietkau 2010-12-12 554 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
115277a3bc0683d Felix Fietkau 2010-12-12 555
115277a3bc0683d Felix Fietkau 2010-12-12 556 maxPwrT4[i] =
940cd2c12ebff68 Felix Fietkau 2010-12-12 557 min(pPwrL[intercepts - 1],
940cd2c12ebff68 Felix Fietkau 2010-12-12 558 pPwrR[intercepts - 1]);
115277a3bc0683d Felix Fietkau 2010-12-12 559
115277a3bc0683d Felix Fietkau 2010-12-12 560
115277a3bc0683d Felix Fietkau 2010-12-12 561 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
115277a3bc0683d Felix Fietkau 2010-12-12 562 pPwrL, pVpdL,
940cd2c12ebff68 Felix Fietkau 2010-12-12 563 intercepts,
115277a3bc0683d Felix Fietkau 2010-12-12 564 vpdTableL[i]);
115277a3bc0683d Felix Fietkau 2010-12-12 565 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
115277a3bc0683d Felix Fietkau 2010-12-12 566 pPwrR, pVpdR,
940cd2c12ebff68 Felix Fietkau 2010-12-12 567 intercepts,
115277a3bc0683d Felix Fietkau 2010-12-12 568 vpdTableR[i]);
115277a3bc0683d Felix Fietkau 2010-12-12 569
115277a3bc0683d Felix Fietkau 2010-12-12 570 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
115277a3bc0683d Felix Fietkau 2010-12-12 571 vpdTableI[i][j] =
115277a3bc0683d Felix Fietkau 2010-12-12 572 (u8)(ath9k_hw_interpolate((u16)
115277a3bc0683d Felix Fietkau 2010-12-12 573 FREQ2FBIN(centers.
115277a3bc0683d Felix Fietkau 2010-12-12 574 synth_center,
115277a3bc0683d Felix Fietkau 2010-12-12 575 IS_CHAN_2GHZ
115277a3bc0683d Felix Fietkau 2010-12-12 576 (chan)),
115277a3bc0683d Felix Fietkau 2010-12-12 577 bChans[idxL], bChans[idxR],
115277a3bc0683d Felix Fietkau 2010-12-12 578 vpdTableL[i][j], vpdTableR[i][j]));
115277a3bc0683d Felix Fietkau 2010-12-12 579 }
115277a3bc0683d Felix Fietkau 2010-12-12 580 }
115277a3bc0683d Felix Fietkau 2010-12-12 581 }
115277a3bc0683d Felix Fietkau 2010-12-12 582
115277a3bc0683d Felix Fietkau 2010-12-12 583 k = 0;
115277a3bc0683d Felix Fietkau 2010-12-12 584
115277a3bc0683d Felix Fietkau 2010-12-12 585 for (i = 0; i < numXpdGains; i++) {
115277a3bc0683d Felix Fietkau 2010-12-12 586 if (i == (numXpdGains - 1))
115277a3bc0683d Felix Fietkau 2010-12-12 587 pPdGainBoundaries[i] =
115277a3bc0683d Felix Fietkau 2010-12-12 588 (u16)(maxPwrT4[i] / 2);
115277a3bc0683d Felix Fietkau 2010-12-12 589 else
115277a3bc0683d Felix Fietkau 2010-12-12 590 pPdGainBoundaries[i] =
115277a3bc0683d Felix Fietkau 2010-12-12 591 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
115277a3bc0683d Felix Fietkau 2010-12-12 592
115277a3bc0683d Felix Fietkau 2010-12-12 593 pPdGainBoundaries[i] =
115277a3bc0683d Felix Fietkau 2010-12-12 594 min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
115277a3bc0683d Felix Fietkau 2010-12-12 595
115277a3bc0683d Felix Fietkau 2010-12-12 596 minDelta = 0;
115277a3bc0683d Felix Fietkau 2010-12-12 597
115277a3bc0683d Felix Fietkau 2010-12-12 598 if (i == 0) {
115277a3bc0683d Felix Fietkau 2010-12-12 599 if (AR_SREV_9280_20_OR_LATER(ah))
115277a3bc0683d Felix Fietkau 2010-12-12 600 ss = (int16_t)(0 - (minPwrT4[i] / 2));
115277a3bc0683d Felix Fietkau 2010-12-12 601 else
115277a3bc0683d Felix Fietkau 2010-12-12 602 ss = 0;
115277a3bc0683d Felix Fietkau 2010-12-12 603 } else {
115277a3bc0683d Felix Fietkau 2010-12-12 604 ss = (int16_t)((pPdGainBoundaries[i - 1] -
115277a3bc0683d Felix Fietkau 2010-12-12 605 (minPwrT4[i] / 2)) -
115277a3bc0683d Felix Fietkau 2010-12-12 606 tPdGainOverlap + 1 + minDelta);
115277a3bc0683d Felix Fietkau 2010-12-12 607 }
115277a3bc0683d Felix Fietkau 2010-12-12 608 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
115277a3bc0683d Felix Fietkau 2010-12-12 609 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
115277a3bc0683d Felix Fietkau 2010-12-12 610
115277a3bc0683d Felix Fietkau 2010-12-12 611 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
115277a3bc0683d Felix Fietkau 2010-12-12 612 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
115277a3bc0683d Felix Fietkau 2010-12-12 613 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
115277a3bc0683d Felix Fietkau 2010-12-12 614 ss++;
115277a3bc0683d Felix Fietkau 2010-12-12 615 }
115277a3bc0683d Felix Fietkau 2010-12-12 616
115277a3bc0683d Felix Fietkau 2010-12-12 617 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
115277a3bc0683d Felix Fietkau 2010-12-12 618 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
115277a3bc0683d Felix Fietkau 2010-12-12 619 (minPwrT4[i] / 2));
115277a3bc0683d Felix Fietkau 2010-12-12 620 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
115277a3bc0683d Felix Fietkau 2010-12-12 621 tgtIndex : sizeCurrVpdTable;
115277a3bc0683d Felix Fietkau 2010-12-12 622
115277a3bc0683d Felix Fietkau 2010-12-12 623 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
115277a3bc0683d Felix Fietkau 2010-12-12 624 pPDADCValues[k++] = vpdTableI[i][ss++];
115277a3bc0683d Felix Fietkau 2010-12-12 625 }
115277a3bc0683d Felix Fietkau 2010-12-12 626
115277a3bc0683d Felix Fietkau 2010-12-12 627 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
115277a3bc0683d Felix Fietkau 2010-12-12 628 vpdTableI[i][sizeCurrVpdTable - 2]);
115277a3bc0683d Felix Fietkau 2010-12-12 629 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
115277a3bc0683d Felix Fietkau 2010-12-12 630
115277a3bc0683d Felix Fietkau 2010-12-12 631 if (tgtIndex >= maxIndex) {
115277a3bc0683d Felix Fietkau 2010-12-12 632 while ((ss <= tgtIndex) &&
115277a3bc0683d Felix Fietkau 2010-12-12 633 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
115277a3bc0683d Felix Fietkau 2010-12-12 634 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
115277a3bc0683d Felix Fietkau 2010-12-12 635 (ss - maxIndex + 1) * vpdStep));
115277a3bc0683d Felix Fietkau 2010-12-12 636 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
115277a3bc0683d Felix Fietkau 2010-12-12 637 255 : tmpVal);
115277a3bc0683d Felix Fietkau 2010-12-12 638 ss++;
115277a3bc0683d Felix Fietkau 2010-12-12 639 }
115277a3bc0683d Felix Fietkau 2010-12-12 640 }
115277a3bc0683d Felix Fietkau 2010-12-12 641 }
115277a3bc0683d Felix Fietkau 2010-12-12 642
115277a3bc0683d Felix Fietkau 2010-12-12 643 if (eeprom_4k)
115277a3bc0683d Felix Fietkau 2010-12-12 644 pdgain_boundary_default = 58;
115277a3bc0683d Felix Fietkau 2010-12-12 645 else
115277a3bc0683d Felix Fietkau 2010-12-12 646 pdgain_boundary_default = pPdGainBoundaries[i - 1];
115277a3bc0683d Felix Fietkau 2010-12-12 647
115277a3bc0683d Felix Fietkau 2010-12-12 648 while (i < AR5416_PD_GAINS_IN_MASK) {
115277a3bc0683d Felix Fietkau 2010-12-12 649 pPdGainBoundaries[i] = pdgain_boundary_default;
115277a3bc0683d Felix Fietkau 2010-12-12 650 i++;
115277a3bc0683d Felix Fietkau 2010-12-12 651 }
115277a3bc0683d Felix Fietkau 2010-12-12 652
115277a3bc0683d Felix Fietkau 2010-12-12 653 while (k < AR5416_NUM_PDADC_VALUES) {
115277a3bc0683d Felix Fietkau 2010-12-12 654 pPDADCValues[k] = pPDADCValues[k - 1];
115277a3bc0683d Felix Fietkau 2010-12-12 655 k++;
115277a3bc0683d Felix Fietkau 2010-12-12 656 }
115277a3bc0683d Felix Fietkau 2010-12-12 @657 }
115277a3bc0683d Felix Fietkau 2010-12-12 658
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply
* Re: [PATCH ath-next v2] wifi: ath12k: avoid setting 320MHZ support on non 6GHz band
From: Rameshkumar Sundaram @ 2026-06-17 5:03 UTC (permalink / raw)
To: Nicolas Escande, ath12k; +Cc: linux-wireless
In-Reply-To: <20260611084422.1511513-1-nico.escande@gmail.com>
On 6/11/2026 2:14 PM, Nicolas Escande wrote:
> On a split phy qcn9274 (2.4GHz + 5GHz low), "iw phy" reports 320MHz
> realated features on the 5GHz band while it should not:
s/realated/related
>
> Wiphy phy1
> [...]
> Band 2:
> [...]
> EHT Iftypes: managed
> [...]
> EHT PHY Capabilities: (0xe2ffdbe018778000):
> 320MHz in 6GHz Supported
> [...]
> Beamformee SS (320MHz): 7
> [...]
> Number Of Sounding Dimensions (320MHz): 3
> [...]
> EHT MCS/NSS: (0x22222222222222222200000000):
>
> This is also reflected in the beacons sent by a mesh interface started on
> that band. They erroneously advertise 320MHZ support too.
s/320MHZ/320MHz
>
> This should not happen as the spec at section 9.4.2.323.3 says we should
Reword the spec citation to: IEEE Std 802.11-2024, subclause 9.4.2.323.3 ...
> not set the 320MHz related fields when not operating on a 6GHz band.
> For example it says about Bit 0 "Support For 320 MHz In 6 GHz"
>
> "Reserved if the EHT Capabilities element is indicating capabilities for
> the 2.4 GHz or 5 GHz bands."
>
> Fix this by clearing the related bits when converting from WMI eht phy
> capabilities to mac80211 phy capabilities, for bands other than 6GHz.
>
> Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00218-QCAHKSWPL_SILICONZ-1
>
The commit log mentions wrong `iw phy` output and wrong mesh beacon
advertisement, so this appears user visible. If that is the intended bug
being fixed, please add a Fixes tag.
> Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
> ---
> Changes from v1:
> - rebased on ath-next
> - clear all 6GHz / 320MHz related phy capabilities fields from the firmware
> ---
> drivers/net/wireless/ath/ath12k/wmi.c | 17 ++++++++++++++++-
> 1 file changed, 16 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
> index 84a31b953db8..a8a4654c4f34 100644
> --- a/drivers/net/wireless/ath/ath12k/wmi.c
> +++ b/drivers/net/wireless/ath/ath12k/wmi.c
> @@ -5154,6 +5154,7 @@ static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,
> __le32 cap_info_internal)
> {
> struct ath12k_band_cap *cap_band = &pdev->cap.band[band];
> + u8 *phy_cap = (u8 *)&cap_band->eht_cap_phy_info[0];
> u32 support_320mhz;
> u8 i;
>
> @@ -5167,8 +5168,22 @@ static void ath12k_wmi_eht_caps_parse(struct ath12k_pdev *pdev, u32 band,
> for (i = 0; i < WMI_MAX_EHTCAP_PHY_SIZE; i++)
> cap_band->eht_cap_phy_info[i] = le32_to_cpu(cap_phy_info[i]);
>
> - if (band == NL80211_BAND_6GHZ)
> + if (band == NL80211_BAND_6GHZ) {
> cap_band->eht_cap_phy_info[0] |= support_320mhz;
> + } else {
> + /*
> + * It seems the firmware can report capabilities specific to
> + * 6GHz also for 5GHz, so lets explicitely clear them out.
The code comment should be less tentative, how about:
/*
* Firmware may report 6 GHz/320 MHz specific capabilities for
* non-6 GHz bands, so explicitly clear them.
*/
> + */
> + phy_cap[0] &= ~IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
> + phy_cap[1] &= ~IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK;
> + phy_cap[2] &= ~IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK;
> + phy_cap[3] &= ~IEEE80211_EHT_PHY_CAP3_SOUNDING_DIM_320MHZ_MASK;
> + phy_cap[6] &= ~IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_320MHZ;
> + phy_cap[6] &= ~IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP;
> + phy_cap[7] &= ~IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ;
> + phy_cap[7] &= ~IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; ;
> + }
>
> cap_band->eht_mcs_20_only = le32_to_cpu(supp_mcs[0]);
> cap_band->eht_mcs_80 = le32_to_cpu(supp_mcs[1]);
checkpatch warnings:
ERROR: trailing whitespace
#61: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5171:
+^Iif (band == NL80211_BAND_6GHZ) {^I$
WARNING: 'explicitely' may be misspelled - perhaps 'explicitly'?
#66: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5176:
+ * 6GHz also for 5GHz, so lets explicitely clear them out.
^^^^^^^^^^^
WARNING: space prohibited before semicolon
#75: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5185:
+ phy_cap[7] &=
~IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; ;
WARNING: Statements terminations use 1 semicolon
#75: FILE: drivers/net/wireless/ath/ath12k/wmi.c:5185:
+ phy_cap[7] &=
~IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ; ;
^ permalink raw reply
* Re: [PATCH ath-next] wifi: ath12k: expand UserPD ID mask to support up to 8 PDs
From: Rameshkumar Sundaram @ 2026-06-17 4:07 UTC (permalink / raw)
To: Aaradhana Sahu, ath12k; +Cc: linux-wireless
In-Reply-To: <20260604031551.4178754-1-aaradhana.sahu@oss.qualcomm.com>
On 6/4/2026 8:45 AM, Aaradhana Sahu wrote:
> Currently ATH12K_USERPD_ID_MASK uses GENMASK(9, 8), which defines a
> 2-bit field and limits supported UserPD IDs to values 0-3.
>
> Future IPQ5332 multi-PD platform variants support more than three
> UserPDs. Expand ATH12K_USERPD_ID_MASK to GENMASK(10, 8), increasing
> the field width to 3 bits and allowing UserPD IDs from 0-7.
>
> ATH12K_USERPD_ID_MASK is currently used only while constructing the
> ath12k AHB PAS ID, so this change does not affect existing platforms.
>
> Also remove the unused ATH12K_MAX_UPDS definition.
>
> Tested-on: IPQ5332 hw1.0 AHB WLAN.WBE.1.6-01275-QCAHKSWPL_SILICONZ-1
>
> Signed-off-by: Aaradhana Sahu <aaradhana.sahu@oss.qualcomm.com>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox