2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
3 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
\r
5 * This software is available to you under the OpenIB.org BSD license
\r
8 * Redistribution and use in source and binary forms, with or
\r
9 * without modification, are permitted provided that the following
\r
10 * conditions are met:
\r
12 * - Redistributions of source code must retain the above
\r
13 * copyright notice, this list of conditions and the following
\r
16 * - Redistributions in binary form must reproduce the above
\r
17 * copyright notice, this list of conditions and the following
\r
18 * disclaimer in the documentation and/or other materials
\r
19 * provided with the distribution.
\r
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
33 #include <iba/ib_al.h>
\r
35 #include "al_cm_shared.h"
\r
36 #include "al_debug.h"
\r
38 #if defined(EVENT_TRACING)
\r
42 #include "ual_cm.tmh"
\r
47 #include "ib_common.h"
\r
53 * Attach the QP and connection object to each other.
\r
57 IN const ib_cm_handle_t h_conn,
\r
58 IN const ib_qp_handle_t h_qp )
\r
60 h_conn->h_qp = h_qp;
\r
61 ((al_conn_qp_t*)h_qp)->p_conn = h_conn;
\r
67 IN struct _al_obj *p_obj )
\r
69 destroy_al_obj( p_obj );
\r
77 IN struct _al_obj *p_obj )
\r
79 ib_cm_handle_t h_conn;
\r
81 h_conn = (ib_cm_handle_t)p_obj;
\r
87 /* Unbind the QP and connection from each other. */
\r
88 ((al_conn_qp_t*)h_conn->h_qp)->p_conn = NULL;
\r
89 h_conn->h_qp = NULL;
\r
92 /* Remove the connection object from AL's list. */
\r
93 al_remove_conn( h_conn );
\r
101 IN const ib_cm_handle_t h_conn )
\r
103 if( !h_conn->p_conn_req )
\r
106 cl_free( h_conn->p_conn_req );
\r
107 h_conn->p_conn_req = NULL;
\r
114 IN struct _al_obj *p_obj )
\r
116 ib_cm_handle_t h_conn;
\r
118 h_conn = (ib_cm_handle_t)p_obj;
\r
120 /* Release all memory used to store the connection information. */
\r
121 __free_conn_req( h_conn );
\r
122 destroy_al_obj( p_obj );
\r
129 IN al_conn_t* const p_conn,
\r
130 IN const ib_rej_status_t reason )
\r
132 ib_cm_rej_t rej = {0};
\r
134 rej.rej_status = reason;
\r
136 ib_cm_rej( p_conn, &rej );
\r
141 * Called by the QP upon destruction if still connected.
\r
145 IN al_conn_qp_t * const p_conn_qp )
\r
147 UNUSED_PARAM( p_conn_qp );
\r
153 * Called by AL to destroy connection objects that were not destroyed
\r
154 * properly. In theory, this function should not be called, unless the
\r
155 * application using AL is not written properly.
\r
159 IN const ib_cm_handle_t h_conn )
\r
161 /* Just destroy the connection object. */
\r
162 ref_al_obj( &h_conn->obj );
\r
163 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
169 * Allocate and initialize a structure to store CM information.
\r
171 static ib_listen_handle_t
\r
173 IN const ib_al_handle_t h_al )
\r
175 ib_listen_handle_t h_listen;
\r
176 ib_api_status_t status;
\r
178 /* Allocate the structure. */
\r
179 h_listen = cl_zalloc( sizeof( al_listen_t ) );
\r
183 /* Initialize the al object portion. */
\r
184 construct_al_obj( &h_listen->obj, AL_OBJ_TYPE_H_LISTEN );
\r
185 status = init_al_obj( &h_listen->obj, h_listen, TRUE,
\r
186 NULL, NULL, __free_listen );
\r
187 if( status != IB_SUCCESS )
\r
189 cl_free( h_listen );
\r
193 /* The CM info structure is a child of AL. */
\r
194 attach_al_obj( &h_al->obj, &h_listen->obj );
\r
201 static ib_cm_handle_t
\r
203 IN const ib_al_handle_t h_al )
\r
205 ib_cm_handle_t h_conn;
\r
206 ib_api_status_t status;
\r
208 /* Allocate the structure. */
\r
209 h_conn = cl_zalloc( sizeof( al_conn_t ) );
\r
213 /* Allocate resources to establish the connection. */
\r
214 h_conn->p_conn_req = cl_zalloc( sizeof( conn_req_t ) );
\r
215 if( !h_conn->p_conn_req )
\r
217 __free_conn( &h_conn->obj );
\r
221 /* Initialize the al object portion. */
\r
222 construct_al_obj( &h_conn->obj, AL_OBJ_TYPE_H_CONN );
\r
223 status = init_al_obj( &h_conn->obj, h_conn, TRUE,
\r
224 __destroying_conn, NULL, __free_conn );
\r
225 if( status != IB_SUCCESS )
\r
227 __free_conn( &h_conn->obj );
\r
231 al_insert_conn( h_al, h_conn );
\r
238 * Reject a connection request.
\r
242 IN const ib_cm_handle_t h_cm,
\r
243 IN ib_rej_status_t rej_status )
\r
245 ib_cm_rej_t cm_rej;
\r
247 cl_memclr( &cm_rej, sizeof( ib_cm_rej_t ) );
\r
248 cm_rej.rej_status = rej_status;
\r
249 ib_cm_rej( h_cm, &cm_rej );
\r
255 * Initiate a listen for a connection request.
\r
259 IN const ib_al_handle_t h_al,
\r
260 IN const ib_cm_listen_t* const p_cm_listen,
\r
261 IN const ib_pfn_listen_err_cb_t pfn_listen_err_cb,
\r
262 IN const void* const listen_context,
\r
263 OUT ib_listen_handle_t* const ph_cm_listen )
\r
265 ual_cm_listen_ioctl_t *p_cm_ioctl;
\r
266 size_t ioctl_buf_sz;
\r
268 ib_api_status_t status;
\r
269 cl_status_t cl_status;
\r
270 ib_listen_handle_t h_listen;
\r
272 AL_ENTER( AL_DBG_CM );
\r
274 /* Validate input parameters. */
\r
275 if( AL_OBJ_INVALID_HANDLE( h_al, AL_OBJ_TYPE_H_AL ) )
\r
277 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Invalid AL handle.\n") );
\r
278 return IB_INVALID_AL_HANDLE;
\r
280 if( !p_cm_listen || !ph_cm_listen )
\r
282 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("NULL parameter.\n") );
\r
283 return IB_INVALID_PARAMETER;
\r
286 /* Get a listen structure. */
\r
287 h_listen = __get_listen( h_al );
\r
290 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
291 ("Failed to allocate listen structure.\n") );
\r
292 return IB_INSUFFICIENT_MEMORY;
\r
295 /* Save the user's information. */
\r
296 h_listen->pfn_cm_req_cb = p_cm_listen->pfn_cm_req_cb;
\r
297 h_listen->pfn_cm_mra_cb = p_cm_listen->pfn_cm_mra_cb;
\r
298 h_listen->pfn_cm_rej_cb = p_cm_listen->pfn_cm_rej_cb;
\r
299 h_listen->pfn_listen_err_cb = pfn_listen_err_cb;
\r
300 h_listen->obj.context = listen_context;
\r
301 h_listen->sidr_context = p_cm_listen->sidr_context;
\r
303 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
304 if( p_cm_listen->p_compare_buffer )
\r
305 ioctl_buf_sz += p_cm_listen->compare_length;
\r
307 p_cm_ioctl = (ual_cm_listen_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
310 h_listen->obj.pfn_destroy( &h_listen->obj, NULL );
\r
311 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate IOCTL buffer.\n") );
\r
312 return IB_INSUFFICIENT_MEMORY;
\r
315 /* Initialize the IOCTL. */
\r
316 p_cm_ioctl->in.context = h_listen;
\r
317 p_cm_ioctl->in.cm_listen = *p_cm_listen;
\r
318 /* Convert the user's information to ALs. */
\r
319 p_cm_ioctl->in.cm_listen.sidr_context = h_listen;
\r
320 if( p_cm_listen->p_compare_buffer )
\r
322 cl_memcpy( (uint8_t*)((&p_cm_ioctl->in.cm_listen) + 1),
\r
323 p_cm_listen->p_compare_buffer, p_cm_listen->compare_length );
\r
326 /* Call the kernel CM to do the listen. */
\r
327 cl_status = do_al_dev_ioctl( UAL_CM_LISTEN, &p_cm_ioctl->in, ioctl_buf_sz,
\r
328 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out), &bytes_ret );
\r
330 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
332 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
333 ("UAL_CM_LISTEN IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
338 status = p_cm_ioctl->out.status;
\r
341 if( status != IB_SUCCESS )
\r
343 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
344 ("Failed to listen: %s.\n", ib_get_err_str(status) ) );
\r
345 h_listen->obj.pfn_destroy( &h_listen->obj, NULL );
\r
349 h_listen->obj.hdl = p_cm_ioctl->out.h_cm_listen;
\r
350 *ph_cm_listen = h_listen;
\r
352 /* Release the reference taken in init_al_obj (__get_listen). */
\r
353 deref_al_obj( &h_listen->obj );
\r
356 cl_free( p_cm_ioctl );
\r
357 AL_EXIT( AL_DBG_CM );
\r
365 IN const ib_listen_handle_t h_cm_listen,
\r
366 IN const ib_pfn_destroy_cb_t pfn_destroy_cb OPTIONAL )
\r
368 ual_cm_cancel_ioctl_t cm_ioctl;
\r
370 ib_api_status_t status;
\r
371 cl_status_t cl_status;
\r
373 AL_ENTER( AL_DBG_CM );
\r
375 if( AL_OBJ_INVALID_HANDLE( h_cm_listen, AL_OBJ_TYPE_H_LISTEN ) )
\r
377 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid listen handle.\n") );
\r
378 return IB_INVALID_HANDLE;
\r
381 /* Take a reference on the listen until the IOCTL completes. */
\r
382 ref_al_obj( &h_cm_listen->obj );
\r
384 /* Initialize the IOCTL. */
\r
385 cl_memclr( &cm_ioctl, sizeof( cm_ioctl ) );
\r
386 cm_ioctl.in.h_cm_listen = h_cm_listen->obj.hdl;
\r
388 /* Call the kernel CM to do the cancel. */
\r
389 cl_status = do_al_dev_ioctl( UAL_CM_CANCEL, &cm_ioctl.in,
\r
390 sizeof(cm_ioctl.in), &cm_ioctl.out, sizeof(cm_ioctl.out), &bytes_ret );
\r
392 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(cm_ioctl.out) )
\r
394 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
395 ("UAL_CM_CANCEL IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
400 status = cm_ioctl.out.status;
\r
402 if( status != IB_SUCCESS )
\r
404 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
405 ("Failed to cancel: %s.\n", ib_get_err_str(status) ) );
\r
406 deref_al_obj( &h_cm_listen->obj );
\r
410 h_cm_listen->obj.pfn_destroy( &h_cm_listen->obj, pfn_destroy_cb );
\r
413 AL_EXIT( AL_DBG_CM );
\r
420 * Initiate a connection request.
\r
424 IN const ib_cm_req_t* const p_cm_req )
\r
426 ib_cm_handle_t h_conn;
\r
427 ual_cm_req_ioctl_t *p_cm_ioctl;
\r
428 size_t ioctl_buf_sz;
\r
431 ib_api_status_t status;
\r
432 cl_status_t cl_status;
\r
434 AL_ENTER( AL_DBG_CM );
\r
436 /* Validate input parameters. */
\r
437 if( !p_cm_req || !p_cm_req->p_primary_path )
\r
439 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
440 ("NULL p_cm_req or primary path\n") );
\r
441 return IB_INVALID_PARAMETER;
\r
444 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
445 if( p_cm_req->p_compare_buffer )
\r
446 ioctl_buf_sz += p_cm_req->compare_length;
\r
447 if( p_cm_req->p_req_pdata )
\r
448 ioctl_buf_sz += p_cm_req->req_length;
\r
449 if( p_cm_req->p_alt_path )
\r
450 ioctl_buf_sz += sizeof(ib_path_rec_t);
\r
452 p_cm_ioctl = (ual_cm_req_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
455 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
456 ("Failed to allocate IOCTL buf.\n") );
\r
457 return IB_INSUFFICIENT_MEMORY;
\r
461 * Save the user's information and replace the handles with appropriate
\r
464 p_cm_ioctl->in.cm_req = *p_cm_req;
\r
465 switch( p_cm_req->qp_type )
\r
467 case IB_QPT_RELIABLE_CONN:
\r
468 case IB_QPT_UNRELIABLE_CONN:
\r
469 if( AL_OBJ_INVALID_HANDLE( p_cm_req->h_qp, AL_OBJ_TYPE_H_QP ) ||
\r
470 (p_cm_req->h_qp->type != p_cm_req->qp_type) )
\r
472 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
473 ("IB_INVALID_QP_HANDLE\n") );
\r
474 status = IB_INVALID_QP_HANDLE;
\r
478 /* Update the QP destroy timeout = timeout x retries + 2 seconds. */
\r
479 set_al_obj_timeout( &p_cm_req->h_qp->obj,
\r
480 p_cm_req->timeout_ms * p_cm_req->max_cm_retries + 2000 );
\r
482 /* Get a connection structure. */
\r
483 h_conn = __get_conn( (ib_al_handle_t)
\r
484 p_cm_req->h_qp->obj.p_parent_obj->p_parent_obj->p_parent_obj );
\r
487 AL_PRINT(TRACE_LEVEL_ERROR , AL_DBG_ERROR ,
\r
488 ("Failed to allocate connection structure.\n") );
\r
489 status = IB_INSUFFICIENT_MEMORY;
\r
493 __bind_qp_and_conn( h_conn, p_cm_req->h_qp );
\r
494 p_cm_ioctl->in.h_qp = p_cm_req->h_qp->obj.hdl;
\r
496 /* Record the connection information for QP transitions. */
\r
497 h_conn->p_conn_req->path_rec = *p_cm_req->p_primary_path;
\r
498 if( p_cm_req->p_alt_path )
\r
499 h_conn->p_conn_req->alt_path_rec = *p_cm_req->p_alt_path;
\r
501 /* Transition the QP to the init state to allow posting receives. */
\r
502 status = cm_init_qp( h_conn->h_qp, &p_cm_req->p_primary_path->sgid,
\r
503 p_cm_req->p_primary_path->pkey,
\r
504 (IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE | IB_AC_MW_BIND) );
\r
505 //h_conn->p_req_info->qp_mod_rts.state.rts.access_ctrl );
\r
506 if( status != IB_SUCCESS )
\r
508 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
509 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
510 ("cm_init_qp returned %s\n", ib_get_err_str(status)) );
\r
515 case IB_QPT_UNRELIABLE_DGRM:
\r
516 if( AL_OBJ_INVALID_HANDLE( p_cm_req->h_al, AL_OBJ_TYPE_H_AL ) )
\r
518 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
519 ("IB_INVALID_AL_HANDLE\n") );
\r
520 status = IB_INVALID_AL_HANDLE;
\r
523 /* Get a connection structure. */
\r
524 h_conn = __get_conn( p_cm_req->h_al );
\r
527 AL_PRINT(TRACE_LEVEL_ERROR , AL_DBG_ERROR ,
\r
528 ("Failed to allocate connection structure.\n") );
\r
529 status = IB_INSUFFICIENT_MEMORY;
\r
532 p_cm_ioctl->in.cm_req.h_al = NULL;
\r
533 h_conn->sidr_context = p_cm_req->sidr_context;
\r
534 p_cm_ioctl->in.cm_req.sidr_context = h_conn;
\r
538 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
539 status = IB_INVALID_SETTING;
\r
543 h_conn->p_conn_req->pfn_cm_req_cb = p_cm_req->pfn_cm_req_cb;
\r
544 h_conn->p_conn_req->pfn_cm_rep_cb = p_cm_req->pfn_cm_rep_cb;
\r
545 h_conn->pfn_cm_mra_cb = p_cm_req->pfn_cm_mra_cb;
\r
546 h_conn->pfn_cm_rej_cb = p_cm_req->pfn_cm_rej_cb;
\r
548 p_cm_ioctl->in.paths[0] = *p_cm_req->p_primary_path;
\r
549 p_data = (uint8_t*)&p_cm_ioctl->in.paths[1];
\r
550 if( p_cm_req->p_alt_path )
\r
552 p_cm_ioctl->in.paths[1] = *p_cm_req->p_alt_path;
\r
553 p_data += sizeof(ib_path_rec_t);
\r
555 if( p_cm_req->req_length )
\r
557 cl_memcpy( p_data, p_cm_req->p_req_pdata, p_cm_req->req_length );
\r
558 p_data += p_cm_req->req_length;
\r
560 if( p_cm_req->compare_length )
\r
562 cl_memcpy( p_data, p_cm_req->p_compare_buffer,
\r
563 p_cm_req->compare_length );
\r
566 cl_status = do_al_dev_ioctl( UAL_CM_REQ, &p_cm_ioctl->in, ioctl_buf_sz,
\r
567 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out), &bytes_ret );
\r
569 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
571 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
572 ("UAL_CM_REQ IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
577 status = p_cm_ioctl->out.status;
\r
580 if( status != IB_SUCCESS )
\r
582 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
583 ("Connection request ioctl failed with status (%s)\n",
\r
584 ib_get_err_str(status) ) );
\r
585 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
589 /* Release the reference taken in init_al_obj (__get_conn). */
\r
590 deref_al_obj( &h_conn->obj );
\r
594 cl_free( p_cm_ioctl );
\r
595 AL_EXIT( AL_DBG_CM );
\r
601 static ib_api_status_t
\r
603 IN const ib_cm_handle_t h_conn,
\r
604 IN const ib_cm_rep_t* const p_cm_rep )
\r
606 ib_port_attr_t *p_port_attr;
\r
607 ib_qp_handle_t h_qp;
\r
609 AL_ENTER(AL_DBG_CM);
\r
611 __bind_qp_and_conn( h_conn, p_cm_rep->h_qp );
\r
612 h_qp = p_cm_rep->h_qp;
\r
614 /* Get the port attributes. */
\r
615 ci_ca_lock_attr( h_qp->obj.p_ci_ca );
\r
616 p_port_attr = get_port_attr( h_qp->obj.p_ci_ca->p_pnp_attr,
\r
617 &h_conn->p_conn_req->path_rec.sgid );
\r
620 ci_ca_unlock_attr( h_qp->obj.p_ci_ca );
\r
621 AL_PRINT(TRACE_LEVEL_ERROR , AL_DBG_ERROR , ("invalid p_gid\n" ) );
\r
622 return IB_INVALID_GID;
\r
625 cm_save_rep_qp_attr( p_cm_rep, p_port_attr, &h_conn->p_conn_req->path_rec,
\r
626 &h_conn->p_conn_req->alt_path_rec, &h_conn->p_conn_req->qp_mod_rtr,
\r
627 &h_conn->p_conn_req->qp_mod_rts );
\r
628 ci_ca_unlock_attr( h_qp->obj.p_ci_ca );
\r
630 AL_EXIT(AL_DBG_CM);
\r
638 IN const ib_cm_handle_t h_cm_req,
\r
639 IN const ib_cm_rep_t* const p_cm_rep )
\r
641 ib_cm_handle_t h_conn;
\r
642 ual_cm_rep_ioctl_t *p_cm_ioctl;
\r
643 size_t ioctl_buf_sz;
\r
645 ib_api_status_t status;
\r
646 cl_status_t cl_status;
\r
648 AL_ENTER(AL_DBG_CM);
\r
650 /* Validate input parameters. */
\r
652 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
654 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid REQ handle.\n") );
\r
655 return IB_INVALID_HANDLE;
\r
659 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_rep\n") );
\r
660 return IB_INVALID_PARAMETER;
\r
663 /* Save the user's information. */
\r
664 h_conn->p_conn_req->pfn_cm_rtu_cb = p_cm_rep->pfn_cm_rtu_cb;
\r
665 h_conn->pfn_cm_lap_cb = p_cm_rep->pfn_cm_lap_cb;
\r
666 h_conn->pfn_cm_dreq_cb = p_cm_rep->pfn_cm_dreq_cb;
\r
668 /* Calculate the size of the IOCTL buffer needed. */
\r
669 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
670 if( p_cm_rep->p_rep_pdata )
\r
671 ioctl_buf_sz += p_cm_rep->rep_length;
\r
673 /* Allocate the IOCTL buffer. */
\r
674 p_cm_ioctl = (ual_cm_rep_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
677 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate IOCTL buffer.\n") );
\r
678 return IB_INSUFFICIENT_MEMORY;
\r
681 /* Replace the handles with appropriate kernel handles. */
\r
682 p_cm_ioctl->in.cm_rep = *p_cm_rep;
\r
683 if( AL_OBJ_INVALID_HANDLE( p_cm_rep->h_qp, AL_OBJ_TYPE_H_QP ) ||
\r
684 p_cm_rep->h_qp->type != p_cm_rep->qp_type )
\r
686 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
687 ("Invalid QP handle.\n") );
\r
688 status = IB_INVALID_QP_HANDLE;
\r
691 p_cm_ioctl->in.h_qp = p_cm_rep->h_qp->obj.hdl;
\r
693 /* Update the QP destruction timeout, use value provided by kernel CM. */
\r
694 set_al_obj_timeout( &p_cm_rep->h_qp->obj, h_conn->p_conn_req->timeout_ms );
\r
696 status = __save_user_rep( h_conn, p_cm_rep );
\r
697 if( status != IB_SUCCESS )
\r
699 __ual_conn_reject( h_conn, IB_REJ_INSUF_QP );
\r
700 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
701 ("__save_user_rep returned %s\n", ib_get_err_str(status) ) );
\r
705 /* Transition the QP to the init state to allow posting receives. */
\r
706 status = cm_init_qp( p_cm_rep->h_qp, &h_conn->p_conn_req->path_rec.sgid,
\r
707 h_conn->p_conn_req->path_rec.pkey, p_cm_rep->access_ctrl );
\r
708 if( status != IB_SUCCESS )
\r
710 __ual_conn_reject( h_conn, IB_REJ_INSUF_QP );
\r
711 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
712 ("cm_init_qp returned %s\n", ib_get_err_str(status) ) );
\r
716 /* Prepost receives. */
\r
717 if( p_cm_rep->p_recv_wr )
\r
719 status = ib_post_recv( p_cm_rep->h_qp, p_cm_rep->p_recv_wr,
\r
720 p_cm_rep->pp_recv_failure );
\r
721 if( status != IB_SUCCESS )
\r
723 __ual_conn_reject( h_conn, IB_REJ_INSUF_QP );
\r
724 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
725 ("ib_post_recv returned %s.\n", ib_get_err_str(status)) );
\r
729 p_cm_ioctl->in.cm_rep.p_recv_wr = NULL;
\r
731 /* Transition the QP to the RTS state. */
\r
732 status = cm_rts_qp( h_conn->h_qp, &h_conn->p_conn_req->qp_mod_rtr,
\r
733 &h_conn->p_conn_req->qp_mod_rts );
\r
734 if( status != IB_SUCCESS )
\r
736 __ual_conn_reject( h_conn, IB_REJ_INSUF_QP );
\r
737 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
738 ("cm_rts_qp with status (%s)\n", ib_get_err_str(status) ) );
\r
742 p_cm_ioctl->in.h_cm_req = h_conn->obj.hdl;
\r
743 /* Copy the private data. */
\r
744 if( p_cm_rep->p_rep_pdata )
\r
746 cl_memcpy( (&p_cm_ioctl->in.cm_rep) + 1,
\r
747 p_cm_rep->p_rep_pdata, p_cm_rep->rep_length );
\r
750 cl_status = do_al_dev_ioctl( UAL_CM_REP,
\r
751 &p_cm_ioctl->in, ioctl_buf_sz,
\r
752 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out),
\r
755 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
757 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
758 ("UAL_CM_REP IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
763 status = p_cm_ioctl->out.status;
\r
766 if( status != IB_SUCCESS )
\r
768 AL_PRINT(TRACE_LEVEL_ERROR , AL_DBG_ERROR ,
\r
769 ("Connection reply ioctl failed with status (%s)\n",
\r
770 ib_get_err_str(status) ) );
\r
771 cm_reset_qp( h_conn->h_qp, 0 );
\r
772 ref_al_obj( &h_conn->obj );
\r
773 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
777 cl_free( p_cm_ioctl );
\r
778 AL_EXIT( AL_DBG_CM );
\r
786 IN const ib_cm_handle_t h_cm_rep,
\r
787 IN const ib_cm_rtu_t* const p_cm_rtu )
\r
789 ib_cm_handle_t h_conn;
\r
790 ual_cm_rtu_ioctl_t *p_cm_ioctl;
\r
791 size_t ioctl_buf_sz;
\r
793 ib_api_status_t status;
\r
794 cl_status_t cl_status;
\r
796 AL_ENTER(AL_DBG_CM);
\r
798 /* Validate input parameters. */
\r
800 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
802 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid rep handle.\n") );
\r
803 return IB_INVALID_HANDLE;
\r
807 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_rtu\n") );
\r
808 return IB_INVALID_PARAMETER;
\r
811 /* Save the user's information. */
\r
812 h_conn->pfn_cm_apr_cb = p_cm_rtu->pfn_cm_apr_cb;
\r
813 h_conn->pfn_cm_dreq_cb = p_cm_rtu->pfn_cm_dreq_cb;
\r
814 cm_save_rtu_qp_attr( p_cm_rtu, &h_conn->p_conn_req->qp_mod_rtr );
\r
816 /* Transition the QP to the RTS state. */
\r
817 status = cm_rts_qp( h_conn->h_qp, &h_conn->p_conn_req->qp_mod_rtr,
\r
818 &h_conn->p_conn_req->qp_mod_rts );
\r
819 if( status != IB_SUCCESS )
\r
821 __ual_conn_reject( h_conn, IB_REJ_INSUF_QP );
\r
822 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
823 ("cm_rts_qp with status (%s)\n", ib_get_err_str(status) ) );
\r
828 * We are done with this connection establishment. After we send the
\r
829 * RTU, the user can disconnect the QP, destroy it, close AL, or do
\r
830 * one of any number of difficult things to deal with, so we destroy
\r
831 * the connection request structure here to avoid possible duplicate
\r
834 __free_conn_req( h_conn );
\r
836 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
837 if( p_cm_rtu->p_rtu_pdata )
\r
838 ioctl_buf_sz += p_cm_rtu->rtu_length;
\r
840 p_cm_ioctl = (ual_cm_rtu_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
843 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate IOCTL buffer\n") );
\r
844 return IB_INSUFFICIENT_MEMORY;
\r
847 p_cm_ioctl->in.h_cm_rep = h_conn->obj.hdl;
\r
848 p_cm_ioctl->in.cm_rtu = *p_cm_rtu;
\r
849 if( p_cm_rtu->p_rtu_pdata )
\r
851 cl_memcpy( (&p_cm_ioctl->in.cm_rtu) + 1,
\r
852 p_cm_rtu->p_rtu_pdata, p_cm_rtu->rtu_length );
\r
855 cl_status = do_al_dev_ioctl( UAL_CM_RTU,
\r
856 &p_cm_ioctl->in, ioctl_buf_sz,
\r
857 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out),
\r
860 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
862 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
863 ("UAL_CM_RTU IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
868 status = p_cm_ioctl->out.status;
\r
871 if( IB_SUCCESS != status )
\r
873 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
874 ("IOCTL status %s.\n", ib_get_err_str(status)) );
\r
875 ref_al_obj( &h_conn->obj );
\r
876 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
879 cl_free( p_cm_ioctl );
\r
880 AL_EXIT( AL_DBG_CM );
\r
888 IN const ib_cm_handle_t h_cm_req,
\r
889 IN const ib_net64_t svc_id )
\r
891 ib_cm_handle_t h_conn;
\r
892 ual_cm_handoff_ioctl_t cm_ioctl;
\r
894 cl_status_t cl_status;
\r
896 AL_ENTER( AL_DBG_CM );
\r
898 /* Validate input parameters. */
\r
900 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
902 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Invalid REQ handle.\n") );
\r
903 return IB_INVALID_HANDLE;
\r
907 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("0 svc_id\n" ) );
\r
908 return IB_INVALID_PARAMETER;
\r
911 cl_memclr( &cm_ioctl, sizeof(ual_cm_rej_ioctl_t) );
\r
913 cm_ioctl.in.h_cm = h_conn->obj.hdl;
\r
914 CL_ASSERT( cm_ioctl.in.h_cm );
\r
915 cm_ioctl.in.sid = svc_id;
\r
917 cl_status = do_al_dev_ioctl( UAL_CM_HANDOFF,
\r
918 &cm_ioctl.in, sizeof(cm_ioctl.in), &cm_ioctl.out, sizeof(cm_ioctl.out),
\r
921 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(cm_ioctl.out) )
\r
923 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
924 ("UAL_CM_HANDOFF IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
927 else if( cm_ioctl.out.status != IB_SUCCESS )
\r
929 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
930 ("IOCTL status %s\n", ib_get_err_str(cm_ioctl.out.status)) );
\r
933 /* Move the QP (if any) to the error state. */
\r
935 cm_reset_qp( h_conn->h_qp, 0 );
\r
937 AL_EXIT( AL_DBG_CM );
\r
938 return cm_ioctl.out.status;
\r
945 IN const ib_cm_handle_t h_cm,
\r
946 IN const ib_cm_rej_t* const p_cm_rej )
\r
948 ib_cm_handle_t h_conn;
\r
949 ual_cm_rej_ioctl_t *p_cm_ioctl;
\r
950 size_t ioctl_buf_sz;
\r
953 ib_api_status_t status;
\r
954 cl_status_t cl_status;
\r
956 AL_ENTER(AL_DBG_CM);
\r
958 /* Validate input parameters. */
\r
960 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
962 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid REJ handle.\n") );
\r
963 return IB_INVALID_HANDLE;
\r
967 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_rej\n") );
\r
968 return IB_INVALID_PARAMETER;
\r
971 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
972 if( p_cm_rej->p_ari )
\r
973 ioctl_buf_sz += p_cm_rej->ari_length;
\r
974 if( p_cm_rej->p_rej_pdata )
\r
975 ioctl_buf_sz += p_cm_rej->rej_length;
\r
977 p_cm_ioctl = (ual_cm_rej_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
980 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
981 ("Failed to allocate IOCTL buffer.\n") );
\r
982 return IB_INSUFFICIENT_MEMORY;
\r
985 p_cm_ioctl->in.h_cm = h_conn->obj.hdl;
\r
986 CL_ASSERT( p_cm_ioctl->in.h_cm );
\r
987 p_cm_ioctl->in.cm_rej = *p_cm_rej;
\r
988 p_data = (uint8_t*)((&p_cm_ioctl->in.cm_rej) + 1);
\r
989 if( p_cm_rej->p_ari )
\r
991 cl_memcpy( p_data, p_cm_rej->p_ari, p_cm_rej->ari_length );
\r
992 p_data += p_cm_rej->ari_length;
\r
994 if( p_cm_rej->p_rej_pdata )
\r
995 cl_memcpy( p_data, p_cm_rej->p_rej_pdata, p_cm_rej->rej_length );
\r
997 cl_status = do_al_dev_ioctl( UAL_CM_REJ,
\r
998 &p_cm_ioctl->in, ioctl_buf_sz,
\r
999 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out),
\r
1002 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
1004 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1005 ("UAL_CM_REJ IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
1006 status = IB_ERROR;
\r
1010 status = p_cm_ioctl->out.status;
\r
1013 if( h_conn->h_qp )
\r
1014 cm_reset_qp( h_conn->h_qp, 0 );
\r
1016 if( IB_SUCCESS == status )
\r
1018 /* Cleanup the connection request. */
\r
1019 ref_al_obj( &h_conn->obj );
\r
1020 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
1024 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1025 ("IOCTL status %s.\n", ib_get_err_str(status)) );
\r
1028 cl_free( p_cm_ioctl );
\r
1029 AL_EXIT( AL_DBG_CM );
\r
1037 IN const ib_cm_handle_t h_cm,
\r
1038 IN const ib_cm_mra_t* const p_cm_mra )
\r
1040 ib_cm_handle_t h_conn;
\r
1041 ual_cm_mra_ioctl_t *p_cm_ioctl;
\r
1042 size_t ioctl_buf_sz;
\r
1043 uintn_t bytes_ret;
\r
1044 ib_api_status_t status;
\r
1045 cl_status_t cl_status;
\r
1047 AL_ENTER(AL_DBG_CM);
\r
1049 /* Validate input parameters. */
\r
1051 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
1053 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid CM handle.\n") );
\r
1054 return IB_INVALID_HANDLE;
\r
1058 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_mra\n") );
\r
1059 return IB_INVALID_PARAMETER;
\r
1062 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
1063 if( p_cm_mra->p_mra_pdata )
\r
1064 ioctl_buf_sz += p_cm_mra->mra_length;
\r
1066 p_cm_ioctl = (ual_cm_mra_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
1069 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
1070 ("Failed to allocate IOCTL buffer\n") );
\r
1071 return IB_INSUFFICIENT_MEMORY;
\r
1074 p_cm_ioctl->in.h_cm = h_conn->obj.hdl;
\r
1075 CL_ASSERT( p_cm_ioctl->in.h_cm );
\r
1076 p_cm_ioctl->in.cm_mra = *p_cm_mra;
\r
1077 if( p_cm_mra->p_mra_pdata )
\r
1079 cl_memcpy( (uint8_t*)((&p_cm_ioctl->in.cm_mra) + 1),
\r
1080 p_cm_mra->p_mra_pdata, p_cm_mra->mra_length );
\r
1083 cl_status = do_al_dev_ioctl( UAL_CM_MRA, &p_cm_ioctl->in, ioctl_buf_sz,
\r
1084 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out), &bytes_ret );
\r
1086 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
1088 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1089 ("UAL_CM_MRA IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
1090 status = IB_ERROR;
\r
1094 status = p_cm_ioctl->out.status;
\r
1095 if( status != IB_SUCCESS )
\r
1097 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1098 ("IOCTL status %s.\n", ib_get_err_str(status)) );
\r
1102 cl_free( p_cm_ioctl );
\r
1103 AL_EXIT(AL_DBG_CM);
\r
1111 IN const ib_cm_lap_t* const p_cm_lap )
\r
1113 ib_cm_handle_t h_conn;
\r
1114 ual_cm_lap_ioctl_t *p_cm_ioctl;
\r
1115 size_t ioctl_buf_sz;
\r
1116 uintn_t bytes_ret;
\r
1117 ib_api_status_t status;
\r
1118 cl_status_t cl_status;
\r
1120 AL_ENTER(AL_DBG_CM);
\r
1122 /* Validate input parameters. */
\r
1123 if( !p_cm_lap || !p_cm_lap->p_alt_path )
\r
1125 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_lap\n") );
\r
1126 return IB_INVALID_PARAMETER;
\r
1129 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
1130 if( p_cm_lap->p_lap_pdata )
\r
1131 ioctl_buf_sz += p_cm_lap->lap_length;
\r
1133 p_cm_ioctl = (ual_cm_lap_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
1136 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate IOCTL buffer.\n") );
\r
1137 return IB_INSUFFICIENT_MEMORY;
\r
1140 /* Convert to the kernel-mode handles. */
\r
1141 p_cm_ioctl->in.cm_lap = *p_cm_lap;
\r
1142 switch( p_cm_lap->qp_type )
\r
1144 case IB_QPT_RELIABLE_CONN:
\r
1145 case IB_QPT_UNRELIABLE_CONN:
\r
1146 if( AL_OBJ_INVALID_HANDLE( p_cm_lap->h_qp, AL_OBJ_TYPE_H_QP ) ||
\r
1147 (p_cm_lap->h_qp->type != p_cm_lap->qp_type) )
\r
1149 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1150 ("IB_INVALID_QP_HANDLE\n") );
\r
1151 status = IB_INVALID_QP_HANDLE;
\r
1154 p_cm_ioctl->in.h_qp = p_cm_lap->h_qp->obj.hdl;
\r
1155 h_conn = ((al_conn_qp_t*)p_cm_lap->h_qp)->p_conn;
\r
1159 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1160 status = IB_INVALID_SETTING;
\r
1164 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
1166 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1167 ("No connection info!\n") );
\r
1168 status = IB_INVALID_SETTING;
\r
1171 h_conn->pfn_cm_apr_cb = p_cm_lap->pfn_cm_apr_cb;
\r
1173 /* Copy the path. */
\r
1174 p_cm_ioctl->in.alt_path = *p_cm_lap->p_alt_path;
\r
1175 /* Copy the private data. */
\r
1176 if( p_cm_lap->p_lap_pdata )
\r
1178 cl_memcpy( (&p_cm_ioctl->in.alt_path) + 1,
\r
1179 p_cm_lap->p_lap_pdata, p_cm_lap->lap_length );
\r
1182 cl_status = do_al_dev_ioctl( UAL_CM_LAP, &p_cm_ioctl->in, ioctl_buf_sz,
\r
1183 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out), &bytes_ret );
\r
1185 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
1187 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1188 ("UAL_CM_LAP IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
1189 status = IB_ERROR;
\r
1193 status = p_cm_ioctl->out.status;
\r
1194 if( status != IB_SUCCESS )
\r
1196 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1197 ("IOCTL status %s.\n", ib_get_err_str(status)) );
\r
1202 cl_free( p_cm_ioctl );
\r
1203 AL_EXIT(AL_DBG_CM);
\r
1211 IN const ib_qp_handle_t h_qp )
\r
1213 ual_force_apm_ioctl_t cm_ioctl;
\r
1214 uintn_t bytes_ret;
\r
1215 ib_api_status_t status;
\r
1216 cl_status_t cl_status;
\r
1218 AL_ENTER(AL_DBG_CM);
\r
1220 /* Clear the apm_ioctl */
\r
1221 cl_memclr( &cm_ioctl, sizeof( cm_ioctl ) );
\r
1223 /* Replace the handles with kernel handles appropriately */
\r
1224 if( AL_OBJ_INVALID_HANDLE( h_qp, AL_OBJ_TYPE_H_QP ) )
\r
1226 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid QP handle.\n") );
\r
1227 return IB_INVALID_QP_HANDLE;
\r
1230 cm_ioctl.in.h_qp = h_qp->obj.hdl;
\r
1232 cl_status = do_al_dev_ioctl( UAL_CM_FORCE_APM,
\r
1233 &cm_ioctl.in, sizeof(cm_ioctl.in), &cm_ioctl.out, sizeof(cm_ioctl.out),
\r
1236 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(cm_ioctl.out) )
\r
1238 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1239 ("UAL_CM_FORCE_APM IOCTL returned %s\n",
\r
1240 CL_STATUS_MSG(cl_status)) );
\r
1241 status = IB_ERROR;
\r
1245 status = cm_ioctl.out.status;
\r
1246 if( status != IB_SUCCESS )
\r
1248 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1249 ("IOCTL status %s.\n", ib_get_err_str(status)) );
\r
1253 AL_EXIT(AL_DBG_CM);
\r
1261 IN const ib_cm_handle_t h_cm_lap,
\r
1262 IN const ib_cm_apr_t* const p_cm_apr )
\r
1264 ib_cm_handle_t h_conn;
\r
1265 ual_cm_apr_ioctl_t *p_cm_ioctl;
\r
1266 size_t ioctl_buf_sz;
\r
1267 uintn_t bytes_ret;
\r
1268 ib_api_status_t status;
\r
1269 cl_status_t cl_status;
\r
1272 AL_ENTER(AL_DBG_CM);
\r
1274 /* Validate input parameters. */
\r
1275 h_conn = h_cm_lap;
\r
1276 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
1278 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid lap handle.\n") );
\r
1279 return IB_INVALID_HANDLE;
\r
1283 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_apr\n") );
\r
1284 return IB_INVALID_PARAMETER;
\r
1287 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
1288 if( p_cm_apr->p_info )
\r
1289 ioctl_buf_sz += p_cm_apr->info_length;
\r
1290 if( p_cm_apr->p_apr_pdata )
\r
1291 ioctl_buf_sz += p_cm_apr->apr_length;
\r
1293 p_cm_ioctl = (ual_cm_apr_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
1296 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate IOCTL buffer.\n") );
\r
1297 return IB_INSUFFICIENT_MEMORY;
\r
1300 /* Replace the handles with kernel handles appropriately */
\r
1301 p_cm_ioctl->in.h_cm_lap = h_conn->obj.hdl;
\r
1302 CL_ASSERT( p_cm_ioctl->in.h_cm_lap );
\r
1304 /* Convert to the kernel-mode handles. */
\r
1305 p_cm_ioctl->in.cm_apr = *p_cm_apr;
\r
1306 switch( p_cm_apr->qp_type )
\r
1308 case IB_QPT_RELIABLE_CONN:
\r
1309 case IB_QPT_UNRELIABLE_CONN:
\r
1310 if( AL_OBJ_INVALID_HANDLE( p_cm_apr->h_qp, AL_OBJ_TYPE_H_QP ) ||
\r
1311 (p_cm_apr->h_qp->type != p_cm_apr->qp_type) )
\r
1313 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1314 ("IB_INVALID_QP_HANDLE\n") );
\r
1315 status = IB_INVALID_QP_HANDLE;
\r
1318 p_cm_ioctl->in.h_qp = p_cm_apr->h_qp->obj.hdl;
\r
1319 h_conn = ((al_conn_qp_t*)p_cm_apr->h_qp)->p_conn;
\r
1323 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1324 status = IB_INVALID_SETTING;
\r
1328 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
1330 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1331 ("No connection info!\n") );
\r
1332 status = IB_INVALID_SETTING;
\r
1336 /* Copy the apr info and private data. */
\r
1337 p_buf = (uint8_t*)((&p_cm_ioctl->in.cm_apr) + 1);
\r
1338 if( p_cm_apr->p_info )
\r
1340 cl_memcpy( p_buf, p_cm_apr->p_info, p_cm_apr->info_length );
\r
1341 p_buf += p_cm_apr->info_length;
\r
1343 if( p_cm_apr->p_apr_pdata )
\r
1344 cl_memcpy( p_buf, p_cm_apr->p_apr_pdata, p_cm_apr->apr_length );
\r
1346 cl_status = do_al_dev_ioctl( UAL_CM_APR,
\r
1347 &p_cm_ioctl->in, ioctl_buf_sz,
\r
1348 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out),
\r
1351 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
1353 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1354 ("UAL_CM_APR IOCTL returned %s.\n", CL_STATUS_MSG(cl_status)) );
\r
1355 status = IB_ERROR;
\r
1359 status = p_cm_ioctl->out.status;
\r
1360 if( status != IB_SUCCESS )
\r
1362 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1363 ("IOCTL status %s.\n", ib_get_err_str(status)) );
\r
1367 /* Release the reference taken when processing the callback. */
\r
1368 deref_al_obj( &h_conn->obj );
\r
1371 cl_free( p_cm_ioctl );
\r
1372 AL_EXIT(AL_DBG_CM);
\r
1373 return IB_SUCCESS;
\r
1380 IN const ib_cm_dreq_t* const p_cm_dreq )
\r
1382 ib_cm_handle_t h_conn;
\r
1383 ual_cm_dreq_ioctl_t *p_cm_ioctl;
\r
1384 size_t ioctl_buf_sz;
\r
1385 uintn_t bytes_ret;
\r
1386 ib_api_status_t status;
\r
1387 cl_status_t cl_status;
\r
1389 AL_ENTER(AL_DBG_CM);
\r
1391 /* Validate input parameters. */
\r
1394 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_dreq\n") );
\r
1395 return IB_INVALID_PARAMETER;
\r
1398 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
1399 if( p_cm_dreq->p_dreq_pdata )
\r
1400 ioctl_buf_sz += p_cm_dreq->dreq_length;
\r
1402 p_cm_ioctl = (ual_cm_dreq_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
1405 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR, ("Failed to allocate IOCTL buffer.\n") );
\r
1406 return IB_INSUFFICIENT_MEMORY;
\r
1409 /* Convert to the kernel-mode handles. */
\r
1410 p_cm_ioctl->in.cm_dreq = *p_cm_dreq;
\r
1411 switch( p_cm_dreq->qp_type )
\r
1413 case IB_QPT_RELIABLE_CONN:
\r
1414 case IB_QPT_UNRELIABLE_CONN:
\r
1415 if( AL_OBJ_INVALID_HANDLE( p_cm_dreq->h_qp, AL_OBJ_TYPE_H_QP ) ||
\r
1416 (p_cm_dreq->h_qp->type != p_cm_dreq->qp_type) )
\r
1418 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1419 ("IB_INVALID_QP_HANDLE\n") );
\r
1420 status = IB_INVALID_QP_HANDLE;
\r
1423 p_cm_ioctl->in.h_qp = p_cm_dreq->h_qp->obj.hdl;
\r
1424 h_conn = ((al_conn_qp_t*)p_cm_dreq->h_qp)->p_conn;
\r
1428 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1429 status = IB_INVALID_SETTING;
\r
1433 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
1435 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1436 ("No connection info!\n") );
\r
1437 status = IB_INVALID_SETTING;
\r
1440 h_conn->pfn_cm_drep_cb = p_cm_dreq->pfn_cm_drep_cb;
\r
1442 /* Copy the private data. */
\r
1443 if( p_cm_dreq->p_dreq_pdata )
\r
1445 cl_memcpy( (&p_cm_ioctl->in.cm_dreq) + 1,
\r
1446 p_cm_dreq->p_dreq_pdata, p_cm_dreq->dreq_length );
\r
1449 cl_status = do_al_dev_ioctl( UAL_CM_DREQ,
\r
1450 &p_cm_ioctl->in, ioctl_buf_sz,
\r
1451 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out),
\r
1454 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
1456 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1457 ("UAL_CM_DREQ IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
1458 status = IB_ERROR;
\r
1462 status = p_cm_ioctl->out.status;
\r
1463 if( IB_SUCCESS != status )
\r
1465 /* We can fail if we just received a DREQ, which is not an error. */
\r
1466 AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_CM ,
\r
1467 ("IOCTL status %s\n", ib_get_err_str(status)) );
\r
1472 cl_free( p_cm_ioctl );
\r
1473 AL_EXIT(AL_DBG_CM);
\r
1481 IN const ib_cm_handle_t h_cm_dreq,
\r
1482 IN const ib_cm_drep_t* const p_cm_drep )
\r
1484 ib_cm_handle_t h_conn;
\r
1485 ual_cm_drep_ioctl_t *p_cm_ioctl;
\r
1486 size_t ioctl_buf_sz;
\r
1487 uintn_t bytes_ret;
\r
1488 ib_api_status_t status;
\r
1489 cl_status_t cl_status;
\r
1491 AL_ENTER(AL_DBG_CM);
\r
1493 /* Validate input parameters. */
\r
1494 h_conn = h_cm_dreq;
\r
1495 if( AL_OBJ_INVALID_HANDLE( h_conn, AL_OBJ_TYPE_H_CONN ) )
\r
1497 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid DREP handle.\n") );
\r
1498 return IB_INVALID_HANDLE;
\r
1502 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("NULL p_cm_drep\n") );
\r
1503 return IB_INVALID_PARAMETER;
\r
1506 ioctl_buf_sz = sizeof(p_cm_ioctl->in);
\r
1507 if( p_cm_drep->p_drep_pdata )
\r
1508 ioctl_buf_sz += p_cm_drep->drep_length;
\r
1510 p_cm_ioctl = (ual_cm_drep_ioctl_t*)cl_zalloc( ioctl_buf_sz );
\r
1513 AL_PRINT_EXIT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR,
\r
1514 ("Failed to allocate IOCTL buffer.\n") );
\r
1515 return IB_INSUFFICIENT_MEMORY;
\r
1518 p_cm_ioctl->in.h_cm_dreq = h_conn->obj.hdl;
\r
1519 CL_ASSERT( p_cm_ioctl->in.h_cm_dreq );
\r
1520 p_cm_ioctl->in.cm_drep = *p_cm_drep;
\r
1521 if( p_cm_drep->p_drep_pdata )
\r
1523 cl_memcpy( (uint8_t*)((&p_cm_ioctl->in.cm_drep) + 1),
\r
1524 p_cm_drep->p_drep_pdata, p_cm_drep->drep_length );
\r
1527 cl_status = do_al_dev_ioctl( UAL_CM_DREP,
\r
1528 &p_cm_ioctl->in, ioctl_buf_sz,
\r
1529 &p_cm_ioctl->out, sizeof(p_cm_ioctl->out),
\r
1532 if( cl_status != CL_SUCCESS || bytes_ret != sizeof(p_cm_ioctl->out) )
\r
1534 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1535 ("UAL_CM_DREP IOCTL returned %s\n", CL_STATUS_MSG(cl_status)) );
\r
1536 status = IB_ERROR;
\r
1540 status = p_cm_ioctl->out.status;
\r
1543 if( IB_SUCCESS == status )
\r
1545 cm_reset_qp( h_conn->h_qp, 0 );
\r
1546 /* Cleanup the connection request. */
\r
1547 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
1551 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1552 ("IOCTL status %s\n", ib_get_err_str(status)) );
\r
1554 /* Release the reference taken when processing the callback. */
\r
1555 deref_al_obj( &h_conn->obj );
\r
1558 cl_free( p_cm_ioctl );
\r
1559 AL_EXIT(AL_DBG_CM);
\r
1566 ual_listen_err_cb(
\r
1567 IN ib_listen_err_rec_t *p_listen_err_rec )
\r
1569 ib_listen_handle_t h_listen;
\r
1571 AL_ENTER(AL_DBG_CM);
\r
1573 /* Get the listen object. */
\r
1574 h_listen = p_listen_err_rec->listen_context;
\r
1575 if( AL_OBJ_INVALID_HANDLE( h_listen, AL_OBJ_TYPE_H_LISTEN ) )
\r
1578 /* Convert to the user's handles and structures. */
\r
1579 p_listen_err_rec->listen_context = (void*)h_listen->obj.context;
\r
1580 p_listen_err_rec->h_cm_listen = h_listen;
\r
1582 /* Call the user's callback. */
\r
1583 h_listen->pfn_listen_err_cb( p_listen_err_rec );
\r
1585 /* Destroy the listen request. */
\r
1586 ref_al_obj( &h_listen->obj );
\r
1587 h_listen->obj.pfn_destroy( &h_listen->obj, NULL );
\r
1589 AL_EXIT(AL_DBG_CM);
\r
1596 IN ib_cm_req_rec_t* p_cm_req_rec,
\r
1597 IN ib_qp_mod_t* p_qp_rtr,
\r
1598 IN ib_qp_mod_t* p_qp_rts,
\r
1599 IN uint32_t timeout_ms )
\r
1601 ib_listen_handle_t h_listen;
\r
1602 ib_cm_handle_t h_conn;
\r
1603 ib_qp_handle_t h_qp;
\r
1605 AL_ENTER(AL_DBG_CM);
\r
1607 if( p_cm_req_rec->h_cm_listen )
\r
1610 * This was generated in response for a listen request. Store
\r
1611 * the kernel handle in the user mode handle in case the
\r
1612 * ib_cm_listen call has not returned yet.
\r
1614 h_listen = (ib_listen_handle_t)p_cm_req_rec->context;
\r
1615 h_listen->obj.hdl = (uint64_t)p_cm_req_rec->h_cm_listen;
\r
1618 * Replace the listen handle with UAL handle and the context with
\r
1619 * the application's context.
\r
1621 p_cm_req_rec->h_cm_listen = h_listen;
\r
1622 p_cm_req_rec->context = h_listen->obj.context;
\r
1623 p_cm_req_rec->sidr_context = h_listen->sidr_context;
\r
1625 /* For a req callback as a result of a listen, there is no
\r
1626 * connection handle associated with the user mode yet. So
\r
1627 * create one that can be used in the reply.
\r
1629 h_conn = __get_conn( (ib_al_handle_t)h_listen->obj.p_parent_obj );
\r
1632 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
\r
1633 ("__get_conn failed.\n") );
\r
1634 __rej_conn( p_cm_req_rec->h_cm_req, IB_REJ_INSUF_RESOURCES );
\r
1638 deref_al_obj( &h_conn->obj );
\r
1640 /* Copy the callbacks from the listen. */
\r
1641 h_conn->p_conn_req->pfn_cm_req_cb = h_listen->pfn_cm_req_cb;
\r
1642 h_conn->pfn_cm_rej_cb = h_listen->pfn_cm_rej_cb;
\r
1643 h_conn->pfn_cm_mra_cb = h_listen->pfn_cm_mra_cb;
\r
1647 /* This callback was generated for peer-to-peer connections */
\r
1648 h_qp = (ib_qp_handle_t)p_cm_req_rec->context;
\r
1649 p_cm_req_rec->context = h_qp->obj.context;
\r
1651 /* Get the connection handle associated with this QP. */
\r
1652 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1655 * Unbind this QP. This allows the user to use a different QP
\r
1656 * when replying to the connection.
\r
1658 cm_unbind_qp( h_conn );
\r
1659 deref_al_obj( &h_qp->obj );
\r
1662 /* Store & replace the kernel handle */
\r
1663 h_conn->obj.hdl = (uint64_t)p_cm_req_rec->h_cm_req;
\r
1664 p_cm_req_rec->h_cm_req = h_conn;
\r
1667 * Copy the connection request information needed to properly configure
\r
1670 h_conn->p_conn_req->path_rec = p_cm_req_rec->primary_path;
\r
1671 h_conn->p_conn_req->alt_path_rec = p_cm_req_rec->alt_path;
\r
1672 h_conn->p_conn_req->qp_mod_rtr = *p_qp_rtr;
\r
1673 h_conn->p_conn_req->qp_mod_rts = *p_qp_rts;
\r
1674 h_conn->p_conn_req->timeout_ms = timeout_ms;
\r
1676 /* Invoke the user's callback. */
\r
1677 h_conn->p_conn_req->pfn_cm_req_cb( p_cm_req_rec );
\r
1679 AL_EXIT(AL_DBG_CM);
\r
1686 IN ib_cm_rep_rec_t* p_cm_rep_rec,
\r
1687 IN ib_qp_mod_t* p_qp_rtr,
\r
1688 IN ib_qp_mod_t* p_qp_rts )
\r
1690 ib_cm_handle_t h_conn;
\r
1691 ib_qp_handle_t h_qp;
\r
1693 AL_ENTER(AL_DBG_CM);
\r
1695 /* Get the user's context. */
\r
1696 switch( p_cm_rep_rec->qp_type )
\r
1698 case IB_QPT_RELIABLE_CONN:
\r
1699 case IB_QPT_UNRELIABLE_CONN:
\r
1700 h_qp = (ib_qp_handle_t)p_cm_rep_rec->qp_context;
\r
1701 p_cm_rep_rec->qp_context = h_qp->obj.context;
\r
1703 /* Get the connection handle associated with this QP. */
\r
1704 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1706 /* Store the kernel reply handle. */
\r
1707 h_conn->obj.hdl = (uint64_t)p_cm_rep_rec->h_cm_rep;
\r
1708 p_cm_rep_rec->h_cm_rep = h_conn;
\r
1711 * Copy the connection request information needed to properly
\r
1712 * configure the QP.
\r
1714 h_conn->p_conn_req->qp_mod_rtr = *p_qp_rtr;
\r
1715 h_conn->p_conn_req->qp_mod_rts = *p_qp_rts;
\r
1717 /* Call the application callback */
\r
1718 h_conn->p_conn_req->pfn_cm_rep_cb( p_cm_rep_rec );
\r
1721 case IB_QPT_UNRELIABLE_DGRM:
\r
1722 /* Get the SIDR request handle associated with this request. */
\r
1723 h_conn = (ib_cm_handle_t)p_cm_rep_rec->sidr_context;
\r
1724 p_cm_rep_rec->sidr_context = h_conn->sidr_context;
\r
1726 /* Call the application callback */
\r
1727 h_conn->p_conn_req->pfn_cm_rep_cb( p_cm_rep_rec );
\r
1729 /* Destroy the SIDR request. */
\r
1730 ref_al_obj( &h_conn->obj );
\r
1731 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
1735 AL_PRINT(TRACE_LEVEL_ERROR , AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1739 AL_EXIT(AL_DBG_CM);
\r
1746 IN ib_cm_rtu_rec_t* p_cm_rtu_rec )
\r
1748 ib_cm_handle_t h_conn;
\r
1749 ib_qp_handle_t h_qp;
\r
1750 ib_pfn_cm_rtu_cb_t pfn_cm_rtu_cb;
\r
1752 AL_ENTER(AL_DBG_CM);
\r
1754 h_qp = (ib_qp_handle_t)p_cm_rtu_rec->qp_context;
\r
1755 p_cm_rtu_rec->qp_context = h_qp->obj.context;
\r
1757 /* Get the connection handle associated with this QP. */
\r
1758 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1761 * We are done with this connection establishment. After we call the
\r
1762 * user back, they can disconnect the QP, destroy it, close AL, or do
\r
1763 * one of any number of difficult things to deal with, so we need to
\r
1764 * handle the case where the connection structure may be destroyed.
\r
1765 * Get a copy of the user's callback.
\r
1767 pfn_cm_rtu_cb = h_conn->p_conn_req->pfn_cm_rtu_cb;
\r
1768 __free_conn_req( h_conn );
\r
1770 /* Invoke the user's callback. */
\r
1771 pfn_cm_rtu_cb( p_cm_rtu_rec );
\r
1773 AL_EXIT(AL_DBG_CM);
\r
1780 IN ib_cm_rej_rec_t* p_cm_rej_rec )
\r
1782 ib_cm_handle_t h_conn;
\r
1783 ib_qp_handle_t h_qp;
\r
1784 ib_pfn_cm_rej_cb_t pfn_cm_rej_cb;
\r
1786 AL_ENTER(AL_DBG_CM);
\r
1788 h_qp = (ib_qp_handle_t)p_cm_rej_rec->qp_context;
\r
1789 p_cm_rej_rec->qp_context = h_qp->obj.context;
\r
1791 /* Get the connection handle associated with this QP. */
\r
1792 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1796 AL_EXIT( AL_DBG_CM );
\r
1800 /* Move the QP to the error state. Timewait is tracked in the kernel. */
\r
1801 cm_reset_qp( h_qp, 0 );
\r
1804 * Since user can reuse the QP associated with this connection after
\r
1805 * receiving the reject message, we need to disassociate this
\r
1806 * connection handle from the QP before calling the user back.
\r
1810 pfn_cm_rej_cb = h_conn->pfn_cm_rej_cb;
\r
1811 ref_al_obj( &h_conn->obj );
\r
1812 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
1814 /* Invoke the user's callback. */
\r
1815 if( pfn_cm_rej_cb )
\r
1816 pfn_cm_rej_cb( p_cm_rej_rec );
\r
1818 AL_EXIT(AL_DBG_CM);
\r
1825 IN ib_cm_mra_rec_t* p_cm_mra_rec )
\r
1827 ib_cm_handle_t h_conn;
\r
1828 ib_qp_handle_t h_qp;
\r
1830 AL_ENTER(AL_DBG_CM);
\r
1832 /* Convert the user's handles. */
\r
1833 switch( p_cm_mra_rec->qp_type )
\r
1835 case IB_QPT_RELIABLE_CONN:
\r
1836 case IB_QPT_UNRELIABLE_CONN:
\r
1837 h_qp = (ib_qp_handle_t)p_cm_mra_rec->qp_context;
\r
1838 p_cm_mra_rec->qp_context = h_qp->obj.context;
\r
1839 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1843 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1847 /* Call the application callback */
\r
1848 h_conn->pfn_cm_mra_cb( p_cm_mra_rec );
\r
1850 AL_EXIT(AL_DBG_CM);
\r
1857 IN ib_cm_lap_rec_t* p_cm_lap_rec )
\r
1859 ib_cm_handle_t h_conn;
\r
1860 ib_qp_handle_t h_qp;
\r
1862 AL_ENTER(AL_DBG_CM);
\r
1864 /* Convert the user's handles. */
\r
1865 switch( p_cm_lap_rec->qp_type )
\r
1867 case IB_QPT_RELIABLE_CONN:
\r
1868 case IB_QPT_UNRELIABLE_CONN:
\r
1869 h_qp = (ib_qp_handle_t)p_cm_lap_rec->qp_context;
\r
1870 p_cm_lap_rec->qp_context = h_qp->obj.context;
\r
1871 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1875 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1879 /* Store & replace the kernel handle */
\r
1880 h_conn->obj.hdl = (uint64_t)p_cm_lap_rec->h_cm_lap;
\r
1881 p_cm_lap_rec->h_cm_lap = h_conn;
\r
1883 /* Reference the connection until the user calls ib_cm_apr. */
\r
1884 ref_al_obj( &h_conn->obj );
\r
1886 /* Call the application callback */
\r
1887 h_conn->pfn_cm_lap_cb( p_cm_lap_rec );
\r
1889 AL_EXIT(AL_DBG_CM);
\r
1896 IN ib_cm_apr_rec_t* p_cm_apr_rec )
\r
1898 ib_cm_handle_t h_conn;
\r
1899 ib_qp_handle_t h_qp;
\r
1901 AL_ENTER(AL_DBG_CM);
\r
1903 /* Convert the user's handles. */
\r
1904 switch( p_cm_apr_rec->qp_type )
\r
1906 case IB_QPT_RELIABLE_CONN:
\r
1907 case IB_QPT_UNRELIABLE_CONN:
\r
1908 h_qp = (ib_qp_handle_t)p_cm_apr_rec->qp_context;
\r
1909 p_cm_apr_rec->qp_context = h_qp->obj.context;
\r
1910 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1914 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1918 /* Call the application callback */
\r
1919 h_conn->pfn_cm_apr_cb( p_cm_apr_rec );
\r
1921 AL_EXIT(AL_DBG_CM);
\r
1928 IN ib_cm_dreq_rec_t* p_cm_dreq_rec )
\r
1930 ib_cm_handle_t h_conn;
\r
1931 ib_qp_handle_t h_qp;
\r
1933 AL_ENTER(AL_DBG_CM);
\r
1935 /* Convert the user's handles. */
\r
1936 switch( p_cm_dreq_rec->qp_type )
\r
1938 case IB_QPT_RELIABLE_CONN:
\r
1939 case IB_QPT_UNRELIABLE_CONN:
\r
1940 h_qp = (ib_qp_handle_t)p_cm_dreq_rec->qp_context;
\r
1941 p_cm_dreq_rec->qp_context = h_qp->obj.context;
\r
1942 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1946 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1950 /* Store the kernel reply handle. */
\r
1951 h_conn->obj.hdl = (uint64_t)p_cm_dreq_rec->h_cm_dreq;
\r
1952 p_cm_dreq_rec->h_cm_dreq = h_conn;
\r
1954 /* Reference the connection until the user calls ib_cm_drep. */
\r
1955 ref_al_obj( &h_conn->obj );
\r
1957 /* Call the application callback */
\r
1958 h_conn->pfn_cm_dreq_cb( p_cm_dreq_rec );
\r
1959 AL_EXIT(AL_DBG_CM);
\r
1966 IN ib_cm_drep_rec_t* p_cm_drep_rec )
\r
1968 ib_cm_handle_t h_conn;
\r
1969 ib_qp_handle_t h_qp;
\r
1970 ib_pfn_cm_drep_cb_t pfn_cm_drep_cb;
\r
1972 AL_ENTER(AL_DBG_CM);
\r
1974 /* Convert the user's handles. */
\r
1975 switch( p_cm_drep_rec->qp_type )
\r
1977 case IB_QPT_RELIABLE_CONN:
\r
1978 case IB_QPT_UNRELIABLE_CONN:
\r
1979 h_qp = (ib_qp_handle_t)p_cm_drep_rec->qp_context;
\r
1980 p_cm_drep_rec->qp_context = h_qp->obj.context;
\r
1981 h_conn = ((al_conn_qp_t*)h_qp)->p_conn;
\r
1985 AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR , ("Invalid qp_type.\n") );
\r
1989 /* TODO: Handle timewait. */
\r
1990 cm_reset_qp( h_qp, 0 );
\r
1993 * We are done with this connection. After we call the user back,
\r
1994 * they can close AL, or do one of any number of difficult things
\r
1995 * to deal with, so we need to handle the case where the connection
\r
1996 * structure may be destroyed. Get a copy of the user's callback.
\r
1998 pfn_cm_drep_cb = h_conn->pfn_cm_drep_cb;
\r
1999 ref_al_obj( &h_conn->obj );
\r
2000 h_conn->obj.pfn_destroy( &h_conn->obj, NULL );
\r
2002 /* Invoke the user's callback. */
\r
2003 pfn_cm_drep_cb( p_cm_drep_rec );
\r
2005 AL_EXIT(AL_DBG_CM);
\r