Commit a79e4198 authored by Jeff Garzik's avatar Jeff Garzik Committed by Greg Kroah-Hartman

PCI: X86: Introduce and enable PCI domain support

* 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: default avatarJeff Garzik <jgarzik@redhat.com>
Cc: Andi Kleen <ak@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 32a2eea7
...@@ -1137,6 +1137,11 @@ config PCI_MMCONFIG ...@@ -1137,6 +1137,11 @@ config PCI_MMCONFIG
depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) depends on PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY)
default y default y
config PCI_DOMAINS
bool
depends on PCI
default y
source "drivers/pci/pcie/Kconfig" source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
......
...@@ -189,6 +189,12 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -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); 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. /* Allocate per-root-bus (not per bus) arch-specific data.
* TODO: leak; this memory is never freed. * TODO: leak; this memory is never freed.
* It's arguable whether it's worth the trouble to care. * 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 ...@@ -199,12 +205,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
return NULL; return NULL;
} }
if (domain != 0) { sd->domain = domain;
printk(KERN_WARNING "PCI: Multiple domains not supported\n");
kfree(sd);
return NULL;
}
sd->node = -1; sd->node = -1;
pxm = acpi_get_pxm(device->handle); pxm = acpi_get_pxm(device->handle);
......
...@@ -29,12 +29,14 @@ struct pci_raw_ops *raw_pci_ops; ...@@ -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) 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) 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 = { struct pci_ops pci_root_ops = {
......
...@@ -724,6 +724,11 @@ config PCI_MMCONFIG ...@@ -724,6 +724,11 @@ config PCI_MMCONFIG
bool "Support mmconfig PCI config space access" bool "Support mmconfig PCI config space access"
depends on PCI && ACPI depends on PCI && ACPI
config PCI_DOMAINS
bool
depends on PCI
default y
source "drivers/pci/pcie/Kconfig" source "drivers/pci/pcie/Kconfig"
source "drivers/pci/Kconfig" source "drivers/pci/Kconfig"
......
...@@ -5,12 +5,24 @@ ...@@ -5,12 +5,24 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
struct pci_sysdata { struct pci_sysdata {
int domain; /* PCI domain */
int node; /* NUMA node */ int node; /* NUMA node */
}; };
/* scan a bus after allocating a pci_sysdata for it */ /* scan a bus after allocating a pci_sysdata for it */
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); 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 */ #include <linux/mm.h> /* for struct page */
/* Can be used to override the logic in pci_scan_bus for skipping /* Can be used to override the logic in pci_scan_bus for skipping
......
...@@ -6,12 +6,24 @@ ...@@ -6,12 +6,24 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
struct pci_sysdata { struct pci_sysdata {
int domain; /* PCI domain */
int node; /* NUMA node */ int node; /* NUMA node */
void* iommu; /* IOMMU private data */ void* iommu; /* IOMMU private data */
}; };
extern struct pci_bus *pci_scan_bus_with_sysdata(int busno); 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 #ifdef CONFIG_CALGARY_IOMMU
static inline void* pci_iommu(struct pci_bus *bus) static inline void* pci_iommu(struct pci_bus *bus)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment