diff options
Diffstat (limited to 'drivers/pci')
100 files changed, 7905 insertions, 4062 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index b6a99f7a9b2..893503fa178 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -105,9 +105,10 @@ config PCI_PASID  	  If unsure, say N.  config PCI_IOAPIC -	tristate "PCI IO-APIC hotplug support" if X86 +	bool "PCI IO-APIC hotplug support" if X86  	depends on PCI  	depends on ACPI +	depends on X86_IO_APIC  	default !X86  config PCI_LABEL diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 6ebf5bf8e7a..e04fe2d9df3 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -4,7 +4,7 @@  obj-y		+= access.o bus.o probe.o host-bridge.o remove.o pci.o \  			pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ -			irq.o vpd.o setup-bus.o +			irq.o vpd.o setup-bus.o vc.o  obj-$(CONFIG_PROC_FS) += proc.o  obj-$(CONFIG_SYSFS) += slot.o @@ -33,21 +33,14 @@ obj-$(CONFIG_PCI_IOV) += iov.o  #  # Some architectures use the generic PCI setup functions  # -obj-$(CONFIG_X86) += setup-bus.o -obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o -obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o -obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o -obj-$(CONFIG_PARISC) += setup-bus.o -obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o -obj-$(CONFIG_PPC) += setup-bus.o -obj-$(CONFIG_FRV) += setup-bus.o -obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o -obj-$(CONFIG_X86_VISWS) += setup-irq.o -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 +obj-$(CONFIG_ALPHA) += setup-irq.o +obj-$(CONFIG_ARM) += setup-irq.o +obj-$(CONFIG_UNICORE32) += setup-irq.o +obj-$(CONFIG_SUPERH) += setup-irq.o +obj-$(CONFIG_MIPS) += setup-irq.o +obj-$(CONFIG_TILE) += setup-irq.o +obj-$(CONFIG_SPARC_LEON) += setup-irq.o +obj-$(CONFIG_M68K) += setup-irq.o  #  # ACPI Related PCI FW Functions diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 0857ca981fa..d292d7cb341 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -148,7 +148,7 @@ static noinline void pci_wait_cfg(struct pci_dev *dev)  int pci_user_read_config_##size						\  	(struct pci_dev *dev, int pos, type *val)			\  {									\ -	int ret = 0;							\ +	int ret = PCIBIOS_SUCCESSFUL;					\  	u32 data = -1;							\  	if (PCI_##size##_BAD)						\  		return -EINVAL;						\ @@ -159,9 +159,7 @@ int pci_user_read_config_##size						\  					pos, sizeof(type), &data);	\  	raw_spin_unlock_irq(&pci_lock);				\  	*val = (type)data;						\ -	if (ret > 0)							\ -		ret = -EINVAL;						\ -	return ret;							\ +	return pcibios_err_to_errno(ret);				\  }									\  EXPORT_SYMBOL_GPL(pci_user_read_config_##size); @@ -170,7 +168,7 @@ EXPORT_SYMBOL_GPL(pci_user_read_config_##size);  int pci_user_write_config_##size					\  	(struct pci_dev *dev, int pos, type val)			\  {									\ -	int ret = -EIO;							\ +	int ret = PCIBIOS_SUCCESSFUL;					\  	if (PCI_##size##_BAD)						\  		return -EINVAL;						\  	raw_spin_lock_irq(&pci_lock);				\ @@ -179,9 +177,7 @@ int pci_user_write_config_##size					\  	ret = dev->bus->ops->write(dev->bus, dev->devfn,		\  					pos, sizeof(type), val);	\  	raw_spin_unlock_irq(&pci_lock);				\ -	if (ret > 0)							\ -		ret = -EINVAL;						\ -	return ret;							\ +	return pcibios_err_to_errno(ret);				\  }									\  EXPORT_SYMBOL_GPL(pci_user_write_config_##size); @@ -235,10 +231,7 @@ static int pci_vpd_pci22_wait(struct pci_dev *dev)  		}  		if (time_after(jiffies, timeout)) { -			dev_printk(KERN_DEBUG, &dev->dev, -				   "vpd r/w failed.  This is likely a firmware " -				   "bug on this device.  Contact the card " -				   "vendor for a firmware update."); +			dev_printk(KERN_DEBUG, &dev->dev, "vpd r/w failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update\n");  			return -ETIMEDOUT;  		}  		if (fatal_signal_pending(current)) @@ -381,30 +374,6 @@ int pci_vpd_pci22_init(struct pci_dev *dev)  }  /** - * pci_vpd_truncate - Set available Vital Product Data size - * @dev:	pci device struct - * @size:	available memory in bytes - * - * Adjust size of available VPD area. - */ -int pci_vpd_truncate(struct pci_dev *dev, size_t size) -{ -	if (!dev->vpd) -		return -EINVAL; - -	/* limited by the access method */ -	if (size > dev->vpd->len) -		return -EINVAL; - -	dev->vpd->len = size; -	if (dev->vpd->attr) -		dev->vpd->attr->size = size; - -	return 0; -} -EXPORT_SYMBOL(pci_vpd_truncate); - -/**   * pci_cfg_access_lock - Lock PCI config reads/writes   * @dev:	pci device struct   * diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c index 95655d7c0d0..a8099d4d0c9 100644 --- a/drivers/pci/ats.c +++ b/drivers/pci/ats.c @@ -235,27 +235,6 @@ void pci_disable_pri(struct pci_dev *pdev)  EXPORT_SYMBOL_GPL(pci_disable_pri);  /** - * pci_pri_enabled - Checks if PRI capability is enabled - * @pdev: PCI device structure - * - * Returns true if PRI is enabled on the device, false otherwise - */ -bool pci_pri_enabled(struct pci_dev *pdev) -{ -	u16 control; -	int pos; - -	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); -	if (!pos) -		return false; - -	pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); - -	return (control & PCI_PRI_CTRL_ENABLE) ? true : false; -} -EXPORT_SYMBOL_GPL(pci_pri_enabled); - -/**   * pci_reset_pri - Resets device's PRI state   * @pdev: PCI device structure   * @@ -282,67 +261,6 @@ int pci_reset_pri(struct pci_dev *pdev)  	return 0;  }  EXPORT_SYMBOL_GPL(pci_reset_pri); - -/** - * pci_pri_stopped - Checks whether the PRI capability is stopped - * @pdev: PCI device structure - * - * Returns true if the PRI capability on the device is disabled and the - * device has no outstanding PRI requests, false otherwise. The device - * indicates this via the STOPPED bit in the status register of the - * capability. - * The device internal state can be cleared by resetting the PRI state - * with pci_reset_pri(). This can force the capability into the STOPPED - * state. - */ -bool pci_pri_stopped(struct pci_dev *pdev) -{ -	u16 control, status; -	int pos; - -	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); -	if (!pos) -		return true; - -	pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); -	pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); - -	if (control & PCI_PRI_CTRL_ENABLE) -		return false; - -	return (status & PCI_PRI_STATUS_STOPPED) ? true : false; -} -EXPORT_SYMBOL_GPL(pci_pri_stopped); - -/** - * pci_pri_status - Request PRI status of a device - * @pdev: PCI device structure - * - * Returns negative value on failure, status on success. The status can - * be checked against status-bits. Supported bits are currently: - * PCI_PRI_STATUS_RF:      Response failure - * PCI_PRI_STATUS_UPRGI:   Unexpected Page Request Group Index - * PCI_PRI_STATUS_STOPPED: PRI has stopped - */ -int pci_pri_status(struct pci_dev *pdev) -{ -	u16 status, control; -	int pos; - -	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); -	if (!pos) -		return -EINVAL; - -	pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); -	pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); - -	/* Stopped bit is undefined when enable == 1, so clear it */ -	if (control & PCI_PRI_CTRL_ENABLE) -		status &= ~PCI_PRI_STATUS_STOPPED; - -	return status; -} -EXPORT_SYMBOL_GPL(pci_pri_status);  #endif /* CONFIG_PCI_PRI */  #ifdef CONFIG_PCI_PASID @@ -410,7 +328,7 @@ EXPORT_SYMBOL_GPL(pci_disable_pasid);   * Otherwise is returns a bitmask with supported features. Current   * features reported are:   * PCI_PASID_CAP_EXEC - Execute permission supported - * PCI_PASID_CAP_PRIV - Priviledged mode supported + * PCI_PASID_CAP_PRIV - Privileged mode supported   */  int pci_pasid_features(struct pci_dev *pdev)  { diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index fc1b7401374..73aef51a28f 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -13,7 +13,6 @@  #include <linux/errno.h>  #include <linux/ioport.h>  #include <linux/proc_fs.h> -#include <linux/init.h>  #include <linux/slab.h>  #include "pci.h" @@ -98,40 +97,53 @@ void pci_bus_remove_resources(struct pci_bus *bus)  	}  } -/** - * pci_bus_alloc_resource - allocate a resource from a parent bus - * @bus: PCI bus - * @res: resource to allocate - * @size: size of resource to allocate - * @align: alignment of resource to allocate - * @min: minimum /proc/iomem address to allocate - * @type_mask: IORESOURCE_* type flags - * @alignf: resource alignment function - * @alignf_data: data argument for resource alignment function - * - * Given the PCI bus a device resides on, the size, minimum address, - * alignment and type, try to find an acceptable resource allocation - * for a specific device resource. +static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL}; +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT +static struct pci_bus_region pci_64_bit = {0, +				(dma_addr_t) 0xffffffffffffffffULL}; +static struct pci_bus_region pci_high = {(dma_addr_t) 0x100000000ULL, +				(dma_addr_t) 0xffffffffffffffffULL}; +#endif + +/* + * @res contains CPU addresses.  Clip it so the corresponding bus addresses + * on @bus are entirely within @region.  This is used to control the bus + * addresses of resources we allocate, e.g., we may need a resource that + * can be mapped by a 32-bit BAR.   */ -int -pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, +static void pci_clip_resource_to_region(struct pci_bus *bus, +					struct resource *res, +					struct pci_bus_region *region) +{ +	struct pci_bus_region r; + +	pcibios_resource_to_bus(bus, &r, res); +	if (r.start < region->start) +		r.start = region->start; +	if (r.end > region->end) +		r.end = region->end; + +	if (r.end < r.start) +		res->end = res->start - 1; +	else +		pcibios_bus_to_resource(bus, res, &r); +} + +static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,  		resource_size_t size, resource_size_t align, -		resource_size_t min, unsigned int type_mask, +		resource_size_t min, unsigned long type_mask,  		resource_size_t (*alignf)(void *,  					  const struct resource *,  					  resource_size_t,  					  resource_size_t), -		void *alignf_data) +		void *alignf_data, +		struct pci_bus_region *region)  { -	int i, ret = -ENOMEM; -	struct resource *r; -	resource_size_t max = -1; - -	type_mask |= IORESOURCE_IO | IORESOURCE_MEM; +	int i, ret; +	struct resource *r, avail; +	resource_size_t max; -	/* don't allocate too high if the pref mem doesn't support 64bit*/ -	if (!(res->flags & IORESOURCE_MEM_64)) -		max = PCIBIOS_MAX_MEM_32; +	type_mask |= IORESOURCE_TYPE_BITS;  	pci_bus_for_each_resource(bus, r, i) {  		if (!r) @@ -147,16 +159,74 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,  		    !(res->flags & IORESOURCE_PREFETCH))  			continue; +		avail = *r; +		pci_clip_resource_to_region(bus, &avail, region); + +		/* +		 * "min" is typically PCIBIOS_MIN_IO or PCIBIOS_MIN_MEM to +		 * protect badly documented motherboard resources, but if +		 * this is an already-configured bridge window, its start +		 * overrides "min". +		 */ +		if (avail.start) +			min = avail.start; + +		max = avail.end; +  		/* Ok, try it out.. */ -		ret = allocate_resource(r, res, size, -					r->start ? : min, -					max, align, -					alignf, alignf_data); +		ret = allocate_resource(r, res, size, min, max, +					align, alignf, alignf_data);  		if (ret == 0) -			break; +			return 0; +	} +	return -ENOMEM; +} + +/** + * pci_bus_alloc_resource - allocate a resource from a parent bus + * @bus: PCI bus + * @res: resource to allocate + * @size: size of resource to allocate + * @align: alignment of resource to allocate + * @min: minimum /proc/iomem address to allocate + * @type_mask: IORESOURCE_* type flags + * @alignf: resource alignment function + * @alignf_data: data argument for resource alignment function + * + * Given the PCI bus a device resides on, the size, minimum address, + * alignment and type, try to find an acceptable resource allocation + * for a specific device resource. + */ +int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, +		resource_size_t size, resource_size_t align, +		resource_size_t min, unsigned long type_mask, +		resource_size_t (*alignf)(void *, +					  const struct resource *, +					  resource_size_t, +					  resource_size_t), +		void *alignf_data) +{ +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT +	int rc; + +	if (res->flags & IORESOURCE_MEM_64) { +		rc = pci_bus_alloc_from_region(bus, res, size, align, min, +					       type_mask, alignf, alignf_data, +					       &pci_high); +		if (rc == 0) +			return 0; + +		return pci_bus_alloc_from_region(bus, res, size, align, min, +						 type_mask, alignf, alignf_data, +						 &pci_64_bit);  	} -	return ret; +#endif + +	return pci_bus_alloc_from_region(bus, res, size, align, min, +					 type_mask, alignf, alignf_data, +					 &pci_32_bit);  } +EXPORT_SYMBOL(pci_bus_alloc_resource);  void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { } @@ -166,7 +236,7 @@ void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }   *   * This adds add sysfs entries and start device drivers   */ -int pci_bus_add_device(struct pci_dev *dev) +void pci_bus_add_device(struct pci_dev *dev)  {  	int retval; @@ -176,15 +246,15 @@ int pci_bus_add_device(struct pci_dev *dev)  	 */  	pci_fixup_device(pci_fixup_final, dev);  	pci_create_sysfs_dev_files(dev); +	pci_proc_attach_device(dev);  	dev->match_driver = true;  	retval = device_attach(&dev->dev);  	WARN_ON(retval < 0);  	dev->is_added = 1; - -	return 0;  } +EXPORT_SYMBOL_GPL(pci_bus_add_device);  /**   * pci_bus_add_devices - start driver for PCI devices @@ -196,16 +266,12 @@ void pci_bus_add_devices(const struct pci_bus *bus)  {  	struct pci_dev *dev;  	struct pci_bus *child; -	int retval;  	list_for_each_entry(dev, &bus->devices, bus_list) {  		/* Skip already-added devices */  		if (dev->is_added)  			continue; -		retval = pci_bus_add_device(dev); -		if (retval) -			dev_err(&dev->dev, "Error adding device (%d)\n", -				retval); +		pci_bus_add_device(dev);  	}  	list_for_each_entry(dev, &bus->devices, bus_list) { @@ -215,6 +281,7 @@ void pci_bus_add_devices(const struct pci_bus *bus)  			pci_bus_add_devices(child);  	}  } +EXPORT_SYMBOL(pci_bus_add_devices);  /** pci_walk_bus - walk devices on/under bus, calling callback.   *  @top      bus whose devices should be walked @@ -280,6 +347,3 @@ void pci_bus_put(struct pci_bus *bus)  }  EXPORT_SYMBOL(pci_bus_put); -EXPORT_SYMBOL(pci_bus_alloc_resource); -EXPORT_SYMBOL_GPL(pci_bus_add_device); -EXPORT_SYMBOL(pci_bus_add_devices); diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c index a68dc613a5b..0e5f3c95af5 100644 --- a/drivers/pci/host-bridge.c +++ b/drivers/pci/host-bridge.c @@ -3,28 +3,24 @@   */  #include <linux/kernel.h> -#include <linux/init.h>  #include <linux/pci.h>  #include <linux/module.h>  #include "pci.h" -static struct pci_bus *find_pci_root_bus(struct pci_dev *dev) +static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)  { -	struct pci_bus *bus; - -	bus = dev->bus;  	while (bus->parent)  		bus = bus->parent;  	return bus;  } -static struct pci_host_bridge *find_pci_host_bridge(struct pci_dev *dev) +static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)  { -	struct pci_bus *bus = find_pci_root_bus(dev); +	struct pci_bus *root_bus = find_pci_root_bus(bus); -	return to_pci_host_bridge(bus->bridge); +	return to_pci_host_bridge(root_bus->bridge);  }  void pci_set_host_bridge_release(struct pci_host_bridge *bridge, @@ -35,22 +31,14 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge,  	bridge->release_data = release_data;  } -static bool resource_contains(struct resource *res1, struct resource *res2) -{ -	return res1->start <= res2->start && res1->end >= res2->end; -} - -void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, +void pcibios_resource_to_bus(struct pci_bus *bus, struct pci_bus_region *region,  			     struct resource *res)  { -	struct pci_host_bridge *bridge = find_pci_host_bridge(dev); +	struct pci_host_bridge *bridge = find_pci_host_bridge(bus);  	struct pci_host_bridge_window *window;  	resource_size_t offset = 0;  	list_for_each_entry(window, &bridge->windows, list) { -		if (resource_type(res) != resource_type(window->res)) -			continue; -  		if (resource_contains(window->res, res)) {  			offset = window->offset;  			break; @@ -68,10 +56,10 @@ static bool region_contains(struct pci_bus_region *region1,  	return region1->start <= region2->start && region1->end >= region2->end;  } -void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, +void pcibios_bus_to_resource(struct pci_bus *bus, struct resource *res,  			     struct pci_bus_region *region)  { -	struct pci_host_bridge *bridge = find_pci_host_bridge(dev); +	struct pci_host_bridge *bridge = find_pci_host_bridge(bus);  	struct pci_host_bridge_window *window;  	resource_size_t offset = 0; diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index 3d950481112..21df477be0c 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -3,7 +3,7 @@ menu "PCI host controller drivers"  config PCI_MVEBU  	bool "Marvell EBU PCIe controller" -	depends on ARCH_MVEBU || ARCH_KIRKWOOD +	depends on ARCH_MVEBU || ARCH_DOVE || ARCH_KIRKWOOD  	depends on OF  config PCIE_DW @@ -15,8 +15,35 @@ config PCI_EXYNOS  	select PCIEPORTBUS  	select PCIE_DW +config PCI_IMX6 +	bool "Freescale i.MX6 PCIe controller" +	depends on SOC_IMX6Q +	select PCIEPORTBUS +	select PCIE_DW +  config PCI_TEGRA  	bool "NVIDIA Tegra PCIe controller"  	depends on ARCH_TEGRA +config PCI_RCAR_GEN2 +	bool "Renesas R-Car Gen2 Internal PCI controller" +	depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST) +	help +	  Say Y here if you want internal PCI support on R-Car Gen2 SoC. +	  There are 3 internal PCI controllers available with a single +	  built-in EHCI/OHCI host controller present on each one. + +config PCI_RCAR_GEN2_PCIE +	bool "Renesas R-Car PCIe controller" +	depends on ARCH_SHMOBILE || (ARM && COMPILE_TEST) +	help +	  Say Y here if you want PCIe controller support on R-Car Gen2 SoCs. + +config PCI_HOST_GENERIC +	bool "Generic PCI host controller" +	depends on ARM && OF +	help +	  Say Y here if you want to support a simple generic PCI host +	  controller, such as the one emulated by kvmtool. +  endmenu diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index c9a997b2690..611ba4b48c9 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile @@ -1,4 +1,8 @@  obj-$(CONFIG_PCIE_DW) += pcie-designware.o  obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o +obj-$(CONFIG_PCI_IMX6) += pci-imx6.o  obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o  obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o +obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o +obj-$(CONFIG_PCI_RCAR_GEN2_PCIE) += pcie-rcar.o +obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c index 94e096bb2d0..c5d0ca38450 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/host/pci-exynos.c @@ -48,6 +48,7 @@ struct exynos_pcie {  #define PCIE_IRQ_SPECIAL		0x008  #define PCIE_IRQ_EN_PULSE		0x00c  #define PCIE_IRQ_EN_LEVEL		0x010 +#define IRQ_MSI_ENABLE			(0x1 << 2)  #define PCIE_IRQ_EN_SPECIAL		0x014  #define PCIE_PWR_RESET			0x018  #define PCIE_CORE_RESET			0x01c @@ -77,18 +78,28 @@ struct exynos_pcie {  #define PCIE_PHY_PLL_BIAS		0x00c  #define PCIE_PHY_DCC_FEEDBACK		0x014  #define PCIE_PHY_PLL_DIV_1		0x05c +#define PCIE_PHY_COMMON_POWER		0x064 +#define PCIE_PHY_COMMON_PD_CMN		(0x1 << 3)  #define PCIE_PHY_TRSV0_EMP_LVL		0x084  #define PCIE_PHY_TRSV0_DRV_LVL		0x088  #define PCIE_PHY_TRSV0_RXCDR		0x0ac +#define PCIE_PHY_TRSV0_POWER		0x0c4 +#define PCIE_PHY_TRSV0_PD_TSV		(0x1 << 7)  #define PCIE_PHY_TRSV0_LVCC		0x0dc  #define PCIE_PHY_TRSV1_EMP_LVL		0x144  #define PCIE_PHY_TRSV1_RXCDR		0x16c +#define PCIE_PHY_TRSV1_POWER		0x184 +#define PCIE_PHY_TRSV1_PD_TSV		(0x1 << 7)  #define PCIE_PHY_TRSV1_LVCC		0x19c  #define PCIE_PHY_TRSV2_EMP_LVL		0x204  #define PCIE_PHY_TRSV2_RXCDR		0x22c +#define PCIE_PHY_TRSV2_POWER		0x244 +#define PCIE_PHY_TRSV2_PD_TSV		(0x1 << 7)  #define PCIE_PHY_TRSV2_LVCC		0x25c  #define PCIE_PHY_TRSV3_EMP_LVL		0x2c4  #define PCIE_PHY_TRSV3_RXCDR		0x2ec +#define PCIE_PHY_TRSV3_POWER		0x304 +#define PCIE_PHY_TRSV3_PD_TSV		(0x1 << 7)  #define PCIE_PHY_TRSV3_LVCC		0x31c  static inline void exynos_elb_writel(struct exynos_pcie *pcie, u32 val, u32 reg) @@ -202,6 +213,58 @@ static void exynos_pcie_deassert_phy_reset(struct pcie_port *pp)  	exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);  } +static void exynos_pcie_power_on_phy(struct pcie_port *pp) +{ +	u32 val; +	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); +	val &= ~PCIE_PHY_COMMON_PD_CMN; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); +	val &= ~PCIE_PHY_TRSV0_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); +	val &= ~PCIE_PHY_TRSV1_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); +	val &= ~PCIE_PHY_TRSV2_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); +	val &= ~PCIE_PHY_TRSV3_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); +} + +static void exynos_pcie_power_off_phy(struct pcie_port *pp) +{ +	u32 val; +	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER); +	val |= PCIE_PHY_COMMON_PD_CMN; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER); +	val |= PCIE_PHY_TRSV0_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER); +	val |= PCIE_PHY_TRSV1_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER); +	val |= PCIE_PHY_TRSV2_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER); + +	val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER); +	val |= PCIE_PHY_TRSV3_PD_TSV; +	exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER); +} +  static void exynos_pcie_init_phy(struct pcie_port *pp)  {  	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); @@ -270,6 +333,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)  	/* de-assert phy reset */  	exynos_pcie_deassert_phy_reset(pp); +	/* power on phy */ +	exynos_pcie_power_on_phy(pp); +  	/* initialize phy */  	exynos_pcie_init_phy(pp); @@ -302,6 +368,9 @@ static int exynos_pcie_establish_link(struct pcie_port *pp)  						       PCIE_PHY_PLL_LOCKED);  				dev_info(pp->dev, "PLL Locked: 0x%x\n", val);  			} +			/* power off phy */ +			exynos_pcie_power_off_phy(pp); +  			dev_err(pp->dev, "PCIe Link Fail\n");  			return -EINVAL;  		} @@ -342,9 +411,34 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)  	return IRQ_HANDLED;  } +static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg) +{ +	struct pcie_port *pp = arg; + +	return dw_handle_msi_irq(pp); +} + +static void exynos_pcie_msi_init(struct pcie_port *pp) +{ +	u32 val; +	struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + +	dw_pcie_msi_init(pp); + +	/* enable MSI interrupt */ +	val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL); +	val |= IRQ_MSI_ENABLE; +	exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL); +	return; +} +  static void exynos_pcie_enable_interrupts(struct pcie_port *pp)  {  	exynos_pcie_enable_irq_pulse(pp); + +	if (IS_ENABLED(CONFIG_PCI_MSI)) +		exynos_pcie_msi_init(pp); +  	return;  } @@ -372,7 +466,7 @@ static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,  	int ret;  	exynos_pcie_sideband_dbi_r_mode(pp, true); -	ret = cfg_read(pp->dbi_base + (where & ~0x3), where, size, val); +	ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, size, val);  	exynos_pcie_sideband_dbi_r_mode(pp, false);  	return ret;  } @@ -383,7 +477,8 @@ static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,  	int ret;  	exynos_pcie_sideband_dbi_w_mode(pp, true); -	ret = cfg_write(pp->dbi_base + (where & ~0x3), where, size, val); +	ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), +			where, size, val);  	exynos_pcie_sideband_dbi_w_mode(pp, false);  	return ret;  } @@ -414,7 +509,8 @@ static struct pcie_host_ops exynos_pcie_host_ops = {  	.host_init = exynos_pcie_host_init,  }; -static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev) +static int __init add_pcie_port(struct pcie_port *pp, +				struct platform_device *pdev)  {  	int ret; @@ -430,10 +526,25 @@ static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)  		return ret;  	} +	if (IS_ENABLED(CONFIG_PCI_MSI)) { +		pp->msi_irq = platform_get_irq(pdev, 0); +		if (!pp->msi_irq) { +			dev_err(&pdev->dev, "failed to get msi irq\n"); +			return -ENODEV; +		} + +		ret = devm_request_irq(&pdev->dev, pp->msi_irq, +					exynos_pcie_msi_irq_handler, +					IRQF_SHARED, "exynos-pcie", pp); +		if (ret) { +			dev_err(&pdev->dev, "failed to request msi irq\n"); +			return ret; +		} +	} +  	pp->root_bus_nr = -1;  	pp->ops = &exynos_pcie_host_ops; -	spin_lock_init(&pp->conf_lock);  	ret = dw_pcie_host_init(pp);  	if (ret) {  		dev_err(&pdev->dev, "failed to initialize host\n"); @@ -455,10 +566,8 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)  	exynos_pcie = devm_kzalloc(&pdev->dev, sizeof(*exynos_pcie),  				GFP_KERNEL); -	if (!exynos_pcie) { -		dev_err(&pdev->dev, "no memory for exynos pcie\n"); +	if (!exynos_pcie)  		return -ENOMEM; -	}  	pp = &exynos_pcie->pp; @@ -487,18 +596,24 @@ static int __init exynos_pcie_probe(struct platform_device *pdev)  	elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	exynos_pcie->elbi_base = devm_ioremap_resource(&pdev->dev, elbi_base); -	if (IS_ERR(exynos_pcie->elbi_base)) -		return PTR_ERR(exynos_pcie->elbi_base); +	if (IS_ERR(exynos_pcie->elbi_base)) { +		ret = PTR_ERR(exynos_pcie->elbi_base); +		goto fail_bus_clk; +	}  	phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1);  	exynos_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base); -	if (IS_ERR(exynos_pcie->phy_base)) -		return PTR_ERR(exynos_pcie->phy_base); +	if (IS_ERR(exynos_pcie->phy_base)) { +		ret = PTR_ERR(exynos_pcie->phy_base); +		goto fail_bus_clk; +	}  	block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);  	exynos_pcie->block_base = devm_ioremap_resource(&pdev->dev, block_base); -	if (IS_ERR(exynos_pcie->block_base)) -		return PTR_ERR(exynos_pcie->block_base); +	if (IS_ERR(exynos_pcie->block_base)) { +		ret = PTR_ERR(exynos_pcie->block_base); +		goto fail_bus_clk; +	}  	ret = add_pcie_port(pp, pdev);  	if (ret < 0) @@ -535,7 +650,7 @@ static struct platform_driver exynos_pcie_driver = {  	.driver = {  		.name	= "exynos-pcie",  		.owner	= THIS_MODULE, -		.of_match_table = of_match_ptr(exynos_pcie_of_match), +		.of_match_table = exynos_pcie_of_match,  	},  }; diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c new file mode 100644 index 00000000000..44fe6aa6a43 --- /dev/null +++ b/drivers/pci/host/pci-host-generic.c @@ -0,0 +1,388 @@ +/* + * Simple, generic PCI host controller driver targetting firmware-initialised + * systems and virtual machines (e.g. the PCI emulation provided by kvmtool). + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <http://www.gnu.org/licenses/>. + * + * Copyright (C) 2014 ARM Limited + * + * Author: Will Deacon <will.deacon@arm.com> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_pci.h> +#include <linux/platform_device.h> + +struct gen_pci_cfg_bus_ops { +	u32 bus_shift; +	void __iomem *(*map_bus)(struct pci_bus *, unsigned int, int); +}; + +struct gen_pci_cfg_windows { +	struct resource				res; +	struct resource				bus_range; +	void __iomem				**win; + +	const struct gen_pci_cfg_bus_ops	*ops; +}; + +struct gen_pci { +	struct pci_host_bridge			host; +	struct gen_pci_cfg_windows		cfg; +	struct list_head			resources; +}; + +static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus, +					     unsigned int devfn, +					     int where) +{ +	struct pci_sys_data *sys = bus->sysdata; +	struct gen_pci *pci = sys->private_data; +	resource_size_t idx = bus->number - pci->cfg.bus_range.start; + +	return pci->cfg.win[idx] + ((devfn << 8) | where); +} + +static struct gen_pci_cfg_bus_ops gen_pci_cfg_cam_bus_ops = { +	.bus_shift	= 16, +	.map_bus	= gen_pci_map_cfg_bus_cam, +}; + +static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus, +					      unsigned int devfn, +					      int where) +{ +	struct pci_sys_data *sys = bus->sysdata; +	struct gen_pci *pci = sys->private_data; +	resource_size_t idx = bus->number - pci->cfg.bus_range.start; + +	return pci->cfg.win[idx] + ((devfn << 12) | where); +} + +static struct gen_pci_cfg_bus_ops gen_pci_cfg_ecam_bus_ops = { +	.bus_shift	= 20, +	.map_bus	= gen_pci_map_cfg_bus_ecam, +}; + +static int gen_pci_config_read(struct pci_bus *bus, unsigned int devfn, +				int where, int size, u32 *val) +{ +	void __iomem *addr; +	struct pci_sys_data *sys = bus->sysdata; +	struct gen_pci *pci = sys->private_data; + +	addr = pci->cfg.ops->map_bus(bus, devfn, where); + +	switch (size) { +	case 1: +		*val = readb(addr); +		break; +	case 2: +		*val = readw(addr); +		break; +	default: +		*val = readl(addr); +	} + +	return PCIBIOS_SUCCESSFUL; +} + +static int gen_pci_config_write(struct pci_bus *bus, unsigned int devfn, +				 int where, int size, u32 val) +{ +	void __iomem *addr; +	struct pci_sys_data *sys = bus->sysdata; +	struct gen_pci *pci = sys->private_data; + +	addr = pci->cfg.ops->map_bus(bus, devfn, where); + +	switch (size) { +	case 1: +		writeb(val, addr); +		break; +	case 2: +		writew(val, addr); +		break; +	default: +		writel(val, addr); +	} + +	return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops gen_pci_ops = { +	.read	= gen_pci_config_read, +	.write	= gen_pci_config_write, +}; + +static const struct of_device_id gen_pci_of_match[] = { +	{ .compatible = "pci-host-cam-generic", +	  .data = &gen_pci_cfg_cam_bus_ops }, + +	{ .compatible = "pci-host-ecam-generic", +	  .data = &gen_pci_cfg_ecam_bus_ops }, + +	{ }, +}; +MODULE_DEVICE_TABLE(of, gen_pci_of_match); + +static int gen_pci_calc_io_offset(struct device *dev, +				  struct of_pci_range *range, +				  struct resource *res, +				  resource_size_t *offset) +{ +	static atomic_t wins = ATOMIC_INIT(0); +	int err, idx, max_win; +	unsigned int window; + +	if (!PAGE_ALIGNED(range->cpu_addr)) +		return -EINVAL; + +	max_win = (IO_SPACE_LIMIT + 1) / SZ_64K; +	idx = atomic_inc_return(&wins); +	if (idx > max_win) +		return -ENOSPC; + +	window = (idx - 1) * SZ_64K; +	err = pci_ioremap_io(window, range->cpu_addr); +	if (err) +		return err; + +	of_pci_range_to_resource(range, dev->of_node, res); +	res->start = window; +	res->end = res->start + range->size - 1; +	*offset = window - range->pci_addr; +	return 0; +} + +static int gen_pci_calc_mem_offset(struct device *dev, +				   struct of_pci_range *range, +				   struct resource *res, +				   resource_size_t *offset) +{ +	of_pci_range_to_resource(range, dev->of_node, res); +	*offset = range->cpu_addr - range->pci_addr; +	return 0; +} + +static void gen_pci_release_of_pci_ranges(struct gen_pci *pci) +{ +	struct pci_host_bridge_window *win; + +	list_for_each_entry(win, &pci->resources, list) +		release_resource(win->res); + +	pci_free_resource_list(&pci->resources); +} + +static int gen_pci_parse_request_of_pci_ranges(struct gen_pci *pci) +{ +	struct of_pci_range range; +	struct of_pci_range_parser parser; +	int err, res_valid = 0; +	struct device *dev = pci->host.dev.parent; +	struct device_node *np = dev->of_node; + +	if (of_pci_range_parser_init(&parser, np)) { +		dev_err(dev, "missing \"ranges\" property\n"); +		return -EINVAL; +	} + +	for_each_of_pci_range(&parser, &range) { +		struct resource *parent, *res; +		resource_size_t offset; +		u32 restype = range.flags & IORESOURCE_TYPE_BITS; + +		res = devm_kmalloc(dev, sizeof(*res), GFP_KERNEL); +		if (!res) { +			err = -ENOMEM; +			goto out_release_res; +		} + +		switch (restype) { +		case IORESOURCE_IO: +			parent = &ioport_resource; +			err = gen_pci_calc_io_offset(dev, &range, res, &offset); +			break; +		case IORESOURCE_MEM: +			parent = &iomem_resource; +			err = gen_pci_calc_mem_offset(dev, &range, res, &offset); +			res_valid |= !(res->flags & IORESOURCE_PREFETCH || err); +			break; +		default: +			err = -EINVAL; +			continue; +		} + +		if (err) { +			dev_warn(dev, +				 "error %d: failed to add resource [type 0x%x, %lld bytes]\n", +				 err, restype, range.size); +			continue; +		} + +		err = request_resource(parent, res); +		if (err) +			goto out_release_res; + +		pci_add_resource_offset(&pci->resources, res, offset); +	} + +	if (!res_valid) { +		dev_err(dev, "non-prefetchable memory resource required\n"); +		err = -EINVAL; +		goto out_release_res; +	} + +	return 0; + +out_release_res: +	gen_pci_release_of_pci_ranges(pci); +	return err; +} + +static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci) +{ +	int err; +	u8 bus_max; +	resource_size_t busn; +	struct resource *bus_range; +	struct device *dev = pci->host.dev.parent; +	struct device_node *np = dev->of_node; + +	if (of_pci_parse_bus_range(np, &pci->cfg.bus_range)) +		pci->cfg.bus_range = (struct resource) { +			.name	= np->name, +			.start	= 0, +			.end	= 0xff, +			.flags	= IORESOURCE_BUS, +		}; + +	err = of_address_to_resource(np, 0, &pci->cfg.res); +	if (err) { +		dev_err(dev, "missing \"reg\" property\n"); +		return err; +	} + +	pci->cfg.win = devm_kcalloc(dev, resource_size(&pci->cfg.bus_range), +				    sizeof(*pci->cfg.win), GFP_KERNEL); +	if (!pci->cfg.win) +		return -ENOMEM; + +	/* Limit the bus-range to fit within reg */ +	bus_max = pci->cfg.bus_range.start + +		  (resource_size(&pci->cfg.res) >> pci->cfg.ops->bus_shift) - 1; +	pci->cfg.bus_range.end = min_t(resource_size_t, pci->cfg.bus_range.end, +				       bus_max); + +	/* Map our Configuration Space windows */ +	if (!devm_request_mem_region(dev, pci->cfg.res.start, +				     resource_size(&pci->cfg.res), +				     "Configuration Space")) +		return -ENOMEM; + +	bus_range = &pci->cfg.bus_range; +	for (busn = bus_range->start; busn <= bus_range->end; ++busn) { +		u32 idx = busn - bus_range->start; +		u32 sz = 1 << pci->cfg.ops->bus_shift; + +		pci->cfg.win[idx] = devm_ioremap(dev, +						 pci->cfg.res.start + busn * sz, +						 sz); +		if (!pci->cfg.win[idx]) +			return -ENOMEM; +	} + +	/* Register bus resource */ +	pci_add_resource(&pci->resources, bus_range); +	return 0; +} + +static int gen_pci_setup(int nr, struct pci_sys_data *sys) +{ +	struct gen_pci *pci = sys->private_data; +	list_splice_init(&pci->resources, &sys->resources); +	return 1; +} + +static int gen_pci_probe(struct platform_device *pdev) +{ +	int err; +	const char *type; +	const struct of_device_id *of_id; +	const int *prop; +	struct device *dev = &pdev->dev; +	struct device_node *np = dev->of_node; +	struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); +	struct hw_pci hw = { +		.nr_controllers	= 1, +		.private_data	= (void **)&pci, +		.setup		= gen_pci_setup, +		.map_irq	= of_irq_parse_and_map_pci, +		.ops		= &gen_pci_ops, +	}; + +	if (!pci) +		return -ENOMEM; + +	type = of_get_property(np, "device_type", NULL); +	if (!type || strcmp(type, "pci")) { +		dev_err(dev, "invalid \"device_type\" %s\n", type); +		return -EINVAL; +	} + +	prop = of_get_property(of_chosen, "linux,pci-probe-only", NULL); +	if (prop) { +		if (*prop) +			pci_add_flags(PCI_PROBE_ONLY); +		else +			pci_clear_flags(PCI_PROBE_ONLY); +	} + +	of_id = of_match_node(gen_pci_of_match, np); +	pci->cfg.ops = of_id->data; +	pci->host.dev.parent = dev; +	INIT_LIST_HEAD(&pci->host.windows); +	INIT_LIST_HEAD(&pci->resources); + +	/* Parse our PCI ranges and request their resources */ +	err = gen_pci_parse_request_of_pci_ranges(pci); +	if (err) +		return err; + +	/* Parse and map our Configuration Space windows */ +	err = gen_pci_parse_map_cfg_windows(pci); +	if (err) { +		gen_pci_release_of_pci_ranges(pci); +		return err; +	} + +	pci_common_init_dev(dev, &hw); +	return 0; +} + +static struct platform_driver gen_pci_driver = { +	.driver = { +		.name = "pci-host-generic", +		.owner = THIS_MODULE, +		.of_match_table = gen_pci_of_match, +	}, +	.probe = gen_pci_probe, +}; +module_platform_driver(gen_pci_driver); + +MODULE_DESCRIPTION("Generic PCI host driver"); +MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>"); +MODULE_LICENSE("GPLv2"); diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c new file mode 100644 index 00000000000..a568efaa331 --- /dev/null +++ b/drivers/pci/host/pci-imx6.c @@ -0,0 +1,616 @@ +/* + * PCIe host controller driver for Freescale i.MX6 SoCs + * + * Copyright (C) 2013 Kosagi + *		http://www.kosagi.com + * + * Author: Sean Cross <xobs@kosagi.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio.h> +#include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/module.h> +#include <linux/of_gpio.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/resource.h> +#include <linux/signal.h> +#include <linux/types.h> +#include <linux/interrupt.h> + +#include "pcie-designware.h" + +#define to_imx6_pcie(x)	container_of(x, struct imx6_pcie, pp) + +struct imx6_pcie { +	int			reset_gpio; +	struct clk		*pcie_bus; +	struct clk		*pcie_phy; +	struct clk		*pcie; +	struct pcie_port	pp; +	struct regmap		*iomuxc_gpr; +	void __iomem		*mem_base; +}; + +/* PCIe Root Complex registers (memory-mapped) */ +#define PCIE_RC_LCR				0x7c +#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1	0x1 +#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2	0x2 +#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK	0xf + +/* PCIe Port Logic registers (memory-mapped) */ +#define PL_OFFSET 0x700 +#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) +#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) +#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING	(1 << 29) +#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP		(1 << 4) + +#define PCIE_PHY_CTRL (PL_OFFSET + 0x114) +#define PCIE_PHY_CTRL_DATA_LOC 0 +#define PCIE_PHY_CTRL_CAP_ADR_LOC 16 +#define PCIE_PHY_CTRL_CAP_DAT_LOC 17 +#define PCIE_PHY_CTRL_WR_LOC 18 +#define PCIE_PHY_CTRL_RD_LOC 19 + +#define PCIE_PHY_STAT (PL_OFFSET + 0x110) +#define PCIE_PHY_STAT_ACK_LOC 16 + +#define PCIE_LINK_WIDTH_SPEED_CONTROL	0x80C +#define PORT_LOGIC_SPEED_CHANGE		(0x1 << 17) + +/* PHY registers (not memory-mapped) */ +#define PCIE_PHY_RX_ASIC_OUT 0x100D + +#define PHY_RX_OVRD_IN_LO 0x1005 +#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5) +#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3) + +static int pcie_phy_poll_ack(void __iomem *dbi_base, int exp_val) +{ +	u32 val; +	u32 max_iterations = 10; +	u32 wait_counter = 0; + +	do { +		val = readl(dbi_base + PCIE_PHY_STAT); +		val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1; +		wait_counter++; + +		if (val == exp_val) +			return 0; + +		udelay(1); +	} while (wait_counter < max_iterations); + +	return -ETIMEDOUT; +} + +static int pcie_phy_wait_ack(void __iomem *dbi_base, int addr) +{ +	u32 val; +	int ret; + +	val = addr << PCIE_PHY_CTRL_DATA_LOC; +	writel(val, dbi_base + PCIE_PHY_CTRL); + +	val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC); +	writel(val, dbi_base + PCIE_PHY_CTRL); + +	ret = pcie_phy_poll_ack(dbi_base, 1); +	if (ret) +		return ret; + +	val = addr << PCIE_PHY_CTRL_DATA_LOC; +	writel(val, dbi_base + PCIE_PHY_CTRL); + +	ret = pcie_phy_poll_ack(dbi_base, 0); +	if (ret) +		return ret; + +	return 0; +} + +/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */ +static int pcie_phy_read(void __iomem *dbi_base, int addr , int *data) +{ +	u32 val, phy_ctl; +	int ret; + +	ret = pcie_phy_wait_ack(dbi_base, addr); +	if (ret) +		return ret; + +	/* assert Read signal */ +	phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC; +	writel(phy_ctl, dbi_base + PCIE_PHY_CTRL); + +	ret = pcie_phy_poll_ack(dbi_base, 1); +	if (ret) +		return ret; + +	val = readl(dbi_base + PCIE_PHY_STAT); +	*data = val & 0xffff; + +	/* deassert Read signal */ +	writel(0x00, dbi_base + PCIE_PHY_CTRL); + +	ret = pcie_phy_poll_ack(dbi_base, 0); +	if (ret) +		return ret; + +	return 0; +} + +static int pcie_phy_write(void __iomem *dbi_base, int addr, int data) +{ +	u32 var; +	int ret; + +	/* write addr */ +	/* cap addr */ +	ret = pcie_phy_wait_ack(dbi_base, addr); +	if (ret) +		return ret; + +	var = data << PCIE_PHY_CTRL_DATA_LOC; +	writel(var, dbi_base + PCIE_PHY_CTRL); + +	/* capture data */ +	var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC); +	writel(var, dbi_base + PCIE_PHY_CTRL); + +	ret = pcie_phy_poll_ack(dbi_base, 1); +	if (ret) +		return ret; + +	/* deassert cap data */ +	var = data << PCIE_PHY_CTRL_DATA_LOC; +	writel(var, dbi_base + PCIE_PHY_CTRL); + +	/* wait for ack de-assertion */ +	ret = pcie_phy_poll_ack(dbi_base, 0); +	if (ret) +		return ret; + +	/* assert wr signal */ +	var = 0x1 << PCIE_PHY_CTRL_WR_LOC; +	writel(var, dbi_base + PCIE_PHY_CTRL); + +	/* wait for ack */ +	ret = pcie_phy_poll_ack(dbi_base, 1); +	if (ret) +		return ret; + +	/* deassert wr signal */ +	var = data << PCIE_PHY_CTRL_DATA_LOC; +	writel(var, dbi_base + PCIE_PHY_CTRL); + +	/* wait for ack de-assertion */ +	ret = pcie_phy_poll_ack(dbi_base, 0); +	if (ret) +		return ret; + +	writel(0x0, dbi_base + PCIE_PHY_CTRL); + +	return 0; +} + +/*  Added for PCI abort handling */ +static int imx6q_pcie_abort_handler(unsigned long addr, +		unsigned int fsr, struct pt_regs *regs) +{ +	return 0; +} + +static int imx6_pcie_assert_core_reset(struct pcie_port *pp) +{ +	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); + +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, +			IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, +			IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); + +	return 0; +} + +static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) +{ +	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); +	int ret; + +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, +			IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, +			IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16); + +	ret = clk_prepare_enable(imx6_pcie->pcie_phy); +	if (ret) { +		dev_err(pp->dev, "unable to enable pcie_phy clock\n"); +		goto err_pcie_phy; +	} + +	ret = clk_prepare_enable(imx6_pcie->pcie_bus); +	if (ret) { +		dev_err(pp->dev, "unable to enable pcie_bus clock\n"); +		goto err_pcie_bus; +	} + +	ret = clk_prepare_enable(imx6_pcie->pcie); +	if (ret) { +		dev_err(pp->dev, "unable to enable pcie clock\n"); +		goto err_pcie; +	} + +	/* allow the clocks to stabilize */ +	usleep_range(200, 500); + +	/* Some boards don't have PCIe reset GPIO. */ +	if (gpio_is_valid(imx6_pcie->reset_gpio)) { +		gpio_set_value(imx6_pcie->reset_gpio, 0); +		msleep(100); +		gpio_set_value(imx6_pcie->reset_gpio, 1); +	} +	return 0; + +err_pcie: +	clk_disable_unprepare(imx6_pcie->pcie_bus); +err_pcie_bus: +	clk_disable_unprepare(imx6_pcie->pcie_phy); +err_pcie_phy: +	return ret; + +} + +static void imx6_pcie_init_phy(struct pcie_port *pp) +{ +	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); + +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +			IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); + +	/* configure constant input signal to the pcie ctrl and phy */ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +			IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +			IMX6Q_GPR12_LOS_LEVEL, 9 << 4); + +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			IMX6Q_GPR8_TX_DEEMPH_GEN1, 0 << 0); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB, 0 << 6); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB, 20 << 12); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			IMX6Q_GPR8_TX_SWING_FULL, 127 << 18); +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8, +			IMX6Q_GPR8_TX_SWING_LOW, 127 << 25); +} + +static int imx6_pcie_wait_for_link(struct pcie_port *pp) +{ +	int count = 200; + +	while (!dw_pcie_link_up(pp)) { +		usleep_range(100, 1000); +		if (--count) +			continue; + +		dev_err(pp->dev, "phy link never came up\n"); +		dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", +			readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), +			readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); +		return -EINVAL; +	} + +	return 0; +} + +static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg) +{ +	struct pcie_port *pp = arg; + +	return dw_handle_msi_irq(pp); +} + +static int imx6_pcie_start_link(struct pcie_port *pp) +{ +	struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); +	uint32_t tmp; +	int ret, count; + +	/* +	 * Force Gen1 operation when starting the link.  In case the link is +	 * started in Gen2 mode, there is a possibility the devices on the +	 * bus will not be detected at all.  This happens with PCIe switches. +	 */ +	tmp = readl(pp->dbi_base + PCIE_RC_LCR); +	tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; +	tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1; +	writel(tmp, pp->dbi_base + PCIE_RC_LCR); + +	/* Start LTSSM. */ +	regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, +			IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); + +	ret = imx6_pcie_wait_for_link(pp); +	if (ret) +		return ret; + +	/* Allow Gen2 mode after the link is up. */ +	tmp = readl(pp->dbi_base + PCIE_RC_LCR); +	tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; +	tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; +	writel(tmp, pp->dbi_base + PCIE_RC_LCR); + +	/* +	 * Start Directed Speed Change so the best possible speed both link +	 * partners support can be negotiated. +	 */ +	tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); +	tmp |= PORT_LOGIC_SPEED_CHANGE; +	writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + +	count = 200; +	while (count--) { +		tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); +		/* Test if the speed change finished. */ +		if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) +			break; +		usleep_range(100, 1000); +	} + +	/* Make sure link training is finished as well! */ +	if (count) +		ret = imx6_pcie_wait_for_link(pp); +	else +		ret = -EINVAL; + +	if (ret) { +		dev_err(pp->dev, "Failed to bring link up!\n"); +	} else { +		tmp = readl(pp->dbi_base + 0x80); +		dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); +	} + +	return ret; +} + +static void imx6_pcie_host_init(struct pcie_port *pp) +{ +	imx6_pcie_assert_core_reset(pp); + +	imx6_pcie_init_phy(pp); + +	imx6_pcie_deassert_core_reset(pp); + +	dw_pcie_setup_rc(pp); + +	imx6_pcie_start_link(pp); + +	if (IS_ENABLED(CONFIG_PCI_MSI)) +		dw_pcie_msi_init(pp); +} + +static void imx6_pcie_reset_phy(struct pcie_port *pp) +{ +	uint32_t temp; + +	pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); +	temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | +		 PHY_RX_OVRD_IN_LO_RX_PLL_EN); +	pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); + +	usleep_range(2000, 3000); + +	pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); +	temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | +		  PHY_RX_OVRD_IN_LO_RX_PLL_EN); +	pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); +} + +static int imx6_pcie_link_up(struct pcie_port *pp) +{ +	u32 rc, debug_r0, rx_valid; +	int count = 5; + +	/* +	 * Test if the PHY reports that the link is up and also that the LTSSM +	 * training finished. There are three possible states of the link when +	 * this code is called: +	 * 1) The link is DOWN (unlikely) +	 *     The link didn't come up yet for some reason. This usually means +	 *     we have a real problem somewhere. Reset the PHY and exit. This +	 *     state calls for inspection of the DEBUG registers. +	 * 2) The link is UP, but still in LTSSM training +	 *     Wait for the training to finish, which should take a very short +	 *     time. If the training does not finish, we have a problem and we +	 *     need to inspect the DEBUG registers. If the training does finish, +	 *     the link is up and operating correctly. +	 * 3) The link is UP and no longer in LTSSM training +	 *     The link is up and operating correctly. +	 */ +	while (1) { +		rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); +		if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP)) +			break; +		if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) +			return 1; +		if (!count--) +			break; +		dev_dbg(pp->dev, "Link is up, but still in training\n"); +		/* +		 * Wait a little bit, then re-check if the link finished +		 * the training. +		 */ +		usleep_range(1000, 2000); +	} +	/* +	 * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. +	 * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2). +	 * If (MAC/LTSSM.state == Recovery.RcvrLock) +	 * && (PHY/rx_valid==0) then pulse PHY/rx_reset. Transition +	 * to gen2 is stuck +	 */ +	pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); +	debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0); + +	if (rx_valid & 0x01) +		return 0; + +	if ((debug_r0 & 0x3f) != 0x0d) +		return 0; + +	dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); +	dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc); + +	imx6_pcie_reset_phy(pp); + +	return 0; +} + +static struct pcie_host_ops imx6_pcie_host_ops = { +	.link_up = imx6_pcie_link_up, +	.host_init = imx6_pcie_host_init, +}; + +static int __init imx6_add_pcie_port(struct pcie_port *pp, +			struct platform_device *pdev) +{ +	int ret; + +	if (IS_ENABLED(CONFIG_PCI_MSI)) { +		pp->msi_irq = platform_get_irq_byname(pdev, "msi"); +		if (pp->msi_irq <= 0) { +			dev_err(&pdev->dev, "failed to get MSI irq\n"); +			return -ENODEV; +		} + +		ret = devm_request_irq(&pdev->dev, pp->msi_irq, +		                       imx6_pcie_msi_handler, +		                       IRQF_SHARED, "mx6-pcie-msi", pp); +		if (ret) { +			dev_err(&pdev->dev, "failed to request MSI irq\n"); +			return -ENODEV; +		} +	} + +	pp->root_bus_nr = -1; +	pp->ops = &imx6_pcie_host_ops; + +	ret = dw_pcie_host_init(pp); +	if (ret) { +		dev_err(&pdev->dev, "failed to initialize host\n"); +		return ret; +	} + +	return 0; +} + +static int __init imx6_pcie_probe(struct platform_device *pdev) +{ +	struct imx6_pcie *imx6_pcie; +	struct pcie_port *pp; +	struct device_node *np = pdev->dev.of_node; +	struct resource *dbi_base; +	int ret; + +	imx6_pcie = devm_kzalloc(&pdev->dev, sizeof(*imx6_pcie), GFP_KERNEL); +	if (!imx6_pcie) +		return -ENOMEM; + +	pp = &imx6_pcie->pp; +	pp->dev = &pdev->dev; + +	/* Added for PCI abort handling */ +	hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0, +		"imprecise external abort"); + +	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base); +	if (IS_ERR(pp->dbi_base)) +		return PTR_ERR(pp->dbi_base); + +	/* Fetch GPIOs */ +	imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); +	if (gpio_is_valid(imx6_pcie->reset_gpio)) { +		ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio, +					    GPIOF_OUT_INIT_LOW, "PCIe reset"); +		if (ret) { +			dev_err(&pdev->dev, "unable to get reset gpio\n"); +			return ret; +		} +	} + +	/* Fetch clocks */ +	imx6_pcie->pcie_phy = devm_clk_get(&pdev->dev, "pcie_phy"); +	if (IS_ERR(imx6_pcie->pcie_phy)) { +		dev_err(&pdev->dev, +			"pcie_phy clock source missing or invalid\n"); +		return PTR_ERR(imx6_pcie->pcie_phy); +	} + +	imx6_pcie->pcie_bus = devm_clk_get(&pdev->dev, "pcie_bus"); +	if (IS_ERR(imx6_pcie->pcie_bus)) { +		dev_err(&pdev->dev, +			"pcie_bus clock source missing or invalid\n"); +		return PTR_ERR(imx6_pcie->pcie_bus); +	} + +	imx6_pcie->pcie = devm_clk_get(&pdev->dev, "pcie"); +	if (IS_ERR(imx6_pcie->pcie)) { +		dev_err(&pdev->dev, +			"pcie clock source missing or invalid\n"); +		return PTR_ERR(imx6_pcie->pcie); +	} + +	/* Grab GPR config register range */ +	imx6_pcie->iomuxc_gpr = +		 syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr"); +	if (IS_ERR(imx6_pcie->iomuxc_gpr)) { +		dev_err(&pdev->dev, "unable to find iomuxc registers\n"); +		return PTR_ERR(imx6_pcie->iomuxc_gpr); +	} + +	ret = imx6_add_pcie_port(pp, pdev); +	if (ret < 0) +		return ret; + +	platform_set_drvdata(pdev, imx6_pcie); +	return 0; +} + +static const struct of_device_id imx6_pcie_of_match[] = { +	{ .compatible = "fsl,imx6q-pcie", }, +	{}, +}; +MODULE_DEVICE_TABLE(of, imx6_pcie_of_match); + +static struct platform_driver imx6_pcie_driver = { +	.driver = { +		.name	= "imx6q-pcie", +		.owner	= THIS_MODULE, +		.of_match_table = imx6_pcie_of_match, +	}, +}; + +/* Freescale PCIe driver does not allow module unload */ + +static int __init imx6_pcie_init(void) +{ +	return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe); +} +fs_initcall(imx6_pcie_init); + +MODULE_AUTHOR("Sean Cross <xobs@kosagi.com>"); +MODULE_DESCRIPTION("Freescale i.MX6 PCIe host controller driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c index 729d5a101d6..ce23e0f076b 100644 --- a/drivers/pci/host/pci-mvebu.c +++ b/drivers/pci/host/pci-mvebu.c @@ -9,13 +9,17 @@  #include <linux/kernel.h>  #include <linux/pci.h>  #include <linux/clk.h> +#include <linux/delay.h> +#include <linux/gpio.h>  #include <linux/module.h>  #include <linux/mbus.h> +#include <linux/msi.h>  #include <linux/slab.h>  #include <linux/platform_device.h>  #include <linux/of_address.h> -#include <linux/of_pci.h>  #include <linux/of_irq.h> +#include <linux/of_gpio.h> +#include <linux/of_pci.h>  #include <linux/of_platform.h>  /* @@ -56,14 +60,6 @@  #define PCIE_DEBUG_CTRL         0x1a60  #define  PCIE_DEBUG_SOFT_RESET		BIT(20) -/* - * This product ID is registered by Marvell, and used when the Marvell - * SoC is not the root complex, but an endpoint on the PCIe bus. It is - * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI - * bridge. - */ -#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846 -  /* PCI configuration space of a PCI-to-PCI bridge */  struct mvebu_sw_pci_bridge {  	u16 vendor; @@ -103,8 +99,11 @@ struct mvebu_pcie_port;  struct mvebu_pcie {  	struct platform_device *pdev;  	struct mvebu_pcie_port *ports; +	struct msi_chip *msi;  	struct resource io; +	char io_name[30];  	struct resource realio; +	char mem_name[30];  	struct resource mem;  	struct resource busn;  	int nports; @@ -114,8 +113,6 @@ struct mvebu_pcie {  struct mvebu_pcie_port {  	char *name;  	void __iomem *base; -	spinlock_t conf_lock; -	int haslink;  	u32 port;  	u32 lane;  	int devfn; @@ -124,6 +121,9 @@ struct mvebu_pcie_port {  	unsigned int io_target;  	unsigned int io_attr;  	struct clk *clk; +	int reset_gpio; +	int reset_active_low; +	char *reset_name;  	struct mvebu_sw_pci_bridge bridge;  	struct device_node *dn;  	struct mvebu_pcie *pcie; @@ -133,29 +133,44 @@ struct mvebu_pcie_port {  	size_t iowin_size;  }; +static inline void mvebu_writel(struct mvebu_pcie_port *port, u32 val, u32 reg) +{ +	writel(val, port->base + reg); +} + +static inline u32 mvebu_readl(struct mvebu_pcie_port *port, u32 reg) +{ +	return readl(port->base + reg); +} + +static inline bool mvebu_has_ioport(struct mvebu_pcie_port *port) +{ +	return port->io_target != -1 && port->io_attr != -1; +} +  static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)  { -	return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); +	return !(mvebu_readl(port, PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);  }  static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)  {  	u32 stat; -	stat = readl(port->base + PCIE_STAT_OFF); +	stat = mvebu_readl(port, PCIE_STAT_OFF);  	stat &= ~PCIE_STAT_BUS;  	stat |= nr << 8; -	writel(stat, port->base + PCIE_STAT_OFF); +	mvebu_writel(port, stat, PCIE_STAT_OFF);  }  static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)  {  	u32 stat; -	stat = readl(port->base + PCIE_STAT_OFF); +	stat = mvebu_readl(port, PCIE_STAT_OFF);  	stat &= ~PCIE_STAT_DEV;  	stat |= nr << 16; -	writel(stat, port->base + PCIE_STAT_OFF); +	mvebu_writel(port, stat, PCIE_STAT_OFF);  }  /* @@ -163,7 +178,7 @@ static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)   * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks   * WIN[0-3] -> DRAM bank[0-3]   */ -static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port) +static void mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)  {  	const struct mbus_dram_target_info *dram;  	u32 size; @@ -173,33 +188,34 @@ static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)  	/* First, disable and clear BARs and windows. */  	for (i = 1; i < 3; i++) { -		writel(0, port->base + PCIE_BAR_CTRL_OFF(i)); -		writel(0, port->base + PCIE_BAR_LO_OFF(i)); -		writel(0, port->base + PCIE_BAR_HI_OFF(i)); +		mvebu_writel(port, 0, PCIE_BAR_CTRL_OFF(i)); +		mvebu_writel(port, 0, PCIE_BAR_LO_OFF(i)); +		mvebu_writel(port, 0, PCIE_BAR_HI_OFF(i));  	}  	for (i = 0; i < 5; i++) { -		writel(0, port->base + PCIE_WIN04_CTRL_OFF(i)); -		writel(0, port->base + PCIE_WIN04_BASE_OFF(i)); -		writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); +		mvebu_writel(port, 0, PCIE_WIN04_CTRL_OFF(i)); +		mvebu_writel(port, 0, PCIE_WIN04_BASE_OFF(i)); +		mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i));  	} -	writel(0, port->base + PCIE_WIN5_CTRL_OFF); -	writel(0, port->base + PCIE_WIN5_BASE_OFF); -	writel(0, port->base + PCIE_WIN5_REMAP_OFF); +	mvebu_writel(port, 0, PCIE_WIN5_CTRL_OFF); +	mvebu_writel(port, 0, PCIE_WIN5_BASE_OFF); +	mvebu_writel(port, 0, PCIE_WIN5_REMAP_OFF);  	/* Setup windows for DDR banks.  Count total DDR size on the fly. */  	size = 0;  	for (i = 0; i < dram->num_cs; i++) {  		const struct mbus_dram_window *cs = dram->cs + i; -		writel(cs->base & 0xffff0000, -		       port->base + PCIE_WIN04_BASE_OFF(i)); -		writel(0, port->base + PCIE_WIN04_REMAP_OFF(i)); -		writel(((cs->size - 1) & 0xffff0000) | -			(cs->mbus_attr << 8) | -			(dram->mbus_dram_target_id << 4) | 1, -		       port->base + PCIE_WIN04_CTRL_OFF(i)); +		mvebu_writel(port, cs->base & 0xffff0000, +			     PCIE_WIN04_BASE_OFF(i)); +		mvebu_writel(port, 0, PCIE_WIN04_REMAP_OFF(i)); +		mvebu_writel(port, +			     ((cs->size - 1) & 0xffff0000) | +			     (cs->mbus_attr << 8) | +			     (dram->mbus_dram_target_id << 4) | 1, +			     PCIE_WIN04_CTRL_OFF(i));  		size += cs->size;  	} @@ -209,41 +225,40 @@ static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)  		size = 1 << fls(size);  	/* Setup BAR[1] to all DRAM banks. */ -	writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1)); -	writel(0, port->base + PCIE_BAR_HI_OFF(1)); -	writel(((size - 1) & 0xffff0000) | 1, -	       port->base + PCIE_BAR_CTRL_OFF(1)); +	mvebu_writel(port, dram->cs[0].base, PCIE_BAR_LO_OFF(1)); +	mvebu_writel(port, 0, PCIE_BAR_HI_OFF(1)); +	mvebu_writel(port, ((size - 1) & 0xffff0000) | 1, +		     PCIE_BAR_CTRL_OFF(1));  } -static void __init mvebu_pcie_setup_hw(struct mvebu_pcie_port *port) +static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)  { -	u16 cmd; -	u32 mask; +	u32 cmd, mask;  	/* Point PCIe unit MBUS decode windows to DRAM space. */  	mvebu_pcie_setup_wins(port);  	/* Master + slave enable. */ -	cmd = readw(port->base + PCIE_CMD_OFF); +	cmd = mvebu_readl(port, PCIE_CMD_OFF);  	cmd |= PCI_COMMAND_IO;  	cmd |= PCI_COMMAND_MEMORY;  	cmd |= PCI_COMMAND_MASTER; -	writew(cmd, port->base + PCIE_CMD_OFF); +	mvebu_writel(port, cmd, PCIE_CMD_OFF);  	/* Enable interrupt lines A-D. */ -	mask = readl(port->base + PCIE_MASK_OFF); +	mask = mvebu_readl(port, PCIE_MASK_OFF);  	mask |= PCIE_MASK_ENABLE_INTS; -	writel(mask, port->base + PCIE_MASK_OFF); +	mvebu_writel(port, mask, PCIE_MASK_OFF);  }  static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,  				 struct pci_bus *bus,  				 u32 devfn, int where, int size, u32 *val)  { -	writel(PCIE_CONF_ADDR(bus->number, devfn, where), -	       port->base + PCIE_CONF_ADDR_OFF); +	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), +		     PCIE_CONF_ADDR_OFF); -	*val = readl(port->base + PCIE_CONF_DATA_OFF); +	*val = mvebu_readl(port, PCIE_CONF_DATA_OFF);  	if (size == 1)  		*val = (*val >> (8 * (where & 3))) & 0xff; @@ -257,21 +272,78 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,  				 struct pci_bus *bus,  				 u32 devfn, int where, int size, u32 val)  { -	int ret = PCIBIOS_SUCCESSFUL; +	u32 _val, shift = 8 * (where & 3); -	writel(PCIE_CONF_ADDR(bus->number, devfn, where), -	       port->base + PCIE_CONF_ADDR_OFF); +	mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where), +		     PCIE_CONF_ADDR_OFF); +	_val = mvebu_readl(port, PCIE_CONF_DATA_OFF);  	if (size == 4) -		writel(val, port->base + PCIE_CONF_DATA_OFF); +		_val = val;  	else if (size == 2) -		writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); +		_val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);  	else if (size == 1) -		writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3)); +		_val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);  	else -		ret = PCIBIOS_BAD_REGISTER_NUMBER; +		return PCIBIOS_BAD_REGISTER_NUMBER; -	return ret; +	mvebu_writel(port, _val, PCIE_CONF_DATA_OFF); + +	return PCIBIOS_SUCCESSFUL; +} + +/* + * Remove windows, starting from the largest ones to the smallest + * ones. + */ +static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port, +				   phys_addr_t base, size_t size) +{ +	while (size) { +		size_t sz = 1 << (fls(size) - 1); + +		mvebu_mbus_del_window(base, sz); +		base += sz; +		size -= sz; +	} +} + +/* + * MBus windows can only have a power of two size, but PCI BARs do not + * have this constraint. Therefore, we have to split the PCI BAR into + * areas each having a power of two size. We start from the largest + * one (i.e highest order bit set in the size). + */ +static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, +				   unsigned int target, unsigned int attribute, +				   phys_addr_t base, size_t size, +				   phys_addr_t remap) +{ +	size_t size_mapped = 0; + +	while (size) { +		size_t sz = 1 << (fls(size) - 1); +		int ret; + +		ret = mvebu_mbus_add_window_remap_by_id(target, attribute, base, +							sz, remap); +		if (ret) { +			phys_addr_t end = base + sz - 1; + +			dev_err(&port->pcie->pdev->dev, +				"Could not create MBus window at [mem %pa-%pa]: %d\n", +				&base, &end, ret); +			mvebu_pcie_del_windows(port, base - size_mapped, +					       size_mapped); +			return; +		} + +		size -= sz; +		size_mapped += sz; +		base += sz; +		if (remap != MVEBU_MBUS_NO_REMAP) +			remap += sz; +	}  }  static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) @@ -280,12 +352,13 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)  	/* Are the new iobase/iolimit values invalid? */  	if (port->bridge.iolimit < port->bridge.iobase || -	    port->bridge.iolimitupper < port->bridge.iobaseupper) { +	    port->bridge.iolimitupper < port->bridge.iobaseupper || +	    !(port->bridge.command & PCI_COMMAND_IO)) {  		/* If a window was configured, remove it */  		if (port->iowin_base) { -			mvebu_mbus_del_window(port->iowin_base, -					      port->iowin_size); +			mvebu_pcie_del_windows(port, port->iowin_base, +					       port->iowin_size);  			port->iowin_base = 0;  			port->iowin_size = 0;  		} @@ -293,6 +366,12 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)  		return;  	} +	if (!mvebu_has_ioport(port)) { +		dev_WARN(&port->pcie->pdev->dev, +			 "Attempt to set IO when IO is disabled\n"); +		return; +	} +  	/*  	 * We read the PCI-to-PCI bridge emulated registers, and  	 * calculate the base address and size of the address decoding @@ -305,24 +384,23 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)  	port->iowin_base = port->pcie->io.start + iobase;  	port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |  			    (port->bridge.iolimitupper << 16)) - -			    iobase); +			    iobase) + 1; -	mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr, -					  port->iowin_base, port->iowin_size, -					  iobase); - -	pci_ioremap_io(iobase, port->iowin_base); +	mvebu_pcie_add_windows(port, port->io_target, port->io_attr, +			       port->iowin_base, port->iowin_size, +			       iobase);  }  static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)  {  	/* Are the new membase/memlimit values invalid? */ -	if (port->bridge.memlimit < port->bridge.membase) { +	if (port->bridge.memlimit < port->bridge.membase || +	    !(port->bridge.command & PCI_COMMAND_MEMORY)) {  		/* If a window was configured, remove it */  		if (port->memwin_base) { -			mvebu_mbus_del_window(port->memwin_base, -					      port->memwin_size); +			mvebu_pcie_del_windows(port, port->memwin_base, +					       port->memwin_size);  			port->memwin_base = 0;  			port->memwin_size = 0;  		} @@ -339,10 +417,11 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)  	port->memwin_base  = ((port->bridge.membase & 0xFFF0) << 16);  	port->memwin_size  =  		(((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) - -		port->memwin_base; +		port->memwin_base + 1; -	mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr, -				    port->memwin_base, port->memwin_size); +	mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr, +			       port->memwin_base, port->memwin_size, +			       MVEBU_MBUS_NO_REMAP);  }  /* @@ -357,7 +436,8 @@ static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)  	bridge->class = PCI_CLASS_BRIDGE_PCI;  	bridge->vendor = PCI_VENDOR_ID_MARVELL; -	bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID; +	bridge->device = mvebu_readl(port, PCIE_DEV_ID_OFF) >> 16; +	bridge->revision = mvebu_readl(port, PCIE_DEV_REV_OFF) & 0xff;  	bridge->header_type = PCI_HEADER_TYPE_BRIDGE;  	bridge->cache_line_size = 0x10; @@ -406,9 +486,12 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,  		break;  	case PCI_IO_BASE: -		*value = (bridge->secondary_status << 16 | -			  bridge->iolimit          <<  8 | -			  bridge->iobase); +		if (!mvebu_has_ioport(port)) +			*value = bridge->secondary_status << 16; +		else +			*value = (bridge->secondary_status << 16 | +				  bridge->iolimit          <<  8 | +				  bridge->iobase);  		break;  	case PCI_MEMORY_BASE: @@ -427,6 +510,11 @@ static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,  		*value = 0;  		break; +	case PCI_INTERRUPT_LINE: +		/* LINE PIN MIN_GNT MAX_LAT */ +		*value = 0; +		break; +  	default:  		*value = 0xffffffff;  		return PCIBIOS_BAD_REGISTER_NUMBER; @@ -465,8 +553,19 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,  	switch (where & ~3) {  	case PCI_COMMAND: +	{ +		u32 old = bridge->command; + +		if (!mvebu_has_ioport(port)) +			value &= ~PCI_COMMAND_IO; +  		bridge->command = value & 0xffff; +		if ((old ^ bridge->command) & PCI_COMMAND_IO) +			mvebu_pcie_handle_iobase_change(port); +		if ((old ^ bridge->command) & PCI_COMMAND_MEMORY) +			mvebu_pcie_handle_membase_change(port);  		break; +	}  	case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:  		bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value; @@ -480,7 +579,6 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,  		 */  		bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32;  		bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32; -		bridge->secondary_status = value >> 16;  		mvebu_pcie_handle_iobase_change(port);  		break; @@ -516,9 +614,9 @@ static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys)  	return sys->private_data;  } -static struct mvebu_pcie_port * -mvebu_pcie_find_port(struct mvebu_pcie *pcie, struct pci_bus *bus, -		     int devfn) +static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie, +						    struct pci_bus *bus, +						    int devfn)  {  	int i; @@ -541,7 +639,6 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  {  	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);  	struct mvebu_pcie_port *port; -	unsigned long flags;  	int ret;  	port = mvebu_pcie_find_port(pcie, bus, devfn); @@ -552,7 +649,7 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  	if (bus->number == 0)  		return mvebu_sw_pci_bridge_write(port, where, size, val); -	if (!port->haslink) +	if (!mvebu_pcie_link_up(port))  		return PCIBIOS_DEVICE_NOT_FOUND;  	/* @@ -567,10 +664,8 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  		return PCIBIOS_DEVICE_NOT_FOUND;  	/* Access the real PCIe interface */ -	spin_lock_irqsave(&port->conf_lock, flags);  	ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,  				    where, size, val); -	spin_unlock_irqrestore(&port->conf_lock, flags);  	return ret;  } @@ -581,7 +676,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,  {  	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);  	struct mvebu_pcie_port *port; -	unsigned long flags;  	int ret;  	port = mvebu_pcie_find_port(pcie, bus, devfn); @@ -594,7 +688,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,  	if (bus->number == 0)  		return mvebu_sw_pci_bridge_read(port, where, size, val); -	if (!port->haslink) { +	if (!mvebu_pcie_link_up(port)) {  		*val = 0xffffffff;  		return PCIBIOS_DEVICE_NOT_FOUND;  	} @@ -613,10 +707,8 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,  	}  	/* Access the real PCIe interface */ -	spin_lock_irqsave(&port->conf_lock, flags);  	ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,  				    where, size, val); -	spin_unlock_irqrestore(&port->conf_lock, flags);  	return ret;  } @@ -626,12 +718,34 @@ static struct pci_ops mvebu_pcie_ops = {  	.write = mvebu_pcie_wr_conf,  }; -static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys) +static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)  {  	struct mvebu_pcie *pcie = sys_to_pcie(sys);  	int i; +	int domain = 0; + +#ifdef CONFIG_PCI_DOMAINS +	domain = sys->domain; +#endif + +	snprintf(pcie->mem_name, sizeof(pcie->mem_name), "PCI MEM %04x", +		 domain); +	pcie->mem.name = pcie->mem_name; + +	snprintf(pcie->io_name, sizeof(pcie->io_name), "PCI I/O %04x", domain); +	pcie->realio.name = pcie->io_name; -	pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset); +	if (request_resource(&iomem_resource, &pcie->mem)) +		return 0; + +	if (resource_size(&pcie->realio) != 0) { +		if (request_resource(&ioport_resource, &pcie->realio)) { +			release_resource(&pcie->mem); +			return 0; +		} +		pci_add_resource_offset(&sys->resources, &pcie->realio, +					sys->io_offset); +	}  	pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);  	pci_add_resource(&sys->resources, &pcie->busn); @@ -645,19 +759,6 @@ static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)  	return 1;  } -static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ -	struct of_irq oirq; -	int ret; - -	ret = of_irq_map_pci(dev, &oirq); -	if (ret) -		return ret; - -	return irq_create_of_mapping(oirq.controller, oirq.specifier, -				     oirq.size); -} -  static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)  {  	struct mvebu_pcie *pcie = sys_to_pcie(sys); @@ -673,30 +774,43 @@ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)  	return bus;  } -resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, -					  const struct resource *res, -					  resource_size_t start, -					  resource_size_t size, -					  resource_size_t align) +static void mvebu_pcie_add_bus(struct pci_bus *bus) +{ +	struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata); +	bus->msi = pcie->msi; +} + +static resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev, +						 const struct resource *res, +						 resource_size_t start, +						 resource_size_t size, +						 resource_size_t align)  {  	if (dev->bus->number != 0)  		return start;  	/*  	 * On the PCI-to-PCI bridge side, the I/O windows must have at -	 * least a 64 KB size and be aligned on their size, and the -	 * memory windows must have at least a 1 MB size and be -	 * aligned on their size +	 * least a 64 KB size and the memory windows must have at +	 * least a 1 MB size. Moreover, MBus windows need to have a +	 * base address aligned on their size, and their size must be +	 * a power of two. This means that if the BAR doesn't have a +	 * power of two size, several MBus windows will actually be +	 * created. We need to ensure that the biggest MBus window +	 * (which will be the first one) is aligned on its size, which +	 * explains the rounddown_pow_of_two() being done here.  	 */  	if (res->flags & IORESOURCE_IO) -		return round_up(start, max((resource_size_t)SZ_64K, size)); +		return round_up(start, max_t(resource_size_t, SZ_64K, +					     rounddown_pow_of_two(size)));  	else if (res->flags & IORESOURCE_MEM) -		return round_up(start, max((resource_size_t)SZ_1M, size)); +		return round_up(start, max_t(resource_size_t, SZ_1M, +					     rounddown_pow_of_two(size)));  	else  		return start;  } -static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie) +static void mvebu_pcie_enable(struct mvebu_pcie *pcie)  {  	struct hw_pci hw; @@ -706,9 +820,10 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)  	hw.private_data   = (void **)&pcie;  	hw.setup          = mvebu_pcie_setup;  	hw.scan           = mvebu_pcie_scan_bus; -	hw.map_irq        = mvebu_pcie_map_irq; +	hw.map_irq        = of_irq_parse_and_map_pci;  	hw.ops            = &mvebu_pcie_ops;  	hw.align_resource = mvebu_pcie_align_resource; +	hw.add_bus        = mvebu_pcie_add_bus;  	pci_common_init(&hw);  } @@ -718,10 +833,9 @@ static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)   * <...> property for one that matches the given port/lane. Once   * found, maps it.   */ -static void __iomem * __init -mvebu_pcie_map_registers(struct platform_device *pdev, -			 struct device_node *np, -			 struct mvebu_pcie_port *port) +static void __iomem *mvebu_pcie_map_registers(struct platform_device *pdev, +					      struct device_node *np, +					      struct mvebu_pcie_port *port)  {  	struct resource regs;  	int ret = 0; @@ -740,12 +854,17 @@ mvebu_pcie_map_registers(struct platform_device *pdev,  #define DT_CPUADDR_TO_ATTR(cpuaddr)   (((cpuaddr) >> 48) & 0xFF)  static int mvebu_get_tgt_attr(struct device_node *np, int devfn, -			      unsigned long type, int *tgt, int *attr) +			      unsigned long type, +			      unsigned int *tgt, +			      unsigned int *attr)  {  	const int na = 3, ns = 2;  	const __be32 *range;  	int rlen, nranges, rangesz, pna, i; +	*tgt = -1; +	*attr = -1; +  	range = of_get_property(np, "ranges", &rlen);  	if (!range)  		return -EINVAL; @@ -756,7 +875,7 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,  	for (i = 0; i < nranges; i++) {  		u32 flags = of_read_number(range, 1); -		u32 slot = of_read_number(range, 2); +		u32 slot = of_read_number(range + 1, 1);  		u64 cpuaddr = of_read_number(range + na, pna);  		unsigned long rtype; @@ -777,7 +896,22 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,  	return -ENOENT;  } -static int __init mvebu_pcie_probe(struct platform_device *pdev) +static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie) +{ +	struct device_node *msi_node; + +	msi_node = of_parse_phandle(pcie->pdev->dev.of_node, +				    "msi-parent", 0); +	if (!msi_node) +		return; + +	pcie->msi = of_pci_find_msi_chip_by_node(msi_node); + +	if (pcie->msi) +		pcie->msi->dev = &pcie->pdev->dev; +} + +static int mvebu_pcie_probe(struct platform_device *pdev)  {  	struct mvebu_pcie *pcie;  	struct device_node *np = pdev->dev.of_node; @@ -790,6 +924,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)  		return -ENOMEM;  	pcie->pdev = pdev; +	platform_set_drvdata(pdev, pcie);  	/* Get the PCIe memory and I/O aperture */  	mvebu_mbus_get_pcie_mem_aperture(&pcie->mem); @@ -799,16 +934,15 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)  	}  	mvebu_mbus_get_pcie_io_aperture(&pcie->io); -	if (resource_size(&pcie->io) == 0) { -		dev_err(&pdev->dev, "invalid I/O aperture size\n"); -		return -EINVAL; -	} -	pcie->realio.flags = pcie->io.flags; -	pcie->realio.start = PCIBIOS_MIN_IO; -	pcie->realio.end = min_t(resource_size_t, -				  IO_SPACE_LIMIT, -				  resource_size(&pcie->io)); +	if (resource_size(&pcie->io) != 0) { +		pcie->realio.flags = pcie->io.flags; +		pcie->realio.start = PCIBIOS_MIN_IO; +		pcie->realio.end = min_t(resource_size_t, +					 IO_SPACE_LIMIT, +					 resource_size(&pcie->io)); +	} else +		pcie->realio = pcie->io;  	/* Get the bus range */  	ret = of_pci_parse_bus_range(np, &pcie->busn); @@ -818,13 +952,14 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)  		return ret;  	} +	i = 0;  	for_each_child_of_node(pdev->dev.of_node, child) {  		if (!of_device_is_available(child))  			continue; -		pcie->nports++; +		i++;  	} -	pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports * +	pcie->ports = devm_kzalloc(&pdev->dev, i *  				   sizeof(struct mvebu_pcie_port),  				   GFP_KERNEL);  	if (!pcie->ports) @@ -833,6 +968,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)  	i = 0;  	for_each_child_of_node(pdev->dev.of_node, child) {  		struct mvebu_pcie_port *port = &pcie->ports[i]; +		enum of_gpio_flags flags;  		if (!of_device_is_available(child))  			continue; @@ -865,53 +1001,71 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)  			continue;  		} -		ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, -					 &port->io_target, &port->io_attr); -		if (ret < 0) { -			dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n", -				port->port, port->lane); +		if (resource_size(&pcie->io) != 0) +			mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO, +					   &port->io_target, &port->io_attr); +		else { +			port->io_target = -1; +			port->io_attr = -1; +		} + +		port->reset_gpio = of_get_named_gpio_flags(child, +						   "reset-gpios", 0, &flags); +		if (gpio_is_valid(port->reset_gpio)) { +			u32 reset_udelay = 20000; + +			port->reset_active_low = flags & OF_GPIO_ACTIVE_LOW; +			port->reset_name = kasprintf(GFP_KERNEL, +				     "pcie%d.%d-reset", port->port, port->lane); +			of_property_read_u32(child, "reset-delay-us", +					     &reset_udelay); + +			ret = devm_gpio_request_one(&pdev->dev, +			    port->reset_gpio, GPIOF_DIR_OUT, port->reset_name); +			if (ret) { +				if (ret == -EPROBE_DEFER) +					return ret; +				continue; +			} + +			gpio_set_value(port->reset_gpio, +				       (port->reset_active_low) ? 1 : 0); +			msleep(reset_udelay/1000); +		} + +		port->clk = of_clk_get_by_name(child, NULL); +		if (IS_ERR(port->clk)) { +			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", +			       port->port, port->lane);  			continue;  		} +		ret = clk_prepare_enable(port->clk); +		if (ret) +			continue; +  		port->base = mvebu_pcie_map_registers(pdev, child, port);  		if (IS_ERR(port->base)) {  			dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",  				port->port, port->lane);  			port->base = NULL; +			clk_disable_unprepare(port->clk);  			continue;  		}  		mvebu_pcie_set_local_dev_nr(port, 1); -		if (mvebu_pcie_link_up(port)) { -			port->haslink = 1; -			dev_info(&pdev->dev, "PCIe%d.%d: link up\n", -				 port->port, port->lane); -		} else { -			port->haslink = 0; -			dev_info(&pdev->dev, "PCIe%d.%d: link down\n", -				 port->port, port->lane); -		} - -		port->clk = of_clk_get_by_name(child, NULL); -		if (IS_ERR(port->clk)) { -			dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n", -			       port->port, port->lane); -			iounmap(port->base); -			port->haslink = 0; -			continue; -		} -  		port->dn = child; - -		clk_prepare_enable(port->clk); -		spin_lock_init(&port->conf_lock); -  		mvebu_sw_pci_bridge_init(port); -  		i++;  	} +	pcie->nports = i; + +	for (i = 0; i < (IO_SPACE_LIMIT - SZ_64K); i += SZ_64K) +		pci_ioremap_io(i, pcie->io.start + i); + +	mvebu_pcie_msi_enable(pcie);  	mvebu_pcie_enable(pcie);  	return 0; @@ -920,6 +1074,7 @@ static int __init mvebu_pcie_probe(struct platform_device *pdev)  static const struct of_device_id mvebu_pcie_of_match_table[] = {  	{ .compatible = "marvell,armada-xp-pcie", },  	{ .compatible = "marvell,armada-370-pcie", }, +	{ .compatible = "marvell,dove-pcie", },  	{ .compatible = "marvell,kirkwood-pcie", },  	{},  }; @@ -929,18 +1084,13 @@ static struct platform_driver mvebu_pcie_driver = {  	.driver = {  		.owner = THIS_MODULE,  		.name = "mvebu-pcie", -		.of_match_table = -		   of_match_ptr(mvebu_pcie_of_match_table), +		.of_match_table = mvebu_pcie_of_match_table, +		/* driver unloading/unbinding currently not supported */ +		.suppress_bind_attrs = true,  	}, +	.probe = mvebu_pcie_probe,  }; - -static int __init mvebu_pcie_init(void) -{ -	return platform_driver_probe(&mvebu_pcie_driver, -				     mvebu_pcie_probe); -} - -subsys_initcall(mvebu_pcie_init); +module_platform_driver(mvebu_pcie_driver);  MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");  MODULE_DESCRIPTION("Marvell EBU PCIe driver"); diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c new file mode 100644 index 00000000000..3ef854f5a5b --- /dev/null +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -0,0 +1,426 @@ +/* + *  pci-rcar-gen2: internal PCI bus support + * + * Copyright (C) 2013 Renesas Solutions Corp. + * Copyright (C) 2013 Cogent Embedded, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of_pci.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/sizes.h> +#include <linux/slab.h> + +/* AHB-PCI Bridge PCI communication registers */ +#define RCAR_AHBPCI_PCICOM_OFFSET	0x800 + +#define RCAR_PCIAHB_WIN1_CTR_REG	(RCAR_AHBPCI_PCICOM_OFFSET + 0x00) +#define RCAR_PCIAHB_WIN2_CTR_REG	(RCAR_AHBPCI_PCICOM_OFFSET + 0x04) +#define RCAR_PCIAHB_PREFETCH0		0x0 +#define RCAR_PCIAHB_PREFETCH4		0x1 +#define RCAR_PCIAHB_PREFETCH8		0x2 +#define RCAR_PCIAHB_PREFETCH16		0x3 + +#define RCAR_AHBPCI_WIN1_CTR_REG	(RCAR_AHBPCI_PCICOM_OFFSET + 0x10) +#define RCAR_AHBPCI_WIN2_CTR_REG	(RCAR_AHBPCI_PCICOM_OFFSET + 0x14) +#define RCAR_AHBPCI_WIN_CTR_MEM		(3 << 1) +#define RCAR_AHBPCI_WIN_CTR_CFG		(5 << 1) +#define RCAR_AHBPCI_WIN1_HOST		(1 << 30) +#define RCAR_AHBPCI_WIN1_DEVICE		(1 << 31) + +#define RCAR_PCI_INT_ENABLE_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x20) +#define RCAR_PCI_INT_STATUS_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x24) +#define RCAR_PCI_INT_SIGTABORT		(1 << 0) +#define RCAR_PCI_INT_SIGRETABORT	(1 << 1) +#define RCAR_PCI_INT_REMABORT		(1 << 2) +#define RCAR_PCI_INT_PERR		(1 << 3) +#define RCAR_PCI_INT_SIGSERR		(1 << 4) +#define RCAR_PCI_INT_RESERR		(1 << 5) +#define RCAR_PCI_INT_WIN1ERR		(1 << 12) +#define RCAR_PCI_INT_WIN2ERR		(1 << 13) +#define RCAR_PCI_INT_A			(1 << 16) +#define RCAR_PCI_INT_B			(1 << 17) +#define RCAR_PCI_INT_PME		(1 << 19) +#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT		| \ +				RCAR_PCI_INT_SIGRETABORT	| \ +				RCAR_PCI_INT_SIGRETABORT	| \ +				RCAR_PCI_INT_REMABORT		| \ +				RCAR_PCI_INT_PERR		| \ +				RCAR_PCI_INT_SIGSERR		| \ +				RCAR_PCI_INT_RESERR		| \ +				RCAR_PCI_INT_WIN1ERR		| \ +				RCAR_PCI_INT_WIN2ERR) + +#define RCAR_AHB_BUS_CTR_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x30) +#define RCAR_AHB_BUS_MMODE_HTRANS	(1 << 0) +#define RCAR_AHB_BUS_MMODE_BYTE_BURST	(1 << 1) +#define RCAR_AHB_BUS_MMODE_WR_INCR	(1 << 2) +#define RCAR_AHB_BUS_MMODE_HBUS_REQ	(1 << 7) +#define RCAR_AHB_BUS_SMODE_READYCTR	(1 << 17) +#define RCAR_AHB_BUS_MODE		(RCAR_AHB_BUS_MMODE_HTRANS |	\ +					RCAR_AHB_BUS_MMODE_BYTE_BURST |	\ +					RCAR_AHB_BUS_MMODE_WR_INCR |	\ +					RCAR_AHB_BUS_MMODE_HBUS_REQ |	\ +					RCAR_AHB_BUS_SMODE_READYCTR) + +#define RCAR_USBCTR_REG			(RCAR_AHBPCI_PCICOM_OFFSET + 0x34) +#define RCAR_USBCTR_USBH_RST		(1 << 0) +#define RCAR_USBCTR_PCICLK_MASK		(1 << 1) +#define RCAR_USBCTR_PLL_RST		(1 << 2) +#define RCAR_USBCTR_DIRPD		(1 << 8) +#define RCAR_USBCTR_PCIAHB_WIN2_EN	(1 << 9) +#define RCAR_USBCTR_PCIAHB_WIN1_256M	(0 << 10) +#define RCAR_USBCTR_PCIAHB_WIN1_512M	(1 << 10) +#define RCAR_USBCTR_PCIAHB_WIN1_1G	(2 << 10) +#define RCAR_USBCTR_PCIAHB_WIN1_2G	(3 << 10) +#define RCAR_USBCTR_PCIAHB_WIN1_MASK	(3 << 10) + +#define RCAR_PCI_ARBITER_CTR_REG	(RCAR_AHBPCI_PCICOM_OFFSET + 0x40) +#define RCAR_PCI_ARBITER_PCIREQ0	(1 << 0) +#define RCAR_PCI_ARBITER_PCIREQ1	(1 << 1) +#define RCAR_PCI_ARBITER_PCIBP_MODE	(1 << 12) + +#define RCAR_PCI_UNIT_REV_REG		(RCAR_AHBPCI_PCICOM_OFFSET + 0x48) + +struct rcar_pci_priv { +	struct device *dev; +	void __iomem *reg; +	struct resource io_res; +	struct resource mem_res; +	struct resource *cfg_res; +	unsigned busnr; +	int irq; +	unsigned long window_size; +}; + +/* PCI configuration space operations */ +static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn, +				       int where) +{ +	struct pci_sys_data *sys = bus->sysdata; +	struct rcar_pci_priv *priv = sys->private_data; +	int slot, val; + +	if (sys->busnr != bus->number || PCI_FUNC(devfn)) +		return NULL; + +	/* Only one EHCI/OHCI device built-in */ +	slot = PCI_SLOT(devfn); +	if (slot > 2) +		return NULL; + +	/* bridge logic only has registers to 0x40 */ +	if (slot == 0x0 && where >= 0x40) +		return NULL; + +	val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG : +		     RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG; + +	iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); +	return priv->reg + (slot >> 1) * 0x100 + where; +} + +static int rcar_pci_read_config(struct pci_bus *bus, unsigned int devfn, +				int where, int size, u32 *val) +{ +	void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where); + +	if (!reg) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	switch (size) { +	case 1: +		*val = ioread8(reg); +		break; +	case 2: +		*val = ioread16(reg); +		break; +	default: +		*val = ioread32(reg); +		break; +	} + +	return PCIBIOS_SUCCESSFUL; +} + +static int rcar_pci_write_config(struct pci_bus *bus, unsigned int devfn, +				 int where, int size, u32 val) +{ +	void __iomem *reg = rcar_pci_cfg_base(bus, devfn, where); + +	if (!reg) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	switch (size) { +	case 1: +		iowrite8(val, reg); +		break; +	case 2: +		iowrite16(val, reg); +		break; +	default: +		iowrite32(val, reg); +		break; +	} + +	return PCIBIOS_SUCCESSFUL; +} + +/* PCI interrupt mapping */ +static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ +	struct pci_sys_data *sys = dev->bus->sysdata; +	struct rcar_pci_priv *priv = sys->private_data; +	int irq; + +	irq = of_irq_parse_and_map_pci(dev, slot, pin); +	if (!irq) +		irq = priv->irq; + +	return irq; +} + +#ifdef CONFIG_PCI_DEBUG +/* if debug enabled, then attach an error handler irq to the bridge */ + +static irqreturn_t rcar_pci_err_irq(int irq, void *pw) +{ +	struct rcar_pci_priv *priv = pw; +	u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG); + +	if (status & RCAR_PCI_INT_ALLERRORS) { +		dev_err(priv->dev, "error irq: status %08x\n", status); + +		/* clear the error(s) */ +		iowrite32(status & RCAR_PCI_INT_ALLERRORS, +			  priv->reg + RCAR_PCI_INT_STATUS_REG); +		return IRQ_HANDLED; +	} + +	return IRQ_NONE; +} + +static void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) +{ +	int ret; +	u32 val; + +	ret = devm_request_irq(priv->dev, priv->irq, rcar_pci_err_irq, +			       IRQF_SHARED, "error irq", priv); +	if (ret) { +		dev_err(priv->dev, "cannot claim IRQ for error handling\n"); +		return; +	} + +	val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG); +	val |= RCAR_PCI_INT_ALLERRORS; +	iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG); +} +#else +static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { } +#endif + +/* PCI host controller setup */ +static int rcar_pci_setup(int nr, struct pci_sys_data *sys) +{ +	struct rcar_pci_priv *priv = sys->private_data; +	void __iomem *reg = priv->reg; +	u32 val; + +	pm_runtime_enable(priv->dev); +	pm_runtime_get_sync(priv->dev); + +	val = ioread32(reg + RCAR_PCI_UNIT_REV_REG); +	dev_info(priv->dev, "PCI: bus%u revision %x\n", sys->busnr, val); + +	/* Disable Direct Power Down State and assert reset */ +	val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD; +	val |= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST; +	iowrite32(val, reg + RCAR_USBCTR_REG); +	udelay(4); + +	/* De-assert reset and reset PCIAHB window1 size */ +	val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK | +		 RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST); + +	/* Setup PCIAHB window1 size */ +	switch (priv->window_size) { +	case SZ_2G: +		val |= RCAR_USBCTR_PCIAHB_WIN1_2G; +		break; +	case SZ_1G: +		val |= RCAR_USBCTR_PCIAHB_WIN1_1G; +		break; +	case SZ_512M: +		val |= RCAR_USBCTR_PCIAHB_WIN1_512M; +		break; +	default: +		pr_warn("unknown window size %ld - defaulting to 256M\n", +			priv->window_size); +		priv->window_size = SZ_256M; +		/* fall-through */ +	case SZ_256M: +		val |= RCAR_USBCTR_PCIAHB_WIN1_256M; +		break; +	} +	iowrite32(val, reg + RCAR_USBCTR_REG); + +	/* Configure AHB master and slave modes */ +	iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG); + +	/* Configure PCI arbiter */ +	val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG); +	val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 | +	       RCAR_PCI_ARBITER_PCIBP_MODE; +	iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); + +	/* PCI-AHB mapping: 0x40000000 base */ +	iowrite32(0x40000000 | RCAR_PCIAHB_PREFETCH16, +		  reg + RCAR_PCIAHB_WIN1_CTR_REG); + +	/* AHB-PCI mapping: OHCI/EHCI registers */ +	val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM; +	iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG); + +	/* Enable AHB-PCI bridge PCI configuration access */ +	iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, +		  reg + RCAR_AHBPCI_WIN1_CTR_REG); +	/* Set PCI-AHB Window1 address */ +	iowrite32(0x40000000 | PCI_BASE_ADDRESS_MEM_PREFETCH, +		  reg + PCI_BASE_ADDRESS_1); +	/* Set AHB-PCI bridge PCI communication area address */ +	val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; +	iowrite32(val, reg + PCI_BASE_ADDRESS_0); + +	val = ioread32(reg + PCI_COMMAND); +	val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | +	       PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; +	iowrite32(val, reg + PCI_COMMAND); + +	/* Enable PCI interrupts */ +	iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, +		  reg + RCAR_PCI_INT_ENABLE_REG); + +	if (priv->irq > 0) +		rcar_pci_setup_errirq(priv); + +	/* Add PCI resources */ +	pci_add_resource(&sys->resources, &priv->io_res); +	pci_add_resource(&sys->resources, &priv->mem_res); + +	/* Setup bus number based on platform device id / of bus-range */ +	sys->busnr = priv->busnr; +	return 1; +} + +static struct pci_ops rcar_pci_ops = { +	.read	= rcar_pci_read_config, +	.write	= rcar_pci_write_config, +}; + +static int rcar_pci_probe(struct platform_device *pdev) +{ +	struct resource *cfg_res, *mem_res; +	struct rcar_pci_priv *priv; +	void __iomem *reg; +	struct hw_pci hw; +	void *hw_private[1]; + +	cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +	reg = devm_ioremap_resource(&pdev->dev, cfg_res); +	if (IS_ERR(reg)) +		return PTR_ERR(reg); + +	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); +	if (!mem_res || !mem_res->start) +		return -ENODEV; + +	priv = devm_kzalloc(&pdev->dev, +			    sizeof(struct rcar_pci_priv), GFP_KERNEL); +	if (!priv) +		return -ENOMEM; + +	priv->mem_res = *mem_res; +	/* +	 * The controller does not support/use port I/O, +	 * so setup a dummy port I/O region here. +	 */ +	priv->io_res.start = priv->mem_res.start; +	priv->io_res.end = priv->mem_res.end; +	priv->io_res.flags = IORESOURCE_IO; + +	priv->cfg_res = cfg_res; + +	priv->irq = platform_get_irq(pdev, 0); +	priv->reg = reg; +	priv->dev = &pdev->dev; + +	if (priv->irq < 0) { +		dev_err(&pdev->dev, "no valid irq found\n"); +		return priv->irq; +	} + +	priv->window_size = SZ_1G; + +	if (pdev->dev.of_node) { +		struct resource busnr; +		int ret; + +		ret = of_pci_parse_bus_range(pdev->dev.of_node, &busnr); +		if (ret < 0) { +			dev_err(&pdev->dev, "failed to parse bus-range\n"); +			return ret; +		} + +		priv->busnr = busnr.start; +		if (busnr.end != busnr.start) +			dev_warn(&pdev->dev, "only one bus number supported\n"); +	} else { +		priv->busnr = pdev->id; +	} + +	hw_private[0] = priv; +	memset(&hw, 0, sizeof(hw)); +	hw.nr_controllers = ARRAY_SIZE(hw_private); +	hw.private_data = hw_private; +	hw.map_irq = rcar_pci_map_irq; +	hw.ops = &rcar_pci_ops; +	hw.setup = rcar_pci_setup; +	pci_common_init_dev(&pdev->dev, &hw); +	return 0; +} + +static struct of_device_id rcar_pci_of_match[] = { +	{ .compatible = "renesas,pci-r8a7790", }, +	{ .compatible = "renesas,pci-r8a7791", }, +	{ }, +}; + +MODULE_DEVICE_TABLE(of, rcar_pci_of_match); + +static struct platform_driver rcar_pci_driver = { +	.driver = { +		.name = "pci-rcar-gen2", +		.owner = THIS_MODULE, +		.suppress_bind_attrs = true, +		.of_match_table = rcar_pci_of_match, +	}, +	.probe = rcar_pci_probe, +}; + +module_platform_driver(rcar_pci_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI"); +MODULE_AUTHOR("Valentine Barshak <valentine.barshak@cogentembedded.com>"); diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 2e9888a0635..083cf37ca04 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -25,7 +25,6 @@   */  #include <linux/clk.h> -#include <linux/clk/tegra.h>  #include <linux/delay.h>  #include <linux/export.h>  #include <linux/interrupt.h> @@ -39,6 +38,7 @@  #include <linux/of_platform.h>  #include <linux/pci.h>  #include <linux/platform_device.h> +#include <linux/reset.h>  #include <linux/sizes.h>  #include <linux/slab.h>  #include <linux/tegra-cpuidle.h> @@ -249,7 +249,7 @@ struct tegra_pcie {  	void __iomem *afi;  	int irq; -	struct list_head busses; +	struct list_head buses;  	struct resource *cs;  	struct resource io; @@ -259,10 +259,13 @@ struct tegra_pcie {  	struct clk *pex_clk;  	struct clk *afi_clk; -	struct clk *pcie_xclk;  	struct clk *pll_e;  	struct clk *cml_clk; +	struct reset_control *pex_rst; +	struct reset_control *afi_rst; +	struct reset_control *pcie_xrst; +  	struct tegra_msi msi;  	struct list_head ports; @@ -399,24 +402,24 @@ free:  /*   * Look up a virtual address mapping for the specified bus number. If no such - * mapping existis, try to create one. + * mapping exists, try to create one.   */  static void __iomem *tegra_pcie_bus_map(struct tegra_pcie *pcie,  					unsigned int busnr)  {  	struct tegra_pcie_bus *bus; -	list_for_each_entry(bus, &pcie->busses, list) +	list_for_each_entry(bus, &pcie->buses, list)  		if (bus->nr == busnr) -			return bus->area->addr; +			return (void __iomem *)bus->area->addr;  	bus = tegra_pcie_bus_alloc(pcie, busnr);  	if (IS_ERR(bus))  		return NULL; -	list_add_tail(&bus->list, &pcie->busses); +	list_add_tail(&bus->list, &pcie->buses); -	return bus->area->addr; +	return (void __iomem *)bus->area->addr;  }  static void __iomem *tegra_pcie_conf_address(struct pci_bus *bus, @@ -636,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)  static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin)  {  	struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); +	int irq;  	tegra_cpuidle_pcie_irqs_in_use(); -	return pcie->irq; +	irq = of_irq_parse_and_map_pci(pdev, slot, pin); +	if (!irq) +		irq = pcie->irq; + +	return irq;  }  static void tegra_pcie_add_bus(struct pci_bus *bus) @@ -805,10 +813,10 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)  	afi_writel(pcie, value, AFI_PCIE_CONFIG);  	value = afi_readl(pcie, AFI_FUSE); -	value &= ~AFI_FUSE_PCIE_T0_GEN2_DIS; +	value |= AFI_FUSE_PCIE_T0_GEN2_DIS;  	afi_writel(pcie, value, AFI_FUSE); -	/* initialze internal PHY, enable up to 16 PCIE lanes */ +	/* initialize internal PHY, enable up to 16 PCIE lanes */  	pads_writel(pcie, 0x0, PADS_CTL_SEL);  	/* override IDDQ to 1 on all 4 lanes */ @@ -858,7 +866,7 @@ static int tegra_pcie_enable_controller(struct tegra_pcie *pcie)  	pads_writel(pcie, value, PADS_CTL);  	/* take the PCIe interface module out of reset */ -	tegra_periph_reset_deassert(pcie->pcie_xclk); +	reset_control_deassert(pcie->pcie_xrst);  	/* finally enable PCIe */  	value = afi_readl(pcie, AFI_CONFIGURATION); @@ -891,9 +899,9 @@ static void tegra_pcie_power_off(struct tegra_pcie *pcie)  	/* TODO: disable and unprepare clocks? */ -	tegra_periph_reset_assert(pcie->pcie_xclk); -	tegra_periph_reset_assert(pcie->afi_clk); -	tegra_periph_reset_assert(pcie->pex_clk); +	reset_control_assert(pcie->pcie_xrst); +	reset_control_assert(pcie->afi_rst); +	reset_control_assert(pcie->pex_rst);  	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); @@ -921,9 +929,9 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)  	const struct tegra_pcie_soc_data *soc = pcie->soc_data;  	int err; -	tegra_periph_reset_assert(pcie->pcie_xclk); -	tegra_periph_reset_assert(pcie->afi_clk); -	tegra_periph_reset_assert(pcie->pex_clk); +	reset_control_assert(pcie->pcie_xrst); +	reset_control_assert(pcie->afi_rst); +	reset_control_assert(pcie->pex_rst);  	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); @@ -952,13 +960,14 @@ static int tegra_pcie_power_on(struct tegra_pcie *pcie)  	}  	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, -						pcie->pex_clk); +						pcie->pex_clk, +						pcie->pex_rst);  	if (err) {  		dev_err(pcie->dev, "powerup sequence failed: %d\n", err);  		return err;  	} -	tegra_periph_reset_deassert(pcie->afi_clk); +	reset_control_deassert(pcie->afi_rst);  	err = clk_prepare_enable(pcie->afi_clk);  	if (err < 0) { @@ -996,10 +1005,6 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)  	if (IS_ERR(pcie->afi_clk))  		return PTR_ERR(pcie->afi_clk); -	pcie->pcie_xclk = devm_clk_get(pcie->dev, "pcie_xclk"); -	if (IS_ERR(pcie->pcie_xclk)) -		return PTR_ERR(pcie->pcie_xclk); -  	pcie->pll_e = devm_clk_get(pcie->dev, "pll_e");  	if (IS_ERR(pcie->pll_e))  		return PTR_ERR(pcie->pll_e); @@ -1013,6 +1018,23 @@ static int tegra_pcie_clocks_get(struct tegra_pcie *pcie)  	return 0;  } +static int tegra_pcie_resets_get(struct tegra_pcie *pcie) +{ +	pcie->pex_rst = devm_reset_control_get(pcie->dev, "pex"); +	if (IS_ERR(pcie->pex_rst)) +		return PTR_ERR(pcie->pex_rst); + +	pcie->afi_rst = devm_reset_control_get(pcie->dev, "afi"); +	if (IS_ERR(pcie->afi_rst)) +		return PTR_ERR(pcie->afi_rst); + +	pcie->pcie_xrst = devm_reset_control_get(pcie->dev, "pcie_x"); +	if (IS_ERR(pcie->pcie_xrst)) +		return PTR_ERR(pcie->pcie_xrst); + +	return 0; +} +  static int tegra_pcie_get_resources(struct tegra_pcie *pcie)  {  	struct platform_device *pdev = to_platform_device(pcie->dev); @@ -1025,6 +1047,12 @@ static int tegra_pcie_get_resources(struct tegra_pcie *pcie)  		return err;  	} +	err = tegra_pcie_resets_get(pcie); +	if (err) { +		dev_err(&pdev->dev, "failed to get resets: %d\n", err); +		return err; +	} +  	err = tegra_pcie_power_on(pcie);  	if (err) {  		dev_err(&pdev->dev, "failed to power up: %d\n", err); @@ -1624,7 +1652,7 @@ static int tegra_pcie_probe(struct platform_device *pdev)  	if (!pcie)  		return -ENOMEM; -	INIT_LIST_HEAD(&pcie->busses); +	INIT_LIST_HEAD(&pcie->buses);  	INIT_LIST_HEAD(&pcie->ports);  	pcie->soc_data = match->data;  	pcie->dev = &pdev->dev; diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index c10e9ac9bbb..1eaf4df3618 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -11,9 +11,13 @@   * published by the Free Software Foundation.   */ +#include <linux/irq.h> +#include <linux/irqdomain.h>  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/msi.h>  #include <linux/of_address.h> +#include <linux/of_pci.h>  #include <linux/pci.h>  #include <linux/pci_regs.h>  #include <linux/types.h> @@ -64,14 +68,14 @@  static struct hw_pci dw_pci; -unsigned long global_io_offset; +static unsigned long global_io_offset;  static inline struct pcie_port *sys_to_pcie(struct pci_sys_data *sys)  {  	return sys->private_data;  } -int cfg_read(void __iomem *addr, int where, int size, u32 *val) +int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val)  {  	*val = readl(addr); @@ -85,7 +89,7 @@ int cfg_read(void __iomem *addr, int where, int size, u32 *val)  	return PCIBIOS_SUCCESSFUL;  } -int cfg_write(void __iomem *addr, int where, int size, u32 val) +int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val)  {  	if (size == 4)  		writel(val, addr); @@ -115,33 +119,258 @@ static inline void dw_pcie_writel_rc(struct pcie_port *pp, u32 val, u32 reg)  		writel(val, pp->dbi_base + reg);  } -int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, -				u32 *val) +static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, +			       u32 *val)  {  	int ret;  	if (pp->ops->rd_own_conf)  		ret = pp->ops->rd_own_conf(pp, where, size, val);  	else -		ret = cfg_read(pp->dbi_base + (where & ~0x3), where, size, val); +		ret = dw_pcie_cfg_read(pp->dbi_base + (where & ~0x3), where, +				size, val);  	return ret;  } -int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, -				u32 val) +static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, +			       u32 val)  {  	int ret;  	if (pp->ops->wr_own_conf)  		ret = pp->ops->wr_own_conf(pp, where, size, val);  	else -		ret = cfg_write(pp->dbi_base + (where & ~0x3), where, size, -				val); +		ret = dw_pcie_cfg_write(pp->dbi_base + (where & ~0x3), where, +				size, val);  	return ret;  } +static struct irq_chip dw_msi_irq_chip = { +	.name = "PCI-MSI", +	.irq_enable = unmask_msi_irq, +	.irq_disable = mask_msi_irq, +	.irq_mask = mask_msi_irq, +	.irq_unmask = unmask_msi_irq, +}; + +/* MSI int handler */ +irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) +{ +	unsigned long val; +	int i, pos, irq; +	irqreturn_t ret = IRQ_NONE; + +	for (i = 0; i < MAX_MSI_CTRLS; i++) { +		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, +				(u32 *)&val); +		if (val) { +			ret = IRQ_HANDLED; +			pos = 0; +			while ((pos = find_next_bit(&val, 32, pos)) != 32) { +				irq = irq_find_mapping(pp->irq_domain, +						i * 32 + pos); +				dw_pcie_wr_own_conf(pp, +						PCIE_MSI_INTR0_STATUS + i * 12, +						4, 1 << pos); +				generic_handle_irq(irq); +				pos++; +			} +		} +	} + +	return ret; +} + +void dw_pcie_msi_init(struct pcie_port *pp) +{ +	pp->msi_data = __get_free_pages(GFP_KERNEL, 0); + +	/* program the msi_data */ +	dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, +			virt_to_phys((void *)pp->msi_data)); +	dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0); +} + +static int find_valid_pos0(struct pcie_port *pp, int msgvec, int pos, int *pos0) +{ +	int flag = 1; + +	do { +		pos = find_next_zero_bit(pp->msi_irq_in_use, +				MAX_MSI_IRQS, pos); +		/*if you have reached to the end then get out from here.*/ +		if (pos == MAX_MSI_IRQS) +			return -ENOSPC; +		/* +		 * Check if this position is at correct offset.nvec is always a +		 * power of two. pos0 must be nvec bit aligned. +		 */ +		if (pos % msgvec) +			pos += msgvec - (pos % msgvec); +		else +			flag = 0; +	} while (flag); + +	*pos0 = pos; +	return 0; +} + +static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base, +			    unsigned int nvec, unsigned int pos) +{ +	unsigned int i, res, bit, val; + +	for (i = 0; i < nvec; i++) { +		irq_set_msi_desc_off(irq_base, i, NULL); +		clear_bit(pos + i, pp->msi_irq_in_use); +		/* Disable corresponding interrupt on MSI controller */ +		res = ((pos + i) / 32) * 12; +		bit = (pos + i) % 32; +		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); +		val &= ~(1 << bit); +		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); +	} +} + +static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos) +{ +	int res, bit, irq, pos0, pos1, i; +	u32 val; +	struct pcie_port *pp = sys_to_pcie(desc->dev->bus->sysdata); + +	if (!pp) { +		BUG(); +		return -EINVAL; +	} + +	pos0 = find_first_zero_bit(pp->msi_irq_in_use, +			MAX_MSI_IRQS); +	if (pos0 % no_irqs) { +		if (find_valid_pos0(pp, no_irqs, pos0, &pos0)) +			goto no_valid_irq; +	} +	if (no_irqs > 1) { +		pos1 = find_next_bit(pp->msi_irq_in_use, +				MAX_MSI_IRQS, pos0); +		/* there must be nvec number of consecutive free bits */ +		while ((pos1 - pos0) < no_irqs) { +			if (find_valid_pos0(pp, no_irqs, pos1, &pos0)) +				goto no_valid_irq; +			pos1 = find_next_bit(pp->msi_irq_in_use, +					MAX_MSI_IRQS, pos0); +		} +	} + +	irq = irq_find_mapping(pp->irq_domain, pos0); +	if (!irq) +		goto no_valid_irq; + +	/* +	 * irq_create_mapping (called from dw_pcie_host_init) pre-allocates +	 * descs so there is no need to allocate descs here. We can therefore +	 * assume that if irq_find_mapping above returns non-zero, then the +	 * descs are also successfully allocated. +	 */ + +	for (i = 0; i < no_irqs; i++) { +		if (irq_set_msi_desc_off(irq, i, desc) != 0) { +			clear_irq_range(pp, irq, i, pos0); +			goto no_valid_irq; +		} +		set_bit(pos0 + i, pp->msi_irq_in_use); +		/*Enable corresponding interrupt in MSI interrupt controller */ +		res = ((pos0 + i) / 32) * 12; +		bit = (pos0 + i) % 32; +		dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val); +		val |= 1 << bit; +		dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val); +	} + +	*pos = pos0; +	return irq; + +no_valid_irq: +	*pos = pos0; +	return -ENOSPC; +} + +static void clear_irq(unsigned int irq) +{ +	unsigned int pos, nvec; +	struct msi_desc *msi; +	struct pcie_port *pp; +	struct irq_data *data = irq_get_irq_data(irq); + +	/* get the port structure */ +	msi = irq_data_get_msi(data); +	pp = sys_to_pcie(msi->dev->bus->sysdata); +	if (!pp) { +		BUG(); +		return; +	} + +	/* undo what was done in assign_irq */ +	pos = data->hwirq; +	nvec = 1 << msi->msi_attrib.multiple; + +	clear_irq_range(pp, irq, nvec, pos); + +	/* all irqs cleared; reset attributes */ +	msi->irq = 0; +	msi->msi_attrib.multiple = 0; +} + +static int dw_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +			struct msi_desc *desc) +{ +	int irq, pos, msgvec; +	u16 msg_ctr; +	struct msi_msg msg; +	struct pcie_port *pp = sys_to_pcie(pdev->bus->sysdata); + +	if (!pp) { +		BUG(); +		return -EINVAL; +	} + +	pci_read_config_word(pdev, desc->msi_attrib.pos+PCI_MSI_FLAGS, +				&msg_ctr); +	msgvec = (msg_ctr&PCI_MSI_FLAGS_QSIZE) >> 4; +	if (msgvec == 0) +		msgvec = (msg_ctr & PCI_MSI_FLAGS_QMASK) >> 1; +	if (msgvec > 5) +		msgvec = 0; + +	irq = assign_irq((1 << msgvec), desc, &pos); +	if (irq < 0) +		return irq; + +	/* +	 * write_msi_msg() will update PCI_MSI_FLAGS so there is +	 * no need to explicitly call pci_write_config_word(). +	 */ +	desc->msi_attrib.multiple = msgvec; + +	msg.address_lo = virt_to_phys((void *)pp->msi_data); +	msg.address_hi = 0x0; +	msg.data = pos; +	write_msi_msg(irq, &msg); + +	return 0; +} + +static void dw_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) +{ +	clear_irq(irq); +} + +static struct msi_chip dw_pcie_msi_chip = { +	.setup_irq = dw_msi_setup_irq, +	.teardown_irq = dw_msi_teardown_irq, +}; +  int dw_pcie_link_up(struct pcie_port *pp)  {  	if (pp->ops->link_up) @@ -150,12 +379,27 @@ int dw_pcie_link_up(struct pcie_port *pp)  		return 0;  } +static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq, +			irq_hw_number_t hwirq) +{ +	irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq); +	irq_set_chip_data(irq, domain->host_data); +	set_irq_flags(irq, IRQF_VALID); + +	return 0; +} + +static const struct irq_domain_ops msi_domain_ops = { +	.map = dw_pcie_msi_map, +}; +  int __init dw_pcie_host_init(struct pcie_port *pp)  {  	struct device_node *np = pp->dev->of_node;  	struct of_pci_range range;  	struct of_pci_range_parser parser;  	u32 val; +	int i;  	if (of_pci_range_parser_init(&parser, np)) {  		dev_err(pp->dev, "missing ranges property\n"); @@ -177,6 +421,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)  					   + global_io_offset);  			pp->config.io_size = resource_size(&pp->io);  			pp->config.io_bus_addr = range.pci_addr; +			pp->io_base = range.cpu_addr;  		}  		if (restype == IORESOURCE_MEM) {  			of_pci_range_to_resource(&range, np, &pp->mem); @@ -202,7 +447,6 @@ int __init dw_pcie_host_init(struct pcie_port *pp)  	pp->cfg0_base = pp->cfg.start;  	pp->cfg1_base = pp->cfg.start + pp->config.cfg0_size; -	pp->io_base = pp->io.start;  	pp->mem_base = pp->mem.start;  	pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, @@ -223,6 +467,19 @@ int __init dw_pcie_host_init(struct pcie_port *pp)  		return -EINVAL;  	} +	if (IS_ENABLED(CONFIG_PCI_MSI)) { +		pp->irq_domain = irq_domain_add_linear(pp->dev->of_node, +					MAX_MSI_IRQS, &msi_domain_ops, +					&dw_pcie_msi_chip); +		if (!pp->irq_domain) { +			dev_err(pp->dev, "irq domain init failed\n"); +			return -ENXIO; +		} + +		for (i = 0; i < MAX_MSI_IRQS; i++) +			irq_create_mapping(pp->irq_domain, i); +	} +  	if (pp->ops->host_init)  		pp->ops->host_init(pp); @@ -238,7 +495,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp)  	dw_pci.nr_controllers = 1;  	dw_pci.private_data = (void **)&pp; -	pci_common_init(&dw_pci); +	pci_common_init_dev(pp->dev, &dw_pci);  	pci_assign_unassigned_resources();  #ifdef CONFIG_PCI_DOMAINS  	dw_pci.domain++; @@ -268,13 +525,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)  	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,  			  PCIE_ATU_VIEWPORT);  	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); -	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);  	dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE);  	dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE);  	dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1,  			  PCIE_ATU_LIMIT);  	dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET);  	dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); +	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);  }  static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) @@ -283,7 +540,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)  	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0,  			  PCIE_ATU_VIEWPORT);  	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); -	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);  	dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE);  	dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE);  	dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, @@ -291,6 +547,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp)  	dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET);  	dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr),  			  PCIE_ATU_UPPER_TARGET); +	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);  }  static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) @@ -299,7 +556,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)  	dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1,  			  PCIE_ATU_VIEWPORT);  	dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); -	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);  	dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE);  	dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE);  	dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, @@ -307,6 +563,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp)  	dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET);  	dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr),  			  PCIE_ATU_UPPER_TARGET); +	dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2);  }  static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, @@ -321,11 +578,13 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,  	if (bus->parent->number == pp->root_bus_nr) {  		dw_pcie_prog_viewport_cfg0(pp, busdev); -		ret = cfg_read(pp->va_cfg0_base + address, where, size, val); +		ret = dw_pcie_cfg_read(pp->va_cfg0_base + address, where, size, +				val);  		dw_pcie_prog_viewport_mem_outbound(pp);  	} else {  		dw_pcie_prog_viewport_cfg1(pp, busdev); -		ret = cfg_read(pp->va_cfg1_base + address, where, size, val); +		ret = dw_pcie_cfg_read(pp->va_cfg1_base + address, where, size, +				val);  		dw_pcie_prog_viewport_io_outbound(pp);  	} @@ -344,18 +603,19 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,  	if (bus->parent->number == pp->root_bus_nr) {  		dw_pcie_prog_viewport_cfg0(pp, busdev); -		ret = cfg_write(pp->va_cfg0_base + address, where, size, val); +		ret = dw_pcie_cfg_write(pp->va_cfg0_base + address, where, size, +				val);  		dw_pcie_prog_viewport_mem_outbound(pp);  	} else {  		dw_pcie_prog_viewport_cfg1(pp, busdev); -		ret = cfg_write(pp->va_cfg1_base + address, where, size, val); +		ret = dw_pcie_cfg_write(pp->va_cfg1_base + address, where, size, +				val);  		dw_pcie_prog_viewport_io_outbound(pp);  	}  	return ret;  } -  static int dw_pcie_valid_config(struct pcie_port *pp,  				struct pci_bus *bus, int dev)  { @@ -383,7 +643,6 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,  			int size, u32 *val)  {  	struct pcie_port *pp = sys_to_pcie(bus->sysdata); -	unsigned long flags;  	int ret;  	if (!pp) { @@ -396,13 +655,11 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,  		return PCIBIOS_DEVICE_NOT_FOUND;  	} -	spin_lock_irqsave(&pp->conf_lock, flags);  	if (bus->number != pp->root_bus_nr)  		ret = dw_pcie_rd_other_conf(pp, bus, devfn,  						where, size, val);  	else  		ret = dw_pcie_rd_own_conf(pp, where, size, val); -	spin_unlock_irqrestore(&pp->conf_lock, flags);  	return ret;  } @@ -411,7 +668,6 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  			int where, int size, u32 val)  {  	struct pcie_port *pp = sys_to_pcie(bus->sysdata); -	unsigned long flags;  	int ret;  	if (!pp) { @@ -422,13 +678,11 @@ static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,  	if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)  		return PCIBIOS_DEVICE_NOT_FOUND; -	spin_lock_irqsave(&pp->conf_lock, flags);  	if (bus->number != pp->root_bus_nr)  		ret = dw_pcie_wr_other_conf(pp, bus, devfn,  						where, size, val);  	else  		ret = dw_pcie_wr_own_conf(pp, where, size, val); -	spin_unlock_irqrestore(&pp->conf_lock, flags);  	return ret;  } @@ -438,7 +692,7 @@ static struct pci_ops dw_pcie_ops = {  	.write = dw_pcie_wr_conf,  }; -int dw_pcie_setup(int nr, struct pci_sys_data *sys) +static int dw_pcie_setup(int nr, struct pci_sys_data *sys)  {  	struct pcie_port *pp; @@ -449,7 +703,7 @@ int dw_pcie_setup(int nr, struct pci_sys_data *sys)  	if (global_io_offset < SZ_1M && pp->config.io_size > 0) {  		sys->io_offset = global_io_offset - pp->config.io_bus_addr; -		pci_ioremap_io(sys->io_offset, pp->io.start); +		pci_ioremap_io(global_io_offset, pp->io_base);  		global_io_offset += SZ_64K;  		pci_add_resource_offset(&sys->resources, &pp->io,  					sys->io_offset); @@ -461,14 +715,14 @@ int dw_pcie_setup(int nr, struct pci_sys_data *sys)  	return 1;  } -struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) +static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)  {  	struct pci_bus *bus;  	struct pcie_port *pp = sys_to_pcie(sys);  	if (pp) {  		pp->root_bus_nr = sys->busnr; -		bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops, +		bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops,  					sys, &sys->resources);  	} else {  		bus = NULL; @@ -478,17 +732,33 @@ struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys)  	return bus;  } -int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)  {  	struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); +	int irq; -	return pp->irq; +	irq = of_irq_parse_and_map_pci(dev, slot, pin); +	if (!irq) +		irq = pp->irq; + +	return irq; +} + +static void dw_pcie_add_bus(struct pci_bus *bus) +{ +	if (IS_ENABLED(CONFIG_PCI_MSI)) { +		struct pcie_port *pp = sys_to_pcie(bus->sysdata); + +		dw_pcie_msi_chip.dev = pp->dev; +		bus->msi = &dw_pcie_msi_chip; +	}  }  static struct hw_pci dw_pci = {  	.setup		= dw_pcie_setup,  	.scan		= dw_pcie_scan_bus,  	.map_irq	= dw_pcie_map_irq, +	.add_bus	= dw_pcie_add_bus,  };  void dw_pcie_setup_rc(struct pcie_port *pp) @@ -498,7 +768,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	u32 membase;  	u32 memlimit; -	/* set the number of lines as 4 */ +	/* set the number of lanes */  	dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val);  	val &= ~PORT_LINK_MODE_MASK;  	switch (pp->lanes) { @@ -532,7 +802,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  	/* setup RC BARs */  	dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_0); -	dw_pcie_writel_rc(pp, 0x00000004, PCI_BASE_ADDRESS_1); +	dw_pcie_writel_rc(pp, 0x00000000, PCI_BASE_ADDRESS_1);  	/* setup interrupt pins */  	dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE, &val); diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h index 133820f1da9..77f592faa7b 100644 --- a/drivers/pci/host/pcie-designware.h +++ b/drivers/pci/host/pcie-designware.h @@ -11,6 +11,9 @@   * published by the Free Software Foundation.   */ +#ifndef _PCIE_DESIGNWARE_H +#define _PCIE_DESIGNWARE_H +  struct pcie_port_info {  	u32		cfg0_size;  	u32		cfg1_size; @@ -20,6 +23,14 @@ struct pcie_port_info {  	phys_addr_t	mem_bus_addr;  }; +/* + * Maximum number of MSI IRQs can be 256 per controller. But keep + * it 32 as of now. Probably we will never need more than 32. If needed, + * then increment it in multiple of 32. + */ +#define MAX_MSI_IRQS			32 +#define MAX_MSI_CTRLS			(MAX_MSI_IRQS / 32) +  struct pcie_port {  	struct device		*dev;  	u8			root_bus_nr; @@ -30,7 +41,6 @@ struct pcie_port {  	void __iomem		*va_cfg1_base;  	u64			io_base;  	u64			mem_base; -	spinlock_t		conf_lock;  	struct resource		cfg;  	struct resource		io;  	struct resource		mem; @@ -38,6 +48,10 @@ struct pcie_port {  	int			irq;  	u32			lanes;  	struct pcie_host_ops	*ops; +	int			msi_irq; +	struct irq_domain	*irq_domain; +	unsigned long		msi_data; +	DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);  };  struct pcie_host_ops { @@ -51,15 +65,12 @@ struct pcie_host_ops {  	void (*host_init)(struct pcie_port *pp);  }; -extern unsigned long global_io_offset; - -int cfg_read(void __iomem *addr, int where, int size, u32 *val); -int cfg_write(void __iomem *addr, int where, int size, u32 val); -int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, u32 val); -int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val); +int dw_pcie_cfg_read(void __iomem *addr, int where, int size, u32 *val); +int dw_pcie_cfg_write(void __iomem *addr, int where, int size, u32 val); +irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); +void dw_pcie_msi_init(struct pcie_port *pp);  int dw_pcie_link_up(struct pcie_port *pp);  void dw_pcie_setup_rc(struct pcie_port *pp);  int dw_pcie_host_init(struct pcie_port *pp); -int dw_pcie_setup(int nr, struct pci_sys_data *sys); -struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys); -int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); + +#endif /* _PCIE_DESIGNWARE_H */ diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c new file mode 100644 index 00000000000..f7d3de32c9a --- /dev/null +++ b/drivers/pci/host/pcie-rcar.c @@ -0,0 +1,1006 @@ +/* + * PCIe driver for Renesas R-Car SoCs + *  Copyright (C) 2014 Renesas Electronics Europe Ltd + * + * Based on: + *  arch/sh/drivers/pci/pcie-sh7786.c + *  arch/sh/drivers/pci/ops-sh7786.c + *  Copyright (C) 2009 - 2011  Paul Mundt + * + * This file is licensed under the terms of the GNU General Public + * License version 2.  This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/irqdomain.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/msi.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_pci.h> +#include <linux/of_platform.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define DRV_NAME "rcar-pcie" + +#define PCIECAR			0x000010 +#define PCIECCTLR		0x000018 +#define  CONFIG_SEND_ENABLE	(1 << 31) +#define  TYPE0			(0 << 8) +#define  TYPE1			(1 << 8) +#define PCIECDR			0x000020 +#define PCIEMSR			0x000028 +#define PCIEINTXR		0x000400 +#define PCIEMSITXR		0x000840 + +/* Transfer control */ +#define PCIETCTLR		0x02000 +#define  CFINIT			1 +#define PCIETSTR		0x02004 +#define  DATA_LINK_ACTIVE	1 +#define PCIEERRFR		0x02020 +#define  UNSUPPORTED_REQUEST	(1 << 4) +#define PCIEMSIFR		0x02044 +#define PCIEMSIALR		0x02048 +#define  MSIFE			1 +#define PCIEMSIAUR		0x0204c +#define PCIEMSIIER		0x02050 + +/* root port address */ +#define PCIEPRAR(x)		(0x02080 + ((x) * 0x4)) + +/* local address reg & mask */ +#define PCIELAR(x)		(0x02200 + ((x) * 0x20)) +#define PCIELAMR(x)		(0x02208 + ((x) * 0x20)) +#define  LAM_PREFETCH		(1 << 3) +#define  LAM_64BIT		(1 << 2) +#define  LAR_ENABLE		(1 << 1) + +/* PCIe address reg & mask */ +#define PCIEPARL(x)		(0x03400 + ((x) * 0x20)) +#define PCIEPARH(x)		(0x03404 + ((x) * 0x20)) +#define PCIEPAMR(x)		(0x03408 + ((x) * 0x20)) +#define PCIEPTCTLR(x)		(0x0340c + ((x) * 0x20)) +#define  PAR_ENABLE		(1 << 31) +#define  IO_SPACE		(1 << 8) + +/* Configuration */ +#define PCICONF(x)		(0x010000 + ((x) * 0x4)) +#define PMCAP(x)		(0x010040 + ((x) * 0x4)) +#define EXPCAP(x)		(0x010070 + ((x) * 0x4)) +#define VCCAP(x)		(0x010100 + ((x) * 0x4)) + +/* link layer */ +#define IDSETR1			0x011004 +#define TLCTLR			0x011048 +#define MACSR			0x011054 +#define MACCTLR			0x011058 +#define  SCRAMBLE_DISABLE	(1 << 27) + +/* R-Car H1 PHY */ +#define H1_PCIEPHYADRR		0x04000c +#define  WRITE_CMD		(1 << 16) +#define  PHY_ACK		(1 << 24) +#define  RATE_POS		12 +#define  LANE_POS		8 +#define  ADR_POS		0 +#define H1_PCIEPHYDOUTR		0x040014 +#define H1_PCIEPHYSR		0x040018 + +#define INT_PCI_MSI_NR	32 + +#define RCONF(x)	(PCICONF(0)+(x)) +#define RPMCAP(x)	(PMCAP(0)+(x)) +#define REXPCAP(x)	(EXPCAP(0)+(x)) +#define RVCCAP(x)	(VCCAP(0)+(x)) + +#define  PCIE_CONF_BUS(b)	(((b) & 0xff) << 24) +#define  PCIE_CONF_DEV(d)	(((d) & 0x1f) << 19) +#define  PCIE_CONF_FUNC(f)	(((f) & 0x7) << 16) + +#define PCI_MAX_RESOURCES 4 +#define MAX_NR_INBOUND_MAPS 6 + +struct rcar_msi { +	DECLARE_BITMAP(used, INT_PCI_MSI_NR); +	struct irq_domain *domain; +	struct msi_chip chip; +	unsigned long pages; +	struct mutex lock; +	int irq1; +	int irq2; +}; + +static inline struct rcar_msi *to_rcar_msi(struct msi_chip *chip) +{ +	return container_of(chip, struct rcar_msi, chip); +} + +/* Structure representing the PCIe interface */ +struct rcar_pcie { +	struct device		*dev; +	void __iomem		*base; +	struct resource		res[PCI_MAX_RESOURCES]; +	struct resource		busn; +	int			root_bus_nr; +	struct clk		*clk; +	struct clk		*bus_clk; +	struct			rcar_msi msi; +}; + +static inline struct rcar_pcie *sys_to_pcie(struct pci_sys_data *sys) +{ +	return sys->private_data; +} + +static void pci_write_reg(struct rcar_pcie *pcie, unsigned long val, +			  unsigned long reg) +{ +	writel(val, pcie->base + reg); +} + +static unsigned long pci_read_reg(struct rcar_pcie *pcie, unsigned long reg) +{ +	return readl(pcie->base + reg); +} + +enum { +	PCI_ACCESS_READ, +	PCI_ACCESS_WRITE, +}; + +static void rcar_rmw32(struct rcar_pcie *pcie, int where, u32 mask, u32 data) +{ +	int shift = 8 * (where & 3); +	u32 val = pci_read_reg(pcie, where & ~3); + +	val &= ~(mask << shift); +	val |= data << shift; +	pci_write_reg(pcie, val, where & ~3); +} + +static u32 rcar_read_conf(struct rcar_pcie *pcie, int where) +{ +	int shift = 8 * (where & 3); +	u32 val = pci_read_reg(pcie, where & ~3); + +	return val >> shift; +} + +/* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ +static int rcar_pcie_config_access(struct rcar_pcie *pcie, +		unsigned char access_type, struct pci_bus *bus, +		unsigned int devfn, int where, u32 *data) +{ +	int dev, func, reg, index; + +	dev = PCI_SLOT(devfn); +	func = PCI_FUNC(devfn); +	reg = where & ~3; +	index = reg / 4; + +	/* +	 * While each channel has its own memory-mapped extended config +	 * space, it's generally only accessible when in endpoint mode. +	 * When in root complex mode, the controller is unable to target +	 * itself with either type 0 or type 1 accesses, and indeed, any +	 * controller initiated target transfer to its own config space +	 * result in a completer abort. +	 * +	 * Each channel effectively only supports a single device, but as +	 * the same channel <-> device access works for any PCI_SLOT() +	 * value, we cheat a bit here and bind the controller's config +	 * space to devfn 0 in order to enable self-enumeration. In this +	 * case the regular ECAR/ECDR path is sidelined and the mangled +	 * config access itself is initiated as an internal bus transaction. +	 */ +	if (pci_is_root_bus(bus)) { +		if (dev != 0) +			return PCIBIOS_DEVICE_NOT_FOUND; + +		if (access_type == PCI_ACCESS_READ) { +			*data = pci_read_reg(pcie, PCICONF(index)); +		} else { +			/* Keep an eye out for changes to the root bus number */ +			if (pci_is_root_bus(bus) && (reg == PCI_PRIMARY_BUS)) +				pcie->root_bus_nr = *data & 0xff; + +			pci_write_reg(pcie, *data, PCICONF(index)); +		} + +		return PCIBIOS_SUCCESSFUL; +	} + +	if (pcie->root_bus_nr < 0) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	/* Clear errors */ +	pci_write_reg(pcie, pci_read_reg(pcie, PCIEERRFR), PCIEERRFR); + +	/* Set the PIO address */ +	pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | PCIE_CONF_DEV(dev) | +				PCIE_CONF_FUNC(func) | reg, PCIECAR); + +	/* Enable the configuration access */ +	if (bus->parent->number == pcie->root_bus_nr) +		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR); +	else +		pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR); + +	/* Check for errors */ +	if (pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	/* Check for master and target aborts */ +	if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) & +		(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT)) +		return PCIBIOS_DEVICE_NOT_FOUND; + +	if (access_type == PCI_ACCESS_READ) +		*data = pci_read_reg(pcie, PCIECDR); +	else +		pci_write_reg(pcie, *data, PCIECDR); + +	/* Disable the configuration access */ +	pci_write_reg(pcie, 0, PCIECCTLR); + +	return PCIBIOS_SUCCESSFUL; +} + +static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, +			       int where, int size, u32 *val) +{ +	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata); +	int ret; + +	if ((size == 2) && (where & 1)) +		return PCIBIOS_BAD_REGISTER_NUMBER; +	else if ((size == 4) && (where & 3)) +		return PCIBIOS_BAD_REGISTER_NUMBER; + +	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ, +				      bus, devfn, where, val); +	if (ret != PCIBIOS_SUCCESSFUL) { +		*val = 0xffffffff; +		return ret; +	} + +	if (size == 1) +		*val = (*val >> (8 * (where & 3))) & 0xff; +	else if (size == 2) +		*val = (*val >> (8 * (where & 2))) & 0xffff; + +	dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n", +		bus->number, devfn, where, size, (unsigned long)*val); + +	return ret; +} + +/* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ +static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, +				int where, int size, u32 val) +{ +	struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata); +	int shift, ret; +	u32 data; + +	if ((size == 2) && (where & 1)) +		return PCIBIOS_BAD_REGISTER_NUMBER; +	else if ((size == 4) && (where & 3)) +		return PCIBIOS_BAD_REGISTER_NUMBER; + +	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_READ, +				      bus, devfn, where, &data); +	if (ret != PCIBIOS_SUCCESSFUL) +		return ret; + +	dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08lx\n", +		bus->number, devfn, where, size, (unsigned long)val); + +	if (size == 1) { +		shift = 8 * (where & 3); +		data &= ~(0xff << shift); +		data |= ((val & 0xff) << shift); +	} else if (size == 2) { +		shift = 8 * (where & 2); +		data &= ~(0xffff << shift); +		data |= ((val & 0xffff) << shift); +	} else +		data = val; + +	ret = rcar_pcie_config_access(pcie, PCI_ACCESS_WRITE, +				      bus, devfn, where, &data); + +	return ret; +} + +static struct pci_ops rcar_pcie_ops = { +	.read	= rcar_pcie_read_conf, +	.write	= rcar_pcie_write_conf, +}; + +static void rcar_pcie_setup_window(int win, struct resource *res, +				   struct rcar_pcie *pcie) +{ +	/* Setup PCIe address space mappings for each resource */ +	resource_size_t size; +	u32 mask; + +	pci_write_reg(pcie, 0x00000000, PCIEPTCTLR(win)); + +	/* +	 * The PAMR mask is calculated in units of 128Bytes, which +	 * keeps things pretty simple. +	 */ +	size = resource_size(res); +	mask = (roundup_pow_of_two(size) / SZ_128) - 1; +	pci_write_reg(pcie, mask << 7, PCIEPAMR(win)); + +	pci_write_reg(pcie, upper_32_bits(res->start), PCIEPARH(win)); +	pci_write_reg(pcie, lower_32_bits(res->start), PCIEPARL(win)); + +	/* First resource is for IO */ +	mask = PAR_ENABLE; +	if (res->flags & IORESOURCE_IO) +		mask |= IO_SPACE; + +	pci_write_reg(pcie, mask, PCIEPTCTLR(win)); +} + +static int rcar_pcie_setup(int nr, struct pci_sys_data *sys) +{ +	struct rcar_pcie *pcie = sys_to_pcie(sys); +	struct resource *res; +	int i; + +	pcie->root_bus_nr = -1; + +	/* Setup PCI resources */ +	for (i = 0; i < PCI_MAX_RESOURCES; i++) { + +		res = &pcie->res[i]; +		if (!res->flags) +			continue; + +		rcar_pcie_setup_window(i, res, pcie); + +		if (res->flags & IORESOURCE_IO) +			pci_ioremap_io(nr * SZ_64K, res->start); +		else +			pci_add_resource(&sys->resources, res); +	} +	pci_add_resource(&sys->resources, &pcie->busn); + +	return 1; +} + +static void rcar_pcie_add_bus(struct pci_bus *bus) +{ +	if (IS_ENABLED(CONFIG_PCI_MSI)) { +		struct rcar_pcie *pcie = sys_to_pcie(bus->sysdata); + +		bus->msi = &pcie->msi.chip; +	} +} + +struct hw_pci rcar_pci = { +	.setup          = rcar_pcie_setup, +	.map_irq        = of_irq_parse_and_map_pci, +	.ops            = &rcar_pcie_ops, +	.add_bus        = rcar_pcie_add_bus, +}; + +static void rcar_pcie_enable(struct rcar_pcie *pcie) +{ +	struct platform_device *pdev = to_platform_device(pcie->dev); + +	rcar_pci.nr_controllers = 1; +	rcar_pci.private_data = (void **)&pcie; + +	pci_common_init_dev(&pdev->dev, &rcar_pci); +#ifdef CONFIG_PCI_DOMAINS +	rcar_pci.domain++; +#endif +} + +static int phy_wait_for_ack(struct rcar_pcie *pcie) +{ +	unsigned int timeout = 100; + +	while (timeout--) { +		if (pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK) +			return 0; + +		udelay(100); +	} + +	dev_err(pcie->dev, "Access to PCIe phy timed out\n"); + +	return -ETIMEDOUT; +} + +static void phy_write_reg(struct rcar_pcie *pcie, +				 unsigned int rate, unsigned int addr, +				 unsigned int lane, unsigned int data) +{ +	unsigned long phyaddr; + +	phyaddr = WRITE_CMD | +		((rate & 1) << RATE_POS) | +		((lane & 0xf) << LANE_POS) | +		((addr & 0xff) << ADR_POS); + +	/* Set write data */ +	pci_write_reg(pcie, data, H1_PCIEPHYDOUTR); +	pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR); + +	/* Ignore errors as they will be dealt with if the data link is down */ +	phy_wait_for_ack(pcie); + +	/* Clear command */ +	pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR); +	pci_write_reg(pcie, 0, H1_PCIEPHYADRR); + +	/* Ignore errors as they will be dealt with if the data link is down */ +	phy_wait_for_ack(pcie); +} + +static int rcar_pcie_wait_for_dl(struct rcar_pcie *pcie) +{ +	unsigned int timeout = 10; + +	while (timeout--) { +		if ((pci_read_reg(pcie, PCIETSTR) & DATA_LINK_ACTIVE)) +			return 0; + +		msleep(5); +	} + +	return -ETIMEDOUT; +} + +static int rcar_pcie_hw_init(struct rcar_pcie *pcie) +{ +	int err; + +	/* Begin initialization */ +	pci_write_reg(pcie, 0, PCIETCTLR); + +	/* Set mode */ +	pci_write_reg(pcie, 1, PCIEMSR); + +	/* +	 * Initial header for port config space is type 1, set the device +	 * class to match. Hardware takes care of propagating the IDSETR +	 * settings, so there is no need to bother with a quirk. +	 */ +	pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1); + +	/* +	 * Setup Secondary Bus Number & Subordinate Bus Number, even though +	 * they aren't used, to avoid bridge being detected as broken. +	 */ +	rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1); +	rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1); + +	/* Initialize default capabilities. */ +	rcar_rmw32(pcie, REXPCAP(0), 0, PCI_CAP_ID_EXP); +	rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS), +		PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4); +	rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f, +		PCI_HEADER_TYPE_BRIDGE); + +	/* Enable data link layer active state reporting */ +	rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), 0, PCI_EXP_LNKCAP_DLLLARC); + +	/* Write out the physical slot number = 0 */ +	rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0); + +	/* Set the completion timer timeout to the maximum 50ms. */ +	rcar_rmw32(pcie, TLCTLR+1, 0x3f, 50); + +	/* Terminate list of capabilities (Next Capability Offset=0) */ +	rcar_rmw32(pcie, RVCCAP(0), 0xfff0, 0); + +	/* Enable MAC data scrambling. */ +	rcar_rmw32(pcie, MACCTLR, SCRAMBLE_DISABLE, 0); + +	/* Enable MSI */ +	if (IS_ENABLED(CONFIG_PCI_MSI)) +		pci_write_reg(pcie, 0x101f0000, PCIEMSITXR); + +	/* Finish initialization - establish a PCI Express link */ +	pci_write_reg(pcie, CFINIT, PCIETCTLR); + +	/* This will timeout if we don't have a link. */ +	err = rcar_pcie_wait_for_dl(pcie); +	if (err) +		return err; + +	/* Enable INTx interrupts */ +	rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8); + +	/* Enable slave Bus Mastering */ +	rcar_rmw32(pcie, RCONF(PCI_STATUS), PCI_STATUS_DEVSEL_MASK, +		PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | +		PCI_STATUS_CAP_LIST | PCI_STATUS_DEVSEL_FAST); + +	wmb(); + +	return 0; +} + +static int rcar_pcie_hw_init_h1(struct rcar_pcie *pcie) +{ +	unsigned int timeout = 10; + +	/* Initialize the phy */ +	phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191); +	phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180); +	phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188); +	phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188); +	phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014); +	phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014); +	phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0); +	phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB); +	phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062); +	phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000); +	phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000); +	phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806); + +	phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5); +	phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F); +	phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000); + +	while (timeout--) { +		if (pci_read_reg(pcie, H1_PCIEPHYSR)) +			return rcar_pcie_hw_init(pcie); + +		msleep(5); +	} + +	return -ETIMEDOUT; +} + +static int rcar_msi_alloc(struct rcar_msi *chip) +{ +	int msi; + +	mutex_lock(&chip->lock); + +	msi = find_first_zero_bit(chip->used, INT_PCI_MSI_NR); +	if (msi < INT_PCI_MSI_NR) +		set_bit(msi, chip->used); +	else +		msi = -ENOSPC; + +	mutex_unlock(&chip->lock); + +	return msi; +} + +static void rcar_msi_free(struct rcar_msi *chip, unsigned long irq) +{ +	mutex_lock(&chip->lock); +	clear_bit(irq, chip->used); +	mutex_unlock(&chip->lock); +} + +static irqreturn_t rcar_pcie_msi_irq(int irq, void *data) +{ +	struct rcar_pcie *pcie = data; +	struct rcar_msi *msi = &pcie->msi; +	unsigned long reg; + +	reg = pci_read_reg(pcie, PCIEMSIFR); + +	/* MSI & INTx share an interrupt - we only handle MSI here */ +	if (!reg) +		return IRQ_NONE; + +	while (reg) { +		unsigned int index = find_first_bit(®, 32); +		unsigned int irq; + +		/* clear the interrupt */ +		pci_write_reg(pcie, 1 << index, PCIEMSIFR); + +		irq = irq_find_mapping(msi->domain, index); +		if (irq) { +			if (test_bit(index, msi->used)) +				generic_handle_irq(irq); +			else +				dev_info(pcie->dev, "unhandled MSI\n"); +		} else { +			/* Unknown MSI, just clear it */ +			dev_dbg(pcie->dev, "unexpected MSI\n"); +		} + +		/* see if there's any more pending in this vector */ +		reg = pci_read_reg(pcie, PCIEMSIFR); +	} + +	return IRQ_HANDLED; +} + +static int rcar_msi_setup_irq(struct msi_chip *chip, struct pci_dev *pdev, +			      struct msi_desc *desc) +{ +	struct rcar_msi *msi = to_rcar_msi(chip); +	struct rcar_pcie *pcie = container_of(chip, struct rcar_pcie, msi.chip); +	struct msi_msg msg; +	unsigned int irq; +	int hwirq; + +	hwirq = rcar_msi_alloc(msi); +	if (hwirq < 0) +		return hwirq; + +	irq = irq_create_mapping(msi->domain, hwirq); +	if (!irq) { +		rcar_msi_free(msi, hwirq); +		return -EINVAL; +	} + +	irq_set_msi_desc(irq, desc); + +	msg.address_lo = pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE; +	msg.address_hi = pci_read_reg(pcie, PCIEMSIAUR); +	msg.data = hwirq; + +	write_msi_msg(irq, &msg); + +	return 0; +} + +static void rcar_msi_teardown_irq(struct msi_chip *chip, unsigned int irq) +{ +	struct rcar_msi *msi = to_rcar_msi(chip); +	struct irq_data *d = irq_get_irq_data(irq); + +	rcar_msi_free(msi, d->hwirq); +} + +static struct irq_chip rcar_msi_irq_chip = { +	.name = "R-Car PCIe MSI", +	.irq_enable = unmask_msi_irq, +	.irq_disable = mask_msi_irq, +	.irq_mask = mask_msi_irq, +	.irq_unmask = unmask_msi_irq, +}; + +static int rcar_msi_map(struct irq_domain *domain, unsigned int irq, +			irq_hw_number_t hwirq) +{ +	irq_set_chip_and_handler(irq, &rcar_msi_irq_chip, handle_simple_irq); +	irq_set_chip_data(irq, domain->host_data); +	set_irq_flags(irq, IRQF_VALID); + +	return 0; +} + +static const struct irq_domain_ops msi_domain_ops = { +	.map = rcar_msi_map, +}; + +static int rcar_pcie_enable_msi(struct rcar_pcie *pcie) +{ +	struct platform_device *pdev = to_platform_device(pcie->dev); +	struct rcar_msi *msi = &pcie->msi; +	unsigned long base; +	int err; + +	mutex_init(&msi->lock); + +	msi->chip.dev = pcie->dev; +	msi->chip.setup_irq = rcar_msi_setup_irq; +	msi->chip.teardown_irq = rcar_msi_teardown_irq; + +	msi->domain = irq_domain_add_linear(pcie->dev->of_node, INT_PCI_MSI_NR, +					    &msi_domain_ops, &msi->chip); +	if (!msi->domain) { +		dev_err(&pdev->dev, "failed to create IRQ domain\n"); +		return -ENOMEM; +	} + +	/* Two irqs are for MSI, but they are also used for non-MSI irqs */ +	err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq, +			       IRQF_SHARED, rcar_msi_irq_chip.name, pcie); +	if (err < 0) { +		dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); +		goto err; +	} + +	err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq, +			       IRQF_SHARED, rcar_msi_irq_chip.name, pcie); +	if (err < 0) { +		dev_err(&pdev->dev, "failed to request IRQ: %d\n", err); +		goto err; +	} + +	/* setup MSI data target */ +	msi->pages = __get_free_pages(GFP_KERNEL, 0); +	base = virt_to_phys((void *)msi->pages); + +	pci_write_reg(pcie, base | MSIFE, PCIEMSIALR); +	pci_write_reg(pcie, 0, PCIEMSIAUR); + +	/* enable all MSI interrupts */ +	pci_write_reg(pcie, 0xffffffff, PCIEMSIIER); + +	return 0; + +err: +	irq_domain_remove(msi->domain); +	return err; +} + +static int rcar_pcie_get_resources(struct platform_device *pdev, +				   struct rcar_pcie *pcie) +{ +	struct resource res; +	int err, i; + +	err = of_address_to_resource(pdev->dev.of_node, 0, &res); +	if (err) +		return err; + +	pcie->clk = devm_clk_get(&pdev->dev, "pcie"); +	if (IS_ERR(pcie->clk)) { +		dev_err(pcie->dev, "cannot get platform clock\n"); +		return PTR_ERR(pcie->clk); +	} +	err = clk_prepare_enable(pcie->clk); +	if (err) +		goto fail_clk; + +	pcie->bus_clk = devm_clk_get(&pdev->dev, "pcie_bus"); +	if (IS_ERR(pcie->bus_clk)) { +		dev_err(pcie->dev, "cannot get pcie bus clock\n"); +		err = PTR_ERR(pcie->bus_clk); +		goto fail_clk; +	} +	err = clk_prepare_enable(pcie->bus_clk); +	if (err) +		goto err_map_reg; + +	i = irq_of_parse_and_map(pdev->dev.of_node, 0); +	if (i < 0) { +		dev_err(pcie->dev, "cannot get platform resources for msi interrupt\n"); +		err = -ENOENT; +		goto err_map_reg; +	} +	pcie->msi.irq1 = i; + +	i = irq_of_parse_and_map(pdev->dev.of_node, 1); +	if (i < 0) { +		dev_err(pcie->dev, "cannot get platform resources for msi interrupt\n"); +		err = -ENOENT; +		goto err_map_reg; +	} +	pcie->msi.irq2 = i; + +	pcie->base = devm_ioremap_resource(&pdev->dev, &res); +	if (IS_ERR(pcie->base)) { +		err = PTR_ERR(pcie->base); +		goto err_map_reg; +	} + +	return 0; + +err_map_reg: +	clk_disable_unprepare(pcie->bus_clk); +fail_clk: +	clk_disable_unprepare(pcie->clk); + +	return err; +} + +static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie, +				    struct of_pci_range *range, +				    int *index) +{ +	u64 restype = range->flags; +	u64 cpu_addr = range->cpu_addr; +	u64 cpu_end = range->cpu_addr + range->size; +	u64 pci_addr = range->pci_addr; +	u32 flags = LAM_64BIT | LAR_ENABLE; +	u64 mask; +	u64 size; +	int idx = *index; + +	if (restype & IORESOURCE_PREFETCH) +		flags |= LAM_PREFETCH; + +	/* +	 * If the size of the range is larger than the alignment of the start +	 * address, we have to use multiple entries to perform the mapping. +	 */ +	if (cpu_addr > 0) { +		unsigned long nr_zeros = __ffs64(cpu_addr); +		u64 alignment = 1ULL << nr_zeros; +		size = min(range->size, alignment); +	} else { +		size = range->size; +	} +	/* Hardware supports max 4GiB inbound region */ +	size = min(size, 1ULL << 32); + +	mask = roundup_pow_of_two(size) - 1; +	mask &= ~0xf; + +	while (cpu_addr < cpu_end) { +		/* +		 * Set up 64-bit inbound regions as the range parser doesn't +		 * distinguish between 32 and 64-bit types. +		 */ +		pci_write_reg(pcie, lower_32_bits(pci_addr), PCIEPRAR(idx)); +		pci_write_reg(pcie, lower_32_bits(cpu_addr), PCIELAR(idx)); +		pci_write_reg(pcie, lower_32_bits(mask) | flags, PCIELAMR(idx)); + +		pci_write_reg(pcie, upper_32_bits(pci_addr), PCIEPRAR(idx+1)); +		pci_write_reg(pcie, upper_32_bits(cpu_addr), PCIELAR(idx+1)); +		pci_write_reg(pcie, 0, PCIELAMR(idx+1)); + +		pci_addr += size; +		cpu_addr += size; +		idx += 2; + +		if (idx > MAX_NR_INBOUND_MAPS) { +			dev_err(pcie->dev, "Failed to map inbound regions!\n"); +			return -EINVAL; +		} +	} +	*index = idx; + +	return 0; +} + +static int pci_dma_range_parser_init(struct of_pci_range_parser *parser, +				     struct device_node *node) +{ +	const int na = 3, ns = 2; +	int rlen; + +	parser->node = node; +	parser->pna = of_n_addr_cells(node); +	parser->np = parser->pna + na + ns; + +	parser->range = of_get_property(node, "dma-ranges", &rlen); +	if (!parser->range) +		return -ENOENT; + +	parser->end = parser->range + rlen / sizeof(__be32); +	return 0; +} + +static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie *pcie, +					  struct device_node *np) +{ +	struct of_pci_range range; +	struct of_pci_range_parser parser; +	int index = 0; +	int err; + +	if (pci_dma_range_parser_init(&parser, np)) +		return -EINVAL; + +	/* Get the dma-ranges from DT */ +	for_each_of_pci_range(&parser, &range) { +		u64 end = range.cpu_addr + range.size - 1; +		dev_dbg(pcie->dev, "0x%08x 0x%016llx..0x%016llx -> 0x%016llx\n", +			range.flags, range.cpu_addr, end, range.pci_addr); + +		err = rcar_pcie_inbound_ranges(pcie, &range, &index); +		if (err) +			return err; +	} + +	return 0; +} + +static const struct of_device_id rcar_pcie_of_match[] = { +	{ .compatible = "renesas,pcie-r8a7779", .data = rcar_pcie_hw_init_h1 }, +	{ .compatible = "renesas,pcie-r8a7790", .data = rcar_pcie_hw_init }, +	{ .compatible = "renesas,pcie-r8a7791", .data = rcar_pcie_hw_init }, +	{}, +}; +MODULE_DEVICE_TABLE(of, rcar_pcie_of_match); + +static int rcar_pcie_probe(struct platform_device *pdev) +{ +	struct rcar_pcie *pcie; +	unsigned int data; +	struct of_pci_range range; +	struct of_pci_range_parser parser; +	const struct of_device_id *of_id; +	int err, win = 0; +	int (*hw_init_fn)(struct rcar_pcie *); + +	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL); +	if (!pcie) +		return -ENOMEM; + +	pcie->dev = &pdev->dev; +	platform_set_drvdata(pdev, pcie); + +	/* Get the bus range */ +	if (of_pci_parse_bus_range(pdev->dev.of_node, &pcie->busn)) { +		dev_err(&pdev->dev, "failed to parse bus-range property\n"); +		return -EINVAL; +	} + +	if (of_pci_range_parser_init(&parser, pdev->dev.of_node)) { +		dev_err(&pdev->dev, "missing ranges property\n"); +		return -EINVAL; +	} + +	err = rcar_pcie_get_resources(pdev, pcie); +	if (err < 0) { +		dev_err(&pdev->dev, "failed to request resources: %d\n", err); +		return err; +	} + +	for_each_of_pci_range(&parser, &range) { +		of_pci_range_to_resource(&range, pdev->dev.of_node, +						&pcie->res[win++]); + +		if (win > PCI_MAX_RESOURCES) +			break; +	} + +	 err = rcar_pcie_parse_map_dma_ranges(pcie, pdev->dev.of_node); +	 if (err) +		return err; + +	if (IS_ENABLED(CONFIG_PCI_MSI)) { +		err = rcar_pcie_enable_msi(pcie); +		if (err < 0) { +			dev_err(&pdev->dev, +				"failed to enable MSI support: %d\n", +				err); +			return err; +		} +	} + +	of_id = of_match_device(rcar_pcie_of_match, pcie->dev); +	if (!of_id || !of_id->data) +		return -EINVAL; +	hw_init_fn = of_id->data; + +	/* Failure to get a link might just be that no cards are inserted */ +	err = hw_init_fn(pcie); +	if (err) { +		dev_info(&pdev->dev, "PCIe link down\n"); +		return 0; +	} + +	data = pci_read_reg(pcie, MACSR); +	dev_info(&pdev->dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); + +	rcar_pcie_enable(pcie); + +	return 0; +} + +static struct platform_driver rcar_pcie_driver = { +	.driver = { +		.name = DRV_NAME, +		.owner = THIS_MODULE, +		.of_match_table = rcar_pcie_of_match, +		.suppress_bind_attrs = true, +	}, +	.probe = rcar_pcie_probe, +}; +module_platform_driver(rcar_pcie_driver); + +MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>"); +MODULE_DESCRIPTION("Renesas R-Car PCIe driver"); +MODULE_LICENSE("GPLv2"); diff --git a/drivers/pci/hotplug-pci.c b/drivers/pci/hotplug-pci.c index 6258dc260d9..c68366cee6b 100644 --- a/drivers/pci/hotplug-pci.c +++ b/drivers/pci/hotplug-pci.c @@ -4,7 +4,7 @@  #include <linux/export.h>  #include "pci.h" -int __ref pci_hp_add_bridge(struct pci_dev *dev) +int pci_hp_add_bridge(struct pci_dev *dev)  {  	struct pci_bus *parent = dev->bus;  	int pass, busnr, start = parent->busn_res.start; diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 0a648af8953..df8caec5978 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -133,8 +133,8 @@ config HOTPLUG_PCI_RPA_DLPAR  	  To compile this driver as a module, choose M here: the  	  module will be called rpadlpar_io. -  - 	  When in doubt, say N. + +	  When in doubt, say N.  config HOTPLUG_PCI_SGI  	tristate "SGI PCI Hotplug Support" diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile index 47ec8c80e16..3e6532b945c 100644 --- a/drivers/pci/hotplug/Makefile +++ b/drivers/pci/hotplug/Makefile @@ -31,7 +31,7 @@ pci_hotplug-objs	+=	cpci_hotplug_core.o	\  				cpci_hotplug_pci.o  endif  ifdef CONFIG_ACPI -pci_hotplug-objs 	+= 	acpi_pcihp.o +pci_hotplug-objs	+=	acpi_pcihp.o  endif  cpqphp-objs		:=	cpqphp_core.o	\ diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 2a47e82821d..a94d850ae22 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -338,7 +338,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)  	acpi_handle chandle, handle;  	struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; -	flags &= OSC_SHPC_NATIVE_HP_CONTROL; +	flags &= OSC_PCI_SHPC_NATIVE_HP_CONTROL;  	if (!flags) {  		err("Invalid flags %u specified!\n", flags);  		return -EINVAL; @@ -367,7 +367,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)  		string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };  	} -	handle = DEVICE_ACPI_HANDLE(&pdev->dev); +	handle = ACPI_HANDLE(&pdev->dev);  	if (!handle) {  		/*  		 * This hotplug controller was not listed in the ACPI name @@ -411,13 +411,10 @@ EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware);  static int pcihp_is_ejectable(acpi_handle handle)  {  	acpi_status status; -	acpi_handle tmp;  	unsigned long long removable; -	status = acpi_get_handle(handle, "_ADR", &tmp); -	if (ACPI_FAILURE(status)) +	if (!acpi_has_method(handle, "_ADR"))  		return 0; -	status = acpi_get_handle(handle, "_EJ0", &tmp); -	if (ACPI_SUCCESS(status)) +	if (acpi_has_method(handle, "_EJ0"))  		return 1;  	status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);  	if (ACPI_SUCCESS(status) && removable) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f4e02892466..b0e61bf261a 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -39,16 +39,6 @@  #include <linux/mutex.h>  #include <linux/pci_hotplug.h> -#define dbg(format, arg...)					\ -	do {							\ -		if (acpiphp_debug)				\ -			printk(KERN_DEBUG "%s: " format,	\ -				MY_NAME , ## arg);		\ -	} while (0) -#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) -#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg) -  struct acpiphp_context;  struct acpiphp_bridge;  struct acpiphp_slot; @@ -87,6 +77,8 @@ struct acpiphp_bridge {  	/* PCI-to-PCI bridge device */  	struct pci_dev *pci_dev; + +	bool is_going_away;  }; @@ -101,7 +93,6 @@ struct acpiphp_slot {  	struct list_head funcs;		/* one slot may have different  					   objects (i.e. for each function) */  	struct slot *slot; -	struct mutex crit_sect;  	u8		device;		/* pci device# */  	u32		flags;		/* see below */ @@ -125,20 +116,40 @@ struct acpiphp_func {  };  struct acpiphp_context { -	acpi_handle handle; +	struct acpi_hotplug_context hp;  	struct acpiphp_func func;  	struct acpiphp_bridge *bridge;  	unsigned int refcount;  }; +static inline struct acpiphp_context *to_acpiphp_context(struct acpi_hotplug_context *hp) +{ +	return container_of(hp, struct acpiphp_context, hp); +} +  static inline struct acpiphp_context *func_to_context(struct acpiphp_func *func)  {  	return container_of(func, struct acpiphp_context, func);  } +static inline struct acpi_device *func_to_acpi_device(struct acpiphp_func *func) +{ +	return func_to_context(func)->hp.self; +} +  static inline acpi_handle func_to_handle(struct acpiphp_func *func)  { -	return func_to_context(func)->handle; +	return func_to_acpi_device(func)->handle; +} + +struct acpiphp_root_context { +	struct acpi_hotplug_context hp; +	struct acpiphp_bridge *root_bridge; +}; + +static inline struct acpiphp_root_context *to_acpiphp_root_context(struct acpi_hotplug_context *hp) +{ +	return container_of(hp, struct acpiphp_root_context, hp);  }  /* @@ -160,12 +171,12 @@ struct acpiphp_attention_info  /* slot flags */  #define SLOT_ENABLED		(0x00000001) +#define SLOT_IS_GOING_AWAY	(0x00000002)  /* function flags */  #define FUNC_HAS_STA		(0x00000001)  #define FUNC_HAS_EJ0		(0x00000002) -#define FUNC_HAS_DCK            (0x00000004)  /* function prototypes */ @@ -179,14 +190,13 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot);  typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data);  int acpiphp_enable_slot(struct acpiphp_slot *slot); -int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); +int acpiphp_disable_slot(struct acpiphp_slot *slot);  u8 acpiphp_get_power_status(struct acpiphp_slot *slot);  u8 acpiphp_get_attention_status(struct acpiphp_slot *slot);  u8 acpiphp_get_latch_status(struct acpiphp_slot *slot);  u8 acpiphp_get_adapter_status(struct acpiphp_slot *slot);  /* variables */ -extern bool acpiphp_debug;  extern bool acpiphp_disabled;  #endif /* _ACPIPHP_H */ diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index bf2203ef130..e291efcd02a 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -31,6 +31,8 @@   *   */ +#define pr_fmt(fmt) "acpiphp: " fmt +  #include <linux/init.h>  #include <linux/module.h>  #include <linux/moduleparam.h> @@ -43,12 +45,9 @@  #include <linux/smp.h>  #include "acpiphp.h" -#define MY_NAME	"acpiphp" -  /* name size which is used for entries in pcihpfs */  #define SLOT_NAME_SIZE  21              /* {_SUN} */ -bool acpiphp_debug;  bool acpiphp_disabled;  /* local variables */ @@ -61,15 +60,9 @@ static struct acpiphp_attention_info *attention_info;  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL"); -MODULE_PARM_DESC(debug, "Debugging mode enabled or not");  MODULE_PARM_DESC(disable, "disable acpiphp driver"); -module_param_named(debug, acpiphp_debug, bool, 0644);  module_param_named(disable, acpiphp_disabled, bool, 0444); -/* export the attention callback registration methods */ -EXPORT_SYMBOL_GPL(acpiphp_register_attention); -EXPORT_SYMBOL_GPL(acpiphp_unregister_attention); -  static int enable_slot		(struct hotplug_slot *slot);  static int disable_slot		(struct hotplug_slot *slot);  static int set_attention_status (struct hotplug_slot *slot, u8 value); @@ -107,6 +100,7 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info)  	}  	return retval;  } +EXPORT_SYMBOL_GPL(acpiphp_register_attention);  /** @@ -114,7 +108,7 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info)   * @info: must match the pointer used to register   *   * Description: This is used to un-register a hardware specific acpi - * driver that manipulates the attention LED.  The pointer to the  + * driver that manipulates the attention LED.  The pointer to the   * info struct must be the same as the one used to set it.   */  int acpiphp_unregister_attention(struct acpiphp_attention_info *info) @@ -127,6 +121,7 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info)  	}  	return retval;  } +EXPORT_SYMBOL_GPL(acpiphp_unregister_attention);  /** @@ -139,7 +134,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)  {  	struct slot *slot = hotplug_slot->private; -	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));  	/* enable the specified slot */  	return acpiphp_enable_slot(slot->acpi_slot); @@ -156,10 +151,10 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)  {  	struct slot *slot = hotplug_slot->private; -	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));  	/* disable the specified slot */ -	return acpiphp_disable_and_eject_slot(slot->acpi_slot); +	return acpiphp_disable_slot(slot->acpi_slot);  } @@ -172,20 +167,21 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)   * was registered with us.  This allows hardware specific   * ACPI implementations to blink the light for us.   */ - static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) - { +static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) +{  	int retval = -ENODEV; -	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot)); -  +	pr_debug("%s - physical_slot = %s\n", __func__, +		hotplug_slot_name(hotplug_slot)); +  	if (attention_info && try_module_get(attention_info->owner)) {  		retval = attention_info->set_attn(hotplug_slot, status);  		module_put(attention_info->owner);  	} else  		attention_info = NULL;  	return retval; - } -  +} +  /**   * get_power_status - get power status of a slot @@ -199,7 +195,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = hotplug_slot->private; -	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));  	*value = acpiphp_get_power_status(slot->acpi_slot); @@ -221,7 +217,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	int retval = -EINVAL; -	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, +		hotplug_slot_name(hotplug_slot));  	if (attention_info && try_module_get(attention_info->owner)) {  		retval = attention_info->get_attn(hotplug_slot, value); @@ -244,7 +241,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = hotplug_slot->private; -	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));  	*value = acpiphp_get_latch_status(slot->acpi_slot); @@ -264,7 +261,7 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = hotplug_slot->private; -	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));  	*value = acpiphp_get_adapter_status(slot->acpi_slot); @@ -279,7 +276,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)  {  	struct slot *slot = hotplug_slot->private; -	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot)); +	pr_debug("%s - physical_slot = %s\n", __func__, slot_name(slot));  	kfree(slot->hotplug_slot);  	kfree(slot); @@ -322,11 +319,11 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot,  	if (retval == -EBUSY)  		goto error_hpslot;  	if (retval) { -		err("pci_hp_register failed with error %d\n", retval); +		pr_err("pci_hp_register failed with error %d\n", retval);  		goto error_hpslot; - 	} +	} -	info("Slot [%s] registered\n", slot_name(slot)); +	pr_info("Slot [%s] registered\n", slot_name(slot));  	return 0;  error_hpslot: @@ -343,17 +340,17 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot)  	struct slot *slot = acpiphp_slot->slot;  	int retval = 0; -	info("Slot [%s] unregistered\n", slot_name(slot)); +	pr_info("Slot [%s] unregistered\n", slot_name(slot));  	retval = pci_hp_deregister(slot->hotplug_slot);  	if (retval) -		err("pci_hp_deregister failed with error %d\n", retval); +		pr_err("pci_hp_deregister failed with error %d\n", retval);  }  void __init acpiphp_init(void)  { -	info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", +	pr_info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n",  		acpiphp_disabled ? ", disabled by user; please report a bug"  				 : "");  } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 0b7d23b4ad9..602d153c705 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -39,7 +39,8 @@   *    bus. It loses the refcount when the the driver unloads.   */ -#include <linux/init.h> +#define pr_fmt(fmt) "acpiphp_glue: " fmt +  #include <linux/module.h>  #include <linux/kernel.h> @@ -56,73 +57,59 @@  static LIST_HEAD(bridge_list);  static DEFINE_MUTEX(bridge_mutex); -static DEFINE_MUTEX(acpiphp_context_lock); - -#define MY_NAME "acpiphp_glue" -static void handle_hotplug_event(acpi_handle handle, u32 type, void *data); +static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type); +static void acpiphp_post_dock_fixup(struct acpi_device *adev);  static void acpiphp_sanitize_bus(struct pci_bus *bus);  static void acpiphp_set_hpp_values(struct pci_bus *bus); -static void hotplug_event(acpi_handle handle, u32 type, void *data); +static void hotplug_event(u32 type, struct acpiphp_context *context);  static void free_bridge(struct kref *kref); -static void acpiphp_context_handler(acpi_handle handle, void *context) -{ -	/* Intentionally empty. */ -} -  /**   * acpiphp_init_context - Create hotplug context and grab a reference to it. - * @handle: ACPI object handle to create the context for. + * @adev: ACPI device object to create the context for.   * - * Call under acpiphp_context_lock. + * Call under acpi_hp_context_lock.   */ -static struct acpiphp_context *acpiphp_init_context(acpi_handle handle) +static struct acpiphp_context *acpiphp_init_context(struct acpi_device *adev)  {  	struct acpiphp_context *context; -	acpi_status status;  	context = kzalloc(sizeof(*context), GFP_KERNEL);  	if (!context)  		return NULL; -	context->handle = handle;  	context->refcount = 1; -	status = acpi_attach_data(handle, acpiphp_context_handler, context); -	if (ACPI_FAILURE(status)) { -		kfree(context); -		return NULL; -	} +	acpi_set_hp_context(adev, &context->hp, acpiphp_hotplug_notify, NULL, +			    acpiphp_post_dock_fixup);  	return context;  }  /**   * acpiphp_get_context - Get hotplug context and grab a reference to it. - * @handle: ACPI object handle to get the context for. + * @adev: ACPI device object to get the context for.   * - * Call under acpiphp_context_lock. + * Call under acpi_hp_context_lock.   */ -static struct acpiphp_context *acpiphp_get_context(acpi_handle handle) +static struct acpiphp_context *acpiphp_get_context(struct acpi_device *adev)  { -	struct acpiphp_context *context = NULL; -	acpi_status status; -	void *data; +	struct acpiphp_context *context; -	status = acpi_get_data(handle, acpiphp_context_handler, &data); -	if (ACPI_SUCCESS(status)) { -		context = data; -		context->refcount++; -	} +	if (!adev->hp) +		return NULL; + +	context = to_acpiphp_context(adev->hp); +	context->refcount++;  	return context;  }  /**   * acpiphp_put_context - Drop a reference to ACPI hotplug context. - * @handle: ACPI object handle to put the context for. + * @context: ACPI hotplug context to drop a reference to.   *   * The context object is removed if there are no more references to it.   * - * Call under acpiphp_context_lock. + * Call under acpi_hp_context_lock.   */  static void acpiphp_put_context(struct acpiphp_context *context)  { @@ -130,7 +117,7 @@ static void acpiphp_put_context(struct acpiphp_context *context)  		return;  	WARN_ON(context->bridge); -	acpi_detach_data(context->handle, acpiphp_context_handler); +	context->hp.self->hp = NULL;  	kfree(context);  } @@ -144,6 +131,27 @@ static inline void put_bridge(struct acpiphp_bridge *bridge)  	kref_put(&bridge->ref, free_bridge);  } +static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev) +{ +	struct acpiphp_context *context; + +	acpi_lock_hp_context(); +	context = acpiphp_get_context(adev); +	if (!context || context->func.parent->is_going_away) { +		acpi_unlock_hp_context(); +		return NULL; +	} +	get_bridge(context->func.parent); +	acpiphp_put_context(context); +	acpi_unlock_hp_context(); +	return context; +} + +static void acpiphp_let_context_go(struct acpiphp_context *context) +{ +	put_bridge(context->func.parent); +} +  static void free_bridge(struct kref *kref)  {  	struct acpiphp_context *context; @@ -151,7 +159,7 @@ static void free_bridge(struct kref *kref)  	struct acpiphp_slot *slot, *next;  	struct acpiphp_func *func, *tmp; -	mutex_lock(&acpiphp_context_lock); +	acpi_lock_hp_context();  	bridge = container_of(kref, struct acpiphp_bridge, ref); @@ -175,31 +183,32 @@ static void free_bridge(struct kref *kref)  	pci_dev_put(bridge->pci_dev);  	kfree(bridge); -	mutex_unlock(&acpiphp_context_lock); +	acpi_unlock_hp_context();  } -/* - * the _DCK method can do funny things... and sometimes not - * hah-hah funny. +/** + * acpiphp_post_dock_fixup - Post-dock fixups for PCI devices. + * @adev: ACPI device object corresponding to a PCI device.   * - * TBD - figure out a way to only call fixups for - * systems that require them. + * TBD - figure out a way to only call fixups for systems that require them.   */ -static void post_dock_fixups(acpi_handle not_used, u32 event, void *data) +static void acpiphp_post_dock_fixup(struct acpi_device *adev)  { -	struct acpiphp_context *context = data; -	struct pci_bus *bus = context->func.slot->bus; +	struct acpiphp_context *context = acpiphp_grab_context(adev); +	struct pci_bus *bus;  	u32 buses; -	if (!bus->self) +	if (!context)  		return; +	bus = context->func.slot->bus; +	if (!bus->self) +		goto out; +  	/* fixup bad _DCK function that rewrites  	 * secondary bridge on slot  	 */ -	pci_read_config_dword(bus->self, -			PCI_PRIMARY_BUS, -			&buses); +	pci_read_config_dword(bus->self, PCI_PRIMARY_BUS, &buses);  	if (((buses >> 8) & 0xff) != bus->busn_res.start) {  		buses = (buses & 0xff000000) @@ -208,13 +217,10 @@ static void post_dock_fixups(acpi_handle not_used, u32 event, void *data)  			| ((unsigned int)(bus->busn_res.end) << 16);  		pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);  	} -} - -static const struct acpi_dock_ops acpiphp_dock_ops = { -	.fixup = post_dock_fixups, -	.handler = hotplug_event, -}; + out: +	acpiphp_let_context_go(context); +}  /* Check whether the PCI device is managed by native PCIe hotplug driver */  static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) @@ -245,26 +251,19 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)  	return true;  } -static void acpiphp_dock_init(void *data) -{ -	struct acpiphp_context *context = data; - -	get_bridge(context->func.parent); -} - -static void acpiphp_dock_release(void *data) -{ -	struct acpiphp_context *context = data; - -	put_bridge(context->func.parent); -} - -/* callback routine to register each ACPI PCI slot object */ -static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data, -				 void **rv) +/** + * acpiphp_add_context - Add ACPIPHP context to an ACPI device object. + * @handle: ACPI handle of the object to add a context to. + * @lvl: Not used. + * @data: The object's parent ACPIPHP bridge. + * @rv: Not used. + */ +static acpi_status acpiphp_add_context(acpi_handle handle, u32 lvl, void *data, +				       void **rv)  {  	struct acpiphp_bridge *bridge = data;  	struct acpiphp_context *context; +	struct acpi_device *adev;  	struct acpiphp_slot *slot;  	struct acpiphp_func *newfunc;  	acpi_status status = AE_OK; @@ -274,39 +273,41 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,  	struct pci_dev *pdev = bridge->pci_dev;  	u32 val; -	if (pdev && device_is_managed_by_native_pciehp(pdev)) -		return AE_OK; -  	status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr);  	if (ACPI_FAILURE(status)) { -		acpi_handle_warn(handle, "can't evaluate _ADR (%#x)\n", status); +		if (status != AE_NOT_FOUND) +			acpi_handle_warn(handle, +				"can't evaluate _ADR (%#x)\n", status);  		return AE_OK;  	} +	if (acpi_bus_get_device(handle, &adev)) +		return AE_OK;  	device = (adr >> 16) & 0xffff;  	function = adr & 0xffff; -	mutex_lock(&acpiphp_context_lock); -	context = acpiphp_init_context(handle); +	acpi_lock_hp_context(); +	context = acpiphp_init_context(adev);  	if (!context) { -		mutex_unlock(&acpiphp_context_lock); +		acpi_unlock_hp_context();  		acpi_handle_err(handle, "No hotplug context\n");  		return AE_NOT_EXIST;  	}  	newfunc = &context->func;  	newfunc->function = function;  	newfunc->parent = bridge; -	mutex_unlock(&acpiphp_context_lock); +	acpi_unlock_hp_context(); -	if (acpi_has_method(handle, "_EJ0")) +	/* +	 * If this is a dock device, its _EJ0 should be executed by the dock +	 * notify handler after calling _DCK. +	 */ +	if (!is_dock_device(adev) && acpi_has_method(handle, "_EJ0"))  		newfunc->flags = FUNC_HAS_EJ0;  	if (acpi_has_method(handle, "_STA"))  		newfunc->flags |= FUNC_HAS_STA; -	if (acpi_has_method(handle, "_DCK")) -		newfunc->flags |= FUNC_HAS_DCK; -  	/* search for objects that share the same slot */  	list_for_each_entry(slot, &bridge->slots, node)  		if (slot->device == device) @@ -314,19 +315,26 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,  	slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL);  	if (!slot) { -		status = AE_NO_MEMORY; -		goto err; +		acpi_lock_hp_context(); +		acpiphp_put_context(context); +		acpi_unlock_hp_context(); +		return AE_NO_MEMORY;  	}  	slot->bus = bridge->pci_bus;  	slot->device = device;  	INIT_LIST_HEAD(&slot->funcs); -	mutex_init(&slot->crit_sect);  	list_add_tail(&slot->node, &bridge->slots); -	/* Register slots for ejectable funtions only. */ -	if (acpi_pci_check_ejectable(pbus, handle)  || is_dock_device(handle)) { +	/* +	 * Expose slots to user space for functions that have _EJ0 or _RMV or +	 * are located in dock stations.  Do not expose them for devices handled +	 * by the native PCIe hotplug (PCIeHP), becuase that code is supposed to +	 * expose slots to user space in those cases. +	 */ +	if ((acpi_pci_check_ejectable(pbus, handle) || is_dock_device(adev)) +	    && !(pdev && device_is_managed_by_native_pciehp(pdev))) {  		unsigned long long sun;  		int retval; @@ -335,7 +343,7 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,  		if (ACPI_FAILURE(status))  			sun = bridge->nr_slots; -		dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", +		pr_debug("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n",  		    sun, pci_domain_nr(pbus), pbus->number, device);  		retval = acpiphp_register_hotplug_slot(slot, sun); @@ -343,11 +351,9 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,  			slot->slot = NULL;  			bridge->nr_slots--;  			if (retval == -EBUSY) -				warn("Slot %llu already registered by another " -					"hotplug driver\n", sun); +				pr_warn("Slot %llu already registered by another hotplug driver\n", sun);  			else -				warn("acpiphp_register_hotplug_slot failed " -					"(err code = 0x%x)\n", retval); +				pr_warn("acpiphp_register_hotplug_slot failed (err code = 0x%x)\n", retval);  		}  		/* Even if the slot registration fails, we can still use it. */  	} @@ -360,52 +366,20 @@ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *data,  				       &val, 60*1000))  		slot->flags |= SLOT_ENABLED; -	if (is_dock_device(handle)) { -		/* we don't want to call this device's _EJ0 -		 * because we want the dock notify handler -		 * to call it after it calls _DCK -		 */ -		newfunc->flags &= ~FUNC_HAS_EJ0; -		if (register_hotplug_dock_device(handle, -			&acpiphp_dock_ops, context, -			acpiphp_dock_init, acpiphp_dock_release)) -			dbg("failed to register dock device\n"); -	} - -	/* install notify handler */ -	if (!(newfunc->flags & FUNC_HAS_DCK)) { -		status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, -						     handle_hotplug_event, -						     context); -		if (ACPI_FAILURE(status)) -			acpi_handle_err(handle, -					"failed to install notify handler\n"); -	} -  	return AE_OK; - - err: -	mutex_lock(&acpiphp_context_lock); -	acpiphp_put_context(context); -	mutex_unlock(&acpiphp_context_lock); -	return status;  } -static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) +static struct acpiphp_bridge *acpiphp_dev_to_bridge(struct acpi_device *adev)  { -	struct acpiphp_context *context;  	struct acpiphp_bridge *bridge = NULL; -	mutex_lock(&acpiphp_context_lock); -	context = acpiphp_get_context(handle); -	if (context) { -		bridge = context->bridge; +	acpi_lock_hp_context(); +	if (adev->hp) { +		bridge = to_acpiphp_root_context(adev->hp)->root_bridge;  		if (bridge)  			get_bridge(bridge); - -		acpiphp_put_context(context);  	} -	mutex_unlock(&acpiphp_context_lock); +	acpi_unlock_hp_context();  	return bridge;  } @@ -413,23 +387,17 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)  {  	struct acpiphp_slot *slot;  	struct acpiphp_func *func; -	acpi_status status;  	list_for_each_entry(slot, &bridge->slots, node) {  		list_for_each_entry(func, &slot->funcs, sibling) { -			acpi_handle handle = func_to_handle(func); - -			if (is_dock_device(handle)) -				unregister_hotplug_dock_device(handle); +			struct acpi_device *adev = func_to_acpi_device(func); -			if (!(func->flags & FUNC_HAS_DCK)) { -				status = acpi_remove_notify_handler(handle, -							ACPI_SYSTEM_NOTIFY, -							handle_hotplug_event); -				if (ACPI_FAILURE(status)) -					err("failed to remove notify handler\n"); -			} +			acpi_lock_hp_context(); +			adev->hp->notify = NULL; +			adev->hp->fixup = NULL; +			acpi_unlock_hp_context();  		} +		slot->flags |= SLOT_IS_GOING_AWAY;  		if (slot->slot)  			acpiphp_unregister_hotplug_slot(slot);  	} @@ -437,6 +405,10 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)  	mutex_lock(&bridge_mutex);  	list_del(&bridge->list);  	mutex_unlock(&bridge_mutex); + +	acpi_lock_hp_context(); +	bridge->is_going_away = true; +	acpi_unlock_hp_context();  }  /** @@ -445,7 +417,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)   */  static unsigned char acpiphp_max_busnr(struct pci_bus *bus)  { -	struct list_head *tmp; +	struct pci_bus *tmp;  	unsigned char max, n;  	/* @@ -458,41 +430,14 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)  	 */  	max = bus->busn_res.start; -	list_for_each(tmp, &bus->children) { -		n = pci_bus_max_busnr(pci_bus_b(tmp)); +	list_for_each_entry(tmp, &bus->children, node) { +		n = pci_bus_max_busnr(tmp);  		if (n > max)  			max = n;  	}  	return max;  } -/** - * acpiphp_bus_trim - Trim device objects in an ACPI namespace subtree. - * @handle: ACPI device object handle to start from. - */ -static void acpiphp_bus_trim(acpi_handle handle) -{ -	struct acpi_device *adev = NULL; - -	acpi_bus_get_device(handle, &adev); -	if (adev) -		acpi_bus_trim(adev); -} - -/** - * acpiphp_bus_add - Scan ACPI namespace subtree. - * @handle: ACPI object handle to start the scan from. - */ -static void acpiphp_bus_add(acpi_handle handle) -{ -	struct acpi_device *adev = NULL; - -	acpi_bus_scan(handle); -	acpi_bus_get_device(handle, &adev); -	if (adev) -		acpi_device_set_power(adev, ACPI_STATE_D0); -} -  static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)  {  	struct acpiphp_func *func; @@ -532,9 +477,13 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot)  {  	struct acpiphp_func *func; -	list_for_each_entry(func, &slot->funcs, sibling) -		acpiphp_bus_add(func_to_handle(func)); +	list_for_each_entry(func, &slot->funcs, sibling) { +		struct acpi_device *adev = func_to_acpi_device(func); +		acpi_bus_scan(adev->handle); +		if (acpi_device_enumerated(adev)) +			acpi_device_set_power(adev, ACPI_STATE_D0); +	}  	return pci_scan_slot(slot->bus, PCI_DEVFN(slot->device, 0));  } @@ -545,24 +494,22 @@ static int acpiphp_rescan_slot(struct acpiphp_slot *slot)   * This function should be called per *physical slot*,   * not per each slot object in ACPI namespace.   */ -static void __ref enable_slot(struct acpiphp_slot *slot) +static void enable_slot(struct acpiphp_slot *slot)  {  	struct pci_dev *dev;  	struct pci_bus *bus = slot->bus;  	struct acpiphp_func *func;  	int max, pass;  	LIST_HEAD(add_list); -	int nr_found; -	nr_found = acpiphp_rescan_slot(slot); +	acpiphp_rescan_slot(slot);  	max = acpiphp_max_busnr(bus);  	for (pass = 0; pass < 2; pass++) {  		list_for_each_entry(dev, &bus->devices, bus_list) {  			if (PCI_SLOT(dev->devfn) != slot->device)  				continue; -			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || -			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { +			if (pci_is_bridge(dev)) {  				max = pci_scan_bridge(bus, dev, max, pass);  				if (pass && dev->subordinate) {  					check_hotplug_bridge(slot, dev); @@ -574,9 +521,6 @@ static void __ref enable_slot(struct acpiphp_slot *slot)  		}  	}  	__pci_bus_assign_resources(bus, &add_list, NULL); -	/* Nothing more to do here if there are no new devices on this bus. */ -	if (!nr_found && (slot->flags & SLOT_ENABLED)) -		return;  	acpiphp_sanitize_bus(bus);  	acpiphp_set_hpp_values(bus); @@ -603,32 +547,15 @@ static void __ref enable_slot(struct acpiphp_slot *slot)  	}  } -/* 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->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_slot - disable a slot   * @slot: ACPI PHP slot   */  static void disable_slot(struct acpiphp_slot *slot)  { +	struct pci_bus *bus = slot->bus; +	struct pci_dev *dev, *prev;  	struct acpiphp_func *func; -	struct pci_dev *pdev;  	/*  	 * enable_slot() enumerates all functions in this device via @@ -636,17 +563,31 @@ static void disable_slot(struct acpiphp_slot *slot)  	 * methods (_EJ0, etc.) or not.  Therefore, we remove all functions  	 * here.  	 */ -	while ((pdev = dev_in_slot(slot))) { -		pci_stop_and_remove_bus_device(pdev); -		pci_dev_put(pdev); -	} +	list_for_each_entry_safe_reverse(dev, prev, &bus->devices, bus_list) +		if (PCI_SLOT(dev->devfn) == slot->device) +			pci_stop_and_remove_bus_device(dev);  	list_for_each_entry(func, &slot->funcs, sibling) -		acpiphp_bus_trim(func_to_handle(func)); +		acpi_bus_trim(func_to_acpi_device(func));  	slot->flags &= (~SLOT_ENABLED);  } +static bool acpiphp_no_hotplug(struct acpi_device *adev) +{ +	return adev && adev->flags.no_hotplug; +} + +static bool slot_no_hotplug(struct acpiphp_slot *slot) +{ +	struct acpiphp_func *func; + +	list_for_each_entry(func, &slot->funcs, sibling) +		if (acpiphp_no_hotplug(func_to_acpi_device(func))) +			return true; + +	return false; +}  /**   * get_slot_status - get ACPI slot status @@ -690,39 +631,48 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)  	return (unsigned int)sta;  } +static inline bool device_status_valid(unsigned int sta) +{ +	/* +	 * ACPI spec says that _STA may return bit 0 clear with bit 3 set +	 * if the device is valid but does not require a device driver to be +	 * loaded (Section 6.3.7 of ACPI 5.0A). +	 */ +	unsigned int mask = ACPI_STA_DEVICE_ENABLED | ACPI_STA_DEVICE_FUNCTIONING; +	return (sta & mask) == mask; +} +  /**   * trim_stale_devices - remove PCI devices that are not responding.   * @dev: PCI device to start walking the hierarchy from.   */  static void trim_stale_devices(struct pci_dev *dev)  { -	acpi_handle handle = ACPI_HANDLE(&dev->dev); +	struct acpi_device *adev = ACPI_COMPANION(&dev->dev);  	struct pci_bus *bus = dev->subordinate;  	bool alive = false; -	if (handle) { +	if (adev) {  		acpi_status status;  		unsigned long long sta; -		status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); -		alive = ACPI_SUCCESS(status) && sta == ACPI_STA_ALL; +		status = acpi_evaluate_integer(adev->handle, "_STA", NULL, &sta); +		alive = (ACPI_SUCCESS(status) && device_status_valid(sta)) +			|| acpiphp_no_hotplug(adev);  	} -	if (!alive) { -		u32 v; +	if (!alive) +		alive = pci_device_is_present(dev); -		/* Check if the device responds. */ -		alive = pci_bus_read_dev_vendor_id(dev->bus, dev->devfn, &v, 0); -	}  	if (!alive) {  		pci_stop_and_remove_bus_device(dev); -		if (handle) -			acpiphp_bus_trim(handle); +		if (adev) +			acpi_bus_trim(adev);  	} else if (bus) {  		struct pci_dev *child, *tmp;  		/* The device is a bridge. so check the bus below it. */  		pm_runtime_get_sync(&dev->dev); -		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) +		list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)  			trim_stale_devices(child);  		pm_runtime_put(&dev->dev); @@ -740,16 +690,20 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)  {  	struct acpiphp_slot *slot; +	/* Bail out if the bridge is going away. */ +	if (bridge->is_going_away) +		return; +  	list_for_each_entry(slot, &bridge->slots, node) {  		struct pci_bus *bus = slot->bus;  		struct pci_dev *dev, *tmp; -		mutex_lock(&slot->crit_sect); -		/* wake up all functions */ -		if (get_slot_status(slot) == ACPI_STA_ALL) { +		if (slot_no_hotplug(slot)) { +			; /* do nothing */ +		} else if (device_status_valid(get_slot_status(slot))) {  			/* remove stale devices if any */ -			list_for_each_entry_safe(dev, tmp, &bus->devices, -						 bus_list) +			list_for_each_entry_safe_reverse(dev, tmp, +							 &bus->devices, bus_list)  				if (PCI_SLOT(dev->devfn) == slot->device)  					trim_stale_devices(dev); @@ -758,7 +712,6 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)  		} else {  			disable_slot(slot);  		} -		mutex_unlock(&slot->crit_sect);  	}  } @@ -780,7 +733,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)  	int i;  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; -	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { +	list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {  		for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {  			struct resource *res = &dev->resource[i];  			if ((res->flags & type_mask) && !res->start && @@ -798,179 +751,112 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)   * ACPI event handlers   */ -void acpiphp_check_host_bridge(acpi_handle handle) +void acpiphp_check_host_bridge(struct acpi_device *adev)  {  	struct acpiphp_bridge *bridge; -	bridge = acpiphp_handle_to_bridge(handle); +	bridge = acpiphp_dev_to_bridge(adev);  	if (bridge) { +		pci_lock_rescan_remove(); +  		acpiphp_check_bridge(bridge); + +		pci_unlock_rescan_remove();  		put_bridge(bridge);  	}  } -static void hotplug_event(acpi_handle handle, u32 type, void *data) +static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot); + +static void hotplug_event(u32 type, struct acpiphp_context *context)  { -	struct acpiphp_context *context = data; +	acpi_handle handle = context->hp.self->handle;  	struct acpiphp_func *func = &context->func; +	struct acpiphp_slot *slot = func->slot;  	struct acpiphp_bridge *bridge; -	char objname[64]; -	struct acpi_buffer buffer = { .length = sizeof(objname), -				      .pointer = objname }; -	mutex_lock(&acpiphp_context_lock); +	acpi_lock_hp_context();  	bridge = context->bridge;  	if (bridge)  		get_bridge(bridge); -	mutex_unlock(&acpiphp_context_lock); +	acpi_unlock_hp_context(); -	acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); +	pci_lock_rescan_remove();  	switch (type) {  	case ACPI_NOTIFY_BUS_CHECK:  		/* bus re-enumerate */ -		dbg("%s: Bus check notify on %s\n", __func__, objname); -		dbg("%s: re-enumerating slots under %s\n", __func__, objname); -		if (bridge) { +		acpi_handle_debug(handle, "Bus check in %s()\n", __func__); +		if (bridge)  			acpiphp_check_bridge(bridge); -		} else { -			struct acpiphp_slot *slot = func->slot; - -			mutex_lock(&slot->crit_sect); +		else if (!(slot->flags & SLOT_IS_GOING_AWAY))  			enable_slot(slot); -			mutex_unlock(&slot->crit_sect); -		} +  		break;  	case ACPI_NOTIFY_DEVICE_CHECK:  		/* device check */ -		dbg("%s: Device check notify on %s\n", __func__, objname); +		acpi_handle_debug(handle, "Device check in %s()\n", __func__);  		if (bridge) {  			acpiphp_check_bridge(bridge); -		} else { -			struct acpiphp_slot *slot = func->slot; -			int ret; - +		} else if (!(slot->flags & SLOT_IS_GOING_AWAY)) {  			/*  			 * Check if anything has changed in the slot and rescan  			 * from the parent if that's the case.  			 */ -			mutex_lock(&slot->crit_sect); -			ret = acpiphp_rescan_slot(slot); -			mutex_unlock(&slot->crit_sect); -			if (ret) +			if (acpiphp_rescan_slot(slot))  				acpiphp_check_bridge(func->parent);  		}  		break;  	case ACPI_NOTIFY_EJECT_REQUEST:  		/* request device eject */ -		dbg("%s: Device eject notify on %s\n", __func__, objname); -		acpiphp_disable_and_eject_slot(func->slot); +		acpi_handle_debug(handle, "Eject request in %s()\n", __func__); +		acpiphp_disable_and_eject_slot(slot);  		break;  	} +	pci_unlock_rescan_remove();  	if (bridge)  		put_bridge(bridge);  } -static void hotplug_event_work(struct work_struct *work) +static int acpiphp_hotplug_notify(struct acpi_device *adev, u32 type)  {  	struct acpiphp_context *context; -	struct acpi_hp_work *hp_work; - -	hp_work = container_of(work, struct acpi_hp_work, work); -	context = hp_work->context; -	acpi_scan_lock_acquire(); -	hotplug_event(hp_work->handle, hp_work->type, context); +	context = acpiphp_grab_context(adev); +	if (!context) +		return -ENODATA; -	acpi_scan_lock_release(); -	acpi_evaluate_hotplug_ost(hp_work->handle, hp_work->type, -				  ACPI_OST_SC_SUCCESS, NULL); -	kfree(hp_work); /* allocated in handle_hotplug_event() */ -	put_bridge(context->func.parent); +	hotplug_event(type, context); +	acpiphp_let_context_go(context); +	return 0;  }  /** - * handle_hotplug_event - handle ACPI hotplug event - * @handle: Notify()'ed acpi_handle - * @type: Notify code - * @data: pointer to acpiphp_context structure + * acpiphp_enumerate_slots - Enumerate PCI slots for a given bus. + * @bus: PCI bus to enumerate the slots for.   * - * Handles ACPI event notification on slots. - */ -static void handle_hotplug_event(acpi_handle handle, u32 type, void *data) -{ -	struct acpiphp_context *context; -	u32 ost_code = ACPI_OST_SC_SUCCESS; - -	switch (type) { -	case ACPI_NOTIFY_BUS_CHECK: -	case ACPI_NOTIFY_DEVICE_CHECK: -		break; -	case ACPI_NOTIFY_EJECT_REQUEST: -		ost_code = ACPI_OST_SC_EJECT_IN_PROGRESS; -		acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); -		break; - -	case ACPI_NOTIFY_DEVICE_WAKE: -		return; - -	case ACPI_NOTIFY_FREQUENCY_MISMATCH: -		acpi_handle_err(handle, "Device cannot be configured due " -				"to a frequency mismatch\n"); -		goto out; - -	case ACPI_NOTIFY_BUS_MODE_MISMATCH: -		acpi_handle_err(handle, "Device cannot be configured due " -				"to a bus mode mismatch\n"); -		goto out; - -	case ACPI_NOTIFY_POWER_FAULT: -		acpi_handle_err(handle, "Device has suffered a power fault\n"); -		goto out; - -	default: -		acpi_handle_warn(handle, "Unsupported event type 0x%x\n", type); -		ost_code = ACPI_OST_SC_UNRECOGNIZED_NOTIFY; -		goto out; -	} - -	mutex_lock(&acpiphp_context_lock); -	context = acpiphp_get_context(handle); -	if (context) { -		get_bridge(context->func.parent); -		acpiphp_put_context(context); -		alloc_acpi_hp_work(handle, type, context, hotplug_event_work); -		mutex_unlock(&acpiphp_context_lock); -		return; -	} -	mutex_unlock(&acpiphp_context_lock); -	ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; - - out: -	acpi_evaluate_hotplug_ost(handle, type, ost_code, NULL); -} - -/* - * Create hotplug slots for the PCI bus. - * It should always return 0 to avoid skipping following notifiers. + * A "slot" is an object associated with a PCI device number.  All functions + * (PCI devices) with the same bus and device number belong to the same slot.   */  void acpiphp_enumerate_slots(struct pci_bus *bus)  {  	struct acpiphp_bridge *bridge; +	struct acpi_device *adev;  	acpi_handle handle;  	acpi_status status;  	if (acpiphp_disabled)  		return; -	handle = ACPI_HANDLE(bus->bridge); -	if (!handle) +	adev = ACPI_COMPANION(bus->bridge); +	if (!adev)  		return; +	handle = adev->handle;  	bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);  	if (!bridge) {  		acpi_handle_err(handle, "No memory for bridge object\n"); @@ -989,45 +875,79 @@ void acpiphp_enumerate_slots(struct pci_bus *bus)  	 */  	get_device(&bus->dev); -	if (!pci_is_root_bus(bridge->pci_bus)) { +	acpi_lock_hp_context(); +	if (pci_is_root_bus(bridge->pci_bus)) { +		struct acpiphp_root_context *root_context; + +		root_context = kzalloc(sizeof(*root_context), GFP_KERNEL); +		if (!root_context) +			goto err; + +		root_context->root_bridge = bridge; +		acpi_set_hp_context(adev, &root_context->hp, NULL, NULL, NULL); +	} else {  		struct acpiphp_context *context;  		/*  		 * This bridge should have been registered as a hotplug function -		 * under its parent, so the context has to be there.  If not, we -		 * are in deep goo. +		 * under its parent, so the context should be there, unless the +		 * parent is going to be handled by pciehp, in which case this +		 * bridge is not interesting to us either.  		 */ -		mutex_lock(&acpiphp_context_lock); -		context = acpiphp_get_context(handle); -		if (WARN_ON(!context)) { -			mutex_unlock(&acpiphp_context_lock); -			put_device(&bus->dev); -			kfree(bridge); -			return; -		} +		context = acpiphp_get_context(adev); +		if (!context) +			goto err; +  		bridge->context = context;  		context->bridge = bridge;  		/* Get a reference to the parent bridge. */  		get_bridge(context->func.parent); -		mutex_unlock(&acpiphp_context_lock);  	} +	acpi_unlock_hp_context(); -	/* must be added to the list prior to calling register_slot */ +	/* Must be added to the list prior to calling acpiphp_add_context(). */  	mutex_lock(&bridge_mutex);  	list_add(&bridge->list, &bridge_list);  	mutex_unlock(&bridge_mutex);  	/* register all slot objects under this bridge */  	status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, -				     register_slot, NULL, bridge, NULL); +				     acpiphp_add_context, NULL, bridge, NULL);  	if (ACPI_FAILURE(status)) {  		acpi_handle_err(handle, "failed to register slots\n");  		cleanup_bridge(bridge);  		put_bridge(bridge);  	} +	return; + + err: +	acpi_unlock_hp_context(); +	put_device(&bus->dev); +	pci_dev_put(bridge->pci_dev); +	kfree(bridge);  } -/* Destroy hotplug slots associated with the PCI bus */ +void acpiphp_drop_bridge(struct acpiphp_bridge *bridge) +{ +	if (pci_is_root_bus(bridge->pci_bus)) { +		struct acpiphp_root_context *root_context; +		struct acpi_device *adev; + +		acpi_lock_hp_context(); +		adev = ACPI_COMPANION(bridge->pci_bus->bridge); +		root_context = to_acpiphp_root_context(adev->hp); +		adev->hp = NULL; +		acpi_unlock_hp_context(); +		kfree(root_context); +	} +	cleanup_bridge(bridge); +	put_bridge(bridge); +} + +/** + * acpiphp_remove_slots - Remove slot objects associated with a given bus. + * @bus: PCI bus to remove the slot objects for. + */  void acpiphp_remove_slots(struct pci_bus *bus)  {  	struct acpiphp_bridge *bridge; @@ -1039,8 +959,7 @@ void acpiphp_remove_slots(struct pci_bus *bus)  	list_for_each_entry(bridge, &bridge_list, list)  		if (bridge->pci_bus == bus) {  			mutex_unlock(&bridge_mutex); -			cleanup_bridge(bridge); -			put_bridge(bridge); +			acpiphp_drop_bridge(bridge);  			return;  		} @@ -1053,12 +972,16 @@ void acpiphp_remove_slots(struct pci_bus *bus)   */  int acpiphp_enable_slot(struct acpiphp_slot *slot)  { -	mutex_lock(&slot->crit_sect); +	pci_lock_rescan_remove(); + +	if (slot->flags & SLOT_IS_GOING_AWAY) +		return -ENODEV; +  	/* configure all functions */  	if (!(slot->flags & SLOT_ENABLED))  		enable_slot(slot); -	mutex_unlock(&slot->crit_sect); +	pci_unlock_rescan_remove();  	return 0;  } @@ -1066,12 +989,12 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)   * acpiphp_disable_and_eject_slot - power off and eject slot   * @slot: ACPI PHP slot   */ -int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot) +static int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)  {  	struct acpiphp_func *func; -	int retval = 0; -	mutex_lock(&slot->crit_sect); +	if (slot->flags & SLOT_IS_GOING_AWAY) +		return -ENODEV;  	/* unconfigure all functions */  	disable_slot(slot); @@ -1086,10 +1009,24 @@ int acpiphp_disable_and_eject_slot(struct acpiphp_slot *slot)  			break;  		} -	mutex_unlock(&slot->crit_sect); -	return retval; +	return 0;  } +int acpiphp_disable_slot(struct acpiphp_slot *slot) +{ +	int ret; + +	/* +	 * Acquire acpi_scan_lock to ensure that the execution of _EJ0 in +	 * acpiphp_disable_and_eject_slot() will be synchronized properly. +	 */ +	acpi_scan_lock_acquire(); +	pci_lock_rescan_remove(); +	ret = acpiphp_disable_and_eject_slot(slot); +	pci_unlock_rescan_remove(); +	acpi_scan_lock_release(); +	return ret; +}  /*   * slot enabled:  1 @@ -1100,7 +1037,6 @@ u8 acpiphp_get_power_status(struct acpiphp_slot *slot)  	return (slot->flags & SLOT_ENABLED);  } -  /*   * latch   open:  1   * latch closed:  0 @@ -1110,7 +1046,6 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot)  	return !(get_slot_status(slot) & ACPI_STA_DEVICE_UI);  } -  /*   * adapter presence : 1   *          absence : 0 diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 2f5786c8522..8dcccffd6e2 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -25,16 +25,17 @@   *   */ +#define pr_fmt(fmt) "acpiphp_ibm: " fmt +  #include <linux/init.h>  #include <linux/slab.h>  #include <linux/module.h>  #include <linux/kernel.h> -#include <acpi/acpi_bus.h>  #include <linux/sysfs.h>  #include <linux/kobject.h> -#include <asm/uaccess.h>  #include <linux/moduleparam.h>  #include <linux/pci.h> +#include <asm/uaccess.h>  #include "acpiphp.h"  #include "../pci.h" @@ -43,23 +44,11 @@  #define DRIVER_AUTHOR	"Irene Zubarev <zubarev@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"  #define DRIVER_DESC	"ACPI Hot Plug PCI Controller Driver IBM extension" -static bool debug;  MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL");  MODULE_VERSION(DRIVER_VERSION); -module_param(debug, bool, 0644); -MODULE_PARM_DESC(debug, " Debugging mode enabled or not"); -#define MY_NAME "acpiphp_ibm" - -#undef dbg -#define dbg(format, arg...)				\ -do {							\ -	if (debug)					\ -		printk(KERN_DEBUG "%s: " format,	\ -				MY_NAME , ## arg);	\ -} while (0)  #define FOUND_APCI 0x61504349  /* these are the names for the IBM ACPI pseudo-device */ @@ -126,7 +115,7 @@ static struct bin_attribute ibm_apci_table_attr = {  	    .read = ibm_read_apci_table,  	    .write = NULL,  }; -static struct acpiphp_attention_info ibm_attention_info =  +static struct acpiphp_attention_info ibm_attention_info =  {  	.set_attn = ibm_set_attention_status,  	.get_attn = ibm_get_attention_status, @@ -181,15 +170,15 @@ ibm_slot_done:   */  static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)  { -	union acpi_object args[2];  +	union acpi_object args[2];  	struct acpi_object_list params = { .pointer = args, .count = 2 }; -	acpi_status stat;  +	acpi_status stat;  	unsigned long long rc;  	union apci_descriptor *ibm_slot;  	ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); -	dbg("%s: set slot %d (%d) attention status to %d\n", __func__, +	pr_debug("%s: set slot %d (%d) attention status to %d\n", __func__,  			ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,  			(status ? 1 : 0)); @@ -202,10 +191,10 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)  	stat = acpi_evaluate_integer(ibm_acpi_handle, "APLS", ¶ms, &rc);  	if (ACPI_FAILURE(stat)) { -		err("APLS evaluation failed:  0x%08x\n", stat); +		pr_err("APLS evaluation failed:  0x%08x\n", stat);  		return -ENODEV;  	} else if (!rc) { -		err("APLS method failed:  0x%08llx\n", rc); +		pr_err("APLS method failed:  0x%08llx\n", rc);  		return -ERANGE;  	}  	return 0; @@ -218,7 +207,7 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)   *   * Description: This method is registered with the acpiphp module as a   * callback to do the device specific task of getting the LED status. - *  + *   * Because there is no direct method of getting the LED status directly   * from an ACPI call, we read the aPCI table and parse out our   * slot descriptor to read the status from that. @@ -234,7 +223,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)  	else  		*status = 0; -	dbg("%s: get slot %d (%d) attention status is %d\n", __func__, +	pr_debug("%s: get slot %d (%d) attention status is %d\n", __func__,  			ibm_slot->slot.slot_num, ibm_slot->slot.slot_id,  			*status); @@ -266,10 +255,10 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)  	u8 subevent = event & 0xf0;  	struct notification *note = context; -	dbg("%s: Received notification %02x\n", __func__, event); +	pr_debug("%s: Received notification %02x\n", __func__, event);  	if (subevent == 0x80) { -		dbg("%s: generationg bus event\n", __func__); +		pr_debug("%s: generating bus event\n", __func__);  		acpi_bus_generate_netlink_event(note->device->pnp.device_class,  						  dev_name(¬e->device->dev),  						  note->event, detail); @@ -301,7 +290,7 @@ static int ibm_get_table_from_acpi(char **bufp)  	status = acpi_evaluate_object(ibm_acpi_handle, "APCI", NULL, &buffer);  	if (ACPI_FAILURE(status)) { -		err("%s:  APCI evaluation failed\n", __func__); +		pr_err("%s:  APCI evaluation failed\n", __func__);  		return -ENODEV;  	} @@ -309,13 +298,13 @@ static int ibm_get_table_from_acpi(char **bufp)  	if (!(package) ||  			(package->type != ACPI_TYPE_PACKAGE) ||  			!(package->package.elements)) { -		err("%s:  Invalid APCI object\n", __func__); +		pr_err("%s:  Invalid APCI object\n", __func__);  		goto read_table_done;  	}  	for(size = 0, i = 0; i < package->package.count; i++) {  		if (package->package.elements[i].type != ACPI_TYPE_BUFFER) { -			err("%s:  Invalid APCI element %d\n", __func__, i); +			pr_err("%s:  Invalid APCI element %d\n", __func__, i);  			goto read_table_done;  		}  		size += package->package.elements[i].buffer.length; @@ -325,7 +314,7 @@ static int ibm_get_table_from_acpi(char **bufp)  		goto read_table_done;  	lbuf = kzalloc(size, GFP_KERNEL); -	dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n", +	pr_debug("%s: element count: %i, ASL table size: %i, &table = 0x%p\n",  			__func__, package->package.count, size, lbuf);  	if (lbuf) { @@ -370,8 +359,8 @@ static ssize_t ibm_read_apci_table(struct file *filp, struct kobject *kobj,  {  	int bytes_read = -EINVAL;  	char *table = NULL; -	 -	dbg("%s: pos = %d, size = %zd\n", __func__, (int)pos, size); + +	pr_debug("%s: pos = %d, size = %zd\n", __func__, (int)pos, size);  	if (pos == 0) {  		bytes_read = ibm_get_table_from_acpi(&table); @@ -397,13 +386,13 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,  		u32 lvl, void *context, void **rv)  {  	acpi_handle *phandle = (acpi_handle *)context; -	acpi_status status;  +	acpi_status status;  	struct acpi_device_info *info;  	int retval = 0;  	status = acpi_get_object_info(handle, &info);  	if (ACPI_FAILURE(status)) { -		err("%s:  Failed to get device information status=0x%x\n", +		pr_err("%s:  Failed to get device information status=0x%x\n",  			__func__, status);  		return retval;  	} @@ -411,11 +400,11 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle,  	if (info->current_status && (info->valid & ACPI_VALID_HID) &&  			(!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) ||  			 !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) { -		dbg("found hardware: %s, handle: %p\n", +		pr_debug("found hardware: %s, handle: %p\n",  			info->hardware_id.string, handle);  		*phandle = handle;  		/* returning non-zero causes the search to stop -		 * and returns this value to the caller of  +		 * and returns this value to the caller of  		 * acpi_walk_namespace, but it also causes some warnings  		 * in the acpi debug code to print...  		 */ @@ -432,18 +421,18 @@ static int __init ibm_acpiphp_init(void)  	struct acpi_device *device;  	struct kobject *sysdir = &pci_slots_kset->kobj; -	dbg("%s\n", __func__); +	pr_debug("%s\n", __func__);  	if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,  			ACPI_UINT32_MAX, ibm_find_acpi_device, NULL,  			&ibm_acpi_handle, NULL) != FOUND_APCI) { -		err("%s: acpi_walk_namespace failed\n", __func__); +		pr_err("%s: acpi_walk_namespace failed\n", __func__);  		retval = -ENODEV;  		goto init_return;  	} -	dbg("%s: found IBM aPCI device\n", __func__); +	pr_debug("%s: found IBM aPCI device\n", __func__);  	if (acpi_bus_get_device(ibm_acpi_handle, &device)) { -		err("%s: acpi_bus_get_device failed\n", __func__); +		pr_err("%s: acpi_bus_get_device failed\n", __func__);  		retval = -ENODEV;  		goto init_return;  	} @@ -457,7 +446,7 @@ static int __init ibm_acpiphp_init(void)  			ACPI_DEVICE_NOTIFY, ibm_handle_events,  			&ibm_note);  	if (ACPI_FAILURE(status)) { -		err("%s: Failed to register notification handler\n", +		pr_err("%s: Failed to register notification handler\n",  				__func__);  		retval = -EBUSY;  		goto init_cleanup; @@ -479,17 +468,17 @@ static void __exit ibm_acpiphp_exit(void)  	acpi_status status;  	struct kobject *sysdir = &pci_slots_kset->kobj; -	dbg("%s\n", __func__); +	pr_debug("%s\n", __func__);  	if (acpiphp_unregister_attention(&ibm_attention_info)) -		err("%s: attention info deregistration failed", __func__); +		pr_err("%s: attention info deregistration failed", __func__);  	status = acpi_remove_notify_handler(  			   ibm_acpi_handle,  			   ACPI_DEVICE_NOTIFY,  			   ibm_handle_events);  	if (ACPI_FAILURE(status)) -		err("%s: Notification handler removal failed\n", __func__); +		pr_err("%s: Notification handler removal failed\n", __func__);  	/* remove the /sys entries */  	sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr);  } diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 1356211431d..6a0ddf75734 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h @@ -56,9 +56,9 @@ struct cpci_hp_controller_ops {  	int (*enable_irq) (void);  	int (*disable_irq) (void);  	int (*check_irq) (void *dev_id); -	int (*hardware_test) (struct slot* slot, u32 value); -	u8  (*get_power) (struct slot* slot); -	int (*set_power) (struct slot* slot, int value); +	int (*hardware_test) (struct slot *slot, u32 value); +	u8  (*get_power) (struct slot *slot); +	int (*set_power) (struct slot *slot, int value);  };  struct cpci_hp_controller { @@ -89,13 +89,13 @@ int cpci_hp_stop(void);  u8 cpci_get_attention_status(struct slot *slot);  u8 cpci_get_latch_status(struct slot *slot);  u8 cpci_get_adapter_status(struct slot *slot); -u16 cpci_get_hs_csr(struct slot * slot); +u16 cpci_get_hs_csr(struct slot *slot);  int cpci_set_attention_status(struct slot *slot, int status); -int cpci_check_and_clear_ins(struct slot * slot); -int cpci_check_ext(struct slot * slot); -int cpci_clear_ext(struct slot * slot); -int cpci_led_on(struct slot * slot); -int cpci_led_off(struct slot * slot); +int cpci_check_and_clear_ins(struct slot *slot); +int cpci_check_ext(struct slot *slot); +int cpci_clear_ext(struct slot *slot); +int cpci_led_on(struct slot *slot); +int cpci_led_off(struct slot *slot);  int cpci_configure_slot(struct slot *slot);  int cpci_unconfigure_slot(struct slot *slot); diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c index 2b4c412f94c..e09cf7827d6 100644 --- a/drivers/pci/hotplug/cpci_hotplug_core.c +++ b/drivers/pci/hotplug/cpci_hotplug_core.c @@ -46,7 +46,7 @@  	do {							\  		if (cpci_debug)					\  			printk (KERN_DEBUG "%s: " format "\n",	\ -				MY_NAME , ## arg); 		\ +				MY_NAME , ## arg);		\  	} while (0)  #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)  #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) @@ -65,10 +65,10 @@ static int thread_finished;  static int enable_slot(struct hotplug_slot *slot);  static int disable_slot(struct hotplug_slot *slot);  static int set_attention_status(struct hotplug_slot *slot, u8 value); -static int get_power_status(struct hotplug_slot *slot, u8 * value); -static int get_attention_status(struct hotplug_slot *slot, u8 * value); -static int get_adapter_status(struct hotplug_slot *slot, u8 * value); -static int get_latch_status(struct hotplug_slot *slot, u8 * value); +static int get_power_status(struct hotplug_slot *slot, u8 *value); +static int get_attention_status(struct hotplug_slot *slot, u8 *value); +static int get_adapter_status(struct hotplug_slot *slot, u8 *value); +static int get_latch_status(struct hotplug_slot *slot, u8 *value);  static struct hotplug_slot_ops cpci_hotplug_slot_ops = {  	.enable_slot = enable_slot, @@ -168,7 +168,7 @@ cpci_get_power_status(struct slot *slot)  }  static int -get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) +get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = hotplug_slot->private; @@ -177,7 +177,7 @@ get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)  }  static int -get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) +get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = hotplug_slot->private; @@ -192,14 +192,14 @@ set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)  }  static int -get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) +get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	*value = hotplug_slot->info->adapter_status;  	return 0;  }  static int -get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) +get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	*value = hotplug_slot->info->latch_status;  	return 0; @@ -299,6 +299,7 @@ error_slot:  error:  	return status;  } +EXPORT_SYMBOL_GPL(cpci_hp_register_bus);  int  cpci_hp_unregister_bus(struct pci_bus *bus) @@ -329,6 +330,7 @@ cpci_hp_unregister_bus(struct pci_bus *bus)  	up_write(&list_rwsem);  	return status;  } +EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus);  /* This is the interrupt mode interrupt handler */  static irqreturn_t @@ -360,7 +362,7 @@ static int  init_slots(int clear_ins)  {  	struct slot *slot; -	struct pci_dev* dev; +	struct pci_dev *dev;  	dbg("%s - enter", __func__);  	down_read(&list_rwsem); @@ -614,6 +616,7 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)  		controller = new_controller;  	return status;  } +EXPORT_SYMBOL_GPL(cpci_hp_register_controller);  static void  cleanup_slots(void) @@ -653,6 +656,7 @@ cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)  		status = -ENODEV;  	return status;  } +EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller);  int  cpci_hp_start(void) @@ -690,6 +694,7 @@ cpci_hp_start(void)  	dbg("%s - exit", __func__);  	return 0;  } +EXPORT_SYMBOL_GPL(cpci_hp_start);  int  cpci_hp_stop(void) @@ -704,6 +709,7 @@ cpci_hp_stop(void)  	cpci_stop_thread();  	return 0;  } +EXPORT_SYMBOL_GPL(cpci_hp_stop);  int __init  cpci_hotplug_init(int debug) @@ -721,10 +727,3 @@ cpci_hotplug_exit(void)  	cpci_hp_stop();  	cpci_hp_unregister_controller(controller);  } - -EXPORT_SYMBOL_GPL(cpci_hp_register_controller); -EXPORT_SYMBOL_GPL(cpci_hp_unregister_controller); -EXPORT_SYMBOL_GPL(cpci_hp_register_bus); -EXPORT_SYMBOL_GPL(cpci_hp_unregister_bus); -EXPORT_SYMBOL_GPL(cpci_hp_start); -EXPORT_SYMBOL_GPL(cpci_hp_stop); diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index d8add34177f..7d48ecae669 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -39,14 +39,14 @@ extern int cpci_debug;  	do {							\  		if (cpci_debug)					\  			printk (KERN_DEBUG "%s: " format "\n",	\ -				MY_NAME , ## arg); 		\ +				MY_NAME , ## arg);		\  	} while (0)  #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)  #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)  #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg) -u8 cpci_get_attention_status(struct slot* slot) +u8 cpci_get_attention_status(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -66,7 +66,7 @@ u8 cpci_get_attention_status(struct slot* slot)  	return hs_csr & 0x0008 ? 1 : 0;  } -int cpci_set_attention_status(struct slot* slot, int status) +int cpci_set_attention_status(struct slot *slot, int status)  {  	int hs_cap;  	u16 hs_csr; @@ -93,7 +93,7 @@ int cpci_set_attention_status(struct slot* slot, int status)  	return 1;  } -u16 cpci_get_hs_csr(struct slot* slot) +u16 cpci_get_hs_csr(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -111,7 +111,7 @@ u16 cpci_get_hs_csr(struct slot* slot)  	return hs_csr;  } -int cpci_check_and_clear_ins(struct slot* slot) +int cpci_check_and_clear_ins(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -140,7 +140,7 @@ int cpci_check_and_clear_ins(struct slot* slot)  	return ins;  } -int cpci_check_ext(struct slot* slot) +int cpci_check_ext(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -161,7 +161,7 @@ int cpci_check_ext(struct slot* slot)  	return ext;  } -int cpci_clear_ext(struct slot* slot) +int cpci_clear_ext(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -187,7 +187,7 @@ int cpci_clear_ext(struct slot* slot)  	return 0;  } -int cpci_led_on(struct slot* slot) +int cpci_led_on(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -216,7 +216,7 @@ int cpci_led_on(struct slot* slot)  	return 0;  } -int cpci_led_off(struct slot* slot) +int cpci_led_off(struct slot *slot)  {  	int hs_cap;  	u16 hs_csr; @@ -250,13 +250,16 @@ int cpci_led_off(struct slot* slot)   * Device configuration functions   */ -int __ref cpci_configure_slot(struct slot *slot) +int cpci_configure_slot(struct slot *slot)  {  	struct pci_dev *dev;  	struct pci_bus *parent; +	int ret = 0;  	dbg("%s - enter", __func__); +	pci_lock_rescan_remove(); +  	if (slot->dev == NULL) {  		dbg("pci_dev null, finding %02x:%02x:%x",  		    slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn)); @@ -277,7 +280,8 @@ int __ref cpci_configure_slot(struct slot *slot)  		slot->dev = pci_get_slot(slot->bus, slot->devfn);  		if (slot->dev == NULL) {  			err("Could not find PCI device for slot %02x", slot->number); -			return -ENODEV; +			ret = -ENODEV; +			goto out;  		}  	}  	parent = slot->dev->bus; @@ -285,8 +289,7 @@ int __ref cpci_configure_slot(struct slot *slot)  	list_for_each_entry(dev, &parent->devices, bus_list)  		if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))  			continue; -		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || -		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) +		if (pci_is_bridge(dev))  			pci_hp_add_bridge(dev); @@ -294,11 +297,13 @@ int __ref cpci_configure_slot(struct slot *slot)  	pci_bus_add_devices(parent); + out: +	pci_unlock_rescan_remove();  	dbg("%s - exit", __func__); -	return 0; +	return ret;  } -int cpci_unconfigure_slot(struct slot* slot) +int cpci_unconfigure_slot(struct slot *slot)  {  	struct pci_dev *dev, *temp; @@ -308,6 +313,8 @@ int cpci_unconfigure_slot(struct slot* slot)  		return -ENODEV;  	} +	pci_lock_rescan_remove(); +  	list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {  		if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))  			continue; @@ -318,6 +325,8 @@ int cpci_unconfigure_slot(struct slot* slot)  	pci_dev_put(slot->dev);  	slot->dev = NULL; +	pci_unlock_rescan_remove(); +  	dbg("%s - exit", __func__);  	return 0;  } diff --git a/drivers/pci/hotplug/cpcihp_generic.c b/drivers/pci/hotplug/cpcihp_generic.c index a6a71c41cdf..04fcd781140 100644 --- a/drivers/pci/hotplug/cpcihp_generic.c +++ b/drivers/pci/hotplug/cpcihp_generic.c @@ -13,14 +13,14 @@   * option) any later version.   *   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY  - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   *   * You should have received a copy of the GNU General Public License along @@ -53,9 +53,9 @@  #define dbg(format, arg...)					\  	do {							\ -		if(debug)					\ +		if (debug)					\  			printk (KERN_DEBUG "%s: " format "\n",	\ -				MY_NAME , ## arg); 		\ +				MY_NAME , ## arg);		\  	} while(0)  #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)  #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) @@ -78,8 +78,8 @@ static struct cpci_hp_controller generic_hpc;  static int __init validate_parameters(void)  { -	char* str; -	char* p; +	char *str; +	char *p;  	unsigned long tmp;  	if(!bridge) { @@ -142,8 +142,8 @@ static int query_enum(void)  static int __init cpcihp_generic_init(void)  {  	int status; -	struct resource* r; -	struct pci_dev* dev; +	struct resource *r; +	struct pci_dev *dev;  	info(DRIVER_DESC " version: " DRIVER_VERSION);  	status = validate_parameters(); diff --git a/drivers/pci/hotplug/cpcihp_zt5550.c b/drivers/pci/hotplug/cpcihp_zt5550.c index 449b4bbc830..6757b3ef7e1 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.c +++ b/drivers/pci/hotplug/cpcihp_zt5550.c @@ -13,14 +13,14 @@   * option) any later version.   *   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY  - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   *   * You should have received a copy of the GNU General Public License along @@ -48,9 +48,9 @@  #define dbg(format, arg...)					\  	do {							\ -		if(debug)					\ +		if (debug)					\  			printk (KERN_DEBUG "%s: " format "\n",	\ -				MY_NAME , ## arg); 		\ +				MY_NAME , ## arg);		\  	} while(0)  #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)  #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) @@ -285,7 +285,7 @@ static struct pci_device_id zt5550_hc_pci_tbl[] = {  	{ 0, }  };  MODULE_DEVICE_TABLE(pci, zt5550_hc_pci_tbl); -	 +  static struct pci_driver zt5550_hc_driver = {  	.name		= "zt5550_hc",  	.id_table	= zt5550_hc_pci_tbl, @@ -295,7 +295,7 @@ static struct pci_driver zt5550_hc_driver = {  static int __init zt5550_init(void)  { -	struct resource* r; +	struct resource *r;  	int rc;  	info(DRIVER_DESC " version: " DRIVER_VERSION); diff --git a/drivers/pci/hotplug/cpcihp_zt5550.h b/drivers/pci/hotplug/cpcihp_zt5550.h index bebc6060a55..9a57fda5348 100644 --- a/drivers/pci/hotplug/cpcihp_zt5550.h +++ b/drivers/pci/hotplug/cpcihp_zt5550.h @@ -13,14 +13,14 @@   * option) any later version.   *   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY  - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL  - * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,  - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   *   * You should have received a copy of the GNU General Public License along @@ -55,7 +55,7 @@  #define HC_CMD_REG		0x0C  #define ARB_CONFIG_GNT_REG	0x10  #define ARB_CONFIG_CFG_REG	0x12 -#define ARB_CONFIG_REG	 	0x10 +#define ARB_CONFIG_REG		0x10  #define ISOL_CONFIG_REG		0x18  #define FAULT_STATUS_REG	0x20  #define FAULT_CONFIG_REG	0x24 diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index 516b87738b6..0450f405807 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -255,7 +255,7 @@ struct pci_func {  	struct pci_resource *io_head;  	struct pci_resource *bus_head;  	struct timer_list *p_task_event; -	struct pci_dev* pci_dev; +	struct pci_dev *pci_dev;  };  struct slot { @@ -278,7 +278,7 @@ struct slot {  };  struct pci_resource { -	struct pci_resource * next; +	struct pci_resource *next;  	u32 base;  	u32 length;  }; diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c index c8eaeb43fa5..4aaee746df8 100644 --- a/drivers/pci/hotplug/cpqphp_core.c +++ b/drivers/pci/hotplug/cpqphp_core.c @@ -94,7 +94,7 @@ static inline int is_slot66mhz(struct slot *slot)   *   * Returns pointer to the head of the SMBIOS tables (or %NULL).   */ -static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end) +static void __iomem *detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end)  {  	void __iomem *fp;  	void __iomem *endp; @@ -131,7 +131,7 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e   *   * For unexpected switch opens   */ -static int init_SERR(struct controller * ctrl) +static int init_SERR(struct controller *ctrl)  {  	u32 tempdword;  	u32 number_of_slots; @@ -291,7 +291,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)  	kfree(slot);  } -static int ctrl_slot_cleanup (struct controller * ctrl) +static int ctrl_slot_cleanup (struct controller *ctrl)  {  	struct slot *old_slot, *next_slot; @@ -706,8 +706,7 @@ static int ctrl_slot_setup(struct controller *ctrl,  		hotplug_slot_info->adapter_status =  			get_presence_status(ctrl, slot); -		dbg("registering bus %d, dev %d, number %d, " -				"ctrl->slot_device_offset %d, slot %d\n", +		dbg("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n",  				slot->bus, slot->device,  				slot->number, ctrl->slot_device_offset,  				slot_number); @@ -837,8 +836,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	bus = pdev->subordinate;  	if (!bus) { -		dev_notice(&pdev->dev, "the device is not a bridge, " -				"skipping\n"); +		dev_notice(&pdev->dev, "the device is not a bridge, skipping\n");  		rc = -ENODEV;  		goto err_disable_device;  	} @@ -862,10 +860,10 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  		goto err_disable_device;  	} -	/* Check for the proper subsystem ID's +	/* Check for the proper subsystem IDs  	 * Intel uses a different SSID programming model than Compaq.  	 * For Intel, each SSID bit identifies a PHP capability. -	 * Also Intel HPC's may have RID=0. +	 * Also Intel HPCs may have RID=0.  	 */  	if ((pdev->revision <= 2) && (vendor_id != PCI_VENDOR_ID_INTEL)) {  		err(msg_HPC_not_supported); @@ -920,12 +918,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  				bus->max_bus_speed = PCI_SPEED_100MHz_PCIX;  				break;  			} -			if (bus_cap & 20) { +			if (bus_cap & 0x20) {  				dbg("bus max supports 66MHz PCI-X\n");  				bus->max_bus_speed = PCI_SPEED_66MHz_PCIX;  				break;  			} -			if (bus_cap & 10) { +			if (bus_cap & 0x10) {  				dbg("bus max supports 66MHz PCI\n");  				bus->max_bus_speed = PCI_SPEED_66MHz;  				break; diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index d282019cda5..bde47fce324 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -39,9 +39,9 @@  #include <linux/kthread.h>  #include "cpqphp.h" -static u32 configure_new_device(struct controller* ctrl, struct pci_func *func, +static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,  			u8 behind_bridge, struct resource_lists *resources); -static int configure_new_function(struct controller* ctrl, struct pci_func *func, +static int configure_new_function(struct controller *ctrl, struct pci_func *func,  			u8 behind_bridge, struct resource_lists *resources);  static void interrupt_event_handler(struct controller *ctrl); @@ -64,7 +64,7 @@ static void long_delay(int delay)  /* FIXME: The following line needs to be somewhere else... */  #define WRONG_BUS_FREQUENCY 0x07 -static u8 handle_switch_change(u8 change, struct controller * ctrl) +static u8 handle_switch_change(u8 change, struct controller *ctrl)  {  	int hp_slot;  	u8 rc = 0; @@ -138,7 +138,7 @@ static struct slot *cpqhp_find_slot(struct controller *ctrl, u8 device)  } -static u8 handle_presence_change(u16 change, struct controller * ctrl) +static u8 handle_presence_change(u16 change, struct controller *ctrl)  {  	int hp_slot;  	u8 rc = 0; @@ -232,7 +232,7 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)  } -static u8 handle_power_fault(u8 change, struct controller * ctrl) +static u8 handle_power_fault(u8 change, struct controller *ctrl)  {  	int hp_slot;  	u8 rc = 0; @@ -709,7 +709,8 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz  				temp = temp->next;  			} -			temp->next = max->next; +			if (temp) +				temp->next = max->next;  		}  		max->next = NULL; @@ -996,7 +997,7 @@ struct pci_func *cpqhp_slot_create(u8 busnumber)   *   * Returns %0 if successful, !0 otherwise.   */ -static int slot_remove(struct pci_func * old_slot) +static int slot_remove(struct pci_func *old_slot)  {  	struct pci_func *next; @@ -1108,7 +1109,7 @@ struct pci_func *cpqhp_slot_find(u8 bus, u8 device, u8 index)  /* DJZ: I don't think is_bridge will work as is.   * FIXME */ -static int is_bridge(struct pci_func * func) +static int is_bridge(struct pci_func *func)  {  	/* Check the header type */  	if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01) @@ -1231,7 +1232,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_  	/* Only if mode change...*/  	if (((bus->cur_bus_speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) || -		((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz)))  +		((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz)))  			set_SOGO(ctrl);  	wait_for_ctrl_irq(ctrl); @@ -1624,7 +1625,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)   * @replace_flag: whether replacing or adding a new device   * @ctrl: target controller   */ -static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl) +static u32 remove_board(struct pci_func *func, u32 replace_flag, struct controller *ctrl)  {  	int index;  	u8 skip = 0; @@ -1741,7 +1742,7 @@ static void pushbutton_helper_thread(unsigned long data)  /* this is the main worker thread */ -static int event_thread(void* data) +static int event_thread(void *data)  {  	struct controller *ctrl; @@ -1828,7 +1829,7 @@ static void interrupt_event_handler(struct controller *ctrl)  				if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {  					dbg("button pressed\n"); -				} else if (ctrl->event_queue[loop].event_type ==  +				} else if (ctrl->event_queue[loop].event_type ==  					   INT_BUTTON_CANCEL) {  					dbg("button cancel\n");  					del_timer(&p_slot->task_event); @@ -1991,7 +1992,7 @@ int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func)  	u16 temp_word;  	u32 tempdword;  	int rc; -	struct slot* p_slot; +	struct slot *p_slot;  	int physical_slot = 0;  	tempdword = 0; @@ -2087,7 +2088,7 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)  	u8 replace_flag;  	u32 rc = 0;  	unsigned int devfn; -	struct slot* p_slot; +	struct slot *p_slot;  	struct pci_bus *pci_bus = ctrl->pci_bus;  	int physical_slot=0; @@ -2269,8 +2270,8 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)   *   * Returns 0 if success.   */ -static u32 configure_new_device(struct controller * ctrl, struct pci_func * func, -				 u8 behind_bridge, struct resource_lists * resources) +static u32 configure_new_device(struct controller  *ctrl, struct pci_func  *func, +				 u8 behind_bridge, struct resource_lists  *resources)  {  	u8 temp_byte, function, max_functions, stop_it;  	int rc; @@ -2411,11 +2412,11 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func  		if (rc)  			return rc; -		/* find range of busses to use */ +		/* find range of buses to use */  		dbg("find ranges of buses to use\n");  		bus_node = get_max_resource(&(resources->bus_head), 1); -		/* If we don't have any busses to allocate, we can't continue */ +		/* If we don't have any buses to allocate, we can't continue */  		if (!bus_node)  			return -ENOMEM; @@ -2900,7 +2901,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func  			/* If this function needs an interrupt and we are behind  			 * a bridge and the pin is tied to something that's -			 * alread mapped, set this one the same */ +			 * already mapped, set this one the same */  			if (temp_byte && resources->irqs &&  			    (resources->irqs->valid_INT &  			     (0x01 << ((temp_byte + resources->irqs->barber_pole - 1) & 0x03)))) { diff --git a/drivers/pci/hotplug/cpqphp_nvram.c b/drivers/pci/hotplug/cpqphp_nvram.c index 76ba8a1c774..0968a9bcb34 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.c +++ b/drivers/pci/hotplug/cpqphp_nvram.c @@ -34,7 +34,6 @@  #include <linux/workqueue.h>  #include <linux/pci.h>  #include <linux/pci_hotplug.h> -#include <linux/init.h>  #include <asm/uaccess.h>  #include "cpqphp.h"  #include "cpqphp_nvram.h" @@ -108,7 +107,7 @@ static spinlock_t int15_lock;   */ -static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail) +static u32 add_byte(u32 **p_buffer, u8 value, u32 *used, u32 *avail)  {  	u8 **tByte; @@ -123,7 +122,7 @@ static u32 add_byte( u32 **p_buffer, u8 value, u32 *used, u32 *avail)  } -static u32 add_dword( u32 **p_buffer, u32 value, u32 *used, u32 *avail) +static u32 add_dword(u32 **p_buffer, u32 value, u32 *used, u32 *avail)  {  	if ((*used + 4) > *avail)  		return(1); @@ -268,12 +267,12 @@ static u32 store_HRT (void __iomem *rom_start)  	ctrl = cpqhp_ctrl_list;  	/* The revision of this structure */ -	rc = add_byte( &pFill, 1 + ctrl->push_flag, &usedbytes, &available); +	rc = add_byte(&pFill, 1 + ctrl->push_flag, &usedbytes, &available);  	if (rc)  		return(rc);  	/* The number of controllers */ -	rc = add_byte( &pFill, 1, &usedbytes, &available); +	rc = add_byte(&pFill, 1, &usedbytes, &available);  	if (rc)  		return(rc); @@ -283,22 +282,22 @@ static u32 store_HRT (void __iomem *rom_start)  		numCtrl++;  		/* The bus number */ -		rc = add_byte( &pFill, ctrl->bus, &usedbytes, &available); +		rc = add_byte(&pFill, ctrl->bus, &usedbytes, &available);  		if (rc)  			return(rc);  		/* The device Number */ -		rc = add_byte( &pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available); +		rc = add_byte(&pFill, PCI_SLOT(ctrl->pci_dev->devfn), &usedbytes, &available);  		if (rc)  			return(rc);  		/* The function Number */ -		rc = add_byte( &pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available); +		rc = add_byte(&pFill, PCI_FUNC(ctrl->pci_dev->devfn), &usedbytes, &available);  		if (rc)  			return(rc);  		/* Skip the number of available entries */ -		rc = add_dword( &pFill, 0, &usedbytes, &available); +		rc = add_dword(&pFill, 0, &usedbytes, &available);  		if (rc)  			return(rc); @@ -312,12 +311,12 @@ static u32 store_HRT (void __iomem *rom_start)  			loop ++;  			/* base */ -			rc = add_dword( &pFill, resNode->base, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->base, &usedbytes, &available);  			if (rc)  				return(rc);  			/* length */ -			rc = add_dword( &pFill, resNode->length, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->length, &usedbytes, &available);  			if (rc)  				return(rc); @@ -337,12 +336,12 @@ static u32 store_HRT (void __iomem *rom_start)  			loop ++;  			/* base */ -			rc = add_dword( &pFill, resNode->base, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->base, &usedbytes, &available);  			if (rc)  				return(rc);  			/* length */ -			rc = add_dword( &pFill, resNode->length, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->length, &usedbytes, &available);  			if (rc)  				return(rc); @@ -362,12 +361,12 @@ static u32 store_HRT (void __iomem *rom_start)  			loop ++;  			/* base */ -			rc = add_dword( &pFill, resNode->base, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->base, &usedbytes, &available);  			if (rc)  				return(rc);  			/* length */ -			rc = add_dword( &pFill, resNode->length, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->length, &usedbytes, &available);  			if (rc)  				return(rc); @@ -387,12 +386,12 @@ static u32 store_HRT (void __iomem *rom_start)  			loop ++;  			/* base */ -			rc = add_dword( &pFill, resNode->base, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->base, &usedbytes, &available);  			if (rc)  				return(rc);  			/* length */ -			rc = add_dword( &pFill, resNode->length, &usedbytes, &available); +			rc = add_dword(&pFill, resNode->length, &usedbytes, &available);  			if (rc)  				return(rc); diff --git a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c index 09801c6945c..1c8c2f130d3 100644 --- a/drivers/pci/hotplug/cpqphp_pci.c +++ b/drivers/pci/hotplug/cpqphp_pci.c @@ -81,11 +81,13 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom  } -int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) +int cpqhp_configure_device (struct controller *ctrl, struct pci_func *func)  {  	struct pci_bus *child;  	int num; +	pci_lock_rescan_remove(); +  	if (func->pci_dev == NULL)  		func->pci_dev = pci_get_bus_and_slot(func->bus,PCI_DEVFN(func->device, func->function)); @@ -100,7 +102,7 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  		func->pci_dev = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, func->function));  		if (func->pci_dev == NULL) {  			dbg("ERROR: pci_dev still null\n"); -			return 0; +			goto out;  		}  	} @@ -113,23 +115,27 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)  	pci_dev_put(func->pci_dev); + out: +	pci_unlock_rescan_remove();  	return 0;  } -int cpqhp_unconfigure_device(struct pci_func* func) +int cpqhp_unconfigure_device(struct pci_func *func)  {  	int j;  	dbg("%s: bus/dev/func = %x/%x/%x\n", __func__, func->bus, func->device, func->function); +	pci_lock_rescan_remove();  	for (j=0; j<8 ; j++) { -		struct pci_dev* temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j)); +		struct pci_dev *temp = pci_get_bus_and_slot(func->bus, PCI_DEVFN(func->device, j));  		if (temp) {  			pci_dev_put(temp);  			pci_stop_and_remove_bus_device(temp);  		}  	} +	pci_unlock_rescan_remove();  	return 0;  } @@ -197,7 +203,7 @@ int cpqhp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)  } -static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 * dev_num) +static int PCI_ScanBusForNonBridge(struct controller *ctrl, u8 bus_num, u8 *dev_num)  {  	u16 tdevice;  	u32 work; @@ -274,7 +280,7 @@ static int PCI_GetBusDevHelper(struct controller *ctrl, u8 *bus_num, u8 *dev_num  } -int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 slot) +int cpqhp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, u8 slot)  {  	/* plain (bridges allowed) */  	return PCI_GetBusDevHelper(ctrl, bus_num, dev_num, slot, 0); @@ -291,7 +297,7 @@ int cpqhp_get_bus_dev (struct controller *ctrl, u8 * bus_num, u8 * dev_num, u8 s   *   * Reads configuration for all slots in a PCI bus and saves info.   * - * Note:  For non-hot plug busses, the slot # saved is the device # + * Note:  For non-hot plug buses, the slot # saved is the device #   *   * returns 0 if success   */ @@ -455,11 +461,11 @@ int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug)   * cpqhp_save_slot_config   *   * Saves configuration info for all PCI devices in a given slot - * including subordinate busses. + * including subordinate buses.   *   * returns 0 if success   */ -int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot) +int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func *new_slot)  {  	long rc;  	u8 class_code; @@ -543,7 +549,7 @@ int cpqhp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot)   *   * returns 0 if success   */ -int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func) +int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func)  {  	u8 cloop;  	u8 header_type; @@ -680,7 +686,7 @@ int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func * func)   *   * returns 0 if success   */ -int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func) +int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func *func)  {  	u8 cloop;  	u8 header_type; @@ -943,7 +949,7 @@ int cpqhp_save_used_resources (struct controller *ctrl, struct pci_func * func)   *   * returns 0 if success   */ -int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func) +int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func)  {  	int cloop;  	u8 header_type; @@ -1021,7 +1027,7 @@ int cpqhp_configure_board(struct controller *ctrl, struct pci_func * func)   *   * returns 0 if the board is the same nonzero otherwise   */ -int cpqhp_valid_replace(struct controller *ctrl, struct pci_func * func) +int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func)  {  	u8 cloop;  	u8 header_type; @@ -1413,7 +1419,7 @@ int cpqhp_find_available_resources(struct controller *ctrl, void __iomem *rom_st   *   * returns 0 if success   */ -int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists * resources) +int cpqhp_return_board_resources(struct pci_func *func, struct resource_lists *resources)  {  	int rc = 0;  	struct pci_resource *node; @@ -1469,7 +1475,7 @@ int cpqhp_return_board_resources(struct pci_func * func, struct resource_lists *   *   * Puts node back in the resource list pointed to by head   */ -void cpqhp_destroy_resource_list (struct resource_lists * resources) +void cpqhp_destroy_resource_list (struct resource_lists *resources)  {  	struct pci_resource *res, *tres; @@ -1516,7 +1522,7 @@ void cpqhp_destroy_resource_list (struct resource_lists * resources)   *   * Puts node back in the resource list pointed to by head   */ -void cpqhp_destroy_board_resources (struct pci_func * func) +void cpqhp_destroy_board_resources (struct pci_func *func)  {  	struct pci_resource *res, *tres; @@ -1556,4 +1562,3 @@ void cpqhp_destroy_board_resources (struct pci_func * func)  		kfree(tres);  	}  } - diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index 17c1f36315d..4a392c44e3d 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -79,7 +79,7 @@ static int show_ctrl (struct controller *ctrl, char *buf)  static int show_dev (struct controller *ctrl, char *buf)  { -	char * out = buf; +	char *out = buf;  	int index;  	struct pci_resource *res;  	struct pci_func *new_slot; diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index 8c5b25871d0..e3e46a7b3ee 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -59,7 +59,7 @@ extern int ibmphp_debug;  /************************************************************ -*  RESOURE TYPE                                             * +*  RESOURCE TYPE                                             *  ************************************************************/  #define EBDA_RSRC_TYPE_MASK		0x03 @@ -103,7 +103,7 @@ extern int ibmphp_debug;  //--------------------------------------------------------------  struct rio_table_hdr { -	u8 ver_num;  +	u8 ver_num;  	u8 scal_count;  	u8 riodev_count;  	u16 offset; @@ -127,7 +127,7 @@ struct scal_detail {  };  //-------------------------------------------------------------- -// RIO DETAIL  +// RIO DETAIL  //--------------------------------------------------------------  struct rio_detail { @@ -152,7 +152,7 @@ struct opt_rio {  	u8 first_slot_num;  	u8 middle_num;  	struct list_head opt_rio_list; -};	 +};  struct opt_rio_lo {  	u8 rio_type; @@ -161,7 +161,7 @@ struct opt_rio_lo {  	u8 middle_num;  	u8 pack_count;  	struct list_head opt_rio_lo_list; -};	 +};  /****************************************************************  *  HPC DESCRIPTOR NODE                                          * @@ -574,7 +574,7 @@ void ibmphp_hpc_stop_poll_thread(void);  #define HPC_CTLR_IRQ_PENDG	0x80  //---------------------------------------------------------------------------- -// HPC_CTLR_WROKING status return codes +// HPC_CTLR_WORKING status return codes  //----------------------------------------------------------------------------  #define HPC_CTLR_WORKING_NO	0x00  #define HPC_CTLR_WORKING_YES	0x01 diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index cbd72d81d25..f7b8684a773 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c @@ -58,7 +58,7 @@ MODULE_DESCRIPTION (DRIVER_DESC);  struct pci_bus *ibmphp_pci_bus;  static int max_slots; -static int irqs[16];    /* PIC mode IRQ's we're using so far (in case MPS +static int irqs[16];    /* PIC mode IRQs we're using so far (in case MPS  			 * tables don't provide default info for empty slots */  static int init_flag; @@ -71,20 +71,20 @@ static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value)  	return get_max_adapter_speed_1 (hs, value, 1);  }  */ -static inline int get_cur_bus_info(struct slot **sl)  +static inline int get_cur_bus_info(struct slot **sl)  {  	int rc = 1; -	struct slot * slot_cur = *sl; +	struct slot *slot_cur = *sl;  	debug("options = %x\n", slot_cur->ctrl->options); -	debug("revision = %x\n", slot_cur->ctrl->revision);	 +	debug("revision = %x\n", slot_cur->ctrl->revision); -	if (READ_BUS_STATUS(slot_cur->ctrl))  +	if (READ_BUS_STATUS(slot_cur->ctrl))  		rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL); -	 -	if (rc)  + +	if (rc)  		return rc; -	   +  	slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus);  	if (READ_BUS_MODE(slot_cur->ctrl))  		slot_cur->bus_on->current_bus_mode = @@ -96,7 +96,7 @@ static inline int get_cur_bus_info(struct slot **sl)  			slot_cur->busstatus,  			slot_cur->bus_on->current_speed,  			slot_cur->bus_on->current_bus_mode); -	 +  	*sl = slot_cur;  	return 0;  } @@ -104,8 +104,8 @@ static inline int get_cur_bus_info(struct slot **sl)  static inline int slot_update(struct slot **sl)  {  	int rc; - 	rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL); -	if (rc)  +	rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL); +	if (rc)  		return rc;  	if (!init_flag)  		rc = get_cur_bus_info(sl); @@ -114,8 +114,8 @@ static inline int slot_update(struct slot **sl)  static int __init get_max_slots (void)  { -	struct slot * slot_cur; -	struct list_head * tmp; +	struct slot *slot_cur; +	struct list_head *tmp;  	u8 slot_count = 0;  	list_for_each(tmp, &ibmphp_slot_head) { @@ -172,7 +172,7 @@ int ibmphp_init_devno(struct slot **cur_slot)  			debug("(*cur_slot)->irq[3] = %x\n",  					(*cur_slot)->irq[3]); -			debug("rtable->exlusive_irqs = %x\n", +			debug("rtable->exclusive_irqs = %x\n",  					rtable->exclusive_irqs);  			debug("rtable->slots[loop].irq[0].bitmap = %x\n",  					rtable->slots[loop].irq[0].bitmap); @@ -271,7 +271,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)  			else  				rc = -ENODEV;  		} -	} else	 +	} else  		rc = -ENODEV;  	ibmphp_unlock_operations(); @@ -280,7 +280,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)  	return rc;  } -static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	int rc = -ENODEV;  	struct slot *pslot; @@ -288,7 +288,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)  	debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",  					(ulong) hotplug_slot, (ulong) value); -         +  	ibmphp_lock_operations();  	if (hotplug_slot) {  		pslot = hotplug_slot->private; @@ -311,7 +311,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)  	return rc;  } -static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	int rc = -ENODEV;  	struct slot *pslot; @@ -338,7 +338,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value)  } -static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	int rc = -ENODEV;  	struct slot *pslot; @@ -364,7 +364,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)  	return rc;  } -static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 *value)  {  	int rc = -ENODEV;  	struct slot *pslot; @@ -406,14 +406,14 @@ static int get_max_bus_speed(struct slot *slot)  	ibmphp_lock_operations();  	mode = slot->supported_bus_mode; -	speed = slot->supported_speed;  +	speed = slot->supported_speed;  	ibmphp_unlock_operations();  	switch (speed) {  	case BUS_SPEED_33:  		break;  	case BUS_SPEED_66: -		if (mode == BUS_MODE_PCIX)  +		if (mode == BUS_MODE_PCIX)  			speed += 0x01;  		break;  	case BUS_SPEED_100: @@ -433,7 +433,7 @@ static int get_max_bus_speed(struct slot *slot)  }  /* -static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value, u8 flag) +static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 *value, u8 flag)  {  	int rc = -ENODEV;  	struct slot *pslot; @@ -471,7 +471,7 @@ static int get_max_adapter_speed_1(struct hotplug_slot *hotplug_slot, u8 * value  	return rc;  } -static int get_bus_name(struct hotplug_slot *hotplug_slot, char * value) +static int get_bus_name(struct hotplug_slot *hotplug_slot, char *value)  {  	int rc = -ENODEV;  	struct slot *pslot = NULL; @@ -515,13 +515,13 @@ static int __init init_ops(void)  		debug("BEFORE GETTING SLOT STATUS, slot # %x\n",  							slot_cur->number); -		if (slot_cur->ctrl->revision == 0xFF)  +		if (slot_cur->ctrl->revision == 0xFF)  			if (get_ctrl_revision(slot_cur,  						&slot_cur->ctrl->revision))  				return -1; -		if (slot_cur->bus_on->current_speed == 0xFF)  -			if (get_cur_bus_info(&slot_cur))  +		if (slot_cur->bus_on->current_speed == 0xFF) +			if (get_cur_bus_info(&slot_cur))  				return -1;  		get_max_bus_speed(slot_cur); @@ -539,8 +539,8 @@ static int __init init_ops(void)  		debug("SLOT_PRESENT = %x\n", SLOT_PRESENT(slot_cur->status));  		debug("SLOT_LATCH = %x\n", SLOT_LATCH(slot_cur->status)); -		if ((SLOT_PWRGD(slot_cur->status)) &&  -		    !(SLOT_PRESENT(slot_cur->status)) &&  +		if ((SLOT_PWRGD(slot_cur->status)) && +		    !(SLOT_PRESENT(slot_cur->status)) &&  		    !(SLOT_LATCH(slot_cur->status))) {  			debug("BEFORE POWER OFF COMMAND\n");  				rc = power_off(slot_cur); @@ -581,13 +581,13 @@ static int validate(struct slot *slot_cur, int opn)  	switch (opn) {  		case ENABLE: -			if (!(SLOT_PWRGD(slot_cur->status)) &&  -			     (SLOT_PRESENT(slot_cur->status)) &&  +			if (!(SLOT_PWRGD(slot_cur->status)) && +			     (SLOT_PRESENT(slot_cur->status)) &&  			     !(SLOT_LATCH(slot_cur->status)))  				return 0;  			break;  		case DISABLE: -			if ((SLOT_PWRGD(slot_cur->status)) &&  +			if ((SLOT_PWRGD(slot_cur->status)) &&  			    (SLOT_PRESENT(slot_cur->status)) &&  			    !(SLOT_LATCH(slot_cur->status)))  				return 0; @@ -617,7 +617,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur)  		err("out of system memory\n");  		return -ENOMEM;  	} -         +  	info->power_status = SLOT_PWRGD(slot_cur->status);  	info->attention_status = SLOT_ATTN(slot_cur->status,  						slot_cur->ext_status); @@ -638,7 +638,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur)  		case BUS_SPEED_33:  			break;  		case BUS_SPEED_66: -			if (mode == BUS_MODE_PCIX)  +			if (mode == BUS_MODE_PCIX)  				bus_speed += 0x01;  			else if (mode == BUS_MODE_PCI)  				; @@ -654,8 +654,8 @@ int ibmphp_update_slot_info(struct slot *slot_cur)  	}  	bus->cur_bus_speed = bus_speed; -	// To do: bus_names  -	 +	// To do: bus_names +  	rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info);  	kfree(info);  	return rc; @@ -671,7 +671,7 @@ static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)  {  	struct pci_func *func_cur;  	struct slot *slot_cur; -	struct list_head * tmp; +	struct list_head *tmp;  	list_for_each(tmp, &ibmphp_slot_head) {  		slot_cur = list_entry(tmp, struct slot, ibm_slot_list);  		if (slot_cur->func) { @@ -696,8 +696,8 @@ static struct pci_func *ibm_slot_find(u8 busno, u8 device, u8 function)  static void free_slots(void)  {  	struct slot *slot_cur; -	struct list_head * tmp; -	struct list_head * next; +	struct list_head *tmp; +	struct list_head *next;  	debug("%s -- enter\n", __func__); @@ -718,6 +718,8 @@ static void ibm_unconfigure_device(struct pci_func *func)  					func->device, func->function);  	debug("func->device << 3 | 0x0  = %x\n", func->device << 3 | 0x0); +	pci_lock_rescan_remove(); +  	for (j = 0; j < 0x08; j++) {  		temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);  		if (temp) { @@ -725,12 +727,15 @@ static void ibm_unconfigure_device(struct pci_func *func)  			pci_dev_put(temp);  		}  	} +  	pci_dev_put(func->dev); + +	pci_unlock_rescan_remove();  }  /* - * The following function is to fix kernel bug regarding  - * getting bus entries, here we manually add those primary  + * The following function is to fix kernel bug regarding + * getting bus entries, here we manually add those primary   * bus entries to kernel bus structure whenever apply   */  static u8 bus_structure_fixup(u8 busno) @@ -780,6 +785,8 @@ static int ibm_configure_device(struct pci_func *func)  	int flag = 0;	/* this is to make sure we don't double scan the bus,  					for bridged devices primarily */ +	pci_lock_rescan_remove(); +  	if (!(bus_structure_fixup(func->busno)))  		flag = 1;  	if (func->dev == NULL) @@ -789,7 +796,7 @@ static int ibm_configure_device(struct pci_func *func)  	if (func->dev == NULL) {  		struct pci_bus *bus = pci_find_bus(0, func->busno);  		if (!bus) -			return 0; +			goto out;  		num = pci_scan_slot(bus,  				PCI_DEVFN(func->device, func->function)); @@ -800,7 +807,7 @@ static int ibm_configure_device(struct pci_func *func)  				PCI_DEVFN(func->device, func->function));  		if (func->dev == NULL) {  			err("ERROR... : pci_dev still NULL\n"); -			return 0; +			goto out;  		}  	}  	if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { @@ -810,16 +817,18 @@ static int ibm_configure_device(struct pci_func *func)  			pci_bus_add_devices(child);  	} + out: +	pci_unlock_rescan_remove();  	return 0;  }  /******************************************************* - * Returns whether the bus is empty or not  + * Returns whether the bus is empty or not   *******************************************************/ -static int is_bus_empty(struct slot * slot_cur) +static int is_bus_empty(struct slot *slot_cur)  {  	int rc; -	struct slot * tmp_slot; +	struct slot *tmp_slot;  	u8 i = slot_cur->bus_on->slot_min;  	while (i <= slot_cur->bus_on->slot_max) { @@ -842,12 +851,12 @@ static int is_bus_empty(struct slot * slot_cur)  }  /*********************************************************** - * If the HPC permits and the bus currently empty, tries to set the  + * If the HPC permits and the bus currently empty, tries to set the   * bus speed and mode at the maximum card and bus capability   * Parameters: slot   * Returns: bus is set (0) or error code   ***********************************************************/ -static int set_bus(struct slot * slot_cur) +static int set_bus(struct slot *slot_cur)  {  	int rc;  	u8 speed; @@ -856,7 +865,7 @@ static int set_bus(struct slot * slot_cur)  	static struct pci_device_id ciobx[] = {  		{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) },  	        { }, -	};	 +	};  	debug("%s - entry slot # %d\n", __func__, slot_cur->number);  	if (SET_BUS_STATUS(slot_cur->ctrl) && is_bus_empty(slot_cur)) { @@ -877,7 +886,7 @@ static int set_bus(struct slot * slot_cur)  				else if (!SLOT_BUS_MODE(slot_cur->ext_status))  					/* if max slot/bus capability is 66 pci  					and there's no bus mode mismatch, then -					the adapter supports 66 pci */  +					the adapter supports 66 pci */  					cmd = HPC_BUS_66CONVMODE;  				else  					cmd = HPC_BUS_33CONVMODE; @@ -930,7 +939,7 @@ static int set_bus(struct slot * slot_cur)  			return -EIO;  		}  	} -	/* This is for x440, once Brandon fixes the firmware,  +	/* This is for x440, once Brandon fixes the firmware,  	will not need this delay */  	msleep(1000);  	debug("%s -Exit\n", __func__); @@ -938,16 +947,16 @@ static int set_bus(struct slot * slot_cur)  }  /* This routine checks the bus limitations that the slot is on from the BIOS. - * This is used in deciding whether or not to power up the slot.   + * This is used in deciding whether or not to power up the slot.   * (electrical/spec limitations. For example, >1 133 MHz or >2 66 PCI cards on - * same bus)  + * same bus)   * Parameters: slot   * Returns: 0 = no limitations, -EINVAL = exceeded limitations on the bus   */  static int check_limitations(struct slot *slot_cur)  {  	u8 i; -	struct slot * tmp_slot; +	struct slot *tmp_slot;  	u8 count = 0;  	u8 limitation = 0; @@ -986,7 +995,7 @@ static int check_limitations(struct slot *slot_cur)  static inline void print_card_capability(struct slot *slot_cur)  {  	info("capability of the card is "); -	if ((slot_cur->ext_status & CARD_INFO) == PCIX133)  +	if ((slot_cur->ext_status & CARD_INFO) == PCIX133)  		info("   133 MHz PCI-X\n");  	else if ((slot_cur->ext_status & CARD_INFO) == PCIX66)  		info("    66 MHz PCI-X\n"); @@ -1020,7 +1029,7 @@ static int enable_slot(struct hotplug_slot *hs)  	}  	attn_LED_blink(slot_cur); -	 +  	rc = set_bus(slot_cur);  	if (rc) {  		err("was not able to set the bus\n"); @@ -1036,8 +1045,7 @@ static int enable_slot(struct hotplug_slot *hs)  	rc = check_limitations(slot_cur);  	if (rc) {  		err("Adding this card exceeds the limitations of this bus.\n"); -		err("(i.e., >1 133MHz cards running on same bus, or " -		     ">2 66 PCI cards running on same bus.\n"); +		err("(i.e., >1 133MHz cards running on same bus, or >2 66 PCI cards running on same bus.\n");  		err("Try hot-adding into another bus\n");  		rc = -EINVAL;  		goto error_nopower; @@ -1061,12 +1069,10 @@ static int enable_slot(struct hotplug_slot *hs)  					!(SLOT_PWRGD(slot_cur->status)))  			err("power fault occurred trying to power up\n");  		else if (SLOT_BUS_SPEED(slot_cur->status)) { -			err("bus speed mismatch occurred.  please check " -				"current bus speed and card capability\n"); +			err("bus speed mismatch occurred.  please check current bus speed and card capability\n");  			print_card_capability(slot_cur);  		} else if (SLOT_BUS_MODE(slot_cur->ext_status)) { -			err("bus mode mismatch occurred.  please check " -				"current bus mode and card capability\n"); +			err("bus mode mismatch occurred.  please check current bus mode and card capability\n");  			print_card_capability(slot_cur);  		}  		ibmphp_update_slot_info(slot_cur); @@ -1082,18 +1088,17 @@ static int enable_slot(struct hotplug_slot *hs)  	rc = slot_update(&slot_cur);  	if (rc)  		goto error_power; -	 +  	rc = -EINVAL;  	if (SLOT_POWER(slot_cur->status) && !(SLOT_PWRGD(slot_cur->status))) {  		err("power fault occurred trying to power up...\n");  		goto error_power;  	}  	if (SLOT_POWER(slot_cur->status) && (SLOT_BUS_SPEED(slot_cur->status))) { -		err("bus speed mismatch occurred.  please check current bus " -					"speed and card capability\n"); +		err("bus speed mismatch occurred.  please check current bus speed and card capability\n");  		print_card_capability(slot_cur);  		goto error_power; -	}  +	}  	/* Don't think this case will happen after above checks...  	 * but just in case, for paranoia sake */  	if (!(SLOT_POWER(slot_cur->status))) { @@ -1144,7 +1149,7 @@ static int enable_slot(struct hotplug_slot *hs)  	ibmphp_print_test();  	rc = ibmphp_update_slot_info(slot_cur);  exit: -	ibmphp_unlock_operations();  +	ibmphp_unlock_operations();  	return rc;  error_nopower: @@ -1180,7 +1185,7 @@ static int ibmphp_disable_slot(struct hotplug_slot *hotplug_slot)  {  	struct slot *slot = hotplug_slot->private;  	int rc; -	 +  	ibmphp_lock_operations();  	rc = ibmphp_do_disable_slot(slot);  	ibmphp_unlock_operations(); @@ -1192,12 +1197,12 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)  	int rc;  	u8 flag; -	debug("DISABLING SLOT...\n");  -		 +	debug("DISABLING SLOT...\n"); +  	if ((slot_cur == NULL) || (slot_cur->ctrl == NULL)) {  		return -ENODEV;  	} -	 +  	flag = slot_cur->flag;  	slot_cur->flag = 1; @@ -1210,7 +1215,7 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)  	attn_LED_blink(slot_cur);  	if (slot_cur->func == NULL) { -		/* We need this for fncs's that were there on bootup */ +		/* We need this for functions that were there on bootup */  		slot_cur->func = kzalloc(sizeof(struct pci_func), GFP_KERNEL);  		if (!slot_cur->func) {  			err("out of system memory\n"); @@ -1222,12 +1227,13 @@ int ibmphp_do_disable_slot(struct slot *slot_cur)  	}  	ibm_unconfigure_device(slot_cur->func); -         -	/* If we got here from latch suddenly opening on operating card or  -	a power fault, there's no power to the card, so cannot -	read from it to determine what resources it occupied.  This operation -	is forbidden anyhow.  The best we can do is remove it from kernel -	lists at least */ + +	/* +	 * If we got here from latch suddenly opening on operating card or +	 * a power fault, there's no power to the card, so cannot +	 * read from it to determine what resources it occupied.  This operation +	 * is forbidden anyhow.  The best we can do is remove it from kernel +	 * lists at least */  	if (!flag) {  		attn_off(slot_cur); @@ -1264,7 +1270,7 @@ error:  		rc = -EFAULT;  		goto exit;  	} -	if (flag)		 +	if (flag)  		ibmphp_update_slot_info(slot_cur);  	goto exit;  } @@ -1339,7 +1345,7 @@ static int __init ibmphp_init(void)  	debug("AFTER Resource & EBDA INITIALIZATIONS\n");  	max_slots = get_max_slots(); -	 +  	if ((rc = ibmphp_register_pci()))  		goto error; diff --git a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c index 9df78bc1454..0f65ac55543 100644 --- a/drivers/pci/hotplug/ibmphp_ebda.c +++ b/drivers/pci/hotplug/ibmphp_ebda.c @@ -123,7 +123,7 @@ static struct ebda_pci_rsrc *alloc_ebda_pci_rsrc (void)  static void __init print_bus_info (void)  {  	struct bus_info *ptr; -	 +  	list_for_each_entry(ptr, &bus_info_head, bus_info_list) {  		debug ("%s - slot_min = %x\n", __func__, ptr->slot_min);  		debug ("%s - slot_max = %x\n", __func__, ptr->slot_max); @@ -131,7 +131,7 @@ static void __init print_bus_info (void)  		debug ("%s - bus# = %x\n", __func__, ptr->busno);  		debug ("%s - current_speed = %x\n", __func__, ptr->current_speed);  		debug ("%s - controller_id = %x\n", __func__, ptr->controller_id); -		 +  		debug ("%s - slots_at_33_conv = %x\n", __func__, ptr->slots_at_33_conv);  		debug ("%s - slots_at_66_conv = %x\n", __func__, ptr->slots_at_66_conv);  		debug ("%s - slots_at_66_pcix = %x\n", __func__, ptr->slots_at_66_pcix); @@ -144,7 +144,7 @@ static void __init print_bus_info (void)  static void print_lo_info (void)  {  	struct rio_detail *ptr; -	debug ("print_lo_info ----\n");	 +	debug ("print_lo_info ----\n");  	list_for_each_entry(ptr, &rio_lo_head, rio_detail_list) {  		debug ("%s - rio_node_id = %x\n", __func__, ptr->rio_node_id);  		debug ("%s - rio_type = %x\n", __func__, ptr->rio_type); @@ -176,7 +176,7 @@ static void __init print_ebda_pci_rsrc (void)  	struct ebda_pci_rsrc *ptr;  	list_for_each_entry(ptr, &ibmphp_ebda_pci_rsrc_head, ebda_pci_rsrc_list) { -		debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",  +		debug ("%s - rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",  			__func__, ptr->rsrc_type ,ptr->bus_num, ptr->dev_fun,ptr->start_addr, ptr->end_addr);  	}  } @@ -259,7 +259,7 @@ int __init ibmphp_access_ebda (void)  	ebda_seg = readw (io_mem);  	iounmap (io_mem);  	debug ("returned ebda segment: %x\n", ebda_seg); -	 +  	io_mem = ioremap(ebda_seg<<4, 1);  	if (!io_mem)  		return -ENOMEM; @@ -310,7 +310,7 @@ int __init ibmphp_access_ebda (void)  			re = readw (io_mem + sub_addr);	/* next sub blk */  			sub_addr += 2; -			rc_id = readw (io_mem + sub_addr); 	/* sub blk id */ +			rc_id = readw (io_mem + sub_addr);	/* sub blk id */  			sub_addr += 2;  			if (rc_id != 0x5243) @@ -330,7 +330,7 @@ int __init ibmphp_access_ebda (void)  			debug ("info about hpc descriptor---\n");  			debug ("hot blk format: %x\n", format);  			debug ("num of controller: %x\n", num_ctlrs); -			debug ("offset of hpc data structure enteries: %x\n ", sub_addr); +			debug ("offset of hpc data structure entries: %x\n ", sub_addr);  			sub_addr = base + re;	/* re sub blk */  			/* FIXME: rc is never used/checked */ @@ -359,7 +359,7 @@ int __init ibmphp_access_ebda (void)  			debug ("info about rsrc descriptor---\n");  			debug ("format: %x\n", format);  			debug ("num of rsrc: %x\n", num_entries); -			debug ("offset of rsrc data structure enteries: %x\n ", sub_addr); +			debug ("offset of rsrc data structure entries: %x\n ", sub_addr);  			hs_complete = 1;  		} else { @@ -376,7 +376,7 @@ int __init ibmphp_access_ebda (void)  			rio_table_ptr->scal_count = readb (io_mem + offset + 1);  			rio_table_ptr->riodev_count = readb (io_mem + offset + 2);  			rio_table_ptr->offset = offset +3 ; -			 +  			debug("info about rio table hdr ---\n");  			debug("ver_num: %x\nscal_count: %x\nriodev_count: %x\noffset of rio table: %x\n ",  				rio_table_ptr->ver_num, rio_table_ptr->scal_count, @@ -440,12 +440,12 @@ static int __init ebda_rio_table (void)  		rio_detail_ptr->chassis_num = readb (io_mem + offset + 14);  //		debug ("rio_node_id: %x\nbbar: %x\nrio_type: %x\nowner_id: %x\nport0_node: %x\nport0_port: %x\nport1_node: %x\nport1_port: %x\nfirst_slot_num: %x\nstatus: %x\n", rio_detail_ptr->rio_node_id, rio_detail_ptr->bbar, rio_detail_ptr->rio_type, rio_detail_ptr->owner_id, rio_detail_ptr->port0_node_connect, rio_detail_ptr->port0_port_connect, rio_detail_ptr->port1_node_connect, rio_detail_ptr->port1_port_connect, rio_detail_ptr->first_slot_num, rio_detail_ptr->status);  		//create linked list of chassis -		if (rio_detail_ptr->rio_type == 4 || rio_detail_ptr->rio_type == 5)  +		if (rio_detail_ptr->rio_type == 4 || rio_detail_ptr->rio_type == 5)  			list_add (&rio_detail_ptr->rio_detail_list, &rio_vg_head); -		//create linked list of expansion box				 -		else if (rio_detail_ptr->rio_type == 6 || rio_detail_ptr->rio_type == 7)  +		//create linked list of expansion box +		else if (rio_detail_ptr->rio_type == 6 || rio_detail_ptr->rio_type == 7)  			list_add (&rio_detail_ptr->rio_detail_list, &rio_lo_head); -		else  +		else  			// not in my concern  			kfree (rio_detail_ptr);  		offset += 15; @@ -456,7 +456,7 @@ static int __init ebda_rio_table (void)  }  /* - * reorganizing linked list of chassis	  + * reorganizing linked list of chassis   */  static struct opt_rio *search_opt_vg (u8 chassis_num)  { @@ -464,7 +464,7 @@ static struct opt_rio *search_opt_vg (u8 chassis_num)  	list_for_each_entry(ptr, &opt_vg_head, opt_rio_list) {  		if (ptr->chassis_num == chassis_num)  			return ptr; -	}		 +	}  	return NULL;  } @@ -472,7 +472,7 @@ static int __init combine_wpg_for_chassis (void)  {  	struct opt_rio *opt_rio_ptr = NULL;  	struct rio_detail *rio_detail_ptr = NULL; -	 +  	list_for_each_entry(rio_detail_ptr, &rio_vg_head, rio_detail_list) {  		opt_rio_ptr = search_opt_vg (rio_detail_ptr->chassis_num);  		if (!opt_rio_ptr) { @@ -484,14 +484,14 @@ static int __init combine_wpg_for_chassis (void)  			opt_rio_ptr->first_slot_num = rio_detail_ptr->first_slot_num;  			opt_rio_ptr->middle_num = rio_detail_ptr->first_slot_num;  			list_add (&opt_rio_ptr->opt_rio_list, &opt_vg_head); -		} else {	 +		} else {  			opt_rio_ptr->first_slot_num = min (opt_rio_ptr->first_slot_num, rio_detail_ptr->first_slot_num);  			opt_rio_ptr->middle_num = max (opt_rio_ptr->middle_num, rio_detail_ptr->first_slot_num); -		}	 +		}  	}  	print_opt_vg (); -	return 0;	 -}	 +	return 0; +}  /*   * reorganizing linked list of expansion box @@ -502,7 +502,7 @@ static struct opt_rio_lo *search_opt_lo (u8 chassis_num)  	list_for_each_entry(ptr, &opt_lo_head, opt_rio_lo_list) {  		if (ptr->chassis_num == chassis_num)  			return ptr; -	}		 +	}  	return NULL;  } @@ -510,7 +510,7 @@ static int combine_wpg_for_expansion (void)  {  	struct opt_rio_lo *opt_rio_lo_ptr = NULL;  	struct rio_detail *rio_detail_ptr = NULL; -	 +  	list_for_each_entry(rio_detail_ptr, &rio_lo_head, rio_detail_list) {  		opt_rio_lo_ptr = search_opt_lo (rio_detail_ptr->chassis_num);  		if (!opt_rio_lo_ptr) { @@ -522,22 +522,22 @@ static int combine_wpg_for_expansion (void)  			opt_rio_lo_ptr->first_slot_num = rio_detail_ptr->first_slot_num;  			opt_rio_lo_ptr->middle_num = rio_detail_ptr->first_slot_num;  			opt_rio_lo_ptr->pack_count = 1; -			 +  			list_add (&opt_rio_lo_ptr->opt_rio_lo_list, &opt_lo_head); -		} else {	 +		} else {  			opt_rio_lo_ptr->first_slot_num = min (opt_rio_lo_ptr->first_slot_num, rio_detail_ptr->first_slot_num);  			opt_rio_lo_ptr->middle_num = max (opt_rio_lo_ptr->middle_num, rio_detail_ptr->first_slot_num);  			opt_rio_lo_ptr->pack_count = 2; -		}	 +		}  	} -	return 0;	 +	return 0;  } -	 +  /* Since we don't know the max slot number per each chassis, hence go   * through the list of all chassis to find out the range - * Arguments: slot_num, 1st slot number of the chassis we think we are on,  - * var (0 = chassis, 1 = expansion box)  + * Arguments: slot_num, 1st slot number of the chassis we think we are on, + * var (0 = chassis, 1 = expansion box)   */  static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)  { @@ -547,7 +547,7 @@ static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)  	if (!var) {  		list_for_each_entry(opt_vg_ptr, &opt_vg_head, opt_rio_list) { -			if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) {  +			if ((first_slot < opt_vg_ptr->first_slot_num) && (slot_num >= opt_vg_ptr->first_slot_num)) {  				rc = -ENODEV;  				break;  			} @@ -563,25 +563,25 @@ static int first_slot_num (u8 slot_num, u8 first_slot, u8 var)  	return rc;  } -static struct opt_rio_lo * find_rxe_num (u8 slot_num) +static struct opt_rio_lo *find_rxe_num (u8 slot_num)  {  	struct opt_rio_lo *opt_lo_ptr;  	list_for_each_entry(opt_lo_ptr, &opt_lo_head, opt_rio_lo_list) {  		//check to see if this slot_num belongs to expansion box -		if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1)))  +		if ((slot_num >= opt_lo_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_lo_ptr->first_slot_num, 1)))  			return opt_lo_ptr;  	}  	return NULL;  } -static struct opt_rio * find_chassis_num (u8 slot_num) +static struct opt_rio *find_chassis_num (u8 slot_num)  {  	struct opt_rio *opt_vg_ptr;  	list_for_each_entry(opt_vg_ptr, &opt_vg_head, opt_rio_list) { -		//check to see if this slot_num belongs to chassis  -		if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0)))  +		//check to see if this slot_num belongs to chassis +		if ((slot_num >= opt_vg_ptr->first_slot_num) && (!first_slot_num (slot_num, opt_vg_ptr->first_slot_num, 0)))  			return opt_vg_ptr;  	}  	return NULL; @@ -593,21 +593,21 @@ static struct opt_rio * find_chassis_num (u8 slot_num)  static u8 calculate_first_slot (u8 slot_num)  {  	u8 first_slot = 1; -	struct slot * slot_cur; -	 +	struct slot *slot_cur; +  	list_for_each_entry(slot_cur, &ibmphp_slot_head, ibm_slot_list) {  		if (slot_cur->ctrl) { -			if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num))  +			if ((slot_cur->ctrl->ctlr_type != 4) && (slot_cur->ctrl->ending_slot_num > first_slot) && (slot_num > slot_cur->ctrl->ending_slot_num))  				first_slot = slot_cur->ctrl->ending_slot_num;  		} -	}			 +	}  	return first_slot + 1;  }  #define SLOT_NAME_SIZE 30 -static char *create_file_name (struct slot * slot_cur) +static char *create_file_name (struct slot *slot_cur)  {  	struct opt_rio *opt_vg_ptr = NULL;  	struct opt_rio_lo *opt_lo_ptr = NULL; @@ -622,11 +622,11 @@ static char *create_file_name (struct slot * slot_cur)  		err ("Structure passed is empty\n");  		return NULL;  	} -	 +  	slot_num = slot_cur->number;  	memset (str, 0, sizeof(str)); -	 +  	if (rio_table_ptr) {  		if (rio_table_ptr->ver_num == 3) {  			opt_vg_ptr = find_chassis_num (slot_num); @@ -660,7 +660,7 @@ static char *create_file_name (struct slot * slot_cur)  			/* if both NULL and we DO have correct RIO table in BIOS */  			return NULL;  		} -	}  +	}  	if (!flag) {  		if (slot_cur->ctrl->ctlr_type == 4) {  			first_slot = calculate_first_slot (slot_num); @@ -798,7 +798,7 @@ static int __init ebda_rsrc_controller (void)  			slot_ptr->ctl_index = readb (io_mem + addr_slot + 2*slot_num);  			slot_ptr->slot_cap = readb (io_mem + addr_slot + 3*slot_num); -			// create bus_info lined list --- if only one slot per bus: slot_min = slot_max  +			// create bus_info lined list --- if only one slot per bus: slot_min = slot_max  			bus_info_ptr2 = ibmphp_find_same_bus_num (slot_ptr->slot_bus_num);  			if (!bus_info_ptr2) { @@ -814,9 +814,9 @@ static int __init ebda_rsrc_controller (void)  				bus_info_ptr1->index = bus_index++;  				bus_info_ptr1->current_speed = 0xff;  				bus_info_ptr1->current_bus_mode = 0xff; -				 +  				bus_info_ptr1->controller_id = hpc_ptr->ctlr_id; -				 +  				list_add_tail (&bus_info_ptr1->bus_info_list, &bus_info_head);  			} else { @@ -851,7 +851,7 @@ static int __init ebda_rsrc_controller (void)  				bus_info_ptr2->slots_at_66_conv = bus_ptr->slots_at_66_conv;  				bus_info_ptr2->slots_at_66_pcix = bus_ptr->slots_at_66_pcix;  				bus_info_ptr2->slots_at_100_pcix = bus_ptr->slots_at_100_pcix; -				bus_info_ptr2->slots_at_133_pcix = bus_ptr->slots_at_133_pcix;  +				bus_info_ptr2->slots_at_133_pcix = bus_ptr->slots_at_133_pcix;  			}  			bus_ptr++;  		} @@ -864,7 +864,7 @@ static int __init ebda_rsrc_controller (void)  				hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1);  				hpc_ptr->irq = readb (io_mem + addr + 2);  				addr += 3; -				debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n",  +				debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n",  					hpc_ptr->u.pci_ctlr.bus,  					hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq);  				break; @@ -932,7 +932,7 @@ static int __init ebda_rsrc_controller (void)  				tmp_slot->supported_speed =  2;  			else if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_66_MAX) == EBDA_SLOT_66_MAX)  				tmp_slot->supported_speed =  1; -				 +  			if ((hpc_ptr->slots[index].slot_cap & EBDA_SLOT_PCIX_CAP) == EBDA_SLOT_PCIX_CAP)  				tmp_slot->supported_bus_mode = 1;  			else @@ -1000,7 +1000,7 @@ error_no_hpc:  	return rc;  } -/*  +/*   * map info (bus, devfun, start addr, end addr..) of i/o, memory,   * pfm from the physical addr to a list of resource.   */ @@ -1057,7 +1057,7 @@ static int __init ebda_rsrc_rsrc (void)  			addr += 10;  			debug ("rsrc from mem or pfm ---\n"); -			debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",  +			debug ("rsrc type: %x bus#: %x dev_func: %x start addr: %x end addr: %x\n",  				rsrc_ptr->rsrc_type, rsrc_ptr->bus_num, rsrc_ptr->dev_fun, rsrc_ptr->start_addr, rsrc_ptr->end_addr);  			list_add (&rsrc_ptr->ebda_pci_rsrc_list, &ibmphp_ebda_pci_rsrc_head); @@ -1096,7 +1096,7 @@ struct bus_info *ibmphp_find_same_bus_num (u32 num)  	struct bus_info *ptr;  	list_for_each_entry(ptr, &bus_info_head, bus_info_list) { -		if (ptr->busno == num)  +		if (ptr->busno == num)  			 return ptr;  	}  	return NULL; @@ -1110,7 +1110,7 @@ int ibmphp_get_bus_index (u8 num)  	struct bus_info *ptr;  	list_for_each_entry(ptr, &bus_info_head, bus_info_list) { -		if (ptr->busno == num)   +		if (ptr->busno == num)  			return ptr->index;  	}  	return -ENODEV; @@ -1168,7 +1168,7 @@ static struct pci_device_id id_table[] = {  		.subdevice	= HPC_SUBSYSTEM_ID,  		.class		= ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),  	}, {} -};		 +};  MODULE_DEVICE_TABLE(pci, id_table); @@ -1192,12 +1192,12 @@ int ibmphp_register_pci (void)  	}  	return rc;  } -static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids) +static int ibmphp_probe (struct pci_dev *dev, const struct pci_device_id *ids)  {  	struct controller *ctrl;  	debug ("inside ibmphp_probe\n"); -	 +  	list_for_each_entry(ctrl, &ebda_hpc_head, ebda_hpc_list) {  		if (ctrl->ctlr_type == 1) {  			if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) { @@ -1210,4 +1210,3 @@ static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids)  	}  	return -ENODEV;  } - diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c index f59ed30512b..a936022956e 100644 --- a/drivers/pci/hotplug/ibmphp_hpc.c +++ b/drivers/pci/hotplug/ibmphp_hpc.c @@ -258,7 +258,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8  {  	u8 rc;  	void __iomem *wpg_addr;	// base addr + offset -	unsigned long wpg_data;	// data to/from WPG LOHI format  +	unsigned long wpg_data;	// data to/from WPG LOHI format  	unsigned long ultemp;  	unsigned long data;	// actual data HILO format  	int i; @@ -351,7 +351,7 @@ static u8 i2c_ctrl_write (struct controller *ctlr_ptr, void __iomem *WPGBbar, u8  }  //------------------------------------------------------------ -//  Read from ISA type HPC  +//  Read from ISA type HPC  //------------------------------------------------------------  static u8 isa_ctrl_read (struct controller *ctlr_ptr, u8 offset)  { @@ -372,7 +372,7 @@ static void isa_ctrl_write (struct controller *ctlr_ptr, u8 offset, u8 data)  {  	u16 start_address;  	u16 port_address; -	 +  	start_address = ctlr_ptr->u.isa_ctlr.io_start;  	port_address = start_address + (u16) offset;  	outb (data, port_address); @@ -533,7 +533,7 @@ static u8 hpc_readcmdtoindex (u8 cmd, u8 index)  *  * Return   0 or error codes  *---------------------------------------------------------------------*/ -int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus) +int ibmphp_hpc_readslot (struct slot *pslot, u8 cmd, u8 *pstatus)  {  	void __iomem *wpg_bbar = NULL;  	struct controller *ctlr_ptr; @@ -656,11 +656,11 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)  	//--------------------------------------------------------------------  	// cleanup  	//-------------------------------------------------------------------- -	 +  	// remove physical to logical address mapping  	if ((ctlr_ptr->ctlr_type == 2) || (ctlr_ptr->ctlr_type == 4))  		iounmap (wpg_bbar); -	 +  	free_hpc_access ();  	debug_polling ("%s - Exit rc[%d]\n", __func__, rc); @@ -672,7 +672,7 @@ int ibmphp_hpc_readslot (struct slot * pslot, u8 cmd, u8 * pstatus)  *  * Action: issue a WRITE command to HPC  *---------------------------------------------------------------------*/ -int ibmphp_hpc_writeslot (struct slot * pslot, u8 cmd) +int ibmphp_hpc_writeslot (struct slot *pslot, u8 cmd)  {  	void __iomem *wpg_bbar = NULL;  	struct controller *ctlr_ptr; @@ -835,7 +835,7 @@ static int poll_hpc(void *data)  		down (&semOperations);  		switch (poll_state) { -		case POLL_LATCH_REGISTER:  +		case POLL_LATCH_REGISTER:  			oldlatchlow = curlatchlow;  			ctrl_count = 0x00;  			list_for_each (pslotlist, &ibmphp_slot_head) { @@ -892,16 +892,16 @@ static int poll_hpc(void *data)  			if (kthread_should_stop())  				goto out_sleep; -			 +  			down (&semOperations); -			 +  			if (poll_count >= POLL_LATCH_CNT) {  				poll_count = 0;  				poll_state = POLL_SLOTS;  			} else  				poll_state = POLL_LATCH_REGISTER;  			break; -		}	 +		}  		/* give up the hardware semaphore */  		up (&semOperations);  		/* sleep for a short time just for good measure */ @@ -958,7 +958,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)  	// bit 5 - HPC_SLOT_PWRGD  	if ((pslot->status & 0x20) != (poldslot->status & 0x20))  		// OFF -> ON: ignore, ON -> OFF: disable slot -		if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status)))  +		if ((poldslot->status & 0x20) && (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status)))  			disable = 1;  	// bit 6 - HPC_SLOT_BUS_SPEED @@ -980,7 +980,7 @@ static int process_changeinstatus (struct slot *pslot, struct slot *poldslot)  					pslot->status &= ~HPC_SLOT_POWER;  			}  		} -		// CLOSE -> OPEN  +		// CLOSE -> OPEN  		else if ((SLOT_PWRGD (poldslot->status) == HPC_SLOT_PWRGD_GOOD)  			&& (SLOT_CONNECT (poldslot->status) == HPC_SLOT_CONNECTED) && (SLOT_PRESENT (poldslot->status))) {  			disable = 1; @@ -1075,7 +1075,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)  	debug ("before locking operations \n");  	ibmphp_lock_operations ();  	debug ("after locking operations \n"); -	 +  	// wait for poll thread to exit  	debug ("before sem_exit down \n");  	down (&sem_exit); @@ -1102,7 +1102,7 @@ void __exit ibmphp_hpc_stop_poll_thread (void)  * Value:  *---------------------------------------------------------------------*/  static int hpc_wait_ctlr_notworking (int timeout, struct controller *ctlr_ptr, void __iomem *wpg_bbar, -				    u8 * pstatus) +				    u8 *pstatus)  {  	int rc = 0;  	u8 done = 0; diff --git a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c index c60f5f3e838..2fd296706ce 100644 --- a/drivers/pci/hotplug/ibmphp_pci.c +++ b/drivers/pci/hotplug/ibmphp_pci.c @@ -1,8 +1,8 @@  /*   * IBM Hot Plug Controller Driver - *  + *   * Written By: Irene Zubarev, IBM Corporation - *  + *   * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)   * Copyright (C) 2001,2002 IBM Corp.   * @@ -42,12 +42,12 @@ static u8 find_sec_number (u8 primary_busno, u8 slotno);  /*   * NOTE..... If BIOS doesn't provide default routing, we assign: - * 9 for SCSI, 10 for LAN adapters, and 11 for everything else.  + * 9 for SCSI, 10 for LAN adapters, and 11 for everything else.   * If adapter is bridged, then we assign 11 to it and devices behind it.   * We also assign the same irq numbers for multi function devices.   * These are PIC mode, so shouldn't matter n.e.ways (hopefully)   */ -static void assign_alt_irq (struct pci_func * cur_func, u8 class_code) +static void assign_alt_irq (struct pci_func *cur_func, u8 class_code)  {  	int j;  	for (j = 0; j < 4; j++) { @@ -71,11 +71,11 @@ static void assign_alt_irq (struct pci_func * cur_func, u8 class_code)   * Configures the device to be added (will allocate needed resources if it   * can), the device can be a bridge or a regular pci device, can also be   * multi-functional - *  + *   * Input: function to be added - *  + *   * TO DO:  The error case with Multifunction device or multi function bridge, - * if there is an error, will need to go through all previous functions and  + * if there is an error, will need to go through all previous functions and   * unconfigure....or can add some code into unconfigure_card....   */  int ibmphp_configure_card (struct pci_func *func, u8 slotno) @@ -98,7 +98,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)  	cur_func = func;  	/* We only get bus and device from IRQ routing table.  So at this point, -	 * func->busno is correct, and func->device contains only device (at the 5  +	 * func->busno is correct, and func->device contains only device (at the 5  	 * highest bits)  	 */ @@ -137,8 +137,8 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)  				     "Please choose another device.\n", cur_func->device);  				return -ENODEV;  			} else if (class == PCI_CLASS_DISPLAY_VGA) { -				err ("The device %x is not supported for hot plugging. " -				     "Please choose another device.\n", cur_func->device); +				err ("The device %x is not supported for hot plugging. Please choose another device.\n", +				     cur_func->device);  				return -ENODEV;  			}  			switch (hdr_type) { @@ -151,7 +151,7 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)  						     cur_func->device, cur_func->busno);  						cleanup_count = 6;  						goto error; -					}	 +					}  					cur_func->next = NULL;  					function = 0x8;  					break; @@ -179,8 +179,8 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)  				case PCI_HEADER_TYPE_MULTIBRIDGE:  					class >>= 8;  					if (class != PCI_CLASS_BRIDGE_PCI) { -						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. " -						     "Please insert another card.\n", cur_func->device); +						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging.  Please insert another card.\n", +						     cur_func->device);  						return -ENODEV;  					}  					assign_alt_irq (cur_func, class_code); @@ -247,8 +247,8 @@ int ibmphp_configure_card (struct pci_func *func, u8 slotno)  					class >>= 8;  					debug ("class now is %x\n", class);  					if (class != PCI_CLASS_BRIDGE_PCI) { -						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging. " -						     "Please insert another card.\n", cur_func->device); +						err ("This %x is not PCI-to-PCI bridge, and as is not supported for hot-plugging.  Please insert another card.\n", +						     cur_func->device);  						return -ENODEV;  					} @@ -339,7 +339,7 @@ error:  }  /* - * This function configures the pci BARs of a single device.   + * This function configures the pci BARs of a single device.   * Input: pointer to the pci_func   * Output: configured PCI, 0, or error   */ @@ -371,17 +371,17 @@ static int configure_device (struct pci_func *func)  	for (count = 0; address[count]; count++) {	/* for 6 BARs */ -		/* not sure if i need this.  per scott, said maybe need smth like this +		/* not sure if i need this.  per scott, said maybe need * something like this  		   if devices don't adhere 100% to the spec, so don't want to write  		   to the reserved bits -		pcibios_read_config_byte(cur_func->busno, cur_func->device,  +		pcibios_read_config_byte(cur_func->busno, cur_func->device,  		PCI_BASE_ADDRESS_0 + 4 * count, &tmp);  		if (tmp & 0x01) // IO -			pcibios_write_config_dword(cur_func->busno, cur_func->device,  +			pcibios_write_config_dword(cur_func->busno, cur_func->device,  			PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFD);  		else  // Memory -			pcibios_write_config_dword(cur_func->busno, cur_func->device,  +			pcibios_write_config_dword(cur_func->busno, cur_func->device,  			PCI_BASE_ADDRESS_0 + 4 * count, 0xFFFFFFFF);  		 */  		pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], 0xFFFFFFFF); @@ -421,8 +421,8 @@ static int configure_device (struct pci_func *func)  				return -EIO;  			}  			pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->io[count]->start); -	 -			/* _______________This is for debugging purposes only_____________________ */  + +			/* _______________This is for debugging purposes only_____________________ */  			debug ("b4 writing, the IO address is %x\n", func->io[count]->start);  			pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);  			debug ("after writing.... the start address is %x\n", bar[count]); @@ -484,7 +484,7 @@ static int configure_device (struct pci_func *func)  				pci_bus_write_config_dword (ibmphp_pci_bus, devfn, address[count], func->pfmem[count]->start); -				/*_______________This is for debugging purposes only______________________________*/				 +				/*_______________This is for debugging purposes only______________________________*/  				debug ("b4 writing, start address is %x\n", func->pfmem[count]->start);  				pci_bus_read_config_dword (ibmphp_pci_bus, devfn, address[count], &bar[count]);  				debug ("after writing, start address is %x\n", bar[count]); @@ -559,7 +559,7 @@ static int configure_device (struct pci_func *func)  /******************************************************************************   * This routine configures a PCI-2-PCI bridge and the functions behind it   * Parameters: pci_func - * Returns:  + * Returns:   ******************************************************************************/  static int configure_bridge (struct pci_func **func_passed, u8 slotno)  { @@ -622,7 +622,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  	debug ("AFTER FIND_SEC_NUMBER, func->busno IS %x\n", func->busno);  	pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, sec_number); -	 +  	/* __________________For debugging purposes only __________________________________  	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);  	debug ("sec_number after write/read is %x\n", sec_number); @@ -644,7 +644,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  	/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -	   !!!!!!!!!!!!!!!NEED TO ADD!!!  FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!!  +	   !!!!!!!!!!!!!!!NEED TO ADD!!!  FAST BACK-TO-BACK ENABLE!!!!!!!!!!!!!!!!!!!!  	   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ @@ -670,7 +670,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  			debug ("len[count] in IO = %x\n", len[count]);  			bus_io[count] = kzalloc(sizeof(struct resource_node), GFP_KERNEL); -		 +  			if (!bus_io[count]) {  				err ("out of system memory\n");  				retval = -ENOMEM; @@ -735,7 +735,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  						ibmphp_add_pfmem_from_mem (bus_pfmem[count]);  						func->pfmem[count] = bus_pfmem[count];  					} else { -						err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n",  +						err ("cannot allocate requested pfmem for bus %x, device %x, len %x\n",  						     func->busno, func->device, len[count]);  						kfree (mem_tmp);  						kfree (bus_pfmem[count]); @@ -805,7 +805,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  	debug ("amount_needed->mem = %x\n", amount_needed->mem);  	debug ("amount_needed->pfmem =  %x\n", amount_needed->pfmem); -	if (amount_needed->not_correct) {		 +	if (amount_needed->not_correct) {  		debug ("amount_needed is not correct\n");  		for (count = 0; address[count]; count++) {  			/* for 2 BARs */ @@ -830,7 +830,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  	} else {  		debug ("it wants %x IO behind the bridge\n", amount_needed->io);  		io = kzalloc(sizeof(*io), GFP_KERNEL); -		 +  		if (!io) {  			err ("out of system memory\n");  			retval = -ENOMEM; @@ -959,7 +959,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  		if (bus->noIORanges) {  			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, 0x00 | bus->rangeIO->start >> 8); -			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8);	 +			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_IO_LIMIT, 0x00 | bus->rangeIO->end >> 8);  			/* _______________This is for debugging purposes only ____________________  			pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_IO_BASE, &temp); @@ -980,7 +980,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  		if (bus->noMemRanges) {  			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, 0x0000 | bus->rangeMem->start >> 16);  			pci_bus_write_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, 0x0000 | bus->rangeMem->end >> 16); -			 +  			/* ____________________This is for debugging purposes only ________________________  			pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &temp);  			debug ("mem_base = %x\n", (temp & PCI_MEMORY_RANGE_TYPE_MASK) << 16); @@ -1017,7 +1017,7 @@ static int configure_bridge (struct pci_func **func_passed, u8 slotno)  		pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_PIN, &irq);  		if ((irq > 0x00) && (irq < 0x05))  			pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_INTERRUPT_LINE, func->irq[irq - 1]); -		/*     +		/*  		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, ctrl);  		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_PARITY);  		pci_bus_write_config_byte (ibmphp_pci_bus, devfn, PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR); @@ -1071,9 +1071,9 @@ error:   * This function adds up the amount of resources needed behind the PPB bridge   * and passes it to the configure_bridge function   * Input: bridge function - * Ouput: amount of resources needed + * Output: amount of resources needed   *****************************************************************************/ -static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno) +static struct res_needed *scan_behind_bridge (struct pci_func *func, u8 busno)  {  	int count, len[6];  	u16 vendor_id; @@ -1125,13 +1125,11 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)  				class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */  				if (class == PCI_CLASS_NOT_DEFINED_VGA) { -					err ("The device %x is VGA compatible and as is not supported for hot plugging. " -					     "Please choose another device.\n", device); +					err ("The device %x is VGA compatible and as is not supported for hot plugging.  Please choose another device.\n", device);  					amount->not_correct = 1;  					return amount;  				} else if (class == PCI_CLASS_DISPLAY_VGA) { -					err ("The device %x is not supported for hot plugging. " -					     "Please choose another device.\n", device); +					err ("The device %x is not supported for hot plugging.  Please choose another device.\n", device);  					amount->not_correct = 1;  					return amount;  				} @@ -1204,9 +1202,9 @@ static struct res_needed *scan_behind_bridge (struct pci_func * func, u8 busno)  	return amount;  } -/* The following 3 unconfigure_boot_ routines deal with the case when we had the card  - * upon bootup in the system, since we don't allocate func to such case, we need to read  - * the start addresses from pci config space and then find the corresponding entries in  +/* The following 3 unconfigure_boot_ routines deal with the case when we had the card + * upon bootup in the system, since we don't allocate func to such case, we need to read + * the start addresses from pci config space and then find the corresponding entries in   * our resource lists.  The functions return either 0, -ENODEV, or -1 (general failure)   * Change: we also call these functions even if we configured the card ourselves (i.e., not   * the bootup case), since it should work same way @@ -1483,12 +1481,10 @@ static int unconfigure_boot_card (struct slot *slot_cur)  			debug ("hdr_type %x, class %x\n", hdr_type, class);  			class >>= 8;	/* to take revision out, class = class.subclass.prog i/f */  			if (class == PCI_CLASS_NOT_DEFINED_VGA) { -				err ("The device %x function %x is VGA compatible and is not supported for hot removing. " -				     "Please choose another device.\n", device, function); +				err ("The device %x function %x is VGA compatible and is not supported for hot removing.  Please choose another device.\n", device, function);  				return -ENODEV;  			} else if (class == PCI_CLASS_DISPLAY_VGA) { -				err ("The device %x function %x is not supported for hot removing. " -				     "Please choose another device.\n", device, function); +				err ("The device %x function %x is not supported for hot removing.  Please choose another device.\n", device, function);  				return -ENODEV;  			} @@ -1513,9 +1509,7 @@ static int unconfigure_boot_card (struct slot *slot_cur)  				case PCI_HEADER_TYPE_BRIDGE:  					class >>= 8;  					if (class != PCI_CLASS_BRIDGE_PCI) { -						err ("This device %x function %x is not PCI-to-PCI bridge, " -						     "and is not supported for hot-removing. " -						     "Please try another card.\n", device, function); +						err ("This device %x function %x is not PCI-to-PCI bridge, and is not supported for hot-removing.  Please try another card.\n", device, function);  						return -ENODEV;  					}  					rc = unconfigure_boot_bridge (busno, device, function); @@ -1529,9 +1523,7 @@ static int unconfigure_boot_card (struct slot *slot_cur)  				case PCI_HEADER_TYPE_MULTIBRIDGE:  					class >>= 8;  					if (class != PCI_CLASS_BRIDGE_PCI) { -						err ("This device %x function %x is not PCI-to-PCI bridge, " -						     "and is not supported for hot-removing. " -						     "Please try another card.\n", device, function); +						err ("This device %x function %x is not PCI-to-PCI bridge,  and is not supported for hot-removing.  Please try another card.\n", device, function);  						return -ENODEV;  					}  					rc = unconfigure_boot_bridge (busno, device, function); @@ -1561,8 +1553,8 @@ static int unconfigure_boot_card (struct slot *slot_cur)   * unconfiguring the device   * TO DO:  will probably need to add some code in case there was some resource,   * to remove it... this is from when we have errors in the configure_card... - * 			!!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!! - * Returns: 0, -1, -ENODEV  + *			!!!!!!!!!!!!!!!!!!!!!!!!!FOR BUSES!!!!!!!!!!!! + * Returns: 0, -1, -ENODEV   */  int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)  { @@ -1634,7 +1626,7 @@ int ibmphp_unconfigure_card (struct slot **slot_cur, int the_end)   * Input: bus and the amount of resources needed (we know we can assign those,   *        since they've been checked already   * Output: bus added to the correct spot - *         0, -1, error  + *         0, -1, error   */  static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct resource_node *mem, struct resource_node *pfmem, u8 parent_busno)  { @@ -1650,7 +1642,7 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r  			err ("strange, cannot find bus which is supposed to be at the system... something is terribly wrong...\n");  			return -ENODEV;  		} -	 +  		list_add (&bus->bus_list, &cur_bus->bus_list);  	}  	if (io) { @@ -1679,7 +1671,7 @@ static int add_new_bus (struct bus_node *bus, struct resource_node *io, struct r  	}  	if (pfmem) {  		pfmem_range = kzalloc(sizeof(*pfmem_range), GFP_KERNEL); -		if (!pfmem_range) {	 +		if (!pfmem_range) {  			err ("out of system memory\n");  			return -ENOMEM;  		} @@ -1726,4 +1718,3 @@ static u8 find_sec_number (u8 primary_busno, u8 slotno)  		return busno;  	return 0xff;  } - diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index e2dc289f767..f34745abd5b 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -46,9 +46,9 @@ static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8);  static LIST_HEAD(gbuses); -static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8 busno, int flag) +static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc *curr, u8 busno, int flag)  { -	struct bus_node * newbus; +	struct bus_node *newbus;  	if (!(curr) && !(flag)) {  		err ("NULL pointer passed\n"); @@ -69,10 +69,10 @@ static struct bus_node * __init alloc_error_bus (struct ebda_pci_rsrc * curr, u8  	return newbus;  } -static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * curr) +static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc *curr)  {  	struct resource_node *rs; -	 +  	if (!curr) {  		err ("NULL passed to allocate\n");  		return NULL; @@ -93,7 +93,7 @@ static struct resource_node * __init alloc_resources (struct ebda_pci_rsrc * cur  static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node **new_range, struct ebda_pci_rsrc *curr, int flag, u8 first_bus)  { -	struct bus_node * newbus; +	struct bus_node *newbus;  	struct range_node *newrange;  	u8 num_ranges = 0; @@ -128,7 +128,7 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node  	}  	newrange->start = curr->start_addr;  	newrange->end = curr->end_addr; -		 +  	if (first_bus || (!num_ranges))  		newrange->rangeno = 1;  	else { @@ -162,7 +162,7 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node  			newbus->rangePFMem = newrange;  			if (first_bus)  				newbus->noPFMemRanges = 1; -			else {	 +			else {  				debug ("1st PFMemory Primary on Bus %x [%x - %x]\n", newbus->busno, newrange->start, newrange->end);  				++newbus->noPFMemRanges;  				fix_resources (newbus); @@ -190,7 +190,7 @@ static int __init alloc_bus_range (struct bus_node **new_bus, struct range_node   * This is the Resource Management initialization function.  It will go through   * the Resource list taken from EBDA and fill in this module's data structures   * - * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES,  + * THIS IS NOT TAKING INTO CONSIDERATION IO RESTRICTIONS OF PRIMARY BUSES,   * SINCE WE'RE GOING TO ASSUME FOR NOW WE DON'T HAVE THOSE ON OUR BUSES FOR NOW   *   * Input: ptr to the head of the resource list from EBDA @@ -382,7 +382,7 @@ int __init ibmphp_rsrc_init (void)   * pci devices' resources for the appropriate resource   *   * Input: type of the resource, range to add, current bus - * Output: 0 or -1, bus and range ptrs  + * Output: 0 or -1, bus and range ptrs   ********************************************************************************/  static int add_bus_range (int type, struct range_node *range, struct bus_node *bus_cur)  { @@ -466,7 +466,7 @@ static void update_resources (struct bus_node *bus_cur, int type, int rangeno)  	switch (type) {  		case MEM: -			if (bus_cur->firstMem)  +			if (bus_cur->firstMem)  				res = bus_cur->firstMem;  			break;  		case PFMEM: @@ -583,7 +583,7 @@ static void fix_resources (struct bus_node *bus_cur)  }  /******************************************************************************* - * This routine adds a resource to the list of resources to the appropriate bus  + * This routine adds a resource to the list of resources to the appropriate bus   * based on their resource type and sorted by their starting addresses.  It assigns   * the ptrs to next and nextRange if needed.   * @@ -605,11 +605,11 @@ int ibmphp_add_resource (struct resource_node *res)  		err ("NULL passed to add\n");  		return -ENODEV;  	} -	 +  	bus_cur = find_bus_wprev (res->busno, NULL, 0); -	 +  	if (!bus_cur) { -		/* didn't find a bus, smth's wrong!!! */ +		/* didn't find a bus, something's wrong!!! */  		debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");  		return -ENODEV;  	} @@ -648,7 +648,7 @@ int ibmphp_add_resource (struct resource_node *res)  	if (!range_cur) {  		switch (res->type) {  			case IO: -				++bus_cur->needIOUpdate;					 +				++bus_cur->needIOUpdate;  				break;  			case MEM:  				++bus_cur->needMemUpdate; @@ -659,13 +659,13 @@ int ibmphp_add_resource (struct resource_node *res)  		}  		res->rangeno = -1;  	} -	 +  	debug ("The range is %d\n", res->rangeno);  	if (!res_start) {  		/* no first{IO,Mem,Pfmem} on the bus, 1st IO/Mem/Pfmem resource ever */  		switch (res->type) {  			case IO: -				bus_cur->firstIO = res;					 +				bus_cur->firstIO = res;  				break;  			case MEM:  				bus_cur->firstMem = res; @@ -673,7 +673,7 @@ int ibmphp_add_resource (struct resource_node *res)  			case PFMEM:  				bus_cur->firstPFMem = res;  				break; -		}	 +		}  		res->next = NULL;  		res->nextRange = NULL;  	} else { @@ -770,7 +770,7 @@ int ibmphp_add_resource (struct resource_node *res)   * This routine will remove the resource from the list of resources   *   * Input: io, mem, and/or pfmem resource to be deleted - * Ouput: modified resource list + * Output: modified resource list   *        0 or error code   ****************************************************************************/  int ibmphp_remove_resource (struct resource_node *res) @@ -789,8 +789,7 @@ int ibmphp_remove_resource (struct resource_node *res)  	bus_cur = find_bus_wprev (res->busno, NULL, 0);  	if (!bus_cur) { -		err ("cannot find corresponding bus of the io resource to remove  " -			"bailing out...\n"); +		err ("cannot find corresponding bus of the io resource to remove  bailing out...\n");  		return -ENODEV;  	} @@ -825,7 +824,7 @@ int ibmphp_remove_resource (struct resource_node *res)  	if (!res_cur) {  		if (res->type == PFMEM) { -			/*  +			/*  			 * case where pfmem might be in the PFMemFromMem list  			 * so will also need to remove the corresponding mem  			 * entry @@ -934,9 +933,9 @@ int ibmphp_remove_resource (struct resource_node *res)  	return 0;  } -static struct range_node * find_range (struct bus_node *bus_cur, struct resource_node * res) +static struct range_node *find_range (struct bus_node *bus_cur, struct resource_node *res)  { -	struct range_node * range = NULL; +	struct range_node *range = NULL;  	switch (res->type) {  		case IO: @@ -961,12 +960,12 @@ static struct range_node * find_range (struct bus_node *bus_cur, struct resource  }  /***************************************************************************** - * This routine will check to make sure the io/mem/pfmem->len that the device asked for  + * This routine will check to make sure the io/mem/pfmem->len that the device asked for   * can fit w/i our list of available IO/MEM/PFMEM resources.  If cannot, returns -EINVAL,   * otherwise, returns 0   *   * Input: resource - * Ouput: the correct start and end address are inputted into the resource node, + * Output: the correct start and end address are inputted into the resource node,   *        0 or -EINVAL   *****************************************************************************/  int ibmphp_check_resource (struct resource_node *res, u8 bridge) @@ -996,7 +995,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)  	bus_cur = find_bus_wprev (res->busno, NULL, 0);  	if (!bus_cur) { -		/* didn't find a bus, smth's wrong!!! */ +		/* didn't find a bus, something's wrong!!! */  		debug ("no bus in the system, either pci_dev's wrong or allocation failed\n");  		return -EINVAL;  	} @@ -1066,7 +1065,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)  								break;  						}  					} -			 +  					if (flag && len_cur == res->len) {  						debug ("but we are not here, right?\n");  						res->start = start_cur; @@ -1118,10 +1117,10 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)  		if (res_prev) {  			if (res_prev->rangeno != res_cur->rangeno) {  				/* 1st device on this range */ -				if ((res_cur->start != range->start) &&  +				if ((res_cur->start != range->start) &&  					((len_tmp = res_cur->start - 1 - range->start) >= res->len)) {  					if ((len_tmp < len_cur) || (len_cur == 0)) { -						if ((range->start % tmp_divide) == 0) {	 +						if ((range->start % tmp_divide) == 0) {  							/* just perfect, starting address is divisible by length */  							flag = 1;  							len_cur = len_tmp; @@ -1344,7 +1343,7 @@ int ibmphp_check_resource (struct resource_node *res, u8 bridge)   * This routine is called from remove_card if the card contained PPB.   * It will remove all the resources on the bus as well as the bus itself   * Input: Bus - * Ouput: 0, -ENODEV + * Output: 0, -ENODEV   ********************************************************************************/  int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)  { @@ -1353,7 +1352,7 @@ int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)  	struct bus_node *prev_bus;  	int rc; -	prev_bus = find_bus_wprev (parent_busno, NULL, 0);	 +	prev_bus = find_bus_wprev (parent_busno, NULL, 0);  	if (!prev_bus) {  		debug ("something terribly wrong. Cannot find parent bus to the one to remove\n"); @@ -1424,7 +1423,7 @@ int ibmphp_remove_bus (struct bus_node *bus, u8 parent_busno)  }  /****************************************************************************** - * This routine deletes the ranges from a given bus, and the entries from the  + * This routine deletes the ranges from a given bus, and the entries from the   * parent's bus in the resources   * Input: current bus, previous bus   * Output: 0, -EINVAL @@ -1453,7 +1452,7 @@ static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)  	if (bus_cur->noMemRanges) {  		range_cur = bus_cur->rangeMem;  		for (i = 0; i < bus_cur->noMemRanges; i++) { -			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0)  +			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, MEM) < 0)  				return -EINVAL;  			ibmphp_remove_resource (res); @@ -1467,7 +1466,7 @@ static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)  	if (bus_cur->noPFMemRanges) {  		range_cur = bus_cur->rangePFMem;  		for (i = 0; i < bus_cur->noPFMemRanges; i++) { -			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0)  +			if (ibmphp_find_resource (bus_prev, range_cur->start, &res, PFMEM) < 0)  				return -EINVAL;  			ibmphp_remove_resource (res); @@ -1482,7 +1481,7 @@ static int remove_ranges (struct bus_node *bus_cur, struct bus_node *bus_prev)  }  /* - * find the resource node in the bus  + * find the resource node in the bus   * Input: Resource needed, start address of the resource, type of resource   */  int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resource_node **res, int flag) @@ -1512,7 +1511,7 @@ int ibmphp_find_resource (struct bus_node *bus, u32 start_address, struct resour  			err ("wrong type of flag\n");  			return -EINVAL;  	} -	 +  	while (res_cur) {  		if (res_cur->start == start_address) {  			*res = res_cur; @@ -1718,7 +1717,7 @@ static int __init once_over (void)  			}	/* end for pfmem */  		}	/* end if */  	}	/* end list_for_each bus */ -	return 0;  +	return 0;  }  int ibmphp_add_pfmem_from_mem (struct resource_node *pfmem) @@ -1760,9 +1759,9 @@ static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u  	list_for_each (tmp, &gbuses) {  		tmp_prev = tmp->prev;  		bus_cur = list_entry (tmp, struct bus_node, bus_list); -		if (flag)  +		if (flag)  			*prev = list_entry (tmp_prev, struct bus_node, bus_list); -		if (bus_cur->busno == bus_number)  +		if (bus_cur->busno == bus_number)  			return bus_cur;  	} @@ -1776,7 +1775,7 @@ void ibmphp_print_test (void)  	struct range_node *range;  	struct resource_node *res;  	struct list_head *tmp; -	 +  	debug_pci ("*****************START**********************\n");  	if ((!list_empty(&gbuses)) && flags) { @@ -1906,7 +1905,7 @@ static int range_exists_already (struct range_node * range, struct bus_node * bu  			return 1;  		range_cur = range_cur->next;  	} -	 +  	return 0;  } @@ -1920,7 +1919,7 @@ static int range_exists_already (struct range_node * range, struct bus_node * bu   * Returns: none   * Note: this function doesn't take into account IO restrictions etc,   *	 so will only work for bridges with no video/ISA devices behind them It - *	 also will not work for onboard PPB's that can have more than 1 *bus + *	 also will not work for onboard PPBs that can have more than 1 *bus   *	 behind them All these are TO DO.   *	 Also need to add more error checkings... (from fnc returns etc)   */ @@ -1963,7 +1962,7 @@ static int __init update_bridge_ranges (struct bus_node **bus)  					case PCI_HEADER_TYPE_BRIDGE:  						function = 0x8;  					case PCI_HEADER_TYPE_MULTIBRIDGE: -						/* We assume here that only 1 bus behind the bridge  +						/* We assume here that only 1 bus behind the bridge  						   TO DO: add functionality for several:  						   temp = secondary;  						   while (temp < subordinate) { @@ -1972,7 +1971,7 @@ static int __init update_bridge_ranges (struct bus_node **bus)  						   }  						 */  						pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_busno); -						bus_sec = find_bus_wprev (sec_busno, NULL, 0);  +						bus_sec = find_bus_wprev (sec_busno, NULL, 0);  						/* this bus structure doesn't exist yet, PPB was configured during previous loading of ibmphp */  						if (!bus_sec) {  							bus_sec = alloc_error_bus (NULL, sec_busno, 1); @@ -2028,7 +2027,7 @@ static int __init update_bridge_ranges (struct bus_node **bus)  								io->len = io->end - io->start + 1;  								ibmphp_add_resource (io);  							} -						}	 +						}  						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_BASE, &start_mem_address);  						pci_bus_read_config_word (ibmphp_pci_bus, devfn, PCI_MEMORY_LIMIT, &end_mem_address); diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index ec20f74c898..56d8486dc16 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -59,14 +59,12 @@ static bool debug;  #define DRIVER_DESC	"PCI Hot Plug PCI Core" -////////////////////////////////////////////////////////////////// -  static LIST_HEAD(pci_hotplug_slot_list);  static DEFINE_MUTEX(pci_hp_mutex);  /* Weee, fun with macros... */ -#define GET_STATUS(name,type)	\ -static int get_##name (struct hotplug_slot *slot, type *value)		\ +#define GET_STATUS(name, type)	\ +static int get_##name(struct hotplug_slot *slot, type *value)		\  {									\  	struct hotplug_slot_ops *ops = slot->ops;			\  	int retval = 0;							\ @@ -92,46 +90,45 @@ static ssize_t power_read_file(struct pci_slot *slot, char *buf)  	retval = get_power_status(slot->hotplug, &value);  	if (retval) -		goto exit; -	retval = sprintf (buf, "%d\n", value); -exit: -	return retval; +		return retval; + +	return sprintf(buf, "%d\n", value);  }  static ssize_t power_write_file(struct pci_slot *pci_slot, const char *buf, -		size_t count) +				size_t count)  {  	struct hotplug_slot *slot = pci_slot->hotplug;  	unsigned long lpower;  	u8 power;  	int retval = 0; -	lpower = simple_strtoul (buf, NULL, 10); +	lpower = simple_strtoul(buf, NULL, 10);  	power = (u8)(lpower & 0xff); -	dbg ("power = %d\n", power); +	dbg("power = %d\n", power);  	if (!try_module_get(slot->ops->owner)) {  		retval = -ENODEV;  		goto exit;  	}  	switch (power) { -		case 0: -			if (slot->ops->disable_slot) -				retval = slot->ops->disable_slot(slot); -			break; - -		case 1: -			if (slot->ops->enable_slot) -				retval = slot->ops->enable_slot(slot); -			break; - -		default: -			err ("Illegal value specified for power\n"); -			retval = -EINVAL; +	case 0: +		if (slot->ops->disable_slot) +			retval = slot->ops->disable_slot(slot); +		break; + +	case 1: +		if (slot->ops->enable_slot) +			retval = slot->ops->enable_slot(slot); +		break; + +	default: +		err("Illegal value specified for power\n"); +		retval = -EINVAL;  	}  	module_put(slot->ops->owner); -exit:	 +exit:  	if (retval)  		return retval;  	return count; @@ -150,24 +147,22 @@ static ssize_t attention_read_file(struct pci_slot *slot, char *buf)  	retval = get_attention_status(slot->hotplug, &value);  	if (retval) -		goto exit; -	retval = sprintf(buf, "%d\n", value); +		return retval; -exit: -	return retval; +	return sprintf(buf, "%d\n", value);  }  static ssize_t attention_write_file(struct pci_slot *slot, const char *buf, -		size_t count) +				    size_t count)  {  	struct hotplug_slot_ops *ops = slot->hotplug->ops;  	unsigned long lattention;  	u8 attention;  	int retval = 0; -	lattention = simple_strtoul (buf, NULL, 10); +	lattention = simple_strtoul(buf, NULL, 10);  	attention = (u8)(lattention & 0xff); -	dbg (" - attention = %d\n", attention); +	dbg(" - attention = %d\n", attention);  	if (!try_module_get(ops->owner)) {  		retval = -ENODEV; @@ -177,7 +172,7 @@ static ssize_t attention_write_file(struct pci_slot *slot, const char *buf,  		retval = ops->set_attention_status(slot->hotplug, attention);  	module_put(ops->owner); -exit:	 +exit:  	if (retval)  		return retval;  	return count; @@ -196,11 +191,9 @@ static ssize_t latch_read_file(struct pci_slot *slot, char *buf)  	retval = get_latch_status(slot->hotplug, &value);  	if (retval) -		goto exit; -	retval = sprintf (buf, "%d\n", value); +		return retval; -exit: -	return retval; +	return sprintf(buf, "%d\n", value);  }  static struct pci_slot_attribute hotplug_slot_attr_latch = { @@ -215,11 +208,9 @@ static ssize_t presence_read_file(struct pci_slot *slot, char *buf)  	retval = get_adapter_status(slot->hotplug, &value);  	if (retval) -		goto exit; -	retval = sprintf (buf, "%d\n", value); +		return retval; -exit: -	return retval; +	return sprintf(buf, "%d\n", value);  }  static struct pci_slot_attribute hotplug_slot_attr_presence = { @@ -228,7 +219,7 @@ static struct pci_slot_attribute hotplug_slot_attr_presence = {  };  static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf, -		size_t count) +			       size_t count)  {  	struct hotplug_slot *slot = pci_slot->hotplug;  	unsigned long ltest; @@ -237,7 +228,7 @@ static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,  	ltest = simple_strtoul (buf, NULL, 10);  	test = (u32)(ltest & 0xffffffff); -	dbg ("test = %d\n", test); +	dbg("test = %d\n", test);  	if (!try_module_get(slot->ops->owner)) {  		retval = -ENODEV; @@ -247,7 +238,7 @@ static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,  		retval = slot->ops->hardware_test(slot, test);  	module_put(slot->ops->owner); -exit:	 +exit:  	if (retval)  		return retval;  	return count; @@ -261,6 +252,7 @@ static struct pci_slot_attribute hotplug_slot_attr_test = {  static bool has_power_file(struct pci_slot *pci_slot)  {  	struct hotplug_slot *slot = pci_slot->hotplug; +  	if ((!slot) || (!slot->ops))  		return false;  	if ((slot->ops->enable_slot) || @@ -273,6 +265,7 @@ static bool has_power_file(struct pci_slot *pci_slot)  static bool has_attention_file(struct pci_slot *pci_slot)  {  	struct hotplug_slot *slot = pci_slot->hotplug; +  	if ((!slot) || (!slot->ops))  		return false;  	if ((slot->ops->set_attention_status) || @@ -284,6 +277,7 @@ static bool has_attention_file(struct pci_slot *pci_slot)  static bool has_latch_file(struct pci_slot *pci_slot)  {  	struct hotplug_slot *slot = pci_slot->hotplug; +  	if ((!slot) || (!slot->ops))  		return false;  	if (slot->ops->get_latch_status) @@ -294,6 +288,7 @@ static bool has_latch_file(struct pci_slot *pci_slot)  static bool has_adapter_file(struct pci_slot *pci_slot)  {  	struct hotplug_slot *slot = pci_slot->hotplug; +  	if ((!slot) || (!slot->ops))  		return false;  	if (slot->ops->get_adapter_status) @@ -304,6 +299,7 @@ static bool has_adapter_file(struct pci_slot *pci_slot)  static bool has_test_file(struct pci_slot *pci_slot)  {  	struct hotplug_slot *slot = pci_slot->hotplug; +  	if ((!slot) || (!slot->ops))  		return false;  	if (slot->ops->hardware_test) @@ -397,13 +393,13 @@ static void fs_remove_slot(struct pci_slot *slot)  	pci_hp_remove_module_link(slot);  } -static struct hotplug_slot *get_slot_from_name (const char *name) +static struct hotplug_slot *get_slot_from_name(const char *name)  {  	struct hotplug_slot *slot;  	struct list_head *tmp; -	list_for_each (tmp, &pci_hotplug_slot_list) { -		slot = list_entry (tmp, struct hotplug_slot, slot_list); +	list_for_each(tmp, &pci_hotplug_slot_list) { +		slot = list_entry(tmp, struct hotplug_slot, slot_list);  		if (strcmp(hotplug_slot_name(slot), name) == 0)  			return slot;  	} @@ -436,8 +432,7 @@ int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus,  	if ((slot->info == NULL) || (slot->ops == NULL))  		return -EINVAL;  	if (slot->release == NULL) { -		dbg("Why are you trying to register a hotplug slot " -		    "without a proper release function?\n"); +		dbg("Why are you trying to register a hotplug slot without a proper release function?\n");  		return -EINVAL;  	} @@ -468,6 +463,7 @@ out:  	mutex_unlock(&pci_hp_mutex);  	return result;  } +EXPORT_SYMBOL_GPL(__pci_hp_register);  /**   * pci_hp_deregister - deregister a hotplug_slot with the PCI hotplug subsystem @@ -506,13 +502,14 @@ int pci_hp_deregister(struct hotplug_slot *hotplug)  	return 0;  } +EXPORT_SYMBOL_GPL(pci_hp_deregister);  /**   * pci_hp_change_slot_info - changes the slot's information structure in the core   * @hotplug: pointer to the slot whose info has changed   * @info: pointer to the info copy into the slot's info structure   * - * @slot must have been registered with the pci  + * @slot must have been registered with the pci   * hotplug subsystem previously with a call to pci_hp_register().   *   * Returns 0 if successful, anything else for an error. @@ -527,24 +524,23 @@ int pci_hp_change_slot_info(struct hotplug_slot *hotplug,  	return 0;  } +EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); -static int __init pci_hotplug_init (void) +static int __init pci_hotplug_init(void)  {  	int result;  	result = cpci_hotplug_init(debug);  	if (result) { -		err ("cpci_hotplug_init with error %d\n", result); -		goto err_cpci; +		err("cpci_hotplug_init with error %d\n", result); +		return result;  	} -	info (DRIVER_DESC " version: " DRIVER_VERSION "\n"); - -err_cpci: +	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");  	return result;  } -static void __exit pci_hotplug_exit (void) +static void __exit pci_hotplug_exit(void)  {  	cpci_hotplug_exit();  } @@ -557,7 +553,3 @@ MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL");  module_param(debug, bool, 0644);  MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); - -EXPORT_SYMBOL_GPL(__pci_hp_register); -EXPORT_SYMBOL_GPL(pci_hp_deregister); -EXPORT_SYMBOL_GPL(pci_hp_change_slot_info); diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 541bbe6d534..8e9012dca45 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -43,7 +43,6 @@  extern bool pciehp_poll_mode;  extern int pciehp_poll_time;  extern bool pciehp_debug; -extern bool pciehp_force;  #define dbg(format, arg...)						\  do {									\ @@ -77,6 +76,7 @@ struct slot {  	struct hotplug_slot *hotplug_slot;  	struct delayed_work work;	/* work for button event */  	struct mutex lock; +	struct mutex hotplug_lock;  	struct workqueue_struct *wq;  }; @@ -110,6 +110,8 @@ struct controller {  #define INT_BUTTON_PRESS		7  #define INT_BUTTON_RELEASE		8  #define INT_BUTTON_CANCEL		9 +#define INT_LINK_UP			10 +#define INT_LINK_DOWN			11  #define STATIC_STATE			0  #define BLINKINGON_STATE		1 @@ -125,7 +127,7 @@ struct controller {  #define HP_SUPR_RM(ctrl)	((ctrl)->slot_cap & PCI_EXP_SLTCAP_HPS)  #define EMI(ctrl)		((ctrl)->slot_cap & PCI_EXP_SLTCAP_EIP)  #define NO_CMD_CMPL(ctrl)	((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS) -#define PSN(ctrl)		((ctrl)->slot_cap >> 19) +#define PSN(ctrl)		(((ctrl)->slot_cap & PCI_EXP_SLTCAP_PSN) >> 19)  int pciehp_sysfs_enable_slot(struct slot *slot);  int pciehp_sysfs_disable_slot(struct slot *slot); @@ -133,6 +135,7 @@ u8 pciehp_handle_attention_button(struct slot *p_slot);  u8 pciehp_handle_switch_change(struct slot *p_slot);  u8 pciehp_handle_presence_change(struct slot *p_slot);  u8 pciehp_handle_power_fault(struct slot *p_slot); +void pciehp_handle_linkstate_change(struct slot *p_slot);  int pciehp_configure_device(struct slot *p_slot);  int pciehp_unconfigure_device(struct slot *p_slot);  void pciehp_queue_pushbutton_work(struct work_struct *work); @@ -140,20 +143,21 @@ struct controller *pcie_init(struct pcie_device *dev);  int pcie_init_notification(struct controller *ctrl);  int pciehp_enable_slot(struct slot *p_slot);  int pciehp_disable_slot(struct slot *p_slot); -int pcie_enable_notification(struct controller *ctrl); +void pcie_enable_notification(struct controller *ctrl);  int pciehp_power_on_slot(struct slot *slot); -int pciehp_power_off_slot(struct slot *slot); -int pciehp_get_power_status(struct slot *slot, u8 *status); -int pciehp_get_attention_status(struct slot *slot, u8 *status); +void pciehp_power_off_slot(struct slot *slot); +void pciehp_get_power_status(struct slot *slot, u8 *status); +void pciehp_get_attention_status(struct slot *slot, u8 *status); -int pciehp_set_attention_status(struct slot *slot, u8 status); -int pciehp_get_latch_status(struct slot *slot, u8 *status); -int pciehp_get_adapter_status(struct slot *slot, u8 *status); +void pciehp_set_attention_status(struct slot *slot, u8 status); +void pciehp_get_latch_status(struct slot *slot, u8 *status); +void pciehp_get_adapter_status(struct slot *slot, u8 *status);  int pciehp_query_power_fault(struct slot *slot);  void pciehp_green_led_on(struct slot *slot);  void pciehp_green_led_off(struct slot *slot);  void pciehp_green_led_blink(struct slot *slot);  int pciehp_check_link_status(struct controller *ctrl); +bool pciehp_check_link_active(struct controller *ctrl);  void pciehp_release_ctrl(struct controller *ctrl);  int pciehp_reset_slot(struct slot *slot, int probe); @@ -163,8 +167,6 @@ static inline const char *slot_name(struct slot *slot)  }  #ifdef CONFIG_ACPI -#include <acpi/acpi.h> -#include <acpi/acpi_bus.h>  #include <linux/pci-acpi.h>  void __init pciehp_acpi_slot_detection_init(void); @@ -180,5 +182,5 @@ static inline int pciehp_acpi_slot_detection_check(struct pci_dev *dev)  {  	return 0;  } -#endif 				/* CONFIG_ACPI */ +#endif				/* CONFIG_ACPI */  #endif				/* _PCIEHP_H */ diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index ead7c534095..93cc9266e8c 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -54,7 +54,7 @@ int pciehp_acpi_slot_detection_check(struct pci_dev *dev)  {  	if (slot_detection_mode != PCIEHP_DETECT_ACPI)  		return 0; -	if (acpi_pci_detect_ejectable(DEVICE_ACPI_HANDLE(&dev->dev))) +	if (acpi_pci_detect_ejectable(ACPI_HANDLE(&dev->dev)))  		return 0;  	return -ENODEV;  } @@ -78,7 +78,7 @@ static int __initdata dup_slot_id;  static int __initdata acpi_slot_detected;  static struct list_head __initdata dummy_slots = LIST_HEAD_INIT(dummy_slots); -/* Dummy driver for dumplicate name detection */ +/* Dummy driver for duplicate name detection */  static int __init dummy_probe(struct pcie_device *dev)  {  	u32 slot_cap; @@ -96,22 +96,23 @@ static int __init dummy_probe(struct pcie_device *dev)  			dup_slot_id++;  	}  	list_add_tail(&slot->list, &dummy_slots); -	handle = DEVICE_ACPI_HANDLE(&pdev->dev); +	handle = ACPI_HANDLE(&pdev->dev);  	if (!acpi_slot_detected && acpi_pci_detect_ejectable(handle))  		acpi_slot_detected = 1;  	return -ENODEV;         /* dummy driver always returns error */  }  static struct pcie_port_service_driver __initdata dummy_driver = { -        .name           = "pciehp_dummy", +	.name		= "pciehp_dummy",  	.port_type	= PCIE_ANY_PORT,  	.service	= PCIE_PORT_SERVICE_HP, -        .probe          = dummy_probe, +	.probe		= dummy_probe,  };  static int __init select_detection_mode(void)  {  	struct dummy_slot *slot, *tmp; +  	if (pcie_port_service_register(&dummy_driver))  		return PCIEHP_DETECT_ACPI;  	pcie_port_service_unregister(&dummy_driver); diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index f4a18f51a29..a2297db8081 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -41,7 +41,7 @@  bool pciehp_debug;  bool pciehp_poll_mode;  int pciehp_poll_time; -bool pciehp_force; +static bool pciehp_force;  #define DRIVER_VERSION	"0.4"  #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" @@ -108,6 +108,7 @@ static int init_slot(struct controller *ctrl)  	ops = kzalloc(sizeof(*ops), GFP_KERNEL);  	if (!ops)  		goto out; +  	ops->enable_slot = enable_slot;  	ops->disable_slot = disable_slot;  	ops->get_power_status = get_power_status; @@ -160,7 +161,8 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)  	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",  		  __func__, slot_name(slot)); -	return pciehp_set_attention_status(slot, status); +	pciehp_set_attention_status(slot, status); +	return 0;  } @@ -192,7 +194,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)  	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",  		  __func__, slot_name(slot)); -	return pciehp_get_power_status(slot, value); +	pciehp_get_power_status(slot, value); +	return 0;  }  static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -202,7 +205,8 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)  	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",  		  __func__, slot_name(slot)); -	return pciehp_get_attention_status(slot, value); +	pciehp_get_attention_status(slot, value); +	return 0;  }  static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -212,7 +216,8 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)  	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",  		 __func__, slot_name(slot)); -	return pciehp_get_latch_status(slot, value); +	pciehp_get_latch_status(slot, value); +	return 0;  }  static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value) @@ -222,7 +227,8 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)  	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",  		 __func__, slot_name(slot)); -	return pciehp_get_adapter_status(slot, value); +	pciehp_get_adapter_status(slot, value); +	return 0;  }  static int reset_slot(struct hotplug_slot *hotplug_slot, int probe) @@ -260,8 +266,7 @@ static int pciehp_probe(struct pcie_device *dev)  	rc = init_slot(ctrl);  	if (rc) {  		if (rc == -EBUSY) -			ctrl_warn(ctrl, "Slot already registered by another " -				  "hotplug driver\n"); +			ctrl_warn(ctrl, "Slot already registered by another hotplug driver\n");  		else  			ctrl_err(ctrl, "Slot initialization failed\n");  		goto err_out_release_ctlr; @@ -278,8 +283,11 @@ static int pciehp_probe(struct pcie_device *dev)  	slot = ctrl->slot;  	pciehp_get_adapter_status(slot, &occupied);  	pciehp_get_power_status(slot, &poweron); -	if (occupied && pciehp_force) +	if (occupied && pciehp_force) { +		mutex_lock(&slot->hotplug_lock);  		pciehp_enable_slot(slot); +		mutex_unlock(&slot->hotplug_lock); +	}  	/* If empty slot's power status is on, turn power off */  	if (!occupied && poweron && POWER_CTRL(ctrl))  		pciehp_power_off_slot(slot); @@ -303,12 +311,12 @@ static void pciehp_remove(struct pcie_device *dev)  }  #ifdef CONFIG_PM -static int pciehp_suspend (struct pcie_device *dev) +static int pciehp_suspend(struct pcie_device *dev)  {  	return 0;  } -static int pciehp_resume (struct pcie_device *dev) +static int pciehp_resume(struct pcie_device *dev)  {  	struct controller *ctrl;  	struct slot *slot; @@ -323,10 +331,12 @@ static int pciehp_resume (struct pcie_device *dev)  	/* Check if slot is occupied */  	pciehp_get_adapter_status(slot, &status); +	mutex_lock(&slot->hotplug_lock);  	if (status)  		pciehp_enable_slot(slot);  	else  		pciehp_disable_slot(slot); +	mutex_unlock(&slot->hotplug_lock);  	return 0;  }  #endif /* PM */ @@ -351,8 +361,8 @@ static int __init pcied_init(void)  	pciehp_firmware_init();  	retval = pcie_port_service_register(&hpdriver_portdrv); - 	dbg("pcie_port_service_register = %d\n", retval); -  	info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); +	dbg("pcie_port_service_register = %d\n", retval); +	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");  	if (retval)  		dbg("Failure to register service\n"); diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 38f01867917..ff32e85e1de 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -150,19 +150,37 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)  	return 1;  } +void pciehp_handle_linkstate_change(struct slot *p_slot) +{ +	u32 event_type; +	struct controller *ctrl = p_slot->ctrl; + +	/* Link Status Change */ +	ctrl_dbg(ctrl, "Data Link Layer State change\n"); + +	if (pciehp_check_link_active(ctrl)) { +		ctrl_info(ctrl, "slot(%s): Link Up event\n", +			  slot_name(p_slot)); +		event_type = INT_LINK_UP; +	} else { +		ctrl_info(ctrl, "slot(%s): Link Down event\n", +			  slot_name(p_slot)); +		event_type = INT_LINK_DOWN; +	} + +	queue_interrupt_event(p_slot, event_type); +} +  /* The following routines constitute the bulk of the     hotplug controller logic   */ -static void set_slot_off(struct controller *ctrl, struct slot * pslot) +static void set_slot_off(struct controller *ctrl, struct slot *pslot)  {  	/* turn off slot, turn on Amber LED, turn off Green LED if supported*/  	if (POWER_CTRL(ctrl)) { -		if (pciehp_power_off_slot(pslot)) { -			ctrl_err(ctrl, -				 "Issue of Slot Power Off command failed\n"); -			return; -		} +		pciehp_power_off_slot(pslot); +  		/*  		 * After turning power off, we must wait for at least 1 second  		 * before taking any action that relies on power having been @@ -171,16 +189,8 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)  		msleep(1000);  	} -	if (PWR_LED(ctrl)) -		pciehp_green_led_off(pslot); - -	if (ATTN_LED(ctrl)) { -		if (pciehp_set_attention_status(pslot, 1)) { -			ctrl_err(ctrl, -				 "Issue of Set Attention Led command failed\n"); -			return; -		} -	} +	pciehp_green_led_off(pslot); +	pciehp_set_attention_status(pslot, 1);  }  /** @@ -203,8 +213,7 @@ static int board_added(struct slot *p_slot)  			return retval;  	} -	if (PWR_LED(ctrl)) -		pciehp_green_led_blink(p_slot); +	pciehp_green_led_blink(p_slot);  	/* Check link training status */  	retval = pciehp_check_link_status(ctrl); @@ -224,12 +233,11 @@ static int board_added(struct slot *p_slot)  	if (retval) {  		ctrl_err(ctrl, "Cannot add device at %04x:%02x:00\n",  			 pci_domain_nr(parent), parent->number); -		goto err_exit; +		if (retval != -EEXIST) +			goto err_exit;  	} -	if (PWR_LED(ctrl)) -		pciehp_green_led_on(p_slot); - +	pciehp_green_led_on(p_slot);  	return 0;  err_exit: @@ -243,7 +251,7 @@ err_exit:   */  static int remove_board(struct slot *p_slot)  { -	int retval = 0; +	int retval;  	struct controller *ctrl = p_slot->ctrl;  	retval = pciehp_unconfigure_device(p_slot); @@ -251,13 +259,8 @@ static int remove_board(struct slot *p_slot)  		return retval;  	if (POWER_CTRL(ctrl)) { -		/* power off slot */ -		retval = pciehp_power_off_slot(p_slot); -		if (retval) { -			ctrl_err(ctrl, -				 "Issue of Slot Disable command failed\n"); -			return retval; -		} +		pciehp_power_off_slot(p_slot); +  		/*  		 * After turning power off, we must wait for at least 1 second  		 * before taking any action that relies on power having been @@ -267,15 +270,16 @@ static int remove_board(struct slot *p_slot)  	}  	/* turn off Green LED */ -	if (PWR_LED(ctrl)) -		pciehp_green_led_off(p_slot); - +	pciehp_green_led_off(p_slot);  	return 0;  }  struct power_work_info {  	struct slot *p_slot;  	struct work_struct work; +	unsigned int req; +#define DISABLE_REQ 0 +#define ENABLE_REQ  1  };  /** @@ -290,30 +294,38 @@ static void pciehp_power_thread(struct work_struct *work)  	struct power_work_info *info =  		container_of(work, struct power_work_info, work);  	struct slot *p_slot = info->p_slot; +	int ret; -	mutex_lock(&p_slot->lock); -	switch (p_slot->state) { -	case POWEROFF_STATE: -		mutex_unlock(&p_slot->lock); +	switch (info->req) { +	case DISABLE_REQ:  		ctrl_dbg(p_slot->ctrl,  			 "Disabling domain:bus:device=%04x:%02x:00\n",  			 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate),  			 p_slot->ctrl->pcie->port->subordinate->number); +		mutex_lock(&p_slot->hotplug_lock);  		pciehp_disable_slot(p_slot); +		mutex_unlock(&p_slot->hotplug_lock);  		mutex_lock(&p_slot->lock);  		p_slot->state = STATIC_STATE; -		break; -	case POWERON_STATE:  		mutex_unlock(&p_slot->lock); -		if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl)) +		break; +	case ENABLE_REQ: +		ctrl_dbg(p_slot->ctrl, +			 "Enabling domain:bus:device=%04x:%02x:00\n", +			 pci_domain_nr(p_slot->ctrl->pcie->port->subordinate), +			 p_slot->ctrl->pcie->port->subordinate->number); +		mutex_lock(&p_slot->hotplug_lock); +		ret = pciehp_enable_slot(p_slot); +		mutex_unlock(&p_slot->hotplug_lock); +		if (ret)  			pciehp_green_led_off(p_slot);  		mutex_lock(&p_slot->lock);  		p_slot->state = STATIC_STATE; +		mutex_unlock(&p_slot->lock);  		break;  	default:  		break;  	} -	mutex_unlock(&p_slot->lock);  	kfree(info);  } @@ -336,9 +348,11 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)  	switch (p_slot->state) {  	case BLINKINGOFF_STATE:  		p_slot->state = POWEROFF_STATE; +		info->req = DISABLE_REQ;  		break;  	case BLINKINGON_STATE:  		p_slot->state = POWERON_STATE; +		info->req = ENABLE_REQ;  		break;  	default:  		kfree(info); @@ -362,21 +376,16 @@ static void handle_button_press_event(struct slot *p_slot)  		pciehp_get_power_status(p_slot, &getstatus);  		if (getstatus) {  			p_slot->state = BLINKINGOFF_STATE; -			ctrl_info(ctrl, -				  "PCI slot #%s - powering off due to button " -				  "press.\n", slot_name(p_slot)); +			ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", +				  slot_name(p_slot));  		} else {  			p_slot->state = BLINKINGON_STATE; -			ctrl_info(ctrl, -				  "PCI slot #%s - powering on due to button " -				  "press.\n", slot_name(p_slot)); +			ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", +				  slot_name(p_slot));  		}  		/* blink green LED and turn off amber */ -		if (PWR_LED(ctrl)) -			pciehp_green_led_blink(p_slot); -		if (ATTN_LED(ctrl)) -			pciehp_set_attention_status(p_slot, 0); - +		pciehp_green_led_blink(p_slot); +		pciehp_set_attention_status(p_slot, 0);  		queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);  		break;  	case BLINKINGOFF_STATE: @@ -388,17 +397,13 @@ static void handle_button_press_event(struct slot *p_slot)  		 */  		ctrl_info(ctrl, "Button cancel on Slot(%s)\n", slot_name(p_slot));  		cancel_delayed_work(&p_slot->work); -		if (p_slot->state == BLINKINGOFF_STATE) { -			if (PWR_LED(ctrl)) -				pciehp_green_led_on(p_slot); -		} else { -			if (PWR_LED(ctrl)) -				pciehp_green_led_off(p_slot); -		} -		if (ATTN_LED(ctrl)) -			pciehp_set_attention_status(p_slot, 0); -		ctrl_info(ctrl, "PCI slot #%s - action canceled " -			  "due to button press\n", slot_name(p_slot)); +		if (p_slot->state == BLINKINGOFF_STATE) +			pciehp_green_led_on(p_slot); +		else +			pciehp_green_led_off(p_slot); +		pciehp_set_attention_status(p_slot, 0); +		ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", +			  slot_name(p_slot));  		p_slot->state = STATIC_STATE;  		break;  	case POWEROFF_STATE: @@ -434,14 +439,81 @@ static void handle_surprise_event(struct slot *p_slot)  	INIT_WORK(&info->work, pciehp_power_thread);  	pciehp_get_adapter_status(p_slot, &getstatus); -	if (!getstatus) +	if (!getstatus) {  		p_slot->state = POWEROFF_STATE; -	else +		info->req = DISABLE_REQ; +	} else {  		p_slot->state = POWERON_STATE; +		info->req = ENABLE_REQ; +	}  	queue_work(p_slot->wq, &info->work);  } +/* + * Note: This function must be called with slot->lock held + */ +static void handle_link_event(struct slot *p_slot, u32 event) +{ +	struct controller *ctrl = p_slot->ctrl; +	struct power_work_info *info; + +	info = kmalloc(sizeof(*info), GFP_KERNEL); +	if (!info) { +		ctrl_err(p_slot->ctrl, "%s: Cannot allocate memory\n", +			 __func__); +		return; +	} +	info->p_slot = p_slot; +	info->req = event == INT_LINK_UP ? ENABLE_REQ : DISABLE_REQ; +	INIT_WORK(&info->work, pciehp_power_thread); + +	switch (p_slot->state) { +	case BLINKINGON_STATE: +	case BLINKINGOFF_STATE: +		cancel_delayed_work(&p_slot->work); +		/* Fall through */ +	case STATIC_STATE: +		p_slot->state = event == INT_LINK_UP ? +		    POWERON_STATE : POWEROFF_STATE; +		queue_work(p_slot->wq, &info->work); +		break; +	case POWERON_STATE: +		if (event == INT_LINK_UP) { +			ctrl_info(ctrl, +				  "Link Up event ignored on slot(%s): already powering on\n", +				  slot_name(p_slot)); +			kfree(info); +		} else { +			ctrl_info(ctrl, +				  "Link Down event queued on slot(%s): currently getting powered on\n", +				  slot_name(p_slot)); +			p_slot->state = POWEROFF_STATE; +			queue_work(p_slot->wq, &info->work); +		} +		break; +	case POWEROFF_STATE: +		if (event == INT_LINK_UP) { +			ctrl_info(ctrl, +				  "Link Up event queued on slot(%s): currently getting powered off\n", +				  slot_name(p_slot)); +			p_slot->state = POWERON_STATE; +			queue_work(p_slot->wq, &info->work); +		} else { +			ctrl_info(ctrl, +				  "Link Down event ignored on slot(%s): already powering off\n", +				  slot_name(p_slot)); +			kfree(info); +		} +		break; +	default: +		ctrl_err(ctrl, "Not a valid state on slot(%s)\n", +			 slot_name(p_slot)); +		kfree(info); +		break; +	} +} +  static void interrupt_event_handler(struct work_struct *work)  {  	struct event_info *info = container_of(work, struct event_info, work); @@ -456,18 +528,27 @@ static void interrupt_event_handler(struct work_struct *work)  	case INT_POWER_FAULT:  		if (!POWER_CTRL(ctrl))  			break; -		if (ATTN_LED(ctrl)) -			pciehp_set_attention_status(p_slot, 1); -		if (PWR_LED(ctrl)) -			pciehp_green_led_off(p_slot); +		pciehp_set_attention_status(p_slot, 1); +		pciehp_green_led_off(p_slot);  		break;  	case INT_PRESENCE_ON: -	case INT_PRESENCE_OFF:  		if (!HP_SUPR_RM(ctrl))  			break; +		ctrl_dbg(ctrl, "Surprise Insertion\n"); +		handle_surprise_event(p_slot); +		break; +	case INT_PRESENCE_OFF: +		/* +		 * Regardless of surprise capability, we need to +		 * definitely remove a card that has been pulled out! +		 */  		ctrl_dbg(ctrl, "Surprise Removal\n");  		handle_surprise_event(p_slot);  		break; +	case INT_LINK_UP: +	case INT_LINK_DOWN: +		handle_link_event(p_slot, info->event_type); +		break;  	default:  		break;  	} @@ -476,20 +557,23 @@ static void interrupt_event_handler(struct work_struct *work)  	kfree(info);  } +/* + * Note: This function must be called with slot->hotplug_lock held + */  int pciehp_enable_slot(struct slot *p_slot)  {  	u8 getstatus = 0;  	int rc;  	struct controller *ctrl = p_slot->ctrl; -	rc = pciehp_get_adapter_status(p_slot, &getstatus); -	if (rc || !getstatus) { +	pciehp_get_adapter_status(p_slot, &getstatus); +	if (!getstatus) {  		ctrl_info(ctrl, "No adapter on slot(%s)\n", slot_name(p_slot));  		return -ENODEV;  	}  	if (MRL_SENS(p_slot->ctrl)) { -		rc = pciehp_get_latch_status(p_slot, &getstatus); -		if (rc || getstatus) { +		pciehp_get_latch_status(p_slot, &getstatus); +		if (getstatus) {  			ctrl_info(ctrl, "Latch open on slot(%s)\n",  				  slot_name(p_slot));  			return -ENODEV; @@ -497,8 +581,8 @@ int pciehp_enable_slot(struct slot *p_slot)  	}  	if (POWER_CTRL(p_slot->ctrl)) { -		rc = pciehp_get_power_status(p_slot, &getstatus); -		if (rc || getstatus) { +		pciehp_get_power_status(p_slot, &getstatus); +		if (getstatus) {  			ctrl_info(ctrl, "Already enabled on slot(%s)\n",  				  slot_name(p_slot));  			return -EINVAL; @@ -508,43 +592,26 @@ int pciehp_enable_slot(struct slot *p_slot)  	pciehp_get_latch_status(p_slot, &getstatus);  	rc = board_added(p_slot); -	if (rc) { +	if (rc)  		pciehp_get_latch_status(p_slot, &getstatus); -	} +  	return rc;  } - +/* + * Note: This function must be called with slot->hotplug_lock held + */  int pciehp_disable_slot(struct slot *p_slot)  {  	u8 getstatus = 0; -	int ret = 0;  	struct controller *ctrl = p_slot->ctrl;  	if (!p_slot->ctrl)  		return 1; -	if (!HP_SUPR_RM(p_slot->ctrl)) { -		ret = pciehp_get_adapter_status(p_slot, &getstatus); -		if (ret || !getstatus) { -			ctrl_info(ctrl, "No adapter on slot(%s)\n", -				  slot_name(p_slot)); -			return -ENODEV; -		} -	} - -	if (MRL_SENS(p_slot->ctrl)) { -		ret = pciehp_get_latch_status(p_slot, &getstatus); -		if (ret || getstatus) { -			ctrl_info(ctrl, "Latch open on slot(%s)\n", -				  slot_name(p_slot)); -			return -ENODEV; -		} -	} -  	if (POWER_CTRL(p_slot->ctrl)) { -		ret = pciehp_get_power_status(p_slot, &getstatus); -		if (ret || !getstatus) { +		pciehp_get_power_status(p_slot, &getstatus); +		if (!getstatus) {  			ctrl_info(ctrl, "Already disabled on slot(%s)\n",  				  slot_name(p_slot));  			return -EINVAL; @@ -566,7 +633,9 @@ int pciehp_sysfs_enable_slot(struct slot *p_slot)  	case STATIC_STATE:  		p_slot->state = POWERON_STATE;  		mutex_unlock(&p_slot->lock); +		mutex_lock(&p_slot->hotplug_lock);  		retval = pciehp_enable_slot(p_slot); +		mutex_unlock(&p_slot->hotplug_lock);  		mutex_lock(&p_slot->lock);  		p_slot->state = STATIC_STATE;  		break; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 51f56ef4ab6..42914e04d11 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -41,34 +41,11 @@  #include "../pci.h"  #include "pciehp.h" -static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value) +static inline struct pci_dev *ctrl_dev(struct controller *ctrl)  { -	struct pci_dev *dev = ctrl->pcie->port; -	return pcie_capability_read_word(dev, reg, value); +	return ctrl->pcie->port;  } -static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value) -{ -	struct pci_dev *dev = ctrl->pcie->port; -	return pcie_capability_read_dword(dev, reg, value); -} - -static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value) -{ -	struct pci_dev *dev = ctrl->pcie->port; -	return pcie_capability_write_word(dev, reg, value); -} - -static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) -{ -	struct pci_dev *dev = ctrl->pcie->port; -	return pcie_capability_write_dword(dev, reg, value); -} - -/* Power Control Command */ -#define POWER_ON	0 -#define POWER_OFF	PCI_EXP_SLTCTL_PCC -  static irqreturn_t pcie_isr(int irq, void *dev_id);  static void start_int_poll_timer(struct controller *ctrl, int sec); @@ -92,7 +69,7 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)  {  	/* Clamp to sane value */  	if ((sec <= 0) || (sec > 60)) -        	sec = 2; +		sec = 2;  	ctrl->poll_timer.function = &int_poll_timeout;  	ctrl->poll_timer.data = (unsigned long)ctrl; @@ -129,20 +106,23 @@ static inline void pciehp_free_irq(struct controller *ctrl)  static int pcie_poll_cmd(struct controller *ctrl)  { +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 slot_status; -	int err, timeout = 1000; +	int timeout = 1000; -	err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -	if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { -		pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); +	if (slot_status & PCI_EXP_SLTSTA_CC) { +		pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, +					   PCI_EXP_SLTSTA_CC);  		return 1;  	}  	while (timeout > 0) {  		msleep(10);  		timeout -= 10; -		err = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -		if (!err && (slot_status & PCI_EXP_SLTSTA_CC)) { -			pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_CC); +		pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); +		if (slot_status & PCI_EXP_SLTSTA_CC) { +			pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, +						   PCI_EXP_SLTSTA_CC);  			return 1;  		}  	} @@ -169,22 +149,18 @@ static void pcie_wait_cmd(struct controller *ctrl, int poll)   * @cmd:  command value written to slot control register   * @mask: bitmask of slot control register to be modified   */ -static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask) +static void pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)  { -	int retval = 0; +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 slot_status;  	u16 slot_ctrl;  	mutex_lock(&ctrl->ctrl_lock); -	retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", -			 __func__); -		goto out; -	} - +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);  	if (slot_status & PCI_EXP_SLTSTA_CC) { +		pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, +					   PCI_EXP_SLTSTA_CC);  		if (!ctrl->no_cmd_complete) {  			/*  			 * After 1 sec and CMD_COMPLETED still not set, just @@ -194,37 +170,28 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)  			ctrl_dbg(ctrl, "CMD_COMPLETED not clear after 1 sec\n");  		} else if (!NO_CMD_CMPL(ctrl)) {  			/* -			 * This controller semms to notify of command completed +			 * This controller seems to notify of command completed  			 * event even though it supports none of power  			 * controller, attention led, power led and EMI.  			 */ -			ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to " -				 "wait for command completed event.\n"); +			ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Need to wait for command completed event\n");  			ctrl->no_cmd_complete = 0;  		} else { -			ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe " -				 "the controller is broken.\n"); +			ctrl_dbg(ctrl, "Unexpected CMD_COMPLETED. Maybe the controller is broken\n");  		}  	} -	retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); -		goto out; -	} - +	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);  	slot_ctrl &= ~mask;  	slot_ctrl |= (cmd & mask);  	ctrl->cmd_busy = 1;  	smp_mb(); -	retval = pciehp_writew(ctrl, PCI_EXP_SLTCTL, slot_ctrl); -	if (retval) -		ctrl_err(ctrl, "Cannot write to SLOTCTRL register\n"); +	pcie_capability_write_word(pdev, PCI_EXP_SLTCTL, slot_ctrl);  	/*  	 * Wait for command completion.  	 */ -	if (!retval && !ctrl->no_cmd_complete) { +	if (!ctrl->no_cmd_complete) {  		int poll = 0;  		/*  		 * if hotplug interrupt is not enabled or command @@ -234,21 +201,18 @@ static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)  		if (!(slot_ctrl & PCI_EXP_SLTCTL_HPIE) ||  		    !(slot_ctrl & PCI_EXP_SLTCTL_CCIE))  			poll = 1; -                pcie_wait_cmd(ctrl, poll); +		pcie_wait_cmd(ctrl, poll);  	} - out:  	mutex_unlock(&ctrl->ctrl_lock); -	return retval;  } -static bool check_link_active(struct controller *ctrl) +bool pciehp_check_link_active(struct controller *ctrl)  { -	bool ret = false; +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 lnk_status; +	bool ret; -	if (pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status)) -		return ret; - +	pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);  	ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);  	if (ret) @@ -261,12 +225,12 @@ static void __pcie_wait_link_active(struct controller *ctrl, bool active)  {  	int timeout = 1000; -	if (check_link_active(ctrl) == active) +	if (pciehp_check_link_active(ctrl) == active)  		return;  	while (timeout > 0) {  		msleep(10);  		timeout -= 10; -		if (check_link_active(ctrl) == active) +		if (pciehp_check_link_active(ctrl) == active)  			return;  	}  	ctrl_dbg(ctrl, "Data Link Layer Link Active not %s in 1000 msec\n", @@ -278,11 +242,6 @@ static void pcie_wait_link_active(struct controller *ctrl)  	__pcie_wait_link_active(ctrl, true);  } -static void pcie_wait_link_not_active(struct controller *ctrl) -{ -	__pcie_wait_link_active(ctrl, false); -} -  static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)  {  	u32 l; @@ -311,71 +270,56 @@ static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)  int pciehp_check_link_status(struct controller *ctrl)  { +	struct pci_dev *pdev = ctrl_dev(ctrl); +	bool found;  	u16 lnk_status; -	int retval = 0; -	bool found = false; -        /* -         * Data Link Layer Link Active Reporting must be capable for -         * hot-plug capable downstream port. But old controller might -         * not implement it. In this case, we wait for 1000 ms. -         */ -        if (ctrl->link_active_reporting) -                pcie_wait_link_active(ctrl); -        else -                msleep(1000); +	/* +	 * Data Link Layer Link Active Reporting must be capable for +	 * hot-plug capable downstream port. But old controller might +	 * not implement it. In this case, we wait for 1000 ms. +	*/ +	if (ctrl->link_active_reporting) +		pcie_wait_link_active(ctrl); +	else +		msleep(1000);  	/* wait 100ms before read pci conf, and try in 1s */  	msleep(100);  	found = pci_bus_check_dev(ctrl->pcie->port->subordinate,  					PCI_DEVFN(0, 0)); -	retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status); -	if (retval) { -		ctrl_err(ctrl, "Cannot read LNKSTATUS register\n"); -		return retval; -	} - +	pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);  	ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);  	if ((lnk_status & PCI_EXP_LNKSTA_LT) ||  	    !(lnk_status & PCI_EXP_LNKSTA_NLW)) { -		ctrl_err(ctrl, "Link Training Error occurs \n"); -		retval = -1; -		return retval; +		ctrl_err(ctrl, "Link Training Error occurs\n"); +		return -1;  	}  	pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status); -	if (!found && !retval) -		retval = -1; +	if (!found) +		return -1; -	return retval; +	return 0;  }  static int __pciehp_link_set(struct controller *ctrl, bool enable)  { +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 lnk_ctrl; -	int retval = 0; -	retval = pciehp_readw(ctrl, PCI_EXP_LNKCTL, &lnk_ctrl); -	if (retval) { -		ctrl_err(ctrl, "Cannot read LNKCTRL register\n"); -		return retval; -	} +	pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnk_ctrl);  	if (enable)  		lnk_ctrl &= ~PCI_EXP_LNKCTL_LD;  	else  		lnk_ctrl |= PCI_EXP_LNKCTL_LD; -	retval = pciehp_writew(ctrl, PCI_EXP_LNKCTL, lnk_ctrl); -	if (retval) { -		ctrl_err(ctrl, "Cannot write LNKCTRL register\n"); -		return retval; -	} +	pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnk_ctrl);  	ctrl_dbg(ctrl, "%s: lnk_ctrl = %x\n", __func__, lnk_ctrl); - -	return retval; +	return 0;  }  static int pciehp_link_enable(struct controller *ctrl) @@ -383,228 +327,165 @@ static int pciehp_link_enable(struct controller *ctrl)  	return __pciehp_link_set(ctrl, true);  } -static int pciehp_link_disable(struct controller *ctrl) -{ -	return __pciehp_link_set(ctrl, false); -} - -int pciehp_get_attention_status(struct slot *slot, u8 *status) +void pciehp_get_attention_status(struct slot *slot, u8 *status)  {  	struct controller *ctrl = slot->ctrl; +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 slot_ctrl; -	u8 atten_led_state; -	int retval = 0; - -	retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); -		return retval; -	} +	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__,  		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); -	atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6; - -	switch (atten_led_state) { -	case 0: -		*status = 0xFF;	/* Reserved */ -		break; -	case 1: +	switch (slot_ctrl & PCI_EXP_SLTCTL_AIC) { +	case PCI_EXP_SLTCTL_ATTN_IND_ON:  		*status = 1;	/* On */  		break; -	case 2: +	case PCI_EXP_SLTCTL_ATTN_IND_BLINK:  		*status = 2;	/* Blink */  		break; -	case 3: +	case PCI_EXP_SLTCTL_ATTN_IND_OFF:  		*status = 0;	/* Off */  		break;  	default:  		*status = 0xFF;  		break;  	} - -	return 0;  } -int pciehp_get_power_status(struct slot *slot, u8 *status) +void pciehp_get_power_status(struct slot *slot, u8 *status)  {  	struct controller *ctrl = slot->ctrl; +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 slot_ctrl; -	u8 pwr_state; -	int	retval = 0; -	retval = pciehp_readw(ctrl, PCI_EXP_SLTCTL, &slot_ctrl); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__); -		return retval; -	} +	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, &slot_ctrl);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__,  		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl); -	pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10; - -	switch (pwr_state) { -	case 0: -		*status = 1; +	switch (slot_ctrl & PCI_EXP_SLTCTL_PCC) { +	case PCI_EXP_SLTCTL_PWR_ON: +		*status = 1;	/* On */  		break; -	case 1: -		*status = 0; +	case PCI_EXP_SLTCTL_PWR_OFF: +		*status = 0;	/* Off */  		break;  	default:  		*status = 0xFF;  		break;  	} - -	return retval;  } -int pciehp_get_latch_status(struct slot *slot, u8 *status) +void pciehp_get_latch_status(struct slot *slot, u8 *status)  { -	struct controller *ctrl = slot->ctrl; +	struct pci_dev *pdev = ctrl_dev(slot->ctrl);  	u16 slot_status; -	int retval; -	retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", -			 __func__); -		return retval; -	} +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);  	*status = !!(slot_status & PCI_EXP_SLTSTA_MRLSS); -	return 0;  } -int pciehp_get_adapter_status(struct slot *slot, u8 *status) +void pciehp_get_adapter_status(struct slot *slot, u8 *status)  { -	struct controller *ctrl = slot->ctrl; +	struct pci_dev *pdev = ctrl_dev(slot->ctrl);  	u16 slot_status; -	int retval; -	retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", -			 __func__); -		return retval; -	} +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);  	*status = !!(slot_status & PCI_EXP_SLTSTA_PDS); -	return 0;  }  int pciehp_query_power_fault(struct slot *slot)  { -	struct controller *ctrl = slot->ctrl; +	struct pci_dev *pdev = ctrl_dev(slot->ctrl);  	u16 slot_status; -	int retval; -	retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -	if (retval) { -		ctrl_err(ctrl, "Cannot check for power fault\n"); -		return retval; -	} +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status);  	return !!(slot_status & PCI_EXP_SLTSTA_PFD);  } -int pciehp_set_attention_status(struct slot *slot, u8 value) +void pciehp_set_attention_status(struct slot *slot, u8 value)  {  	struct controller *ctrl = slot->ctrl;  	u16 slot_cmd; -	u16 cmd_mask; -	cmd_mask = PCI_EXP_SLTCTL_AIC; +	if (!ATTN_LED(ctrl)) +		return; +  	switch (value) { -	case 0 :	/* turn off */ -		slot_cmd = 0x00C0; +	case 0:		/* turn off */ +		slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_OFF;  		break;  	case 1:		/* turn on */ -		slot_cmd = 0x0040; +		slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_ON;  		break;  	case 2:		/* turn blink */ -		slot_cmd = 0x0080; +		slot_cmd = PCI_EXP_SLTCTL_ATTN_IND_BLINK;  		break;  	default: -		return -EINVAL; +		return;  	}  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,  		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); -	return pcie_write_cmd(ctrl, slot_cmd, cmd_mask); +	pcie_write_cmd(ctrl, slot_cmd, PCI_EXP_SLTCTL_AIC);  }  void pciehp_green_led_on(struct slot *slot)  {  	struct controller *ctrl = slot->ctrl; -	u16 slot_cmd; -	u16 cmd_mask; -	slot_cmd = 0x0100; -	cmd_mask = PCI_EXP_SLTCTL_PIC; -	pcie_write_cmd(ctrl, slot_cmd, cmd_mask); +	if (!PWR_LED(ctrl)) +		return; + +	pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_ON, PCI_EXP_SLTCTL_PIC);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, -		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); +		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, +		 PCI_EXP_SLTCTL_PWR_IND_ON);  }  void pciehp_green_led_off(struct slot *slot)  {  	struct controller *ctrl = slot->ctrl; -	u16 slot_cmd; -	u16 cmd_mask; -	slot_cmd = 0x0300; -	cmd_mask = PCI_EXP_SLTCTL_PIC; -	pcie_write_cmd(ctrl, slot_cmd, cmd_mask); +	if (!PWR_LED(ctrl)) +		return; + +	pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_OFF, PCI_EXP_SLTCTL_PIC);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, -		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); +		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, +		 PCI_EXP_SLTCTL_PWR_IND_OFF);  }  void pciehp_green_led_blink(struct slot *slot)  {  	struct controller *ctrl = slot->ctrl; -	u16 slot_cmd; -	u16 cmd_mask; -	slot_cmd = 0x0200; -	cmd_mask = PCI_EXP_SLTCTL_PIC; -	pcie_write_cmd(ctrl, slot_cmd, cmd_mask); +	if (!PWR_LED(ctrl)) +		return; + +	pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_IND_BLINK, PCI_EXP_SLTCTL_PIC);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, -		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); +		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, +		 PCI_EXP_SLTCTL_PWR_IND_BLINK);  } -int pciehp_power_on_slot(struct slot * slot) +int pciehp_power_on_slot(struct slot *slot)  {  	struct controller *ctrl = slot->ctrl; -	u16 slot_cmd; -	u16 cmd_mask; +	struct pci_dev *pdev = ctrl_dev(ctrl);  	u16 slot_status; -	int retval = 0; +	int retval;  	/* Clear sticky power-fault bit from previous power failures */ -	retval = pciehp_readw(ctrl, PCI_EXP_SLTSTA, &slot_status); -	if (retval) { -		ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS register\n", -			 __func__); -		return retval; -	} -	slot_status &= PCI_EXP_SLTSTA_PFD; -	if (slot_status) { -		retval = pciehp_writew(ctrl, PCI_EXP_SLTSTA, slot_status); -		if (retval) { -			ctrl_err(ctrl, -				 "%s: Cannot write to SLOTSTATUS register\n", -				 __func__); -			return retval; -		} -	} +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &slot_status); +	if (slot_status & PCI_EXP_SLTSTA_PFD) +		pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, +					   PCI_EXP_SLTSTA_PFD);  	ctrl->power_fault_detected = 0; -	slot_cmd = POWER_ON; -	cmd_mask = PCI_EXP_SLTCTL_PCC; -	retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); -	if (retval) { -		ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd); -		return retval; -	} +	pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_ON, PCI_EXP_SLTCTL_PCC);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, -		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); +		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, +		 PCI_EXP_SLTCTL_PWR_ON);  	retval = pciehp_link_enable(ctrl);  	if (retval) @@ -613,36 +494,20 @@ int pciehp_power_on_slot(struct slot * slot)  	return retval;  } -int pciehp_power_off_slot(struct slot * slot) +void pciehp_power_off_slot(struct slot *slot)  {  	struct controller *ctrl = slot->ctrl; -	u16 slot_cmd; -	u16 cmd_mask; -	int retval; -	/* Disable the link at first */ -	pciehp_link_disable(ctrl); -	/* wait the link is down */ -	if (ctrl->link_active_reporting) -		pcie_wait_link_not_active(ctrl); -	else -		msleep(1000); - -	slot_cmd = POWER_OFF; -	cmd_mask = PCI_EXP_SLTCTL_PCC; -	retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask); -	if (retval) { -		ctrl_err(ctrl, "Write command failed!\n"); -		return retval; -	} +	pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PWR_OFF, PCI_EXP_SLTCTL_PCC);  	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__, -		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd); -	return 0; +		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, +		 PCI_EXP_SLTCTL_PWR_OFF);  }  static irqreturn_t pcie_isr(int irq, void *dev_id)  {  	struct controller *ctrl = (struct controller *)dev_id; +	struct pci_dev *pdev = ctrl_dev(ctrl);  	struct slot *slot = ctrl->slot;  	u16 detected, intr_loc; @@ -653,24 +518,18 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)  	 */  	intr_loc = 0;  	do { -		if (pciehp_readw(ctrl, PCI_EXP_SLTSTA, &detected)) { -			ctrl_err(ctrl, "%s: Cannot read SLOTSTATUS\n", -				 __func__); -			return IRQ_NONE; -		} +		pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, &detected);  		detected &= (PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD |  			     PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | -			     PCI_EXP_SLTSTA_CC); +			     PCI_EXP_SLTSTA_CC | PCI_EXP_SLTSTA_DLLSC);  		detected &= ~intr_loc;  		intr_loc |= detected;  		if (!intr_loc)  			return IRQ_NONE; -		if (detected && pciehp_writew(ctrl, PCI_EXP_SLTSTA, intr_loc)) { -			ctrl_err(ctrl, "%s: Cannot write to SLOTSTATUS\n", -				 __func__); -			return IRQ_NONE; -		} +		if (detected) +			pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, +						   intr_loc);  	} while (detected);  	ctrl_dbg(ctrl, "%s: intr_loc %x\n", __func__, intr_loc); @@ -702,10 +561,14 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)  		ctrl->power_fault_detected = 1;  		pciehp_handle_power_fault(slot);  	} + +	if (intr_loc & PCI_EXP_SLTSTA_DLLSC) +		pciehp_handle_linkstate_change(slot); +  	return IRQ_HANDLED;  } -int pcie_enable_notification(struct controller *ctrl) +void pcie_enable_notification(struct controller *ctrl)  {  	u16 cmd, mask; @@ -719,9 +582,17 @@ int pcie_enable_notification(struct controller *ctrl)  	 * when it is cleared in the interrupt service routine, and  	 * next power fault detected interrupt was notified again.  	 */ -	cmd = PCI_EXP_SLTCTL_PDCE; + +	/* +	 * Always enable link events: thus link-up and link-down shall +	 * always be treated as hotplug and unplug respectively. Enable +	 * presence detect only if Attention Button is not present. +	 */ +	cmd = PCI_EXP_SLTCTL_DLLSCE;  	if (ATTN_BUTTN(ctrl))  		cmd |= PCI_EXP_SLTCTL_ABPE; +	else +		cmd |= PCI_EXP_SLTCTL_PDCE;  	if (MRL_SENS(ctrl))  		cmd |= PCI_EXP_SLTCTL_MRLSCE;  	if (!pciehp_poll_mode) @@ -729,53 +600,57 @@ int pcie_enable_notification(struct controller *ctrl)  	mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |  		PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE | -		PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE); +		PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE | +		PCI_EXP_SLTCTL_DLLSCE); -	if (pcie_write_cmd(ctrl, cmd, mask)) { -		ctrl_err(ctrl, "Cannot enable software notification\n"); -		return -1; -	} -	return 0; +	pcie_write_cmd(ctrl, cmd, mask);  }  static void pcie_disable_notification(struct controller *ctrl)  {  	u16 mask; +  	mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |  		PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |  		PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |  		PCI_EXP_SLTCTL_DLLSCE); -	if (pcie_write_cmd(ctrl, 0, mask)) -		ctrl_warn(ctrl, "Cannot disable software notification\n"); +	pcie_write_cmd(ctrl, 0, mask);  }  /*   * pciehp has a 1:1 bus:slot relationship so we ultimately want a secondary - * bus reset of the bridge, but if the slot supports surprise removal we need - * to disable presence detection around the bus reset and clear any spurious + * bus reset of the bridge, but at the same time we want to ensure that it is + * not seen as a hot-unplug, followed by the hot-plug of the device. Thus, + * disable link state notification and presence detection change notification + * momentarily, if we see that they could interfere. Also, clear any spurious   * events after.   */  int pciehp_reset_slot(struct slot *slot, int probe)  {  	struct controller *ctrl = slot->ctrl; +	struct pci_dev *pdev = ctrl_dev(ctrl); +	u16 stat_mask = 0, ctrl_mask = 0;  	if (probe)  		return 0; -	if (HP_SUPR_RM(ctrl)) { -		pcie_write_cmd(ctrl, 0, PCI_EXP_SLTCTL_PDCE); -		if (pciehp_poll_mode) -			del_timer_sync(&ctrl->poll_timer); +	if (!ATTN_BUTTN(ctrl)) { +		ctrl_mask |= PCI_EXP_SLTCTL_PDCE; +		stat_mask |= PCI_EXP_SLTSTA_PDC;  	} +	ctrl_mask |= PCI_EXP_SLTCTL_DLLSCE; +	stat_mask |= PCI_EXP_SLTSTA_DLLSC; + +	pcie_write_cmd(ctrl, 0, ctrl_mask); +	if (pciehp_poll_mode) +		del_timer_sync(&ctrl->poll_timer);  	pci_reset_bridge_secondary_bus(ctrl->pcie->port); -	if (HP_SUPR_RM(ctrl)) { -		pciehp_writew(ctrl, PCI_EXP_SLTSTA, PCI_EXP_SLTSTA_PDC); -		pcie_write_cmd(ctrl, PCI_EXP_SLTCTL_PDCE, PCI_EXP_SLTCTL_PDCE); -		if (pciehp_poll_mode) -			int_poll_timeout(ctrl->poll_timer.data); -	} +	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, stat_mask); +	pcie_write_cmd(ctrl, ctrl_mask, ctrl_mask); +	if (pciehp_poll_mode) +		int_poll_timeout(ctrl->poll_timer.data);  	return 0;  } @@ -784,10 +659,7 @@ int pcie_init_notification(struct controller *ctrl)  {  	if (pciehp_request_irq(ctrl))  		return -1; -	if (pcie_enable_notification(ctrl)) { -		pciehp_free_irq(ctrl); -		return -1; -	} +	pcie_enable_notification(ctrl);  	ctrl->notification_enabled = 1;  	return 0;  } @@ -815,6 +687,7 @@ static int pcie_init_slot(struct controller *ctrl)  	slot->ctrl = ctrl;  	mutex_init(&slot->lock); +	mutex_init(&slot->hotplug_lock);  	INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);  	ctrl->slot = slot;  	return 0; @@ -875,12 +748,14 @@ static inline void dbg_ctrl(struct controller *ctrl)  		  EMI(ctrl)        ? "yes" : "no");  	ctrl_info(ctrl, "  Command Completed    : %3s\n",  		  NO_CMD_CMPL(ctrl) ? "no" : "yes"); -	pciehp_readw(ctrl, PCI_EXP_SLTSTA, ®16); +	pcie_capability_read_word(pdev, PCI_EXP_SLTSTA, ®16);  	ctrl_info(ctrl, "Slot Status            : 0x%04x\n", reg16); -	pciehp_readw(ctrl, PCI_EXP_SLTCTL, ®16); +	pcie_capability_read_word(pdev, PCI_EXP_SLTCTL, ®16);  	ctrl_info(ctrl, "Slot Control           : 0x%04x\n", reg16);  } +#define FLAG(x, y)	(((x) & (y)) ? '+' : '-') +  struct controller *pcie_init(struct pcie_device *dev)  {  	struct controller *ctrl; @@ -893,11 +768,7 @@ struct controller *pcie_init(struct pcie_device *dev)  		goto abort;  	}  	ctrl->pcie = dev; -	if (pciehp_readl(ctrl, PCI_EXP_SLTCAP, &slot_cap)) { -		ctrl_err(ctrl, "Cannot read SLOTCAP register\n"); -		goto abort_ctrl; -	} - +	pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);  	ctrl->slot_cap = slot_cap;  	mutex_init(&ctrl->ctrl_lock);  	init_waitqueue_head(&ctrl->queue); @@ -910,28 +781,34 @@ struct controller *pcie_init(struct pcie_device *dev)  	 */  	if (NO_CMD_CMPL(ctrl) ||  	    !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) -	    ctrl->no_cmd_complete = 1; - -        /* Check if Data Link Layer Link Active Reporting is implemented */ -        if (pciehp_readl(ctrl, PCI_EXP_LNKCAP, &link_cap)) { -                ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__); -                goto abort_ctrl; -        } -        if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { -                ctrl_dbg(ctrl, "Link Active Reporting supported\n"); -                ctrl->link_active_reporting = 1; -        } +		ctrl->no_cmd_complete = 1; + +	/* Check if Data Link Layer Link Active Reporting is implemented */ +	pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, &link_cap); +	if (link_cap & PCI_EXP_LNKCAP_DLLLARC) { +		ctrl_dbg(ctrl, "Link Active Reporting supported\n"); +		ctrl->link_active_reporting = 1; +	}  	/* Clear all remaining event bits in Slot Status register */ -	if (pciehp_writew(ctrl, PCI_EXP_SLTSTA, 0x1f)) -		goto abort_ctrl; +	pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, +		PCI_EXP_SLTSTA_ABP | PCI_EXP_SLTSTA_PFD | +		PCI_EXP_SLTSTA_MRLSC | PCI_EXP_SLTSTA_PDC | +		PCI_EXP_SLTSTA_CC); -	/* Disable sotfware notification */ +	/* Disable software notification */  	pcie_disable_notification(ctrl); -	ctrl_info(ctrl, "HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", -		  pdev->vendor, pdev->device, pdev->subsystem_vendor, -		  pdev->subsystem_device); +	ctrl_info(ctrl, "Slot #%d AttnBtn%c AttnInd%c PwrInd%c PwrCtrl%c MRL%c Interlock%c NoCompl%c LLActRep%c\n", +		(slot_cap & PCI_EXP_SLTCAP_PSN) >> 19, +		FLAG(slot_cap, PCI_EXP_SLTCAP_ABP), +		FLAG(slot_cap, PCI_EXP_SLTCAP_AIP), +		FLAG(slot_cap, PCI_EXP_SLTCAP_PIP), +		FLAG(slot_cap, PCI_EXP_SLTCAP_PCP), +		FLAG(slot_cap, PCI_EXP_SLTCAP_MRLSP), +		FLAG(slot_cap, PCI_EXP_SLTCAP_EIP), +		FLAG(slot_cap, PCI_EXP_SLTCAP_NCCS), +		FLAG(link_cap, PCI_EXP_LNKCAP_DLLLARC));  	if (pcie_init_slot(ctrl))  		goto abort_ctrl; diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 0e0d0f7f63f..5f871f4c4af 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -39,27 +39,29 @@ int pciehp_configure_device(struct slot *p_slot)  	struct pci_dev *dev;  	struct pci_dev *bridge = p_slot->ctrl->pcie->port;  	struct pci_bus *parent = bridge->subordinate; -	int num; +	int num, ret = 0;  	struct controller *ctrl = p_slot->ctrl; +	pci_lock_rescan_remove(); +  	dev = pci_get_slot(parent, PCI_DEVFN(0, 0));  	if (dev) { -		ctrl_err(ctrl, "Device %s already exists " -			 "at %04x:%02x:00, cannot hot-add\n", pci_name(dev), -			 pci_domain_nr(parent), parent->number); +		ctrl_err(ctrl, "Device %s already exists at %04x:%02x:00, cannot hot-add\n", +			 pci_name(dev), pci_domain_nr(parent), parent->number);  		pci_dev_put(dev); -		return -EINVAL; +		ret = -EEXIST; +		goto out;  	}  	num = pci_scan_slot(parent, PCI_DEVFN(0, 0));  	if (num == 0) {  		ctrl_err(ctrl, "No new device found\n"); -		return -ENODEV; +		ret = -ENODEV; +		goto out;  	}  	list_for_each_entry(dev, &parent->devices, bus_list) -		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || -				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) +		if (pci_is_bridge(dev))  			pci_hp_add_bridge(dev);  	pci_assign_unassigned_bridge_resources(bridge); @@ -73,12 +75,14 @@ int pciehp_configure_device(struct slot *p_slot)  	pci_bus_add_devices(parent); -	return 0; + out: +	pci_unlock_rescan_remove(); +	return ret;  }  int pciehp_unconfigure_device(struct slot *p_slot)  { -	int ret, rc = 0; +	int rc = 0;  	u8 bctl = 0;  	u8 presence = 0;  	struct pci_dev *dev, *temp; @@ -88,9 +92,9 @@ int pciehp_unconfigure_device(struct slot *p_slot)  	ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:00\n",  		 __func__, pci_domain_nr(parent), parent->number); -	ret = pciehp_get_adapter_status(p_slot, &presence); -	if (ret) -		presence = 0; +	pciehp_get_adapter_status(p_slot, &presence); + +	pci_lock_rescan_remove();  	/*  	 * Stopping an SR-IOV PF device removes all the associated VFs, @@ -126,5 +130,6 @@ int pciehp_unconfigure_device(struct slot *p_slot)  		pci_dev_put(dev);  	} +	pci_unlock_rescan_remove();  	return rc;  } diff --git a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c index 1f00b937f72..d062c008fc9 100644 --- a/drivers/pci/hotplug/pcihp_skeleton.c +++ b/drivers/pci/hotplug/pcihp_skeleton.c @@ -51,8 +51,8 @@ static LIST_HEAD(slot_list);  #define dbg(format, arg...)					\  	do {							\  		if (debug)					\ -			printk (KERN_DEBUG "%s: " format "\n",	\ -				MY_NAME , ## arg); 		\ +			printk(KERN_DEBUG "%s: " format "\n",	\ +				MY_NAME , ## arg);		\  	} while (0)  #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)  #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg) @@ -128,18 +128,18 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)  	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);  	switch (status) { -		case 0: -			/* -			 * Fill in code here to turn light off -			 */ -			break; - -		case 1: -		default: -			/* -			 * Fill in code here to turn light on -			 */ -			break; +	case 0: +		/* +		 * Fill in code here to turn light off +		 */ +		break; + +	case 1: +	default: +		/* +		 * Fill in code here to turn light on +		 */ +		break;  	}  	return retval; @@ -153,12 +153,12 @@ static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)  	dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);  	switch (value) { -		case 0: -			/* Specify a test here */ -			break; -		case 1: -			/* Specify another test here */ -			break; +	case 0: +		/* Specify a test here */ +		break; +	case 1: +		/* Specify another test here */ +		break;  	}  	return retval; @@ -287,7 +287,7 @@ static int __init init_slots(void)  		hotplug_slot->release = &release_slot;  		make_slot_name(slot);  		hotplug_slot->ops = &skel_hotplug_slot_ops; -		 +  		/*  		 * Initialize the slot info structure with some known  		 * good values. @@ -296,7 +296,7 @@ static int __init init_slots(void)  		get_attention_status(hotplug_slot, &info->attention_status);  		get_latch_status(hotplug_slot, &info->latch_status);  		get_adapter_status(hotplug_slot, &info->adapter_status); -		 +  		dbg("registering slot %d\n", i);  		retval = pci_hp_register(slot->hotplug_slot);  		if (retval) { @@ -336,7 +336,7 @@ static void __exit cleanup_slots(void)  		pci_hp_deregister(slot->hotplug_slot);  	}  } -		 +  static int __init pcihp_skel_init(void)  {  	int retval; diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c index 16f92035231..e246a10a0d2 100644 --- a/drivers/pci/hotplug/pcihp_slot.c +++ b/drivers/pci/hotplug/pcihp_slot.c @@ -160,8 +160,7 @@ void pci_configure_slot(struct pci_dev *dev)  			(dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))  		return; -	if (dev->bus) -		pcie_bus_configure_settings(dev->bus); +	pcie_bus_configure_settings(dev->bus);  	memset(&hpp, 0, sizeof(hpp));  	ret = pci_get_hp_params(dev, &hpp); diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index bb7af78e4ee..7660232ef46 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -157,8 +157,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)  	}  	/* Scan below the new bridge */ -	if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || -	    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) +	if (pci_is_bridge(dev))  		of_scan_pci_bridge(dev);  	/* Map IO space for child bus, which may or may not succeed */ @@ -217,7 +216,7 @@ static int dlpar_remove_phb(char *drc_name, struct device_node *dn)  	if (!pcibios_find_pci_bus(dn))  		return -EINVAL; -	/* If pci slot is hotplugable, use hotplug to remove it */ +	/* If pci slot is hotpluggable, use hotplug to remove it */  	slot = find_php_slot(dn);  	if (slot && rpaphp_deregister_slot(slot)) {  		printk(KERN_ERR "%s: unable to remove hotplug slot %s\n", @@ -354,10 +353,15 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  {  	struct pci_bus *bus;  	struct slot *slot; +	int ret = 0; + +	pci_lock_rescan_remove();  	bus = pcibios_find_pci_bus(dn); -	if (!bus) -		return -EINVAL; +	if (!bus) { +		ret = -EINVAL; +		goto out; +	}  	pr_debug("PCI: Removing PCI slot below EADS bridge %s\n",  		 bus->self ? pci_name(bus->self) : "<!PHB!>"); @@ -371,7 +375,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  			printk(KERN_ERR  				"%s: unable to remove hotplug slot %s\n",  				__func__, drc_name); -			return -EIO; +			ret = -EIO; +			goto out;  		}  	} @@ -382,7 +387,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  	if (pcibios_unmap_io_space(bus)) {  		printk(KERN_ERR "%s: failed to unmap bus range\n",  			__func__); -		return -ERANGE; +		ret = -ERANGE; +		goto out;  	}  	/* Remove the EADS bridge device itself */ @@ -390,7 +396,9 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)  	pr_debug("PCI: Now removing bridge device %s\n", pci_name(bus->self));  	pci_stop_and_remove_bus_device(bus->self); -	return 0; + out: +	pci_unlock_rescan_remove(); +	return ret;  }  /** diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index 3135856e5e1..b2593e876a0 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -49,9 +49,9 @@  extern bool rpaphp_debug;  #define dbg(format, arg...)					\  	do {							\ -		if (rpaphp_debug)					\ +		if (rpaphp_debug)				\  			printk(KERN_DEBUG "%s: " format,	\ -				MY_NAME , ## arg); 		\ +				MY_NAME , ## arg);		\  	} while (0)  #define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg)  #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) @@ -99,5 +99,5 @@ void dealloc_slot_struct(struct slot *slot);  struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);  int rpaphp_register_slot(struct slot *slot);  int rpaphp_deregister_slot(struct slot *slot); -	 +  #endif				/* _PPC64PHP_H */ diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 127d6e60018..93aa29f6d39 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -39,6 +39,7 @@  bool rpaphp_debug;  LIST_HEAD(rpaphp_slot_head); +EXPORT_SYMBOL_GPL(rpaphp_slot_head);  #define DRIVER_VERSION	"0.1"  #define DRIVER_AUTHOR	"Linda Xie <lxie@us.ibm.com>" @@ -88,7 +89,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)   * @hotplug_slot: slot to get status   * @value: pointer to store status   */ -static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	int retval, level;  	struct slot *slot = (struct slot *)hotplug_slot->private; @@ -104,14 +105,14 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)   * @hotplug_slot: slot to get status   * @value: pointer to store status   */ -static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = (struct slot *)hotplug_slot->private;  	*value = slot->hotplug_slot->info->attention_status;  	return 0;  } -static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value) +static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)  {  	struct slot *slot = (struct slot *)hotplug_slot->private;  	int rc, state; @@ -223,16 +224,16 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,  	type_tmp = (char *) &types[1];  	/* Iterate through parent properties, looking for my-drc-index */ -	for (i = 0; i < indexes[0]; i++) { +	for (i = 0; i < be32_to_cpu(indexes[0]); i++) {  		if ((unsigned int) indexes[i + 1] == *my_index) {  			if (drc_name) -                		*drc_name = name_tmp; +				*drc_name = name_tmp;  			if (drc_type)  				*drc_type = type_tmp;  			if (drc_index) -				*drc_index = *my_index; +				*drc_index = be32_to_cpu(*my_index);  			if (drc_power_domain) -				*drc_power_domain = domains[i+1]; +				*drc_power_domain = be32_to_cpu(domains[i+1]);  			return 0;  		}  		name_tmp += (strlen(name_tmp) + 1); @@ -241,6 +242,7 @@ int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,  	return -EINVAL;  } +EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);  static int is_php_type(char *drc_type)  { @@ -289,7 +291,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes,   * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.   * @dn: device node of slot   * - * This subroutine will register a hotplugable slot with the + * This subroutine will register a hotpluggable slot with the   * PCI hotplug infrastructure. This routine is typically called   * during boot time, if the hotplug slots are present at boot time,   * or is called later, by the dlpar add code, if the slot is @@ -321,16 +323,19 @@ int rpaphp_add_slot(struct device_node *dn)  	/* register PCI devices */  	name = (char *) &names[1];  	type = (char *) &types[1]; -	for (i = 0; i < indexes[0]; i++) { +	for (i = 0; i < be32_to_cpu(indexes[0]); i++) { +		int index; -		slot = alloc_slot_struct(dn, indexes[i + 1], name, power_domains[i + 1]); +		index = be32_to_cpu(indexes[i + 1]); +		slot = alloc_slot_struct(dn, index, name, +					 be32_to_cpu(power_domains[i + 1]));  		if (!slot)  			return -ENOMEM;  		slot->type = simple_strtoul(type, NULL, 10); -				 +  		dbg("Found drc-index:0x%x drc-name:%s drc-type:%s\n", -				indexes[i + 1], name, type); +				index, name, type);  		retval = rpaphp_enable_slot(slot);  		if (!retval) @@ -347,6 +352,7 @@ int rpaphp_add_slot(struct device_node *dn)  	/* XXX FIXME: reports a failure only if last entry in loop failed */  	return retval;  } +EXPORT_SYMBOL_GPL(rpaphp_add_slot);  static void __exit cleanup_slots(void)  { @@ -356,7 +362,7 @@ static void __exit cleanup_slots(void)  	/*  	 * Unregister all of our slots with the pci_hotplug subsystem,  	 * and free up all memory that we had allocated. -	 * memory will be freed in release_slot callback.  +	 * memory will be freed in release_slot callback.  	 */  	list_for_each_safe(tmp, n, &rpaphp_slot_head) { @@ -398,7 +404,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)  		return retval;  	if (state == PRESENT) { +		pci_lock_rescan_remove();  		pcibios_add_pci_devices(slot->bus); +		pci_unlock_rescan_remove();  		slot->state = CONFIGURED;  	} else if (state == EMPTY) {  		slot->state = EMPTY; @@ -418,7 +426,9 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)  	if (slot->state == NOT_CONFIGURED)  		return -EINVAL; +	pci_lock_rescan_remove();  	pcibios_remove_pci_devices(slot->bus); +	pci_unlock_rescan_remove();  	vm_unmap_aliases();  	slot->state = NOT_CONFIGURED; @@ -436,7 +446,3 @@ struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {  module_init(rpaphp_init);  module_exit(rpaphp_exit); - -EXPORT_SYMBOL_GPL(rpaphp_add_slot); -EXPORT_SYMBOL_GPL(rpaphp_slot_head); -EXPORT_SYMBOL_GPL(rpaphp_get_drc_props); diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c index 513e1e28239..9243f3e7a1c 100644 --- a/drivers/pci/hotplug/rpaphp_pci.c +++ b/drivers/pci/hotplug/rpaphp_pci.c @@ -44,7 +44,7 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)  			dbg("%s: slot must be power up to get sensor-state\n",  			    __func__); -			/* some slots have to be powered up  +			/* some slots have to be powered up  			 * before get-sensor will succeed.  			 */  			rc = rtas_set_power_level(slot->power_domain, POWER_ON, @@ -133,4 +133,3 @@ int rpaphp_enable_slot(struct slot *slot)  	return 0;  } - diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c index b283bbea6d2..a6082cc263f 100644 --- a/drivers/pci/hotplug/rpaphp_slot.c +++ b/drivers/pci/hotplug/rpaphp_slot.c @@ -1,5 +1,5 @@  /* - * RPA Virtual I/O device functions  + * RPA Virtual I/O device functions   * Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>   *   * All rights reserved. @@ -51,27 +51,27 @@ struct slot *alloc_slot_struct(struct device_node *dn,                         int drc_index, char *drc_name, int power_domain)  {  	struct slot *slot; -	 +  	slot = kzalloc(sizeof(struct slot), GFP_KERNEL);  	if (!slot)  		goto error_nomem;  	slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);  	if (!slot->hotplug_slot) -		goto error_slot;	 +		goto error_slot;  	slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),  					   GFP_KERNEL);  	if (!slot->hotplug_slot->info)  		goto error_hpslot;  	slot->name = kstrdup(drc_name, GFP_KERNEL);  	if (!slot->name) -		goto error_info;	 +		goto error_info;  	slot->dn = dn;  	slot->index = drc_index;  	slot->power_domain = power_domain;  	slot->hotplug_slot->private = slot;  	slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;  	slot->hotplug_slot->release = &rpaphp_release_slot; -	 +  	return (slot);  error_info: @@ -91,7 +91,7 @@ static int is_registered(struct slot *slot)  	list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {  		if (!strcmp(tmp_slot->name, slot->name))  			return 1; -	}	 +	}  	return 0;  } @@ -104,7 +104,7 @@ int rpaphp_deregister_slot(struct slot *slot)  		__func__, slot->name);  	list_del(&slot->rpaphp_slot_list); -	 +  	retval = pci_hp_deregister(php_slot);  	if (retval)  		err("Problem unregistering a slot %s\n", slot->name); @@ -120,7 +120,7 @@ int rpaphp_register_slot(struct slot *slot)  	int retval;  	int slotno; -	dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",  +	dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",  		__func__, slot->dn->full_name, slot->index, slot->name,  		slot->power_domain, slot->type); @@ -128,7 +128,7 @@ int rpaphp_register_slot(struct slot *slot)  	if (is_registered(slot)) {  		err("rpaphp_register_slot: slot[%s] is already registered\n", slot->name);  		return -EAGAIN; -	}	 +	}  	if (slot->dn->child)  		slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn); @@ -145,4 +145,3 @@ int rpaphp_register_slot(struct slot *slot)  	info("Slot [%s] registered\n", slot->name);  	return 0;  } - diff --git a/drivers/pci/hotplug/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c index 66e505ca24e..d1332d2f873 100644 --- a/drivers/pci/hotplug/s390_pci_hpc.c +++ b/drivers/pci/hotplug/s390_pci_hpc.c @@ -15,7 +15,6 @@  #include <linux/slab.h>  #include <linux/pci.h>  #include <linux/pci_hotplug.h> -#include <linux/init.h>  #include <asm/pci_debug.h>  #include <asm/sclp.h> @@ -80,7 +79,9 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)  		goto out_deconfigure;  	pci_scan_slot(slot->zdev->bus, ZPCI_DEVFN); +	pci_lock_rescan_remove();  	pci_bus_add_devices(slot->zdev->bus); +	pci_unlock_rescan_remove();  	return rc; @@ -98,7 +99,7 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)  		return -EIO;  	if (slot->zdev->pdev) -		pci_stop_and_remove_bus_device(slot->zdev->pdev); +		pci_stop_and_remove_bus_device_locked(slot->zdev->pdev);  	rc = zpci_disable_device(slot->zdev);  	if (rc) @@ -133,7 +134,6 @@ static void release_slot(struct hotplug_slot *hotplug_slot)  {  	struct slot *slot = hotplug_slot->private; -	pr_debug("%s - physical_slot = %s\n", __func__, hotplug_slot_name(hotplug_slot));  	kfree(slot->hotplug_slot->info);  	kfree(slot->hotplug_slot);  	kfree(slot); @@ -183,10 +183,9 @@ int zpci_init_slot(struct zpci_dev *zdev)  	snprintf(name, SLOT_NAME_SIZE, "%08x", zdev->fid);  	rc = pci_hp_register(slot->hotplug_slot, zdev->bus,  			     ZPCI_DEVFN, name); -	if (rc) { -		pr_err("pci_hp_register failed with error %d\n", rc); +	if (rc)  		goto error_reg; -	} +  	list_add(&slot->slot_list, &s390_hotplug_slot_list);  	return 0; diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index b2781dfe60e..bada2099987 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -9,6 +9,7 @@   * Work to add BIOS PROM support was completed by Mike Habeck.   */ +#include <linux/acpi.h>  #include <linux/init.h>  #include <linux/kernel.h>  #include <linux/module.h> @@ -29,7 +30,6 @@  #include <asm/sn/sn_feature_sets.h>  #include <asm/sn/sn_sal.h>  #include <asm/sn/types.h> -#include <linux/acpi.h>  #include <asm/sn/acpi.h>  #include "../pci.h" @@ -188,7 +188,7 @@ static int sn_hp_slot_private_alloc(struct hotplug_slot *bss_hotplug_slot,  	return 0;  } -static struct hotplug_slot * sn_hp_destroy(void) +static struct hotplug_slot *sn_hp_destroy(void)  {  	struct slot *slot;  	struct pci_slot *pci_slot; @@ -250,15 +250,13 @@ static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,  	}  	if (rc == PCI_L1_ERR) { -		dev_dbg(&slot->pci_bus->self->dev, -			"L1 failure %d with message: %s", +		dev_dbg(&slot->pci_bus->self->dev, "L1 failure %d with message: %s",  			resp.resp_sub_errno, resp.resp_l1_msg);  		return -EPERM;  	}  	if (rc) { -		dev_dbg(&slot->pci_bus->self->dev, -			"insert failed with error %d sub-error %d\n", +		dev_dbg(&slot->pci_bus->self->dev, "insert failed with error %d sub-error %d\n",  			rc, resp.resp_sub_errno);  		return -EIO;  	} @@ -288,21 +286,18 @@ static int sn_slot_disable(struct hotplug_slot *bss_hotplug_slot,  	}  	if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_EMPTY_33MHZ)) { -		dev_dbg(&slot->pci_bus->self->dev, -			"Cannot remove last 33MHz card\n"); +		dev_dbg(&slot->pci_bus->self->dev, "Cannot remove last 33MHz card\n");  		return -EPERM;  	}  	if ((action == PCI_REQ_SLOT_ELIGIBLE) && (rc == PCI_L1_ERR)) { -		dev_dbg(&slot->pci_bus->self->dev, -			"L1 failure %d with message \n%s\n", +		dev_dbg(&slot->pci_bus->self->dev, "L1 failure %d with message \n%s\n",  			resp.resp_sub_errno, resp.resp_l1_msg);  		return -EPERM;  	}  	if ((action == PCI_REQ_SLOT_ELIGIBLE) && rc) { -		dev_dbg(&slot->pci_bus->self->dev, -			"remove failed with error %d sub-error %d\n", +		dev_dbg(&slot->pci_bus->self->dev, "remove failed with error %d sub-error %d\n",  			rc, resp.resp_sub_errno);  		return -EIO;  	} @@ -414,11 +409,10 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)  		acpi_handle rethandle;  		acpi_status ret; -		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; +		phandle = acpi_device_handle(PCI_CONTROLLER(slot->pci_bus)->companion);  		if (acpi_bus_get_device(phandle, &pdevice)) { -			dev_dbg(&slot->pci_bus->self->dev, -				"no parent device, assuming NULL\n"); +			dev_dbg(&slot->pci_bus->self->dev, "no parent device, assuming NULL\n");  			pdevice = NULL;  		} @@ -447,10 +441,8 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)  				ret = acpi_bus_scan(chandle);  				if (ACPI_FAILURE(ret)) { -					printk(KERN_ERR "%s: acpi_bus_scan " -					       "failed (0x%x) for slot %d " -					       "func %d\n", __func__, -					       ret, (int)(adr>>16), +					printk(KERN_ERR "%s: acpi_bus_scan failed (0x%x) for slot %d func %d\n", +					       __func__, ret, (int)(adr>>16),  					       (int)(adr&0xffff));  					/* try to continue on */  				} @@ -459,20 +451,21 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)  		acpi_scan_lock_release();  	} +	pci_lock_rescan_remove(); +  	/* Call the driver for the new device */  	pci_bus_add_devices(slot->pci_bus);  	/* Call the drivers for the new devices subordinate to PPB */  	if (new_ppb)  		pci_bus_add_devices(new_bus); +	pci_unlock_rescan_remove();  	mutex_unlock(&sn_hotplug_mutex);  	if (rc == 0) -		dev_dbg(&slot->pci_bus->self->dev, -			"insert operation successful\n"); +		dev_dbg(&slot->pci_bus->self->dev, "insert operation successful\n");  	else -		dev_dbg(&slot->pci_bus->self->dev, -			"insert operation failed rc = %d\n", rc); +		dev_dbg(&slot->pci_bus->self->dev, "insert operation failed rc = %d\n", rc);  	return rc;  } @@ -495,7 +488,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)  	/* free the ACPI resources for the slot */  	if (SN_ACPI_BASE_SUPPORT() && -            PCI_CONTROLLER(slot->pci_bus)->acpi_handle) { +            PCI_CONTROLLER(slot->pci_bus)->companion) {  		unsigned long long adr;  		struct acpi_device *device;  		acpi_handle phandle; @@ -504,7 +497,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)  		acpi_status ret;  		/* Get the rootbus node pointer */ -		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle; +		phandle = acpi_device_handle(PCI_CONTROLLER(slot->pci_bus)->companion);  		acpi_scan_lock_acquire();  		/* @@ -540,6 +533,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)  		acpi_scan_lock_release();  	} +	pci_lock_rescan_remove();  	/* Free the SN resources assigned to the Linux device.*/  	list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {  		if (PCI_SLOT(dev->devfn) != slot->device_num + 1) @@ -550,14 +544,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)  		pci_stop_and_remove_bus_device(dev);  		pci_dev_put(dev);  	} +	pci_unlock_rescan_remove();  	/* Remove the SSDT for the slot from the ACPI namespace */  	if (SN_ACPI_BASE_SUPPORT() && ssdt_id) {  		acpi_status ret;  		ret = acpi_unload_table_id(ssdt_id);  		if (ACPI_FAILURE(ret)) { -			printk(KERN_ERR "%s: acpi_unload_table_id " -			       "failed (0x%x) for id %d\n", +			printk(KERN_ERR "%s: acpi_unload_table_id failed (0x%x) for id %d\n",  			       __func__, ret, ssdt_id);  			/* try to continue on */  		} diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index e260f207a90..5897d516427 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -180,7 +180,7 @@ int shpchp_configure_device(struct slot *p_slot);  int shpchp_unconfigure_device(struct slot *p_slot);  void cleanup_slots(struct controller *ctrl);  void shpchp_queue_pushbutton_work(struct work_struct *work); -int shpc_init( struct controller *ctrl, struct pci_dev *pdev); +int shpc_init(struct controller *ctrl, struct pci_dev *pdev);  static inline const char *slot_name(struct slot *slot)  { @@ -191,7 +191,7 @@ static inline const char *slot_name(struct slot *slot)  #include <linux/pci-acpi.h>  static inline int get_hp_hw_control_from_firmware(struct pci_dev *dev)  { -	u32 flags = OSC_SHPC_NATIVE_HP_CONTROL; +	u32 flags = OSC_PCI_SHPC_NATIVE_HP_CONTROL;  	return acpi_get_hp_hw_control_from_firmware(dev, flags);  }  #else @@ -216,13 +216,13 @@ struct ctrl_reg {  /* offsets to the controller registers based on the above structure layout */  enum ctrl_offsets { -	BASE_OFFSET 	 = offsetof(struct ctrl_reg, base_offset), -	SLOT_AVAIL1 	 = offsetof(struct ctrl_reg, slot_avail1), +	BASE_OFFSET	 = offsetof(struct ctrl_reg, base_offset), +	SLOT_AVAIL1	 = offsetof(struct ctrl_reg, slot_avail1),  	SLOT_AVAIL2	 = offsetof(struct ctrl_reg, slot_avail2), -	SLOT_CONFIG 	 = offsetof(struct ctrl_reg, slot_config), +	SLOT_CONFIG	 = offsetof(struct ctrl_reg, slot_config),  	SEC_BUS_CONFIG	 = offsetof(struct ctrl_reg, sec_bus_config),  	MSI_CTRL	 = offsetof(struct ctrl_reg, msi_ctrl), -	PROG_INTERFACE 	 = offsetof(struct ctrl_reg, prog_interface), +	PROG_INTERFACE	 = offsetof(struct ctrl_reg, prog_interface),  	CMD		 = offsetof(struct ctrl_reg, cmd),  	CMD_STATUS	 = offsetof(struct ctrl_reg, cmd_status),  	INTR_LOC	 = offsetof(struct ctrl_reg, intr_loc), @@ -295,7 +295,7 @@ static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)  		pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);  	}  	/* restore MiscII register */ -	pci_read_config_dword( p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp ); +	pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp );  	if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK)  		pcix_misc2_temp |= SERRFATALENABLE_MASK; diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index d3f757df691..294ef4b10cf 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -143,11 +143,10 @@ static int init_slots(struct controller *ctrl)  		snprintf(name, SLOT_NAME_SIZE, "%d", slot->number);  		hotplug_slot->ops = &shpchp_hotplug_slot_ops; - 		ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x " - 			 "hp_slot=%x sun=%x slot_device_offset=%x\n", - 			 pci_domain_nr(ctrl->pci_dev->subordinate), - 			 slot->bus, slot->device, slot->hp_slot, slot->number, - 			 ctrl->slot_device_offset); +		ctrl_dbg(ctrl, "Registering domain:bus:dev=%04x:%02x:%02x hp_slot=%x sun=%x slot_device_offset=%x\n", +			 pci_domain_nr(ctrl->pci_dev->subordinate), +			 slot->bus, slot->device, slot->hp_slot, slot->number, +			 ctrl->slot_device_offset);  		retval = pci_hp_register(slot->hotplug_slot,  				ctrl->pci_dev->subordinate, slot->device, name);  		if (retval) { diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index 58499277903..a81fb67ea9a 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -162,7 +162,7 @@ u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl)  	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset); -	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) { +	if (!(p_slot->hpc_ops->query_power_fault(p_slot))) {  		/*  		 * Power fault Cleared  		 */ @@ -196,8 +196,8 @@ static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,  	ctrl_dbg(ctrl, "Change speed to %d\n", speed);  	if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) { -		ctrl_err(ctrl, "%s: Issue of set bus speed mode command " -			 "failed\n", __func__); +		ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n", +			 __func__);  		return WRONG_BUS_FREQUENCY;  	}  	return rc; @@ -215,8 +215,8 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,  	 */  	if (flag) {  		if (asp < bsp) { -			ctrl_err(ctrl, "Speed of bus %x and adapter %x " -				 "mismatch\n", bsp, asp); +			ctrl_err(ctrl, "Speed of bus %x and adapter %x mismatch\n", +				 bsp, asp);  			rc = WRONG_BUS_FREQUENCY;  		}  		return rc; @@ -250,8 +250,7 @@ static int board_added(struct slot *p_slot)  	hp_slot = p_slot->device - ctrl->slot_device_offset; -	ctrl_dbg(ctrl, -		 "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n", +	ctrl_dbg(ctrl, "%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",  		 __func__, p_slot->device, ctrl->slot_device_offset, hp_slot);  	/* Power on slot without connecting to bus */ @@ -263,8 +262,8 @@ static int board_added(struct slot *p_slot)  	if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {  		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__); +			ctrl_err(ctrl, "%s: Issue of set bus speed mode command failed\n", +				 __func__);  			return WRONG_BUS_FREQUENCY;  		} @@ -277,20 +276,19 @@ static int board_added(struct slot *p_slot)  	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);  	if (rc) { -		ctrl_err(ctrl, "Can't get adapter speed or " -			 "bus mode mismatch\n"); +		ctrl_err(ctrl, "Can't get adapter speed or bus mode mismatch\n");  		return WRONG_BUS_FREQUENCY;  	} -	bsp = ctrl->pci_dev->bus->cur_bus_speed; -	msp = ctrl->pci_dev->bus->max_bus_speed; +	bsp = ctrl->pci_dev->subordinate->cur_bus_speed; +	msp = ctrl->pci_dev->subordinate->max_bus_speed;  	/* Check if there are other slots or devices on the same bus */  	if (!list_empty(&ctrl->pci_dev->subordinate->devices))  		slots_not_empty = 1; -	ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d," -		 " max_bus_speed %d\n", __func__, slots_not_empty, asp, +	ctrl_dbg(ctrl, "%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, max_bus_speed %d\n", +		 __func__, slots_not_empty, asp,  		 bsp, msp);  	rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp); @@ -490,12 +488,12 @@ static void handle_button_press_event(struct slot *p_slot)  		p_slot->hpc_ops->get_power_status(p_slot, &getstatus);  		if (getstatus) {  			p_slot->state = BLINKINGOFF_STATE; -			ctrl_info(ctrl, "PCI slot #%s - powering off due to " -				  "button press.\n", slot_name(p_slot)); +			ctrl_info(ctrl, "PCI slot #%s - powering off due to button press\n", +				  slot_name(p_slot));  		} else {  			p_slot->state = BLINKINGON_STATE; -			ctrl_info(ctrl, "PCI slot #%s - powering on due to " -				  "button press.\n", slot_name(p_slot)); +			ctrl_info(ctrl, "PCI slot #%s - powering on due to button press\n", +				  slot_name(p_slot));  		}  		/* blink green LED and turn off amber */  		p_slot->hpc_ops->green_led_blink(p_slot); @@ -518,8 +516,8 @@ static void handle_button_press_event(struct slot *p_slot)  		else  			p_slot->hpc_ops->green_led_off(p_slot);  		p_slot->hpc_ops->set_attention_status(p_slot, 0); -		ctrl_info(ctrl, "PCI slot #%s - action canceled due to " -			  "button press\n", slot_name(p_slot)); +		ctrl_info(ctrl, "PCI slot #%s - action canceled due to button press\n", +			  slot_name(p_slot));  		p_slot->state = STATIC_STATE;  		break;  	case POWEROFF_STATE: diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c index 75ba2311b54..29e22352822 100644 --- a/drivers/pci/hotplug/shpchp_hpc.c +++ b/drivers/pci/hotplug/shpchp_hpc.c @@ -116,7 +116,7 @@  #define SLOT_REG_RSVDZ_MASK	((1 << 15) | (7 << 21))  /* - * SHPC Command Code definitnions + * SHPC Command Code definitions   *   *     Slot Operation				00h - 3Fh   *     Set Bus Segment Speed/Mode A		40h - 47h @@ -341,8 +341,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)  	cmd_status = hpc_check_cmd_status(slot->ctrl);  	if (cmd_status) { -		ctrl_err(ctrl, -			 "Failed to issued command 0x%x (error code = %d)\n", +		ctrl_err(ctrl, "Failed to issued command 0x%x (error code = %d)\n",  			 cmd, cmd_status);  		retval = -EIO;  	} @@ -404,7 +403,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)  	return 0;  } -static int hpc_get_power_status(struct slot * slot, u8 *status) +static int hpc_get_power_status(struct slot *slot, u8 *status)  {  	struct controller *ctrl = slot->ctrl;  	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); @@ -528,7 +527,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)  	return retval;  } -static int hpc_query_power_fault(struct slot * slot) +static int hpc_query_power_fault(struct slot *slot)  {  	struct controller *ctrl = slot->ctrl;  	u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot)); @@ -614,7 +613,7 @@ static void hpc_release_ctlr(struct controller *ctrl)  	release_mem_region(ctrl->mmio_base, ctrl->mmio_size);  } -static int hpc_power_on_slot(struct slot * slot) +static int hpc_power_on_slot(struct slot *slot)  {  	int retval; @@ -625,7 +624,7 @@ static int hpc_power_on_slot(struct slot * slot)  	return retval;  } -static int hpc_slot_enable(struct slot * slot) +static int hpc_slot_enable(struct slot *slot)  {  	int retval; @@ -638,7 +637,7 @@ static int hpc_slot_enable(struct slot * slot)  	return retval;  } -static int hpc_slot_disable(struct slot * slot) +static int hpc_slot_disable(struct slot *slot)  {  	int retval; @@ -720,7 +719,7 @@ static int shpc_get_cur_bus_speed(struct controller *ctrl)  } -static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value) +static int hpc_set_bus_speed_mode(struct slot *slot, enum pci_bus_speed value)  {  	int retval;  	struct controller *ctrl = slot->ctrl; @@ -974,8 +973,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)  		for (i = 0; i < 9 + num_slots; i++) {  			rc = shpc_indirect_read(ctrl, i, &tempdword);  			if (rc) { -				ctrl_err(ctrl, -					 "Cannot read creg (index = %d)\n", i); +				ctrl_err(ctrl, "Cannot read creg (index = %d)\n", +					 i);  				goto abort;  			}  			ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword); @@ -1060,10 +1059,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)  		/* Installs the interrupt handler */  		rc = pci_enable_msi(pdev);  		if (rc) { -			ctrl_info(ctrl, -				  "Can't get msi for the hotplug controller\n"); -			ctrl_info(ctrl, -				  "Use INTx for the hotplug controller\n"); +			ctrl_info(ctrl, "Can't get msi for the hotplug controller\n"); +			ctrl_info(ctrl, "Use INTx for the hotplug controller\n");  		}  		rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED, @@ -1071,8 +1068,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)  		ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",  			 ctrl->pci_dev->irq, rc);  		if (rc) { -			ctrl_err(ctrl, "Can't get irq %d for the hotplug " -				 "controller\n", ctrl->pci_dev->irq); +			ctrl_err(ctrl, "Can't get irq %d for the hotplug controller\n", +				 ctrl->pci_dev->irq);  			goto abort_iounmap;  		}  	} diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index b0e83132542..469454e0cc4 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -34,34 +34,37 @@  #include "../pci.h"  #include "shpchp.h" -int __ref shpchp_configure_device(struct slot *p_slot) +int shpchp_configure_device(struct slot *p_slot)  {  	struct pci_dev *dev;  	struct controller *ctrl = p_slot->ctrl;  	struct pci_dev *bridge = ctrl->pci_dev;  	struct pci_bus *parent = bridge->subordinate; -	int num; +	int num, ret = 0; + +	pci_lock_rescan_remove();  	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));  	if (dev) { -		ctrl_err(ctrl, "Device %s already exists " -			 "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev), -			 pci_domain_nr(parent), p_slot->bus, p_slot->device); +		ctrl_err(ctrl, "Device %s already exists at %04x:%02x:%02x, cannot hot-add\n", +			 pci_name(dev), pci_domain_nr(parent), +			 p_slot->bus, p_slot->device);  		pci_dev_put(dev); -		return -EINVAL; +		ret = -EINVAL; +		goto out;  	}  	num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));  	if (num == 0) {  		ctrl_err(ctrl, "No new device found\n"); -		return -ENODEV; +		ret = -ENODEV; +		goto out;  	}  	list_for_each_entry(dev, &parent->devices, bus_list) {  		if (PCI_SLOT(dev->devfn) != p_slot->device)  			continue; -		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || -		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) +		if (pci_is_bridge(dev))  			pci_hp_add_bridge(dev);  	} @@ -75,7 +78,9 @@ int __ref shpchp_configure_device(struct slot *p_slot)  	pci_bus_add_devices(parent); -	return 0; + out: +	pci_unlock_rescan_remove(); +	return ret;  }  int shpchp_unconfigure_device(struct slot *p_slot) @@ -89,6 +94,8 @@ int shpchp_unconfigure_device(struct slot *p_slot)  	ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",  		 __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); +	pci_lock_rescan_remove(); +  	list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {  		if (PCI_SLOT(dev->devfn) != p_slot->device)  			continue; @@ -108,6 +115,8 @@ int shpchp_unconfigure_device(struct slot *p_slot)  		pci_stop_and_remove_bus_device(dev);  		pci_dev_put(dev);  	} + +	pci_unlock_rescan_remove();  	return rc;  } diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index e8c31fe2056..52875b36046 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -38,7 +38,7 @@  static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)  {  	struct pci_dev *pdev; -	char * out = buf; +	char *out = buf;  	int index, busnr;  	struct resource *res;  	struct pci_bus *bus; diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 6e373ea57b3..a94dd2c4183 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c @@ -87,12 +87,9 @@ void unmask_ht_irq(struct irq_data *data)  int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)  {  	struct ht_irq_cfg *cfg; +	int max_irq, pos, irq;  	unsigned long flags;  	u32 data; -	int max_irq; -	int pos; -	int irq; -	int node;  	pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ);  	if (!pos) @@ -105,7 +102,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)  	spin_unlock_irqrestore(&ht_irq_lock, flags);  	max_irq = (data >> 16) & 0xff; -	if ( idx > max_irq) +	if (idx > max_irq)  		return -EINVAL;  	cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); @@ -120,10 +117,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)  	cfg->msg.address_lo = 0xffffffff;  	cfg->msg.address_hi = 0xffffffff; -	node = dev_to_node(&dev->dev); -	irq = create_irq_nr(0, node); - -	if (irq <= 0) { +	irq = irq_alloc_hwirq(dev_to_node(&dev->dev)); +	if (!irq) {  		kfree(cfg);  		return -EBUSY;  	} @@ -136,6 +131,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update)  	return irq;  } +EXPORT_SYMBOL(__ht_create_irq);  /**   * ht_create_irq - create an irq and attach it to a device. @@ -151,6 +147,7 @@ int ht_create_irq(struct pci_dev *dev, int idx)  {  	return __ht_create_irq(dev, idx, NULL);  } +EXPORT_SYMBOL(ht_create_irq);  /**   * ht_destroy_irq - destroy an irq created with ht_create_irq @@ -166,11 +163,8 @@ void ht_destroy_irq(unsigned int irq)  	cfg = irq_get_handler_data(irq);  	irq_set_chip(irq, NULL);  	irq_set_handler_data(irq, NULL); -	destroy_irq(irq); +	irq_free_hwirq(irq);  	kfree(cfg);  } - -EXPORT_SYMBOL(__ht_create_irq); -EXPORT_SYMBOL(ht_create_irq);  EXPORT_SYMBOL(ht_destroy_irq); diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c index 1b90579b233..6b2b7dddbbd 100644 --- a/drivers/pci/ioapic.c +++ b/drivers/pci/ioapic.c @@ -20,7 +20,6 @@  #include <linux/module.h>  #include <linux/acpi.h>  #include <linux/slab.h> -#include <acpi/acpi_bus.h>  struct ioapic {  	acpi_handle	handle; @@ -37,7 +36,7 @@ static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)  	char *type;  	struct resource *res; -	handle = DEVICE_ACPI_HANDLE(&dev->dev); +	handle = ACPI_HANDLE(&dev->dev);  	if (!handle)  		return -EINVAL; @@ -113,6 +112,10 @@ static struct pci_driver ioapic_driver = {  	.remove		= ioapic_remove,  }; -module_pci_driver(ioapic_driver); +static int __init ioapic_init(void) +{ +	return pci_register_driver(&ioapic_driver); +} +module_init(ioapic_init);  MODULE_LICENSE("GPL"); diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index 21a7182dccd..cb6f24740ee 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c @@ -84,6 +84,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)  	virtfn->dev.parent = dev->dev.parent;  	virtfn->physfn = pci_dev_get(dev);  	virtfn->is_virtfn = 1; +	virtfn->multifunction = 0;  	for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {  		res = dev->resource + PCI_IOV_RESOURCES + i; @@ -105,7 +106,7 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)  	pci_device_add(virtfn, virtfn->bus);  	mutex_unlock(&iov->dev->sriov->lock); -	rc = pci_bus_add_device(virtfn); +	pci_bus_add_device(virtfn);  	sprintf(buf, "virtfn%u", id);  	rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);  	if (rc) @@ -169,97 +170,6 @@ static void virtfn_remove(struct pci_dev *dev, int id, int reset)  	pci_dev_put(dev);  } -static int sriov_migration(struct pci_dev *dev) -{ -	u16 status; -	struct pci_sriov *iov = dev->sriov; - -	if (!iov->num_VFs) -		return 0; - -	if (!(iov->cap & PCI_SRIOV_CAP_VFM)) -		return 0; - -	pci_read_config_word(dev, iov->pos + PCI_SRIOV_STATUS, &status); -	if (!(status & PCI_SRIOV_STATUS_VFM)) -		return 0; - -	schedule_work(&iov->mtask); - -	return 1; -} - -static void sriov_migration_task(struct work_struct *work) -{ -	int i; -	u8 state; -	u16 status; -	struct pci_sriov *iov = container_of(work, struct pci_sriov, mtask); - -	for (i = iov->initial_VFs; i < iov->num_VFs; i++) { -		state = readb(iov->mstate + i); -		if (state == PCI_SRIOV_VFM_MI) { -			writeb(PCI_SRIOV_VFM_AV, iov->mstate + i); -			state = readb(iov->mstate + i); -			if (state == PCI_SRIOV_VFM_AV) -				virtfn_add(iov->self, i, 1); -		} else if (state == PCI_SRIOV_VFM_MO) { -			virtfn_remove(iov->self, i, 1); -			writeb(PCI_SRIOV_VFM_UA, iov->mstate + i); -			state = readb(iov->mstate + i); -			if (state == PCI_SRIOV_VFM_AV) -				virtfn_add(iov->self, i, 0); -		} -	} - -	pci_read_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, &status); -	status &= ~PCI_SRIOV_STATUS_VFM; -	pci_write_config_word(iov->self, iov->pos + PCI_SRIOV_STATUS, status); -} - -static int sriov_enable_migration(struct pci_dev *dev, int nr_virtfn) -{ -	int bir; -	u32 table; -	resource_size_t pa; -	struct pci_sriov *iov = dev->sriov; - -	if (nr_virtfn <= iov->initial_VFs) -		return 0; - -	pci_read_config_dword(dev, iov->pos + PCI_SRIOV_VFM, &table); -	bir = PCI_SRIOV_VFM_BIR(table); -	if (bir > PCI_STD_RESOURCE_END) -		return -EIO; - -	table = PCI_SRIOV_VFM_OFFSET(table); -	if (table + nr_virtfn > pci_resource_len(dev, bir)) -		return -EIO; - -	pa = pci_resource_start(dev, bir) + table; -	iov->mstate = ioremap(pa, nr_virtfn); -	if (!iov->mstate) -		return -ENOMEM; - -	INIT_WORK(&iov->mtask, sriov_migration_task); - -	iov->ctrl |= PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR; -	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - -	return 0; -} - -static void sriov_disable_migration(struct pci_dev *dev) -{ -	struct pci_sriov *iov = dev->sriov; - -	iov->ctrl &= ~(PCI_SRIOV_CTRL_VFM | PCI_SRIOV_CTRL_INTR); -	pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); - -	cancel_work_sync(&iov->mtask); -	iounmap(iov->mstate); -} -  static int sriov_enable(struct pci_dev *dev, int nr_virtfn)  {  	int rc; @@ -350,12 +260,6 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)  			goto failed;  	} -	if (iov->cap & PCI_SRIOV_CAP_VFM) { -		rc = sriov_enable_migration(dev, nr_virtfn); -		if (rc) -			goto failed; -	} -  	kobject_uevent(&dev->dev.kobj, KOBJ_CHANGE);  	iov->num_VFs = nr_virtfn; @@ -386,9 +290,6 @@ static void sriov_disable(struct pci_dev *dev)  	if (!iov->num_VFs)  		return; -	if (iov->cap & PCI_SRIOV_CAP_VFM) -		sriov_disable_migration(dev); -  	for (i = 0; i < iov->num_VFs; i++)  		virtfn_remove(dev, i, 0); @@ -441,6 +342,7 @@ static int sriov_init(struct pci_dev *dev, int pos)  found:  	pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl); +	pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, 0);  	pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);  	pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);  	if (!offset || (total > 1 && !stride)) @@ -610,7 +512,7 @@ resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno)  	struct resource tmp;  	enum pci_bar_type type;  	int reg = pci_iov_resource_bar(dev, resno, &type); -	 +  	if (!reg)  		return 0; @@ -686,25 +588,6 @@ void pci_disable_sriov(struct pci_dev *dev)  EXPORT_SYMBOL_GPL(pci_disable_sriov);  /** - * pci_sriov_migration - notify SR-IOV core of Virtual Function Migration - * @dev: the PCI device - * - * Returns IRQ_HANDLED if the IRQ is handled, or IRQ_NONE if not. - * - * Physical Function driver is responsible to register IRQ handler using - * VF Migration Interrupt Message Number, and call this function when the - * interrupt is generated by the hardware. - */ -irqreturn_t pci_sriov_migration(struct pci_dev *dev) -{ -	if (!dev->is_physfn) -		return IRQ_NONE; - -	return sriov_migration(dev) ? IRQ_HANDLED : IRQ_NONE; -} -EXPORT_SYMBOL_GPL(pci_sriov_migration); - -/**   * pci_num_vf - return number of VFs associated with a PF device_release_driver   * @dev: the PCI device   * diff --git a/drivers/pci/irq.c b/drivers/pci/irq.c index b008cf86b9c..6684f153ab5 100644 --- a/drivers/pci/irq.c +++ b/drivers/pci/irq.c @@ -25,7 +25,7 @@ static void pci_note_irq_problem(struct pci_dev *pdev, const char *reason)  /**   * pci_lost_interrupt - reports a lost PCI interrupt   * @pdev:	device whose interrupt is lost - *  + *   * The primary function of this routine is to report a lost interrupt   * in a standard way which users can recognise (instead of blaming the   * driver). diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index d5f90d6383b..13f3d303727 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -10,7 +10,6 @@  #include <linux/mm.h>  #include <linux/irq.h>  #include <linux/interrupt.h> -#include <linux/init.h>  #include <linux/export.h>  #include <linux/ioport.h>  #include <linux/pci.h> @@ -116,7 +115,7 @@ void __weak arch_teardown_msi_irqs(struct pci_dev *dev)  	return default_teardown_msi_irqs(dev);  } -void default_restore_msi_irqs(struct pci_dev *dev, int irq) +static void default_restore_msi_irq(struct pci_dev *dev, int irq)  {  	struct msi_desc *entry; @@ -134,9 +133,9 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq)  		write_msi_msg(irq, &entry->msg);  } -void __weak arch_restore_msi_irqs(struct pci_dev *dev, int irq) +void __weak arch_restore_msi_irqs(struct pci_dev *dev)  { -	return default_restore_msi_irqs(dev, irq); +	return default_restore_msi_irqs(dev);  }  static void msi_set_enable(struct pci_dev *dev, int enable) @@ -185,7 +184,7 @@ static inline __attribute_const__ u32 msi_enabled_mask(u16 control)   * reliably as devices without an INTx disable bit will then generate a   * level IRQ which will never be cleared.   */ -static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) +u32 default_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)  {  	u32 mask_bits = desc->masked; @@ -199,9 +198,14 @@ static u32 __msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)  	return mask_bits;  } +__weak u32 arch_msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag) +{ +	return default_msi_mask_irq(desc, mask, flag); +} +  static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)  { -	desc->masked = __msi_mask_irq(desc, mask, flag); +	desc->masked = arch_msi_mask_irq(desc, mask, flag);  }  /* @@ -211,7 +215,7 @@ static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)   * file.  This saves a few milliseconds when initialising devices with lots   * of MSI-X interrupts.   */ -static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag) +u32 default_msix_mask_irq(struct msi_desc *desc, u32 flag)  {  	u32 mask_bits = desc->masked;  	unsigned offset = desc->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + @@ -224,9 +228,14 @@ static u32 __msix_mask_irq(struct msi_desc *desc, u32 flag)  	return mask_bits;  } +__weak u32 arch_msix_mask_irq(struct msi_desc *desc, u32 flag) +{ +	return default_msix_mask_irq(desc, flag); +} +  static void msix_mask_irq(struct msi_desc *desc, u32 flag)  { -	desc->masked = __msix_mask_irq(desc, flag); +	desc->masked = arch_msix_mask_irq(desc, flag);  }  static void msi_set_mask_bit(struct irq_data *data, u32 flag) @@ -252,6 +261,15 @@ void unmask_msi_irq(struct irq_data *data)  	msi_set_mask_bit(data, 0);  } +void default_restore_msi_irqs(struct pci_dev *dev) +{ +	struct msi_desc *entry; + +	list_for_each_entry(entry, &dev->msi_list, list) { +		default_restore_msi_irq(dev, entry->irq); +	} +} +  void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)  {  	BUG_ON(entry->dev->current_state != PCI_D0); @@ -353,6 +371,9 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)  static void free_msi_irqs(struct pci_dev *dev)  {  	struct msi_desc *entry, *tmp; +	struct attribute **msi_attrs; +	struct device_attribute *dev_attr; +	int count = 0;  	list_for_each_entry(entry, &dev->msi_list, list) {  		int i, nvec; @@ -388,6 +409,22 @@ static void free_msi_irqs(struct pci_dev *dev)  		list_del(&entry->list);  		kfree(entry);  	} + +	if (dev->msi_irq_groups) { +		sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups); +		msi_attrs = dev->msi_irq_groups[0]->attrs; +		while (msi_attrs[count]) { +			dev_attr = container_of(msi_attrs[count], +						struct device_attribute, attr); +			kfree(dev_attr->attr.name); +			kfree(dev_attr); +			++count; +		} +		kfree(msi_attrs); +		kfree(dev->msi_irq_groups[0]); +		kfree(dev->msi_irq_groups); +		dev->msi_irq_groups = NULL; +	}  }  static struct msi_desc *alloc_msi_entry(struct pci_dev *dev) @@ -420,7 +457,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)  	pci_intx_for_msi(dev, 0);  	msi_set_enable(dev, 0); -	arch_restore_msi_irqs(dev, dev->irq); +	arch_restore_msi_irqs(dev);  	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);  	msi_mask_irq(entry, msi_capable_mask(control), entry->masked); @@ -445,8 +482,8 @@ static void __pci_restore_msix_state(struct pci_dev *dev)  	control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL;  	pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); +	arch_restore_msi_irqs(dev);  	list_for_each_entry(entry, &dev->msi_list, list) { -		arch_restore_msi_irqs(dev, entry->irq);  		msix_mask_irq(entry, entry->masked);  	} @@ -461,95 +498,99 @@ void pci_restore_msi_state(struct pci_dev *dev)  }  EXPORT_SYMBOL_GPL(pci_restore_msi_state); - -#define to_msi_attr(obj) container_of(obj, struct msi_attribute, attr) -#define to_msi_desc(obj) container_of(obj, struct msi_desc, kobj) - -struct msi_attribute { -	struct attribute        attr; -	ssize_t (*show)(struct msi_desc *entry, struct msi_attribute *attr, -			char *buf); -	ssize_t (*store)(struct msi_desc *entry, struct msi_attribute *attr, -			 const char *buf, size_t count); -}; - -static ssize_t show_msi_mode(struct msi_desc *entry, struct msi_attribute *atr, +static ssize_t msi_mode_show(struct device *dev, struct device_attribute *attr,  			     char *buf)  { -	return sprintf(buf, "%s\n", entry->msi_attrib.is_msix ? "msix" : "msi"); -} - -static ssize_t msi_irq_attr_show(struct kobject *kobj, -				 struct attribute *attr, char *buf) -{ -	struct msi_attribute *attribute = to_msi_attr(attr); -	struct msi_desc *entry = to_msi_desc(kobj); - -	if (!attribute->show) -		return -EIO; - -	return attribute->show(entry, attribute, buf); -} - -static const struct sysfs_ops msi_irq_sysfs_ops = { -	.show = msi_irq_attr_show, -}; - -static struct msi_attribute mode_attribute = -	__ATTR(mode, S_IRUGO, show_msi_mode, NULL); - - -static struct attribute *msi_irq_default_attrs[] = { -	&mode_attribute.attr, -	NULL -}; +	struct pci_dev *pdev = to_pci_dev(dev); +	struct msi_desc *entry; +	unsigned long irq; +	int retval; -static void msi_kobj_release(struct kobject *kobj) -{ -	struct msi_desc *entry = to_msi_desc(kobj); +	retval = kstrtoul(attr->attr.name, 10, &irq); +	if (retval) +		return retval; -	pci_dev_put(entry->dev); +	list_for_each_entry(entry, &pdev->msi_list, list) { +		if (entry->irq == irq) { +			return sprintf(buf, "%s\n", +				       entry->msi_attrib.is_msix ? "msix" : "msi"); +		} +	} +	return -ENODEV;  } -static struct kobj_type msi_irq_ktype = { -	.release = msi_kobj_release, -	.sysfs_ops = &msi_irq_sysfs_ops, -	.default_attrs = msi_irq_default_attrs, -}; -  static int populate_msi_sysfs(struct pci_dev *pdev)  { +	struct attribute **msi_attrs; +	struct attribute *msi_attr; +	struct device_attribute *msi_dev_attr; +	struct attribute_group *msi_irq_group; +	const struct attribute_group **msi_irq_groups;  	struct msi_desc *entry; -	struct kobject *kobj; -	int ret; +	int ret = -ENOMEM; +	int num_msi = 0;  	int count = 0; -	pdev->msi_kset = kset_create_and_add("msi_irqs", NULL, &pdev->dev.kobj); -	if (!pdev->msi_kset) -		return -ENOMEM; +	/* Determine how many msi entries we have */ +	list_for_each_entry(entry, &pdev->msi_list, list) { +		++num_msi; +	} +	if (!num_msi) +		return 0; +	/* Dynamically create the MSI attributes for the PCI device */ +	msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL); +	if (!msi_attrs) +		return -ENOMEM;  	list_for_each_entry(entry, &pdev->msi_list, list) { -		kobj = &entry->kobj; -		kobj->kset = pdev->msi_kset; -		pci_dev_get(pdev); -		ret = kobject_init_and_add(kobj, &msi_irq_ktype, NULL, -				     "%u", entry->irq); -		if (ret) -			goto out_unroll; - -		count++; +		msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); +		if (!msi_dev_attr) +			goto error_attrs; +		msi_attrs[count] = &msi_dev_attr->attr; + +		sysfs_attr_init(&msi_dev_attr->attr); +		msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d", +						    entry->irq); +		if (!msi_dev_attr->attr.name) +			goto error_attrs; +		msi_dev_attr->attr.mode = S_IRUGO; +		msi_dev_attr->show = msi_mode_show; +		++count;  	} +	msi_irq_group = kzalloc(sizeof(*msi_irq_group), GFP_KERNEL); +	if (!msi_irq_group) +		goto error_attrs; +	msi_irq_group->name = "msi_irqs"; +	msi_irq_group->attrs = msi_attrs; + +	msi_irq_groups = kzalloc(sizeof(void *) * 2, GFP_KERNEL); +	if (!msi_irq_groups) +		goto error_irq_group; +	msi_irq_groups[0] = msi_irq_group; + +	ret = sysfs_create_groups(&pdev->dev.kobj, msi_irq_groups); +	if (ret) +		goto error_irq_groups; +	pdev->msi_irq_groups = msi_irq_groups; +  	return 0; -out_unroll: -	list_for_each_entry(entry, &pdev->msi_list, list) { -		if (!count) -			break; -		kobject_del(&entry->kobj); -		kobject_put(&entry->kobj); -		count--; +error_irq_groups: +	kfree(msi_irq_groups); +error_irq_group: +	kfree(msi_irq_group); +error_attrs: +	count = 0; +	msi_attr = msi_attrs[count]; +	while (msi_attr) { +		msi_dev_attr = container_of(msi_attr, struct device_attribute, attr); +		kfree(msi_attr->name); +		kfree(msi_dev_attr); +		++count; +		msi_attr = msi_attrs[count];  	} +	kfree(msi_attrs);  	return ret;  } @@ -719,7 +760,7 @@ static int msix_capability_init(struct pci_dev *dev,  	ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);  	if (ret) -		goto error; +		goto out_avail;  	/*  	 * Some devices require MSI-X to be enabled before we can touch the @@ -732,10 +773,8 @@ static int msix_capability_init(struct pci_dev *dev,  	msix_program_entries(dev, entries);  	ret = populate_msi_sysfs(dev); -	if (ret) { -		ret = 0; -		goto error; -	} +	if (ret) +		goto out_free;  	/* Set MSI-X enabled bits and unmask the function */  	pci_intx_for_msi(dev, 0); @@ -746,7 +785,7 @@ static int msix_capability_init(struct pci_dev *dev,  	return 0; -error: +out_avail:  	if (ret < 0) {  		/*  		 * If we had some success, report the number of irqs @@ -763,6 +802,7 @@ error:  			ret = avail;  	} +out_free:  	free_msi_irqs(dev);  	return ret; @@ -774,7 +814,7 @@ error:   * @nvec: how many MSIs have been requested ?   * @type: are we checking for MSI or MSI-X ?   * - * Look at global flags, the device itself, and its parent busses + * Look at global flags, the device itself, and its parent buses   * to determine if MSI/-X are supported for the device. If MSI/-X is   * supported return 0, else return an error code.   **/ @@ -814,52 +854,18 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type)  }  /** - * pci_enable_msi_block - configure device's MSI capability structure - * @dev: device to configure - * @nvec: number of interrupts to configure + * pci_msi_vec_count - Return the number of MSI vectors a device can send + * @dev: device to report about   * - * Allocate IRQs for a device with the MSI capability. - * This function returns a negative errno if an error occurs.  If it - * is unable to allocate the number of interrupts requested, it returns - * the number of interrupts it might be able to allocate.  If it successfully - * allocates at least the number of interrupts requested, it returns 0 and - * updates the @dev's irq member to the lowest new interrupt number; the - * other interrupt numbers allocated to this device are consecutive. - */ -int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec) -{ -	int status, maxvec; -	u16 msgctl; - -	if (!dev->msi_cap) -		return -EINVAL; - -	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl); -	maxvec = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); -	if (nvec > maxvec) -		return maxvec; - -	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); -	if (status) -		return status; - -	WARN_ON(!!dev->msi_enabled); - -	/* Check whether driver already requested MSI-X irqs */ -	if (dev->msix_enabled) { -		dev_info(&dev->dev, "can't enable MSI " -			 "(MSI-X already enabled)\n"); -		return -EINVAL; -	} - -	status = msi_capability_init(dev, nvec); -	return status; -} -EXPORT_SYMBOL(pci_enable_msi_block); - -int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec) + * This function returns the number of MSI vectors a device requested via + * Multiple Message Capable register. It returns a negative errno if the + * device is not capable sending MSI interrupts. Otherwise, the call succeeds + * and returns a power of two, up to a maximum of 2^5 (32), according to the + * MSI specification. + **/ +int pci_msi_vec_count(struct pci_dev *dev)  { -	int ret, nvec; +	int ret;  	u16 msgctl;  	if (!dev->msi_cap) @@ -868,19 +874,9 @@ int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)  	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);  	ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); -	if (maxvec) -		*maxvec = ret; - -	do { -		nvec = ret; -		ret = pci_enable_msi_block(dev, nvec); -	} while (ret > 0); - -	if (ret < 0) -		return ret; -	return nvec; +	return ret;  } -EXPORT_SYMBOL(pci_enable_msi_block_auto); +EXPORT_SYMBOL(pci_msi_vec_count);  void pci_msi_shutdown(struct pci_dev *dev)  { @@ -902,7 +898,7 @@ void pci_msi_shutdown(struct pci_dev *dev)  	pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &ctrl);  	mask = msi_capable_mask(ctrl);  	/* Keep cached state to be restored */ -	__msi_mask_irq(desc, mask, ~mask); +	arch_msi_mask_irq(desc, mask, ~mask);  	/* Restore dev->irq to its default pin-assertion irq */  	dev->irq = desc->msi_attrib.default_irq; @@ -915,25 +911,28 @@ void pci_disable_msi(struct pci_dev *dev)  	pci_msi_shutdown(dev);  	free_msi_irqs(dev); -	kset_unregister(dev->msi_kset); -	dev->msi_kset = NULL;  }  EXPORT_SYMBOL(pci_disable_msi);  /** - * pci_msix_table_size - return the number of device's MSI-X table entries + * pci_msix_vec_count - return the number of device's MSI-X table entries   * @dev: pointer to the pci_dev data structure of MSI-X device function - */ -int pci_msix_table_size(struct pci_dev *dev) + * This function returns the number of device's MSI-X table entries and + * therefore the number of MSI-X vectors device is capable of sending. + * It returns a negative errno if the device is not capable of sending MSI-X + * interrupts. + **/ +int pci_msix_vec_count(struct pci_dev *dev)  {  	u16 control;  	if (!dev->msix_cap) -		return 0; +		return -EINVAL;  	pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);  	return msix_table_size(control);  } +EXPORT_SYMBOL(pci_msix_vec_count);  /**   * pci_enable_msix - configure device's MSI-X capability structure @@ -955,14 +954,16 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)  	int status, nr_entries;  	int i, j; -	if (!entries || !dev->msix_cap) +	if (!entries || !dev->msix_cap || dev->current_state != PCI_D0)  		return -EINVAL;  	status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX);  	if (status)  		return status; -	nr_entries = pci_msix_table_size(dev); +	nr_entries = pci_msix_vec_count(dev); +	if (nr_entries < 0) +		return nr_entries;  	if (nvec > nr_entries)  		return nr_entries; @@ -979,8 +980,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)  	/* Check whether driver already requested for MSI irq */  	if (dev->msi_enabled) { -		dev_info(&dev->dev, "can't enable MSI-X " -		       "(MSI IRQ already assigned)\n"); +		dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n");  		return -EINVAL;  	}  	status = msix_capability_init(dev, entries, nvec); @@ -998,7 +998,7 @@ void pci_msix_shutdown(struct pci_dev *dev)  	/* Return the device with MSI-X masked as initial states */  	list_for_each_entry(entry, &dev->msi_list, list) {  		/* Keep cached states to be restored */ -		__msix_mask_irq(entry, 1); +		arch_msix_mask_irq(entry, 1);  	}  	msix_set_enable(dev, 0); @@ -1013,8 +1013,6 @@ void pci_disable_msix(struct pci_dev *dev)  	pci_msix_shutdown(dev);  	free_msi_irqs(dev); -	kset_unregister(dev->msi_kset); -	dev->msi_kset = NULL;  }  EXPORT_SYMBOL(pci_disable_msix); @@ -1069,3 +1067,108 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)  	if (dev->msix_cap)  		msix_set_enable(dev, 0);  } + +/** + * pci_enable_msi_range - configure device's MSI capability structure + * @dev: device to configure + * @minvec: minimal number of interrupts to configure + * @maxvec: maximum number of interrupts to configure + * + * This function tries to allocate a maximum possible number of interrupts in a + * range between @minvec and @maxvec. It returns a negative errno if an error + * occurs. If it succeeds, it returns the actual number of interrupts allocated + * and updates the @dev's irq member to the lowest new interrupt number; + * the other interrupt numbers allocated to this device are consecutive. + **/ +int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) +{ +	int nvec; +	int rc; + +	if (dev->current_state != PCI_D0) +		return -EINVAL; + +	WARN_ON(!!dev->msi_enabled); + +	/* Check whether driver already requested MSI-X irqs */ +	if (dev->msix_enabled) { +		dev_info(&dev->dev, +			 "can't enable MSI (MSI-X already enabled)\n"); +		return -EINVAL; +	} + +	if (maxvec < minvec) +		return -ERANGE; + +	nvec = pci_msi_vec_count(dev); +	if (nvec < 0) +		return nvec; +	else if (nvec < minvec) +		return -EINVAL; +	else if (nvec > maxvec) +		nvec = maxvec; + +	do { +		rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); +		if (rc < 0) { +			return rc; +		} else if (rc > 0) { +			if (rc < minvec) +				return -ENOSPC; +			nvec = rc; +		} +	} while (rc); + +	do { +		rc = msi_capability_init(dev, nvec); +		if (rc < 0) { +			return rc; +		} else if (rc > 0) { +			if (rc < minvec) +				return -ENOSPC; +			nvec = rc; +		} +	} while (rc); + +	return nvec; +} +EXPORT_SYMBOL(pci_enable_msi_range); + +/** + * pci_enable_msix_range - configure device's MSI-X capability structure + * @dev: pointer to the pci_dev data structure of MSI-X device function + * @entries: pointer to an array of MSI-X entries + * @minvec: minimum number of MSI-X irqs requested + * @maxvec: maximum number of MSI-X irqs requested + * + * Setup the MSI-X capability structure of device function with a maximum + * possible number of interrupts in the range between @minvec and @maxvec + * upon its software driver call to request for MSI-X mode enabled on its + * hardware device function. It returns a negative errno if an error occurs. + * If it succeeds, it returns the actual number of interrupts allocated and + * indicates the successful configuration of MSI-X capability structure + * with new allocated MSI-X interrupts. + **/ +int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries, +			       int minvec, int maxvec) +{ +	int nvec = maxvec; +	int rc; + +	if (maxvec < minvec) +		return -ERANGE; + +	do { +		rc = pci_enable_msix(dev, entries, nvec); +		if (rc < 0) { +			return rc; +		} else if (rc > 0) { +			if (rc < minvec) +				return -ENOSPC; +			nvec = rc; +		} +	} while (rc); + +	return nvec; +} +EXPORT_SYMBOL(pci_enable_msix_range); diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index b0299e6d9a3..ca4927ba843 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -12,9 +12,6 @@  #include <linux/pci.h>  #include <linux/module.h>  #include <linux/pci-aspm.h> -#include <acpi/acpi.h> -#include <acpi/acpi_bus.h> -  #include <linux/pci-acpi.h>  #include <linux/pm_runtime.h>  #include <linux/pm_qos.h> @@ -141,7 +138,7 @@ phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)   * if (_PRW at S-state x)   *	choose from highest power _SxD to lowest power _SxW   * else // no _PRW at S-state x - * 	choose highest power _SxD or any lower power + *	choose highest power _SxD or any lower power   */  static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev) @@ -173,15 +170,14 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev)  static bool acpi_pci_power_manageable(struct pci_dev *dev)  { -	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); +	acpi_handle handle = ACPI_HANDLE(&dev->dev);  	return handle ? acpi_bus_power_manageable(handle) : false;  }  static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)  { -	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); -	acpi_handle tmp; +	acpi_handle handle = ACPI_HANDLE(&dev->dev);  	static const u8 state_conv[] = {  		[PCI_D0] = ACPI_STATE_D0,  		[PCI_D1] = ACPI_STATE_D1, @@ -192,7 +188,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)  	int error = -EINVAL;  	/* If the ACPI device has _EJ0, ignore the device */ -	if (!handle || ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp))) +	if (!handle || acpi_has_method(handle, "_EJ0"))  		return -ENODEV;  	switch (state) { @@ -218,7 +214,7 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)  static bool acpi_pci_can_wakeup(struct pci_dev *dev)  { -	acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev); +	acpi_handle handle = ACPI_HANDLE(&dev->dev);  	return handle ? acpi_bus_can_wakeup(handle) : false;  } @@ -307,65 +303,60 @@ void acpi_pci_remove_bus(struct pci_bus *bus)  }  /* ACPI bus type */ -static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) +static struct acpi_device *acpi_pci_find_companion(struct device *dev)  {  	struct pci_dev *pci_dev = to_pci_dev(dev); -	bool is_bridge; +	bool check_children;  	u64 addr; -	/* -	 * pci_is_bridge() is not suitable here, because pci_dev->subordinate -	 * is set only after acpi_pci_find_device() has been called for the -	 * given device. -	 */ -	is_bridge = pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE -			|| pci_dev->hdr_type == PCI_HEADER_TYPE_CARDBUS; +	check_children = pci_is_bridge(pci_dev);  	/* Please ref to ACPI spec for the syntax of _ADR */  	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn); -	*handle = acpi_find_child(ACPI_HANDLE(dev->parent), addr, is_bridge); -	if (!*handle) -		return -ENODEV; -	return 0; +	return acpi_find_child_device(ACPI_COMPANION(dev->parent), addr, +				      check_children);  }  static void pci_acpi_setup(struct device *dev)  {  	struct pci_dev *pci_dev = to_pci_dev(dev); -	acpi_handle handle = ACPI_HANDLE(dev); -	struct acpi_device *adev; +	struct acpi_device *adev = ACPI_COMPANION(dev); + +	if (!adev) +		return; -	if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid) +	pci_acpi_add_pm_notifier(adev, pci_dev); +	if (!adev->wakeup.flags.valid)  		return;  	device_set_wakeup_capable(dev, true);  	acpi_pci_sleep_wake(pci_dev, false); - -	pci_acpi_add_pm_notifier(adev, pci_dev);  	if (adev->wakeup.flags.run_wake)  		device_set_run_wake(dev, true);  }  static void pci_acpi_cleanup(struct device *dev)  { -	acpi_handle handle = ACPI_HANDLE(dev); -	struct acpi_device *adev; +	struct acpi_device *adev = ACPI_COMPANION(dev); + +	if (!adev) +		return; -	if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) { +	pci_acpi_remove_pm_notifier(adev); +	if (adev->wakeup.flags.valid) {  		device_set_wakeup_capable(dev, false);  		device_set_run_wake(dev, false); -		pci_acpi_remove_pm_notifier(adev);  	}  }  static bool pci_acpi_bus_match(struct device *dev)  { -	return dev->bus == &pci_bus_type; +	return dev_is_pci(dev);  }  static struct acpi_bus_type acpi_pci_bus = {  	.name = "PCI",  	.match = pci_acpi_bus_match, -	.find_device = acpi_pci_find_device, +	.find_companion = acpi_pci_find_companion,  	.setup = pci_acpi_setup,  	.cleanup = pci_acpi_cleanup,  }; diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 98f7b9b8950..3f8e3dbcaa7 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -19,6 +19,7 @@  #include <linux/cpu.h>  #include <linux/pm_runtime.h>  #include <linux/suspend.h> +#include <linux/kexec.h>  #include "pci.h"  struct pci_dynid { @@ -76,6 +77,7 @@ int pci_add_dynid(struct pci_driver *drv,  	return retval;  } +EXPORT_SYMBOL_GPL(pci_add_dynid);  static void pci_free_dynids(struct pci_driver *drv)  { @@ -97,16 +99,16 @@ static void pci_free_dynids(struct pci_driver *drv)   *   * Allow PCI IDs to be added to an existing driver via sysfs.   */ -static ssize_t -store_new_id(struct device_driver *driver, const char *buf, size_t count) +static ssize_t store_new_id(struct device_driver *driver, const char *buf, +			    size_t count)  {  	struct pci_driver *pdrv = to_pci_driver(driver);  	const struct pci_device_id *ids = pdrv->id_table; -	__u32 vendor, device, subvendor=PCI_ANY_ID, -		subdevice=PCI_ANY_ID, class=0, class_mask=0; -	unsigned long driver_data=0; -	int fields=0; -	int retval; +	__u32 vendor, device, subvendor = PCI_ANY_ID, +		subdevice = PCI_ANY_ID, class = 0, class_mask = 0; +	unsigned long driver_data = 0; +	int fields = 0; +	int retval = 0;  	fields = sscanf(buf, "%x %x %x %x %x %x %lx",  			&vendor, &device, &subvendor, &subdevice, @@ -114,6 +116,26 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)  	if (fields < 2)  		return -EINVAL; +	if (fields != 7) { +		struct pci_dev *pdev = kzalloc(sizeof(*pdev), GFP_KERNEL); +		if (!pdev) +			return -ENOMEM; + +		pdev->vendor = vendor; +		pdev->device = device; +		pdev->subsystem_vendor = subvendor; +		pdev->subsystem_device = subdevice; +		pdev->class = class; + +		if (pci_match_id(pdrv->id_table, pdev)) +			retval = -EEXIST; + +		kfree(pdev); + +		if (retval) +			return retval; +	} +  	/* Only accept driver_data values that match an existing id_table  	   entry */  	if (ids) { @@ -135,6 +157,7 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)  		return retval;  	return count;  } +static DRIVER_ATTR(new_id, S_IWUSR, NULL, store_new_id);  /**   * store_remove_id - remove a PCI device ID from this driver @@ -144,8 +167,8 @@ store_new_id(struct device_driver *driver, const char *buf, size_t count)   *   * Removes a dynamic pci device ID to this driver.   */ -static ssize_t -store_remove_id(struct device_driver *driver, const char *buf, size_t count) +static ssize_t store_remove_id(struct device_driver *driver, const char *buf, +			       size_t count)  {  	struct pci_dynid *dynid, *n;  	struct pci_driver *pdrv = to_pci_driver(driver); @@ -180,12 +203,14 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count)  		return retval;  	return count;  } +static DRIVER_ATTR(remove_id, S_IWUSR, NULL, store_remove_id); -static struct driver_attribute pci_drv_attrs[] = { -	__ATTR(new_id, S_IWUSR, NULL, store_new_id), -	__ATTR(remove_id, S_IWUSR, NULL, store_remove_id), -	__ATTR_NULL, +static struct attribute *pci_drv_attrs[] = { +	&driver_attr_new_id.attr, +	&driver_attr_remove_id.attr, +	NULL,  }; +ATTRIBUTE_GROUPS(pci_drv);  /**   * pci_match_id - See if a pci device matches a given pci_id table @@ -211,6 +236,14 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,  	}  	return NULL;  } +EXPORT_SYMBOL(pci_match_id); + +static const struct pci_device_id pci_device_id_any = { +	.vendor = PCI_ANY_ID, +	.device = PCI_ANY_ID, +	.subvendor = PCI_ANY_ID, +	.subdevice = PCI_ANY_ID, +};  /**   * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure @@ -225,18 +258,30 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,  						    struct pci_dev *dev)  {  	struct pci_dynid *dynid; +	const struct pci_device_id *found_id = NULL; + +	/* When driver_override is set, only bind to the matching driver */ +	if (dev->driver_override && strcmp(dev->driver_override, drv->name)) +		return NULL;  	/* Look at the dynamic ids first, before the static ones */  	spin_lock(&drv->dynids.lock);  	list_for_each_entry(dynid, &drv->dynids.list, node) {  		if (pci_match_one_device(&dynid->id, dev)) { -			spin_unlock(&drv->dynids.lock); -			return &dynid->id; +			found_id = &dynid->id; +			break;  		}  	}  	spin_unlock(&drv->dynids.lock); -	return pci_match_id(drv->id_table, dev); +	if (!found_id) +		found_id = pci_match_id(drv->id_table, dev); + +	/* driver_override will always match, send a dummy id */ +	if (!found_id && dev->driver_override) +		found_id = &pci_device_id_any; + +	return found_id;  }  struct drv_dev_and_id { @@ -264,11 +309,19 @@ static long local_pci_probe(void *_ddi)  	pm_runtime_get_sync(dev);  	pci_dev->driver = pci_drv;  	rc = pci_drv->probe(pci_dev, ddi->id); -	if (rc) { +	if (!rc) +		return rc; +	if (rc < 0) {  		pci_dev->driver = NULL;  		pm_runtime_put_sync(dev); +		return rc;  	} -	return rc; +	/* +	 * Probe function should return < 0 for failure, 0 for success +	 * Treat values > 0 as success, but warn. +	 */ +	dev_warn(dev, "Driver probe function unexpectedly returned %d\n", rc); +	return 0;  }  static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev, @@ -277,12 +330,27 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,  	int error, node;  	struct drv_dev_and_id ddi = { drv, dev, id }; -	/* Execute driver initialization on node where the device's -	   bus is attached to.  This way the driver likely allocates -	   its local memory on the right node without any need to -	   change it. */ +	/* +	 * Execute driver initialization on node where the device is +	 * attached.  This way the driver likely allocates its local memory +	 * on the right node. +	 */  	node = dev_to_node(&dev->dev); -	if (node >= 0) { + +	/* +	 * On NUMA systems, we are likely to call a PF probe function using +	 * work_on_cpu().  If that probe calls pci_enable_sriov() (which +	 * adds the VF devices via pci_bus_add_device()), we may re-enter +	 * this function to call the VF probe function.  Calling +	 * work_on_cpu() again will cause a lockdep warning.  Since VFs are +	 * always on the same node as the PF, we can work around this by +	 * avoiding work_on_cpu() when we're already on the correct node. +	 * +	 * Preemption is enabled, so it's theoretically unsafe to use +	 * numa_node_id(), but even if we run the probe function on the +	 * wrong node, it should be functionally correct. +	 */ +	if (node >= 0 && node != numa_node_id()) {  		int cpu;  		get_online_cpus(); @@ -294,6 +362,7 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,  		put_online_cpus();  	} else  		error = local_pci_probe(&ddi); +  	return error;  } @@ -301,12 +370,11 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,   * __pci_device_probe - check if a driver wants to claim a specific PCI device   * @drv: driver to call to check if it wants the PCI device   * @pci_dev: PCI device being probed - *  + *   * returns 0 on success, else error.   * side-effect: pci_dev->driver is set to drv when drv claims pci_dev.   */ -static int -__pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev) +static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)  {  	const struct pci_device_id *id;  	int error = 0; @@ -323,7 +391,7 @@ __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)  	return error;  } -static int pci_device_probe(struct device * dev) +static int pci_device_probe(struct device *dev)  {  	int error = 0;  	struct pci_driver *drv; @@ -339,10 +407,10 @@ static int pci_device_probe(struct device * dev)  	return error;  } -static int pci_device_remove(struct device * dev) +static int pci_device_remove(struct device *dev)  { -	struct pci_dev * pci_dev = to_pci_dev(dev); -	struct pci_driver * drv = pci_dev->driver; +	struct pci_dev *pci_dev = to_pci_dev(dev); +	struct pci_driver *drv = pci_dev->driver;  	if (drv) {  		if (drv->remove) { @@ -367,7 +435,7 @@ static int pci_device_remove(struct device * dev)  	 * We would love to complain here if pci_dev->is_enabled is set, that  	 * the driver should have called pci_disable_device(), but the  	 * unfortunate fact is there are too many odd BIOS and bridge setups -	 * that don't like drivers doing that all of the time.   +	 * that don't like drivers doing that all of the time.  	 * Oh well, we can dream of sane hardware when we sleep, no matter how  	 * horrible the crap we have to deal with is when we are awake...  	 */ @@ -388,12 +456,17 @@ static void pci_device_shutdown(struct device *dev)  	pci_msi_shutdown(pci_dev);  	pci_msix_shutdown(pci_dev); +#ifdef CONFIG_KEXEC  	/* -	 * Turn off Bus Master bit on the device to tell it to not -	 * continue to do DMA. Don't touch devices in D3cold or unknown states. +	 * If this is a kexec reboot, turn off Bus Master bit on the +	 * device to tell it to not continue to do DMA. Don't touch +	 * devices in D3cold or unknown states. +	 * If it is not a kexec reboot, firmware will hit the PCI +	 * devices with big hammer and stop their DMA any way.  	 */ -	if (pci_dev->current_state <= PCI_D3hot) +	if (kexec_in_progress && (pci_dev->current_state <= PCI_D3hot))  		pci_clear_master(pci_dev); +#endif  }  #ifdef CONFIG_PM @@ -465,8 +538,8 @@ static int pci_pm_reenable_device(struct pci_dev *pci_dev)  static int pci_legacy_suspend(struct device *dev, pm_message_t state)  { -	struct pci_dev * pci_dev = to_pci_dev(dev); -	struct pci_driver * drv = pci_dev->driver; +	struct pci_dev *pci_dev = to_pci_dev(dev); +	struct pci_driver *drv = pci_dev->driver;  	if (drv && drv->suspend) {  		pci_power_t prev = pci_dev->current_state; @@ -492,8 +565,8 @@ static int pci_legacy_suspend(struct device *dev, pm_message_t state)  static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)  { -	struct pci_dev * pci_dev = to_pci_dev(dev); -	struct pci_driver * drv = pci_dev->driver; +	struct pci_dev *pci_dev = to_pci_dev(dev); +	struct pci_driver *drv = pci_dev->driver;  	if (drv && drv->suspend_late) {  		pci_power_t prev = pci_dev->current_state; @@ -523,8 +596,8 @@ static int pci_legacy_suspend_late(struct device *dev, pm_message_t state)  static int pci_legacy_resume_early(struct device *dev)  { -	struct pci_dev * pci_dev = to_pci_dev(dev); -	struct pci_driver * drv = pci_dev->driver; +	struct pci_dev *pci_dev = to_pci_dev(dev); +	struct pci_driver *drv = pci_dev->driver;  	return drv && drv->resume_early ?  			drv->resume_early(pci_dev) : 0; @@ -532,8 +605,8 @@ static int pci_legacy_resume_early(struct device *dev)  static int pci_legacy_resume(struct device *dev)  { -	struct pci_dev * pci_dev = to_pci_dev(dev); -	struct pci_driver * drv = pci_dev->driver; +	struct pci_dev *pci_dev = to_pci_dev(dev); +	struct pci_driver *drv = pci_dev->driver;  	pci_fixup_device(pci_fixup_resume, pci_dev); @@ -547,14 +620,14 @@ static void pci_pm_default_resume(struct pci_dev *pci_dev)  {  	pci_fixup_device(pci_fixup_resume, pci_dev); -	if (!pci_is_bridge(pci_dev)) +	if (!pci_has_subordinate(pci_dev))  		pci_enable_wake(pci_dev, PCI_D0, false);  }  static void pci_pm_default_suspend(struct pci_dev *pci_dev)  {  	/* Disable non-bridge devices without PM support */ -	if (!pci_is_bridge(pci_dev)) +	if (!pci_has_subordinate(pci_dev))  		pci_disable_enabled_device(pci_dev);  } @@ -583,15 +656,11 @@ static int pci_pm_prepare(struct device *dev)  	int error = 0;  	/* -	 * PCI devices suspended at run time need to be resumed at this -	 * point, because in general it is necessary to reconfigure them for -	 * system suspend.  Namely, if the device is supposed to wake up the -	 * system from the sleep state, we may need to reconfigure it for this -	 * purpose.  In turn, if the device is not supposed to wake up the -	 * system from the sleep state, we'll have to prevent it from signaling -	 * wake-up. +	 * Devices having power.ignore_children set may still be necessary for +	 * suspending their children in the next phase of device suspend.  	 */ -	pm_runtime_resume(dev); +	if (dev->power.ignore_children) +		pm_runtime_resume(dev);  	if (drv && drv->pm && drv->pm->prepare)  		error = drv->pm->prepare(dev); @@ -599,18 +668,10 @@ static int pci_pm_prepare(struct device *dev)  	return error;  } -static void pci_pm_complete(struct device *dev) -{ -	struct device_driver *drv = dev->driver; - -	if (drv && drv->pm && drv->pm->complete) -		drv->pm->complete(dev); -}  #else /* !CONFIG_PM_SLEEP */  #define pci_pm_prepare	NULL -#define pci_pm_complete	NULL  #endif /* !CONFIG_PM_SLEEP */ @@ -629,6 +690,16 @@ static int pci_pm_suspend(struct device *dev)  		goto Fixup;  	} +	/* +	 * PCI devices suspended at run time need to be resumed at this point, +	 * because in general it is necessary to reconfigure them for system +	 * suspend.  Namely, if the device is supposed to wake up the system +	 * from the sleep state, we may need to reconfigure it for this purpose. +	 * In turn, if the device is not supposed to wake up the system from the +	 * sleep state, we'll have to prevent it from signaling wake-up. +	 */ +	pm_runtime_resume(dev); +  	pci_dev->state_saved = false;  	if (pm->suspend) {  		pci_power_t prev = pci_dev->current_state; @@ -686,7 +757,7 @@ static int pci_pm_suspend_noirq(struct device *dev)  	if (!pci_dev->state_saved) {  		pci_save_state(pci_dev); -		if (!pci_is_bridge(pci_dev)) +		if (!pci_has_subordinate(pci_dev))  			pci_prepare_to_sleep(pci_dev);  	} @@ -783,6 +854,14 @@ static int pci_pm_freeze(struct device *dev)  		return 0;  	} +	/* +	 * This used to be done in pci_pm_prepare() for all devices and some +	 * drivers may depend on it, so do it here.  Ideally, runtime-suspended +	 * devices should not be touched during freeze/thaw transitions, +	 * however. +	 */ +	pm_runtime_resume(dev); +  	pci_dev->state_saved = false;  	if (pm->freeze) {  		int error; @@ -890,6 +969,9 @@ static int pci_pm_poweroff(struct device *dev)  		goto Fixup;  	} +	/* The reason to do that is the same as in pci_pm_suspend(). */ +	pm_runtime_resume(dev); +  	pci_dev->state_saved = false;  	if (pm->poweroff) {  		int error; @@ -929,7 +1011,7 @@ static int pci_pm_poweroff_noirq(struct device *dev)  			return error;  	} -	if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) +	if (!pci_dev->state_saved && !pci_has_subordinate(pci_dev))  		pci_prepare_to_sleep(pci_dev);  	/* @@ -1121,9 +1203,8 @@ static int pci_pm_runtime_idle(struct device *dev)  #ifdef CONFIG_PM -const struct dev_pm_ops pci_dev_pm_ops = { +static const struct dev_pm_ops pci_dev_pm_ops = {  	.prepare = pci_pm_prepare, -	.complete = pci_pm_complete,  	.suspend = pci_pm_suspend,  	.resume = pci_pm_resume,  	.freeze = pci_pm_freeze, @@ -1154,10 +1235,10 @@ const struct dev_pm_ops pci_dev_pm_ops = {   * @drv: the driver structure to register   * @owner: owner module of drv   * @mod_name: module name string - *  + *   * Adds the driver structure to the list of registered drivers. - * Returns a negative value on error, otherwise 0.  - * If no error occurred, the driver remains registered even if  + * Returns a negative value on error, otherwise 0. + * If no error occurred, the driver remains registered even if   * no device was claimed during registration.   */  int __pci_register_driver(struct pci_driver *drv, struct module *owner, @@ -1175,23 +1256,24 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,  	/* register with core */  	return driver_register(&drv->driver);  } +EXPORT_SYMBOL(__pci_register_driver);  /**   * pci_unregister_driver - unregister a pci driver   * @drv: the driver structure to unregister - *  + *   * Deletes the driver structure from the list of registered PCI drivers,   * gives it a chance to clean up by calling its remove() function for   * each device it was responsible for, and marks those devices as   * driverless.   */ -void -pci_unregister_driver(struct pci_driver *drv) +void pci_unregister_driver(struct pci_driver *drv)  {  	driver_unregister(&drv->driver);  	pci_free_dynids(drv);  } +EXPORT_SYMBOL(pci_unregister_driver);  static struct pci_driver pci_compat_driver = {  	.name = "compat" @@ -1201,28 +1283,28 @@ static struct pci_driver pci_compat_driver = {   * pci_dev_driver - get the pci_driver of a device   * @dev: the device to query   * - * Returns the appropriate pci_driver structure or %NULL if there is no  + * Returns the appropriate pci_driver structure or %NULL if there is no   * registered driver for the device.   */ -struct pci_driver * -pci_dev_driver(const struct pci_dev *dev) +struct pci_driver *pci_dev_driver(const struct pci_dev *dev)  {  	if (dev->driver)  		return dev->driver;  	else {  		int i; -		for(i=0; i<=PCI_ROM_RESOURCE; i++) +		for (i = 0; i <= PCI_ROM_RESOURCE; i++)  			if (dev->resource[i].flags & IORESOURCE_BUSY)  				return &pci_compat_driver;  	}  	return NULL;  } +EXPORT_SYMBOL(pci_dev_driver);  /**   * pci_bus_match - Tell if a PCI device structure has a matching PCI device id structure   * @dev: the PCI device structure to match against   * @drv: the device driver to search for matching PCI device id structures - *  + *   * Used by a driver to check whether a PCI device present in the   * system is in its list of supported devices. Returns the matching   * pci_device_id structure or %NULL if there is no match. @@ -1262,6 +1344,7 @@ struct pci_dev *pci_dev_get(struct pci_dev *dev)  		get_device(&dev->dev);  	return dev;  } +EXPORT_SYMBOL(pci_dev_get);  /**   * pci_dev_put - release a use of the pci device structure @@ -1275,6 +1358,7 @@ void pci_dev_put(struct pci_dev *dev)  	if (dev)  		put_device(&dev->dev);  } +EXPORT_SYMBOL(pci_dev_put);  static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)  { @@ -1284,8 +1368,6 @@ static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)  		return -ENODEV;  	pdev = to_pci_dev(dev); -	if (!pdev) -		return -ENODEV;  	if (add_uevent_var(env, "PCI_CLASS=%04X", pdev->class))  		return -ENOMEM; @@ -1306,6 +1388,7 @@ static int pci_uevent(struct device *dev, struct kobj_uevent_env *env)  			   (u8)(pdev->class >> 16), (u8)(pdev->class >> 8),  			   (u8)(pdev->class)))  		return -ENOMEM; +  	return 0;  } @@ -1316,24 +1399,15 @@ struct bus_type pci_bus_type = {  	.probe		= pci_device_probe,  	.remove		= pci_device_remove,  	.shutdown	= pci_device_shutdown, -	.dev_attrs	= pci_dev_attrs, -	.bus_attrs	= pci_bus_attrs, -	.drv_attrs	= pci_drv_attrs, +	.dev_groups	= pci_dev_groups, +	.bus_groups	= pci_bus_groups, +	.drv_groups	= pci_drv_groups,  	.pm		= PCI_PM_OPS_PTR,  }; +EXPORT_SYMBOL(pci_bus_type);  static int __init pci_driver_init(void)  {  	return bus_register(&pci_bus_type);  } -  postcore_initcall(pci_driver_init); - -EXPORT_SYMBOL_GPL(pci_add_dynid); -EXPORT_SYMBOL(pci_match_id); -EXPORT_SYMBOL(__pci_register_driver); -EXPORT_SYMBOL(pci_unregister_driver); -EXPORT_SYMBOL(pci_dev_driver); -EXPORT_SYMBOL(pci_bus_type); -EXPORT_SYMBOL(pci_dev_get); -EXPORT_SYMBOL(pci_dev_put); diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index edaed6f4da6..a3fbe2012ea 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -29,35 +29,19 @@  #include <linux/nls.h>  #include <linux/acpi.h>  #include <linux/pci-acpi.h> -#include <acpi/acpi_bus.h>  #include "pci.h"  #define	DEVICE_LABEL_DSM	0x07 -#ifndef CONFIG_DMI - -static inline int -pci_create_smbiosname_file(struct pci_dev *pdev) -{ -	return -1; -} - -static inline void -pci_remove_smbiosname_file(struct pci_dev *pdev) -{ -} - -#else - +#ifdef CONFIG_DMI  enum smbios_attr_enum {  	SMBIOS_ATTR_NONE = 0,  	SMBIOS_ATTR_LABEL_SHOW,  	SMBIOS_ATTR_INSTANCE_SHOW,  }; -static size_t -find_smbios_instance_string(struct pci_dev *pdev, char *buf, -			    enum smbios_attr_enum attribute) +static size_t find_smbios_instance_string(struct pci_dev *pdev, char *buf, +					  enum smbios_attr_enum attribute)  {  	const struct dmi_device *dmi;  	struct dmi_dev_onboard *donboard; @@ -89,9 +73,8 @@ find_smbios_instance_string(struct pci_dev *pdev, char *buf,  	return 0;  } -static umode_t -smbios_instance_string_exist(struct kobject *kobj, struct attribute *attr, -			     int n) +static umode_t smbios_instance_string_exist(struct kobject *kobj, +					    struct attribute *attr, int n)  {  	struct device *dev;  	struct pci_dev *pdev; @@ -103,8 +86,8 @@ smbios_instance_string_exist(struct kobject *kobj, struct attribute *attr,  					   S_IRUGO : 0;  } -static ssize_t -smbioslabel_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t smbioslabel_show(struct device *dev, +				struct device_attribute *attr, char *buf)  {  	struct pci_dev *pdev;  	pdev = to_pci_dev(dev); @@ -113,9 +96,8 @@ smbioslabel_show(struct device *dev, struct device_attribute *attr, char *buf)  					   SMBIOS_ATTR_LABEL_SHOW);  } -static ssize_t -smbiosinstance_show(struct device *dev, -		    struct device_attribute *attr, char *buf) +static ssize_t smbiosinstance_show(struct device *dev, +				   struct device_attribute *attr, char *buf)  {  	struct pci_dev *pdev;  	pdev = to_pci_dev(dev); @@ -145,49 +127,33 @@ static struct attribute_group smbios_attr_group = {  	.is_visible = smbios_instance_string_exist,  }; -static int -pci_create_smbiosname_file(struct pci_dev *pdev) +static int pci_create_smbiosname_file(struct pci_dev *pdev)  {  	return sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group);  } -static void -pci_remove_smbiosname_file(struct pci_dev *pdev) +static void pci_remove_smbiosname_file(struct pci_dev *pdev)  {  	sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);  } - -#endif - -#ifndef CONFIG_ACPI - -static inline int -pci_create_acpi_index_label_files(struct pci_dev *pdev) -{ -	return -1; -} - -static inline int -pci_remove_acpi_index_label_files(struct pci_dev *pdev) +#else +static inline int pci_create_smbiosname_file(struct pci_dev *pdev)  {  	return -1;  } -static inline bool -device_has_dsm(struct device *dev) +static inline void pci_remove_smbiosname_file(struct pci_dev *pdev)  { -	return false;  } +#endif -#else - +#ifdef CONFIG_ACPI  static const char device_label_dsm_uuid[] = {  	0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,  	0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D  };  enum acpi_attr_enum { -	ACPI_ATTR_NONE = 0,  	ACPI_ATTR_LABEL_SHOW,  	ACPI_ATTR_INDEX_SHOW,  }; @@ -195,88 +161,64 @@ enum acpi_attr_enum {  static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)  {  	int len; -	len = utf16s_to_utf8s((const wchar_t *)obj-> -			      package.elements[1].string.pointer, -			      obj->package.elements[1].string.length, +	len = utf16s_to_utf8s((const wchar_t *)obj->string.pointer, +			      obj->string.length,  			      UTF16_LITTLE_ENDIAN,  			      buf, PAGE_SIZE);  	buf[len] = '\n';  } -static int -dsm_get_label(acpi_handle handle, int func, -	      struct acpi_buffer *output, -	      char *buf, enum acpi_attr_enum attribute) +static int dsm_get_label(struct device *dev, char *buf, +			 enum acpi_attr_enum attr)  { -	struct acpi_object_list input; -	union acpi_object params[4]; -	union acpi_object *obj; -	int len = 0; - -	int err; - -	input.count = 4; -	input.pointer = params; -	params[0].type = ACPI_TYPE_BUFFER; -	params[0].buffer.length = sizeof(device_label_dsm_uuid); -	params[0].buffer.pointer = (char *)device_label_dsm_uuid; -	params[1].type = ACPI_TYPE_INTEGER; -	params[1].integer.value = 0x02; -	params[2].type = ACPI_TYPE_INTEGER; -	params[2].integer.value = func; -	params[3].type = ACPI_TYPE_PACKAGE; -	params[3].package.count = 0; -	params[3].package.elements = NULL; - -	err = acpi_evaluate_object(handle, "_DSM", &input, output); -	if (err) +	acpi_handle handle; +	union acpi_object *obj, *tmp; +	int len = -1; + +	handle = ACPI_HANDLE(dev); +	if (!handle)  		return -1; -	obj = (union acpi_object *)output->pointer; - -	switch (obj->type) { -	case ACPI_TYPE_PACKAGE: -		if (obj->package.count != 2) -			break; -		len = obj->package.elements[0].integer.value; -		if (buf) { -			if (attribute == ACPI_ATTR_INDEX_SHOW) -				scnprintf(buf, PAGE_SIZE, "%llu\n", -				obj->package.elements[0].integer.value); -			else if (attribute == ACPI_ATTR_LABEL_SHOW) -				dsm_label_utf16s_to_utf8s(obj, buf); -			kfree(output->pointer); -			return strlen(buf); -		} -		kfree(output->pointer); -		return len; -	break; -	default: -		kfree(output->pointer); +	obj = acpi_evaluate_dsm(handle, device_label_dsm_uuid, 0x2, +				DEVICE_LABEL_DSM, NULL); +	if (!obj) +		return -1; + +	tmp = obj->package.elements; +	if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 2 && +	    tmp[0].type == ACPI_TYPE_INTEGER && +	    tmp[1].type == ACPI_TYPE_STRING) { +		/* +		 * The second string element is optional even when +		 * this _DSM is implemented; when not implemented, +		 * this entry must return a null string. +		 */ +		if (attr == ACPI_ATTR_INDEX_SHOW) +			scnprintf(buf, PAGE_SIZE, "%llu\n", tmp->integer.value); +		else if (attr == ACPI_ATTR_LABEL_SHOW) +			dsm_label_utf16s_to_utf8s(tmp + 1, buf); +		len = strlen(buf) > 0 ? strlen(buf) : -1;  	} -	return -1; + +	ACPI_FREE(obj); + +	return len;  } -static bool -device_has_dsm(struct device *dev) +static bool device_has_dsm(struct device *dev)  {  	acpi_handle handle; -	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; - -	handle = DEVICE_ACPI_HANDLE(dev); +	handle = ACPI_HANDLE(dev);  	if (!handle) -		return FALSE; +		return false; -	if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL, -			  ACPI_ATTR_NONE) > 0) -		return TRUE; - -	return FALSE; +	return !!acpi_check_dsm(handle, device_label_dsm_uuid, 0x2, +				1 << DEVICE_LABEL_DSM);  } -static umode_t -acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n) +static umode_t acpi_index_string_exist(struct kobject *kobj, +				       struct attribute *attr, int n)  {  	struct device *dev; @@ -288,47 +230,16 @@ acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n)  	return 0;  } -static ssize_t -acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t acpilabel_show(struct device *dev, +			      struct device_attribute *attr, char *buf)  { -	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; -	acpi_handle handle; -	int length; - -	handle = DEVICE_ACPI_HANDLE(dev); - -	if (!handle) -		return -1; - -	length = dsm_get_label(handle, DEVICE_LABEL_DSM, -			       &output, buf, ACPI_ATTR_LABEL_SHOW); - -	if (length < 1) -		return -1; - -	return length; +	return dsm_get_label(dev, buf, ACPI_ATTR_LABEL_SHOW);  } -static ssize_t -acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t acpiindex_show(struct device *dev, +			      struct device_attribute *attr, char *buf)  { -	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; -	acpi_handle handle; -	int length; - -	handle = DEVICE_ACPI_HANDLE(dev); - -	if (!handle) -		return -1; - -	length = dsm_get_label(handle, DEVICE_LABEL_DSM, -			       &output, buf, ACPI_ATTR_INDEX_SHOW); - -	if (length < 0) -		return -1; - -	return length; - +	return dsm_get_label(dev, buf, ACPI_ATTR_INDEX_SHOW);  }  static struct device_attribute acpi_attr_label = { @@ -352,18 +263,31 @@ static struct attribute_group acpi_attr_group = {  	.is_visible = acpi_index_string_exist,  }; -static int -pci_create_acpi_index_label_files(struct pci_dev *pdev) +static int pci_create_acpi_index_label_files(struct pci_dev *pdev)  {  	return sysfs_create_group(&pdev->dev.kobj, &acpi_attr_group);  } -static int -pci_remove_acpi_index_label_files(struct pci_dev *pdev) +static int pci_remove_acpi_index_label_files(struct pci_dev *pdev)  {  	sysfs_remove_group(&pdev->dev.kobj, &acpi_attr_group);  	return 0;  } +#else +static inline int pci_create_acpi_index_label_files(struct pci_dev *pdev) +{ +	return -1; +} + +static inline int pci_remove_acpi_index_label_files(struct pci_dev *pdev) +{ +	return -1; +} + +static inline bool device_has_dsm(struct device *dev) +{ +	return false; +}  #endif  void pci_create_firmware_label_files(struct pci_dev *pdev) diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c index 6e47c519c51..886fb357027 100644 --- a/drivers/pci/pci-stub.c +++ b/drivers/pci/pci-stub.c @@ -2,13 +2,13 @@   *   * Copyright (C) 2008 Red Hat, Inc.   * Author: - * 	Chris Wright + *	Chris Wright   *   * This work is licensed under the terms of the GNU GPL, version 2.   *   * Usage is simple, allocate a new id to the stub driver and bind the   * device to it.  For example: - *  + *   * # echo "8086 10f5" > /sys/bus/pci/drivers/pci-stub/new_id   * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind   * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/pci-stub/bind @@ -55,7 +55,7 @@ static int __init pci_stub_init(void)  	p = ids;  	while ((id = strsep(&p, ","))) {  		unsigned int vendor, device, subvendor = PCI_ANY_ID, -			subdevice = PCI_ANY_ID, class=0, class_mask=0; +			subdevice = PCI_ANY_ID, class = 0, class_mask = 0;  		int fields;  		if (!strlen(id)) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 7128cfdd64a..9ff0a901ecf 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -10,7 +10,7 @@   *   * File attributes for PCI devices   * - * Modeled after usb's driverfs.c  + * Modeled after usb's driverfs.c   *   */ @@ -29,6 +29,7 @@  #include <linux/slab.h>  #include <linux/vgaarb.h>  #include <linux/pm_runtime.h> +#include <linux/of.h>  #include "pci.h"  static int sysfs_initialized;	/* = 0 */ @@ -40,9 +41,10 @@ field##_show(struct device *dev, struct device_attribute *attr, char *buf)				\  {									\  	struct pci_dev *pdev;						\  									\ -	pdev = to_pci_dev (dev);					\ -	return sprintf (buf, format_string, pdev->field);		\ -} +	pdev = to_pci_dev(dev);						\ +	return sprintf(buf, format_string, pdev->field);		\ +}									\ +static DEVICE_ATTR_RO(field)  pci_config_attr(vendor, "0x%04x\n");  pci_config_attr(device, "0x%04x\n"); @@ -56,7 +58,7 @@ static ssize_t broken_parity_status_show(struct device *dev,  					 char *buf)  {  	struct pci_dev *pdev = to_pci_dev(dev); -	return sprintf (buf, "%u\n", pdev->broken_parity_status); +	return sprintf(buf, "%u\n", pdev->broken_parity_status);  }  static ssize_t broken_parity_status_store(struct device *dev, @@ -73,10 +75,11 @@ static ssize_t broken_parity_status_store(struct device *dev,  	return count;  } +static DEVICE_ATTR_RW(broken_parity_status); -static ssize_t local_cpus_show(struct device *dev, -			struct device_attribute *attr, char *buf) -{		 +static ssize_t pci_dev_show_local_cpu(struct device *dev, int type, +				      struct device_attribute *attr, char *buf) +{  	const struct cpumask *mask;  	int len; @@ -86,36 +89,33 @@ static ssize_t local_cpus_show(struct device *dev,  #else  	mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);  #endif -	len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask); +	len = type ? +		cpumask_scnprintf(buf, PAGE_SIZE-2, mask) : +		cpulist_scnprintf(buf, PAGE_SIZE-2, mask); +  	buf[len++] = '\n';  	buf[len] = '\0';  	return len;  } +static ssize_t local_cpus_show(struct device *dev, +			       struct device_attribute *attr, char *buf) +{ +	return pci_dev_show_local_cpu(dev, 1, attr, buf); +} +static DEVICE_ATTR_RO(local_cpus);  static ssize_t local_cpulist_show(struct device *dev, -			struct device_attribute *attr, char *buf) +				  struct device_attribute *attr, char *buf)  { -	const struct cpumask *mask; -	int len; - -#ifdef CONFIG_NUMA -	mask = (dev_to_node(dev) == -1) ? cpu_online_mask : -					  cpumask_of_node(dev_to_node(dev)); -#else -	mask = cpumask_of_pcibus(to_pci_dev(dev)->bus); -#endif -	len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask); -	buf[len++] = '\n'; -	buf[len] = '\0'; -	return len; +	return pci_dev_show_local_cpu(dev, 0, attr, buf);  } +static DEVICE_ATTR_RO(local_cpulist);  /*   * PCI Bus Class Devices   */ -static ssize_t pci_bus_show_cpuaffinity(struct device *dev, -					int type, +static ssize_t pci_bus_show_cpuaffinity(struct device *dev, int type,  					struct device_attribute *attr,  					char *buf)  { @@ -146,11 +146,11 @@ static ssize_t cpulistaffinity_show(struct device *dev,  static DEVICE_ATTR_RO(cpulistaffinity);  /* show resources */ -static ssize_t -resource_show(struct device * dev, struct device_attribute *attr, char * buf) +static ssize_t resource_show(struct device *dev, struct device_attribute *attr, +			     char *buf)  { -	struct pci_dev * pci_dev = to_pci_dev(dev); -	char * str = buf; +	struct pci_dev *pci_dev = to_pci_dev(dev); +	char *str = buf;  	int i;  	int max;  	resource_size_t start, end; @@ -163,15 +163,17 @@ resource_show(struct device * dev, struct device_attribute *attr, char * buf)  	for (i = 0; i < max; i++) {  		struct resource *res =  &pci_dev->resource[i];  		pci_resource_to_user(pci_dev, i, res, &start, &end); -		str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n", +		str += sprintf(str, "0x%016llx 0x%016llx 0x%016llx\n",  			       (unsigned long long)start,  			       (unsigned long long)end,  			       (unsigned long long)res->flags);  	}  	return (str - buf);  } +static DEVICE_ATTR_RO(resource); -static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, +			     char *buf)  {  	struct pci_dev *pci_dev = to_pci_dev(dev); @@ -181,10 +183,10 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,  		       (u8)(pci_dev->class >> 16), (u8)(pci_dev->class >> 8),  		       (u8)(pci_dev->class));  } +static DEVICE_ATTR_RO(modalias); -static ssize_t is_enabled_store(struct device *dev, -				struct device_attribute *attr, const char *buf, -				size_t count) +static ssize_t enabled_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; @@ -208,53 +210,56 @@ static ssize_t is_enabled_store(struct device *dev,  	return result < 0 ? result : count;  } -static ssize_t is_enabled_show(struct device *dev, -			       struct device_attribute *attr, char *buf) +static ssize_t enabled_show(struct device *dev, struct device_attribute *attr, +			    char *buf)  {  	struct pci_dev *pdev; -	pdev = to_pci_dev (dev); -	return sprintf (buf, "%u\n", atomic_read(&pdev->enable_cnt)); +	pdev = to_pci_dev(dev); +	return sprintf(buf, "%u\n", atomic_read(&pdev->enable_cnt));  } +static DEVICE_ATTR_RW(enabled);  #ifdef CONFIG_NUMA -static ssize_t -numa_node_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t numa_node_show(struct device *dev, struct device_attribute *attr, +			      char *buf)  { -	return sprintf (buf, "%d\n", dev->numa_node); +	return sprintf(buf, "%d\n", dev->numa_node);  } +static DEVICE_ATTR_RO(numa_node);  #endif -static ssize_t -dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t dma_mask_bits_show(struct device *dev, +				  struct device_attribute *attr, char *buf)  {  	struct pci_dev *pdev = to_pci_dev(dev); -	return sprintf (buf, "%d\n", fls64(pdev->dma_mask)); +	return sprintf(buf, "%d\n", fls64(pdev->dma_mask));  } +static DEVICE_ATTR_RO(dma_mask_bits); -static ssize_t -consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr, -				 char *buf) +static ssize_t consistent_dma_mask_bits_show(struct device *dev, +					     struct device_attribute *attr, +					     char *buf)  { -	return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask)); +	return sprintf(buf, "%d\n", fls64(dev->coherent_dma_mask));  } +static DEVICE_ATTR_RO(consistent_dma_mask_bits); -static ssize_t -msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t msi_bus_show(struct device *dev, struct device_attribute *attr, +			    char *buf)  {  	struct pci_dev *pdev = to_pci_dev(dev);  	if (!pdev->subordinate)  		return 0; -	return sprintf (buf, "%u\n", -			!(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI)); +	return sprintf(buf, "%u\n", +		       !(pdev->subordinate->bus_flags & PCI_BUS_FLAGS_NO_MSI));  } -static ssize_t -msi_bus_store(struct device *dev, struct device_attribute *attr, -	      const char *buf, size_t count) +static ssize_t msi_bus_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; @@ -262,13 +267,17 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,  	if (kstrtoul(buf, 0, &val) < 0)  		return -EINVAL; -	/* bad things may happen if the no_msi flag is changed -	 * while some drivers are loaded */ +	/* +	 * Bad things may happen if the no_msi flag is changed +	 * while drivers are loaded. +	 */  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; -	/* Maybe pci devices without subordinate busses shouldn't even have this -	 * attribute in the first place?  */ +	/* +	 * Maybe devices without subordinate buses shouldn't have this +	 * attribute in the first place? +	 */  	if (!pdev->subordinate)  		return count; @@ -277,14 +286,14 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,  	    !!val) {  		pdev->subordinate->bus_flags ^= PCI_BUS_FLAGS_NO_MSI; -		dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI," -			 " bad things could happen\n", val ? "" : " not"); +		dev_warn(&pdev->dev, "forced subordinate bus to%s support MSI, bad things could happen\n", +			 val ? "" : " not");  	}  	return count;  } +static DEVICE_ATTR_RW(msi_bus); -static DEFINE_MUTEX(pci_remove_rescan_mutex);  static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,  				size_t count)  { @@ -295,22 +304,32 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,  		return -EINVAL;  	if (val) { -		mutex_lock(&pci_remove_rescan_mutex); +		pci_lock_rescan_remove();  		while ((b = pci_find_next_bus(b)) != NULL)  			pci_rescan_bus(b); -		mutex_unlock(&pci_remove_rescan_mutex); +		pci_unlock_rescan_remove();  	}  	return count;  } +static BUS_ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store); + +static struct attribute *pci_bus_attrs[] = { +	&bus_attr_rescan.attr, +	NULL, +}; -struct bus_attribute pci_bus_attrs[] = { -	__ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, bus_rescan_store), -	__ATTR_NULL +static const struct attribute_group pci_bus_group = { +	.attrs = pci_bus_attrs, +}; + +const struct attribute_group *pci_bus_groups[] = { +	&pci_bus_group, +	NULL,  }; -static ssize_t -dev_rescan_store(struct device *dev, struct device_attribute *attr, -		 const char *buf, size_t count) +static ssize_t dev_rescan_store(struct device *dev, +				struct device_attribute *attr, const char *buf, +				size_t count)  {  	unsigned long val;  	struct pci_dev *pdev = to_pci_dev(dev); @@ -319,49 +338,35 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr,  		return -EINVAL;  	if (val) { -		mutex_lock(&pci_remove_rescan_mutex); +		pci_lock_rescan_remove();  		pci_rescan_bus(pdev->bus); -		mutex_unlock(&pci_remove_rescan_mutex); +		pci_unlock_rescan_remove();  	}  	return count;  } -struct device_attribute dev_rescan_attr = __ATTR(rescan, (S_IWUSR|S_IWGRP), -						 NULL, dev_rescan_store); - -static void remove_callback(struct device *dev) -{ -	struct pci_dev *pdev = to_pci_dev(dev); - -	mutex_lock(&pci_remove_rescan_mutex); -	pci_stop_and_remove_bus_device(pdev); -	mutex_unlock(&pci_remove_rescan_mutex); -} +static struct device_attribute dev_rescan_attr = __ATTR(rescan, +							(S_IWUSR|S_IWGRP), +							NULL, dev_rescan_store); -static ssize_t -remove_store(struct device *dev, struct device_attribute *dummy, -	     const char *buf, size_t count) +static ssize_t remove_store(struct device *dev, struct device_attribute *attr, +			    const char *buf, size_t count)  { -	int ret = 0;  	unsigned long val;  	if (kstrtoul(buf, 0, &val) < 0)  		return -EINVAL; -	/* An attribute cannot be unregistered by one of its own methods, -	 * so we have to use this roundabout approach. -	 */ -	if (val) -		ret = device_schedule_callback(dev, remove_callback); -	if (ret) -		count = ret; +	if (val && device_remove_file_self(dev, attr)) +		pci_stop_and_remove_bus_device_locked(to_pci_dev(dev));  	return count;  } -struct device_attribute dev_remove_attr = __ATTR(remove, (S_IWUSR|S_IWGRP), -						 NULL, remove_store); +static struct device_attribute dev_remove_attr = __ATTR(remove, +							(S_IWUSR|S_IWGRP), +							NULL, remove_store); -static ssize_t -dev_bus_rescan_store(struct device *dev, struct device_attribute *attr, -		 const char *buf, size_t count) +static ssize_t dev_bus_rescan_store(struct device *dev, +				    struct device_attribute *attr, +				    const char *buf, size_t count)  {  	unsigned long val;  	struct pci_bus *bus = to_pci_bus(dev); @@ -370,12 +375,12 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,  		return -EINVAL;  	if (val) { -		mutex_lock(&pci_remove_rescan_mutex); +		pci_lock_rescan_remove();  		if (!pci_is_root_bus(bus) && list_empty(&bus->devices))  			pci_rescan_bus_bridge_resize(bus->self);  		else  			pci_rescan_bus(bus); -		mutex_unlock(&pci_remove_rescan_mutex); +		pci_unlock_rescan_remove();  	}  	return count;  } @@ -402,8 +407,23 @@ 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); +	return sprintf(buf, "%u\n", pdev->d3cold_allowed);  } +static DEVICE_ATTR_RW(d3cold_allowed); +#endif + +#ifdef CONFIG_OF +static ssize_t devspec_show(struct device *dev, +			    struct device_attribute *attr, char *buf) +{ +	struct pci_dev *pdev = to_pci_dev(dev); +	struct device_node *np = pci_device_to_OF_node(pdev); + +	if (np == NULL || np->full_name == NULL) +		return 0; +	return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR_RO(devspec);  #endif  #ifdef CONFIG_PCI_IOV @@ -489,30 +509,81 @@ static struct device_attribute sriov_numvfs_attr =  		       sriov_numvfs_show, sriov_numvfs_store);  #endif /* CONFIG_PCI_IOV */ -struct device_attribute pci_dev_attrs[] = { -	__ATTR_RO(resource), -	__ATTR_RO(vendor), -	__ATTR_RO(device), -	__ATTR_RO(subsystem_vendor), -	__ATTR_RO(subsystem_device), -	__ATTR_RO(class), -	__ATTR_RO(irq), -	__ATTR_RO(local_cpus), -	__ATTR_RO(local_cpulist), -	__ATTR_RO(modalias), +static ssize_t driver_override_store(struct device *dev, +				     struct device_attribute *attr, +				     const char *buf, size_t count) +{ +	struct pci_dev *pdev = to_pci_dev(dev); +	char *driver_override, *old = pdev->driver_override, *cp; + +	if (count > PATH_MAX) +		return -EINVAL; + +	driver_override = kstrndup(buf, count, GFP_KERNEL); +	if (!driver_override) +		return -ENOMEM; + +	cp = strchr(driver_override, '\n'); +	if (cp) +		*cp = '\0'; + +	if (strlen(driver_override)) { +		pdev->driver_override = driver_override; +	} else { +		kfree(driver_override); +		pdev->driver_override = NULL; +	} + +	kfree(old); + +	return count; +} + +static ssize_t driver_override_show(struct device *dev, +				    struct device_attribute *attr, char *buf) +{ +	struct pci_dev *pdev = to_pci_dev(dev); + +	return sprintf(buf, "%s\n", pdev->driver_override); +} +static DEVICE_ATTR_RW(driver_override); + +static struct attribute *pci_dev_attrs[] = { +	&dev_attr_resource.attr, +	&dev_attr_vendor.attr, +	&dev_attr_device.attr, +	&dev_attr_subsystem_vendor.attr, +	&dev_attr_subsystem_device.attr, +	&dev_attr_class.attr, +	&dev_attr_irq.attr, +	&dev_attr_local_cpus.attr, +	&dev_attr_local_cpulist.attr, +	&dev_attr_modalias.attr,  #ifdef CONFIG_NUMA -	__ATTR_RO(numa_node), +	&dev_attr_numa_node.attr,  #endif -	__ATTR_RO(dma_mask_bits), -	__ATTR_RO(consistent_dma_mask_bits), -	__ATTR(enable, 0600, is_enabled_show, is_enabled_store), -	__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR), -		broken_parity_status_show,broken_parity_status_store), -	__ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store), +	&dev_attr_dma_mask_bits.attr, +	&dev_attr_consistent_dma_mask_bits.attr, +	&dev_attr_enabled.attr, +	&dev_attr_broken_parity_status.attr, +	&dev_attr_msi_bus.attr,  #if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI) -	__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store), +	&dev_attr_d3cold_allowed.attr,  #endif -	__ATTR_NULL, +#ifdef CONFIG_OF +	&dev_attr_devspec.attr, +#endif +	&dev_attr_driver_override.attr, +	NULL, +}; + +static const struct attribute_group pci_dev_group = { +	.attrs = pci_dev_attrs, +}; + +const struct attribute_group *pci_dev_groups[] = { +	&pci_dev_group, +	NULL,  };  static struct attribute *pcibus_attrs[] = { @@ -531,8 +602,8 @@ const struct attribute_group *pcibus_groups[] = {  	NULL,  }; -static ssize_t -boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t boot_vga_show(struct device *dev, struct device_attribute *attr, +			     char *buf)  {  	struct pci_dev *pdev = to_pci_dev(dev);  	struct pci_dev *vga_dev = vga_default_device(); @@ -544,24 +615,23 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)  		!!(pdev->resource[PCI_ROM_RESOURCE].flags &  		   IORESOURCE_ROM_SHADOW));  } -struct device_attribute vga_attr = __ATTR_RO(boot_vga); +static struct device_attribute vga_attr = __ATTR_RO(boot_vga); -static ssize_t -pci_read_config(struct file *filp, struct kobject *kobj, -		struct bin_attribute *bin_attr, -		char *buf, loff_t off, size_t count) +static ssize_t pci_read_config(struct file *filp, struct kobject *kobj, +			       struct bin_attribute *bin_attr, char *buf, +			       loff_t off, size_t count)  { -	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); +	struct pci_dev *dev = to_pci_dev(container_of(kobj, struct device, +						      kobj));  	unsigned int size = 64;  	loff_t init_off = off; -	u8 *data = (u8*) buf; +	u8 *data = (u8 *) buf;  	/* Several chips lock up trying to read undefined config space */ -	if (security_capable(filp->f_cred, &init_user_ns, CAP_SYS_ADMIN) == 0) { +	if (security_capable(filp->f_cred, &init_user_ns, CAP_SYS_ADMIN) == 0)  		size = dev->cfg_size; -	} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { +	else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)  		size = 128; -	}  	if (off > size)  		return 0; @@ -624,15 +694,15 @@ pci_read_config(struct file *filp, struct kobject *kobj,  	return count;  } -static ssize_t -pci_write_config(struct file* filp, struct kobject *kobj, -		 struct bin_attribute *bin_attr, -		 char *buf, loff_t off, size_t count) +static ssize_t pci_write_config(struct file *filp, struct kobject *kobj, +				struct bin_attribute *bin_attr, char *buf, +				loff_t off, size_t count)  { -	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj)); +	struct pci_dev *dev = to_pci_dev(container_of(kobj, struct device, +						      kobj));  	unsigned int size = count;  	loff_t init_off = off; -	u8 *data = (u8*) buf; +	u8 *data = (u8 *) buf;  	if (off > dev->cfg_size)  		return 0; @@ -640,7 +710,7 @@ pci_write_config(struct file* filp, struct kobject *kobj,  		size = dev->cfg_size - off;  		count = size;  	} -	 +  	pci_config_pm_runtime_get(dev);  	if ((off & 1) && size) { @@ -648,14 +718,14 @@ pci_write_config(struct file* filp, struct kobject *kobj,  		off++;  		size--;  	} -	 +  	if ((off & 3) && size > 2) {  		u16 val = data[off - init_off];  		val |= (u16) data[off - init_off + 1] << 8; -                pci_user_write_config_word(dev, off, val); -                off += 2; -                size -= 2; -        } +		pci_user_write_config_word(dev, off, val); +		off += 2; +		size -= 2; +	}  	while (size > 3) {  		u32 val = data[off - init_off]; @@ -666,7 +736,7 @@ pci_write_config(struct file* filp, struct kobject *kobj,  		off += 4;  		size -= 4;  	} -	 +  	if (size >= 2) {  		u16 val = data[off - init_off];  		val |= (u16) data[off - init_off + 1] << 8; @@ -686,10 +756,9 @@ pci_write_config(struct file* filp, struct kobject *kobj,  	return count;  } -static ssize_t -read_vpd_attr(struct file *filp, struct kobject *kobj, -	      struct bin_attribute *bin_attr, -	      char *buf, loff_t off, size_t count) +static ssize_t read_vpd_attr(struct file *filp, struct kobject *kobj, +			     struct bin_attribute *bin_attr, char *buf, +			     loff_t off, size_t count)  {  	struct pci_dev *dev =  		to_pci_dev(container_of(kobj, struct device, kobj)); @@ -702,10 +771,9 @@ read_vpd_attr(struct file *filp, struct kobject *kobj,  	return pci_read_vpd(dev, off, count, buf);  } -static ssize_t -write_vpd_attr(struct file *filp, struct kobject *kobj, -	       struct bin_attribute *bin_attr, -	       char *buf, loff_t off, size_t count) +static ssize_t write_vpd_attr(struct file *filp, struct kobject *kobj, +			      struct bin_attribute *bin_attr, char *buf, +			      loff_t off, size_t count)  {  	struct pci_dev *dev =  		to_pci_dev(container_of(kobj, struct device, kobj)); @@ -731,20 +799,18 @@ write_vpd_attr(struct file *filp, struct kobject *kobj,   * Reads 1, 2, or 4 bytes from legacy I/O port space using an arch specific   * callback routine (pci_legacy_read).   */ -static ssize_t -pci_read_legacy_io(struct file *filp, struct kobject *kobj, -		   struct bin_attribute *bin_attr, -		   char *buf, loff_t off, size_t count) +static ssize_t pci_read_legacy_io(struct file *filp, struct kobject *kobj, +				  struct bin_attribute *bin_attr, char *buf, +				  loff_t off, size_t count)  { -        struct pci_bus *bus = to_pci_bus(container_of(kobj, -                                                      struct device, +	struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,  						      kobj)); -        /* Only support 1, 2 or 4 byte accesses */ -        if (count != 1 && count != 2 && count != 4) -                return -EINVAL; +	/* Only support 1, 2 or 4 byte accesses */ +	if (count != 1 && count != 2 && count != 4) +		return -EINVAL; -        return pci_legacy_read(bus, off, (u32 *)buf, count); +	return pci_legacy_read(bus, off, (u32 *)buf, count);  }  /** @@ -759,19 +825,18 @@ pci_read_legacy_io(struct file *filp, struct kobject *kobj,   * Writes 1, 2, or 4 bytes from legacy I/O port space using an arch specific   * callback routine (pci_legacy_write).   */ -static ssize_t -pci_write_legacy_io(struct file *filp, struct kobject *kobj, -		    struct bin_attribute *bin_attr, -		    char *buf, loff_t off, size_t count) +static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj, +				   struct bin_attribute *bin_attr, char *buf, +				   loff_t off, size_t count)  { -        struct pci_bus *bus = to_pci_bus(container_of(kobj, -						      struct device, +	struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,  						      kobj)); -        /* Only support 1, 2 or 4 byte accesses */ -        if (count != 1 && count != 2 && count != 4) -                return -EINVAL; -        return pci_legacy_write(bus, off, *(u32 *)buf, count); +	/* Only support 1, 2 or 4 byte accesses */ +	if (count != 1 && count != 2 && count != 4) +		return -EINVAL; + +	return pci_legacy_write(bus, off, *(u32 *)buf, count);  }  /** @@ -785,16 +850,14 @@ pci_write_legacy_io(struct file *filp, struct kobject *kobj,   * legacy memory space (first meg of bus space) into application virtual   * memory space.   */ -static int -pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj, -		    struct bin_attribute *attr, -                    struct vm_area_struct *vma) +static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj, +			       struct bin_attribute *attr, +			       struct vm_area_struct *vma)  { -        struct pci_bus *bus = to_pci_bus(container_of(kobj, -                                                      struct device, +	struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,  						      kobj)); -        return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem); +	return pci_mmap_legacy_page_range(bus, vma, pci_mmap_mem);  }  /** @@ -808,16 +871,14 @@ pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,   * legacy IO space (first meg of bus space) into application virtual   * memory space. Returns -ENOSYS if the operation isn't supported   */ -static int -pci_mmap_legacy_io(struct file *filp, struct kobject *kobj, -		   struct bin_attribute *attr, -		   struct vm_area_struct *vma) +static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj, +			      struct bin_attribute *attr, +			      struct vm_area_struct *vma)  { -        struct pci_bus *bus = to_pci_bus(container_of(kobj, -                                                      struct device, +	struct pci_bus *bus = to_pci_bus(container_of(kobj, struct device,  						      kobj)); -        return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io); +	return pci_mmap_legacy_page_range(bus, vma, pci_mmap_io);  }  /** @@ -827,10 +888,9 @@ pci_mmap_legacy_io(struct file *filp, struct kobject *kobj,   *   * Stub implementation. Can be overridden by arch if necessary.   */ -void __weak -pci_adjust_legacy_attr(struct pci_bus *b, enum pci_mmap_state mmap_type) +void __weak pci_adjust_legacy_attr(struct pci_bus *b, +				   enum pci_mmap_state mmap_type)  { -	return;  }  /** @@ -885,8 +945,7 @@ legacy_io_err:  	kfree(b->legacy_io);  	b->legacy_io = NULL;  kzalloc_err: -	printk(KERN_WARNING "pci: warning: could not create legacy I/O port " -	       "and ISA memory resources to sysfs\n"); +	printk(KERN_WARNING "pci: warning: could not create legacy I/O port and ISA memory resources to sysfs\n");  	return;  } @@ -929,9 +988,8 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,   *   * Use the regular PCI mapping routines to map a PCI resource into userspace.   */ -static int -pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, -		  struct vm_area_struct *vma, int write_combine) +static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr, +			     struct vm_area_struct *vma, int write_combine)  {  	struct pci_dev *pdev = to_pci_dev(container_of(kobj,  						       struct device, kobj)); @@ -947,8 +1005,7 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,  		return -ENODEV;  	if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) { -		WARN(1, "process \"%s\" tried to map 0x%08lx bytes " -			"at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n", +		WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",  			current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,  			pci_name(pdev), i,  			(u64)pci_resource_start(pdev, i), @@ -970,26 +1027,23 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,  	return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);  } -static int -pci_mmap_resource_uc(struct file *filp, struct kobject *kobj, -		     struct bin_attribute *attr, -		     struct vm_area_struct *vma) +static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj, +				struct bin_attribute *attr, +				struct vm_area_struct *vma)  {  	return pci_mmap_resource(kobj, attr, vma, 0);  } -static int -pci_mmap_resource_wc(struct file *filp, struct kobject *kobj, -		     struct bin_attribute *attr, -		     struct vm_area_struct *vma) +static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj, +				struct bin_attribute *attr, +				struct vm_area_struct *vma)  {  	return pci_mmap_resource(kobj, attr, vma, 1);  } -static ssize_t -pci_resource_io(struct file *filp, struct kobject *kobj, -		struct bin_attribute *attr, char *buf, -		loff_t off, size_t count, bool write) +static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj, +			       struct bin_attribute *attr, char *buf, +			       loff_t off, size_t count, bool write)  {  	struct pci_dev *pdev = to_pci_dev(container_of(kobj,  						       struct device, kobj)); @@ -1034,18 +1088,16 @@ pci_resource_io(struct file *filp, struct kobject *kobj,  	return -EINVAL;  } -static ssize_t -pci_read_resource_io(struct file *filp, struct kobject *kobj, -		     struct bin_attribute *attr, char *buf, -		     loff_t off, size_t count) +static ssize_t pci_read_resource_io(struct file *filp, struct kobject *kobj, +				    struct bin_attribute *attr, char *buf, +				    loff_t off, size_t count)  {  	return pci_resource_io(filp, kobj, attr, buf, off, count, false);  } -static ssize_t -pci_write_resource_io(struct file *filp, struct kobject *kobj, -		      struct bin_attribute *attr, char *buf, -		      loff_t off, size_t count) +static ssize_t pci_write_resource_io(struct file *filp, struct kobject *kobj, +				     struct bin_attribute *attr, char *buf, +				     loff_t off, size_t count)  {  	return pci_resource_io(filp, kobj, attr, buf, off, count, true);  } @@ -1057,8 +1109,7 @@ pci_write_resource_io(struct file *filp, struct kobject *kobj,   * If we created resource files for @pdev, remove them from sysfs and   * free their resources.   */ -static void -pci_remove_resource_files(struct pci_dev *pdev) +static void pci_remove_resource_files(struct pci_dev *pdev)  {  	int i; @@ -1161,10 +1212,9 @@ void __weak pci_remove_resource_files(struct pci_dev *dev) { return; }   *   * writing anything except 0 enables it   */ -static ssize_t -pci_write_rom(struct file *filp, struct kobject *kobj, -	      struct bin_attribute *bin_attr, -	      char *buf, loff_t off, size_t count) +static ssize_t pci_write_rom(struct file *filp, struct kobject *kobj, +			     struct bin_attribute *bin_attr, char *buf, +			     loff_t off, size_t count)  {  	struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj)); @@ -1188,10 +1238,9 @@ pci_write_rom(struct file *filp, struct kobject *kobj,   * Put @count bytes starting at @off into @buf from the ROM in the PCI   * device corresponding to @kobj.   */ -static ssize_t -pci_read_rom(struct file *filp, struct kobject *kobj, -	     struct bin_attribute *bin_attr, -	     char *buf, loff_t off, size_t count) +static ssize_t pci_read_rom(struct file *filp, struct kobject *kobj, +			    struct bin_attribute *bin_attr, char *buf, +			    loff_t off, size_t count)  {  	struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));  	void __iomem *rom; @@ -1199,21 +1248,21 @@ pci_read_rom(struct file *filp, struct kobject *kobj,  	if (!pdev->rom_attr_enabled)  		return -EINVAL; -	 +  	rom = pci_map_rom(pdev, &size);	/* size starts out as PCI window size */  	if (!rom || !size)  		return -EIO; -		 +  	if (off >= size)  		count = 0;  	else {  		if (off + count > size)  			count = size - off; -		 +  		memcpy_fromio(buf, rom + off, count);  	}  	pci_unmap_rom(pdev, rom); -		 +  	return count;  } @@ -1237,14 +1286,8 @@ static struct bin_attribute pcie_config_attr = {  	.write = pci_write_config,  }; -int __weak pcibios_add_platform_entries(struct pci_dev *dev) -{ -	return 0; -} - -static ssize_t reset_store(struct device *dev, -			   struct device_attribute *attr, const char *buf, -			   size_t count) +static ssize_t reset_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; @@ -1311,7 +1354,7 @@ error:  	return retval;  } -int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) +int __must_check pci_create_sysfs_dev_files(struct pci_dev *pdev)  {  	int retval;  	int rom_size = 0; @@ -1357,11 +1400,6 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)  		pdev->rom_attr = attr;  	} -	/* add platform-specific attributes */ -	retval = pcibios_add_platform_entries(pdev); -	if (retval) -		goto err_rom_file; -  	/* add sysfs entries for various capabilities */  	retval = pci_create_capabilities_sysfs(pdev);  	if (retval) @@ -1454,7 +1492,6 @@ static int __init pci_sysfs_init(void)  	return 0;  } -  late_initcall(pci_sysfs_init);  static struct attribute *pci_dev_dev_attrs[] = { @@ -1463,7 +1500,7 @@ static struct attribute *pci_dev_dev_attrs[] = {  };  static umode_t pci_dev_attrs_are_visible(struct kobject *kobj, -						struct attribute *a, int n) +					 struct attribute *a, int n)  {  	struct device *dev = container_of(kobj, struct device, kobj);  	struct pci_dev *pdev = to_pci_dev(dev); @@ -1482,7 +1519,7 @@ static struct attribute *pci_dev_hp_attrs[] = {  };  static umode_t pci_dev_hp_attrs_are_visible(struct kobject *kobj, -						struct attribute *a, int n) +					    struct attribute *a, int n)  {  	struct device *dev = container_of(kobj, struct device, kobj);  	struct pci_dev *pdev = to_pci_dev(dev); @@ -1506,7 +1543,7 @@ static struct attribute *sriov_dev_attrs[] = {  };  static umode_t sriov_attrs_are_visible(struct kobject *kobj, -					 struct attribute *a, int n) +				       struct attribute *a, int n)  {  	struct device *dev = container_of(kobj, struct device, kobj); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index bdd64b1b481..1c8592b0e14 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -106,15 +106,15 @@ static bool pcie_ari_disabled;   * Given a PCI bus, returns the highest PCI bus number present in the set   * including the given PCI bus and its list of child PCI buses.   */ -unsigned char pci_bus_max_busnr(struct pci_bus* bus) +unsigned char pci_bus_max_busnr(struct pci_bus *bus)  { -	struct list_head *tmp; +	struct pci_bus *tmp;  	unsigned char max, n;  	max = bus->busn_res.end; -	list_for_each(tmp, &bus->children) { -		n = pci_bus_max_busnr(pci_bus_b(tmp)); -		if(n > max) +	list_for_each_entry(tmp, &bus->children, node) { +		n = pci_bus_max_busnr(tmp); +		if (n > max)  			max = n;  	}  	return max; @@ -198,7 +198,7 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,  }  /** - * pci_find_capability - query for devices' capabilities  + * pci_find_capability - query for devices' capabilities   * @dev: PCI device to query   * @cap: capability code   * @@ -207,12 +207,12 @@ static int __pci_bus_find_cap_start(struct pci_bus *bus,   * device's PCI configuration space or 0 in case the device does not   * support it.  Possible values for @cap:   * - *  %PCI_CAP_ID_PM           Power Management  - *  %PCI_CAP_ID_AGP          Accelerated Graphics Port  - *  %PCI_CAP_ID_VPD          Vital Product Data  - *  %PCI_CAP_ID_SLOTID       Slot Identification  + *  %PCI_CAP_ID_PM           Power Management + *  %PCI_CAP_ID_AGP          Accelerated Graphics Port + *  %PCI_CAP_ID_VPD          Vital Product Data + *  %PCI_CAP_ID_SLOTID       Slot Identification   *  %PCI_CAP_ID_MSI          Message Signalled Interrupts - *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap  + *  %PCI_CAP_ID_CHSWP        CompactPCI HotSwap   *  %PCI_CAP_ID_PCIX         PCI-X   *  %PCI_CAP_ID_EXP          PCI Express   */ @@ -226,15 +226,16 @@ int pci_find_capability(struct pci_dev *dev, int cap)  	return pos;  } +EXPORT_SYMBOL(pci_find_capability);  /** - * pci_bus_find_capability - query for devices' capabilities  + * pci_bus_find_capability - query for devices' capabilities   * @bus:   the PCI bus to query   * @devfn: PCI device to query   * @cap:   capability code   *   * Like pci_find_capability() but works for pci devices that do not have a - * pci_dev structure set up yet.  + * 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 @@ -253,6 +254,7 @@ int pci_bus_find_capability(struct pci_bus *bus, unsigned int devfn, int cap)  	return pos;  } +EXPORT_SYMBOL(pci_bus_find_capability);  /**   * pci_find_next_ext_capability - Find an extended capability @@ -401,33 +403,67 @@ EXPORT_SYMBOL_GPL(pci_find_ht_capability);   * @res: child resource record for which parent is sought   *   *  For given resource region of given device, return the resource - *  region of parent bus the given region is contained in or where - *  it should be allocated from. + *  region of parent bus the given region is contained in.   */ -struct resource * -pci_find_parent_resource(const struct pci_dev *dev, struct resource *res) +struct resource *pci_find_parent_resource(const struct pci_dev *dev, +					  struct resource *res)  {  	const struct pci_bus *bus = dev->bus; +	struct resource *r;  	int i; -	struct resource *best = NULL, *r;  	pci_bus_for_each_resource(bus, r, i) {  		if (!r)  			continue; -		if (res->start && !(res->start >= r->start && res->end <= r->end)) -			continue;	/* Not contained */ -		if ((res->flags ^ r->flags) & (IORESOURCE_IO | IORESOURCE_MEM)) -			continue;	/* Wrong type */ -		if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH)) -			return r;	/* Exact match */ -		/* We can't insert a non-prefetch resource inside a prefetchable parent .. */ -		if (r->flags & IORESOURCE_PREFETCH) -			continue; -		/* .. but we can put a prefetchable resource inside a non-prefetchable one */ -		if (!best) -			best = r; +		if (res->start && resource_contains(r, res)) { + +			/* +			 * If the window is prefetchable but the BAR is +			 * not, the allocator made a mistake. +			 */ +			if (r->flags & IORESOURCE_PREFETCH && +			    !(res->flags & IORESOURCE_PREFETCH)) +				return NULL; + +			/* +			 * If we're below a transparent bridge, there may +			 * be both a positively-decoded aperture and a +			 * subtractively-decoded region that contain the BAR. +			 * We want the positively-decoded one, so this depends +			 * on pci_bus_for_each_resource() giving us those +			 * first. +			 */ +			return r; +		}  	} -	return best; +	return NULL; +} +EXPORT_SYMBOL(pci_find_parent_resource); + +/** + * pci_wait_for_pending - wait for @mask bit(s) to clear in status word @pos + * @dev: the PCI device to operate on + * @pos: config space offset of status word + * @mask: mask of bit(s) to care about in status word + * + * Return 1 when mask bit(s) in status word clear, 0 otherwise. + */ +int pci_wait_for_pending(struct pci_dev *dev, int pos, u16 mask) +{ +	int i; + +	/* Wait for Transaction Pending bit clean */ +	for (i = 0; i < 4; i++) { +		u16 status; +		if (i) +			msleep((1 << (i - 1)) * 100); + +		pci_read_config_word(dev, pos, &status); +		if (!(status & mask)) +			return 1; +	} + +	return 0;  }  /** @@ -437,8 +473,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)   * Restore the BAR values for a given device, so as to make it   * accessible by its driver.   */ -static void -pci_restore_bars(struct pci_dev *dev) +static void pci_restore_bars(struct pci_dev *dev)  {  	int i; @@ -463,7 +498,7 @@ static inline bool platform_pci_power_manageable(struct pci_dev *dev)  }  static inline int platform_pci_set_power_state(struct pci_dev *dev, -                                                pci_power_t t) +					       pci_power_t t)  {  	return pci_platform_pm ? pci_platform_pm->set_state(dev, t) : -ENOSYS;  } @@ -515,13 +550,13 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)  		return -EINVAL;  	/* Validate current state: -	 * Can enter D0 from any state, but if we can only go deeper  +	 * Can enter D0 from any state, but if we can only go deeper  	 * to sleep if we're already in a low power state  	 */  	if (state != PCI_D0 && dev->current_state <= PCI_D3cold  	    && dev->current_state > state) { -		dev_err(&dev->dev, "invalid power transition " -			"(from state %d to %d)\n", dev->current_state, state); +		dev_err(&dev->dev, "invalid power transition (from state %d to %d)\n", +			dev->current_state, state);  		return -EINVAL;  	} @@ -568,8 +603,8 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)  	pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);  	dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);  	if (dev->current_state != state && printk_ratelimit()) -		dev_info(&dev->dev, "Refused to change power state, " -			"currently in D%d\n", dev->current_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 @@ -657,6 +692,28 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state)  }  /** + * pci_wakeup - Wake up a PCI device + * @pci_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. + */ +static void pci_wakeup_bus(struct pci_bus *bus) +{ +	if (bus) +		pci_walk_bus(bus, pci_wakeup, NULL); +} + +/**   * __pci_start_power_transition - Start power transition of a PCI device   * @dev: PCI device to handle.   * @state: State to put the device into. @@ -791,6 +848,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)  	return error;  } +EXPORT_SYMBOL(pci_set_power_state);  /**   * pci_choose_state - Choose the power state of a PCI device @@ -829,24 +887,32 @@ pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state)  	}  	return PCI_D0;  } -  EXPORT_SYMBOL(pci_choose_state);  #define PCI_EXP_SAVE_REGS	7 - -static struct pci_cap_saved_state *pci_find_saved_cap( -	struct pci_dev *pci_dev, char cap) +static struct pci_cap_saved_state *_pci_find_saved_cap(struct pci_dev *pci_dev, +						       u16 cap, bool extended)  {  	struct pci_cap_saved_state *tmp;  	hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) { -		if (tmp->cap.cap_nr == cap) +		if (tmp->cap.cap_extended == extended && tmp->cap.cap_nr == cap)  			return tmp;  	}  	return NULL;  } +struct pci_cap_saved_state *pci_find_saved_cap(struct pci_dev *dev, char cap) +{ +	return _pci_find_saved_cap(dev, cap, false); +} + +struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, u16 cap) +{ +	return _pci_find_saved_cap(dev, cap, true); +} +  static int pci_save_pcie_state(struct pci_dev *dev)  {  	int i = 0; @@ -936,8 +1002,7 @@ static void pci_restore_pcix_state(struct pci_dev *dev)   * pci_save_state - save the PCI configuration space of a device before suspending   * @dev: - PCI device that we're dealing with   */ -int -pci_save_state(struct pci_dev *dev) +int pci_save_state(struct pci_dev *dev)  {  	int i;  	/* XXX: 100% dword access ok here? */ @@ -948,8 +1013,11 @@ pci_save_state(struct pci_dev *dev)  		return i;  	if ((i = pci_save_pcix_state(dev)) != 0)  		return i; +	if ((i = pci_save_vc_state(dev)) != 0) +		return i;  	return 0;  } +EXPORT_SYMBOL(pci_save_state);  static void pci_restore_config_dword(struct pci_dev *pdev, int offset,  				     u32 saved_val, int retry) @@ -961,8 +1029,8 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset,  		return;  	for (;;) { -		dev_dbg(&pdev->dev, "restoring config space at offset " -			"%#x (was %#x, writing %#x)\n", offset, val, saved_val); +		dev_dbg(&pdev->dev, "restoring config space at offset %#x (was %#x, writing %#x)\n", +			offset, val, saved_val);  		pci_write_config_dword(pdev, offset, saved_val);  		if (retry-- <= 0)  			return; @@ -998,7 +1066,7 @@ static void pci_restore_config_space(struct pci_dev *pdev)  	}  } -/**  +/**   * pci_restore_state - Restore the saved state of a PCI device   * @dev: - PCI device that we're dealing with   */ @@ -1010,6 +1078,7 @@ void pci_restore_state(struct pci_dev *dev)  	/* PCI Express register must be restored first */  	pci_restore_pcie_state(dev);  	pci_restore_ats_state(dev); +	pci_restore_vc_state(dev);  	pci_restore_config_space(dev); @@ -1019,6 +1088,7 @@ void pci_restore_state(struct pci_dev *dev)  	dev->state_saved = false;  } +EXPORT_SYMBOL(pci_restore_state);  struct pci_saved_state {  	u32 config_space[16]; @@ -1030,7 +1100,7 @@ struct pci_saved_state {   *			   the device saved state.   * @dev: PCI device that we're dealing with   * - * Rerturn NULL if no state or error. + * Return NULL if no state or error.   */  struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev)  { @@ -1071,7 +1141,8 @@ EXPORT_SYMBOL_GPL(pci_store_saved_state);   * @dev: PCI device that we're dealing with   * @state: Saved state returned from pci_store_saved_state()   */ -int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state) +static int pci_load_saved_state(struct pci_dev *dev, +				struct pci_saved_state *state)  {  	struct pci_cap_saved_data *cap; @@ -1087,7 +1158,7 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)  	while (cap->size) {  		struct pci_cap_saved_state *tmp; -		tmp = pci_find_saved_cap(dev, cap->cap_nr); +		tmp = _pci_find_saved_cap(dev, cap->cap_nr, cap->cap_extended);  		if (!tmp || tmp->cap.size != cap->size)  			return -EINVAL; @@ -1099,7 +1170,6 @@ int pci_load_saved_state(struct pci_dev *dev, struct pci_saved_state *state)  	dev->state_saved = true;  	return 0;  } -EXPORT_SYMBOL_GPL(pci_load_saved_state);  /**   * pci_load_and_free_saved_state - Reload the save state pointed to by state, @@ -1117,9 +1187,16 @@ int pci_load_and_free_saved_state(struct pci_dev *dev,  }  EXPORT_SYMBOL_GPL(pci_load_and_free_saved_state); +int __weak pcibios_enable_device(struct pci_dev *dev, int bars) +{ +	return pci_enable_resources(dev, bars); +} +  static int do_pci_enable_device(struct pci_dev *dev, int bars)  {  	int err; +	u16 cmd; +	u8 pin;  	err = pci_set_power_state(dev, PCI_D0);  	if (err < 0 && err != -EIO) @@ -1129,6 +1206,17 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)  		return err;  	pci_fixup_device(pci_fixup_enable, dev); +	if (dev->msi_enabled || dev->msix_enabled) +		return 0; + +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); +	if (pin) { +		pci_read_config_word(dev, PCI_COMMAND, &cmd); +		if (cmd & PCI_COMMAND_INTX_DISABLE) +			pci_write_config_word(dev, PCI_COMMAND, +					      cmd & ~PCI_COMMAND_INTX_DISABLE); +	} +  	return 0;  } @@ -1145,21 +1233,20 @@ int pci_reenable_device(struct pci_dev *dev)  		return do_pci_enable_device(dev, (1 << PCI_NUM_RESOURCES) - 1);  	return 0;  } +EXPORT_SYMBOL(pci_reenable_device);  static void pci_enable_bridge(struct pci_dev *dev)  { +	struct pci_dev *bridge;  	int retval; -	if (!dev) -		return; - -	pci_enable_bridge(dev->bus->self); +	bridge = pci_upstream_bridge(dev); +	if (bridge) +		pci_enable_bridge(bridge);  	if (pci_is_enabled(dev)) { -		if (!dev->is_busmaster) { -			dev_warn(&dev->dev, "driver skip pci_set_master, fix it!\n"); +		if (!dev->is_busmaster)  			pci_set_master(dev); -		}  		return;  	} @@ -1172,6 +1259,7 @@ static void pci_enable_bridge(struct pci_dev *dev)  static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)  { +	struct pci_dev *bridge;  	int err;  	int i, bars = 0; @@ -1190,7 +1278,9 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)  	if (atomic_inc_return(&dev->enable_cnt) > 1)  		return 0;		/* already enabled */ -	pci_enable_bridge(dev->bus->self); +	bridge = pci_upstream_bridge(dev); +	if (bridge) +		pci_enable_bridge(bridge);  	/* only skip sriov related */  	for (i = 0; i <= PCI_ROM_RESOURCE; i++) @@ -1218,6 +1308,7 @@ int pci_enable_device_io(struct pci_dev *dev)  {  	return pci_enable_device_flags(dev, IORESOURCE_IO);  } +EXPORT_SYMBOL(pci_enable_device_io);  /**   * pci_enable_device_mem - Initialize a device for use with Memory space @@ -1231,6 +1322,7 @@ int pci_enable_device_mem(struct pci_dev *dev)  {  	return pci_enable_device_flags(dev, IORESOURCE_MEM);  } +EXPORT_SYMBOL(pci_enable_device_mem);  /**   * pci_enable_device - Initialize device before it's used by a driver. @@ -1247,6 +1339,7 @@ int pci_enable_device(struct pci_dev *dev)  {  	return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);  } +EXPORT_SYMBOL(pci_enable_device);  /*   * Managed PCI resources.  This manages device on/off, intx/msi/msix @@ -1284,7 +1377,7 @@ static void pcim_release(struct device *gendev, void *res)  		pci_disable_device(dev);  } -static struct pci_devres * get_pci_dr(struct pci_dev *pdev) +static struct pci_devres *get_pci_dr(struct pci_dev *pdev)  {  	struct pci_devres *dr, *new_dr; @@ -1298,7 +1391,7 @@ static struct pci_devres * get_pci_dr(struct pci_dev *pdev)  	return devres_get(&pdev->dev, new_dr, NULL, NULL);  } -static struct pci_devres * find_pci_dr(struct pci_dev *pdev) +static struct pci_devres *find_pci_dr(struct pci_dev *pdev)  {  	if (pci_is_managed(pdev))  		return devres_find(&pdev->dev, pcim_release, NULL, NULL); @@ -1329,6 +1422,7 @@ int pcim_enable_device(struct pci_dev *pdev)  	}  	return rc;  } +EXPORT_SYMBOL(pcim_enable_device);  /**   * pcim_pin_device - Pin managed PCI device @@ -1347,6 +1441,7 @@ void pcim_pin_device(struct pci_dev *pdev)  	if (dr)  		dr->pinned = 1;  } +EXPORT_SYMBOL(pcim_pin_device);  /*   * pcibios_add_device - provide arch specific hooks when adding device dev @@ -1356,7 +1451,7 @@ void pcim_pin_device(struct pci_dev *pdev)   * devices are added. This is the default implementation. Architecture   * implementations can override this.   */ -int __weak pcibios_add_device (struct pci_dev *dev) +int __weak pcibios_add_device(struct pci_dev *dev)  {  	return 0;  } @@ -1381,6 +1476,17 @@ void __weak pcibios_release_device(struct pci_dev *dev) {}   */  void __weak pcibios_disable_device (struct pci_dev *dev) {} +/** + * pcibios_penalize_isa_irq - penalize an ISA IRQ + * @irq: ISA IRQ to penalize + * @active: IRQ active or not + * + * Permits the platform to provide architecture-specific functionality when + * penalizing ISA IRQs. This is the default implementation. Architecture + * implementations can override this. + */ +void __weak pcibios_penalize_isa_irq(int irq, int active) {} +  static void do_pci_disable_device(struct pci_dev *dev)  {  	u16 pci_command; @@ -1417,8 +1523,7 @@ void pci_disable_enabled_device(struct pci_dev *dev)   * Note we don't actually disable the device until all callers of   * pci_enable_device() have called pci_disable_device().   */ -void -pci_disable_device(struct pci_dev *dev) +void pci_disable_device(struct pci_dev *dev)  {  	struct pci_devres *dr; @@ -1436,6 +1541,7 @@ pci_disable_device(struct pci_dev *dev)  	dev->is_busmaster = 0;  } +EXPORT_SYMBOL(pci_disable_device);  /**   * pcibios_set_pcie_reset_state - set reset state for device dev @@ -1464,6 +1570,7 @@ int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state)  {  	return pcibios_set_pcie_reset_state(dev, state);  } +EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state);  /**   * pci_check_pme_status - Check if given device has generated PME. @@ -1530,27 +1637,6 @@ void pci_pme_wakeup_bus(struct pci_bus *bus)  		pci_walk_bus(bus, pci_pme_wakeup, (void *)true);  } -/** - * pci_wakeup - Wake up a PCI device - * @pci_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# @@ -1564,35 +1650,34 @@ bool pci_pme_capable(struct pci_dev *dev, pci_power_t state)  	return !!(dev->pme_support & (1 << state));  } +EXPORT_SYMBOL(pci_pme_capable);  static void pci_pme_list_scan(struct work_struct *work)  {  	struct pci_pme_device *pme_dev, *n;  	mutex_lock(&pci_pme_list_mutex); -	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); -				kfree(pme_dev); -			} +	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); +			kfree(pme_dev);  		} -		if (!list_empty(&pci_pme_list)) -			schedule_delayed_work(&pci_pme_work, -					      msecs_to_jiffies(PME_TIMEOUT));  	} +	if (!list_empty(&pci_pme_list)) +		schedule_delayed_work(&pci_pme_work, +				      msecs_to_jiffies(PME_TIMEOUT));  	mutex_unlock(&pci_pme_list_mutex);  } @@ -1644,8 +1729,10 @@ void pci_pme_active(struct pci_dev *dev, bool enable)  		if (enable) {  			pme_dev = kmalloc(sizeof(struct pci_pme_device),  					  GFP_KERNEL); -			if (!pme_dev) -				goto out; +			if (!pme_dev) { +				dev_warn(&dev->dev, "can't enable PME#\n"); +				return; +			}  			pme_dev->dev = dev;  			mutex_lock(&pci_pme_list_mutex);  			list_add(&pme_dev->list, &pci_pme_list); @@ -1666,9 +1753,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable)  		}  	} -out:  	dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled");  } +EXPORT_SYMBOL(pci_pme_active);  /**   * __pci_enable_wake - enable PCI device as wakeup event source @@ -1754,6 +1841,7 @@ int pci_wake_from_d3(struct pci_dev *dev, bool enable)  			pci_enable_wake(dev, PCI_D3cold, enable) :  			pci_enable_wake(dev, PCI_D3hot, enable);  } +EXPORT_SYMBOL(pci_wake_from_d3);  /**   * pci_target_state - find an appropriate low power state for a given PCI dev @@ -1763,7 +1851,7 @@ int pci_wake_from_d3(struct pci_dev *dev, bool enable)   * If the platform can't manage @dev, return the deepest state from which it   * can generate wake events, based on any available PME info.   */ -pci_power_t pci_target_state(struct pci_dev *dev) +static pci_power_t pci_target_state(struct pci_dev *dev)  {  	pci_power_t target_state = PCI_D3hot; @@ -1832,6 +1920,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev)  	return error;  } +EXPORT_SYMBOL(pci_prepare_to_sleep);  /**   * pci_back_from_sleep - turn PCI device on during system-wide transition into working state @@ -1844,6 +1933,7 @@ int pci_back_from_sleep(struct pci_dev *dev)  	pci_enable_wake(dev, PCI_D0, false);  	return pci_set_power_state(dev, PCI_D0);  } +EXPORT_SYMBOL(pci_back_from_sleep);  /**   * pci_finish_runtime_suspend - Carry out PCI-specific part of runtime suspend. @@ -1878,7 +1968,7 @@ int pci_finish_runtime_suspend(struct pci_dev *dev)   * pci_dev_run_wake - Check if device can generate run-time wake-up events.   * @dev: Device to check.   * - * Return true if the device itself is cabable of generating wake-up events + * Return true if the device itself is capable of generating wake-up events   * (through the platform or using the native PCIe PME) or if the device supports   * PME and one of its upstream bridges can generate wake-up events.   */ @@ -2019,18 +2109,24 @@ static void pci_add_saved_cap(struct pci_dev *pci_dev,  }  /** - * pci_add_cap_save_buffer - allocate buffer for saving given capability registers + * _pci_add_cap_save_buffer - allocate buffer for saving given + *                            capability registers   * @dev: the PCI device   * @cap: the capability to allocate the buffer for + * @extended: Standard or Extended capability ID   * @size: requested size of the buffer   */ -static int pci_add_cap_save_buffer( -	struct pci_dev *dev, char cap, unsigned int size) +static int _pci_add_cap_save_buffer(struct pci_dev *dev, u16 cap, +				    bool extended, unsigned int size)  {  	int pos;  	struct pci_cap_saved_state *save_state; -	pos = pci_find_capability(dev, cap); +	if (extended) +		pos = pci_find_ext_capability(dev, cap); +	else +		pos = pci_find_capability(dev, cap); +  	if (pos <= 0)  		return 0; @@ -2039,12 +2135,23 @@ static int pci_add_cap_save_buffer(  		return -ENOMEM;  	save_state->cap.cap_nr = cap; +	save_state->cap.cap_extended = extended;  	save_state->cap.size = size;  	pci_add_saved_cap(dev, save_state);  	return 0;  } +int pci_add_cap_save_buffer(struct pci_dev *dev, char cap, unsigned int size) +{ +	return _pci_add_cap_save_buffer(dev, cap, false, size); +} + +int pci_add_ext_cap_save_buffer(struct pci_dev *dev, u16 cap, unsigned int size) +{ +	return _pci_add_cap_save_buffer(dev, cap, true, size); +} +  /**   * pci_allocate_cap_save_buffers - allocate buffers for saving capabilities   * @dev: the PCI device @@ -2063,6 +2170,8 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)  	if (error)  		dev_err(&dev->dev,  			"unable to preallocate PCI-X save buffer\n"); + +	pci_allocate_vc_save_buffers(dev);  }  void pci_free_cap_save_buffers(struct pci_dev *dev) @@ -2108,242 +2217,6 @@ void pci_configure_ari(struct pci_dev *dev)  	}  } -/** - * pci_enable_ido - enable ID-based Ordering on a device - * @dev: the PCI device - * @type: which types of IDO to enable - * - * Enable ID-based ordering on @dev.  @type can contain the bits - * %PCI_EXP_IDO_REQUEST and/or %PCI_EXP_IDO_COMPLETION to indicate - * which types of transactions are allowed to be re-ordered. - */ -void pci_enable_ido(struct pci_dev *dev, unsigned long type) -{ -	u16 ctrl = 0; - -	if (type & PCI_EXP_IDO_REQUEST) -		ctrl |= PCI_EXP_DEVCTL2_IDO_REQ_EN; -	if (type & PCI_EXP_IDO_COMPLETION) -		ctrl |= PCI_EXP_DEVCTL2_IDO_CMP_EN; -	if (ctrl) -		pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, ctrl); -} -EXPORT_SYMBOL(pci_enable_ido); - -/** - * pci_disable_ido - disable ID-based ordering on a device - * @dev: the PCI device - * @type: which types of IDO to disable - */ -void pci_disable_ido(struct pci_dev *dev, unsigned long type) -{ -	u16 ctrl = 0; - -	if (type & PCI_EXP_IDO_REQUEST) -		ctrl |= PCI_EXP_DEVCTL2_IDO_REQ_EN; -	if (type & PCI_EXP_IDO_COMPLETION) -		ctrl |= PCI_EXP_DEVCTL2_IDO_CMP_EN; -	if (ctrl) -		pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, ctrl); -} -EXPORT_SYMBOL(pci_disable_ido); - -/** - * pci_enable_obff - enable optimized buffer flush/fill - * @dev: PCI device - * @type: type of signaling to use - * - * Try to enable @type OBFF signaling on @dev.  It will try using WAKE# - * signaling if possible, falling back to message signaling only if - * WAKE# isn't supported.  @type should indicate whether the PCIe link - * be brought out of L0s or L1 to send the message.  It should be either - * %PCI_EXP_OBFF_SIGNAL_ALWAYS or %PCI_OBFF_SIGNAL_L0. - * - * If your device can benefit from receiving all messages, even at the - * power cost of bringing the link back up from a low power state, use - * %PCI_EXP_OBFF_SIGNAL_ALWAYS.  Otherwise, use %PCI_OBFF_SIGNAL_L0 (the - * preferred type). - * - * RETURNS: - * Zero on success, appropriate error number on failure. - */ -int pci_enable_obff(struct pci_dev *dev, enum pci_obff_signal_type type) -{ -	u32 cap; -	u16 ctrl; -	int ret; - -	pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); -	if (!(cap & PCI_EXP_DEVCAP2_OBFF_MASK)) -		return -ENOTSUPP; /* no OBFF support at all */ - -	/* Make sure the topology supports OBFF as well */ -	if (dev->bus->self) { -		ret = pci_enable_obff(dev->bus->self, type); -		if (ret) -			return ret; -	} - -	pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &ctrl); -	if (cap & PCI_EXP_DEVCAP2_OBFF_WAKE) -		ctrl |= PCI_EXP_DEVCTL2_OBFF_WAKE_EN; -	else { -		switch (type) { -		case PCI_EXP_OBFF_SIGNAL_L0: -			if (!(ctrl & PCI_EXP_DEVCTL2_OBFF_WAKE_EN)) -				ctrl |= PCI_EXP_DEVCTL2_OBFF_MSGA_EN; -			break; -		case PCI_EXP_OBFF_SIGNAL_ALWAYS: -			ctrl &= ~PCI_EXP_DEVCTL2_OBFF_WAKE_EN; -			ctrl |= PCI_EXP_DEVCTL2_OBFF_MSGB_EN; -			break; -		default: -			WARN(1, "bad OBFF signal type\n"); -			return -ENOTSUPP; -		} -	} -	pcie_capability_write_word(dev, PCI_EXP_DEVCTL2, ctrl); - -	return 0; -} -EXPORT_SYMBOL(pci_enable_obff); - -/** - * pci_disable_obff - disable optimized buffer flush/fill - * @dev: PCI device - * - * Disable OBFF on @dev. - */ -void pci_disable_obff(struct pci_dev *dev) -{ -	pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, -				   PCI_EXP_DEVCTL2_OBFF_WAKE_EN); -} -EXPORT_SYMBOL(pci_disable_obff); - -/** - * pci_ltr_supported - check whether a device supports LTR - * @dev: PCI device - * - * RETURNS: - * True if @dev supports latency tolerance reporting, false otherwise. - */ -static bool pci_ltr_supported(struct pci_dev *dev) -{ -	u32 cap; - -	pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap); - -	return cap & PCI_EXP_DEVCAP2_LTR; -} - -/** - * pci_enable_ltr - enable latency tolerance reporting - * @dev: PCI device - * - * Enable LTR on @dev if possible, which means enabling it first on - * upstream ports. - * - * RETURNS: - * Zero on success, errno on failure. - */ -int pci_enable_ltr(struct pci_dev *dev) -{ -	int ret; - -	/* Only primary function can enable/disable LTR */ -	if (PCI_FUNC(dev->devfn) != 0) -		return -EINVAL; - -	if (!pci_ltr_supported(dev)) -		return -ENOTSUPP; - -	/* Enable upstream ports first */ -	if (dev->bus->self) { -		ret = pci_enable_ltr(dev->bus->self); -		if (ret) -			return ret; -	} - -	return pcie_capability_set_word(dev, PCI_EXP_DEVCTL2, -					PCI_EXP_DEVCTL2_LTR_EN); -} -EXPORT_SYMBOL(pci_enable_ltr); - -/** - * pci_disable_ltr - disable latency tolerance reporting - * @dev: PCI device - */ -void pci_disable_ltr(struct pci_dev *dev) -{ -	/* Only primary function can enable/disable LTR */ -	if (PCI_FUNC(dev->devfn) != 0) -		return; - -	if (!pci_ltr_supported(dev)) -		return; - -	pcie_capability_clear_word(dev, PCI_EXP_DEVCTL2, -				   PCI_EXP_DEVCTL2_LTR_EN); -} -EXPORT_SYMBOL(pci_disable_ltr); - -static int __pci_ltr_scale(int *val) -{ -	int scale = 0; - -	while (*val > 1023) { -		*val = (*val + 31) / 32; -		scale++; -	} -	return scale; -} - -/** - * pci_set_ltr - set LTR latency values - * @dev: PCI device - * @snoop_lat_ns: snoop latency in nanoseconds - * @nosnoop_lat_ns: nosnoop latency in nanoseconds - * - * Figure out the scale and set the LTR values accordingly. - */ -int pci_set_ltr(struct pci_dev *dev, int snoop_lat_ns, int nosnoop_lat_ns) -{ -	int pos, ret, snoop_scale, nosnoop_scale; -	u16 val; - -	if (!pci_ltr_supported(dev)) -		return -ENOTSUPP; - -	snoop_scale = __pci_ltr_scale(&snoop_lat_ns); -	nosnoop_scale = __pci_ltr_scale(&nosnoop_lat_ns); - -	if (snoop_lat_ns > PCI_LTR_VALUE_MASK || -	    nosnoop_lat_ns > PCI_LTR_VALUE_MASK) -		return -EINVAL; - -	if ((snoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT)) || -	    (nosnoop_scale > (PCI_LTR_SCALE_MASK >> PCI_LTR_SCALE_SHIFT))) -		return -EINVAL; - -	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR); -	if (!pos) -		return -ENOTSUPP; - -	val = (snoop_scale << PCI_LTR_SCALE_SHIFT) | snoop_lat_ns; -	ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_SNOOP_LAT, val); -	if (ret != 4) -		return -EIO; - -	val = (nosnoop_scale << PCI_LTR_SCALE_SHIFT) | nosnoop_lat_ns; -	ret = pci_write_config_word(dev, pos + PCI_LTR_MAX_NOSNOOP_LAT, val); -	if (ret != 4) -		return -EIO; - -	return 0; -} -EXPORT_SYMBOL(pci_set_ltr); -  static int pci_acs_enable;  /** @@ -2355,21 +2228,18 @@ void pci_request_acs(void)  }  /** - * pci_enable_acs - enable ACS if hardware support it + * pci_std_enable_acs - enable ACS on devices using standard ACS capabilites   * @dev: the PCI device   */ -void pci_enable_acs(struct pci_dev *dev) +static int pci_std_enable_acs(struct pci_dev *dev)  {  	int pos;  	u16 cap;  	u16 ctrl; -	if (!pci_acs_enable) -		return; -  	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);  	if (!pos) -		return; +		return -ENODEV;  	pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);  	pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl); @@ -2387,6 +2257,23 @@ void pci_enable_acs(struct pci_dev *dev)  	ctrl |= (cap & PCI_ACS_UF);  	pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl); + +	return 0; +} + +/** + * pci_enable_acs - enable ACS if hardware support it + * @dev: the PCI device + */ +void pci_enable_acs(struct pci_dev *dev) +{ +	if (!pci_acs_enable) +		return; + +	if (!pci_std_enable_acs(dev)) +		return; + +	pci_dev_specific_enable_acs(dev);  }  static bool pci_acs_flags_enabled(struct pci_dev *pdev, u16 acs_flags) @@ -2445,7 +2332,7 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)  	switch (pci_pcie_type(pdev)) {  	/*  	 * PCI/X-to-PCIe bridges are not specifically mentioned by the spec, -	 * but since their primary inteface is PCI/X, we conservatively +	 * but since their primary interface is PCI/X, we conservatively  	 * handle them as we would a non-PCIe device.  	 */  	case PCI_EXP_TYPE_PCIE_BRIDGE: @@ -2469,7 +2356,7 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)  	/*  	 * PCIe 3.0, 6.12.1.2 specifies ACS capabilities that should be  	 * implemented by the remaining PCIe types to indicate peer-to-peer -	 * capabilities, but only when they are part of a multifunciton +	 * capabilities, but only when they are part of a multifunction  	 * device.  The footnote for section 6.12 indicates the specific  	 * PCIe types included here.  	 */ @@ -2484,7 +2371,7 @@ bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags)  	}  	/* -	 * PCIe 3.0, 6.12.1.3 specifies no ACS capabilties are applicable +	 * PCIe 3.0, 6.12.1.3 specifies no ACS capabilities are applicable  	 * to single function devices with the exception of downstream ports.  	 */  	return true; @@ -2542,8 +2429,7 @@ u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin)  	return (((pin - 1) + slot) % 4) + 1;  } -int -pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge) +int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)  {  	u8 pin; @@ -2605,6 +2491,7 @@ void pci_release_region(struct pci_dev *pdev, int bar)  	if (dr)  		dr->region_mask &= ~(1 << bar);  } +EXPORT_SYMBOL(pci_release_region);  /**   *	__pci_request_region - Reserved PCI I/O and memory resource @@ -2620,25 +2507,24 @@ void pci_release_region(struct pci_dev *pdev, int bar)   *   *	If @exclusive is set, then the region is marked so that userspace   *	is explicitly not allowed to map the resource via /dev/mem or - * 	sysfs MMIO access. + *	sysfs MMIO access.   *   *	Returns 0 on success, or %EBUSY on error.  A warning   *	message is also printed on failure.   */ -static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_name, -									int exclusive) +static int __pci_request_region(struct pci_dev *pdev, int bar, +				const char *res_name, int exclusive)  {  	struct pci_devres *dr;  	if (pci_resource_len(pdev, bar) == 0)  		return 0; -		 +  	if (pci_resource_flags(pdev, bar) & IORESOURCE_IO) {  		if (!request_region(pci_resource_start(pdev, bar),  			    pci_resource_len(pdev, bar), res_name))  			goto err_out; -	} -	else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) { +	} else if (pci_resource_flags(pdev, bar) & IORESOURCE_MEM) {  		if (!__request_mem_region(pci_resource_start(pdev, bar),  					pci_resource_len(pdev, bar), res_name,  					exclusive)) @@ -2675,6 +2561,7 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)  {  	return __pci_request_region(pdev, bar, res_name, 0);  } +EXPORT_SYMBOL(pci_request_region);  /**   *	pci_request_region_exclusive - Reserved PCI I/O and memory resource @@ -2692,12 +2579,15 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)   *   *	The key difference that _exclusive makes it that userspace is   *	explicitly not allowed to map the resource via /dev/mem or - * 	sysfs. + *	sysfs.   */ -int pci_request_region_exclusive(struct pci_dev *pdev, int bar, const char *res_name) +int pci_request_region_exclusive(struct pci_dev *pdev, int bar, +				 const char *res_name)  {  	return __pci_request_region(pdev, bar, res_name, IORESOURCE_EXCLUSIVE);  } +EXPORT_SYMBOL(pci_request_region_exclusive); +  /**   * pci_release_selected_regions - Release selected PCI I/O and memory resources   * @pdev: PCI device whose resources were previously reserved @@ -2714,9 +2604,10 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars)  		if (bars & (1 << i))  			pci_release_region(pdev, i);  } +EXPORT_SYMBOL(pci_release_selected_regions);  static int __pci_request_selected_regions(struct pci_dev *pdev, int bars, -				 const char *res_name, int excl) +					  const char *res_name, int excl)  {  	int i; @@ -2727,7 +2618,7 @@ static int __pci_request_selected_regions(struct pci_dev *pdev, int bars,  	return 0;  err_out: -	while(--i >= 0) +	while (--i >= 0)  		if (bars & (1 << i))  			pci_release_region(pdev, i); @@ -2746,13 +2637,15 @@ int pci_request_selected_regions(struct pci_dev *pdev, int bars,  {  	return __pci_request_selected_regions(pdev, bars, res_name, 0);  } +EXPORT_SYMBOL(pci_request_selected_regions); -int pci_request_selected_regions_exclusive(struct pci_dev *pdev, -				 int bars, const char *res_name) +int pci_request_selected_regions_exclusive(struct pci_dev *pdev, int bars, +					   const char *res_name)  {  	return __pci_request_selected_regions(pdev, bars, res_name,  			IORESOURCE_EXCLUSIVE);  } +EXPORT_SYMBOL(pci_request_selected_regions_exclusive);  /**   *	pci_release_regions - Release reserved PCI I/O and memory resources @@ -2767,6 +2660,7 @@ void pci_release_regions(struct pci_dev *pdev)  {  	pci_release_selected_regions(pdev, (1 << 6) - 1);  } +EXPORT_SYMBOL(pci_release_regions);  /**   *	pci_request_regions - Reserved PCI I/O and memory resources @@ -2785,6 +2679,7 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)  {  	return pci_request_selected_regions(pdev, ((1 << 6) - 1), res_name);  } +EXPORT_SYMBOL(pci_request_regions);  /**   *	pci_request_regions_exclusive - Reserved PCI I/O and memory resources @@ -2797,7 +2692,7 @@ int pci_request_regions(struct pci_dev *pdev, const char *res_name)   *	successfully.   *   *	pci_request_regions_exclusive() will mark the region so that - * 	/dev/mem and the sysfs MMIO access will not be allowed. + *	/dev/mem and the sysfs MMIO access will not be allowed.   *   *	Returns 0 on success, or %EBUSY on error.  A warning   *	message is also printed on failure. @@ -2807,6 +2702,7 @@ int pci_request_regions_exclusive(struct pci_dev *pdev, const char *res_name)  	return pci_request_selected_regions_exclusive(pdev,  					((1 << 6) - 1), res_name);  } +EXPORT_SYMBOL(pci_request_regions_exclusive);  static void __pci_set_master(struct pci_dev *dev, bool enable)  { @@ -2860,7 +2756,7 @@ void __weak pcibios_set_master(struct pci_dev *dev)  		lat = pcibios_max_latency;  	else  		return; -	dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat); +  	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);  } @@ -2876,6 +2772,7 @@ void pci_set_master(struct pci_dev *dev)  	__pci_set_master(dev, true);  	pcibios_set_master(dev);  } +EXPORT_SYMBOL(pci_set_master);  /**   * pci_clear_master - disables bus-mastering for device dev @@ -2885,6 +2782,7 @@ void pci_clear_master(struct pci_dev *dev)  {  	__pci_set_master(dev, false);  } +EXPORT_SYMBOL(pci_clear_master);  /**   * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed @@ -2917,30 +2815,13 @@ int pci_set_cacheline_size(struct pci_dev *dev)  	if (cacheline_size == pci_cache_line_size)  		return 0; -	dev_printk(KERN_DEBUG, &dev->dev, "cache line size of %d is not " -		   "supported\n", pci_cache_line_size << 2); +	dev_printk(KERN_DEBUG, &dev->dev, "cache line size of %d is not supported\n", +		   pci_cache_line_size << 2);  	return -EINVAL;  }  EXPORT_SYMBOL_GPL(pci_set_cacheline_size); -#ifdef PCI_DISABLE_MWI -int pci_set_mwi(struct pci_dev *dev) -{ -	return 0; -} - -int pci_try_set_mwi(struct pci_dev *dev) -{ -	return 0; -} - -void pci_clear_mwi(struct pci_dev *dev) -{ -} - -#else -  /**   * pci_set_mwi - enables memory-write-invalidate PCI transaction   * @dev: the PCI device for which MWI is enabled @@ -2949,9 +2830,11 @@ void pci_clear_mwi(struct pci_dev *dev)   *   * RETURNS: An appropriate -ERRNO error value on error, or zero for success.   */ -int -pci_set_mwi(struct pci_dev *dev) +int pci_set_mwi(struct pci_dev *dev)  { +#ifdef PCI_DISABLE_MWI +	return 0; +#else  	int rc;  	u16 cmd; @@ -2960,14 +2843,15 @@ pci_set_mwi(struct pci_dev *dev)  		return rc;  	pci_read_config_word(dev, PCI_COMMAND, &cmd); -	if (! (cmd & PCI_COMMAND_INVALIDATE)) { +	if (!(cmd & PCI_COMMAND_INVALIDATE)) {  		dev_dbg(&dev->dev, "enabling Mem-Wr-Inval\n");  		cmd |= PCI_COMMAND_INVALIDATE;  		pci_write_config_word(dev, PCI_COMMAND, cmd);  	} -	  	return 0; +#endif  } +EXPORT_SYMBOL(pci_set_mwi);  /**   * pci_try_set_mwi - enables memory-write-invalidate PCI transaction @@ -2980,9 +2864,13 @@ pci_set_mwi(struct pci_dev *dev)   */  int pci_try_set_mwi(struct pci_dev *dev)  { -	int rc = pci_set_mwi(dev); -	return rc; +#ifdef PCI_DISABLE_MWI +	return 0; +#else +	return pci_set_mwi(dev); +#endif  } +EXPORT_SYMBOL(pci_try_set_mwi);  /**   * pci_clear_mwi - disables Memory-Write-Invalidate for device dev @@ -2990,9 +2878,9 @@ int pci_try_set_mwi(struct pci_dev *dev)   *   * Disables PCI Memory-Write-Invalidate transaction on the device   */ -void -pci_clear_mwi(struct pci_dev *dev) +void pci_clear_mwi(struct pci_dev *dev)  { +#ifndef PCI_DISABLE_MWI  	u16 cmd;  	pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -3000,8 +2888,9 @@ pci_clear_mwi(struct pci_dev *dev)  		cmd &= ~PCI_COMMAND_INVALIDATE;  		pci_write_config_word(dev, PCI_COMMAND, cmd);  	} +#endif  } -#endif /* ! PCI_DISABLE_MWI */ +EXPORT_SYMBOL(pci_clear_mwi);  /**   * pci_intx - enables/disables PCI INTx for device dev @@ -3010,18 +2899,16 @@ pci_clear_mwi(struct pci_dev *dev)   *   * Enables/disables PCI INTx for device dev   */ -void -pci_intx(struct pci_dev *pdev, int enable) +void pci_intx(struct pci_dev *pdev, int enable)  {  	u16 pci_command, new;  	pci_read_config_word(pdev, PCI_COMMAND, &pci_command); -	if (enable) { +	if (enable)  		new = pci_command & ~PCI_COMMAND_INTX_DISABLE; -	} else { +	else  		new = pci_command | PCI_COMMAND_INTX_DISABLE; -	}  	if (new != pci_command) {  		struct pci_devres *dr; @@ -3035,6 +2922,7 @@ pci_intx(struct pci_dev *pdev, int enable)  		}  	}  } +EXPORT_SYMBOL_GPL(pci_intx);  /**   * pci_intx_mask_supported - probe for INTx masking support @@ -3064,8 +2952,8 @@ bool pci_intx_mask_supported(struct pci_dev *dev)  	 * go ahead and check it.  	 */  	if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) { -		dev_err(&dev->dev, "Command register changed from " -			"0x%x to 0x%x: driver or hardware bug?\n", orig, new); +		dev_err(&dev->dev, "Command register changed from 0x%x to 0x%x: driver or hardware bug?\n", +			orig, new);  	} else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {  		mask_supported = true;  		pci_write_config_word(dev, PCI_COMMAND, orig); @@ -3136,7 +3024,7 @@ bool pci_check_and_mask_intx(struct pci_dev *dev)  EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);  /** - * pci_check_and_mask_intx - unmask INTx of no interrupt is pending + * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending   * @dev: the PCI device to operate on   *   * Check if the device dev has its INTx line asserted, unmask it if not @@ -3202,20 +3090,11 @@ EXPORT_SYMBOL(pci_set_dma_seg_boundary);   */  int pci_wait_for_pending_transaction(struct pci_dev *dev)  { -	int i; -	u16 status; - -	/* Wait for Transaction Pending bit clean */ -	for (i = 0; i < 4; i++) { -		if (i) -			msleep((1 << (i - 1)) * 100); - -		pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &status); -		if (!(status & PCI_EXP_DEVSTA_TRPND)) -			return 1; -	} +	if (!pci_is_pcie(dev)) +		return 1; -	return 0; +	return pci_wait_for_pending(dev, pci_pcie_cap(dev) + PCI_EXP_DEVSTA, +				    PCI_EXP_DEVSTA_TRPND);  }  EXPORT_SYMBOL(pci_wait_for_pending_transaction); @@ -3242,10 +3121,8 @@ static int pcie_flr(struct pci_dev *dev, int probe)  static int pci_af_flr(struct pci_dev *dev, int probe)  { -	int i;  	int pos;  	u8 cap; -	u8 status;  	pos = pci_find_capability(dev, PCI_CAP_ID_AF);  	if (!pos) @@ -3258,18 +3135,16 @@ static int pci_af_flr(struct pci_dev *dev, int probe)  	if (probe)  		return 0; -	/* Wait for Transaction Pending bit clean */ -	for (i = 0; i < 4; i++) { -		if (i) -			msleep((1 << (i - 1)) * 100); - -		pci_read_config_byte(dev, pos + PCI_AF_STATUS, &status); -		if (!(status & PCI_AF_STATUS_TP)) -			goto clear; -	} +	/* +	 * Wait for Transaction Pending bit to clear.  A word-aligned test +	 * is used, so we use the conrol offset rather than status and shift +	 * the test bit to match. +	 */ +	if (pci_wait_for_pending(dev, pos + PCI_AF_CTRL, +				 PCI_AF_STATUS_TP << 8)) +		goto clear; -	dev_err(&dev->dev, "transaction is not cleared; " -			"proceeding with reset anyway\n"); +	dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");  clear:  	pci_write_config_byte(dev, pos + PCI_AF_CTRL, PCI_AF_CTRL_FLR); @@ -3290,7 +3165,7 @@ clear:   *   * NOTE: This causes the caller to sleep for twice the device power transition   * cooldown period, which for the D0->D3hot and D3hot->D0 transitions is 10 ms - * by devault (i.e. unless the @dev's d3_delay field has a different value). + * by default (i.e. unless the @dev's d3_delay field has a different value).   * Moreover, only devices in D0 can be reset by this function.   */  static int pci_pm_reset(struct pci_dev *dev, int probe) @@ -3323,14 +3198,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe)  	return 0;  } -/** - * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge. - * @dev: Bridge device - * - * Use the bridge control register to assert reset on the secondary bus. - * Devices on the secondary bus are left in power-on state. - */ -void pci_reset_bridge_secondary_bus(struct pci_dev *dev) +void __weak pcibios_reset_secondary_bus(struct pci_dev *dev)  {  	u16 ctrl; @@ -3339,7 +3207,7 @@ void pci_reset_bridge_secondary_bus(struct pci_dev *dev)  	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, ctrl);  	/*  	 * PCI spec v3.0 7.6.4.2 requires minimum Trst of 1ms.  Double -	 * this to 2ms to ensure that we meet the minium requirement. +	 * this to 2ms to ensure that we meet the minimum requirement.  	 */  	msleep(2); @@ -3355,6 +3223,18 @@ void pci_reset_bridge_secondary_bus(struct pci_dev *dev)  	 */  	ssleep(1);  } + +/** + * pci_reset_bridge_secondary_bus - Reset the secondary bus on a PCI bridge. + * @dev: Bridge device + * + * Use the bridge control register to assert reset on the secondary bus. + * Devices on the secondary bus are left in power-on state. + */ +void pci_reset_bridge_secondary_bus(struct pci_dev *dev) +{ +	pcibios_reset_secondary_bus(dev); +}  EXPORT_SYMBOL_GPL(pci_reset_bridge_secondary_bus);  static int pci_parent_bus_reset(struct pci_dev *dev, int probe) @@ -3443,14 +3323,45 @@ static void pci_dev_lock(struct pci_dev *dev)  	device_lock(&dev->dev);  } +/* Return 1 on successful lock, 0 on contention */ +static int pci_dev_trylock(struct pci_dev *dev) +{ +	if (pci_cfg_access_trylock(dev)) { +		if (device_trylock(&dev->dev)) +			return 1; +		pci_cfg_access_unlock(dev); +	} + +	return 0; +} +  static void pci_dev_unlock(struct pci_dev *dev)  {  	device_unlock(&dev->dev);  	pci_cfg_access_unlock(dev);  } +/** + * pci_reset_notify - notify device driver of reset + * @dev: device to be notified of reset + * @prepare: 'true' if device is about to be reset; 'false' if reset attempt + *           completed + * + * Must be called prior to device access being disabled and after device + * access is restored. + */ +static void pci_reset_notify(struct pci_dev *dev, bool prepare) +{ +	const struct pci_error_handlers *err_handler = +			dev->driver ? dev->driver->err_handler : NULL; +	if (err_handler && err_handler->reset_notify) +		err_handler->reset_notify(dev, prepare); +} +  static void pci_dev_save_and_disable(struct pci_dev *dev)  { +	pci_reset_notify(dev, true); +  	/*  	 * Wake-up device prior to save.  PM registers default to D0 after  	 * reset and a simple register restore doesn't reliably return @@ -3472,6 +3383,7 @@ static void pci_dev_save_and_disable(struct pci_dev *dev)  static void pci_dev_restore(struct pci_dev *dev)  {  	pci_restore_state(dev); +	pci_reset_notify(dev, false);  }  static int pci_dev_reset(struct pci_dev *dev, int probe) @@ -3488,6 +3400,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)  	return rc;  } +  /**   * __pci_reset_function - reset a PCI device function   * @dev: PCI device to reset @@ -3586,6 +3499,34 @@ int pci_reset_function(struct pci_dev *dev)  }  EXPORT_SYMBOL_GPL(pci_reset_function); +/** + * pci_try_reset_function - quiesce and reset a PCI device function + * @dev: PCI device to reset + * + * Same as above, except return -EAGAIN if unable to lock device. + */ +int pci_try_reset_function(struct pci_dev *dev) +{ +	int rc; + +	rc = pci_dev_reset(dev, 1); +	if (rc) +		return rc; + +	pci_dev_save_and_disable(dev); + +	if (pci_dev_trylock(dev)) { +		rc = __pci_dev_reset(dev, 0); +		pci_dev_unlock(dev); +	} else +		rc = -EAGAIN; + +	pci_dev_restore(dev); + +	return rc; +} +EXPORT_SYMBOL_GPL(pci_try_reset_function); +  /* Lock devices from the top of the tree down */  static void pci_bus_lock(struct pci_bus *bus)  { @@ -3610,6 +3551,32 @@ static void pci_bus_unlock(struct pci_bus *bus)  	}  } +/* Return 1 on successful lock, 0 on contention */ +static int pci_bus_trylock(struct pci_bus *bus) +{ +	struct pci_dev *dev; + +	list_for_each_entry(dev, &bus->devices, bus_list) { +		if (!pci_dev_trylock(dev)) +			goto unlock; +		if (dev->subordinate) { +			if (!pci_bus_trylock(dev->subordinate)) { +				pci_dev_unlock(dev); +				goto unlock; +			} +		} +	} +	return 1; + +unlock: +	list_for_each_entry_continue_reverse(dev, &bus->devices, bus_list) { +		if (dev->subordinate) +			pci_bus_unlock(dev->subordinate); +		pci_dev_unlock(dev); +	} +	return 0; +} +  /* Lock devices from the top of the tree down */  static void pci_slot_lock(struct pci_slot *slot)  { @@ -3638,6 +3605,37 @@ static void pci_slot_unlock(struct pci_slot *slot)  	}  } +/* Return 1 on successful lock, 0 on contention */ +static int pci_slot_trylock(struct pci_slot *slot) +{ +	struct pci_dev *dev; + +	list_for_each_entry(dev, &slot->bus->devices, bus_list) { +		if (!dev->slot || dev->slot != slot) +			continue; +		if (!pci_dev_trylock(dev)) +			goto unlock; +		if (dev->subordinate) { +			if (!pci_bus_trylock(dev->subordinate)) { +				pci_dev_unlock(dev); +				goto unlock; +			} +		} +	} +	return 1; + +unlock: +	list_for_each_entry_continue_reverse(dev, +					     &slot->bus->devices, bus_list) { +		if (!dev->slot || dev->slot != slot) +			continue; +		if (dev->subordinate) +			pci_bus_unlock(dev->subordinate); +		pci_dev_unlock(dev); +	} +	return 0; +} +  /* Save and disable devices from the top of the tree down */  static void pci_bus_save_and_disable(struct pci_bus *bus)  { @@ -3761,6 +3759,35 @@ int pci_reset_slot(struct pci_slot *slot)  }  EXPORT_SYMBOL_GPL(pci_reset_slot); +/** + * pci_try_reset_slot - Try to reset a PCI slot + * @slot: PCI slot to reset + * + * Same as above except return -EAGAIN if the slot cannot be locked + */ +int pci_try_reset_slot(struct pci_slot *slot) +{ +	int rc; + +	rc = pci_slot_reset(slot, 1); +	if (rc) +		return rc; + +	pci_slot_save_and_disable(slot); + +	if (pci_slot_trylock(slot)) { +		might_sleep(); +		rc = pci_reset_hotplug_slot(slot->hotplug, 0); +		pci_slot_unlock(slot); +	} else +		rc = -EAGAIN; + +	pci_slot_restore(slot); + +	return rc; +} +EXPORT_SYMBOL_GPL(pci_try_reset_slot); +  static int pci_bus_reset(struct pci_bus *bus, int probe)  {  	if (!bus->self) @@ -3820,6 +3847,35 @@ int pci_reset_bus(struct pci_bus *bus)  EXPORT_SYMBOL_GPL(pci_reset_bus);  /** + * pci_try_reset_bus - Try to reset a PCI bus + * @bus: top level PCI bus to reset + * + * Same as above except return -EAGAIN if the bus cannot be locked + */ +int pci_try_reset_bus(struct pci_bus *bus) +{ +	int rc; + +	rc = pci_bus_reset(bus, 1); +	if (rc) +		return rc; + +	pci_bus_save_and_disable(bus); + +	if (pci_bus_trylock(bus)) { +		might_sleep(); +		pci_reset_bridge_secondary_bus(bus->self); +		pci_bus_unlock(bus); +	} else +		rc = -EAGAIN; + +	pci_bus_restore(bus); + +	return rc; +} +EXPORT_SYMBOL_GPL(pci_try_reset_bus); + +/**   * pcix_get_max_mmrbc - get PCI-X maximum designed memory read byte count   * @dev: PCI device to query   * @@ -3978,6 +4034,7 @@ int pcie_get_mps(struct pci_dev *dev)  	return 128 << ((ctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5);  } +EXPORT_SYMBOL(pcie_get_mps);  /**   * pcie_set_mps - set PCI Express maximum payload size @@ -3995,13 +4052,14 @@ int pcie_set_mps(struct pci_dev *dev, int mps)  		return -EINVAL;  	v = ffs(mps) - 8; -	if (v > dev->pcie_mpss)  +	if (v > dev->pcie_mpss)  		return -EINVAL;  	v <<= 5;  	return pcie_capability_clear_and_set_word(dev, PCI_EXP_DEVCTL,  						  PCI_EXP_DEVCTL_PAYLOAD, v);  } +EXPORT_SYMBOL(pcie_set_mps);  /**   * pcie_get_minimum_link - determine minimum link settings of a PCI device @@ -4061,6 +4119,7 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags)  			bars |= (1 << i);  	return bars;  } +EXPORT_SYMBOL(pci_select_bars);  /**   * pci_resource_bar - get position of the BAR associated with a resource @@ -4100,7 +4159,7 @@ void __init pci_register_set_vga_state(arch_set_vga_state_t func)  }  static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode, -		      unsigned int command_bits, u32 flags) +				  unsigned int command_bits, u32 flags)  {  	if (arch_set_vga_state)  		return arch_set_vga_state(dev, decode, command_bits, @@ -4124,7 +4183,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,  	u16 cmd;  	int rc; -	WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) & (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY))); +	WARN_ON((flags & PCI_VGA_STATE_CHANGE_DECODES) && (command_bits & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY)));  	/* ARCH specific VGA enables */  	rc = pci_set_vga_state_arch(dev, decode, command_bits, flags); @@ -4161,6 +4220,14 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,  	return 0;  } +bool pci_device_is_present(struct pci_dev *pdev) +{ +	u32 v; + +	return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0); +} +EXPORT_SYMBOL_GPL(pci_device_is_present); +  #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE  static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};  static DEFINE_SPINLOCK(resource_alignment_lock); @@ -4204,11 +4271,10 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)  			bus == dev->bus->number &&  			slot == PCI_SLOT(dev->devfn) &&  			func == PCI_FUNC(dev->devfn)) { -			if (align_order == -1) { +			if (align_order == -1)  				align = PAGE_SIZE; -			} else { +			else  				align = 1 << align_order; -			}  			/* Found */  			break;  		} @@ -4265,6 +4331,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)  				"Rounding up size of resource #%d to %#llx.\n",  				i, (unsigned long long)size);  		} +		r->flags |= IORESOURCE_UNSET;  		r->end = size - 1;  		r->start = 0;  	} @@ -4278,6 +4345,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)  			r = &dev->resource[i];  			if (!(r->flags & IORESOURCE_MEM))  				continue; +			r->flags |= IORESOURCE_UNSET;  			r->end = resource_size(r) - 1;  			r->start = 0;  		} @@ -4324,7 +4392,6 @@ static int __init pci_resource_alignment_sysfs_init(void)  	return bus_create_file(&pci_bus_type,  					&bus_attr_resource_alignment);  } -  late_initcall(pci_resource_alignment_sysfs_init);  static void pci_no_domains(void) @@ -4403,42 +4470,3 @@ static int __init pci_setup(char *str)  	return 0;  }  early_param("pci", pci_setup); - -EXPORT_SYMBOL(pci_reenable_device); -EXPORT_SYMBOL(pci_enable_device_io); -EXPORT_SYMBOL(pci_enable_device_mem); -EXPORT_SYMBOL(pci_enable_device); -EXPORT_SYMBOL(pcim_enable_device); -EXPORT_SYMBOL(pcim_pin_device); -EXPORT_SYMBOL(pci_disable_device); -EXPORT_SYMBOL(pci_find_capability); -EXPORT_SYMBOL(pci_bus_find_capability); -EXPORT_SYMBOL(pci_release_regions); -EXPORT_SYMBOL(pci_request_regions); -EXPORT_SYMBOL(pci_request_regions_exclusive); -EXPORT_SYMBOL(pci_release_region); -EXPORT_SYMBOL(pci_request_region); -EXPORT_SYMBOL(pci_request_region_exclusive); -EXPORT_SYMBOL(pci_release_selected_regions); -EXPORT_SYMBOL(pci_request_selected_regions); -EXPORT_SYMBOL(pci_request_selected_regions_exclusive); -EXPORT_SYMBOL(pci_set_master); -EXPORT_SYMBOL(pci_clear_master); -EXPORT_SYMBOL(pci_set_mwi); -EXPORT_SYMBOL(pci_try_set_mwi); -EXPORT_SYMBOL(pci_clear_mwi); -EXPORT_SYMBOL_GPL(pci_intx); -EXPORT_SYMBOL(pci_assign_resource); -EXPORT_SYMBOL(pci_find_parent_resource); -EXPORT_SYMBOL(pci_select_bars); - -EXPORT_SYMBOL(pci_set_power_state); -EXPORT_SYMBOL(pci_save_state); -EXPORT_SYMBOL(pci_restore_state); -EXPORT_SYMBOL(pci_pme_capable); -EXPORT_SYMBOL(pci_pme_active); -EXPORT_SYMBOL(pci_wake_from_d3); -EXPORT_SYMBOL(pci_target_state); -EXPORT_SYMBOL(pci_prepare_to_sleep); -EXPORT_SYMBOL(pci_back_from_sleep); -EXPORT_SYMBOL_GPL(pci_set_pcie_reset_state); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 8a00c063d7b..0601890db22 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -1,12 +1,9 @@  #ifndef DRIVERS_PCI_H  #define DRIVERS_PCI_H -#include <linux/workqueue.h> -  #define PCI_CFG_SPACE_SIZE	256  #define PCI_CFG_SPACE_EXP_SIZE	4096 -extern const unsigned char pcix_bus_speed[];  extern const unsigned char pcie_link_speed[];  /* Functions internal to the PCI core code */ @@ -68,7 +65,6 @@ void pci_power_up(struct pci_dev *dev);  void pci_disable_enabled_device(struct pci_dev *dev);  int pci_finish_runtime_suspend(struct pci_dev *dev);  int __pci_pme_wakeup(struct pci_dev *dev, void *ign); -void pci_wakeup_bus(struct pci_bus *bus);  void pci_config_pm_runtime_get(struct pci_dev *dev);  void pci_config_pm_runtime_put(struct pci_dev *dev);  void pci_pm_init(struct pci_dev *dev); @@ -81,7 +77,7 @@ static inline void pci_wakeup_event(struct pci_dev *dev)  	pm_wakeup_event(&dev->dev, 100);  } -static inline bool pci_is_bridge(struct pci_dev *pci_dev) +static inline bool pci_has_subordinate(struct pci_dev *pci_dev)  {  	return !!(pci_dev->subordinate);  } @@ -153,10 +149,10 @@ static inline int pci_no_d1d2(struct pci_dev *dev)  	return (dev->no_d1d2 || parent_dstates);  } -extern struct device_attribute pci_dev_attrs[]; +extern const struct attribute_group *pci_dev_groups[];  extern const struct attribute_group *pcibus_groups[];  extern struct device_type pci_dev_type; -extern struct bus_attribute pci_bus_attrs[]; +extern const struct attribute_group *pci_bus_groups[];  /** @@ -205,11 +201,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,  		    struct resource *res, unsigned int reg);  int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type);  void pci_configure_ari(struct pci_dev *dev); -void __ref __pci_bus_size_bridges(struct pci_bus *bus, +void __pci_bus_size_bridges(struct pci_bus *bus,  			struct list_head *realloc_head); -void __ref __pci_bus_assign_resources(const struct pci_bus *bus, -				      struct list_head *realloc_head, -				      struct list_head *fail_head); +void __pci_bus_assign_resources(const struct pci_bus *bus, +				struct list_head *realloc_head, +				struct list_head *fail_head);  /**   * pci_ari_enabled - query ARI forwarding status @@ -242,8 +238,6 @@ struct pci_sriov {  	struct pci_dev *dev;	/* lowest numbered PF */  	struct pci_dev *self;	/* this PF */  	struct mutex lock;	/* lock for VF bus */ -	struct work_struct mtask; /* VF Migration task */ -	u8 __iomem *mstate;	/* VF Migration State Array */  };  #ifdef CONFIG_PCI_ATS diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 587e7e85310..182224acedb 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -397,16 +397,14 @@ static int aer_inject(struct aer_error_inj *einj)  	if (!aer_mask_override && einj->cor_status &&  	    !(einj->cor_status & ~cor_mask)) {  		ret = -EINVAL; -		printk(KERN_WARNING "The correctable error(s) is masked " -				"by device\n"); +		printk(KERN_WARNING "The correctable error(s) is masked by device\n");  		spin_unlock_irqrestore(&inject_lock, flags);  		goto out_put;  	}  	if (!aer_mask_override && einj->uncor_status &&  	    !(einj->uncor_status & ~uncor_mask)) {  		ret = -EINVAL; -		printk(KERN_WARNING "The uncorrectable error(s) is masked " -				"by device\n"); +		printk(KERN_WARNING "The uncorrectable error(s) is masked by device\n");  		spin_unlock_irqrestore(&inject_lock, flags);  		goto out_put;  	} @@ -464,8 +462,7 @@ static int aer_inject(struct aer_error_inj *einj)  			goto out_put;  		}  		aer_irq(-1, edev); -	} -	else +	} else  		ret = -EINVAL;  out_put:  	kfree(err_alloc); diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index cf611ab2193..01906576ab9 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -23,10 +23,10 @@  static inline int hest_match_pci(struct acpi_hest_aer_common *p,  				 struct pci_dev *pci)  { -	return	(0           == pci_domain_nr(pci->bus) && -		 p->bus      == pci->bus->number && -		 p->device   == PCI_SLOT(pci->devfn) && -		 p->function == PCI_FUNC(pci->devfn)); +	return   ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) && +		 ACPI_HEST_BUS(p->bus)     == pci->bus->number && +		 p->device                 == PCI_SLOT(pci->devfn) && +		 p->function               == PCI_FUNC(pci->devfn);  }  static inline bool hest_match_type(struct acpi_hest_header *hest_hdr, @@ -50,14 +50,37 @@ struct aer_hest_parse_info {  	int firmware_first;  }; +static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr) +{ +	if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT || +	    hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT || +	    hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE) +		return 1; +	return 0; +} +  static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)  {  	struct aer_hest_parse_info *info = data;  	struct acpi_hest_aer_common *p;  	int ff; +	if (!hest_source_is_pcie_aer(hest_hdr)) +		return 0; +  	p = (struct acpi_hest_aer_common *)(hest_hdr + 1);  	ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); + +	/* +	 * If no specific device is supplied, determine whether +	 * FIRMWARE_FIRST is set for *any* PCIe device. +	 */ +	if (!info->pci_dev) { +		info->firmware_first |= ff; +		return 0; +	} + +	/* Otherwise, check the specific device */  	if (p->flags & ACPI_HEST_GLOBAL) {  		if (hest_match_type(hest_hdr, info->pci_dev))  			info->firmware_first = ff; @@ -97,33 +120,20 @@ int pcie_aer_get_firmware_first(struct pci_dev *dev)  static bool aer_firmware_first; -static int aer_hest_parse_aff(struct acpi_hest_header *hest_hdr, void *data) -{ -	struct acpi_hest_aer_common *p; - -	if (aer_firmware_first) -		return 0; - -	switch (hest_hdr->type) { -	case ACPI_HEST_TYPE_AER_ROOT_PORT: -	case ACPI_HEST_TYPE_AER_ENDPOINT: -	case ACPI_HEST_TYPE_AER_BRIDGE: -		p = (struct acpi_hest_aer_common *)(hest_hdr + 1); -		aer_firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); -	default: -		return 0; -	} -} -  /**   * aer_acpi_firmware_first - Check if APEI should control AER.   */  bool aer_acpi_firmware_first(void)  {  	static bool parsed = false; +	struct aer_hest_parse_info info = { +		.pci_dev	= NULL,	/* Check all PCIe devices */ +		.firmware_first	= 0, +	};  	if (!parsed) { -		apei_hest_parse(aer_hest_parse_aff, NULL); +		apei_hest_parse(aer_hest_parse, &info); +		aer_firmware_first = info.firmware_first;  		parsed = true;  	}  	return aer_firmware_first; diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 85ca36f2136..5653ea94547 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -525,7 +525,7 @@ static void handle_error_source(struct pcie_device *aerdev,  	if (info->severity == AER_CORRECTABLE) {  		/* -		 * Correctable error does not need software intevention. +		 * Correctable error does not need software intervention.  		 * No need to go through error recovery process.  		 */  		pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); @@ -542,8 +542,7 @@ static void aer_recover_work_func(struct work_struct *work);  #define AER_RECOVER_RING_ORDER		4  #define AER_RECOVER_RING_SIZE		(1 << AER_RECOVER_RING_ORDER) -struct aer_recover_entry -{ +struct aer_recover_entry {  	u8	bus;  	u8	devfn;  	u16	domain; @@ -574,7 +573,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,  	};  	spin_lock_irqsave(&aer_recover_ring_lock, flags); -	if (kfifo_put(&aer_recover_ring, &entry)) +	if (kfifo_put(&aer_recover_ring, entry))  		schedule_work(&aer_recover_work);  	else  		pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n", diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 2c7c9f5f592..36ed31b5219 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c @@ -124,6 +124,21 @@ static const char *aer_agent_string[] = {  	"Transmitter ID"  }; +static void __print_tlp_header(struct pci_dev *dev, +			       struct aer_header_log_regs *t) +{ +	unsigned char *tlp = (unsigned char *)&t; + +	dev_err(&dev->dev, "  TLP Header:" +		" %02x%02x%02x%02x %02x%02x%02x%02x" +		" %02x%02x%02x%02x %02x%02x%02x%02x\n", +		*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, +		*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), +		*(tlp + 11), *(tlp + 10), *(tlp + 9), +		*(tlp + 8), *(tlp + 15), *(tlp + 14), +		*(tlp + 13), *(tlp + 12)); +} +  static void __aer_print_error(struct pci_dev *dev,  			      struct aer_err_info *info)  { @@ -153,48 +168,35 @@ static void __aer_print_error(struct pci_dev *dev,  void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)  { +	int layer, agent;  	int id = ((dev->bus->number << 8) | dev->devfn); -	if (info->status == 0) { -		dev_err(&dev->dev, -			"PCIe Bus Error: severity=%s, type=Unaccessible, " -			"id=%04x(Unregistered Agent ID)\n", +	if (!info->status) { +		dev_err(&dev->dev, "PCIe Bus Error: severity=%s, type=Unaccessible, id=%04x(Unregistered Agent ID)\n",  			aer_error_severity_string[info->severity], id); -	} else { -		int layer, agent; - -		layer = AER_GET_LAYER_ERROR(info->severity, info->status); -		agent = AER_GET_AGENT(info->severity, info->status); - -		dev_err(&dev->dev, -			"PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", -			aer_error_severity_string[info->severity], -			aer_error_layer[layer], id, aer_agent_string[agent]); - -		dev_err(&dev->dev, -			"  device [%04x:%04x] error status/mask=%08x/%08x\n", -			dev->vendor, dev->device, -			info->status, info->mask); - -		__aer_print_error(dev, info); - -		if (info->tlp_header_valid) { -			unsigned char *tlp = (unsigned char *) &info->tlp; -			dev_err(&dev->dev, "  TLP Header:" -				" %02x%02x%02x%02x %02x%02x%02x%02x" -				" %02x%02x%02x%02x %02x%02x%02x%02x\n", -				*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, -				*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), -				*(tlp + 11), *(tlp + 10), *(tlp + 9), -				*(tlp + 8), *(tlp + 15), *(tlp + 14), -				*(tlp + 13), *(tlp + 12)); -		} +		goto out;  	} +	layer = AER_GET_LAYER_ERROR(info->severity, info->status); +	agent = AER_GET_AGENT(info->severity, info->status); + +	dev_err(&dev->dev, "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", +		aer_error_severity_string[info->severity], +		aer_error_layer[layer], id, aer_agent_string[agent]); + +	dev_err(&dev->dev, "  device [%04x:%04x] error status/mask=%08x/%08x\n", +		dev->vendor, dev->device, +		info->status, info->mask); + +	__aer_print_error(dev, info); + +	if (info->tlp_header_valid) +		__print_tlp_header(dev, &info->tlp); + +out:  	if (info->id && info->error_dev_num > 1 && info->id == id) -		dev_err(&dev->dev, -			   "  Error of this Agent(%04x) is reported first\n", -			id); +		dev_err(&dev->dev, "  Error of this Agent(%04x) is reported first\n", id); +  	trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),  			info->severity);  } @@ -228,6 +230,7 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity,  	const char **status_strs;  	aer_severity = cper_severity_to_aer(cper_severity); +  	if (aer_severity == AER_CORRECTABLE) {  		status = aer->cor_status;  		mask = aer->cor_mask; @@ -240,28 +243,22 @@ void cper_print_aer(struct pci_dev *dev, int cper_severity,  		status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string);  		tlp_header_valid = status & AER_LOG_TLP_MASKS;  	} +  	layer = AER_GET_LAYER_ERROR(aer_severity, status);  	agent = AER_GET_AGENT(aer_severity, status); -	dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", -	       status, mask); + +	dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);  	cper_print_bits("", status, status_strs, status_strs_size);  	dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", -	       aer_error_layer[layer], aer_agent_string[agent]); +		aer_error_layer[layer], aer_agent_string[agent]); +  	if (aer_severity != AER_CORRECTABLE)  		dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", -		       aer->uncor_severity); -	if (tlp_header_valid) { -		const unsigned char *tlp; -		tlp = (const unsigned char *)&aer->header_log; -		dev_err(&dev->dev, "aer_tlp_header:" -			" %02x%02x%02x%02x %02x%02x%02x%02x" -			" %02x%02x%02x%02x %02x%02x%02x%02x\n", -			*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, -			*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), -			*(tlp + 11), *(tlp + 10), *(tlp + 9), -			*(tlp + 8), *(tlp + 15), *(tlp + 14), -			*(tlp + 13), *(tlp + 12)); -	} +			aer->uncor_severity); + +	if (tlp_header_valid) +		__print_tlp_header(dev, &aer->header_log); +  	trace_aer_event(dev_name(&dev->dev), (status & ~mask),  			aer_severity);  } diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 403a44374ed..e1e7026b838 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -548,7 +548,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev)  /*   * pcie_aspm_init_link_state: Initiate PCI express link state. - * It is called after the pcie and its children devices are scaned. + * It is called after the pcie and its children devices are scanned.   * @pdev: the root port or switch downstream port   */  void pcie_aspm_init_link_state(struct pci_dev *pdev) @@ -984,18 +984,6 @@ void pcie_no_aspm(void)  	}  } -/** - * pcie_aspm_enabled - is PCIe ASPM enabled? - * - * Returns true if ASPM has not been disabled by the command-line option - * pcie_aspm=off. - **/ -int pcie_aspm_enabled(void) -{ -       return !aspm_disabled; -} -EXPORT_SYMBOL(pcie_aspm_enabled); -  bool pcie_aspm_support_enabled(void)  {  	return aspm_support_enabled; diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index e56e594ce11..82e06a86cd7 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -199,8 +199,7 @@ static void pcie_pme_handle_request(struct pci_dev *port, u16 req_id)  		 * assuming that the PME was reported by a PCIe-PCI bridge that  		 * used devfn different from zero.  		 */ -		dev_dbg(&port->dev, "PME interrupt generated for " -			"non-existent device %02x:%02x.%d\n", +		dev_dbg(&port->dev, "PME interrupt generated for non-existent device %02x:%02x.%d\n",  			busnr, PCI_SLOT(devfn), PCI_FUNC(devfn));  		found = pcie_pme_from_pci_bridge(bus, 0);  	} @@ -419,8 +418,8 @@ static void pcie_pme_remove(struct pcie_device *srv)  static struct pcie_port_service_driver pcie_pme_driver = {  	.name		= "pcie_pme", -	.port_type 	= PCI_EXP_TYPE_ROOT_PORT, -	.service 	= PCIE_PORT_SERVICE_PME, +	.port_type	= PCI_EXP_TYPE_ROOT_PORT, +	.service	= PCIE_PORT_SERVICE_PME,  	.probe		= pcie_pme_probe,  	.suspend	= pcie_pme_suspend, diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index d2eb80aab56..d525548404d 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -14,7 +14,7 @@  #define PCIE_PORT_DEVICE_MAXSERVICES   4  /*   * According to the PCI Express Base Specification 2.0, the indices of - * the MSI-X table entires used by port services must not exceed 31 + * the MSI-X table entries used by port services must not exceed 31   */  #define PCIE_PORT_MAX_MSIX_ENTRIES	32 diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c index 67be55a7f26..87e79a6ffb5 100644 --- a/drivers/pci/pcie/portdrv_bus.c +++ b/drivers/pci/pcie/portdrv_bus.c @@ -18,8 +18,8 @@  static int pcie_port_bus_match(struct device *dev, struct device_driver *drv);  struct bus_type pcie_port_bus_type = { -	.name 		= "pci_express", -	.match 		= pcie_port_bus_match, +	.name		= "pci_express", +	.match		= pcie_port_bus_match,  };  EXPORT_SYMBOL_GPL(pcie_port_bus_type); diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 31063ac3099..2f0ce668a77 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c @@ -46,7 +46,7 @@ static void release_pcie_device(struct device *dev)   * pcie_port_msix_add_entry - add entry to given array of MSI-X entries   * @entries: Array of MSI-X entries   * @new_entry: Index of the entry to add to the array - * @nr_entries: Number of entries aleady in the array + * @nr_entries: Number of entries already in the array   *   * Return value: Position of the added entry in the array   */ @@ -79,9 +79,10 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)  	u16 reg16;  	u32 reg32; -	nr_entries = pci_msix_table_size(dev); -	if (!nr_entries) -		return -EINVAL; +	nr_entries = pci_msix_vec_count(dev); +	if (nr_entries < 0) +		return nr_entries; +	BUG_ON(!nr_entries);  	if (nr_entries > PCIE_PORT_MAX_MSIX_ENTRIES)  		nr_entries = PCIE_PORT_MAX_MSIX_ENTRIES; @@ -98,7 +99,7 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)  	for (i = 0; i < nr_entries; i++)  		msix_entries[i].entry = i; -	status = pci_enable_msix(dev, msix_entries, nr_entries); +	status = pci_enable_msix_exact(dev, msix_entries, nr_entries);  	if (status)  		goto Exit; @@ -170,7 +171,7 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)  		pci_disable_msix(dev);  		/* Now allocate the MSI-X vectors for real */ -		status = pci_enable_msix(dev, msix_entries, nvec); +		status = pci_enable_msix_exact(dev, msix_entries, nvec);  		if (status)  			goto Exit;  	} @@ -260,13 +261,14 @@ static int get_port_device_capability(struct pci_dev *dev)  	if (pcie_ports_disabled)  		return 0; -	err = pcie_port_platform_notify(dev, &cap_mask); -	if (!pcie_ports_auto) { -		cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP -				| PCIE_PORT_SERVICE_VC; -		if (pci_aer_available()) -			cap_mask |= PCIE_PORT_SERVICE_AER; -	} else if (err) { +	cap_mask = PCIE_PORT_SERVICE_PME | PCIE_PORT_SERVICE_HP +			| PCIE_PORT_SERVICE_VC; +	if (pci_aer_available()) +		cap_mask |= PCIE_PORT_SERVICE_AER; + +	if (pcie_ports_auto) { +		err = pcie_port_platform_notify(dev, &cap_mask); +		if (err)  			return 0;  	} @@ -343,11 +345,12 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)  	device_enable_async_suspend(device);  	retval = device_register(device); -	if (retval) -		kfree(pcie); -	else -		get_device(device); -	return retval; +	if (retval) { +		put_device(device); +		return retval; +	} + +	return 0;  }  /** @@ -376,10 +379,13 @@ int pcie_port_device_register(struct pci_dev *dev)  	/*  	 * Initialize service irqs. Don't use service devices that  	 * require interrupts if there is no way to generate them. +	 * However, some drivers may have a polling mode (e.g. pciehp_poll_mode) +	 * that can be used in the absence of irqs.  Allow them to determine +	 * if that is to be used.  	 */  	status = init_service_irqs(dev, irqs, capabilities);  	if (status) { -		capabilities &= PCIE_PORT_SERVICE_VC; +		capabilities &= PCIE_PORT_SERVICE_VC | PCIE_PORT_SERVICE_HP;  		if (!capabilities)  			goto error_disable;  	} @@ -453,10 +459,8 @@ int pcie_port_device_resume(struct device *dev)  static int remove_iter(struct device *dev, void *data)  { -	if (dev->bus == &pcie_port_bus_type) { -		put_device(dev); +	if (dev->bus == &pcie_port_bus_type)  		device_unregister(dev); -	}  	return 0;  } @@ -497,12 +501,12 @@ static int pcie_port_probe_service(struct device *dev)  	pciedev = to_pcie_device(dev);  	status = driver->probe(pciedev); -	if (!status) { -		dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", -			driver->name); -		get_device(dev); -	} -	return status; +	if (status) +		return status; + +	dev_printk(KERN_DEBUG, dev, "service driver %s loaded\n", driver->name); +	get_device(dev); +	return 0;  }  /** @@ -553,7 +557,7 @@ int pcie_port_service_register(struct pcie_port_service_driver *new)  	if (pcie_ports_disabled)  		return -ENODEV; -	new->driver.name = (char *)new->name; +	new->driver.name = new->name;  	new->driver.bus = &pcie_port_bus_type;  	new->driver.probe = pcie_port_probe_service;  	new->driver.remove = pcie_port_remove_service; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 696caed5fdf..80887eaa066 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -204,8 +204,8 @@ static int pcie_portdrv_probe(struct pci_dev *dev,  		return -ENODEV;  	if (!dev->irq && dev->pin) { -		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; " -			 "check vendor BIOS\n", dev->vendor, dev->device); +		dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; check vendor BIOS\n", +			 dev->vendor, dev->device);  	}  	status = pcie_port_device_register(dev);  	if (status) @@ -223,7 +223,6 @@ static int pcie_portdrv_probe(struct pci_dev *dev,  static void pcie_portdrv_remove(struct pci_dev *dev)  {  	pcie_port_device_remove(dev); -	pci_disable_device(dev);  }  static int error_detected_iter(struct device *device, void *data) @@ -390,15 +389,15 @@ static struct pci_driver pcie_portdriver = {  	.probe		= pcie_portdrv_probe,  	.remove		= pcie_portdrv_remove, -	.err_handler 	= &pcie_portdrv_err_handler, +	.err_handler	= &pcie_portdrv_err_handler, -	.driver.pm 	= PCIE_PORTDRV_PM_OPS, +	.driver.pm	= PCIE_PORTDRV_PM_OPS,  };  static int __init dmi_pcie_pme_disable_msi(const struct dmi_system_id *d)  {  	pr_notice("%s detected: will not use MSI for PCIe PME signaling\n", -			d->ident); +		  d->ident);  	pcie_pme_disable_msi();  	return 0;  } @@ -412,7 +411,7 @@ static struct dmi_system_id __initdata pcie_portdrv_dmi_table[] = {  	 .ident = "MSI Wind U-100",  	 .matches = {  		     DMI_MATCH(DMI_SYS_VENDOR, -		     		"MICRO-STAR INTERNATIONAL CO., LTD"), +				"MICRO-STAR INTERNATIONAL CO., LTD"),  		     DMI_MATCH(DMI_PRODUCT_NAME, "U-100"),  		     },  	 }, diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 7ef0f868b3e..e3cf8a2e629 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -16,7 +16,7 @@  #define CARDBUS_LATENCY_TIMER	176	/* secondary latency timer */  #define CARDBUS_RESERVE_BUSNR	3 -struct resource busn_resource = { +static struct resource busn_resource = {  	.name	= "PCI busn",  	.start	= 0,  	.end	= 255, @@ -168,12 +168,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)   * Returns 1 if the BAR is 64-bit, or 0 if 32-bit.   */  int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, -			struct resource *res, unsigned int pos) +		    struct resource *res, unsigned int pos)  {  	u32 l, sz, mask; +	u64 l64, sz64, mask64;  	u16 orig_cmd;  	struct pci_bus_region region, inverted_region; -	bool bar_too_big = false, bar_disabled = false; +	bool bar_too_big = false, bar_too_high = false, bar_invalid = false;  	mask = type ? PCI_ROM_ADDRESS_MASK : ~0; @@ -226,9 +227,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,  	}  	if (res->flags & IORESOURCE_MEM_64) { -		u64 l64 = l; -		u64 sz64 = sz; -		u64 mask64 = mask | (u64)~0 << 32; +		l64 = l; +		sz64 = sz; +		mask64 = mask | (u64)~0 << 32;  		pci_read_config_dword(dev, pos + 4, &l);  		pci_write_config_dword(dev, pos + 4, ~0); @@ -243,18 +244,22 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,  		if (!sz64)  			goto fail; -		if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) { +		if ((sizeof(dma_addr_t) < 8 || sizeof(resource_size_t) < 8) && +		    sz64 > 0x100000000ULL) { +			res->flags |= IORESOURCE_UNSET | IORESOURCE_DISABLED; +			res->start = 0; +			res->end = 0;  			bar_too_big = true; -			goto fail; +			goto out;  		} -		if ((sizeof(resource_size_t) < 8) && l) { -			/* Address above 32-bit boundary; disable the BAR */ -			pci_write_config_dword(dev, pos, 0); -			pci_write_config_dword(dev, pos + 4, 0); -			region.start = 0; -			region.end = sz64; -			bar_disabled = true; +		if ((sizeof(dma_addr_t) < 8) && l) { +			/* Above 32-bit boundary; try to reallocate */ +			res->flags |= IORESOURCE_UNSET; +			res->start = 0; +			res->end = sz64; +			bar_too_high = true; +			goto out;  		} else {  			region.start = l64;  			region.end = l64 + sz64; @@ -269,8 +274,8 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,  		region.end = l + sz;  	} -	pcibios_bus_to_resource(dev, res, ®ion); -	pcibios_resource_to_bus(dev, &inverted_region, res); +	pcibios_bus_to_resource(dev->bus, res, ®ion); +	pcibios_resource_to_bus(dev->bus, &inverted_region, res);  	/*  	 * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is @@ -284,11 +289,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,  	 * be claimed by the device.  	 */  	if (inverted_region.start != region.start) { -		dev_info(&dev->dev, "reg 0x%x: initial BAR value %pa invalid; forcing reassignment\n", -			 pos, ®ion.start);  		res->flags |= IORESOURCE_UNSET; -		res->end -= res->start;  		res->start = 0; +		res->end = region.end - region.start; +		bar_invalid = true;  	}  	goto out; @@ -302,8 +306,15 @@ out:  		pci_write_config_word(dev, PCI_COMMAND, orig_cmd);  	if (bar_too_big) -		dev_err(&dev->dev, "reg 0x%x: can't handle 64-bit BAR\n", pos); -	if (res->flags && !bar_disabled) +		dev_err(&dev->dev, "reg 0x%x: can't handle BAR larger than 4GB (size %#010llx)\n", +			pos, (unsigned long long) sz64); +	if (bar_too_high) +		dev_info(&dev->dev, "reg 0x%x: can't handle BAR above 4G (bus address %#010llx)\n", +			 pos, (unsigned long long) l64); +	if (bar_invalid) +		dev_info(&dev->dev, "reg 0x%x: initial BAR value %#010llx invalid\n", +			 pos, (unsigned long long) region.start); +	if (res->flags)  		dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);  	return (res->flags & IORESOURCE_MEM_64) ? 1 : 0; @@ -364,7 +375,7 @@ static void pci_read_bridge_io(struct pci_bus *child)  		res->flags = (io_base_lo & PCI_IO_RANGE_TYPE_MASK) | IORESOURCE_IO;  		region.start = base;  		region.end = limit + io_granularity - 1; -		pcibios_bus_to_resource(dev, res, ®ion); +		pcibios_bus_to_resource(dev->bus, res, ®ion);  		dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);  	}  } @@ -386,7 +397,7 @@ static void pci_read_bridge_mmio(struct pci_bus *child)  		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); +		pcibios_bus_to_resource(dev->bus, res, ®ion);  		dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);  	}  } @@ -422,8 +433,7 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)  			limit |= ((unsigned long) mem_limit_hi) << 32;  #else  			if (mem_base_hi || mem_limit_hi) { -				dev_err(&dev->dev, "can't handle 64-bit " -					"address space for bridge\n"); +				dev_err(&dev->dev, "can't handle 64-bit address space for bridge\n");  				return;  			}  #endif @@ -436,7 +446,7 @@ static void pci_read_bridge_mmio_pref(struct pci_bus *child)  			res->flags |= IORESOURCE_MEM_64;  		region.start = base;  		region.end = limit + 0xfffff; -		pcibios_bus_to_resource(dev, res, ®ion); +		pcibios_bus_to_resource(dev->bus, res, ®ion);  		dev_printk(KERN_DEBUG, &dev->dev, "  bridge window %pR\n", res);  	}  } @@ -464,7 +474,7 @@ void pci_read_bridge_bases(struct pci_bus *child)  	if (dev->transparent) {  		pci_bus_for_each_resource(child->parent, res, i) { -			if (res) { +			if (res && res->flags) {  				pci_bus_add_resource(child, res,  						     PCI_SUBTRACTIVE_DECODE);  				dev_printk(KERN_DEBUG, &dev->dev, @@ -518,7 +528,7 @@ static struct pci_host_bridge *pci_alloc_host_bridge(struct pci_bus *b)  	return bridge;  } -const unsigned char pcix_bus_speed[] = { +static const unsigned char pcix_bus_speed[] = {  	PCI_SPEED_UNKNOWN,		/* 0 */  	PCI_SPEED_66MHz_PCIX,		/* 1 */  	PCI_SPEED_100MHz_PCIX,		/* 2 */ @@ -582,7 +592,7 @@ static enum pci_bus_speed agp_speed(int agp3, int agpstat)  		index = 1;  	else  		goto out; -	 +  	if (agp3) {  		index += 2;  		if (index == 5) @@ -593,7 +603,6 @@ static enum pci_bus_speed agp_speed(int agp3, int agpstat)  	return agp_speeds[index];  } -  static void pci_set_bus_speed(struct pci_bus *bus)  {  	struct pci_dev *bridge = bus->self; @@ -625,11 +634,10 @@ static void pci_set_bus_speed(struct pci_bus *bus)  		} else if (status & PCI_X_SSTATUS_266MHZ) {  			max = PCI_SPEED_133MHz_PCIX_266;  		} else if (status & PCI_X_SSTATUS_133MHZ) { -			if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2) { +			if ((status & PCI_X_SSTATUS_VERS) == PCI_X_SSTATUS_V2)  				max = PCI_SPEED_133MHz_PCIX_ECC; -			} else { +			else  				max = PCI_SPEED_133MHz_PCIX; -			}  		} else {  			max = PCI_SPEED_66MHz_PCIX;  		} @@ -641,8 +649,7 @@ static void pci_set_bus_speed(struct pci_bus *bus)  		return;  	} -	pos = pci_find_capability(bridge, PCI_CAP_ID_EXP); -	if (pos) { +	if (pci_is_pcie(bridge)) {  		u32 linkcap;  		u16 linksta; @@ -654,7 +661,6 @@ static void pci_set_bus_speed(struct pci_bus *bus)  	}  } -  static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,  					   struct pci_dev *bridge, int busnr)  { @@ -719,7 +725,8 @@ add_dev:  	return child;  } -struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) +struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, +				int busnr)  {  	struct pci_bus *child; @@ -731,22 +738,7 @@ struct pci_bus *__ref pci_add_new_bus(struct pci_bus *parent, struct pci_dev *de  	}  	return child;  } - -static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) -{ -	struct pci_bus *parent = child->parent; - -	/* Attempts to fix that up are really dangerous unless -	   we're going to re-assign all bus numbers. */ -	if (!pcibios_assign_all_busses()) -		return; - -	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; -	} -} +EXPORT_SYMBOL(pci_add_new_bus);  /*   * If it's a bridge, configure it and scan the bus behind it. @@ -783,14 +775,14 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  	/* Check if setup is sensible at all */  	if (!pass &&  	    (primary != bus->number || secondary <= bus->number || -	     secondary > subordinate)) { +	     secondary > subordinate || subordinate > bus->busn_res.end)) {  		dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n",  			 secondary, subordinate);  		broken = 1;  	}  	/* Disable MasterAbortMode during probing to avoid reporting -	   of bus errors (in some architectures) */  +	   of bus errors (in some architectures) */  	pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bctl);  	pci_write_config_word(dev, PCI_BRIDGE_CONTROL,  			      bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT); @@ -806,11 +798,10 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  			goto out;  		/* -		 * If we already got to this bus through a different bridge, -		 * don't re-add it. This can happen with the i450NX chipset. -		 * -		 * However, we continue to descend down the hierarchy and -		 * scan remaining child buses. +		 * The bus might already exist for two reasons: Either we are +		 * rescanning the bus or the bus is reachable through more than +		 * one bridge. The second case can happen with the i450NX +		 * chipset.  		 */  		child = pci_find_bus(pci_domain_nr(bus), secondary);  		if (!child) { @@ -823,17 +814,19 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  		}  		cmax = pci_scan_child_bus(child); -		if (cmax > max) -			max = cmax; -		if (child->busn_res.end > max) -			max = child->busn_res.end; +		if (cmax > subordinate) +			dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n", +				 subordinate, cmax); +		/* subordinate should equal child->busn_res.end */ +		if (subordinate > max) +			max = subordinate;  	} else {  		/*  		 * We need to assign a number to this bus which we always  		 * do in the second pass.  		 */  		if (!pass) { -			if (pcibios_assign_all_busses() || broken) +			if (pcibios_assign_all_busses() || broken || is_cardbus)  				/* Temporarily disable forwarding of the  				   configuration cycles on all bridges in  				   this bus segment to avoid possible @@ -845,19 +838,25 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  			goto out;  		} +		if (max >= bus->busn_res.end) { +			dev_warn(&dev->dev, "can't allocate child bus %02x from %pR\n", +				 max, &bus->busn_res); +			goto out; +		} +  		/* Clear errors */  		pci_write_config_word(dev, PCI_STATUS, 0xffff); -		/* Prevent assigning a bus number that already exists. -		 * This can happen when a bridge is hot-plugged, so in -		 * this case we only re-scan this bus. */ +		/* The bus will already exist if we are rescanning */  		child = pci_find_bus(pci_domain_nr(bus), max+1);  		if (!child) { -			child = pci_add_new_bus(bus, dev, ++max); +			child = pci_add_new_bus(bus, dev, max+1);  			if (!child)  				goto out; -			pci_bus_insert_busn_res(child, max, 0xff); +			pci_bus_insert_busn_res(child, max+1, +						bus->busn_res.end);  		} +		max++;  		buses = (buses & 0xff000000)  		      | ((unsigned int)(child->primary)     <<  0)  		      | ((unsigned int)(child->busn_res.start)   <<  8) @@ -879,27 +878,14 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  		if (!is_cardbus) {  			child->bridge_ctl = bctl; -			/* -			 * Adjust subordinate busnr in parent buses. -			 * We do this before scanning for children because -			 * some devices may not be detected if the bios -			 * was lazy. -			 */ -			pci_fixup_parent_subordinate_busnr(child, max); -			/* Now we can scan all subordinate buses... */  			max = pci_scan_child_bus(child); -			/* -			 * now fix it up again since we have found -			 * the real value of max. -			 */ -			pci_fixup_parent_subordinate_busnr(child, max);  		} else {  			/*  			 * For CardBus bridges, we leave 4 bus numbers  			 * as cards with a PCI-to-PCI bridge can be  			 * inserted later.  			 */ -			for (i=0; i<CARDBUS_RESERVE_BUSNR; i++) { +			for (i = 0; i < CARDBUS_RESERVE_BUSNR; i++) {  				struct pci_bus *parent = bus;  				if (pci_find_bus(pci_domain_nr(bus),  							max+i+1)) @@ -923,11 +909,15 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  				}  			}  			max += i; -			pci_fixup_parent_subordinate_busnr(child, max);  		}  		/*  		 * Set the subordinate bus number to its real value.  		 */ +		if (max > bus->busn_res.end) { +			dev_warn(&dev->dev, "max busn %02x is outside %pR\n", +				 max, &bus->busn_res); +			max = bus->busn_res.end; +		}  		pci_bus_update_busn_res_end(child, max);  		pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);  	} @@ -942,8 +932,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)  		    (child->number > bus->busn_res.end) ||  		    (child->number < bus->number) ||  		    (child->busn_res.end < bus->number)) { -			dev_info(&child->dev, "%pR %s " -				"hidden behind%s bridge %s %pR\n", +			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) ? @@ -960,6 +949,7 @@ out:  	return max;  } +EXPORT_SYMBOL(pci_scan_bridge);  /*   * Read interrupt line and base address registers. @@ -984,7 +974,6 @@ void set_pcie_port_type(struct pci_dev *pdev)  	pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);  	if (!pos)  		return; -	pdev->is_pcie = 1;  	pdev->pcie_cap = pos;  	pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16);  	pdev->pcie_flags_reg = reg16; @@ -1001,13 +990,103 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev)  		pdev->is_hotplug_bridge = 1;  } +/** + * pci_ext_cfg_is_aliased - is ext config space just an alias of std config? + * @dev: PCI device + * + * PCI Express to PCI/PCI-X Bridge Specification, rev 1.0, 4.1.4 says that + * when forwarding a type1 configuration request the bridge must check that + * the extended register address field is zero.  The bridge is not permitted + * to forward the transactions and must handle it as an Unsupported Request. + * Some bridges do not follow this rule and simply drop the extended register + * bits, resulting in the standard config space being aliased, every 256 + * bytes across the entire configuration space.  Test for this condition by + * comparing the first dword of each potential alias to the vendor/device ID. + * Known offenders: + *   ASM1083/1085 PCIe-to-PCI Reversible Bridge (1b21:1080, rev 01 & 03) + *   AMD/ATI SBx00 PCI to PCI Bridge (1002:4384, rev 40) + */ +static bool pci_ext_cfg_is_aliased(struct pci_dev *dev) +{ +#ifdef CONFIG_PCI_QUIRKS +	int pos; +	u32 header, tmp; + +	pci_read_config_dword(dev, PCI_VENDOR_ID, &header); + +	for (pos = PCI_CFG_SPACE_SIZE; +	     pos < PCI_CFG_SPACE_EXP_SIZE; pos += PCI_CFG_SPACE_SIZE) { +		if (pci_read_config_dword(dev, pos, &tmp) != PCIBIOS_SUCCESSFUL +		    || header != tmp) +			return false; +	} + +	return true; +#else +	return false; +#endif +} + +/** + * pci_cfg_space_size - get the configuration space size of the PCI device. + * @dev: PCI device + * + * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices + * have 4096 bytes.  Even if the device is capable, that doesn't mean we can + * access it.  Maybe we don't have a way to generate extended config space + * accesses, or the device is behind a reverse Express bridge.  So we try + * reading the dword at 0x100 which must either be 0 or a valid extended + * capability header. + */ +static int pci_cfg_space_size_ext(struct pci_dev *dev) +{ +	u32 status; +	int pos = PCI_CFG_SPACE_SIZE; + +	if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL) +		goto fail; +	if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev)) +		goto fail; + +	return PCI_CFG_SPACE_EXP_SIZE; + + fail: +	return PCI_CFG_SPACE_SIZE; +} + +int pci_cfg_space_size(struct pci_dev *dev) +{ +	int pos; +	u32 status; +	u16 class; + +	class = dev->class >> 8; +	if (class == PCI_CLASS_BRIDGE_HOST) +		return pci_cfg_space_size_ext(dev); + +	if (!pci_is_pcie(dev)) { +		pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); +		if (!pos) +			goto fail; + +		pci_read_config_dword(dev, pos + PCI_X_STATUS, &status); +		if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))) +			goto fail; +	} + +	return pci_cfg_space_size_ext(dev); + + fail: +	return PCI_CFG_SPACE_SIZE; +} +  #define LEGACY_IO_RESOURCE	(IORESOURCE_IO | IORESOURCE_PCI_FIXED)  /**   * pci_setup_device - fill in class and map information of a device   * @dev: the device structure to fill   * - * Initialize the device structure with information about the device's  + * Initialize the device structure with information about the device's   * vendor,class,memory and IO-space addresses,IRQ lines etc.   * Called at initialisation of the PCI subsystem and by CardBus services.   * Returns 0 on success and negative if unknown type of device (not normal, @@ -1073,10 +1152,10 @@ int pci_setup_device(struct pci_dev *dev)  		pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);  		/* -		 *	Do the ugly legacy mode stuff here rather than broken chip -		 *	quirk code. Legacy mode ATA controllers have fixed -		 *	addresses. These are not always echoed in BAR0-3, and -		 *	BAR0-3 in a few cases contain junk! +		 * Do the ugly legacy mode stuff here rather than broken chip +		 * quirk code. Legacy mode ATA controllers have fixed +		 * addresses. These are not always echoed in BAR0-3, and +		 * BAR0-3 in a few cases contain junk!  		 */  		if (class == PCI_CLASS_STORAGE_IDE) {  			u8 progif; @@ -1086,24 +1165,32 @@ int pci_setup_device(struct pci_dev *dev)  				region.end = 0x1F7;  				res = &dev->resource[0];  				res->flags = LEGACY_IO_RESOURCE; -				pcibios_bus_to_resource(dev, res, ®ion); +				pcibios_bus_to_resource(dev->bus, res, ®ion); +				dev_info(&dev->dev, "legacy IDE quirk: reg 0x10: %pR\n", +					 res);  				region.start = 0x3F6;  				region.end = 0x3F6;  				res = &dev->resource[1];  				res->flags = LEGACY_IO_RESOURCE; -				pcibios_bus_to_resource(dev, res, ®ion); +				pcibios_bus_to_resource(dev->bus, res, ®ion); +				dev_info(&dev->dev, "legacy IDE quirk: reg 0x14: %pR\n", +					 res);  			}  			if ((progif & 4) == 0) {  				region.start = 0x170;  				region.end = 0x177;  				res = &dev->resource[2];  				res->flags = LEGACY_IO_RESOURCE; -				pcibios_bus_to_resource(dev, res, ®ion); +				pcibios_bus_to_resource(dev->bus, res, ®ion); +				dev_info(&dev->dev, "legacy IDE quirk: reg 0x18: %pR\n", +					 res);  				region.start = 0x376;  				region.end = 0x376;  				res = &dev->resource[3];  				res->flags = LEGACY_IO_RESOURCE; -				pcibios_bus_to_resource(dev, res, ®ion); +				pcibios_bus_to_resource(dev->bus, res, ®ion); +				dev_info(&dev->dev, "legacy IDE quirk: reg 0x1c: %pR\n", +					 res);  			}  		}  		break; @@ -1113,7 +1200,7 @@ int pci_setup_device(struct pci_dev *dev)  			goto bad;  		/* The PCI-to-PCI bridge spec requires that subtractive  		   decoding (i.e. transparent) bridge must have programming -		   interface code of 0x01. */  +		   interface code of 0x01. */  		pci_read_irq(dev);  		dev->transparent = ((dev->class & 0xff) == 1);  		pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); @@ -1135,13 +1222,13 @@ int pci_setup_device(struct pci_dev *dev)  		break;  	default:				    /* unknown header */ -		dev_err(&dev->dev, "unknown header type %02x, " -			"ignoring device\n", dev->hdr_type); +		dev_err(&dev->dev, "unknown header type %02x, ignoring device\n", +			dev->hdr_type);  		return -EIO;  	bad: -		dev_err(&dev->dev, "ignoring class %#08x (doesn't match header " -			"type %02x)\n", dev->class, dev->hdr_type); +		dev_err(&dev->dev, "ignoring class %#08x (doesn't match header type %02x)\n", +			dev->class, dev->hdr_type);  		dev->class = PCI_CLASS_NOT_DEFINED;  	} @@ -1172,62 +1259,10 @@ static void pci_release_dev(struct device *dev)  	pci_release_of_node(pci_dev);  	pcibios_release_device(pci_dev);  	pci_bus_put(pci_dev->bus); +	kfree(pci_dev->driver_override);  	kfree(pci_dev);  } -/** - * pci_cfg_space_size - get the configuration space size of the PCI device. - * @dev: PCI device - * - * Regular PCI devices have 256 bytes, but PCI-X 2 and PCI Express devices - * have 4096 bytes.  Even if the device is capable, that doesn't mean we can - * access it.  Maybe we don't have a way to generate extended config space - * accesses, or the device is behind a reverse Express bridge.  So we try - * reading the dword at 0x100 which must either be 0 or a valid extended - * capability header. - */ -int pci_cfg_space_size_ext(struct pci_dev *dev) -{ -	u32 status; -	int pos = PCI_CFG_SPACE_SIZE; - -	if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL) -		goto fail; -	if (status == 0xffffffff) -		goto fail; - -	return PCI_CFG_SPACE_EXP_SIZE; - - fail: -	return PCI_CFG_SPACE_SIZE; -} - -int pci_cfg_space_size(struct pci_dev *dev) -{ -	int pos; -	u32 status; -	u16 class; - -	class = dev->class >> 8; -	if (class == PCI_CLASS_BRIDGE_HOST) -		return pci_cfg_space_size_ext(dev); - -	if (!pci_is_pcie(dev)) { -		pos = pci_find_capability(dev, PCI_CAP_ID_PCIX); -		if (!pos) -			goto fail; - -		pci_read_config_dword(dev, pos + PCI_X_STATUS, &status); -		if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))) -			goto fail; -	} - -	return pci_cfg_space_size_ext(dev); - - fail: -	return PCI_CFG_SPACE_SIZE; -} -  struct pci_dev *pci_alloc_dev(struct pci_bus *bus)  {  	struct pci_dev *dev; @@ -1244,14 +1279,8 @@ struct pci_dev *pci_alloc_dev(struct pci_bus *bus)  }  EXPORT_SYMBOL(pci_alloc_dev); -struct pci_dev *alloc_pci_dev(void) -{ -	return pci_alloc_dev(NULL); -} -EXPORT_SYMBOL(alloc_pci_dev); -  bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l, -				 int crs_timeout) +				int crs_timeout)  {  	int delay = 1; @@ -1274,10 +1303,9 @@ bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,  			return false;  		/* Card hasn't responded in 60 seconds?  Must be stuck. */  		if (delay > crs_timeout) { -			printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not " -					"responding\n", pci_domain_nr(bus), -					bus->number, PCI_SLOT(devfn), -					PCI_FUNC(devfn)); +			printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not responding\n", +			       pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), +			       PCI_FUNC(devfn));  			return false;  		}  	} @@ -1383,11 +1411,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)  	dev->match_driver = false;  	ret = device_add(&dev->dev);  	WARN_ON(ret < 0); - -	pci_proc_attach_device(dev);  } -struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) +struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)  {  	struct pci_dev *dev; @@ -1489,6 +1515,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)  	return nr;  } +EXPORT_SYMBOL(pci_scan_slot);  static int pcie_find_smpss(struct pci_dev *dev, void *data)  { @@ -1572,7 +1599,7 @@ static void pcie_write_mrrs(struct pci_dev *dev)  	 * subsequent read will verify if the value is acceptable or not.  	 * If the MRRS value provided is not acceptable (e.g., too large),  	 * shrink the value until it is acceptable to the HW. - 	 */ +	 */  	while (mrrs != pcie_get_readrq(dev) && mrrs >= 128) {  		rc = pcie_set_readrq(dev, mrrs);  		if (!rc) @@ -1583,9 +1610,7 @@ static void pcie_write_mrrs(struct pci_dev *dev)  	}  	if (mrrs < 128) -		dev_err(&dev->dev, "MRRS was unable to be configured with a " -			"safe value.  If problems are experienced, try running " -			"with pci=pcie_bus_safe.\n"); +		dev_err(&dev->dev, "MRRS was unable to be configured with a safe value.  If problems are experienced, try running with pci=pcie_bus_safe\n");  }  static void pcie_bus_detect_mps(struct pci_dev *dev) @@ -1622,8 +1647,8 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)  	pcie_write_mps(dev, mps);  	pcie_write_mrrs(dev); -	dev_info(&dev->dev, "Max Payload Size set to %4d/%4d (was %4d), " -		 "Max Read Rq %4d\n", pcie_get_mps(dev), 128 << dev->pcie_mpss, +	dev_info(&dev->dev, "Max Payload Size set to %4d/%4d (was %4d), Max Read Rq %4d\n", +		 pcie_get_mps(dev), 128 << dev->pcie_mpss,  		 orig_mps, pcie_get_readrq(dev));  	return 0; @@ -1635,7 +1660,7 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data)   */  void pcie_bus_configure_settings(struct pci_bus *bus)  { -	u8 smpss; +	u8 smpss = 0;  	if (!bus->self)  		return; @@ -1686,10 +1711,9 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)  		bus->is_added = 1;  	} -	for (pass=0; pass < 2; pass++) +	for (pass = 0; pass < 2; pass++)  		list_for_each_entry(dev, &bus->devices, bus_list) { -			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || -			    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) +			if (pci_is_bridge(dev))  				max = pci_scan_bridge(bus, dev, max, pass);  		} @@ -1703,6 +1727,7 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)  	dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);  	return max;  } +EXPORT_SYMBOL_GPL(pci_scan_child_bus);  /**   * pcibios_root_bridge_prepare - Platform-specific host bridge setup. @@ -1844,7 +1869,7 @@ int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)  		res->flags |= IORESOURCE_PCI_FIXED;  	} -	conflict = insert_resource_conflict(parent_res, res); +	conflict = request_resource_conflict(parent_res, res);  	if (conflict)  		dev_printk(KERN_DEBUG, &b->dev, @@ -1976,7 +2001,7 @@ EXPORT_SYMBOL(pci_scan_bus);   *   * Returns the max number of subordinate bus discovered.   */ -unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge) +unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge)  {  	unsigned int max;  	struct pci_bus *bus = bridge->subordinate; @@ -1999,7 +2024,7 @@ unsigned int __ref pci_rescan_bus_bridge_resize(struct pci_dev *bridge)   *   * Returns the max number of subordinate bus discovered.   */ -unsigned int __ref pci_rescan_bus(struct pci_bus *bus) +unsigned int pci_rescan_bus(struct pci_bus *bus)  {  	unsigned int max; @@ -2011,12 +2036,26 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus)  }  EXPORT_SYMBOL_GPL(pci_rescan_bus); -EXPORT_SYMBOL(pci_add_new_bus); -EXPORT_SYMBOL(pci_scan_slot); -EXPORT_SYMBOL(pci_scan_bridge); -EXPORT_SYMBOL_GPL(pci_scan_child_bus); +/* + * pci_rescan_bus(), pci_rescan_bus_bridge_resize() and PCI device removal + * routines should always be executed under this mutex. + */ +static DEFINE_MUTEX(pci_rescan_remove_lock); + +void pci_lock_rescan_remove(void) +{ +	mutex_lock(&pci_rescan_remove_lock); +} +EXPORT_SYMBOL_GPL(pci_lock_rescan_remove); + +void pci_unlock_rescan_remove(void) +{ +	mutex_unlock(&pci_rescan_remove_lock); +} +EXPORT_SYMBOL_GPL(pci_unlock_rescan_remove); -static int __init pci_sort_bf_cmp(const struct device *d_a, const struct device *d_b) +static int __init pci_sort_bf_cmp(const struct device *d_a, +				  const struct device *d_b)  {  	const struct pci_dev *a = to_pci_dev(d_a);  	const struct pci_dev *b = to_pci_dev(d_b); diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index cdc7836d7e3..3f155e78513 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -17,15 +17,14 @@  static int proc_initialized;	/* = 0 */ -static loff_t -proc_bus_pci_lseek(struct file *file, loff_t off, int whence) +static loff_t proc_bus_pci_lseek(struct file *file, loff_t off, int whence)  {  	struct pci_dev *dev = PDE_DATA(file_inode(file));  	return fixed_size_llseek(file, off, whence, dev->cfg_size);  } -static ssize_t -proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) +static ssize_t proc_bus_pci_read(struct file *file, char __user *buf, +				 size_t nbytes, loff_t *ppos)  {  	struct pci_dev *dev = PDE_DATA(file_inode(file));  	unsigned int pos = *ppos; @@ -108,8 +107,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp  	return nbytes;  } -static ssize_t -proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos) +static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf, +				  size_t nbytes, loff_t *ppos)  {  	struct inode *ino = file_inode(file);  	struct pci_dev *dev = PDE_DATA(ino); @@ -222,7 +221,7 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,  	default:  		ret = -EINVAL;  		break; -	}; +	}  	return ret;  } @@ -413,7 +412,7 @@ int pci_proc_detach_device(struct pci_dev *dev)  	return 0;  } -int pci_proc_detach_bus(struct pci_bus* bus) +int pci_proc_detach_bus(struct pci_bus *bus)  {  	proc_remove(bus->procdir);  	return 0; @@ -423,6 +422,7 @@ static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)  {  	return seq_open(file, &proc_bus_pci_devices_op);  } +  static const struct file_operations proc_bus_pci_dev_operations = {  	.owner		= THIS_MODULE,  	.open		= proc_bus_pci_dev_open, @@ -443,6 +443,4 @@ static int __init pci_proc_init(void)  	return 0;  } -  device_initcall(pci_proc_init); - diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f6c31fabf3a..d0f69269eb6 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -9,10 +9,6 @@   *   *  Init/reset quirks for USB host controllers should be in the   *  USB quirks file, where their drivers can access reuse it. - * - *  The bridge optimization stuff has been removed. If you really - *  have a silly BIOS which is unable to set your host bridge right, - *  use the PowerTweak utility (see http://powertweak.sourceforge.net).   */  #include <linux/types.h> @@ -52,10 +48,10 @@ static void quirk_mellanox_tavor(struct pci_dev *dev)  {  	dev->broken_parity_status = 1;	/* This device gives false positives */  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR,quirk_mellanox_tavor); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX,PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE,quirk_mellanox_tavor); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR, quirk_mellanox_tavor); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_MELLANOX, PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE, quirk_mellanox_tavor); -/* Deal with broken BIOS'es that neglect to enable passive release, +/* Deal with broken BIOSes that neglect to enable passive release,     which can cause problems in combination with the 82441FX/PPro MTRRs */  static void quirk_passive_release(struct pci_dev *dev)  { @@ -78,15 +74,15 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_p  /*  The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround      but VIA don't answer queries. If you happen to have good contacts at VIA -    ask them for me please -- Alan  -     -    This appears to be BIOS not version dependent. So presumably there is a  +    ask them for me please -- Alan + +    This appears to be BIOS not version dependent. So presumably there is a      chipset level fix */ -     +  static void quirk_isa_dma_hangs(struct pci_dev *dev)  {  	if (!isa_dma_bridge_buggy) { -		isa_dma_bridge_buggy=1; +		isa_dma_bridge_buggy = 1;  		dev_info(&dev->dev, "Activating ISA DMA hang workarounds\n");  	}  } @@ -97,7 +93,7 @@ static void quirk_isa_dma_hangs(struct pci_dev *dev)  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C596,	quirk_isa_dma_hangs);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82371SB_0,  quirk_isa_dma_hangs); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533, 	quirk_isa_dma_hangs); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1533,		quirk_isa_dma_hangs);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_1,	quirk_isa_dma_hangs);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_2,	quirk_isa_dma_hangs);  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC,	PCI_DEVICE_ID_NEC_CBUS_3,	quirk_isa_dma_hangs); @@ -127,7 +123,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TGP_LPC, quirk   */  static void quirk_nopcipci(struct pci_dev *dev)  { -	if ((pci_pci_problems & PCIPCI_FAIL)==0) { +	if ((pci_pci_problems & PCIPCI_FAIL) == 0) {  		dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");  		pci_pci_problems |= PCIPCI_FAIL;  	} @@ -152,26 +148,26 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_8151_0,	quirk_nopci   */  static void quirk_triton(struct pci_dev *dev)  { -	if ((pci_pci_problems&PCIPCI_TRITON)==0) { +	if ((pci_pci_problems&PCIPCI_TRITON) == 0) {  		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");  		pci_pci_problems |= PCIPCI_TRITON;  	}  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437, 	quirk_triton); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82437VX, 	quirk_triton); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439, 	quirk_triton); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82439TX, 	quirk_triton); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82437,	quirk_triton); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82437VX,	quirk_triton); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82439,	quirk_triton); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82439TX,	quirk_triton);  /*   *	VIA Apollo KT133 needs PCI latency patch   *	Made according to a windows driver based patch by George E. Breese   *	see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm   *	and http://www.georgebreese.com/net/software/#PCI - *      Also see http://www.au-ja.org/review-kt133a-1-en.phtml for - *      the info on which Mr Breese based his work. + *	Also see http://www.au-ja.org/review-kt133a-1-en.phtml for + *	the info on which Mr Breese based his work.   *   *	Updated based on further information from the site and also on - *	information provided by VIA  + *	information provided by VIA   */  static void quirk_vialatency(struct pci_dev *dev)  { @@ -179,24 +175,24 @@ static void quirk_vialatency(struct pci_dev *dev)  	u8 busarb;  	/* Ok we have a potential problem chipset here. Now see if we have  	   a buggy southbridge */ -	    +  	p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL); -	if (p!=NULL) { +	if (p != NULL) {  		/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */  		/* Check for buggy part revisions */  		if (p->revision < 0x40 || p->revision > 0x42)  			goto exit;  	} else {  		p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL); -		if (p==NULL)	/* No problem parts */ +		if (p == NULL)	/* No problem parts */  			goto exit;  		/* Check for buggy part revisions */  		if (p->revision < 0x10 || p->revision > 0x12)  			goto exit;  	} -	 +  	/* -	 *	Ok we have the problem. Now set the PCI master grant to  +	 *	Ok we have the problem. Now set the PCI master grant to  	 *	occur every master grant. The apparent bug is that under high  	 *	PCI load (quite common in Linux of course) you can get data  	 *	loss when the CPU is held off the bus for 3 bus master requests @@ -209,7 +205,7 @@ static void quirk_vialatency(struct pci_dev *dev)  	 */  	pci_read_config_byte(dev, 0x76, &busarb); -	/* Set bit 4 and bi 5 of byte 76 to 0x01  +	/* Set bit 4 and bi 5 of byte 76 to 0x01  	   "Master priority rotation on every PCI master grant */  	busarb &= ~(1<<5);  	busarb |= (1<<4); @@ -231,7 +227,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8361,		quirk_viala   */  static void quirk_viaetbf(struct pci_dev *dev)  { -	if ((pci_pci_problems&PCIPCI_VIAETBF)==0) { +	if ((pci_pci_problems&PCIPCI_VIAETBF) == 0) {  		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");  		pci_pci_problems |= PCIPCI_VIAETBF;  	} @@ -240,7 +236,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C597_0,	quirk_via  static void quirk_vsfx(struct pci_dev *dev)  { -	if ((pci_pci_problems&PCIPCI_VSFX)==0) { +	if ((pci_pci_problems&PCIPCI_VSFX) == 0) {  		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");  		pci_pci_problems |= PCIPCI_VSFX;  	} @@ -252,16 +248,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C576,	quirk_vsfx)   *	that DMA to AGP space. Latency must be set to 0xA and triton   *	workaround applied too   *	[Info kindly provided by ALi] - */	 + */  static void quirk_alimagik(struct pci_dev *dev)  { -	if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) { +	if ((pci_pci_problems&PCIPCI_ALIMAGIK) == 0) {  		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");  		pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON;  	}  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1647, 	quirk_alimagik); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimagik); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1647,		quirk_alimagik); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL,	PCI_DEVICE_ID_AL_M1651,		quirk_alimagik);  /*   *	Natoma has some interesting boundary conditions with Zoran stuff @@ -269,17 +265,17 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, 	PCI_DEVICE_ID_AL_M1651, 	quirk_alimag   */  static void quirk_natoma(struct pci_dev *dev)  { -	if ((pci_pci_problems&PCIPCI_NATOMA)==0) { +	if ((pci_pci_problems&PCIPCI_NATOMA) == 0) {  		dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");  		pci_pci_problems |= PCIPCI_NATOMA;  	}  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82441, 	quirk_natoma); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_0, 	quirk_natoma); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443LX_1, 	quirk_natoma); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_0, 	quirk_natoma); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_1, 	quirk_natoma); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 	PCI_DEVICE_ID_INTEL_82443BX_2, 	quirk_natoma); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_natoma); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443LX_0,	quirk_natoma); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443LX_1,	quirk_natoma); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443BX_0,	quirk_natoma); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443BX_1,	quirk_natoma); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443BX_2,	quirk_natoma);  /*   *  This chip can cause PCI parity errors if config register 0xA0 is read @@ -300,6 +296,7 @@ static void quirk_s3_64M(struct pci_dev *dev)  	struct resource *r = &dev->resource[0];  	if ((r->start & 0x3ffffff) || r->end != r->start + 0x3ffffff) { +		r->flags |= IORESOURCE_UNSET;  		r->start = 0;  		r->end = 0x3ffffff;  	} @@ -318,8 +315,7 @@ static void quirk_cs5536_vsa(struct pci_dev *dev)  	if (pci_resource_len(dev, 0) != 8) {  		struct resource *res = &dev->resource[0];  		res->end = res->start + 8 - 1; -		dev_info(&dev->dev, "CS5536 ISA bridge bug detected " -				"(incorrect header); workaround applied.\n"); +		dev_info(&dev->dev, "CS5536 ISA bridge bug detected (incorrect header); workaround applied\n");  	}  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); @@ -343,7 +339,7 @@ static void quirk_io_region(struct pci_dev *dev, int port,  	/* Convert from PCI bus to resource space */  	bus_region.start = region;  	bus_region.end = region + size - 1; -	pcibios_bus_to_resource(dev, res, &bus_region); +	pcibios_bus_to_resource(dev->bus, res, &bus_region);  	if (!pci_claim_resource(dev, nr))  		dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name); @@ -400,10 +396,11 @@ static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int p  	/*  	 * For now we only print it out. Eventually we'll want to  	 * reserve it (at least if it's in the 0x1000+ range), but -	 * let's get enough confirmation reports first.  +	 * let's get enough confirmation reports first.  	 */  	base &= -size; -	dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base + size - 1); +	dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, +		 base + size - 1);  }  static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable) @@ -425,10 +422,11 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int  	}  	/*  	 * For now we only print it out. Eventually we'll want to -	 * reserve it, but let's get enough confirmation reports first.  +	 * reserve it, but let's get enough confirmation reports first.  	 */  	base &= -size; -	dev_info(&dev->dev, "%s MMIO at %04x-%04x\n", name, base, base + size - 1); +	dev_info(&dev->dev, "%s MMIO at %04x-%04x\n", name, base, +		 base + size - 1);  }  /* @@ -671,8 +669,7 @@ static void quirk_xio2000a(struct pci_dev *dev)  	struct pci_dev *pdev;  	u16 command; -	dev_warn(&dev->dev, "TI XIO2000a quirk detected; " -		"secondary bus fast back-to-back transfers disabled\n"); +	dev_warn(&dev->dev, "TI XIO2000a quirk detected; secondary bus fast back-to-back transfers disabled\n");  	list_for_each_entry(pdev, &dev->subordinate->devices, bus_list) {  		pci_read_config_word(pdev, PCI_COMMAND, &command);  		if (command & PCI_COMMAND_FAST_BACK) @@ -682,7 +679,7 @@ static void quirk_xio2000a(struct pci_dev *dev)  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XIO2000A,  			quirk_xio2000a); -#ifdef CONFIG_X86_IO_APIC  +#ifdef CONFIG_X86_IO_APIC  #include <asm/io_apic.h> @@ -696,23 +693,23 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XIO2000A,  static void quirk_via_ioapic(struct pci_dev *dev)  {  	u8 tmp; -	 +  	if (nr_ioapics < 1)  		tmp = 0;    /* nothing routed to external APIC */  	else  		tmp = 0x1f; /* all known bits (4-0) routed to external APIC */ -		 +  	dev_info(&dev->dev, "%sbling VIA external APIC routing\n",  	       tmp == 0 ? "Disa" : "Ena");  	/* Offset 0x58: External APIC IRQ output control */ -	pci_write_config_byte (dev, 0x58, tmp); +	pci_write_config_byte(dev, 0x58, tmp);  }  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic);  DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic);  /* - * VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit. + * VIA 8237: Some BIOSes don't set the 'Bypass APIC De-Assert Message' Bit.   * This leads to doubled level interrupt rates.   * Set this bit to get rid of cycle wastage.   * Otherwise uncritical. @@ -764,8 +761,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw);  static void quirk_amd_8131_mmrbc(struct pci_dev *dev)  {  	if (dev->subordinate && dev->revision <= 0x12) { -		dev_info(&dev->dev, "AMD8131 rev %x detected; " -			"disabling PCI-X MMRBC\n", dev->revision); +		dev_info(&dev->dev, "AMD8131 rev %x detected; disabling PCI-X MMRBC\n", +			 dev->revision);  		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;  	}  } @@ -919,12 +916,12 @@ static void quirk_amd_ordering(struct pci_dev *dev)  {  	u32 pcic;  	pci_read_config_dword(dev, 0x4C, &pcic); -	if ((pcic&6)!=6) { +	if ((pcic & 6) != 6) {  		pcic |= 6;  		dev_warn(&dev->dev, "BIOS failed to enable PCI standards compliance; fixing this error\n");  		pci_write_config_dword(dev, 0x4C, pcic);  		pci_read_config_dword(dev, 0x84, &pcic); -		pcic |= (1<<23);	/* Required in this mode */ +		pcic |= (1 << 23);	/* Required in this mode */  		pci_write_config_dword(dev, 0x84, pcic);  	}  } @@ -940,7 +937,9 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_FE_GATE_700C   */  static void quirk_dunord(struct pci_dev *dev)  { -	struct resource *r = &dev->resource [1]; +	struct resource *r = &dev->resource[1]; + +	r->flags |= IORESOURCE_UNSET;  	r->start = 0;  	r->end = 0xffffff;  } @@ -968,11 +967,13 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA,	0x605,	quirk_transparent_bridge)  static void quirk_mediagx_master(struct pci_dev *dev)  {  	u8 reg; +  	pci_read_config_byte(dev, 0x41, ®);  	if (reg & 2) {  		reg &= ~2; -		dev_info(&dev->dev, "Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg); -                pci_write_config_byte(dev, 0x41, reg); +		dev_info(&dev->dev, "Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", +			 reg); +		pci_write_config_byte(dev, 0x41, reg);  	}  }  DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master); @@ -986,7 +987,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX,	PCI_DEVICE_ID_CYRIX_PCI_MASTER, qu  static void quirk_disable_pxb(struct pci_dev *pdev)  {  	u16 config; -	 +  	if (pdev->revision != 0x04)		/* Only C0 requires this */  		return;  	pci_read_config_word(pdev, 0x40, &config); @@ -1094,11 +1095,11 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82375,	quirk_e   * On ASUS P4B boards, the SMBus PCI Device within the ICH2/4 southbridge   * is not activated. The myth is that Asus said that they do not want the   * users to be irritated by just another PCI Device in the Win98 device - * manager. (see the file prog/hotplug/README.p4b in the lm_sensors  + * manager. (see the file prog/hotplug/README.p4b in the lm_sensors   * package 2.7.0 for details)   * - * The SMBus PCI Device can be activated by setting a bit in the ICH LPC  - * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it  + * The SMBus PCI Device can be activated by setting a bit in the ICH LPC + * bridge. Unfortunately, this device has no subvendor/subdevice ID. So it   * becomes necessary to do this tweak in two steps -- the chosen trigger   * is either the Host bridge (preferred) or on-board VGA controller.   * @@ -1121,7 +1122,7 @@ static void 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) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0x8025: /* P4B-LX */  			case 0x8070: /* P4B */  			case 0x8088: /* P4B533 */ @@ -1129,14 +1130,14 @@ static void asus_hides_smbus_hostbridge(struct pci_dev *dev)  				asus_hides_smbus = 1;  			}  		else if (dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0x80b1: /* P4GE-V */  			case 0x80b2: /* P4PE */  			case 0x8093: /* P4B533-V */  				asus_hides_smbus = 1;  			}  		else if (dev->device == PCI_DEVICE_ID_INTEL_82850_HB) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0x8030: /* P4T533 */  				asus_hides_smbus = 1;  			} @@ -1176,7 +1177,7 @@ static void asus_hides_smbus_hostbridge(struct pci_dev *dev)  			}  	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_HP)) {  		if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0x088C: /* HP Compaq nc8000 */  			case 0x0890: /* HP Compaq nc6000 */  				asus_hides_smbus = 1; @@ -1193,20 +1194,20 @@ static void asus_hides_smbus_hostbridge(struct pci_dev *dev)  			case 0x12bf: /* HP xw4100 */  				asus_hides_smbus = 1;  			} -       } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) { -               if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB) -                       switch(dev->subsystem_device) { -                       case 0xC00C: /* Samsung P35 notebook */ -                               asus_hides_smbus = 1; -                       } +	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) { +		if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB) +			switch (dev->subsystem_device) { +			case 0xC00C: /* Samsung P35 notebook */ +				asus_hides_smbus = 1; +		}  	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ)) {  		if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0x0058: /* Compaq Evo N620c */  				asus_hides_smbus = 1;  			}  		else if (dev->device == PCI_DEVICE_ID_INTEL_82810_IG3) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0xB16C: /* Compaq Deskpro EP 401963-001 (PCA# 010174) */  				/* Motherboard doesn't have Host bridge  				 * subvendor/subdevice IDs, therefore checking @@ -1214,7 +1215,7 @@ static void asus_hides_smbus_hostbridge(struct pci_dev *dev)  				asus_hides_smbus = 1;  			}  		else if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_2) -			switch(dev->subsystem_device) { +			switch (dev->subsystem_device) {  			case 0x00b8: /* Compaq Evo D510 CMT */  			case 0x00b9: /* Compaq Evo D510 SFF */  			case 0x00ba: /* Compaq Evo D510 USDT */ @@ -1253,7 +1254,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82815_CGC,	asu  static void asus_hides_smbus_lpc(struct pci_dev *dev)  {  	u16 val; -	 +  	if (likely(!asus_hides_smbus))  		return; @@ -1262,7 +1263,8 @@ static void asus_hides_smbus_lpc(struct pci_dev *dev)  		pci_write_config_word(dev, 0xF2, val & (~0x8));  		pci_read_config_word(dev, 0xF2, &val);  		if (val & 0x8) -			dev_info(&dev->dev, "i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val); +			dev_info(&dev->dev, "i801 SMBus device continues to play 'hide and seek'! 0x%x\n", +				 val);  		else  			dev_info(&dev->dev, "Enabled i801 SMBus device\n");  	} @@ -1410,7 +1412,8 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev)  		pci_write_config_byte(dev, 0x50, val & (~0xc0));  		pci_read_config_byte(dev, 0x50, &val);  		if (val & 0xc0) -			dev_info(&dev->dev, "Onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val); +			dev_info(&dev->dev, "Onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", +				 val);  		else  			dev_info(&dev->dev, "Enabled onboard AC97/MC97 devices\n");  	} @@ -1515,10 +1518,8 @@ static void quirk_alder_ioapic(struct pci_dev *pdev)  	/* The next five BARs all seem to be rubbish, so just clean  	 * them out */ -	for (i=1; i < 6; i++) { +	for (i = 1; i < 6; i++)  		memset(&pdev->resource[i], 0, sizeof(pdev->resource[i])); -	} -  }  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_EESSC,	quirk_alder_ioapic);  #endif @@ -1553,7 +1554,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_PXHV,	quirk_pci   * Some Intel PCI Express chipsets have trouble with downstream   * device power management.   */ -static void quirk_intel_pcie_pm(struct pci_dev * dev) +static void quirk_intel_pcie_pm(struct pci_dev *dev)  {  	pci_pm_d3_delay = 120;  	dev->no_d1d2 = 1; @@ -1640,8 +1641,8 @@ static void quirk_disable_intel_boot_interrupt(struct pci_dev *dev)  	dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n",  		 dev->vendor, dev->device);  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ESB_10, 	quirk_disable_intel_boot_interrupt); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ESB_10, 	quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ESB_10,	quirk_disable_intel_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_ESB_10,	quirk_disable_intel_boot_interrupt);  /*   * disable boot interrupts on HT-1000 @@ -1673,8 +1674,8 @@ static void quirk_disable_broadcom_boot_interrupt(struct pci_dev *dev)  	dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n",  		 dev->vendor, dev->device);  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS,   PCI_DEVICE_ID_SERVERWORKS_HT1000SB, 	quirk_disable_broadcom_boot_interrupt); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS,   PCI_DEVICE_ID_SERVERWORKS_HT1000SB, 	quirk_disable_broadcom_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS,   PCI_DEVICE_ID_SERVERWORKS_HT1000SB,	quirk_disable_broadcom_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS,   PCI_DEVICE_ID_SERVERWORKS_HT1000SB,	quirk_disable_broadcom_boot_interrupt);  /*   * disable boot interrupts on AMD and ATI chipsets @@ -1722,16 +1723,16 @@ static void quirk_disable_amd_8111_boot_interrupt(struct pci_dev *dev)  	pci_read_config_word(dev, AMD_8111_PCI_IRQ_ROUTING, &pci_config_word);  	if (!pci_config_word) { -		dev_info(&dev->dev, "boot interrupts on device [%04x:%04x] " -			 "already disabled\n", dev->vendor, dev->device); +		dev_info(&dev->dev, "boot interrupts on device [%04x:%04x] already disabled\n", +			 dev->vendor, dev->device);  		return;  	}  	pci_write_config_word(dev, AMD_8111_PCI_IRQ_ROUTING, 0);  	dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n",  		 dev->vendor, dev->device);  } -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8111_SMBUS, 	quirk_disable_amd_8111_boot_interrupt); -DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8111_SMBUS, 	quirk_disable_amd_8111_boot_interrupt); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8111_SMBUS,	quirk_disable_amd_8111_boot_interrupt); +DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD,   PCI_DEVICE_ID_AMD_8111_SMBUS,	quirk_disable_amd_8111_boot_interrupt);  #endif /* CONFIG_X86_IO_APIC */  /* @@ -1744,6 +1745,7 @@ static void quirk_tc86c001_ide(struct pci_dev *dev)  	struct resource *r = &dev->resource[0];  	if (r->start & 0x8) { +		r->flags |= IORESOURCE_UNSET;  		r->start = 0;  		r->end = 0xf;  	} @@ -1770,9 +1772,9 @@ static void quirk_plx_pci9050(struct pci_dev *dev)  		if (pci_resource_len(dev, bar) == 0x80 &&  		    (pci_resource_start(dev, bar) & 0x80)) {  			struct resource *r = &dev->resource[bar]; -			dev_info(&dev->dev, -				 "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n", +			dev_info(&dev->dev, "Re-allocating PLX PCI 9050 BAR %u to length 256 to avoid bit 7 bug\n",  				 bar); +			r->flags |= IORESOURCE_UNSET;  			r->start = 0;  			r->end = 0xff;  		} @@ -1817,9 +1819,7 @@ static void quirk_netmos(struct pci_dev *dev)  	case PCI_DEVICE_ID_NETMOS_9845:  	case PCI_DEVICE_ID_NETMOS_9855:  		if (num_parallel) { -			dev_info(&dev->dev, "Netmos %04x (%u parallel, " -				"%u serial); changing class SERIAL to OTHER " -				"(use parport_serial)\n", +			dev_info(&dev->dev, "Netmos %04x (%u parallel, %u serial); changing class SERIAL to OTHER (use parport_serial)\n",  				dev->device, num_parallel, num_serial);  			dev->class = (PCI_CLASS_COMMUNICATION_OTHER << 8) |  			    (dev->class & 0xff); @@ -1886,8 +1886,7 @@ static void quirk_e100_interrupt(struct pci_dev *dev)  	cmd_hi = readb(csr + 3);  	if (cmd_hi == 0) { -		dev_warn(&dev->dev, "Firmware left e100 interrupts enabled; " -			"disabling\n"); +		dev_warn(&dev->dev, "Firmware left e100 interrupts enabled; disabling\n");  		writeb(1, csr + 3);  	} @@ -1957,8 +1956,7 @@ static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)  	if (pci_read_config_byte(dev, 0xf41, &b) == 0) {  		if (!(b & 0x20)) {  			pci_write_config_byte(dev, 0xf41, b | 0x20); -			dev_info(&dev->dev, -			       "Linking AER extended capability\n"); +			dev_info(&dev->dev, "Linking AER extended capability\n");  		}  	}  } @@ -1996,8 +1994,7 @@ static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)  			/* Turn off PCI Bus Parking */  			pci_write_config_byte(dev, 0x76, b ^ 0x40); -			dev_info(&dev->dev, -				"Disabling VIA CX700 PCI parking\n"); +			dev_info(&dev->dev, "Disabling VIA CX700 PCI parking\n");  		}  	} @@ -2012,8 +2009,7 @@ static void quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)  			/* Disable "Read FIFO Timer" */  			pci_write_config_byte(dev, 0x77, 0x0); -			dev_info(&dev->dev, -				"Disabling VIA CX700 PCI caching\n"); +			dev_info(&dev->dev, "Disabling VIA CX700 PCI caching\n");  		}  	}  } @@ -2127,8 +2123,8 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);  #ifdef CONFIG_PCI_MSI  /* Some chipsets do not support MSI. We cannot easily rely on setting   * PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually - * some other busses controlled by the chipset even if Linux is not - * aware of it.  Instead of setting the flag on all busses in the + * some other buses controlled by the chipset even if Linux is not + * aware of it.  Instead of setting the flag on all buses in the   * machine, simply disable MSI globally.   */  static void quirk_disable_all_msi(struct pci_dev *dev) @@ -2148,8 +2144,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disab  static void quirk_disable_msi(struct pci_dev *dev)  {  	if (dev->subordinate) { -		dev_warn(&dev->dev, "MSI quirk detected; " -			"subordinate MSI disabled\n"); +		dev_warn(&dev->dev, "MSI quirk detected; subordinate MSI disabled\n");  		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;  	}  } @@ -2188,8 +2183,7 @@ static int msi_ht_cap_enabled(struct pci_dev *dev)  		u8 flags;  		if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, -					 &flags) == 0) -		{ +					 &flags) == 0) {  			dev_info(&dev->dev, "Found %s HT MSI Mapping\n",  				flags & HT_MSI_FLAGS_ENABLE ?  				"enabled" : "disabled"); @@ -2206,8 +2200,7 @@ static int msi_ht_cap_enabled(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; " -			"subordinate MSI disabled\n"); +		dev_warn(&dev->dev, "MSI quirk detected; subordinate MSI disabled\n");  		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;  	}  } @@ -2231,8 +2224,7 @@ static void quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)  	if (!pdev)  		return;  	if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) { -		dev_warn(&dev->dev, "MSI quirk detected; " -			"subordinate MSI disabled\n"); +		dev_warn(&dev->dev, "MSI quirk detected; subordinate MSI disabled\n");  		dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;  	}  	pci_dev_put(pdev); @@ -2278,8 +2270,7 @@ static void nvenet_msi_disable(struct pci_dev *dev)  	if (board_name &&  	    (strstr(board_name, "P5N32-SLI PREMIUM") ||  	     strstr(board_name, "P5N32-E SLI"))) { -		dev_info(&dev->dev, -			 "Disabling msi for MCP55 NIC on P5N32-SLI\n"); +		dev_info(&dev->dev, "Disabling msi for MCP55 NIC on P5N32-SLI\n");  		dev->no_msi = 1;  	}  } @@ -2288,14 +2279,14 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA,  			nvenet_msi_disable);  /* - * Some versions of the MCP55 bridge from nvidia have a legacy irq routing - * config register.  This register controls the routing of legacy interrupts - * from devices that route through the MCP55.  If this register is misprogramed - * interrupts are only sent to the bsp, unlike conventional systems where the - * irq is broadxast to all online cpus.  Not having this register set - * properly prevents kdump from booting up properly, so lets make sure that - * we have it set correctly. - * Note this is an undocumented register. + * Some versions of the MCP55 bridge from Nvidia have a legacy IRQ routing + * config register.  This register controls the routing of legacy + * interrupts from devices that route through the MCP55.  If this register + * is misprogrammed, interrupts are only sent to the BSP, unlike + * conventional systems where the IRQ is broadcast to all online CPUs.  Not + * having this register set properly prevents kdump from booting up + * properly, so let's make sure that we have it set correctly. + * Note that this is an undocumented register.   */  static void nvbridge_check_legacy_irq_routing(struct pci_dev *dev)  { @@ -2488,8 +2479,7 @@ static void __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)  	 */  	host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0));  	if (host_bridge == NULL) { -		dev_warn(&dev->dev, -			 "nv_msi_ht_cap_quirk didn't locate host bridge\n"); +		dev_warn(&dev->dev, "nv_msi_ht_cap_quirk didn't locate host bridge\n");  		return;  	} @@ -2626,7 +2616,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0xe091,  /* Allow manual resource allocation for PCI hotplug bridges   * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For   * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6), - * kernel fails to allocate resources when hotplug device is  + * kernel fails to allocate resources when hotplug device is   * inserted and PCI bus is rescanned.   */  static void quirk_hotplug_bridge(struct pci_dev *dev) @@ -2816,8 +2806,7 @@ static void quirk_intel_mc_errata(struct pci_dev *dev)  	 */  	err = pci_read_config_word(dev, 0x48, &rcc);  	if (err) { -		dev_err(&dev->dev, "Error attempting to read the read " -			"completion coalescing register.\n"); +		dev_err(&dev->dev, "Error attempting to read the read completion coalescing register\n");  		return;  	} @@ -2828,13 +2817,11 @@ static void quirk_intel_mc_errata(struct pci_dev *dev)  	err = pci_write_config_word(dev, 0x48, rcc);  	if (err) { -		dev_err(&dev->dev, "Error attempting to write the read " -			"completion coalescing register.\n"); +		dev_err(&dev->dev, "Error attempting to write the read completion coalescing register\n");  		return;  	} -	pr_info_once("Read completion coalescing disabled due to hardware " -		     "errata relating to 256B MPS.\n"); +	pr_info_once("Read completion coalescing disabled due to hardware errata relating to 256B MPS\n");  }  /* Intel 5000 series memory controllers and ports 2-7 */  DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x25c0, quirk_intel_mc_errata); @@ -2943,8 +2930,7 @@ static void disable_igfx_irq(struct pci_dev *dev)  	/* Check if any interrupt line is still enabled */  	if (readl(regs + I915_DEIER_REG) != 0) { -		dev_warn(&dev->dev, "BIOS left Intel GPU interrupts enabled; " -			"disabling\n"); +		dev_warn(&dev->dev, "BIOS left Intel GPU interrupts enabled; disabling\n");  		writel(0, regs + I915_DEIER_REG);  	} @@ -2953,6 +2939,30 @@ static void 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); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0152, disable_igfx_irq); + +/* + * PCI devices which are on Intel chips can skip the 10ms delay + * before entering D3 mode. + */ +static void quirk_remove_d3_delay(struct pci_dev *dev) +{ +	dev->d3_delay = 0; +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0412, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c0c, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c18, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c1c, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay);  /*   * Some devices may pass our check in pci_intx_mask_supported if @@ -2967,6 +2977,14 @@ 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); +/* + * Realtek RTL8169 PCI Gigabit Ethernet Controller (rev 10) + * Subsystem: Realtek RTL8169/8110 Family PCI Gigabit Ethernet NIC + * + * RTL8110SC - Fails under PCI device assignment using DisINTx masking. + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_REALTEK, 0x8169, +			 quirk_broken_intx_masking);  static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,  			  struct pci_fixup *end) @@ -3007,7 +3025,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)  {  	struct pci_fixup *start, *end; -	switch(pass) { +	switch (pass) {  	case pci_fixup_early:  		start = __start_pci_fixups_early;  		end = __end_pci_fixups_early; @@ -3079,8 +3097,8 @@ static int __init pci_apply_final_quirks(void)  			if (!tmp || cls == tmp)  				continue; -			printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), " -			       "using %u bytes\n", cls << 2, tmp << 2, +			printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), using %u bytes\n", +			       cls << 2, tmp << 2,  			       pci_dfl_cache_line_size << 2);  			pci_cache_line_size = pci_dfl_cache_line_size;  		} @@ -3309,6 +3327,85 @@ int pci_dev_specific_reset(struct pci_dev *dev, int probe)  	return -ENOTTY;  } +static void quirk_dma_func0_alias(struct pci_dev *dev) +{ +	if (PCI_FUNC(dev->devfn) != 0) { +		dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0); +		dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; +	} +} + +/* + * https://bugzilla.redhat.com/show_bug.cgi?id=605888 + * + * Some Ricoh devices use function 0 as the PCIe requester ID for DMA. + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe832, quirk_dma_func0_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RICOH, 0xe476, quirk_dma_func0_alias); + +static void quirk_dma_func1_alias(struct pci_dev *dev) +{ +	if (PCI_FUNC(dev->devfn) != 1) { +		dev->dma_alias_devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 1); +		dev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN; +	} +} + +/* + * Marvell 88SE9123 uses function 1 as the requester ID for DMA.  In some + * SKUs function 1 is present and is a legacy IDE controller, in other + * SKUs this function is not present, making this a ghost requester. + * https://bugzilla.kernel.org/show_bug.cgi?id=42679 + */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9123, +			 quirk_dma_func1_alias); +/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c14 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9130, +			 quirk_dma_func1_alias); +/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c47 + c57 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9172, +			 quirk_dma_func1_alias); +/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c59 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x917a, +			 quirk_dma_func1_alias); +/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c46 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x91a0, +			 quirk_dma_func1_alias); +/* https://bugzilla.kernel.org/show_bug.cgi?id=42679#c49 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL_EXT, 0x9230, +			 quirk_dma_func1_alias); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TTI, 0x0642, +			 quirk_dma_func1_alias); +/* https://bugs.gentoo.org/show_bug.cgi?id=497630 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JMICRON, +			 PCI_DEVICE_ID_JMICRON_JMB388_ESD, +			 quirk_dma_func1_alias); + +/* + * A few PCIe-to-PCI bridges fail to expose a PCIe capability, resulting in + * using the wrong DMA alias for the device.  Some of these devices can be + * used as either forward or reverse bridges, so we need to test whether the + * device is operating in the correct mode.  We could probably apply this + * quirk to PCI_ANY_ID, but for now we'll just use known offenders.  The test + * is for a non-root, non-PCIe bridge where the upstream device is PCIe and + * is not a PCIe-to-PCI bridge, then @pdev is actually a PCIe-to-PCI bridge. + */ +static void quirk_use_pcie_bridge_dma_alias(struct pci_dev *pdev) +{ +	if (!pci_is_root_bus(pdev->bus) && +	    pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE && +	    !pci_is_pcie(pdev) && pci_is_pcie(pdev->bus->self) && +	    pci_pcie_type(pdev->bus->self) != PCI_EXP_TYPE_PCI_BRIDGE) +		pdev->dev_flags |= PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS; +} +/* ASM1083/1085, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c46 */ +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1080, +			 quirk_use_pcie_bridge_dma_alias); +/* Tundra 8113, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c43 */ +DECLARE_PCI_FIXUP_HEADER(0x10e3, 0x8113, quirk_use_pcie_bridge_dma_alias); +/* ITE 8892, https://bugzilla.kernel.org/show_bug.cgi?id=73551 */ +DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias); +  static struct pci_dev *pci_func_0_dma_source(struct pci_dev *dev)  {  	if (!PCI_FUNC(dev->devfn)) @@ -3404,6 +3501,63 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags)  #endif  } +/* + * Many Intel PCH root ports do provide ACS-like features to disable peer + * transactions and validate bus numbers in requests, but do not provide an + * actual PCIe ACS capability.  This is the list of device IDs known to fall + * into that category as provided by Intel in Red Hat bugzilla 1037684. + */ +static const u16 pci_quirk_intel_pch_acs_ids[] = { +	/* Ibexpeak PCH */ +	0x3b42, 0x3b43, 0x3b44, 0x3b45, 0x3b46, 0x3b47, 0x3b48, 0x3b49, +	0x3b4a, 0x3b4b, 0x3b4c, 0x3b4d, 0x3b4e, 0x3b4f, 0x3b50, 0x3b51, +	/* Cougarpoint PCH */ +	0x1c10, 0x1c11, 0x1c12, 0x1c13, 0x1c14, 0x1c15, 0x1c16, 0x1c17, +	0x1c18, 0x1c19, 0x1c1a, 0x1c1b, 0x1c1c, 0x1c1d, 0x1c1e, 0x1c1f, +	/* Pantherpoint PCH */ +	0x1e10, 0x1e11, 0x1e12, 0x1e13, 0x1e14, 0x1e15, 0x1e16, 0x1e17, +	0x1e18, 0x1e19, 0x1e1a, 0x1e1b, 0x1e1c, 0x1e1d, 0x1e1e, 0x1e1f, +	/* Lynxpoint-H PCH */ +	0x8c10, 0x8c11, 0x8c12, 0x8c13, 0x8c14, 0x8c15, 0x8c16, 0x8c17, +	0x8c18, 0x8c19, 0x8c1a, 0x8c1b, 0x8c1c, 0x8c1d, 0x8c1e, 0x8c1f, +	/* Lynxpoint-LP PCH */ +	0x9c10, 0x9c11, 0x9c12, 0x9c13, 0x9c14, 0x9c15, 0x9c16, 0x9c17, +	0x9c18, 0x9c19, 0x9c1a, 0x9c1b, +	/* Wildcat PCH */ +	0x9c90, 0x9c91, 0x9c92, 0x9c93, 0x9c94, 0x9c95, 0x9c96, 0x9c97, +	0x9c98, 0x9c99, 0x9c9a, 0x9c9b, +	/* Patsburg (X79) PCH */ +	0x1d10, 0x1d12, 0x1d14, 0x1d16, 0x1d18, 0x1d1a, 0x1d1c, 0x1d1e, +}; + +static bool pci_quirk_intel_pch_acs_match(struct pci_dev *dev) +{ +	int i; + +	/* Filter out a few obvious non-matches first */ +	if (!pci_is_pcie(dev) || pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) +		return false; + +	for (i = 0; i < ARRAY_SIZE(pci_quirk_intel_pch_acs_ids); i++) +		if (pci_quirk_intel_pch_acs_ids[i] == dev->device) +			return true; + +	return false; +} + +#define INTEL_PCH_ACS_FLAGS (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_SV) + +static int pci_quirk_intel_pch_acs(struct pci_dev *dev, u16 acs_flags) +{ +	u16 flags = dev->dev_flags & PCI_DEV_FLAGS_ACS_ENABLED_QUIRK ? +		    INTEL_PCH_ACS_FLAGS : 0; + +	if (!pci_quirk_intel_pch_acs_match(dev)) +		return -ENOTTY; + +	return acs_flags & ~flags ? 0 : 1; +} +  static const struct pci_dev_acs_enabled {  	u16 vendor;  	u16 device; @@ -3415,6 +3569,7 @@ static const struct pci_dev_acs_enabled {  	{ PCI_VENDOR_ID_ATI, 0x439d, pci_quirk_amd_sb_acs },  	{ PCI_VENDOR_ID_ATI, 0x4384, pci_quirk_amd_sb_acs },  	{ PCI_VENDOR_ID_ATI, 0x4399, pci_quirk_amd_sb_acs }, +	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs },  	{ 0 }  }; @@ -3442,3 +3597,132 @@ int pci_dev_specific_acs_enabled(struct pci_dev *dev, u16 acs_flags)  	return -ENOTTY;  } + +/* Config space offset of Root Complex Base Address register */ +#define INTEL_LPC_RCBA_REG 0xf0 +/* 31:14 RCBA address */ +#define INTEL_LPC_RCBA_MASK 0xffffc000 +/* RCBA Enable */ +#define INTEL_LPC_RCBA_ENABLE (1 << 0) + +/* Backbone Scratch Pad Register */ +#define INTEL_BSPR_REG 0x1104 +/* Backbone Peer Non-Posted Disable */ +#define INTEL_BSPR_REG_BPNPD (1 << 8) +/* Backbone Peer Posted Disable */ +#define INTEL_BSPR_REG_BPPD  (1 << 9) + +/* Upstream Peer Decode Configuration Register */ +#define INTEL_UPDCR_REG 0x1114 +/* 5:0 Peer Decode Enable bits */ +#define INTEL_UPDCR_REG_MASK 0x3f + +static int pci_quirk_enable_intel_lpc_acs(struct pci_dev *dev) +{ +	u32 rcba, bspr, updcr; +	void __iomem *rcba_mem; + +	/* +	 * Read the RCBA register from the LPC (D31:F0).  PCH root ports +	 * are D28:F* and therefore get probed before LPC, thus we can't +	 * use pci_get_slot/pci_read_config_dword here. +	 */ +	pci_bus_read_config_dword(dev->bus, PCI_DEVFN(31, 0), +				  INTEL_LPC_RCBA_REG, &rcba); +	if (!(rcba & INTEL_LPC_RCBA_ENABLE)) +		return -EINVAL; + +	rcba_mem = ioremap_nocache(rcba & INTEL_LPC_RCBA_MASK, +				   PAGE_ALIGN(INTEL_UPDCR_REG)); +	if (!rcba_mem) +		return -ENOMEM; + +	/* +	 * The BSPR can disallow peer cycles, but it's set by soft strap and +	 * therefore read-only.  If both posted and non-posted peer cycles are +	 * disallowed, we're ok.  If either are allowed, then we need to use +	 * the UPDCR to disable peer decodes for each port.  This provides the +	 * PCIe ACS equivalent of PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_UF +	 */ +	bspr = readl(rcba_mem + INTEL_BSPR_REG); +	bspr &= INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD; +	if (bspr != (INTEL_BSPR_REG_BPNPD | INTEL_BSPR_REG_BPPD)) { +		updcr = readl(rcba_mem + INTEL_UPDCR_REG); +		if (updcr & INTEL_UPDCR_REG_MASK) { +			dev_info(&dev->dev, "Disabling UPDCR peer decodes\n"); +			updcr &= ~INTEL_UPDCR_REG_MASK; +			writel(updcr, rcba_mem + INTEL_UPDCR_REG); +		} +	} + +	iounmap(rcba_mem); +	return 0; +} + +/* Miscellaneous Port Configuration register */ +#define INTEL_MPC_REG 0xd8 +/* MPC: Invalid Receive Bus Number Check Enable */ +#define INTEL_MPC_REG_IRBNCE (1 << 26) + +static void pci_quirk_enable_intel_rp_mpc_acs(struct pci_dev *dev) +{ +	u32 mpc; + +	/* +	 * When enabled, the IRBNCE bit of the MPC register enables the +	 * equivalent of PCI ACS Source Validation (PCI_ACS_SV), which +	 * ensures that requester IDs fall within the bus number range +	 * of the bridge.  Enable if not already. +	 */ +	pci_read_config_dword(dev, INTEL_MPC_REG, &mpc); +	if (!(mpc & INTEL_MPC_REG_IRBNCE)) { +		dev_info(&dev->dev, "Enabling MPC IRBNCE\n"); +		mpc |= INTEL_MPC_REG_IRBNCE; +		pci_write_config_word(dev, INTEL_MPC_REG, mpc); +	} +} + +static int pci_quirk_enable_intel_pch_acs(struct pci_dev *dev) +{ +	if (!pci_quirk_intel_pch_acs_match(dev)) +		return -ENOTTY; + +	if (pci_quirk_enable_intel_lpc_acs(dev)) { +		dev_warn(&dev->dev, "Failed to enable Intel PCH ACS quirk\n"); +		return 0; +	} + +	pci_quirk_enable_intel_rp_mpc_acs(dev); + +	dev->dev_flags |= PCI_DEV_FLAGS_ACS_ENABLED_QUIRK; + +	dev_info(&dev->dev, "Intel PCH root port ACS workaround enabled\n"); + +	return 0; +} + +static const struct pci_dev_enable_acs { +	u16 vendor; +	u16 device; +	int (*enable_acs)(struct pci_dev *dev); +} pci_dev_enable_acs[] = { +	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_enable_intel_pch_acs }, +	{ 0 } +}; + +void pci_dev_specific_enable_acs(struct pci_dev *dev) +{ +	const struct pci_dev_enable_acs *i; +	int ret; + +	for (i = pci_dev_enable_acs; i->enable_acs; i++) { +		if ((i->vendor == dev->vendor || +		     i->vendor == (u16)PCI_ANY_ID) && +		    (i->device == dev->device || +		     i->device == (u16)PCI_ANY_ID)) { +			ret = i->enable_acs(dev); +			if (ret >= 0) +				return; +		} +	} +} diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 8fc54b7327b..8bd76c9ba21 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -7,8 +7,6 @@ static void pci_free_resources(struct pci_dev *dev)  {  	int i; - 	msi_remove_pci_irq_vectors(dev); -  	pci_cleanup_rom(dev);  	for (i = 0; i < PCI_NUM_RESOURCES; i++) {  		struct resource *res = dev->resource + i; @@ -24,7 +22,7 @@ static void pci_stop_dev(struct pci_dev *dev)  	if (dev->is_added) {  		pci_proc_detach_device(dev);  		pci_remove_sysfs_dev_files(dev); -		device_del(&dev->dev); +		device_release_driver(&dev->dev);  		dev->is_added = 0;  	} @@ -34,6 +32,11 @@ static void pci_stop_dev(struct pci_dev *dev)  static void pci_destroy_dev(struct pci_dev *dev)  { +	if (!dev->dev.kobj.parent) +		return; + +	device_del(&dev->dev); +  	down_write(&pci_bus_sem);  	list_del(&dev->bus_list);  	up_write(&pci_bus_sem); @@ -112,6 +115,14 @@ void pci_stop_and_remove_bus_device(struct pci_dev *dev)  }  EXPORT_SYMBOL(pci_stop_and_remove_bus_device); +void pci_stop_and_remove_bus_device_locked(struct pci_dev *dev) +{ +	pci_lock_rescan_remove(); +	pci_stop_and_remove_bus_device(dev); +	pci_unlock_rescan_remove(); +} +EXPORT_SYMBOL_GPL(pci_stop_and_remove_bus_device_locked); +  void pci_stop_root_bus(struct pci_bus *bus)  {  	struct pci_dev *child, *tmp; @@ -126,7 +137,7 @@ void pci_stop_root_bus(struct pci_bus *bus)  		pci_stop_bus_device(child);  	/* stop the host bridge */ -	device_del(&host_bridge->dev); +	device_release_driver(&host_bridge->dev);  }  void pci_remove_root_bus(struct pci_bus *bus) @@ -145,5 +156,5 @@ void pci_remove_root_bus(struct pci_bus *bus)  	host_bridge->bus = NULL;  	/* remove the host bridge */ -	put_device(&host_bridge->dev); +	device_unregister(&host_bridge->dev);  } diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index c5d0a08a874..f955edb9bea 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -31,13 +31,14 @@ int pci_enable_rom(struct pci_dev *pdev)  	if (!res->flags)  		return -1; -	pcibios_resource_to_bus(pdev, ®ion, res); +	pcibios_resource_to_bus(pdev->bus, ®ion, res);  	pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);  	rom_addr &= ~PCI_ROM_ADDRESS_MASK;  	rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE;  	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);  	return 0;  } +EXPORT_SYMBOL_GPL(pci_enable_rom);  /**   * pci_disable_rom - disable ROM decoding for a PCI device @@ -53,6 +54,7 @@ void pci_disable_rom(struct pci_dev *pdev)  	rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;  	pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);  } +EXPORT_SYMBOL_GPL(pci_disable_rom);  /**   * pci_get_rom_size - obtain the actual size of the ROM image @@ -135,7 +137,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)  		} else {  			/* assign the ROM an address if it doesn't have one */  			if (res->parent == NULL && -			    pci_assign_resource(pdev,PCI_ROM_RESOURCE)) +			    pci_assign_resource(pdev, PCI_ROM_RESOURCE))  				return NULL;  			start = pci_resource_start(pdev, PCI_ROM_RESOURCE);  			*size = pci_resource_len(pdev, PCI_ROM_RESOURCE); @@ -166,6 +168,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)  	*size = pci_get_rom_size(pdev, rom, *size);  	return rom;  } +EXPORT_SYMBOL(pci_map_rom);  /**   * pci_unmap_rom - unmap the ROM from kernel space @@ -187,6 +190,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)  	if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))  		pci_disable_rom(pdev);  } +EXPORT_SYMBOL(pci_unmap_rom);  /**   * pci_cleanup_rom - free the ROM copy created by pci_map_rom_copy @@ -197,8 +201,10 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)  void pci_cleanup_rom(struct pci_dev *pdev)  {  	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; +  	if (res->flags & IORESOURCE_ROM_COPY) { -		kfree((void*)(unsigned long)res->start); +		kfree((void *)(unsigned long)res->start); +		res->flags |= IORESOURCE_UNSET;  		res->flags &= ~IORESOURCE_ROM_COPY;  		res->start = 0;  		res->end = 0; @@ -220,9 +226,4 @@ void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)  	return NULL;  } - -EXPORT_SYMBOL(pci_map_rom); -EXPORT_SYMBOL(pci_unmap_rom); -EXPORT_SYMBOL_GPL(pci_enable_rom); -EXPORT_SYMBOL_GPL(pci_disable_rom);  EXPORT_SYMBOL(pci_platform_rom); diff --git a/drivers/pci/search.c b/drivers/pci/search.c index d0627fa9f36..827ad831f1d 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -1,5 +1,5 @@  /* - * 	PCI searching functions. + *	PCI searching functions.   *   *	Copyright (C) 1993 -- 1997 Drew Eckhardt, Frederic Potter,   *					David Mosberger-Tang @@ -7,7 +7,6 @@   *	Copyright (C) 2003 -- 2004 Greg Kroah-Hartman <greg@kroah.com>   */ -#include <linux/init.h>  #include <linux/pci.h>  #include <linux/slab.h>  #include <linux/module.h> @@ -18,14 +17,100 @@ DECLARE_RWSEM(pci_bus_sem);  EXPORT_SYMBOL_GPL(pci_bus_sem);  /* + * pci_for_each_dma_alias - Iterate over DMA aliases for a device + * @pdev: starting downstream device + * @fn: function to call for each alias + * @data: opaque data to pass to @fn + * + * Starting @pdev, walk up the bus calling @fn for each possible alias + * of @pdev at the root bus. + */ +int pci_for_each_dma_alias(struct pci_dev *pdev, +			   int (*fn)(struct pci_dev *pdev, +				     u16 alias, void *data), void *data) +{ +	struct pci_bus *bus; +	int ret; + +	ret = fn(pdev, PCI_DEVID(pdev->bus->number, pdev->devfn), data); +	if (ret) +		return ret; + +	/* +	 * If the device is broken and uses an alias requester ID for +	 * DMA, iterate over that too. +	 */ +	if (unlikely(pdev->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_DEVFN)) { +		ret = fn(pdev, PCI_DEVID(pdev->bus->number, +					 pdev->dma_alias_devfn), data); +		if (ret) +			return ret; +	} + +	for (bus = pdev->bus; !pci_is_root_bus(bus); bus = bus->parent) { +		struct pci_dev *tmp; + +		/* Skip virtual buses */ +		if (!bus->self) +			continue; + +		tmp = bus->self; + +		/* +		 * PCIe-to-PCI/X bridges alias transactions from downstream +		 * devices using the subordinate bus number (PCI Express to +		 * PCI/PCI-X Bridge Spec, rev 1.0, sec 2.3).  For all cases +		 * where the upstream bus is PCI/X we alias to the bridge +		 * (there are various conditions in the previous reference +		 * where the bridge may take ownership of transactions, even +		 * when the secondary interface is PCI-X). +		 */ +		if (pci_is_pcie(tmp)) { +			switch (pci_pcie_type(tmp)) { +			case PCI_EXP_TYPE_ROOT_PORT: +			case PCI_EXP_TYPE_UPSTREAM: +			case PCI_EXP_TYPE_DOWNSTREAM: +				continue; +			case PCI_EXP_TYPE_PCI_BRIDGE: +				ret = fn(tmp, +					 PCI_DEVID(tmp->subordinate->number, +						   PCI_DEVFN(0, 0)), data); +				if (ret) +					return ret; +				continue; +			case PCI_EXP_TYPE_PCIE_BRIDGE: +				ret = fn(tmp, +					 PCI_DEVID(tmp->bus->number, +						   tmp->devfn), data); +				if (ret) +					return ret; +				continue; +			} +		} else { +			if (tmp->dev_flags & PCI_DEV_FLAG_PCIE_BRIDGE_ALIAS) +				ret = fn(tmp, +					 PCI_DEVID(tmp->subordinate->number, +						   PCI_DEVFN(0, 0)), data); +			else +				ret = fn(tmp, +					 PCI_DEVID(tmp->bus->number, +						   tmp->devfn), data); +			if (ret) +				return ret; +		} +	} + +	return ret; +} + +/*   * find the upstream PCIe-to-PCI bridge of a PCI device   * if the device is PCIE, return NULL   * if the device isn't connected to a PCIe bridge (that is its parent is a   * legacy PCI bridge and the bridge is directly connected to bus 0), return its   * parent   */ -struct pci_dev * -pci_find_upstream_pcie_bridge(struct pci_dev *pdev) +struct pci_dev *pci_find_upstream_pcie_bridge(struct pci_dev *pdev)  {  	struct pci_dev *tmp = NULL; @@ -54,15 +139,15 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)  static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)  { -	struct pci_bus* child; -	struct list_head *tmp; +	struct pci_bus *child; +	struct pci_bus *tmp; -	if(bus->number == busnr) +	if (bus->number == busnr)  		return bus; -	list_for_each(tmp, &bus->children) { -		child = pci_do_find_bus(pci_bus_b(tmp), busnr); -		if(child) +	list_for_each_entry(tmp, &bus->children, node) { +		child = pci_do_find_bus(tmp, busnr); +		if (child)  			return child;  	}  	return NULL; @@ -77,7 +162,7 @@ static struct pci_bus *pci_do_find_bus(struct pci_bus *bus, unsigned char busnr)   * in the global list of PCI buses.  If the bus is found, a pointer to its   * data structure is returned.  If no bus is found, %NULL is returned.   */ -struct pci_bus * pci_find_bus(int domain, int busnr) +struct pci_bus *pci_find_bus(int domain, int busnr)  {  	struct pci_bus *bus = NULL;  	struct pci_bus *tmp_bus; @@ -91,18 +176,18 @@ struct pci_bus * pci_find_bus(int domain, int busnr)  	}  	return NULL;  } +EXPORT_SYMBOL(pci_find_bus);  /**   * pci_find_next_bus - begin or continue searching for a PCI bus   * @from: Previous PCI bus found, or %NULL for new search.   * - * Iterates through the list of known PCI busses.  A new search is + * Iterates through the list of known PCI buses.  A new search is   * initiated by passing %NULL as the @from argument.  Otherwise if   * @from is not %NULL, searches continue from next device on the   * global list.   */ -struct pci_bus *  -pci_find_next_bus(const struct pci_bus *from) +struct pci_bus *pci_find_next_bus(const struct pci_bus *from)  {  	struct list_head *n;  	struct pci_bus *b = NULL; @@ -111,19 +196,20 @@ pci_find_next_bus(const struct pci_bus *from)  	down_read(&pci_bus_sem);  	n = from ? from->node.next : pci_root_buses.next;  	if (n != &pci_root_buses) -		b = pci_bus_b(n); +		b = list_entry(n, struct pci_bus, node);  	up_read(&pci_bus_sem);  	return b;  } +EXPORT_SYMBOL(pci_find_next_bus);  /**   * pci_get_slot - locate PCI device for a given PCI slot   * @bus: PCI bus on which desired PCI device resides - * @devfn: encodes number of PCI slot in which the desired PCI  - * device resides and the logical device number within that slot  + * @devfn: encodes number of PCI slot in which the desired PCI + * device resides and the logical device number within that slot   * in case of multi-function devices.   * - * Given a PCI bus and slot/function number, the desired PCI device  + * Given a PCI bus and slot/function number, the desired PCI device   * is located in the list of PCI devices.   * If the device is found, its reference count is increased and this   * function returns a pointer to its data structure.  The caller must @@ -148,6 +234,7 @@ struct pci_dev *pci_get_slot(struct pci_bus *bus, unsigned int devfn)  	up_read(&pci_bus_sem);  	return dev;  } +EXPORT_SYMBOL(pci_get_slot);  /**   * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot @@ -252,6 +339,7 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,  	return pci_get_dev_by_id(&id, from);  } +EXPORT_SYMBOL(pci_get_subsys);  /**   * pci_get_device - begin or continue searching for a PCI device by vendor/device id @@ -267,11 +355,12 @@ struct pci_dev *pci_get_subsys(unsigned int vendor, unsigned int device,   * from next device on the global list.  The reference count for @from is   * always decremented if it is not %NULL.   */ -struct pci_dev * -pci_get_device(unsigned int vendor, unsigned int device, struct pci_dev *from) +struct pci_dev *pci_get_device(unsigned int vendor, unsigned int device, +			       struct pci_dev *from)  {  	return pci_get_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);  } +EXPORT_SYMBOL(pci_get_device);  /**   * pci_get_class - begin or continue searching for a PCI device by class @@ -300,6 +389,7 @@ struct pci_dev *pci_get_class(unsigned int class, struct pci_dev *from)  	return pci_get_dev_by_id(&id, from);  } +EXPORT_SYMBOL(pci_get_class);  /**   * pci_dev_present - Returns 1 if device matching the device list is present, 0 if not. @@ -329,12 +419,3 @@ int pci_dev_present(const struct pci_device_id *ids)  	return 0;  }  EXPORT_SYMBOL(pci_dev_present); - -/* For boot time work */ -EXPORT_SYMBOL(pci_find_bus); -EXPORT_SYMBOL(pci_find_next_bus); -/* For everyone */ -EXPORT_SYMBOL(pci_get_device); -EXPORT_SYMBOL(pci_get_subsys); -EXPORT_SYMBOL(pci_get_slot); -EXPORT_SYMBOL(pci_get_class); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index bc26d7990cc..a5a63ecfb62 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -68,7 +68,7 @@ static int add_to_list(struct list_head *head,  	tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);  	if (!tmp) { -		pr_warning("add_to_list: kmalloc() failed!\n"); +		pr_warn("add_to_list: kmalloc() failed!\n");  		return -ENOMEM;  	} @@ -148,8 +148,7 @@ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head)  		tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);  		if (!tmp) -			panic("pdev_sort_resources(): " -			      "kmalloc() failed!\n"); +			panic("pdev_sort_resources(): kmalloc() failed!\n");  		tmp->res = r;  		tmp->dev = dev; @@ -292,8 +291,8 @@ static void assign_requested_resources_sorted(struct list_head *head,  				      (!(res->flags & IORESOURCE_ROM_ENABLE))))  					add_to_list(fail_head,  						    dev_res->dev, res, -						    0 /* dont care */, -						    0 /* dont care */); +						    0 /* don't care */, +						    0 /* don't care */);  			}  			reset_resource(res);  		} @@ -475,7 +474,7 @@ void pci_setup_cardbus(struct pci_bus *bus)  		 &bus->busn_res);  	res = bus->resource[0]; -	pcibios_resource_to_bus(bridge, ®ion, res); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_IO) {  		/*  		 * The IO resource is allocated a range twice as large as it @@ -489,7 +488,7 @@ void pci_setup_cardbus(struct pci_bus *bus)  	}  	res = bus->resource[1]; -	pcibios_resource_to_bus(bridge, ®ion, res); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_IO) {  		dev_info(&bridge->dev, "  bridge window %pR\n", res);  		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1, @@ -499,7 +498,7 @@ void pci_setup_cardbus(struct pci_bus *bus)  	}  	res = bus->resource[2]; -	pcibios_resource_to_bus(bridge, ®ion, res); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_MEM) {  		dev_info(&bridge->dev, "  bridge window %pR\n", res);  		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0, @@ -509,7 +508,7 @@ void pci_setup_cardbus(struct pci_bus *bus)  	}  	res = bus->resource[3]; -	pcibios_resource_to_bus(bridge, ®ion, res); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_MEM) {  		dev_info(&bridge->dev, "  bridge window %pR\n", res);  		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1, @@ -538,7 +537,8 @@ static void pci_setup_bridge_io(struct pci_bus *bus)  	struct pci_bus_region region;  	unsigned long io_mask;  	u8 io_base_lo, io_limit_lo; -	u32 l, io_upper16; +	u16 l; +	u32 io_upper16;  	io_mask = PCI_IO_RANGE_MASK;  	if (bridge->io_window_1k) @@ -546,13 +546,12 @@ static void pci_setup_bridge_io(struct pci_bus *bus)  	/* 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); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_IO) { -		pci_read_config_dword(bridge, PCI_IO_BASE, &l); -		l &= 0xffff0000; +		pci_read_config_word(bridge, PCI_IO_BASE, &l);  		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; +		l = ((u16) 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); @@ -564,7 +563,7 @@ static void pci_setup_bridge_io(struct pci_bus *bus)  	/* Temporarily disable the I/O range before updating PCI_IO_BASE. */  	pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);  	/* Update lower 16 bits of I/O base/limit. */ -	pci_write_config_dword(bridge, PCI_IO_BASE, l); +	pci_write_config_word(bridge, PCI_IO_BASE, l);  	/* Update upper 16 bits of I/O base/limit. */  	pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, io_upper16);  } @@ -578,7 +577,7 @@ static void pci_setup_bridge_mmio(struct pci_bus *bus)  	/* Set up the top and bottom of the PCI Memory segment for this bus. */  	res = bus->resource[1]; -	pcibios_resource_to_bus(bridge, ®ion, res); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_MEM) {  		l = (region.start >> 16) & 0xfff0;  		l |= region.end & 0xfff00000; @@ -604,7 +603,7 @@ static void pci_setup_bridge_mmio_pref(struct pci_bus *bus)  	/* Set up PREF base/limit. */  	bu = lu = 0;  	res = bus->resource[2]; -	pcibios_resource_to_bus(bridge, ®ion, res); +	pcibios_resource_to_bus(bridge->bus, ®ion, res);  	if (res->flags & IORESOURCE_PREFETCH) {  		l = (region.start >> 16) & 0xfff0;  		l |= region.end & 0xfff00000; @@ -665,21 +664,23 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)  	pci_read_config_word(bridge, PCI_IO_BASE, &io);  	if (!io) { -		pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); +		pci_write_config_word(bridge, PCI_IO_BASE, 0xe0f0);  		pci_read_config_word(bridge, PCI_IO_BASE, &io); - 		pci_write_config_word(bridge, PCI_IO_BASE, 0x0); - 	} - 	if (io) +		pci_write_config_word(bridge, PCI_IO_BASE, 0x0); +	} +	if (io)  		b_res[0].flags |= IORESOURCE_IO; +  	/*  DECchip 21050 pass 2 errata: the bridge may miss an address  	    disconnect boundary by one PCI data phase.  	    Workaround: do not use prefetching on this device. */  	if (bridge->vendor == PCI_VENDOR_ID_DEC && bridge->device == 0x0001)  		return; +  	pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);  	if (!pmem) {  		pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, -					       0xfff0fff0); +					       0xffe0fff0);  		pci_read_config_dword(bridge, PCI_PREF_MEMORY_BASE, &pmem);  		pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0);  	} @@ -711,12 +712,11 @@ static void pci_bridge_check_ranges(struct pci_bus *bus)     bus resource of a given type. Note: we intentionally skip     the bus resources which have already been assigned (that is,     have non-NULL parent resource). */ -static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned long type) +static struct resource *find_free_bus_resource(struct pci_bus *bus, +			 unsigned long type_mask, unsigned long type)  {  	int i;  	struct resource *r; -	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | -				  IORESOURCE_PREFETCH;  	pci_bus_for_each_resource(bus, r, i) {  		if (r == &ioport_resource || r == &iomem_resource) @@ -735,7 +735,7 @@ static resource_size_t calculate_iosize(resource_size_t size,  {  	if (size < min_size)  		size = min_size; -	if (old_size == 1 ) +	if (old_size == 1)  		old_size = 0;  	/* To be fixed in 2.5: we should have sort of HAVE_ISA  	   flag in the struct pci_bus. */ @@ -756,7 +756,7 @@ static resource_size_t calculate_memsize(resource_size_t size,  {  	if (size < min_size)  		size = min_size; -	if (old_size == 1 ) +	if (old_size == 1)  		old_size = 0;  	if (size < old_size)  		size = old_size; @@ -813,13 +813,14 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,  		resource_size_t add_size, struct list_head *realloc_head)  {  	struct pci_dev *dev; -	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO); +	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO, +							IORESOURCE_IO);  	resource_size_t size = 0, size0 = 0, size1 = 0;  	resource_size_t children_add_size = 0;  	resource_size_t min_align, align;  	if (!b_res) - 		return; +		return;  	min_align = window_alignment(bus, IORESOURCE_IO);  	list_for_each_entry(dev, &bus->devices, bus_list) { @@ -857,9 +858,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,  			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 %pR (unused)\n", b_res, -				 &bus->busn_res); +			dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n", +				 b_res, &bus->busn_res);  		b_res->flags = 0;  		return;  	} @@ -870,10 +870,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,  	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 %pR add_size %llx\n", b_res, -				 &bus->busn_res, -				 (unsigned long long)size1-size0); +		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx\n", +			   b_res, &bus->busn_res, +			   (unsigned long long)size1-size0);  	}  } @@ -905,36 +904,40 @@ static inline resource_size_t calculate_mem_align(resource_size_t *aligns,   * @bus : the bus   * @mask: mask the resource flag, then compare it with type   * @type: the type of free resource from bridge + * @type2: second match type + * @type3: third match type   * @min_size : the minimum memory window that must to be allocated   * @add_size : additional optional memory window   * @realloc_head : track the additional memory window on this list   *   * Calculate the size of the bus and minimal alignment which   * guarantees that all child resources fit in this size. + * + * Returns -ENOSPC if there's no available bus resource of the desired type. + * Otherwise, sets the bus resource start/end to indicate the required + * size, adds things to realloc_head (if supplied), and returns 0.   */  static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, -			 unsigned long type, resource_size_t min_size, -			resource_size_t add_size, -			struct list_head *realloc_head) +			 unsigned long type, unsigned long type2, +			 unsigned long type3, +			 resource_size_t min_size, resource_size_t add_size, +			 struct list_head *realloc_head)  {  	struct pci_dev *dev;  	resource_size_t min_align, align, size, size0, size1; -	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */ +	resource_size_t aligns[14];	/* Alignments from 1Mb to 8Gb */  	int order, max_order; -	struct resource *b_res = find_free_bus_resource(bus, type); -	unsigned int mem64_mask = 0; +	struct resource *b_res = find_free_bus_resource(bus, +					mask | IORESOURCE_PREFETCH, type);  	resource_size_t children_add_size = 0;  	if (!b_res) -		return 0; +		return -ENOSPC;  	memset(aligns, 0, sizeof(aligns));  	max_order = 0;  	size = 0; -	mem64_mask = b_res->flags & IORESOURCE_MEM_64; -	b_res->flags &= ~IORESOURCE_MEM_64; -  	list_for_each_entry(dev, &bus->devices, bus_list) {  		int i; @@ -942,7 +945,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,  			struct resource *r = &dev->resource[i];  			resource_size_t r_size; -			if (r->parent || (r->flags & mask) != type) +			if (r->parent || ((r->flags & mask) != type && +					  (r->flags & mask) != type2 && +					  (r->flags & mask) != type3))  				continue;  			r_size = resource_size(r);  #ifdef CONFIG_PCI_IOV @@ -950,31 +955,34 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,  			if (realloc_head && i >= PCI_IOV_RESOURCES &&  					i <= PCI_IOV_RESOURCE_END) {  				r->end = r->start - 1; -				add_to_list(realloc_head, dev, r, r_size, 0/* dont' care */); +				add_to_list(realloc_head, dev, r, r_size, 0/* don't care */);  				children_add_size += r_size;  				continue;  			}  #endif -			/* For bridges size != alignment */ +			/* +			 * aligns[0] is for 1MB (since bridge memory +			 * windows are always at least 1MB aligned), so +			 * keep "order" from being negative for smaller +			 * resources. +			 */  			align = pci_resource_alignment(dev, r);  			order = __ffs(align) - 20; -			if (order > 11) { -				dev_warn(&dev->dev, "disabling BAR %d: %pR " -					 "(bad alignment %#llx)\n", i, r, -					 (unsigned long long) align); +			if (order < 0) +				order = 0; +			if (order >= ARRAY_SIZE(aligns)) { +				dev_warn(&dev->dev, "disabling BAR %d: %pR (bad alignment %#llx)\n", +					 i, r, (unsigned long long) align);  				r->flags = 0;  				continue;  			}  			size += r_size; -			if (order < 0) -				order = 0;  			/* Exclude ranges with size > align from  			   calculation of the alignment. */  			if (r_size == align)  				aligns[order] += align;  			if (order > max_order)  				max_order = order; -			mem64_mask &= r->flags & IORESOURCE_MEM_64;  			if (realloc_head)  				children_add_size += get_res_add_size(realloc_head, r); @@ -982,7 +990,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,  	}  	min_align = calculate_mem_align(aligns, max_order); -	min_align = max(min_align, window_alignment(bus, b_res->flags & mask)); +	min_align = max(min_align, window_alignment(bus, b_res->flags));  	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);  	if (children_add_size > add_size)  		add_size = children_add_size; @@ -991,22 +999,21 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,  				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 %pR (unused)\n", b_res, -				 &bus->busn_res); +			dev_info(&bus->self->dev, "disabling bridge window %pR to %pR (unused)\n", +				 b_res, &bus->busn_res);  		b_res->flags = 0; -		return 1; +		return 0;  	}  	b_res->start = min_align;  	b_res->end = size0 + min_align - 1; -	b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask; +	b_res->flags |= IORESOURCE_STARTALIGN;  	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 %pR add_size %llx\n", b_res, -				 &bus->busn_res, (unsigned long long)size1-size0); +		dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window %pR to %pR add_size %llx\n", +			   b_res, &bus->busn_res, +			   (unsigned long long)size1-size0);  	} -	return 1; +	return 0;  }  unsigned long pci_cardbus_resource_alignment(struct resource *res) @@ -1111,12 +1118,13 @@ handle_done:  	;  } -void __ref __pci_bus_size_bridges(struct pci_bus *bus, -			struct list_head *realloc_head) +void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head)  {  	struct pci_dev *dev; -	unsigned long mask, prefmask; +	unsigned long mask, prefmask, type2 = 0, type3 = 0;  	resource_size_t additional_mem_size = 0, additional_io_size = 0; +	struct resource *b_res; +	int ret;  	list_for_each_entry(dev, &bus->devices, bus_list) {  		struct pci_bus *b = dev->subordinate; @@ -1136,7 +1144,7 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,  	}  	/* The root bus? */ -	if (!bus->self) +	if (pci_is_root_bus(bus))  		return;  	switch (bus->self->class >> 8) { @@ -1150,41 +1158,93 @@ void __ref __pci_bus_size_bridges(struct pci_bus *bus,  			additional_io_size  = pci_hotplug_io_size;  			additional_mem_size = pci_hotplug_mem_size;  		} -		/* -		 * Follow thru -		 */ +		/* Fall through */  	default:  		pbus_size_io(bus, realloc_head ? 0 : additional_io_size,  			     additional_io_size, realloc_head); -		/* If the bridge supports prefetchable range, size it -		   separately. If it doesn't, or its prefetchable window -		   has already been allocated by arch code, try -		   non-prefetchable range for both types of PCI memory -		   resources. */ + +		/* +		 * If there's a 64-bit prefetchable MMIO window, compute +		 * the size required to put all 64-bit prefetchable +		 * resources in it. +		 */ +		b_res = &bus->self->resource[PCI_BRIDGE_RESOURCES];  		mask = IORESOURCE_MEM;  		prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH; -		if (pbus_size_mem(bus, prefmask, prefmask, +		if (b_res[2].flags & IORESOURCE_MEM_64) { +			prefmask |= IORESOURCE_MEM_64; +			ret = pbus_size_mem(bus, prefmask, prefmask, +				  prefmask, prefmask,  				  realloc_head ? 0 : additional_mem_size, -				  additional_mem_size, realloc_head)) -			mask = prefmask; /* Success, size non-prefetch only. */ -		else -			additional_mem_size += additional_mem_size; -		pbus_size_mem(bus, mask, IORESOURCE_MEM, +				  additional_mem_size, realloc_head); + +			/* +			 * If successful, all non-prefetchable resources +			 * and any 32-bit prefetchable resources will go in +			 * the non-prefetchable window. +			 */ +			if (ret == 0) { +				mask = prefmask; +				type2 = prefmask & ~IORESOURCE_MEM_64; +				type3 = prefmask & ~IORESOURCE_PREFETCH; +			} +		} + +		/* +		 * If there is no 64-bit prefetchable window, compute the +		 * size required to put all prefetchable resources in the +		 * 32-bit prefetchable window (if there is one). +		 */ +		if (!type2) { +			prefmask &= ~IORESOURCE_MEM_64; +			ret = pbus_size_mem(bus, prefmask, prefmask, +					 prefmask, prefmask, +					 realloc_head ? 0 : additional_mem_size, +					 additional_mem_size, realloc_head); + +			/* +			 * If successful, only non-prefetchable resources +			 * will go in the non-prefetchable window. +			 */ +			if (ret == 0) +				mask = prefmask; +			else +				additional_mem_size += additional_mem_size; + +			type2 = type3 = IORESOURCE_MEM; +		} + +		/* +		 * Compute the size required to put everything else in the +		 * non-prefetchable window.  This includes: +		 * +		 *   - all non-prefetchable resources +		 *   - 32-bit prefetchable resources if there's a 64-bit +		 *     prefetchable window or no prefetchable window at all +		 *   - 64-bit prefetchable resources if there's no +		 *     prefetchable window at all +		 * +		 * Note that the strategy in __pci_assign_resource() must +		 * match that used here.  Specifically, we cannot put a +		 * 32-bit prefetchable resource in a 64-bit prefetchable +		 * window. +		 */ +		pbus_size_mem(bus, mask, IORESOURCE_MEM, type2, type3,  				realloc_head ? 0 : additional_mem_size,  				additional_mem_size, realloc_head);  		break;  	}  } -void __ref pci_bus_size_bridges(struct pci_bus *bus) +void pci_bus_size_bridges(struct pci_bus *bus)  {  	__pci_bus_size_bridges(bus, NULL);  }  EXPORT_SYMBOL(pci_bus_size_bridges); -void __ref __pci_bus_assign_resources(const struct pci_bus *bus, -				      struct list_head *realloc_head, -				      struct list_head *fail_head) +void __pci_bus_assign_resources(const struct pci_bus *bus, +				struct list_head *realloc_head, +				struct list_head *fail_head)  {  	struct pci_bus *b;  	struct pci_dev *dev; @@ -1209,22 +1269,22 @@ void __ref __pci_bus_assign_resources(const struct pci_bus *bus,  			break;  		default: -			dev_info(&dev->dev, "not setting up bridge for bus " -				 "%04x:%02x\n", pci_domain_nr(b), b->number); +			dev_info(&dev->dev, "not setting up bridge for bus %04x:%02x\n", +				 pci_domain_nr(b), b->number);  			break;  		}  	}  } -void __ref pci_bus_assign_resources(const struct pci_bus *bus) +void pci_bus_assign_resources(const struct pci_bus *bus)  {  	__pci_bus_assign_resources(bus, NULL, NULL);  }  EXPORT_SYMBOL(pci_bus_assign_resources); -static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge, -					 struct list_head *add_head, -					 struct list_head *fail_head) +static void __pci_bridge_assign_resources(const struct pci_dev *bridge, +					  struct list_head *add_head, +					  struct list_head *fail_head)  {  	struct pci_bus *b; @@ -1247,50 +1307,74 @@ static void __ref __pci_bridge_assign_resources(const struct pci_dev *bridge,  		break;  	default: -		dev_info(&bridge->dev, "not setting up bridge for bus " -			 "%04x:%02x\n", pci_domain_nr(b), b->number); +		dev_info(&bridge->dev, "not setting up bridge for bus %04x:%02x\n", +			 pci_domain_nr(b), b->number);  		break;  	}  }  static void pci_bridge_release_resources(struct pci_bus *bus,  					  unsigned long type)  { -	int idx; -	bool changed = false; -	struct pci_dev *dev; +	struct pci_dev *dev = bus->self;  	struct resource *r;  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | -				  IORESOURCE_PREFETCH; +				  IORESOURCE_PREFETCH | IORESOURCE_MEM_64; +	unsigned old_flags = 0; +	struct resource *b_res; +	int idx = 1; -	dev = bus->self; -	for (idx = PCI_BRIDGE_RESOURCES; idx <= PCI_BRIDGE_RESOURCE_END; -	     idx++) { -		r = &dev->resource[idx]; -		if ((r->flags & type_mask) != type) -			continue; -		if (!r->parent) -			continue; -		/* -		 * if there are children under that, we should release them -		 *  all -		 */ -		release_child_resources(r); -		if (!release_resource(r)) { -			dev_printk(KERN_DEBUG, &dev->dev, -				 "resource %d %pR released\n", idx, r); -			/* keep the old size */ -			r->end = resource_size(r) - 1; -			r->start = 0; -			r->flags = 0; -			changed = true; -		} -	} +	b_res = &dev->resource[PCI_BRIDGE_RESOURCES]; + +	/* +	 *     1. if there is io port assign fail, will release bridge +	 *	  io port. +	 *     2. if there is non pref mmio assign fail, release bridge +	 *	  nonpref mmio. +	 *     3. if there is 64bit pref mmio assign fail, and bridge pref +	 *	  is 64bit, release bridge pref mmio. +	 *     4. if there is pref mmio assign fail, and bridge pref is +	 *	  32bit mmio, release bridge pref mmio +	 *     5. if there is pref mmio assign fail, and bridge pref is not +	 *	  assigned, release bridge nonpref mmio. +	 */ +	if (type & IORESOURCE_IO) +		idx = 0; +	else if (!(type & IORESOURCE_PREFETCH)) +		idx = 1; +	else if ((type & IORESOURCE_MEM_64) && +		 (b_res[2].flags & IORESOURCE_MEM_64)) +		idx = 2; +	else if (!(b_res[2].flags & IORESOURCE_MEM_64) && +		 (b_res[2].flags & IORESOURCE_PREFETCH)) +		idx = 2; +	else +		idx = 1; + +	r = &b_res[idx]; + +	if (!r->parent) +		return; + +	/* +	 * if there are children under that, we should release them +	 *  all +	 */ +	release_child_resources(r); +	if (!release_resource(r)) { +		type = old_flags = r->flags & type_mask; +		dev_printk(KERN_DEBUG, &dev->dev, "resource %d %pR released\n", +					PCI_BRIDGE_RESOURCES + idx, r); +		/* keep the old size */ +		r->end = resource_size(r) - 1; +		r->start = 0; +		r->flags = 0; -	if (changed) {  		/* avoiding touch the one without PREF */  		if (type & IORESOURCE_PREFETCH)  			type = IORESOURCE_PREFETCH;  		__pci_setup_bridge(bus, type); +		/* for next child res under same bridge */ +		r->flags = old_flags;  	}  } @@ -1302,9 +1386,9 @@ enum release_type {   * try to release pci bridge resources that is from leaf bridge,   * so we can allocate big new one later   */ -static void __ref pci_bus_release_bridge_resources(struct pci_bus *bus, -						   unsigned long type, -						   enum release_type rel_type) +static void pci_bus_release_bridge_resources(struct pci_bus *bus, +					     unsigned long type, +					     enum release_type rel_type)  {  	struct pci_dev *dev;  	bool is_leaf_bridge = true; @@ -1341,10 +1425,10 @@ static void pci_bus_dump_res(struct pci_bus *bus)  	pci_bus_for_each_resource(bus, res, i) {  		if (!res || !res->end || !res->flags) -                        continue; +			continue;  		dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res); -        } +	}  }  static void pci_bus_dump_resources(struct pci_bus *bus) @@ -1369,7 +1453,7 @@ static int pci_bus_get_depth(struct pci_bus *bus)  	int depth = 0;  	struct pci_bus *child_bus; -	list_for_each_entry(child_bus, &bus->children, node){ +	list_for_each_entry(child_bus, &bus->children, node) {  		int ret;  		ret = pci_bus_get_depth(child_bus); @@ -1422,7 +1506,7 @@ static int iov_resources_unassigned(struct pci_dev *dev, void *data)  		if (!r->flags)  			continue; -		pcibios_resource_to_bus(dev, ®ion, r); +		pcibios_resource_to_bus(dev->bus, ®ion, r);  		if (!region.start) {  			*unassigned = true;  			return 1; /* return early from pci_walk_bus() */ @@ -1456,8 +1540,8 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus,  /*   * first try will not touch pci bridge res - * second  and later try will clear small leaf bridge res - * will stop till to the max  deepth if can not find good one + * second and later try will clear small leaf bridge res + * will stop till to the max depth if can not find good one   */  void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)  { @@ -1469,7 +1553,7 @@ void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus)  	LIST_HEAD(fail_head);  	struct pci_dev_resource *fail_res;  	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | -				  IORESOURCE_PREFETCH; +				  IORESOURCE_PREFETCH | IORESOURCE_MEM_64;  	int pci_try_num = 1;  	enum enable_type enable_local; @@ -1627,9 +1711,7 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus)  	down_read(&pci_bus_sem);  	list_for_each_entry(dev, &bus->devices, bus_list) -		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || -		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) -			if (dev->subordinate) +		if (pci_is_bridge(dev) && pci_has_subordinate(dev))  				__pci_bus_size_bridges(dev->subordinate,  							 &add_list);  	up_read(&pci_bus_sem); diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c index 9bd6864ec5d..4e2d595d50c 100644 --- a/drivers/pci/setup-irq.c +++ b/drivers/pci/setup-irq.c @@ -10,7 +10,6 @@   */ -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/pci.h>  #include <linux/errno.h> @@ -23,10 +22,9 @@ void __weak pcibios_update_irq(struct pci_dev *dev, int irq)  	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);  } -static void -pdev_fixup_irq(struct pci_dev *dev, -	       u8 (*swizzle)(struct pci_dev *, u8 *), -	       int (*map_irq)(const struct pci_dev *, u8, u8)) +static void pdev_fixup_irq(struct pci_dev *dev, +			   u8 (*swizzle)(struct pci_dev *, u8 *), +			   int (*map_irq)(const struct pci_dev *, u8, u8))  {  	u8 pin, slot;  	int irq = 0; @@ -59,11 +57,11 @@ pdev_fixup_irq(struct pci_dev *dev,  	pcibios_update_irq(dev, irq);  } -void -pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), -	       int (*map_irq)(const struct pci_dev *, u8, u8)) +void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), +		    int (*map_irq)(const struct pci_dev *, u8, u8))  {  	struct pci_dev *dev = NULL; +  	for_each_pci_dev(dev)  		pdev_fixup_irq(dev, swizzle, map_irq);  } diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 07f2eddc09c..caed1ce6fac 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -16,7 +16,6 @@   *	     Resource sorting   */ -#include <linux/init.h>  #include <linux/kernel.h>  #include <linux/export.h>  #include <linux/pci.h> @@ -44,6 +43,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)  	if (!res->flags)  		return; +	if (res->flags & IORESOURCE_UNSET) +		return; +  	/*  	 * Ignore non-moveable resources.  This might be legacy resources for  	 * which no functional BAR register exists or another important @@ -52,7 +54,7 @@ void pci_update_resource(struct pci_dev *dev, int resno)  	if (res->flags & IORESOURCE_PCI_FIXED)  		return; -	pcibios_resource_to_bus(dev, ®ion, res); +	pcibios_resource_to_bus(dev->bus, ®ion, res);  	new = region.start | (res->flags & PCI_REGION_FLAG_MASK);  	if (res->flags & IORESOURCE_IO) @@ -94,18 +96,13 @@ void pci_update_resource(struct pci_dev *dev, int resno)  		pci_write_config_dword(dev, reg + 4, new);  		pci_read_config_dword(dev, reg + 4, &check);  		if (check != new) { -			dev_err(&dev->dev, "BAR %d: error updating " -			       "(high %#08x != %#08x)\n", resno, new, check); +			dev_err(&dev->dev, "BAR %d: error updating (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, -		(unsigned long long)region.end);  }  int pci_claim_resource(struct pci_dev *dev, int resource) @@ -113,18 +110,23 @@ int pci_claim_resource(struct pci_dev *dev, int resource)  	struct resource *res = &dev->resource[resource];  	struct resource *root, *conflict; +	if (res->flags & IORESOURCE_UNSET) { +		dev_info(&dev->dev, "can't claim BAR %d %pR: no address assigned\n", +			 resource, res); +		return -EINVAL; +	} +  	root = pci_find_parent_resource(dev, res);  	if (!root) { -		dev_info(&dev->dev, "no compatible bridge window for %pR\n", -			 res); +		dev_info(&dev->dev, "can't claim BAR %d %pR: no compatible bridge window\n", +			 resource, res);  		return -EINVAL;  	}  	conflict = request_resource_conflict(root, res);  	if (conflict) { -		dev_info(&dev->dev, -			 "address space collision: %pR conflicts with %s %pR\n", -			 res, conflict->name, conflict); +		dev_info(&dev->dev, "can't claim BAR %d %pR: address conflict with %s %pR\n", +			 resource, res, conflict->name, conflict);  		return -EBUSY;  	} @@ -159,7 +161,7 @@ resource_size_t __weak pcibios_retrieve_fw_addr(struct pci_dev *dev, int idx)  	return 0;  } -static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,  +static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev,  		int resno, resource_size_t size)  {  	struct resource *root, *conflict; @@ -206,21 +208,42 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,  	min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; -	/* First, try exact prefetching match.. */ +	/* +	 * First, try exact prefetching match.  Even if a 64-bit +	 * prefetchable bridge window is below 4GB, we can't put a 32-bit +	 * prefetchable resource in it because pbus_size_mem() assumes a +	 * 64-bit window will contain no 32-bit resources.  If we assign +	 * things differently than they were sized, not everything will fit. +	 */  	ret = pci_bus_alloc_resource(bus, res, size, align, min, -				     IORESOURCE_PREFETCH, +				     IORESOURCE_PREFETCH | IORESOURCE_MEM_64,  				     pcibios_align_resource, dev); +	if (ret == 0) +		return 0; -	if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { -		/* -		 * That failed. -		 * -		 * But a prefetching area can handle a non-prefetching -		 * window (it will just not perform as well). -		 */ -		ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, +	/* +	 * If the prefetchable window is only 32 bits wide, we can put +	 * 64-bit prefetchable resources in it. +	 */ +	if ((res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) == +	     (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) { +		ret = pci_bus_alloc_resource(bus, res, size, align, min, +					     IORESOURCE_PREFETCH,  					     pcibios_align_resource, dev); +		if (ret == 0) +			return 0;  	} + +	/* +	 * If we didn't find a better match, we can put any memory resource +	 * in a non-prefetchable window.  If this resource is 32 bits and +	 * non-prefetchable, the first call already tried the only possibility +	 * so we don't need to try again. +	 */ +	if (res->flags & (IORESOURCE_PREFETCH | IORESOURCE_MEM_64)) +		ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, +					     pcibios_align_resource, dev); +  	return ret;  } @@ -263,10 +286,11 @@ int pci_assign_resource(struct pci_dev *dev, int resno)  	resource_size_t align, size;  	int ret; +	res->flags |= IORESOURCE_UNSET;  	align = pci_resource_alignment(dev, res);  	if (!align) { -		dev_info(&dev->dev, "BAR %d: can't assign %pR " -			 "(bogus alignment)\n", resno, res); +		dev_info(&dev->dev, "BAR %d: can't assign %pR (bogus alignment)\n", +			 resno, res);  		return -EINVAL;  	} @@ -282,6 +306,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)  		ret = pci_revert_fw_address(res, dev, resno, size);  	if (!ret) { +		res->flags &= ~IORESOURCE_UNSET;  		res->flags &= ~IORESOURCE_STARTALIGN;  		dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);  		if (resno < PCI_BRIDGE_RESOURCES) @@ -289,6 +314,7 @@ int pci_assign_resource(struct pci_dev *dev, int resno)  	}  	return ret;  } +EXPORT_SYMBOL(pci_assign_resource);  int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsize,  			resource_size_t min_align) @@ -297,9 +323,10 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz  	resource_size_t new_size;  	int ret; +	res->flags |= IORESOURCE_UNSET;  	if (!res->parent) { -		dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR " -			 "\n", resno, res); +		dev_info(&dev->dev, "BAR %d: can't reassign an unassigned resource %pR\n", +			 resno, res);  		return -EINVAL;  	} @@ -307,6 +334,7 @@ int pci_reassign_resource(struct pci_dev *dev, int resno, resource_size_t addsiz  	new_size = resource_size(res) + addsize;  	ret = _pci_assign_resource(dev, resno, new_size, min_align);  	if (!ret) { +		res->flags &= ~IORESOURCE_UNSET;  		res->flags &= ~IORESOURCE_STARTALIGN;  		dev_info(&dev->dev, "BAR %d: reassigned %pR\n", resno, res);  		if (resno < PCI_BRIDGE_RESOURCES) @@ -336,9 +364,15 @@ int pci_enable_resources(struct pci_dev *dev, int mask)  				(!(r->flags & IORESOURCE_ROM_ENABLE)))  			continue; +		if (r->flags & IORESOURCE_UNSET) { +			dev_err(&dev->dev, "can't enable device: BAR %d %pR not assigned\n", +				i, r); +			return -EINVAL; +		} +  		if (!r->parent) { -			dev_err(&dev->dev, "device not available " -				"(can't reserve %pR)\n", r); +			dev_err(&dev->dev, "can't enable device: BAR %d %pR not claimed\n", +				i, r);  			return -EINVAL;  		} diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index c1e9284a677..396c200b9dd 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -53,7 +53,7 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf)  static const char *pci_bus_speed_strings[] = {  	"33 MHz PCI",		/* 0x00 */  	"66 MHz PCI",		/* 0x01 */ -	"66 MHz PCI-X", 	/* 0x02 */ +	"66 MHz PCI-X",		/* 0x02 */  	"100 MHz PCI-X",	/* 0x03 */  	"133 MHz PCI-X",	/* 0x04 */  	NULL,			/* 0x05 */ @@ -116,11 +116,11 @@ static void pci_slot_release(struct kobject *kobj)  }  static struct pci_slot_attribute pci_slot_attr_address = -	__ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL); +	__ATTR(address, S_IRUGO, address_read_file, NULL);  static struct pci_slot_attribute pci_slot_attr_max_speed = -	__ATTR(max_bus_speed, (S_IFREG | S_IRUGO), max_speed_read_file, NULL); +	__ATTR(max_bus_speed, S_IRUGO, max_speed_read_file, NULL);  static struct pci_slot_attribute pci_slot_attr_cur_speed = -	__ATTR(cur_bus_speed, (S_IFREG | S_IRUGO), cur_speed_read_file, NULL); +	__ATTR(cur_bus_speed, S_IRUGO, cur_speed_read_file, NULL);  static struct attribute *pci_slot_default_attrs[] = {  	&pci_slot_attr_address.attr, @@ -320,32 +320,6 @@ err:  EXPORT_SYMBOL_GPL(pci_create_slot);  /** - * pci_renumber_slot - update %struct pci_slot -> number - * @slot: &struct pci_slot to update - * @slot_nr: new number for slot - * - * The primary purpose of this interface is to allow callers who earlier - * created a placeholder slot in pci_create_slot() by passing a -1 as - * slot_nr, to update their %struct pci_slot with the correct @slot_nr. - */ -void pci_renumber_slot(struct pci_slot *slot, int slot_nr) -{ -	struct pci_slot *tmp; - -	down_write(&pci_bus_sem); - -	list_for_each_entry(tmp, &slot->bus->slots, list) { -		WARN_ON(tmp->number == slot_nr); -		goto out; -	} - -	slot->number = slot_nr; -out: -	up_write(&pci_bus_sem); -} -EXPORT_SYMBOL_GPL(pci_renumber_slot); - -/**   * pci_destroy_slot - decrement refcount for physical PCI slot   * @slot: struct pci_slot to decrement   * diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c index e1c1ec54089..b91c4da6836 100644 --- a/drivers/pci/syscall.c +++ b/drivers/pci/syscall.c @@ -44,7 +44,7 @@ SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn,  	default:  		err = -EINVAL;  		goto error; -	}; +	}  	err = -EIO;  	if (cfg_ret != PCIBIOS_SUCCESSFUL) @@ -99,7 +99,7 @@ SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,  	if (!dev)  		return -ENODEV; -	switch(len) { +	switch (len) {  	case 1:  		err = get_user(byte, (u8 __user *)buf);  		if (err) diff --git a/drivers/pci/vc.c b/drivers/pci/vc.c new file mode 100644 index 00000000000..7e1304d2e38 --- /dev/null +++ b/drivers/pci/vc.c @@ -0,0 +1,434 @@ +/* + * PCI Virtual Channel support + * + * Copyright (C) 2013 Red Hat, Inc.  All rights reserved. + *     Author: Alex Williamson <alex.williamson@redhat.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/device.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/pci_regs.h> +#include <linux/types.h> + +/** + * pci_vc_save_restore_dwords - Save or restore a series of dwords + * @dev: device + * @pos: starting config space position + * @buf: buffer to save to or restore from + * @dwords: number of dwords to save/restore + * @save: whether to save or restore + */ +static void pci_vc_save_restore_dwords(struct pci_dev *dev, int pos, +				       u32 *buf, int dwords, bool save) +{ +	int i; + +	for (i = 0; i < dwords; i++, buf++) { +		if (save) +			pci_read_config_dword(dev, pos + (i * 4), buf); +		else +			pci_write_config_dword(dev, pos + (i * 4), *buf); +	} +} + +/** + * pci_vc_load_arb_table - load and wait for VC arbitration table + * @dev: device + * @pos: starting position of VC capability (VC/VC9/MFVC) + * + * Set Load VC Arbitration Table bit requesting hardware to apply the VC + * Arbitration Table (previously loaded).  When the VC Arbitration Table + * Status clears, hardware has latched the table into VC arbitration logic. + */ +static void pci_vc_load_arb_table(struct pci_dev *dev, int pos) +{ +	u16 ctrl; + +	pci_read_config_word(dev, pos + PCI_VC_PORT_CTRL, &ctrl); +	pci_write_config_word(dev, pos + PCI_VC_PORT_CTRL, +			      ctrl | PCI_VC_PORT_CTRL_LOAD_TABLE); +	if (pci_wait_for_pending(dev, pos + PCI_VC_PORT_STATUS, +				 PCI_VC_PORT_STATUS_TABLE)) +		return; + +	dev_err(&dev->dev, "VC arbitration table failed to load\n"); +} + +/** + * pci_vc_load_port_arb_table - Load and wait for VC port arbitration table + * @dev: device + * @pos: starting position of VC capability (VC/VC9/MFVC) + * @res: VC resource number, ie. VCn (0-7) + * + * Set Load Port Arbitration Table bit requesting hardware to apply the Port + * Arbitration Table (previously loaded).  When the Port Arbitration Table + * Status clears, hardware has latched the table into port arbitration logic. + */ +static void pci_vc_load_port_arb_table(struct pci_dev *dev, int pos, int res) +{ +	int ctrl_pos, status_pos; +	u32 ctrl; + +	ctrl_pos = pos + PCI_VC_RES_CTRL + (res * PCI_CAP_VC_PER_VC_SIZEOF); +	status_pos = pos + PCI_VC_RES_STATUS + (res * PCI_CAP_VC_PER_VC_SIZEOF); + +	pci_read_config_dword(dev, ctrl_pos, &ctrl); +	pci_write_config_dword(dev, ctrl_pos, +			       ctrl | PCI_VC_RES_CTRL_LOAD_TABLE); + +	if (pci_wait_for_pending(dev, status_pos, PCI_VC_RES_STATUS_TABLE)) +		return; + +	dev_err(&dev->dev, "VC%d port arbitration table failed to load\n", res); +} + +/** + * pci_vc_enable - Enable virtual channel + * @dev: device + * @pos: starting position of VC capability (VC/VC9/MFVC) + * @res: VC res number, ie. VCn (0-7) + * + * A VC is enabled by setting the enable bit in matching resource control + * registers on both sides of a link.  We therefore need to find the opposite + * end of the link.  To keep this simple we enable from the downstream device. + * RC devices do not have an upstream device, nor does it seem that VC9 do + * (spec is unclear).  Once we find the upstream device, match the VC ID to + * get the correct resource, disable and enable on both ends. + */ +static void pci_vc_enable(struct pci_dev *dev, int pos, int res) +{ +	int ctrl_pos, status_pos, id, pos2, evcc, i, ctrl_pos2, status_pos2; +	u32 ctrl, header, cap1, ctrl2; +	struct pci_dev *link = NULL; + +	/* Enable VCs from the downstream device */ +	if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT || +	    pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM) +		return; + +	ctrl_pos = pos + PCI_VC_RES_CTRL + (res * PCI_CAP_VC_PER_VC_SIZEOF); +	status_pos = pos + PCI_VC_RES_STATUS + (res * PCI_CAP_VC_PER_VC_SIZEOF); + +	pci_read_config_dword(dev, ctrl_pos, &ctrl); +	id = ctrl & PCI_VC_RES_CTRL_ID; + +	pci_read_config_dword(dev, pos, &header); + +	/* If there is no opposite end of the link, skip to enable */ +	if (PCI_EXT_CAP_ID(header) == PCI_EXT_CAP_ID_VC9 || +	    pci_is_root_bus(dev->bus)) +		goto enable; + +	pos2 = pci_find_ext_capability(dev->bus->self, PCI_EXT_CAP_ID_VC); +	if (!pos2) +		goto enable; + +	pci_read_config_dword(dev->bus->self, pos2 + PCI_VC_PORT_CAP1, &cap1); +	evcc = cap1 & PCI_VC_CAP1_EVCC; + +	/* VC0 is hardwired enabled, so we can start with 1 */ +	for (i = 1; i < evcc + 1; i++) { +		ctrl_pos2 = pos2 + PCI_VC_RES_CTRL + +				(i * PCI_CAP_VC_PER_VC_SIZEOF); +		status_pos2 = pos2 + PCI_VC_RES_STATUS + +				(i * PCI_CAP_VC_PER_VC_SIZEOF); +		pci_read_config_dword(dev->bus->self, ctrl_pos2, &ctrl2); +		if ((ctrl2 & PCI_VC_RES_CTRL_ID) == id) { +			link = dev->bus->self; +			break; +		} +	} + +	if (!link) +		goto enable; + +	/* Disable if enabled */ +	if (ctrl2 & PCI_VC_RES_CTRL_ENABLE) { +		ctrl2 &= ~PCI_VC_RES_CTRL_ENABLE; +		pci_write_config_dword(link, ctrl_pos2, ctrl2); +	} + +	/* Enable on both ends */ +	ctrl2 |= PCI_VC_RES_CTRL_ENABLE; +	pci_write_config_dword(link, ctrl_pos2, ctrl2); +enable: +	ctrl |= PCI_VC_RES_CTRL_ENABLE; +	pci_write_config_dword(dev, ctrl_pos, ctrl); + +	if (!pci_wait_for_pending(dev, status_pos, PCI_VC_RES_STATUS_NEGO)) +		dev_err(&dev->dev, "VC%d negotiation stuck pending\n", id); + +	if (link && !pci_wait_for_pending(link, status_pos2, +					  PCI_VC_RES_STATUS_NEGO)) +		dev_err(&link->dev, "VC%d negotiation stuck pending\n", id); +} + +/** + * pci_vc_do_save_buffer - Size, save, or restore VC state + * @dev: device + * @pos: starting position of VC capability (VC/VC9/MFVC) + * @save_state: buffer for save/restore + * @name: for error message + * @save: if provided a buffer, this indicates what to do with it + * + * Walking Virtual Channel config space to size, save, or restore it + * is complicated, so we do it all from one function to reduce code and + * guarantee ordering matches in the buffer.  When called with NULL + * @save_state, return the size of the necessary save buffer.  When called + * with a non-NULL @save_state, @save determines whether we save to the + * buffer or restore from it. + */ +static int pci_vc_do_save_buffer(struct pci_dev *dev, int pos, +				 struct pci_cap_saved_state *save_state, +				 bool save) +{ +	u32 cap1; +	char evcc, lpevcc, parb_size; +	int i, len = 0; +	u8 *buf = save_state ? (u8 *)save_state->cap.data : NULL; + +	/* Sanity check buffer size for save/restore */ +	if (buf && save_state->cap.size != +	    pci_vc_do_save_buffer(dev, pos, NULL, save)) { +		dev_err(&dev->dev, +			"VC save buffer size does not match @0x%x\n", pos); +		return -ENOMEM; +	} + +	pci_read_config_dword(dev, pos + PCI_VC_PORT_CAP1, &cap1); +	/* Extended VC Count (not counting VC0) */ +	evcc = cap1 & PCI_VC_CAP1_EVCC; +	/* Low Priority Extended VC Count (not counting VC0) */ +	lpevcc = (cap1 & PCI_VC_CAP1_LPEVCC) >> 4; +	/* Port Arbitration Table Entry Size (bits) */ +	parb_size = 1 << ((cap1 & PCI_VC_CAP1_ARB_SIZE) >> 10); + +	/* +	 * Port VC Control Register contains VC Arbitration Select, which +	 * cannot be modified when more than one LPVC is in operation.  We +	 * therefore save/restore it first, as only VC0 should be enabled +	 * after device reset. +	 */ +	if (buf) { +		if (save) +			pci_read_config_word(dev, pos + PCI_VC_PORT_CTRL, +					     (u16 *)buf); +		else +			pci_write_config_word(dev, pos + PCI_VC_PORT_CTRL, +					      *(u16 *)buf); +		buf += 2; +	} +	len += 2; + +	/* +	 * If we have any Low Priority VCs and a VC Arbitration Table Offset +	 * in Port VC Capability Register 2 then save/restore it next. +	 */ +	if (lpevcc) { +		u32 cap2; +		int vcarb_offset; + +		pci_read_config_dword(dev, pos + PCI_VC_PORT_CAP2, &cap2); +		vcarb_offset = ((cap2 & PCI_VC_CAP2_ARB_OFF) >> 24) * 16; + +		if (vcarb_offset) { +			int size, vcarb_phases = 0; + +			if (cap2 & PCI_VC_CAP2_128_PHASE) +				vcarb_phases = 128; +			else if (cap2 & PCI_VC_CAP2_64_PHASE) +				vcarb_phases = 64; +			else if (cap2 & PCI_VC_CAP2_32_PHASE) +				vcarb_phases = 32; + +			/* Fixed 4 bits per phase per lpevcc (plus VC0) */ +			size = ((lpevcc + 1) * vcarb_phases * 4) / 8; + +			if (size && buf) { +				pci_vc_save_restore_dwords(dev, +							   pos + vcarb_offset, +							   (u32 *)buf, +							   size / 4, save); +				/* +				 * On restore, we need to signal hardware to +				 * re-load the VC Arbitration Table. +				 */ +				if (!save) +					pci_vc_load_arb_table(dev, pos); + +				buf += size; +			} +			len += size; +		} +	} + +	/* +	 * In addition to each VC Resource Control Register, we may have a +	 * Port Arbitration Table attached to each VC.  The Port Arbitration +	 * Table Offset in each VC Resource Capability Register tells us if +	 * it exists.  The entry size is global from the Port VC Capability +	 * Register1 above.  The number of phases is determined per VC. +	 */ +	for (i = 0; i < evcc + 1; i++) { +		u32 cap; +		int parb_offset; + +		pci_read_config_dword(dev, pos + PCI_VC_RES_CAP + +				      (i * PCI_CAP_VC_PER_VC_SIZEOF), &cap); +		parb_offset = ((cap & PCI_VC_RES_CAP_ARB_OFF) >> 24) * 16; +		if (parb_offset) { +			int size, parb_phases = 0; + +			if (cap & PCI_VC_RES_CAP_256_PHASE) +				parb_phases = 256; +			else if (cap & (PCI_VC_RES_CAP_128_PHASE | +					PCI_VC_RES_CAP_128_PHASE_TB)) +				parb_phases = 128; +			else if (cap & PCI_VC_RES_CAP_64_PHASE) +				parb_phases = 64; +			else if (cap & PCI_VC_RES_CAP_32_PHASE) +				parb_phases = 32; + +			size = (parb_size * parb_phases) / 8; + +			if (size && buf) { +				pci_vc_save_restore_dwords(dev, +							   pos + parb_offset, +							   (u32 *)buf, +							   size / 4, save); +				buf += size; +			} +			len += size; +		} + +		/* VC Resource Control Register */ +		if (buf) { +			int ctrl_pos = pos + PCI_VC_RES_CTRL + +						(i * PCI_CAP_VC_PER_VC_SIZEOF); +			if (save) +				pci_read_config_dword(dev, ctrl_pos, +						      (u32 *)buf); +			else { +				u32 tmp, ctrl = *(u32 *)buf; +				/* +				 * For an FLR case, the VC config may remain. +				 * Preserve enable bit, restore the rest. +				 */ +				pci_read_config_dword(dev, ctrl_pos, &tmp); +				tmp &= PCI_VC_RES_CTRL_ENABLE; +				tmp |= ctrl & ~PCI_VC_RES_CTRL_ENABLE; +				pci_write_config_dword(dev, ctrl_pos, tmp); +				/* Load port arbitration table if used */ +				if (ctrl & PCI_VC_RES_CTRL_ARB_SELECT) +					pci_vc_load_port_arb_table(dev, pos, i); +				/* Re-enable if needed */ +				if ((ctrl ^ tmp) & PCI_VC_RES_CTRL_ENABLE) +					pci_vc_enable(dev, pos, i); +			} +			buf += 4; +		} +		len += 4; +	} + +	return buf ? 0 : len; +} + +static struct { +	u16 id; +	const char *name; +} vc_caps[] = { { PCI_EXT_CAP_ID_MFVC, "MFVC" }, +		{ PCI_EXT_CAP_ID_VC, "VC" }, +		{ PCI_EXT_CAP_ID_VC9, "VC9" } }; + +/** + * pci_save_vc_state - Save VC state to pre-allocate save buffer + * @dev: device + * + * For each type of VC capability, VC/VC9/MFVC, find the capability and + * save it to the pre-allocated save buffer. + */ +int pci_save_vc_state(struct pci_dev *dev) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { +		int pos, ret; +		struct pci_cap_saved_state *save_state; + +		pos = pci_find_ext_capability(dev, vc_caps[i].id); +		if (!pos) +			continue; + +		save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); +		if (!save_state) { +			dev_err(&dev->dev, "%s buffer not found in %s\n", +				vc_caps[i].name, __func__); +			return -ENOMEM; +		} + +		ret = pci_vc_do_save_buffer(dev, pos, save_state, true); +		if (ret) { +			dev_err(&dev->dev, "%s save unsuccessful %s\n", +				vc_caps[i].name, __func__); +			return ret; +		} +	} + +	return 0; +} + +/** + * pci_restore_vc_state - Restore VC state from save buffer + * @dev: device + * + * For each type of VC capability, VC/VC9/MFVC, find the capability and + * restore it from the previously saved buffer. + */ +void pci_restore_vc_state(struct pci_dev *dev) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { +		int pos; +		struct pci_cap_saved_state *save_state; + +		pos = pci_find_ext_capability(dev, vc_caps[i].id); +		save_state = pci_find_saved_ext_cap(dev, vc_caps[i].id); +		if (!save_state || !pos) +			continue; + +		pci_vc_do_save_buffer(dev, pos, save_state, false); +	} +} + +/** + * pci_allocate_vc_save_buffers - Allocate save buffers for VC caps + * @dev: device + * + * For each type of VC capability, VC/VC9/MFVC, find the capability, size + * it, and allocate a buffer for save/restore. + */ + +void pci_allocate_vc_save_buffers(struct pci_dev *dev) +{ +	int i; + +	for (i = 0; i < ARRAY_SIZE(vc_caps); i++) { +		int len, pos = pci_find_ext_capability(dev, vc_caps[i].id); + +		if (!pos) +			continue; + +		len = pci_vc_do_save_buffer(dev, pos, NULL, false); +		if (pci_add_ext_cap_save_buffer(dev, vc_caps[i].id, len)) +			dev_err(&dev->dev, +				"unable to preallocate %s save buffer\n", +				vc_caps[i].name); +	} +} diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index f7197a79034..53df39a22c8 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -20,6 +20,7 @@  #include <linux/workqueue.h>  #include <linux/bitops.h>  #include <linux/time.h> +#include <xen/platform_pci.h>  #include <asm/xen/swiotlb-xen.h>  #define INVALID_GRANT_REF (0) @@ -471,12 +472,15 @@ static int pcifront_scan_root(struct pcifront_device *pdev,  	}  	pcifront_init_sd(sd, domain, bus, pdev); +	pci_lock_rescan_remove(); +  	b = pci_scan_bus_parented(&pdev->xdev->dev, bus,  				  &pcifront_bus_ops, sd);  	if (!b) {  		dev_err(&pdev->xdev->dev,  			"Error creating PCI Frontend Bus!\n");  		err = -ENOMEM; +		pci_unlock_rescan_remove();  		goto err_out;  	} @@ -494,6 +498,7 @@ static int pcifront_scan_root(struct pcifront_device *pdev,  	/* Create SysFS and notify udev of the devices. Aka: "going live" */  	pci_bus_add_devices(b); +	pci_unlock_rescan_remove();  	return err;  err_out: @@ -556,6 +561,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev)  	dev_dbg(&pdev->xdev->dev, "cleaning up root buses\n"); +	pci_lock_rescan_remove();  	list_for_each_entry_safe(bus_entry, t, &pdev->root_buses, list) {  		list_del(&bus_entry->list); @@ -568,6 +574,7 @@ static void pcifront_free_roots(struct pcifront_device *pdev)  		kfree(bus_entry);  	} +	pci_unlock_rescan_remove();  }  static pci_ers_result_t pcifront_common_process(int cmd, @@ -655,9 +662,9 @@ static void pcifront_do_aer(struct work_struct *data)  	notify_remote_via_evtchn(pdev->evtchn);  	/*in case of we lost an aer request in four lines time_window*/ -	smp_mb__before_clear_bit(); +	smp_mb__before_atomic();  	clear_bit(_PDEVB_op_active, &pdev->flags); -	smp_mb__after_clear_bit(); +	smp_mb__after_atomic();  	schedule_pcifront_aer_op(pdev); @@ -1043,8 +1050,10 @@ static int pcifront_detach_devices(struct pcifront_device *pdev)  				domain, bus, slot, func);  			continue;  		} +		pci_lock_rescan_remove();  		pci_stop_and_remove_bus_device(pci_dev);  		pci_dev_put(pci_dev); +		pci_unlock_rescan_remove();  		dev_dbg(&pdev->xdev->dev,  			"PCI device %04x:%02x:%02x.%d removed.\n", @@ -1138,6 +1147,9 @@ static int __init pcifront_init(void)  	if (!xen_pv_domain() || xen_initial_domain())  		return -ENODEV; +	if (!xen_has_pv_devices()) +		return -ENODEV; +  	pci_frontend_registrar(1 /* enable */);  	return xenbus_register_frontend(&xenpci_driver);  | 
