Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci: (80 commits)
  x86/PCI: Expand the x86_msi_ops to have a restore MSIs.
  PCI: Increase resource array mask bit size in pcim_iomap_regions()
  PCI: DEVICE_COUNT_RESOURCE should be equal to PCI_NUM_RESOURCES
  PCI: pci_ids: add device ids for STA2X11 device (aka ConneXT)
  PNP: work around Dell 1536/1546 BIOS MMCONFIG bug that breaks USB
  x86/PCI: amd: factor out MMCONFIG discovery
  PCI: Enable ATS at the device state restore
  PCI: msi: fix imbalanced refcount of msi irq sysfs objects
  PCI: kconfig: English typo in pci/pcie/Kconfig
  PCI/PM/Runtime: make PCI traces quieter
  PCI: remove pci_create_bus()
  xtensa/PCI: convert to pci_scan_root_bus() for correct root bus resources
  x86/PCI: convert to pci_create_root_bus() and pci_scan_root_bus()
  x86/PCI: use pci_scan_bus() instead of pci_scan_bus_parented()
  x86/PCI: read Broadcom CNB20LE host bridge info before PCI scan
  sparc32, leon/PCI: convert to pci_scan_root_bus() for correct root bus resources
  sparc/PCI: convert to pci_create_root_bus()
  sh/PCI: convert to pci_scan_root_bus() for correct root bus resources
  powerpc/PCI: convert to pci_create_root_bus()
  powerpc/PCI: split PHB part out of pcibios_map_io_space()
  ...

Fix up conflicts in drivers/pci/msi.c and include/linux/pci_regs.h due
to the same patches being applied in other branches.
This commit is contained in:
Linus Torvalds 2012-01-11 18:50:26 -08:00
commit 7b67e75147
91 changed files with 1134 additions and 815 deletions

View File

@ -544,3 +544,15 @@ When: 3.5
Why: The iwlagn module has been renamed iwlwifi. The alias will be around Why: The iwlagn module has been renamed iwlwifi. The alias will be around
for backward compatibility for several cycles and then dropped. for backward compatibility for several cycles and then dropped.
Who: Don Fry <donald.h.fry@intel.com> Who: Don Fry <donald.h.fry@intel.com>
----------------------------
What: pci_scan_bus_parented()
When: 3.5
Why: The pci_scan_bus_parented() interface creates a new root bus. The
bus is created with default resources (ioport_resource and
iomem_resource) that are always wrong, so we rely on arch code to
correct them later. Callers of pci_scan_bus_parented() should
convert to using pci_scan_root_bus() so they can supply a list of
bus resources when the bus is created.
Who: Bjorn Helgaas <bhelgaas@google.com>

View File

@ -281,27 +281,9 @@ pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus)
void __devinit void __devinit
pcibios_fixup_bus(struct pci_bus *bus) pcibios_fixup_bus(struct pci_bus *bus)
{ {
/* Propagate hose info into the subordinate devices. */
struct pci_controller *hose = bus->sysdata;
struct pci_dev *dev = bus->self; struct pci_dev *dev = bus->self;
if (!dev) { if (pci_probe_only && dev &&
/* Root bus. */
u32 pci_mem_end;
u32 sg_base = hose->sg_pci ? hose->sg_pci->dma_base : ~0;
unsigned long end;
bus->resource[0] = hose->io_space;
bus->resource[1] = hose->mem_space;
/* Adjust hose mem_space limit to prevent PCI allocations
in the iommu windows. */
pci_mem_end = min((u32)__direct_map_base, sg_base) - 1;
end = hose->mem_space->start + pci_mem_end;
if (hose->mem_space->end > end)
hose->mem_space->end = end;
} else if (pci_probe_only &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(dev, bus); pcibios_fixup_device_resources(dev, bus);
@ -414,13 +396,31 @@ void __init
common_init_pci(void) common_init_pci(void)
{ {
struct pci_controller *hose; struct pci_controller *hose;
struct list_head resources;
struct pci_bus *bus; struct pci_bus *bus;
int next_busno; int next_busno;
int need_domain_info = 0; int need_domain_info = 0;
u32 pci_mem_end;
u32 sg_base;
unsigned long end;
/* Scan all of the recorded PCI controllers. */ /* Scan all of the recorded PCI controllers. */
for (next_busno = 0, hose = hose_head; hose; hose = hose->next) { for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
bus = pci_scan_bus(next_busno, alpha_mv.pci_ops, hose); sg_base = hose->sg_pci ? hose->sg_pci->dma_base : ~0;
/* Adjust hose mem_space limit to prevent PCI allocations
in the iommu windows. */
pci_mem_end = min((u32)__direct_map_base, sg_base) - 1;
end = hose->mem_space->start + pci_mem_end;
if (hose->mem_space->end > end)
hose->mem_space->end = end;
INIT_LIST_HEAD(&resources);
pci_add_resource(&resources, hose->io_space);
pci_add_resource(&resources, hose->mem_space);
bus = pci_scan_root_bus(NULL, next_busno, alpha_mv.pci_ops,
hose, &resources);
hose->bus = bus; hose->bus = bus;
hose->need_domain_info = need_domain_info; hose->need_domain_info = need_domain_info;
next_busno = bus->subordinate + 1; next_busno = bus->subordinate + 1;

View File

@ -299,8 +299,8 @@ int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
goto err1; goto err1;
} }
sys->resource[0] = &it8152_io; pci_add_resource(&sys->resources, &it8152_io);
sys->resource[1] = &it8152_mem; pci_add_resource(&sys->resources, &it8152_mem);
if (platform_notify || platform_notify_remove) { if (platform_notify || platform_notify_remove) {
printk(KERN_ERR "PCI: Can't use platform_notify\n"); printk(KERN_ERR "PCI: Can't use platform_notify\n");
@ -327,6 +327,9 @@ int __init it8152_pci_setup(int nr, struct pci_sys_data *sys)
*/ */
unsigned int pcibios_max_latency = 255; unsigned int pcibios_max_latency = 255;
/* ITE bridge requires setting latency timer to avoid early bus access
termination by PCI bus master devices
*/
void pcibios_set_master(struct pci_dev *dev) void pcibios_set_master(struct pci_dev *dev)
{ {
u8 lat; u8 lat;
@ -352,7 +355,7 @@ void pcibios_set_master(struct pci_dev *dev)
struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(nr, &it8152_ops, sys); return pci_scan_root_bus(NULL, nr, &it8152_ops, sys, &sys->resources);
} }
EXPORT_SYMBOL(dma_set_coherent_mask); EXPORT_SYMBOL(dma_set_coherent_mask);

View File

@ -86,7 +86,8 @@ int __init via82c505_setup(int nr, struct pci_sys_data *sys)
struct pci_bus * __init via82c505_scan_bus(int nr, struct pci_sys_data *sysdata) struct pci_bus * __init via82c505_scan_bus(int nr, struct pci_sys_data *sysdata)
{ {
if (nr == 0) if (nr == 0)
return pci_scan_bus(0, &via82c505_ops, sysdata); return pci_scan_root_bus(NULL, 0, &via82c505_ops, sysdata,
&sysdata->resources);
return NULL; return NULL;
} }

View File

@ -40,7 +40,7 @@ struct pci_sys_data {
u64 mem_offset; /* bus->cpu memory mapping offset */ u64 mem_offset; /* bus->cpu memory mapping offset */
unsigned long io_offset; /* bus->cpu IO mapping offset */ unsigned long io_offset; /* bus->cpu IO mapping offset */
struct pci_bus *bus; /* PCI bus */ struct pci_bus *bus; /* PCI bus */
struct resource *resource[3]; /* Primary PCI bus resources */ struct list_head resources; /* root bus resources (apertures) */
/* Bridge swizzling */ /* Bridge swizzling */
u8 (*swizzle)(struct pci_dev *, u8 *); u8 (*swizzle)(struct pci_dev *, u8 *);
/* IRQ mapping */ /* IRQ mapping */

View File

@ -31,18 +31,6 @@ static inline int pci_proc_domain(struct pci_bus *bus)
} }
#endif /* CONFIG_PCI_DOMAINS */ #endif /* CONFIG_PCI_DOMAINS */
#ifdef CONFIG_PCI_HOST_ITE8152
/* ITE bridge requires setting latency timer to avoid early bus access
termination by PIC bus mater devices
*/
extern void pcibios_set_master(struct pci_dev *dev);
#else
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
#endif
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -316,21 +316,6 @@ pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
} }
} }
static void __devinit
pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
{
struct pci_dev *dev = bus->self;
int i;
if (!dev) {
/*
* Assign root bus resources.
*/
for (i = 0; i < 3; i++)
bus->resource[i] = root->resource[i];
}
}
/* /*
* pcibios_fixup_bus - Called after each bus is probed, * pcibios_fixup_bus - Called after each bus is probed,
* but before its children are examined. * but before its children are examined.
@ -341,8 +326,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
struct pci_dev *dev; struct pci_dev *dev;
u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK; u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
pbus_assign_bus_resources(bus, root);
/* /*
* Walk the devices on this bus, working out what we can * Walk the devices on this bus, working out what we can
* and can't support. * and can't support.
@ -508,12 +491,18 @@ static void __init pcibios_init_hw(struct hw_pci *hw)
sys->busnr = busnr; sys->busnr = busnr;
sys->swizzle = hw->swizzle; sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq; sys->map_irq = hw->map_irq;
sys->resource[0] = &ioport_resource; INIT_LIST_HEAD(&sys->resources);
sys->resource[1] = &iomem_resource;
ret = hw->setup(nr, sys); ret = hw->setup(nr, sys);
if (ret > 0) { if (ret > 0) {
if (list_empty(&sys->resources)) {
pci_add_resource(&sys->resources,
&ioport_resource);
pci_add_resource(&sys->resources,
&iomem_resource);
}
sys->bus = hw->scan(nr, sys); sys->bus = hw->scan(nr, sys);
if (!sys->bus) if (!sys->bus)
@ -571,6 +560,13 @@ void __init pci_common_init(struct hw_pci *hw)
} }
} }
#ifndef CONFIG_PCI_HOST_ITE8152
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
#endif
char * __init pcibios_setup(char *str) char * __init pcibios_setup(char *str)
{ {
if (!strcmp(str, "debug")) { if (!strcmp(str, "debug")) {

View File

@ -151,13 +151,12 @@ static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys)
struct cns3xxx_pcie *cnspci = sysdata_to_cnspci(sys); struct cns3xxx_pcie *cnspci = sysdata_to_cnspci(sys);
struct resource *res_io = &cnspci->res_io; struct resource *res_io = &cnspci->res_io;
struct resource *res_mem = &cnspci->res_mem; struct resource *res_mem = &cnspci->res_mem;
struct resource **sysres = sys->resource;
BUG_ON(request_resource(&iomem_resource, res_io) || BUG_ON(request_resource(&iomem_resource, res_io) ||
request_resource(&iomem_resource, res_mem)); request_resource(&iomem_resource, res_mem));
sysres[0] = res_io; pci_add_resource(&sys->resources, res_io);
sysres[1] = res_mem; pci_add_resource(&sys->resources, res_mem);
return 1; return 1;
} }
@ -169,7 +168,8 @@ static struct pci_ops cns3xxx_pcie_ops = {
static struct pci_bus *cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys) static struct pci_bus *cns3xxx_pci_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &cns3xxx_pcie_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &cns3xxx_pcie_ops, sys,
&sys->resources);
} }
static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)

View File

@ -69,7 +69,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[0].flags = IORESOURCE_IO; pp->res[0].flags = IORESOURCE_IO;
if (request_resource(&ioport_resource, &pp->res[0])) if (request_resource(&ioport_resource, &pp->res[0]))
panic("Request PCIe IO resource failed\n"); panic("Request PCIe IO resource failed\n");
sys->resource[0] = &pp->res[0]; pci_add_resource(&sys->resources, &pp->res[0]);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
@ -88,9 +88,7 @@ static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[1].flags = IORESOURCE_MEM; pp->res[1].flags = IORESOURCE_MEM;
if (request_resource(&iomem_resource, &pp->res[1])) if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe Memory resource failed\n"); panic("Request PCIe Memory resource failed\n");
sys->resource[1] = &pp->res[1]; pci_add_resource(&sys->resources, &pp->res[1]);
sys->resource[2] = NULL;
return 1; return 1;
} }
@ -184,7 +182,8 @@ dove_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pci_bus *bus; struct pci_bus *bus;
if (nr < num_pcie_ports) { if (nr < num_pcie_ports) {
bus = pci_scan_bus(sys->busnr, &pcie_ops, sys); bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
} else { } else {
bus = NULL; bus = NULL;
BUG(); BUG();

View File

@ -275,9 +275,9 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
allocate_resource(&iomem_resource, &res[0], 0x40000000, allocate_resource(&iomem_resource, &res[0], 0x40000000,
0x80000000, 0xffffffff, 0x40000000, NULL, NULL); 0x80000000, 0xffffffff, 0x40000000, NULL, NULL);
sys->resource[0] = &ioport_resource; pci_add_resource(&sys->resources, &ioport_resource);
sys->resource[1] = &res[0]; pci_add_resource(&sys->resources, &res[0]);
sys->resource[2] = &res[1]; pci_add_resource(&sys->resources, &res[1]);
sys->mem_offset = DC21285_PCI_MEM; sys->mem_offset = DC21285_PCI_MEM;
return 1; return 1;
@ -285,7 +285,7 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus * __init dc21285_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(0, &dc21285_ops, sys); return pci_scan_root_bus(NULL, 0, &dc21285_ops, sys, &sys->resources);
} }
#define dc21285_request_irq(_a, _b, _c, _d, _e) \ #define dc21285_request_irq(_a, _b, _c, _d, _e) \

View File

@ -359,7 +359,7 @@ static struct resource pre_mem = {
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
}; };
static int __init pci_v3_setup_resources(struct resource **resource) static int __init pci_v3_setup_resources(struct pci_sys_data *sys)
{ {
if (request_resource(&iomem_resource, &non_mem)) { if (request_resource(&iomem_resource, &non_mem)) {
printk(KERN_ERR "PCI: unable to allocate non-prefetchable " printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
@ -374,13 +374,13 @@ static int __init pci_v3_setup_resources(struct resource **resource)
} }
/* /*
* bus->resource[0] is the IO resource for this bus * the IO resource for this bus
* bus->resource[1] is the mem resource for this bus * the mem resource for this bus
* bus->resource[2] is the prefetch mem resource for this bus * the prefetch mem resource for this bus
*/ */
resource[0] = &ioport_resource; pci_add_resource(&sys->resources, &ioport_resource);
resource[1] = &non_mem; pci_add_resource(&sys->resources, &non_mem);
resource[2] = &pre_mem; pci_add_resource(&sys->resources, &pre_mem);
return 1; return 1;
} }
@ -481,7 +481,7 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
if (nr == 0) { if (nr == 0) {
sys->mem_offset = PHYS_PCI_MEM_BASE; sys->mem_offset = PHYS_PCI_MEM_BASE;
ret = pci_v3_setup_resources(sys->resource); ret = pci_v3_setup_resources(sys);
} }
return ret; return ret;
@ -489,7 +489,8 @@ int __init pci_v3_setup(int nr, struct pci_sys_data *sys)
struct pci_bus * __init pci_v3_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus * __init pci_v3_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &pci_v3_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &pci_v3_ops, sys,
&sys->resources);
} }
/* /*

View File

@ -537,14 +537,14 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
while(time_before(jiffies, atux_trhfa_timeout)) while(time_before(jiffies, atux_trhfa_timeout))
udelay(100); udelay(100);
bus = pci_bus_atux = pci_scan_bus(sys->busnr, bus = pci_bus_atux = pci_scan_root_bus(NULL, sys->busnr,
&iop13xx_atux_ops, &iop13xx_atux_ops,
sys); sys, &sys->resources);
break; break;
case IOP13XX_INIT_ATU_ATUE: case IOP13XX_INIT_ATU_ATUE:
bus = pci_bus_atue = pci_scan_bus(sys->busnr, bus = pci_bus_atue = pci_scan_root_bus(NULL, sys->busnr,
&iop13xx_atue_ops, &iop13xx_atue_ops,
sys); sys, &sys->resources);
break; break;
} }
@ -1084,9 +1084,8 @@ int iop13xx_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&ioport_resource, &res[0]); request_resource(&ioport_resource, &res[0]);
request_resource(&iomem_resource, &res[1]); request_resource(&iomem_resource, &res[1]);
sys->resource[0] = &res[0]; pci_add_resource(&sys->resources, &res[0]);
sys->resource[1] = &res[1]; pci_add_resource(&sys->resources, &res[1]);
sys->resource[2] = NULL;
return 1; return 1;
} }

View File

@ -145,7 +145,8 @@ static struct pci_ops enp2611_pci_ops = {
static struct pci_bus * __init enp2611_pci_scan_bus(int nr, static struct pci_bus * __init enp2611_pci_scan_bus(int nr,
struct pci_sys_data *sys) struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &enp2611_pci_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &enp2611_pci_ops, sys,
&sys->resources);
} }
static int __init enp2611_pci_map_irq(const struct pci_dev *dev, u8 slot, static int __init enp2611_pci_map_irq(const struct pci_dev *dev, u8 slot,

View File

@ -132,7 +132,8 @@ static struct pci_ops ixp2000_pci_ops = {
struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata) struct pci_bus *ixp2000_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
{ {
return pci_scan_bus(sysdata->busnr, &ixp2000_pci_ops, sysdata); return pci_scan_root_bus(NULL, sysdata->busnr, &ixp2000_pci_ops,
sysdata, &sysdata->resources);
} }
@ -242,9 +243,8 @@ int ixp2000_pci_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1) if (nr >= 1)
return 0; return 0;
sys->resource[0] = &ixp2000_pci_io_space; pci_add_resource(&sys->resources, &ixp2000_pci_io_space);
sys->resource[1] = &ixp2000_pci_mem_space; pci_add_resource(&sys->resources, &ixp2000_pci_mem_space);
sys->resource[2] = NULL;
return 1; return 1;
} }

View File

@ -143,7 +143,8 @@ struct pci_ops ixp23xx_pci_ops = {
struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata) struct pci_bus *ixp23xx_pci_scan_bus(int nr, struct pci_sys_data *sysdata)
{ {
return pci_scan_bus(sysdata->busnr, &ixp23xx_pci_ops, sysdata); return pci_scan_root_bus(NULL, sysdata->busnr, &ixp23xx_pci_ops,
sysdata, &sysdata->resources);
} }
int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) int ixp23xx_pci_abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
@ -280,9 +281,8 @@ int ixp23xx_pci_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1) if (nr >= 1)
return 0; return 0;
sys->resource[0] = &ixp23xx_pci_io_space; pci_add_resource(&sys->resources, &ixp23xx_pci_io_space);
sys->resource[1] = &ixp23xx_pci_mem_space; pci_add_resource(&sys->resources, &ixp23xx_pci_mem_space);
sys->resource[2] = NULL;
return 1; return 1;
} }

View File

@ -472,9 +472,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
request_resource(&ioport_resource, &res[0]); request_resource(&ioport_resource, &res[0]);
request_resource(&iomem_resource, &res[1]); request_resource(&iomem_resource, &res[1]);
sys->resource[0] = &res[0]; pci_add_resource(&sys->resources, &res[0]);
sys->resource[1] = &res[1]; pci_add_resource(&sys->resources, &res[1]);
sys->resource[2] = NULL;
platform_notify = ixp4xx_pci_platform_notify; platform_notify = ixp4xx_pci_platform_notify;
platform_notify_remove = ixp4xx_pci_platform_notify_remove; platform_notify_remove = ixp4xx_pci_platform_notify_remove;
@ -484,7 +483,8 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus * __devinit ixp4xx_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &ixp4xx_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &ixp4xx_ops, sys,
&sys->resources);
} }
int dma_set_coherent_mask(struct device *dev, u64 mask) int dma_set_coherent_mask(struct device *dev, u64 mask)

View File

@ -198,9 +198,8 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
if (request_resource(&iomem_resource, &pp->res[1])) if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe%d Memory resource failed\n", index); panic("Request PCIe%d Memory resource failed\n", index);
sys->resource[0] = &pp->res[0]; pci_add_resource(&sys->resources, &pp->res[0]);
sys->resource[1] = &pp->res[1]; pci_add_resource(&sys->resources, &pp->res[1]);
sys->resource[2] = NULL;
sys->io_offset = 0; sys->io_offset = 0;
/* /*
@ -236,7 +235,8 @@ kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pci_bus *bus; struct pci_bus *bus;
if (nr < num_pcie_ports) { if (nr < num_pcie_ports) {
bus = pci_scan_bus(sys->busnr, &pcie_ops, sys); bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
} else { } else {
bus = NULL; bus = NULL;
BUG(); BUG();

View File

@ -143,7 +143,8 @@ static struct pci_ops ks8695_pci_ops = {
static struct pci_bus* __init ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys) static struct pci_bus* __init ks8695_pci_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &ks8695_pci_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &ks8695_pci_ops, sys,
&sys->resources);
} }
static struct resource pci_mem = { static struct resource pci_mem = {
@ -168,9 +169,8 @@ static int __init ks8695_pci_setup(int nr, struct pci_sys_data *sys)
request_resource(&iomem_resource, &pci_mem); request_resource(&iomem_resource, &pci_mem);
request_resource(&ioport_resource, &pci_io); request_resource(&ioport_resource, &pci_io);
sys->resource[0] = &pci_io; pci_add_resource(&sys->resources, &pci_io);
sys->resource[1] = &pci_mem; pci_add_resource(&sys->resources, &pci_mem);
sys->resource[2] = NULL;
/* Assign and enable processor bridge */ /* Assign and enable processor bridge */
ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA); ks8695_local_writeconfig(PCI_BASE_ADDRESS_0, KS8695_PCIMEM_PA);

