Commit 6109e2ce authored by Linus Torvalds's avatar Linus Torvalds

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: (36 commits)
  PCI: hotplug: pciehp: Removed check for hotplug of display devices
  PCI: read memory ranges out of Broadcom CNB20LE host bridge
  PCI: Allow manual resource allocation for PCI hotplug bridges
  x86/PCI: make ACPI MCFG reserved error messages ACPI specific
  PCI hotplug: Use kmemdup
  PM/PCI: Update PCI power management documentation
  PCI: output FW warning in pci_read/write_vpd
  PCI: fix typos pci_device_dis/enable to pci_dis/enable_device in comments
  PCI quirks: disable msi on AMD rs4xx internal gfx bridges
  PCI: Disable MSI for MCP55 on P5N32-E SLI
  x86/PCI: irq and pci_ids patch for additional Intel Cougar Point DeviceIDs
  PCI: aerdrv: trivial cleanup for aerdrv_core.c
  PCI: aerdrv: trivial cleanup for aerdrv.c
  PCI: aerdrv: introduce default_downstream_reset_link
  PCI: aerdrv: rework find_aer_service
  PCI: aerdrv: remove is_downstream
  PCI: aerdrv: remove magical ROOT_ERR_STATUS_MASKS
  PCI: aerdrv: redefine PCI_ERR_ROOT_*_SRC
  PCI: aerdrv: rework do_recovery
  PCI: aerdrv: rework get_e_source()
  ...
