aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorGavin Shan <shangw@linux.vnet.ibm.com>2013-06-20 01:21:02 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2013-06-20 03:06:07 -0400
commit99866595340fa24079f61962b2541db3225e7aad (patch)
treec8c46660889edcc691efb4c052ddc1350f714fc6 /arch
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')
-rw-r--r--arch/powerpc/include/asm/eeh_event.h1
-rw-r--r--arch/powerpc/kernel/eeh_event.c37
2 files changed, 38 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/eeh_event.h b/arch/powerpc/include/asm/eeh_event.h
index de92c86221e7..89d5670b2eeb 100644
--- a/arch/powerpc/include/asm/eeh_event.h
+++ b/arch/powerpc/include/asm/eeh_event.h
@@ -33,6 +33,7 @@ struct eeh_event {
33 33
34int eeh_event_init(void); 34int eeh_event_init(void);
35int eeh_send_failure_event(struct eeh_pe *pe); 35int eeh_send_failure_event(struct eeh_pe *pe);
36void eeh_remove_event(struct eeh_pe *pe);
36void eeh_handle_event(struct eeh_pe *pe); 37void eeh_handle_event(struct eeh_pe *pe);
37 38
38#endif /* __KERNEL__ */ 39#endif /* __KERNEL__ */
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)
142 142
143 return 0; 143 return 0;
144} 144}
145
146/**
147 * eeh_remove_event - Remove EEH event from the queue
148 * @pe: Event binding to the PE
149 *
150 * On PowerNV platform, we might have subsequent coming events
151 * is part of the former one. For that case, those subsequent
152 * coming events are totally duplicated and unnecessary, thus
153 * they should be removed.
154 */
155void eeh_remove_event(struct eeh_pe *pe)
156{
157 unsigned long flags;
158 struct eeh_event *event, *tmp;
159
160 spin_lock_irqsave(&eeh_eventlist_lock, flags);
161 list_for_each_entry_safe(event, tmp, &eeh_eventlist, list) {
162 /*
163 * If we don't have valid PE passed in, that means
164 * we already have event corresponding to dead IOC
165 * and all events should be purged.
166 */
167 if (!pe) {
168 list_del(&event->list);
169 kfree(event);
170 } else if (pe->type & EEH_PE_PHB) {
171 if (event->pe && event->pe->phb == pe->phb) {
172 list_del(&event->list);
173 kfree(event);
174 }
175 } else if (event->pe == pe) {
176 list_del(&event->list);
177 kfree(event);
178 }
179 }
180 spin_unlock_irqrestore(&eeh_eventlist_lock, flags);
181}