[DAPL2] DAPL Counters & 2.0.3 extensions to support counter retrieval.
[mirror/winof/.git] / ulp / dapl2 / dapl / common / dapl_ep_create.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_create.c\r
31  *\r
32  * PURPOSE: Endpoint management\r
33  *\r
34  * $Id:$\r
35  **********************************************************************/\r
36 \r
37 #include "dapl.h"\r
38 #include "dapl_ia_util.h"\r
39 #include "dapl_ep_util.h"\r
40 #include "dapl_adapter_util.h"\r
41 \r
42 \r
43 /*\r
44  * dapl_ep_create\r
45  *\r
46  * Create an instance of an Endpoint that is provided to the\r
47  * consumer at ep_handle.\r
48  *\r
49  * Input:\r
50  *      ia_handle\r
51  *      pz_handle\r
52  *      recv_evd_handle (recv DTOs)\r
53  *      request_evd_handle (xmit DTOs)\r
54  *      connect_evd_handle\r
55  *      ep_attrs\r
56  *\r
57  * Output:\r
58  *      ep_handle\r
59  *\r
60  * Returns:\r
61  *      DAT_SUCCESS\r
62  *      DAT_INSUFFICIENT_RESOURCES\r
63  *      DAT_INVALID_PARAMETER\r
64  *      DAT_INVALID_ATTRIBUTE\r
65  *      DAT_MODEL_NOT_SUPPORTED\r
66  */\r
67 DAT_RETURN DAT_API\r
68 dapl_ep_create (\r
69     IN  DAT_IA_HANDLE           ia_handle,\r
70     IN  DAT_PZ_HANDLE           pz_handle,\r
71     IN  DAT_EVD_HANDLE          recv_evd_handle,\r
72     IN  DAT_EVD_HANDLE          request_evd_handle,\r
73     IN  DAT_EVD_HANDLE          connect_evd_handle,\r
74     IN  const DAT_EP_ATTR       *ep_attr,\r
75     OUT DAT_EP_HANDLE           *ep_handle )\r
76 {\r
77     DAPL_IA                     *ia_ptr;\r
78     DAPL_EP                     *ep_ptr;\r
79     DAT_EP_ATTR                 ep_attr_limit;\r
80     DAPL_EVD                    *evd_ptr;\r
81     DAT_RETURN                  dat_status;\r
82 \r
83     dapl_dbg_log (DAPL_DBG_TYPE_API,\r
84                   "dapl_ep_create (%p, %p, %p, %p, %p, %p, %p)\n",\r
85                   ia_handle, \r
86                   pz_handle, \r
87                   recv_evd_handle, \r
88                   request_evd_handle,\r
89                   connect_evd_handle, \r
90                   ep_attr, \r
91                   ep_handle);\r
92 \r
93     ia_ptr = (DAPL_IA *)ia_handle;\r
94     dat_status = DAT_SUCCESS;\r
95 \r
96     /*\r
97      * Verify parameters\r
98      */\r
99     if ( DAPL_BAD_HANDLE (ia_ptr, DAPL_MAGIC_IA) )\r
100     {\r
101         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA);\r
102         goto bail;\r
103     }\r
104     DAPL_CNTR(ia_ptr, DCNT_IA_EP_CREATE);\r
105 \r
106     /*\r
107      * Verify non-required parameters.\r
108      * N.B. Assumption: any parameter that can be\r
109      *      modified by dat_ep_modify() is not strictly\r
110      *      required when the EP is created\r
111      */\r
112     if ( pz_handle != DAT_HANDLE_NULL && \r
113          DAPL_BAD_HANDLE (pz_handle, DAPL_MAGIC_PZ) )\r
114     {\r
115         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_PZ);\r
116         goto bail;\r
117     }\r
118 \r
119     /* If connect handle is !NULL verify handle is good  */\r
120     if (connect_evd_handle != DAT_HANDLE_NULL &&\r
121         (DAPL_BAD_HANDLE (connect_evd_handle, DAPL_MAGIC_EVD) ||\r
122          ! (((DAPL_EVD *)connect_evd_handle)->evd_flags & DAT_EVD_CONNECTION_FLAG)) )\r
123     {\r
124         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CONN);\r
125         goto bail;\r
126     }\r
127 \r
128     /* If recv_evd is !NULL, verify handle is good and flags are valid */\r
129     if (recv_evd_handle != DAT_HANDLE_NULL &&\r
130         (DAPL_BAD_HANDLE (recv_evd_handle, DAPL_MAGIC_EVD) ||\r
131          ! (((DAPL_EVD *)recv_evd_handle)->evd_flags & DAT_EVD_DTO_FLAG) ) )\r
132     {\r
133         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_RECV);\r
134         goto bail;\r
135     }\r
136 \r
137     /* If req_evd is !NULL, verify handle is good and flags are valid */\r
138     if (request_evd_handle != DAT_HANDLE_NULL && \r
139         (DAPL_BAD_HANDLE (request_evd_handle, DAPL_MAGIC_EVD) ||\r
140          ! (((DAPL_EVD *)request_evd_handle)->evd_flags & DAT_EVD_DTO_FLAG) ) )\r
141     {\r
142         dat_status = DAT_ERROR (DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_REQUEST);\r
143         goto bail;\r
144     }\r
145 \r
146     if ( ep_handle == NULL )\r
147     {\r
148         dat_status = DAT_ERROR (DAT_INVALID_PARAMETER, DAT_INVALID_ARG7);\r
149         goto bail;\r
150     }\r
151     if (DAPL_BAD_PTR(ep_attr))\r
152     {\r
153         dat_status = DAT_ERROR (DAT_INVALID_PARAMETER, DAT_INVALID_ARG6);\r
154         goto bail;\r
155     }\r
156 \r
157     /*\r
158      * Qualify EP Attributes are legal and make sense.  Note that if one\r
159      * or both of the DTO handles are NULL, then the corresponding\r
160      * max_*_dtos must 0 as the user will not be able to post dto ops on\r
161      * the respective queue.\r
162      */\r
163     if (ep_attr != NULL && \r
164         (ep_attr->service_type != DAT_SERVICE_TYPE_RC ||\r
165          (recv_evd_handle == DAT_HANDLE_NULL && ep_attr->max_recv_dtos != 0) ||\r
166          (recv_evd_handle != DAT_HANDLE_NULL && ep_attr->max_recv_dtos == 0) ||\r
167          (request_evd_handle == DAT_HANDLE_NULL && ep_attr->max_request_dtos != 0) ||\r
168          (request_evd_handle != DAT_HANDLE_NULL && ep_attr->max_request_dtos == 0) ||\r
169          (recv_evd_handle != DAT_HANDLE_NULL && ep_attr->max_recv_iov == 0) ||\r
170          ep_attr->max_request_iov == 0 ||\r
171          (DAT_SUCCESS != dapl_ep_check_recv_completion_flags (\r
172              ep_attr->recv_completion_flags)) ))\r
173     {\r
174         dat_status = DAT_ERROR (DAT_INVALID_PARAMETER, DAT_INVALID_ARG6);\r
175         goto bail;\r
176     }\r
177 \r
178     /* Verify the attributes against the transport */\r
179     if (ep_attr != NULL)\r
180     {\r
181         dapl_os_memzero (&ep_attr_limit, sizeof (DAT_EP_ATTR));\r
182         dat_status = dapls_ib_query_hca (ia_ptr->hca_ptr, \r
183                                          NULL, &ep_attr_limit, NULL);\r
184         if (dat_status != DAT_SUCCESS)\r
185         {\r
186             goto bail;\r
187         }\r
188         if ( ep_attr->max_mtu_size     > ep_attr_limit.max_mtu_size       ||\r
189              ep_attr->max_rdma_size    > ep_attr_limit.max_rdma_size      ||\r
190              ep_attr->max_recv_dtos    > ep_attr_limit.max_recv_dtos      ||\r
191              ep_attr->max_request_dtos > ep_attr_limit.max_request_dtos   ||\r
192              ep_attr->max_recv_iov     > ep_attr_limit.max_recv_iov       ||\r
193              ep_attr->max_request_iov  > ep_attr_limit.max_request_iov    ||\r
194              ep_attr->max_rdma_read_in > ep_attr_limit.max_rdma_read_in   ||\r
195              ep_attr->max_rdma_read_out> ep_attr_limit.max_rdma_read_out )\r
196 \r
197         {\r
198             dat_status = DAT_INVALID_PARAMETER | DAT_INVALID_ARG6;\r
199             goto bail;\r
200         }\r
201     }\r
202 \r
203     /*\r
204      * Verify the completion flags for the EVD and the EP\r
205      */\r
206     /*\r
207      * XXX FIXME\r
208      * XXX Need to make assign the EVD to the right completion type\r
209      * XXX depending on the EP attributes. Fail if the types don't\r
210      * XXX match, they are mutually exclusive.\r
211      */\r
212     evd_ptr = (DAPL_EVD *)recv_evd_handle;\r
213     if (evd_ptr != NULL && evd_ptr->completion_type == DAPL_EVD_STATE_INIT)\r
214     {\r
215         if (ep_attr != NULL && \r
216             ep_attr->recv_completion_flags == DAT_COMPLETION_DEFAULT_FLAG)\r
217         {\r
218             evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;\r
219         }\r
220         else\r
221         {\r
222             evd_ptr->completion_type = ep_attr->recv_completion_flags;\r
223         }\r
224     }\r
225 \r
226     evd_ptr = (DAPL_EVD *)request_evd_handle;\r
227     if (evd_ptr != NULL && evd_ptr->completion_type == DAPL_EVD_STATE_INIT)\r
228     {\r
229         if (ep_attr != NULL && \r
230             ep_attr->recv_completion_flags == DAT_COMPLETION_DEFAULT_FLAG)\r
231         {\r
232             evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;\r
233         }\r
234         else\r
235         {\r
236             evd_ptr->completion_type = ep_attr->recv_completion_flags;\r
237         }\r
238     }\r
239 \r
240 \r
241     /* Allocate EP */\r
242     ep_ptr = dapl_ep_alloc ( ia_ptr, ep_attr );\r
243     if ( ep_ptr == NULL )\r
244     {\r
245         dat_status = DAT_ERROR (DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);\r
246         goto bail;\r
247     }\r
248 \r
249     /*\r
250      * Fill in the EP\r
251      */\r
252     ep_ptr->param.ia_handle           = ia_handle;\r
253     ep_ptr->param.ep_state            = DAT_EP_STATE_UNCONNECTED;\r
254     ep_ptr->param.local_ia_address_ptr=\r
255         (DAT_IA_ADDRESS_PTR)&ia_ptr->hca_ptr->hca_address;\r
256     /* Set the remote address pointer to the end of the EP struct */\r
257     ep_ptr->param.remote_ia_address_ptr = (DAT_IA_ADDRESS_PTR) (ep_ptr + 1);\r
258 \r
259     ep_ptr->param.pz_handle           = pz_handle;\r
260     ep_ptr->param.recv_evd_handle     = recv_evd_handle;\r
261     ep_ptr->param.request_evd_handle  = request_evd_handle;\r
262     ep_ptr->param.connect_evd_handle  = connect_evd_handle;\r
263 \r
264     /*\r
265      * Make sure we handle the NULL DTO EVDs\r
266      */\r
267     if ( recv_evd_handle == DAT_HANDLE_NULL && ep_attr == NULL )\r
268     {\r
269         ep_ptr->param.ep_attr.max_recv_dtos = 0;\r
270     }\r
271 \r
272     if ( request_evd_handle == DAT_HANDLE_NULL && ep_attr == NULL )\r
273     {\r
274         ep_ptr->param.ep_attr.max_request_dtos = 0;\r
275     }\r
276 \r
277     /*\r
278      * If the user has specified a PZ handle we allocate a QP for\r
279      * this EP; else we defer until it is assigned via ep_modify().\r
280      * As much as possible we try to keep QP creation out of the\r
281      * connect path to avoid resource errors in strange places.\r
282      */\r
283     if (pz_handle != DAT_HANDLE_NULL )\r
284     {\r
285         /* Take a reference on the PZ handle */\r
286         dapl_os_atomic_inc (& ((DAPL_PZ *)pz_handle)->pz_ref_count);\r
287 \r
288         /*\r
289          * Get a QP from the IB provider\r
290          */\r
291         dat_status = dapls_ib_qp_alloc ( ia_ptr, ep_ptr, ep_ptr );\r
292 \r
293         if ( dat_status != DAT_SUCCESS)\r
294         {\r
295             dapl_os_atomic_dec (& ((DAPL_PZ *)pz_handle)->pz_ref_count);\r
296             dapl_ep_dealloc ( ep_ptr );\r
297             goto bail;\r
298         }\r
299     }\r
300     else\r
301     {\r
302         ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;\r
303     }\r
304 \r
305     /*\r
306      * Update ref counts. See the spec where the endpoint marks\r
307      * a data object as 'in use'\r
308      *   pz_handle: dat_pz_free, uDAPL Document, 6.6.1.2\r
309      *   evd_handles:\r
310      *\r
311      * N.B. This should really be done by a util routine.\r
312      */\r
313     if (connect_evd_handle != DAT_HANDLE_NULL)\r
314     {\r
315         dapl_os_atomic_inc (& ((DAPL_EVD *)connect_evd_handle)->evd_ref_count);\r
316     }\r
317     /* Optional handles */\r
318     if (recv_evd_handle != DAT_HANDLE_NULL)\r
319     {\r
320         dapl_os_atomic_inc (& ((DAPL_EVD *)recv_evd_handle)->evd_ref_count);\r
321     }\r
322     if (request_evd_handle != DAT_HANDLE_NULL)\r
323     {\r
324         dapl_os_atomic_inc (& ((DAPL_EVD *)request_evd_handle)->evd_ref_count);\r
325     }\r
326 \r
327     /* Link it onto the IA */\r
328     dapl_ia_link_ep (ia_ptr, ep_ptr);\r
329 \r
330     *ep_handle = ep_ptr;\r
331 \r
332 bail:\r
333     return dat_status;\r
334 }\r
335 \r
336 \r
337 /*\r
338  * Local variables:\r
339  *  c-indent-level: 4\r
340  *  c-basic-offset: 4\r
341  *  tab-width: 8\r
342  * End:\r
343  */\r