0769c3fb9be8b2fada160a70ae8afe11ba1a9db2
[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                 goto proxy_mad_recv_cb_err;\r
701 \r
702         /* Insert an item to track the MAD until the user fetches it. */\r
703         cl_spinlock_acquire( &p_context->h_al->obj.lock );\r
704         hdl = al_hdl_insert( p_context->h_al, p_mad_element, AL_OBJ_TYPE_H_MAD );\r
705         if( hdl == AL_INVALID_HANDLE )\r
706                 goto proxy_mad_recv_cb_err;\r
707 \r
708         cb_info.ioctl_rec.mad_recv_cb_ioctl_rec.h_mad = hdl;\r
709 \r
710         /* Queue this mad completion notification for the user. */\r
711         if( !proxy_queue_cb_buf( UAL_GET_MISC_CB_INFO, p_context, &cb_info,\r
712                 &h_mad_svc->obj ) )\r
713         {\r
714                 al_hdl_free( p_context->h_al, hdl );\r
715 proxy_mad_recv_cb_err:\r
716                 proxy_put_mad( p_mad_element );\r
717         }\r
718         cl_spinlock_release( &p_context->h_al->obj.lock );\r
719 \r
720         proxy_context_deref( p_context );\r
721 \r
722         CL_EXIT( ( AL_DBG_PROXY_CB | AL_DBG_MAD ), g_al_dbg_lvl );\r
723 }\r
724 \r
725 \r
726 \r
727 static cl_status_t\r
728 proxy_reg_mad_svc(\r
729         IN              void                                    *p_open_context,\r
730         IN              cl_ioctl_handle_t               h_ioctl,\r
731                 OUT     size_t                                  *p_ret_bytes )\r
732 {\r
733         ual_reg_mad_svc_ioctl_t *p_ioctl =\r
734                 (ual_reg_mad_svc_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
735         al_dev_open_context_t   *p_context =\r
736                 (al_dev_open_context_t *)p_open_context;\r
737         ib_qp_handle_t                  h_qp;\r
738         ib_mad_svc_handle_t             h_mad_svc;\r
739 \r
740         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
741 \r
742         /* Validate input buffers. */\r
743         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
744                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
745                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
746         {\r
747                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
748                 return CL_INVALID_PARAMETER;\r
749         }\r
750 \r
751         /* Set the return bytes in all cases */\r
752         *p_ret_bytes = sizeof(p_ioctl->out);\r
753 \r
754         /* Validate QP handle */\r
755         h_qp = (ib_qp_handle_t)\r
756                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
757         if( !h_qp )\r
758         {\r
759                 p_ioctl->out.status = IB_INVALID_QP_HANDLE;\r
760                 p_ioctl->out.h_mad_svc = AL_INVALID_HANDLE;\r
761                 AL_TRACE_EXIT( AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
762                 return CL_SUCCESS;\r
763         }\r
764 \r
765         /* Now proxy's mad_svc overrides */\r
766         p_ioctl->in.mad_svc.pfn_mad_send_cb = __proxy_mad_send_cb;\r
767         p_ioctl->in.mad_svc.pfn_mad_recv_cb = __proxy_mad_recv_cb;\r
768 \r
769         p_ioctl->out.status = reg_mad_svc( h_qp,\r
770                 &p_ioctl->in.mad_svc, &h_mad_svc );\r
771         if( p_ioctl->out.status == IB_SUCCESS )\r
772         {\r
773                 p_ioctl->out.h_mad_svc = h_mad_svc->obj.hdl;\r
774                 h_mad_svc->obj.hdl_valid = TRUE;\r
775                 deref_al_obj( &h_mad_svc->obj );\r
776         }\r
777         else\r
778         {\r
779                 p_ioctl->out.h_mad_svc = AL_INVALID_HANDLE;\r
780         }\r
781 \r
782         deref_al_obj( &h_qp->obj );\r
783 \r
784         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
785         return CL_SUCCESS;\r
786 }\r
787 \r
788 \r
789 \r
790 /*\r
791  * Deregister the MAD service.\r
792  */\r
793 static cl_status_t\r
794 proxy_dereg_mad_svc(\r
795         IN              void                                    *p_open_context,\r
796         IN              cl_ioctl_handle_t               h_ioctl,\r
797                 OUT     size_t                                  *p_ret_bytes )\r
798 {\r
799         ual_dereg_mad_svc_ioctl_t       *p_ioctl;\r
800         al_dev_open_context_t           *p_context;\r
801         ib_mad_svc_handle_t                     h_mad_svc;\r
802 \r
803         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
804 \r
805         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
806                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
807                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
808         {\r
809                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
810                         ("IOCTL buffer is invalid\n") );\r
811                 return CL_INVALID_PARAMETER;\r
812         }\r
813 \r
814         p_ioctl = (ual_dereg_mad_svc_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
815         p_context = (al_dev_open_context_t*)p_open_context;\r
816 \r
817         /* Set the return bytes in all cases */\r
818         *p_ret_bytes = sizeof(p_ioctl->out);\r
819 \r
820         /* Validate MAD service. */\r
821         h_mad_svc = (ib_mad_svc_handle_t)al_hdl_ref(\r
822                 p_context->h_al, p_ioctl->in.h_mad_svc, AL_OBJ_TYPE_H_MAD_SVC );\r
823         if( !h_mad_svc )\r
824         {\r
825                 p_ioctl->out.status = IB_INVALID_HANDLE;\r
826                 AL_TRACE_EXIT( AL_DBG_ERROR, ("IB_INVALID_HANDLE\n") );\r
827                 return CL_SUCCESS;\r
828         }\r
829 \r
830         /* Destroy the MAD service. */\r
831         h_mad_svc->obj.pfn_destroy( &h_mad_svc->obj, ib_sync_destroy );\r
832         p_ioctl->out.status = IB_SUCCESS;\r
833 \r
834         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
835         return CL_SUCCESS;\r
836 }\r
837 \r
838 \r
839 \r
840 /*\r
841  * UAL only uses reg_mad_pool/dereg_mad_pool ioctls\r
842  * create/destroy mad pool is implicit in these ioctls\r
843  */\r
844 static\r
845 cl_status_t\r
846 proxy_reg_mad_pool(\r
847         IN              void                                    *p_open_context,\r
848         IN              cl_ioctl_handle_t               h_ioctl,\r
849                 OUT     size_t                                  *p_ret_bytes )\r
850 {\r
851         ual_reg_mad_pool_ioctl_t        *p_ioctl =\r
852                 (ual_reg_mad_pool_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
853         al_dev_open_context_t           *p_context =\r
854                 (al_dev_open_context_t *)p_open_context;\r
855         ib_pd_handle_t                          h_pd;\r
856         ib_pool_key_t                           pool_key;\r
857 \r
858         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
859 \r
860         /* Validate input buffers. */\r
861         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
862                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
863                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
864         {\r
865                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
866                 return CL_INVALID_PARAMETER;\r
867         }\r
868 \r
869         /* Set the return bytes in all cases */\r
870         *p_ret_bytes = sizeof(p_ioctl->out);\r
871 \r
872         /* Validate PD handle */\r
873         h_pd = (ib_pd_handle_t)\r
874                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
875         if( !h_pd )\r
876         {\r
877                 p_ioctl->out.status = IB_INVALID_PD_HANDLE;\r
878                 p_ioctl->out.pool_key = AL_INVALID_HANDLE;\r
879                 AL_TRACE_EXIT( AL_DBG_ERROR, ("IB_INVALID_PD_HANDLE\n") );\r
880                 return CL_SUCCESS;\r
881         }\r
882 \r
883         /*\r
884          * If we're in the kernel, we are using the global MAD pool.  Other\r
885          * MAD pools remain entirely in user-mode.\r
886          */\r
887 \r
888         /* Register the PD with the MAD pool to obtain a pool_key. */\r
889         p_ioctl->out.status = reg_mad_pool( gh_mad_pool, h_pd, &pool_key );\r
890         if( p_ioctl->out.status == IB_SUCCESS )\r
891         {\r
892                 /* Track the pool info with the process context. */\r
893                 p_ioctl->out.pool_key = pool_key->obj.hdl;\r
894                 pool_key->obj.hdl_valid = TRUE;\r
895                 deref_al_obj( &pool_key->obj );\r
896         }\r
897         else\r
898         {\r
899                 p_ioctl->out.pool_key = AL_INVALID_HANDLE;\r
900                 AL_TRACE( AL_DBG_ERROR, ("reg_mad_pool returned %s.\n",\r
901                         ib_get_err_str(p_ioctl->out.status)) );\r
902         }\r
903 \r
904         deref_al_obj( &h_pd->obj );\r
905 \r
906         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
907         return CL_SUCCESS;\r
908 }\r
909 \r
910 \r
911 \r
912 /*\r
913  * Deregister the pool_key with the MAD pool.  Destroy the MAD pool if we\r
914  * created one.\r
915  */\r
916 static\r
917 cl_status_t\r
918 proxy_dereg_mad_pool(\r
919         IN              void                                    *p_open_context,\r
920         IN              cl_ioctl_handle_t               h_ioctl,\r
921                 OUT     size_t                                  *p_ret_bytes )\r
922 {\r
923         ual_dereg_mad_pool_ioctl_t      *p_ioctl =\r
924                 (ual_dereg_mad_pool_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
925         al_dev_open_context_t           *p_context =\r
926                 (al_dev_open_context_t *)p_open_context;\r
927         ib_pool_key_t                           pool_key;\r
928 \r
929         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
930 \r
931         /* Validate input buffers. */\r
932         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
933                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
934                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
935         {\r
936                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
937                         ("IOCTL buffer is invalid\n") );\r
938                 return CL_INVALID_PARAMETER;\r
939         }\r
940 \r
941         /* Set the return bytes in all cases */\r
942         *p_ret_bytes = sizeof(p_ioctl->out);\r
943 \r
944         /* Validate pool key */\r
945         pool_key = (ib_pool_key_t)al_hdl_ref(\r
946                 p_context->h_al, p_ioctl->in.pool_key, AL_OBJ_TYPE_H_POOL_KEY );\r
947         if( !pool_key )\r
948         {\r
949                 p_ioctl->out.status = IB_INVALID_HANDLE;\r
950                 CL_TRACE_EXIT( AL_DBG_ERROR, g_al_dbg_lvl,\r
951                         ("User-mode provided pool key is invalid\n") );\r
952                 return CL_SUCCESS;\r
953         }\r
954 \r
955         /* We should only have alias pool keys exported to user-mode. */\r
956         p_ioctl->out.status = dereg_mad_pool( pool_key, AL_KEY_ALIAS );\r
957         if( p_ioctl->out.status != IB_SUCCESS )\r
958         {\r
959                 deref_al_obj( &pool_key->obj );\r
960                 AL_TRACE( AL_DBG_ERROR, ("dereg_mad_pool failed: %s\n",\r
961                         ib_get_err_str( p_ioctl->out.status )) );\r
962         }\r
963 \r
964         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
965         return CL_SUCCESS;\r
966 }\r
967 \r
968 \r
969 \r
970 cl_status_t\r
971 proxy_cancel_mad(\r
972         IN              void                                    *p_open_context,\r
973         IN              cl_ioctl_handle_t               h_ioctl,\r
974                 OUT     size_t                                  *p_ret_bytes )\r
975 {\r
976         ual_cancel_mad_ioctl_t  *p_ioctl;\r
977         al_dev_open_context_t   *p_context;\r
978         ib_mad_svc_handle_t             h_mad_svc;\r
979 \r
980         CL_ENTER( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
981 \r
982         /* Validate input buffers. */\r
983         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
984                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
985                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
986         {\r
987                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
988                 return CL_INVALID_PARAMETER;\r
989         }\r
990 \r
991         p_ioctl = (ual_cancel_mad_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
992         p_context = (al_dev_open_context_t*)p_open_context;\r
993 \r
994         /* Set the return bytes in all cases */\r
995         *p_ret_bytes = sizeof(p_ioctl->out);\r
996 \r
997         /* Validate MAD service handle. */\r
998         h_mad_svc = (ib_mad_svc_handle_t)al_hdl_ref(\r
999                 p_context->h_al, p_ioctl->in.h_mad_svc, AL_OBJ_TYPE_H_MAD_SVC );\r
1000         if( !h_mad_svc )\r
1001         {\r
1002                 p_ioctl->out.status = IB_INVALID_HANDLE;\r
1003                 CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
1004                 return CL_SUCCESS;\r
1005         }\r
1006 \r
1007         p_ioctl->out.status =\r
1008                 ib_cancel_mad( h_mad_svc, p_ioctl->in.h_proxy_element );\r
1009 \r
1010         /*\r
1011          * The clean up of resources allocated for the sent mad will\r
1012          * be handled in the send completion callback\r
1013          */\r
1014         CL_EXIT( ( AL_DBG_DEV | AL_DBG_MAD ), g_al_dbg_lvl );\r
1015         return CL_SUCCESS;\r
1016 }\r
1017 \r
1018 \r
1019 cl_status_t\r
1020 subnet_ioctl(\r
1021         IN              cl_ioctl_handle_t               h_ioctl,\r
1022                 OUT     size_t                                  *p_ret_bytes )\r
1023 {\r
1024         cl_status_t cl_status;\r
1025         IO_STACK_LOCATION               *p_io_stack;\r
1026         void                                    *p_context;\r
1027 \r
1028         AL_ENTER( AL_DBG_DEV );\r
1029 \r
1030         CL_ASSERT( h_ioctl && p_ret_bytes );\r
1031 \r
1032         p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl );\r
1033         p_context = p_io_stack->FileObject->FsContext;\r
1034 \r
1035         if( !p_context )\r
1036         {\r
1037                 AL_EXIT( AL_DBG_DEV );\r
1038                 return CL_INVALID_PARAMETER;\r
1039         }\r
1040 \r
1041         switch( cl_ioctl_ctl_code( h_ioctl ) )\r
1042         {\r
1043         case UAL_REG_SVC:\r
1044                 cl_status = proxy_reg_svc( p_context, h_ioctl, p_ret_bytes );\r
1045                 break;\r
1046         case UAL_SEND_SA_REQ:\r
1047                 cl_status = proxy_send_sa_req( p_context, h_ioctl, p_ret_bytes );\r
1048                 break;\r
1049         case UAL_CANCEL_SA_REQ:\r
1050                 cl_status = proxy_cancel_sa_req( p_context, h_ioctl, p_ret_bytes );\r
1051                 break;\r
1052         case UAL_MAD_SEND:\r
1053                 cl_status = proxy_send_mad( p_context, h_ioctl, p_ret_bytes );\r
1054                 break;\r
1055         case UAL_INIT_DGRM_SVC:\r
1056                 cl_status = proxy_init_dgrm( p_context, h_ioctl, p_ret_bytes );\r
1057                 break;\r
1058         case UAL_REG_MAD_SVC:\r
1059                 cl_status = proxy_reg_mad_svc( p_context, h_ioctl, p_ret_bytes );\r
1060                 break;\r
1061         case UAL_REG_MAD_POOL:\r
1062                 cl_status = proxy_reg_mad_pool( p_context, h_ioctl, p_ret_bytes );\r
1063                 break;\r
1064         case UAL_CANCEL_MAD:\r
1065                 cl_status = proxy_cancel_mad( p_context, h_ioctl, p_ret_bytes );\r
1066                 break;\r
1067         case UAL_MAD_RECV_COMP:\r
1068                 cl_status = proxy_mad_comp( p_context, h_ioctl, p_ret_bytes );\r
1069                 break;\r
1070         case UAL_DEREG_SVC:\r
1071                 cl_status = proxy_dereg_svc( p_context, h_ioctl, p_ret_bytes );\r
1072                 break;\r
1073         case UAL_DEREG_MAD_SVC:\r
1074                 cl_status = proxy_dereg_mad_svc( p_context, h_ioctl, p_ret_bytes );\r
1075                 break;\r
1076         case UAL_DEREG_MAD_POOL:\r
1077                 cl_status = proxy_dereg_mad_pool( p_context, h_ioctl, p_ret_bytes );\r
1078                 break;\r
1079         default:\r
1080                 cl_status = CL_INVALID_PARAMETER;\r
1081                 break;\r
1082         }\r
1083 \r
1084         return cl_status;\r
1085 }\r