PCI: X86: Introduce and enable PCI domain support
Jeff Garzik [Thu, 11 Oct 2007 20:58:30 +0000 (16:58 -0400)]
* fix bug in pci_read() and pci_write() which prevented PCI domain
  support from working (hardcoded domain 0).

* unconditionally enable CONFIG_PCI_DOMAINS

* implement pci_domain_nr() and pci_proc_domain(), as required of
  all arches when CONFIG_PCI_DOMAINS is enabled.

* store domain in struct pci_sysdata, as assigned by ACPI

* support "pci=nodomains"

Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

arch/i386/Kconfig
arch/x86/pci/acpi.c
arch/x86/pci/common.c
arch/x86_64/Kconfig
include/asm-x86/pci_32.h
include/asm-x86/pci_64.h

index 2d85e4b..515abb9 100644 (file)
@@ -1137,6 +1137,11 @@ config PCI_MMCONFIG
        depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
        default y
 
+config PCI_DOMAINS
+       bool
+       depends on PCI
+       default y
+
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
index c6fd3a6..27a391d 100644 (file)
@@ -189,6 +189,12 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
 
        dmi_check_system(acpi_pciprobe_dmi_table);
 
+       if (domain && !pci_domains_supported) {
+               printk(KERN_WARNING "PCI: Multiple domains not supported "
+                      "(dom %d, bus %d)\n", domain, busnum);
+               return NULL;
+       }
+
        /* Allocate per-root-bus (not per bus) arch-specific data.
         * TODO: leak; this memory is never freed.
         * It's arguable whether it's worth the trouble to care.
@@ -199,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
                return NULL;
        }
 
-       if (domain != 0) {
-               printk(KERN_WARNING "PCI: Multiple domains not supported\n");
-               kfree(sd);
-               return NULL;
-       }
-
+       sd->domain = domain;
        sd->node = -1;
 
        pxm = acpi_get_pxm(device->handle);
index 7d6a9a5..2d71bbc 100644 (file)
@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops;
 
 static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
 {
-       return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
+       return raw_pci_ops->read(pci_domain_nr(bus), bus->number,
+                                devfn, where, size, value);
 }
 
 static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
 {
-       return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
+       return raw_pci_ops->write(pci_domain_nr(bus), bus->number,
+                                 devfn, where, size, value);
 }
 
 struct pci_ops pci_root_ops = {
index b1b98e6..04d324c 100644 (file)
@@ -724,6 +724,11 @@ config PCI_MMCONFIG
        bool "Support mmconfig PCI config space access"
        depends on PCI && ACPI
 
+config PCI_DOMAINS
+       bool
+       depends on PCI
+       default y
+
 source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pci/Kconfig"
index 4fcacc7..0d91605 100644 (file)
@@ -5,12 +5,24 @@
 #ifdef __KERNEL__
 
 struct pci_sysdata {
+       int             domain;         /* PCI domain */
        int             node;           /* NUMA node */
 };
 
 /* scan a bus after allocating a pci_sysdata for it */
 extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
 
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+       struct pci_sysdata *sd = bus->sysdata;
+       return sd->domain;
+}
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+       return pci_domain_nr(bus);
+}
+
 #include <linux/mm.h>          /* for struct page */
 
 /* Can be used to override the logic in pci_scan_bus for skipping
index 5da8cb0..0a123d6 100644 (file)
@@ -6,12 +6,24 @@
 #ifdef __KERNEL__
 
 struct pci_sysdata {
+       int             domain;         /* PCI domain */
        int             node;           /* NUMA node */
        void*           iommu;          /* IOMMU private data */
 };
 
 extern struct pci_bus *pci_scan_bus_with_sysdata(int busno);
 
+static inline int pci_domain_nr(struct pci_bus *bus)
+{
+       struct pci_sysdata *sd = bus->sysdata;
+       return sd->domain;
+}
+
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+       return pci_domain_nr(bus);
+}
+
 #ifdef CONFIG_CALGARY_IOMMU
 static inline void* pci_iommu(struct pci_bus *bus)
 {