diff options
author | Linas Vepstas <linas@linas.org> | 2005-11-03 19:52:49 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-01-09 23:28:32 -0500 |
commit | 77bd741561016134d1761d6101c4f0361025062f (patch) | |
tree | 5e3389b6941add4b24a2be64c730b7a9087c1f2f /arch/powerpc/platforms/pseries/eeh_event.c | |
parent | 977127174a7dff52d17faeeb4c4949a54221881f (diff) |
[PATCH] powerpc: PCI Error Recovery: PPC64 core recovery routines
Various PCI bus errors can be signaled by newer PCI controllers. The
core error recovery routines are architecture dependent. This patch adds
a recovery infrastructure for the PPC64 pSeries systems.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
(cherry picked from e8ca11b460c4c9c7fa6b529be221529ebd770e38 commit)
Diffstat (limited to 'arch/powerpc/platforms/pseries/eeh_event.c')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_event.c | 39 |
1 files changed, 12 insertions, 27 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 92497333c2b..9a9961f2748 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/pci.h> | 22 | #include <linux/pci.h> |
23 | #include <asm/eeh_event.h> | 23 | #include <asm/eeh_event.h> |
24 | #include <asm/ppc-pci.h> | ||
24 | 25 | ||
25 | /** Overview: | 26 | /** Overview: |
26 | * EEH error states may be detected within exception handlers; | 27 | * EEH error states may be detected within exception handlers; |
@@ -37,31 +38,6 @@ static void eeh_thread_launcher(void *); | |||
37 | DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); | 38 | DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); |
38 | 39 | ||
39 | /** | 40 | /** |
40 | * eeh_panic - call panic() for an eeh event that cannot be handled. | ||
41 | * The philosophy of this routine is that it is better to panic and | ||
42 | * halt the OS than it is to risk possible data corruption by | ||
43 | * oblivious device drivers that don't know better. | ||
44 | * | ||
45 | * @dev pci device that had an eeh event | ||
46 | * @reset_state current reset state of the device slot | ||
47 | */ | ||
48 | static void eeh_panic(struct pci_dev *dev, int reset_state) | ||
49 | { | ||
50 | /* | ||
51 | * Since the panic_on_oops sysctl is used to halt the system | ||
52 | * in light of potential corruption, we can use it here. | ||
53 | */ | ||
54 | if (panic_on_oops) { | ||
55 | panic("EEH: MMIO failure (%d) on device:%s\n", reset_state, | ||
56 | pci_name(dev)); | ||
57 | } | ||
58 | else { | ||
59 | printk(KERN_INFO "EEH: Ignored MMIO failure (%d) on device:%s\n", | ||
60 | reset_state, pci_name(dev)); | ||
61 | } | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * eeh_event_handler - dispatch EEH events. The detection of a frozen | 41 | * eeh_event_handler - dispatch EEH events. The detection of a frozen |
66 | * slot can occur inside an interrupt, where it can be hard to do | 42 | * slot can occur inside an interrupt, where it can be hard to do |
67 | * anything about it. The goal of this routine is to pull these | 43 | * anything about it. The goal of this routine is to pull these |
@@ -82,10 +58,16 @@ static int eeh_event_handler(void * dummy) | |||
82 | 58 | ||
83 | spin_lock_irqsave(&eeh_eventlist_lock, flags); | 59 | spin_lock_irqsave(&eeh_eventlist_lock, flags); |
84 | event = NULL; | 60 | event = NULL; |
61 | |||
62 | /* Unqueue the event, get ready to process. */ | ||
85 | if (!list_empty(&eeh_eventlist)) { | 63 | if (!list_empty(&eeh_eventlist)) { |
86 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); | 64 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); |
87 | list_del(&event->list); | 65 | list_del(&event->list); |
88 | } | 66 | } |
67 | |||
68 | if (event) | ||
69 | eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); | ||
70 | |||
89 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | 71 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); |
90 | if (event == NULL) | 72 | if (event == NULL) |
91 | break; | 73 | break; |
@@ -93,8 +75,11 @@ static int eeh_event_handler(void * dummy) | |||
93 | printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", | 75 | printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", |
94 | pci_name(event->dev)); | 76 | pci_name(event->dev)); |
95 | 77 | ||
96 | eeh_panic (event->dev, event->state); | 78 | handle_eeh_events(event); |
79 | |||
80 | eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); | ||
97 | 81 | ||
82 | pci_dev_put(event->dev); | ||
98 | kfree(event); | 83 | kfree(event); |
99 | } | 84 | } |
100 | 85 | ||
@@ -122,7 +107,7 @@ static void eeh_thread_launcher(void *dummy) | |||
122 | */ | 107 | */ |
123 | int eeh_send_failure_event (struct device_node *dn, | 108 | int eeh_send_failure_event (struct device_node *dn, |
124 | struct pci_dev *dev, | 109 | struct pci_dev *dev, |
125 | int state, | 110 | enum pci_channel_state state, |
126 | int time_unavail) | 111 | int time_unavail) |
127 | { | 112 | { |
128 | unsigned long flags; | 113 | unsigned long flags; |