[PATCH 02/10] resource: Pass full extent of empty space to resource_alignf CB

Ilpo Järvinen
2026-03-24T16:59:06Z

__find_resource_space() calculates the full extent of empty space but
only passes the aligned space to resource_alignf callback. In some
situations, the callback may choose take advantage of the free space
before the requested alignment.

Pass the full extent of the calculated empty space to resource_alignf
callback as an additional parameter.

Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
arch/alpha/kernel/pci.c | 1 +
arch/arm/kernel/bios32.c | 4 +++-
arch/m68k/kernel/pcibios.c | 4 +++-
arch/mips/pci/pci-generic.c | 3 ++-
arch/mips/pci/pci-legacy.c | 1 +
arch/parisc/kernel/pci.c | 4 +++-
arch/powerpc/kernel/pci-common.c | 4 +++-
arch/s390/pci/pci.c | 1 +
arch/sh/drivers/pci/pci.c | 4 +++-
arch/x86/pci/i386.c | 3 ++-
arch/xtensa/kernel/pci.c | 1 +
drivers/pci/setup-res.c | 3 ++-
drivers/pcmcia/rsrc_nonstatic.c | 3 ++-
include/linux/ioport.h | 2 ++
include/linux/pci.h | 7 ++++---
kernel/resource.c | 3 ++-
16 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 51a8a4c4572a..11df411b1d18 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -125,6 +125,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);

resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index b5793e8fbdc1..5b9b4fcd0e54 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -560,7 +560,9 @@ char * __init pcibios_setup(char *str)
* which might be mirrored at 0x0100-0x03ff..
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size,
+ resource_size_t align)
{
struct pci_dev *dev = data;
resource_size_t start = res->start;
diff --git a/arch/m68k/kernel/pcibios.c b/arch/m68k/kernel/pcibios.c
index e6ab3f9ff5d8..1415f6e4e5ce 100644
--- a/arch/m68k/kernel/pcibios.c
+++ b/arch/m68k/kernel/pcibios.c
@@ -27,7 +27,9 @@
* which might be mirrored at 0x0100-0x03ff..
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size,
+ resource_size_t align)
{
resource_size_t start = res->start;

diff --git a/arch/mips/pci/pci-generic.c b/arch/mips/pci/pci-generic.c
index d2d68bac3d25..f4957c26efc7 100644
--- a/arch/mips/pci/pci-generic.c
+++ b/arch/mips/pci/pci-generic.c
@@ -22,7 +22,8 @@
* which might have be mirrored at 0x0100-0x03ff..
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
resource_size_t start = res->start;
diff --git a/arch/mips/pci/pci-legacy.c b/arch/mips/pci/pci-legacy.c
index d04b7c1294b6..817e97402afe 100644
--- a/arch/mips/pci/pci-legacy.c
+++ b/arch/mips/pci/pci-legacy.c
@@ -52,6 +52,7 @@ unsigned long pci_address_to_pio(phys_addr_t address)
*/
resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index cf285b17a5ae..f99b20795d5a 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -196,7 +196,9 @@ void __ref pcibios_init_bridge(struct pci_dev *dev)
* than res->start.
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t alignment)
+ const struct resource *empty_res,
+ resource_size_t size,
+ resource_size_t alignment)
{
resource_size_t mask, align, start = res->start;

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index a7a2fb605971..e7bfa15da043 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1132,7 +1132,9 @@ static int skip_isa_ioresource_align(struct pci_dev *dev)
* which might have be mirrored at 0x0100-0x03ff..
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size,
+ resource_size_t align)
{
struct pci_dev *dev = data;
resource_size_t start = res->start;
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 2a430722cbe4..39bd2adfc240 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -266,6 +266,7 @@ static int zpci_cfg_store(struct zpci_dev *zdev, int offset, u32 val, u8 len)
}

resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size,
resource_size_t align)
{
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index a3903304f33f..7a0522316ee3 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -168,7 +168,9 @@ subsys_initcall(pcibios_init);
* modulo 0x400.
*/
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size,
+ resource_size_t align)
{
struct pci_dev *dev = data;
struct pci_channel *hose = dev->sysdata;
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index c4ec39ad276b..6fbd4b34c3f7 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -153,7 +153,8 @@ skip_isa_ioresource_align(struct pci_dev *dev) {
*/
resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
resource_size_t start = res->start;
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
index 62c900e400d6..64ccb7e0d92f 100644
--- a/arch/xtensa/kernel/pci.c
+++ b/arch/xtensa/kernel/pci.c
@@ -39,6 +39,7 @@
*/
resource_size_t
pcibios_align_resource(void *data, const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index bb2aef373d6f..c375e255c509 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -251,10 +251,11 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
*/
resource_size_t __weak pcibios_align_resource(void *data,
const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size,
resource_size_t align)
{
- return res->start;
+ return res->start;
}

static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 0679dd434719..949e69921fe9 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -602,7 +602,8 @@ static resource_size_t pcmcia_common_align(struct pcmcia_align_data *align_data,

static resource_size_t
pcmcia_align(void *align_data, const struct resource *res,
- resource_size_t size, resource_size_t align)
+ const struct resource *empty_res,
+ resource_size_t size, resource_size_t align)
{
struct pcmcia_align_data *data = align_data;
struct resource_map *m;
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 19d5e04564d9..3c73c9c0d4f7 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -202,6 +202,7 @@ enum {
* typedef resource_alignf - Resource alignment callback
* @data: Private data used by the callback
* @res: Resource candidate range (an empty resource space)
+ * @empty_res: Empty resource range without alignment applied
* @size: The minimum size of the empty space
* @align: Alignment from the constraints
*
@@ -212,6 +213,7 @@ enum {
*/
typedef resource_size_t (*resource_alignf)(void *data,
const struct resource *res,
+ const struct resource *empty_res,
resource_size_t size,
resource_size_t align);

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1c270f1d5123..ac332ff9da9f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1206,9 +1206,10 @@ int __must_check pcibios_enable_device(struct pci_dev *, int mask);
char *pcibios_setup(char *str);

/* Used only when drivers/pci/setup.c is used */
-resource_size_t pcibios_align_resource(void *, const struct resource *,
- resource_size_t,
- resource_size_t);
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+ const struct resource *empty_res,
+ resource_size_t size,
+ resource_size_t align);

/* Generic PCI functions used internally */

diff --git a/kernel/resource.c b/kernel/resource.c
index 1e2f1dfc0edd..1b8d3101bdc6 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -759,7 +759,8 @@ static int __find_resource_space(struct resource *root, struct resource *old,
alloc.flags = avail.flags;
if (alignf) {
alloc.start = alignf(constraint->alignf_data,
- &avail, size, constraint->align);
+ &avail, &tmp,
+ size, constraint->align);
} else {
alloc.start = avail.start;
}
--
2.39.5