diff options
author | Cliff Wickman <cpw@sgi.com> | 2012-01-16 16:19:47 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2012-01-17 03:09:54 -0500 |
commit | c5d35d399e685acccc85a675e8765c26b2a9813a (patch) | |
tree | 5b66e875217ccc2e106162a089efddd5fec40c21 /arch/x86/include/asm/uv | |
parent | d059f9fa84a30e04279c6ff615e9e2cf3b260191 (diff) |
x86/UV2: Work around BAU bug
This patch implements a workaround for a UV2 hardware bug.
The bug is a non-atomic update of a memory-mapped register. When
hardware message delivery and software message acknowledge occur
simultaneously the pending message acknowledge for the arriving
message may be lost. This causes the sender's message status to
stay busy.
Part of the workaround is to not acknowledge a completed message
until it is verified that no other message is actually using the
resource that is mistakenly recorded in the completed message.
Part of the workaround is to test for long elapsed time in such
a busy condition, then handle it by using a spare sending
descriptor. The stay-busy condition is eventually timed out by
hardware, and then the original sending descriptor can be
re-used. Most of that logic change is in keeping track of the
current descriptor and the state of the spares.
The occurrences of the workaround are added to the BAU
statistics.
Signed-off-by: Cliff Wickman <cpw@sgi.com>
Link: http://lkml.kernel.org/r/20120116211947.GC5767@sgi.com
Cc: <stable@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/include/asm/uv')
-rw-r--r-- | arch/x86/include/asm/uv/uv_bau.h | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index 4a46b27ee9a0..1b82f7e87393 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h | |||
@@ -167,6 +167,7 @@ | |||
167 | #define FLUSH_RETRY_TIMEOUT 2 | 167 | #define FLUSH_RETRY_TIMEOUT 2 |
168 | #define FLUSH_GIVEUP 3 | 168 | #define FLUSH_GIVEUP 3 |
169 | #define FLUSH_COMPLETE 4 | 169 | #define FLUSH_COMPLETE 4 |
170 | #define FLUSH_RETRY_BUSYBUG 5 | ||
170 | 171 | ||
171 | /* | 172 | /* |
172 | * tuning the action when the numalink network is extremely delayed | 173 | * tuning the action when the numalink network is extremely delayed |
@@ -463,7 +464,6 @@ struct bau_pq_entry { | |||
463 | struct msg_desc { | 464 | struct msg_desc { |
464 | struct bau_pq_entry *msg; | 465 | struct bau_pq_entry *msg; |
465 | int msg_slot; | 466 | int msg_slot; |
466 | int swack_slot; | ||
467 | struct bau_pq_entry *queue_first; | 467 | struct bau_pq_entry *queue_first; |
468 | struct bau_pq_entry *queue_last; | 468 | struct bau_pq_entry *queue_last; |
469 | }; | 469 | }; |
@@ -517,6 +517,9 @@ struct ptc_stats { | |||
517 | unsigned long s_retry_messages; /* retry broadcasts */ | 517 | unsigned long s_retry_messages; /* retry broadcasts */ |
518 | unsigned long s_bau_reenabled; /* for bau enable/disable */ | 518 | unsigned long s_bau_reenabled; /* for bau enable/disable */ |
519 | unsigned long s_bau_disabled; /* for bau enable/disable */ | 519 | unsigned long s_bau_disabled; /* for bau enable/disable */ |
520 | unsigned long s_uv2_wars; /* uv2 workaround, perm. busy */ | ||
521 | unsigned long s_uv2_wars_hw; /* uv2 workaround, hiwater */ | ||
522 | unsigned long s_uv2_war_waits; /* uv2 workaround, long waits */ | ||
520 | /* destination statistics */ | 523 | /* destination statistics */ |
521 | unsigned long d_alltlb; /* times all tlb's on this | 524 | unsigned long d_alltlb; /* times all tlb's on this |
522 | cpu were flushed */ | 525 | cpu were flushed */ |
@@ -593,6 +596,8 @@ struct bau_control { | |||
593 | short cpus_in_socket; | 596 | short cpus_in_socket; |
594 | short cpus_in_uvhub; | 597 | short cpus_in_uvhub; |
595 | short partition_base_pnode; | 598 | short partition_base_pnode; |
599 | short using_desc; /* an index, like uvhub_cpu */ | ||
600 | unsigned int inuse_map; | ||
596 | unsigned short message_number; | 601 | unsigned short message_number; |
597 | unsigned short uvhub_quiesce; | 602 | unsigned short uvhub_quiesce; |
598 | short socket_acknowledge_count[DEST_Q_SIZE]; | 603 | short socket_acknowledge_count[DEST_Q_SIZE]; |
@@ -610,6 +615,7 @@ struct bau_control { | |||
610 | int cong_response_us; | 615 | int cong_response_us; |
611 | int cong_reps; | 616 | int cong_reps; |
612 | int cong_period; | 617 | int cong_period; |
618 | unsigned long clocks_per_100_usec; | ||
613 | cycles_t period_time; | 619 | cycles_t period_time; |
614 | long period_requests; | 620 | long period_requests; |
615 | struct hub_and_pnode *thp; | 621 | struct hub_and_pnode *thp; |
@@ -670,6 +676,11 @@ static inline void write_mmr_sw_ack(unsigned long mr) | |||
670 | uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr); | 676 | uv_write_local_mmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr); |
671 | } | 677 | } |
672 | 678 | ||
679 | static inline void write_gmmr_sw_ack(int pnode, unsigned long mr) | ||
680 | { | ||
681 | write_gmmr(pnode, UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE_ALIAS, mr); | ||
682 | } | ||
683 | |||
673 | static inline unsigned long read_mmr_sw_ack(void) | 684 | static inline unsigned long read_mmr_sw_ack(void) |
674 | { | 685 | { |
675 | return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE); | 686 | return read_lmmr(UVH_LB_BAU_INTD_SOFTWARE_ACKNOWLEDGE); |