Commit 8c33fd11 authored by Linas Vepstas's avatar Linas Vepstas Committed by Paul Mackerras

[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: default avatarLinas Vepstas <linas@austin.ibm.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent f18dd516
...@@ -19,7 +19,9 @@ ...@@ -19,7 +19,9 @@
*/ */
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/workqueue.h>
#include <asm/eeh_event.h> #include <asm/eeh_event.h>
#include <asm/ppc-pci.h> #include <asm/ppc-pci.h>
...@@ -37,14 +39,18 @@ LIST_HEAD(eeh_eventlist); ...@@ -37,14 +39,18 @@ LIST_HEAD(eeh_eventlist);
static void eeh_thread_launcher(void *); static void eeh_thread_launcher(void *);
DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL); DECLARE_WORK(eeh_event_wq, eeh_thread_launcher, NULL);
/* Serialize reset sequences for a given pci device */
DEFINE_MUTEX(eeh_event_mutex);
/** /**
* eeh_event_handler - dispatch EEH events. The detection of a frozen * eeh_event_handler - dispatch EEH events.
* slot can occur inside an interrupt, where it can be hard to do
* anything about it. The goal of this routine is to pull these
* detection events out of the context of the interrupt handler, and
* re-dispatch them for processing at a later time in a normal context.
*
* @dummy - unused * @dummy - unused
*
* The detection of a frozen slot can occur inside an interrupt,
* where it can be hard to do anything about it. The goal of this
* routine is to pull these detection events out of the context
* of the interrupt handler, and re-dispatch them for processing
* at a later time in a normal context.
*/ */
static int eeh_event_handler(void * dummy) static int eeh_event_handler(void * dummy)
{ {
...@@ -64,23 +70,24 @@ static int eeh_event_handler(void * dummy) ...@@ -64,23 +70,24 @@ static int eeh_event_handler(void * dummy)
event = list_entry(eeh_eventlist.next, struct eeh_event, list); event = list_entry(eeh_eventlist.next, struct eeh_event, list);
list_del(&event->list); list_del(&event->list);
} }
if (event)
eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
spin_unlock_irqrestore(&eeh_eventlist_lock, flags); spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
if (event == NULL) if (event == NULL)
break; break;
/* Serialize processing of EEH events */
mutex_lock(&eeh_event_mutex);
eeh_mark_slot(event->dn, EEH_MODE_RECOVERING);
printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n", printk(KERN_INFO "EEH: Detected PCI bus error on device %s\n",
pci_name(event->dev)); pci_name(event->dev));
handle_eeh_events(event); handle_eeh_events(event);
eeh_clear_slot(event->dn, EEH_MODE_RECOVERING); eeh_clear_slot(event->dn, EEH_MODE_RECOVERING);
pci_dev_put(event->dev); pci_dev_put(event->dev);
kfree(event); kfree(event);
mutex_unlock(&eeh_event_mutex);
} }
return 0; return 0;
...@@ -88,7 +95,6 @@ static int eeh_event_handler(void * dummy) ...@@ -88,7 +95,6 @@ static int eeh_event_handler(void * dummy)
/** /**
* eeh_thread_launcher * eeh_thread_launcher
*
* @dummy - unused * @dummy - unused
*/ */
static void eeh_thread_launcher(void *dummy) static void eeh_thread_launcher(void *dummy)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment