From 85467136cdcc674f30beb0e5b79f048fe3a6a76f Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Feb 2013 17:06:45 -0700 Subject: [PATCH 01/63] PCI: Add PCI_BUS_NUM() and PCI_DEVID() interfaces PCI defines PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() interfaces; however, it doesn't have interfaces to return PCI bus and PCI device id. Drivers (AMD IOMMU, and AER) implement module specific definitions for PCI_BUS() and AMD_IOMMU driver also has a module specific interface to calculate PCI device id from bus number and devfn. Add PCI_BUS_NUM and PCI_DEVID interfaces to return PCI bus number and PCI device id respectively to avoid the need for duplicate definitions in other modules. AER driver code and AMD IOMMU driver define PCI_BUS. AMD IOMMU driver defines an interface to calculate device id from bus number, and devfn pair. PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() interfaces are exported to user-space via uapi/linux/pci.h. However, in the interest to keep the new interfaces as kernel only and not export them to user-space unnecessarily, added them to linux/pci.h instead. Signed-off-by: Shuah Khan Signed-off-by: Bjorn Helgaas Acked-by: Joerg Roedel --- include/linux/pci.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/linux/pci.h b/include/linux/pci.h index 2461033a7987..849a336e149c 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -35,6 +35,21 @@ /* Include the ID list */ #include +/* + * The PCI interface treats multi-function devices as independent + * devices. The slot/function address of each device is encoded + * in a single byte as follows: + * + * 7:3 = slot + * 2:0 = function + * PCI_DEVFN(), PCI_SLOT(), and PCI_FUNC() are defined uapi/linux/pci.h + * In the interest of not exposing interfaces to user-space unnecessarily, + * the following kernel only defines are being added here. + */ +#define PCI_DEVID(bus, devfn) ((((u16)bus) << 8) | devfn) +/* return bus from PCI devid = ((u16)bus_number) << 8) | devfn */ +#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff) + /* pci_slot represents a physical slot */ struct pci_slot { struct pci_bus *bus; /* The bus this slot is on */ From fff0ee3640d55c1df4e9da6084b20e2b3345abec Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Feb 2013 17:07:05 -0700 Subject: [PATCH 02/63] PCI/AER: Remove local PCI_BUS() define and use PCI_BUS_NUM() from PCI Change to remove local PCI_BUS() define and use the new PCI_BUS_NUM() interface from PCI. Signed-off-by: Shuah Khan Signed-off-by: Bjorn Helgaas Acked-by: Joerg Roedel --- drivers/pci/pcie/aer/aerdrv_core.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 564d97f94b6c..8ec8b4f48560 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -89,8 +89,6 @@ static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev) return -ENOSPC; } -#define PCI_BUS(x) (((x) >> 8) & 0xff) - /** * is_error_source - check whether the device is source of reported error * @dev: pointer to pci_dev to be checked @@ -106,7 +104,7 @@ static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info) * When bus id is equal to 0, it might be a bad id * reported by root port. */ - if (!nosourceid && (PCI_BUS(e_info->id) != 0)) { + if (!nosourceid && (PCI_BUS_NUM(e_info->id) != 0)) { /* Device ID match? */ if (e_info->id == ((dev->bus->number << 8) | dev->devfn)) return true; From c5081cd7a2b3db31a72b4c697321cf0425dbc2f1 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Feb 2013 17:07:19 -0700 Subject: [PATCH 03/63] iommu/amd: Remove local PCI_BUS() define and use PCI_BUS_NUM() from PCI Change to remove local PCI_BUS() define and use the new PCI_BUS_NUM() interface from PCI. Signed-off-by: Shuah Khan Signed-off-by: Bjorn Helgaas Acked-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 12 ++++++------ drivers/iommu/amd_iommu_init.c | 34 ++++++++++++++++----------------- drivers/iommu/amd_iommu_types.h | 4 +--- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 98f555dafb55..2a50fbe31c7b 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -649,26 +649,26 @@ retry: case EVENT_TYPE_ILL_DEV: printk("ILLEGAL_DEV_TABLE_ENTRY device=%02x:%02x.%x " "address=0x%016llx flags=0x%04x]\n", - PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), address, flags); dump_dte_entry(devid); break; case EVENT_TYPE_IO_FAULT: printk("IO_PAGE_FAULT device=%02x:%02x.%x " "domain=0x%04x address=0x%016llx flags=0x%04x]\n", - PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), domid, address, flags); break; case EVENT_TYPE_DEV_TAB_ERR: printk("DEV_TAB_HARDWARE_ERROR device=%02x:%02x.%x " "address=0x%016llx flags=0x%04x]\n", - PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), address, flags); break; case EVENT_TYPE_PAGE_TAB_ERR: printk("PAGE_TAB_HARDWARE_ERROR device=%02x:%02x.%x " "domain=0x%04x address=0x%016llx flags=0x%04x]\n", - PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), domid, address, flags); break; case EVENT_TYPE_ILL_CMD: @@ -682,13 +682,13 @@ retry: case EVENT_TYPE_IOTLB_INV_TO: printk("IOTLB_INV_TIMEOUT device=%02x:%02x.%x " "address=0x%016llx]\n", - PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), address); break; case EVENT_TYPE_INV_DEV_REQ: printk("INVALID_DEVICE_REQUEST device=%02x:%02x.%x " "address=0x%016llx flags=0x%04x]\n", - PCI_BUS(devid), PCI_SLOT(devid), PCI_FUNC(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid), address, flags); break; default: diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index b6ecddb63cd0..f8ed6f143d9d 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -423,7 +423,7 @@ static int __init find_last_devid_from_ivhd(struct ivhd_header *h) p += sizeof(*h); end += h->length; - find_last_devid_on_pci(PCI_BUS(h->devid), + find_last_devid_on_pci(PCI_BUS_NUM(h->devid), PCI_SLOT(h->devid), PCI_FUNC(h->devid), h->cap_ptr); @@ -784,10 +784,10 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_ALL\t\t\t first devid: %02x:%02x.%x" " last device %02x:%02x.%x flags: %02x\n", - PCI_BUS(iommu->first_device), + PCI_BUS_NUM(iommu->first_device), PCI_SLOT(iommu->first_device), PCI_FUNC(iommu->first_device), - PCI_BUS(iommu->last_device), + PCI_BUS_NUM(iommu->last_device), PCI_SLOT(iommu->last_device), PCI_FUNC(iommu->last_device), e->flags); @@ -801,7 +801,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_SELECT\t\t\t devid: %02x:%02x.%x " "flags: %02x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags); @@ -813,7 +813,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_SELECT_RANGE_START\t " "devid: %02x:%02x.%x flags: %02x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags); @@ -827,11 +827,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_ALIAS\t\t\t devid: %02x:%02x.%x " "flags: %02x devid_to: %02x:%02x.%x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, - PCI_BUS(e->ext >> 8), + PCI_BUS_NUM(e->ext >> 8), PCI_SLOT(e->ext >> 8), PCI_FUNC(e->ext >> 8)); @@ -846,11 +846,11 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_ALIAS_RANGE\t\t " "devid: %02x:%02x.%x flags: %02x " "devid_to: %02x:%02x.%x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, - PCI_BUS(e->ext >> 8), + PCI_BUS_NUM(e->ext >> 8), PCI_SLOT(e->ext >> 8), PCI_FUNC(e->ext >> 8)); @@ -864,7 +864,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_EXT_SELECT\t\t devid: %02x:%02x.%x " "flags: %02x ext: %08x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, e->ext); @@ -877,7 +877,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_EXT_SELECT_RANGE\t devid: " "%02x:%02x.%x flags: %02x ext: %08x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid), e->flags, e->ext); @@ -890,7 +890,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, case IVHD_DEV_RANGE_END: DUMP_printk(" DEV_RANGE_END\t\t devid: %02x:%02x.%x\n", - PCI_BUS(e->devid), + PCI_BUS_NUM(e->devid), PCI_SLOT(e->devid), PCI_FUNC(e->devid)); @@ -924,7 +924,7 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu, DUMP_printk(" DEV_SPECIAL(%s[%d])\t\tdevid: %02x:%02x.%x\n", var, (int)handle, - PCI_BUS(devid), + PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid)); @@ -1086,7 +1086,7 @@ static int __init init_iommu_all(struct acpi_table_header *table) DUMP_printk("device: %02x:%02x.%01x cap: %04x " "seg: %d flags: %01x info %04x\n", - PCI_BUS(h->devid), PCI_SLOT(h->devid), + PCI_BUS_NUM(h->devid), PCI_SLOT(h->devid), PCI_FUNC(h->devid), h->cap_ptr, h->pci_seg, h->flags, h->info); DUMP_printk(" mmio-addr: %016llx\n", @@ -1116,7 +1116,7 @@ static int iommu_init_pci(struct amd_iommu *iommu) int cap_ptr = iommu->cap_ptr; u32 range, misc, low, high; - iommu->dev = pci_get_bus_and_slot(PCI_BUS(iommu->devid), + iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid), iommu->devid & 0xff); if (!iommu->dev) return -ENODEV; @@ -1388,8 +1388,8 @@ static int __init init_unity_map_range(struct ivmd_header *m) DUMP_printk("%s devid_start: %02x:%02x.%x devid_end: %02x:%02x.%x" " range_start: %016llx range_end: %016llx flags: %x\n", s, - PCI_BUS(e->devid_start), PCI_SLOT(e->devid_start), - PCI_FUNC(e->devid_start), PCI_BUS(e->devid_end), + PCI_BUS_NUM(e->devid_start), PCI_SLOT(e->devid_start), + PCI_FUNC(e->devid_start), PCI_BUS_NUM(e->devid_end), PCI_SLOT(e->devid_end), PCI_FUNC(e->devid_end), e->address_start, e->address_end, m->flags); diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index e38ab438bb34..a07882f60b32 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -24,6 +24,7 @@ #include #include #include +#include /* * Maximum number of IOMMUs supported @@ -315,9 +316,6 @@ #define MAX_DOMAIN_ID 65536 -/* FIXME: move this macro to */ -#define PCI_BUS(x) (((x) >> 8) & 0xff) - /* Protection domain flags */ #define PD_DMA_OPS_MASK (1UL << 0) /* domain used for dma_ops */ #define PD_DEFAULT_MASK (1UL << 1) /* domain is a default dma_ops From 6f2729bab2cc386bb603698646dacd9ab6297ba0 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 27 Feb 2013 17:07:30 -0700 Subject: [PATCH 04/63] iommu/amd: Remove calc_devid() and use PCI_DEVID() from PCI Change to remove calc_devid() and use PCI_DEVID() from PCI instead. Signed-off-by: Shuah Khan Signed-off-by: Bjorn Helgaas Acked-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 2 +- drivers/iommu/amd_iommu_init.c | 6 +++--- drivers/iommu/amd_iommu_types.h | 7 ------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 2a50fbe31c7b..e046d7acca84 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -173,7 +173,7 @@ static inline u16 get_device_id(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); - return calc_devid(pdev->bus->number, pdev->devfn); + return PCI_DEVID(pdev->bus->number, pdev->devfn); } static struct iommu_dev_data *get_dev_data(struct device *dev) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index f8ed6f143d9d..551768af3fe7 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -406,7 +406,7 @@ static int __init find_last_devid_on_pci(int bus, int dev, int fn, int cap_ptr) u32 cap; cap = read_pci_config(bus, dev, fn, cap_ptr+MMIO_RANGE_OFFSET); - update_last_devid(calc_devid(MMIO_GET_BUS(cap), MMIO_GET_LD(cap))); + update_last_devid(PCI_DEVID(MMIO_GET_BUS(cap), MMIO_GET_LD(cap))); return 0; } @@ -1128,9 +1128,9 @@ static int iommu_init_pci(struct amd_iommu *iommu) pci_read_config_dword(iommu->dev, cap_ptr + MMIO_MISC_OFFSET, &misc); - iommu->first_device = calc_devid(MMIO_GET_BUS(range), + iommu->first_device = PCI_DEVID(MMIO_GET_BUS(range), MMIO_GET_FD(range)); - iommu->last_device = calc_devid(MMIO_GET_BUS(range), + iommu->last_device = PCI_DEVID(MMIO_GET_BUS(range), MMIO_GET_LD(range)); if (!(iommu->cap & (1 << IOMMU_CAP_IOTLB))) diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index a07882f60b32..ec36cf63e0ca 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -701,13 +701,6 @@ extern int amd_iommu_max_glx_val; */ extern void iommu_flush_all_caches(struct amd_iommu *iommu); -/* takes bus and device/function and returns the device id - * FIXME: should that be in generic PCI code? */ -static inline u16 calc_devid(u8 bus, u8 devfn) -{ - return (((u16)bus) << 8) | devfn; -} - static inline int get_ioapic_devid(int id) { struct devid_map *entry; From e82b14bdd390c534750a191f9936f842bab255d4 Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 20 Mar 2013 12:04:43 +0000 Subject: [PATCH 05/63] PCI: aer_inject: Fix return values when device not found Currently the aer_inject driver returns -ENOTTY when the target PCIe device root port is not found or if the device or root port doesn't support AER. In the case where the root port isn't found, the driver should return -ENODEV, and in the other cases it should return -EPERM. Signed-off-by: Prarit Bhargava Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/aer/aer_inject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 4e24cb8a94ae..8d4a5e3dbe8e 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -334,13 +334,13 @@ static int aer_inject(struct aer_error_inj *einj) return -ENODEV; rpdev = pcie_find_root_port(dev); if (!rpdev) { - ret = -ENOTTY; + ret = -ENODEV; goto out_put; } pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); if (!pos_cap_err) { - ret = -ENOTTY; + ret = -EPERM; goto out_put; } pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever); @@ -350,7 +350,7 @@ static int aer_inject(struct aer_error_inj *einj) rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR); if (!rp_pos_cap_err) { - ret = -ENOTTY; + ret = -EPERM; goto out_put; } From 705888184276552a12475f9d9f9ee78136cd523a Mon Sep 17 00:00:00 2001 From: Xiong Huang Date: Thu, 7 Mar 2013 08:55:16 +0000 Subject: [PATCH 06/63] PCI: Add MSI INTX_DISABLE quirks for AR8161/AR8162/AR8171/AR8172/E210X The following PCIe devices with revision lower than 0x18 have this bug: AR8161(1091)/AR8162(1090)/AR8171(10A1)/AR8172(10A0)/E210X(E091). Signed-off-by: Huang,Xiong Signed-off-by: Bjorn Helgaas Reviewed-by: Wei Yang --- drivers/pci/quirks.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0369fb6fc1da..4273a2d7132c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2594,6 +2594,14 @@ static void quirk_msi_intx_disable_ati_bug(struct pci_dev *dev) dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; pci_dev_put(p); } +static void quirk_msi_intx_disable_qca_bug(struct pci_dev *dev) +{ + /* AR816X/AR817X/E210X MSI is fixed at HW level from revision 0x18 */ + if (dev->revision < 0x18) { + dev_info(&dev->dev, "set MSI_INTX_DISABLE_BUG flag\n"); + dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG; + } +} DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780, quirk_msi_intx_disable_bug); @@ -2643,6 +2651,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1073, quirk_msi_intx_disable_bug); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1083, quirk_msi_intx_disable_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1090, + quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x1091, + quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a0, + quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0x10a1, + quirk_msi_intx_disable_qca_bug); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, 0xe091, + quirk_msi_intx_disable_qca_bug); #endif /* CONFIG_PCI_MSI */ /* Allow manual resource allocation for PCI hotplug bridges From 10629d711ed780470937ecda50d9ffa0e925a4ee Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 10 Apr 2013 09:56:54 -0600 Subject: [PATCH 07/63] PCI: Remove __weak annotation from pcibios_get_phb_of_node decl The __weak annotation on the pcibios_get_phb_of_node() declaration causes *every* definition to be marked "weak." The linker then selects one based on link order, which may be the wrong one. Gabor found that on MIPS, the linker selected the generic implementation from drivers/pci even though arch/mips supplied a definition without the __weak annotation: $ mipsel-openwrt-linux-readelf -s arch/mips/pci/built-in.o \ drivers/pci/built-in.o vmlinux.o | grep pcibios_get_phb_of_node 86: 0000046c 12 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node 1430: 00012e2c 104 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node 31898: 0017e4ec 104 FUNC WEAK DEFAULT 2 pcibios_get_phb_of_node This removes the __weak annotation from the pcibios_get_phb_of_node() declaration so arch-specific non-weak implementations work reliably. Suggested-by: Gabor Juhos Signed-off-by: Bjorn Helgaas --- include/linux/pci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index 2461033a7987..67734407fc7f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1823,7 +1823,7 @@ extern void pci_set_bus_of_node(struct pci_bus *bus); extern void pci_release_bus_of_node(struct pci_bus *bus); /* Arch may override this (weak) */ -extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus); +extern struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus); static inline struct device_node * pci_device_to_OF_node(const struct pci_dev *pdev) From 9a97cd43f4ef62520a852b5a2348233b0f37455b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Thu, 4 Apr 2013 20:01:23 +0200 Subject: [PATCH 08/63] MIPS/PCI: Implement pcibios_get_phb_of_node The of_node field of the device assigned to a PCI bus is used during scanning of the PCI bus. However on MIPS, the of_node field is assigned only after the bus has been scanned. Implement the architecture specific version of 'pcibios_get_phb_of_node'. Which ensures that the PCI driver core will initialize the of_node field before starting the scan. Also remove the local assignment of bus->dev.of_node, it is not needed after the patch. Signed-off-by: Gabor Juhos Signed-off-by: Bjorn Helgaas --- arch/mips/pci/pci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 0872f12f268d..594e60d6a43b 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -115,7 +115,6 @@ static void pcibios_scanbus(struct pci_controller *hose) pci_bus_assign_resources(bus); pci_enable_bridges(bus); } - bus->dev.of_node = hose->of_node; } } @@ -169,6 +168,13 @@ void pci_load_of_ranges(struct pci_controller *hose, struct device_node *node) } } } + +struct device_node *pcibios_get_phb_of_node(struct pci_bus *bus) +{ + struct pci_controller *hose = bus->sysdata; + + return of_node_get(hose->of_node); +} #endif static DEFINE_MUTEX(pci_scan_mutex); From 139f925126cc31b925484b2bc2cd0b0357c2bbd6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 12 Apr 2013 11:17:47 -0600 Subject: [PATCH 09/63] PCI: Fix missing prototype for pcie_port_acpi_setup() This fixes a "no previous prototype" warning for pcie_port_acpi_setup() found via "make W=1". [bhelgaas: changelog] Signed-off-by: Andy Shevchenko Signed-off-by: Bjorn Helgaas --- drivers/pci/pcie/portdrv_acpi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c index a86b56e5f2f2..b4d2894ee3fc 100644 --- a/drivers/pci/pcie/portdrv_acpi.c +++ b/drivers/pci/pcie/portdrv_acpi.c @@ -17,6 +17,7 @@ #include "aer/aerdrv.h" #include "../pci.h" +#include "portdrv.h" /** * pcie_port_acpi_setup - Request the BIOS to release control of PCIe services. From 9738abedd6721926dfb25fe6912be207b7168d03 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 12 Apr 2013 11:20:03 -0600 Subject: [PATCH 10/63] PCI: Make local functions/structs static This fixes "no previous prototype" warnings found via "make W=1". Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 4 ++-- drivers/pci/pci.c | 8 ++++---- drivers/pci/pcie/aer/aer_inject.c | 4 ++-- drivers/pci/setup-bus.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 00cc78c7aa04..bbff7d5a9b35 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -484,12 +484,12 @@ static struct msi_attribute mode_attribute = __ATTR(mode, S_IRUGO, show_msi_mode, NULL); -struct attribute *msi_irq_default_attrs[] = { +static struct attribute *msi_irq_default_attrs[] = { &mode_attribute.attr, NULL }; -void msi_kobj_release(struct kobject *kobj) +static void msi_kobj_release(struct kobject *kobj) { struct msi_desc *entry = to_msi_desc(kobj); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b099e0025d2b..f0ef3997ed3b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2619,7 +2619,7 @@ void pci_release_selected_regions(struct pci_dev *pdev, int bars) pci_release_region(pdev, i); } -int __pci_request_selected_regions(struct pci_dev *pdev, int bars, +static int __pci_request_selected_regions(struct pci_dev *pdev, int bars, const char *res_name, int excl) { int i; @@ -3699,7 +3699,7 @@ static DEFINE_SPINLOCK(resource_alignment_lock); * RETURNS: Resource alignment if it is specified. * Zero if it is not specified. */ -resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) +static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev) { int seg, bus, slot, func, align_order, count; resource_size_t align = 0; @@ -3812,7 +3812,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev) } } -ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) +static ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) { if (count > RESOURCE_ALIGNMENT_PARAM_SIZE - 1) count = RESOURCE_ALIGNMENT_PARAM_SIZE - 1; @@ -3823,7 +3823,7 @@ ssize_t pci_set_resource_alignment_param(const char *buf, size_t count) return count; } -ssize_t pci_get_resource_alignment_param(char *buf, size_t size) +static ssize_t pci_get_resource_alignment_param(char *buf, size_t size) { size_t count; spin_lock(&resource_alignment_lock); diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c index 4e24cb8a94ae..2f15475b56bc 100644 --- a/drivers/pci/pcie/aer/aer_inject.c +++ b/drivers/pci/pcie/aer/aer_inject.c @@ -212,8 +212,8 @@ out: return ops->read(bus, devfn, where, size, val); } -int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size, - u32 val) +static int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) { u32 *sim; struct aer_error *err; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 7e8739e25b9e..502a75ea12fb 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1044,7 +1044,7 @@ handle_done: ; } -void __ref __pci_bus_size_bridges(struct pci_bus *bus, +static void __ref __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) { struct pci_dev *dev; From 1e89d268e7a83d8388d4d09d3f2089ced72cc15f Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:15 +0000 Subject: [PATCH 11/63] PCI: When removing bus, always remove legacy files & unregister We always call device_register() and pci_create_legacy_files() for a new bus before handing out the "struct pci_bus *". Therefore, there's no possiblity of removing the bus with pci_remove_bus() before those calls have been made, so we don't need to check "bus->is_added" before calling pci_remove_legacy_files() and device_unregister(). [bhelgaas: changelog] Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/remove.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index cc875e6ed159..a8318801c092 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -50,9 +50,6 @@ void pci_remove_bus(struct pci_bus *bus) list_del(&bus->node); pci_bus_release_busn_res(bus); up_write(&pci_bus_sem); - if (!bus->is_added) - return; - pci_remove_legacy_files(bus); device_unregister(&bus->dev); } From 981cf9ea9a6a6c422e51fc04bedad00b7792ccbc Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:16 +0000 Subject: [PATCH 12/63] PCI: Clean up usages of pci_bus->is_added Now pci_bus->is_added is only used to guard invoking of pcibios_fixup_bus() in pci_scan_child_bus(), so just set it directly after the fixups and remove the other test and set in pci_bus_add_devices(). [bhelgaas: changelog] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu --- drivers/pci/bus.c | 11 ++--------- drivers/pci/probe.c | 3 +-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 8647dc6f52d0..bdc1e8bf7e60 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -206,16 +206,9 @@ void pci_bus_add_devices(const struct pci_bus *bus) list_for_each_entry(dev, &bus->devices, bus_list) { BUG_ON(!dev->is_added); - child = dev->subordinate; - - if (!child) - continue; - pci_bus_add_devices(child); - - if (child->is_added) - continue; - child->is_added = 1; + if (child) + pci_bus_add_devices(child); } } diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b494066ef32f..45c93b39af35 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1627,8 +1627,7 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) if (!bus->is_added) { dev_dbg(&bus->dev, "fixups for bus\n"); pcibios_fixup_bus(bus); - if (pci_is_root_bus(bus)) - bus->is_added = 1; + bus->is_added = 1; } for (pass=0; pass < 2; pass++) From d65eba6a7a769bb939303969267cbf1c916358f5 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 12 Apr 2013 05:44:17 +0000 Subject: [PATCH 13/63] PCI: acpiphp: Use list_for_each_entry_safe() in acpiphp_sanitize_bus() Function acpiphp_sanitize_bus() may call pci_stop_and_remove_bus_device(), which in turn may remove device from bus->devices list. So walk the bus->devices list with list_for_each_entry_safe(). Signed-off-by: Yijing Wang Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/hotplug/acpiphp_glue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 270fdbadc19c..7948bc919605 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -1082,11 +1082,11 @@ static void acpiphp_set_hpp_values(struct pci_bus *bus) */ static void acpiphp_sanitize_bus(struct pci_bus *bus) { - struct pci_dev *dev; + struct pci_dev *dev, *tmp; int i; unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; - list_for_each_entry(dev, &bus->devices, bus_list) { + list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { for (i=0; iresource[i]; if ((res->flags & type_mask) && !res->start && From 3a0e40beefc20852191ed65d53e1b82d95ac11b8 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:18 +0000 Subject: [PATCH 14/63] PCI: acpiphp: Remove all functions even if function 0 doesn't exist Currently function disable_device() detects slot state by checking existence of PCI function 0. It's unreliable because the PCI device for function 0 may be removed through the sysfs interface. If that happens, it will cause powering off a hotplug slot without destroying all PCI devices. On the other hand, it won't hurt us except wasting some computation power if the check is removed, because all code of disable_device() is self-protected. So remove the check. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/hotplug/acpiphp_glue.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 7948bc919605..a1c8dd67aae1 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -914,13 +914,6 @@ static int disable_device(struct acpiphp_slot *slot) struct pci_dev *pdev; struct pci_bus *bus = slot->bridge->pci_bus; - /* The slot will be enabled when func 0 is added, so check - func 0 before disable the slot. */ - pdev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0)); - if (!pdev) - goto err_exit; - pci_dev_put(pdev); - list_for_each_entry(func, &slot->funcs, sibling) { if (func->bridge) { /* cleanup p2p bridges under this P2P bridge */ From ce15d873d05ebf3bf38579c4e0252140e28f1781 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:19 +0000 Subject: [PATCH 15/63] PCI: acpiphp: Replace local macros with standard ACPI macros Replace local defined macros (ACPI_STA_xxx) with standard ACPI macros (ACPI_STA_DEVICE_xxx). Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/hotplug/acpiphp.h | 4 ---- drivers/pci/hotplug/acpiphp_glue.c | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b70ac00a117e..1b311f9db82d 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -146,10 +146,6 @@ struct acpiphp_attention_info #define ACPI_PCI_HOST_HID "PNP0A03" /* ACPI _STA method value (ignore bit 4; battery present) */ -#define ACPI_STA_PRESENT (0x00000001) -#define ACPI_STA_ENABLED (0x00000002) -#define ACPI_STA_SHOW_IN_UI (0x00000004) -#define ACPI_STA_FUNCTIONING (0x00000008) #define ACPI_STA_ALL (0x0000000f) /* bridge flags */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a1c8dd67aae1..718464f8fd40 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -487,7 +487,7 @@ static int add_bridge(struct acpi_pci_root *root) dbg("%s: _STA evaluation failure\n", __func__); return 0; } - if ((tmp & ACPI_STA_FUNCTIONING) == 0) + if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0) /* don't register this object */ return 0; } @@ -1389,7 +1389,7 @@ u8 acpiphp_get_latch_status(struct acpiphp_slot *slot) sta = get_slot_status(slot); - return (sta & ACPI_STA_SHOW_IN_UI) ? 0 : 1; + return (sta & ACPI_STA_DEVICE_UI) ? 0 : 1; } From 10a9574756201fbbdd0cac11f370f00d3d02bfa1 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:20 +0000 Subject: [PATCH 16/63] PCI: Add pcibios hooks for adding and removing PCI buses On ACPI-based platforms, the pci_slot driver creates PCI slot devices according to information from ACPI tables by registering an ACPI PCI subdriver. The ACPI PCI subdriver will only be called when creating/ destroying PCI root buses, and it won't be called when hot-plugging P2P bridges. It may cause stale PCI slot devices after hot-removing a P2P bridge if that bridge has associated PCI slots. And the acpiphp driver has the same issue too. This patch introduces two hook points into the PCI core, which will be invoked when creating/destroying PCI buses for PCI host and P2P bridges. They could be used to setup/destroy platform dependent stuff in a unified way, both at boot time and for PCI hotplug operations. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani Cc: Tony Luck Cc: Fenghua Yu Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Myron Stowe --- drivers/pci/probe.c | 12 ++++++++++++ drivers/pci/remove.c | 1 + include/linux/pci.h | 2 ++ 3 files changed, 15 insertions(+) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 45c93b39af35..43ece5d41d36 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -673,6 +673,8 @@ add_dev: ret = device_register(&child->dev); WARN_ON(ret < 0); + pcibios_add_bus(child); + /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(child); @@ -1660,6 +1662,14 @@ int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) return 0; } +void __weak pcibios_add_bus(struct pci_bus *bus) +{ +} + +void __weak pcibios_remove_bus(struct pci_bus *bus) +{ +} + struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources) { @@ -1714,6 +1724,8 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, if (error) goto class_dev_reg_err; + pcibios_add_bus(b); + /* Create legacy_io and legacy_mem files for this bus */ pci_create_legacy_files(b); diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index a8318801c092..8fc54b7327bc 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -51,6 +51,7 @@ void pci_remove_bus(struct pci_bus *bus) pci_bus_release_busn_res(bus); up_write(&pci_bus_sem); pci_remove_legacy_files(bus); + pcibios_remove_bus(bus); device_unregister(&bus->dev); } EXPORT_SYMBOL(pci_remove_bus); diff --git a/include/linux/pci.h b/include/linux/pci.h index 2461033a7987..be9399452133 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -678,6 +678,8 @@ extern struct list_head pci_root_buses; /* list of all known PCI buses */ extern int no_pci_devices(void); void pcibios_resource_survey_bus(struct pci_bus *bus); +void pcibios_add_bus(struct pci_bus *bus); +void pcibios_remove_bus(struct pci_bus *bus); void pcibios_fixup_bus(struct pci_bus *); int __must_check pcibios_enable_device(struct pci_dev *, int mask); /* Architecture specific versions may override this (weak) */ From 5090d4a6a1f150ec593ac5f2a755b5a3e878b21e Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:21 +0000 Subject: [PATCH 17/63] PCI/ACPI: Prepare stub functions to handle ACPI PCI (hotplug) slots Prepare two stub functions to handle ACPI PCI slots and ACPI PCI hotplug slots, which will be invoked by the PCI core when creating/destroying PCI buses. It will be used to get rid of ACPI PCI subdrivers for pci_slot and acpiphp, and eventually remove the ACPI PCI subdriver mechanism. And it will also be used to handle ACPI PCI (hotplug) slots in a unified way, both at boot time and for PCI hotplug operations. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani Cc: Tony Luck Cc: Fenghua Yu Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Myron Stowe --- drivers/pci/pci-acpi.c | 24 ++++++++++++++++++++++++ include/linux/pci-acpi.h | 8 +++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index dee5dddaa292..b8b8437c703e 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -287,6 +287,30 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = { .run_wake = acpi_pci_run_wake, }; +void acpi_pci_add_bus(struct pci_bus *bus) +{ + acpi_handle handle = NULL; + + if (bus->bridge) + handle = ACPI_HANDLE(bus->bridge); + if (acpi_pci_disabled || handle == NULL) + return; + + /* TODO: add PCI slots and acpiphp hotplug slots */ +} + +void acpi_pci_remove_bus(struct pci_bus *bus) +{ + /* + * bus->bridge->acpi_node.handle has already been reset to NULL + * when acpi_pci_remove_bus() is called, so don't check ACPI handle. + */ + if (acpi_pci_disabled) + return; + + /* TODO: remove PCI slots and acpiphp hotplug slots */ +} + /* ACPI bus type */ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) { diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 9a22b5efb384..2b1743cc3186 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -41,7 +41,13 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) return DEVICE_ACPI_HANDLE(dev); } -#endif + +void acpi_pci_add_bus(struct pci_bus *bus); +void acpi_pci_remove_bus(struct pci_bus *bus); +#else /* CONFIG_ACPI */ +static inline void acpi_pci_add_bus(struct pci_bus *bus) { } +static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } +#endif /* CONFIG_ACPI */ #ifdef CONFIG_ACPI_APEI extern bool aer_acpi_firmware_first(void); From b02a4a193420890fdf0d1285cfb9a92e416dcd5c Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:22 +0000 Subject: [PATCH 18/63] ia64/PCI: Implement pcibios_{add|remove}_bus() hooks Implement pcibios_{add|remove}_bus() hooks for IA64 platforms. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani Cc: Tony Luck Cc: Fenghua Yu --- arch/ia64/pci/pci.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 60532ab27346..de1474ff0bc5 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -458,6 +459,16 @@ void pcibios_fixup_bus(struct pci_bus *b) platform_pci_fixup_bus(b); } +void pcibios_add_bus(struct pci_bus *bus) +{ + acpi_pci_add_bus(bus); +} + +void pcibios_remove_bus(struct pci_bus *bus) +{ + acpi_pci_remove_bus(bus); +} + void pcibios_set_master (struct pci_dev *dev) { /* No special bus mastering setup handling */ From 89016506b62a79766c091959ecb40ec666f381bc Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:23 +0000 Subject: [PATCH 19/63] x86/PCI: Implement pcibios_{add|remove}_bus() hooks Implement pcibios_{add|remove}_bus() hooks for x86 platforms. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Cc: Myron Stowe --- arch/x86/pci/common.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 901177d75ff5..305c68b8d538 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -170,6 +171,16 @@ void pcibios_fixup_bus(struct pci_bus *b) pcibios_fixup_device_resources(dev); } +void pcibios_add_bus(struct pci_bus *bus) +{ + acpi_pci_add_bus(bus); +} + +void pcibios_remove_bus(struct pci_bus *bus) +{ + acpi_pci_remove_bus(bus); +} + /* * Only use DMI information to set this if nothing was passed * on the kernel command line (which was parsed earlier). From 5c0b04e3d913c91aee6e48e567e20a3f67849618 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:24 +0000 Subject: [PATCH 20/63] PCI/ACPI: Handle PCI slot devices when creating/destroying PCI buses Currently the pci_slot driver doesn't update PCI slot devices when PCI device hotplug event happens, which may cause memory leak and returning stale information to user. Now the pci_slot driver has been changed as built-in driver, so invoke PCI slot enumeration and destroy routines directly from the PCI core. And remove ACPI PCI sub-driver related code because it isn't needed any more. [bhelgas: removed "extern" from function declarations] Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Acked-by: Rafael J. Wysocki Cc: Toshi Kani --- drivers/acpi/pci_slot.c | 170 ++++++--------------------------------- drivers/acpi/scan.c | 1 - drivers/pci/pci-acpi.c | 7 +- include/linux/pci-acpi.h | 12 +++ 4 files changed, 41 insertions(+), 149 deletions(-) diff --git a/drivers/acpi/pci_slot.c b/drivers/acpi/pci_slot.c index cd1434eb1de8..033d1179bdb5 100644 --- a/drivers/acpi/pci_slot.c +++ b/drivers/acpi/pci_slot.c @@ -9,6 +9,9 @@ * Copyright (C) 2007-2008 Hewlett-Packard Development Company, L.P. * Alex Chiang * + * Copyright (C) 2013 Huawei Tech. Co., Ltd. + * Jiang Liu + * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. @@ -28,10 +31,9 @@ #include #include #include +#include #include #include -#include -#include #include static bool debug; @@ -61,20 +63,12 @@ ACPI_MODULE_NAME("pci_slot"); #define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ struct acpi_pci_slot { - acpi_handle root_handle; /* handle of the root bridge */ struct pci_slot *pci_slot; /* corresponding pci_slot */ struct list_head list; /* node in the list of slots */ }; -static int acpi_pci_slot_add(struct acpi_pci_root *root); -static void acpi_pci_slot_remove(struct acpi_pci_root *root); - static LIST_HEAD(slot_list); static DEFINE_MUTEX(slot_list_lock); -static struct acpi_pci_driver acpi_pci_slot_driver = { - .add = acpi_pci_slot_add, - .remove = acpi_pci_slot_remove, -}; static int check_slot(acpi_handle handle, unsigned long long *sun) @@ -113,21 +107,8 @@ out: return device; } -struct callback_args { - acpi_walk_callback user_function; /* only for walk_p2p_bridge */ - struct pci_bus *pci_bus; - acpi_handle root_handle; -}; - /* - * register_slot - * - * Called once for each SxFy object in the namespace. Don't worry about - * calling pci_create_slot multiple times for the same pci_bus:device, - * since each subsequent call simply bumps the refcount on the pci_slot. - * - * The number of calls to pci_destroy_slot from unregister_slot is - * symmetrical. + * Check whether handle has an associated slot and create PCI slot if it has. */ static acpi_status register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) @@ -137,13 +118,22 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) char name[SLOT_NAME_SIZE]; struct acpi_pci_slot *slot; struct pci_slot *pci_slot; - struct callback_args *parent_context = context; - struct pci_bus *pci_bus = parent_context->pci_bus; + struct pci_bus *pci_bus = context; device = check_slot(handle, &sun); if (device < 0) return AE_OK; + /* + * There may be multiple PCI functions associated with the same slot. + * Check whether PCI slot has already been created for this PCI device. + */ + list_for_each_entry(slot, &slot_list, list) { + pci_slot = slot->pci_slot; + if (pci_slot->bus == pci_bus && pci_slot->number == device) + return AE_OK; + } + slot = kmalloc(sizeof(*slot), GFP_KERNEL); if (!slot) { err("%s: cannot allocate memory\n", __func__); @@ -158,12 +148,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } - slot->root_handle = parent_context->root_handle; slot->pci_slot = pci_slot; - INIT_LIST_HEAD(&slot->list); - mutex_lock(&slot_list_lock); list_add(&slot->list, &slot_list); - mutex_unlock(&slot_list_lock); get_device(&pci_bus->dev); @@ -173,131 +159,24 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -/* - * walk_p2p_bridge - discover and walk p2p bridges - * @handle: points to an acpi_pci_root - * @context: p2p_bridge_context pointer - * - * Note that when we call ourselves recursively, we pass a different - * value of pci_bus in the child_context. - */ -static acpi_status -walk_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) +void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle) { - int device, function; - unsigned long long adr; - acpi_status status; - acpi_handle dummy_handle; - acpi_walk_callback user_function; - - struct pci_dev *dev; - struct pci_bus *pci_bus; - struct callback_args child_context; - struct callback_args *parent_context = context; - - pci_bus = parent_context->pci_bus; - user_function = parent_context->user_function; - - status = acpi_get_handle(handle, "_ADR", &dummy_handle); - if (ACPI_FAILURE(status)) - return AE_OK; - - status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); - if (ACPI_FAILURE(status)) - return AE_OK; - - device = (adr >> 16) & 0xffff; - function = adr & 0xffff; - - dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function)); - if (!dev || !dev->subordinate) - goto out; - - child_context.pci_bus = dev->subordinate; - child_context.user_function = user_function; - child_context.root_handle = parent_context->root_handle; - - dbg("p2p bridge walk, pci_bus = %x\n", dev->subordinate->number); - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - user_function, NULL, &child_context, NULL); - if (ACPI_FAILURE(status)) - goto out; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - walk_p2p_bridge, NULL, &child_context, NULL); -out: - pci_dev_put(dev); - return AE_OK; + mutex_lock(&slot_list_lock); + acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1, + register_slot, NULL, bus, NULL); + mutex_unlock(&slot_list_lock); } -/* - * walk_root_bridge - generic root bridge walker - * @root: poiner of an acpi_pci_root - * @user_function: user callback for slot objects - * - * Call user_function for all objects underneath this root bridge. - * Walk p2p bridges underneath us and call user_function on those too. - */ -static int -walk_root_bridge(struct acpi_pci_root *root, acpi_walk_callback user_function) -{ - acpi_status status; - acpi_handle handle = root->device->handle; - struct pci_bus *pci_bus = root->bus; - struct callback_args context; - - context.pci_bus = pci_bus; - context.user_function = user_function; - context.root_handle = handle; - - dbg("root bridge walk, pci_bus = %x\n", pci_bus->number); - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - user_function, NULL, &context, NULL); - if (ACPI_FAILURE(status)) - return status; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - walk_p2p_bridge, NULL, &context, NULL); - if (ACPI_FAILURE(status)) - err("%s: walk_p2p_bridge failure - %d\n", __func__, status); - - return status; -} - -/* - * acpi_pci_slot_add - * @handle: points to an acpi_pci_root - */ -static int -acpi_pci_slot_add(struct acpi_pci_root *root) -{ - acpi_status status; - - status = walk_root_bridge(root, register_slot); - if (ACPI_FAILURE(status)) - err("%s: register_slot failure - %d\n", __func__, status); - - return status; -} - -/* - * acpi_pci_slot_remove - * @handle: points to an acpi_pci_root - */ -static void -acpi_pci_slot_remove(struct acpi_pci_root *root) +void acpi_pci_slot_remove(struct pci_bus *bus) { struct acpi_pci_slot *slot, *tmp; - struct pci_bus *pbus; - acpi_handle handle = root->device->handle; mutex_lock(&slot_list_lock); list_for_each_entry_safe(slot, tmp, &slot_list, list) { - if (slot->root_handle == handle) { + if (slot->pci_slot->bus == bus) { list_del(&slot->list); - pbus = slot->pci_slot->bus; pci_destroy_slot(slot->pci_slot); - put_device(&pbus->dev); + put_device(&bus->dev); kfree(slot); } } @@ -332,5 +211,4 @@ static struct dmi_system_id acpi_pci_slot_dmi_table[] __initdata = { void __init acpi_pci_slot_init(void) { dmi_check_system(acpi_pci_slot_dmi_table); - acpi_pci_register_driver(&acpi_pci_slot_driver); } diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 5e7e991717d7..f54d1985e594 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1790,7 +1790,6 @@ int __init acpi_scan_init(void) acpi_platform_init(); acpi_csrt_init(); acpi_container_init(); - acpi_pci_slot_init(); mutex_lock(&acpi_scan_lock); /* diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index b8b8437c703e..98e582a2c909 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -296,7 +296,7 @@ void acpi_pci_add_bus(struct pci_bus *bus) if (acpi_pci_disabled || handle == NULL) return; - /* TODO: add PCI slots and acpiphp hotplug slots */ + acpi_pci_slot_enumerate(bus, handle); } void acpi_pci_remove_bus(struct pci_bus *bus) @@ -308,7 +308,7 @@ void acpi_pci_remove_bus(struct pci_bus *bus) if (acpi_pci_disabled) return; - /* TODO: remove PCI slots and acpiphp hotplug slots */ + acpi_pci_slot_remove(bus); } /* ACPI bus type */ @@ -385,7 +385,10 @@ static int __init acpi_pci_init(void) ret = register_acpi_bus_type(&acpi_pci_bus); if (ret) return 0; + pci_set_platform_pm(&acpi_pci_platform_pm); + acpi_pci_slot_init(); + return 0; } arch_initcall(acpi_pci_init); diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 2b1743cc3186..23cd40abba4f 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -44,6 +44,18 @@ static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) void acpi_pci_add_bus(struct pci_bus *bus); void acpi_pci_remove_bus(struct pci_bus *bus); + +#ifdef CONFIG_ACPI_PCI_SLOT +void acpi_pci_slot_init(void); +void acpi_pci_slot_enumerate(struct pci_bus *bus, acpi_handle handle); +void acpi_pci_slot_remove(struct pci_bus *bus); +#else +static inline void acpi_pci_slot_init(void) { } +static inline void acpi_pci_slot_enumerate(struct pci_bus *bus, + acpi_handle handle) { } +static inline void acpi_pci_slot_remove(struct pci_bus *bus) { } +#endif + #else /* CONFIG_ACPI */ static inline void acpi_pci_add_bus(struct pci_bus *bus) { } static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } From 6037a803b05eef9943fb64982e19964007fb7478 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:25 +0000 Subject: [PATCH 21/63] PCI: acpiphp: Convert acpiphp to be builtin only, not modular Convert acpiphp to be builtin only, with no module option. Previously, when HOTPLUG_PCI_ACPI=m, users could disable acpiphp by removing the module or preventing it from loading. That can't be done if acpiphp is builtin statically, so this adds an "acpiphp.disable" kernel parameter. If a user needs to use this parameter, it is a bug, and we want to hear about it. [bhelgaas: fold in acpiphp.disable here, remove documentation] Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/Kconfig | 7 ++----- drivers/pci/hotplug/acpiphp.h | 1 + drivers/pci/hotplug/acpiphp_core.c | 19 +++++++------------ 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index 13e9e63a7266..9fcb87f353d4 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -52,15 +52,12 @@ config HOTPLUG_PCI_IBM When in doubt, say N. config HOTPLUG_PCI_ACPI - tristate "ACPI PCI Hotplug driver" - depends on (!ACPI_DOCK && ACPI) || (ACPI_DOCK) + bool "ACPI PCI Hotplug driver" + depends on HOTPLUG_PCI=y && ((!ACPI_DOCK && ACPI) || (ACPI_DOCK)) help Say Y here if you have a system that supports PCI Hotplug using ACPI. - To compile this driver as a module, choose M here: the - module will be called acpiphp. - When in doubt, say N. config HOTPLUG_PCI_ACPI_IBM diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 1b311f9db82d..b06ae681d5b7 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -190,5 +190,6 @@ extern 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 c2fd3095701f..81adbfa4df1b 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -48,6 +48,7 @@ #define SLOT_NAME_SIZE 21 /* {_SUN} */ bool acpiphp_debug; +bool acpiphp_disabled; /* local variables */ static struct acpiphp_attention_info *attention_info; @@ -60,7 +61,9 @@ 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); @@ -353,9 +356,11 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) static int __init acpiphp_init(void) { - info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); + info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", + acpiphp_disabled ? ", disabled by user; please report a bug" + : ""); - if (acpi_pci_disabled) + if (acpi_pci_disabled || acpiphp_disabled) return 0; /* read all the ACPI info from the system */ @@ -364,14 +369,4 @@ static int __init acpiphp_init(void) } -static void __exit acpiphp_exit(void) -{ - if (acpi_pci_disabled) - return; - - /* deallocate internal data structures etc. */ - acpiphp_glue_exit(); -} - module_init(acpiphp_init); -module_exit(acpiphp_exit); From 3b63aaa70e1ccc4b66d60acc78da09700706a703 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:26 +0000 Subject: [PATCH 22/63] PCI: acpiphp: Do not use ACPI PCI subdriver mechanism Previously the acpiphp driver registered itself as an ACPI PCI subdriver, so its callbacks were invoked when creating/destroying PCI root buses to manage ACPI-based PCI hotplug slots. But it doesn't handle P2P bridge hotplug events, so it will cause strange behaviour if there are hotplug slots associated with a hot-removed P2P bridge. This patch fixes this issue by: 1) Directly hooking into PCI core to update hotplug slot devices when creating/destroying PCI buses through: pci_{add|remove}_bus() -> acpi_pci_{add|remove}_bus() 2) Getting rid of unused ACPI PCI subdriver-related code It also cleans up unused code in the acpiphp driver. [bhelgaas: keep acpi_pci_add_bus() stub for CONFIG_ACPI=n] Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/hotplug/acpiphp.h | 3 - drivers/pci/hotplug/acpiphp_core.c | 13 +- drivers/pci/hotplug/acpiphp_glue.c | 288 ++++++----------------------- drivers/pci/pci-acpi.c | 3 + include/linux/pci-acpi.h | 11 ++ 5 files changed, 71 insertions(+), 247 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b06ae681d5b7..abd48d309ad0 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -119,7 +119,6 @@ struct acpiphp_slot { */ struct acpiphp_func { struct acpiphp_slot *slot; /* parent */ - struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ struct list_head sibling; struct notifier_block nb; @@ -176,8 +175,6 @@ extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ -extern int acpiphp_glue_init (void); -extern void acpiphp_glue_exit (void); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); extern int acpiphp_enable_slot (struct acpiphp_slot *slot); diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 81adbfa4df1b..ca8127950fcd 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -354,19 +355,9 @@ void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *acpiphp_slot) } -static int __init acpiphp_init(void) +void __init acpiphp_init(void) { info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n", acpiphp_disabled ? ", disabled by user; please report a bug" : ""); - - if (acpi_pci_disabled || acpiphp_disabled) - return 0; - - /* read all the ACPI info from the system */ - /* initialize internal data structure etc. */ - return acpiphp_glue_init(); } - - -module_init(acpiphp_init); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 718464f8fd40..20db4d6564a8 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -157,6 +157,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) int device, function, retval; struct pci_bus *pbus = bridge->pci_bus; struct pci_dev *pdev; + u32 val; if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) return AE_OK; @@ -249,11 +250,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) newfunc->slot = slot; list_add_tail(&newfunc->sibling, &slot->funcs); - pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); - if (pdev) { + if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), + &val, 60*1000)) slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); - pci_dev_put(pdev); - } if (is_dock_device(handle)) { /* we don't want to call this device's _EJ0 @@ -366,148 +365,6 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle } -static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge) -{ - acpi_handle dummy_handle; - struct acpiphp_func *func; - - if (ACPI_SUCCESS(acpi_get_handle(bridge->handle, - "_EJ0", &dummy_handle))) { - bridge->flags |= BRIDGE_HAS_EJ0; - - dbg("found ejectable p2p bridge\n"); - - /* make link between PCI bridge and PCI function */ - func = acpiphp_bridge_handle_to_function(bridge->handle); - if (!func) - return; - bridge->func = func; - func->bridge = bridge; - } -} - - -/* allocate and initialize host bridge data structure */ -static void add_host_bridge(struct acpi_pci_root *root) -{ - struct acpiphp_bridge *bridge; - acpi_handle handle = root->device->handle; - - bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); - if (bridge == NULL) - return; - - bridge->handle = handle; - - bridge->pci_bus = root->bus; - - init_bridge_misc(bridge); -} - - -/* allocate and initialize PCI-to-PCI bridge data structure */ -static void add_p2p_bridge(acpi_handle *handle) -{ - struct acpiphp_bridge *bridge; - - bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); - if (bridge == NULL) { - err("out of memory\n"); - return; - } - - bridge->handle = handle; - config_p2p_bridge_flags(bridge); - - bridge->pci_dev = acpi_get_pci_dev(handle); - bridge->pci_bus = bridge->pci_dev->subordinate; - if (!bridge->pci_bus) { - err("This is not a PCI-to-PCI bridge!\n"); - goto err; - } - - /* - * Grab a ref to the subordinate PCI bus in case the bus is - * removed via PCI core logical hotplug. The ref pins the bus - * (which we access during module unload). - */ - get_device(&bridge->pci_bus->dev); - - init_bridge_misc(bridge); - return; - err: - pci_dev_put(bridge->pci_dev); - kfree(bridge); - return; -} - - -/* callback routine to find P2P bridges */ -static acpi_status -find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - acpi_status status; - struct pci_dev *dev; - - dev = acpi_get_pci_dev(handle); - if (!dev || !dev->subordinate) - goto out; - - /* check if this bridge has ejectable slots */ - if ((detect_ejectable_slots(handle) > 0)) { - dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev)); - add_p2p_bridge(handle); - } - - /* search P2P bridges under this p2p bridge */ - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - find_p2p_bridge, NULL, NULL, NULL); - if (ACPI_FAILURE(status)) - warn("find_p2p_bridge failed (error code = 0x%x)\n", status); - - out: - pci_dev_put(dev); - return AE_OK; -} - - -/* find hot-pluggable slots, and then find P2P bridge */ -static int add_bridge(struct acpi_pci_root *root) -{ - acpi_status status; - unsigned long long tmp; - acpi_handle dummy_handle; - acpi_handle handle = root->device->handle; - - /* if the bridge doesn't have _STA, we assume it is always there */ - status = acpi_get_handle(handle, "_STA", &dummy_handle); - if (ACPI_SUCCESS(status)) { - status = acpi_evaluate_integer(handle, "_STA", NULL, &tmp); - if (ACPI_FAILURE(status)) { - dbg("%s: _STA evaluation failure\n", __func__); - return 0; - } - if ((tmp & ACPI_STA_DEVICE_FUNCTIONING) == 0) - /* don't register this object */ - return 0; - } - - /* check if this bridge has ejectable slots */ - if (detect_ejectable_slots(handle) > 0) { - dbg("found PCI host-bus bridge with hot-pluggable slots\n"); - add_host_bridge(root); - } - - /* search P2P bridges under this host bridge */ - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - find_p2p_bridge, NULL, NULL, NULL); - - if (ACPI_FAILURE(status)) - warn("find_p2p_bridge failed (error code = 0x%x)\n", status); - - return 0; -} - static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; @@ -567,56 +424,12 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) slot = next; } - /* - * Only P2P bridges have a pci_dev - */ - if (bridge->pci_dev) - put_device(&bridge->pci_bus->dev); - + put_device(&bridge->pci_bus->dev); pci_dev_put(bridge->pci_dev); list_del(&bridge->list); kfree(bridge); } -static acpi_status -cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv) -{ - struct acpiphp_bridge *bridge; - - /* cleanup p2p bridges under this P2P bridge - in a depth-first manner */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1, - cleanup_p2p_bridge, NULL, NULL, NULL); - - bridge = acpiphp_handle_to_bridge(handle); - if (bridge) - cleanup_bridge(bridge); - - return AE_OK; -} - -static void remove_bridge(struct acpi_pci_root *root) -{ - struct acpiphp_bridge *bridge; - acpi_handle handle = root->device->handle; - - /* cleanup p2p bridges under this host bridge - in a depth-first manner */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, - (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL); - - /* - * On root bridges with hotplug slots directly underneath (ie, - * no p2p bridge between), we call cleanup_bridge(). - * - * The else clause cleans up root bridges that either had no - * hotplug slots at all, or had a p2p bridge underneath. - */ - bridge = acpiphp_handle_to_bridge(handle); - if (bridge) - cleanup_bridge(bridge); -} - static int power_on_slot(struct acpiphp_slot *slot) { acpi_status status; @@ -798,6 +611,7 @@ static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev) } } } + /** * enable_device - enable, configure a slot * @slot: slot to be enabled @@ -812,7 +626,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) struct acpiphp_func *func; int retval = 0; int num, max, pass; - acpi_status status; if (slot->flags & SLOT_ENABLED) goto err_exit; @@ -867,18 +680,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) slot->flags &= (~SLOT_ENABLED); continue; } - - if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && - dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { - pci_dev_put(dev); - continue; - } - - status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); - if (ACPI_FAILURE(status)) - warn("find_p2p_bridge failed (error code = 0x%x)\n", - status); - pci_dev_put(dev); } @@ -912,16 +713,6 @@ static int disable_device(struct acpiphp_slot *slot) { struct acpiphp_func *func; struct pci_dev *pdev; - struct pci_bus *bus = slot->bridge->pci_bus; - - list_for_each_entry(func, &slot->funcs, sibling) { - if (func->bridge) { - /* cleanup p2p bridges under this P2P bridge */ - cleanup_p2p_bridge(func->bridge->handle, - (u32)1, NULL, NULL); - func->bridge = NULL; - } - } /* * enable_device() enumerates all functions in this device via @@ -940,7 +731,6 @@ static int disable_device(struct acpiphp_slot *slot) slot->flags &= (~SLOT_ENABLED); -err_exit: return 0; } @@ -1287,30 +1077,62 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); } -static struct acpi_pci_driver acpi_pci_hp_driver = { - .add = add_bridge, - .remove = remove_bridge, -}; - -/** - * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures +/* + * Create hotplug slots for the PCI bus. + * It should always return 0 to avoid skipping following notifiers. */ -int __init acpiphp_glue_init(void) +void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) { - acpi_pci_register_driver(&acpi_pci_hp_driver); + acpi_handle dummy_handle; + struct acpiphp_bridge *bridge; - return 0; + if (acpiphp_disabled) + return; + + if (detect_ejectable_slots(handle) <= 0) + return; + + bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL); + if (bridge == NULL) { + err("out of memory\n"); + return; + } + + bridge->handle = handle; + bridge->pci_dev = pci_dev_get(bus->self); + bridge->pci_bus = bus; + + /* + * Grab a ref to the subordinate PCI bus in case the bus is + * removed via PCI core logical hotplug. The ref pins the bus + * (which we access during module unload). + */ + get_device(&bus->dev); + + if (!pci_is_root_bus(bridge->pci_bus) && + ACPI_SUCCESS(acpi_get_handle(bridge->handle, + "_EJ0", &dummy_handle))) { + dbg("found ejectable p2p bridge\n"); + bridge->flags |= BRIDGE_HAS_EJ0; + bridge->func = acpiphp_bridge_handle_to_function(handle); + } + + init_bridge_misc(bridge); } - -/** - * acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures - * - * This function frees all data allocated in acpiphp_glue_init(). - */ -void acpiphp_glue_exit(void) +/* Destroy hotplug slots associated with the PCI bus */ +void acpiphp_remove_slots(struct pci_bus *bus) { - acpi_pci_unregister_driver(&acpi_pci_hp_driver); + struct acpiphp_bridge *bridge, *tmp; + + if (acpiphp_disabled) + return; + + list_for_each_entry_safe(bridge, tmp, &bridge_list, list) + if (bridge->pci_bus == bus) { + cleanup_bridge(bridge); + break; + } } /** diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 98e582a2c909..d927933dcf44 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -297,6 +297,7 @@ void acpi_pci_add_bus(struct pci_bus *bus) return; acpi_pci_slot_enumerate(bus, handle); + acpiphp_enumerate_slots(bus, handle); } void acpi_pci_remove_bus(struct pci_bus *bus) @@ -308,6 +309,7 @@ void acpi_pci_remove_bus(struct pci_bus *bus) if (acpi_pci_disabled) return; + acpiphp_remove_slots(bus); acpi_pci_slot_remove(bus); } @@ -388,6 +390,7 @@ static int __init acpi_pci_init(void) pci_set_platform_pm(&acpi_pci_platform_pm); acpi_pci_slot_init(); + acpiphp_init(); return 0; } diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h index 23cd40abba4f..81b31613eb25 100644 --- a/include/linux/pci-acpi.h +++ b/include/linux/pci-acpi.h @@ -56,6 +56,17 @@ static inline void acpi_pci_slot_enumerate(struct pci_bus *bus, static inline void acpi_pci_slot_remove(struct pci_bus *bus) { } #endif +#ifdef CONFIG_HOTPLUG_PCI_ACPI +void acpiphp_init(void); +void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle); +void acpiphp_remove_slots(struct pci_bus *bus); +#else +static inline void acpiphp_init(void) { } +static inline void acpiphp_enumerate_slots(struct pci_bus *bus, + acpi_handle handle) { } +static inline void acpiphp_remove_slots(struct pci_bus *bus) { } +#endif + #else /* CONFIG_ACPI */ static inline void acpi_pci_add_bus(struct pci_bus *bus) { } static inline void acpi_pci_remove_bus(struct pci_bus *bus) { } From c3139ba212ddc240656f4bcfc7c946418cd83e19 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 15 Apr 2013 10:44:18 -0600 Subject: [PATCH 23/63] PCI: Move cpci_hotplug_init() proto to header file cpci_hotplug_init() and cpci_hotplug_exit() are defined in cpci_hotplug_core.c but had extern declarations in pci_hotplug_core.c. This puts the declarations in a header file included both places so the compiler can help keep everything consistent. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/cpci_hotplug.h | 8 ++++++++ drivers/pci/hotplug/pci_hotplug_core.c | 9 +-------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 9fff878cf026..3ae19f774cb3 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h @@ -99,4 +99,12 @@ extern int cpci_led_off(struct slot * slot); extern int cpci_configure_slot(struct slot *slot); extern int cpci_unconfigure_slot(struct slot *slot); +#ifdef CONFIG_HOTPLUG_PCI_CPCI +int cpci_hotplug_init(int debug); +void cpci_hotplug_exit(void); +#else +static inline int cpci_hotplug_init(int debug) { return 0; } +static inline void cpci_hotplug_exit(void) { } +#endif + #endif /* _CPCI_HOTPLUG_H */ diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 202f4a969eb5..6a25f4d8ba32 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -41,6 +41,7 @@ #include #include #include "../pci.h" +#include "cpci_hotplug.h" #define MY_NAME "pci_hotplug" @@ -63,14 +64,6 @@ static bool debug; static LIST_HEAD(pci_hotplug_slot_list); static DEFINE_MUTEX(pci_hp_mutex); -#ifdef CONFIG_HOTPLUG_PCI_CPCI -extern int cpci_hotplug_init(int debug); -extern void cpci_hotplug_exit(void); -#else -static inline int cpci_hotplug_init(int debug) { return 0; } -static inline void cpci_hotplug_exit(void) { } -#endif - /* Weee, fun with macros... */ #define GET_STATUS(name,type) \ static int get_##name (struct hotplug_slot *slot, type *value) \ From b638d7e7b849ad402aaecfe7edb599687b5eb3a8 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 12 Apr 2013 11:18:01 -0600 Subject: [PATCH 24/63] PCI: Remove unused variables This fixes "set but not used" warnings found via "make W=1". Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pci_hotplug_core.c | 2 -- drivers/pci/pcie/portdrv_pci.c | 17 +++++------------ drivers/pci/setup-res.c | 2 -- 3 files changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 6a25f4d8ba32..9d4c199a64be 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -520,10 +520,8 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug, struct hotplug_slot_info *info) { - struct pci_slot *slot; if (!hotplug || !info) return -ENODEV; - slot = hotplug->pci_slot; memcpy(hotplug->info, info, sizeof(struct hotplug_slot_info)); diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 08c243ab034e..0efba0539cc9 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -272,11 +272,9 @@ static pci_ers_result_t pcie_portdrv_error_detected(struct pci_dev *dev, enum pci_channel_state error) { struct aer_broadcast_data data = {error, PCI_ERS_RESULT_CAN_RECOVER}; - int ret; - - /* can not fail */ - ret = device_for_each_child(&dev->dev, &data, error_detected_iter); + /* get true return value from &data */ + device_for_each_child(&dev->dev, &data, error_detected_iter); return data.result; } @@ -308,10 +306,9 @@ static int mmio_enabled_iter(struct device *device, void *data) static pci_ers_result_t pcie_portdrv_mmio_enabled(struct pci_dev *dev) { pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; - int retval; /* get true return value from &status */ - retval = device_for_each_child(&dev->dev, &status, mmio_enabled_iter); + device_for_each_child(&dev->dev, &status, mmio_enabled_iter); return status; } @@ -343,7 +340,6 @@ static int slot_reset_iter(struct device *device, void *data) static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) { pci_ers_result_t status = PCI_ERS_RESULT_RECOVERED; - int retval; /* If fatal, restore cfg space for possible link reset at upstream */ if (dev->error_state == pci_channel_io_frozen) { @@ -354,8 +350,7 @@ static pci_ers_result_t pcie_portdrv_slot_reset(struct pci_dev *dev) } /* get true return value from &status */ - retval = device_for_each_child(&dev->dev, &status, slot_reset_iter); - + device_for_each_child(&dev->dev, &status, slot_reset_iter); return status; } @@ -381,9 +376,7 @@ static int resume_iter(struct device *device, void *data) static void pcie_portdrv_err_resume(struct pci_dev *dev) { - int retval; - /* nothing to do with error value, if it ever happens */ - retval = device_for_each_child(&dev->dev, NULL, resume_iter); + device_for_each_child(&dev->dev, NULL, resume_iter); } /* diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index 81b88bda7930..07f2eddc09ce 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -261,7 +261,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno) { struct resource *res = dev->resource + resno; resource_size_t align, size; - struct pci_bus *bus; int ret; align = pci_resource_alignment(dev, res); @@ -271,7 +270,6 @@ int pci_assign_resource(struct pci_dev *dev, int resno) return -EINVAL; } - bus = dev->bus; size = resource_size(res); ret = _pci_assign_resource(dev, resno, size, align); From 769ba7212f2059ca9fe0c73371e3d415c8c1c529 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 12 Apr 2013 13:58:17 +0000 Subject: [PATCH 25/63] PCI/PM: Fix fallback to PCI_D0 in pci_platform_power_transition() Commit b51306c (PCI: Set device power state to PCI_D0 for device without native PM support) modified pci_platform_power_transition() by adding code causing dev->current_state for devices that don't support native PCI PM but are power-manageable by the platform to be changed to PCI_D0 regardless of the value returned by the preceding platform_pci_set_power_state(). In particular, that also is done if the platform_pci_set_power_state() has been successful, which causes the correct power state of the device set by pci_update_current_state() in that case to be overwritten by PCI_D0. Fix that mistake by making the fallback to PCI_D0 only happen if the platform_pci_set_power_state() has returned an error. [bhelgaas: folded in Yinghai's simplification, added URL & stable info] Reference: http://lkml.kernel.org/r/27806FC4E5928A408B78E88BBC67A2306F466BBA@ORSMSX101.amr.corp.intel.com Reported-by: Chris J. Benenati Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas Acked-by: Yinghai Lu Cc: # v3.2+ --- drivers/pci/pci.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b099e0025d2b..fc9bd81e8e3b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -646,15 +646,11 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) error = platform_pci_set_power_state(dev, state); if (!error) pci_update_current_state(dev, state); - /* Fall back to PCI_D0 if native PM is not supported */ - if (!dev->pm_cap) - dev->current_state = PCI_D0; - } else { + } else error = -ENODEV; - /* Fall back to PCI_D0 if native PM is not supported */ - if (!dev->pm_cap) - dev->current_state = PCI_D0; - } + + if (error && !dev->pm_cap) /* Fall back to PCI_D0 */ + dev->current_state = PCI_D0; return error; } From ffaddbe8f925a4f41eecb31e7fe69a9bdb6e2e59 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 10 Apr 2013 10:32:51 +0000 Subject: [PATCH 26/63] PCI/PM: Make pci_pme_active() ignore devices without PME support Make pci_pme_active() ignore devices without PME support, so that it doesn't print the "PME enabled" or "PME disabled" debug messages for devices that don't support PME. So that pci_pme_active() doesn't have to check pm_cap in addition to pme_support, make pci_pm_init() clear pme_support upfront to make sure that it will be 0 for pm_cap equal to 0. Signed-off-by: Rafael J. Wysocki Signed-off-by: Bjorn Helgaas --- drivers/pci/pci.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index fc9bd81e8e3b..a5e0e5f4953c 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1571,7 +1571,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable) { u16 pmcsr; - if (!dev->pm_cap) + if (!dev->pme_support) return; pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); @@ -1920,6 +1920,7 @@ void pci_pm_init(struct pci_dev *dev) dev->wakeup_prepared = false; dev->pm_cap = 0; + dev->pme_support = 0; /* find PCI PM capability in list */ pm = pci_find_capability(dev, PCI_CAP_ID_PM); @@ -1971,8 +1972,6 @@ void pci_pm_init(struct pci_dev *dev) device_set_wakeup_capable(&dev->dev, true); /* Disable the PME# generation functionality */ pci_pme_active(dev, false); - } else { - dev->pme_support = 0; } } From 8e7ee6f5dfb56a32da760d990be908ed35b1c5bf Mon Sep 17 00:00:00 2001 From: Xiangliang Yu Date: Wed, 20 Mar 2013 22:34:56 -0600 Subject: [PATCH 27/63] PCI: Define macro for Marvell vendor ID Define PCI_VENDOR_ID_MARVELL_EXT macro for 0x1b4b vendor ID Signed-off-by: Xiangliang Yu Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas --- include/linux/pci_ids.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f11c1c2609d5..a80f9e6ce9e5 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1604,6 +1604,7 @@ #define PCI_SUBDEVICE_ID_KEYSPAN_SX2 0x5334 #define PCI_VENDOR_ID_MARVELL 0x11ab +#define PCI_VENDOR_ID_MARVELL_EXT 0x1b4b #define PCI_DEVICE_ID_MARVELL_GT64111 0x4146 #define PCI_DEVICE_ID_MARVELL_GT64260 0x6430 #define PCI_DEVICE_ID_MARVELL_MV64360 0x6460 From 69fd3157363935b1e052bd76b8f8ec65e494306e Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 8 Apr 2013 11:32:49 -0600 Subject: [PATCH 28/63] ahci: Use PCI_VENDOR_ID_MARVELL_EXT for 0x1b4b With the 0x1b4b vendor ID #define in place, convert hard-coded ID values. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas Acked-by: Jeff Garzik --- drivers/ata/ahci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a99112cfd8b1..616952facd6e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -413,17 +413,17 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* Marvell */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ { PCI_VDEVICE(MARVELL, 0x6121), board_ahci_mv }, /* 6121 */ - { PCI_DEVICE(0x1b4b, 0x9123), + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9123), .class = PCI_CLASS_STORAGE_SATA_AHCI, .class_mask = 0xffffff, .driver_data = board_ahci_yes_fbs }, /* 88se9128 */ - { PCI_DEVICE(0x1b4b, 0x9125), + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9125), .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ - { PCI_DEVICE(0x1b4b, 0x917a), + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ - { PCI_DEVICE(0x1b4b, 0x9192), + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x9192), .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ - { PCI_DEVICE(0x1b4b, 0x91a3), + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, 0x91a3), .driver_data = board_ahci_yes_fbs }, /* Promise */ From 412e704fbca3b259cafb3e98f6798efde968eb29 Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 8 Apr 2013 11:35:44 -0600 Subject: [PATCH 29/63] [SCSI] mvsas: Use PCI_VENDOR_ID_MARVELL_EXT for 0x1b4b With the 0x1b4b vendor ID #define in place, convert hard-coded ID values. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas Acked-by: James Bottomley --- drivers/scsi/mvsas/mv_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index ce90d0546cdd..74550922ad55 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c @@ -703,7 +703,7 @@ static struct pci_device_id mvs_pci_table[] = { { PCI_VDEVICE(TTI, 0x2744), chip_9480 }, { PCI_VDEVICE(TTI, 0x2760), chip_9480 }, { - .vendor = 0x1b4b, + .vendor = PCI_VENDOR_ID_MARVELL_EXT, .device = 0x9480, .subvendor = PCI_ANY_ID, .subdevice = 0x9480, @@ -712,7 +712,7 @@ static struct pci_device_id mvs_pci_table[] = { .driver_data = chip_9480, }, { - .vendor = 0x1b4b, + .vendor = PCI_VENDOR_ID_MARVELL_EXT, .device = 0x9445, .subvendor = PCI_ANY_ID, .subdevice = 0x9480, @@ -721,7 +721,7 @@ static struct pci_device_id mvs_pci_table[] = { .driver_data = chip_9445, }, { - .vendor = 0x1b4b, + .vendor = PCI_VENDOR_ID_MARVELL_EXT, .device = 0x9485, .subvendor = PCI_ANY_ID, .subdevice = 0x9480, From c85bcadc78a99763961b621a5ce097d3134f1aca Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Mon, 8 Apr 2013 11:37:55 -0600 Subject: [PATCH 30/63] [SCSI] mvumi: Use PCI_VENDOR_ID_MARVELL_EXT for 0x1b4b With the 0x1b4b vendor ID #define in place, convert hard-coded ID values. Signed-off-by: Myron Stowe Signed-off-by: Bjorn Helgaas Acked-by: James Bottomley --- drivers/scsi/mvumi.c | 4 ++-- drivers/scsi/mvumi.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c index 4594ccaaf49b..c3601b57a80c 100644 --- a/drivers/scsi/mvumi.c +++ b/drivers/scsi/mvumi.c @@ -49,8 +49,8 @@ MODULE_AUTHOR("jyli@marvell.com"); MODULE_DESCRIPTION("Marvell UMI Driver"); static DEFINE_PCI_DEVICE_TABLE(mvumi_pci_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9143) }, - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_2, PCI_DEVICE_ID_MARVELL_MV9580) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9143) }, + { PCI_DEVICE(PCI_VENDOR_ID_MARVELL_EXT, PCI_DEVICE_ID_MARVELL_MV9580) }, { 0 } }; diff --git a/drivers/scsi/mvumi.h b/drivers/scsi/mvumi.h index e360135fd1bd..41f168702ac7 100644 --- a/drivers/scsi/mvumi.h +++ b/drivers/scsi/mvumi.h @@ -32,7 +32,6 @@ #define VER_BUILD 1500 #define MV_DRIVER_NAME "mvumi" -#define PCI_VENDOR_ID_MARVELL_2 0x1b4b #define PCI_DEVICE_ID_MARVELL_MV9143 0x9143 #define PCI_DEVICE_ID_MARVELL_MV9580 0x9580 From 05795726e82372d3fe46210fcb3320f1fa49aea7 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 11 Apr 2013 17:36:50 -0600 Subject: [PATCH 31/63] PCI: Remove unnecessary dependencies between PME and ACPI PCIe PME doesn't depend on ACPI, so remove the #includes and Kconfig dependency. Based-on-patch-by: Andrew Murray Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- drivers/pci/pcie/Kconfig | 2 +- drivers/pci/pcie/pme.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index fde4a32a0295..569f82fc9e22 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -82,4 +82,4 @@ endchoice config PCIE_PME def_bool y - depends on PCIEPORTBUS && PM_RUNTIME && ACPI + depends on PCIEPORTBUS && PM_RUNTIME diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c index 9ca0dc9ffd84..795db1f9d50c 100644 --- a/drivers/pci/pcie/pme.c +++ b/drivers/pci/pcie/pme.c @@ -19,8 +19,6 @@ #include #include #include -#include -#include #include #include "../pci.h" From 545d7b78e0bbe686056cdd6cd431ca1946641b31 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Tue, 9 Apr 2013 16:46:12 -0600 Subject: [PATCH 32/63] PCI: Use PCI_EXP_SLTCAP_PSN mask when extracting slot number Use PCI_EXP_SLTCAP_PSN mask to make it easier to find where the Physical Slot Number is used. The Physical Slot Number is bits 31:19 of the Slot Capabilities Register, and slot_cap is a u32, so the mask is technically unnecessary, but it's helpful for human readers. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pciehp_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c index 24d709b7388c..ead7c534095e 100644 --- a/drivers/pci/hotplug/pciehp_acpi.c +++ b/drivers/pci/hotplug/pciehp_acpi.c @@ -90,7 +90,7 @@ static int __init dummy_probe(struct pcie_device *dev) slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; - slot->number = slot_cap >> 19; + slot->number = (slot_cap & PCI_EXP_SLTCAP_PSN) >> 19; list_for_each_entry(tmp, &dummy_slots, list) { if (tmp->number == slot->number) dup_slot_id++; From 64b001758e778b2b1aad08aa1f6c5896da5f5773 Mon Sep 17 00:00:00 2001 From: Libin Date: Mon, 15 Apr 2013 02:48:54 +0000 Subject: [PATCH 33/63] PCI: Use vma_pages() to replace (vm_end - vm_start) >> PAGE_SHIFT (*->vm_end - *->vm_start) >> PAGE_SHIFT operation is implemented as an inline funcion vma_pages() in linux/mm.h, so use it. Signed-off-by: Libin Signed-off-by: Bjorn Helgaas --- drivers/pci/pci-sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 9c6e9bb674ec..5b4a9d9cd200 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -897,7 +897,7 @@ int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma, if (pci_resource_len(pdev, resno) == 0) return 0; - nr = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; + nr = vma_pages(vma); start = vma->vm_pgoff; size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1; pci_start = (mmap_api == PCI_MMAP_PROCFS) ? From 65195c76a7f855c879a168937f90a27032662328 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 12 Apr 2013 12:44:15 +0000 Subject: [PATCH 34/63] PCI: Clean up quirk_io_region Before every call of quirk_io_region(), pci_read_config_word() is called. We can fold that call into quirk_io_region() to make code more readable. [bhelgaas: changelog, fill bus_region directly rather than copying from res] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/quirks.c | 130 +++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 85 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4273a2d7132c..7d68aeebf56b 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -324,29 +324,30 @@ static void quirk_cs5536_vsa(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, quirk_cs5536_vsa); -static void quirk_io_region(struct pci_dev *dev, unsigned region, - unsigned size, int nr, const char *name) +static void quirk_io_region(struct pci_dev *dev, int port, + unsigned size, int nr, const char *name) { - region &= ~(size-1); - if (region) { - struct pci_bus_region bus_region; - struct resource *res = dev->resource + nr; + u16 region; + struct pci_bus_region bus_region; + struct resource *res = dev->resource + nr; - res->name = pci_name(dev); - res->start = region; - res->end = region + size - 1; - res->flags = IORESOURCE_IO; + pci_read_config_word(dev, port, ®ion); + region &= ~(size - 1); - /* Convert from PCI bus to resource space. */ - bus_region.start = res->start; - bus_region.end = res->end; - pcibios_bus_to_resource(dev, res, &bus_region); + if (!region) + return; - if (pci_claim_resource(dev, nr) == 0) - dev_info(&dev->dev, "quirk: %pR claimed by %s\n", - res, name); - } -} + res->name = pci_name(dev); + res->flags = IORESOURCE_IO; + + /* 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); + + if (!pci_claim_resource(dev, nr)) + dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name); +} /* * ATI Northbridge setups MCE the processor if you even @@ -374,12 +375,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_ */ static void quirk_ali7101_acpi(struct pci_dev *dev) { - u16 region; - - pci_read_config_word(dev, 0xE0, ®ion); - quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI"); - pci_read_config_word(dev, 0xE2, ®ion); - quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB"); + quirk_io_region(dev, 0xE0, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI"); + quirk_io_region(dev, 0xE2, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi); @@ -442,12 +439,10 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int */ static void quirk_piix4_acpi(struct pci_dev *dev) { - u32 region, res_a; + u32 res_a; - pci_read_config_dword(dev, 0x40, ®ion); - quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); - pci_read_config_dword(dev, 0x90, ®ion); - quirk_io_region(dev, region, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); + quirk_io_region(dev, 0x40, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI"); + quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+1, "PIIX4 SMB"); /* Device resource A has enables for some of the other ones */ pci_read_config_dword(dev, 0x5c, &res_a); @@ -491,7 +486,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, qui */ static void quirk_ich4_lpc_acpi(struct pci_dev *dev) { - u32 region; u8 enable; /* @@ -503,22 +497,14 @@ static void quirk_ich4_lpc_acpi(struct pci_dev *dev) */ pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); - if (enable & ICH4_ACPI_EN) { - pci_read_config_dword(dev, ICH_PMBASE, ®ion); - region &= PCI_BASE_ADDRESS_IO_MASK; - if (region >= PCIBIOS_MIN_IO) - quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, - "ICH4 ACPI/GPIO/TCO"); - } + if (enable & ICH4_ACPI_EN) + quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES, + "ICH4 ACPI/GPIO/TCO"); pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable); - if (enable & ICH4_GPIO_EN) { - pci_read_config_dword(dev, ICH4_GPIOBASE, ®ion); - region &= PCI_BASE_ADDRESS_IO_MASK; - if (region >= PCIBIOS_MIN_IO) - quirk_io_region(dev, region, 64, - PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO"); - } + if (enable & ICH4_GPIO_EN) + quirk_io_region(dev, ICH4_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1, + "ICH4 GPIO"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, quirk_ich4_lpc_acpi); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, quirk_ich4_lpc_acpi); @@ -533,26 +519,17 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, qui static void ich6_lpc_acpi_gpio(struct pci_dev *dev) { - u32 region; u8 enable; pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable); - if (enable & ICH6_ACPI_EN) { - pci_read_config_dword(dev, ICH_PMBASE, ®ion); - region &= PCI_BASE_ADDRESS_IO_MASK; - if (region >= PCIBIOS_MIN_IO) - quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, - "ICH6 ACPI/GPIO/TCO"); - } + if (enable & ICH6_ACPI_EN) + quirk_io_region(dev, ICH_PMBASE, 128, PCI_BRIDGE_RESOURCES, + "ICH6 ACPI/GPIO/TCO"); pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable); - if (enable & ICH6_GPIO_EN) { - pci_read_config_dword(dev, ICH6_GPIOBASE, ®ion); - region &= PCI_BASE_ADDRESS_IO_MASK; - if (region >= PCIBIOS_MIN_IO) - quirk_io_region(dev, region, 64, - PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO"); - } + if (enable & ICH6_GPIO_EN) + quirk_io_region(dev, ICH6_GPIOBASE, 64, PCI_BRIDGE_RESOURCES+1, + "ICH6 GPIO"); } static void ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize) @@ -650,13 +627,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_1, qui */ static void quirk_vt82c586_acpi(struct pci_dev *dev) { - u32 region; - - if (dev->revision & 0x10) { - pci_read_config_dword(dev, 0x48, ®ion); - region &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI"); - } + if (dev->revision & 0x10) + quirk_io_region(dev, 0x48, 256, PCI_BRIDGE_RESOURCES, + "vt82c586 ACPI"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi); @@ -668,18 +641,12 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt */ static void quirk_vt82c686_acpi(struct pci_dev *dev) { - u16 hm; - u32 smb; - quirk_vt82c586_acpi(dev); - pci_read_config_word(dev, 0x70, &hm); - hm &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon"); + quirk_io_region(dev, 0x70, 128, PCI_BRIDGE_RESOURCES+1, + "vt82c686 HW-mon"); - pci_read_config_dword(dev, 0x90, &smb); - smb &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB"); + quirk_io_region(dev, 0x90, 16, PCI_BRIDGE_RESOURCES+2, "vt82c686 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi); @@ -690,15 +657,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt */ static void quirk_vt8235_acpi(struct pci_dev *dev) { - u16 pm, smb; - - pci_read_config_word(dev, 0x88, &pm); - pm &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, pm, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM"); - - pci_read_config_word(dev, 0xd0, &smb); - smb &= PCI_BASE_ADDRESS_IO_MASK; - quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 1, "vt8235 SMB"); + quirk_io_region(dev, 0x88, 128, PCI_BRIDGE_RESOURCES, "vt8235 PM"); + quirk_io_region(dev, 0xd0, 16, PCI_BRIDGE_RESOURCES+1, "vt8235 SMB"); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, quirk_vt8235_acpi); From 4cf9f24db3954ac5802de24c826b7ebed27760c4 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 15 Apr 2013 14:33:42 -0600 Subject: [PATCH 35/63] EISA: Use dev_printk() when possible Use dev_printk() when possible to make messages more useful. Signed-off-by: Bjorn Helgaas --- drivers/eisa/eisa-bus.c | 59 ++++++++++++++++++----------------------- drivers/eisa/pci_eisa.c | 5 ++-- 2 files changed, 28 insertions(+), 36 deletions(-) diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 806c77bfd434..0b06df44ed54 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -314,22 +314,22 @@ static int __init eisa_probe(struct eisa_root_device *root) { int i, c; struct eisa_device *edev; + char *enabled_str; - printk(KERN_INFO "EISA: Probing bus %d at %s\n", - root->bus_nr, dev_name(root->dev)); + dev_info(root->dev, "Probing EISA bus %d\n", root->bus_nr); /* First try to get hold of slot 0. If there is no device * here, simply fail, unless root->force_probe is set. */ edev = kzalloc(sizeof(*edev), GFP_KERNEL); if (!edev) { - printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n"); + dev_err(root->dev, "EISA: Couldn't allocate mainboard slot\n"); return -ENOMEM; } if (eisa_request_resources(root, edev, 0)) { - printk(KERN_WARNING \ - "EISA: Cannot allocate resource for mainboard\n"); + dev_warn(root->dev, + "EISA: Cannot allocate resource for mainboard\n"); kfree(edev); if (!root->force_probe) return -EBUSY; @@ -344,11 +344,11 @@ static int __init eisa_probe(struct eisa_root_device *root) goto force_probe; } - printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig); + dev_info(&edev->dev, "EISA: Mainboard %s detected\n", edev->id.sig); if (eisa_register_device(edev)) { - printk(KERN_ERR "EISA: Failed to register %s\n", - edev->id.sig); + dev_err(&edev->dev, "EISA: Failed to register %s\n", + edev->id.sig); eisa_release_resources(edev); kfree(edev); } @@ -358,14 +358,15 @@ static int __init eisa_probe(struct eisa_root_device *root) for (c = 0, i = 1; i <= root->slots; i++) { edev = kzalloc(sizeof(*edev), GFP_KERNEL); if (!edev) { - printk(KERN_ERR "EISA: Out of memory for slot %d\n", i); + dev_err(root->dev, "EISA: Out of memory for slot %d\n", + i); continue; } if (eisa_request_resources(root, edev, i)) { - printk(KERN_WARNING \ - "Cannot allocate resource for EISA slot %d\n", - i); + dev_warn(root->dev, + "Cannot allocate resource for EISA slot %d\n", + i); kfree(edev); continue; } @@ -375,38 +376,30 @@ static int __init eisa_probe(struct eisa_root_device *root) kfree(edev); continue; } - - printk(KERN_INFO "EISA: slot %d : %s detected", - i, edev->id.sig); - - switch (edev->state) { - case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED: - printk(" (forced enabled)"); - break; - case EISA_CONFIG_FORCED: - printk(" (forced disabled)"); - break; + if (edev->state == (EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED)) + enabled_str = " (forced enabled)"; + else if (edev->state == EISA_CONFIG_FORCED) + enabled_str = " (forced disabled)"; + else if (edev->state == 0) + enabled_str = " (disabled)"; + else + enabled_str = ""; - case 0: - printk(" (disabled)"); - break; - } - - printk (".\n"); + dev_info(&edev->dev, "EISA: slot %d: %s detected%s\n", i, + edev->id.sig, enabled_str); c++; if (eisa_register_device(edev)) { - printk(KERN_ERR "EISA: Failed to register %s\n", - edev->id.sig); + dev_err(&edev->dev, "EISA: Failed to register %s\n", + edev->id.sig); eisa_release_resources(edev); kfree(edev); } } - printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s"); - + dev_info(root->dev, "EISA: Detected %d card%s\n", c, c == 1 ? "" : "s"); return 0; } diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c index cdae207028a7..0d42ea791060 100644 --- a/drivers/eisa/pci_eisa.c +++ b/drivers/eisa/pci_eisa.c @@ -25,8 +25,7 @@ static int __init pci_eisa_init(struct pci_dev *pdev, int rc; if ((rc = pci_enable_device (pdev))) { - printk (KERN_ERR "pci_eisa : Could not enable device %s\n", - pci_name(pdev)); + dev_err(&pdev->dev, "Could not enable device\n"); return rc; } @@ -38,7 +37,7 @@ static int __init pci_eisa_init(struct pci_dev *pdev, dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root); if (eisa_root_register (&pci_eisa_root)) { - printk (KERN_ERR "pci_eisa : Could not register EISA root\n"); + dev_err(&pdev->dev, "Could not register EISA root\n"); return -1; } From 76668257b26957ce2ca815da9e7d7fc740164123 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 15 Apr 2013 14:33:56 -0600 Subject: [PATCH 36/63] EISA: Mark vendor ID resource as I/O port space Previously we marked this as merely IORESOURCE_BUSY without indicating the type. Setting the type makes %pR on the resource work better. Signed-off-by: Bjorn Helgaas --- drivers/eisa/eisa-bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index 0b06df44ed54..bf30dcb77bcb 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -285,7 +285,7 @@ static int __init eisa_request_resources(struct eisa_root_device *root, edev->res[i].start = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET; edev->res[i].end = edev->res[i].start + 3; - edev->res[i].flags = IORESOURCE_BUSY; + edev->res[i].flags = IORESOURCE_IO | IORESOURCE_BUSY; } if (request_resource(root->res, &edev->res[i])) From 26abfeed4341872364386c6a52b9acef8c81a81a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 15 Apr 2013 14:34:02 -0600 Subject: [PATCH 37/63] EISA: Initialize device before its resources Move eisa_init_device() before eisa_request_resources() so the device name is set before we set up its resources. That way we can print better messages. Previously edev->res[i].name was set to NULL in eisa_request_resources(), then filled in by eisa_init_device(). Now it is filled in by eisa_init_device() first, and we don't want to clear it out later in eisa_request_resources(). Signed-off-by: Bjorn Helgaas --- drivers/eisa/eisa-bus.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index bf30dcb77bcb..d0c50b477d0b 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -275,13 +275,11 @@ static int __init eisa_request_resources(struct eisa_root_device *root, } if (slot) { - edev->res[i].name = NULL; edev->res[i].start = SLOT_ADDRESS(root, slot) + (i * 0x400); edev->res[i].end = edev->res[i].start + 0xff; edev->res[i].flags = IORESOURCE_IO; } else { - edev->res[i].name = NULL; edev->res[i].start = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET; edev->res[i].end = edev->res[i].start + 3; @@ -327,6 +325,13 @@ static int __init eisa_probe(struct eisa_root_device *root) return -ENOMEM; } + if (eisa_init_device(root, edev, 0)) { + kfree(edev); + if (!root->force_probe) + return -ENODEV; + goto force_probe; + } + if (eisa_request_resources(root, edev, 0)) { dev_warn(root->dev, "EISA: Cannot allocate resource for mainboard\n"); @@ -336,14 +341,6 @@ static int __init eisa_probe(struct eisa_root_device *root) goto force_probe; } - if (eisa_init_device(root, edev, 0)) { - eisa_release_resources(edev); - kfree(edev); - if (!root->force_probe) - return -ENODEV; - goto force_probe; - } - dev_info(&edev->dev, "EISA: Mainboard %s detected\n", edev->id.sig); if (eisa_register_device(edev)) { @@ -363,16 +360,15 @@ static int __init eisa_probe(struct eisa_root_device *root) continue; } - if (eisa_request_resources(root, edev, i)) { - dev_warn(root->dev, - "Cannot allocate resource for EISA slot %d\n", - i); + if (eisa_init_device(root, edev, i)) { kfree(edev); continue; } - if (eisa_init_device(root, edev, i)) { - eisa_release_resources(edev); + if (eisa_request_resources(root, edev, i)) { + dev_warn(root->dev, + "Cannot allocate resource for EISA slot %d\n", + i); kfree(edev); continue; } From a2080d0c561c546d73cb8b296d4b7ca414e6860b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 15 Apr 2013 14:34:07 -0600 Subject: [PATCH 38/63] EISA: Log device resources in dmesg Note the resources consumed by EISA devices in dmesg, similar to what we already do for PCI and PNP devices. Signed-off-by: Bjorn Helgaas --- drivers/eisa/eisa-bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index d0c50b477d0b..272a3ec35957 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -286,6 +286,7 @@ static int __init eisa_request_resources(struct eisa_root_device *root, edev->res[i].flags = IORESOURCE_IO | IORESOURCE_BUSY; } + dev_printk(KERN_DEBUG, &edev->dev, "%pR\n", &edev->res[i]); if (request_resource(root->res, &edev->res[i])) goto failed; } From ad41dd9dd0c8ca1876f30b62c5c79625ffe83174 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 12 Apr 2013 05:44:27 +0000 Subject: [PATCH 39/63] PCI: acpiphp: Use normal list to simplify implementation Use normal list for struct acpiphp_slot to simplify implementation. Signed-off-by: Yijing Wang Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/hotplug/acpiphp.h | 4 ++-- drivers/pci/hotplug/acpiphp_glue.c | 23 ++++++++++------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index abd48d309ad0..4ff716b6a6b3 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -73,8 +73,8 @@ static inline const char *slot_name(struct slot *slot) */ struct acpiphp_bridge { struct list_head list; + struct list_head slots; acpi_handle handle; - struct acpiphp_slot *slots; /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ struct acpiphp_func *func; @@ -97,7 +97,7 @@ struct acpiphp_bridge { * PCI slot information for each *physical* PCI slot */ struct acpiphp_slot { - struct acpiphp_slot *next; + struct list_head node; struct acpiphp_bridge *bridge; /* parent */ struct list_head funcs; /* one slot may have different objects (i.e. for each function) */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 20db4d6564a8..453a749d9595 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -154,7 +154,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) acpi_handle tmp; acpi_status status = AE_OK; unsigned long long adr, sun; - int device, function, retval; + int device, function, retval, found = 0; struct pci_bus *pbus = bridge->pci_bus; struct pci_dev *pdev; u32 val; @@ -208,14 +208,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } /* search for objects that share the same slot */ - for (slot = bridge->slots; slot; slot = slot->next) + list_for_each_entry(slot, &bridge->slots, node) if (slot->device == device) { if (slot->sun != sun) warn("sibling found, but _SUN doesn't match!\n"); + found = 1; break; } - if (!slot) { + if (!found) { slot = kzalloc(sizeof(struct acpiphp_slot), GFP_KERNEL); if (!slot) { kfree(newfunc); @@ -228,9 +229,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) INIT_LIST_HEAD(&slot->funcs); mutex_init(&slot->crit_sect); - slot->next = bridge->slots; - bridge->slots = slot; - + list_add_tail(&slot->node, &bridge->slots); bridge->nr_slots++; dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", @@ -289,7 +288,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) err_exit: bridge->nr_slots--; - bridge->slots = slot->next; + list_del(&slot->node); kfree(slot); kfree(newfunc); @@ -353,7 +352,7 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle struct acpiphp_func *func; list_for_each_entry(bridge, &bridge_list, list) { - for (slot = bridge->slots; slot; slot = slot->next) { + list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(func, &slot->funcs, sibling) { if (func->handle == handle) return func; @@ -400,9 +399,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) err("failed to install interrupt notify handler\n"); } - slot = bridge->slots; - while (slot) { - next = slot->next; + list_for_each_entry_safe(slot, next, &bridge->slots, node) { list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { if (is_dock_device(func->handle)) { unregister_hotplug_dock_device(func->handle); @@ -421,7 +418,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) acpiphp_unregister_hotplug_slot(slot); list_del(&slot->funcs); kfree(slot); - slot = next; } put_device(&bridge->pci_bus->dev); @@ -820,7 +816,7 @@ static int acpiphp_check_bridge(struct acpiphp_bridge *bridge) enabled = disabled = 0; - for (slot = bridge->slots; slot; slot = slot->next) { + list_for_each_entry(slot, &bridge->slots, node) { unsigned int status = get_slot_status(slot); if (slot->flags & SLOT_ENABLED) { if (status == ACPI_STA_ALL) @@ -1098,6 +1094,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) return; } + INIT_LIST_HEAD(&bridge->slots); bridge->handle = handle; bridge->pci_dev = pci_dev_get(bus->self); bridge->pci_bus = bus; From 3d54a3160fb6ba877324ffffa5d301dec8038fd9 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Fri, 12 Apr 2013 05:44:28 +0000 Subject: [PATCH 40/63] PCI: acpiphp: Protect acpiphp data structures from concurrent updates Now acpiphp_enumerate_slots() and acpiphp_remove_slots() may be invoked concurrently by the PCI core, so add a bridge_mutex and reference count mechanism to protect acpiphp bridge/slot/function data structures. To avoid deadlock, handle_hotplug_event_bridge() will requeue the hotplug event onto the kacpi_hotplug_wq by calling alloc_acpi_hp_work(). But the workaround has introduced a minor race window because the 'bridge' passed to _handle_hotplug_event_bridge() may have already been destroyed when _handle_hotplug_event_bridge() is actually executed by the kacpi_hotplug_wq. So hold a reference count on the passed 'bridge'. Fix the same issue for handle_hotplug_event_func() too. Signed-off-by: Jiang Liu Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/pci/hotplug/acpiphp.h | 1 + drivers/pci/hotplug/acpiphp_glue.c | 95 ++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 18 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 4ff716b6a6b3..6a319f42b30c 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -74,6 +74,7 @@ static inline const char *slot_name(struct slot *slot) struct acpiphp_bridge { struct list_head list; struct list_head slots; + struct kref ref; acpi_handle handle; /* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */ diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 453a749d9595..96fed19c6d90 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -54,6 +54,7 @@ #include "acpiphp.h" static LIST_HEAD(bridge_list); +static DEFINE_MUTEX(bridge_mutex); #define MY_NAME "acpiphp_glue" @@ -61,6 +62,7 @@ static void handle_hotplug_event_bridge (acpi_handle, u32, void *); static void acpiphp_sanitize_bus(struct pci_bus *bus); static void acpiphp_set_hpp_values(struct pci_bus *bus); static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context); +static void free_bridge(struct kref *kref); /* callback routine to check for the existence of a pci dock device */ static acpi_status @@ -76,6 +78,39 @@ is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv) } } +static inline void get_bridge(struct acpiphp_bridge *bridge) +{ + kref_get(&bridge->ref); +} + +static inline void put_bridge(struct acpiphp_bridge *bridge) +{ + kref_put(&bridge->ref, free_bridge); +} + +static void free_bridge(struct kref *kref) +{ + struct acpiphp_bridge *bridge; + struct acpiphp_slot *slot, *next; + struct acpiphp_func *func, *tmp; + + bridge = container_of(kref, struct acpiphp_bridge, ref); + + list_for_each_entry_safe(slot, next, &bridge->slots, node) { + list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { + kfree(func); + } + kfree(slot); + } + + /* Release reference acquired by acpiphp_bridge_handle_to_function() */ + if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) + put_bridge(bridge->func->slot->bridge); + put_device(&bridge->pci_bus->dev); + pci_dev_put(bridge->pci_dev); + kfree(bridge); +} + /* * the _DCK method can do funny things... and sometimes not * hah-hah funny. @@ -171,7 +206,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) device = (adr >> 16) & 0xffff; function = adr & 0xffff; - pdev = pbus->self; + pdev = bridge->pci_dev; if (pdev && device_is_managed_by_native_pciehp(pdev)) return AE_OK; @@ -179,7 +214,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (!newfunc) return AE_NO_MEMORY; - INIT_LIST_HEAD(&newfunc->sibling); newfunc->handle = handle; newfunc->function = function; @@ -229,7 +263,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) INIT_LIST_HEAD(&slot->funcs); mutex_init(&slot->crit_sect); + mutex_lock(&bridge_mutex); list_add_tail(&slot->node, &bridge->slots); + mutex_unlock(&bridge_mutex); bridge->nr_slots++; dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", @@ -247,7 +283,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } newfunc->slot = slot; + mutex_lock(&bridge_mutex); list_add_tail(&newfunc->sibling, &slot->funcs); + mutex_unlock(&bridge_mutex); if (pci_bus_read_dev_vendor_id(pbus, PCI_DEVFN(device, function), &val, 60*1000)) @@ -288,7 +326,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) err_exit: bridge->nr_slots--; + mutex_lock(&bridge_mutex); list_del(&slot->node); + mutex_unlock(&bridge_mutex); kfree(slot); kfree(newfunc); @@ -313,13 +353,17 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge) acpi_status status; /* must be added to the list prior to calling register_slot */ + 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, bridge->handle, (u32)1, register_slot, NULL, bridge, NULL); if (ACPI_FAILURE(status)) { + mutex_lock(&bridge_mutex); list_del(&bridge->list); + mutex_unlock(&bridge_mutex); return; } @@ -349,16 +393,21 @@ static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle { struct acpiphp_bridge *bridge; struct acpiphp_slot *slot; - struct acpiphp_func *func; + struct acpiphp_func *func = NULL; + mutex_lock(&bridge_mutex); list_for_each_entry(bridge, &bridge_list, list) { list_for_each_entry(slot, &bridge->slots, node) { list_for_each_entry(func, &slot->funcs, sibling) { - if (func->handle == handle) + if (func->handle == handle) { + get_bridge(func->slot->bridge); + mutex_unlock(&bridge_mutex); return func; + } } } } + mutex_unlock(&bridge_mutex); return NULL; } @@ -368,17 +417,22 @@ static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle) { struct acpiphp_bridge *bridge; + mutex_lock(&bridge_mutex); list_for_each_entry(bridge, &bridge_list, list) - if (bridge->handle == handle) + if (bridge->handle == handle) { + get_bridge(bridge); + mutex_unlock(&bridge_mutex); return bridge; + } + mutex_unlock(&bridge_mutex); return NULL; } static void cleanup_bridge(struct acpiphp_bridge *bridge) { - struct acpiphp_slot *slot, *next; - struct acpiphp_func *func, *tmp; + struct acpiphp_slot *slot; + struct acpiphp_func *func; acpi_status status; acpi_handle handle = bridge->handle; @@ -399,8 +453,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) err("failed to install interrupt notify handler\n"); } - list_for_each_entry_safe(slot, next, &bridge->slots, node) { - list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) { + list_for_each_entry(slot, &bridge->slots, node) { + list_for_each_entry(func, &slot->funcs, sibling) { if (is_dock_device(func->handle)) { unregister_hotplug_dock_device(func->handle); unregister_dock_notifier(&func->nb); @@ -412,18 +466,13 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) if (ACPI_FAILURE(status)) err("failed to remove notify handler\n"); } - list_del(&func->sibling); - kfree(func); } acpiphp_unregister_hotplug_slot(slot); - list_del(&slot->funcs); - kfree(slot); } - put_device(&bridge->pci_bus->dev); - pci_dev_put(bridge->pci_dev); + mutex_lock(&bridge_mutex); list_del(&bridge->list); - kfree(bridge); + mutex_unlock(&bridge_mutex); } static int power_on_slot(struct acpiphp_slot *slot) @@ -620,7 +669,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) struct pci_dev *dev; struct pci_bus *bus = slot->bridge->pci_bus; struct acpiphp_func *func; - int retval = 0; int num, max, pass; if (slot->flags & SLOT_ENABLED) @@ -680,7 +728,7 @@ static int __ref enable_device(struct acpiphp_slot *slot) err_exit: - return retval; + return 0; } /* return first device in slot, acquiring a reference on it */ @@ -897,6 +945,7 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv) dbg("%s: re-enumerating slots under %s\n", __func__, objname); acpiphp_check_bridge(bridge); + put_bridge(bridge); } return AE_OK ; } @@ -974,6 +1023,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ + put_bridge(bridge); } /** @@ -987,6 +1037,8 @@ static void _handle_hotplug_event_bridge(struct work_struct *work) static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context) { + struct acpiphp_bridge *bridge = context; + /* * Currently the code adds all hotplug events to the kacpid_wq * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -995,6 +1047,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, * For now just re-add this work to the kacpi_hotplug_wq so we * don't deadlock on hotplug actions. */ + get_bridge(bridge); alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge); } @@ -1049,6 +1102,7 @@ static void _handle_hotplug_event_func(struct work_struct *work) acpi_scan_lock_release(); kfree(hp_work); /* allocated in handle_hotplug_event_func */ + put_bridge(func->slot->bridge); } /** @@ -1062,6 +1116,8 @@ static void _handle_hotplug_event_func(struct work_struct *work) static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context) { + struct acpiphp_func *func = context; + /* * Currently the code adds all hotplug events to the kacpid_wq * queue when it should add hotplug events to the kacpi_hotplug_wq. @@ -1070,6 +1126,7 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, * For now just re-add this work to the kacpi_hotplug_wq so we * don't deadlock on hotplug actions. */ + get_bridge(func->slot->bridge); alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func); } @@ -1095,6 +1152,7 @@ void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle) } INIT_LIST_HEAD(&bridge->slots); + kref_init(&bridge->ref); bridge->handle = handle; bridge->pci_dev = pci_dev_get(bus->self); bridge->pci_bus = bus; @@ -1128,6 +1186,7 @@ void acpiphp_remove_slots(struct pci_bus *bus) list_for_each_entry_safe(bridge, tmp, &bridge_list, list) if (bridge->pci_bus == bus) { cleanup_bridge(bridge); + put_bridge(bridge); break; } } From c309dbb4debb714566e4cf0d5d4e4023c3c4ff2f Mon Sep 17 00:00:00 2001 From: Myron Stowe Date: Fri, 12 Apr 2013 05:44:30 +0000 Subject: [PATCH 41/63] PCI/ACPI: Remove support of ACPI PCI subdrivers Both sub-drivers of the "PCI Root Bridge ("pci_bridge")" driver, "acpiphp" and "pci_slot", have been converted to hook directly into the PCI core. With the conversions there are no remaining usages of the 'struct acpi_pci_driver' list based infrastructure. This patch removes it. Signed-off-by: Myron Stowe Signed-off-by: Jiang Liu Signed-off-by: Bjorn Helgaas Reviewed-by: Yinghai Lu Cc: "Rafael J. Wysocki" Cc: Toshi Kani --- drivers/acpi/pci_root.c | 48 +---------------------------------------- include/linux/acpi.h | 9 -------- 2 files changed, 1 insertion(+), 56 deletions(-) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0ac546d5e53f..b80e06e0b2d9 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -65,44 +65,12 @@ static struct acpi_scan_handler pci_root_handler = { .detach = acpi_pci_root_remove, }; -/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ +/* Lock to protect both acpi_pci_roots lists */ static DEFINE_MUTEX(acpi_pci_root_lock); static LIST_HEAD(acpi_pci_roots); -static LIST_HEAD(acpi_pci_drivers); static DEFINE_MUTEX(osc_lock); -int acpi_pci_register_driver(struct acpi_pci_driver *driver) -{ - int n = 0; - struct acpi_pci_root *root; - - mutex_lock(&acpi_pci_root_lock); - list_add_tail(&driver->node, &acpi_pci_drivers); - if (driver->add) - list_for_each_entry(root, &acpi_pci_roots, node) { - driver->add(root); - n++; - } - mutex_unlock(&acpi_pci_root_lock); - - return n; -} -EXPORT_SYMBOL(acpi_pci_register_driver); - -void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) -{ - struct acpi_pci_root *root; - - mutex_lock(&acpi_pci_root_lock); - list_del(&driver->node); - if (driver->remove) - list_for_each_entry(root, &acpi_pci_roots, node) - driver->remove(root); - mutex_unlock(&acpi_pci_root_lock); -} -EXPORT_SYMBOL(acpi_pci_unregister_driver); - /** * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge * @handle - the ACPI CA node in question. @@ -413,7 +381,6 @@ static int acpi_pci_root_add(struct acpi_device *device, acpi_status status; int result; struct acpi_pci_root *root; - struct acpi_pci_driver *driver; u32 flags, base_flags; bool is_osc_granted = false; @@ -573,12 +540,6 @@ static int acpi_pci_root_add(struct acpi_device *device, pci_assign_unassigned_bus_resources(root->bus); } - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(driver, &acpi_pci_drivers, node) - if (driver->add) - driver->add(root); - mutex_unlock(&acpi_pci_root_lock); - /* need to after hot-added ioapic is registered */ if (system_state != SYSTEM_BOOTING) pci_enable_bridges(root->bus); @@ -599,16 +560,9 @@ end: static void acpi_pci_root_remove(struct acpi_device *device) { struct acpi_pci_root *root = acpi_driver_data(device); - struct acpi_pci_driver *driver; pci_stop_root_bus(root->bus); - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry_reverse(driver, &acpi_pci_drivers, node) - if (driver->remove) - driver->remove(root); - mutex_unlock(&acpi_pci_root_lock); - device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index bcbdd7484e58..03053aca5b32 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -152,15 +152,6 @@ void acpi_penalize_isa_irq(int irq, int active); void acpi_pci_irq_disable (struct pci_dev *dev); -struct acpi_pci_driver { - struct list_head node; - int (*add)(struct acpi_pci_root *root); - void (*remove)(struct acpi_pci_root *root); -}; - -int acpi_pci_register_driver(struct acpi_pci_driver *driver); -void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); - extern int ec_read(u8 addr, u8 *val); extern int ec_write(u8 addr, u8 val); extern int ec_transaction(u8 command, From d67aed63b8bfa4a06575ed578328b02f909699ee Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 12 Apr 2013 11:18:07 -0600 Subject: [PATCH 42/63] PCI: Remove __must_check from definitions The __must_check (gcc "warn_unused_result") attribute only makes sense when compiling the *caller* of the function, so the attribute should appear on the declaration in the header file, not on the definition. The declarations of these functions are already annotated with __must_check. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/pci_hotplug_core.c | 4 ++-- drivers/pci/hotplug/shpchp_sysfs.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 9d4c199a64be..ec20f74c8981 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -517,8 +517,8 @@ int pci_hp_deregister(struct hotplug_slot *hotplug) * * Returns 0 if successful, anything else for an error. */ -int __must_check pci_hp_change_slot_info(struct hotplug_slot *hotplug, - struct hotplug_slot_info *info) +int pci_hp_change_slot_info(struct hotplug_slot *hotplug, + struct hotplug_slot_info *info) { if (!hotplug || !info) return -ENODEV; diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index eeb23ceae4a8..e8c31fe20566 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -85,7 +85,7 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha } static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL); -int __must_check shpchp_create_ctrl_files (struct controller *ctrl) +int shpchp_create_ctrl_files (struct controller *ctrl) { return device_create_file (&ctrl->pci_dev->dev, &dev_attr_ctrl); } From 9fc9eea09f518b9bbdc0a14ef668698c913ba614 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 12 Apr 2013 11:35:40 -0600 Subject: [PATCH 43/63] PCI: Warn about failures instead of "must_check" functions These places capture return values to avoid "must_check" warnings, but we didn't *do* anything with the return values, which causes "set but not used" warnings. We might as well do something instead of just trying to evade the "must_check" warnings. Signed-off-by: Bjorn Helgaas --- drivers/pci/bus.c | 3 +++ drivers/pci/setup-bus.c | 2 ++ drivers/pci/slot.c | 7 +++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 8647dc6f52d0..ee4c4c4fde17 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -202,6 +202,9 @@ void pci_bus_add_devices(const struct pci_bus *bus) if (dev->is_added) continue; retval = pci_bus_add_device(dev); + if (retval) + dev_err(&dev->dev, "Error adding device (%d)\n", + retval); } list_for_each_entry(dev, &bus->devices, bus_list) { diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 502a75ea12fb..16abaaa1f83c 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1545,6 +1545,8 @@ again: enable_all: retval = pci_reenable_device(bridge); + if (retval) + dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval); pci_set_master(bridge); pci_enable_bridges(parent); } diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index ac6412fb8d6f..c1e9284a677b 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -377,14 +377,17 @@ void pci_hp_create_module_link(struct pci_slot *pci_slot) { struct hotplug_slot *slot = pci_slot->hotplug; struct kobject *kobj = NULL; - int no_warn; + int ret; if (!slot || !slot->ops) return; kobj = kset_find_obj(module_kset, slot->ops->mod_name); if (!kobj) return; - no_warn = sysfs_create_link(&pci_slot->kobj, kobj, "module"); + ret = sysfs_create_link(&pci_slot->kobj, kobj, "module"); + if (ret) + dev_err(&pci_slot->bus->dev, "Error creating sysfs link (%d)\n", + ret); kobject_put(kobj); } EXPORT_SYMBOL_GPL(pci_hp_create_module_link); From f39d5b72913e2a9ff00ba5ab145ee05a888b1286 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Fri, 12 Apr 2013 12:02:59 -0600 Subject: [PATCH 44/63] PCI: Remove "extern" from function declarations We had an inconsistent mix of using and omitting the "extern" keyword on function declarations in header files. This removes them all. Signed-off-by: Bjorn Helgaas --- drivers/pci/hotplug/acpiphp.h | 26 ++++---- drivers/pci/hotplug/cpci_hotplug.h | 36 +++++------ drivers/pci/hotplug/cpqphp.h | 70 ++++++++++------------ drivers/pci/hotplug/cpqphp_nvram.h | 12 ++-- drivers/pci/hotplug/ibmphp.h | 66 ++++++++++----------- drivers/pci/hotplug/pciehp.h | 22 +++---- drivers/pci/hotplug/rpadlpar.h | 8 +-- drivers/pci/hotplug/rpaphp.h | 16 ++--- drivers/pci/hotplug/shpchp.h | 26 ++++---- drivers/pci/pci.h | 89 ++++++++++++++-------------- drivers/pci/pcie/aer/aerdrv.h | 14 ++--- drivers/pci/pcie/portdrv.h | 18 +++--- include/linux/pci-aspm.h | 20 +++---- include/linux/pci-ats.h | 26 ++++---- include/linux/pci.h | 95 +++++++++++++++--------------- include/linux/pci_hotplug.h | 12 ++-- include/linux/pcieport_if.h | 4 +- 17 files changed, 275 insertions(+), 285 deletions(-) diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index b70ac00a117e..9daddf4b9576 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h @@ -174,23 +174,23 @@ struct acpiphp_attention_info /* function prototypes */ /* acpiphp_core.c */ -extern int acpiphp_register_attention(struct acpiphp_attention_info*info); -extern int acpiphp_unregister_attention(struct acpiphp_attention_info *info); -extern int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); -extern void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); +int acpiphp_register_attention(struct acpiphp_attention_info*info); +int acpiphp_unregister_attention(struct acpiphp_attention_info *info); +int acpiphp_register_hotplug_slot(struct acpiphp_slot *slot); +void acpiphp_unregister_hotplug_slot(struct acpiphp_slot *slot); /* acpiphp_glue.c */ -extern int acpiphp_glue_init (void); -extern void acpiphp_glue_exit (void); +int acpiphp_glue_init(void); +void acpiphp_glue_exit(void); typedef int (*acpiphp_callback)(struct acpiphp_slot *slot, void *data); -extern int acpiphp_enable_slot (struct acpiphp_slot *slot); -extern int acpiphp_disable_slot (struct acpiphp_slot *slot); -extern int acpiphp_eject_slot (struct acpiphp_slot *slot); -extern u8 acpiphp_get_power_status (struct acpiphp_slot *slot); -extern u8 acpiphp_get_attention_status (struct acpiphp_slot *slot); -extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot); -extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot); +int acpiphp_enable_slot(struct acpiphp_slot *slot); +int acpiphp_disable_slot(struct acpiphp_slot *slot); +int acpiphp_eject_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; diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h index 3ae19f774cb3..1356211431d0 100644 --- a/drivers/pci/hotplug/cpci_hotplug.h +++ b/drivers/pci/hotplug/cpci_hotplug.h @@ -75,29 +75,29 @@ static inline const char *slot_name(struct slot *slot) return hotplug_slot_name(slot->hotplug_slot); } -extern int cpci_hp_register_controller(struct cpci_hp_controller *controller); -extern int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); -extern int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); -extern int cpci_hp_unregister_bus(struct pci_bus *bus); -extern int cpci_hp_start(void); -extern int cpci_hp_stop(void); +int cpci_hp_register_controller(struct cpci_hp_controller *controller); +int cpci_hp_unregister_controller(struct cpci_hp_controller *controller); +int cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last); +int cpci_hp_unregister_bus(struct pci_bus *bus); +int cpci_hp_start(void); +int cpci_hp_stop(void); /* * Internal function prototypes, these functions should not be used by * board/chassis drivers. */ -extern u8 cpci_get_attention_status(struct slot *slot); -extern u8 cpci_get_latch_status(struct slot *slot); -extern u8 cpci_get_adapter_status(struct slot *slot); -extern u16 cpci_get_hs_csr(struct slot * slot); -extern int cpci_set_attention_status(struct slot *slot, int status); -extern int cpci_check_and_clear_ins(struct slot * slot); -extern int cpci_check_ext(struct slot * slot); -extern int cpci_clear_ext(struct slot * slot); -extern int cpci_led_on(struct slot * slot); -extern int cpci_led_off(struct slot * slot); -extern int cpci_configure_slot(struct slot *slot); -extern int cpci_unconfigure_slot(struct slot *slot); +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); +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_configure_slot(struct slot *slot); +int cpci_unconfigure_slot(struct slot *slot); #ifdef CONFIG_HOTPLUG_PCI_CPCI int cpci_hotplug_init(int debug); diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h index d8ffc7366801..516b87738b6e 100644 --- a/drivers/pci/hotplug/cpqphp.h +++ b/drivers/pci/hotplug/cpqphp.h @@ -404,50 +404,44 @@ struct resource_lists { /* debugfs functions for the hotplug controller info */ -extern void cpqhp_initialize_debugfs(void); -extern void cpqhp_shutdown_debugfs(void); -extern void cpqhp_create_debugfs_files(struct controller *ctrl); -extern void cpqhp_remove_debugfs_files(struct controller *ctrl); +void cpqhp_initialize_debugfs(void); +void cpqhp_shutdown_debugfs(void); +void cpqhp_create_debugfs_files(struct controller *ctrl); +void cpqhp_remove_debugfs_files(struct controller *ctrl); /* controller functions */ -extern void cpqhp_pushbutton_thread(unsigned long event_pointer); -extern irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data); -extern int cpqhp_find_available_resources(struct controller *ctrl, - void __iomem *rom_start); -extern int cpqhp_event_start_thread(void); -extern void cpqhp_event_stop_thread(void); -extern struct pci_func *cpqhp_slot_create(unsigned char busnumber); -extern struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device, - unsigned char index); -extern int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func); -extern int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func); -extern int cpqhp_hardware_test(struct controller *ctrl, int test_num); +void cpqhp_pushbutton_thread(unsigned long event_pointer); +irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data); +int cpqhp_find_available_resources(struct controller *ctrl, + void __iomem *rom_start); +int cpqhp_event_start_thread(void); +void cpqhp_event_stop_thread(void); +struct pci_func *cpqhp_slot_create(unsigned char busnumber); +struct pci_func *cpqhp_slot_find(unsigned char bus, unsigned char device, + unsigned char index); +int cpqhp_process_SI(struct controller *ctrl, struct pci_func *func); +int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func); +int cpqhp_hardware_test(struct controller *ctrl, int test_num); /* resource functions */ -extern int cpqhp_resource_sort_and_combine (struct pci_resource **head); +int cpqhp_resource_sort_and_combine (struct pci_resource **head); /* pci functions */ -extern int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); -extern int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, - u8 slot); -extern int cpqhp_save_config(struct controller *ctrl, int busnumber, - int is_hot_plug); -extern int cpqhp_save_base_addr_length(struct controller *ctrl, - struct pci_func *func); -extern int cpqhp_save_used_resources(struct controller *ctrl, - struct pci_func *func); -extern int cpqhp_configure_board(struct controller *ctrl, - struct pci_func *func); -extern int cpqhp_save_slot_config(struct controller *ctrl, - struct pci_func *new_slot); -extern int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func); -extern void cpqhp_destroy_board_resources(struct pci_func *func); -extern int cpqhp_return_board_resources (struct pci_func *func, - struct resource_lists *resources); -extern void cpqhp_destroy_resource_list(struct resource_lists *resources); -extern int cpqhp_configure_device(struct controller *ctrl, - struct pci_func *func); -extern int cpqhp_unconfigure_device(struct pci_func *func); +int cpqhp_set_irq(u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num); +int cpqhp_get_bus_dev(struct controller *ctrl, u8 *bus_num, u8 *dev_num, + u8 slot); +int cpqhp_save_config(struct controller *ctrl, int busnumber, int is_hot_plug); +int cpqhp_save_base_addr_length(struct controller *ctrl, struct pci_func *func); +int cpqhp_save_used_resources(struct controller *ctrl, struct pci_func *func); +int cpqhp_configure_board(struct controller *ctrl, struct pci_func *func); +int cpqhp_save_slot_config(struct controller *ctrl, struct pci_func *new_slot); +int cpqhp_valid_replace(struct controller *ctrl, struct pci_func *func); +void cpqhp_destroy_board_resources(struct pci_func *func); +int cpqhp_return_board_resources(struct pci_func *func, + struct resource_lists *resources); +void cpqhp_destroy_resource_list(struct resource_lists *resources); +int cpqhp_configure_device(struct controller *ctrl, struct pci_func *func); +int cpqhp_unconfigure_device(struct pci_func *func); /* Global variables */ extern int cpqhp_debug; diff --git a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h index e89c0702119d..34e4e54fcf15 100644 --- a/drivers/pci/hotplug/cpqphp_nvram.h +++ b/drivers/pci/hotplug/cpqphp_nvram.h @@ -30,26 +30,26 @@ #ifndef CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM -static inline void compaq_nvram_init (void __iomem *rom_start) +static inline void compaq_nvram_init(void __iomem *rom_start) { return; } -static inline int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl) +static inline int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl) { return 0; } -static inline int compaq_nvram_store (void __iomem *rom_start) +static inline int compaq_nvram_store(void __iomem *rom_start) { return 0; } #else -extern void compaq_nvram_init (void __iomem *rom_start); -extern int compaq_nvram_load (void __iomem *rom_start, struct controller *ctrl); -extern int compaq_nvram_store (void __iomem *rom_start); +void compaq_nvram_init(void __iomem *rom_start); +int compaq_nvram_load(void __iomem *rom_start, struct controller *ctrl); +int compaq_nvram_store(void __iomem *rom_start); #endif diff --git a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h index a8d391a4957d..8c5b25871d02 100644 --- a/drivers/pci/hotplug/ibmphp.h +++ b/drivers/pci/hotplug/ibmphp.h @@ -275,17 +275,17 @@ extern struct list_head ibmphp_slot_head; * FUNCTION PROTOTYPES * ***********************************************************/ -extern void ibmphp_free_ebda_hpc_queue (void); -extern int ibmphp_access_ebda (void); -extern struct slot *ibmphp_get_slot_from_physical_num (u8); -extern int ibmphp_get_total_hp_slots (void); -extern void ibmphp_free_ibm_slot (struct slot *); -extern void ibmphp_free_bus_info_queue (void); -extern void ibmphp_free_ebda_pci_rsrc_queue (void); -extern struct bus_info *ibmphp_find_same_bus_num (u32); -extern int ibmphp_get_bus_index (u8); -extern u16 ibmphp_get_total_controllers (void); -extern int ibmphp_register_pci (void); +void ibmphp_free_ebda_hpc_queue(void); +int ibmphp_access_ebda(void); +struct slot *ibmphp_get_slot_from_physical_num(u8); +int ibmphp_get_total_hp_slots(void); +void ibmphp_free_ibm_slot(struct slot *); +void ibmphp_free_bus_info_queue(void); +void ibmphp_free_ebda_pci_rsrc_queue(void); +struct bus_info *ibmphp_find_same_bus_num(u32); +int ibmphp_get_bus_index(u8); +u16 ibmphp_get_total_controllers(void); +int ibmphp_register_pci(void); /* passed parameters */ #define MEM 0 @@ -381,24 +381,24 @@ struct res_needed { /* functions */ -extern int ibmphp_rsrc_init (void); -extern int ibmphp_add_resource (struct resource_node *); -extern int ibmphp_remove_resource (struct resource_node *); -extern int ibmphp_find_resource (struct bus_node *, u32, struct resource_node **, int); -extern int ibmphp_check_resource (struct resource_node *, u8); -extern int ibmphp_remove_bus (struct bus_node *, u8); -extern void ibmphp_free_resources (void); -extern int ibmphp_add_pfmem_from_mem (struct resource_node *); -extern struct bus_node *ibmphp_find_res_bus (u8); -extern void ibmphp_print_test (void); /* for debugging purposes */ +int ibmphp_rsrc_init(void); +int ibmphp_add_resource(struct resource_node *); +int ibmphp_remove_resource(struct resource_node *); +int ibmphp_find_resource(struct bus_node *, u32, struct resource_node **, int); +int ibmphp_check_resource(struct resource_node *, u8); +int ibmphp_remove_bus(struct bus_node *, u8); +void ibmphp_free_resources(void); +int ibmphp_add_pfmem_from_mem(struct resource_node *); +struct bus_node *ibmphp_find_res_bus(u8); +void ibmphp_print_test(void); /* for debugging purposes */ -extern void ibmphp_hpc_initvars (void); -extern int ibmphp_hpc_readslot (struct slot *, u8, u8 *); -extern int ibmphp_hpc_writeslot (struct slot *, u8); -extern void ibmphp_lock_operations (void); -extern void ibmphp_unlock_operations (void); -extern int ibmphp_hpc_start_poll_thread (void); -extern void ibmphp_hpc_stop_poll_thread (void); +void ibmphp_hpc_initvars(void); +int ibmphp_hpc_readslot(struct slot *, u8, u8 *); +int ibmphp_hpc_writeslot(struct slot *, u8); +void ibmphp_lock_operations(void); +void ibmphp_unlock_operations(void); +int ibmphp_hpc_start_poll_thread(void); +void ibmphp_hpc_stop_poll_thread(void); //---------------------------------------------------------------------------- @@ -749,11 +749,11 @@ struct controller { /* Functions */ -extern int ibmphp_init_devno (struct slot **); /* This function is called from EBDA, so we need it not be static */ -extern int ibmphp_do_disable_slot (struct slot *slot_cur); -extern int ibmphp_update_slot_info (struct slot *); /* This function is called from HPC, so we need it to not be be static */ -extern int ibmphp_configure_card (struct pci_func *, u8); -extern int ibmphp_unconfigure_card (struct slot **, int); +int ibmphp_init_devno(struct slot **); /* This function is called from EBDA, so we need it not be static */ +int ibmphp_do_disable_slot(struct slot *slot_cur); +int ibmphp_update_slot_info(struct slot *); /* This function is called from HPC, so we need it to not be be static */ +int ibmphp_configure_card(struct pci_func *, u8); +int ibmphp_unconfigure_card(struct slot **, int); extern struct hotplug_slot_ops ibmphp_hotplug_slot_ops; #endif //__IBMPHP_H diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 2c113de94323..7fb326983ed6 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -127,15 +127,15 @@ struct controller { #define NO_CMD_CMPL(ctrl) ((ctrl)->slot_cap & PCI_EXP_SLTCAP_NCCS) #define PSN(ctrl) ((ctrl)->slot_cap >> 19) -extern int pciehp_sysfs_enable_slot(struct slot *slot); -extern int pciehp_sysfs_disable_slot(struct slot *slot); -extern u8 pciehp_handle_attention_button(struct slot *p_slot); -extern u8 pciehp_handle_switch_change(struct slot *p_slot); -extern u8 pciehp_handle_presence_change(struct slot *p_slot); -extern u8 pciehp_handle_power_fault(struct slot *p_slot); -extern int pciehp_configure_device(struct slot *p_slot); -extern int pciehp_unconfigure_device(struct slot *p_slot); -extern void pciehp_queue_pushbutton_work(struct work_struct *work); +int pciehp_sysfs_enable_slot(struct slot *slot); +int pciehp_sysfs_disable_slot(struct slot *slot); +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); +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); struct controller *pcie_init(struct pcie_device *dev); int pcie_init_notification(struct controller *ctrl); int pciehp_enable_slot(struct slot *p_slot); @@ -166,8 +166,8 @@ static inline const char *slot_name(struct slot *slot) #include #include -extern void __init pciehp_acpi_slot_detection_init(void); -extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev); +void __init pciehp_acpi_slot_detection_init(void); +int pciehp_acpi_slot_detection_check(struct pci_dev *dev); static inline void pciehp_firmware_init(void) { diff --git a/drivers/pci/hotplug/rpadlpar.h b/drivers/pci/hotplug/rpadlpar.h index 4a0a59b82eae..81df93931ad0 100644 --- a/drivers/pci/hotplug/rpadlpar.h +++ b/drivers/pci/hotplug/rpadlpar.h @@ -15,10 +15,10 @@ #ifndef _RPADLPAR_IO_H_ #define _RPADLPAR_IO_H_ -extern int dlpar_sysfs_init(void); -extern void dlpar_sysfs_exit(void); +int dlpar_sysfs_init(void); +void dlpar_sysfs_exit(void); -extern int dlpar_add_slot(char *drc_name); -extern int dlpar_remove_slot(char *drc_name); +int dlpar_add_slot(char *drc_name); +int dlpar_remove_slot(char *drc_name); #endif diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h index df5677440a08..3135856e5e1c 100644 --- a/drivers/pci/hotplug/rpaphp.h +++ b/drivers/pci/hotplug/rpaphp.h @@ -86,18 +86,18 @@ extern struct list_head rpaphp_slot_head; /* function prototypes */ /* rpaphp_pci.c */ -extern int rpaphp_enable_slot(struct slot *slot); -extern int rpaphp_get_sensor_state(struct slot *slot, int *state); +int rpaphp_enable_slot(struct slot *slot); +int rpaphp_get_sensor_state(struct slot *slot, int *state); /* rpaphp_core.c */ -extern int rpaphp_add_slot(struct device_node *dn); -extern int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, +int rpaphp_add_slot(struct device_node *dn); +int rpaphp_get_drc_props(struct device_node *dn, int *drc_index, char **drc_name, char **drc_type, int *drc_power_domain); /* rpaphp_slot.c */ -extern void dealloc_slot_struct(struct slot *slot); -extern struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain); -extern int rpaphp_register_slot(struct slot *slot); -extern int rpaphp_deregister_slot(struct slot *slot); +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/shpchp.h b/drivers/pci/hotplug/shpchp.h index b849f995075a..e260f207a90e 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -168,19 +168,19 @@ struct controller { #define WRONG_BUS_FREQUENCY 0x0000000D #define POWER_FAILURE 0x0000000E -extern int __must_check shpchp_create_ctrl_files(struct controller *ctrl); -extern void shpchp_remove_ctrl_files(struct controller *ctrl); -extern int shpchp_sysfs_enable_slot(struct slot *slot); -extern int shpchp_sysfs_disable_slot(struct slot *slot); -extern u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl); -extern u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl); -extern u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); -extern u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); -extern int shpchp_configure_device(struct slot *p_slot); -extern int shpchp_unconfigure_device(struct slot *p_slot); -extern void cleanup_slots(struct controller *ctrl); -extern void shpchp_queue_pushbutton_work(struct work_struct *work); -extern int shpc_init( struct controller *ctrl, struct pci_dev *pdev); +int __must_check shpchp_create_ctrl_files(struct controller *ctrl); +void shpchp_remove_ctrl_files(struct controller *ctrl); +int shpchp_sysfs_enable_slot(struct slot *slot); +int shpchp_sysfs_disable_slot(struct slot *slot); +u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl); +u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl); +u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl); +u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl); +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); static inline const char *slot_name(struct slot *slot) { diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 7346ee68f47d..68678ed76b0d 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -8,26 +8,25 @@ /* Functions internal to the PCI core code */ -extern int pci_create_sysfs_dev_files(struct pci_dev *pdev); -extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev); +int pci_create_sysfs_dev_files(struct pci_dev *pdev); +void pci_remove_sysfs_dev_files(struct pci_dev *pdev); #if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI) static inline void pci_create_firmware_label_files(struct pci_dev *pdev) { return; } static inline void pci_remove_firmware_label_files(struct pci_dev *pdev) { return; } #else -extern void pci_create_firmware_label_files(struct pci_dev *pdev); -extern void pci_remove_firmware_label_files(struct pci_dev *pdev); +void pci_create_firmware_label_files(struct pci_dev *pdev); +void pci_remove_firmware_label_files(struct pci_dev *pdev); #endif -extern void pci_cleanup_rom(struct pci_dev *dev); +void pci_cleanup_rom(struct pci_dev *dev); #ifdef HAVE_PCI_MMAP enum pci_mmap_api { PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices//resource */ PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/ */ }; -extern int pci_mmap_fits(struct pci_dev *pdev, int resno, - struct vm_area_struct *vmai, - enum pci_mmap_api mmap_api); +int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai, + enum pci_mmap_api mmap_api); #endif int pci_probe_reset_function(struct pci_dev *dev); @@ -60,17 +59,17 @@ struct pci_platform_pm_ops { int (*run_wake)(struct pci_dev *dev, bool enable); }; -extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); -extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); -extern void pci_power_up(struct pci_dev *dev); -extern void pci_disable_enabled_device(struct pci_dev *dev); -extern int pci_finish_runtime_suspend(struct pci_dev *dev); -extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign); -extern void pci_wakeup_bus(struct pci_bus *bus); -extern void pci_config_pm_runtime_get(struct pci_dev *dev); -extern void pci_config_pm_runtime_put(struct pci_dev *dev); -extern void pci_pm_init(struct pci_dev *dev); -extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); +int pci_set_platform_pm(struct pci_platform_pm_ops *ops); +void pci_update_current_state(struct pci_dev *dev, pci_power_t state); +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); +void pci_allocate_cap_save_buffers(struct pci_dev *dev); void pci_free_cap_save_buffers(struct pci_dev *dev); static inline void pci_wakeup_event(struct pci_dev *dev) @@ -96,7 +95,7 @@ struct pci_vpd { struct bin_attribute *attr; /* descriptor for sysfs VPD entry */ }; -extern int pci_vpd_pci22_init(struct pci_dev *dev); +int pci_vpd_pci22_init(struct pci_dev *dev); static inline void pci_vpd_release(struct pci_dev *dev) { if (dev->vpd) @@ -105,9 +104,9 @@ static inline void pci_vpd_release(struct pci_dev *dev) /* PCI /proc functions */ #ifdef CONFIG_PROC_FS -extern int pci_proc_attach_device(struct pci_dev *dev); -extern int pci_proc_detach_device(struct pci_dev *dev); -extern int pci_proc_detach_bus(struct pci_bus *bus); +int pci_proc_attach_device(struct pci_dev *dev); +int pci_proc_detach_device(struct pci_dev *dev); +int pci_proc_detach_bus(struct pci_bus *bus); #else static inline int pci_proc_attach_device(struct pci_dev *dev) { return 0; } static inline int pci_proc_detach_device(struct pci_dev *dev) { return 0; } @@ -118,8 +117,8 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } int pci_hp_add_bridge(struct pci_dev *dev); #ifdef HAVE_PCI_LEGACY -extern void pci_create_legacy_files(struct pci_bus *bus); -extern void pci_remove_legacy_files(struct pci_bus *bus); +void pci_create_legacy_files(struct pci_bus *bus); +void pci_remove_legacy_files(struct pci_bus *bus); #else static inline void pci_create_legacy_files(struct pci_bus *bus) { return; } static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; } @@ -134,7 +133,7 @@ extern unsigned int pci_pm_d3_delay; #ifdef CONFIG_PCI_MSI void pci_no_msi(void); -extern void pci_msi_init_pci_dev(struct pci_dev *dev); +void pci_msi_init_pci_dev(struct pci_dev *dev); #else static inline void pci_no_msi(void) { } static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { } @@ -198,12 +197,11 @@ enum pci_bar_type { bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *pl, int crs_timeout); -extern int pci_setup_device(struct pci_dev *dev); -extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, - struct resource *res, unsigned int reg); -extern int pci_resource_bar(struct pci_dev *dev, int resno, - enum pci_bar_type *type); -extern void pci_configure_ari(struct pci_dev *dev); +int pci_setup_device(struct pci_dev *dev); +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); /** * pci_ari_enabled - query ARI forwarding status @@ -217,7 +215,7 @@ static inline int pci_ari_enabled(struct pci_bus *bus) } void pci_reassigndev_resource_alignment(struct pci_dev *dev); -extern void pci_disable_bridge_window(struct pci_dev *dev); +void pci_disable_bridge_window(struct pci_dev *dev); /* Single Root I/O Virtualization */ struct pci_sriov { @@ -241,7 +239,7 @@ struct pci_sriov { }; #ifdef CONFIG_PCI_ATS -extern void pci_restore_ats_state(struct pci_dev *dev); +void pci_restore_ats_state(struct pci_dev *dev); #else static inline void pci_restore_ats_state(struct pci_dev *dev) { @@ -249,14 +247,13 @@ static inline void pci_restore_ats_state(struct pci_dev *dev) #endif /* CONFIG_PCI_ATS */ #ifdef CONFIG_PCI_IOV -extern int pci_iov_init(struct pci_dev *dev); -extern void pci_iov_release(struct pci_dev *dev); -extern int pci_iov_resource_bar(struct pci_dev *dev, int resno, - enum pci_bar_type *type); -extern resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, - int resno); -extern void pci_restore_iov_state(struct pci_dev *dev); -extern int pci_iov_bus_range(struct pci_bus *bus); +int pci_iov_init(struct pci_dev *dev); +void pci_iov_release(struct pci_dev *dev); +int pci_iov_resource_bar(struct pci_dev *dev, int resno, + enum pci_bar_type *type); +resource_size_t pci_sriov_resource_alignment(struct pci_dev *dev, int resno); +void pci_restore_iov_state(struct pci_dev *dev); +int pci_iov_bus_range(struct pci_bus *bus); #else static inline int pci_iov_init(struct pci_dev *dev) @@ -282,10 +279,10 @@ static inline int pci_iov_bus_range(struct pci_bus *bus) #endif /* CONFIG_PCI_IOV */ -extern unsigned long pci_cardbus_resource_alignment(struct resource *); +unsigned long pci_cardbus_resource_alignment(struct resource *); static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, - struct resource *res) + struct resource *res) { #ifdef CONFIG_PCI_IOV int resno = res - dev->resource; @@ -298,7 +295,7 @@ static inline resource_size_t pci_resource_alignment(struct pci_dev *dev, return resource_alignment(res); } -extern void pci_enable_acs(struct pci_dev *dev); +void pci_enable_acs(struct pci_dev *dev); struct pci_dev_reset_methods { u16 vendor; @@ -307,7 +304,7 @@ struct pci_dev_reset_methods { }; #ifdef CONFIG_PCI_QUIRKS -extern int pci_dev_specific_reset(struct pci_dev *dev, int probe); +int pci_dev_specific_reset(struct pci_dev *dev, int probe); #else static inline int pci_dev_specific_reset(struct pci_dev *dev, int probe) { diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 22f840f4dda1..d12c77cd6991 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -110,15 +110,15 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, } extern struct bus_type pcie_port_bus_type; -extern void aer_do_secondary_bus_reset(struct pci_dev *dev); -extern int aer_init(struct pcie_device *dev); -extern void aer_isr(struct work_struct *work); -extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); -extern void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); -extern irqreturn_t aer_irq(int irq, void *context); +void aer_do_secondary_bus_reset(struct pci_dev *dev); +int aer_init(struct pcie_device *dev); +void aer_isr(struct work_struct *work); +void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); +void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info); +irqreturn_t aer_irq(int irq, void *context); #ifdef CONFIG_ACPI_APEI -extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); +int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); #else static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) { diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h index eea2ca2375e6..d2eb80aab569 100644 --- a/drivers/pci/pcie/portdrv.h +++ b/drivers/pci/pcie/portdrv.h @@ -21,18 +21,18 @@ #define get_descriptor_id(type, service) (((type - 4) << 4) | service) extern struct bus_type pcie_port_bus_type; -extern int pcie_port_device_register(struct pci_dev *dev); +int pcie_port_device_register(struct pci_dev *dev); #ifdef CONFIG_PM -extern int pcie_port_device_suspend(struct device *dev); -extern int pcie_port_device_resume(struct device *dev); +int pcie_port_device_suspend(struct device *dev); +int pcie_port_device_resume(struct device *dev); #endif -extern void pcie_port_device_remove(struct pci_dev *dev); -extern int __must_check pcie_port_bus_register(void); -extern void pcie_port_bus_unregister(void); +void pcie_port_device_remove(struct pci_dev *dev); +int __must_check pcie_port_bus_register(void); +void pcie_port_bus_unregister(void); struct pci_dev; -extern void pcie_clear_root_pme_status(struct pci_dev *dev); +void pcie_clear_root_pme_status(struct pci_dev *dev); #ifdef CONFIG_HOTPLUG_PCI_PCIE extern bool pciehp_msi_disabled; @@ -59,7 +59,7 @@ static inline bool pcie_pme_no_msi(void) return pcie_pme_msi_disabled; } -extern void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable); +void pcie_pme_interrupt_enable(struct pci_dev *dev, bool enable); #else /* !CONFIG_PCIE_PME */ static inline void pcie_pme_disable_msi(void) {} static inline bool pcie_pme_no_msi(void) { return false; } @@ -67,7 +67,7 @@ static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {} #endif /* !CONFIG_PCIE_PME */ #ifdef CONFIG_ACPI -extern int pcie_port_acpi_setup(struct pci_dev *port, int *mask); +int pcie_port_acpi_setup(struct pci_dev *port, int *mask); static inline int pcie_port_platform_notify(struct pci_dev *port, int *mask) { diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h index c8320144fe79..8af4610c2e41 100644 --- a/include/linux/pci-aspm.h +++ b/include/linux/pci-aspm.h @@ -23,14 +23,14 @@ #define PCIE_LINK_STATE_CLKPM 4 #ifdef CONFIG_PCIEASPM -extern void pcie_aspm_init_link_state(struct pci_dev *pdev); -extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); -extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); -extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev); -extern void pci_disable_link_state(struct pci_dev *pdev, int state); -extern void pci_disable_link_state_locked(struct pci_dev *pdev, int state); -extern void pcie_clear_aspm(struct pci_bus *bus); -extern void pcie_no_aspm(void); +void pcie_aspm_init_link_state(struct pci_dev *pdev); +void pcie_aspm_exit_link_state(struct pci_dev *pdev); +void pcie_aspm_pm_state_change(struct pci_dev *pdev); +void pcie_aspm_powersave_config_link(struct pci_dev *pdev); +void pci_disable_link_state(struct pci_dev *pdev, int state); +void pci_disable_link_state_locked(struct pci_dev *pdev, int state); +void pcie_clear_aspm(struct pci_bus *bus); +void pcie_no_aspm(void); #else static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { @@ -56,8 +56,8 @@ static inline void pcie_no_aspm(void) #endif #ifdef CONFIG_PCIEASPM_DEBUG /* this depends on CONFIG_PCIEASPM */ -extern void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev); -extern void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev); +void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev); +void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev); #else static inline void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) { diff --git a/include/linux/pci-ats.h b/include/linux/pci-ats.h index 7ef68724f0f0..68bcefd7fca0 100644 --- a/include/linux/pci-ats.h +++ b/include/linux/pci-ats.h @@ -14,9 +14,9 @@ struct pci_ats { #ifdef CONFIG_PCI_ATS -extern int pci_enable_ats(struct pci_dev *dev, int ps); -extern void pci_disable_ats(struct pci_dev *dev); -extern int pci_ats_queue_depth(struct pci_dev *dev); +int pci_enable_ats(struct pci_dev *dev, int ps); +void pci_disable_ats(struct pci_dev *dev); +int pci_ats_queue_depth(struct pci_dev *dev); /** * pci_ats_enabled - query the ATS status @@ -54,12 +54,12 @@ static inline int pci_ats_enabled(struct pci_dev *dev) #ifdef CONFIG_PCI_PRI -extern int pci_enable_pri(struct pci_dev *pdev, u32 reqs); -extern void pci_disable_pri(struct pci_dev *pdev); -extern bool pci_pri_enabled(struct pci_dev *pdev); -extern int pci_reset_pri(struct pci_dev *pdev); -extern bool pci_pri_stopped(struct pci_dev *pdev); -extern int pci_pri_status(struct pci_dev *pdev); +int pci_enable_pri(struct pci_dev *pdev, u32 reqs); +void pci_disable_pri(struct pci_dev *pdev); +bool pci_pri_enabled(struct pci_dev *pdev); +int pci_reset_pri(struct pci_dev *pdev); +bool pci_pri_stopped(struct pci_dev *pdev); +int pci_pri_status(struct pci_dev *pdev); #else /* CONFIG_PCI_PRI */ @@ -95,10 +95,10 @@ static inline int pci_pri_status(struct pci_dev *pdev) #ifdef CONFIG_PCI_PASID -extern int pci_enable_pasid(struct pci_dev *pdev, int features); -extern void pci_disable_pasid(struct pci_dev *pdev); -extern int pci_pasid_features(struct pci_dev *pdev); -extern int pci_max_pasids(struct pci_dev *pdev); +int pci_enable_pasid(struct pci_dev *pdev, int features); +void pci_disable_pasid(struct pci_dev *pdev); +int pci_pasid_features(struct pci_dev *pdev); +int pci_max_pasids(struct pci_dev *pdev); #else /* CONFIG_PCI_PASID */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 2461033a7987..614512bed7b0 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -348,7 +348,7 @@ static inline struct pci_dev *pci_physfn(struct pci_dev *dev) return dev; } -extern struct pci_dev *alloc_pci_dev(void); +struct pci_dev *alloc_pci_dev(void); #define to_pci_dev(n) container_of(n, struct pci_dev, dev) #define for_each_pci_dev(d) while ((d = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, d)) != NULL) @@ -504,10 +504,10 @@ struct pci_ops { * ACPI needs to be able to access PCI config space before we've done a * PCI bus scan and created pci_bus structures. */ -extern int raw_pci_read(unsigned int domain, unsigned int bus, - unsigned int devfn, int reg, int len, u32 *val); -extern int raw_pci_write(unsigned int domain, unsigned int bus, - unsigned int devfn, int reg, int len, u32 val); +int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 *val); +int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, + int reg, int len, u32 val); struct pci_bus_region { resource_size_t start; @@ -658,7 +658,7 @@ struct pci_driver { /* these external functions are only available when PCI support is enabled */ #ifdef CONFIG_PCI -extern void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss); +void pcie_bus_configure_settings(struct pci_bus *bus, u8 smpss); enum pcie_bus_config_types { PCIE_BUS_TUNE_OFF, @@ -675,7 +675,7 @@ extern struct bus_type pci_bus_type; * code, or pci core code. */ extern struct list_head pci_root_buses; /* list of all known PCI buses */ /* Some device drivers need know if pci is initiated */ -extern int no_pci_devices(void); +int no_pci_devices(void); void pcibios_resource_survey_bus(struct pci_bus *bus); void pcibios_fixup_bus(struct pci_bus *); @@ -699,7 +699,7 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res, struct pci_bus_region *region); void pcibios_scan_specific_bus(int busn); -extern struct pci_bus *pci_find_bus(int domain, int busnr); +struct pci_bus *pci_find_bus(int domain, int busnr); void pci_bus_add_devices(const struct pci_bus *bus); struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata); @@ -732,14 +732,14 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev, u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin); int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge); u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp); -extern struct pci_dev *pci_dev_get(struct pci_dev *dev); -extern void pci_dev_put(struct pci_dev *dev); -extern void pci_remove_bus(struct pci_bus *b); -extern void pci_stop_and_remove_bus_device(struct pci_dev *dev); +struct pci_dev *pci_dev_get(struct pci_dev *dev); +void pci_dev_put(struct pci_dev *dev); +void pci_remove_bus(struct pci_bus *b); +void pci_stop_and_remove_bus_device(struct pci_dev *dev); void pci_stop_root_bus(struct pci_bus *bus); void pci_remove_root_bus(struct pci_bus *bus); void pci_setup_cardbus(struct pci_bus *bus); -extern void pci_sort_breadthfirst(void); +void pci_sort_breadthfirst(void); #define dev_is_pci(d) ((d)->bus == &pci_bus_type) #define dev_is_pf(d) ((dev_is_pci(d) ? to_pci_dev(d)->is_physfn : false)) #define dev_num_vf(d) ((dev_is_pci(d) ? pci_num_vf(to_pci_dev(d)) : 0)) @@ -1141,18 +1141,17 @@ static inline int pci_msi_enabled(void) return 0; } #else -extern int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec); -extern int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec); -extern void pci_msi_shutdown(struct pci_dev *dev); -extern void pci_disable_msi(struct pci_dev *dev); -extern int pci_msix_table_size(struct pci_dev *dev); -extern int pci_enable_msix(struct pci_dev *dev, - struct msix_entry *entries, int nvec); -extern void pci_msix_shutdown(struct pci_dev *dev); -extern void pci_disable_msix(struct pci_dev *dev); -extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); -extern void pci_restore_msi_state(struct pci_dev *dev); -extern int pci_msi_enabled(void); +int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec); +int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec); +void pci_msi_shutdown(struct pci_dev *dev); +void pci_disable_msi(struct pci_dev *dev); +int pci_msix_table_size(struct pci_dev *dev); +int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec); +void pci_msix_shutdown(struct pci_dev *dev); +void pci_disable_msix(struct pci_dev *dev); +void msi_remove_pci_irq_vectors(struct pci_dev *dev); +void pci_restore_msi_state(struct pci_dev *dev); +int pci_msi_enabled(void); #endif #ifdef CONFIG_PCIEPORTBUS @@ -1167,8 +1166,8 @@ extern bool pcie_ports_auto; static inline int pcie_aspm_enabled(void) { return 0; } static inline bool pcie_aspm_support_enabled(void) { return false; } #else -extern int pcie_aspm_enabled(void); -extern bool pcie_aspm_support_enabled(void); +int pcie_aspm_enabled(void); +bool pcie_aspm_support_enabled(void); #endif #ifdef CONFIG_PCIEAER @@ -1186,8 +1185,8 @@ static inline void pcie_set_ecrc_checking(struct pci_dev *dev) } static inline void pcie_ecrc_get_policy(char *str) {}; #else -extern void pcie_set_ecrc_checking(struct pci_dev *dev); -extern void pcie_ecrc_get_policy(char *str); +void pcie_set_ecrc_checking(struct pci_dev *dev); +void pcie_ecrc_get_policy(char *str); #endif #define pci_enable_msi(pdev) pci_enable_msi_block(pdev, 1) @@ -1198,9 +1197,9 @@ int ht_create_irq(struct pci_dev *dev, int idx); void ht_destroy_irq(unsigned int irq); #endif /* CONFIG_HT_IRQ */ -extern void pci_cfg_access_lock(struct pci_dev *dev); -extern bool pci_cfg_access_trylock(struct pci_dev *dev); -extern void pci_cfg_access_unlock(struct pci_dev *dev); +void pci_cfg_access_lock(struct pci_dev *dev); +bool pci_cfg_access_trylock(struct pci_dev *dev); +void pci_cfg_access_unlock(struct pci_dev *dev); /* * PCI domain support. Sometimes called PCI segment (eg by ACPI), @@ -1225,7 +1224,7 @@ static inline int pci_proc_domain(struct pci_bus *bus) /* some architectures require additional setup to direct VGA traffic */ typedef int (*arch_set_vga_state_t)(struct pci_dev *pdev, bool decode, unsigned int command_bits, u32 flags); -extern void pci_register_set_vga_state(arch_set_vga_state_t func); +void pci_register_set_vga_state(arch_set_vga_state_t func); #else /* CONFIG_PCI is not enabled */ @@ -1627,8 +1626,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, int pcibios_add_device(struct pci_dev *dev); #ifdef CONFIG_PCI_MMCONFIG -extern void __init pci_mmcfg_early_init(void); -extern void __init pci_mmcfg_late_init(void); +void __init pci_mmcfg_early_init(void); +void __init pci_mmcfg_late_init(void); #else static inline void pci_mmcfg_early_init(void) { } static inline void pci_mmcfg_late_init(void) { } @@ -1639,12 +1638,12 @@ int pci_ext_cfg_avail(void); void __iomem *pci_ioremap_bar(struct pci_dev *pdev, int bar); #ifdef CONFIG_PCI_IOV -extern int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); -extern void pci_disable_sriov(struct pci_dev *dev); -extern irqreturn_t pci_sriov_migration(struct pci_dev *dev); -extern int pci_num_vf(struct pci_dev *dev); -extern int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); -extern int pci_sriov_get_totalvfs(struct pci_dev *dev); +int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn); +void pci_disable_sriov(struct pci_dev *dev); +irqreturn_t pci_sriov_migration(struct pci_dev *dev); +int pci_num_vf(struct pci_dev *dev); +int pci_sriov_set_totalvfs(struct pci_dev *dev, u16 numvfs); +int pci_sriov_get_totalvfs(struct pci_dev *dev); #else static inline int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn) { @@ -1672,8 +1671,8 @@ static inline int pci_sriov_get_totalvfs(struct pci_dev *dev) #endif #if defined(CONFIG_HOTPLUG_PCI) || defined(CONFIG_HOTPLUG_PCI_MODULE) -extern void pci_hp_create_module_link(struct pci_slot *pci_slot); -extern void pci_hp_remove_module_link(struct pci_slot *pci_slot); +void pci_hp_create_module_link(struct pci_slot *pci_slot); +void pci_hp_remove_module_link(struct pci_slot *pci_slot); #endif /** @@ -1817,13 +1816,13 @@ int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off, /* PCI <-> OF binding helpers */ #ifdef CONFIG_OF struct device_node; -extern void pci_set_of_node(struct pci_dev *dev); -extern void pci_release_of_node(struct pci_dev *dev); -extern void pci_set_bus_of_node(struct pci_bus *bus); -extern void pci_release_bus_of_node(struct pci_bus *bus); +void pci_set_of_node(struct pci_dev *dev); +void pci_release_of_node(struct pci_dev *dev); +void pci_set_bus_of_node(struct pci_bus *bus); +void pci_release_bus_of_node(struct pci_bus *bus); /* Arch may override this (weak) */ -extern struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus); +struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus); static inline struct device_node * pci_device_to_OF_node(const struct pci_dev *pdev) diff --git a/include/linux/pci_hotplug.h b/include/linux/pci_hotplug.h index 45fc162cbdc0..8db71dcd6337 100644 --- a/include/linux/pci_hotplug.h +++ b/include/linux/pci_hotplug.h @@ -125,12 +125,12 @@ static inline const char *hotplug_slot_name(const struct hotplug_slot *slot) return pci_slot_name(slot->pci_slot); } -extern int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, - int nr, const char *name, - struct module *owner, const char *mod_name); -extern int pci_hp_deregister(struct hotplug_slot *slot); -extern int __must_check pci_hp_change_slot_info (struct hotplug_slot *slot, - struct hotplug_slot_info *info); +int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *pbus, int nr, + const char *name, struct module *owner, + const char *mod_name); +int pci_hp_deregister(struct hotplug_slot *slot); +int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, + struct hotplug_slot_info *info); /* use a define to avoid include chaining to get THIS_MODULE & friends */ #define pci_hp_register(slot, pbus, devnr, name) \ diff --git a/include/linux/pcieport_if.h b/include/linux/pcieport_if.h index e6f91b1406d8..9572669eea97 100644 --- a/include/linux/pcieport_if.h +++ b/include/linux/pcieport_if.h @@ -62,7 +62,7 @@ struct pcie_port_service_driver { #define to_service_driver(d) \ container_of(d, struct pcie_port_service_driver, driver) -extern int pcie_port_service_register(struct pcie_port_service_driver *new); -extern void pcie_port_service_unregister(struct pcie_port_service_driver *new); +int pcie_port_service_register(struct pcie_port_service_driver *new); +void pcie_port_service_unregister(struct pcie_port_service_driver *new); #endif /* _PCIEPORT_IF_H_ */ From 99369065970e9ea7d1ca489341ed29d1a72ec0b5 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 18:08:44 -0600 Subject: [PATCH 45/63] [SCSI] megaraid_sas: Use correct #define for MSI-X capability Previously we used PCI_MSI_FLAGS to locate a register in the MSI-X capability. This did work because the MSI and MSI-X flags happen to be at the same offsets, but was confusing. PCI_MSIX_FLAGS_ENABLE is already defined in include/uapi/linux/pci_regs.h, so no need to define it again. Signed-off-by: Bjorn Helgaas Acked-by: Adam Radford --- drivers/scsi/megaraid/megaraid_sas.h | 3 --- drivers/scsi/megaraid/megaraid_sas_base.c | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 408d2548a748..684cc343cf09 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -1488,7 +1488,4 @@ struct megasas_mgmt_info { int max_index; }; -#define msi_control_reg(base) (base + PCI_MSI_FLAGS) -#define PCI_MSIX_FLAGS_ENABLE (1 << 15) - #endif /*LSI_MEGARAID_SAS_H */ diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 9d53540207ec..7c90d57b867e 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3984,12 +3984,12 @@ static int megasas_probe_one(struct pci_dev *pdev, if (reset_devices) { pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); if (pos) { - pci_read_config_word(pdev, msi_control_reg(pos), + pci_read_config_word(pdev, pos + PCI_MSIX_FLAGS, &control); if (control & PCI_MSIX_FLAGS_ENABLE) { dev_info(&pdev->dev, "resetting MSI-X\n"); pci_write_config_word(pdev, - msi_control_reg(pos), + pos + PCI_MSIX_FLAGS, control & ~PCI_MSIX_FLAGS_ENABLE); } From 703860ed4e36ded696bd44af6107243fdedfb746 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 16:57:56 -0600 Subject: [PATCH 46/63] PCI: Use u8, not int, for PM capability offset The Power Management Capability (PCI_CAP_ID_PM == 0x01) is defined by PCI and must appear in the 256-byte PCI Configuration Space from 0-0xff. It cannot be in the PCIe Extended Configuration space from 0x100-0xfff, so we only need a u8 to hold its offset. Signed-off-by: Bjorn Helgaas Acked-by: Rafael J. Wysocki --- include/linux/pci.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/linux/pci.h b/include/linux/pci.h index 2461033a7987..9587d4d19279 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -249,8 +249,7 @@ struct pci_dev { pci_power_t current_state; /* Current operating state. In ACPI-speak, this is D0-D3, D0 being fully functional, and D3 being off. */ - int pm_cap; /* PM capability offset in the - configuration space */ + u8 pm_cap; /* PM capability offset */ unsigned int pme_support:5; /* Bitmask of states from which PME# can be generated */ unsigned int pme_interrupt:1; From e375b561817d9ae098cc4296a729fc88924a0159 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 4 Apr 2013 16:54:30 +0000 Subject: [PATCH 47/63] PCI: Cache MSI/MSI-X capability offsets in struct pci_dev The patch caches the MSI and MSI-X capability offset in PCI device (struct pci_dev) so that we needn't read it from the config space upon enabling or disabling MSI or MSI-X interrupts. [bhelgaas: moved pm_cap size change to separate patch] Signed-off-by: Gavin Shan Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 42 +++++++++++++++++++----------------------- include/linux/pci.h | 2 ++ 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 00cc78c7aa04..99befbd99938 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -111,32 +111,26 @@ void default_restore_msi_irqs(struct pci_dev *dev, int irq) } #endif -static void msi_set_enable(struct pci_dev *dev, int pos, int enable) +static void msi_set_enable(struct pci_dev *dev, int enable) { u16 control; - BUG_ON(!pos); - - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); control &= ~PCI_MSI_FLAGS_ENABLE; if (enable) control |= PCI_MSI_FLAGS_ENABLE; - pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); } static void msix_set_enable(struct pci_dev *dev, int enable) { - int pos; u16 control; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (pos) { - pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); - control &= ~PCI_MSIX_FLAGS_ENABLE; - if (enable) - control |= PCI_MSIX_FLAGS_ENABLE; - pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); - } + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); + control &= ~PCI_MSIX_FLAGS_ENABLE; + if (enable) + control |= PCI_MSIX_FLAGS_ENABLE; + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); } static inline __attribute_const__ u32 msi_mask(unsigned x) @@ -402,7 +396,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev) pos = entry->msi_attrib.pos; pci_intx_for_msi(dev, 0); - msi_set_enable(dev, pos, 0); + msi_set_enable(dev, 0); arch_restore_msi_irqs(dev, dev->irq); pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); @@ -557,7 +551,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) unsigned mask; pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - msi_set_enable(dev, pos, 0); /* Disable MSI during set up */ + msi_set_enable(dev, 0); /* Disable MSI during set up */ pci_read_config_word(dev, msi_control_reg(pos), &control); /* MSI Entry Initialization */ @@ -598,7 +592,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) /* Set MSI enabled bits */ pci_intx_for_msi(dev, 0); - msi_set_enable(dev, pos, 1); + msi_set_enable(dev, 1); dev->msi_enabled = 1; dev->irq = entry->irq; @@ -885,7 +879,7 @@ void pci_msi_shutdown(struct pci_dev *dev) desc = list_first_entry(&dev->msi_list, struct msi_desc, list); pos = desc->msi_attrib.pos; - msi_set_enable(dev, pos, 0); + msi_set_enable(dev, 0); pci_intx_for_msi(dev, 1); dev->msi_enabled = 0; @@ -1048,15 +1042,17 @@ EXPORT_SYMBOL(pci_msi_enabled); void pci_msi_init_pci_dev(struct pci_dev *dev) { - int pos; INIT_LIST_HEAD(&dev->msi_list); /* Disable the msi hardware to avoid screaming interrupts * during boot. This is the power on reset default so * usually this should be a noop. */ - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (pos) - msi_set_enable(dev, pos, 0); - msix_set_enable(dev, 0); + dev->msi_cap = pci_find_capability(dev, PCI_CAP_ID_MSI); + if (dev->msi_cap) + msi_set_enable(dev, 0); + + dev->msix_cap = pci_find_capability(dev, PCI_CAP_ID_MSIX); + if (dev->msix_cap) + msix_set_enable(dev, 0); } diff --git a/include/linux/pci.h b/include/linux/pci.h index 9587d4d19279..b73c2460ad57 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -232,6 +232,8 @@ struct pci_dev { u8 revision; /* PCI revision, low byte of class word */ u8 hdr_type; /* PCI header type (`multi' flag masked out) */ u8 pcie_cap; /* PCI-E capability offset */ + u8 msi_cap; /* MSI capability offset */ + u8 msix_cap; /* MSI-X capability offset */ u8 pcie_mpss:3; /* PCI-E Max Payload Size Supported */ u8 rom_base_reg; /* which config register controls the ROM */ u8 pin; /* which interrupt pin this device uses */ From cdf1fd4d906bc8c06510fd3e1d6a073441792792 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 4 Apr 2013 16:54:31 +0000 Subject: [PATCH 48/63] PCI: Remove MSI/MSI-X cap check in pci_msi_check_device() The function pci_msi_check_device() is called while enabling MSI or MSI-X interrupts to make sure the PCI device can support MSI or MSI-X capability. This patch removes the check on MSI or MSI-X capability in the function and lets the caller do the check. Signed-off-by: Gavin Shan Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 99befbd99938..60a4b10fa99c 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -789,9 +789,6 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type) if (ret) return ret; - if (!pci_find_capability(dev, type)) - return -EINVAL; - return 0; } @@ -942,7 +939,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec) int status, nr_entries; int i, j; - if (!entries) + if (!entries || !dev->msix_cap) return -EINVAL; status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSIX); From f465136d7287538cabdcdbf8deb24f99a9f855e4 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 4 Apr 2013 16:54:32 +0000 Subject: [PATCH 49/63] PCI: Use cached MSI cap while enabling MSI interrupts The patch uses the cached MSI capability offset in pci_dev instead of reading it from config space when enabling MSI interrupts. [bhelgaas: removed unrelated msi_control_reg() changes] Signed-off-by: Gavin Shan Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 60a4b10fa99c..0138550dc806 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -546,14 +546,13 @@ out_unroll: static int msi_capability_init(struct pci_dev *dev, int nvec) { struct msi_desc *entry; - int pos, ret; + int ret; u16 control; unsigned mask; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); msi_set_enable(dev, 0); /* Disable MSI during set up */ - pci_read_config_word(dev, msi_control_reg(pos), &control); + pci_read_config_word(dev, msi_control_reg(dev->msi_cap), &control); /* MSI Entry Initialization */ entry = alloc_msi_entry(dev); if (!entry) @@ -564,9 +563,9 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) entry->msi_attrib.entry_nr = 0; entry->msi_attrib.maskbit = is_mask_bit_support(control); entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ - entry->msi_attrib.pos = pos; + entry->msi_attrib.pos = dev->msi_cap; - entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64); + entry->mask_pos = msi_mask_reg(dev->msi_cap, entry->msi_attrib.is_64); /* All MSIs are unmasked by default, Mask them all */ if (entry->msi_attrib.maskbit) pci_read_config_dword(dev, entry->mask_pos, &entry->masked); @@ -807,13 +806,13 @@ static int pci_msi_check_device(struct pci_dev *dev, int nvec, int type) */ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec) { - int status, pos, maxvec; + int status, maxvec; u16 msgctl; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (!pos) + if (!dev->msi_cap) return -EINVAL; - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + + 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; @@ -838,14 +837,13 @@ EXPORT_SYMBOL(pci_enable_msi_block); int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec) { - int ret, pos, nvec; + int ret, nvec; u16 msgctl; - pos = pci_find_capability(dev, PCI_CAP_ID_MSI); - if (!pos) + if (!dev->msi_cap) return -EINVAL; - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl); ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); if (maxvec) From 520fe9dc1b07827d795578037ffd11190767e448 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 4 Apr 2013 16:54:33 +0000 Subject: [PATCH 50/63] PCI: Use cached MSI-X cap while enabling MSI-X The patch uses the cached MSI-X capability offset in pci_dev instead of reading it from config space when enabling MSI-X interrupts. Signed-off-by: Gavin Shan Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 0138550dc806..79d9d045a1b8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -598,14 +598,14 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) return 0; } -static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, - unsigned nr_entries) +static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) { resource_size_t phys_addr; u32 table_offset; u8 bir; - pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); + pci_read_config_dword(dev, + msix_table_offset_reg(dev->msix_cap), &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; phys_addr = pci_resource_start(dev, bir) + table_offset; @@ -613,9 +613,8 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); } -static int msix_setup_entries(struct pci_dev *dev, unsigned pos, - void __iomem *base, struct msix_entry *entries, - int nvec) +static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, + struct msix_entry *entries, int nvec) { struct msi_desc *entry; int i; @@ -635,7 +634,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos, entry->msi_attrib.is_64 = 1; entry->msi_attrib.entry_nr = entries[i].entry; entry->msi_attrib.default_irq = dev->irq; - entry->msi_attrib.pos = pos; + entry->msi_attrib.pos = dev->msix_cap; entry->mask_base = base; list_add_tail(&entry->list, &dev->msi_list); @@ -645,7 +644,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos, } static void msix_program_entries(struct pci_dev *dev, - struct msix_entry *entries) + struct msix_entry *entries) { struct msi_desc *entry; int i = 0; @@ -675,23 +674,22 @@ static void msix_program_entries(struct pci_dev *dev, static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries, int nvec) { - int pos, ret; + int ret; u16 control; void __iomem *base; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); /* Ensure MSI-X is disabled while it is set up */ control &= ~PCI_MSIX_FLAGS_ENABLE; - pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); /* Request & Map MSI-X table region */ - base = msix_map_region(dev, pos, multi_msix_capable(control)); + base = msix_map_region(dev, multi_msix_capable(control)); if (!base) return -ENOMEM; - ret = msix_setup_entries(dev, pos, base, entries, nvec); + ret = msix_setup_entries(dev, base, entries, nvec); if (ret) return ret; @@ -705,7 +703,7 @@ static int msix_capability_init(struct pci_dev *dev, * interrupts coming in before they're fully set up. */ control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE; - pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); msix_program_entries(dev, entries); @@ -720,7 +718,7 @@ static int msix_capability_init(struct pci_dev *dev, dev->msix_enabled = 1; control &= ~PCI_MSIX_FLAGS_MASKALL; - pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); return 0; @@ -906,14 +904,12 @@ EXPORT_SYMBOL(pci_disable_msi); */ int pci_msix_table_size(struct pci_dev *dev) { - int pos; u16 control; - pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); - if (!pos) + if (!dev->msix_cap) return 0; - pci_read_config_word(dev, msi_control_reg(pos), &control); + pci_read_config_word(dev, msi_control_reg(dev->msix_cap), &control); return multi_msix_capable(control); } From 24bc69da32a93edac91b4dfb7806a7fb9c24c625 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:26:23 -0600 Subject: [PATCH 51/63] PCI: Clean up MSI/MSI-X capability #defines This doesn't change any existing symbols, but it puts them in logical order and uses explicit masks instead of shifts, like the rest of the file. It also adds new symbols for PCI_MSIX_TABLE_BIR, PCI_MSIX_TABLE_OFFSET, PCI_MSIX_PBA_BIR, and PCI_MSIX_PBA_OFFSET to replace the mis-named PCI_MSIX_FLAGS_BIRMASK (the BAR index fields are part of the Table and PBA registers, not the flags register). Signed-off-by: Bjorn Helgaas --- include/uapi/linux/pci_regs.h | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h index ebfadc56d1b4..864e324da80d 100644 --- a/include/uapi/linux/pci_regs.h +++ b/include/uapi/linux/pci_regs.h @@ -292,12 +292,12 @@ /* Message Signalled Interrupts registers */ -#define PCI_MSI_FLAGS 2 /* Various flags */ -#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ -#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ -#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ -#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ -#define PCI_MSI_FLAGS_MASKBIT 0x100 /* 64-bit mask bits allowed */ +#define PCI_MSI_FLAGS 2 /* Message Control */ +#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */ +#define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */ +#define PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured */ +#define PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */ +#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */ #define PCI_MSI_RFU 3 /* Rest of capability flags */ #define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ #define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ @@ -309,13 +309,17 @@ #define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */ /* MSI-X registers */ -#define PCI_MSIX_FLAGS 2 -#define PCI_MSIX_FLAGS_QSIZE 0x7FF -#define PCI_MSIX_FLAGS_ENABLE (1 << 15) -#define PCI_MSIX_FLAGS_MASKALL (1 << 14) -#define PCI_MSIX_TABLE 4 -#define PCI_MSIX_PBA 8 -#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) +#define PCI_MSIX_FLAGS 2 /* Message Control */ +#define PCI_MSIX_FLAGS_QSIZE 0x07FF /* Table size */ +#define PCI_MSIX_FLAGS_MASKALL 0x4000 /* Mask all vectors for this function */ +#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */ +#define PCI_MSIX_TABLE 4 /* Table offset */ +#define PCI_MSIX_TABLE_BIR 0x00000007 /* BAR index */ +#define PCI_MSIX_TABLE_OFFSET 0xfffffff8 /* Offset into specified BAR */ +#define PCI_MSIX_PBA 8 /* Pending Bit Array offset */ +#define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */ +#define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */ +#define PCI_MSIX_FLAGS_BIRMASK (7 << 0) /* deprecated */ #define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */ /* MSI-X entry's format */ From f5322169b4bc931c760c6a14484582a95c39edde Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:34:36 -0600 Subject: [PATCH 52/63] PCI: Use cached MSI/MSI-X offsets from dev, not from msi_desc We always know the type (MSI vs MSI-X), so we can use the correct cached capability offset rather than relying on the copy in the msi_attrib. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 79d9d045a1b8..631249ea394c 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -241,7 +241,7 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) msg->data = readl(base + PCI_MSIX_ENTRY_DATA); } else { struct pci_dev *dev = entry->dev; - int pos = entry->msi_attrib.pos; + int pos = dev->msi_cap; u16 data; pci_read_config_dword(dev, msi_lower_address_reg(pos), @@ -296,7 +296,7 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) writel(msg->data, base + PCI_MSIX_ENTRY_DATA); } else { struct pci_dev *dev = entry->dev; - int pos = entry->msi_attrib.pos; + int pos = dev->msi_cap; u16 msgctl; pci_read_config_word(dev, msi_control_reg(pos), &msgctl); @@ -385,7 +385,6 @@ static void pci_intx_for_msi(struct pci_dev *dev, int enable) static void __pci_restore_msi_state(struct pci_dev *dev) { - int pos; u16 control; struct msi_desc *entry; @@ -393,22 +392,20 @@ static void __pci_restore_msi_state(struct pci_dev *dev) return; entry = irq_get_msi_desc(dev->irq); - pos = entry->msi_attrib.pos; pci_intx_for_msi(dev, 0); msi_set_enable(dev, 0); arch_restore_msi_irqs(dev, dev->irq); - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control); + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); msi_mask_irq(entry, msi_capable_mask(control), entry->masked); control &= ~PCI_MSI_FLAGS_QSIZE; control |= (entry->msi_attrib.multiple << 4) | PCI_MSI_FLAGS_ENABLE; - pci_write_config_word(dev, pos + PCI_MSI_FLAGS, control); + pci_write_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, control); } static void __pci_restore_msix_state(struct pci_dev *dev) { - int pos; struct msi_desc *entry; u16 control; @@ -416,13 +413,12 @@ static void __pci_restore_msix_state(struct pci_dev *dev) return; BUG_ON(list_empty(&dev->msi_list)); entry = list_first_entry(&dev->msi_list, struct msi_desc, list); - pos = entry->msi_attrib.pos; - pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); /* route the table */ pci_intx_for_msi(dev, 0); control |= PCI_MSIX_FLAGS_ENABLE | PCI_MSIX_FLAGS_MASKALL; - pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); list_for_each_entry(entry, &dev->msi_list, list) { arch_restore_msi_irqs(dev, entry->irq); @@ -430,7 +426,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) } control &= ~PCI_MSIX_FLAGS_MASKALL; - pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); + pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); } void pci_restore_msi_state(struct pci_dev *dev) @@ -863,21 +859,19 @@ void pci_msi_shutdown(struct pci_dev *dev) struct msi_desc *desc; u32 mask; u16 ctrl; - unsigned pos; if (!pci_msi_enable || !dev || !dev->msi_enabled) return; BUG_ON(list_empty(&dev->msi_list)); desc = list_first_entry(&dev->msi_list, struct msi_desc, list); - pos = desc->msi_attrib.pos; msi_set_enable(dev, 0); pci_intx_for_msi(dev, 1); dev->msi_enabled = 0; /* Return the device with MSI unmasked as initial states */ - pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &ctrl); + 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); From f84ecd285f40012f804173110c10f2caaa23b7ee Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:38:32 -0600 Subject: [PATCH 53/63] PCI: Drop msi_control_reg() macro and use PCI_MSI_FLAGS directly Note the error in pci_msix_table_size() -- we used PCI_MSI_FLAGS to locate the PCI_MSIX_FLAGS word. No actual breakage because PCI_MSI_FLAGS and PCI_MSIX_FLAGS happen to be the same. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 8 ++++---- drivers/pci/msi.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 631249ea394c..b1a60e0a1ee3 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -299,10 +299,10 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) int pos = dev->msi_cap; u16 msgctl; - pci_read_config_word(dev, msi_control_reg(pos), &msgctl); + pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); msgctl &= ~PCI_MSI_FLAGS_QSIZE; msgctl |= entry->msi_attrib.multiple << 4; - pci_write_config_word(dev, msi_control_reg(pos), msgctl); + pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); pci_write_config_dword(dev, msi_lower_address_reg(pos), msg->address_lo); @@ -548,7 +548,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) msi_set_enable(dev, 0); /* Disable MSI during set up */ - pci_read_config_word(dev, msi_control_reg(dev->msi_cap), &control); + pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control); /* MSI Entry Initialization */ entry = alloc_msi_entry(dev); if (!entry) @@ -903,7 +903,7 @@ int pci_msix_table_size(struct pci_dev *dev) if (!dev->msix_cap) return 0; - pci_read_config_word(dev, msi_control_reg(dev->msix_cap), &control); + pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); return multi_msix_capable(control); } diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 65c42f80f23e..6aa7b1903796 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,7 +6,6 @@ #ifndef MSI_H #define MSI_H -#define msi_control_reg(base) (base + PCI_MSI_FLAGS) #define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) #define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) #define msi_data_reg(base, is64bit) \ From 9925ad0cf12675203cf209e1d96ebab19f19c86a Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:39:57 -0600 Subject: [PATCH 54/63] PCI: Drop msi_lower_address_reg() and msi_upper_address_reg() macros msi_lower_address_reg() and msi_upper_address_reg() don't provide any useful abstraction, so drop them. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 16 ++++++++-------- drivers/pci/msi.h | 2 -- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index b1a60e0a1ee3..7011c5d95e5e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -244,11 +244,11 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) int pos = dev->msi_cap; u16 data; - pci_read_config_dword(dev, msi_lower_address_reg(pos), - &msg->address_lo); + pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, + &msg->address_lo); if (entry->msi_attrib.is_64) { - pci_read_config_dword(dev, msi_upper_address_reg(pos), - &msg->address_hi); + pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, + &msg->address_hi); pci_read_config_word(dev, msi_data_reg(pos, 1), &data); } else { msg->address_hi = 0; @@ -304,11 +304,11 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) msgctl |= entry->msi_attrib.multiple << 4; pci_write_config_word(dev, pos + PCI_MSI_FLAGS, msgctl); - pci_write_config_dword(dev, msi_lower_address_reg(pos), - msg->address_lo); + pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_LO, + msg->address_lo); if (entry->msi_attrib.is_64) { - pci_write_config_dword(dev, msi_upper_address_reg(pos), - msg->address_hi); + pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, + msg->address_hi); pci_write_config_word(dev, msi_data_reg(pos, 1), msg->data); } else { diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index 6aa7b1903796..e5b87d60cb95 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,8 +6,6 @@ #ifndef MSI_H #define MSI_H -#define msi_lower_address_reg(base) (base + PCI_MSI_ADDRESS_LO) -#define msi_upper_address_reg(base) (base + PCI_MSI_ADDRESS_HI) #define msi_data_reg(base, is64bit) \ (base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32)) #define msi_mask_reg(base, is64bit) \ From 2f221349366daf074bad07cc670e483cc52ab203 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:41:13 -0600 Subject: [PATCH 55/63] PCI: Drop msi_data_reg() macro msi_data_reg() doesn't provide any useful abstraction, so drop it. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 12 ++++++------ drivers/pci/msi.h | 2 -- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 7011c5d95e5e..1688c26db962 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -249,10 +249,10 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) if (entry->msi_attrib.is_64) { pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, &msg->address_hi); - pci_read_config_word(dev, msi_data_reg(pos, 1), &data); + pci_read_config_word(dev, pos + PCI_MSI_DATA_64, &data); } else { msg->address_hi = 0; - pci_read_config_word(dev, msi_data_reg(pos, 0), &data); + pci_read_config_word(dev, pos + PCI_MSI_DATA_32, &data); } msg->data = data; } @@ -309,11 +309,11 @@ void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) if (entry->msi_attrib.is_64) { pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI, msg->address_hi); - pci_write_config_word(dev, msi_data_reg(pos, 1), - msg->data); + pci_write_config_word(dev, pos + PCI_MSI_DATA_64, + msg->data); } else { - pci_write_config_word(dev, msi_data_reg(pos, 0), - msg->data); + pci_write_config_word(dev, pos + PCI_MSI_DATA_32, + msg->data); } } entry->msg = *msg; diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index e5b87d60cb95..d2c6cd982a21 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -6,8 +6,6 @@ #ifndef MSI_H #define MSI_H -#define msi_data_reg(base, is64bit) \ - (base + ((is64bit == 1) ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32)) #define msi_mask_reg(base, is64bit) \ (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) #define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT)) From 4987ce82056327a43cd58c32adf8a3f255e7d862 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:42:30 -0600 Subject: [PATCH 56/63] PCI: Drop is_64bit_address() and is_mask_bit_support() macros is_64bit_address() and is_mask_bit_support() don't provide any useful abstraction, so drop them. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 4 ++-- drivers/pci/msi.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 1688c26db962..aaaf954ad3a4 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -555,9 +555,9 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) return -ENOMEM; entry->msi_attrib.is_msix = 0; - entry->msi_attrib.is_64 = is_64bit_address(control); + entry->msi_attrib.is_64 = !!(control & PCI_MSI_FLAGS_64BIT); entry->msi_attrib.entry_nr = 0; - entry->msi_attrib.maskbit = is_mask_bit_support(control); + entry->msi_attrib.maskbit = !!(control & PCI_MSI_FLAGS_MASKBIT); entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ entry->msi_attrib.pos = dev->msi_cap; diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index d2c6cd982a21..bc5cd9969062 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -8,8 +8,6 @@ #define msi_mask_reg(base, is64bit) \ (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) -#define is_64bit_address(control) (!!(control & PCI_MSI_FLAGS_64BIT)) -#define is_mask_bit_support(control) (!!(control & PCI_MSI_FLAGS_MASKBIT)) #define msix_table_offset_reg(base) (base + PCI_MSIX_TABLE) #define msix_pba_offset_reg(base) (base + PCI_MSIX_PBA) From 909094c62e21c71c4fd122642512ad05b75fe019 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:43:40 -0600 Subject: [PATCH 57/63] PCI: Drop msix_table_offset_reg() and msix_pba_offset_reg() macros msix_table_offset_reg() is used only once and adds a useless indirection, so just use the table offset directly. msix_pba_offset_reg() is unused, so just delete it. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 4 ++-- drivers/pci/msi.h | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index aaaf954ad3a4..fb07e05a947b 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -600,8 +600,8 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) u32 table_offset; u8 bir; - pci_read_config_dword(dev, - msix_table_offset_reg(dev->msix_cap), &table_offset); + pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE, + &table_offset); bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; phys_addr = pci_resource_start(dev, bir) + table_offset; diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index bc5cd9969062..d76c7b2c993c 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -9,8 +9,6 @@ #define msi_mask_reg(base, is64bit) \ (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) -#define msix_table_offset_reg(base) (base + PCI_MSIX_TABLE) -#define msix_pba_offset_reg(base) (base + PCI_MSIX_PBA) #define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1) #define multi_msix_capable(control) msix_table_size((control)) From 527eee292d2ee69708a20b90049ef49bdeefc882 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:44:48 -0600 Subject: [PATCH 58/63] PCI: Use msix_table_size() directly, drop multi_msix_capable() The users of multi_msix_capable() are really interested in the table size, so just say what we mean. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 7 +++++-- drivers/pci/msi.h | 3 --- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index fb07e05a947b..06c5f6edb150 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -26,6 +26,9 @@ static int pci_msi_enable = 1; +#define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) + + /* Arch hooks */ #ifndef arch_msi_check_device @@ -681,7 +684,7 @@ static int msix_capability_init(struct pci_dev *dev, pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); /* Request & Map MSI-X table region */ - base = msix_map_region(dev, multi_msix_capable(control)); + base = msix_map_region(dev, msix_table_size(control)); if (!base) return -ENOMEM; @@ -904,7 +907,7 @@ int pci_msix_table_size(struct pci_dev *dev) return 0; pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); - return multi_msix_capable(control); + return msix_table_size(control); } /** diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h index d76c7b2c993c..df128309f837 100644 --- a/drivers/pci/msi.h +++ b/drivers/pci/msi.h @@ -9,7 +9,4 @@ #define msi_mask_reg(base, is64bit) \ (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) -#define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1) -#define multi_msix_capable(control) msix_table_size((control)) - #endif /* MSI_H */ From 78b5a310ce0ff22889e1a1af932e5c17b26962ba Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 17:58:47 -0600 Subject: [PATCH 59/63] PCI: Drop msi_mask_reg() and remove drivers/pci/msi.h msi_mask_reg() doesn't provide any useful abstraction, do drop it. Remove the now-empty drivers/pci/msi.h. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 4 ++-- drivers/pci/msi.h | 12 ------------ 2 files changed, 2 insertions(+), 14 deletions(-) delete mode 100644 drivers/pci/msi.h diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 06c5f6edb150..afdc388b9553 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -22,7 +22,6 @@ #include #include "pci.h" -#include "msi.h" static int pci_msi_enable = 1; @@ -564,7 +563,8 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ entry->msi_attrib.pos = dev->msi_cap; - entry->mask_pos = msi_mask_reg(dev->msi_cap, entry->msi_attrib.is_64); + entry->mask_pos = dev->msi_cap + (control & PCI_MSI_FLAGS_64BIT) ? + PCI_MSI_MASK_64 : PCI_MSI_MASK_32; /* All MSIs are unmasked by default, Mask them all */ if (entry->msi_attrib.maskbit) pci_read_config_dword(dev, entry->mask_pos, &entry->masked); diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h deleted file mode 100644 index df128309f837..000000000000 --- a/drivers/pci/msi.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (C) 2003-2004 Intel - * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com) - */ - -#ifndef MSI_H -#define MSI_H - -#define msi_mask_reg(base, is64bit) \ - (base + ((is64bit == 1) ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32)) - -#endif /* MSI_H */ From 4d18760c67af2688a6f9d3f0131dc505e0b9f2c9 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Wed, 17 Apr 2013 18:10:07 -0600 Subject: [PATCH 60/63] PCI: Use PCI_MSIX_TABLE_BIR, not PCI_MSIX_FLAGS_BIRMASK PCI_MSIX_FLAGS_BIRMASK is mis-named because the BIR mask is in the Table Offset register, not the flags ("Message Control" per spec) register. Signed-off-by: Bjorn Helgaas --- drivers/pci/msi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index afdc388b9553..f8a1f39e4f68 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -605,8 +605,8 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE, &table_offset); - bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); - table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; + bir = (u8)(table_offset & PCI_MSIX_TABLE_BIR); + table_offset &= PCI_MSIX_TABLE_OFFSET; phys_addr = pci_resource_start(dev, bir) + table_offset; return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); From 2366d06eb15d3cf21d3b243ff586bcb80896c9f2 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 18 Apr 2013 10:55:46 -0600 Subject: [PATCH 61/63] PCI: Remove "extern" from function declarations We had an inconsistent mix of using and omitting the "extern" keyword on function declarations in header files. This removes them all. Signed-off-by: Bjorn Helgaas --- include/linux/msi.h | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/include/linux/msi.h b/include/linux/msi.h index ce93a341337d..20c2d6dd5d25 100644 --- a/include/linux/msi.h +++ b/include/linux/msi.h @@ -13,14 +13,14 @@ struct msi_msg { /* Helper functions */ struct irq_data; struct msi_desc; -extern void mask_msi_irq(struct irq_data *data); -extern void unmask_msi_irq(struct irq_data *data); -extern void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); -extern void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg); -extern void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); -extern void read_msi_msg(unsigned int irq, struct msi_msg *msg); -extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); -extern void write_msi_msg(unsigned int irq, struct msi_msg *msg); +void mask_msi_irq(struct irq_data *data); +void unmask_msi_irq(struct irq_data *data); +void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg); +void __get_cached_msi_msg(struct msi_desc *entry, struct msi_msg *msg); +void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg); +void read_msi_msg(unsigned int irq, struct msi_msg *msg); +void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg); +void write_msi_msg(unsigned int irq, struct msi_msg *msg); struct msi_desc { struct { @@ -54,9 +54,8 @@ struct msi_desc { */ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc); void arch_teardown_msi_irq(unsigned int irq); -extern int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); -extern void arch_teardown_msi_irqs(struct pci_dev *dev); -extern int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); - +int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type); +void arch_teardown_msi_irqs(struct pci_dev *dev); +int arch_msi_check_device(struct pci_dev* dev, int nvec, int type); #endif /* LINUX_MSI_H */ From 508d1aa602ef0679a9cfc181ce918fbc4a2b3a45 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 18 Apr 2013 12:42:58 -0600 Subject: [PATCH 62/63] vfio-pci: Use PCI_MSIX_TABLE_BIR, not PCI_MSIX_FLAGS_BIRMASK PCI_MSIX_FLAGS_BIRMASK is mis-named because the BIR mask is in the Table Offset register, not the flags ("Message Control" per spec) register. Signed-off-by: Bjorn Helgaas Acked-by: Alex Williamson --- drivers/vfio/pci/vfio_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 8189cb6a86af..10626e825f41 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -78,8 +78,8 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) pci_read_config_word(pdev, msix_pos + PCI_MSIX_FLAGS, &flags); pci_read_config_dword(pdev, msix_pos + PCI_MSIX_TABLE, &table); - vdev->msix_bar = table & PCI_MSIX_FLAGS_BIRMASK; - vdev->msix_offset = table & ~PCI_MSIX_FLAGS_BIRMASK; + vdev->msix_bar = table & PCI_MSIX_TABLE_BIR; + vdev->msix_offset = table & PCI_MSIX_TABLE_OFFSET; vdev->msix_size = ((flags & PCI_MSIX_FLAGS_QSIZE) + 1) * 16; } else vdev->msix_bar = 0xFF; From a9047f24df85b06d3fd443ff76e9993bc127c570 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 18 Apr 2013 15:12:58 -0600 Subject: [PATCH 63/63] vfio-pci: Use cached MSI/MSI-X capabilities We now cache the MSI/MSI-X capability offsets in the struct pci_dev, so no need to find the capabilities again. Signed-off-by: Bjorn Helgaas Acked-by: Alex Williamson --- drivers/vfio/pci/vfio_pci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 10626e825f41..05afe883f038 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -70,7 +70,7 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) pci_write_config_word(pdev, PCI_COMMAND, cmd); } - msix_pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); + msix_pos = pdev->msix_cap; if (msix_pos) { u16 flags; u32 table; @@ -183,7 +183,7 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) u8 pos; u16 flags; - pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSI); + pos = vdev->pdev->msi_cap; if (pos) { pci_read_config_word(vdev->pdev, pos + PCI_MSI_FLAGS, &flags); @@ -194,7 +194,7 @@ static int vfio_pci_get_irq_count(struct vfio_pci_device *vdev, int irq_type) u8 pos; u16 flags; - pos = pci_find_capability(vdev->pdev, PCI_CAP_ID_MSIX); + pos = vdev->pdev->msix_cap; if (pos) { pci_read_config_word(vdev->pdev, pos + PCI_MSIX_FLAGS, &flags);