aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-xp/xpc_sn2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_sn2.c')
-rw-r--r--drivers/misc/sgi-xp/xpc_sn2.c851
1 files changed, 539 insertions, 312 deletions
diff --git a/drivers/misc/sgi-xp/xpc_sn2.c b/drivers/misc/sgi-xp/xpc_sn2.c
index 4659f6cb885e..69d74bd56899 100644
--- a/drivers/misc/sgi-xp/xpc_sn2.c
+++ b/drivers/misc/sgi-xp/xpc_sn2.c
@@ -196,37 +196,85 @@ xpc_activate_IRQ_send_local_sn2(int from_nasid)
196 wake_up_interruptible(&xpc_activate_IRQ_wq); 196 wake_up_interruptible(&xpc_activate_IRQ_wq);
197} 197}
198 198
199static void 199/*
200xpc_IPI_send_local_activate_sn2(int from_nasid) 200 * IPIs associated with SGI_XPC_NOTIFY IRQ.
201{ 201 */
202 xpc_activate_IRQ_send_local_sn2(from_nasid);
203}
204 202
203/*
204 * Check to see if there is any channel activity to/from the specified
205 * partition.
206 */
205static void 207static void
206xpc_IPI_send_activated_sn2(struct xpc_partition *part) 208xpc_check_for_channel_activity_sn2(struct xpc_partition *part)
207{ 209{
208 xpc_activate_IRQ_send_sn2(part->remote_amos_page_pa, 210 u64 IPI_amo;
209 cnodeid_to_nasid(0), part->remote_act_nasid, 211 unsigned long irq_flags;
210 part->remote_act_phys_cpuid);
211}
212 212
213static void 213 IPI_amo = xpc_IPI_receive_sn2(part->sn.sn2.local_IPI_amo_va);
214xpc_IPI_send_local_reactivate_sn2(int from_nasid) 214 if (IPI_amo == 0)
215{ 215 return;
216 xpc_activate_IRQ_send_local_sn2(from_nasid); 216
217 spin_lock_irqsave(&part->IPI_lock, irq_flags);
218 part->local_IPI_amo |= IPI_amo;
219 spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
220
221 dev_dbg(xpc_chan, "received IPI from partid=%d, IPI_amo=0x%lx\n",
222 XPC_PARTID(part), IPI_amo);
223
224 xpc_wakeup_channel_mgr(part);
217} 225}
218 226
219static void 227/*
220xpc_IPI_send_disengage_sn2(struct xpc_partition *part) 228 * Handle the receipt of a SGI_XPC_NOTIFY IRQ by seeing whether the specified
229 * partition actually sent it. Since SGI_XPC_NOTIFY IRQs may be shared by more
230 * than one partition, we use an AMO_t structure per partition to indicate
231 * whether a partition has sent an IPI or not. If it has, then wake up the
232 * associated kthread to handle it.
233 *
234 * All SGI_XPC_NOTIFY IRQs received by XPC are the result of IPIs sent by XPC
235 * running on other partitions.
236 *
237 * Noteworthy Arguments:
238 *
239 * irq - Interrupt ReQuest number. NOT USED.
240 *
241 * dev_id - partid of IPI's potential sender.
242 */
243static irqreturn_t
244xpc_handle_notify_IRQ_sn2(int irq, void *dev_id)
221{ 245{
222 xpc_activate_IRQ_send_sn2(part->remote_amos_page_pa, 246 short partid = (short)(u64)dev_id;
223 cnodeid_to_nasid(0), part->remote_act_nasid, 247 struct xpc_partition *part = &xpc_partitions[partid];
224 part->remote_act_phys_cpuid); 248
249 DBUG_ON(partid < 0 || partid >= xp_max_npartitions);
250
251 if (xpc_part_ref(part)) {
252 xpc_check_for_channel_activity_sn2(part);
253
254 xpc_part_deref(part);
255 }
256 return IRQ_HANDLED;
225} 257}
226 258
227/* 259/*
228 * IPIs associated with SGI_XPC_NOTIFY IRQ. 260 * Check to see if xpc_handle_notify_IRQ_sn2() dropped any IPIs on the floor
261 * because the write to their associated IPI amo completed after the IRQ/IPI
262 * was received.
229 */ 263 */
264static void
265xpc_dropped_notify_IRQ_check_sn2(struct xpc_partition *part)
266{
267 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
268
269 if (xpc_part_ref(part)) {
270 xpc_check_for_channel_activity_sn2(part);
271
272 part_sn2->dropped_notify_IRQ_timer.expires = jiffies +
273 XPC_P_DROPPED_IPI_WAIT_INTERVAL;
274 add_timer(&part_sn2->dropped_notify_IRQ_timer);
275 xpc_part_deref(part);
276 }
277}
230 278
231/* 279/*
232 * Send an IPI to the remote partition that is associated with the 280 * Send an IPI to the remote partition that is associated with the
@@ -237,13 +285,14 @@ xpc_notify_IRQ_send_sn2(struct xpc_channel *ch, u8 ipi_flag,
237 char *ipi_flag_string, unsigned long *irq_flags) 285 char *ipi_flag_string, unsigned long *irq_flags)
238{ 286{
239 struct xpc_partition *part = &xpc_partitions[ch->partid]; 287 struct xpc_partition *part = &xpc_partitions[ch->partid];
288 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
240 enum xp_retval ret; 289 enum xp_retval ret;
241 290
242 if (likely(part->act_state != XPC_P_DEACTIVATING)) { 291 if (likely(part->act_state != XPC_P_DEACTIVATING)) {
243 ret = xpc_IPI_send_sn2(part->remote_IPI_amo_va, 292 ret = xpc_IPI_send_sn2(part_sn2->remote_IPI_amo_va,
244 (u64)ipi_flag << (ch->number * 8), 293 (u64)ipi_flag << (ch->number * 8),
245 part->remote_IPI_nasid, 294 part_sn2->remote_IPI_nasid,
246 part->remote_IPI_phys_cpuid, 295 part_sn2->remote_IPI_phys_cpuid,
247 SGI_XPC_NOTIFY); 296 SGI_XPC_NOTIFY);
248 dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n", 297 dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
249 ipi_flag_string, ch->partid, ch->number, ret); 298 ipi_flag_string, ch->partid, ch->number, ret);
@@ -263,7 +312,7 @@ xpc_notify_IRQ_send_sn2(struct xpc_channel *ch, u8 ipi_flag,
263/* 312/*
264 * Make it look like the remote partition, which is associated with the 313 * Make it look like the remote partition, which is associated with the
265 * specified channel, sent us an IPI. This faked IPI will be handled 314 * specified channel, sent us an IPI. This faked IPI will be handled
266 * by xpc_dropped_IPI_check(). 315 * by xpc_dropped_notify_IRQ_check_sn2().
267 */ 316 */
268static void 317static void
269xpc_notify_IRQ_send_local_sn2(struct xpc_channel *ch, u8 ipi_flag, 318xpc_notify_IRQ_send_local_sn2(struct xpc_channel *ch, u8 ipi_flag,
@@ -271,7 +320,7 @@ xpc_notify_IRQ_send_local_sn2(struct xpc_channel *ch, u8 ipi_flag,
271{ 320{
272 struct xpc_partition *part = &xpc_partitions[ch->partid]; 321 struct xpc_partition *part = &xpc_partitions[ch->partid];
273 322
274 FETCHOP_STORE_OP(TO_AMO((u64)&part->local_IPI_amo_va->variable), 323 FETCHOP_STORE_OP(TO_AMO((u64)&part->sn.sn2.local_IPI_amo_va->variable),
275 FETCHOP_OR, ((u64)ipi_flag << (ch->number * 8))); 324 FETCHOP_OR, ((u64)ipi_flag << (ch->number * 8)));
276 dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n", 325 dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
277 ipi_flag_string, ch->partid, ch->number); 326 ipi_flag_string, ch->partid, ch->number);
@@ -281,7 +330,8 @@ xpc_notify_IRQ_send_local_sn2(struct xpc_channel *ch, u8 ipi_flag,
281 xpc_notify_IRQ_send_local_sn2(_ch, _ipi_f, #_ipi_f) 330 xpc_notify_IRQ_send_local_sn2(_ch, _ipi_f, #_ipi_f)
282 331
283static void 332static void
284xpc_IPI_send_closerequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags) 333xpc_send_channel_closerequest_sn2(struct xpc_channel *ch,
334 unsigned long *irq_flags)
285{ 335{
286 struct xpc_openclose_args *args = ch->local_openclose_args; 336 struct xpc_openclose_args *args = ch->local_openclose_args;
287 337
@@ -290,13 +340,15 @@ xpc_IPI_send_closerequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
290} 340}
291 341
292static void 342static void
293xpc_IPI_send_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags) 343xpc_send_channel_closereply_sn2(struct xpc_channel *ch,
344 unsigned long *irq_flags)
294{ 345{
295 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_CLOSEREPLY, irq_flags); 346 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_CLOSEREPLY, irq_flags);
296} 347}
297 348
298static void 349static void
299xpc_IPI_send_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags) 350xpc_send_channel_openrequest_sn2(struct xpc_channel *ch,
351 unsigned long *irq_flags)
300{ 352{
301 struct xpc_openclose_args *args = ch->local_openclose_args; 353 struct xpc_openclose_args *args = ch->local_openclose_args;
302 354
@@ -306,7 +358,7 @@ xpc_IPI_send_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
306} 358}
307 359
308static void 360static void
309xpc_IPI_send_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags) 361xpc_send_channel_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
310{ 362{
311 struct xpc_openclose_args *args = ch->local_openclose_args; 363 struct xpc_openclose_args *args = ch->local_openclose_args;
312 364
@@ -317,13 +369,13 @@ xpc_IPI_send_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
317} 369}
318 370
319static void 371static void
320xpc_IPI_send_msgrequest_sn2(struct xpc_channel *ch) 372xpc_send_channel_msgrequest_sn2(struct xpc_channel *ch)
321{ 373{
322 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_MSGREQUEST, NULL); 374 XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_MSGREQUEST, NULL);
323} 375}
324 376
325static void 377static void
326xpc_IPI_send_local_msgrequest_sn2(struct xpc_channel *ch) 378xpc_send_channel_local_msgrequest_sn2(struct xpc_channel *ch)
327{ 379{
328 XPC_NOTIFY_IRQ_SEND_LOCAL_SN2(ch, XPC_IPI_MSGREQUEST); 380 XPC_NOTIFY_IRQ_SEND_LOCAL_SN2(ch, XPC_IPI_MSGREQUEST);
329} 381}
@@ -334,10 +386,10 @@ xpc_IPI_send_local_msgrequest_sn2(struct xpc_channel *ch)
334 */ 386 */
335 387
336static void 388static void
337xpc_mark_partition_engaged_sn2(struct xpc_partition *part) 389xpc_indicate_partition_engaged_sn2(struct xpc_partition *part)
338{ 390{
339 unsigned long irq_flags; 391 unsigned long irq_flags;
340 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa + 392 AMO_t *amo = (AMO_t *)__va(part->sn.sn2.remote_amos_page_pa +
341 (XPC_ENGAGED_PARTITIONS_AMO * 393 (XPC_ENGAGED_PARTITIONS_AMO *
342 sizeof(AMO_t))); 394 sizeof(AMO_t)));
343 395
@@ -360,10 +412,11 @@ xpc_mark_partition_engaged_sn2(struct xpc_partition *part)
360} 412}
361 413
362static void 414static void
363xpc_mark_partition_disengaged_sn2(struct xpc_partition *part) 415xpc_indicate_partition_disengaged_sn2(struct xpc_partition *part)
364{ 416{
417 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
365 unsigned long irq_flags; 418 unsigned long irq_flags;
366 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa + 419 AMO_t *amo = (AMO_t *)__va(part_sn2->remote_amos_page_pa +
367 (XPC_ENGAGED_PARTITIONS_AMO * 420 (XPC_ENGAGED_PARTITIONS_AMO *
368 sizeof(AMO_t))); 421 sizeof(AMO_t)));
369 422
@@ -383,96 +436,44 @@ xpc_mark_partition_disengaged_sn2(struct xpc_partition *part)
383 xp_nofault_PIOR_target)); 436 xp_nofault_PIOR_target));
384 437
385 local_irq_restore(irq_flags); 438 local_irq_restore(irq_flags);
386}
387
388static void
389xpc_request_partition_disengage_sn2(struct xpc_partition *part)
390{
391 unsigned long irq_flags;
392 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
393 (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
394
395 local_irq_save(irq_flags);
396 439
397 /* set bit corresponding to our partid in remote partition's AMO */
398 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
399 (1UL << sn_partition_id));
400 /* 440 /*
401 * We must always use the nofault function regardless of whether we 441 * Send activate IRQ to get other side to see that we've cleared our
402 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we 442 * bit in their engaged partitions AMO.
403 * didn't, we'd never know that the other partition is down and would
404 * keep sending IPIs and AMOs to it until the heartbeat times out.
405 */ 443 */
406 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo-> 444 xpc_activate_IRQ_send_sn2(part_sn2->remote_amos_page_pa,
407 variable), 445 cnodeid_to_nasid(0),
408 xp_nofault_PIOR_target)); 446 part_sn2->activate_IRQ_nasid,
409 447 part_sn2->activate_IRQ_phys_cpuid);
410 local_irq_restore(irq_flags);
411} 448}
412 449
413static void 450static int
414xpc_cancel_partition_disengage_request_sn2(struct xpc_partition *part) 451xpc_partition_engaged_sn2(short partid)
415{
416 unsigned long irq_flags;
417 AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
418 (XPC_DISENGAGE_REQUEST_AMO * sizeof(AMO_t)));
419
420 local_irq_save(irq_flags);
421
422 /* clear bit corresponding to our partid in remote partition's AMO */
423 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
424 ~(1UL << sn_partition_id));
425 /*
426 * We must always use the nofault function regardless of whether we
427 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
428 * didn't, we'd never know that the other partition is down and would
429 * keep sending IPIs and AMOs to it until the heartbeat times out.
430 */
431 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
432 variable),
433 xp_nofault_PIOR_target));
434
435 local_irq_restore(irq_flags);
436}
437
438static u64
439xpc_partition_engaged_sn2(u64 partid_mask)
440{ 452{
441 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; 453 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
442 454
443 /* return our partition's AMO variable ANDed with partid_mask */ 455 /* our partition's AMO variable ANDed with partid mask */
444 return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) & 456 return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
445 partid_mask); 457 (1UL << partid)) != 0;
446} 458}
447 459
448static u64 460static int
449xpc_partition_disengage_requested_sn2(u64 partid_mask) 461xpc_any_partition_engaged_sn2(void)
450{
451 AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
452
453 /* return our partition's AMO variable ANDed with partid_mask */
454 return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
455 partid_mask);
456}
457
458static void
459xpc_clear_partition_engaged_sn2(u64 partid_mask)
460{ 462{
461 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO; 463 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
462 464
463 /* clear bit(s) based on partid_mask in our partition's AMO */ 465 /* our partition's AMO variable */
464 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND, 466 return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) != 0;
465 ~partid_mask);
466} 467}
467 468
468static void 469static void
469xpc_clear_partition_disengage_request_sn2(u64 partid_mask) 470xpc_assume_partition_disengaged_sn2(short partid)
470{ 471{
471 AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO; 472 AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
472 473
473 /* clear bit(s) based on partid_mask in our partition's AMO */ 474 /* clear bit(s) based on partid mask in our partition's AMO */
474 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND, 475 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
475 ~partid_mask); 476 ~(1UL << partid));
476} 477}
477 478
478/* original protection values for each node */ 479/* original protection values for each node */
@@ -545,7 +546,6 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
545 xpc_vars_part = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) + 546 xpc_vars_part = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
546 XPC_RP_VARS_SIZE); 547 XPC_RP_VARS_SIZE);
547 548
548
549 /* 549 /*
550 * Before clearing xpc_vars, see if a page of AMOs had been previously 550 * Before clearing xpc_vars, see if a page of AMOs had been previously
551 * allocated. If not we'll need to allocate one and set permissions 551 * allocated. If not we'll need to allocate one and set permissions
@@ -583,8 +583,8 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
583 memset(xpc_vars, 0, sizeof(struct xpc_vars_sn2)); 583 memset(xpc_vars, 0, sizeof(struct xpc_vars_sn2));
584 584
585 xpc_vars->version = XPC_V_VERSION; 585 xpc_vars->version = XPC_V_VERSION;
586 xpc_vars->act_nasid = cpuid_to_nasid(0); 586 xpc_vars->activate_IRQ_nasid = cpuid_to_nasid(0);
587 xpc_vars->act_phys_cpuid = cpu_physical_id(0); 587 xpc_vars->activate_IRQ_phys_cpuid = cpu_physical_id(0);
588 xpc_vars->vars_part_pa = __pa(xpc_vars_part); 588 xpc_vars->vars_part_pa = __pa(xpc_vars_part);
589 xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page); 589 xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page);
590 xpc_vars->amos_page = amos_page; /* save for next load of XPC */ 590 xpc_vars->amos_page = amos_page; /* save for next load of XPC */
@@ -599,7 +599,7 @@ xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
599 599
600 /* initialize the engaged remote partitions related AMO variables */ 600 /* initialize the engaged remote partitions related AMO variables */
601 (void)xpc_IPI_init_sn2(XPC_ENGAGED_PARTITIONS_AMO); 601 (void)xpc_IPI_init_sn2(XPC_ENGAGED_PARTITIONS_AMO);
602 (void)xpc_IPI_init_sn2(XPC_DISENGAGE_REQUEST_AMO); 602 (void)xpc_IPI_init_sn2(XPC_DEACTIVATE_REQUEST_AMO);
603 603
604 return xpSuccess; 604 return xpSuccess;
605} 605}
@@ -671,7 +671,7 @@ xpc_check_remote_hb_sn2(void)
671 671
672 /* pull the remote_hb cache line */ 672 /* pull the remote_hb cache line */
673 ret = xp_remote_memcpy(remote_vars, 673 ret = xp_remote_memcpy(remote_vars,
674 (void *)part->remote_vars_pa, 674 (void *)part->sn.sn2.remote_vars_pa,
675 XPC_RP_VARS_SIZE); 675 XPC_RP_VARS_SIZE);
676 if (ret != xpSuccess) { 676 if (ret != xpSuccess) {
677 XPC_DEACTIVATE_PARTITION(part, ret); 677 XPC_DEACTIVATE_PARTITION(part, ret);
@@ -726,10 +726,86 @@ xpc_get_remote_vars_sn2(u64 remote_vars_pa, struct xpc_vars_sn2 *remote_vars)
726} 726}
727 727
728static void 728static void
729xpc_initiate_partition_activation_sn2(struct xpc_rsvd_page *remote_rp, 729xpc_request_partition_activation_sn2(struct xpc_rsvd_page *remote_rp,
730 u64 remote_rp_pa, int nasid) 730 u64 remote_rp_pa, int nasid)
731{ 731{
732 xpc_IPI_send_local_activate(nasid); 732 xpc_activate_IRQ_send_local_sn2(nasid);
733}
734
735static void
736xpc_request_partition_reactivation_sn2(struct xpc_partition *part)
737{
738 xpc_activate_IRQ_send_local_sn2(part->sn.sn2.activate_IRQ_nasid);
739}
740
741static void
742xpc_request_partition_deactivation_sn2(struct xpc_partition *part)
743{
744 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
745 unsigned long irq_flags;
746 AMO_t *amo = (AMO_t *)__va(part_sn2->remote_amos_page_pa +
747 (XPC_DEACTIVATE_REQUEST_AMO * sizeof(AMO_t)));
748
749 local_irq_save(irq_flags);
750
751 /* set bit corresponding to our partid in remote partition's AMO */
752 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
753 (1UL << sn_partition_id));
754 /*
755 * We must always use the nofault function regardless of whether we
756 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
757 * didn't, we'd never know that the other partition is down and would
758 * keep sending IPIs and AMOs to it until the heartbeat times out.
759 */
760 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
761 variable),
762 xp_nofault_PIOR_target));
763
764 local_irq_restore(irq_flags);
765
766 /*
767 * Send activate IRQ to get other side to see that we've set our
768 * bit in their deactivate request AMO.
769 */
770 xpc_activate_IRQ_send_sn2(part_sn2->remote_amos_page_pa,
771 cnodeid_to_nasid(0),
772 part_sn2->activate_IRQ_nasid,
773 part_sn2->activate_IRQ_phys_cpuid);
774}
775
776static void
777xpc_cancel_partition_deactivation_request_sn2(struct xpc_partition *part)
778{
779 unsigned long irq_flags;
780 AMO_t *amo = (AMO_t *)__va(part->sn.sn2.remote_amos_page_pa +
781 (XPC_DEACTIVATE_REQUEST_AMO * sizeof(AMO_t)));
782
783 local_irq_save(irq_flags);
784
785 /* clear bit corresponding to our partid in remote partition's AMO */
786 FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
787 ~(1UL << sn_partition_id));
788 /*
789 * We must always use the nofault function regardless of whether we
790 * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
791 * didn't, we'd never know that the other partition is down and would
792 * keep sending IPIs and AMOs to it until the heartbeat times out.
793 */
794 (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
795 variable),
796 xp_nofault_PIOR_target));
797
798 local_irq_restore(irq_flags);
799}
800
801static int
802xpc_partition_deactivation_requested_sn2(short partid)
803{
804 AMO_t *amo = xpc_vars->amos_page + XPC_DEACTIVATE_REQUEST_AMO;
805
806 /* our partition's AMO variable ANDed with partid mask */
807 return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
808 (1UL << partid)) != 0;
733} 809}
734 810
735/* 811/*
@@ -741,6 +817,8 @@ xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
741 u64 remote_vars_pa, 817 u64 remote_vars_pa,
742 struct xpc_vars_sn2 *remote_vars) 818 struct xpc_vars_sn2 *remote_vars)
743{ 819{
820 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
821
744 part->remote_rp_version = remote_rp_version; 822 part->remote_rp_version = remote_rp_version;
745 dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n", 823 dev_dbg(xpc_part, " remote_rp_version = 0x%016x\n",
746 part->remote_rp_version); 824 part->remote_rp_version);
@@ -752,33 +830,34 @@ xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
752 part->remote_rp_pa = remote_rp_pa; 830 part->remote_rp_pa = remote_rp_pa;
753 dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n", part->remote_rp_pa); 831 dev_dbg(xpc_part, " remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
754 832
755 part->remote_vars_pa = remote_vars_pa; 833 part_sn2->remote_vars_pa = remote_vars_pa;
756 dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n", 834 dev_dbg(xpc_part, " remote_vars_pa = 0x%016lx\n",
757 part->remote_vars_pa); 835 part_sn2->remote_vars_pa);
758 836
759 part->last_heartbeat = remote_vars->heartbeat; 837 part->last_heartbeat = remote_vars->heartbeat;
760 dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n", 838 dev_dbg(xpc_part, " last_heartbeat = 0x%016lx\n",
761 part->last_heartbeat); 839 part->last_heartbeat);
762 840
763 part->remote_vars_part_pa = remote_vars->vars_part_pa; 841 part_sn2->remote_vars_part_pa = remote_vars->vars_part_pa;
764 dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n", 842 dev_dbg(xpc_part, " remote_vars_part_pa = 0x%016lx\n",
765 part->remote_vars_part_pa); 843 part_sn2->remote_vars_part_pa);
766 844
767 part->remote_act_nasid = remote_vars->act_nasid; 845 part_sn2->activate_IRQ_nasid = remote_vars->activate_IRQ_nasid;
768 dev_dbg(xpc_part, " remote_act_nasid = 0x%x\n", 846 dev_dbg(xpc_part, " activate_IRQ_nasid = 0x%x\n",
769 part->remote_act_nasid); 847 part_sn2->activate_IRQ_nasid);
770 848
771 part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid; 849 part_sn2->activate_IRQ_phys_cpuid =
772 dev_dbg(xpc_part, " remote_act_phys_cpuid = 0x%x\n", 850 remote_vars->activate_IRQ_phys_cpuid;
773 part->remote_act_phys_cpuid); 851 dev_dbg(xpc_part, " activate_IRQ_phys_cpuid = 0x%x\n",
852 part_sn2->activate_IRQ_phys_cpuid);
774 853
775 part->remote_amos_page_pa = remote_vars->amos_page_pa; 854 part_sn2->remote_amos_page_pa = remote_vars->amos_page_pa;
776 dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n", 855 dev_dbg(xpc_part, " remote_amos_page_pa = 0x%lx\n",
777 part->remote_amos_page_pa); 856 part_sn2->remote_amos_page_pa);
778 857
779 part->remote_vars_version = remote_vars->version; 858 part_sn2->remote_vars_version = remote_vars->version;
780 dev_dbg(xpc_part, " remote_vars_version = 0x%x\n", 859 dev_dbg(xpc_part, " remote_vars_version = 0x%x\n",
781 part->remote_vars_version); 860 part_sn2->remote_vars_version);
782} 861}
783 862
784/* 863/*
@@ -807,6 +886,7 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
807 unsigned long remote_rp_stamp = 0; 886 unsigned long remote_rp_stamp = 0;
808 short partid; 887 short partid;
809 struct xpc_partition *part; 888 struct xpc_partition *part;
889 struct xpc_partition_sn2 *part_sn2;
810 enum xp_retval ret; 890 enum xp_retval ret;
811 891
812 /* pull over the reserved page structure */ 892 /* pull over the reserved page structure */
@@ -822,11 +902,11 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
822 902
823 remote_vars_pa = remote_rp->sn.vars_pa; 903 remote_vars_pa = remote_rp->sn.vars_pa;
824 remote_rp_version = remote_rp->version; 904 remote_rp_version = remote_rp->version;
825 if (XPC_SUPPORTS_RP_STAMP(remote_rp_version)) 905 remote_rp_stamp = remote_rp->stamp;
826 remote_rp_stamp = remote_rp->stamp;
827 906
828 partid = remote_rp->SAL_partid; 907 partid = remote_rp->SAL_partid;
829 part = &xpc_partitions[partid]; 908 part = &xpc_partitions[partid];
909 part_sn2 = &part->sn.sn2;
830 910
831 /* pull over the cross partition variables */ 911 /* pull over the cross partition variables */
832 912
@@ -834,7 +914,6 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
834 914
835 ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars); 915 ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
836 if (ret != xpSuccess) { 916 if (ret != xpSuccess) {
837
838 dev_warn(xpc_part, "unable to get XPC variables from nasid %d, " 917 dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
839 "which sent interrupt, reason=%d\n", nasid, ret); 918 "which sent interrupt, reason=%d\n", nasid, ret);
840 919
@@ -855,18 +934,12 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
855 &remote_rp_stamp, remote_rp_pa, 934 &remote_rp_stamp, remote_rp_pa,
856 remote_vars_pa, remote_vars); 935 remote_vars_pa, remote_vars);
857 936
858 if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) { 937 if (xpc_partition_deactivation_requested_sn2(partid)) {
859 if (xpc_partition_disengage_requested(1UL << partid)) { 938 /*
860 /* 939 * Other side is waiting on us to deactivate even though
861 * Other side is waiting on us to disengage, 940 * we already have.
862 * even though we already have. 941 */
863 */ 942 return;
864 return;
865 }
866
867 } else {
868 /* other side doesn't support disengage requests */
869 xpc_clear_partition_disengage_request(1UL << partid);
870 } 943 }
871 944
872 xpc_activate_partition(part); 945 xpc_activate_partition(part);
@@ -874,93 +947,30 @@ xpc_identify_activate_IRQ_req_sn2(int nasid)
874 } 947 }
875 948
876 DBUG_ON(part->remote_rp_version == 0); 949 DBUG_ON(part->remote_rp_version == 0);
877 DBUG_ON(part->remote_vars_version == 0); 950 DBUG_ON(part_sn2->remote_vars_version == 0);
878
879 if (!XPC_SUPPORTS_RP_STAMP(part->remote_rp_version)) {
880 DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(part->
881 remote_vars_version));
882
883 if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
884 DBUG_ON(XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->
885 version));
886 /* see if the other side rebooted */
887 if (part->remote_amos_page_pa ==
888 remote_vars->amos_page_pa &&
889 xpc_hb_allowed(sn_partition_id,
890 &remote_vars->heartbeating_to_mask)) {
891 /* doesn't look that way, so ignore the IPI */
892 return;
893 }
894 }
895 951
896 /* 952 if (remote_rp_stamp != part->remote_rp_stamp) {
897 * Other side rebooted and previous XPC didn't support the
898 * disengage request, so we don't need to do anything special.
899 */
900 953
901 xpc_update_partition_info_sn2(part, remote_rp_version, 954 /* the other side rebooted */
902 &remote_rp_stamp, remote_rp_pa,
903 remote_vars_pa, remote_vars);
904 part->reactivate_nasid = nasid;
905 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
906 return;
907 }
908 955
909 DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)); 956 DBUG_ON(xpc_partition_engaged_sn2(partid));
910 957 DBUG_ON(xpc_partition_deactivation_requested_sn2(partid));
911 if (!XPC_SUPPORTS_RP_STAMP(remote_rp_version)) {
912 DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
913
914 /*
915 * Other side rebooted and previous XPC did support the
916 * disengage request, but the new one doesn't.
917 */
918
919 xpc_clear_partition_engaged(1UL << partid);
920 xpc_clear_partition_disengage_request(1UL << partid);
921 958
922 xpc_update_partition_info_sn2(part, remote_rp_version, 959 xpc_update_partition_info_sn2(part, remote_rp_version,
923 &remote_rp_stamp, remote_rp_pa, 960 &remote_rp_stamp, remote_rp_pa,
924 remote_vars_pa, remote_vars); 961 remote_vars_pa, remote_vars);
925 reactivate = 1; 962 reactivate = 1;
926
927 } else {
928 DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(remote_vars->version));
929
930 if (remote_rp_stamp != part->remote_rp_stamp) {
931
932 /*
933 * Other side rebooted and the previous XPC did support
934 * the disengage request, as does the new one.
935 */
936
937 DBUG_ON(xpc_partition_engaged(1UL << partid));
938 DBUG_ON(xpc_partition_disengage_requested(1UL <<
939 partid));
940
941 xpc_update_partition_info_sn2(part, remote_rp_version,
942 &remote_rp_stamp,
943 remote_rp_pa,
944 remote_vars_pa,
945 remote_vars);
946 reactivate = 1;
947 }
948 } 963 }
949 964
950 if (part->disengage_request_timeout > 0 && 965 if (part->disengage_timeout > 0 && !xpc_partition_disengaged(part)) {
951 !xpc_partition_disengaged(part)) {
952 /* still waiting on other side to disengage from us */ 966 /* still waiting on other side to disengage from us */
953 return; 967 return;
954 } 968 }
955 969
956 if (reactivate) { 970 if (reactivate)
957 part->reactivate_nasid = nasid;
958 XPC_DEACTIVATE_PARTITION(part, xpReactivating); 971 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
959 972 else if (xpc_partition_deactivation_requested_sn2(partid))
960 } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
961 xpc_partition_disengage_requested(1UL << partid)) {
962 XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown); 973 XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown);
963 }
964} 974}
965 975
966/* 976/*
@@ -1038,6 +1048,7 @@ xpc_process_activate_IRQ_rcvd_sn2(int n_IRQs_expected)
1038static enum xp_retval 1048static enum xp_retval
1039xpc_setup_infrastructure_sn2(struct xpc_partition *part) 1049xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1040{ 1050{
1051 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1041 enum xp_retval retval; 1052 enum xp_retval retval;
1042 int ret; 1053 int ret;
1043 int cpuid; 1054 int cpuid;
@@ -1060,28 +1071,29 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1060 1071
1061 /* allocate all the required GET/PUT values */ 1072 /* allocate all the required GET/PUT values */
1062 1073
1063 part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, 1074 part_sn2->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
1064 GFP_KERNEL, 1075 GFP_KERNEL,
1065 &part->local_GPs_base); 1076 &part_sn2->
1066 if (part->local_GPs == NULL) { 1077 local_GPs_base);
1078 if (part_sn2->local_GPs == NULL) {
1067 dev_err(xpc_chan, "can't get memory for local get/put " 1079 dev_err(xpc_chan, "can't get memory for local get/put "
1068 "values\n"); 1080 "values\n");
1069 retval = xpNoMemory; 1081 retval = xpNoMemory;
1070 goto out_1; 1082 goto out_1;
1071 } 1083 }
1072 1084
1073 part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, 1085 part_sn2->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
1074 GFP_KERNEL, 1086 GFP_KERNEL,
1075 &part-> 1087 &part_sn2->
1076 remote_GPs_base); 1088 remote_GPs_base);
1077 if (part->remote_GPs == NULL) { 1089 if (part_sn2->remote_GPs == NULL) {
1078 dev_err(xpc_chan, "can't get memory for remote get/put " 1090 dev_err(xpc_chan, "can't get memory for remote get/put "
1079 "values\n"); 1091 "values\n");
1080 retval = xpNoMemory; 1092 retval = xpNoMemory;
1081 goto out_2; 1093 goto out_2;
1082 } 1094 }
1083 1095
1084 part->remote_GPs_pa = 0; 1096 part_sn2->remote_GPs_pa = 0;
1085 1097
1086 /* allocate all the required open and close args */ 1098 /* allocate all the required open and close args */
1087 1099
@@ -1103,22 +1115,23 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1103 goto out_4; 1115 goto out_4;
1104 } 1116 }
1105 1117
1106 part->remote_openclose_args_pa = 0; 1118 part_sn2->remote_openclose_args_pa = 0;
1107 1119
1108 part->local_IPI_amo_va = xpc_IPI_init_sn2(partid); 1120 part_sn2->local_IPI_amo_va = xpc_IPI_init_sn2(partid);
1109 part->local_IPI_amo = 0; 1121 part->local_IPI_amo = 0;
1110 spin_lock_init(&part->IPI_lock); 1122 spin_lock_init(&part->IPI_lock);
1111 1123
1112 part->remote_IPI_nasid = 0; 1124 part_sn2->remote_IPI_nasid = 0;
1113 part->remote_IPI_phys_cpuid = 0; 1125 part_sn2->remote_IPI_phys_cpuid = 0;
1114 part->remote_IPI_amo_va = NULL; 1126 part_sn2->remote_IPI_amo_va = NULL;
1115 1127
1116 atomic_set(&part->channel_mgr_requests, 1); 1128 atomic_set(&part->channel_mgr_requests, 1);
1117 init_waitqueue_head(&part->channel_mgr_wq); 1129 init_waitqueue_head(&part->channel_mgr_wq);
1118 1130
1119 sprintf(part->IPI_owner, "xpc%02d", partid); 1131 sprintf(part_sn2->IPI_owner, "xpc%02d", partid);
1120 ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED, 1132 ret = request_irq(SGI_XPC_NOTIFY, xpc_handle_notify_IRQ_sn2,
1121 part->IPI_owner, (void *)(u64)partid); 1133 IRQF_SHARED, part_sn2->IPI_owner,
1134 (void *)(u64)partid);
1122 if (ret != 0) { 1135 if (ret != 0) {
1123 dev_err(xpc_chan, "can't register NOTIFY IRQ handler, " 1136 dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
1124 "errno=%d\n", -ret); 1137 "errno=%d\n", -ret);
@@ -1127,9 +1140,10 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1127 } 1140 }
1128 1141
1129 /* Setup a timer to check for dropped IPIs */ 1142 /* Setup a timer to check for dropped IPIs */
1130 timer = &part->dropped_IPI_timer; 1143 timer = &part_sn2->dropped_notify_IRQ_timer;
1131 init_timer(timer); 1144 init_timer(timer);
1132 timer->function = (void (*)(unsigned long))xpc_dropped_IPI_check; 1145 timer->function =
1146 (void (*)(unsigned long))xpc_dropped_notify_IRQ_check_sn2;
1133 timer->data = (unsigned long)part; 1147 timer->data = (unsigned long)part;
1134 timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT_INTERVAL; 1148 timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT_INTERVAL;
1135 add_timer(timer); 1149 add_timer(timer);
@@ -1146,7 +1160,7 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1146 ch->number = ch_number; 1160 ch->number = ch_number;
1147 ch->flags = XPC_C_DISCONNECTED; 1161 ch->flags = XPC_C_DISCONNECTED;
1148 1162
1149 ch->local_GP = &part->local_GPs[ch_number]; 1163 ch->sn.sn2.local_GP = &part_sn2->local_GPs[ch_number];
1150 ch->local_openclose_args = 1164 ch->local_openclose_args =
1151 &part->local_openclose_args[ch_number]; 1165 &part->local_openclose_args[ch_number];
1152 1166
@@ -1158,7 +1172,7 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1158 atomic_set(&ch->n_to_notify, 0); 1172 atomic_set(&ch->n_to_notify, 0);
1159 1173
1160 spin_lock_init(&ch->lock); 1174 spin_lock_init(&ch->lock);
1161 mutex_init(&ch->msg_to_pull_mutex); 1175 mutex_init(&ch->sn.sn2.msg_to_pull_mutex);
1162 init_completion(&ch->wdisconnect_wait); 1176 init_completion(&ch->wdisconnect_wait);
1163 1177
1164 atomic_set(&ch->n_on_msg_allocate_wq, 0); 1178 atomic_set(&ch->n_on_msg_allocate_wq, 0);
@@ -1179,10 +1193,10 @@ xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1179 * The setting of the magic # indicates that these per partition 1193 * The setting of the magic # indicates that these per partition
1180 * specific variables are ready to be used. 1194 * specific variables are ready to be used.
1181 */ 1195 */
1182 xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs); 1196 xpc_vars_part[partid].GPs_pa = __pa(part_sn2->local_GPs);
1183 xpc_vars_part[partid].openclose_args_pa = 1197 xpc_vars_part[partid].openclose_args_pa =
1184 __pa(part->local_openclose_args); 1198 __pa(part->local_openclose_args);
1185 xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va); 1199 xpc_vars_part[partid].IPI_amo_pa = __pa(part_sn2->local_IPI_amo_va);
1186 cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */ 1200 cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
1187 xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid); 1201 xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid);
1188 xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid); 1202 xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid);
@@ -1199,11 +1213,11 @@ out_4:
1199 kfree(part->local_openclose_args_base); 1213 kfree(part->local_openclose_args_base);
1200 part->local_openclose_args = NULL; 1214 part->local_openclose_args = NULL;
1201out_3: 1215out_3:
1202 kfree(part->remote_GPs_base); 1216 kfree(part_sn2->remote_GPs_base);
1203 part->remote_GPs = NULL; 1217 part_sn2->remote_GPs = NULL;
1204out_2: 1218out_2:
1205 kfree(part->local_GPs_base); 1219 kfree(part_sn2->local_GPs_base);
1206 part->local_GPs = NULL; 1220 part_sn2->local_GPs = NULL;
1207out_1: 1221out_1:
1208 kfree(part->channels); 1222 kfree(part->channels);
1209 part->channels = NULL; 1223 part->channels = NULL;
@@ -1217,6 +1231,7 @@ out_1:
1217static void 1231static void
1218xpc_teardown_infrastructure_sn2(struct xpc_partition *part) 1232xpc_teardown_infrastructure_sn2(struct xpc_partition *part)
1219{ 1233{
1234 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1220 short partid = XPC_PARTID(part); 1235 short partid = XPC_PARTID(part);
1221 1236
1222 /* 1237 /*
@@ -1248,19 +1263,19 @@ xpc_teardown_infrastructure_sn2(struct xpc_partition *part)
1248 part->setup_state = XPC_P_TORNDOWN; 1263 part->setup_state = XPC_P_TORNDOWN;
1249 1264
1250 /* in case we've still got outstanding timers registered... */ 1265 /* in case we've still got outstanding timers registered... */
1251 del_timer_sync(&part->dropped_IPI_timer); 1266 del_timer_sync(&part_sn2->dropped_notify_IRQ_timer);
1252 1267
1253 kfree(part->remote_openclose_args_base); 1268 kfree(part->remote_openclose_args_base);
1254 part->remote_openclose_args = NULL; 1269 part->remote_openclose_args = NULL;
1255 kfree(part->local_openclose_args_base); 1270 kfree(part->local_openclose_args_base);
1256 part->local_openclose_args = NULL; 1271 part->local_openclose_args = NULL;
1257 kfree(part->remote_GPs_base); 1272 kfree(part_sn2->remote_GPs_base);
1258 part->remote_GPs = NULL; 1273 part_sn2->remote_GPs = NULL;
1259 kfree(part->local_GPs_base); 1274 kfree(part_sn2->local_GPs_base);
1260 part->local_GPs = NULL; 1275 part_sn2->local_GPs = NULL;
1261 kfree(part->channels); 1276 kfree(part->channels);
1262 part->channels = NULL; 1277 part->channels = NULL;
1263 part->local_IPI_amo_va = NULL; 1278 part_sn2->local_IPI_amo_va = NULL;
1264} 1279}
1265 1280
1266/* 1281/*
@@ -1300,6 +1315,7 @@ xpc_pull_remote_cachelines_sn2(struct xpc_partition *part, void *dst,
1300static enum xp_retval 1315static enum xp_retval
1301xpc_pull_remote_vars_part_sn2(struct xpc_partition *part) 1316xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1302{ 1317{
1318 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1303 u8 buffer[L1_CACHE_BYTES * 2]; 1319 u8 buffer[L1_CACHE_BYTES * 2];
1304 struct xpc_vars_part_sn2 *pulled_entry_cacheline = 1320 struct xpc_vars_part_sn2 *pulled_entry_cacheline =
1305 (struct xpc_vars_part_sn2 *)L1_CACHE_ALIGN((u64)buffer); 1321 (struct xpc_vars_part_sn2 *)L1_CACHE_ALIGN((u64)buffer);
@@ -1310,11 +1326,11 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1310 1326
1311 /* pull the cacheline that contains the variables we're interested in */ 1327 /* pull the cacheline that contains the variables we're interested in */
1312 1328
1313 DBUG_ON(part->remote_vars_part_pa != 1329 DBUG_ON(part_sn2->remote_vars_part_pa !=
1314 L1_CACHE_ALIGN(part->remote_vars_part_pa)); 1330 L1_CACHE_ALIGN(part_sn2->remote_vars_part_pa));
1315 DBUG_ON(sizeof(struct xpc_vars_part_sn2) != L1_CACHE_BYTES / 2); 1331 DBUG_ON(sizeof(struct xpc_vars_part_sn2) != L1_CACHE_BYTES / 2);
1316 1332
1317 remote_entry_pa = part->remote_vars_part_pa + 1333 remote_entry_pa = part_sn2->remote_vars_part_pa +
1318 sn_partition_id * sizeof(struct xpc_vars_part_sn2); 1334 sn_partition_id * sizeof(struct xpc_vars_part_sn2);
1319 1335
1320 remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1)); 1336 remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
@@ -1364,13 +1380,13 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1364 1380
1365 /* the variables we imported look to be valid */ 1381 /* the variables we imported look to be valid */
1366 1382
1367 part->remote_GPs_pa = pulled_entry->GPs_pa; 1383 part_sn2->remote_GPs_pa = pulled_entry->GPs_pa;
1368 part->remote_openclose_args_pa = 1384 part_sn2->remote_openclose_args_pa =
1369 pulled_entry->openclose_args_pa; 1385 pulled_entry->openclose_args_pa;
1370 part->remote_IPI_amo_va = 1386 part_sn2->remote_IPI_amo_va =
1371 (AMO_t *)__va(pulled_entry->IPI_amo_pa); 1387 (AMO_t *)__va(pulled_entry->IPI_amo_pa);
1372 part->remote_IPI_nasid = pulled_entry->IPI_nasid; 1388 part_sn2->remote_IPI_nasid = pulled_entry->IPI_nasid;
1373 part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid; 1389 part_sn2->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
1374 1390
1375 if (part->nchannels > pulled_entry->nchannels) 1391 if (part->nchannels > pulled_entry->nchannels)
1376 part->nchannels = pulled_entry->nchannels; 1392 part->nchannels = pulled_entry->nchannels;
@@ -1394,6 +1410,7 @@ xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1394static enum xp_retval 1410static enum xp_retval
1395xpc_make_first_contact_sn2(struct xpc_partition *part) 1411xpc_make_first_contact_sn2(struct xpc_partition *part)
1396{ 1412{
1413 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1397 enum xp_retval ret; 1414 enum xp_retval ret;
1398 1415
1399 /* 1416 /*
@@ -1406,7 +1423,7 @@ xpc_make_first_contact_sn2(struct xpc_partition *part)
1406 * we should get the same page for remote_amos_page_pa after module 1423 * we should get the same page for remote_amos_page_pa after module
1407 * reloads and system reboots. 1424 * reloads and system reboots.
1408 */ 1425 */
1409 if (sn_register_xp_addr_region(part->remote_amos_page_pa, 1426 if (sn_register_xp_addr_region(part_sn2->remote_amos_page_pa,
1410 PAGE_SIZE, 1) < 0) { 1427 PAGE_SIZE, 1) < 0) {
1411 dev_warn(xpc_part, "xpc_activating(%d) failed to register " 1428 dev_warn(xpc_part, "xpc_activating(%d) failed to register "
1412 "xp_addr region\n", XPC_PARTID(part)); 1429 "xp_addr region\n", XPC_PARTID(part));
@@ -1416,7 +1433,14 @@ xpc_make_first_contact_sn2(struct xpc_partition *part)
1416 return ret; 1433 return ret;
1417 } 1434 }
1418 1435
1419 xpc_IPI_send_activated(part); 1436 /*
1437 * Send activate IRQ to get other side to activate if they've not
1438 * already begun to do so.
1439 */
1440 xpc_activate_IRQ_send_sn2(part_sn2->remote_amos_page_pa,
1441 cnodeid_to_nasid(0),
1442 part_sn2->activate_IRQ_nasid,
1443 part_sn2->activate_IRQ_phys_cpuid);
1420 1444
1421 while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) { 1445 while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) {
1422 if (ret != xpRetry) { 1446 if (ret != xpRetry) {
@@ -1443,6 +1467,7 @@ xpc_make_first_contact_sn2(struct xpc_partition *part)
1443static u64 1467static u64
1444xpc_get_IPI_flags_sn2(struct xpc_partition *part) 1468xpc_get_IPI_flags_sn2(struct xpc_partition *part)
1445{ 1469{
1470 struct xpc_partition_sn2 *part_sn2 = &part->sn.sn2;
1446 unsigned long irq_flags; 1471 unsigned long irq_flags;
1447 u64 IPI_amo; 1472 u64 IPI_amo;
1448 enum xp_retval ret; 1473 enum xp_retval ret;
@@ -1459,9 +1484,9 @@ xpc_get_IPI_flags_sn2(struct xpc_partition *part)
1459 spin_unlock_irqrestore(&part->IPI_lock, irq_flags); 1484 spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
1460 1485
1461 if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) { 1486 if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
1462 ret = xpc_pull_remote_cachelines_sn2(part, 1487 ret = xpc_pull_remote_cachelines_sn2(part, part->
1463 part->remote_openclose_args, 1488 remote_openclose_args,
1464 (void *)part-> 1489 (void *)part_sn2->
1465 remote_openclose_args_pa, 1490 remote_openclose_args_pa,
1466 XPC_OPENCLOSE_ARGS_SIZE); 1491 XPC_OPENCLOSE_ARGS_SIZE);
1467 if (ret != xpSuccess) { 1492 if (ret != xpSuccess) {
@@ -1477,8 +1502,8 @@ xpc_get_IPI_flags_sn2(struct xpc_partition *part)
1477 } 1502 }
1478 1503
1479 if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) { 1504 if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
1480 ret = xpc_pull_remote_cachelines_sn2(part, part->remote_GPs, 1505 ret = xpc_pull_remote_cachelines_sn2(part, part_sn2->remote_GPs,
1481 (void *)part->remote_GPs_pa, 1506 (void *)part_sn2->remote_GPs_pa,
1482 XPC_GP_SIZE); 1507 XPC_GP_SIZE);
1483 if (ret != xpSuccess) { 1508 if (ret != xpSuccess) {
1484 XPC_DEACTIVATE_PARTITION(part, ret); 1509 XPC_DEACTIVATE_PARTITION(part, ret);
@@ -1494,28 +1519,220 @@ xpc_get_IPI_flags_sn2(struct xpc_partition *part)
1494 return IPI_amo; 1519 return IPI_amo;
1495} 1520}
1496 1521
1522/*
1523 * Notify those who wanted to be notified upon delivery of their message.
1524 */
1525static void
1526xpc_notify_senders_sn2(struct xpc_channel *ch, enum xp_retval reason, s64 put)
1527{
1528 struct xpc_notify *notify;
1529 u8 notify_type;
1530 s64 get = ch->sn.sn2.w_remote_GP.get - 1;
1531
1532 while (++get < put && atomic_read(&ch->n_to_notify) > 0) {
1533
1534 notify = &ch->notify_queue[get % ch->local_nentries];
1535
1536 /*
1537 * See if the notify entry indicates it was associated with
1538 * a message who's sender wants to be notified. It is possible
1539 * that it is, but someone else is doing or has done the
1540 * notification.
1541 */
1542 notify_type = notify->type;
1543 if (notify_type == 0 ||
1544 cmpxchg(&notify->type, notify_type, 0) != notify_type) {
1545 continue;
1546 }
1547
1548 DBUG_ON(notify_type != XPC_N_CALL);
1549
1550 atomic_dec(&ch->n_to_notify);
1551
1552 if (notify->func != NULL) {
1553 dev_dbg(xpc_chan, "notify->func() called, notify=0x%p, "
1554 "msg_number=%ld, partid=%d, channel=%d\n",
1555 (void *)notify, get, ch->partid, ch->number);
1556
1557 notify->func(reason, ch->partid, ch->number,
1558 notify->key);
1559
1560 dev_dbg(xpc_chan, "notify->func() returned, "
1561 "notify=0x%p, msg_number=%ld, partid=%d, "
1562 "channel=%d\n", (void *)notify, get,
1563 ch->partid, ch->number);
1564 }
1565 }
1566}
1567
1568static void
1569xpc_notify_senders_of_disconnect_sn2(struct xpc_channel *ch)
1570{
1571 xpc_notify_senders_sn2(ch, ch->reason, ch->sn.sn2.w_local_GP.put);
1572}
1573
1574/*
1575 * Clear some of the msg flags in the local message queue.
1576 */
1577static inline void
1578xpc_clear_local_msgqueue_flags_sn2(struct xpc_channel *ch)
1579{
1580 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1581 struct xpc_msg *msg;
1582 s64 get;
1583
1584 get = ch_sn2->w_remote_GP.get;
1585 do {
1586 msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
1587 (get % ch->local_nentries) *
1588 ch->msg_size);
1589 msg->flags = 0;
1590 } while (++get < ch_sn2->remote_GP.get);
1591}
1592
1593/*
1594 * Clear some of the msg flags in the remote message queue.
1595 */
1596static inline void
1597xpc_clear_remote_msgqueue_flags_sn2(struct xpc_channel *ch)
1598{
1599 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1600 struct xpc_msg *msg;
1601 s64 put;
1602
1603 put = ch_sn2->w_remote_GP.put;
1604 do {
1605 msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
1606 (put % ch->remote_nentries) *
1607 ch->msg_size);
1608 msg->flags = 0;
1609 } while (++put < ch_sn2->remote_GP.put);
1610}
1611
1612static void
1613xpc_process_msg_IPI_sn2(struct xpc_partition *part, int ch_number)
1614{
1615 struct xpc_channel *ch = &part->channels[ch_number];
1616 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1617 int nmsgs_sent;
1618
1619 ch_sn2->remote_GP = part->sn.sn2.remote_GPs[ch_number];
1620
1621 /* See what, if anything, has changed for each connected channel */
1622
1623 xpc_msgqueue_ref(ch);
1624
1625 if (ch_sn2->w_remote_GP.get == ch_sn2->remote_GP.get &&
1626 ch_sn2->w_remote_GP.put == ch_sn2->remote_GP.put) {
1627 /* nothing changed since GPs were last pulled */
1628 xpc_msgqueue_deref(ch);
1629 return;
1630 }
1631
1632 if (!(ch->flags & XPC_C_CONNECTED)) {
1633 xpc_msgqueue_deref(ch);
1634 return;
1635 }
1636
1637 /*
1638 * First check to see if messages recently sent by us have been
1639 * received by the other side. (The remote GET value will have
1640 * changed since we last looked at it.)
1641 */
1642
1643 if (ch_sn2->w_remote_GP.get != ch_sn2->remote_GP.get) {
1644
1645 /*
1646 * We need to notify any senders that want to be notified
1647 * that their sent messages have been received by their
1648 * intended recipients. We need to do this before updating
1649 * w_remote_GP.get so that we don't allocate the same message
1650 * queue entries prematurely (see xpc_allocate_msg()).
1651 */
1652 if (atomic_read(&ch->n_to_notify) > 0) {
1653 /*
1654 * Notify senders that messages sent have been
1655 * received and delivered by the other side.
1656 */
1657 xpc_notify_senders_sn2(ch, xpMsgDelivered,
1658 ch_sn2->remote_GP.get);
1659 }
1660
1661 /*
1662 * Clear msg->flags in previously sent messages, so that
1663 * they're ready for xpc_allocate_msg().
1664 */
1665 xpc_clear_local_msgqueue_flags_sn2(ch);
1666
1667 ch_sn2->w_remote_GP.get = ch_sn2->remote_GP.get;
1668
1669 dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
1670 "channel=%d\n", ch_sn2->w_remote_GP.get, ch->partid,
1671 ch->number);
1672
1673 /*
1674 * If anyone was waiting for message queue entries to become
1675 * available, wake them up.
1676 */
1677 if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
1678 wake_up(&ch->msg_allocate_wq);
1679 }
1680
1681 /*
1682 * Now check for newly sent messages by the other side. (The remote
1683 * PUT value will have changed since we last looked at it.)
1684 */
1685
1686 if (ch_sn2->w_remote_GP.put != ch_sn2->remote_GP.put) {
1687 /*
1688 * Clear msg->flags in previously received messages, so that
1689 * they're ready for xpc_get_deliverable_msg().
1690 */
1691 xpc_clear_remote_msgqueue_flags_sn2(ch);
1692
1693 ch_sn2->w_remote_GP.put = ch_sn2->remote_GP.put;
1694
1695 dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
1696 "channel=%d\n", ch_sn2->w_remote_GP.put, ch->partid,
1697 ch->number);
1698
1699 nmsgs_sent = ch_sn2->w_remote_GP.put - ch_sn2->w_local_GP.get;
1700 if (nmsgs_sent > 0) {
1701 dev_dbg(xpc_chan, "msgs waiting to be copied and "
1702 "delivered=%d, partid=%d, channel=%d\n",
1703 nmsgs_sent, ch->partid, ch->number);
1704
1705 if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)
1706 xpc_activate_kthreads(ch, nmsgs_sent);
1707 }
1708 }
1709
1710 xpc_msgqueue_deref(ch);
1711}
1712
1497static struct xpc_msg * 1713static struct xpc_msg *
1498xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get) 1714xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1499{ 1715{
1500 struct xpc_partition *part = &xpc_partitions[ch->partid]; 1716 struct xpc_partition *part = &xpc_partitions[ch->partid];
1717 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1501 struct xpc_msg *remote_msg, *msg; 1718 struct xpc_msg *remote_msg, *msg;
1502 u32 msg_index, nmsgs; 1719 u32 msg_index, nmsgs;
1503 u64 msg_offset; 1720 u64 msg_offset;
1504 enum xp_retval ret; 1721 enum xp_retval ret;
1505 1722
1506 if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) { 1723 if (mutex_lock_interruptible(&ch_sn2->msg_to_pull_mutex) != 0) {
1507 /* we were interrupted by a signal */ 1724 /* we were interrupted by a signal */
1508 return NULL; 1725 return NULL;
1509 } 1726 }
1510 1727
1511 while (get >= ch->next_msg_to_pull) { 1728 while (get >= ch_sn2->next_msg_to_pull) {
1512 1729
1513 /* pull as many messages as are ready and able to be pulled */ 1730 /* pull as many messages as are ready and able to be pulled */
1514 1731
1515 msg_index = ch->next_msg_to_pull % ch->remote_nentries; 1732 msg_index = ch_sn2->next_msg_to_pull % ch->remote_nentries;
1516 1733
1517 DBUG_ON(ch->next_msg_to_pull >= ch->w_remote_GP.put); 1734 DBUG_ON(ch_sn2->next_msg_to_pull >= ch_sn2->w_remote_GP.put);
1518 nmsgs = ch->w_remote_GP.put - ch->next_msg_to_pull; 1735 nmsgs = ch_sn2->w_remote_GP.put - ch_sn2->next_msg_to_pull;
1519 if (msg_index + nmsgs > ch->remote_nentries) { 1736 if (msg_index + nmsgs > ch->remote_nentries) {
1520 /* ignore the ones that wrap the msg queue for now */ 1737 /* ignore the ones that wrap the msg queue for now */
1521 nmsgs = ch->remote_nentries - msg_index; 1738 nmsgs = ch->remote_nentries - msg_index;
@@ -1532,19 +1749,19 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1532 1749
1533 dev_dbg(xpc_chan, "failed to pull %d msgs starting with" 1750 dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
1534 " msg %ld from partition %d, channel=%d, " 1751 " msg %ld from partition %d, channel=%d, "
1535 "ret=%d\n", nmsgs, ch->next_msg_to_pull, 1752 "ret=%d\n", nmsgs, ch_sn2->next_msg_to_pull,
1536 ch->partid, ch->number, ret); 1753 ch->partid, ch->number, ret);
1537 1754
1538 XPC_DEACTIVATE_PARTITION(part, ret); 1755 XPC_DEACTIVATE_PARTITION(part, ret);
1539 1756
1540 mutex_unlock(&ch->msg_to_pull_mutex); 1757 mutex_unlock(&ch_sn2->msg_to_pull_mutex);
1541 return NULL; 1758 return NULL;
1542 } 1759 }
1543 1760
1544 ch->next_msg_to_pull += nmsgs; 1761 ch_sn2->next_msg_to_pull += nmsgs;
1545 } 1762 }
1546 1763
1547 mutex_unlock(&ch->msg_to_pull_mutex); 1764 mutex_unlock(&ch_sn2->msg_to_pull_mutex);
1548 1765
1549 /* return the message we were looking for */ 1766 /* return the message we were looking for */
1550 msg_offset = (get % ch->remote_nentries) * ch->msg_size; 1767 msg_offset = (get % ch->remote_nentries) * ch->msg_size;
@@ -1553,12 +1770,19 @@ xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1553 return msg; 1770 return msg;
1554} 1771}
1555 1772
1773static int
1774xpc_n_of_deliverable_msgs_sn2(struct xpc_channel *ch)
1775{
1776 return ch->sn.sn2.w_remote_GP.put - ch->sn.sn2.w_local_GP.get;
1777}
1778
1556/* 1779/*
1557 * Get a message to be delivered. 1780 * Get a message to be delivered.
1558 */ 1781 */
1559static struct xpc_msg * 1782static struct xpc_msg *
1560xpc_get_deliverable_msg_sn2(struct xpc_channel *ch) 1783xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
1561{ 1784{
1785 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1562 struct xpc_msg *msg = NULL; 1786 struct xpc_msg *msg = NULL;
1563 s64 get; 1787 s64 get;
1564 1788
@@ -1566,9 +1790,9 @@ xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
1566 if (ch->flags & XPC_C_DISCONNECTING) 1790 if (ch->flags & XPC_C_DISCONNECTING)
1567 break; 1791 break;
1568 1792
1569 get = ch->w_local_GP.get; 1793 get = ch_sn2->w_local_GP.get;
1570 rmb(); /* guarantee that .get loads before .put */ 1794 rmb(); /* guarantee that .get loads before .put */
1571 if (get == ch->w_remote_GP.put) 1795 if (get == ch_sn2->w_remote_GP.put)
1572 break; 1796 break;
1573 1797
1574 /* There are messages waiting to be pulled and delivered. 1798 /* There are messages waiting to be pulled and delivered.
@@ -1578,7 +1802,7 @@ xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
1578 * to try again for the next one. 1802 * to try again for the next one.
1579 */ 1803 */
1580 1804
1581 if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) { 1805 if (cmpxchg(&ch_sn2->w_local_GP.get, get, get + 1) == get) {
1582 /* we got the entry referenced by get */ 1806 /* we got the entry referenced by get */
1583 1807
1584 dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, " 1808 dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
@@ -1609,6 +1833,7 @@ xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
1609static void 1833static void
1610xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put) 1834xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1611{ 1835{
1836 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1612 struct xpc_msg *msg; 1837 struct xpc_msg *msg;
1613 s64 put = initial_put + 1; 1838 s64 put = initial_put + 1;
1614 int send_IPI = 0; 1839 int send_IPI = 0;
@@ -1616,7 +1841,7 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1616 while (1) { 1841 while (1) {
1617 1842
1618 while (1) { 1843 while (1) {
1619 if (put == ch->w_local_GP.put) 1844 if (put == ch_sn2->w_local_GP.put)
1620 break; 1845 break;
1621 1846
1622 msg = (struct xpc_msg *)((u64)ch->local_msgqueue + 1847 msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
@@ -1634,10 +1859,10 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1634 break; 1859 break;
1635 } 1860 }
1636 1861
1637 if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) != 1862 if (cmpxchg_rel(&ch_sn2->local_GP->put, initial_put, put) !=
1638 initial_put) { 1863 initial_put) {
1639 /* someone else beat us to it */ 1864 /* someone else beat us to it */
1640 DBUG_ON(ch->local_GP->put < initial_put); 1865 DBUG_ON(ch_sn2->local_GP->put < initial_put);
1641 break; 1866 break;
1642 } 1867 }
1643 1868
@@ -1657,7 +1882,7 @@ xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1657 } 1882 }
1658 1883
1659 if (send_IPI) 1884 if (send_IPI)
1660 xpc_IPI_send_msgrequest_sn2(ch); 1885 xpc_send_channel_msgrequest_sn2(ch);
1661} 1886}
1662 1887
1663/* 1888/*
@@ -1668,6 +1893,7 @@ static enum xp_retval
1668xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags, 1893xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
1669 struct xpc_msg **address_of_msg) 1894 struct xpc_msg **address_of_msg)
1670{ 1895{
1896 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1671 struct xpc_msg *msg; 1897 struct xpc_msg *msg;
1672 enum xp_retval ret; 1898 enum xp_retval ret;
1673 s64 put; 1899 s64 put;
@@ -1681,9 +1907,9 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
1681 1907
1682 while (1) { 1908 while (1) {
1683 1909
1684 put = ch->w_local_GP.put; 1910 put = ch_sn2->w_local_GP.put;
1685 rmb(); /* guarantee that .put loads before .get */ 1911 rmb(); /* guarantee that .put loads before .get */
1686 if (put - ch->w_remote_GP.get < ch->local_nentries) { 1912 if (put - ch_sn2->w_remote_GP.get < ch->local_nentries) {
1687 1913
1688 /* There are available message entries. We need to try 1914 /* There are available message entries. We need to try
1689 * to secure one for ourselves. We'll do this by trying 1915 * to secure one for ourselves. We'll do this by trying
@@ -1691,7 +1917,8 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
1691 * doesn't beat us to it. If they do, we'll have to 1917 * doesn't beat us to it. If they do, we'll have to
1692 * try again. 1918 * try again.
1693 */ 1919 */
1694 if (cmpxchg(&ch->w_local_GP.put, put, put + 1) == put) { 1920 if (cmpxchg(&ch_sn2->w_local_GP.put, put, put + 1) ==
1921 put) {
1695 /* we got the entry referenced by put */ 1922 /* we got the entry referenced by put */
1696 break; 1923 break;
1697 } 1924 }
@@ -1708,7 +1935,7 @@ xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
1708 * GP values as if an IPI was sent by the other side. 1935 * GP values as if an IPI was sent by the other side.
1709 */ 1936 */
1710 if (ret == xpTimeout) 1937 if (ret == xpTimeout)
1711 xpc_IPI_send_local_msgrequest_sn2(ch); 1938 xpc_send_channel_local_msgrequest_sn2(ch);
1712 1939
1713 if (flags & XPC_NOWAIT) 1940 if (flags & XPC_NOWAIT)
1714 return xpNoWait; 1941 return xpNoWait;
@@ -1810,13 +2037,13 @@ xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
1810 2037
1811 /* 2038 /*
1812 * The preceding store of msg->flags must occur before the following 2039 * The preceding store of msg->flags must occur before the following
1813 * load of ch->local_GP->put. 2040 * load of local_GP->put.
1814 */ 2041 */
1815 mb(); 2042 mb();
1816 2043
1817 /* see if the message is next in line to be sent, if so send it */ 2044 /* see if the message is next in line to be sent, if so send it */
1818 2045
1819 put = ch->local_GP->put; 2046 put = ch->sn.sn2.local_GP->put;
1820 if (put == msg_number) 2047 if (put == msg_number)
1821 xpc_send_msgs_sn2(ch, put); 2048 xpc_send_msgs_sn2(ch, put);
1822 2049
@@ -1833,6 +2060,7 @@ out_1:
1833static void 2060static void
1834xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags) 2061xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
1835{ 2062{
2063 struct xpc_channel_sn2 *ch_sn2 = &ch->sn.sn2;
1836 struct xpc_msg *msg; 2064 struct xpc_msg *msg;
1837 s64 get = initial_get + 1; 2065 s64 get = initial_get + 1;
1838 int send_IPI = 0; 2066 int send_IPI = 0;
@@ -1840,7 +2068,7 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
1840 while (1) { 2068 while (1) {
1841 2069
1842 while (1) { 2070 while (1) {
1843 if (get == ch->w_local_GP.get) 2071 if (get == ch_sn2->w_local_GP.get)
1844 break; 2072 break;
1845 2073
1846 msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + 2074 msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
@@ -1859,10 +2087,10 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
1859 break; 2087 break;
1860 } 2088 }
1861 2089
1862 if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) != 2090 if (cmpxchg_rel(&ch_sn2->local_GP->get, initial_get, get) !=
1863 initial_get) { 2091 initial_get) {
1864 /* someone else beat us to it */ 2092 /* someone else beat us to it */
1865 DBUG_ON(ch->local_GP->get <= initial_get); 2093 DBUG_ON(ch_sn2->local_GP->get <= initial_get);
1866 break; 2094 break;
1867 } 2095 }
1868 2096
@@ -1882,7 +2110,7 @@ xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
1882 } 2110 }
1883 2111
1884 if (send_IPI) 2112 if (send_IPI)
1885 xpc_IPI_send_msgrequest_sn2(ch); 2113 xpc_send_channel_msgrequest_sn2(ch);
1886} 2114}
1887 2115
1888static void 2116static void
@@ -1902,7 +2130,7 @@ xpc_received_msg_sn2(struct xpc_channel *ch, struct xpc_msg *msg)
1902 2130
1903 /* 2131 /*
1904 * The preceding store of msg->flags must occur before the following 2132 * The preceding store of msg->flags must occur before the following
1905 * load of ch->local_GP->get. 2133 * load of local_GP->get.
1906 */ 2134 */
1907 mb(); 2135 mb();
1908 2136
@@ -1910,7 +2138,7 @@ xpc_received_msg_sn2(struct xpc_channel *ch, struct xpc_msg *msg)
1910 * See if this message is next in line to be acknowledged as having 2138 * See if this message is next in line to be acknowledged as having
1911 * been delivered. 2139 * been delivered.
1912 */ 2140 */
1913 get = ch->local_GP->get; 2141 get = ch->sn.sn2.local_GP->get;
1914 if (get == msg_number) 2142 if (get == msg_number)
1915 xpc_acknowledge_msgs_sn2(ch, get, msg->flags); 2143 xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
1916} 2144}
@@ -1928,36 +2156,35 @@ xpc_init_sn2(void)
1928 xpc_heartbeat_exit = xpc_heartbeat_exit_sn2; 2156 xpc_heartbeat_exit = xpc_heartbeat_exit_sn2;
1929 xpc_check_remote_hb = xpc_check_remote_hb_sn2; 2157 xpc_check_remote_hb = xpc_check_remote_hb_sn2;
1930 2158
1931 xpc_initiate_partition_activation = 2159 xpc_request_partition_activation = xpc_request_partition_activation_sn2;
1932 xpc_initiate_partition_activation_sn2; 2160 xpc_request_partition_reactivation =
2161 xpc_request_partition_reactivation_sn2;
2162 xpc_request_partition_deactivation =
2163 xpc_request_partition_deactivation_sn2;
2164 xpc_cancel_partition_deactivation_request =
2165 xpc_cancel_partition_deactivation_request_sn2;
2166
1933 xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2; 2167 xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2;
1934 xpc_setup_infrastructure = xpc_setup_infrastructure_sn2; 2168 xpc_setup_infrastructure = xpc_setup_infrastructure_sn2;
1935 xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2; 2169 xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2;
1936 xpc_make_first_contact = xpc_make_first_contact_sn2; 2170 xpc_make_first_contact = xpc_make_first_contact_sn2;
1937 xpc_get_IPI_flags = xpc_get_IPI_flags_sn2; 2171 xpc_get_IPI_flags = xpc_get_IPI_flags_sn2;
2172 xpc_notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_sn2;
2173 xpc_process_msg_IPI = xpc_process_msg_IPI_sn2;
2174 xpc_n_of_deliverable_msgs = xpc_n_of_deliverable_msgs_sn2;
1938 xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2; 2175 xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2;
1939 2176
1940 xpc_mark_partition_engaged = xpc_mark_partition_engaged_sn2; 2177 xpc_indicate_partition_engaged = xpc_indicate_partition_engaged_sn2;
1941 xpc_mark_partition_disengaged = xpc_mark_partition_disengaged_sn2;
1942 xpc_request_partition_disengage = xpc_request_partition_disengage_sn2;
1943 xpc_cancel_partition_disengage_request =
1944 xpc_cancel_partition_disengage_request_sn2;
1945 xpc_partition_engaged = xpc_partition_engaged_sn2; 2178 xpc_partition_engaged = xpc_partition_engaged_sn2;
1946 xpc_partition_disengage_requested = 2179 xpc_any_partition_engaged = xpc_any_partition_engaged_sn2;
1947 xpc_partition_disengage_requested_sn2; 2180 xpc_indicate_partition_disengaged =
1948 xpc_clear_partition_engaged = xpc_clear_partition_engaged_sn2; 2181 xpc_indicate_partition_disengaged_sn2;
1949 xpc_clear_partition_disengage_request = 2182 xpc_assume_partition_disengaged = xpc_assume_partition_disengaged_sn2;
1950 xpc_clear_partition_disengage_request_sn2; 2183
1951 2184 xpc_send_channel_closerequest = xpc_send_channel_closerequest_sn2;
1952 xpc_IPI_send_local_activate = xpc_IPI_send_local_activate_sn2; 2185 xpc_send_channel_closereply = xpc_send_channel_closereply_sn2;
1953 xpc_IPI_send_activated = xpc_IPI_send_activated_sn2; 2186 xpc_send_channel_openrequest = xpc_send_channel_openrequest_sn2;
1954 xpc_IPI_send_local_reactivate = xpc_IPI_send_local_reactivate_sn2; 2187 xpc_send_channel_openreply = xpc_send_channel_openreply_sn2;
1955 xpc_IPI_send_disengage = xpc_IPI_send_disengage_sn2;
1956
1957 xpc_IPI_send_closerequest = xpc_IPI_send_closerequest_sn2;
1958 xpc_IPI_send_closereply = xpc_IPI_send_closereply_sn2;
1959 xpc_IPI_send_openrequest = xpc_IPI_send_openrequest_sn2;
1960 xpc_IPI_send_openreply = xpc_IPI_send_openreply_sn2;
1961 2188
1962 xpc_send_msg = xpc_send_msg_sn2; 2189 xpc_send_msg = xpc_send_msg_sn2;
1963 xpc_received_msg = xpc_received_msg_sn2; 2190 xpc_received_msg = xpc_received_msg_sn2;