mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
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: (30 commits)
PCI: update for owner removal from struct device_attribute
PCI: Fix warnings when CONFIG_DMI unset
PCI: Do not run NVidia quirks related to MSI with MSI disabled
x86/PCI: use for_each_pci_dev()
PCI: use for_each_pci_dev()
PCI: MSI: Restore read_msi_msg_desc(); add get_cached_msi_msg_desc()
PCI: export SMBIOS provided firmware instance and label to sysfs
PCI: Allow read/write access to sysfs I/O port resources
x86/PCI: use host bridge _CRS info on ASRock ALiveSATA2-GLAN
PCI: remove unused HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_{SIZE|BOUNDARY}
PCI: disable mmio during bar sizing
PCI: MSI: Remove unsafe and unnecessary hardware access
PCI: Default PCIe ASPM control to on and require !EMBEDDED to disable
PCI: kernel oops on access to pci proc file while hot-removal
PCI: pci-sysfs: remove casts from void*
ACPI: Disable ASPM if the platform won't provide _OSC control for PCIe
PCI hotplug: make sure child bridges are enabled at hotplug time
PCI hotplug: shpchp: Removed check for hotplug of display devices
PCI hotplug: pciehp: Fixed return value sign for pciehp_unconfigure_device
PCI: Don't enable aspm before drivers have had a chance to veto it
...
This commit is contained in:
commit
1cfd2bda8c
39 changed files with 517 additions and 94 deletions
|
|
@ -55,6 +55,9 @@ obj-$(CONFIG_MICROBLAZE) += setup-bus.o
|
|||
#
|
||||
obj-$(CONFIG_ACPI) += pci-acpi.o
|
||||
|
||||
# SMBIOS provided firmware instance and labels
|
||||
obj-$(CONFIG_DMI) += pci-label.o
|
||||
|
||||
# Cardbus & CompactPCI use setup-bus
|
||||
obj-$(CONFIG_HOTPLUG) += setup-bus.o
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ void pci_bus_remove_resources(struct pci_bus *bus)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
|
||||
bus->resource[i] = 0;
|
||||
bus->resource[i] = NULL;
|
||||
|
||||
list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
|
||||
list_del(&bus_res->list);
|
||||
|
|
@ -240,6 +240,8 @@ void pci_enable_bridges(struct pci_bus *bus)
|
|||
if (dev->subordinate) {
|
||||
if (!pci_is_enabled(dev)) {
|
||||
retval = pci_enable_device(dev);
|
||||
if (retval)
|
||||
dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval);
|
||||
pci_set_master(dev);
|
||||
}
|
||||
pci_enable_bridges(dev->subordinate);
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static int __init init_legacy(void)
|
|||
struct pci_dev *pdev = NULL;
|
||||
|
||||
/* Add existing devices */
|
||||
while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)))
|
||||
for_each_pci_dev(pdev)
|
||||
legacy_add_slot(pdev);
|
||||
|
||||
/* Be alerted of any new ones */
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ int pciehp_unconfigure_device(struct slot *p_slot)
|
|||
"Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
rc = EINVAL;
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@
|
|||
#define CON_PFAULT_INTR_MASK (1 << 28)
|
||||
#define MRL_CHANGE_SERR_MASK (1 << 29)
|
||||
#define CON_PFAULT_SERR_MASK (1 << 30)
|
||||
#define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21)
|
||||
#define SLOT_REG_RSVDZ_MASK ((1 << 15) | (7 << 21))
|
||||
|
||||
/*
|
||||
* SHPC Command Code definitnions
|
||||
|
|
|
|||
|
|
@ -60,12 +60,6 @@ int __ref shpchp_configure_device(struct slot *p_slot)
|
|||
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
|
||||
if (!dev)
|
||||
continue;
|
||||
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
ctrl_err(ctrl, "Cannot hot-add display device %s\n",
|
||||
pci_name(dev));
|
||||
pci_dev_put(dev);
|
||||
continue;
|
||||
}
|
||||
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
|
||||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
|
||||
/* Find an unused bus number for the new bridge */
|
||||
|
|
@ -114,17 +108,11 @@ int shpchp_unconfigure_device(struct slot *p_slot)
|
|||
ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
|
||||
__func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
|
||||
|
||||
for (j=0; j<8 ; j++) {
|
||||
struct pci_dev* temp = pci_get_slot(parent,
|
||||
for (j = 0; j < 8 ; j++) {
|
||||
struct pci_dev *temp = pci_get_slot(parent,
|
||||
(p_slot->device << 3) | j);
|
||||
if (!temp)
|
||||
continue;
|
||||
if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
|
||||
ctrl_err(ctrl, "Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
}
|
||||
if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
|
||||
if (bctl & PCI_BRIDGE_CTL_VGA) {
|
||||
|
|
@ -132,7 +120,8 @@ int shpchp_unconfigure_device(struct slot *p_slot)
|
|||
"Cannot remove display device %s\n",
|
||||
pci_name(temp));
|
||||
pci_dev_put(temp);
|
||||
continue;
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pci_remove_bus_device(temp);
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ void unmask_msi_irq(unsigned int irq)
|
|||
void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
|
||||
{
|
||||
struct msi_desc *entry = get_irq_desc_msi(desc);
|
||||
|
||||
BUG_ON(entry->dev->current_state != PCI_D0);
|
||||
|
||||
if (entry->msi_attrib.is_msix) {
|
||||
void __iomem *base = entry->mask_base +
|
||||
entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
|
||||
|
|
@ -229,10 +232,32 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg)
|
|||
read_msi_msg_desc(desc, msg);
|
||||
}
|
||||
|
||||
void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
|
||||
{
|
||||
struct msi_desc *entry = get_irq_desc_msi(desc);
|
||||
|
||||
/* Assert that the cache is valid, assuming that
|
||||
* valid messages are not all-zeroes. */
|
||||
BUG_ON(!(entry->msg.address_hi | entry->msg.address_lo |
|
||||
entry->msg.data));
|
||||
|
||||
*msg = entry->msg;
|
||||
}
|
||||
|
||||
void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||
{
|
||||
struct irq_desc *desc = irq_to_desc(irq);
|
||||
|
||||
get_cached_msi_msg_desc(desc, msg);
|
||||
}
|
||||
|
||||
void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg)
|
||||
{
|
||||
struct msi_desc *entry = get_irq_desc_msi(desc);
|
||||
if (entry->msi_attrib.is_msix) {
|
||||
|
||||
if (entry->dev->current_state != PCI_D0) {
|
||||
/* Don't touch the hardware now */
|
||||
} else if (entry->msi_attrib.is_msix) {
|
||||
void __iomem *base;
|
||||
base = entry->mask_base +
|
||||
entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE;
|
||||
|
|
@ -435,7 +460,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
|
|||
static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos,
|
||||
unsigned nr_entries)
|
||||
{
|
||||
unsigned long phys_addr;
|
||||
resource_size_t phys_addr;
|
||||
u32 table_offset;
|
||||
u8 bir;
|
||||
|
||||
|
|
|
|||
|
|
@ -289,8 +289,26 @@ struct drv_dev_and_id {
|
|||
static long local_pci_probe(void *_ddi)
|
||||
{
|
||||
struct drv_dev_and_id *ddi = _ddi;
|
||||
struct device *dev = &ddi->dev->dev;
|
||||
int rc;
|
||||
|
||||
return ddi->drv->probe(ddi->dev, ddi->id);
|
||||
/* Unbound PCI devices are always set to disabled and suspended.
|
||||
* During probe, the device is set to enabled and active and the
|
||||
* usage count is incremented. If the driver supports runtime PM,
|
||||
* it should call pm_runtime_put_noidle() in its probe routine and
|
||||
* pm_runtime_get_noresume() in its remove routine.
|
||||
*/
|
||||
pm_runtime_get_noresume(dev);
|
||||
pm_runtime_set_active(dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
rc = ddi->drv->probe(ddi->dev, ddi->id);
|
||||
if (rc) {
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int pci_call_probe(struct pci_driver *drv, struct pci_dev *dev,
|
||||
|
|
@ -369,11 +387,19 @@ static int pci_device_remove(struct device * dev)
|
|||
struct pci_driver * drv = pci_dev->driver;
|
||||
|
||||
if (drv) {
|
||||
if (drv->remove)
|
||||
if (drv->remove) {
|
||||
pm_runtime_get_sync(dev);
|
||||
drv->remove(pci_dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
}
|
||||
pci_dev->driver = NULL;
|
||||
}
|
||||
|
||||
/* Undo the runtime PM settings in local_pci_probe() */
|
||||
pm_runtime_disable(dev);
|
||||
pm_runtime_set_suspended(dev);
|
||||
pm_runtime_put_noidle(dev);
|
||||
|
||||
/*
|
||||
* If the device is still on, set the power state as "unknown",
|
||||
* since it might change by the next time we load the driver.
|
||||
|
|
|
|||
143
drivers/pci/pci-label.c
Normal file
143
drivers/pci/pci-label.c
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
* Purpose: Export the firmware instance and label associated with
|
||||
* a pci device to sysfs
|
||||
* Copyright (C) 2010 Dell Inc.
|
||||
* by Narendra K <Narendra_K@dell.com>,
|
||||
* Jordan Hargrave <Jordan_Hargrave@dell.com>
|
||||
*
|
||||
* SMBIOS defines type 41 for onboard pci devices. This code retrieves
|
||||
* the instance number and string from the type 41 record and exports
|
||||
* it to sysfs.
|
||||
*
|
||||
* Please see http://linux.dell.com/wiki/index.php/Oss/libnetdevname for more
|
||||
* information.
|
||||
*/
|
||||
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci_ids.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include "pci.h"
|
||||
|
||||
enum smbios_attr_enum {
|
||||
SMBIOS_ATTR_NONE = 0,
|
||||
SMBIOS_ATTR_LABEL_SHOW,
|
||||
SMBIOS_ATTR_INSTANCE_SHOW,
|
||||
};
|
||||
|
||||
static mode_t
|
||||
find_smbios_instance_string(struct pci_dev *pdev, char *buf,
|
||||
enum smbios_attr_enum attribute)
|
||||
{
|
||||
const struct dmi_device *dmi;
|
||||
struct dmi_dev_onboard *donboard;
|
||||
int bus;
|
||||
int devfn;
|
||||
|
||||
bus = pdev->bus->number;
|
||||
devfn = pdev->devfn;
|
||||
|
||||
dmi = NULL;
|
||||
while ((dmi = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD,
|
||||
NULL, dmi)) != NULL) {
|
||||
donboard = dmi->device_data;
|
||||
if (donboard && donboard->bus == bus &&
|
||||
donboard->devfn == devfn) {
|
||||
if (buf) {
|
||||
if (attribute == SMBIOS_ATTR_INSTANCE_SHOW)
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"%d\n",
|
||||
donboard->instance);
|
||||
else if (attribute == SMBIOS_ATTR_LABEL_SHOW)
|
||||
return scnprintf(buf, PAGE_SIZE,
|
||||
"%s\n",
|
||||
dmi->name);
|
||||
}
|
||||
return strlen(dmi->name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mode_t
|
||||
smbios_instance_string_exist(struct kobject *kobj, struct attribute *attr,
|
||||
int n)
|
||||
{
|
||||
struct device *dev;
|
||||
struct pci_dev *pdev;
|
||||
|
||||
dev = container_of(kobj, struct device, kobj);
|
||||
pdev = to_pci_dev(dev);
|
||||
|
||||
return find_smbios_instance_string(pdev, NULL, SMBIOS_ATTR_NONE) ?
|
||||
S_IRUGO : 0;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
smbioslabel_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
pdev = to_pci_dev(dev);
|
||||
|
||||
return find_smbios_instance_string(pdev, buf,
|
||||
SMBIOS_ATTR_LABEL_SHOW);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
smbiosinstance_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct pci_dev *pdev;
|
||||
pdev = to_pci_dev(dev);
|
||||
|
||||
return find_smbios_instance_string(pdev, buf,
|
||||
SMBIOS_ATTR_INSTANCE_SHOW);
|
||||
}
|
||||
|
||||
static struct device_attribute smbios_attr_label = {
|
||||
.attr = {.name = "label", .mode = 0444},
|
||||
.show = smbioslabel_show,
|
||||
};
|
||||
|
||||
static struct device_attribute smbios_attr_instance = {
|
||||
.attr = {.name = "index", .mode = 0444},
|
||||
.show = smbiosinstance_show,
|
||||
};
|
||||
|
||||
static struct attribute *smbios_attributes[] = {
|
||||
&smbios_attr_label.attr,
|
||||
&smbios_attr_instance.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group smbios_attr_group = {
|
||||
.attrs = smbios_attributes,
|
||||
.is_visible = smbios_instance_string_exist,
|
||||
};
|
||||
|
||||
static int
|
||||
pci_create_smbiosname_file(struct pci_dev *pdev)
|
||||
{
|
||||
if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group))
|
||||
return 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void
|
||||
pci_remove_smbiosname_file(struct pci_dev *pdev)
|
||||
{
|
||||
sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);
|
||||
}
|
||||
|
||||
void pci_create_firmware_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
if (!pci_create_smbiosname_file(pdev))
|
||||
;
|
||||
}
|
||||
|
||||
void pci_remove_firmware_label_files(struct pci_dev *pdev)
|
||||
{
|
||||
pci_remove_smbiosname_file(pdev);
|
||||
}
|
||||
|
|
@ -734,7 +734,7 @@ pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
|
|||
{
|
||||
struct pci_dev *pdev = to_pci_dev(container_of(kobj,
|
||||
struct device, kobj));
|
||||
struct resource *res = (struct resource *)attr->private;
|
||||
struct resource *res = attr->private;
|
||||
enum pci_mmap_state mmap_type;
|
||||
resource_size_t start, end;
|
||||
int i;
|
||||
|
|
@ -778,6 +778,70 @@ pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
|
|||
return pci_mmap_resource(kobj, attr, vma, 1);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
pci_resource_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count, bool write)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(container_of(kobj,
|
||||
struct device, kobj));
|
||||
struct resource *res = attr->private;
|
||||
unsigned long port = off;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PCI_ROM_RESOURCE; i++)
|
||||
if (res == &pdev->resource[i])
|
||||
break;
|
||||
if (i >= PCI_ROM_RESOURCE)
|
||||
return -ENODEV;
|
||||
|
||||
port += pci_resource_start(pdev, i);
|
||||
|
||||
if (port > pci_resource_end(pdev, i))
|
||||
return 0;
|
||||
|
||||
if (port + count - 1 > pci_resource_end(pdev, i))
|
||||
return -EINVAL;
|
||||
|
||||
switch (count) {
|
||||
case 1:
|
||||
if (write)
|
||||
outb(*(u8 *)buf, port);
|
||||
else
|
||||
*(u8 *)buf = inb(port);
|
||||
return 1;
|
||||
case 2:
|
||||
if (write)
|
||||
outw(*(u16 *)buf, port);
|
||||
else
|
||||
*(u16 *)buf = inw(port);
|
||||
return 2;
|
||||
case 4:
|
||||
if (write)
|
||||
outl(*(u32 *)buf, port);
|
||||
else
|
||||
*(u32 *)buf = inl(port);
|
||||
return 4;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
pci_read_resource_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pci_resource_io(filp, kobj, attr, buf, off, count, false);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
pci_write_resource_io(struct file *filp, struct kobject *kobj,
|
||||
struct bin_attribute *attr, char *buf,
|
||||
loff_t off, size_t count)
|
||||
{
|
||||
return pci_resource_io(filp, kobj, attr, buf, off, count, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_remove_resource_files - cleanup resource files
|
||||
* @pdev: dev to cleanup
|
||||
|
|
@ -828,6 +892,10 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
|
|||
sprintf(res_attr_name, "resource%d", num);
|
||||
res_attr->mmap = pci_mmap_resource_uc;
|
||||
}
|
||||
if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
|
||||
res_attr->read = pci_read_resource_io;
|
||||
res_attr->write = pci_write_resource_io;
|
||||
}
|
||||
res_attr->attr.name = res_attr_name;
|
||||
res_attr->attr.mode = S_IRUSR | S_IWUSR;
|
||||
res_attr->size = pci_resource_len(pdev, num);
|
||||
|
|
@ -1097,6 +1165,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
|
|||
if (retval)
|
||||
goto err_vga_file;
|
||||
|
||||
pci_create_firmware_label_files(pdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_vga_file:
|
||||
|
|
@ -1164,6 +1234,9 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
|
|||
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
|
||||
kfree(pdev->rom_attr);
|
||||
}
|
||||
|
||||
pci_remove_firmware_label_files(pdev);
|
||||
|
||||
}
|
||||
|
||||
static int __init pci_sysfs_init(void)
|
||||
|
|
|
|||
|
|
@ -2312,21 +2312,17 @@ void pci_msi_off(struct pci_dev *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pci_msi_off);
|
||||
|
||||
#ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE
|
||||
int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size)
|
||||
{
|
||||
return dma_set_max_seg_size(&dev->dev, size);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_set_dma_max_seg_size);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ARCH_PCI_SET_DMA_SEGMENT_BOUNDARY
|
||||
int pci_set_dma_seg_boundary(struct pci_dev *dev, unsigned long mask)
|
||||
{
|
||||
return dma_set_seg_boundary(&dev->dev, mask);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_set_dma_seg_boundary);
|
||||
#endif
|
||||
|
||||
static int pcie_flr(struct pci_dev *dev, int probe)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -11,6 +11,15 @@
|
|||
extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
|
||||
extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
|
||||
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
|
||||
#ifndef CONFIG_DMI
|
||||
static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
|
||||
{ return; }
|
||||
static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
|
||||
{ return; }
|
||||
#else
|
||||
extern void pci_create_firmware_label_files(struct pci_dev *pdev);
|
||||
extern void pci_remove_firmware_label_files(struct pci_dev *pdev);
|
||||
#endif
|
||||
extern void pci_cleanup_rom(struct pci_dev *dev);
|
||||
#ifdef HAVE_PCI_MMAP
|
||||
extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
|
||||
|
|
|
|||
|
|
@ -31,14 +31,22 @@ source "drivers/pci/pcie/aer/Kconfig"
|
|||
# PCI Express ASPM
|
||||
#
|
||||
config PCIEASPM
|
||||
bool "PCI Express ASPM support(Experimental)"
|
||||
depends on PCI && EXPERIMENTAL && PCIEPORTBUS
|
||||
default n
|
||||
bool "PCI Express ASPM control" if EMBEDDED
|
||||
depends on PCI && PCIEPORTBUS
|
||||
default y
|
||||
help
|
||||
This enables PCI Express ASPM (Active State Power Management) and
|
||||
Clock Power Management. ASPM supports state L0/L0s/L1.
|
||||
This enables OS control over PCI Express ASPM (Active State
|
||||
Power Management) and Clock Power Management. ASPM supports
|
||||
state L0/L0s/L1.
|
||||
|
||||
When in doubt, say N.
|
||||
ASPM is initially set up the the firmware. With this option enabled,
|
||||
Linux can modify this state in order to disable ASPM on known-bad
|
||||
hardware or configurations and enable it when known-safe.
|
||||
|
||||
ASPM can be disabled or enabled at runtime via
|
||||
/sys/module/pcie_aspm/parameters/policy
|
||||
|
||||
When in doubt, say Y.
|
||||
config PCIEASPM_DEBUG
|
||||
bool "Debug PCI Express ASPM"
|
||||
depends on PCIEASPM
|
||||
|
|
|
|||
|
|
@ -727,20 +727,21 @@ static void aer_isr_one_error(struct pcie_device *p_device,
|
|||
static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
|
||||
{
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
/* Lock access to Root error producer/consumer index */
|
||||
spin_lock_irqsave(&rpc->e_lock, flags);
|
||||
if (rpc->prod_idx != rpc->cons_idx) {
|
||||
*e_src = rpc->e_sources[rpc->cons_idx];
|
||||
rpc->cons_idx++;
|
||||
if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
|
||||
rpc->cons_idx = 0;
|
||||
ret = 1;
|
||||
if (rpc->prod_idx == rpc->cons_idx) {
|
||||
spin_unlock_irqrestore(&rpc->e_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*e_src = rpc->e_sources[rpc->cons_idx];
|
||||
rpc->cons_idx++;
|
||||
if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
|
||||
rpc->cons_idx = 0;
|
||||
spin_unlock_irqrestore(&rpc->e_lock, flags);
|
||||
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -588,11 +588,23 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
|
|||
* update through pcie_aspm_cap_init().
|
||||
*/
|
||||
pcie_aspm_cap_init(link, blacklist);
|
||||
pcie_config_aspm_path(link);
|
||||
|
||||
/* Setup initial Clock PM state */
|
||||
pcie_clkpm_cap_init(link, blacklist);
|
||||
pcie_set_clkpm(link, policy_to_clkpm_state(link));
|
||||
|
||||
/*
|
||||
* At this stage drivers haven't had an opportunity to change the
|
||||
* link policy setting. Enabling ASPM on broken hardware can cripple
|
||||
* it even before the driver has had a chance to disable ASPM, so
|
||||
* default to a safe level right now. If we're enabling ASPM beyond
|
||||
* the BIOS's expectation, we'll do so once pci_enable_device() is
|
||||
* called.
|
||||
*/
|
||||
if (aspm_policy != POLICY_POWERSAVE) {
|
||||
pcie_config_aspm_path(link);
|
||||
pcie_set_clkpm(link, policy_to_clkpm_state(link));
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&aspm_lock);
|
||||
out:
|
||||
|
|
|
|||
|
|
@ -163,9 +163,16 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
struct resource *res, unsigned int pos)
|
||||
{
|
||||
u32 l, sz, mask;
|
||||
u16 orig_cmd;
|
||||
|
||||
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
|
||||
|
||||
if (!dev->mmio_always_on) {
|
||||
pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
|
||||
pci_write_config_word(dev, PCI_COMMAND,
|
||||
orig_cmd & ~(PCI_COMMAND_MEMORY | PCI_COMMAND_IO));
|
||||
}
|
||||
|
||||
res->name = pci_name(dev);
|
||||
|
||||
pci_read_config_dword(dev, pos, &l);
|
||||
|
|
@ -173,6 +180,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
|
|||
pci_read_config_dword(dev, pos, &sz);
|
||||
pci_write_config_dword(dev, pos, l);
|
||||
|
||||
if (!dev->mmio_always_on)
|
||||
pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
|
||||
|
||||
/*
|
||||
* All bits set in sz means the device isn't working properly.
|
||||
* If the BAR isn't implemented, all bits must be 0. If it's a
|
||||
|
|
|
|||
|
|
@ -431,8 +431,6 @@ int pci_proc_detach_device(struct pci_dev *dev)
|
|||
struct proc_dir_entry *e;
|
||||
|
||||
if ((e = dev->procent)) {
|
||||
if (atomic_read(&e->count) > 1)
|
||||
return -EBUSY;
|
||||
remove_proc_entry(e->name, dev->bus->procdir);
|
||||
dev->procent = NULL;
|
||||
}
|
||||
|
|
@ -485,9 +483,9 @@ static int __init pci_proc_init(void)
|
|||
proc_create("devices", 0, proc_bus_pci_dir,
|
||||
&proc_bus_pci_dev_operations);
|
||||
proc_initialized = 1;
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
for_each_pci_dev(dev)
|
||||
pci_proc_attach_device(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,19 @@ static void __devinit quirk_resource_alignment(struct pci_dev *dev)
|
|||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_resource_alignment);
|
||||
|
||||
/*
|
||||
* Decoding should be disabled for a PCI device during BAR sizing to avoid
|
||||
* conflict. But doing so may cause problems on host bridge and perhaps other
|
||||
* key system devices. For devices that need to have mmio decoding always-on,
|
||||
* we need to set the dev->mmio_always_on bit.
|
||||
*/
|
||||
static void __devinit quirk_mmio_always_on(struct pci_dev *dev)
|
||||
{
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
|
||||
dev->mmio_always_on = 1;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, quirk_mmio_always_on);
|
||||
|
||||
/* The Mellanox Tavor device gives false positive parity errors
|
||||
* Mark this device with a broken_parity_status, to allow
|
||||
* PCI scanning code to "skip" this now blacklisted device.
|
||||
|
|
@ -2121,6 +2134,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS480, quirk_disabl
|
|||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3336, quirk_disable_all_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3351, quirk_disable_all_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VT3364, quirk_disable_all_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8380_0, quirk_disable_all_msi);
|
||||
|
||||
/* Disable MSI on chipsets that are known to not support it */
|
||||
static void __devinit quirk_disable_msi(struct pci_dev *dev)
|
||||
|
|
@ -2132,12 +2146,29 @@ static void __devinit quirk_disable_msi(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE, quirk_disable_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ASUSTEK, 0x9602, quirk_disable_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 0x9602, quirk_disable_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_VIA, 0xa238, quirk_disable_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
|
||||
|
||||
/*
|
||||
* The APC bridge device in AMD 780 family northbridges has some random
|
||||
* OEM subsystem ID in its vendor ID register (erratum 18), so instead
|
||||
* we use the possible vendor/device IDs of the host bridge for the
|
||||
* declared quirk, and search for the APC bridge by slot number.
|
||||
*/
|
||||
static void __devinit quirk_amd_780_apc_msi(struct pci_dev *host_bridge)
|
||||
{
|
||||
struct pci_dev *apc_bridge;
|
||||
|
||||
apc_bridge = pci_get_slot(host_bridge->bus, PCI_DEVFN(1, 0));
|
||||
if (apc_bridge) {
|
||||
if (apc_bridge->device == 0x9602)
|
||||
quirk_disable_msi(apc_bridge);
|
||||
pci_dev_put(apc_bridge);
|
||||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9600, quirk_amd_780_apc_msi);
|
||||
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9601, quirk_amd_780_apc_msi);
|
||||
|
||||
/* Go through the list of Hypertransport capabilities and
|
||||
* return 1 if a HT MSI capability is found and enabled */
|
||||
static int __devinit msi_ht_cap_enabled(struct pci_dev *dev)
|
||||
|
|
@ -2396,6 +2427,9 @@ static void __devinit __nv_msi_ht_cap_quirk(struct pci_dev *dev, int all)
|
|||
int pos;
|
||||
int found;
|
||||
|
||||
if (!pci_msi_enabled())
|
||||
return;
|
||||
|
||||
/* check if there is HT MSI cap or enabled on this device */
|
||||
found = ht_check_msi_mapping(dev);
|
||||
|
||||
|
|
@ -2748,7 +2782,7 @@ static int __init pci_apply_final_quirks(void)
|
|||
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) {
|
||||
for_each_pci_dev(dev) {
|
||||
pci_fixup_device(pci_fixup_final, dev);
|
||||
/*
|
||||
* If arch hasn't set it explicitly yet, use the CLS
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ struct pci_dev *pci_get_domain_bus_and_slot(int domain, unsigned int bus,
|
|||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
for_each_pci_dev(dev) {
|
||||
if (pci_domain_nr(dev->bus) == domain &&
|
||||
(dev->bus->number == bus && dev->devfn == devfn))
|
||||
return dev;
|
||||
|
|
|
|||
|
|
@ -874,19 +874,16 @@ void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge)
|
|||
again:
|
||||
pci_bus_size_bridges(parent);
|
||||
__pci_bridge_assign_resources(bridge, &head);
|
||||
retval = pci_reenable_device(bridge);
|
||||
pci_set_master(bridge);
|
||||
pci_enable_bridges(parent);
|
||||
|
||||
tried_times++;
|
||||
|
||||
if (!head.next)
|
||||
return;
|
||||
goto enable_all;
|
||||
|
||||
if (tried_times >= 2) {
|
||||
/* still fail, don't need to try more */
|
||||
free_failed_list(&head);
|
||||
return;
|
||||
goto enable_all;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n",
|
||||
|
|
@ -919,5 +916,10 @@ again:
|
|||
free_failed_list(&head);
|
||||
|
||||
goto again;
|
||||
|
||||
enable_all:
|
||||
retval = pci_reenable_device(bridge);
|
||||
pci_set_master(bridge);
|
||||
pci_enable_bridges(parent);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
|
|||
int (*map_irq)(struct pci_dev *, u8, u8))
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
for_each_pci_dev(dev)
|
||||
pdev_fixup_irq(dev, swizzle, map_irq);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue