sgi-xp: isolate activate IRQ's hardware specific components
[linux-2.6] / drivers / misc / sgi-xp / xpc_sn2.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (c) 2008 Silicon Graphics, Inc.  All Rights Reserved.
7  */
8
9 /*
10  * Cross Partition Communication (XPC) sn2-based functions.
11  *
12  *     Architecture specific implementation of common functions.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/delay.h>
18 #include <asm/uncached.h>
19 #include <asm/sn/sn_sal.h>
20 #include "xpc.h"
21
22 static struct xpc_vars_sn2 *xpc_vars;   /* >>> Add _sn2 suffix? */
23 static struct xpc_vars_part_sn2 *xpc_vars_part; /* >>> Add _sn2 suffix? */
24
25 /* SH_IPI_ACCESS shub register value on startup */
26 static u64 xpc_sh1_IPI_access;
27 static u64 xpc_sh2_IPI_access0;
28 static u64 xpc_sh2_IPI_access1;
29 static u64 xpc_sh2_IPI_access2;
30 static u64 xpc_sh2_IPI_access3;
31
32 /*
33  * Change protections to allow IPI operations.
34  */
35 static void
36 xpc_allow_IPI_ops_sn2(void)
37 {
38         int node;
39         int nasid;
40
41         /* >>> The following should get moved into SAL. */
42         if (is_shub2()) {
43                 xpc_sh2_IPI_access0 =
44                     (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS0));
45                 xpc_sh2_IPI_access1 =
46                     (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS1));
47                 xpc_sh2_IPI_access2 =
48                     (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS2));
49                 xpc_sh2_IPI_access3 =
50                     (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH2_IPI_ACCESS3));
51
52                 for_each_online_node(node) {
53                         nasid = cnodeid_to_nasid(node);
54                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
55                               -1UL);
56                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
57                               -1UL);
58                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
59                               -1UL);
60                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
61                               -1UL);
62                 }
63         } else {
64                 xpc_sh1_IPI_access =
65                     (u64)HUB_L((u64 *)LOCAL_MMR_ADDR(SH1_IPI_ACCESS));
66
67                 for_each_online_node(node) {
68                         nasid = cnodeid_to_nasid(node);
69                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
70                               -1UL);
71                 }
72         }
73 }
74
75 /*
76  * Restrict protections to disallow IPI operations.
77  */
78 static void
79 xpc_disallow_IPI_ops_sn2(void)
80 {
81         int node;
82         int nasid;
83
84         /* >>> The following should get moved into SAL. */
85         if (is_shub2()) {
86                 for_each_online_node(node) {
87                         nasid = cnodeid_to_nasid(node);
88                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS0),
89                               xpc_sh2_IPI_access0);
90                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS1),
91                               xpc_sh2_IPI_access1);
92                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS2),
93                               xpc_sh2_IPI_access2);
94                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH2_IPI_ACCESS3),
95                               xpc_sh2_IPI_access3);
96                 }
97         } else {
98                 for_each_online_node(node) {
99                         nasid = cnodeid_to_nasid(node);
100                         HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid, SH1_IPI_ACCESS),
101                               xpc_sh1_IPI_access);
102                 }
103         }
104 }
105
106 /*
107  * The following set of macros and functions are used for the sending and
108  * receiving of IPIs (also known as IRQs). There are two flavors of IPIs,
109  * one that is associated with partition activity (SGI_XPC_ACTIVATE) and
110  * the other that is associated with channel activity (SGI_XPC_NOTIFY).
111  */
112
113 static u64
114 xpc_IPI_receive_sn2(AMO_t *amo)
115 {
116         return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR);
117 }
118
119 static enum xp_retval
120 xpc_IPI_send_sn2(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector)
121 {
122         int ret = 0;
123         unsigned long irq_flags;
124
125         local_irq_save(irq_flags);
126
127         FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR, flag);
128         sn_send_IPI_phys(nasid, phys_cpuid, vector, 0);
129
130         /*
131          * We must always use the nofault function regardless of whether we
132          * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
133          * didn't, we'd never know that the other partition is down and would
134          * keep sending IPIs and AMOs to it until the heartbeat times out.
135          */
136         ret = xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->variable),
137                                                      xp_nofault_PIOR_target));
138
139         local_irq_restore(irq_flags);
140
141         return ((ret == 0) ? xpSuccess : xpPioReadError);
142 }
143
144 static AMO_t *
145 xpc_IPI_init_sn2(int index)
146 {
147         AMO_t *amo = xpc_vars->amos_page + index;
148
149         (void)xpc_IPI_receive_sn2(amo); /* clear AMO variable */
150         return amo;
151 }
152
153 /*
154  * IPIs associated with SGI_XPC_ACTIVATE IRQ.
155  */
156
157 /*
158  * Notify the heartbeat check thread that an activate IRQ has been received.
159  */
160 static irqreturn_t
161 xpc_handle_activate_IRQ_sn2(int irq, void *dev_id)
162 {
163         atomic_inc(&xpc_activate_IRQ_rcvd);
164         wake_up_interruptible(&xpc_activate_IRQ_wq);
165         return IRQ_HANDLED;
166 }
167
168 /*
169  * Flag the appropriate AMO variable and send an IPI to the specified node.
170  */
171 static void
172 xpc_activate_IRQ_send_sn2(u64 amos_page_pa, int from_nasid, int to_nasid,
173                       int to_phys_cpuid)
174 {
175         int w_index = XPC_NASID_W_INDEX(from_nasid);
176         int b_index = XPC_NASID_B_INDEX(from_nasid);
177         AMO_t *amos = (AMO_t *)__va(amos_page_pa +
178                                     (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
179
180         (void)xpc_IPI_send_sn2(&amos[w_index], (1UL << b_index), to_nasid,
181                                to_phys_cpuid, SGI_XPC_ACTIVATE);
182 }
183
184 static void
185 xpc_activate_IRQ_send_local_sn2(int from_nasid)
186 {
187         int w_index = XPC_NASID_W_INDEX(from_nasid);
188         int b_index = XPC_NASID_B_INDEX(from_nasid);
189         AMO_t *amos = (AMO_t *)__va(xpc_vars->amos_page_pa +
190                                     (XPC_ACTIVATE_IRQ_AMOS * sizeof(AMO_t)));
191
192         /* fake the sending and receipt of an activate IRQ from remote nasid */
193         FETCHOP_STORE_OP(TO_AMO((u64)&amos[w_index].variable), FETCHOP_OR,
194                          (1UL << b_index));
195         atomic_inc(&xpc_activate_IRQ_rcvd);
196         wake_up_interruptible(&xpc_activate_IRQ_wq);
197 }
198
199 static void
200 xpc_IPI_send_local_activate_sn2(int from_nasid)
201 {
202         xpc_activate_IRQ_send_local_sn2(from_nasid);
203 }
204
205 static void
206 xpc_IPI_send_activated_sn2(struct xpc_partition *part)
207 {
208         xpc_activate_IRQ_send_sn2(part->remote_amos_page_pa,
209                                   cnodeid_to_nasid(0), part->remote_act_nasid,
210                                   part->remote_act_phys_cpuid);
211 }
212
213 static void
214 xpc_IPI_send_local_reactivate_sn2(int from_nasid)
215 {
216         xpc_activate_IRQ_send_local_sn2(from_nasid);
217 }
218
219 static void
220 xpc_IPI_send_disengage_sn2(struct xpc_partition *part)
221 {
222         xpc_activate_IRQ_send_sn2(part->remote_amos_page_pa,
223                                   cnodeid_to_nasid(0), part->remote_act_nasid,
224                                   part->remote_act_phys_cpuid);
225 }
226
227 /*
228  * IPIs associated with SGI_XPC_NOTIFY IRQ.
229  */
230
231 /*
232  * Send an IPI to the remote partition that is associated with the
233  * specified channel.
234  */
235 static void
236 xpc_notify_IRQ_send_sn2(struct xpc_channel *ch, u8 ipi_flag,
237                         char *ipi_flag_string, unsigned long *irq_flags)
238 {
239         struct xpc_partition *part = &xpc_partitions[ch->partid];
240         enum xp_retval ret;
241
242         if (likely(part->act_state != XPC_P_DEACTIVATING)) {
243                 ret = xpc_IPI_send_sn2(part->remote_IPI_amo_va,
244                                        (u64)ipi_flag << (ch->number * 8),
245                                        part->remote_IPI_nasid,
246                                        part->remote_IPI_phys_cpuid,
247                                        SGI_XPC_NOTIFY);
248                 dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n",
249                         ipi_flag_string, ch->partid, ch->number, ret);
250                 if (unlikely(ret != xpSuccess)) {
251                         if (irq_flags != NULL)
252                                 spin_unlock_irqrestore(&ch->lock, *irq_flags);
253                         XPC_DEACTIVATE_PARTITION(part, ret);
254                         if (irq_flags != NULL)
255                                 spin_lock_irqsave(&ch->lock, *irq_flags);
256                 }
257         }
258 }
259
260 #define XPC_NOTIFY_IRQ_SEND_SN2(_ch, _ipi_f, _irq_f) \
261                 xpc_notify_IRQ_send_sn2(_ch, _ipi_f, #_ipi_f, _irq_f)
262
263 /*
264  * 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
266  * by xpc_dropped_IPI_check().
267  */
268 static void
269 xpc_notify_IRQ_send_local_sn2(struct xpc_channel *ch, u8 ipi_flag,
270                               char *ipi_flag_string)
271 {
272         struct xpc_partition *part = &xpc_partitions[ch->partid];
273
274         FETCHOP_STORE_OP(TO_AMO((u64)&part->local_IPI_amo_va->variable),
275                          FETCHOP_OR, ((u64)ipi_flag << (ch->number * 8)));
276         dev_dbg(xpc_chan, "%s sent local from partid=%d, channel=%d\n",
277                 ipi_flag_string, ch->partid, ch->number);
278 }
279
280 #define XPC_NOTIFY_IRQ_SEND_LOCAL_SN2(_ch, _ipi_f) \
281                 xpc_notify_IRQ_send_local_sn2(_ch, _ipi_f, #_ipi_f)
282
283 static void
284 xpc_IPI_send_closerequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
285 {
286         struct xpc_openclose_args *args = ch->local_openclose_args;
287
288         args->reason = ch->reason;
289         XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_CLOSEREQUEST, irq_flags);
290 }
291
292 static void
293 xpc_IPI_send_closereply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
294 {
295         XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_CLOSEREPLY, irq_flags);
296 }
297
298 static void
299 xpc_IPI_send_openrequest_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
300 {
301         struct xpc_openclose_args *args = ch->local_openclose_args;
302
303         args->msg_size = ch->msg_size;
304         args->local_nentries = ch->local_nentries;
305         XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_OPENREQUEST, irq_flags);
306 }
307
308 static void
309 xpc_IPI_send_openreply_sn2(struct xpc_channel *ch, unsigned long *irq_flags)
310 {
311         struct xpc_openclose_args *args = ch->local_openclose_args;
312
313         args->remote_nentries = ch->remote_nentries;
314         args->local_nentries = ch->local_nentries;
315         args->local_msgqueue_pa = __pa(ch->local_msgqueue);
316         XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_OPENREPLY, irq_flags);
317 }
318
319 static void
320 xpc_IPI_send_msgrequest_sn2(struct xpc_channel *ch)
321 {
322         XPC_NOTIFY_IRQ_SEND_SN2(ch, XPC_IPI_MSGREQUEST, NULL);
323 }
324
325 static void
326 xpc_IPI_send_local_msgrequest_sn2(struct xpc_channel *ch)
327 {
328         XPC_NOTIFY_IRQ_SEND_LOCAL_SN2(ch, XPC_IPI_MSGREQUEST);
329 }
330
331 /*
332  * This next set of functions are used to keep track of when a partition is
333  * potentially engaged in accessing memory belonging to another partition.
334  */
335
336 static void
337 xpc_mark_partition_engaged_sn2(struct xpc_partition *part)
338 {
339         unsigned long irq_flags;
340         AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
341                                    (XPC_ENGAGED_PARTITIONS_AMO *
342                                     sizeof(AMO_t)));
343
344         local_irq_save(irq_flags);
345
346         /* set bit corresponding to our partid in remote partition's AMO */
347         FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_OR,
348                          (1UL << sn_partition_id));
349         /*
350          * We must always use the nofault function regardless of whether we
351          * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
352          * didn't, we'd never know that the other partition is down and would
353          * keep sending IPIs and AMOs to it until the heartbeat times out.
354          */
355         (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
356                                                                variable),
357                                                      xp_nofault_PIOR_target));
358
359         local_irq_restore(irq_flags);
360 }
361
362 static void
363 xpc_mark_partition_disengaged_sn2(struct xpc_partition *part)
364 {
365         unsigned long irq_flags;
366         AMO_t *amo = (AMO_t *)__va(part->remote_amos_page_pa +
367                                    (XPC_ENGAGED_PARTITIONS_AMO *
368                                     sizeof(AMO_t)));
369
370         local_irq_save(irq_flags);
371
372         /* clear bit corresponding to our partid in remote partition's AMO */
373         FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
374                          ~(1UL << sn_partition_id));
375         /*
376          * We must always use the nofault function regardless of whether we
377          * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
378          * didn't, we'd never know that the other partition is down and would
379          * keep sending IPIs and AMOs to it until the heartbeat times out.
380          */
381         (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
382                                                                variable),
383                                                      xp_nofault_PIOR_target));
384
385         local_irq_restore(irq_flags);
386 }
387
388 static void
389 xpc_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
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         /*
401          * We must always use the nofault function regardless of whether we
402          * are on a Shub 1.1 system or a Shub 1.2 slice 0xc processor. If we
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          */
406         (void)xp_nofault_PIOR((u64 *)GLOBAL_MMR_ADDR(NASID_GET(&amo->
407                                                                variable),
408                                                      xp_nofault_PIOR_target));
409
410         local_irq_restore(irq_flags);
411 }
412
413 static void
414 xpc_cancel_partition_disengage_request_sn2(struct xpc_partition *part)
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
438 static u64
439 xpc_partition_engaged_sn2(u64 partid_mask)
440 {
441         AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
442
443         /* return our partition's AMO variable ANDed with partid_mask */
444         return (FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_LOAD) &
445                 partid_mask);
446 }
447
448 static u64
449 xpc_partition_disengage_requested_sn2(u64 partid_mask)
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
458 static void
459 xpc_clear_partition_engaged_sn2(u64 partid_mask)
460 {
461         AMO_t *amo = xpc_vars->amos_page + XPC_ENGAGED_PARTITIONS_AMO;
462
463         /* clear bit(s) based on partid_mask in our partition's AMO */
464         FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
465                          ~partid_mask);
466 }
467
468 static void
469 xpc_clear_partition_disengage_request_sn2(u64 partid_mask)
470 {
471         AMO_t *amo = xpc_vars->amos_page + XPC_DISENGAGE_REQUEST_AMO;
472
473         /* clear bit(s) based on partid_mask in our partition's AMO */
474         FETCHOP_STORE_OP(TO_AMO((u64)&amo->variable), FETCHOP_AND,
475                          ~partid_mask);
476 }
477
478 /* original protection values for each node */
479 static u64 xpc_prot_vec_sn2[MAX_NUMNODES];
480
481 /*
482  * Change protections to allow AMO operations on non-Shub 1.1 systems.
483  */
484 static enum xp_retval
485 xpc_allow_AMO_ops_sn2(AMO_t *amos_page)
486 {
487         u64 nasid_array = 0;
488         int ret;
489
490         /*
491          * On SHUB 1.1, we cannot call sn_change_memprotect() since the BIST
492          * collides with memory operations. On those systems we call
493          * xpc_allow_AMO_ops_shub_wars_1_1_sn2() instead.
494          */
495         if (!enable_shub_wars_1_1()) {
496                 ret = sn_change_memprotect(ia64_tpa((u64)amos_page), PAGE_SIZE,
497                                            SN_MEMPROT_ACCESS_CLASS_1,
498                                            &nasid_array);
499                 if (ret != 0)
500                         return xpSalError;
501         }
502         return xpSuccess;
503 }
504
505 /*
506  * Change protections to allow AMO operations on Shub 1.1 systems.
507  */
508 static void
509 xpc_allow_AMO_ops_shub_wars_1_1_sn2(void)
510 {
511         int node;
512         int nasid;
513
514         if (!enable_shub_wars_1_1())
515                 return;
516
517         for_each_online_node(node) {
518                 nasid = cnodeid_to_nasid(node);
519                 /* save current protection values */
520                 xpc_prot_vec_sn2[node] =
521                     (u64)HUB_L((u64 *)GLOBAL_MMR_ADDR(nasid,
522                                                   SH1_MD_DQLP_MMR_DIR_PRIVEC0));
523                 /* open up everything */
524                 HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
525                                              SH1_MD_DQLP_MMR_DIR_PRIVEC0),
526                       -1UL);
527                 HUB_S((u64 *)GLOBAL_MMR_ADDR(nasid,
528                                              SH1_MD_DQRP_MMR_DIR_PRIVEC0),
529                       -1UL);
530         }
531 }
532
533 static enum xp_retval
534 xpc_rsvd_page_init_sn2(struct xpc_rsvd_page *rp)
535 {
536         AMO_t *amos_page;
537         int i;
538         int ret;
539
540         xpc_vars = XPC_RP_VARS(rp);
541
542         rp->sn.vars_pa = __pa(xpc_vars);
543
544         /* vars_part array follows immediately after vars */
545         xpc_vars_part = (struct xpc_vars_part_sn2 *)((u8 *)XPC_RP_VARS(rp) +
546                                                      XPC_RP_VARS_SIZE);
547
548
549         /*
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
552          * so that cross-partition AMOs are allowed.
553          *
554          * The allocated AMO page needs MCA reporting to remain disabled after
555          * XPC has unloaded.  To make this work, we keep a copy of the pointer
556          * to this page (i.e., amos_page) in the struct xpc_vars structure,
557          * which is pointed to by the reserved page, and re-use that saved copy
558          * on subsequent loads of XPC. This AMO page is never freed, and its
559          * memory protections are never restricted.
560          */
561         amos_page = xpc_vars->amos_page;
562         if (amos_page == NULL) {
563                 amos_page = (AMO_t *)TO_AMO(uncached_alloc_page(0, 1));
564                 if (amos_page == NULL) {
565                         dev_err(xpc_part, "can't allocate page of AMOs\n");
566                         return xpNoMemory;
567                 }
568
569                 /*
570                  * Open up AMO-R/W to cpu.  This is done on Shub 1.1 systems
571                  * when xpc_allow_AMO_ops_shub_wars_1_1_sn2() is called.
572                  */
573                 ret = xpc_allow_AMO_ops_sn2(amos_page);
574                 if (ret != xpSuccess) {
575                         dev_err(xpc_part, "can't allow AMO operations\n");
576                         uncached_free_page(__IA64_UNCACHED_OFFSET |
577                                            TO_PHYS((u64)amos_page), 1);
578                         return ret;
579                 }
580         }
581
582         /* clear xpc_vars */
583         memset(xpc_vars, 0, sizeof(struct xpc_vars_sn2));
584
585         xpc_vars->version = XPC_V_VERSION;
586         xpc_vars->act_nasid = cpuid_to_nasid(0);
587         xpc_vars->act_phys_cpuid = cpu_physical_id(0);
588         xpc_vars->vars_part_pa = __pa(xpc_vars_part);
589         xpc_vars->amos_page_pa = ia64_tpa((u64)amos_page);
590         xpc_vars->amos_page = amos_page;        /* save for next load of XPC */
591
592         /* clear xpc_vars_part */
593         memset((u64 *)xpc_vars_part, 0, sizeof(struct xpc_vars_part_sn2) *
594                xp_max_npartitions);
595
596         /* initialize the activate IRQ related AMO variables */
597         for (i = 0; i < xp_nasid_mask_words; i++)
598                 (void)xpc_IPI_init_sn2(XPC_ACTIVATE_IRQ_AMOS + i);
599
600         /* initialize the engaged remote partitions related AMO variables */
601         (void)xpc_IPI_init_sn2(XPC_ENGAGED_PARTITIONS_AMO);
602         (void)xpc_IPI_init_sn2(XPC_DISENGAGE_REQUEST_AMO);
603
604         return xpSuccess;
605 }
606
607 static void
608 xpc_increment_heartbeat_sn2(void)
609 {
610         xpc_vars->heartbeat++;
611 }
612
613 static void
614 xpc_offline_heartbeat_sn2(void)
615 {
616         xpc_increment_heartbeat_sn2();
617         xpc_vars->heartbeat_offline = 1;
618 }
619
620 static void
621 xpc_online_heartbeat_sn2(void)
622 {
623         xpc_increment_heartbeat_sn2();
624         xpc_vars->heartbeat_offline = 0;
625 }
626
627 static void
628 xpc_heartbeat_init_sn2(void)
629 {
630         DBUG_ON(xpc_vars == NULL);
631
632         bitmap_zero(xpc_vars->heartbeating_to_mask, XP_MAX_NPARTITIONS_SN2);
633         xpc_heartbeating_to_mask = &xpc_vars->heartbeating_to_mask[0];
634         xpc_online_heartbeat_sn2();
635 }
636
637 static void
638 xpc_heartbeat_exit_sn2(void)
639 {
640         xpc_offline_heartbeat_sn2();
641 }
642
643 /*
644  * At periodic intervals, scan through all active partitions and ensure
645  * their heartbeat is still active.  If not, the partition is deactivated.
646  */
647 static void
648 xpc_check_remote_hb_sn2(void)
649 {
650         struct xpc_vars_sn2 *remote_vars;
651         struct xpc_partition *part;
652         short partid;
653         enum xp_retval ret;
654
655         remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer;
656
657         for (partid = 0; partid < xp_max_npartitions; partid++) {
658
659                 if (xpc_exiting)
660                         break;
661
662                 if (partid == sn_partition_id)
663                         continue;
664
665                 part = &xpc_partitions[partid];
666
667                 if (part->act_state == XPC_P_INACTIVE ||
668                     part->act_state == XPC_P_DEACTIVATING) {
669                         continue;
670                 }
671
672                 /* pull the remote_hb cache line */
673                 ret = xp_remote_memcpy(remote_vars,
674                                        (void *)part->remote_vars_pa,
675                                        XPC_RP_VARS_SIZE);
676                 if (ret != xpSuccess) {
677                         XPC_DEACTIVATE_PARTITION(part, ret);
678                         continue;
679                 }
680
681                 dev_dbg(xpc_part, "partid = %d, heartbeat = %ld, last_heartbeat"
682                         " = %ld, heartbeat_offline = %ld, HB_mask[0] = 0x%lx\n",
683                         partid, remote_vars->heartbeat, part->last_heartbeat,
684                         remote_vars->heartbeat_offline,
685                         remote_vars->heartbeating_to_mask[0]);
686
687                 if (((remote_vars->heartbeat == part->last_heartbeat) &&
688                      (remote_vars->heartbeat_offline == 0)) ||
689                     !xpc_hb_allowed(sn_partition_id,
690                                     &remote_vars->heartbeating_to_mask)) {
691
692                         XPC_DEACTIVATE_PARTITION(part, xpNoHeartbeat);
693                         continue;
694                 }
695
696                 part->last_heartbeat = remote_vars->heartbeat;
697         }
698 }
699
700 /*
701  * Get a copy of the remote partition's XPC variables from the reserved page.
702  *
703  * remote_vars points to a buffer that is cacheline aligned for BTE copies and
704  * assumed to be of size XPC_RP_VARS_SIZE.
705  */
706 static enum xp_retval
707 xpc_get_remote_vars_sn2(u64 remote_vars_pa, struct xpc_vars_sn2 *remote_vars)
708 {
709         enum xp_retval ret;
710
711         if (remote_vars_pa == 0)
712                 return xpVarsNotSet;
713
714         /* pull over the cross partition variables */
715         ret = xp_remote_memcpy(remote_vars, (void *)remote_vars_pa,
716                                XPC_RP_VARS_SIZE);
717         if (ret != xpSuccess)
718                 return ret;
719
720         if (XPC_VERSION_MAJOR(remote_vars->version) !=
721             XPC_VERSION_MAJOR(XPC_V_VERSION)) {
722                 return xpBadVersion;
723         }
724
725         return xpSuccess;
726 }
727
728 static void
729 xpc_initiate_partition_activation_sn2(struct xpc_rsvd_page *remote_rp,
730                                       u64 remote_rp_pa, int nasid)
731 {
732         xpc_IPI_send_local_activate(nasid);
733 }
734
735 /*
736  * Update the remote partition's info.
737  */
738 static void
739 xpc_update_partition_info_sn2(struct xpc_partition *part, u8 remote_rp_version,
740                               unsigned long *remote_rp_stamp, u64 remote_rp_pa,
741                               u64 remote_vars_pa,
742                               struct xpc_vars_sn2 *remote_vars)
743 {
744         part->remote_rp_version = remote_rp_version;
745         dev_dbg(xpc_part, "  remote_rp_version = 0x%016x\n",
746                 part->remote_rp_version);
747
748         part->remote_rp_stamp = *remote_rp_stamp;
749         dev_dbg(xpc_part, "  remote_rp_stamp = 0x%016lx\n",
750                 part->remote_rp_stamp);
751
752         part->remote_rp_pa = remote_rp_pa;
753         dev_dbg(xpc_part, "  remote_rp_pa = 0x%016lx\n", part->remote_rp_pa);
754
755         part->remote_vars_pa = remote_vars_pa;
756         dev_dbg(xpc_part, "  remote_vars_pa = 0x%016lx\n",
757                 part->remote_vars_pa);
758
759         part->last_heartbeat = remote_vars->heartbeat;
760         dev_dbg(xpc_part, "  last_heartbeat = 0x%016lx\n",
761                 part->last_heartbeat);
762
763         part->remote_vars_part_pa = remote_vars->vars_part_pa;
764         dev_dbg(xpc_part, "  remote_vars_part_pa = 0x%016lx\n",
765                 part->remote_vars_part_pa);
766
767         part->remote_act_nasid = remote_vars->act_nasid;
768         dev_dbg(xpc_part, "  remote_act_nasid = 0x%x\n",
769                 part->remote_act_nasid);
770
771         part->remote_act_phys_cpuid = remote_vars->act_phys_cpuid;
772         dev_dbg(xpc_part, "  remote_act_phys_cpuid = 0x%x\n",
773                 part->remote_act_phys_cpuid);
774
775         part->remote_amos_page_pa = remote_vars->amos_page_pa;
776         dev_dbg(xpc_part, "  remote_amos_page_pa = 0x%lx\n",
777                 part->remote_amos_page_pa);
778
779         part->remote_vars_version = remote_vars->version;
780         dev_dbg(xpc_part, "  remote_vars_version = 0x%x\n",
781                 part->remote_vars_version);
782 }
783
784 /*
785  * Prior code has determined the nasid which generated an IPI.  Inspect
786  * that nasid to determine if its partition needs to be activated or
787  * deactivated.
788  *
789  * A partition is consider "awaiting activation" if our partition
790  * flags indicate it is not active and it has a heartbeat.  A
791  * partition is considered "awaiting deactivation" if our partition
792  * flags indicate it is active but it has no heartbeat or it is not
793  * sending its heartbeat to us.
794  *
795  * To determine the heartbeat, the remote nasid must have a properly
796  * initialized reserved page.
797  */
798 static void
799 xpc_identify_activate_IRQ_req_sn2(int nasid)
800 {
801         struct xpc_rsvd_page *remote_rp;
802         struct xpc_vars_sn2 *remote_vars;
803         u64 remote_rp_pa;
804         u64 remote_vars_pa;
805         int remote_rp_version;
806         int reactivate = 0;
807         unsigned long remote_rp_stamp = 0;
808         short partid;
809         struct xpc_partition *part;
810         enum xp_retval ret;
811
812         /* pull over the reserved page structure */
813
814         remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer;
815
816         ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa);
817         if (ret != xpSuccess) {
818                 dev_warn(xpc_part, "unable to get reserved page from nasid %d, "
819                          "which sent interrupt, reason=%d\n", nasid, ret);
820                 return;
821         }
822
823         remote_vars_pa = remote_rp->sn.vars_pa;
824         remote_rp_version = remote_rp->version;
825         if (XPC_SUPPORTS_RP_STAMP(remote_rp_version))
826                 remote_rp_stamp = remote_rp->stamp;
827
828         partid = remote_rp->SAL_partid;
829         part = &xpc_partitions[partid];
830
831         /* pull over the cross partition variables */
832
833         remote_vars = (struct xpc_vars_sn2 *)xpc_remote_copy_buffer;
834
835         ret = xpc_get_remote_vars_sn2(remote_vars_pa, remote_vars);
836         if (ret != xpSuccess) {
837
838                 dev_warn(xpc_part, "unable to get XPC variables from nasid %d, "
839                          "which sent interrupt, reason=%d\n", nasid, ret);
840
841                 XPC_DEACTIVATE_PARTITION(part, ret);
842                 return;
843         }
844
845         part->activate_IRQ_rcvd++;
846
847         dev_dbg(xpc_part, "partid for nasid %d is %d; IRQs = %d; HB = "
848                 "%ld:0x%lx\n", (int)nasid, (int)partid, part->activate_IRQ_rcvd,
849                 remote_vars->heartbeat, remote_vars->heartbeating_to_mask[0]);
850
851         if (xpc_partition_disengaged(part) &&
852             part->act_state == XPC_P_INACTIVE) {
853
854                 xpc_update_partition_info_sn2(part, remote_rp_version,
855                                               &remote_rp_stamp, remote_rp_pa,
856                                               remote_vars_pa, remote_vars);
857
858                 if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version)) {
859                         if (xpc_partition_disengage_requested(1UL << partid)) {
860                                 /*
861                                  * Other side is waiting on us to disengage,
862                                  * even though we already have.
863                                  */
864                                 return;
865                         }
866
867                 } else {
868                         /* other side doesn't support disengage requests */
869                         xpc_clear_partition_disengage_request(1UL << partid);
870                 }
871
872                 xpc_activate_partition(part);
873                 return;
874         }
875
876         DBUG_ON(part->remote_rp_version == 0);
877         DBUG_ON(part->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
896                 /*
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
901                 xpc_update_partition_info_sn2(part, remote_rp_version,
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
909         DBUG_ON(!XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version));
910
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
922                 xpc_update_partition_info_sn2(part, remote_rp_version,
923                                               &remote_rp_stamp, remote_rp_pa,
924                                               remote_vars_pa, remote_vars);
925                 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         }
949
950         if (part->disengage_request_timeout > 0 &&
951             !xpc_partition_disengaged(part)) {
952                 /* still waiting on other side to disengage from us */
953                 return;
954         }
955
956         if (reactivate) {
957                 part->reactivate_nasid = nasid;
958                 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
959
960         } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) &&
961                    xpc_partition_disengage_requested(1UL << partid)) {
962                 XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown);
963         }
964 }
965
966 /*
967  * Loop through the activation AMO variables and process any bits
968  * which are set.  Each bit indicates a nasid sending a partition
969  * activation or deactivation request.
970  *
971  * Return #of IRQs detected.
972  */
973 int
974 xpc_identify_activate_IRQ_sender_sn2(void)
975 {
976         int word, bit;
977         u64 nasid_mask;
978         u64 nasid;              /* remote nasid */
979         int n_IRQs_detected = 0;
980         AMO_t *act_amos;
981
982         act_amos = xpc_vars->amos_page + XPC_ACTIVATE_IRQ_AMOS;
983
984         /* scan through act AMO variable looking for non-zero entries */
985         for (word = 0; word < xp_nasid_mask_words; word++) {
986
987                 if (xpc_exiting)
988                         break;
989
990                 nasid_mask = xpc_IPI_receive_sn2(&act_amos[word]);
991                 if (nasid_mask == 0) {
992                         /* no IRQs from nasids in this variable */
993                         continue;
994                 }
995
996                 dev_dbg(xpc_part, "AMO[%d] gave back 0x%lx\n", word,
997                         nasid_mask);
998
999                 /*
1000                  * If this nasid has been added to the machine since
1001                  * our partition was reset, this will retain the
1002                  * remote nasid in our reserved pages machine mask.
1003                  * This is used in the event of module reload.
1004                  */
1005                 xpc_mach_nasids[word] |= nasid_mask;
1006
1007                 /* locate the nasid(s) which sent interrupts */
1008
1009                 for (bit = 0; bit < (8 * sizeof(u64)); bit++) {
1010                         if (nasid_mask & (1UL << bit)) {
1011                                 n_IRQs_detected++;
1012                                 nasid = XPC_NASID_FROM_W_B(word, bit);
1013                                 dev_dbg(xpc_part, "interrupt from nasid %ld\n",
1014                                         nasid);
1015                                 xpc_identify_activate_IRQ_req_sn2(nasid);
1016                         }
1017                 }
1018         }
1019         return n_IRQs_detected;
1020 }
1021
1022 static void
1023 xpc_process_activate_IRQ_rcvd_sn2(int n_IRQs_expected)
1024 {
1025         int n_IRQs_detected;
1026
1027         n_IRQs_detected = xpc_identify_activate_IRQ_sender_sn2();
1028         if (n_IRQs_detected < n_IRQs_expected) {
1029                 /* retry once to help avoid missing AMO */
1030                 (void)xpc_identify_activate_IRQ_sender_sn2();
1031         }
1032 }
1033
1034 /*
1035  * Setup the infrastructure necessary to support XPartition Communication
1036  * between the specified remote partition and the local one.
1037  */
1038 static enum xp_retval
1039 xpc_setup_infrastructure_sn2(struct xpc_partition *part)
1040 {
1041         enum xp_retval retval;
1042         int ret;
1043         int cpuid;
1044         int ch_number;
1045         struct xpc_channel *ch;
1046         struct timer_list *timer;
1047         short partid = XPC_PARTID(part);
1048
1049         /*
1050          * Allocate all of the channel structures as a contiguous chunk of
1051          * memory.
1052          */
1053         DBUG_ON(part->channels != NULL);
1054         part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_MAX_NCHANNELS,
1055                                  GFP_KERNEL);
1056         if (part->channels == NULL) {
1057                 dev_err(xpc_chan, "can't get memory for channels\n");
1058                 return xpNoMemory;
1059         }
1060
1061         /* allocate all the required GET/PUT values */
1062
1063         part->local_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
1064                                                         GFP_KERNEL,
1065                                                         &part->local_GPs_base);
1066         if (part->local_GPs == NULL) {
1067                 dev_err(xpc_chan, "can't get memory for local get/put "
1068                         "values\n");
1069                 retval = xpNoMemory;
1070                 goto out_1;
1071         }
1072
1073         part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE,
1074                                                          GFP_KERNEL,
1075                                                          &part->
1076                                                          remote_GPs_base);
1077         if (part->remote_GPs == NULL) {
1078                 dev_err(xpc_chan, "can't get memory for remote get/put "
1079                         "values\n");
1080                 retval = xpNoMemory;
1081                 goto out_2;
1082         }
1083
1084         part->remote_GPs_pa = 0;
1085
1086         /* allocate all the required open and close args */
1087
1088         part->local_openclose_args =
1089             xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
1090                                           &part->local_openclose_args_base);
1091         if (part->local_openclose_args == NULL) {
1092                 dev_err(xpc_chan, "can't get memory for local connect args\n");
1093                 retval = xpNoMemory;
1094                 goto out_3;
1095         }
1096
1097         part->remote_openclose_args =
1098             xpc_kzalloc_cacheline_aligned(XPC_OPENCLOSE_ARGS_SIZE, GFP_KERNEL,
1099                                           &part->remote_openclose_args_base);
1100         if (part->remote_openclose_args == NULL) {
1101                 dev_err(xpc_chan, "can't get memory for remote connect args\n");
1102                 retval = xpNoMemory;
1103                 goto out_4;
1104         }
1105
1106         part->remote_openclose_args_pa = 0;
1107
1108         part->local_IPI_amo_va = xpc_IPI_init_sn2(partid);
1109         part->local_IPI_amo = 0;
1110         spin_lock_init(&part->IPI_lock);
1111
1112         part->remote_IPI_nasid = 0;
1113         part->remote_IPI_phys_cpuid = 0;
1114         part->remote_IPI_amo_va = NULL;
1115
1116         atomic_set(&part->channel_mgr_requests, 1);
1117         init_waitqueue_head(&part->channel_mgr_wq);
1118
1119         sprintf(part->IPI_owner, "xpc%02d", partid);
1120         ret = request_irq(SGI_XPC_NOTIFY, xpc_notify_IRQ_handler, IRQF_SHARED,
1121                           part->IPI_owner, (void *)(u64)partid);
1122         if (ret != 0) {
1123                 dev_err(xpc_chan, "can't register NOTIFY IRQ handler, "
1124                         "errno=%d\n", -ret);
1125                 retval = xpLackOfResources;
1126                 goto out_5;
1127         }
1128
1129         /* Setup a timer to check for dropped IPIs */
1130         timer = &part->dropped_IPI_timer;
1131         init_timer(timer);
1132         timer->function = (void (*)(unsigned long))xpc_dropped_IPI_check;
1133         timer->data = (unsigned long)part;
1134         timer->expires = jiffies + XPC_P_DROPPED_IPI_WAIT_INTERVAL;
1135         add_timer(timer);
1136
1137         part->nchannels = XPC_MAX_NCHANNELS;
1138
1139         atomic_set(&part->nchannels_active, 0);
1140         atomic_set(&part->nchannels_engaged, 0);
1141
1142         for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
1143                 ch = &part->channels[ch_number];
1144
1145                 ch->partid = partid;
1146                 ch->number = ch_number;
1147                 ch->flags = XPC_C_DISCONNECTED;
1148
1149                 ch->local_GP = &part->local_GPs[ch_number];
1150                 ch->local_openclose_args =
1151                     &part->local_openclose_args[ch_number];
1152
1153                 atomic_set(&ch->kthreads_assigned, 0);
1154                 atomic_set(&ch->kthreads_idle, 0);
1155                 atomic_set(&ch->kthreads_active, 0);
1156
1157                 atomic_set(&ch->references, 0);
1158                 atomic_set(&ch->n_to_notify, 0);
1159
1160                 spin_lock_init(&ch->lock);
1161                 mutex_init(&ch->msg_to_pull_mutex);
1162                 init_completion(&ch->wdisconnect_wait);
1163
1164                 atomic_set(&ch->n_on_msg_allocate_wq, 0);
1165                 init_waitqueue_head(&ch->msg_allocate_wq);
1166                 init_waitqueue_head(&ch->idle_wq);
1167         }
1168
1169         /*
1170          * With the setting of the partition setup_state to XPC_P_SETUP, we're
1171          * declaring that this partition is ready to go.
1172          */
1173         part->setup_state = XPC_P_SETUP;
1174
1175         /*
1176          * Setup the per partition specific variables required by the
1177          * remote partition to establish channel connections with us.
1178          *
1179          * The setting of the magic # indicates that these per partition
1180          * specific variables are ready to be used.
1181          */
1182         xpc_vars_part[partid].GPs_pa = __pa(part->local_GPs);
1183         xpc_vars_part[partid].openclose_args_pa =
1184             __pa(part->local_openclose_args);
1185         xpc_vars_part[partid].IPI_amo_pa = __pa(part->local_IPI_amo_va);
1186         cpuid = raw_smp_processor_id(); /* any CPU in this partition will do */
1187         xpc_vars_part[partid].IPI_nasid = cpuid_to_nasid(cpuid);
1188         xpc_vars_part[partid].IPI_phys_cpuid = cpu_physical_id(cpuid);
1189         xpc_vars_part[partid].nchannels = part->nchannels;
1190         xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
1191
1192         return xpSuccess;
1193
1194         /* setup of infrastructure failed */
1195 out_5:
1196         kfree(part->remote_openclose_args_base);
1197         part->remote_openclose_args = NULL;
1198 out_4:
1199         kfree(part->local_openclose_args_base);
1200         part->local_openclose_args = NULL;
1201 out_3:
1202         kfree(part->remote_GPs_base);
1203         part->remote_GPs = NULL;
1204 out_2:
1205         kfree(part->local_GPs_base);
1206         part->local_GPs = NULL;
1207 out_1:
1208         kfree(part->channels);
1209         part->channels = NULL;
1210         return retval;
1211 }
1212
1213 /*
1214  * Teardown the infrastructure necessary to support XPartition Communication
1215  * between the specified remote partition and the local one.
1216  */
1217 static void
1218 xpc_teardown_infrastructure_sn2(struct xpc_partition *part)
1219 {
1220         short partid = XPC_PARTID(part);
1221
1222         /*
1223          * We start off by making this partition inaccessible to local
1224          * processes by marking it as no longer setup. Then we make it
1225          * inaccessible to remote processes by clearing the XPC per partition
1226          * specific variable's magic # (which indicates that these variables
1227          * are no longer valid) and by ignoring all XPC notify IPIs sent to
1228          * this partition.
1229          */
1230
1231         DBUG_ON(atomic_read(&part->nchannels_engaged) != 0);
1232         DBUG_ON(atomic_read(&part->nchannels_active) != 0);
1233         DBUG_ON(part->setup_state != XPC_P_SETUP);
1234         part->setup_state = XPC_P_WTEARDOWN;
1235
1236         xpc_vars_part[partid].magic = 0;
1237
1238         free_irq(SGI_XPC_NOTIFY, (void *)(u64)partid);
1239
1240         /*
1241          * Before proceeding with the teardown we have to wait until all
1242          * existing references cease.
1243          */
1244         wait_event(part->teardown_wq, (atomic_read(&part->references) == 0));
1245
1246         /* now we can begin tearing down the infrastructure */
1247
1248         part->setup_state = XPC_P_TORNDOWN;
1249
1250         /* in case we've still got outstanding timers registered... */
1251         del_timer_sync(&part->dropped_IPI_timer);
1252
1253         kfree(part->remote_openclose_args_base);
1254         part->remote_openclose_args = NULL;
1255         kfree(part->local_openclose_args_base);
1256         part->local_openclose_args = NULL;
1257         kfree(part->remote_GPs_base);
1258         part->remote_GPs = NULL;
1259         kfree(part->local_GPs_base);
1260         part->local_GPs = NULL;
1261         kfree(part->channels);
1262         part->channels = NULL;
1263         part->local_IPI_amo_va = NULL;
1264 }
1265
1266 /*
1267  * Create a wrapper that hides the underlying mechanism for pulling a cacheline
1268  * (or multiple cachelines) from a remote partition.
1269  *
1270  * src must be a cacheline aligned physical address on the remote partition.
1271  * dst must be a cacheline aligned virtual address on this partition.
1272  * cnt must be cacheline sized
1273  */
1274 /* >>> Replace this function by call to xp_remote_memcpy() or bte_copy()? */
1275 static enum xp_retval
1276 xpc_pull_remote_cachelines_sn2(struct xpc_partition *part, void *dst,
1277                                const void *src, size_t cnt)
1278 {
1279         enum xp_retval ret;
1280
1281         DBUG_ON((u64)src != L1_CACHE_ALIGN((u64)src));
1282         DBUG_ON((u64)dst != L1_CACHE_ALIGN((u64)dst));
1283         DBUG_ON(cnt != L1_CACHE_ALIGN(cnt));
1284
1285         if (part->act_state == XPC_P_DEACTIVATING)
1286                 return part->reason;
1287
1288         ret = xp_remote_memcpy(dst, src, cnt);
1289         if (ret != xpSuccess) {
1290                 dev_dbg(xpc_chan, "xp_remote_memcpy() from partition %d failed,"
1291                         " ret=%d\n", XPC_PARTID(part), ret);
1292         }
1293         return ret;
1294 }
1295
1296 /*
1297  * Pull the remote per partition specific variables from the specified
1298  * partition.
1299  */
1300 static enum xp_retval
1301 xpc_pull_remote_vars_part_sn2(struct xpc_partition *part)
1302 {
1303         u8 buffer[L1_CACHE_BYTES * 2];
1304         struct xpc_vars_part_sn2 *pulled_entry_cacheline =
1305             (struct xpc_vars_part_sn2 *)L1_CACHE_ALIGN((u64)buffer);
1306         struct xpc_vars_part_sn2 *pulled_entry;
1307         u64 remote_entry_cacheline_pa, remote_entry_pa;
1308         short partid = XPC_PARTID(part);
1309         enum xp_retval ret;
1310
1311         /* pull the cacheline that contains the variables we're interested in */
1312
1313         DBUG_ON(part->remote_vars_part_pa !=
1314                 L1_CACHE_ALIGN(part->remote_vars_part_pa));
1315         DBUG_ON(sizeof(struct xpc_vars_part_sn2) != L1_CACHE_BYTES / 2);
1316
1317         remote_entry_pa = part->remote_vars_part_pa +
1318             sn_partition_id * sizeof(struct xpc_vars_part_sn2);
1319
1320         remote_entry_cacheline_pa = (remote_entry_pa & ~(L1_CACHE_BYTES - 1));
1321
1322         pulled_entry = (struct xpc_vars_part_sn2 *)((u64)pulled_entry_cacheline
1323                                                     + (remote_entry_pa &
1324                                                     (L1_CACHE_BYTES - 1)));
1325
1326         ret = xpc_pull_remote_cachelines_sn2(part, pulled_entry_cacheline,
1327                                              (void *)remote_entry_cacheline_pa,
1328                                              L1_CACHE_BYTES);
1329         if (ret != xpSuccess) {
1330                 dev_dbg(xpc_chan, "failed to pull XPC vars_part from "
1331                         "partition %d, ret=%d\n", partid, ret);
1332                 return ret;
1333         }
1334
1335         /* see if they've been set up yet */
1336
1337         if (pulled_entry->magic != XPC_VP_MAGIC1 &&
1338             pulled_entry->magic != XPC_VP_MAGIC2) {
1339
1340                 if (pulled_entry->magic != 0) {
1341                         dev_dbg(xpc_chan, "partition %d's XPC vars_part for "
1342                                 "partition %d has bad magic value (=0x%lx)\n",
1343                                 partid, sn_partition_id, pulled_entry->magic);
1344                         return xpBadMagic;
1345                 }
1346
1347                 /* they've not been initialized yet */
1348                 return xpRetry;
1349         }
1350
1351         if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) {
1352
1353                 /* validate the variables */
1354
1355                 if (pulled_entry->GPs_pa == 0 ||
1356                     pulled_entry->openclose_args_pa == 0 ||
1357                     pulled_entry->IPI_amo_pa == 0) {
1358
1359                         dev_err(xpc_chan, "partition %d's XPC vars_part for "
1360                                 "partition %d are not valid\n", partid,
1361                                 sn_partition_id);
1362                         return xpInvalidAddress;
1363                 }
1364
1365                 /* the variables we imported look to be valid */
1366
1367                 part->remote_GPs_pa = pulled_entry->GPs_pa;
1368                 part->remote_openclose_args_pa =
1369                     pulled_entry->openclose_args_pa;
1370                 part->remote_IPI_amo_va =
1371                     (AMO_t *)__va(pulled_entry->IPI_amo_pa);
1372                 part->remote_IPI_nasid = pulled_entry->IPI_nasid;
1373                 part->remote_IPI_phys_cpuid = pulled_entry->IPI_phys_cpuid;
1374
1375                 if (part->nchannels > pulled_entry->nchannels)
1376                         part->nchannels = pulled_entry->nchannels;
1377
1378                 /* let the other side know that we've pulled their variables */
1379
1380                 xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
1381         }
1382
1383         if (pulled_entry->magic == XPC_VP_MAGIC1)
1384                 return xpRetry;
1385
1386         return xpSuccess;
1387 }
1388
1389 /*
1390  * Establish first contact with the remote partititon. This involves pulling
1391  * the XPC per partition variables from the remote partition and waiting for
1392  * the remote partition to pull ours.
1393  */
1394 static enum xp_retval
1395 xpc_make_first_contact_sn2(struct xpc_partition *part)
1396 {
1397         enum xp_retval ret;
1398
1399         /*
1400          * Register the remote partition's AMOs with SAL so it can handle
1401          * and cleanup errors within that address range should the remote
1402          * partition go down. We don't unregister this range because it is
1403          * difficult to tell when outstanding writes to the remote partition
1404          * are finished and thus when it is safe to unregister. This should
1405          * not result in wasted space in the SAL xp_addr_region table because
1406          * we should get the same page for remote_amos_page_pa after module
1407          * reloads and system reboots.
1408          */
1409         if (sn_register_xp_addr_region(part->remote_amos_page_pa,
1410                                        PAGE_SIZE, 1) < 0) {
1411                 dev_warn(xpc_part, "xpc_activating(%d) failed to register "
1412                          "xp_addr region\n", XPC_PARTID(part));
1413
1414                 ret = xpPhysAddrRegFailed;
1415                 XPC_DEACTIVATE_PARTITION(part, ret);
1416                 return ret;
1417         }
1418
1419         xpc_IPI_send_activated(part);
1420
1421         while ((ret = xpc_pull_remote_vars_part_sn2(part)) != xpSuccess) {
1422                 if (ret != xpRetry) {
1423                         XPC_DEACTIVATE_PARTITION(part, ret);
1424                         return ret;
1425                 }
1426
1427                 dev_dbg(xpc_part, "waiting to make first contact with "
1428                         "partition %d\n", XPC_PARTID(part));
1429
1430                 /* wait a 1/4 of a second or so */
1431                 (void)msleep_interruptible(250);
1432
1433                 if (part->act_state == XPC_P_DEACTIVATING)
1434                         return part->reason;
1435         }
1436
1437         return xpSuccess;
1438 }
1439
1440 /*
1441  * Get the IPI flags and pull the openclose args and/or remote GPs as needed.
1442  */
1443 static u64
1444 xpc_get_IPI_flags_sn2(struct xpc_partition *part)
1445 {
1446         unsigned long irq_flags;
1447         u64 IPI_amo;
1448         enum xp_retval ret;
1449
1450         /*
1451          * See if there are any IPI flags to be handled.
1452          */
1453
1454         spin_lock_irqsave(&part->IPI_lock, irq_flags);
1455         IPI_amo = part->local_IPI_amo;
1456         if (IPI_amo != 0)
1457                 part->local_IPI_amo = 0;
1458
1459         spin_unlock_irqrestore(&part->IPI_lock, irq_flags);
1460
1461         if (XPC_ANY_OPENCLOSE_IPI_FLAGS_SET(IPI_amo)) {
1462                 ret = xpc_pull_remote_cachelines_sn2(part,
1463                                                     part->remote_openclose_args,
1464                                                      (void *)part->
1465                                                      remote_openclose_args_pa,
1466                                                      XPC_OPENCLOSE_ARGS_SIZE);
1467                 if (ret != xpSuccess) {
1468                         XPC_DEACTIVATE_PARTITION(part, ret);
1469
1470                         dev_dbg(xpc_chan, "failed to pull openclose args from "
1471                                 "partition %d, ret=%d\n", XPC_PARTID(part),
1472                                 ret);
1473
1474                         /* don't bother processing IPIs anymore */
1475                         IPI_amo = 0;
1476                 }
1477         }
1478
1479         if (XPC_ANY_MSG_IPI_FLAGS_SET(IPI_amo)) {
1480                 ret = xpc_pull_remote_cachelines_sn2(part, part->remote_GPs,
1481                                                     (void *)part->remote_GPs_pa,
1482                                                      XPC_GP_SIZE);
1483                 if (ret != xpSuccess) {
1484                         XPC_DEACTIVATE_PARTITION(part, ret);
1485
1486                         dev_dbg(xpc_chan, "failed to pull GPs from partition "
1487                                 "%d, ret=%d\n", XPC_PARTID(part), ret);
1488
1489                         /* don't bother processing IPIs anymore */
1490                         IPI_amo = 0;
1491                 }
1492         }
1493
1494         return IPI_amo;
1495 }
1496
1497 static struct xpc_msg *
1498 xpc_pull_remote_msg_sn2(struct xpc_channel *ch, s64 get)
1499 {
1500         struct xpc_partition *part = &xpc_partitions[ch->partid];
1501         struct xpc_msg *remote_msg, *msg;
1502         u32 msg_index, nmsgs;
1503         u64 msg_offset;
1504         enum xp_retval ret;
1505
1506         if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) {
1507                 /* we were interrupted by a signal */
1508                 return NULL;
1509         }
1510
1511         while (get >= ch->next_msg_to_pull) {
1512
1513                 /* pull as many messages as are ready and able to be pulled */
1514
1515                 msg_index = ch->next_msg_to_pull % ch->remote_nentries;
1516
1517                 DBUG_ON(ch->next_msg_to_pull >= ch->w_remote_GP.put);
1518                 nmsgs = ch->w_remote_GP.put - ch->next_msg_to_pull;
1519                 if (msg_index + nmsgs > ch->remote_nentries) {
1520                         /* ignore the ones that wrap the msg queue for now */
1521                         nmsgs = ch->remote_nentries - msg_index;
1522                 }
1523
1524                 msg_offset = msg_index * ch->msg_size;
1525                 msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
1526                 remote_msg = (struct xpc_msg *)(ch->remote_msgqueue_pa +
1527                                                 msg_offset);
1528
1529                 ret = xpc_pull_remote_cachelines_sn2(part, msg, remote_msg,
1530                                                      nmsgs * ch->msg_size);
1531                 if (ret != xpSuccess) {
1532
1533                         dev_dbg(xpc_chan, "failed to pull %d msgs starting with"
1534                                 " msg %ld from partition %d, channel=%d, "
1535                                 "ret=%d\n", nmsgs, ch->next_msg_to_pull,
1536                                 ch->partid, ch->number, ret);
1537
1538                         XPC_DEACTIVATE_PARTITION(part, ret);
1539
1540                         mutex_unlock(&ch->msg_to_pull_mutex);
1541                         return NULL;
1542                 }
1543
1544                 ch->next_msg_to_pull += nmsgs;
1545         }
1546
1547         mutex_unlock(&ch->msg_to_pull_mutex);
1548
1549         /* return the message we were looking for */
1550         msg_offset = (get % ch->remote_nentries) * ch->msg_size;
1551         msg = (struct xpc_msg *)((u64)ch->remote_msgqueue + msg_offset);
1552
1553         return msg;
1554 }
1555
1556 /*
1557  * Get a message to be delivered.
1558  */
1559 static struct xpc_msg *
1560 xpc_get_deliverable_msg_sn2(struct xpc_channel *ch)
1561 {
1562         struct xpc_msg *msg = NULL;
1563         s64 get;
1564
1565         do {
1566                 if (ch->flags & XPC_C_DISCONNECTING)
1567                         break;
1568
1569                 get = ch->w_local_GP.get;
1570                 rmb();  /* guarantee that .get loads before .put */
1571                 if (get == ch->w_remote_GP.put)
1572                         break;
1573
1574                 /* There are messages waiting to be pulled and delivered.
1575                  * We need to try to secure one for ourselves. We'll do this
1576                  * by trying to increment w_local_GP.get and hope that no one
1577                  * else beats us to it. If they do, we'll we'll simply have
1578                  * to try again for the next one.
1579                  */
1580
1581                 if (cmpxchg(&ch->w_local_GP.get, get, get + 1) == get) {
1582                         /* we got the entry referenced by get */
1583
1584                         dev_dbg(xpc_chan, "w_local_GP.get changed to %ld, "
1585                                 "partid=%d, channel=%d\n", get + 1,
1586                                 ch->partid, ch->number);
1587
1588                         /* pull the message from the remote partition */
1589
1590                         msg = xpc_pull_remote_msg_sn2(ch, get);
1591
1592                         DBUG_ON(msg != NULL && msg->number != get);
1593                         DBUG_ON(msg != NULL && (msg->flags & XPC_M_DONE));
1594                         DBUG_ON(msg != NULL && !(msg->flags & XPC_M_READY));
1595
1596                         break;
1597                 }
1598
1599         } while (1);
1600
1601         return msg;
1602 }
1603
1604 /*
1605  * Now we actually send the messages that are ready to be sent by advancing
1606  * the local message queue's Put value and then send an IPI to the recipient
1607  * partition.
1608  */
1609 static void
1610 xpc_send_msgs_sn2(struct xpc_channel *ch, s64 initial_put)
1611 {
1612         struct xpc_msg *msg;
1613         s64 put = initial_put + 1;
1614         int send_IPI = 0;
1615
1616         while (1) {
1617
1618                 while (1) {
1619                         if (put == ch->w_local_GP.put)
1620                                 break;
1621
1622                         msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
1623                                                  (put % ch->local_nentries) *
1624                                                  ch->msg_size);
1625
1626                         if (!(msg->flags & XPC_M_READY))
1627                                 break;
1628
1629                         put++;
1630                 }
1631
1632                 if (put == initial_put) {
1633                         /* nothing's changed */
1634                         break;
1635                 }
1636
1637                 if (cmpxchg_rel(&ch->local_GP->put, initial_put, put) !=
1638                     initial_put) {
1639                         /* someone else beat us to it */
1640                         DBUG_ON(ch->local_GP->put < initial_put);
1641                         break;
1642                 }
1643
1644                 /* we just set the new value of local_GP->put */
1645
1646                 dev_dbg(xpc_chan, "local_GP->put changed to %ld, partid=%d, "
1647                         "channel=%d\n", put, ch->partid, ch->number);
1648
1649                 send_IPI = 1;
1650
1651                 /*
1652                  * We need to ensure that the message referenced by
1653                  * local_GP->put is not XPC_M_READY or that local_GP->put
1654                  * equals w_local_GP.put, so we'll go have a look.
1655                  */
1656                 initial_put = put;
1657         }
1658
1659         if (send_IPI)
1660                 xpc_IPI_send_msgrequest_sn2(ch);
1661 }
1662
1663 /*
1664  * Allocate an entry for a message from the message queue associated with the
1665  * specified channel.
1666  */
1667 static enum xp_retval
1668 xpc_allocate_msg_sn2(struct xpc_channel *ch, u32 flags,
1669                      struct xpc_msg **address_of_msg)
1670 {
1671         struct xpc_msg *msg;
1672         enum xp_retval ret;
1673         s64 put;
1674
1675         /*
1676          * Get the next available message entry from the local message queue.
1677          * If none are available, we'll make sure that we grab the latest
1678          * GP values.
1679          */
1680         ret = xpTimeout;
1681
1682         while (1) {
1683
1684                 put = ch->w_local_GP.put;
1685                 rmb();  /* guarantee that .put loads before .get */
1686                 if (put - ch->w_remote_GP.get < ch->local_nentries) {
1687
1688                         /* There are available message entries. We need to try
1689                          * to secure one for ourselves. We'll do this by trying
1690                          * to increment w_local_GP.put as long as someone else
1691                          * doesn't beat us to it. If they do, we'll have to
1692                          * try again.
1693                          */
1694                         if (cmpxchg(&ch->w_local_GP.put, put, put + 1) == put) {
1695                                 /* we got the entry referenced by put */
1696                                 break;
1697                         }
1698                         continue;       /* try again */
1699                 }
1700
1701                 /*
1702                  * There aren't any available msg entries at this time.
1703                  *
1704                  * In waiting for a message entry to become available,
1705                  * we set a timeout in case the other side is not
1706                  * sending completion IPIs. This lets us fake an IPI
1707                  * that will cause the IPI handler to fetch the latest
1708                  * GP values as if an IPI was sent by the other side.
1709                  */
1710                 if (ret == xpTimeout)
1711                         xpc_IPI_send_local_msgrequest_sn2(ch);
1712
1713                 if (flags & XPC_NOWAIT)
1714                         return xpNoWait;
1715
1716                 ret = xpc_allocate_msg_wait(ch);
1717                 if (ret != xpInterrupted && ret != xpTimeout)
1718                         return ret;
1719         }
1720
1721         /* get the message's address and initialize it */
1722         msg = (struct xpc_msg *)((u64)ch->local_msgqueue +
1723                                  (put % ch->local_nentries) * ch->msg_size);
1724
1725         DBUG_ON(msg->flags != 0);
1726         msg->number = put;
1727
1728         dev_dbg(xpc_chan, "w_local_GP.put changed to %ld; msg=0x%p, "
1729                 "msg_number=%ld, partid=%d, channel=%d\n", put + 1,
1730                 (void *)msg, msg->number, ch->partid, ch->number);
1731
1732         *address_of_msg = msg;
1733         return xpSuccess;
1734 }
1735
1736 /*
1737  * Common code that does the actual sending of the message by advancing the
1738  * local message queue's Put value and sends an IPI to the partition the
1739  * message is being sent to.
1740  */
1741 static enum xp_retval
1742 xpc_send_msg_sn2(struct xpc_channel *ch, u32 flags, void *payload,
1743                  u16 payload_size, u8 notify_type, xpc_notify_func func,
1744                  void *key)
1745 {
1746         enum xp_retval ret = xpSuccess;
1747         struct xpc_msg *msg = msg;
1748         struct xpc_notify *notify = notify;
1749         s64 msg_number;
1750         s64 put;
1751
1752         DBUG_ON(notify_type == XPC_N_CALL && func == NULL);
1753
1754         if (XPC_MSG_SIZE(payload_size) > ch->msg_size)
1755                 return xpPayloadTooBig;
1756
1757         xpc_msgqueue_ref(ch);
1758
1759         if (ch->flags & XPC_C_DISCONNECTING) {
1760                 ret = ch->reason;
1761                 goto out_1;
1762         }
1763         if (!(ch->flags & XPC_C_CONNECTED)) {
1764                 ret = xpNotConnected;
1765                 goto out_1;
1766         }
1767
1768         ret = xpc_allocate_msg_sn2(ch, flags, &msg);
1769         if (ret != xpSuccess)
1770                 goto out_1;
1771
1772         msg_number = msg->number;
1773
1774         if (notify_type != 0) {
1775                 /*
1776                  * Tell the remote side to send an ACK interrupt when the
1777                  * message has been delivered.
1778                  */
1779                 msg->flags |= XPC_M_INTERRUPT;
1780
1781                 atomic_inc(&ch->n_to_notify);
1782
1783                 notify = &ch->notify_queue[msg_number % ch->local_nentries];
1784                 notify->func = func;
1785                 notify->key = key;
1786                 notify->type = notify_type;
1787
1788                 /* >>> is a mb() needed here? */
1789
1790                 if (ch->flags & XPC_C_DISCONNECTING) {
1791                         /*
1792                          * An error occurred between our last error check and
1793                          * this one. We will try to clear the type field from
1794                          * the notify entry. If we succeed then
1795                          * xpc_disconnect_channel() didn't already process
1796                          * the notify entry.
1797                          */
1798                         if (cmpxchg(&notify->type, notify_type, 0) ==
1799                             notify_type) {
1800                                 atomic_dec(&ch->n_to_notify);
1801                                 ret = ch->reason;
1802                         }
1803                         goto out_1;
1804                 }
1805         }
1806
1807         memcpy(&msg->payload, payload, payload_size);
1808
1809         msg->flags |= XPC_M_READY;
1810
1811         /*
1812          * The preceding store of msg->flags must occur before the following
1813          * load of ch->local_GP->put.
1814          */
1815         mb();
1816
1817         /* see if the message is next in line to be sent, if so send it */
1818
1819         put = ch->local_GP->put;
1820         if (put == msg_number)
1821                 xpc_send_msgs_sn2(ch, put);
1822
1823 out_1:
1824         xpc_msgqueue_deref(ch);
1825         return ret;
1826 }
1827
1828 /*
1829  * Now we actually acknowledge the messages that have been delivered and ack'd
1830  * by advancing the cached remote message queue's Get value and if requested
1831  * send an IPI to the message sender's partition.
1832  */
1833 static void
1834 xpc_acknowledge_msgs_sn2(struct xpc_channel *ch, s64 initial_get, u8 msg_flags)
1835 {
1836         struct xpc_msg *msg;
1837         s64 get = initial_get + 1;
1838         int send_IPI = 0;
1839
1840         while (1) {
1841
1842                 while (1) {
1843                         if (get == ch->w_local_GP.get)
1844                                 break;
1845
1846                         msg = (struct xpc_msg *)((u64)ch->remote_msgqueue +
1847                                                  (get % ch->remote_nentries) *
1848                                                  ch->msg_size);
1849
1850                         if (!(msg->flags & XPC_M_DONE))
1851                                 break;
1852
1853                         msg_flags |= msg->flags;
1854                         get++;
1855                 }
1856
1857                 if (get == initial_get) {
1858                         /* nothing's changed */
1859                         break;
1860                 }
1861
1862                 if (cmpxchg_rel(&ch->local_GP->get, initial_get, get) !=
1863                     initial_get) {
1864                         /* someone else beat us to it */
1865                         DBUG_ON(ch->local_GP->get <= initial_get);
1866                         break;
1867                 }
1868
1869                 /* we just set the new value of local_GP->get */
1870
1871                 dev_dbg(xpc_chan, "local_GP->get changed to %ld, partid=%d, "
1872                         "channel=%d\n", get, ch->partid, ch->number);
1873
1874                 send_IPI = (msg_flags & XPC_M_INTERRUPT);
1875
1876                 /*
1877                  * We need to ensure that the message referenced by
1878                  * local_GP->get is not XPC_M_DONE or that local_GP->get
1879                  * equals w_local_GP.get, so we'll go have a look.
1880                  */
1881                 initial_get = get;
1882         }
1883
1884         if (send_IPI)
1885                 xpc_IPI_send_msgrequest_sn2(ch);
1886 }
1887
1888 static void
1889 xpc_received_msg_sn2(struct xpc_channel *ch, struct xpc_msg *msg)
1890 {
1891         s64 get;
1892         s64 msg_number = msg->number;
1893
1894         dev_dbg(xpc_chan, "msg=0x%p, msg_number=%ld, partid=%d, channel=%d\n",
1895                 (void *)msg, msg_number, ch->partid, ch->number);
1896
1897         DBUG_ON((((u64)msg - (u64)ch->remote_msgqueue) / ch->msg_size) !=
1898                 msg_number % ch->remote_nentries);
1899         DBUG_ON(msg->flags & XPC_M_DONE);
1900
1901         msg->flags |= XPC_M_DONE;
1902
1903         /*
1904          * The preceding store of msg->flags must occur before the following
1905          * load of ch->local_GP->get.
1906          */
1907         mb();
1908
1909         /*
1910          * See if this message is next in line to be acknowledged as having
1911          * been delivered.
1912          */
1913         get = ch->local_GP->get;
1914         if (get == msg_number)
1915                 xpc_acknowledge_msgs_sn2(ch, get, msg->flags);
1916 }
1917
1918 int
1919 xpc_init_sn2(void)
1920 {
1921         int ret;
1922
1923         xpc_rsvd_page_init = xpc_rsvd_page_init_sn2;
1924         xpc_increment_heartbeat = xpc_increment_heartbeat_sn2;
1925         xpc_offline_heartbeat = xpc_offline_heartbeat_sn2;
1926         xpc_online_heartbeat = xpc_online_heartbeat_sn2;
1927         xpc_heartbeat_init = xpc_heartbeat_init_sn2;
1928         xpc_heartbeat_exit = xpc_heartbeat_exit_sn2;
1929         xpc_check_remote_hb = xpc_check_remote_hb_sn2;
1930
1931         xpc_initiate_partition_activation =
1932             xpc_initiate_partition_activation_sn2;
1933         xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_sn2;
1934         xpc_setup_infrastructure = xpc_setup_infrastructure_sn2;
1935         xpc_teardown_infrastructure = xpc_teardown_infrastructure_sn2;
1936         xpc_make_first_contact = xpc_make_first_contact_sn2;
1937         xpc_get_IPI_flags = xpc_get_IPI_flags_sn2;
1938         xpc_get_deliverable_msg = xpc_get_deliverable_msg_sn2;
1939
1940         xpc_mark_partition_engaged = xpc_mark_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;
1946         xpc_partition_disengage_requested =
1947             xpc_partition_disengage_requested_sn2;
1948         xpc_clear_partition_engaged = xpc_clear_partition_engaged_sn2;
1949         xpc_clear_partition_disengage_request =
1950             xpc_clear_partition_disengage_request_sn2;
1951
1952         xpc_IPI_send_local_activate = xpc_IPI_send_local_activate_sn2;
1953         xpc_IPI_send_activated = xpc_IPI_send_activated_sn2;
1954         xpc_IPI_send_local_reactivate = xpc_IPI_send_local_reactivate_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
1962         xpc_send_msg = xpc_send_msg_sn2;
1963         xpc_received_msg = xpc_received_msg_sn2;
1964
1965         /* open up protections for IPI and [potentially] AMO operations */
1966         xpc_allow_IPI_ops_sn2();
1967         xpc_allow_AMO_ops_shub_wars_1_1_sn2();
1968
1969         /*
1970          * This is safe to do before the xpc_hb_checker thread has started
1971          * because the handler releases a wait queue.  If an interrupt is
1972          * received before the thread is waiting, it will not go to sleep,
1973          * but rather immediately process the interrupt.
1974          */
1975         ret = request_irq(SGI_XPC_ACTIVATE, xpc_handle_activate_IRQ_sn2, 0,
1976                           "xpc hb", NULL);
1977         if (ret != 0) {
1978                 dev_err(xpc_part, "can't register ACTIVATE IRQ handler, "
1979                         "errno=%d\n", -ret);
1980                 xpc_disallow_IPI_ops_sn2();
1981         }
1982         return ret;
1983 }
1984
1985 void
1986 xpc_exit_sn2(void)
1987 {
1988         free_irq(SGI_XPC_ACTIVATE, NULL);
1989         xpc_disallow_IPI_ops_sn2();
1990 }