aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/pci_64.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-15 00:05:33 -0500
committerPaul Mackerras <paulus@samba.org>2005-11-15 21:29:46 -0500
commitb5166cc252190be80465f3b4f050e4a0310f71af (patch)
tree565d11c2ea25d1553489d6c8a9b4d2c00e110288 /arch/powerpc/kernel/pci_64.c
parentf9e4ec57c66586d0c165ed9373efaf9e329d5766 (diff)
[PATCH] powerpc: pci_64 fixes & cleanups
I discovered that in some cases (PowerMac for example) we wouldn't properly map the PCI IO space on recent kernels. In addition, the code for initializing PCI host bridges was scattered all over the place with some duplication between platforms. This patch fixes the problem and does a small cleanup by creating a pcibios_alloc_controller() in pci_64.c that is similar to the one in pci_32.c (just takes an additional device node argument) that takes care of all the grunt allocation and initialisation work. It should work for both boot time and dynamically allocated PHBs. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/pci_64.c')
-rw-r--r--arch/powerpc/kernel/pci_64.c68
1 files changed, 65 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index d7de3ec0bf83..5a5b24685081 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -187,7 +187,7 @@ static DEFINE_SPINLOCK(hose_spinlock);
187/* 187/*
188 * pci_controller(phb) initialized common variables. 188 * pci_controller(phb) initialized common variables.
189 */ 189 */
190void __devinit pci_setup_pci_controller(struct pci_controller *hose) 190static void __devinit pci_setup_pci_controller(struct pci_controller *hose)
191{ 191{
192 memset(hose, 0, sizeof(struct pci_controller)); 192 memset(hose, 0, sizeof(struct pci_controller));
193 193
@@ -197,6 +197,65 @@ void __devinit pci_setup_pci_controller(struct pci_controller *hose)
197 spin_unlock(&hose_spinlock); 197 spin_unlock(&hose_spinlock);
198} 198}
199 199
200static void add_linux_pci_domain(struct device_node *dev,
201 struct pci_controller *phb)
202{
203 struct property *of_prop;
204 unsigned int size;
205
206 of_prop = (struct property *)
207 get_property(dev, "linux,pci-domain", &size);
208 if (of_prop != NULL)
209 return;
210 WARN_ON(of_prop && size < sizeof(int));
211 if (of_prop && size < sizeof(int))
212 of_prop = NULL;
213 size = sizeof(struct property) + sizeof(int);
214 if (of_prop == NULL) {
215 if (mem_init_done)
216 of_prop = kmalloc(size, GFP_KERNEL);
217 else
218 of_prop = alloc_bootmem(size);
219 }
220 memset(of_prop, 0, sizeof(struct property));
221 of_prop->name = "linux,pci-domain";
222 of_prop->length = sizeof(int);
223 of_prop->value = (unsigned char *)&of_prop[1];
224 *((int *)of_prop->value) = phb->global_number;
225 prom_add_property(dev, of_prop);
226}
227
228struct pci_controller * pcibios_alloc_controller(struct device_node *dev)
229{
230 struct pci_controller *phb;
231
232 if (mem_init_done)
233 phb = kmalloc(sizeof(struct pci_controller), GFP_KERNEL);
234 else
235 phb = alloc_bootmem(sizeof (struct pci_controller));
236 if (phb == NULL)
237 return NULL;
238 pci_setup_pci_controller(phb);
239 phb->arch_data = dev;
240 phb->is_dynamic = mem_init_done;
241 if (dev)
242 add_linux_pci_domain(dev, phb);
243 return phb;
244}
245
246void pcibios_free_controller(struct pci_controller *phb)
247{
248 if (phb->arch_data) {
249 struct device_node *np = phb->arch_data;
250 int *domain = (int *)get_property(np,
251 "linux,pci-domain", NULL);
252 if (domain)
253 *domain = -1;
254 }
255 if (phb->is_dynamic)
256 kfree(phb);
257}
258
200static void __init pcibios_claim_one_bus(struct pci_bus *b) 259static void __init pcibios_claim_one_bus(struct pci_bus *b)
201{ 260{
202 struct pci_dev *dev; 261 struct pci_dev *dev;
@@ -907,9 +966,10 @@ void __devinit pci_process_bridge_OF_ranges(struct pci_controller *hose,
907 * (size depending on dev->n_addr_cells) 966 * (size depending on dev->n_addr_cells)
908 * cells 4+5 or 5+6: the size of the range 967 * cells 4+5 or 5+6: the size of the range
909 */ 968 */
910 rlen = 0;
911 hose->io_base_phys = 0;
912 ranges = (unsigned int *) get_property(dev, "ranges", &rlen); 969 ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
970 if (ranges == NULL)
971 return;
972 hose->io_base_phys = 0;
913 while ((rlen -= np * sizeof(unsigned int)) >= 0) { 973 while ((rlen -= np * sizeof(unsigned int)) >= 0) {
914 res = NULL; 974 res = NULL;
915 pci_space = ranges[0]; 975 pci_space = ranges[0];
@@ -1107,6 +1167,8 @@ int remap_bus_range(struct pci_bus *bus)
1107 1167
1108 if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) 1168 if (get_bus_io_range(bus, &start_phys, &start_virt, &size))
1109 return 1; 1169 return 1;
1170 if (start_phys == 0)
1171 return 1;
1110 printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); 1172 printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size);
1111 if (__ioremap_explicit(start_phys, start_virt, size, 1173 if (__ioremap_explicit(start_phys, start_virt, size,
1112 _PAGE_NO_CACHE | _PAGE_GUARDED)) 1174 _PAGE_NO_CACHE | _PAGE_GUARDED))