diff options
author | Yinghai Lu <yinghai@kernel.org> | 2015-10-20 12:36:53 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-10-29 18:35:46 -0400 |
commit | af86fa4001ca5644ae20cc2c52cdf67bb7db9752 (patch) | |
tree | 54e20db34eb04b1561900c8b4325408f24a02b62 | |
parent | 597becb4adb7d57b8e9d857a68f764ce96a141b8 (diff) |
sparc/PCI: Add mem64 resource parsing for root bus
David reported that a T5-8 sparc system failed to boot with:
pci_sun4v f02dbcfc: PCI host bridge to bus 0000:00
pci_bus 0000:00: root bus resource [io 0x804000000000-0x80400fffffff] (bus address [0x0000-0xfffffff])
pci_bus 0000:00: root bus resource [mem 0x800000000000-0x80007effffff] (bus address [0x00000000-0x7effffff])
pci 0000:00:01.0: can't claim BAR 15 [mem 0x100000000-0x4afffffff pref]: no compatible bridge window
Note that we don't know about a host bridge aperture that contains
BAR 15. OF does report a MEM64 aperture, but before this patch,
pci_determine_mem_io_space() ignored it.
Add support for host bridge apertures with 64-bit PCI addresses. Also
set IORESOURCE_MEM_64 for PCI device and bridge resources in PCI 64-bit
memory space.
Sparc doesn't actually print the device and bridge resources, but after
this patch, we should have the equivalent of this:
pci_sun4v f02dbcfc: PCI host bridge to bus 0000:00
pci_bus 0000:00: root bus resource [io 0x804000000000-0x80400fffffff] (bus address [0x0000-0xfffffff])
pci_bus 0000:00: root bus resource [mem 0x800000000000-0x80007effffff] (bus address [0x00000000-0x7effffff])
pci_bus 0000:00: root bus resource [mem 0x800100000000-0x8007ffffffff] (bus address [0x100000000-0x7ffffffff])
pci 0000:00:01.0: bridge window [mem 0x800100000000-0x8004afffffff 64bit pref]
[bhelgaas: changelog, URL to David's report]
Fixes: d63e2e1f3df9 ("sparc/PCI: Clip bridge windows to fit in upstream windows")
Link: http://lkml.kernel.org/r/5514391F.2030300@oracle.com
Reported-by: David Ahern <david.ahern@oracle.com>
Tested-by: David Ahern <david.ahern@oracle.com>
Tested-by: Khalid Aziz <khalid.aziz@oracle.com>
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | arch/sparc/kernel/pci.c | 7 | ||||
-rw-r--r-- | arch/sparc/kernel/pci_common.c | 17 | ||||
-rw-r--r-- | arch/sparc/kernel/pci_impl.h | 1 |
3 files changed, 22 insertions, 3 deletions
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index b91d7f146175..badf0951d73c 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c | |||
@@ -185,8 +185,10 @@ static unsigned long pci_parse_of_flags(u32 addr0) | |||
185 | 185 | ||
186 | if (addr0 & 0x02000000) { | 186 | if (addr0 & 0x02000000) { |
187 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; | 187 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; |
188 | flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
189 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; | 188 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; |
189 | if (addr0 & 0x01000000) | ||
190 | flags |= IORESOURCE_MEM_64 | ||
191 | | PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
190 | if (addr0 & 0x40000000) | 192 | if (addr0 & 0x40000000) |
191 | flags |= IORESOURCE_PREFETCH | 193 | flags |= IORESOURCE_PREFETCH |
192 | | PCI_BASE_ADDRESS_MEM_PREFETCH; | 194 | | PCI_BASE_ADDRESS_MEM_PREFETCH; |
@@ -655,6 +657,9 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, | |||
655 | pbm->io_space.start); | 657 | pbm->io_space.start); |
656 | pci_add_resource_offset(&resources, &pbm->mem_space, | 658 | pci_add_resource_offset(&resources, &pbm->mem_space, |
657 | pbm->mem_space.start); | 659 | pbm->mem_space.start); |
660 | if (pbm->mem64_space.flags) | ||
661 | pci_add_resource_offset(&resources, &pbm->mem64_space, | ||
662 | pbm->mem_space.start); | ||
658 | pbm->busn.start = pbm->pci_first_busno; | 663 | pbm->busn.start = pbm->pci_first_busno; |
659 | pbm->busn.end = pbm->pci_last_busno; | 664 | pbm->busn.end = pbm->pci_last_busno; |
660 | pbm->busn.flags = IORESOURCE_BUS; | 665 | pbm->busn.flags = IORESOURCE_BUS; |
diff --git a/arch/sparc/kernel/pci_common.c b/arch/sparc/kernel/pci_common.c index 944a06536ecc..33524c1d5328 100644 --- a/arch/sparc/kernel/pci_common.c +++ b/arch/sparc/kernel/pci_common.c | |||
@@ -406,6 +406,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | |||
406 | } | 406 | } |
407 | 407 | ||
408 | num_pbm_ranges = i / sizeof(*pbm_ranges); | 408 | num_pbm_ranges = i / sizeof(*pbm_ranges); |
409 | memset(&pbm->mem64_space, 0, sizeof(struct resource)); | ||
409 | 410 | ||
410 | for (i = 0; i < num_pbm_ranges; i++) { | 411 | for (i = 0; i < num_pbm_ranges; i++) { |
411 | const struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; | 412 | const struct linux_prom_pci_ranges *pr = &pbm_ranges[i]; |
@@ -451,7 +452,12 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | |||
451 | break; | 452 | break; |
452 | 453 | ||
453 | case 3: | 454 | case 3: |
454 | /* XXX 64-bit MEM handling XXX */ | 455 | /* 64-bit MEM handling */ |
456 | pbm->mem64_space.start = a; | ||
457 | pbm->mem64_space.end = a + size - 1UL; | ||
458 | pbm->mem64_space.flags = IORESOURCE_MEM; | ||
459 | saw_mem = 1; | ||
460 | break; | ||
455 | 461 | ||
456 | default: | 462 | default: |
457 | break; | 463 | break; |
@@ -465,15 +471,22 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | |||
465 | prom_halt(); | 471 | prom_halt(); |
466 | } | 472 | } |
467 | 473 | ||
468 | printk("%s: PCI IO[%llx] MEM[%llx]\n", | 474 | printk("%s: PCI IO[%llx] MEM[%llx]", |
469 | pbm->name, | 475 | pbm->name, |
470 | pbm->io_space.start, | 476 | pbm->io_space.start, |
471 | pbm->mem_space.start); | 477 | pbm->mem_space.start); |
478 | if (pbm->mem64_space.flags) | ||
479 | printk(" MEM64[%llx]", | ||
480 | pbm->mem64_space.start); | ||
481 | printk("\n"); | ||
472 | 482 | ||
473 | pbm->io_space.name = pbm->mem_space.name = pbm->name; | 483 | pbm->io_space.name = pbm->mem_space.name = pbm->name; |
484 | pbm->mem64_space.name = pbm->name; | ||
474 | 485 | ||
475 | request_resource(&ioport_resource, &pbm->io_space); | 486 | request_resource(&ioport_resource, &pbm->io_space); |
476 | request_resource(&iomem_resource, &pbm->mem_space); | 487 | request_resource(&iomem_resource, &pbm->mem_space); |
488 | if (pbm->mem64_space.flags) | ||
489 | request_resource(&iomem_resource, &pbm->mem64_space); | ||
477 | 490 | ||
478 | pci_register_legacy_regions(&pbm->io_space, | 491 | pci_register_legacy_regions(&pbm->io_space, |
479 | &pbm->mem_space); | 492 | &pbm->mem_space); |
diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h index 75803c780af3..37222ca849df 100644 --- a/arch/sparc/kernel/pci_impl.h +++ b/arch/sparc/kernel/pci_impl.h | |||
@@ -97,6 +97,7 @@ struct pci_pbm_info { | |||
97 | /* PBM I/O and Memory space resources. */ | 97 | /* PBM I/O and Memory space resources. */ |
98 | struct resource io_space; | 98 | struct resource io_space; |
99 | struct resource mem_space; | 99 | struct resource mem_space; |
100 | struct resource mem64_space; | ||
100 | struct resource busn; | 101 | struct resource busn; |
101 | 102 | ||
102 | /* Base of PCI Config space, can be per-PBM or shared. */ | 103 | /* Base of PCI Config space, can be per-PBM or shared. */ |