diff mbox

pcie: Ensure hotplug ports have a minimum number of resources.

Message ID m1hbvftjd9.fsf@fess.ebiederm.org (mailing list archive)
State Accepted, archived
Headers show

Commit Message

Eric W. Biederman Sept. 7, 2009, 5:27 a.m. UTC
In general a BIOS may goof or we may hotplug in a hotplug controller.
In either case the kernel needs to reserve resources for plugging
in more devices in the future instead of creating a minimal resource
assignment.

We already do this for cardbus bridges I am just adding a variant
for pcie bridges.

Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
---
 drivers/pci/pci.c       |   10 ++++++++++
 drivers/pci/setup-bus.c |   43 ++++++++++++++++++++++++++++++++++++++-----
 include/linux/pci.h     |    3 +++
 3 files changed, 51 insertions(+), 5 deletions(-)

Comments

Rolf Eike Beer Sept. 7, 2009, 6:23 a.m. UTC | #1
Eric W. Biederman wrote:
> In general a BIOS may goof or we may hotplug in a hotplug controller.
> In either case the kernel needs to reserve resources for plugging
> in more devices in the future instead of creating a minimal resource
> assignment.
> 
> We already do this for cardbus bridges I am just adding a variant
> for pcie bridges.

> +static int is_pci_hotplug_bridge(struct pci_bus *bus)
> +{
> +	struct pci_dev *bridge = bus->self;
> +	int pos;
> +
> +	/* Test for a generic pci hotplug bridge */
> +	pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
> +	if (pos) {
> +		u32 reg32;
> +		u16 reg16;
> +		pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &reg16);
> +		if (reg16 & PCI_EXP_FLAGS_SLOT) {
> +			pci_read_config_dword(bridge,
> +				pos + PCI_EXP_SLTCAP, &reg32);
> +			if (reg32 & PCI_EXP_SLTCAP_HPC)
> +				return 1;
> +		}
> +	}
> +	return 0;
> +}

Can that return "bool"?

Eike
Kenji Kaneshige Sept. 7, 2009, 7:16 a.m. UTC | #2
Eric W. Biederman wrote:
> In general a BIOS may goof or we may hotplug in a hotplug controller.
> In either case the kernel needs to reserve resources for plugging
> in more devices in the future instead of creating a minimal resource
> assignment.
> 

I think we would need the same mechanism also for PCI bus number
assignment so that we can hot-plug devices containing bridges on
the leaf hot-plug slots.

(snip.)

>  /**
>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>   * @bus: pointer to PCI bus structure to search
> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>  							strlen(str + 19));
>  			} else if (!strncmp(str, "ecrc=", 5)) {
>  				pcie_ecrc_get_policy(str + 5);
> +			} else if (!strncmp(str, "hpiosize=", 9)) {
> +				pci_hotplug_io_size = memparse(str + 9, &str);
> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>  			} else {
>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>  						str);

I think it would be better if we can specify the size per hotplug
controller driver or per slot or etc.

(snip.)

> +static int is_pci_hotplug_bridge(struct pci_bus *bus)
> +{
> +	struct pci_dev *bridge = bus->self;
> +	int pos;
> +
> +	/* Test for a generic pci hotplug bridge */
> +	pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
> +	if (pos) {
> +		u32 reg32;
> +		u16 reg16;
> +		pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &reg16);
> +		if (reg16 & PCI_EXP_FLAGS_SLOT) {
> +			pci_read_config_dword(bridge,
> +				pos + PCI_EXP_SLTCAP, &reg32);
> +			if (reg32 & PCI_EXP_SLTCAP_HPC)
> +				return 1;
> +		}
> +	}
> +	return 0;
> +}
> +

I think it would be better if we can move this kind of hot-plug
controller specific code into each hotplug driver code.

Thanks,
Kenji Kaneshige



--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric W. Biederman Sept. 7, 2009, 9:13 a.m. UTC | #3
Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:

> Eric W. Biederman wrote:
>> In general a BIOS may goof or we may hotplug in a hotplug controller.
>> In either case the kernel needs to reserve resources for plugging
>> in more devices in the future instead of creating a minimal resource
>> assignment.
>>
>
> I think we would need the same mechanism also for PCI bus number
> assignment so that we can hot-plug devices containing bridges on
> the leaf hot-plug slots.

Yep that would be handy.  I haven't had that case come up as a problem
yet.