parents 0961d658 ac81860e
...@@ -133,6 +133,46 @@ Description: ...@@ -133,6 +133,46 @@ Description:
The symbolic link points to the PCI device sysfs entry of the The symbolic link points to the PCI device sysfs entry of the
Physical Function this device associates with. Physical Function this device associates with.
What: /sys/bus/pci/slots/...
Date: April 2005 (possibly older)
KernelVersion: 2.6.12 (possibly older)
Contact: linux-pci@vger.kernel.org
Description:
When the appropriate driver is loaded, it will create a
directory per claimed physical PCI slot in
/sys/bus/pci/slots/. The names of these directories are
specific to the driver, which in turn, are specific to the
platform, but in general, should match the label on the
machine's physical chassis.
The drivers that can create slot directories include the
PCI hotplug drivers, and as of 2.6.27, the pci_slot driver.
The slot directories contain, at a minimum, a file named
'address' which contains the PCI bus:device:function tuple.
Other files may appear as well, but are specific to the
driver.
What: /sys/bus/pci/slots/.../function[0-7]
Date: March 2010
KernelVersion: 2.6.35
Contact: linux-pci@vger.kernel.org
Description:
If PCI slot directories (as described above) are created,
and the physical slot is actually populated with a device,
symbolic links in the slot directory pointing to the
device's PCI functions are created as well.
What: /sys/bus/pci/devices/.../slot
Date: March 2010
KernelVersion: 2.6.35
Contact: linux-pci@vger.kernel.org
Description:
If PCI slot directories (as described above) are created,
a symbolic link pointing to the slot directory will be
created as well.
What: /sys/bus/pci/slots/.../module What: /sys/bus/pci/slots/.../module
Date: June 2009 Date: June 2009
Contact: linux-pci@vger.kernel.org Contact: linux-pci@vger.kernel.org
......
...@@ -13,7 +13,7 @@ Reporting (AER) driver and provides information on how to use it, as ...@@ -13,7 +13,7 @@ Reporting (AER) driver and provides information on how to use it, as
well as how to enable the drivers of endpoint devices to conform with well as how to enable the drivers of endpoint devices to conform with
PCI Express AER driver. PCI Express AER driver.
1.2 Copyright © Intel Corporation 2006. 1.2 Copyright (C) Intel Corporation 2006.
1.3 What is the PCI Express AER Driver? 1.3 What is the PCI Express AER Driver?
...@@ -71,15 +71,11 @@ console. If it's a correctable error, it is outputed as a warning. ...@@ -71,15 +71,11 @@ console. If it's a correctable error, it is outputed as a warning.
Otherwise, it is printed as an error. So users could choose different Otherwise, it is printed as an error. So users could choose different
log level to filter out correctable error messages. log level to filter out correctable error messages.
Below shows an example. Below shows an example:
+------ PCI-Express Device Error -----+ 0000:50:00.0: PCIe Bus Error: severity=Uncorrected (Fatal), type=Transaction Layer, id=0500(Requester ID)
Error Severity : Uncorrected (Fatal) 0000:50:00.0: device [8086:0329] error status/mask=00100000/00000000
PCIE Bus Error type : Transaction Layer 0000:50:00.0: [20] Unsupported Request (First)
Unsupported Request : First 0000:50:00.0: TLP Header: 04000001 00200a03 05010000 00050100
Requester ID : 0500
VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h
TLB Header:
04000001 00200a03 05010000 00050100
In the example, 'Requester ID' means the ID of the device who sends In the example, 'Requester ID' means the ID of the device who sends
the error message to root port. Pls. refer to pci express specs for the error message to root port. Pls. refer to pci express specs for
...@@ -112,7 +108,7 @@ but the PCI Express link itself is fully functional. Fatal errors, on ...@@ -112,7 +108,7 @@ but the PCI Express link itself is fully functional. Fatal errors, on
the other hand, cause the link to be unreliable. the other hand, cause the link to be unreliable.
When AER is enabled, a PCI Express device will automatically send an When AER is enabled, a PCI Express device will automatically send an
error message to the PCIE root port above it when the device captures error message to the PCIe root port above it when the device captures
an error. The Root Port, upon receiving an error reporting message, an error. The Root Port, upon receiving an error reporting message,
internally processes and logs the error message in its PCI Express internally processes and logs the error message in its PCI Express
capability structure. Error information being logged includes storing capability structure. Error information being logged includes storing
...@@ -198,8 +194,9 @@ to reset link, AER port service driver is required to provide the ...@@ -198,8 +194,9 @@ to reset link, AER port service driver is required to provide the
function to reset link. Firstly, kernel looks for if the upstream function to reset link. Firstly, kernel looks for if the upstream
component has an aer driver. If it has, kernel uses the reset_link component has an aer driver. If it has, kernel uses the reset_link
callback of the aer driver. If the upstream component has no aer driver callback of the aer driver. If the upstream component has no aer driver
and the port is downstream port, we will use the aer driver of the and the port is downstream port, we will perform a hot reset as the
root port who reports the AER error. As for upstream ports, default by setting the Secondary Bus Reset bit of the Bridge Control
register associated with the downstream port. As for upstream ports,
they should provide their own aer service drivers with reset_link they should provide their own aer service drivers with reset_link
function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and
reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes
...@@ -253,11 +250,11 @@ cleanup uncorrectable status register. Pls. refer to section 3.3. ...@@ -253,11 +250,11 @@ cleanup uncorrectable status register. Pls. refer to section 3.3.
4. Software error injection 4. Software error injection
Debugging PCIE AER error recovery code is quite difficult because it Debugging PCIe AER error recovery code is quite difficult because it
is hard to trigger real hardware errors. Software based error is hard to trigger real hardware errors. Software based error
injection can be used to fake various kinds of PCIE errors. injection can be used to fake various kinds of PCIe errors.
First you should enable PCIE AER software error injection in kernel First you should enable PCIe AER software error injection in kernel
configuration, that is, following item should be in your .config. configuration, that is, following item should be in your .config.
CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m
......
This diff is collapsed.
...@@ -1923,6 +1923,14 @@ config PCI_MMCONFIG ...@@ -1923,6 +1923,14 @@ config PCI_MMCONFIG
bool "Support mmconfig PCI config space access" bool "Support mmconfig PCI config space access"
depends on X86_64 && PCI && ACPI depends on X86_64 && PCI && ACPI
config PCI_CNB20LE_QUIRK
bool "Read CNB20LE Host Bridge Windows"
depends on PCI
help
Read the PCI windows out of the CNB20LE host bridge. This allows
PCI hotplug to work on systems with the CNB20LE chipset which do
not have ACPI.
config DMAR config DMAR
bool "Support for DMA Remapping Devices (EXPERIMENTAL)" bool "Support for DMA Remapping Devices (EXPERIMENTAL)"
depends on PCI_MSI && ACPI && EXPERIMENTAL depends on PCI_MSI && ACPI && EXPERIMENTAL
......
...@@ -83,7 +83,7 @@ struct irq_routing_table { ...@@ -83,7 +83,7 @@ struct irq_routing_table {
extern unsigned int pcibios_irq_mask; extern unsigned int pcibios_irq_mask;
extern spinlock_t pci_config_lock; extern raw_spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev); extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev); extern void (*pcibios_disable_irq)(struct pci_dev *dev);
......
...@@ -18,6 +18,8 @@ obj-$(CONFIG_X86_MRST) += mrst.o ...@@ -18,6 +18,8 @@ obj-$(CONFIG_X86_MRST) += mrst.o
obj-y += common.o early.o obj-y += common.o early.o
obj-y += amd_bus.o bus_numa.o obj-y += amd_bus.o bus_numa.o
obj-$(CONFIG_PCI_CNB20LE_QUIRK) += broadcom_bus.o
ifeq ($(CONFIG_PCI_DEBUG),y) ifeq ($(CONFIG_PCI_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG EXTRA_CFLAGS += -DDEBUG
endif endif
/*
* Read address ranges from a Broadcom CNB20LE Host Bridge
*
* Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/pci_x86.h>
#include "bus_numa.h"
static void __devinit cnb20le_res(struct pci_dev *dev)
{
struct pci_root_info *info;
struct resource res;
u16 word1, word2;
u8 fbus, lbus;
int i;
/*
* The x86_pci_root_bus_res_quirks() function already refuses to use
* this information if ACPI _CRS was used. Therefore, we don't bother
* checking if ACPI is enabled, and just generate the information
* for both the ACPI _CRS and no ACPI cases.
*/
info = &pci_root_info[pci_root_num];
pci_root_num++;
/* read the PCI bus numbers */
pci_read_config_byte(dev, 0x44, &fbus);
pci_read_config_byte(dev, 0x45, &lbus);
info->bus_min = fbus;
info->bus_max = lbus;
/*
* Add the legacy IDE ports on bus 0
*
* These do not exist anywhere in the bridge registers, AFAICT. I do
* not have the datasheet, so this is the best I can do.
*/
if (fbus == 0) {
update_res(info, 0x01f0, 0x01f7, IORESOURCE_IO, 0);
update_res(info, 0x03f6, 0x03f6, IORESOURCE_IO, 0);
update_res(info, 0x0170, 0x0177, IORESOURCE_IO, 0);
update_res(info, 0x0376, 0x0376, IORESOURCE_IO, 0);
update_res(info, 0xffa0, 0xffaf, IORESOURCE_IO, 0);
}
/* read the non-prefetchable memory window */
pci_read_config_word(dev, 0xc0, &word1);
pci_read_config_word(dev, 0xc2, &word2);
if (word1 != word2) {
res.start = (word1 << 16) | 0x0000;
res.end = (word2 << 16) | 0xffff;
res.flags = IORESOURCE_MEM;
update_res(info, res.start, res.end, res.flags, 0);
}
/* read the prefetchable memory window */
pci_read_config_word(dev, 0xc4, &word1);
pci_read_config_word(dev, 0xc6, &word2);
if (word1 != word2) {
res.start = (word1 << 16) | 0x0000;
res.end = (word2 << 16) | 0xffff;
res.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
update_res(info, res.start, res.end, res.flags, 0);
}
/* read the IO port window */
pci_read_config_word(dev, 0xd0, &word1);
pci_read_config_word(dev, 0xd2, &word2);
if (word1 != word2) {
res.start = word1;
res.end = word2;
res.flags = IORESOURCE_IO;
update_res(info, res.start, res.end, res.flags, 0);
}
/* print information about this host bridge */
res.start = fbus;
res.end = lbus;
res.flags = IORESOURCE_BUS;
dev_info(&dev->dev, "CNB20LE PCI Host Bridge (domain %04x %pR)\n",
pci_domain_nr(dev->bus), &res);
for (i = 0; i < info->res_num; i++)
dev_info(&dev->dev, "host bridge window %pR\n", &info->res[i]);
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_LE,
cnb20le_res);
...@@ -76,7 +76,7 @@ struct pci_ops pci_root_ops = { ...@@ -76,7 +76,7 @@ struct pci_ops pci_root_ops = {
* This interrupt-safe spinlock protects all accesses to PCI * This interrupt-safe spinlock protects all accesses to PCI
* configuration space. * configuration space.
*/ */
DEFINE_SPINLOCK(pci_config_lock); DEFINE_RAW_SPINLOCK(pci_config_lock);
static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d)
{ {
......
...@@ -27,7 +27,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus, ...@@ -27,7 +27,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus,
return -EINVAL; return -EINVAL;
} }
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
...@@ -43,7 +43,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus, ...@@ -43,7 +43,7 @@ static int pci_conf1_read(unsigned int seg, unsigned int bus,
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
...@@ -56,7 +56,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus, ...@@ -56,7 +56,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus,
if ((bus > 255) || (devfn > 255) || (reg > 4095)) if ((bus > 255) || (devfn > 255) || (reg > 4095))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
...@@ -72,7 +72,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus, ...@@ -72,7 +72,7 @@ static int pci_conf1_write(unsigned int seg, unsigned int bus,
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
...@@ -108,7 +108,7 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus, ...@@ -108,7 +108,7 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus,
if (dev & 0x10) if (dev & 0x10)
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
outb((u8)(0xF0 | (fn << 1)), 0xCF8); outb((u8)(0xF0 | (fn << 1)), 0xCF8);
outb((u8)bus, 0xCFA); outb((u8)bus, 0xCFA);
...@@ -127,7 +127,7 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus, ...@@ -127,7 +127,7 @@ static int pci_conf2_read(unsigned int seg, unsigned int bus,
outb(0, 0xCF8); outb(0, 0xCF8);
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
...@@ -147,7 +147,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus, ...@@ -147,7 +147,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
if (dev & 0x10) if (dev & 0x10)
return PCIBIOS_DEVICE_NOT_FOUND; return PCIBIOS_DEVICE_NOT_FOUND;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
outb((u8)(0xF0 | (fn << 1)), 0xCF8); outb((u8)(0xF0 | (fn << 1)), 0xCF8);
outb((u8)bus, 0xCFA); outb((u8)bus, 0xCFA);
...@@ -166,7 +166,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus, ...@@ -166,7 +166,7 @@ static int pci_conf2_write(unsigned int seg, unsigned int bus,
outb(0, 0xCF8); outb(0, 0xCF8);
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
......
...@@ -589,8 +589,6 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route ...@@ -589,8 +589,6 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
case PCI_DEVICE_ID_INTEL_ICH10_1: case PCI_DEVICE_ID_INTEL_ICH10_1:
case PCI_DEVICE_ID_INTEL_ICH10_2: case PCI_DEVICE_ID_INTEL_ICH10_2:
case PCI_DEVICE_ID_INTEL_ICH10_3: case PCI_DEVICE_ID_INTEL_ICH10_3:
case PCI_DEVICE_ID_INTEL_CPT_LPC1:
case PCI_DEVICE_ID_INTEL_CPT_LPC2:
r->name = "PIIX/ICH"; r->name = "PIIX/ICH";
r->get = pirq_piix_get; r->get = pirq_piix_get;
r->set = pirq_piix_set; r->set = pirq_piix_set;
...@@ -605,6 +603,13 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route ...@@ -605,6 +603,13 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
return 1; return 1;
} }
if ((device >= PCI_DEVICE_ID_INTEL_CPT_LPC_MIN) &&
(device <= PCI_DEVICE_ID_INTEL_CPT_LPC_MAX)) {
r->name = "PIIX/ICH";
r->get = pirq_piix_get;
r->set = pirq_piix_set;
return 1;
}
return 0; return 0;
} }
......
...@@ -483,16 +483,17 @@ static void __init pci_mmcfg_reject_broken(int early) ...@@ -483,16 +483,17 @@ static void __init pci_mmcfg_reject_broken(int early)
list_for_each_entry(cfg, &pci_mmcfg_list, list) { list_for_each_entry(cfg, &pci_mmcfg_list, list) {
int valid = 0; int valid = 0;
if (!early && !acpi_disabled) if (!early && !acpi_disabled) {
valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0); valid = is_mmconf_reserved(is_acpi_reserved, cfg, 0);
if (valid) if (valid)
continue; continue;
else
if (!early)
printk(KERN_ERR FW_BUG PREFIX printk(KERN_ERR FW_BUG PREFIX
"MMCONFIG at %pR not reserved in " "MMCONFIG at %pR not reserved in "
"ACPI motherboard resources\n", &cfg->res); "ACPI motherboard resources\n",
&cfg->res);
}
/* Don't try to do this check unless configuration /* Don't try to do this check unless configuration
type 1 is available. how about type 2 ?*/ type 1 is available. how about type 2 ?*/
......
...@@ -64,7 +64,7 @@ err: *value = -1; ...@@ -64,7 +64,7 @@ err: *value = -1;
if (!base) if (!base)
goto err; goto err;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
pci_exp_set_dev_base(base, bus, devfn); pci_exp_set_dev_base(base, bus, devfn);
...@@ -79,7 +79,7 @@ err: *value = -1; ...@@ -79,7 +79,7 @@ err: *value = -1;
*value = mmio_config_readl(mmcfg_virt_addr + reg); *value = mmio_config_readl(mmcfg_virt_addr + reg);
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
...@@ -97,7 +97,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, ...@@ -97,7 +97,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
if (!base) if (!base)
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
pci_exp_set_dev_base(base, bus, devfn); pci_exp_set_dev_base(base, bus, devfn);
...@@ -112,7 +112,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus, ...@@ -112,7 +112,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
mmio_config_writel(mmcfg_virt_addr + reg, value); mmio_config_writel(mmcfg_virt_addr + reg, value);
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
......
...@@ -37,7 +37,7 @@ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus, ...@@ -37,7 +37,7 @@ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
write_cf8(bus, devfn, reg); write_cf8(bus, devfn, reg);
...@@ -62,7 +62,7 @@ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus, ...@@ -62,7 +62,7 @@ static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
...@@ -76,7 +76,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus, ...@@ -76,7 +76,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
write_cf8(bus, devfn, reg); write_cf8(bus, devfn, reg);
...@@ -101,7 +101,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus, ...@@ -101,7 +101,7 @@ static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
} }
......
...@@ -162,7 +162,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, ...@@ -162,7 +162,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) if (!value || (bus > 255) || (devfn > 255) || (reg > 255))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
switch (len) { switch (len) {
case 1: case 1:
...@@ -213,7 +213,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus, ...@@ -213,7 +213,7 @@ static int pci_bios_read(unsigned int seg, unsigned int bus,
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return (int)((result & 0xff00) >> 8); return (int)((result & 0xff00) >> 8);
} }
...@@ -228,7 +228,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, ...@@ -228,7 +228,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
if ((bus > 255) || (devfn > 255) || (reg > 255)) if ((bus > 255) || (devfn > 255) || (reg > 255))
return -EINVAL; return -EINVAL;
spin_lock_irqsave(&pci_config_lock, flags); raw_spin_lock_irqsave(&pci_config_lock, flags);
switch (len) { switch (len) {
case 1: case 1:
...@@ -269,7 +269,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus, ...@@ -269,7 +269,7 @@ static int pci_bios_write(unsigned int seg, unsigned int bus,
break; break;
} }
spin_unlock_irqrestore(&pci_config_lock, flags); raw_spin_unlock_irqrestore(&pci_config_lock, flags);
return (int)((result & 0xff00) >> 8); return (int)((result & 0xff00) >> 8);
} }
......
...@@ -294,7 +294,7 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev, ...@@ -294,7 +294,7 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev,
{ {
debugf0("%s()\n", __func__); debugf0("%s()\n", __func__);
/* don't need to call pci_device_enable() */ /* don't need to call pci_enable_device() */
return amd76x_probe1(pdev, ent->driver_data); return amd76x_probe1(pdev, ent->driver_data);
} }
......
...@@ -354,7 +354,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, ...@@ -354,7 +354,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
debugf0("MC: " __FILE__ ": %s()\n", __func__); debugf0("MC: " __FILE__ ": %s()\n", __func__);
/* don't need to call pci_device_enable() */ /* don't need to call pci_enable_device() */
rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data);
if (mci_pdev == NULL) if (mci_pdev == NULL)
......
...@@ -354,7 +354,7 @@ static int __devinit r82600_init_one(struct pci_dev *pdev, ...@@ -354,7 +354,7 @@ static int __devinit r82600_init_one(struct pci_dev *pdev,
{ {
debugf0("%s()\n", __func__); debugf0("%s()\n", __func__);
/* don't need to call pci_device_enable() */ /* don't need to call pci_enable_device() */
return r82600_probe1(pdev, ent->driver_data); return r82600_probe1(pdev, ent->driver_data);
} }
......
...@@ -19,7 +19,7 @@ config PCI_MSI ...@@ -19,7 +19,7 @@ config PCI_MSI
by using the 'pci=nomsi' option. This disables MSI for the by using the 'pci=nomsi' option. This disables MSI for the
entire system. entire system.
If you don't know what to do here, say N. If you don't know what to do here, say Y.
config PCI_DEBUG config PCI_DEBUG
bool "PCI Debugging" bool "PCI Debugging"
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* configuration space. * configuration space.
*/ */
static DEFINE_SPINLOCK(pci_lock); static DEFINE_RAW_SPINLOCK(pci_lock);
/* /*
* Wrappers for all PCI configuration access functions. They just check * Wrappers for all PCI configuration access functions. They just check
...@@ -33,10 +33,10 @@ int pci_bus_read_config_##size \ ...@@ -33,10 +33,10 @@ int pci_bus_read_config_##size \
unsigned long flags; \ unsigned long flags; \
u32 data = 0; \ u32 data = 0; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
spin_lock_irqsave(&pci_lock, flags); \ raw_spin_lock_irqsave(&pci_lock, flags); \
res = bus->ops->read(bus, devfn, pos, len, &data); \ res = bus->ops->read(bus, devfn, pos, len, &data); \
*value = (type)data; \ *value = (type)data; \
spin_unlock_irqrestore(&pci_lock, flags); \ raw_spin_unlock_irqrestore(&pci_lock, flags); \
return res; \ return res; \
} }
...@@ -47,9 +47,9 @@ int pci_bus_write_config_##size \ ...@@ -47,9 +47,9 @@ int pci_bus_write_config_##size \
int res; \ int res; \
unsigned long flags; \ unsigned long flags; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
spin_lock_irqsave(&pci_lock, flags); \ raw_spin_lock_irqsave(&pci_lock, flags); \
res = bus->ops->write(bus, devfn, pos, len, value); \ res = bus->ops->write(bus, devfn, pos, len, value); \
spin_unlock_irqrestore(&pci_lock, flags); \ raw_spin_unlock_irqrestore(&pci_lock, flags); \
return res; \ return res; \
} }
...@@ -79,10 +79,10 @@ struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops) ...@@ -79,10 +79,10 @@ struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
struct pci_ops *old_ops; struct pci_ops *old_ops;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&pci_lock, flags); raw_spin_lock_irqsave(&pci_lock, flags);
old_ops = bus->ops; old_ops = bus->ops;
bus->ops = ops; bus->ops = ops;
spin_unlock_irqrestore(&pci_lock, flags); raw_spin_unlock_irqrestore(&pci_lock, flags);
return old_ops; return old_ops;
} }
EXPORT_SYMBOL(pci_bus_set_ops); EXPORT_SYMBOL(pci_bus_set_ops);
...@@ -136,9 +136,9 @@ static noinline void pci_wait_ucfg(struct pci_dev *dev) ...@@ -136,9 +136,9 @@ static noinline void pci_wait_ucfg(struct pci_dev *dev)
__add_wait_queue(&pci_ucfg_wait, &wait); __add_wait_queue(&pci_ucfg_wait, &wait);
do { do {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&pci_lock); raw_spin_unlock_irq(&pci_lock);
schedule(); schedule();
spin_lock_irq(&pci_lock); raw_spin_lock_irq(&pci_lock);
} while (dev->block_ucfg_access); } while (dev->block_ucfg_access);
__remove_wait_queue(&pci_ucfg_wait, &wait); __remove_wait_queue(&pci_ucfg_wait, &wait);
} }
...@@ -150,11 +150,11 @@ int pci_user_read_config_##size \ ...@@ -150,11 +150,11 @@ int pci_user_read_config_##size \
int ret = 0; \ int ret = 0; \
u32 data = -1; \ u32 data = -1; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
spin_lock_irq(&pci_lock); \ raw_spin_lock_irq(&pci_lock); \
if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
ret = dev->bus->ops->read(dev->bus, dev->devfn, \ ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \ pos, sizeof(type), &data); \
spin_unlock_irq(&pci_lock); \ raw_spin_unlock_irq(&pci_lock); \
*val = (type)data; \ *val = (type)data; \
return ret; \ return ret; \
} }
...@@ -165,11 +165,11 @@ int pci_user_write_config_##size \ ...@@ -165,11 +165,11 @@ int pci_user_write_config_##size \
{ \ { \
int ret = -EIO; \ int ret = -EIO; \
if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \ if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER; \
spin_lock_irq(&pci_lock); \ raw_spin_lock_irq(&pci_lock); \
if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \ if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \ ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \ pos, sizeof(type), val); \
spin_unlock_irq(&pci_lock); \ raw_spin_unlock_irq(&pci_lock); \
return ret; \ return ret; \
} }
...@@ -220,8 +220,13 @@ static int pci_vpd_pci22_wait(struct pci_dev *dev) ...@@ -220,8 +220,13 @@ static int pci_vpd_pci22_wait(struct pci_dev *dev)
return 0; return 0;
} }
if (time_after(jiffies, timeout)) if (time_after(jiffies, timeout)) {
dev_printk(KERN_DEBUG, &dev->dev,
"vpd r/w failed. This is likely a firmware "
"bug on this device. Contact the card "
"vendor for a firmware update.");
return -ETIMEDOUT; return -ETIMEDOUT;
}
if (fatal_signal_pending(current)) if (fatal_signal_pending(current))
return -EINTR; return -EINTR;
if (!cond_resched()) if (!cond_resched())
...@@ -396,10 +401,10 @@ void pci_block_user_cfg_access(struct pci_dev *dev) ...@@ -396,10 +401,10 @@ void pci_block_user_cfg_access(struct pci_dev *dev)
unsigned long flags; unsigned long flags;
int was_blocked; int was_blocked;
spin_lock_irqsave(&pci_lock, flags); raw_spin_lock_irqsave(&pci_lock, flags);
was_blocked = dev->block_ucfg_access; was_blocked = dev->block_ucfg_access;
dev->block_ucfg_access = 1; dev->block_ucfg_access = 1;
spin_unlock_irqrestore(&pci_lock, flags); raw_spin_unlock_irqrestore(&pci_lock, flags);
/* If we BUG() inside the pci_lock, we're guaranteed to hose /* If we BUG() inside the pci_lock, we're guaranteed to hose
* the machine */ * the machine */
...@@ -417,7 +422,7 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev) ...@@ -417,7 +422,7 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&pci_lock, flags); raw_spin_lock_irqsave(&pci_lock, flags);
/* This indicates a problem in the caller, but we don't need /* This indicates a problem in the caller, but we don't need
* to kill them, unlike a double-block above. */ * to kill them, unlike a double-block above. */
...@@ -425,6 +430,6 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev) ...@@ -425,6 +430,6 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev)
dev->block_ucfg_access = 0; dev->block_ucfg_access = 0;
wake_up_all(&pci_ucfg_wait); wake_up_all(&pci_ucfg_wait);
spin_unlock_irqrestore(&pci_lock, flags); raw_spin_unlock_irqrestore(&pci_lock, flags);
} }
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access); EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
...@@ -1075,13 +1075,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1075,13 +1075,12 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* make our own copy of the pci bus structure, /* make our own copy of the pci bus structure,
* as we like tweaking it a lot */ * as we like tweaking it a lot */
ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL); ctrl->pci_bus = kmemdup(pdev->bus, sizeof(*ctrl->pci_bus), GFP_KERNEL);
if (!ctrl->pci_bus) { if (!ctrl->pci_bus) {
err("out of memory\n"); err("out of memory\n");
rc = -ENOMEM; rc = -ENOMEM;
goto err_free_ctrl; goto err_free_ctrl;
} }
memcpy(ctrl->pci_bus, pdev->bus, sizeof(*ctrl->pci_bus));
ctrl->bus = pdev->bus->number; ctrl->bus = pdev->bus->number;
ctrl->rev = pdev->revision; ctrl->rev = pdev->revision;
......
...@@ -84,12 +84,6 @@ int pciehp_configure_device(struct slot *p_slot) ...@@ -84,12 +84,6 @@ int pciehp_configure_device(struct slot *p_slot)
dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); dev = pci_get_slot(parent, PCI_DEVFN(0, fn));
if (!dev) if (!dev)
continue; 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) || if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
pciehp_add_bridge(dev); pciehp_add_bridge(dev);
...@@ -133,15 +127,9 @@ int pciehp_unconfigure_device(struct slot *p_slot) ...@@ -133,15 +127,9 @@ int pciehp_unconfigure_device(struct slot *p_slot)
presence = 0; presence = 0;
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
struct pci_dev* temp = pci_get_slot(parent, PCI_DEVFN(0, j)); struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j));
if (!temp) if (!temp)
continue; 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 && presence) { if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
if (bctl & PCI_BRIDGE_CTL_VGA) { if (bctl & PCI_BRIDGE_CTL_VGA) {
...@@ -149,7 +137,8 @@ int pciehp_unconfigure_device(struct slot *p_slot) ...@@ -149,7 +137,8 @@ int pciehp_unconfigure_device(struct slot *p_slot)
"Cannot remove display device %s\n", "Cannot remove display device %s\n",
pci_name(temp)); pci_name(temp));
pci_dev_put(temp); pci_dev_put(temp);
continue; rc = EINVAL;
break;
} }
} }
pci_remove_bus_device(temp); pci_remove_bus_device(temp);
......
...@@ -979,7 +979,12 @@ static ssize_t reset_store(struct device *dev, ...@@ -979,7 +979,12 @@ static ssize_t reset_store(struct device *dev,
if (val != 1) if (val != 1)
return -EINVAL; return -EINVAL;
return pci_reset_function(pdev);
result = pci_reset_function(pdev);
if (result < 0)
return result;
return count;
} }
static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store); static struct device_attribute reset_attr = __ATTR(reset, 0200, NULL, reset_store);
...@@ -1030,6 +1035,39 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev) ...@@ -1030,6 +1035,39 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
return retval; return retval;
} }
static void pci_remove_slot_links(struct pci_dev *dev)
{
char func[10];
struct pci_slot *slot;
sysfs_remove_link(&dev->dev.kobj, "slot");
list_for_each_entry(slot, &dev->bus->slots, list) {
if (slot->number != PCI_SLOT(dev->devfn))
continue;
snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
sysfs_remove_link(&slot->kobj, func);
}
}
static int pci_create_slot_links(struct pci_dev *dev)
{
int result = 0;
char func[10];
struct pci_slot *slot;
list_for_each_entry(slot, &dev->bus->slots, list) {
if (slot->number != PCI_SLOT(dev->devfn))
continue;
result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
if (result)
goto out;
snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
}
out:
return result;
}
int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
{ {
int retval; int retval;
...@@ -1092,6 +1130,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) ...@@ -1092,6 +1130,8 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
if (retval) if (retval)
goto err_vga_file; goto err_vga_file;
pci_create_slot_links(pdev);
return 0; return 0;
err_vga_file: err_vga_file:
...@@ -1141,6 +1181,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) ...@@ -1141,6 +1181,8 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
if (!sysfs_initialized) if (!sysfs_initialized)
return; return;
pci_remove_slot_links(pdev);
pci_remove_capabilities_sysfs(pdev); pci_remove_capabilities_sysfs(pdev);
if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE) if (pdev->cfg_size < PCI_CFG_SPACE_EXP_SIZE)
......
...@@ -1193,7 +1193,7 @@ void pci_disable_enabled_device(struct pci_dev *dev) ...@@ -1193,7 +1193,7 @@ void pci_disable_enabled_device(struct pci_dev *dev)
* anymore. This only involves disabling PCI bus-mastering, if active. * anymore. This only involves disabling PCI bus-mastering, if active.
* *
* Note we don't actually disable the device until all callers of * Note we don't actually disable the device until all callers of
* pci_device_enable() have called pci_device_disable(). * pci_enable_device() have called pci_disable_device().
*/ */
void void
pci_disable_device(struct pci_dev *dev) pci_disable_device(struct pci_dev *dev)
...@@ -1631,7 +1631,6 @@ void pci_pm_init(struct pci_dev *dev) ...@@ -1631,7 +1631,6 @@ void pci_pm_init(struct pci_dev *dev)
* let the user space enable it to wake up the system as needed. * let the user space enable it to wake up the system as needed.
*/ */
device_set_wakeup_capable(&dev->dev, true); device_set_wakeup_capable(&dev->dev, true);
device_set_wakeup_enable(&dev->dev, false);
/* Disable the PME# generation functionality */ /* Disable the PME# generation functionality */
pci_pme_active(dev, false); pci_pme_active(dev, false);
} else { } else {
...@@ -1655,7 +1654,6 @@ void platform_pci_wakeup_init(struct pci_dev *dev) ...@@ -1655,7 +1654,6 @@ void platform_pci_wakeup_init(struct pci_dev *dev)
return; return;
device_set_wakeup_capable(&dev->dev, true); device_set_wakeup_capable(&dev->dev, true);
device_set_wakeup_enable(&dev->dev, false);
platform_pci_sleep_wake(dev, false); platform_pci_sleep_wake(dev, false);
} }
......
...@@ -168,7 +168,7 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where, ...@@ -168,7 +168,7 @@ static u32 *find_pci_config_dword(struct aer_error *err, int where,
target = &err->root_status; target = &err->root_status;
rw1cs = 1; rw1cs = 1;
break; break;
case PCI_ERR_ROOT_COR_SRC: case PCI_ERR_ROOT_ERR_SRC:
target = &err->source_id; target = &err->source_id;
break; break;
} }
......
...@@ -72,13 +72,120 @@ void pci_no_aer(void) ...@@ -72,13 +72,120 @@ void pci_no_aer(void)
pcie_aer_disable = 1; /* has priority over 'forceload' */ pcie_aer_disable = 1; /* has priority over 'forceload' */
} }
static int set_device_error_reporting(struct pci_dev *dev, void *data)
{
bool enable = *((bool *)data);
if ((dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
(dev->pcie_type == PCI_EXP_TYPE_UPSTREAM) ||
(dev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)) {
if (enable)
pci_enable_pcie_error_reporting(dev);
else
pci_disable_pcie_error_reporting(dev);
}
if (enable)
pcie_set_ecrc_checking(dev);
return 0;
}
/**
* set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports.
* @dev: pointer to root port's pci_dev data structure
* @enable: true = enable error reporting, false = disable error reporting.
*/
static void set_downstream_devices_error_reporting(struct pci_dev *dev,
bool enable)
{
set_device_error_reporting(dev, &enable);
if (!dev->subordinate)
return;
pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
}
/**
* aer_enable_rootport - enable Root Port's interrupts when receiving messages
* @rpc: pointer to a Root Port data structure
*
* Invoked when PCIe bus loads AER service driver.
*/
static void aer_enable_rootport(struct aer_rpc *rpc)
{
struct pci_dev *pdev = rpc->rpd->port;
int pos, aer_pos;
u16 reg16;
u32 reg32;
pos = pci_pcie_cap(pdev);
/* Clear PCIe Capability's Device Status */
pci_read_config_word(pdev, pos+PCI_EXP_DEVSTA, &reg16);
pci_write_config_word(pdev, pos+PCI_EXP_DEVSTA, reg16);
/* Disable system error generation in response to error messages */
pci_read_config_word(pdev, pos + PCI_EXP_RTCTL, &reg16);
reg16 &= ~(SYSTEM_ERROR_INTR_ON_MESG_MASK);
pci_write_config_word(pdev, pos + PCI_EXP_RTCTL, reg16);
aer_pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
/* Clear error status */
pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
/*
* Enable error reporting for the root port device and downstream port
* devices.
*/
set_downstream_devices_error_reporting(pdev, true);
/* Enable Root Port's interrupt in response to error messages */
pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
}
/**
* aer_disable_rootport - disable Root Port's interrupts when receiving messages
* @rpc: pointer to a Root Port data structure
*
* Invoked when PCIe bus unloads AER service driver.
*/
static void aer_disable_rootport(struct aer_rpc *rpc)
{
struct pci_dev *pdev = rpc->rpd->port;
u32 reg32;
int pos;
/*
* Disable error reporting for the root port device and downstream port
* devices.
*/
set_downstream_devices_error_reporting(pdev, false);
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
/* Disable Root's interrupt in response to error messages */
pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
/* Clear Root's error status reg */
pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
}
/** /**
* aer_irq - Root Port's ISR * aer_irq - Root Port's ISR
* @irq: IRQ assigned to Root Port * @irq: IRQ assigned to Root Port
* @context: pointer to Root Port data structure * @context: pointer to Root Port data structure
* *
* Invoked when Root Port detects AER messages. * Invoked when Root Port detects AER messages.
**/ */
irqreturn_t aer_irq(int irq, void *context) irqreturn_t aer_irq(int irq, void *context)
{ {
unsigned int status, id; unsigned int status, id;
...@@ -97,13 +204,13 @@ irqreturn_t aer_irq(int irq, void *context) ...@@ -97,13 +204,13 @@ irqreturn_t aer_irq(int irq, void *context)
/* Read error status */ /* Read error status */
pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status); pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
if (!(status & ROOT_ERR_STATUS_MASKS)) { if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
spin_unlock_irqrestore(&rpc->e_lock, flags); spin_unlock_irqrestore(&rpc->e_lock, flags);
return IRQ_NONE; return IRQ_NONE;
} }
/* Read error source and clear error status */ /* Read error source and clear error status */
pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_COR_SRC, &id); pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status); pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
/* Store error source for later DPC handler */ /* Store error source for later DPC handler */
...@@ -135,7 +242,7 @@ EXPORT_SYMBOL_GPL(aer_irq); ...@@ -135,7 +242,7 @@ EXPORT_SYMBOL_GPL(aer_irq);
* @dev: pointer to the pcie_dev data structure * @dev: pointer to the pcie_dev data structure
* *
* Invoked when Root Port's AER service is loaded. * Invoked when Root Port's AER service is loaded.
**/ */
static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
{ {
struct aer_rpc *rpc; struct aer_rpc *rpc;
...@@ -144,15 +251,11 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) ...@@ -144,15 +251,11 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
if (!rpc) if (!rpc)
return NULL; return NULL;
/* /* Initialize Root lock access, e_lock, to Root Error Status Reg */
* Initialize Root lock access, e_lock, to Root Error Status Reg,
* Root Error ID Reg, and Root error producer/consumer index.
*/
spin_lock_init(&rpc->e_lock); spin_lock_init(&rpc->e_lock);
rpc->rpd = dev; rpc->rpd = dev;
INIT_WORK(&rpc->dpc_handler, aer_isr); INIT_WORK(&rpc->dpc_handler, aer_isr);
rpc->prod_idx = rpc->cons_idx = 0;
mutex_init(&rpc->rpc_mutex); mutex_init(&rpc->rpc_mutex);
init_waitqueue_head(&rpc->wait_release); init_waitqueue_head(&rpc->wait_release);
...@@ -167,7 +270,7 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev) ...@@ -167,7 +270,7 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
* @dev: pointer to the pcie_dev data structure * @dev: pointer to the pcie_dev data structure
* *
* Invoked when PCI Express bus unloads or AER probe fails. * Invoked when PCI Express bus unloads or AER probe fails.
**/ */
static void aer_remove(struct pcie_device *dev) static void aer_remove(struct pcie_device *dev)
{ {
struct aer_rpc *rpc = get_service_data(dev); struct aer_rpc *rpc = get_service_data(dev);
...@@ -179,7 +282,8 @@ static void aer_remove(struct pcie_device *dev) ...@@ -179,7 +282,8 @@ static void aer_remove(struct pcie_device *dev)
wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx); wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
aer_delete_rootport(rpc); aer_disable_rootport(rpc);
kfree(rpc);
set_service_data(dev, NULL); set_service_data(dev, NULL);
} }
} }
...@@ -190,7 +294,7 @@ static void aer_remove(struct pcie_device *dev) ...@@ -190,7 +294,7 @@ static void aer_remove(struct pcie_device *dev)
* @id: pointer to the service id data structure * @id: pointer to the service id data structure
* *
* Invoked when PCI Express bus loads AER service driver. * Invoked when PCI Express bus loads AER service driver.
**/ */
static int __devinit aer_probe(struct pcie_device *dev) static int __devinit aer_probe(struct pcie_device *dev)
{ {
int status; int status;
...@@ -230,47 +334,30 @@ static int __devinit aer_probe(struct pcie_device *dev) ...@@ -230,47 +334,30 @@ static int __devinit aer_probe(struct pcie_device *dev)
* @dev: pointer to Root Port's pci_dev data structure * @dev: pointer to Root Port's pci_dev data structure
* *
* Invoked by Port Bus driver when performing link reset at Root Port. * Invoked by Port Bus driver when performing link reset at Root Port.
**/ */
static pci_ers_result_t aer_root_reset(struct pci_dev *dev) static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
{ {
u16 p2p_ctrl; u32 reg32;
u32 status;
int pos; int pos;
pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
/* Disable Root's interrupt in response to error messages */ /* Disable Root's interrupt in response to error messages */
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, 0); pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
/* Assert Secondary Bus Reset */ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &p2p_ctrl);
p2p_ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
/*
* we should send hot reset message for 2ms to allow it time to
* propogate to all downstream ports
*/
msleep(2);
/* De-assert Secondary Bus Reset */
p2p_ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
pci_write_config_word(dev, PCI_BRIDGE_CONTROL, p2p_ctrl);
/* aer_do_secondary_bus_reset(dev);
* System software must wait for at least 100ms from the end
* of a reset of one or more device before it is permitted
* to issue Configuration Requests to those devices.
*/
msleep(200);
dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n"); dev_printk(KERN_DEBUG, &dev->dev, "Root Port link has been reset\n");
/* Clear Root Error Status */
pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
/* Enable Root Port's interrupt in response to error messages */ /* Enable Root Port's interrupt in response to error messages */
pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status); pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status); reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
pci_write_config_dword(dev, pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
pos + PCI_ERR_ROOT_COMMAND,
ROOT_PORT_INTR_ON_MESG_MASK);
return PCI_ERS_RESULT_RECOVERED; return PCI_ERS_RESULT_RECOVERED;
} }
...@@ -281,7 +368,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev) ...@@ -281,7 +368,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
* @error: error severity being notified by port bus * @error: error severity being notified by port bus
* *
* Invoked by Port Bus driver during error recovery. * Invoked by Port Bus driver during error recovery.
**/ */
static pci_ers_result_t aer_error_detected(struct pci_dev *dev, static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
enum pci_channel_state error) enum pci_channel_state error)
{ {
...@@ -294,7 +381,7 @@ static pci_ers_result_t aer_error_detected(struct pci_dev *dev, ...@@ -294,7 +381,7 @@ static pci_ers_result_t aer_error_detected(struct pci_dev *dev,
* @dev: pointer to Root Port's pci_dev data structure * @dev: pointer to Root Port's pci_dev data structure
* *
* Invoked by Port Bus driver during nonfatal recovery. * Invoked by Port Bus driver during nonfatal recovery.
**/ */
static void aer_error_resume(struct pci_dev *dev) static void aer_error_resume(struct pci_dev *dev)
{ {
int pos; int pos;
...@@ -321,7 +408,7 @@ static void aer_error_resume(struct pci_dev *dev) ...@@ -321,7 +408,7 @@ static void aer_error_resume(struct pci_dev *dev)
* aer_service_init - register AER root service driver * aer_service_init - register AER root service driver
* *
* Invoked when AER root service driver is loaded. * Invoked when AER root service driver is loaded.
**/ */
static int __init aer_service_init(void) static int __init aer_service_init(void)
{ {
if (pcie_aer_disable) if (pcie_aer_disable)
...@@ -335,7 +422,7 @@ static int __init aer_service_init(void) ...@@ -335,7 +422,7 @@ static int __init aer_service_init(void)
* aer_service_exit - unregister AER root service driver * aer_service_exit - unregister AER root service driver
* *
* Invoked when AER root service driver is unloaded. * Invoked when AER root service driver is unloaded.
**/ */
static void __exit aer_service_exit(void) static void __exit aer_service_exit(void)
{ {
pcie_port_service_unregister(&aerdriver); pcie_port_service_unregister(&aerdriver);
......
...@@ -17,9 +17,6 @@ ...@@ -17,9 +17,6 @@
#define AER_FATAL 1 #define AER_FATAL 1
#define AER_CORRECTABLE 2 #define AER_CORRECTABLE 2
/* Root Error Status Register Bits */
#define ROOT_ERR_STATUS_MASKS 0x0f
#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \ #define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
PCI_EXP_RTCTL_SENFEE| \ PCI_EXP_RTCTL_SENFEE| \
PCI_EXP_RTCTL_SEFEE) PCI_EXP_RTCTL_SEFEE)
...@@ -117,8 +114,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig, ...@@ -117,8 +114,7 @@ static inline pci_ers_result_t merge_result(enum pci_ers_result orig,
} }
extern struct bus_type pcie_port_bus_type; extern struct bus_type pcie_port_bus_type;
extern void aer_enable_rootport(struct aer_rpc *rpc); extern void aer_do_secondary_bus_reset(struct pci_dev *dev);
extern void aer_delete_rootport(struct aer_rpc *rpc);
extern int aer_init(struct pcie_device *dev); extern int aer_init(struct pcie_device *dev);
extern void aer_isr(struct work_struct *work); extern void aer_isr(struct work_struct *work);
extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info); extern void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
......
This diff is collapsed.
...@@ -2127,6 +2127,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x9602, quirk_disable_msi); ...@@ -2127,6 +2127,7 @@ 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_ASUSTEK, 0x9602, quirk_disable_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AI, 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_VIA, 0xa238, quirk_disable_msi);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x5a3f, quirk_disable_msi);
/* Go through the list of Hypertransport capabilities and /* Go through the list of Hypertransport capabilities and
* return 1 if a HT MSI capability is found and enabled */ * return 1 if a HT MSI capability is found and enabled */
...@@ -2218,15 +2219,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS, ...@@ -2218,15 +2219,16 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SERVERWORKS,
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE, DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8132_BRIDGE,
ht_enable_msi_mapping); ht_enable_msi_mapping);
/* The P5N32-SLI Premium motherboard from Asus has a problem with msi /* The P5N32-SLI motherboards from Asus have a problem with msi
* for the MCP55 NIC. It is not yet determined whether the msi problem * for the MCP55 NIC. It is not yet determined whether the msi problem
* also affects other devices. As for now, turn off msi for this device. * also affects other devices. As for now, turn off msi for this device.
*/ */
static void __devinit nvenet_msi_disable(struct pci_dev *dev) static void __devinit nvenet_msi_disable(struct pci_dev *dev)
{ {
if (dmi_name_in_vendors("P5N32-SLI PREMIUM")) { if (dmi_name_in_vendors("P5N32-SLI PREMIUM") ||
dmi_name_in_vendors("P5N32-E SLI")) {
dev_info(&dev->dev, dev_info(&dev->dev,
"Disabling msi for MCP55 NIC on P5N32-SLI Premium\n"); "Disabling msi for MCP55 NIC on P5N32-SLI\n");
dev->no_msi = 1; dev->no_msi = 1;
} }
} }
...@@ -2552,6 +2554,19 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov); ...@@ -2552,6 +2554,19 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov);
#endif /* CONFIG_PCI_IOV */ #endif /* CONFIG_PCI_IOV */
/* Allow manual resource allocation for PCI hotplug bridges
* via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
* some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6),
* kernel fails to allocate resources when hotplug device is
* inserted and PCI bus is rescanned.
*/
static void __devinit quirk_hotplug_bridge(struct pci_dev *dev)
{
dev->is_hotplug_bridge = 1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0020, quirk_hotplug_bridge);
/* /*
* This is a quirk for the Ricoh MMC controller found as a part of * This is a quirk for the Ricoh MMC controller found as a part of
* some mulifunction chips. * some mulifunction chips.
......
...@@ -97,6 +97,50 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf) ...@@ -97,6 +97,50 @@ static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
return bus_speed_read(slot->bus->cur_bus_speed, buf); return bus_speed_read(slot->bus->cur_bus_speed, buf);
} }
static void remove_sysfs_files(struct pci_slot *slot)
{
char func[10];
struct list_head *tmp;
list_for_each(tmp, &slot->bus->devices) {
struct pci_dev *dev = pci_dev_b(tmp);
if (PCI_SLOT(dev->devfn) != slot->number)
continue;
sysfs_remove_link(&dev->dev.kobj, "slot");
snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
sysfs_remove_link(&slot->kobj, func);
}
}
static int create_sysfs_files(struct pci_slot *slot)
{
int result;
char func[10];
struct list_head *tmp;
list_for_each(tmp, &slot->bus->devices) {
struct pci_dev *dev = pci_dev_b(tmp);
if (PCI_SLOT(dev->devfn) != slot->number)
continue;
result = sysfs_create_link(&dev->dev.kobj, &slot->kobj, "slot");
if (result)
goto fail;
snprintf(func, 10, "function%d", PCI_FUNC(dev->devfn));
result = sysfs_create_link(&slot->kobj, &dev->dev.kobj, func);
if (result)
goto fail;
}
return 0;
fail:
remove_sysfs_files(slot);
return result;
}
static void pci_slot_release(struct kobject *kobj) static void pci_slot_release(struct kobject *kobj)
{ {
struct pci_dev *dev; struct pci_dev *dev;
...@@ -109,6 +153,8 @@ static void pci_slot_release(struct kobject *kobj) ...@@ -109,6 +153,8 @@ static void pci_slot_release(struct kobject *kobj)
if (PCI_SLOT(dev->devfn) == slot->number) if (PCI_SLOT(dev->devfn) == slot->number)
dev->slot = NULL; dev->slot = NULL;
remove_sysfs_files(slot);
list_del(&slot->list); list_del(&slot->list);
kfree(slot); kfree(slot);
...@@ -300,6 +346,8 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, ...@@ -300,6 +346,8 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
INIT_LIST_HEAD(&slot->list); INIT_LIST_HEAD(&slot->list);
list_add(&slot->list, &parent->slots); list_add(&slot->list, &parent->slots);
create_sysfs_files(slot);
list_for_each_entry(dev, &parent->devices, bus_list) list_for_each_entry(dev, &parent->devices, bus_list)
if (PCI_SLOT(dev->devfn) == slot_nr) if (PCI_SLOT(dev->devfn) == slot_nr)
dev->slot = slot; dev->slot = slot;
......
...@@ -52,6 +52,7 @@ struct resource_list { ...@@ -52,6 +52,7 @@ struct resource_list {
#define IORESOURCE_MEM_64 0x00100000 #define IORESOURCE_MEM_64 0x00100000
#define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */ #define IORESOURCE_WINDOW 0x00200000 /* forwarded by bridge */
#define IORESOURCE_MUXED 0x00400000 /* Resource is software muxed */
#define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */ #define IORESOURCE_EXCLUSIVE 0x08000000 /* Userland may not map this resource */
#define IORESOURCE_DISABLED 0x10000000 #define IORESOURCE_DISABLED 0x10000000
...@@ -144,6 +145,7 @@ static inline unsigned long resource_type(const struct resource *res) ...@@ -144,6 +145,7 @@ static inline unsigned long resource_type(const struct resource *res)
/* Convenience shorthand with allocation */ /* Convenience shorthand with allocation */
#define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0) #define request_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), 0)
#define request_muxed_region(start,n,name) __request_region(&ioport_resource, (start), (n), (name), IORESOURCE_MUXED)
#define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl) #define __request_mem_region(start,n,name, excl) __request_region(&iomem_resource, (start), (n), (name), excl)
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0) #define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)
#define request_mem_region_exclusive(start,n,name) \ #define request_mem_region_exclusive(start,n,name) \
......
...@@ -2419,8 +2419,8 @@ ...@@ -2419,8 +2419,8 @@
#define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30
#define PCI_DEVICE_ID_INTEL_IOAT 0x1a38 #define PCI_DEVICE_ID_INTEL_IOAT 0x1a38
#define PCI_DEVICE_ID_INTEL_CPT_SMBUS 0x1c22 #define PCI_DEVICE_ID_INTEL_CPT_SMBUS 0x1c22
#define PCI_DEVICE_ID_INTEL_CPT_LPC1 0x1c42 #define PCI_DEVICE_ID_INTEL_CPT_LPC_MIN 0x1c41
#define PCI_DEVICE_ID_INTEL_CPT_LPC2 0x1c43 #define PCI_DEVICE_ID_INTEL_CPT_LPC_MAX 0x1c5f
#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 #define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410
#define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411 #define PCI_DEVICE_ID_INTEL_82801AA_1 0x2411
#define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413 #define PCI_DEVICE_ID_INTEL_82801AA_3 0x2413
......
...@@ -566,8 +566,7 @@ ...@@ -566,8 +566,7 @@
#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */ #define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */
#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */ #define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */
#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */ #define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
#define PCI_ERR_ROOT_COR_SRC 52 #define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */
#define PCI_ERR_ROOT_SRC 54
/* Virtual Channel */ /* Virtual Channel */
#define PCI_VC_PORT_REG1 4 #define PCI_VC_PORT_REG1 4
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/pfn.h> #include <linux/pfn.h>
...@@ -681,6 +682,8 @@ resource_size_t resource_alignment(struct resource *res) ...@@ -681,6 +682,8 @@ resource_size_t resource_alignment(struct resource *res)
* release_region releases a matching busy region. * release_region releases a matching busy region.
*/ */
static DECLARE_WAIT_QUEUE_HEAD(muxed_resource_wait);
/** /**
* __request_region - create a new busy resource region * __request_region - create a new busy resource region
* @parent: parent resource descriptor * @parent: parent resource descriptor
...@@ -693,6 +696,7 @@ struct resource * __request_region(struct resource *parent, ...@@ -693,6 +696,7 @@ struct resource * __request_region(struct resource *parent,
resource_size_t start, resource_size_t n, resource_size_t start, resource_size_t n,
const char *name, int flags) const char *name, int flags)
{ {
DECLARE_WAITQUEUE(wait, current);
struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL); struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
if (!res) if (!res)
...@@ -717,7 +721,15 @@ struct resource * __request_region(struct resource *parent, ...@@ -717,7 +721,15 @@ struct resource * __request_region(struct resource *parent,
if (!(conflict->flags & IORESOURCE_BUSY)) if (!(conflict->flags & IORESOURCE_BUSY))
continue; continue;
} }
if (conflict->flags & flags & IORESOURCE_MUXED) {
add_wait_queue(&muxed_resource_wait, &wait);
write_unlock(&resource_lock);
set_current_state(TASK_UNINTERRUPTIBLE);
schedule();
remove_wait_queue(&muxed_resource_wait, &wait);
write_lock(&resource_lock);
continue;
}
/* Uhhuh, that didn't work out.. */ /* Uhhuh, that didn't work out.. */
kfree(res); kfree(res);
res = NULL; res = NULL;
...@@ -791,6 +803,8 @@ void __release_region(struct resource *parent, resource_size_t start, ...@@ -791,6 +803,8 @@ void __release_region(struct resource *parent, resource_size_t start,
break; break;
*p = res->sibling; *p = res->sibling;
write_unlock(&resource_lock); write_unlock(&resource_lock);
if (res->flags & IORESOURCE_MUXED)
wake_up(&muxed_resource_wait);
kfree(res); kfree(res);
return; return;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment