aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2006-02-15 09:02:21 -0500
committerTony Luck <tony.luck@intel.com>2006-02-15 16:35:03 -0500
commit4c2cd96696ae0896ce4bcf725b9f0eaffafeb640 (patch)
tree12b7d967d677e8e8ea154b0b4ae957df6cc43e39
parentc2a4969ba14e852bf4ee92c7db3b0cf82405a0c9 (diff)
[IA64-SGI] enforce proper ordering of callouts by XPC
Fix XPC so that it does not deliver any messages until the connected callout has returned, as well as, prevent the disconnected callout to occur before the disconnecting callout has returned. Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c8
-rw-r--r--arch/ia64/sn/kernel/xpc_main.c20
-rw-r--r--include/asm-ia64/sn/xpc.h31
3 files changed, 36 insertions, 23 deletions
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 36e5437a0fb6..cdf6856ce089 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -738,7 +738,9 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
738 738
739 /* make sure all activity has settled down first */ 739 /* make sure all activity has settled down first */
740 740
741 if (atomic_read(&ch->references) > 0) { 741 if (atomic_read(&ch->references) > 0 ||
742 ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
743 !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) {
742 return; 744 return;
743 } 745 }
744 DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); 746 DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
@@ -775,7 +777,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
775 777
776 /* both sides are disconnected now */ 778 /* both sides are disconnected now */
777 779
778 if (ch->flags & XPC_C_CONNECTCALLOUT) { 780 if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
779 spin_unlock_irqrestore(&ch->lock, *irq_flags); 781 spin_unlock_irqrestore(&ch->lock, *irq_flags);
780 xpc_disconnect_callout(ch, xpcDisconnected); 782 xpc_disconnect_callout(ch, xpcDisconnected);
781 spin_lock_irqsave(&ch->lock, *irq_flags); 783 spin_lock_irqsave(&ch->lock, *irq_flags);
@@ -1300,7 +1302,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
1300 "delivered=%d, partid=%d, channel=%d\n", 1302 "delivered=%d, partid=%d, channel=%d\n",
1301 nmsgs_sent, ch->partid, ch->number); 1303 nmsgs_sent, ch->partid, ch->number);
1302 1304
1303 if (ch->flags & XPC_C_CONNECTCALLOUT) { 1305 if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
1304 xpc_activate_kthreads(ch, nmsgs_sent); 1306 xpc_activate_kthreads(ch, nmsgs_sent);
1305 } 1307 }
1306 } 1308 }
diff --git a/arch/ia64/sn/kernel/xpc_main.c b/arch/ia64/sn/kernel/xpc_main.c
index 9cd460dfe27e..8cbf16432570 100644
--- a/arch/ia64/sn/kernel/xpc_main.c
+++ b/arch/ia64/sn/kernel/xpc_main.c
@@ -750,12 +750,16 @@ xpc_daemonize_kthread(void *args)
750 /* let registerer know that connection has been established */ 750 /* let registerer know that connection has been established */
751 751
752 spin_lock_irqsave(&ch->lock, irq_flags); 752 spin_lock_irqsave(&ch->lock, irq_flags);
753 if (!(ch->flags & XPC_C_CONNECTCALLOUT)) { 753 if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
754 ch->flags |= XPC_C_CONNECTCALLOUT; 754 ch->flags |= XPC_C_CONNECTEDCALLOUT;
755 spin_unlock_irqrestore(&ch->lock, irq_flags); 755 spin_unlock_irqrestore(&ch->lock, irq_flags);
756 756
757 xpc_connected_callout(ch); 757 xpc_connected_callout(ch);
758 758
759 spin_lock_irqsave(&ch->lock, irq_flags);
760 ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
761 spin_unlock_irqrestore(&ch->lock, irq_flags);
762
759 /* 763 /*
760 * It is possible that while the callout was being 764 * It is possible that while the callout was being
761 * made that the remote partition sent some messages. 765 * made that the remote partition sent some messages.
@@ -777,15 +781,17 @@ xpc_daemonize_kthread(void *args)
777 781
778 if (atomic_dec_return(&ch->kthreads_assigned) == 0) { 782 if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
779 spin_lock_irqsave(&ch->lock, irq_flags); 783 spin_lock_irqsave(&ch->lock, irq_flags);
780 if ((ch->flags & XPC_C_CONNECTCALLOUT) && 784 if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
781 !(ch->flags & XPC_C_DISCONNECTCALLOUT)) { 785 !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
782 ch->flags |= XPC_C_DISCONNECTCALLOUT; 786 ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
783 spin_unlock_irqrestore(&ch->lock, irq_flags); 787 spin_unlock_irqrestore(&ch->lock, irq_flags);
784 788
785 xpc_disconnect_callout(ch, xpcDisconnecting); 789 xpc_disconnect_callout(ch, xpcDisconnecting);
786 } else { 790
787 spin_unlock_irqrestore(&ch->lock, irq_flags); 791 spin_lock_irqsave(&ch->lock, irq_flags);
792 ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
788 } 793 }
794 spin_unlock_irqrestore(&ch->lock, irq_flags);
789 if (atomic_dec_return(&part->nchannels_engaged) == 0) { 795 if (atomic_dec_return(&part->nchannels_engaged) == 0) {
790 xpc_mark_partition_disengaged(part); 796 xpc_mark_partition_disengaged(part);
791 xpc_IPI_send_disengage(part); 797 xpc_IPI_send_disengage(part);
diff --git a/include/asm-ia64/sn/xpc.h b/include/asm-ia64/sn/xpc.h
index 0c36928ffd8b..df7f5f4f3cde 100644
--- a/include/asm-ia64/sn/xpc.h
+++ b/include/asm-ia64/sn/xpc.h
@@ -508,19 +508,24 @@ struct xpc_channel {
508#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */ 508#define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */
509 509
510#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */ 510#define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */
511#define XPC_C_CONNECTCALLOUT 0x00000040 /* channel connected callout made */ 511#define XPC_C_CONNECTEDCALLOUT 0x00000040 /* connected callout initiated */
512#define XPC_C_CONNECTED 0x00000080 /* local channel is connected */ 512#define XPC_C_CONNECTEDCALLOUT_MADE \
513#define XPC_C_CONNECTING 0x00000100 /* channel is being connected */ 513 0x00000080 /* connected callout completed */
514 514#define XPC_C_CONNECTED 0x00000100 /* local channel is connected */
515#define XPC_C_RCLOSEREPLY 0x00000200 /* remote close channel reply */ 515#define XPC_C_CONNECTING 0x00000200 /* channel is being connected */
516#define XPC_C_CLOSEREPLY 0x00000400 /* local close channel reply */ 516
517#define XPC_C_RCLOSEREQUEST 0x00000800 /* remote close channel request */ 517#define XPC_C_RCLOSEREPLY 0x00000400 /* remote close channel reply */
518#define XPC_C_CLOSEREQUEST 0x00001000 /* local close channel request */ 518#define XPC_C_CLOSEREPLY 0x00000800 /* local close channel reply */
519 519#define XPC_C_RCLOSEREQUEST 0x00001000 /* remote close channel request */
520#define XPC_C_DISCONNECTED 0x00002000 /* channel is disconnected */ 520#define XPC_C_CLOSEREQUEST 0x00002000 /* local close channel request */
521#define XPC_C_DISCONNECTING 0x00004000 /* channel is being disconnected */ 521
522#define XPC_C_DISCONNECTCALLOUT 0x00008000 /* chan disconnected callout made */ 522#define XPC_C_DISCONNECTED 0x00004000 /* channel is disconnected */
523#define XPC_C_WDISCONNECT 0x00010000 /* waiting for channel disconnect */ 523#define XPC_C_DISCONNECTING 0x00008000 /* channel is being disconnected */
524#define XPC_C_DISCONNECTINGCALLOUT \
525 0x00010000 /* disconnecting callout initiated */
526#define XPC_C_DISCONNECTINGCALLOUT_MADE \
527 0x00020000 /* disconnecting callout completed */
528#define XPC_C_WDISCONNECT 0x00040000 /* waiting for channel disconnect */
524 529
525 530
526 531