[IA64-SGI] enforce proper ordering of callouts by XPC
authorDean Nelson <dcn@sgi.com>
Wed, 15 Feb 2006 14:02:21 +0000 (08:02 -0600)
committerTony Luck <tony.luck@intel.com>
Wed, 15 Feb 2006 21:35:03 +0000 (13:35 -0800)
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>
arch/ia64/sn/kernel/xpc_channel.c
arch/ia64/sn/kernel/xpc_main.c
include/asm-ia64/sn/xpc.h

index 36e5437a0fb6bdc281e104340b4b9ec8f4358a3a..cdf6856ce089c07c4344f6150439e1bd4ef29523 100644 (file)
@@ -738,7 +738,9 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
 
        /* make sure all activity has settled down first */
 
-       if (atomic_read(&ch->references) > 0) {
+       if (atomic_read(&ch->references) > 0 ||
+                       ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+                       !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) {
                return;
        }
        DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0);
@@ -775,7 +777,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
 
        /* both sides are disconnected now */
 
-       if (ch->flags & XPC_C_CONNECTCALLOUT) {
+       if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) {
                spin_unlock_irqrestore(&ch->lock, *irq_flags);
                xpc_disconnect_callout(ch, xpcDisconnected);
                spin_lock_irqsave(&ch->lock, *irq_flags);
@@ -1300,7 +1302,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number)
                                "delivered=%d, partid=%d, channel=%d\n",
                                nmsgs_sent, ch->partid, ch->number);
 
-                       if (ch->flags & XPC_C_CONNECTCALLOUT) {
+                       if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) {
                                xpc_activate_kthreads(ch, nmsgs_sent);
                        }
                }
index 9cd460dfe27ef71b0e0a1517114b54812b490c54..8cbf164325703048ecd277ebf141efb432e8b075 100644 (file)
@@ -750,12 +750,16 @@ xpc_daemonize_kthread(void *args)
                /* let registerer know that connection has been established */
 
                spin_lock_irqsave(&ch->lock, irq_flags);
-               if (!(ch->flags & XPC_C_CONNECTCALLOUT)) {
-                       ch->flags |= XPC_C_CONNECTCALLOUT;
+               if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) {
+                       ch->flags |= XPC_C_CONNECTEDCALLOUT;
                        spin_unlock_irqrestore(&ch->lock, irq_flags);
 
                        xpc_connected_callout(ch);
 
+                       spin_lock_irqsave(&ch->lock, irq_flags);
+                       ch->flags |= XPC_C_CONNECTEDCALLOUT_MADE;
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
                        /*
                         * It is possible that while the callout was being
                         * made that the remote partition sent some messages.
@@ -777,15 +781,17 @@ xpc_daemonize_kthread(void *args)
 
        if (atomic_dec_return(&ch->kthreads_assigned) == 0) {
                spin_lock_irqsave(&ch->lock, irq_flags);
-               if ((ch->flags & XPC_C_CONNECTCALLOUT) &&
-                               !(ch->flags & XPC_C_DISCONNECTCALLOUT)) {
-                       ch->flags |= XPC_C_DISCONNECTCALLOUT;
+               if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) &&
+                               !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) {
+                       ch->flags |= XPC_C_DISCONNECTINGCALLOUT;
                        spin_unlock_irqrestore(&ch->lock, irq_flags);
 
                        xpc_disconnect_callout(ch, xpcDisconnecting);
-               } else {
-                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+                       spin_lock_irqsave(&ch->lock, irq_flags);
+                       ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE;
                }
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
                if (atomic_dec_return(&part->nchannels_engaged) == 0) {
                        xpc_mark_partition_disengaged(part);
                        xpc_IPI_send_disengage(part);
index 0c36928ffd8b56c1e67ff1090124b8b902be126c..df7f5f4f3cde2d7e68f8360ca771554c0039227e 100644 (file)
@@ -508,19 +508,24 @@ struct xpc_channel {
 #define        XPC_C_OPENREQUEST       0x00000010 /* local open channel request */
 
 #define        XPC_C_SETUP             0x00000020 /* channel's msgqueues are alloc'd */
-#define        XPC_C_CONNECTCALLOUT    0x00000040 /* channel connected callout made */
-#define        XPC_C_CONNECTED         0x00000080 /* local channel is connected */
-#define        XPC_C_CONNECTING        0x00000100 /* channel is being connected */
-
-#define        XPC_C_RCLOSEREPLY       0x00000200 /* remote close channel reply */
-#define        XPC_C_CLOSEREPLY        0x00000400 /* local close channel reply */
-#define        XPC_C_RCLOSEREQUEST     0x00000800 /* remote close channel request */
-#define        XPC_C_CLOSEREQUEST      0x00001000 /* local close channel request */
-
-#define        XPC_C_DISCONNECTED      0x00002000 /* channel is disconnected */
-#define        XPC_C_DISCONNECTING     0x00004000 /* channel is being disconnected */
-#define        XPC_C_DISCONNECTCALLOUT 0x00008000 /* chan disconnected callout made */
-#define        XPC_C_WDISCONNECT       0x00010000 /* waiting for channel disconnect */
+#define        XPC_C_CONNECTEDCALLOUT  0x00000040 /* connected callout initiated */
+#define        XPC_C_CONNECTEDCALLOUT_MADE \
+                               0x00000080 /* connected callout completed */
+#define        XPC_C_CONNECTED         0x00000100 /* local channel is connected */
+#define        XPC_C_CONNECTING        0x00000200 /* channel is being connected */
+
+#define        XPC_C_RCLOSEREPLY       0x00000400 /* remote close channel reply */
+#define        XPC_C_CLOSEREPLY        0x00000800 /* local close channel reply */
+#define        XPC_C_RCLOSEREQUEST     0x00001000 /* remote close channel request */
+#define        XPC_C_CLOSEREQUEST      0x00002000 /* local close channel request */
+
+#define        XPC_C_DISCONNECTED      0x00004000 /* channel is disconnected */
+#define        XPC_C_DISCONNECTING     0x00008000 /* channel is being disconnected */
+#define        XPC_C_DISCONNECTINGCALLOUT \
+                               0x00010000 /* disconnecting callout initiated */
+#define        XPC_C_DISCONNECTINGCALLOUT_MADE \
+                               0x00020000 /* disconnecting callout completed */
+#define        XPC_C_WDISCONNECT       0x00040000 /* waiting for channel disconnect */