aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/Kconfig15
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/dmar.c7
-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/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/intel-iommu.c10
-rw-r--r--drivers/pci/intr_remapping.c93
-rw-r--r--drivers/pci/intr_remapping.h7
-rw-r--r--drivers/pci/ioapic.c127
-rw-r--r--drivers/pci/iov.c2
-rw-r--r--drivers/pci/pci-acpi.c4
-rw-r--r--drivers/pci/pci-sysfs.c25
-rw-r--r--drivers/pci/pci.c154
-rw-r--r--drivers/pci/pci.h2
-rw-r--r--drivers/pci/pcie/aer/aer_inject.c58
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c4
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c70
-rw-r--r--drivers/pci/pcie/aer/ecrc.c4
-rw-r--r--drivers/pci/pcie/aspm.c41
-rw-r--r--drivers/pci/pcie/portdrv.h21
-rw-r--r--drivers/pci/pcie/portdrv_bus.c7
-rw-r--r--drivers/pci/pcie/portdrv_core.c239
-rw-r--r--drivers/pci/pcie/portdrv_pci.c14
-rw-r--r--drivers/pci/probe.c83
-rw-r--r--drivers/pci/quirks.c40
-rw-r--r--drivers/pci/search.c38
-rw-r--r--drivers/pci/setup-bus.c112
-rw-r--r--drivers/pci/setup-res.c68
39 files changed, 921 insertions, 983 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index fdc864f9cf2..b1ecefa2a23 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -27,10 +27,10 @@ config PCI_LEGACY
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.
+ pci_find_device() API. 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"
@@ -69,3 +69,10 @@ config PCI_IOV
physical resources.
If unsure, say N.
+
+config PCI_IOAPIC
+ bool
+ depends on PCI
+ depends on ACPI
+ depends on HOTPLUG
+ default y
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 4a7f11d8f43..4df48d58eaa 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -14,6 +14,8 @@ CFLAGS_legacy.o += -Wno-deprecated-declarations
# Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/
+obj-$(CONFIG_PCI_IOAPIC) += ioapic.o
+
obj-$(CONFIG_HOTPLUG) += hotplug.o
# Build the PCI Hotplug drivers if we were asked to
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c
index 416f6ac65b7..6cdc931f7c1 100644
--- a/drivers/pci/dmar.c
+++ b/drivers/pci/dmar.c
@@ -320,7 +320,7 @@ found:
for (bus = dev->bus; bus; bus = bus->parent) {
struct pci_dev *bridge = bus->self;
- if (!bridge || !bridge->is_pcie ||
+ if (!bridge || !pci_is_pcie(bridge) ||
bridge->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE)
return 0;
@@ -645,8 +645,11 @@ void __init detect_intel_iommu(void)
"x2apic and Intr-remapping.\n");
#endif
#ifdef CONFIG_DMAR
- if (ret && !no_iommu && !iommu_detected && !dmar_disabled)
+ if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
iommu_detected = 1;
+ /* Make sure ACS will be enabled */
+ pci_request_acs();
+ }
#endif
#ifdef CONFIG_X86
if (ret)
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/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/intel-iommu.c b/drivers/pci/intel-iommu.c
index 9261327b49f..8d615942631 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -1611,7 +1611,7 @@ domain_context_mapping(struct dmar_domain *domain, struct pci_dev *pdev,
return ret;
parent = parent->bus->self;
}
- if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+ if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
return domain_context_mapping_one(domain,
pci_domain_nr(tmp->subordinate),
tmp->subordinate->number, 0,
@@ -1651,7 +1651,7 @@ static int domain_context_mapped(struct pci_dev *pdev)
return ret;
parent = parent->bus->self;
}
- if (tmp->is_pcie)
+ if (pci_is_pcie(tmp))
return device_context_mapped(iommu, tmp->subordinate->number,
0);
else
@@ -1821,7 +1821,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
dev_tmp = pci_find_upstream_pcie_bridge(pdev);
if (dev_tmp) {
- if (dev_tmp->is_pcie) {
+ if (pci_is_pcie(dev_tmp)) {
bus = dev_tmp->subordinate->number;
devfn = 0;
} else {
@@ -2182,7 +2182,7 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
* the 1:1 domain, just in _case_ one of their siblings turns out
* not to be able to map all of memory.
*/
- if (!pdev->is_pcie) {
+ if (!pci_is_pcie(pdev)) {
if (!pci_is_root_bus(pdev->bus))
return 0;
if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
@@ -3319,7 +3319,7 @@ static void iommu_detach_dependent_devices(struct intel_iommu *iommu,
parent->devfn);
parent = parent->bus->self;
}
- if (tmp->is_pcie) /* this is a PCIE-to-PCI bridge */
+ if (pci_is_pcie(tmp)) /* this is a PCIE-to-PCI bridge */
iommu_detach_dev(iommu,
tmp->subordinate->number, 0);
else /* this is a legacy PCI bridge */
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 0ed78a764de..1487bf2be86 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -2,6 +2,7 @@
#include <linux/dmar.h>
#include <linux/spinlock.h>
#include <linux/jiffies.h>
+#include <linux/hpet.h>
#include <linux/pci.h>
#include <linux/irq.h>
#include <asm/io_apic.h>
@@ -14,7 +15,8 @@
#include "pci.h"
static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
-static int ir_ioapic_num;
+static struct hpet_scope ir_hpet[MAX_HPET_TBS];
+static int ir_ioapic_num, ir_hpet_num;
int intr_remapping_enabled;
static int disable_intremap;
@@ -343,6 +345,16 @@ int flush_irte(int irq)
return rc;
}
+struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
+{
+ int i;
+
+ for (i = 0; i < MAX_HPET_TBS; i++)
+ if (ir_hpet[i].id == hpet_id)
+ return ir_hpet[i].iommu;
+ return NULL;
+}
+
struct intel_iommu *map_ioapic_to_ir(int apic)
{
int i;
@@ -470,6 +482,36 @@ int set_ioapic_sid(struct irte *irte, int apic)
return 0;
}
+int set_hpet_sid(struct irte *irte, u8 id)
+{
+ int i;
+ u16 sid = 0;
+
+ if (!irte)
+ return -1;
+
+ for (i = 0; i < MAX_HPET_TBS; i++) {
+ if (ir_hpet[i].id == id) {
+ sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
+ break;
+ }
+ }
+
+ if (sid == 0) {
+ pr_warning("Failed to set source-id of HPET block (%d)\n", id);
+ return -1;
+ }
+
+ /*
+ * Should really use SQ_ALL_16. Some platforms are broken.
+ * While we figure out the right quirks for these broken platforms, use
+ * SQ_13_IGNORE_3 for now.
+ */
+ set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_13_IGNORE_3, sid);
+
+ return 0;
+}
+
int set_msi_sid(struct irte *irte, struct pci_dev *dev)
{
struct pci_dev *bridge;
@@ -478,7 +520,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
return -1;
/* PCIe device or Root Complex integrated PCI device */
- if (dev->is_pcie || !dev->bus->parent) {
+ if (pci_is_pcie(dev) || !dev->bus->parent) {
set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
(dev->bus->number << 8) | dev->devfn);
return 0;
@@ -486,7 +528,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
bridge = pci_find_upstream_pcie_bridge(dev);
if (bridge) {
- if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */
+ if (pci_is_pcie(bridge))/* this is a PCIE-to-PCI/PCIX bridge */
set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
(bridge->bus->number << 8) | dev->bus->number);
else /* this is a legacy PCI bridge */
@@ -711,6 +753,34 @@ error:
return -1;
}
+static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope,
+ struct intel_iommu *iommu)
+{
+ struct acpi_dmar_pci_path *path;
+ u8 bus;
+ int count;
+
+ bus = scope->bus;
+ path = (struct acpi_dmar_pci_path *)(scope + 1);
+ count = (scope->length - sizeof(struct acpi_dmar_device_scope))
+ / sizeof(struct acpi_dmar_pci_path);
+
+ while (--count > 0) {
+ /*
+ * Access PCI directly due to the PCI
+ * subsystem isn't initialized yet.
+ */
+ bus = read_pci_config_byte(bus, path->dev, path->fn,
+ PCI_SECONDARY_BUS);
+ path++;
+ }
+ ir_hpet[ir_hpet_num].bus = bus;
+ ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn);
+ ir_hpet[ir_hpet_num].iommu = iommu;
+ ir_hpet[ir_hpet_num].id = scope->enumeration_id;
+ ir_hpet_num++;
+}
+
static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
struct intel_iommu *iommu)
{
@@ -740,8 +810,8 @@ static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
ir_ioapic_num++;
}
-static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
- struct intel_iommu *iommu)
+static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header,
+ struct intel_iommu *iommu)
{
struct acpi_dmar_hardware_unit *drhd;
struct acpi_dmar_device_scope *scope;
@@ -765,6 +835,17 @@ static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
drhd->address);
ir_parse_one_ioapic_scope(scope, iommu);
+ } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
+ if (ir_hpet_num == MAX_HPET_TBS) {
+ printk(KERN_WARNING "Exceeded Max HPET blocks\n");
+ return -1;
+ }
+
+ printk(KERN_INFO "HPET id %d under DRHD base"
+ " 0x%Lx\n", scope->enumeration_id,
+ drhd->address);
+
+ ir_parse_one_hpet_scope(scope, iommu);
}
start += scope->length;
}
@@ -785,7 +866,7 @@ int __init parse_ioapics_under_ir(void)
struct intel_iommu *iommu = drhd->iommu;
if (ecap_ir_support(iommu->ecap)) {
- if (ir_parse_ioapic_scope(drhd->hdr, iommu))
+ if (ir_parse_ioapic_hpet_scope(drhd->hdr, iommu))
return -1;
ir_supported = 1;
diff --git a/drivers/pci/intr_remapping.h b/drivers/pci/intr_remapping.h
index 63a263c1841..5662fecfee6 100644
--- a/drivers/pci/intr_remapping.h
+++ b/drivers/pci/intr_remapping.h
@@ -7,4 +7,11 @@ struct ioapic_scope {
unsigned int devfn; /* PCI devfn number */
};
+struct hpet_scope {
+ struct intel_iommu *iommu;
+ u8 id;
+ unsigned int bus;
+ unsigned int devfn;
+};
+
#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
new file mode 100644
index 00000000000..3e0d7b5dd1b
--- /dev/null
+++ b/drivers/pci/ioapic.c
@@ -0,0 +1,127 @@
+/*
+ * IOAPIC/IOxAPIC/IOSAPIC driver
+ *
+ * Copyright (C) 2009 Fujitsu Limited.
+ * (c) Copyright 2009 Hewlett-Packard Development Company, L.P.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * This driver manages PCI I/O APICs added by hotplug after boot. We try to
+ * claim all I/O APIC PCI devices, but those present at boot were registered
+ * when we parsed the ACPI MADT, so we'll fail when we try to re-register
+ * them.
+ */
+
+#include <linux/pci.h>
+#include <linux/acpi.h>
+#include <acpi/acpi_bus.h>
+
+struct ioapic {
+ acpi_handle handle;
+ u32 gsi_base;
+};
+
+static int ioapic_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+ acpi_handle handle;
+ acpi_status status;
+ unsigned long long gsb;
+ struct ioapic *ioapic;
+ u64 addr;
+ int ret;
+ char *type;
+
+ handle = DEVICE_ACPI_HANDLE(&dev->dev);
+ if (!handle)
+ return -EINVAL;
+
+ status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+
+ /*
+ * The previous code in acpiphp evaluated _MAT if _GSB failed, but
+ * ACPI spec 4.0 sec 6.2.2 requires _GSB for hot-pluggable I/O APICs.
+ */
+
+ ioapic = kzalloc(sizeof(*ioapic), GFP_KERNEL);
+ if (!ioapic)
+ return -ENOMEM;
+
+ ioapic->handle = handle;
+ ioapic->gsi_base = (u32) gsb;
+
+ if (dev->class == PCI_CLASS_SYSTEM_PIC_IOAPIC)
+ type = "IOAPIC";
+ else
+ type = "IOxAPIC";
+
+ ret = pci_enable_device(dev);
+ if (ret < 0)
+ goto exit_free;
+
+ pci_set_master(dev);
+
+ if (pci_request_region(dev, 0, type))
+ goto exit_disable;
+
+ addr = pci_resource_start(dev, 0);
+ if (acpi_register_ioapic(ioapic->handle, addr, ioapic->gsi_base))
+ goto exit_release;
+
+ pci_set_drvdata(dev, ioapic);
+ dev_info(&dev->dev, "%s at %#llx, GSI %u\n", type, addr,
+ ioapic->gsi_base);
+ return 0;
+
+exit_release:
+ pci_release_region(dev, 0);
+exit_disable:
+ pci_disable_device(dev);
+exit_free:
+ kfree(ioapic);
+ return -ENODEV;
+}
+
+static void ioapic_remove(struct pci_dev *dev)
+{
+ struct ioapic *ioapic = pci_get_drvdata(dev);
+
+ acpi_unregister_ioapic(ioapic->handle, ioapic->gsi_base);
+ pci_release_region(dev, 0);
+ pci_disable_device(dev);
+ kfree(ioapic);
+}
+
+
+static struct pci_device_id ioapic_devices[] = {
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_SYSTEM_PIC_IOAPIC << 8, 0xffff00, },
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_SYSTEM_PIC_IOXAPIC << 8, 0xffff00, },
+ { }
+};
+
+static struct pci_driver ioapic_driver = {
+ .name = "ioapic",
+ .id_table = ioapic_devices,
+ .probe = ioapic_probe,
+ .remove = __devexit_p(ioapic_remove),
+};
+
+static int __init ioapic_init(void)
+{
+ return pci_register_driver(&ioapic_driver);
+}
+
+static void __exit ioapic_exit(void)
+{
+ pci_unregister_driver(&ioapic_driver);
+}
+
+module_init(ioapic_init);
+module_exit(ioapic_exit);
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index e03fe98f061..b2a448e19fe 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -555,7 +555,7 @@ int pci_iov_init(struct pci_dev *dev)
{
int pos;
- if (!dev->is_pcie)
+ if (!pci_is_pcie(dev))
return -ENODEV;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 33317df4769..cc617ddd33d 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -116,7 +116,7 @@ static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable)
int ret;
ret = acpi_pm_device_sleep_wake(&bridge->dev, enable);
- if (!ret || bridge->is_pcie)
+ if (!ret || pci_is_pcie(bridge))
return;
bus = bus->parent;
}
@@ -131,7 +131,7 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
if (acpi_pci_can_wakeup(dev))
return acpi_pm_device_sleep_wake(&dev->dev, enable);
- if (!dev->is_pcie)
+ if (!pci_is_pcie(dev))
acpi_pci_propagate_wakeup_enable(dev->bus, enable);
return 0;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 0f6382f090e..c5df94e8667 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -74,7 +74,11 @@ static ssize_t local_cpus_show(struct device *dev,
const struct cpumask *mask;
int len;
+#ifdef CONFIG_NUMA
+ mask = cpumask_of_node(dev_to_node(dev));
+#else
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
+#endif
len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n';
buf[len] = '\0';
@@ -88,7 +92,11 @@ static ssize_t local_cpulist_show(struct device *dev,
const struct cpumask *mask;
int len;
+#ifdef CONFIG_NUMA
+ mask = cpumask_of_node(dev_to_node(dev));
+#else
mask = cpumask_of_pcibus(to_pci_dev(dev)->bus);
+#endif
len = cpulist_scnprintf(buf, PAGE_SIZE-2, mask);
buf[len++] = '\n';
buf[len] = '\0';
@@ -176,6 +184,21 @@ numa_node_show(struct device *dev, struct device_attribute *attr, char *buf)
#endif
static ssize_t
+dma_mask_bits_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ return sprintf (buf, "%d\n", fls64(pdev->dma_mask));
+}
+
+static ssize_t
+consistent_dma_mask_bits_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf (buf, "%d\n", fls64(dev->coherent_dma_mask));
+}
+
+static ssize_t
msi_bus_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -306,6 +329,8 @@ struct device_attribute pci_dev_attrs[] = {
#ifdef CONFIG_NUMA
__ATTR_RO(numa_node),
#endif
+ __ATTR_RO(dma_mask_bits),
+ __ATTR_RO(consistent_dma_mask_bits),
__ATTR(enable, 0600, is_enabled_show, is_enabled_store),
__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
broken_parity_status_show,broken_parity_status_store),
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 4e4c295a049..0bc27e05901 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -47,6 +47,15 @@ unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
unsigned long pci_hotplug_io_size = DEFAULT_HOTPLUG_IO_SIZE;
unsigned long pci_hotplug_mem_size = DEFAULT_HOTPLUG_MEM_SIZE;
+/*
+ * The default CLS is used if arch didn't set CLS explicitly and not
+ * all pci devices agree on the same value. Arch can override either
+ * the dfl or actual value as it sees fit. Don't forget this is
+ * measured in 32-bit words, not bytes.
+ */
+u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
+u8 pci_cache_line_size;
+
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search
@@ -373,8 +382,12 @@ pci_find_parent_resource(const struct pci_dev *dev, struct resource *res)
continue; /* Wrong type */
if (!((res->flags ^ r->flags) & IORESOURCE_PREFETCH))
return r; /* Exact match */
- if ((res->flags & IORESOURCE_PREFETCH) && !(r->flags & IORESOURCE_PREFETCH))
- best = r; /* Approximating prefetchable by non-prefetchable */
+ /* We can't insert a non-prefetch resource inside a prefetchable parent .. */
+ if (r->flags & IORESOURCE_PREFETCH)
+ continue;
+ /* .. but we can put a prefetchable resource inside a non-prefetchable one */
+ if (!best)
+ best = r;
}
return best;
}
@@ -728,8 +741,8 @@ static int pci_save_pcie_state(struct pci_dev *dev)
u16 *cap;
u16 flags;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
- if (pos <= 0)
+ pos = pci_pcie_cap(dev);
+ if (!pos)
return 0;
save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
@@ -837,7 +850,7 @@ pci_save_state(struct pci_dev *dev)
int i;
/* XXX: 100% dword access ok here? */
for (i = 0; i < 16; i++)
- pci_read_config_dword(dev, i * 4,&dev->saved_config_space[i]);
+ pci_read_config_dword(dev, i * 4, &dev->saved_config_space[i]);
dev->state_saved = true;
if ((i = pci_save_pcie_state(dev)) != 0)
return i;
@@ -1202,7 +1215,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);
- dev_printk(KERN_INFO, &dev->dev, "PME# %s\n",
+ dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
enable ? "enabled" : "disabled");
}
@@ -1413,7 +1426,8 @@ void pci_pm_init(struct pci_dev *dev)
pmc &= PCI_PM_CAP_PME_MASK;
if (pmc) {
- dev_info(&dev->dev, "PME# supported from%s%s%s%s%s\n",
+ dev_printk(KERN_DEBUG, &dev->dev,
+ "PME# supported from%s%s%s%s%s\n",
(pmc & PCI_PM_CAP_PME_D0) ? " D0" : "",
(pmc & PCI_PM_CAP_PME_D1) ? " D1" : "",
(pmc & PCI_PM_CAP_PME_D2) ? " D2" : "",
@@ -1510,7 +1524,7 @@ void pci_enable_ari(struct pci_dev *dev)
u16 ctrl;
struct pci_dev *bridge;
- if (!dev->is_pcie || dev->devfn)
+ if (!pci_is_pcie(dev) || dev->devfn)
return;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI);
@@ -1518,10 +1532,10 @@ void pci_enable_ari(struct pci_dev *dev)
return;
bridge = dev->bus->self;
- if (!bridge || !bridge->is_pcie)
+ if (!bridge || !pci_is_pcie(bridge))
return;
- pos = pci_find_capability(bridge, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(bridge);
if (!pos)
return;
@@ -1536,6 +1550,54 @@ void pci_enable_ari(struct pci_dev *dev)
bridge->ari_enabled = 1;
}
+static int pci_acs_enable;
+
+/**
+ * pci_request_acs - ask for ACS to be enabled if supported
+ */
+void pci_request_acs(void)
+{
+ pci_acs_enable = 1;
+}
+
+/**
+ * pci_enable_acs - enable ACS if hardware support it
+ * @dev: the PCI device
+ */
+void pci_enable_acs(struct pci_dev *dev)
+{
+ int pos;
+ u16 cap;
+ u16 ctrl;
+
+ if (!pci_acs_enable)
+ return;
+
+ if (!pci_is_pcie(dev))
+ return;
+
+ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ACS);
+ if (!pos)
+ return;
+
+ pci_read_config_word(dev, pos + PCI_ACS_CAP, &cap);
+ pci_read_config_word(dev, pos + PCI_ACS_CTRL, &ctrl);
+
+ /* Source Validation */
+ ctrl |= (cap & PCI_ACS_SV);
+
+ /* P2P Request Redirect */
+ ctrl |= (cap & PCI_ACS_RR);
+
+ /* P2P Completion Redirect */
+ ctrl |= (cap & PCI_ACS_CR);
+
+ /* Upstream Forwarding */
+ ctrl |= (cap & PCI_ACS_UF);
+
+ pci_write_config_word(dev, pos + PCI_ACS_CTRL, ctrl);
+}
+
/**
* pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
* @dev: the PCI device
@@ -1669,9 +1731,7 @@ static int __pci_request_region(struct pci_dev *pdev, int bar, const char *res_n
return 0;
err_out:
- dev_warn(&pdev->dev, "BAR %d: can't reserve %s region %pR\n",
- bar,
- pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
+ dev_warn(&pdev->dev, "BAR %d: can't reserve %pR\n", bar,
&pdev->resource[bar]);
return -EBUSY;
}
@@ -1866,31 +1926,6 @@ void pci_clear_master(struct pci_dev *dev)
__pci_set_master(dev, false);
}
-#ifdef PCI_DISABLE_MWI
-int pci_set_mwi(struct pci_dev *dev)
-{
- return 0;
-}
-
-int pci_try_set_mwi(struct pci_dev *dev)
-{
- return 0;
-}
-
-void pci_clear_mwi(struct pci_dev *dev)
-{
-}
-
-#else
-
-#ifndef PCI_CACHE_LINE_BYTES
-#define PCI_CACHE_LINE_BYTES L1_CACHE_BYTES
-#endif
-
-/* This can be overridden by arch code. */
-/* Don't forget this is measured in 32-bit words, not bytes */
-u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
-
/**
* pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed
* @dev: the PCI device for which MWI is to be enabled
@@ -1901,13 +1936,12 @@ u8 pci_cache_line_size = PCI_CACHE_LINE_BYTES / 4;
*
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/
-static int
-pci_set_cacheline_size(struct pci_dev *dev)
+int pci_set_cacheline_size(struct pci_dev *dev)
{
u8 cacheline_size;
if (!pci_cache_line_size)
- return -EINVAL; /* The system doesn't support MWI. */
+ return -EINVAL;
/* Validate current setting: the PCI_CACHE_LINE_SIZE must be
equal to or multiple of the right value. */
@@ -1928,6 +1962,24 @@ pci_set_cacheline_size(struct pci_dev *dev)
return -EINVAL;
}
+EXPORT_SYMBOL_GPL(pci_set_cacheline_size);
+
+#ifdef PCI_DISABLE_MWI
+int pci_set_mwi(struct pci_dev *dev)
+{
+ return 0;
+}
+
+int pci_try_set_mwi(struct pci_dev *dev)
+{
+ return 0;
+}
+
+void pci_clear_mwi(struct pci_dev *dev)
+{
+}
+
+#else
/**
* pci_set_mwi - enables memory-write-invalidate PCI transaction
@@ -2062,6 +2114,7 @@ pci_set_dma_mask(struct pci_dev *dev, u64 mask)
return -EIO;
dev->dma_mask = mask;
+ dev_dbg(&dev->dev, "using %dbit DMA mask\n", fls64(mask));
return 0;
}
@@ -2073,6 +2126,7 @@ pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
return -EIO;
dev->dev.coherent_dma_mask = mask;
+ dev_dbg(&dev->dev, "using %dbit consistent DMA mask\n", fls64(mask));
return 0;
}
@@ -2099,9 +2153,9 @@ static int pcie_flr(struct pci_dev *dev, int probe)
int i;
int pos;
u32 cap;
- u16 status;
+ u16 status, control;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(dev);
if (!pos)
return -ENOTTY;
@@ -2126,8 +2180,10 @@ static int pcie_flr(struct pci_dev *dev, int probe)
"proceeding with reset anyway\n");
clear:
- pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
- PCI_EXP_DEVCTL_BCR_FLR);
+ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &control);
+ control |= PCI_EXP_DEVCTL_BCR_FLR;
+ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, control);
+
msleep(100);
return 0;
@@ -2450,7 +2506,7 @@ int pcie_get_readrq(struct pci_dev *dev)
int ret, cap;
u16 ctl;
- cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(dev);
if (!cap)
return -EINVAL;
@@ -2480,7 +2536,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq)
v = (ffs(rq) - 8) << 12;
- cap = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ cap = pci_pcie_cap(dev);
if (!cap)
goto out;
@@ -2540,7 +2596,7 @@ int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type)
return reg;
}
- dev_err(&dev->dev, "BAR: invalid resource #%d\n", resno);
+ dev_err(&dev->dev, "BAR %d: invalid resource\n", resno);
return 0;
}
@@ -2590,7 +2646,7 @@ int pci_set_vga_state(struct pci_dev *dev, bool decode,
#define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
-spinlock_t resource_alignment_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(resource_alignment_lock);
/**
* pci_specified_resource_alignment - get resource alignment specified by user.
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index d92d1954a2f..33ed8e0aba1 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -311,4 +311,6 @@ static inline int pci_resource_alignment(struct pci_dev *dev,
return resource_alignment(res);
}
+extern void pci_enable_acs(struct pci_dev *dev);
+
#endif /* DRIVERS_PCI_H */
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer/aer_inject.c
index 62d15f652bb..7fcd5331b14 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer/aer_inject.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
+#include <linux/stddef.h>
#include "aerdrv.h"
struct aer_error_inj {
@@ -35,10 +36,12 @@ struct aer_error_inj {
u32 header_log1;
u32 header_log2;
u32 header_log3;
+ u16 domain;
};
struct aer_error {
struct list_head list;
+ u16 domain;
unsigned int bus;
unsigned int devfn;
int pos_cap_err;
@@ -66,22 +69,27 @@ static LIST_HEAD(pci_bus_ops_list);
/* Protect einjected and pci_bus_ops_list */
static DEFINE_SPINLOCK(inject_lock);
-static void aer_error_init(struct aer_error *err, unsigned int bus,
- unsigned int devfn, int pos_cap_err)
+static void aer_error_init(struct aer_error *err, u16 domain,
+ unsigned int bus, unsigned int devfn,
+ int pos_cap_err)
{
INIT_LIST_HEAD(&err->list);
+ err->domain = domain;
err->bus = bus;
err->devfn = devfn;
err->pos_cap_err = pos_cap_err;
}
/* inject_lock must be held before calling */
-static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
+static struct aer_error *__find_aer_error(u16 domain, unsigned int bus,
+ unsigned int devfn)
{
struct aer_error *err;
list_for_each_entry(err, &einjected, list) {
- if (bus == err->bus && devfn == err->devfn)
+ if (domain == err->domain &&
+ bus == err->bus &&
+ devfn == err->devfn)
return err;
}
return NULL;
@@ -90,7 +98,10 @@ static struct aer_error *__find_aer_error(unsigned int bus, unsigned int devfn)
/* inject_lock must be held before calling */
static struct aer_error *__find_aer_error_by_dev(struct pci_dev *dev)
{
- return __find_aer_error(dev->bus->number, dev->devfn);
+ int domain = pci_domain_nr(dev->bus);
+ if (domain < 0)
+ return NULL;
+ return __find_aer_error((u16)domain, dev->bus->number, dev->devfn);
}
/* inject_lock must be held before calling */
@@ -172,11 +183,15 @@ static int pci_read_aer(struct pci_bus *bus, unsigned int devfn, int where,
struct aer_error *err;
unsigned long flags;
struct pci_ops *ops;
+ int domain;
spin_lock_irqsave(&inject_lock, flags);
if (size != sizeof(u32))
goto out;
- err = __find_aer_error(bus->number, devfn);
+ domain = pci_domain_nr(bus);
+ if (domain < 0)
+ goto out;
+ err = __find_aer_error((u16)domain, bus->number, devfn);
if (!err)
goto out;
@@ -200,11 +215,15 @@ int pci_write_aer(struct pci_bus *bus, unsigned int devfn, int where, int size,
unsigned long flags;
int rw1cs;
struct pci_ops *ops;
+ int domain;
spin_lock_irqsave(&inject_lock, flags);
if (size != sizeof(u32))
goto out;
- err = __find_aer_error(bus->number, devfn);
+ domain = pci_domain_nr(bus);
+ if (domain < 0)
+ goto out;
+ err = __find_aer_error((u16)domain, bus->number, devfn);
if (!err)
goto out;
@@ -262,7 +281,7 @@ out:
static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
{
while (1) {
- if (!dev->is_pcie)
+ if (!pci_is_pcie(dev))
break;
if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
return dev;
@@ -305,25 +324,25 @@ static int aer_inject(struct aer_error_inj *einj)
u32 sever;
int ret = 0;
- dev = pci_get_bus_and_slot(einj->bus, devfn);
+ dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
if (!dev)
- return -EINVAL;
+ return -ENODEV;
rpdev = pcie_find_root_port(dev);
if (!rpdev) {
- ret = -EINVAL;
+ ret = -ENOTTY;
goto out_put;
}
pos_cap_err = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos_cap_err) {
- ret = -EIO;
+ ret = -ENOTTY;
goto out_put;
}
pci_read_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_SEVER, &sever);
rp_pos_cap_err = pci_find_ext_capability(rpdev, PCI_EXT_CAP_ID_ERR);
if (!rp_pos_cap_err) {
- ret = -EIO;
+ ret = -ENOTTY;
goto out_put;
}
@@ -344,7 +363,8 @@ static int aer_inject(struct aer_error_inj *einj)
if (!err) {
err = err_alloc;
err_alloc = NULL;
- aer_error_init(err, einj->bus, devfn, pos_cap_err);
+ aer_error_init(err, einj->domain, einj->bus, devfn,
+ pos_cap_err);
list_add(&err->list, &einjected);
}
err->uncor_status |= einj->uncor_status;
@@ -358,7 +378,8 @@ static int aer_inject(struct aer_error_inj *einj)
if (!rperr) {
rperr = rperr_alloc;
rperr_alloc = NULL;
- aer_error_init(rperr, rpdev->bus->number, rpdev->devfn,
+ aer_error_init(rperr, pci_domain_nr(rpdev->bus),
+ rpdev->bus->number, rpdev->devfn,
rp_pos_cap_err);
list_add(&rperr->list, &einjected);
}
@@ -411,10 +432,11 @@ static ssize_t aer_inject_write(struct file *filp, const char __user *ubuf,
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
-
- if (usize != sizeof(struct aer_error_inj))
+ if (usize < offsetof(struct aer_error_inj, domain) ||
+ usize > sizeof(einj))
return -EINVAL;
+ memset(&einj, 0, sizeof(einj));
if (copy_from_user(&einj, ubuf, usize))
return -EFAULT;
@@ -452,7 +474,7 @@ static void __exit aer_inject_exit(void)
}
spin_lock_irqsave(&inject_lock, flags);
- list_for_each_entry_safe(err, err_next, &pci_bus_ops_list, list) {
+ list_for_each_entry_safe(err, err_next, &einjected, list) {
list_del(&err->list);
kfree(err);
}
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 40c3cc5d1ca..97a345927b5 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -53,7 +53,7 @@ static struct pci_error_handlers aer_error_handlers = {
static struct pcie_port_service_driver aerdriver = {
.name = "aer",
- .port_type = PCIE_RC_PORT,
+ .port_type = PCI_EXP_TYPE_ROOT_PORT,
.service = PCIE_PORT_SERVICE_AER,
.probe = aer_probe,
@@ -295,7 +295,7 @@ static void aer_error_resume(struct pci_dev *dev)
u16 reg16;
/* Clean up Root device status */
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(dev);
pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &reg16);
pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, reg16);
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 9f5ccbeb4fa..ae672ca8033 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -35,11 +35,14 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev)
u16 reg16 = 0;
int pos;
+ if (dev->aer_firmware_first)
+ return -EIO;
+
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return -EIO;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(dev);
if (!pos)
return -EIO;
@@ -60,7 +63,10 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev)
u16 reg16 = 0;
int pos;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ if (dev->aer_firmware_first)
+ return -EIO;
+
+ pos = pci_pcie_cap(dev);
if (!pos)
return -EIO;
@@ -78,48 +84,27 @@ EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
{
int pos;
- u32 status, mask;
+ u32 status;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
if (!pos)
return -EIO;
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
- if (dev->error_state == pci_channel_io_normal)
- status &= ~mask; /* Clear corresponding nonfatal bits */
- else
- status &= mask; /* Clear corresponding fatal bits */
- pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+ if (status)
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
return 0;
}
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
-#if 0
-int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
-{
- int pos;
- u32 status;
-
- pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
- if (!pos)
- return -EIO;
-
- pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
- pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
-
- return 0;
-}
-#endif /* 0 */
-
static int set_device_error_reporting(struct pci_dev *dev, void *data)
{
bool enable = *((bool *)data);
- if (dev->pcie_type == PCIE_RC_PORT ||
- dev->pcie_type == PCIE_SW_UPSTREAM_PORT ||
- dev->pcie_type == PCIE_SW_DOWNSTREAM_PORT) {
+ if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
+ (dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
+ (dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) {
if (enable)
pci_enable_pcie_error_reporting(dev);
else
@@ -218,7 +203,7 @@ static int find_device_iter(struct pci_dev *dev, void *data)
*/
if (atomic_read(&dev->enable_cnt) == 0)
return 0;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(dev);
if (!pos)
return 0;
/* Check if AER is enabled */
@@ -431,10 +416,9 @@ static int find_aer_service_iter(struct device *device, void *data)
result = (struct find_aer_service_data *) data;
if (device->bus == &pcie_port_bus_type) {
- struct pcie_port_data *port_data;
+ struct pcie_device *pcie = to_pcie_device(device);
- port_data = pci_get_drvdata(to_pcie_device(device)->port);
- if (port_data->port_type == PCIE_SW_DOWNSTREAM_PORT)
+ if (pcie->port->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
result->is_downstream = 1;
driver = device->driver;
@@ -612,7 +596,7 @@ void aer_enable_rootport(struct aer_rpc *rpc)
u16 reg16;
u32 reg32;
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
/* Clear PCIE Capability's Device Status */
pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
@@ -874,8 +858,22 @@ void aer_delete_rootport(struct aer_rpc *rpc)
*/
int aer_init(struct pcie_device *dev)
{
- if (aer_osc_setup(dev) && !forceload)
- return -ENXIO;
+ if (dev->port->aer_firmware_first) {
+ dev_printk(KERN_DEBUG, &dev->device,
+ "PCIe errors handled by platform firmware.\n");
+ goto out;
+ }
+
+ if (aer_osc_setup(dev))
+ goto out;
return 0;
+out:
+ if (forceload) {
+ dev_printk(KERN_DEBUG, &dev->device,
+ "aerdrv forceload requested.\n");
+ dev->port->aer_firmware_first = 0;
+ return 0;
+ }
+ return -ENXIO;
}
diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c
index a928d8ab6bd..a2747a663bc 100644
--- a/drivers/pci/pcie/aer/ecrc.c
+++ b/drivers/pci/pcie/aer/ecrc.c
@@ -51,7 +51,7 @@ static int enable_ecrc_checking(struct pci_dev *dev)
int pos;
u32 reg32;
- if (!dev->is_pcie)
+ if (!pci_is_pcie(dev))
return -ENODEV;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
@@ -79,7 +79,7 @@ static int disable_ecrc_checking(struct pci_dev *dev)
int pos;
u32 reg32;
- if (!dev->is_pcie)
+ if (!pci_is_pcie(dev))
return -ENODEV;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 5b7056cec00..5a01fc7fbf0 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -122,7 +122,7 @@ static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
struct pci_bus *linkbus = link->pdev->subordinate;
list_for_each_entry(child, &linkbus->devices, bus_list) {
- pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(child);
if (!pos)
return;
pci_read_config_word(child, pos + PCI_EXP_LNKCTL, &reg16);
@@ -156,7 +156,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
/* All functions should have the same cap and state, take the worst */
list_for_each_entry(child, &linkbus->devices, bus_list) {
- pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(child);
if (!pos)
return;
pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, &reg32);
@@ -191,23 +191,23 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
* Configuration, so just check one function
*/
child = list_entry(linkbus->devices.next, struct pci_dev, bus_list);
- BUG_ON(!child->is_pcie);
+ BUG_ON(!pci_is_pcie(child));
/* Check downstream component if bit Slot Clock Configuration is 1 */
- cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ cpos = pci_pcie_cap(child);
pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_SLC))
same_clock = 0;
/* Check upstream component if bit Slot Clock Configuration is 1 */
- ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
+ ppos = pci_pcie_cap(parent);
pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, &reg16);
if (!(reg16 & PCI_EXP_LNKSTA_SLC))
same_clock = 0;
/* Configure downstream component, all functions */
list_for_each_entry(child, &linkbus->devices, bus_list) {
- cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ cpos = pci_pcie_cap(child);
pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, &reg16);
child_reg[PCI_FUNC(child->devfn)] = reg16;
if (same_clock)
@@ -247,7 +247,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
dev_printk(KERN_ERR, &parent->dev,
"ASPM: Could not configure common clock\n");
list_for_each_entry(child, &linkbus->devices, bus_list) {
- cpos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ cpos = pci_pcie_cap(child);
pci_write_config_word(child, cpos + PCI_EXP_LNKCTL,
child_reg[PCI_FUNC(child->devfn)]);
}
@@ -300,7 +300,7 @@ static void pcie_get_aspm_reg(struct pci_dev *pdev,
u16 reg16;
u32 reg32;
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, &reg32);
info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10;
info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12;
@@ -420,7 +420,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
child->pcie_type != PCI_EXP_TYPE_LEG_END)
continue;
- pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(child);
pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, &reg32);
/* Calculate endpoint L0s acceptable latency */
encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6;
@@ -436,7 +436,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val)
{
u16 reg16;
- int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ int pos = pci_pcie_cap(pdev);
pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
reg16 &= ~0x3;
@@ -503,7 +503,7 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
* very strange. Disable ASPM for the whole slot
*/
list_for_each_entry(child, &pdev->subordinate->devices, bus_list) {
- pos = pci_find_capability(child, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(child);
if (!pos)
return -EINVAL;
/*
@@ -563,7 +563,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
struct pcie_link_state *link;
int blacklist = !!pcie_aspm_sanity_check(pdev);
- if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
+ if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state)
return;
if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
@@ -629,7 +629,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link;
- if (aspm_disabled || !pdev->is_pcie || !parent || !parent->link_state)
+ if (aspm_disabled || !pci_is_pcie(pdev) ||
+ !parent || !parent->link_state)
return;
if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -670,7 +671,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
{
struct pcie_link_state *link = pdev->link_state;
- if (aspm_disabled || !pdev->is_pcie || !link)
+ if (aspm_disabled || !pci_is_pcie(pdev) || !link)
return;
if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -696,7 +697,7 @@ void pci_disable_link_state(struct pci_dev *pdev, int state)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;
- if (aspm_disabled || !pdev->is_pcie)
+ if (aspm_disabled || !pci_is_pcie(pdev))
return;
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
@@ -841,8 +842,9 @@ 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) || !link_state)
+ if (!pci_is_pcie(pdev) ||
+ (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
return;
if (link_state->aspm_support)
@@ -857,8 +859,9 @@ 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) || !link_state)
+ if (!pci_is_pcie(pdev) ||
+ (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
+ pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state)
return;
if (link_state->aspm_support)
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 17ad53868f9..aaeb9d21cba 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -11,31 +11,16 @@
#include <linux/compiler.h>
-#if !defined(PCI_CAP_ID_PME)
-#define PCI_CAP_ID_PME 1
-#endif
-
-#if !defined(PCI_CAP_ID_EXP)
-#define PCI_CAP_ID_EXP 0x10
-#endif
-
-#define PORT_TYPE_MASK 0xf
-#define PORT_TO_SLOT_MASK 0x100
-#define SLOT_HP_CAPABLE_MASK 0x40
-#define PCIE_CAPABILITIES_REG 0x2
-#define PCIE_SLOT_CAPABILITIES_REG 0x14
-#define PCIE_PORT_DEVICE_MAXSERVICES 4
-#define PCIE_PORT_MSI_VECTOR_MASK 0x1f
+#define PCIE_PORT_DEVICE_MAXSERVICES 4
/*
- * According to the PCI Express Base Specification 2.0, the indices of the MSI-X
- * table entires used by port services must not exceed 31
+ * According to the PCI Express Base Specification 2.0, the indices of
+ * the MSI-X table entires used by port services must not exceed 31
*/
#define PCIE_PORT_MAX_MSIX_ENTRIES 32
#define get_descriptor_id(type, service) (((type - 4) << 4) | service)
extern struct bus_type pcie_port_bus_type;
-extern int pcie_port_device_probe(struct pci_dev *dev);
extern int pcie_port_device_register(struct pci_dev *dev);
#ifdef CONFIG_PM
extern int pcie_port_device_suspend(struct device *dev);
diff --git a/drivers/pci/pcie/portdrv_bus.c b/drivers/pci/pcie/portdrv_bus.c
index ef3a4eeaebb..18bf90f748f 100644
--- a/drivers/pci/pcie/portdrv_bus.c
+++ b/drivers/pci/pcie/portdrv_bus.c
@@ -26,7 +26,6 @@ EXPORT_SYMBOL_GPL(pcie_port_bus_type);
static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
{
struct pcie_device *pciedev;
- struct pcie_port_data *port_data;
struct pcie_port_service_driver *driver;
if (drv->bus != &pcie_port_bus_type || dev->bus != &pcie_port_bus_type)
@@ -38,10 +37,8 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
if (driver->service != pciedev->service)
return 0;
- port_data = pci_get_drvdata(pciedev->port);
-
- if (driver->port_type != PCIE_ANY_PORT
- && driver->port_type != port_data->port_type)
+ if ((driver->port_type != PCIE_ANY_PORT) &&
+ (driver->port_type != pciedev->port->pcie_type))
return 0;
return 1;
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 52f84fca9f7..413262eb95b 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -108,9 +108,9 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
* the value in this field indicates which MSI-X Table entry is
* used to generate the interrupt message."
*/
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
- pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16);
- entry = (reg16 >> 9) & PCIE_PORT_MSI_VECTOR_MASK;
+ pos = pci_pcie_cap(dev);
+ pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
+ entry = (reg16 & PCI_EXP_FLAGS_IRQ) >> 9;
if (entry >= nr_entries)
goto Error;
@@ -177,37 +177,40 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
}
/**
- * assign_interrupt_mode - choose interrupt mode for PCI Express port services
- * (INTx, MSI-X, MSI) and set up vectors
+ * init_service_irqs - initialize irqs for PCI Express port services
* @dev: PCI Express port to handle
- * @vectors: Array of interrupt vectors to populate
+ * @irqs: Array of irqs to populate
* @mask: Bitmask of port capabilities returned by get_port_device_capability()
*
* Return value: Interrupt mode associated with the port
*/
-static int assign_interrupt_mode(struct pci_dev *dev, int *vectors, int mask)
+static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
{
- int irq, interrupt_mode = PCIE_PORT_NO_IRQ;
- int i;
+ int i, irq;
/* Try to use MSI-X if supported */
- if (!pcie_port_enable_msix(dev, vectors, mask))
- return PCIE_PORT_MSIX_MODE;
-
+ if (!pcie_port_enable_msix(dev, irqs, mask))
+ return 0;
/* We're not going to use MSI-X, so try MSI and fall back to INTx */
- if (!pci_enable_msi(dev))
- interrupt_mode = PCIE_PORT_MSI_MODE;
-
- if (interrupt_mode == PCIE_PORT_NO_IRQ && dev->pin)
- interrupt_mode = PCIE_PORT_INTx_MODE;
+ irq = -1;
+ if (!pci_enable_msi(dev) || dev->pin)
+ irq = dev->irq;
- irq = interrupt_mode != PCIE_PORT_NO_IRQ ? dev->irq : -1;
for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
- vectors[i] = irq;
+ irqs[i] = irq;
+ irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
- vectors[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
+ if (irq < 0)
+ return -ENODEV;
+ return 0;
+}
- return interrupt_mode;
+static void cleanup_service_irqs(struct pci_dev *dev)
+{
+ if (dev->msix_enabled)
+ pci_disable_msix(dev);
+ else if (dev->msi_enabled)
+ pci_disable_msi(dev);
}
/**
@@ -226,13 +229,12 @@ static int get_port_device_capability(struct pci_dev *dev)
u16 reg16;
u32 reg32;
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
- pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg16);
+ pos = pci_pcie_cap(dev);
+ pci_read_config_word(dev, pos + PCI_EXP_FLAGS, &reg16);
/* Hot-Plug Capable */
- if (reg16 & PORT_TO_SLOT_MASK) {
- pci_read_config_dword(dev,
- pos + PCIE_SLOT_CAPABILITIES_REG, &reg32);
- if (reg32 & SLOT_HP_CAPABLE_MASK)
+ if (reg16 & PCI_EXP_FLAGS_SLOT) {
+ pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
+ if (reg32 & PCI_EXP_SLTCAP_HPC)
services |= PCIE_PORT_SERVICE_HP;
}
/* AER capable */
@@ -241,80 +243,47 @@ static int get_port_device_capability(struct pci_dev *dev)
/* VC support */
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
services |= PCIE_PORT_SERVICE_VC;
+ /* Root ports are capable of generating PME too */
+ if (dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+ services |= PCIE_PORT_SERVICE_PME;
return services;
}
/**
- * pcie_device_init - initialize PCI Express port service device
- * @dev: Port service device to initialize
- * @parent: PCI Express port to associate the service device with
- * @port_type: Type of the port
- * @service_type: Type of service to associate with the service device
+ * pcie_device_init - allocate and initialize PCI Express port service device
+ * @pdev: PCI Express port to associate the service device with
+ * @service: Type of service to associate with the service device
* @irq: Interrupt vector to associate with the service device
*/
-static void pcie_device_init(struct pci_dev *parent, struct pcie_device *dev,
- int service_type, int irq)
+static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
{
- struct pcie_port_data *port_data = pci_get_drvdata(parent);
+ int retval;
+ struct pcie_device *pcie;
struct device *device;
- int port_type = port_data->port_type;
- dev->port = parent;
- dev->irq = irq;
- dev->service = service_type;
+ pcie = kzalloc(sizeof(*pcie), GFP_KERNEL);
+ if (!pcie)
+ return -ENOMEM;
+ pcie->port = pdev;
+ pcie->irq = irq;
+ pcie->service = service;
/* Initialize generic device interface */
- device = &dev->device;
- memset(device, 0, sizeof(struct device));
+ device = &pcie->device;
device->bus = &pcie_port_bus_type;
- device->driver = NULL;
- dev_set_drvdata(device, NULL);
device->release = release_pcie_device; /* callback to free pcie dev */
dev_set_name(device, "%s:pcie%02x",
- pci_name(parent), get_descriptor_id(port_type, service_type));
- device->parent = &parent->dev;
-}
-
-/**
- * alloc_pcie_device - allocate PCI Express port service device structure
- * @parent: PCI Express port to associate the service device with
- * @port_type: Type of the port
- * @service_type: Type of service to associate with the service device
- * @irq: Interrupt vector to associate with the service device
- */
-static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
- int service_type, int irq)
-{
- struct pcie_device *device;
-
- device = kzalloc(sizeof(struct pcie_device), GFP_KERNEL);
- if (!device)
- return NULL;
-
- pcie_device_init(parent, device, service_type, irq);
- return device;
-}
-
-/**
- * pcie_port_device_probe - check if device is a PCI Express port
- * @dev: Device to check
- */
-int pcie_port_device_probe(struct pci_dev *dev)
-{
- int pos, type;
- u16 reg;
-
- if (!(pos = pci_find_capability(dev, PCI_CAP_ID_EXP)))
- return -ENODEV;
-
- pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
- type = (reg >> 4) & PORT_TYPE_MASK;
- if ( type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
- type == PCIE_SW_DOWNSTREAM_PORT )
- return 0;
-
- return -ENODEV;
+ pci_name(pdev),
+ get_descriptor_id(pdev->pcie_type, service));
+ device->parent = &pdev->dev;
+
+ retval = device_register(device);
+ if (retval)
+ kfree(pcie);
+ else
+ get_device(device);
+ return retval;
}
/**
@@ -326,77 +295,49 @@ int pcie_port_device_probe(struct pci_dev *dev)
*/
int pcie_port_device_register(struct pci_dev *dev)
{
- struct pcie_port_data *port_data;
- int status, capabilities, irq_mode, i, nr_serv;
- int vectors[PCIE_PORT_DEVICE_MAXSERVICES];
- u16 reg16;
-
- port_data = kzalloc(sizeof(*port_data), GFP_KERNEL);
- if (!port_data)
- return -ENOMEM;
- pci_set_drvdata(dev, port_data);
-
- /* Get port type */
- pci_read_config_word(dev,
- pci_find_capability(dev, PCI_CAP_ID_EXP) +
- PCIE_CAPABILITIES_REG, &reg16);
- port_data->port_type = (reg16 >> 4) & PORT_TYPE_MASK;
+ int status, capabilities, i, nr_service;
+ int irqs[PCIE_PORT_DEVICE_MAXSERVICES];
+ /* Get and check PCI Express port services */
capabilities = get_port_device_capability(dev);
- /* Root ports are capable of generating PME too */
- if (port_data->port_type == PCIE_RC_PORT)
- capabilities |= PCIE_PORT_SERVICE_PME;
-
- irq_mode = assign_interrupt_mode(dev, vectors, capabilities);
- if (irq_mode == PCIE_PORT_NO_IRQ) {
- /*
- * Don't use service devices that require interrupts if there is
- * no way to generate them.
- */
- if (!(capabilities & PCIE_PORT_SERVICE_VC)) {
- status = -ENODEV;
- goto Error;
- }
- capabilities = PCIE_PORT_SERVICE_VC;
- }
- port_data->port_irq_mode = irq_mode;
+ if (!capabilities)
+ return -ENODEV;
+ /* Enable PCI Express port device */
status = pci_enable_device(dev);
if (status)
- goto Error;
+ return status;
pci_set_master(dev);
+ /*
+ * Initialize service irqs. Don't use service devices that
+ * require interrupts if there is no way to generate them.
+ */
+ status = init_service_irqs(dev, irqs, capabilities);
+ if (status) {
+ capabilities &= PCIE_PORT_SERVICE_VC;
+ if (!capabilities)
+ goto error_disable;
+ }
/* Allocate child services if any */
- for (i = 0, nr_serv = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
- struct pcie_device *child;
+ status = -ENODEV;
+ nr_service = 0;
+ for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++) {
int service = 1 << i;
-
if (!(capabilities & service))
continue;
-
- child = alloc_pcie_device(dev, service, vectors[i]);
- if (!child)
- continue;
-
- status = device_register(&child->device);
- if (status) {
- kfree(child);
- continue;
- }
-
- get_device(&child->device);
- nr_serv++;
- }
- if (!nr_serv) {
- pci_disable_device(dev);
- status = -ENODEV;
- goto Error;
+ if (!pcie_device_init(dev, service, irqs[i]))
+ nr_service++;
}
+ if (!nr_service)
+ goto error_cleanup_irqs;
return 0;
- Error:
- kfree(port_data);
+error_cleanup_irqs:
+ cleanup_service_irqs(dev);
+error_disable:
+ pci_disable_device(dev);
return status;
}
@@ -464,21 +405,9 @@ static int remove_iter(struct device *dev, void *data)
*/
void pcie_port_device_remove(struct pci_dev *dev)
{
- struct pcie_port_data *port_data = pci_get_drvdata(dev);
-
device_for_each_child(&dev->dev, NULL, remove_iter);
+ cleanup_service_irqs(dev);
pci_disable_device(dev);
-
- switch (port_data->port_irq_mode) {
- case PCIE_PORT_MSIX_MODE:
- pci_disable_msix(dev);
- break;
- case PCIE_PORT_MSI_MODE:
- pci_disable_msi(dev);
- break;
- }
-
- kfree(port_data);
}
/**
diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
index f635e476d63..ce52ea34fee 100644
--- a/drivers/pci/pcie/portdrv_pci.c
+++ b/drivers/pci/pcie/portdrv_pci.c
@@ -67,14 +67,16 @@ static struct dev_pm_ops pcie_portdrv_pm_ops = {
* this port device.
*
*/
-static int __devinit pcie_portdrv_probe (struct pci_dev *dev,
- const struct pci_device_id *id )
+static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
- int status;
+ int status;
- status = pcie_port_device_probe(dev);
- if (status)
- return status;
+ if (!pci_is_pcie(dev) ||
+ ((dev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
+ (dev->pcie_type != PCI_EXP_TYPE_UPSTREAM) &&
+ (dev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)))
+ return -ENODEV;
if (!dev->irq && dev->pin) {
dev_warn(&dev->dev, "device [%04x:%04x] has invalid IRQ; "
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 8105e32117f..98ffb2de22e 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/cpumask.h>
#include <linux/pci-aspm.h>
+#include <acpi/acpi_hest.h>
#include "pci.h"
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
@@ -163,12 +164,12 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
{
u32 l, sz, mask;
- mask = type ? ~PCI_ROM_ADDRESS_ENABLE : ~0;
+ mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
res->name = pci_name(dev);
pci_read_config_dword(dev, pos, &l);
- pci_write_config_dword(dev, pos, mask);
+ pci_write_config_dword(dev, pos, l | mask);
pci_read_config_dword(dev, pos, &sz);
pci_write_config_dword(dev, pos, l);
@@ -223,9 +224,13 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
goto fail;
if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
- dev_err(&dev->dev, "can't handle 64-bit BAR\n");
+ dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
+ pos);
goto fail;
- } else if ((sizeof(resource_size_t) < 8) && l) {
+ }
+
+ res->flags |= IORESOURCE_MEM_64;
+ if ((sizeof(resource_size_t) < 8) && l) {
/* Address above 32-bit boundary; disable the BAR */
pci_write_config_dword(dev, pos, 0);
pci_write_config_dword(dev, pos + 4, 0);
@@ -234,14 +239,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
} else {
res->start = l64;
res->end = l64 + sz64;
- dev_printk(KERN_DEBUG, &dev->dev,
- "reg %x %s: %pR\n", pos,
- (res->flags & IORESOURCE_PREFETCH) ?
- "64bit mmio pref" : "64bit mmio",
- res);
+ dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
+ pos, res);
}
-
- res->flags |= IORESOURCE_MEM_64;
} else {
sz = pci_size(l, sz, mask);
@@ -251,11 +251,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
res->start = l;
res->end = l + sz;
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x %s: %pR\n", pos,
- (res->flags & IORESOURCE_IO) ? "io port" :
- ((res->flags & IORESOURCE_PREFETCH) ?
- "32bit mmio pref" : "32bit mmio"),
- res);
+ dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
}
out:
@@ -297,8 +293,11 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
return;
+ dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n",
+ child->secondary, child->subordinate,
+ dev->transparent ? " (subtractive decode)": "");
+
if (dev->transparent) {
- dev_info(&dev->dev, "transparent bridge\n");
for(i = 3; i < PCI_BUS_NUM_RESOURCES; i++)
child->resource[i] = child->parent->resource[i - 3];
}
@@ -323,7 +322,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->start = base;
if (!res->end)
res->end = limit + 0xfff;
- dev_printk(KERN_DEBUG, &dev->dev, "bridge io port: %pR\n", res);
+ dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
res = child->resource[1];
@@ -335,8 +334,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
res->start = base;
res->end = limit + 0xfffff;
- dev_printk(KERN_DEBUG, &dev->dev, "bridge 32bit mmio: %pR\n",
- res);
+ dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
res = child->resource[2];
@@ -375,9 +373,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
res->flags |= IORESOURCE_MEM_64;
res->start = base;
res->end = limit + 0xfffff;
- dev_printk(KERN_DEBUG, &dev->dev, "bridge %sbit mmio pref: %pR\n",
- (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
- res);
+ dev_printk(KERN_DEBUG, &dev->dev, " bridge window %pR\n", res);
}
}
@@ -651,13 +647,14 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
(child->number > bus->subordinate) ||
(child->number < bus->number) ||
(child->subordinate < bus->number)) {
- pr_debug("PCI: Bus #%02x (-#%02x) is %s "
- "hidden behind%s bridge #%02x (-#%02x)\n",
+ dev_info(&child->dev, "[bus %02x-%02x] %s "
+ "hidden behind%s bridge %s [bus %02x-%02x]\n",
child->number, child->subordinate,
(bus->number > child->subordinate &&
bus->subordinate < child->number) ?
"wholly" : "partially",
bus->self->transparent ? " transparent" : "",
+ dev_name(&bus->dev),
bus->number, bus->subordinate);
}
bus = bus->parent;
@@ -693,6 +690,7 @@ static void set_pcie_port_type(struct pci_dev *pdev)
if (!pos)
return;
pdev->is_pcie = 1;
+ pdev->pcie_cap = pos;
pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4;
}
@@ -703,7 +701,7 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev)
u16 reg16;
u32 reg32;
- pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(pdev);
if (!pos)
return;
pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
@@ -714,6 +712,12 @@ static void set_pcie_hotplug_bridge(struct pci_dev *pdev)
pdev->is_hotplug_bridge = 1;
}
+static void set_pci_aer_firmware_first(struct pci_dev *pdev)
+{
+ if (acpi_hest_firmware_first_pci(pdev))
+ pdev->aer_firmware_first = 1;
+}
+
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
/**
@@ -731,6 +735,7 @@ int pci_setup_device(struct pci_dev *dev)
u32 class;
u8 hdr_type;
struct pci_slot *slot;
+ int pos = 0;
if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
return -EIO;
@@ -742,6 +747,7 @@ int pci_setup_device(struct pci_dev *dev)
dev->multifunction = !!(hdr_type & 0x80);
dev->error_state = pci_channel_io_normal;
set_pcie_port_type(dev);
+ set_pci_aer_firmware_first(dev);
list_for_each_entry(slot, &dev->bus->slots, list)
if (PCI_SLOT(dev->devfn) == slot->number)
@@ -822,6 +828,11 @@ int pci_setup_device(struct pci_dev *dev)
dev->transparent = ((dev->class & 0xff) == 1);
pci_read_bases(dev, 2, PCI_ROM_ADDRESS1);
set_pcie_hotplug_bridge(dev);
+ pos = pci_find_capability(dev, PCI_CAP_ID_SSVID);
+ if (pos) {
+ pci_read_config_word(dev, pos + PCI_SSVID_VENDOR_ID, &dev->subsystem_vendor);
+ pci_read_config_word(dev, pos + PCI_SSVID_DEVICE_ID, &dev->subsystem_device);
+ }
break;
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */
@@ -907,7 +918,7 @@ int pci_cfg_space_size(struct pci_dev *dev)
if (class == PCI_CLASS_BRIDGE_HOST)
return pci_cfg_space_size_ext(dev);
- pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+ pos = pci_pcie_cap(dev);
if (!pos) {
pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (!pos)
@@ -1014,6 +1025,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
/* Single Root I/O Virtualization */
pci_iov_init(dev);
+
+ /* Enable ACS P2P upstream forwarding */
+ pci_enable_acs(dev);
}
void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
@@ -1110,7 +1124,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
unsigned int devfn, pass, max = bus->secondary;
struct pci_dev *dev;
- pr_debug("PCI: Scanning bus %04x:%02x\n", pci_domain_nr(bus), bus->number);
+ dev_dbg(&bus->dev, "scanning bus\n");
/* Go find them, Rover! */
for (devfn = 0; devfn < 0x100; devfn += 8)
@@ -1124,8 +1138,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
* all PCI-to-PCI bridges on this bus.
*/
if (!bus->is_added) {
- pr_debug("PCI: Fixups for bus %04x:%02x\n",
- pci_domain_nr(bus), bus->number);
+ dev_dbg(&bus->dev, "fixups for bus\n");
pcibios_fixup_bus(bus);
if (pci_is_root_bus(bus))
bus->is_added = 1;
@@ -1145,8 +1158,7 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
*
* Return how far we've got finding sub-buses.
*/
- pr_debug("PCI: Bus scan for %04x:%02x returning with max=%02x\n",
- pci_domain_nr(bus), bus->number, max);
+ dev_dbg(&bus->dev, "bus scan returning with max=%02x\n", max);
return max;
}
@@ -1154,7 +1166,7 @@ struct pci_bus * pci_create_bus(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
{
int error;
- struct pci_bus *b;
+ struct pci_bus *b, *b2;
struct device *dev;
b = pci_alloc_bus();
@@ -1170,9 +1182,10 @@ struct pci_bus * pci_create_bus(struct device *parent,
b->sysdata = sysdata;
b->ops = ops;
- if (pci_find_bus(pci_domain_nr(b), bus)) {
+ b2 = pci_find_bus(pci_domain_nr(b), bus);
+ if (b2) {
/* If we already got to this bus through a different bridge, ignore it */
- pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);
+ dev_dbg(&b2->dev, "bus already known\n");
goto err_out;
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 245d2cdb476..7cfa7c38d31 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -357,7 +357,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);
- dev_info(&dev->dev, "quirk: region %04x-%04x claimed by %s\n", region, region + size - 1, name);
+ dev_info(&dev->dev, "quirk: %pR claimed by %s\n", res, name);
}
}
@@ -1680,6 +1680,7 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_
*/
#define AMD_813X_MISC 0x40
#define AMD_813X_NOIOAMODE (1<<0)
+#define AMD_813X_REV_B1 0x12
#define AMD_813X_REV_B2 0x13
static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
@@ -1688,7 +1689,8 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
if (noioapicquirk)
return;
- if (dev->revision == AMD_813X_REV_B2)
+ if ((dev->revision == AMD_813X_REV_B1) ||
+ (dev->revision == AMD_813X_REV_B2))
return;
pci_read_config_dword(dev, AMD_813X_MISC, &pci_config_dword);
@@ -1698,8 +1700,10 @@ static void quirk_disable_amd_813x_boot_interrupt(struct pci_dev *dev)
dev_info(&dev->dev, "disabled boot interrupts on device [%04x:%04x]\n",
dev->vendor, dev->device);
}
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
-DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, quirk_disable_amd_813x_boot_interrupt);
#define AMD_8111_PCI_IRQ_ROUTING 0x56
@@ -2595,9 +2599,37 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
static int __init pci_apply_final_quirks(void)
{
struct pci_dev *dev = NULL;
+ u8 cls = 0;
+ u8 tmp;
+
+ if (pci_cache_line_size)
+ printk(KERN_DEBUG "PCI: CLS %u bytes\n",
+ pci_cache_line_size << 2);
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
pci_fixup_device(pci_fixup_final, dev);
+ /*
+ * If arch hasn't set it explicitly yet, use the CLS
+ * value shared by all PCI devices. If there's a
+ * mismatch, fall back to the default value.
+ */
+ if (!pci_cache_line_size) {
+ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp);
+ if (!cls)
+ cls = tmp;
+ if (!tmp || cls == tmp)
+ continue;
+
+ printk(KERN_DEBUG "PCI: CLS mismatch (%u != %u), "
+ "using %u bytes\n", cls << 2, tmp << 2,
+ pci_dfl_cache_line_size << 2);
+ pci_cache_line_size = pci_dfl_cache_line_size;
+ }
+ }
+ if (!pci_cache_line_size) {
+ printk(KERN_DEBUG "PCI: CLS %u bytes, default %u\n",
+ cls << 2, pci_dfl_cache_line_size << 2);
+ pci_cache_line_size = cls;
}
return 0;
diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index ec415352d9b..6dae8714325 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -26,14 +26,14 @@ pci_find_upstream_pcie_bridge(struct pci_dev *pdev)
{
struct pci_dev *tmp = NULL;
- if (pdev->is_pcie)
+ if (pci_is_pcie(pdev))
return NULL;
while (1) {
if (pci_is_root_bus(pdev->bus))
break;
pdev = pdev->bus->self;
/* a p2p bridge */
- if (!pdev->is_pcie) {
+ if (!pci_is_pcie(pdev)) {
tmp = pdev;
continue;
}
@@ -149,32 +149,33 @@ struct pci_dev * pci_get_slot(struct pci_bus *bus, unsigned int devfn)
}
/**
- * pci_get_bus_and_slot - locate PCI device from a given PCI bus & slot
- * @bus: number of PCI bus on which desired PCI device resides
- * @devfn: encodes number of PCI slot in which the desired PCI
- * device resides and the logical device number within that slot
- * in case of multi-function devices.
- *
- * Note: the bus/slot search is limited to PCI domain (segment) 0.
+ * pci_get_domain_bus_and_slot - locate PCI device for a given PCI domain (segment), bus, and slot
+ * @domain: PCI domain/segment on which the PCI device resides.
+ * @bus: PCI bus on which desired PCI device resides
+ * @devfn: encodes number of PCI slot in which the desired PCI device
+ * resides and the logical device number within that slot in case of
+ * multi-function devices.
*
- * Given a PCI bus and slot/function number, the desired PCI device
- * is located in system global list of PCI devices. If the device
- * is found, a pointer to its data structure is returned. If no
- * device is found, %NULL is returned. The returned device has its
- * reference count bumped by one.
+ * Given a PCI domain, bus, and slot/function number, the desired PCI
+ * device is located in the list of PCI devices. If the device is
+ * found, its reference count is increased and this function returns a
+ * pointer to its data structure. The caller must decrement the
+ * reference count by calling pci_dev_put(). If no device is found,
+ * %NULL is returned.
*/
-
-struct pci_dev * pci_get_bus_and_slot(unsigned int bus, unsigned int devfn)
+struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
+ unsigned int devfn)
{
struct pci_dev *dev = NULL;
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
- if (pci_domain_nr(dev->bus) == 0 &&
- (dev->bus->number == bus && dev->devfn == devfn))
+ if (pci_domain_nr(dev->bus) == domain &&
+ (dev->bus->number == bus && dev->devfn == devfn))
return dev;
}
return NULL;
}
+EXPORT_SYMBOL(pci_get_domain_bus_and_slot);
static int match_pci_dev_by_id(struct device *dev, void *data)
{
@@ -354,5 +355,4 @@ EXPORT_SYMBOL(pci_find_next_bus);
EXPORT_SYMBOL(pci_get_device);
EXPORT_SYMBOL(pci_get_subsys);
EXPORT_SYMBOL(pci_get_slot);
-EXPORT_SYMBOL(pci_get_bus_and_slot);
EXPORT_SYMBOL(pci_get_class);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index cb1a027eb55..c48cd377b3f 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -71,53 +71,50 @@ static void pbus_assign_resources_sorted(const struct pci_bus *bus)
void pci_setup_cardbus(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
+ struct resource *res;
struct pci_bus_region region;
- dev_info(&bridge->dev, "CardBus bridge, secondary bus %04x:%02x\n",
- pci_domain_nr(bus), bus->number);
+ dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n",
+ bus->secondary, bus->subordinate);
- pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
- if (bus->resource[0]->flags & IORESOURCE_IO) {
+ res = bus->resource[0];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_IO) {
/*
* The IO resource is allocated a range twice as large as it
* would normally need. This allows us to set both IO regs.
*/
- dev_info(&bridge->dev, " IO window: %#08lx-%#08lx\n",
- (unsigned long)region.start,
- (unsigned long)region.end);
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
region.end);
}
- pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
- if (bus->resource[1]->flags & IORESOURCE_IO) {
- dev_info(&bridge->dev, " IO window: %#08lx-%#08lx\n",
- (unsigned long)region.start,
- (unsigned long)region.end);
+ res = bus->resource[1];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_IO) {
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
region.start);
pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
region.end);
}
- pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
- if (bus->resource[2]->flags & IORESOURCE_MEM) {
- dev_info(&bridge->dev, " PREFETCH window: %#08lx-%#08lx\n",
- (unsigned long)region.start,
- (unsigned long)region.end);
+ res = bus->resource[2];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_MEM) {
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
region.end);
}
- pcibios_resource_to_bus(bridge, &region, bus->resource[3]);
- if (bus->resource[3]->flags & IORESOURCE_MEM) {
- dev_info(&bridge->dev, " MEM window: %#08lx-%#08lx\n",
- (unsigned long)region.start,
- (unsigned long)region.end);
+ res = bus->resource[3];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_MEM) {
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
region.start);
pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
@@ -140,34 +137,33 @@ EXPORT_SYMBOL(pci_setup_cardbus);
static void pci_setup_bridge(struct pci_bus *bus)
{
struct pci_dev *bridge = bus->self;
+ struct resource *res;
struct pci_bus_region region;
u32 l, bu, lu, io_upper16;
- int pref_mem64;
if (pci_is_enabled(bridge))
return;
- dev_info(&bridge->dev, "PCI bridge, secondary bus %04x:%02x\n",
- pci_domain_nr(bus), bus->number);
+ dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n",
+ bus->secondary, bus->subordinate);
/* Set up the top and bottom of the PCI I/O segment for this bus. */
- pcibios_resource_to_bus(bridge, &region, bus->resource[0]);
- if (bus->resource[0]->flags & IORESOURCE_IO) {
+ res = bus->resource[0];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_IO) {
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
l &= 0xffff0000;
l |= (region.start >> 8) & 0x00f0;
l |= region.end & 0xf000;
/* Set up upper 16 bits of I/O base/limit. */
io_upper16 = (region.end & 0xffff0000) | (region.start >> 16);
- dev_info(&bridge->dev, " IO window: %#04lx-%#04lx\n",
- (unsigned long)region.start,
- (unsigned long)region.end);
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
}
else {
/* Clear upper 16 bits of I/O base/limit. */
io_upper16 = 0;
l = 0x00f0;
- dev_info(&bridge->dev, " IO window: disabled\n");
+ dev_info(&bridge->dev, " bridge window [io disabled]\n");
}
/* Temporarily disable the I/O range before updating PCI_IO_BASE. */
pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0x0000ffff);
@@ -178,17 +174,16 @@ static void pci_setup_bridge(struct pci_bus *bus)
/* Set up the top and bottom of the PCI Memory segment
for this bus. */
- pcibios_resource_to_bus(bridge, &region, bus->resource[1]);
- if (bus->resource[1]->flags & IORESOURCE_MEM) {
+ res = bus->resource[1];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_MEM) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- dev_info(&bridge->dev, " MEM window: %#08lx-%#08lx\n",
- (unsigned long)region.start,
- (unsigned long)region.end);
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
}
else {
l = 0x0000fff0;
- dev_info(&bridge->dev, " MEM window: disabled\n");
+ dev_info(&bridge->dev, " bridge window [mem disabled]\n");
}
pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);
@@ -198,34 +193,27 @@ static void pci_setup_bridge(struct pci_bus *bus)
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */
- pref_mem64 = 0;
bu = lu = 0;
- pcibios_resource_to_bus(bridge, &region, bus->resource[2]);
- if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
- int width = 8;
+ res = bus->resource[2];
+ pcibios_resource_to_bus(bridge, &region, res);
+ if (res->flags & IORESOURCE_PREFETCH) {
l = (region.start >> 16) & 0xfff0;
l |= region.end & 0xfff00000;
- if (bus->resource[2]->flags & IORESOURCE_MEM_64) {
- pref_mem64 = 1;
+ if (res->flags & IORESOURCE_MEM_64) {
bu = upper_32_bits(region.start);
lu = upper_32_bits(region.end);
- width = 16;
}
- dev_info(&bridge->dev, " PREFETCH window: %#0*llx-%#0*llx\n",
- width, (unsigned long long)region.start,
- width, (unsigned long long)region.end);
+ dev_info(&bridge->dev, " bridge window %pR\n", res);
}
else {
l = 0x0000fff0;
- dev_info(&bridge->dev, " PREFETCH window: disabled\n");
+ dev_info(&bridge->dev, " bridge window [mem pref disabled]\n");
}
pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
- if (pref_mem64) {
- /* 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);
- }
+ /* 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);
}
@@ -345,6 +333,10 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
#endif
size = ALIGN(size + size1, 4096);
if (!size) {
+ if (b_res->start || b_res->end)
+ dev_info(&bus->self->dev, "disabling bridge window "
+ "%pR to [bus %02x-%02x] (unused)\n", b_res,
+ bus->secondary, bus->subordinate);
b_res->flags = 0;
return;
}
@@ -390,8 +382,9 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
align = pci_resource_alignment(dev, r);
order = __ffs(align) - 20;
if (order > 11) {
- dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
- "%pR\n", i, (unsigned long long)align, r);
+ dev_warn(&dev->dev, "disabling BAR %d: %pR "
+ "(bad alignment %#llx)\n", i, r,
+ (unsigned long long) align);
r->flags = 0;
continue;
}
@@ -425,6 +418,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
}
size = ALIGN(size, min_align);
if (!size) {
+ if (b_res->start || b_res->end)
+ dev_info(&bus->self->dev, "disabling bridge window "
+ "%pR to [bus %02x-%02x] (unused)\n", b_res,
+ bus->secondary, bus->subordinate);
b_res->flags = 0;
return 1;
}
@@ -582,10 +579,7 @@ static void pci_bus_dump_res(struct pci_bus *bus)
if (!res || !res->end)
continue;
- dev_printk(KERN_DEBUG, &bus->dev, "resource %d %s %pR\n", i,
- (res->flags & IORESOURCE_IO) ? "io: " :
- ((res->flags & IORESOURCE_PREFETCH)? "pref mem":"mem:"),
- res);
+ dev_printk(KERN_DEBUG, &bus->dev, "resource %d %pR\n", i, res);
}
}
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index c54526b206b..7d678bb15ff 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -51,12 +51,6 @@ void pci_update_resource(struct pci_dev *dev, int resno)
pcibios_resource_to_bus(dev, &region, res);
- dev_dbg(&dev->dev, "BAR %d: got res %pR bus [%#llx-%#llx] "
- "flags %#lx\n", resno, res,
- (unsigned long long)region.start,
- (unsigned long long)region.end,
- (unsigned long)res->flags);
-
new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
if (res->flags & IORESOURCE_IO)
mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
@@ -91,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
}
}
res->flags &= ~IORESOURCE_UNSET;
- dev_dbg(&dev->dev, "BAR %d: moved to bus [%#llx-%#llx] flags %#lx\n",
- resno, (unsigned long long)region.start,
- (unsigned long long)region.end, res->flags);
+ dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx]\n",
+ resno, res, (unsigned long long)region.start,
+ (unsigned long long)region.end);
}
int pci_claim_resource(struct pci_dev *dev, int resource)
@@ -103,20 +97,17 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
int err;
root = pci_find_parent_resource(dev, res);
-
- err = -EINVAL;
- if (root != NULL)
- err = request_resource(root, res);
-
- if (err) {
- const char *dtype = resource < PCI_BRIDGE_RESOURCES ? "device" : "bridge";
- dev_err(&dev->dev, "BAR %d: %s of %s %pR\n",
- resource,
- root ? "address space collision on" :
- "no parent found for",
- dtype, res);
+ if (!root) {
+ dev_err(&dev->dev, "no compatible bridge window for %pR\n",
+ res);
+ return -EINVAL;
}
+ err = request_resource(root, res);
+ if (err)
+ dev_err(&dev->dev,
+ "address space collision: %pR already in use\n", res);
+
return err;
}
EXPORT_SYMBOL(pci_claim_resource);
@@ -124,7 +115,7 @@ EXPORT_SYMBOL(pci_claim_resource);
#ifdef CONFIG_PCI_QUIRKS
void pci_disable_bridge_window(struct pci_dev *dev)
{
- dev_dbg(&dev->dev, "Disabling bridge window.\n");
+ dev_info(&dev->dev, "disabling bridge mem windows\n");
/* MMIO Base/Limit */
pci_write_config_dword(dev, PCI_MEMORY_BASE, 0x0000fff0);
@@ -165,6 +156,7 @@ static int __pci_assign_resource(struct pci_bus *bus, struct pci_dev *dev,
if (!ret) {
res->flags &= ~IORESOURCE_STARTALIGN;
+ dev_info(&dev->dev, "BAR %d: assigned %pR\n", resno, res);
if (resno < PCI_BRIDGE_RESOURCES)
pci_update_resource(dev, resno);
}
@@ -178,12 +170,12 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
resource_size_t align;
struct pci_bus *bus;
int ret;
+ char *type;
align = pci_resource_alignment(dev, res);
if (!align) {
- dev_info(&dev->dev, "BAR %d: can't allocate resource (bogus "
- "alignment) %pR flags %#lx\n",
- resno, res, res->flags);
+ dev_info(&dev->dev, "BAR %d: can't assign %pR "
+ "(bogus alignment)\n", resno, res);
return -EINVAL;
}
@@ -198,9 +190,20 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
break;
}
- if (ret)
- dev_info(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
- resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
+ if (ret) {
+ if (res->flags & IORESOURCE_MEM)
+ if (res->flags & IORESOURCE_PREFETCH)
+ type = "mem pref";
+ else
+ type = "mem";
+ else if (res->flags & IORESOURCE_IO)
+ type = "io";
+ else
+ type = "unknown";
+ dev_info(&dev->dev,
+ "BAR %d: can't assign %s (size %#llx)\n",
+ resno, type, (unsigned long long) resource_size(res));
+ }
return ret;
}
@@ -225,9 +228,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
r_align = pci_resource_alignment(dev, r);
if (!r_align) {
- dev_warn(&dev->dev, "BAR %d: bogus alignment "
- "%pR flags %#lx\n",
- i, r, r->flags);
+ dev_warn(&dev->dev, "BAR %d: %pR has bogus alignment\n",
+ i, r);
continue;
}
for (list = head; ; list = list->next) {
@@ -274,8 +276,8 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
continue;
if (!r->parent) {
- dev_err(&dev->dev, "device not available because of "
- "BAR %d %pR collisions\n", i, r);
+ dev_err(&dev->dev, "device not available "
+ "(can't reserve %pR)\n", r);
return -EINVAL;
}