diff options
author | Dean Nelson <dcn@sgi.com> | 2005-10-25 15:07:43 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-10-25 19:27:37 -0400 |
commit | e54af724c1ae3530c95135157776c9be65cdb747 (patch) | |
tree | 99623edaf5d8fb34c8b43cbd19cf3d7b47d8b8f8 /arch/ia64/sn/kernel/xpc_channel.c | |
parent | a607c38971fd078865fa9bef39e6c1d4435680c8 (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.c | 117 |
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 | ||
830 | again: | ||
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(®istration->sema) != 0) { | 1089 | if (down_trylock(®istration->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) | |||
1467 | void | 1521 | void |
1468 | xpc_connected_callout(struct xpc_channel *ch) | 1522 | xpc_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 | ||