diff options
author | Zhang, Yanmin <yanmin_zhang@linux.intel.com> | 2009-06-16 09:34:38 +0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-06-17 01:30:13 +0400 |
commit | 70298c6e6c1ba68346336b4ea54bd5c0abbf73c8 (patch) | |
tree | 363d0a784d8a28688c0fda006279563a7fd3629b /drivers/pci/bus.c | |
parent | a6c0d5c6ebb3d988b1f18a1612b5188f3f555637 (diff) | |
download | linux-70298c6e6c1ba68346336b4ea54bd5c0abbf73c8.tar.xz |
PCI AER: support Multiple Error Received and no error source id
Based on PCI Express AER specs, a root port might receive multiple
TLP errors while it could only save a correctable error source id
and an uncorrectable error source id at the same time. In addition,
some root port hardware might be unable to provide a correct source
id, i.e., the source id, or the bus id part of the source id provided
by root port might be equal to 0.
The patchset implements the support in kernel by searching the device
tree under the root port.
Patch 1 changes parameter cb of function pci_walk_bus to return a value.
When cb return non-zero, pci_walk_bus stops more searching on the
device tree.
Reviewed-by: Andrew Patterson <andrew.patterson@hp.com>
Signed-off-by: Zhang Yanmin <yanmin_zhang@linux.intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/bus.c')
-rw-r--r-- | drivers/pci/bus.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 40af27f31043..cef28a79103f 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -206,13 +206,18 @@ void pci_enable_bridges(struct pci_bus *bus) * Walk the given bus, including any bridged devices * on buses under this bus. Call the provided callback * on each device found. + * + * We check the return of @cb each time. If it returns anything + * other than 0, we break out. + * */ -void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), +void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *), void *userdata) { struct pci_dev *dev; struct pci_bus *bus; struct list_head *next; + int retval; bus = top; down_read(&pci_bus_sem); @@ -236,8 +241,10 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), /* Run device routines with the device locked */ down(&dev->dev.sem); - cb(dev, userdata); + retval = cb(dev, userdata); up(&dev->dev.sem); + if (retval) + break; } up_read(&pci_bus_sem); } |