diff options
99 files changed, 1795 insertions, 955 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 14bc7071f9d..28b4679d8c7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5195,7 +5195,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/ diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index 1a629636cc1..9816d5a4d17 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -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) { diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 25552508c3f..2b2f25e7fef 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -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 { diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c index bc0cfdad1cb..5b1ee82f63c 100644 --- a/arch/cris/arch-v32/drivers/pci/bios.c +++ b/arch/cris/arch-v32/drivers/pci/bios.c @@ -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; diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 6b0b82ff441..d04ed14bbf0 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -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; diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 524df4295c9..81acc7a57f3 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -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) diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c index ed22bfc5db1..bd61512a1be 100644 --- a/arch/microblaze/pci/pci-common.c +++ b/arch/microblaze/pci/pci-common.c @@ -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 @@ -1506,10 +1501,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) diff --git a/arch/mips/mti-malta/malta-pci.c b/arch/mips/mti-malta/malta-pci.c index bf80921f2f5..b6634025d67 100644 --- a/arch/mips/mti-malta/malta-pci.c +++ b/arch/mips/mti-malta/malta-pci.c @@ -253,7 +253,7 @@ void __init mips_pcibios_init(void)  }  /* Enable PCI 2.1 compatibility in PIIX4 */ -static void __init quirk_dlcsetup(struct pci_dev *dev) +static void __devinit quirk_dlcsetup(struct pci_dev *dev)  {  	u8 odlc, ndlc;  	(void) pci_read_config_byte(dev, 0x82, &odlc); diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c index a1e7e6d80c8..bc13e29d2bb 100644 --- a/arch/mips/pci/ops-tx4927.c +++ b/arch/mips/pci/ops-tx4927.c @@ -495,7 +495,7 @@ irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id)  }  #ifdef CONFIG_TOSHIBA_FPCIB0 -static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev) +static void __devinit tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)  {  	struct tx4927_pcic_reg __iomem *pcicptr = pci_bus_to_pcicptr(dev->bus); diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 271e8c4a54c..690356808f8 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -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); diff --git a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c index 63be40e470d..14dc9c8fff0 100644 --- a/arch/mips/pmc-sierra/yosemite/ht.c +++ b/arch/mips/pmc-sierra/yosemite/ht.c @@ -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 */ diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c index 682efb0c108..125db323ab1 100644 --- a/arch/mips/txx9/generic/pci.c +++ b/arch/mips/txx9/generic/pci.c @@ -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; @@ -269,7 +269,7 @@ txx9_i8259_irq_setup(int irq)  	return err;  } -static void __init quirk_slc90e66_bridge(struct pci_dev *dev) +static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev)  {  	int irq;	/* PCI/ISA Bridge interrupt */  	u8 reg_64; @@ -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; diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c index 24644aca10c..60309051875 100644 --- a/arch/parisc/kernel/pci.c +++ b/arch/parisc/kernel/pci.c @@ -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.   * diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ac39e6a3b25..8cccbee6151 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -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 diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 8e78e93c818..cf40f2c2c08 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -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 @@ -1637,6 +1632,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); @@ -1646,7 +1646,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)  		pci_free_resource_list(&resources);  		return;  	} -	bus->secondary = hose->first_busno;  	hose->bus = bus;  	/* Get probe mode and perform scan */ @@ -1654,13 +1653,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 diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 94a54f61d34..4ff190ff24a 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -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;  	} diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 89dde171a6f..ae5ea5e04d6 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -240,7 +240,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 */ diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index 4d786c25d3e..3e70a2035e5 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c @@ -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; diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 1fca663f1b2..563aafa8629 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -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; diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 14e0e576bcb..cc6a91ae088 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -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; diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index 1638f43599f..aead6b337f4 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -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; diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index fbdd74dac3a..9cda6a1ad0c 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -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 ? */ diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 8b7bafa489c..3ccebc83dc0 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -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 || diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 6073288fed2..edbf79465d5 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -36,7 +36,7 @@  static int fsl_pcie_bus_fixup, is_mpc83xx_pci; -static void __init quirk_fsl_pcie_header(struct pci_dev *dev) +static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev)  {  	u8 progif; diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c index b0037cefaad..364b14d4754 100644 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ b/arch/powerpc/sysdev/mv64x60_pci.c @@ -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 diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c index edeea8960c3..a5fe1b54c95 100644 --- a/arch/sh/drivers/pci/fixups-dreamcast.c +++ b/arch/sh/drivers/pci/fixups-dreamcast.c @@ -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; diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c index 0e18ee33255..36eb6fc3c18 100644 --- a/arch/sh/drivers/pci/fixups-sdk7786.c +++ b/arch/sh/drivers/pci/fixups-sdk7786.c @@ -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; diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 9d10a3cb879..40db2d0aef3 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -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, diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c index 19f56058742..21dcda75a52 100644 --- a/arch/sparc/kernel/leon_pci.c +++ b/arch/sparc/kernel/leon_pci.c @@ -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)  { diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index fdaf2181167..065b88c4f86 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -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 diff --git a/arch/sparc/kernel/pci_impl.h b/arch/sparc/kernel/pci_impl.h index 6beb60df31d..918a2031c8b 100644 --- a/arch/sparc/kernel/pci_impl.h +++ b/arch/sparc/kernel/pci_impl.h @@ -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; diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index ded3f6090c3..521fdf1b20e 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -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. diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c index b56d12bf590..0fdd99d0d8b 100644 --- a/arch/tile/kernel/pci.c +++ b/arch/tile/kernel/pci.c @@ -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] = @@ -401,16 +404,6 @@ void pcibios_set_master(struct pci_dev *dev)  }  /* - * 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.   */  void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c index 2fc2b1ba825..46cb6c9de6c 100644 --- a/arch/unicore32/kernel/pci.c +++ b/arch/unicore32/kernel/pci.c @@ -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; diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index b3a53174602..b2652e95b3d 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -100,6 +100,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; @@ -135,6 +136,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; diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 03920a15a63..1b27de56356 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c @@ -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; diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index fc09c2754e0..505acdd6d60 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -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); diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 5aed49bff05..e9e6ed5cdf9 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -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); diff --git a/arch/x86/pci/bus_numa.c b/arch/x86/pci/bus_numa.c index 306579f7d0f..d37e2fec97e 100644 --- a/arch/x86/pci/bus_numa.c +++ b/arch/x86/pci/bus_numa.c @@ -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; diff --git a/arch/x86/pci/bus_numa.h b/arch/x86/pci/bus_numa.h index 226a466b2b2..ff8f65b0457 100644 --- a/arch/x86/pci/bus_numa.h +++ b/arch/x86/pci/bus_numa.h @@ -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;  }; diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 0ad990a20d4..720e973fc34 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -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; diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 301e325992f..937bcece700 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -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,69 +457,91 @@ 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 void __init pci_mmcfg_reject_broken(int early) +static int __ref pci_mmcfg_check_reserved(struct device *dev, +		  struct pci_mmcfg_region *cfg, int early)  { -	struct pci_mmcfg_region *cfg; - -	list_for_each_entry(cfg, &pci_mmcfg_list, list) { -		int valid = 0; +	if (!early && !acpi_disabled) { +		if (is_mmconf_reserved(is_acpi_reserved, cfg, dev, 0)) +			return 1; -		if (!early && !acpi_disabled) { -			valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0); +		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); +	} -			if (valid) -				continue; -			else -				printk(KERN_ERR FW_BUG 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) -			valid = is_mmconf_reserved(e820_all_mapped, cfg, 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); -		if (!valid) -			goto reject; -	} +	return 0; +} -	return; +static void __init pci_mmcfg_reject_broken(int early) +{ +	struct pci_mmcfg_region *cfg; -reject: -	printk(KERN_INFO PREFIX "not using MMCONFIG\n"); -	free_all_mmcfg(); +	list_for_each_entry(cfg, &pci_mmcfg_list, list) { +		if (pci_mmcfg_check_reserved(NULL, cfg, early) == 0) { +			pr_info(PREFIX "not using MMCONFIG\n"); +			free_all_mmcfg(); +			return; +		} +	}  } -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; +} diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index 5372e86834c..db63ac23e3d 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -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); +} diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index 915a493502c..d4ebd07c306 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -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;  	}  } diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c index 140942f66b3..e14a2ff708b 100644 --- a/arch/x86/pci/mrst.c +++ b/arch/x86/pci/mrst.c @@ -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); diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index eb30e356f5b..69759e9cb3e 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c @@ -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 */ diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7aff6312ce7..ec54014c321 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -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. diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 88561029cca..1cc02ca2af2 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -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 */ diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b12af2ff8c5..2fb7d1598a6 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -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;  		} diff --git a/drivers/misc/cb710/core.c b/drivers/misc/cb710/core.c index 85cc7710193..9d5eed75466 100644 --- a/drivers/misc/cb710/core.c +++ b/drivers/misc/cb710/core.c @@ -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;  } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index edeeb516807..09fa3c687a1 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14168,7 +14168,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); @@ -14196,7 +14196,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); diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index 432d4bbcc62..ffddc4f6426 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -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; diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1f9e9fefb8e..83380c8fcb6 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -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);  } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 052fa230bc7..4f9cf2456f4 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -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. */ diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 01c001f3b76..8d688b260e2 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -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 diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 2a581642c23..ba91a7e1751 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -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) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 4ce5ef2f282..4b0970b46e0 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -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; diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c index d3509cdeb55..6258dc260d9 100644 --- a/drivers/pci/hotplug-pci.c +++ b/drivers/pci/hotplug-pci.c @@ -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; - -	max = pci_scan_child_bus(bus); +	struct pci_bus *parent = dev->bus; +	int pass, busnr, start = parent->busn_res.start; +	int end = parent->busn_res.end; -	/* -	 * Make the discovered devices available. -	 */ -	pci_bus_add_devices(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; -	return max; +	return 0;  } -EXPORT_SYMBOL(pci_do_scan_bus); +EXPORT_SYMBOL_GPL(pci_hp_add_bridge); diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 7722108e78d..a1afb5b39ad 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -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 */ diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index aa41631e9e0..96316b74969 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -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();  } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 806c44fa645..ad6fd669549 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -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) { diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 3fadf2f135e..2b4c412f94c 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -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; diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index ae853ccd0cd..dcc75c78544 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -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; diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index 187a199da93..c8eaeb43fa5 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -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; diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 1c8494021a4..09801c6945c 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -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); diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index 4fda7e6a86a..7dccad5fc89 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -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; diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 47d9dc06b10..09cecaf450c 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -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);  	} diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index b20ceaaa31f..1f00b937f72 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -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; diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index de573113c10..f64ca92253d 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -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);  		} diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 7414fd9ad1d..b6de307248e 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -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; diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b00b09bdd38..f9b5a52e411 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -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__); diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index df7e4bfadae..c627ed9957d 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -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;  } diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index efa30da1ae8..eeb23ceae4a 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -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;  } diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 6554e1a0f63..74bbaf82638 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -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;  	} diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 61e2fefeeda..fbf7b26c7c8 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -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)) diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index bf0cee629b6..1dd1d9dfa17 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -459,16 +459,17 @@ static int pci_restore_standard_config(struct pci_dev *pci_dev)  	return 0;  } +#endif + +#ifdef CONFIG_PM_SLEEP +  static void pci_pm_default_resume_early(struct pci_dev *pci_dev)  { -	pci_restore_standard_config(pci_dev); +	pci_power_up(pci_dev); +	pci_restore_state(pci_dev);  	pci_fixup_device(pci_fixup_resume_early, pci_dev);  } -#endif - -#ifdef CONFIG_PM_SLEEP -  /*   * Default "suspend" method for devices that have no driver provided suspend,   * or not even a driver at all (second part). @@ -1019,10 +1020,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); @@ -1044,17 +1048,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) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 86c63fe45d1..6869009c739 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -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), @@ -402,6 +428,9 @@ struct device_attribute pci_dev_attrs[] = {  	__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;  } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 447e83472c0..f3ea977a5b1 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -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, @@ -278,6 +254,38 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)  }  /** + * 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   * @cap: capability code @@ -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 { @@ -662,6 +638,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.   * @state: State to put the device into. @@ -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;  } @@ -1498,6 +1542,28 @@ void pci_pme_wakeup_bus(struct pci_bus *bus)  }  /** + * 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.   * @state: PCI state from which device will issue PME#. @@ -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; @@ -2360,6 +2435,75 @@ void pci_enable_acs(struct pci_dev *dev)  }  /** + * 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   * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD) @@ -2666,6 +2810,18 @@ static void __pci_set_master(struct pci_dev *dev, bool 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;  } diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index e4943479b23..bacbcba69cf 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -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); diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 275bf158ffa..124f20ff11b 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -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 diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index e0610bda1de..3a7eefcb270 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -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) @@ -117,6 +165,14 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {  #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);  } diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 658ac977cb5..6c143b4497c 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -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); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 2a752167754..003f356a897 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -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 = 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 calltime, delta, rettime; +	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; +} diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index fd77e2bde2e..04a4861b474 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -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; diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 9d75dc8ca60..993d4a0a246 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -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 diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8fa2d4be88d..fdb11770af1 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -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;  } diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 3ce9fa317d1..81b88bda793 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -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, diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 6e75153c5b4..24caeaf5052 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -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 || diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index d07f9ac8c41..667678db115 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -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);  	}  } diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index d21e8f59c84..507a8e2b9a4 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -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; diff --git a/drivers/xen/xen-pciback/conf_space.c b/drivers/xen/xen-pciback/conf_space.c index 30d7be026c1..46ae0f9f02a 100644 --- a/drivers/xen/xen-pciback/conf_space.c +++ b/drivers/xen/xen-pciback/conf_space.c @@ -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) diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index 38f508816e4..b177f97f53b 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -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 */ diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 9e6e1c6eb60..6a6c46e84ae 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -401,6 +401,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 */ @@ -414,13 +415,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 diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 44623500f41..248fba2af98 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -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)  { diff --git a/include/linux/pci.h b/include/linux/pci.h index d8c379dba6a..5faa8310eec 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -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) diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index 4b608f54341..53274bff577 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -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 */ diff --git a/include/linux/sfi_acpi.h b/include/linux/sfi_acpi.h index c4a5a8cd446..631af63af42 100644 --- a/include/linux/sfi_acpi.h +++ b/include/linux/sfi_acpi.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); diff --git a/kernel/resource.c b/kernel/resource.c index e1d2b8ee76d..dc8b4776444 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -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; diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 0f84bb38eb0..68e9f5ed0a6 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -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 },  |