aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/eeh.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 81cd0311dee8..7c567be3dd03 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -269,6 +269,58 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
269 return pa | (token & (PAGE_SIZE-1)); 269 return pa | (token & (PAGE_SIZE-1));
270} 270}
271 271
272/*
273 * On PowerNV platform, we might already have fenced PHB there.
274 * For that case, it's meaningless to recover frozen PE. Intead,
275 * We have to handle fenced PHB firstly.
276 */
277static int eeh_phb_check_failure(struct eeh_pe *pe)
278{
279 struct eeh_pe *phb_pe;
280 unsigned long flags;
281 int ret;
282
283 if (!eeh_probe_mode_dev())
284 return -EPERM;
285
286 /* Find the PHB PE */
287 phb_pe = eeh_phb_pe_get(pe->phb);
288 if (!phb_pe) {
289 pr_warning("%s Can't find PE for PHB#%d\n",
290 __func__, pe->phb->global_number);
291 return -EEXIST;
292 }
293
294 /* If the PHB has been in problematic state */
295 eeh_serialize_lock(&flags);
296 if (phb_pe->state & (EEH_PE_ISOLATED | EEH_PE_PHB_DEAD)) {
297 ret = 0;
298 goto out;
299 }
300
301 /* Check PHB state */
302 ret = eeh_ops->get_state(phb_pe, NULL);
303 if ((ret < 0) ||
304 (ret == EEH_STATE_NOT_SUPPORT) ||
305 (ret & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) ==
306 (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) {
307 ret = 0;
308 goto out;
309 }
310
311 /* Isolate the PHB and send event */
312 eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED);
313 eeh_serialize_unlock(flags);
314 eeh_send_failure_event(phb_pe);
315
316 WARN(1, "EEH: PHB failure detected\n");
317
318 return 1;
319out:
320 eeh_serialize_unlock(flags);
321 return ret;
322}
323
272/** 324/**
273 * eeh_dev_check_failure - Check if all 1's data is due to EEH slot freeze 325 * eeh_dev_check_failure - Check if all 1's data is due to EEH slot freeze
274 * @edev: eeh device 326 * @edev: eeh device
@@ -319,6 +371,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev)
319 return 0; 371 return 0;
320 } 372 }
321 373
374 /*
375 * On PowerNV platform, we might already have fenced PHB
376 * there and we need take care of that firstly.
377 */
378 ret = eeh_phb_check_failure(pe);
379 if (ret > 0)
380 return ret;
381
322 /* If we already have a pending isolation event for this 382 /* If we already have a pending isolation event for this
323 * slot, we know it's bad already, we don't need to check. 383 * slot, we know it's bad already, we don't need to check.
324 * Do this checking under a lock; as multiple PCI devices 384 * Do this checking under a lock; as multiple PCI devices