summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2013-11-01 21:17:16 (GMT)
committerScott Wood <scottwood@freescale.com>2013-11-03 22:47:10 (GMT)
commit31110de40dca4d4aeff4f253b3def948b88fa590 (patch)
tree0d811783836d52f15e37b4244de54f44ed4f93ad /drivers/pci
parentae60d5d27c429b13cf28a09ab8b9d30682433c5a (diff)
parent8bb495e3f02401ee6f76d1b1d77f3ac9f079e376 (diff)
downloadlinux-fsl-qoriq-31110de40dca4d4aeff4f253b3def948b88fa590.tar.xz
Merge tag 'v3.10' into sdk-kernel-3.10
git rebase --continue Linux 3.10 Conflicts: Documentation/virtual/kvm/api.txt arch/ia64/kvm/Makefile arch/powerpc/Kconfig arch/powerpc/Makefile arch/powerpc/boot/dts/b4420qds.dts arch/powerpc/boot/dts/b4860qds.dts arch/powerpc/boot/dts/b4qds.dts arch/powerpc/boot/dts/fsl/b4420si-post.dtsi arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi arch/powerpc/boot/dts/fsl/b4860si-post.dtsi arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi arch/powerpc/boot/dts/fsl/b4si-post.dtsi arch/powerpc/boot/dts/fsl/p1010si-post.dtsi arch/powerpc/boot/dts/fsl/p2041si-post.dtsi arch/powerpc/boot/dts/fsl/p3041si-post.dtsi arch/powerpc/boot/dts/fsl/p4080si-post.dtsi arch/powerpc/boot/dts/fsl/p5020si-post.dtsi arch/powerpc/boot/dts/fsl/p5040si-post.dtsi arch/powerpc/boot/dts/fsl/qonverge-usb2-dr-0.dtsi arch/powerpc/boot/dts/fsl/qoriq-sec5.0-0.dtsi arch/powerpc/boot/dts/fsl/t4240si-post.dtsi arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi arch/powerpc/boot/dts/p1025rdb_36b.dts arch/powerpc/boot/dts/t4240qds.dts arch/powerpc/configs/corenet64_smp_defconfig arch/powerpc/configs/mpc85xx_defconfig arch/powerpc/configs/mpc85xx_smp_defconfig arch/powerpc/include/asm/cputable.h arch/powerpc/include/asm/kvm_host.h arch/powerpc/include/asm/kvm_ppc.h arch/powerpc/include/asm/machdep.h arch/powerpc/include/uapi/asm/kvm.h arch/powerpc/kernel/cpu_setup_fsl_booke.S arch/powerpc/kernel/cputable.c arch/powerpc/kernel/idle.c arch/powerpc/kernel/pci-common.c arch/powerpc/kvm/Kconfig arch/powerpc/kvm/book3s.c arch/powerpc/kvm/booke.c arch/powerpc/kvm/e500.c arch/powerpc/kvm/e500_mmu.c arch/powerpc/kvm/e500_mmu_host.c arch/powerpc/kvm/e500mc.c arch/powerpc/kvm/emulate.c arch/powerpc/kvm/irq.h arch/powerpc/kvm/mpic.c arch/powerpc/kvm/powerpc.c arch/powerpc/mm/tlb_nohash.c arch/powerpc/platforms/85xx/Kconfig arch/powerpc/platforms/85xx/b4_qds.c arch/powerpc/platforms/85xx/t4240_qds.c arch/powerpc/platforms/pseries/smp.c arch/powerpc/sysdev/fsl_85xx_l2ctlr.c arch/powerpc/sysdev/fsl_msi.c arch/powerpc/sysdev/fsl_pci.c arch/powerpc/sysdev/fsl_pci.h arch/powerpc/sysdev/mpic.c arch/x86/kvm/Makefile arch/x86/kvm/x86.c drivers/Kconfig drivers/clk/Kconfig drivers/cpufreq/Makefile drivers/crypto/caam/caamalg.c drivers/crypto/caam/intern.h drivers/crypto/caam/jr.c drivers/crypto/caam/regs.h drivers/infiniband/ulp/ipoib/ipoib_ethtool.c drivers/iommu/Makefile drivers/iommu/amd_iommu.c drivers/iommu/exynos-iommu.c drivers/iommu/intel-iommu.c drivers/iommu/iommu.c drivers/iommu/msm_iommu.c drivers/iommu/omap-iommu.c drivers/iommu/tegra-gart.c drivers/iommu/tegra-smmu.c drivers/misc/Makefile drivers/mmc/card/block.c drivers/mmc/card/queue.c drivers/mmc/core/core.c drivers/mtd/nand/fsl_ifc_nand.c drivers/net/ethernet/3com/3c501.c drivers/net/ethernet/8390/3c503.c drivers/net/ethernet/dec/ewrk3.c drivers/net/ethernet/freescale/fec.c drivers/net/ethernet/freescale/gianfar.c drivers/net/ethernet/freescale/gianfar.h drivers/net/ethernet/i825xx/3c505.c drivers/net/ethernet/i825xx/3c507.c drivers/rtc/rtc-ds3232.c drivers/s390/net/qeth_core_main.c drivers/staging/Kconfig drivers/staging/Makefile drivers/staging/ccg/u_ether.c drivers/usb/gadget/fsl_udc_core.c drivers/usb/otg/fsl_otg.c drivers/vfio/vfio.c drivers/watchdog/Kconfig include/linux/iommu.h include/linux/kvm_host.h include/linux/mmc/sdhci.h include/linux/msi.h include/linux/netdev_features.h include/linux/pci.h include/linux/skbuff.h include/net/ip6_route.h include/net/sch_generic.h include/net/xfrm.h include/uapi/linux/kvm.h net/core/netpoll.c virt/kvm/irqchip.c virt/kvm/kvm_main.c
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/access.c6
-rw-r--r--drivers/pci/bus.c88
-rw-r--r--drivers/pci/hotplug/Kconfig7
-rw-r--r--drivers/pci/hotplug/acpiphp.h49
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c49
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c744
-rw-r--r--drivers/pci/hotplug/cpci_hotplug.h44
-rw-r--r--drivers/pci/hotplug/cpci_hotplug_pci.c29
-rw-r--r--drivers/pci/hotplug/cpqphp.h70
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c57
-rw-r--r--drivers/pci/hotplug/cpqphp_nvram.h12
-rw-r--r--drivers/pci/hotplug/ibmphp.h66
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c15
-rw-r--r--drivers/pci/hotplug/pciehp.h22
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c2
-rw-r--r--drivers/pci/hotplug/pciehp_core.c2
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c44
-rw-r--r--drivers/pci/hotplug/rpadlpar.h8
-rw-r--r--drivers/pci/hotplug/rpaphp.h16
-rw-r--r--drivers/pci/hotplug/s390_pci_hpc.c72
-rw-r--r--drivers/pci/hotplug/sgi_hotplug.c78
-rw-r--r--drivers/pci/hotplug/shpchp.h26
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c36
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c2
-rw-r--r--drivers/pci/iov.c51
-rw-r--r--drivers/pci/msi.c200
-rw-r--r--drivers/pci/msi.h24
-rw-r--r--drivers/pci/pci-acpi.c96
-rw-r--r--drivers/pci/pci-driver.c15
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/pci.c117
-rw-r--r--drivers/pci/pci.h101
-rw-r--r--drivers/pci/pcie/Kconfig2
-rw-r--r--drivers/pci/pcie/aer/aer_inject.c10
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h14
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c9
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c65
-rw-r--r--drivers/pci/pcie/aspm.c8
-rw-r--r--drivers/pci/pcie/pme.c2
-rw-r--r--drivers/pci/pcie/portdrv.h18
-rw-r--r--drivers/pci/pcie/portdrv_acpi.c1
-rw-r--r--drivers/pci/pcie/portdrv_core.c2
-rw-r--r--drivers/pci/pcie/portdrv_pci.c30
-rw-r--r--drivers/pci/probe.c120
-rw-r--r--drivers/pci/proc.c38
-rw-r--r--drivers/pci/quirks.c148
-rw-r--r--drivers/pci/remove.c8
-rw-r--r--drivers/pci/rom.c28
-rw-r--r--drivers/pci/search.c10
-rw-r--r--drivers/pci/setup-bus.c10
-rw-r--r--drivers/pci/setup-res.c2
-rw-r--r--drivers/pci/slot.c7
52 files changed, 1152 insertions, 1530 deletions
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 3af0478..1cc2366 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -472,7 +472,7 @@ EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
static inline int pcie_cap_version(const struct pci_dev *dev)
{
- return dev->pcie_flags_reg & PCI_EXP_FLAGS_VERS;
+ return pcie_caps_reg(dev) & PCI_EXP_FLAGS_VERS;
}
static inline bool pcie_cap_has_devctl(const struct pci_dev *dev)
@@ -497,7 +497,7 @@ static inline bool pcie_cap_has_sltctl(const struct pci_dev *dev)
return pcie_cap_version(dev) > 1 ||
type == PCI_EXP_TYPE_ROOT_PORT ||
(type == PCI_EXP_TYPE_DOWNSTREAM &&
- dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT);
+ pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT);
}
static inline bool pcie_cap_has_rtctl(const struct pci_dev *dev)
@@ -515,7 +515,7 @@ static bool pcie_capability_reg_implemented(struct pci_dev *dev, int pos)
return false;
switch (pos) {
- case PCI_EXP_FLAGS_TYPE:
+ case PCI_EXP_FLAGS:
return true;
case PCI_EXP_DEVCAP:
case PCI_EXP_DEVCTL:
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index ad6a8b6..32e66a6 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -158,69 +158,39 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
return ret;
}
+void __weak pcibios_resource_survey_bus(struct pci_bus *bus) { }
+
/**
- * pci_bus_add_device - add a single device
+ * pci_bus_add_device - start driver for a single device
* @dev: device to add
*
- * This adds a single pci device to the global
- * device list and adds sysfs and procfs entries
+ * This adds add sysfs entries and start device drivers
*/
int pci_bus_add_device(struct pci_dev *dev)
{
int retval;
+ /*
+ * Can not put in pci_device_add yet because resources
+ * are not assigned yet for some devices.
+ */
pci_fixup_device(pci_fixup_final, dev);
-
- retval = pcibios_add_device(dev);
- if (retval)
- return retval;
-
- retval = device_add(&dev->dev);
- if (retval)
- return retval;
-
- dev->is_added = 1;
- pci_proc_attach_device(dev);
pci_create_sysfs_dev_files(dev);
- return 0;
-}
-
-/**
- * pci_bus_add_child - add a child bus
- * @bus: bus to add
- *
- * This adds sysfs entries for a single bus
- */
-int pci_bus_add_child(struct pci_bus *bus)
-{
- int retval;
-
- if (bus->bridge)
- bus->dev.parent = bus->bridge;
-
- retval = device_register(&bus->dev);
- if (retval)
- return retval;
- bus->is_added = 1;
+ dev->match_driver = true;
+ retval = device_attach(&dev->dev);
+ WARN_ON(retval < 0);
- /* Create legacy_io and legacy_mem files for this bus */
- pci_create_legacy_files(bus);
+ dev->is_added = 1;
- return retval;
+ return 0;
}
/**
- * pci_bus_add_devices - insert newly discovered PCI devices
+ * pci_bus_add_devices - start driver for PCI devices
* @bus: bus to check for new devices
*
- * Add newly discovered PCI devices (which are on the bus->devices
- * list) to the global PCI device list, add the sysfs and procfs
- * entries. Where a bridge is found, add the discovered bus to
- * the parents list of child buses, and recurse (breadth-first
- * to be compatible with 2.4)
- *
- * Call hotplug for each new devices.
+ * Start driver for PCI devices and add some sysfs entries.
*/
void pci_bus_add_devices(const struct pci_bus *bus)
{
@@ -234,35 +204,15 @@ void pci_bus_add_devices(const struct pci_bus *bus)
continue;
retval = pci_bus_add_device(dev);
if (retval)
- dev_err(&dev->dev, "Error adding device, continuing\n");
+ dev_err(&dev->dev, "Error adding device (%d)\n",
+ retval);
}
list_for_each_entry(dev, &bus->devices, bus_list) {
BUG_ON(!dev->is_added);
-
child = dev->subordinate;
- /*
- * If there is an unattached subordinate bus, attach
- * it and then scan for unattached PCI devices.
- */
- if (!child)
- continue;
- if (list_empty(&child->node)) {
- down_write(&pci_bus_sem);
- list_add_tail(&child->node, &dev->bus->children);
- up_write(&pci_bus_sem);
- }
- pci_bus_add_devices(child);
-
- /*
- * register the bus with sysfs as the parent is now
- * properly registered.
- */
- if (child->is_added)
- continue;
- retval = pci_bus_add_child(child);
- if (retval)
- dev_err(&dev->dev, "Error adding bus, continuing\n");
+ if (child)
+ pci_bus_add_devices(child);
}
}
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 13e9e63..9fcb87f 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 a1afb5b..6fdd49c 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -73,13 +73,13 @@ 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;
- struct acpiphp_slot *slots;
/* Ejectable PCI-to-PCI bridge (PCI bridge and PCI function) */
struct acpiphp_func *func;
- int type;
int nr_slots;
u32 flags;
@@ -98,7 +98,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) */
@@ -120,7 +120,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;
@@ -146,25 +145,11 @@ struct acpiphp_attention_info
/* PCI bus bridge HID */
#define ACPI_PCI_HOST_HID "PNP0A03"
-/* PCI BRIDGE type */
-#define BRIDGE_TYPE_HOST 0
-#define BRIDGE_TYPE_P2P 1
-
/* 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 */
-#define BRIDGE_HAS_STA (0x00000001)
-#define BRIDGE_HAS_EJ0 (0x00000002)
-#define BRIDGE_HAS_HPP (0x00000004)
-#define BRIDGE_HAS_PS0 (0x00000010)
-#define BRIDGE_HAS_PS1 (0x00000020)
-#define BRIDGE_HAS_PS2 (0x00000040)
-#define BRIDGE_HAS_PS3 (0x00000080)
+#define BRIDGE_HAS_EJ0 (0x00000001)
/* slot flags */
@@ -185,26 +170,24 @@ 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);
-extern int acpiphp_get_num_slots (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;
+extern bool acpiphp_disabled;
#endif /* _ACPIPHP_H */
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index 96316b7..ca81279 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -37,6 +37,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/pci-acpi.h>
#include <linux/pci_hotplug.h>
#include <linux/slab.h>
#include <linux/smp.h>
@@ -48,9 +49,9 @@
#define SLOT_NAME_SIZE 21 /* {_SUN} */
bool acpiphp_debug;
+bool acpiphp_disabled;
/* local variables */
-static int num_slots;
static struct acpiphp_attention_info *attention_info;
#define DRIVER_VERSION "0.5"
@@ -61,7 +62,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);
@@ -272,25 +275,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
return 0;
}
-static int __init init_acpi(void)
-{
- int retval;
-
- /* initialize internal data structure etc. */
- retval = acpiphp_glue_init();
-
- /* read initial number of slots */
- if (!retval) {
- num_slots = acpiphp_get_num_slots();
- if (num_slots == 0) {
- acpiphp_glue_exit();
- retval = -ENODEV;
- }
- }
-
- return retval;
-}
-
/**
* release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free
@@ -371,26 +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 "\n");
-
- if (acpi_pci_disabled)
- return 0;
-
- /* read all the ACPI info from the system */
- return init_acpi();
-}
-
-
-static void __exit acpiphp_exit(void)
-{
- if (acpi_pci_disabled)
- return;
-
- /* deallocate internal data structures etc. */
- acpiphp_glue_exit();
+ info(DRIVER_DESC " version: " DRIVER_VERSION "%s\n",
+ acpiphp_disabled ? ", disabled by user; please report a bug"
+ : "");
}
-
-module_init(acpiphp_init);
-module_exit(acpiphp_exit);
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 3d6d4fd..59df857 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -54,13 +54,16 @@
#include "acpiphp.h"
static LIST_HEAD(bridge_list);
+static DEFINE_MUTEX(bridge_mutex);
#define MY_NAME "acpiphp_glue"
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 hotplug_event_func(acpi_handle handle, u32 type, void *context);
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 +79,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.
@@ -112,7 +148,7 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
static const struct acpi_dock_ops acpiphp_dock_ops = {
- .handler = handle_hotplug_event_func,
+ .handler = hotplug_event_func,
};
/* Check whether the PCI device is managed by native PCIe hotplug driver */
@@ -144,6 +180,20 @@ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
return true;
}
+static void acpiphp_dock_init(void *data)
+{
+ struct acpiphp_func *func = data;
+
+ get_bridge(func->slot->bridge);
+}
+
+static void acpiphp_dock_release(void *data)
+{
+ struct acpiphp_func *func = data;
+
+ put_bridge(func->slot->bridge);
+}
+
/* callback routine to register each ACPI PCI slot object */
static acpi_status
register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
@@ -154,9 +204,10 @@ 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;
if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle))
return AE_OK;
@@ -170,7 +221,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;
@@ -178,7 +229,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;
@@ -207,14 +257,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);
@@ -227,9 +278,9 @@ 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;
-
+ 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,13 +298,13 @@ 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);
- 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
@@ -262,7 +313,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
*/
newfunc->flags &= ~FUNC_HAS_EJ0;
if (register_hotplug_dock_device(handle,
- &acpiphp_dock_ops, newfunc))
+ &acpiphp_dock_ops, newfunc,
+ acpiphp_dock_init, acpiphp_dock_release))
dbg("failed to register dock device\n");
/* we need to be notified when dock events happen
@@ -290,7 +342,9 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
err_exit:
bridge->nr_slots--;
- bridge->slots = slot->next;
+ mutex_lock(&bridge_mutex);
+ list_del(&slot->node);
+ mutex_unlock(&bridge_mutex);
kfree(slot);
kfree(newfunc);
@@ -315,18 +369,22 @@ 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;
}
- /* install notify handler */
- if (bridge->type != BRIDGE_TYPE_HOST) {
+ /* install notify handler for P2P bridges */
+ if (!pci_is_root_bus(bridge->pci_bus)) {
if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
status = acpi_remove_notify_handler(bridge->func->handle,
ACPI_SYSTEM_NOTIFY,
@@ -351,205 +409,58 @@ 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) {
- 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)
+ if (func->handle == handle) {
+ get_bridge(func->slot->bridge);
+ mutex_unlock(&bridge_mutex);
return func;
+ }
}
}
}
+ mutex_unlock(&bridge_mutex);
return NULL;
}
-static inline void config_p2p_bridge_flags(struct acpiphp_bridge *bridge)
-{
- acpi_handle dummy_handle;
-
- if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
- "_STA", &dummy_handle)))
- bridge->flags |= BRIDGE_HAS_STA;
-
- if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
- "_EJ0", &dummy_handle)))
- bridge->flags |= BRIDGE_HAS_EJ0;
-
- if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
- "_PS0", &dummy_handle)))
- bridge->flags |= BRIDGE_HAS_PS0;
-
- if (ACPI_SUCCESS(acpi_get_handle(bridge->handle,
- "_PS3", &dummy_handle)))
- bridge->flags |= BRIDGE_HAS_PS3;
-
- /* is this ejectable p2p bridge? */
- if (bridge->flags & BRIDGE_HAS_EJ0) {
- struct acpiphp_func *func;
-
- 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->type = BRIDGE_TYPE_HOST;
- 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->type = BRIDGE_TYPE_P2P;
- 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_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;
+ 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;
- status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ if (!pci_is_root_bus(bridge->pci_bus)) {
+ status = acpi_remove_notify_handler(handle,
+ ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_bridge);
- if (ACPI_FAILURE(status))
- err("failed to remove notify handler\n");
+ if (ACPI_FAILURE(status))
+ err("failed to remove notify handler\n");
+ }
- if ((bridge->type != BRIDGE_TYPE_HOST) &&
- ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func)) {
+ if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
status = acpi_install_notify_handler(bridge->func->handle,
ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_func,
@@ -558,10 +469,8 @@ 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(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);
@@ -573,66 +482,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);
- slot = next;
}
- /*
- * Only P2P bridges have a pci_dev
- */
- if (bridge->pci_dev)
- put_device(&bridge->pci_bus->dev);
-
- pci_dev_put(bridge->pci_dev);
+ mutex_lock(&bridge_mutex);
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);
- else
- acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_bridge);
+ mutex_unlock(&bridge_mutex);
}
static int power_on_slot(struct acpiphp_slot *slot)
@@ -734,34 +590,24 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
*/
static int acpiphp_bus_add(struct acpiphp_func *func)
{
- acpi_handle phandle;
- struct acpi_device *device, *pdevice;
+ struct acpi_device *device;
int ret_val;
- acpi_get_parent(func->handle, &phandle);
- if (acpi_bus_get_device(phandle, &pdevice)) {
- dbg("no parent device, assuming NULL\n");
- pdevice = NULL;
- }
if (!acpi_bus_get_device(func->handle, &device)) {
dbg("bus exists... trim\n");
/* this shouldn't be in here, so remove
* the bus then re-add it...
*/
- ret_val = acpi_bus_trim(device, 1);
- dbg("acpi_bus_trim return %x\n", ret_val);
+ acpi_bus_trim(device);
}
- ret_val = acpi_bus_add(&device, pdevice, func->handle,
- ACPI_BUS_TYPE_DEVICE);
- if (ret_val) {
- dbg("error adding bus, %x\n",
- -ret_val);
- goto acpiphp_bus_add_out;
- }
- ret_val = acpi_bus_start(device);
+ ret_val = acpi_bus_scan(func->handle);
+ if (!ret_val)
+ ret_val = acpi_bus_get_device(func->handle, &device);
+
+ if (ret_val)
+ dbg("error adding bus, %x\n", -ret_val);
-acpiphp_bus_add_out:
return ret_val;
}
@@ -781,11 +627,8 @@ static int acpiphp_bus_trim(acpi_handle handle)
return retval;
}
- retval = acpi_bus_trim(device, 1);
- if (retval)
- err("cannot remove from acpi list\n");
-
- return retval;
+ acpi_bus_trim(device);
+ return 0;
}
static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
@@ -806,6 +649,30 @@ static void acpiphp_set_acpi_region(struct acpiphp_slot *slot)
}
}
+static void check_hotplug_bridge(struct acpiphp_slot *slot, struct pci_dev *dev)
+{
+ struct acpiphp_func *func;
+
+ if (!dev->subordinate)
+ return;
+
+ /* quirk, or pcie could set it already */
+ if (dev->is_hotplug_bridge)
+ return;
+
+ if (PCI_SLOT(dev->devfn) != slot->device)
+ return;
+
+ list_for_each_entry(func, &slot->funcs, sibling) {
+ if (PCI_FUNC(dev->devfn) == func->function) {
+ /* check if this bridge has ejectable slots */
+ if ((detect_ejectable_slots(func->handle) > 0))
+ dev->is_hotplug_bridge = 1;
+ break;
+ }
+ }
+}
+
/**
* enable_device - enable, configure a slot
* @slot: slot to be enabled
@@ -818,13 +685,15 @@ 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;
- acpi_status status;
+ LIST_HEAD(add_list);
if (slot->flags & SLOT_ENABLED)
goto err_exit;
+ list_for_each_entry(func, &slot->funcs, sibling)
+ acpiphp_bus_add(func);
+
num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));
if (num == 0) {
/* Maybe only part of funcs are added. */
@@ -840,16 +709,17 @@ static int __ref enable_device(struct acpiphp_slot *slot)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
max = pci_scan_bridge(bus, dev, max, pass);
- if (pass && dev->subordinate)
- pci_bus_size_bridges(dev->subordinate);
+ if (pass && dev->subordinate) {
+ check_hotplug_bridge(slot, dev);
+ pcibios_resource_survey_bus(dev->subordinate);
+ __pci_bus_size_bridges(dev->subordinate,
+ &add_list);
+ }
}
}
}
- list_for_each_entry(func, &slot->funcs, sibling)
- acpiphp_bus_add(func);
-
- pci_bus_assign_resources(bus);
+ __pci_bus_assign_resources(bus, &add_list, NULL);
acpiphp_sanitize_bus(bus);
acpiphp_set_hpp_values(bus);
acpiphp_set_acpi_region(slot);
@@ -873,23 +743,11 @@ 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);
}
err_exit:
- return retval;
+ return 0;
}
/* return first device in slot, acquiring a reference on it */
@@ -918,23 +776,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;
-
- /* 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 */
- cleanup_p2p_bridge(func->bridge->handle,
- (u32)1, NULL, NULL);
- func->bridge = NULL;
- }
- }
/*
* enable_device() enumerates all functions in this device via
@@ -953,7 +794,6 @@ static int disable_device(struct acpiphp_slot *slot)
slot->flags &= (~SLOT_ENABLED);
-err_exit:
return 0;
}
@@ -1043,7 +883,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)
@@ -1088,11 +928,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; i<PCI_BRIDGE_RESOURCES; i++) {
struct resource *res = &dev->resource[i];
if ((res->flags & type_mask) && !res->start &&
@@ -1106,73 +946,11 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
}
}
-/* Program resources in newly inserted bridge */
-static int acpiphp_configure_bridge (acpi_handle handle)
-{
- struct pci_bus *bus;
-
- if (acpi_is_root_bridge(handle)) {
- struct acpi_pci_root *root = acpi_pci_find_root(handle);
- bus = root->bus;
- } else {
- struct pci_dev *pdev = acpi_get_pci_dev(handle);
- bus = pdev->subordinate;
- pci_dev_put(pdev);
- }
-
- pci_bus_size_bridges(bus);
- pci_bus_assign_resources(bus);
- acpiphp_sanitize_bus(bus);
- acpiphp_set_hpp_values(bus);
- pci_enable_bridges(bus);
- return 0;
-}
-
-static void handle_bridge_insertion(acpi_handle handle, u32 type)
-{
- struct acpi_device *device, *pdevice;
- acpi_handle phandle;
-
- if ((type != ACPI_NOTIFY_BUS_CHECK) &&
- (type != ACPI_NOTIFY_DEVICE_CHECK)) {
- err("unexpected notification type %d\n", type);
- return;
- }
-
- acpi_get_parent(handle, &phandle);
- if (acpi_bus_get_device(phandle, &pdevice)) {
- dbg("no parent device, assuming NULL\n");
- pdevice = NULL;
- }
- if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {
- err("cannot add bridge to acpi list\n");
- return;
- }
- if (!acpiphp_configure_bridge(handle) &&
- !acpi_bus_start(device))
- add_bridge(handle);
- else
- err("cannot configure and start bridge\n");
-
-}
-
/*
* ACPI event handlers
*/
static acpi_status
-count_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- int *count = (int *)context;
- struct acpiphp_bridge *bridge;
-
- bridge = acpiphp_handle_to_bridge(handle);
- if (bridge)
- (*count)++;
- return AE_OK ;
-}
-
-static acpi_status
check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
struct acpiphp_bridge *bridge;
@@ -1186,36 +964,23 @@ 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 ;
}
-struct acpiphp_hp_work {
- struct work_struct work;
- acpi_handle handle;
- u32 type;
- void *context;
-};
-
-static void alloc_acpiphp_hp_work(acpi_handle handle, u32 type,
- void *context,
- void (*func)(struct work_struct *work))
+void acpiphp_check_host_bridge(acpi_handle handle)
{
- struct acpiphp_hp_work *hp_work;
- int ret;
-
- hp_work = kmalloc(sizeof(*hp_work), GFP_KERNEL);
- if (!hp_work)
- return;
+ struct acpiphp_bridge *bridge;
- hp_work->handle = handle;
- hp_work->type = type;
- hp_work->context = context;
+ bridge = acpiphp_handle_to_bridge(handle);
+ if (bridge) {
+ acpiphp_check_bridge(bridge);
+ put_bridge(bridge);
+ }
- INIT_WORK(&hp_work->work, func);
- ret = queue_work(kacpi_hotplug_wq, &hp_work->work);
- if (!ret)
- kfree(hp_work);
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+ ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
}
static void _handle_hotplug_event_bridge(struct work_struct *work)
@@ -1224,32 +989,16 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
- struct acpi_device *device;
- int num_sub_bridges = 0;
- struct acpiphp_hp_work *hp_work;
+ struct acpi_hp_work *hp_work;
acpi_handle handle;
u32 type;
- hp_work = container_of(work, struct acpiphp_hp_work, work);
+ hp_work = container_of(work, struct acpi_hp_work, work);
handle = hp_work->handle;
type = hp_work->type;
+ bridge = (struct acpiphp_bridge *)hp_work->context;
- if (acpi_bus_get_device(handle, &device)) {
- /* This bridge must have just been physically inserted */
- handle_bridge_insertion(handle, type);
- goto out;
- }
-
- bridge = acpiphp_handle_to_bridge(handle);
- if (type == ACPI_NOTIFY_BUS_CHECK) {
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
- count_sub_bridges, NULL, &num_sub_bridges, NULL);
- }
-
- if (!bridge && !num_sub_bridges) {
- err("cannot get bridge info\n");
- goto out;
- }
+ acpi_scan_lock_acquire();
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
@@ -1257,14 +1006,10 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */
dbg("%s: Bus check notify on %s\n", __func__, objname);
- if (bridge) {
- dbg("%s: re-enumerating slots under %s\n",
- __func__, objname);
- acpiphp_check_bridge(bridge);
- }
- if (num_sub_bridges)
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
- ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
+ dbg("%s: re-enumerating slots under %s\n", __func__, objname);
+ acpiphp_check_bridge(bridge);
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
+ ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
break;
case ACPI_NOTIFY_DEVICE_CHECK:
@@ -1281,8 +1026,7 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */
dbg("%s: Device eject notify on %s\n", __func__, objname);
- if ((bridge->type != BRIDGE_TYPE_HOST) &&
- (bridge->flags & BRIDGE_HAS_EJ0)) {
+ if ((bridge->flags & BRIDGE_HAS_EJ0) && bridge->func) {
struct acpiphp_slot *slot;
slot = bridge->func->slot;
if (!acpiphp_disable_slot(slot))
@@ -1310,8 +1054,9 @@ static void _handle_hotplug_event_bridge(struct work_struct *work)
break;
}
-out:
+ acpi_scan_lock_release();
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
+ put_bridge(bridge);
}
/**
@@ -1325,6 +1070,8 @@ out:
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.
@@ -1333,30 +1080,19 @@ 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.
*/
- alloc_acpiphp_hp_work(handle, type, context,
- _handle_hotplug_event_bridge);
+ get_bridge(bridge);
+ alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_bridge);
}
-static void _handle_hotplug_event_func(struct work_struct *work)
+static void hotplug_event_func(acpi_handle handle, u32 type, void *context)
{
- struct acpiphp_func *func;
+ struct acpiphp_func *func = context;
char objname[64];
struct acpi_buffer buffer = { .length = sizeof(objname),
.pointer = objname };
- struct acpiphp_hp_work *hp_work;
- acpi_handle handle;
- u32 type;
- void *context;
-
- hp_work = container_of(work, struct acpiphp_hp_work, work);
- handle = hp_work->handle;
- type = hp_work->type;
- context = hp_work->context;
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
- func = (struct acpiphp_func *)context;
-
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* bus re-enumerate */
@@ -1386,8 +1122,22 @@ static void _handle_hotplug_event_func(struct work_struct *work)
warn("notify_handler: unknown event type 0x%x for %s\n", type, objname);
break;
}
+}
+
+static void _handle_hotplug_event_func(struct work_struct *work)
+{
+ struct acpi_hp_work *hp_work;
+ struct acpiphp_func *func;
+
+ hp_work = container_of(work, struct acpi_hp_work, work);
+ func = hp_work->context;
+ acpi_scan_lock_acquire();
+
+ hotplug_event_func(hp_work->handle, hp_work->type, func);
+ acpi_scan_lock_release();
kfree(hp_work); /* allocated in handle_hotplug_event_func */
+ put_bridge(func->slot->bridge);
}
/**
@@ -1401,6 +1151,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.
@@ -1409,81 +1161,71 @@ 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.
*/
- alloc_acpiphp_hp_work(handle, type, context,
- _handle_hotplug_event_func);
+ get_bridge(func->slot->bridge);
+ alloc_acpi_hp_work(handle, type, context, _handle_hotplug_event_func);
}
-static acpi_status
-find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
+/*
+ * Create hotplug slots for the PCI bus.
+ * It should always return 0 to avoid skipping following notifiers.
+ */
+void acpiphp_enumerate_slots(struct pci_bus *bus, acpi_handle handle)
{
- int *count = (int *)context;
-
- if (!acpi_is_root_bridge(handle))
- return AE_OK;
-
- (*count)++;
- acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- handle_hotplug_event_bridge, NULL);
-
- return AE_OK ;
-}
+ acpi_handle dummy_handle;
+ struct acpiphp_bridge *bridge;
-static struct acpi_pci_driver acpi_pci_hp_driver = {
- .add = add_bridge,
- .remove = remove_bridge,
-};
+ if (acpiphp_disabled)
+ return;
-/**
- * acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
- */
-int __init acpiphp_glue_init(void)
-{
- int num = 0;
+ if (detect_ejectable_slots(handle) <= 0)
+ return;
- acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
+ bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
+ if (bridge == NULL) {
+ err("out of memory\n");
+ return;
+ }
- if (num <= 0)
- return -1;
- else
- acpi_pci_register_driver(&acpi_pci_hp_driver);
+ INIT_LIST_HEAD(&bridge->slots);
+ kref_init(&bridge->ref);
+ bridge->handle = handle;
+ bridge->pci_dev = pci_dev_get(bus->self);
+ bridge->pci_bus = bus;
- return 0;
-}
+ /*
+ * 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);
+ }
-/**
- * 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)
-{
- acpi_pci_unregister_driver(&acpi_pci_hp_driver);
+ init_bridge_misc(bridge);
}
-
-/**
- * acpiphp_get_num_slots - count number of slots in a system
- */
-int __init acpiphp_get_num_slots(void)
+/* Destroy hotplug slots associated with the PCI bus */
+void acpiphp_remove_slots(struct pci_bus *bus)
{
- struct acpiphp_bridge *bridge;
- int num_slots = 0;
+ struct acpiphp_bridge *bridge, *tmp;
- list_for_each_entry(bridge, &bridge_list, list) {
- dbg("Bus %04x:%02x has %d slot%s\n",
- pci_domain_nr(bridge->pci_bus),
- bridge->pci_bus->number, bridge->nr_slots,
- bridge->nr_slots == 1 ? "" : "s");
- num_slots += bridge->nr_slots;
- }
+ if (acpiphp_disabled)
+ return;
- dbg("Total %d slots\n", num_slots);
- return num_slots;
+ list_for_each_entry_safe(bridge, tmp, &bridge_list, list)
+ if (bridge->pci_bus == bus) {
+ cleanup_bridge(bridge);
+ put_bridge(bridge);
+ break;
+ }
}
-
/**
* acpiphp_enable_slot - power on slot
* @slot: ACPI PHP slot
@@ -1560,7 +1302,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;
}
diff --git a/drivers/pci/hotplug/cpci_hotplug.h b/drivers/pci/hotplug/cpci_hotplug.h
index 9fff878..1356211 100644
--- a/drivers/pci/hotplug/cpci_hotplug.h
+++ b/drivers/pci/hotplug/cpci_hotplug.h
@@ -75,28 +75,36 @@ 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);
+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/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index dcc75c7..d8add34 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot)
int __ref cpci_configure_slot(struct slot *slot)
{
+ struct pci_dev *dev;
struct pci_bus *parent;
- int fn;
dbg("%s - enter", __func__);
@@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot)
}
parent = slot->dev->bus;
- for (fn = 0; fn < 8; fn++) {
- struct pci_dev *dev;
-
- dev = pci_get_slot(parent,
- PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
- if (!dev)
+ list_for_each_entry(dev, &parent->devices, bus_list)
+ if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
- pci_dev_put(dev);
- }
+
pci_assign_unassigned_bridge_resources(parent->self);
@@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot)
int cpci_unconfigure_slot(struct slot* slot)
{
- int i;
- struct pci_dev *dev;
+ struct pci_dev *dev, *temp;
dbg("%s - enter", __func__);
if (!slot->dev) {
@@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot)
return -ENODEV;
}
- for (i = 0; i < 8; i++) {
- dev = pci_get_slot(slot->bus,
- PCI_DEVFN(PCI_SLOT(slot->devfn), i));
- if (dev) {
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
- }
+ list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn))
+ continue;
+ pci_dev_get(dev);
+ pci_stop_and_remove_bus_device(dev);
+ pci_dev_put(dev);
}
pci_dev_put(slot->dev);
slot->dev = NULL;
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index d8ffc73..516b877 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_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 36112fe..d282019 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -1900,8 +1900,7 @@ static void interrupt_event_handler(struct controller *ctrl)
dbg("power fault\n");
} else {
/* refresh notification */
- if (p_slot)
- update_slot_info(ctrl, p_slot);
+ update_slot_info(ctrl, p_slot);
}
ctrl->event_queue[loop].event_type = 0;
@@ -2520,44 +2519,28 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
/* If we have IO resources copy them and fill in the bridge's
* IO range registers */
- if (io_node) {
- memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
- io_node->next = NULL;
+ memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
+ io_node->next = NULL;
- /* set IO base and Limit registers */
- temp_byte = io_node->base >> 8;
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
+ /* set IO base and Limit registers */
+ temp_byte = io_node->base >> 8;
+ rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte);
- temp_byte = (io_node->base + io_node->length - 1) >> 8;
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
- } else {
- kfree(hold_IO_node);
- hold_IO_node = NULL;
- }
-
- /* If we have memory resources copy them and fill in the
- * bridge's memory range registers. Otherwise, fill in the
- * range registers with values that disable them. */
- if (mem_node) {
- memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
- mem_node->next = NULL;
-
- /* set Mem base and Limit registers */
- temp_word = mem_node->base >> 16;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+ temp_byte = (io_node->base + io_node->length - 1) >> 8;
+ rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
- temp_word = (mem_node->base + mem_node->length - 1) >> 16;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
+ /* Copy the memory resources and fill in the bridge's memory
+ * range registers.
+ */
+ memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource));
+ mem_node->next = NULL;
- temp_word = 0x0000;
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
+ /* set Mem base and Limit registers */
+ temp_word = mem_node->base >> 16;
+ rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
- kfree(hold_mem_node);
- hold_mem_node = NULL;
- }
+ temp_word = (mem_node->base + mem_node->length - 1) >> 16;
+ rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource));
p_mem_node->next = NULL;
@@ -2627,7 +2610,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
/* Return unused bus resources
* First use the temporary node to store information for
* the board */
- if (hold_bus_node && bus_node && temp_resources.bus_head) {
+ if (bus_node && temp_resources.bus_head) {
hold_bus_node->length = bus_node->base - hold_bus_node->base;
hold_bus_node->next = func->bus_head;
@@ -2751,7 +2734,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func
}
/* If we have prefetchable memory space available and there
* is some left at the end, return the unused portion */
- if (hold_p_mem_node && temp_resources.p_mem_head) {
+ if (temp_resources.p_mem_head) {
p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
&hold_p_mem_node, 0x100000);
diff --git a/drivers/pci/hotplug/cpqphp_nvram.h b/drivers/pci/hotplug/cpqphp_nvram.h
index e89c070..34e4e54 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 a8d391a..8c5b258 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/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 202f4a9..ec20f74 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -41,6 +41,7 @@
#include <linux/pci_hotplug.h>
#include <asm/uaccess.h>
#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) \
@@ -524,13 +517,11 @@ 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)
{
- 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/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 2c113de..7fb3269 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 <acpi/acpi_bus.h>
#include <linux/pci-acpi.h>
-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/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 24d709b..ead7c53 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++;
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 939bd1d..7d72c5e 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -293,7 +293,6 @@ static void pciehp_remove(struct pcie_device *dev)
#ifdef CONFIG_PM
static int pciehp_suspend (struct pcie_device *dev)
{
- dev_info(&dev->device, "%s ENTRY\n", __func__);
return 0;
}
@@ -303,7 +302,6 @@ static int pciehp_resume (struct pcie_device *dev)
struct slot *slot;
u8 status;
- dev_info(&dev->device, "%s ENTRY\n", __func__);
ctrl = get_service_data(dev);
/* reinitialize the chipset's event detection logic */
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index 09cecaf..aac7a40 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot)
struct pci_dev *dev;
struct pci_dev *bridge = p_slot->ctrl->pcie->port;
struct pci_bus *parent = bridge->subordinate;
- int num, fn;
+ int num;
struct controller *ctrl = p_slot->ctrl;
dev = pci_get_slot(parent, PCI_DEVFN(0, 0));
@@ -57,28 +57,18 @@ int pciehp_configure_device(struct slot *p_slot)
return -ENODEV;
}
- for (fn = 0; fn < 8; fn++) {
- dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
- if (!dev)
- continue;
+ list_for_each_entry(dev, &parent->devices, bus_list)
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
- pci_dev_put(dev);
- }
pci_assign_unassigned_bridge_resources(bridge);
- for (fn = 0; fn < 8; fn++) {
- dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
- if (!dev)
+ list_for_each_entry(dev, &parent->devices, bus_list) {
+ if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
continue;
- if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- pci_dev_put(dev);
- continue;
- }
+
pci_configure_slot(dev);
- pci_dev_put(dev);
}
pci_bus_add_devices(parent);
@@ -89,9 +79,9 @@ int pciehp_configure_device(struct slot *p_slot)
int pciehp_unconfigure_device(struct slot *p_slot)
{
int ret, rc = 0;
- int j;
u8 bctl = 0;
u8 presence = 0;
+ struct pci_dev *dev, *temp;
struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate;
u16 command;
struct controller *ctrl = p_slot->ctrl;
@@ -102,33 +92,31 @@ int pciehp_unconfigure_device(struct slot *p_slot)
if (ret)
presence = 0;
- for (j = 0; j < 8; j++) {
- struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j));
- if (!temp)
- continue;
- if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
- pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+ list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
+ pci_dev_get(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+ pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
ctrl_err(ctrl,
"Cannot remove display device %s\n",
- pci_name(temp));
- pci_dev_put(temp);
+ pci_name(dev));
+ pci_dev_put(dev);
rc = -EINVAL;
break;
}
}
- pci_stop_and_remove_bus_device(temp);
+ pci_stop_and_remove_bus_device(dev);
/*
* Ensure that no new Requests will be generated from
* the device.
*/
if (presence) {
- pci_read_config_word(temp, PCI_COMMAND, &command);
+ pci_read_config_word(dev, PCI_COMMAND, &command);
command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
command |= PCI_COMMAND_INTX_DISABLE;
- pci_write_config_word(temp, PCI_COMMAND, command);
+ pci_write_config_word(dev, PCI_COMMAND, command);
}
- pci_dev_put(temp);
+ pci_dev_put(dev);
}
return rc;
diff --git a/drivers/pci/hotplug/rpadlpar.h b/drivers/pci/hotplug/rpadlpar.h
index 4a0a59b..81df939 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 df56774..3135856 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/s390_pci_hpc.c b/drivers/pci/hotplug/s390_pci_hpc.c
index dee68e0..46a7b73 100644
--- a/drivers/pci/hotplug/s390_pci_hpc.c
+++ b/drivers/pci/hotplug/s390_pci_hpc.c
@@ -16,6 +16,7 @@
#include <linux/pci.h>
#include <linux/pci_hotplug.h>
#include <linux/init.h>
+#include <asm/pci_debug.h>
#include <asm/sclp.h>
#define SLOT_NAME_SIZE 10
@@ -49,6 +50,7 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
return -EIO;
rc = sclp_pci_configure(slot->zdev->fid);
+ zpci_dbg(3, "conf fid:%x, rc:%d\n", slot->zdev->fid, rc);
if (!rc) {
slot->zdev->state = ZPCI_FN_STATE_CONFIGURED;
/* automatically scan the device after is was configured */
@@ -66,16 +68,16 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
if (!zpci_fn_configured(slot->zdev->state))
return -EIO;
+ rc = zpci_disable_device(slot->zdev);
+ if (rc)
+ return rc;
/* TODO: we rely on the user to unbind/remove the device, is that plausible
* or do we need to trigger that here?
*/
rc = sclp_pci_deconfigure(slot->zdev->fid);
- if (!rc) {
- /* Fixme: better call List-PCI to find the disabled FH
- for the FID since the FH should be opaque... */
- slot->zdev->fh &= 0x7fffffff;
+ zpci_dbg(3, "deconf fid:%x, rc:%d\n", slot->zdev->fid, rc);
+ if (!rc)
slot->zdev->state = ZPCI_FN_STATE_STANDBY;
- }
return rc;
}
@@ -172,25 +174,6 @@ error:
return -ENOMEM;
}
-static int __init init_pci_slots(void)
-{
- struct zpci_dev *zdev;
- int device = 0;
-
- /*
- * Create a structure for each slot, and register that slot
- * with the pci_hotplug subsystem.
- */
- mutex_lock(&zpci_list_lock);
- list_for_each_entry(zdev, &zpci_list, entry) {
- init_pci_slot(zdev);
- device++;
- }
-
- mutex_unlock(&zpci_list_lock);
- return (device) ? 0 : -ENODEV;
-}
-
static void exit_pci_slot(struct zpci_dev *zdev)
{
struct list_head *tmp, *n;
@@ -205,6 +188,26 @@ static void exit_pci_slot(struct zpci_dev *zdev)
}
}
+static struct pci_hp_callback_ops hp_ops = {
+ .create_slot = init_pci_slot,
+ .remove_slot = exit_pci_slot,
+};
+
+static void __init init_pci_slots(void)
+{
+ struct zpci_dev *zdev;
+
+ /*
+ * Create a structure for each slot, and register that slot
+ * with the pci_hotplug subsystem.
+ */
+ mutex_lock(&zpci_list_lock);
+ list_for_each_entry(zdev, &zpci_list, entry) {
+ init_pci_slot(zdev);
+ }
+ mutex_unlock(&zpci_list_lock);
+}
+
static void __exit exit_pci_slots(void)
{
struct list_head *tmp, *n;
@@ -224,28 +227,19 @@ static void __exit exit_pci_slots(void)
static int __init pci_hotplug_s390_init(void)
{
- /*
- * Do specific initialization stuff for your driver here
- * like initializing your controller hardware (if any) and
- * determining the number of slots you have in the system
- * right now.
- */
-
- if (!pci_probe)
+ if (!s390_pci_probe)
return -EOPNOTSUPP;
- /* register callbacks for slot handling from arch code */
- mutex_lock(&zpci_list_lock);
- hotplug_ops.create_slot = init_pci_slot;
- hotplug_ops.remove_slot = exit_pci_slot;
- mutex_unlock(&zpci_list_lock);
- pr_info("registered hotplug slot callbacks\n");
- return init_pci_slots();
+ zpci_register_hp_ops(&hp_ops);
+ init_pci_slots();
+
+ return 0;
}
static void __exit pci_hotplug_s390_exit(void)
{
exit_pci_slots();
+ zpci_deregister_hp_ops();
}
module_init(pci_hotplug_s390_init);
diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c
index f64ca92..b2781df 100644
--- a/drivers/pci/hotplug/sgi_hotplug.c
+++ b/drivers/pci/hotplug/sgi_hotplug.c
@@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
struct slot *slot = bss_hotplug_slot->private;
struct pci_bus *new_bus = NULL;
struct pci_dev *dev;
- int func, num_funcs;
+ int num_funcs;
int new_ppb = 0;
int rc;
char *ssdt = NULL;
@@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
* to the Linux PCI interface and tell the drivers
* about them.
*/
- for (func = 0; func < num_funcs; func++) {
- dev = pci_get_slot(slot->pci_bus,
- PCI_DEVFN(slot->device_num + 1,
- PCI_FUNC(func)));
- if (dev) {
- /* Need to do slot fixup on PPB before fixup of children
- * (PPB's pcidev_info needs to be in pcidev_info list
- * before child's SN_PCIDEV_INFO() call to setup
- * pdi_host_pcidev_info).
- */
- pcibios_fixup_device_resources(dev);
- if (SN_ACPI_BASE_SUPPORT())
- sn_acpi_slot_fixup(dev);
- else
- sn_io_slot_fixup(dev);
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_hp_add_bridge(dev);
- if (dev->subordinate) {
- new_bus = dev->subordinate;
- new_ppb = 1;
- }
+ list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
+ continue;
+
+ /* Need to do slot fixup on PPB before fixup of children
+ * (PPB's pcidev_info needs to be in pcidev_info list
+ * before child's SN_PCIDEV_INFO() call to setup
+ * pdi_host_pcidev_info).
+ */
+ pcibios_fixup_device_resources(dev);
+ if (SN_ACPI_BASE_SUPPORT())
+ sn_acpi_slot_fixup(dev);
+ else
+ sn_io_slot_fixup(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_hp_add_bridge(dev);
+ if (dev->subordinate) {
+ new_bus = dev->subordinate;
+ new_ppb = 1;
}
- pci_dev_put(dev);
}
}
@@ -412,7 +409,6 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
if (SN_ACPI_BASE_SUPPORT() && ssdt) {
unsigned long long adr;
struct acpi_device *pdevice;
- struct acpi_device *device;
acpi_handle phandle;
acpi_handle chandle = NULL;
acpi_handle rethandle;
@@ -426,6 +422,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
pdevice = NULL;
}
+ acpi_scan_lock_acquire();
/*
* Walk the rootbus node's immediate children looking for
* the slot's device node(s). There can be more than
@@ -448,20 +445,18 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
if (ACPI_SUCCESS(ret) &&
(adr>>16) == (slot->device_num + 1)) {
- ret = acpi_bus_add(&device, pdevice, chandle,
- ACPI_BUS_TYPE_DEVICE);
+ ret = acpi_bus_scan(chandle);
if (ACPI_FAILURE(ret)) {
- printk(KERN_ERR "%s: acpi_bus_add "
+ printk(KERN_ERR "%s: acpi_bus_scan "
"failed (0x%x) for slot %d "
"func %d\n", __func__,
ret, (int)(adr>>16),
(int)(adr&0xffff));
/* try to continue on */
- } else {
- acpi_bus_start(device);
}
}
}
+ acpi_scan_lock_release();
}
/* Call the driver for the new device */
@@ -485,8 +480,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
{
struct slot *slot = bss_hotplug_slot->private;
- struct pci_dev *dev;
- int func;
+ struct pci_dev *dev, *temp;
int rc;
acpi_owner_id ssdt_id = 0;
@@ -512,6 +506,7 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
/* Get the rootbus node pointer */
phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
+ acpi_scan_lock_acquire();
/*
* Walk the rootbus node's immediate children looking for
* the slot's device node(s). There can be more than
@@ -539,22 +534,21 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot)
ret = acpi_bus_get_device(chandle,
&device);
if (ACPI_SUCCESS(ret))
- acpi_bus_trim(device, 1);
+ acpi_bus_trim(device);
}
}
-
+ acpi_scan_lock_release();
}
/* Free the SN resources assigned to the Linux device.*/
- for (func = 0; func < 8; func++) {
- dev = pci_get_slot(slot->pci_bus,
- PCI_DEVFN(slot->device_num + 1,
- PCI_FUNC(func)));
- if (dev) {
- sn_bus_free_data(dev);
- pci_stop_and_remove_bus_device(dev);
- pci_dev_put(dev);
- }
+ list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != slot->device_num + 1)
+ continue;
+
+ pci_dev_get(dev);
+ sn_bus_free_data(dev);
+ pci_stop_and_remove_bus_device(dev);
+ pci_dev_put(dev);
}
/* Remove the SSDT for the slot from the ACPI namespace */
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index b849f995..e260f20 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/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index c627ed9..b0e8313 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot)
struct controller *ctrl = p_slot->ctrl;
struct pci_dev *bridge = ctrl->pci_dev;
struct pci_bus *parent = bridge->subordinate;
- int num, fn;
+ int num;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) {
@@ -57,24 +57,20 @@ int __ref shpchp_configure_device(struct slot *p_slot)
return -ENODEV;
}
- for (fn = 0; fn < 8; fn++) {
- dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
- if (!dev)
+ list_for_each_entry(dev, &parent->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pci_hp_add_bridge(dev);
- pci_dev_put(dev);
}
pci_assign_unassigned_bridge_resources(bridge);
- for (fn = 0; fn < 8; fn++) {
- dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
- if (!dev)
+ list_for_each_entry(dev, &parent->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
pci_configure_slot(dev);
- pci_dev_put(dev);
}
pci_bus_add_devices(parent);
@@ -85,32 +81,32 @@ int __ref shpchp_configure_device(struct slot *p_slot)
int shpchp_unconfigure_device(struct slot *p_slot)
{
int rc = 0;
- int j;
u8 bctl = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ struct pci_dev *dev, *temp;
struct controller *ctrl = p_slot->ctrl;
ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
__func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
- for (j = 0; j < 8 ; j++) {
- struct pci_dev *temp = pci_get_slot(parent,
- (p_slot->device << 3) | j);
- if (!temp)
+ list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
+ if (PCI_SLOT(dev->devfn) != p_slot->device)
continue;
- if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+
+ pci_dev_get(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) {
ctrl_err(ctrl,
"Cannot remove display device %s\n",
- pci_name(temp));
- pci_dev_put(temp);
+ pci_name(dev));
+ pci_dev_put(dev);
rc = -EINVAL;
break;
}
}
- pci_stop_and_remove_bus_device(temp);
- pci_dev_put(temp);
+ pci_stop_and_remove_bus_device(dev);
+ pci_dev_put(dev);
}
return rc;
}
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index eeb23ce..e8c31fe 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);
}
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index c18e5bf..c93071d 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -33,7 +33,6 @@ static inline u8 virtfn_devfn(struct pci_dev *dev, int id)
static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
{
- int rc;
struct pci_bus *child;
if (bus->number == busnr)
@@ -48,12 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
return NULL;
pci_bus_insert_busn_res(child, busnr, busnr);
- child->dev.parent = bus->bridge;
- rc = pci_bus_add_child(child);
- if (rc) {
- pci_remove_bus(child);
- return NULL;
- }
+ bus->is_added = 1;
return child;
}
@@ -123,8 +117,6 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
virtfn->is_virtfn = 1;
rc = pci_bus_add_device(virtfn);
- if (rc)
- goto failed1;
sprintf(buf, "virtfn%u", id);
rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
if (rc)
@@ -737,6 +729,47 @@ int pci_num_vf(struct pci_dev *dev)
EXPORT_SYMBOL_GPL(pci_num_vf);
/**
+ * pci_vfs_assigned - returns number of VFs are assigned to a guest
+ * @dev: the PCI device
+ *
+ * Returns number of VFs belonging to this device that are assigned to a guest.
+ * If device is not a physical function returns -ENODEV.
+ */
+int pci_vfs_assigned(struct pci_dev *dev)
+{
+ struct pci_dev *vfdev;
+ unsigned int vfs_assigned = 0;
+ unsigned short dev_id;
+
+ /* only search if we are a PF */
+ if (!dev->is_physfn)
+ return 0;
+
+ /*
+ * determine the device ID for the VFs, the vendor ID will be the
+ * same as the PF so there is no need to check for that one
+ */
+ pci_read_config_word(dev, dev->sriov->pos + PCI_SRIOV_VF_DID, &dev_id);
+
+ /* loop through all the VFs to see if we own any that are assigned */
+ vfdev = pci_get_device(dev->vendor, dev_id, NULL);
+ while (vfdev) {
+ /*
+ * It is considered assigned if it is a virtual function with
+ * our dev as the physical function and the assigned bit is set
+ */
+ if (vfdev->is_virtfn && (vfdev->physfn == dev) &&
+ (vfdev->dev_flags & PCI_DEV_FLAGS_ASSIGNED))
+ vfs_assigned++;
+
+ vfdev = pci_get_device(dev->vendor, dev_id, vfdev);
+ }
+
+ return vfs_assigned;
+}
+EXPORT_SYMBOL_GPL(pci_vfs_assigned);
+
+/**
* pci_sriov_set_totalvfs -- reduce the TotalVFs available
* @dev: the PCI PF device
* @numvfs: number that should be used for TotalVFs supported
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index e7da2f3..2851387 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -22,10 +22,12 @@
#include <linux/slab.h>
#include "pci.h"
-#include "msi.h"
static int pci_msi_enable = 1;
+#define msix_table_size(flags) ((flags & PCI_MSIX_FLAGS_QSIZE) + 1)
+
+
/* Arch hooks */
#ifndef arch_msi_get_region_count
@@ -125,32 +127,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)
@@ -261,18 +257,18 @@ 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),
- &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_word(dev, msi_data_reg(pos, 1), &data);
+ pci_read_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
+ &msg->address_hi);
+ 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;
}
@@ -316,24 +312,24 @@ 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);
+ 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);
+ 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_word(dev, msi_data_reg(pos, 1),
- msg->data);
+ pci_write_config_dword(dev, pos + PCI_MSI_ADDRESS_HI,
+ msg->address_hi);
+ 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;
@@ -405,7 +401,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;
@@ -413,22 +408,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, pos, 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;
@@ -436,13 +429,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);
@@ -450,7 +442,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)
@@ -498,12 +490,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);
@@ -566,27 +558,29 @@ 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, 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);
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &control);
/* MSI Entry Initialization */
entry = alloc_msi_entry(dev);
if (!entry)
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 = pos;
+ entry->msi_attrib.pos = dev->msi_cap;
- entry->mask_pos = msi_mask_reg(pos, entry->msi_attrib.is_64);
+ if (control & PCI_MSI_FLAGS_64BIT)
+ entry->mask_pos = dev->msi_cap + PCI_MSI_MASK_64;
+ else
+ entry->mask_pos = dev->msi_cap + 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);
@@ -612,31 +606,30 @@ 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;
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);
- bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
- table_offset &= ~PCI_MSIX_FLAGS_BIRMASK;
+ pci_read_config_dword(dev, dev->msix_cap + PCI_MSIX_TABLE,
+ &table_offset);
+ 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);
}
-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;
@@ -656,7 +649,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);
@@ -666,7 +659,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;
@@ -696,23 +689,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, msix_table_size(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;
@@ -726,7 +718,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);
@@ -741,7 +733,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;
@@ -809,9 +801,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;
}
@@ -830,13 +819,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;
@@ -859,26 +848,49 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec)
}
EXPORT_SYMBOL(pci_enable_msi_block);
+int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec)
+{
+ int ret, nvec;
+ u16 msgctl;
+
+ if (!dev->msi_cap)
+ return -EINVAL;
+
+ pci_read_config_word(dev, dev->msi_cap + PCI_MSI_FLAGS, &msgctl);
+ ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1);
+
+ if (maxvec)
+ *maxvec = ret;
+
+ do {
+ nvec = ret;
+ ret = pci_enable_msi_block(dev, nvec);
+ } while (ret > 0);
+
+ if (ret < 0)
+ return ret;
+ return nvec;
+}
+EXPORT_SYMBOL(pci_enable_msi_block_auto);
+
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, pos, 0);
+ 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);
@@ -917,15 +929,13 @@ EXPORT_SYMBOL(msi_get_region);
*/
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);
- return multi_msix_capable(control);
+ pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
+ return msix_table_size(control);
}
/**
@@ -948,7 +958,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);
@@ -1048,15 +1058,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/drivers/pci/msi.h b/drivers/pci/msi.h
deleted file mode 100644
index 65c42f8..0000000
--- a/drivers/pci/msi.h
+++ /dev/null
@@ -1,24 +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_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) \
- (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))
-#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)
-#define msix_table_size(control) ((control & PCI_MSIX_FLAGS_QSIZE)+1)
-#define multi_msix_capable(control) msix_table_size((control))
-
-#endif /* MSI_H */
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 1af4008..e4b1fb2 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -53,14 +53,15 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
return;
}
- if (!pci_dev->pm_cap || !pci_dev->pme_support
- || pci_check_pme_status(pci_dev)) {
- if (pci_dev->pme_poll)
- pci_dev->pme_poll = false;
+ /* Clear PME Status if set. */
+ if (pci_dev->pme_support)
+ pci_check_pme_status(pci_dev);
- pci_wakeup_event(pci_dev);
- pm_runtime_resume(&pci_dev->dev);
- }
+ if (pci_dev->pme_poll)
+ pci_dev->pme_poll = false;
+
+ pci_wakeup_event(pci_dev);
+ pm_runtime_resume(&pci_dev->dev);
if (pci_dev->subordinate)
pci_pme_wakeup_bus(pci_dev->subordinate);
@@ -283,11 +284,36 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
.is_manageable = acpi_pci_power_manageable,
.set_state = acpi_pci_set_power_state,
.choose_state = acpi_pci_choose_state,
- .can_wakeup = acpi_pci_can_wakeup,
.sleep_wake = acpi_pci_sleep_wake,
.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;
+
+ acpi_pci_slot_enumerate(bus, handle);
+ acpiphp_enumerate_slots(bus, handle);
+}
+
+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;
+
+ acpiphp_remove_slots(bus);
+ acpi_pci_slot_remove(bus);
+}
+
/* ACPI bus type */
static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
{
@@ -303,28 +329,46 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
return 0;
}
-static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
+static void pci_acpi_setup(struct device *dev)
{
- int num;
- unsigned int seg, bus;
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ acpi_handle handle = ACPI_HANDLE(dev);
+ struct acpi_device *adev;
- /*
- * The string should be the same as root bridge's name
- * Please look at 'pci_scan_bus_parented'
- */
- num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus);
- if (num != 2)
- return -ENODEV;
- *handle = acpi_get_pci_rootbridge_handle(seg, bus);
- if (!*handle)
- return -ENODEV;
- return 0;
+ if (acpi_bus_get_device(handle, &adev) || !adev->wakeup.flags.valid)
+ return;
+
+ device_set_wakeup_capable(dev, true);
+ acpi_pci_sleep_wake(pci_dev, false);
+
+ pci_acpi_add_pm_notifier(adev, pci_dev);
+ if (adev->wakeup.flags.run_wake)
+ device_set_run_wake(dev, true);
+}
+
+static void pci_acpi_cleanup(struct device *dev)
+{
+ acpi_handle handle = ACPI_HANDLE(dev);
+ struct acpi_device *adev;
+
+ if (!acpi_bus_get_device(handle, &adev) && adev->wakeup.flags.valid) {
+ device_set_wakeup_capable(dev, false);
+ device_set_run_wake(dev, false);
+ pci_acpi_remove_pm_notifier(adev);
+ }
+}
+
+static bool pci_acpi_bus_match(struct device *dev)
+{
+ return dev->bus == &pci_bus_type;
}
static struct acpi_bus_type acpi_pci_bus = {
- .bus = &pci_bus_type,
+ .name = "PCI",
+ .match = pci_acpi_bus_match,
.find_device = acpi_pci_find_device,
- .find_bridge = acpi_pci_find_root_bridge,
+ .setup = pci_acpi_setup,
+ .cleanup = pci_acpi_cleanup,
};
static int __init acpi_pci_init(void)
@@ -344,7 +388,11 @@ 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();
+ acpiphp_init();
+
return 0;
}
arch_initcall(acpi_pci_init);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index f79cbcd..79277fb 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -390,9 +390,10 @@ static void pci_device_shutdown(struct device *dev)
/*
* Turn off Bus Master bit on the device to tell it to not
- * continue to do DMA
+ * continue to do DMA. Don't touch devices in D3cold or unknown states.
*/
- pci_disable_device(pci_dev);
+ if (pci_dev->current_state <= PCI_D3hot)
+ pci_clear_master(pci_dev);
}
#ifdef CONFIG_PM
@@ -628,6 +629,7 @@ static int pci_pm_suspend(struct device *dev)
goto Fixup;
}
+ pci_dev->state_saved = false;
if (pm->suspend) {
pci_power_t prev = pci_dev->current_state;
int error;
@@ -774,6 +776,7 @@ static int pci_pm_freeze(struct device *dev)
return 0;
}
+ pci_dev->state_saved = false;
if (pm->freeze) {
int error;
@@ -862,6 +865,7 @@ static int pci_pm_poweroff(struct device *dev)
goto Fixup;
}
+ pci_dev->state_saved = false;
if (pm->poweroff) {
int error;
@@ -987,6 +991,7 @@ static int pci_pm_runtime_suspend(struct device *dev)
if (!pm || !pm->runtime_suspend)
return -ENOSYS;
+ pci_dev->state_saved = false;
pci_dev->no_d3cold = false;
error = pm->runtime_suspend(dev);
suspend_report_result(pm->runtime_suspend, error);
@@ -1186,9 +1191,13 @@ pci_dev_driver(const struct pci_dev *dev)
static int pci_bus_match(struct device *dev, struct device_driver *drv)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
- struct pci_driver *pci_drv = to_pci_driver(drv);
+ struct pci_driver *pci_drv;
const struct pci_device_id *found_id;
+ if (!pci_dev->match_driver)
+ return 0;
+
+ pci_drv = to_pci_driver(drv);
found_id = pci_match_device(pci_drv, pci_dev);
if (found_id)
return 1;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 9c6e9bb..5b4a9d9 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) ?
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5cb5820..a899d8b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_platform_pm;
int pci_set_platform_pm(struct pci_platform_pm_ops *ops)
{
if (!ops->is_manageable || !ops->set_state || !ops->choose_state
- || !ops->sleep_wake || !ops->can_wakeup)
+ || !ops->sleep_wake)
return -EINVAL;
pci_platform_pm = ops;
return 0;
@@ -473,11 +473,6 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
}
-static inline bool platform_pci_can_wakeup(struct pci_dev *dev)
-{
- return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false;
-}
-
static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
{
return pci_platform_pm ?
@@ -651,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;
}
@@ -847,9 +838,8 @@ static struct pci_cap_saved_state *pci_find_saved_cap(
struct pci_dev *pci_dev, char cap)
{
struct pci_cap_saved_state *tmp;
- struct hlist_node *pos;
- hlist_for_each_entry(tmp, pos, &pci_dev->saved_cap_space, next) {
+ hlist_for_each_entry(tmp, &pci_dev->saved_cap_space, next) {
if (tmp->cap.cap_nr == cap)
return tmp;
}
@@ -1046,7 +1036,6 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev)
struct pci_saved_state *state;
struct pci_cap_saved_state *tmp;
struct pci_cap_saved_data *cap;
- struct hlist_node *pos;
size_t size;
if (!dev->state_saved)
@@ -1054,7 +1043,7 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev)
size = sizeof(*state) + sizeof(struct pci_cap_saved_data);
- hlist_for_each_entry(tmp, pos, &dev->saved_cap_space, next)
+ hlist_for_each_entry(tmp, &dev->saved_cap_space, next)
size += sizeof(struct pci_cap_saved_data) + tmp->cap.size;
state = kzalloc(size, GFP_KERNEL);
@@ -1065,7 +1054,7 @@ struct pci_saved_state *pci_store_saved_state(struct pci_dev *dev)
sizeof(state->config_space));
cap = state->cap;
- hlist_for_each_entry(tmp, pos, &dev->saved_cap_space, next) {
+ hlist_for_each_entry(tmp, &dev->saved_cap_space, next) {
size_t len = sizeof(struct pci_cap_saved_data) + tmp->cap.size;
memcpy(cap, &tmp->cap, len);
cap = (struct pci_cap_saved_data *)((u8 *)cap + len);
@@ -1156,8 +1145,7 @@ int pci_reenable_device(struct pci_dev *dev)
return 0;
}
-static int __pci_enable_device_flags(struct pci_dev *dev,
- resource_size_t flags)
+static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
{
int err;
int i, bars = 0;
@@ -1174,7 +1162,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
}
- if (atomic_add_return(1, &dev->enable_cnt) > 1)
+ if (atomic_inc_return(&dev->enable_cnt) > 1)
return 0; /* already enabled */
/* only skip sriov related */
@@ -1201,7 +1189,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev,
*/
int pci_enable_device_io(struct pci_dev *dev)
{
- return __pci_enable_device_flags(dev, IORESOURCE_IO);
+ return pci_enable_device_flags(dev, IORESOURCE_IO);
}
/**
@@ -1214,7 +1202,7 @@ int pci_enable_device_io(struct pci_dev *dev)
*/
int pci_enable_device_mem(struct pci_dev *dev)
{
- return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+ return pci_enable_device_flags(dev, IORESOURCE_MEM);
}
/**
@@ -1230,7 +1218,7 @@ int pci_enable_device_mem(struct pci_dev *dev)
*/
int pci_enable_device(struct pci_dev *dev)
{
- return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
+ return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
}
/*
@@ -1401,7 +1389,10 @@ pci_disable_device(struct pci_dev *dev)
if (dr)
dr->enabled = 0;
- if (atomic_sub_return(1, &dev->enable_cnt) != 0)
+ dev_WARN_ONCE(&dev->dev, atomic_read(&dev->enable_cnt) <= 0,
+ "disabling already-disabled device");
+
+ if (atomic_dec_return(&dev->enable_cnt) != 0)
return;
do_pci_disable_device(dev);
@@ -1580,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);
@@ -1929,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);
@@ -1980,30 +1972,9 @@ 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;
}
}
-/**
- * platform_pci_wakeup_init - init platform wakeup if present
- * @dev: PCI device
- *
- * Some devices don't have PCI PM caps but can still generate wakeup
- * events through platform methods (like ACPI events). If @dev supports
- * platform wakeup events, set the device flag to indicate as much. This
- * may be redundant if the device also supports PCI PM caps, but double
- * initialization should be safe in that case.
- */
-void platform_pci_wakeup_init(struct pci_dev *dev)
-{
- if (!platform_pci_can_wakeup(dev))
- return;
-
- device_set_wakeup_capable(&dev->dev, true);
- platform_pci_sleep_wake(dev, false);
-}
-
static void pci_add_saved_cap(struct pci_dev *pci_dev,
struct pci_cap_saved_state *new_cap)
{
@@ -2060,17 +2031,20 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev)
void pci_free_cap_save_buffers(struct pci_dev *dev)
{
struct pci_cap_saved_state *tmp;
- struct hlist_node *pos, *n;
+ struct hlist_node *n;
- hlist_for_each_entry_safe(tmp, pos, n, &dev->saved_cap_space, next)
+ hlist_for_each_entry_safe(tmp, n, &dev->saved_cap_space, next)
kfree(tmp);
}
/**
- * pci_enable_ari - enable ARI forwarding if hardware support it
+ * pci_configure_ari - enable or disable ARI forwarding
* @dev: the PCI device
+ *
+ * If @dev and its upstream bridge both support ARI, enable ARI in the
+ * bridge. Otherwise, disable ARI in the bridge.
*/
-void pci_enable_ari(struct pci_dev *dev)
+void pci_configure_ari(struct pci_dev *dev)
{
u32 cap;
struct pci_dev *bridge;
@@ -2078,9 +2052,6 @@ void pci_enable_ari(struct pci_dev *dev)
if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn)
return;
- if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI))
- return;
-
bridge = dev->bus->self;
if (!bridge)
return;
@@ -2089,8 +2060,15 @@ void pci_enable_ari(struct pci_dev *dev)
if (!(cap & PCI_EXP_DEVCAP2_ARI))
return;
- pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI);
- bridge->ari_enabled = 1;
+ if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) {
+ pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
+ PCI_EXP_DEVCTL2_ARI);
+ bridge->ari_enabled = 1;
+ } else {
+ pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2,
+ PCI_EXP_DEVCTL2_ARI);
+ bridge->ari_enabled = 0;
+ }
}
/**
@@ -2636,7 +2614,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;
@@ -3716,7 +3694,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;
@@ -3766,18 +3744,6 @@ resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
return align;
}
-/**
- * pci_is_reassigndev - check if specified PCI is target device to reassign
- * @dev: the PCI device to check
- *
- * RETURNS: non-zero for PCI device is a target device to reassign,
- * or zero is not.
- */
-int pci_is_reassigndev(struct pci_dev *dev)
-{
- return (pci_specified_resource_alignment(dev) != 0);
-}
-
/*
* This function disables memory decoding and releases memory resources
* of the device specified by kernel's boot parameter 'pci=resource_alignment='.
@@ -3792,7 +3758,9 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
resource_size_t align, size;
u16 command;
- if (!pci_is_reassigndev(dev))
+ /* check if specified PCI is target device to reassign */
+ align = pci_specified_resource_alignment(dev);
+ if (!align)
return;
if (dev->hdr_type == PCI_HEADER_TYPE_NORMAL &&
@@ -3808,7 +3776,6 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
command &= ~PCI_COMMAND_MEMORY;
pci_write_config_word(dev, PCI_COMMAND, command);
- align = pci_specified_resource_alignment(dev);
for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
r = &dev->resource[i];
if (!(r->flags & IORESOURCE_MEM))
@@ -3840,7 +3807,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;
@@ -3851,7 +3818,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/pci.h b/drivers/pci/pci.h
index e851829..d1182c4 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/<BDF>/resource<N> */
PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
};
-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);
@@ -43,9 +42,6 @@ int pci_probe_reset_function(struct pci_dev *dev);
* platform; to be used during system-wide transitions from a
* sleeping state to the working state and vice versa
*
- * @can_wakeup: returns 'true' if given device is capable of waking up the
- * system from a sleeping state
- *
* @sleep_wake: enables/disables the system wake up capability of given device
*
* @run_wake: enables/disables the platform to generate run-time wake-up events
@@ -59,23 +55,21 @@ struct pci_platform_pm_ops {
bool (*is_manageable)(struct pci_dev *dev);
int (*set_state)(struct pci_dev *dev, pci_power_t state);
pci_power_t (*choose_state)(struct pci_dev *dev);
- bool (*can_wakeup)(struct pci_dev *dev);
int (*sleep_wake)(struct pci_dev *dev, bool enable);
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 platform_pci_wakeup_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)
@@ -101,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)
@@ -110,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; }
@@ -123,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; }
@@ -139,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) { }
@@ -203,13 +197,17 @@ 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 int pci_bus_add_child(struct pci_bus *bus);
-extern void pci_enable_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);
+void __ref __pci_bus_size_bridges(struct pci_bus *bus,
+ struct list_head *realloc_head);
+void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
+ struct list_head *realloc_head,
+ struct list_head *fail_head);
+
/**
* pci_ari_enabled - query ARI forwarding status
* @bus: the PCI bus
@@ -222,7 +220,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 {
@@ -246,7 +244,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)
{
@@ -254,14 +252,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)
@@ -287,10 +284,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;
@@ -303,7 +300,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;
@@ -312,7 +309,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/Kconfig b/drivers/pci/pcie/Kconfig
index fde4a32..569f82f 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/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 4e24cb8..587e7e8 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;
@@ -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;
}
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index 22f840f..d12c77c 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/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 564d97f..0f4554e 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;
@@ -582,6 +580,7 @@ struct aer_recover_entry
u8 devfn;
u16 domain;
int severity;
+ struct aer_capability_regs *regs;
};
static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
@@ -595,7 +594,7 @@ static DEFINE_SPINLOCK(aer_recover_ring_lock);
static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
- int severity)
+ int severity, struct aer_capability_regs *aer_regs)
{
unsigned long flags;
struct aer_recover_entry entry = {
@@ -603,6 +602,7 @@ void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
.devfn = devfn,
.domain = domain,
.severity = severity,
+ .regs = aer_regs,
};
spin_lock_irqsave(&aer_recover_ring_lock, flags);
@@ -629,6 +629,7 @@ static void aer_recover_work_func(struct work_struct *work)
PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
continue;
}
+ cper_print_aer(pdev, entry.severity, entry.regs);
do_recovery(pdev, entry.severity);
pci_dev_put(pdev);
}
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
index 3ea5173..2c7c9f5 100644
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ b/drivers/pci/pcie/aer/aerdrv_errprint.c
@@ -23,6 +23,9 @@
#include "aerdrv.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/ras.h>
+
#define AER_AGENT_RECEIVER 0
#define AER_AGENT_REQUESTER 1
#define AER_AGENT_COMPLETER 2
@@ -121,12 +124,11 @@ static const char *aer_agent_string[] = {
"Transmitter ID"
};
-static void __aer_print_error(const char *prefix,
+static void __aer_print_error(struct pci_dev *dev,
struct aer_err_info *info)
{
int i, status;
const char *errmsg = NULL;
-
status = (info->status & ~info->mask);
for (i = 0; i < 32; i++) {
@@ -141,26 +143,22 @@ static void __aer_print_error(const char *prefix,
aer_uncorrectable_error_string[i] : NULL;
if (errmsg)
- printk("%s"" [%2d] %-22s%s\n", prefix, i, errmsg,
+ dev_err(&dev->dev, " [%2d] %-22s%s\n", i, errmsg,
info->first_error == i ? " (First)" : "");
else
- printk("%s"" [%2d] Unknown Error Bit%s\n", prefix, i,
- info->first_error == i ? " (First)" : "");
+ dev_err(&dev->dev, " [%2d] Unknown Error Bit%s\n",
+ i, info->first_error == i ? " (First)" : "");
}
}
void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
{
int id = ((dev->bus->number << 8) | dev->devfn);
- char prefix[44];
-
- snprintf(prefix, sizeof(prefix), "%s%s %s: ",
- (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR,
- dev_driver_string(&dev->dev), dev_name(&dev->dev));
if (info->status == 0) {
- printk("%s""PCIe Bus Error: severity=%s, type=Unaccessible, "
- "id=%04x(Unregistered Agent ID)\n", prefix,
+ dev_err(&dev->dev,
+ "PCIe Bus Error: severity=%s, type=Unaccessible, "
+ "id=%04x(Unregistered Agent ID)\n",
aer_error_severity_string[info->severity], id);
} else {
int layer, agent;
@@ -168,22 +166,24 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
layer = AER_GET_LAYER_ERROR(info->severity, info->status);
agent = AER_GET_AGENT(info->severity, info->status);
- printk("%s""PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
- prefix, aer_error_severity_string[info->severity],
+ dev_err(&dev->dev,
+ "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
+ aer_error_severity_string[info->severity],
aer_error_layer[layer], id, aer_agent_string[agent]);
- printk("%s"" device [%04x:%04x] error status/mask=%08x/%08x\n",
- prefix, dev->vendor, dev->device,
+ dev_err(&dev->dev,
+ " device [%04x:%04x] error status/mask=%08x/%08x\n",
+ dev->vendor, dev->device,
info->status, info->mask);
- __aer_print_error(prefix, info);
+ __aer_print_error(dev, info);
if (info->tlp_header_valid) {
unsigned char *tlp = (unsigned char *) &info->tlp;
- printk("%s"" TLP Header:"
+ dev_err(&dev->dev, " TLP Header:"
" %02x%02x%02x%02x %02x%02x%02x%02x"
" %02x%02x%02x%02x %02x%02x%02x%02x\n",
- prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+ *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
*(tlp + 11), *(tlp + 10), *(tlp + 9),
*(tlp + 8), *(tlp + 15), *(tlp + 14),
@@ -192,8 +192,11 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
}
if (info->id && info->error_dev_num > 1 && info->id == id)
- printk("%s"" Error of this Agent(%04x) is reported first\n",
- prefix, id);
+ dev_err(&dev->dev,
+ " Error of this Agent(%04x) is reported first\n",
+ id);
+ trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
+ info->severity);
}
void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
@@ -217,7 +220,7 @@ int cper_severity_to_aer(int cper_severity)
}
EXPORT_SYMBOL_GPL(cper_severity_to_aer);
-void cper_print_aer(const char *prefix, int cper_severity,
+void cper_print_aer(struct pci_dev *dev, int cper_severity,
struct aer_capability_regs *aer)
{
int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
@@ -239,25 +242,27 @@ void cper_print_aer(const char *prefix, int cper_severity,
}
layer = AER_GET_LAYER_ERROR(aer_severity, status);
agent = AER_GET_AGENT(aer_severity, status);
- printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n",
- prefix, status, mask);
- cper_print_bits(prefix, status, status_strs, status_strs_size);
- printk("%s""aer_layer=%s, aer_agent=%s\n", prefix,
+ dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n",
+ status, mask);
+ cper_print_bits("", status, status_strs, status_strs_size);
+ dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n",
aer_error_layer[layer], aer_agent_string[agent]);
if (aer_severity != AER_CORRECTABLE)
- printk("%s""aer_uncor_severity: 0x%08x\n",
- prefix, aer->uncor_severity);
+ dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n",
+ aer->uncor_severity);
if (tlp_header_valid) {
const unsigned char *tlp;
tlp = (const unsigned char *)&aer->header_log;
- printk("%s""aer_tlp_header:"
+ dev_err(&dev->dev, "aer_tlp_header:"
" %02x%02x%02x%02x %02x%02x%02x%02x"
" %02x%02x%02x%02x %02x%02x%02x%02x\n",
- prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+ *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
*(tlp + 11), *(tlp + 10), *(tlp + 9),
*(tlp + 8), *(tlp + 15), *(tlp + 14),
*(tlp + 13), *(tlp + 12));
}
+ trace_aer_event(dev_name(&dev->dev), (status & ~mask),
+ aer_severity);
}
#endif
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 8474b6a..d320df6 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -556,6 +556,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
struct pcie_link_state *link;
int blacklist = !!pcie_aspm_sanity_check(pdev);
+ if (!aspm_support_enabled)
+ return;
+
if (!pci_is_pcie(pdev) || pdev->link_state)
return;
if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT &&
@@ -634,10 +637,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link;
- if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
- return;
- if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) &&
- (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM))
+ if (!parent || !parent->link_state)
return;
down_read(&pci_bus_sem);
diff --git a/drivers/pci/pcie/pme.c b/drivers/pci/pcie/pme.c
index 9ca0dc9..795db1f 100644
--- a/drivers/pci/pcie/pme.c
+++ b/drivers/pci/pcie/pme.c
@@ -19,8 +19,6 @@
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/pcieport_if.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
#include <linux/pm_runtime.h>
#include "../pci.h"
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index eea2ca2..d2eb80a 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/drivers/pci/pcie/portdrv_acpi.c b/drivers/pci/pcie/portdrv_acpi.c
index a86b56e..b4d2894 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.
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index b42133a..31063ac 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -272,7 +272,7 @@ static int get_port_device_capability(struct pci_dev *dev)
/* Hot-Plug Capable */
if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
- dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
+ pcie_caps_reg(dev) & PCI_EXP_FLAGS_SLOT) {
pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
if (reg32 & PCI_EXP_SLTCAP_HPC) {
services |= PCIE_PORT_SERVICE_HP;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index 08c243a..696caed 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -185,14 +185,6 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
#endif /* !PM */
/*
- * PCIe port runtime suspend is broken for some chipsets, so use a
- * black list to disable runtime PM for these chipsets.
- */
-static const struct pci_device_id port_runtime_pm_black_list[] = {
- { /* end: all zeroes */ }
-};
-
-/*
* pcie_portdrv_probe - Probe PCI-Express port devices
* @dev: PCI-Express port device being probed
*
@@ -225,16 +217,11 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
* it by default.
*/
dev->d3cold_allowed = false;
- if (!pci_match_id(port_runtime_pm_black_list, dev))
- pm_runtime_put_noidle(&dev->dev);
-
return 0;
}
static void pcie_portdrv_remove(struct pci_dev *dev)
{
- if (!pci_match_id(port_runtime_pm_black_list, dev))
- pm_runtime_get_noresume(&dev->dev);
pcie_port_device_remove(dev);
pci_disable_device(dev);
}
@@ -272,11 +259,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 +293,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 +327,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 +337,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 +363,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/probe.c b/drivers/pci/probe.c
index 6186f03..70f10fa 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -623,6 +623,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
{
struct pci_bus *child;
int i;
+ int ret;
/*
* Allocate a new bus, and inherit stuff from the parent..
@@ -637,8 +638,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->bus_flags = parent->bus_flags;
/* initialize some portions of the bus device, but don't register it
- * now as the parent is not properly set up yet. This device will get
- * registered later in pci_bus_add_devices()
+ * now as the parent is not properly set up yet.
*/
child->dev.class = &pcibus_class;
dev_set_name(&child->dev, "%04x:%02x", pci_domain_nr(child), busnr);
@@ -651,11 +651,14 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
child->primary = parent->busn_res.start;
child->busn_res.end = 0xff;
- if (!bridge)
- return child;
+ if (!bridge) {
+ child->dev.parent = parent->bridge;
+ goto add_dev;
+ }
child->self = bridge;
child->bridge = get_device(&bridge->dev);
+ child->dev.parent = child->bridge;
pci_set_bus_of_node(child);
pci_set_bus_speed(child);
@@ -666,6 +669,15 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
}
bridge->subordinate = child;
+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);
+
return child;
}
@@ -978,7 +990,6 @@ int pci_setup_device(struct pci_dev *dev)
dev->sysdata = dev->bus->sysdata;
dev->dev.parent = dev->bus->bridge;
dev->dev.bus = &pci_bus_type;
- dev->dev.type = &pci_dev_type;
dev->hdr_type = hdr_type & 0x7f;
dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal;
@@ -1198,6 +1209,7 @@ struct pci_dev *alloc_pci_dev(void)
return NULL;
INIT_LIST_HEAD(&dev->bus_list);
+ dev->dev.type = &pci_dev_type;
return dev;
}
@@ -1280,13 +1292,12 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* Power Management */
pci_pm_init(dev);
- platform_pci_wakeup_init(dev);
/* Vital Product Data */
pci_vpd_pci22_init(dev);
/* Alternative Routing-ID Forwarding */
- pci_enable_ari(dev);
+ pci_configure_ari(dev);
/* Single Root I/O Virtualization */
pci_iov_init(dev);
@@ -1297,10 +1308,12 @@ static void pci_init_capabilities(struct pci_dev *dev)
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
{
+ int ret;
+
device_initialize(&dev->dev);
dev->dev.release = pci_release_dev;
- pci_dev_get(dev);
+ set_dev_node(&dev->dev, pcibus_to_node(bus));
dev->dev.dma_mask = &dev->dma_mask;
dev->dev.dma_parms = &dev->dma_parms;
dev->dev.coherent_dma_mask = 0xffffffffull;
@@ -1327,6 +1340,16 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
down_write(&pci_bus_sem);
list_add_tail(&dev->bus_list, &bus->devices);
up_write(&pci_bus_sem);
+
+ ret = pcibios_add_device(dev);
+ WARN_ON(ret < 0);
+
+ /* Notifier could use PCI capabilities */
+ dev->match_driver = false;
+ ret = device_add(&dev->dev);
+ WARN_ON(ret < 0);
+
+ pci_proc_attach_device(dev);
}
struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
@@ -1349,31 +1372,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn)
}
EXPORT_SYMBOL(pci_scan_single_device);
-static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn)
+static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn)
{
- u16 cap;
- unsigned pos, next_fn;
+ int pos;
+ u16 cap = 0;
+ unsigned next_fn;
- if (!dev)
- return 0;
+ if (pci_ari_enabled(bus)) {
+ if (!dev)
+ return 0;
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
+ if (!pos)
+ return 0;
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
- if (!pos)
- return 0;
- pci_read_config_word(dev, pos + 4, &cap);
- next_fn = cap >> 8;
- if (next_fn <= fn)
- return 0;
- return next_fn;
-}
+ pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap);
+ next_fn = PCI_ARI_CAP_NFN(cap);
+ if (next_fn <= fn)
+ return 0; /* protect against malformed list */
-static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn)
-{
- return (fn + 1) % 8;
-}
+ return next_fn;
+ }
+
+ /* dev may be NULL for non-contiguous multifunction devices */
+ if (!dev || dev->multifunction)
+ return (fn + 1) % 8;
-static unsigned no_next_fn(struct pci_dev *dev, unsigned fn)
-{
return 0;
}
@@ -1406,7 +1429,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
{
unsigned fn, nr = 0;
struct pci_dev *dev;
- unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn;
if (only_one_child(bus) && (devfn > 0))
return 0; /* Already scanned the entire slot */
@@ -1417,12 +1439,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
if (!dev->is_added)
nr++;
- if (pci_ari_enabled(bus))
- next_fn = next_ari_fn;
- else if (dev->multifunction)
- next_fn = next_trad_fn;
-
- for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) {
+ for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) {
dev = pci_scan_single_device(bus, devfn + fn);
if (dev) {
if (!dev->is_added)
@@ -1611,8 +1628,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++)
@@ -1633,6 +1649,26 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
return max;
}
+/**
+ * pcibios_root_bridge_prepare - Platform-specific host bridge setup.
+ * @bridge: Host bridge to set up.
+ *
+ * Default empty implementation. Replace with an architecture-specific setup
+ * routine, if necessary.
+ */
+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)
{
@@ -1645,13 +1681,13 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
char bus_addr[64];
char *fmt;
-
b = pci_alloc_bus();
if (!b)
return NULL;
b->sysdata = sysdata;
b->ops = ops;
+ b->number = b->busn_res.start = bus;
b2 = pci_find_bus(pci_domain_nr(b), bus);
if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
@@ -1666,6 +1702,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
bridge->dev.parent = parent;
bridge->dev.release = pci_release_bus_bridge_dev;
dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus);
+ error = pcibios_root_bridge_prepare(bridge);
+ if (error)
+ goto bridge_dev_reg_err;
+
error = device_register(&bridge->dev);
if (error)
goto bridge_dev_reg_err;
@@ -1683,11 +1723,11 @@ 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);
- b->number = b->busn_res.start = bus;
-
if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
else
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 9b8505c..0812608 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -21,7 +21,7 @@ static loff_t
proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
{
loff_t new = -1;
- struct inode *inode = file->f_path.dentry->d_inode;
+ struct inode *inode = file_inode(file);
mutex_lock(&inode->i_mutex);
switch (whence) {
@@ -46,9 +46,7 @@ proc_bus_pci_lseek(struct file *file, loff_t off, int whence)
static ssize_t
proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
- const struct inode *ino = file->f_path.dentry->d_inode;
- const struct proc_dir_entry *dp = PDE(ino);
- struct pci_dev *dev = dp->data;
+ struct pci_dev *dev = PDE_DATA(file_inode(file));
unsigned int pos = *ppos;
unsigned int cnt, size;
@@ -59,7 +57,7 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
*/
if (capable(CAP_SYS_ADMIN))
- size = dp->size;
+ size = dev->cfg_size;
else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
size = 128;
else
@@ -132,11 +130,10 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
static ssize_t
proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, loff_t *ppos)
{
- struct inode *ino = file->f_path.dentry->d_inode;
- const struct proc_dir_entry *dp = PDE(ino);
- struct pci_dev *dev = dp->data;
+ struct inode *ino = file_inode(file);
+ struct pci_dev *dev = PDE_DATA(ino);
int pos = *ppos;
- int size = dp->size;
+ int size = dev->cfg_size;
int cnt;
if (pos >= size)
@@ -200,7 +197,7 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
pci_config_pm_runtime_put(dev);
*ppos = pos;
- i_size_write(ino, dp->size);
+ i_size_write(ino, dev->cfg_size);
return nbytes;
}
@@ -212,8 +209,7 @@ struct pci_filp_private {
static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
- const struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
- struct pci_dev *dev = dp->data;
+ struct pci_dev *dev = PDE_DATA(file_inode(file));
#ifdef HAVE_PCI_MMAP
struct pci_filp_private *fpriv = file->private_data;
#endif /* HAVE_PCI_MMAP */
@@ -253,9 +249,7 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
#ifdef HAVE_PCI_MMAP
static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct inode *inode = file->f_path.dentry->d_inode;
- const struct proc_dir_entry *dp = PDE(inode);
- struct pci_dev *dev = dp->data;
+ struct pci_dev *dev = PDE_DATA(file_inode(file));
struct pci_filp_private *fpriv = file->private_data;
int i, ret;
@@ -425,7 +419,7 @@ int pci_proc_attach_device(struct pci_dev *dev)
&proc_bus_pci_operations, dev);
if (!e)
return -ENOMEM;
- e->size = dev->cfg_size;
+ proc_set_size(e, dev->cfg_size);
dev->procent = e;
return 0;
@@ -433,20 +427,14 @@ int pci_proc_attach_device(struct pci_dev *dev)
int pci_proc_detach_device(struct pci_dev *dev)
{
- struct proc_dir_entry *e;
-
- if ((e = dev->procent)) {
- remove_proc_entry(e->name, dev->bus->procdir);
- dev->procent = NULL;
- }
+ proc_remove(dev->procent);
+ dev->procent = NULL;
return 0;
}
int pci_proc_detach_bus(struct pci_bus* bus)
{
- struct proc_dir_entry *de = bus->procdir;
- if (de)
- remove_proc_entry(de->name, proc_bus_pci_dir);
+ proc_remove(bus->procdir);
return 0;
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 0369fb6..7d68aee 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, &region);
+ 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, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "ali7101 ACPI");
- pci_read_config_word(dev, 0xE2, &region);
- 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, &region);
- quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES, "PIIX4 ACPI");
- pci_read_config_dword(dev, 0x90, &region);
- 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, &region);
- 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, &region);
- 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, &region);
- 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, &region);
- 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, &region);
- 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);
@@ -2594,6 +2554,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 +2611,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
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 84954a7..8fc54b7 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -24,7 +24,7 @@ static void pci_stop_dev(struct pci_dev *dev)
if (dev->is_added) {
pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
- device_unregister(&dev->dev);
+ device_del(&dev->dev);
dev->is_added = 0;
}
@@ -39,7 +39,7 @@ static void pci_destroy_dev(struct pci_dev *dev)
up_write(&pci_bus_sem);
pci_free_resources(dev);
- pci_dev_put(dev);
+ put_device(&dev->dev);
}
void pci_remove_bus(struct pci_bus *bus)
@@ -50,10 +50,8 @@ 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);
+ pcibios_remove_bus(bus);
device_unregister(&bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index ab886b7..c5d0a08 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -118,17 +118,11 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
void __iomem *rom;
/*
- * Some devices may provide ROMs via a source other than the BAR
- */
- if (pdev->rom && pdev->romlen) {
- *size = pdev->romlen;
- return phys_to_virt(pdev->rom);
- /*
* IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
* memory map if the VGA enable bit of the Bridge Control register is
* set for embedded VGA.
*/
- } else if (res->flags & IORESOURCE_ROM_SHADOW) {
+ if (res->flags & IORESOURCE_ROM_SHADOW) {
/* primary video rom always starts here */
start = (loff_t)0xC0000;
*size = 0x20000; /* cover C000:0 through E000:0 */
@@ -187,8 +181,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
return;
- if (!pdev->rom || !pdev->romlen)
- iounmap(rom);
+ iounmap(rom);
/* Disable again before continuing, leave enabled if pci=rom */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
@@ -212,7 +205,24 @@ void pci_cleanup_rom(struct pci_dev *pdev)
}
}
+/**
+ * pci_platform_rom - provides a pointer to any ROM image provided by the
+ * platform
+ * @pdev: pointer to pci device struct
+ * @size: pointer to receive size of pci window over ROM
+ */
+void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
+{
+ if (pdev->rom && pdev->romlen) {
+ *size = pdev->romlen;
+ return phys_to_virt((phys_addr_t)pdev->rom);
+ }
+
+ return NULL;
+}
+
EXPORT_SYMBOL(pci_map_rom);
EXPORT_SYMBOL(pci_unmap_rom);
EXPORT_SYMBOL_GPL(pci_enable_rom);
EXPORT_SYMBOL_GPL(pci_disable_rom);
+EXPORT_SYMBOL(pci_platform_rom);
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index bf969ba..d0627fa 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -319,13 +319,13 @@ int pci_dev_present(const struct pci_device_id *ids)
WARN_ON(in_interrupt());
while (ids->vendor || ids->subvendor || ids->class_mask) {
found = pci_get_dev_by_id(ids, NULL);
- if (found)
- goto exit;
+ if (found) {
+ pci_dev_put(found);
+ return 1;
+ }
ids++;
}
-exit:
- if (found)
- return 1;
+
return 0;
}
EXPORT_SYMBOL(pci_dev_present);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 6d3591d..d254e23 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -283,7 +283,7 @@ static void assign_requested_resources_sorted(struct list_head *head,
idx = res - &dev_res->dev->resource[0];
if (resource_size(res) &&
pci_assign_resource(dev_res->dev, idx)) {
- if (fail_head && !pci_is_root_bus(dev_res->dev->bus)) {
+ if (fail_head) {
/*
* if the failed res is for ROM BAR, and it will
* be enabled later, don't add it to the list
@@ -1115,9 +1115,9 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
}
EXPORT_SYMBOL(pci_bus_size_bridges);
-static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
- struct list_head *realloc_head,
- struct list_head *fail_head)
+void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
+ struct list_head *realloc_head,
+ struct list_head *fail_head)
{
struct pci_bus *b;
struct pci_dev *dev;
@@ -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/setup-res.c b/drivers/pci/setup-res.c
index 81b88bd..07f2edd 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);
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index ac6412f..c1e9284 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);