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 | |
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')
-rw-r--r-- | drivers/misc/sgi-gru/grufault.c | 3 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grufile.c | 2 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 12 | ||||
-rw-r--r-- | drivers/misc/sgi-gru/grutables.h | 1 |
4 files changed, 14 insertions, 4 deletions
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c index a489807613f8..6d0681236db5 100644 --- a/drivers/misc/sgi-gru/grufault.c +++ b/drivers/misc/sgi-gru/grufault.c | |||
@@ -614,7 +614,7 @@ int gru_get_exception_detail(unsigned long arg) | |||
614 | } else if (gts->ts_gru) { | 614 | } else if (gts->ts_gru) { |
615 | cbrnum = thread_cbr_number(gts, ucbnum); | 615 | cbrnum = thread_cbr_number(gts, ucbnum); |
616 | cbe = get_cbe_by_index(gts->ts_gru, cbrnum); | 616 | cbe = get_cbe_by_index(gts->ts_gru, cbrnum); |
617 | prefetchw(cbe);/* Harmless on hardware, required for emulator */ | 617 | gru_flush_cache(cbe); /* CBE not coherent */ |
618 | excdet.opc = cbe->opccpy; | 618 | excdet.opc = cbe->opccpy; |
619 | excdet.exopc = cbe->exopccpy; | 619 | excdet.exopc = cbe->exopccpy; |
620 | excdet.ecause = cbe->ecause; | 620 | excdet.ecause = cbe->ecause; |
@@ -622,6 +622,7 @@ int gru_get_exception_detail(unsigned long arg) | |||
622 | excdet.exceptdet1 = cbe->idef3upd; | 622 | excdet.exceptdet1 = cbe->idef3upd; |
623 | excdet.cbrstate = cbe->cbrstate; | 623 | excdet.cbrstate = cbe->cbrstate; |
624 | excdet.cbrexecstatus = cbe->cbrexecstatus; | 624 | excdet.cbrexecstatus = cbe->cbrexecstatus; |
625 | gru_flush_cache(cbe); | ||
625 | ret = 0; | 626 | ret = 0; |
626 | } else { | 627 | } else { |
627 | ret = -EAGAIN; | 628 | ret = -EAGAIN; |
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index 796ac704795e..bfc88d1b2a5b 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c | |||
@@ -46,6 +46,7 @@ | |||
46 | 46 | ||
47 | struct gru_blade_state *gru_base[GRU_MAX_BLADES] __read_mostly; | 47 | struct gru_blade_state *gru_base[GRU_MAX_BLADES] __read_mostly; |
48 | unsigned long gru_start_paddr __read_mostly; | 48 | unsigned long gru_start_paddr __read_mostly; |
49 | void *gru_start_vaddr __read_mostly; | ||
49 | unsigned long gru_end_paddr __read_mostly; | 50 | unsigned long gru_end_paddr __read_mostly; |
50 | unsigned int gru_max_gids __read_mostly; | 51 | unsigned int gru_max_gids __read_mostly; |
51 | struct gru_stats_s gru_stats; | 52 | struct gru_stats_s gru_stats; |
@@ -376,7 +377,6 @@ static int __init gru_init(void) | |||
376 | { | 377 | { |
377 | int ret, irq, chip; | 378 | int ret, irq, chip; |
378 | char id[10]; | 379 | char id[10]; |
379 | void *gru_start_vaddr; | ||
380 | 380 | ||
381 | if (!is_uv_system()) | 381 | if (!is_uv_system()) |
382 | return 0; | 382 | return 0; |
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 | ||
diff --git a/drivers/misc/sgi-gru/grutables.h b/drivers/misc/sgi-gru/grutables.h index 246c63883ebf..665704683ab8 100644 --- a/drivers/misc/sgi-gru/grutables.h +++ b/drivers/misc/sgi-gru/grutables.h | |||
@@ -153,6 +153,7 @@ | |||
153 | extern struct gru_stats_s gru_stats; | 153 | extern struct gru_stats_s gru_stats; |
154 | extern struct gru_blade_state *gru_base[]; | 154 | extern struct gru_blade_state *gru_base[]; |
155 | extern unsigned long gru_start_paddr, gru_end_paddr; | 155 | extern unsigned long gru_start_paddr, gru_end_paddr; |
156 | extern void *gru_start_vaddr; | ||
156 | extern unsigned int gru_max_gids; | 157 | extern unsigned int gru_max_gids; |
157 | 158 | ||
158 | #define GRU_MAX_BLADES MAX_NUMNODES | 159 | #define GRU_MAX_BLADES MAX_NUMNODES |