diff options
Diffstat (limited to 'drivers/misc/sgi-gru/grufault.c')
-rw-r--r-- | drivers/misc/sgi-gru/grufault.c | 25 |
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 | ||
406 | failnoexception: | ||
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 | |||
404 | failidle: | 415 | failidle: |
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(>s->ts_mm->mmap_sem)) { | 486 | if (!gts->ts_force_cch_reload && |
487 | down_read_trylock(>s->ts_mm->mmap_sem)) { | ||
476 | gru_try_dropin(gts, tfh, NULL); | 488 | gru_try_dropin(gts, tfh, NULL); |
477 | up_read(>s->ts_mm->mmap_sem); | 489 | up_read(>s->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; |