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: Jeff Garzik <jgarzik@redhat.com> Cc: Andi Kleen <ak@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
32a2eea795
commit
a79e4198d1
6 changed files with 45 additions and 8 deletions
|
@ -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
|
||||||
|
|
||||||
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
|
||||||
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;
|
||||||
|
|
||||||
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
|
||||||
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 @@
|
||||||
#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 @@
|
||||||
#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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue