Skip to content

Commit

Permalink
Merge branch 'linux-next' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/jbarnes/pci-2.6

* 'linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (74 commits)
  PCI: make msi_free_irqs() to use msix_mask_irq() instead of open coded write
  PCI: Fix the NIU MSI-X problem in a better way
  PCI ASPM: remove get_root_port_link
  PCI ASPM: cleanup pcie_aspm_sanity_check
  PCI ASPM: remove has_switch field
  PCI ASPM: cleanup calc_Lx_latency
  PCI ASPM: cleanup pcie_aspm_get_cap_device
  PCI ASPM: cleanup clkpm checks
  PCI ASPM: cleanup __pcie_aspm_check_state_one
  PCI ASPM: cleanup initialization
  PCI ASPM: cleanup change input argument of aspm functions
  PCI ASPM: cleanup misc in struct pcie_link_state
  PCI ASPM: cleanup clkpm state in struct pcie_link_state
  PCI ASPM: cleanup latency field in struct pcie_link_state
  PCI ASPM: cleanup aspm state field in struct pcie_link_state
  PCI ASPM: fix typo in struct pcie_link_state
  PCI: drivers/pci/slot.c should depend on CONFIG_SYSFS
  PCI: remove redundant __msi_set_enable()
  PCI PM: consistently use type bool for wake enable variable
  x86/ACPI: Correct maximum allowed _CRS returned resources and warn if exceeded
  ...
  • Loading branch information
Linus Torvalds committed Jun 22, 2009
2 parents 5165aec + 2af5066 commit 59ef7a8
Show file tree
Hide file tree
Showing 55 changed files with 3,038 additions and 2,201 deletions.
7 changes: 7 additions & 0 deletions Documentation/ABI/testing/sysfs-bus-pci
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,10 @@ Description:
This symbolic link appears when a device is a Virtual Function.
The symbolic link points to the PCI device sysfs entry of the
Physical Function this device associates with.

What: /sys/bus/pci/slots/.../module
Date: June 2009
Contact: linux-pci@vger.kernel.org
Description:
This symbolic link points to the PCI hotplug controller driver
module that manages the hotplug slot.
25 changes: 25 additions & 0 deletions Documentation/PCI/pcieaer-howto.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ be initiated although firmwares have no _OSC support. To enable the
walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line
when booting kernel. Note that forceload=n by default.

nosourceid, another parameter of type bool, can be used when broken
hardware (mostly chipsets) has root ports that cannot obtain the reporting
source ID. nosourceid=n by default.

2.3 AER error output
When a PCI-E AER error is captured, an error message will be outputed to
console. If it's a correctable error, it is outputed as a warning.
Expand Down Expand Up @@ -246,3 +250,24 @@ with the PCI Express AER Root driver?
A: It could call the helper functions to enable AER in devices and
cleanup uncorrectable status register. Pls. refer to section 3.3.


4. Software error injection

Debugging PCIE AER error recovery code is quite difficult because it
is hard to trigger real hardware errors. Software based error
injection can be used to fake various kinds of PCIE errors.

First you should enable PCIE AER software error injection in kernel
configuration, that is, following item should be in your .config.

CONFIG_PCIEAER_INJECT=y or CONFIG_PCIEAER_INJECT=m

After reboot with new kernel or insert the module, a device file named
/dev/aer_inject should be created.

Then, you need a user space tool named aer-inject, which can be gotten
from:
http://www.kernel.org/pub/linux/utils/pci/aer-inject/

More information about aer-inject can be found in the document comes
with its source code.
11 changes: 10 additions & 1 deletion Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1776,6 +1776,9 @@ and is between 256 and 4096 characters. It is defined in the file
root domains (aka PCI segments, in ACPI-speak).
nommconf [X86] Disable use of MMCONFIG for PCI
Configuration
check_enable_amd_mmconf [X86] check for and enable
properly configured MMIO access to PCI
config space on AMD family 10h CPU
nomsi [MSI] If the PCI_MSI kernel config parameter is
enabled, this kernel boot option can be used to
disable the use of MSI interrupts system-wide.
Expand Down Expand Up @@ -1828,7 +1831,7 @@ and is between 256 and 4096 characters. It is defined in the file
IRQ routing is enabled.
noacpi [X86] Do not use ACPI for IRQ routing
or for PCI scanning.
use_crs [X86] Use _CRS for PCI resource
nocrs [X86] Don't use _CRS for PCI resource
allocation.
routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(),
Expand Down Expand Up @@ -1865,6 +1868,12 @@ and is between 256 and 4096 characters. It is defined in the file
PAGE_SIZE is used as alignment.
PCI-PCI bridge can be specified, if resource
windows need to be expanded.
ecrc= Enable/disable PCIe ECRC (transaction layer
end-to-end CRC checking).
bios: Use BIOS/firmware settings. This is the
the default.
off: Turn ECRC off
on: Turn ECRC on.

