aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha/kernel
diff options
context:
space:
mode:
authorLorenzo Pieralisi <lorenzo.pieralisi@arm.com>2017-07-31 12:37:51 -0400
committerBjorn Helgaas <bhelgaas@google.com>2017-08-03 17:25:28 -0400
commit0e4c2eeb758a91e68b9eaf7a4bee9bd5ed97ff2b (patch)
tree6aa5b2f6bb0b8699334c9afad2170a2153f6ff47 /arch/alpha/kernel
parent20d693225ab78f0651b0e116b74196aaf8a950bb (diff)
alpha/PCI: Replace pci_fixup_irqs() call with host bridge IRQ mapping hooks
The pci_fixup_irqs() function allocates IRQs for all PCI devices present in a system; those PCI devices possibly belong to different PCI bus trees (and possibly rooted at different host bridges) and may well be enabled (ie probed and bound to a driver) by the time pci_fixup_irqs() is called when probing a given host bridge driver. Furthermore, current kernel code relying on pci_fixup_irqs() to assign legacy PCI IRQs to devices does not work at all for hotplugged devices in that the code carrying out the IRQ fixup is called at host bridge driver probe time, which just cannot take into account devices hotplugged after the system has booted. The introduction of map/swizzle function hooks in struct pci_host_bridge allows us to define per-bridge map/swizzle functions that can be used at device probe time in PCI core code to allocate IRQs for a given device (through pci_assign_irq()). Convert PCI host bridge initialization code to the pci_scan_root_bus_bridge() API (that allows to pass a struct pci_host_bridge with initialized map/swizzle pointers) and remove the pci_fixup_irqs() call from arch code. Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: Richard Henderson <rth@twiddle.net> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Diffstat (limited to 'arch/alpha/kernel')
-rw-r--r--arch/alpha/kernel/pci.c27
-rw-r--r--arch/alpha/kernel/sys_nautilus.c31
2 files changed, 47 insertions, 11 deletions
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 5f387ee5b5c5..d558287c6133 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -312,8 +312,9 @@ common_init_pci(void)
312{ 312{
313 struct pci_controller *hose; 313 struct pci_controller *hose;
314 struct list_head resources; 314 struct list_head resources;
315 struct pci_host_bridge *bridge;
315 struct pci_bus *bus; 316 struct pci_bus *bus;
316 int next_busno; 317 int ret, next_busno;
317 int need_domain_info = 0; 318 int need_domain_info = 0;
318 u32 pci_mem_end; 319 u32 pci_mem_end;
319 u32 sg_base; 320 u32 sg_base;
@@ -336,11 +337,25 @@ common_init_pci(void)
336 pci_add_resource_offset(&resources, hose->mem_space, 337 pci_add_resource_offset(&resources, hose->mem_space,
337 hose->mem_space->start); 338 hose->mem_space->start);
338 339
339 bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops, 340 bridge = pci_alloc_host_bridge(0);
340 hose, &resources); 341 if (!bridge)
341 if (!bus)
342 continue; 342 continue;
343 hose->bus = bus; 343
344 list_splice_init(&resources, &bridge->windows);
345 bridge->dev.parent = NULL;
346 bridge->sysdata = hose;
347 bridge->busnr = next_busno;
348 bridge->ops = alpha_mv.pci_ops;
349 bridge->swizzle_irq = alpha_mv.pci_swizzle;
350 bridge->map_irq = alpha_mv.pci_map_irq;
351
352 ret = pci_scan_root_bus_bridge(bridge);
353 if (ret) {
354 pci_free_host_bridge(bridge);
355 continue;
356 }
357
358 bus = hose->bus = bridge->bus;
344 hose->need_domain_info = need_domain_info; 359 hose->need_domain_info = need_domain_info;
345 next_busno = bus->busn_res.end + 1; 360 next_busno = bus->busn_res.end + 1;
346 /* Don't allow 8-bit bus number overflow inside the hose - 361 /* Don't allow 8-bit bus number overflow inside the hose -
@@ -354,7 +369,6 @@ common_init_pci(void)
354 pcibios_claim_console_setup(); 369 pcibios_claim_console_setup();
355 370
356 pci_assign_unassigned_resources(); 371 pci_assign_unassigned_resources();
357 pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
358 for (hose = hose_head; hose; hose = hose->next) { 372 for (hose = hose_head; hose; hose = hose->next) {
359 bus = hose->bus; 373 bus = hose->bus;
360 if (bus) 374 if (bus)
@@ -362,7 +376,6 @@ common_init_pci(void)
362 } 376 }
363} 377}
364 378
365
366struct pci_controller * __init 379struct pci_controller * __init
367alloc_pci_controller(void) 380alloc_pci_controller(void)
368{ 381{
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 2cfaa0e5c577..8ae04a121186 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -194,22 +194,46 @@ static struct resource irongate_mem = {
194 .name = "Irongate PCI MEM", 194 .name = "Irongate PCI MEM",
195 .flags = IORESOURCE_MEM, 195 .flags = IORESOURCE_MEM,
196}; 196};
197static struct resource busn_resource = {
198 .name = "PCI busn",
199 .start = 0,
200 .end = 255,
201 .flags = IORESOURCE_BUS,
202};
197 203
198void __init 204void __init
199nautilus_init_pci(void) 205nautilus_init_pci(void)
200{ 206{
201 struct pci_controller *hose = hose_head; 207 struct pci_controller *hose = hose_head;
208 struct pci_host_bridge *bridge;
202 struct pci_bus *bus; 209 struct pci_bus *bus;
203 struct pci_dev *irongate; 210 struct pci_dev *irongate;
204 unsigned long bus_align, bus_size, pci_mem; 211 unsigned long bus_align, bus_size, pci_mem;
205 unsigned long memtop = max_low_pfn << PAGE_SHIFT; 212 unsigned long memtop = max_low_pfn << PAGE_SHIFT;
213 int ret;
214
215 bridge = pci_alloc_host_bridge(0);
216 if (!bridge)
217 return;
218
219 pci_add_resource(&bridge->windows, &ioport_resource);
220 pci_add_resource(&bridge->windows, &iomem_resource);
221 pci_add_resource(&bridge->windows, &busn_resource);
222 bridge->dev.parent = NULL;
223 bridge->sysdata = hose;
224 bridge->busnr = 0;
225 bridge->ops = alpha_mv.pci_ops;
226 bridge->swizzle_irq = alpha_mv.pci_swizzle;
227 bridge->map_irq = alpha_mv.pci_map_irq;
206 228
207 /* Scan our single hose. */ 229 /* Scan our single hose. */
208 bus = pci_scan_bus(0, alpha_mv.pci_ops, hose); 230 ret = pci_scan_root_bus_bridge(bridge);
209 if (!bus) 231 if (ret) {
232 pci_free_host_bridge(bridge);
210 return; 233 return;
234 }
211 235
212 hose->bus = bus; 236 bus = hose->bus = bridge->bus;
213 pcibios_claim_one_bus(bus); 237 pcibios_claim_one_bus(bus);
214 238
215 irongate = pci_get_bus_and_slot(0, 0); 239 irongate = pci_get_bus_and_slot(0, 0);
@@ -254,7 +278,6 @@ nautilus_init_pci(void)
254 /* pci_common_swizzle() relies on bus->self being NULL 278 /* pci_common_swizzle() relies on bus->self being NULL
255 for the root bus, so just clear it. */ 279 for the root bus, so just clear it. */
256 bus->self = NULL; 280 bus->self = NULL;
257 pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
258 pci_bus_add_devices(bus); 281 pci_bus_add_devices(bus);
259} 282}
260 283