diff options
Diffstat (limited to 'arch/powerpc/kernel/pci_64.c')
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 68 |
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 | */ |
190 | void __devinit pci_setup_pci_controller(struct pci_controller *hose) | 190 | static 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 | ||
200 | static 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 | |||
228 | struct 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 | |||
246 | void 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 | |||
200 | static void __init pcibios_claim_one_bus(struct pci_bus *b) | 259 | static 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)) |