[IBAL, HW] Remove pointers from ci_umv_buf_t.
[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                 /* Return proxy's PD handle when AV was created */\r
1778                 p_ioctl->out.pd_context = (void*)h_pd->obj.context;\r
1779         }\r
1780         else\r
1781         {\r
1782 proxy_query_av_err:\r
1783                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1784                 cl_memclr( &p_ioctl->out.attr, sizeof(ib_av_attr_t) );\r
1785                 p_ioctl->out.pd_context = NULL;\r
1786         }\r
1787         free_umvbuf( p_umv_buf );\r
1788 \r
1789         if( h_av )\r
1790                 deref_al_obj( &h_av->obj );\r
1791 \r
1792         p_ioctl->out.status = status;\r
1793         *p_ret_bytes = sizeof(p_ioctl->out);\r
1794 \r
1795         AL_EXIT( AL_DBG_AV );\r
1796         return CL_SUCCESS;\r
1797 }\r
1798 \r
1799 \r
1800 \r
1801 /*\r
1802  * Process the ioctl UAL_MODIFY_AV:\r
1803  */\r
1804 static\r
1805 cl_status_t\r
1806 proxy_modify_av(\r
1807         IN              void                                    *p_open_context,\r
1808         IN              cl_ioctl_handle_t               h_ioctl,\r
1809                 OUT     size_t                                  *p_ret_bytes )\r
1810 {\r
1811         ual_modify_av_ioctl_t   *p_ioctl =\r
1812                 (ual_modify_av_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1813         al_dev_open_context_t   *p_context =\r
1814                 (al_dev_open_context_t *)p_open_context;\r
1815         ib_av_handle_t                  h_av;\r
1816         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1817         ib_api_status_t                 status;\r
1818 \r
1819         AL_ENTER( AL_DBG_AV );\r
1820 \r
1821         /* Validate input buffers. */\r
1822         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1823                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1824                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1825         {\r
1826                 AL_EXIT( AL_DBG_AV );\r
1827                 return CL_INVALID_PARAMETER;\r
1828         }\r
1829 \r
1830         /* Validate AV handle */\r
1831         h_av = (ib_av_handle_t)\r
1832                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_av, AL_OBJ_TYPE_H_AV );\r
1833         if( !h_av )\r
1834         {\r
1835                 status = IB_INVALID_AV_HANDLE;\r
1836                 goto proxy_modify_av_err;\r
1837         }\r
1838 \r
1839         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1840         if( status != IB_SUCCESS )\r
1841                 goto proxy_modify_av_err;\r
1842 \r
1843         status = modify_av( h_av, &p_ioctl->in.attr, p_umv_buf );\r
1844 \r
1845         if( status != IB_SUCCESS )\r
1846                 goto proxy_modify_av_err;\r
1847 \r
1848         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1849         if( status != IB_SUCCESS )\r
1850         {\r
1851 proxy_modify_av_err:\r
1852                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1853         }\r
1854         free_umvbuf( p_umv_buf );\r
1855 \r
1856         if( h_av )\r
1857                 deref_al_obj( &h_av->obj );\r
1858 \r
1859         p_ioctl->out.status = status;\r
1860         *p_ret_bytes = sizeof(p_ioctl->out);\r
1861 \r
1862         AL_EXIT( AL_DBG_AV );\r
1863         return CL_SUCCESS;\r
1864 }\r
1865 \r
1866 \r
1867 \r
1868 /*\r
1869  * Process the ioctl UAL_DESTROY_AV:\r
1870  */\r
1871 static\r
1872 cl_status_t\r
1873 proxy_destroy_av(\r
1874         IN              void                                    *p_open_context,\r
1875         IN              cl_ioctl_handle_t               h_ioctl,\r
1876                 OUT     size_t                                  *p_ret_bytes )\r
1877 {\r
1878         ual_destroy_av_ioctl_t  *p_ioctl =\r
1879                 (ual_destroy_av_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1880         al_dev_open_context_t   *p_context =\r
1881                 (al_dev_open_context_t *)p_open_context;\r
1882         ib_av_handle_t                  h_av;\r
1883 \r
1884         AL_ENTER( AL_DBG_AV );\r
1885 \r
1886         /* Validate input buffers. */\r
1887         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1888                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1889                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1890         {\r
1891                 AL_EXIT( AL_DBG_AV );\r
1892                 return CL_INVALID_PARAMETER;\r
1893         }\r
1894 \r
1895         /* Set the return bytes in all cases */\r
1896         *p_ret_bytes = sizeof(p_ioctl->out);\r
1897 \r
1898         /* Validate AV handle */\r
1899         h_av = (ib_av_handle_t)\r
1900                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_av, AL_OBJ_TYPE_H_AV );\r
1901         if( !h_av )\r
1902         {\r
1903                 p_ioctl->out.status = IB_INVALID_AV_HANDLE;\r
1904                 AL_EXIT( AL_DBG_AV );\r
1905                 return CL_SUCCESS;\r
1906         }\r
1907 \r
1908         h_av->obj.pfn_destroy( &h_av->obj, NULL );\r
1909         p_ioctl->out.status = IB_SUCCESS;\r
1910 \r
1911         AL_EXIT( AL_DBG_AV );\r
1912         return CL_SUCCESS;\r
1913 }\r
1914 \r
1915 \r
1916 \r
1917 /*\r
1918  * Process the ioctl UAL_MODIFY_CQ:\r
1919  */\r
1920 static\r
1921 cl_status_t\r
1922 proxy_modify_cq(\r
1923         IN              void                                    *p_open_context,\r
1924         IN              cl_ioctl_handle_t               h_ioctl,\r
1925                 OUT     size_t                                  *p_ret_bytes )\r
1926 {\r
1927         ual_modify_cq_ioctl_t   *p_ioctl =\r
1928                 (ual_modify_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
1929         al_dev_open_context_t   *p_context =\r
1930                 (al_dev_open_context_t *)p_open_context;\r
1931         ib_cq_handle_t                  h_cq;\r
1932         ci_umv_buf_t                    *p_umv_buf = NULL;\r
1933         ib_api_status_t                 status;\r
1934         uint32_t                                size;\r
1935 \r
1936         AL_ENTER( AL_DBG_CQ );\r
1937 \r
1938         /* Validate input buffers. */\r
1939         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
1940                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
1941                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
1942         {\r
1943                 AL_EXIT( AL_DBG_CQ );\r
1944                 return CL_INVALID_PARAMETER;\r
1945         }\r
1946 \r
1947         /* Validate CQ handle */\r
1948         h_cq = (ib_cq_handle_t)\r
1949                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
1950         if( !h_cq )\r
1951         {\r
1952                 status = IB_INVALID_CQ_HANDLE;\r
1953                 goto proxy_modify_cq_err;\r
1954         }\r
1955 \r
1956         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
1957         if( status != IB_SUCCESS )\r
1958                 goto proxy_modify_cq_err;\r
1959 \r
1960         size = p_ioctl->in.size;\r
1961         status = modify_cq( h_cq, &size, p_umv_buf );\r
1962         if( status != IB_SUCCESS )\r
1963                 goto proxy_modify_cq_err;\r
1964 \r
1965         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
1966         if( status == IB_SUCCESS )\r
1967         {\r
1968                 p_ioctl->out.size = size;\r
1969         }\r
1970         else\r
1971         {\r
1972 proxy_modify_cq_err:\r
1973                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
1974                 p_ioctl->out.size = 0;\r
1975         }\r
1976         free_umvbuf( p_umv_buf );\r
1977 \r
1978         if( h_cq )\r
1979                 deref_al_obj( &h_cq->obj );\r
1980 \r
1981         p_ioctl->out.status = status;\r
1982         *p_ret_bytes = sizeof(p_ioctl->out);\r
1983 \r
1984         AL_EXIT( AL_DBG_CQ );\r
1985         return CL_SUCCESS;\r
1986 }\r
1987 \r
1988 \r
1989 \r
1990 /*\r
1991  * Proxy's CQ completion callback\r
1992  */\r
1993 static void\r
1994 proxy_cq_comp_cb(\r
1995         IN                              ib_cq_handle_t                          h_cq,\r
1996         IN                              void                                            *cq_context )\r
1997 {\r
1998         comp_cb_ioctl_info_t    cb_info;\r
1999         al_dev_open_context_t   *p_context = h_cq->obj.h_al->p_context;\r
2000 \r
2001         /*\r
2002          * If we're already closing the device - do not queue a callback, since\r
2003          * we're cleaning up the callback lists.\r
2004          */\r
2005         if( !proxy_context_ref( p_context ) )\r
2006         {\r
2007                 proxy_context_deref( p_context );\r
2008                 return;\r
2009         }\r
2010 \r
2011         /* Set up context and callback record type appropriate for UAL */\r
2012         cb_info.cq_context = cq_context;\r
2013 \r
2014         /* The proxy handle must be valid now. */\r
2015         if( !h_cq->obj.hdl_valid )\r
2016                 h_cq->obj.hdl_valid = TRUE;\r
2017 \r
2018         proxy_queue_cb_buf( UAL_GET_COMP_CB_INFO, p_context, &cb_info,\r
2019                 &h_cq->obj );\r
2020         \r
2021         proxy_context_deref( p_context );\r
2022 }\r
2023 \r
2024 \r
2025 \r
2026 /*\r
2027  * Proxy's CQ error callback\r
2028  */\r
2029 static void\r
2030 proxy_cq_err_cb(\r
2031         IN                              ib_async_event_rec_t            *p_err_rec)\r
2032 {\r
2033         ib_cq_handle_t                  h_cq = p_err_rec->handle.h_cq;\r
2034         al_dev_open_context_t   *p_context = h_cq->obj.h_al->p_context;\r
2035         misc_cb_ioctl_info_t    cb_info;\r
2036 \r
2037         /*\r
2038          * If we're already closing the device - do not queue a callback, since\r
2039          * we're cleaning up the callback lists.\r
2040          */\r
2041         if( !proxy_context_ref( p_context ) )\r
2042         {\r
2043                 proxy_context_deref( p_context );\r
2044                 return;\r
2045         }\r
2046 \r
2047         /* Set up context and callback record type appropriate for UAL */\r
2048         cb_info.rec_type = CQ_ERROR_REC;\r
2049         /* Return the Proxy's cq handle and the user's context */\r
2050         cb_info.ioctl_rec.event_rec = *p_err_rec;\r
2051         cb_info.ioctl_rec.event_rec.handle.h_cq = (ib_cq_handle_t)HDL_TO_PTR(h_cq->obj.hdl);\r
2052 \r
2053         /* The proxy handle must be valid now. */\r
2054         if( !h_cq->obj.hdl_valid )\r
2055                 h_cq->obj.hdl_valid = TRUE;\r
2056 \r
2057         proxy_queue_cb_buf( UAL_GET_MISC_CB_INFO, p_context, &cb_info,\r
2058                 &h_cq->obj );\r
2059         proxy_context_deref( p_context );\r
2060 }\r
2061 \r
2062 \r
2063 \r
2064 /*\r
2065  * Process the ioctl UAL_CREATE_CQ:\r
2066  */\r
2067 static cl_status_t\r
2068 proxy_create_cq(\r
2069         IN              void                                    *p_open_context,\r
2070         IN              cl_ioctl_handle_t               h_ioctl,\r
2071                 OUT     size_t                                  *p_ret_bytes )\r
2072 {\r
2073         ual_create_cq_ioctl_t   *p_ioctl =\r
2074                 (ual_create_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2075         al_dev_open_context_t   *p_context =\r
2076                 (al_dev_open_context_t *)p_open_context;\r
2077         ib_ca_handle_t                  h_ca;\r
2078         ib_cq_handle_t                  h_cq;\r
2079         ib_cq_create_t                  cq_create;\r
2080         ci_umv_buf_t                    *p_umv_buf = NULL;\r
2081         ib_api_status_t                 status;\r
2082         ib_pfn_event_cb_t               pfn_ev;\r
2083 \r
2084         AL_ENTER( AL_DBG_CQ );\r
2085 \r
2086         /* Validate input buffers. */\r
2087         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2088                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2089                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2090         {\r
2091                 AL_EXIT( AL_DBG_CQ );\r
2092                 return CL_INVALID_PARAMETER;\r
2093         }\r
2094 \r
2095         /* Validate CA handle */\r
2096         h_ca = (ib_ca_handle_t)\r
2097                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_ca, AL_OBJ_TYPE_H_CA );\r
2098         if( !h_ca )\r
2099         {\r
2100                 status = IB_INVALID_CA_HANDLE;\r
2101                 goto proxy_create_cq_err1;\r
2102         }\r
2103 \r
2104         cq_create.size = p_ioctl->in.size;\r
2105 \r
2106         if( p_ioctl->in.h_wait_obj )\r
2107         {\r
2108                 cq_create.pfn_comp_cb = NULL;\r
2109                 cq_create.h_wait_obj = cl_waitobj_ref( p_ioctl->in.h_wait_obj );\r
2110                 if( !cq_create.h_wait_obj )\r
2111                 {\r
2112                         status = IB_INVALID_PARAMETER;\r
2113                         goto proxy_create_cq_err1;\r
2114                 }\r
2115         }\r
2116         else\r
2117         {\r
2118                 /* Override with proxy's cq callback */\r
2119                 cq_create.pfn_comp_cb = proxy_cq_comp_cb;\r
2120                 cq_create.h_wait_obj = NULL;\r
2121         }\r
2122 \r
2123         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
2124         if( status != IB_SUCCESS )\r
2125                 goto proxy_create_cq_err2;\r
2126 \r
2127         if( p_ioctl->in.ev_notify )\r
2128                 pfn_ev = proxy_cq_err_cb;\r
2129         else\r
2130                 pfn_ev = NULL;\r
2131 \r
2132         status = create_cq( h_ca, &cq_create, p_ioctl->in.context,\r
2133                 pfn_ev, &h_cq, p_umv_buf );\r
2134 \r
2135         if( status != IB_SUCCESS )\r
2136                 goto proxy_create_cq_err2;\r
2137 \r
2138         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
2139         if( status == IB_SUCCESS )\r
2140         {\r
2141                 p_ioctl->out.size = cq_create.size;\r
2142                 p_ioctl->out.h_cq = h_cq->obj.hdl;\r
2143                 h_cq->obj.hdl_valid = TRUE;\r
2144                 deref_al_obj( &h_cq->obj );\r
2145         }\r
2146         else\r
2147         {\r
2148                 h_cq->obj.pfn_destroy( &h_cq->obj, NULL );\r
2149 \r
2150 proxy_create_cq_err2:\r
2151                 if( cq_create.h_wait_obj )\r
2152                         cl_waitobj_deref( cq_create.h_wait_obj );\r
2153 \r
2154 proxy_create_cq_err1:\r
2155                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
2156                 p_ioctl->out.h_cq = AL_INVALID_HANDLE;\r
2157                 p_ioctl->out.size = 0;\r
2158         }\r
2159         free_umvbuf( p_umv_buf );\r
2160 \r
2161         if( h_ca )\r
2162                 deref_al_obj( &h_ca->obj );\r
2163 \r
2164         p_ioctl->out.status = status;\r
2165         *p_ret_bytes = sizeof(p_ioctl->out);\r
2166 \r
2167         AL_EXIT( AL_DBG_CQ );\r
2168         return CL_SUCCESS;\r
2169 }\r
2170 \r
2171 \r
2172 /*\r
2173  * Process the ioctl UAL_QUERY_CQ:\r
2174  */\r
2175 static\r
2176 cl_status_t\r
2177 proxy_query_cq(\r
2178         IN              void                                    *p_open_context,\r
2179         IN              cl_ioctl_handle_t               h_ioctl,\r
2180                 OUT     size_t                                  *p_ret_bytes )\r
2181 {\r
2182         ual_query_cq_ioctl_t    *p_ioctl =\r
2183                 (ual_query_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2184         al_dev_open_context_t   *p_context =\r
2185                 (al_dev_open_context_t *)p_open_context;\r
2186         ib_cq_handle_t                  h_cq;\r
2187         ci_umv_buf_t                    *p_umv_buf = NULL;\r
2188         ib_api_status_t                 status;\r
2189 \r
2190         AL_ENTER( AL_DBG_CQ );\r
2191 \r
2192         /* Validate input buffers. */\r
2193         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2194                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2195                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2196         {\r
2197                 AL_EXIT( AL_DBG_CQ );\r
2198                 return CL_INVALID_PARAMETER;\r
2199         }\r
2200 \r
2201         /* Validate CQ handle */\r
2202         h_cq = (ib_cq_handle_t)\r
2203                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2204         if( !h_cq )\r
2205         {\r
2206                 status = IB_INVALID_CQ_HANDLE;\r
2207                 goto proxy_query_cq_err;\r
2208         }\r
2209 \r
2210         status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf );\r
2211         if( status != IB_SUCCESS )\r
2212                 goto proxy_query_cq_err;\r
2213 \r
2214         status = query_cq( h_cq, &p_ioctl->out.size, p_umv_buf );\r
2215 \r
2216         if( status != IB_SUCCESS )\r
2217                 goto proxy_query_cq_err;\r
2218 \r
2219         status = cpyout_umvbuf( &p_ioctl->out.umv_buf, p_umv_buf );\r
2220         if( status != IB_SUCCESS )\r
2221         {\r
2222 proxy_query_cq_err:\r
2223                 p_ioctl->out.umv_buf = p_ioctl->in.umv_buf;\r
2224                 p_ioctl->out.size = 0;\r
2225         }\r
2226         free_umvbuf( p_umv_buf );\r
2227 \r
2228         if( h_cq )\r
2229                 deref_al_obj( &h_cq->obj );\r
2230 \r
2231         p_ioctl->out.status = status;\r
2232         *p_ret_bytes = sizeof(p_ioctl->out);\r
2233 \r
2234         AL_EXIT( AL_DBG_CQ );\r
2235         return CL_SUCCESS;\r
2236 }\r
2237 \r
2238 \r
2239 /*\r
2240  * Process the ioctl UAL_DESTROY_CQ\r
2241  */\r
2242 static\r
2243 cl_status_t\r
2244 proxy_destroy_cq(\r
2245         IN              void                                    *p_open_context,\r
2246         IN              cl_ioctl_handle_t               h_ioctl,\r
2247                 OUT     size_t                                  *p_ret_bytes )\r
2248 {\r
2249         ual_destroy_cq_ioctl_t  *p_ioctl =\r
2250                 (ual_destroy_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2251         al_dev_open_context_t   *p_context =\r
2252                 (al_dev_open_context_t *)p_open_context;\r
2253         ib_cq_handle_t                  h_cq;\r
2254         cl_waitobj_handle_t             h_wait_obj;\r
2255 \r
2256         AL_ENTER( AL_DBG_CQ );\r
2257 \r
2258         /* Validate input buffers. */\r
2259         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2260                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2261                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2262         {\r
2263                 AL_EXIT( AL_DBG_CQ );\r
2264                 return CL_INVALID_PARAMETER;\r
2265         }\r
2266 \r
2267         /* Set the return bytes in all cases */\r
2268         *p_ret_bytes = sizeof(p_ioctl->out);\r
2269 \r
2270         /* Validate CQ handle */\r
2271         h_cq = (ib_cq_handle_t)\r
2272                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2273         if( !h_cq )\r
2274         {\r
2275                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2276                 AL_EXIT( AL_DBG_CQ );\r
2277                 return CL_SUCCESS;\r
2278         }\r
2279 \r
2280         h_wait_obj = h_cq->h_wait_obj;\r
2281 \r
2282         h_cq->obj.pfn_destroy( &h_cq->obj, ib_sync_destroy );\r
2283 \r
2284         /* Deref the wait object, if any. */\r
2285         if( h_wait_obj )\r
2286                 cl_waitobj_deref( h_wait_obj );\r
2287 \r
2288         p_ioctl->out.status = IB_SUCCESS;\r
2289 \r
2290         AL_EXIT( AL_DBG_CQ );\r
2291         return CL_SUCCESS;\r
2292 }\r
2293 \r
2294 \r
2295 /*\r
2296  * Process the ioctl UAL_POST_SEND\r
2297  */\r
2298 static\r
2299 cl_status_t\r
2300 proxy_post_send(\r
2301         IN              void                                    *p_open_context,\r
2302         IN              cl_ioctl_handle_t               h_ioctl,\r
2303                 OUT     size_t                                  *p_ret_bytes )\r
2304 {\r
2305         ual_post_send_ioctl_t   *p_ioctl =\r
2306                 (ual_post_send_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2307         al_dev_open_context_t   *p_context =\r
2308                 (al_dev_open_context_t *)p_open_context;\r
2309         ib_qp_handle_t                  h_qp;\r
2310         ib_av_handle_t                  h_av;\r
2311         ib_send_wr_t                    *p_wr;\r
2312         ib_send_wr_t                    *p_send_failure;\r
2313         uintn_t                                 i = 0;\r
2314         ib_local_ds_t                   *p_ds;\r
2315         uintn_t                                 num_ds = 0;\r
2316         ib_api_status_t                 status;\r
2317         size_t                                  in_buf_sz;\r
2318 \r
2319         AL_ENTER( AL_DBG_QP );\r
2320         /* Validate input buffers. */\r
2321         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2322                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
2323                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2324         {\r
2325                 AL_EXIT( AL_DBG_QP );\r
2326                 return CL_INVALID_PARAMETER;\r
2327         }\r
2328 \r
2329         /*\r
2330          * Additional input buffer validation based on actual settings.\r
2331          * Note that this validates that work requests are actually\r
2332          * being passed in.\r
2333          */\r
2334         in_buf_sz = sizeof(p_ioctl->in);\r
2335         in_buf_sz += sizeof(ib_send_wr_t) * (p_ioctl->in.num_wr - 1);\r
2336         in_buf_sz += sizeof(ib_local_ds_t) * p_ioctl->in.num_ds;\r
2337         if( cl_ioctl_in_size( h_ioctl ) != in_buf_sz )\r
2338         {\r
2339                 AL_EXIT( AL_DBG_QP );\r
2340                 return CL_INVALID_PARAMETER;\r
2341         }\r
2342 \r
2343         /* Setup p_send_failure to head of list. */\r
2344         p_send_failure = p_wr = p_ioctl->in.send_wr;\r
2345 \r
2346         /* Validate QP handle */\r
2347         h_qp = (ib_qp_handle_t)\r
2348                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
2349         if( !h_qp )\r
2350         {\r
2351                 status = IB_INVALID_QP_HANDLE;\r
2352                 goto proxy_post_send_done;\r
2353         }\r
2354 \r
2355         /* Setup the base data segment pointer. */\r
2356         p_ds = (ib_local_ds_t*)&p_ioctl->in.send_wr[p_ioctl->in.num_wr];\r
2357 \r
2358         /* Setup the user's work requests and data segments and translate. */\r
2359         for( i = 0; i < p_ioctl->in.num_wr; i++ )\r
2360         {\r
2361                 if( h_qp->type == IB_QPT_UNRELIABLE_DGRM )\r
2362                 {\r
2363                         /* Validate the AV handle for UD */\r
2364                         h_av = (ib_av_handle_t)al_hdl_ref( p_context->h_al,\r
2365                                 (uint64_t)p_wr[i].dgrm.ud.h_av, AL_OBJ_TYPE_H_AV );\r
2366                         if( !h_av )\r
2367                         {\r
2368                                 status = IB_INVALID_AV_HANDLE;\r
2369                                 goto proxy_post_send_done;\r
2370                         }\r
2371                         /* substitute with KAL AV handle */\r
2372                         p_wr[i].dgrm.ud.h_av = h_av;\r
2373                 }\r
2374 \r
2375                 /* Setup the data segments, if any. */\r
2376                 if( p_wr[i].num_ds )\r
2377                 {\r
2378                         num_ds += p_wr[i].num_ds;\r
2379                         if( num_ds > p_ioctl->in.num_ds )\r
2380                         {\r
2381                                 /*\r
2382                                 * The work request submitted exceed the number of data\r
2383                                 * segments specified in the IOCTL.\r
2384                                 */\r
2385                                 status = IB_INVALID_PARAMETER;\r
2386                                 goto proxy_post_send_done;\r
2387                         }\r
2388                         p_wr[i].ds_array = p_ds;\r
2389                         p_ds += p_wr->num_ds;\r
2390                 }\r
2391                 else\r
2392                 {\r
2393                         p_wr[i].ds_array = NULL;\r
2394                 }\r
2395 \r
2396                 p_wr[i].p_next = &p_wr[i + 1];\r
2397         }\r
2398 \r
2399         /* Mark the end of list. */\r
2400         p_wr[i - 1].p_next = NULL;\r
2401 \r
2402         /* so much for the set up, let's roll! */\r
2403         status = ib_post_send( h_qp, p_wr, &p_send_failure );\r
2404 \r
2405         if( status == IB_SUCCESS )\r
2406         {\r
2407                 p_ioctl->out.failed_cnt = 0;\r
2408         }\r
2409         else\r
2410         {\r
2411 proxy_post_send_done:\r
2412                 /* First set up as if all failed. */\r
2413                 p_ioctl->out.failed_cnt = p_ioctl->in.num_wr;\r
2414                 /* Now subtract successful ones. */\r
2415                 p_ioctl->out.failed_cnt -= (uint32_t)(\r
2416                         (((uintn_t)p_send_failure) - ((uintn_t)p_wr))\r
2417                         / sizeof(ib_send_wr_t));\r
2418         }\r
2419 \r
2420         /* releases the references on address vectors. */\r
2421         if( h_qp )\r
2422         {\r
2423                 if( h_qp->type == IB_QPT_UNRELIABLE_DGRM )\r
2424                 {\r
2425                         while( i-- )\r
2426                                 deref_al_obj( &p_wr[i].dgrm.ud.h_av->obj );\r
2427                 }\r
2428                 deref_al_obj( &h_qp->obj );\r
2429         }\r
2430 \r
2431         p_ioctl->out.status = status;\r
2432         *p_ret_bytes = sizeof(p_ioctl->out);\r
2433 \r
2434         AL_EXIT( AL_DBG_QP );\r
2435         return CL_SUCCESS;\r
2436 }\r
2437 \r
2438 \r
2439 \r
2440 /*\r
2441  * Process the ioctl UAL_POST_RECV\r
2442  */\r
2443 static\r
2444 cl_status_t\r
2445 proxy_post_recv(\r
2446         IN              void                                    *p_open_context,\r
2447         IN              cl_ioctl_handle_t               h_ioctl,\r
2448                 OUT     size_t                                  *p_ret_bytes )\r
2449 {\r
2450         ual_post_recv_ioctl_t   *p_ioctl =\r
2451                 (ual_post_recv_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2452         al_dev_open_context_t   *p_context =\r
2453                 (al_dev_open_context_t *)p_open_context;\r
2454         ib_qp_handle_t                  h_qp;\r
2455         ib_recv_wr_t                    *p_wr;\r
2456         ib_recv_wr_t                    *p_recv_failure;\r
2457         uintn_t                                 i;\r
2458         ib_local_ds_t                   *p_ds;\r
2459         uintn_t                                 num_ds = 0;\r
2460         ib_api_status_t                 status;\r
2461         size_t                                  in_buf_sz;\r
2462 \r
2463         AL_ENTER( AL_DBG_QP );\r
2464 \r
2465         /* Validate input buffers. */\r
2466         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2467                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
2468                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2469         {\r
2470                 AL_EXIT( AL_DBG_QP );\r
2471                 return CL_INVALID_PARAMETER;\r
2472         }\r
2473 \r
2474         /*\r
2475          * Additional input buffer validation based on actual settings.\r
2476          * Note that this validates that work requests are actually\r
2477          * being passed in.\r
2478          */\r
2479         in_buf_sz = sizeof(p_ioctl->in);\r
2480         in_buf_sz += sizeof(ib_recv_wr_t) * (p_ioctl->in.num_wr - 1);\r
2481         in_buf_sz += sizeof(ib_local_ds_t) * p_ioctl->in.num_ds;\r
2482         if( cl_ioctl_in_size( h_ioctl ) != in_buf_sz )\r
2483         {\r
2484                 AL_EXIT( AL_DBG_QP );\r
2485                 return CL_INVALID_PARAMETER;\r
2486         }\r
2487 \r
2488         /* Setup p_send_failure to head of list. */\r
2489         p_recv_failure = p_wr = p_ioctl->in.recv_wr;\r
2490 \r
2491         /* Validate QP handle */\r
2492         h_qp = (ib_qp_handle_t)\r
2493                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_qp, AL_OBJ_TYPE_H_QP );\r
2494         if( !h_qp )\r
2495         {\r
2496                 status = IB_INVALID_QP_HANDLE;\r
2497                 goto proxy_post_recv_done;\r
2498         }\r
2499 \r
2500         /* Setup the base data segment pointer. */\r
2501         p_ds = (ib_local_ds_t*)&p_ioctl->in.recv_wr[p_ioctl->in.num_wr];\r
2502 \r
2503         /* Setup the user's work requests and data segments and translate. */\r
2504         for( i = 0; i < p_ioctl->in.num_wr; i++ )\r
2505         {\r
2506                 /* Setup the data segments, if any. */\r
2507                 if( p_wr[i].num_ds )\r
2508                 {\r
2509                         num_ds += p_wr[i].num_ds;\r
2510                         if( num_ds > p_ioctl->in.num_ds )\r
2511                         {\r
2512                                 /*\r
2513                                 * The work request submitted exceed the number of data\r
2514                                 * segments specified in the IOCTL.\r
2515                                 */\r
2516                                 status = IB_INVALID_PARAMETER;\r
2517                                 goto proxy_post_recv_done;\r
2518                         }\r
2519                         p_wr[i].ds_array = p_ds;\r
2520                         p_ds += p_wr->num_ds;\r
2521                 }\r
2522                 else\r
2523                 {\r
2524                         p_wr[i].ds_array = NULL;\r
2525                 }\r
2526 \r
2527                 p_wr[i].p_next = &p_wr[i + 1];\r
2528         }\r
2529 \r
2530         /* Mark the end of list. */\r
2531         p_wr[i-1].p_next = NULL;\r
2532 \r
2533         status = ib_post_recv( h_qp, p_wr, &p_recv_failure );\r
2534 \r
2535         if( status == IB_SUCCESS )\r
2536         {\r
2537                 p_ioctl->out.failed_cnt = 0;\r
2538         }\r
2539         else\r
2540         {\r
2541 proxy_post_recv_done:\r
2542                 /* First set up as if all failed. */\r
2543                 p_ioctl->out.failed_cnt = p_ioctl->in.num_wr;\r
2544                 /* Now subtract successful ones. */\r
2545                 p_ioctl->out.failed_cnt -= (uint32_t)(\r
2546                         (((uintn_t)p_recv_failure) - ((uintn_t)p_wr))\r
2547                         / sizeof(ib_recv_wr_t));\r
2548         }\r
2549 \r
2550         if( h_qp )\r
2551                 deref_al_obj( &h_qp->obj );\r
2552 \r
2553         p_ioctl->out.status = status;\r
2554         *p_ret_bytes = sizeof(p_ioctl->out);\r
2555 \r
2556         AL_EXIT( AL_DBG_QP );\r
2557         return CL_SUCCESS;\r
2558 }\r
2559 \r
2560 \r
2561 /*\r
2562  * Process the ioctl UAL_POST_SRQ_RECV\r
2563  */\r
2564 static\r
2565 cl_status_t\r
2566 proxy_post_srq_recv(\r
2567         IN              void                                    *p_open_context,\r
2568         IN              cl_ioctl_handle_t               h_ioctl,\r
2569                 OUT     size_t                                  *p_ret_bytes )\r
2570 {\r
2571         ual_post_srq_recv_ioctl_t       *p_ioctl =\r
2572                 (ual_post_srq_recv_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2573         al_dev_open_context_t   *p_context =\r
2574                 (al_dev_open_context_t *)p_open_context;\r
2575         ib_srq_handle_t                 h_srq;\r
2576         ib_recv_wr_t                    *p_wr;\r
2577         ib_recv_wr_t                    *p_recv_failure;\r
2578         uintn_t                                 i;\r
2579         ib_local_ds_t                   *p_ds;\r
2580         uintn_t                                 num_ds = 0;\r
2581         ib_api_status_t                 status;\r
2582         size_t                                  in_buf_sz;\r
2583 \r
2584         AL_ENTER( AL_DBG_QP );\r
2585 \r
2586         /* Validate input buffers. */\r
2587         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2588                 cl_ioctl_in_size( h_ioctl ) < sizeof(p_ioctl->in) ||\r
2589                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2590         {\r
2591                 AL_EXIT( AL_DBG_QP );\r
2592                 return CL_INVALID_PARAMETER;\r
2593         }\r
2594 \r
2595         /*\r
2596          * Additional input buffer validation based on actual settings.\r
2597          * Note that this validates that work requests are actually\r
2598          * being passed in.\r
2599          */\r
2600         in_buf_sz = sizeof(p_ioctl->in);\r
2601         in_buf_sz += sizeof(ib_recv_wr_t) * (p_ioctl->in.num_wr - 1);\r
2602         in_buf_sz += sizeof(ib_local_ds_t) * p_ioctl->in.num_ds;\r
2603         if( cl_ioctl_in_size( h_ioctl ) != in_buf_sz )\r
2604         {\r
2605                 AL_EXIT( AL_DBG_QP );\r
2606                 return CL_INVALID_PARAMETER;\r
2607         }\r
2608 \r
2609         /* Setup p_send_failure to head of list. */\r
2610         p_recv_failure = p_wr = p_ioctl->in.recv_wr;\r
2611 \r
2612         /* Validate SRQ handle */\r
2613         h_srq = (ib_srq_handle_t)\r
2614                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_srq, AL_OBJ_TYPE_H_QP );\r
2615         if( !h_srq )\r
2616         {\r
2617                 status = IB_INVALID_SRQ_HANDLE;\r
2618                 goto proxy_post_recv_done;\r
2619         }\r
2620 \r
2621         /* Setup the base data segment pointer. */\r
2622         p_ds = (ib_local_ds_t*)&p_ioctl->in.recv_wr[p_ioctl->in.num_wr];\r
2623 \r
2624         /* Setup the user's work requests and data segments and translate. */\r
2625         for( i = 0; i < p_ioctl->in.num_wr; i++ )\r
2626         {\r
2627                 /* Setup the data segments, if any. */\r
2628                 if( p_wr[i].num_ds )\r
2629                 {\r
2630                         num_ds += p_wr[i].num_ds;\r
2631                         if( num_ds > p_ioctl->in.num_ds )\r
2632                         {\r
2633                                 /*\r
2634                                 * The work request submitted exceed the number of data\r
2635                                 * segments specified in the IOCTL.\r
2636                                 */\r
2637                                 status = IB_INVALID_PARAMETER;\r
2638                                 goto proxy_post_recv_done;\r
2639                         }\r
2640                         p_wr[i].ds_array = p_ds;\r
2641                         p_ds += p_wr->num_ds;\r
2642                 }\r
2643                 else\r
2644                 {\r
2645                         p_wr[i].ds_array = NULL;\r
2646                 }\r
2647 \r
2648                 p_wr[i].p_next = &p_wr[i + 1];\r
2649         }\r
2650 \r
2651         /* Mark the end of list. */\r
2652         p_wr[i-1].p_next = NULL;\r
2653 \r
2654         status = ib_post_srq_recv( h_srq, p_wr, &p_recv_failure );\r
2655 \r
2656         if( status == IB_SUCCESS )\r
2657         {\r
2658                 p_ioctl->out.failed_cnt = 0;\r
2659         }\r
2660         else\r
2661         {\r
2662 proxy_post_recv_done:\r
2663                 /* First set up as if all failed. */\r
2664                 p_ioctl->out.failed_cnt = p_ioctl->in.num_wr;\r
2665                 /* Now subtract successful ones. */\r
2666                 p_ioctl->out.failed_cnt -= (uint32_t)(\r
2667                         (((uintn_t)p_recv_failure) - ((uintn_t)p_wr))\r
2668                         / sizeof(ib_recv_wr_t));\r
2669         }\r
2670 \r
2671         if( h_srq )\r
2672                 deref_al_obj( &h_srq->obj );\r
2673 \r
2674         p_ioctl->out.status = status;\r
2675         *p_ret_bytes = sizeof(p_ioctl->out);\r
2676 \r
2677         AL_EXIT( AL_DBG_QP );\r
2678         return CL_SUCCESS;\r
2679 }\r
2680 \r
2681 \r
2682 /*\r
2683  * Process the ioctl UAL_PEEK_CQ\r
2684  */\r
2685 static cl_status_t\r
2686 proxy_peek_cq(\r
2687         IN              void                                    *p_open_context,\r
2688         IN              cl_ioctl_handle_t               h_ioctl,\r
2689                 OUT     size_t                                  *p_ret_bytes )\r
2690 {\r
2691         ual_peek_cq_ioctl_t             *p_ioctl =\r
2692                 (ual_peek_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2693         al_dev_open_context_t   *p_context =\r
2694                 (al_dev_open_context_t *)p_open_context;\r
2695         ib_cq_handle_t                  h_cq;\r
2696 \r
2697         AL_ENTER( AL_DBG_CQ );\r
2698 \r
2699         /* Validate input buffers. */\r
2700         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2701                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2702                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2703         {\r
2704                 AL_EXIT( AL_DBG_CQ );\r
2705                 return CL_INVALID_PARAMETER;\r
2706         }\r
2707 \r
2708         /* Set the return bytes in all cases */\r
2709         *p_ret_bytes = sizeof(p_ioctl->out);\r
2710 \r
2711         /* Validate CQ handle */\r
2712         h_cq = (ib_cq_handle_t)\r
2713                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2714         if( !h_cq )\r
2715         {\r
2716                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2717                 p_ioctl->out.n_cqes = 0;\r
2718                 AL_EXIT( AL_DBG_CQ );\r
2719                 return CL_SUCCESS;\r
2720         }\r
2721 \r
2722         p_ioctl->out.status = ib_peek_cq( h_cq, &p_ioctl->out.n_cqes );\r
2723 \r
2724         deref_al_obj( &h_cq->obj );\r
2725 \r
2726         AL_EXIT( AL_DBG_CQ );\r
2727         return CL_SUCCESS;\r
2728 }\r
2729 \r
2730 \r
2731 \r
2732 /*\r
2733  * Process the ioctl UAL_POLL_CQ\r
2734  */\r
2735 static cl_status_t\r
2736 proxy_poll_cq(\r
2737         IN              void                                    *p_open_context,\r
2738         IN              cl_ioctl_handle_t               h_ioctl,\r
2739                 OUT     size_t                                  *p_ret_bytes )\r
2740 {\r
2741         ual_poll_cq_ioctl_t             *p_ioctl;\r
2742         al_dev_open_context_t   *p_context;\r
2743         ib_cq_handle_t                  h_cq;\r
2744         ib_wc_t                                 *p_free_wc;\r
2745         ib_wc_t                                 *p_done_wc = NULL;\r
2746         uint32_t                                i, num_wc;\r
2747         size_t                                  out_buf_sz;\r
2748         ib_api_status_t                 status;\r
2749 \r
2750         AL_ENTER( AL_DBG_CQ );\r
2751 \r
2752         p_ioctl = (ual_poll_cq_ioctl_t*)cl_ioctl_in_buf( h_ioctl );\r
2753         p_context = (al_dev_open_context_t*)p_open_context;\r
2754 \r
2755         /* Validate input buffers. */\r
2756         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2757                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2758                 cl_ioctl_out_size( h_ioctl ) < sizeof(p_ioctl->out) )\r
2759         {\r
2760                 AL_EXIT( AL_DBG_CQ );\r
2761                 return CL_INVALID_PARAMETER;\r
2762         }\r
2763 \r
2764         /*\r
2765          * Additional validation of input and output sizes.\r
2766          * Note that this also checks that work completions are actually\r
2767          * being passed in.\r
2768          */\r
2769         out_buf_sz = sizeof(p_ioctl->out);\r
2770         out_buf_sz += sizeof(ib_wc_t) * (p_ioctl->in.num_wc - 1);\r
2771         if( cl_ioctl_out_size( h_ioctl ) != out_buf_sz )\r
2772         {\r
2773                 AL_EXIT( AL_DBG_CQ );\r
2774                 return CL_INVALID_PARAMETER;\r
2775         }\r
2776 \r
2777         /* Validate CQ handle. */\r
2778         h_cq = (ib_cq_handle_t)\r
2779                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2780         if( !h_cq )\r
2781         {\r
2782                 status = IB_INVALID_CQ_HANDLE;\r
2783                 goto proxy_poll_cq_err;\r
2784         }\r
2785 \r
2786         p_free_wc = p_ioctl->out.wc;\r
2787         num_wc = p_ioctl->in.num_wc;\r
2788         for( i = 0; i < num_wc; i++ )\r
2789                 p_free_wc[i].p_next = &p_free_wc[i+1];\r
2790         p_free_wc[i - 1].p_next = NULL;\r
2791 \r
2792         status = ib_poll_cq( h_cq, &p_free_wc, &p_done_wc );\r
2793 \r
2794         /*\r
2795          * If any of the completions are done, copy to user\r
2796          * otherwise, just return\r
2797          */\r
2798         if( status == IB_SUCCESS )\r
2799         {\r
2800                 CL_ASSERT( p_done_wc );\r
2801                 /* Calculate the number of WCs. */\r
2802                 if( !p_free_wc )\r
2803                 {\r
2804                         p_ioctl->out.num_wc = num_wc;\r
2805                 }\r
2806                 else\r
2807                 {\r
2808                         p_ioctl->out.num_wc = (uint32_t)\r
2809                                 (((uintn_t)p_free_wc) - ((uintn_t)p_done_wc)) /\r
2810                                 sizeof(ib_wc_t);\r
2811                 }\r
2812         }\r
2813         else\r
2814         {\r
2815 proxy_poll_cq_err:\r
2816                 p_ioctl->out.num_wc = 0;\r
2817         }\r
2818 \r
2819         if( h_cq )\r
2820                 deref_al_obj( &h_cq->obj );\r
2821 \r
2822         p_ioctl->out.status = status;\r
2823         *p_ret_bytes = sizeof(p_ioctl->out) - sizeof(ib_wc_t);\r
2824         if( p_ioctl->out.num_wc )\r
2825                 *p_ret_bytes += (sizeof(ib_wc_t) * (p_ioctl->out.num_wc));\r
2826 \r
2827         AL_EXIT( AL_DBG_CQ );\r
2828         return CL_SUCCESS;\r
2829 }\r
2830 \r
2831 \r
2832 \r
2833 /*\r
2834  * Process the ioctl UAL_REARM_CQ\r
2835  */\r
2836 static cl_status_t\r
2837 proxy_rearm_cq(\r
2838         IN              void                                    *p_open_context,\r
2839         IN              cl_ioctl_handle_t               h_ioctl,\r
2840                 OUT     size_t                                  *p_ret_bytes )\r
2841 {\r
2842         ual_rearm_cq_ioctl_t    *p_ioctl =\r
2843                 (ual_rearm_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2844         al_dev_open_context_t   *p_context =\r
2845                 (al_dev_open_context_t *)p_open_context;\r
2846         ib_cq_handle_t                  h_cq;\r
2847 \r
2848         AL_ENTER( AL_DBG_CQ );\r
2849 \r
2850         /* Validate input buffers. */\r
2851         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2852                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2853                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2854         {\r
2855                 AL_EXIT( AL_DBG_CQ );\r
2856                 return CL_INVALID_PARAMETER;\r
2857         }\r
2858 \r
2859         /* Set the return bytes in all cases */\r
2860         *p_ret_bytes = sizeof(p_ioctl->out);\r
2861 \r
2862         /* Validate CQ handle */\r
2863         h_cq = (ib_cq_handle_t)\r
2864                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2865         if( !h_cq )\r
2866         {\r
2867                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2868                 AL_EXIT( AL_DBG_CQ );\r
2869                 return CL_SUCCESS;\r
2870         }\r
2871 \r
2872         p_ioctl->out.status = ib_rearm_cq( h_cq, p_ioctl->in.solicited );\r
2873 \r
2874         deref_al_obj( &h_cq->obj );\r
2875 \r
2876         AL_EXIT( AL_DBG_CQ );\r
2877         return CL_SUCCESS;\r
2878 }\r
2879 \r
2880 \r
2881 \r
2882 /*\r
2883  * Process the ioctl UAL_REARM_N_CQ\r
2884  */\r
2885 static\r
2886 cl_status_t\r
2887 proxy_rearm_n_cq(\r
2888         IN              void                                    *p_open_context,\r
2889         IN              cl_ioctl_handle_t               h_ioctl,\r
2890                 OUT     size_t                                  *p_ret_bytes )\r
2891 {\r
2892         ual_rearm_n_cq_ioctl_t *p_ioctl =\r
2893                 (ual_rearm_n_cq_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2894         al_dev_open_context_t   *p_context =\r
2895                 (al_dev_open_context_t *)p_open_context;\r
2896         ib_cq_handle_t                  h_cq;\r
2897 \r
2898         AL_ENTER( AL_DBG_CQ );\r
2899 \r
2900         /* Validate input buffers. */\r
2901         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2902                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2903                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2904         {\r
2905                 AL_EXIT( AL_DBG_CQ );\r
2906                 return CL_INVALID_PARAMETER;\r
2907         }\r
2908 \r
2909         /* Set the return bytes in all cases */\r
2910         *p_ret_bytes = sizeof(p_ioctl->out);\r
2911 \r
2912         /* Validate CQ handle */\r
2913         h_cq = (ib_cq_handle_t)\r
2914                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_cq, AL_OBJ_TYPE_H_CQ );\r
2915         if( !h_cq )\r
2916         {\r
2917                 p_ioctl->out.status = IB_INVALID_CQ_HANDLE;\r
2918                 AL_EXIT( AL_DBG_CQ );\r
2919                 return CL_SUCCESS;\r
2920         }\r
2921 \r
2922         p_ioctl->out.status = ib_rearm_n_cq( h_cq, p_ioctl->in.n_cqes );\r
2923 \r
2924         deref_al_obj( &h_cq->obj );\r
2925 \r
2926         AL_EXIT( AL_DBG_CQ );\r
2927         return CL_SUCCESS;\r
2928 }\r
2929 \r
2930 \r
2931 \r
2932 /*\r
2933  * Process the ioctl UAL_REGISTER_MEM:\r
2934  */\r
2935 static cl_status_t\r
2936 proxy_register_mr(\r
2937         IN              void                                    *p_open_context,\r
2938         IN              cl_ioctl_handle_t               h_ioctl,\r
2939                 OUT     size_t                                  *p_ret_bytes )\r
2940 {\r
2941         ual_reg_mem_ioctl_t             *p_ioctl =\r
2942                 (ual_reg_mem_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
2943         al_dev_open_context_t   *p_context =\r
2944                 (al_dev_open_context_t *)p_open_context;\r
2945         ib_pd_handle_t                  h_pd;\r
2946         ib_mr_handle_t                  h_mr;\r
2947         ib_api_status_t                 status;\r
2948 \r
2949         AL_ENTER( AL_DBG_MR );\r
2950 \r
2951         /* Validate input buffers. */\r
2952         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
2953                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
2954                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
2955         {\r
2956                 AL_EXIT( AL_DBG_MR );\r
2957                 return CL_INVALID_PARAMETER;\r
2958         }\r
2959 \r
2960         /* Validate PD handle */\r
2961         h_pd = (ib_pd_handle_t)\r
2962                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
2963         if( !h_pd )\r
2964         {\r
2965                 status = IB_INVALID_PD_HANDLE;\r
2966                 goto proxy_register_mr_err;\r
2967         }\r
2968 \r
2969         /* Validate input region size. */\r
2970         if( p_ioctl->in.mem_create.length > ~((size_t)0) )\r
2971         {\r
2972                 status = IB_INVALID_SETTING;\r
2973                 goto proxy_register_mr_err;\r
2974         }\r
2975 \r
2976         status = reg_mem( h_pd, &p_ioctl->in.mem_create, &p_ioctl->out.lkey,\r
2977                 &p_ioctl->out.rkey, &h_mr, TRUE );\r
2978 \r
2979         if( status == IB_SUCCESS )\r
2980         {\r
2981                 p_ioctl->out.h_mr = h_mr->obj.hdl;\r
2982                 h_mr->obj.hdl_valid = TRUE;\r
2983                 deref_al_obj( &h_mr->obj );\r
2984         }\r
2985         else\r
2986         {\r
2987 proxy_register_mr_err:\r
2988                 p_ioctl->out.h_mr = AL_INVALID_HANDLE;\r
2989                 p_ioctl->out.lkey = 0;\r
2990                 p_ioctl->out.rkey = 0;\r
2991         }\r
2992 \r
2993         if( h_pd )\r
2994                 deref_al_obj( &h_pd->obj );\r
2995 \r
2996         p_ioctl->out.status = status;\r
2997         *p_ret_bytes = sizeof(p_ioctl->out);\r
2998 \r
2999         AL_EXIT( AL_DBG_MR );\r
3000         return CL_SUCCESS;\r
3001 }\r
3002 \r
3003 \r
3004 \r
3005 /*\r
3006  * Process the ioctl UAL_QUERY_MEM:\r
3007  */\r
3008 static cl_status_t\r
3009 proxy_query_mr(\r
3010         IN              void                                    *p_open_context,\r
3011         IN              cl_ioctl_handle_t               h_ioctl,\r
3012         OUT             size_t                                  *p_ret_bytes )\r
3013 {\r
3014         ual_query_mr_ioctl_t    *p_ioctl =\r
3015                 (ual_query_mr_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
3016         al_dev_open_context_t   *p_context =\r
3017                 (al_dev_open_context_t *)p_open_context;\r
3018         ib_mr_handle_t                  h_mr;\r
3019         ib_api_status_t                 status;\r
3020 \r
3021         AL_ENTER( AL_DBG_MR );\r
3022 \r
3023         /* Validate input buffers. */\r
3024         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
3025                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
3026                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
3027         {\r
3028                 AL_EXIT( AL_DBG_MR );\r
3029                 return CL_INVALID_PARAMETER;\r
3030         }\r
3031 \r
3032         /* Validate MR handle */\r
3033         h_mr = (ib_mr_handle_t)\r
3034                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_mr, AL_OBJ_TYPE_H_MR );\r
3035         if( !h_mr )\r
3036         {\r
3037                 status = IB_INVALID_MR_HANDLE;\r
3038                 goto proxy_query_mr_err;\r
3039         }\r
3040 \r
3041         status = ib_query_mr( h_mr, &p_ioctl->out.attr );\r
3042 \r
3043         if( status == IB_SUCCESS )\r
3044         {\r
3045                 /* Replace the pd handle with proxy's handle */\r
3046                 p_ioctl->out.attr.h_pd =\r
3047                         (ib_pd_handle_t)HDL_TO_PTR(p_ioctl->out.attr.h_pd->obj.hdl);\r
3048         }\r
3049         else\r
3050         {\r
3051 proxy_query_mr_err:\r
3052                 cl_memclr( &p_ioctl->out.attr, sizeof(ib_mr_attr_t) );\r
3053         }\r
3054 \r
3055         if( h_mr )\r
3056                 deref_al_obj( &h_mr->obj );\r
3057 \r
3058         p_ioctl->out.status = status;\r
3059         *p_ret_bytes = sizeof(p_ioctl->out);\r
3060 \r
3061         AL_EXIT( AL_DBG_MR );\r
3062         return CL_SUCCESS;\r
3063 }\r
3064 \r
3065 \r
3066 \r
3067 /*\r
3068  * Process the ioctl UAL_MODIFY_MEM:\r
3069  */\r
3070 static cl_status_t\r
3071 proxy_modify_mr(\r
3072         IN              void                                    *p_open_context,\r
3073         IN              cl_ioctl_handle_t               h_ioctl,\r
3074                 OUT     size_t                                  *p_ret_bytes )\r
3075 {\r
3076         ual_rereg_mem_ioctl_t   *p_ioctl =\r
3077                 (ual_rereg_mem_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
3078         al_dev_open_context_t   *p_context =\r
3079                 (al_dev_open_context_t *)p_open_context;\r
3080         ib_mr_handle_t                  h_mr;\r
3081         ib_pd_handle_t                  h_pd = NULL;\r
3082         ib_mr_create_t                  *p_mr_create;\r
3083         ib_api_status_t                 status;\r
3084 \r
3085         AL_ENTER( AL_DBG_MR );\r
3086 \r
3087         /* Validate input buffers. */\r
3088         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
3089                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
3090                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
3091         {\r
3092                 AL_EXIT( AL_DBG_MR );\r
3093                 return CL_INVALID_PARAMETER;\r
3094         }\r
3095 \r
3096         /* Validate MR handle */\r
3097         h_mr = (ib_mr_handle_t)\r
3098                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_mr, AL_OBJ_TYPE_H_MR );\r
3099         if( !h_mr )\r
3100         {\r
3101                 status = IB_INVALID_MR_HANDLE;\r
3102                 goto proxy_modify_mr_err;\r
3103         }\r
3104 \r
3105         /* Validate input region size. */\r
3106         if( p_ioctl->in.mem_create.length > ~((size_t)0) )\r
3107         {\r
3108                 status = IB_INVALID_SETTING;\r
3109                 goto proxy_modify_mr_err;\r
3110         }\r
3111 \r
3112         if( p_ioctl->in.mem_mod_mask & IB_MR_MOD_PD )\r
3113         {\r
3114                 if( !p_ioctl->in.h_pd )\r
3115                 {\r
3116                         status = IB_INVALID_PD_HANDLE;\r
3117                         goto proxy_modify_mr_err;\r
3118                 }\r
3119                 /* This is a modify PD request, validate the PD handle */\r
3120                 h_pd = (ib_pd_handle_t)\r
3121                         al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
3122                 if( !h_pd )\r
3123                 {\r
3124                         status = IB_INVALID_PD_HANDLE;\r
3125                         goto proxy_modify_mr_err;\r
3126                 }\r
3127         }\r
3128         else\r
3129         {\r
3130                 h_pd = NULL;\r
3131         }\r
3132 \r
3133         if( p_ioctl->in.mem_mod_mask != IB_MR_MOD_PD )\r
3134                 p_mr_create = &p_ioctl->in.mem_create;\r
3135         else\r
3136                 p_mr_create = NULL;\r
3137 \r
3138         status = rereg_mem( h_mr, p_ioctl->in.mem_mod_mask,\r
3139                 p_mr_create, &p_ioctl->out.lkey, &p_ioctl->out.rkey, h_pd, TRUE );\r
3140 \r
3141         if( status != IB_SUCCESS )\r
3142         {\r
3143 proxy_modify_mr_err:\r
3144                 p_ioctl->out.lkey = 0;\r
3145                 p_ioctl->out.rkey = 0;\r
3146         }\r
3147 \r
3148         if( h_pd )\r
3149                 deref_al_obj( &h_pd->obj );\r
3150 \r
3151         if( h_mr )\r
3152                 deref_al_obj( &h_mr->obj );\r
3153 \r
3154         p_ioctl->out.status = status;\r
3155         *p_ret_bytes = sizeof(p_ioctl->out);\r
3156 \r
3157         AL_EXIT( AL_DBG_MR );\r
3158         return CL_SUCCESS;\r
3159 }\r
3160 \r
3161 \r
3162 \r
3163 /*\r
3164  * Process the ioctl UAL_REG_SHARED_MEM:\r
3165  */\r
3166 static cl_status_t\r
3167 proxy_shared_mr(\r
3168         IN              void                                    *p_open_context,\r
3169         IN              cl_ioctl_handle_t               h_ioctl,\r
3170                 OUT     size_t                                  *p_ret_bytes )\r
3171 {\r
3172         ual_reg_shared_ioctl_t  *p_ioctl =\r
3173                 (ual_reg_shared_ioctl_t *)cl_ioctl_in_buf( h_ioctl );\r
3174         al_dev_open_context_t   *p_context =\r
3175                 (al_dev_open_context_t *)p_open_context;\r
3176         ib_pd_handle_t                  h_pd;\r
3177         ib_mr_handle_t                  h_mr, h_cur_mr;\r
3178         ib_api_status_t                 status;\r
3179         uint64_t                                vaddr;\r
3180 \r
3181         AL_ENTER( AL_DBG_MR );\r
3182 \r
3183         /* Validate input buffers. */\r
3184         if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) ||\r
3185                 cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) ||\r
3186                 cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) )\r
3187         {\r
3188                 AL_EXIT( AL_DBG_MR );\r
3189                 return CL_INVALID_PARAMETER;\r
3190         }\r
3191 \r
3192         /*\r
3193          * TODO: Must support taking an input handle that isn't\r
3194          * in this process's context.\r
3195          */\r
3196         /* Validate MR handle */\r
3197         h_cur_mr = (ib_mr_handle_t)\r
3198                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_mr, AL_OBJ_TYPE_H_MR );\r
3199         if( !h_cur_mr )\r
3200         {\r
3201                 h_pd = NULL;\r
3202                 status = IB_INVALID_MR_HANDLE;\r
3203                 goto proxy_shared_mr_err;\r
3204         }\r
3205 \r
3206         /* Validate the PD handle */\r
3207         h_pd = (ib_pd_handle_t)\r
3208                 al_hdl_ref( p_context->h_al, p_ioctl->in.h_pd, AL_OBJ_TYPE_H_PD );\r
3209         if( !h_pd )\r
3210         {\r
3211                 status = IB_INVALID_PD_HANDLE;\r
3212                 goto proxy_shared_mr_err;\r
3213         }\r
3214 \r
3215         vaddr = p_ioctl->in.vaddr;\r
3216         status = reg_shared( h_cur_mr, h_pd,\r
3217                 p_ioctl->in.access_ctrl, &vaddr, &p_ioctl->out.lkey,\r
3218                 &p_ioctl->out.rkey, &h_mr, TRUE );\r
3219 \r
3220         if( status == IB_SUCCESS )\r
3221         {\r
3222                 p_ioctl->out.h_new_mr = h_mr->obj.hdl;\r
3223                 p_ioctl->out.vaddr = vaddr;\r
3224                 h_mr->obj.hdl_valid = TRUE;\r
3225                 deref_al_obj( &h_mr->obj );\r
3226         }\r
3227         else\r
3228         {\r
3229 proxy_shared_mr_err:\r
3230                 cl_memclr( &p_ioctl->out, sizeof(p_ioctl->out) );\r
3231         }\r
3232 \r
3233         if( h_pd )\r
3234                 deref_al_obj( &h_pd->obj );\r
3235 \r
3236         if( h_cur_mr )\r
3237                 deref_al_obj( &h_cur_mr->obj );\r
3238 \r
3239         p_ioctl->out.status = status;\r
3240         *p_ret_bytes = sizeof(p_ioctl->out);\r
3241 \r
3242         AL_EXIT( AL_DBG_MR );\r
3243         return CL_SUCCESS;\r
3244 }\r
3245 \r
3246 \r
3247 \r
3248 /*\r
3249  * Process the ioctl UAL_DEREGISTER_MEM:\r
3250  */\r