[DAPL2] DAPL Counters & 2.0.3 extensions to support counter retrieval.
[mirror/winof/.git] / ulp / dapl2 / dapl / common / dapl_ep_disconnect.c
1 /*\r
2  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
3  *\r
4  * This Software is licensed under one of the following licenses:\r
5  *\r
6  * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
7  *    available from the Open Source Initiative, see\r
8  *    http://www.opensource.org/licenses/cpl.php.\r
9  *\r
10  * 2) under the terms of the "The BSD License" a copy of which is\r
11  *    available from the Open Source Initiative, see\r
12  *    http://www.opensource.org/licenses/bsd-license.php.\r
13  *\r
14  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
15  *    copy of which is available from the Open Source Initiative, see\r
16  *    http://www.opensource.org/licenses/gpl-license.php.\r
17  *\r
18  * Licensee has the right to choose one of the above licenses.\r
19  *\r
20  * Redistributions of source code must retain the above copyright\r
21  * notice and one of the license notices.\r
22  *\r
23  * Redistributions in binary form must reproduce both the above copyright\r
24  * notice, one of the license notices in the documentation\r
25  * and/or other materials provided with the distribution.\r
26  */\r
27 \r
28 /**********************************************************************\r
29  *\r
30  * MODULE: dapl_ep_disconnect.c\r
31  *\r
32  * PURPOSE: Endpoint management\r
33  * Description: Interfaces in this file are completely described in\r
34  *              the DAPL 1.1 API, Chapter 6, section 5\r
35  *\r
36  * $Id:$\r
37  **********************************************************************/\r
38 \r
39 #include "dapl.h"\r
40 #include "dapl_ia_util.h"\r
41 #include "dapl_ep_util.h"\r
42 #include "dapl_sp_util.h"\r
43 #include "dapl_evd_util.h"\r
44 #include "dapl_adapter_util.h"\r
45 \r
46 /*\r
47  * dapl_ep_disconnect\r
48  *\r
49  * DAPL Requirements Version xxx, 6.5.9\r
50  *\r
51  * Terminate a connection.\r
52  *\r
53  * Input:\r
54  *      ep_handle\r
55  *      disconnect_flags\r
56  *\r
57  * Output:\r
58  *      None\r
59  *\r
60  * Returns:\r
61  *      DAT_SUCCESS\r
62  *      DAT_INSUFFICIENT_RESOURCES\r
63  *      DAT_INVALID_PARAMETER\r
64  */\r
65 DAT_RETURN DAT_API\r
66 dapl_ep_disconnect (\r
67         IN      DAT_EP_HANDLE           ep_handle,\r
68         IN      DAT_CLOSE_FLAGS         disconnect_flags)\r
69 {\r
70     DAPL_EP             *ep_ptr;\r
71     DAPL_EVD            *evd_ptr;\r
72     DAT_RETURN          dat_status;\r
73 \r
74     dapl_dbg_log (DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,\r
75                  "dapl_ep_disconnect (%p, %x)\n",\r
76                   ep_handle,\r
77                   disconnect_flags);\r
78 \r
79     ep_ptr = (DAPL_EP *) ep_handle;\r
80 \r
81     /*\r
82      * Verify parameter & state\r
83      */\r
84     if ( DAPL_BAD_HANDLE (ep_ptr, DAPL_MAGIC_EP ) )\r
85     {\r
86         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);\r
87         goto bail;\r
88     }\r
89     DAPL_CNTR(ep_ptr, DCNT_EP_DISCONNECT);\r
90 \r
91     /*\r
92      * Do the verification of parameters and the state change\r
93      * atomically.\r
94      */\r
95     dapl_os_lock ( &ep_ptr->header.lock );\r
96 \r
97     /* Disconnecting a disconnected EP is a no-op. */\r
98     if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED )\r
99     {\r
100         dapl_os_unlock ( &ep_ptr->header.lock );\r
101         dat_status = DAT_SUCCESS;\r
102         goto bail;\r
103     }\r
104 \r
105     /* Check the EP state to ensure we are queiscent. Note that\r
106      * we may get called in UNCONNECTED state in order to remove\r
107      * RECV requests from the queue prior to destroying an EP.\r
108      * See the states in the spec at 6.5.1 Endpont Lifecycle\r
109      */\r
110     if ( ep_ptr->param.ep_state != DAT_EP_STATE_CONNECTED &&\r
111          ep_ptr->param.ep_state != DAT_EP_STATE_ACTIVE_CONNECTION_PENDING &&\r
112          ep_ptr->param.ep_state != DAT_EP_STATE_COMPLETION_PENDING &&\r
113          ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECT_PENDING )\r
114     {\r
115         dapl_os_unlock ( &ep_ptr->header.lock );\r
116         dat_status = DAT_ERROR (DAT_INVALID_STATE, dapls_ep_state_subtype (ep_ptr));\r
117         goto bail;\r
118     }\r
119 \r
120     if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING &&\r
121          disconnect_flags != DAT_CLOSE_ABRUPT_FLAG)\r
122     {\r
123         /*\r
124          * If in state DISCONNECT_PENDING then this must be an\r
125          * ABRUPT disconnect\r
126          */\r
127         dapl_os_unlock ( &ep_ptr->header.lock );\r
128         dat_status = DAT_ERROR (DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);\r
129         goto bail;\r
130     }\r
131 \r
132     if ( ep_ptr->param.ep_state == DAT_EP_STATE_ACTIVE_CONNECTION_PENDING ||\r
133          ep_ptr->param.ep_state == DAT_EP_STATE_COMPLETION_PENDING )\r
134     {\r
135         /*\r
136          * Beginning or waiting on a connection: abort and reset the\r
137          * state\r
138          */\r
139         ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;\r
140 \r
141         dapl_os_unlock ( &ep_ptr->header.lock );\r
142         /* disconnect and make sure we get no callbacks */\r
143         (void) dapls_ib_disconnect (ep_ptr, DAT_CLOSE_ABRUPT_FLAG);\r
144 \r
145         /* clean up connection state */\r
146         dapl_sp_remove_ep (ep_ptr);\r
147 \r
148         evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;\r
149         dapls_evd_post_connection_event (evd_ptr,\r
150                                         DAT_CONNECTION_EVENT_DISCONNECTED,\r
151                                         (DAT_HANDLE) ep_ptr,\r
152                                         0,\r
153                                         0);\r
154         dat_status = DAT_SUCCESS;\r
155         goto bail;\r
156     }\r
157 \r
158     /*\r
159      * Transition the EP state to DISCONNECT_PENDING if we are\r
160      * CONNECTED. Otherwise we do not get a disconnect event and will be\r
161      * stuck in DISCONNECT_PENDING.\r
162      *\r
163      * If the user specifies a graceful disconnect, the underlying\r
164      * provider should complete all DTOs before disconnecting; in IB\r
165      * terms, this means setting the QP state to SQD before completing\r
166      * the disconnect state transitions.\r
167      */\r
168     if ( ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED )\r
169     {\r
170         ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING;\r
171     }\r
172     dapl_os_unlock ( &ep_ptr->header.lock );\r
173     dat_status =  dapls_ib_disconnect ( ep_ptr, disconnect_flags );\r
174 \r
175 bail:\r
176     dapl_dbg_log (DAPL_DBG_TYPE_RTN | DAPL_DBG_TYPE_CM,\r
177                   "dapl_ep_disconnect (EP %p) %s returns 0x%x\n",\r
178                   ep_ptr,dapl_get_ep_state_str(ep_ptr->param.ep_state),\r
179                   dat_status);\r
180 \r
181     return dat_status;\r
182 }\r
183 \r
184 \r
185 /*\r
186  * Local variables:\r
187  *  c-indent-level: 4\r
188  *  c-basic-offset: 4\r
189  *  tab-width: 8\r
190  * End:\r
191  */\r