[IBAL] Remove PD context from IOCTLs.
[mirror/winof/.git] / core / al / kernel / al_proxy_verbs.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  * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
5  *\r
6  * This software is available to you under the OpenIB.org BSD license\r
7  * below:\r
8  *\r
9  *     Redistribution and use in source and binary forms, with or\r
10  *     without modification, are permitted provided that the following\r
11  *     conditions are met:\r
12  *\r
13  *      - Redistributions of source code must retain the above\r
14  *        copyright notice, this list of conditions and the following\r
15  *        disclaimer.\r
16  *\r
17  *      - Redistributions in binary form must reproduce the above\r
18  *        copyright notice, this list of conditions and the following\r
19  *        disclaimer in the documentation and/or other materials\r
20  *        provided with the distribution.\r
21  *\r
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
29  * SOFTWARE.\r
30  *\r
31  * $Id$\r
32  */\r
33 \r
34 \r
35 #include <complib/comp_lib.h>\r
36 #include <iba/ib_al.h>\r
37 #include <iba/ib_al_ioctl.h>\r
38 #include "al.h"\r
39 #include "al_debug.h"\r
40 \r
41 #if defined(EVENT_TRACING)\r
42 #ifdef offsetof\r
43 #undef offsetof\r
44 #endif\r
45 #include "al_proxy_verbs.tmh"\r
46 #endif\r
47 \r
48 #include "al_dev.h"\r
49 /* Get the internal definitions of apis for the proxy */\r
50 #include "al_ca.h"\r
51 #include "al_pd.h"\r
52 #include "al_qp.h"\r
53 #include "al_srq.h"\r
54 #include "al_cq.h"\r
55 #include "al_mr.h"\r
56 #include "al_mw.h"\r
57 #include "al_av.h"\r
58 #include "al_ci_ca.h"\r
59 #include "al_mgr.h"\r
60 #include "ib_common.h"\r
61 #include "al_proxy.h"\r
62 \r
63 \r
64 extern al_mgr_t                         *gp_al_mgr;\r
65 \r
66 \r
67 /*\r
68  *\r
69  * Utility function to:\r
70  * a. allocate an umv_buf and p_buf in kernel space\r
71  * b. copy umv_buf and the contents of p_buf from user-mode\r
72  *\r
73  * It is assumed that the p_buf does not have any embedded user-mode pointers\r
74  */\r
75 \r
76 ib_api_status_t\r
77 cpyin_umvbuf(\r
78         IN              ci_umv_buf_t    *p_src,\r
79                 OUT     ci_umv_buf_t    **pp_dst )\r
80 {\r
81         size_t                  umv_buf_size;\r
82         ci_umv_buf_t    *p_dest;\r
83 \r
84         /* Allocate space for umv_buf */\r
85         CL_ASSERT( pp_dst );\r
86 \r
87         umv_buf_size = sizeof(ci_umv_buf_t);\r
88         umv_buf_size += MAX(p_src->input_size, p_src->output_size);\r
89 \r
90         if( p_src->p_inout_buf )\r
91         {\r
92                 if( p_src->input_size && cl_check_for_read(\r
93                         (void*)(ULONG_PTR)p_src->p_inout_buf, (size_t)p_src->input_size )\r
94                         != CL_SUCCESS )\r
95                 {\r
96                         /* user-supplied memory area not readable */\r
97                         return IB_INVALID_PERMISSION;\r
98                 }\r
99                 if( p_src->output_size && cl_check_for_write(\r
100                         (void*)(ULONG_PTR)p_src->p_inout_buf, (size_t)p_src->output_size )\r
101                         != CL_SUCCESS )\r
102                 {\r
103                         /* user-supplied memory area not writeable */\r
104                         return IB_INVALID_PERMISSION;\r
105                 }\r
106         }\r
107         p_dest = (ci_umv_buf_t*)cl_zalloc( (size_t)umv_buf_size );\r
108         if( !p_dest )\r
109                 return IB_INSUFFICIENT_MEMORY;\r
110 \r
111         /* Copy the umv_buf structure. */\r
112         *p_dest = *p_src;\r
113         if( p_src->p_inout_buf )\r
114                 p_dest->p_inout_buf = (ULONG_PTR)(p_dest + 1);\r
115 \r
116         /* Setup the buffer - either we have an input or output buffer */\r
117         if( p_src->input_size )\r
118         {\r
119                 if( cl_copy_from_user( (void*)(ULONG_PTR)p_dest->p_inout_buf,\r
120                         (void*)(ULONG_PTR)p_src->p_inout_buf,\r
121                         (size_t)p_src->input_size ) != CL_SUCCESS )\r
122                 {\r
123                         cl_free( p_dest );\r
124                         return IB_INVALID_PERMISSION;\r
125                 }\r
126         }\r
127         *pp_dst = p_dest;\r
128         return IB_SUCCESS;\r
129 }\r
130 \r
131 \r
132 \r
133 /*\r
134  *\r
135  * Utility function to copy the results of umv_buf and the contents\r
136  * of p_buf to umv_buf in user-space.\r
137  *\r
138  * It is assumed that the p_buf does not have any embedded user-mode pointers\r
139  *\r
140  * This function can NOT be called from asynchronous callbacks where\r
141  * user process context may not be valid\r
142  *\r
143  */\r
144 ib_api_status_t\r
145 cpyout_umvbuf(\r
146         IN              ci_umv_buf_t    *p_dest,\r
147         IN              ci_umv_buf_t    *p_src)\r
148 {\r
149         CL_ASSERT( p_dest );\r
150 \r
151         if( p_src )\r
152         {\r
153                 CL_ASSERT( p_dest->command == p_src->command );\r
154                 CL_ASSERT( p_dest->input_size == p_src->input_size );\r
155                 /* Copy output buf only on success. */\r
156                 if( p_src->status == IB_SUCCESS )\r
157                 {\r
158                         uint32_t        out_size;\r
159 \r
160                         out_size = MIN( p_dest->output_size, p_src->output_size );\r
161 \r
162                         if( cl_copy_to_user(\r
163                                 (void*)(ULONG_PTR)p_dest->p_inout_buf,\r
164                                 (void*)(ULONG_PTR)p_src->p_inout_buf,\r
165                                 out_size ) != CL_SUCCESS )\r
166                         {\r
167                                 p_dest->output_size = 0;\r
168                                 return IB_INVALID_PERMISSION;\r
169                         }\r
170                         p_dest->status = p_src->status;\r
171                         p_dest->output_size = out_size;\r
172                 }\r
173         }\r
174         return IB_SUCCESS;\r
175 }\r
176 \r
177 \r
178 void\r
179 free_umvbuf(\r
180         IN                              ci_umv_buf_t                            *p_umv_buf )\r
181 {\r
182         if( p_umv_buf )\r
183                 cl_free( p_umv_buf );\r
184 }\r
185 \r
186 \r
187 \r
188 /*\r
189  * Process the ioctl UAL_GET_VENDOR_LIBCFG:\r
190  */\r
191 static cl_status_t\r
192 proxy_get_vendor_libcfg(\r
193         IN              void                                    *p_open_context,\r
194         IN              cl_ioctl_handle_t               h_ioctl,\r
195                 OUT     size_t                                  *p_ret_bytes )\r
196 {\r
197         ual_get_uvp_name_ioctl_t        *p_ioctl =\r
198                         (ual_get_uvp_name_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
199         al_ci_ca_t                                      *p_ci_ca;\r
200 \r
201         AL_ENTER( AL_DBG_CA );\r
202 \r
203         UNUSED_PARAM( p_open_context );\r
204 \r
205         /* Validate input buffers. */\r
206         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
207                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
208                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
209         {\r
210                 AL_EXIT( AL_DBG_CA );\r
211                 return CL_INVALID_PARAMETER;\r
212         }\r
213 \r
214         /* Find the CAguid */\r
215         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CA,\r
216                         ("CA guid %I64x.\n", p_ioctl->in.ca_guid) );\r
217 \r
218         cl_spinlock_acquire( &gp_al_mgr->obj.lock );\r
219         p_ci_ca = find_ci_ca( p_ioctl->in.ca_guid );\r
220 \r
221         if( !p_ci_ca )\r
222         {\r
223                 cl_spinlock_release( &gp_al_mgr->obj.lock );\r
224                 p_ioctl->out.status = IB_NOT_FOUND;\r
225         }\r
226         else\r
227         {\r
228                 /* found the ca guid, copy the user-mode verbs provider libname */\r
229                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_CA,\r
230                                 ("CA guid %I64x. libname (%s)\n",\r
231                                 p_ioctl->in.ca_guid, p_ci_ca->verbs.libname) );\r
232                 cl_memcpy( p_ioctl->out.uvp_lib_name, p_ci_ca->verbs.libname,\r
233                         sizeof(p_ci_ca->verbs.libname));\r
234                 cl_spinlock_release( &gp_al_mgr->obj.lock );\r
235                 p_ioctl->out.status = IB_SUCCESS;\r
236         }\r
237         *p_ret_bytes = sizeof(p_ioctl->out);\r
238         AL_EXIT( AL_DBG_CA );\r
239         return CL_SUCCESS;\r
240 }\r
241 \r
242 \r
243 /*\r
244  * Allocate an ioctl buffer of appropriate size\r
245  * Copy the given ioctl buffer\r
246  * Queue the ioctl buffer as needed\r
247  */\r
248 boolean_t\r
249 proxy_queue_cb_buf(\r
250         IN              uintn_t                                 cb_type,\r
251         IN              al_dev_open_context_t   *p_context,\r
252         IN              void                                    *p_cb_data,\r
253         IN              al_obj_t                                *p_al_obj               OPTIONAL )\r
254 {\r
255         cl_qlist_t                                      *p_cb_list;\r
256         al_proxy_cb_info_t                      *p_cb_info;\r
257         cl_ioctl_handle_t                       *ph_ioctl, h_ioctl;\r
258         uintn_t                                         ioctl_size;\r
259 \r
260         AL_ENTER( AL_DBG_DEV );\r
261         \r
262         /* Set up the appropriate callback list. */\r
263         switch( cb_type )\r
264         {\r
265         case UAL_GET_COMP_CB_INFO:\r
266                 p_cb_list = &p_context->comp_cb_list;\r
267                 ph_ioctl = &p_context->h_comp_ioctl;\r
268                 ioctl_size = sizeof( comp_cb_ioctl_info_t );\r
269                 break;\r
270 \r
271         case UAL_GET_MISC_CB_INFO:\r
272                 p_cb_list = &p_context->misc_cb_list;\r
273                 ph_ioctl = &p_context->h_misc_ioctl;\r
274                 ioctl_size = sizeof( misc_cb_ioctl_info_t );\r
275                 break;\r
276 \r
277         default:\r
278                 return FALSE;\r
279         }\r
280 \r
281         /* Get a callback record to queue the callback. */\r
282         p_cb_info = proxy_cb_get( p_context );\r
283         if( !p_cb_info )\r
284                 return FALSE;\r
285 \r
286         cl_memcpy( &p_cb_info->cb_type, p_cb_data, ioctl_size );\r
287 \r
288         /*\r
289          * If an AL object was specified, we need to reference it to prevent its\r
290          * destruction until the callback has been fully specified.\r
291          */\r
292         if( p_al_obj )\r
293         {\r
294                 p_cb_info->p_al_obj = p_al_obj;\r
295                 ref_al_obj( p_al_obj );\r
296         }\r
297 \r
298         /* Insert the callback record into the callback list */\r
299         cl_spinlock_acquire( &p_context->cb_lock );\r
300         cl_qlist_insert_tail( p_cb_list, &p_cb_info->pool_item.list_item );\r
301 \r
302         /* See if there is a pending IOCTL ready to receive the callback. */\r
303         if( *ph_ioctl )\r
304         {\r
305                 h_ioctl = *ph_ioctl;\r
306                 *ph_ioctl = NULL;\r
307 #pragma warning(push, 3)\r
308                 IoSetCancelRoutine( h_ioctl, NULL );\r
309 #pragma warning(pop)\r
310 \r
311                 p_cb_info->reported = TRUE;\r
312 \r
313                 /* Complete the IOCTL to return the callback information. */\r
314                 CL_ASSERT( cl_ioctl_out_size( h_ioctl ) >= ioctl_size );\r
315                 cl_memcpy( cl_ioctl_out_buf( h_ioctl ), p_cb_data, ioctl_size );\r
316                 cl_ioctl_complete( h_ioctl, CL_SUCCESS, ioctl_size );\r
317                 proxy_context_deref( p_context );\r
318         }\r
319         cl_spinlock_release( &p_context->cb_lock );\r
320 \r
321         AL_EXIT( AL_DBG_DEV );\r
322         return TRUE;\r
323 }\r
324 \r
325 \r
326 /*\r
327  * Proxy's ca error callback\r
328  * The context in the error record is proxy's ca context\r
329  * Context is the a list object in the CA list\r
330  */\r
331 static void\r
332 proxy_ca_err_cb(\r
333         IN ib_async_event_rec_t *p_err_rec)\r
334 {\r
335         ib_ca_handle_t                  h_ca = p_err_rec->handle.h_ca;\r
336         al_dev_open_context_t   *p_context = h_ca->obj.h_al->p_context;\r
337         misc_cb_ioctl_info_t    cb_info;\r
338 \r
339         /*\r
340          * If we're already closing the device - do not queue a callback, since\r
341          * we're cleaning up the callback lists.\r
342          */\r
343         if( !proxy_context_ref( p_context ) )\r
344         {\r
345                 proxy_context_deref( p_context );\r
346                 return;\r
347         }\r
348 \r
349         /* Set up context and callback record type appropriate for UAL */\r
350         cb_info.rec_type = CA_ERROR_REC;\r
351         /* Return the Proxy's open_ca handle and the user's context */\r
352         cb_info.ioctl_rec.event_rec = *p_err_rec;\r
353         cb_info.ioctl_rec.event_rec.handle.h_ca = (ib_ca_handle_t)HDL_TO_PTR(h_ca->obj.hdl);\r
354 \r
355         /* The proxy handle must be valid now. */\r
356         if( !h_ca->obj.hdl_valid )\r
357                 h_ca->obj.hdl_valid = TRUE;\r
358 \r
359         proxy_queue_cb_buf( UAL_GET_MISC_CB_INFO, p_context, &cb_info,\r
360                 &h_ca->obj );\r
361 \r
362         proxy_context_deref( p_context );\r
363 }\r
364 \r
365 \r
366 /*\r
367  * Process the ioctl UAL_OPEN_CA:\r
368  *\r
369  * Returns the ca_list_obj as the handle to UAL\r
370  */\r
371 static cl_status_t\r
372 proxy_open_ca(\r
373         IN              void                                    *p_open_context,\r
374         IN              cl_ioctl_handle_t               h_ioctl,\r
375                 OUT     size_t                                  *p_ret_bytes )\r
376 {\r
377         ual_open_ca_ioctl_t             *p_ioctl =\r
378                 (ual_open_ca_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
379         al_dev_open_context_t   *p_context =\r
380                 (al_dev_open_context_t *)p_open_context;\r
381         ib_ca_handle_t                  h_ca;\r
382         ci_umv_buf_t                    *p_umv_buf = NULL;\r
383         ib_api_status_t                 status;\r
384 \r
385         AL_ENTER( AL_DBG_CA );\r
386 \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                 AL_EXIT( AL_DBG_CA );\r
393                 return CL_INVALID_PARAMETER;\r
394         }\r
395 \r
396         /* Set the return bytes in all cases. */\r
397         *p_ret_bytes = sizeof(p_ioctl->out);\r
398 \r
399         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
400         if( status != IB_SUCCESS )\r
401                 goto proxy_open_ca_err;\r
402 \r
403         status = open_ca( p_context->h_al, p_ioctl->in.guid, proxy_ca_err_cb,\r
404                 p_ioctl->in.context, &h_ca, p_umv_buf );\r
405         if( status != IB_SUCCESS )\r
406                 goto proxy_open_ca_err;\r
407 \r
408         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
409         if( status == IB_SUCCESS )\r
410         {\r
411                 p_ioctl->out.h_ca = h_ca->obj.hdl;\r
412                 h_ca->obj.hdl_valid = TRUE;\r
413                 /* Release the reference taken in init_al_obj */\r
414                 deref_al_obj( &h_ca->obj );\r
415         }\r
416         else\r
417         {\r
418                 h_ca->obj.pfn_destroy( &h_ca->obj, NULL );\r
419 \r
420 proxy_open_ca_err:      /* getting a handle failed. */\r
421                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
422                 p_ioctl->out.h_ca = AL_INVALID_HANDLE;\r
423         }\r
424         free_umvbuf( p_umv_buf );\r
425 \r
426         p_ioctl->out.status = status;\r
427 \r
428         AL_EXIT( AL_DBG_CA );\r
429         return CL_SUCCESS;\r
430 }\r
431 \r
432 \r
433 \r
434 /*\r
435  * Process the ioctl UAL_QUERY_CA:\r
436  */\r
437 static cl_status_t\r
438 proxy_query_ca(\r
439         IN              void                                    *p_open_context,\r
440         IN              cl_ioctl_handle_t               h_ioctl,\r
441                 OUT     size_t                                  *p_ret_bytes )\r
442 {\r
443         ual_query_ca_ioctl_t    *p_ioctl =\r
444                         (ual_query_ca_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
445         al_dev_open_context_t   *p_context =\r
446                                                         (al_dev_open_context_t *)p_open_context;\r
447         ib_ca_handle_t                  h_ca;\r
448         ib_ca_attr_t                    *p_ca_attr = NULL;\r
449         ci_umv_buf_t                    *p_umv_buf = NULL;\r
450         ib_api_status_t                 status;\r
451         uint32_t                                byte_cnt = 0;\r
452 \r
453         AL_ENTER( AL_DBG_CA );\r
454 \r
455         /* Validate input buffers. */\r
456         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
457                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
458                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
459         {\r
460                 AL_EXIT( AL_DBG_CA );\r
461                 return CL_INVALID_PARAMETER;\r
462         }\r
463 \r
464         /* Set the return bytes in all cases */\r
465         *p_ret_bytes = sizeof(p_ioctl->out);\r
466 \r
467         /* Validate CA handle */\r
468         h_ca = (ib_ca_handle_t)\r
469                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
470         if( !h_ca )\r
471         {\r
472                 status = IB_INVALID_CA_HANDLE;\r
473                 goto proxy_query_ca_err;\r
474         }\r
475 \r
476         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
477         if( status != IB_SUCCESS )\r
478                 goto proxy_query_ca_err;\r
479 \r
480         byte_cnt = p_ioctl->in.byte_cnt;\r
481         if( p_ioctl->in.p_ca_attr && byte_cnt )\r
482         {\r
483                 p_ca_attr = (ib_ca_attr_t*)cl_zalloc( byte_cnt );\r
484                 if( !p_ca_attr )\r
485                 {\r
486                         status = IB_INSUFFICIENT_MEMORY;\r
487                         goto proxy_query_ca_err;\r
488                 }\r
489         }\r
490         status = query_ca( h_ca, p_ca_attr, &byte_cnt, p_umv_buf );\r
491 \r
492         if( status != IB_SUCCESS )\r
493                 goto proxy_query_ca_err;\r
494 \r
495         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
496 \r
497         if( status != IB_SUCCESS )\r
498                 goto proxy_query_ca_err;\r
499 \r
500         /* copy CA attribute back to user */\r
501         if( p_ca_attr )\r
502         {\r
503                 __try\r
504                 {\r
505                         ProbeForWrite( p_ioctl->in.p_ca_attr, byte_cnt, sizeof(void*) );\r
506                         ib_copy_ca_attr( p_ioctl->in.p_ca_attr, p_ca_attr );\r
507                 }\r
508                 __except(EXCEPTION_EXECUTE_HANDLER)\r
509                 {\r
510                         AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
511                                 ("Failed to copy CA attributes to user buffer %016I64x\n",\r
512                                 (LONG64)p_ioctl->in.p_ca_attr) );\r
513                         status = IB_INVALID_PERMISSION;\r
514                 }\r
515         }\r
516 \r
517         /* Free the ca_attr buffer allocated locally */\r
518         if( status != IB_SUCCESS )\r
519         {\r
520 proxy_query_ca_err:\r
521                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
522         }\r
523         if( p_ca_attr )\r
524                 cl_free( p_ca_attr );\r
525 \r
526         free_umvbuf( p_umv_buf );\r
527 \r
528         if( h_ca )\r
529                 deref_al_obj( &h_ca->obj );\r
530 \r
531         p_ioctl->out.status = status;\r
532         p_ioctl->out.byte_cnt = byte_cnt;\r
533 \r
534         AL_EXIT( AL_DBG_CA );\r
535         return CL_SUCCESS;\r
536 }\r
537 \r
538 \r
539 /*\r
540  * Process the ioctl UAL_MODIFY_CA:\r
541  */\r
542 static\r
543 cl_status_t\r
544 proxy_modify_ca(\r
545         IN              void                                    *p_open_context,\r
546         IN              cl_ioctl_handle_t               h_ioctl,\r
547                 OUT     size_t                                  *p_ret_bytes )\r
548 {\r
549         ual_modify_ca_ioctl_t   *p_ioctl =\r
550                         (ual_modify_ca_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
551         al_dev_open_context_t   *p_context =\r
552                                                         (al_dev_open_context_t *)p_open_context;\r
553         ib_ca_handle_t                  h_ca;\r
554 \r
555         AL_ENTER( AL_DBG_CA );\r
556 \r
557         /* Validate input buffers. */\r
558         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
559                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
560                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
561         {\r
562                 AL_EXIT( AL_DBG_CA );\r
563                 return CL_INVALID_PARAMETER;\r
564         }\r
565 \r
566         /* Set the return bytes in all cases */\r
567         *p_ret_bytes = sizeof(p_ioctl->out);\r
568 \r
569         /* Validate CA handle */\r
570         h_ca = (ib_ca_handle_t)\r
571                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
572         if( !h_ca )\r
573         {\r
574                 p_ioctl->out.status = IB_INVALID_CA_HANDLE;\r
575                 AL_EXIT( AL_DBG_CA );\r
576                 return CL_SUCCESS;\r
577         }\r
578 \r
579         p_ioctl->out.status = ib_modify_ca( h_ca, p_ioctl->in.port_num,\r
580                 p_ioctl->in.ca_mod, &p_ioctl->in.port_attr_mod );\r
581 \r
582         deref_al_obj( &h_ca->obj );\r
583 \r
584         AL_EXIT( AL_DBG_CA );\r
585         return CL_SUCCESS;\r
586 }\r
587 \r
588 \r
589 /*\r
590  * Process the ioctl UAL_CLOSE_CA:\r
591  */\r
592 static\r
593 cl_status_t\r
594 proxy_close_ca(\r
595         IN              void                                    *p_open_context,\r
596         IN              cl_ioctl_handle_t               h_ioctl,\r
597                 OUT     size_t                                  *p_ret_bytes )\r
598 {\r
599         ual_close_ca_ioctl_t    *p_ioctl =\r
600                         (ual_close_ca_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
601         al_dev_open_context_t   *p_context =\r
602                                                         (al_dev_open_context_t *)p_open_context;\r
603         ib_ca_handle_t                  h_ca;\r
604 \r
605         AL_ENTER( AL_DBG_CA );\r
606 \r
607         /* Validate input buffers. */\r
608         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
609                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
610                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
611         {\r
612                 AL_EXIT( AL_DBG_CA );\r
613                 return CL_INVALID_PARAMETER;\r
614         }\r
615 \r
616         /* Set the return bytes in all cases */\r
617         *p_ret_bytes = sizeof(p_ioctl->out);\r
618 \r
619         /* Validate CA handle */\r
620         h_ca = (ib_ca_handle_t)\r
621                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
622         if( !h_ca )\r
623         {\r
624                 p_ioctl->out.status = IB_INVALID_CA_HANDLE;\r
625                 AL_EXIT( AL_DBG_CA );\r
626                 return CL_SUCCESS;\r
627         }\r
628 \r
629         /*\r
630          * Note that we hold a reference on the CA, so we need to\r
631          * call close_ca, not ib_close_ca.  We also don't release the reference\r
632          * since close_ca will do so (by destroying the object).\r
633          */\r
634         h_ca->obj.pfn_destroy( &h_ca->obj, ib_sync_destroy );\r
635         p_ioctl->out.status = IB_SUCCESS;\r
636 \r
637         AL_EXIT( AL_DBG_CA );\r
638         return CL_SUCCESS;\r
639 }\r
640 \r
641 \r
642 /*\r
643  * Validates the proxy handles and converts them to AL handles\r
644  */\r
645 static ib_api_status_t\r
646 __convert_to_al_handles(\r
647         IN                              al_dev_open_context_t*  const   p_context,\r
648         IN                              uint64_t*                               const   um_handle_array,\r
649         IN                              uint32_t                                                num_handles,\r
650                 OUT                     void**                                  const   p_handle_array )\r
651 {\r
652         uint32_t                                i;\r
653 \r
654         for( i = 0; i < num_handles; i++ )\r
655         {\r
656                 /* Validate the handle in the resource map */\r
657                 p_handle_array[i] = al_hdl_ref(\r
658                         p_context->h_al, um_handle_array[i], AL_OBJ_TYPE_UNKNOWN );\r
659                 if( !p_handle_array[i] )\r
660                 {\r
661                         /* Release references taken so far. */\r
662                         while( i-- )\r
663                                 deref_al_obj( p_handle_array[i] );\r
664 \r
665                         /* Could not find the handle in the map */\r
666                         return IB_INVALID_HANDLE;\r
667                 }\r
668         }\r
669 \r
670         return IB_SUCCESS;\r
671 }\r
672 \r
673 \r
674 \r
675 static\r
676 cl_status_t\r
677 proxy_ci_call(\r
678         IN              void                                    *p_open_context,\r
679         IN              cl_ioctl_handle_t               h_ioctl,\r
680                 OUT     size_t                                  *p_ret_bytes )\r
681 {\r
682         ual_ci_call_ioctl_t     *p_ioctl =\r
683                 (ual_ci_call_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
684         al_dev_open_context_t   *p_context =\r
685                 (al_dev_open_context_t *)p_open_context;\r
686         ib_ca_handle_t                  h_ca;\r
687         ci_umv_buf_t                    *p_umv_buf = NULL;\r
688         void*                                   p_ci_op_buf = NULL;\r
689         void*                                   p_ci_op_user_buf = NULL;\r
690         void**                                  p_handle_array = NULL;\r
691         size_t                                  ci_op_buf_size;\r
692         ib_api_status_t                 status;\r
693         uint32_t                                num_handles;\r
694 \r
695         AL_ENTER( AL_DBG_CA );\r
696 \r
697         /* Validate input buffers. */\r
698         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
699                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
700                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
701         {\r
702                 AL_EXIT( AL_DBG_CA );\r
703                 return CL_INVALID_PARAMETER;\r
704         }\r
705 \r
706         num_handles = p_ioctl->in.num_handles;\r
707         if( num_handles > 1 &&\r
708                 cl_ioctl_in_size( h_ioctl ) != (sizeof(uint64_t) * (num_handles - 1)) )\r
709         {\r
710                 AL_EXIT( AL_DBG_CA );\r
711                 return CL_INVALID_PARAMETER;\r
712         }\r
713 \r
714         ci_op_buf_size = (size_t)p_ioctl->in.ci_op.buf_size;\r
715 \r
716         /* Set the return bytes in all cases */\r
717         *p_ret_bytes = sizeof(p_ioctl->out);\r
718 \r
719         /* Validate CA handle */\r
720         h_ca = (ib_ca_handle_t)\r
721                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
722         if( !h_ca )\r
723         {\r
724                 p_ioctl->out.status = IB_INVALID_CA_HANDLE;\r
725                 AL_EXIT( AL_DBG_CA );\r
726                 return CL_SUCCESS;\r
727         }\r
728 \r
729         /* Save the user buffer address */\r
730         p_ci_op_user_buf = p_ioctl->in.ci_op.p_buf;\r
731 \r
732         /* Validate the handle array */\r
733         if( num_handles )\r
734         {\r
735                 p_handle_array = cl_malloc( sizeof(void*) * num_handles );\r
736                 if( !p_handle_array )\r
737                 {\r
738                         p_ioctl->out.status = IB_INSUFFICIENT_MEMORY;\r
739                         deref_al_obj( &h_ca->obj );\r
740                         AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Failed to allocate handle array.\n") );\r
741                         return CL_SUCCESS;\r
742                 }\r
743 \r
744                 /*\r
745                  * Now we have the handle array in kernel space. Replace\r
746                  * the handles with the correct AL handles based on the\r
747                  * type\r
748                  */\r
749                 status = __convert_to_al_handles( p_context, p_ioctl->in.handle_array,\r
750                         num_handles, p_handle_array );\r
751                 if( status != IB_SUCCESS )\r
752                 {\r
753                         cl_free( p_handle_array );\r
754                         p_ioctl->out.status = status;\r
755                         deref_al_obj( &h_ca->obj );\r
756                         AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Failed to convert handles.\n") );\r
757                         return CL_SUCCESS;\r
758                 }\r
759         }\r
760 \r
761         /* Copy in the UMV buffer */\r
762         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
763         if( status != IB_SUCCESS )\r
764                 goto proxy_ci_call_err;\r
765 \r
766         if( p_ioctl->in.ci_op.buf_size && p_ioctl->in.ci_op.p_buf )\r
767         {\r
768                 p_ci_op_buf = cl_zalloc( ci_op_buf_size );\r
769                 if( !p_ci_op_buf )\r
770                 {\r
771                         status = IB_INSUFFICIENT_MEMORY;\r
772                         goto proxy_ci_call_err;\r
773                 }\r
774 \r
775                 /* Copy from user the buffer */\r
776                 if( cl_copy_from_user( p_ci_op_buf, p_ioctl->in.ci_op.p_buf,\r
777                         ci_op_buf_size ) != CL_SUCCESS )\r
778                 {\r
779                         status = IB_INVALID_PERMISSION;\r
780                         goto proxy_ci_call_err;\r
781                 }\r
782                 /* Update the buffer pointer to reference the kernel copy. */\r
783                 p_ioctl->in.ci_op.p_buf = p_ci_op_buf;\r
784         }\r
785 \r
786         status = ci_call( h_ca, p_handle_array,\r
787                 num_handles, &p_ioctl->in.ci_op, p_umv_buf );\r
788         if( status != IB_SUCCESS )\r
789                 goto proxy_ci_call_err;\r
790 \r
791         /* Copy the umv_buf back to user space */\r
792         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
793         if( status != IB_SUCCESS )\r
794         {\r
795                 status = IB_INVALID_PERMISSION;\r
796                 goto proxy_ci_call_err;\r
797         }\r
798 \r
799         /*\r
800          * Copy the data buffer.  Copy the buf size so that if the\r
801          * num_bytes_ret is greater than the buffer size, we copy\r
802          * only what the buffer can hold\r
803          */\r
804         if( cl_copy_to_user( p_ci_op_user_buf, p_ioctl->in.ci_op.p_buf,\r
805                 ci_op_buf_size ) != CL_SUCCESS )\r
806         {\r
807                 status = IB_INVALID_PERMISSION;\r
808         }\r
809 \r
810 proxy_ci_call_err:\r
811 \r
812         /* Restore the data buffer */\r
813         p_ioctl->out.ci_op.p_buf = p_ci_op_user_buf;\r
814         p_ioctl->out.status = status;\r
815 \r
816         /* Release the resources allocated */\r
817         if( p_handle_array )\r
818         {\r
819                 while( num_handles-- )\r
820                         deref_al_obj( (al_obj_t*)p_handle_array[num_handles] );\r
821                 cl_free( p_handle_array );\r
822         }\r
823         if( p_ci_op_buf )\r
824                 cl_free( p_ci_op_buf );\r
825 \r
826         free_umvbuf( p_umv_buf );\r
827 \r
828         deref_al_obj( &h_ca->obj );\r
829 \r
830         AL_EXIT( AL_DBG_CA );\r
831         return CL_SUCCESS;\r
832 }\r
833 \r
834 \r
835 /*\r
836  * Process the ioctl UAL_ALLOC_PD:\r
837  *\r
838  * Returns the pd_list_obj as the handle to UAL\r
839  */\r
840 static\r
841 cl_status_t\r
842 proxy_alloc_pd(\r
843         IN              void                                    *p_open_context,\r
844         IN              cl_ioctl_handle_t               h_ioctl,\r
845                 OUT     size_t                                  *p_ret_bytes )\r
846 {\r
847         ual_alloc_pd_ioctl_t    *p_ioctl =\r
848                 (ual_alloc_pd_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
849         al_dev_open_context_t   *p_context =\r
850                 (al_dev_open_context_t *)p_open_context;\r
851         ib_ca_handle_t                  h_ca;\r
852         ib_pd_handle_t                  h_pd;\r
853         ci_umv_buf_t                    *p_umv_buf = NULL;\r
854         ib_api_status_t                 status;\r
855 \r
856         AL_ENTER( AL_DBG_PD );\r
857 \r
858         /* Validate input buffers. */\r
859         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
860                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
861                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
862         {\r
863                 AL_EXIT( AL_DBG_PD );\r
864                 return CL_INVALID_PARAMETER;\r
865         }\r
866 \r
867         /* Validate CA handle */\r
868         h_ca = (ib_ca_handle_t)\r
869                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
870         if( !h_ca )\r
871         {\r
872                 status = IB_INVALID_CA_HANDLE;\r
873                 goto proxy_alloc_pd_err;\r
874         }\r
875 \r
876         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
877         if( status != IB_SUCCESS )\r
878                 goto proxy_alloc_pd_err;\r
879 \r
880         status = alloc_pd( h_ca, p_ioctl->in.type, p_ioctl->in.context,\r
881                 &h_pd, p_umv_buf );\r
882 \r
883         if( status != IB_SUCCESS )\r
884                 goto proxy_alloc_pd_err;\r
885 \r
886         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
887         if( status == IB_SUCCESS )\r
888         {\r
889                 p_ioctl->out.h_pd = h_pd->obj.hdl;\r
890                 h_pd->obj.hdl_valid = TRUE;\r
891                 deref_al_obj( &h_pd->obj );\r
892         }\r
893         else\r
894         {\r
895                 h_pd->obj.pfn_destroy( &h_pd->obj, NULL );\r
896 \r
897 proxy_alloc_pd_err:\r
898                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
899                 p_ioctl->out.h_pd = AL_INVALID_HANDLE;\r
900         }\r
901         free_umvbuf( p_umv_buf );\r
902 \r
903         if( h_ca )\r
904                 deref_al_obj( &h_ca->obj );\r
905 \r
906         p_ioctl->out.status = status;\r
907         *p_ret_bytes = sizeof(p_ioctl->out);\r
908 \r
909         AL_EXIT( AL_DBG_PD );\r
910         return CL_SUCCESS;\r
911 }\r
912 \r
913 \r
914 /*\r
915  * Process the ioctl UAL_DEALLOC_PD:\r
916  */\r
917 static cl_status_t\r
918 proxy_dealloc_pd(\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_dealloc_pd_ioctl_t  *p_ioctl =\r
924                 (ual_dealloc_pd_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_pd_handle_t                  h_pd;\r
928 \r
929         AL_ENTER( AL_DBG_PD );\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                 AL_EXIT( AL_DBG_PD );\r
937                 return CL_INVALID_PARAMETER;\r
938         }\r
939 \r
940         /* Set the return bytes in all cases */\r
941         *p_ret_bytes = sizeof(p_ioctl->out);\r
942 \r
943         /* Validate PD handle */\r
944         h_pd = (ib_pd_handle_t)al_hdl_ref(\r
945                 p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
946         if( !h_pd )\r
947         {\r
948                 p_ioctl->out.status = IB_INVALID_PD_HANDLE;\r
949                 AL_EXIT( AL_DBG_PD );\r
950                 return CL_SUCCESS;\r
951         }\r
952 \r
953         h_pd->obj.pfn_destroy( &h_pd->obj, ib_sync_destroy );\r
954         p_ioctl->out.status = IB_SUCCESS;\r
955 \r
956         AL_EXIT( AL_DBG_PD );\r
957         return CL_SUCCESS;\r
958 }\r
959 \r
960 \r
961 /*\r
962  * Proxy's SRQ error handler\r
963  */\r
964 static void\r
965 proxy_srq_err_cb(\r
966         IN ib_async_event_rec_t *p_err_rec )\r
967 {\r
968         ib_srq_handle_t h_srq = p_err_rec->handle.h_srq;\r
969         al_dev_open_context_t   *p_context = h_srq->obj.h_al->p_context;\r
970         misc_cb_ioctl_info_t    cb_info;\r
971 \r
972         AL_ENTER( AL_DBG_QP );\r
973 \r
974         /*\r
975          * If we're already closing the device - do not queue a callback, since\r
976          * we're cleaning up the callback lists.\r
977          */\r
978         if( !proxy_context_ref( p_context ) )\r
979         {\r
980                 proxy_context_deref( p_context );\r
981                 return;\r
982         }\r
983 \r
984         /* Set up context and callback record type appropriate for UAL */\r
985         cb_info.rec_type = SRQ_ERROR_REC;\r
986         /* Return the Proxy's SRQ handle and the user's context */\r
987         cb_info.ioctl_rec.event_rec = *p_err_rec;\r
988         cb_info.ioctl_rec.event_rec.handle.h_srq = (ib_srq_handle_t) HDL_TO_PTR(h_srq->obj.hdl);\r
989 \r
990         /* The proxy handle must be valid now. */\r
991         if( !h_srq->obj.hdl_valid )\r
992                 h_srq->obj.hdl_valid = TRUE;\r
993 \r
994         proxy_queue_cb_buf(\r
995                 UAL_GET_MISC_CB_INFO, p_context, &cb_info, &h_srq->obj );\r
996 \r
997         proxy_context_deref( p_context );\r
998 \r
999         AL_EXIT( AL_DBG_QP );\r
1000 }\r
1001 \r
1002 /*\r
1003  * Process the ioctl UAL_CREATE_SRQ\r
1004  *\r
1005  * Returns the srq_list_obj as the handle to UAL\r
1006  */\r
1007 static cl_status_t\r
1008 proxy_create_srq(\r
1009         IN              void                                    *p_open_context,\r
1010         IN              cl_ioctl_handle_t               h_ioctl,\r
1011                 OUT     size_t                                  *p_ret_bytes )\r
1012 {\r
1013         ual_create_srq_ioctl_t  *p_ioctl =\r
1014                 (ual_create_srq_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
1015         al_dev_open_context_t   *p_context =\r
1016                 (al_dev_open_context_t *)p_open_context;\r
1017         ib_pd_handle_t                  h_pd;\r
1018         ib_srq_handle_t                 h_srq;\r
1019         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1020         ib_api_status_t                 status;\r
1021         ib_pfn_event_cb_t               pfn_ev;\r
1022 \r
1023         AL_ENTER( AL_DBG_SRQ );\r
1024 \r
1025         /* Validate input buffers. */\r
1026         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1027                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1028                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1029         {\r
1030                 AL_EXIT( AL_DBG_SRQ );\r
1031                 return CL_INVALID_PARAMETER;\r
1032         }\r
1033 \r
1034         /* Validate handles. */\r
1035         h_pd = (ib_pd_handle_t)\r
1036                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
1037         if( !h_pd)\r
1038         {\r
1039                 status = IB_INVALID_PD_HANDLE;\r
1040                 goto proxy_create_srq_err1;\r
1041         }\r
1042 \r
1043         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1044         if( status != IB_SUCCESS )\r
1045                 goto proxy_create_srq_err1;\r
1046 \r
1047         if( p_ioctl->in.ev_notify )\r
1048                 pfn_ev = proxy_srq_err_cb;\r
1049         else\r
1050                 pfn_ev = NULL;\r
1051 \r
1052         status = create_srq( h_pd, &p_ioctl->in.srq_attr, p_ioctl->in.context,\r
1053                 pfn_ev, &h_srq, p_umv_buf );\r
1054         if( status != IB_SUCCESS )\r
1055                 goto proxy_create_srq_err1;\r
1056 \r
1057         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1058         if( status == IB_SUCCESS )\r
1059         {\r
1060                 p_ioctl->out.h_srq = h_srq->obj.hdl;\r
1061                 h_srq->obj.hdl_valid = TRUE;\r
1062                 /* Release the reference taken in create_srq (by init_al_obj) */\r
1063                 deref_al_obj( &h_srq->obj );\r
1064         }\r
1065         else\r
1066         {\r
1067 proxy_create_srq_err1:\r
1068                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1069                 p_ioctl->out.h_srq = AL_INVALID_HANDLE;\r
1070         }\r
1071         free_umvbuf( p_umv_buf );\r
1072 \r
1073         p_ioctl->out.status = status;\r
1074         *p_ret_bytes = sizeof(p_ioctl->out);\r
1075 \r
1076         if( h_pd )\r
1077                 deref_al_obj( &h_pd->obj );\r
1078 \r
1079         AL_EXIT( AL_DBG_SRQ );\r
1080         return CL_SUCCESS;\r
1081 }\r
1082 \r
1083 \r
1084 /*\r
1085  * Process the ioctl UAL_QUERY_SRQ:\r
1086  */\r
1087 static\r
1088 cl_status_t\r
1089 proxy_query_srq(\r
1090         IN              void                                    *p_open_context,\r
1091         IN              cl_ioctl_handle_t               h_ioctl,\r
1092                 OUT     size_t                                  *p_ret_bytes )\r
1093 {\r
1094         ual_query_srq_ioctl_t   *p_ioctl =\r
1095                 (ual_query_srq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1096         al_dev_open_context_t   *p_context =\r
1097                 (al_dev_open_context_t *)p_open_context;\r
1098         ib_srq_handle_t                 h_srq;\r
1099         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1100         ib_api_status_t                 status;\r
1101 \r
1102         AL_ENTER( AL_DBG_SRQ );\r
1103 \r
1104         /* Validate input buffers. */\r
1105         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1106                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1107                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1108         {\r
1109                 AL_EXIT( AL_DBG_SRQ );\r
1110                 return CL_INVALID_PARAMETER;\r
1111         }\r
1112 \r
1113         /* Validate SRQ handle */\r
1114         h_srq = (ib_srq_handle_t)\r
1115                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_srq, AL_OBJ_TYPE_H_SRQ );\r
1116         if( !h_srq )\r
1117         {\r
1118                 status = IB_INVALID_SRQ_HANDLE;\r
1119                 goto proxy_query_srq_err;\r
1120         }\r
1121 \r
1122         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1123         if( status != IB_SUCCESS )\r
1124                 goto proxy_query_srq_err;\r
1125 \r
1126         status = query_srq( h_srq, &p_ioctl->out.srq_attr, p_umv_buf );\r
1127         if( status != IB_SUCCESS )\r
1128                 goto proxy_query_srq_err;\r
1129 \r
1130         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1131         if( status != IB_SUCCESS )\r
1132         {\r
1133 proxy_query_srq_err:\r
1134                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1135                 cl_memclr( &p_ioctl->out.srq_attr, sizeof(ib_srq_attr_t) );\r
1136         }\r
1137         free_umvbuf( p_umv_buf );\r
1138 \r
1139         if( h_srq )\r
1140                 deref_al_obj( &h_srq->obj );\r
1141 \r
1142         p_ioctl->out.status = status;\r
1143         *p_ret_bytes = sizeof(p_ioctl->out);\r
1144 \r
1145         AL_EXIT( AL_DBG_SRQ );\r
1146         return CL_SUCCESS;\r
1147 }\r
1148 \r
1149 \r
1150 \r
1151 /*\r
1152  * Process the ioctl UAL_MODIFY_SRQ:\r
1153  */\r
1154 static\r
1155 cl_status_t\r
1156 proxy_modify_srq(\r
1157         IN              void                                    *p_open_context,\r
1158         IN              cl_ioctl_handle_t               h_ioctl,\r
1159                 OUT     size_t                                  *p_ret_bytes )\r
1160 {\r
1161         ual_modify_srq_ioctl_t  *p_ioctl =\r
1162                 (ual_modify_srq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1163         al_dev_open_context_t   *p_context =\r
1164                 (al_dev_open_context_t *)p_open_context;\r
1165         ib_srq_handle_t                 h_srq;\r
1166         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1167         ib_api_status_t                 status;\r
1168 \r
1169         AL_ENTER( AL_DBG_SRQ );\r
1170 \r
1171         /* Validate input buffers. */\r
1172         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1173                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1174                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1175         {\r
1176                 AL_EXIT( AL_DBG_SRQ );\r
1177                 return CL_INVALID_PARAMETER;\r
1178         }\r
1179 \r
1180         /* Validate SRQ handle */\r
1181         h_srq = (ib_srq_handle_t)\r
1182                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_srq, AL_OBJ_TYPE_H_SRQ );\r
1183         if( !h_srq )\r
1184         {\r
1185                 status = IB_INVALID_SRQ_HANDLE;\r
1186                 goto proxy_modify_srq_err;\r
1187         }\r
1188 \r
1189         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1190         if( status != IB_SUCCESS )\r
1191                 goto proxy_modify_srq_err;\r
1192 \r
1193         status = modify_srq( h_srq, &p_ioctl->in.srq_attr, p_ioctl->in.srq_attr_mask, p_umv_buf );\r
1194 \r
1195         if( status != IB_SUCCESS )\r
1196                 goto proxy_modify_srq_err;\r
1197         \r
1198         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1199         if( status != IB_SUCCESS )\r
1200         {\r
1201 proxy_modify_srq_err:\r
1202                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1203         }\r
1204         free_umvbuf( p_umv_buf );\r
1205 \r
1206         if( h_srq )\r
1207                 deref_al_obj( &h_srq->obj );\r
1208 \r
1209         p_ioctl->out.status = status;\r
1210         *p_ret_bytes = sizeof(p_ioctl->out);\r
1211 \r
1212         AL_EXIT( AL_DBG_SRQ );\r
1213         return CL_SUCCESS;\r
1214 }\r
1215 \r
1216 \r
1217 /*\r
1218  * Process the ioctl UAL_DESTROY_SRQ\r
1219  */\r
1220 static cl_status_t\r
1221 proxy_destroy_srq(\r
1222         IN              void                                    *p_open_context,\r
1223         IN              cl_ioctl_handle_t               h_ioctl,\r
1224                 OUT     size_t                                  *p_ret_bytes )\r
1225 {\r
1226         ual_destroy_srq_ioctl_t *p_ioctl =\r
1227                 (ual_destroy_srq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1228         al_dev_open_context_t   *p_context =\r
1229                 (al_dev_open_context_t *)p_open_context;\r
1230         ib_srq_handle_t                 h_srq;\r
1231 \r
1232         AL_ENTER( AL_DBG_SRQ );\r
1233 \r
1234         /* Validate input buffers. */\r
1235         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1236                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1237                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1238         {\r
1239                 AL_EXIT( AL_DBG_SRQ );\r
1240                 return CL_INVALID_PARAMETER;\r
1241         }\r
1242 \r
1243         /* Set the return bytes in all cases */\r
1244         *p_ret_bytes = sizeof(p_ioctl->out);\r
1245 \r
1246         /* Validate SRQ handle */\r
1247         h_srq = (ib_srq_handle_t)\r
1248                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_srq, AL_OBJ_TYPE_H_SRQ );\r
1249         if( !h_srq )\r
1250         {\r
1251                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_SRQ_HANDLE\n") );\r
1252                 p_ioctl->out.status = IB_INVALID_SRQ_HANDLE;\r
1253         }\r
1254         else\r
1255         {\r
1256                 h_srq->obj.pfn_destroy( &h_srq->obj, ib_sync_destroy );\r
1257                 p_ioctl->out.status = IB_SUCCESS;\r
1258         }\r
1259 \r
1260         AL_EXIT( AL_DBG_SRQ );\r
1261         return CL_SUCCESS;\r
1262 }\r
1263 \r
1264 \r
1265 /*\r
1266  * Proxy's QP error handler\r
1267  */\r
1268 static void\r
1269 proxy_qp_err_cb(\r
1270         IN ib_async_event_rec_t *p_err_rec )\r
1271 {\r
1272         ib_qp_handle_t                  h_qp = p_err_rec->handle.h_qp;\r
1273         al_dev_open_context_t   *p_context = h_qp->obj.h_al->p_context;\r
1274         misc_cb_ioctl_info_t    cb_info;\r
1275 \r
1276         AL_ENTER( AL_DBG_QP );\r
1277 \r
1278         /*\r
1279          * If we're already closing the device - do not queue a callback, since\r
1280          * we're cleaning up the callback lists.\r
1281          */\r
1282         if( !proxy_context_ref( p_context ) )\r
1283         {\r
1284                 proxy_context_deref( p_context );\r
1285                 return;\r
1286         }\r
1287 \r
1288         /* Set up context and callback record type appropriate for UAL */\r
1289         cb_info.rec_type = QP_ERROR_REC;\r
1290         /* Return the Proxy's QP handle and the user's context */\r
1291         cb_info.ioctl_rec.event_rec = *p_err_rec;\r
1292         cb_info.ioctl_rec.event_rec.handle.h_qp = (ib_qp_handle_t)HDL_TO_PTR(h_qp->obj.hdl);\r
1293 \r
1294         /* The proxy handle must be valid now. */\r
1295         if( !h_qp->obj.hdl_valid )\r
1296                 h_qp->obj.hdl_valid = TRUE;\r
1297 \r
1298         proxy_queue_cb_buf(\r
1299                 UAL_GET_MISC_CB_INFO, p_context, &cb_info, &h_qp->obj );\r
1300 \r
1301         proxy_context_deref( p_context );\r
1302 \r
1303         AL_EXIT( AL_DBG_QP );\r
1304 }\r
1305 \r
1306 \r
1307 \r
1308 /*\r
1309  * Process the ioctl UAL_CREATE_QP\r
1310  *\r
1311  * Returns the qp_list_obj as the handle to UAL\r
1312  */\r
1313 static cl_status_t\r
1314 proxy_create_qp(\r
1315         IN              void                                    *p_open_context,\r
1316         IN              cl_ioctl_handle_t               h_ioctl,\r
1317                 OUT     size_t                                  *p_ret_bytes )\r
1318 {\r
1319         ual_create_qp_ioctl_t   *p_ioctl =\r
1320                 (ual_create_qp_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
1321         al_dev_open_context_t   *p_context =\r
1322                 (al_dev_open_context_t *)p_open_context;\r
1323         ib_pd_handle_t                  h_pd;\r
1324         ib_qp_handle_t                  h_qp;\r
1325         ib_srq_handle_t                 h_srq = NULL;\r
1326         ib_cq_handle_t                  h_sq_cq, h_rq_cq;\r
1327         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1328         ib_api_status_t                 status;\r
1329         ib_pfn_event_cb_t               pfn_ev;\r
1330 \r
1331         AL_ENTER( AL_DBG_QP );\r
1332 \r
1333         /* Validate input buffers. */\r
1334         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1335                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1336                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1337         {\r
1338                 AL_EXIT( AL_DBG_QP );\r
1339                 return CL_INVALID_PARAMETER;\r
1340         }\r
1341 \r
1342         /* Validate handles. */\r
1343         h_pd = (ib_pd_handle_t)\r
1344                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
1345         h_sq_cq = (ib_cq_handle_t)al_hdl_ref( p_context->h_al,\r
1346                 (uint64_t)p_ioctl->in.qp_create.h_sq_cq, AL_OBJ_TYPE_H_CQ );\r
1347         h_rq_cq = (ib_cq_handle_t)al_hdl_ref( p_context->h_al,\r
1348                 (uint64_t)p_ioctl->in.qp_create.h_rq_cq, AL_OBJ_TYPE_H_CQ );\r
1349         if (p_ioctl->in.qp_create.h_srq) {\r
1350                 h_srq = (ib_srq_handle_t)al_hdl_ref( p_context->h_al,\r
1351                         (uint64_t)p_ioctl->in.qp_create.h_srq, AL_OBJ_TYPE_H_SRQ );\r
1352                 if( !h_srq)\r
1353                 {\r
1354                         status = IB_INVALID_SRQ_HANDLE;\r
1355                         goto proxy_create_qp_err1;\r
1356                 }\r
1357         }\r
1358         if( !h_pd)\r
1359         {\r
1360                 status = IB_INVALID_PD_HANDLE;\r
1361                 goto proxy_create_qp_err1;\r
1362         }\r
1363         if( !h_sq_cq )\r
1364         {\r
1365                 status = IB_INVALID_CQ_HANDLE;\r
1366                 goto proxy_create_qp_err1;\r
1367         }\r
1368         if( !h_rq_cq )\r
1369         {\r
1370                 status = IB_INVALID_CQ_HANDLE;\r
1371                 goto proxy_create_qp_err1;\r
1372         }\r
1373 \r
1374         /* Substitute rq_cq handle with AL's cq handle */\r
1375         p_ioctl->in.qp_create.h_sq_cq = h_sq_cq;\r
1376         /* Substitute rq_cq handle with AL's cq handle */\r
1377         p_ioctl->in.qp_create.h_rq_cq = h_rq_cq;\r
1378         /* Substitute srq handle with AL's srq handle */\r
1379         p_ioctl->in.qp_create.h_srq = h_srq;\r
1380 \r
1381         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1382         if( status != IB_SUCCESS )\r
1383                 goto proxy_create_qp_err1;\r
1384 \r
1385         if( p_ioctl->in.ev_notify )\r
1386                 pfn_ev = proxy_qp_err_cb;\r
1387         else\r
1388                 pfn_ev = NULL;\r
1389 \r
1390         status = create_qp( h_pd, &p_ioctl->in.qp_create, p_ioctl->in.context,\r
1391                 pfn_ev, &h_qp, p_umv_buf );\r
1392         /* TODO: The create_qp call should return the attributes... */\r
1393         if( status != IB_SUCCESS )\r
1394                 goto proxy_create_qp_err1;\r
1395 \r
1396         status = query_qp( h_qp, &p_ioctl->out.attr, NULL );\r
1397         if( status != IB_SUCCESS )\r
1398                 goto proxy_create_qp_err2;\r
1399         \r
1400         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1401         if( status == IB_SUCCESS )\r
1402         {\r
1403                 p_ioctl->out.h_qp = h_qp->obj.hdl;\r
1404                 h_qp->obj.hdl_valid = TRUE;\r
1405                 /* Release the reference taken in create_qp (by init_al_obj) */\r
1406                 deref_al_obj( &h_qp->obj );\r
1407         }\r
1408         else\r
1409         {\r
1410 proxy_create_qp_err2:\r
1411                 /*\r
1412                  * Note that we hold the reference taken in create_qp (by init_al_obj)\r
1413                  */\r
1414                 h_qp->obj.pfn_destroy( &h_qp->obj, NULL );\r
1415 \r
1416 proxy_create_qp_err1:\r
1417                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1418                 p_ioctl->out.h_qp = AL_INVALID_HANDLE;\r
1419                 cl_memclr( &p_ioctl->out.attr, sizeof(ib_qp_attr_t) );\r
1420         }\r
1421         free_umvbuf( p_umv_buf );\r
1422 \r
1423         p_ioctl->out.status = status;\r
1424         *p_ret_bytes = sizeof(p_ioctl->out);\r
1425 \r
1426         if( h_pd )\r
1427                 deref_al_obj( &h_pd->obj );\r
1428         if( h_rq_cq )\r
1429                 deref_al_obj( &h_rq_cq->obj );\r
1430         if( h_sq_cq )\r
1431                 deref_al_obj( &h_sq_cq->obj );\r
1432         if( h_srq )\r
1433                 deref_al_obj( &h_srq->obj );\r
1434 \r
1435         AL_EXIT( AL_DBG_QP );\r
1436         return CL_SUCCESS;\r
1437 }\r
1438 \r
1439 \r
1440 /*\r
1441  * Process the ioctl UAL_QUERY_QP:\r
1442  */\r
1443 static\r
1444 cl_status_t\r
1445 proxy_query_qp(\r
1446         IN              void                                    *p_open_context,\r
1447         IN              cl_ioctl_handle_t               h_ioctl,\r
1448                 OUT     size_t                                  *p_ret_bytes )\r
1449 {\r
1450         ual_query_qp_ioctl_t    *p_ioctl =\r
1451                 (ual_query_qp_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1452         al_dev_open_context_t   *p_context =\r
1453                 (al_dev_open_context_t *)p_open_context;\r
1454         ib_qp_handle_t                  h_qp;\r
1455         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1456         ib_api_status_t                 status;\r
1457 \r
1458         AL_ENTER( AL_DBG_QP );\r
1459 \r
1460         /* Validate input buffers. */\r
1461         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1462                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1463                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1464         {\r
1465                 AL_EXIT( AL_DBG_QP );\r
1466                 return CL_INVALID_PARAMETER;\r
1467         }\r
1468 \r
1469         /* Validate QP handle */\r
1470         h_qp = (ib_qp_handle_t)\r
1471                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
1472         if( !h_qp )\r
1473         {\r
1474                 status = IB_INVALID_QP_HANDLE;\r
1475                 goto proxy_query_qp_err;\r
1476         }\r
1477 \r
1478         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1479         if( status != IB_SUCCESS )\r
1480                 goto proxy_query_qp_err;\r
1481 \r
1482         status = query_qp( h_qp, &p_ioctl->out.attr, p_umv_buf );\r
1483         if( status != IB_SUCCESS )\r
1484                 goto proxy_query_qp_err;\r
1485 \r
1486         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1487         if( status == IB_SUCCESS )\r
1488         {\r
1489                 if( p_ioctl->out.attr.h_pd )\r
1490                 {\r
1491                         p_ioctl->out.attr.h_pd =\r
1492                                 (ib_pd_handle_t)HDL_TO_PTR(p_ioctl->out.attr.h_pd->obj.hdl);\r
1493                 }\r
1494 \r
1495                 if( p_ioctl->out.attr.h_sq_cq )\r
1496                 {\r
1497                         p_ioctl->out.attr.h_sq_cq =\r
1498                                 (ib_cq_handle_t)HDL_TO_PTR(p_ioctl->out.attr.h_sq_cq->obj.hdl);\r
1499                 }\r
1500 \r
1501                 if( p_ioctl->out.attr.h_rq_cq )\r
1502                 {\r
1503                         p_ioctl->out.attr.h_rq_cq =\r
1504                                 (ib_cq_handle_t)HDL_TO_PTR(p_ioctl->out.attr.h_rq_cq->obj.hdl);\r
1505                 }\r
1506 \r
1507                 if( p_ioctl->out.attr.h_srq )\r
1508                 {\r
1509                         p_ioctl->out.attr.h_srq =\r
1510                                 (ib_srq_handle_t)HDL_TO_PTR(p_ioctl->out.attr.h_srq->obj.hdl);\r
1511                 }\r
1512         }\r
1513         else\r
1514         {\r
1515 proxy_query_qp_err:\r
1516                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1517                 cl_memclr( &p_ioctl->out.attr, sizeof(ib_qp_attr_t) );\r
1518         }\r
1519         free_umvbuf( p_umv_buf );\r
1520 \r
1521         if( h_qp )\r
1522                 deref_al_obj( &h_qp->obj );\r
1523 \r
1524         p_ioctl->out.status = status;\r
1525         *p_ret_bytes = sizeof(p_ioctl->out);\r
1526 \r
1527         AL_EXIT( AL_DBG_QP );\r
1528         return CL_SUCCESS;\r
1529 }\r
1530 \r
1531 \r
1532 \r
1533 /*\r
1534  * Process the ioctl UAL_MODIFY_QP:\r
1535  */\r
1536 static\r
1537 cl_status_t\r
1538 proxy_modify_qp(\r
1539         IN              void                                    *p_open_context,\r
1540         IN              cl_ioctl_handle_t               h_ioctl,\r
1541                 OUT     size_t                                  *p_ret_bytes )\r
1542 {\r
1543         ual_modify_qp_ioctl_t   *p_ioctl =\r
1544                 (ual_modify_qp_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1545         al_dev_open_context_t   *p_context =\r
1546                 (al_dev_open_context_t *)p_open_context;\r
1547         ib_qp_handle_t                  h_qp;\r
1548         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1549         ib_api_status_t                 status;\r
1550 \r
1551         AL_ENTER( AL_DBG_QP );\r
1552 \r
1553         /* Validate input buffers. */\r
1554         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1555                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1556                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1557         {\r
1558                 AL_EXIT( AL_DBG_QP );\r
1559                 return CL_INVALID_PARAMETER;\r
1560         }\r
1561 \r
1562         /* Validate QP handle */\r
1563         h_qp = (ib_qp_handle_t)\r
1564                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
1565         if( !h_qp )\r
1566         {\r
1567                 status = IB_INVALID_QP_HANDLE;\r
1568                 goto proxy_modify_qp_err;\r
1569         }\r
1570 \r
1571         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1572         if( status != IB_SUCCESS )\r
1573                 goto proxy_modify_qp_err;\r
1574 \r
1575         status = modify_qp( h_qp, &p_ioctl->in.modify_attr, p_umv_buf );\r
1576 \r
1577         if( status != IB_SUCCESS )\r
1578                 goto proxy_modify_qp_err;\r
1579         \r
1580         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1581         if( status != IB_SUCCESS )\r
1582         {\r
1583 proxy_modify_qp_err:\r
1584                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1585         }\r
1586         free_umvbuf( p_umv_buf );\r
1587 \r
1588         if( h_qp )\r
1589                 deref_al_obj( &h_qp->obj );\r
1590 \r
1591         p_ioctl->out.status = status;\r
1592         *p_ret_bytes = sizeof(p_ioctl->out);\r
1593 \r
1594         AL_EXIT( AL_DBG_QP );\r
1595         return CL_SUCCESS;\r
1596 }\r
1597 \r
1598 \r
1599 /*\r
1600  * Process the ioctl UAL_DESTROY_QP\r
1601  */\r
1602 static cl_status_t\r
1603 proxy_destroy_qp(\r
1604         IN              void                                    *p_open_context,\r
1605         IN              cl_ioctl_handle_t               h_ioctl,\r
1606                 OUT     size_t                                  *p_ret_bytes )\r
1607 {\r
1608         ual_destroy_qp_ioctl_t  *p_ioctl =\r
1609                 (ual_destroy_qp_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1610         al_dev_open_context_t   *p_context =\r
1611                 (al_dev_open_context_t *)p_open_context;\r
1612         ib_qp_handle_t                  h_qp;\r
1613 \r
1614         AL_ENTER( AL_DBG_QP );\r
1615 \r
1616         /* Validate input buffers. */\r
1617         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1618                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1619                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1620         {\r
1621                 AL_EXIT( AL_DBG_QP );\r
1622                 return CL_INVALID_PARAMETER;\r
1623         }\r
1624 \r
1625         /* Set the return bytes in all cases */\r
1626         *p_ret_bytes = sizeof(p_ioctl->out);\r
1627 \r
1628         /* Validate QP handle */\r
1629         h_qp = (ib_qp_handle_t)\r
1630                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
1631         if( !h_qp )\r
1632         {\r
1633                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("IB_INVALID_QP_HANDLE\n") );\r
1634                 p_ioctl->out.status = IB_INVALID_QP_HANDLE;\r
1635         }\r
1636         else\r
1637         {\r
1638                 h_qp->obj.pfn_destroy( &h_qp->obj, ib_sync_destroy );\r
1639                 p_ioctl->out.status = IB_SUCCESS;\r
1640         }\r
1641 \r
1642         AL_EXIT( AL_DBG_QP );\r
1643         return CL_SUCCESS;\r
1644 }\r
1645 \r
1646 \r
1647 \r
1648 /*\r
1649  * Process the ioctl UAL_CREATE_AV:\r
1650  */\r
1651 static\r
1652 cl_status_t\r
1653 proxy_create_av(\r
1654         IN              void                                    *p_open_context,\r
1655         IN              cl_ioctl_handle_t               h_ioctl,\r
1656                 OUT     size_t                                  *p_ret_bytes )\r
1657 {\r
1658         ual_create_av_ioctl_t   *p_ioctl =\r
1659                 (ual_create_av_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1660         al_dev_open_context_t   *p_context =\r
1661                 (al_dev_open_context_t *)p_open_context;\r
1662         ib_pd_handle_t                  h_pd;\r
1663         ib_av_handle_t                  h_av;\r
1664         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1665         ib_api_status_t                 status;\r
1666 \r
1667         AL_ENTER( AL_DBG_AV );\r
1668 \r
1669         /* Validate input buffers. */\r
1670         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1671                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1672                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1673         {\r
1674                 AL_EXIT( AL_DBG_AV );\r
1675                 return CL_INVALID_PARAMETER;\r
1676         }\r
1677 \r
1678         /* Validate PD handle */\r
1679         h_pd = (ib_pd_handle_t)\r
1680                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
1681         if( !h_pd )\r
1682         {\r
1683                 status = IB_INVALID_PD_HANDLE;\r
1684                 goto proxy_create_av_err;\r
1685         }\r
1686 \r
1687         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1688         if( status != IB_SUCCESS )\r
1689                 goto proxy_create_av_err;\r
1690 \r
1691         status = create_av( h_pd, &p_ioctl->in.attr, &h_av, p_umv_buf );\r
1692 \r
1693         if( status != IB_SUCCESS )\r
1694                 goto proxy_create_av_err;\r
1695 \r
1696         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1697         if( status == IB_SUCCESS )\r
1698         {\r
1699                 p_ioctl->out.h_av = h_av->obj.hdl;\r
1700                 h_av->obj.hdl_valid = TRUE;\r
1701                 /* Release the reference taken in create_av. */\r
1702                 deref_al_obj( &h_av->obj );\r
1703         }\r
1704         else\r
1705         {\r
1706                 h_av->obj.pfn_destroy( &h_av->obj, NULL );\r
1707 \r
1708 proxy_create_av_err:\r
1709                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1710                 p_ioctl->out.h_av = AL_INVALID_HANDLE;\r
1711         }\r
1712         free_umvbuf( p_umv_buf );\r
1713 \r
1714         if( h_pd )\r
1715                 deref_al_obj( &h_pd->obj );\r
1716 \r
1717         p_ioctl->out.status = status;\r
1718         *p_ret_bytes = sizeof(p_ioctl->out);\r
1719         \r
1720         AL_EXIT( AL_DBG_AV );\r
1721         return CL_SUCCESS;\r
1722 }\r
1723 \r
1724 \r
1725 \r
1726 /*\r
1727  * Process the ioctl UAL_QUERY_AV:\r
1728  */\r
1729 static\r
1730 cl_status_t\r
1731 proxy_query_av(\r
1732         IN              void                                    *p_open_context,\r
1733         IN              cl_ioctl_handle_t               h_ioctl,\r
1734                 OUT     size_t                                  *p_ret_bytes )\r
1735 {\r
1736         ual_query_av_ioctl_t    *p_ioctl =\r
1737                 (ual_query_av_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1738         al_dev_open_context_t   *p_context =\r
1739                 (al_dev_open_context_t *)p_open_context;\r
1740         ib_av_handle_t                  h_av;\r
1741         ib_pd_handle_t                  h_pd;\r
1742         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1743         ib_api_status_t                 status;\r
1744 \r
1745         AL_ENTER( AL_DBG_AV );\r
1746 \r
1747         /* Validate input buffers. */\r
1748         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1749                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1750                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1751         {\r
1752                 AL_EXIT( AL_DBG_AV );\r
1753                 return CL_INVALID_PARAMETER;\r
1754         }\r
1755 \r
1756         /* Validate AV handle */\r
1757         h_av = (ib_av_handle_t)\r
1758                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_av, AL_OBJ_TYPE_H_AV );\r
1759         if( !h_av )\r
1760         {\r
1761                 status = IB_INVALID_AV_HANDLE;\r
1762                 goto proxy_query_av_err;\r
1763         }\r
1764 \r
1765         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1766         if( status != IB_SUCCESS )\r
1767                 goto proxy_query_av_err;\r
1768 \r
1769         status = query_av( h_av, &p_ioctl->out.attr, &h_pd, p_umv_buf );\r
1770 \r
1771         if( status != IB_SUCCESS )\r
1772                 goto proxy_query_av_err;\r
1773 \r
1774         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1775         if( status != IB_SUCCESS )\r
1776         {\r
1777 proxy_query_av_err:\r
1778                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1779                 cl_memclr( &p_ioctl->out.attr, sizeof(ib_av_attr_t) );\r
1780         }\r
1781         free_umvbuf( p_umv_buf );\r
1782 \r
1783         if( h_av )\r
1784                 deref_al_obj( &h_av->obj );\r
1785 \r
1786         p_ioctl->out.status = status;\r
1787         *p_ret_bytes = sizeof(p_ioctl->out);\r
1788 \r
1789         AL_EXIT( AL_DBG_AV );\r
1790         return CL_SUCCESS;\r
1791 }\r
1792 \r
1793 \r
1794 \r
1795 /*\r
1796  * Process the ioctl UAL_MODIFY_AV:\r
1797  */\r
1798 static\r
1799 cl_status_t\r
1800 proxy_modify_av(\r
1801         IN              void                                    *p_open_context,\r
1802         IN              cl_ioctl_handle_t               h_ioctl,\r
1803                 OUT     size_t                                  *p_ret_bytes )\r
1804 {\r
1805         ual_modify_av_ioctl_t   *p_ioctl =\r
1806                 (ual_modify_av_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1807         al_dev_open_context_t   *p_context =\r
1808                 (al_dev_open_context_t *)p_open_context;\r
1809         ib_av_handle_t                  h_av;\r
1810         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1811         ib_api_status_t                 status;\r
1812 \r
1813         AL_ENTER( AL_DBG_AV );\r
1814 \r
1815         /* Validate input buffers. */\r
1816         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1817                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1818                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1819         {\r
1820                 AL_EXIT( AL_DBG_AV );\r
1821                 return CL_INVALID_PARAMETER;\r
1822         }\r
1823 \r
1824         /* Validate AV handle */\r
1825         h_av = (ib_av_handle_t)\r
1826                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_av, AL_OBJ_TYPE_H_AV );\r
1827         if( !h_av )\r
1828         {\r
1829                 status = IB_INVALID_AV_HANDLE;\r
1830                 goto proxy_modify_av_err;\r
1831         }\r
1832 \r
1833         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1834         if( status != IB_SUCCESS )\r
1835                 goto proxy_modify_av_err;\r
1836 \r
1837         status = modify_av( h_av, &p_ioctl->in.attr, p_umv_buf );\r
1838 \r
1839         if( status != IB_SUCCESS )\r
1840                 goto proxy_modify_av_err;\r
1841 \r
1842         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1843         if( status != IB_SUCCESS )\r
1844         {\r
1845 proxy_modify_av_err:\r
1846                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1847         }\r
1848         free_umvbuf( p_umv_buf );\r
1849 \r
1850         if( h_av )\r
1851                 deref_al_obj( &h_av->obj );\r
1852 \r
1853         p_ioctl->out.status = status;\r
1854         *p_ret_bytes = sizeof(p_ioctl->out);\r
1855 \r
1856         AL_EXIT( AL_DBG_AV );\r
1857         return CL_SUCCESS;\r
1858 }\r
1859 \r
1860 \r
1861 \r
1862 /*\r
1863  * Process the ioctl UAL_DESTROY_AV:\r
1864  */\r
1865 static\r
1866 cl_status_t\r
1867 proxy_destroy_av(\r
1868         IN              void                                    *p_open_context,\r
1869         IN              cl_ioctl_handle_t               h_ioctl,\r
1870                 OUT     size_t                                  *p_ret_bytes )\r
1871 {\r
1872         ual_destroy_av_ioctl_t  *p_ioctl =\r
1873                 (ual_destroy_av_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1874         al_dev_open_context_t   *p_context =\r
1875                 (al_dev_open_context_t *)p_open_context;\r
1876         ib_av_handle_t                  h_av;\r
1877 \r
1878         AL_ENTER( AL_DBG_AV );\r
1879 \r
1880         /* Validate input buffers. */\r
1881         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1882                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1883                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1884         {\r
1885                 AL_EXIT( AL_DBG_AV );\r
1886                 return CL_INVALID_PARAMETER;\r
1887         }\r
1888 \r
1889         /* Set the return bytes in all cases */\r
1890         *p_ret_bytes = sizeof(p_ioctl->out);\r
1891 \r
1892         /* Validate AV handle */\r
1893         h_av = (ib_av_handle_t)\r
1894                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_av, AL_OBJ_TYPE_H_AV );\r
1895         if( !h_av )\r
1896         {\r
1897                 p_ioctl->out.status = IB_INVALID_AV_HANDLE;\r
1898                 AL_EXIT( AL_DBG_AV );\r
1899                 return CL_SUCCESS;\r
1900         }\r
1901 \r
1902         h_av->obj.pfn_destroy( &h_av->obj, NULL );\r
1903         p_ioctl->out.status = IB_SUCCESS;\r
1904 \r
1905         AL_EXIT( AL_DBG_AV );\r
1906         return CL_SUCCESS;\r
1907 }\r
1908 \r
1909 \r
1910 \r
1911 /*\r
1912  * Process the ioctl UAL_MODIFY_CQ:\r
1913  */\r
1914 static\r
1915 cl_status_t\r
1916 proxy_modify_cq(\r
1917         IN              void                                    *p_open_context,\r
1918         IN              cl_ioctl_handle_t               h_ioctl,\r
1919                 OUT     size_t                                  *p_ret_bytes )\r
1920 {\r
1921         ual_modify_cq_ioctl_t   *p_ioctl =\r
1922                 (ual_modify_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1923         al_dev_open_context_t   *p_context =\r
1924                 (al_dev_open_context_t *)p_open_context;\r
1925         ib_cq_handle_t                  h_cq;\r
1926         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1927         ib_api_status_t                 status;\r
1928         uint32_t                                size;\r
1929 \r
1930         AL_ENTER( AL_DBG_CQ );\r
1931 \r
1932         /* Validate input buffers. */\r
1933         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1934                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1935                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1936         {\r
1937                 AL_EXIT( AL_DBG_CQ );\r
1938                 return CL_INVALID_PARAMETER;\r
1939         }\r
1940 \r
1941         /* Validate CQ handle */\r
1942         h_cq = (ib_cq_handle_t)\r
1943                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
1944         if( !h_cq )\r
1945         {\r
1946                 status = IB_INVALID_CQ_HANDLE;\r
1947                 goto proxy_modify_cq_err;\r
1948         }\r
1949 \r
1950         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1951         if( status != IB_SUCCESS )\r
1952                 goto proxy_modify_cq_err;\r
1953 \r
1954         size = p_ioctl->in.size;\r
1955         status = modify_cq( h_cq, &size, p_umv_buf );\r
1956         if( status != IB_SUCCESS )\r
1957                 goto proxy_modify_cq_err;\r
1958 \r
1959         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1960         if( status == IB_SUCCESS )\r
1961         {\r
1962                 p_ioctl->out.size = size;\r
1963         }\r
1964         else\r
1965         {\r
1966 proxy_modify_cq_err:\r
1967                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1968                 p_ioctl->out.size = 0;\r
1969         }\r
1970         free_umvbuf( p_umv_buf );\r
1971 \r
1972         if( h_cq )\r
1973                 deref_al_obj( &h_cq->obj );\r
1974 \r
1975         p_ioctl->out.status = status;\r
1976         *p_ret_bytes = sizeof(p_ioctl->out);\r
1977 \r
1978         AL_EXIT( AL_DBG_CQ );\r
1979         return CL_SUCCESS;\r
1980 }\r
1981 \r
1982 \r
1983 \r
1984 /*\r
1985  * Proxy's CQ completion callback\r
1986  */\r
1987 static void\r
1988 proxy_cq_comp_cb(\r
1989         IN                              ib_cq_handle_t                          h_cq,\r
1990         IN                              void                                            *cq_context )\r
1991 {\r
1992         comp_cb_ioctl_info_t    cb_info;\r
1993         al_dev_open_context_t   *p_context = h_cq->obj.h_al->p_context;\r
1994 \r
1995         /*\r
1996          * If we're already closing the device - do not queue a callback, since\r
1997          * we're cleaning up the callback lists.\r
1998          */\r
1999         if( !proxy_context_ref( p_context ) )\r
2000         {\r
2001                 proxy_context_deref( p_context );\r
2002                 return;\r
2003         }\r
2004 \r
2005         /* Set up context and callback record type appropriate for UAL */\r
2006         cb_info.cq_context = cq_context;\r
2007 \r
2008         /* The proxy handle must be valid now. */\r
2009         if( !h_cq->obj.hdl_valid )\r
2010                 h_cq->obj.hdl_valid = TRUE;\r
2011 \r
2012         proxy_queue_cb_buf( UAL_GET_COMP_CB_INFO, p_context, &cb_info,\r
2013                 &h_cq->obj );\r
2014         \r
2015         proxy_context_deref( p_context );\r
2016 }\r
2017 \r
2018 \r
2019 \r
2020 /*\r
2021  * Proxy's CQ error callback\r
2022  */\r
2023 static void\r
2024 proxy_cq_err_cb(\r
2025         IN                              ib_async_event_rec_t            *p_err_rec)\r
2026 {\r
2027         ib_cq_handle_t                  h_cq = p_err_rec->handle.h_cq;\r
2028         al_dev_open_context_t   *p_context = h_cq->obj.h_al->p_context;\r
2029         misc_cb_ioctl_info_t    cb_info;\r
2030 \r
2031         /*\r
2032          * If we're already closing the device - do not queue a callback, since\r
2033          * we're cleaning up the callback lists.\r
2034          */\r
2035         if( !proxy_context_ref( p_context ) )\r
2036         {\r
2037                 proxy_context_deref( p_context );\r
2038                 return;\r
2039         }\r
2040 \r
2041         /* Set up context and callback record type appropriate for UAL */\r
2042         cb_info.rec_type = CQ_ERROR_REC;\r
2043         /* Return the Proxy's cq handle and the user's context */\r
2044         cb_info.ioctl_rec.event_rec = *p_err_rec;\r
2045         cb_info.ioctl_rec.event_rec.handle.h_cq = (ib_cq_handle_t)HDL_TO_PTR(h_cq->obj.hdl);\r
2046 \r
2047         /* The proxy handle must be valid now. */\r
2048         if( !h_cq->obj.hdl_valid )\r
2049                 h_cq->obj.hdl_valid = TRUE;\r
2050 \r
2051         proxy_queue_cb_buf( UAL_GET_MISC_CB_INFO, p_context, &cb_info,\r
2052                 &h_cq->obj );\r
2053         proxy_context_deref( p_context );\r
2054 }\r
2055 \r
2056 \r
2057 \r
2058 /*\r
2059  * Process the ioctl UAL_CREATE_CQ:\r
2060  */\r
2061 static cl_status_t\r
2062 proxy_create_cq(\r
2063         IN              void                                    *p_open_context,\r
2064         IN              cl_ioctl_handle_t               h_ioctl,\r
2065                 OUT     size_t                                  *p_ret_bytes )\r
2066 {\r
2067         ual_create_cq_ioctl_t   *p_ioctl =\r
2068                 (ual_create_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2069         al_dev_open_context_t   *p_context =\r
2070                 (al_dev_open_context_t *)p_open_context;\r
2071         ib_ca_handle_t                  h_ca;\r
2072         ib_cq_handle_t                  h_cq;\r
2073         ib_cq_create_t                  cq_create;\r
2074         ci_umv_buf_t                    *p_umv_buf = NULL;\r
2075         ib_api_status_t                 status;\r
2076         ib_pfn_event_cb_t               pfn_ev;\r
2077 \r
2078         AL_ENTER( AL_DBG_CQ );\r
2079 \r
2080         /* Validate input buffers. */\r
2081         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2082                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2083                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2084         {\r
2085                 AL_EXIT( AL_DBG_CQ );\r
2086                 return CL_INVALID_PARAMETER;\r
2087         }\r
2088 \r
2089         /* Validate CA handle */\r
2090         h_ca = (ib_ca_handle_t)\r
2091                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
2092         if( !h_ca )\r
2093         {\r
2094                 status = IB_INVALID_CA_HANDLE;\r
2095                 goto proxy_create_cq_err1;\r
2096         }\r
2097 \r
2098         cq_create.size = p_ioctl->in.size;\r
2099 \r
2100         if( p_ioctl->in.h_wait_obj )\r
2101         {\r
2102                 cq_create.pfn_comp_cb = NULL;\r
2103                 cq_create.h_wait_obj = cl_waitobj_ref( p_ioctl->in.h_wait_obj );\r
2104                 if( !cq_create.h_wait_obj )\r
2105                 {\r
2106                         status = IB_INVALID_PARAMETER;\r
2107                         goto proxy_create_cq_err1;\r
2108                 }\r
2109         }\r
2110         else\r
2111         {\r
2112                 /* Override with proxy's cq callback */\r
2113                 cq_create.pfn_comp_cb = proxy_cq_comp_cb;\r
2114                 cq_create.h_wait_obj = NULL;\r
2115         }\r
2116 \r
2117         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
2118         if( status != IB_SUCCESS )\r
2119                 goto proxy_create_cq_err2;\r
2120 \r
2121         if( p_ioctl->in.ev_notify )\r
2122                 pfn_ev = proxy_cq_err_cb;\r
2123         else\r
2124                 pfn_ev = NULL;\r
2125 \r
2126         status = create_cq( h_ca, &cq_create, p_ioctl->in.context,\r
2127                 pfn_ev, &h_cq, p_umv_buf );\r
2128 \r
2129         if( status != IB_SUCCESS )\r
2130                 goto proxy_create_cq_err2;\r
2131 \r
2132         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
2133         if( status == IB_SUCCESS )\r
2134         {\r
2135                 p_ioctl->out.size = cq_create.size;\r
2136                 p_ioctl->out.h_cq = h_cq->obj.hdl;\r
2137                 h_cq->obj.hdl_valid = TRUE;\r
2138                 deref_al_obj( &h_cq->obj );\r
2139         }\r
2140         else\r
2141         {\r
2142                 h_cq->obj.pfn_destroy( &h_cq->obj, NULL );\r
2143 \r
2144 proxy_create_cq_err2:\r
2145                 if( cq_create.h_wait_obj )\r
2146                         cl_waitobj_deref( cq_create.h_wait_obj );\r
2147 \r
2148 proxy_create_cq_err1:\r
2149                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
2150                 p_ioctl->out.h_cq = AL_INVALID_HANDLE;\r
2151                 p_ioctl->out.size = 0;\r
2152         }\r
2153         free_umvbuf( p_umv_buf );\r
2154 \r
2155         if( h_ca )\r
2156                 deref_al_obj( &h_ca->obj );\r
2157 \r
2158         p_ioctl->out.status = status;\r
2159         *p_ret_bytes = sizeof(p_ioctl->out);\r
2160 \r
2161         AL_EXIT( AL_DBG_CQ );\r
2162         return CL_SUCCESS;\r
2163 }\r
2164 \r
2165 \r
2166 /*\r
2167  * Process the ioctl UAL_QUERY_CQ:\r
2168  */\r
2169 static\r
2170 cl_status_t\r
2171 proxy_query_cq(\r
2172         IN              void                                    *p_open_context,\r
2173         IN              cl_ioctl_handle_t               h_ioctl,\r
2174                 OUT     size_t                                  *p_ret_bytes )\r
2175 {\r
2176         ual_query_cq_ioctl_t    *p_ioctl =\r
2177                 (ual_query_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2178         al_dev_open_context_t   *p_context =\r
2179                 (al_dev_open_context_t *)p_open_context;\r
2180         ib_cq_handle_t                  h_cq;\r
2181         ci_umv_buf_t                    *p_umv_buf = NULL;\r
2182         ib_api_status_t                 status;\r
2183 \r
2184         AL_ENTER( AL_DBG_CQ );\r
2185 \r
2186         /* Validate input buffers. */\r
2187         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2188                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2189                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2190         {\r
2191                 AL_EXIT( AL_DBG_CQ );\r
2192                 return CL_INVALID_PARAMETER;\r
2193         }\r
2194 \r
2195         /* Validate CQ handle */\r
2196         h_cq = (ib_cq_handle_t)\r
2197                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2198         if( !h_cq )\r
2199         {\r
2200                 status = IB_INVALID_CQ_HANDLE;\r
2201                 goto proxy_query_cq_err;\r
2202         }\r
2203 \r
2204         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
2205         if( status != IB_SUCCESS )\r
2206                 goto proxy_query_cq_err;\r
2207 \r
2208         status = query_cq( h_cq, &p_ioctl->out.size, p_umv_buf );\r
2209 \r
2210         if( status != IB_SUCCESS )\r
2211                 goto proxy_query_cq_err;\r
2212 \r
2213         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
2214         if( status != IB_SUCCESS )\r
2215         {\r
2216 proxy_query_cq_err:\r
2217                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
2218                 p_ioctl->out.size = 0;\r
2219         }\r
2220         free_umvbuf( p_umv_buf );\r
2221 \r
2222         if( h_cq )\r
2223                 deref_al_obj( &h_cq->obj );\r
2224 \r
2225         p_ioctl->out.status = status;\r
2226         *p_ret_bytes = sizeof(p_ioctl->out);\r
2227 \r
2228         AL_EXIT( AL_DBG_CQ );\r
2229         return CL_SUCCESS;\r
2230 }\r
2231 \r
2232 \r
2233 /*\r
2234  * Process the ioctl UAL_DESTROY_CQ\r
2235  */\r
2236 static\r
2237 cl_status_t\r
2238 proxy_destroy_cq(\r
2239         IN              void                                    *p_open_context,\r
2240         IN              cl_ioctl_handle_t               h_ioctl,\r
2241                 OUT     size_t                                  *p_ret_bytes )\r
2242 {\r
2243         ual_destroy_cq_ioctl_t  *p_ioctl =\r
2244                 (ual_destroy_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2245         al_dev_open_context_t   *p_context =\r
2246                 (al_dev_open_context_t *)p_open_context;\r
2247         ib_cq_handle_t                  h_cq;\r
2248         cl_waitobj_handle_t             h_wait_obj;\r
2249 \r
2250         AL_ENTER( AL_DBG_CQ );\r
2251 \r
2252         /* Validate input buffers. */\r
2253         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2254                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2255                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2256         {\r
2257                 AL_EXIT( AL_DBG_CQ );\r
2258                 return CL_INVALID_PARAMETER;\r
2259         }\r
2260 \r
2261         /* Set the return bytes in all cases */\r
2262         *p_ret_bytes = sizeof(p_ioctl->out);\r
2263 \r
2264         /* Validate CQ handle */\r
2265         h_cq = (ib_cq_handle_t)\r
2266                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2267         if( !h_cq )\r
2268         {\r
2269                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2270                 AL_EXIT( AL_DBG_CQ );\r
2271                 return CL_SUCCESS;\r
2272         }\r
2273 \r
2274         h_wait_obj = h_cq->h_wait_obj;\r
2275 \r
2276         h_cq->obj.pfn_destroy( &h_cq->obj, ib_sync_destroy );\r
2277 \r
2278         /* Deref the wait object, if any. */\r
2279         if( h_wait_obj )\r
2280                 cl_waitobj_deref( h_wait_obj );\r
2281 \r
2282         p_ioctl->out.status = IB_SUCCESS;\r
2283 \r
2284         AL_EXIT( AL_DBG_CQ );\r
2285         return CL_SUCCESS;\r
2286 }\r
2287 \r
2288 \r
2289 /*\r
2290  * Process the ioctl UAL_POST_SEND\r
2291  */\r
2292 static\r
2293 cl_status_t\r
2294 proxy_post_send(\r
2295         IN              void                                    *p_open_context,\r
2296         IN              cl_ioctl_handle_t               h_ioctl,\r
2297                 OUT     size_t                                  *p_ret_bytes )\r
2298 {\r
2299         ual_post_send_ioctl_t   *p_ioctl =\r
2300                 (ual_post_send_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2301         al_dev_open_context_t   *p_context =\r
2302                 (al_dev_open_context_t *)p_open_context;\r
2303         ib_qp_handle_t                  h_qp;\r
2304         ib_av_handle_t                  h_av;\r
2305         ib_send_wr_t                    *p_wr;\r
2306         ib_send_wr_t                    *p_send_failure;\r
2307         uintn_t                                 i = 0;\r
2308         ib_local_ds_t                   *p_ds;\r
2309         uintn_t                                 num_ds = 0;\r
2310         ib_api_status_t                 status;\r
2311         size_t                                  in_buf_sz;\r
2312 \r
2313         AL_ENTER( AL_DBG_QP );\r
2314         /* Validate input buffers. */\r
2315         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2316                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
2317                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2318         {\r
2319                 AL_EXIT( AL_DBG_QP );\r
2320                 return CL_INVALID_PARAMETER;\r
2321         }\r
2322 \r
2323         /*\r
2324          * Additional input buffer validation based on actual settings.\r
2325          * Note that this validates that work requests are actually\r
2326          * being passed in.\r
2327          */\r
2328         in_buf_sz = sizeof(p_ioctl->in);\r
2329         in_buf_sz += sizeof(ib_send_wr_t) * (p_ioctl->in.num_wr - 1);\r
2330         in_buf_sz += sizeof(ib_local_ds_t) * p_ioctl->in.num_ds;\r
2331         if( cl_ioctl_in_size( h_ioctl ) != in_buf_sz )\r
2332         {\r
2333                 AL_EXIT( AL_DBG_QP );\r
2334                 return CL_INVALID_PARAMETER;\r
2335         }\r
2336 \r
2337         /* Setup p_send_failure to head of list. */\r
2338         p_send_failure = p_wr = p_ioctl->in.send_wr;\r
2339 \r
2340         /* Validate QP handle */\r
2341         h_qp = (ib_qp_handle_t)\r
2342                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
2343         if( !h_qp )\r
2344         {\r
2345                 status = IB_INVALID_QP_HANDLE;\r
2346                 goto proxy_post_send_done;\r
2347         }\r
2348 \r
2349         /* Setup the base data segment pointer. */\r
2350         p_ds = (ib_local_ds_t*)&p_ioctl->in.send_wr[p_ioctl->in.num_wr];\r
2351 \r
2352         /* Setup the user's work requests and data segments and translate. */\r
2353         for( i = 0; i < p_ioctl->in.num_wr; i++ )\r
2354         {\r
2355                 if( h_qp->type == IB_QPT_UNRELIABLE_DGRM )\r
2356                 {\r
2357                         /* Validate the AV handle for UD */\r
2358                         h_av = (ib_av_handle_t)al_hdl_ref( p_context->h_al,\r
2359                                 (uint64_t)p_wr[i].dgrm.ud.h_av, AL_OBJ_TYPE_H_AV );\r
2360                         if( !h_av )\r
2361                         {\r
2362                                 status = IB_INVALID_AV_HANDLE;\r
2363                                 goto proxy_post_send_done;\r
2364                         }\r
2365                         /* substitute with KAL AV handle */\r
2366                         p_wr[i].dgrm.ud.h_av = h_av;\r
2367                 }\r
2368 \r
2369                 /* Setup the data segments, if any. */\r
2370                 if( p_wr[i].num_ds )\r
2371                 {\r
2372                         num_ds += p_wr[i].num_ds;\r
2373                         if( num_ds > p_ioctl->in.num_ds )\r
2374                         {\r
2375                                 /*\r
2376                                 * The work request submitted exceed the number of data\r
2377                                 * segments specified in the IOCTL.\r
2378                                 */\r
2379                                 status = IB_INVALID_PARAMETER;\r
2380                                 goto proxy_post_send_done;\r
2381                         }\r
2382                         p_wr[i].ds_array = p_ds;\r
2383                         p_ds += p_wr->num_ds;\r
2384                 }\r
2385                 else\r
2386                 {\r
2387                         p_wr[i].ds_array = NULL;\r
2388                 }\r
2389 \r
2390                 p_wr[i].p_next = &p_wr[i + 1];\r
2391         }\r
2392 \r
2393         /* Mark the end of list. */\r
2394         p_wr[i - 1].p_next = NULL;\r
2395 \r
2396         /* so much for the set up, let's roll! */\r
2397         status = ib_post_send( h_qp, p_wr, &p_send_failure );\r
2398 \r
2399         if( status == IB_SUCCESS )\r
2400         {\r
2401                 p_ioctl->out.failed_cnt = 0;\r
2402         }\r
2403         else\r
2404         {\r
2405 proxy_post_send_done:\r
2406                 /* First set up as if all failed. */\r
2407                 p_ioctl->out.failed_cnt = p_ioctl->in.num_wr;\r
2408                 /* Now subtract successful ones. */\r
2409                 p_ioctl->out.failed_cnt -= (uint32_t)(\r
2410                         (((uintn_t)p_send_failure) - ((uintn_t)p_wr))\r
2411                         / sizeof(ib_send_wr_t));\r
2412         }\r
2413 \r
2414         /* releases the references on address vectors. */\r
2415         if( h_qp )\r
2416         {\r
2417                 if( h_qp->type == IB_QPT_UNRELIABLE_DGRM )\r
2418                 {\r
2419                         while( i-- )\r
2420                                 deref_al_obj( &p_wr[i].dgrm.ud.h_av->obj );\r
2421                 }\r
2422                 deref_al_obj( &h_qp->obj );\r
2423         }\r
2424 \r
2425         p_ioctl->out.status = status;\r
2426         *p_ret_bytes = sizeof(p_ioctl->out);\r
2427 \r
2428         AL_EXIT( AL_DBG_QP );\r
2429         return CL_SUCCESS;\r
2430 }\r
2431 \r
2432 \r
2433 \r
2434 /*\r
2435  * Process the ioctl UAL_POST_RECV\r
2436  */\r
2437 static\r
2438 cl_status_t\r
2439 proxy_post_recv(\r
2440         IN              void                                    *p_open_context,\r
2441         IN              cl_ioctl_handle_t               h_ioctl,\r
2442                 OUT     size_t                                  *p_ret_bytes )\r
2443 {\r
2444         ual_post_recv_ioctl_t   *p_ioctl =\r
2445                 (ual_post_recv_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2446         al_dev_open_context_t   *p_context =\r
2447                 (al_dev_open_context_t *)p_open_context;\r
2448         ib_qp_handle_t                  h_qp;\r
2449         ib_recv_wr_t                    *p_wr;\r
2450         ib_recv_wr_t                    *p_recv_failure;\r
2451         uintn_t                                 i;\r
2452         ib_local_ds_t                   *p_ds;\r
2453         uintn_t                                 num_ds = 0;\r
2454         ib_api_status_t                 status;\r
2455         size_t                                  in_buf_sz;\r
2456 \r
2457         AL_ENTER( AL_DBG_QP );\r
2458 \r
2459         /* Validate input buffers. */\r
2460         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2461                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
2462                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2463         {\r
2464                 AL_EXIT( AL_DBG_QP );\r
2465                 return CL_INVALID_PARAMETER;\r
2466         }\r
2467 \r
2468         /*\r
2469          * Additional input buffer validation based on actual settings.\r
2470          * Note that this validates that work requests are actually\r
2471          * being passed in.\r
2472          */\r
2473         in_buf_sz = sizeof(p_ioctl->in);\r
2474         in_buf_sz += sizeof(ib_recv_wr_t) * (p_ioctl->in.num_wr - 1);\r
2475         in_buf_sz += sizeof(ib_local_ds_t) * p_ioctl->in.num_ds;\r
2476         if( cl_ioctl_in_size( h_ioctl ) != in_buf_sz )\r
2477         {\r
2478                 AL_EXIT( AL_DBG_QP );\r
2479                 return CL_INVALID_PARAMETER;\r
2480         }\r
2481 \r
2482         /* Setup p_send_failure to head of list. */\r
2483         p_recv_failure = p_wr = p_ioctl->in.recv_wr;\r
2484 \r
2485         /* Validate QP handle */\r
2486         h_qp = (ib_qp_handle_t)\r
2487                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
2488         if( !h_qp )\r
2489         {\r
2490                 status = IB_INVALID_QP_HANDLE;\r
2491                 goto proxy_post_recv_done;\r
2492         }\r
2493 \r
2494         /* Setup the base data segment pointer. */\r
2495         p_ds = (ib_local_ds_t*)&p_ioctl->in.recv_wr[p_ioctl->in.num_wr];\r
2496 \r
2497         /* Setup the user's work requests and data segments and translate. */\r
2498         for( i = 0; i < p_ioctl->in.num_wr; i++ )\r
2499         {\r
2500                 /* Setup the data segments, if any. */\r
2501                 if( p_wr[i].num_ds )\r
2502                 {\r
2503                         num_ds += p_wr[i].num_ds;\r
2504                         if( num_ds > p_ioctl->in.num_ds )\r
2505                         {\r
2506                                 /*\r
2507                                 * The work request submitted exceed the number of data\r
2508                                 * segments specified in the IOCTL.\r
2509                                 */\r
2510                                 status = IB_INVALID_PARAMETER;\r
2511                                 goto proxy_post_recv_done;\r
2512                         }\r
2513                         p_wr[i].ds_array = p_ds;\r
2514                         p_ds += p_wr->num_ds;\r
2515                 }\r
2516                 else\r
2517                 {\r
2518                         p_wr[i].ds_array = NULL;\r
2519                 }\r
2520 \r
2521                 p_wr[i].p_next = &p_wr[i + 1];\r
2522         }\r
2523 \r
2524         /* Mark the end of list. */\r
2525         p_wr[i-1].p_next = NULL;\r
2526 \r
2527         status = ib_post_recv( h_qp, p_wr, &p_recv_failure );\r
2528 \r
2529         if( status == IB_SUCCESS )\r
2530         {\r
2531                 p_ioctl->out.failed_cnt = 0;\r
2532         }\r
2533         else\r
2534         {\r
2535 proxy_post_recv_done:\r
2536                 /* First set up as if all failed. */\r
2537                 p_ioctl->out.failed_cnt = p_ioctl->in.num_wr;\r
2538                 /* Now subtract successful ones. */\r
2539                 p_ioctl->out.failed_cnt -= (uint32_t)(\r
2540                         (((uintn_t)p_recv_failure) - ((uintn_t)p_wr))\r
2541                         / sizeof(ib_recv_wr_t));\r
2542         }\r
2543 \r
2544         if( h_qp )\r
2545                 deref_al_obj( &h_qp->obj );\r
2546 \r
2547         p_ioctl->out.status = status;\r
2548         *p_ret_bytes = sizeof(p_ioctl->out);\r
2549 \r
2550         AL_EXIT( AL_DBG_QP );\r
2551         return CL_SUCCESS;\r
2552 }\r
2553 \r
2554 \r
2555 /*\r
2556  * Process the ioctl UAL_POST_SRQ_RECV\r
2557  */\r
2558 static\r
2559 cl_status_t\r
2560 proxy_post_srq_recv(\r
2561         IN              void                                    *p_open_context,\r
2562         IN              cl_ioctl_handle_t               h_ioctl,\r
2563                 OUT     size_t                                  *p_ret_bytes )\r
2564 {\r
2565         ual_post_srq_recv_ioctl_t       *p_ioctl =\r
2566                 (ual_post_srq_recv_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2567         al_dev_open_context_t   *p_context =\r
2568                 (al_dev_open_context_t *)p_open_context;\r
2569         ib_srq_handle_t                 h_srq;\r
2570         ib_recv_wr_t                    *p_wr;\r
2571         ib_recv_wr_t                    *p_recv_failure;\r
2572         uintn_t                                 i;\r
2573         ib_local_ds_t                   *p_ds;\r
2574         uintn_t                                 num_ds = 0;\r
2575         ib_api_status_t                 status;\r
2576         size_t                                  in_buf_sz;\r
2577 \r
2578         AL_ENTER( AL_DBG_QP );\r
2579 \r
2580         /* Validate input buffers. */\r
2581         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2582                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
2583                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2584         {\r
2585                 AL_EXIT( AL_DBG_QP );\r
2586                 return CL_INVALID_PARAMETER;\r
2587         }\r
2588 \r
2589         /*\r
2590          * Additional input buffer validation based on actual settings.\r
2591          * Note that this validates that work requests are actually\r
2592          * being passed in.\r
2593          */\r
2594         in_buf_sz = sizeof(p_ioctl->in);\r
2595         in_buf_sz += sizeof(ib_recv_wr_t) * (p_ioctl->in.num_wr - 1);\r
2596         in_buf_sz += sizeof(ib_local_ds_t) * p_ioctl->in.num_ds;\r
2597         if( cl_ioctl_in_size( h_ioctl ) != in_buf_sz )\r
2598         {\r
2599                 AL_EXIT( AL_DBG_QP );\r
2600                 return CL_INVALID_PARAMETER;\r
2601         }\r
2602 \r
2603         /* Setup p_send_failure to head of list. */\r
2604         p_recv_failure = p_wr = p_ioctl->in.recv_wr;\r
2605 \r
2606         /* Validate SRQ handle */\r
2607         h_srq = (ib_srq_handle_t)\r
2608                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_srq, AL_OBJ_TYPE_H_QP );\r
2609         if( !h_srq )\r
2610         {\r
2611                 status = IB_INVALID_SRQ_HANDLE;\r
2612                 goto proxy_post_recv_done;\r
2613         }\r
2614 \r
2615         /* Setup the base data segment pointer. */\r
2616         p_ds = (ib_local_ds_t*)&p_ioctl->in.recv_wr[p_ioctl->in.num_wr];\r
2617 \r
2618         /* Setup the user's work requests and data segments and translate. */\r
2619         for( i = 0; i < p_ioctl->in.num_wr; i++ )\r
2620         {\r
2621                 /* Setup the data segments, if any. */\r
2622                 if( p_wr[i].num_ds )\r
2623                 {\r
2624                         num_ds += p_wr[i].num_ds;\r
2625                         if( num_ds > p_ioctl->in.num_ds )\r
2626                         {\r
2627                                 /*\r
2628                                 * The work request submitted exceed the number of data\r
2629                                 * segments specified in the IOCTL.\r
2630                                 */\r
2631                                 status = IB_INVALID_PARAMETER;\r
2632                                 goto proxy_post_recv_done;\r
2633                         }\r
2634                         p_wr[i].ds_array = p_ds;\r
2635                         p_ds += p_wr->num_ds;\r
2636                 }\r
2637                 else\r
2638                 {\r
2639                         p_wr[i].ds_array = NULL;\r
2640                 }\r
2641 \r
2642                 p_wr[i].p_next = &p_wr[i + 1];\r
2643         }\r
2644 \r
2645         /* Mark the end of list. */\r
2646         p_wr[i-1].p_next = NULL;\r
2647 \r
2648         status = ib_post_srq_recv( h_srq, p_wr, &p_recv_failure );\r
2649 \r
2650         if( status == IB_SUCCESS )\r
2651         {\r
2652                 p_ioctl->out.failed_cnt = 0;\r
2653         }\r
2654         else\r
2655         {\r
2656 proxy_post_recv_done:\r
2657                 /* First set up as if all failed. */\r
2658                 p_ioctl->out.failed_cnt = p_ioctl->in.num_wr;\r
2659                 /* Now subtract successful ones. */\r
2660                 p_ioctl->out.failed_cnt -= (uint32_t)(\r
2661                         (((uintn_t)p_recv_failure) - ((uintn_t)p_wr))\r
2662                         / sizeof(ib_recv_wr_t));\r
2663         }\r
2664 \r
2665         if( h_srq )\r
2666                 deref_al_obj( &h_srq->obj );\r
2667 \r
2668         p_ioctl->out.status = status;\r
2669         *p_ret_bytes = sizeof(p_ioctl->out);\r
2670 \r
2671         AL_EXIT( AL_DBG_QP );\r
2672         return CL_SUCCESS;\r
2673 }\r
2674 \r
2675 \r
2676 /*\r
2677  * Process the ioctl UAL_PEEK_CQ\r
2678  */\r
2679 static cl_status_t\r
2680 proxy_peek_cq(\r
2681         IN              void                                    *p_open_context,\r
2682         IN              cl_ioctl_handle_t               h_ioctl,\r
2683                 OUT     size_t                                  *p_ret_bytes )\r
2684 {\r
2685         ual_peek_cq_ioctl_t             *p_ioctl =\r
2686                 (ual_peek_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2687         al_dev_open_context_t   *p_context =\r
2688                 (al_dev_open_context_t *)p_open_context;\r
2689         ib_cq_handle_t                  h_cq;\r
2690 \r
2691         AL_ENTER( AL_DBG_CQ );\r
2692 \r
2693         /* Validate input buffers. */\r
2694         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2695                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2696                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2697         {\r
2698                 AL_EXIT( AL_DBG_CQ );\r
2699                 return CL_INVALID_PARAMETER;\r
2700         }\r
2701 \r
2702         /* Set the return bytes in all cases */\r
2703         *p_ret_bytes = sizeof(p_ioctl->out);\r
2704 \r
2705         /* Validate CQ handle */\r
2706         h_cq = (ib_cq_handle_t)\r
2707                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2708         if( !h_cq )\r
2709         {\r
2710                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2711                 p_ioctl->out.n_cqes = 0;\r
2712                 AL_EXIT( AL_DBG_CQ );\r
2713                 return CL_SUCCESS;\r
2714         }\r
2715 \r
2716         p_ioctl->out.status = ib_peek_cq( h_cq, &p_ioctl->out.n_cqes );\r
2717 \r
2718         deref_al_obj( &h_cq->obj );\r
2719 \r
2720         AL_EXIT( AL_DBG_CQ );\r
2721         return CL_SUCCESS;\r
2722 }\r
2723 \r
2724 \r
2725 \r
2726 /*\r
2727  * Process the ioctl UAL_POLL_CQ\r
2728  */\r
2729 static cl_status_t\r
2730 proxy_poll_cq(\r
2731         IN              void                                    *p_open_context,\r
2732         IN              cl_ioctl_handle_t               h_ioctl,\r
2733                 OUT     size_t                                  *p_ret_bytes )\r
2734 {\r
2735         ual_poll_cq_ioctl_t             *p_ioctl;\r
2736         al_dev_open_context_t   *p_context;\r
2737         ib_cq_handle_t                  h_cq;\r
2738         ib_wc_t                                 *p_free_wc;\r
2739         ib_wc_t                                 *p_done_wc = NULL;\r
2740         uint32_t                                i, num_wc;\r
2741         size_t                                  out_buf_sz;\r
2742         ib_api_status_t                 status;\r
2743 \r
2744         AL_ENTER( AL_DBG_CQ );\r
2745 \r
2746         p_ioctl = (ual_poll_cq_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
2747         p_context = (al_dev_open_context_t*)p_open_context;\r
2748 \r
2749         /* Validate input buffers. */\r
2750         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2751                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2752                 cl_ioctl_out_size( h_ioctl ) < sizeof(p_ioctl->out) )\r
2753         {\r
2754                 AL_EXIT( AL_DBG_CQ );\r
2755                 return CL_INVALID_PARAMETER;\r
2756         }\r
2757 \r
2758         /*\r
2759          * Additional validation of input and output sizes.\r
2760          * Note that this also checks that work completions are actually\r
2761          * being passed in.\r
2762          */\r
2763         out_buf_sz = sizeof(p_ioctl->out);\r
2764         out_buf_sz += sizeof(ib_wc_t) * (p_ioctl->in.num_wc - 1);\r
2765         if( cl_ioctl_out_size( h_ioctl ) != out_buf_sz )\r
2766         {\r
2767                 AL_EXIT( AL_DBG_CQ );\r
2768                 return CL_INVALID_PARAMETER;\r
2769         }\r
2770 \r
2771         /* Validate CQ handle. */\r
2772         h_cq = (ib_cq_handle_t)\r
2773                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2774         if( !h_cq )\r
2775         {\r
2776                 status = IB_INVALID_CQ_HANDLE;\r
2777                 goto proxy_poll_cq_err;\r
2778         }\r
2779 \r
2780         p_free_wc = p_ioctl->out.wc;\r
2781         num_wc = p_ioctl->in.num_wc;\r
2782         for( i = 0; i < num_wc; i++ )\r
2783                 p_free_wc[i].p_next = &p_free_wc[i+1];\r
2784         p_free_wc[i - 1].p_next = NULL;\r
2785 \r
2786         status = ib_poll_cq( h_cq, &p_free_wc, &p_done_wc );\r
2787 \r
2788         /*\r
2789          * If any of the completions are done, copy to user\r
2790          * otherwise, just return\r
2791          */\r
2792         if( status == IB_SUCCESS )\r
2793         {\r
2794                 CL_ASSERT( p_done_wc );\r
2795                 /* Calculate the number of WCs. */\r
2796                 if( !p_free_wc )\r
2797                 {\r
2798                         p_ioctl->out.num_wc = num_wc;\r
2799                 }\r
2800                 else\r
2801                 {\r
2802                         p_ioctl->out.num_wc = (uint32_t)\r
2803                                 (((uintn_t)p_free_wc) - ((uintn_t)p_done_wc)) /\r
2804                                 sizeof(ib_wc_t);\r
2805                 }\r
2806         }\r
2807         else\r
2808         {\r
2809 proxy_poll_cq_err:\r
2810                 p_ioctl->out.num_wc = 0;\r
2811         }\r
2812 \r
2813         if( h_cq )\r
2814                 deref_al_obj( &h_cq->obj );\r
2815 \r
2816         p_ioctl->out.status = status;\r
2817         *p_ret_bytes = sizeof(p_ioctl->out) - sizeof(ib_wc_t);\r
2818         if( p_ioctl->out.num_wc )\r
2819                 *p_ret_bytes += (sizeof(ib_wc_t) * (p_ioctl->out.num_wc));\r
2820 \r
2821         AL_EXIT( AL_DBG_CQ );\r
2822         return CL_SUCCESS;\r
2823 }\r
2824 \r
2825 \r
2826 \r
2827 /*\r
2828  * Process the ioctl UAL_REARM_CQ\r
2829  */\r
2830 static cl_status_t\r
2831 proxy_rearm_cq(\r
2832         IN              void                                    *p_open_context,\r
2833         IN              cl_ioctl_handle_t               h_ioctl,\r
2834                 OUT     size_t                                  *p_ret_bytes )\r
2835 {\r
2836         ual_rearm_cq_ioctl_t    *p_ioctl =\r
2837                 (ual_rearm_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2838         al_dev_open_context_t   *p_context =\r
2839                 (al_dev_open_context_t *)p_open_context;\r
2840         ib_cq_handle_t                  h_cq;\r
2841 \r
2842         AL_ENTER( AL_DBG_CQ );\r
2843 \r
2844         /* Validate input buffers. */\r
2845         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2846                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2847                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2848         {\r
2849                 AL_EXIT( AL_DBG_CQ );\r
2850                 return CL_INVALID_PARAMETER;\r
2851         }\r
2852 \r
2853         /* Set the return bytes in all cases */\r
2854         *p_ret_bytes = sizeof(p_ioctl->out);\r
2855 \r
2856         /* Validate CQ handle */\r
2857         h_cq = (ib_cq_handle_t)\r
2858                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2859         if( !h_cq )\r
2860         {\r
2861                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2862                 AL_EXIT( AL_DBG_CQ );\r
2863                 return CL_SUCCESS;\r
2864         }\r
2865 \r
2866         p_ioctl->out.status = ib_rearm_cq( h_cq, p_ioctl->in.solicited );\r
2867 \r
2868         deref_al_obj( &h_cq->obj );\r
2869 \r
2870         AL_EXIT( AL_DBG_CQ );\r
2871         return CL_SUCCESS;\r
2872 }\r
2873 \r
2874 \r
2875 \r
2876 /*\r
2877  * Process the ioctl UAL_REARM_N_CQ\r
2878  */\r
2879 static\r
2880 cl_status_t\r
2881 proxy_rearm_n_cq(\r
2882         IN              void                                    *p_open_context,\r
2883         IN              cl_ioctl_handle_t               h_ioctl,\r
2884                 OUT     size_t                                  *p_ret_bytes )\r
2885 {\r
2886         ual_rearm_n_cq_ioctl_t *p_ioctl =\r
2887                 (ual_rearm_n_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2888         al_dev_open_context_t   *p_context =\r
2889                 (al_dev_open_context_t *)p_open_context;\r
2890         ib_cq_handle_t                  h_cq;\r
2891 \r
2892         AL_ENTER( AL_DBG_CQ );\r
2893 \r
2894         /* Validate input buffers. */\r
2895         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2896                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2897                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2898         {\r
2899                 AL_EXIT( AL_DBG_CQ );\r
2900                 return CL_INVALID_PARAMETER;\r
2901         }\r
2902 \r
2903         /* Set the return bytes in all cases */\r
2904         *p_ret_bytes = sizeof(p_ioctl->out);\r
2905 \r
2906         /* Validate CQ handle */\r
2907         h_cq = (ib_cq_handle_t)\r
2908                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2909         if( !h_cq )\r
2910         {\r
2911                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2912                 AL_EXIT( AL_DBG_CQ );\r
2913                 return CL_SUCCESS;\r
2914         }\r
2915 \r
2916         p_ioctl->out.status = ib_rearm_n_cq( h_cq, p_ioctl->in.n_cqes );\r
2917 \r
2918         deref_al_obj( &h_cq->obj );\r
2919 \r
2920         AL_EXIT( AL_DBG_CQ );\r
2921         return CL_SUCCESS;\r
2922 }\r
2923 \r
2924 \r
2925 \r
2926 /*\r
2927  * Process the ioctl UAL_REGISTER_MEM:\r
2928  */\r
2929 static cl_status_t\r
2930 proxy_register_mr(\r
2931         IN              void                                    *p_open_context,\r
2932         IN              cl_ioctl_handle_t               h_ioctl,\r
2933                 OUT     size_t                                  *p_ret_bytes )\r
2934 {\r
2935         ual_reg_mem_ioctl_t             *p_ioctl =\r
2936                 (ual_reg_mem_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2937         al_dev_open_context_t   *p_context =\r
2938                 (al_dev_open_context_t *)p_open_context;\r
2939         ib_pd_handle_t                  h_pd;\r
2940         ib_mr_handle_t                  h_mr;\r
2941         ib_api_status_t                 status;\r
2942 \r
2943         AL_ENTER( AL_DBG_MR );\r
2944 \r
2945         /* Validate input buffers. */\r
2946         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2947                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2948                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2949         {\r
2950                 AL_EXIT( AL_DBG_MR );\r
2951                 return CL_INVALID_PARAMETER;\r
2952         }\r
2953 \r
2954         /* Validate PD handle */\r
2955         h_pd = (ib_pd_handle_t)\r
2956                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
2957         if( !h_pd )\r
2958         {\r
2959                 status = IB_INVALID_PD_HANDLE;\r
2960                 goto proxy_register_mr_err;\r
2961         }\r
2962 \r
2963         /* Validate input region size. */\r
2964         if( p_ioctl->in.mem_create.length > ~((size_t)0) )\r
2965         {\r
2966                 status = IB_INVALID_SETTING;\r
2967                 goto proxy_register_mr_err;\r
2968         }\r
2969 \r
2970         status = reg_mem( h_pd, &p_ioctl->in.mem_create, &p_ioctl->out.lkey,\r
2971                 &p_ioctl->out.rkey, &h_mr, TRUE );\r
2972 \r
2973         if( status == IB_SUCCESS )\r
2974         {\r
2975                 p_ioctl->out.h_mr = h_mr->obj.hdl;\r
2976                 h_mr->obj.hdl_valid = TRUE;\r
2977                 deref_al_obj( &h_mr->obj );\r
2978         }\r
2979         else\r
2980         {\r
2981 proxy_register_mr_err:\r
2982                 p_ioctl->out.h_mr = AL_INVALID_HANDLE;\r
2983                 p_ioctl->out.lkey = 0;\r
2984                 p_ioctl->out.rkey = 0;\r
2985         }\r
2986 \r
2987         if( h_pd )\r
2988                 deref_al_obj( &h_pd->obj );\r
2989 \r
2990         p_ioctl->out.status = status;\r
2991         *p_ret_bytes = sizeof(p_ioctl->out);\r
2992 \r
2993         AL_EXIT( AL_DBG_MR );\r
2994         return CL_SUCCESS;\r
2995 }\r
2996 \r
2997 \r
2998 \r
2999 /*\r
3000  * Process the ioctl UAL_QUERY_MEM:\r
3001  */\r
3002 static cl_status_t\r
3003 proxy_query_mr(\r
3004         IN              void                                    *p_open_context,\r
3005         IN              cl_ioctl_handle_t               h_ioctl,\r
3006         OUT             size_t                                  *p_ret_bytes )\r
3007 {\r
3008         ual_query_mr_ioctl_t    *p_ioctl =\r
3009                 (ual_query_mr_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
3010         al_dev_open_context_t   *p_context =\r
3011                 (al_dev_open_context_t *)p_open_context;\r
3012         ib_mr_handle_t                  h_mr;\r
3013         ib_api_status_t                 status;\r
3014 \r
3015         AL_ENTER( AL_DBG_MR );\r
3016 \r
3017         /* Validate input buffers. */\r
3018         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
3019                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
3020                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
3021         {\r
3022                 AL_EXIT( AL_DBG_MR );\r
3023                 return CL_INVALID_PARAMETER;\r
3024         }\r
3025 \r
3026         /* Validate MR handle */\r
3027         h_mr = (ib_mr_handle_t)\r
3028                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_mr, AL_OBJ_TYPE_H_MR );\r
3029         if( !h_mr )\r
3030         {\r
3031                 status = IB_INVALID_MR_HANDLE;\r
3032                 goto proxy_query_mr_err;\r
3033         }\r
3034 \r
3035         status = ib_query_mr( h_mr, &p_ioctl->out.attr );\r
3036 \r
3037         if( status == IB_SUCCESS )\r
3038         {\r
3039                 /* Replace the pd handle with proxy's handle */\r
3040                 p_ioctl->out.attr.h_pd =\r
3041                         (ib_pd_handle_t)HDL_TO_PTR(p_ioctl->out.attr.h_pd->obj.hdl);\r
3042         }\r
3043         else\r
3044         {\r
3045 proxy_query_mr_err:\r
3046                 cl_memclr( &p_ioctl->out.attr, sizeof(ib_mr_attr_t) );\r
3047         }\r
3048 \r
3049         if( h_mr )\r
3050                 deref_al_obj( &h_mr->obj );\r
3051 \r
3052         p_ioctl->out.status = status;\r
3053         *p_ret_bytes = sizeof(p_ioctl->out);\r
3054 \r
3055         AL_EXIT( AL_DBG_MR );\r
3056         return CL_SUCCESS;\r
3057 }\r
3058 \r
3059 \r
3060 \r
3061 /*\r
3062  * Process the ioctl UAL_MODIFY_MEM:\r
3063  */\r
3064 static cl_status_t\r
3065 proxy_modify_mr(\r
3066         IN              void                                    *p_open_context,\r
3067         IN              cl_ioctl_handle_t               h_ioctl,\r
3068                 OUT     size_t                                  *p_ret_bytes )\r
3069 {\r
3070         ual_rereg_mem_ioctl_t   *p_ioctl =\r
3071                 (ual_rereg_mem_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
3072         al_dev_open_context_t   *p_context =\r
3073                 (al_dev_open_context_t *)p_open_context;\r
3074         ib_mr_handle_t                  h_mr;\r
3075         ib_pd_handle_t                  h_pd = NULL;\r
3076         ib_mr_create_t                  *p_mr_create;\r
3077         ib_api_status_t                 status;\r
3078 \r
3079         AL_ENTER( AL_DBG_MR );\r
3080 \r
3081         /* Validate input buffers. */\r
3082         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
3083                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
3084                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
3085         {\r
3086                 AL_EXIT( AL_DBG_MR );\r
3087                 return CL_INVALID_PARAMETER;\r
3088         }\r
3089 \r
3090         /* Validate MR handle */\r
3091         h_mr = (ib_mr_handle_t)\r
3092                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_mr, AL_OBJ_TYPE_H_MR );\r
3093         if( !h_mr )\r
3094         {\r
3095                 status = IB_INVALID_MR_HANDLE;\r
3096                 goto proxy_modify_mr_err;\r
3097         }\r
3098 \r
3099         /* Validate input region size. */\r
3100         if( p_ioctl->in.mem_create.length > ~((size_t)0) )\r
3101         {\r
3102                 status = IB_INVALID_SETTING;\r
3103                 goto proxy_modify_mr_err;\r
3104         }\r
3105 \r
3106         if( p_ioctl->in.mem_mod_mask & IB_MR_MOD_PD )\r
3107         {\r
3108                 if( !p_ioctl->in.h_pd )\r
3109                 {\r
3110                         status = IB_INVALID_PD_HANDLE;\r
3111                         goto proxy_modify_mr_err;\r
3112                 }\r
3113                 /* This is a modify PD request, validate the PD handle */\r
3114                 h_pd = (ib_pd_handle_t)\r
3115                         al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
3116                 if( !h_pd )\r
3117                 {\r
3118                         status = IB_INVALID_PD_HANDLE;\r
3119                         goto proxy_modify_mr_err;\r
3120                 }\r
3121         }\r
3122         else\r
3123         {\r
3124                 h_pd = NULL;\r
3125         }\r
3126 \r
3127         if( p_ioctl->in.mem_mod_mask != IB_MR_MOD_PD )\r
3128                 p_mr_create = &p_ioctl->in.mem_create;\r
3129         else\r
3130                 p_mr_create = NULL;\r
3131 \r
3132         status = rereg_mem( h_mr, p_ioctl->in.mem_mod_mask,\r
3133                 p_mr_create, &p_ioctl->out.lkey, &p_ioctl->out.rkey, h_pd, TRUE );\r
3134 \r
3135         if( status != IB_SUCCESS )\r
3136         {\r
3137 proxy_modify_mr_err:\r
3138                 p_ioctl->out.lkey = 0;\r
3139                 p_ioctl->out.rkey = 0;\r
3140         }\r
3141 \r
3142         if( h_pd )\r
3143                 deref_al_obj( &h_pd->obj );\r
3144 \r
3145         if( h_mr )\r
3146                 deref_al_obj( &h_mr->obj );\r
3147 \r
3148         p_ioctl->out.status = status;\r
3149         *p_ret_bytes = sizeof(p_ioctl->out);\r
3150 \r
3151         AL_EXIT( AL_DBG_MR );\r
3152         return CL_SUCCESS;\r
3153 }\r
3154 \r
3155 \r
3156 \r
3157 /*\r
3158  * Process the ioctl UAL_REG_SHARED_MEM:\r
3159  */\r
3160 static cl_status_t\r
3161 proxy_shared_mr(\r
3162         IN              void                                    *p_open_context,\r
3163         IN              cl_ioctl_handle_t               h_ioctl,\r
3164                 OUT     size_t                                  *p_ret_bytes )\r
3165 {\r
3166         ual_reg_shared_ioctl_t  *p_ioctl =\r
3167                 (ual_reg_shared_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
3168         al_dev_open_context_t   *p_context =\r
3169                 (al_dev_open_context_t *)p_open_context;\r
3170         ib_pd_handle_t                  h_pd;\r
3171         ib_mr_handle_t                  h_mr, h_cur_mr;\r
3172         ib_api_status_t                 status;\r
3173         uint64_t                                vaddr;\r
3174 \r
3175         AL_ENTER( AL_DBG_MR );\r
3176 \r
3177         /* Validate input buffers. */\r
3178         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
3179                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
3180                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
3181         {\r
3182                 AL_EXIT( AL_DBG_MR );\r
3183                 return CL_INVALID_PARAMETER;\r
3184         }\r
3185 \r
3186         /*\r
3187          * TODO: Must support taking an input handle that isn't\r
3188          * in this process's context.\r
3189          */\r
3190         /* Validate MR handle */\r
3191         h_cur_mr = (ib_mr_handle_t)\r
3192                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_mr, AL_OBJ_TYPE_H_MR );\r
3193         if( !h_cur_mr )\r
3194         {\r
3195                 h_pd = NULL;\r
3196                 status = IB_INVALID_MR_HANDLE;\r
3197                 goto proxy_shared_mr_err;\r
3198         }\r
3199 \r
3200         /* Validate the PD handle */\r
3201         h_pd = (ib_pd_handle_t)\r
3202                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
3203         if( !h_pd )\r
3204         {\r
3205                 status = IB_INVALID_PD_HANDLE;\r
3206                 goto proxy_shared_mr_err;\r
3207         }\r
3208 \r
3209         vaddr = p_ioctl->in.vaddr;\r
3210         status = reg_shared( h_cur_mr, h_pd,\r
3211                 p_ioctl->in.access_ctrl, &vaddr, &p_ioctl->out.lkey,\r
3212                 &p_ioctl->out.rkey, &h_mr, TRUE );\r
3213 \r
3214         if( status == IB_SUCCESS )\r
3215         {\r
3216                 p_ioctl->out.h_new_mr = h_mr->obj.hdl;\r
3217                 p_ioctl->out.vaddr = vaddr;\r
3218                 h_mr->obj.hdl_valid = TRUE;\r
3219                 deref_al_obj( &h_mr->obj );\r
3220         }\r
3221         else\r
3222         {\r
3223 proxy_shared_mr_err:\r
3224                 cl_memclr( &p_ioctl->out, sizeof(p_ioctl->out) );\r
3225         }\r
3226 \r
3227         if( h_pd )\r
3228                 deref_al_obj( &h_pd->obj );\r
3229 \r
3230         if( h_cur_mr )\r
3231                 deref_al_obj( &h_cur_mr->obj );\r
3232 \r
3233         p_ioctl->out.status = status;\r
3234         *p_ret_bytes = sizeof(p_ioctl->out);\r
3235 \r
3236         AL_EXIT( AL_DBG_MR );\r
3237         return CL_SUCCESS;\r
3238 }\r
3239 \r
3240 \r
3241 \r
3242 /*\r
3243  * Process the ioctl UAL_DEREGISTER_MEM:\r
3244  */\r
3245 static cl_status_t\r
3246 proxy_deregister_mr(\r
3247         IN              void                                    *p_open_context,\r
3248         IN              cl_ioctl_handle_t               h_ioctl,\r
3249                 OUT     size_t                                  *p_ret_byt