aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2007-12-10 22:48:20 -0500
committerPaul Mackerras <paulus@samba.org>2007-12-10 23:43:35 -0500
commit05d3957e110c46b8c613214d68705bc97d9c6609 (patch)
tree37b97985e2cba447f080adf93d0020695ed6e0e9
parent13dccb9e65dc0fa4de83e5bd5639f7a7f3f6fb9e (diff)
[POWERPC] Fix powerpc 32-bit resource fixup for 64-bit resources
The 32-bit powerpc resource fixup code uses unsigned longs to do the offsetting of resources which overflows on platforms such as 4xx where resources can be 64 bits. This fixes it by using resource_size_t instead. However, the IO stuff does rely on some 32 bits arithmetic, so we hack by cropping the result of the fixups for IO resources with a 32 bits mask. This isn't the prettiest but should work for now until we change the 32 bits PCI code to do IO mappings like 64 bits does, within a reserved are of the kernel address space. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/kernel/pci_32.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
index 20a1192de1a2..03a7dc494b42 100644
--- a/arch/powerpc/kernel/pci_32.c
+++ b/arch/powerpc/kernel/pci_32.c
@@ -104,7 +104,7 @@ pcibios_fixup_resources(struct pci_dev *dev)
104{ 104{
105 struct pci_controller* hose = (struct pci_controller *)dev->sysdata; 105 struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
106 int i; 106 int i;
107 unsigned long offset; 107 resource_size_t offset, mask;
108 108
109 if (!hose) { 109 if (!hose) {
110 printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev)); 110 printk(KERN_ERR "No hose for PCI dev %s!\n", pci_name(dev));
@@ -123,15 +123,17 @@ pcibios_fixup_resources(struct pci_dev *dev)
123 continue; 123 continue;
124 } 124 }
125 offset = 0; 125 offset = 0;
126 mask = (resource_size_t)-1;
126 if (res->flags & IORESOURCE_MEM) { 127 if (res->flags & IORESOURCE_MEM) {
127 offset = hose->pci_mem_offset; 128 offset = hose->pci_mem_offset;
128 } else if (res->flags & IORESOURCE_IO) { 129 } else if (res->flags & IORESOURCE_IO) {
129 offset = (unsigned long) hose->io_base_virt 130 offset = (unsigned long) hose->io_base_virt
130 - isa_io_base; 131 - isa_io_base;
132 mask = 0xffffffffu;
131 } 133 }
132 if (offset != 0) { 134 if (offset != 0) {
133 res->start += offset; 135 res->start = (res->start + offset) & mask;
134 res->end += offset; 136 res->end = (res->end + offset) & mask;
135 DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n", 137 DBG("Fixup res %d (%lx) of dev %s: %llx -> %llx\n",
136 i, res->flags, pci_name(dev), 138 i, res->flags, pci_name(dev),
137 (u64)res->start - offset, (u64)res->start); 139 (u64)res->start - offset, (u64)res->start);
@@ -147,30 +149,32 @@ DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
147void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, 149void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
148 struct resource *res) 150 struct resource *res)
149{ 151{
150 unsigned long offset = 0; 152 resource_size_t offset = 0, mask = (resource_size_t)-1;
151 struct pci_controller *hose = dev->sysdata; 153 struct pci_controller *hose = dev->sysdata;
152 154
153 if (hose && res->flags & IORESOURCE_IO) 155 if (hose && res->flags & IORESOURCE_IO) {
154 offset = (unsigned long)hose->io_base_virt - isa_io_base; 156 offset = (unsigned long)hose->io_base_virt - isa_io_base;
155 else if (hose && res->flags & IORESOURCE_MEM) 157 mask = 0xffffffffu;
158 } else if (hose && res->flags & IORESOURCE_MEM)
156 offset = hose->pci_mem_offset; 159 offset = hose->pci_mem_offset;
157 region->start = res->start - offset; 160 region->start = (res->start - offset) & mask;
158 region->end = res->end - offset; 161 region->end = (res->end - offset) & mask;
159} 162}
160EXPORT_SYMBOL(pcibios_resource_to_bus); 163EXPORT_SYMBOL(pcibios_resource_to_bus);
161 164
162void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, 165void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
163 struct pci_bus_region *region) 166 struct pci_bus_region *region)
164{ 167{
165 unsigned long offset = 0; 168 resource_size_t offset = 0, mask = (resource_size_t)-1;
166 struct pci_controller *hose = dev->sysdata; 169 struct pci_controller *hose = dev->sysdata;
167 170
168 if (hose && res->flags & IORESOURCE_IO) 171 if (hose && res->flags & IORESOURCE_IO) {
169 offset = (unsigned long)hose->io_base_virt - isa_io_base; 172 offset = (unsigned long)hose->io_base_virt - isa_io_base;
170 else if (hose && res->flags & IORESOURCE_MEM) 173 mask = 0xffffffffu;
174 } else if (hose && res->flags & IORESOURCE_MEM)
171 offset = hose->pci_mem_offset; 175 offset = hose->pci_mem_offset;
172 res->start = region->start + offset; 176 res->start = (region->start + offset) & mask;
173 res->end = region->end + offset; 177 res->end = (region->end + offset) & mask;
174} 178}
175EXPORT_SYMBOL(pcibios_bus_to_resource); 179EXPORT_SYMBOL(pcibios_bus_to_resource);
176 180
@@ -334,9 +338,9 @@ static int __init
334pci_relocate_bridge_resource(struct pci_bus *bus, int i) 338pci_relocate_bridge_resource(struct pci_bus *bus, int i)
335{ 339{
336 struct resource *res, *pr, *conflict; 340 struct resource *res, *pr, *conflict;
337 unsigned long try, size; 341 resource_size_t try, size;
338 int j;
339 struct pci_bus *parent = bus->parent; 342 struct pci_bus *parent = bus->parent;
343 int j;
340 344
341 if (parent == NULL) { 345 if (parent == NULL) {
342 /* shouldn't ever happen */ 346 /* shouldn't ever happen */
@@ -438,7 +442,7 @@ update_bridge_resource(struct pci_dev *dev, struct resource *res)
438 u8 io_base_lo, io_limit_lo; 442 u8 io_base_lo, io_limit_lo;
439 u16 mem_base, mem_limit; 443 u16 mem_base, mem_limit;
440 u16 cmd; 444 u16 cmd;
441 unsigned long start, end, off; 445 resource_size_t start, end, off;
442 struct pci_controller *hose = dev->sysdata; 446 struct pci_controller *hose = dev->sysdata;
443 447
444 if (!hose) { 448 if (!hose) {
@@ -1157,8 +1161,8 @@ void pcibios_fixup_bus(struct pci_bus *bus)
1157 res->end = IO_SPACE_LIMIT; 1161 res->end = IO_SPACE_LIMIT;
1158 res->flags = IORESOURCE_IO; 1162 res->flags = IORESOURCE_IO;
1159 } 1163 }
1160 res->start += io_offset; 1164 res->start = (res->start + io_offset) & 0xffffffffu;
1161 res->end += io_offset; 1165 res->end = (res->end + io_offset) & 0xffffffffu;
1162 1166
1163 for (i = 0; i < 3; ++i) { 1167 for (i = 0; i < 3; ++i) {
1164 res = &hose->mem_resources[i]; 1168 res = &hose->mem_resources[i];
@@ -1183,8 +1187,10 @@ void pcibios_fixup_bus(struct pci_bus *bus)
1183 if (!res->flags || bus->self->transparent) 1187 if (!res->flags || bus->self->transparent)
1184 continue; 1188 continue;
1185 if (io_offset && (res->flags & IORESOURCE_IO)) { 1189 if (io_offset && (res->flags & IORESOURCE_IO)) {
1186 res->start += io_offset; 1190 res->start = (res->start + io_offset) &
1187 res->end += io_offset; 1191 0xffffffffu;
1192 res->end = (res->end + io_offset) &
1193 0xffffffffu;
1188 } else if (hose->pci_mem_offset 1194 } else if (hose->pci_mem_offset
1189 && (res->flags & IORESOURCE_MEM)) { 1195 && (res->flags & IORESOURCE_MEM)) {
1190 res->start += hose->pci_mem_offset; 1196 res->start += hose->pci_mem_offset;