]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/misc/sgi-xp/xpc_uv.c
x86: uv: update XPC to handle updated BIOS interface
[net-next-2.6.git] / drivers / misc / sgi-xp / xpc_uv.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-2009 Silicon Graphics, Inc.  All Rights Reserved.
7  */
8
9 /*
10  * Cross Partition Communication (XPC) uv-based functions.
11  *
12  *     Architecture specific implementation of common functions.
13  *
14  */
15
16 #include <linux/kernel.h>
17 #include <linux/mm.h>
18 #include <linux/interrupt.h>
19 #include <linux/delay.h>
20 #include <linux/device.h>
21 #include <linux/err.h>
22 #include <asm/uv/uv_hub.h>
23 #if defined CONFIG_X86_64
24 #include <asm/uv/bios.h>
25 #include <asm/uv/uv_irq.h>
26 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
27 #include <asm/sn/intr.h>
28 #include <asm/sn/sn_sal.h>
29 #endif
30 #include "../sgi-gru/gru.h"
31 #include "../sgi-gru/grukservices.h"
32 #include "xpc.h"
33
34 #if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
35 struct uv_IO_APIC_route_entry {
36         __u64   vector          :  8,
37                 delivery_mode   :  3,
38                 dest_mode       :  1,
39                 delivery_status :  1,
40                 polarity        :  1,
41                 __reserved_1    :  1,
42                 trigger         :  1,
43                 mask            :  1,
44                 __reserved_2    : 15,
45                 dest            : 32;
46 };
47 #endif
48
49 static struct xpc_heartbeat_uv *xpc_heartbeat_uv;
50
51 #define XPC_ACTIVATE_MSG_SIZE_UV        (1 * GRU_CACHE_LINE_BYTES)
52 #define XPC_ACTIVATE_MQ_SIZE_UV         (4 * XP_MAX_NPARTITIONS_UV * \
53                                          XPC_ACTIVATE_MSG_SIZE_UV)
54 #define XPC_ACTIVATE_IRQ_NAME           "xpc_activate"
55
56 #define XPC_NOTIFY_MSG_SIZE_UV          (2 * GRU_CACHE_LINE_BYTES)
57 #define XPC_NOTIFY_MQ_SIZE_UV           (4 * XP_MAX_NPARTITIONS_UV * \
58                                          XPC_NOTIFY_MSG_SIZE_UV)
59 #define XPC_NOTIFY_IRQ_NAME             "xpc_notify"
60
61 static struct xpc_gru_mq_uv *xpc_activate_mq_uv;
62 static struct xpc_gru_mq_uv *xpc_notify_mq_uv;
63
64 static int
65 xpc_setup_partitions_uv(void)
66 {
67         short partid;
68         struct xpc_partition_uv *part_uv;
69
70         for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
71                 part_uv = &xpc_partitions[partid].sn.uv;
72
73                 mutex_init(&part_uv->cached_activate_gru_mq_desc_mutex);
74                 spin_lock_init(&part_uv->flags_lock);
75                 part_uv->remote_act_state = XPC_P_AS_INACTIVE;
76         }
77         return 0;
78 }
79
80 static void
81 xpc_teardown_partitions_uv(void)
82 {
83         short partid;
84         struct xpc_partition_uv *part_uv;
85         unsigned long irq_flags;
86
87         for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
88                 part_uv = &xpc_partitions[partid].sn.uv;
89
90                 if (part_uv->cached_activate_gru_mq_desc != NULL) {
91                         mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex);
92                         spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
93                         part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
94                         spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
95                         kfree(part_uv->cached_activate_gru_mq_desc);
96                         part_uv->cached_activate_gru_mq_desc = NULL;
97                         mutex_unlock(&part_uv->
98                                      cached_activate_gru_mq_desc_mutex);
99                 }
100         }
101 }
102
103 static int
104 xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name)
105 {
106         int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
107
108 #if defined CONFIG_X86_64
109         mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset,
110                         UV_AFFINITY_CPU);
111         if (mq->irq < 0) {
112                 dev_err(xpc_part, "uv_setup_irq() returned error=%d\n",
113                         -mq->irq);
114                 return mq->irq;
115         }
116
117         mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset);
118
119 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
120         if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0)
121                 mq->irq = SGI_XPC_ACTIVATE;
122         else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0)
123                 mq->irq = SGI_XPC_NOTIFY;
124         else
125                 return -EINVAL;
126
127         mq->mmr_value = (unsigned long)cpu_physical_id(cpu) << 32 | mq->irq;
128         uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mq->mmr_value);
129 #else
130         #error not a supported configuration
131 #endif
132
133         return 0;
134 }
135
136 static void
137 xpc_release_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq)
138 {
139 #if defined CONFIG_X86_64
140         uv_teardown_irq(mq->irq);
141
142 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
143         int mmr_pnode;
144         unsigned long mmr_value;
145
146         mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
147         mmr_value = 1UL << 16;
148
149         uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mmr_value);
150 #else
151         #error not a supported configuration
152 #endif
153 }
154
155 static int
156 xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq)
157 {
158         int ret;
159
160 #if defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
161         int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
162
163         ret = sn_mq_watchlist_alloc(mmr_pnode, (void *)uv_gpa(mq->address),
164                                     mq->order, &mq->mmr_offset);
165         if (ret < 0) {
166                 dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n",
167                         ret);
168                 return -EBUSY;
169         }
170 #elif defined CONFIG_X86_64
171         ret = uv_bios_mq_watchlist_alloc(uv_gpa(mq->address),
172                                          mq->order, &mq->mmr_offset);
173         if (ret < 0) {
174                 dev_err(xpc_part, "uv_bios_mq_watchlist_alloc() failed, "
175                         "ret=%d\n", ret);
176                 return ret;
177         }
178 #else
179         #error not a supported configuration
180 #endif
181
182         mq->watchlist_num = ret;
183         return 0;
184 }
185
186 static void
187 xpc_gru_mq_watchlist_free_uv(struct xpc_gru_mq_uv *mq)
188 {
189         int ret;
190         int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade);
191
192 #if defined CONFIG_X86_64
193         ret = uv_bios_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
194         BUG_ON(ret != BIOS_STATUS_SUCCESS);
195 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
196         ret = sn_mq_watchlist_free(mmr_pnode, mq->watchlist_num);
197         BUG_ON(ret != SALRET_OK);
198 #else
199         #error not a supported configuration
200 #endif
201 }
202
203 static struct xpc_gru_mq_uv *
204 xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name,
205                      irq_handler_t irq_handler)
206 {
207         enum xp_retval xp_ret;
208         int ret;
209         int nid;
210         int pg_order;
211         struct page *page;
212         struct xpc_gru_mq_uv *mq;
213         struct uv_IO_APIC_route_entry *mmr_value;
214
215         mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL);
216         if (mq == NULL) {
217                 dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
218                         "a xpc_gru_mq_uv structure\n");
219                 ret = -ENOMEM;
220                 goto out_0;
221         }
222
223         mq->gru_mq_desc = kzalloc(sizeof(struct gru_message_queue_desc),
224                                   GFP_KERNEL);
225         if (mq->gru_mq_desc == NULL) {
226                 dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() "
227                         "a gru_message_queue_desc structure\n");
228                 ret = -ENOMEM;
229                 goto out_1;
230         }
231
232         pg_order = get_order(mq_size);
233         mq->order = pg_order + PAGE_SHIFT;
234         mq_size = 1UL << mq->order;
235
236         mq->mmr_blade = uv_cpu_to_blade_id(cpu);
237
238         nid = cpu_to_node(cpu);
239         page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE,
240                                 pg_order);
241         if (page == NULL) {
242                 dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d "
243                         "bytes of memory on nid=%d for GRU mq\n", mq_size, nid);
244                 ret = -ENOMEM;
245                 goto out_2;
246         }
247         mq->address = page_address(page);
248
249         /* enable generation of irq when GRU mq operation occurs to this mq */
250         ret = xpc_gru_mq_watchlist_alloc_uv(mq);
251         if (ret != 0)
252                 goto out_3;
253
254         ret = xpc_get_gru_mq_irq_uv(mq, cpu, irq_name);
255         if (ret != 0)
256                 goto out_4;
257
258         ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL);
259         if (ret != 0) {
260                 dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n",
261                         mq->irq, -ret);
262                 goto out_5;
263         }
264
265         mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value;
266         ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size,
267                                        nid, mmr_value->vector, mmr_value->dest);
268         if (ret != 0) {
269                 dev_err(xpc_part, "gru_create_message_queue() returned "
270                         "error=%d\n", ret);
271                 ret = -EINVAL;
272                 goto out_6;
273         }
274
275         /* allow other partitions to access this GRU mq */
276         xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size);
277         if (xp_ret != xpSuccess) {
278                 ret = -EACCES;
279                 goto out_6;
280         }
281
282         return mq;
283
284         /* something went wrong */
285 out_6:
286         free_irq(mq->irq, NULL);
287 out_5:
288         xpc_release_gru_mq_irq_uv(mq);
289 out_4:
290         xpc_gru_mq_watchlist_free_uv(mq);
291 out_3:
292         free_pages((unsigned long)mq->address, pg_order);
293 out_2:
294         kfree(mq->gru_mq_desc);
295 out_1:
296         kfree(mq);
297 out_0:
298         return ERR_PTR(ret);
299 }
300
301 static void
302 xpc_destroy_gru_mq_uv(struct xpc_gru_mq_uv *mq)
303 {
304         unsigned int mq_size;
305         int pg_order;
306         int ret;
307
308         /* disallow other partitions to access GRU mq */
309         mq_size = 1UL << mq->order;
310         ret = xp_restrict_memprotect(xp_pa(mq->address), mq_size);
311         BUG_ON(ret != xpSuccess);
312
313         /* unregister irq handler and release mq irq/vector mapping */
314         free_irq(mq->irq, NULL);
315         xpc_release_gru_mq_irq_uv(mq);
316
317         /* disable generation of irq when GRU mq op occurs to this mq */
318         xpc_gru_mq_watchlist_free_uv(mq);
319
320         pg_order = mq->order - PAGE_SHIFT;
321         free_pages((unsigned long)mq->address, pg_order);
322
323         kfree(mq);
324 }
325
326 static enum xp_retval
327 xpc_send_gru_msg(struct gru_message_queue_desc *gru_mq_desc, void *msg,
328                  size_t msg_size)
329 {
330         enum xp_retval xp_ret;
331         int ret;
332
333         while (1) {
334                 ret = gru_send_message_gpa(gru_mq_desc, msg, msg_size);
335                 if (ret == MQE_OK) {
336                         xp_ret = xpSuccess;
337                         break;
338                 }
339
340                 if (ret == MQE_QUEUE_FULL) {
341                         dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
342                                 "error=MQE_QUEUE_FULL\n");
343                         /* !!! handle QLimit reached; delay & try again */
344                         /* ??? Do we add a limit to the number of retries? */
345                         (void)msleep_interruptible(10);
346                 } else if (ret == MQE_CONGESTION) {
347                         dev_dbg(xpc_chan, "gru_send_message_gpa() returned "
348                                 "error=MQE_CONGESTION\n");
349                         /* !!! handle LB Overflow; simply try again */
350                         /* ??? Do we add a limit to the number of retries? */
351                 } else {
352                         /* !!! Currently this is MQE_UNEXPECTED_CB_ERR */
353                         dev_err(xpc_chan, "gru_send_message_gpa() returned "
354                                 "error=%d\n", ret);
355                         xp_ret = xpGruSendMqError;
356                         break;
357                 }
358         }
359         return xp_ret;
360 }
361
362 static void
363 xpc_process_activate_IRQ_rcvd_uv(void)
364 {
365         unsigned long irq_flags;
366         short partid;
367         struct xpc_partition *part;
368         u8 act_state_req;
369
370         DBUG_ON(xpc_activate_IRQ_rcvd == 0);
371
372         spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
373         for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
374                 part = &xpc_partitions[partid];
375
376                 if (part->sn.uv.act_state_req == 0)
377                         continue;
378
379                 xpc_activate_IRQ_rcvd--;
380                 BUG_ON(xpc_activate_IRQ_rcvd < 0);
381
382                 act_state_req = part->sn.uv.act_state_req;
383                 part->sn.uv.act_state_req = 0;
384                 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
385
386                 if (act_state_req == XPC_P_ASR_ACTIVATE_UV) {
387                         if (part->act_state == XPC_P_AS_INACTIVE)
388                                 xpc_activate_partition(part);
389                         else if (part->act_state == XPC_P_AS_DEACTIVATING)
390                                 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
391
392                 } else if (act_state_req == XPC_P_ASR_REACTIVATE_UV) {
393                         if (part->act_state == XPC_P_AS_INACTIVE)
394                                 xpc_activate_partition(part);
395                         else
396                                 XPC_DEACTIVATE_PARTITION(part, xpReactivating);
397
398                 } else if (act_state_req == XPC_P_ASR_DEACTIVATE_UV) {
399                         XPC_DEACTIVATE_PARTITION(part, part->sn.uv.reason);
400
401                 } else {
402                         BUG();
403                 }
404
405                 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
406                 if (xpc_activate_IRQ_rcvd == 0)
407                         break;
408         }
409         spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
410
411 }
412
413 static void
414 xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
415                               struct xpc_activate_mq_msghdr_uv *msg_hdr,
416                               int *wakeup_hb_checker)
417 {
418         unsigned long irq_flags;
419         struct xpc_partition_uv *part_uv = &part->sn.uv;
420         struct xpc_openclose_args *args;
421
422         part_uv->remote_act_state = msg_hdr->act_state;
423
424         switch (msg_hdr->type) {
425         case XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV:
426                 /* syncing of remote_act_state was just done above */
427                 break;
428
429         case XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV: {
430                 struct xpc_activate_mq_msg_activate_req_uv *msg;
431
432                 /*
433                  * ??? Do we deal here with ts_jiffies being different
434                  * ??? if act_state != XPC_P_AS_INACTIVE instead of
435                  * ??? below?
436                  */
437                 msg = container_of(msg_hdr, struct
438                                    xpc_activate_mq_msg_activate_req_uv, hdr);
439
440                 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
441                 if (part_uv->act_state_req == 0)
442                         xpc_activate_IRQ_rcvd++;
443                 part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV;
444                 part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */
445                 part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies;
446                 part_uv->heartbeat_gpa = msg->heartbeat_gpa;
447
448                 if (msg->activate_gru_mq_desc_gpa !=
449                     part_uv->activate_gru_mq_desc_gpa) {
450                         spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
451                         part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
452                         spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
453                         part_uv->activate_gru_mq_desc_gpa =
454                             msg->activate_gru_mq_desc_gpa;
455                 }
456                 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
457
458                 (*wakeup_hb_checker)++;
459                 break;
460         }
461         case XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV: {
462                 struct xpc_activate_mq_msg_deactivate_req_uv *msg;
463
464                 msg = container_of(msg_hdr, struct
465                                    xpc_activate_mq_msg_deactivate_req_uv, hdr);
466
467                 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
468                 if (part_uv->act_state_req == 0)
469                         xpc_activate_IRQ_rcvd++;
470                 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
471                 part_uv->reason = msg->reason;
472                 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
473
474                 (*wakeup_hb_checker)++;
475                 return;
476         }
477         case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
478                 struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
479
480                 msg = container_of(msg_hdr, struct
481                                    xpc_activate_mq_msg_chctl_closerequest_uv,
482                                    hdr);
483                 args = &part->remote_openclose_args[msg->ch_number];
484                 args->reason = msg->reason;
485
486                 spin_lock_irqsave(&part->chctl_lock, irq_flags);
487                 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREQUEST;
488                 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
489
490                 xpc_wakeup_channel_mgr(part);
491                 break;
492         }
493         case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
494                 struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
495
496                 msg = container_of(msg_hdr, struct
497                                    xpc_activate_mq_msg_chctl_closereply_uv,
498                                    hdr);
499
500                 spin_lock_irqsave(&part->chctl_lock, irq_flags);
501                 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_CLOSEREPLY;
502                 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
503
504                 xpc_wakeup_channel_mgr(part);
505                 break;
506         }
507         case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
508                 struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
509
510                 msg = container_of(msg_hdr, struct
511                                    xpc_activate_mq_msg_chctl_openrequest_uv,
512                                    hdr);
513                 args = &part->remote_openclose_args[msg->ch_number];
514                 args->entry_size = msg->entry_size;
515                 args->local_nentries = msg->local_nentries;
516
517                 spin_lock_irqsave(&part->chctl_lock, irq_flags);
518                 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREQUEST;
519                 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
520
521                 xpc_wakeup_channel_mgr(part);
522                 break;
523         }
524         case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
525                 struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
526
527                 msg = container_of(msg_hdr, struct
528                                    xpc_activate_mq_msg_chctl_openreply_uv, hdr);
529                 args = &part->remote_openclose_args[msg->ch_number];
530                 args->remote_nentries = msg->remote_nentries;
531                 args->local_nentries = msg->local_nentries;
532                 args->local_msgqueue_pa = msg->notify_gru_mq_desc_gpa;
533
534                 spin_lock_irqsave(&part->chctl_lock, irq_flags);
535                 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY;
536                 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
537
538                 xpc_wakeup_channel_mgr(part);
539                 break;
540         }
541         case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
542                 struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
543
544                 msg = container_of(msg_hdr, struct
545                                 xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
546                 spin_lock_irqsave(&part->chctl_lock, irq_flags);
547                 part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENCOMPLETE;
548                 spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
549
550                 xpc_wakeup_channel_mgr(part);
551         }
552         case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV:
553                 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
554                 part_uv->flags |= XPC_P_ENGAGED_UV;
555                 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
556                 break;
557
558         case XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV:
559                 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
560                 part_uv->flags &= ~XPC_P_ENGAGED_UV;
561                 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
562                 break;
563
564         default:
565                 dev_err(xpc_part, "received unknown activate_mq msg type=%d "
566                         "from partition=%d\n", msg_hdr->type, XPC_PARTID(part));
567
568                 /* get hb checker to deactivate from the remote partition */
569                 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
570                 if (part_uv->act_state_req == 0)
571                         xpc_activate_IRQ_rcvd++;
572                 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
573                 part_uv->reason = xpBadMsgType;
574                 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
575
576                 (*wakeup_hb_checker)++;
577                 return;
578         }
579
580         if (msg_hdr->rp_ts_jiffies != part->remote_rp_ts_jiffies &&
581             part->remote_rp_ts_jiffies != 0) {
582                 /*
583                  * ??? Does what we do here need to be sensitive to
584                  * ??? act_state or remote_act_state?
585                  */
586                 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
587                 if (part_uv->act_state_req == 0)
588                         xpc_activate_IRQ_rcvd++;
589                 part_uv->act_state_req = XPC_P_ASR_REACTIVATE_UV;
590                 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
591
592                 (*wakeup_hb_checker)++;
593         }
594 }
595
596 static irqreturn_t
597 xpc_handle_activate_IRQ_uv(int irq, void *dev_id)
598 {
599         struct xpc_activate_mq_msghdr_uv *msg_hdr;
600         short partid;
601         struct xpc_partition *part;
602         int wakeup_hb_checker = 0;
603         int part_referenced;
604
605         while (1) {
606                 msg_hdr = gru_get_next_message(xpc_activate_mq_uv->gru_mq_desc);
607                 if (msg_hdr == NULL)
608                         break;
609
610                 partid = msg_hdr->partid;
611                 if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
612                         dev_err(xpc_part, "xpc_handle_activate_IRQ_uv() "
613                                 "received invalid partid=0x%x in message\n",
614                                 partid);
615                 } else {
616                         part = &xpc_partitions[partid];
617
618                         part_referenced = xpc_part_ref(part);
619                         xpc_handle_activate_mq_msg_uv(part, msg_hdr,
620                                                       &wakeup_hb_checker);
621                         if (part_referenced)
622                                 xpc_part_deref(part);
623                 }
624
625                 gru_free_message(xpc_activate_mq_uv->gru_mq_desc, msg_hdr);
626         }
627
628         if (wakeup_hb_checker)
629                 wake_up_interruptible(&xpc_activate_IRQ_wq);
630
631         return IRQ_HANDLED;
632 }
633
634 static enum xp_retval
635 xpc_cache_remote_gru_mq_desc_uv(struct gru_message_queue_desc *gru_mq_desc,
636                                 unsigned long gru_mq_desc_gpa)
637 {
638         enum xp_retval ret;
639
640         ret = xp_remote_memcpy(uv_gpa(gru_mq_desc), gru_mq_desc_gpa,
641                                sizeof(struct gru_message_queue_desc));
642         if (ret == xpSuccess)
643                 gru_mq_desc->mq = NULL;
644
645         return ret;
646 }
647
648 static enum xp_retval
649 xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size,
650                          int msg_type)
651 {
652         struct xpc_activate_mq_msghdr_uv *msg_hdr = msg;
653         struct xpc_partition_uv *part_uv = &part->sn.uv;
654         struct gru_message_queue_desc *gru_mq_desc;
655         unsigned long irq_flags;
656         enum xp_retval ret;
657
658         DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV);
659
660         msg_hdr->type = msg_type;
661         msg_hdr->partid = xp_partition_id;
662         msg_hdr->act_state = part->act_state;
663         msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies;
664
665         mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex);
666 again:
667         if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) {
668                 gru_mq_desc = part_uv->cached_activate_gru_mq_desc;
669                 if (gru_mq_desc == NULL) {
670                         gru_mq_desc = kmalloc(sizeof(struct
671                                               gru_message_queue_desc),
672                                               GFP_KERNEL);
673                         if (gru_mq_desc == NULL) {
674                                 ret = xpNoMemory;
675                                 goto done;
676                         }
677                         part_uv->cached_activate_gru_mq_desc = gru_mq_desc;
678                 }
679
680                 ret = xpc_cache_remote_gru_mq_desc_uv(gru_mq_desc,
681                                                       part_uv->
682                                                       activate_gru_mq_desc_gpa);
683                 if (ret != xpSuccess)
684                         goto done;
685
686                 spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
687                 part_uv->flags |= XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV;
688                 spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
689         }
690
691         /* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */
692         ret = xpc_send_gru_msg(part_uv->cached_activate_gru_mq_desc, msg,
693                                msg_size);
694         if (ret != xpSuccess) {
695                 smp_rmb();      /* ensure a fresh copy of part_uv->flags */
696                 if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV))
697                         goto again;
698         }
699 done:
700         mutex_unlock(&part_uv->cached_activate_gru_mq_desc_mutex);
701         return ret;
702 }
703
704 static void
705 xpc_send_activate_IRQ_part_uv(struct xpc_partition *part, void *msg,
706                               size_t msg_size, int msg_type)
707 {
708         enum xp_retval ret;
709
710         ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
711         if (unlikely(ret != xpSuccess))
712                 XPC_DEACTIVATE_PARTITION(part, ret);
713 }
714
715 static void
716 xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags,
717                          void *msg, size_t msg_size, int msg_type)
718 {
719         struct xpc_partition *part = &xpc_partitions[ch->partid];
720         enum xp_retval ret;
721
722         ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type);
723         if (unlikely(ret != xpSuccess)) {
724                 if (irq_flags != NULL)
725                         spin_unlock_irqrestore(&ch->lock, *irq_flags);
726
727                 XPC_DEACTIVATE_PARTITION(part, ret);
728
729                 if (irq_flags != NULL)
730                         spin_lock_irqsave(&ch->lock, *irq_flags);
731         }
732 }
733
734 static void
735 xpc_send_local_activate_IRQ_uv(struct xpc_partition *part, int act_state_req)
736 {
737         unsigned long irq_flags;
738         struct xpc_partition_uv *part_uv = &part->sn.uv;
739
740         /*
741          * !!! Make our side think that the remote partition sent an activate
742          * !!! mq message our way by doing what the activate IRQ handler would
743          * !!! do had one really been sent.
744          */
745
746         spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
747         if (part_uv->act_state_req == 0)
748                 xpc_activate_IRQ_rcvd++;
749         part_uv->act_state_req = act_state_req;
750         spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
751
752         wake_up_interruptible(&xpc_activate_IRQ_wq);
753 }
754
755 static enum xp_retval
756 xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa,
757                                   size_t *len)
758 {
759         s64 status;
760         enum xp_retval ret;
761
762 #if defined CONFIG_X86_64
763         status = uv_bios_reserved_page_pa((u64)buf, cookie, (u64 *)rp_pa,
764                                           (u64 *)len);
765         if (status == BIOS_STATUS_SUCCESS)
766                 ret = xpSuccess;
767         else if (status == BIOS_STATUS_MORE_PASSES)
768                 ret = xpNeedMoreInfo;
769         else
770                 ret = xpBiosError;
771
772 #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV
773         status = sn_partition_reserved_page_pa((u64)buf, cookie, rp_pa, len);
774         if (status == SALRET_OK)
775                 ret = xpSuccess;
776         else if (status == SALRET_MORE_PASSES)
777                 ret = xpNeedMoreInfo;
778         else
779                 ret = xpSalError;
780
781 #else
782         #error not a supported configuration
783 #endif
784
785         return ret;
786 }
787
788 static int
789 xpc_setup_rsvd_page_uv(struct xpc_rsvd_page *rp)
790 {
791         xpc_heartbeat_uv =
792             &xpc_partitions[sn_partition_id].sn.uv.cached_heartbeat;
793         rp->sn.uv.heartbeat_gpa = uv_gpa(xpc_heartbeat_uv);
794         rp->sn.uv.activate_gru_mq_desc_gpa =
795             uv_gpa(xpc_activate_mq_uv->gru_mq_desc);
796         return 0;
797 }
798
799 static void
800 xpc_allow_hb_uv(short partid)
801 {
802 }
803
804 static void
805 xpc_disallow_hb_uv(short partid)
806 {
807 }
808
809 static void
810 xpc_disallow_all_hbs_uv(void)
811 {
812 }
813
814 static void
815 xpc_increment_heartbeat_uv(void)
816 {
817         xpc_heartbeat_uv->value++;
818 }
819
820 static void
821 xpc_offline_heartbeat_uv(void)
822 {
823         xpc_increment_heartbeat_uv();
824         xpc_heartbeat_uv->offline = 1;
825 }
826
827 static void
828 xpc_online_heartbeat_uv(void)
829 {
830         xpc_increment_heartbeat_uv();
831         xpc_heartbeat_uv->offline = 0;
832 }
833
834 static void
835 xpc_heartbeat_init_uv(void)
836 {
837         xpc_heartbeat_uv->value = 1;
838         xpc_heartbeat_uv->offline = 0;
839 }
840
841 static void
842 xpc_heartbeat_exit_uv(void)
843 {
844         xpc_offline_heartbeat_uv();
845 }
846
847 static enum xp_retval
848 xpc_get_remote_heartbeat_uv(struct xpc_partition *part)
849 {
850         struct xpc_partition_uv *part_uv = &part->sn.uv;
851         enum xp_retval ret;
852
853         ret = xp_remote_memcpy(uv_gpa(&part_uv->cached_heartbeat),
854                                part_uv->heartbeat_gpa,
855                                sizeof(struct xpc_heartbeat_uv));
856         if (ret != xpSuccess)
857                 return ret;
858
859         if (part_uv->cached_heartbeat.value == part->last_heartbeat &&
860             !part_uv->cached_heartbeat.offline) {
861
862                 ret = xpNoHeartbeat;
863         } else {
864                 part->last_heartbeat = part_uv->cached_heartbeat.value;
865         }
866         return ret;
867 }
868
869 static void
870 xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp,
871                                     unsigned long remote_rp_gpa, int nasid)
872 {
873         short partid = remote_rp->SAL_partid;
874         struct xpc_partition *part = &xpc_partitions[partid];
875         struct xpc_activate_mq_msg_activate_req_uv msg;
876
877         part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */
878         part->remote_rp_ts_jiffies = remote_rp->ts_jiffies;
879         part->sn.uv.heartbeat_gpa = remote_rp->sn.uv.heartbeat_gpa;
880         part->sn.uv.activate_gru_mq_desc_gpa =
881             remote_rp->sn.uv.activate_gru_mq_desc_gpa;
882
883         /*
884          * ??? Is it a good idea to make this conditional on what is
885          * ??? potentially stale state information?
886          */
887         if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) {
888                 msg.rp_gpa = uv_gpa(xpc_rsvd_page);
889                 msg.heartbeat_gpa = xpc_rsvd_page->sn.uv.heartbeat_gpa;
890                 msg.activate_gru_mq_desc_gpa =
891                     xpc_rsvd_page->sn.uv.activate_gru_mq_desc_gpa;
892                 xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
893                                            XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV);
894         }
895
896         if (part->act_state == XPC_P_AS_INACTIVE)
897                 xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
898 }
899
900 static void
901 xpc_request_partition_reactivation_uv(struct xpc_partition *part)
902 {
903         xpc_send_local_activate_IRQ_uv(part, XPC_P_ASR_ACTIVATE_UV);
904 }
905
906 static void
907 xpc_request_partition_deactivation_uv(struct xpc_partition *part)
908 {
909         struct xpc_activate_mq_msg_deactivate_req_uv msg;
910
911         /*
912          * ??? Is it a good idea to make this conditional on what is
913          * ??? potentially stale state information?
914          */
915         if (part->sn.uv.remote_act_state != XPC_P_AS_DEACTIVATING &&
916             part->sn.uv.remote_act_state != XPC_P_AS_INACTIVE) {
917
918                 msg.reason = part->reason;
919                 xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
920                                          XPC_ACTIVATE_MQ_MSG_DEACTIVATE_REQ_UV);
921         }
922 }
923
924 static void
925 xpc_cancel_partition_deactivation_request_uv(struct xpc_partition *part)
926 {
927         /* nothing needs to be done */
928         return;
929 }
930
931 static void
932 xpc_init_fifo_uv(struct xpc_fifo_head_uv *head)
933 {
934         head->first = NULL;
935         head->last = NULL;
936         spin_lock_init(&head->lock);
937         head->n_entries = 0;
938 }
939
940 static void *
941 xpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head)
942 {
943         unsigned long irq_flags;
944         struct xpc_fifo_entry_uv *first;
945
946         spin_lock_irqsave(&head->lock, irq_flags);
947         first = head->first;
948         if (head->first != NULL) {
949                 head->first = first->next;
950                 if (head->first == NULL)
951                         head->last = NULL;
952         }
953         head->n_entries--;
954         BUG_ON(head->n_entries < 0);
955         spin_unlock_irqrestore(&head->lock, irq_flags);
956         first->next = NULL;
957         return first;
958 }
959
960 static void
961 xpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head,
962                       struct xpc_fifo_entry_uv *last)
963 {
964         unsigned long irq_flags;
965
966         last->next = NULL;
967         spin_lock_irqsave(&head->lock, irq_flags);
968         if (head->last != NULL)
969                 head->last->next = last;
970         else
971                 head->first = last;
972         head->last = last;
973         head->n_entries++;
974         spin_unlock_irqrestore(&head->lock, irq_flags);
975 }
976
977 static int
978 xpc_n_of_fifo_entries_uv(struct xpc_fifo_head_uv *head)
979 {
980         return head->n_entries;
981 }
982
983 /*
984  * Setup the channel structures that are uv specific.
985  */
986 static enum xp_retval
987 xpc_setup_ch_structures_uv(struct xpc_partition *part)
988 {
989         struct xpc_channel_uv *ch_uv;
990         int ch_number;
991
992         for (ch_number = 0; ch_number < part->nchannels; ch_number++) {
993                 ch_uv = &part->channels[ch_number].sn.uv;
994
995                 xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
996                 xpc_init_fifo_uv(&ch_uv->recv_msg_list);
997         }
998
999         return xpSuccess;
1000 }
1001
1002 /*
1003  * Teardown the channel structures that are uv specific.
1004  */
1005 static void
1006 xpc_teardown_ch_structures_uv(struct xpc_partition *part)
1007 {
1008         /* nothing needs to be done */
1009         return;
1010 }
1011
1012 static enum xp_retval
1013 xpc_make_first_contact_uv(struct xpc_partition *part)
1014 {
1015         struct xpc_activate_mq_msg_uv msg;
1016
1017         /*
1018          * We send a sync msg to get the remote partition's remote_act_state
1019          * updated to our current act_state which at this point should
1020          * be XPC_P_AS_ACTIVATING.
1021          */
1022         xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
1023                                       XPC_ACTIVATE_MQ_MSG_SYNC_ACT_STATE_UV);
1024
1025         while (part->sn.uv.remote_act_state != XPC_P_AS_ACTIVATING) {
1026
1027                 dev_dbg(xpc_part, "waiting to make first contact with "
1028                         "partition %d\n", XPC_PARTID(part));
1029
1030                 /* wait a 1/4 of a second or so */
1031                 (void)msleep_interruptible(250);
1032
1033                 if (part->act_state == XPC_P_AS_DEACTIVATING)
1034                         return part->reason;
1035         }
1036
1037         return xpSuccess;
1038 }
1039
1040 static u64
1041 xpc_get_chctl_all_flags_uv(struct xpc_partition *part)
1042 {
1043         unsigned long irq_flags;
1044         union xpc_channel_ctl_flags chctl;
1045
1046         spin_lock_irqsave(&part->chctl_lock, irq_flags);
1047         chctl = part->chctl;
1048         if (chctl.all_flags != 0)
1049                 part->chctl.all_flags = 0;
1050
1051         spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
1052         return chctl.all_flags;
1053 }
1054
1055 static enum xp_retval
1056 xpc_allocate_send_msg_slot_uv(struct xpc_channel *ch)
1057 {
1058         struct xpc_channel_uv *ch_uv = &ch->sn.uv;
1059         struct xpc_send_msg_slot_uv *msg_slot;
1060         unsigned long irq_flags;
1061         int nentries;
1062         int entry;
1063         size_t nbytes;
1064
1065         for (nentries = ch->local_nentries; nentries > 0; nentries--) {
1066                 nbytes = nentries * sizeof(struct xpc_send_msg_slot_uv);
1067                 ch_uv->send_msg_slots = kzalloc(nbytes, GFP_KERNEL);
1068                 if (ch_uv->send_msg_slots == NULL)
1069                         continue;
1070
1071                 for (entry = 0; entry < nentries; entry++) {
1072                         msg_slot = &ch_uv->send_msg_slots[entry];
1073
1074                         msg_slot->msg_slot_number = entry;
1075                         xpc_put_fifo_entry_uv(&ch_uv->msg_slot_free_list,
1076                                               &msg_slot->next);
1077                 }
1078
1079                 spin_lock_irqsave(&ch->lock, irq_flags);
1080                 if (nentries < ch->local_nentries)
1081                         ch->local_nentries = nentries;
1082                 spin_unlock_irqrestore(&ch->lock, irq_flags);
1083                 return xpSuccess;
1084         }
1085
1086         return xpNoMemory;
1087 }
1088
1089 static enum xp_retval
1090 xpc_allocate_recv_msg_slot_uv(struct xpc_channel *ch)
1091 {
1092         struct xpc_channel_uv *ch_uv = &ch->sn.uv;
1093         struct xpc_notify_mq_msg_uv *msg_slot;
1094         unsigned long irq_flags;
1095         int nentries;
1096         int entry;
1097         size_t nbytes;
1098
1099         for (nentries = ch->remote_nentries; nentries > 0; nentries--) {
1100                 nbytes = nentries * ch->entry_size;
1101                 ch_uv->recv_msg_slots = kzalloc(nbytes, GFP_KERNEL);
1102                 if (ch_uv->recv_msg_slots == NULL)
1103                         continue;
1104
1105                 for (entry = 0; entry < nentries; entry++) {
1106                         msg_slot = ch_uv->recv_msg_slots +
1107                             entry * ch->entry_size;
1108
1109                         msg_slot->hdr.msg_slot_number = entry;
1110                 }
1111
1112                 spin_lock_irqsave(&ch->lock, irq_flags);
1113                 if (nentries < ch->remote_nentries)
1114                         ch->remote_nentries = nentries;
1115                 spin_unlock_irqrestore(&ch->lock, irq_flags);
1116                 return xpSuccess;
1117         }
1118
1119         return xpNoMemory;
1120 }
1121
1122 /*
1123  * Allocate msg_slots associated with the channel.
1124  */
1125 static enum xp_retval
1126 xpc_setup_msg_structures_uv(struct xpc_channel *ch)
1127 {
1128         static enum xp_retval ret;
1129         struct xpc_channel_uv *ch_uv = &ch->sn.uv;
1130
1131         DBUG_ON(ch->flags & XPC_C_SETUP);
1132
1133         ch_uv->cached_notify_gru_mq_desc = kmalloc(sizeof(struct
1134                                                    gru_message_queue_desc),
1135                                                    GFP_KERNEL);
1136         if (ch_uv->cached_notify_gru_mq_desc == NULL)
1137                 return xpNoMemory;
1138
1139         ret = xpc_allocate_send_msg_slot_uv(ch);
1140         if (ret == xpSuccess) {
1141
1142                 ret = xpc_allocate_recv_msg_slot_uv(ch);
1143                 if (ret != xpSuccess) {
1144                         kfree(ch_uv->send_msg_slots);
1145                         xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
1146                 }
1147         }
1148         return ret;
1149 }
1150
1151 /*
1152  * Free up msg_slots and clear other stuff that were setup for the specified
1153  * channel.
1154  */
1155 static void
1156 xpc_teardown_msg_structures_uv(struct xpc_channel *ch)
1157 {
1158         struct xpc_channel_uv *ch_uv = &ch->sn.uv;
1159
1160         DBUG_ON(!spin_is_locked(&ch->lock));
1161
1162         kfree(ch_uv->cached_notify_gru_mq_desc);
1163         ch_uv->cached_notify_gru_mq_desc = NULL;
1164
1165         if (ch->flags & XPC_C_SETUP) {
1166                 xpc_init_fifo_uv(&ch_uv->msg_slot_free_list);
1167                 kfree(ch_uv->send_msg_slots);
1168                 xpc_init_fifo_uv(&ch_uv->recv_msg_list);
1169                 kfree(ch_uv->recv_msg_slots);
1170         }
1171 }
1172
1173 static void
1174 xpc_send_chctl_closerequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
1175 {
1176         struct xpc_activate_mq_msg_chctl_closerequest_uv msg;
1177
1178         msg.ch_number = ch->number;
1179         msg.reason = ch->reason;
1180         xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
1181                                     XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV);
1182 }
1183
1184 static void
1185 xpc_send_chctl_closereply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
1186 {
1187         struct xpc_activate_mq_msg_chctl_closereply_uv msg;
1188
1189         msg.ch_number = ch->number;
1190         xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
1191                                     XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV);
1192 }
1193
1194 static void
1195 xpc_send_chctl_openrequest_uv(struct xpc_channel *ch, unsigned long *irq_flags)
1196 {
1197         struct xpc_activate_mq_msg_chctl_openrequest_uv msg;
1198
1199         msg.ch_number = ch->number;
1200         msg.entry_size = ch->entry_size;
1201         msg.local_nentries = ch->local_nentries;
1202         xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
1203                                     XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV);
1204 }
1205
1206 static void
1207 xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags)
1208 {
1209         struct xpc_activate_mq_msg_chctl_openreply_uv msg;
1210
1211         msg.ch_number = ch->number;
1212         msg.local_nentries = ch->local_nentries;
1213         msg.remote_nentries = ch->remote_nentries;
1214         msg.notify_gru_mq_desc_gpa = uv_gpa(xpc_notify_mq_uv->gru_mq_desc);
1215         xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
1216                                     XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV);
1217 }
1218
1219 static void
1220 xpc_send_chctl_opencomplete_uv(struct xpc_channel *ch, unsigned long *irq_flags)
1221 {
1222         struct xpc_activate_mq_msg_chctl_opencomplete_uv msg;
1223
1224         msg.ch_number = ch->number;
1225         xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg),
1226                                     XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV);
1227 }
1228
1229 static void
1230 xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number)
1231 {
1232         unsigned long irq_flags;
1233
1234         spin_lock_irqsave(&part->chctl_lock, irq_flags);
1235         part->chctl.flags[ch_number] |= XPC_CHCTL_MSGREQUEST;
1236         spin_unlock_irqrestore(&part->chctl_lock, irq_flags);
1237
1238         xpc_wakeup_channel_mgr(part);
1239 }
1240
1241 static enum xp_retval
1242 xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch,
1243                                unsigned long gru_mq_desc_gpa)
1244 {
1245         struct xpc_channel_uv *ch_uv = &ch->sn.uv;
1246
1247         DBUG_ON(ch_uv->cached_notify_gru_mq_desc == NULL);
1248         return xpc_cache_remote_gru_mq_desc_uv(ch_uv->cached_notify_gru_mq_desc,
1249                                                gru_mq_desc_gpa);
1250 }
1251
1252 static void
1253 xpc_indicate_partition_engaged_uv(struct xpc_partition *part)
1254 {
1255         struct xpc_activate_mq_msg_uv msg;
1256
1257         xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
1258                                       XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV);
1259 }
1260
1261 static void
1262 xpc_indicate_partition_disengaged_uv(struct xpc_partition *part)
1263 {
1264         struct xpc_activate_mq_msg_uv msg;
1265
1266         xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg),
1267                                       XPC_ACTIVATE_MQ_MSG_MARK_DISENGAGED_UV);
1268 }
1269
1270 static void
1271 xpc_assume_partition_disengaged_uv(short partid)
1272 {
1273         struct xpc_partition_uv *part_uv = &xpc_partitions[partid].sn.uv;
1274         unsigned long irq_flags;
1275
1276         spin_lock_irqsave(&part_uv->flags_lock, irq_flags);
1277         part_uv->flags &= ~XPC_P_ENGAGED_UV;
1278         spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags);
1279 }
1280
1281 static int
1282 xpc_partition_engaged_uv(short partid)
1283 {
1284         return (xpc_partitions[partid].sn.uv.flags & XPC_P_ENGAGED_UV) != 0;
1285 }
1286
1287 static int
1288 xpc_any_partition_engaged_uv(void)
1289 {
1290         struct xpc_partition_uv *part_uv;
1291         short partid;
1292
1293         for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) {
1294                 part_uv = &xpc_partitions[partid].sn.uv;
1295                 if ((part_uv->flags & XPC_P_ENGAGED_UV) != 0)
1296                         return 1;
1297         }
1298         return 0;
1299 }
1300
1301 static enum xp_retval
1302 xpc_allocate_msg_slot_uv(struct xpc_channel *ch, u32 flags,
1303                          struct xpc_send_msg_slot_uv **address_of_msg_slot)
1304 {
1305         enum xp_retval ret;
1306         struct xpc_send_msg_slot_uv *msg_slot;
1307         struct xpc_fifo_entry_uv *entry;
1308
1309         while (1) {
1310                 entry = xpc_get_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list);
1311                 if (entry != NULL)
1312                         break;
1313
1314                 if (flags & XPC_NOWAIT)
1315                         return xpNoWait;
1316
1317                 ret = xpc_allocate_msg_wait(ch);
1318                 if (ret != xpInterrupted && ret != xpTimeout)
1319                         return ret;
1320         }
1321
1322         msg_slot = container_of(entry, struct xpc_send_msg_slot_uv, next);
1323         *address_of_msg_slot = msg_slot;
1324         return xpSuccess;
1325 }
1326
1327 static void
1328 xpc_free_msg_slot_uv(struct xpc_channel *ch,
1329                      struct xpc_send_msg_slot_uv *msg_slot)
1330 {
1331         xpc_put_fifo_entry_uv(&ch->sn.uv.msg_slot_free_list, &msg_slot->next);
1332
1333         /* wakeup anyone waiting for a free msg slot */
1334         if (atomic_read(&ch->n_on_msg_allocate_wq) > 0)
1335                 wake_up(&ch->msg_allocate_wq);
1336 }
1337
1338 static void
1339 xpc_notify_sender_uv(struct xpc_channel *ch,
1340                      struct xpc_send_msg_slot_uv *msg_slot,
1341                      enum xp_retval reason)
1342 {
1343         xpc_notify_func func = msg_slot->func;
1344
1345         if (func != NULL && cmpxchg(&msg_slot->func, func, NULL) == func) {
1346
1347                 atomic_dec(&ch->n_to_notify);
1348
1349                 dev_dbg(xpc_chan, "msg_slot->func() called, msg_slot=0x%p "
1350                         "msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
1351                         msg_slot->msg_slot_number, ch->partid, ch->number);
1352
1353                 func(reason, ch->partid, ch->number, msg_slot->key);
1354
1355                 dev_dbg(xpc_chan, "msg_slot->func() returned, msg_slot=0x%p "
1356                         "msg_slot_number=%d partid=%d channel=%d\n", msg_slot,
1357                         msg_slot->msg_slot_number, ch->partid, ch->number);
1358         }
1359 }
1360
1361 static void
1362 xpc_handle_notify_mq_ack_uv(struct xpc_channel *ch,
1363                             struct xpc_notify_mq_msg_uv *msg)
1364 {
1365         struct xpc_send_msg_slot_uv *msg_slot;
1366         int entry = msg->hdr.msg_slot_number % ch->local_nentries;
1367
1368         msg_slot = &ch->sn.uv.send_msg_slots[entry];
1369
1370         BUG_ON(msg_slot->msg_slot_number != msg->hdr.msg_slot_number);
1371         msg_slot->msg_slot_number += ch->local_nentries;
1372
1373         if (msg_slot->func != NULL)
1374                 xpc_notify_sender_uv(ch, msg_slot, xpMsgDelivered);
1375
1376         xpc_free_msg_slot_uv(ch, msg_slot);
1377 }
1378
1379 static void
1380 xpc_handle_notify_mq_msg_uv(struct xpc_partition *part,
1381                             struct xpc_notify_mq_msg_uv *msg)
1382 {
1383         struct xpc_partition_uv *part_uv = &part->sn.uv;
1384         struct xpc_channel *ch;
1385         struct xpc_channel_uv *ch_uv;
1386         struct xpc_notify_mq_msg_uv *msg_slot;
1387         unsigned long irq_flags;
1388         int ch_number = msg->hdr.ch_number;
1389
1390         if (unlikely(ch_number >= part->nchannels)) {
1391                 dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received invalid "
1392                         "channel number=0x%x in message from partid=%d\n",
1393                         ch_number, XPC_PARTID(part));
1394
1395                 /* get hb checker to deactivate from the remote partition */
1396                 spin_lock_irqsave(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1397                 if (part_uv->act_state_req == 0)
1398                         xpc_activate_IRQ_rcvd++;
1399                 part_uv->act_state_req = XPC_P_ASR_DEACTIVATE_UV;
1400                 part_uv->reason = xpBadChannelNumber;
1401                 spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags);
1402
1403                 wake_up_interruptible(&xpc_activate_IRQ_wq);
1404                 return;
1405         }
1406
1407         ch = &part->channels[ch_number];
1408         xpc_msgqueue_ref(ch);
1409
1410         if (!(ch->flags & XPC_C_CONNECTED)) {
1411                 xpc_msgqueue_deref(ch);
1412                 return;
1413         }
1414
1415         /* see if we're really dealing with an ACK for a previously sent msg */
1416         if (msg->hdr.size == 0) {
1417                 xpc_handle_notify_mq_ack_uv(ch, msg);
1418                 xpc_msgqueue_deref(ch);
1419                 return;
1420         }
1421
1422         /* we're dealing with a normal message sent via the notify_mq */
1423         ch_uv = &ch->sn.uv;
1424
1425         msg_slot = ch_uv->recv_msg_slots +
1426             (msg->hdr.msg_slot_number % ch->remote_nentries) * ch->entry_size;
1427
1428         BUG_ON(msg->hdr.msg_slot_number != msg_slot->hdr.msg_slot_number);
1429         BUG_ON(msg_slot->hdr.size != 0);
1430
1431         memcpy(msg_slot, msg, msg->hdr.size);
1432
1433         xpc_put_fifo_entry_uv(&ch_uv->recv_msg_list, &msg_slot->hdr.u.next);
1434
1435         if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
1436                 /*
1437                  * If there is an existing idle kthread get it to deliver
1438                  * the payload, otherwise we'll have to get the channel mgr
1439                  * for this partition to create a kthread to do the delivery.
1440                  */
1441                 if (atomic_read(&ch->kthreads_idle) > 0)
1442                         wake_up_nr(&ch->idle_wq, 1);
1443                 else
1444                         xpc_send_chctl_local_msgrequest_uv(part, ch->number);
1445         }
1446         xpc_msgqueue_deref(ch);
1447 }
1448
1449 static irqreturn_t
1450 xpc_handle_notify_IRQ_uv(int irq, void *dev_id)
1451 {
1452         struct xpc_notify_mq_msg_uv *msg;
1453         short partid;
1454         struct xpc_partition *part;
1455
1456         while ((msg = gru_get_next_message(xpc_notify_mq_uv->gru_mq_desc)) !=
1457                NULL) {
1458
1459                 partid = msg->hdr.partid;
1460                 if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) {
1461                         dev_err(xpc_part, "xpc_handle_notify_IRQ_uv() received "
1462                                 "invalid partid=0x%x in message\n", partid);
1463                 } else {
1464                         part = &xpc_partitions[partid];
1465
1466                         if (xpc_part_ref(part)) {
1467                                 xpc_handle_notify_mq_msg_uv(part, msg);
1468                                 xpc_part_deref(part);
1469                         }
1470                 }
1471
1472                 gru_free_message(xpc_notify_mq_uv->gru_mq_desc, msg);
1473         }
1474
1475         return IRQ_HANDLED;
1476 }
1477
1478 static int
1479 xpc_n_of_deliverable_payloads_uv(struct xpc_channel *ch)
1480 {
1481         return xpc_n_of_fifo_entries_uv(&ch->sn.uv.recv_msg_list);
1482 }
1483
1484 static void
1485 xpc_process_msg_chctl_flags_uv(struct xpc_partition *part, int ch_number)
1486 {
1487         struct xpc_channel *ch = &part->channels[ch_number];
1488         int ndeliverable_payloads;
1489
1490         xpc_msgqueue_ref(ch);
1491
1492         ndeliverable_payloads = xpc_n_of_deliverable_payloads_uv(ch);
1493
1494         if (ndeliverable_payloads > 0 &&
1495             (ch->flags & XPC_C_CONNECTED) &&
1496             (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE)) {
1497
1498                 xpc_activate_kthreads(ch, ndeliverable_payloads);
1499         }
1500
1501         xpc_msgqueue_deref(ch);
1502 }
1503
1504 static enum xp_retval
1505 xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload,
1506                     u16 payload_size, u8 notify_type, xpc_notify_func func,
1507                     void *key)
1508 {
1509         enum xp_retval ret = xpSuccess;
1510         struct xpc_send_msg_slot_uv *msg_slot = NULL;
1511         struct xpc_notify_mq_msg_uv *msg;
1512         u8 msg_buffer[XPC_NOTIFY_MSG_SIZE_UV];
1513         size_t msg_size;
1514
1515         DBUG_ON(notify_type != XPC_N_CALL);
1516
1517         msg_size = sizeof(struct xpc_notify_mq_msghdr_uv) + payload_size;
1518         if (msg_size > ch->entry_size)
1519                 return xpPayloadTooBig;
1520
1521         xpc_msgqueue_ref(ch);
1522
1523         if (ch->flags & XPC_C_DISCONNECTING) {
1524                 ret = ch->reason;
1525                 goto out_1;
1526         }
1527         if (!(ch->flags & XPC_C_CONNECTED)) {
1528                 ret = xpNotConnected;
1529                 goto out_1;
1530         }
1531
1532         ret = xpc_allocate_msg_slot_uv(ch, flags, &msg_slot);
1533         if (ret != xpSuccess)
1534                 goto out_1;
1535
1536         if (func != NULL) {
1537                 atomic_inc(&ch->n_to_notify);
1538
1539                 msg_slot->key = key;
1540                 smp_wmb(); /* a non-NULL func must hit memory after the key */
1541                 msg_slot->func = func;
1542
1543                 if (ch->flags & XPC_C_DISCONNECTING) {
1544                         ret = ch->reason;
1545                         goto out_2;
1546                 }
1547         }
1548
1549         msg = (struct xpc_notify_mq_msg_uv *)&msg_buffer;
1550         msg->hdr.partid = xp_partition_id;
1551         msg->hdr.ch_number = ch->number;
1552         msg->hdr.size = msg_size;
1553         msg->hdr.msg_slot_number = msg_slot->msg_slot_number;
1554         memcpy(&msg->payload, payload, payload_size);
1555
1556         ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg,
1557                                msg_size);
1558         if (ret == xpSuccess)
1559                 goto out_1;
1560
1561         XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
1562 out_2:
1563         if (func != NULL) {
1564                 /*
1565                  * Try to NULL the msg_slot's func field. If we fail, then
1566                  * xpc_notify_senders_of_disconnect_uv() beat us to it, in which
1567                  * case we need to pretend we succeeded to send the message
1568                  * since the user will get a callout for the disconnect error
1569                  * by xpc_notify_senders_of_disconnect_uv(), and to also get an
1570                  * error returned here will confuse them. Additionally, since
1571                  * in this case the channel is being disconnected we don't need
1572                  * to put the the msg_slot back on the free list.
1573                  */
1574                 if (cmpxchg(&msg_slot->func, func, NULL) != func) {
1575                         ret = xpSuccess;
1576                         goto out_1;
1577                 }
1578
1579                 msg_slot->key = NULL;
1580                 atomic_dec(&ch->n_to_notify);
1581         }
1582         xpc_free_msg_slot_uv(ch, msg_slot);
1583 out_1:
1584         xpc_msgqueue_deref(ch);
1585         return ret;
1586 }
1587
1588 /*
1589  * Tell the callers of xpc_send_notify() that the status of their payloads
1590  * is unknown because the channel is now disconnecting.
1591  *
1592  * We don't worry about putting these msg_slots on the free list since the
1593  * msg_slots themselves are about to be kfree'd.
1594  */
1595 static void
1596 xpc_notify_senders_of_disconnect_uv(struct xpc_channel *ch)
1597 {
1598         struct xpc_send_msg_slot_uv *msg_slot;
1599         int entry;
1600
1601         DBUG_ON(!(ch->flags & XPC_C_DISCONNECTING));
1602
1603         for (entry = 0; entry < ch->local_nentries; entry++) {
1604
1605                 if (atomic_read(&ch->n_to_notify) == 0)
1606                         break;
1607
1608                 msg_slot = &ch->sn.uv.send_msg_slots[entry];
1609                 if (msg_slot->func != NULL)
1610                         xpc_notify_sender_uv(ch, msg_slot, ch->reason);
1611         }
1612 }
1613
1614 /*
1615  * Get the next deliverable message's payload.
1616  */
1617 static void *
1618 xpc_get_deliverable_payload_uv(struct xpc_channel *ch)
1619 {
1620         struct xpc_fifo_entry_uv *entry;
1621         struct xpc_notify_mq_msg_uv *msg;
1622         void *payload = NULL;
1623
1624         if (!(ch->flags & XPC_C_DISCONNECTING)) {
1625                 entry = xpc_get_fifo_entry_uv(&ch->sn.uv.recv_msg_list);
1626                 if (entry != NULL) {
1627                         msg = container_of(entry, struct xpc_notify_mq_msg_uv,
1628                                            hdr.u.next);
1629                         payload = &msg->payload;
1630                 }
1631         }
1632         return payload;
1633 }
1634
1635 static void
1636 xpc_received_payload_uv(struct xpc_channel *ch, void *payload)
1637 {
1638         struct xpc_notify_mq_msg_uv *msg;
1639         enum xp_retval ret;
1640
1641         msg = container_of(payload, struct xpc_notify_mq_msg_uv, payload);
1642
1643         /* return an ACK to the sender of this message */
1644
1645         msg->hdr.partid = xp_partition_id;
1646         msg->hdr.size = 0;      /* size of zero indicates this is an ACK */
1647
1648         ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg,
1649                                sizeof(struct xpc_notify_mq_msghdr_uv));
1650         if (ret != xpSuccess)
1651                 XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret);
1652
1653         msg->hdr.msg_slot_number += ch->remote_nentries;
1654 }
1655
1656 static struct xpc_arch_operations xpc_arch_ops_uv = {
1657         .setup_partitions = xpc_setup_partitions_uv,
1658         .teardown_partitions = xpc_teardown_partitions_uv,
1659         .process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv,
1660         .get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv,
1661         .setup_rsvd_page = xpc_setup_rsvd_page_uv,
1662
1663         .allow_hb = xpc_allow_hb_uv,
1664         .disallow_hb = xpc_disallow_hb_uv,
1665         .disallow_all_hbs = xpc_disallow_all_hbs_uv,
1666         .increment_heartbeat = xpc_increment_heartbeat_uv,
1667         .offline_heartbeat = xpc_offline_heartbeat_uv,
1668         .online_heartbeat = xpc_online_heartbeat_uv,
1669         .heartbeat_init = xpc_heartbeat_init_uv,
1670         .heartbeat_exit = xpc_heartbeat_exit_uv,
1671         .get_remote_heartbeat = xpc_get_remote_heartbeat_uv,
1672
1673         .request_partition_activation =
1674                 xpc_request_partition_activation_uv,
1675         .request_partition_reactivation =
1676                 xpc_request_partition_reactivation_uv,
1677         .request_partition_deactivation =
1678                 xpc_request_partition_deactivation_uv,
1679         .cancel_partition_deactivation_request =
1680                 xpc_cancel_partition_deactivation_request_uv,
1681
1682         .setup_ch_structures = xpc_setup_ch_structures_uv,
1683         .teardown_ch_structures = xpc_teardown_ch_structures_uv,
1684
1685         .make_first_contact = xpc_make_first_contact_uv,
1686
1687         .get_chctl_all_flags = xpc_get_chctl_all_flags_uv,
1688         .send_chctl_closerequest = xpc_send_chctl_closerequest_uv,
1689         .send_chctl_closereply = xpc_send_chctl_closereply_uv,
1690         .send_chctl_openrequest = xpc_send_chctl_openrequest_uv,
1691         .send_chctl_openreply = xpc_send_chctl_openreply_uv,
1692         .send_chctl_opencomplete = xpc_send_chctl_opencomplete_uv,
1693         .process_msg_chctl_flags = xpc_process_msg_chctl_flags_uv,
1694
1695         .save_remote_msgqueue_pa = xpc_save_remote_msgqueue_pa_uv,
1696
1697         .setup_msg_structures = xpc_setup_msg_structures_uv,
1698         .teardown_msg_structures = xpc_teardown_msg_structures_uv,
1699
1700         .indicate_partition_engaged = xpc_indicate_partition_engaged_uv,
1701         .indicate_partition_disengaged = xpc_indicate_partition_disengaged_uv,
1702         .assume_partition_disengaged = xpc_assume_partition_disengaged_uv,
1703         .partition_engaged = xpc_partition_engaged_uv,
1704         .any_partition_engaged = xpc_any_partition_engaged_uv,
1705
1706         .n_of_deliverable_payloads = xpc_n_of_deliverable_payloads_uv,
1707         .send_payload = xpc_send_payload_uv,
1708         .get_deliverable_payload = xpc_get_deliverable_payload_uv,
1709         .received_payload = xpc_received_payload_uv,
1710         .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv,
1711 };
1712
1713 int
1714 xpc_init_uv(void)
1715 {
1716         xpc_arch_ops = xpc_arch_ops_uv;
1717
1718         if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) {
1719                 dev_err(xpc_part, "xpc_notify_mq_msghdr_uv is larger than %d\n",
1720                         XPC_MSG_HDR_MAX_SIZE);
1721                 return -E2BIG;
1722         }
1723
1724         xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0,
1725                                                   XPC_ACTIVATE_IRQ_NAME,
1726                                                   xpc_handle_activate_IRQ_uv);
1727         if (IS_ERR(xpc_activate_mq_uv))
1728                 return PTR_ERR(xpc_activate_mq_uv);
1729
1730         xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0,
1731                                                 XPC_NOTIFY_IRQ_NAME,
1732                                                 xpc_handle_notify_IRQ_uv);
1733         if (IS_ERR(xpc_notify_mq_uv)) {
1734                 xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
1735                 return PTR_ERR(xpc_notify_mq_uv);
1736         }
1737
1738         return 0;
1739 }
1740
1741 void
1742 xpc_exit_uv(void)
1743 {
1744         xpc_destroy_gru_mq_uv(xpc_notify_mq_uv);
1745         xpc_destroy_gru_mq_uv(xpc_activate_mq_uv);
1746 }