提交 c40a22e0 编写于 作者: B Benjamin Herrenschmidt 提交者: Greg Kroah-Hartman

PCI: Fix bus resource assignment on 32 bits with 64b resources

The current pci_assign_unassigned_resources() code doesn't work properly
on 32 bits platforms with 64 bits resources. The main reason is the use
of unsigned long in various places instead of resource_size_t.

This is a pre-requisite for making powerpc use the generic code instead of
its own half-useful implementation.
Signed-off-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
上级 f07234b6
...@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus) ...@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
* The IO resource is allocated a range twice as large as it * The IO resource is allocated a range twice as large as it
* would normally need. This allows us to set both IO regs. * would normally need. This allows us to set both IO regs.
*/ */
printk(" IO window: %08lx-%08lx\n", printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
region.start, region.end); (unsigned long)region.start,
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_0, pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0, pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
...@@ -99,8 +100,9 @@ void pci_setup_cardbus(struct pci_bus *bus) ...@@ -99,8 +100,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[1]); pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
if (bus->resource[1]->flags & IORESOURCE_IO) { if (bus->resource[1]->flags & IORESOURCE_IO) {
printk(" IO window: %08lx-%08lx\n", printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
region.start, region.end); (unsigned long)region.start,
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1, pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
...@@ -109,8 +111,9 @@ void pci_setup_cardbus(struct pci_bus *bus) ...@@ -109,8 +111,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[2]); pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_MEM) { if (bus->resource[2]->flags & IORESOURCE_MEM) {
printk(" PREFETCH window: %08lx-%08lx\n", printk(KERN_INFO " PREFETCH window: 0x%08lx-0x%08lx\n",
region.start, region.end); (unsigned long)region.start,
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0, pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
...@@ -119,8 +122,9 @@ void pci_setup_cardbus(struct pci_bus *bus) ...@@ -119,8 +122,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[3]); pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
if (bus->resource[3]->flags & IORESOURCE_MEM) { if (bus->resource[3]->flags & IORESOURCE_MEM) {
printk(" MEM window: %08lx-%08lx\n", printk(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
region.start, region.end); (unsigned long)region.start,
(unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
region.start); region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1, pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
...@@ -145,7 +149,7 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -145,7 +149,7 @@ pci_setup_bridge(struct pci_bus *bus)
{ {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
struct pci_bus_region region; struct pci_bus_region region;
u32 l, io_upper16; u32 l, bu, lu, io_upper16;
DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge)); DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
...@@ -159,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -159,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus)
/* Set up upper 16 bits of I/O base/limit. */ /* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
DBG(KERN_INFO " IO window: %04lx-%04lx\n", DBG(KERN_INFO " IO window: %04lx-%04lx\n",
region.start, region.end); (unsigned long)region.start,
(unsigned long)region.end);
} }
else { else {
/* Clear upper 16 bits of I/O base/limit. */ /* Clear upper 16 bits of I/O base/limit. */
...@@ -180,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -180,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus)
if (bus->resource[1]->flags & IORESOURCE_MEM) { if (bus->resource[1]->flags & IORESOURCE_MEM) {
l = (region.start >> 16) & 0xfff0; l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000; l |= region.end & 0xfff00000;
DBG(KERN_INFO " MEM window: %08lx-%08lx\n", DBG(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
region.start, region.end); (unsigned long)region.start,
(unsigned long)region.end);
} }
else { else {
l = 0x0000fff0; l = 0x0000fff0;
...@@ -195,12 +201,18 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -195,12 +201,18 @@ pci_setup_bridge(struct pci_bus *bus)
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */ /* Set up PREF base/limit. */
bu = lu = 0;
pcibios_resource_to_bus(bridge, &region, bus->resource[2]); pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
l = (region.start >> 16) & 0xfff0; l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000; l |= region.end & 0xfff00000;
DBG(KERN_INFO " PREFETCH window: %08lx-%08lx\n", #ifdef CONFIG_RESOURCES_64BIT
region.start, region.end); bu = region.start >> 32;
lu = region.end >> 32;
#endif
DBG(KERN_INFO " PREFETCH window: 0x%016llx-0x%016llx\n",
(unsigned long long)region.start,
(unsigned long long)region.end);
} }
else { else {
l = 0x0000fff0; l = 0x0000fff0;
...@@ -208,8 +220,9 @@ pci_setup_bridge(struct pci_bus *bus) ...@@ -208,8 +220,9 @@ pci_setup_bridge(struct pci_bus *bus)
} }
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
/* Clear out the upper 32 bits of PREF base. */ /* Set the upper 32 bits of PREF base & limit. */
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
} }
...@@ -323,8 +336,8 @@ static void pbus_size_io(struct pci_bus *bus) ...@@ -323,8 +336,8 @@ static void pbus_size_io(struct pci_bus *bus)
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)
{ {
struct pci_dev *dev; struct pci_dev *dev;
unsigned long min_align, align, size; resource_size_t min_align, align, size;
unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */ resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
int order, max_order; int order, max_order;
struct resource *b_res = find_free_bus_resource(bus, type); struct resource *b_res = find_free_bus_resource(bus, type);
...@@ -340,7 +353,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long ...@@ -340,7 +353,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
for (i = 0; i < PCI_NUM_RESOURCES; i++) { for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i]; struct resource *r = &dev->resource[i];
unsigned long r_size; resource_size_t r_size;
if (r->parent || (r->flags & mask) != type) if (r->parent || (r->flags & mask) != type)
continue; continue;
...@@ -350,10 +363,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long ...@@ -350,10 +363,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
order = __ffs(align) - 20; order = __ffs(align) - 20;
if (order > 11) { if (order > 11) {
printk(KERN_WARNING "PCI: region %s/%d " printk(KERN_WARNING "PCI: region %s/%d "
"too large: %llx-%llx\n", "too large: 0x%016llx-0x%016llx\n",
pci_name(dev), i, pci_name(dev), i,
(unsigned long long)r->start, (unsigned long long)r->start,
(unsigned long long)r->end); (unsigned long long)r->end);
r->flags = 0; r->flags = 0;
continue; continue;
} }
...@@ -372,8 +385,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long ...@@ -372,8 +385,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
align = 0; align = 0;
min_align = 0; min_align = 0;
for (order = 0; order <= max_order; order++) { for (order = 0; order <= max_order; order++) {
unsigned long align1 = 1UL << (order + 20); #ifdef CONFIG_RESOURCES_64BIT
resource_size_t align1 = 1ULL << (order + 20);
#else
resource_size_t align1 = 1U << (order + 20);
#endif
if (!align) if (!align)
min_align = align1; min_align = align1;
else if (ALIGN(align + min_align, min_align) < align1) else if (ALIGN(align + min_align, min_align) < align1)
......
...@@ -309,8 +309,8 @@ struct pci_raw_ops { ...@@ -309,8 +309,8 @@ struct pci_raw_ops {
extern struct pci_raw_ops *raw_pci_ops; extern struct pci_raw_ops *raw_pci_ops;
struct pci_bus_region { struct pci_bus_region {
unsigned long start; resource_size_t start;
unsigned long end; resource_size_t end;
}; };
struct pci_dynids { struct pci_dynids {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册