aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grufault.c
diff options
context:
space:
mode:
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 ab118558552..4089f862aa2 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;