aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorRobin Holt <holt@sgi.com>2009-04-13 17:40:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-13 18:04:33 -0400
commita374c57b0764432a80303abee3d1afd1939b5a0a (patch)
treeb3e15b590d5342e5de6c2b62da4dd61fb2ad0836 /drivers/misc
parenta06bba4643ae10ac6b202dade1cde38bc5e08b25 (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.h100
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c8
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c44
-rw-r--r--drivers/misc/sgi-xp/xpc_uv.c123
4 files changed, 123 insertions, 152 deletions
diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h
index 114444cfd49..da32bbe8caa 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 */
194struct 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 */
203struct xpc_activate_mq_msghdr_uv { 217struct 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
228struct xpc_activate_mq_msg_uv { 239struct 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
232struct xpc_activate_mq_msg_heartbeat_req_uv {
233 struct xpc_activate_mq_msghdr_uv hdr;
234 u64 heartbeat;
235};
236
237struct xpc_activate_mq_msg_activate_req_uv { 243struct 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
689struct xpc_partition_uv { 696struct 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;
807extern int xpc_activate_IRQ_rcvd; 815extern int xpc_activate_IRQ_rcvd;
808extern spinlock_t xpc_activate_IRQ_rcvd_lock; 816extern spinlock_t xpc_activate_IRQ_rcvd_lock;
809extern wait_queue_head_t xpc_activate_IRQ_wq; 817extern wait_queue_head_t xpc_activate_IRQ_wq;
810extern void *xpc_heartbeating_to_mask;
811extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **); 818extern void *xpc_kzalloc_cacheline_aligned(size_t, gfp_t, void **);
812extern void xpc_activate_partition(struct xpc_partition *); 819extern void xpc_activate_partition(struct xpc_partition *);
813extern void xpc_activate_kthreads(struct xpc_channel *, int); 820extern void xpc_activate_kthreads(struct xpc_channel *, int);
@@ -825,6 +832,9 @@ extern void (*xpc_increment_heartbeat) (void);
825extern void (*xpc_offline_heartbeat) (void); 832extern void (*xpc_offline_heartbeat) (void);
826extern void (*xpc_online_heartbeat) (void); 833extern void (*xpc_online_heartbeat) (void);
827extern enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *); 834extern enum xp_retval (*xpc_get_remote_heartbeat) (struct xpc_partition *);
835extern void (*xpc_allow_hb) (short);
836extern void (*xpc_disallow_hb) (short);
837extern void (*xpc_disallow_all_hbs) (void);
828extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *); 838extern enum xp_retval (*xpc_make_first_contact) (struct xpc_partition *);
829extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *); 839extern u64 (*xpc_get_chctl_all_flags) (struct xpc_partition *);
830extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *); 840extern enum xp_retval (*xpc_setup_msg_structures) (struct xpc_channel *);
@@ -909,40 +919,6 @@ extern void xpc_disconnect_channel(const int, struct xpc_channel *,
909extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval); 919extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval);
910extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval); 920extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval);
911 921
912static inline int
913xpc_hb_allowed(short partid, void *heartbeating_to_mask)
914{
915 return test_bit(partid, heartbeating_to_mask);
916}
917
918static inline int
919xpc_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
925static inline void
926xpc_allow_hb(short partid)
927{
928 DBUG_ON(xpc_heartbeating_to_mask == NULL);
929 set_bit(partid, xpc_heartbeating_to_mask);
930}
931
932static inline void
933xpc_disallow_hb(short partid)
934{
935 DBUG_ON(xpc_heartbeating_to_mask == NULL);
936 clear_bit(partid, xpc_heartbeating_to_mask);
937}
938
939static inline void
940xpc_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
946static inline void 922static inline void
947xpc_wakeup_channel_mgr(struct xpc_partition *part) 923xpc_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 1ab9fda87fa..34b084cd63d 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
151static unsigned long xpc_hb_check_timeout; 151static unsigned long xpc_hb_check_timeout;
152static struct timer_list xpc_hb_timer; 152static struct timer_list xpc_hb_timer;
153void *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 */
156static DECLARE_COMPLETION(xpc_hb_checker_exited); 155static 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);
178int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp); 177int (*xpc_setup_rsvd_page_sn) (struct xpc_rsvd_page *rp);
178
179void (*xpc_allow_hb) (short partid);
180void (*xpc_disallow_hb) (short partid);
181void (*xpc_disallow_all_hbs) (void);
179void (*xpc_heartbeat_init) (void); 182void (*xpc_heartbeat_init) (void);
180void (*xpc_heartbeat_exit) (void); 183void (*xpc_heartbeat_exit) (void);
181void (*xpc_increment_heartbeat) (void); 184void (*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 eaaa964942d..43ad2968daf 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
696static int
697xpc_hb_allowed_sn2(short partid, void *heartbeating_to_mask)
698{
699 return test_bit(partid, heartbeating_to_mask);
700}
701
702static void
703xpc_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
709static void
710xpc_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
716static void
717xpc_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
696static void 723static void
697xpc_increment_heartbeat_sn2(void) 724xpc_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 f7fff4727ed..97f7cb21a0a 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
49static atomic64_t xpc_heartbeat_uv; 49static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
50static 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,
808static int 773static int
809xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) 774xpc_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
816static void 784static void
817xpc_send_heartbeat_uv(int msg_type) 785xpc_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), 789static void
839 msg_type); 790xpc_disallow_hb_uv(short partid)
791{
792}
840 793
841 partid = find_next_bit(xpc_heartbeating_to_mask_uv, 794static void
842 XP_MAX_NPARTITIONS_UV, partid + 1); 795xpc_disallow_all_hbs_uv(void)
843 } 796{
844} 797}
845 798
846static void 799static void
847xpc_increment_heartbeat_uv(void) 800xpc_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
852static void 805static void
853xpc_offline_heartbeat_uv(void) 806xpc_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
858static void 812static void
859xpc_online_heartbeat_uv(void) 813xpc_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
864static void 819static void
865xpc_heartbeat_init_uv(void) 820xpc_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
872static void 826static void
873xpc_heartbeat_exit_uv(void) 827xpc_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
878static enum xp_retval 832static enum xp_retval
879xpc_get_remote_heartbeat_uv(struct xpc_partition *part) 833xpc_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;