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:
Коммит
1cfd2bda8c
|
@ -139,3 +139,30 @@ Contact: linux-pci@vger.kernel.org
|
|||
Description:
|
||||
This symbolic link points to the PCI hotplug controller driver
|
||||
module that manages the hotplug slot.
|
||||
|
||||
What: /sys/bus/pci/devices/.../label
|
||||
Date: July 2010
|
||||
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||
Description:
|
||||
Reading this attribute will provide the firmware
|
||||
given name(SMBIOS type 41 string) of the PCI device.
|
||||
The attribute will be created only if the firmware
|
||||
has given a name to the PCI device.
|
||||
Users:
|
||||
Userspace applications interested in knowing the
|
||||
firmware assigned name of the PCI device.
|
||||
|
||||
What: /sys/bus/pci/devices/.../index
|
||||
Date: July 2010
|
||||
Contact: Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
|
||||
Description:
|
||||
Reading this attribute will provide the firmware
|
||||
given instance(SMBIOS type 41 device type instance)
|
||||
of the PCI device. The attribute will be created
|
||||
only if the firmware has given a device type instance
|
||||
to the PCI device.
|
||||
Users:
|
||||
Userspace applications interested in knowing the
|
||||
firmware assigned device type instance of the PCI
|
||||
device that can help in understanding the firmware
|
||||
intended order of the PCI device.
|
||||
|
|
|
@ -39,7 +39,7 @@ files, each with their own function.
|
|||
local_cpus nearby CPU mask (cpumask, ro)
|
||||
remove remove device from kernel's list (ascii, wo)
|
||||
resource PCI resource host addresses (ascii, ro)
|
||||
resource0..N PCI resource N, if present (binary, mmap)
|
||||
resource0..N PCI resource N, if present (binary, mmap, rw[1])
|
||||
resource0_wc..N_wc PCI WC map resource N, if prefetchable (binary, mmap)
|
||||
rom PCI ROM resource, if present (binary, ro)
|
||||
subsystem_device PCI subsystem device (ascii, ro)
|
||||
|
@ -54,13 +54,16 @@ files, each with their own function.
|
|||
binary - file contains binary data
|
||||
cpumask - file contains a cpumask type
|
||||
|
||||
[1] rw for RESOURCE_IO (I/O port) regions only
|
||||
|
||||
The read only files are informational, writes to them will be ignored, with
|
||||
the exception of the 'rom' file. Writable files can be used to perform
|
||||
actions on the device (e.g. changing config space, detaching a device).
|
||||
mmapable files are available via an mmap of the file at offset 0 and can be
|
||||
used to do actual device programming from userspace. Note that some platforms
|
||||
don't support mmapping of certain resources, so be sure to check the return
|
||||
value from any attempted mmap.
|
||||
value from any attempted mmap. The most notable of these are I/O port
|
||||
resources, which also provide read/write access.
|
||||
|
||||
The 'enable' file provides a counter that indicates how many times the device
|
||||
has been enabled. If the 'enable' file currently returns '4', and a '1' is
|
||||
|
|
|
@ -1976,6 +1976,8 @@ and is between 256 and 4096 characters. It is defined in the file
|
|||
norom [X86] Do not assign address space to
|
||||
expansion ROMs that do not already have
|
||||
BIOS assigned address ranges.
|
||||
nobar [X86] Do not assign address space to the
|
||||
BARs that weren't assigned by the BIOS.
|
||||
irqmask=0xMMMM [X86] Set a bit mask of IRQs allowed to be
|
||||
assigned automatically to PCI devices. You can
|
||||
make the kernel exclude IRQs of your ISA cards
|
||||
|
|
|
@ -25,7 +25,7 @@ static int ia64_set_msi_irq_affinity(unsigned int irq,
|
|||
if (irq_prepare_move(irq, cpu))
|
||||
return -1;
|
||||
|
||||
read_msi_msg(irq, &msg);
|
||||
get_cached_msi_msg(irq, &msg);
|
||||
|
||||
addr = msg.address_lo;
|
||||
addr &= MSI_ADDR_DEST_ID_MASK;
|
||||
|
|
|
@ -175,7 +175,7 @@ static int sn_set_msi_irq_affinity(unsigned int irq,
|
|||
* Release XIO resources for the old MSI PCI address
|
||||
*/
|
||||
|
||||
read_msi_msg(irq, &msg);
|
||||
get_cached_msi_msg(irq, &msg);
|
||||
sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
|
||||
pdev = sn_pdev->pdi_linux_pcidev;
|
||||
provider = SN_PCIDEV_BUSPROVIDER(pdev);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define PCI_HAS_IO_ECS 0x40000
|
||||
#define PCI_NOASSIGN_ROMS 0x80000
|
||||
#define PCI_ROOT_NO_CRS 0x100000
|
||||
#define PCI_NOASSIGN_BARS 0x200000
|
||||
|
||||
extern unsigned int pci_probe;
|
||||
extern unsigned long pirq_table_addr;
|
||||
|
|
|
@ -3397,7 +3397,7 @@ static int set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
|
|||
|
||||
cfg = desc->chip_data;
|
||||
|
||||
read_msi_msg_desc(desc, &msg);
|
||||
get_cached_msi_msg_desc(desc, &msg);
|
||||
|
||||
msg.data &= ~MSI_DATA_VECTOR_MASK;
|
||||
msg.data |= MSI_DATA_VECTOR(cfg->vector);
|
||||
|
|
|
@ -34,6 +34,15 @@ static const struct dmi_system_id pci_use_crs_table[] __initconst = {
|
|||
DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
|
||||
},
|
||||
},
|
||||
/* https://bugzilla.kernel.org/show_bug.cgi?id=16007 */
|
||||
/* 2006 AMD HT/VIA system with two host bridges */
|
||||
{
|
||||
.callback = set_use_crs,
|
||||
.ident = "ASRock ALiveSATA2-GLAN",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "ALiveSATA2-GLAN"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -125,6 +125,23 @@ void __init dmi_check_skip_isa_align(void)
|
|||
static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
|
||||
{
|
||||
struct resource *rom_r = &dev->resource[PCI_ROM_RESOURCE];
|
||||
struct resource *bar_r;
|
||||
int bar;
|
||||
|
||||
if (pci_probe & PCI_NOASSIGN_BARS) {
|
||||
/*
|
||||
* If the BIOS did not assign the BAR, zero out the
|
||||
* resource so the kernel doesn't attmept to assign
|
||||
* it later on in pci_assign_unassigned_resources
|
||||
*/
|
||||
for (bar = 0; bar <= PCI_STD_RESOURCE_END; bar++) {
|
||||
bar_r = &dev->resource[bar];
|
||||
if (bar_r->start == 0 && bar_r->end != 0) {
|
||||
bar_r->flags = 0;
|
||||
bar_r->end = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pci_probe & PCI_NOASSIGN_ROMS) {
|
||||
if (rom_r->parent)
|
||||
|
@ -509,6 +526,9 @@ char * __devinit pcibios_setup(char *str)
|
|||
} else if (!strcmp(str, "norom")) {
|
||||
pci_probe |= PCI_NOASSIGN_ROMS;
|
||||
return NULL;
|
||||
} else if (!strcmp(str, "nobar")) {
|
||||
pci_probe |= PCI_NOASSIGN_BARS;
|
||||
return NULL;
|
||||
} else if (!strcmp(str, "assign-busses")) {
|
||||
pci_probe |= PCI_ASSIGN_ALL_BUSSES;
|
||||
return NULL;
|
||||
|
|
|
@ -989,7 +989,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
|
|||
dev_info(&dev->dev, "%s PCI INT %c -> IRQ %d\n", msg, 'A' + pin - 1, irq);
|
||||
|
||||
/* Update IRQ for all devices with the same pirq value */
|
||||
while ((dev2 = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev2)) != NULL) {
|
||||
for_each_pci_dev(dev2) {
|
||||
pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin);
|
||||
if (!pin)
|
||||
continue;
|
||||
|
@ -1028,7 +1028,7 @@ void __init pcibios_fixup_irqs(void)
|
|||
u8 pin;
|
||||
|
||||
DBG(KERN_DEBUG "PCI: IRQ fixup\n");
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
for_each_pci_dev(dev) {
|
||||
/*
|
||||
* If the BIOS has set an out of range IRQ number, just
|
||||
* ignore it. Also keep track of which IRQ's are
|
||||
|
@ -1052,7 +1052,7 @@ void __init pcibios_fixup_irqs(void)
|
|||
return;
|
||||
|
||||
dev = NULL;
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
for_each_pci_dev(dev) {
|
||||
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
|
||||
if (!pin)
|
||||
continue;
|
||||
|
|
|
@ -36,7 +36,7 @@ int __init pci_legacy_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void pcibios_scan_specific_bus(int busn)
|
||||
void __devinit pcibios_scan_specific_bus(int busn)
|
||||
{
|
||||
int devfn;
|
||||
long node;
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/pci-acpi.h>
|
||||
#include <linux/pci-aspm.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/slab.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
|
@ -543,6 +544,14 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|||
if (flags != base_flags)
|
||||
acpi_pci_osc_support(root, flags);
|
||||
|
||||
status = acpi_pci_osc_control_set(root->device->handle,
|
||||
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk(KERN_INFO "Unable to assume PCIe control: Disabling ASPM\n");
|
||||
pcie_no_aspm();
|
||||
}
|
||||
|
||||
pci_acpi_add_bus_pm_notifier(device, root->bus);
|
||||
if (device->wakeup.flags.run_wake)
|
||||
device_set_run_wake(root->bus->bridge, true);
|
||||
|
|
|
@ -277,6 +277,29 @@ static void __init dmi_save_ipmi_device(const struct dmi_header *dm)
|
|||
list_add_tail(&dev->list, &dmi_devices);
|
||||
}
|
||||
|
||||
static void __init dmi_save_dev_onboard(int instance, int segment, int bus,
|
||||
int devfn, const char *name)
|
||||
{
|
||||
struct dmi_dev_onboard *onboard_dev;
|
||||
|
||||
onboard_dev = dmi_alloc(sizeof(*onboard_dev) + strlen(name) + 1);
|
||||
if (!onboard_dev) {
|
||||
printk(KERN_ERR "dmi_save_dev_onboard: out of memory.\n");
|
||||
return;
|
||||
}
|
||||
onboard_dev->instance = instance;
|
||||
onboard_dev->segment = segment;
|
||||
onboard_dev->bus = bus;
|
||||
onboard_dev->devfn = devfn;
|
||||
|
||||
strcpy((char *)&onboard_dev[1], name);
|
||||
onboard_dev->dev.type = DMI_DEV_TYPE_DEV_ONBOARD;
|
||||
onboard_dev->dev.name = (char *)&onboard_dev[1];
|
||||
onboard_dev->dev.device_data = onboard_dev;
|
||||
|
||||
list_add(&onboard_dev->dev.list, &dmi_devices);
|
||||
}
|
||||
|
||||
static void __init dmi_save_extended_devices(const struct dmi_header *dm)
|
||||
{
|
||||
const u8 *d = (u8*) dm + 5;
|
||||
|
@ -285,6 +308,8 @@ static void __init dmi_save_extended_devices(const struct dmi_header *dm)
|
|||
if ((*d & 0x80) == 0)
|
||||
return;
|
||||
|
||||
dmi_save_dev_onboard(*(d+1), *(u16 *)(d+2), *(d+4), *(d+5),
|
||||
dmi_string_nosave(dm, *(d-1)));
|
||||
dmi_save_one_device(*d & 0x7f, dmi_string_nosave(dm, *(d - 1)));
|
||||
}
|
||||
|
||||
|
|
|
@ -5825,11 +5825,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
|
|||
|
||||
e1000_print_device_info(adapter);
|
||||
|
||||
if (pci_dev_run_wake(pdev)) {
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
}
|
||||
pm_schedule_suspend(&pdev->dev, MSEC_PER_SEC);
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -5875,8 +5872,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
|||
struct e1000_adapter *adapter = netdev_priv(netdev);
|
||||
bool down = test_bit(__E1000_DOWN, &adapter->state);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
/*
|
||||
* flush_scheduled work may reschedule our watchdog task, so
|
||||
* explicitly disable watchdog tasks from being rescheduled
|
||||
|
@ -5901,11 +5896,8 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
|
|||
clear_bit(__E1000_DOWN, &adapter->state);
|
||||
unregister_netdev(netdev);
|
||||
|
||||
if (pci_dev_run_wake(pdev)) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
}
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
||||
/*
|
||||
* Release control of h/w to f/w. If f/w is AMT enabled, this
|
||||
|
|
|
@ -3219,11 +3219,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
|
||||
device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
|
||||
|
||||
if (pci_dev_run_wake(pdev)) {
|
||||
pm_runtime_set_active(&pdev->dev);
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
}
|
||||
pm_runtime_idle(&pdev->dev);
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
|
||||
out:
|
||||
return rc;
|
||||
|
@ -3246,17 +3243,12 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
|
|||
struct net_device *dev = pci_get_drvdata(pdev);
|
||||
struct rtl8169_private *tp = netdev_priv(dev);
|
||||
|
||||
pm_runtime_get_sync(&pdev->dev);
|
||||
|
||||
flush_scheduled_work();
|
||||
|
||||
unregister_netdev(dev);
|
||||
|
||||
if (pci_dev_run_wake(pdev)) {
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
pm_runtime_set_suspended(&pdev->dev);
|
||||
}
|
||||
pm_runtime_put_noidle(&pdev->dev);
|
||||
if (pci_dev_run_wake(pdev))
|
||||
pm_runtime_get_noresume(&pdev->dev);
|
||||
|
||||
/* restore original MAC address */
|
||||
rtl_rar_set(tp, dev->perm_addr);
|
||||
|
|
|
@ -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 */
|
||||
|
@ -119,12 +113,6 @@ int shpchp_unconfigure_device(struct slot *p_slot)
|
|||
(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.
|
||||
|
|
|
@ -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) {
|
||||
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;
|
||||
ret = 1;
|
||||
}
|
||||
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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ enum dmi_device_type {
|
|||
DMI_DEV_TYPE_SAS,
|
||||
DMI_DEV_TYPE_IPMI = -1,
|
||||
DMI_DEV_TYPE_OEM_STRING = -2,
|
||||
DMI_DEV_TYPE_DEV_ONBOARD = -3,
|
||||
};
|
||||
|
||||
struct dmi_header {
|
||||
|
@ -37,6 +38,14 @@ struct dmi_device {
|
|||
|
||||
#ifdef CONFIG_DMI
|
||||
|
||||
struct dmi_dev_onboard {
|
||||
struct dmi_device dev;
|
||||
int instance;
|
||||
int segment;
|
||||
int bus;
|
||||
int devfn;
|
||||
};
|
||||
|
||||
extern int dmi_check_system(const struct dmi_system_id *list);
|
||||
const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list);
|
||||
extern const char * dmi_get_system_info(int field);
|
||||
|
|
|
@ -14,8 +14,10 @@ struct irq_desc;
|
|||
extern void mask_msi_irq(unsigned int irq);
|
||||
extern void unmask_msi_irq(unsigned int irq);
|
||||
extern void read_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
|
||||
extern void get_cached_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
|
||||
extern void write_msi_msg_desc(struct irq_desc *desc, struct msi_msg *msg);
|
||||
extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||
extern void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||
extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
|
||||
|
||||
struct msi_desc {
|
||||
|
|
|
@ -270,6 +270,8 @@ struct pci_dev {
|
|||
unsigned int d1_support:1; /* Low power state D1 is supported */
|
||||
unsigned int d2_support:1; /* Low power state D2 is supported */
|
||||
unsigned int no_d1d2:1; /* Only allow D0 and D3 */
|
||||
unsigned int mmio_always_on:1; /* disallow turning off io/mem
|
||||
decoding during bar sizing */
|
||||
unsigned int wakeup_prepared:1;
|
||||
unsigned int d3_delay; /* D3->D0 transition time in ms */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче