diff options
author | Jack Steiner <steiner@sgi.com> | 2009-06-17 19:28:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-18 16:04:02 -0400 |
commit | 1a2c09e3b41e334b6651d53b39cfe8ceefbc45f8 (patch) | |
tree | f005fcb5c5251256767b15f4a23ee220e6de5c88 /drivers/misc/sgi-gru/grukservices.c | |
parent | 270952a907220c0331fdaecbb55df892921c5e2d (diff) |
gru: fix cache coherency issues with instruction retry
Fix two problems related to GRU instruction failures. Cache coherency is
not maintained for CBEs except when loading or unloading contexts. When
reading a CBE to extract error information, the CBE must first be flushed
from the cache.
The function that reads kerrnel CBEs was reading the wrong CBE.
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/grukservices.c')
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index ba6fcd963f30..7586b89fd0d3 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c | |||
@@ -98,6 +98,9 @@ | |||
98 | #define ASYNC_HAN_TO_BID(h) ((h) - 1) | 98 | #define ASYNC_HAN_TO_BID(h) ((h) - 1) |
99 | #define ASYNC_BID_TO_HAN(b) ((b) + 1) | 99 | #define ASYNC_BID_TO_HAN(b) ((b) + 1) |
100 | #define ASYNC_HAN_TO_BS(h) gru_base[ASYNC_HAN_TO_BID(h)] | 100 | #define ASYNC_HAN_TO_BS(h) gru_base[ASYNC_HAN_TO_BID(h)] |
101 | #define KCB_TO_GID(cb) ((cb - gru_start_vaddr) / \ | ||
102 | (GRU_SIZE * GRU_CHIPLETS_PER_BLADE)) | ||
103 | #define KCB_TO_BS(cb) gru_base[KCB_TO_GID(cb)] | ||
101 | 104 | ||
102 | #define GRU_NUM_KERNEL_CBR 1 | 105 | #define GRU_NUM_KERNEL_CBR 1 |
103 | #define GRU_NUM_KERNEL_DSR_BYTES 256 | 106 | #define GRU_NUM_KERNEL_DSR_BYTES 256 |
@@ -354,14 +357,19 @@ int gru_get_cb_exception_detail(void *cb, | |||
354 | struct control_block_extended_exc_detail *excdet) | 357 | struct control_block_extended_exc_detail *excdet) |
355 | { | 358 | { |
356 | struct gru_control_block_extended *cbe; | 359 | struct gru_control_block_extended *cbe; |
360 | struct gru_blade_state *bs; | ||
361 | int cbrnum; | ||
357 | 362 | ||
358 | cbe = get_cbe(GRUBASE(cb), get_cb_number(cb)); | 363 | bs = KCB_TO_BS(cb); |
359 | prefetchw(cbe); /* Harmless on hardware, required for emulator */ | 364 | cbrnum = thread_cbr_number(bs->bs_kgts, get_cb_number(cb)); |
365 | cbe = get_cbe(GRUBASE(cb), cbrnum); | ||
366 | gru_flush_cache(cbe); /* CBE not coherent */ | ||
360 | excdet->opc = cbe->opccpy; | 367 | excdet->opc = cbe->opccpy; |
361 | excdet->exopc = cbe->exopccpy; | 368 | excdet->exopc = cbe->exopccpy; |
362 | excdet->ecause = cbe->ecause; | 369 | excdet->ecause = cbe->ecause; |
363 | excdet->exceptdet0 = cbe->idef1upd; | 370 | excdet->exceptdet0 = cbe->idef1upd; |
364 | excdet->exceptdet1 = cbe->idef3upd; | 371 | excdet->exceptdet1 = cbe->idef3upd; |
372 | gru_flush_cache(cbe); | ||
365 | return 0; | 373 | return 0; |
366 | } | 374 | } |
367 | 375 | ||