diff options
author | Jack Steiner <steiner@sgi.com> | 2009-12-15 19:48:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 10:20:16 -0500 |
commit | 1848a710287b33a92c3c5b2f4c3ae201a879eb7e (patch) | |
tree | dec401fd0857ee69b34d88cb19ac1f9a0307c1ea /drivers/misc/sgi-gru | |
parent | c550222f64265c9384c45d7f691445386025a82b (diff) |
gru: fix bug in exception handling
Fix a GRU driver bug converting a CBR address to the context that contains
the CBR. The conversion is rarely done so performance does not matter.
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')
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 30 |
1 files changed, 22 insertions, 8 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index d9ff0289a1c3..c13342dda5fd 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
@@ -97,9 +97,6 @@ | |||
97 | #define ASYNC_HAN_TO_BID(h) ((h) - 1) | 97 | #define ASYNC_HAN_TO_BID(h) ((h) - 1) |
98 | #define ASYNC_BID_TO_HAN(b) ((b) + 1) | 98 | #define ASYNC_BID_TO_HAN(b) ((b) + 1) |
99 | #define ASYNC_HAN_TO_BS(h) gru_base[ASYNC_HAN_TO_BID(h)] | 99 | #define ASYNC_HAN_TO_BS(h) gru_base[ASYNC_HAN_TO_BID(h)] |
100 | #define KCB_TO_GID(cb) ((cb - gru_start_vaddr) / \ | ||
101 | (GRU_SIZE * GRU_CHIPLETS_PER_BLADE)) | ||
102 | #define KCB_TO_BS(cb) gru_base[KCB_TO_GID(cb)] | ||
103 | 100 | ||
104 | #define GRU_NUM_KERNEL_CBR 1 | 101 | #define GRU_NUM_KERNEL_CBR 1 |
105 | #define GRU_NUM_KERNEL_DSR_BYTES 256 | 102 | #define GRU_NUM_KERNEL_DSR_BYTES 256 |
@@ -388,11 +385,28 @@ int gru_get_cb_exception_detail(void *cb, | |||
388 | struct control_block_extended_exc_detail *excdet) | 385 | struct control_block_extended_exc_detail *excdet) |
389 | { | 386 | { |
390 | struct gru_control_block_extended *cbe; | 387 | struct gru_control_block_extended *cbe; |
391 | struct gru_blade_state *bs; | 388 | struct gru_thread_state *kgts = NULL; |
392 | int cbrnum; | 389 | unsigned long off; |
393 | 390 | int cbrnum, bid; | |
394 | bs = KCB_TO_BS(cb); | 391 | |
395 | cbrnum = thread_cbr_number(bs->bs_kgts, get_cb_number(cb)); | 392 | /* |
393 | * Locate kgts for cb. This algorithm is SLOW but | ||
394 | * this function is rarely called (ie., almost never). | ||
395 | * Performance does not matter. | ||
396 | */ | ||
397 | for_each_possible_blade(bid) { | ||
398 | if (!gru_base[bid]) | ||
399 | break; | ||
400 | kgts = gru_base[bid]->bs_kgts; | ||
401 | if (!kgts || !kgts->ts_gru) | ||
402 | continue; | ||
403 | off = cb - kgts->ts_gru->gs_gru_base_vaddr; | ||
404 | if (off < GRU_SIZE) | ||
405 | break; | ||
406 | kgts = NULL; | ||
407 | } | ||
408 | BUG_ON(!kgts); | ||
409 | cbrnum = thread_cbr_number(kgts, get_cb_number(cb)); | ||
396 | cbe = get_cbe(GRUBASE(cb), cbrnum); | 410 | cbe = get_cbe(GRUBASE(cb), cbrnum); |
397 | gru_flush_cache(cbe); /* CBE not coherent */ | 411 | gru_flush_cache(cbe); /* CBE not coherent */ |
398 | sync_core(); | 412 | sync_core(); |