mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-10 07:34:40 +01:00
Compare commits
2 commits
b91ebdabbb
...
721f808253
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
721f808253 | ||
|
|
1c02c78e7c |
3 changed files with 70 additions and 81 deletions
|
|
@ -0,0 +1,69 @@
|
|||
From 88f17c87ddc9ee7467acdc322d383e5a443a55ab Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Mon, 8 Dec 2025 20:50:47 +0100
|
||||
Subject: [PATCH 1/2] wifi: ath11k: fix wrong usage of resource_size() causing
|
||||
firmware panic
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On converting to the of_reserved_mem_region_to_resource() helper with
|
||||
commit 900730dc4705 ("wifi: ath: Use
|
||||
of_reserved_mem_region_to_resource() for "memory-region"") a logic error
|
||||
was introduced in the ath11k_core_coldboot_cal_support() if condition.
|
||||
|
||||
The original code checked for hremote_node presence and skipped
|
||||
ath11k_core_coldboot_cal_support() in the other switch case but now
|
||||
everything is driven entirely on the values of the resource struct.
|
||||
|
||||
resource_size() (in this case) is wrongly assumed to return a size of
|
||||
zero if the passed resource struct is init to zero. This is not the case
|
||||
as a resource struct should be always init with correct values (or at
|
||||
best set the end value to -1 to signal it's not configured)
|
||||
(the return value of resource_size() for a resource struct with start
|
||||
and end set to zero is 1)
|
||||
|
||||
On top of this, using resource_size() to check if a resource struct is
|
||||
initialized or not is generally wrong and other measure should be used
|
||||
instead.
|
||||
|
||||
To better handle this, use the DEFINE_RES macro to initialize the
|
||||
resource struct and set the IORESOURCE_UNSET flag by default.
|
||||
|
||||
Replace the resource_size() check with checking for the resource struct
|
||||
flags and check if it's IORESOURCE_UNSET.
|
||||
|
||||
This change effectively restore the original logic and restore correct
|
||||
loading of the ath11k firmware (restoring correct functionality of
|
||||
Wi-Fi)
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 900730dc4705 ("wifi: ath: Use of_reserved_mem_region_to_resource() for "memory-region"")
|
||||
Link: https://lore.kernel.org/all/20251207215359.28895-1-ansuelsmth@gmail.com/T/#m990492684913c5a158ff0e5fc90697d8ad95351b
|
||||
Cc: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
drivers/net/wireless/ath/ath11k/qmi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
||||
@@ -2039,8 +2039,8 @@ static int ath11k_qmi_alloc_target_mem_c
|
||||
|
||||
static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
|
||||
{
|
||||
+ struct resource res = DEFINE_RES_NAMED(0, 0, NULL, IORESOURCE_UNSET);
|
||||
struct device *dev = ab->dev;
|
||||
- struct resource res = {};
|
||||
u32 host_ddr_sz;
|
||||
int i, idx, ret;
|
||||
|
||||
@@ -2086,7 +2086,7 @@ static int ath11k_qmi_assign_target_mem_
|
||||
}
|
||||
|
||||
if (ath11k_core_coldboot_cal_support(ab)) {
|
||||
- if (resource_size(&res)) {
|
||||
+ if (res.flags != IORESOURCE_UNSET) {
|
||||
ab->qmi.target_mem[idx].paddr =
|
||||
res.start + host_ddr_sz;
|
||||
ab->qmi.target_mem[idx].iaddr =
|
||||
|
|
@ -11,8 +11,8 @@ Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
|
|||
--- a/drivers/net/wireless/ath/ath11k/qmi.c
|
||||
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
|
||||
@@ -2042,6 +2042,7 @@ static int ath11k_qmi_assign_target_mem_
|
||||
struct resource res = DEFINE_RES_NAMED(0, 0, NULL, IORESOURCE_UNSET);
|
||||
struct device *dev = ab->dev;
|
||||
struct resource res = {};
|
||||
u32 host_ddr_sz;
|
||||
+ u32 addr;
|
||||
int i, idx, ret;
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
From 7e1241396c241f9b4fff2ff133806fef4ddd9ecc Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sun, 7 Dec 2025 22:18:11 +0100
|
||||
Subject: [PATCH] resource: handle wrong resource_size value on zero start/end
|
||||
resource
|
||||
|
||||
Commit 900730dc4705 ("wifi: ath: Use
|
||||
of_reserved_mem_region_to_resource() for "memory-region"") uncovered a
|
||||
massive problem with the usage of resource_size() helper.
|
||||
|
||||
The reported commit caused a regression with ath11k WiFi firmware
|
||||
loading and the change was just a simple replacement of duplicate code
|
||||
with a new helper of_reserved_mem_region_to_resource().
|
||||
|
||||
On reworking this, in the commit also a check for the presence of the
|
||||
node was replaced with resource_size(&res). This was done following the
|
||||
logic that if the node wasn't present then it's expected that also the
|
||||
resource_size is zero, mimicking the same if-else logic.
|
||||
|
||||
This was also the reason the regression was mostly hard to catch at
|
||||
first sight as the rework is correctly done given the assumption on the
|
||||
used helpers.
|
||||
|
||||
BUT this is actually not the case. On further inspection on
|
||||
resource_size() it was found that it NEVER actually returns 0.
|
||||
|
||||
Even if the resource value of start and end are 0, the return value of
|
||||
resource_size() will ALWAYS be 1, resulting in the broken if-else
|
||||
condition ALWAYS going in the first if condition.
|
||||
|
||||
This was simply confirmed by reading the resource_size() logic:
|
||||
|
||||
return res->end - res->start + 1;
|
||||
|
||||
Given the confusion, also other case of such usage were searched in the
|
||||
kernel and with great suprise it seems LOTS of place assume
|
||||
resource_size() should return zero in the context of the resource start
|
||||
and end set to 0.
|
||||
|
||||
Quoting for example comments in drivers/vfio/pci/vfio_pci_core.c:
|
||||
|
||||
/*
|
||||
* The PCI core shouldn't set up a resource with a
|
||||
* type but zero size. But there may be bugs that
|
||||
* cause us to do that.
|
||||
*/
|
||||
if (!resource_size(res))
|
||||
goto no_mmap;
|
||||
|
||||
It really seems resource_size() was tought with the assumption that
|
||||
resource struct was always correctly initialized before calling it and
|
||||
never set to zero.
|
||||
|
||||
But across the year this got lost and now there are lots of driver that
|
||||
assume resource_size() returns 0 if start and end are also 0.
|
||||
|
||||
To better handle this and make resource_size() returns correct value in
|
||||
such case, add a simple check and return 0 if both resource start and
|
||||
resource end are zero.
|
||||
|
||||
Cc: Rob Herring (Arm) <robh@kernel.org>
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 1a4e564b7db9 ("resource: add resource_size()")
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
---
|
||||
include/linux/ioport.h | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
--- a/include/linux/ioport.h
|
||||
+++ b/include/linux/ioport.h
|
||||
@@ -283,6 +283,9 @@ static inline void resource_set_range(st
|
||||
|
||||
static inline resource_size_t resource_size(const struct resource *res)
|
||||
{
|
||||
+ if (!res->start && !res->end)
|
||||
+ return 0;
|
||||
+
|
||||
return res->end - res->start + 1;
|
||||
}
|
||||
static inline unsigned long resource_type(const struct resource *res)
|
||||
Loading…
Add table
Reference in a new issue