diff options
author | Linas Vepstas <linas@austin.ibm.com> | 2006-03-29 16:29:18 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-04-01 06:35:01 -0500 |
commit | 8c33fd11e3a21a15af35b5831f1516faf53094f1 (patch) | |
tree | 80e4ac00c80db232a131907fcf9e5b9cd5cfdfb2 /arch/powerpc | |
parent | f18dd516d433d0b740aa8365d706f5ad47603449 (diff) |
[PATCH] powerpc/pseries: mutex lock to serialize EEH event processing
This forces the processing of EEH PCI events to be serialized,
using a very simple mutex lock. This serialization is required to
avoid races involving additional PCI device failures that may occur
during the recovery phase of a previous failure.
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_event.c | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 9a9961f27480..a1bda6f96fd1 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c | |||
@@ -19,7 +19,9 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/mutex.h> | ||
22 | #include <linux/pci.h> | 23 | #include <linux/pci.h> |
24 | #include <linux/workqueue.h> | ||
23 | #include <asm/eeh_event.h> | 25 | #include <asm/eeh_event.h> |
24 | #include <asm/ppc-pci.h> | 26 | #include <asm/ppc-pci.h> |
25 | 27 | ||
@@ -37,14 +39,18 @@ LIST_HEAD(eeh_eventlist); | |||
37 | static void eeh_thread_launcher(void *); | 39 | static void eeh_thread_launcher(void *); |
38 | DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); | 40 | DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); |
39 | 41 | ||
42 | /* Serialize reset sequences for a given pci device */ | ||
43 | DEFINE_MUTEX(eeh_event_mutex); | ||
44 | |||
40 | /** | 45 | /** |
41 | * eeh_event_handler - dispatch EEH events. The detection of a frozen | 46 | * eeh_event_handler - dispatch EEH events. |
42 | * slot can occur inside an interrupt, where it can be hard to do | ||
43 | * anything about it. The goal of this routine is to pull these | ||
44 | * detection events out of the context of the interrupt handler, and | ||
45 | * re-dispatch them for processing at a later time in a normal context. | ||
46 | * | ||
47 | * @dummy - unused | 47 | * @dummy - unused |
48 | * | ||
49 | * The detection of a frozen slot can occur inside an interrupt, | ||
50 | * where it can be hard to do anything about it. The goal of this | ||
51 | * routine is to pull these detection events out of the context | ||
52 | * of the interrupt handler, and re-dispatch them for processing | ||
53 | * at a later time in a normal context. | ||
48 | */ | 54 | */ |
49 | static int eeh_event_handler(void * dummy) | 55 | static int eeh_event_handler(void * dummy) |
50 | { | 56 | { |
@@ -64,23 +70,24 @@ static int eeh_event_handler(void * dummy) | |||
64 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); | 70 | event = list_entry(eeh_eventlist.next, struct eeh_event, list); |
65 | list_del(&event->list); | 71 | list_del(&event->list); |
66 | } | 72 | } |
67 | |||
68 | if (event) | ||
69 | eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); | ||
70 | |||
71 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); | 73 | spin_unlock_irqrestore(&eeh_eventlist_lock, flags); |
74 | |||
72 | if (event == NULL) | 75 | if (event == NULL) |
73 | break; | 76 | break; |
74 | 77 | ||
78 | /* Serialize processing of EEH events */ | ||
79 | mutex_lock(&eeh_event_mutex); | ||
80 | eeh_mark_slot(event->dn, EEH_MODE_RECOVERING); | ||
81 | |||
75 | printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", | 82 | printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", |
76 | pci_name(event->dev)); | 83 | pci_name(event->dev)); |
77 | 84 | ||
78 | handle_eeh_events(event); | 85 | handle_eeh_events(event); |
79 | 86 | ||
80 | eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); | 87 | eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); |
81 | |||
82 | pci_dev_put(event->dev); | 88 | pci_dev_put(event->dev); |
83 | kfree(event); | 89 | kfree(event); |
90 | mutex_unlock(&eeh_event_mutex); | ||
84 | } | 91 | } |
85 | 92 | ||
86 | return 0; | 93 | return 0; |
@@ -88,7 +95,6 @@ static int eeh_event_handler(void * dummy) | |||
88 | 95 | ||
89 | /** | 96 | /** |
90 | * eeh_thread_launcher | 97 | * eeh_thread_launcher |
91 | * | ||
92 | * @dummy - unused | 98 | * @dummy - unused |
93 | */ | 99 | */ |
94 | static void eeh_thread_launcher(void *dummy) | 100 | static void eeh_thread_launcher(void *dummy) |