diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh_driver.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_driver.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 1fba695e32e..0ec9a5445b9 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -23,9 +23,8 @@ | |||
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/irq.h> | ||
27 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
28 | #include <linux/notifier.h> | 27 | #include <linux/irq.h> |
29 | #include <linux/pci.h> | 28 | #include <linux/pci.h> |
30 | #include <asm/eeh.h> | 29 | #include <asm/eeh.h> |
31 | #include <asm/eeh_event.h> | 30 | #include <asm/eeh_event.h> |
@@ -202,7 +201,11 @@ static void eeh_report_failure(struct pci_dev *dev, void *userdata) | |||
202 | 201 | ||
203 | static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) | 202 | static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) |
204 | { | 203 | { |
205 | int rc; | 204 | int cnt, rc; |
205 | |||
206 | /* pcibios will clear the counter; save the value */ | ||
207 | cnt = pe_dn->eeh_freeze_count; | ||
208 | |||
206 | if (bus) | 209 | if (bus) |
207 | pcibios_remove_pci_devices(bus); | 210 | pcibios_remove_pci_devices(bus); |
208 | 211 | ||
@@ -241,6 +244,7 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) | |||
241 | ssleep (5); | 244 | ssleep (5); |
242 | pcibios_add_pci_devices(bus); | 245 | pcibios_add_pci_devices(bus); |
243 | } | 246 | } |
247 | pe_dn->eeh_freeze_count = cnt; | ||
244 | 248 | ||
245 | return 0; | 249 | return 0; |
246 | } | 250 | } |
@@ -250,23 +254,29 @@ static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) | |||
250 | */ | 254 | */ |
251 | #define MAX_WAIT_FOR_RECOVERY 15 | 255 | #define MAX_WAIT_FOR_RECOVERY 15 |
252 | 256 | ||
253 | void handle_eeh_events (struct eeh_event *event) | 257 | struct pci_dn * handle_eeh_events (struct eeh_event *event) |
254 | { | 258 | { |
255 | struct device_node *frozen_dn; | 259 | struct device_node *frozen_dn; |
256 | struct pci_dn *frozen_pdn; | 260 | struct pci_dn *frozen_pdn; |
257 | struct pci_bus *frozen_bus; | 261 | struct pci_bus *frozen_bus; |
258 | int rc = 0; | 262 | int rc = 0; |
259 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; | 263 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; |
260 | const char *pci_str, *drv_str; | 264 | const char *location, *pci_str, *drv_str; |
261 | 265 | ||
262 | frozen_dn = find_device_pe(event->dn); | 266 | frozen_dn = find_device_pe(event->dn); |
263 | frozen_bus = pcibios_find_pci_bus(frozen_dn); | 267 | frozen_bus = pcibios_find_pci_bus(frozen_dn); |
264 | 268 | ||
265 | if (!frozen_dn) { | 269 | if (!frozen_dn) { |
266 | printk(KERN_ERR "EEH: Error: Cannot find partition endpoint for %s\n", | 270 | |
267 | pci_name(event->dev)); | 271 | location = (char *) get_property(event->dn, "ibm,loc-code", NULL); |
268 | return; | 272 | location = location ? location : "unknown"; |
273 | printk(KERN_ERR "EEH: Error: Cannot find partition endpoint " | ||
274 | "for location=%s pci addr=%s\n", | ||
275 | location, pci_name(event->dev)); | ||
276 | return NULL; | ||
269 | } | 277 | } |
278 | location = (char *) get_property(frozen_dn, "ibm,loc-code", NULL); | ||
279 | location = location ? location : "unknown"; | ||
270 | 280 | ||
271 | /* There are two different styles for coming up with the PE. | 281 | /* There are two different styles for coming up with the PE. |
272 | * In the old style, it was the highest EEH-capable device | 282 | * In the old style, it was the highest EEH-capable device |
@@ -278,9 +288,10 @@ void handle_eeh_events (struct eeh_event *event) | |||
278 | frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); | 288 | frozen_bus = pcibios_find_pci_bus (frozen_dn->parent); |
279 | 289 | ||
280 | if (!frozen_bus) { | 290 | if (!frozen_bus) { |
281 | printk(KERN_ERR "EEH: Cannot find PCI bus for %s\n", | 291 | printk(KERN_ERR "EEH: Cannot find PCI bus " |
282 | frozen_dn->full_name); | 292 | "for location=%s dn=%s\n", |
283 | return; | 293 | location, frozen_dn->full_name); |
294 | return NULL; | ||
284 | } | 295 | } |
285 | 296 | ||
286 | #if 0 | 297 | #if 0 |
@@ -314,8 +325,9 @@ void handle_eeh_events (struct eeh_event *event) | |||
314 | 325 | ||
315 | eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); | 326 | eeh_slot_error_detail(frozen_pdn, 1 /* Temporary Error */); |
316 | printk(KERN_WARNING | 327 | printk(KERN_WARNING |
317 | "EEH: This PCI device has failed %d times since last reboot: %s - %s\n", | 328 | "EEH: This PCI device has failed %d times since last reboot: " |
318 | frozen_pdn->eeh_freeze_count, drv_str, pci_str); | 329 | "location=%s driver=%s pci addr=%s\n", |
330 | frozen_pdn->eeh_freeze_count, location, drv_str, pci_str); | ||
319 | 331 | ||
320 | /* Walk the various device drivers attached to this slot through | 332 | /* Walk the various device drivers attached to this slot through |
321 | * a reset sequence, giving each an opportunity to do what it needs | 333 | * a reset sequence, giving each an opportunity to do what it needs |
@@ -355,7 +367,7 @@ void handle_eeh_events (struct eeh_event *event) | |||
355 | /* Tell all device drivers that they can resume operations */ | 367 | /* Tell all device drivers that they can resume operations */ |
356 | pci_walk_bus(frozen_bus, eeh_report_resume, NULL); | 368 | pci_walk_bus(frozen_bus, eeh_report_resume, NULL); |
357 | 369 | ||
358 | return; | 370 | return frozen_pdn; |
359 | 371 | ||
360 | excess_failures: | 372 | excess_failures: |
361 | /* | 373 | /* |
@@ -364,17 +376,18 @@ excess_failures: | |||
364 | * due to actual, failed cards. | 376 | * due to actual, failed cards. |
365 | */ | 377 | */ |
366 | printk(KERN_ERR | 378 | printk(KERN_ERR |
367 | "EEH: PCI device %s - %s has failed %d times \n" | 379 | "EEH: PCI device at location=%s driver=%s pci addr=%s \n" |
368 | "and has been permanently disabled. Please try reseating\n" | 380 | "has failed %d times and has been permanently disabled. \n" |
369 | "this device or replacing it.\n", | 381 | "Please try reseating this device or replacing it.\n", |
370 | drv_str, pci_str, frozen_pdn->eeh_freeze_count); | 382 | location, drv_str, pci_str, frozen_pdn->eeh_freeze_count); |
371 | goto perm_error; | 383 | goto perm_error; |
372 | 384 | ||
373 | hard_fail: | 385 | hard_fail: |
374 | printk(KERN_ERR | 386 | printk(KERN_ERR |
375 | "EEH: Unable to recover from failure of PCI device %s - %s\n" | 387 | "EEH: Unable to recover from failure of PCI device " |
388 | "at location=%s driver=%s pci addr=%s \n" | ||
376 | "Please try reseating this device or replacing it.\n", | 389 | "Please try reseating this device or replacing it.\n", |
377 | drv_str, pci_str); | 390 | location, drv_str, pci_str); |
378 | 391 | ||
379 | perm_error: | 392 | perm_error: |
380 | eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); | 393 | eeh_slot_error_detail(frozen_pdn, 2 /* Permanent Error */); |
@@ -384,6 +397,8 @@ perm_error: | |||
384 | 397 | ||
385 | /* Shut down the device drivers for good. */ | 398 | /* Shut down the device drivers for good. */ |
386 | pcibios_remove_pci_devices(frozen_bus); | 399 | pcibios_remove_pci_devices(frozen_bus); |
400 | |||
401 | return NULL; | ||
387 | } | 402 | } |
388 | 403 | ||
389 | /* ---------- end of file ---------- */ | 404 | /* ---------- end of file ---------- */ |