> (snip.)
>
>>  /**
>>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>>   * @bus: pointer to PCI bus structure to search
>> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>>  							strlen(str + 19));
>>  			} else if (!strncmp(str, "ecrc=", 5)) {
>>  				pcie_ecrc_get_policy(str + 5);
>> +			} else if (!strncmp(str, "hpiosize=", 9)) {
>> +				pci_hotplug_io_size = memparse(str + 9, &str);
>> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
>> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>>  			} else {
>>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>>  						str);
>
> I think it would be better if we can specify the size per hotplug
> controller driver or per slot or etc.

This happens too early to do anything per driver as this all happens
before the hotplug drivers load.  A per slot override seems reasonable
but I am starting with the simplest case an override of the default
allocation.

> (snip.)
>
>> +static int is_pci_hotplug_bridge(struct pci_bus *bus)
>> +{
>> +	struct pci_dev *bridge = bus->self;
>> +	int pos;
>> +
>> +	/* Test for a generic pci hotplug bridge */
>> +	pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
>> +	if (pos) {
>> +		u32 reg32;
>> +		u16 reg16;
>> +		pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &reg16);
>> +		if (reg16 & PCI_EXP_FLAGS_SLOT) {
>> +			pci_read_config_dword(bridge,
>> +				pos + PCI_EXP_SLTCAP, &reg32);
>> +			if (reg32 & PCI_EXP_SLTCAP_HPC)
>> +				return 1;
>> +		}
>> +	}
>> +	return 0;
>> +}
>> +
>
> I think it would be better if we can move this kind of hot-plug
> controller specific code into each hotplug driver code.

This happens too early to move it into drivers.  At best we can do is
add a flag hotplug_bridge :1 to pci_dev and add quirks to set it.