View File

@ -155,9 +155,8 @@ static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
orion_pcie_set_local_bus_nr(pp->base, sys->busnr); orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
orion_pcie_setup(pp->base); orion_pcie_setup(pp->base);
sys->resource[0] = &pp->res[0]; pci_add_resource(&sys->resources, &pp->res[0]);
sys->resource[1] = &pp->res[1]; pci_add_resource(&sys->resources, &pp->res[1]);
sys->resource[2] = NULL;
return 1; return 1;
} }
@ -251,7 +250,8 @@ mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
struct pci_bus *bus; struct pci_bus *bus;
if (nr < num_pcie_ports) { if (nr < num_pcie_ports) {
bus = pci_scan_bus(sys->busnr, &pcie_ops, sys); bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
} else { } else {
bus = NULL; bus = NULL;
BUG(); BUG();

View File

@ -177,7 +177,7 @@ static int __init pcie_setup(struct pci_sys_data *sys)
res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1; res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0])) if (request_resource(&ioport_resource, &res[0]))
panic("Request PCIe IO resource failed\n"); panic("Request PCIe IO resource failed\n");
sys->resource[0] = &res[0]; pci_add_resource(&sys->resources, &res[0]);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
@ -188,9 +188,8 @@ static int __init pcie_setup(struct pci_sys_data *sys)
res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1; res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1])) if (request_resource(&iomem_resource, &res[1]))
panic("Request PCIe Memory resource failed\n"); panic("Request PCIe Memory resource failed\n");
sys->resource[1] = &res[1]; pci_add_resource(&sys->resources, &res[1]);
sys->resource[2] = NULL;
sys->io_offset = 0; sys->io_offset = 0;
return 1; return 1;
@ -506,7 +505,7 @@ static int __init pci_setup(struct pci_sys_data *sys)
res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1; res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
if (request_resource(&ioport_resource, &res[0])) if (request_resource(&ioport_resource, &res[0]))
panic("Request PCI IO resource failed\n"); panic("Request PCI IO resource failed\n");
sys->resource[0] = &res[0]; pci_add_resource(&sys->resources, &res[0]);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
@ -517,9 +516,8 @@ static int __init pci_setup(struct pci_sys_data *sys)
res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1; res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
if (request_resource(&iomem_resource, &res[1])) if (request_resource(&iomem_resource, &res[1]))
panic("Request PCI Memory resource failed\n"); panic("Request PCI Memory resource failed\n");
sys->resource[1] = &res[1]; pci_add_resource(&sys->resources, &res[1]);
sys->resource[2] = NULL;
sys->io_offset = 0; sys->io_offset = 0;
return 1; return 1;
@ -580,9 +578,11 @@ struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys
struct pci_bus *bus; struct pci_bus *bus;
if (nr == 0) { if (nr == 0) {
bus = pci_scan_bus(sys->busnr, &pcie_ops, sys); bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
} else if (nr == 1 && !orion5x_pci_disabled) { } else if (nr == 1 && !orion5x_pci_disabled) {
bus = pci_scan_bus(sys->busnr, &pci_ops, sys); bus = pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys,
&sys->resources);
} else { } else {
bus = NULL; bus = NULL;
BUG(); BUG();

View File

@ -131,7 +131,8 @@ static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot,
struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &pci_nano_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &pci_nano_ops, sys,
&sys->resources);
} }
static struct resource pci_io_ports = { static struct resource pci_io_ports = {
@ -226,7 +227,7 @@ static struct resource pci_prefetchable_memory = {
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
}; };
static int __init pci_nanoengine_setup_resources(struct resource **resource) static int __init pci_nanoengine_setup_resources(struct pci_sys_data *sys)
{ {
if (request_resource(&ioport_resource, &pci_io_ports)) { if (request_resource(&ioport_resource, &pci_io_ports)) {
printk(KERN_ERR "PCI: unable to allocate io port region\n"); printk(KERN_ERR "PCI: unable to allocate io port region\n");
@ -243,9 +244,9 @@ static int __init pci_nanoengine_setup_resources(struct resource **resource)
printk(KERN_ERR "PCI: unable to allocate prefetchable\n"); printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
return -EBUSY; return -EBUSY;
} }
resource[0] = &pci_io_ports; pci_add_resource(&sys->resources, &pci_io_ports);
resource[1] = &pci_non_prefetchable_memory; pci_add_resource(&sys->resources, &pci_non_prefetchable_memory);
resource[2] = &pci_prefetchable_memory; pci_add_resource(&sys->resources, &pci_prefetchable_memory);
return 1; return 1;
} }
@ -260,7 +261,7 @@ int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
if (nr == 0) { if (nr == 0) {
sys->mem_offset = NANO_PCI_MEM_RW_PHYS; sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
sys->io_offset = 0x400; sys->io_offset = 0x400;
ret = pci_nanoengine_setup_resources(sys->resource); ret = pci_nanoengine_setup_resources(sys);
/* Enable alternate memory bus master mode, see /* Enable alternate memory bus master mode, see
* "Intel StrongARM SA1110 Developer's Manual", * "Intel StrongARM SA1110 Developer's Manual",
* section 10.8, "Alternate Memory Bus Master Mode". */ * section 10.8, "Alternate Memory Bus Master Mode". */

View File

@ -408,7 +408,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[0].flags = IORESOURCE_IO; pp->res[0].flags = IORESOURCE_IO;
if (request_resource(&ioport_resource, &pp->res[0])) if (request_resource(&ioport_resource, &pp->res[0]))
panic("Request PCIe IO resource failed\n"); panic("Request PCIe IO resource failed\n");
sys->resource[0] = &pp->res[0]; pci_add_resource(&sys->resources, &pp->res[0]);
/* /*
* IORESOURCE_MEM * IORESOURCE_MEM
@ -427,7 +427,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[1].flags = IORESOURCE_MEM; pp->res[1].flags = IORESOURCE_MEM;
if (request_resource(&iomem_resource, &pp->res[1])) if (request_resource(&iomem_resource, &pp->res[1]))
panic("Request PCIe Memory resource failed\n"); panic("Request PCIe Memory resource failed\n");
sys->resource[1] = &pp->res[1]; pci_add_resource(&sys->resources, &pp->res[1]);
/* /*
* IORESOURCE_MEM | IORESOURCE_PREFETCH * IORESOURCE_MEM | IORESOURCE_PREFETCH
@ -446,7 +446,7 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH; pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
if (request_resource(&iomem_resource, &pp->res[2])) if (request_resource(&iomem_resource, &pp->res[2]))
panic("Request PCIe Prefetch Memory resource failed\n"); panic("Request PCIe Prefetch Memory resource failed\n");
sys->resource[2] = &pp->res[2]; pci_add_resource(&sys->resources, &pp->res[2]);
return 1; return 1;
} }
@ -467,7 +467,8 @@ static struct pci_bus __init *tegra_pcie_scan_bus(int nr,
pp = tegra_pcie.port + nr; pp = tegra_pcie.port + nr;
pp->root_bus_nr = sys->busnr; pp->root_bus_nr = sys->busnr;
return pci_scan_bus(sys->busnr, &tegra_pcie_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &tegra_pcie_ops, sys,
&sys->resources);
} }
static struct hw_pci tegra_pcie_hw __initdata = { static struct hw_pci tegra_pcie_hw __initdata = {

View File

@ -191,7 +191,7 @@ static struct resource pre_mem = {
.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH, .flags = IORESOURCE_MEM | IORESOURCE_PREFETCH,
}; };
static int __init pci_versatile_setup_resources(struct resource **resource) static int __init pci_versatile_setup_resources(struct list_head *resources)
{ {
int ret = 0; int ret = 0;
@ -215,13 +215,13 @@ static int __init pci_versatile_setup_resources(struct resource **resource)
} }
/* /*
* bus->resource[0] is the IO resource for this bus * the IO resource for this bus
* bus->resource[1] is the mem resource for this bus * the mem resource for this bus
* bus->resource[2] is the prefetch mem resource for this bus * the prefetch mem resource for this bus
*/ */
resource[0] = &io_mem; pci_add_resource(resources, &io_mem);
resource[1] = &non_mem; pci_add_resource(resources, &non_mem);
resource[2] = &pre_mem; pci_add_resource(resources, &pre_mem);
goto out; goto out;
@ -250,7 +250,7 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
if (nr == 0) { if (nr == 0) {
sys->mem_offset = 0; sys->mem_offset = 0;
ret = pci_versatile_setup_resources(sys->resource); ret = pci_versatile_setup_resources(&sys->resources);
if (ret < 0) { if (ret < 0) {
printk("pci_versatile_setup: resources... oops?\n"); printk("pci_versatile_setup: resources... oops?\n");
goto out; goto out;
@ -306,7 +306,8 @@ int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
struct pci_bus * __init pci_versatile_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus * __init pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &pci_versatile_ops, sys,
&sys->resources);
} }
void __init pci_versatile_preinit(void) void __init pci_versatile_preinit(void)

View File

@ -215,16 +215,16 @@ int iop3xx_pci_setup(int nr, struct pci_sys_data *sys)
sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0; sys->mem_offset = IOP3XX_PCI_LOWER_MEM_PA - *IOP3XX_OMWTVR0;
sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR; sys->io_offset = IOP3XX_PCI_LOWER_IO_PA - *IOP3XX_OIOWTVR;
sys->resource[0] = &res[0]; pci_add_resource(&sys->resources, &res[0]);
sys->resource[1] = &res[1]; pci_add_resource(&sys->resources, &res[1]);
sys->resource[2] = NULL;
return 1; return 1;
} }
struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys) struct pci_bus *iop3xx_pci_scan_bus(int nr, struct pci_sys_data *sys)
{ {
return pci_scan_bus(sys->busnr, &iop3xx_ops, sys); return pci_scan_root_bus(NULL, sys->busnr, &iop3xx_ops, sys,
&sys->resources);
} }
void __init iop3xx_atu_setup(void) void __init iop3xx_atu_setup(void)

View File

@ -10,10 +10,6 @@
#define PCIBIOS_MIN_IO 0x00001000 #define PCIBIOS_MIN_IO 0x00001000
#define PCIBIOS_MIN_MEM 0x10000000 #define PCIBIOS_MIN_MEM 0x10000000
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq) static inline void pcibios_penalize_isa_irq(int irq)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -194,23 +194,3 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(1); pcibios_allocate_resources(1);
pcibios_assign_resources(); pcibios_assign_resources();
} }
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}

View File

@ -26,8 +26,6 @@ extern unsigned int __nongpreldata pci_probe;
/* pci-frv.c */ /* pci-frv.c */
extern unsigned int pcibios_max_latency;
void pcibios_resource_survey(void); void pcibios_resource_survey(void);
/* pci-vdk.c */ /* pci-vdk.c */

View File

@ -327,11 +327,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number); printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
#endif #endif
if (bus->number == 0) {
bus->resource[0] = &pci_ioport_resource;
bus->resource[1] = &pci_iomem_resource;
}
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
if (bus->number == 0) { if (bus->number == 0) {
@ -357,6 +352,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
int __init pcibios_init(void) int __init pcibios_init(void)
{ {
struct pci_ops *dir = NULL; struct pci_ops *dir = NULL;
LIST_HEAD(resources);
if (!mb93090_mb00_detected) if (!mb93090_mb00_detected)
return -ENXIO; return -ENXIO;
@ -420,7 +416,10 @@ int __init pcibios_init(void)
} }
printk("PCI: Probing PCI hardware\n"); printk("PCI: Probing PCI hardware\n");
pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); pci_add_resource(&resources, &pci_ioport_resource);
pci_add_resource(&resources, &pci_iomem_resource);
pci_root_bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL,
&resources);
pcibios_irq_init(); pcibios_irq_init();
pcibios_fixup_peer_bridges(); pcibios_fixup_peer_bridges();

View File

@ -9,11 +9,6 @@
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -42,12 +42,6 @@ struct pci_dev;
extern unsigned long ia64_max_iommu_merge_mask; extern unsigned long ia64_max_iommu_merge_mask;
#define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL) #define PCI_DMA_BUS_IS_PHYS (ia64_max_iommu_merge_mask == ~0UL)
static inline void
pcibios_set_master (struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void static inline void
pcibios_penalize_isa_irq (int irq, int active) pcibios_penalize_isa_irq (int irq, int active)
{ {

View File

@ -134,6 +134,7 @@ alloc_pci_controller (int seg)
struct pci_root_info { struct pci_root_info {
struct acpi_device *bridge; struct acpi_device *bridge;
struct pci_controller *controller; struct pci_controller *controller;
struct list_head resources;
char *name; char *name;
}; };
@ -315,26 +316,15 @@ static __devinit acpi_status add_window(struct acpi_resource *res, void *data)
&window->resource); &window->resource);
} }
/* HP's firmware has a hack to work around a Windows bug.
* Ignore these tiny memory ranges */
if (!((window->resource.flags & IORESOURCE_MEM) &&
(window->resource.end - window->resource.start < 16)))
pci_add_resource(&info->resources, &window->resource);
return AE_OK; return AE_OK;
} }
static void __devinit
pcibios_setup_root_windows(struct pci_bus *bus, struct pci_controller *ctrl)
{
int i;
pci_bus_remove_resources(bus);
for (i = 0; i < ctrl->windows; i++) {
struct resource *res = &ctrl->window[i].resource;
/* HP's firmware has a hack to work around a Windows bug.
* Ignore these tiny memory ranges */
if ((res->flags & IORESOURCE_MEM) &&
(res->end - res->start < 16))
continue;
pci_bus_add_resource(bus, res, 0);
}
}
struct pci_bus * __devinit struct pci_bus * __devinit
pci_acpi_scan_root(struct acpi_pci_root *root) pci_acpi_scan_root(struct acpi_pci_root *root)
{ {
@ -343,6 +333,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
int bus = root->secondary.start; int bus = root->secondary.start;
struct pci_controller *controller; struct pci_controller *controller;
unsigned int windows = 0; unsigned int windows = 0;
struct pci_root_info info;
struct pci_bus *pbus; struct pci_bus *pbus;
char *name; char *name;
int pxm; int pxm;
@ -359,11 +350,10 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
controller->node = pxm_to_node(pxm); controller->node = pxm_to_node(pxm);
#endif #endif
INIT_LIST_HEAD(&info.resources);
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
&windows); &windows);
if (windows) { if (windows) {
struct pci_root_info info;
controller->window = controller->window =
kmalloc_node(sizeof(*controller->window) * windows, kmalloc_node(sizeof(*controller->window) * windows,
GFP_KERNEL, controller->node); GFP_KERNEL, controller->node);
@ -387,8 +377,14 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
* should handle the case here, but it appears that IA64 hasn't * should handle the case here, but it appears that IA64 hasn't
* such quirk. So we just ignore the case now. * such quirk. So we just ignore the case now.
*/ */
pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller); pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
&info.resources);
if (!pbus) {
pci_free_resource_list(&info.resources);
return NULL;
}
pbus->subordinate = pci_scan_child_bus(pbus);
return pbus; return pbus;
out3: out3:
@ -504,14 +500,15 @@ pcibios_fixup_bus (struct pci_bus *b)
if (b->self) { if (b->self) {
pci_read_bridge_bases(b); pci_read_bridge_bases(b);
pcibios_fixup_bridge_resources(b->self); pcibios_fixup_bridge_resources(b->self);
} else {
pcibios_setup_root_windows(b, b->sysdata);
} }
list_for_each_entry(dev, &b->devices, bus_list) list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev); pcibios_fixup_device_resources(dev);
platform_pci_fixup_bus(b); platform_pci_fixup_bus(b);
}
return; void pcibios_set_master (struct pci_dev *dev)
{
/* No special bus mastering setup handling */
} }
void __devinit void __devinit

