[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>
This commit is contained in:
Родитель
f18dd516d4
Коммит
8c33fd11e3
|
@ -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);
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* eeh_thread_launcher
|
* eeh_thread_launcher
|
||||||
*
|
|
||||||
* @dummy - unused
|
* @dummy - unused
|
||||||
*/
|
*/
|
||||||
static void eeh_thread_launcher(void *dummy)
|
static void eeh_thread_launcher(void *dummy)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче