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