View File

@ -140,7 +140,6 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
/* Allocate & free a PCI host bridge structure */ /* Allocate & free a PCI host bridge structure */
extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
extern void pcibios_free_controller(struct pci_controller *phb); extern void pcibios_free_controller(struct pci_controller *phb);
extern void pcibios_setup_phb_resources(struct pci_controller *hose);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_MICROBLAZE_PCI_BRIDGE_H */ #endif /* _ASM_MICROBLAZE_PCI_BRIDGE_H */

View File

@ -42,11 +42,6 @@ struct pci_dev;
*/ */
#define pcibios_assign_all_busses() 0 #define pcibios_assign_all_busses() 0
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -190,6 +190,11 @@ int pcibios_add_platform_entries(struct pci_dev *pdev)
return device_create_file(&pdev->dev, &dev_attr_devspec); return device_create_file(&pdev->dev, &dev_attr_devspec);
} }
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
char __devinit *pcibios_setup(char *str) char __devinit *pcibios_setup(char *str)
{ {
return str; return str;
@ -1019,7 +1024,6 @@ static void __devinit pcibios_fixup_bridge(struct pci_bus *bus)
struct pci_dev *dev = bus->self; struct pci_dev *dev = bus->self;
pci_bus_for_each_resource(bus, res, i) { pci_bus_for_each_resource(bus, res, i) {
res = bus->resource[i];
if (!res) if (!res)
continue; continue;
if (!res->flags) if (!res->flags)
@ -1219,7 +1223,6 @@ void pcibios_allocate_bus_resources(struct pci_bus *bus)
pci_domain_nr(bus), bus->number); pci_domain_nr(bus), bus->number);
pci_bus_for_each_resource(bus, res, i) { pci_bus_for_each_resource(bus, res, i) {
res = bus->resource[i];
if (!res || !res->flags if (!res || !res->flags
|| res->start > res->end || res->parent) || res->start > res->end || res->parent)
continue; continue;
@ -1510,14 +1513,18 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pci_enable_resources(dev, mask); return pci_enable_resources(dev, mask);
} }
void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
{ {
struct pci_bus *bus = hose->bus;
struct resource *res; struct resource *res;
int i; int i;
/* Hookup PHB IO resource */ /* Hookup PHB IO resource */
bus->resource[0] = res = &hose->io_resource; res = &hose->io_resource;
/* Fixup IO space offset */
io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
res->start = (res->start + io_offset) & 0xffffffffu;
res->end = (res->end + io_offset) & 0xffffffffu;
if (!res->flags) { if (!res->flags) {
printk(KERN_WARNING "PCI: I/O resource not set for host" printk(KERN_WARNING "PCI: I/O resource not set for host"
@ -1528,6 +1535,7 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
res->end = res->start + IO_SPACE_LIMIT; res->end = res->start + IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO; res->flags = IORESOURCE_IO;
} }
pci_add_resource(resources, res);
pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n", pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n",
(unsigned long long)res->start, (unsigned long long)res->start,
@ -1550,7 +1558,7 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
} }
bus->resource[i+1] = res; pci_add_resource(resources, res);
pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n",
i, (unsigned long long)res->start, i, (unsigned long long)res->start,
@ -1573,34 +1581,27 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
static void __devinit pcibios_scan_phb(struct pci_controller *hose) static void __devinit pcibios_scan_phb(struct pci_controller *hose)
{ {
LIST_HEAD(resources);
struct pci_bus *bus; struct pci_bus *bus;
struct device_node *node = hose->dn; struct device_node *node = hose->dn;
unsigned long io_offset;
struct resource *res = &hose->io_resource;
pr_debug("PCI: Scanning PHB %s\n", pr_debug("PCI: Scanning PHB %s\n",
node ? node->full_name : "<NO NAME>"); node ? node->full_name : "<NO NAME>");
/* Create an empty bus for the toplevel */ pcibios_setup_phb_resources(hose, &resources);
bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
bus = pci_scan_root_bus(hose->parent, hose->first_busno,
hose->ops, hose, &resources);
if (bus == NULL) { if (bus == NULL) {
printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
hose->global_number); hose->global_number);
pci_free_resource_list(&resources);
return; return;
} }
bus->secondary = hose->first_busno; bus->secondary = hose->first_busno;
hose->bus = bus; hose->bus = bus;
/* Fixup IO space offset */ hose->last_busno = bus->subordinate;
io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
res->start = (res->start + io_offset) & 0xffffffffu;
res->end = (res->end + io_offset) & 0xffffffffu;
/* Wire up PHB bus resources */
pcibios_setup_phb_resources(hose);
/* Scan children */
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
} }
static int __init pcibios_init(void) static int __init pcibios_init(void)
@ -1614,8 +1615,6 @@ static int __init pcibios_init(void)
list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
hose->last_busno = 0xff; hose->last_busno = 0xff;
pcibios_scan_phb(hose); pcibios_scan_phb(hose);
printk(KERN_INFO "calling pci_bus_add_devices()\n");
pci_bus_add_devices(hose->bus);
if (next_busno <= hose->last_busno) if (next_busno <= hose->last_busno)
next_busno = hose->last_busno + 1; next_busno = hose->last_busno + 1;
} }

View File

@ -81,6 +81,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
{ {
static int next_busno; static int next_busno;
static int need_domain_info; static int need_domain_info;
LIST_HEAD(resources);
struct pci_bus *bus; struct pci_bus *bus;
if (!hose->iommu) if (!hose->iommu)
@ -89,7 +90,13 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
if (hose->get_busno && pci_probe_only) if (hose->get_busno && pci_probe_only)
next_busno = (*hose->get_busno)(); next_busno = (*hose->get_busno)();
bus = pci_scan_bus(next_busno, hose->pci_ops, hose); pci_add_resource(&resources, hose->mem_resource);
pci_add_resource(&resources, hose->io_resource);
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
if (!bus)
pci_free_resource_list(&resources);
hose->bus = bus; hose->bus = bus;
need_domain_info = need_domain_info || hose->index; need_domain_info = need_domain_info || hose->index;
@ -205,27 +212,6 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask)
return 0; return 0;
} }
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
static unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
printk(KERN_DEBUG "PCI: Setting latency timer of device %s to %d\n",
pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
unsigned int pcibios_assign_all_busses(void) unsigned int pcibios_assign_all_busses(void)
{ {
return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0; return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
@ -266,15 +252,11 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{ {
/* Propagate hose info into the subordinate devices. */ /* Propagate hose info into the subordinate devices. */
struct pci_controller *hose = bus->sysdata;
struct list_head *ln; struct list_head *ln;
struct pci_dev *dev = bus->self; struct pci_dev *dev = bus->self;
if (!dev) { if (pci_probe_only && dev &&
bus->resource[0] = hose->io_resource; (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
bus->resource[1] = hose->mem_resource;
} else if (pci_probe_only &&
(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(dev, bus); pcibios_fixup_device_resources(dev, bus);
} }

View File

@ -213,28 +213,6 @@ void __init pcibios_resource_survey(void)
pcibios_allocate_resources(1); pcibios_allocate_resources(1);
} }
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine) enum pci_mmap_state mmap_state, int write_combine)
{ {

View File

@ -31,8 +31,6 @@ extern unsigned int pci_probe;
/* pci-asb2305.c */ /* pci-asb2305.c */
extern unsigned int pcibios_max_latency;
extern void pcibios_resource_survey(void); extern void pcibios_resource_survey(void);
/* pci.c */ /* pci.c */

View File

@ -380,11 +380,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{ {
struct pci_dev *dev; struct pci_dev *dev;
if (bus->number == 0) {
bus->resource[0] = &pci_ioport_resource;
bus->resource[1] = &pci_iomem_resource;
}
if (bus->self) { if (bus->self) {
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
pcibios_fixup_device_resources(bus->self); pcibios_fixup_device_resources(bus->self);
@ -402,6 +397,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
*/ */
static int __init pcibios_init(void) static int __init pcibios_init(void)
{ {
LIST_HEAD(resources);
ioport_resource.start = 0xA0000000; ioport_resource.start = 0xA0000000;
ioport_resource.end = 0xDFFFFFFF; ioport_resource.end = 0xDFFFFFFF;
iomem_resource.start = 0xA0000000; iomem_resource.start = 0xA0000000;
@ -423,7 +420,10 @@ static int __init pcibios_init(void)
printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n", printk(KERN_INFO "PCI: Probing PCI hardware [mempage %08x]\n",
MEM_PAGING_REG); MEM_PAGING_REG);
pci_root_bus = pci_scan_bus(0, &pci_direct_ampci, NULL); pci_add_resource(&resources, &pci_ioport_resource);
pci_add_resource(&resources, &pci_iomem_resource);
pci_root_bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL,
&resources);
pcibios_irq_init(); pcibios_irq_init();
pcibios_fixup_irqs(); pcibios_fixup_irqs();

View File

@ -226,7 +226,6 @@ extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
/* Allocate & free a PCI host bridge structure */ /* Allocate & free a PCI host bridge structure */
extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev); extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
extern void pcibios_free_controller(struct pci_controller *phb); extern void pcibios_free_controller(struct pci_controller *phb);
extern void pcibios_setup_phb_resources(struct pci_controller *hose);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
extern int pcibios_vaddr_is_ioport(void __iomem *address); extern int pcibios_vaddr_is_ioport(void __iomem *address);

View File

@ -46,11 +46,6 @@ struct pci_dev;
#define pcibios_assign_all_busses() \ #define pcibios_assign_all_busses() \
(pci_has_flag(PCI_REASSIGN_ALL_BUS)) (pci_has_flag(PCI_REASSIGN_ALL_BUS))
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -1131,6 +1131,11 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
} }
} }
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
void __devinit pcibios_fixup_bus(struct pci_bus *bus) void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{ {
/* When called from the generic PCI probe, read PCI<->PCI bridge /* When called from the generic PCI probe, read PCI<->PCI bridge
@ -1560,14 +1565,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pci_enable_resources(dev, mask); return pci_enable_resources(dev, mask);
} }
void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) static void __devinit pcibios_setup_phb_resources(struct pci_controller *hose, struct list_head *resources)
{ {
struct pci_bus *bus = hose->bus;
struct resource *res; struct resource *res;
int i; int i;
/* Hookup PHB IO resource */ /* Hookup PHB IO resource */
bus->resource[0] = res = &hose->io_resource; res = &hose->io_resource;
if (!res->flags) { if (!res->flags) {
printk(KERN_WARNING "PCI: I/O resource not set for host" printk(KERN_WARNING "PCI: I/O resource not set for host"
@ -1585,6 +1589,7 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
(unsigned long long)res->start, (unsigned long long)res->start,
(unsigned long long)res->end, (unsigned long long)res->end,
(unsigned long)res->flags); (unsigned long)res->flags);
pci_add_resource(resources, res);
/* Hookup PHB Memory resources */ /* Hookup PHB Memory resources */
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
@ -1602,12 +1607,12 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
res->flags = IORESOURCE_MEM; res->flags = IORESOURCE_MEM;
#endif /* CONFIG_PPC32 */ #endif /* CONFIG_PPC32 */
} }
bus->resource[i+1] = res;
pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i, pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n", i,
(unsigned long long)res->start, (unsigned long long)res->start,
(unsigned long long)res->end, (unsigned long long)res->end,
(unsigned long)res->flags); (unsigned long)res->flags);
pci_add_resource(resources, res);
} }
pr_debug("PCI: PHB MEM offset = %016llx\n", pr_debug("PCI: PHB MEM offset = %016llx\n",
@ -1701,6 +1706,7 @@ struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus)
*/ */
void __devinit pcibios_scan_phb(struct pci_controller *hose) void __devinit pcibios_scan_phb(struct pci_controller *hose)
{ {
LIST_HEAD(resources);
struct pci_bus *bus; struct pci_bus *bus;
struct device_node *node = hose->dn; struct device_node *node = hose->dn;
int mode; int mode;
@ -1708,21 +1714,23 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
pr_debug("PCI: Scanning PHB %s\n", pr_debug("PCI: Scanning PHB %s\n",
node ? node->full_name : "<NO NAME>"); node ? node->full_name : "<NO NAME>");
/* Create an empty bus for the toplevel */
bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
if (bus == NULL) {
pr_err("Failed to create bus for PCI domain %04x\n",
hose->global_number);
return;
}
bus->secondary = hose->first_busno;
hose->bus = bus;
/* Get some IO space for the new PHB */ /* Get some IO space for the new PHB */
pcibios_setup_phb_io_space(hose); pcibios_setup_phb_io_space(hose);
/* Wire up PHB bus resources */ /* Wire up PHB bus resources */
pcibios_setup_phb_resources(hose); pcibios_setup_phb_resources(hose, &resources);
/* Create an empty bus for the toplevel */
bus = pci_create_root_bus(hose->parent, hose->first_busno,
hose->ops, hose, &resources);
if (bus == NULL) {
pr_err("Failed to create bus for PCI domain %04x\n",
hose->global_number);
pci_free_resource_list(&resources);
return;
}
bus->secondary = hose->first_busno;
hose->bus = bus;
/* Get probe mode and perform scan */ /* Get probe mode and perform scan */
mode = PCI_PROBE_NORMAL; mode = PCI_PROBE_NORMAL;

View File

@ -131,30 +131,13 @@ EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
#endif /* CONFIG_HOTPLUG */ #endif /* CONFIG_HOTPLUG */
int __devinit pcibios_map_io_space(struct pci_bus *bus) static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
{ {
struct vm_struct *area; struct vm_struct *area;
unsigned long phys_page; unsigned long phys_page;
unsigned long size_page; unsigned long size_page;
unsigned long io_virt_offset; unsigned long io_virt_offset;
struct pci_controller *hose;
WARN_ON(bus == NULL);
/* If this not a PHB, nothing to do, page tables still exist and
* thus HPTEs will be faulted in when needed
*/
if (bus->self) {
pr_debug("IO mapping for PCI-PCI bridge %s\n",
pci_name(bus->self));
pr_debug(" virt=0x%016llx...0x%016llx\n",
bus->resource[0]->start + _IO_BASE,
bus->resource[0]->end + _IO_BASE);
return 0;
}
/* Get the host bridge */
hose = pci_bus_to_host(bus);
phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE); phys_page = _ALIGN_DOWN(hose->io_base_phys, PAGE_SIZE);
size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE); size_page = _ALIGN_UP(hose->pci_io_size, PAGE_SIZE);
@ -198,11 +181,30 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
return 0; return 0;
} }
int __devinit pcibios_map_io_space(struct pci_bus *bus)
{
WARN_ON(bus == NULL);
/* If this not a PHB, nothing to do, page tables still exist and
* thus HPTEs will be faulted in when needed
*/
if (bus->self) {
pr_debug("IO mapping for PCI-PCI bridge %s\n",
pci_name(bus->self));
pr_debug(" virt=0x%016llx...0x%016llx\n",
bus->resource[0]->start + _IO_BASE,
bus->resource[0]->end + _IO_BASE);
return 0;
}
return pcibios_map_phb_io_space(pci_bus_to_host(bus));
}
EXPORT_SYMBOL_GPL(pcibios_map_io_space); EXPORT_SYMBOL_GPL(pcibios_map_io_space);
void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose) void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
{ {
pcibios_map_io_space(hose->bus); pcibios_map_phb_io_space(hose);
} }
#define IOBASE_BRIDGE_NUMBER 0 #define IOBASE_BRIDGE_NUMBER 0

View File

@ -36,9 +36,15 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
{ {
static int next_busno; static int next_busno;
static int need_domain_info; static int need_domain_info;
LIST_HEAD(resources);
int i;
struct pci_bus *bus; struct pci_bus *bus;
bus = pci_scan_bus(next_busno, hose->pci_ops, hose); for (i = 0; i < hose->nr_resources; i++)
pci_add_resource(&resources, hose->resources + i);
bus = pci_scan_root_bus(NULL, next_busno, hose->pci_ops, hose,
&resources);
hose->bus = bus; hose->bus = bus;
need_domain_info = need_domain_info || hose->index; need_domain_info = need_domain_info || hose->index;
@ -55,6 +61,8 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
pci_enable_bridges(bus); pci_enable_bridges(bus);
} else {
pci_free_resource_list(&resources);
} }
} }
@ -162,16 +170,8 @@ static void pcibios_fixup_device_resources(struct pci_dev *dev,
*/ */
void __devinit pcibios_fixup_bus(struct pci_bus *bus) void __devinit pcibios_fixup_bus(struct pci_bus *bus)
{ {
struct pci_dev *dev = bus->self; struct pci_dev *dev;
struct list_head *ln; struct list_head *ln;
struct pci_channel *hose = bus->sysdata;
if (!dev) {
int i;
for (i = 0; i < hose->nr_resources; i++)
bus->resource[i] = hose->resources + i;
}
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
dev = pci_dev_b(ln); dev = pci_dev_b(ln);
@ -243,27 +243,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
return pci_enable_resources(dev, mask); return pci_enable_resources(dev, mask);
} }
/*
* If we set up a device for bus mastering, we need to check and set
* the latency timer as it may not be properly set.
*/
static unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n",
pci_name(dev), lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
void __init pcibios_update_irq(struct pci_dev *dev, int irq) void __init pcibios_update_irq(struct pci_dev *dev, int irq)
{ {
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);

View File

@ -16,11 +16,6 @@
#define PCI_IRQ_NONE 0xffffffff #define PCI_IRQ_NONE 0xffffffff
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -16,11 +16,6 @@
#define PCI_IRQ_NONE 0xffffffff #define PCI_IRQ_NONE 0xffffffff
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -19,22 +19,22 @@
*/ */
void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info) void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
{ {
LIST_HEAD(resources);
struct pci_bus *root_bus; struct pci_bus *root_bus;
root_bus = pci_scan_bus_parented(&ofdev->dev, 0, info->ops, info); pci_add_resource(&resources, &info->io_space);
pci_add_resource(&resources, &info->mem_space);
root_bus = pci_scan_root_bus(&ofdev->dev, 0, info->ops, info,
&resources);
if (root_bus) { if (root_bus) {
root_bus->resource[0] = &info->io_space;
root_bus->resource[1] = &info->mem_space;
root_bus->resource[2] = NULL;
/* Init all PCI devices into PCI tree */
pci_bus_add_devices(root_bus);
/* Setup IRQs of all devices using custom routines */ /* Setup IRQs of all devices using custom routines */
pci_fixup_irqs(pci_common_swizzle, info->map_irq); pci_fixup_irqs(pci_common_swizzle, info->map_irq);
/* Assign devices with resources */ /* Assign devices with resources */
pci_assign_unassigned_resources(); pci_assign_unassigned_resources();
} else {
pci_free_resource_list(&resources);
} }
} }
@ -83,15 +83,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
int i, has_io, has_mem; int i, has_io, has_mem;
u16 cmd; u16 cmd;
/* Generic PCI bus probing sets these to point at
* &io{port,mem}_resouce which is wrong for us.
*/
if (pbus->self == NULL) {
pbus->resource[0] = &info->io_space;
pbus->resource[1] = &info->mem_space;
pbus->resource[2] = NULL;
}
list_for_each_entry(dev, &pbus->devices, bus_list) { list_for_each_entry(dev, &pbus->devices, bus_list) {
/* /*
* We can not rely on that the bootloader has enabled I/O * We can not rely on that the bootloader has enabled I/O

View File

@ -685,23 +685,25 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus)
struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
struct device *parent) struct device *parent)
{ {
LIST_HEAD(resources);
struct device_node *node = pbm->op->dev.of_node; struct device_node *node = pbm->op->dev.of_node;
struct pci_bus *bus; struct pci_bus *bus;
printk("PCI: Scanning PBM %s\n", node->full_name); printk("PCI: Scanning PBM %s\n", node->full_name);
bus = pci_create_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm); pci_add_resource(&resources, &pbm->io_space);
pci_add_resource(&resources, &pbm->mem_space);
bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
pbm, &resources);
if (!bus) { if (!bus) {
printk(KERN_ERR "Failed to create bus for %s\n", printk(KERN_ERR "Failed to create bus for %s\n",
node->full_name); node->full_name);
pci_free_resource_list(&resources);
return NULL; return NULL;
} }
bus->secondary = pbm->pci_first_busno; bus->secondary = pbm->pci_first_busno;
bus->subordinate = pbm->pci_last_busno; bus->subordinate = pbm->pci_last_busno;
bus->resource[0] = &pbm->io_space;
bus->resource[1] = &pbm->mem_space;
pci_of_scan_bus(pbm, node, bus); pci_of_scan_bus(pbm, node, bus);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
pci_bus_register_of_sysfs(bus); pci_bus_register_of_sysfs(bus);
@ -711,13 +713,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
void __devinit pcibios_fixup_bus(struct pci_bus *pbus) void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
{ {
struct pci_pbm_info *pbm = pbus->sysdata;
/* Generic PCI bus probing sets these to point at
* &io{port,mem}_resouce which is wrong for us.
*/
pbus->resource[0] = &pbm->io_space;
pbus->resource[1] = &pbm->mem_space;
} }
void pcibios_update_irq(struct pci_dev *pdev, int irq) void pcibios_update_irq(struct pci_dev *pdev, int irq)
@ -1083,6 +1078,11 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar,
*end = rp->end - offset; *end = rp->end - offset;
} }
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static int __init pcibios_init(void) static int __init pcibios_init(void)
{ {
pci_dfl_cache_line_size = 64 >> 2; pci_dfl_cache_line_size = 64 >> 2;

View File

@ -76,13 +76,6 @@ static inline int pcibios_assign_all_busses(void)
return 1; return 1;
} }
/*
* No special bus mastering setup handling.
*/
static inline void pcibios_set_master(struct pci_dev *dev)
{
}
#define PCIBIOS_MIN_MEM 0 #define PCIBIOS_MIN_MEM 0
#define PCIBIOS_MIN_IO 0 #define PCIBIOS_MIN_IO 0

