From 68d0d9794864a6bfbc6f88bb0ec980400bc17922 Mon Sep 17 00:00:00 2001 From: Alexander Kuleshov Date: Fri, 9 Oct 2015 00:51:46 +0600 Subject: x86/PCI: Make pci_subsys_init() static The pci_subsys_init() is a subsys_initcall that can be declared static. Signed-off-by: Alexander Kuleshov Signed-off-by: Bjorn Helgaas --- arch/x86/pci/legacy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch') diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index 5b662c0faf8c..ea6f3802c17b 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c @@ -54,7 +54,7 @@ void pcibios_scan_specific_bus(int busn) } EXPORT_SYMBOL_GPL(pcibios_scan_specific_bus); -int __init pci_subsys_init(void) +static int __init pci_subsys_init(void) { /* * The init function returns an non zero value when -- cgit v1.2.3 From 8affb487d4a4e223d961d7034cb41cd31982b618 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 9 Oct 2015 12:23:34 +0200 Subject: x86/PCI: Don't alloc pcibios-irq when MSI is enabled The pcibios-irq and MSI both use dev->irq to store the IRQ number. While the MSI code checks for that and frees the pcibios-irq before overwriting dev->irq, the pcibios_alloc_irq() function does not. Usually this is not a problem, as the pcibios-irq is allocated before probe time of the device and the MSI IRQ is allocted from the driver's probe path. But there are PCI devices handled by the core kernel and not by a standard PCI driver, like the AMD IOMMU for example. For the AMD IOMMU a normal PCI device driver does not make sense, because a driver can be forcibly unbound from its device, which is not a good idea for an IOMMU. Nevertheless the PCI core code tries to match the PCI device implementing the AMD IOMMU against drivers, and allocates/frees a pcibios IRQ every time it tries out a new driver. This overwrites the dev->irq field set by pci_enable_msi() and sets it to 0 in the end (because the probe fails and the pcibios-irq is freed again). On suspend/resume this breaks the kernel, because the IRQ descriptor for IRQ 0 is NULL. Fix this by not allocating a pcibios-irq when MSI is already active. This also has the benefit, that a device claimed by the core kernel can not be probed by a PCI driver later. Reported-by: Borislav Petkov Signed-off-by: Joerg Roedel Signed-off-by: Bjorn Helgaas Reviewed-by: Thomas Gleixner Cc: Jiang Liu --- arch/x86/pci/common.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch') diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 09d3afc0a181..b106c67f88c5 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -674,6 +674,14 @@ int pcibios_add_device(struct pci_dev *dev) int pcibios_alloc_irq(struct pci_dev *dev) { + /* + * If the PCI device was already claimed by core code and has + * MSI enabled, probing of the pcibios IRQ will overwrite + * dev->irq. So bail out if MSI is already enabled. + */ + if (pci_dev_msi_enabled(dev)) + return -EBUSY; + return pcibios_enable_irq(dev); } -- cgit v1.2.3 From af86fa4001ca5644ae20cc2c52cdf67bb7db9752 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 20 Oct 2015 11:36:53 -0500 Subject: 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 Tested-by: David Ahern Tested-by: Khalid Aziz Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/sparc/kernel/pci.c | 7 ++++++- arch/sparc/kernel/pci_common.c | 17 +++++++++++++++-- arch/sparc/kernel/pci_impl.h | 1 + 3 files changed, 22 insertions(+), 3 deletions(-) (limited to 'arch') 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) if (addr0 & 0x02000000) { flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; - flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; + if (addr0 & 0x01000000) + flags |= IORESOURCE_MEM_64 + | PCI_BASE_ADDRESS_MEM_TYPE_64; if (addr0 & 0x40000000) flags |= IORESOURCE_PREFETCH | PCI_BASE_ADDRESS_MEM_PREFETCH; @@ -655,6 +657,9 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, pbm->io_space.start); pci_add_resource_offset(&resources, &pbm->mem_space, pbm->mem_space.start); + if (pbm->mem64_space.flags) + pci_add_resource_offset(&resources, &pbm->mem64_space, + pbm->mem_space.start); pbm->busn.start = pbm->pci_first_busno; pbm->busn.end = pbm->pci_last_busno; 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) } num_pbm_ranges = i / sizeof(*pbm_ranges); + memset(&pbm->mem64_space, 0, sizeof(struct resource)); for (i = 0; i < num_pbm_ranges; i++) { 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) break; case 3: - /* XXX 64-bit MEM handling XXX */ + /* 64-bit MEM handling */ + pbm->mem64_space.start = a; + pbm->mem64_space.end = a + size - 1UL; + pbm->mem64_space.flags = IORESOURCE_MEM; + saw_mem = 1; + break; default: break; @@ -465,15 +471,22 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) prom_halt(); } - printk("%s: PCI IO[%llx] MEM[%llx]\n", + printk("%s: PCI IO[%llx] MEM[%llx]", pbm->name, pbm->io_space.start, pbm->mem_space.start); + if (pbm->mem64_space.flags) + printk(" MEM64[%llx]", + pbm->mem64_space.start); + printk("\n"); pbm->io_space.name = pbm->mem_space.name = pbm->name; + pbm->mem64_space.name = pbm->name; request_resource(&ioport_resource, &pbm->io_space); request_resource(&iomem_resource, &pbm->mem_space); + if (pbm->mem64_space.flags) + request_resource(&iomem_resource, &pbm->mem64_space); pci_register_legacy_regions(&pbm->io_space, &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 { /* PBM I/O and Memory space resources. */ struct resource io_space; struct resource mem_space; + struct resource mem64_space; struct resource busn; /* Base of PCI Config space, can be per-PBM or shared. */ -- cgit v1.2.3