Eric
--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kenji Kaneshige Sept. 8, 2009, 1:06 a.m. UTC | #4
Eric W. Biederman wrote:
> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
> 
>> Eric W. Biederman wrote:
>>> In general a BIOS may goof or we may hotplug in a hotplug controller.
>>> In either case the kernel needs to reserve resources for plugging
>>> in more devices in the future instead of creating a minimal resource
>>> assignment.
>>>
>> I think we would need the same mechanism also for PCI bus number
>> assignment so that we can hot-plug devices containing bridges on
>> the leaf hot-plug slots.
> 
> Yep that would be handy.  I haven't had that case come up as a problem
> yet.
> 
>> (snip.)
>>
>>>  /**
>>>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>>>   * @bus: pointer to PCI bus structure to search
>>> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>>>  							strlen(str + 19));
>>>  			} else if (!strncmp(str, "ecrc=", 5)) {
>>>  				pcie_ecrc_get_policy(str + 5);
>>> +			} else if (!strncmp(str, "hpiosize=", 9)) {
>>> +				pci_hotplug_io_size = memparse(str + 9, &str);
>>> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
>>> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>>>  			} else {
>>>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>>>  						str);
>> I think it would be better if we can specify the size per hotplug
>> controller driver or per slot or etc.
> 
> This happens too early to do anything per driver as this all happens
> before the hotplug drivers load.  A per slot override seems reasonable
> but I am starting with the simplest case an override of the default
> allocation.

Do you need to override the resource assignments by firmware
at boot time?

Thanks,
Kenji Kaneshige


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric W. Biederman Sept. 8, 2009, 11:59 a.m. UTC | #5
Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:

> Eric W. Biederman wrote:
>> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
>>
>>> Eric W. Biederman wrote:
>>>> In general a BIOS may goof or we may hotplug in a hotplug controller.
>>>> In either case the kernel needs to reserve resources for plugging
>>>> in more devices in the future instead of creating a minimal resource
>>>> assignment.
>>>>
>>> I think we would need the same mechanism also for PCI bus number
>>> assignment so that we can hot-plug devices containing bridges on
>>> the leaf hot-plug slots.
>>
>> Yep that would be handy.  I haven't had that case come up as a problem
>> yet.
>>
>>> (snip.)
>>>
>>>>  /**
>>>>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>>>>   * @bus: pointer to PCI bus structure to search
>>>> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>>>>  							strlen(str + 19));
>>>>  			} else if (!strncmp(str, "ecrc=", 5)) {
>>>>  				pcie_ecrc_get_policy(str + 5);
>>>> +			} else if (!strncmp(str, "hpiosize=", 9)) {
>>>> +				pci_hotplug_io_size = memparse(str + 9, &str);
>>>> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
>>>> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>>>>  			} else {
>>>>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>>>>  						str);
>>> I think it would be better if we can specify the size per hotplug
>>> controller driver or per slot or etc.
>>
>> This happens too early to do anything per driver as this all happens
>> before the hotplug drivers load.  A per slot override seems reasonable
>> but I am starting with the simplest case an override of the default
>> allocation.
>
> Do you need to override the resource assignments by firmware
> at boot time?

That has come up.  Unfortunately the kernel didn't know that hardware
platform well enough to assign the resources correctly.  So I had to
go back in and fix the firmware.

I more commonly plug in pcie hotplug bridges into my pcie hotplug
bridges, and long before I can load a driver on them I need to assign
resources.

Eric

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kenji Kaneshige Sept. 9, 2009, 2:38 a.m. UTC | #6
Eric W. Biederman wrote:
> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
> 
>> Eric W. Biederman wrote:
>>> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
>>>
>>>> Eric W. Biederman wrote:
>>>>> In general a BIOS may goof or we may hotplug in a hotplug controller.
>>>>> In either case the kernel needs to reserve resources for plugging
>>>>> in more devices in the future instead of creating a minimal resource
>>>>> assignment.
>>>>>
>>>> I think we would need the same mechanism also for PCI bus number
>>>> assignment so that we can hot-plug devices containing bridges on
>>>> the leaf hot-plug slots.
>>> Yep that would be handy.  I haven't had that case come up as a problem
>>> yet.
>>>
>>>> (snip.)
>>>>
>>>>>  /**
>>>>>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>>>>>   * @bus: pointer to PCI bus structure to search
>>>>> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>>>>>  							strlen(str + 19));
>>>>>  			} else if (!strncmp(str, "ecrc=", 5)) {
>>>>>  				pcie_ecrc_get_policy(str + 5);
>>>>> +			} else if (!strncmp(str, "hpiosize=", 9)) {
>>>>> +				pci_hotplug_io_size = memparse(str + 9, &str);
>>>>> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
>>>>> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>>>>>  			} else {
>>>>>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>>>>>  						str);
>>>> I think it would be better if we can specify the size per hotplug
>>>> controller driver or per slot or etc.
>>> This happens too early to do anything per driver as this all happens
>>> before the hotplug drivers load.  A per slot override seems reasonable
>>> but I am starting with the simplest case an override of the default
>>> allocation.
>> Do you need to override the resource assignments by firmware
>> at boot time?
> 
> That has come up.  Unfortunately the kernel didn't know that hardware
> platform well enough to assign the resources correctly.  So I had to
> go back in and fix the firmware.
> 
> I more commonly plug in pcie hotplug bridges into my pcie hotplug
> bridges, and long before I can load a driver on them I need to assign
> resources.
> 

In addition to your requirement, I noticed another situation that
would require the resource assignment by PCI core. I guess it
would be required for hot-plugging PCI host bridge that contains
some PCIe hotplug slots.

Thanks,
Kenji Kaneshige


--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Eric W. Biederman Sept. 9, 2009, 3:08 a.m. UTC | #7
Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:

> Eric W. Biederman wrote:
>> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
>>
>>> Eric W. Biederman wrote:
>>>> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
>>>>
>>>>> Eric W. Biederman wrote:
>>>>>> In general a BIOS may goof or we may hotplug in a hotplug controller.
>>>>>> In either case the kernel needs to reserve resources for plugging
>>>>>> in more devices in the future instead of creating a minimal resource
>>>>>> assignment.
>>>>>>
>>>>> I think we would need the same mechanism also for PCI bus number
>>>>> assignment so that we can hot-plug devices containing bridges on
>>>>> the leaf hot-plug slots.
>>>> Yep that would be handy.  I haven't had that case come up as a problem
>>>> yet.
>>>>
>>>>> (snip.)
>>>>>
>>>>>>  /**
>>>>>>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>>>>>>   * @bus: pointer to PCI bus structure to search
>>>>>> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>>>>>>  							strlen(str + 19));
>>>>>>  			} else if (!strncmp(str, "ecrc=", 5)) {
>>>>>>  				pcie_ecrc_get_policy(str + 5);
>>>>>> +			} else if (!strncmp(str, "hpiosize=", 9)) {
>>>>>> +				pci_hotplug_io_size = memparse(str + 9, &str);
>>>>>> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
>>>>>> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>>>>>>  			} else {
>>>>>>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>>>>>>  						str);
>>>>> I think it would be better if we can specify the size per hotplug
>>>>> controller driver or per slot or etc.
>>>> This happens too early to do anything per driver as this all happens
>>>> before the hotplug drivers load.  A per slot override seems reasonable
>>>> but I am starting with the simplest case an override of the default
>>>> allocation.
>>> Do you need to override the resource assignments by firmware
>>> at boot time?
>>
>> That has come up.  Unfortunately the kernel didn't know that hardware
>> platform well enough to assign the resources correctly.  So I had to
>> go back in and fix the firmware.
>>
>> I more commonly plug in pcie hotplug bridges into my pcie hotplug
>> bridges, and long before I can load a driver on them I need to assign
>> resources.
>>
>
> In addition to your requirement, I noticed another situation that
> would require the resource assignment by PCI core. I guess it
> would be required for hot-plugging PCI host bridge that contains
> some PCIe hotplug slots.

I don't quite see how that is different from my version of plugging
in pcie hotplug slots, but that certainly sounds correct.  This is
also how the linux hotplug code has worked for a long time it is just
that no one has generalized this code beyond cardbus bridges before.

So we are in agreement that this is useful functionality?

Eric

--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kenji Kaneshige Sept. 9, 2009, 3:47 a.m. UTC | #8
Eric W. Biederman wrote:
> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
> 
>> Eric W. Biederman wrote:
>>> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
>>>
>>>> Eric W. Biederman wrote:
>>>>> Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> writes:
>>>>>
>>>>>> Eric W. Biederman wrote:
>>>>>>> In general a BIOS may goof or we may hotplug in a hotplug controller.
>>>>>>> In either case the kernel needs to reserve resources for plugging
>>>>>>> in more devices in the future instead of creating a minimal resource
>>>>>>> assignment.
>>>>>>>
>>>>>> I think we would need the same mechanism also for PCI bus number
>>>>>> assignment so that we can hot-plug devices containing bridges on
>>>>>> the leaf hot-plug slots.
>>>>> Yep that would be handy.  I haven't had that case come up as a problem
>>>>> yet.
>>>>>
>>>>>> (snip.)
>>>>>>
>>>>>>>  /**
>>>>>>>   * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
>>>>>>>   * @bus: pointer to PCI bus structure to search
>>>>>>> @@ -2672,6 +2678,10 @@ static int __init pci_setup(char *str)
>>>>>>>  							strlen(str + 19));
>>>>>>>  			} else if (!strncmp(str, "ecrc=", 5)) {
>>>>>>>  				pcie_ecrc_get_policy(str + 5);
>>>>>>> +			} else if (!strncmp(str, "hpiosize=", 9)) {
>>>>>>> +				pci_hotplug_io_size = memparse(str + 9, &str);
>>>>>>> +			} else if (!strncmp(str, "hpmemsize=", 10)) {
>>>>>>> +				pci_hotplug_mem_size = memparse(str + 10, &str);
>>>>>>>  			} else {
>>>>>>>  				printk(KERN_ERR "PCI: Unknown option `%s'\n",
>>>>>>>  						str);
>>>>>> I think it would be better if we can specify the size per hotplug
>>>>>> controller driver or per slot or etc.
>>>>> This happens too early to do anything per driver as this all happens
>>>>> before the hotplug drivers load.  A per slot override seems reasonable
>>>>> but I am starting with the simplest case an override of the default
>>>>> allocation.
>>>> Do you need to override the resource assignments by firmware
>>>> at boot time?
>>> That has come up.  Unfortunately the kernel didn't know that hardware
>>> platform well enough to assign the resources correctly.  So I had to
>>> go back in and fix the firmware.
>>>
>>> I more commonly plug in pcie hotplug bridges into my pcie hotplug
>>> bridges, and long before I can load a driver on them I need to assign
>>> resources.
>>>
>> In addition to your requirement, I noticed another situation that
>> would require the resource assignment by PCI core. I guess it
>> would be required for hot-plugging PCI host bridge that contains
>> some PCIe hotplug slots.
> 
> I don't quite see how that is different from my version of plugging
> in pcie hotplug slots, but that certainly sounds correct.  This is
> also how the linux hotplug code has worked for a long time it is just
> that no one has generalized this code beyond cardbus bridges before.
> 
> So we are in agreement that this is useful functionality?

Yes (though I don't have platforms that need it).

Thanks,
Kenji Kaneshige



--
To unsubscribe from this list: send the line "unsubscribe linux-pci" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 7b70312..36efcf3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -41,6 +41,12 @@  int pci_domains_supported = 1;
 unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE;
 unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
 
+#define DEFAULT_HOTPLUG_IO_SIZE		(256)
+#define DEFAULT_HOTPLUG_MEM_SIZE	(2*1024*1024)
+/* pci=hpmemsize=nnM,hpiosize=nn can override this */
+unsigned long pci_hotplug_io_size  = DEFAULT_HOTPLUG_IO_SIZE;
+unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
+
 /**
  * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
  * @bus: pointer to PCI bus structure to search
@@ -2672,6 +2678,10 @@  static int __init pci_setup(char *str)
 							strlen(str + 19));
 			} else if (!strncmp(str, "ecrc=", 5)) {
 				pcie_ecrc_get_policy(str + 5);
+			} else if (!strncmp(str, "hpiosize=", 9)) {
+				pci_hotplug_io_size = memparse(str + 9, &str);
+			} else if (!strncmp(str, "hpmemsize=", 10)) {
+				pci_hotplug_mem_size = memparse(str + 10, &str);
 			} else {
 				printk(KERN_ERR "PCI: Unknown option `%s'\n",
 						str);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index b636e24..5ab90ec 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -309,7 +309,7 @@  static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
    since these windows have 4K granularity and the IO ranges
    of non-bridge PCI devices are limited to 256 bytes.
    We must be careful with the ISA aliasing though. */
