diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-12-10 01:32:15 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-01 18:04:25 -0500 |
commit | c40a22e0ce5eb400f27449e59e43d021bee58b8d (patch) | |
tree | 9335519358ff657a6a80baefd759337e324dc26d | |
parent | f07234b66af1d1a204b9ddabdbdb312e8f1fb35e (diff) |
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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/pci/setup-bus.c | 64 | ||||
-rw-r--r-- | include/linux/pci.h | 4 |
2 files changed, 42 insertions, 26 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 401e03c920bd..8a7232feb553 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus) | |||
89 | * The IO resource is allocated a range twice as large as it | 89 | * The IO resource is allocated a range twice as large as it |
90 | * would normally need. This allows us to set both IO regs. | 90 | * would normally need. This allows us to set both IO regs. |
91 | */ | 91 | */ |
92 | printk(" IO window: %08lx-%08lx\n", | 92 | printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n", |
93 | region.start, region.end); | 93 | (unsigned long)region.start, |
94 | (unsigned long)region.end); | ||
94 | pci_write_config_dword(bridge, PCI_CB_IO_BASE_0, | 95 | pci_write_config_dword(bridge, PCI_CB_IO_BASE_0, |
95 | region.start); | 96 | region.start); |
96 | pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0, | 97 | pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0, |
@@ -99,8 +100,9 @@ void pci_setup_cardbus(struct pci_bus *bus) | |||
99 | 100 | ||
100 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]); | 101 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]); |
101 | if (bus->resource[1]->flags & IORESOURCE_IO) { | 102 | if (bus->resource[1]->flags & IORESOURCE_IO) { |
102 | printk(" IO window: %08lx-%08lx\n", | 103 | printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n", |
103 | region.start, region.end); | 104 | (unsigned long)region.start, |
105 | (unsigned long)region.end); | ||
104 | pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, | 106 | pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, |
105 | region.start); | 107 | region.start); |
106 | pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1, | 108 | pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1, |
@@ -109,8 +111,9 @@ void pci_setup_cardbus(struct pci_bus *bus) | |||
109 | 111 | ||
110 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); | 112 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); |
111 | if (bus->resource[2]->flags & IORESOURCE_MEM) { | 113 | if (bus->resource[2]->flags & IORESOURCE_MEM) { |
112 | printk(" PREFETCH window: %08lx-%08lx\n", | 114 | printk(KERN_INFO " PREFETCH window: 0x%08lx-0x%08lx\n", |
113 | region.start, region.end); | 115 | (unsigned long)region.start, |
116 | (unsigned long)region.end); | ||
114 | pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, | 117 | pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, |
115 | region.start); | 118 | region.start); |
116 | pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0, | 119 | pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0, |
@@ -119,8 +122,9 @@ void pci_setup_cardbus(struct pci_bus *bus) | |||
119 | 122 | ||
120 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[3]); | 123 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[3]); |
121 | if (bus->resource[3]->flags & IORESOURCE_MEM) { | 124 | if (bus->resource[3]->flags & IORESOURCE_MEM) { |
122 | printk(" MEM window: %08lx-%08lx\n", | 125 | printk(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n", |
123 | region.start, region.end); | 126 | (unsigned long)region.start, |
127 | (unsigned long)region.end); | ||
124 | pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, | 128 | pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, |
125 | region.start); | 129 | region.start); |
126 | pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1, | 130 | pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1, |
@@ -145,7 +149,7 @@ pci_setup_bridge(struct pci_bus *bus) | |||
145 | { | 149 | { |
146 | struct pci_dev *bridge = bus->self; | 150 | struct pci_dev *bridge = bus->self; |
147 | struct pci_bus_region region; | 151 | struct pci_bus_region region; |
148 | u32 l, io_upper16; | 152 | u32 l, bu, lu, io_upper16; |
149 | 153 | ||
150 | DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge)); | 154 | DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge)); |
151 | 155 | ||
@@ -159,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus) | |||
159 | /* Set up upper 16 bits of I/O base/limit. */ | 163 | /* Set up upper 16 bits of I/O base/limit. */ |
160 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); | 164 | io_upper16 = (region.end & 0xffff0000) | (region.start >> 16); |
161 | DBG(KERN_INFO " IO window: %04lx-%04lx\n", | 165 | DBG(KERN_INFO " IO window: %04lx-%04lx\n", |
162 | region.start, region.end); | 166 | (unsigned long)region.start, |
167 | (unsigned long)region.end); | ||
163 | } | 168 | } |
164 | else { | 169 | else { |
165 | /* Clear upper 16 bits of I/O base/limit. */ | 170 | /* Clear upper 16 bits of I/O base/limit. */ |
@@ -180,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus) | |||
180 | if (bus->resource[1]->flags & IORESOURCE_MEM) { | 185 | if (bus->resource[1]->flags & IORESOURCE_MEM) { |
181 | l = (region.start >> 16) & 0xfff0; | 186 | l = (region.start >> 16) & 0xfff0; |
182 | l |= region.end & 0xfff00000; | 187 | l |= region.end & 0xfff00000; |
183 | DBG(KERN_INFO " MEM window: %08lx-%08lx\n", | 188 | DBG(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n", |
184 | region.start, region.end); | 189 | (unsigned long)region.start, |
190 | (unsigned long)region.end); | ||
185 | } | 191 | } |
186 | else { | 192 | else { |
187 | l = 0x0000fff0; | 193 | l = 0x0000fff0; |
@@ -195,12 +201,18 @@ pci_setup_bridge(struct pci_bus *bus) | |||
195 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); | 201 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); |
196 | 202 | ||
197 | /* Set up PREF base/limit. */ | 203 | /* Set up PREF base/limit. */ |
204 | bu = lu = 0; | ||
198 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); | 205 | pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]); |
199 | if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { | 206 | if (bus->resource[2]->flags & IORESOURCE_PREFETCH) { |
200 | l = (region.start >> 16) & 0xfff0; | 207 | l = (region.start >> 16) & 0xfff0; |
201 | l |= region.end & 0xfff00000; | 208 | l |= region.end & 0xfff00000; |
202 | DBG(KERN_INFO " PREFETCH window: %08lx-%08lx\n", | 209 | #ifdef CONFIG_RESOURCES_64BIT |
203 | region.start, region.end); | 210 | bu = region.start >> 32; |
211 | lu = region.end >> 32; | ||
212 | #endif | ||
213 | DBG(KERN_INFO " PREFETCH window: 0x%016llx-0x%016llx\n", | ||
214 | (unsigned long long)region.start, | ||
215 | (unsigned long long)region.end); | ||
204 | } | 216 | } |
205 | else { | 217 | else { |
206 | l = 0x0000fff0; | 218 | l = 0x0000fff0; |
@@ -208,8 +220,9 @@ pci_setup_bridge(struct pci_bus *bus) | |||
208 | } | 220 | } |
209 | pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); | 221 | pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); |
210 | 222 | ||
211 | /* Clear out the upper 32 bits of PREF base. */ | 223 | /* Set the upper 32 bits of PREF base & limit. */ |
212 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); | 224 | pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu); |
225 | pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu); | ||
213 | 226 | ||
214 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); | 227 | pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl); |
215 | } | 228 | } |
@@ -323,8 +336,8 @@ static void pbus_size_io(struct pci_bus *bus) | |||
323 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) | 336 | static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type) |
324 | { | 337 | { |
325 | struct pci_dev *dev; | 338 | struct pci_dev *dev; |
326 | unsigned long min_align, align, size; | 339 | resource_size_t min_align, align, size; |
327 | unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */ | 340 | resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */ |
328 | int order, max_order; | 341 | int order, max_order; |
329 | struct resource *b_res = find_free_bus_resource(bus, type); | 342 | struct resource *b_res = find_free_bus_resource(bus, type); |
330 | 343 | ||
@@ -340,7 +353,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
340 | 353 | ||
341 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { | 354 | for (i = 0; i < PCI_NUM_RESOURCES; i++) { |
342 | struct resource *r = &dev->resource[i]; | 355 | struct resource *r = &dev->resource[i]; |
343 | unsigned long r_size; | 356 | resource_size_t r_size; |
344 | 357 | ||
345 | if (r->parent || (r->flags & mask) != type) | 358 | if (r->parent || (r->flags & mask) != type) |
346 | continue; | 359 | continue; |
@@ -350,10 +363,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
350 | order = __ffs(align) - 20; | 363 | order = __ffs(align) - 20; |
351 | if (order > 11) { | 364 | if (order > 11) { |
352 | printk(KERN_WARNING "PCI: region %s/%d " | 365 | printk(KERN_WARNING "PCI: region %s/%d " |
353 | "too large: %llx-%llx\n", | 366 | "too large: 0x%016llx-0x%016llx\n", |
354 | pci_name(dev), i, | 367 | pci_name(dev), i, |
355 | (unsigned long long)r->start, | 368 | (unsigned long long)r->start, |
356 | (unsigned long long)r->end); | 369 | (unsigned long long)r->end); |
357 | r->flags = 0; | 370 | r->flags = 0; |
358 | continue; | 371 | continue; |
359 | } | 372 | } |
@@ -372,8 +385,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long | |||
372 | align = 0; | 385 | align = 0; |
373 | min_align = 0; | 386 | min_align = 0; |
374 | for (order = 0; order <= max_order; order++) { | 387 | for (order = 0; order <= max_order; order++) { |
375 | unsigned long align1 = 1UL << (order + 20); | 388 | #ifdef CONFIG_RESOURCES_64BIT |
376 | 389 | resource_size_t align1 = 1ULL << (order + 20); | |
390 | #else | ||
391 | resource_size_t align1 = 1U << (order + 20); | ||
392 | #endif | ||
377 | if (!align) | 393 | if (!align) |
378 | min_align = align1; | 394 | min_align = align1; |
379 | else if (ALIGN(align + min_align, min_align) < align1) | 395 | else if (ALIGN(align + min_align, min_align) < align1) |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 87aab07e239a..4b4d711a5da8 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
@@ -309,8 +309,8 @@ struct pci_raw_ops { | |||
309 | extern struct pci_raw_ops *raw_pci_ops; | 309 | extern struct pci_raw_ops *raw_pci_ops; |
310 | 310 | ||
311 | struct pci_bus_region { | 311 | struct pci_bus_region { |
312 | unsigned long start; | 312 | resource_size_t start; |
313 | unsigned long end; | 313 | resource_size_t end; |
314 | }; | 314 | }; |
315 | 315 | ||
316 | struct pci_dynids { | 316 | struct pci_dynids { |