aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorZhang, Yanmin <yanmin_zhang@linux.intel.com>2009-06-16 01:34:38 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-16 17:30:13 -0400
commit70298c6e6c1ba68346336b4ea54bd5c0abbf73c8 (patch)
tree363d0a784d8a28688c0fda006279563a7fd3629b /drivers
parenta6c0d5c6ebb3d988b1f18a1612b5188f3f555637 (diff)
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')
-rw-r--r--drivers/pci/bus.c11
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c30
2 files changed, 25 insertions, 16 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)
206 * Walk the given bus, including any bridged devices 206 * Walk the given bus, including any bridged devices
207 * on buses under this bus. Call the provided callback 207 * on buses under this bus. Call the provided callback
208 * on each device found. 208 * on each device found.
209 *
210 * We check the return of @cb each time. If it returns anything
211 * other than 0, we break out.
212 *
209 */ 213 */
210void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *), 214void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
211 void *userdata) 215 void *userdata)
212{ 216{
213 struct pci_dev *dev; 217 struct pci_dev *dev;
214 struct pci_bus *bus; 218 struct pci_bus *bus;
215 struct list_head *next; 219 struct list_head *next;
220 int retval;
216 221
217 bus = top; 222 bus = top;
218 down_read(&pci_bus_sem); 223 down_read(&pci_bus_sem);
@@ -236,8 +241,10 @@ void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
236 241
237 /* Run device routines with the device locked */ 242 /* Run device routines with the device locked */
238 down(&dev->dev.sem); 243 down(&dev->dev.sem);
239 cb(dev, userdata); 244 retval = cb(dev, userdata);
240 up(&dev->dev.sem); 245 up(&dev->dev.sem);
246 if (retval)
247 break;
241 } 248 }
242 up_read(&pci_bus_sem); 249 up_read(&pci_bus_sem);
243} 250}
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index dd3829e68e3f..a7a3919904bb 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -109,7 +109,7 @@ int pci_cleanup_aer_correct_error_status(struct pci_dev *dev)
109#endif /* 0 */ 109#endif /* 0 */
110 110
111 111
112static void set_device_error_reporting(struct pci_dev *dev, void *data) 112static int set_device_error_reporting(struct pci_dev *dev, void *data)
113{ 113{
114 bool enable = *((bool *)data); 114 bool enable = *((bool *)data);
115 115
@@ -124,6 +124,8 @@ static void set_device_error_reporting(struct pci_dev *dev, void *data)
124 124
125 if (enable) 125 if (enable)
126 pcie_set_ecrc_checking(dev); 126 pcie_set_ecrc_checking(dev);
127
128 return 0;
127} 129}
128 130
129/** 131/**
@@ -207,7 +209,7 @@ static struct device* find_source_device(struct pci_dev *parent, u16 id)
207 return NULL; 209 return NULL;
208} 210}
209 211
210static void report_error_detected(struct pci_dev *dev, void *data) 212static int report_error_detected(struct pci_dev *dev, void *data)
211{ 213{
212 pci_ers_result_t vote; 214 pci_ers_result_t vote;
213 struct pci_error_handlers *err_handler; 215 struct pci_error_handlers *err_handler;
@@ -232,16 +234,16 @@ static void report_error_detected(struct pci_dev *dev, void *data)
232 dev->driver ? 234 dev->driver ?
233 "no AER-aware driver" : "no driver"); 235 "no AER-aware driver" : "no driver");
234 } 236 }
235 return; 237 return 0;
236 } 238 }
237 239
238 err_handler = dev->driver->err_handler; 240 err_handler = dev->driver->err_handler;
239 vote = err_handler->error_detected(dev, result_data->state); 241 vote = err_handler->error_detected(dev, result_data->state);
240 result_data->result = merge_result(result_data->result, vote); 242 result_data->result = merge_result(result_data->result, vote);
241 return; 243 return 0;
242} 244}
243 245
244static void report_mmio_enabled(struct pci_dev *dev, void *data) 246static int report_mmio_enabled(struct pci_dev *dev, void *data)
245{ 247{
246 pci_ers_result_t vote; 248 pci_ers_result_t vote;
247 struct pci_error_handlers *err_handler; 249 struct pci_error_handlers *err_handler;
@@ -251,15 +253,15 @@ static void report_mmio_enabled(struct pci_dev *dev, void *data)
251 if (!dev->driver || 253 if (!dev->driver ||
252 !dev->driver->err_handler || 254 !dev->driver->err_handler ||
253 !dev->driver->err_handler->mmio_enabled) 255 !dev->driver->err_handler->mmio_enabled)
254 return; 256 return 0;
255 257
256 err_handler = dev->driver->err_handler; 258 err_handler = dev->driver->err_handler;
257 vote = err_handler->mmio_enabled(dev); 259 vote = err_handler->mmio_enabled(dev);
258 result_data->result = merge_result(result_data->result, vote); 260 result_data->result = merge_result(result_data->result, vote);
259 return; 261 return 0;
260} 262}
261 263
262static void report_slot_reset(struct pci_dev *dev, void *data) 264static int report_slot_reset(struct pci_dev *dev, void *data)
263{ 265{
264 pci_ers_result_t vote; 266 pci_ers_result_t vote;
265 struct pci_error_handlers *err_handler; 267 struct pci_error_handlers *err_handler;
@@ -269,15 +271,15 @@ static void report_slot_reset(struct pci_dev *dev, void *data)
269 if (!dev->driver || 271 if (!dev->driver ||
270 !dev->driver->err_handler || 272 !dev->driver->err_handler ||
271 !dev->driver->err_handler->slot_reset) 273 !dev->driver->err_handler->slot_reset)
272 return; 274 return 0;
273 275
274 err_handler = dev->driver->err_handler; 276 err_handler = dev->driver->err_handler;
275 vote = err_handler->slot_reset(dev); 277 vote = err_handler->slot_reset(dev);
276 result_data->result = merge_result(result_data->result, vote); 278 result_data->result = merge_result(result_data->result, vote);
277 return; 279 return 0;
278} 280}
279 281
280static void report_resume(struct pci_dev *dev, void *data) 282static int report_resume(struct pci_dev *dev, void *data)
281{ 283{
282 struct pci_error_handlers *err_handler; 284 struct pci_error_handlers *err_handler;
283 285
@@ -286,11 +288,11 @@ static void report_resume(struct pci_dev *dev, void *data)
286 if (!dev->driver || 288 if (!dev->driver ||
287 !dev->driver->err_handler || 289 !dev->driver->err_handler ||
288 !dev->driver->err_handler->resume) 290 !dev->driver->err_handler->resume)
289 return; 291 return 0;
290 292
291 err_handler = dev->driver->err_handler; 293 err_handler = dev->driver->err_handler;
292 err_handler->resume(dev); 294 err_handler->resume(dev);
293 return; 295 return 0;
294} 296}
295 297
296/** 298/**
@@ -307,7 +309,7 @@ static void report_resume(struct pci_dev *dev, void *data)
307static pci_ers_result_t broadcast_error_message(struct pci_dev *dev, 309static pci_ers_result_t broadcast_error_message(struct pci_dev *dev,
308 enum pci_channel_state state, 310 enum pci_channel_state state,
309 char *error_mesg, 311 char *error_mesg,
310 void (*cb)(struct pci_dev *, void *)) 312 int (*cb)(struct pci_dev *, void *))
311{ 313{
312 struct aer_broadcast_data result_data; 314 struct aer_broadcast_data result_data;
313 315