View File

@ -395,6 +395,11 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
/* Nothing needs to be done. */ /* Nothing needs to be done. */
} }
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling. */
}
/* /*
* This can be called from the generic PCI layer, but doesn't need to * This can be called from the generic PCI layer, but doesn't need to
* do anything. * do anything.

View File

@ -17,11 +17,6 @@
#include <asm-generic/pci.h> #include <asm-generic/pci.h>
#include <mach/hardware.h> /* for PCIBIOS_MIN_* */ #include <mach/hardware.h> /* for PCIBIOS_MIN_* */
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq, int active) static inline void pcibios_penalize_isa_irq(int irq, int active)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -309,6 +309,11 @@ char * __devinit pcibios_setup(char *str)
return str; return str;
} }
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
/* /*
* From arch/i386/kernel/pci-i386.c: * From arch/i386/kernel/pci-i386.c:
* *

View File

@ -1,6 +1,7 @@
#ifndef _ASM_X86_AMD_NB_H #ifndef _ASM_X86_AMD_NB_H
#define _ASM_X86_AMD_NB_H #define _ASM_X86_AMD_NB_H
#include <linux/ioport.h>
#include <linux/pci.h> #include <linux/pci.h>
struct amd_nb_bus_dev_range { struct amd_nb_bus_dev_range {
@ -13,6 +14,7 @@ extern const struct pci_device_id amd_nb_misc_ids[];
extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[]; extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[];
extern bool early_is_amd_nb(u32 value); extern bool early_is_amd_nb(u32 value);
extern struct resource *amd_get_mmconfig_range(struct resource *res);
extern int amd_cache_northbridges(void); extern int amd_cache_northbridges(void);
extern void amd_flush_garts(void); extern void amd_flush_garts(void);
extern int amd_numa_init(void); extern int amd_numa_init(void);

View File

@ -112,19 +112,28 @@ static inline void x86_teardown_msi_irq(unsigned int irq)
{ {
x86_msi.teardown_msi_irq(irq); x86_msi.teardown_msi_irq(irq);
} }
static inline void x86_restore_msi_irqs(struct pci_dev *dev, int irq)
{
x86_msi.restore_msi_irqs(dev, irq);
}
#define arch_setup_msi_irqs x86_setup_msi_irqs #define arch_setup_msi_irqs x86_setup_msi_irqs
#define arch_teardown_msi_irqs x86_teardown_msi_irqs #define arch_teardown_msi_irqs x86_teardown_msi_irqs
#define arch_teardown_msi_irq x86_teardown_msi_irq #define arch_teardown_msi_irq x86_teardown_msi_irq
#define arch_restore_msi_irqs x86_restore_msi_irqs
/* implemented in arch/x86/kernel/apic/io_apic. */ /* implemented in arch/x86/kernel/apic/io_apic. */
int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type);
void native_teardown_msi_irq(unsigned int irq); void native_teardown_msi_irq(unsigned int irq);
void native_restore_msi_irqs(struct pci_dev *dev, int irq);
/* default to the implementation in drivers/lib/msi.c */ /* default to the implementation in drivers/lib/msi.c */
#define HAVE_DEFAULT_MSI_TEARDOWN_IRQS #define HAVE_DEFAULT_MSI_TEARDOWN_IRQS
#define HAVE_DEFAULT_MSI_RESTORE_IRQS
void default_teardown_msi_irqs(struct pci_dev *dev); void default_teardown_msi_irqs(struct pci_dev *dev);
void default_restore_msi_irqs(struct pci_dev *dev, int irq);
#else #else
#define native_setup_msi_irqs NULL #define native_setup_msi_irqs NULL
#define native_teardown_msi_irq NULL #define native_teardown_msi_irq NULL
#define default_teardown_msi_irqs NULL #define default_teardown_msi_irqs NULL
#define default_restore_msi_irqs NULL
#endif #endif
#define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys) #define PCI_DMA_BUS_IS_PHYS (dma_ops->is_phys)

View File

@ -44,8 +44,6 @@ enum pci_bf_sort_state {
/* pci-i386.c */ /* pci-i386.c */
extern unsigned int pcibios_max_latency;
void pcibios_resource_survey(void); void pcibios_resource_survey(void);
void pcibios_set_cache_line_size(void); void pcibios_set_cache_line_size(void);

View File

@ -172,7 +172,7 @@ static inline void arch_fix_phys_package_id(int num, u32 slot)
} }
struct pci_bus; struct pci_bus;
void x86_pci_root_bus_res_quirks(struct pci_bus *b); void x86_pci_root_bus_resources(int bus, struct list_head *resources);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define mc_capable() ((boot_cpu_data.x86_max_cores > 1) && \ #define mc_capable() ((boot_cpu_data.x86_max_cores > 1) && \

View File

@ -179,6 +179,7 @@ struct x86_msi_ops {
int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type); int (*setup_msi_irqs)(struct pci_dev *dev, int nvec, int type);
void (*teardown_msi_irq)(unsigned int irq); void (*teardown_msi_irq)(unsigned int irq);
void (*teardown_msi_irqs)(struct pci_dev *dev); void (*teardown_msi_irqs)(struct pci_dev *dev);
void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
}; };
extern struct x86_init_ops x86_init; extern struct x86_init_ops x86_init;

View File

@ -119,6 +119,37 @@ bool __init early_is_amd_nb(u32 device)
return false; return false;
} }
struct resource *amd_get_mmconfig_range(struct resource *res)
{
u32 address;
u64 base, msr;
unsigned segn_busn_bits;
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return NULL;
/* assume all cpus from fam10h have mmconfig */
if (boot_cpu_data.x86 < 0x10)
return NULL;
address = MSR_FAM10H_MMIO_CONF_BASE;
rdmsrl(address, msr);
/* mmconfig is not enabled */
if (!(msr & FAM10H_MMIO_CONF_ENABLE))
return NULL;
base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
FAM10H_MMIO_CONF_BUSRANGE_MASK;
res->flags = IORESOURCE_MEM;
res->start = base;
res->end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
return res;
}
int amd_get_subcaches(int cpu) int amd_get_subcaches(int cpu)
{ {
struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link; struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;

View File

@ -115,4 +115,5 @@ struct x86_msi_ops x86_msi = {
.setup_msi_irqs = native_setup_msi_irqs, .setup_msi_irqs = native_setup_msi_irqs,
.teardown_msi_irq = native_teardown_msi_irq, .teardown_msi_irq = native_teardown_msi_irq,
.teardown_msi_irqs = default_teardown_msi_irqs, .teardown_msi_irqs = default_teardown_msi_irqs,
.restore_msi_irqs = default_restore_msi_irqs,
}; };

View File

@ -12,7 +12,7 @@ struct pci_root_info {
char *name; char *name;
unsigned int res_num; unsigned int res_num;
struct resource *res; struct resource *res;
struct pci_bus *bus; struct list_head *resources;
int busnum; int busnum;
}; };
@ -24,6 +24,12 @@ static int __init set_use_crs(const struct dmi_system_id *id)
return 0; return 0;
} }
static int __init set_nouse_crs(const struct dmi_system_id *id)
{
pci_use_crs = false;
return 0;
}
static const struct dmi_system_id pci_use_crs_table[] __initconst = { static const struct dmi_system_id pci_use_crs_table[] __initconst = {
/* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */ /* http://bugzilla.kernel.org/show_bug.cgi?id=14183 */
{ {
@ -54,6 +60,29 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."), DMI_MATCH(DMI_BIOS_VENDOR, "American Megatrends Inc."),
}, },
}, },
/* Now for the blacklist.. */
/* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */
{
.callback = set_nouse_crs,
.ident = "Dell Studio 1557",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Dell Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"),
DMI_MATCH(DMI_BIOS_VERSION, "A09"),
},
},
/* https://bugzilla.redhat.com/show_bug.cgi?id=769657 */
{
.callback = set_nouse_crs,
.ident = "Thinkpad SL510",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_BOARD_NAME, "2847DFG"),
DMI_MATCH(DMI_BIOS_VERSION, "6JET85WW (1.43 )"),
},
},
{} {}
}; };
@ -149,7 +178,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
struct acpi_resource_address64 addr; struct acpi_resource_address64 addr;
acpi_status status; acpi_status status;
unsigned long flags; unsigned long flags;
u64 start, end; u64 start, orig_end, end;
status = resource_to_addr(acpi_res, &addr); status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status)) if (!ACPI_SUCCESS(status))
@ -165,7 +194,21 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
return AE_OK; return AE_OK;
start = addr.minimum + addr.translation_offset; start = addr.minimum + addr.translation_offset;
end = addr.maximum + addr.translation_offset; orig_end = end = addr.maximum + addr.translation_offset;
/* Exclude non-addressable range or non-addressable portion of range */
end = min(end, (u64)iomem_resource.end);
if (end <= start) {
dev_info(&info->bridge->dev,
"host bridge window [%#llx-%#llx] "
"(ignored, not CPU addressable)\n", start, orig_end);
return AE_OK;
} else if (orig_end != end) {
dev_info(&info->bridge->dev,
"host bridge window [%#llx-%#llx] "
"([%#llx-%#llx] ignored, not CPU addressable)\n",
start, orig_end, end + 1, orig_end);
}
res = &info->res[info->res_num]; res = &info->res[info->res_num];
res->name = info->name; res->name = info->name;
@ -261,23 +304,20 @@ static void add_resources(struct pci_root_info *info)
"ignoring host bridge window %pR (conflicts with %s %pR)\n", "ignoring host bridge window %pR (conflicts with %s %pR)\n",
res, conflict->name, conflict); res, conflict->name, conflict);
else else
pci_bus_add_resource(info->bus, res, 0); pci_add_resource(info->resources, res);
} }
} }
static void static void
get_current_resources(struct acpi_device *device, int busnum, get_current_resources(struct acpi_device *device, int busnum,
int domain, struct pci_bus *bus) int domain, struct list_head *resources)
{ {
struct pci_root_info info; struct pci_root_info info;
size_t size; size_t size;
if (pci_use_crs)
pci_bus_remove_resources(bus);
info.bridge = device; info.bridge = device;
info.bus = bus;
info.res_num = 0; info.res_num = 0;
info.resources = resources;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
&info); &info);
if (!info.res_num) if (!info.res_num)
@ -286,7 +326,7 @@ get_current_resources(struct acpi_device *device, int busnum,
size = sizeof(*info.res) * info.res_num; size = sizeof(*info.res) * info.res_num;
info.res = kmalloc(size, GFP_KERNEL); info.res = kmalloc(size, GFP_KERNEL);
if (!info.res) if (!info.res)
goto res_alloc_fail; return;
info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum); info.name = kasprintf(GFP_KERNEL, "PCI Bus %04x:%02x", domain, busnum);
if (!info.name) if (!info.name)
@ -301,8 +341,6 @@ get_current_resources(struct acpi_device *device, int busnum,
name_alloc_fail: name_alloc_fail:
kfree(info.res); kfree(info.res);
res_alloc_fail:
return;
} }
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
@ -310,6 +348,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
struct acpi_device *device = root->device; struct acpi_device *device = root->device;
int domain = root->segment; int domain = root->segment;
int busnum = root->secondary.start; int busnum = root->secondary.start;
LIST_HEAD(resources);
struct pci_bus *bus; struct pci_bus *bus;
struct pci_sysdata *sd; struct pci_sysdata *sd;
int node; int node;
@ -364,11 +403,15 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
memcpy(bus->sysdata, sd, sizeof(*sd)); memcpy(bus->sysdata, sd, sizeof(*sd));
kfree(sd); kfree(sd);
} else { } else {
bus = pci_create_bus(NULL, busnum, &pci_root_ops, sd); get_current_resources(device, busnum, domain, &resources);
if (bus) { if (list_empty(&resources))
get_current_resources(device, busnum, domain, bus); x86_pci_root_bus_resources(busnum, &resources);
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources);
if (bus)
bus->subordinate = pci_scan_child_bus(bus); bus->subordinate = pci_scan_child_bus(bus);
} else
pci_free_resource_list(&resources);
} }
/* After the PCI-E bus has been walked and all devices discovered, /* After the PCI-E bus has been walked and all devices discovered,

View File

@ -30,34 +30,6 @@ static struct pci_hostbridge_probe pci_probes[] __initdata = {
{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 },
}; };
static u64 __initdata fam10h_mmconf_start;
static u64 __initdata fam10h_mmconf_end;
static void __init get_pci_mmcfg_amd_fam10h_range(void)
{
u32 address;
u64 base, msr;
unsigned segn_busn_bits;
/* assume all cpus from fam10h have mmconf */
if (boot_cpu_data.x86 < 0x10)
return;
address = MSR_FAM10H_MMIO_CONF_BASE;
rdmsrl(address, msr);
/* mmconfig is not enable */
if (!(msr & FAM10H_MMIO_CONF_ENABLE))
return;
base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT);
segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) &
FAM10H_MMIO_CONF_BUSRANGE_MASK;
fam10h_mmconf_start = base;
fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1;
}
#define RANGE_NUM 16 #define RANGE_NUM 16
/** /**
@ -85,6 +57,9 @@ static int __init early_fill_mp_bus_info(void)
u64 val; u64 val;
u32 address; u32 address;
bool found; bool found;
struct resource fam10h_mmconf_res, *fam10h_mmconf;
u64 fam10h_mmconf_start;
u64 fam10h_mmconf_end;
if (!early_pci_allowed()) if (!early_pci_allowed())
return -1; return -1;
@ -211,12 +186,17 @@ static int __init early_fill_mp_bus_info(void)
subtract_range(range, RANGE_NUM, 0, end); subtract_range(range, RANGE_NUM, 0, end);
/* get mmconfig */ /* get mmconfig */
get_pci_mmcfg_amd_fam10h_range(); fam10h_mmconf = amd_get_mmconfig_range(&fam10h_mmconf_res);
/* need to take out mmconf range */ /* need to take out mmconf range */
if (fam10h_mmconf_end) { if (fam10h_mmconf) {
printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end); printk(KERN_DEBUG "Fam 10h mmconf %pR\n", fam10h_mmconf);
fam10h_mmconf_start = fam10h_mmconf->start;
fam10h_mmconf_end = fam10h_mmconf->end;
subtract_range(range, RANGE_NUM, fam10h_mmconf_start, subtract_range(range, RANGE_NUM, fam10h_mmconf_start,
fam10h_mmconf_end + 1); fam10h_mmconf_end + 1);
} else {
fam10h_mmconf_start = 0;
fam10h_mmconf_end = 0;
} }
/* mmio resource */ /* mmio resource */
@ -403,7 +383,6 @@ static void __init pci_enable_pci_io_ecs(void)
++n; ++n;
} }
} }
pr_info("Extended Config Space enabled on %u nodes\n", n);
#endif #endif
} }

