[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 738 739 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 744 return; 743 745 } 744 746 DBUG_ON(atomic_read(&ch->kthreads_assigned) != 0); ··· 777 775 778 776 /* both sides are disconnected now */ 779 777 780 - if (ch->flags & XPC_C_CONNECTCALLOUT) { 778 + if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) { 781 779 spin_unlock_irqrestore(&ch->lock, *irq_flags); 782 780 xpc_disconnect_callout(ch, xpcDisconnected); 783 781 spin_lock_irqsave(&ch->lock, *irq_flags); ··· 1302 1300 "delivered=%d, partid=%d, channel=%d\n", 1303 1301 nmsgs_sent, ch->partid, ch->number); 1304 1302 1305 - if (ch->flags & XPC_C_CONNECTCALLOUT) { 1303 + if (ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) { 1306 1304 xpc_activate_kthreads(ch, nmsgs_sent); 1307 1305 } 1308 1306 }
+13 -7
arch/ia64/sn/kernel/xpc_main.c
··· 750 750 /* let registerer know that connection has been established */ 751 751 752 752 spin_lock_irqsave(&ch->lock, irq_flags); 753 - if (!(ch->flags & XPC_C_CONNECTCALLOUT)) { 754 - ch->flags |= XPC_C_CONNECTCALLOUT; 753 + if (!(ch->flags & XPC_C_CONNECTEDCALLOUT)) { 754 + ch->flags |= XPC_C_CONNECTEDCALLOUT; 755 755 spin_unlock_irqrestore(&ch->lock, irq_flags); 756 756 757 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); 758 762 759 763 /* 760 764 * It is possible that while the callout was being ··· 781 777 782 778 if (atomic_dec_return(&ch->kthreads_assigned) == 0) { 783 779 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; 780 + if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && 781 + !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { 782 + ch->flags |= XPC_C_DISCONNECTINGCALLOUT; 787 783 spin_unlock_irqrestore(&ch->lock, irq_flags); 788 784 789 785 xpc_disconnect_callout(ch, xpcDisconnecting); 790 - } else { 791 - spin_unlock_irqrestore(&ch->lock, irq_flags); 786 + 787 + spin_lock_irqsave(&ch->lock, irq_flags); 788 + ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; 792 789 } 790 + spin_unlock_irqrestore(&ch->lock, irq_flags); 793 791 if (atomic_dec_return(&part->nchannels_engaged) == 0) { 794 792 xpc_mark_partition_disengaged(part); 795 793 xpc_IPI_send_disengage(part);
+16 -11
include/asm-ia64/sn/xpc.h
··· 508 508 #define XPC_C_OPENREQUEST 0x00000010 /* local open channel request */ 509 509 510 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 */ 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 */ 514 516 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 */ 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 */ 519 521 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 */ 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 */ 524 529 525 530 526 531