summaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-02-10 16:55:28 -0800
committerH. Peter Anvin <hpa@zytor.com>2010-02-10 16:55:28 -0800
commit84abd88a70090cf00f9e45c3a81680874f17626e (patch)
tree4f58b80057f6e1f5817af1dc33a5458b3dfc9a99 /drivers/pci/hotplug
parent13ca0fcaa33f6b1984c4111b6ec5df42689fea6f (diff)
parente28cab42f384745c8a947a9ccd51e4aae52f5d51 (diff)
Merge remote branch 'linus/master' into x86/bootmem
Diffstat (limited to 'drivers/pci/hotplug')
-rw-r--r--drivers/pci/hotplug/Makefile12
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c7
-rw-r--r--drivers/pci/hotplug/acpiphp.h6
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c266
-rw-r--r--drivers/pci/hotplug/acpiphp_ibm.c2
-rw-r--r--drivers/pci/hotplug/cpqphp.h1
-rw-r--r--drivers/pci/hotplug/ibmphp_hpc.c3
-rw-r--r--drivers/pci/hotplug/pci_hotplug_core.c22
-rw-r--r--drivers/pci/hotplug/pciehp.h1
-rw-r--r--drivers/pci/hotplug/pciehp_acpi.c3
-rw-r--r--drivers/pci/hotplug/pciehp_core.c119
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c57
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c155
-rw-r--r--drivers/pci/hotplug/pcihp_slot.c4
-rw-r--r--drivers/pci/hotplug/shpchp.h2
15 files changed, 156 insertions, 504 deletions
diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
index 3625b094bf7..6cd9f3c9887 100644
--- a/drivers/pci/hotplug/Makefile
+++ b/drivers/pci/hotplug/Makefile
@@ -6,18 +6,22 @@ obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o
obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o
-# pciehp should be linked before acpiphp in order to allow the native driver
-# to attempt to bind first. We can then fall back to generic support.
+# native drivers should be linked before acpiphp in order to allow the
+# native driver to attempt to bind first. We can then fall back to
+# generic support.
obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
-obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
-obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o
obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o
+obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
+
+# acpiphp_ibm extends acpiphp, so should be linked afterwards.
+
+obj-$(CONFIG_HOTPLUG_PCI_ACPI_IBM) += acpiphp_ibm.o
# Link this last so it doesn't claim devices that have a real hotplug driver
obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index a73028ec52e..3c76fc67cf0 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -362,6 +362,8 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
status = acpi_pci_osc_control_set(handle, flags);
if (ACPI_SUCCESS(status))
goto got_one;
+ if (status == AE_SUPPORT)
+ goto no_control;
kfree(string.pointer);
string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL };
}
@@ -394,10 +396,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *pdev, u32 flags)
if (ACPI_FAILURE(status))
break;
}
-
+no_control:
dbg("Cannot get control of hotplug hardware for pci %s\n",
pci_name(pdev));
-
kfree(string.pointer);
return -ENODEV;
got_one:
@@ -471,7 +472,7 @@ int acpi_pci_detect_ejectable(acpi_handle handle)
return found;
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
- check_hotplug, (void *)&found, NULL);
+ check_hotplug, NULL, (void *)&found, NULL);
return found;
}
EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable);
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h
index 7d938df7920..bab52047baa 100644
--- a/drivers/pci/hotplug/acpiphp.h
+++ b/drivers/pci/hotplug/acpiphp.h
@@ -146,12 +146,6 @@ struct acpiphp_attention_info
struct module *owner;
};
-struct acpiphp_ioapic {
- struct pci_dev *dev;
- u32 gsi_base;
- struct list_head list;
-};
-
/* PCI bus bridge HID */
#define ACPI_PCI_HOST_HID "PNP0A03"
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index 58d25a163a8..8e952fdab76 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -52,8 +52,6 @@
#include "acpiphp.h"
static LIST_HEAD(bridge_list);
-static LIST_HEAD(ioapic_list);
-static DEFINE_SPINLOCK(ioapic_list_lock);
#define MY_NAME "acpiphp_glue"
@@ -266,7 +264,7 @@ static int detect_ejectable_slots(acpi_handle handle)
int found = acpi_pci_detect_ejectable(handle);
if (!found) {
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- is_pci_dock_device, (void *)&found, NULL);
+ is_pci_dock_device, NULL, (void *)&found, NULL);
}
return found;
}
@@ -281,7 +279,7 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
/* register all slot objects under this bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,
- register_slot, bridge, NULL);
+ register_slot, NULL, bridge, NULL);
if (ACPI_FAILURE(status)) {
list_del(&bridge->list);
return;
@@ -311,17 +309,13 @@ static void init_bridge_misc(struct acpiphp_bridge *bridge)
/* find acpiphp_func from acpiphp_bridge */
static struct acpiphp_func *acpiphp_bridge_handle_to_function(acpi_handle handle)
{
- struct list_head *node, *l;
struct acpiphp_bridge *bridge;
struct acpiphp_slot *slot;
struct acpiphp_func *func;
- list_for_each(node, &bridge_list) {
- bridge = list_entry(node, struct acpiphp_bridge, list);
+ list_for_each_entry(bridge, &bridge_list, list) {
for (slot = bridge->slots; slot; slot = slot->next) {
- list_for_each(l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func,
- sibling);
+ list_for_each_entry(func, &slot->funcs, sibling) {
if (func->handle == handle)
return func;
}
@@ -447,7 +441,7 @@ find_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
/* search P2P bridges under this p2p bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- find_p2p_bridge, NULL, NULL);
+ find_p2p_bridge, NULL, NULL, NULL);
if (ACPI_FAILURE(status))
warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
@@ -485,7 +479,7 @@ static int add_bridge(acpi_handle handle)
/* search P2P bridges under this host bridge */
status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- find_p2p_bridge, NULL, NULL);
+ find_p2p_bridge, NULL, NULL, NULL);
if (ACPI_FAILURE(status))
warn("find_p2p_bridge failed (error code = 0x%x)\n", status);
@@ -495,21 +489,19 @@ static int add_bridge(acpi_handle handle)
static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)
{
- struct list_head *head;
- list_for_each(head, &bridge_list) {
- struct acpiphp_bridge *bridge = list_entry(head,
- struct acpiphp_bridge, list);
+ struct acpiphp_bridge *bridge;
+
+ list_for_each_entry(bridge, &bridge_list, list)
if (bridge->handle == handle)
return bridge;
- }
return NULL;
}
static void cleanup_bridge(struct acpiphp_bridge *bridge)
{
- struct list_head *list, *tmp;
- struct acpiphp_slot *slot;
+ struct acpiphp_slot *slot, *next;
+ struct acpiphp_func *func, *tmp;
acpi_status status;
acpi_handle handle = bridge->handle;
@@ -530,10 +522,8 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
slot = bridge->slots;
while (slot) {
- struct acpiphp_slot *next = slot->next;
- list_for_each_safe (list, tmp, &slot->funcs) {
- struct acpiphp_func *func;
- func = list_entry(list, struct acpiphp_func, sibling);
+ next = slot->next;
+ list_for_each_entry_safe(func, tmp, &slot->funcs, sibling) {
if (is_dock_device(func->handle)) {
unregister_hotplug_dock_device(func->handle);
unregister_dock_notifier(&func->nb);
@@ -545,7 +535,7 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge)
if (ACPI_FAILURE(status))
err("failed to remove notify handler\n");
}
- list_del(list);
+ list_del(&func->sibling);
kfree(func);
}
acpiphp_unregister_hotplug_slot(slot);
@@ -573,7 +563,7 @@ cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)
/* cleanup p2p bridges under this P2P bridge
in a depth-first manner */
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
- cleanup_p2p_bridge, NULL, NULL);
+ cleanup_p2p_bridge, NULL, NULL, NULL);
bridge = acpiphp_handle_to_bridge(handle);
if (bridge)
@@ -589,7 +579,7 @@ static void remove_bridge(acpi_handle handle)
/* cleanup p2p bridges under this host bridge
in a depth-first manner */
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
- (u32)1, cleanup_p2p_bridge, NULL, NULL);
+ (u32)1, cleanup_p2p_bridge, NULL, NULL, NULL);
/*
* On root bridges with hotplug slots directly underneath (ie,
@@ -606,204 +596,17 @@ static void remove_bridge(acpi_handle handle)
handle_hotplug_event_bridge);
}
-static struct pci_dev * get_apic_pci_info(acpi_handle handle)
-{
- struct pci_dev *dev;
-
- dev = acpi_get_pci_dev(handle);
- if (!dev)
- return NULL;
-
- if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&
- (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))
- {
- pci_dev_put(dev);
- return NULL;
- }
-
- return dev;
-}
-
-static int get_gsi_base(acpi_handle handle, u32 *gsi_base)
-{
- acpi_status status;
- int result = -1;
- unsigned long long gsb;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
- union acpi_object *obj;
- void *table;
-
- status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
- if (ACPI_SUCCESS(status)) {
- *gsi_base = (u32)gsb;
- return 0;
- }
-
- status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);
- if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)
- return -1;
-
- obj = buffer.pointer;
- if (obj->type != ACPI_TYPE_BUFFER)
- goto out;
-
- table = obj->buffer.pointer;
- switch (((struct acpi_subtable_header *)table)->type) {
- case ACPI_MADT_TYPE_IO_SAPIC:
- *gsi_base = ((struct acpi_madt_io_sapic *)table)->global_irq_base;
- result = 0;
- break;
- case ACPI_MADT_TYPE_IO_APIC:
- *gsi_base = ((struct acpi_madt_io_apic *)table)->global_irq_base;
- result = 0;
- break;
- default:
- break;
- }
- out:
- kfree(buffer.pointer);
- return result;
-}
-
-static acpi_status
-ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- acpi_status status;
- unsigned long long sta;
- acpi_handle tmp;
- struct pci_dev *pdev;
- u32 gsi_base;
- u64 phys_addr;
- struct acpiphp_ioapic *ioapic;
-
- /* Evaluate _STA if present */
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
- if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
- return AE_CTRL_DEPTH;
-
- /* Scan only PCI bus scope */
- status = acpi_get_handle(handle, "_HID", &tmp);
- if (ACPI_SUCCESS(status))
- return AE_CTRL_DEPTH;
-
- if (get_gsi_base(handle, &gsi_base))
- return AE_OK;
-
- ioapic = kmalloc(sizeof(*ioapic), GFP_KERNEL);
- if (!ioapic)
- return AE_NO_MEMORY;
-
- pdev = get_apic_pci_info(handle);
- if (!pdev)
- goto exit_kfree;
-
- if (pci_enable_device(pdev))
- goto exit_pci_dev_put;
-
- pci_set_master(pdev);
-
- if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)"))
- goto exit_pci_disable_device;
-
- phys_addr = pci_resource_start(pdev, 0);
- if (acpi_register_ioapic(handle, phys_addr, gsi_base))
- goto exit_pci_release_region;
-
- ioapic->gsi_base = gsi_base;
- ioapic->dev = pdev;
- spin_lock(&ioapic_list_lock);
- list_add_tail(&ioapic->list, &ioapic_list);
- spin_unlock(&ioapic_list_lock);
-
- return AE_OK;
-
- exit_pci_release_region:
- pci_release_region(pdev, 0);
- exit_pci_disable_device:
- pci_disable_device(pdev);
- exit_pci_dev_put:
- pci_dev_put(pdev);
- exit_kfree:
- kfree(ioapic);
-
- return AE_OK;
-}
-
-static acpi_status
-ioapic_remove(acpi_handle handle, u32 lvl, void *context, void **rv)
-{
- acpi_status status;
- unsigned long long sta;
- acpi_handle tmp;
- u32 gsi_base;
- struct acpiphp_ioapic *pos, *n, *ioapic = NULL;
-
- /* Evaluate _STA if present */
- status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
- if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)
- return AE_CTRL_DEPTH;
-
- /* Scan only PCI bus scope */
- status = acpi_get_handle(handle, "_HID", &tmp);
- if (ACPI_SUCCESS(status))
- return AE_CTRL_DEPTH;
-
- if (get_gsi_base(handle, &gsi_base))
- return AE_OK;
-
- acpi_unregister_ioapic(handle, gsi_base);
-
- spin_lock(&ioapic_list_lock);
- list_for_each_entry_safe(pos, n, &ioapic_list, list) {
- if (pos->gsi_base != gsi_base)
- continue;
- ioapic = pos;
- list_del(&ioapic->list);
- break;
- }
- spin_unlock(&ioapic_list_lock);
-
- if (!ioapic)
- return AE_OK;
-
- pci_release_region(ioapic->dev, 0);
- pci_disable_device(ioapic->dev);
- pci_dev_put(ioapic->dev);
- kfree(ioapic);
-
- return AE_OK;
-}
-
-static int acpiphp_configure_ioapics(acpi_handle handle)
-{
- ioapic_add(handle, 0, NULL, NULL);
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
- ACPI_UINT32_MAX, ioapic_add, NULL, NULL);
- return 0;
-}
-
-static int acpiphp_unconfigure_ioapics(acpi_handle handle)
-{
- ioapic_remove(handle, 0, NULL, NULL);
- acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
- ACPI_UINT32_MAX, ioapic_remove, NULL, NULL);
- return 0;
-}
-
static int power_on_slot(struct acpiphp_slot *slot)
{
acpi_status status;
struct acpiphp_func *func;
- struct list_head *l;
int retval = 0;
/* if already enabled, just skip */
if (slot->flags & SLOT_POWEREDON)
goto err_exit;
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
-
+ list_for_each_entry(func, &slot->funcs, sibling) {
if (func->flags & FUNC_HAS_PS0) {
dbg("%s: executing _PS0\n", __func__);
status = acpi_evaluate_object(func->handle, "_PS0", NULL, NULL);
@@ -829,7 +632,6 @@ static int power_off_slot(struct acpiphp_slot *slot)
{
acpi_status status;
struct acpiphp_func *func;
- struct list_head *l;
int retval = 0;
@@ -837,9 +639,7 @@ static int power_off_slot(struct acpiphp_slot *slot)
if ((slot->flags & SLOT_POWEREDON) == 0)
goto err_exit;
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
-
+ list_for_each_entry(func, &slot->funcs, sibling) {
if (func->flags & FUNC_HAS_PS3) {
status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);
if (ACPI_FAILURE(status)) {
@@ -966,7 +766,6 @@ static int __ref enable_device(struct acpiphp_slot *slot)
{
struct pci_dev *dev;
struct pci_bus *bus = slot->bridge->pci_bus;
- struct list_head *l;
struct acpiphp_func *func;
int retval = 0;
int num, max, pass;
@@ -1006,21 +805,16 @@ static int __ref enable_device(struct acpiphp_slot *slot)
}
}
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
+ list_for_each_entry(func, &slot->funcs, sibling)
acpiphp_bus_add(func);
- }
pci_bus_assign_resources(bus);
acpiphp_sanitize_bus(bus);
acpiphp_set_hpp_values(bus);
- list_for_each_entry(func, &slot->funcs, sibling)
- acpiphp_configure_ioapics(func->handle);
pci_enable_bridges(bus);
pci_bus_add_devices(bus);
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
+ list_for_each_entry(func, &slot->funcs, sibling) {
dev = pci_get_slot(bus, PCI_DEVFN(slot->device,
func->function));
if (!dev)
@@ -1091,7 +885,6 @@ static int disable_device(struct acpiphp_slot *slot)
}
list_for_each_entry(func, &slot->funcs, sibling) {
- acpiphp_unconfigure_ioapics(func->handle);
acpiphp_bus_trim(func->handle);
}
@@ -1119,12 +912,9 @@ static unsigned int get_slot_status(struct acpiphp_slot *slot)
acpi_status status;
unsigned long long sta = 0;
u32 dvid;
- struct list_head *l;
struct acpiphp_func *func;
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
-
+ list_for_each_entry(func, &slot->funcs, sibling) {
if (func->flags & FUNC_HAS_STA) {
status = acpi_evaluate_integer(func->handle, "_STA", NULL, &sta);
if (ACPI_SUCCESS(status) && sta)
@@ -1152,13 +942,10 @@ int acpiphp_eject_slot(struct acpiphp_slot *slot)
{
acpi_status status;
struct acpiphp_func *func;
- struct list_head *l;
struct acpi_object_list arg_list;
union acpi_object arg;
- list_for_each (l, &slot->funcs) {
- func = list_entry(l, struct acpiphp_func, sibling);
-
+ list_for_each_entry(func, &slot->funcs, sibling) {
/* We don't want to call _EJ0 on non-existing functions. */
if ((func->flags & FUNC_HAS_EJ0)) {
/* _EJ0 method take one argument */
@@ -1275,7 +1062,6 @@ static int acpiphp_configure_bridge (acpi_handle handle)
acpiphp_sanitize_bus(bus);
acpiphp_set_hpp_values(bus);
pci_enable_bridges(bus);
- acpiphp_configure_ioapics(handle);
return 0;
}
@@ -1367,7 +1153,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
bridge = acpiphp_handle_to_bridge(handle);
if (type == ACPI_NOTIFY_BUS_CHECK) {
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, ACPI_UINT32_MAX,
- count_sub_bridges, &num_sub_bridges, NULL);
+ count_sub_bridges, NULL, &num_sub_bridges, NULL);
}
if (!bridge && !num_sub_bridges) {
@@ -1388,7 +1174,7 @@ static void handle_hotplug_event_bridge(acpi_handle handle, u32 type, void *cont
}
if (num_sub_bridges)
acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,
- ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL);
+ ACPI_UINT32_MAX, check_sub_bridges, NULL, NULL, NULL);
break;
case ACPI_NOTIFY_DEVICE_CHECK:
@@ -1512,7 +1298,7 @@ int __init acpiphp_glue_init(void)
int num = 0;
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, find_root_bridges, &num, NULL);
+ ACPI_UINT32_MAX, find_root_bridges, NULL, &num, NULL);
if (num <= 0)
return -1;
@@ -1542,7 +1328,7 @@ int __init acpiphp_get_num_slots(void)
struct acpiphp_bridge *bridge;
int num_slots = 0;
- list_for_each_entry (bridge, &bridge_list, list) {
+ list_for_each_entry(bridge, &bridge_list, list) {
dbg("Bus %04x:%02x has %d slot%s\n",
pci_domain_nr(bridge->pci_bus),
bridge->pci_bus->number, bridge->nr_slots,
diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c
index e7be66dbac2..aa5df485f8c 100644
--- a/drivers/pci/hotplug/acpiphp_ibm.c
+++ b/drivers/pci/hotplug/acpiphp_ibm.c
@@ -434,7 +434,7 @@ static int __init ibm_acpiphp_init(void)
dbg("%s\n", __func__);
if (acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX, ibm_find_acpi_device,
+ ACPI_UINT32_MAX, ibm_find_acpi_device, NULL,
&ibm_acpi_handle, NULL) != FOUND_APCI) {
err("%s: acpi_walk_namespace failed\n", __func__);
retval = -ENODEV;
diff --git a/drivers/pci/hotplug/cpqphp.h b/drivers/pci/hotplug/cpqphp.h
index 53836001d51..9c6a9fd2681 100644
--- a/drivers/pci/hotplug/cpqphp.h
+++ b/drivers/pci/hotplug/cpqphp.h
@@ -32,6 +32,7 @@
#include <asm/io.h> /* for read? and write? functions */
#include <linux/delay.h> /* for delays */
#include <linux/mutex.h>
+#include <linux/sched.h> /* for signal_pending() */
#define MY_NAME "cpqphp"
diff --git a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c
index 83f337c891a..c7084f0eca5 100644
--- a/drivers/pci/hotplug/ibmphp_hpc.c
+++ b/drivers/pci/hotplug/ibmphp_hpc.c
@@ -890,7 +890,7 @@ static int poll_hpc(void *data)
msleep(POLL_INTERVAL_SEC * 1000);
if (kthread_should_stop())
- break;
+ goto out_sleep;
down (&semOperations);
@@ -904,6 +904,7 @@ static int poll_hpc(void *data)
/* give up the hardware semaphore */
up (&semOperations);
/* sleep for a short time just for good measure */
+out_sleep:
msleep(100);
}
up (&sem_exit);
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 0325d989bb4..38183a534b6 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -68,26 +68,26 @@ static DEFINE_MUTEX(pci_hp_mutex);
static char *pci_bus_speed_strings[] = {
"33 MHz PCI", /* 0x00 */
"66 MHz PCI", /* 0x01 */
- "66 MHz PCIX", /* 0x02 */
- "100 MHz PCIX", /* 0x03 */
- "133 MHz PCIX", /* 0x04 */
+ "66 MHz PCI-X", /* 0x02 */
+ "100 MHz PCI-X", /* 0x03 */
+ "133 MHz PCI-X", /* 0x04 */
NULL, /* 0x05 */
NULL, /* 0x06 */
NULL, /* 0x07 */
NULL, /* 0x08 */
- "66 MHz PCIX 266", /* 0x09 */
- "100 MHz PCIX 266", /* 0x0a */
- "133 MHz PCIX 266", /* 0x0b */
+ "66 MHz PCI-X 266", /* 0x09 */
+ "100 MHz PCI-X 266", /* 0x0a */
+ "133 MHz PCI-X 266", /* 0x0b */
NULL, /* 0x0c */
NULL, /* 0x0d */
NULL, /* 0x0e */
NULL, /* 0x0f */
NULL, /* 0x10 */
- "66 MHz PCIX 533", /* 0x11 */
- "100 MHz PCIX 533", /* 0x12 */
- "133 MHz PCIX 533", /* 0x13 */
- "2.5 GT/s PCI-E", /* 0x14 */
- "5.0 GT/s PCI-E", /* 0x15 */
+ "66 MHz PCI-X 533", /* 0x11 */
+ "100 MHz PCI-X 533", /* 0x12 */
+ "133 MHz PCI-X 533", /* 0x13 */
+ "2.5 GT/s PCIe", /* 0x14 */
+ "5.0 GT/s PCIe", /* 0x15 */
};
#ifdef CONFIG_HOTPLUG_PCI_CPCI
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 3070f77eb56..4ed76b47b6d 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -91,7 +91,6 @@ struct controller {
struct slot *slot;
wait_queue_head_t queue; /* sleep & wake process */
u32 slot_cap;
- u8 cap_base;
struct timer_list poll_timer;
unsigned int cmd_busy:1;
unsigned int no_cmd_complete:1;
diff --git a/drivers/pci/hotplug/pciehp_acpi.c b/drivers/pci/hotplug/pciehp_acpi.c
index 37c8d3d0323..b09b083011d 100644
--- a/drivers/pci/hotplug/pciehp_acpi.c
+++ b/drivers/pci/hotplug/pciehp_acpi.c
@@ -87,7 +87,8 @@ static int __init dummy_probe(struct pcie_device *dev)
/* Note: pciehp_detect_mode != PCIEHP_DETECT_ACPI here */
if (pciehp_get_hp_hw_control_from_firmware(pdev))
return -ENODEV;
- if (!(pos = pci_find_capability(pdev, PCI_CAP_ID_EXP)))
+ pos = pci_pcie_cap(pdev);
+ if (!pos)
return -ENODEV;
pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, &slot_cap);
slot = kzalloc(sizeof(*slot), GFP_KERNEL);
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index bc234719b1d..5674b2075bd 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -72,18 +72,6 @@ static int get_adapter_status (struct hotplug_slot *slot, u8 *value);
static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);
-static struct hotplug_slot_ops pciehp_hotplug_slot_ops = {
- .set_attention_status = set_attention_status,
- .enable_slot = enable_slot,
- .disable_slot = disable_slot,
- .get_power_status = get_power_status,
- .get_attention_status = get_attention_status,
- .get_latch_status = get_latch_status,
- .get_adapter_status = get_adapter_status,
- .get_max_bus_speed = get_max_bus_speed,
- .get_cur_bus_speed = get_cur_bus_speed,
-};
-
/**
* release_slot - free up the memory used by a slot
* @hotplug_slot: slot to free
@@ -95,6 +83,7 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, hotplug_slot_name(hotplug_slot));
+ kfree(hotplug_slot->ops);
kfree(hotplug_slot->info);
kfree(hotplug_slot);
}
@@ -104,6 +93,7 @@ static int init_slot(struct controller *ctrl)
struct slot *slot = ctrl->slot;
struct hotplug_slot *hotplug = NULL;
struct hotplug_slot_info *info = NULL;
+ struct hotplug_slot_ops *ops = NULL;
char name[SLOT_NAME_SIZE];
int retval = -ENOMEM;
@@ -115,11 +105,28 @@ static int init_slot(struct controller *ctrl)
if (!info)
goto out;
+ /* Setup hotplug slot ops */
+ ops = kzalloc(sizeof(*ops), GFP_KERNEL);
+ if (!ops)
+ goto out;
+ ops->enable_slot = enable_slot;
+ ops->disable_slot = disable_slot;
+ ops->get_power_status = get_power_status;
+ ops->get_adapter_status = get_adapter_status;
+ ops->get_max_bus_speed = get_max_bus_speed;
+ ops->get_cur_bus_speed = get_cur_bus_speed;
+ if (MRL_SENS(ctrl))
+ ops->get_latch_status = get_latch_status;
+ if (ATTN_LED(ctrl)) {
+ ops->get_attention_status = get_attention_status;
+ ops->set_attention_status = set_attention_status;
+ }
+
/* register this slot with the hotplug pci core */
hotplug->info = info;
hotplug->private = slot;
hotplug->release = &release_slot;
- hotplug->ops = &pciehp_hotplug_slot_ops;
+ hotplug->ops = ops;
slot->hotplug_slot = hotplug;
snprintf(name, SLOT_NAME_SIZE, "%u", PSN(ctrl));
@@ -128,17 +135,12 @@ static int init_slot(struct controller *ctrl)
ctrl->pcie->port->subordinate->number, PSN(ctrl));
retval = pci_hp_register(hotplug,
ctrl->pcie->port->subordinate, 0, name);
- if (retval) {
+ if (retval)
ctrl_err(ctrl,
"pci_hp_register failed with error %d\n", retval);
- goto out;
- }
- get_power_status(hotplug, &info->power_status);
- get_attention_status(hotplug, &info->attention_status);
- get_latch_status(hotplug, &info->latch_status);
- get_adapter_status(hotplug, &info->adapter_status);
out:
if (retval) {
+ kfree(ops);
kfree(info);
kfree(hotplug);
}
@@ -160,12 +162,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- hotplug_slot->info->attention_status = status;
-
- if (ATTN_LED(slot->ctrl))
- pciehp_set_attention_status(slot, status);
-
- return 0;
+ return pciehp_set_attention_status(slot, status);
}
@@ -193,92 +190,62 @@ static int disable_slot(struct hotplug_slot *hotplug_slot)
static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- retval = pciehp_get_power_status(slot, value);
- if (retval < 0)
- *value = hotplug_slot->info->power_status;
-
- return 0;
+ return pciehp_get_power_status(slot, value);
}
static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- retval = pciehp_get_attention_status(slot, value);
- if (retval < 0)
- *value = hotplug_slot->info->attention_status;
-
- return 0;
+ return pciehp_get_attention_status(slot, value);
}
static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- retval = pciehp_get_latch_status(slot, value);
- if (retval < 0)
- *value = hotplug_slot->info->latch_status;
-
- return 0;
+ return pciehp_get_latch_status(slot, value);
}
static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
{
struct slot *slot = hotplug_slot->private;
- int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- retval = pciehp_get_adapter_status(slot, value);
- if (retval < 0)
- *value = hotplug_slot->info->adapter_status;
-
- return 0;
+ return pciehp_get_adapter_status(slot, value);
}
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
enum pci_bus_speed *value)
{
struct slot *slot = hotplug_slot->private;
- int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- retval = pciehp_get_max_link_speed(slot, value);
- if (retval < 0)
- *value = PCI_SPEED_UNKNOWN;
-
- return 0;
+ return pciehp_get_max_link_speed(slot, value);
}
static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
{
struct slot *slot = hotplug_slot->private;
- int retval;
ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
__func__, slot_name(slot));
- retval = pciehp_get_cur_link_speed(slot, value);
- if (retval < 0)
- *value = PCI_SPEED_UNKNOWN;
-
- return 0;
+ return pciehp_get_cur_link_speed(slot, value);
}
static int pciehp_probe(struct pcie_device *dev)
@@ -286,14 +253,13 @@ static int pciehp_probe(struct pcie_device *dev)
int rc;
struct controller *ctrl;
struct slot *slot;
- u8 value;
- struct pci_dev *pdev = dev->port;
+ u8 occupied, poweron;
if (pciehp_force)
dev_info(&dev->device,
"Bypassing BIOS check for pciehp use on %s\n",
- pci_name(pdev));
- else if (pciehp_get_hp_hw_control_from_firmware(pdev))
+ pci_name(dev->port));
+ else if (pciehp_get_hp_hw_control_from_firmware(dev->port))
goto err_out_none;
ctrl = pcie_init(dev);
@@ -318,23 +284,18 @@ static int pciehp_probe(struct pcie_device *dev)
rc = pcie_init_notification(ctrl);
if (rc) {
ctrl_err(ctrl, "Notification initialization failed\n");
- goto err_out_release_ctlr;
+ goto err_out_free_ctrl_slot;
}
/* Check if slot is occupied */
slot = ctrl->slot;
- pciehp_get_adapter_status(slot, &value);
- if (value) {
- if (pciehp_force)
- pciehp_enable_slot(slot);
- } else {
- /* Power off slot if not occupied */
- if (POWER_CTRL(ctrl)) {
- rc = pciehp_power_off_slot(slot);
- if (rc)
- goto err_out_free_ctrl_slot;
- }
- }
+ pciehp_get_adapter_status(slot, &occupied);
+ pciehp_get_power_status(slot, &poweron);
+ if (occupied && pciehp_force)
+ pciehp_enable_slot(slot);
+ /* If empty slot's power status is on, turn power off */
+ if (!occupied && poweron && POWER_CTRL(ctrl))
+ pciehp_power_off_slot(slot);
return 0;
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 84487d126e4..d6ac1b261dd 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -142,23 +142,9 @@ u8 pciehp_handle_power_fault(struct slot *p_slot)
/* power fault */
ctrl_dbg(ctrl, "Power fault interrupt received\n");
-
- if (!pciehp_query_power_fault(p_slot)) {
- /*
- * power fault Cleared
- */
- ctrl_info(ctrl, "Power fault cleared on Slot(%s)\n",
- slot_name(p_slot));
- event_type = INT_POWER_FAULT_CLEAR;
- } else {
- /*
- * power fault
- */
- ctrl_info(ctrl, "Power fault on Slot(%s)\n", slot_name(p_slot));
- event_type = INT_POWER_FAULT;
- ctrl_info(ctrl, "Power fault bit %x set\n", 0);
- }
-
+ ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
+ event_type = INT_POWER_FAULT;
+ ctrl_info(ctrl, "Power fault bit %x set\n", 0);
queue_interrupt_event(p_slot, event_type);
return 1;
@@ -224,13 +210,12 @@ static int board_added(struct slot *p_slot)
retval = pciehp_check_link_status(ctrl);
if (retval) {
ctrl_err(ctrl, "Failed to check link status\n");
- set_slot_off(ctrl, p_slot);
- return retval;
+ goto err_exit;
}
/* Check for a power fault */
- if (pciehp_query_power_fault(p_slot)) {
- ctrl_dbg(ctrl, "Power fault detected\n");
+ if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
+ ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
retval = -EIO;
goto err_exit;
}
@@ -363,25 +348,6 @@ void pciehp_queue_pushbutton_work(struct work_struct *work)
mutex_unlock(&p_slot->lock);
}
-static int update_slot_info(struct slot *slot)
-{
- struct hotplug_slot_info *info;
- int result;
-
- info = kmalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- pciehp_get_power_status(slot, &info->power_status);
- pciehp_get_attention_status(slot, &info->attention_status);
- pciehp_get_latch_status(slot, &info->latch_status);
- pciehp_get_adapter_status(slot, &info->adapter_status);
-
- result = pci_hp_change_slot_info(slot->hotplug_slot, info);
- kfree (info);
- return result;
-}
-
/*
* Note: This function must be called with slot->lock held
*/
@@ -442,7 +408,6 @@ static void handle_button_press_event(struct slot *p_slot)
* to hot-add or hot-remove is undergoing
*/
ctrl_info(ctrl, "Button ignore on Slot(%s)\n", slot_name(p_slot));
- update_slot_info(p_slot);
break;
default:
ctrl_warn(ctrl, "Not a valid state\n");
@@ -500,11 +465,9 @@ static void interrupt_event_handler(struct work_struct *work)
if (!HP_SUPR_RM(ctrl))
break;
ctrl_dbg(ctrl, "Surprise Removal\n");
- update_slot_info(p_slot);
handle_surprise_event(p_slot);
break;
default:
- update_slot_info(p_slot);
break;
}
mutex_unlock(&p_slot->lock);
@@ -547,9 +510,6 @@ int pciehp_enable_slot(struct slot *p_slot)
if (rc) {
pciehp_get_latch_status(p_slot, &getstatus);
}
-
- update_slot_info(p_slot);
-
return rc;
}
@@ -590,10 +550,7 @@ int pciehp_disable_slot(struct slot *p_slot)
}
}
- ret = remove_board(p_slot);
- update_slot_info(p_slot);
-
- return ret;
+ return remove_board(p_slot);
}
int pciehp_sysfs_enable_slot(struct slot *p_slot)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 9ef4605c1ef..10040d58c8e 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -45,25 +45,25 @@ static atomic_t pciehp_num_controllers = ATOMIC_INIT(0);
static inline int pciehp_readw(struct controller *ctrl, int reg, u16 *value)
{
struct pci_dev *dev = ctrl->pcie->port;
- return pci_read_config_word(dev, ctrl->cap_base + reg, value);
+ return pci_read_config_word(dev, pci_pcie_cap(dev) + reg, value);
}
static inline int pciehp_readl(struct controller *ctrl, int reg, u32 *value)
{
struct pci_dev *dev = ctrl->pcie->port;
- return pci_read_config_dword(dev, ctrl->cap_base + reg, value);
+ return pci_read_config_dword(dev, pci_pcie_cap(dev) + reg, value);
}
static inline int pciehp_writew(struct controller *ctrl, int reg, u16 value)
{
struct pci_dev *dev = ctrl->pcie->port;
- return pci_write_config_word(dev, ctrl->cap_base + reg, value);
+ return pci_write_config_word(dev, pci_pcie_cap(dev) + reg, value);
}
static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value)
{
struct pci_dev *dev = ctrl->pcie->port;
- return pci_write_config_dword(dev, ctrl->cap_base + reg, value);
+ return pci_write_config_dword(dev, pci_pcie_cap(dev) + reg, value);
}
/* Power Control Command */
@@ -318,8 +318,8 @@ int pciehp_get_attention_status(struct slot *slot, u8 *status)
return retval;
}
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x, value read %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
atten_led_state = (slot_ctrl & PCI_EXP_SLTCTL_AIC) >> 6;
@@ -356,8 +356,8 @@ int pciehp_get_power_status(struct slot *slot, u8 *status)
ctrl_err(ctrl, "%s: Cannot read SLOTCTRL register\n", __func__);
return retval;
}
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_ctrl);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x value read %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_ctrl);
pwr_state = (slot_ctrl & PCI_EXP_SLTCTL_PCC) >> 10;
@@ -427,27 +427,24 @@ int pciehp_set_attention_status(struct slot *slot, u8 value)
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
u16 cmd_mask;
- int rc;
cmd_mask = PCI_EXP_SLTCTL_AIC;
switch (value) {
- case 0 : /* turn off */
- slot_cmd = 0x00C0;
- break;
- case 1: /* turn on */
- slot_cmd = 0x0040;
- break;
- case 2: /* turn blink */
- slot_cmd = 0x0080;
- break;
- default:
- return -1;
+ case 0 : /* turn off */
+ slot_cmd = 0x00C0;
+ break;
+ case 1: /* turn on */
+ slot_cmd = 0x0040;
+ break;
+ case 2: /* turn blink */
+ slot_cmd = 0x0080;
+ break;
+ default:
+ return -EINVAL;
}
- rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
-
- return rc;
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+ return pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
}
void pciehp_green_led_on(struct slot *slot)
@@ -459,8 +456,8 @@ void pciehp_green_led_on(struct slot *slot)
slot_cmd = 0x0100;
cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
}
void pciehp_green_led_off(struct slot *slot)
@@ -472,8 +469,8 @@ void pciehp_green_led_off(struct slot *slot)
slot_cmd = 0x0300;
cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
}
void pciehp_green_led_blink(struct slot *slot)
@@ -485,8 +482,8 @@ void pciehp_green_led_blink(struct slot *slot)
slot_cmd = 0x0200;
cmd_mask = PCI_EXP_SLTCTL_PIC;
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
}
int pciehp_power_on_slot(struct slot * slot)
@@ -514,97 +511,38 @@ int pciehp_power_on_slot(struct slot * slot)
return retval;
}
}
+ ctrl->power_fault_detected = 0;
slot_cmd = POWER_ON;
cmd_mask = PCI_EXP_SLTCTL_PCC;
- if (!pciehp_poll_mode) {
- /* Enable power fault detection turned off at power off time */
- slot_cmd |= PCI_EXP_SLTCTL_PFDE;
- cmd_mask |= PCI_EXP_SLTCTL_PFDE;
- }
-
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
ctrl_err(ctrl, "Write %x command failed!\n", slot_cmd);
return retval;
}
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
- ctrl->power_fault_detected = 0;
return retval;
}
-static inline int pcie_mask_bad_dllp(struct controller *ctrl)
-{
- struct pci_dev *dev = ctrl->pcie->port;
- 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->pcie->port;
- 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);
-}
-
int pciehp_power_off_slot(struct slot * slot)
{
struct controller *ctrl = slot->ctrl;
u16 slot_cmd;
u16 cmd_mask;
- int retval = 0;
- int changed;
-
- /*
- * 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);
+ int retval;
slot_cmd = POWER_OFF;
cmd_mask = PCI_EXP_SLTCTL_PCC;
- if (!pciehp_poll_mode) {
- /* Disable power fault detection */
- slot_cmd &= ~PCI_EXP_SLTCTL_PFDE;
- cmd_mask |= PCI_EXP_SLTCTL_PFDE;
- }
-
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
if (retval) {
ctrl_err(ctrl, "Write command failed!\n");
- retval = -1;
- goto out;
+ return retval;
}
- ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n",
- __func__, ctrl->cap_base + PCI_EXP_SLTCTL, slot_cmd);
- out:
- if (changed)
- pcie_unmask_bad_dllp(ctrl);
-
- return retval;
+ ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
+ pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
+ return 0;
}
static irqreturn_t pcie_isr(int irq, void *dev_id)
@@ -840,11 +778,19 @@ int pcie_enable_notification(struct controller *ctrl)
{
u16 cmd, mask;
+ /*
+ * TBD: Power fault detected software notification support.
+ *
+ * Power fault detected software notification is not enabled
+ * now, because it caused power fault detected interrupt storm
+ * on some machines. On those machines, power fault detected
+ * bit in the slot status register was set again immediately
+ * when it is cleared in the interrupt service routine, and
+ * next power fault detected interrupt was notified again.
+ */
cmd = PCI_EXP_SLTCTL_PDCE;
if (ATTN_BUTTN(ctrl))
cmd |= PCI_EXP_SLTCTL_ABPE;
- if (POWER_CTRL(ctrl))
- cmd |= PCI_EXP_SLTCTL_PFDE;
if (MRL_SENS(ctrl))
cmd |= PCI_EXP_SLTCTL_MRLSCE;
if (!pciehp_poll_mode)
@@ -866,7 +812,8 @@ static void pcie_disable_notification(struct controller *ctrl)
u16 mask;
mask = (PCI_EXP_SLTCTL_PDCE | PCI_EXP_SLTCTL_ABPE |
PCI_EXP_SLTCTL_MRLSCE | PCI_EXP_SLTCTL_PFDE |
- PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE);
+ PCI_EXP_SLTCTL_HPIE | PCI_EXP_SLTCTL_CCIE |
+ PCI_EXP_SLTCTL_DLLSCE);
if (pcie_write_cmd(ctrl, 0, mask))
ctrl_warn(ctrl, "Cannot disable software notification\n");
}
@@ -934,7 +881,8 @@ static inline void dbg_ctrl(struct controller *ctrl)
pdev->subsystem_device);
ctrl_info(ctrl, " Subsystem Vendor ID : 0x%04x\n",
pdev->subsystem_vendor);
- ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
+ ctrl_info(ctrl, " PCIe Cap offset : 0x%02x\n",
+ pci_pcie_cap(pdev));
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
if (!pci_resource_len(pdev, i))
continue;
@@ -978,8 +926,7 @@ struct controller *pcie_init(struct pcie_device *dev)
goto abort;
}
ctrl->pcie = dev;
- ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
- if (!ctrl->cap_base) {
+ if (!pci_pcie_cap(pdev)) {
ctrl_err(ctrl, "Cannot find PCI Express capability\n");
goto abort_ctrl;
}
diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c
index cc8ec3aa41a..80b461c9855 100644
--- a/drivers/pci/hotplug/pcihp_slot.c
+++ b/drivers/pci/hotplug/pcihp_slot.c
@@ -43,7 +43,7 @@ static void program_hpp_type0(struct pci_dev *dev, struct hpp_type0 *hpp)
* Perhaps we *should* use default settings for PCIe, but
* pciehp didn't, so we won't either.
*/
- if (dev->is_pcie)
+ if (pci_is_pcie(dev))
return;
dev_info(&dev->dev, "using default PCI settings\n");
hpp = &pci_default_type0;
@@ -102,7 +102,7 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
return;
/* Find PCI Express capability */
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(dev);
if (!pos)
return;
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index bd588eb8e92..8e210cd76e5 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -121,7 +121,7 @@ struct controller {
#define PCI_DEVICE_ID_AMD_GOLAM_7450 0x7450
#define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
-/* AMD PCIX bridge registers */
+/* AMD PCI-X bridge registers */
#define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
#define PCIX_MISCII_OFFSET 0x48
#define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80