aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/pci_root.c101
-rw-r--r--drivers/ata/ahci.c1
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c3
-rw-r--r--drivers/iommu/irq_remapping.c12
-rw-r--r--drivers/pci/ioapic.c13
-rw-r--r--drivers/pci/iov.c5
-rw-r--r--drivers/pci/msi.c10
-rw-r--r--drivers/pci/pci-acpi.c4
-rw-r--r--drivers/pci/pci-sysfs.c48
-rw-r--r--drivers/pci/pci.c2
-rw-r--r--drivers/pci/pcie/aspm.c29
-rw-r--r--drivers/pci/probe.c31
-rw-r--r--drivers/pci/quirks.c27
14 files changed, 175 insertions, 112 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 1dd6f6c85874..122b4dc7b0fa 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -65,10 +65,6 @@ static struct acpi_scan_handler pci_root_handler = {
.detach = acpi_pci_root_remove,
};
-/* Lock to protect both acpi_pci_roots lists */
-static DEFINE_MUTEX(acpi_pci_root_lock);
-static LIST_HEAD(acpi_pci_roots);
-
static DEFINE_MUTEX(osc_lock);
/**
@@ -100,13 +96,12 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
{
struct resource *res = data;
struct acpi_resource_address64 address;
+ acpi_status status;
- if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
- resource->type != ACPI_RESOURCE_TYPE_ADDRESS32 &&
- resource->type != ACPI_RESOURCE_TYPE_ADDRESS64)
+ status = acpi_resource_to_address64(resource, &address);
+ if (ACPI_FAILURE(status))
return AE_OK;
- acpi_resource_to_address64(resource, &address);
if ((address.address_length > 0) &&
(address.resource_type == ACPI_BUS_NUMBER_RANGE)) {
res->start = address.minimum;
@@ -382,23 +377,24 @@ static int acpi_pci_root_add(struct acpi_device *device,
int result;
struct acpi_pci_root *root;
u32 flags, base_flags;
+ acpi_handle handle = device->handle;
root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
if (!root)
return -ENOMEM;
segment = 0;
- status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL,
+ status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL,
&segment);
if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
- printk(KERN_ERR PREFIX "can't evaluate _SEG\n");
+ dev_err(&device->dev, "can't evaluate _SEG\n");
result = -ENODEV;
goto end;
}
/* Check _CRS first, then _BBN. If no _BBN, default to zero. */
root->secondary.flags = IORESOURCE_BUS;
- status = try_get_root_bridge_busnr(device->handle, &root->secondary);
+ status = try_get_root_bridge_busnr(handle, &root->secondary);
if (ACPI_FAILURE(status)) {
/*
* We need both the start and end of the downstream bus range
@@ -407,33 +403,32 @@ static int acpi_pci_root_add(struct acpi_device *device,
* can do is assume [_BBN-0xFF] or [0-0xFF].
*/
root->secondary.end = 0xFF;
- printk(KERN_WARNING FW_BUG PREFIX
- "no secondary bus range in _CRS\n");
- status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN,
+ dev_warn(&device->dev,
+ FW_BUG "no secondary bus range in _CRS\n");
+ status = acpi_evaluate_integer(handle, METHOD_NAME__BBN,
NULL, &bus);
if (ACPI_SUCCESS(status))
root->secondary.start = bus;
else if (status == AE_NOT_FOUND)
root->secondary.start = 0;
else {
- printk(KERN_ERR PREFIX "can't evaluate _BBN\n");
+ dev_err(&device->dev, "can't evaluate _BBN\n");
result = -ENODEV;
goto end;
}
}
- INIT_LIST_HEAD(&root->node);
root->device = device;
root->segment = segment & 0xFFFF;
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS);
device->driver_data = root;
- printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n",
+ pr_info(PREFIX "%s [%s] (domain %04x %pR)\n",
acpi_device_name(device), acpi_device_bid(device),
root->segment, &root->secondary);
- root->mcfg_addr = acpi_pci_root_get_mcfg_addr(device->handle);
+ root->mcfg_addr = acpi_pci_root_get_mcfg_addr(handle);
/*
* All supported architectures that use ACPI have support for
@@ -446,10 +441,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
* TBD: Need PCI interface for enumeration/configuration of roots.
*/
- mutex_lock(&acpi_pci_root_lock);
- list_add_tail(&root->node, &acpi_pci_roots);
- mutex_unlock(&acpi_pci_root_lock);
-
/*
* Scan the Root Bridge
* --------------------
@@ -459,11 +450,11 @@ static int acpi_pci_root_add(struct acpi_device *device,
*/
root->bus = pci_acpi_scan_root(root);
if (!root->bus) {
- printk(KERN_ERR PREFIX
- "Bus %04x:%02x not present in PCI namespace\n",
- root->segment, (unsigned int)root->secondary.start);
+ dev_err(&device->dev,
+ "Bus %04x:%02x not present in PCI namespace\n",
+ root->segment, (unsigned int)root->secondary.start);
result = -ENODEV;
- goto out_del_root;
+ goto end;
}
/* Indicate support for various _OSC capabilities. */
@@ -502,7 +493,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
dev_info(&device->dev,
"Requesting ACPI _OSC control (0x%02x)\n", flags);
- status = acpi_pci_osc_control_set(device->handle, &flags,
+ status = acpi_pci_osc_control_set(handle, &flags,
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
if (ACPI_SUCCESS(status)) {
dev_info(&device->dev,
@@ -519,8 +510,8 @@ static int acpi_pci_root_add(struct acpi_device *device,
"ACPI _OSC request failed (%s), "
"returned control mask: 0x%02x\n",
acpi_format_exception(status), flags);
- pr_info("ACPI _OSC control for PCIe not granted, "
- "disabling ASPM\n");
+ dev_info(&device->dev,
+ "ACPI _OSC control for PCIe not granted, disabling ASPM\n");
pcie_no_aspm();
}
} else {
@@ -536,20 +527,14 @@ static int acpi_pci_root_add(struct acpi_device *device,
if (system_state != SYSTEM_BOOTING) {
pcibios_resource_survey_bus(root->bus);
pci_assign_unassigned_bus_resources(root->bus);
- }
- /* need to after hot-added ioapic is registered */
- if (system_state != SYSTEM_BOOTING)
+ /* need to after hot-added ioapic is registered */
pci_enable_bridges(root->bus);
+ }
pci_bus_add_devices(root->bus);
return 1;
-out_del_root:
- mutex_lock(&acpi_pci_root_lock);
- list_del(&root->node);
- mutex_unlock(&acpi_pci_root_lock);
-
end:
kfree(root);
return result;
@@ -566,9 +551,6 @@ static void acpi_pci_root_remove(struct acpi_device *device)
pci_remove_root_bus(root->bus);
- mutex_lock(&acpi_pci_root_lock);
- list_del(&root->node);
- mutex_unlock(&acpi_pci_root_lock);
kfree(root);
}
@@ -588,12 +570,13 @@ static void handle_root_bridge_insertion(acpi_handle handle)
struct acpi_device *device;
if (!acpi_bus_get_device(handle, &device)) {
- printk(KERN_DEBUG "acpi device exists...\n");
+ dev_printk(KERN_DEBUG, &device->dev,
+ "acpi device already exists; ignoring notify\n");
return;
}
if (acpi_bus_scan(handle))
- printk(KERN_ERR "cannot add bridge to acpi list\n");
+ acpi_handle_err(handle, "cannot add bridge to acpi list\n");
}
static void handle_root_bridge_removal(struct acpi_device *device)
@@ -622,7 +605,6 @@ static void handle_root_bridge_removal(struct acpi_device *device)
static void _handle_hotplug_event_root(struct work_struct *work)
{
struct acpi_pci_root *root;
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER };
struct acpi_hp_work *hp_work;
acpi_handle handle;
u32 type;
@@ -634,13 +616,12 @@ static void _handle_hotplug_event_root(struct work_struct *work)
acpi_scan_lock_acquire();
root = acpi_pci_find_root(handle);
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
/* bus enumerate */
- printk(KERN_DEBUG "%s: Bus check notify on %s\n", __func__,
- (char *)buffer.pointer);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "Bus check notify on %s\n", __func__);
if (!root)
handle_root_bridge_insertion(handle);
@@ -648,28 +629,28 @@ static void _handle_hotplug_event_root(struct work_struct *work)
case ACPI_NOTIFY_DEVICE_CHECK:
/* device check */
- printk(KERN_DEBUG "%s: Device check notify on %s\n", __func__,
- (char *)buffer.pointer);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "Device check notify on %s\n", __func__);
if (!root)
handle_root_bridge_insertion(handle);
break;
case ACPI_NOTIFY_EJECT_REQUEST:
/* request device eject */
- printk(KERN_DEBUG "%s: Device eject notify on %s\n", __func__,
- (char *)buffer.pointer);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "Device eject notify on %s\n", __func__);
if (root)
handle_root_bridge_removal(root->device);
break;
default:
- printk(KERN_WARNING "notify_handler: unknown event type 0x%x for %s\n",
- type, (char *)buffer.pointer);
+ acpi_handle_warn(handle,
+ "notify_handler: unknown event type 0x%x\n",
+ type);
break;
}
acpi_scan_lock_release();
kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
- kfree(buffer.pointer);
}
static void handle_hotplug_event_root(acpi_handle handle, u32 type,
@@ -683,9 +664,6 @@ static acpi_status __init
find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
{
acpi_status status;
- char objname[64];
- struct acpi_buffer buffer = { .length = sizeof(objname),
- .pointer = objname };
int *count = (int *)context;
if (!acpi_is_root_bridge(handle))
@@ -693,16 +671,15 @@ find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
(*count)++;
- acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
-
status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
handle_hotplug_event_root, NULL);
if (ACPI_FAILURE(status))
- printk(KERN_DEBUG "acpi root: %s notify handler is not installed, exit status: %u\n",
- objname, (unsigned int)status);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "notify handler is not installed, exit status: %u\n",
+ (unsigned int)status);
else
- printk(KERN_DEBUG "acpi root: %s notify handler is installed\n",
- objname);
+ acpi_handle_printk(KERN_DEBUG, handle,
+ "notify handler is installed\n");
return AE_OK;
}
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 251e57d38942..98496600a15a 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -310,6 +310,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
/* AMD */
{ PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
+ { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */
/* AMD is using RAID class only for ahci controllers */
{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 631736e2e7ed..4faf02b3657d 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -150,6 +150,7 @@ config I2C_PIIX4
ATI SB700/SP5100
ATI SB800
AMD Hudson-2
+ AMD CZ
Serverworks OSB4
Serverworks CSB5
Serverworks CSB6
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 39ab78c1a02c..d05ad590af29 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -22,7 +22,7 @@
Intel PIIX4, 440MX
Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
ATI IXP200, IXP300, IXP400, SB600, SB700/SP5100, SB800
- AMD Hudson-2
+ AMD Hudson-2, CZ
SMSC Victory66
Note: we assume there can only be one device, with one or more
@@ -522,6 +522,7 @@ static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) },
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x790b) },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
PCI_DEVICE_ID_SERVERWORKS_OSB4) },
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index dcfea4e39be7..39f81aeefcd6 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -51,26 +51,27 @@ static void irq_remapping_disable_io_apic(void)
static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
{
- int node, ret, sub_handle, index = 0;
+ int node, ret, sub_handle, nvec_pow2, index = 0;
unsigned int irq;
struct msi_desc *msidesc;
- nvec = __roundup_pow_of_two(nvec);
-
WARN_ON(!list_is_singular(&dev->msi_list));
msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
WARN_ON(msidesc->irq);
WARN_ON(msidesc->msi_attrib.multiple);
+ WARN_ON(msidesc->nvec_used);
node = dev_to_node(&dev->dev);
irq = __create_irqs(get_nr_irqs_gsi(), nvec, node);
if (irq == 0)
return -ENOSPC;
- msidesc->msi_attrib.multiple = ilog2(nvec);
+ nvec_pow2 = __roundup_pow_of_two(nvec);
+ msidesc->nvec_used = nvec;
+ msidesc->msi_attrib.multiple = ilog2(nvec_pow2);
for (sub_handle = 0; sub_handle < nvec; sub_handle++) {
if (!sub_handle) {
- index = msi_alloc_remapped_irq(dev, irq, nvec);
+ index = msi_alloc_remapped_irq(dev, irq, nvec_pow2);
if (index < 0) {
ret = index;
goto error;
@@ -95,6 +96,7 @@ error:
* IRQs from tearing down again in default_teardown_msi_irqs()
*/
msidesc->irq = 0;
+ msidesc->nvec_used = 0;
msidesc->msi_attrib.multiple = 0;
return ret;
diff --git a/drivers/pci/ioapic.c b/drivers/pci/ioapic.c
index 3c6bbdd059a4..1b90579b233a 100644
--- a/drivers/pci/ioapic.c
+++ b/drivers/pci/ioapic.c
@@ -113,17 +113,6 @@ static struct pci_driver ioapic_driver = {
.remove = 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);
+module_pci_driver(ioapic_driver);
MODULE_LICENSE("GPL");
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index c93071d428f5..a971a6f6268d 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -92,6 +92,8 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
pci_read_config_word(dev, iov->pos + PCI_SRIOV_VF_DID, &virtfn->device);
pci_setup_device(virtfn);
virtfn->dev.parent = dev->dev.parent;
+ virtfn->physfn = pci_dev_get(dev);
+ virtfn->is_virtfn = 1;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
res = dev->resource + PCI_IOV_RESOURCES + i;
@@ -113,9 +115,6 @@ static int virtfn_add(struct pci_dev *dev, int id, int reset)
pci_device_add(virtfn, virtfn->bus);
mutex_unlock(&iov->dev->sriov->lock);
- virtfn->physfn = pci_dev_get(dev);
- virtfn->is_virtfn = 1;
-
rc = pci_bus_add_device(virtfn);
sprintf(buf, "virtfn%u", id);
rc = sysfs_create_link(&dev->dev.kobj, &virtfn->dev.kobj, buf);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 2c1075213bec..aca7578b05e5 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -81,7 +81,10 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
int i, nvec;
if (entry->irq == 0)
continue;
- nvec = 1 << entry->msi_attrib.multiple;
+ if (entry->nvec_used)
+ nvec = entry->nvec_used;
+ else
+ nvec = 1 << entry->msi_attrib.multiple;
for (i = 0; i < nvec; i++)
arch_teardown_msi_irq(entry->irq + i);
}
@@ -336,7 +339,10 @@ static void free_msi_irqs(struct pci_dev *dev)
int i, nvec;
if (!entry->irq)
continue;
- nvec = 1 << entry->msi_attrib.multiple;
+ if (entry->nvec_used)
+ nvec = entry->nvec_used;
+ else
+ nvec = 1 << entry->msi_attrib.multiple;
#ifdef CONFIG_GENERIC_HARDIRQS
for (i = 0; i < nvec; i++)
BUG_ON(irq_has_action(entry->irq + i));
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index e4b1fb2c0f5d..6c15d6a96935 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -376,12 +376,12 @@ static int __init acpi_pci_init(void)
int ret;
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) {
- printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
+ pr_info("ACPI FADT declares the system doesn't support MSI, so disable it\n");
pci_no_msi();
}
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
- printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
+ pr_info("ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
pcie_no_aspm();
}
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 5b4a9d9cd200..c0dbe1f61362 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -66,7 +66,7 @@ static ssize_t broken_parity_status_store(struct device *dev,
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
pdev->broken_parity_status = !!val;
@@ -188,7 +188,7 @@ static ssize_t is_enabled_store(struct device *dev,
{
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- ssize_t result = strict_strtoul(buf, 0, &val);
+ ssize_t result = kstrtoul(buf, 0, &val);
if (result < 0)
return result;
@@ -259,7 +259,7 @@ msi_bus_store(struct device *dev, struct device_attribute *attr,
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
/* bad things may happen if the no_msi flag is changed
@@ -291,7 +291,7 @@ static ssize_t bus_rescan_store(struct bus_type *bus, const char *buf,
unsigned long val;
struct pci_bus *b = NULL;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val) {
@@ -315,7 +315,7 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr,
unsigned long val;
struct pci_dev *pdev = to_pci_dev(dev);
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val) {
@@ -325,6 +325,8 @@ dev_rescan_store(struct device *dev, struct device_attribute *attr,
}
return count;
}
+struct device_attribute dev_rescan_attr = __ATTR(rescan, (S_IWUSR|S_IWGRP),
+ NULL, dev_rescan_store);
static void remove_callback(struct device *dev)
{
@@ -342,7 +344,7 @@ remove_store(struct device *dev, struct device_attribute *dummy,
int ret = 0;
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
/* An attribute cannot be unregistered by one of its own methods,
@@ -354,6 +356,8 @@ remove_store(struct device *dev, struct device_attribute *dummy,
count = ret;
return count;
}
+struct device_attribute dev_remove_attr = __ATTR(remove, (S_IWUSR|S_IWGRP),
+ NULL, remove_store);
static ssize_t
dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
@@ -362,7 +366,7 @@ dev_bus_rescan_store(struct device *dev, struct device_attribute *attr,
unsigned long val;
struct pci_bus *bus = to_pci_bus(dev);
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
if (val) {
@@ -384,7 +388,7 @@ static ssize_t d3cold_allowed_store(struct device *dev,
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- if (strict_strtoul(buf, 0, &val) < 0)
+ if (kstrtoul(buf, 0, &val) < 0)
return -EINVAL;
pdev->d3cold_allowed = !!val;
@@ -504,8 +508,6 @@ struct device_attribute pci_dev_attrs[] = {
__ATTR(broken_parity_status,(S_IRUGO|S_IWUSR),
broken_parity_status_show,broken_parity_status_store),
__ATTR(msi_bus, 0644, msi_bus_show, msi_bus_store),
- __ATTR(remove, (S_IWUSR|S_IWGRP), NULL, remove_store),
- __ATTR(rescan, (S_IWUSR|S_IWGRP), NULL, dev_rescan_store),
#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_ACPI)
__ATTR(d3cold_allowed, 0644, d3cold_allowed_show, d3cold_allowed_store),
#endif
@@ -1236,7 +1238,7 @@ static ssize_t reset_store(struct device *dev,
{
struct pci_dev *pdev = to_pci_dev(dev);
unsigned long val;
- ssize_t result = strict_strtoul(buf, 0, &val);
+ ssize_t result = kstrtoul(buf, 0, &val);
if (result < 0)
return result;
@@ -1463,6 +1465,29 @@ static umode_t pci_dev_attrs_are_visible(struct kobject *kobj,
return a->mode;
}
+static struct attribute *pci_dev_hp_attrs[] = {
+ &dev_remove_attr.attr,
+ &dev_rescan_attr.attr,
+ NULL,
+};
+
+static umode_t pci_dev_hp_attrs_are_visible(struct kobject *kobj,
+ struct attribute *a, int n)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ if (pdev->is_virtfn)
+ return 0;
+
+ return a->mode;
+}
+
+static struct attribute_group pci_dev_hp_attr_group = {
+ .attrs = pci_dev_hp_attrs,
+ .is_visible = pci_dev_hp_attrs_are_visible,
+};
+
#ifdef CONFIG_PCI_IOV
static struct attribute *sriov_dev_attrs[] = {
&sriov_totalvfs_attr.attr,
@@ -1494,6 +1519,7 @@ static struct attribute_group pci_dev_attr_group = {
static const struct attribute_group *pci_dev_attr_groups[] = {
&pci_dev_attr_group,
+ &pci_dev_hp_attr_group,
#ifdef CONFIG_PCI_IOV
&sriov_dev_attr_group,
#endif
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index a899d8bb190d..e5f4e55d407d 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -2421,7 +2421,7 @@ bool pci_acs_path_enabled(struct pci_dev *start,
/**
* pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
* @dev: the PCI device
- * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTD, 4=INTD)
+ * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
*
* Perform INTx swizzling for a device behind one level of bridge. This is
* required by section 9.1 of the PCI-to-PCI bridge specification for devices
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index d320df6375a2..403a44374ed5 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -714,19 +714,12 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
up_read(&pci_bus_sem);
}
-/*
- * pci_disable_link_state - disable pci device's link state, so the link will
- * never enter specific states
- */
static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
bool force)
{
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;
- if (aspm_disabled && !force)
- return;
-
if (!pci_is_pcie(pdev))
return;
@@ -736,6 +729,19 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
if (!parent || !parent->link_state)
return;
+ /*
+ * A driver requested that ASPM be disabled on this device, but
+ * if we don't have permission to manage ASPM (e.g., on ACPI
+ * systems we have to observe the FADT ACPI_FADT_NO_ASPM bit and
+ * the _OSC method), we can't honor that request. Windows has
+ * a similar mechanism using "PciASPMOptOut", which is also
+ * ignored in this situation.
+ */
+ if (aspm_disabled && !force) {
+ dev_warn(&pdev->dev, "can't disable ASPM; OS doesn't have ASPM control\n");
+ return;
+ }
+
if (sem)
down_read(&pci_bus_sem);
mutex_lock(&aspm_lock);
@@ -761,6 +767,15 @@ void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
}
EXPORT_SYMBOL(pci_disable_link_state_locked);
+/**
+ * pci_disable_link_state - Disable device's link state, so the link will
+ * never enter specific states. Note that if the BIOS didn't grant ASPM
+ * control to the OS, this does nothing because we can't touch the LNKCTL
+ * register.
+ *
+ * @pdev: PCI device
+ * @state: ASPM link state to disable
+ */
void pci_disable_link_state(struct pci_dev *pdev, int state)
{
__pci_disable_link_state(pdev, state, true, false);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 70f10fa3c1b2..fe5b50bd7536 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -170,7 +170,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
{
u32 l, sz, mask;
u16 orig_cmd;
- struct pci_bus_region region;
+ struct pci_bus_region region, inverted_region;
bool bar_too_big = false, bar_disabled = false;
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
@@ -250,12 +250,10 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
pci_write_config_dword(dev, pos + 4, 0);
region.start = 0;
region.end = sz64;
- pcibios_bus_to_resource(dev, res, &region);
bar_disabled = true;
} else {
region.start = l64;
region.end = l64 + sz64;
- pcibios_bus_to_resource(dev, res, &region);
}
} else {
sz = pci_size(l, sz, mask);
@@ -265,7 +263,28 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
region.start = l;
region.end = l + sz;
- pcibios_bus_to_resource(dev, res, &region);
+ }
+
+ pcibios_bus_to_resource(dev, res, &region);
+ pcibios_resource_to_bus(dev, &inverted_region, res);
+
+ /*
+ * If "A" is a BAR value (a bus address), "bus_to_resource(A)" is
+ * the corresponding resource address (the physical address used by
+ * the CPU. Converting that resource address back to a bus address
+ * should yield the original BAR value:
+ *
+ * resource_to_bus(bus_to_resource(A)) == A
+ *
+ * If it doesn't, CPU accesses to "bus_to_resource(A)" will not
+ * be claimed by the device.
+ */
+ if (inverted_region.start != region.start) {
+ dev_info(&dev->dev, "reg 0x%x: initial BAR value %pa invalid; forcing reassignment\n",
+ pos, &region.start);
+ res->flags |= IORESOURCE_UNSET;
+ res->end -= res->start;
+ res->start = 0;
}
goto out;
@@ -278,9 +297,9 @@ out:
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
if (bar_too_big)
- dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+ dev_err(&dev->dev, "reg 0x%x: can't handle 64-bit BAR\n", pos);
if (res->flags && !bar_disabled)
- dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+ dev_printk(KERN_DEBUG, &dev->dev, "reg 0x%x: %pR\n", pos, res);
return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 7d68aeebf56b..c3a04026cca8 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1022,6 +1022,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x7900, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, 0x7900, quirk_amd_ide_mode);
/*
* Serverworks CSB5 IDE does not fully support native mode
@@ -2865,6 +2867,31 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65f9, quirk_intel_mc_errata);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x65fa, quirk_intel_mc_errata);
+/*
+ * Ivytown NTB BAR sizes are misreported by the hardware due to an erratum. To
+ * work around this, query the size it should be configured to by the device and
+ * modify the resource end to correspond to this new size.
+ */
+static void quirk_intel_ntb(struct pci_dev *dev)
+{
+ int rc;
+ u8 val;
+
+ rc = pci_read_config_byte(dev, 0x00D0, &val);
+ if (rc)
+ return;
+
+ dev->resource[2].end = dev->resource[2].start + ((u64) 1 << val) - 1;
+
+ rc = pci_read_config_byte(dev, 0x00D1, &val);
+ if (rc)
+ return;
+
+ dev->resource[4].end = dev->resource[4].start + ((u64) 1 << val) - 1;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e08, quirk_intel_ntb);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0e0d, quirk_intel_ntb);
+
static ktime_t fixup_debug_start(struct pci_dev *dev,
void (*fn)(struct pci_dev *dev))
{