-static void pbus_size_io(struct pci_bus *bus)
+static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
 {
 	struct pci_dev *dev;
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
@@ -336,6 +336,8 @@  static void pbus_size_io(struct pci_bus *bus)
 				size1 += r_size;
 		}
 	}
+	if (size < min_size)
+		size = min_size;
 /* To be fixed in 2.5: we should have sort of HAVE_ISA
    flag in the struct pci_bus. */
 #if defined(CONFIG_ISA) || defined(CONFIG_EISA)
@@ -354,7 +356,8 @@  static void pbus_size_io(struct pci_bus *bus)
 
 /* Calculate the size of the bus and minimal alignment which
    guarantees that all child resources fit in this size. */
-static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
+static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
+			 unsigned long type, resource_size_t min_size)
 {
 	struct pci_dev *dev;
 	resource_size_t min_align, align, size;
@@ -404,6 +407,8 @@  static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
 			mem64_mask &= r->flags & IORESOURCE_MEM_64;
 		}
 	}
+	if (size < min_size)
+		size = min_size;
 
 	align = 0;
 	min_align = 0;
@@ -479,10 +484,32 @@  static void pci_bus_size_cardbus(struct pci_bus *bus)
 	}
 }
 
+static int is_pci_hotplug_bridge(struct pci_bus *bus)
+{
+	struct pci_dev *bridge = bus->self;
+	int pos;
+
+	/* Test for a generic pci hotplug bridge */
+	pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+	if (pos) {
+		u32 reg32;
+		u16 reg16;
+		pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &reg16);
+		if (reg16 & PCI_EXP_FLAGS_SLOT) {
+			pci_read_config_dword(bridge,
+				pos + PCI_EXP_SLTCAP, &reg32);
+			if (reg32 & PCI_EXP_SLTCAP_HPC)
+				return 1;
+		}
+	}
+	return 0;
+}
+
 void __ref pci_bus_size_bridges(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	unsigned long mask, prefmask;
+	resource_size_t min_mem_size = 0, min_io_size = 0;
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		struct pci_bus *b = dev->subordinate;
@@ -512,8 +539,12 @@  void __ref pci_bus_size_bridges(struct pci_bus *bus)
 
 	case PCI_CLASS_BRIDGE_PCI:
 		pci_bridge_check_ranges(bus);
+		if (is_pci_hotplug_bridge(bus)) {
+			min_io_size  = pci_hotplug_io_size;
+			min_mem_size = pci_hotplug_mem_size;
+		}
 	default:
-		pbus_size_io(bus);
+		pbus_size_io(bus, min_io_size);
 		/* If the bridge supports prefetchable range, size it
 		   separately. If it doesn't, or its prefetchable window
 		   has already been allocated by arch code, try
@@ -521,9 +552,11 @@  void __ref pci_bus_size_bridges(struct pci_bus *bus)
 		   resources. */
 		mask = IORESOURCE_MEM;
 		prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-		if (pbus_size_mem(bus, prefmask, prefmask))
+		if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size))
 			mask = prefmask; /* Success, size non-prefetch only. */
-		pbus_size_mem(bus, mask, IORESOURCE_MEM);
+		else
+			min_mem_size += min_mem_size;
+		pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size);
 		break;
 	}
 }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 115fb7b..d6e57b0 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1236,6 +1236,9 @@  extern int pci_pci_problems;
 extern unsigned long pci_cardbus_io_size;
 extern unsigned long pci_cardbus_mem_size;
 
+extern unsigned long pci_hotplug_io_size;
+extern unsigned long pci_hotplug_mem_size;
+
 int pcibios_add_platform_entries(struct pci_dev *dev);
 void pcibios_disable_device(struct pci_dev *dev);
 int pcibios_set_pcie_reset_state(struct pci_dev *dev,