View File

@ -15,10 +15,11 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/pci_x86.h> #include <asm/pci_x86.h>
#include <asm/pci-direct.h>
#include "bus_numa.h" #include "bus_numa.h"
static void __devinit cnb20le_res(struct pci_dev *dev) static void __init cnb20le_res(u8 bus, u8 slot, u8 func)
{ {
struct pci_root_info *info; struct pci_root_info *info;
struct resource res; struct resource res;
@ -26,21 +27,12 @@ static void __devinit cnb20le_res(struct pci_dev *dev)
u8 fbus, lbus; u8 fbus, lbus;
int i; int i;
#ifdef CONFIG_ACPI
/*
* We should get host bridge information from ACPI unless the BIOS
* doesn't support it.
*/
if (acpi_os_get_root_pointer())
return;
#endif
info = &pci_root_info[pci_root_num]; info = &pci_root_info[pci_root_num];
pci_root_num++; pci_root_num++;
/* read the PCI bus numbers */ /* read the PCI bus numbers */
pci_read_config_byte(dev, 0x44, &fbus); fbus = read_pci_config_byte(bus, slot, func, 0x44);
pci_read_config_byte(dev, 0x45, &lbus); lbus = read_pci_config_byte(bus, slot, func, 0x45);
info->bus_min = fbus; info->bus_min = fbus;
info->bus_max = lbus; info->bus_max = lbus;
@ -59,8 +51,8 @@ static void __devinit cnb20le_res(struct pci_dev *dev)
} }
/* read the non-prefetchable memory window */ /* read the non-prefetchable memory window */
pci_read_config_word(dev, 0xc0, &word1); word1 = read_pci_config_16(bus, slot, func, 0xc0);
pci_read_config_word(dev, 0xc2, &word2); word2 = read_pci_config_16(bus, slot, func, 0xc2);
if (word1 != word2) { if (word1 != word2) {
res.start = (word1 << 16) | 0x0000; res.start = (word1 << 16) | 0x0000;
res.end = (word2 << 16) | 0xffff; res.end = (word2 << 16) | 0xffff;
@ -69,8 +61,8 @@ static void __devinit cnb20le_res(struct pci_dev *dev)
} }
/* read the prefetchable memory window */ /* read the prefetchable memory window */
pci_read_config_word(dev, 0xc4, &word1); word1 = read_pci_config_16(bus, slot, func, 0xc4);
pci_read_config_word(dev, 0xc6, &word2); word2 = read_pci_config_16(bus, slot, func, 0xc6);
if (word1 != word2) { if (word1 != word2) {
res.start = (word1 << 16) | 0x0000; res.start = (word1 << 16) | 0x0000;
res.end = (word2 << 16) | 0xffff; res.end = (word2 << 16) | 0xffff;
@ -79,8 +71,8 @@ static void __devinit cnb20le_res(struct pci_dev *dev)
} }
/* read the IO port window */ /* read the IO port window */
pci_read_config_word(dev, 0xd0, &word1); word1 = read_pci_config_16(bus, slot, func, 0xd0);
pci_read_config_word(dev, 0xd2, &word2); word2 = read_pci_config_16(bus, slot, func, 0xd2);
if (word1 != word2) { if (word1 != word2) {
res.start = word1; res.start = word1;
res.end = word2; res.end = word2;
@ -92,13 +84,37 @@ static void __devinit cnb20le_res(struct pci_dev *dev)
res.start = fbus; res.start = fbus;
res.end = lbus; res.end = lbus;
res.flags = IORESOURCE_BUS; res.flags = IORESOURCE_BUS;
dev_info(&dev->dev, "CNB20LE PCI Host Bridge (domain %04x %pR)\n", printk(KERN_INFO "CNB20LE PCI Host Bridge (domain 0000 %pR)\n", &res);
pci_domain_nr(dev->bus), &res);
for (i = 0; i < info->res_num; i++) for (i = 0; i < info->res_num; i++)
dev_info(&dev->dev, "host bridge window %pR\n", &info->res[i]); printk(KERN_INFO "host bridge window %pR\n", &info->res[i]);
} }
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE, static int __init broadcom_postcore_init(void)
cnb20le_res); {
u8 bus = 0, slot = 0;
u32 id;
u16 vendor, device;
#ifdef CONFIG_ACPI
/*
* We should get host bridge information from ACPI unless the BIOS
* doesn't support it.
*/
if (acpi_os_get_root_pointer())
return 0;
#endif
id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID);
vendor = id & 0xffff;
device = (id >> 16) & 0xffff;
if (vendor == PCI_VENDOR_ID_SERVERWORKS &&
device == PCI_DEVICE_ID_SERVERWORKS_LE) {
cnb20le_res(bus, slot, 0);
cnb20le_res(bus, slot, 1);
}
return 0;
}
postcore_initcall(broadcom_postcore_init);

View File

@ -7,45 +7,50 @@
int pci_root_num; int pci_root_num;
struct pci_root_info pci_root_info[PCI_ROOT_NR]; struct pci_root_info pci_root_info[PCI_ROOT_NR];
void x86_pci_root_bus_res_quirks(struct pci_bus *b) void x86_pci_root_bus_resources(int bus, struct list_head *resources)
{ {
int i; int i;
int j; int j;
struct pci_root_info *info; struct pci_root_info *info;
/* don't go for it if _CRS is used already */
if (b->resource[0] != &ioport_resource ||
b->resource[1] != &iomem_resource)
return;
if (!pci_root_num) if (!pci_root_num)
return; goto default_resources;
for (i = 0; i < pci_root_num; i++) { for (i = 0; i < pci_root_num; i++) {
if (pci_root_info[i].bus_min == b->number) if (pci_root_info[i].bus_min == bus)
break; break;
} }
if (i == pci_root_num) if (i == pci_root_num)
return; goto default_resources;
printk(KERN_DEBUG "PCI: peer root bus %02x res updated from pci conf\n", printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
b->number); bus);
pci_bus_remove_resources(b);
info = &pci_root_info[i]; info = &pci_root_info[i];
for (j = 0; j < info->res_num; j++) { for (j = 0; j < info->res_num; j++) {
struct resource *res; struct resource *res;
struct resource *root; struct resource *root;
res = &info->res[j]; res = &info->res[j];
pci_bus_add_resource(b, res, 0); pci_add_resource(resources, res);
if (res->flags & IORESOURCE_IO) if (res->flags & IORESOURCE_IO)
root = &ioport_resource; root = &ioport_resource;
else else
root = &iomem_resource; root = &iomem_resource;
insert_resource(root, res); insert_resource(root, res);
} }
return;
default_resources:
/*
* We don't have any host bridge aperture information from the
* "native host bridge drivers," e.g., amd_bus or broadcom_bus,
* so fall back to the defaults historically used by pci_create_bus().
*/
printk(KERN_DEBUG "PCI: root bus %02x: using default resources\n", bus);
pci_add_resource(resources, &ioport_resource);
pci_add_resource(resources, &iomem_resource);
} }
void __devinit update_res(struct pci_root_info *info, resource_size_t start, void __devinit update_res(struct pci_root_info *info, resource_size_t start,

View File

@ -164,9 +164,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b)
{ {
struct pci_dev *dev; struct pci_dev *dev;
/* root bus? */
if (!b->parent)
x86_pci_root_bus_res_quirks(b);
pci_read_bridge_bases(b); pci_read_bridge_bases(b);
list_for_each_entry(dev, &b->devices, bus_list) list_for_each_entry(dev, &b->devices, bus_list)
pcibios_fixup_device_resources(dev); pcibios_fixup_device_resources(dev);
@ -433,6 +430,7 @@ void __init dmi_check_pciprobe(void)
struct pci_bus * __devinit pcibios_scan_root(int busnum) struct pci_bus * __devinit pcibios_scan_root(int busnum)
{ {
LIST_HEAD(resources);
struct pci_bus *bus = NULL; struct pci_bus *bus = NULL;
struct pci_sysdata *sd; struct pci_sysdata *sd;
@ -456,9 +454,12 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)
sd->node = get_mp_bus_to_node(busnum); sd->node = get_mp_bus_to_node(busnum);
printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum);
bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); x86_pci_root_bus_resources(busnum, &resources);
if (!bus) bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
kfree(sd); kfree(sd);
}
return bus; return bus;
} }
@ -639,6 +640,7 @@ int pci_ext_cfg_avail(struct pci_dev *dev)
struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node) struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node)
{ {
LIST_HEAD(resources);
struct pci_bus *bus = NULL; struct pci_bus *bus = NULL;
struct pci_sysdata *sd; struct pci_sysdata *sd;
@ -653,9 +655,12 @@ struct pci_bus * __devinit pci_scan_bus_on_node(int busno, struct pci_ops *ops,
return NULL; return NULL;
} }
sd->node = node; sd->node = node;
bus = pci_scan_bus(busno, ops, sd); x86_pci_root_bus_resources(busno, &resources);
if (!bus) bus = pci_scan_root_bus(NULL, busno, ops, sd, &resources);
if (!bus) {
pci_free_resource_list(&resources);
kfree(sd); kfree(sd);
}
return bus; return bus;
} }

View File

@ -254,26 +254,6 @@ void __init pcibios_resource_survey(void)
*/ */
fs_initcall(pcibios_assign_resources); fs_initcall(pcibios_assign_resources);
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain crappy BIOSes forget to set it properly.
*/
unsigned int pcibios_max_latency = 255;
void pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
static const struct vm_operations_struct pci_mmap_ops = { static const struct vm_operations_struct pci_mmap_ops = {
.access = generic_access_phys, .access = generic_access_phys,
}; };

View File

@ -31,9 +31,6 @@ int __init pci_legacy_init(void)
printk("PCI: Probing PCI hardware\n"); printk("PCI: Probing PCI hardware\n");
pci_root_bus = pcibios_scan_root(0); pci_root_bus = pcibios_scan_root(0);
if (pci_root_bus)
pci_bus_add_devices(pci_root_bus);
return 0; return 0;
} }

View File

@ -153,8 +153,6 @@ int __init pci_numaq_init(void)
raw_pci_ops = &pci_direct_conf1_mq; raw_pci_ops = &pci_direct_conf1_mq;
pci_root_bus = pcibios_scan_root(0); pci_root_bus = pcibios_scan_root(0);
if (pci_root_bus)
pci_bus_add_devices(pci_root_bus);
if (num_online_nodes() > 1) if (num_online_nodes() > 1)
for_each_online_node(quad) { for_each_online_node(quad) {
if (quad == 0) if (quad == 0)

View File

@ -22,11 +22,6 @@
extern struct pci_controller* pcibios_alloc_controller(void); extern struct pci_controller* pcibios_alloc_controller(void);
static inline void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
static inline void pcibios_penalize_isa_irq(int irq) static inline void pcibios_penalize_isa_irq(int irq)
{ {
/* We don't do dynamic PCI IRQ allocation */ /* We don't do dynamic PCI IRQ allocation */

View File

@ -134,9 +134,46 @@ struct pci_controller * __init pcibios_alloc_controller(void)
return pci_ctrl; return pci_ctrl;
} }
static void __init pci_controller_apertures(struct pci_controller *pci_ctrl,
struct list_head *resources)
{
struct resource *res;
unsigned long io_offset;
int i;
io_offset = (unsigned long)pci_ctrl->io_space.base;
res = &pci_ctrl->io_resource;
if (!res->flags) {
if (io_offset)
printk (KERN_ERR "I/O resource not set for host"
" bridge %d\n", pci_ctrl->index);
res->start = 0;
res->end = IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
}
res->start += io_offset;
res->end += io_offset;
pci_add_resource(resources, res);
for (i = 0; i < 3; i++) {
res = &pci_ctrl->mem_resources[i];
if (!res->flags) {
if (i > 0)
continue;
printk(KERN_ERR "Memory resource not set for "
"host bridge %d\n", pci_ctrl->index);
res->start = 0;
res->end = ~0U;
res->flags = IORESOURCE_MEM;
}
pci_add_resource(resources, res);
}
}
static int __init pcibios_init(void) static int __init pcibios_init(void)
{ {
struct pci_controller *pci_ctrl; struct pci_controller *pci_ctrl;
struct list_head resources;
struct pci_bus *bus; struct pci_bus *bus;
int next_busno = 0, i; int next_busno = 0, i;
@ -145,19 +182,10 @@ static int __init pcibios_init(void)
/* Scan all of the recorded PCI controllers. */ /* Scan all of the recorded PCI controllers. */
for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) { for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) {
pci_ctrl->last_busno = 0xff; pci_ctrl->last_busno = 0xff;
bus = pci_scan_bus(pci_ctrl->first_busno, pci_ctrl->ops, INIT_LIST_HEAD(&resources);
pci_ctrl); pci_controller_apertures(pci_ctrl, &resources);
if (pci_ctrl->io_resource.flags) { bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
unsigned long offs; pci_ctrl->ops, pci_ctrl, &resources);
offs = (unsigned long)pci_ctrl->io_space.base;
pci_ctrl->io_resource.start += offs;
pci_ctrl->io_resource.end += offs;
bus->resource[0] = &pci_ctrl->io_resource;
}
for (i = 0; i < 3; ++i)
if (pci_ctrl->mem_resources[i].flags)
bus->resource[i+1] =&pci_ctrl->mem_resources[i];
pci_ctrl->bus = bus; pci_ctrl->bus = bus;
pci_ctrl->last_busno = bus->subordinate; pci_ctrl->last_busno = bus->subordinate;
if (next_busno <= pci_ctrl->last_busno) if (next_busno <= pci_ctrl->last_busno)
@ -178,36 +206,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
int i; int i;
io_offset = (unsigned long)pci_ctrl->io_space.base; io_offset = (unsigned long)pci_ctrl->io_space.base;
if (bus->parent == NULL) { if (bus->parent) {
/* this is a host bridge - fill in its resources */
pci_ctrl->bus = bus;
bus->resource[0] = res = &pci_ctrl->io_resource;
if (!res->flags) {
if (io_offset)
printk (KERN_ERR "I/O resource not set for host"
" bridge %d\n", pci_ctrl->index);
res->start = 0;
res->end = IO_SPACE_LIMIT;
res->flags = IORESOURCE_IO;
}
res->start += io_offset;
res->end += io_offset;
for (i = 0; i < 3; i++) {
res = &pci_ctrl->mem_resources[i];
if (!res->flags) {
if (i > 0)
continue;
printk(KERN_ERR "Memory resource not set for "
"host bridge %d\n", pci_ctrl->index);
res->start = 0;
res->end = ~0U;
res->flags = IORESOURCE_MEM;
}
bus->resource[i+1] = res;
}
} else {
/* This is a subordinate bridge */ /* This is a subordinate bridge */
pci_read_bridge_bases(bus); pci_read_bridge_bases(bus);
@ -227,6 +226,11 @@ char __init *pcibios_setup(char *str)
return str; return str;
} }
void pcibios_set_master(struct pci_dev *dev)
{
/* No special bus mastering setup handling */
}
/* the next one is stolen from the alpha port... */ /* the next one is stolen from the alpha port... */
void __init void __init

View File

@ -487,10 +487,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
else else
link_desc[0] = '\0'; link_desc[0] = '\0';
dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
pin_name(pin), link_desc, gsi, pin_name(pin), link_desc, gsi,
(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return 0; return 0;
} }
@ -524,6 +524,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
* (e.g. PCI_UNDEFINED_IRQ). * (e.g. PCI_UNDEFINED_IRQ).
*/ */
dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin)); dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
acpi_unregister_gsi(gsi); acpi_unregister_gsi(gsi);
} }

