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 | |
| 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>
| -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) |
