[IBAL] Fix error handling in __proxy_mad_recv_cb to not release a spinlock
[mirror/winof/.git] / core / al / kernel / al_proxy_subnet.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 \r
34 #include <complib/comp_lib.h>\r
35 #include <iba/ib_al.h>\r
36 #include <iba/ib_al_ioctl.h>\r
37 \r
38 #include "al.h"\r
39 #include "al_av.h"\r
40 #include "al_ca.h"\r
41 #include "al_cq.h"\r
42 #include "al_debug.h"\r
43 #include "al_dev.h"\r
44 #include "al_mad_pool.h"\r
45 #include "al_mr.h"\r
46 #include "al_mw.h"\r
47 #include "al_pd.h"\r
48 #include "al_qp.h"\r
49 #include "ib_common.h"\r
50 #include "al_proxy.h"\r
51 \r
52 \r
53 extern  ib_pool_handle_t                gh_mad_pool;\r
54 \r
55 \r
56 \r
57 static\r
58 cl_status_t\r
59 proxy_reg_svc(\r
60         IN              void                                    *p_open_context,\r
61         IN              cl_ioctl_handle_t               h_ioctl,\r
62                 OUT     size_t                                  *p_ret_bytes )\r
63 {\r
64         UNUSED_PARAM( p_open_context );\r
65         UNUSED_PARAM( h_ioctl );\r
66         UNUSED_PARAM( p_ret_bytes );\r
67         return CL_ERROR;\r
68 }\r
69 static\r
70 cl_status_t\r
71 proxy_dereg_svc(\r
72         IN              void                                    *p_open_context,\r
73         IN              cl_ioctl_handle_t               h_ioctl,\r
74                 OUT     size_t                                  *p_ret_bytes )\r
75 {\r
76         UNUSED_PARAM( p_open_context );\r
77         UNUSED_PARAM( h_ioctl );\r
78         UNUSED_PARAM( p_ret_bytes );\r
79         return CL_ERROR;\r
80 }\r
81 \r
82 \r
83 static void\r
84 __proxy_sa_req_cb(\r
85         IN                              al_sa_req_t                                     *p_sa_req,\r
86         IN                              ib_mad_element_t                        *p_mad_response )\r
87 {\r
88         IRP                                             *p_irp;\r
89         IO_STACK_LOCATION               *p_io_stack;\r
90         ual_send_sa_req_ioctl_t *p_ioctl;\r
91         al_dev_open_context_t   *p_context;\r
92         uint64_t                                hdl;\r
93 \r
94         AL_ENTER( AL_DBG_DEV | AL_DBG_QUERY );\r
95 \r
96         p_irp = (IRP*)p_sa_req->user_context;\r
97         CL_ASSERT( p_irp );\r
98 \r
99         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
100         p_ioctl = cl_ioctl_out_buf( p_irp );\r
101 \r
102         p_context = p_io_stack->FileObject->FsContext;\r
103         ASSERT( p_context );\r
104 #pragma warning(push, 3)\r
105         IoSetCancelRoutine( p_irp, NULL );\r
106 #pragma warning(pop)\r
107         /* Clear the pointer to the query to prevent cancelation. */\r
108         hdl = (size_t)InterlockedExchangePointer(\r
109                 &p_irp->Tail.Overlay.DriverContext[0], AL_INVALID_HANDLE );\r
110 \r
111         cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
112         if( hdl != AL_INVALID_HANDLE )\r
113         {\r
114                 CL_ASSERT( p_sa_req ==\r
115                         al_hdl_chk( p_context->h_al, hdl, AL_OBJ_TYPE_H_SA_REQ ) );\r
116                 al_hdl_free( p_context->h_al, hdl );\r
117         }\r
118 \r
119         p_ioctl->out.status = p_sa_req->status;\r
120         if( p_mad_response )\r
121         {\r
122                 /* Insert an item to track the MAD until the user fetches it. */\r
123                 hdl = al_hdl_insert( p_context->h_al,\r
124                         p_mad_response, AL_OBJ_TYPE_H_MAD );\r
125                 if( hdl != AL_INVALID_HANDLE )\r
126                 {\r
127                         p_ioctl->out.h_resp = hdl;\r
128                         p_ioctl->out.resp_size = p_mad_response->size;\r
129                 }\r
130                 else\r
131                 {\r
132                         p_ioctl->out.h_resp = AL_INVALID_HANDLE;\r
133                         p_ioctl->out.resp_size = 0;\r
134                         p_ioctl->out.status = IB_TIMEOUT;\r
135                         ib_put_mad( p_sa_req->p_mad_response );\r
136                 }\r
137         }\r
138         else\r
139         {\r
140                 p_ioctl->out.h_resp = AL_INVALID_HANDLE;\r
141                 p_ioctl->out.resp_size = 0;\r
142         }\r
143         cl_spinlock_release( &p_context->h_al->obj.lock );\r
144 \r
145         p_irp->IoStatus.Status = STATUS_SUCCESS;\r
146         p_irp->IoStatus.Information = sizeof(p_ioctl->out);\r
147         IoCompleteRequest( p_irp, IO_NO_INCREMENT );\r
148 \r
149         /* Release the reference taken when the query was initiated. */\r
150         proxy_context_deref( p_context );\r
151 \r
152         cl_free( p_sa_req );\r
153 \r
154         AL_EXIT( AL_DBG_QUERY );\r
155 }\r
156 \r
157 \r
158 static void\r
159 __proxy_cancel_sa_req(\r
160         IN                              DEVICE_OBJECT*                          p_dev_obj,\r
161         IN                              IRP*                                            p_irp )\r
162 {\r
163         al_dev_open_context_t   *p_context;\r
164         PIO_STACK_LOCATION              p_io_stack;\r
165         uint64_t                                hdl;\r
166         al_sa_req_t                             *p_sa_req;\r
167 \r
168         AL_ENTER( AL_DBG_DEV );\r
169 \r
170         UNUSED_PARAM( p_dev_obj );\r
171 \r
172         /* Get the stack location. */\r
173         p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
174 \r
175         p_context = (al_dev_open_context_t *)p_io_stack->FileObject->FsContext;\r
176         ASSERT( p_context );\r
177 \r
178         hdl = (size_t)InterlockedExchangePointer(\r
179                 &p_irp->Tail.Overlay.DriverContext[0], NULL );\r
180         if( hdl != AL_INVALID_HANDLE )\r
181         {\r
182 #pragma warning(push, 3)\r
183                 IoSetCancelRoutine( p_irp, NULL );\r
184 #pragma warning(pop)\r
185                 cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
186                 p_sa_req = al_hdl_chk( p_context->h_al, hdl, AL_OBJ_TYPE_H_SA_REQ );\r
187                 CL_ASSERT( p_sa_req );\r
188                 al_cancel_sa_req( p_sa_req );\r
189                 al_hdl_free( p_context->h_al, hdl );\r
190                 cl_spinlock_release( &p_context->h_al->obj.lock );\r
191         }\r
192 \r
193         IoReleaseCancelSpinLock( p_irp->CancelIrql );\r
194 }\r
195 \r
196 \r
197 static cl_status_t\r
198 proxy_send_sa_req(\r
199         IN              void                                    *p_open_context,\r
200         IN              cl_ioctl_handle_t               h_ioctl,\r
201                 OUT     size_t                                  *p_ret_bytes )\r
202 {\r
203         ual_send_sa_req_ioctl_t *p_ioctl;\r
204         cl_status_t                             status;\r
205         ib_api_status_t                 ib_status, *p_usr_status;\r
206         IO_STACK_LOCATION               *p_io_stack;\r
207         al_dev_open_context_t   *p_context;\r
208         al_sa_req_t                             *p_sa_req;\r
209         uint64_t                                hdl, *p_usr_hdl;\r
210 \r
211         AL_ENTER( AL_DBG_QUERY );\r
212 \r
213         UNUSED_PARAM( p_ret_bytes );\r
214 \r
215         p_context = p_open_context;\r
216 \r
217         p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl );\r
218         /*\r
219          * We support SA requests coming in either through the main file object\r
220          * or the async file handle.\r
221          */\r
222         if( p_io_stack->FileObject->FsContext2 &&\r
223                 (uintn_t)p_io_stack->FileObject->FsContext2 != AL_OBJ_TYPE_SA_REQ_SVC )\r
224         {\r
225                 AL_TRACE_EXIT( AL_DBG_ERROR,\r
226                         ("Invalid file object type for request: %d\n",\r
227                         p_io_stack->FileObject->FsContext2) );\r
228                 return CL_INVALID_PARAMETER;\r
229         }\r
230 \r
231         /* Check the size of the ioctl */\r
232         if( cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
233                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
234         {\r
235                 AL_TRACE_EXIT( AL_DBG_ERROR, ("Invalid IOCTL buffers.\n") );\r
236                 return CL_INVALID_PARAMETER;\r
237         }\r
238 \r
239         p_ioctl = cl_ioctl_in_buf( h_ioctl );\r
240         CL_ASSERT( p_ioctl );\r
241 \r
242         /* Must save user's pointers in case req completes before call returns. */\r
243         p_usr_status = p_ioctl->in.p_status;\r
244         p_usr_hdl = p_ioctl->in.ph_sa_req;\r
245 \r
246         if( p_ioctl->in.sa_req.attr_size > IB_SA_DATA_SIZE )\r
247         {\r
248                 ib_status = IB_INVALID_SETTING;\r
249                 AL_TRACE_EXIT( AL_DBG_ERROR, ("Invalid SA data size: %d\n",\r
250                         p_ioctl->in.sa_req.attr_size) );\r
251                 goto proxy_send_sa_req_err1;\r
252         }\r
253 \r
254         p_sa_req = (al_sa_req_t*)cl_zalloc( sizeof(al_sa_req_t) );\r
255         if( !p_sa_req )\r
256         {\r
257                 ib_status = IB_INSUFFICIENT_MEMORY;\r
258                 AL_TRACE_EXIT( AL_DBG_ERROR, ("Failed to allocate SA req.\n") );\r
259                 goto proxy_send_sa_req_err1;\r
260         }\r
261 \r
262         /* Synchronize with callbacks. */\r
263         cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
264 \r
265         /* Track the request. */\r
266         hdl = al_hdl_insert( p_context->h_al, p_sa_req, AL_OBJ_TYPE_H_SA_REQ );\r
267         if( hdl == AL_INVALID_HANDLE )\r
268         {\r
269                 ib_status = IB_INSUFFICIENT_MEMORY;\r
270                 AL_TRACE_EXIT( AL_DBG_ERROR, ("Failed to create handle.\n") );\r
271                 goto proxy_send_sa_req_err2;\r
272         }\r
273 \r
274         /*\r
275          * Store the handle in the IRP's driver context so we can cancel it.\r
276          * Note that the handle is really a size_t variable, but is cast to a\r
277          * uint64_t to provide constant size in mixed 32- and 64-bit environments.\r
278          */\r
279         h_ioctl->Tail.Overlay.DriverContext[0] = (void*)(size_t)hdl;\r
280 \r
281         /* Format the SA request */\r
282         p_sa_req->user_context = h_ioctl;\r
283         p_sa_req->pfn_sa_req_cb = __proxy_sa_req_cb;\r
284 \r
285         p_ioctl->in.sa_req.p_attr = p_ioctl->in.attr;\r
286 \r
287         /*\r
288          * We never pass the user-mode flag when sending SA requests - the\r
289          * I/O manager will perform all synchronization to make this IRP sync\r
290          * if it needs to.\r
291          */\r
292         ib_status = al_send_sa_req( p_sa_req, p_ioctl->in.port_guid,\r
293                 p_ioctl->in.timeout_ms, p_ioctl->in.retry_cnt,\r
294                 &p_ioctl->in.sa_req, 0 );\r
295         if( ib_status == IB_SUCCESS )\r
296         {\r
297                 /* Hold a reference on the proxy context until the request completes. */\r
298                 proxy_context_ref( p_context );\r
299 #pragma warning(push, 3)\r
300                 IoSetCancelRoutine( h_ioctl, __proxy_cancel_sa_req );\r
301 #pragma warning(pop)\r
302                 IoMarkIrpPending( h_ioctl );\r
303 \r
304                 cl_spinlock_release( &p_context->h_al->obj.lock );\r
305 \r
306                 cl_copy_to_user( p_usr_hdl, &hdl, sizeof(hdl) );\r
307                 status = CL_PENDING;\r
308         }\r
309         else\r
310         {\r
311                 al_hdl_free( p_context->h_al, hdl );\r
312 \r
313 proxy_send_sa_req_err2:\r
314                 cl_spinlock_release( &p_context->h_al->obj.lock );\r
315                 cl_free( p_sa_req );\r
316 \r
317 proxy_send_sa_req_err1:\r
318                 status = CL_INVALID_PARAMETER;\r
319         }\r
320 \r
321         cl_copy_to_user( p_usr_status, &ib_status, sizeof(ib_api_status_t) );\r
322 \r
323         AL_EXIT( AL_DBG_QUERY );\r
324         return status;\r
325 }\r
326 \r
327 \r
328 static cl_status_t\r
329 proxy_cancel_sa_req(\r
330         IN              void                                    *p_open_context,\r
331         IN              cl_ioctl_handle_t               h_ioctl,\r
332                 OUT     size_t                                  *p_ret_bytes )\r
333 {\r
334         ual_cancel_sa_req_ioctl_t       *p_ioctl;\r
335         al_dev_open_context_t           *p_context;\r
336         al_sa_req_t                                     *p_sa_req;\r
337 \r
338         AL_ENTER( AL_DBG_QUERY );\r
339 \r
340         UNUSED_PARAM( p_ret_bytes );\r
341 \r
342         p_context = p_open_context;\r
343 \r
344         /* Check the size of the ioctl */\r
345         if( cl_ioctl_in_size( h_ioctl ) != sizeof(ual_cancel_sa_req_ioctl_t) ||\r
346                 cl_ioctl_out_size( h_ioctl ) )\r
347         {\r
348                 AL_TRACE_EXIT( AL_DBG_ERROR, ("Invalid input buffer.\n") );\r
349                 return CL_INVALID_PARAMETER;\r
350         }\r
351 \r
352         p_ioctl = cl_ioctl_in_buf( h_ioctl );\r
353         CL_ASSERT( p_ioctl );\r
354 \r
355         cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
356         p_sa_req =\r
357                 al_hdl_chk( p_context->h_al, p_ioctl->h_sa_req, AL_OBJ_TYPE_H_SA_REQ );\r
358         if( p_sa_req )\r
359                 al_cancel_sa_req( p_sa_req );\r
360         cl_spinlock_release( &p_context->h_al->obj.lock );\r
361 \r
362         AL_EXIT( AL_DBG_QUERY );\r
363         return CL_SUCCESS;\r
364 }\r
365 \r
366 \r
367 static cl_status_t\r
368 proxy_send_mad(\r
369         IN              void                                    *p_open_context,\r
370         IN              cl_ioctl_handle_t               h_ioctl,\r
371                 OUT     size_t                                  *p_ret_bytes )\r
372 {\r
373         ual_send_mad_ioctl_t    *p_ioctl =\r
374                 (ual_send_mad_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
375         al_dev_open_context_t   *p_context =\r
376                 (al_dev_open_context_t *)p_open_context;\r
377         ib_mad_svc_handle_t             h_mad_svc;\r
378         ib_pool_key_t                   pool_key = NULL;\r
379         ib_av_handle_t                  h_av = NULL;\r
380         ib_mad_element_t                *p_mad_el;\r
381         al_mad_element_t                *p_al_el;\r
382         ib_mad_t                                *p_mad_buf, *p_usr_buf;\r
383         ib_grh_t                                *p_grh, *p_usr_grh;\r
384         ib_api_status_t                 status;\r
385 \r
386         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
387         /* Validate input buffers. */\r
388         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
389                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
390                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
391         {\r
392                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
393                 return CL_INVALID_PARAMETER;\r
394         }\r
395 \r
396         /* Validate mad svc handle. */\r
397         h_mad_svc = (ib_mad_svc_handle_t)al_hdl_ref(\r
398                 p_context->h_al, p_ioctl->in.h_mad_svc, AL_OBJ_TYPE_H_MAD_SVC );\r
399         if( !h_mad_svc )\r
400         {\r
401                 status = IB_INVALID_HANDLE;\r
402                 goto proxy_send_mad_err1;\r
403         }\r
404 \r
405         /* Validate the pool key */\r
406         pool_key = (ib_pool_key_t)al_hdl_ref(\r
407                 p_context->h_al, p_ioctl->in.pool_key, AL_OBJ_TYPE_H_POOL_KEY );\r
408         if( !pool_key )\r
409         {\r
410                 status = IB_INVALID_HANDLE;\r
411                 goto proxy_send_mad_err1;\r
412         }\r
413 \r
414         /* Validate the AV handle in the mad element if it is not NULL. */\r
415         if( p_ioctl->in.h_av )\r
416         {\r
417                 h_av = (ib_av_handle_t)\r
418                         al_hdl_ref( p_context->h_al, p_ioctl->in.h_av, AL_OBJ_TYPE_H_AV );\r
419                 if( !h_av )\r
420                 {\r
421                         status = IB_INVALID_AV_HANDLE;\r
422                         goto proxy_send_mad_err1;\r
423                 }\r
424         }\r
425 \r
426         /*\r
427          * Get a mad element from kernel MAD pool\r
428          * This should not fail since the pool is set to grow\r
429          * dynamically\r
430          */\r
431         status = ib_get_mad( pool_key, p_ioctl->in.size, &p_mad_el );\r
432         if( status != IB_SUCCESS )\r
433                 goto proxy_send_mad_err1;\r
434 \r
435         /* Store the MAD and GRH buffers pointers. */\r
436         p_mad_buf = p_mad_el->p_mad_buf;\r
437         p_grh = p_mad_el->p_grh;\r
438 \r
439         /* Now copy the mad element with all info */\r
440         status = ib_convert_cl_status( cl_copy_from_user( p_mad_el,\r
441                 p_ioctl->in.p_mad_element, sizeof(ib_mad_element_t) ) );\r
442         if( status != IB_SUCCESS )\r
443                 goto proxy_send_mad_err2;\r
444 \r
445         /* Store the UM pointers. */\r
446         p_usr_buf = p_mad_el->p_mad_buf;\r
447         p_usr_grh = p_mad_el->p_grh;\r
448         /* Restore the MAD and GRH buffer pointers. */\r
449         p_mad_el->p_mad_buf = p_mad_buf;\r
450         p_mad_el->p_grh = p_grh;\r
451         /* Clear the next pointer. */\r
452         p_mad_el->p_next = NULL;\r
453         /*\r
454          * Override the send context so that a response's MAD has a way\r
455          * of getting back to the associated send.  This is needed because a\r
456          * MAD receive completion could fail to be delivered to the app even though\r
457          * the response was properly received in the kernel.\r
458          */\r
459         p_mad_el->context1 = p_ioctl->in.p_mad_element;\r
460 \r
461         /* Set the kernel AV handle. This is either NULL or a valid KM handle. */\r
462         p_mad_el->h_av = h_av;\r
463 \r
464         /* Copy the GRH, if valid. */\r
465         if( p_mad_el->grh_valid )\r
466         {\r
467                 status = ib_convert_cl_status(\r
468                         cl_copy_from_user( p_grh, p_usr_grh, sizeof(ib_grh_t) ) );\r
469                 if( status != IB_SUCCESS )\r
470                         goto proxy_send_mad_err2;\r
471         }\r
472 \r
473         /* Copy the mad payload. */\r
474         status = ib_convert_cl_status(\r
475                 cl_copy_from_user( p_mad_buf, p_usr_buf, p_ioctl->in.size ) );\r
476         if( status != IB_SUCCESS )\r
477                 goto proxy_send_mad_err2;\r
478 \r
479         /* Copy the handle to UM to allow cancelling. */\r
480         status = ib_convert_cl_status( cl_copy_to_user(\r
481                 p_ioctl->in.ph_proxy, p_mad_el, sizeof(ib_mad_element_t*) ) );\r
482         if( status != IB_SUCCESS )\r
483                 goto proxy_send_mad_err2;\r
484 \r
485         /*\r
486          * Copy the UM element pointer to the kernel's AL element\r
487          * for use in completion generation.\r
488          */\r
489         p_al_el = PARENT_STRUCT( p_mad_el, al_mad_element_t, element );\r
490         p_al_el->h_proxy_element = p_ioctl->in.p_mad_element;\r
491 \r
492         /* Post the element. */\r
493         status = ib_send_mad( h_mad_svc, p_mad_el, NULL );\r
494 \r
495         if( status != IB_SUCCESS )\r
496         {\r
497 proxy_send_mad_err2:\r
498                 ib_put_mad( p_mad_el );\r
499         }\r
500 proxy_send_mad_err1:\r
501 \r
502         if( h_av )\r
503                 deref_al_obj( &h_av->obj );\r
504         if( pool_key )\r
505                 deref_al_obj( &pool_key->obj );\r
506         if( h_mad_svc )\r
507                 deref_al_obj( &h_mad_svc->obj );\r
508 \r
509         p_ioctl->out.status = status;\r
510         *p_ret_bytes = sizeof(p_ioctl->out);\r
511 \r
512         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
513         return CL_SUCCESS;\r
514 }\r
515 \r
516 \r
517 \r
518 /*\r
519  * Process the ioctl to retrieve a received MAD.\r
520  */\r
521 static cl_status_t\r
522 proxy_mad_comp(\r
523         IN              void                                    *p_open_context,\r
524         IN              cl_ioctl_handle_t               h_ioctl,\r
525                 OUT     size_t                                  *p_ret_bytes )\r
526 {\r
527         ual_mad_recv_ioctl_t    *p_ioctl;\r
528         al_dev_open_context_t   *p_context;\r
529         ib_mad_element_t                *p_mad;\r
530         ib_api_status_t                 status;\r
531 \r
532         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
533 \r
534         /* Validate input buffers. */\r
535         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
536                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
537                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
538         {\r
539                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
540                 return CL_INVALID_PARAMETER;\r
541         }\r
542 \r
543         p_ioctl = (ual_mad_recv_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
544         p_context = (al_dev_open_context_t*)p_open_context;\r
545 \r
546         /* Validate the MAD handle and remove it from the handle manager. */\r
547         p_mad = al_hdl_get_mad( p_context->h_al, p_ioctl->in.h_mad );\r
548         if( !p_mad )\r
549         {\r
550                 status = IB_INVALID_HANDLE;\r
551                 goto proxy_mad_comp_err1;\r
552         }\r
553 \r
554         /*\r
555          * Return the MAD to the user.  The user-mode library is responsible\r
556          * for correcting all pointers.\r
557          */\r
558         status = ib_convert_cl_status( cl_copy_to_user(\r
559                 p_ioctl->in.p_user_mad, p_mad, sizeof(ib_mad_element_t) ) );\r
560         if( status != IB_SUCCESS )\r
561         {\r
562                 AL_TRACE_EXIT( AL_DBG_ERROR,\r
563                         ("Unable to copy element to user's MAD\n") );\r
564                 goto proxy_mad_comp_err2;\r
565         }\r
566 \r
567         /* Copy the MAD buffer. */\r
568         status = ib_convert_cl_status( cl_copy_to_user(\r
569                 p_ioctl->in.p_mad_buf, p_mad->p_mad_buf, p_mad->size ) );\r
570         if( status != IB_SUCCESS )\r
571         {\r
572                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
573                         ("Unable to copy buffer to user's MAD\n") );\r
574                 goto proxy_mad_comp_err2;\r
575         }\r
576 \r
577         /* Copy the GRH if it is valid. */\r
578         if( p_mad->grh_valid )\r
579         {\r
580                 status = ib_convert_cl_status( cl_copy_to_user(\r
581                         p_ioctl->in.p_grh, p_mad->p_grh, sizeof(ib_grh_t) ) );\r
582                 if( status != IB_SUCCESS )\r
583                 {\r
584                         AL_TRACE_EXIT( AL_DBG_ERROR,\r
585                                 ("Unable to copy GRH to user's MAD\n") );\r
586                         goto proxy_mad_comp_err2;\r
587                 }\r
588         }\r
589 \r
590         if( status == IB_SUCCESS )\r
591         {\r
592                 ib_put_mad( p_mad );\r
593         }\r
594         else\r
595         {\r
596 proxy_mad_comp_err2:\r
597                 ib_put_mad( p_mad );\r
598 proxy_mad_comp_err1:\r
599                 cl_memclr( &p_ioctl->out, sizeof(p_ioctl->out) );\r
600         }\r
601 \r
602         p_ioctl->out.status = status;\r
603         *p_ret_bytes = sizeof(p_ioctl->out);\r
604 \r
605         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
606         return CL_SUCCESS;\r
607 }\r
608 \r
609 \r
610 \r
611 static cl_status_t\r
612 proxy_init_dgrm(\r
613         IN              void                                    *p_open_context,\r
614         IN              cl_ioctl_handle_t               h_ioctl,\r
615                 OUT     size_t                                  *p_ret_bytes )\r
616 {\r
617         UNUSED_PARAM( p_open_context );\r
618         UNUSED_PARAM( h_ioctl );\r
619         UNUSED_PARAM( p_ret_bytes );\r
620         return CL_ERROR;\r
621 }\r
622 \r
623 \r
624 \r
625 static void\r
626 __proxy_mad_send_cb(\r
627         IN                              ib_mad_svc_handle_t                     h_mad_svc,\r
628         IN                              void                                            *mad_svc_context,\r
629         IN                              ib_mad_element_t                        *p_mad_element )\r
630 {\r
631         misc_cb_ioctl_info_t    cb_info;\r
632         al_dev_open_context_t   *p_context;\r
633         al_mad_element_t                *p_al_el;\r
634 \r
635         CL_ENTER( ( AL_DBG_PROXY_CB | AL_DBG_MAD ), g_al_dbg_lvl );\r
636 \r
637         CL_ASSERT( p_mad_element );\r
638         CL_ASSERT( !p_mad_element->p_next );\r
639         p_context = h_mad_svc->obj.h_al->p_context;\r
640         p_al_el = PARENT_STRUCT( p_mad_element, al_mad_element_t, element );\r
641 \r
642         /*\r
643          * If we're already closing the device - do not queue a callback, since\r
644          * we're cleaning up the callback lists.\r
645          */\r
646         if( proxy_context_ref( p_context ) )\r
647         {\r
648                 /* Set up context and callback record type appropriate for UAL */\r
649                 cb_info.rec_type = MAD_SEND_REC;\r
650                 cb_info.ioctl_rec.mad_send_cb_ioctl_rec.wc_status =\r
651                         p_mad_element->status;\r
652                 cb_info.ioctl_rec.mad_send_cb_ioctl_rec.p_um_mad =\r
653                         p_al_el->h_proxy_element;\r
654                 cb_info.ioctl_rec.mad_send_cb_ioctl_rec.mad_svc_context =\r
655                         mad_svc_context;\r
656 \r
657                 /* Queue this mad completion notification for the user. */\r
658                 proxy_queue_cb_buf( UAL_GET_MISC_CB_INFO, p_context, &cb_info,\r
659                         &h_mad_svc->obj );\r
660         }\r
661 \r
662         /* Return the MAD. */\r
663         ib_put_mad( p_mad_element );\r
664 \r
665         proxy_context_deref( p_context );\r
666         CL_EXIT( ( AL_DBG_PROXY_CB | AL_DBG_MAD ), g_al_dbg_lvl );\r
667 }\r
668 \r
669 \r
670 \r
671 static void\r
672 __proxy_mad_recv_cb(\r
673         IN                              ib_mad_svc_handle_t                     h_mad_svc,\r
674         IN                              void                                            *mad_svc_context,\r
675         IN                              ib_mad_element_t                        *p_mad_element )\r
676 {\r
677         misc_cb_ioctl_info_t    cb_info;\r
678         al_dev_open_context_t   *p_context;\r
679         al_mad_element_t                *p_al_mad;\r
680         uint64_t                                hdl;\r
681 \r
682         CL_ENTER( ( AL_DBG_PROXY_CB | AL_DBG_MAD ), g_al_dbg_lvl );\r
683 \r
684         p_context = h_mad_svc->obj.h_al->p_context;\r
685 \r
686         p_al_mad = PARENT_STRUCT( p_mad_element, al_mad_element_t, element );\r
687 \r
688         /* Set up context and callback record type appropriate for UAL */\r
689         cb_info.rec_type = MAD_RECV_REC;\r
690         cb_info.ioctl_rec.mad_recv_cb_ioctl_rec.mad_svc_context = mad_svc_context;\r
691         cb_info.ioctl_rec.mad_recv_cb_ioctl_rec.elem_size = p_mad_element->size;\r
692         cb_info.ioctl_rec.mad_recv_cb_ioctl_rec.p_send_mad =\r
693                 (ib_mad_element_t* __ptr64)p_mad_element->send_context1;\r
694 \r
695         /*\r
696          * If we're already closing the device - do not queue a callback, since\r
697          * we're cleaning up the callback lists.\r
698          */\r
699         if( !proxy_context_ref( p_context ) )\r
700         {\r
701                 proxy_put_mad( p_mad_element );\r
702                 CL_EXIT( ( AL_DBG_PROXY_CB | AL_DBG_MAD ), g_al_dbg_lvl );\r
703                 return;\r
704         }\r
705 \r
706         /* Insert an item to track the MAD until the user fetches it. */\r
707         cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
708         hdl = al_hdl_insert( p_context->h_al, p_mad_element, AL_OBJ_TYPE_H_MAD );\r
709         if( hdl == AL_INVALID_HANDLE )\r
710                 goto proxy_mad_recv_cb_err;\r
711 \r
712         cb_info.ioctl_rec.mad_recv_cb_ioctl_rec.h_mad = hdl;\r
713 \r
714         /* Queue this mad completion notification for the user. */\r
715         if( !proxy_queue_cb_buf( UAL_GET_MISC_CB_INFO, p_context, &cb_info,\r
716                 &h_mad_svc->obj ) )\r
717         {\r
718                 al_hdl_free( p_context->h_al, hdl );\r
719 proxy_mad_recv_cb_err:\r
720                 proxy_put_mad( p_mad_element );\r
721         }\r
722         cl_spinlock_release( &p_context->h_al->obj.lock );\r
723 \r
724         proxy_context_deref( p_context );\r
725 \r
726         CL_EXIT( ( AL_DBG_PROXY_CB | AL_DBG_MAD ), g_al_dbg_lvl );\r
727 }\r
728 \r
729 \r
730 \r
731 static cl_status_t\r
732 proxy_reg_mad_svc(\r
733         IN              void                                    *p_open_context,\r
734         IN              cl_ioctl_handle_t               h_ioctl,\r
735                 OUT     size_t                                  *p_ret_bytes )\r
736 {\r
737         ual_reg_mad_svc_ioctl_t *p_ioctl =\r
738                 (ual_reg_mad_svc_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
739         al_dev_open_context_t   *p_context =\r
740                 (al_dev_open_context_t *)p_open_context;\r
741         ib_qp_handle_t                  h_qp;\r
742         ib_mad_svc_handle_t             h_mad_svc;\r
743 \r
744         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
745 \r
746         /* Validate input buffers. */\r
747         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
748                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
749                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
750         {\r
751                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
752                 return CL_INVALID_PARAMETER;\r
753         }\r
754 \r
755         /* Set the return bytes in all cases */\r
756         *p_ret_bytes = sizeof(p_ioctl->out);\r
757 \r
758         /* Validate QP handle */\r
759         h_qp = (ib_qp_handle_t)\r
760                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
761         if( !h_qp )\r
762         {\r
763                 p_ioctl->out.status = IB_INVALID_QP_HANDLE;\r
764                 p_ioctl->out.h_mad_svc = AL_INVALID_HANDLE;\r
765                 AL_TRACE_EXIT( AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
766                 return CL_SUCCESS;\r
767         }\r
768 \r
769         /* Now proxy's mad_svc overrides */\r
770         p_ioctl->in.mad_svc.pfn_mad_send_cb = __proxy_mad_send_cb;\r
771         p_ioctl->in.mad_svc.pfn_mad_recv_cb = __proxy_mad_recv_cb;\r
772 \r
773         p_ioctl->out.status = reg_mad_svc( h_qp,\r
774                 &p_ioctl->in.mad_svc, &h_mad_svc );\r
775         if( p_ioctl->out.status == IB_SUCCESS )\r
776         {\r
777                 p_ioctl->out.h_mad_svc = h_mad_svc->obj.hdl;\r
778                 h_mad_svc->obj.hdl_valid = TRUE;\r
779                 deref_al_obj( &h_mad_svc->obj );\r
780         }\r
781         else\r
782         {\r
783                 p_ioctl->out.h_mad_svc = AL_INVALID_HANDLE;\r
784         }\r
785 \r
786         deref_al_obj( &h_qp->obj );\r
787 \r
788         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
789         return CL_SUCCESS;\r
790 }\r
791 \r
792 \r
793 \r
794 /*\r
795  * Deregister the MAD service.\r
796  */\r
797 static cl_status_t\r
798 proxy_dereg_mad_svc(\r
799         IN              void                                    *p_open_context,\r
800         IN              cl_ioctl_handle_t               h_ioctl,\r
801                 OUT     size_t                                  *p_ret_bytes )\r
802 {\r
803         ual_dereg_mad_svc_ioctl_t       *p_ioctl;\r
804         al_dev_open_context_t           *p_context;\r
805         ib_mad_svc_handle_t                     h_mad_svc;\r
806 \r
807         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
808 \r
809         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
810                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
811                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
812         {\r
813                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
814                         ("IOCTL buffer is invalid\n") );\r
815                 return CL_INVALID_PARAMETER;\r
816         }\r
817 \r
818         p_ioctl = (ual_dereg_mad_svc_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
819         p_context = (al_dev_open_context_t*)p_open_context;\r
820 \r
821         /* Set the return bytes in all cases */\r
822         *p_ret_bytes = sizeof(p_ioctl->out);\r
823 \r
824         /* Validate MAD service. */\r
825         h_mad_svc = (ib_mad_svc_handle_t)al_hdl_ref(\r
826                 p_context->h_al, p_ioctl->in.h_mad_svc, AL_OBJ_TYPE_H_MAD_SVC );\r
827         if( !h_mad_svc )\r
828         {\r
829                 p_ioctl->out.status = IB_INVALID_HANDLE;\r
830                 AL_TRACE_EXIT( AL_DBG_ERROR, ("IB_INVALID_HANDLE\n") );\r
831                 return CL_SUCCESS;\r
832         }\r
833 \r
834         /* Destroy the MAD service. */\r
835         h_mad_svc->obj.pfn_destroy( &h_mad_svc->obj, ib_sync_destroy );\r
836         p_ioctl->out.status = IB_SUCCESS;\r
837 \r
838         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
839         return CL_SUCCESS;\r
840 }\r
841 \r
842 \r
843 \r
844 /*\r
845  * UAL only uses reg_mad_pool/dereg_mad_pool ioctls\r
846  * create/destroy mad pool is implicit in these ioctls\r
847  */\r
848 static\r
849 cl_status_t\r
850 proxy_reg_mad_pool(\r
851         IN              void                                    *p_open_context,\r
852         IN              cl_ioctl_handle_t               h_ioctl,\r
853                 OUT     size_t                                  *p_ret_bytes )\r
854 {\r
855         ual_reg_mad_pool_ioctl_t        *p_ioctl =\r
856                 (ual_reg_mad_pool_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
857         al_dev_open_context_t           *p_context =\r
858                 (al_dev_open_context_t *)p_open_context;\r
859         ib_pd_handle_t                          h_pd;\r
860         ib_pool_key_t                           pool_key;\r
861 \r
862         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
863 \r
864         /* Validate input buffers. */\r
865         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
866                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
867                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
868         {\r
869                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
870                 return CL_INVALID_PARAMETER;\r
871         }\r
872 \r
873         /* Set the return bytes in all cases */\r
874         *p_ret_bytes = sizeof(p_ioctl->out);\r
875 \r
876         /* Validate PD handle */\r
877         h_pd = (ib_pd_handle_t)\r
878                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
879         if( !h_pd )\r
880         {\r
881                 p_ioctl->out.status = IB_INVALID_PD_HANDLE;\r
882                 p_ioctl->out.pool_key = AL_INVALID_HANDLE;\r
883                 AL_TRACE_EXIT( AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );\r
884                 return CL_SUCCESS;\r
885         }\r
886 \r
887         /*\r
888          * If we're in the kernel, we are using the global MAD pool.  Other\r
889          * MAD pools remain entirely in user-mode.\r
890          */\r
891 \r
892         /* Register the PD with the MAD pool to obtain a pool_key. */\r
893         p_ioctl->out.status = reg_mad_pool( gh_mad_pool, h_pd, &pool_key );\r
894         if( p_ioctl->out.status == IB_SUCCESS )\r
895         {\r
896                 /* Track the pool info with the process context. */\r
897                 p_ioctl->out.pool_key = pool_key->obj.hdl;\r
898                 pool_key->obj.hdl_valid = TRUE;\r
899                 deref_al_obj( &pool_key->obj );\r
900         }\r
901         else\r
902         {\r
903                 p_ioctl->out.pool_key = AL_INVALID_HANDLE;\r
904                 AL_TRACE( AL_DBG_ERROR, ("reg_mad_pool returned %s.\n",\r
905                         ib_get_err_str(p_ioctl->out.status)) );\r
906         }\r
907 \r
908         deref_al_obj( &h_pd->obj );\r
909 \r
910         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
911         return CL_SUCCESS;\r
912 }\r
913 \r
914 \r
915 \r
916 /*\r
917  * Deregister the pool_key with the MAD pool.  Destroy the MAD pool if we\r
918  * created one.\r
919  */\r
920 static\r
921 cl_status_t\r
922 proxy_dereg_mad_pool(\r
923         IN              void                                    *p_open_context,\r
924         IN              cl_ioctl_handle_t               h_ioctl,\r
925                 OUT     size_t                                  *p_ret_bytes )\r
926 {\r
927         ual_dereg_mad_pool_ioctl_t      *p_ioctl =\r
928                 (ual_dereg_mad_pool_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
929         al_dev_open_context_t           *p_context =\r
930                 (al_dev_open_context_t *)p_open_context;\r
931         ib_pool_key_t                           pool_key;\r
932 \r
933         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
934 \r
935         /* Validate input buffers. */\r
936         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
937                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
938                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
939         {\r
940                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
941                         ("IOCTL buffer is invalid\n") );\r
942                 return CL_INVALID_PARAMETER;\r
943         }\r
944 \r
945         /* Set the return bytes in all cases */\r
946         *p_ret_bytes = sizeof(p_ioctl->out);\r
947 \r
948         /* Validate pool key */\r
949         pool_key = (ib_pool_key_t)al_hdl_ref(\r
950                 p_context->h_al, p_ioctl->in.pool_key, AL_OBJ_TYPE_H_POOL_KEY );\r
951         if( !pool_key )\r
952         {\r
953                 p_ioctl->out.status = IB_INVALID_HANDLE;\r
954                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
955                         ("User-mode provided pool key is invalid\n") );\r
956                 return CL_SUCCESS;\r
957         }\r
958 \r
959         /* We should only have alias pool keys exported to user-mode. */\r
960         p_ioctl->out.status = dereg_mad_pool( pool_key, AL_KEY_ALIAS );\r
961         if( p_ioctl->out.status != IB_SUCCESS )\r
962         {\r
963                 deref_al_obj( &pool_key->obj );\r
964                 AL_TRACE( AL_DBG_ERROR, ("dereg_mad_pool failed: %s\n",\r
965                         ib_get_err_str( p_ioctl->out.status )) );\r
966         }\r
967 \r
968         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
969         return CL_SUCCESS;\r
970 }\r
971 \r
972 \r
973 \r
974 cl_status_t\r
975 proxy_cancel_mad(\r
976         IN              void                                    *p_open_context,\r
977         IN              cl_ioctl_handle_t               h_ioctl,\r
978                 OUT     size_t                                  *p_ret_bytes )\r
979 {\r
980         ual_cancel_mad_ioctl_t  *p_ioctl;\r
981         al_dev_open_context_t   *p_context;\r
982         ib_mad_svc_handle_t             h_mad_svc;\r
983 \r
984         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
985 \r
986         /* Validate input buffers. */\r
987         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
988                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
989                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
990         {\r
991                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
992                 return CL_INVALID_PARAMETER;\r
993         }\r
994 \r
995         p_ioctl = (ual_cancel_mad_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
996         p_context = (al_dev_open_context_t*)p_open_context;\r
997 \r
998         /* Set the return bytes in all cases */\r
999         *p_ret_bytes = sizeof(p_ioctl->out);\r
1000 \r
1001         /* Validate MAD service handle. */\r
1002         h_mad_svc = (ib_mad_svc_handle_t)al_hdl_ref(\r
1003                 p_context->h_al, p_ioctl->in.h_mad_svc, AL_OBJ_TYPE_H_MAD_SVC );\r
1004         if( !h_mad_svc )\r
1005         {\r
1006                 p_ioctl->out.status = IB_INVALID_HANDLE;\r
1007                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
1008                 return CL_SUCCESS;\r
1009         }\r
1010 \r
1011         p_ioctl->out.status =\r
1012                 ib_cancel_mad( h_mad_svc, p_ioctl->in.h_proxy_element );\r
1013 \r
1014         /*\r
1015          * The clean up of resources allocated for the sent mad will\r
1016          * be handled in the send completion callback\r
1017          */\r
1018         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
1019         return CL_SUCCESS;\r
1020 }\r
1021 \r
1022 \r
1023 cl_status_t\r
1024 subnet_ioctl(\r
1025         IN              cl_ioctl_handle_t               h_ioctl,\r
1026                 OUT     size_t                                  *p_ret_bytes )\r
1027 {\r
1028         cl_status_t cl_status;\r
1029         IO_STACK_LOCATION               *p_io_stack;\r
1030         void                                    *p_context;\r
1031 \r
1032         AL_ENTER( AL_DBG_DEV );\r
1033 \r
1034         CL_ASSERT( h_ioctl && p_ret_bytes );\r
1035 \r
1036         p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl );\r
1037         p_context = p_io_stack->FileObject->FsContext;\r
1038 \r
1039         if( !p_context )\r
1040         {\r
1041                 AL_EXIT( AL_DBG_DEV );\r
1042                 return CL_INVALID_PARAMETER;\r
1043         }\r
1044 \r
1045         switch( cl_ioctl_ctl_code( h_ioctl ) )\r
1046         {\r
1047         case UAL_REG_SVC:\r
1048                 cl_status = proxy_reg_svc( p_context, h_ioctl, p_ret_bytes );\r
1049                 break;\r
1050         case UAL_SEND_SA_REQ:\r
1051                 cl_status = proxy_send_sa_req( p_context, h_ioctl, p_ret_bytes );\r
1052                 break;\r
1053         case UAL_CANCEL_SA_REQ:\r
1054                 cl_status = proxy_cancel_sa_req( p_context, h_ioctl, p_ret_bytes );\r
1055                 break;\r
1056         case UAL_MAD_SEND:\r
1057                 cl_status = proxy_send_mad( p_context, h_ioctl, p_ret_bytes );\r
1058                 break;\r
1059         case UAL_INIT_DGRM_SVC:\r
1060                 cl_status = proxy_init_dgrm( p_context, h_ioctl, p_ret_bytes );\r
1061                 break;\r
1062         case UAL_REG_MAD_SVC:\r
1063                 cl_status = proxy_reg_mad_svc( p_context, h_ioctl, p_ret_bytes );\r
1064                 break;\r
1065         case UAL_REG_MAD_POOL:\r
1066                 cl_status = proxy_reg_mad_pool( p_context, h_ioctl, p_ret_bytes );\r
1067                 break;\r
1068         case UAL_CANCEL_MAD:\r
1069                 cl_status = proxy_cancel_mad( p_context, h_ioctl, p_ret_bytes );\r
1070                 break;\r
1071         case UAL_MAD_RECV_COMP:\r
1072                 cl_status = proxy_mad_comp( p_context, h_ioctl, p_ret_bytes );\r
1073                 break;\r
1074         case UAL_DEREG_SVC:\r
1075                 cl_status = proxy_dereg_svc( p_context, h_ioctl, p_ret_bytes );\r
1076                 break;\r
1077         case UAL_DEREG_MAD_SVC:\r
1078                 cl_status = proxy_dereg_mad_svc( p_context, h_ioctl, p_ret_bytes );\r
1079                 break;\r
1080         case UAL_DEREG_MAD_POOL:\r
1081                 cl_status = proxy_dereg_mad_pool( p_context, h_ioctl, p_ret_bytes );\r
1082                 break;\r
1083         default:\r
1084                 cl_status = CL_INVALID_PARAMETER;\r
1085                 break;\r
1086         }\r
1087 \r
1088         return cl_status;\r
1089 }\r