View File

@ -562,19 +562,6 @@ dino_fixup_bus(struct pci_bus *bus)
/* Firmware doesn't set up card-mode dino, so we have to */ /* Firmware doesn't set up card-mode dino, so we have to */
if (is_card_dino(&dino_dev->hba.dev->id)) { if (is_card_dino(&dino_dev->hba.dev->id)) {
dino_card_setup(bus, dino_dev->hba.base_addr); dino_card_setup(bus, dino_dev->hba.base_addr);
} else if(bus->parent == NULL) {
/* must have a dino above it, reparent the resources
* into the dino window */
int i;
struct resource *res = &dino_dev->hba.lmmio_space;
bus->resource[0] = &(dino_dev->hba.io_space);
for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) {
if(res[i].flags == 0)
break;
bus->resource[i+1] = &res[i];
}
} else if (bus->parent) { } else if (bus->parent) {
int i; int i;
@ -927,6 +914,7 @@ static int __init dino_probe(struct parisc_device *dev)
const char *version = "unknown"; const char *version = "unknown";
char *name; char *name;
int is_cujo = 0; int is_cujo = 0;
LIST_HEAD(resources);
struct pci_bus *bus; struct pci_bus *bus;
unsigned long hpa = dev->hpa.start; unsigned long hpa = dev->hpa.start;
@ -1003,26 +991,37 @@ static int __init dino_probe(struct parisc_device *dev)
dev->dev.platform_data = dino_dev; dev->dev.platform_data = dino_dev;
pci_add_resource(&resources, &dino_dev->hba.io_space);
if (dino_dev->hba.lmmio_space.flags)
pci_add_resource(&resources, &dino_dev->hba.lmmio_space);
if (dino_dev->hba.elmmio_space.flags)
pci_add_resource(&resources, &dino_dev->hba.elmmio_space);
if (dino_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
/* /*
** It's not used to avoid chicken/egg problems ** It's not used to avoid chicken/egg problems
** with configuration accessor functions. ** with configuration accessor functions.
*/ */
dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev, dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
dino_current_bus, &dino_cfg_ops, NULL); dino_current_bus, &dino_cfg_ops, NULL, &resources);
if (!bus) {
if(bus) {
/* This code *depends* on scanning being single threaded
* if it isn't, this global bus number count will fail
*/
dino_current_bus = bus->subordinate + 1;
pci_bus_assign_resources(bus);
pci_bus_add_devices(bus);
} else {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n", printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus); dev_name(&dev->dev), dino_current_bus);
pci_free_resource_list(&resources);
/* increment the bus number in case of duplicates */ /* increment the bus number in case of duplicates */
dino_current_bus++; dino_current_bus++;
return 0;
} }
bus->subordinate = pci_scan_child_bus(bus);
/* This code *depends* on scanning being single threaded
* if it isn't, this global bus number count will fail
*/
dino_current_bus = bus->subordinate + 1;
pci_bus_assign_resources(bus);
pci_bus_add_devices(bus);
return 0; return 0;
} }

View File

@ -653,7 +653,7 @@ lba_fixup_bus(struct pci_bus *bus)
} }
} else { } else {
/* Host-PCI Bridge */ /* Host-PCI Bridge */
int err, i; int err;
DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n", DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
ldev->hba.io_space.name, ldev->hba.io_space.name,
@ -669,9 +669,6 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&ioport_resource, 2); lba_dump_res(&ioport_resource, 2);
BUG(); BUG();
} }
/* advertize Host bridge resources to PCI bus */
bus->resource[0] = &(ldev->hba.io_space);
i = 1;
if (ldev->hba.elmmio_space.start) { if (ldev->hba.elmmio_space.start) {
err = request_resource(&iomem_resource, err = request_resource(&iomem_resource,
@ -685,35 +682,17 @@ lba_fixup_bus(struct pci_bus *bus)
/* lba_dump_res(&iomem_resource, 2); */ /* lba_dump_res(&iomem_resource, 2); */
/* BUG(); */ /* BUG(); */
} else }
bus->resource[i++] = &(ldev->hba.elmmio_space);
} }
if (ldev->hba.lmmio_space.flags) {
/* Overlaps with elmmio can (and should) fail here.
* We will prune (or ignore) the distributed range.
*
* FIXME: SBA code should register all elmmio ranges first.
* that would take care of elmmio ranges routed
* to a different rope (already discovered) from
* getting registered *after* LBA code has already
* registered it's distributed lmmio range.
*/
if (truncate_pat_collision(&iomem_resource,
&(ldev->hba.lmmio_space))) {
printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
(long)ldev->hba.lmmio_space.start,
(long)ldev->hba.lmmio_space.end);
} else {
err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space)); err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
if (err < 0) { if (err < 0) {
printk(KERN_ERR "FAILED: lba_fixup_bus() request for " printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
"lmmio_space [%lx/%lx]\n", "lmmio_space [%lx/%lx]\n",
(long)ldev->hba.lmmio_space.start, (long)ldev->hba.lmmio_space.start,
(long)ldev->hba.lmmio_space.end); (long)ldev->hba.lmmio_space.end);
} else }
bus->resource[i++] = &(ldev->hba.lmmio_space);
} }
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
@ -728,7 +707,6 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&iomem_resource, 2); lba_dump_res(&iomem_resource, 2);
BUG(); BUG();
} }
bus->resource[i++] = &(ldev->hba.gmmio_space);
} }
#endif #endif
@ -1404,6 +1382,7 @@ static int __init
lba_driver_probe(struct parisc_device *dev) lba_driver_probe(struct parisc_device *dev)
{ {
struct lba_device *lba_dev; struct lba_device *lba_dev;
LIST_HEAD(resources);
struct pci_bus *lba_bus; struct pci_bus *lba_bus;
struct pci_ops *cfg_ops; struct pci_ops *cfg_ops;
u32 func_class; u32 func_class;
@ -1518,10 +1497,41 @@ lba_driver_probe(struct parisc_device *dev)
if (lba_dev->hba.bus_num.start < lba_next_bus) if (lba_dev->hba.bus_num.start < lba_next_bus)
lba_dev->hba.bus_num.start = lba_next_bus; lba_dev->hba.bus_num.start = lba_next_bus;
/* Overlaps with elmmio can (and should) fail here.
* We will prune (or ignore) the distributed range.
*
* FIXME: SBA code should register all elmmio ranges first.
* that would take care of elmmio ranges routed
* to a different rope (already discovered) from
* getting registered *after* LBA code has already
* registered it's distributed lmmio range.
*/
if (truncate_pat_collision(&iomem_resource,
&(lba_dev->hba.lmmio_space))) {
printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
(long)lba_dev->hba.lmmio_space.start,
(long)lba_dev->hba.lmmio_space.end);
lba_dev->hba.lmmio_space.flags = 0;
}
pci_add_resource(&resources, &lba_dev->hba.io_space);
if (lba_dev->hba.elmmio_space.start)
pci_add_resource(&resources, &lba_dev->hba.elmmio_space);
if (lba_dev->hba.lmmio_space.flags)
pci_add_resource(&resources, &lba_dev->hba.lmmio_space);
if (lba_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
dev->dev.platform_data = lba_dev; dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus = lba_bus = lba_dev->hba.hba_bus =
pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start, pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
cfg_ops, NULL); cfg_ops, NULL, &resources);
if (!lba_bus) {
pci_free_resource_list(&resources);
return 0;
}
lba_bus->subordinate = pci_scan_child_bus(lba_bus);
/* This is in lieu of calling pci_assign_unassigned_resources() */ /* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) { if (is_pdc_pat()) {
@ -1551,10 +1561,8 @@ lba_driver_probe(struct parisc_device *dev)
lba_dev->flags |= LBA_FLAG_SKIP_PROBE; lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
} }
if (lba_bus) { lba_next_bus = lba_bus->subordinate + 1;
lba_next_bus = lba_bus->subordinate + 1; pci_bus_add_devices(lba_bus);
pci_bus_add_devices(lba_bus);
}
/* Whew! Finally done! Tell services we got this one covered. */ /* Whew! Finally done! Tell services we got this one covered. */
return 0; return 0;

View File

@ -13,7 +13,7 @@
* configuration space. * configuration space.
*/ */
static DEFINE_RAW_SPINLOCK(pci_lock); DEFINE_RAW_SPINLOCK(pci_lock);
/* /*
* Wrappers for all PCI configuration access functions. They just check * Wrappers for all PCI configuration access functions. They just check
@ -127,20 +127,20 @@ EXPORT_SYMBOL(pci_write_vpd);
* We have a bit per device to indicate it's blocked and a global wait queue * We have a bit per device to indicate it's blocked and a global wait queue
* for callers to sleep on until devices are unblocked. * for callers to sleep on until devices are unblocked.
*/ */
static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait); static DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
static noinline void pci_wait_ucfg(struct pci_dev *dev) static noinline void pci_wait_cfg(struct pci_dev *dev)
{ {
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
__add_wait_queue(&pci_ucfg_wait, &wait); __add_wait_queue(&pci_cfg_wait, &wait);
do { do {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
raw_spin_unlock_irq(&pci_lock); raw_spin_unlock_irq(&pci_lock);
schedule(); schedule();
raw_spin_lock_irq(&pci_lock); raw_spin_lock_irq(&pci_lock);
} while (dev->block_ucfg_access); } while (dev->block_cfg_access);
__remove_wait_queue(&pci_ucfg_wait, &wait); __remove_wait_queue(&pci_cfg_wait, &wait);
} }
/* Returns 0 on success, negative values indicate error. */ /* Returns 0 on success, negative values indicate error. */
@ -153,7 +153,8 @@ int pci_user_read_config_##size \
if (PCI_##size##_BAD) \ if (PCI_##size##_BAD) \
return -EINVAL; \ return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \ raw_spin_lock_irq(&pci_lock); \
if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ if (unlikely(dev->block_cfg_access)) \
pci_wait_cfg(dev); \
ret = dev->bus->ops->read(dev->bus, dev->devfn, \ ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \ pos, sizeof(type), &data); \
raw_spin_unlock_irq(&pci_lock); \ raw_spin_unlock_irq(&pci_lock); \
@ -172,7 +173,8 @@ int pci_user_write_config_##size \
if (PCI_##size##_BAD) \ if (PCI_##size##_BAD) \
return -EINVAL; \ return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \ raw_spin_lock_irq(&pci_lock); \
if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ if (unlikely(dev->block_cfg_access)) \
pci_wait_cfg(dev); \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \ ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \ pos, sizeof(type), val); \
raw_spin_unlock_irq(&pci_lock); \ raw_spin_unlock_irq(&pci_lock); \
@ -401,36 +403,56 @@ int pci_vpd_truncate(struct pci_dev *dev, size_t size)
EXPORT_SYMBOL(pci_vpd_truncate); EXPORT_SYMBOL(pci_vpd_truncate);
/** /**
* pci_block_user_cfg_access - Block userspace PCI config reads/writes * pci_cfg_access_lock - Lock PCI config reads/writes
* @dev: pci device struct * @dev: pci device struct
* *
* When user access is blocked, any reads or writes to config space will * When access is locked, any userspace reads or writes to config
* sleep until access is unblocked again. We don't allow nesting of * space and concurrent lock requests will sleep until access is
* block/unblock calls. * allowed via pci_cfg_access_unlocked again.
*/ */
void pci_block_user_cfg_access(struct pci_dev *dev) void pci_cfg_access_lock(struct pci_dev *dev)
{ {
unsigned long flags; might_sleep();
int was_blocked;
raw_spin_lock_irqsave(&pci_lock, flags); raw_spin_lock_irq(&pci_lock);
was_blocked = dev->block_ucfg_access; if (dev->block_cfg_access)
dev->block_ucfg_access = 1; pci_wait_cfg(dev);
raw_spin_unlock_irqrestore(&pci_lock, flags); dev->block_cfg_access = 1;
raw_spin_unlock_irq(&pci_lock);
/* If we BUG() inside the pci_lock, we're guaranteed to hose
* the machine */
BUG_ON(was_blocked);
} }
EXPORT_SYMBOL_GPL(pci_block_user_cfg_access); EXPORT_SYMBOL_GPL(pci_cfg_access_lock);
/** /**
* pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes * pci_cfg_access_trylock - try to lock PCI config reads/writes
* @dev: pci device struct * @dev: pci device struct
* *
* This function allows userspace PCI config accesses to resume. * Same as pci_cfg_access_lock, but will return 0 if access is
* already locked, 1 otherwise. This function can be used from
* atomic contexts.
*/ */
void pci_unblock_user_cfg_access(struct pci_dev *dev) bool pci_cfg_access_trylock(struct pci_dev *dev)
{
unsigned long flags;
bool locked = true;
raw_spin_lock_irqsave(&pci_lock, flags);
if (dev->block_cfg_access)
locked = false;
else
dev->block_cfg_access = 1;
raw_spin_unlock_irqrestore(&pci_lock, flags);
return locked;
}
EXPORT_SYMBOL_GPL(pci_cfg_access_trylock);
/**
* pci_cfg_access_unlock - Unlock PCI config reads/writes
* @dev: pci device struct
*
* This function allows PCI config accesses to resume.
*/
void pci_cfg_access_unlock(struct pci_dev *dev)
{ {
unsigned long flags; unsigned long flags;
@ -438,10 +460,10 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev)
/* This indicates a problem in the caller, but we don't need /* This indicates a problem in the caller, but we don't need
* to kill them, unlike a double-block above. */ * to kill them, unlike a double-block above. */
WARN_ON(!dev->block_ucfg_access); WARN_ON(!dev->block_cfg_access);
dev->block_ucfg_access = 0; dev->block_cfg_access = 0;
wake_up_all(&pci_ucfg_wait); wake_up_all(&pci_cfg_wait);
raw_spin_unlock_irqrestore(&pci_lock, flags); raw_spin_unlock_irqrestore(&pci_lock, flags);
} }
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);

View File

@ -128,6 +128,23 @@ void pci_disable_ats(struct pci_dev *dev)
} }
EXPORT_SYMBOL_GPL(pci_disable_ats); EXPORT_SYMBOL_GPL(pci_disable_ats);
void pci_restore_ats_state(struct pci_dev *dev)
{
u16 ctrl;
if (!pci_ats_enabled(dev))
return;
if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS))
BUG();
ctrl = PCI_ATS_CTRL_ENABLE;
if (!dev->is_virtfn)
ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU);
pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
}
EXPORT_SYMBOL_GPL(pci_restore_ats_state);
/** /**
* pci_ats_queue_depth - query the ATS Invalidate Queue Depth * pci_ats_queue_depth - query the ATS Invalidate Queue Depth
* @dev: the PCI device * @dev: the PCI device

View File

@ -18,6 +18,32 @@
#include "pci.h" #include "pci.h"
void pci_add_resource(struct list_head *resources, struct resource *res)
{
struct pci_bus_resource *bus_res;
bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
if (!bus_res) {
printk(KERN_ERR "PCI: can't add bus resource %pR\n", res);
return;
}
bus_res->res = res;
list_add_tail(&bus_res->list, resources);
}
EXPORT_SYMBOL(pci_add_resource);
void pci_free_resource_list(struct list_head *resources)
{
struct pci_bus_resource *bus_res, *tmp;
list_for_each_entry_safe(bus_res, tmp, resources, list) {
list_del(&bus_res->list);
kfree(bus_res);
}
}
EXPORT_SYMBOL(pci_free_resource_list);
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
unsigned int flags) unsigned int flags)
{ {
@ -52,16 +78,12 @@ EXPORT_SYMBOL_GPL(pci_bus_resource_n);
void pci_bus_remove_resources(struct pci_bus *bus) void pci_bus_remove_resources(struct pci_bus *bus)
{ {
struct pci_bus_resource *bus_res, *tmp;
int i; int i;
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
bus->resource[i] = NULL; bus->resource[i] = NULL;
list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) { pci_free_resource_list(&bus->resources);
list_del(&bus_res->list);
kfree(bus_res);
}
} }
/** /**

View File

@ -347,11 +347,13 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return rc; return rc;
} }
pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
pci_block_user_cfg_access(dev); pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
msleep(100); msleep(100);
pci_unblock_user_cfg_access(dev); pci_cfg_access_unlock(dev);
iov->initial = initial; iov->initial = initial;
if (nr_virtfn < initial) if (nr_virtfn < initial)
@ -379,10 +381,10 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
virtfn_remove(dev, j, 0); virtfn_remove(dev, j, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
pci_block_user_cfg_access(dev); pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
ssleep(1); ssleep(1);
pci_unblock_user_cfg_access(dev); pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn) if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link"); sysfs_remove_link(&dev->dev.kobj, "dep_link");
@ -405,10 +407,10 @@ static void sriov_disable(struct pci_dev *dev)
virtfn_remove(dev, i, 0); virtfn_remove(dev, i, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE); iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
pci_block_user_cfg_access(dev); pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
ssleep(1); ssleep(1);
pci_unblock_user_cfg_access(dev); pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn) if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link"); sysfs_remove_link(&dev->dev.kobj, "dep_link");
@ -452,7 +454,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
found: found:
pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl);
pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, total);
pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset); pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride); pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
if (!offset || (total > 1 && !stride)) if (!offset || (total > 1 && !stride))
@ -465,7 +466,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
return -EIO; return -EIO;
pgsz &= ~(pgsz - 1); pgsz &= ~(pgsz - 1);
pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
nres = 0; nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {

View File

@ -86,6 +86,31 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
} }
#endif #endif
#ifndef arch_restore_msi_irqs
# define arch_restore_msi_irqs default_restore_msi_irqs
# define HAVE_DEFAULT_MSI_RESTORE_IRQS
#endif
#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
void default_restore_msi_irqs(struct pci_dev *dev, int irq)
{
struct msi_desc *entry;
entry = NULL;
if (dev->msix_enabled) {
list_for_each_entry(entry, &dev->msi_list, list) {
if (irq == entry->irq)
break;
}
} else if (dev->msi_enabled) {
entry = irq_get_msi_desc(irq);
}
if (entry)
write_msi_msg(irq, &entry->msg);
}
#endif
static void msi_set_enable(struct pci_dev *dev, int pos, int enable) static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
{ {
u16 control; u16 control;
@ -323,8 +348,18 @@ static void free_msi_irqs(struct pci_dev *dev)
if (list_is_last(&entry->list, &dev->msi_list)) if (list_is_last(&entry->list, &dev->msi_list))
iounmap(entry->mask_base); iounmap(entry->mask_base);
} }
kobject_del(&entry->kobj);
kobject_put(&entry->kobj); /*
* Its possible that we get into this path
* When populate_msi_sysfs fails, which means the entries
* were not registered with sysfs. In that case don't
* unregister them.
*/
if (entry->kobj.parent) {
kobject_del(&entry->kobj);
kobject_put(&entry->kobj);
}
list_del(&entry->list); list_del(&entry->list);
kfree(entry); kfree(entry);
} }
@ -362,7 +397,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
pci_intx_for_msi(dev, 0); pci_intx_for_msi(dev, 0);
msi_set_enable(dev, pos, 0); msi_set_enable(dev, pos, 0);
write_msi_msg(dev->irq, &entry->msg); arch_restore_msi_irqs(dev, dev->irq);
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
msi_mask_irq(entry, msi_capable_mask(control), entry->masked); msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
@ -390,7 +425,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
list_for_each_entry(entry, &dev->msi_list, list) { list_for_each_entry(entry, &dev->msi_list, list) {
write_msi_msg(entry->irq, &entry->msg); arch_restore_msi_irqs(dev, entry->irq);
msix_mask_irq(entry, entry->masked); msix_mask_irq(entry, entry->masked);
} }

