diff options
author | Jack Steiner <steiner@sgi.com> | 2009-04-02 19:59:10 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:05:06 -0400 |
commit | 6f2584f47474d29ce829604bfc8b56c10b352fdb (patch) | |
tree | f5b5c63c7c73785a641c995c2fe48b4c5cc726eb /drivers/misc/sgi-xp/xpc_uv.c | |
parent | ecdaf2b55251f718a1fbaf4a3f72bfd6e25c582c (diff) |
sgi-gru: add support to the GRU driver for message queue interrupts
Add support to the GRU driver for message queue interrupts.
Signed-off-by: Jack Steiner <steiner@sgi.com>
Signed-off-by: Dean Nelson <dcn@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/misc/sgi-xp/xpc_uv.c')
-rw-r--r-- | drivers/misc/sgi-xp/xpc_uv.c | 229 |
1 files changed, 181 insertions, 48 deletions
diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 29c0502a96b2..f7fff4727edb 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c | |||
@@ -31,6 +31,21 @@ | |||
31 | #include "../sgi-gru/grukservices.h" | 31 | #include "../sgi-gru/grukservices.h" |
32 | #include "xpc.h" | 32 | #include "xpc.h" |
33 | 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 | |||
34 | static atomic64_t xpc_heartbeat_uv; | 49 | static atomic64_t xpc_heartbeat_uv; |
35 | static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); | 50 | static DECLARE_BITMAP(xpc_heartbeating_to_mask_uv, XP_MAX_NPARTITIONS_UV); |
36 | 51 | ||
@@ -56,26 +71,52 @@ xpc_setup_partitions_sn_uv(void) | |||
56 | for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) { | 71 | for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) { |
57 | part_uv = &xpc_partitions[partid].sn.uv; | 72 | part_uv = &xpc_partitions[partid].sn.uv; |
58 | 73 | ||
74 | mutex_init(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
59 | spin_lock_init(&part_uv->flags_lock); | 75 | spin_lock_init(&part_uv->flags_lock); |
60 | part_uv->remote_act_state = XPC_P_AS_INACTIVE; | 76 | part_uv->remote_act_state = XPC_P_AS_INACTIVE; |
61 | } | 77 | } |
62 | return 0; | 78 | return 0; |
63 | } | 79 | } |
64 | 80 | ||
81 | static void | ||
82 | xpc_teardown_partitions_sn_uv(void) | ||
83 | { | ||
84 | short partid; | ||
85 | struct xpc_partition_uv *part_uv; | ||
86 | unsigned long irq_flags; | ||
87 | |||
88 | for (partid = 0; partid < XP_MAX_NPARTITIONS_UV; partid++) { | ||
89 | part_uv = &xpc_partitions[partid].sn.uv; | ||
90 | |||
91 | if (part_uv->cached_activate_gru_mq_desc != NULL) { | ||
92 | mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
93 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
94 | part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; | ||
95 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
96 | kfree(part_uv->cached_activate_gru_mq_desc); | ||
97 | part_uv->cached_activate_gru_mq_desc = NULL; | ||
98 | mutex_unlock(&part_uv-> | ||
99 | cached_activate_gru_mq_desc_mutex); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | |||
65 | static int | 104 | static int |
66 | xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) | 105 | xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) |
67 | { | 106 | { |
107 | int mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); | ||
108 | |||
68 | #if defined CONFIG_X86_64 | 109 | #if defined CONFIG_X86_64 |
69 | mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset); | 110 | mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset); |
70 | if (mq->irq < 0) { | 111 | if (mq->irq < 0) { |
71 | dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", | 112 | dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", |
72 | mq->irq); | 113 | -mq->irq); |
114 | return mq->irq; | ||
73 | } | 115 | } |
74 | 116 | ||
75 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | 117 | mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); |
76 | int mmr_pnode; | ||
77 | unsigned long mmr_value; | ||
78 | 118 | ||
119 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | ||
79 | if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0) | 120 | if (strcmp(irq_name, XPC_ACTIVATE_IRQ_NAME) == 0) |
80 | mq->irq = SGI_XPC_ACTIVATE; | 121 | mq->irq = SGI_XPC_ACTIVATE; |
81 | else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0) | 122 | else if (strcmp(irq_name, XPC_NOTIFY_IRQ_NAME) == 0) |
@@ -83,10 +124,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) | |||
83 | else | 124 | else |
84 | return -EINVAL; | 125 | return -EINVAL; |
85 | 126 | ||
86 | mmr_pnode = uv_blade_to_pnode(mq->mmr_blade); | 127 | mq->mmr_value = (unsigned long)cpu_physical_id(cpu) << 32 | mq->irq; |
87 | mmr_value = (unsigned long)cpu_physical_id(cpu) << 32 | mq->irq; | 128 | uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mq->mmr_value); |
88 | |||
89 | uv_write_global_mmr64(mmr_pnode, mq->mmr_offset, mmr_value); | ||
90 | #else | 129 | #else |
91 | #error not a supported configuration | 130 | #error not a supported configuration |
92 | #endif | 131 | #endif |
@@ -127,7 +166,7 @@ xpc_gru_mq_watchlist_alloc_uv(struct xpc_gru_mq_uv *mq) | |||
127 | return ret; | 166 | return ret; |
128 | } | 167 | } |
129 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV | 168 | #elif defined CONFIG_IA64_GENERIC || defined CONFIG_IA64_SGI_UV |
130 | ret = sn_mq_watchlist_alloc(mq->mmr_blade, uv_gpa(mq->address), | 169 | ret = sn_mq_watchlist_alloc(mq->mmr_blade, (void *)uv_gpa(mq->address), |
131 | mq->order, &mq->mmr_offset); | 170 | mq->order, &mq->mmr_offset); |
132 | if (ret < 0) { | 171 | if (ret < 0) { |
133 | dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", | 172 | dev_err(xpc_part, "sn_mq_watchlist_alloc() failed, ret=%d\n", |
@@ -168,12 +207,22 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
168 | int pg_order; | 207 | int pg_order; |
169 | struct page *page; | 208 | struct page *page; |
170 | struct xpc_gru_mq_uv *mq; | 209 | struct xpc_gru_mq_uv *mq; |
210 | struct uv_IO_APIC_route_entry *mmr_value; | ||
171 | 211 | ||
172 | mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL); | 212 | mq = kmalloc(sizeof(struct xpc_gru_mq_uv), GFP_KERNEL); |
173 | if (mq == NULL) { | 213 | if (mq == NULL) { |
174 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " | 214 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " |
175 | "a xpc_gru_mq_uv structure\n"); | 215 | "a xpc_gru_mq_uv structure\n"); |
176 | ret = -ENOMEM; | 216 | ret = -ENOMEM; |
217 | goto out_0; | ||
218 | } | ||
219 | |||
220 | mq->gru_mq_desc = kzalloc(sizeof(struct gru_message_queue_desc), | ||
221 | GFP_KERNEL); | ||
222 | if (mq->gru_mq_desc == NULL) { | ||
223 | dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to kmalloc() " | ||
224 | "a gru_message_queue_desc structure\n"); | ||
225 | ret = -ENOMEM; | ||
177 | goto out_1; | 226 | goto out_1; |
178 | } | 227 | } |
179 | 228 | ||
@@ -194,14 +243,6 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
194 | } | 243 | } |
195 | mq->address = page_address(page); | 244 | mq->address = page_address(page); |
196 | 245 | ||
197 | ret = gru_create_message_queue(mq->address, mq_size); | ||
198 | if (ret != 0) { | ||
199 | dev_err(xpc_part, "gru_create_message_queue() returned " | ||
200 | "error=%d\n", ret); | ||
201 | ret = -EINVAL; | ||
202 | goto out_3; | ||
203 | } | ||
204 | |||
205 | /* enable generation of irq when GRU mq operation occurs to this mq */ | 246 | /* enable generation of irq when GRU mq operation occurs to this mq */ |
206 | ret = xpc_gru_mq_watchlist_alloc_uv(mq); | 247 | ret = xpc_gru_mq_watchlist_alloc_uv(mq); |
207 | if (ret != 0) | 248 | if (ret != 0) |
@@ -214,10 +255,20 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, | |||
214 | ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL); | 255 | ret = request_irq(mq->irq, irq_handler, 0, irq_name, NULL); |
215 | if (ret != 0) { | 256 | if (ret != 0) { |
216 | dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n", | 257 | dev_err(xpc_part, "request_irq(irq=%d) returned error=%d\n", |
217 | mq->irq, ret); | 258 | mq->irq, -ret); |
218 | goto out_5; | 259 | goto out_5; |
219 | } | 260 | } |
220 | 261 | ||
262 | mmr_value = (struct uv_IO_APIC_route_entry *)&mq->mmr_value; | ||
263 | ret = gru_create_message_queue(mq->gru_mq_desc, mq->address, mq_size, | ||
264 | nid, mmr_value->vector, mmr_value->dest); | ||
265 | if (ret != 0) { | ||
266 | dev_err(xpc_part, "gru_create_message_queue() returned " | ||
267 | "error=%d\n", ret); | ||
268 | ret = -EINVAL; | ||
269 | goto out_6; | ||
270 | } | ||
271 | |||
221 | /* allow other partitions to access this GRU mq */ | 272 | /* allow other partitions to access this GRU mq */ |
222 | xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size); | 273 | xp_ret = xp_expand_memprotect(xp_pa(mq->address), mq_size); |
223 | if (xp_ret != xpSuccess) { | 274 | if (xp_ret != xpSuccess) { |
@@ -237,8 +288,10 @@ out_4: | |||
237 | out_3: | 288 | out_3: |
238 | free_pages((unsigned long)mq->address, pg_order); | 289 | free_pages((unsigned long)mq->address, pg_order); |
239 | out_2: | 290 | out_2: |
240 | kfree(mq); | 291 | kfree(mq->gru_mq_desc); |
241 | out_1: | 292 | out_1: |
293 | kfree(mq); | ||
294 | out_0: | ||
242 | return ERR_PTR(ret); | 295 | return ERR_PTR(ret); |
243 | } | 296 | } |
244 | 297 | ||
@@ -268,13 +321,14 @@ xpc_destroy_gru_mq_uv(struct xpc_gru_mq_uv *mq) | |||
268 | } | 321 | } |
269 | 322 | ||
270 | static enum xp_retval | 323 | static enum xp_retval |
271 | xpc_send_gru_msg(unsigned long mq_gpa, void *msg, size_t msg_size) | 324 | xpc_send_gru_msg(struct gru_message_queue_desc *gru_mq_desc, void *msg, |
325 | size_t msg_size) | ||
272 | { | 326 | { |
273 | enum xp_retval xp_ret; | 327 | enum xp_retval xp_ret; |
274 | int ret; | 328 | int ret; |
275 | 329 | ||
276 | while (1) { | 330 | while (1) { |
277 | ret = gru_send_message_gpa(mq_gpa, msg, msg_size); | 331 | ret = gru_send_message_gpa(gru_mq_desc, msg, msg_size); |
278 | if (ret == MQE_OK) { | 332 | if (ret == MQE_OK) { |
279 | xp_ret = xpSuccess; | 333 | xp_ret = xpSuccess; |
280 | break; | 334 | break; |
@@ -421,7 +475,15 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
421 | part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; | 475 | part_uv->act_state_req = XPC_P_ASR_ACTIVATE_UV; |
422 | part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ | 476 | part->remote_rp_pa = msg->rp_gpa; /* !!! _pa is _gpa */ |
423 | part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; | 477 | part->remote_rp_ts_jiffies = msg_hdr->rp_ts_jiffies; |
424 | part_uv->remote_activate_mq_gpa = msg->activate_mq_gpa; | 478 | |
479 | if (msg->activate_gru_mq_desc_gpa != | ||
480 | part_uv->activate_gru_mq_desc_gpa) { | ||
481 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
482 | part_uv->flags &= ~XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; | ||
483 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
484 | part_uv->activate_gru_mq_desc_gpa = | ||
485 | msg->activate_gru_mq_desc_gpa; | ||
486 | } | ||
425 | spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags); | 487 | spin_unlock_irqrestore(&xpc_activate_IRQ_rcvd_lock, irq_flags); |
426 | 488 | ||
427 | (*wakeup_hb_checker)++; | 489 | (*wakeup_hb_checker)++; |
@@ -498,7 +560,7 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, | |||
498 | args = &part->remote_openclose_args[msg->ch_number]; | 560 | args = &part->remote_openclose_args[msg->ch_number]; |
499 | args->remote_nentries = msg->remote_nentries; | 561 | args->remote_nentries = msg->remote_nentries; |
500 | args->local_nentries = msg->local_nentries; | 562 | args->local_nentries = msg->local_nentries; |
501 | args->local_msgqueue_pa = msg->local_notify_mq_gpa; | 563 | args->local_msgqueue_pa = msg->notify_gru_mq_desc_gpa; |
502 | 564 | ||
503 | spin_lock_irqsave(&part->chctl_lock, irq_flags); | 565 | spin_lock_irqsave(&part->chctl_lock, irq_flags); |
504 | part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY; | 566 | part->chctl.flags[msg->ch_number] |= XPC_CHCTL_OPENREPLY; |
@@ -558,9 +620,10 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
558 | short partid; | 620 | short partid; |
559 | struct xpc_partition *part; | 621 | struct xpc_partition *part; |
560 | int wakeup_hb_checker = 0; | 622 | int wakeup_hb_checker = 0; |
623 | int part_referenced; | ||
561 | 624 | ||
562 | while (1) { | 625 | while (1) { |
563 | msg_hdr = gru_get_next_message(xpc_activate_mq_uv->address); | 626 | msg_hdr = gru_get_next_message(xpc_activate_mq_uv->gru_mq_desc); |
564 | if (msg_hdr == NULL) | 627 | if (msg_hdr == NULL) |
565 | break; | 628 | break; |
566 | 629 | ||
@@ -571,14 +634,15 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
571 | partid); | 634 | partid); |
572 | } else { | 635 | } else { |
573 | part = &xpc_partitions[partid]; | 636 | part = &xpc_partitions[partid]; |
574 | if (xpc_part_ref(part)) { | 637 | |
575 | xpc_handle_activate_mq_msg_uv(part, msg_hdr, | 638 | part_referenced = xpc_part_ref(part); |
576 | &wakeup_hb_checker); | 639 | xpc_handle_activate_mq_msg_uv(part, msg_hdr, |
640 | &wakeup_hb_checker); | ||
641 | if (part_referenced) | ||
577 | xpc_part_deref(part); | 642 | xpc_part_deref(part); |
578 | } | ||
579 | } | 643 | } |
580 | 644 | ||
581 | gru_free_message(xpc_activate_mq_uv->address, msg_hdr); | 645 | gru_free_message(xpc_activate_mq_uv->gru_mq_desc, msg_hdr); |
582 | } | 646 | } |
583 | 647 | ||
584 | if (wakeup_hb_checker) | 648 | if (wakeup_hb_checker) |
@@ -588,21 +652,73 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id) | |||
588 | } | 652 | } |
589 | 653 | ||
590 | static enum xp_retval | 654 | static enum xp_retval |
655 | xpc_cache_remote_gru_mq_desc_uv(struct gru_message_queue_desc *gru_mq_desc, | ||
656 | unsigned long gru_mq_desc_gpa) | ||
657 | { | ||
658 | enum xp_retval ret; | ||
659 | |||
660 | ret = xp_remote_memcpy(uv_gpa(gru_mq_desc), gru_mq_desc_gpa, | ||
661 | sizeof(struct gru_message_queue_desc)); | ||
662 | if (ret == xpSuccess) | ||
663 | gru_mq_desc->mq = NULL; | ||
664 | |||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | static enum xp_retval | ||
591 | xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size, | 669 | xpc_send_activate_IRQ_uv(struct xpc_partition *part, void *msg, size_t msg_size, |
592 | int msg_type) | 670 | int msg_type) |
593 | { | 671 | { |
594 | struct xpc_activate_mq_msghdr_uv *msg_hdr = msg; | 672 | struct xpc_activate_mq_msghdr_uv *msg_hdr = msg; |
673 | struct xpc_partition_uv *part_uv = &part->sn.uv; | ||
674 | struct gru_message_queue_desc *gru_mq_desc; | ||
675 | unsigned long irq_flags; | ||
676 | enum xp_retval ret; | ||
595 | 677 | ||
596 | DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV); | 678 | DBUG_ON(msg_size > XPC_ACTIVATE_MSG_SIZE_UV); |
597 | 679 | ||
598 | msg_hdr->type = msg_type; | 680 | msg_hdr->type = msg_type; |
599 | msg_hdr->partid = XPC_PARTID(part); | 681 | msg_hdr->partid = xp_partition_id; |
600 | msg_hdr->act_state = part->act_state; | 682 | msg_hdr->act_state = part->act_state; |
601 | msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies; | 683 | msg_hdr->rp_ts_jiffies = xpc_rsvd_page->ts_jiffies; |
602 | 684 | ||
685 | mutex_lock(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
686 | again: | ||
687 | if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) { | ||
688 | gru_mq_desc = part_uv->cached_activate_gru_mq_desc; | ||
689 | if (gru_mq_desc == NULL) { | ||
690 | gru_mq_desc = kmalloc(sizeof(struct | ||
691 | gru_message_queue_desc), | ||
692 | GFP_KERNEL); | ||
693 | if (gru_mq_desc == NULL) { | ||
694 | ret = xpNoMemory; | ||
695 | goto done; | ||
696 | } | ||
697 | part_uv->cached_activate_gru_mq_desc = gru_mq_desc; | ||
698 | } | ||
699 | |||
700 | ret = xpc_cache_remote_gru_mq_desc_uv(gru_mq_desc, | ||
701 | part_uv-> | ||
702 | activate_gru_mq_desc_gpa); | ||
703 | if (ret != xpSuccess) | ||
704 | goto done; | ||
705 | |||
706 | spin_lock_irqsave(&part_uv->flags_lock, irq_flags); | ||
707 | part_uv->flags |= XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV; | ||
708 | spin_unlock_irqrestore(&part_uv->flags_lock, irq_flags); | ||
709 | } | ||
710 | |||
603 | /* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */ | 711 | /* ??? Is holding a spin_lock (ch->lock) during this call a bad idea? */ |
604 | return xpc_send_gru_msg(part->sn.uv.remote_activate_mq_gpa, msg, | 712 | ret = xpc_send_gru_msg(part_uv->cached_activate_gru_mq_desc, msg, |
605 | msg_size); | 713 | msg_size); |
714 | if (ret != xpSuccess) { | ||
715 | smp_rmb(); /* ensure a fresh copy of part_uv->flags */ | ||
716 | if (!(part_uv->flags & XPC_P_CACHED_ACTIVATE_GRU_MQ_DESC_UV)) | ||
717 | goto again; | ||
718 | } | ||
719 | done: | ||
720 | mutex_unlock(&part_uv->cached_activate_gru_mq_desc_mutex); | ||
721 | return ret; | ||
606 | } | 722 | } |
607 | 723 | ||
608 | static void | 724 | static void |
@@ -620,7 +736,7 @@ static void | |||
620 | xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags, | 736 | xpc_send_activate_IRQ_ch_uv(struct xpc_channel *ch, unsigned long *irq_flags, |
621 | void *msg, size_t msg_size, int msg_type) | 737 | void *msg, size_t msg_size, int msg_type) |
622 | { | 738 | { |
623 | struct xpc_partition *part = &xpc_partitions[ch->number]; | 739 | struct xpc_partition *part = &xpc_partitions[ch->partid]; |
624 | enum xp_retval ret; | 740 | enum xp_retval ret; |
625 | 741 | ||
626 | ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type); | 742 | ret = xpc_send_activate_IRQ_uv(part, msg, msg_size, msg_type); |
@@ -692,7 +808,8 @@ xpc_get_partition_rsvd_page_pa_uv(void *buf, u64 *cookie, unsigned long *rp_pa, | |||
692 | static int | 808 | static int |
693 | xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) | 809 | xpc_setup_rsvd_page_sn_uv(struct xpc_rsvd_page *rp) |
694 | { | 810 | { |
695 | rp->sn.activate_mq_gpa = uv_gpa(xpc_activate_mq_uv->address); | 811 | rp->sn.activate_gru_mq_desc_gpa = |
812 | uv_gpa(xpc_activate_mq_uv->gru_mq_desc); | ||
696 | return 0; | 813 | return 0; |
697 | } | 814 | } |
698 | 815 | ||
@@ -787,7 +904,8 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, | |||
787 | 904 | ||
788 | part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ | 905 | part->remote_rp_pa = remote_rp_gpa; /* !!! _pa here is really _gpa */ |
789 | part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; | 906 | part->remote_rp_ts_jiffies = remote_rp->ts_jiffies; |
790 | part->sn.uv.remote_activate_mq_gpa = remote_rp->sn.activate_mq_gpa; | 907 | part->sn.uv.activate_gru_mq_desc_gpa = |
908 | remote_rp->sn.activate_gru_mq_desc_gpa; | ||
791 | 909 | ||
792 | /* | 910 | /* |
793 | * ??? Is it a good idea to make this conditional on what is | 911 | * ??? Is it a good idea to make this conditional on what is |
@@ -795,7 +913,8 @@ xpc_request_partition_activation_uv(struct xpc_rsvd_page *remote_rp, | |||
795 | */ | 913 | */ |
796 | if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { | 914 | if (part->sn.uv.remote_act_state == XPC_P_AS_INACTIVE) { |
797 | msg.rp_gpa = uv_gpa(xpc_rsvd_page); | 915 | msg.rp_gpa = uv_gpa(xpc_rsvd_page); |
798 | msg.activate_mq_gpa = xpc_rsvd_page->sn.activate_mq_gpa; | 916 | msg.activate_gru_mq_desc_gpa = |
917 | xpc_rsvd_page->sn.activate_gru_mq_desc_gpa; | ||
799 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), | 918 | xpc_send_activate_IRQ_part_uv(part, &msg, sizeof(msg), |
800 | XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); | 919 | XPC_ACTIVATE_MQ_MSG_ACTIVATE_REQ_UV); |
801 | } | 920 | } |
@@ -857,7 +976,8 @@ xpc_get_fifo_entry_uv(struct xpc_fifo_head_uv *head) | |||
857 | if (head->first == NULL) | 976 | if (head->first == NULL) |
858 | head->last = NULL; | 977 | head->last = NULL; |
859 | } | 978 | } |
860 | head->n_entries++; | 979 | head->n_entries--; |
980 | BUG_ON(head->n_entries < 0); | ||
861 | spin_unlock_irqrestore(&head->lock, irq_flags); | 981 | spin_unlock_irqrestore(&head->lock, irq_flags); |
862 | first->next = NULL; | 982 | first->next = NULL; |
863 | return first; | 983 | return first; |
@@ -876,8 +996,7 @@ xpc_put_fifo_entry_uv(struct xpc_fifo_head_uv *head, | |||
876 | else | 996 | else |
877 | head->first = last; | 997 | head->first = last; |
878 | head->last = last; | 998 | head->last = last; |
879 | head->n_entries--; | 999 | head->n_entries++; |
880 | BUG_ON(head->n_entries < 0); | ||
881 | spin_unlock_irqrestore(&head->lock, irq_flags); | 1000 | spin_unlock_irqrestore(&head->lock, irq_flags); |
882 | } | 1001 | } |
883 | 1002 | ||
@@ -1037,6 +1156,12 @@ xpc_setup_msg_structures_uv(struct xpc_channel *ch) | |||
1037 | 1156 | ||
1038 | DBUG_ON(ch->flags & XPC_C_SETUP); | 1157 | DBUG_ON(ch->flags & XPC_C_SETUP); |
1039 | 1158 | ||
1159 | ch_uv->cached_notify_gru_mq_desc = kmalloc(sizeof(struct | ||
1160 | gru_message_queue_desc), | ||
1161 | GFP_KERNEL); | ||
1162 | if (ch_uv->cached_notify_gru_mq_desc == NULL) | ||
1163 | return xpNoMemory; | ||
1164 | |||
1040 | ret = xpc_allocate_send_msg_slot_uv(ch); | 1165 | ret = xpc_allocate_send_msg_slot_uv(ch); |
1041 | if (ret == xpSuccess) { | 1166 | if (ret == xpSuccess) { |
1042 | 1167 | ||
@@ -1060,7 +1185,8 @@ xpc_teardown_msg_structures_uv(struct xpc_channel *ch) | |||
1060 | 1185 | ||
1061 | DBUG_ON(!spin_is_locked(&ch->lock)); | 1186 | DBUG_ON(!spin_is_locked(&ch->lock)); |
1062 | 1187 | ||
1063 | ch_uv->remote_notify_mq_gpa = 0; | 1188 | kfree(ch_uv->cached_notify_gru_mq_desc); |
1189 | ch_uv->cached_notify_gru_mq_desc = NULL; | ||
1064 | 1190 | ||
1065 | if (ch->flags & XPC_C_SETUP) { | 1191 | if (ch->flags & XPC_C_SETUP) { |
1066 | xpc_init_fifo_uv(&ch_uv->msg_slot_free_list); | 1192 | xpc_init_fifo_uv(&ch_uv->msg_slot_free_list); |
@@ -1111,7 +1237,7 @@ xpc_send_chctl_openreply_uv(struct xpc_channel *ch, unsigned long *irq_flags) | |||
1111 | msg.ch_number = ch->number; | 1237 | msg.ch_number = ch->number; |
1112 | msg.local_nentries = ch->local_nentries; | 1238 | msg.local_nentries = ch->local_nentries; |
1113 | msg.remote_nentries = ch->remote_nentries; | 1239 | msg.remote_nentries = ch->remote_nentries; |
1114 | msg.local_notify_mq_gpa = uv_gpa(xpc_notify_mq_uv); | 1240 | msg.notify_gru_mq_desc_gpa = uv_gpa(xpc_notify_mq_uv->gru_mq_desc); |
1115 | xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg), | 1241 | xpc_send_activate_IRQ_ch_uv(ch, irq_flags, &msg, sizeof(msg), |
1116 | XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV); | 1242 | XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV); |
1117 | } | 1243 | } |
@@ -1128,11 +1254,15 @@ xpc_send_chctl_local_msgrequest_uv(struct xpc_partition *part, int ch_number) | |||
1128 | xpc_wakeup_channel_mgr(part); | 1254 | xpc_wakeup_channel_mgr(part); |
1129 | } | 1255 | } |
1130 | 1256 | ||
1131 | static void | 1257 | static enum xp_retval |
1132 | xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch, | 1258 | xpc_save_remote_msgqueue_pa_uv(struct xpc_channel *ch, |
1133 | unsigned long msgqueue_pa) | 1259 | unsigned long gru_mq_desc_gpa) |
1134 | { | 1260 | { |
1135 | ch->sn.uv.remote_notify_mq_gpa = msgqueue_pa; | 1261 | struct xpc_channel_uv *ch_uv = &ch->sn.uv; |
1262 | |||
1263 | DBUG_ON(ch_uv->cached_notify_gru_mq_desc == NULL); | ||
1264 | return xpc_cache_remote_gru_mq_desc_uv(ch_uv->cached_notify_gru_mq_desc, | ||
1265 | gru_mq_desc_gpa); | ||
1136 | } | 1266 | } |
1137 | 1267 | ||
1138 | static void | 1268 | static void |
@@ -1339,7 +1469,8 @@ xpc_handle_notify_IRQ_uv(int irq, void *dev_id) | |||
1339 | short partid; | 1469 | short partid; |
1340 | struct xpc_partition *part; | 1470 | struct xpc_partition *part; |
1341 | 1471 | ||
1342 | while ((msg = gru_get_next_message(xpc_notify_mq_uv)) != NULL) { | 1472 | while ((msg = gru_get_next_message(xpc_notify_mq_uv->gru_mq_desc)) != |
1473 | NULL) { | ||
1343 | 1474 | ||
1344 | partid = msg->hdr.partid; | 1475 | partid = msg->hdr.partid; |
1345 | if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) { | 1476 | if (partid < 0 || partid >= XP_MAX_NPARTITIONS_UV) { |
@@ -1354,7 +1485,7 @@ xpc_handle_notify_IRQ_uv(int irq, void *dev_id) | |||
1354 | } | 1485 | } |
1355 | } | 1486 | } |
1356 | 1487 | ||
1357 | gru_free_message(xpc_notify_mq_uv, msg); | 1488 | gru_free_message(xpc_notify_mq_uv->gru_mq_desc, msg); |
1358 | } | 1489 | } |
1359 | 1490 | ||
1360 | return IRQ_HANDLED; | 1491 | return IRQ_HANDLED; |
@@ -1438,7 +1569,8 @@ xpc_send_payload_uv(struct xpc_channel *ch, u32 flags, void *payload, | |||
1438 | msg->hdr.msg_slot_number = msg_slot->msg_slot_number; | 1569 | msg->hdr.msg_slot_number = msg_slot->msg_slot_number; |
1439 | memcpy(&msg->payload, payload, payload_size); | 1570 | memcpy(&msg->payload, payload, payload_size); |
1440 | 1571 | ||
1441 | ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg, msg_size); | 1572 | ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg, |
1573 | msg_size); | ||
1442 | if (ret == xpSuccess) | 1574 | if (ret == xpSuccess) |
1443 | goto out_1; | 1575 | goto out_1; |
1444 | 1576 | ||
@@ -1529,7 +1661,7 @@ xpc_received_payload_uv(struct xpc_channel *ch, void *payload) | |||
1529 | msg->hdr.partid = xp_partition_id; | 1661 | msg->hdr.partid = xp_partition_id; |
1530 | msg->hdr.size = 0; /* size of zero indicates this is an ACK */ | 1662 | msg->hdr.size = 0; /* size of zero indicates this is an ACK */ |
1531 | 1663 | ||
1532 | ret = xpc_send_gru_msg(ch->sn.uv.remote_notify_mq_gpa, msg, | 1664 | ret = xpc_send_gru_msg(ch->sn.uv.cached_notify_gru_mq_desc, msg, |
1533 | sizeof(struct xpc_notify_mq_msghdr_uv)); | 1665 | sizeof(struct xpc_notify_mq_msghdr_uv)); |
1534 | if (ret != xpSuccess) | 1666 | if (ret != xpSuccess) |
1535 | XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret); | 1667 | XPC_DEACTIVATE_PARTITION(&xpc_partitions[ch->partid], ret); |
@@ -1541,6 +1673,7 @@ int | |||
1541 | xpc_init_uv(void) | 1673 | xpc_init_uv(void) |
1542 | { | 1674 | { |
1543 | xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv; | 1675 | xpc_setup_partitions_sn = xpc_setup_partitions_sn_uv; |
1676 | xpc_teardown_partitions_sn = xpc_teardown_partitions_sn_uv; | ||
1544 | xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; | 1677 | xpc_process_activate_IRQ_rcvd = xpc_process_activate_IRQ_rcvd_uv; |
1545 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; | 1678 | xpc_get_partition_rsvd_page_pa = xpc_get_partition_rsvd_page_pa_uv; |
1546 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; | 1679 | xpc_setup_rsvd_page_sn = xpc_setup_rsvd_page_sn_uv; |