[DAPL2] DAPL Counters & 2.0.3 extensions to support counter retrieval.
[mirror/winof/.git] / ulp / dapl2 / dapl / common / dapl_ep_free.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_free.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.4\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_adapter_util.h"\r
43 #include "dapl_ring_buffer_util.h"\r
44 #include "dapl_timer_util.h"\r
45 \r
46 /*\r
47  * dapl_ep_free\r
48  *\r
49  * DAPL Requirements Version xxx, 6.5.3\r
50  *\r
51  * Destroy an instance of the Endpoint\r
52  *\r
53  * Input:\r
54  *      ep_handle\r
55  *\r
56  * Output:\r
57  *      none\r
58  *\r
59  * Returns:\r
60  *      DAT_SUCCESS\r
61  *      DAT_INVALID_PARAMETER\r
62  *      DAT_INVALID_STATE\r
63  */\r
64 DAT_RETURN DAT_API\r
65 dapl_ep_free (\r
66         IN      DAT_EP_HANDLE      ep_handle)\r
67 {\r
68     DAPL_EP             *ep_ptr;\r
69     DAPL_IA             *ia_ptr;\r
70     DAT_EP_PARAM        *param;\r
71     ib_qp_state_t       save_qp_state;\r
72     DAT_RETURN          dat_status = DAT_SUCCESS;\r
73 \r
74     dapl_dbg_log (DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,\r
75                   "dapl_ep_free (%p)\n", ep_handle);\r
76 \r
77     ep_ptr = (DAPL_EP *) ep_handle;\r
78     param = &ep_ptr->param;\r
79 \r
80     /*\r
81      * Verify parameter & state\r
82      */\r
83     if ( DAPL_BAD_HANDLE (ep_ptr, DAPL_MAGIC_EP ) )\r
84     {\r
85         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);\r
86         goto bail;\r
87     }\r
88     DAPL_CNTR(ep_ptr->header.owner_ia, DCNT_IA_EP_FREE);\r
89 \r
90     if ( ep_ptr->param.ep_state == DAT_EP_STATE_RESERVED ||\r
91          ep_ptr->param.ep_state == DAT_EP_STATE_PASSIVE_CONNECTION_PENDING ||\r
92          ep_ptr->param.ep_state == DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING )\r
93     {\r
94         dapl_dbg_log (DAPL_DBG_TYPE_WARN,\r
95                       "--> dapl_ep_free: invalid state: %x, ep %p\n",\r
96                       ep_ptr->param.ep_state,\r
97                       ep_ptr);\r
98         dat_status = DAT_ERROR (DAT_INVALID_STATE,\r
99                                 dapls_ep_state_subtype (ep_ptr));\r
100         goto bail;\r
101     }\r
102 \r
103     ia_ptr = ep_ptr->header.owner_ia;\r
104 \r
105     /* If we are connected, issue a disconnect. If we are in the\r
106      * disconnect_pending state, disconnect with the ABRUPT flag\r
107      * set.\r
108      */\r
109 \r
110     /*\r
111      * Invoke ep_disconnect to clean up outstanding connections\r
112      */\r
113     (void) dapl_ep_disconnect (ep_ptr, DAT_CLOSE_ABRUPT_FLAG);\r
114 \r
115     /*\r
116      * Do verification of parameters and the state change atomically.\r
117      */\r
118     dapl_os_lock ( &ep_ptr->header.lock );\r
119 \r
120 #ifdef DAPL_DBG\r
121     /* check if event pending and warn, don't assert, state is valid */\r
122     if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) {\r
123         dapl_dbg_log (DAPL_DBG_TYPE_WARN, " dat_ep_free WARNING: "\r
124                       "EVENT PENDING on ep %p, disconnect "\r
125                       "and wait before calling dat_ep_free\n",\r
126                       ep_ptr);\r
127     }\r
128 #endif\r
129 \r
130     if (ep_ptr->cxn_timer != NULL)\r
131     {\r
132         dapls_timer_cancel ( ep_ptr->cxn_timer );\r
133         dapl_os_free ( ep_ptr->cxn_timer, sizeof ( DAPL_OS_TIMER ) );\r
134         ep_ptr->cxn_timer = NULL;\r
135     }\r
136 \r
137     /* Remove the EP from the IA */\r
138     dapl_ia_unlink_ep ( ia_ptr, ep_ptr );\r
139 \r
140     /*\r
141      * Update ref counts. Note the user may have used ep_modify\r
142      * to set handles to NULL. Set handles to NULL so this routine\r
143      * is idempotent.\r
144      */\r
145     if ( param->pz_handle != NULL )\r
146     {\r
147         dapl_os_atomic_dec (& ((DAPL_PZ *)param->pz_handle)->pz_ref_count);\r
148         param->pz_handle = NULL;\r
149     }\r
150     if ( param->recv_evd_handle != NULL )\r
151     {\r
152         dapl_os_atomic_dec (& ((DAPL_EVD *)param->recv_evd_handle)->evd_ref_count);\r
153         param->recv_evd_handle = NULL;\r
154     }\r
155     if ( param->request_evd_handle != NULL )\r
156     {\r
157         dapl_os_atomic_dec (& ((DAPL_EVD *)param->request_evd_handle)->evd_ref_count);\r
158         param->request_evd_handle = NULL;\r
159     }\r
160     if ( param->connect_evd_handle != NULL )\r
161     {\r
162         dapl_os_atomic_dec (& ((DAPL_EVD *)param->connect_evd_handle)->evd_ref_count);\r
163         param->connect_evd_handle = NULL;\r
164     }\r
165 \r
166     /*\r
167      * Finish tearing everything down.\r
168      */\r
169     dapl_dbg_log (DAPL_DBG_TYPE_EP | DAPL_DBG_TYPE_CM,\r
170                   "dapl_ep_free: Free EP: %x, ep %p qp_state %x qp_handle %x\n",\r
171                   ep_ptr->param.ep_state,\r
172                   ep_ptr,\r
173                   ep_ptr->qp_state,\r
174                   ep_ptr->qp_handle);\r
175     /*\r
176      * Take care of the transport resource. Make a copy of the qp_state\r
177      * to prevent race conditions when we exit the lock.\r
178      */\r
179     save_qp_state     = ep_ptr->qp_state;\r
180     ep_ptr->qp_state  = DAPL_QP_STATE_UNATTACHED;\r
181     dapl_os_unlock (&ep_ptr->header.lock);\r
182 \r
183     /* Free the QP. If the EP has never been used, the QP is invalid */\r
184     if ( save_qp_state != DAPL_QP_STATE_UNATTACHED )\r
185     {\r
186         dat_status = dapls_ib_qp_free (ia_ptr, ep_ptr);\r
187         /* This should always succeed, but report to the user if\r
188          * there is a problem. The qp_state must be restored so\r
189          * they can try it again in the face of EINTR or similar\r
190          * where the QP is OK but the call couldn't complete.\r
191          */\r
192         if (dat_status != DAT_SUCCESS)\r
193         {\r
194             ep_ptr->qp_state = save_qp_state;\r
195             goto bail;\r
196         }\r
197     }\r
198 \r
199     /* Free the resource */\r
200     dapl_ep_dealloc (ep_ptr);\r
201 \r
202 bail:\r
203     return dat_status;\r
204 \r
205 }\r
206 \r
207 /*\r
208  * Local variables:\r
209  *  c-indent-level: 4\r
210  *  c-basic-offset: 4\r
211  *  tab-width: 8\r
212  * End:\r
213  */\r