View File

@ -604,7 +604,8 @@ static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
* supported as well. Drivers are supposed to support either the * supported as well. Drivers are supposed to support either the
* former, or the latter, but not both at the same time. * former, or the latter, but not both at the same time.
*/ */
WARN_ON(ret && drv->driver.pm); WARN(ret && drv->driver.pm, "driver %s device %04x:%04x\n",
drv->name, pci_dev->vendor, pci_dev->device);
return ret; return ret;
} }

View File

@ -88,6 +88,12 @@ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2; u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
u8 pci_cache_line_size; u8 pci_cache_line_size;
/*
* If we set up a device for bus mastering, we need to check the latency
* timer as certain BIOSes forget to set it properly.
*/
unsigned int pcibios_max_latency = 255;
/** /**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children * pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search * @bus: pointer to PCI bus structure to search
@ -959,6 +965,7 @@ void pci_restore_state(struct pci_dev *dev)
/* PCI Express register must be restored first */ /* PCI Express register must be restored first */
pci_restore_pcie_state(dev); pci_restore_pcie_state(dev);
pci_restore_ats_state(dev);
/* /*
* The Base Address register should be programmed before the command * The Base Address register should be programmed before the command
@ -967,7 +974,7 @@ void pci_restore_state(struct pci_dev *dev)
for (i = 15; i >= 0; i--) { for (i = 15; i >= 0; i--) {
pci_read_config_dword(dev, i * 4, &val); pci_read_config_dword(dev, i * 4, &val);
if (val != dev->saved_config_space[i]) { if (val != dev->saved_config_space[i]) {
dev_printk(KERN_DEBUG, &dev->dev, "restoring config " dev_dbg(&dev->dev, "restoring config "
"space at offset %#x (was %#x, writing %#x)\n", "space at offset %#x (was %#x, writing %#x)\n",
i, val, (int)dev->saved_config_space[i]); i, val, (int)dev->saved_config_space[i]);
pci_write_config_dword(dev,i * 4, pci_write_config_dword(dev,i * 4,
@ -1536,8 +1543,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
} }
out: out:
dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n", dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled");
enable ? "enabled" : "disabled");
} }
/** /**
@ -2595,6 +2601,33 @@ static void __pci_set_master(struct pci_dev *dev, bool enable)
dev->is_busmaster = enable; dev->is_busmaster = enable;
} }
/**
* pcibios_set_master - enable PCI bus-mastering for device dev
* @dev: the PCI device to enable
*
* Enables PCI bus-mastering for the device. This is the default
* implementation. Architecture specific implementations can override
* this if necessary.
*/
void __weak pcibios_set_master(struct pci_dev *dev)
{
u8 lat;
/* The latency timer doesn't apply to PCIe (either Type 0 or Type 1) */
if (pci_is_pcie(dev))
return;
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16)
lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
else if (lat > pcibios_max_latency)
lat = pcibios_max_latency;
else
return;
dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
}
/** /**
* pci_set_master - enables bus-mastering for device dev * pci_set_master - enables bus-mastering for device dev
* @dev: the PCI device to enable * @dev: the PCI device to enable
@ -2767,6 +2800,116 @@ pci_intx(struct pci_dev *pdev, int enable)
} }
} }
/**
* pci_intx_mask_supported - probe for INTx masking support
* @pdev: the PCI device to operate on
*
* Check if the device dev support INTx masking via the config space
* command word.
*/
bool pci_intx_mask_supported(struct pci_dev *dev)
{
bool mask_supported = false;
u16 orig, new;
pci_cfg_access_lock(dev);
pci_read_config_word(dev, PCI_COMMAND, &orig);
pci_write_config_word(dev, PCI_COMMAND,
orig ^ PCI_COMMAND_INTX_DISABLE);
pci_read_config_word(dev, PCI_COMMAND, &new);
/*
* There's no way to protect against hardware bugs or detect them
* reliably, but as long as we know what the value should be, let's
* go ahead and check it.
*/
if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
dev_err(&dev->dev, "Command register changed from "
"0x%x to 0x%x: driver or hardware bug?\n", orig, new);
} else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
mask_supported = true;
pci_write_config_word(dev, PCI_COMMAND, orig);
}
pci_cfg_access_unlock(dev);
return mask_supported;
}
EXPORT_SYMBOL_GPL(pci_intx_mask_supported);
static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
{
struct pci_bus *bus = dev->bus;
bool mask_updated = true;
u32 cmd_status_dword;
u16 origcmd, newcmd;
unsigned long flags;
bool irq_pending;
/*
* We do a single dword read to retrieve both command and status.
* Document assumptions that make this possible.
*/
BUILD_BUG_ON(PCI_COMMAND % 4);
BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
raw_spin_lock_irqsave(&pci_lock, flags);
bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
/*
* Check interrupt status register to see whether our device
* triggered the interrupt (when masking) or the next IRQ is
* already pending (when unmasking).
*/
if (mask != irq_pending) {
mask_updated = false;
goto done;
}
origcmd = cmd_status_dword;
newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
if (mask)
newcmd |= PCI_COMMAND_INTX_DISABLE;
if (newcmd != origcmd)
bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
done:
raw_spin_unlock_irqrestore(&pci_lock, flags);
return mask_updated;
}
/**
* pci_check_and_mask_intx - mask INTx on pending interrupt
* @pdev: the PCI device to operate on
*
* Check if the device dev has its INTx line asserted, mask it and
* return true in that case. False is returned if not interrupt was
* pending.
*/
bool pci_check_and_mask_intx(struct pci_dev *dev)
{
return pci_check_and_set_intx_mask(dev, true);
}
EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
/**
* pci_check_and_mask_intx - unmask INTx of no interrupt is pending
* @pdev: the PCI device to operate on
*
* Check if the device dev has its INTx line asserted, unmask it if not
* and return true. False is returned and the mask remains active if
* there was still an interrupt pending.
*/
bool pci_check_and_unmask_intx(struct pci_dev *dev)
{
return pci_check_and_set_intx_mask(dev, false);
}
EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
/** /**
* pci_msi_off - disables any msi or msix capabilities * pci_msi_off - disables any msi or msix capabilities
* @dev: the PCI device to operate on * @dev: the PCI device to operate on
@ -2965,7 +3108,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
might_sleep(); might_sleep();
if (!probe) { if (!probe) {
pci_block_user_cfg_access(dev); pci_cfg_access_lock(dev);
/* block PM suspend, driver probe, etc. */ /* block PM suspend, driver probe, etc. */
device_lock(&dev->dev); device_lock(&dev->dev);
} }
@ -2990,7 +3133,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
done: done:
if (!probe) { if (!probe) {
device_unlock(&dev->dev); device_unlock(&dev->dev);
pci_unblock_user_cfg_access(dev); pci_cfg_access_unlock(dev);
} }
return rc; return rc;

View File

@ -136,6 +136,8 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/* Lock for read/write access to pci device and bus lists */ /* Lock for read/write access to pci device and bus lists */
extern struct rw_semaphore pci_bus_sem; extern struct rw_semaphore pci_bus_sem;
extern raw_spinlock_t pci_lock;
extern unsigned int pci_pm_d3_delay; extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
@ -249,6 +251,14 @@ struct pci_sriov {
u8 __iomem *mstate; /* VF Migration State Array */ u8 __iomem *mstate; /* VF Migration State Array */
}; };
#ifdef CONFIG_PCI_ATS
extern void pci_restore_ats_state(struct pci_dev *dev);
#else
static inline void pci_restore_ats_state(struct pci_dev *dev)
{
}
#endif /* CONFIG_PCI_ATS */
#ifdef CONFIG_PCI_IOV #ifdef CONFIG_PCI_IOV
extern int pci_iov_init(struct pci_dev *dev); extern int pci_iov_init(struct pci_dev *dev);
extern void pci_iov_release(struct pci_dev *dev); extern void pci_iov_release(struct pci_dev *dev);

View File

@ -39,7 +39,7 @@ config PCIEASPM
Power Management) and Clock Power Management. ASPM supports Power Management) and Clock Power Management. ASPM supports
state L0/L0s/L1. state L0/L0s/L1.
ASPM is initially set up the the firmware. With this option enabled, ASPM is initially set up by the firmware. With this option enabled,
Linux can modify this state in order to disable ASPM on known-bad Linux can modify this state in order to disable ASPM on known-bad
hardware or configurations and enable it when known-safe. hardware or configurations and enable it when known-safe.

View File

@ -1522,19 +1522,21 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
return max; return max;
} }
struct pci_bus * pci_create_bus(struct device *parent, struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int bus, struct pci_ops *ops, void *sysdata) struct pci_ops *ops, void *sysdata, struct list_head *resources)
{ {
int error; int error, i;
struct pci_bus *b, *b2; struct pci_bus *b, *b2;
struct device *dev; struct device *dev;
struct pci_bus_resource *bus_res, *n;
struct resource *res;
b = pci_alloc_bus(); b = pci_alloc_bus();
if (!b) if (!b)
return NULL; return NULL;
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev){ if (!dev) {
kfree(b); kfree(b);
return NULL; return NULL;
} }
@ -1577,8 +1579,20 @@ struct pci_bus * pci_create_bus(struct device *parent,
pci_create_legacy_files(b); pci_create_legacy_files(b);
b->number = b->secondary = bus; b->number = b->secondary = bus;
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource; /* Add initial resources to the bus */
list_for_each_entry_safe(bus_res, n, resources, list)
list_move_tail(&bus_res->list, &b->resources);
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
else
printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
pci_bus_for_each_resource(b, res, i) {
if (res)
dev_info(&b->dev, "root bus resource %pR\n", res);
}
return b; return b;
@ -1594,18 +1608,58 @@ struct pci_bus * pci_create_bus(struct device *parent,
return NULL; return NULL;
} }
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
int bus, struct pci_ops *ops, void *sysdata) struct pci_ops *ops, void *sysdata, struct list_head *resources)
{ {
struct pci_bus *b; struct pci_bus *b;
b = pci_create_bus(parent, bus, ops, sysdata); b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
if (!b)
return NULL;
b->subordinate = pci_scan_child_bus(b);
pci_bus_add_devices(b);
return b;
}
EXPORT_SYMBOL(pci_scan_root_bus);
/* Deprecated; use pci_scan_root_bus() instead */
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
{
LIST_HEAD(resources);
struct pci_bus *b;
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
if (b) if (b)
b->subordinate = pci_scan_child_bus(b); b->subordinate = pci_scan_child_bus(b);
else
pci_free_resource_list(&resources);
return b; return b;
} }
EXPORT_SYMBOL(pci_scan_bus_parented); EXPORT_SYMBOL(pci_scan_bus_parented);
struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
void *sysdata)
{
LIST_HEAD(resources);
struct pci_bus *b;
pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
if (b) {
b->subordinate = pci_scan_child_bus(b);
pci_bus_add_devices(b);
} else {
pci_free_resource_list(&resources);
}
return b;
}
EXPORT_SYMBOL(pci_scan_bus);
#ifdef CONFIG_HOTPLUG #ifdef CONFIG_HOTPLUG
/** /**
* pci_rescan_bus - scan a PCI bus for devices. * pci_rescan_bus - scan a PCI bus for devices.

View File

@ -89,9 +89,8 @@ EXPORT_SYMBOL(pci_remove_bus);
* device lists, remove the /proc entry, and notify userspace * device lists, remove the /proc entry, and notify userspace
* (/sbin/hotplug). * (/sbin/hotplug).
*/ */
void pci_remove_bus_device(struct pci_dev *dev) static void __pci_remove_bus_device(struct pci_dev *dev)
{ {
pci_stop_bus_device(dev);
if (dev->subordinate) { if (dev->subordinate) {
struct pci_bus *b = dev->subordinate; struct pci_bus *b = dev->subordinate;
@ -102,6 +101,11 @@ void pci_remove_bus_device(struct pci_dev *dev)
pci_destroy_dev(dev); pci_destroy_dev(dev);
} }
void pci_remove_bus_device(struct pci_dev *dev)
{
pci_stop_bus_device(dev);
__pci_remove_bus_device(dev);
}
/** /**
* pci_remove_behind_bridge - remove all devices behind a PCI bridge * pci_remove_behind_bridge - remove all devices behind a PCI bridge
@ -117,7 +121,7 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
if (dev->subordinate) if (dev->subordinate)
list_for_each_safe(l, n, &dev->subordinate->devices) list_for_each_safe(l, n, &dev->subordinate->devices)
pci_remove_bus_device(pci_dev_b(l)); __pci_remove_bus_device(pci_dev_b(l));
} }
static void pci_stop_bus_devices(struct pci_bus *bus) static void pci_stop_bus_devices(struct pci_bus *bus)

View File

@ -85,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
} }
} }
res->flags &= ~IORESOURCE_UNSET; res->flags &= ~IORESOURCE_UNSET;
dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n", dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
resno, res, (unsigned long long)region.start, resno, res, (unsigned long long)region.start,
(unsigned long long)region.end); (unsigned long long)region.end);
} }
int pci_claim_resource(struct pci_dev *dev, int resource) int pci_claim_resource(struct pci_dev *dev, int resource)

View File

@ -295,6 +295,45 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
} }
} }
#ifdef CONFIG_AMD_NB
#include <asm/amd_nb.h>
static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
{
resource_size_t start, end;
struct pnp_resource *pnp_res;
struct resource *res;
struct resource mmconfig_res, *mmconfig;
mmconfig = amd_get_mmconfig_range(&mmconfig_res);
if (!mmconfig)
return;
list_for_each_entry(pnp_res, &dev->resources, list) {
res = &pnp_res->res;
if (res->end < mmconfig->start || res->start > mmconfig->end ||
(res->start == mmconfig->start && res->end == mmconfig->end))
continue;
dev_info(&dev->dev, FW_BUG
"%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",
res, mmconfig);
if (mmconfig->start < res->start) {
start = mmconfig->start;
end = res->start - 1;
pnp_add_mem_resource(dev, start, end, 0);
}
if (mmconfig->end > res->end) {
start = res->end + 1;
end = mmconfig->end;
pnp_add_mem_resource(dev, start, end, 0);
}
break;
}
}
#endif
/* /*
* PnP Quirks * PnP Quirks
* Cards or devices that need some tweaking due to incomplete resource info * Cards or devices that need some tweaking due to incomplete resource info
@ -322,6 +361,9 @@ static struct pnp_fixup pnp_fixups[] = {
/* PnP resources that might overlap PCI BARs */ /* PnP resources that might overlap PCI BARs */
{"PNP0c01", quirk_system_pci_resources}, {"PNP0c01", quirk_system_pci_resources},
{"PNP0c02", quirk_system_pci_resources}, {"PNP0c02", quirk_system_pci_resources},
#ifdef CONFIG_AMD_NB
{"PNP0c01", quirk_amd_mmconfig_area},
#endif
{""} {""}
}; };

View File

