__pci_read_base() sets resource start and end addresses when resource is larger than 4G but pci_bus_addr_t or resource_size_t are not capable of representing 64-bit PCI addresses. This creates a problematic resource that has non-zero flags but the start and end addresses do not yield to resource size of 0 but 1.
Replace custom resource addresses setup with resource_set_range() that correctly sets end address as -1 which results in resource_size() returning 0.
For consistency, also use resource_set_range() in the other branch that does size based resource setup.
Fixes: 23b13bc76f35 ("PCI: Fail safely if we can't handle BARs larger than 4GB") Link: https://lore.kernel.org/all/20251207215359.28895-1-ansuelsmth@gmail.com/T/#m... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Cc: stable@vger.kernel.org Cc: Christian Marangi ansuelsmth@gmail.com --- drivers/pci/probe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 124d2d309c58..b8294a2f11f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -287,8 +287,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8 || sizeof(resource_size_t) < 8) && sz64 > 0x100000000ULL) { res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; - res->start = 0; - res->end = 0; + resource_set_range(res, 0, 0); pci_err(dev, "%s: can't handle BAR larger than 4GB (size %#010llx)\n", res_name, (unsigned long long)sz64); goto out; @@ -297,8 +296,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8) && l) { /* Above 32-bit boundary; try to reallocate */ res->flags |= IORESOURCE_UNSET; - res->start = 0; - res->end = sz64 - 1; + resource_set_range(res, 0, sz64); pci_info(dev, "%s: can't handle BAR above 4GB (bus address %#010llx)\n", res_name, (unsigned long long)l64); goto out;
base-commit: 43dfc13ca972988e620a6edb72956981b75ab6b0
On Mon, Dec 08, 2025 at 04:56:54PM +0200, Ilpo Järvinen wrote:
__pci_read_base() sets resource start and end addresses when resource is larger than 4G but pci_bus_addr_t or resource_size_t are not capable of representing 64-bit PCI addresses. This creates a problematic resource that has non-zero flags but the start and end addresses do not yield to resource size of 0 but 1.
Replace custom resource addresses setup with resource_set_range() that correctly sets end address as -1 which results in resource_size() returning 0.
For consistency, also use resource_set_range() in the other branch that does size based resource setup.
Since I have been involved in the related discussion and the patch LGTM, Reviewed-by: Andy Shevchenko andriy.shevchenko@intel.com
On Mon, Dec 08, 2025 at 04:56:54PM +0200, Ilpo Järvinen wrote:
__pci_read_base() sets resource start and end addresses when resource is larger than 4G but pci_bus_addr_t or resource_size_t are not capable of representing 64-bit PCI addresses. This creates a problematic resource that has non-zero flags but the start and end addresses do not yield to resource size of 0 but 1.
Replace custom resource addresses setup with resource_set_range() that correctly sets end address as -1 which results in resource_size() returning 0.
For consistency, also use resource_set_range() in the other branch that does size based resource setup.
IIUC this fixes an ath11k regression (and probably others). And typically when booting a 32-bit kernel with a device with a BAR larger than 4GB?
Christian, is there any dmesg snippet we could include here to help users diagnose the problem? I guess the "can't handle BAR larger than 4GB" message is probably one clue.
Are you able to test this and verify that it fixes the regression you saw?
Fixes: 23b13bc76f35 ("PCI: Fail safely if we can't handle BARs larger than 4GB") Link: https://lore.kernel.org/all/20251207215359.28895-1-ansuelsmth@gmail.com/T/#m... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Cc: stable@vger.kernel.org Cc: Christian Marangi ansuelsmth@gmail.com
drivers/pci/probe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 124d2d309c58..b8294a2f11f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -287,8 +287,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8 || sizeof(resource_size_t) < 8) && sz64 > 0x100000000ULL) { res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
res->start = 0;res->end = 0;
resource_set_range(res, 0, 0); pci_err(dev, "%s: can't handle BAR larger than 4GB (size %#010llx)\n", res_name, (unsigned long long)sz64); goto out;@@ -297,8 +296,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8) && l) { /* Above 32-bit boundary; try to reallocate */ res->flags |= IORESOURCE_UNSET;
res->start = 0;res->end = sz64 - 1;
resource_set_range(res, 0, sz64); pci_info(dev, "%s: can't handle BAR above 4GB (bus address %#010llx)\n", res_name, (unsigned long long)l64); goto out;base-commit: 43dfc13ca972988e620a6edb72956981b75ab6b0
2.39.5
On Wed, Dec 10, 2025 at 11:13:19AM -0600, Bjorn Helgaas wrote:
On Mon, Dec 08, 2025 at 04:56:54PM +0200, Ilpo Järvinen wrote:
__pci_read_base() sets resource start and end addresses when resource is larger than 4G but pci_bus_addr_t or resource_size_t are not capable of representing 64-bit PCI addresses. This creates a problematic resource that has non-zero flags but the start and end addresses do not yield to resource size of 0 but 1.
Replace custom resource addresses setup with resource_set_range() that correctly sets end address as -1 which results in resource_size() returning 0.
For consistency, also use resource_set_range() in the other branch that does size based resource setup.
IIUC this fixes an ath11k regression (and probably others). And typically when booting a 32-bit kernel with a device with a BAR larger than 4GB?
Christian, is there any dmesg snippet we could include here to help users diagnose the problem? I guess the "can't handle BAR larger than 4GB" message is probably one clue.
Are you able to test this and verify that it fixes the regression you saw?
No my regression was on a different section and for AHB cards, no PCI. (I sent a fix for my regression on the net mailing list)
Could be hard to find a device with 4+ gb of ram that is not x86 or on an ipq SoC.
Fixes: 23b13bc76f35 ("PCI: Fail safely if we can't handle BARs larger than 4GB") Link: https://lore.kernel.org/all/20251207215359.28895-1-ansuelsmth@gmail.com/T/#m... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Cc: stable@vger.kernel.org Cc: Christian Marangi ansuelsmth@gmail.com
drivers/pci/probe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 124d2d309c58..b8294a2f11f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -287,8 +287,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8 || sizeof(resource_size_t) < 8) && sz64 > 0x100000000ULL) { res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
res->start = 0;res->end = 0;
resource_set_range(res, 0, 0); pci_err(dev, "%s: can't handle BAR larger than 4GB (size %#010llx)\n", res_name, (unsigned long long)sz64); goto out;@@ -297,8 +296,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8) && l) { /* Above 32-bit boundary; try to reallocate */ res->flags |= IORESOURCE_UNSET;
res->start = 0;res->end = sz64 - 1;
resource_set_range(res, 0, sz64); pci_info(dev, "%s: can't handle BAR above 4GB (bus address %#010llx)\n", res_name, (unsigned long long)l64); goto out;base-commit: 43dfc13ca972988e620a6edb72956981b75ab6b0
2.39.5
On Mon, Dec 08, 2025 at 04:56:54PM +0200, Ilpo Järvinen wrote:
__pci_read_base() sets resource start and end addresses when resource is larger than 4G but pci_bus_addr_t or resource_size_t are not capable of representing 64-bit PCI addresses. This creates a problematic resource that has non-zero flags but the start and end addresses do not yield to resource size of 0 but 1.
Replace custom resource addresses setup with resource_set_range() that correctly sets end address as -1 which results in resource_size() returning 0.
For consistency, also use resource_set_range() in the other branch that does size based resource setup.
Fixes: 23b13bc76f35 ("PCI: Fail safely if we can't handle BARs larger than 4GB") Link: https://lore.kernel.org/all/20251207215359.28895-1-ansuelsmth@gmail.com/T/#m... Signed-off-by: Ilpo Järvinen ilpo.jarvinen@linux.intel.com Cc: stable@vger.kernel.org Cc: Christian Marangi ansuelsmth@gmail.com
Applied to pci/resource for v6.20, thanks!
drivers/pci/probe.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 124d2d309c58..b8294a2f11f9 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -287,8 +287,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8 || sizeof(resource_size_t) < 8) && sz64 > 0x100000000ULL) { res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED;
res->start = 0;res->end = 0;
resource_set_range(res, 0, 0); pci_err(dev, "%s: can't handle BAR larger than 4GB (size %#010llx)\n", res_name, (unsigned long long)sz64); goto out;@@ -297,8 +296,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, if ((sizeof(pci_bus_addr_t) < 8) && l) { /* Above 32-bit boundary; try to reallocate */ res->flags |= IORESOURCE_UNSET;
res->start = 0;res->end = sz64 - 1;
resource_set_range(res, 0, sz64); pci_info(dev, "%s: can't handle BAR above 4GB (bus address %#010llx)\n", res_name, (unsigned long long)l64); goto out;base-commit: 43dfc13ca972988e620a6edb72956981b75ab6b0
2.39.5
linux-stable-mirror@lists.linaro.org