diff options
author | Robin Holt <holt@sgi.com> | 2009-04-13 17:40:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-13 18:04:33 -0400 |
commit | a374c57b0764432a80303abee3d1afd1939b5a0a (patch) | |
tree | b3e15b590d5342e5de6c2b62da4dd61fb2ad0836 /drivers/misc | |
parent | a06bba4643ae10ac6b202dade1cde38bc5e08b25 (diff) |
sgi-xpc: prevent false heartbeat failures
The heartbeat timeout functionality in sgi-xpc is currently not trained to
the connection time. If a connection is made and the code is in the last
polling window prior to doing a timeout, the next polling window will see
the heartbeat as unchanged and initiate a no-heartbeat disconnect.
Signed-off-by: Robin Holt <holt@sgi.com>
Signed-off-by: Dean Nelson <dcn@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')
-rw-r--r-- | drivers/misc/sgi-xp/xpc.h | 100 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_main.c | 8 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_sn2.c | 44 | ||||
-rw-r--r-- | drivers/misc/sgi-xp/xpc_uv.c | 123 |
4 files changed, 123 insertions, 152 deletions
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index 114444cfd496..da32bbe8caaf 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h | |||
@@ -90,18 +90,21 @@ struct xpc_rsvd_page { | |||
90 | short max_npartitions; /* value of XPC_MAX_PARTITIONS */ | 90 | short max_npartitions; /* value of XPC_MAX_PARTITIONS */ |
91 | u8 version; | 91 | u8 version; |
92 | u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */ | 92 | u8 pad1[3]; /* align to next u64 in 1st 64-byte cacheline */ |
93 | unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */ | ||
93 | union { | 94 | union { |
94 | unsigned long vars_pa; /* phys address of struct xpc_vars */ | 95 | struct { |
95 | unsigned long activate_gru_mq_desc_gpa; /* phys addr of */ | 96 | unsigned long vars_pa; /* phys addr */ |
96 | /* activate mq's */ | 97 | } sn2; |
97 | /* gru mq descriptor */ | 98 | struct { |
99 | unsigned long heartbeat_gpa; /* phys addr */ | ||
100 | unsigned long activate_gru_mq_desc_gpa; /* phys addr */ | ||
101 | } uv; | ||
98 | } sn; | 102 | } sn; |
99 | unsigned long ts_jiffies; /* timestamp when rsvd pg was setup by XPC */ | 103 | u64 pad2[9]; /* align to last u64 in 2nd 64-byte cacheline */ |
100 | u64 pad2[10]; /* align to last u64 in 2nd 64-byte cacheline */ | ||
101 | u64 SAL_nasids_size; /* SAL: size of each nasid mask in bytes */ | 104 | u64 SAL_nasids_size; /* SAL: size of each nasid mask in bytes */ |
102 | }; | 105 | }; |
103 | 106 | ||
104 | #define XPC_RP_VERSION _XPC_VERSION(2, 0) /* version 2.0 of the reserved page */ | 107 | #define XPC_RP_VERSION _XPC_VERSION(3, 0) /* version 3.0 of the reserved page */ |
105 | 108 | ||
106 | /* | 109 | /* |
107 | * Define the structures by which XPC variables can be exported to other | 110 | * Define the structures by which XPC variables can be exported to other |
@@ -182,6 +185,17 @@ struct xpc_vars_part_sn2 { | |||
182 | (XPC_RP_MACH_NASIDS(_rp) + \ | 185 | (XPC_RP_MACH_NASIDS(_rp) + \ |
183 | xpc_nasid_mask_nlongs)) | 186 | xpc_nasid_mask_nlongs)) |
184 | 187 | ||
188 | |||
189 | /* | ||
190 | * The following structure describes the partition's heartbeat info which | ||
191 | * will be periodically read by other partitions to determine whether this | ||
192 | * XPC is still 'alive'. | ||
193 | */ | ||
194 | struct xpc_heartbeat_uv { | ||
195 | unsigned long value; | ||
196 | unsigned long offline; /* if 0, heartbeat should be changing */ | ||
197 | }; | ||
198 | |||
185 | /* | 199 | /* |
186 | * Info pertinent to a GRU message queue using a watch list for irq generation. | 200 | * Info pertinent to a GRU message queue using a watch list for irq generation. |
187 | */ | 201 | */ |
@@ -198,7 +212,7 @@ struct xpc_gru_mq_uv { | |||
198 | 212 | ||
199 | /* | 213 | /* |
200 | * The activate_mq is used to send/receive GRU messages that affect XPC's | 214 | * The activate_mq is used to send/receive GRU messages that affect XPC's |
201 | * heartbeat, partition active state, and channel state. This is UV only. | 215 | * partition active state and channel state. This is uv only. |
202 | */ | 216 | */ |
203 | struct xpc_activate_mq_msghdr_uv { | 217 | struct xpc_activate_mq_msghdr_uv { |
204 | unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */ | 218 | unsigned int gru_msg_hdr; /* FOR GRU INTERNAL USE ONLY */ |
@@ -210,33 +224,26 @@ struct xpc_activate_mq_msghdr_uv { | |||
210 | 224 | ||
211 | /* activate_mq defined message types */ | 225 | /* activate_mq defined message types */ |
212 | #define XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV 0 | 226 | #define XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV 0 |
213 | #define XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV 1 | ||
214 | #define XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV 2 | ||
215 | #define XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV 3 | ||
216 | 227 | ||
217 | #define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV 4 | 228 | #define XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV 1 |
218 | #define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV 5 | 229 | #define XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV 2 |
219 | 230 | ||
220 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV 6 | 231 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV 3 |
221 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV 7 | 232 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV 4 |
222 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV 8 | 233 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV 5 |
223 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV 9 | 234 | #define XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV 6 |
224 | 235 | ||
225 | #define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV 10 | 236 | #define XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV 7 |
226 | #define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 11 | 237 | #define XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV 8 |
227 | 238 | ||
228 | struct xpc_activate_mq_msg_uv { | 239 | struct xpc_activate_mq_msg_uv { |
229 | struct xpc_activate_mq_msghdr_uv hdr; | 240 | struct xpc_activate_mq_msghdr_uv hdr; |
230 | }; | 241 | }; |
231 | 242 | ||
232 | struct xpc_activate_mq_msg_heartbeat_req_uv { | ||
233 | struct xpc_activate_mq_msghdr_uv hdr; | ||
234 | u64 heartbeat; | ||
235 | }; | ||
236 | |||
237 | struct xpc_activate_mq_msg_activate_req_uv { | 243 | struct xpc_activate_mq_msg_activate_req_uv { |
238 | struct xpc_activate_mq_msghdr_uv hdr; | 244 | struct xpc_activate_mq_msghdr_uv hdr; |
239 | unsigned long rp_gpa; | 245 | unsigned long rp_gpa; |
246 | unsigned long heartbeat_gpa; | ||
240 | unsigned long activate_gru_mq_desc_gpa; | 247 | unsigned long activate_gru_mq_desc_gpa; |
241 | }; | 248 | }; |
242 | 249 | ||
@@ -687,6 +694,9 @@ struct xpc_partition_sn2 { | |||
687 | }; | 694 | }; |
688 | 695 | ||
689 | struct xpc_partition_uv { | 696 | struct xpc_partition_uv { |
697 | unsigned long heartbeat_gpa; /* phys addr of partition's heartbeat */ | ||
698 | struct xpc_heartbeat_uv cached_heartbeat; /* cached copy of */ | ||
699 | /* partition's heartbeat */ | ||
690 | unsigned long activate_gru_mq_desc_gpa; /* phys addr of parititon's */ | 700 | unsigned long activate_gru_mq_desc_gpa; /* phys addr of parititon's */ |
691 | /* activate mq's gru mq */ | 701 | /* activate mq's gru mq */ |
692 | /* descriptor */ | 702 | /* descriptor */ |
@@ -698,14 +708,12 @@ struct xpc_partition_uv { | |||
698 | u8 remote_act_state; /* remote partition's act_state */ | 708 | u8 remote_act_state; /* remote partition's act_state */ |
699 | u8 act_state_req; /* act_state request from remote partition */ | 709 | u8 act_state_req; /* act_state request from remote partition */ |
700 | enum xp_retval reason; /* reason for deactivate act_state request */ | 710 | enum xp_retval reason; /* reason for deactivate act_state request */ |
701 | u64 heartbeat; /* incremented by remote partition */ | ||
702 | }; | 711 | }; |
703 | 712 | ||
704 | /* struct xpc_partition_uv flags */ | 713 | /* struct xpc_partition_uv flags */ |
705 | 714 | ||
706 | #define XPC_P_HEARTBEAT_OFFLINE_UV 0x00000001 | 715 | #define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000001 |
707 | #define XPC_P_ENGAGED_UV 0x00000002 | 716 | #define XPC_P_ENGAGED_UV 0x00000002 |
708 | #define XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV 0x00000004 | ||
709 | 717 | ||
710 | /* struct xpc_partition_uv act_state change requests */ | 718 | /* struct xpc_partition_uv act_state change requests */ |
711 | 719 | ||
@@ -807,7 +815,6 @@ extern int xpc_disengage_timedout; | |||
807 | extern int xpc_activate_IRQ_rcvd; | 815 | extern int xpc_activate_IRQ_rcvd; |
808 | extern spinlock_t xpc_activate_IRQ_rcvd_lock; | 816 | extern spinlock_t xpc_activate_IRQ_rcvd_lock; |
809 | extern wait_queue_head_t xpc_activate_IRQ_wq; | 817 | extern wait_queue_head_t xpc_activate_IRQ_wq; |
810 | extern void *xpc_heartbeating_to_mask; | ||
811 | extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **); | 818 | extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **); |
812 | extern void xpc_activate_partition(struct xpc_partition *); | 819 | extern void xpc_activate_partition(struct xpc_partition *); |
813 | extern void xpc_activate_kthreads(struct xpc_channel *, int); | 820 | extern void xpc_activate_kthreads(struct xpc_channel *, int); |
@@ -825,6 +832,9 @@ extern void (*xpc_increment_heartbeat) (void); | |||
825 | extern void (*xpc_offline_heartbeat) (void); | 832 | extern void (*xpc_offline_heartbeat) (void); |
826 | extern void (*xpc_online_heartbeat) (void); | 833 | extern void (*xpc_online_heartbeat) (void); |
827 | extern enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *); | 834 | extern enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *); |
835 | extern void (*xpc_allow_hb) (short); | ||
836 | extern void (*xpc_disallow_hb) (short); | ||
837 | extern void (*xpc_disallow_all_hbs) (void); | ||
828 | extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *); | 838 | extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *); |
829 | extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *); | 839 | extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *); |
830 | extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *); | 840 | extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *); |
@@ -909,40 +919,6 @@ extern void xpc_disconnect_channel(const int, struct xpc_channel *, | |||
909 | extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval); | 919 | extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval); |
910 | extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval); | 920 | extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval); |
911 | 921 | ||
912 | static inline int | ||
913 | xpc_hb_allowed(short partid, void *heartbeating_to_mask) | ||
914 | { | ||
915 | return test_bit(partid, heartbeating_to_mask); | ||
916 | } | ||
917 | |||
918 | static inline int | ||
919 | xpc_any_hbs_allowed(void) | ||
920 | { | ||
921 | DBUG_ON(xpc_heartbeating_to_mask == NULL); | ||
922 | return !bitmap_empty(xpc_heartbeating_to_mask, xp_max_npartitions); | ||
923 | } | ||
924 | |||
925 | static inline void | ||
926 | xpc_allow_hb(short partid) | ||
927 | { | ||
928 | DBUG_ON(xpc_heartbeating_to_mask == NULL); | ||
929 | set_bit(partid, xpc_heartbeating_to_mask); | ||
930 | } | ||
931 | |||
932 | static inline void | ||
933 | xpc_disallow_hb(short partid) | ||
934 | { | ||
935 | DBUG_ON(xpc_heartbeating_to_mask == NULL); | ||
936 | clear_bit(partid, xpc_heartbeating_to_mask); | ||
937 | } | ||
938 | |||
939 | static inline void | ||
940 | xpc_disallow_all_hbs(void) | ||
941 | { | ||
942 | DBUG_ON(xpc_heartbeating_to_mask == NULL); | ||
943 | bitmap_zero(xpc_heartbeating_to_mask, xp_max_npartitions); | ||
944 | } | ||
945 | |||
946 | static inline void | 922 | static inline void |
947 | xpc_wakeup_channel_mgr(struct xpc_partition *part) | 923 | xpc_wakeup_channel_mgr(struct xpc_partition *part) |
948 | { | 924 | { |
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 1ab9fda87fab..34b084cd63da 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2004-2008 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2004-2009 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
@@ -150,7 +150,6 @@ DECLARE_WAIT_QUEUE_HEAD(xpc_activate_IRQ_wq); | |||
150 | 150 | ||
151 | static unsigned long xpc_hb_check_timeout; | 151 | static unsigned long xpc_hb_check_timeout; |
152 | static struct timer_list xpc_hb_timer; | 152 | static struct timer_list xpc_hb_timer; |
153 | void *xpc_heartbeating_to_mask; | ||
154 | 153 | ||
155 | /* notification that the xpc_hb_checker thread has exited */ | 154 | /* notification that the xpc_hb_checker thread has exited */ |
156 | static DECLARE_COMPLETION(xpc_hb_checker_exited); | 155 | static DECLARE_COMPLETION(xpc_hb_checker_exited); |
@@ -176,6 +175,10 @@ enum xp_retval (*xpc_get_partition_rsvd_page_pa) (void *buf, u64 *cookie, | |||
176 | unsigned long *rp_pa, | 175 | unsigned long *rp_pa, |
177 | size_t *len); | 176 | size_t *len); |
178 | int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp); | 177 | int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp); |
178 | |||
179 | void (*xpc_allow_hb) (short partid); | ||
180 | void (*xpc_disallow_hb) (short partid); | ||
181 | void (*xpc_disallow_all_hbs) (void); | ||
179 | void (*xpc_heartbeat_init) (void); | 182 | void (*xpc_heartbeat_init) (void); |
180 | void (*xpc_heartbeat_exit) (void); | 183 | void (*xpc_heartbeat_exit) (void); |
181 | void (*xpc_increment_heartbeat) (void); | 184 | void (*xpc_increment_heartbeat) (void); |
@@ -1087,7 +1090,6 @@ xpc_do_exit(enum xp_retval reason) | |||
1087 | } while (1); | 1090 | } while (1); |
1088 | 1091 | ||
1089 | DBUG_ON(xpc_any_partition_engaged()); | 1092 | DBUG_ON(xpc_any_partition_engaged()); |
1090 | DBUG_ON(xpc_any_hbs_allowed() != 0); | ||
1091 | 1093 | ||
1092 | xpc_teardown_rsvd_page(); | 1094 | xpc_teardown_rsvd_page(); |
1093 | 1095 | ||
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c index eaaa964942de..43ad2968daf5 100644 --- a/drivers/misc/sgi-xp/xpc_sn2.c +++ b/drivers/misc/sgi-xp/xpc_sn2.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * License. See the file "COPYING" in the main directory of this archive | 3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. | 4 | * for more details. |
5 | * | 5 | * |
6 | * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. | 6 | * Copyright (c) 2008-2009 Silicon Graphics, Inc. All Rights Reserved. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | /* | 9 | /* |
@@ -629,7 +629,7 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp) | |||
629 | 629 | ||
630 | xpc_vars_sn2 = XPC_RP_VARS(rp); | 630 | xpc_vars_sn2 = XPC_RP_VARS(rp); |
631 | 631 | ||
632 | rp->sn.vars_pa = xp_pa(xpc_vars_sn2); | 632 | rp->sn.sn2.vars_pa = xp_pa(xpc_vars_sn2); |
633 | 633 | ||
634 | /* vars_part array follows immediately after vars */ | 634 | /* vars_part array follows immediately after vars */ |
635 | xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) + | 635 | xpc_vars_part_sn2 = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) + |
@@ -693,6 +693,33 @@ xpc_setup_rsvd_page_sn_sn2(struct xpc_rsvd_page *rp) | |||
693 | return 0; | 693 | return 0; |
694 | } | 694 | } |
695 | 695 | ||
696 | static int | ||
697 | xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask) | ||
698 | { | ||
699 | return test_bit(partid, heartbeating_to_mask); | ||
700 | } | ||
701 | |||
702 | static void | ||
703 | xpc_allow_hb_sn2(short partid) | ||
704 | { | ||
705 | DBUG_ON(xpc_vars_sn2 == NULL); | ||
706 | set_bit(partid, xpc_vars_sn2->heartbeating_to_mask); | ||
707 | } | ||
708 | |||
709 | static void | ||
710 | xpc_disallow_hb_sn2(short partid) | ||
711 | { | ||
712 | DBUG_ON(xpc_vars_sn2 == NULL); | ||
713 | clear_bit(partid, xpc_vars_sn2->heartbeating_to_mask); | ||
714 | } | ||
715 | |||
716 | static void | ||
717 | xpc_disallow_all_hbs_sn2(void) | ||
718 | { | ||
719 | DBUG_ON(xpc_vars_sn2 == NULL); | ||
720 | bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, xp_max_npartitions); | ||
721 | } | ||
722 | |||
696 | static void | 723 | static void |
697 | xpc_increment_heartbeat_sn2(void) | 724 | xpc_increment_heartbeat_sn2(void) |
698 | { | 725 | { |
@@ -719,7 +746,6 @@ xpc_heartbeat_init_sn2(void) | |||
719 | DBUG_ON(xpc_vars_sn2 == NULL); | 746 | DBUG_ON(xpc_vars_sn2 == NULL); |
720 | 747 | ||
721 | bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2); | 748 | bitmap_zero(xpc_vars_sn2->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2); |
722 | xpc_heartbeating_to_mask = &xpc_vars_sn2->heartbeating_to_mask[0]; | ||
723 | xpc_online_heartbeat_sn2(); | 749 | xpc_online_heartbeat_sn2(); |
724 | } | 750 | } |
725 | 751 | ||
@@ -751,9 +777,9 @@ xpc_get_remote_heartbeat_sn2(struct xpc_partition *part) | |||
751 | remote_vars->heartbeating_to_mask[0]); | 777 | remote_vars->heartbeating_to_mask[0]); |
752 | 778 | ||
753 | if ((remote_vars->heartbeat == part->last_heartbeat && | 779 | if ((remote_vars->heartbeat == part->last_heartbeat && |
754 | remote_vars->heartbeat_offline == 0) || | 780 | !remote_vars->heartbeat_offline) || |
755 | !xpc_hb_allowed(sn_partition_id, | 781 | !xpc_hb_allowed_sn2(sn_partition_id, |
756 | &remote_vars->heartbeating_to_mask)) { | 782 | remote_vars->heartbeating_to_mask)) { |
757 | ret = xpNoHeartbeat; | 783 | ret = xpNoHeartbeat; |
758 | } else { | 784 | } else { |
759 | part->last_heartbeat = remote_vars->heartbeat; | 785 | part->last_heartbeat = remote_vars->heartbeat; |
@@ -972,7 +998,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid) | |||
972 | return; | 998 | return; |
973 | } | 999 | } |
974 | 1000 | ||
975 | remote_vars_pa = remote_rp->sn.vars_pa; | 1001 | remote_vars_pa = remote_rp->sn.sn2.vars_pa; |
976 | remote_rp_version = remote_rp->version; | 1002 | remote_rp_version = remote_rp->version; |
977 | remote_rp_ts_jiffies = remote_rp->ts_jiffies; | 1003 | remote_rp_ts_jiffies = remote_rp->ts_jiffies; |
978 | 1004 | ||
@@ -2325,6 +2351,10 @@ xpc_init_sn2(void) | |||
2325 | xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_sn2; | 2351 | xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_sn2; |
2326 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2; | 2352 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_sn2; |
2327 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2; | 2353 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_sn2; |
2354 | |||
2355 | xpc_allow_hb = xpc_allow_hb_sn2; | ||
2356 | xpc_disallow_hb = xpc_disallow_hb_sn2; | ||
2357 | xpc_disallow_all_hbs = xpc_disallow_all_hbs_sn2; | ||
2328 | xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; | 2358 | xpc_increment_heartbeat = xpc_increment_heartbeat_sn2; |
2329 | xpc_offline_heartbeat = xpc_offline_heartbeat_sn2; | 2359 | xpc_offline_heartbeat = xpc_offline_heartbeat_sn2; |
2330 | xpc_online_heartbeat = xpc_online_heartbeat_sn2; | 2360 | xpc_online_heartbeat = xpc_online_heartbeat_sn2; |
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index f7fff4727edb..97f7cb21a0a2 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c | |||
@@ -46,8 +46,7 @@ struct uv_IO_APIC_route_entry { | |||
46 | }; | 46 | }; |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | static atomic64_t xpc_heartbeat_uv; | 49 | static struct xpc_heartbeat_uv *xpc_heartbeat_uv; |
50 | static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); | ||
51 | 50 | ||
52 | #define XPC_ACTIVATE_MSG_SIZE_UV (1 * GRU_CACHE_LINE_BYTES) | 51 | #define XPC_ACTIVATE_MSG_SIZE_UV (1 * GRU_CACHE_LINE_BYTES) |
53 | #define XPC_ACTIVATE_MQ_SIZE_UV (4 * XP_MAX_NPARTITIONS_UV * \ | 52 | #define XPC_ACTIVATE_MQ_SIZE_UV (4 * XP_MAX_NPARTITIONS_UV * \ |
@@ -423,41 +422,6 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
423 | /* syncing of remote_act_state was just done above */ | 422 | /* syncing of remote_act_state was just done above */ |
424 | break; | 423 | break; |
425 | 424 | ||
426 | case XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV: { | ||
427 | struct xpc_activate_mq_msg_heartbeat_req_uv *msg; | ||
428 | |||
429 | msg = container_of(msg_hdr, | ||
430 | struct xpc_activate_mq_msg_heartbeat_req_uv, | ||
431 | hdr); | ||
432 | part_uv->heartbeat = msg->heartbeat; | ||
433 | break; | ||
434 | } | ||
435 | case XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV: { | ||
436 | struct xpc_activate_mq_msg_heartbeat_req_uv *msg; | ||
437 | |||
438 | msg = container_of(msg_hdr, | ||
439 | struct xpc_activate_mq_msg_heartbeat_req_uv, | ||
440 | hdr); | ||
441 | part_uv->heartbeat = msg->heartbeat; | ||
442 | |||
443 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
444 | part_uv->flags |= XPC_P_HEARTBEAT_OFFLINE_UV; | ||
445 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
446 | break; | ||
447 | } | ||
448 | case XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV: { | ||
449 | struct xpc_activate_mq_msg_heartbeat_req_uv *msg; | ||
450 | |||
451 | msg = container_of(msg_hdr, | ||
452 | struct xpc_activate_mq_msg_heartbeat_req_uv, | ||
453 | hdr); | ||
454 | part_uv->heartbeat = msg->heartbeat; | ||
455 | |||
456 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
457 | part_uv->flags &= ~XPC_P_HEARTBEAT_OFFLINE_UV; | ||
458 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
459 | break; | ||
460 | } | ||
461 | case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: { | 425 | case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: { |
462 | struct xpc_activate_mq_msg_activate_req_uv *msg; | 426 | struct xpc_activate_mq_msg_activate_req_uv *msg; |
463 | 427 | ||
@@ -475,6 +439,7 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
475 | part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; | 439 | part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; |
476 | part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ | 440 | part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ |
477 | part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; | 441 | part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; |
442 | part_uv->heartbeat_gpa = msg->heartbeat_gpa; | ||
478 | 443 | ||
479 | if (msg->activate_gru_mq_desc_gpa != | 444 | if (msg->activate_gru_mq_desc_gpa != |
480 | part_uv->activate_gru_mq_desc_gpa) { | 445 | part_uv->activate_gru_mq_desc_gpa) { |
@@ -759,7 +724,7 @@ xpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req) | |||
759 | 724 | ||
760 | /* | 725 | /* |
761 | * !!! Make our side think that the remote partition sent an activate | 726 | * !!! Make our side think that the remote partition sent an activate |
762 | * !!! message our way by doing what the activate IRQ handler would | 727 | * !!! mq message our way by doing what the activate IRQ handler would |
763 | * !!! do had one really been sent. | 728 | * !!! do had one really been sent. |
764 | */ | 729 | */ |
765 | 730 | ||
@@ -808,88 +773,80 @@ xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa, | |||
808 | static int | 773 | static int |
809 | xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) | 774 | xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) |
810 | { | 775 | { |
811 | rp->sn.activate_gru_mq_desc_gpa = | 776 | xpc_heartbeat_uv = |
777 | &xpc_partitions[sn_partition_id].sn.uv.cached_heartbeat; | ||
778 | rp->sn.uv.heartbeat_gpa = uv_gpa(xpc_heartbeat_uv); | ||
779 | rp->sn.uv.activate_gru_mq_desc_gpa = | ||
812 | uv_gpa(xpc_activate_mq_uv->gru_mq_desc); | 780 | uv_gpa(xpc_activate_mq_uv->gru_mq_desc); |
813 | return 0; | 781 | return 0; |
814 | } | 782 | } |
815 | 783 | ||
816 | static void | 784 | static void |
817 | xpc_send_heartbeat_uv(int msg_type) | 785 | xpc_allow_hb_uv(short partid) |
818 | { | 786 | { |
819 | short partid; | 787 | } |
820 | struct xpc_partition *part; | ||
821 | struct xpc_activate_mq_msg_heartbeat_req_uv msg; | ||
822 | |||
823 | /* | ||
824 | * !!! On uv we're broadcasting a heartbeat message every 5 seconds. | ||
825 | * !!! Whereas on sn2 we're bte_copy'ng the heartbeat info every 20 | ||
826 | * !!! seconds. This is an increase in numalink traffic. | ||
827 | * ??? Is this good? | ||
828 | */ | ||
829 | |||
830 | msg.heartbeat = atomic64_inc_return(&xpc_heartbeat_uv); | ||
831 | |||
832 | partid = find_first_bit(xpc_heartbeating_to_mask_uv, | ||
833 | XP_MAX_NPARTITIONS_UV); | ||
834 | |||
835 | while (partid < XP_MAX_NPARTITIONS_UV) { | ||
836 | part = &xpc_partitions[partid]; | ||
837 | 788 | ||
838 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), | 789 | static void |
839 | msg_type); | 790 | xpc_disallow_hb_uv(short partid) |
791 | { | ||
792 | } | ||
840 | 793 | ||
841 | partid = find_next_bit(xpc_heartbeating_to_mask_uv, | 794 | static void |
842 | XP_MAX_NPARTITIONS_UV, partid + 1); | 795 | xpc_disallow_all_hbs_uv(void) |
843 | } | 796 | { |
844 | } | 797 | } |
845 | 798 | ||
846 | static void | 799 | static void |
847 | xpc_increment_heartbeat_uv(void) | 800 | xpc_increment_heartbeat_uv(void) |
848 | { | 801 | { |
849 | xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_INC_HEARTBEAT_UV); | 802 | xpc_heartbeat_uv->value++; |
850 | } | 803 | } |
851 | 804 | ||
852 | static void | 805 | static void |
853 | xpc_offline_heartbeat_uv(void) | 806 | xpc_offline_heartbeat_uv(void) |
854 | { | 807 | { |
855 | xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV); | 808 | xpc_increment_heartbeat_uv(); |
809 | xpc_heartbeat_uv->offline = 1; | ||
856 | } | 810 | } |
857 | 811 | ||
858 | static void | 812 | static void |
859 | xpc_online_heartbeat_uv(void) | 813 | xpc_online_heartbeat_uv(void) |
860 | { | 814 | { |
861 | xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_ONLINE_HEARTBEAT_UV); | 815 | xpc_increment_heartbeat_uv(); |
816 | xpc_heartbeat_uv->offline = 0; | ||
862 | } | 817 | } |
863 | 818 | ||
864 | static void | 819 | static void |
865 | xpc_heartbeat_init_uv(void) | 820 | xpc_heartbeat_init_uv(void) |
866 | { | 821 | { |
867 | atomic64_set(&xpc_heartbeat_uv, 0); | 822 | xpc_heartbeat_uv->value = 1; |
868 | bitmap_zero(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); | 823 | xpc_heartbeat_uv->offline = 0; |
869 | xpc_heartbeating_to_mask = &xpc_heartbeating_to_mask_uv[0]; | ||
870 | } | 824 | } |
871 | 825 | ||
872 | static void | 826 | static void |
873 | xpc_heartbeat_exit_uv(void) | 827 | xpc_heartbeat_exit_uv(void) |
874 | { | 828 | { |
875 | xpc_send_heartbeat_uv(XPC_ACTIVATE_MQ_MSG_OFFLINE_HEARTBEAT_UV); | 829 | xpc_offline_heartbeat_uv(); |
876 | } | 830 | } |
877 | 831 | ||
878 | static enum xp_retval | 832 | static enum xp_retval |
879 | xpc_get_remote_heartbeat_uv(struct xpc_partition *part) | 833 | xpc_get_remote_heartbeat_uv(struct xpc_partition *part) |
880 | { | 834 | { |
881 | struct xpc_partition_uv *part_uv = &part->sn.uv; | 835 | struct xpc_partition_uv *part_uv = &part->sn.uv; |
882 | enum xp_retval ret = xpNoHeartbeat; | 836 | enum xp_retval ret; |
883 | 837 | ||
884 | if (part_uv->remote_act_state != XPC_P_AS_INACTIVE && | 838 | ret = xp_remote_memcpy(uv_gpa(&part_uv->cached_heartbeat), |
885 | part_uv->remote_act_state != XPC_P_AS_DEACTIVATING) { | 839 | part_uv->heartbeat_gpa, |
840 | sizeof(struct xpc_heartbeat_uv)); | ||
841 | if (ret != xpSuccess) | ||
842 | return ret; | ||
886 | 843 | ||
887 | if (part_uv->heartbeat != part->last_heartbeat || | 844 | if (part_uv->cached_heartbeat.value == part->last_heartbeat && |
888 | (part_uv->flags & XPC_P_HEARTBEAT_OFFLINE_UV)) { | 845 | !part_uv->cached_heartbeat.offline) { |
889 | 846 | ||
890 | part->last_heartbeat = part_uv->heartbeat; | 847 | ret = xpNoHeartbeat; |
891 | ret = xpSuccess; | 848 | } else { |
892 | } | 849 | part->last_heartbeat = part_uv->cached_heartbeat.value; |
893 | } | 850 | } |
894 | return ret; | 851 | return ret; |
895 | } | 852 | } |
@@ -904,8 +861,9 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, | |||
904 | 861 | ||
905 | part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ | 862 | part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ |
906 | part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; | 863 | part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; |
864 | part->sn.uv.heartbeat_gpa = remote_rp->sn.uv.heartbeat_gpa; | ||
907 | part->sn.uv.activate_gru_mq_desc_gpa = | 865 | part->sn.uv.activate_gru_mq_desc_gpa = |
908 | remote_rp->sn.activate_gru_mq_desc_gpa; | 866 | remote_rp->sn.uv.activate_gru_mq_desc_gpa; |
909 | 867 | ||
910 | /* | 868 | /* |
911 | * ??? Is it a good idea to make this conditional on what is | 869 | * ??? Is it a good idea to make this conditional on what is |
@@ -913,8 +871,9 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, | |||
913 | */ | 871 | */ |
914 | if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { | 872 | if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { |
915 | msg.rp_gpa = uv_gpa(xpc_rsvd_page); | 873 | msg.rp_gpa = uv_gpa(xpc_rsvd_page); |
874 | msg.heartbeat_gpa = xpc_rsvd_page->sn.uv.heartbeat_gpa; | ||
916 | msg.activate_gru_mq_desc_gpa = | 875 | msg.activate_gru_mq_desc_gpa = |
917 | xpc_rsvd_page->sn.activate_gru_mq_desc_gpa; | 876 | xpc_rsvd_page->sn.uv.activate_gru_mq_desc_gpa; |
918 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), | 877 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), |
919 | XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); | 878 | XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); |
920 | } | 879 | } |
@@ -1677,6 +1636,10 @@ xpc_init_uv(void) | |||
1677 | xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; | 1636 | xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; |
1678 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; | 1637 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; |
1679 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; | 1638 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; |
1639 | |||
1640 | xpc_allow_hb = xpc_allow_hb_uv; | ||
1641 | xpc_disallow_hb = xpc_disallow_hb_uv; | ||
1642 | xpc_disallow_all_hbs = xpc_disallow_all_hbs_uv; | ||
1680 | xpc_increment_heartbeat = xpc_increment_heartbeat_uv; | 1643 | xpc_increment_heartbeat = xpc_increment_heartbeat_uv; |
1681 | xpc_offline_heartbeat = xpc_offline_heartbeat_uv; | 1644 | xpc_offline_heartbeat = xpc_offline_heartbeat_uv; |
1682 | xpc_online_heartbeat = xpc_online_heartbeat_uv; | 1645 | xpc_online_heartbeat = xpc_online_heartbeat_uv; |