Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (109 commits)
  PCI: fix coding style issue in pci_save_state()
  PCI: add pci_request_acs
  PCI: fix BUG_ON triggered by logical PCIe root port removal
  PCI: remove ifdefed pci_cleanup_aer_correct_error_status
  PCI: unconditionally clear AER uncorr status register during cleanup
  x86/PCI: claim SR-IOV BARs in pcibios_allocate_resource
  PCI: portdrv: remove redundant definitions
  PCI: portdrv: remove unnecessary struct pcie_port_data
  PCI: portdrv: minor cleanup for pcie_port_device_register
  PCI: portdrv: add missing irq cleanup
  PCI: portdrv: enable device before irq initialization
  PCI: portdrv: cleanup service irqs initialization
  PCI: portdrv: check capabilities first
  PCI: portdrv: move PME capability check
  PCI: portdrv: remove redundant pcie type calculation
  PCI: portdrv: cleanup pcie_device registration
  PCI: portdrv: remove redundant pcie_port_device_probe
  PCI: Always set prefetchable base/limit upper32 registers
  PCI: read-modify-write the pcie device control register when initiating pcie flr
  PCI: show dma_mask bits in /sys
  ...

Fixed up conflicts in:
	arch/x86/kernel/amd_iommu_init.c
	drivers/pci/dmar.c
	drivers/pci/hotplug/acpiphp_glue.c
This commit is contained in:
Linus Torvalds 2009-12-11 12:18:16 -08:00
commit 11bd04f6f3
83 changed files with 1787 additions and 1564 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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:

View file

@ -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"

View file

@ -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"
@ -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;
}
@ -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);
@ -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, 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, 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;
}
@ -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,

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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;
}

View file

@ -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;

View file

@ -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 */

View file

@ -520,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;
@ -528,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 */

127
drivers/pci/ioapic.c Normal file
View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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';
@ -175,6 +183,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)
{
@ -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),

View file

@ -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.

View file

@ -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 */

View file

@ -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);
}

View file

@ -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);

View file

@ -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;
@ -76,28 +82,6 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev)
EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
{
int pos;
u32 status, mask;
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);
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;
@ -106,20 +90,21 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
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);
pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
if (status)
pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
return 0;
}
#endif /* 0 */
EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
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;
}

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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;

View file

@ -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;
irq = -1;
if (!pci_enable_msi(dev) || dev->pin)
irq = dev->irq;
if (interrupt_mode == PCIE_PORT_NO_IRQ && dev->pin)
interrupt_mode = PCIE_PORT_INTx_MODE;
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;
}
pci_name(pdev),
get_descriptor_id(pdev->pcie_type, service));
device->parent = &pdev->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;
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);
}
/**

View file

@ -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; "

View file

@ -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;
}

View file

@ -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;

View file

@ -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.
* 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.
*
* Note: the bus/slot search is limited to PCI domain (segment) 0.
*
* 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);

View file

@ -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);
}
}

View file

@ -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;
}