[IBAL] Call um_close_ca after child resources are released.
[mirror/winof/.git] / core / al / al_ca.c
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. \r
4  *\r
5  * This software is available to you under the OpenIB.org BSD license\r
6  * below:\r
7  *\r
8  *     Redistribution and use in source and binary forms, with or\r
9  *     without modification, are permitted provided that the following\r
10  *     conditions are met:\r
11  *\r
12  *      - Redistributions of source code must retain the above\r
13  *        copyright notice, this list of conditions and the following\r
14  *        disclaimer.\r
15  *\r
16  *      - Redistributions in binary form must reproduce the above\r
17  *        copyright notice, this list of conditions and the following\r
18  *        disclaimer in the documentation and/or other materials\r
19  *        provided with the distribution.\r
20  *\r
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
25  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
26  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
27  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
28  * SOFTWARE.\r
29  *\r
30  * $Id$\r
31  */\r
32 \r
33 #include <complib/cl_atomic.h>\r
34 #include <iba/ib_al.h>\r
35 \r
36 #include "al.h"\r
37 #include "al_av.h"\r
38 #include "al_ca.h"\r
39 #include "al_cq.h"\r
40 #include "al_debug.h"\r
41 #include "al_mgr.h"\r
42 #include "al_mr.h"\r
43 #include "al_mw.h"\r
44 #include "al_pd.h"\r
45 #include "al_qp.h"\r
46 #include "al_verbs.h"\r
47 #include "ib_common.h"\r
48 \r
49 \r
50 static void\r
51 __destroying_ca(\r
52         IN                              struct _al_obj                          *p_obj );\r
53 \r
54 static void\r
55 __cleanup_ca(\r
56         IN                              struct _al_obj                          *p_obj );\r
57 \r
58 static void\r
59 __free_ca(\r
60         IN                              struct _al_obj                          *p_obj );\r
61 \r
62 \r
63 \r
64 ib_api_status_t\r
65 ib_open_ca(\r
66         IN              const   ib_al_handle_t                          h_al,\r
67         IN              const   ib_net64_t                                      ca_guid,\r
68         IN              const   ib_pfn_event_cb_t                       pfn_ca_event_cb OPTIONAL,\r
69         IN              const   void* const                                     ca_context,\r
70                 OUT                     ib_ca_handle_t* const           ph_ca )\r
71 {\r
72         ib_api_status_t status;\r
73 \r
74         if( AL_OBJ_INVALID_HANDLE( h_al, AL_OBJ_TYPE_H_AL ) )\r
75         {\r
76                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_AL_HANDLE\n") );\r
77                 return IB_INVALID_AL_HANDLE;\r
78         }\r
79 \r
80         status = open_ca( h_al, ca_guid, pfn_ca_event_cb, ca_context, ph_ca, NULL );\r
81         \r
82         /* Release the reference taken in init_al_obj. */\r
83         if( status == IB_SUCCESS )\r
84                 deref_al_obj( &(*ph_ca)->obj );\r
85 \r
86         return status;\r
87 }\r
88 \r
89 \r
90 ib_api_status_t\r
91 open_ca(\r
92         IN              const   ib_al_handle_t                          h_al,\r
93         IN              const   ib_net64_t                                      ca_guid,\r
94         IN              const   ib_pfn_event_cb_t                       pfn_ca_event_cb OPTIONAL,\r
95         IN              const   void* const                                     ca_context,\r
96                 OUT                     ib_ca_handle_t* const           ph_ca,\r
97         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf OPTIONAL )\r
98 {\r
99         ib_ca_handle_t                  h_ca;\r
100         ib_api_status_t                 status;\r
101         al_obj_type_t                   obj_type = AL_OBJ_TYPE_H_CA;\r
102 \r
103         CL_ENTER( AL_DBG_CA, g_al_dbg_lvl );\r
104         if( !ph_ca )\r
105         {\r
106                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
107                 return IB_INVALID_PARAMETER;\r
108         }\r
109 \r
110         /* Allocate a CA instance. */\r
111         h_ca = (ib_ca_handle_t)cl_zalloc( sizeof( ib_ca_t ) );\r
112         if( !h_ca )\r
113         {\r
114                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
115                         ("IB_INSUFFICIENT_MEMORY\n") );\r
116                 return IB_INSUFFICIENT_MEMORY;\r
117         }\r
118 \r
119         /* Construct the CA. */\r
120         if( p_umv_buf )\r
121                 obj_type |= AL_OBJ_SUBTYPE_UM_EXPORT;\r
122         construct_al_obj( &h_ca->obj, obj_type );\r
123         h_ca->pfn_event_cb = pfn_ca_event_cb;\r
124 \r
125         status = init_al_obj( &h_ca->obj, ca_context, TRUE,\r
126                 NULL, __cleanup_ca, __free_ca );\r
127         if( status != IB_SUCCESS )\r
128         {\r
129                 __free_ca( &h_ca->obj );\r
130                 CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
131                 return status;\r
132         }\r
133 \r
134         status = attach_al_obj( &h_al->obj, &h_ca->obj );\r
135         if( status != IB_SUCCESS )\r
136         {\r
137                 h_ca->obj.pfn_destroy( &h_ca->obj, NULL );\r
138                 AL_EXIT( AL_DBG_CA );\r
139                 return status;\r
140         }\r
141 \r
142         /* Obtain a reference to the correct CI CA. */\r
143         h_ca->obj.p_ci_ca = acquire_ci_ca( ca_guid, h_ca );\r
144         if( !h_ca->obj.p_ci_ca )\r
145         {\r
146                 h_ca->obj.pfn_destroy( &h_ca->obj, NULL );\r
147                 CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
148                 return IB_INVALID_GUID;\r
149         }\r
150 \r
151 #if defined(CL_KERNEL)\r
152         /* If a UM open, pass to the VPD to establish the UM CA context. */\r
153         if( p_umv_buf )\r
154         {\r
155                 status = h_ca->obj.p_ci_ca->verbs.um_open_ca(\r
156                         h_ca->obj.p_ci_ca->h_ci_ca, p_umv_buf, &h_ca->h_um_ca );\r
157                 if( status != IB_SUCCESS )\r
158                 {\r
159                         h_ca->obj.pfn_destroy( &h_ca->obj, NULL );\r
160                         CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
161                         return status;\r
162                 }\r
163         }\r
164 #endif  /* defined(CL_KERNEL) */\r
165 \r
166         *ph_ca = h_ca;\r
167 \r
168         CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
169         return IB_SUCCESS;\r
170 }\r
171 \r
172 \r
173 /*\r
174  * Destroy an instance of an AL channel adapter.\r
175  */\r
176 ib_api_status_t\r
177 ib_close_ca(\r
178         IN              const   ib_ca_handle_t                          h_ca,\r
179         IN              const   ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL )\r
180 {\r
181         CL_ENTER( AL_DBG_CA, g_al_dbg_lvl );\r
182 \r
183         if( AL_OBJ_INVALID_HANDLE( h_ca, AL_OBJ_TYPE_H_CA ) )\r
184         {\r
185                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CA_HANDLE\n") );\r
186                 return IB_INVALID_CA_HANDLE;\r
187         }\r
188 \r
189         ref_al_obj( &h_ca->obj );\r
190         h_ca->obj.pfn_destroy( &h_ca->obj, pfn_destroy_cb );\r
191 \r
192         CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
193         return IB_SUCCESS;\r
194 }\r
195 \r
196 \r
197 /*\r
198  * Release all resources associated with the CA.\r
199  */\r
200 static void\r
201 __cleanup_ca(\r
202         IN                              struct _al_obj                          *p_obj )\r
203 {\r
204 #if defined(CL_KERNEL)\r
205         ib_ca_handle_t                  h_ca;\r
206 \r
207         CL_ASSERT( p_obj );\r
208         h_ca = PARENT_STRUCT( p_obj, ib_ca_t, obj );\r
209         if( h_ca->h_um_ca )\r
210         {\r
211                 h_ca->obj.p_ci_ca->verbs.um_close_ca(\r
212                         h_ca->obj.p_ci_ca->h_ci_ca, h_ca->h_um_ca );\r
213         }\r
214 #endif\r
215 \r
216         /* It is now safe to release the CI CA. */\r
217         if( p_obj->p_ci_ca )\r
218                 release_ci_ca( PARENT_STRUCT( p_obj, ib_ca_t, obj ) );\r
219 }\r
220 \r
221 \r
222 \r
223 static void\r
224 __free_ca(\r
225         IN                              struct _al_obj                          *p_obj )\r
226 {\r
227         ib_ca_handle_t                  h_ca;\r
228 \r
229         CL_ASSERT( p_obj );\r
230         h_ca = PARENT_STRUCT( p_obj, ib_ca_t, obj );\r
231 \r
232         destroy_al_obj( p_obj );\r
233         cl_free( h_ca );\r
234 }\r
235 \r
236 \r
237 \r
238 ib_api_status_t\r
239 ib_query_ca(\r
240         IN              const   ib_ca_handle_t                          h_ca,\r
241                 OUT                     ib_ca_attr_t* const                     p_ca_attr OPTIONAL,\r
242         IN      OUT                     uint32_t* const                         p_size )\r
243 {\r
244         return query_ca( h_ca, p_ca_attr, p_size, NULL );\r
245 }\r
246 \r
247 \r
248 \r
249 ib_api_status_t\r
250 query_ca(\r
251         IN              const   ib_ca_handle_t                          h_ca,\r
252                 OUT                     ib_ca_attr_t* const                     p_ca_attr OPTIONAL,\r
253         IN      OUT                     uint32_t* const                         p_size,\r
254         IN      OUT                     ci_umv_buf_t* const                     p_umv_buf )\r
255 {\r
256         ib_api_status_t                 status;\r
257 \r
258         CL_ENTER( AL_DBG_CA, g_al_dbg_lvl );\r
259 \r
260         if( AL_OBJ_INVALID_HANDLE( h_ca, AL_OBJ_TYPE_H_CA ) )\r
261         {\r
262                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CA_HANDLE\n") );\r
263                 return IB_INVALID_CA_HANDLE;\r
264         }\r
265         if( !p_size )\r
266         {\r
267                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
268                 return IB_INVALID_PARAMETER;\r
269         }\r
270 \r
271         status = verbs_query_ca( h_ca, p_ca_attr, p_size );\r
272 \r
273         CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
274         return status;\r
275 }\r
276 \r
277 \r
278 \r
279 ib_api_status_t\r
280 ib_modify_ca(\r
281         IN              const ib_ca_handle_t                            h_ca,\r
282         IN              const uint8_t                                           port_num,\r
283         IN              const ib_ca_mod_t                                       ca_mod,\r
284         IN              const ib_port_attr_mod_t* const         p_port_attr_mod )\r
285 {\r
286         ib_api_status_t                 status;\r
287 \r
288         CL_ENTER( AL_DBG_CA, g_al_dbg_lvl );\r
289 \r
290         if( AL_OBJ_INVALID_HANDLE( h_ca, AL_OBJ_TYPE_H_CA ) )\r
291         {\r
292                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CA_HANDLE\n") );\r
293                 return IB_INVALID_CA_HANDLE;\r
294         }\r
295         if( !p_port_attr_mod )\r
296         {\r
297                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_PARAMETER\n") );\r
298                 return IB_INVALID_PARAMETER;\r
299         }\r
300 \r
301         status = verbs_modify_ca(h_ca, port_num, ca_mod, p_port_attr_mod);\r
302 \r
303         CL_EXIT( AL_DBG_CA, g_al_dbg_lvl );\r
304         return status;\r
305 }\r
306 \r
307 \r
308 \r
309 /*\r
310  * Allocate a new protection domain.\r
311  */\r
312 ib_api_status_t\r
313 ib_alloc_pd(\r
314         IN              const   ib_ca_handle_t                          h_ca,\r
315         IN              const   ib_pd_type_t                            pd_type,\r
316         IN              const   void * const                            pd_context,\r
317                 OUT                     ib_pd_handle_t* const           ph_pd )\r
318 {\r
319         ib_api_status_t                 status;\r
320 \r
321         CL_ENTER( AL_DBG_PD, g_al_dbg_lvl );\r
322 \r
323         if( AL_OBJ_INVALID_HANDLE( h_ca, AL_OBJ_TYPE_H_CA ) )\r
324         {\r
325                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CA_HANDLE\n") );\r
326                 return IB_INVALID_CA_HANDLE;\r
327         }\r
328 \r
329         status = alloc_pd( h_ca, pd_type, pd_context, ph_pd, NULL );\r
330 \r
331         /* Release the reference taken in init_al_obj. */\r
332         if( status == IB_SUCCESS )\r
333                 deref_al_obj( &(*ph_pd)->obj );\r
334 \r
335         CL_EXIT( AL_DBG_PD, g_al_dbg_lvl );\r
336         return status;\r
337 }\r
338 \r
339 \r
340 \r
341 ib_api_status_t\r
342 ib_create_cq(\r
343         IN              const   ib_ca_handle_t                          h_ca,\r
344         IN      OUT                     ib_cq_create_t* const           p_cq_create,\r
345         IN              const   void* const                                     cq_context,\r
346         IN              const   ib_pfn_event_cb_t                       pfn_cq_event_cb OPTIONAL,\r
347                 OUT                     ib_cq_handle_t* const           ph_cq )\r
348 {\r
349         ib_api_status_t                 status;\r
350 \r
351         CL_ENTER( AL_DBG_CQ, g_al_dbg_lvl );\r
352 \r
353         if( AL_OBJ_INVALID_HANDLE( h_ca, AL_OBJ_TYPE_H_CA ) )\r
354         {\r
355                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl, ("IB_INVALID_CA_HANDLE\n") );\r
356                 return IB_INVALID_CA_HANDLE;\r
357         }\r
358 \r
359         status = create_cq( h_ca, p_cq_create, cq_context, pfn_cq_event_cb,\r
360                 ph_cq, NULL );\r
361 \r
362         /* Release the reference taken in init_al_obj. */\r
363         if( status == IB_SUCCESS )\r
364                 deref_al_obj( &(*ph_cq)->obj );\r
365 \r
366         CL_EXIT( AL_DBG_CQ, g_al_dbg_lvl );\r
367         return status;\r
368 }\r
369 \r
370 \r
371 ib_api_status_t\r
372 al_convert_to_ci_handles(\r
373         IN                              void* __ptr64 *         const   dst_handle_array,\r
374         IN              const   void* __ptr64 *         const   src_handle_array,\r
375         IN                              uint32_t                                        num_handles )\r
376 {\r
377         uint32_t                i;\r
378         al_obj_t                *p_al_obj;\r
379 \r
380         for( i = 0; i < num_handles; i++ )\r
381         {\r
382                 p_al_obj = (al_obj_t*)(const void*)src_handle_array[i];\r
383                 switch( p_al_obj->type )\r
384                 {\r
385                 case AL_OBJ_TYPE_H_PD:\r
386                         dst_handle_array[i] = ((ib_pd_t*)p_al_obj)->h_ci_pd;\r
387                         break;\r
388                 case AL_OBJ_TYPE_H_CQ:\r
389                         dst_handle_array[i] = ((ib_cq_t*)p_al_obj)->h_ci_cq;\r
390                         break;\r
391                 case AL_OBJ_TYPE_H_AV:\r
392                         dst_handle_array[i] = ((ib_av_t*)p_al_obj)->h_ci_av;\r
393                         break;\r
394                 case AL_OBJ_TYPE_H_QP:\r
395                         dst_handle_array[i] = ((ib_qp_t*)p_al_obj)->h_ci_qp;\r
396                         break;\r
397                 case AL_OBJ_TYPE_H_MR:\r
398                         dst_handle_array[i] = ((ib_mr_t*)p_al_obj)->h_ci_mr;\r
399                         break;\r
400                 case AL_OBJ_TYPE_H_MW:\r
401                         dst_handle_array[i] = ((ib_mw_t*)p_al_obj)->h_ci_mw;\r
402                         break;\r
403                 default:\r
404                         /* Bad handle type. */\r
405                         CL_ASSERT( p_al_obj->type == AL_OBJ_TYPE_H_PD ||\r
406                                 p_al_obj->type == AL_OBJ_TYPE_H_CQ ||\r
407                                 p_al_obj->type == AL_OBJ_TYPE_H_AV ||\r
408                                 p_al_obj->type == AL_OBJ_TYPE_H_QP ||\r
409                                 p_al_obj->type == AL_OBJ_TYPE_H_MR ||\r
410                                 p_al_obj->type == AL_OBJ_TYPE_H_MW );\r
411                         return IB_INVALID_HANDLE;\r
412                 }\r
413         }\r
414 \r
415         return IB_SUCCESS;\r
416 }\r