aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCliff Wickman <cpw@sgi.com>2014-05-14 17:15:47 -0400
committerIngo Molnar <mingo@kernel.org>2014-06-05 08:17:20 -0400
commita26fd71953711acb4884df84e393d52de57e4f17 (patch)
tree327923aa12694c97e56b398c12a259919db87c75
parentfe455b17de6c881eecf4f9784c3b0483a5e3d19e (diff)
x86/uv: Update the UV3 TLB shootdown logic
Update of TLB shootdown code for UV3. Kernel function native_flush_tlb_others() calls uv_flush_tlb_others() on UV to invalidate tlb page definitions on remote cpus. The UV systems have a hardware 'broadcast assist unit' which can be used to broadcast shootdown messages to all cpu's of selected nodes. The behavior of the BAU has changed only slightly with UV3: - UV3 is recognized with is_uv3_hub(). - UV2 functions and structures (uv2_xxx) are in most cases simply renamed to uv2_3_xxx. - Some UV2 error workarounds are not needed for UV3. (see uv_bau_message_interrupt and enable_timeouts) Signed-off-by: Cliff Wickman <cpw@sgi.com> Link: http://lkml.kernel.org/r/E1WkgWh-0001yJ-3K@eag09.americas.sgi.com [ Removed a few linebreak uglies. ] Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/uv/uv_bau.h19
-rw-r--r--arch/x86/platform/uv/tlb_uv.c69
2 files changed, 49 insertions, 39 deletions
diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h
index 0b46ef261c77..2d60a7813dfe 100644
--- a/arch/x86/include/asm/uv/uv_bau.h
+++ b/arch/x86/include/asm/uv/uv_bau.h
@@ -73,6 +73,7 @@
73#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (is_uv1_hub() ? \ 73#define UV_INTD_SOFT_ACK_TIMEOUT_PERIOD (is_uv1_hub() ? \
74 UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD : \ 74 UV1_INTD_SOFT_ACK_TIMEOUT_PERIOD : \
75 UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD) 75 UV2_INTD_SOFT_ACK_TIMEOUT_PERIOD)
76/* assuming UV3 is the same */
76 77
77#define BAU_MISC_CONTROL_MULT_MASK 3 78#define BAU_MISC_CONTROL_MULT_MASK 3
78 79
@@ -93,6 +94,8 @@
93#define SOFTACK_MSHIFT UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT 94#define SOFTACK_MSHIFT UVH_LB_BAU_MISC_CONTROL_ENABLE_INTD_SOFT_ACK_MODE_SHFT
94#define SOFTACK_PSHIFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT 95#define SOFTACK_PSHIFT UVH_LB_BAU_MISC_CONTROL_INTD_SOFT_ACK_TIMEOUT_PERIOD_SHFT
95#define SOFTACK_TIMEOUT_PERIOD UV_INTD_SOFT_ACK_TIMEOUT_PERIOD 96#define SOFTACK_TIMEOUT_PERIOD UV_INTD_SOFT_ACK_TIMEOUT_PERIOD
97#define PREFETCH_HINT_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_INTD_PREFETCH_HINT_SHFT
98#define SB_STATUS_SHFT UV3H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT
96#define write_gmmr uv_write_global_mmr64 99#define write_gmmr uv_write_global_mmr64
97#define write_lmmr uv_write_local_mmr 100#define write_lmmr uv_write_local_mmr
98#define read_lmmr uv_read_local_mmr 101#define read_lmmr uv_read_local_mmr
@@ -322,8 +325,9 @@ struct uv1_bau_msg_header {
322/* 325/*
323 * UV2 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor) 326 * UV2 Message header: 16 bytes (128 bits) (bytes 0x30-0x3f of descriptor)
324 * see figure 9-2 of harp_sys.pdf 327 * see figure 9-2 of harp_sys.pdf
328 * assuming UV3 is the same
325 */ 329 */
326struct uv2_bau_msg_header { 330struct uv2_3_bau_msg_header {
327 unsigned int base_dest_nasid:15; /* nasid of the first bit */ 331 unsigned int base_dest_nasid:15; /* nasid of the first bit */
328 /* bits 14:0 */ /* in uvhub map */ 332 /* bits 14:0 */ /* in uvhub map */
329 unsigned int dest_subnodeid:5; /* must be 0x10, for the LB */ 333 unsigned int dest_subnodeid:5; /* must be 0x10, for the LB */
@@ -395,7 +399,7 @@ struct bau_desc {
395 */ 399 */
396 union bau_msg_header { 400 union bau_msg_header {
397 struct uv1_bau_msg_header uv1_hdr; 401 struct uv1_bau_msg_header uv1_hdr;
398 struct uv2_bau_msg_header uv2_hdr; 402 struct uv2_3_bau_msg_header uv2_3_hdr;
399 } header; 403 } header;
400 404
401 struct bau_msg_payload payload; 405 struct bau_msg_payload payload;
@@ -631,11 +635,6 @@ struct bau_control {
631 struct hub_and_pnode *thp; 635 struct hub_and_pnode *thp;
632}; 636};
633 637
634static inline unsigned long read_mmr_uv2_status(void)
635{
636 return read_lmmr(UV2H_LB_BAU_SB_ACTIVATION_STATUS_2);
637}
638
639static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image) 638static inline void write_mmr_data_broadcast(int pnode, unsigned long mmr_image)
640{ 639{
641 write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image); 640 write_gmmr(pnode, UVH_BAU_DATA_BROADCAST, mmr_image);
@@ -760,7 +759,11 @@ static inline int atomic_read_short(const struct atomic_short *v)
760 */ 759 */
761static inline int atom_asr(short i, struct atomic_short *v) 760static inline int atom_asr(short i, struct atomic_short *v)
762{ 761{
763 return i + xadd(&v->counter, i); 762 short __i = i;
763 asm volatile(LOCK_PREFIX "xaddw %0, %1"
764 : "+r" (i), "+m" (v->counter)
765 : : "memory");
766 return i + __i;
764} 767}
765 768
766/* 769/*
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index dfe605ac1bcd..ed161c6e278b 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * SGI UltraViolet TLB flush routines. 2 * SGI UltraViolet TLB flush routines.
3 * 3 *
4 * (c) 2008-2012 Cliff Wickman <cpw@sgi.com>, SGI. 4 * (c) 2008-2014 Cliff Wickman <cpw@sgi.com>, SGI.
5 * 5 *
6 * This code is released under the GNU General Public License version 2 or 6 * This code is released under the GNU General Public License version 2 or
7 * later. 7 * later.
@@ -451,7 +451,7 @@ static inline unsigned long long cycles_2_ns(unsigned long long cyc)
451 451
452/* 452/*
453 * The reverse of the above; converts a duration in ns to a duration in cycles. 453 * The reverse of the above; converts a duration in ns to a duration in cycles.
454 */ 454 */
455static inline unsigned long long ns_2_cycles(unsigned long long ns) 455static inline unsigned long long ns_2_cycles(unsigned long long ns)
456{ 456{
457 struct cyc2ns_data *data = cyc2ns_read_begin(); 457 struct cyc2ns_data *data = cyc2ns_read_begin();
@@ -563,7 +563,7 @@ static int uv1_wait_completion(struct bau_desc *bau_desc,
563 * UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register. 563 * UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register.
564 * But not currently used. 564 * But not currently used.
565 */ 565 */
566static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc) 566static unsigned long uv2_3_read_status(unsigned long offset, int rshft, int desc)
567{ 567{
568 unsigned long descriptor_status; 568 unsigned long descriptor_status;
569 569
@@ -606,7 +606,7 @@ int handle_uv2_busy(struct bau_control *bcp)
606 return FLUSH_GIVEUP; 606 return FLUSH_GIVEUP;
607} 607}
608 608
609static int uv2_wait_completion(struct bau_desc *bau_desc, 609static int uv2_3_wait_completion(struct bau_desc *bau_desc,
610 unsigned long mmr_offset, int right_shift, 610 unsigned long mmr_offset, int right_shift,
611 struct bau_control *bcp, long try) 611 struct bau_control *bcp, long try)
612{ 612{
@@ -616,7 +616,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
616 long busy_reps = 0; 616 long busy_reps = 0;
617 struct ptc_stats *stat = bcp->statp; 617 struct ptc_stats *stat = bcp->statp;
618 618
619 descriptor_stat = uv2_read_status(mmr_offset, right_shift, desc); 619 descriptor_stat = uv2_3_read_status(mmr_offset, right_shift, desc);
620 620
621 /* spin on the status MMR, waiting for it to go idle */ 621 /* spin on the status MMR, waiting for it to go idle */
622 while (descriptor_stat != UV2H_DESC_IDLE) { 622 while (descriptor_stat != UV2H_DESC_IDLE) {
@@ -658,8 +658,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
658 /* not to hammer on the clock */ 658 /* not to hammer on the clock */
659 busy_reps = 0; 659 busy_reps = 0;
660 ttm = get_cycles(); 660 ttm = get_cycles();
661 if ((ttm - bcp->send_message) > 661 if ((ttm - bcp->send_message) > bcp->timeout_interval)
662 bcp->timeout_interval)
663 return handle_uv2_busy(bcp); 662 return handle_uv2_busy(bcp);
664 } 663 }
665 /* 664 /*
@@ -667,8 +666,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
667 */ 666 */
668 cpu_relax(); 667 cpu_relax();
669 } 668 }
670 descriptor_stat = uv2_read_status(mmr_offset, right_shift, 669 descriptor_stat = uv2_3_read_status(mmr_offset, right_shift, desc);
671 desc);
672 } 670 }
673 bcp->conseccompletes++; 671 bcp->conseccompletes++;
674 return FLUSH_COMPLETE; 672 return FLUSH_COMPLETE;
@@ -679,8 +677,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
679 * which register to read and position in that register based on cpu in 677 * which register to read and position in that register based on cpu in
680 * current hub. 678 * current hub.
681 */ 679 */
682static int wait_completion(struct bau_desc *bau_desc, 680static int wait_completion(struct bau_desc *bau_desc, struct bau_control *bcp, long try)
683 struct bau_control *bcp, long try)
684{ 681{
685 int right_shift; 682 int right_shift;
686 unsigned long mmr_offset; 683 unsigned long mmr_offset;
@@ -695,11 +692,9 @@ static int wait_completion(struct bau_desc *bau_desc,
695 } 692 }
696 693
697 if (bcp->uvhub_version == 1) 694 if (bcp->uvhub_version == 1)
698 return uv1_wait_completion(bau_desc, mmr_offset, right_shift, 695 return uv1_wait_completion(bau_desc, mmr_offset, right_shift, bcp, try);
699 bcp, try);
700 else 696 else
701 return uv2_wait_completion(bau_desc, mmr_offset, right_shift, 697 return uv2_3_wait_completion(bau_desc