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