@ -7638,8 +7638,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
**/ **/
static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd) static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
{ {
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
ENTER; ENTER;
pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); if (ioa_cfg->cfg_locked)
pci_cfg_access_unlock(ioa_cfg->pdev);
ioa_cfg->cfg_locked = 0;
ipr_cmd->job_step = ipr_reset_restore_cfg_space; ipr_cmd->job_step = ipr_reset_restore_cfg_space;
LEAVE; LEAVE;
return IPR_RC_JOB_CONTINUE; return IPR_RC_JOB_CONTINUE;
@ -7660,8 +7664,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
int rc = PCIBIOS_SUCCESSFUL; int rc = PCIBIOS_SUCCESSFUL;
ENTER; ENTER;
pci_block_user_cfg_access(ioa_cfg->pdev);
if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO) if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO)
writel(IPR_UPROCI_SIS64_START_BIST, writel(IPR_UPROCI_SIS64_START_BIST,
ioa_cfg->regs.set_uproc_interrupt_reg32); ioa_cfg->regs.set_uproc_interrupt_reg32);
@ -7673,7 +7675,9 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
rc = IPR_RC_JOB_RETURN; rc = IPR_RC_JOB_RETURN;
} else { } else {
pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); if (ioa_cfg->cfg_locked)
pci_cfg_access_unlock(ipr_cmd->ioa_cfg->pdev);
ioa_cfg->cfg_locked = 0;
ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
rc = IPR_RC_JOB_CONTINUE; rc = IPR_RC_JOB_CONTINUE;
} }
@ -7716,7 +7720,6 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
struct pci_dev *pdev = ioa_cfg->pdev; struct pci_dev *pdev = ioa_cfg->pdev;
ENTER; ENTER;
pci_block_user_cfg_access(pdev);
pci_set_pcie_reset_state(pdev, pcie_warm_reset); pci_set_pcie_reset_state(pdev, pcie_warm_reset);
ipr_cmd->job_step = ipr_reset_slot_reset_done; ipr_cmd->job_step = ipr_reset_slot_reset_done;
ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT); ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
@ -7724,6 +7727,56 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
return IPR_RC_JOB_RETURN; return IPR_RC_JOB_RETURN;
} }
/**
* ipr_reset_block_config_access_wait - Wait for permission to block config access
* @ipr_cmd: ipr command struct
*
* Description: This attempts to block config access to the IOA.
*
* Return value:
* IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
**/
static int ipr_reset_block_config_access_wait(struct ipr_cmnd *ipr_cmd)
{
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
int rc = IPR_RC_JOB_CONTINUE;
if (pci_cfg_access_trylock(ioa_cfg->pdev)) {
ioa_cfg->cfg_locked = 1;
ipr_cmd->job_step = ioa_cfg->reset;
} else {
if (ipr_cmd->u.time_left) {
rc = IPR_RC_JOB_RETURN;
ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
ipr_reset_start_timer(ipr_cmd,
IPR_CHECK_FOR_RESET_TIMEOUT);
} else {
ipr_cmd->job_step = ioa_cfg->reset;
dev_err(&ioa_cfg->pdev->dev,
"Timed out waiting to lock config access. Resetting anyway.\n");
}
}
return rc;
}
/**
* ipr_reset_block_config_access - Block config access to the IOA
* @ipr_cmd: ipr command struct
*
* Description: This attempts to block config access to the IOA
*
* Return value:
* IPR_RC_JOB_CONTINUE
**/
static int ipr_reset_block_config_access(struct ipr_cmnd *ipr_cmd)
{
ipr_cmd->ioa_cfg->cfg_locked = 0;
ipr_cmd->job_step = ipr_reset_block_config_access_wait;
ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
return IPR_RC_JOB_CONTINUE;
}
/** /**
* ipr_reset_allowed - Query whether or not IOA can be reset * ipr_reset_allowed - Query whether or not IOA can be reset
* @ioa_cfg: ioa config struct * @ioa_cfg: ioa config struct
@ -7763,7 +7816,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT; ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT); ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
} else { } else {
ipr_cmd->job_step = ioa_cfg->reset; ipr_cmd->job_step = ipr_reset_block_config_access;
rc = IPR_RC_JOB_CONTINUE; rc = IPR_RC_JOB_CONTINUE;
} }
@ -7796,7 +7849,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32); writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32);
ipr_cmd->job_step = ipr_reset_wait_to_start_bist; ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
} else { } else {
ipr_cmd->job_step = ioa_cfg->reset; ipr_cmd->job_step = ipr_reset_block_config_access;
} }
ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT; ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;

View File

@ -1387,6 +1387,7 @@ struct ipr_ioa_cfg {
u8 msi_received:1; u8 msi_received:1;
u8 sis64:1; u8 sis64:1;
u8 dump_timeout:1; u8 dump_timeout:1;
u8 cfg_locked:1;
u8 revid; u8 revid;

View File

@ -45,77 +45,12 @@ to_uio_pci_generic_dev(struct uio_info *info)
static irqreturn_t irqhandler(int irq, struct uio_info *info) static irqreturn_t irqhandler(int irq, struct uio_info *info)
{ {
struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info); struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
struct pci_dev *pdev = gdev->pdev;
irqreturn_t ret = IRQ_NONE;
u32 cmd_status_dword;
u16 origcmd, newcmd, status;
/* We do a single dword read to retrieve both command and status. if (!pci_check_and_mask_intx(gdev->pdev))
* Document assumptions that make this possible. */ return IRQ_NONE;
BUILD_BUG_ON(PCI_COMMAND % 4);
BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
pci_block_user_cfg_access(pdev);
/* Read both command and status registers in a single 32-bit operation.
* Note: we could cache the value for command and move the status read
* out of the lock if there was a way to get notified of user changes
* to command register through sysfs. Should be good for shared irqs. */
pci_read_config_dword(pdev, PCI_COMMAND, &cmd_status_dword);
origcmd = cmd_status_dword;
status = cmd_status_dword >> 16;
/* Check interrupt status register to see whether our device
* triggered the interrupt. */
if (!(status & PCI_STATUS_INTERRUPT))
goto done;
/* We triggered the interrupt, disable it. */
newcmd = origcmd | PCI_COMMAND_INTX_DISABLE;
if (newcmd != origcmd)
pci_write_config_word(pdev, PCI_COMMAND, newcmd);
/* UIO core will signal the user process. */ /* UIO core will signal the user process. */
ret = IRQ_HANDLED; return IRQ_HANDLED;
done:
pci_unblock_user_cfg_access(pdev);
return ret;
}
/* Verify that the device supports Interrupt Disable bit in command register,
* per PCI 2.3, by flipping this bit and reading it back: this bit was readonly
* in PCI 2.2. */
static int __devinit verify_pci_2_3(struct pci_dev *pdev)
{
u16 orig, new;
int err = 0;
pci_block_user_cfg_access(pdev);
pci_read_config_word(pdev, PCI_COMMAND, &orig);
pci_write_config_word(pdev, PCI_COMMAND,
orig ^ PCI_COMMAND_INTX_DISABLE);
pci_read_config_word(pdev, PCI_COMMAND, &new);
/* There's no way to protect against
* hardware bugs or detect them reliably, but as long as we know
* what the value should be, let's go ahead and check it. */
if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
err = -EBUSY;
dev_err(&pdev->dev, "Command changed from 0x%x to 0x%x: "
"driver or HW bug?\n", orig, new);
goto err;
}
if (!((new ^ orig) & PCI_COMMAND_INTX_DISABLE)) {
dev_warn(&pdev->dev, "Device does not support "
"disabling interrupts: unable to bind.\n");
err = -ENODEV;
goto err;
}
/* Now restore the original value. */
pci_write_config_word(pdev, PCI_COMMAND, orig);
err:
pci_unblock_user_cfg_access(pdev);
return err;
} }
static int __devinit probe(struct pci_dev *pdev, static int __devinit probe(struct pci_dev *pdev,
@ -138,9 +73,10 @@ static int __devinit probe(struct pci_dev *pdev,
return -ENODEV; return -ENODEV;
} }
err = verify_pci_2_3(pdev); if (!pci_intx_mask_supported(pdev)) {
if (err) err = -ENODEV;
goto err_verify; goto err_verify;
}
gdev = kzalloc(sizeof(struct uio_pci_generic_dev), GFP_KERNEL); gdev = kzalloc(sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
if (!gdev) { if (!gdev) {

View File

@ -111,7 +111,7 @@ enum {
PCI_NUM_RESOURCES, PCI_NUM_RESOURCES,
/* preserve this for compatibility */ /* preserve this for compatibility */
DEVICE_COUNT_RESOURCE DEVICE_COUNT_RESOURCE = PCI_NUM_RESOURCES,
}; };
typedef int __bitwise pci_power_t; typedef int __bitwise pci_power_t;
@ -308,7 +308,7 @@ struct pci_dev {
unsigned int is_added:1; unsigned int is_added:1;
unsigned int is_busmaster:1; /* device is busmaster */ unsigned int is_busmaster:1; /* device is busmaster */
unsigned int no_msi:1; /* device may not use msi */ unsigned int no_msi:1; /* device may not use msi */
unsigned int block_ucfg_access:1; /* userspace config space access is blocked */ unsigned int block_cfg_access:1; /* config space access is blocked */
unsigned int broken_parity_status:1; /* Device generates false positive parity */ unsigned int broken_parity_status:1; /* Device generates false positive parity */
unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */ unsigned int irq_reroute_variant:2; /* device needs IRQ rerouting variant */
unsigned int msi_enabled:1; unsigned int msi_enabled:1;
@ -661,17 +661,13 @@ extern struct pci_bus *pci_find_bus(int domain, int busnr);
void pci_bus_add_devices(const struct pci_bus *bus); void pci_bus_add_devices(const struct pci_bus *bus);
struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata); struct pci_ops *ops, void *sysdata);
static inline struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
void *sysdata) struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
{ struct pci_ops *ops, void *sysdata,
struct pci_bus *root_bus; struct list_head *resources);
root_bus = pci_scan_bus_parented(NULL, bus, ops, sysdata); struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
if (root_bus) struct pci_ops *ops, void *sysdata,
pci_bus_add_devices(root_bus); struct list_head *resources);
return root_bus;
}
struct pci_bus *pci_create_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
int busnr); int busnr);
void pcie_update_link_speed(struct pci_bus *bus, u16 link_status); void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
@ -795,8 +791,11 @@ static inline int pci_is_managed(struct pci_dev *pdev)
} }
void pci_disable_device(struct pci_dev *dev); void pci_disable_device(struct pci_dev *dev);
extern unsigned int pcibios_max_latency;
void pci_set_master(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev);
void pci_clear_master(struct pci_dev *dev); void pci_clear_master(struct pci_dev *dev);
int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
int pci_set_cacheline_size(struct pci_dev *dev); int pci_set_cacheline_size(struct pci_dev *dev);
#define HAVE_PCI_SET_MWI #define HAVE_PCI_SET_MWI
@ -804,6 +803,9 @@ int __must_check pci_set_mwi(struct pci_dev *dev);
int pci_try_set_mwi(struct pci_dev *dev); int pci_try_set_mwi(struct pci_dev *dev);
void pci_clear_mwi(struct pci_dev *dev); void pci_clear_mwi(struct pci_dev *dev);
void pci_intx(struct pci_dev *dev, int enable); void pci_intx(struct pci_dev *dev, int enable);
bool pci_intx_mask_supported(struct pci_dev *dev);
bool pci_check_and_mask_intx(struct pci_dev *dev);
bool pci_check_and_unmask_intx(struct pci_dev *dev);
void pci_msi_off(struct pci_dev *dev); void pci_msi_off(struct pci_dev *dev);
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size); int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size);
int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask); int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask);
@ -911,6 +913,8 @@ int pci_request_selected_regions_exclusive(struct pci_dev *, int, const char *);
void pci_release_selected_regions(struct pci_dev *, int); void pci_release_selected_regions(struct pci_dev *, int);
/* drivers/pci/bus.c */ /* drivers/pci/bus.c */
void pci_add_resource(struct list_head *resources, struct resource *res);
void pci_free_resource_list(struct list_head *resources);
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags); void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags);
struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n); struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
void pci_bus_remove_resources(struct pci_bus *bus); void pci_bus_remove_resources(struct pci_bus *bus);
@ -1085,8 +1089,9 @@ int ht_create_irq(struct pci_dev *dev, int idx);
void ht_destroy_irq(unsigned int irq); void ht_destroy_irq(unsigned int irq);
#endif /* CONFIG_HT_IRQ */ #endif /* CONFIG_HT_IRQ */
extern void pci_block_user_cfg_access(struct pci_dev *dev); extern void pci_cfg_access_lock(struct pci_dev *dev);
extern void pci_unblock_user_cfg_access(struct pci_dev *dev); extern bool pci_cfg_access_trylock(struct pci_dev *dev);
extern void pci_cfg_access_unlock(struct pci_dev *dev);
/* /*
* PCI domain support. Sometimes called PCI segment (eg by ACPI), * PCI domain support. Sometimes called PCI segment (eg by ACPI),
@ -1283,10 +1288,13 @@ static inline void pci_release_regions(struct pci_dev *dev)
#define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0) #define pci_dma_burst_advice(pdev, strat, strategy_parameter) do { } while (0)
static inline void pci_block_user_cfg_access(struct pci_dev *dev) static inline void pci_block_cfg_access(struct pci_dev *dev)
{ } { }
static inline void pci_unblock_user_cfg_access(struct pci_dev *dev) static inline int pci_block_cfg_access_in_atomic(struct pci_dev *dev)
{ return 0; }
static inline void pci_unblock_cfg_access(struct pci_dev *dev)
{ } { }
static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from) static inline struct pci_bus *pci_find_next_bus(const struct pci_bus *from)
@ -1424,10 +1432,10 @@ static inline void pci_fixup_device(enum pci_fixup_pass pass,
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen); void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr); void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr);
void __iomem * const *pcim_iomap_table(struct pci_dev *pdev); void __iomem * const *pcim_iomap_table(struct pci_dev *pdev);
int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name); int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name);
int pcim_iomap_regions_request_all(struct pci_dev *pdev, u16 mask, int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
const char *name); const char *name);
void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask); void pcim_iounmap_regions(struct pci_dev *pdev, int mask);
extern int pci_pci_problems; extern int pci_pci_problems;
#define PCIPCI_FAIL 1 /* No PCI PCI DMA */ #define PCIPCI_FAIL 1 /* No PCI PCI DMA */
@ -1446,8 +1454,10 @@ extern u8 pci_cache_line_size;
extern unsigned long pci_hotplug_io_size; extern unsigned long pci_hotplug_io_size;
extern unsigned long pci_hotplug_mem_size; extern unsigned long pci_hotplug_mem_size;
/* Architecture specific versions may override these (weak) */
int pcibios_add_platform_entries(struct pci_dev *dev); int pcibios_add_platform_entries(struct pci_dev *dev);
void pcibios_disable_device(struct pci_dev *dev); void pcibios_disable_device(struct pci_dev *dev);
void pcibios_set_master(struct pci_dev *dev);
int pcibios_set_pcie_reset_state(struct pci_dev *dev, int pcibios_set_pcie_reset_state(struct pci_dev *dev,
enum pcie_reset_state state); enum pcie_reset_state state);

View File

@ -776,6 +776,29 @@
#define PCI_DEVICE_ID_ELSA_QS3000 0x3000 #define PCI_DEVICE_ID_ELSA_QS3000 0x3000
#define PCI_VENDOR_ID_STMICRO 0x104A #define PCI_VENDOR_ID_STMICRO 0x104A
#define PCI_DEVICE_ID_STMICRO_USB_HOST 0xCC00
#define PCI_DEVICE_ID_STMICRO_USB_OHCI 0xCC01
#define PCI_DEVICE_ID_STMICRO_USB_OTG 0xCC02
#define PCI_DEVICE_ID_STMICRO_UART_HWFC 0xCC03
#define PCI_DEVICE_ID_STMICRO_UART_NO_HWFC 0xCC04
#define PCI_DEVICE_ID_STMICRO_SOC_DMA 0xCC05
#define PCI_DEVICE_ID_STMICRO_SATA 0xCC06
#define PCI_DEVICE_ID_STMICRO_I2C 0xCC07
#define PCI_DEVICE_ID_STMICRO_SPI_HS 0xCC08
#define PCI_DEVICE_ID_STMICRO_MAC 0xCC09
#define PCI_DEVICE_ID_STMICRO_SDIO_EMMC 0xCC0A
#define PCI_DEVICE_ID_STMICRO_SDIO 0xCC0B
#define PCI_DEVICE_ID_STMICRO_GPIO 0xCC0C
#define PCI_DEVICE_ID_STMICRO_VIP 0xCC0D
#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA 0xCC0E
#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_SRCS 0xCC0F
#define PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_MSPS 0xCC10
#define PCI_DEVICE_ID_STMICRO_CAN 0xCC11
#define PCI_DEVICE_ID_STMICRO_MLB 0xCC12
#define PCI_DEVICE_ID_STMICRO_DBP 0xCC13
#define PCI_DEVICE_ID_STMICRO_SATA_PHY 0xCC14
#define PCI_DEVICE_ID_STMICRO_ESRAM 0xCC15
#define PCI_DEVICE_ID_STMICRO_VIC 0xCC16
#define PCI_VENDOR_ID_BUSLOGIC 0x104B #define PCI_VENDOR_ID_BUSLOGIC 0x104B
#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140 #define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140

View File

@ -392,7 +392,7 @@
#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */ #define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */ #define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCI/PCI-X Bridge */
#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */ #define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
#define PCI_EXP_TYPE_RC_EC 0x10 /* Root Complex Event Collector */ #define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */ #define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */ #define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
#define PCI_EXP_DEVCAP 4 /* Device capabilities */ #define PCI_EXP_DEVCAP 4 /* Device capabilities */

View File

@ -304,7 +304,7 @@ EXPORT_SYMBOL(pcim_iounmap);
* *
* Request and iomap regions specified by @mask. * Request and iomap regions specified by @mask.
*/ */
int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name) int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
{ {
void __iomem * const *iomap; void __iomem * const *iomap;
int i, rc; int i, rc;
@ -357,7 +357,7 @@ EXPORT_SYMBOL(pcim_iomap_regions);
* *
* Request all PCI BARs and iomap regions specified by @mask. * Request all PCI BARs and iomap regions specified by @mask.
*/ */
int pcim_iomap_regions_request_all(struct pci_dev *pdev, u16 mask, int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
const char *name) const char *name)
{ {
int request_mask = ((1 << 6) - 1) & ~mask; int request_mask = ((1 << 6) - 1) & ~mask;
@ -381,7 +381,7 @@ EXPORT_SYMBOL(pcim_iomap_regions_request_all);
* *
* Unmap and release regions specified by @mask. * Unmap and release regions specified by @mask.
*/ */
void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask) void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
{ {
void __iomem * const *iomap; void __iomem * const *iomap;
int i; int i;