From d8986643df247f5616bc0fe44c15a0744a616dfb Mon Sep 17 00:00:00 2001 From: leonidk Date: Tue, 23 Oct 2007 16:32:04 +0000 Subject: [PATCH] [IBAL] Added Ioctl UAL_NDI_REP_CM git-svn-id: svn://openib.tc.cornell.edu/gen1@884 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- branches/Ndi/core/al/al_cm_cep.h | 8 + branches/Ndi/core/al/kernel/al_cm_cep.c | 89 +++++-- branches/Ndi/core/al/kernel/al_ndi_cm.c | 258 +++++++++++++++++---- branches/Ndi/core/al/kernel/al_proxy_ndi.c | 19 +- branches/Ndi/inc/iba/ib_al_ioctl.h | 2 +- 5 files changed, 300 insertions(+), 76 deletions(-) diff --git a/branches/Ndi/core/al/al_cm_cep.h b/branches/Ndi/core/al/al_cm_cep.h index be3c62ad..90ed7944 100644 --- a/branches/Ndi/core/al/al_cm_cep.h +++ b/branches/Ndi/core/al/al_cm_cep.h @@ -144,6 +144,14 @@ al_cep_pre_rep( IN const ib_cm_rep_t* const p_cm_rep, OUT ib_qp_mod_t* const p_init ); +ib_api_status_t +al_cep_pre_rep_ex( + IN ib_al_handle_t h_al, + IN net32_t cid, + IN void* __ptr64 context, + IN const ib_cm_rep_t* const p_cm_rep, + IN al_pfn_cep_cb_t pfn_cb, + OUT ib_qp_mod_t* const p_init ); ib_api_status_t al_cep_send_rep( diff --git a/branches/Ndi/core/al/kernel/al_cm_cep.c b/branches/Ndi/core/al/kernel/al_cm_cep.c index 5176816e..b672bcce 100644 --- a/branches/Ndi/core/al/kernel/al_cm_cep.c +++ b/branches/Ndi/core/al/kernel/al_cm_cep.c @@ -4880,34 +4880,22 @@ __format_rep( } + ib_api_status_t -al_cep_pre_rep( - IN ib_al_handle_t h_al, - IN net32_t cid, +__al_cep_pre_rep( + IN kcep_t *p_cep, IN void* __ptr64 context, IN const ib_cm_rep_t* const p_cm_rep, OUT ib_qp_mod_t* const p_init ) { ib_api_status_t status; - kcep_t *p_cep; - KLOCK_QUEUE_HANDLE hdl; cep_agent_t *p_port_cep; AL_ENTER( AL_DBG_CM ); - CL_ASSERT( h_al ); CL_ASSERT( p_cm_rep ); CL_ASSERT( p_init ); - KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl ); - p_cep = __lookup_cep( h_al, cid ); - if( !p_cep ) - { - KeReleaseInStackQueuedSpinLock( &hdl ); - AL_EXIT( AL_DBG_CM ); - return IB_INVALID_HANDLE; - } - switch( p_cep->state ) { case CEP_STATE_PRE_REP: @@ -4954,12 +4942,83 @@ al_cep_pre_rep( ("Invalid state: %d\n", p_cep->state) ); status = IB_INVALID_STATE; } + AL_EXIT( AL_DBG_CM ); + return status; +} + + +ib_api_status_t +al_cep_pre_rep( + IN ib_al_handle_t h_al, + IN net32_t cid, + IN void* __ptr64 context, + IN const ib_cm_rep_t* const p_cm_rep, + OUT ib_qp_mod_t* const p_init ) +{ + ib_api_status_t status; + kcep_t *p_cep; + KLOCK_QUEUE_HANDLE hdl; + + AL_ENTER( AL_DBG_CM ); + + CL_ASSERT( h_al ); + CL_ASSERT( p_cm_rep ); + CL_ASSERT( p_init ); + + KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl ); + p_cep = __lookup_cep( h_al, cid ); + if( !p_cep ) + { + KeReleaseInStackQueuedSpinLock( &hdl ); + AL_EXIT( AL_DBG_CM ); + return IB_INVALID_HANDLE; + } + + status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init ); + KeReleaseInStackQueuedSpinLock( &hdl ); AL_EXIT( AL_DBG_CM ); return status; } +ib_api_status_t +al_cep_pre_rep_ex( + IN ib_al_handle_t h_al, + IN net32_t cid, + IN void* __ptr64 context, + IN const ib_cm_rep_t* const p_cm_rep, + IN al_pfn_cep_cb_t pfn_cb, + OUT ib_qp_mod_t* const p_init ) +{ + ib_api_status_t status; + kcep_t *p_cep; + KLOCK_QUEUE_HANDLE hdl; + + AL_ENTER( AL_DBG_CM ); + + CL_ASSERT( h_al ); + CL_ASSERT( p_cm_rep ); + CL_ASSERT( p_init ); + + KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl ); + p_cep = __lookup_cep( h_al, cid ); + if( !p_cep ) + { + KeReleaseInStackQueuedSpinLock( &hdl ); + AL_EXIT( AL_DBG_CM ); + return IB_INVALID_HANDLE; + } + + status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init ); + + p_cep->pfn_cb = pfn_cb; + + KeReleaseInStackQueuedSpinLock( &hdl ); + AL_EXIT( AL_DBG_CM ); + return status; +} + ib_api_status_t al_cep_send_rep( IN ib_al_handle_t h_al, diff --git a/branches/Ndi/core/al/kernel/al_ndi_cm.c b/branches/Ndi/core/al/kernel/al_ndi_cm.c index fb8af722..024b8dba 100644 --- a/branches/Ndi/core/al/kernel/al_ndi_cm.c +++ b/branches/Ndi/core/al/kernel/al_ndi_cm.c @@ -175,6 +175,66 @@ __cep_timewait_qp( AL_EXIT( AL_DBG_CM ); } +static ib_api_status_t +__ndi_qp2rts( + IN ib_qp_handle_t const h_qp, + IN uint8_t init_depth, + IN uint8_t resp_res, + IN PIRP p_irp, + IN OUT ib_qp_mod_t *p_qp_mod + ) +{ + ib_api_status_t status; + + AL_ENTER( AL_DBG_NDI ); + + /* fill required qp attributes */ + status = al_cep_get_rtr_attr( qp_get_al( h_qp ), + ((al_conn_qp_t*)h_qp)->cid, p_qp_mod ); + if ( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_cep_get_rtr_attr returned %s\n", ib_get_err_str( status )) ); + goto exit; + } + p_qp_mod->state.rtr.resp_res = resp_res; + + /* perform the request: INIT->RTR */ + status = ndi_modify_qp( h_qp, p_qp_mod, + cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) ); + if ( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("ndi_modify_qp to RTR returned %s.\n", ib_get_err_str(status) ) ); + goto exit; + } + + /* fill required qp attributes */ + status = al_cep_get_rts_attr( qp_get_al( h_qp ), + ((al_conn_qp_t*)h_qp)->cid, p_qp_mod ); + if ( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_cep_get_rts_attr returned %s\n", ib_get_err_str( status )) ); + goto exit; + } + p_qp_mod->state.rts.init_depth = init_depth; + + /* perform the request: RTR->RTS */ + status = ndi_modify_qp( h_qp, p_qp_mod, + cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) ); + if ( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("ndi_modify_qp to RTS returned %s.\n", ib_get_err_str(status) ) ); + goto exit; + } + +exit: + AL_EXIT( AL_DBG_NDI ); + return status; +} + /******************************************************************* * @@ -483,6 +543,7 @@ __ndi_proc_rej( case NDI_CM_CONNECTING_RTU_SENT: case NDI_CM_CONNECTED: + case NDI_CM_REP_SENT: /* a race: the passive side’s REP times out, but active side has sent the RTU. We are treating this case it like a DREQ */ { @@ -546,7 +607,7 @@ __ndi_proc_rep( } /* fill the rej data */ - al_cep_set_pdata( p_cm->h_al, p_cm->cid, IB_REP_PDATA_SIZE, p_rep->pdata ); + al_cep_set_pdata( p_cm->h_al, p_cm->cid, IB_REJ_PDATA_SIZE, p_rep->pdata ); __ndi_complete_irp_ex( p_cm->h_qp, STATUS_SUCCESS, NDI_CM_CONNECTING_REP_RCVD ); @@ -997,58 +1058,25 @@ __ndi_rtu_cm( ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0]; ual_ndi_rtu_cm_ioctl_in_t *p_rtu = (ual_ndi_rtu_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp ); - uint8_t pdata[IB_REP_PDATA_SIZE]; + uint8_t pdata[IB_REJ_PDATA_SIZE]; uint8_t psize = sizeof(pdata); UNUSED_PARAM(p_dev_obj); AL_ENTER( AL_DBG_NDI ); + /* free the work item if any */ if ( p_irp->Tail.Overlay.DriverContext[1] ) IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] ); - /* fill required qp attributes */ - status = al_cep_get_rtr_attr( qp_get_al( h_qp ), - ((al_conn_qp_t*)h_qp)->cid, &qp_mod ); + /* change the QP state to RTS */ + status = __ndi_qp2rts( h_qp, p_rtu->init_depth, + p_rtu->resp_res, p_irp, &qp_mod ); if ( status != IB_SUCCESS ) { - AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, - ("al_cep_get_rtr_attr returned %s\n", ib_get_err_str( status )) ); goto err; } - qp_mod.state.rtr.resp_res = p_rtu->resp_res; - - /* perform the request: INIT->RTR */ - status = ndi_modify_qp( h_qp, &qp_mod, - cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) ); - if ( status != IB_SUCCESS ) - { - AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, - ("ndi_modify_qp to RTR returned %s.\n", ib_get_err_str(status) ) ); - goto err; - } - - /* fill required qp attributes */ - status = al_cep_get_rts_attr( qp_get_al( h_qp ), - ((al_conn_qp_t*)h_qp)->cid, &qp_mod ); - if ( status != IB_SUCCESS ) - { - AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, - ("al_cep_get_rts_attr returned %s\n", ib_get_err_str( status )) ); - goto err; - } - qp_mod.state.rts.init_depth = p_rtu->init_depth; - - /* perform the request: RTR->RTS */ - status = ndi_modify_qp( h_qp, &qp_mod, - cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) ); - if ( status != IB_SUCCESS ) - { - AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, - ("ndi_modify_qp to RTS returned %s.\n", ib_get_err_str(status) ) ); - goto err; - } - + /* send RTU */ al_cep_get_pdata( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid, &psize, pdata ); status = al_cep_rtu( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid, pdata, psize ); @@ -1115,6 +1143,7 @@ ndi_rtu_cm( } else { /* syncronous performing */ + p_irp->Tail.Overlay.DriverContext[1] = NULL; __ndi_rtu_cm( p_io_stack->DeviceObject, p_irp ); } @@ -1129,26 +1158,157 @@ ndi_rtu_cm( * ******************************************************************/ +static void +__ndi_rep_cm( + IN DEVICE_OBJECT* p_dev_obj, + IN PIRP p_irp ) +{ + NTSTATUS nt_status; + ib_qp_mod_t qp_mod; + ib_api_status_t status; + ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0]; + ual_ndi_rep_cm_ioctl_in_t *p_rep = + (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp ); + + UNUSED_PARAM(p_dev_obj); + + AL_ENTER( AL_DBG_NDI ); + + /* free the work item if any */ + if ( p_irp->Tail.Overlay.DriverContext[1] ) + IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] ); + + /* change the QP state to RTS */ + status = __ndi_qp2rts( h_qp, p_rep->init_depth, + p_rep->resp_res, p_irp, &qp_mod ); + if ( status != IB_SUCCESS ) + { + goto err; + } + + /* send REP */ + status = al_cep_send_rep ( qp_get_al( h_qp ), p_rep->cid ); + if( status != IB_SUCCESS ) + { + AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_cep_send_rep returned %s\n", ib_get_err_str(status)) ); +err: + cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID ); + + /* Reject and abort the connection. */ + al_cep_rej( qp_get_al( h_qp ), p_rep->cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 ); + + /* transit QP to error state */ + __cep_timewait_qp( h_qp ); + + ref_al_obj( &h_qp->obj ); + if( al_destroy_cep( qp_get_al( h_qp ), p_rep->cid, deref_al_obj ) != IB_SUCCESS ) + deref_al_obj( &h_qp->obj ); + + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_cep_rtu returned %s.\n", ib_get_err_str( status )) ); + h_qp->p_irp_que->state = NDI_CM_IDLE; + nt_status = STATUS_DRIVER_INTERNAL_ERROR; + p_irp->IoStatus.Information = 0; + goto exit; + } + + p_irp->IoStatus.Information = sizeof(uint32_t);; + h_qp->p_irp_que->state = NDI_CM_REP_SENT; + nt_status = STATUS_SUCCESS; + +exit: + p_irp->IoStatus.Status = nt_status; + IoCompleteRequest( p_irp, IO_NO_INCREMENT ); + deref_al_obj( &h_qp->obj ); + AL_EXIT( AL_DBG_NDI ); +} + +static void +__ndi_fill_cm_rep( + IN ib_qp_handle_t const h_qp, + IN ual_ndi_rep_cm_ioctl_in_t *p_rep, + IN ib_cm_rep_t *p_cm_rep) +{ + AL_ENTER( AL_DBG_NDI ); + + memset( p_cm_rep, 0, sizeof(ib_cm_rep_t) ); + + p_cm_rep->p_rep_pdata = (uint8_t *)&p_rep->pdata; + p_cm_rep->rep_length = sizeof(p_rep->pdata); + + p_cm_rep->qp_type = IB_QPT_RELIABLE_CONN; + p_cm_rep->h_qp = h_qp; + + p_cm_rep->init_depth = 0; + p_cm_rep->target_ack_delay = 10; + p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED; + p_cm_rep->flow_ctrl = TRUE; /* HCAs must support end-to-end flow control. */ + p_cm_rep->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT; + p_cm_rep->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY; + + AL_EXIT( AL_DBG_NDI ); +} NTSTATUS ndi_rep_cm( IN ib_qp_handle_t const h_qp, IN net32_t const cid, - IN cl_ioctl_handle_t h_ioctl, - IN ual_ndi_rep_cm_ioctl_in_t *p_ndi_rep_cm + IN PIRP p_irp, + IN ual_ndi_rep_cm_ioctl_in_t *p_rep ) { - NTSTATUS nt_status = CL_SUCCESS; + IO_STACK_LOCATION *p_io_stack; + ib_cm_rep_t cm_rep; + ib_qp_mod_t qp_mod; + net32_t old_cid; + ib_api_status_t status; - UNUSED_PARAM(h_qp); - UNUSED_PARAM(cid); - UNUSED_PARAM(h_ioctl); - UNUSED_PARAM(p_ndi_rep_cm); - AL_ENTER( AL_DBG_NDI ); + /* Format ib_cm_req_t structure */ + __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep ); + + /* prepare CEP for connection */ + status = al_cep_pre_rep_ex( qp_get_al( h_qp ), cid, h_qp, &cm_rep, __ndi_cm_handler, &qp_mod ); + if( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_cep_pre_rep_ex returned %s.\n", ib_get_err_str( status )) ); + goto err_cep_destroy; + } + + /* See if this QP has already been connected. */ + old_cid = cl_atomic_comp_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID, cid ); + if( old_cid != AL_INVALID_CID ) + goto err_cep_destroy; + + /* transfer work to a work the thread */ + p_irp->Tail.Overlay.DriverContext[0] = h_qp; + p_io_stack = IoGetCurrentIrpStackLocation( p_irp ); + p_irp->Tail.Overlay.DriverContext[1] = IoAllocateWorkItem( p_io_stack->DeviceObject ); + if ( p_irp->Tail.Overlay.DriverContext[1] ) + { /* asyncronous performing */ + IoMarkIrpPending( p_irp ); + IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1], + __ndi_rep_cm, DelayedWorkQueue, p_irp ); + } + else + { /* syncronous performing */ + p_irp->Tail.Overlay.DriverContext[1] = NULL; + __ndi_rep_cm( p_io_stack->DeviceObject, p_irp ); + } + goto exit; + +err_cep_destroy: + al_destroy_cep( qp_get_al( h_qp ), cid, NULL ); + + h_qp->p_irp_que->state = NDI_CM_IDLE; + __ndi_complete_irp( h_qp, p_irp, STATUS_HOST_UNREACHABLE ); + +exit: AL_EXIT( AL_DBG_NDI ); - return nt_status; + return CL_PENDING; } diff --git a/branches/Ndi/core/al/kernel/al_proxy_ndi.c b/branches/Ndi/core/al/kernel/al_proxy_ndi.c index de194d9b..e77ae343 100644 --- a/branches/Ndi/core/al/kernel/al_proxy_ndi.c +++ b/branches/Ndi/core/al/kernel/al_proxy_ndi.c @@ -320,8 +320,7 @@ __ndi_req_cm( p_context = (al_dev_open_context_t*)p_open_context; /* Validate user parameters. */ - if( cl_ioctl_in_size( h_ioctl ) < - (sizeof(ual_ndi_req_cm_ioctl_in_t) + p_req->pdata_size)) + if( cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_req_cm_ioctl_in_t)) { cl_status = CL_INVALID_REQUEST; goto exit; @@ -373,15 +372,15 @@ __ndi_rep_cm( net32_t cid; ual_ndi_rep_cm_ioctl_in_t *p_rep = (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl ); + UNUSED_PARAM(p_ret_bytes); AL_ENTER( AL_DBG_NDI ); p_context = (al_dev_open_context_t*)p_open_context; /* Validate user parameters. */ - if( (cl_ioctl_in_size( h_ioctl ) < (sizeof(ual_ndi_req_cm_ioctl_in_t) + p_rep->pdata_size)) || - (p_rep->pdata_size < sizeof(ib_cm_rdma_req_t)) || - cl_ioctl_out_size( h_ioctl ) != sizeof(atomic32_t) ) + if( (cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_rep_cm_ioctl_in_t)) || + cl_ioctl_out_size( h_ioctl ) < sizeof(net32_t) ) { cl_status = CL_INVALID_REQUEST; goto exit; @@ -413,14 +412,9 @@ __ndi_rep_cm( /* perform the ioctls */ cl_status = ndi_rep_cm( h_qp, cid, h_ioctl, p_rep ); - if( cl_status != CL_SUCCESS ) - goto exit; - - *p_ret_bytes = sizeof(uint32_t); - cl_status = CL_SUCCESS; exit: - if (h_qp) + if (h_qp && cl_status != CL_PENDING) deref_al_obj( &h_qp->obj ); AL_EXIT( AL_DBG_NDI ); @@ -472,6 +466,9 @@ __ndi_rtu_cm( cl_status = ndi_rtu_cm( h_qp, h_ioctl ); exit: + if (h_qp && cl_status != CL_PENDING) + deref_al_obj( &h_qp->obj ); + AL_EXIT( AL_DBG_NDI ); return cl_status; } diff --git a/branches/Ndi/inc/iba/ib_al_ioctl.h b/branches/Ndi/inc/iba/ib_al_ioctl.h index 22ebc279..bf51b898 100644 --- a/branches/Ndi/inc/iba/ib_al_ioctl.h +++ b/branches/Ndi/inc/iba/ib_al_ioctl.h @@ -3536,7 +3536,7 @@ typedef struct _ual_ndi_rep_cm_ioctl_in uint8_t init_depth; uint8_t resp_res; uint8_t pdata_size; - uint8_t pdata[IB_REP_PDATA_SIZE]; + uint8_t pdata[IB_REJ_PDATA_SIZE]; } ual_ndi_rep_cm_ioctl_in_t; /* -- 2.41.0