aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/xpc_channel.c
diff options
context:
space:
mode:
authorDean Nelson <dcn@sgi.com>2005-10-25 15:07:43 -0400
committerTony Luck <tony.luck@intel.com>2005-10-25 19:27:37 -0400
commite54af724c1ae3530c95135157776c9be65cdb747 (patch)
tree99623edaf5d8fb34c8b43cbd19cf3d7b47d8b8f8 /arch/ia64/sn/kernel/xpc_channel.c
parenta607c38971fd078865fa9bef39e6c1d4435680c8 (diff)
[IA64-SGI] fixes for XPC disengage and open/close protocol
This patch addresses a few issues with the open/close protocol that were revealed by the newly added disengage functionality combined with more extensive testing. Signed-off-by: Dean Nelson <dcn@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/sn/kernel/xpc_channel.c')
-rw-r--r--arch/ia64/sn/kernel/xpc_channel.c117
1 files changed, 82 insertions, 35 deletions
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 195ac1b8e262..abf4fc2a87bb 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -792,11 +792,20 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags)
792 "reason=%d\n", ch->number, ch->partid, ch->reason); 792 "reason=%d\n", ch->number, ch->partid, ch->reason);
793 } 793 }
794 794
795 /* wake the thread that is waiting for this channel to disconnect */
796 if (ch->flags & XPC_C_WDISCONNECT) { 795 if (ch->flags & XPC_C_WDISCONNECT) {
797 spin_unlock_irqrestore(&ch->lock, *irq_flags); 796 spin_unlock_irqrestore(&ch->lock, *irq_flags);
798 up(&ch->wdisconnect_sema); 797 up(&ch->wdisconnect_sema);
799 spin_lock_irqsave(&ch->lock, *irq_flags); 798 spin_lock_irqsave(&ch->lock, *irq_flags);
799
800 } else if (ch->delayed_IPI_flags) {
801 if (part->act_state != XPC_P_DEACTIVATING) {
802 /* time to take action on any delayed IPI flags */
803 spin_lock(&part->IPI_lock);
804 XPC_SET_IPI_FLAGS(part->local_IPI_amo, ch->number,
805 ch->delayed_IPI_flags);
806 spin_unlock(&part->IPI_lock);
807 }
808 ch->delayed_IPI_flags = 0;
800 } 809 }
801} 810}
802 811
@@ -818,6 +827,19 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
818 827
819 spin_lock_irqsave(&ch->lock, irq_flags); 828 spin_lock_irqsave(&ch->lock, irq_flags);
820 829
830again:
831
832 if ((ch->flags & XPC_C_DISCONNECTED) &&
833 (ch->flags & XPC_C_WDISCONNECT)) {
834 /*
835 * Delay processing IPI flags until thread waiting disconnect
836 * has had a chance to see that the channel is disconnected.
837 */
838 ch->delayed_IPI_flags |= IPI_flags;
839 spin_unlock_irqrestore(&ch->lock, irq_flags);
840 return;
841 }
842
821 843
822 if (IPI_flags & XPC_IPI_CLOSEREQUEST) { 844 if (IPI_flags & XPC_IPI_CLOSEREQUEST) {
823 845
@@ -843,14 +865,22 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
843 865
844 /* both sides have finished disconnecting */ 866 /* both sides have finished disconnecting */
845 xpc_process_disconnect(ch, &irq_flags); 867 xpc_process_disconnect(ch, &irq_flags);
868 DBUG_ON(!(ch->flags & XPC_C_DISCONNECTED));
869 goto again;
846 } 870 }
847 871
848 if (ch->flags & XPC_C_DISCONNECTED) { 872 if (ch->flags & XPC_C_DISCONNECTED) {
849 // >>> explain this section
850
851 if (!(IPI_flags & XPC_IPI_OPENREQUEST)) { 873 if (!(IPI_flags & XPC_IPI_OPENREQUEST)) {
852 DBUG_ON(part->act_state != 874 if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo,
853 XPC_P_DEACTIVATING); 875 ch_number) & XPC_IPI_OPENREQUEST)) {
876
877 DBUG_ON(ch->delayed_IPI_flags != 0);
878 spin_lock(&part->IPI_lock);
879 XPC_SET_IPI_FLAGS(part->local_IPI_amo,
880 ch_number,
881 XPC_IPI_CLOSEREQUEST);
882 spin_unlock(&part->IPI_lock);
883 }
854 spin_unlock_irqrestore(&ch->lock, irq_flags); 884 spin_unlock_irqrestore(&ch->lock, irq_flags);
855 return; 885 return;
856 } 886 }
@@ -880,9 +910,13 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
880 } 910 }
881 911
882 XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags); 912 XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags);
883 } else { 913
884 xpc_process_disconnect(ch, &irq_flags); 914 DBUG_ON(IPI_flags & XPC_IPI_CLOSEREPLY);
915 spin_unlock_irqrestore(&ch->lock, irq_flags);
916 return;
885 } 917 }
918
919 xpc_process_disconnect(ch, &irq_flags);
886 } 920 }
887 921
888 922
@@ -898,7 +932,20 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
898 } 932 }
899 933
900 DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST)); 934 DBUG_ON(!(ch->flags & XPC_C_CLOSEREQUEST));
901 DBUG_ON(!(ch->flags & XPC_C_RCLOSEREQUEST)); 935
936 if (!(ch->flags & XPC_C_RCLOSEREQUEST)) {
937 if ((XPC_GET_IPI_FLAGS(part->local_IPI_amo, ch_number)
938 & XPC_IPI_CLOSEREQUEST)) {
939
940 DBUG_ON(ch->delayed_IPI_flags != 0);
941 spin_lock(&part->IPI_lock);
942 XPC_SET_IPI_FLAGS(part->local_IPI_amo,
943 ch_number, XPC_IPI_CLOSEREPLY);
944 spin_unlock(&part->IPI_lock);
945 }
946 spin_unlock_irqrestore(&ch->lock, irq_flags);
947 return;
948 }
902 949
903 ch->flags |= XPC_C_RCLOSEREPLY; 950 ch->flags |= XPC_C_RCLOSEREPLY;
904 951
@@ -916,8 +963,14 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
916 "channel=%d\n", args->msg_size, args->local_nentries, 963 "channel=%d\n", args->msg_size, args->local_nentries,
917 ch->partid, ch->number); 964 ch->partid, ch->number);
918 965
919 if ((ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) || 966 if (part->act_state == XPC_P_DEACTIVATING ||
920 part->act_state == XPC_P_DEACTIVATING) { 967 (ch->flags & XPC_C_ROPENREQUEST)) {
968 spin_unlock_irqrestore(&ch->lock, irq_flags);
969 return;
970 }
971
972 if (ch->flags & (XPC_C_DISCONNECTING | XPC_C_WDISCONNECT)) {
973 ch->delayed_IPI_flags |= XPC_IPI_OPENREQUEST;
921 spin_unlock_irqrestore(&ch->lock, irq_flags); 974 spin_unlock_irqrestore(&ch->lock, irq_flags);
922 return; 975 return;
923 } 976 }
@@ -931,8 +984,11 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
931 * msg_size = size of channel's messages in bytes 984 * msg_size = size of channel's messages in bytes
932 * local_nentries = remote partition's local_nentries 985 * local_nentries = remote partition's local_nentries
933 */ 986 */
934 DBUG_ON(args->msg_size == 0); 987 if (args->msg_size == 0 || args->local_nentries == 0) {
935 DBUG_ON(args->local_nentries == 0); 988 /* assume OPENREQUEST was delayed by mistake */
989 spin_unlock_irqrestore(&ch->lock, irq_flags);
990 return;
991 }
936 992
937 ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING); 993 ch->flags |= (XPC_C_ROPENREQUEST | XPC_C_CONNECTING);
938 ch->remote_nentries = args->local_nentries; 994 ch->remote_nentries = args->local_nentries;
@@ -970,7 +1026,13 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number,
970 spin_unlock_irqrestore(&ch->lock, irq_flags); 1026 spin_unlock_irqrestore(&ch->lock, irq_flags);
971 return; 1027 return;
972 } 1028 }
973 DBUG_ON(!(ch->flags & XPC_C_OPENREQUEST)); 1029 if (!(ch->flags & XPC_C_OPENREQUEST)) {
1030 XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError,
1031 &irq_flags);
1032 spin_unlock_irqrestore(&ch->lock, irq_flags);
1033 return;
1034 }
1035
974 DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST)); 1036 DBUG_ON(!(ch->flags & XPC_C_ROPENREQUEST));
975 DBUG_ON(ch->flags & XPC_C_CONNECTED); 1037 DBUG_ON(ch->flags & XPC_C_CONNECTED);
976 1038
@@ -1024,8 +1086,8 @@ xpc_connect_channel(struct xpc_channel *ch)
1024 struct xpc_registration *registration = &xpc_registrations[ch->number]; 1086 struct xpc_registration *registration = &xpc_registrations[ch->number];
1025 1087
1026 1088
1027 if (down_interruptible(&registration->sema) != 0) { 1089 if (down_trylock(&registration->sema) != 0) {
1028 return xpcInterrupted; 1090 return xpcRetry;
1029 } 1091 }
1030 1092
1031 if (!XPC_CHANNEL_REGISTERED(ch->number)) { 1093 if (!XPC_CHANNEL_REGISTERED(ch->number)) {
@@ -1445,19 +1507,11 @@ xpc_initiate_connect(int ch_number)
1445 if (xpc_part_ref(part)) { 1507 if (xpc_part_ref(part)) {
1446 ch = &part->channels[ch_number]; 1508 ch = &part->channels[ch_number];
1447 1509
1448 if (!(ch->flags & XPC_C_DISCONNECTING)) { 1510 /*
1449 DBUG_ON(ch->flags & XPC_C_OPENREQUEST); 1511 * Initiate the establishment of a connection on the
1450 DBUG_ON(ch->flags & XPC_C_CONNECTED); 1512 * newly registered channel to the remote partition.
1451 DBUG_ON(ch->flags & XPC_C_SETUP); 1513 */
1452 1514 xpc_wakeup_channel_mgr(part);
1453 /*
1454 * Initiate the establishment of a connection
1455 * on the newly registered channel to the
1456 * remote partition.
1457 */
1458 xpc_wakeup_channel_mgr(part);
1459 }
1460
1461 xpc_part_deref(part); 1515 xpc_part_deref(part);
1462 } 1516 }
1463 } 1517 }
@@ -1467,9 +1521,6 @@ xpc_initiate_connect(int ch_number)
1467void 1521void
1468xpc_connected_callout(struct xpc_channel *ch) 1522xpc_connected_callout(struct xpc_channel *ch)
1469{ 1523{
1470 unsigned long irq_flags;
1471
1472
1473 /* let the registerer know that a connection has been established */ 1524 /* let the registerer know that a connection has been established */
1474 1525
1475 if (ch->func != NULL) { 1526 if (ch->func != NULL) {
@@ -1482,10 +1533,6 @@ xpc_connected_callout(struct xpc_channel *ch)
1482 dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, " 1533 dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, "
1483 "partid=%d, channel=%d\n", ch->partid, ch->number); 1534 "partid=%d, channel=%d\n", ch->partid, ch->number);
1484 } 1535 }
1485
1486 spin_lock_irqsave(&ch->lock, irq_flags);
1487 ch->flags |= XPC_C_CONNECTCALLOUT;
1488 spin_unlock_irqrestore(&ch->lock, irq_flags);
1489} 1536}
1490 1537
1491 1538