aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_sn2.c
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2008-07-30 01:34:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-30 12:41:49 -0400
commit33ba3c7724be79f7cdbfc611335572c056d9a05a (patch)
treedb0371c031b0bbab13ccb2aeaf015424633cf2d8 /drivers/misc/sgi-xp/xpc_sn2.c
parente17d416b1bc947df68499863f13b401fb42b48f6 (diff)
sgi-xp: isolate xpc_vars structure to sn2 only
Isolate the xpc_vars structure of XPC's reserved page to sn2 only. 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/sgi-xp/xpc_sn2.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c1181
1 files changed, 1175 insertions, 6 deletions
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index ee28e231dc4..89c0bb9a27f 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -19,9 +19,370 @@
19#include <asm/sn/sn_sal.h> 19#include <asm/sn/sn_sal.h>
20#include "xpc.h" 20#include "xpc.h"
21 21
22struct xpc_vars *xpc_vars; 22static struct xpc_vars_sn2 *xpc_vars; /* >>> Add _sn2 suffix? */
23static struct xpc_vars_part_sn2 *xpc_vars_part; /* >>> Add _sn2 suffix? */ 23static struct xpc_vars_part_sn2 *xpc_vars_part; /* >>> Add _sn2 suffix? */
24 24
25/*
26 * The following set of macros and functions are used for the sending and
27 * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
28 * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
29 * the other that is associated with channel activity (SGI_XPC_NOTIFY).
30 */
31
32static u64
33xpc_IPI_receive_sn2(AMO_t *amo)
34{
35 return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
36}
37
38static enum xp_retval
39xpc_IPI_send_sn2(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
40{
41 int ret = 0;
42 unsigned long irq_flags;
43
44 local_irq_save(irq_flags);
45
46 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
47 sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
48
49 /*
50 * We must always use the nofault function regardless of whether we
51 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
52 * didn't, we'd never know that the other partition is down and would
53 * keep sending IPIs and AMOs to it until the heartbeat times out.
54 */
55 ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
56 xp_nofault_PIOR_target));
57
58 local_irq_restore(irq_flags);
59
60 return ((ret == 0) ? xpSuccess : xpPioReadError);
61}
62
63static AMO_t *
64xpc_IPI_init_sn2(int index)
65{
66 AMO_t *amo = xpc_vars->amos_page + index;
67
68 (void)xpc_IPI_receive_sn2(amo); /* clear AMO variable */
69 return amo;
70}
71
72/*
73 * IPIs associated with SGI_XPC_ACTIVATE IRQ.
74 */
75
76/*
77 * Flag the appropriate AMO variable and send an IPI to the specified node.
78 */
79static void
80xpc_activate_IRQ_send_sn2(u64 amos_page_pa, int from_nasid, int to_nasid,
81 int to_phys_cpuid)
82{
83 int w_index = XPC_NASID_W_INDEX(from_nasid);
84 int b_index = XPC_NASID_B_INDEX(from_nasid);
85 AMO_t *amos = (AMO_t *)__va(amos_page_pa +
86 (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
87
88 (void)xpc_IPI_send_sn2(&amos[w_index], (1UL << b_index), to_nasid,
89 to_phys_cpuid, SGI_XPC_ACTIVATE);
90}
91
92static void
93xpc_activate_IRQ_send_local_sn2(int from_nasid)
94{
95 int w_index = XPC_NASID_W_INDEX(from_nasid);
96 int b_index = XPC_NASID_B_INDEX(from_nasid);
97 AMO_t *amos = (AMO_t *)__va(xpc_vars->amos_page_pa +
98 (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
99
100 /* fake the sending and receipt of an activate IRQ from remote nasid */
101 FETCHOP_STORE_OP(TO_AMO((u64)&amos[w_index].variable), FETCHOP_OR,
102 (1UL << b_index));
103 atomic_inc(&xpc_act_IRQ_rcvd);
104 wake_up_interruptible(&xpc_act_IRQ_wq);
105}
106
107static void
108xpc_IPI_send_local_activate_sn2(int from_nasid)
109{
110 xpc_activate_IRQ_send_local_sn2(from_nasid);
111}
112
113static void
114xpc_IPI_send_activated_sn2(struct xpc_partition *part)
115{
116 xpc_activate_IRQ_send_sn2(part->remote_amos_page_pa,
117 cnodeid_to_nasid(0), part->remote_act_nasid,
118 part->remote_act_phys_cpuid);
119}
120
121static void
122xpc_IPI_send_local_reactivate_sn2(int from_nasid)
123{
124 xpc_activate_IRQ_send_local_sn2(from_nasid);
125}
126
127static void
128xpc_IPI_send_disengage_sn2(struct xpc_partition *part)
129{
130 xpc_activate_IRQ_send_sn2(part->remote_amos_page_pa,
131 cnodeid_to_nasid(0), part->remote_act_nasid,
132 part->remote_act_phys_cpuid);
133}
134
135/*
136 * IPIs associated with SGI_XPC_NOTIFY IRQ.
137 */
138
139/*
140 * Send an IPI to the remote partition that is associated with the
141 * specified channel.
142 */
143static void
144xpc_notify_IRQ_send_sn2(struct xpc_channel *ch, u8 ipi_flag,
145 char *ipi_flag_string, unsigned long *irq_flags)
146{
147 struct xpc_partition *part = &xpc_partitions[ch->partid];
148 enum xp_retval ret;
149
150 if (likely(part->act_state != XPC_P_DEACTIVATING)) {
151 ret = xpc_IPI_send_sn2(part->remote_IPI_amo_va,
152 (u64)ipi_flag << (ch->number * 8),
153 part->remote_IPI_nasid,
154 part->remote_IPI_phys_cpuid,
155 SGI_XPC_NOTIFY);
156 dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
157 ipi_flag_string, ch->partid, ch->number, ret);
158 if (unlikely(ret != xpSuccess)) {
159 if (irq_flags != NULL)
160 spin_unlock_irqrestore(&ch->lock, *irq_flags);
161 XPC_DEACTIVATE_PARTITION(part, ret);
162 if (irq_flags != NULL)
163 spin_lock_irqsave(&ch->lock, *irq_flags);
164 }
165 }
166}
167
168#define XPC_NOTIFY_IRQ_SEND_SN2(_ch, _ipi_f, _irq_f) \
169 xpc_notify_IRQ_send_sn2(_ch, _ipi_f, #_ipi_f, _irq_f)
170
171/*
172 * Make it look like the remote partition, which is associated with the
173 * specified channel, sent us an IPI. This faked IPI will be handled
174 * by xpc_dropped_IPI_check().
175 */
176static void
177xpc_notify_IRQ_send_local_sn2(struct xpc_channel *ch, u8 ipi_flag,
178 char *ipi_flag_string)
179{
180 struct xpc_partition *part = &xpc_partitions[ch->partid];
181
182 FETCHOP_STORE_OP(TO_AMO((u64)&part->local_IPI_amo_va->variable),
183 FETCHOP_OR, ((u64)ipi_flag << (ch->number * 8)));
184 dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
185 ipi_flag_string, ch->partid, ch->number);
186}
187
188#define XPC_NOTIFY_IRQ_SEND_LOCAL_SN2(_ch, _ipi_f) \
189 xpc_notify_IRQ_send_local_sn2(_ch, _ipi_f, #_ipi_f)
190
191static void
192xpc_IPI_send_closerequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
193{
194 struct xpc_openclose_args *args = ch->local_openclose_args;
195
196 args->reason = ch->reason;
197 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
198}
199
200static void
201xpc_IPI_send_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
202{
203 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_CLOSEREPLY, irq_flags);
204}
205
206static void
207xpc_IPI_send_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
208{
209 struct xpc_openclose_args *args = ch->local_openclose_args;
210
211 args->msg_size = ch->msg_size;
212 args->local_nentries = ch->local_nentries;
213 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_OPENREQUEST, irq_flags);
214}
215
216static void
217xpc_IPI_send_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
218{
219 struct xpc_openclose_args *args = ch->local_openclose_args;
220
221 args->remote_nentries = ch->remote_nentries;
222 args->local_nentries = ch->local_nentries;
223 args->local_msgqueue_pa = __pa(ch->local_msgqueue);
224 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_OPENREPLY, irq_flags);
225}
226
227static void
228xpc_IPI_send_msgrequest_sn2(struct xpc_channel *ch)
229{
230 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_MSGREQUEST, NULL);
231}
232
233static void
234xpc_IPI_send_local_msgrequest_sn2(struct xpc_channel *ch)
235{
236 XPC_NOTIFY_IRQ_SEND_LOCAL_SN2(ch, XPC_IPI_MSGREQUEST);
237}
238
239/*
240 * This next set of functions are used to keep track of when a partition is
241 * potentially engaged in accessing memory belonging to another partition.
242 */
243
244static void
245xpc_mark_partition_engaged_sn2(struct xpc_partition *part)
246{
247 unsigned long irq_flags;
248 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
249 (XPC_ENGAGED_PARTITIONS_AMO *
250 sizeof(AMO_t)));
251
252 local_irq_save(irq_flags);
253
254 /* set bit corresponding to our partid in remote partition's AMO */
255 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
256 (1UL << sn_partition_id));
257 /*
258 * We must always use the nofault function regardless of whether we
259 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
260 * didn't, we'd never know that the other partition is down and would
261 * keep sending IPIs and AMOs to it until the heartbeat times out.
262 */
263 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
264 variable),
265 xp_nofault_PIOR_target));
266
267 local_irq_restore(irq_flags);
268}
269
270static void
271xpc_mark_partition_disengaged_sn2(struct xpc_partition *part)
272{
273 unsigned long irq_flags;
274 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
275 (XPC_ENGAGED_PARTITIONS_AMO *
276 sizeof(AMO_t)));
277
278 local_irq_save(irq_flags);
279
280 /* clear bit corresponding to our partid in remote partition's AMO */
281 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
282 ~(1UL << sn_partition_id));
283 /*
284 * We must always use the nofault function regardless of whether we
285 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
286 * didn't, we'd never know that the other partition is down and would
287 * keep sending IPIs and AMOs to it until the heartbeat times out.
288 */
289 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
290 variable),
291 xp_nofault_PIOR_target));
292
293 local_irq_restore(irq_flags);
294}
295
296static void
297xpc_request_partition_disengage_sn2(struct xpc_partition *part)
298{
299 unsigned long irq_flags;
300 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
301 (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
302
303 local_irq_save(irq_flags);
304
305 /* set bit corresponding to our partid in remote partition's AMO */
306 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
307 (1UL << sn_partition_id));
308 /*
309 * We must always use the nofault function regardless of whether we
310 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
311 * didn't, we'd never know that the other partition is down and would
312 * keep sending IPIs and AMOs to it until the heartbeat times out.
313 */
314 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
315 variable),
316 xp_nofault_PIOR_target));
317
318 local_irq_restore(irq_flags);
319}
320
321static void
322xpc_cancel_partition_disengage_request_sn2(struct xpc_partition *part)
323{
324 unsigned long irq_flags;
325 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
326 (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
327
328 local_irq_save(irq_flags);
329
330 /* clear bit corresponding to our partid in remote partition's AMO */
331 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
332 ~(1UL << sn_partition_id));
333 /*
334 * We must always use the nofault function regardless of whether we
335 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
336 * didn't, we'd never know that the other partition is down and would
337 * keep sending IPIs and AMOs to it until the heartbeat times out.
338 */
339 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
340 variable),
341 xp_nofault_PIOR_target));
342
343 local_irq_restore(irq_flags);
344}
345
346static u64
347xpc_partition_engaged_sn2(u64 partid_mask)
348{
349 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
350
351 /* return our partition's AMO variable ANDed with partid_mask */
352 return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
353 partid_mask);
354}
355
356static u64
357xpc_partition_disengage_requested_sn2(u64 partid_mask)
358{
359 AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
360
361 /* return our partition's AMO variable ANDed with partid_mask */
362 return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
363 partid_mask);
364}
365
366static void
367xpc_clear_partition_engaged_sn2(u64 partid_mask)
368{
369 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
370
371 /* clear bit(s) based on partid_mask in our partition's AMO */
372 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
373 ~partid_mask);
374}
375
376static void
377xpc_clear_partition_disengage_request_sn2(u64 partid_mask)
378{
379 AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
380
381 /* clear bit(s) based on partid_mask in our partition's AMO */
382 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
383 ~partid_mask);
384}
385
25static enum xp_retval 386static enum xp_retval
26xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp) 387xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
27{ 388{
@@ -79,7 +440,7 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
79 } 440 }
80 441
81 /* clear xpc_vars */ 442 /* clear xpc_vars */
82 memset(xpc_vars, 0, sizeof(struct xpc_vars)); 443 memset(xpc_vars, 0, sizeof(struct xpc_vars_sn2));
83 444
84 xpc_vars->version = XPC_V_VERSION; 445 xpc_vars->version = XPC_V_VERSION;
85 xpc_vars->act_nasid = cpuid_to_nasid(0); 446 xpc_vars->act_nasid = cpuid_to_nasid(0);
@@ -94,15 +455,446 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
94 455
95 /* initialize the activate IRQ related AMO variables */ 456 /* initialize the activate IRQ related AMO variables */
96 for (i = 0; i < xp_nasid_mask_words; i++) 457 for (i = 0; i < xp_nasid_mask_words; i++)
97 (void)xpc_IPI_init(XPC_ACTIVATE_IRQ_AMOS + i); 458 (void)xpc_IPI_init_sn2(XPC_ACTIVATE_IRQ_AMOS + i);
98 459
99 /* initialize the engaged remote partitions related AMO variables */ 460 /* initialize the engaged remote partitions related AMO variables */
100 (void)xpc_IPI_init(XPC_ENGAGED_PARTITIONS_AMO); 461 (void)xpc_IPI_init_sn2(XPC_ENGAGED_PARTITIONS_AMO);
101 (void)xpc_IPI_init(XPC_DISENGAGE_REQUEST_AMO); 462 (void)xpc_IPI_init_sn2(XPC_DISENGAGE_REQUEST_AMO);
463
464 return xpSuccess;
465}
466
467static void
468xpc_increment_heartbeat_sn2(void)
469{
470 xpc_vars->heartbeat++;
471}
472
473static void
474xpc_offline_heartbeat_sn2(void)
475{
476 xpc_increment_heartbeat_sn2();
477 xpc_vars->heartbeat_offline = 1;
478}
479
480static void
481xpc_online_heartbeat_sn2(void)
482{
483 xpc_increment_heartbeat_sn2();
484 xpc_vars->heartbeat_offline = 0;
485}
486
487static void
488xpc_heartbeat_init_sn2(void)
489{
490 DBUG_ON(xpc_vars == NULL);
491
492 bitmap_zero(xpc_vars->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
493 xpc_heartbeating_to_mask = &xpc_vars->heartbeating_to_mask[0];
494 xpc_online_heartbeat_sn2();
495}
496
497static void
498xpc_heartbeat_exit_sn2(void)
499{
500 xpc_offline_heartbeat_sn2();
501}
502
503/*
504 * At periodic intervals, scan through all active partitions and ensure
505 * their heartbeat is still active. If not, the partition is deactivated.
506 */
507static void
508xpc_check_remote_hb_sn2(void)
509{
510 struct xpc_vars_sn2 *remote_vars;
511 struct xpc_partition *part;
512 short partid;
513 enum xp_retval ret;
514
515 remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer;
516
517 for (partid = 0; partid < xp_max_npartitions; partid++) {
518
519 if (xpc_exiting)
520 break;
521
522 if (partid == sn_partition_id)
523 continue;
524
525 part = &xpc_partitions[partid];
526
527 if (part->act_state == XPC_P_INACTIVE ||
528 part->act_state == XPC_P_DEACTIVATING) {
529 continue;
530 }
531
532 /* pull the remote_hb cache line */
533 ret = xp_remote_memcpy(remote_vars,
534 (void *)part->remote_vars_pa,
535 XPC_RP_VARS_SIZE);
536 if (ret != xpSuccess) {
537 XPC_DEACTIVATE_PARTITION(part, ret);
538 continue;
539 }
540
541 dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
542 " = %ld, heartbeat_offline = %ld, HB_mask[0] = 0x%lx\n",
543 partid, remote_vars->heartbeat, part->last_heartbeat,
544 remote_vars->heartbeat_offline,
545 remote_vars->heartbeating_to_mask[0]);
546
547 if (((remote_vars->heartbeat == part->last_heartbeat) &&
548 (remote_vars->heartbeat_offline == 0)) ||
549 !xpc_hb_allowed(sn_partition_id,
550 &remote_vars->heartbeating_to_mask)) {
551
552 XPC_DEACTIVATE_PARTITION(part, xpNoHeartbeat);
553 continue;
554 }
555
556 part->last_heartbeat = remote_vars->heartbeat;
557 }
558}
559
560/*
561 * Get a copy of the remote partition's XPC variables from the reserved page.
562 *
563 * remote_vars points to a buffer that is cacheline aligned for BTE copies and
564 * assumed to be of size XPC_RP_VARS_SIZE.
565 */
566static enum xp_retval
567xpc_get_remote_vars_sn2(u64 remote_vars_pa, struct xpc_vars_sn2 *remote_vars)
568{
569 enum xp_retval ret;
570
571 if (remote_vars_pa == 0)
572 return xpVarsNotSet;
573
574 /* pull over the cross partition variables */
575 ret = xp_remote_memcpy(remote_vars, (void *)remote_vars_pa,
576 XPC_RP_VARS_SIZE);
577 if (ret != xpSuccess)
578 return ret;
579
580 if (XPC_VERSION_MAJOR(remote_vars->version) !=
581 XPC_VERSION_MAJOR(XPC_V_VERSION)) {
582 return xpBadVersion;
583 }
102 584
103 return xpSuccess; 585 return xpSuccess;
104} 586}
105 587
588static void
589xpc_initiate_partition_activation_sn2(struct xpc_rsvd_page *remote_rp,
590 u64 remote_rp_pa, int nasid)
591{
592 xpc_IPI_send_local_activate(nasid);
593}
594
595/*
596 * Update the remote partition's info.
597 */
598static void
599xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
600 struct timespec *remote_rp_stamp,
601 u64 remote_rp_pa, u64 remote_vars_pa,
602 struct xpc_vars_sn2 *remote_vars)
603{
604 part->remote_rp_version = remote_rp_version;
605 dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n",
606 part->remote_rp_version);
607
608 part->remote_rp_stamp = *remote_rp_stamp;
609 dev_dbg(xpc_part, " remote_rp_stamp (tv_sec = 0x%lx tv_nsec = 0x%lx\n",
610 part->remote_rp_stamp.tv_sec, part->remote_rp_stamp.tv_nsec);
611
612 part->remote_rp_pa = remote_rp_pa;
613 dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
614
615 part->remote_vars_pa = remote_vars_pa;
616 dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
617 part->remote_vars_pa);
618
619 part->last_heartbeat = remote_vars->heartbeat;
620 dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
621 part->last_heartbeat);
622
623 part->remote_vars_part_pa = remote_vars->vars_part_pa;
624 dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n",
625 part->remote_vars_part_pa);
626
627 part->remote_act_nasid = remote_vars->act_nasid;
628 dev_dbg(xpc_part, " remote_act_nasid = 0x%x\n",
629 part->remote_act_nasid);
630
631 part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
632 dev_dbg(xpc_part, " remote_act_phys_cpuid = 0x%x\n",
633 part->remote_act_phys_cpuid);
634
635 part->remote_amos_page_pa = remote_vars->amos_page_pa;
636 dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n",
637 part->remote_amos_page_pa);
638
639 part->remote_vars_version = remote_vars->version;
640 dev_dbg(xpc_part, " remote_vars_version = 0x%x\n",
641 part->remote_vars_version);
642}
643
644/*
645 * Prior code has determined the nasid which generated an IPI. Inspect
646 * that nasid to determine if its partition needs to be activated or
647 * deactivated.
648 *
649 * A partition is consider "awaiting activation" if our partition
650 * flags indicate it is not active and it has a heartbeat. A
651 * partition is considered "awaiting deactivation" if our partition
652 * flags indicate it is active but it has no heartbeat or it is not
653 * sending its heartbeat to us.
654 *
655 * To determine the heartbeat, the remote nasid must have a properly
656 * initialized reserved page.
657 */
658static void
659xpc_identify_act_IRQ_req_sn2(int nasid)
660{
661 struct xpc_rsvd_page *remote_rp;
662 struct xpc_vars_sn2 *remote_vars;
663 u64 remote_rp_pa;
664 u64 remote_vars_pa;
665 int remote_rp_version;
666 int reactivate = 0;
667 int stamp_diff;
668 struct timespec remote_rp_stamp = { 0, 0 }; /*>>> ZERO_STAMP */
669 short partid;
670 struct xpc_partition *part;
671 enum xp_retval ret;
672
673 /* pull over the reserved page structure */
674
675 remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer;
676
677 ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
678 if (ret != xpSuccess) {
679 dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
680 "which sent interrupt, reason=%d\n", nasid, ret);
681 return;
682 }
683
684 remote_vars_pa = remote_rp->sn.vars_pa;
685 remote_rp_version = remote_rp->version;
686 if (XPC_SUPPORTS_RP_STAMP(remote_rp_version))
687 remote_rp_stamp = remote_rp->stamp;
688
689 partid = remote_rp->SAL_partid;
690 part = &xpc_partitions[partid];
691
692 /* pull over the cross partition variables */
693
694 remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer;
695
696 ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
697 if (ret != xpSuccess) {
698
699 dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
700 "which sent interrupt, reason=%d\n", nasid, ret);
701
702 XPC_DEACTIVATE_PARTITION(part, ret);
703 return;
704 }
705
706 part->act_IRQ_rcvd++;
707
708 dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
709 "%ld:0x%lx\n", (int)nasid, (int)partid, part->act_IRQ_rcvd,
710 remote_vars->heartbeat, remote_vars->heartbeating_to_mask[0]);
711
712 if (xpc_partition_disengaged(part) &&
713 part->act_state == XPC_P_INACTIVE) {
714
715 xpc_update_partition_info_sn2(part, remote_rp_version,
716 &remote_rp_stamp, remote_rp_pa,
717 remote_vars_pa, remote_vars);
718
719 if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
720 if (xpc_partition_disengage_requested(1UL << partid)) {
721 /*
722 * Other side is waiting on us to disengage,
723 * even though we already have.
724 */
725 return;
726 }
727
728 } else {
729 /* other side doesn't support disengage requests */
730 xpc_clear_partition_disengage_request(1UL << partid);
731 }
732
733 xpc_activate_partition(part);
734 return;
735 }
736
737 DBUG_ON(part->remote_rp_version == 0);
738 DBUG_ON(part->remote_vars_version == 0);
739
740 if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
741 DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
742 remote_vars_version));
743
744 if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
745 DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
746 version));
747 /* see if the other side rebooted */
748 if (part->remote_amos_page_pa ==
749 remote_vars->amos_page_pa &&
750 xpc_hb_allowed(sn_partition_id,
751 &remote_vars->heartbeating_to_mask)) {
752 /* doesn't look that way, so ignore the IPI */
753 return;
754 }
755 }
756
757 /*
758 * Other side rebooted and previous XPC didn't support the
759 * disengage request, so we don't need to do anything special.
760 */
761
762 xpc_update_partition_info_sn2(part, remote_rp_version,
763 &remote_rp_stamp, remote_rp_pa,
764 remote_vars_pa, remote_vars);
765 part->reactivate_nasid = nasid;
766 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
767 return;
768 }
769
770 DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
771
772 if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
773 DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
774
775 /*
776 * Other side rebooted and previous XPC did support the
777 * disengage request, but the new one doesn't.
778 */
779
780 xpc_clear_partition_engaged(1UL << partid);
781 xpc_clear_partition_disengage_request(1UL << partid);
782
783 xpc_update_partition_info_sn2(part, remote_rp_version,
784 &remote_rp_stamp, remote_rp_pa,
785 remote_vars_pa, remote_vars);
786 reactivate = 1;
787
788 } else {
789 DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
790
791 stamp_diff = xpc_compare_stamps(&part->remote_rp_stamp,
792 &remote_rp_stamp);
793 if (stamp_diff != 0) {
794 DBUG_ON(stamp_diff >= 0);
795
796 /*
797 * Other side rebooted and the previous XPC did support
798 * the disengage request, as does the new one.
799 */
800
801 DBUG_ON(xpc_partition_engaged(1UL << partid));
802 DBUG_ON(xpc_partition_disengage_requested(1UL <<
803 partid));
804
805 xpc_update_partition_info_sn2(part, remote_rp_version,
806 &remote_rp_stamp,
807 remote_rp_pa,
808 remote_vars_pa,
809 remote_vars);
810 reactivate = 1;
811 }
812 }
813
814 if (part->disengage_request_timeout > 0 &&
815 !xpc_partition_disengaged(part)) {
816 /* still waiting on other side to disengage from us */
817 return;
818 }
819
820 if (reactivate) {
821 part->reactivate_nasid = nasid;
822 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
823
824 } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
825 xpc_partition_disengage_requested(1UL << partid)) {
826 XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown);
827 }
828}
829
830/*
831 * Loop through the activation AMO variables and process any bits
832 * which are set. Each bit indicates a nasid sending a partition
833 * activation or deactivation request.
834 *
835 * Return #of IRQs detected.
836 */
837int
838xpc_identify_act_IRQ_sender_sn2(void)
839{
840 int word, bit;
841 u64 nasid_mask;
842 u64 nasid; /* remote nasid */
843 int n_IRQs_detected = 0;
844 AMO_t *act_amos;
845
846 act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
847
848 /* scan through act AMO variable looking for non-zero entries */
849 for (word = 0; word < xp_nasid_mask_words; word++) {
850
851 if (xpc_exiting)
852 break;
853
854 nasid_mask = xpc_IPI_receive_sn2(&act_amos[word]);
855 if (nasid_mask == 0) {
856 /* no IRQs from nasids in this variable */
857 continue;
858 }
859
860 dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
861 nasid_mask);
862
863 /*
864 * If this nasid has been added to the machine since
865 * our partition was reset, this will retain the
866 * remote nasid in our reserved pages machine mask.
867 * This is used in the event of module reload.
868 */
869 xpc_mach_nasids[word] |= nasid_mask;
870
871 /* locate the nasid(s) which sent interrupts */
872
873 for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
874 if (nasid_mask & (1UL << bit)) {
875 n_IRQs_detected++;
876 nasid = XPC_NASID_FROM_W_B(word, bit);
877 dev_dbg(xpc_part, "interrupt from nasid %ld\n",
878 nasid);
879 xpc_identify_act_IRQ_req_sn2(nasid);
880 }
881 }
882 }
883 return n_IRQs_detected;
884}
885
886static void
887xpc_process_act_IRQ_rcvd_sn2(int n_IRQs_expected)
888{
889 int n_IRQs_detected;
890
891 n_IRQs_detected = xpc_identify_act_IRQ_sender_sn2();
892 if (n_IRQs_detected < n_IRQs_expected) {
893 /* retry once to help avoid missing AMO */
894 (void)xpc_identify_act_IRQ_sender_sn2();
895 }
896}
897
106/* 898/*
107 * Setup the infrastructure necessary to support XPartition Communication 899 * Setup the infrastructure necessary to support XPartition Communication
108 * between the specified remote partition and the local one. 900 * between the specified remote partition and the local one.
@@ -177,7 +969,7 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
177 969
178 part->remote_openclose_args_pa = 0; 970 part->remote_openclose_args_pa = 0;
179 971
180 part->local_IPI_amo_va = xpc_IPI_init(partid); 972 part->local_IPI_amo_va = xpc_IPI_init_sn2(partid);
181 part->local_IPI_amo = 0; 973 part->local_IPI_amo = 0;
182 spin_lock_init(&part->IPI_lock); 974 spin_lock_init(&part->IPI_lock);
183 975
@@ -468,6 +1260,28 @@ xpc_make_first_contact_sn2(struct xpc_partition *part)
468{ 1260{
469 enum xp_retval ret; 1261 enum xp_retval ret;
470 1262
1263 /*
1264 * Register the remote partition's AMOs with SAL so it can handle
1265 * and cleanup errors within that address range should the remote
1266 * partition go down. We don't unregister this range because it is
1267 * difficult to tell when outstanding writes to the remote partition
1268 * are finished and thus when it is safe to unregister. This should
1269 * not result in wasted space in the SAL xp_addr_region table because
1270 * we should get the same page for remote_amos_page_pa after module
1271 * reloads and system reboots.
1272 */
1273 if (sn_register_xp_addr_region(part->remote_amos_page_pa,
1274 PAGE_SIZE, 1) < 0) {
1275 dev_warn(xpc_part, "xpc_activating(%d) failed to register "
1276 "xp_addr region\n", XPC_PARTID(part));
1277
1278 ret = xpPhysAddrRegFailed;
1279 XPC_DEACTIVATE_PARTITION(part, ret);
1280 return ret;
1281 }
1282
1283 xpc_IPI_send_activated(part);
1284
471 while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) { 1285 while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) {
472 if (ret != xpRetry) { 1286 if (ret != xpRetry) {
473 XPC_DEACTIVATE_PARTITION(part, ret); 1287 XPC_DEACTIVATE_PARTITION(part, ret);
@@ -651,15 +1465,370 @@ xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
651 return msg; 1465 return msg;
652} 1466}
653 1467
1468/*
1469 * Now we actually send the messages that are ready to be sent by advancing
1470 * the local message queue's Put value and then send an IPI to the recipient
1471 * partition.
1472 */
1473static void
1474xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1475{
1476 struct xpc_msg *msg;
1477 s64 put = initial_put + 1;
1478 int send_IPI = 0;
1479
1480 while (1) {
1481
1482 while (1) {
1483 if (put == ch->w_local_GP.put)
1484 break;
1485
1486 msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
1487 (put % ch->local_nentries) *
1488 ch->msg_size);
1489
1490 if (!(msg->flags & XPC_M_READY))
1491 break;
1492
1493 put++;
1494 }
1495
1496 if (put == initial_put) {
1497 /* nothing's changed */
1498 break;
1499 }
1500
1501 if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
1502 initial_put) {
1503 /* someone else beat us to it */
1504 DBUG_ON(ch->local_GP->put < initial_put);
1505 break;
1506 }
1507
1508 /* we just set the new value of local_GP->put */
1509
1510 dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
1511 "channel=%d\n", put, ch->partid, ch->number);
1512
1513 send_IPI = 1;
1514
1515 /*
1516 * We need to ensure that the message referenced by
1517 * local_GP->put is not XPC_M_READY or that local_GP->put
1518 * equals w_local_GP.put, so we'll go have a look.
1519 */
1520 initial_put = put;
1521 }
1522
1523 if (send_IPI)
1524 xpc_IPI_send_msgrequest_sn2(ch);
1525}
1526
1527/*
1528 * Allocate an entry for a message from the message queue associated with the
1529 * specified channel.
1530 */
1531static enum xp_retval
1532xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
1533 struct xpc_msg **address_of_msg)
1534{
1535 struct xpc_msg *msg;
1536 enum xp_retval ret;
1537 s64 put;
1538
1539 /* this reference will be dropped in xpc_send_msg_sn2() */
1540 xpc_msgqueue_ref(ch);
1541
1542 if (ch->flags & XPC_C_DISCONNECTING) {
1543 xpc_msgqueue_deref(ch);
1544 return ch->reason;
1545 }
1546 if (!(ch->flags & XPC_C_CONNECTED)) {
1547 xpc_msgqueue_deref(ch);
1548 return xpNotConnected;
1549 }
1550
1551 /*
1552 * Get the next available message entry from the local message queue.
1553 * If none are available, we'll make sure that we grab the latest
1554 * GP values.
1555 */
1556 ret = xpTimeout;
1557
1558 while (1) {
1559
1560 put = ch->w_local_GP.put;
1561 rmb(); /* guarantee that .put loads before .get */
1562 if (put - ch->w_remote_GP.get < ch->local_nentries) {
1563
1564 /* There are available message entries. We need to try
1565 * to secure one for ourselves. We'll do this by trying
1566 * to increment w_local_GP.put as long as someone else
1567 * doesn't beat us to it. If they do, we'll have to
1568 * try again.
1569 */
1570 if (cmpxchg(&ch->w_local_GP.put, put, put + 1) == put) {
1571 /* we got the entry referenced by put */
1572 break;
1573 }
1574 continue; /* try again */
1575 }
1576
1577 /*
1578 * There aren't any available msg entries at this time.
1579 *
1580 * In waiting for a message entry to become available,
1581 * we set a timeout in case the other side is not
1582 * sending completion IPIs. This lets us fake an IPI
1583 * that will cause the IPI handler to fetch the latest
1584 * GP values as if an IPI was sent by the other side.
1585 */
1586 if (ret == xpTimeout)
1587 xpc_IPI_send_local_msgrequest_sn2(ch);
1588
1589 if (flags & XPC_NOWAIT) {
1590 xpc_msgqueue_deref(ch);
1591 return xpNoWait;
1592 }
1593
1594 ret = xpc_allocate_msg_wait(ch);
1595 if (ret != xpInterrupted && ret != xpTimeout) {
1596 xpc_msgqueue_deref(ch);
1597 return ret;
1598 }
1599 }
1600
1601 /* get the message's address and initialize it */
1602 msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
1603 (put % ch->local_nentries) * ch->msg_size);
1604
1605 DBUG_ON(msg->flags != 0);
1606 msg->number = put;
1607
1608 dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
1609 "msg_number=%ld, partid=%d, channel=%d\n", put + 1,
1610 (void *)msg, msg->number, ch->partid, ch->number);
1611
1612 *address_of_msg = msg;
1613
1614 return xpSuccess;
1615}
1616
1617/*
1618 * Common code that does the actual sending of the message by advancing the
1619 * local message queue's Put value and sends an IPI to the partition the
1620 * message is being sent to.
1621 */
1622static enum xp_retval
1623xpc_send_msg_sn2(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type,
1624 xpc_notify_func func, void *key)
1625{
1626 enum xp_retval ret = xpSuccess;
1627 struct xpc_notify *notify = notify;
1628 s64 put, msg_number = msg->number;
1629
1630 DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
1631 DBUG_ON((((u64)msg - (u64)ch->local_msgqueue) / ch->msg_size) !=
1632 msg_number % ch->local_nentries);
1633 DBUG_ON(msg->flags & XPC_M_READY);
1634
1635 if (ch->flags & XPC_C_DISCONNECTING) {
1636 /* drop the reference grabbed in xpc_allocate_msg_sn2() */
1637 xpc_msgqueue_deref(ch);
1638 return ch->reason;
1639 }
1640
1641 if (notify_type != 0) {
1642 /*
1643 * Tell the remote side to send an ACK interrupt when the
1644 * message has been delivered.
1645 */
1646 msg->flags |= XPC_M_INTERRUPT;
1647
1648 atomic_inc(&ch->n_to_notify);
1649
1650 notify = &ch->notify_queue[msg_number % ch->local_nentries];
1651 notify->func = func;
1652 notify->key = key;
1653 notify->type = notify_type;
1654
1655 /* >>> is a mb() needed here? */
1656
1657 if (ch->flags & XPC_C_DISCONNECTING) {
1658 /*
1659 * An error occurred between our last error check and
1660 * this one. We will try to clear the type field from
1661 * the notify entry. If we succeed then
1662 * xpc_disconnect_channel() didn't already process
1663 * the notify entry.
1664 */
1665 if (cmpxchg(&notify->type, notify_type, 0) ==
1666 notify_type) {
1667 atomic_dec(&ch->n_to_notify);
1668 ret = ch->reason;
1669 }
1670
1671 /* drop reference grabbed in xpc_allocate_msg_sn2() */
1672 xpc_msgqueue_deref(ch);
1673 return ret;
1674 }
1675 }
1676
1677 msg->flags |= XPC_M_READY;
1678
1679 /*
1680 * The preceding store of msg->flags must occur before the following
1681 * load of ch->local_GP->put.
1682 */
1683 mb();
1684
1685 /* see if the message is next in line to be sent, if so send it */
1686
1687 put = ch->local_GP->put;
1688 if (put == msg_number)
1689 xpc_send_msgs_sn2(ch, put);
1690
1691 /* drop the reference grabbed in xpc_allocate_msg_sn2() */
1692 xpc_msgqueue_deref(ch);
1693 return ret;
1694}
1695
1696/*
1697 * Now we actually acknowledge the messages that have been delivered and ack'd
1698 * by advancing the cached remote message queue's Get value and if requested
1699 * send an IPI to the message sender's partition.
1700 */
1701static void
1702xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
1703{
1704 struct xpc_msg *msg;
1705 s64 get = initial_get + 1;
1706 int send_IPI = 0;
1707
1708 while (1) {
1709
1710 while (1) {
1711 if (get == ch->w_local_GP.get)
1712 break;
1713
1714 msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
1715 (get % ch->remote_nentries) *
1716 ch->msg_size);
1717
1718 if (!(msg->flags & XPC_M_DONE))
1719 break;
1720
1721 msg_flags |= msg->flags;
1722 get++;
1723 }
1724
1725 if (get == initial_get) {
1726 /* nothing's changed */
1727 break;
1728 }
1729
1730 if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
1731 initial_get) {
1732 /* someone else beat us to it */
1733 DBUG_ON(ch->local_GP->get <= initial_get);
1734 break;
1735 }
1736
1737 /* we just set the new value of local_GP->get */
1738
1739 dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
1740 "channel=%d\n", get, ch->partid, ch->number);
1741
1742 send_IPI = (msg_flags & XPC_M_INTERRUPT);
1743
1744 /*
1745 * We need to ensure that the message referenced by
1746 * local_GP->get is not XPC_M_DONE or that local_GP->get
1747 * equals w_local_GP.get, so we'll go have a look.
1748 */
1749 initial_get = get;
1750 }
1751
1752 if (send_IPI)
1753 xpc_IPI_send_msgrequest_sn2(ch);
1754}
1755
1756static void
1757xpc_received_msg_sn2(struct xpc_channel *ch, struct xpc_msg *msg)
1758{
1759 s64 get;
1760 s64 msg_number = msg->number;
1761
1762 dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
1763 (void *)msg, msg_number, ch->partid, ch->number);
1764
1765 DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->msg_size) !=
1766 msg_number % ch->remote_nentries);
1767 DBUG_ON(msg->flags & XPC_M_DONE);
1768
1769 msg->flags |= XPC_M_DONE;
1770
1771 /*
1772 * The preceding store of msg->flags must occur before the following
1773 * load of ch->local_GP->get.
1774 */
1775 mb();
1776
1777 /*
1778 * See if this message is next in line to be acknowledged as having
1779 * been delivered.
1780 */
1781 get = ch->local_GP->get;
1782 if (get == msg_number)
1783 xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
1784}
1785
654void 1786void
655xpc_init_sn2(void) 1787xpc_init_sn2(void)
656{ 1788{
657 xpc_rsvd_page_init = xpc_rsvd_page_init_sn2; 1789 xpc_rsvd_page_init = xpc_rsvd_page_init_sn2;
1790 xpc_increment_heartbeat = xpc_increment_heartbeat_sn2;
1791 xpc_offline_heartbeat = xpc_offline_heartbeat_sn2;
1792 xpc_online_heartbeat = xpc_online_heartbeat_sn2;
1793 xpc_heartbeat_init = xpc_heartbeat_init_sn2;
1794 xpc_heartbeat_exit = xpc_heartbeat_exit_sn2;
1795 xpc_check_remote_hb = xpc_check_remote_hb_sn2;
1796
1797 xpc_initiate_partition_activation =
1798 xpc_initiate_partition_activation_sn2;
1799 xpc_process_act_IRQ_rcvd = xpc_process_act_IRQ_rcvd_sn2;
658 xpc_setup_infrastructure = xpc_setup_infrastructure_sn2; 1800 xpc_setup_infrastructure = xpc_setup_infrastructure_sn2;
659 xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2; 1801 xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2;
660 xpc_make_first_contact = xpc_make_first_contact_sn2; 1802 xpc_make_first_contact = xpc_make_first_contact_sn2;
661 xpc_get_IPI_flags = xpc_get_IPI_flags_sn2; 1803 xpc_get_IPI_flags = xpc_get_IPI_flags_sn2;
662 xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2; 1804 xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2;
1805
1806 xpc_mark_partition_engaged = xpc_mark_partition_engaged_sn2;
1807 xpc_mark_partition_disengaged = xpc_mark_partition_disengaged_sn2;
1808 xpc_request_partition_disengage = xpc_request_partition_disengage_sn2;
1809 xpc_cancel_partition_disengage_request =
1810 xpc_cancel_partition_disengage_request_sn2;
1811 xpc_partition_engaged = xpc_partition_engaged_sn2;
1812 xpc_partition_disengage_requested =
1813 xpc_partition_disengage_requested_sn2;
1814 xpc_clear_partition_engaged = xpc_clear_partition_engaged_sn2;
1815 xpc_clear_partition_disengage_request =
1816 xpc_clear_partition_disengage_request_sn2;
1817
1818 xpc_IPI_send_local_activate = xpc_IPI_send_local_activate_sn2;
1819 xpc_IPI_send_activated = xpc_IPI_send_activated_sn2;
1820 xpc_IPI_send_local_reactivate = xpc_IPI_send_local_reactivate_sn2;
1821 xpc_IPI_send_disengage = xpc_IPI_send_disengage_sn2;
1822
1823 xpc_IPI_send_closerequest = xpc_IPI_send_closerequest_sn2;
1824 xpc_IPI_send_closereply = xpc_IPI_send_closereply_sn2;
1825 xpc_IPI_send_openrequest = xpc_IPI_send_openrequest_sn2;
1826 xpc_IPI_send_openreply = xpc_IPI_send_openreply_sn2;
1827
1828 xpc_allocate_msg = xpc_allocate_msg_sn2;
1829
1830 xpc_send_msg = xpc_send_msg_sn2;
1831 xpc_received_msg = xpc_received_msg_sn2;
663} 1832}
664 1833
665void 1834void