aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grufault.c
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-06-17 19:28:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-18 16:03:59 -0400
commitcd1334f03f7b799bc6893b511daf2080e8f73863 (patch)
tree468d9bc99e19aa7895321927eaf30c4dae55166f /drivers/misc/sgi-gru/grufault.c
parentd6580a9f15238b87e618310c862231ae3f352d2d (diff)
gru: bug fixes for GRU exception handling
Bug fixes for GRU exception handling. Additional fields from the CBR must be returned to the user to allow the user to correctly diagnose GRU exceptions. Handle endcase in TFH TLB miss handling. Verify that TFH actually indicates a pending exception. Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-gru/grufault.c')
-rw-r--r--drivers/misc/sgi-gru/grufault.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index ab118558552e..4089f862aa29 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -334,6 +334,8 @@ static int gru_try_dropin(struct gru_thread_state *gts,
334 * Might be a hardware race OR a stupid user. Ignore FMM because FMM 334 * Might be a hardware race OR a stupid user. Ignore FMM because FMM
335 * is a transient state. 335 * is a transient state.
336 */ 336 */
337 if (tfh->status != TFHSTATUS_EXCEPTION)
338 goto failnoexception;
337 if (tfh->state == TFHSTATE_IDLE) 339 if (tfh->state == TFHSTATE_IDLE)
338 goto failidle; 340 goto failidle;
339 if (tfh->state == TFHSTATE_MISS_FMM && cb) 341 if (tfh->state == TFHSTATE_MISS_FMM && cb)
@@ -401,8 +403,17 @@ failfmm:
401 gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state); 403 gru_dbg(grudev, "FAILED fmm tfh: 0x%p, state %d\n", tfh, tfh->state);
402 return 0; 404 return 0;
403 405
406failnoexception:
407 /* TFH status did not show exception pending */
408 gru_flush_cache(tfh);
409 if (cb)
410 gru_flush_cache(cb);
411 STAT(tlb_dropin_fail_no_exception);
412 gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n", tfh, tfh->status, tfh->state);
413 return 0;
414
404failidle: 415failidle:
405 /* TFH was idle - no miss pending */ 416 /* TFH state was idle - no miss pending */
406 gru_flush_cache(tfh); 417 gru_flush_cache(tfh);
407 if (cb) 418 if (cb)
408 gru_flush_cache(cb); 419 gru_flush_cache(cb);
@@ -472,7 +483,8 @@ irqreturn_t gru_intr(int irq, void *dev_id)
472 * This is running in interrupt context. Trylock the mmap_sem. 483 * This is running in interrupt context. Trylock the mmap_sem.
473 * If it fails, retry the fault in user context. 484 * If it fails, retry the fault in user context.
474 */ 485 */
475 if (down_read_trylock(&gts->ts_mm->mmap_sem)) { 486 if (!gts->ts_force_cch_reload &&
487 down_read_trylock(&gts->ts_mm->mmap_sem)) {
476 gru_try_dropin(gts, tfh, NULL); 488 gru_try_dropin(gts, tfh, NULL);
477 up_read(&gts->ts_mm->mmap_sem); 489 up_read(&gts->ts_mm->mmap_sem);
478 } else { 490 } else {
@@ -595,14 +607,19 @@ int gru_get_exception_detail(unsigned long arg)
595 excdet.ecause = cbe->ecause; 607 excdet.ecause = cbe->ecause;
596 excdet.exceptdet0 = cbe->idef1upd; 608 excdet.exceptdet0 = cbe->idef1upd;
597 excdet.exceptdet1 = cbe->idef3upd; 609 excdet.exceptdet1 = cbe->idef3upd;
610 excdet.cbrstate = cbe->cbrstate;
611 excdet.cbrexecstatus = cbe->cbrexecstatus;
598 ret = 0; 612 ret = 0;
599 } else { 613 } else {
600 ret = -EAGAIN; 614 ret = -EAGAIN;
601 } 615 }
602 gru_unlock_gts(gts); 616 gru_unlock_gts(gts);
603 617
604 gru_dbg(grudev, "address 0x%lx, ecause 0x%x\n", excdet.cb, 618 gru_dbg(grudev,
605 excdet.ecause); 619 "cb 0x%lx, op %d, exopc %d, cbrstate %d, cbrexecstatus 0x%x, ecause 0x%x, "
620 "exdet0 0x%lx, exdet1 0x%x\n",
621 excdet.cb, excdet.opc, excdet.exopc, excdet.cbrstate, excdet.cbrexecstatus,
622 excdet.ecause, excdet.exceptdet0, excdet.exceptdet1);
606 if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet))) 623 if (!ret && copy_to_user((void __user *)arg, &excdet, sizeof(excdet)))
607 ret = -EFAULT; 624 ret = -EFAULT;
608 return ret; 625 return ret;