aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/sgi-gru/grufault.c49
1 files changed, 20 insertions, 29 deletions
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index 2605edfbaebe..a9f0cf483005 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -122,22 +122,11 @@ static void gru_unlock_gts(struct gru_thread_state *gts)
122 * is necessary to prevent the user from seeing a stale cb.istatus that will 122 * is necessary to prevent the user from seeing a stale cb.istatus that will
123 * change as soon as the TFH restart is complete. Races may cause an 123 * change as soon as the TFH restart is complete. Races may cause an
124 * occasional failure to clear the cb.istatus, but that is ok. 124 * occasional failure to clear the cb.istatus, but that is ok.
125 *
126 * If the cb address is not valid (should not happen, but...), nothing
127 * bad will happen.. The get_user()/put_user() will fail but there
128 * are no bad side-effects.
129 */ 125 */
130static void gru_cb_set_istatus_active(unsigned long __user *cb) 126static void gru_cb_set_istatus_active(struct gru_instruction_bits *cbk)
131{ 127{
132 union { 128 if (cbk) {
133 struct gru_instruction_bits bits; 129 cbk->istatus = CBS_ACTIVE;
134 unsigned long dw;
135 } u;
136
137 if (cb) {
138 get_user(u.dw, cb);
139 u.bits.istatus = CBS_ACTIVE;
140 put_user(u.dw, cb);
141 } 130 }
142} 131}
143 132
@@ -322,9 +311,9 @@ upm:
322 */ 311 */
323static int gru_try_dropin(struct gru_thread_state *gts, 312static int gru_try_dropin(struct gru_thread_state *gts,
324 struct gru_tlb_fault_handle *tfh, 313 struct gru_tlb_fault_handle *tfh,
325 unsigned long __user *cb) 314 struct gru_instruction_bits *cbk)
326{ 315{
327 int pageshift = 0, asid, write, ret, atomic = !cb; 316 int pageshift = 0, asid, write, ret, atomic = !cbk;
328 unsigned long gpa = 0, vaddr = 0; 317 unsigned long gpa = 0, vaddr = 0;
329 318
330 /* 319 /*
@@ -347,7 +336,7 @@ static int gru_try_dropin(struct gru_thread_state *gts,
347 } 336 }
348 if (tfh->state == TFHSTATE_IDLE) 337 if (tfh->state == TFHSTATE_IDLE)
349 goto failidle; 338 goto failidle;
350 if (tfh->state == TFHSTATE_MISS_FMM && cb) 339 if (tfh->state == TFHSTATE_MISS_FMM && cbk)
351 goto failfmm; 340 goto failfmm;
352 341
353 write = (tfh->cause & TFHCAUSE_TLB_MOD) != 0; 342 write = (tfh->cause & TFHCAUSE_TLB_MOD) != 0;
@@ -378,7 +367,7 @@ static int gru_try_dropin(struct gru_thread_state *gts,
378 goto failupm; 367 goto failupm;
379 } 368 }
380 } 369 }
381 gru_cb_set_istatus_active(cb); 370 gru_cb_set_istatus_active(cbk);
382 tfh_write_restart(tfh, gpa, GAA_RAM, vaddr, asid, write, 371 tfh_write_restart(tfh, gpa, GAA_RAM, vaddr, asid, write,
383 GRU_PAGESIZE(pageshift)); 372 GRU_PAGESIZE(pageshift));
384 STAT(tlb_dropin); 373 STAT(tlb_dropin);
@@ -392,7 +381,7 @@ failnoasid:
392 /* No asid (delayed unload). */ 381 /* No asid (delayed unload). */
393 STAT(tlb_dropin_fail_no_asid); 382 STAT(tlb_dropin_fail_no_asid);
394 gru_dbg(grudev, "FAILED no_asid tfh: 0x%p, vaddr 0x%lx\n", tfh, vaddr); 383 gru_dbg(grudev, "FAILED no_asid tfh: 0x%p, vaddr 0x%lx\n", tfh, vaddr);
395 if (!cb) 384 if (!cbk)
396 tfh_user_polling_mode(tfh); 385 tfh_user_polling_mode(tfh);
397 else 386 else
398 gru_flush_cache(tfh); 387 gru_flush_cache(tfh);
@@ -415,17 +404,18 @@ failfmm:
415failnoexception: 404failnoexception:
416 /* TFH status did not show exception pending */ 405 /* TFH status did not show exception pending */
417 gru_flush_cache(tfh); 406 gru_flush_cache(tfh);
418 if (cb) 407 if (cbk)
419 gru_flush_cache(cb); 408 gru_flush_cache(cbk);
420 STAT(tlb_dropin_fail_no_exception); 409 STAT(tlb_dropin_fail_no_exception);
421 gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n", tfh, tfh->status, tfh->state); 410 gru_dbg(grudev, "FAILED non-exception tfh: 0x%p, status %d, state %d\n",
411 tfh, tfh->status, tfh->state);
422 return 0; 412 return 0;
423 413
424failidle: 414failidle:
425 /* TFH state was idle - no miss pending */ 415 /* TFH state was idle - no miss pending */
426 gru_flush_cache(tfh); 416 gru_flush_cache(tfh);
427 if (cb) 417 if (cbk)
428 gru_flush_cache(cb); 418 gru_flush_cache(cbk);
429 STAT(tlb_dropin_fail_idle); 419 STAT(tlb_dropin_fail_idle);
430 gru_dbg(grudev, "FAILED idle tfh: 0x%p, state %d\n", tfh, tfh->state); 420 gru_dbg(grudev, "FAILED idle tfh: 0x%p, state %d\n", tfh, tfh->state);
431 return 0; 421 return 0;
@@ -439,7 +429,7 @@ failinval:
439 429
440failactive: 430failactive:
441 /* Range invalidate active. Switch to UPM iff atomic */ 431 /* Range invalidate active. Switch to UPM iff atomic */
442 if (!cb) 432 if (!cbk)
443 tfh_user_polling_mode(tfh); 433 tfh_user_polling_mode(tfh);
444 else 434 else
445 gru_flush_cache(tfh); 435 gru_flush_cache(tfh);
@@ -512,7 +502,7 @@ irqreturn_t gru_intr(int irq, void *dev_id)
512 502
513static int gru_user_dropin(struct gru_thread_state *gts, 503static int gru_user_dropin(struct gru_thread_state *gts,
514 struct gru_tlb_fault_handle *tfh, 504 struct gru_tlb_fault_handle *tfh,
515 unsigned long __user *cb) 505 void *cb)
516{ 506{
517 struct gru_mm_struct *gms = gts->ts_gms; 507 struct gru_mm_struct *gms = gts->ts_gms;
518 int ret; 508 int ret;
@@ -538,7 +528,7 @@ int gru_handle_user_call_os(unsigned long cb)
538{ 528{
539 struct gru_tlb_fault_handle *tfh; 529 struct gru_tlb_fault_handle *tfh;
540 struct gru_thread_state *gts; 530 struct gru_thread_state *gts;
541 unsigned long __user *cbp; 531 void *cbk;
542 int ucbnum, cbrnum, ret = -EINVAL; 532 int ucbnum, cbrnum, ret = -EINVAL;
543 533
544 STAT(call_os); 534 STAT(call_os);
@@ -548,7 +538,6 @@ int gru_handle_user_call_os(unsigned long cb)
548 ucbnum = get_cb_number((void *)cb); 538 ucbnum = get_cb_number((void *)cb);
549 if ((cb & (GRU_HANDLE_STRIDE - 1)) || ucbnum >= GRU_NUM_CB) 539 if ((cb & (GRU_HANDLE_STRIDE - 1)) || ucbnum >= GRU_NUM_CB)
550 return -EINVAL; 540 return -EINVAL;
551 cbp = (unsigned long *)cb;
552 541
553 gts = gru_find_lock_gts(cb); 542 gts = gru_find_lock_gts(cb);
554 if (!gts) 543 if (!gts)
@@ -583,7 +572,9 @@ int gru_handle_user_call_os(unsigned long cb)
583 gru_unload_context(gts, 1); 572 gru_unload_context(gts, 1);
584 } else if (gts->ts_gru) { 573 } else if (gts->ts_gru) {
585 tfh = get_tfh_by_index(gts->ts_gru, cbrnum); 574 tfh = get_tfh_by_index(gts->ts_gru, cbrnum);
586 ret = gru_user_dropin(gts, tfh, cbp); 575 cbk = get_gseg_base_address_cb(gts->ts_gru->gs_gru_base_vaddr,
576 gts->ts_ctxnum, ucbnum);
577 ret = gru_user_dropin(gts, tfh, cbk);
587 } 578 }
588exit: 579exit:
589 gru_unlock_gts(gts); 580 gru_unlock_gts(gts);