[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>

authored by Dean Nelson and committed by Tony Luck 4c2cd966 c2a4969b

+34 -21
+5 -3
arch/ia64/sn/kernel/xpc_channel.c
··· 738 739 /* make sure all activity has settled down first */ 740 741 - if (atomic_read(&ch->references) > 0) { 742 return; 743 } 744 DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); ··· 777 778 /* both sides are disconnected now */ 779 780 - if (ch->flags & XPC_C_CONNECTCALLOUT) { 781 spin_unlock_irqrestore(&ch->lock, *irq_flags); 782 xpc_disconnect_callout(ch, xpcDisconnected); 783 spin_lock_irqsave(&ch->lock, *irq_flags); ··· 1302 "delivered=%d, partid=%d, channel=%d\n", 1303 nmsgs_sent, ch->partid, ch->number); 1304 1305 - if (ch->flags & XPC_C_CONNECTCALLOUT) { 1306 xpc_activate_kthreads(ch, nmsgs_sent); 1307 } 1308 }
··· 738 739 /* make sure all activity has settled down first */ 740 741 + if (atomic_read(&ch->references) > 0 || 742 + ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && 743 + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE))) { 744 return; 745 } 746 DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); ··· 775 776 /* both sides are disconnected now */ 777 778 + if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) { 779 spin_unlock_irqrestore(&ch->lock, *irq_flags); 780 xpc_disconnect_callout(ch, xpcDisconnected); 781 spin_lock_irqsave(&ch->lock, *irq_flags); ··· 1300 "delivered=%d, partid=%d, channel=%d\n", 1301 nmsgs_sent, ch->partid, ch->number); 1302 1303 + if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) { 1304 xpc_activate_kthreads(ch, nmsgs_sent); 1305 } 1306 }
+13 -7
arch/ia64/sn/kernel/xpc_main.c
··· 750 /* let registerer know that connection has been established */ 751 752 spin_lock_irqsave(&ch->lock, irq_flags); 753 - if (!(ch->flags & XPC_C_CONNECTCALLOUT)) { 754 - ch->flags |= XPC_C_CONNECTCALLOUT; 755 spin_unlock_irqrestore(&ch->lock, irq_flags); 756 757 xpc_connected_callout(ch); 758 759 /* 760 * It is possible that while the callout was being ··· 781 782 if (atomic_dec_return(&ch->kthreads_assigned) == 0) { 783 spin_lock_irqsave(&ch->lock, irq_flags); 784 - if ((ch->flags & XPC_C_CONNECTCALLOUT) && 785 - !(ch->flags & XPC_C_DISCONNECTCALLOUT)) { 786 - ch->flags |= XPC_C_DISCONNECTCALLOUT; 787 spin_unlock_irqrestore(&ch->lock, irq_flags); 788 789 xpc_disconnect_callout(ch, xpcDisconnecting); 790 - } else { 791 - spin_unlock_irqrestore(&ch->lock, irq_flags); 792 } 793 if (atomic_dec_return(&part->nchannels_engaged) == 0) { 794 xpc_mark_partition_disengaged(part); 795 xpc_IPI_send_disengage(part);
··· 750 /* let registerer know that connection has been established */ 751 752 spin_lock_irqsave(&ch->lock, irq_flags); 753 + if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { 754 + ch->flags |= XPC_C_CONNECTEDCALLOUT; 755 spin_unlock_irqrestore(&ch->lock, irq_flags); 756 757 xpc_connected_callout(ch); 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 763 /* 764 * It is possible that while the callout was being ··· 777 778 if (atomic_dec_return(&ch->kthreads_assigned) == 0) { 779 spin_lock_irqsave(&ch->lock, irq_flags); 780 + if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && 781 + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { 782 + ch->flags |= XPC_C_DISCONNECTINGCALLOUT; 783 spin_unlock_irqrestore(&ch->lock, irq_flags); 784 785 xpc_disconnect_callout(ch, xpcDisconnecting); 786 + 787 + spin_lock_irqsave(&ch->lock, irq_flags); 788 + ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; 789 } 790 + spin_unlock_irqrestore(&ch->lock, irq_flags); 791 if (atomic_dec_return(&part->nchannels_engaged) == 0) { 792 xpc_mark_partition_disengaged(part); 793 xpc_IPI_send_disengage(part);
+16 -11
include/asm-ia64/sn/xpc.h
··· 508 #define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */ 509 510 #define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */ 511 - #define XPC_C_CONNECTCALLOUT 0x00000040 /* channel connected callout made */ 512 - #define XPC_C_CONNECTED 0x00000080 /* local channel is connected */ 513 - #define XPC_C_CONNECTING 0x00000100 /* channel is being connected */ 514 515 - #define XPC_C_RCLOSEREPLY 0x00000200 /* remote close channel reply */ 516 - #define XPC_C_CLOSEREPLY 0x00000400 /* local close channel reply */ 517 - #define XPC_C_RCLOSEREQUEST 0x00000800 /* remote close channel request */ 518 - #define XPC_C_CLOSEREQUEST 0x00001000 /* local close channel request */ 519 520 - #define XPC_C_DISCONNECTED 0x00002000 /* channel is disconnected */ 521 - #define XPC_C_DISCONNECTING 0x00004000 /* channel is being disconnected */ 522 - #define XPC_C_DISCONNECTCALLOUT 0x00008000 /* chan disconnected callout made */ 523 - #define XPC_C_WDISCONNECT 0x00010000 /* waiting for channel disconnect */ 524 525 526
··· 508 #define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */ 509 510 #define XPC_C_SETUP 0x00000020 /* channel's msgqueues are alloc'd */ 511 + #define XPC_C_CONNECTEDCALLOUT 0x00000040 /* connected callout initiated */ 512 + #define XPC_C_CONNECTEDCALLOUT_MADE \ 513 + 0x00000080 /* connected callout completed */ 514 + #define XPC_C_CONNECTED 0x00000100 /* local channel is connected */ 515 + #define XPC_C_CONNECTING 0x00000200 /* channel is being connected */ 516 517 + #define XPC_C_RCLOSEREPLY 0x00000400 /* remote close channel reply */ 518 + #define XPC_C_CLOSEREPLY 0x00000800 /* local close channel reply */ 519 + #define XPC_C_RCLOSEREQUEST 0x00001000 /* remote close channel request */ 520 + #define XPC_C_CLOSEREQUEST 0x00002000 /* local close channel request */ 521 522 + #define XPC_C_DISCONNECTED 0x00004000 /* channel is disconnected */ 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 */ 529 530 531