mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-24 12:44:11 +08:00
PCI changes for the 3.6 merge window:
Host bridge hotplug - Add MMCONFIG support for hot-added host bridges (Jiang Liu) Device hotplug - Move fixups from __init to __devinit (Sebastian Andrzej Siewior) - Call FINAL fixups for hot-added devices, too (Myron Stowe) - Factor out generic code for P2P bridge hot-add (Yinghai Lu) - Remove all functions in a slot, not just those with _EJx (Amos Kong) Dynamic resource management - Track bus number allocation (struct resource tree per domain) (Yinghai Lu) - Make P2P bridge 1K I/O windows work with resource reassignment (Bjorn Helgaas, Yinghai Lu) - Disable decoding while updating 64-bit BARs (Bjorn Helgaas) Power management - Add PCIe runtime D3cold support (Huang Ying) Virtualization - Add VFIO infrastructure (ACS, DMA source ID quirks) (Alex Williamson) - Add quirks for devices with broken INTx masking (Jan Kiszka) Miscellaneous - Fix some PCI Express capability version issues (Myron Stowe) - Factor out some arch code with a weak, generic, pcibios_setup() (Myron Stowe) -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) iQIcBAABAgAGBQJQBy+9AAoJEPGMOI97Hn6zOpQP+wVFvA7pcteFj6HPs5nTq2Hc 55oeRqCO0wBHoFMCKB0AjeTATjqxi9OhcjaiVrZejxNyWKC9MnrXuunpQ0l/hCbR M/TK+BCelfX2FU4eXNf+TBCCcOhOVWqQft9Gm6nYKwX8Y0msRVCceI4WwhZgSwtI vdtmnqlwolscdnq+8ThsnvUMtwkN0gExmn2FJRl6EoEgG0DTqhMkZ83uA+NPBhvv I+g0XbA6haaZph2nnSYR0hIW4Q7JkT/LgA6uVAQxamctwxLol7xxsjCRnfqrulkf kaRr2fAgBXfmaOIltro4UkXrCM52ZSyggCDfExHp6mWGPKMjE5ZcyK1YbGfmmumk DS3t1S0eBdDJXrnf9l/Yb8e95dQxRCYKelKzr1rTD9QAXsInE8rC40hvhfFaTa4s nZYRTz0SKv6coQihqaOR7shx1DNomLFk7jndaWEElfl9/cT/nQnZ8XLfVMzkJNNB Y4SM6zkiIaCL0aiSEE16MqVjmODYRjbURLYzQIrqr2KJQg8X6XjIRojQLjL6xEgA 22ry2ZRPhqO68g7aLqvixiSDaTp0Z0Vw+JmgjtBqvkokwZcGQtm4umkpAdOi+Es8 3bJaMY7ZUpDX53FE8iyP6AnmR/1k19rC1gNnNq/syWyjtYOYJ9i3QCTafFgvE1VC 5coQ1L5tByHvpzK5PHwf =oo/A -----END PGP SIGNATURE----- Merge tag 'for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci Pull PCI changes from Bjorn Helgaas: "Host bridge hotplug: - Add MMCONFIG support for hot-added host bridges (Jiang Liu) Device hotplug: - Move fixups from __init to __devinit (Sebastian Andrzej Siewior) - Call FINAL fixups for hot-added devices, too (Myron Stowe) - Factor out generic code for P2P bridge hot-add (Yinghai Lu) - Remove all functions in a slot, not just those with _EJx (Amos Kong) Dynamic resource management: - Track bus number allocation (struct resource tree per domain) (Yinghai Lu) - Make P2P bridge 1K I/O windows work with resource reassignment (Bjorn Helgaas, Yinghai Lu) - Disable decoding while updating 64-bit BARs (Bjorn Helgaas) Power management: - Add PCIe runtime D3cold support (Huang Ying) Virtualization: - Add VFIO infrastructure (ACS, DMA source ID quirks) (Alex Williamson) - Add quirks for devices with broken INTx masking (Jan Kiszka) Miscellaneous: - Fix some PCI Express capability version issues (Myron Stowe) - Factor out some arch code with a weak, generic, pcibios_setup() (Myron Stowe)" * tag 'for-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (122 commits) PCI: hotplug: ensure a consistent return value in error case PCI: fix undefined reference to 'pci_fixup_final_inited' PCI: build resource code for M68K architecture PCI: pciehp: remove unused pciehp_get_max_lnk_width(), pciehp_get_cur_lnk_width() PCI: reorder __pci_assign_resource() (no change) PCI: fix truncation of resource size to 32 bits PCI: acpiphp: merge acpiphp_debug and debug PCI: acpiphp: remove unused res_lock sparc/PCI: replace pci_cfg_fake_ranges() with pci_read_bridge_bases() PCI: call final fixups hot-added devices PCI: move final fixups from __init to __devinit x86/PCI: move final fixups from __init to __devinit MIPS/PCI: move final fixups from __init to __devinit PCI: support sizing P2P bridge I/O windows with 1K granularity PCI: reimplement P2P bridge 1K I/O windows (Intel P64H2) PCI: disable MEM decoding while updating 64-bit MEM BARs PCI: leave MEM and IO decoding disabled during 64-bit BAR sizing, too PCI: never discard enable/suspend/resume_early/resume fixups PCI: release temporary reference in __nv_msi_ht_cap_quirk() PCI: restructure 'pci_do_fixups()' ...
This commit is contained in:
commit
6dd53aa456
@ -5210,7 +5210,7 @@ PCI SUBSYSTEM
|
||||
M: Bjorn Helgaas <bhelgaas@google.com>
|
||||
L: linux-pci@vger.kernel.org
|
||||
Q: http://patchwork.ozlabs.org/project/linux-pci/list/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/linux.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git
|
||||
S: Supported
|
||||
F: Documentation/PCI/
|
||||
F: drivers/pci/
|
||||
|
@ -59,15 +59,13 @@ struct pci_controller *pci_isa_hose;
|
||||
* Quirks.
|
||||
*/
|
||||
|
||||
static void __init
|
||||
quirk_isa_bridge(struct pci_dev *dev)
|
||||
static void __devinit quirk_isa_bridge(struct pci_dev *dev)
|
||||
{
|
||||
dev->class = PCI_CLASS_BRIDGE_ISA << 8;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
|
||||
|
||||
static void __init
|
||||
quirk_cypress(struct pci_dev *dev)
|
||||
static void __devinit quirk_cypress(struct pci_dev *dev)
|
||||
{
|
||||
/* The Notorious Cy82C693 chip. */
|
||||
|
||||
@ -106,8 +104,7 @@ quirk_cypress(struct pci_dev *dev)
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, quirk_cypress);
|
||||
|
||||
/* Called for each device after PCI setup is done. */
|
||||
static void __init
|
||||
pcibios_fixup_final(struct pci_dev *dev)
|
||||
static void __devinit pcibios_fixup_final(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int class = dev->class >> 8;
|
||||
|
||||
@ -198,12 +195,6 @@ pcibios_init(void)
|
||||
|
||||
subsys_initcall(pcibios_init);
|
||||
|
||||
char * __devinit
|
||||
pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
#ifdef ALPHA_RESTORE_SRM_SETUP
|
||||
static struct pdev_srm_saved_conf *srm_saved_configs;
|
||||
|
||||
@ -359,7 +350,7 @@ common_init_pci(void)
|
||||
hose, &resources);
|
||||
hose->bus = bus;
|
||||
hose->need_domain_info = need_domain_info;
|
||||
next_busno = bus->subordinate + 1;
|
||||
next_busno = bus->busn_res.end + 1;
|
||||
/* Don't allow 8-bit bus number overflow inside the hose -
|
||||
reserve some space for bridges. */
|
||||
if (next_busno > 224) {
|
||||
|
@ -253,7 +253,7 @@ static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, pci_fixup_cy82c693);
|
||||
|
||||
static void __init pci_fixup_it8152(struct pci_dev *dev)
|
||||
static void __devinit pci_fixup_it8152(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
/* fixup for ITE 8152 devices */
|
||||
@ -461,7 +461,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
|
||||
if (!sys->bus)
|
||||
panic("PCI: unable to scan bus!");
|
||||
|
||||
busnr = sys->bus->subordinate + 1;
|
||||
busnr = sys->bus->busn_res.end + 1;
|
||||
|
||||
list_add(&sys->node, head);
|
||||
} else {
|
||||
|
@ -6,11 +6,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *b)
|
||||
{
|
||||
}
|
||||
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pcibios_set_master(struct pci_dev *dev)
|
||||
{
|
||||
u8 lat;
|
||||
|
@ -268,7 +268,7 @@ static void __init pci_fixup_umc_ide(struct pci_dev *d)
|
||||
d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
|
||||
}
|
||||
|
||||
static void __init pci_fixup_ide_bases(struct pci_dev *d)
|
||||
static void __devinit pci_fixup_ide_bases(struct pci_dev *d)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -287,7 +287,7 @@ static void __init pci_fixup_ide_bases(struct pci_dev *d)
|
||||
}
|
||||
}
|
||||
|
||||
static void __init pci_fixup_ide_trash(struct pci_dev *d)
|
||||
static void __devinit pci_fixup_ide_trash(struct pci_dev *d)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -351,6 +351,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
#endif
|
||||
|
||||
INIT_LIST_HEAD(&info.resources);
|
||||
/* insert busn resource at first */
|
||||
pci_add_resource(&info.resources, &root->secondary);
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
|
||||
&windows);
|
||||
if (windows) {
|
||||
@ -384,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pbus->subordinate = pci_scan_child_bus(pbus);
|
||||
pci_scan_child_bus(pbus);
|
||||
return pbus;
|
||||
|
||||
out3:
|
||||
@ -496,15 +498,6 @@ pcibios_align_resource (void *data, const struct resource *res,
|
||||
return res->start;
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI BIOS setup, always defaults to SAL interface
|
||||
*/
|
||||
char * __init
|
||||
pcibios_setup (char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
int
|
||||
pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
enum pci_mmap_state mmap_state, int write_combine)
|
||||
|
@ -192,11 +192,6 @@ void pcibios_set_master(struct pci_dev *dev)
|
||||
/* No special bus mastering setup handling */
|
||||
}
|
||||
|
||||
char __devinit *pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads the interrupt pin to determine if interrupt is use by card.
|
||||
* If the interrupt is used, then gets the interrupt line from the
|
||||
@ -1504,10 +1499,10 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
|
||||
pci_free_resource_list(&resources);
|
||||
return;
|
||||
}
|
||||
bus->secondary = hose->first_busno;
|
||||
bus->busn_res.start = hose->first_busno;
|
||||
hose->bus = bus;
|
||||
|
||||
hose->last_busno = bus->subordinate;
|
||||
hose->last_busno = bus->busn_res.end;
|
||||
}
|
||||
|
||||
static int __init pcibios_init(void)
|
||||
|
@ -102,7 +102,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
|
||||
need_domain_info = need_domain_info || hose->index;
|
||||
hose->need_domain_info = need_domain_info;
|
||||
if (bus) {
|
||||
next_busno = bus->subordinate + 1;
|
||||
next_busno = bus->busn_res.end + 1;
|
||||
/* Don't allow 8-bit bus number overflow inside the hose -
|
||||
reserve some space for bridges. */
|
||||
if (next_busno > 224) {
|
||||
@ -348,9 +348,9 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
|
||||
vma->vm_end - vma->vm_start, vma->vm_page_prot);
|
||||
}
|
||||
|
||||
char * (*pcibios_plat_setup)(char *str) __devinitdata;
|
||||
char * (*pcibios_plat_setup)(char *str) __initdata;
|
||||
|
||||
char *__devinit pcibios_setup(char *str)
|
||||
char *__init pcibios_setup(char *str)
|
||||
{
|
||||
if (pcibios_plat_setup)
|
||||
return pcibios_plat_setup(str);
|
||||
|
@ -395,17 +395,6 @@ void __init pcibios_init(void)
|
||||
pci_scan_bus(3, &titan_pci_ops, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* for parsing "pci=" kernel boot arguments.
|
||||
*/
|
||||
char *pcibios_setup(char *str)
|
||||
{
|
||||
printk(KERN_INFO "rr: pcibios_setup\n");
|
||||
/* Nothing to do for now. */
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
unsigned __init int pcibios_assign_all_busses(void)
|
||||
{
|
||||
/* We want to use the PCI bus detection done by PMON */
|
||||
|
@ -256,7 +256,7 @@ static irqreturn_t i8259_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int __init
|
||||
static int __devinit
|
||||
txx9_i8259_irq_setup(int irq)
|
||||
{
|
||||
int err;
|
||||
@ -398,9 +398,9 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
return txx9_board_vec->pci_map_irq(dev, slot, pin);
|
||||
}
|
||||
|
||||
char * (*txx9_board_pcibios_setup)(char *str) __devinitdata;
|
||||
char * (*txx9_board_pcibios_setup)(char *str) __initdata;
|
||||
|
||||
char *__devinit txx9_pcibios_setup(char *str)
|
||||
char *__init txx9_pcibios_setup(char *str)
|
||||
{
|
||||
if (txx9_board_pcibios_setup && !txx9_board_pcibios_setup(str))
|
||||
return NULL;
|
||||
|
@ -139,11 +139,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
|
||||
}
|
||||
|
||||
|
||||
char *pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by pci_set_master() - a driver interface.
|
||||
*
|
||||
|
@ -30,6 +30,7 @@ struct pci_controller {
|
||||
int first_busno;
|
||||
int last_busno;
|
||||
int self_busno;
|
||||
struct resource busn;
|
||||
|
||||
void __iomem *io_base_virt;
|
||||
#ifdef CONFIG_PPC64
|
||||
|
@ -200,11 +200,6 @@ int pcibios_add_platform_entries(struct pci_dev *pdev)
|
||||
return device_create_file(&pdev->dev, &dev_attr_devspec);
|
||||
}
|
||||
|
||||
char __devinit *pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads the interrupt pin to determine if interrupt is use by card.
|
||||
* If the interrupt is used, then gets the interrupt line from the
|
||||
@ -1635,6 +1630,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
|
||||
/* Wire up PHB bus resources */
|
||||
pcibios_setup_phb_resources(hose, &resources);
|
||||
|
||||
hose->busn.start = hose->first_busno;
|
||||
hose->busn.end = hose->last_busno;
|
||||
hose->busn.flags = IORESOURCE_BUS;
|
||||
pci_add_resource(&resources, &hose->busn);
|
||||
|
||||
/* Create an empty bus for the toplevel */
|
||||
bus = pci_create_root_bus(hose->parent, hose->first_busno,
|
||||
hose->ops, hose, &resources);
|
||||
@ -1651,13 +1651,14 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
|
||||
if (node && ppc_md.pci_probe_mode)
|
||||
mode = ppc_md.pci_probe_mode(bus);
|
||||
pr_debug(" probe mode: %d\n", mode);
|
||||
if (mode == PCI_PROBE_DEVTREE) {
|
||||
bus->subordinate = hose->last_busno;
|
||||
if (mode == PCI_PROBE_DEVTREE)
|
||||
of_scan_bus(node, bus);
|
||||
}
|
||||
|
||||
if (mode == PCI_PROBE_NORMAL)
|
||||
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
|
||||
if (mode == PCI_PROBE_NORMAL) {
|
||||
pci_bus_update_busn_res_end(bus, 255);
|
||||
hose->last_busno = pci_scan_child_bus(bus);
|
||||
pci_bus_update_busn_res_end(bus, hose->last_busno);
|
||||
}
|
||||
|
||||
/* Platform gets a chance to do some global fixups before
|
||||
* we proceed to resource allocation
|
||||
|
@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
|
||||
|
||||
for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
|
||||
bus = pci_bus_b(ln);
|
||||
if (in_bus >= bus->number && in_bus <= bus->subordinate)
|
||||
if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
|
||||
break;
|
||||
bus = NULL;
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
bus->primary = dev->bus->number;
|
||||
bus->subordinate = busrange[1];
|
||||
pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
|
||||
bus->bridge_ctl = 0;
|
||||
|
||||
/* parse ranges property */
|
||||
|
@ -102,7 +102,7 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m)
|
||||
seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
|
||||
}
|
||||
|
||||
static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev)
|
||||
static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
|
@ -164,7 +164,7 @@ static void gef_ppc9a_show_cpuinfo(struct seq_file *m)
|
||||
gef_ppc9a_get_vme_is_syscon() ? "yes" : "no");
|
||||
}
|
||||
|
||||
static void __init gef_ppc9a_nec_fixup(struct pci_dev *pdev)
|
||||
static void __devinit gef_ppc9a_nec_fixup(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
|
@ -152,7 +152,7 @@ static void gef_sbc310_show_cpuinfo(struct seq_file *m)
|
||||
|
||||
}
|
||||
|
||||
static void __init gef_sbc310_nec_fixup(struct pci_dev *pdev)
|
||||
static void __devinit gef_sbc310_nec_fixup(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
|
@ -141,7 +141,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m)
|
||||
seq_printf(m, "SVR\t\t: 0x%x\n", svid);
|
||||
}
|
||||
|
||||
static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev)
|
||||
static void __devinit gef_sbc610_nec_fixup(struct pci_dev *pdev)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
|
@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
|
||||
dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
|
||||
fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
|
||||
parent = pe->pbus->self;
|
||||
count = pe->pbus->subordinate - pe->pbus->secondary + 1;
|
||||
count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
|
||||
switch(count) {
|
||||
case 1: bcomp = OpalPciBusAll; break;
|
||||
case 2: bcomp = OpalPciBus7Bits; break;
|
||||
@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
|
||||
pe->pdev = NULL;
|
||||
pe->tce32_seg = -1;
|
||||
pe->mve_number = -1;
|
||||
pe->rid = bus->secondary << 8;
|
||||
pe->rid = bus->busn_res.start << 8;
|
||||
pe->dma_weight = 0;
|
||||
|
||||
pe_info(pe, "Secondary busses %d..%d associated with PE\n",
|
||||
bus->secondary, bus->subordinate);
|
||||
pe_info(pe, "Secondary busses %pR associated with PE\n",
|
||||
&bus->busn_res);
|
||||
|
||||
if (pnv_ioda_configure_pe(phb, pe)) {
|
||||
/* XXX What do we do here ? */
|
||||
|
@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
|
||||
if (!num)
|
||||
return;
|
||||
pcibios_setup_bus_devices(bus);
|
||||
max = bus->secondary;
|
||||
max = bus->busn_res.start;
|
||||
for (pass=0; pass < 2; pass++)
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
|
@ -104,7 +104,7 @@ subsys_initcall(mv64x60_sysfs_init);
|
||||
|
||||
#endif /* CONFIG_SYSFS */
|
||||
|
||||
static void __init mv64x60_pci_fixup_early(struct pci_dev *dev)
|
||||
static void __devinit mv64x60_pci_fixup_early(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* Set the host bridge hdr_type to an invalid value so that
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <asm/irq.h>
|
||||
#include <mach/pci.h>
|
||||
|
||||
static void __init gapspci_fixup_resources(struct pci_dev *dev)
|
||||
static void __devinit gapspci_fixup_resources(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_channel *p = dev->sysdata;
|
||||
|
||||
|
@ -23,9 +23,9 @@
|
||||
* Misconfigurations can be detected through the FPGA via the slot
|
||||
* resistors to determine card presence. Hotplug remains unsupported.
|
||||
*/
|
||||
static unsigned int slot4en __devinitdata;
|
||||
static unsigned int slot4en __initdata;
|
||||
|
||||
char *__devinit pcibios_setup(char *str)
|
||||
char *__init pcibios_setup(char *str)
|
||||
{
|
||||
if (strcmp(str, "slot4en") == 0) {
|
||||
slot4en = 1;
|
||||
|
@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
|
||||
need_domain_info = need_domain_info || hose->index;
|
||||
hose->need_domain_info = need_domain_info;
|
||||
if (bus) {
|
||||
next_busno = bus->subordinate + 1;
|
||||
next_busno = bus->busn_res.end + 1;
|
||||
/* Don't allow 8-bit bus number overflow inside the hose -
|
||||
reserve some space for bridges. */
|
||||
if (next_busno > 224) {
|
||||
@ -197,11 +197,6 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
|
||||
}
|
||||
|
||||
char * __devinit __weak pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
static void __init
|
||||
pcibios_bus_report_status_early(struct pci_channel *hose,
|
||||
int top_bus, int current_bus,
|
||||
|
@ -91,14 +91,6 @@ void __devinit pcibios_fixup_bus(struct pci_bus *pbus)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Other archs parse arguments here.
|
||||
*/
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
{
|
||||
|
@ -375,93 +375,6 @@ static void __devinit apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
|
||||
*last_p = last;
|
||||
}
|
||||
|
||||
/* For PCI bus devices which lack a 'ranges' property we interrogate
|
||||
* the config space values to set the resources, just like the generic
|
||||
* Linux PCI probing code does.
|
||||
*/
|
||||
static void __devinit pci_cfg_fake_ranges(struct pci_dev *dev,
|
||||
struct pci_bus *bus,
|
||||
struct pci_pbm_info *pbm)
|
||||
{
|
||||
struct pci_bus_region region;
|
||||
struct resource *res, res2;
|
||||
u8 io_base_lo, io_limit_lo;
|
||||
u16 mem_base_lo, mem_limit_lo;
|
||||
unsigned long base, limit;
|
||||
|
||||
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
|
||||
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
|
||||
base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
|
||||
limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
|
||||
|
||||
if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
|
||||
u16 io_base_hi, io_limit_hi;
|
||||
|
||||
pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
|
||||
pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
|
||||
base |= (io_base_hi << 16);
|
||||
limit |= (io_limit_hi << 16);
|
||||
}
|
||||
|
||||
res = bus->resource[0];
|
||||
if (base <= limit) {
|
||||
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
|
||||
res2.flags = res->flags;
|
||||
region.start = base;
|
||||
region.end = limit + 0xfff;
|
||||
pcibios_bus_to_resource(dev, &res2, ®ion);
|
||||
if (!res->start)
|
||||
res->start = res2.start;
|
||||
if (!res->end)
|
||||
res->end = res2.end;
|
||||
}
|
||||
|
||||
pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
|
||||
pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
|
||||
base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
|
||||
limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
|
||||
|
||||
res = bus->resource[1];
|
||||
if (base <= limit) {
|
||||
res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
|
||||
IORESOURCE_MEM);
|
||||
region.start = base;
|
||||
region.end = limit + 0xfffff;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
}
|
||||
|
||||
pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
|
||||
pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
|
||||
base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
|
||||
limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
|
||||
|
||||
if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
|
||||
u32 mem_base_hi, mem_limit_hi;
|
||||
|
||||
pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
|
||||
pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
|
||||
|
||||
/*
|
||||
* Some bridges set the base > limit by default, and some
|
||||
* (broken) BIOSes do not initialize them. If we find
|
||||
* this, just assume they are not being used.
|
||||
*/
|
||||
if (mem_base_hi <= mem_limit_hi) {
|
||||
base |= ((long) mem_base_hi) << 32;
|
||||
limit |= ((long) mem_limit_hi) << 32;
|
||||
}
|
||||
}
|
||||
|
||||
res = bus->resource[2];
|
||||
if (base <= limit) {
|
||||
res->flags = ((mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) |
|
||||
IORESOURCE_MEM | IORESOURCE_PREFETCH);
|
||||
region.start = base;
|
||||
region.end = limit + 0xfffff;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cook up fake bus resources for SUNW,simba PCI bridges which lack
|
||||
* a proper 'ranges' property.
|
||||
*/
|
||||
@ -535,7 +448,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
|
||||
}
|
||||
|
||||
bus->primary = dev->bus->number;
|
||||
bus->subordinate = busrange[1];
|
||||
pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
|
||||
bus->bridge_ctl = 0;
|
||||
|
||||
/* parse ranges property, or cook one up by hand for Simba */
|
||||
@ -550,7 +463,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
|
||||
apb_fake_ranges(dev, bus, pbm);
|
||||
goto after_ranges;
|
||||
} else if (ranges == NULL) {
|
||||
pci_cfg_fake_ranges(dev, bus, pbm);
|
||||
pci_read_bridge_bases(bus);
|
||||
goto after_ranges;
|
||||
}
|
||||
i = 1;
|
||||
@ -685,6 +598,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
|
||||
pbm->io_space.start);
|
||||
pci_add_resource_offset(&resources, &pbm->mem_space,
|
||||
pbm->mem_space.start);
|
||||
pbm->busn.start = pbm->pci_first_busno;
|
||||
pbm->busn.end = pbm->pci_last_busno;
|
||||
pbm->busn.flags = IORESOURCE_BUS;
|
||||
pci_add_resource(&resources, &pbm->busn);
|
||||
bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
|
||||
pbm, &resources);
|
||||
if (!bus) {
|
||||
@ -693,8 +610,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
|
||||
pci_free_resource_list(&resources);
|
||||
return NULL;
|
||||
}
|
||||
bus->secondary = pbm->pci_first_busno;
|
||||
bus->subordinate = pbm->pci_last_busno;
|
||||
|
||||
pci_of_scan_bus(pbm, node, bus);
|
||||
pci_bus_add_devices(bus);
|
||||
@ -747,11 +662,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
/* Platform support for /proc/bus/pci/X/Y mmap()s. */
|
||||
|
||||
/* If the user uses a host-bridge as the PCI device, he may use
|
||||
|
@ -97,6 +97,7 @@ struct pci_pbm_info {
|
||||
/* PBM I/O and Memory space resources. */
|
||||
struct resource io_space;
|
||||
struct resource mem_space;
|
||||
struct resource busn;
|
||||
|
||||
/* Base of PCI Config space, can be per-PBM or shared. */
|
||||
unsigned long config_space;
|
||||
|
@ -767,14 +767,6 @@ static void watchdog_reset() {
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Other archs parse arguments here.
|
||||
*/
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
{
|
||||
@ -884,11 +876,6 @@ void __init sun4m_pci_init_IRQ(void)
|
||||
sparc_config.load_profile_irq = pcic_load_profile_irq;
|
||||
}
|
||||
|
||||
int pcibios_assign_resource(struct pci_dev *pdev, int resource)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* This probably belongs here rather than ioport.c because
|
||||
* we do not want this crud linked into SBus kernels.
|
||||
|
@ -310,6 +310,7 @@ int __init pcibios_init(void)
|
||||
if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
|
||||
struct pci_controller *controller = &controllers[i];
|
||||
struct pci_bus *bus;
|
||||
LIST_HEAD(resources);
|
||||
|
||||
if (tile_init_irqs(i, controller)) {
|
||||
pr_err("PCI: Could not initialize IRQs\n");
|
||||
@ -327,9 +328,11 @@ int __init pcibios_init(void)
|
||||
* This is inlined in linux/pci.h and calls into
|
||||
* pci_scan_bus_parented() in probe.c.
|
||||
*/
|
||||
bus = pci_scan_bus(0, controller->ops, controller);
|
||||
pci_add_resource(&resources, &ioport_resource);
|
||||
pci_add_resource(&resources, &iomem_resource);
|
||||
bus = pci_scan_root_bus(NULL, 0, controller->ops, controller, &resources);
|
||||
controller->root_bus = bus;
|
||||
controller->last_busno = bus->subordinate;
|
||||
controller->last_busno = bus->busn_res.end;
|
||||
}
|
||||
}
|
||||
|
||||
@ -366,7 +369,7 @@ int __init pcibios_init(void)
|
||||
*/
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
|
||||
(PCI_SLOT(dev->devfn) == 0)) {
|
||||
next_bus = dev->subordinate;
|
||||
next_bus = dev->busn_res.end;
|
||||
controllers[i].mem_resources[0] =
|
||||
*next_bus->resource[0];
|
||||
controllers[i].mem_resources[1] =
|
||||
@ -400,16 +403,6 @@ 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
|
||||
* do anything.
|
||||
*/
|
||||
char __devinit *pcibios_setup(char *str)
|
||||
{
|
||||
/* Nothing needs to be done. */
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from the generic Linux layer.
|
||||
*/
|
||||
|
@ -296,7 +296,7 @@ static int __init pci_common_init(void)
|
||||
}
|
||||
subsys_initcall(pci_common_init);
|
||||
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
char * __init pcibios_setup(char *str)
|
||||
{
|
||||
if (!strcmp(str, "debug")) {
|
||||
debug_pci = 1;
|
||||
|
@ -104,6 +104,7 @@ struct pci_raw_ops {
|
||||
extern const struct pci_raw_ops *raw_pci_ops;
|
||||
extern const struct pci_raw_ops *raw_pci_ext_ops;
|
||||
|
||||
extern const struct pci_raw_ops pci_mmcfg;
|
||||
extern const struct pci_raw_ops pci_direct_conf1;
|
||||
extern bool port_cf9_safe;
|
||||
|
||||
@ -139,6 +140,12 @@ struct pci_mmcfg_region {
|
||||
|
||||
extern int __init pci_mmcfg_arch_init(void);
|
||||
extern void __init pci_mmcfg_arch_free(void);
|
||||
extern int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg);
|
||||
extern void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg);
|
||||
extern int __devinit pci_mmconfig_insert(struct device *dev,
|
||||
u16 seg, u8 start,
|
||||
u8 end, phys_addr_t addr);
|
||||
extern int pci_mmconfig_delete(u16 seg, u8 start, u8 end);
|
||||
extern struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus);
|
||||
|
||||
extern struct list_head pci_mmcfg_list;
|
||||
|
@ -512,7 +512,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
|
||||
|
||||
#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
|
||||
/* Set correct numa_node information for AMD NB functions */
|
||||
static void __init quirk_amd_nb_node(struct pci_dev *dev)
|
||||
static void __devinit quirk_amd_nb_node(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *nb_ht;
|
||||
unsigned int devfn;
|
||||
|
@ -12,8 +12,13 @@ struct pci_root_info {
|
||||
char name[16];
|
||||
unsigned int res_num;
|
||||
struct resource *res;
|
||||
int busnum;
|
||||
struct pci_sysdata sd;
|
||||
#ifdef CONFIG_PCI_MMCONFIG
|
||||
bool mcfg_added;
|
||||
u16 segment;
|
||||
u8 start_bus;
|
||||
u8 end_bus;
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool pci_use_crs = true;
|
||||
@ -120,6 +125,81 @@ void __init pci_acpi_crs_quirks(void)
|
||||
pci_use_crs ? "nocrs" : "use_crs");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_MMCONFIG
|
||||
static int __devinit check_segment(u16 seg, struct device *dev, char *estr)
|
||||
{
|
||||
if (seg) {
|
||||
dev_err(dev,
|
||||
"%s can't access PCI configuration "
|
||||
"space under this host bridge.\n",
|
||||
estr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Failure in adding MMCFG information is not fatal,
|
||||
* just can't access extended configuration space of
|
||||
* devices under this host bridge.
|
||||
*/
|
||||
dev_warn(dev,
|
||||
"%s can't access extended PCI configuration "
|
||||
"space under this bridge.\n",
|
||||
estr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit setup_mcfg_map(struct pci_root_info *info,
|
||||
u16 seg, u8 start, u8 end,
|
||||
phys_addr_t addr)
|
||||
{
|
||||
int result;
|
||||
struct device *dev = &info->bridge->dev;
|
||||
|
||||
info->start_bus = start;
|
||||
info->end_bus = end;
|
||||
info->mcfg_added = false;
|
||||
|
||||
/* return success if MMCFG is not in use */
|
||||
if (raw_pci_ext_ops && raw_pci_ext_ops != &pci_mmcfg)
|
||||
return 0;
|
||||
|
||||
if (!(pci_probe & PCI_PROBE_MMCONF))
|
||||
return check_segment(seg, dev, "MMCONFIG is disabled,");
|
||||
|
||||
result = pci_mmconfig_insert(dev, seg, start, end, addr);
|
||||
if (result == 0) {
|
||||
/* enable MMCFG if it hasn't been enabled yet */
|
||||
if (raw_pci_ext_ops == NULL)
|
||||
raw_pci_ext_ops = &pci_mmcfg;
|
||||
info->mcfg_added = true;
|
||||
} else if (result != -EEXIST)
|
||||
return check_segment(seg, dev,
|
||||
"fail to add MMCONFIG information,");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void teardown_mcfg_map(struct pci_root_info *info)
|
||||
{
|
||||
if (info->mcfg_added) {
|
||||
pci_mmconfig_delete(info->segment, info->start_bus,
|
||||
info->end_bus);
|
||||
info->mcfg_added = false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
static int __devinit setup_mcfg_map(struct pci_root_info *info,
|
||||
u16 seg, u8 start, u8 end,
|
||||
phys_addr_t addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static void teardown_mcfg_map(struct pci_root_info *info)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static acpi_status
|
||||
resource_to_addr(struct acpi_resource *resource,
|
||||
struct acpi_resource_address64 *addr)
|
||||
@ -234,13 +314,6 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
|
||||
}
|
||||
|
||||
info->res_num++;
|
||||
if (addr.translation_offset)
|
||||
dev_info(&info->bridge->dev, "host bridge window %pR "
|
||||
"(PCI address [%#llx-%#llx])\n",
|
||||
res, res->start - addr.translation_offset,
|
||||
res->end - addr.translation_offset);
|
||||
else
|
||||
dev_info(&info->bridge->dev, "host bridge window %pR\n", res);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
@ -332,8 +405,11 @@ static void __release_pci_root_info(struct pci_root_info *info)
|
||||
|
||||
free_pci_root_info_res(info);
|
||||
|
||||
teardown_mcfg_map(info);
|
||||
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static void release_pci_root_info(struct pci_host_bridge *bridge)
|
||||
{
|
||||
struct pci_root_info *info = bridge->release_data;
|
||||
@ -347,7 +423,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
|
||||
{
|
||||
size_t size;
|
||||
|
||||
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
|
||||
info->bridge = device;
|
||||
|
||||
info->res_num = 0;
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
|
||||
info);
|
||||
@ -360,8 +438,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
|
||||
if (!info->res)
|
||||
return;
|
||||
|
||||
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
|
||||
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
|
||||
info);
|
||||
}
|
||||
@ -373,7 +449,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
int domain = root->segment;
|
||||
int busnum = root->secondary.start;
|
||||
LIST_HEAD(resources);
|
||||
struct pci_bus *bus;
|
||||
struct pci_bus *bus = NULL;
|
||||
struct pci_sysdata *sd;
|
||||
int node;
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
@ -426,6 +502,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
} else {
|
||||
probe_pci_root_info(info, device, busnum, domain);
|
||||
|
||||
/* insert busn res at first */
|
||||
pci_add_resource(&resources, &root->secondary);
|
||||
/*
|
||||
* _CRS with no apertures is normal, so only fall back to
|
||||
* defaults or native bridge info if we're ignoring _CRS.
|
||||
@ -437,10 +515,13 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
x86_pci_root_bus_resources(busnum, &resources);
|
||||
}
|
||||
|
||||
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
|
||||
&resources);
|
||||
if (!setup_mcfg_map(info, domain, (u8)root->secondary.start,
|
||||
(u8)root->secondary.end, root->mcfg_addr))
|
||||
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops,
|
||||
sd, &resources);
|
||||
|
||||
if (bus) {
|
||||
bus->subordinate = pci_scan_child_bus(bus);
|
||||
pci_scan_child_bus(bus);
|
||||
pci_set_host_bridge_release(
|
||||
to_pci_host_bridge(bus->bridge),
|
||||
release_pci_root_info, info);
|
||||
|
@ -121,7 +121,6 @@ static int __init early_fill_mp_bus_info(void)
|
||||
link = (reg >> 8) & 0x03;
|
||||
|
||||
info = alloc_pci_root_info(min_bus, max_bus, node, link);
|
||||
sprintf(info->name, "PCI Bus #%02x", min_bus);
|
||||
}
|
||||
|
||||
/* get the default node and link for left over res */
|
||||
@ -300,9 +299,9 @@ static int __init early_fill_mp_bus_info(void)
|
||||
int busnum;
|
||||
struct pci_root_res *root_res;
|
||||
|
||||
busnum = info->bus_min;
|
||||
printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n",
|
||||
info->bus_min, info->bus_max, info->node, info->link);
|
||||
busnum = info->busn.start;
|
||||
printk(KERN_DEBUG "bus: %pR on node %x link %x\n",
|
||||
&info->busn, info->node, info->link);
|
||||
list_for_each_entry(root_res, &info->resources, list)
|
||||
printk(KERN_DEBUG "bus: %02x %pR\n",
|
||||
busnum, &root_res->res);
|
||||
|
@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
|
||||
return NULL;
|
||||
|
||||
list_for_each_entry(info, &pci_root_infos, list)
|
||||
if (info->bus_min == bus)
|
||||
if (info->busn.start == bus)
|
||||
return info;
|
||||
|
||||
return NULL;
|
||||
@ -24,6 +24,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
|
||||
{
|
||||
struct pci_root_info *info = x86_find_pci_root_info(bus);
|
||||
struct pci_root_res *root_res;
|
||||
struct pci_host_bridge_window *window;
|
||||
bool found = false;
|
||||
|
||||
if (!info)
|
||||
goto default_resources;
|
||||
@ -31,6 +33,16 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
|
||||
printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
|
||||
bus);
|
||||
|
||||
/* already added by acpi ? */
|
||||
list_for_each_entry(window, resources, list)
|
||||
if (window->res->flags & IORESOURCE_BUS) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
pci_add_resource(resources, &info->busn);
|
||||
|
||||
list_for_each_entry(root_res, &info->resources, list) {
|
||||
struct resource *res;
|
||||
struct resource *root;
|
||||
@ -66,9 +78,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
|
||||
if (!info)
|
||||
return info;
|
||||
|
||||
sprintf(info->name, "PCI Bus #%02x", bus_min);
|
||||
|
||||
INIT_LIST_HEAD(&info->resources);
|
||||
info->bus_min = bus_min;
|
||||
info->bus_max = bus_max;
|
||||
info->busn.name = info->name;
|
||||
info->busn.start = bus_min;
|
||||
info->busn.end = bus_max;
|
||||
info->busn.flags = IORESOURCE_BUS;
|
||||
info->node = node;
|
||||
info->link = link;
|
||||
|
||||
|
@ -13,8 +13,7 @@ struct pci_root_info {
|
||||
struct list_head list;
|
||||
char name[12];
|
||||
struct list_head resources;
|
||||
int bus_min;
|
||||
int bus_max;
|
||||
struct resource busn;
|
||||
int node;
|
||||
int link;
|
||||
};
|
||||
|
@ -494,7 +494,7 @@ int __init pcibios_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * __devinit pcibios_setup(char *str)
|
||||
char * __init pcibios_setup(char *str)
|
||||
{
|
||||
if (!strcmp(str, "off")) {
|
||||
pci_probe = 0;
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <asm/e820.h>
|
||||
#include <asm/pci_x86.h>
|
||||
#include <asm/acpi.h>
|
||||
@ -24,7 +26,9 @@
|
||||
#define PREFIX "PCI: "
|
||||
|
||||
/* Indicate if the mmcfg resources have been placed into the resource table. */
|
||||
static int __initdata pci_mmcfg_resources_inserted;
|
||||
static bool pci_mmcfg_running_state;
|
||||
static bool pci_mmcfg_arch_init_failed;
|
||||
static DEFINE_MUTEX(pci_mmcfg_lock);
|
||||
|
||||
LIST_HEAD(pci_mmcfg_list);
|
||||
|
||||
@ -45,24 +49,25 @@ static __init void free_all_mmcfg(void)
|
||||
pci_mmconfig_remove(cfg);
|
||||
}
|
||||
|
||||
static __init void list_add_sorted(struct pci_mmcfg_region *new)
|
||||
static __devinit void list_add_sorted(struct pci_mmcfg_region *new)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
/* keep list sorted by segment and starting bus number */
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list) {
|
||||
list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list) {
|
||||
if (cfg->segment > new->segment ||
|
||||
(cfg->segment == new->segment &&
|
||||
cfg->start_bus >= new->start_bus)) {
|
||||
list_add_tail(&new->list, &cfg->list);
|
||||
list_add_tail_rcu(&new->list, &cfg->list);
|
||||
return;
|
||||
}
|
||||
}
|
||||
list_add_tail(&new->list, &pci_mmcfg_list);
|
||||
list_add_tail_rcu(&new->list, &pci_mmcfg_list);
|
||||
}
|
||||
|
||||
static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
|
||||
int end, u64 addr)
|
||||
static __devinit struct pci_mmcfg_region *pci_mmconfig_alloc(int segment,
|
||||
int start,
|
||||
int end, u64 addr)
|
||||
{
|
||||
struct pci_mmcfg_region *new;
|
||||
struct resource *res;
|
||||
@ -79,8 +84,6 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
|
||||
new->start_bus = start;
|
||||
new->end_bus = end;
|
||||
|
||||
list_add_sorted(new);
|
||||
|
||||
res = &new->res;
|
||||
res->start = addr + PCI_MMCFG_BUS_OFFSET(start);
|
||||
res->end = addr + PCI_MMCFG_BUS_OFFSET(end + 1) - 1;
|
||||
@ -89,9 +92,25 @@ static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
|
||||
"PCI MMCONFIG %04x [bus %02x-%02x]", segment, start, end);
|
||||
res->name = new->name;
|
||||
|
||||
printk(KERN_INFO PREFIX "MMCONFIG for domain %04x [bus %02x-%02x] at "
|
||||
"%pR (base %#lx)\n", segment, start, end, &new->res,
|
||||
(unsigned long) addr);
|
||||
return new;
|
||||
}
|
||||
|
||||
static __init struct pci_mmcfg_region *pci_mmconfig_add(int segment, int start,
|
||||
int end, u64 addr)
|
||||
{
|
||||
struct pci_mmcfg_region *new;
|
||||
|
||||
new = pci_mmconfig_alloc(segment, start, end, addr);
|
||||
if (new) {
|
||||
mutex_lock(&pci_mmcfg_lock);
|
||||
list_add_sorted(new);
|
||||
mutex_unlock(&pci_mmcfg_lock);
|
||||
|
||||
pr_info(PREFIX
|
||||
"MMCONFIG for domain %04x [bus %02x-%02x] at %pR "
|
||||
"(base %#lx)\n",
|
||||
segment, start, end, &new->res, (unsigned long)addr);
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
@ -100,7 +119,7 @@ struct pci_mmcfg_region *pci_mmconfig_lookup(int segment, int bus)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list)
|
||||
list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
|
||||
if (cfg->segment == segment &&
|
||||
cfg->start_bus <= bus && bus <= cfg->end_bus)
|
||||
return cfg;
|
||||
@ -343,8 +362,7 @@ static int __init pci_mmcfg_check_hostbridge(void)
|
||||
name = pci_mmcfg_probes[i].probe();
|
||||
|
||||
if (name)
|
||||
printk(KERN_INFO PREFIX "%s with MMCONFIG support\n",
|
||||
name);
|
||||
pr_info(PREFIX "%s with MMCONFIG support\n", name);
|
||||
}
|
||||
|
||||
/* some end_bus_number is crazy, fix it */
|
||||
@ -353,19 +371,8 @@ static int __init pci_mmcfg_check_hostbridge(void)
|
||||
return !list_empty(&pci_mmcfg_list);
|
||||
}
|
||||
|
||||
static void __init pci_mmcfg_insert_resources(void)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list)
|
||||
insert_resource(&iomem_resource, &cfg->res);
|
||||
|
||||
/* Mark that the resources have been inserted. */
|
||||
pci_mmcfg_resources_inserted = 1;
|
||||
}
|
||||
|
||||
static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
|
||||
void *data)
|
||||
static acpi_status __devinit check_mcfg_resource(struct acpi_resource *res,
|
||||
void *data)
|
||||
{
|
||||
struct resource *mcfg_res = data;
|
||||
struct acpi_resource_address64 address;
|
||||
@ -401,8 +408,8 @@ static acpi_status __init check_mcfg_resource(struct acpi_resource *res,
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
|
||||
void *context, void **rv)
|
||||
static acpi_status __devinit find_mboard_resource(acpi_handle handle, u32 lvl,
|
||||
void *context, void **rv)
|
||||
{
|
||||
struct resource *mcfg_res = context;
|
||||
|
||||
@ -415,7 +422,7 @@ static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl,
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
|
||||
static int __devinit is_acpi_reserved(u64 start, u64 end, unsigned not_used)
|
||||
{
|
||||
struct resource mcfg_res;
|
||||
|
||||
@ -434,13 +441,15 @@ static int __init is_acpi_reserved(u64 start, u64 end, unsigned not_used)
|
||||
|
||||
typedef int (*check_reserved_t)(u64 start, u64 end, unsigned type);
|
||||
|
||||
static int __init is_mmconf_reserved(check_reserved_t is_reserved,
|
||||
struct pci_mmcfg_region *cfg, int with_e820)
|
||||
static int __ref is_mmconf_reserved(check_reserved_t is_reserved,
|
||||
struct pci_mmcfg_region *cfg,
|
||||
struct device *dev, int with_e820)
|
||||
{
|
||||
u64 addr = cfg->res.start;
|
||||
u64 size = resource_size(&cfg->res);
|
||||
u64 old_size = size;
|
||||
int valid = 0, num_buses;
|
||||
int num_buses;
|
||||
char *method = with_e820 ? "E820" : "ACPI motherboard resources";
|
||||
|
||||
while (!is_reserved(addr, addr + size, E820_RESERVED)) {
|
||||
size >>= 1;
|
||||
@ -448,30 +457,76 @@ static int __init is_mmconf_reserved(check_reserved_t is_reserved,
|
||||
break;
|
||||
}
|
||||
|
||||
if (size >= (16UL<<20) || size == old_size) {
|
||||
printk(KERN_INFO PREFIX "MMCONFIG at %pR reserved in %s\n",
|
||||
&cfg->res,
|
||||
with_e820 ? "E820" : "ACPI motherboard resources");
|
||||
valid = 1;
|
||||
if (size < (16UL<<20) && size != old_size)
|
||||
return 0;
|
||||
|
||||
if (old_size != size) {
|
||||
/* update end_bus */
|
||||
cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
|
||||
num_buses = cfg->end_bus - cfg->start_bus + 1;
|
||||
cfg->res.end = cfg->res.start +
|
||||
PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
|
||||
snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
|
||||
"PCI MMCONFIG %04x [bus %02x-%02x]",
|
||||
cfg->segment, cfg->start_bus, cfg->end_bus);
|
||||
printk(KERN_INFO PREFIX
|
||||
"MMCONFIG for %04x [bus%02x-%02x] "
|
||||
"at %pR (base %#lx) (size reduced!)\n",
|
||||
cfg->segment, cfg->start_bus, cfg->end_bus,
|
||||
&cfg->res, (unsigned long) cfg->address);
|
||||
}
|
||||
if (dev)
|
||||
dev_info(dev, "MMCONFIG at %pR reserved in %s\n",
|
||||
&cfg->res, method);
|
||||
else
|
||||
pr_info(PREFIX "MMCONFIG at %pR reserved in %s\n",
|
||||
&cfg->res, method);
|
||||
|
||||
if (old_size != size) {
|
||||
/* update end_bus */
|
||||
cfg->end_bus = cfg->start_bus + ((size>>20) - 1);
|
||||
num_buses = cfg->end_bus - cfg->start_bus + 1;
|
||||
cfg->res.end = cfg->res.start +
|
||||
PCI_MMCFG_BUS_OFFSET(num_buses) - 1;
|
||||
snprintf(cfg->name, PCI_MMCFG_RESOURCE_NAME_LEN,
|
||||
"PCI MMCONFIG %04x [bus %02x-%02x]",
|
||||
cfg->segment, cfg->start_bus, cfg->end_bus);
|
||||
|
||||
if (dev)
|
||||
dev_info(dev,
|
||||
"MMCONFIG "
|
||||
"at %pR (base %#lx) (size reduced!)\n",
|
||||
&cfg->res, (unsigned long) cfg->address);
|
||||
else
|
||||
pr_info(PREFIX
|
||||
"MMCONFIG for %04x [bus%02x-%02x] "
|
||||
"at %pR (base %#lx) (size reduced!)\n",
|
||||
cfg->segment, cfg->start_bus, cfg->end_bus,
|
||||
&cfg->res, (unsigned long) cfg->address);
|
||||
}
|
||||
|
||||
return valid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __ref pci_mmcfg_check_reserved(struct device *dev,
|
||||
struct pci_mmcfg_region *cfg, int early)
|
||||
{
|
||||
if (!early && !acpi_disabled) {
|
||||
if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0))
|
||||
return 1;
|
||||
|
||||
if (dev)
|
||||
dev_info(dev, FW_INFO
|
||||
"MMCONFIG at %pR not reserved in "
|
||||
"ACPI motherboard resources\n",
|
||||
&cfg->res);
|
||||
else
|
||||
pr_info(FW_INFO PREFIX
|
||||
"MMCONFIG at %pR not reserved in "
|
||||
"ACPI motherboard resources\n",
|
||||
&cfg->res);
|
||||
}
|
||||
|
||||
/*
|
||||
* e820_all_mapped() is marked as __init.
|
||||
* All entries from ACPI MCFG table have been checked at boot time.
|
||||
* For MCFG information constructed from hotpluggable host bridge's
|
||||
* _CBA method, just assume it's reserved.
|
||||
*/
|
||||
if (pci_mmcfg_running_state)
|
||||
return 1;
|
||||
|
||||
/* Don't try to do this check unless configuration
|
||||
type 1 is available. how about type 2 ?*/
|
||||
if (raw_pci_ops)
|
||||
return is_mmconf_reserved(e820_all_mapped, cfg, dev, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init pci_mmcfg_reject_broken(int early)
|
||||
@ -479,38 +534,14 @@ static void __init pci_mmcfg_reject_broken(int early)
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list) {
|
||||
int valid = 0;
|
||||
|
||||
if (!early && !acpi_disabled) {
|
||||
valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0);
|
||||
|
||||
if (valid)
|
||||
continue;
|
||||
else
|
||||
printk(KERN_ERR FW_BUG PREFIX
|
||||
"MMCONFIG at %pR not reserved in "
|
||||
"ACPI motherboard resources\n",
|
||||
&cfg->res);
|
||||
if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) {
|
||||
pr_info(PREFIX "not using MMCONFIG\n");
|
||||
free_all_mmcfg();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't try to do this check unless configuration
|
||||
type 1 is available. how about type 2 ?*/
|
||||
if (raw_pci_ops)
|
||||
valid = is_mmconf_reserved(e820_all_mapped, cfg, 1);
|
||||
|
||||
if (!valid)
|
||||
goto reject;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
reject:
|
||||
printk(KERN_INFO PREFIX "not using MMCONFIG\n");
|
||||
free_all_mmcfg();
|
||||
}
|
||||
|
||||
static int __initdata known_bridge;
|
||||
|
||||
static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
|
||||
struct acpi_mcfg_allocation *cfg)
|
||||
{
|
||||
@ -529,7 +560,7 @@ static int __init acpi_mcfg_check_entry(struct acpi_table_mcfg *mcfg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
printk(KERN_ERR PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx "
|
||||
pr_err(PREFIX "MCFG region for %04x [bus %02x-%02x] at %#llx "
|
||||
"is above 4GB, ignored\n", cfg->pci_segment,
|
||||
cfg->start_bus_number, cfg->end_bus_number, cfg->address);
|
||||
return -EINVAL;
|
||||
@ -556,7 +587,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
|
||||
i -= sizeof(struct acpi_mcfg_allocation);
|
||||
};
|
||||
if (entries == 0) {
|
||||
printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
|
||||
pr_err(PREFIX "MMCONFIG has no entries\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@ -570,8 +601,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
|
||||
|
||||
if (pci_mmconfig_add(cfg->pci_segment, cfg->start_bus_number,
|
||||
cfg->end_bus_number, cfg->address) == NULL) {
|
||||
printk(KERN_WARNING PREFIX
|
||||
"no memory for MCFG entries\n");
|
||||
pr_warn(PREFIX "no memory for MCFG entries\n");
|
||||
free_all_mmcfg();
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -582,28 +612,7 @@ static int __init pci_parse_mcfg(struct acpi_table_header *header)
|
||||
|
||||
static void __init __pci_mmcfg_init(int early)
|
||||
{
|
||||
/* MMCONFIG disabled */
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
return;
|
||||
|
||||
/* MMCONFIG already enabled */
|
||||
if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF))
|
||||
return;
|
||||
|
||||
/* for late to exit */
|
||||
if (known_bridge)
|
||||
return;
|
||||
|
||||
if (early) {
|
||||
if (pci_mmcfg_check_hostbridge())
|
||||
known_bridge = 1;
|
||||
}
|
||||
|
||||
if (!known_bridge)
|
||||
acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
|
||||
|
||||
pci_mmcfg_reject_broken(early);
|
||||
|
||||
if (list_empty(&pci_mmcfg_list))
|
||||
return;
|
||||
|
||||
@ -620,33 +629,48 @@ static void __init __pci_mmcfg_init(int early)
|
||||
if (pci_mmcfg_arch_init())
|
||||
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
|
||||
else {
|
||||
/*
|
||||
* Signal not to attempt to insert mmcfg resources because
|
||||
* the architecture mmcfg setup could not initialize.
|
||||
*/
|
||||
pci_mmcfg_resources_inserted = 1;
|
||||
free_all_mmcfg();
|
||||
pci_mmcfg_arch_init_failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
static int __initdata known_bridge;
|
||||
|
||||
void __init pci_mmcfg_early_init(void)
|
||||
{
|
||||
__pci_mmcfg_init(1);
|
||||
if (pci_probe & PCI_PROBE_MMCONF) {
|
||||
if (pci_mmcfg_check_hostbridge())
|
||||
known_bridge = 1;
|
||||
else
|
||||
acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
|
||||
__pci_mmcfg_init(1);
|
||||
}
|
||||
}
|
||||
|
||||
void __init pci_mmcfg_late_init(void)
|
||||
{
|
||||
__pci_mmcfg_init(0);
|
||||
/* MMCONFIG disabled */
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
return;
|
||||
|
||||
if (known_bridge)
|
||||
return;
|
||||
|
||||
/* MMCONFIG hasn't been enabled yet, try again */
|
||||
if (pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF) {
|
||||
acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg);
|
||||
__pci_mmcfg_init(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pci_mmcfg_late_insert_resources(void)
|
||||
{
|
||||
/*
|
||||
* If resources are already inserted or we are not using MMCONFIG,
|
||||
* don't insert the resources.
|
||||
*/
|
||||
if ((pci_mmcfg_resources_inserted == 1) ||
|
||||
(pci_probe & PCI_PROBE_MMCONF) == 0 ||
|
||||
list_empty(&pci_mmcfg_list))
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
pci_mmcfg_running_state = true;
|
||||
|
||||
/* If we are not using MMCONFIG, don't insert the resources. */
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -654,7 +678,9 @@ static int __init pci_mmcfg_late_insert_resources(void)
|
||||
* marked so it won't cause request errors when __request_region is
|
||||
* called.
|
||||
*/
|
||||
pci_mmcfg_insert_resources();
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list)
|
||||
if (!cfg->res.parent)
|
||||
insert_resource(&iomem_resource, &cfg->res);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -665,3 +691,101 @@ static int __init pci_mmcfg_late_insert_resources(void)
|
||||
* with other system resources.
|
||||
*/
|
||||
late_initcall(pci_mmcfg_late_insert_resources);
|
||||
|
||||
/* Add MMCFG information for host bridges */
|
||||
int __devinit pci_mmconfig_insert(struct device *dev,
|
||||
u16 seg, u8 start, u8 end,
|
||||
phys_addr_t addr)
|
||||
{
|
||||
int rc;
|
||||
struct resource *tmp = NULL;
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
if (!(pci_probe & PCI_PROBE_MMCONF) || pci_mmcfg_arch_init_failed)
|
||||
return -ENODEV;
|
||||
|
||||
if (start > end)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&pci_mmcfg_lock);
|
||||
cfg = pci_mmconfig_lookup(seg, start);
|
||||
if (cfg) {
|
||||
if (cfg->end_bus < end)
|
||||
dev_info(dev, FW_INFO
|
||||
"MMCONFIG for "
|
||||
"domain %04x [bus %02x-%02x] "
|
||||
"only partially covers this bridge\n",
|
||||
cfg->segment, cfg->start_bus, cfg->end_bus);
|
||||
mutex_unlock(&pci_mmcfg_lock);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
if (!addr) {
|
||||
mutex_unlock(&pci_mmcfg_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = -EBUSY;
|
||||
cfg = pci_mmconfig_alloc(seg, start, end, addr);
|
||||
if (cfg == NULL) {
|
||||
dev_warn(dev, "fail to add MMCONFIG (out of memory)\n");
|
||||
rc = -ENOMEM;
|
||||
} else if (!pci_mmcfg_check_reserved(dev, cfg, 0)) {
|
||||
dev_warn(dev, FW_BUG "MMCONFIG %pR isn't reserved\n",
|
||||
&cfg->res);
|
||||
} else {
|
||||
/* Insert resource if it's not in boot stage */
|
||||
if (pci_mmcfg_running_state)
|
||||
tmp = insert_resource_conflict(&iomem_resource,
|
||||
&cfg->res);
|
||||
|
||||
if (tmp) {
|
||||
dev_warn(dev,
|
||||
"MMCONFIG %pR conflicts with "
|
||||
"%s %pR\n",
|
||||
&cfg->res, tmp->name, tmp);
|
||||
} else if (pci_mmcfg_arch_map(cfg)) {
|
||||
dev_warn(dev, "fail to map MMCONFIG %pR.\n",
|
||||
&cfg->res);
|
||||
} else {
|
||||
list_add_sorted(cfg);
|
||||
dev_info(dev, "MMCONFIG at %pR (base %#lx)\n",
|
||||
&cfg->res, (unsigned long)addr);
|
||||
cfg = NULL;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg) {
|
||||
if (cfg->res.parent)
|
||||
release_resource(&cfg->res);
|
||||
kfree(cfg);
|
||||
}
|
||||
|
||||
mutex_unlock(&pci_mmcfg_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Delete MMCFG information for host bridges */
|
||||
int pci_mmconfig_delete(u16 seg, u8 start, u8 end)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
mutex_lock(&pci_mmcfg_lock);
|
||||
list_for_each_entry_rcu(cfg, &pci_mmcfg_list, list)
|
||||
if (cfg->segment == seg && cfg->start_bus == start &&
|
||||
cfg->end_bus == end) {
|
||||
list_del_rcu(&cfg->list);
|
||||
synchronize_rcu();
|
||||
pci_mmcfg_arch_unmap(cfg);
|
||||
if (cfg->res.parent)
|
||||
release_resource(&cfg->res);
|
||||
mutex_unlock(&pci_mmcfg_lock);
|
||||
kfree(cfg);
|
||||
return 0;
|
||||
}
|
||||
mutex_unlock(&pci_mmcfg_lock);
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/e820.h>
|
||||
#include <asm/pci_x86.h>
|
||||
#include <acpi/acpi.h>
|
||||
@ -60,9 +61,12 @@ err: *value = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
base = get_base_addr(seg, bus, devfn);
|
||||
if (!base)
|
||||
if (!base) {
|
||||
rcu_read_unlock();
|
||||
goto err;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
|
||||
@ -80,6 +84,7 @@ err: *value = -1;
|
||||
break;
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -93,9 +98,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
|
||||
if ((bus > 255) || (devfn > 255) || (reg > 4095))
|
||||
return -EINVAL;
|
||||
|
||||
rcu_read_lock();
|
||||
base = get_base_addr(seg, bus, devfn);
|
||||
if (!base)
|
||||
if (!base) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
|
||||
@ -113,11 +121,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
|
||||
break;
|
||||
}
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pci_raw_ops pci_mmcfg = {
|
||||
const struct pci_raw_ops pci_mmcfg = {
|
||||
.read = pci_mmcfg_read,
|
||||
.write = pci_mmcfg_write,
|
||||
};
|
||||
@ -132,3 +141,18 @@ int __init pci_mmcfg_arch_init(void)
|
||||
void __init pci_mmcfg_arch_free(void)
|
||||
{
|
||||
}
|
||||
|
||||
int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* Invalidate the cached mmcfg map entry. */
|
||||
raw_spin_lock_irqsave(&pci_config_lock, flags);
|
||||
mmcfg_last_accessed_device = 0;
|
||||
raw_spin_unlock_irqrestore(&pci_config_lock, flags);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <asm/e820.h>
|
||||
#include <asm/pci_x86.h>
|
||||
|
||||
@ -34,9 +35,12 @@ err: *value = -1;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
addr = pci_dev_base(seg, bus, devfn);
|
||||
if (!addr)
|
||||
if (!addr) {
|
||||
rcu_read_unlock();
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
@ -49,6 +53,7 @@ err: *value = -1;
|
||||
*value = mmio_config_readl(addr + reg);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -62,9 +67,12 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
|
||||
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
|
||||
return -EINVAL;
|
||||
|
||||
rcu_read_lock();
|
||||
addr = pci_dev_base(seg, bus, devfn);
|
||||
if (!addr)
|
||||
if (!addr) {
|
||||
rcu_read_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
@ -77,16 +85,17 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
|
||||
mmio_config_writel(addr + reg, value);
|
||||
break;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pci_raw_ops pci_mmcfg = {
|
||||
const struct pci_raw_ops pci_mmcfg = {
|
||||
.read = pci_mmcfg_read,
|
||||
.write = pci_mmcfg_write,
|
||||
};
|
||||
|
||||
static void __iomem * __init mcfg_ioremap(struct pci_mmcfg_region *cfg)
|
||||
static void __iomem * __devinit mcfg_ioremap(struct pci_mmcfg_region *cfg)
|
||||
{
|
||||
void __iomem *addr;
|
||||
u64 start, size;
|
||||
@ -105,16 +114,14 @@ int __init pci_mmcfg_arch_init(void)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list) {
|
||||
cfg->virt = mcfg_ioremap(cfg);
|
||||
if (!cfg->virt) {
|
||||
printk(KERN_ERR PREFIX "can't map MMCONFIG at %pR\n",
|
||||
&cfg->res);
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list)
|
||||
if (pci_mmcfg_arch_map(cfg)) {
|
||||
pci_mmcfg_arch_free();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
raw_pci_ext_ops = &pci_mmcfg;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -122,10 +129,25 @@ void __init pci_mmcfg_arch_free(void)
|
||||
{
|
||||
struct pci_mmcfg_region *cfg;
|
||||
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list) {
|
||||
if (cfg->virt) {
|
||||
iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
|
||||
cfg->virt = NULL;
|
||||
}
|
||||
list_for_each_entry(cfg, &pci_mmcfg_list, list)
|
||||
pci_mmcfg_arch_unmap(cfg);
|
||||
}
|
||||
|
||||
int __devinit pci_mmcfg_arch_map(struct pci_mmcfg_region *cfg)
|
||||
{
|
||||
cfg->virt = mcfg_ioremap(cfg);
|
||||
if (!cfg->virt) {
|
||||
pr_err(PREFIX "can't map MMCONFIG at %pR\n", &cfg->res);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pci_mmcfg_arch_unmap(struct pci_mmcfg_region *cfg)
|
||||
{
|
||||
if (cfg && cfg->virt) {
|
||||
iounmap(cfg->virt + PCI_MMCFG_BUS_OFFSET(cfg->start_bus));
|
||||
cfg->virt = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_d3delay_fixup);
|
||||
|
||||
static void __devinit mrst_power_off_unused_dev(struct pci_dev *dev)
|
||||
{
|
||||
pci_set_power_state(dev, PCI_D3cold);
|
||||
pci_set_power_state(dev, PCI_D3hot);
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0801, mrst_power_off_unused_dev);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0809, mrst_power_off_unused_dev);
|
||||
|
@ -46,7 +46,6 @@
|
||||
* pcibios_fixups
|
||||
* pcibios_align_resource
|
||||
* pcibios_fixup_bus
|
||||
* pcibios_setup
|
||||
* pci_bus_add_device
|
||||
* pci_mmap_page_range
|
||||
*/
|
||||
@ -187,7 +186,7 @@ static int __init pcibios_init(void)
|
||||
bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
|
||||
pci_ctrl->ops, pci_ctrl, &resources);
|
||||
pci_ctrl->bus = bus;
|
||||
pci_ctrl->last_busno = bus->subordinate;
|
||||
pci_ctrl->last_busno = bus->busn_res.end;
|
||||
if (next_busno <= pci_ctrl->last_busno)
|
||||
next_busno = pci_ctrl->last_busno+1;
|
||||
}
|
||||
@ -206,11 +205,6 @@ void __init pcibios_fixup_bus(struct pci_bus *bus)
|
||||
}
|
||||
}
|
||||
|
||||
char __init *pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
void pcibios_set_master(struct pci_dev *dev)
|
||||
{
|
||||
/* No special bus mastering setup handling */
|
||||
|
@ -505,6 +505,8 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
||||
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
|
||||
device->driver_data = root;
|
||||
|
||||
root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
|
||||
|
||||
/*
|
||||
* All supported architectures that use ACPI have support for
|
||||
* PCI domains, so we indicate this in _OSC support capabilities.
|
||||
|
@ -716,8 +716,9 @@ int acpi_suspend(u32 acpi_state)
|
||||
* @dev: device to examine; its driver model wakeup flags control
|
||||
* whether it should be able to wake up the system
|
||||
* @d_min_p: used to store the upper limit of allowed states range
|
||||
* Return value: preferred power state of the device on success, -ENODEV on
|
||||
* failure (ie. if there's no 'struct acpi_device' for @dev)
|
||||
* @d_max_in: specify the lowest allowed states
|
||||
* Return value: preferred power state of the device on success, -ENODEV
|
||||
* (ie. if there's no 'struct acpi_device' for @dev) or -EINVAL on failure
|
||||
*
|
||||
* Find the lowest power (highest number) ACPI device power state that
|
||||
* device @dev can be in while the system is in the sleep state represented
|
||||
@ -732,13 +733,15 @@ int acpi_suspend(u32 acpi_state)
|
||||
* via @wake.
|
||||
*/
|
||||
|
||||
int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
|
||||
int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p, int d_max_in)
|
||||
{
|
||||
acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
|
||||
struct acpi_device *adev;
|
||||
char acpi_method[] = "_SxD";
|
||||
unsigned long long d_min, d_max;
|
||||
|
||||
if (d_max_in < ACPI_STATE_D0 || d_max_in > ACPI_STATE_D3)
|
||||
return -EINVAL;
|
||||
if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
|
||||
printk(KERN_DEBUG "ACPI handle has no context!\n");
|
||||
return -ENODEV;
|
||||
@ -746,8 +749,10 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
|
||||
|
||||
acpi_method[2] = '0' + acpi_target_sleep_state;
|
||||
/*
|
||||
* If the sleep state is S0, we will return D3, but if the device has
|
||||
* _S0W, we will use the value from _S0W
|
||||
* If the sleep state is S0, the lowest limit from ACPI is D3,
|
||||
* but if the device has _S0W, we will use the value from _S0W
|
||||
* as the lowest limit from ACPI. Finally, we will constrain
|
||||
* the lowest limit with the specified one.
|
||||
*/
|
||||
d_min = ACPI_STATE_D0;
|
||||
d_max = ACPI_STATE_D3;
|
||||
@ -791,8 +796,17 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
|
||||
}
|
||||
}
|
||||
|
||||
if (d_max_in < d_min)
|
||||
return -EINVAL;
|
||||
if (d_min_p)
|
||||
*d_min_p = d_min;
|
||||
/* constrain d_max with specified lowest limit (max number) */
|
||||
if (d_max > d_max_in) {
|
||||
for (d_max = d_max_in; d_max > d_min; d_max--) {
|
||||
if (adev->power.states[d_max].flags.valid)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return d_max;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
@ -661,7 +661,7 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
|
||||
if (drhd->devices[i] &&
|
||||
drhd->devices[i]->subordinate &&
|
||||
drhd->devices[i]->subordinate->number <= bus &&
|
||||
drhd->devices[i]->subordinate->subordinate >= bus)
|
||||
drhd->devices[i]->subordinate->busn_res.end >= bus)
|
||||
return drhd->iommu;
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ static int cb710_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
if (state.event & PM_EVENT_SLEEP)
|
||||
pci_set_power_state(pdev, PCI_D3cold);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -14368,7 +14368,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
if (bridge->subordinate &&
|
||||
(bridge->subordinate->number <=
|
||||
tp->pdev->bus->number) &&
|
||||
(bridge->subordinate->subordinate >=
|
||||
(bridge->subordinate->busn_res.end >=
|
||||
tp->pdev->bus->number)) {
|
||||
tg3_flag_set(tp, 5701_DMA_BUG);
|
||||
pci_dev_put(bridge);
|
||||
@ -14396,7 +14396,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||
if (bridge && bridge->subordinate &&
|
||||
(bridge->subordinate->number <=
|
||||
tp->pdev->bus->number) &&
|
||||
(bridge->subordinate->subordinate >=
|
||||
(bridge->subordinate->busn_res.end >=
|
||||
tp->pdev->bus->number)) {
|
||||
tg3_flag_set(tp, 40BIT_DMA_BUG);
|
||||
pci_dev_put(bridge);
|
||||
|
@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 *val)
|
||||
{
|
||||
struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
|
||||
u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
|
||||
void __iomem *base_addr = d->hba.base_addr;
|
||||
unsigned long flags;
|
||||
@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where,
|
||||
int size, u32 val)
|
||||
{
|
||||
struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
|
||||
u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
|
||||
void __iomem *base_addr = d->hba.base_addr;
|
||||
unsigned long flags;
|
||||
@ -554,7 +554,7 @@ dino_fixup_bus(struct pci_bus *bus)
|
||||
struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
|
||||
|
||||
DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n",
|
||||
__func__, bus, bus->secondary,
|
||||
__func__, bus, bus->busn_res.start,
|
||||
bus->bridge->platform_data);
|
||||
|
||||
/* Firmware doesn't set up card-mode dino, so we have to */
|
||||
@ -898,6 +898,7 @@ static int __init dino_probe(struct parisc_device *dev)
|
||||
LIST_HEAD(resources);
|
||||
struct pci_bus *bus;
|
||||
unsigned long hpa = dev->hpa.start;
|
||||
int max;
|
||||
|
||||
name = "Dino";
|
||||
if (is_card_dino(&dev->id)) {
|
||||
@ -983,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev)
|
||||
if (dino_dev->hba.gmmio_space.flags)
|
||||
pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
|
||||
|
||||
dino_dev->hba.bus_num.start = dino_current_bus;
|
||||
dino_dev->hba.bus_num.end = 255;
|
||||
dino_dev->hba.bus_num.flags = IORESOURCE_BUS;
|
||||
pci_add_resource(&resources, &dino_dev->hba.bus_num);
|
||||
/*
|
||||
** It's not used to avoid chicken/egg problems
|
||||
** with configuration accessor functions.
|
||||
@ -998,12 +1003,13 @@ static int __init dino_probe(struct parisc_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bus->subordinate = pci_scan_child_bus(bus);
|
||||
max = pci_scan_child_bus(bus);
|
||||
pci_bus_update_busn_res_end(bus, max);
|
||||
|
||||
/* 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;
|
||||
dino_current_bus = max + 1;
|
||||
pci_bus_assign_resources(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
return 0;
|
||||
|
@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
|
||||
intr_slot = PCI_SLOT(pcidev->devfn);
|
||||
}
|
||||
DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
|
||||
pcidev->bus->secondary, intr_slot, intr_pin);
|
||||
pcidev->bus->busn_res.start, intr_slot, intr_pin);
|
||||
|
||||
return irt_find_irqline(isi, intr_slot, intr_pin);
|
||||
}
|
||||
|
@ -189,8 +189,8 @@ lba_dump_res(struct resource *r, int d)
|
||||
|
||||
static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d)
|
||||
{
|
||||
u8 first_bus = d->hba.hba_bus->secondary;
|
||||
u8 last_sub_bus = d->hba.hba_bus->subordinate;
|
||||
u8 first_bus = d->hba.hba_bus->busn_res.start;
|
||||
u8 last_sub_bus = d->hba.hba_bus->busn_res.end;
|
||||
|
||||
if ((bus < first_bus) ||
|
||||
(bus > last_sub_bus) ||
|
||||
@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
|
||||
static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
|
||||
{
|
||||
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
|
||||
u32 tok = LBA_CFG_TOK(local_bus, devfn);
|
||||
void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
|
||||
|
||||
@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) {
|
||||
if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) {
|
||||
DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos);
|
||||
/* either don't want to look or know device isn't present. */
|
||||
*data = ~0U;
|
||||
@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
|
||||
static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
|
||||
{
|
||||
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
|
||||
u32 tok = LBA_CFG_TOK(local_bus,devfn);
|
||||
|
||||
if ((pos > 255) || (devfn > 255))
|
||||
@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) {
|
||||
if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) {
|
||||
DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data);
|
||||
return 1; /* New Workaround */
|
||||
}
|
||||
@ -481,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = {
|
||||
static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
|
||||
{
|
||||
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
|
||||
u32 tok = LBA_CFG_TOK(local_bus, devfn);
|
||||
void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
|
||||
|
||||
@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i
|
||||
{
|
||||
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
|
||||
void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
|
||||
u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
|
||||
u32 tok = LBA_CFG_TOK(local_bus,devfn);
|
||||
|
||||
if ((pos > 255) || (devfn > 255))
|
||||
@ -636,7 +636,7 @@ lba_fixup_bus(struct pci_bus *bus)
|
||||
struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
|
||||
|
||||
DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
|
||||
bus, bus->secondary, bus->bridge->platform_data);
|
||||
bus, (int)bus->busn_res.start, bus->bridge->platform_data);
|
||||
|
||||
/*
|
||||
** Properly Setup MMIO resources for this bus.
|
||||
@ -989,6 +989,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
|
||||
case PAT_PBNUM:
|
||||
lba_dev->hba.bus_num.start = p->start;
|
||||
lba_dev->hba.bus_num.end = p->end;
|
||||
lba_dev->hba.bus_num.flags = IORESOURCE_BUS;
|
||||
break;
|
||||
|
||||
case PAT_LMMIO:
|
||||
@ -1366,6 +1367,7 @@ lba_driver_probe(struct parisc_device *dev)
|
||||
void *tmp_obj;
|
||||
char *version;
|
||||
void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
|
||||
int max;
|
||||
|
||||
/* Read HW Rev First */
|
||||
func_class = READ_REG32(addr + LBA_FCLASS);
|
||||
@ -1502,6 +1504,8 @@ lba_driver_probe(struct parisc_device *dev)
|
||||
if (lba_dev->hba.gmmio_space.flags)
|
||||
pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
|
||||
|
||||
pci_add_resource(&resources, &lba_dev->hba.bus_num);
|
||||
|
||||
dev->dev.platform_data = lba_dev;
|
||||
lba_bus = lba_dev->hba.hba_bus =
|
||||
pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
|
||||
@ -1511,7 +1515,7 @@ lba_driver_probe(struct parisc_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
lba_bus->subordinate = pci_scan_child_bus(lba_bus);
|
||||
max = pci_scan_child_bus(lba_bus);
|
||||
|
||||
/* This is in lieu of calling pci_assign_unassigned_resources() */
|
||||
if (is_pdc_pat()) {
|
||||
@ -1541,7 +1545,7 @@ lba_driver_probe(struct parisc_device *dev)
|
||||
lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
|
||||
}
|
||||
|
||||
lba_next_bus = lba_bus->subordinate + 1;
|
||||
lba_next_bus = max + 1;
|
||||
pci_bus_add_devices(lba_bus);
|
||||
|
||||
/* Whew! Finally done! Tell services we got this one covered. */
|
||||
|
@ -49,6 +49,7 @@ obj-$(CONFIG_MN10300) += setup-bus.o
|
||||
obj-$(CONFIG_MICROBLAZE) += setup-bus.o
|
||||
obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
|
||||
obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
|
||||
obj-$(CONFIG_M68K) += setup-bus.o setup-irq.o
|
||||
|
||||
#
|
||||
# ACPI Related PCI FW Functions
|
||||
|
@ -162,7 +162,8 @@ int pci_user_read_config_##size \
|
||||
if (ret > 0) \
|
||||
ret = -EINVAL; \
|
||||
return ret; \
|
||||
}
|
||||
} \
|
||||
EXPORT_SYMBOL_GPL(pci_user_read_config_##size);
|
||||
|
||||
/* Returns 0 on success, negative values indicate error. */
|
||||
#define PCI_USER_WRITE_CONFIG(size,type) \
|
||||
@ -181,7 +182,8 @@ int pci_user_write_config_##size \
|
||||
if (ret > 0) \
|
||||
ret = -EINVAL; \
|
||||
return ret; \
|
||||
}
|
||||
} \
|
||||
EXPORT_SYMBOL_GPL(pci_user_write_config_##size);
|
||||
|
||||
PCI_USER_READ_CONFIG(byte, u8)
|
||||
PCI_USER_READ_CONFIG(word, u16)
|
||||
|
@ -164,6 +164,8 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
|
||||
int pci_bus_add_device(struct pci_dev *dev)
|
||||
{
|
||||
int retval;
|
||||
|
||||
pci_fixup_device(pci_fixup_final, dev);
|
||||
retval = device_add(&dev->dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
@ -4,18 +4,26 @@
|
||||
#include <linux/export.h>
|
||||
#include "pci.h"
|
||||
|
||||
|
||||
unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
|
||||
int __ref pci_hp_add_bridge(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int max;
|
||||
struct pci_bus *parent = dev->bus;
|
||||
int pass, busnr, start = parent->busn_res.start;
|
||||
int end = parent->busn_res.end;
|
||||
|
||||
max = pci_scan_child_bus(bus);
|
||||
for (busnr = start; busnr <= end; busnr++) {
|
||||
if (!pci_find_bus(pci_domain_nr(parent), busnr))
|
||||
break;
|
||||
}
|
||||
if (busnr-- > end) {
|
||||
printk(KERN_ERR "No bus number available for hot-added bridge %s\n",
|
||||
pci_name(dev));
|
||||
return -1;
|
||||
}
|
||||
for (pass = 0; pass < 2; pass++)
|
||||
busnr = pci_scan_bridge(parent, dev, busnr, pass);
|
||||
if (!dev->subordinate)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Make the discovered devices available.
|
||||
*/
|
||||
pci_bus_add_devices(bus);
|
||||
|
||||
return max;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_do_scan_bus);
|
||||
EXPORT_SYMBOL_GPL(pci_hp_add_bridge);
|
||||
|
@ -89,8 +89,6 @@ struct acpiphp_bridge {
|
||||
|
||||
/* PCI-to-PCI bridge device */
|
||||
struct pci_dev *pci_dev;
|
||||
|
||||
spinlock_t res_lock;
|
||||
};
|
||||
|
||||
|
||||
@ -207,6 +205,6 @@ extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);
|
||||
extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);
|
||||
|
||||
/* variables */
|
||||
extern int acpiphp_debug;
|
||||
extern bool acpiphp_debug;
|
||||
|
||||
#endif /* _ACPIPHP_H */
|
||||
|
@ -47,8 +47,7 @@
|
||||
/* name size which is used for entries in pcihpfs */
|
||||
#define SLOT_NAME_SIZE 21 /* {_SUN} */
|
||||
|
||||
static bool debug;
|
||||
int acpiphp_debug;
|
||||
bool acpiphp_debug;
|
||||
|
||||
/* local variables */
|
||||
static int num_slots;
|
||||
@ -62,7 +61,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
|
||||
module_param(debug, bool, 0644);
|
||||
module_param_named(debug, acpiphp_debug, bool, 0644);
|
||||
|
||||
/* export the attention callback registration methods */
|
||||
EXPORT_SYMBOL_GPL(acpiphp_register_attention);
|
||||
@ -379,8 +378,6 @@ static int __init acpiphp_init(void)
|
||||
if (acpi_pci_disabled)
|
||||
return 0;
|
||||
|
||||
acpiphp_debug = debug;
|
||||
|
||||
/* read all the ACPI info from the system */
|
||||
return init_acpi();
|
||||
}
|
||||
|
@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
|
||||
PCI_PRIMARY_BUS,
|
||||
&buses);
|
||||
|
||||
if (((buses >> 8) & 0xff) != bus->secondary) {
|
||||
if (((buses >> 8) & 0xff) != bus->busn_res.start) {
|
||||
buses = (buses & 0xff000000)
|
||||
| ((unsigned int)(bus->primary) << 0)
|
||||
| ((unsigned int)(bus->secondary) << 8)
|
||||
| ((unsigned int)(bus->subordinate) << 16);
|
||||
| ((unsigned int)(bus->busn_res.start) << 8)
|
||||
| ((unsigned int)(bus->busn_res.end) << 16);
|
||||
pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
|
||||
}
|
||||
return NOTIFY_OK;
|
||||
@ -132,6 +132,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
|
||||
return AE_OK;
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
warn("can't evaluate _ADR (%#x)\n", status);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
device = (adr >> 16) & 0xffff;
|
||||
function = adr & 0xffff;
|
||||
|
||||
pdev = pbus->self;
|
||||
if (pdev && pci_is_pcie(pdev)) {
|
||||
tmp = acpi_find_root_bridge_handle(pdev);
|
||||
@ -144,10 +153,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
}
|
||||
}
|
||||
|
||||
acpi_evaluate_integer(handle, "_ADR", NULL, &adr);
|
||||
device = (adr >> 16) & 0xffff;
|
||||
function = adr & 0xffff;
|
||||
|
||||
newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
|
||||
if (!newfunc)
|
||||
return AE_NO_MEMORY;
|
||||
@ -391,8 +396,6 @@ static void add_host_bridge(acpi_handle *handle)
|
||||
|
||||
bridge->pci_bus = root->bus;
|
||||
|
||||
spin_lock_init(&bridge->res_lock);
|
||||
|
||||
init_bridge_misc(bridge);
|
||||
}
|
||||
|
||||
@ -425,7 +428,6 @@ static void add_p2p_bridge(acpi_handle *handle)
|
||||
* (which we access during module unload).
|
||||
*/
|
||||
get_device(&bridge->pci_bus->dev);
|
||||
spin_lock_init(&bridge->res_lock);
|
||||
|
||||
init_bridge_misc(bridge);
|
||||
return;
|
||||
@ -692,7 +694,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
|
||||
* bus->subordinate value because it could have
|
||||
* padding in it.
|
||||
*/
|
||||
max = bus->secondary;
|
||||
max = bus->busn_res.start;
|
||||
|
||||
list_for_each(tmp, &bus->children) {
|
||||
n = pci_bus_max_busnr(pci_bus_b(tmp));
|
||||
@ -878,6 +880,24 @@ static void disable_bridges(struct pci_bus *bus)
|
||||
}
|
||||
}
|
||||
|
||||
/* return first device in slot, acquiring a reference on it */
|
||||
static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
|
||||
{
|
||||
struct pci_bus *bus = slot->bridge->pci_bus;
|
||||
struct pci_dev *dev;
|
||||
struct pci_dev *ret = NULL;
|
||||
|
||||
down_read(&pci_bus_sem);
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
if (PCI_SLOT(dev->devfn) == slot->device) {
|
||||
ret = pci_dev_get(dev);
|
||||
break;
|
||||
}
|
||||
up_read(&pci_bus_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* disable_device - disable a slot
|
||||
* @slot: ACPI PHP slot
|
||||
@ -893,6 +913,7 @@ static int disable_device(struct acpiphp_slot *slot)
|
||||
pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));
|
||||
if (!pdev)
|
||||
goto err_exit;
|
||||
pci_dev_put(pdev);
|
||||
|
||||
list_for_each_entry(func, &slot->funcs, sibling) {
|
||||
if (func->bridge) {
|
||||
@ -901,18 +922,22 @@ static int disable_device(struct acpiphp_slot *slot)
|
||||
(u32)1, NULL, NULL);
|
||||
func->bridge = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
pdev = pci_get_slot(slot->bridge->pci_bus,
|
||||
PCI_DEVFN(slot->device, func->function));
|
||||
if (pdev) {
|
||||
pci_stop_bus_device(pdev);
|
||||
if (pdev->subordinate) {
|
||||
disable_bridges(pdev->subordinate);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
__pci_remove_bus_device(pdev);
|
||||
pci_dev_put(pdev);
|
||||
/*
|
||||
* enable_device() enumerates all functions in this device via
|
||||
* pci_scan_slot(), whether they have associated ACPI hotplug
|
||||
* methods (_EJ0, etc.) or not. Therefore, we remove all functions
|
||||
* here.
|
||||
*/
|
||||
while ((pdev = dev_in_slot(slot))) {
|
||||
pci_stop_bus_device(pdev);
|
||||
if (pdev->subordinate) {
|
||||
disable_bridges(pdev->subordinate);
|
||||
pci_disable_device(pdev);
|
||||
}
|
||||
__pci_remove_bus_device(pdev);
|
||||
pci_dev_put(pdev);
|
||||
}
|
||||
|
||||
list_for_each_entry(func, &slot->funcs, sibling) {
|
||||
|
@ -225,7 +225,7 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *info;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
int status = -ENOMEM;
|
||||
int status;
|
||||
int i;
|
||||
|
||||
if (!(controller && bus))
|
||||
@ -237,18 +237,24 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
|
||||
*/
|
||||
for (i = first; i <= last; ++i) {
|
||||
slot = kzalloc(sizeof (struct slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
if (!slot) {
|
||||
status = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
hotplug_slot =
|
||||
kzalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
if (!hotplug_slot) {
|
||||
status = -ENOMEM;
|
||||
goto error_slot;
|
||||
}
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
info = kzalloc(sizeof (struct hotplug_slot_info), GFP_KERNEL);
|
||||
if (!info)
|
||||
if (!info) {
|
||||
status = -ENOMEM;
|
||||
goto error_hpslot;
|
||||
}
|
||||
hotplug_slot->info = info;
|
||||
|
||||
slot->bus = bus;
|
||||
|
@ -285,42 +285,19 @@ int __ref cpci_configure_slot(struct slot *slot)
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
struct pci_dev *dev;
|
||||
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
|
||||
dev = pci_get_slot(parent,
|
||||
PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
|
||||
if (!dev)
|
||||
continue;
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
|
||||
/* Find an unused bus number for the new bridge */
|
||||
struct pci_bus *child;
|
||||
unsigned char busnr, start = parent->secondary;
|
||||
unsigned char end = parent->subordinate;
|
||||
|
||||
for (busnr = start; busnr <= end; busnr++) {
|
||||
if (!pci_find_bus(pci_domain_nr(parent),
|
||||
busnr))
|
||||
break;
|
||||
}
|
||||
if (busnr >= end) {
|
||||
err("No free bus for hot-added bridge\n");
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
child = pci_add_new_bus(parent, dev, busnr);
|
||||
if (!child) {
|
||||
err("Cannot add new bus for %s\n",
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
child->subordinate = pci_do_scan_bus(child);
|
||||
pci_bus_size_bridges(child);
|
||||
}
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||
pci_hp_add_bridge(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_bus_assign_resources(parent);
|
||||
pci_assign_unassigned_bridge_resources(parent->self);
|
||||
|
||||
pci_bus_add_devices(parent);
|
||||
pci_enable_bridges(parent);
|
||||
|
||||
dbg("%s - exit", __func__);
|
||||
return 0;
|
||||
|
@ -611,7 +611,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
|
||||
u32 tempdword;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
void __iomem *slot_entry= NULL;
|
||||
int result = -ENOMEM;
|
||||
int result;
|
||||
|
||||
dbg("%s\n", __func__);
|
||||
|
||||
@ -623,19 +623,25 @@ static int ctrl_slot_setup(struct controller *ctrl,
|
||||
|
||||
while (number_of_slots) {
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
if (!slot) {
|
||||
result = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
slot->hotplug_slot = kzalloc(sizeof(*(slot->hotplug_slot)),
|
||||
GFP_KERNEL);
|
||||
if (!slot->hotplug_slot)
|
||||
if (!slot->hotplug_slot) {
|
||||
result = -ENOMEM;
|
||||
goto error_slot;
|
||||
}
|
||||
hotplug_slot = slot->hotplug_slot;
|
||||
|
||||
hotplug_slot->info = kzalloc(sizeof(*(hotplug_slot->info)),
|
||||
GFP_KERNEL);
|
||||
if (!hotplug_slot->info)
|
||||
if (!hotplug_slot->info) {
|
||||
result = -ENOMEM;
|
||||
goto error_hpslot;
|
||||
}
|
||||
hotplug_slot_info = hotplug_slot->info;
|
||||
|
||||
slot->ctrl = ctrl;
|
||||
|
@ -83,7 +83,6 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
|
||||
|
||||
int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
|
||||
{
|
||||
unsigned char bus;
|
||||
struct pci_bus *child;
|
||||
int num;
|
||||
|
||||
@ -106,9 +105,10 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
|
||||
}
|
||||
|
||||
if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
|
||||
child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
|
||||
pci_do_scan_bus(child);
|
||||
pci_hp_add_bridge(func->pci_dev);
|
||||
child = func->pci_dev->subordinate;
|
||||
if (child)
|
||||
pci_bus_add_devices(child);
|
||||
}
|
||||
|
||||
pci_dev_put(func->pci_dev);
|
||||
|
@ -775,7 +775,6 @@ static u8 bus_structure_fixup(u8 busno)
|
||||
|
||||
static int ibm_configure_device(struct pci_func *func)
|
||||
{
|
||||
unsigned char bus;
|
||||
struct pci_bus *child;
|
||||
int num;
|
||||
int flag = 0; /* this is to make sure we don't double scan the bus,
|
||||
@ -805,9 +804,10 @@ static int ibm_configure_device(struct pci_func *func)
|
||||
}
|
||||
}
|
||||
if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
|
||||
pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus);
|
||||
child = pci_add_new_bus(func->dev->bus, func->dev, bus);
|
||||
pci_do_scan_bus(child);
|
||||
pci_hp_add_bridge(func->dev);
|
||||
child = func->dev->subordinate;
|
||||
if (child)
|
||||
pci_bus_add_devices(child);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -149,10 +149,6 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status);
|
||||
int pciehp_set_attention_status(struct slot *slot, u8 status);
|
||||
int pciehp_get_latch_status(struct slot *slot, u8 *status);
|
||||
int pciehp_get_adapter_status(struct slot *slot, u8 *status);
|
||||
int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *speed);
|
||||
int pciehp_get_max_link_width(struct slot *slot, enum pcie_link_width *val);
|
||||
int pciehp_get_cur_link_speed(struct slot *slot, enum pci_bus_speed *speed);
|
||||
int pciehp_get_cur_link_width(struct slot *slot, enum pcie_link_width *val);
|
||||
int pciehp_query_power_fault(struct slot *slot);
|
||||
void pciehp_green_led_on(struct slot *slot);
|
||||
void pciehp_green_led_off(struct slot *slot);
|
||||
|
@ -705,107 +705,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
int pciehp_get_max_lnk_width(struct slot *slot,
|
||||
enum pcie_link_width *value)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
enum pcie_link_width lnk_wdth;
|
||||
u32 lnk_cap;
|
||||
int retval = 0;
|
||||
|
||||
retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap);
|
||||
if (retval) {
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
switch ((lnk_cap & PCI_EXP_LNKSTA_NLW) >> 4){
|
||||
case 0:
|
||||
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
|
||||
break;
|
||||
case 1:
|
||||
lnk_wdth = PCIE_LNK_X1;
|
||||
break;
|
||||
case 2:
|
||||
lnk_wdth = PCIE_LNK_X2;
|
||||
break;
|
||||
case 4:
|
||||
lnk_wdth = PCIE_LNK_X4;
|
||||
break;
|
||||
case 8:
|
||||
lnk_wdth = PCIE_LNK_X8;
|
||||
break;
|
||||
case 12:
|
||||
lnk_wdth = PCIE_LNK_X12;
|
||||
break;
|
||||
case 16:
|
||||
lnk_wdth = PCIE_LNK_X16;
|
||||
break;
|
||||
case 32:
|
||||
lnk_wdth = PCIE_LNK_X32;
|
||||
break;
|
||||
default:
|
||||
lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
*value = lnk_wdth;
|
||||
ctrl_dbg(ctrl, "Max link width = %d\n", lnk_wdth);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int pciehp_get_cur_lnk_width(struct slot *slot,
|
||||
enum pcie_link_width *value)
|
||||
{
|
||||
struct controller *ctrl = slot->ctrl;
|
||||
enum pcie_link_width lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
int retval = 0;
|
||||
u16 lnk_status;
|
||||
|
||||
retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
|
||||
if (retval) {
|
||||
ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
|
||||
__func__);
|
||||
return retval;
|
||||
}
|
||||
|
||||
switch ((lnk_status & PCI_EXP_LNKSTA_NLW) >> 4){
|
||||
case 0:
|
||||
lnk_wdth = PCIE_LNK_WIDTH_RESRV;
|
||||
break;
|
||||
case 1:
|
||||
lnk_wdth = PCIE_LNK_X1;
|
||||
break;
|
||||
case 2:
|
||||
lnk_wdth = PCIE_LNK_X2;
|
||||
break;
|
||||
case 4:
|
||||
lnk_wdth = PCIE_LNK_X4;
|
||||
break;
|
||||
case 8:
|
||||
lnk_wdth = PCIE_LNK_X8;
|
||||
break;
|
||||
case 12:
|
||||
lnk_wdth = PCIE_LNK_X12;
|
||||
break;
|
||||
case 16:
|
||||
lnk_wdth = PCIE_LNK_X16;
|
||||
break;
|
||||
case 32:
|
||||
lnk_wdth = PCIE_LNK_X32;
|
||||
break;
|
||||
default:
|
||||
lnk_wdth = PCIE_LNK_WIDTH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
*value = lnk_wdth;
|
||||
ctrl_dbg(ctrl, "Current link width = %d\n", lnk_wdth);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int pcie_enable_notification(struct controller *ctrl)
|
||||
{
|
||||
u16 cmd, mask;
|
||||
|
@ -34,29 +34,6 @@
|
||||
#include "../pci.h"
|
||||
#include "pciehp.h"
|
||||
|
||||
static int __ref pciehp_add_bridge(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus *parent = dev->bus;
|
||||
int pass, busnr, start = parent->secondary;
|
||||
int end = parent->subordinate;
|
||||
|
||||
for (busnr = start; busnr <= end; busnr++) {
|
||||
if (!pci_find_bus(pci_domain_nr(parent), busnr))
|
||||
break;
|
||||
}
|
||||
if (busnr-- > end) {
|
||||
err("No bus number available for hot-added bridge %s\n",
|
||||
pci_name(dev));
|
||||
return -1;
|
||||
}
|
||||
for (pass = 0; pass < 2; pass++)
|
||||
busnr = pci_scan_bridge(parent, dev, busnr, pass);
|
||||
if (!dev->subordinate)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pciehp_configure_device(struct slot *p_slot)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
@ -85,9 +62,8 @@ int pciehp_configure_device(struct slot *p_slot)
|
||||
if (!dev)
|
||||
continue;
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
|
||||
pciehp_add_bridge(dev);
|
||||
}
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||
pci_hp_add_bridge(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ static int __init init_slots(void)
|
||||
struct slot *slot;
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *info;
|
||||
int retval = -ENOMEM;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
/*
|
||||
@ -261,17 +261,23 @@ static int __init init_slots(void)
|
||||
*/
|
||||
for (i = 0; i < num_slots; ++i) {
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
if (!slot) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
if (!hotplug_slot) {
|
||||
retval = -ENOMEM;
|
||||
goto error_slot;
|
||||
}
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
if (!info) {
|
||||
retval = -ENOMEM;
|
||||
goto error_hpslot;
|
||||
}
|
||||
hotplug_slot->info = info;
|
||||
|
||||
slot->number = i;
|
||||
|
@ -397,13 +397,11 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
|
||||
else
|
||||
sn_io_slot_fixup(dev);
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
unsigned char sec_bus;
|
||||
pci_read_config_byte(dev, PCI_SECONDARY_BUS,
|
||||
&sec_bus);
|
||||
new_bus = pci_add_new_bus(dev->bus, dev,
|
||||
sec_bus);
|
||||
pci_scan_child_bus(new_bus);
|
||||
new_ppb = 1;
|
||||
pci_hp_add_bridge(dev);
|
||||
if (dev->subordinate) {
|
||||
new_bus = dev->subordinate;
|
||||
new_ppb = 1;
|
||||
}
|
||||
}
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
@ -99,22 +99,28 @@ static int init_slots(struct controller *ctrl)
|
||||
struct hotplug_slot *hotplug_slot;
|
||||
struct hotplug_slot_info *info;
|
||||
char name[SLOT_NAME_SIZE];
|
||||
int retval = -ENOMEM;
|
||||
int retval;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ctrl->num_slots; i++) {
|
||||
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
|
||||
if (!slot)
|
||||
if (!slot) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
|
||||
if (!hotplug_slot)
|
||||
if (!hotplug_slot) {
|
||||
retval = -ENOMEM;
|
||||
goto error_slot;
|
||||
}
|
||||
slot->hotplug_slot = hotplug_slot;
|
||||
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
if (!info) {
|
||||
retval = -ENOMEM;
|
||||
goto error_hpslot;
|
||||
}
|
||||
hotplug_slot->info = info;
|
||||
|
||||
slot->hp_slot = i;
|
||||
|
@ -262,9 +262,6 @@ static int board_added(struct slot *p_slot)
|
||||
}
|
||||
|
||||
if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
|
||||
if (slots_not_empty)
|
||||
return WRONG_BUS_FREQUENCY;
|
||||
|
||||
if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
|
||||
ctrl_err(ctrl, "%s: Issue of set bus speed mode command"
|
||||
" failed\n", __func__);
|
||||
|
@ -37,9 +37,10 @@
|
||||
int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
|
||||
int num, fn;
|
||||
struct controller *ctrl = p_slot->ctrl;
|
||||
struct pci_dev *bridge = ctrl->pci_dev;
|
||||
struct pci_bus *parent = bridge->subordinate;
|
||||
int num, fn;
|
||||
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
|
||||
if (dev) {
|
||||
@ -61,39 +62,23 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
||||
if (!dev)
|
||||
continue;
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
|
||||
/* Find an unused bus number for the new bridge */
|
||||
struct pci_bus *child;
|
||||
unsigned char busnr, start = parent->secondary;
|
||||
unsigned char end = parent->subordinate;
|
||||
for (busnr = start; busnr <= end; busnr++) {
|
||||
if (!pci_find_bus(pci_domain_nr(parent),
|
||||
busnr))
|
||||
break;
|
||||
}
|
||||
if (busnr > end) {
|
||||
ctrl_err(ctrl,
|
||||
"No free bus for hot-added bridge\n");
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
child = pci_add_new_bus(parent, dev, busnr);
|
||||
if (!child) {
|
||||
ctrl_err(ctrl, "Cannot add new bus for %s\n",
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
child->subordinate = pci_do_scan_bus(child);
|
||||
pci_bus_size_bridges(child);
|
||||
}
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
|
||||
pci_hp_add_bridge(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_assign_unassigned_bridge_resources(bridge);
|
||||
|
||||
for (fn = 0; fn < 8; fn++) {
|
||||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
|
||||
if (!dev)
|
||||
continue;
|
||||
pci_configure_slot(dev);
|
||||
pci_dev_put(dev);
|
||||
}
|
||||
|
||||
pci_bus_assign_resources(parent);
|
||||
pci_bus_add_devices(parent);
|
||||
pci_enable_bridges(parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
|
||||
}
|
||||
}
|
||||
out += sprintf(out, "Free resources: bus numbers\n");
|
||||
for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) {
|
||||
for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) {
|
||||
if (!pci_find_bus(pci_domain_nr(bus), busnr))
|
||||
break;
|
||||
}
|
||||
if (busnr < bus->subordinate)
|
||||
if (busnr < bus->busn_res.end)
|
||||
out += sprintf(out, "start = %8.8x, length = %8.8x\n",
|
||||
busnr, (bus->subordinate - busnr));
|
||||
busnr, (int)(bus->busn_res.end - busnr));
|
||||
|
||||
return out - buf;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
|
||||
if (!child)
|
||||
return NULL;
|
||||
|
||||
child->subordinate = busnr;
|
||||
pci_bus_insert_busn_res(child, busnr, busnr);
|
||||
child->dev.parent = bus->bridge;
|
||||
rc = pci_bus_add_child(child);
|
||||
if (rc) {
|
||||
@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
|
||||
iov->offset = offset;
|
||||
iov->stride = stride;
|
||||
|
||||
if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) {
|
||||
if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->busn_res.end) {
|
||||
dev_err(&dev->dev, "SR-IOV: bus number out of range\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -48,6 +48,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
|
||||
if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev)
|
||||
return;
|
||||
|
||||
if (pci_dev->current_state == PCI_D3cold) {
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_runtime_resume(&pci_dev->dev);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pci_dev->pm_cap || !pci_dev->pme_support
|
||||
|| pci_check_pme_status(pci_dev)) {
|
||||
if (pci_dev->pme_poll)
|
||||
@ -162,6 +168,20 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
|
||||
return remove_pm_notifier(dev, pci_acpi_wake_dev);
|
||||
}
|
||||
|
||||
phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
|
||||
{
|
||||
acpi_status status = AE_NOT_EXIST;
|
||||
unsigned long long mcfg_addr;
|
||||
|
||||
if (handle)
|
||||
status = acpi_evaluate_integer(handle, METHOD_NAME__CBA,
|
||||
NULL, &mcfg_addr);
|
||||
if (ACPI_FAILURE(status))
|
||||
return 0;
|
||||
|
||||
return (phys_addr_t)mcfg_addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* _SxD returns the D-state with the highest power
|
||||
* (lowest D-state number) supported in the S-state "x".
|
||||
@ -187,9 +207,13 @@ acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
|
||||
|
||||
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)
|
||||
{
|
||||
int acpi_state;
|
||||
int acpi_state, d_max;
|
||||
|
||||
acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL);
|
||||
if (pdev->no_d3cold)
|
||||
d_max = ACPI_STATE_D3_HOT;
|
||||
else
|
||||
d_max = ACPI_STATE_D3_COLD;
|
||||
acpi_state = acpi_pm_device_sleep_state(&pdev->dev, NULL, d_max);
|
||||
if (acpi_state < 0)
|
||||
return PCI_POWER_ERROR;
|
||||
|
||||
@ -296,7 +320,13 @@ static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
|
||||
|
||||
static int acpi_pci_run_wake(struct pci_dev *dev, bool enable)
|
||||
{
|
||||
if (dev->pme_interrupt)
|
||||
/*
|
||||
* Per PCI Express Base Specification Revision 2.0 section
|
||||
* 5.3.3.2 Link Wakeup, platform support is needed for D3cold
|
||||
* waking up to power on the main link even if there is PME
|
||||
* support for D3cold
|
||||
*/
|
||||
if (dev->pme_interrupt && !dev->runtime_d3cold)
|
||||
return 0;
|
||||
|
||||
if (!acpi_pm_device_run_wake(&dev->dev, enable))
|
||||
|
@ -459,16 +459,17 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
|
||||
{
|
||||
pci_restore_standard_config(pci_dev);
|
||||
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
||||
static void pci_pm_default_resume_early(struct pci_dev *pci_dev)
|
||||
{
|
||||
pci_power_up(pci_dev);
|
||||
pci_restore_state(pci_dev);
|
||||
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Default "suspend" method for devices that have no driver provided suspend,
|
||||
* or not even a driver at all (second part).
|
||||
@ -1031,10 +1032,13 @@ static int pci_pm_runtime_suspend(struct device *dev)
|
||||
if (!pm || !pm->runtime_suspend)
|
||||
return -ENOSYS;
|
||||
|
||||
pci_dev->no_d3cold = false;
|
||||
error = pm->runtime_suspend(dev);
|
||||
suspend_report_result(pm->runtime_suspend, error);
|
||||
if (error)
|
||||
return error;
|
||||
if (!pci_dev->d3cold_allowed)
|
||||
pci_dev->no_d3cold = true;
|
||||
|
||||
pci_fixup_device(pci_fixup_suspend, pci_dev);
|
||||
|
||||
@ -1056,17 +1060,23 @@ static int pci_pm_runtime_suspend(struct device *dev)
|
||||
|
||||
static int pci_pm_runtime_resume(struct device *dev)
|
||||
{
|
||||
int rc;
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
||||
|
||||
if (!pm || !pm->runtime_resume)
|
||||
return -ENOSYS;
|
||||
|
||||
pci_pm_default_resume_early(pci_dev);
|
||||
pci_restore_standard_config(pci_dev);
|
||||
pci_fixup_device(pci_fixup_resume_early, pci_dev);
|
||||
__pci_enable_wake(pci_dev, PCI_D0, true, false);
|
||||
pci_fixup_device(pci_fixup_resume, pci_dev);
|
||||
|
||||
return pm->runtime_resume(dev);
|
||||
rc = pm->runtime_resume(dev);
|
||||
|
||||
pci_dev->runtime_d3cold = false;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pci_pm_runtime_idle(struct device *dev)
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/pci-aspm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include "pci.h"
|
||||
|
||||
static int sysfs_initialized; /* = 0 */
|
||||
@ -378,6 +379,31 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
|
||||
static ssize_t d3cold_allowed_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
unsigned long val;
|
||||
|
||||
if (strict_strtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pdev->d3cold_allowed = !!val;
|
||||
pm_runtime_resume(dev);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t d3cold_allowed_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
return sprintf (buf, "%u\n", pdev->d3cold_allowed);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct device_attribute pci_dev_attrs[] = {
|
||||
__ATTR_RO(resource),
|
||||
__ATTR_RO(vendor),
|
||||
@ -401,6 +427,9 @@ struct device_attribute pci_dev_attrs[] = {
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
__ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
|
||||
__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
|
||||
#endif
|
||||
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
|
||||
__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store),
|
||||
#endif
|
||||
__ATTR_NULL,
|
||||
};
|
||||
@ -1112,7 +1141,7 @@ static struct bin_attribute pcie_config_attr = {
|
||||
.write = pci_write_config,
|
||||
};
|
||||
|
||||
int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev)
|
||||
int __weak pcibios_add_platform_entries(struct pci_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus)
|
||||
struct list_head *tmp;
|
||||
unsigned char max, n;
|
||||
|
||||
max = bus->subordinate;
|
||||
max = bus->busn_res.end;
|
||||
list_for_each(tmp, &bus->children) {
|
||||
n = pci_bus_max_busnr(pci_bus_b(tmp));
|
||||
if(n > max)
|
||||
@ -136,30 +136,6 @@ void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar)
|
||||
EXPORT_SYMBOL_GPL(pci_ioremap_bar);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* pci_max_busnr - returns maximum PCI bus number
|
||||
*
|
||||
* Returns the highest PCI bus number present in the system global list of
|
||||
* PCI buses.
|
||||
*/
|
||||
unsigned char __devinit
|
||||
pci_max_busnr(void)
|
||||
{
|
||||
struct pci_bus *bus = NULL;
|
||||
unsigned char max, n;
|
||||
|
||||
max = 0;
|
||||
while ((bus = pci_find_next_bus(bus)) != NULL) {
|
||||
n = pci_bus_max_busnr(bus);
|
||||
if(n > max)
|
||||
max = n;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
#define PCI_FIND_CAP_TTL 48
|
||||
|
||||
static int __pci_find_next_cap_ttl(struct pci_bus *bus, unsigned int devfn,
|
||||
@ -277,6 +253,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_pcie_cap2 - query for devices' PCI_CAP_ID_EXP v2 capability structure
|
||||
* @dev: PCI device to check
|
||||
*
|
||||
* Like pci_pcie_cap() but also checks that the PCIe capability version is
|
||||
* >= 2. Note that v1 capability structures could be sparse in that not
|
||||
* all register fields were required. v2 requires the entire structure to
|
||||
* be present size wise, while still allowing for non-implemented registers
|
||||
* to exist but they must be hardwired to 0.
|
||||
*
|
||||
* Due to the differences in the versions of capability structures, one
|
||||
* must be careful not to try and access non-existant registers that may
|
||||
* exist in early versions - v1 - of Express devices.
|
||||
*
|
||||
* Returns the offset of the PCIe capability structure as long as the
|
||||
* capability version is >= 2; otherwise 0 is returned.
|
||||
*/
|
||||
static int pci_pcie_cap2(struct pci_dev *dev)
|
||||
{
|
||||
u16 flags;
|
||||
int pos;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
if (pos) {
|
||||
pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &flags);
|
||||
if ((flags & PCI_EXP_FLAGS_VERS) < 2)
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_find_ext_capability - Find an extended capability
|
||||
* @dev: PCI device to query
|
||||
@ -329,49 +337,6 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_find_ext_capability);
|
||||
|
||||
/**
|
||||
* pci_bus_find_ext_capability - find an extended capability
|
||||
* @bus: the PCI bus to query
|
||||
* @devfn: PCI device to query
|
||||
* @cap: capability code
|
||||
*
|
||||
* Like pci_find_ext_capability() but works for pci devices that do not have a
|
||||
* pci_dev structure set up yet.
|
||||
*
|
||||
* Returns the address of the requested capability structure within the
|
||||
* device's PCI configuration space or 0 in case the device does not
|
||||
* support it.
|
||||
*/
|
||||
int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
|
||||
int cap)
|
||||
{
|
||||
u32 header;
|
||||
int ttl;
|
||||
int pos = PCI_CFG_SPACE_SIZE;
|
||||
|
||||
/* minimum 8 bytes per capability */
|
||||
ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
|
||||
|
||||
if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
|
||||
return 0;
|
||||
if (header == 0xffffffff || header == 0)
|
||||
return 0;
|
||||
|
||||
while (ttl-- > 0) {
|
||||
if (PCI_EXT_CAP_ID(header) == cap)
|
||||
return pos;
|
||||
|
||||
pos = PCI_EXT_CAP_NEXT(header);
|
||||
if (pos < PCI_CFG_SPACE_SIZE)
|
||||
break;
|
||||
|
||||
if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
|
||||
{
|
||||
int rc, ttl = PCI_FIND_CAP_TTL;
|
||||
@ -622,7 +587,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
dev_info(&dev->dev, "Refused to change power state, "
|
||||
"currently in D%d\n", dev->current_state);
|
||||
|
||||
/* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
|
||||
/*
|
||||
* According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
|
||||
* INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
|
||||
* from D3hot to D0 _may_ perform an internal reset, thereby
|
||||
* going to "D0 Uninitialized" rather than "D0 Initialized".
|
||||
@ -654,6 +620,16 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
|
||||
if (dev->pm_cap) {
|
||||
u16 pmcsr;
|
||||
|
||||
/*
|
||||
* Configuration space is not accessible for device in
|
||||
* D3cold, so just keep or set D3cold for safety
|
||||
*/
|
||||
if (dev->current_state == PCI_D3cold)
|
||||
return;
|
||||
if (state == PCI_D3cold) {
|
||||
dev->current_state = PCI_D3cold;
|
||||
return;
|
||||
}
|
||||
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
|
||||
dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
|
||||
} else {
|
||||
@ -661,6 +637,19 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_power_up - Put the given device into D0 forcibly
|
||||
* @dev: PCI device to power up
|
||||
*/
|
||||
void pci_power_up(struct pci_dev *dev)
|
||||
{
|
||||
if (platform_pci_power_manageable(dev))
|
||||
platform_pci_set_power_state(dev, PCI_D0);
|
||||
|
||||
pci_raw_set_power_state(dev, PCI_D0);
|
||||
pci_update_current_state(dev, PCI_D0);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_platform_power_transition - Use platform to change device power state
|
||||
* @dev: PCI device to handle.
|
||||
@ -694,8 +683,50 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)
|
||||
*/
|
||||
static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
|
||||
{
|
||||
if (state == PCI_D0)
|
||||
if (state == PCI_D0) {
|
||||
pci_platform_power_transition(dev, PCI_D0);
|
||||
/*
|
||||
* Mandatory power management transition delays, see
|
||||
* PCI Express Base Specification Revision 2.0 Section
|
||||
* 6.6.1: Conventional Reset. Do not delay for
|
||||
* devices powered on/off by corresponding bridge,
|
||||
* because have already delayed for the bridge.
|
||||
*/
|
||||
if (dev->runtime_d3cold) {
|
||||
msleep(dev->d3cold_delay);
|
||||
/*
|
||||
* When powering on a bridge from D3cold, the
|
||||
* whole hierarchy may be powered on into
|
||||
* D0uninitialized state, resume them to give
|
||||
* them a chance to suspend again
|
||||
*/
|
||||
pci_wakeup_bus(dev->subordinate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __pci_dev_set_current_state - Set current state of a PCI device
|
||||
* @dev: Device to handle
|
||||
* @data: pointer to state to be set
|
||||
*/
|
||||
static int __pci_dev_set_current_state(struct pci_dev *dev, void *data)
|
||||
{
|
||||
pci_power_t state = *(pci_power_t *)data;
|
||||
|
||||
dev->current_state = state;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* __pci_bus_set_current_state - Walk given bus and set current state of devices
|
||||
* @bus: Top bus of the subtree to walk.
|
||||
* @state: state to be set
|
||||
*/
|
||||
static void __pci_bus_set_current_state(struct pci_bus *bus, pci_power_t state)
|
||||
{
|
||||
if (bus)
|
||||
pci_walk_bus(bus, __pci_dev_set_current_state, &state);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -707,8 +738,15 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
|
||||
*/
|
||||
int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state)
|
||||
{
|
||||
return state >= PCI_D0 ?
|
||||
pci_platform_power_transition(dev, state) : -EINVAL;
|
||||
int ret;
|
||||
|
||||
if (state <= PCI_D0)
|
||||
return -EINVAL;
|
||||
ret = pci_platform_power_transition(dev, state);
|
||||
/* Power off the bridge may power off the whole hierarchy */
|
||||
if (!ret && state == PCI_D3cold)
|
||||
__pci_bus_set_current_state(dev->subordinate, PCI_D3cold);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__pci_complete_power_transition);
|
||||
|
||||
@ -732,8 +770,8 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
int error;
|
||||
|
||||
/* bound the state we're entering */
|
||||
if (state > PCI_D3hot)
|
||||
state = PCI_D3hot;
|
||||
if (state > PCI_D3cold)
|
||||
state = PCI_D3cold;
|
||||
else if (state < PCI_D0)
|
||||
state = PCI_D0;
|
||||
else if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
|
||||
@ -744,14 +782,23 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
||||
*/
|
||||
return 0;
|
||||
|
||||
/* Check if we're already there */
|
||||
if (dev->current_state == state)
|
||||
return 0;
|
||||
|
||||
__pci_start_power_transition(dev, state);
|
||||
|
||||
/* This device is quirked not to be put into D3, so
|
||||
don't put it in D3 */
|
||||
if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
|
||||
if (state >= PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
|
||||
return 0;
|
||||
|
||||
error = pci_raw_set_power_state(dev, state);
|
||||
/*
|
||||
* To put device in D3cold, we put device into D3hot in native
|
||||
* way, then put device into D3cold with platform ops
|
||||
*/
|
||||
error = pci_raw_set_power_state(dev, state > PCI_D3hot ?
|
||||
PCI_D3hot : state);
|
||||
|
||||
if (!__pci_complete_power_transition(dev, state))
|
||||
error = 0;
|
||||
@ -822,12 +869,6 @@ EXPORT_SYMBOL(pci_choose_state);
|
||||
((flags & PCI_EXP_FLAGS_VERS) > 1 || \
|
||||
(type == PCI_EXP_TYPE_ROOT_PORT || \
|
||||
type == PCI_EXP_TYPE_RC_EC))
|
||||
#define pcie_cap_has_devctl2(type, flags) \
|
||||
((flags & PCI_EXP_FLAGS_VERS) > 1)
|
||||
#define pcie_cap_has_lnkctl2(type, flags) \
|
||||
((flags & PCI_EXP_FLAGS_VERS) > 1)
|
||||
#define pcie_cap_has_sltctl2(type, flags) \
|
||||
((flags & PCI_EXP_FLAGS_VERS) > 1)
|
||||
|
||||
static struct pci_cap_saved_state *pci_find_saved_cap(
|
||||
struct pci_dev *pci_dev, char cap)
|
||||
@ -870,13 +911,14 @@ static int pci_save_pcie_state(struct pci_dev *dev)
|
||||
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
|
||||
if (pcie_cap_has_rtctl(dev->pcie_type, flags))
|
||||
pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
|
||||
if (pcie_cap_has_devctl2(dev->pcie_type, flags))
|
||||
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
|
||||
if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
|
||||
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
|
||||
if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
|
||||
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
|
||||
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return 0;
|
||||
|
||||
pci_read_config_word(dev, pos + PCI_EXP_DEVCTL2, &cap[i++]);
|
||||
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL2, &cap[i++]);
|
||||
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL2, &cap[i++]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -903,12 +945,14 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
|
||||
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL, cap[i++]);
|
||||
if (pcie_cap_has_rtctl(dev->pcie_type, flags))
|
||||
pci_write_config_word(dev, pos + PCI_EXP_RTCTL, cap[i++]);
|
||||
if (pcie_cap_has_devctl2(dev->pcie_type, flags))
|
||||
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
|
||||
if (pcie_cap_has_lnkctl2(dev->pcie_type, flags))
|
||||
pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
|
||||
if (pcie_cap_has_sltctl2(dev->pcie_type, flags))
|
||||
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
|
||||
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
pci_write_config_word(dev, pos + PCI_EXP_DEVCTL2, cap[i++]);
|
||||
pci_write_config_word(dev, pos + PCI_EXP_LNKCTL2, cap[i++]);
|
||||
pci_write_config_word(dev, pos + PCI_EXP_SLTCTL2, cap[i++]);
|
||||
}
|
||||
|
||||
|
||||
@ -1349,7 +1393,7 @@ void pcim_pin_device(struct pci_dev *pdev)
|
||||
* is the default implementation. Architecture implementations can
|
||||
* override this.
|
||||
*/
|
||||
void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
|
||||
void __weak pcibios_disable_device (struct pci_dev *dev) {}
|
||||
|
||||
static void do_pci_disable_device(struct pci_dev *dev)
|
||||
{
|
||||
@ -1413,8 +1457,8 @@ pci_disable_device(struct pci_dev *dev)
|
||||
* Sets the PCIe reset state for the device. This is the default
|
||||
* implementation. Architecture implementations can override this.
|
||||
*/
|
||||
int __attribute__ ((weak)) pcibios_set_pcie_reset_state(struct pci_dev *dev,
|
||||
enum pcie_reset_state state)
|
||||
int __weak pcibios_set_pcie_reset_state(struct pci_dev *dev,
|
||||
enum pcie_reset_state state)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -1497,6 +1541,28 @@ void pci_pme_wakeup_bus(struct pci_bus *bus)
|
||||
pci_walk_bus(bus, pci_pme_wakeup, (void *)true);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wakeup - Wake up a PCI device
|
||||
* @dev: Device to handle.
|
||||
* @ign: ignored parameter
|
||||
*/
|
||||
static int pci_wakeup(struct pci_dev *pci_dev, void *ign)
|
||||
{
|
||||
pci_wakeup_event(pci_dev);
|
||||
pm_request_resume(&pci_dev->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_wakeup_bus - Walk given bus and wake up devices on it
|
||||
* @bus: Top bus of the subtree to walk.
|
||||
*/
|
||||
void pci_wakeup_bus(struct pci_bus *bus)
|
||||
{
|
||||
if (bus)
|
||||
pci_walk_bus(bus, pci_wakeup, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_pme_capable - check the capability of PCI device to generate PME#
|
||||
* @dev: PCI device to handle.
|
||||
@ -1518,6 +1584,16 @@ static void pci_pme_list_scan(struct work_struct *work)
|
||||
if (!list_empty(&pci_pme_list)) {
|
||||
list_for_each_entry_safe(pme_dev, n, &pci_pme_list, list) {
|
||||
if (pme_dev->dev->pme_poll) {
|
||||
struct pci_dev *bridge;
|
||||
|
||||
bridge = pme_dev->dev->bus->self;
|
||||
/*
|
||||
* If bridge is in low power state, the
|
||||
* configuration space of subordinate devices
|
||||
* may be not accessible
|
||||
*/
|
||||
if (bridge && bridge->current_state != PCI_D0)
|
||||
continue;
|
||||
pci_pme_wakeup(pme_dev->dev, NULL);
|
||||
} else {
|
||||
list_del(&pme_dev->list);
|
||||
@ -1744,6 +1820,10 @@ int pci_prepare_to_sleep(struct pci_dev *dev)
|
||||
if (target_state == PCI_POWER_ERROR)
|
||||
return -EIO;
|
||||
|
||||
/* D3cold during system suspend/hibernate is not supported */
|
||||
if (target_state > PCI_D3hot)
|
||||
target_state = PCI_D3hot;
|
||||
|
||||
pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev));
|
||||
|
||||
error = pci_set_power_state(dev, target_state);
|
||||
@ -1781,12 +1861,16 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)
|
||||
if (target_state == PCI_POWER_ERROR)
|
||||
return -EIO;
|
||||
|
||||
dev->runtime_d3cold = target_state == PCI_D3cold;
|
||||
|
||||
__pci_enable_wake(dev, target_state, true, pci_dev_run_wake(dev));
|
||||
|
||||
error = pci_set_power_state(dev, target_state);
|
||||
|
||||
if (error)
|
||||
if (error) {
|
||||
__pci_enable_wake(dev, target_state, true, false);
|
||||
dev->runtime_d3cold = false;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -1856,6 +1940,7 @@ void pci_pm_init(struct pci_dev *dev)
|
||||
|
||||
dev->pm_cap = pm;
|
||||
dev->d3_delay = PCI_PM_D3_WAIT;
|
||||
dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
|
||||
|
||||
dev->d1_support = false;
|
||||
dev->d2_support = false;
|
||||
@ -1983,7 +2068,7 @@ void pci_enable_ari(struct pci_dev *dev)
|
||||
{
|
||||
int pos;
|
||||
u32 cap;
|
||||
u16 flags, ctrl;
|
||||
u16 ctrl;
|
||||
struct pci_dev *bridge;
|
||||
|
||||
if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
|
||||
@ -1994,18 +2079,14 @@ void pci_enable_ari(struct pci_dev *dev)
|
||||
return;
|
||||
|
||||
bridge = dev->bus->self;
|
||||
if (!bridge || !pci_is_pcie(bridge))
|
||||
if (!bridge)
|
||||
return;
|
||||
|
||||
pos = pci_pcie_cap(bridge);
|
||||
/* ARI is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(bridge);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
/* ARI is a PCIe v2 feature */
|
||||
pci_read_config_word(bridge, pos + PCI_EXP_FLAGS, &flags);
|
||||
if ((flags & PCI_EXP_FLAGS_VERS) < 2)
|
||||
return;
|
||||
|
||||
pci_read_config_dword(bridge, pos + PCI_EXP_DEVCAP2, &cap);
|
||||
if (!(cap & PCI_EXP_DEVCAP2_ARI))
|
||||
return;
|
||||
@ -2018,7 +2099,7 @@ void pci_enable_ari(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_enable_ido - enable ID-based ordering on a device
|
||||
* pci_enable_ido - enable ID-based Ordering on a device
|
||||
* @dev: the PCI device
|
||||
* @type: which types of IDO to enable
|
||||
*
|
||||
@ -2031,7 +2112,8 @@ void pci_enable_ido(struct pci_dev *dev, unsigned long type)
|
||||
int pos;
|
||||
u16 ctrl;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* ID-based Ordering is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
@ -2054,10 +2136,8 @@ void pci_disable_ido(struct pci_dev *dev, unsigned long type)
|
||||
int pos;
|
||||
u16 ctrl;
|
||||
|
||||
if (!pci_is_pcie(dev))
|
||||
return;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* ID-based Ordering is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
@ -2096,10 +2176,8 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
|
||||
u16 ctrl;
|
||||
int ret;
|
||||
|
||||
if (!pci_is_pcie(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* OBFF is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return -ENOTSUPP;
|
||||
|
||||
@ -2108,7 +2186,7 @@ int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type)
|
||||
return -ENOTSUPP; /* no OBFF support at all */
|
||||
|
||||
/* Make sure the topology supports OBFF as well */
|
||||
if (dev->bus) {
|
||||
if (dev->bus->self) {
|
||||
ret = pci_enable_obff(dev->bus->self, type);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -2149,10 +2227,8 @@ void pci_disable_obff(struct pci_dev *dev)
|
||||
int pos;
|
||||
u16 ctrl;
|
||||
|
||||
if (!pci_is_pcie(dev))
|
||||
return;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* OBFF is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
@ -2169,15 +2245,13 @@ EXPORT_SYMBOL(pci_disable_obff);
|
||||
* RETURNS:
|
||||
* True if @dev supports latency tolerance reporting, false otherwise.
|
||||
*/
|
||||
bool pci_ltr_supported(struct pci_dev *dev)
|
||||
static bool pci_ltr_supported(struct pci_dev *dev)
|
||||
{
|
||||
int pos;
|
||||
u32 cap;
|
||||
|
||||
if (!pci_is_pcie(dev))
|
||||
return false;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* LTR is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return false;
|
||||
|
||||
@ -2185,7 +2259,6 @@ bool pci_ltr_supported(struct pci_dev *dev)
|
||||
|
||||
return cap & PCI_EXP_DEVCAP2_LTR;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_ltr_supported);
|
||||
|
||||
/**
|
||||
* pci_enable_ltr - enable latency tolerance reporting
|
||||
@ -2206,7 +2279,8 @@ int pci_enable_ltr(struct pci_dev *dev)
|
||||
if (!pci_ltr_supported(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* LTR is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return -ENOTSUPP;
|
||||
|
||||
@ -2215,7 +2289,7 @@ int pci_enable_ltr(struct pci_dev *dev)
|
||||
return -EINVAL;
|
||||
|
||||
/* Enable upstream ports first */
|
||||
if (dev->bus) {
|
||||
if (dev->bus->self) {
|
||||
ret = pci_enable_ltr(dev->bus->self);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -2241,7 +2315,8 @@ void pci_disable_ltr(struct pci_dev *dev)
|
||||
if (!pci_ltr_supported(dev))
|
||||
return;
|
||||
|
||||
pos = pci_pcie_cap(dev);
|
||||
/* LTR is a PCIe cap v2 feature */
|
||||
pos = pci_pcie_cap2(dev);
|
||||
if (!pos)
|
||||
return;
|
||||
|
||||
@ -2359,6 +2434,75 @@ void pci_enable_acs(struct pci_dev *dev)
|
||||
pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_acs_enabled - test ACS against required flags for a given device
|
||||
* @pdev: device to test
|
||||
* @acs_flags: required PCI ACS flags
|
||||
*
|
||||
* Return true if the device supports the provided flags. Automatically
|
||||
* filters out flags that are not implemented on multifunction devices.
|
||||
*/
|
||||
bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)
|
||||
{
|
||||
int pos, ret;
|
||||
u16 ctrl;
|
||||
|
||||
ret = pci_dev_specific_acs_enabled(pdev, acs_flags);
|
||||
if (ret >= 0)
|
||||
return ret > 0;
|
||||
|
||||
if (!pci_is_pcie(pdev))
|
||||
return false;
|
||||
|
||||
/* Filter out flags not applicable to multifunction */
|
||||
if (pdev->multifunction)
|
||||
acs_flags &= (PCI_ACS_RR | PCI_ACS_CR |
|
||||
PCI_ACS_EC | PCI_ACS_DT);
|
||||
|
||||
if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM ||
|
||||
pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
|
||||
pdev->multifunction) {
|
||||
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ACS);
|
||||
if (!pos)
|
||||
return false;
|
||||
|
||||
pci_read_config_word(pdev, pos + PCI_ACS_CTRL, &ctrl);
|
||||
if ((ctrl & acs_flags) != acs_flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_acs_path_enable - test ACS flags from start to end in a hierarchy
|
||||
* @start: starting downstream device
|
||||
* @end: ending upstream device or NULL to search to the root bus
|
||||
* @acs_flags: required flags
|
||||
*
|
||||
* Walk up a device tree from start to end testing PCI ACS support. If
|
||||
* any step along the way does not support the required flags, return false.
|
||||
*/
|
||||
bool pci_acs_path_enabled(struct pci_dev *start,
|
||||
struct pci_dev *end, u16 acs_flags)
|
||||
{
|
||||
struct pci_dev *pdev, *parent = start;
|
||||
|
||||
do {
|
||||
pdev = parent;
|
||||
|
||||
if (!pci_acs_enabled(pdev, acs_flags))
|
||||
return false;
|
||||
|
||||
if (pci_is_root_bus(pdev->bus))
|
||||
return (end == NULL);
|
||||
|
||||
parent = pdev->bus->self;
|
||||
} while (pdev != end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
|
||||
* @dev: the PCI device
|
||||
@ -2665,6 +2809,18 @@ static void __pci_set_master(struct pci_dev *dev, bool enable)
|
||||
dev->is_busmaster = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcibios_setup - process "pci=" kernel boot arguments
|
||||
* @str: string used to pass in "pci=" kernel boot arguments
|
||||
*
|
||||
* Process kernel boot arguments. This is the default implementation.
|
||||
* Architecture specific implementations can override this as necessary.
|
||||
*/
|
||||
char * __weak __init pcibios_setup(char *str)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* pcibios_set_master - enable PCI bus-mastering for device dev
|
||||
* @dev: the PCI device to enable
|
||||
@ -2876,6 +3032,9 @@ bool pci_intx_mask_supported(struct pci_dev *dev)
|
||||
bool mask_supported = false;
|
||||
u16 orig, new;
|
||||
|
||||
if (dev->broken_intx_masking)
|
||||
return false;
|
||||
|
||||
pci_cfg_access_lock(dev);
|
||||
|
||||
pci_read_config_word(dev, PCI_COMMAND, &orig);
|
||||
@ -3395,8 +3554,7 @@ int pcix_set_mmrbc(struct pci_dev *dev, int mmrbc)
|
||||
|
||||
o = (cmd & PCI_X_CMD_MAX_READ) >> 2;
|
||||
if (o != v) {
|
||||
if (v > o && dev->bus &&
|
||||
(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
|
||||
if (v > o && (dev->bus->bus_flags & PCI_BUS_FLAGS_NO_MMRBC))
|
||||
return -EIO;
|
||||
|
||||
cmd &= ~PCI_X_CMD_MAX_READ;
|
||||
@ -3851,7 +4009,7 @@ static void __devinit pci_no_domains(void)
|
||||
* greater than 0xff). This is the default implementation. Architecture
|
||||
* implementations can override this.
|
||||
*/
|
||||
int __attribute__ ((weak)) pci_ext_cfg_avail(struct pci_dev *dev)
|
||||
int __weak pci_ext_cfg_avail(struct pci_dev *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
@ -67,9 +67,11 @@ struct pci_platform_pm_ops {
|
||||
|
||||
extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
|
||||
extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
|
||||
extern void pci_power_up(struct pci_dev *dev);
|
||||
extern void pci_disable_enabled_device(struct pci_dev *dev);
|
||||
extern int pci_finish_runtime_suspend(struct pci_dev *dev);
|
||||
extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
|
||||
extern void pci_wakeup_bus(struct pci_bus *bus);
|
||||
extern void pci_pm_init(struct pci_dev *dev);
|
||||
extern void platform_pci_wakeup_init(struct pci_dev *dev);
|
||||
extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
|
||||
@ -86,13 +88,6 @@ static inline bool pci_is_bridge(struct pci_dev *pci_dev)
|
||||
return !!(pci_dev->subordinate);
|
||||
}
|
||||
|
||||
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
|
||||
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
|
||||
extern int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
|
||||
extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
|
||||
extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
|
||||
extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
|
||||
|
||||
struct pci_vpd_ops {
|
||||
ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
|
||||
ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
|
||||
@ -124,7 +119,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
|
||||
#endif
|
||||
|
||||
/* Functions for PCI Hotplug drivers to use */
|
||||
extern unsigned int pci_do_scan_bus(struct pci_bus *bus);
|
||||
int pci_hp_add_bridge(struct pci_dev *dev);
|
||||
|
||||
#ifdef HAVE_PCI_LEGACY
|
||||
extern void pci_create_legacy_files(struct pci_bus *bus);
|
||||
|
@ -59,7 +59,7 @@ static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
|
||||
|
||||
p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
|
||||
if (p->flags & ACPI_HEST_GLOBAL) {
|
||||
if ((info->pci_dev->is_pcie &&
|
||||
if ((pci_is_pcie(info->pci_dev) &&
|
||||
info->pci_dev->pcie_type == pcie_type) || bridge)
|
||||
ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
|
||||
} else
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/pcieport_if.h>
|
||||
#include <linux/aer.h>
|
||||
@ -99,6 +100,51 @@ static int pcie_port_resume_noirq(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
struct d3cold_info {
|
||||
bool no_d3cold;
|
||||
unsigned int d3cold_delay;
|
||||
};
|
||||
|
||||
static int pci_dev_d3cold_info(struct pci_dev *pdev, void *data)
|
||||
{
|
||||
struct d3cold_info *info = data;
|
||||
|
||||
info->d3cold_delay = max_t(unsigned int, pdev->d3cold_delay,
|
||||
info->d3cold_delay);
|
||||
if (pdev->no_d3cold)
|
||||
info->no_d3cold = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcie_port_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
struct d3cold_info d3cold_info = {
|
||||
.no_d3cold = false,
|
||||
.d3cold_delay = PCI_PM_D3_WAIT,
|
||||
};
|
||||
|
||||
/*
|
||||
* If any subordinate device disable D3cold, we should not put
|
||||
* the port into D3cold. The D3cold delay of port should be
|
||||
* the max of that of all subordinate devices.
|
||||
*/
|
||||
pci_walk_bus(pdev->subordinate, pci_dev_d3cold_info, &d3cold_info);
|
||||
pdev->no_d3cold = d3cold_info.no_d3cold;
|
||||
pdev->d3cold_delay = d3cold_info.d3cold_delay;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcie_port_runtime_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define pcie_port_runtime_suspend NULL
|
||||
#define pcie_port_runtime_resume NULL
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
||||
.suspend = pcie_port_device_suspend,
|
||||
.resume = pcie_port_device_resume,
|
||||
@ -107,6 +153,8 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
||||
.poweroff = pcie_port_device_suspend,
|
||||
.restore = pcie_port_device_resume,
|
||||
.resume_noirq = pcie_port_resume_noirq,
|
||||
.runtime_suspend = pcie_port_runtime_suspend,
|
||||
.runtime_resume = pcie_port_runtime_resume,
|
||||
};
|
||||
|
||||
#define PCIE_PORTDRV_PM_OPS (&pcie_portdrv_pm_ops)
|
||||
@ -116,6 +164,14 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
|
||||
#define PCIE_PORTDRV_PM_OPS NULL
|
||||
#endif /* !PM */
|
||||
|
||||
/*
|
||||
* PCIe port runtime suspend is broken for some chipsets, so use a
|
||||
* black list to disable runtime PM for these chipsets.
|
||||
*/
|
||||
static const struct pci_device_id port_runtime_pm_black_list[] = {
|
||||
{ /* end: all zeroes */ }
|
||||
};
|
||||
|
||||
/*
|
||||
* pcie_portdrv_probe - Probe PCI-Express port devices
|
||||
* @dev: PCI-Express port device being probed
|
||||
@ -144,12 +200,16 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
|
||||
return status;
|
||||
|
||||
pci_save_state(dev);
|
||||
if (!pci_match_id(port_runtime_pm_black_list, dev))
|
||||
pm_runtime_put_noidle(&dev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pcie_portdrv_remove(struct pci_dev *dev)
|
||||
{
|
||||
if (!pci_match_id(port_runtime_pm_black_list, dev))
|
||||
pm_runtime_get_noresume(&dev->dev);
|
||||
pcie_port_device_remove(dev);
|
||||
pci_disable_device(dev);
|
||||
}
|
||||
|
@ -16,10 +16,47 @@
|
||||
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
|
||||
#define CARDBUS_RESERVE_BUSNR 3
|
||||
|
||||
struct resource busn_resource = {
|
||||
.name = "PCI busn",
|
||||
.start = 0,
|
||||
.end = 255,
|
||||
.flags = IORESOURCE_BUS,
|
||||
};
|
||||
|
||||
/* Ugh. Need to stop exporting this to modules. */
|
||||
LIST_HEAD(pci_root_buses);
|
||||
EXPORT_SYMBOL(pci_root_buses);
|
||||
|
||||
static LIST_HEAD(pci_domain_busn_res_list);
|
||||
|
||||
struct pci_domain_busn_res {
|
||||
struct list_head list;
|
||||
struct resource res;
|
||||
int domain_nr;
|
||||
};
|
||||
|
||||
static struct resource *get_pci_domain_busn_res(int domain_nr)
|
||||
{
|
||||
struct pci_domain_busn_res *r;
|
||||
|
||||
list_for_each_entry(r, &pci_domain_busn_res_list, list)
|
||||
if (r->domain_nr == domain_nr)
|
||||
return &r->res;
|
||||
|
||||
r = kzalloc(sizeof(*r), GFP_KERNEL);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
r->domain_nr = domain_nr;
|
||||
r->res.start = 0;
|
||||
r->res.end = 0xff;
|
||||
r->res.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED;
|
||||
|
||||
list_add_tail(&r->list, &pci_domain_busn_res_list);
|
||||
|
||||
return &r->res;
|
||||
}
|
||||
|
||||
static int find_anything(struct device *dev, void *data)
|
||||
{
|
||||
return 1;
|
||||
@ -152,9 +189,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||
pci_read_config_dword(dev, pos, &sz);
|
||||
pci_write_config_dword(dev, pos, l);
|
||||
|
||||
if (!dev->mmio_always_on)
|
||||
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
|
||||
|
||||
/*
|
||||
* All bits set in sz means the device isn't working properly.
|
||||
* If the BAR isn't implemented, all bits must be 0. If it's a
|
||||
@ -239,6 +273,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
||||
}
|
||||
|
||||
out:
|
||||
if (!dev->mmio_always_on)
|
||||
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
|
||||
|
||||
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
|
||||
fail:
|
||||
res->flags = 0;
|
||||
@ -269,34 +306,38 @@ static void __devinit pci_read_bridge_io(struct pci_bus *child)
|
||||
{
|
||||
struct pci_dev *dev = child->self;
|
||||
u8 io_base_lo, io_limit_lo;
|
||||
unsigned long base, limit;
|
||||
unsigned long io_mask, io_granularity, base, limit;
|
||||
struct pci_bus_region region;
|
||||
struct resource *res, res2;
|
||||
struct resource *res;
|
||||
|
||||
io_mask = PCI_IO_RANGE_MASK;
|
||||
io_granularity = 0x1000;
|
||||
if (dev->io_window_1k) {
|
||||
/* Support 1K I/O space granularity */
|
||||
io_mask = PCI_IO_1K_RANGE_MASK;
|
||||
io_granularity = 0x400;
|
||||
}
|
||||
|
||||
res = child->resource[0];
|
||||
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
|
||||
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
|
||||
base = (io_base_lo & PCI_IO_RANGE_MASK) << 8;
|
||||
limit = (io_limit_lo & PCI_IO_RANGE_MASK) << 8;
|
||||
base = (io_base_lo & io_mask) << 8;
|
||||
limit = (io_limit_lo & io_mask) << 8;
|
||||
|
||||
if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) {
|
||||
u16 io_base_hi, io_limit_hi;
|
||||
|
||||
pci_read_config_word(dev, PCI_IO_BASE_UPPER16, &io_base_hi);
|
||||
pci_read_config_word(dev, PCI_IO_LIMIT_UPPER16, &io_limit_hi);
|
||||
base |= (io_base_hi << 16);
|
||||
limit |= (io_limit_hi << 16);
|
||||
base |= ((unsigned long) io_base_hi << 16);
|
||||
limit |= ((unsigned long) io_limit_hi << 16);
|
||||
}
|
||||
|
||||
if (base && base <= limit) {
|
||||
if (base <= limit) {
|
||||
res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;
|
||||
res2.flags = res->flags;
|
||||
region.start = base;
|
||||
region.end = limit + 0xfff;
|
||||
pcibios_bus_to_resource(dev, &res2, ®ion);
|
||||
if (!res->start)
|
||||
res->start = res2.start;
|
||||
if (!res->end)
|
||||
res->end = res2.end;
|
||||
region.end = limit + io_granularity - 1;
|
||||
pcibios_bus_to_resource(dev, res, ®ion);
|
||||
dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
|
||||
}
|
||||
}
|
||||
@ -312,9 +353,9 @@ static void __devinit pci_read_bridge_mmio(struct pci_bus *child)
|
||||
res = child->resource[1];
|
||||
pci_read_config_word(dev, PCI_MEMORY_BASE, &mem_base_lo);
|
||||
pci_read_config_word(dev, PCI_MEMORY_LIMIT, &mem_limit_lo);
|
||||
base = (mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
|
||||
limit = (mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
|
||||
if (base && base <= limit) {
|
||||
base = ((unsigned long) mem_base_lo & PCI_MEMORY_RANGE_MASK) << 16;
|
||||
limit = ((unsigned long) mem_limit_lo & PCI_MEMORY_RANGE_MASK) << 16;
|
||||
if (base <= limit) {
|
||||
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
|
||||
region.start = base;
|
||||
region.end = limit + 0xfffff;
|
||||
@ -334,11 +375,12 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
|
||||
res = child->resource[2];
|
||||
pci_read_config_word(dev, PCI_PREF_MEMORY_BASE, &mem_base_lo);
|
||||
pci_read_config_word(dev, PCI_PREF_MEMORY_LIMIT, &mem_limit_lo);
|
||||
base = (mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
|
||||
limit = (mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
|
||||
base = ((unsigned long) mem_base_lo & PCI_PREF_RANGE_MASK) << 16;
|
||||
limit = ((unsigned long) mem_limit_lo & PCI_PREF_RANGE_MASK) << 16;
|
||||
|
||||
if ((mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) == PCI_PREF_RANGE_TYPE_64) {
|
||||
u32 mem_base_hi, mem_limit_hi;
|
||||
|
||||
pci_read_config_dword(dev, PCI_PREF_BASE_UPPER32, &mem_base_hi);
|
||||
pci_read_config_dword(dev, PCI_PREF_LIMIT_UPPER32, &mem_limit_hi);
|
||||
|
||||
@ -349,8 +391,8 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
|
||||
*/
|
||||
if (mem_base_hi <= mem_limit_hi) {
|
||||
#if BITS_PER_LONG == 64
|
||||
base |= ((long) mem_base_hi) << 32;
|
||||
limit |= ((long) mem_limit_hi) << 32;
|
||||
base |= ((unsigned long) mem_base_hi) << 32;
|
||||
limit |= ((unsigned long) mem_limit_hi) << 32;
|
||||
#else
|
||||
if (mem_base_hi || mem_limit_hi) {
|
||||
dev_err(&dev->dev, "can't handle 64-bit "
|
||||
@ -360,7 +402,7 @@ static void __devinit pci_read_bridge_mmio_pref(struct pci_bus *child)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (base && base <= limit) {
|
||||
if (base <= limit) {
|
||||
res->flags = (mem_base_lo & PCI_PREF_RANGE_TYPE_MASK) |
|
||||
IORESOURCE_MEM | IORESOURCE_PREFETCH;
|
||||
if (res->flags & PCI_PREF_RANGE_TYPE_64)
|
||||
@ -381,8 +423,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
|
||||
if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
|
||||
return;
|
||||
|
||||
dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
|
||||
child->secondary, child->subordinate,
|
||||
dev_info(&dev->dev, "PCI bridge to %pR%s\n",
|
||||
&child->busn_res,
|
||||
dev->transparent ? " (subtractive decode)" : "");
|
||||
|
||||
pci_bus_remove_resources(child);
|
||||
@ -599,9 +641,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
|
||||
* Set up the primary, secondary and subordinate
|
||||
* bus numbers.
|
||||
*/
|
||||
child->number = child->secondary = busnr;
|
||||
child->primary = parent->secondary;
|
||||
child->subordinate = 0xff;
|
||||
child->number = child->busn_res.start = busnr;
|
||||
child->primary = parent->busn_res.start;
|
||||
child->busn_res.end = 0xff;
|
||||
|
||||
if (!bridge)
|
||||
return child;
|
||||
@ -643,8 +685,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
|
||||
if (!pcibios_assign_all_busses())
|
||||
return;
|
||||
|
||||
while (parent->parent && parent->subordinate < max) {
|
||||
parent->subordinate = max;
|
||||
while (parent->parent && parent->busn_res.end < max) {
|
||||
parent->busn_res.end = max;
|
||||
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
|
||||
parent = parent->parent;
|
||||
}
|
||||
@ -718,15 +760,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
||||
if (!child)
|
||||
goto out;
|
||||
child->primary = primary;
|
||||
child->subordinate = subordinate;
|
||||
pci_bus_insert_busn_res(child, secondary, subordinate);
|
||||
child->bridge_ctl = bctl;
|
||||
}
|
||||
|
||||
cmax = pci_scan_child_bus(child);
|
||||
if (cmax > max)
|
||||
max = cmax;
|
||||
if (child->subordinate > max)
|
||||
max = child->subordinate;
|
||||
if (child->busn_res.end > max)
|
||||
max = child->busn_res.end;
|
||||
} else {
|
||||
/*
|
||||
* We need to assign a number to this bus which we always
|
||||
@ -756,11 +798,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
||||
child = pci_add_new_bus(bus, dev, ++max);
|
||||
if (!child)
|
||||
goto out;
|
||||
pci_bus_insert_busn_res(child, max, 0xff);
|
||||
}
|
||||
buses = (buses & 0xff000000)
|
||||
| ((unsigned int)(child->primary) << 0)
|
||||
| ((unsigned int)(child->secondary) << 8)
|
||||
| ((unsigned int)(child->subordinate) << 16);
|
||||
| ((unsigned int)(child->busn_res.start) << 8)
|
||||
| ((unsigned int)(child->busn_res.end) << 16);
|
||||
|
||||
/*
|
||||
* yenta.c forces a secondary latency timer of 176.
|
||||
@ -805,8 +848,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
||||
break;
|
||||
while (parent->parent) {
|
||||
if ((!pcibios_assign_all_busses()) &&
|
||||
(parent->subordinate > max) &&
|
||||
(parent->subordinate <= max+i)) {
|
||||
(parent->busn_res.end > max) &&
|
||||
(parent->busn_res.end <= max+i)) {
|
||||
j = 1;
|
||||
}
|
||||
parent = parent->parent;
|
||||
@ -827,7 +870,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
||||
/*
|
||||
* Set the subordinate bus number to its real value.
|
||||
*/
|
||||
child->subordinate = max;
|
||||
pci_bus_update_busn_res_end(child, max);
|
||||
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
|
||||
}
|
||||
|
||||
@ -837,19 +880,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
|
||||
|
||||
/* Has only triggered on CardBus, fixup is in yenta_socket */
|
||||
while (bus->parent) {
|
||||
if ((child->subordinate > bus->subordinate) ||
|
||||
(child->number > bus->subordinate) ||
|
||||
if ((child->busn_res.end > bus->busn_res.end) ||
|
||||
(child->number > bus->busn_res.end) ||
|
||||
(child->number < bus->number) ||
|
||||
(child->subordinate < bus->number)) {
|
||||
dev_info(&child->dev, "[bus %02x-%02x] %s "
|
||||
"hidden behind%s bridge %s [bus %02x-%02x]\n",
|
||||
child->number, child->subordinate,
|
||||
(bus->number > child->subordinate &&
|
||||
bus->subordinate < child->number) ?
|
||||
(child->busn_res.end < bus->number)) {
|
||||
dev_info(&child->dev, "%pR %s "
|
||||
"hidden behind%s bridge %s %pR\n",
|
||||
&child->busn_res,
|
||||
(bus->number > child->busn_res.end &&
|
||||
bus->busn_res.end < child->number) ?
|
||||
"wholly" : "partially",
|
||||
bus->self->transparent ? " transparent" : "",
|
||||
dev_name(&bus->dev),
|
||||
bus->number, bus->subordinate);
|
||||
&bus->busn_res);
|
||||
}
|
||||
bus = bus->parent;
|
||||
}
|
||||
@ -1548,7 +1591,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
|
||||
|
||||
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
|
||||
{
|
||||
unsigned int devfn, pass, max = bus->secondary;
|
||||
unsigned int devfn, pass, max = bus->busn_res.start;
|
||||
struct pci_dev *dev;
|
||||
|
||||
dev_dbg(&bus->dev, "scanning bus\n");
|
||||
@ -1642,7 +1685,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
|
||||
/* Create legacy_io and legacy_mem files for this bus */
|
||||
pci_create_legacy_files(b);
|
||||
|
||||
b->number = b->secondary = bus;
|
||||
b->number = b->busn_res.start = bus;
|
||||
|
||||
if (parent)
|
||||
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
|
||||
@ -1654,7 +1697,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
|
||||
list_move_tail(&window->list, &bridge->windows);
|
||||
res = window->res;
|
||||
offset = window->offset;
|
||||
pci_bus_add_resource(b, res, 0);
|
||||
if (res->flags & IORESOURCE_BUS)
|
||||
pci_bus_insert_busn_res(b, bus, res->end);
|
||||
else
|
||||
pci_bus_add_resource(b, res, 0);
|
||||
if (offset) {
|
||||
if (resource_type(res) == IORESOURCE_IO)
|
||||
fmt = " (bus address [%#06llx-%#06llx])";
|
||||
@ -1684,16 +1730,104 @@ err_out:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
|
||||
{
|
||||
struct resource *res = &b->busn_res;
|
||||
struct resource *parent_res, *conflict;
|
||||
|
||||
res->start = bus;
|
||||
res->end = bus_max;
|
||||
res->flags = IORESOURCE_BUS;
|
||||
|
||||
if (!pci_is_root_bus(b))
|
||||
parent_res = &b->parent->busn_res;
|
||||
else {
|
||||
parent_res = get_pci_domain_busn_res(pci_domain_nr(b));
|
||||
res->flags |= IORESOURCE_PCI_FIXED;
|
||||
}
|
||||
|
||||
conflict = insert_resource_conflict(parent_res, res);
|
||||
|
||||
if (conflict)
|
||||
dev_printk(KERN_DEBUG, &b->dev,
|
||||
"busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n",
|
||||
res, pci_is_root_bus(b) ? "domain " : "",
|
||||
parent_res, conflict->name, conflict);
|
||||
else
|
||||
dev_printk(KERN_DEBUG, &b->dev,
|
||||
"busn_res: %pR is inserted under %s%pR\n",
|
||||
res, pci_is_root_bus(b) ? "domain " : "",
|
||||
parent_res);
|
||||
|
||||
return conflict == NULL;
|
||||
}
|
||||
|
||||
int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
|
||||
{
|
||||
struct resource *res = &b->busn_res;
|
||||
struct resource old_res = *res;
|
||||
resource_size_t size;
|
||||
int ret;
|
||||
|
||||
if (res->start > bus_max)
|
||||
return -EINVAL;
|
||||
|
||||
size = bus_max - res->start + 1;
|
||||
ret = adjust_resource(res, res->start, size);
|
||||
dev_printk(KERN_DEBUG, &b->dev,
|
||||
"busn_res: %pR end %s updated to %02x\n",
|
||||
&old_res, ret ? "can not be" : "is", bus_max);
|
||||
|
||||
if (!ret && !res->parent)
|
||||
pci_bus_insert_busn_res(b, res->start, res->end);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pci_bus_release_busn_res(struct pci_bus *b)
|
||||
{
|
||||
struct resource *res = &b->busn_res;
|
||||
int ret;
|
||||
|
||||
if (!res->flags || !res->parent)
|
||||
return;
|
||||
|
||||
ret = release_resource(res);
|
||||
dev_printk(KERN_DEBUG, &b->dev,
|
||||
"busn_res: %pR %s released\n",
|
||||
res, ret ? "can not be" : "is");
|
||||
}
|
||||
|
||||
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
|
||||
struct pci_ops *ops, void *sysdata, struct list_head *resources)
|
||||
{
|
||||
struct pci_host_bridge_window *window;
|
||||
bool found = false;
|
||||
struct pci_bus *b;
|
||||
int max;
|
||||
|
||||
list_for_each_entry(window, resources, list)
|
||||
if (window->res->flags & IORESOURCE_BUS) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
|
||||
if (!b)
|
||||
return NULL;
|
||||
|
||||
b->subordinate = pci_scan_child_bus(b);
|
||||
if (!found) {
|
||||
dev_info(&b->dev,
|
||||
"No busn resource found for root bus, will use [bus %02x-ff]\n",
|
||||
bus);
|
||||
pci_bus_insert_busn_res(b, bus, 255);
|
||||
}
|
||||
|
||||
max = pci_scan_child_bus(b);
|
||||
|
||||
if (!found)
|
||||
pci_bus_update_busn_res_end(b, max);
|
||||
|
||||
pci_bus_add_devices(b);
|
||||
return b;
|
||||
}
|
||||
@ -1708,9 +1842,10 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
|
||||
|
||||
pci_add_resource(&resources, &ioport_resource);
|
||||
pci_add_resource(&resources, &iomem_resource);
|
||||
pci_add_resource(&resources, &busn_resource);
|
||||
b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
|
||||
if (b)
|
||||
b->subordinate = pci_scan_child_bus(b);
|
||||
pci_scan_child_bus(b);
|
||||
else
|
||||
pci_free_resource_list(&resources);
|
||||
return b;
|
||||
@ -1725,9 +1860,10 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
|
||||
|
||||
pci_add_resource(&resources, &ioport_resource);
|
||||
pci_add_resource(&resources, &iomem_resource);
|
||||
pci_add_resource(&resources, &busn_resource);
|
||||
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
|
||||
if (b) {
|
||||
b->subordinate = pci_scan_child_bus(b);
|
||||
pci_scan_child_bus(b);
|
||||
pci_bus_add_devices(b);
|
||||
} else {
|
||||
pci_free_resource_list(&resources);
|
||||
|
@ -253,7 +253,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx)
|
||||
* workaround applied too
|
||||
* [Info kindly provided by ALi]
|
||||
*/
|
||||
static void __init quirk_alimagik(struct pci_dev *dev)
|
||||
static void __devinit quirk_alimagik(struct pci_dev *dev)
|
||||
{
|
||||
if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
|
||||
dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
|
||||
@ -789,7 +789,7 @@ static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic);
|
||||
|
||||
static void __init quirk_ioapic_rmw(struct pci_dev *dev)
|
||||
static void __devinit quirk_ioapic_rmw(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->devfn == 0 && dev->bus->number == 0)
|
||||
sis_apic_bug = 1;
|
||||
@ -801,7 +801,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw);
|
||||
* Some settings of MMRBC can lead to data corruption so block changes.
|
||||
* See AMD 8131 HyperTransport PCI-X Tunnel Revision Guide
|
||||
*/
|
||||
static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
|
||||
static void __devinit quirk_amd_8131_mmrbc(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->subordinate && dev->revision <= 0x12) {
|
||||
dev_info(&dev->dev, "AMD8131 rev %x detected; "
|
||||
@ -1039,7 +1039,7 @@ static void quirk_disable_pxb(struct pci_dev *pdev)
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
|
||||
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
|
||||
|
||||
static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev)
|
||||
static void quirk_amd_ide_mode(struct pci_dev *pdev)
|
||||
{
|
||||
/* set SBX00/Hudson-2 SATA in IDE mode to AHCI mode */
|
||||
u8 tmp;
|
||||
@ -1082,7 +1082,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB
|
||||
/*
|
||||
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
|
||||
*/
|
||||
static void __init quirk_ide_samemode(struct pci_dev *pdev)
|
||||
static void __devinit quirk_ide_samemode(struct pci_dev *pdev)
|
||||
{
|
||||
u8 prog;
|
||||
|
||||
@ -1121,7 +1121,7 @@ DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_VIA, PCI_ANY_ID,
|
||||
/* This was originally an Alpha specific thing, but it really fits here.
|
||||
* The i82375 PCI/EISA bridge appears as non-classified. Fix that.
|
||||
*/
|
||||
static void __init quirk_eisa_bridge(struct pci_dev *dev)
|
||||
static void __devinit quirk_eisa_bridge(struct pci_dev *dev)
|
||||
{
|
||||
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
|
||||
}
|
||||
@ -1155,7 +1155,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_e
|
||||
*/
|
||||
static int asus_hides_smbus;
|
||||
|
||||
static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
|
||||
static void __devinit asus_hides_smbus_hostbridge(struct pci_dev *dev)
|
||||
{
|
||||
if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK)) {
|
||||
if (dev->device == PCI_DEVICE_ID_INTEL_82845_HB)
|
||||
@ -1538,7 +1538,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_JMICRON, PCI_DEVICE_ID_JMICRON_JMB3
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_IO_APIC
|
||||
static void __init quirk_alder_ioapic(struct pci_dev *pdev)
|
||||
static void __devinit quirk_alder_ioapic(struct pci_dev *pdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1777,7 +1777,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, qui
|
||||
* but the PIO transfers won't work if BAR0 falls at the odd 8 bytes.
|
||||
* Re-allocate the region if needed...
|
||||
*/
|
||||
static void __init quirk_tc86c001_ide(struct pci_dev *dev)
|
||||
static void __devinit quirk_tc86c001_ide(struct pci_dev *dev)
|
||||
{
|
||||
struct resource *r = &dev->resource[0];
|
||||
|
||||
@ -1938,53 +1938,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1
|
||||
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
|
||||
{
|
||||
u16 en1k;
|
||||
u8 io_base_lo, io_limit_lo;
|
||||
unsigned long base, limit;
|
||||
struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
|
||||
|
||||
pci_read_config_word(dev, 0x40, &en1k);
|
||||
|
||||
if (en1k & 0x200) {
|
||||
dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
|
||||
|
||||
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
|
||||
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
|
||||
base = (io_base_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
|
||||
limit = (io_limit_lo & (PCI_IO_RANGE_MASK | 0x0c)) << 8;
|
||||
|
||||
if (base <= limit) {
|
||||
res->start = base;
|
||||
res->end = limit + 0x3ff;
|
||||
}
|
||||
dev->io_window_1k = 1;
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io);
|
||||
|
||||
/* Fix the IOBL_ADR for 1k I/O space granularity on the Intel P64H2
|
||||
* The IOBL_ADR gets re-written to 4k boundaries in pci_setup_bridge()
|
||||
* in drivers/pci/setup-bus.c
|
||||
*/
|
||||
static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev)
|
||||
{
|
||||
u16 en1k, iobl_adr, iobl_adr_1k;
|
||||
struct resource *res = dev->resource + PCI_BRIDGE_RESOURCES;
|
||||
|
||||
pci_read_config_word(dev, 0x40, &en1k);
|
||||
|
||||
if (en1k & 0x200) {
|
||||
pci_read_config_word(dev, PCI_IO_BASE, &iobl_adr);
|
||||
|
||||
iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
|
||||
|
||||
if (iobl_adr != iobl_adr_1k) {
|
||||
dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
|
||||
iobl_adr,iobl_adr_1k);
|
||||
pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
|
||||
}
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1460, quirk_p64h2_1k_io_fix_iobl);
|
||||
|
||||
/* Under some circumstances, AER is not linked with extended capabilities.
|
||||
* Force it to be linked by setting the corresponding control bit in the
|
||||
* config space.
|
||||
@ -2104,7 +2067,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
|
||||
PCI_DEVICE_ID_NX2_5709S,
|
||||
quirk_brcm_570x_limit_vpd);
|
||||
|
||||
static void __devinit quirk_brcm_5719_limit_mrrs(struct pci_dev *dev)
|
||||
static void quirk_brcm_5719_limit_mrrs(struct pci_dev *dev)
|
||||
{
|
||||
u32 rev;
|
||||
|
||||
@ -2169,7 +2132,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
|
||||
* aware of it. Instead of setting the flag on all busses in the
|
||||
* machine, simply disable MSI globally.
|
||||
*/
|
||||
static void __init quirk_disable_all_msi(struct pci_dev *dev)
|
||||
static void __devinit quirk_disable_all_msi(struct pci_dev *dev)
|
||||
{
|
||||
pci_no_msi();
|
||||
dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
|
||||
@ -2217,7 +2180,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
|
||||
|
||||
/* Go through the list of Hypertransport capabilities and
|
||||
* return 1 if a HT MSI capability is found and enabled */
|
||||
static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
|
||||
static int msi_ht_cap_enabled(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ttl = 48;
|
||||
|
||||
@ -2241,7 +2204,7 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
/* Check the hypertransport MSI mapping to know whether MSI is enabled or not */
|
||||
static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
|
||||
static void quirk_msi_ht_cap(struct pci_dev *dev)
|
||||
{
|
||||
if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
|
||||
dev_warn(&dev->dev, "MSI quirk detected; "
|
||||
@ -2255,7 +2218,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2
|
||||
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
|
||||
* MSI are supported if the MSI capability set in any of these mappings.
|
||||
*/
|
||||
static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
|
||||
static void quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
|
||||
@ -2279,7 +2242,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
|
||||
quirk_nvidia_ck804_msi_ht_cap);
|
||||
|
||||
/* Force enable MSI mapping capability on HT bridges */
|
||||
static void __devinit ht_enable_msi_mapping(struct pci_dev *dev)
|
||||
static void ht_enable_msi_mapping(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ttl = 48;
|
||||
|
||||
@ -2359,7 +2322,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,
|
||||
PCI_DEVICE_ID_NVIDIA_MCP55_BRIDGE_V4,
|
||||
nvbridge_check_legacy_irq_routing);
|
||||
|
||||
static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
|
||||
static int ht_check_msi_mapping(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ttl = 48;
|
||||
int found = 0;
|
||||
@ -2387,7 +2350,7 @@ static int __devinit ht_check_msi_mapping(struct pci_dev *dev)
|
||||
return found;
|
||||
}
|
||||
|
||||
static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
|
||||
static int host_bridge_with_leaf(struct pci_dev *host_bridge)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
int pos;
|
||||
@ -2421,7 +2384,7 @@ static int __devinit host_bridge_with_leaf(struct pci_dev *host_bridge)
|
||||
#define PCI_HT_CAP_SLAVE_CTRL0 4 /* link control */
|
||||
#define PCI_HT_CAP_SLAVE_CTRL1 8 /* link control to */
|
||||
|
||||
static int __devinit is_end_of_ht_chain(struct pci_dev *dev)
|
||||
static int is_end_of_ht_chain(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ctrl_off;
|
||||
int end = 0;
|
||||
@ -2445,7 +2408,7 @@ out:
|
||||
return end;
|
||||
}
|
||||
|
||||
static void __devinit nv_ht_enable_msi_mapping(struct pci_dev *dev)
|
||||
static void nv_ht_enable_msi_mapping(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_dev *host_bridge;
|
||||
int pos;
|
||||
@ -2484,7 +2447,7 @@ out:
|
||||
pci_dev_put(host_bridge);
|
||||
}
|
||||
|
||||
static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
|
||||
static void ht_disable_msi_mapping(struct pci_dev *dev)
|
||||
{
|
||||
int pos, ttl = 48;
|
||||
|
||||
@ -2504,7 +2467,7 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
|
||||
static void __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
|
||||
{
|
||||
struct pci_dev *host_bridge;
|
||||
int pos;
|
||||
@ -2541,23 +2504,26 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
|
||||
else
|
||||
nv_ht_enable_msi_mapping(dev);
|
||||
}
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* HT MSI is not enabled */
|
||||
if (found == 1)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
/* Host bridge is not to HT, disable HT MSI mapping on this device */
|
||||
ht_disable_msi_mapping(dev);
|
||||
|
||||
out:
|
||||
pci_dev_put(host_bridge);
|
||||
}
|
||||
|
||||
static void __devinit nv_msi_ht_cap_quirk_all(struct pci_dev *dev)
|
||||
static void nv_msi_ht_cap_quirk_all(struct pci_dev *dev)
|
||||
{
|
||||
return __nv_msi_ht_cap_quirk(dev, 1);
|
||||
}
|
||||
|
||||
static void __devinit nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
|
||||
static void nv_msi_ht_cap_quirk_leaf(struct pci_dev *dev)
|
||||
{
|
||||
return __nv_msi_ht_cap_quirk(dev, 0);
|
||||
}
|
||||
@ -2879,20 +2845,34 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
|
||||
|
||||
|
||||
static void do_one_fixup_debug(void (*fn)(struct pci_dev *dev), struct pci_dev *dev)
|
||||
static ktime_t fixup_debug_start(struct pci_dev *dev,
|
||||
void (*fn)(struct pci_dev *dev))
|
||||
{
|
||||
ktime_t calltime, delta, rettime;
|
||||
ktime_t calltime = ktime_set(0, 0);
|
||||
|
||||
dev_dbg(&dev->dev, "calling %pF\n", fn);
|
||||
if (initcall_debug) {
|
||||
pr_debug("calling %pF @ %i for %s\n",
|
||||
fn, task_pid_nr(current), dev_name(&dev->dev));
|
||||
calltime = ktime_get();
|
||||
}
|
||||
|
||||
return calltime;
|
||||
}
|
||||
|
||||
static void fixup_debug_report(struct pci_dev *dev, ktime_t calltime,
|
||||
void (*fn)(struct pci_dev *dev))
|
||||
{
|
||||
ktime_t delta, rettime;
|
||||
unsigned long long duration;
|
||||
|
||||
printk(KERN_DEBUG "calling %pF @ %i for %s\n",
|
||||
fn, task_pid_nr(current), dev_name(&dev->dev));
|
||||
calltime = ktime_get();
|
||||
fn(dev);
|
||||
rettime = ktime_get();
|
||||
delta = ktime_sub(rettime, calltime);
|
||||
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
|
||||
printk(KERN_DEBUG "pci fixup %pF returned after %lld usecs for %s\n",
|
||||
fn, duration, dev_name(&dev->dev));
|
||||
if (initcall_debug) {
|
||||
rettime = ktime_get();
|
||||
delta = ktime_sub(rettime, calltime);
|
||||
duration = (unsigned long long) ktime_to_ns(delta) >> 10;
|
||||
pr_debug("pci fixup %pF returned after %lld usecs for %s\n",
|
||||
fn, duration, dev_name(&dev->dev));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2929,9 +2909,25 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev)
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq);
|
||||
|
||||
/*
|
||||
* Some devices may pass our check in pci_intx_mask_supported if
|
||||
* PCI_COMMAND_INTX_DISABLE works though they actually do not properly
|
||||
* support this feature.
|
||||
*/
|
||||
static void __devinit quirk_broken_intx_masking(struct pci_dev *dev)
|
||||
{
|
||||
dev->broken_intx_masking = 1;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CHELSIO, 0x0030,
|
||||
quirk_broken_intx_masking);
|
||||
DECLARE_PCI_FIXUP_HEADER(0x1814, 0x0601, /* Ralink RT2800 802.11n PCI */
|
||||
quirk_broken_intx_masking);
|
||||
|
||||
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
||||
struct pci_fixup *end)
|
||||
{
|
||||
ktime_t calltime;
|
||||
|
||||
for (; f < end; f++)
|
||||
if ((f->class == (u32) (dev->class >> f->class_shift) ||
|
||||
f->class == (u32) PCI_ANY_ID) &&
|
||||
@ -2939,11 +2935,9 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
|
||||
f->vendor == (u16) PCI_ANY_ID) &&
|
||||
(f->device == dev->device ||
|
||||
f->device == (u16) PCI_ANY_ID)) {
|
||||
dev_dbg(&dev->dev, "calling %pF\n", f->hook);
|
||||
if (initcall_debug)
|
||||
do_one_fixup_debug(f->hook, dev);
|
||||
else
|
||||
f->hook(dev);
|
||||
calltime = fixup_debug_start(dev, f->hook);
|
||||
f->hook(dev);
|
||||
fixup_debug_report(dev, calltime, f->hook);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2962,6 +2956,7 @@ extern struct pci_fixup __end_pci_fixups_resume_early[];
|
||||
extern struct pci_fixup __start_pci_fixups_suspend[];
|
||||
extern struct pci_fixup __end_pci_fixups_suspend[];
|
||||
|
||||
static bool pci_apply_fixup_final_quirks;
|
||||
|
||||
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
|
||||
{
|
||||
@ -2979,6 +2974,8 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
|
||||
break;
|
||||
|
||||
case pci_fixup_final:
|
||||
if (!pci_apply_fixup_final_quirks)
|
||||
return;
|
||||
start = __start_pci_fixups_final;
|
||||
end = __end_pci_fixups_final;
|
||||
break;
|
||||
@ -3011,6 +3008,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_fixup_device);
|
||||
|
||||
|
||||
static int __init pci_apply_final_quirks(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
@ -3021,6 +3019,7 @@ static int __init pci_apply_final_quirks(void)
|
||||
printk(KERN_DEBUG "PCI: CLS %u bytes\n",
|
||||
pci_cache_line_size << 2);
|
||||
|
||||
pci_apply_fixup_final_quirks = true;
|
||||
for_each_pci_dev(dev) {
|
||||
pci_fixup_device(pci_fixup_final, dev);
|
||||
/*
|
||||
@ -3041,6 +3040,7 @@ static int __init pci_apply_final_quirks(void)
|
||||
pci_cache_line_size = pci_dfl_cache_line_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pci_cache_line_size) {
|
||||
printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
|
||||
cls << 2, pci_dfl_cache_line_size << 2);
|
||||
@ -3179,3 +3179,87 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe)
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)
|
||||
{
|
||||
if (!PCI_FUNC(dev->devfn))
|
||||
return pci_dev_get(dev);
|
||||
|
||||
return pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
|
||||
}
|
||||
|
||||
static const struct pci_dev_dma_source {
|
||||
u16 vendor;
|
||||
u16 device;
|
||||
struct pci_dev *(*dma_source)(struct pci_dev *dev);
|
||||
} pci_dev_dma_source[] = {
|
||||
/*
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=605888
|
||||
*
|
||||
* Some Ricoh devices use the function 0 source ID for DMA on
|
||||
* other functions of a multifunction device. The DMA devices
|
||||
* is therefore function 0, which will have implications of the
|
||||
* iommu grouping of these devices.
|
||||
*/
|
||||
{ PCI_VENDOR_ID_RICOH, 0xe822, pci_func_0_dma_source },
|
||||
{ PCI_VENDOR_ID_RICOH, 0xe230, pci_func_0_dma_source },
|
||||
{ PCI_VENDOR_ID_RICOH, 0xe832, pci_func_0_dma_source },
|
||||
{ PCI_VENDOR_ID_RICOH, 0xe476, pci_func_0_dma_source },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* IOMMUs with isolation capabilities need to be programmed with the
|
||||
* correct source ID of a device. In most cases, the source ID matches
|
||||
* the device doing the DMA, but sometimes hardware is broken and will
|
||||
* tag the DMA as being sourced from a different device. This function
|
||||
* allows that translation. Note that the reference count of the
|
||||
* returned device is incremented on all paths.
|
||||
*/
|
||||
struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
|
||||
{
|
||||
const struct pci_dev_dma_source *i;
|
||||
|
||||
for (i = pci_dev_dma_source; i->dma_source; i++) {
|
||||
if ((i->vendor == dev->vendor ||
|
||||
i->vendor == (u16)PCI_ANY_ID) &&
|
||||
(i->device == dev->device ||
|
||||
i->device == (u16)PCI_ANY_ID))
|
||||
return i->dma_source(dev);
|
||||
}
|
||||
|
||||
return pci_dev_get(dev);
|
||||
}
|
||||
|
||||
static const struct pci_dev_acs_enabled {
|
||||
u16 vendor;
|
||||
u16 device;
|
||||
int (*acs_enabled)(struct pci_dev *dev, u16 acs_flags);
|
||||
} pci_dev_acs_enabled[] = {
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)
|
||||
{
|
||||
const struct pci_dev_acs_enabled *i;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Allow devices that do not expose standard PCIe ACS capabilities
|
||||
* or control to indicate their support here. Multi-function express
|
||||
* devices which do not allow internal peer-to-peer between functions,
|
||||
* but do not implement PCIe ACS may wish to return true here.
|
||||
*/
|
||||
for (i = pci_dev_acs_enabled; i->acs_enabled; i++) {
|
||||
if ((i->vendor == dev->vendor ||
|
||||
i->vendor == (u16)PCI_ANY_ID) &&
|
||||
(i->device == dev->device ||
|
||||
i->device == (u16)PCI_ANY_ID)) {
|
||||
ret = i->acs_enabled(dev, acs_flags);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
|
||||
|
||||
down_write(&pci_bus_sem);
|
||||
list_del(&pci_bus->node);
|
||||
pci_bus_release_busn_res(pci_bus);
|
||||
up_write(&pci_bus_sem);
|
||||
if (!pci_bus->is_added)
|
||||
return;
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "pci.h"
|
||||
|
||||
DECLARE_RWSEM(pci_bus_sem);
|
||||
EXPORT_SYMBOL_GPL(pci_bus_sem);
|
||||
|
||||
/*
|
||||
* find the upstream PCIe-to-PCI bridge of a PCI device
|
||||
* if the device is PCIE, return NULL
|
||||
|
@ -265,7 +265,7 @@ out:
|
||||
* assign_requested_resources_sorted() - satisfy resource requests
|
||||
*
|
||||
* @head : head of the list tracking requests for resources
|
||||
* @failed_list : head of the list tracking requests that could
|
||||
* @fail_head : head of the list tracking requests that could
|
||||
* not be allocated
|
||||
*
|
||||
* Satisfy resource requests of each element in the list. Add
|
||||
@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus)
|
||||
struct resource *res;
|
||||
struct pci_bus_region region;
|
||||
|
||||
dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
|
||||
bus->secondary, bus->subordinate);
|
||||
dev_info(&bridge->dev, "CardBus bridge to %pR\n",
|
||||
&bus->busn_res);
|
||||
|
||||
res = bus->resource[0];
|
||||
pcibios_resource_to_bus(bridge, ®ion, res);
|
||||
@ -469,16 +469,23 @@ static void pci_setup_bridge_io(struct pci_bus *bus)
|
||||
struct pci_dev *bridge = bus->self;
|
||||
struct resource *res;
|
||||
struct pci_bus_region region;
|
||||
unsigned long io_mask;
|
||||
u8 io_base_lo, io_limit_lo;
|
||||
u32 l, io_upper16;
|
||||
|
||||
io_mask = PCI_IO_RANGE_MASK;
|
||||
if (bridge->io_window_1k)
|
||||
io_mask = PCI_IO_1K_RANGE_MASK;
|
||||
|
||||
/* Set up the top and bottom of the PCI I/O segment for this bus. */
|
||||
res = bus->resource[0];
|
||||
pcibios_resource_to_bus(bridge, ®ion, res);
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
|
||||
l &= 0xffff0000;
|
||||
l |= (region.start >> 8) & 0x00f0;
|
||||
l |= region.end & 0xf000;
|
||||
io_base_lo = (region.start >> 8) & io_mask;
|
||||
io_limit_lo = (region.end >> 8) & io_mask;
|
||||
l |= ((u32) io_limit_lo << 8) | io_base_lo;
|
||||
/* Set up upper 16 bits of I/O base/limit. */
|
||||
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
|
||||
dev_info(&bridge->dev, " bridge window %pR\n", res);
|
||||
@ -553,8 +560,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
|
||||
{
|
||||
struct pci_dev *bridge = bus->self;
|
||||
|
||||
dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
|
||||
bus->secondary, bus->subordinate);
|
||||
dev_info(&bridge->dev, "PCI bridge to %pR\n",
|
||||
&bus->busn_res);
|
||||
|
||||
if (type & IORESOURCE_IO)
|
||||
pci_setup_bridge_io(bus);
|
||||
@ -699,7 +706,7 @@ static resource_size_t calculate_memsize(resource_size_t size,
|
||||
* @realloc_head : track the additional io window on this list
|
||||
*
|
||||
* Sizing the IO windows of the PCI-PCI bridge is trivial,
|
||||
* since these windows have 4K granularity and the IO ranges
|
||||
* since these windows have 1K or 4K granularity and the IO ranges
|
||||
* of non-bridge PCI devices are limited to 256 bytes.
|
||||
* We must be careful with the ISA aliasing though.
|
||||
*/
|
||||
@ -710,10 +717,17 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
|
||||
unsigned long size = 0, size0 = 0, size1 = 0;
|
||||
resource_size_t children_add_size = 0;
|
||||
resource_size_t min_align = 4096, align;
|
||||
|
||||
if (!b_res)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Per spec, I/O windows are 4K-aligned, but some bridges have an
|
||||
* extension to support 1K alignment.
|
||||
*/
|
||||
if (bus->self->io_window_1k)
|
||||
min_align = 1024;
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
int i;
|
||||
|
||||
@ -731,34 +745,43 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
|
||||
else
|
||||
size1 += r_size;
|
||||
|
||||
align = pci_resource_alignment(dev, r);
|
||||
if (align > min_align)
|
||||
min_align = align;
|
||||
|
||||
if (realloc_head)
|
||||
children_add_size += get_res_add_size(realloc_head, r);
|
||||
}
|
||||
}
|
||||
|
||||
if (min_align > 4096)
|
||||
min_align = 4096;
|
||||
|
||||
size0 = calculate_iosize(size, min_size, size1,
|
||||
resource_size(b_res), 4096);
|
||||
resource_size(b_res), min_align);
|
||||
if (children_add_size > add_size)
|
||||
add_size = children_add_size;
|
||||
size1 = (!realloc_head || (realloc_head && !add_size)) ? size0 :
|
||||
calculate_iosize(size, min_size, add_size + size1,
|
||||
resource_size(b_res), 4096);
|
||||
resource_size(b_res), min_align);
|
||||
if (!size0 && !size1) {
|
||||
if (b_res->start || b_res->end)
|
||||
dev_info(&bus->self->dev, "disabling bridge window "
|
||||
"%pR to [bus %02x-%02x] (unused)\n", b_res,
|
||||
bus->secondary, bus->subordinate);
|
||||
"%pR to %pR (unused)\n", b_res,
|
||||
&bus->busn_res);
|
||||
b_res->flags = 0;
|
||||
return;
|
||||
}
|
||||
/* Alignment of the IO window is always 4K */
|
||||
b_res->start = 4096;
|
||||
|
||||
b_res->start = min_align;
|
||||
b_res->end = b_res->start + size0 - 1;
|
||||
b_res->flags |= IORESOURCE_STARTALIGN;
|
||||
if (size1 > size0 && realloc_head) {
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0,
|
||||
min_align);
|
||||
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
|
||||
"%pR to [bus %02x-%02x] add_size %lx\n", b_res,
|
||||
bus->secondary, bus->subordinate, size1-size0);
|
||||
"%pR to %pR add_size %lx\n", b_res,
|
||||
&bus->busn_res, size1-size0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -863,8 +886,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
if (!size0 && !size1) {
|
||||
if (b_res->start || b_res->end)
|
||||
dev_info(&bus->self->dev, "disabling bridge window "
|
||||
"%pR to [bus %02x-%02x] (unused)\n", b_res,
|
||||
bus->secondary, bus->subordinate);
|
||||
"%pR to %pR (unused)\n", b_res,
|
||||
&bus->busn_res);
|
||||
b_res->flags = 0;
|
||||
return 1;
|
||||
}
|
||||
@ -874,8 +897,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
|
||||
if (size1 > size0 && realloc_head) {
|
||||
add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
|
||||
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
|
||||
"%pR to [bus %02x-%02x] add_size %llx\n", b_res,
|
||||
bus->secondary, bus->subordinate, (unsigned long long)size1-size0);
|
||||
"%pR to %pR add_size %llx\n", b_res,
|
||||
&bus->busn_res, (unsigned long long)size1-size0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -30,6 +30,8 @@
|
||||
void pci_update_resource(struct pci_dev *dev, int resno)
|
||||
{
|
||||
struct pci_bus_region region;
|
||||
bool disable;
|
||||
u16 cmd;
|
||||
u32 new, check, mask;
|
||||
int reg;
|
||||
enum pci_bar_type type;
|
||||
@ -67,6 +69,18 @@ void pci_update_resource(struct pci_dev *dev, int resno)
|
||||
new |= PCI_ROM_ADDRESS_ENABLE;
|
||||
}
|
||||
|
||||
/*
|
||||
* We can't update a 64-bit BAR atomically, so when possible,
|
||||
* disable decoding so that a half-updated BAR won't conflict
|
||||
* with another device.
|
||||
*/
|
||||
disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on;
|
||||
if (disable) {
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
pci_write_config_word(dev, PCI_COMMAND,
|
||||
cmd & ~PCI_COMMAND_MEMORY);
|
||||
}
|
||||
|
||||
pci_write_config_dword(dev, reg, new);
|
||||
pci_read_config_dword(dev, reg, &check);
|
||||
|
||||
@ -84,6 +98,10 @@ void pci_update_resource(struct pci_dev *dev, int resno)
|
||||
"(high %#08x != %#08x)\n", resno, new, check);
|
||||
}
|
||||
}
|
||||
|
||||
if (disable)
|
||||
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
||||
|
||||
res->flags &= ~IORESOURCE_UNSET;
|
||||
dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
|
||||
resno, res, (unsigned long long)region.start,
|
||||
@ -127,33 +145,6 @@ void pci_disable_bridge_window(struct pci_dev *dev)
|
||||
pci_write_config_dword(dev, PCI_PREF_BASE_UPPER32, 0xffffffff);
|
||||
}
|
||||
|
||||
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
||||
int resno, resource_size_t size, resource_size_t align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t min;
|
||||
int ret;
|
||||
|
||||
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
|
||||
|
||||
/* First, try exact prefetching match.. */
|
||||
ret = pci_bus_alloc_resource(bus, res, size, align, min,
|
||||
IORESOURCE_PREFETCH,
|
||||
pcibios_align_resource, dev);
|
||||
|
||||
if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
|
||||
/*
|
||||
* That failed.
|
||||
*
|
||||
* But a prefetching area can handle a non-prefetching
|
||||
* window (it will just not perform as well).
|
||||
*/
|
||||
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
|
||||
pcibios_align_resource, dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic function that returns a value indicating that the device's
|
||||
* original BIOS BAR address was not saved and so is not available for
|
||||
@ -206,7 +197,35 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align)
|
||||
static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
|
||||
int resno, resource_size_t size, resource_size_t align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t min;
|
||||
int ret;
|
||||
|
||||
min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM;
|
||||
|
||||
/* First, try exact prefetching match.. */
|
||||
ret = pci_bus_alloc_resource(bus, res, size, align, min,
|
||||
IORESOURCE_PREFETCH,
|
||||
pcibios_align_resource, dev);
|
||||
|
||||
if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) {
|
||||
/*
|
||||
* That failed.
|
||||
*
|
||||
* But a prefetching area can handle a non-prefetching
|
||||
* window (it will just not perform as well).
|
||||
*/
|
||||
ret = pci_bus_alloc_resource(bus, res, size, align, min, 0,
|
||||
pcibios_align_resource, dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _pci_assign_resource(struct pci_dev *dev, int resno,
|
||||
resource_size_t size, resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
struct pci_bus *bus;
|
||||
@ -238,31 +257,6 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resour
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
|
||||
resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t new_size;
|
||||
int ret;
|
||||
|
||||
if (!res->parent) {
|
||||
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
|
||||
"\n", resno, res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* already aligned with min_align */
|
||||
new_size = resource_size(res) + addsize;
|
||||
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
@ -298,6 +292,31 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,
|
||||
resource_size_t min_align)
|
||||
{
|
||||
struct resource *res = dev->resource + resno;
|
||||
resource_size_t new_size;
|
||||
int ret;
|
||||
|
||||
if (!res->parent) {
|
||||
dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR "
|
||||
"\n", resno, res);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* already aligned with min_align */
|
||||
new_size = resource_size(res) + addsize;
|
||||
ret = _pci_assign_resource(dev, resno, new_size, min_align);
|
||||
if (!ret) {
|
||||
res->flags &= ~IORESOURCE_STARTALIGN;
|
||||
dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);
|
||||
if (resno < PCI_BRIDGE_RESOURCES)
|
||||
pci_update_resource(dev, resno);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int pci_enable_resources(struct pci_dev *dev, int mask)
|
||||
{
|
||||
u16 cmd, old_cmd;
|
||||
|
@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
|
||||
s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
|
||||
pci_fixup_cardbus(bus);
|
||||
|
||||
max = bus->secondary;
|
||||
max = bus->busn_res.start;
|
||||
for (pass = 0; pass < 2; pass++)
|
||||
list_for_each_entry(dev, &bus->devices, bus_list)
|
||||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
|
@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket)
|
||||
config_writeb(socket, PCI_LATENCY_TIMER, 168);
|
||||
config_writel(socket, PCI_PRIMARY_BUS,
|
||||
(176 << 24) | /* sec. latency timer */
|
||||
(dev->subordinate->subordinate << 16) | /* subordinate bus */
|
||||
(dev->subordinate->secondary << 8) | /* secondary bus */
|
||||
((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */
|
||||
((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */
|
||||
dev->subordinate->primary); /* primary bus */
|
||||
|
||||
/*
|
||||
@ -1086,14 +1086,14 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
|
||||
struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
|
||||
|
||||
/* Check bus numbers are already set up correctly: */
|
||||
if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate)
|
||||
if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end)
|
||||
return; /* The subordinate number is ok, nothing to do */
|
||||
|
||||
if (!bridge_to_fix->parent)
|
||||
return; /* Root bridges are ok */
|
||||
|
||||
/* stay within the limits of the bus range of the parent: */
|
||||
upper_limit = bridge_to_fix->parent->subordinate;
|
||||
upper_limit = bridge_to_fix->parent->busn_res.end;
|
||||
|
||||
/* check the bus ranges of all silbling bridges to prevent overlap */
|
||||
list_for_each(tmp, &bridge_to_fix->parent->children) {
|
||||
@ -1104,36 +1104,36 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
|
||||
* current upper limit, set the new upper limit to
|
||||
* the bus number below the silbling's range:
|
||||
*/
|
||||
if (silbling->secondary > bridge_to_fix->subordinate
|
||||
&& silbling->secondary <= upper_limit)
|
||||
upper_limit = silbling->secondary - 1;
|
||||
if (silbling->busn_res.start > bridge_to_fix->busn_res.end
|
||||
&& silbling->busn_res.start <= upper_limit)
|
||||
upper_limit = silbling->busn_res.start - 1;
|
||||
}
|
||||
|
||||
/* Show that the wanted subordinate number is not possible: */
|
||||
if (cardbus_bridge->subordinate > upper_limit)
|
||||
if (cardbus_bridge->busn_res.end > upper_limit)
|
||||
dev_printk(KERN_WARNING, &cardbus_bridge->dev,
|
||||
"Upper limit for fixing this "
|
||||
"bridge's parent bridge: #%02x\n", upper_limit);
|
||||
|
||||
/* If we have room to increase the bridge's subordinate number, */
|
||||
if (bridge_to_fix->subordinate < upper_limit) {
|
||||
if (bridge_to_fix->busn_res.end < upper_limit) {
|
||||
|
||||
/* use the highest number of the hidden bus, within limits */
|
||||
unsigned char subordinate_to_assign =
|
||||
min(cardbus_bridge->subordinate, upper_limit);
|
||||
min_t(int, cardbus_bridge->busn_res.end, upper_limit);
|
||||
|
||||
dev_printk(KERN_INFO, &bridge_to_fix->dev,
|
||||
"Raising subordinate bus# of parent "
|
||||
"bus (#%02x) from #%02x to #%02x\n",
|
||||
bridge_to_fix->number,
|
||||
bridge_to_fix->subordinate, subordinate_to_assign);
|
||||
(int)bridge_to_fix->busn_res.end, subordinate_to_assign);
|
||||
|
||||
/* Save the new subordinate in the bus struct of the bridge */
|
||||
bridge_to_fix->subordinate = subordinate_to_assign;
|
||||
bridge_to_fix->busn_res.end = subordinate_to_assign;
|
||||
|
||||
/* and update the PCI config space with the new subordinate */
|
||||
pci_write_config_byte(bridge_to_fix->self,
|
||||
PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate);
|
||||
PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,8 +170,8 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
|
||||
}
|
||||
|
||||
if (acpi_bus_power_manageable(handle)) {
|
||||
int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
|
||||
|
||||
int power_state = acpi_pm_device_sleep_state(&dev->dev, NULL,
|
||||
ACPI_STATE_D3);
|
||||
if (power_state < 0)
|
||||
power_state = (state.event == PM_EVENT_ON) ?
|
||||
ACPI_STATE_D0 : ACPI_STATE_D3;
|
||||
|
@ -124,7 +124,7 @@ static inline u32 merge_value(u32 val, u32 new_val, u32 new_val_mask,
|
||||
return val;
|
||||
}
|
||||
|
||||
static int pcibios_err_to_errno(int err)
|
||||
static int xen_pcibios_err_to_errno(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case PCIBIOS_SUCCESSFUL:
|
||||
@ -202,7 +202,7 @@ out:
|
||||
pci_name(dev), size, offset, value);
|
||||
|
||||
*ret_val = value;
|
||||
return pcibios_err_to_errno(err);
|
||||
return xen_pcibios_err_to_errno(err);
|
||||
}
|
||||
|
||||
int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
|
||||
@ -290,7 +290,7 @@ int xen_pcibk_config_write(struct pci_dev *dev, int offset, int size, u32 value)
|
||||
}
|
||||
}
|
||||
|
||||
return pcibios_err_to_errno(err);
|
||||
return xen_pcibios_err_to_errno(err);
|
||||
}
|
||||
|
||||
void xen_pcibk_config_free_dyn_fields(struct pci_dev *dev)
|
||||
|
@ -62,6 +62,7 @@
|
||||
#define METHOD_NAME__AEI "_AEI"
|
||||
#define METHOD_NAME__PRW "_PRW"
|
||||
#define METHOD_NAME__SRS "_SRS"
|
||||
#define METHOD_NAME__CBA "_CBA"
|
||||
|
||||
/* Method names - these methods must appear at the namespace root */
|
||||
|
||||
|
@ -396,6 +396,7 @@ struct acpi_pci_root {
|
||||
|
||||
u32 osc_support_set; /* _OSC state of support bits */
|
||||
u32 osc_control_set; /* _OSC state of control bits */
|
||||
phys_addr_t mcfg_addr;
|
||||
};
|
||||
|
||||
/* helper */
|
||||
@ -409,13 +410,13 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
|
||||
int acpi_disable_wakeup_device_power(struct acpi_device *dev);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int acpi_pm_device_sleep_state(struct device *, int *);
|
||||
int acpi_pm_device_sleep_state(struct device *, int *, int);
|
||||
#else
|
||||
static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
|
||||
static inline int acpi_pm_device_sleep_state(struct device *d, int *p, int m)
|
||||
{
|
||||
if (p)
|
||||
*p = ACPI_STATE_D0;
|
||||
return ACPI_STATE_D3;
|
||||
return (m >= ACPI_STATE_D0 && m <= ACPI_STATE_D3) ? m : ACPI_STATE_D0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -17,6 +17,7 @@ extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev);
|
||||
extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
|
||||
struct pci_dev *pci_dev);
|
||||
extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev);
|
||||
extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
|
||||
|
||||
static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)
|
||||
{
|
||||
|
@ -132,9 +132,10 @@ static inline const char *pci_power_name(pci_power_t state)
|
||||
return pci_power_names[1 + (int) state];
|
||||
}
|
||||
|
||||
#define PCI_PM_D2_DELAY 200
|
||||
#define PCI_PM_D3_WAIT 10
|
||||
#define PCI_PM_BUS_WAIT 50
|
||||
#define PCI_PM_D2_DELAY 200
|
||||
#define PCI_PM_D3_WAIT 10
|
||||
#define PCI_PM_D3COLD_WAIT 100
|
||||
#define PCI_PM_BUS_WAIT 50
|
||||
|
||||
/** The pci_channel state describes connectivity between the CPU and
|
||||
* the pci device. If some PCI bus between here and the pci device
|
||||
@ -278,11 +279,18 @@ struct pci_dev {
|
||||
unsigned int pme_poll:1; /* Poll device's PME status bit */
|
||||
unsigned int d1_support:1; /* Low power state D1 is supported */
|
||||
unsigned int d2_support:1; /* Low power state D2 is supported */
|
||||
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
|
||||
unsigned int no_d1d2:1; /* D1 and D2 are forbidden */
|
||||
unsigned int no_d3cold:1; /* D3cold is forbidden */
|
||||
unsigned int d3cold_allowed:1; /* D3cold is allowed by user */
|
||||
unsigned int mmio_always_on:1; /* disallow turning off io/mem
|
||||
decoding during bar sizing */
|
||||
unsigned int wakeup_prepared:1;
|
||||
unsigned int runtime_d3cold:1; /* whether go through runtime
|
||||
D3cold, not set for devices
|
||||
powered on/off by the
|
||||
corresponding bridge */
|
||||
unsigned int d3_delay; /* D3->D0 transition time in ms */
|
||||
unsigned int d3cold_delay; /* D3cold->D0 transition time in ms */
|
||||
|
||||
#ifdef CONFIG_PCIEASPM
|
||||
struct pcie_link_state *link_state; /* ASPM link state. */
|
||||
@ -324,6 +332,8 @@ struct pci_dev {
|
||||
unsigned int is_hotplug_bridge:1;
|
||||
unsigned int __aer_firmware_first_valid:1;
|
||||
unsigned int __aer_firmware_first:1;
|
||||
unsigned int broken_intx_masking:1;
|
||||
unsigned int io_window_1k:1; /* Intel P2P bridge 1K I/O windows */
|
||||
pci_dev_flags_t dev_flags;
|
||||
atomic_t enable_cnt; /* pci_enable_device has been called */
|
||||
|
||||
@ -368,6 +378,8 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
|
||||
return (pdev->error_state != pci_channel_io_normal);
|
||||
}
|
||||
|
||||
extern struct resource busn_resource;
|
||||
|
||||
struct pci_host_bridge_window {
|
||||
struct list_head list;
|
||||
struct resource *res; /* host bridge aperture (CPU address) */
|
||||
@ -419,6 +431,7 @@ struct pci_bus {
|
||||
struct list_head slots; /* list of slots on this bus */
|
||||
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
|
||||
struct list_head resources; /* address space routed to this bus */
|
||||
struct resource busn_res; /* bus numbers routed to this bus */
|
||||
|
||||
struct pci_ops *ops; /* configuration access functions */
|
||||
void *sysdata; /* hook for sys-specific extension */
|
||||
@ -426,8 +439,6 @@ struct pci_bus {
|
||||
|
||||
unsigned char number; /* bus number */
|
||||
unsigned char primary; /* number of primary bridge */
|
||||
unsigned char secondary; /* number of secondary bridge */
|
||||
unsigned char subordinate; /* max number of subordinate buses */
|
||||
unsigned char max_bus_speed; /* enum pci_bus_speed */
|
||||
unsigned char cur_bus_speed; /* enum pci_bus_speed */
|
||||
|
||||
@ -474,6 +485,32 @@ static inline bool pci_dev_msi_enabled(struct pci_dev *pci_dev) { return false;
|
||||
#define PCIBIOS_SET_FAILED 0x88
|
||||
#define PCIBIOS_BUFFER_TOO_SMALL 0x89
|
||||
|
||||
/*
|
||||
* Translate above to generic errno for passing back through non-pci.
|
||||
*/
|
||||
static inline int pcibios_err_to_errno(int err)
|
||||
{
|
||||
if (err <= PCIBIOS_SUCCESSFUL)
|
||||
return err; /* Assume already errno */
|
||||
|
||||
switch (err) {
|
||||
case PCIBIOS_FUNC_NOT_SUPPORTED:
|
||||
return -ENOENT;
|
||||
case PCIBIOS_BAD_VENDOR_ID:
|
||||
return -EINVAL;
|
||||
case PCIBIOS_DEVICE_NOT_FOUND:
|
||||
return -ENODEV;
|
||||
case PCIBIOS_BAD_REGISTER_NUMBER:
|
||||
return -EFAULT;
|
||||
case PCIBIOS_SET_FAILED:
|
||||
return -EIO;
|
||||
case PCIBIOS_BUFFER_TOO_SMALL:
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Low-level architecture-dependent routines */
|
||||
|
||||
struct pci_ops {
|
||||
@ -642,6 +679,7 @@ extern int no_pci_devices(void);
|
||||
|
||||
void pcibios_fixup_bus(struct pci_bus *);
|
||||
int __must_check pcibios_enable_device(struct pci_dev *, int mask);
|
||||
/* Architecture specific versions may override this (weak) */
|
||||
char *pcibios_setup(char *str);
|
||||
|
||||
/* Used only when drivers/pci/setup.c is used */
|
||||
@ -668,6 +706,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
|
||||
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
|
||||
struct pci_ops *ops, void *sysdata,
|
||||
struct list_head *resources);
|
||||
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
|
||||
int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
|
||||
void pci_bus_release_busn_res(struct pci_bus *b);
|
||||
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
|
||||
struct pci_ops *ops, void *sysdata,
|
||||
struct list_head *resources);
|
||||
@ -714,8 +755,6 @@ enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev);
|
||||
int pci_find_capability(struct pci_dev *dev, int cap);
|
||||
int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
|
||||
int pci_find_ext_capability(struct pci_dev *dev, int cap);
|
||||
int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
|
||||
int cap);
|
||||
int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
|
||||
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
|
||||
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
|
||||
@ -777,6 +816,14 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where,
|
||||
return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
|
||||
}
|
||||
|
||||
/* user-space driven config access */
|
||||
int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
|
||||
int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
|
||||
int pci_user_read_config_dword(struct pci_dev *dev, int where, u32 *val);
|
||||
int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val);
|
||||
int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val);
|
||||
int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val);
|
||||
|
||||
int __must_check pci_enable_device(struct pci_dev *dev);
|
||||
int __must_check pci_enable_device_io(struct pci_dev *dev);
|
||||
int __must_check pci_enable_device_mem(struct pci_dev *dev);
|
||||
@ -875,7 +922,6 @@ enum pci_obff_signal_type {
|
||||
int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type);
|
||||
void pci_disable_obff(struct pci_dev *dev);
|
||||
|
||||
bool pci_ltr_supported(struct pci_dev *dev);
|
||||
int pci_enable_ltr(struct pci_dev *dev);
|
||||
void pci_disable_ltr(struct pci_dev *dev);
|
||||
int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns);
|
||||
@ -1332,6 +1378,9 @@ static inline struct pci_dev *pci_get_bus_and_slot(unsigned int bus,
|
||||
static inline int pci_domain_nr(struct pci_bus *bus)
|
||||
{ return 0; }
|
||||
|
||||
static inline struct pci_dev *pci_dev_get(struct pci_dev *dev)
|
||||
{ return NULL; }
|
||||
|
||||
#define dev_is_pci(d) (false)
|
||||
#define dev_is_pf(d) (false)
|
||||
#define dev_num_vf(d) (0)
|
||||
@ -1486,9 +1535,20 @@ enum pci_fixup_pass {
|
||||
|
||||
#ifdef CONFIG_PCI_QUIRKS
|
||||
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
|
||||
struct pci_dev *pci_get_dma_source(struct pci_dev *dev);
|
||||
int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags);
|
||||
#else
|
||||
static inline void pci_fixup_device(enum pci_fixup_pass pass,
|
||||
struct pci_dev *dev) {}
|
||||
static inline struct pci_dev *pci_get_dma_source(struct pci_dev *dev)
|
||||
{
|
||||
return pci_dev_get(dev);
|
||||
}
|
||||
static inline int pci_dev_specific_acs_enabled(struct pci_dev *dev,
|
||||
u16 acs_flags)
|
||||
{
|
||||
return -ENOTTY;
|
||||
}
|
||||
#endif
|
||||
|
||||
void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen);
|
||||
@ -1591,7 +1651,9 @@ static inline bool pci_is_pcie(struct pci_dev *dev)
|
||||
}
|
||||
|
||||
void pci_request_acs(void);
|
||||
|
||||
bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
|
||||
bool pci_acs_path_enabled(struct pci_dev *start,
|
||||
struct pci_dev *end, u16 acs_flags);
|
||||
|
||||
#define PCI_VPD_LRDT 0x80 /* Large Resource Data Type */
|
||||
#define PCI_VPD_LRDT_ID(x) (x | PCI_VPD_LRDT)
|
||||
|
@ -26,6 +26,7 @@
|
||||
* Under PCI, each device has 256 bytes of configuration address space,
|
||||
* of which the first 64 bytes are standardized as follows:
|
||||
*/
|
||||
#define PCI_STD_HEADER_SIZEOF 64
|
||||
#define PCI_VENDOR_ID 0x00 /* 16 bits */
|
||||
#define PCI_DEVICE_ID 0x02 /* 16 bits */
|
||||
#define PCI_COMMAND 0x04 /* 16 bits */
|
||||
@ -125,7 +126,8 @@
|
||||
#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
|
||||
#define PCI_IO_RANGE_TYPE_16 0x00
|
||||
#define PCI_IO_RANGE_TYPE_32 0x01
|
||||
#define PCI_IO_RANGE_MASK (~0x0fUL)
|
||||
#define PCI_IO_RANGE_MASK (~0x0fUL) /* Standard 4K I/O windows */
|
||||
#define PCI_IO_1K_RANGE_MASK (~0x03UL) /* Intel 1K I/O windows */
|
||||
#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
|
||||
#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
|
||||
#define PCI_MEMORY_LIMIT 0x22
|
||||
@ -209,9 +211,12 @@
|
||||
#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
|
||||
#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */
|
||||
#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */
|
||||
#define PCI_CAP_ID_SECDEV 0x0F /* Secure Device */
|
||||
#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
|
||||
#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
|
||||
#define PCI_CAP_ID_SATA 0x12 /* SATA Data/Index Conf. */
|
||||
#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */
|
||||
#define PCI_CAP_ID_MAX PCI_CAP_ID_AF
|
||||
#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
|
||||
#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
|
||||
#define PCI_CAP_SIZEOF 4
|
||||
@ -276,6 +281,7 @@
|
||||
#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */
|
||||
#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */
|
||||
#define PCI_VPD_DATA 4 /* 32-bits of data returned here */
|
||||
#define PCI_CAP_VPD_SIZEOF 8
|
||||
|
||||
/* Slot Identification */
|
||||
|
||||
@ -297,8 +303,10 @@
|
||||
#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
|
||||
#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
|
||||
#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */
|
||||
#define PCI_MSI_PENDING_32 16 /* Pending intrs for 32-bit devices */
|
||||
#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
|
||||
#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
|
||||
#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */
|
||||
|
||||
/* MSI-X registers */
|
||||
#define PCI_MSIX_FLAGS 2
|
||||
@ -308,6 +316,7 @@
|
||||
#define PCI_MSIX_TABLE 4
|
||||
#define PCI_MSIX_PBA 8
|
||||
#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
|
||||
#define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */
|
||||
|
||||
/* MSI-X entry's format */
|
||||
#define PCI_MSIX_ENTRY_SIZE 16
|
||||
@ -338,6 +347,7 @@
|
||||
#define PCI_AF_CTRL_FLR 0x01
|
||||
#define PCI_AF_STATUS 5
|
||||
#define PCI_AF_STATUS_TP 0x01
|
||||
#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */
|
||||
|
||||
/* PCI-X registers */
|
||||
|
||||
@ -374,6 +384,10 @@
|
||||
#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
|
||||
#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
|
||||
#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
|
||||
#define PCI_X_ECC_CSR 8 /* ECC control and status */
|
||||
#define PCI_CAP_PCIX_SIZEOF_V0 8 /* size of registers for Version 0 */
|
||||
#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */
|
||||
#define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */
|
||||
|
||||
/* PCI Bridge Subsystem ID registers */
|
||||
|
||||
@ -462,6 +476,7 @@
|
||||
#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
|
||||
#define PCI_EXP_LNKSTA_LBMS 0x4000 /* Link Bandwidth Management Status */
|
||||
#define PCI_EXP_LNKSTA_LABS 0x8000 /* Link Autonomous Bandwidth Status */
|
||||
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V1 20 /* v1 endpoints end here */
|
||||
#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
|
||||
#define PCI_EXP_SLTCAP_ABP 0x00000001 /* Attention Button Present */
|
||||
#define PCI_EXP_SLTCAP_PCP 0x00000002 /* Power Controller Present */
|
||||
@ -507,6 +522,12 @@
|
||||
#define PCI_EXP_RTSTA 32 /* Root Status */
|
||||
#define PCI_EXP_RTSTA_PME 0x10000 /* PME status */
|
||||
#define PCI_EXP_RTSTA_PENDING 0x20000 /* PME pending */
|
||||
/*
|
||||
* Note that the following PCI Express 'Capability Structure' registers
|
||||
* were introduced with 'Capability Version' 0x2 (v2). These registers
|
||||
* do not exist on devices with Capability Version 1. Use pci_pcie_cap2()
|
||||
* to use these fields safely.
|
||||
*/
|
||||
#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
|
||||
#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */
|
||||
#define PCI_EXP_DEVCAP2_LTR 0x800 /* Latency tolerance reporting */
|
||||
@ -521,6 +542,7 @@
|
||||
#define PCI_EXP_OBFF_MSGA_EN 0x2000 /* OBFF enable with Message type A */
|
||||
#define PCI_EXP_OBFF_MSGB_EN 0x4000 /* OBFF enable with Message type B */
|
||||
#define PCI_EXP_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
|
||||
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
|
||||
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
|
||||
#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
|
||||
|
||||
@ -529,23 +551,43 @@
|
||||
#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
|
||||
#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
|
||||
|
||||
#define PCI_EXT_CAP_ID_ERR 1
|
||||
#define PCI_EXT_CAP_ID_VC 2
|
||||
#define PCI_EXT_CAP_ID_DSN 3
|
||||
#define PCI_EXT_CAP_ID_PWR 4
|
||||
#define PCI_EXT_CAP_ID_VNDR 11
|
||||
#define PCI_EXT_CAP_ID_ACS 13
|
||||
#define PCI_EXT_CAP_ID_ARI 14
|
||||
#define PCI_EXT_CAP_ID_ATS 15
|
||||
#define PCI_EXT_CAP_ID_SRIOV 16
|
||||
#define PCI_EXT_CAP_ID_PRI 19
|
||||
#define PCI_EXT_CAP_ID_LTR 24
|
||||
#define PCI_EXT_CAP_ID_PASID 27
|
||||
#define PCI_EXT_CAP_ID_ERR 0x01 /* Advanced Error Reporting */
|
||||
#define PCI_EXT_CAP_ID_VC 0x02 /* Virtual Channel Capability */
|
||||
#define PCI_EXT_CAP_ID_DSN 0x03 /* Device Serial Number */
|
||||
#define PCI_EXT_CAP_ID_PWR 0x04 /* Power Budgeting */
|
||||
#define PCI_EXT_CAP_ID_RCLD 0x05 /* Root Complex Link Declaration */
|
||||
#define PCI_EXT_CAP_ID_RCILC 0x06 /* Root Complex Internal Link Control */
|
||||
#define PCI_EXT_CAP_ID_RCEC 0x07 /* Root Complex Event Collector */
|
||||
#define PCI_EXT_CAP_ID_MFVC 0x08 /* Multi-Function VC Capability */
|
||||
#define PCI_EXT_CAP_ID_VC9 0x09 /* same as _VC */
|
||||
#define PCI_EXT_CAP_ID_RCRB 0x0A /* Root Complex RB? */
|
||||
#define PCI_EXT_CAP_ID_VNDR 0x0B /* Vendor Specific */
|
||||
#define PCI_EXT_CAP_ID_CAC 0x0C /* Config Access - obsolete */
|
||||
#define PCI_EXT_CAP_ID_ACS 0x0D /* Access Control Services */
|
||||
#define PCI_EXT_CAP_ID_ARI 0x0E /* Alternate Routing ID */
|
||||
#define PCI_EXT_CAP_ID_ATS 0x0F /* Address Translation Services */
|
||||
#define PCI_EXT_CAP_ID_SRIOV 0x10 /* Single Root I/O Virtualization */
|
||||
#define PCI_EXT_CAP_ID_MRIOV 0x11 /* Multi Root I/O Virtualization */
|
||||
#define PCI_EXT_CAP_ID_MCAST 0x12 /* Multicast */
|
||||
#define PCI_EXT_CAP_ID_PRI 0x13 /* Page Request Interface */
|
||||
#define PCI_EXT_CAP_ID_AMD_XXX 0x14 /* reserved for AMD */
|
||||
#define PCI_EXT_CAP_ID_REBAR 0x15 /* resizable BAR */
|
||||
#define PCI_EXT_CAP_ID_DPA 0x16 /* dynamic power alloc */
|
||||
#define PCI_EXT_CAP_ID_TPH 0x17 /* TPH request */
|
||||
#define PCI_EXT_CAP_ID_LTR 0x18 /* latency tolerance reporting */
|
||||
#define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe */
|
||||
#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */
|
||||
#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */
|
||||
#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PASID
|
||||
|
||||
#define PCI_EXT_CAP_DSN_SIZEOF 12
|
||||
#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
|
||||
|
||||
/* Advanced Error Reporting */
|
||||
#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
|
||||
#define PCI_ERR_UNC_TRAIN 0x00000001 /* Training */
|
||||
#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */
|
||||
#define PCI_ERR_UNC_SURPDN 0x00000020 /* Surprise Down */
|
||||
#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */
|
||||
#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */
|
||||
#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */
|
||||
@ -555,6 +597,11 @@
|
||||
#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */
|
||||
#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */
|
||||
#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */
|
||||
#define PCI_ERR_UNC_ACSV 0x00200000 /* ACS Violation */
|
||||
#define PCI_ERR_UNC_INTN 0x00400000 /* internal error */
|
||||
#define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC blocked TLP */
|
||||
#define PCI_ERR_UNC_ATOMEG 0x01000000 /* Atomic egress blocked */
|
||||
#define PCI_ERR_UNC_TLPPRE 0x02000000 /* TLP prefix blocked */
|
||||
#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */
|
||||
/* Same bits as above */
|
||||
#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */
|
||||
@ -565,6 +612,9 @@
|
||||
#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */
|
||||
#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */
|
||||
#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */
|
||||
#define PCI_ERR_COR_ADV_NFAT 0x00002000 /* Advisory Non-Fatal */
|
||||
#define PCI_ERR_COR_INTERNAL 0x00004000 /* Corrected Internal */
|
||||
#define PCI_ERR_COR_LOG_OVER 0x00008000 /* Header Log Overflow */
|
||||
#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */
|
||||
/* Same bits as above */
|
||||
#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */
|
||||
@ -596,12 +646,18 @@
|
||||
|
||||
/* Virtual Channel */
|
||||
#define PCI_VC_PORT_REG1 4
|
||||
#define PCI_VC_REG1_EVCC 0x7 /* extended vc count */
|
||||
#define PCI_VC_PORT_REG2 8
|
||||
#define PCI_VC_REG2_32_PHASE 0x2
|
||||
#define PCI_VC_REG2_64_PHASE 0x4
|
||||
#define PCI_VC_REG2_128_PHASE 0x8
|
||||
#define PCI_VC_PORT_CTRL 12
|
||||
#define PCI_VC_PORT_STATUS 14
|
||||
#define PCI_VC_RES_CAP 16
|
||||
#define PCI_VC_RES_CTRL 20
|
||||
#define PCI_VC_RES_STATUS 26
|
||||
#define PCI_CAP_VC_BASE_SIZEOF 0x10
|
||||
#define PCI_CAP_VC_PER_VC_SIZEOF 0x0C
|
||||
|
||||
/* Power Budgeting */
|
||||
#define PCI_PWR_DSR 4 /* Data Select Register */
|
||||
@ -614,6 +670,7 @@
|
||||
#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */
|
||||
#define PCI_PWR_CAP 12 /* Capability */
|
||||
#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
|
||||
#define PCI_EXT_CAP_PWR_SIZEOF 16
|
||||
|
||||
/*
|
||||
* Hypertransport sub capability types
|
||||
@ -646,6 +703,8 @@
|
||||
#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
|
||||
#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 hypertransport configuration */
|
||||
#define HT_CAPTYPE_PM 0xE0 /* Hypertransport powermanagement configuration */
|
||||
#define HT_CAP_SIZEOF_LONG 28 /* slave & primary */
|
||||
#define HT_CAP_SIZEOF_SHORT 24 /* host & secondary */
|
||||
|
||||
/* Alternative Routing-ID Interpretation */
|
||||
#define PCI_ARI_CAP 0x04 /* ARI Capability Register */
|
||||
@ -656,6 +715,7 @@
|
||||
#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */
|
||||
#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */
|
||||
#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */
|
||||
#define PCI_EXT_CAP_ARI_SIZEOF 8
|
||||
|
||||
/* Address Translation Service */
|
||||
#define PCI_ATS_CAP 0x04 /* ATS Capability Register */
|
||||
@ -665,6 +725,7 @@
|
||||
#define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */
|
||||
#define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */
|
||||
#define PCI_ATS_MIN_STU 12 /* shift of minimum STU block */
|
||||
#define PCI_EXT_CAP_ATS_SIZEOF 8
|
||||
|
||||
/* Page Request Interface */
|
||||
#define PCI_PRI_CTRL 0x04 /* PRI control register */
|
||||
@ -676,6 +737,7 @@
|
||||
#define PCI_PRI_STATUS_STOPPED 0x100 /* PRI Stopped */
|
||||
#define PCI_PRI_MAX_REQ 0x08 /* PRI max reqs supported */
|
||||
#define PCI_PRI_ALLOC_REQ 0x0c /* PRI max reqs allowed */
|
||||
#define PCI_EXT_CAP_PRI_SIZEOF 16
|
||||
|
||||
/* PASID capability */
|
||||
#define PCI_PASID_CAP 0x04 /* PASID feature register */
|
||||
@ -685,6 +747,7 @@
|
||||
#define PCI_PASID_CTRL_ENABLE 0x01 /* Enable bit */
|
||||
#define PCI_PASID_CTRL_EXEC 0x02 /* Exec permissions Enable */
|
||||
#define PCI_PASID_CTRL_PRIV 0x04 /* Priviledge Mode Enable */
|
||||
#define PCI_EXT_CAP_PASID_SIZEOF 8
|
||||
|
||||
/* Single Root I/O Virtualization */
|
||||
#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */
|
||||
@ -716,12 +779,14 @@
|
||||
#define PCI_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */
|
||||
#define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */
|
||||
#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */
|
||||
#define PCI_EXT_CAP_SRIOV_SIZEOF 64
|
||||
|
||||
#define PCI_LTR_MAX_SNOOP_LAT 0x4
|
||||
#define PCI_LTR_MAX_NOSNOOP_LAT 0x6
|
||||
#define PCI_LTR_VALUE_MASK 0x000003ff
|
||||
#define PCI_LTR_SCALE_MASK 0x00001c00
|
||||
#define PCI_LTR_SCALE_SHIFT 10
|
||||
#define PCI_EXT_CAP_LTR_SIZEOF 8
|
||||
|
||||
/* Access Control Service */
|
||||
#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
|
||||
@ -732,7 +797,38 @@
|
||||
#define PCI_ACS_UF 0x10 /* Upstream Forwarding */
|
||||
#define PCI_ACS_EC 0x20 /* P2P Egress Control */
|
||||
#define PCI_ACS_DT 0x40 /* Direct Translated P2P */
|
||||
#define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */
|
||||
#define PCI_ACS_CTRL 0x06 /* ACS Control Register */
|
||||
#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */
|
||||
|
||||
#define PCI_VSEC_HDR 4 /* extended cap - vendor specific */
|
||||
#define PCI_VSEC_HDR_LEN_SHIFT 20 /* shift for length field */
|
||||
|
||||
/* sata capability */
|
||||
#define PCI_SATA_REGS 4 /* SATA REGs specifier */
|
||||
#define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */
|
||||
#define PCI_SATA_REGS_INLINE 0xF /* REGS in config space */
|
||||
#define PCI_SATA_SIZEOF_SHORT 8
|
||||
#define PCI_SATA_SIZEOF_LONG 16
|
||||
|
||||
/* resizable BARs */
|
||||
#define PCI_REBAR_CTRL 8 /* control register */
|
||||
#define PCI_REBAR_CTRL_NBAR_MASK (7 << 5) /* mask for # bars */
|
||||
#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # bars */
|
||||
|
||||
/* dynamic power allocation */
|
||||
#define PCI_DPA_CAP 4 /* capability register */
|
||||
#define PCI_DPA_CAP_SUBSTATE_MASK 0x1F /* # substates - 1 */
|
||||
#define PCI_DPA_BASE_SIZEOF 16 /* size with 0 substates */
|
||||
|
||||
/* TPH Requester */
|
||||
#define PCI_TPH_CAP 4 /* capability register */
|
||||
#define PCI_TPH_CAP_LOC_MASK 0x600 /* location mask */
|
||||
#define PCI_TPH_LOC_NONE 0x000 /* no location */
|
||||
#define PCI_TPH_LOC_CAP 0x200 /* in capability */
|
||||
#define PCI_TPH_LOC_MSIX 0x400 /* in MSI-X */
|
||||
#define PCI_TPH_CAP_ST_MASK 0x07FF0000 /* st table mask */
|
||||
#define PCI_TPH_CAP_ST_SHIFT 16 /* st table shift */
|
||||
#define PCI_TPH_BASE_SIZEOF 12 /* size with no st table */
|
||||
|
||||
#endif /* LINUX_PCI_REGS_H */
|
||||
|
@ -66,7 +66,7 @@ extern int sfi_acpi_table_parse(char *signature, char *oem_id,
|
||||
char *oem_table_id,
|
||||
int (*handler)(struct acpi_table_header *));
|
||||
|
||||
static inline int acpi_sfi_table_parse(char *signature,
|
||||
static inline int __init acpi_sfi_table_parse(char *signature,
|
||||
int (*handler)(struct acpi_table_header *))
|
||||
{
|
||||
if (!acpi_table_parse(signature, handler))
|
||||
@ -83,7 +83,7 @@ static inline int sfi_acpi_table_parse(char *signature, char *oem_id,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int acpi_sfi_table_parse(char *signature,
|
||||
static inline int __init acpi_sfi_table_parse(char *signature,
|
||||
int (*handler)(struct acpi_table_header *))
|
||||
{
|
||||
return acpi_table_parse(signature, handler);
|
||||
|
@ -722,14 +722,12 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
|
||||
|
||||
write_lock(&resource_lock);
|
||||
|
||||
if (!parent)
|
||||
goto skip;
|
||||
|
||||
if ((start < parent->start) || (end > parent->end))
|
||||
goto out;
|
||||
|
||||
for (tmp = res->child; tmp; tmp = tmp->sibling) {
|
||||
if ((tmp->start < start) || (tmp->end > end))
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (res->sibling && (res->sibling->start <= end))
|
||||
goto out;
|
||||
|
||||
@ -741,6 +739,11 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
|
||||
goto out;
|
||||
}
|
||||
|
||||
skip:
|
||||
for (tmp = res->child; tmp; tmp = tmp->sibling)
|
||||
if ((tmp->start < start) || (tmp->end > end))
|
||||
goto out;
|
||||
|
||||
res->start = start;
|
||||
res->end = end;
|
||||
result = 0;
|
||||
|
@ -865,6 +865,11 @@ static void check_section(const char *modname, struct elf_info *elf,
|
||||
#define ALL_EXIT_TEXT_SECTIONS \
|
||||
".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$"
|
||||
|
||||
#define ALL_PCI_INIT_SECTIONS \
|
||||
".pci_fixup_early$", ".pci_fixup_header$", ".pci_fixup_final$", \
|
||||
".pci_fixup_enable$", ".pci_fixup_resume$", \
|
||||
".pci_fixup_resume_early$", ".pci_fixup_suspend$"
|
||||
|
||||
#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \
|
||||
MEM_INIT_SECTIONS
|
||||
#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \
|
||||
@ -1027,6 +1032,12 @@ const struct sectioncheck sectioncheck[] = {
|
||||
.mismatch = ANY_EXIT_TO_ANY_INIT,
|
||||
.symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL },
|
||||
},
|
||||
{
|
||||
.fromsec = { ALL_PCI_INIT_SECTIONS, NULL },
|
||||
.tosec = { INIT_SECTIONS, NULL },
|
||||
.mismatch = ANY_INIT_TO_ANY_EXIT,
|
||||
.symbol_white_list = { NULL },
|
||||
},
|
||||
/* Do not export init/exit functions or data */
|
||||
{
|
||||
.fromsec = { "__ksymtab*", NULL },
|
||||
|
Loading…
Reference in New Issue
Block a user