[IBAL] ib_dereg_svc check that the handle is from the right type
[mirror/winof/.git] / core / al / al_reg_svc.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 <iba/ib_al.h>\r
34 \r
35 #include "al.h"\r
36 #include "al_debug.h"\r
37 #if defined(EVENT_TRACING)\r
38 #ifdef offsetof\r
39 #undef offsetof\r
40 #endif\r
41 #include "al_reg_svc.tmh"\r
42 #endif\r
43 #include "al_reg_svc.h"\r
44 #include "ib_common.h"\r
45 #include "al_mgr.h"\r
46 \r
47 \r
48 \r
49 static void\r
50 __dereg_svc_cb(\r
51         IN              al_sa_req_t                     *p_sa_req,\r
52         IN              ib_mad_element_t        *p_mad_response )\r
53 {\r
54         ib_reg_svc_handle_t             h_reg_svc;\r
55 \r
56         /*\r
57          * Note that we come into this callback with a reference\r
58          * on the registration object.\r
59          */\r
60         h_reg_svc = PARENT_STRUCT( p_sa_req, al_reg_svc_t, sa_req );\r
61 \r
62         if( p_mad_response )\r
63                 ib_put_mad( p_mad_response );\r
64 \r
65         h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, NULL );\r
66 }\r
67 \r
68 \r
69 static void\r
70 __sa_dereg_svc(\r
71         IN              const   ib_reg_svc_handle_t                     h_reg_svc )\r
72 {\r
73         ib_user_query_t                 sa_mad_data;\r
74 \r
75         ref_al_obj( &h_reg_svc->obj );\r
76 \r
77         /* Set the request information. */\r
78         h_reg_svc->sa_req.pfn_sa_req_cb = __dereg_svc_cb;\r
79 \r
80         /* Set the MAD attributes and component mask correctly. */\r
81         sa_mad_data.method = IB_MAD_METHOD_DELETE;\r
82         sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;\r
83         sa_mad_data.attr_size = sizeof(ib_service_record_t);\r
84 \r
85         sa_mad_data.p_attr = &h_reg_svc->svc_rec;\r
86         sa_mad_data.comp_mask = ~CL_CONST64(0);\r
87 \r
88         if( al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid,\r
89                 500, 0, &sa_mad_data, 0 ) != IB_SUCCESS )\r
90         {\r
91                 /* Cleanup from the registration. */\r
92                 deref_al_obj( &h_reg_svc->obj );\r
93         }\r
94 }\r
95 \r
96 \r
97 void\r
98 reg_svc_req_cb(\r
99         IN                              al_sa_req_t                                     *p_sa_req,\r
100         IN                              ib_mad_element_t                        *p_mad_response )\r
101 {\r
102         ib_reg_svc_handle_t             h_reg_svc;\r
103         ib_sa_mad_t                             *p_sa_mad;\r
104         ib_reg_svc_rec_t                reg_svc_rec;\r
105 \r
106         /*\r
107          * Note that we come into this callback with a reference\r
108          * on the registration object.\r
109          */\r
110         h_reg_svc = PARENT_STRUCT( p_sa_req, al_reg_svc_t, sa_req );\r
111 \r
112         CL_ASSERT( h_reg_svc->pfn_reg_svc_cb );\r
113 \r
114         /* Record the status of the registration request. */\r
115         h_reg_svc->req_status = p_sa_req->status;\r
116 \r
117         if( p_mad_response )\r
118         {\r
119                 p_sa_mad = (ib_sa_mad_t *)p_mad_response->p_mad_buf;\r
120                 h_reg_svc->resp_status = p_sa_mad->status;\r
121 \r
122                 if ( h_reg_svc->req_status == IB_SUCCESS )\r
123                 {\r
124                         /* Save the service registration results. */\r
125                         h_reg_svc->svc_rec = *((ib_service_record_t *)p_sa_mad->data);\r
126                 }\r
127 \r
128                 /* We no longer need the response MAD. */\r
129                 ib_put_mad( p_mad_response );\r
130         }\r
131 \r
132         /* Initialize the user's callback record. */\r
133         cl_memclr( &reg_svc_rec, sizeof( ib_reg_svc_rec_t ) );\r
134         reg_svc_rec.svc_context = h_reg_svc->sa_req.user_context;\r
135         reg_svc_rec.req_status = h_reg_svc->req_status;\r
136         reg_svc_rec.resp_status = h_reg_svc->resp_status;\r
137         reg_svc_rec.svc_rec = h_reg_svc->svc_rec;\r
138 \r
139         cl_spinlock_acquire( &h_reg_svc->obj.lock );\r
140         /* See if the registration was successful. */\r
141         if( reg_svc_rec.req_status == IB_SUCCESS )\r
142         {\r
143                 /* Ensure that the user wants the registration to proceed. */\r
144                 if( h_reg_svc->state == SA_REG_STARTING )\r
145                 {\r
146                         h_reg_svc->state = SA_REG_ACTIVE;\r
147                         reg_svc_rec.h_reg_svc = h_reg_svc;\r
148                 }\r
149                 else\r
150                 {\r
151                         CL_ASSERT( h_reg_svc->state == SA_REG_CANCELING );\r
152                         reg_svc_rec.req_status = IB_CANCELED;\r
153 \r
154                         /* Notify the SA that we're deregistering. */\r
155                         __sa_dereg_svc( h_reg_svc );\r
156                 }\r
157         }\r
158         else\r
159         {\r
160                 h_reg_svc->state = SA_REG_ERROR;\r
161         }\r
162         cl_spinlock_release( &h_reg_svc->obj.lock );\r
163 \r
164         h_reg_svc->pfn_reg_svc_cb( &reg_svc_rec );\r
165 \r
166         if( p_sa_req->status != IB_SUCCESS )\r
167         {\r
168                 h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, NULL );\r
169         }\r
170         else\r
171         {\r
172                 /* Release the reference taken when issuing the request. */\r
173                 deref_al_obj( &h_reg_svc->obj );\r
174         }\r
175 }\r
176 \r
177 \r
178 static void\r
179 __destroying_sa_reg(\r
180         IN                              al_obj_t* const                         p_obj )\r
181 {\r
182         ib_reg_svc_handle_t             h_sa_reg;\r
183 \r
184         AL_ENTER( AL_DBG_SA_REQ );\r
185 \r
186         h_sa_reg = PARENT_STRUCT( p_obj, al_reg_svc_t, obj );\r
187 \r
188         cl_spinlock_acquire( &p_obj->lock );\r
189 \r
190         CL_ASSERT( h_sa_reg->state != SA_REG_HALTING );\r
191         switch( h_sa_reg->state )\r
192         {\r
193         case SA_REG_STARTING:\r
194                 /*\r
195                  * Cancel registration.  Note that there is a reference held until\r
196                  * this completes.\r
197                  */\r
198                 h_sa_reg->state = SA_REG_CANCELING;\r
199                 al_cancel_sa_req( &h_sa_reg->sa_req );\r
200                 break;\r
201 \r
202         case SA_REG_ERROR:\r
203                 /* Nothing to do. */\r
204                 break;\r
205                 \r
206         default:\r
207                 h_sa_reg->state = SA_REG_HALTING;\r
208 \r
209                 __sa_dereg_svc( h_sa_reg );\r
210         }\r
211         cl_spinlock_release( &p_obj->lock );\r
212 \r
213 }\r
214 \r
215 \r
216 static void\r
217 __free_sa_reg(\r
218         IN                              al_obj_t* const                         p_obj )\r
219 {\r
220         ib_reg_svc_handle_t             h_sa_reg;\r
221 \r
222         AL_ENTER( AL_DBG_SA_REQ );\r
223 \r
224         h_sa_reg = PARENT_STRUCT( p_obj, al_reg_svc_t, obj );\r
225 \r
226         destroy_al_obj( p_obj );\r
227         cl_free( h_sa_reg );\r
228 \r
229         AL_EXIT( AL_DBG_SA_REQ );\r
230 }\r
231 \r
232 \r
233 static ib_api_status_t\r
234 sa_reg_svc(\r
235         IN              const   ib_reg_svc_handle_t                     h_reg_svc,\r
236         IN              const   ib_reg_svc_req_t* const         p_reg_svc_req )\r
237 {\r
238         ib_user_query_t                 sa_mad_data;\r
239 \r
240         /* Set the request information. */\r
241         h_reg_svc->sa_req.pfn_sa_req_cb = reg_svc_req_cb;\r
242 \r
243         /* Set the MAD attributes and component mask correctly. */\r
244         sa_mad_data.method = IB_MAD_METHOD_SET;\r
245         sa_mad_data.attr_id = IB_MAD_ATTR_SERVICE_RECORD;\r
246         sa_mad_data.attr_size = sizeof(ib_service_record_t);\r
247 \r
248         /* Initialize the component mask. */\r
249         sa_mad_data.comp_mask = p_reg_svc_req->svc_data_mask;\r
250         sa_mad_data.p_attr = &h_reg_svc->svc_rec;\r
251 \r
252         return al_send_sa_req( &h_reg_svc->sa_req, h_reg_svc->port_guid,\r
253                 p_reg_svc_req->timeout_ms, p_reg_svc_req->retry_cnt, &sa_mad_data,\r
254                 p_reg_svc_req->flags );\r
255 }\r
256 \r
257 \r
258 ib_api_status_t\r
259 ib_reg_svc(\r
260         IN              const   ib_al_handle_t                          h_al,\r
261         IN              const   ib_reg_svc_req_t* const         p_reg_svc_req,\r
262                 OUT                     ib_reg_svc_handle_t* const      ph_reg_svc )\r
263 {\r
264         ib_reg_svc_handle_t             h_sa_reg = NULL;\r
265         ib_api_status_t                 status;\r
266 \r
267         AL_ENTER( AL_DBG_SA_REQ );\r
268 \r
269         if( AL_OBJ_INVALID_HANDLE( h_al, AL_OBJ_TYPE_H_AL ) )\r
270         {\r
271                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_AL_HANDLE\n") );\r
272                 return IB_INVALID_AL_HANDLE;\r
273         }\r
274         if( !p_reg_svc_req )\r
275         {\r
276                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_PARAMETER\n") );\r
277                 return IB_INVALID_PARAMETER;\r
278         }\r
279 \r
280         /* Allocate a new service registration request. */\r
281         h_sa_reg = cl_zalloc( sizeof( al_reg_svc_t ) );\r
282         if( !h_sa_reg )\r
283         {\r
284                 AL_EXIT( AL_DBG_SA_REQ );\r
285                 return IB_INSUFFICIENT_MEMORY;\r
286         }\r
287 \r
288         construct_al_obj( &h_sa_reg->obj, AL_OBJ_TYPE_H_SA_REG );\r
289 \r
290         status = init_al_obj( &h_sa_reg->obj, p_reg_svc_req->svc_context, TRUE,\r
291                 __destroying_sa_reg, NULL, __free_sa_reg );\r
292         if( status != IB_SUCCESS )\r
293         {\r
294                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
295                         ("init_al_obj returned %s.\n", ib_get_err_str( status )) );\r
296                 __free_sa_reg( &h_sa_reg->obj );\r
297                 return status;\r
298         }\r
299 \r
300         /* Track the registered service with the AL instance. */\r
301         status = attach_al_obj( &h_al->obj, &h_sa_reg->obj );\r
302         if( status != IB_SUCCESS )\r
303         {\r
304                 h_sa_reg->obj.pfn_destroy( &h_sa_reg->obj, NULL );\r
305                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
306                         ("attach_al_obj returned %s.\n", ib_get_err_str( status )) );\r
307                 return status;\r
308         }\r
309 \r
310         /* Store the port GUID on which to issue the request. */\r
311         h_sa_reg->port_guid = p_reg_svc_req->port_guid;\r
312 \r
313         /* Copy the service registration information. */\r
314         h_sa_reg->sa_req.user_context = p_reg_svc_req->svc_context;\r
315         h_sa_reg->pfn_reg_svc_cb = p_reg_svc_req->pfn_reg_svc_cb;\r
316         h_sa_reg->svc_rec = p_reg_svc_req->svc_rec;\r
317 \r
318         h_sa_reg->state = SA_REG_STARTING;\r
319 \r
320         /* Issue the MAD to the SA. */\r
321         status = sa_reg_svc( h_sa_reg, p_reg_svc_req );\r
322         if( status != IB_SUCCESS )\r
323         {\r
324                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
325                         ("sa_reg_svc failed: %s\n", ib_get_err_str(status) ) );\r
326                 h_sa_reg->state = SA_REG_ERROR;\r
327 \r
328                 h_sa_reg->obj.pfn_destroy( &h_sa_reg->obj, NULL );\r
329         }\r
330         else\r
331         {\r
332                 *ph_reg_svc = h_sa_reg;\r
333         }\r
334 \r
335         AL_EXIT( AL_DBG_SA_REQ );\r
336         return status;\r
337 }\r
338 \r
339 \r
340 ib_api_status_t\r
341 ib_dereg_svc(\r
342         IN              const   ib_reg_svc_handle_t                     h_reg_svc,\r
343         IN              const   ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL )\r
344 {\r
345         AL_ENTER( AL_DBG_SA_REQ );\r
346 \r
347         if( AL_OBJ_INVALID_HANDLE( h_reg_svc, AL_OBJ_TYPE_H_SA_REG) )\r
348         {\r
349                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_HANDLE\n") );\r
350                 return IB_INVALID_HANDLE;\r
351         }\r
352 \r
353         ref_al_obj( &h_reg_svc->obj );\r
354         h_reg_svc->obj.pfn_destroy( &h_reg_svc->obj, pfn_destroy_cb );\r
355 \r
356         AL_EXIT( AL_DBG_SA_REQ );\r
357         return IB_SUCCESS;\r
358 }\r