pcie_aspm= [PCIE] Forcibly enable or disable PCIe Active State Power
Management.
Expand Down
38 changes: 24 additions & 14 deletions arch/powerpc/platforms/pseries/eeh_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,29 @@ static void eeh_enable_irq(struct pci_dev *dev)
* passed back in "userdata".
*/

static void eeh_report_error(struct pci_dev *dev, void *userdata)
static int eeh_report_error(struct pci_dev *dev, void *userdata)
{
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver;

dev->error_state = pci_channel_io_frozen;

if (!driver)
return;
return 0;

eeh_disable_irq(dev);

if (!driver->err_handler ||
!driver->err_handler->error_detected)
return;
return 0;

rc = driver->err_handler->error_detected (dev, pci_channel_io_frozen);

/* A driver that needs a reset trumps all others */
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *res = rc;

return 0;
}

/**
Expand All @@ -153,70 +155,76 @@ static void eeh_report_error(struct pci_dev *dev, void *userdata)
* Cumulative response passed back in "userdata".
*/

static void eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata)
{
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver;

if (!driver ||
!driver->err_handler ||
!driver->err_handler->mmio_enabled)
return;
return 0;

rc = driver->err_handler->mmio_enabled (dev);

/* A driver that needs a reset trumps all others */
if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;
if (*res == PCI_ERS_RESULT_NONE) *res = rc;

return 0;
}

/**
* eeh_report_reset - tell device that slot has been reset
*/

static void eeh_report_reset(struct pci_dev *dev, void *userdata)
static int eeh_report_reset(struct pci_dev *dev, void *userdata)
{
enum pci_ers_result rc, *res = userdata;
struct pci_driver *driver = dev->driver;

if (!driver)
return;
return 0;

dev->error_state = pci_channel_io_normal;

eeh_enable_irq(dev);

if (!driver->err_handler ||
!driver->err_handler->slot_reset)
return;
return 0;

rc = driver->err_handler->slot_reset(dev);
if ((*res == PCI_ERS_RESULT_NONE) ||
(*res == PCI_ERS_RESULT_RECOVERED)) *res = rc;
if (*res == PCI_ERS_RESULT_DISCONNECT &&
rc == PCI_ERS_RESULT_NEED_RESET) *res = rc;

return 0;
}

/**
* eeh_report_resume - tell device to resume normal operations
*/

static void eeh_report_resume(struct pci_dev *dev, void *userdata)
static int eeh_report_resume(struct pci_dev *dev, void *userdata)
{
struct pci_driver *driver = dev->driver;

dev->error_state = pci_channel_io_normal;

if (!driver)
return;
return 0;

eeh_enable_irq(dev);

if (!driver->err_handler ||
!driver->err_handler->resume)
return;
return 0;

driver->err_handler->resume(dev);

return 0;
}

/**
Expand All @@ -226,22 +234,24 @@ static void eeh_report_resume(struct pci_dev *dev, void *userdata)
* dead, and that no further recovery attempts will be made on it.
*/

static void eeh_report_failure(struct pci_dev *dev, void *userdata)
static int eeh_report_failure(struct pci_dev *dev, void *userdata)
{
struct pci_driver *driver = dev->driver;

dev->error_state = pci_channel_io_perm_failure;

if (!driver)
return;
return 0;

eeh_disable_irq(dev);

if (!driver->err_handler ||
!driver->err_handler->error_detected)
return;
return 0;

driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);

return 0;
}

/* ------------------------------------------------------- */
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ extern void pci_iommu_alloc(void);

/* generic pci stuff */
#include <asm-generic/pci.h>
#define PCIBIOS_MAX_MEM_32 0xffffffff

#ifdef CONFIG_NUMA
/* Returns the node based on pci bus */
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/include/asm/pci_x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#define PCI_BIOS_IRQ_SCAN 0x2000
#define PCI_ASSIGN_ALL_BUSSES 0x4000
#define PCI_CAN_SKIP_ISA_ALIGN 0x8000
#define PCI_USE__CRS 0x10000
#define PCI_NO_ROOT_CRS 0x10000
#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000
#define PCI_HAS_IO_ECS 0x40000
#define PCI_NOASSIGN_ROMS 0x80000
Expand Down
35 changes: 28 additions & 7 deletions arch/x86/pci/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,26 @@ count_resource(struct acpi_resource *acpi_res, void *data)
struct acpi_resource_address64 addr;
acpi_status status;

