summaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/eeh_event.c
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2013-06-20 13:21:02 +0800
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-06-20 17:06:07 +1000
commit99866595340fa24079f61962b2541db3225e7aad (patch)
treec8c46660889edcc691efb4c052ddc1350f714fc6 /arch/powerpc/kernel/eeh_event.c
parent5a71978e4b6ee6a01bc6aab926a3571055123029 (diff)
powerpc/eeh: Allow to purge EEH events
On PowerNV platform, we might run into the situation where subsequent events are duplicated events of former one, which is being processed. For the case, we need the function implemented by the patch to purge EEH events accordingly. Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/eeh_event.c')
-rw-r--r--arch/powerpc/kernel/eeh_event.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/eeh_event.c b/arch/powerpc/kernel/eeh_event.c
index 62e532ddfb68..39bcd81e7f5d 100644
--- a/arch/powerpc/kernel/eeh_event.c
+++ b/arch/powerpc/kernel/eeh_event.c
@@ -142,3 +142,40 @@ int eeh_send_failure_event(struct eeh_pe *pe)
return 0;
}
+
+/**
+ * eeh_remove_event - Remove EEH event from the queue
+ * @pe: Event binding to the PE
+ *
+ * On PowerNV platform, we might have subsequent coming events
+ * is part of the former one. For that case, those subsequent
+ * coming events are totally duplicated and unnecessary, thus
+ * they should be removed.
+ */
+void eeh_remove_event(struct eeh_pe *pe)
+{
+ unsigned long flags;
+ struct eeh_event *event, *tmp;
+
+ spin_lock_irqsave(&eeh_eventlist_lock, flags);
+ list_for_each_entry_safe(event, tmp, &eeh_eventlist, list) {
+ /*
+ * If we don't have valid PE passed in, that means
+ * we already have event corresponding to dead IOC
+ * and all events should be purged.
+ */
+ if (!pe) {
+ list_del(&event->list);
+ kfree(event);
+ } else if (pe->type & EEH_PE_PHB) {
+ if (event->pe && event->pe->phb == pe->phb) {
+ list_del(&event->list);
+ kfree(event);
+ }
+ } else if (event->pe == pe) {
+ list_del(&event->list);
+ kfree(event);
+ }
+ }
+ spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
+}