aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Kconfig11
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/bus.c18
-rw-r--r--drivers/pci/dmar.c20
-rw-r--r--drivers/pci/hotplug/Kconfig10
-rw-r--r--drivers/pci/hotplug/Makefile4
-rw-r--r--drivers/pci/hotplug/acpiphp.h9
-rw-r--r--drivers/pci/hotplug/acpiphp_core.c29
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c41
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c51
-rw-r--r--drivers/pci/hotplug/cpqphp_core.c41
-rw-r--r--drivers/pci/hotplug/cpqphp_ctrl.c112
-rw-r--r--drivers/pci/hotplug/fakephp.c53
-rw-r--r--drivers/pci/hotplug/ibmphp_core.c11
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c43
-rw-r--r--drivers/pci/hotplug/pciehp.h9
-rw-r--r--drivers/pci/hotplug/pciehp_core.c33
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c43
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c314
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c43
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c21
-rw-r--r--drivers/pci/hotplug/rpadlpar_sysfs.c113
-rw-r--r--drivers/pci/hotplug/rpaphp.h1
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c15
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c15
-rw-r--r--drivers/pci/hotplug/rpaphp_slot.c47
-rw-r--r--drivers/pci/hotplug/shpchp_ctrl.c16
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c2
-rw-r--r--drivers/pci/intel-iommu.c15
-rw-r--r--drivers/pci/intel-iommu.h2
-rw-r--r--drivers/pci/msi.c112
-rw-r--r--drivers/pci/pci-acpi.c7
-rw-r--r--drivers/pci/pci-driver.c68
-rw-r--r--drivers/pci/pci-sysfs.c15
-rw-r--r--drivers/pci/pci.c96
-rw-r--r--drivers/pci/pci.h16
-rw-r--r--drivers/pci/pcie/Kconfig20
-rw-r--r--drivers/pci/pcie/Makefile3
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c24
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c29
-rw-r--r--drivers/pci/pcie/aspm.c802
-rw-r--r--drivers/pci/pcie/portdrv_core.c5
-rw-r--r--drivers/pci/pcie/portdrv_pci.c2
-rw-r--r--drivers/pci/probe.c160
-rw-r--r--drivers/pci/proc.c17
-rw-r--r--drivers/pci/quirks.c508
-rw-r--r--drivers/pci/remove.c10
-rw-r--r--drivers/pci/rom.c6
-rw-r--r--drivers/pci/search.c9
-rw-r--r--drivers/pci/setup-bus.c64
-rw-r--r--drivers/pci/setup-res.c7
-rw-r--r--drivers/pci/syscall.c5
52 files changed, 2093 insertions, 1036 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 7a1d6d51283..e1ca42591ac 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -21,6 +21,17 @@ config PCI_MSI
If you don't know what to do here, say N.
+config PCI_LEGACY
+ bool "Enable deprecated pci_find_* API"
+ depends on PCI
+ default y
+ help
+ Say Y here if you want to include support for the deprecated
+ pci_find_slot() and pci_find_device() APIs. Most drivers have
+ been converted over to using the proper hotplug APIs, so this
+ option serves to include/exclude only a few drivers that are
+ still using this API.
+
config PCI_DEBUG
bool "PCI Debugging"
depends on PCI && DEBUG_KERNEL
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 55505565073..f697f3d728e 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -32,7 +32,7 @@ obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
obj-$(CONFIG_PARISC) += setup-bus.o
obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
obj-$(CONFIG_PPC32) += setup-irq.o
-obj-$(CONFIG_PPC64) += setup-bus.o
+obj-$(CONFIG_PPC) += setup-bus.o
obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 9e5ea074ad2..ef5a6a245f5 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -108,6 +108,7 @@ int pci_bus_add_device(struct pci_dev *dev)
void pci_bus_add_devices(struct pci_bus *bus)
{
struct pci_dev *dev;
+ struct pci_bus *child_bus;
int retval;
list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -138,11 +139,19 @@ void pci_bus_add_devices(struct pci_bus *bus)
up_write(&pci_bus_sem);
}
pci_bus_add_devices(dev->subordinate);
- retval = sysfs_create_link(&dev->subordinate->class_dev.kobj,
- &dev->dev.kobj, "bridge");
+
+ /* register the bus with sysfs as the parent is now
+ * properly registered. */
+ child_bus = dev->subordinate;
+ child_bus->dev.parent = child_bus->bridge;
+ retval = device_register(&child_bus->dev);
+ if (!retval)
+ retval = device_create_file(&child_bus->dev,
+ &dev_attr_cpuaffinity);
if (retval)
- dev_err(&dev->dev, "Error creating sysfs "
- "bridge symlink, continuing...\n");
+ dev_err(&dev->dev, "Error registering pci_bus"
+ " device bridge symlink,"
+ " continuing...\n");
}
}
}
@@ -204,7 +213,6 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
}
up_read(&pci_bus_sem);
}
-EXPORT_SYMBOL_GPL(pci_walk_bus);
EXPORT_SYMBOL(pci_bus_alloc_resource);
EXPORT_SYMBOL_GPL(pci_bus_add_device);
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 5dfdfdac92e..91b2dc956be 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -25,6 +25,7 @@
#include <linux/pci.h>
#include <linux/dmar.h>
+#include "iova.h"
#undef PREFIX
#define PREFIX "DMAR:"
@@ -263,8 +264,8 @@ parse_dmar_table(void)
if (!dmar)
return -ENODEV;
- if (!dmar->width) {
- printk (KERN_WARNING PREFIX "Zero: Invalid DMAR haw\n");
+ if (dmar->width < PAGE_SHIFT_4K - 1) {
+ printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
return -EINVAL;
}
@@ -301,11 +302,24 @@ parse_dmar_table(void)
int __init dmar_table_init(void)
{
- parse_dmar_table();
+ int ret;
+
+ ret = parse_dmar_table();
+ if (ret) {
+ printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+ return ret;
+ }
+
if (list_empty(&dmar_drhd_units)) {
printk(KERN_INFO PREFIX "No DMAR devices found\n");
return -ENODEV;
}
+
+ if (list_empty(&dmar_rmrr_units)) {
+ printk(KERN_INFO PREFIX "No RMRR found\n");
+ return -ENODEV;
+ }
+
return 0;
}
diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
index 63d62752fb9..2cdd8326f13 100644
--- a/drivers/pci/hotplug/Kconfig
+++ b/drivers/pci/hotplug/Kconfig
@@ -3,8 +3,8 @@
#
menuconfig HOTPLUG_PCI
- tristate "Support for PCI Hotplug (EXPERIMENTAL)"
- depends on PCI && EXPERIMENTAL && HOTPLUG
+ tristate "Support for PCI Hotplug"
+ depends on PCI && HOTPLUG
---help---
Say Y here if you have a motherboard with a PCI Hotplug controller.
This allows you to add and remove PCI cards while the machine is
@@ -41,7 +41,7 @@ config HOTPLUG_PCI_FAKE
config HOTPLUG_PCI_COMPAQ
tristate "Compaq PCI Hotplug driver"
- depends on X86 && PCI_BIOS
+ depends on X86 && PCI_BIOS && PCI_LEGACY
help
Say Y here if you have a motherboard with a Compaq PCI Hotplug
controller.
@@ -63,7 +63,7 @@ config HOTPLUG_PCI_COMPAQ_NVRAM
config HOTPLUG_PCI_IBM
tristate "IBM PCI Hotplug driver"
- depends on X86_IO_APIC && X86 && PCI_BIOS
+ depends on X86_IO_APIC && X86 && PCI_BIOS && PCI_LEGACY
help
Say Y here if you have a motherboard with a IBM PCI Hotplug
controller.
@@ -119,7 +119,7 @@ config HOTPLUG_PCI_CPCI_ZT5550
config HOTPLUG_PCI_CPCI_GENERIC
tristate "Generic port I/O CompactPCI Hotplug driver"
- depends on HOTPLUG_PCI_CPCI && X86
+ depends on HOTPLUG_PCI_CPCI && X86 && PCI_LEGACY
help
Say Y here if you have a CompactPCI system card that exposes the #ENUM
hotswap signal as a bit in a system register that can be read through
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 34a1891191f..9bdbe1a6688 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -3,7 +3,6 @@
#
obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
-obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
@@ -16,6 +15,9 @@ obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
+# Link this last so it doesn't claim devices that have a real hotplug driver
+obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
+
pci_hotplug-objs := pci_hotplug_core.o
ifdef CONFIG_HOTPLUG_PCI_CPCI
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index f6cc0c5b565..7a29164d4b3 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -66,7 +66,7 @@ struct slot {
char name[SLOT_NAME_SIZE];
};
-/**
+/*
* struct acpiphp_bridge - PCI bridge information
*
* for each bridge device in ACPI namespace
@@ -97,7 +97,7 @@ struct acpiphp_bridge {
};
-/**
+/*
* struct acpiphp_slot - PCI slot information
*
* PCI slot information for each *physical* PCI slot
@@ -113,12 +113,11 @@ struct acpiphp_slot {
u8 device; /* pci device# */
u32 sun; /* ACPI _SUN (slot unique number) */
- u32 slotno; /* slot number relative to bridge */
u32 flags; /* see below */
};
-/**
+/*
* struct acpiphp_func - PCI function information
*
* PCI function information for each object in ACPI namespace
@@ -137,7 +136,7 @@ struct acpiphp_func {
u32 flags; /* see below */
};
-/**
+/*
* struct acpiphp_attention_info - device specific attention registration
*
* ACPI has no generic method of setting/getting attention status
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c
index a0ca63adad5..c8c263875c2 100644
--- a/drivers/pci/hotplug/acpiphp_core.c
+++ b/drivers/pci/hotplug/acpiphp_core.c
@@ -91,10 +91,10 @@ static struct hotplug_slot_ops acpi_hotplug_slot_ops = {
* acpiphp_register_attention - set attention LED callback
* @info: must be completely filled with LED callbacks
*
- * Description: this is used to register a hardware specific ACPI
+ * Description: This is used to register a hardware specific ACPI
* driver that manipulates the attention LED. All the fields in
* info must be set.
- **/
+ */
int acpiphp_register_attention(struct acpiphp_attention_info *info)
{
int retval = -EINVAL;
@@ -112,10 +112,10 @@ int acpiphp_register_attention(struct acpiphp_attention_info *info)
* acpiphp_unregister_attention - unset attention LED callback
* @info: must match the pointer used to register
*
- * Description: this is used to un-register a hardware specific acpi
+ * Description: This is used to un-register a hardware specific acpi
* driver that manipulates the attention LED. The pointer to the
* info struct must be the same as the one used to set it.
- **/
+ */
int acpiphp_unregister_attention(struct acpiphp_attention_info *info)
{
int retval = -EINVAL;
@@ -133,7 +133,6 @@ int acpiphp_unregister_attention(struct acpiphp_attention_info *info)
* @hotplug_slot: slot to enable
*
* Actual tasks are done in acpiphp_enable_slot()
- *
*/
static int enable_slot(struct hotplug_slot *hotplug_slot)
{
@@ -151,7 +150,6 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
* @hotplug_slot: slot to disable
*
* Actual tasks are done in acpiphp_disable_slot()
- *
*/
static int disable_slot(struct hotplug_slot *hotplug_slot)
{
@@ -168,15 +166,15 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
}
- /**
- * set_attention_status - set attention LED
+/**
+ * set_attention_status - set attention LED
* @hotplug_slot: slot to set attention LED on
* @status: value to set attention LED to (0 or 1)
*
* attention status LED, so we use a callback that
* was registered with us. This allows hardware specific
* ACPI implementations to blink the light for us.
- **/
+ */
static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
{
int retval = -ENODEV;
@@ -199,7 +197,6 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
*
* Some platforms may not implement _STA method properly.
* In that case, the value returned may not be reliable.
- *
*/
static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
@@ -213,7 +210,7 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
}
- /**
+/**
* get_attention_status - get attention LED status
* @hotplug_slot: slot to get status from
* @value: returns with value of attention LED
@@ -221,8 +218,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
* ACPI doesn't have known method to determine the state
* of the attention status LED, so we use a callback that
* was registered with us. This allows hardware specific
- * ACPI implementations to determine its state
- **/
+ * ACPI implementations to determine its state.
+ */
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
int retval = -EINVAL;
@@ -244,8 +241,7 @@ static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
* @value: pointer to store status
*
* ACPI doesn't provide any formal means to access latch status.
- * Instead, we fake latch status from _STA
- *
+ * Instead, we fake latch status from _STA.
*/
static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
@@ -265,8 +261,7 @@ static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
* @value: pointer to store status
*
* ACPI doesn't provide any formal means to access adapter status.
- * Instead, we fake adapter status from _STA
- *
+ * Instead, we fake adapter status from _STA.
*/
static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 1e125b56c9a..cf22f9e01e0 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -82,7 +82,6 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *contex
* 2. has _PS0 method
* 3. has _PS3 method
* 4. ..
- *
*/
static int is_ejectable(acpi_handle handle)
{
@@ -103,7 +102,7 @@ static int is_ejectable(acpi_handle handle)
}
-/* callback routine to check the existence of ejectable slots */
+/* callback routine to check for the existence of ejectable slots */
static acpi_status
is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
{
@@ -118,7 +117,7 @@ is_ejectable_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
}
}
-/* callback routine to check for the existance of a pci dock device */
+/* callback routine to check for the existence of a pci dock device */
static acpi_status
is_pci_dock_device(acpi_handle handle, u32 lvl, void *context, void **rv)
{
@@ -986,10 +985,8 @@ static int power_off_slot(struct acpiphp_slot *slot)
/**
- * acpiphp_max_busnr - return the highest reserved bus number under
- * the given bus.
+ * acpiphp_max_busnr - return the highest reserved bus number under the given bus.
* @bus: bus to start search with
- *
*/
static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
{
@@ -1018,7 +1015,6 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
/**
* acpiphp_bus_add - add a new bus to acpi subsystem
* @func: acpiphp_func of the bridge
- *
*/
static int acpiphp_bus_add(struct acpiphp_func *func)
{
@@ -1063,7 +1059,6 @@ acpiphp_bus_add_out:
/**
* acpiphp_bus_trim - trim a bus from acpi subsystem
* @handle: handle to acpi namespace
- *
*/
static int acpiphp_bus_trim(acpi_handle handle)
{
@@ -1089,7 +1084,6 @@ static int acpiphp_bus_trim(acpi_handle handle)
*
* This function should be called per *physical slot*,
* not per each slot object in ACPI namespace.
- *
*/
static int enable_device(struct acpiphp_slot *slot)
{
@@ -1185,6 +1179,7 @@ static void disable_bridges(struct pci_bus *bus)
/**
* disable_device - disable a slot
+ * @slot: ACPI PHP slot
*/
static int disable_device(struct acpiphp_slot *slot)
{
@@ -1240,14 +1235,15 @@ static int disable_device(struct acpiphp_slot *slot)
/**
* get_slot_status - get ACPI slot status
+ * @slot: ACPI PHP slot
*
- * if a slot has _STA for each function and if any one of them
- * returned non-zero status, return it
+ * If a slot has _STA for each function and if any one of them
+ * returned non-zero status, return it.
*
- * if a slot doesn't have _STA and if any one of its functions'
- * configuration space is configured, return 0x0f as a _STA
+ * If a slot doesn't have _STA and if any one of its functions'
+ * configuration space is configured, return 0x0f as a _STA.
*
- * otherwise return 0
+ * Otherwise return 0.
*/
static unsigned int get_slot_status(struct acpiphp_slot *slot)
{
@@ -1281,6 +1277,7 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
/**
* acpiphp_eject_slot - physically eject the slot
+ * @slot: ACPI PHP slot
*/
int acpiphp_eject_slot(struct acpiphp_slot *slot)
{
@@ -1314,6 +1311,7 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
/**
* acpiphp_check_bridge - re-enumerate devices
+ * @bridge: where to begin re-enumeration
*
* Iterate over all slots under this bridge and make sure that if a
* card is present they are enabled, and if not they are disabled.
@@ -1530,7 +1528,6 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
dbg("%s: re-enumerating slots under %s\n",
__FUNCTION__, objname);
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
acpiphp_check_bridge(bridge);
}
return AE_OK ;
@@ -1538,13 +1535,11 @@ check_sub_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
/**
* handle_hotplug_event_bridge - handle ACPI event on bridges
- *
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_bridge structure
*
- * handles ACPI event notification on {host,p2p} bridges
- *
+ * Handles ACPI event notification on {host,p2p} bridges.
*/
static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *context)
{
@@ -1634,13 +1629,11 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
/**
* handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)
- *
* @handle: Notify()'ed acpi_handle
* @type: Notify code
* @context: pointer to acpiphp_func structure
*
- * handles ACPI event notification on slots
- *
+ * Handles ACPI event notification on slots.
*/
static void handle_hotplug_event_func(acpi_handle handle, u32 type, void *context)
{
@@ -1705,7 +1698,6 @@ static struct acpi_pci_driver acpi_pci_hp_driver = {
/**
* acpiphp_glue_init - initializes all PCI hotplug - ACPI glue data structures
- *
*/
int __init acpiphp_glue_init(void)
{
@@ -1726,7 +1718,7 @@ int __init acpiphp_glue_init(void)
/**
* acpiphp_glue_exit - terminates all PCI hotplug - ACPI glue data structures
*
- * This function frees all data allocated in acpiphp_glue_init()
+ * This function frees all data allocated in acpiphp_glue_init().
*/
void acpiphp_glue_exit(void)
{
@@ -1760,7 +1752,6 @@ int __init acpiphp_get_num_slots(void)
* acpiphp_for_each_slot - call function for each slot
* @fn: callback function
* @data: context to be passed to callback function
- *
*/
static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
{
@@ -1786,6 +1777,7 @@ static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
/**
* acpiphp_enable_slot - power on slot
+ * @slot: ACPI PHP slot
*/
int acpiphp_enable_slot(struct acpiphp_slot *slot)
{
@@ -1815,6 +1807,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
/**
* acpiphp_disable_slot - power off slot
+ * @slot: ACPI PHP slot
*/
int acpiphp_disable_slot(struct acpiphp_slot *slot)
{
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index 56829f82be4..750ebd7a4c1 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -134,11 +134,11 @@ static struct acpiphp_attention_info ibm_attention_info =
* ibm_slot_from_id - workaround for bad ibm hardware
* @id: the slot number that linux refers to the slot by
*
- * Description: this method returns the aCPI slot descriptor
+ * Description: This method returns the aCPI slot descriptor
* corresponding to the Linux slot number. This descriptor
* has info about the aPCI slot id and attention status.
* This descriptor must be freed using kfree when done.
- **/
+ */
static union apci_descriptor *ibm_slot_from_id(int id)
{
int ind = 0, size;
@@ -173,9 +173,9 @@ ibm_slot_done:
* @slot: the hotplug_slot to work with
* @status: what to set the LED to (0 or 1)
*
- * Description: this method is registered with the acpiphp module as a
- * callback to do the device specific task of setting the LED status
- **/
+ * Description: This method is registered with the acpiphp module as a
+ * callback to do the device specific task of setting the LED status.
+ */
static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
{
union acpi_object args[2];
@@ -213,13 +213,13 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status)
* @slot: the hotplug_slot to work with
* @status: returns what the LED is set to (0 or 1)
*
- * Description: this method is registered with the acpiphp module as a
- * callback to do the device specific task of getting the LED status
+ * Description: This method is registered with the acpiphp module as a
+ * callback to do the device specific task of getting the LED status.
*
* Because there is no direct method of getting the LED status directly
* from an ACPI call, we read the aPCI table and parse out our
* slot descriptor to read the status from that.
- **/
+ */
static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
{
union apci_descriptor *ibm_slot;
@@ -245,8 +245,8 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
* @event: the event info (device specific)
* @context: passed context (our notification struct)
*
- * Description: this method is registered as a callback with the ACPI
- * subsystem it is called when this device has an event to notify the OS of
+ * Description: This method is registered as a callback with the ACPI
+ * subsystem it is called when this device has an event to notify the OS of.
*
* The events actually come from the device as two events that get
* synthesized into one event with data by this function. The event
@@ -256,7 +256,7 @@ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status)
* From section 5.6.2.2 of the ACPI 2.0 spec, I understand that the OSPM will
* only re-enable the interrupt that causes this event AFTER this method
* has returned, thereby enforcing serial access for the notification struct.
- **/
+ */
static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
{
u8 detail = event & 0x0f;
@@ -279,16 +279,16 @@ static void ibm_handle_events(acpi_handle handle, u32 event, void *context)
* ibm_get_table_from_acpi - reads the APLS buffer from ACPI
* @bufp: address to pointer to allocate for the table
*
- * Description: this method reads the APLS buffer in from ACPI and
+ * Description: This method reads the APLS buffer in from ACPI and
* stores the "stripped" table into a single buffer
- * it allocates and passes the address back in bufp
+ * it allocates and passes the address back in bufp.
*
* If NULL is passed in as buffer, this method only calculates
* the size of the table and returns that without filling
- * in the buffer
+ * in the buffer.
*
- * returns < 0 on error or the size of the table on success
- **/
+ * Returns < 0 on error or the size of the table on success.
+ */
static int ibm_get_table_from_acpi(char **bufp)
{
union acpi_object *package;
@@ -349,17 +349,18 @@ read_table_done:
/**
* ibm_read_apci_table - callback for the sysfs apci_table file
* @kobj: the kobject this binary attribute is a part of
+ * @bin_attr: struct bin_attribute for this file
* @buffer: the kernel space buffer to fill
* @pos: the offset into the file
* @size: the number of bytes requested
*
- * Description: gets registered with sysfs as the reader callback
- * to be executed when /sys/bus/pci/slots/apci_table gets read
+ * Description: Gets registered with sysfs as the reader callback
+ * to be executed when /sys/bus/pci/slots/apci_table gets read.
*
* Since we don't get notified on open and close for this file,
* things get really tricky here...
- * our solution is to only allow reading the table in all at once
- **/
+ * our solution is to only allow reading the table in all at once.
+ */
static ssize_t ibm_read_apci_table(struct kobject *kobj,
struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t size)
@@ -385,10 +386,10 @@ static ssize_t ibm_read_apci_table(struct kobject *kobj,
* @context: a pointer to our handle to fill when we find the device
* @rv: a return value to fill if desired
*
- * Description: used as a callback when calling acpi_walk_namespace
+ * Description: Used as a callback when calling acpi_walk_namespace
* to find our device. When this method returns non-zero
- * acpi_walk_namespace quits its search and returns our value
- **/
+ * acpi_walk_namespace quits its search and returns our value.
+ */
static acpi_status __init ibm_find_acpi_device(acpi_handle handle,
u32 lvl, void *context, void **rv)
{
@@ -428,7 +429,7 @@ static int __init ibm_acpiphp_init(void)
int retval = 0;
acpi_status status;
struct acpi_device *device;
- struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
+ struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
dbg("%s\n", __FUNCTION__);
@@ -475,7 +476,7 @@ init_return:
static void __exit ibm_acpiphp_exit(void)
{
acpi_status status;
- struct kobject *sysdir = &pci_hotplug_slots_subsys.kobj;
+ struct kobject *sysdir = &pci_hotplug_slots_kset->kobj;
dbg("%s\n", __FUNCTION__);
diff --git a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c
index a96b739b2d3..74178875b94 100644
--- a/drivers/pci/hotplug/cpqphp_core.c
+++ b/drivers/pci/hotplug/cpqphp_core.c
@@ -117,12 +117,10 @@ static inline int is_slot66mhz(struct slot *slot)
/**
* detect_SMBIOS_pointer - find the System Management BIOS Table in mem region.
- *
* @begin: begin pointer for region to be scanned.
* @end: end pointer for region to be scanned.
*
- * Returns pointer to the head of the SMBIOS tables (or NULL)
- *
+ * Returns pointer to the head of the SMBIOS tables (or %NULL).
*/
static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *end)
{
@@ -157,9 +155,9 @@ static void __iomem * detect_SMBIOS_pointer(void __iomem *begin, void __iomem *e
/**
* init_SERR - Initializes the per slot SERR generation.
+ * @ctrl: controller to use
*
* For unexpected switch opens
- *
*/
static int init_SERR(struct controller * ctrl)
{
@@ -224,14 +222,15 @@ static int pci_print_IRQ_route (void)
/**
* get_subsequent_smbios_entry: get the next entry from bios table.
- *
- * Gets the first entry if previous == NULL
- * Otherwise, returns the next entry
- * Uses global SMBIOS Table pointer
- *
+ * @smbios_start: where to start in the SMBIOS table
+ * @smbios_table: location of the SMBIOS table
* @curr: %NULL or pointer to previously returned structure
*
- * returns a pointer to an SMBIOS structure or NULL if none found
+ * Gets the first entry if previous == NULL;
+ * otherwise, returns the next entry.
+ * Uses global SMBIOS Table pointer.
+ *
+ * Returns a pointer to an SMBIOS structure or NULL if none found.
*/
static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
void __iomem *smbios_table,
@@ -272,17 +271,18 @@ static void __iomem *get_subsequent_smbios_entry(void __iomem *smbios_start,
/**
- * get_SMBIOS_entry
- *
- * @type:SMBIOS structure type to be returned
+ * get_SMBIOS_entry - return the requested SMBIOS entry or %NULL
+ * @smbios_start: where to start in the SMBIOS table
+ * @smbios_table: location of the SMBIOS table
+ * @type: SMBIOS structure type to be returned
* @previous: %NULL or pointer to previously returned structure
*
- * Gets the first entry of the specified type if previous == NULL
+ * Gets the first entry of the specified type if previous == %NULL;
* Otherwise, returns the next entry of the given type.
- * Uses global SMBIOS Table pointer
- * Uses get_subsequent_smbios_entry
+ * Uses global SMBIOS Table pointer.
+ * Uses get_subsequent_smbios_entry.
*
- * returns a pointer to an SMBIOS structure or %NULL if none found
+ * Returns a pointer to an SMBIOS structure or %NULL if none found.
*/
static void __iomem *get_SMBIOS_entry(void __iomem *smbios_start,
void __iomem *smbios_table,
@@ -581,7 +581,9 @@ get_slot_mapping(struct pci_bus *bus, u8 bus_num, u8 dev_num, u8 *slot)
/**
* cpqhp_set_attention_status - Turns the Amber LED for a slot on or off
- *
+ * @ctrl: struct controller to use
+ * @func: PCI device/function info
+ * @status: LED control flag: 1 = LED on, 0 = LED off
*/
static int
cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
@@ -621,7 +623,8 @@ cpqhp_set_attention_status(struct controller *ctrl, struct pci_func *func,
/**
* set_attention_status - Turns the Amber LED for a slot on or off
- *
+ * @hotplug_slot: slot to change LED on
+ * @status: LED control flag
*/
static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status)
{
diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c
index 3ef0a4875a6..4018420c6f9 100644
--- a/drivers/pci/hotplug/cpqphp_ctrl.c
+++ b/drivers/pci/hotplug/cpqphp_ctrl.c
@@ -123,7 +123,7 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
}
/**
- * cpqhp_find_slot: find the struct slot of given device
+ * cpqhp_find_slot - find the struct slot of given device
* @ctrl: scan lots of this controller
* @device: the device id to find
*/
@@ -305,9 +305,8 @@ static u8 handle_power_fault(u8 change, struct controller * ctrl)
/**
- * sort_by_size: sort nodes on the list by their length, smallest first.
+ * sort_by_size - sort nodes on the list by their length, smallest first.
* @head: list to sort
- *
*/
static int sort_by_size(struct pci_resource **head)
{
@@ -354,9 +353,8 @@ static int sort_by_size(struct pci_resource **head)
/**
- * sort_by_max_size: sort nodes on the list by their length, largest first.
+ * sort_by_max_size - sort nodes on the list by their length, largest first.
* @head: list to sort
- *
*/
static int sort_by_max_size(struct pci_resource **head)
{
@@ -403,8 +401,10 @@ static int sort_by_max_size(struct pci_resource **head)
/**
- * do_pre_bridge_resource_split: find node of resources that are unused
- *
+ * do_pre_bridge_resource_split - find node of resources that are unused
+ * @head: new list head
+ * @orig_head: original list head
+ * @alignment: max node size (?)
*/
static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **head,
struct pci_resource **orig_head, u32 alignment)
@@ -477,8 +477,9 @@ static struct pci_resource *do_pre_bridge_resource_split(struct pci_resource **h
/**
- * do_bridge_resource_split: find one node of resources that aren't in use
- *
+ * do_bridge_resource_split - find one node of resources that aren't in use
+ * @head: list head
+ * @alignment: max node size (?)
*/
static struct pci_resource *do_bridge_resource_split(struct pci_resource **head, u32 alignment)
{
@@ -525,14 +526,13 @@ error:
/**
- * get_io_resource: find first node of given size not in ISA aliasing window.
+ * get_io_resource - find first node of given size not in ISA aliasing window.
* @head: list to search
* @size: size of node to find, must be a power of two.
*
- * Description: this function sorts the resource list by size and then returns
+ * Description: This function sorts the resource list by size and then returns
* returns the first node of "size" length that is not in the ISA aliasing
* window. If it finds a node larger than "size" it will split it up.
- *
*/
static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size)
{
@@ -620,7 +620,7 @@ static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size
/**
- * get_max_resource: get largest node which has at least the given size.
+ * get_max_resource - get largest node which has at least the given size.
* @head: the list to search the node in
* @size: the minimum size of the node to find
*
@@ -712,7 +712,7 @@ static struct pci_resource *get_max_resource(struct pci_resource **head, u32 siz
/**
- * get_resource: find resource of given size and split up larger ones.
+ * get_resource - find resource of given size and split up larger ones.
* @head: the list to search for resources
* @size: the size limit to use
*
@@ -804,14 +804,14 @@ static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
/**
- * cpqhp_resource_sort_and_combine: sort nodes by base addresses and clean up.
+ * cpqhp_resource_sort_and_combine - sort nodes by base addresses and clean up
* @head: the list to sort and clean up
*
* Description: Sorts all of the nodes in the list in ascending order by
* their base addresses. Also does garbage collection by
* combining adjacent nodes.
*
- * returns 0 if success
+ * Returns %0 if success.
*/
int cpqhp_resource_sort_and_combine(struct pci_resource **head)
{
@@ -951,9 +951,9 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data)
/**
* cpqhp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
+ * @busnumber: bus where new node is to be located
*
- * Returns pointer to the new node or NULL if unsuccessful
+ * Returns pointer to the new node or %NULL if unsuccessful.
*/
struct pci_func *cpqhp_slot_create(u8 busnumber)
{
@@ -986,7 +986,7 @@ struct pci_func *cpqhp_slot_create(u8 busnumber)
* slot_remove - Removes a node from the linked list of slots.
* @old_slot: slot to remove
*
- * Returns 0 if successful, !0 otherwise.
+ * Returns %0 if successful, !0 otherwise.
*/
static int slot_remove(struct pci_func * old_slot)
{
@@ -1026,7 +1026,7 @@ static int slot_remove(struct pci_func * old_slot)
* bridge_slot_remove - Removes a node from the linked list of slots.
* @bridge: bridge to remove
*
- * Returns 0 if successful, !0 otherwise.
+ * Returns %0 if successful, !0 otherwise.
*/
static int bridge_slot_remove(struct pci_func *bridge)
{
@@ -1071,7 +1071,7 @@ out:
* cpqhp_slot_find - Looks for a node by bus, and device, multiple functions accessed
* @bus: bus to find
* @device: device to find
- * @index: is 0 for first function found, 1 for the second...
+ * @index: is %0 for first function found, %1 for the second...
*
* Returns pointer to the node if successful, %NULL otherwise.
*/
@@ -1115,16 +1115,13 @@ static int is_bridge(struct pci_func * func)
/**
- * set_controller_speed - set the frequency and/or mode of a specific
- * controller segment.
- *
+ * set_controller_speed - set the frequency and/or mode of a specific controller segment.
* @ctrl: controller to change frequency/mode for.
* @adapter_speed: the speed of the adapter we want to match.
* @hp_slot: the slot number where the adapter is installed.
*
- * Returns 0 if we successfully change frequency and/or mode to match the
+ * Returns %0 if we successfully change frequency and/or mode to match the
* adapter speed.
- *
*/
static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
{
@@ -1253,13 +1250,14 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
/**
* board_replaced - Called after a board has been replaced in the system.
+ * @func: PCI device/function information
+ * @ctrl: hotplug controller
*
- * This is only used if we don't have resources for hot add
- * Turns power on for the board
- * Checks to see if board is the same
- * If board is same, reconfigures it
+ * This is only used if we don't have resources for hot add.
+ * Turns power on for the board.
+ * Checks to see if board is the same.
+ * If board is same, reconfigures it.
* If board isn't same, turns it back off.
- *
*/
static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
{
@@ -1403,10 +1401,11 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
/**
* board_added - Called after a board has been added to the system.
+ * @func: PCI device/function info
+ * @ctrl: hotplug controller
*
- * Turns power on for the board
- * Configures board
- *
+ * Turns power on for the board.
+ * Configures board.
*/
static u32 board_added(struct pci_func *func, struct controller *ctrl)
{
@@ -1607,8 +1606,10 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
/**
- * remove_board - Turns off slot and LED's
- *
+ * remove_board - Turns off slot and LEDs
+ * @func: PCI device/function info
+ * @replace_flag: whether replacing or adding a new device
+ * @ctrl: target controller
*/
static u32 remove_board(struct pci_func * func, u32 replace_flag, struct controller * ctrl)
{
@@ -1902,11 +1903,11 @@ static void interrupt_event_handler(struct controller *ctrl)
/**
- * cpqhp_pushbutton_thread
+ * cpqhp_pushbutton_thread - handle pushbutton events
+ * @slot: target slot (struct)
*
- * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Scheduled procedure to handle blocking stuff for the pushbuttons.
* Handles all pending events and exits.
- *
*/
void cpqhp_pushbutton_thread(unsigned long slot)
{
@@ -1931,16 +1932,14 @@ void cpqhp_pushbutton_thread(unsigned long slot)
return ;
}
- if (func != NULL && ctrl != NULL) {
- if (cpqhp_process_SS(ctrl, func) != 0) {
- amber_LED_on (ctrl, hp_slot);
- green_LED_on (ctrl, hp_slot);
-
- set_SOGO(ctrl);
+ if (cpqhp_process_SS(ctrl, func) != 0) {
+ amber_LED_on(ctrl, hp_slot);
+ green_LED_on(ctrl, hp_slot);
- /* Wait for SOBS to be unset */
- wait_for_ctrl_irq (ctrl);
- }
+ set_SOGO(ctrl);
+
+ /* Wait for SOBS to be unset */
+ wait_for_ctrl_irq(ctrl);
}
p_slot->state = STATIC_STATE;
@@ -2139,9 +2138,10 @@ int cpqhp_process_SS(struct controller *ctrl, struct pci_func *func)
}
/**
- * switch_leds: switch the leds, go from one site to the other.
+ * switch_leds - switch the leds, go from one site to the other.
* @ctrl: controller to use
* @num_of_slots: number of slots to use
+ * @work_LED: LED control value
* @direction: 1 to start from the left side, 0 to start right.
*/
static void switch_leds(struct controller *ctrl, const int num_of_slots,
@@ -2167,11 +2167,11 @@ static void switch_leds(struct controller *ctrl, const int num_of_slots,
}
/**
- * hardware_test - runs hardware tests
+ * cpqhp_hardware_test - runs hardware tests
+ * @ctrl: target controller
+ * @test_num: the number written to the "test" file in sysfs.
*
* For hot plug ctrl folks to play with.
- * test_num is the number written to the "test" file in sysfs
- *
*/
int cpqhp_hardware_test(struct controller *ctrl, int test_num)
{
@@ -2251,14 +2251,12 @@ int cpqhp_hardware_test(struct controller *ctrl, int test_num)
/**
* configure_new_device - Configures the PCI header information of one board.
- *
* @ctrl: pointer to controller structure
* @func: pointer to function structure
* @behind_bridge: 1 if this is a recursive call, 0 if not
* @resources: pointer to set of resource lists
*
- * Returns 0 if success
- *
+ * Returns 0 if success.
*/
static u32 configure_new_device(struct controller * ctrl, struct pci_func * func,
u8 behind_bridge, struct resource_lists * resources)
@@ -2348,15 +2346,13 @@ static u32 configure_new_device(struct controller * ctrl, struct pci_func * func
/**
* configure_new_function - Configures the PCI header information of one device
- *
* @ctrl: pointer to controller structure
* @func: pointer to function structure
* @behind_bridge: 1 if this is a recursive call, 0 if not
* @resources: pointer to set of resource lists
*
* Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
+ * Returns 0 if success.
*/
static int configure_new_function(struct controller *ctrl, struct pci_func *func,
u8 behind_bridge,
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 027f6865d7e..94b640146d4 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -39,6 +39,7 @@
#include <linux/init.h>
#include <linux/string.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include "../pci.h"
#if !defined(MODULE)
@@ -63,10 +64,16 @@ struct dummy_slot {
struct list_head node;
struct hotplug_slot *slot;
struct pci_dev *dev;
+ struct work_struct remove_work;
+ unsigned long removed;
};
static int debug;
static LIST_HEAD(slot_list);
+static struct workqueue_struct *dummyphp_wq;
+
+static void pci_rescan_worker(struct work_struct *work);
+static DECLARE_WORK(pci_rescan_work, pci_rescan_worker);
static int enable_slot (struct hotplug_slot *slot);
static int disable_slot (struct hotplug_slot *slot);
@@ -109,7 +116,7 @@ static int add_slot(struct pci_dev *dev)
slot->name = &dev->dev.bus_id[0];
dbg("slot->name = %s\n", slot->name);
- dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL);
+ dslot = kzalloc(sizeof(struct dummy_slot), GFP_KERNEL);
if (!dslot)
goto error_info;
@@ -164,12 +171,20 @@ static void remove_slot(struct dummy_slot *dslot)
err("Problem unregistering a slot %s\n", dslot->slot->name);
}
+/* called from the single-threaded workqueue handler to remove a slot */
+static void remove_slot_worker(struct work_struct *work)
+{
+ struct dummy_slot *dslot =
+ container_of(work, struct dummy_slot, remove_work);
+ remove_slot(dslot);
+}
+
/**
- * Rescan slot.
- * Tries hard not to re-enable already existing devices
- * also handles scanning of subfunctions
+ * pci_rescan_slot - Rescan slot
+ * @temp: Device template. Should be set: bus and devfn.
*
- * @param temp Device template. Should be set: bus and devfn.
+ * Tries hard not to re-enable already existing devices;
+ * also handles scanning of subfunctions.
*/
static void pci_rescan_slot(struct pci_dev *temp)
{
@@ -229,10 +244,10 @@ static void pci_rescan_slot(struct pci_dev *temp)
/**
- * Rescan PCI bus.
- * call pci_rescan_slot for each possible function of the bus
+ * pci_rescan_bus - Rescan PCI bus
+ * @bus: the PCI bus to rescan
*
- * @param bus
+ * Call pci_rescan_slot for each possible function of the bus.
*/
static void pci_rescan_bus(const struct pci_bus *bus)
{
@@ -267,11 +282,17 @@ static inline void pci_rescan(void) {
pci_rescan_buses(&pci_root_buses);
}
+/* called from the single-threaded workqueue handler to rescan all pci buses */
+static void pci_rescan_worker(struct work_struct *work)
+{
+ pci_rescan();
+}
static int enable_slot(struct hotplug_slot *hotplug_slot)
{
/* mis-use enable_slot for rescanning of the pci bus */
- pci_rescan();
+ cancel_work_sync(&pci_rescan_work);
+ queue_work(dummyphp_wq, &pci_rescan_work);
return -ENODEV;
}
@@ -306,6 +327,10 @@ static int disable_slot(struct hotplug_slot *slot)
err("Can't remove PCI devices with other PCI devices behind it yet.\n");
return -ENODEV;
}
+ if (test_and_set_bit(0, &dslot->removed)) {
+ dbg("Slot already scheduled for removal\n");
+ return -ENODEV;
+ }
/* search for subfunctions and disable them first */
if (!(dslot->dev->devfn & 7)) {
for (func = 1; func < 8; func++) {
@@ -328,8 +353,9 @@ static int disable_slot(struct hotplug_slot *slot)
/* remove the device from the pci core */
pci_remove_bus_device(dslot->dev);
- /* blow away this sysfs entry and other parts. */
- remove_slot(dslot);
+ /* queue work item to blow away this sysfs entry and other parts. */
+ INIT_WORK(&dslot->remove_work, remove_slot_worker);
+ queue_work(dummyphp_wq, &dslot->remove_work);
return 0;
}
@@ -340,6 +366,7 @@ static void cleanup_slots (void)
struct list_head *next;
struct dummy_slot *dslot;
+ destroy_workqueue(dummyphp_wq);
list_for_each_safe (tmp, next, &slot_list) {
dslot = list_entry (tmp, struct dummy_slot, node);
remove_slot(dslot);
@@ -351,6 +378,10 @@ static int __init dummyphp_init(void)
{
info(DRIVER_DESC "\n");
+ dummyphp_wq = create_singlethread_workqueue(MY_NAME);
+ if (!dummyphp_wq)
+ return -ENOMEM;
+
return pci_scan_buses();
}
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c
index a90c28d0c69..87b6b8b280e 100644
--- a/drivers/pci/hotplug/ibmphp_core.c
+++ b/drivers/pci/hotplug/ibmphp_core.c
@@ -761,10 +761,13 @@ static void ibm_unconfigure_device(struct pci_func *func)
debug("func->device << 3 | 0x0 = %x\n", func->device << 3 | 0x0);
for (j = 0; j < 0x08; j++) {
- temp = pci_find_slot(func->busno, (func->device << 3) | j);
- if (temp)
+ temp = pci_get_bus_and_slot(func->busno, (func->device << 3) | j);
+ if (temp) {
pci_remove_bus_device(temp);
+ pci_dev_put(temp);
+ }
}
+ pci_dev_put(func->dev);
}
/*
@@ -823,7 +826,7 @@ static int ibm_configure_device(struct pci_func *func)
if (!(bus_structure_fixup(func->busno)))
flag = 1;
if (func->dev == NULL)
- func->dev = pci_find_slot(func->busno,
+ func->dev = pci_get_bus_and_slot(func->busno,
PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
@@ -836,7 +839,7 @@ static int ibm_configure_device(struct pci_func *func)
if (num)
pci_bus_add_devices(bus);
- func->dev = pci_find_slot(func->busno,
+ func->dev = pci_get_bus_and_slot(func->busno,
PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) {
err("ERROR... : pci_dev still NULL\n");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 01c351c176a..dd59a050260 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -61,7 +61,7 @@ static int debug;
static LIST_HEAD(pci_hotplug_slot_list);
-struct kset pci_hotplug_slots_subsys;
+struct kset *pci_hotplug_slots_kset;
static ssize_t hotplug_slot_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
@@ -96,8 +96,6 @@ static struct kobj_type hotplug_slot_ktype = {
.release = &hotplug_slot_release,
};
-decl_subsys_name(pci_hotplug_slots, slots, &hotplug_slot_ktype, NULL);
-
/* these strings match up with the values in pci_bus_speed */
static char *pci_bus_speed_strings[] = {
"33 MHz PCI", /* 0x00 */
@@ -139,7 +137,7 @@ static int get_##name (struct hotplug_slot *slot, type *value) \
int retval = 0; \
if (try_module_get(ops->owner)) { \
if (ops->get_##name) \
- retval = ops->get_##name (slot, value); \
+ retval = ops->get_##name(slot, value); \
else \
*value = slot->info->name; \
module_put(ops->owner); \
@@ -627,23 +625,24 @@ int pci_hp_register (struct hotplug_slot *slot)
if ((slot->info == NULL) || (slot->ops == NULL))
return -EINVAL;
if (slot->release == NULL) {
- dbg("Why are you trying to register a hotplug slot"
+ dbg("Why are you trying to register a hotplug slot "
"without a proper release function?\n");
return -EINVAL;
}
- kobject_set_name(&slot->kobj, "%s", slot->name);
- kobj_set_kset_s(slot, pci_hotplug_slots_subsys);
-
/* this can fail if we have already registered a slot with the same name */
- if (kobject_register(&slot->kobj)) {
- err("Unable to register kobject");
+ slot->kobj.kset = pci_hotplug_slots_kset;
+ result = kobject_init_and_add(&slot->kobj, &hotplug_slot_ktype, NULL,
+ "%s", slot->name);
+ if (result) {
+ err("Unable to register kobject '%s'", slot->name);
return -EINVAL;
}
-
+
list_add (&slot->slot_list, &pci_hotplug_slot_list);
result = fs_add_slot (slot);
+ kobject_uevent(&slot->kobj, KOBJ_ADD);
dbg ("Added slot %s to the list\n", slot->name);
return result;
}
@@ -672,7 +671,7 @@ int pci_hp_deregister (struct hotplug_slot *slot)
fs_remove_slot (slot);
dbg ("Removed slot %s from the list\n", slot->name);
- kobject_unregister(&slot->kobj);
+ kobject_put(&slot->kobj);
return 0;
}
@@ -700,11 +699,15 @@ int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot,
static int __init pci_hotplug_init (void)
{
int result;
+ struct kset *pci_bus_kset;
- kobj_set_kset_s(&pci_hotplug_slots_subsys, pci_bus_type.subsys);
- result = subsystem_register(&pci_hotplug_slots_subsys);
- if (result) {
- err("Register subsys with error %d\n", result);
+ pci_bus_kset = bus_get_kset(&pci_bus_type);
+
+ pci_hotplug_slots_kset = kset_create_and_add("slots", NULL,
+ &pci_bus_kset->kobj);
+ if (!pci_hotplug_slots_kset) {
+ result = -ENOMEM;
+ err("Register subsys error\n");
goto exit;
}
result = cpci_hotplug_init(debug);
@@ -715,9 +718,9 @@ static int __init pci_hotplug_init (void)
info (DRIVER_DESC " version: " DRIVER_VERSION "\n");
goto exit;
-
+
err_subsys:
- subsystem_unregister(&pci_hotplug_slots_subsys);
+ kset_unregister(pci_hotplug_slots_kset);
exit:
return result;
}
@@ -725,7 +728,7 @@ exit:
static void __exit pci_hotplug_exit (void)
{
cpci_hotplug_exit();
- subsystem_unregister(&pci_hotplug_slots_subsys);
+ kset_unregister(pci_hotplug_slots_kset);
}
module_init(pci_hotplug_init);
@@ -737,7 +740,7 @@ MODULE_LICENSE("GPL");
module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
-EXPORT_SYMBOL_GPL(pci_hotplug_slots_subsys);
+EXPORT_SYMBOL_GPL(pci_hotplug_slots_kset);
EXPORT_SYMBOL_GPL(pci_hp_register);
EXPORT_SYMBOL_GPL(pci_hp_deregister);
EXPORT_SYMBOL_GPL(pci_hp_change_slot_info);
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 7959c222dc2..ca656b27a50 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -82,24 +82,18 @@ struct event_info {
};
struct controller {
- struct controller *next;
struct mutex crit_sect; /* critical section mutex */
struct mutex ctrl_lock; /* controller lock */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
struct pci_dev *pci_dev;
struct list_head slot_list;
- struct slot *slot;
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
- u8 bus;
- u8 device;
- u8 function;
u8 slot_device_offset;
u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u8 ctrlcap;
- u16 vendor_id;
u8 cap_base;
struct timer_list poll_timer;
volatile int cmd_busy;
@@ -161,6 +155,9 @@ 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 pcie_init(struct controller *ctrl, struct pcie_device *dev);
+int pciehp_enable_slot(struct slot *p_slot);
+int pciehp_disable_slot(struct slot *p_slot);
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev);
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 6462ac3b405..7f4836b8e71 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -453,13 +453,9 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
pci_set_drvdata(pdev, ctrl);
- ctrl->bus = pdev->bus->number; /* ctrl bus */
- ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */
-
- ctrl->device = PCI_SLOT(pdev->devfn);
- ctrl->function = PCI_FUNC(pdev->devfn);
- dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n", __FUNCTION__,
- ctrl->bus, ctrl->device, ctrl->function, pdev->irq);
+ dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
+ __FUNCTION__, pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn), pdev->irq);
/* Setup the slot information structures */
rc = init_slots(ctrl);
@@ -471,6 +467,11 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
+ if (value) {
+ rc = pciehp_enable_slot(t_slot);
+ if (rc) /* -ENODEV: shouldn't happen, but deal with it */
+ value = 0;
+ }
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
if (rc)
@@ -509,6 +510,24 @@ static int pciehp_suspend (struct pcie_device *dev, pm_message_t state)
static int pciehp_resume (struct pcie_device *dev)
{
printk("%s ENTRY\n", __FUNCTION__);
+ if (pciehp_force) {
+ struct pci_dev *pdev = dev->port;
+ struct controller *ctrl = pci_get_drvdata(pdev);
+ struct slot *t_slot;
+ u8 status;
+
+ /* reinitialize the chipset's event detection logic */
+ pcie_init_hardware_part2(ctrl, dev);
+
+ t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
+
+ /* Check if slot is occupied */
+ t_slot->hpc_ops->get_adapter_status(t_slot, &status);
+ if (status)
+ pciehp_enable_slot(t_slot);
+ else
+ pciehp_disable_slot(t_slot);
+ }
return 0;
}
#endif
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index c8cb49c5a75..b23061c5611 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -37,8 +37,6 @@
#include "pciehp.h"
static void interrupt_event_handler(struct work_struct *work);
-static int pciehp_enable_slot(struct slot *p_slot);
-static int pciehp_disable_slot(struct slot *p_slot);
static int queue_interrupt_event(struct slot *p_slot, u32 event_type)
{
@@ -197,33 +195,24 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
__FUNCTION__);
return;
}
- /*
- * After turning power off, we must wait for at least
- * 1 second before taking any action that relies on
- * power having been removed from the slot/adapter.
- */
- msleep(1000);
}
}
/**
* board_added - Called after a board has been added to the system.
+ * @p_slot: &slot where board is added
*
- * Turns power on for the board
- * Configures board
- *
+ * Turns power on for the board.
+ * Configures board.
*/
static int board_added(struct slot *p_slot)
{
- u8 hp_slot;
int retval = 0;
struct controller *ctrl = p_slot->ctrl;
- hp_slot = p_slot->device - ctrl->slot_device_offset;
-
dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
__FUNCTION__, p_slot->device,
- ctrl->slot_device_offset, hp_slot);
+ ctrl->slot_device_offset, p_slot->hp_slot);
if (POWER_CTRL(ctrl->ctrlcap)) {
/* Power on slot */
@@ -276,13 +265,11 @@ err_exit:
}
/**
- * remove_board - Turns off slot and LED's
- *
+ * remove_board - Turns off slot and LEDs
+ * @p_slot: slot where board is being removed
*/
static int remove_board(struct slot *p_slot)
{
- u8 device;
- u8 hp_slot;
int retval = 0;
struct controller *ctrl = p_slot->ctrl;
@@ -290,11 +277,7 @@ static int remove_board(struct slot *p_slot)
if (retval)
return retval;
- device = p_slot->device;
- hp_slot = p_slot->device - ctrl->slot_device_offset;
- p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
-
- dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
+ dbg("In %s, hp_slot = %d\n", __FUNCTION__, p_slot->hp_slot);
if (POWER_CTRL(ctrl->ctrlcap)) {
/* power off slot */
@@ -319,11 +302,11 @@ struct power_work_info {
};
/**
- * pciehp_pushbutton_thread
+ * pciehp_power_thread - handle pushbutton events
+ * @work: &struct work_struct describing work to be done
*
- * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Scheduled procedure to handle blocking stuff for the pushbuttons.
* Handles all pending events and exits.
- *
*/
static void pciehp_power_thread(struct work_struct *work)
{
@@ -621,12 +604,6 @@ int pciehp_disable_slot(struct slot *p_slot)
mutex_unlock(&p_slot->ctrl->crit_sect);
return -EINVAL;
}
- /*
- * After turning power off, we must wait for at least
- * 1 second before taking any action that relies on
- * power having been removed from the slot/adapter.
- */
- msleep(1000);
}
ret = remove_board(p_slot);
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 06d025b8b13..6eba9b2cfb9 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -636,15 +636,57 @@ static int hpc_power_on_slot(struct slot * slot)
return retval;
}
+static inline int pcie_mask_bad_dllp(struct controller *ctrl)
+{
+ struct pci_dev *dev = ctrl->pci_dev;
+ int pos;
+ u32 reg;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ return 0;
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+ if (reg & PCI_ERR_COR_BAD_DLLP)
+ return 0;
+ reg |= PCI_ERR_COR_BAD_DLLP;
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+ return 1;
+}
+
+static inline void pcie_unmask_bad_dllp(struct controller *ctrl)
+{
+ struct pci_dev *dev = ctrl->pci_dev;
+ u32 reg;
+ int pos;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ if (!pos)
+ return;
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &reg);
+ if (!(reg & PCI_ERR_COR_BAD_DLLP))
+ return;
+ reg &= ~PCI_ERR_COR_BAD_DLLP;
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, reg);
+}
+
static int hpc_power_off_slot(struct slot * slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
u16 cmd_mask;
int retval = 0;
+ int changed;
dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot);
+ /*
+ * Set Bad DLLP Mask bit in Correctable Error Mask
+ * Register. This is the workaround against Bad DLLP error
+ * that sometimes happens during turning power off the slot
+ * which conforms to PCI Express 1.0a spec.
+ */
+ changed = pcie_mask_bad_dllp(ctrl);
+
slot_cmd = POWER_OFF;
cmd_mask = PWR_CTRL;
/*
@@ -674,6 +716,16 @@ static int hpc_power_off_slot(struct slot * slot)
dbg("%s: SLOTCTRL %x write cmd %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);
+ /*
+ * After turning power off, we must wait for at least 1 second
+ * before taking any action that relies on power having been
+ * removed from the slot/adapter.
+ */
+ msleep(1000);
+
+ if (changed)
+ pcie_unmask_bad_dllp(ctrl);
+
return retval;
}
@@ -1067,13 +1119,143 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
}
#endif
-int pcie_init(struct controller * ctrl, struct pcie_device *dev)
+static int pcie_init_hardware_part1(struct controller *ctrl,
+ struct pcie_device *dev)
+{
+ int rc;
+ u16 temp_word;
+ u32 slot_cap;
+ u16 slot_status;
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+ err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+ return -1;
+ }
+
+ /* Mask Hot-plug Interrupt Enable */
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+ err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+ return -1;
+ }
+
+ dbg("%s: SLOTCTRL %x value read %x\n",
+ __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
+ temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
+ 0x00;
+
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+ return -1;
+ }
+
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+ err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+ return -1;
+ }
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+ return -1;
+ }
+ return 0;
+}
+
+int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
{
int rc;
u16 temp_word;
- u16 cap_reg;
u16 intr_enable = 0;
u32 slot_cap;
+ u16 slot_status;
+
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (rc) {
+ err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
+ goto abort;
+ }
+
+ intr_enable = intr_enable | PRSN_DETECT_ENABLE;
+
+ rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
+ if (rc) {
+ err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
+ goto abort;
+ }
+
+ if (ATTN_BUTTN(slot_cap))
+ intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
+
+ if (POWER_CTRL(slot_cap))
+ intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
+
+ if (MRL_SENS(slot_cap))
+ intr_enable = intr_enable | MRL_DETECT_ENABLE;
+
+ temp_word = (temp_word & ~intr_enable) | intr_enable;
+
+ if (pciehp_poll_mode) {
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
+ } else {
+ temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
+ }
+
+ /*
+ * Unmask Hot-plug Interrupt Enable for the interrupt
+ * notification mechanism case.
+ */
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
+ goto abort;
+ }
+ rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
+ if (rc) {
+ err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
+ goto abort_disable_intr;
+ }
+
+ temp_word = 0x1F; /* Clear all events */
+ rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
+ if (rc) {
+ err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
+ goto abort_disable_intr;
+ }
+
+ if (pciehp_force) {
+ dbg("Bypassing BIOS check for pciehp use on %s\n",
+ pci_name(ctrl->pci_dev));
+ } else {
+ rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+ if (rc)
+ goto abort_disable_intr;
+ }
+
+ return 0;
+
+ /* We end up here for the many possible ways to fail this API. */
+abort_disable_intr:
+ rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
+ if (!rc) {
+ temp_word &= ~(intr_enable | HP_INTR_ENABLE);
+ rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
+ }
+ if (rc)
+ err("%s : disabling interrupts failed\n", __FUNCTION__);
+abort:
+ return -1;
+}
+
+int pcie_init(struct controller *ctrl, struct pcie_device *dev)
+{
+ int rc;
+ u16 cap_reg;
+ u32 slot_cap;
int cap_base;
u16 slot_status, slot_ctrl;
struct pci_dev *pdev;
@@ -1084,9 +1266,10 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
__FUNCTION__, pdev->vendor, pdev->device);
- if ((cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP)) == 0) {
+ cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ if (cap_base == 0) {
dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
ctrl->cap_base = cap_base;
@@ -1096,7 +1279,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
if (rc) {
err("%s: Cannot read CAPREG register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: CAPREG offset %x cap_reg %x\n",
__FUNCTION__, ctrl->cap_base + CAPREG, cap_reg);
@@ -1106,26 +1289,26 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
dbg("%s : This is not a root port or the port is not "
"connected to a slot\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
if (rc) {
err("%s: Cannot read SLOTCAP register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: SLOTCAP offset %x slot_cap %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCAP, slot_cap);
if (!(slot_cap & HP_CAP)) {
dbg("%s : This slot is not hot-plug capable\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
/* For debugging purpose */
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
if (rc) {
err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
__FUNCTION__, ctrl->cap_base + SLOTSTATUS, slot_status);
@@ -1133,7 +1316,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
if (rc) {
err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_ctlr;
+ goto abort;
}
dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
__FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
@@ -1161,36 +1344,9 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
ctrl->first_slot = slot_cap >> 19;
ctrl->ctrlcap = slot_cap & 0x0000007f;
- /* Mask Hot-plug Interrupt Enable */
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- dbg("%s: SLOTCTRL %x value read %x\n",
- __FUNCTION__, ctrl->cap_base + SLOTCTRL, temp_word);
- temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
- 0x00;
-
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
- if (rc) {
- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
-
- temp_word = 0x1F; /* Clear all events */
- rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
- goto abort_free_ctlr;
- }
+ rc = pcie_init_hardware_part1(ctrl, dev);
+ if (rc)
+ goto abort;
if (pciehp_poll_mode) {
/* Install interrupt polling timer. Start with 10 sec delay */
@@ -1206,7 +1362,7 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
if (rc) {
err("Can't get irq %d for the hotplug controller\n",
ctrl->pci_dev->irq);
- goto abort_free_ctlr;
+ goto abort;
}
}
dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
@@ -1224,82 +1380,16 @@ int pcie_init(struct controller * ctrl, struct pcie_device *dev)
}
}
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (rc) {
- err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_irq;
+ rc = pcie_init_hardware_part2(ctrl, dev);
+ if (rc == 0) {
+ ctrl->hpc_ops = &pciehp_hpc_ops;
+ return 0;
}
-
- intr_enable = intr_enable | PRSN_DETECT_ENABLE;
-
- if (ATTN_BUTTN(slot_cap))
- intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
-
- if (POWER_CTRL(slot_cap))
- intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
-
- if (MRL_SENS(slot_cap))
- intr_enable = intr_enable | MRL_DETECT_ENABLE;
-
- temp_word = (temp_word & ~intr_enable) | intr_enable;
-
- if (pciehp_poll_mode) {
- temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
- } else {
- temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
- }
-
- /*
- * Unmask Hot-plug Interrupt Enable for the interrupt
- * notification mechanism case.
- */
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__);
- goto abort_free_irq;
- }
- rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
- if (rc) {
- err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__);
- goto abort_disable_intr;
- }
-
- temp_word = 0x1F; /* Clear all events */
- rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
- if (rc) {
- err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
- goto abort_disable_intr;
- }
-
- if (pciehp_force) {
- dbg("Bypassing BIOS check for pciehp use on %s\n",
- pci_name(ctrl->pci_dev));
- } else {
- rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
- if (rc)
- goto abort_disable_intr;
- }
-
- ctrl->hpc_ops = &pciehp_hpc_ops;
-
- return 0;
-
- /* We end up here for the many possible ways to fail this API. */
-abort_disable_intr:
- rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
- if (!rc) {
- temp_word &= ~(intr_enable | HP_INTR_ENABLE);
- rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
- }
- if (rc)
- err("%s : disabling interrupts failed\n", __FUNCTION__);
-
abort_free_irq:
if (pciehp_poll_mode)
del_timer_sync(&ctrl->poll_timer);
else
free_irq(ctrl->pci_dev->irq, ctrl);
-
-abort_free_ctlr:
+abort:
return -1;
}
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index c424aded13f..dd50713966d 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -105,12 +105,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
}
/* Find Advanced Error Reporting Enhanced Capability */
- pos = 256;
- do {
- pci_read_config_dword(dev, pos, &reg32);
- if (PCI_EXT_CAP_ID(reg32) == PCI_EXT_CAP_ID_ERR)
- break;
- } while ((pos = PCI_EXT_CAP_NEXT(reg32)));
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return;
@@ -248,11 +243,15 @@ int pciehp_unconfigure_device(struct slot *p_slot)
u8 bctl = 0;
u8 presence = 0;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ u16 command;
dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
p_slot->device);
+ ret = p_slot->hpc_ops->get_adapter_status(p_slot, &presence);
+ if (ret)
+ presence = 0;
- for (j=0; j<8 ; j++) {
+ for (j = 0; j < 8; j++) {
struct pci_dev* temp = pci_get_slot(parent,
(p_slot->device << 3) | j);
if (!temp)
@@ -263,21 +262,26 @@ int pciehp_unconfigure_device(struct slot *p_slot)
pci_dev_put(temp);
continue;
}
- if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- ret = p_slot->hpc_ops->get_adapter_status(p_slot,
- &presence);
- if (!ret && presence) {
- pci_read_config_byte(temp, PCI_BRIDGE_CONTROL,
- &bctl);
- if (bctl & PCI_BRIDGE_CTL_VGA) {
- err("Cannot remove display device %s\n",
- pci_name(temp));
- pci_dev_put(temp);
- continue;
- }
+ if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
+ pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+ if (bctl & PCI_BRIDGE_CTL_VGA) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ pci_dev_put(temp);
+ continue;
}
}
pci_remove_bus_device(temp);
+ /*
+ * Ensure that no new Requests will be generated from
+ * the device.
+ */
+ if (presence) {
+ pci_read_config_word(temp, PCI_COMMAND, &command);
+ command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+ command |= PCI_COMMAND_INTX_DISABLE;
+ pci_write_config_word(temp, PCI_COMMAND, command);
+ }
pci_dev_put(temp);
}
/*
@@ -288,4 +292,3 @@ int pciehp_unconfigure_device(struct slot *p_slot)
return rc;
}
-
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index deb6b5e35fe..191954bc8e5 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -100,6 +100,7 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
/**
* find_php_slot - return hotplug slot structure for device node
+ * @dn: target &device_node
*
* This routine will return the hotplug slot structure
* for a given device node. Note that built-in PCI slots
@@ -154,7 +155,7 @@ static void dlpar_pci_add_bus(struct device_node *dn)
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
of_scan_pci_bridge(dn, dev);
- pcibios_fixup_new_pci_devices(dev->subordinate,0);
+ pcibios_fixup_new_pci_devices(dev->subordinate);
/* Claim new bus resources */
pcibios_claim_one_bus(dev->bus);
@@ -293,9 +294,8 @@ static int dlpar_add_vio_slot(char *drc_name, struct device_node *dn)
* dlpar_add_slot - DLPAR add an I/O Slot
* @drc_name: drc-name of newly added slot
*
- * Make the hotplug module and the kernel aware
- * of a newly added I/O Slot.
- * Return Codes -
+ * Make the hotplug module and the kernel aware of a newly added I/O Slot.
+ * Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
* -EINVAL Slot already added
@@ -339,9 +339,9 @@ exit:
/**
* dlpar_remove_vio_slot - DLPAR remove a virtual I/O Slot
* @drc_name: drc-name of newly added slot
+ * @dn: &device_node
*
- * Remove the kernel and hotplug representations
- * of an I/O Slot.
+ * Remove the kernel and hotplug representations of an I/O Slot.
* Return Codes:
* 0 Success
* -EINVAL Vio dev doesn't exist
@@ -359,11 +359,11 @@ static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
}
/**
- * dlpar_remove_slot - DLPAR remove a PCI I/O Slot
+ * dlpar_remove_pci_slot - DLPAR remove a PCI I/O Slot
* @drc_name: drc-name of newly added slot
+ * @dn: &device_node
*
- * Remove the kernel and hotplug representations
- * of a PCI I/O Slot.
+ * Remove the kernel and hotplug representations of a PCI I/O Slot.
* Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
@@ -405,8 +405,7 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
* dlpar_remove_slot - DLPAR remove an I/O Slot
* @drc_name: drc-name of newly added slot
*
- * Remove the kernel and hotplug representations
- * of an I/O Slot.
+ * Remove the kernel and hotplug representations of an I/O Slot.
* Return Codes:
* 0 Success
* -ENODEV Not a valid drc_name
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index a080fedf033..e32148a8fa1 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -23,44 +23,13 @@
#define MAX_DRC_NAME_LEN 64
-/* Store return code of dlpar operation in attribute struct */
-struct dlpar_io_attr {
- int rc;
- struct attribute attr;
- ssize_t (*store)(struct dlpar_io_attr *dlpar_attr, const char *buf,
- size_t nbytes);
-};
-/* Common show callback for all attrs, display the return code
- * of the dlpar op */
-static ssize_t
-dlpar_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
-{
- struct dlpar_io_attr *dlpar_attr = container_of(attr,
- struct dlpar_io_attr, attr);
- return sprintf(buf, "%d\n", dlpar_attr->rc);
-}
-
-static ssize_t
-dlpar_attr_store(struct kobject * kobj, struct attribute * attr,
- const char *buf, size_t nbytes)
-{
- struct dlpar_io_attr *dlpar_attr = container_of(attr,
- struct dlpar_io_attr, attr);
- return dlpar_attr->store ?
- dlpar_attr->store(dlpar_attr, buf, nbytes) : -EIO;
-}
-
-static struct sysfs_ops dlpar_attr_sysfs_ops = {
- .show = dlpar_attr_show,
- .store = dlpar_attr_store,
-};
-
-static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr,
- const char *buf, size_t nbytes)
+static ssize_t add_slot_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t nbytes)
{
char drc_name[MAX_DRC_NAME_LEN];
char *end;
+ int rc;
if (nbytes >= MAX_DRC_NAME_LEN)
return 0;
@@ -72,15 +41,25 @@ static ssize_t add_slot_store(struct dlpar_io_attr *dlpar_attr,
end = &drc_name[nbytes];
*end = '\0';
- dlpar_attr->rc = dlpar_add_slot(drc_name);
+ rc = dlpar_add_slot(drc_name);
+ if (rc)
+ return rc;
return nbytes;
}
-static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr,
- const char *buf, size_t nbytes)
+static ssize_t add_slot_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "0\n");
+}
+
+static ssize_t remove_slot_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t nbytes)
{
char drc_name[MAX_DRC_NAME_LEN];
+ int rc;
char *end;
if (nbytes >= MAX_DRC_NAME_LEN)
@@ -93,22 +72,24 @@ static ssize_t remove_slot_store(struct dlpar_io_attr *dlpar_attr,
end = &drc_name[nbytes];
*end = '\0';
- dlpar_attr->rc = dlpar_remove_slot(drc_name);
+ rc = dlpar_remove_slot(drc_name);
+ if (rc)
+ return rc;
return nbytes;
}
-static struct dlpar_io_attr add_slot_attr = {
- .rc = 0,
- .attr = { .name = ADD_SLOT_ATTR_NAME, .mode = 0644, },
- .store = add_slot_store,
-};
+static ssize_t remove_slot_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return sprintf(buf, "0\n");
+}
-static struct dlpar_io_attr remove_slot_attr = {
- .rc = 0,
- .attr = { .name = REMOVE_SLOT_ATTR_NAME, .mode = 0644},
- .store = remove_slot_store,
-};
+static struct kobj_attribute add_slot_attr =
+ __ATTR(ADD_SLOT_ATTR_NAME, 0644, add_slot_show, add_slot_store);
+
+static struct kobj_attribute remove_slot_attr =
+ __ATTR(REMOVE_SLOT_ATTR_NAME, 0644, remove_slot_show, remove_slot_store);
static struct attribute *default_attrs[] = {
&add_slot_attr.attr,
@@ -116,37 +97,29 @@ static struct attribute *default_attrs[] = {
NULL,
};
-static void dlpar_io_release(struct kobject *kobj)
-{
- /* noop */
- return;
-}
-
-struct kobj_type ktype_dlpar_io = {
- .release = dlpar_io_release,
- .sysfs_ops = &dlpar_attr_sysfs_ops,
- .default_attrs = default_attrs,
+static struct attribute_group dlpar_attr_group = {
+ .attrs = default_attrs,
};
-struct kset dlpar_io_kset = {
- .kobj = {.ktype = &ktype_dlpar_io,
- .parent = &pci_hotplug_slots_subsys.kobj},
- .ktype = &ktype_dlpar_io,
-};
+static struct kobject *dlpar_kobj;
int dlpar_sysfs_init(void)
{
- kobject_set_name(&dlpar_io_kset.kobj, DLPAR_KOBJ_NAME);
- if (kset_register(&dlpar_io_kset)) {
- printk(KERN_ERR "rpadlpar_io: cannot register kset for %s\n",
- kobject_name(&dlpar_io_kset.kobj));
+ int error;
+
+ dlpar_kobj = kobject_create_and_add(DLPAR_KOBJ_NAME,
+ &pci_hotplug_slots_kset->kobj);
+ if (!dlpar_kobj)
return -EINVAL;
- }
- return 0;
+ error = sysfs_create_group(dlpar_kobj, &dlpar_attr_group);
+ if (error)
+ kobject_put(dlpar_kobj);
+ return error;
}
void dlpar_sysfs_exit(void)
{
- kset_unregister(&dlpar_io_kset);
+ sysfs_remove_group(dlpar_kobj, &dlpar_attr_group);
+ kobject_put(dlpar_kobj);
}
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index c822a779653..7d5921b1ee7 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -74,7 +74,6 @@ struct slot {
u32 type;
u32 power_domain;
char *name;
- char *location;
struct device_node *dn;
struct pci_bus *bus;
struct list_head *pci_devs;
diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
index 458c08ef265..58f1a992770 100644
--- a/drivers/pci/hotplug/rpaphp_core.c
+++ b/drivers/pci/hotplug/rpaphp_core.c
@@ -54,10 +54,12 @@ module_param(debug, bool, 0644);
/**
* set_attention_status - set attention LED
+ * @hotplug_slot: target &hotplug_slot
+ * @value: LED control value
+ *
* echo 0 > attention -- set LED OFF
* echo 1 > attention -- set LED ON
* echo 2 > attention -- set LED ID(identify, light is blinking)
- *
*/
static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
{
@@ -99,6 +101,8 @@ static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value)
/**
* get_attention_status - get attention LED status
+ * @hotplug_slot: slot to get status
+ * @value: pointer to store status
*/
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value)
{
@@ -254,6 +258,11 @@ static int is_php_type(char *drc_type)
/**
* is_php_dn() - return 1 if this is a hotpluggable pci slot, else 0
+ * @dn: target &device_node
+ * @indexes: passed to get_children_props()
+ * @names: passed to get_children_props()
+ * @types: returned from get_children_props()
+ * @power_domains:
*
* This routine will return true only if the device node is
* a hotpluggable slot. This routine will return false
@@ -279,7 +288,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
/**
* rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.
- * @dn device node of slot
+ * @dn: device node of slot
*
* This subroutine will register a hotplugable slot with the
* PCI hotplug infrastructure. This routine is typicaly called
@@ -291,7 +300,7 @@ static int is_php_dn(struct device_node *dn, const int **indexes,
* routine will just return without doing anything, since embedded
* slots cannot be hotplugged.
*
- * To remove a slot, it suffices to call rpaphp_deregister_slot()
+ * To remove a slot, it suffices to call rpaphp_deregister_slot().
*/
int rpaphp_add_slot(struct device_node *dn)
{
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index 54ca8650d51..6571e9b4c2e 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -64,21 +64,9 @@ int rpaphp_get_sensor_state(struct slot *slot, int *state)
return rc;
}
-static void set_slot_name(struct slot *slot)
-{
- struct pci_bus *bus = slot->bus;
- struct pci_dev *bridge;
-
- bridge = bus->self;
- if (bridge)
- strcpy(slot->name, pci_name(bridge));
- else
- sprintf(slot->name, "%04x:%02x:00.0", pci_domain_nr(bus),
- bus->number);
-}
-
/**
* rpaphp_enable_slot - record slot state, config pci device
+ * @slot: target &slot
*
* Initialize values in the slot, and the hotplug_slot info
* structures to indicate if there is a pci card plugged into
@@ -114,7 +102,6 @@ int rpaphp_enable_slot(struct slot *slot)
info->adapter_status = EMPTY;
slot->bus = bus;
slot->pci_devs = &bus->devices;
- set_slot_name(slot);
/* if there's an adapter in the slot, go add the pci devices */
if (state == PRESENT) {
diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index d4ee8723fcb..8ad3debb379 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -33,23 +33,31 @@
#include <asm/rtas.h>
#include "rpaphp.h"
-static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
+static ssize_t address_read_file (struct hotplug_slot *php_slot, char *buf)
{
- char *value;
- int retval = -ENOENT;
+ int retval;
struct slot *slot = (struct slot *)php_slot->private;
+ struct pci_bus *bus;
if (!slot)
- return retval;
+ return -ENOENT;
+
+ bus = slot->bus;
+ if (!bus)
+ return -ENOENT;
+
+ if (bus->self)
+ retval = sprintf(buf, pci_name(bus->self));
+ else
+ retval = sprintf(buf, "%04x:%02x:00.0",
+ pci_domain_nr(bus), bus->number);
- value = slot->location;
- retval = sprintf (buf, "%s\n", value);
return retval;
}
-static struct hotplug_slot_attribute php_attr_location = {
- .attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
- .show = location_read_file,
+static struct hotplug_slot_attribute php_attr_address = {
+ .attr = {.name = "address", .mode = S_IFREG | S_IRUGO},
+ .show = address_read_file,
};
/* free up the memory used by a slot */
@@ -64,7 +72,6 @@ void dealloc_slot_struct(struct slot *slot)
kfree(slot->hotplug_slot->info);
kfree(slot->hotplug_slot->name);
kfree(slot->hotplug_slot);
- kfree(slot->location);
kfree(slot);
}
@@ -83,16 +90,13 @@ struct slot *alloc_slot_struct(struct device_node *dn,
GFP_KERNEL);
if (!slot->hotplug_slot->info)
goto error_hpslot;
- slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
+ slot->hotplug_slot->name = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
if (!slot->hotplug_slot->name)
goto error_info;
- slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
- if (!slot->location)
- goto error_name;
slot->name = slot->hotplug_slot->name;
+ strcpy(slot->name, drc_name);
slot->dn = dn;
slot->index = drc_index;
- strcpy(slot->location, drc_name);
slot->power_domain = power_domain;
slot->hotplug_slot->private = slot;
slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
@@ -100,8 +104,6 @@ struct slot *alloc_slot_struct(struct device_node *dn,
return (slot);
-error_name:
- kfree(slot->hotplug_slot->name);
error_info:
kfree(slot->hotplug_slot->info);
error_hpslot:
@@ -133,8 +135,8 @@ int rpaphp_deregister_slot(struct slot *slot)
list_del(&slot->rpaphp_slot_list);
- /* remove "phy_location" file */
- sysfs_remove_file(&php_slot->kobj, &php_attr_location.attr);
+ /* remove "address" file */
+ sysfs_remove_file(&php_slot->kobj, &php_attr_address.attr);
retval = pci_hp_deregister(php_slot);
if (retval)
@@ -166,8 +168,8 @@ int rpaphp_register_slot(struct slot *slot)
return retval;
}
- /* create "phy_location" file */
- retval = sysfs_create_file(&php_slot->kobj, &php_attr_location.attr);
+ /* create "address" file */
+ retval = sysfs_create_file(&php_slot->kobj, &php_attr_address.attr);
if (retval) {
err("sysfs_create_file failed with error %d\n", retval);
goto sysfs_fail;
@@ -175,8 +177,7 @@ int rpaphp_register_slot(struct slot *slot)
/* add slot to our internal list */
list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
- info("Slot [%s](PCI location=%s) registered\n", slot->name,
- slot->location);
+ info("Slot [%s] registered\n", slot->name);
return 0;
sysfs_fail:
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index d2fc35598cd..eb5cac6f08a 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -231,10 +231,10 @@ static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,
/**
* board_added - Called after a board has been added to the system.
+ * @p_slot: target &slot
*
- * Turns power on for the board
- * Configures board
- *
+ * Turns power on for the board.
+ * Configures board.
*/
static int board_added(struct slot *p_slot)
{
@@ -350,8 +350,8 @@ err_exit:
/**
- * remove_board - Turns off slot and LED's
- *
+ * remove_board - Turns off slot and LEDs
+ * @p_slot: target &slot
*/
static int remove_board(struct slot *p_slot)
{
@@ -397,11 +397,11 @@ struct pushbutton_work_info {
};
/**
- * shpchp_pushbutton_thread
+ * shpchp_pushbutton_thread - handle pushbutton events
+ * @work: &struct work_struct to be handled
*
- * Scheduled procedure to handle blocking stuff for the pushbuttons
+ * Scheduled procedure to handle blocking stuff for the pushbuttons.
* Handles all pending events and exits.
- *
*/
static void shpchp_pushbutton_thread(struct work_struct *work)
{
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 5183a45d45b..e8aa138128c 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -597,7 +597,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
cleanup_slots(ctrl);
/*
- * Mask SERR and System Interrut generation
+ * Mask SERR and System Interrupt generation
*/
serr_int = shpc_readl(ctrl, SERR_INTR_ENABLE);
serr_int |= (GLOBAL_INTR_MASK | GLOBAL_SERR_MASK |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index 0c4ab3b0727..4e01df99681 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -34,7 +34,7 @@
#include "intel-iommu.h"
#include <asm/proto.h> /* force_iommu in this header in x86-64*/
#include <asm/cacheflush.h>
-#include <asm/iommu.h>
+#include <asm/gart.h>
#include "pci.h"
#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
@@ -745,12 +745,12 @@ static char *fault_reason_strings[] =
"non-zero reserved fields in PTE",
"Unknown"
};
-#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings)
+#define MAX_FAULT_REASON_IDX ARRAY_SIZE(fault_reason_strings) - 1
char *dmar_get_fault_reason(u8 fault_reason)
{
- if (fault_reason > MAX_FAULT_REASON_IDX)
- return fault_reason_strings[MAX_FAULT_REASON_IDX];
+ if (fault_reason >= MAX_FAULT_REASON_IDX)
+ return fault_reason_strings[MAX_FAULT_REASON_IDX - 1];
else
return fault_reason_strings[fault_reason];
}
@@ -995,7 +995,6 @@ static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd)
return iommu;
error_unmap:
iounmap(iommu->reg);
- iommu->reg = 0;
error:
kfree(iommu);
return NULL;
@@ -1782,7 +1781,7 @@ __intel_alloc_iova(struct device *dev, struct dmar_domain *domain,
/*
* First try to allocate an io virtual address in
* DMA_32BIT_MASK and if that fails then try allocating
- * from higer range
+ * from higher range
*/
iova = iommu_alloc_iova(domain, size, DMA_32BIT_MASK);
if (!iova)
@@ -1808,7 +1807,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
if (!domain) {
printk(KERN_ERR
"Allocating domain for %s failed", pci_name(pdev));
- return 0;
+ return NULL;
}
/* make sure context mapping is ok */
@@ -1818,7 +1817,7 @@ get_valid_domain_for_dev(struct pci_dev *pdev)
printk(KERN_ERR
"Domain context map for %s failed",
pci_name(pdev));
- return 0;
+ return NULL;
}
}
diff --git a/drivers/pci/intel-iommu.h b/drivers/pci/intel-iommu.h
index ee88dd2400c..459ad1f9dc5 100644
--- a/drivers/pci/intel-iommu.h
+++ b/drivers/pci/intel-iommu.h
@@ -58,7 +58,7 @@
hi = readl(dmar + reg + 4); \
(((u64) hi) << 32) + lo; })
*/
-static inline u64 dmar_readq(void *addr)
+static inline u64 dmar_readq(void __iomem *addr)
{
u32 lo, hi;
lo = readl(addr);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 87e01615053..26938da8f43 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -25,6 +25,51 @@
static int pci_msi_enable = 1;
+/* Arch hooks */
+
+int __attribute__ ((weak))
+arch_msi_check_device(struct pci_dev *dev, int nvec, int type)
+{
+ return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
+{
+ return 0;
+}
+
+int __attribute__ ((weak))
+arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ struct msi_desc *entry;
+ int ret;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ ret = arch_setup_msi_irq(dev, entry);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
+{
+ return;
+}
+
+void __attribute__ ((weak))
+arch_teardown_msi_irqs(struct pci_dev *dev)
+{
+ struct msi_desc *entry;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (entry->irq != 0)
+ arch_teardown_msi_irq(entry->irq);
+ }
+}
+
static void msi_set_enable(struct pci_dev *dev, int enable)
{
int pos;
@@ -224,7 +269,12 @@ static struct msi_desc* alloc_msi_entry(void)
return entry;
}
-#ifdef CONFIG_PM
+static void pci_intx_for_msi(struct pci_dev *dev, int enable)
+{
+ if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG))
+ pci_intx(dev, enable);
+}
+
static void __pci_restore_msi_state(struct pci_dev *dev)
{
int pos;
@@ -237,7 +287,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
entry = get_irq_msi(dev->irq);
pos = entry->msi_attrib.pos;
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msi_set_enable(dev, 0);
write_msi_msg(dev->irq, &entry->msg);
if (entry->msi_attrib.maskbit)
@@ -260,7 +310,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
return;
/* route the table */
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msix_set_enable(dev, 0);
list_for_each_entry(entry, &dev->msi_list, list) {
@@ -282,7 +332,7 @@ void pci_restore_msi_state(struct pci_dev *dev)
__pci_restore_msi_state(dev);
__pci_restore_msix_state(dev);
}
-#endif /* CONFIG_PM */
+EXPORT_SYMBOL_GPL(pci_restore_msi_state);
/**
* msi_capability_init - configure device's MSI capability structure
@@ -343,7 +393,7 @@ static int msi_capability_init(struct pci_dev *dev)
}
/* Set MSI enabled bits */
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msi_set_enable(dev, 1);
dev->msi_enabled = 1;
@@ -433,7 +483,7 @@ static int msix_capability_init(struct pci_dev *dev,
i++;
}
/* Set MSI-X enabled bits */
- pci_intx(dev, 0); /* disable intx */
+ pci_intx_for_msi(dev, 0);
msix_set_enable(dev, 1);
dev->msix_enabled = 1;
@@ -528,7 +578,7 @@ void pci_disable_msi(struct pci_dev* dev)
return;
msi_set_enable(dev, 0);
- pci_intx(dev, 1); /* enable intx */
+ pci_intx_for_msi(dev, 1);
dev->msi_enabled = 0;
BUG_ON(list_empty(&dev->msi_list));
@@ -640,7 +690,7 @@ void pci_disable_msix(struct pci_dev* dev)
return;
msix_set_enable(dev, 0);
- pci_intx(dev, 1); /* enable intx */
+ pci_intx_for_msi(dev, 1);
dev->msix_enabled = 0;
msix_free_all_irqs(dev);
@@ -677,49 +727,3 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
{
INIT_LIST_HEAD(&dev->msi_list);
}
-
-
-/* Arch hooks */
-
-int __attribute__ ((weak))
-arch_msi_check_device(struct pci_dev* dev, int nvec, int type)
-{
- return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *entry)
-{
- return 0;
-}
-
-int __attribute__ ((weak))
-arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
-{
- struct msi_desc *entry;
- int ret;
-
- list_for_each_entry(entry, &dev->msi_list, list) {
- ret = arch_setup_msi_irq(dev, entry);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-void __attribute__ ((weak)) arch_teardown_msi_irq(unsigned int irq)
-{
- return;
-}
-
-void __attribute__ ((weak))
-arch_teardown_msi_irqs(struct pci_dev *dev)
-{
- struct msi_desc *entry;
-
- list_for_each_entry(entry, &dev->msi_list, list) {
- if (entry->irq != 0)
- arch_teardown_msi_irq(entry->irq);
- }
-}
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 5c6a5d04300..e569645d59e 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -156,13 +156,13 @@ run_osc_out:
}
/**
- * pci_osc_support_set - register OS support to Firmware
+ * __pci_osc_support_set - register OS support to Firmware
* @flags: OS support bits
*
* Update OS support fields and doing a _OSC Query to obtain an update
* from Firmware on supported control bits.
**/
-acpi_status pci_osc_support_set(u32 flags)
+acpi_status __pci_osc_support_set(u32 flags, const char *hid)
{
u32 temp;
acpi_status retval;
@@ -176,7 +176,7 @@ acpi_status pci_osc_support_set(u32 flags)
temp = ctrlset_buf[OSC_CONTROL_TYPE];
ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
- acpi_get_devices ( PCI_ROOT_HID_STRING,
+ acpi_get_devices(hid,
acpi_query_osc,
ctrlset_buf,
(void **) &retval );
@@ -188,7 +188,6 @@ acpi_status pci_osc_support_set(u32 flags)
}
return AE_OK;
}
-EXPORT_SYMBOL(pci_osc_support_set);
/**
* pci_osc_control_set - commit requested control to Firmware
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 6e2760b6c20..e571c72e675 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -1,6 +1,11 @@
/*
* drivers/pci/pci-driver.c
*
+ * (C) Copyright 2002-2004, 2007 Greg Kroah-Hartman <greg@kroah.com>
+ * (C) Copyright 2007 Novell Inc.
+ *
+ * Released under the GPL v2 only.
+ *
*/
#include <linux/pci.h>
@@ -96,17 +101,21 @@ pci_create_newid_file(struct pci_driver *drv)
{
int error = 0;
if (drv->probe != NULL)
- error = sysfs_create_file(&drv->driver.kobj,
- &driver_attr_new_id.attr);
+ error = driver_create_file(&drv->driver, &driver_attr_new_id);
return error;
}
+static void pci_remove_newid_file(struct pci_driver *drv)
+{
+ driver_remove_file(&drv->driver, &driver_attr_new_id);
+}
#else /* !CONFIG_HOTPLUG */
static inline void pci_free_dynids(struct pci_driver *drv) {}
static inline int pci_create_newid_file(struct pci_driver *drv)
{
return 0;
}
+static inline void pci_remove_newid_file(struct pci_driver *drv) {}
#endif
/**
@@ -143,8 +152,8 @@ const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
* system is in its list of supported devices. Returns the matching
* pci_device_id structure or %NULL if there is no match.
*/
-const struct pci_device_id *pci_match_device(struct pci_driver *drv,
- struct pci_dev *dev)
+static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
+ struct pci_dev *dev)
{
struct pci_dynid *dynid;
@@ -177,13 +186,11 @@ static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
set_cpus_allowed(current, node_to_cpumask(node));
/* And set default memory allocation policy */
oldpol = current->mempolicy;
- current->mempolicy = &default_policy;
- mpol_get(current->mempolicy);
+ current->mempolicy = NULL; /* fall back to system default policy */
#endif
error = drv->probe(dev, id);
#ifdef CONFIG_NUMA
set_cpus_allowed(current, oldmask);
- mpol_free(current->mempolicy);
current->mempolicy = oldpol;
#endif
return error;
@@ -352,50 +359,6 @@ static void pci_device_shutdown(struct device *dev)
drv->shutdown(pci_dev);
}
-#define kobj_to_pci_driver(obj) container_of(obj, struct device_driver, kobj)
-#define attr_to_driver_attribute(obj) container_of(obj, struct driver_attribute, attr)
-
-static ssize_t
-pci_driver_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
-{
- struct device_driver *driver = kobj_to_pci_driver(kobj);
- struct driver_attribute *dattr = attr_to_driver_attribute(attr);
- ssize_t ret;
-
- if (!get_driver(driver))
- return -ENODEV;
-
- ret = dattr->show ? dattr->show(driver, buf) : -EIO;
-
- put_driver(driver);
- return ret;
-}
-
-static ssize_t
-pci_driver_attr_store(struct kobject * kobj, struct attribute *attr,
- const char *buf, size_t count)
-{
- struct device_driver *driver = kobj_to_pci_driver(kobj);
- struct driver_attribute *dattr = attr_to_driver_attribute(attr);
- ssize_t ret;
-
- if (!get_driver(driver))
- return -ENODEV;
-
- ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
-
- put_driver(driver);
- return ret;
-}
-
-static struct sysfs_ops pci_driver_sysfs_ops = {
- .show = pci_driver_attr_show,
- .store = pci_driver_attr_store,
-};
-static struct kobj_type pci_driver_kobj_type = {
- .sysfs_ops = &pci_driver_sysfs_ops,
-};
-
/**
* __pci_register_driver - register a new pci driver
* @drv: the driver structure to register
@@ -417,7 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
drv->driver.bus = &pci_bus_type;
drv->driver.owner = owner;
drv->driver.mod_name = mod_name;
- drv->driver.kobj.ktype = &pci_driver_kobj_type;
spin_lock_init(&drv->dynids.lock);
INIT_LIST_HEAD(&drv->dynids.list);
@@ -447,6 +409,7 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
void
pci_unregister_driver(struct pci_driver *drv)
{
+ pci_remove_newid_file(drv);
driver_unregister(&drv->driver);
pci_free_dynids(drv);
}
@@ -559,7 +522,6 @@ static int __init pci_driver_init(void)
postcore_initcall(pci_driver_init);
EXPORT_SYMBOL(pci_match_id);
-EXPORT_SYMBOL(pci_match_device);
EXPORT_SYMBOL(__pci_register_driver);
EXPORT_SYMBOL(pci_unregister_driver);
EXPORT_SYMBOL(pci_dev_driver);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 1b7b2812bf2..abf4203304e 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -21,6 +21,7 @@
#include <linux/topology.h>
#include <linux/mm.h>
#include <linux/capability.h>
+#include <linux/aspm.h>
#include "pci.h"
static int sysfs_initialized; /* = 0 */
@@ -358,7 +359,7 @@ pci_read_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
- struct class_device,
+ struct device,
kobj));
/* Only support 1, 2 or 4 byte accesses */
@@ -383,7 +384,7 @@ pci_write_legacy_io(struct kobject *kobj, struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
- struct class_device,
+ struct device,
kobj));
/* Only support 1, 2 or 4 byte accesses */
if (count != 1 && count != 2 && count != 4)
@@ -407,7 +408,7 @@ pci_mmap_legacy_mem(struct kobject *kobj, struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(container_of(kobj,
- struct class_device,
+ struct device,
kobj));
return pci_mmap_legacy_page_range(bus, vma);
@@ -650,6 +651,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
if (pcibios_add_platform_entries(pdev))
goto err_rom_file;
+ pcie_aspm_create_sysfs_dev_files(pdev);
+
return 0;
err_rom_file:
@@ -679,6 +682,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
if (!sysfs_initialized)
return;
+ pcie_aspm_remove_sysfs_dev_files(pdev);
+
if (pdev->cfg_size < 4096)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else
@@ -702,8 +707,10 @@ static int __init pci_sysfs_init(void)
sysfs_initialized = 1;
for_each_pci_dev(pdev) {
retval = pci_create_sysfs_dev_files(pdev);
- if (retval)
+ if (retval) {
+ pci_dev_put(pdev);
return retval;
+ }
}
return 0;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 71d561fda0a..b3e9294e4a0 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -18,6 +18,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/log2.h>
+#include <linux/aspm.h>
#include <asm/dma.h> /* isa_dma_bridge_buggy */
#include "pci.h"
@@ -314,6 +315,24 @@ int pci_find_ht_capability(struct pci_dev *dev, int ht_cap)
}
EXPORT_SYMBOL_GPL(pci_find_ht_capability);
+void pcie_wait_pending_transaction(struct pci_dev *dev)
+{
+ int pos;
+ u16 reg16;
+
+ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ while (1) {
+ pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
+ if (!(reg16 & PCI_EXP_DEVSTA_TRPND))
+ break;
+ cpu_relax();
+ }
+
+}
+EXPORT_SYMBOL_GPL(pcie_wait_pending_transaction);
+
/**
* pci_find_parent_resource - return resource region of parent bus of given region
* @dev: PCI device structure contains resources to be searched
@@ -353,7 +372,7 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
* Restore the BAR values for a given device, so as to make it
* accessible by its driver.
*/
-void
+static void
pci_restore_bars(struct pci_dev *dev)
{
int i, numres;
@@ -501,6 +520,9 @@ pci_set_power_state(struct pci_dev *dev, pci_power_t state)
if (need_restore)
pci_restore_bars(dev);
+ if (dev->bus->self)
+ pcie_aspm_pm_state_change(dev->bus->self);
+
return 0;
}
@@ -551,6 +573,7 @@ static int pci_save_pcie_state(struct pci_dev *dev)
int pos, i = 0;
struct pci_cap_saved_state *save_state;
u16 *cap;
+ int found = 0;
pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
if (pos <= 0)
@@ -559,6 +582,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
if (!save_state)
save_state = kzalloc(sizeof(*save_state) + sizeof(u16) * 4, GFP_KERNEL);
+ else
+ found = 1;
if (!save_state) {
dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
return -ENOMEM;
@@ -569,7 +594,9 @@ static int pci_save_pcie_state(struct pci_dev *dev)
pci_read_config_word(dev, pos + PCI_EXP_LNKCTL, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_SLTCTL, &cap[i++]);
pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &cap[i++]);
- pci_add_saved_cap(dev, save_state);
+ save_state->cap_nr = PCI_CAP_ID_EXP;
+ if (!found)
+ pci_add_saved_cap(dev, save_state);
return 0;
}
@@ -597,14 +624,17 @@ static int pci_save_pcix_state(struct pci_dev *dev)
int pos, i = 0;
struct pci_cap_saved_state *save_state;
u16 *cap;
+ int found = 0;
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (pos <= 0)
return 0;
- save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+ save_state = pci_find_saved_cap(dev, PCI_CAP_ID_PCIX);
if (!save_state)
save_state = kzalloc(sizeof(*save_state) + sizeof(u16), GFP_KERNEL);
+ else
+ found = 1;
if (!save_state) {
dev_err(&dev->dev, "Out of memory in pci_save_pcie_state\n");
return -ENOMEM;
@@ -612,7 +642,9 @@ static int pci_save_pcix_state(struct pci_dev *dev)
cap = (u16 *)&save_state->data[0];
pci_read_config_word(dev, pos + PCI_X_CMD, &cap[i++]);
- pci_add_saved_cap(dev, save_state);
+ save_state->cap_nr = PCI_CAP_ID_PCIX;
+ if (!found)
+ pci_add_saved_cap(dev, save_state);
return 0;
}
@@ -713,23 +745,19 @@ int pci_reenable_device(struct pci_dev *dev)
return 0;
}
-/**
- * pci_enable_device_bars - Initialize some of a device for use
- * @dev: PCI device to be initialized
- * @bars: bitmask of BAR's that must be configured
- *
- * Initialize device before it's used by a driver. Ask low-level code
- * to enable selected I/O and memory resources. Wake up the device if it
- * was suspended. Beware, this function can fail.
- */
-int
-pci_enable_device_bars(struct pci_dev *dev, int bars)
+static int __pci_enable_device_flags(struct pci_dev *dev,
+ resource_size_t flags)
{
int err;
+ int i, bars = 0;
if (atomic_add_return(1, &dev->enable_cnt) > 1)
return 0; /* already enabled */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+ if (dev->resource[i].flags & flags)
+ bars |= (1 << i);
+
err = do_pci_enable_device(dev, bars);
if (err < 0)
atomic_dec(&dev->enable_cnt);
@@ -737,6 +765,32 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
}
/**
+ * pci_enable_device_io - Initialize a device for use with IO space
+ * @dev: PCI device to be initialized
+ *
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable I/O resources. Wake up the device if it was suspended.
+ * Beware, this function can fail.
+ */
+int pci_enable_device_io(struct pci_dev *dev)
+{
+ return __pci_enable_device_flags(dev, IORESOURCE_IO);
+}
+
+/**
+ * pci_enable_device_mem - Initialize a device for use with Memory space
+ * @dev: PCI device to be initialized
+ *
+ * Initialize device before it's used by a driver. Ask low-level code
+ * to enable Memory resources. Wake up the device if it was suspended.
+ * Beware, this function can fail.
+ */
+int pci_enable_device_mem(struct pci_dev *dev)
+{
+ return __pci_enable_device_flags(dev, IORESOURCE_MEM);
+}
+
+/**
* pci_enable_device - Initialize device before it's used by a driver.
* @dev: PCI device to be initialized
*
@@ -749,7 +803,7 @@ pci_enable_device_bars(struct pci_dev *dev, int bars)
*/
int pci_enable_device(struct pci_dev *dev)
{
- return pci_enable_device_bars(dev, (1 << PCI_NUM_RESOURCES) - 1);
+ return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
}
/*
@@ -823,7 +877,8 @@ int pcim_enable_device(struct pci_dev *pdev)
dr = get_pci_dr(pdev);
if (unlikely(!dr))
return -ENOMEM;
- WARN_ON(!!dr->enabled);
+ if (dr->enabled)
+ return 0;
rc = pci_enable_device(pdev);
if (!rc) {
@@ -884,6 +939,9 @@ pci_disable_device(struct pci_dev *dev)
if (atomic_sub_return(1, &dev->enable_cnt) != 0)
return;
+ /* Wait for all transactions are finished before disabling the device */
+ pcie_wait_pending_transaction(dev);
+
pci_read_config_word(dev, PCI_COMMAND, &pci_command);
if (pci_command & PCI_COMMAND_MASTER) {
pci_command &= ~PCI_COMMAND_MASTER;
@@ -1618,9 +1676,9 @@ early_param("pci", pci_setup);
device_initcall(pci_init);
-EXPORT_SYMBOL_GPL(pci_restore_bars);
EXPORT_SYMBOL(pci_reenable_device);
-EXPORT_SYMBOL(pci_enable_device_bars);
+EXPORT_SYMBOL(pci_enable_device_io);
+EXPORT_SYMBOL(pci_enable_device_mem);
EXPORT_SYMBOL(pci_enable_device);
EXPORT_SYMBOL(pcim_enable_device);
EXPORT_SYMBOL(pcim_pin_device);
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index fc87e14b50d..eabeb1f2ec9 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -6,8 +6,10 @@ extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev);
/* Firmware callbacks */
-extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev, pm_message_t state);
-extern int (*platform_pci_set_power_state)(struct pci_dev *dev, pci_power_t state);
+extern pci_power_t (*platform_pci_choose_state)(struct pci_dev *dev,
+ pm_message_t state);
+extern int (*platform_pci_set_power_state)(struct pci_dev *dev,
+ pci_power_t state);
extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
extern int pci_user_read_config_word(struct pci_dev *dev, int where, u16 *val);
@@ -45,12 +47,6 @@ static inline void pci_no_msi(void) { }
static inline void pci_msi_init_pci_dev(struct pci_dev *dev) { }
#endif
-#if defined(CONFIG_PCI_MSI) && defined(CONFIG_PM)
-void pci_restore_msi_state(struct pci_dev *dev);
-#else
-static inline void pci_restore_msi_state(struct pci_dev *dev) {}
-#endif
-
#ifdef CONFIG_PCIEAER
void pci_no_aer(void);
#else
@@ -68,14 +64,14 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
}
extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[];
-extern struct class_device_attribute class_device_attr_cpuaffinity;
+extern struct device_attribute dev_attr_cpuaffinity;
/**
* pci_match_one_device - Tell if a PCI device structure has a matching
* PCI device id structure
* @id: single PCI device id structure to match
* @dev: the PCI device structure to match against
- *
+ *
* Returns the matching pci_device_id structure or %NULL if there is no match.
*/
static inline const struct pci_device_id *
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 287a9311716..60104cf9879 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -26,3 +26,23 @@ config HOTPLUG_PCI_PCIE
When in doubt, say N.
source "drivers/pci/pcie/aer/Kconfig"
+
+#
+# PCI Express ASPM
+#
+config PCIEASPM
+ bool "PCI Express ASPM support(Experimental)"
+ depends on PCI && EXPERIMENTAL
+ default y
+ help
+ This enables PCI Express ASPM (Active State Power Management) and
+ Clock Power Management. ASPM supports state L0/L0s/L1.
+
+ When in doubt, say N.
+config PCIEASPM_DEBUG
+ bool "Debug PCI Express ASPM"
+ depends on PCIEASPM
+ default n
+ help
+ This enables PCI Express ASPM debug support. It will add per-device
+ interface to control ASPM.
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index e00fb99acf4..11f6bb1eae2 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -2,6 +2,9 @@
# Makefile for PCI-Express PORT Driver
#
+# Build PCI Express ASPM if needed
+obj-$(CONFIG_PCIEASPM) += aspm.o
+
pcieportdrv-y := portdrv_core.o portdrv_pci.o portdrv_bus.o
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
index 1a1eb45a779..8c199ae84f6 100644
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ b/drivers/pci/pcie/aer/aerdrv_acpi.c
@@ -31,26 +31,16 @@ int aer_osc_setup(struct pcie_device *pciedev)
{
acpi_status status = AE_NOT_FOUND;
struct pci_dev *pdev = pciedev->port;
- acpi_handle handle = DEVICE_ACPI_HANDLE(&pdev->dev);
- struct pci_bus *parent;
+ acpi_handle handle = 0;
- while (!handle) {
- if (!pdev || !pdev->bus->parent)
- break;
- parent = pdev->bus->parent;
- if (!parent->self)
- /* Parent must be a host bridge */
- handle = acpi_get_pci_rootbridge_handle(
- pci_domain_nr(parent),
- parent->number);
- else
- handle = DEVICE_ACPI_HANDLE(
- &(parent->self->dev));
- pdev = parent->self;
- }
+ /* Find root host bridge */
+ while (pdev->bus && pdev->bus->self)
+ pdev = pdev->bus->self;
+ handle = acpi_get_pci_rootbridge_handle(
+ pci_domain_nr(pdev->bus), pdev->bus->number);
if (handle) {
- pci_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
+ pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT);
status = pci_osc_control_set(handle,
OSC_PCI_EXPRESS_AER_CONTROL |
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 92a8469b21b..3c0d8d138f5 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -168,11 +168,11 @@ static int find_device_iter(struct device *device, void *data)
/**
* find_source_device - search through device hierarchy for source device
- * @p_dev: pointer to Root Port pci_dev data structure
+ * @parent: pointer to Root Port pci_dev data structure
* @id: device ID of agent who sends an error message to this Root Port
*
* Invoked when error is detected at the Root Port.
- **/
+ */
static struct device* find_source_device(struct pci_dev *parent, u16 id)
{
struct pci_dev *dev = parent;
@@ -286,14 +286,15 @@ static void report_resume(struct pci_dev *dev, void *data)
/**
* broadcast_error_message - handle message broadcast to downstream drivers
- * @device: pointer to from where in a hierarchy message is broadcasted down
- * @api: callback to be broadcasted
+ * @dev: pointer to from where in a hierarchy message is broadcasted down
* @state: error state
+ * @error_mesg: message to print
+ * @cb: callback to be broadcasted
*
* Invoked during error recovery process. Once being invoked, the content
* of error severity will be broadcasted to all downstream drivers in a
* hierarchy in question.
- **/
+ */
static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
enum pci_channel_state state,
char *error_mesg,
@@ -428,7 +429,7 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,
* Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
* error detected message to all downstream drivers within a hierarchy in
* question and return the returned code.
- **/
+ */
static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
struct pci_dev *dev,
int severity)
@@ -488,7 +489,7 @@ static pci_ers_result_t do_recovery(struct pcie_device *aerdev,
* @info: comprehensive error information
*
* Invoked when an error being detected by Root Port.
- **/
+ */
static void handle_error_source(struct pcie_device * aerdev,
struct pci_dev *dev,
struct aer_err_info info)
@@ -521,7 +522,7 @@ static void handle_error_source(struct pcie_device * aerdev,
* @rpc: pointer to a Root Port data structure
*
* Invoked when PCIE bus loads AER service driver.
- **/
+ */
void aer_enable_rootport(struct aer_rpc *rpc)
{
struct pci_dev *pdev = rpc->rpd->port;
@@ -569,7 +570,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
* @rpc: pointer to a Root Port data structure
*
* Invoked when PCIE bus unloads AER service driver.
- **/
+ */
static void disable_root_aer(struct aer_rpc *rpc)
{
struct pci_dev *pdev = rpc->rpd->port;
@@ -590,7 +591,7 @@ static void disable_root_aer(struct aer_rpc *rpc)
* @rpc: pointer to the root port which holds an error
*
* Invoked by DPC handler to consume an error.
- **/
+ */
static struct aer_err_source* get_e_source(struct aer_rpc *rpc)
{
struct aer_err_source *e_source;
@@ -655,7 +656,7 @@ static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
* aer_isr_one_error - consume an error detected by root port
* @p_device: pointer to error root port service device
* @e_src: pointer to an error source
- **/
+ */
static void aer_isr_one_error(struct pcie_device *p_device,
struct aer_err_source *e_src)
{
@@ -706,7 +707,7 @@ static void aer_isr_one_error(struct pcie_device *p_device,
* @work: definition of this work item
*
* Invoked, as DPC, when root port records new detected error
- **/
+ */
void aer_isr(struct work_struct *work)
{
struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
@@ -729,7 +730,7 @@ void aer_isr(struct work_struct *work)
* @rpc: pointer to a root port device being deleted
*
* Invoked when AER service unloaded on a specific Root Port
- **/
+ */
void aer_delete_rootport(struct aer_rpc *rpc)
{
/* Disable root port AER itself */
@@ -743,7 +744,7 @@ void aer_delete_rootport(struct aer_rpc *rpc)
* @dev: pointer to AER pcie device
*
* Invoked when AER service driver is loaded.
- **/
+ */
int aer_init(struct pcie_device *dev)
{
if (aer_osc_setup(dev) && !forceload)
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
new file mode 100644
index 00000000000..1a5adeb10c9
--- /dev/null
+++ b/drivers/pci/pcie/aspm.c
@@ -0,0 +1,802 @@
+/*
+ * File: drivers/pci/pcie/aspm.c
+ * Enabling PCIE link L0s/L1 state and Clock Power Management
+ *
+ * Copyright (C) 2007 Intel
+ * Copyright (C) Zhang Yanmin (yanmin.zhang@intel.com)
+ * Copyright (C) Shaohua Li (shaohua.li@intel.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/aspm.h>
+#include <acpi/acpi_bus.h>
+#include <linux/pci-acpi.h>
+#include "../pci.h"
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "pcie_aspm."
+
+struct endpoint_state {
+ unsigned int l0s_acceptable_latency;
+ unsigned int l1_acceptable_latency;
+};
+
+struct pcie_link_state {
+ struct list_head sibiling;
+ struct pci_dev *pdev;
+
+ /* ASPM state */
+ unsigned int support_state;
+ unsigned int enabled_state;
+ unsigned int bios_aspm_state;
+ /* upstream component */
+ unsigned int l0s_upper_latency;
+ unsigned int l1_upper_latency;
+ /* downstream component */
+ unsigned int l0s_down_latency;
+ unsigned int l1_down_latency;
+ /* Clock PM state*/
+ unsigned int clk_pm_capable;
+ unsigned int clk_pm_enabled;
+ unsigned int bios_clk_state;
+
+ /*
+ * A pcie downstream port only has one slot under it, so at most there
+ * are 8 functions
+ */
+ struct endpoint_state endpoints[8];
+};
+
+static int aspm_disabled;
+static DEFINE_MUTEX(aspm_lock);
+static LIST_HEAD(link_list);
+
+#define POLICY_DEFAULT 0 /* BIOS default setting */
+#define POLICY_PERFORMANCE 1 /* high performance */
+#define POLICY_POWERSAVE 2 /* high power saving */
+static int aspm_policy;
+static const char *policy_str[] = {
+ [POLICY_DEFAULT] = "default",
+ [POLICY_PERFORMANCE] = "performance",
+ [POLICY_POWERSAVE] = "powersave"
+};
+
+static int policy_to_aspm_state(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ switch (aspm_policy) {
+ case POLICY_PERFORMANCE:
+ /* Disable ASPM and Clock PM */
+ return 0;
+ case POLICY_POWERSAVE:
+ /* Enable ASPM L0s/L1 */
+ return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+ case POLICY_DEFAULT:
+ return link_state->bios_aspm_state;
+ }
+ return 0;
+}
+
+static int policy_to_clkpm_state(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ switch (aspm_policy) {
+ case POLICY_PERFORMANCE:
+ /* Disable ASPM and Clock PM */
+ return 0;
+ case POLICY_POWERSAVE:
+ /* Disable Clock PM */
+ return 1;
+ case POLICY_DEFAULT:
+ return link_state->bios_clk_state;
+ }
+ return 0;
+}
+
+static void pcie_set_clock_pm(struct pci_dev *pdev, int enable)
+{
+ struct pci_dev *child_dev;
+ int pos;
+ u16 reg16;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+ if (enable)
+ reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN;
+ else
+ reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ pci_write_config_word(child_dev, pos + PCI_EXP_LNKCTL, reg16);
+ }
+ link_state->clk_pm_enabled = !!enable;
+}
+
+static void pcie_check_clock_pm(struct pci_dev *pdev)
+{
+ int pos;
+ u32 reg32;
+ u16 reg16;
+ int capable = 1, enabled = 1;
+ struct pci_dev *child_dev;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ /* All functions should have the same cap and state, take the worst */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ if (!pos)
+ return;
+ pci_read_config_dword(child_dev, pos + PCI_EXP_LNKCAP, &reg32);
+ if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) {
+ capable = 0;
+ enabled = 0;
+ break;
+ }
+ pci_read_config_word(child_dev, pos + PCI_EXP_LNKCTL, &reg16);
+ if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN))
+ enabled = 0;
+ }
+ link_state->clk_pm_capable = capable;
+ link_state->clk_pm_enabled = enabled;
+ link_state->bios_clk_state = enabled;
+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+}
+
+/*
+ * pcie_aspm_configure_common_clock: check if the 2 ends of a link
+ * could use common clock. If they are, configure them to use the
+ * common clock. That will reduce the ASPM state exit latency.
+ */
+static void pcie_aspm_configure_common_clock(struct pci_dev *pdev)
+{
+ int pos, child_pos;
+ u16 reg16 = 0;
+ struct pci_dev *child_dev;
+ int same_clock = 1;
+
+ /*
+ * all functions of a slot should have the same Slot Clock
+ * Configuration, so just check one function
+ * */
+ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+ bus_list);
+ BUG_ON(!child_dev->is_pcie);
+
+ /* Check downstream component if bit Slot Clock Configuration is 1 */
+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKSTA, &reg16);
+ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+ same_clock = 0;
+
+ /* Check upstream component if bit Slot Clock Configuration is 1 */
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+ if (!(reg16 & PCI_EXP_LNKSTA_SLC))
+ same_clock = 0;
+
+ /* Configure downstream component, all functions */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ pci_read_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+ &reg16);
+ if (same_clock)
+ reg16 |= PCI_EXP_LNKCTL_CCC;
+ else
+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
+ pci_write_config_word(child_dev, child_pos + PCI_EXP_LNKCTL,
+ reg16);
+ }
+
+ /* Configure upstream component */
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ if (same_clock)
+ reg16 |= PCI_EXP_LNKCTL_CCC;
+ else
+ reg16 &= ~PCI_EXP_LNKCTL_CCC;
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+ /* retrain link */
+ reg16 |= PCI_EXP_LNKCTL_RL;
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+
+ /* Wait for link training end */
+ while (1) {
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKSTA, &reg16);
+ if (!(reg16 & PCI_EXP_LNKSTA_LT))
+ break;
+ cpu_relax();
+ }
+}
+
+/*
+ * calc_L0S_latency: Convert L0s latency encoding to ns
+ */
+static unsigned int calc_L0S_latency(unsigned int latency_encoding, int ac)
+{
+ unsigned int ns = 64;
+
+ if (latency_encoding == 0x7) {
+ if (ac)
+ ns = -1U;
+ else
+ ns = 5*1000; /* > 4us */
+ } else
+ ns *= (1 << latency_encoding);
+ return ns;
+}
+
+/*
+ * calc_L1_latency: Convert L1 latency encoding to ns
+ */
+static unsigned int calc_L1_latency(unsigned int latency_encoding, int ac)
+{
+ unsigned int ns = 1000;
+
+ if (latency_encoding == 0x7) {
+ if (ac)
+ ns = -1U;
+ else
+ ns = 65*1000; /* > 64us */
+ } else
+ ns *= (1 << latency_encoding);
+ return ns;
+}
+
+static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
+ unsigned int *l0s, unsigned int *l1, unsigned int *enabled)
+{
+ int pos;
+ u16 reg16;
+ u32 reg32;
+ unsigned int latency;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
+ *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
+ if (*state != PCIE_LINK_STATE_L0S &&
+ *state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S))
+ * state = 0;
+ if (*state == 0)
+ return;
+
+ latency = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
+ *l0s = calc_L0S_latency(latency, 0);
+ if (*state & PCIE_LINK_STATE_L1) {
+ latency = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15;
+ *l1 = calc_L1_latency(latency, 0);
+ }
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
+}
+
+static void pcie_aspm_cap_init(struct pci_dev *pdev)
+{
+ struct pci_dev *child_dev;
+ u32 state, tmp;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ /* upstream component states */
+ pcie_aspm_get_cap_device(pdev, &link_state->support_state,
+ &link_state->l0s_upper_latency,
+ &link_state->l1_upper_latency,
+ &link_state->enabled_state);
+ /* downstream component states, all functions have the same setting */
+ child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev,
+ bus_list);
+ pcie_aspm_get_cap_device(child_dev, &state,
+ &link_state->l0s_down_latency,
+ &link_state->l1_down_latency,
+ &tmp);
+ link_state->support_state &= state;
+ if (!link_state->support_state)
+ return;
+ link_state->enabled_state &= link_state->support_state;
+ link_state->bios_aspm_state = link_state->enabled_state;
+
+ /* ENDPOINT states*/
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ int pos;
+ u32 reg32;
+ unsigned int latency;
+ struct endpoint_state *ep_state =
+ &link_state->endpoints[PCI_FUNC(child_dev->devfn)];
+
+ if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END)
+ continue;
+
+ pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP);
+ pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, &reg32);
+ latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
+ latency = calc_L0S_latency(latency, 1);
+ ep_state->l0s_acceptable_latency = latency;
+ if (link_state->support_state & PCIE_LINK_STATE_L1) {
+ latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9;
+ latency = calc_L1_latency(latency, 1);
+ ep_state->l1_acceptable_latency = latency;
+ }
+ }
+}
+
+static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
+ unsigned int state)
+{
+ struct pci_dev *parent_dev, *tmp_dev;
+ unsigned int latency, l1_latency = 0;
+ struct pcie_link_state *link_state;
+ struct endpoint_state *ep_state;
+
+ parent_dev = pdev->bus->self;
+ link_state = parent_dev->link_state;
+ state &= link_state->support_state;
+ if (state == 0)
+ return 0;
+ ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)];
+
+ /*
+ * Check latency for endpoint device.
+ * TBD: The latency from the endpoint to root complex vary per
+ * switch's upstream link state above the device. Here we just do a
+ * simple check which assumes all links above the device can be in L1
+ * state, that is we just consider the worst case. If switch's upstream
+ * link can't be put into L0S/L1, then our check is too strictly.
+ */
+ tmp_dev = pdev;
+ while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
+ parent_dev = tmp_dev->bus->self;
+ link_state = parent_dev->link_state;
+ if (state & PCIE_LINK_STATE_L0S) {
+ latency = max_t(unsigned int,
+ link_state->l0s_upper_latency,
+ link_state->l0s_down_latency);
+ if (latency > ep_state->l0s_acceptable_latency)
+ state &= ~PCIE_LINK_STATE_L0S;
+ }
+ if (state & PCIE_LINK_STATE_L1) {
+ latency = max_t(unsigned int,
+ link_state->l1_upper_latency,
+ link_state->l1_down_latency);
+ if (latency + l1_latency >
+ ep_state->l1_acceptable_latency)
+ state &= ~PCIE_LINK_STATE_L1;
+ }
+ if (!parent_dev->bus->self) /* parent_dev is a root port */
+ break;
+ else {
+ /*
+ * parent_dev is the downstream port of a switch, make
+ * tmp_dev the upstream port of the switch
+ */
+ tmp_dev = parent_dev->bus->self;
+ /*
+ * every switch on the path to root complex need 1 more
+ * microsecond for L1. Spec doesn't mention L0S.
+ */
+ if (state & PCIE_LINK_STATE_L1)
+ l1_latency += 1000;
+ }
+ }
+ return state;
+}
+
+static unsigned int pcie_aspm_check_state(struct pci_dev *pdev,
+ unsigned int state)
+{
+ struct pci_dev *child_dev;
+
+ /* If no child, disable the link */
+ if (list_empty(&pdev->subordinate->devices))
+ return 0;
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+ /*
+ * If downstream component of a link is pci bridge, we
+ * disable ASPM for now for the link
+ * */
+ state = 0;
+ break;
+ }
+ if ((child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT &&
+ child_dev->pcie_type != PCI_EXP_TYPE_LEG_END))
+ continue;
+ /* Device not in D0 doesn't need check latency */
+ if (child_dev->current_state == PCI_D1 ||
+ child_dev->current_state == PCI_D2 ||
+ child_dev->current_state == PCI_D3hot ||
+ child_dev->current_state == PCI_D3cold)
+ continue;
+ state = __pcie_aspm_check_state_one(child_dev, state);
+ }
+ return state;
+}
+
+static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state)
+{
+ u16 reg16;
+ int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+
+ pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
+ reg16 &= ~0x3;
+ reg16 |= state;
+ pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
+}
+
+static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state)
+{
+ struct pci_dev *child_dev;
+ int valid = 1;
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ /*
+ * if the downstream component has pci bridge function, don't do ASPM
+ * now
+ */
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) {
+ if (child_dev->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) {
+ valid = 0;
+ break;
+ }
+ }
+ if (!valid)
+ return;
+
+ /*
+ * spec 2.0 suggests all functions should be configured the same
+ * setting for ASPM. Enabling ASPM L1 should be done in upstream
+ * component first and then downstream, and vice versa for disabling
+ * ASPM L1. Spec doesn't mention L0S.
+ */
+ if (state & PCIE_LINK_STATE_L1)
+ __pcie_aspm_config_one_dev(pdev, state);
+
+ list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list)
+ __pcie_aspm_config_one_dev(child_dev, state);
+
+ if (!(state & PCIE_LINK_STATE_L1))
+ __pcie_aspm_config_one_dev(pdev, state);
+
+ link_state->enabled_state = state;
+}
+
+static void __pcie_aspm_configure_link_state(struct pci_dev *pdev,
+ unsigned int state)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (link_state->support_state == 0)
+ return;
+ state &= PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1;
+
+ /* state 0 means disabling aspm */
+ state = pcie_aspm_check_state(pdev, state);
+ if (link_state->enabled_state == state)
+ return;
+ __pcie_aspm_config_link(pdev, state);
+}
+
+/*
+ * pcie_aspm_configure_link_state: enable/disable PCI express link state
+ * @pdev: the root port or switch downstream port
+ */
+static void pcie_aspm_configure_link_state(struct pci_dev *pdev,
+ unsigned int state)
+{
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ __pcie_aspm_configure_link_state(pdev, state);
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+}
+
+static void free_link_state(struct pci_dev *pdev)
+{
+ kfree(pdev->link_state);
+ pdev->link_state = NULL;
+}
+
+/*
+ * pcie_aspm_init_link_state: Initiate PCI express link state.
+ * It is called after the pcie and its children devices are scaned.
+ * @pdev: the root port or switch downstream port
+ */
+void pcie_aspm_init_link_state(struct pci_dev *pdev)
+{
+ unsigned int state;
+ struct pcie_link_state *link_state;
+ int error = 0;
+
+ if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+ return;
+ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ down_read(&pci_bus_sem);
+ if (list_empty(&pdev->subordinate->devices))
+ goto out;
+
+ mutex_lock(&aspm_lock);
+
+ link_state = kzalloc(sizeof(*link_state), GFP_KERNEL);
+ if (!link_state)
+ goto unlock_out;
+ pdev->link_state = link_state;
+
+ pcie_aspm_configure_common_clock(pdev);
+
+ pcie_aspm_cap_init(pdev);
+
+ /* config link state to avoid BIOS error */
+ state = pcie_aspm_check_state(pdev, policy_to_aspm_state(pdev));
+ __pcie_aspm_config_link(pdev, state);
+
+ pcie_check_clock_pm(pdev);
+
+ link_state->pdev = pdev;
+ list_add(&link_state->sibiling, &link_list);
+
+unlock_out:
+ if (error)
+ free_link_state(pdev);
+ mutex_unlock(&aspm_lock);
+out:
+ up_read(&pci_bus_sem);
+}
+
+/* @pdev: the endpoint device */
+void pcie_aspm_exit_link_state(struct pci_dev *pdev)
+{
+ struct pci_dev *parent = pdev->bus->self;
+ struct pcie_link_state *link_state = parent->link_state;
+
+ if (aspm_disabled || !pdev->is_pcie || !parent || !link_state)
+ return;
+ if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+
+ /*
+ * All PCIe functions are in one slot, remove one function will remove
+ * the the whole slot, so just wait
+ */
+ if (!list_empty(&parent->subordinate->devices))
+ goto out;
+
+ /* All functions are removed, so just disable ASPM for the link */
+ __pcie_aspm_config_one_dev(parent, 0);
+ list_del(&link_state->sibiling);
+ /* Clock PM is for endpoint device */
+
+ free_link_state(parent);
+out:
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+}
+
+/* @pdev: the root port or switch downstream port */
+void pcie_aspm_pm_state_change(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (aspm_disabled || !pdev->is_pcie || !pdev->link_state)
+ return;
+ if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
+ return;
+ /*
+ * devices changed PM state, we should recheck if latency meets all
+ * functions' requirement
+ */
+ pcie_aspm_configure_link_state(pdev, link_state->enabled_state);
+}
+
+/*
+ * pci_disable_link_state - disable pci device's link state, so the link will
+ * never enter specific states
+ */
+void pci_disable_link_state(struct pci_dev *pdev, int state)
+{
+ struct pci_dev *parent = pdev->bus->self;
+ struct pcie_link_state *link_state;
+
+ if (aspm_disabled || !pdev->is_pcie)
+ return;
+ if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
+ pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
+ parent = pdev;
+ if (!parent)
+ return;
+
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ link_state = parent->link_state;
+ link_state->support_state &=
+ ~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1));
+ if (state & PCIE_LINK_STATE_CLKPM)
+ link_state->clk_pm_capable = 0;
+
+ __pcie_aspm_configure_link_state(parent, link_state->enabled_state);
+ if (!link_state->clk_pm_capable && link_state->clk_pm_enabled)
+ pcie_set_clock_pm(parent, 0);
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+}
+EXPORT_SYMBOL(pci_disable_link_state);
+
+static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
+{
+ int i;
+ struct pci_dev *pdev;
+ struct pcie_link_state *link_state;
+
+ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+ if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
+ break;
+ if (i >= ARRAY_SIZE(policy_str))
+ return -EINVAL;
+ if (i == aspm_policy)
+ return 0;
+
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ aspm_policy = i;
+ list_for_each_entry(link_state, &link_list, sibiling) {
+ pdev = link_state->pdev;
+ __pcie_aspm_configure_link_state(pdev,
+ policy_to_aspm_state(pdev));
+ if (link_state->clk_pm_capable &&
+ link_state->clk_pm_enabled != policy_to_clkpm_state(pdev))
+ pcie_set_clock_pm(pdev, policy_to_clkpm_state(pdev));
+
+ }
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+ return 0;
+}
+
+static int pcie_aspm_get_policy(char *buffer, struct kernel_param *kp)
+{
+ int i, cnt = 0;
+ for (i = 0; i < ARRAY_SIZE(policy_str); i++)
+ if (i == aspm_policy)
+ cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]);
+ else
+ cnt += sprintf(buffer + cnt, "%s ", policy_str[i]);
+ return cnt;
+}
+
+module_param_call(policy, pcie_aspm_set_policy, pcie_aspm_get_policy,
+ NULL, 0644);
+
+#ifdef CONFIG_PCIEASPM_DEBUG
+static ssize_t link_state_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ struct pcie_link_state *link_state = pci_device->link_state;
+
+ return sprintf(buf, "%d\n", link_state->enabled_state);
+}
+
+static ssize_t link_state_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ int state;
+
+ if (n < 1)
+ return -EINVAL;
+ state = buf[0]-'0';
+ if (state >= 0 && state <= 3) {
+ /* setup link aspm state */
+ pcie_aspm_configure_link_state(pci_device, state);
+ return n;
+ }
+
+ return -EINVAL;
+}
+
+static ssize_t clk_ctl_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ struct pcie_link_state *link_state = pci_device->link_state;
+
+ return sprintf(buf, "%d\n", link_state->clk_pm_enabled);
+}
+
+static ssize_t clk_ctl_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ struct pci_dev *pci_device = to_pci_dev(dev);
+ int state;
+
+ if (n < 1)
+ return -EINVAL;
+ state = buf[0]-'0';
+
+ down_read(&pci_bus_sem);
+ mutex_lock(&aspm_lock);
+ pcie_set_clock_pm(pci_device, !!state);
+ mutex_unlock(&aspm_lock);
+ up_read(&pci_bus_sem);
+
+ return n;
+}
+
+static DEVICE_ATTR(link_state, 0644, link_state_show, link_state_store);
+static DEVICE_ATTR(clk_ctl, 0644, clk_ctl_show, clk_ctl_store);
+
+static char power_group[] = "power";
+void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+ return;
+
+ if (link_state->support_state)
+ sysfs_add_file_to_group(&pdev->dev.kobj,
+ &dev_attr_link_state.attr, power_group);
+ if (link_state->clk_pm_capable)
+ sysfs_add_file_to_group(&pdev->dev.kobj,
+ &dev_attr_clk_ctl.attr, power_group);
+}
+
+void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
+{
+ struct pcie_link_state *link_state = pdev->link_state;
+
+ if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+ return;
+
+ if (link_state->support_state)
+ sysfs_remove_file_from_group(&pdev->dev.kobj,
+ &dev_attr_link_state.attr, power_group);
+ if (link_state->clk_pm_capable)
+ sysfs_remove_file_from_group(&pdev->dev.kobj,
+ &dev_attr_clk_ctl.attr, power_group);
+}
+#endif
+
+static int __init pcie_aspm_disable(char *str)
+{
+ aspm_disabled = 1;
+ return 1;
+}
+
+__setup("pcie_noaspm", pcie_aspm_disable);
+
+static int __init pcie_aspm_init(void)
+{
+ if (aspm_disabled)
+ return 0;
+ pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT|
+ OSC_CLOCK_PWR_CAPABILITY_SUPPORT);
+ return 0;
+}
+
+fs_initcall(pcie_aspm_init);
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index b20a9b81dae..23d9eb07329 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -192,9 +192,8 @@ static int get_port_device_capability(struct pci_dev *dev)
if (reg32 & SLOT_HP_CAPABLE_MASK)
services |= PCIE_PORT_SERVICE_HP;
}
- /* PME Capable */
- pos = pci_find_capability(dev, PCI_CAP_ID_PME);
- if (pos)
+ /* PME Capable - root port capability */
+ if (((reg16 >> 4) & PORT_TYPE_MASK) == PCIE_RC_PORT)
services |= PCIE_PORT_SERVICE_PME;
pos = PCI_CFG_SPACE_SIZE;
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index df383645e36..26057f98f72 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -217,7 +217,7 @@ 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_t status = PCI_ERS_RESULT_NONE;
int retval;
/* If fatal, restore cfg space for possible link reset at upstream */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 463a5a9d583..8b505bd925a 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -9,6 +9,7 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/cpumask.h>
+#include <linux/aspm.h>
#include "pci.h"
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
@@ -53,7 +54,7 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_io->read = pci_read_legacy_io;
b->legacy_io->write = pci_write_legacy_io;
- class_device_create_bin_file(&b->class_dev, b->legacy_io);
+ device_create_bin_file(&b->dev, b->legacy_io);
/* Allocated above after the legacy_io struct */
b->legacy_mem = b->legacy_io + 1;
@@ -61,15 +62,15 @@ static void pci_create_legacy_files(struct pci_bus *b)
b->legacy_mem->size = 1024*1024;
b->legacy_mem->attr.mode = S_IRUSR | S_IWUSR;
b->legacy_mem->mmap = pci_mmap_legacy_mem;
- class_device_create_bin_file(&b->class_dev, b->legacy_mem);
+ device_create_bin_file(&b->dev, b->legacy_mem);
}
}
void pci_remove_legacy_files(struct pci_bus *b)
{
if (b->legacy_io) {
- class_device_remove_bin_file(&b->class_dev, b->legacy_io);
- class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+ device_remove_bin_file(&b->dev, b->legacy_io);
+ device_remove_bin_file(&b->dev, b->legacy_mem);
kfree(b->legacy_io); /* both are allocated here */
}
}
@@ -81,26 +82,27 @@ void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/*
* PCI Bus Class Devices
*/
-static ssize_t pci_bus_show_cpuaffinity(struct class_device *class_dev,
+static ssize_t pci_bus_show_cpuaffinity(struct device *dev,
+ struct device_attribute *attr,
char *buf)
{
int ret;
cpumask_t cpumask;
- cpumask = pcibus_to_cpumask(to_pci_bus(class_dev));
+ cpumask = pcibus_to_cpumask(to_pci_bus(dev));
ret = cpumask_scnprintf(buf, PAGE_SIZE, cpumask);
if (ret < PAGE_SIZE)
buf[ret++] = '\n';
return ret;
}
-CLASS_DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
+DEVICE_ATTR(cpuaffinity, S_IRUGO, pci_bus_show_cpuaffinity, NULL);
/*
* PCI Bus Class
*/
-static void release_pcibus_dev(struct class_device *class_dev)
+static void release_pcibus_dev(struct device *dev)
{
- struct pci_bus *pci_bus = to_pci_bus(class_dev);
+ struct pci_bus *pci_bus = to_pci_bus(dev);
if (pci_bus->bridge)
put_device(pci_bus->bridge);
@@ -109,7 +111,7 @@ static void release_pcibus_dev(struct class_device *class_dev)
static struct class pcibus_class = {
.name = "pci_bus",
- .release = &release_pcibus_dev,
+ .dev_release = &release_pcibus_dev,
};
static int __init pcibus_class_init(void)
@@ -276,7 +278,8 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
sz = pci_size(l, sz, (u32)PCI_ROM_ADDRESS_MASK);
if (sz) {
res->flags = (l & IORESOURCE_ROM_ENABLE) |
- IORESOURCE_MEM | IORESOURCE_READONLY;
+ IORESOURCE_MEM | IORESOURCE_PREFETCH |
+ IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
res->start = l & PCI_ROM_ADDRESS_MASK;
res->end = res->start + (unsigned long) sz;
}
@@ -391,7 +394,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
{
struct pci_bus *child;
int i;
- int retval;
/*
* Allocate a new bus, and inherit stuff from the parent..
@@ -407,15 +409,12 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
child->bus_flags = parent->bus_flags;
child->bridge = get_device(&bridge->dev);
- child->class_dev.class = &pcibus_class;
- sprintf(child->class_dev.class_id, "%04x:%02x", pci_domain_nr(child), busnr);
- retval = class_device_register(&child->class_dev);
- if (retval)
- goto error_register;
- retval = class_device_create_file(&child->class_dev,
- &class_device_attr_cpuaffinity);
- if (retval)
- goto error_file_create;
+ /* 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()
+ */
+ child->dev.class = &pcibus_class;
+ sprintf(child->dev.bus_id, "%04x:%02x", pci_domain_nr(child), busnr);
/*
* Set up the primary, secondary and subordinate
@@ -433,12 +432,6 @@ pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
bridge->subordinate = child;
return child;
-
-error_file_create:
- class_device_unregister(&child->class_dev);
-error_register:
- kfree(child);
- return NULL;
}
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
@@ -454,22 +447,6 @@ struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int
return child;
}
-static void pci_enable_crs(struct pci_dev *dev)
-{
- u16 cap, rpctl;
- int rpcap = pci_find_capability(dev, PCI_CAP_ID_EXP);
- if (!rpcap)
- return;
-
- pci_read_config_word(dev, rpcap + PCI_CAP_FLAGS, &cap);
- if (((cap & PCI_EXP_FLAGS_TYPE) >> 4) != PCI_EXP_TYPE_ROOT_PORT)
- return;
-
- pci_read_config_word(dev, rpcap + PCI_EXP_RTCTL, &rpctl);
- rpctl |= PCI_EXP_RTCTL_CRSSVE;
- pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
-}
-
static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
{
struct pci_bus *parent = child->parent;
@@ -486,8 +463,6 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
}
}
-unsigned int pci_scan_child_bus(struct pci_bus *bus);
-
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
@@ -516,8 +491,6 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
pci_write_config_word(dev, PCI_BRIDGE_CONTROL,
bctl & ~PCI_BRIDGE_CTL_MASTER_ABORT);
- pci_enable_crs(dev);
-
if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) {
unsigned int cmax, busnr;
/*
@@ -658,13 +631,13 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
(child->number > bus->subordinate) ||
(child->number < bus->number) ||
(child->subordinate < bus->number)) {
- pr_debug("PCI: Bus #%02x (-#%02x) is %s"
+ pr_debug("PCI: Bus #%02x (-#%02x) is %s "
"hidden behind%s bridge #%02x (-#%02x)\n",
child->number, child->subordinate,
(bus->number > child->subordinate &&
bus->subordinate < child->number) ?
- "wholly " : " partially",
- bus->self->transparent ? " transparent" : " ",
+ "wholly" : "partially",
+ bus->self->transparent ? " transparent" : "",
bus->number, bus->subordinate);
}
bus = bus->parent;
@@ -743,46 +716,22 @@ static int pci_setup_device(struct pci_dev * dev)
*/
if (class == PCI_CLASS_STORAGE_IDE) {
u8 progif;
- struct pci_bus_region region;
-
pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
if ((progif & 1) == 0) {
- struct resource resource = {
- .start = 0x1F0,
- .end = 0x1F7,
- .flags = LEGACY_IO_RESOURCE,
- };
-
- pcibios_resource_to_bus(dev, &region, &resource);
- dev->resource[0].start = region.start;
- dev->resource[0].end = region.end;
- dev->resource[0].flags = resource.flags;
- resource.start = 0x3F6;
- resource.end = 0x3F6;
- resource.flags = LEGACY_IO_RESOURCE;
- pcibios_resource_to_bus(dev, &region, &resource);
- dev->resource[1].start = region.start;
- dev->resource[1].end = region.end;
- dev->resource[1].flags = resource.flags;
+ dev->resource[0].start = 0x1F0;
+ dev->resource[0].end = 0x1F7;
+ dev->resource[0].flags = LEGACY_IO_RESOURCE;
+ dev->resource[1].start = 0x3F6;
+ dev->resource[1].end = 0x3F6;
+ dev->resource[1].flags = LEGACY_IO_RESOURCE;
}
if ((progif & 4) == 0) {
- struct resource resource = {
- .start = 0x170,
- .end = 0x177,
- .flags = LEGACY_IO_RESOURCE,
- };
-
- pcibios_resource_to_bus(dev, &region, &resource);
- dev->resource[2].start = region.start;
- dev->resource[2].end = region.end;
- dev->resource[2].flags = resource.flags;
- resource.start = 0x376;
- resource.end = 0x376;
- resource.flags = LEGACY_IO_RESOURCE;
- pcibios_resource_to_bus(dev, &region, &resource);
- dev->resource[3].start = region.start;
- dev->resource[3].end = region.end;
- dev->resource[3].flags = resource.flags;
+ dev->resource[2].start = 0x170;
+ dev->resource[2].end = 0x177;
+ dev->resource[2].flags = LEGACY_IO_RESOURCE;
+ dev->resource[3].start = 0x376;
+ dev->resource[3].end = 0x376;
+ dev->resource[3].flags = LEGACY_IO_RESOURCE;
}
}
break;
@@ -1012,6 +961,7 @@ struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn)
return dev;
}
+EXPORT_SYMBOL(pci_scan_single_device);
/**
* pci_scan_slot - scan a PCI slot on a bus for devices.
@@ -1052,6 +1002,10 @@ int pci_scan_slot(struct pci_bus *bus, int devfn)
break;
}
}
+
+ if (bus->self)
+ pcie_aspm_init_link_state(bus->self);
+
return nr;
}
@@ -1144,32 +1098,27 @@ struct pci_bus * pci_create_bus(struct device *parent,
goto dev_reg_err;
b->bridge = get_device(dev);
- b->class_dev.class = &pcibus_class;
- sprintf(b->class_dev.class_id, "%04x:%02x", pci_domain_nr(b), bus);
- error = class_device_register(&b->class_dev);
+ b->dev.class = &pcibus_class;
+ b->dev.parent = b->bridge;
+ sprintf(b->dev.bus_id, "%04x:%02x", pci_domain_nr(b), bus);
+ error = device_register(&b->dev);
if (error)
goto class_dev_reg_err;
- error = class_device_create_file(&b->class_dev, &class_device_attr_cpuaffinity);
+ error = device_create_file(&b->dev, &dev_attr_cpuaffinity);
if (error)
- goto class_dev_create_file_err;
+ goto dev_create_file_err;
/* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(b);
- error = sysfs_create_link(&b->class_dev.kobj, &b->bridge->kobj, "bridge");
- if (error)
- goto sys_create_link_err;
-
b->number = b->secondary = bus;
b->resource[0] = &ioport_resource;
b->resource[1] = &iomem_resource;
return b;
-sys_create_link_err:
- class_device_remove_file(&b->class_dev, &class_device_attr_cpuaffinity);
-class_dev_create_file_err:
- class_device_unregister(&b->class_dev);
+dev_create_file_err:
+ device_unregister(&b->dev);
class_dev_reg_err:
device_unregister(dev);
dev_reg_err:
@@ -1181,7 +1130,6 @@ err_out:
kfree(b);
return NULL;
}
-EXPORT_SYMBOL_GPL(pci_create_bus);
struct pci_bus *pci_scan_bus_parented(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
@@ -1200,7 +1148,6 @@ EXPORT_SYMBOL(pci_add_new_bus);
EXPORT_SYMBOL(pci_do_scan_bus);
EXPORT_SYMBOL(pci_scan_slot);
EXPORT_SYMBOL(pci_scan_bridge);
-EXPORT_SYMBOL(pci_scan_single_device);
EXPORT_SYMBOL_GPL(pci_scan_child_bus);
#endif
@@ -1251,16 +1198,19 @@ static void __init pci_sort_breadthfirst_klist(void)
struct klist_node *n;
struct device *dev;
struct pci_dev *pdev;
+ struct klist *device_klist;
+
+ device_klist = bus_get_device_klist(&pci_bus_type);
- spin_lock(&pci_bus_type.klist_devices.k_lock);
- list_for_each_safe(pos, tmp, &pci_bus_type.klist_devices.k_list) {
+ spin_lock(&device_klist->k_lock);
+ list_for_each_safe(pos, tmp, &device_klist->k_list) {
n = container_of(pos, struct klist_node, n_node);
dev = container_of(n, struct device, knode_bus);
pdev = to_pci_dev(dev);
pci_insertion_sort_klist(pdev, &sorted_devices);
}
- list_splice(&sorted_devices, &pci_bus_type.klist_devices.k_list);
- spin_unlock(&pci_bus_type.klist_devices.k_lock);
+ list_splice(&sorted_devices, &device_klist->k_list);
+ spin_unlock(&device_klist->k_lock);
}
static void __init pci_insertion_sort_devices(struct pci_dev *a, struct list_head *list)
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 716439e25dd..68aeeb7206d 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+#include <linux/smp_lock.h>
#include <linux/capability.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -202,15 +203,18 @@ struct pci_filp_private {
int write_combine;
};
-static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
- const struct proc_dir_entry *dp = PDE(inode);
+ const struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
struct pci_dev *dev = dp->data;
#ifdef HAVE_PCI_MMAP
struct pci_filp_private *fpriv = file->private_data;
#endif /* HAVE_PCI_MMAP */
int ret = 0;
+ lock_kernel();
+
switch (cmd) {
case PCIIOC_CONTROLLER:
ret = pci_domain_nr(dev->bus);
@@ -239,6 +243,7 @@ static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned i
break;
};
+ unlock_kernel();
return ret;
}
@@ -291,7 +296,7 @@ static const struct file_operations proc_bus_pci_operations = {
.llseek = proc_bus_pci_lseek,
.read = proc_bus_pci_read,
.write = proc_bus_pci_write,
- .ioctl = proc_bus_pci_ioctl,
+ .unlocked_ioctl = proc_bus_pci_ioctl,
#ifdef HAVE_PCI_MMAP
.open = proc_bus_pci_open,
.release = proc_bus_pci_release,
@@ -370,7 +375,7 @@ static int show_device(struct seq_file *m, void *v)
return 0;
}
-static struct seq_operations proc_bus_pci_devices_op = {
+static const struct seq_operations proc_bus_pci_devices_op = {
.start = pci_seq_start,
.next = pci_seq_next,
.stop = pci_seq_stop,
@@ -480,7 +485,3 @@ static int __init pci_proc_init(void)
__initcall(pci_proc_init);
-#ifdef CONFIG_HOTPLUG
-EXPORT_SYMBOL(pci_proc_detach_bus);
-#endif
-
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index d0bb5b9d212..0a953d43b9a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/acpi.h>
+#include <linux/kallsyms.h>
#include "pci.h"
/* The Mellanox Tavor device gives false positive parity errors
@@ -46,14 +47,14 @@ static void quirk_passive_release(struct pci_dev *dev)
while ((d = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
pci_read_config_byte(d, 0x82, &dlc);
if (!(dlc & 1<<1)) {
- printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", pci_name(d));
+ dev_err(&d->dev, "PIIX3: Enabling Passive Release\n");
dlc |= 1<<1;
pci_write_config_byte(d, 0x82, dlc);
}
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_passive_release);
/* The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
but VIA don't answer queries. If you happen to have good contacts at VIA
@@ -68,20 +69,20 @@ static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
{
if (!isa_dma_bridge_buggy) {
isa_dma_bridge_buggy=1;
- printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
+ dev_info(&dev->dev, "Activating ISA DMA hang workarounds\n");
}
}
/*
* Its not totally clear which chipsets are the problematic ones
* We know 82C586 and 82C596 variants are affected.
*/
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs);
int pci_pci_problems;
EXPORT_SYMBOL(pci_pci_problems);
@@ -92,12 +93,12 @@ EXPORT_SYMBOL(pci_pci_problems);
static void __devinit quirk_nopcipci(struct pci_dev *dev)
{
if ((pci_pci_problems & PCIPCI_FAIL)==0) {
- printk(KERN_INFO "Disabling direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Disabling direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_FAIL;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci);
static void __devinit quirk_nopciamd(struct pci_dev *dev)
{
@@ -105,11 +106,11 @@ static void __devinit quirk_nopciamd(struct pci_dev *dev)
pci_read_config_byte(dev, 0x08, &rev);
if (rev == 0x13) {
/* Erratum 24 */
- printk(KERN_INFO "Chipset erratum: Disabling direct PCI/AGP transfers.\n");
+ dev_info(&dev->dev, "Chipset erratum: Disabling direct PCI/AGP transfers\n");
pci_pci_problems |= PCIAGP_FAIL;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopciamd);
/*
* Triton requires workarounds to be used by the drivers
@@ -117,14 +118,14 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8151_0, quirk_nopci
static void __devinit quirk_triton(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_TRITON)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_TRITON;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437VX, quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439, quirk_triton);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quirk_triton);
/*
* VIA Apollo KT133 needs PCI latency patch
@@ -139,25 +140,22 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82439TX, quir
static void quirk_vialatency(struct pci_dev *dev)
{
struct pci_dev *p;
- u8 rev;
u8 busarb;
/* Ok we have a potential problem chipset here. Now see if we have
a buggy southbridge */
p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
if (p!=NULL) {
- pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
/* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
/* Check for buggy part revisions */
- if (rev < 0x40 || rev > 0x42)
+ if (p->revision < 0x40 || p->revision > 0x42)
goto exit;
} else {
p = pci_get_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
if (p==NULL) /* No problem parts */
goto exit;
- pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
/* Check for buggy part revisions */
- if (rev < 0x10 || rev > 0x12)
+ if (p->revision < 0x10 || p->revision > 0x12)
goto exit;
}
@@ -180,17 +178,17 @@ static void quirk_vialatency(struct pci_dev *dev)
busarb &= ~(1<<5);
busarb |= (1<<4);
pci_write_config_byte(dev, 0x76, busarb);
- printk(KERN_INFO "Applying VIA southbridge workaround.\n");
+ dev_info(&dev->dev, "Applying VIA southbridge workaround\n");
exit:
pci_dev_put(p);
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency);
/* Must restore this on a resume from RAM */
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency );
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency);
/*
* VIA Apollo VP3 needs ETBF on BT848/878
@@ -198,20 +196,20 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_viala
static void __devinit quirk_viaetbf(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_VIAETBF)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_VIAETBF;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf);
static void __devinit quirk_vsfx(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_VSFX)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_VSFX;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx);
/*
* Ali Magik requires workarounds to be used by the drivers
@@ -222,12 +220,12 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx
static void __init quirk_alimagik(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_ALIMAGIK)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_ALIMAGIK|PCIPCI_TRITON;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik);
/*
* Natoma has some interesting boundary conditions with Zoran stuff
@@ -236,16 +234,16 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimag
static void __devinit quirk_natoma(struct pci_dev *dev)
{
if ((pci_pci_problems&PCIPCI_NATOMA)==0) {
- printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ dev_info(&dev->dev, "Limiting direct PCI/PCI transfers\n");
pci_pci_problems |= PCIPCI_NATOMA;
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_0, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443LX_1, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_1, quirk_natoma);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma);
/*
* This chip can cause PCI parity errors if config register 0xA0 is read
@@ -255,7 +253,7 @@ static void __devinit quirk_citrine(struct pci_dev *dev)
{
dev->cfg_size = 0xA0;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, quirk_citrine);
/*
* S3 868 and 968 chips report region size equal to 32M, but they decode 64M.
@@ -270,8 +268,8 @@ static void __devinit quirk_s3_64M(struct pci_dev *dev)
r->end = 0x3ffffff;
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M);
static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
unsigned size, int nr, const char *name)
@@ -292,7 +290,7 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
pcibios_bus_to_resource(dev, res, &bus_region);
pci_claim_resource(dev, nr);
- printk("PCI quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
+ dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
}
}
@@ -302,12 +300,12 @@ static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region,
*/
static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev)
{
- printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n");
+ dev_info(&dev->dev, "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb\n");
/* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */
request_region(0x3b0, 0x0C, "RadeonIGP");
request_region(0x3d3, 0x01, "RadeonIGP");
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_exploding_mce );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100, quirk_ati_exploding_mce);
/*
* Let's make the southbridge information explicit instead
@@ -329,7 +327,7 @@ static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
pci_read_config_word(dev, 0xE2, &region);
quirk_io_region(dev, region, 32, PCI_BRIDGE_RESOURCES+1, "ali7101 SMB");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi);
static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
{
@@ -354,7 +352,7 @@ static void piix4_io_quirk(struct pci_dev *dev, const char *name, unsigned int p
* let's get enough confirmation reports first.
*/
base &= -size;
- printk("%s PIO at %04x-%04x\n", name, base, base + size - 1);
+ dev_info(&dev->dev, "%s PIO at %04x-%04x\n", name, base, base + size - 1);
}
static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int port, unsigned int enable)
@@ -379,7 +377,7 @@ static void piix4_mem_quirk(struct pci_dev *dev, const char *name, unsigned int
* reserve it, but let's get enough confirmation reports first.
*/
base &= -size;
- printk("%s MMIO at %04x-%04x\n", name, base, base + size - 1);
+ dev_info(&dev->dev, "%s MMIO at %04x-%04x\n", name, base, base + size - 1);
}
/*
@@ -418,8 +416,8 @@ static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
piix4_io_quirk(dev, "PIIX4 devres I", 0x78, 1 << 20);
piix4_io_quirk(dev, "PIIX4 devres J", 0x7c, 1 << 20);
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, quirk_piix4_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, quirk_piix4_acpi);
/*
* ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
@@ -436,16 +434,16 @@ static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
pci_read_config_dword(dev, 0x58, &region);
quirk_io_region(dev, region, 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 );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi );
+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);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, quirk_ich4_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, quirk_ich4_lpc_acpi);
static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
{
@@ -457,14 +455,20 @@ static void __devinit quirk_ich6_lpc_acpi(struct pci_dev *dev)
pci_read_config_dword(dev, 0x48, &region);
quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_0, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_2, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_3, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_2, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_4, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7, quirk_ich6_lpc_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_8, quirk_ich6_lpc_acpi);
/*
* VIA ACPI: One IO region pointed to by longword at
@@ -480,7 +484,7 @@ static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
quirk_io_region(dev, region, 256, PCI_BRIDGE_RESOURCES, "vt82c586 ACPI");
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi);
/*
* VIA VT82C686 ACPI: Three IO region pointed to by (long)words at
@@ -503,7 +507,7 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
smb &= PCI_BASE_ADDRESS_IO_MASK;
quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi);
/*
* VIA VT8235 ISA Bridge: Two IO regions pointed to by words at
@@ -545,14 +549,14 @@ static void quirk_via_ioapic(struct pci_dev *dev)
else
tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
- printk(KERN_INFO "PCI: %sbling Via external APIC routing\n",
+ dev_info(&dev->dev, "%sbling VIA external APIC routing\n",
tmp == 0 ? "Disa" : "Ena");
/* Offset 0x58: External APIC IRQ output control */
pci_write_config_byte (dev, 0x58, tmp);
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic);
/*
* VIA 8237: Some BIOSs don't set the 'Bypass APIC De-Assert Message' Bit.
@@ -567,7 +571,7 @@ static void quirk_via_vt8237_bypass_apic_deassert(struct pci_dev *dev)
pci_read_config_byte(dev, 0x5B, &misc_control2);
if (!(misc_control2 & BYPASS_APIC_DEASSERT)) {
- printk(KERN_INFO "PCI: Bypassing VIA 8237 APIC De-Assert Message\n");
+ dev_info(&dev->dev, "Bypassing VIA 8237 APIC De-Assert Message\n");
pci_write_config_byte(dev, 0x5B, misc_control2|BYPASS_APIC_DEASSERT);
}
}
@@ -586,18 +590,18 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, quirk_via_v
static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
{
if (dev->revision >= 0x02) {
- printk(KERN_WARNING "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
- printk(KERN_WARNING " : booting with the \"noapic\" option.\n");
+ dev_warn(&dev->dev, "I/O APIC: AMD Erratum #22 may be present. In the event of instability try\n");
+ dev_warn(&dev->dev, " : booting with the \"noapic\" option\n");
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic);
static void __init quirk_ioapic_rmw(struct pci_dev *dev)
{
if (dev->devfn == 0 && dev->bus->number == 0)
sis_apic_bug = 1;
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI, PCI_ANY_ID, quirk_ioapic_rmw);
#define AMD8131_revA0 0x01
#define AMD8131_revB0 0x11
@@ -611,7 +615,7 @@ static void quirk_amd_8131_ioapic(struct pci_dev *dev)
return;
if (dev->revision == AMD8131_revA0 || dev->revision == AMD8131_revB0) {
- printk(KERN_INFO "Fixing up AMD8131 IOAPIC mode\n");
+ dev_info(&dev->dev, "Fixing up AMD8131 IOAPIC mode\n");
pci_read_config_byte( dev, AMD8131_MISC, &tmp);
tmp &= ~(1 << AMD8131_NIOAMODE_BIT);
pci_write_config_byte( dev, AMD8131_MISC, tmp);
@@ -628,8 +632,8 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk
static void __init quirk_amd_8131_mmrbc(struct pci_dev *dev)
{
if (dev->subordinate && dev->revision <= 0x12) {
- printk(KERN_INFO "AMD8131 rev %x detected, disabling PCI-X "
- "MMRBC\n", dev->revision);
+ dev_info(&dev->dev, "AMD8131 rev %x detected; "
+ "disabling PCI-X MMRBC\n", dev->revision);
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MMRBC;
}
}
@@ -654,8 +658,8 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
if (irq && (irq != 2))
d->irq = irq;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi);
/*
@@ -736,8 +740,8 @@ static void quirk_via_vlink(struct pci_dev *dev)
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
if (new_irq != irq) {
- printk(KERN_INFO "PCI: VIA VLink IRQ fixup for %s, from %d to %d\n",
- pci_name(dev), irq, new_irq);
+ dev_info(&dev->dev, "VIA VLink IRQ fixup, from %d to %d\n",
+ irq, new_irq);
udelay(15); /* unknown if delay really needed */
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
}
@@ -755,7 +759,7 @@ static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
pci_write_config_byte(dev, 0xfc, 0);
pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id);
/*
* CardBus controllers have a legacy base address that enables them
@@ -785,15 +789,15 @@ static void quirk_amd_ordering(struct pci_dev *dev)
pci_read_config_dword(dev, 0x4C, &pcic);
if ((pcic&6)!=6) {
pcic |= 6;
- printk(KERN_WARNING "BIOS failed to enable PCI standards compliance, fixing this error.\n");
+ dev_warn(&dev->dev, "BIOS failed to enable PCI standards compliance; fixing this error\n");
pci_write_config_dword(dev, 0x4C, pcic);
pci_read_config_dword(dev, 0x84, &pcic);
pcic |= (1<<23); /* Required in this mode */
pci_write_config_dword(dev, 0x84, pcic);
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering);
/*
* DreamWorks provided workaround for Dunord I-3000 problem
@@ -808,7 +812,7 @@ static void __devinit quirk_dunord ( struct pci_dev * dev )
r->start = 0;
r->end = 0xffffff;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DUNORD, PCI_DEVICE_ID_DUNORD_I3000, quirk_dunord);
/*
* i82380FB mobile docking controller: its PCI-to-PCI bridge
@@ -820,8 +824,8 @@ static void __devinit quirk_transparent_bridge(struct pci_dev *dev)
{
dev->transparent = 1;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82380FB, quirk_transparent_bridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge);
/*
* Common misconfiguration of the MediaGX/Geode PCI master that will
@@ -835,12 +839,12 @@ static void quirk_mediagx_master(struct pci_dev *dev)
pci_read_config_byte(dev, 0x41, &reg);
if (reg & 2) {
reg &= ~2;
- printk(KERN_INFO "PCI: Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
+ dev_info(&dev->dev, "Fixup for MediaGX/Geode Slave Disconnect Boundary (0x41=0x%02x)\n", reg);
pci_write_config_byte(dev, 0x41, reg);
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master);
/*
* Ensure C0 rev restreaming is off. This is normally done by
@@ -857,11 +861,11 @@ static void quirk_disable_pxb(struct pci_dev *pdev)
if (config & (1<<6)) {
config &= ~(1<<6);
pci_write_config_word(pdev, 0x40, config);
- printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n");
+ dev_info(&pdev->dev, "C0 revision 450NX. Disabling PCI restreaming\n");
}
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb);
static void __devinit quirk_sb600_sata(struct pci_dev *pdev)
@@ -896,7 +900,7 @@ static void __devinit quirk_svwks_csb5ide(struct pci_dev *pdev)
/* PCI layer will sort out resources */
}
}
-DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide );
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide);
/*
* Intel 82801CAM ICH3-M datasheet says IDE modes must be the same
@@ -908,7 +912,7 @@ static void __init quirk_ide_samemode(struct pci_dev *pdev)
pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
if (((prog & 1) && !(prog & 4)) || ((prog & 4) && !(prog & 1))) {
- printk(KERN_INFO "PCI: IDE mode mismatch; forcing legacy mode\n");
+ dev_info(&pdev->dev, "IDE mode mismatch; forcing legacy mode\n");
prog &= ~5;
pdev->class &= ~5;
pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
@@ -923,7 +927,7 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge);
/*
@@ -1016,6 +1020,11 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
case 0x12bd: /* HP D530 */
asus_hides_smbus = 1;
}
+ else if (dev->device == PCI_DEVICE_ID_INTEL_82875_HB)
+ switch (dev->subsystem_device) {
+ case 0x12bf: /* HP xw4100 */
+ asus_hides_smbus = 1;
+ }
else if (dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
switch (dev->subsystem_device) {
case 0x099c: /* HP Compaq nx6110 */
@@ -1043,17 +1052,18 @@ static void __init asus_hides_smbus_hostbridge(struct pci_dev *dev)
}
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82850_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_7205_0, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7501_MCH, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855PM_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82855GM_HB, asus_hides_smbus_hostbridge);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82915GM_HB, asus_hides_smbus_hostbridge);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, asus_hides_smbus_hostbridge);
static void asus_hides_smbus_lpc(struct pci_dev *dev)
{
@@ -1067,25 +1077,25 @@ static void asus_hides_smbus_lpc(struct pci_dev *dev)
pci_write_config_word(dev, 0xF2, val & (~0x8));
pci_read_config_word(dev, 0xF2, &val);
if (val & 0x8)
- printk(KERN_INFO "PCI: i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
+ dev_info(&dev->dev, "i801 SMBus device continues to play 'hide and seek'! 0x%x\n", val);
else
- printk(KERN_INFO "PCI: Enabled i801 SMBus device\n");
+ dev_info(&dev->dev, "Enabled i801 SMBus device\n");
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12, asus_hides_smbus_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, asus_hides_smbus_lpc);
static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
{
@@ -1100,10 +1110,10 @@ static void asus_hides_smbus_lpc_ich6(struct pci_dev *dev)
val=readl(base + 0x3418); /* read the Function Disable register, dword mode only */
writel(val & 0xFFFFFFF7, base + 0x3418); /* enable the SMBus device */
iounmap(base);
- printk(KERN_INFO "PCI: Enabled ICH6/i801 SMBus device\n");
+ dev_info(&dev->dev, "Enabled ICH6/i801 SMBus device\n");
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6 );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, asus_hides_smbus_lpc_ich6);
/*
* SiS 96x south bridge: BIOS typically hides SMBus device...
@@ -1113,18 +1123,18 @@ static void quirk_sis_96x_smbus(struct pci_dev *dev)
u8 val = 0;
pci_read_config_byte(dev, 0x77, &val);
if (val & 0x10) {
- printk(KERN_INFO "Enabling SiS 96x SMBus.\n");
+ dev_info(&dev->dev, "Enabling SiS 96x SMBus\n");
pci_write_config_byte(dev, 0x77, val & ~0x10);
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_961, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_962, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_963, quirk_sis_96x_smbus);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC, quirk_sis_96x_smbus);
/*
* ... This is further complicated by the fact that some SiS96x south
@@ -1157,8 +1167,8 @@ static void quirk_sis_503(struct pci_dev *dev)
dev->device = devid;
quirk_sis_96x_smbus(dev);
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503 );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, quirk_sis_503);
/*
@@ -1185,13 +1195,13 @@ static void asus_hides_ac97_lpc(struct pci_dev *dev)
pci_write_config_byte(dev, 0x50, val & (~0xc0));
pci_read_config_byte(dev, 0x50, &val);
if (val & 0xc0)
- printk(KERN_INFO "PCI: onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
+ dev_info(&dev->dev, "Onboard AC97/MC97 devices continue to play 'hide and seek'! 0x%x\n", val);
else
- printk(KERN_INFO "PCI: enabled onboard AC97/MC97 devices\n");
+ dev_info(&dev->dev, "Enabled onboard AC97/MC97 devices\n");
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, asus_hides_ac97_lpc);
#if defined(CONFIG_ATA) || defined(CONFIG_ATA_MODULE)
@@ -1286,7 +1296,7 @@ static void __init quirk_alder_ioapic(struct pci_dev *pdev)
}
}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic );
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_alder_ioapic);
#endif
int pcie_mch_quirk;
@@ -1296,9 +1306,9 @@ static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
{
pcie_mch_quirk = 1;
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch );
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch );
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch);
/*
@@ -1308,11 +1318,8 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quir
static void __devinit quirk_pcie_pxh(struct pci_dev *dev)
{
pci_msi_off(dev);
-
dev->no_msi = 1;
-
- printk(KERN_WARNING "PCI: PXH quirk detected, "
- "disabling MSI for SHPC device\n");
+ dev_warn(&dev->dev, "PXH quirk detected; SHPC device MSI disabled\n");
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_0, quirk_pcie_pxh);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PXHD_1, quirk_pcie_pxh);
@@ -1393,7 +1400,7 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
case PCI_DEVICE_ID_NETMOS_9855:
if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_SERIAL &&
num_parallel) {
- printk(KERN_INFO "PCI: Netmos %04x (%u parallel, "
+ dev_info(&dev->dev, "Netmos %04x (%u parallel, "
"%u serial); changing class SERIAL to OTHER "
"(use parport_serial)\n",
dev->device, num_parallel, num_serial);
@@ -1406,9 +1413,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
{
- u16 command;
+ u16 command, pmcsr;
u8 __iomem *csr;
u8 cmd_hi;
+ int pm;
switch (dev->device) {
/* PCI IDs taken from drivers/net/e100.c */
@@ -1442,18 +1450,28 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev)
if (!(command & PCI_COMMAND_MEMORY) || !pci_resource_start(dev, 0))
return;
+ /*
+ * Check that the device is in the D0 power state. If it's not,
+ * there is no point to look any further.
+ */
+ pm = pci_find_capability(dev, PCI_CAP_ID_PM);
+ if (pm) {
+ pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
+ if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0)
+ return;
+ }
+
/* Convert from PCI bus to resource space. */
csr = ioremap(pci_resource_start(dev, 0), 8);
if (!csr) {
- printk(KERN_WARNING "PCI: Can't map %s e100 registers\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "Can't map e100 registers\n");
return;
}
cmd_hi = readb(csr + 3);
if (cmd_hi == 0) {
- printk(KERN_WARNING "PCI: Firmware left %s e100 interrupts "
- "enabled, disabling\n", pci_name(dev));
+ dev_warn(&dev->dev, "Firmware left e100 interrupts enabled; "
+ "disabling\n");
writeb(1, csr + 3);
}
@@ -1468,7 +1486,7 @@ static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
*/
if (dev->class == PCI_CLASS_NOT_DEFINED) {
- printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n");
+ dev_info(&dev->dev, "NCR 53c810 rev 1 detected; setting PCI class\n");
dev->class = PCI_CLASS_STORAGE_SCSI;
}
}
@@ -1479,7 +1497,11 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f
while (f < end) {
if ((f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
- pr_debug("PCI: Calling quirk %p for %s\n", f->hook, pci_name(dev));
+#ifdef DEBUG
+ dev_dbg(&dev->dev, "calling quirk 0x%p", f->hook);
+ print_fn_descriptor_symbol(": %s()\n",
+ (unsigned long) f->hook);
+#endif
f->hook(dev);
}
f++;
@@ -1547,7 +1569,7 @@ static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
pci_read_config_word(dev, 0x40, &en1k);
if (en1k & 0x200) {
- printk(KERN_INFO "PCI: Enable I/O Space to 1 KB Granularity\n");
+ dev_info(&dev->dev, "Enable I/O Space to 1KB granularity\n");
pci_read_config_byte(dev, PCI_IO_BASE, &io_base_lo);
pci_read_config_byte(dev, PCI_IO_LIMIT, &io_limit_lo);
@@ -1579,7 +1601,7 @@ static void __devinit quirk_p64h2_1k_io_fix_iobl(struct pci_dev *dev)
iobl_adr_1k = iobl_adr | (res->start >> 8) | (res->end & 0xfc00);
if (iobl_adr != iobl_adr_1k) {
- printk(KERN_INFO "PCI: Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1 KB Granularity\n",
+ dev_info(&dev->dev, "Fixing P64H2 IOBL_ADR from 0x%x to 0x%x for 1KB granularity\n",
iobl_adr,iobl_adr_1k);
pci_write_config_word(dev, PCI_IO_BASE, iobl_adr_1k);
}
@@ -1597,9 +1619,8 @@ static void quirk_nvidia_ck804_pcie_aer_ext_cap(struct pci_dev *dev)
if (pci_read_config_byte(dev, 0xf41, &b) == 0) {
if (!(b & 0x20)) {
pci_write_config_byte(dev, 0xf41, b | 0x20);
- printk(KERN_INFO
- "PCI: Linking AER extended capability on %s\n",
- pci_name(dev));
+ dev_info(&dev->dev,
+ "Linking AER extended capability\n");
}
}
}
@@ -1608,6 +1629,34 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_pcie_aer_ext_cap);
+static void __devinit quirk_via_cx700_pci_parking_caching(struct pci_dev *dev)
+{
+ /*
+ * Disable PCI Bus Parking and PCI Master read caching on CX700
+ * which causes unspecified timing errors with a VT6212L on the PCI
+ * bus leading to USB2.0 packet loss. The defaults are that these
+ * features are turned off but some BIOSes turn them on.
+ */
+
+ uint8_t b;
+ if (pci_read_config_byte(dev, 0x76, &b) == 0) {
+ if (b & 0x40) {
+ /* Turn off PCI Bus Parking */
+ pci_write_config_byte(dev, 0x76, b ^ 0x40);
+
+ /* Turn off PCI Master read caching */
+ pci_write_config_byte(dev, 0x72, 0x0);
+ pci_write_config_byte(dev, 0x75, 0x1);
+ pci_write_config_byte(dev, 0x77, 0x0);
+
+ printk(KERN_INFO
+ "PCI: VIA CX700 PCI parking/caching fixup on %s\n",
+ pci_name(dev));
+ }
+ }
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_VIA, 0x324e, quirk_via_cx700_pci_parking_caching);
+
#ifdef CONFIG_PCI_MSI
/* Some chipsets do not support MSI. We cannot easily rely on setting
* PCI_BUS_FLAGS_NO_MSI in its bus flags because there are actually
@@ -1618,24 +1667,19 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
static void __init quirk_disable_all_msi(struct pci_dev *dev)
{
pci_no_msi();
- printk(KERN_WARNING "PCI: MSI quirk detected. MSI deactivated.\n");
+ dev_warn(&dev->dev, "MSI quirk detected; MSI disabled\n");
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT1000_PCIX, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS400_200, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RD580, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RX790, quirk_disable_all_msi);
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS690, quirk_disable_all_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
/* Disable MSI on chipsets that are known to not support it */
static void __devinit quirk_disable_msi(struct pci_dev *dev)
{
if (dev->subordinate) {
- printk(KERN_WARNING "PCI: MSI quirk detected. "
- "PCI_BUS_FLAGS_NO_MSI set for %s subordinate bus.\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "MSI quirk detected; "
+ "subordinate MSI disabled\n");
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
}
}
@@ -1654,9 +1698,9 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS,
&flags) == 0)
{
- printk(KERN_INFO "PCI: Found %s HT MSI Mapping on %s\n",
+ dev_info(&dev->dev, "Found %s HT MSI Mapping\n",
flags & HT_MSI_FLAGS_ENABLE ?
- "enabled" : "disabled", pci_name(dev));
+ "enabled" : "disabled");
return (flags & HT_MSI_FLAGS_ENABLE) != 0;
}
@@ -1670,15 +1714,41 @@ static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
static void __devinit quirk_msi_ht_cap(struct pci_dev *dev)
{
if (dev->subordinate && !msi_ht_cap_enabled(dev)) {
- printk(KERN_WARNING "PCI: MSI quirk detected. "
- "MSI disabled on chipset %s.\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "MSI quirk detected; "
+ "subordinate MSI disabled\n");
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE,
quirk_msi_ht_cap);
+
+/*
+ * Force enable MSI mapping capability on HT bridges
+ */
+static void __devinit quirk_msi_ht_cap_enable(struct pci_dev *dev)
+{
+ int pos, ttl = 48;
+
+ pos = pci_find_ht_capability(dev, HT_CAPTYPE_MSI_MAPPING);
+ while (pos && ttl--) {
+ u8 flags;
+
+ if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags) == 0) {
+ printk(KERN_INFO "PCI: Enabling HT MSI Mapping on %s\n",
+ pci_name(dev));
+
+ pci_write_config_byte(dev, pos + HT_MSI_FLAGS,
+ flags | HT_MSI_FLAGS_ENABLE);
+ }
+ pos = pci_find_next_ht_capability(dev, pos,
+ HT_CAPTYPE_MSI_MAPPING);
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
+ PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB,
+ quirk_msi_ht_cap_enable);
+
/* The nVidia CK804 chipset may have 2 HT MSI mappings.
* MSI are supported if the MSI capability set in any of these mappings.
*/
@@ -1696,13 +1766,71 @@ static void __devinit quirk_nvidia_ck804_msi_ht_cap(struct pci_dev *dev)
if (!pdev)
return;
if (!msi_ht_cap_enabled(dev) && !msi_ht_cap_enabled(pdev)) {
- printk(KERN_WARNING "PCI: MSI quirk detected. "
- "MSI disabled on chipset %s.\n",
- pci_name(dev));
+ dev_warn(&dev->dev, "MSI quirk detected; "
+ "subordinate MSI disabled\n");
dev->subordinate->bus_flags |= PCI_BUS_FLAGS_NO_MSI;
}
pci_dev_put(pdev);
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_CK804_PCIE,
quirk_nvidia_ck804_msi_ht_cap);
+
+static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev)
+{
+ dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+}
+static void __devinit quirk_msi_intx_disable_ati_bug(struct pci_dev *dev)
+{
+ struct pci_dev *p;
+
+ /* SB700 MSI issue will be fixed at HW level from revision A21,
+ * we need check PCI REVISION ID of SMBus controller to get SB700
+ * revision.
+ */
+ p = pci_get_device(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+ NULL);
+ if (!p)
+ return;
+
+ if ((p->revision < 0x3B) && (p->revision >= 0x30))
+ dev->dev_flags |= PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG;
+ pci_dev_put(p);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5780,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5780S,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5714,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5714S,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5715,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
+ PCI_DEVICE_ID_TIGON3_5715S,
+ quirk_msi_intx_disable_bug);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4390,
+ quirk_msi_intx_disable_ati_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4391,
+ quirk_msi_intx_disable_ati_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4392,
+ quirk_msi_intx_disable_ati_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4393,
+ quirk_msi_intx_disable_ati_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4394,
+ quirk_msi_intx_disable_ati_bug);
+
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4373,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4374,
+ quirk_msi_intx_disable_bug);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x4375,
+ quirk_msi_intx_disable_bug);
+
#endif /* CONFIG_PCI_MSI */
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 430281b2e92..ec4a82ba29a 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -1,5 +1,6 @@
#include <linux/pci.h>
#include <linux/module.h>
+#include <linux/aspm.h>
#include "pci.h"
static void pci_free_resources(struct pci_dev *dev)
@@ -30,6 +31,9 @@ static void pci_stop_dev(struct pci_dev *dev)
dev->global_list.next = dev->global_list.prev = NULL;
up_write(&pci_bus_sem);
}
+
+ if (dev->bus->self)
+ pcie_aspm_exit_link_state(dev);
}
static void pci_destroy_dev(struct pci_dev *dev)
@@ -74,10 +78,8 @@ void pci_remove_bus(struct pci_bus *pci_bus)
list_del(&pci_bus->node);
up_write(&pci_bus_sem);
pci_remove_legacy_files(pci_bus);
- class_device_remove_file(&pci_bus->class_dev,
- &class_device_attr_cpuaffinity);
- sysfs_remove_link(&pci_bus->class_dev.kobj, "bridge");
- class_device_unregister(&pci_bus->class_dev);
+ device_remove_file(&pci_bus->dev, &dev_attr_cpuaffinity);
+ device_unregister(&pci_bus->dev);
}
EXPORT_SYMBOL(pci_remove_bus);
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index dbbcc04abd1..a98b2470b9e 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -162,6 +162,7 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
return rom;
}
+#if 0
/**
* pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
* @pdev: pointer to pci device struct
@@ -196,6 +197,7 @@ void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
return (void __iomem *)(unsigned long)res->start;
}
+#endif /* 0 */
/**
* pci_unmap_rom - unmap the ROM from kernel space
@@ -218,6 +220,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
pci_disable_rom(pdev);
}
+#if 0
/**
* pci_remove_rom - disable the ROM and remove its sysfs attribute
* @pdev: pointer to pci device struct
@@ -236,6 +239,7 @@ void pci_remove_rom(struct pci_dev *pdev)
IORESOURCE_ROM_COPY)))
pci_disable_rom(pdev);
}
+#endif /* 0 */
/**
* pci_cleanup_rom - internal routine for freeing the ROM copy created
@@ -256,6 +260,4 @@ void pci_cleanup_rom(struct pci_dev *pdev)
}
EXPORT_SYMBOL(pci_map_rom);
-EXPORT_SYMBOL(pci_map_rom_copy);
EXPORT_SYMBOL(pci_unmap_rom);
-EXPORT_SYMBOL(pci_remove_rom);
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index b001b5922e3..8541034021f 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -113,6 +113,8 @@ pci_find_next_bus(const struct pci_bus *from)
return b;
}
+#ifdef CONFIG_PCI_LEGACY
+
/**
* pci_find_slot - locate PCI device from a given PCI slot
* @bus: number of PCI bus on which desired PCI device resides
@@ -137,6 +139,8 @@ pci_find_slot(unsigned int bus, unsigned int devfn)
return NULL;
}
+#endif /* CONFIG_PCI_LEGACY */
+
/**
* pci_get_slot - locate PCI device for a given PCI slot
* @bus: PCI bus on which desired PCI device resides
@@ -200,6 +204,7 @@ struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
return NULL;
}
+#ifdef CONFIG_PCI_LEGACY
/**
* pci_find_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
* @vendor: PCI vendor id to match, or %PCI_ANY_ID to match all vendor ids
@@ -278,6 +283,7 @@ pci_find_device(unsigned int vendor, unsigned int device, const struct pci_dev *
{
return pci_find_subsys(vendor, device, PCI_ANY_ID, PCI_ANY_ID, from);
}
+#endif /* CONFIG_PCI_LEGACY */
/**
* pci_get_subsys - begin or continue searching for a PCI device by vendor/subvendor/device/subdevice id
@@ -468,8 +474,11 @@ int pci_dev_present(const struct pci_device_id *ids)
EXPORT_SYMBOL(pci_dev_present);
EXPORT_SYMBOL(pci_find_present);
+#ifdef CONFIG_PCI_LEGACY
EXPORT_SYMBOL(pci_find_device);
EXPORT_SYMBOL(pci_find_slot);
+#endif /* CONFIG_PCI_LEGACY */
+
/* For boot time work */
EXPORT_SYMBOL(pci_find_bus);
EXPORT_SYMBOL(pci_find_next_bus);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 401e03c920b..8a7232feb55 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -89,8 +89,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
* The IO resource is allocated a range twice as large as it
* would normally need. This allows us to set both IO regs.
*/
- printk(" IO window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
@@ -99,8 +100,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
if (bus->resource[1]->flags & IORESOURCE_IO) {
- printk(" IO window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " IO window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
@@ -109,8 +111,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_MEM) {
- printk(" PREFETCH window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " PREFETCH window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
@@ -119,8 +122,9 @@ void pci_setup_cardbus(struct pci_bus *bus)
pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
if (bus->resource[3]->flags & IORESOURCE_MEM) {
- printk(" MEM window: %08lx-%08lx\n",
- region.start, region.end);
+ printk(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
@@ -145,7 +149,7 @@ pci_setup_bridge(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
struct pci_bus_region region;
- u32 l, io_upper16;
+ u32 l, bu, lu, io_upper16;
DBG(KERN_INFO "PCI: Bridge: %s\n", pci_name(bridge));
@@ -159,7 +163,8 @@ pci_setup_bridge(struct pci_bus *bus)
/* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
DBG(KERN_INFO " IO window: %04lx-%04lx\n",
- region.start, region.end);
+ (unsigned long)region.start,
+ (unsigned long)region.end);
}
else {
/* Clear upper 16 bits of I/O base/limit. */
@@ -180,8 +185,9 @@ pci_setup_bridge(struct pci_bus *bus)
if (bus->resource[1]->flags & IORESOURCE_MEM) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- DBG(KERN_INFO " MEM window: %08lx-%08lx\n",
- region.start, region.end);
+ DBG(KERN_INFO " MEM window: 0x%08lx-0x%08lx\n",
+ (unsigned long)region.start,
+ (unsigned long)region.end);
}
else {
l = 0x0000fff0;
@@ -195,12 +201,18 @@ pci_setup_bridge(struct pci_bus *bus)
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */
+ bu = lu = 0;
pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- DBG(KERN_INFO " PREFETCH window: %08lx-%08lx\n",
- region.start, region.end);
+#ifdef CONFIG_RESOURCES_64BIT
+ bu = region.start >> 32;
+ lu = region.end >> 32;
+#endif
+ DBG(KERN_INFO " PREFETCH window: 0x%016llx-0x%016llx\n",
+ (unsigned long long)region.start,
+ (unsigned long long)region.end);
}
else {
l = 0x0000fff0;
@@ -208,8 +220,9 @@ pci_setup_bridge(struct pci_bus *bus)
}
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
- /* Clear out the upper 32 bits of PREF base. */
- pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
+ /* Set the upper 32 bits of PREF base & limit. */
+ pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, bu);
+ pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, lu);
pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
}
@@ -323,8 +336,8 @@ static void pbus_size_io(struct pci_bus *bus)
static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long type)
{
struct pci_dev *dev;
- unsigned long min_align, align, size;
- unsigned long aligns[12]; /* Alignments from 1Mb to 2Gb */
+ resource_size_t min_align, align, size;
+ resource_size_t aligns[12]; /* Alignments from 1Mb to 2Gb */
int order, max_order;
struct resource *b_res = find_free_bus_resource(bus, type);
@@ -340,7 +353,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *r = &dev->resource[i];
- unsigned long r_size;
+ resource_size_t r_size;
if (r->parent || (r->flags & mask) != type)
continue;
@@ -350,10 +363,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
order = __ffs(align) - 20;
if (order > 11) {
printk(KERN_WARNING "PCI: region %s/%d "
- "too large: %llx-%llx\n",
+ "too large: 0x%016llx-0x%016llx\n",
pci_name(dev), i,
- (unsigned long long)r->start,
- (unsigned long long)r->end);
+ (unsigned long long)r->start,
+ (unsigned long long)r->end);
r->flags = 0;
continue;
}
@@ -372,8 +385,11 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
align = 0;
min_align = 0;
for (order = 0; order <= max_order; order++) {
- unsigned long align1 = 1UL << (order + 20);
-
+#ifdef CONFIG_RESOURCES_64BIT
+ resource_size_t align1 = 1ULL << (order + 20);
+#else
+ resource_size_t align1 = 1U << (order + 20);
+#endif
if (!align)
min_align = align1;
else if (ALIGN(align + min_align, min_align) < align1)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 6dfd86167e3..4be7ccf7e3a 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -51,10 +51,12 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
pcibios_resource_to_bus(dev, &region, res);
- pr_debug(" got res [%llx:%llx] bus [%lx:%lx] flags %lx for "
+ pr_debug(" got res [%llx:%llx] bus [%llx:%llx] flags %lx for "
"BAR %d of %s\n", (unsigned long long)res->start,
(unsigned long long)res->end,
- region.start, region.end, res->flags, resno, pci_name(dev));
+ (unsigned long long)region.start,
+ (unsigned long long)region.end,
+ (unsigned long)res->flags, resno, pci_name(dev));
new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
if (res->flags & IORESOURCE_IO)
@@ -125,7 +127,6 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
return err;
}
-EXPORT_SYMBOL_GPL(pci_claim_resource);
int pci_assign_resource(struct pci_dev *dev, int resno)
{
diff --git a/drivers/pci/syscall.c b/drivers/pci/syscall.c
index 2ac050d7f8c..645d7a60e41 100644
--- a/drivers/pci/syscall.c
+++ b/drivers/pci/syscall.c
@@ -34,7 +34,6 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
if (!dev)
goto error;
- lock_kernel();
switch (len) {
case 1:
cfg_ret = pci_user_read_config_byte(dev, off, &byte);
@@ -47,10 +46,8 @@ sys_pciconfig_read(unsigned long bus, unsigned long dfn,
break;
default:
err = -EINVAL;
- unlock_kernel();
goto error;
};
- unlock_kernel();
err = -EIO;
if (cfg_ret != PCIBIOS_SUCCESSFUL)
@@ -107,7 +104,6 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
if (!dev)
return -ENODEV;
- lock_kernel();
switch(len) {
case 1:
err = get_user(byte, (u8 __user *)buf);
@@ -140,7 +136,6 @@ sys_pciconfig_write(unsigned long bus, unsigned long dfn,
err = -EINVAL;
break;
}
- unlock_kernel();
pci_dev_put(dev);
return err;
}