if (info->res_num >= PCI_BUS_NUM_RESOURCES)
return AE_OK;

status = resource_to_addr(acpi_res, &addr);
if (ACPI_SUCCESS(status))
info->res_num++;
return AE_OK;
}

static int
bus_has_transparent_bridge(struct pci_bus *bus)
{
struct pci_dev *dev;

list_for_each_entry(dev, &bus->devices, bus_list) {
u16 class = dev->class >> 8;

if (class == PCI_CLASS_BRIDGE_PCI && dev->transparent)
return true;
}
return false;
}

static acpi_status
setup_resource(struct acpi_resource *acpi_res, void *data)
{
Expand All @@ -56,9 +67,7 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
acpi_status status;
unsigned long flags;
struct resource *root;

if (info->res_num >= PCI_BUS_NUM_RESOURCES)
return AE_OK;
int max_root_bus_resources = PCI_BUS_NUM_RESOURCES;

status = resource_to_addr(acpi_res, &addr);
if (!ACPI_SUCCESS(status))
Expand All @@ -82,6 +91,18 @@ setup_resource(struct acpi_resource *acpi_res, void *data)
res->end = res->start + addr.address_length - 1;
res->child = NULL;

if (bus_has_transparent_bridge(info->bus))
max_root_bus_resources -= 3;
if (info->res_num >= max_root_bus_resources) {
printk(KERN_WARNING "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s due to _CRS returning more than "
"%d resource descriptors\n", (unsigned long) res->start,
(unsigned long) res->end, root->name, info->name,
max_root_bus_resources);
info->res_num++;
return AE_OK;
}

if (insert_resource(root, res)) {
printk(KERN_ERR "PCI: Failed to allocate 0x%lx-0x%lx "
"from %s for %s\n", (unsigned long) res->start,
Expand Down Expand Up @@ -217,7 +238,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
#endif
}

if (bus && (pci_probe & PCI_USE__CRS))
if (bus && !(pci_probe & PCI_NO_ROOT_CRS))
get_current_resources(device, busnum, domain, bus);
return bus;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/pci/amd_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void x86_pci_root_bus_res_quirks(struct pci_bus *b)
struct pci_root_info *info;

/* don't go for it if _CRS is used */
if (pci_probe & PCI_USE__CRS)
if (!(pci_probe & PCI_NO_ROOT_CRS))
return;

/* if only one root bus, don't need to anything */
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/pci/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,8 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL;
} else if (!strcmp(str, "use_crs")) {
pci_probe |= PCI_USE__CRS;
} else if (!strcmp(str, "nocrs")) {
pci_probe |= PCI_NO_ROOT_CRS;
return NULL;
} else if (!strcmp(str, "earlydump")) {
pci_early_dump_regs = 1;
Expand Down
1 change: 1 addition & 0 deletions drivers/acpi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ config ACPI_DEBUG_FUNC_TRACE

config ACPI_PCI_SLOT
tristate "PCI slot detection driver"
depends on SYSFS
default n
help
This driver creates entries in /sys/bus/pci/slots/ for all PCI
Expand Down
3 changes: 2 additions & 1 deletion drivers/pci/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
# Makefile for the PCI bus specific drivers.
#

obj-y += access.o bus.o probe.o remove.o pci.o quirks.o slot.o \
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o

# Build PCI Express stuff if needed
obj-$(CONFIG_PCIEPORTBUS) += pcie/
Expand Down
19 changes: 19 additions & 0 deletions drivers/pci/access.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,25 @@ EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);

/**
* pci_bus_set_ops - Set raw operations of pci bus
* @bus: pci bus struct
* @ops: new raw operations
*
* Return previous raw operations
*/
struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops)
{
struct pci_ops *old_ops;
unsigned long flags;

spin_lock_irqsave(&pci_lock, flags);
old_ops = bus->ops;
bus->ops = ops;
spin_unlock_irqrestore(&pci_lock, flags);
return old_ops;
}
EXPORT_SYMBOL(pci_bus_set_ops);

/**
* pci_read_vpd - Read one entry from Vital Product Data
Expand Down
Loading

0 comments on commit 59ef7a8

Please sign in to comment.