[ofw] [PATCH] Fix ND connection establishment races
Leonid Keller
leonid at mellanox.co.il
Sun Apr 5 08:25:59 PDT 2009
Applied in 2079, thank you.
> -----Original Message-----
> From: ofw-bounces at lists.openfabrics.org
> [mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Fab Tillier
> Sent: Thursday, March 26, 2009 11:05 PM
> To: ofw at lists.openfabrics.org
> Subject: [ofw] [PATCH] Fix ND connection establishment races
>
> Hi Folks,
>
> This patch fixes issues with connection establishment for
> NetworkDirect. The root cause of the issue is 'too many
> cooks' - CIDs exposed to user-mode should not be destroyed in
> the kernel code without explicit request from the user.
> Otherwise, the CID can get recycled in the kernel for the
> same process and improperly freed when the stale CID is
> released by the application (multiple connection objects in
> the app have the same CID.)
>
> Unfortunately, the fix is not simple. The QP references the
> CEP, so QP destruction frees the CEP, even if there's a
> reference to that CEP left in the application. Removing the
> CEP reference form the QP solves this problem, but deadlocks
> the app if it destroys the QP before the CEP, since the QP is
> used to queue connection-related IRPs, and the CEP uses the
> QP as its context and so holds a reference on it.
>
> This patch does the following:
> - Remove CEP reference for ND related QP.
> - Remove ND connection related IRP queue from QP.
> - Remove ND IRP handling from CEP manager.
> - Add a function to CEP manager to reference the context
> associated with a CEP if the context is non-NULL.
> - Move ND connection related IRP management into al_ndi_cm.c,
> in nd_csq_t structure.
>
> As part of testing, I needed to add NotifyDisconnect
> functionality, so this is also included in the patch.
>
> Note that the patch depends on Sean's previous patch to
> change kal_cep_destroy to allow silently dropping a REQ. I
> did not remove Sean's previous changes from this patch, so
> they are duplicated here. This allows the patch to be
> applied and build.
>
> I tested an earlier version of this, before I went through
> and did some minor cosmetic cleanup. I wanted to send this
> patch to get the review process going, and will report back
> when I finish retesting.
>
> Sorry for the big patch, I couldn't find a good way to split
> it up into smaller chunks.
>
> -Fab
>
> Signed-off-by: Fab Tillier <ftillier at microsoft.com>
>
> Index: core/al/kernel/al_cm_cep.c
> ===================================================================
> --- core/al/kernel/al_cm_cep.c (revision 2061)
> +++ core/al/kernel/al_cm_cep.c (working copy)
> @@ -370,9 +370,6 @@ typedef struct _al_kcep
> * NDI stuff - TODO: manage above core kernel CM code
> */
>
> - /* IRP list head */
> - LIST_ENTRY irp_que;
> -
> /* private data of REQ, REP, REJ CM requests */
> uint8_t psize;
> uint8_t
> pdata[IB_REP_PDATA_SIZE];
> @@ -3382,24 +3379,6 @@ create_cep_mgr(
> * CEP manager API
>
> **************************************************************
> ****************/
>
> -static inline void
> -__complete_ndi_irp(
> - IN PIRP
> p_irp,
> - IN ib_mad_element_t*
> p_mad )
> -{
> - net32_t* p_new_cid = (net32_t*)cl_ioctl_out_buf( p_irp );
> - kcep_t* p_cep = (kcep_t*)p_mad->send_context1;
> -
> - AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM,
> - ("Completing al_cep_get_cid IRP with CID =
> %d\n", p_cep->cid) );
> -
> - *p_new_cid = p_cep->cid;
> - p_irp->IoStatus.Information = sizeof(uint32_t);
> - p_irp->IoStatus.Status = STATUS_SUCCESS;
> - IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> - ib_put_mad( p_mad );
> -}
> -
>
> /* Called with the CEP and CEP manager locks held */
> static ib_api_status_t
> @@ -3422,8 +3401,6 @@ __cep_queue_mad(
> if ( p_cep->state == CEP_STATE_LISTEN &&
> (p_cep->sid & ~0x0ffffffI64) ==
> IB_REQ_CM_RDMA_SID_PREFIX )
> { /* Try to complete pending IRP, if any */
> - PIRP p_irp;
> - PLIST_ENTRY p_list_entry;
> mad_cm_req_t* p_req =
> (mad_cm_req_t*)ib_get_mad_buf( p_mad );
> ib_cm_rdma_req_t *p_rdma_req =
> (ib_cm_rdma_req_t *)p_req->pdata;
>
> @@ -3437,24 +3414,6 @@ __cep_queue_mad(
> p_rdma_req->maj_min_ver,
> p_rdma_req->ipv ) );
> return IB_UNSUPPORTED;
> }
> -
> - /* get a pending IRP */
> - if ( !IsListEmpty( &p_cep->irp_que ) )
> - {
> - // get IRP
> - p_list_entry = RemoveHeadList(
> &p_cep->irp_que );
> - p_irp = (PIRP)CONTAINING_RECORD(
> p_list_entry, IRP, Tail.Overlay.ListEntry );
> -
> - // complete GetConnectionReq IRP
> -#pragma warning(push, 3)
> - IoSetCancelRoutine( p_irp, NULL );
> -#pragma warning(pop)
> -
> - __complete_ndi_irp( p_irp, p_mad );
> -
> - AL_EXIT( AL_DBG_CM );
> - return IB_PENDING;
> - }
> }
>
> /* Queue this MAD for processing. */
> @@ -3628,8 +3587,6 @@ __create_cep()
>
> p_cep->p_cid->p_cep = p_cep;
>
> - InitializeListHead( &p_cep->irp_que );
> -
> ref_al_obj( &gp_cep_mgr->obj );
>
> AL_EXIT( AL_DBG_CM );
> @@ -3682,7 +3639,7 @@ kal_cep_alloc(
> return IB_SUCCESS;
> }
>
> -void
> +ib_api_status_t
> kal_cep_config(
> IN ib_al_handle_t
> h_al,
> IN net32_t
> cid,
> @@ -3695,13 +3652,18 @@ kal_cep_config(
>
> KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> p_cep = __lookup_cep( h_al, cid );
> - CL_ASSERT( p_cep );
> + if( p_cep == NULL )
> + {
> + KeReleaseInStackQueuedSpinLock( &hdl );
> + return IB_INVALID_HANDLE;
> + }
>
> p_cep->pfn_cb = pfn_cb;
> p_cep->context = context;
> p_cep->pfn_destroy_cb = pfn_destroy_cb;
>
> KeReleaseInStackQueuedSpinLock( &hdl );
> + return IB_SUCCESS;
> }
>
> static inline void
> @@ -4128,7 +4090,7 @@ al_create_cep(
> status = kal_cep_alloc(h_al, p_cid);
> if ( status == IB_SUCCESS )
> {
> - kal_cep_config(h_al, *p_cid, pfn_cb, context,
> pfn_destroy_cb);
> + status = kal_cep_config(h_al, *p_cid, pfn_cb,
> context, pfn_destroy_cb);
> }
>
> AL_EXIT( AL_DBG_CM );
> @@ -4174,28 +4136,6 @@ al_destroy_cep(
> context = p_cep->context;
> pfn_destroy_cb = p_cep->pfn_destroy_cb;
>
> - /* Cancel any queued IRP */
> - __cep_complete_irp( p_cep, STATUS_CANCELLED,
> IO_NO_INCREMENT );
> -
> - while( !IsListEmpty( &p_cep->irp_que ) )
> - {
> - LIST_ENTRY* p_list_entry;
> - IRP* p_irp;
> -
> - // get IRP
> - p_list_entry = RemoveHeadList( &p_cep->irp_que );
> - p_irp = (PIRP)CONTAINING_RECORD( p_list_entry, IRP,
> Tail.Overlay.ListEntry );
> -
> - // complete GetConnectionReq IRP
> -#pragma warning(push, 3)
> - IoSetCancelRoutine( p_irp, NULL );
> -#pragma warning(pop)
> -
> - p_irp->IoStatus.Information = 0;
> - p_irp->IoStatus.Status = STATUS_CANCELLED;
> - IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> - }
> -
> __unbind_cep( p_cep );
> ref_cnt = __cleanup_cep( p_cep );
> if( reusable )
> @@ -4218,9 +4158,35 @@ al_destroy_cep(
> void
> kal_cep_destroy(
> IN ib_al_handle_t
> h_al,
> - IN net32_t
> cid )
> + IN net32_t
> cid,
> + IN NTSTATUS
> status )
> {
> - al_destroy_cep(h_al, &cid, FALSE);
> + KLOCK_QUEUE_HANDLE hdl;
> + kcep_t *p_cep;
> + ib_pfn_destroy_cb_t pfn_destroy_cb;
> + void *context;
> + int32_t ref_cnt;
> +
> + KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> + p_cep = __lookup_cep( h_al, cid );
> + CL_ASSERT( p_cep );
> +
> + context = p_cep->context;
> + pfn_destroy_cb = p_cep->pfn_destroy_cb;
> +
> + __unbind_cep( p_cep );
> + /* Drop new REQs so they can be retried when
> resources may be available */
> + if( status == STATUS_NO_MORE_ENTRIES &&
> + (p_cep->state == CEP_STATE_REQ_RCVD ||
> + p_cep->state == CEP_STATE_REQ_MRA_SENT) )
> + {
> + p_cep->state = CEP_STATE_IDLE;
> + }
> + ref_cnt = __cleanup_cep( p_cep );
> + KeReleaseInStackQueuedSpinLock( &hdl );
> +
> + if( !ref_cnt && pfn_destroy_cb )
> + pfn_destroy_cb( context );
> }
>
>
> @@ -5078,55 +5044,6 @@ out:
>
>
> ib_api_status_t
> -kal_cep_config_pre_rep_copy_cid(
> - IN ib_al_handle_t
> h_al,
> - IN net32_t
> cid,
> - IN al_pfn_cep_cb_t
> pfn_cb,
> - IN void*
> context,
> - IN ib_pfn_destroy_cb_t
> pfn_destroy_cb,
> - IN const iba_cm_rep* const
> p_cm_rep,
> - IN uint8_t
> rnr_nak_timeout,
> - IN OUT net32_t* const
> p_cid,
> - OUT ib_qp_mod_t* const
> p_init )
> -{
> - kcep_t *p_cep;
> - KLOCK_QUEUE_HANDLE hdl;
> - ib_api_status_t status;
> -
> - CL_ASSERT( h_al );
> - CL_ASSERT( p_cm_rep );
> - CL_ASSERT( p_init );
> -
> - KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> - if (*p_cid != AL_INVALID_CID)
> - {
> - status = IB_RESOURCE_BUSY;
> - goto out;
> - }
> -
> - p_cep = __lookup_cep( h_al, cid );
> - if (!p_cep )
> - {
> - status = IB_INVALID_HANDLE;
> - goto out;
> - }
> -
> - status = __al_cep_pre_rep( p_cep, p_cm_rep,
> rnr_nak_timeout, p_init );
> - if ( status == IB_SUCCESS )
> - {
> - p_cep->pfn_cb = pfn_cb;
> - p_cep->context = context;
> - p_cep->pfn_destroy_cb = pfn_destroy_cb;
> - *p_cid = cid;
> - }
> -
> -out:
> - KeReleaseInStackQueuedSpinLock( &hdl );
> - return status;
> -}
> -
> -
> -ib_api_status_t
> kal_cep_pre_rep(
> IN ib_al_handle_t
> h_al,
> IN net32_t
> cid,
> @@ -6678,60 +6595,6 @@ __cep_cancel_ndi_irp(
> AL_EXIT( AL_DBG_CM );
> }
>
> -NTSTATUS
> -al_cep_get_cid(
> - IN ib_al_handle_t
> h_al,
> - IN net32_t const
> cid,
> - IN PIRP
> p_irp
> - )
> -{
> - kcep_t *p_cep;
> - NTSTATUS nt_status;
> - KLOCK_QUEUE_HANDLE hdl;
> - ib_mad_element_t* p_mad = NULL;
> -
> - AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("[ CID =
> %d\n", cid) );
> - KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> -
> - p_cep = __lookup_cep( h_al, cid );
> - if( !p_cep )
> - {
> - p_irp->IoStatus.Information = 0;
> - p_irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
> - IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> - nt_status = STATUS_EVENT_DONE;
> - goto exit;
> - }
> -
> - if( !p_cep->p_mad_head )
> - { /* no pending MADs - queue the IRP */
> - p_cep->signalled = FALSE;
> - InsertTailList( &p_cep->irp_que,
> &p_irp->Tail.Overlay.ListEntry );
> - p_irp->Tail.Overlay.DriverContext[0] =
> (void*)(size_t)cid;
> - p_irp->Tail.Overlay.DriverContext[1] = (void*)h_al;
> -#pragma warning(push, 3)
> - IoSetCancelRoutine( p_irp, __cep_cancel_ndi_irp );
> -#pragma warning(pop)
> - IoMarkIrpPending( p_irp );
> - nt_status = STATUS_PENDING;
> - goto exit;
> - }
> -
> - /* Set the MAD. */
> - p_mad = p_cep->p_mad_head;
> - p_cep->p_mad_head = p_mad->p_next;
> - p_mad->p_next = NULL;
> -
> - /* complete the IRP */
> - __complete_ndi_irp( p_irp, p_mad );
> - nt_status = STATUS_EVENT_DONE;
> -
> -exit:
> - KeReleaseInStackQueuedSpinLock( &hdl );
> - AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("]
> returned %08x\n", nt_status) );
> - return nt_status;
> -}
> -
>
> NTSTATUS
> al_cep_get_pdata(
> @@ -6778,4 +6641,58 @@ al_cep_get_pdata(
> KeReleaseInStackQueuedSpinLock( &hdl );
> AL_EXIT( AL_DBG_CM );
> return STATUS_SUCCESS;
> +}
> +
> +
> +/*
> + * This function is designed to support moving the
> NetorkDirect IRP queue to the CEP
> + * without performing major surgery on the CEP manager.
> + *
> + * It retrieves the context associated with a CEP, using the
> pfn_addref function
> + * to prevent the context from being destroyed after it is returned.
> + *
> + * It returns NULL if there is no context, requiring
> contexts to be pointers.
> + */
> +void*
> +kal_cep_get_context(
> + IN ib_al_handle_t
> h_al,
> + IN net32_t
> cid,
> + IN al_pfn_cep_cb_t
> pfn_cb,
> + IN ib_pfn_destroy_cb_t
> pfn_addref )
> +{
> + kcep_t *p_cep;
> + void* context = NULL;
> + KLOCK_QUEUE_HANDLE hdl;
> +
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("[ CID =
> %d\n", cid) );
> +
> + CL_ASSERT( h_al );
> + CL_ASSERT( pfn_addref );
> +
> + KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> + p_cep = __lookup_cep( h_al, cid );
> + if( !p_cep )
> + {
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> + ("CEP not found for cid %d, h_al
> %p\n", cid, h_al ));
> + goto out;
> + }
> +
> + if( p_cep->pfn_cb != pfn_cb )
> + {
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> + ("CEP callback mismatch for cid %d,
> h_al %p\n", cid, h_al ));
> + goto out;
> + }
> +
> + context = p_cep->context;
> + if( context != NULL )
> + {
> + pfn_addref( context );
> + }
> +
> +out:
> + KeReleaseInStackQueuedSpinLock( &hdl );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("]
> returning %p\n", context) );
> + return context;
> }
> Index: core/al/kernel/al_ndi_cm.c
> ===================================================================
> --- core/al/kernel/al_ndi_cm.c (revision 2061)
> +++ core/al/kernel/al_ndi_cm.c (working copy)
> @@ -81,7 +81,7 @@ __ndi_send_req(
>
> NTSTATUS
> __ndi_send_rep(
> - IN ib_qp_handle_t
> h_qp,
> + IN nd_csq_t
> *p_csq,
> IN PIRP
> p_irp
> );
>
> @@ -90,11 +90,18 @@ __ndi_send_dreq(
> IN IRP*
> p_irp
> );
>
> +NTSTATUS
> +__ndi_get_req(
> + IN nd_csq_t
> *p_csq,
> + IN IRP*
> p_irp
> + );
> +
> static void
> __ndi_queue_drep(
> IN IRP
> *p_irp
> );
>
> +
> /*******************************************************************
> *
> * Helpers
> @@ -123,12 +130,12 @@ static char * State2String(ndi_cm_state_
>
> static inline void
> __ndi_complete_irp(
> - IN ib_qp_handle_t
> h_qp,
> + IN nd_csq_t*
> p_csq,
> IN PIRP
> p_irp,
> IN NTSTATUS
> status
> )
> {
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID =
> %d\n", p_csq->cid) );
>
> CL_ASSERT( p_irp );
> CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] == NULL );
> @@ -144,7 +151,7 @@ __ndi_complete_irp(
> p_irp->IoStatus.Information = 0;
> IoCompleteRequest( p_irp, 0 );
> }
> - deref_al_obj( &h_qp->obj ); /* Release IRP reference */
> + nd_csq_release( p_csq ); /* Release IRP reference */
>
> AL_EXIT( AL_DBG_NDI );
> }
> @@ -159,23 +166,28 @@ __ndi_complete_irp(
> */
> static void
> __cep_timewait_qp(
> - IN const ib_qp_handle_t
> h_qp )
> + IN nd_csq_t
> *p_csq )
> {
> uint64_t timewait = 0;
> + ib_qp_handle_t h_qp;
> ib_qp_mod_t qp_mod;
> ib_api_status_t status;
>
> AL_ENTER( AL_DBG_CM );
>
> - CL_ASSERT( h_qp );
> + CL_ASSERT( p_csq != NULL );
>
> /*
> * The CM should have set the proper timewait
> time-out value. Reset
> * the QP and let it enter the timewait state.
> */
> - if( al_cep_get_timewait( h_qp->obj.h_al,
> - ((al_conn_qp_t*)h_qp)->cid, &timewait ) ==
> IB_SUCCESS )
> + if( al_cep_get_timewait( p_csq->h_al, p_csq->cid,
> &timewait ) == IB_SUCCESS )
> {
> + h_qp = CONTAINING_RECORD(
> + al_hdl_ref( p_csq->h_al, p_csq->h_qp,
> AL_OBJ_TYPE_H_QP ),
> + ib_qp_t,
> + obj );
> +
> /* Special checks on the QP state for error
> handling - see above. */
> if( !h_qp || !AL_OBJ_IS_TYPE( h_qp,
> AL_OBJ_TYPE_H_QP ) ||
> ( (h_qp->obj.state != CL_INITIALIZED) &&
> @@ -192,16 +204,16 @@ __cep_timewait_qp(
> status = h_qp->pfn_modify_qp( h_qp, &qp_mod, NULL );
> if( status != IB_SUCCESS )
> {
> - AL_PRINT_EXIT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR,
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> ("pfn_modify_qp to
> IB_QPS_ERROR returned %s\n",
> ib_get_err_str( status )) );
> - return;
> }
> -
> -#ifdef CL_KERNEL
> - /* Store the timestamp after which the QP
> exits timewait. */
> - h_qp->timewait = cl_get_time_stamp() + timewait;
> -#endif /* CL_KERNEL */
> + else
> + {
> + /* Store the timestamp after which
> the QP exits timewait. */
> + h_qp->timewait = cl_get_time_stamp()
> + timewait;
> + }
> + deref_al_obj( &h_qp->obj );
> }
>
> AL_EXIT( AL_DBG_CM );
> @@ -209,22 +221,39 @@ __cep_timewait_qp(
>
> static ib_api_status_t
> __ndi_qp2rts(
> - IN ib_qp_handle_t const
> h_qp,
> + IN nd_csq_t*
> p_csq,
> IN PIRP
> p_irp
> )
> {
> ib_api_status_t status;
> + ib_qp_handle_t h_qp;
> ib_qp_mod_t qp_mod;
>
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("[ CID = %d\n", p_csq->cid) );
> +
> + h_qp = CONTAINING_RECORD(
> + al_hdl_ref( p_csq->h_al, p_csq->h_qp,
> AL_OBJ_TYPE_H_QP ),
> + ib_qp_t,
> + obj );
> + if( h_qp == NULL )
> + {
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> + ("Bad QP %I64d\n", p_csq->h_qp) );
> + status = IB_INVALID_HANDLE;
> + goto err;
> + }
> +
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("QP %p state %d\n", h_qp, h_qp->state) );
>
> /* fill required qp attributes */
> - status = al_cep_get_rtr_attr( qp_get_al( h_qp ),
> - ((al_conn_qp_t*)h_qp)->cid, &qp_mod );
> + status = al_cep_get_rtr_attr( p_csq->h_al,
> p_csq->cid, &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 )) );
> + ("al_cep_get_rtr_attr for CID %d
> returned %s\n",
> + p_csq->cid, ib_get_err_str( status )) );
> goto exit;
> }
>
> @@ -234,17 +263,18 @@ __ndi_qp2rts(
> 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) ) );
> + ("ndi_modify_qp %p from %d to RTR
> returned %s.\n",
> + h_qp, h_qp->state, 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, &qp_mod );
> + status = al_cep_get_rts_attr( p_csq->h_al,
> p_csq->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 )) );
> + ("al_cep_get_rts_attr for CID %d
> returned %s\n",
> + p_csq->cid, ib_get_err_str( status )) );
> goto exit;
> }
>
> @@ -254,10 +284,13 @@ __ndi_qp2rts(
> 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) ) );
> + ("ndi_modify_qp %p from %d to RTS
> returned %s.\n",
> + h_qp, h_qp->state, ib_get_err_str(status) ) );
> }
>
> exit:
> + deref_al_obj( &h_qp->obj );
> +err:
> AL_EXIT( AL_DBG_NDI );
> return status;
> }
> @@ -277,11 +310,15 @@ static NTSTATUS __ndi_insert_irp_ex(
> )
> {
> NTSTATUS status;
> - ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)pCsq;
> + nd_csq_t *p_ndi_csq = CONTAINING_RECORD( pCsq,
> nd_csq_t, csq );
>
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID =
> %d\n", p_ndi_csq->cid) );
> switch( (ULONG_PTR)Context )
> {
> + case NDI_CM_LISTEN:
> + status = __ndi_get_req( p_ndi_csq, pIrp );
> + break;
> +
> case NDI_CM_CONNECTING_QPR_SENT:
> status = __ndi_pr_query( pIrp );
> break;
> @@ -290,24 +327,38 @@ static NTSTATUS __ndi_insert_irp_ex(
> status = __ndi_send_req( pIrp );
> break;
>
> - case NDI_CM_CONNECTING_REP_SENT:
> - status = __ndi_send_rep( p_ndi_csq->h_qp, pIrp );
> - break;
> -
> case NDI_CM_DISCONNECTING:
> status = __ndi_send_dreq( pIrp );
> break;
>
> + case NDI_CM_CONNECTED_DREQ_RCVD:
> + if( p_ndi_csq->state == NDI_CM_LISTEN )
> + {
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_NDI,
> + ("] Invalid state (%d).\n",
> p_ndi_csq->state) );
> + return STATUS_INVALID_DEVICE_REQUEST;
> + }
> +
> + /*
> + * Overwrite the context so that the state change
> + * below turns into a noop.
> + */
> + Context = (VOID*)(ULONG_PTR)p_ndi_csq->state;
> + status = STATUS_PENDING;
> + break;
> +
> default:
> status = STATUS_INVALID_DEVICE_REQUEST;
> ASSERT( FALSE );
> }
>
> - if( status == STATUS_SUCCESS )
> + ASSERT( status == STATUS_PENDING || !NT_SUCCESS( status ) );
> + if( NT_SUCCESS( status ) )
> {
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> ("] Queueing IRP\n") );
> p_ndi_csq->state = (ndi_cm_state_t)(ULONG_PTR)Context;
> InsertTailList( &p_ndi_csq->queue,
> &pIrp->Tail.Overlay.ListEntry );
> - ref_al_obj( &p_ndi_csq->h_qp->obj ); /* Take
> IRP reference. */
> + nd_csq_ref( p_ndi_csq ); /* Take IRP reference. */
> }
> AL_EXIT( AL_DBG_NDI );
> return status;
> @@ -334,7 +385,7 @@ static PIRP __ndi_peek_next_irp(
> PIRP nextIrp = NULL;
> PLIST_ENTRY nextEntry;
> PLIST_ENTRY listHead;
> - ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> + nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
>
> AL_ENTER( AL_DBG_NDI );
>
> @@ -380,16 +431,12 @@ static PIRP __ndi_peek_next_irp(
>
> static VOID __ndi_acquire_lock(
> IN PIO_CSQ
> Csq,
> - OUT PKIRQL
> Irql
> + OUT PKIRQL
> pIrql
> )
> {
> - ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> - ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
> - UNUSED_PARAM( Irql );
> + nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
>
> - AL_ENTER( AL_DBG_NDI );
> - cl_spinlock_acquire( &h_qp->obj.lock );
> - AL_EXIT( AL_DBG_NDI );
> + KeAcquireSpinLock( &p_ndi_csq->lock, pIrql );
> }
>
> static VOID __ndi_release_lock(
> @@ -397,13 +444,9 @@ static VOID __ndi_release_lock(
> IN KIRQL
> Irql
> )
> {
> - ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> - ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
> - UNUSED_PARAM( Irql );
> + nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
>
> - AL_ENTER( AL_DBG_NDI );
> - cl_spinlock_release( &h_qp->obj.lock );
> - AL_EXIT( AL_DBG_NDI );
> + KeReleaseSpinLock( &p_ndi_csq->lock, Irql );
> }
>
> static VOID __ndi_complete_cancelled_irp(
> @@ -411,8 +454,7 @@ static VOID __ndi_complete_cancelled_irp
> IN PIRP
> p_irp
> )
> {
> - ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> - ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
> + nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
> KIRQL irql;
> ib_query_handle_t h_query;
>
> @@ -427,14 +469,11 @@ static VOID __ndi_complete_cancelled_irp
> * SA callback by the CSQ lock.
> */
> #pragma warning( disable:4305 )
> - h_query = InterlockedExchangePointer(
> &h_qp->p_irp_queue->h_query, NULL );
> + h_query = InterlockedExchangePointer(
> &p_ndi_csq->h_query, NULL );
> #pragma warning( default:4305 )
> if( h_query != NULL )
> al_cancel_sa_req( &h_query->sa_req );
>
> - /* Always try to destroy the CEP. The CEP
> manager handles invalid CIDs. */
> - al_destroy_cep( qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> -
> if( p_ndi_csq->state != NDI_CM_INVALID )
> p_ndi_csq->state = NDI_CM_IDLE;
>
> @@ -443,7 +482,8 @@ static VOID __ndi_complete_cancelled_irp
> __fallthrough;
>
> case UAL_NDI_NOTIFY_DREQ:
> - __ndi_complete_irp( h_qp, p_irp, STATUS_CANCELLED );
> + case UAL_NDI_GET_REQ_CM:
> + __ndi_complete_irp( p_ndi_csq, p_irp,
> STATUS_CANCELLED );
> break;
>
> case UAL_NDI_DREQ_CM:
> @@ -457,138 +497,158 @@ static VOID __ndi_complete_cancelled_irp
>
>
> NTSTATUS
> -ndi_qp_init(
> - IN ib_qp_handle_t
> h_qp )
> +nd_csq_init(
> + IN ib_al_handle_t
> h_al,
> + IN net32_t
> cid,
> + IN uint64_t
> h_qp,
> + OUT nd_csq_t
> **pp_csq )
> {
> -
> + nd_csq_t *p_nd_csq;
> NTSTATUS status;
> + ib_api_status_t ib_status;
>
> AL_ENTER( AL_DBG_NDI );
>
> - if ( h_qp->type != IB_QPT_RELIABLE_CONN )
> - {
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("Only RC QP type is supported \n"));
> - status = STATUS_SUCCESS;
> - goto exit;
> - }
> -
> - h_qp->p_irp_queue =
> (ndi_qp_csq_t*)cl_zalloc(sizeof(ndi_qp_csq_t));
> - if (!h_qp->p_irp_queue)
> + p_nd_csq = (nd_csq_t*)cl_zalloc( sizeof(*p_nd_csq) );
> + if( p_nd_csq == NULL )
> {
> status = STATUS_NO_MEMORY;
> goto exit;
> }
>
> - status = IoCsqInitializeEx( &h_qp->p_irp_queue->csq,
> + KeInitializeSpinLock( &p_nd_csq->lock );
> + InitializeListHead( &p_nd_csq->queue );
> + p_nd_csq->h_al = h_al;
> + p_nd_csq->h_qp = h_qp;
> + p_nd_csq->h_query = NULL;
> + p_nd_csq->state = NDI_CM_IDLE;
> + p_nd_csq->cid = cid;
> +
> + status = IoCsqInitializeEx( &p_nd_csq->csq,
> __ndi_insert_irp_ex, __ndi_remove_irp,
> __ndi_peek_next_irp, __ndi_acquire_lock,
> __ndi_release_lock, __ndi_complete_cancelled_irp );
> if ( !NT_SUCCESS( status ) )
> + {
> + cl_free( p_nd_csq );
> goto exit;
> + }
>
> - InitializeListHead( &h_qp->p_irp_queue->queue );
> - h_qp->p_irp_queue->h_qp = h_qp;
> - h_qp->p_irp_queue->h_query = NULL;
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> + /*
> + * One reference for the CEP, one for the caller (so
> that if the CEP
> + * gets destroyed we don't blow up.)
> + */
> + p_nd_csq->ref_cnt = 2;
> +
> + ib_status = kal_cep_config(
> + h_al, cid, nd_cm_handler, p_nd_csq, nd_csq_release );
> +
> + if( ib_status != IB_SUCCESS )
> + {
> + status = STATUS_UNSUCCESSFUL;
> + cl_free( p_nd_csq );
> + goto exit;
> + }
> +
> + *pp_csq = p_nd_csq;
> status = STATUS_SUCCESS;
>
> -AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("Creating h_qp %#I64x, uhdl %#I64x \n",
> - (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl ) );
> + AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> + ("Creating CSQ %p, uhdl %#I64x \n", p_nd_csq, h_qp) );
>
> exit:
> AL_EXIT( AL_DBG_NDI );
> return status;
> }
>
> -#pragma warning(disable:4706)
> +
> void
> -ndi_qp_destroy(
> - IN ib_qp_handle_t
> h_qp )
> +ndi_cancel_cm_irps(
> + IN nd_csq_t
> *p_nd_csq )
> {
> - KIRQL irql;
> PIRP Irp;
>
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("[ CSQ %p (CID = %d)\n",
> + p_nd_csq, p_nd_csq->cid ) );
>
> - if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)
> + /* cancel pending IRPS for NDI type CQ */
> + AL_ENTER( AL_DBG_NDI );
> + for( Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, NULL );
> + Irp != NULL;
> + Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, NULL ) )
> {
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("Destroying h_qp %#I64x, uhdl
> %#I64x, cid %d\n",
> - (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, ((al_conn_qp_t*)h_qp)->cid ) );
> + __ndi_complete_cancelled_irp( &p_nd_csq->csq, Irp );
> + }
> + for( Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
> + Irp != NULL;
> + Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ ) )
> + {
> + __ndi_complete_cancelled_irp( &p_nd_csq->csq, Irp );
> + }
>
> - /* Move the state before flushing, so that
> all new IRPs fail to queue. */
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - h_qp->p_irp_queue->state = NDI_CM_INVALID;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + AL_EXIT( AL_DBG_NDI );
> +}
>
> - /* cancel pending IRPS for NDI type CQ */
> - AL_ENTER( AL_DBG_NDI );
> - while( Irp = IoCsqRemoveNextIrp(
> &h_qp->p_irp_queue->csq, NULL ) )
> - {
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("h_qp %#I64x, uhdl %#I64x,
> ref_cnt %d\n",
> - (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
>
> - __ndi_complete_cancelled_irp(
> &h_qp->p_irp_queue->csq, Irp );
> - }
> - while( Irp = IoCsqRemoveNextIrp(
> - &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ ) )
> - {
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("h_qp %#I64x, uhdl %#I64x,
> ref_cnt %d\n",
> - (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> +void
> +nd_csq_destroy(
> + IN nd_csq_t
> *p_nd_csq )
> +{
> + KIRQL irql;
>
> - __ndi_complete_cancelled_irp(
> &h_qp->p_irp_queue->csq, Irp );
> - }
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
> - (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> - }
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("[ CSQ %p (CID = %d)\n",
> + p_nd_csq, p_nd_csq->cid ) );
> +
> + /* Move the state before flushing, so that all new
> IRPs fail to queue. */
> + __ndi_acquire_lock( &p_nd_csq->csq, &irql );
> + p_nd_csq->state = NDI_CM_INVALID;
> + __ndi_release_lock( &p_nd_csq->csq, irql );
> +
> + /* cancel pending IRPS */
> + ndi_cancel_cm_irps( p_nd_csq );
> +
> + cl_free( p_nd_csq );
>
> AL_EXIT( AL_DBG_NDI );
> }
> -#pragma warning(default:4706)
>
>
> void
> -ndi_qp_free(
> - IN ib_qp_handle_t
> h_qp )
> +nd_csq_ref( nd_csq_t* p_csq )
> {
> - AL_ENTER( AL_DBG_NDI );
> + InterlockedIncrement( &p_csq->ref_cnt );
> +}
>
> - if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)
> +
> +void
> +nd_csq_release( nd_csq_t* p_csq )
> +{
> + if( InterlockedDecrement( &p_csq->ref_cnt ) == 0 )
> {
> - /* free NDI context */
> - cl_free( h_qp->p_irp_queue );
> - h_qp->p_irp_queue = NULL;
> + nd_csq_destroy( p_csq );
> }
> -
> - AL_EXIT( AL_DBG_NDI );
> }
>
>
> static inline void
> -__ndi_complete_req_irp(
> - IN ib_qp_handle_t
> h_qp,
> - IN NTSTATUS
> code
> - )
> +__ndi_timeout_req_irp(
> + __in nd_csq_t* p_csq )
> {
> PIRP Irp;
> KIRQL irql;
>
> AL_ENTER( AL_DBG_NDI );
> - Irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> - if ( Irp )
> + Irp = IoCsqRemoveNextIrp( &p_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> + if( Irp )
> {
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> - __ndi_complete_irp( h_qp, Irp, code );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state != NDI_CM_INVALID )
> + p_csq->state = NDI_CM_IDLE;
> + __ndi_release_lock( &p_csq->csq, irql );
> + __ndi_complete_irp( p_csq, Irp, STATUS_TIMEOUT );
> }
> - al_destroy_cep( qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> AL_EXIT( AL_DBG_NDI );
> }
>
> @@ -600,38 +660,41 @@ __ndi_complete_req_irp(
>
> static void
> __ndi_notify_dreq(
> - IN ib_qp_handle_t const
> h_qp )
> + __in nd_csq_t* p_csq )
> {
> - IRP *p_irp = IoCsqRemoveNextIrp(
> - &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
> -
> - if( p_irp )
> + IRP *p_irp;
> + do
> {
> - __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );
> - }
> + p_irp = IoCsqRemoveNextIrp(
> + &p_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
> +
> + if( p_irp )
> + {
> + __ndi_complete_irp( p_csq, p_irp,
> STATUS_SUCCESS );
> + }
> +
> + } while ( p_irp );
> }
>
>
> static void
> __ndi_proc_dreq(
> - IN ib_qp_handle_t const
> h_qp )
> + IN nd_csq_t
> *p_csq)
> {
> IRP *p_irp;
> KIRQL irql;
> - ndi_cm_state_t old_state;
>
> - __ndi_notify_dreq( h_qp );
> + __ndi_notify_dreq( p_csq );
>
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - old_state = h_qp->p_irp_queue->state;
> - if( old_state == NDI_CM_CONNECTED )
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state == NDI_CM_CONNECTED )
> {
> - h_qp->p_irp_queue->state = NDI_CM_CONNECTED_DREQ_RCVD;
> + p_csq->state = NDI_CM_CONNECTED_DREQ_RCVD;
> }
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_release_lock( &p_csq->csq, irql );
>
> p_irp = IoCsqRemoveNextIrp(
> - &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
> + &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
> if( p_irp != NULL )
> {
> __ndi_queue_drep( p_irp );
> @@ -645,7 +708,7 @@ __ndi_proc_dreq(
> */
> static void
> __ndi_proc_rej(
> - IN ib_qp_handle_t const
> h_qp,
> + IN nd_csq_t*
> p_csq,
> IN const mad_cm_rej_t* const
> p_rej )
> {
> KIRQL irql;
> @@ -654,73 +717,135 @@ __ndi_proc_rej(
> AL_ENTER( AL_DBG_NDI );
>
> AL_PRINT(TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("p_rej %p, h_qp %#I64x, uhdl %#I64x, connect
> reject, reason=%hd\n",
> - p_rej, (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, cl_ntoh16(p_rej->reason) ) );
> + ("p_rej %p, CID=%d, uhdl %#I64x, connect
> reject, reason=%hd\n",
> + p_rej, p_csq->cid, p_csq->h_qp,
> cl_ntoh16(p_rej->reason) ) );
>
> - p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, NULL );
> - __ndi_notify_dreq( h_qp );
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> + p_irp = IoCsqRemoveNextIrp( &p_csq->csq, NULL );
> + __ndi_notify_dreq( p_csq );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> if( p_irp != NULL )
> {
> switch( cl_ioctl_ctl_code( p_irp ) )
> {
> case UAL_NDI_REQ_CM:
> - if( h_qp->p_irp_queue->state !=
> NDI_CM_INVALID )
> - h_qp->p_irp_queue->state =
> NDI_CM_IDLE;
> - if( p_rej->reason == IB_REJ_TIMEOUT )
> - __ndi_complete_irp( h_qp,
> p_irp, STATUS_TIMEOUT );
> + if( p_csq->state != NDI_CM_INVALID )
> + p_csq->state = NDI_CM_IDLE;
> + if( p_rej->reason == IB_REJ_USER_DEFINED )
> + __ndi_complete_irp( p_csq,
> p_irp, STATUS_CONNECTION_REFUSED );
> else
> - __ndi_complete_irp( h_qp,
> p_irp, STATUS_CONNECTION_REFUSED );
> + __ndi_complete_irp( p_csq,
> p_irp, STATUS_TIMEOUT );
>
> - al_destroy_cep(
> - qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> + /* We leave the CEP active so that
> the private data can be retrieved. */
> break;
>
> case UAL_NDI_DREQ_CM:
> __ndi_queue_drep( p_irp );
> break;
> +
> + case UAL_NDI_NOTIFY_DREQ:
> + __ndi_complete_irp( p_csq, p_irp,
> STATUS_CONNECTION_ABORTED );
> + break;
> +
> + default:
> + ASSERT( cl_ioctl_ctl_code( p_irp ) ==
> UAL_NDI_REQ_CM ||
> + cl_ioctl_ctl_code( p_irp ) ==
> UAL_NDI_DREQ_CM ||
> + cl_ioctl_ctl_code( p_irp ) ==
> UAL_NDI_NOTIFY_DREQ );
> }
> }
> - else if( h_qp->p_irp_queue->state == NDI_CM_CONNECTED )
> + else if( p_csq->state == NDI_CM_CONNECTED ||
> p_csq->state == NDI_CM_CONNECTING_REQ_RCVD )
> {
> - if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> - h_qp->p_irp_queue->state =
> NDI_CM_CONNECTED_DREQ_RCVD;
> + p_csq->state = NDI_CM_CONNECTED_DREQ_RCVD;
> + }
> + __ndi_release_lock( &p_csq->csq, irql );
> +
> + AL_EXIT( AL_DBG_NDI );
> +}
> +
> +
> +static void
> +__ndi_proc_req(
> + IN nd_csq_t*
> p_csq,
> + IN net32_t
> new_cid,
> + IN ib_mad_element_t
> *p_mad )
> +{
> + IRP* p_irp;
> + KIRQL irql;
> + NTSTATUS status;
> + nd_csq_t* p_new_csq;
> +
> + AL_ENTER( AL_DBG_NDI );
> +
> + AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("CID
> = %d\n", p_csq->cid));
> +
> + status = nd_csq_init( p_csq->h_al, new_cid, 0, &p_new_csq );
> + if( status != STATUS_SUCCESS )
> + {
> + // Ignore the request.
> + kal_cep_destroy( p_csq->h_al, new_cid,
> STATUS_NO_MORE_ENTRIES );
> + ib_put_mad( p_mad );
> + return;
> + }
> +
> + __ndi_acquire_lock( &p_new_csq->csq, &irql );
> + p_new_csq->state = NDI_CM_CONNECTING_REQ_RCVD;
> + __ndi_release_lock( &p_new_csq->csq, irql );
> + nd_csq_release( p_new_csq );
> +
> + p_irp = IoCsqRemoveNextIrp( &p_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_GET_REQ_CM );
> + if( p_irp == NULL )
> + {
> + p_mad->send_context1 = (VOID*)(ULONG_PTR)new_cid;
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->p_mad_head == NULL )
> + {
> + p_csq->p_mad_head = p_mad;
> + }
> + else
> + {
> + p_csq->p_mad_tail->p_next = p_mad;
> + }
> + p_csq->p_mad_tail = p_mad;
> + __ndi_release_lock( &p_csq->csq, irql );
> + }
> + else
> + {
> + *(net32_t*)cl_ioctl_out_buf( p_irp ) = new_cid;
> + __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );
> + ib_put_mad( p_mad );
> }
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
>
> AL_EXIT( AL_DBG_NDI );
> + return;
> }
>
>
> static void
> __ndi_proc_rep(
> - IN ib_qp_handle_t const
> h_qp,
> - IN net32_t
> cid )
> + IN nd_csq_t*
> p_csq )
> {
> - ndi_qp_csq_t *p_ndi_csq = h_qp->p_irp_queue;
> IRP* p_irp;
> KIRQL irql;
>
> AL_ENTER( AL_DBG_NDI );
>
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("h_qp
> = 0x%p\n", h_qp));
> + AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("CID
> = %d\n", p_csq->cid));
>
> - p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> - __ndi_acquire_lock( &p_ndi_csq->csq, &irql );
> + p_irp = IoCsqRemoveNextIrp( &p_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> if( p_irp == NULL )
> {
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("Not the expected state %s\n",
> State2String( p_ndi_csq->state )));
> - CL_ASSERT( IsListEmpty( &h_qp->p_irp_queue->queue ) );
> - al_cep_rej( qp_get_al( h_qp ), cid,
> IB_REJ_INVALID_COMM_INSTANCE, NULL, 0, NULL, 0 );
> + ("Not the expected state %s\n",
> State2String( p_csq->state )));
> + CL_ASSERT( IsListEmpty( &p_csq->queue ) );
> + al_cep_rej( p_csq->h_al, p_csq->cid,
> IB_REJ_INVALID_COMM_INSTANCE, NULL, 0, NULL, 0 );
> }
> else
> {
> - p_ndi_csq->state = NDI_CM_CONNECTING_REP_RCVD;
> + p_csq->state = NDI_CM_CONNECTING_REP_RCVD;
>
> - __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );
> + __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );
> }
> - __ndi_release_lock( &p_ndi_csq->csq, irql );
> + __ndi_release_lock( &p_csq->csq, irql );
>
> AL_EXIT( AL_DBG_NDI );
> return;
> @@ -732,7 +857,8 @@ __ndi_do_drep(
> IN DEVICE_OBJECT*
> p_dev_obj,
> IN PIRP
> p_irp )
> {
> - ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
> + nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];
> + ib_qp_handle_t h_qp;
> ib_qp_mod_t qp_mod;
> ib_api_status_t status;
> uint64_t timewait_us;
> @@ -746,11 +872,8 @@ __ndi_do_drep(
> CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] );
> IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
> - deref_al_obj( &h_qp->obj ); /* Release work item reference. */
> -
> - status = al_cep_get_timewait( qp_get_al( h_qp ),
> - ((al_conn_qp_t*)h_qp)->cid, &timewait_us );
>
> + status = al_cep_get_timewait( p_csq->h_al,
> p_csq->cid, &timewait_us );
> if (status != IB_SUCCESS)
> {
> nt_status = STATUS_CONNECTION_INVALID;
> @@ -758,31 +881,44 @@ __ndi_do_drep(
> }
>
> /* Store the timestamp after which the QP exits timewait. */
> - h_qp->timewait = cl_get_time_stamp() + timewait_us;
> + h_qp = CONTAINING_RECORD(
> + al_hdl_ref( p_csq->h_al, p_csq->h_qp,
> AL_OBJ_TYPE_H_QP ),
> + ib_qp_t,
> + obj );
> + if( h_qp != NULL )
> + {
> + h_qp->timewait = cl_get_time_stamp() + timewait_us;
> + }
>
> - al_destroy_cep( qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> + /* Send the DREP. */
> + al_cep_drep( p_csq->h_al, p_csq->cid, NULL, 0 );
>
> /* bring QP to error state */
> - cl_memclr( &qp_mod, sizeof(qp_mod) );
> - qp_mod.req_state = IB_QPS_ERROR;
> -
> - status = ndi_modify_qp( h_qp, &qp_mod,
> - cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf(
> p_irp ) );
> - if ( status != IB_SUCCESS )
> + if( h_qp != NULL )
> {
> - AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("ndi_modify_qp to ERROR returned
> %s.\n", ib_get_err_str(status) ) );
> + cl_memclr( &qp_mod, sizeof(qp_mod) );
> + qp_mod.req_state = IB_QPS_ERROR;
> +
> + 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 ERROR
> returned %s.\n", ib_get_err_str(status) ) );
> + }
> + deref_al_obj( &h_qp->obj );
> }
>
> nt_status = ib_to_ntstatus( status );
>
> exit:
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state != NDI_CM_INVALID )
> + p_csq->state = NDI_CM_IDLE;
> + __ndi_release_lock( &p_csq->csq, irql );
>
> - __ndi_complete_irp( h_qp, p_irp, nt_status );
> + __ndi_complete_irp( p_csq, p_irp, nt_status );
> + nd_csq_release( p_csq ); /* Release work item reference. */
> AL_EXIT( AL_DBG_NDI );
> }
>
> @@ -799,16 +935,17 @@ __ndi_queue_drep(
>
> static void
> __ndi_proc_drep(
> - IN ib_qp_handle_t const
> h_qp )
> + IN nd_csq_t*
> p_csq )
> {
> IRP* p_irp;
>
> AL_ENTER( AL_DBG_NDI );
>
> p_irp = IoCsqRemoveNextIrp(
> - &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
> + &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
> if( p_irp != NULL )
> {
> + CL_ASSERT(
> p_irp->Tail.Overlay.DriverContext[0] == p_csq );
> __ndi_queue_drep( p_irp );
> }
>
> @@ -816,8 +953,8 @@ __ndi_proc_drep(
> }
>
>
> -static void
> -__ndi_cm_handler(
> +void
> +nd_cm_handler(
> IN const ib_al_handle_t
> h_al,
> IN const net32_t
> cid )
> {
> @@ -829,8 +966,11 @@ __ndi_cm_handler(
>
> while( al_cep_poll( h_al, cid, &context, &new_cid,
> &p_mad_el ) == IB_SUCCESS )
> {
> - ib_mad_t*p_mad = ib_get_mad_buf( p_mad_el );
> - ib_qp_handle_t h_qp = (ib_qp_handle_t)context;
> + ib_mad_t* p_mad = ib_get_mad_buf( p_mad_el );
> + nd_csq_t* p_csq = (nd_csq_t*)context;
> +
> + CL_ASSERT( p_csq != NULL );
> + CL_ASSERT( p_csq->cid == cid );
>
> if( p_mad_el->status != IB_SUCCESS )
> {
> @@ -838,28 +978,28 @@ __ndi_cm_handler(
> {
> case CM_REQ_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("REQ timeouted for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> - __ndi_complete_req_irp( h_qp,
> STATUS_TIMEOUT );
> + ("REQ timed out for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_timeout_req_irp( p_csq );
> break;
>
> case CM_REP_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("REP timeouted for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> + ("REP timed out for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> break;
>
> case CM_DREQ_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("DREQ timeouted for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> - __ndi_proc_drep( h_qp );
> + ("DREQ timed out for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_proc_drep( p_csq );
> break;
>
> default:
> AL_PRINT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR,
> ("Unhandled failed
> MAD attr ID %d for CEP with cid %d, h_al %p, context %p,
> new_cid %d .\n",
> - p_mad->attr_id, cid,
> h_al, h_qp, new_cid ) );
> + p_mad->attr_id, cid,
> h_al, p_csq, new_cid ) );
> break;
> }
> }
> @@ -867,50 +1007,51 @@ __ndi_cm_handler(
> {
> switch( p_mad->attr_id )
> {
> + case CM_REQ_ATTR_ID:
> + AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> + ("REQ received for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_proc_req( p_csq,
> new_cid, p_mad_el );
> + continue;
> +
> case CM_REP_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("REP received for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> - CL_ASSERT(
> ((al_conn_qp_t*)h_qp)->cid == (int32_t)cid ||
> -
> ((al_conn_qp_t*)h_qp)->cid == AL_INVALID_CID ||
> -
> ((al_conn_qp_t*)h_qp)->cid == AL_RESERVED_CID );
> - __ndi_proc_rep( h_qp, cid );
> + ("REP received for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_proc_rep( p_csq );
> break;
>
> case CM_REJ_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("REJ received for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> - __ndi_proc_rej( h_qp,
> (mad_cm_rej_t*)p_mad );
> + ("REJ received for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_proc_rej( p_csq,
> (mad_cm_rej_t*)p_mad );
> break;
>
> case CM_DREQ_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("DREQ received for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> - CL_ASSERT(
> ((al_conn_qp_t*)h_qp)->cid == (int32_t)cid ||
> - ((al_conn_qp_t*)h_qp)->cid ==
> AL_INVALID_CID ||
> - ((al_conn_qp_t*)h_qp)->cid ==
> AL_RESERVED_CID );
> - __ndi_proc_dreq( h_qp );
> + ("DREQ received for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_proc_dreq( p_csq );
> break;
>
> case CM_DREP_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("DREP received for
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - cid, h_al, h_qp, new_cid ) );
> - __ndi_proc_drep( h_qp );
> + ("DREP received for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> + __ndi_proc_drep( p_csq );
> break;
>
> case CM_RTU_ATTR_ID:
> AL_PRINT(
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("RTU received for
> CEP with cid %d, h_al %p, context %p, new_cid %d.\n",
> - cid, h_al, h_qp, new_cid ) );
> + ("RTU received for
> CEP with cid %d, h_al %p, context %p.\n",
> + cid, h_al, p_csq ) );
> break;
>
> default:
> AL_PRINT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR,
> ("Unhandled MAD attr
> ID %d for CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> - p_mad->attr_id, cid,
> h_al, h_qp, new_cid ) );
> + p_mad->attr_id, cid,
> h_al, p_csq, new_cid ) );
> }
> }
>
> @@ -922,24 +1063,26 @@ __ndi_cm_handler(
>
> static void
> __ndi_fill_cm_req(
> - IN ib_qp_handle_t const
> h_qp,
> + IN net32_t
> qpn,
> IN ual_ndi_req_cm_ioctl_in_t
> *p_req,
> IN ib_path_rec_t
> *p_path_rec,
> - OUT ib_cm_req_t
> *p_cm_req)
> + OUT iba_cm_req
> *p_cm_req)
> {
> AL_ENTER( AL_DBG_NDI );
>
> - memset( p_cm_req, 0, sizeof(ib_cm_req_t) );
> -
> - p_cm_req->svc_id = IB_REQ_CM_RDMA_SID_PREFIX |
> (p_req->prot << 16) | p_req->dst_port;
> - p_cm_req->max_cm_retries = g_max_cm_retries;
> - p_cm_req->p_primary_path = p_path_rec;
> + memset( p_cm_req, 0, sizeof(*p_cm_req) );
>
> - p_cm_req->p_req_pdata = (uint8_t *)&p_req->pdata;
> - p_cm_req->req_length = sizeof(p_req->pdata);
> + p_cm_req->service_id = IB_REQ_CM_RDMA_SID_PREFIX |
> (p_req->prot << 16) | p_req->dst_port;
> + p_cm_req->p_primary_path = p_path_rec;
>
> + p_cm_req->qpn = qpn;
> p_cm_req->qp_type = IB_QPT_RELIABLE_CONN;
> - p_cm_req->h_qp = h_qp;
> + p_cm_req->starting_psn = qpn;
> +
> + p_cm_req->p_pdata = (uint8_t *)&p_req->pdata;
> + p_cm_req->pdata_len = sizeof(p_req->pdata);
> +
> + p_cm_req->max_cm_retries = g_max_cm_retries;
> p_cm_req->resp_res = p_req->resp_res;
> p_cm_req->init_depth = p_req->init_depth;
>
> @@ -959,10 +1102,8 @@ __ndi_fill_cm_req(
> else if( p_cm_req->local_resp_timeout < CM_MIN_LOCAL_TIMEOUT )
> p_cm_req->local_resp_timeout = CM_MIN_LOCAL_TIMEOUT;
>
> - p_cm_req->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;
> p_cm_req->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY;
> p_cm_req->retry_cnt = g_qp_retries;
> - p_cm_req->p_alt_path = NULL;
>
> AL_EXIT( AL_DBG_NDI );
> }
> @@ -974,58 +1115,47 @@ __ndi_send_req(
> )
> {
> ib_api_status_t status;
> - ib_qp_handle_t h_qp =
> (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
> + nd_csq_t* p_csq =
> (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];
> ib_path_rec_t *p_path_rec =
> p_irp->Tail.Overlay.DriverContext[1];
> ual_ndi_req_cm_ioctl_in_t *p_req =
> (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
> NTSTATUS nt_status;
> - ib_cm_req_t cm_req;
> - ib_qp_mod_t qp_mod;
> - al_conn_qp_t *p_qp;
> + ib_qp_handle_t h_qp;
> + iba_cm_req cm_req;
>
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("[ CID = %d, h_al %p, context %p\n",
> + p_req->cid, p_csq->h_al, p_csq) );
>
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
>
> - if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_QPR_SENT &&
> - h_qp->p_irp_queue->state != NDI_CM_IDLE )
> + if( p_csq->state != NDI_CM_CONNECTING_QPR_SENT &&
> + p_csq->state != NDI_CM_IDLE )
> {
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("Unexpected state: %d\n",
> h_qp->p_irp_queue->state) );
> + ("Unexpected state: %d\n", p_csq->state) );
> return STATUS_CONNECTION_ACTIVE;
> }
>
> - /* Get a CEP and bind it to the QP. */
> - p_qp = (al_conn_qp_t*)h_qp;
> - cl_spinlock_acquire( &h_qp->obj.lock );
> - if( h_qp->obj.state != CL_DESTROYING && p_qp->cid ==
> AL_INVALID_CID )
> - {
> - status = al_create_cep( qp_get_al( h_qp ),
> __ndi_cm_handler,
> -
> &h_qp->obj, deref_al_obj, &p_qp->cid );
> - }
> - else
> - {
> - status = IB_RESOURCE_BUSY;
> - }
> - cl_spinlock_release( &h_qp->obj.lock );
> - if( status != IB_SUCCESS )
> + h_qp = CONTAINING_RECORD(
> + al_hdl_ref( p_csq->h_al, p_req->h_qp,
> AL_OBJ_TYPE_H_QP ),
> + ib_qp_t,
> + obj );
> + if( !h_qp )
> {
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> + /* The QP was valid when the IOCTL first came in... */
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("al_create_cep returned %s.\n",
> ib_get_err_str( status )) );
> - return ib_to_ntstatus( status );
> + ("Invalid QP: %I64d\n", p_req->h_qp) );
> + return STATUS_CONNECTION_ABORTED;
> }
> - AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> - ("Created Active CEP with cid %d, h_al %p,
> context %p\n",
> - p_qp->cid, qp_get_al( h_qp ), h_qp ) );
> -
> - ref_al_obj( &h_qp->obj ); /* Take CEP reference. */
>
> /* Format ib_cm_req_t structure */
> - __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );
> + __ndi_fill_cm_req( h_qp->num, p_req, p_path_rec, &cm_req );
> + deref_al_obj( &h_qp->obj );
>
> /* prepare CEP for connection */
> - status = al_cep_pre_req( qp_get_al( h_qp ),
> p_qp->cid, &cm_req, &qp_mod );
> + status = kal_cep_pre_req(
> + p_csq->h_al, p_csq->cid, &cm_req,
> QP_ATTRIB_RNR_NAK_TIMEOUT, NULL );
> if( status != STATUS_SUCCESS )
> {
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> @@ -1034,7 +1164,7 @@ __ndi_send_req(
> }
>
> /* send CM REQ */
> - status = al_cep_send_req( qp_get_al( h_qp ), p_qp->cid );
> + status = al_cep_send_req( p_csq->h_al, p_csq->cid );
> if( status != IB_SUCCESS )
> {
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> @@ -1044,11 +1174,9 @@ __ndi_send_req(
>
> /* SUCCESS ! */
> AL_EXIT( AL_DBG_NDI );
> - return STATUS_SUCCESS;
> + return STATUS_PENDING;
>
> error:
> - al_destroy_cep( qp_get_al( h_qp ), &p_qp->cid, TRUE );
> -
> switch( status )
> {
> case IB_INVALID_HANDLE:
> @@ -1063,7 +1191,7 @@ error:
> nt_status = ib_to_ntstatus( status );
> }
>
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> + p_csq->state = NDI_CM_IDLE;
> AL_EXIT( AL_DBG_NDI );
> return nt_status;
> }
> @@ -1076,7 +1204,7 @@ __ndi_pr_query_cb(
> cl_ioctl_handle_t p_irp;
> uint8_t pkt_life;
> ib_path_rec_t *p_path_rec;
> - ib_qp_handle_t h_qp =
> (ib_qp_handle_t)p_query_rec->query_context;
> + nd_csq_t* p_csq = (nd_csq_t*)p_query_rec->query_context;
> NTSTATUS status;
> KIRQL irql;
>
> @@ -1086,22 +1214,22 @@ __ndi_pr_query_cb(
> ("status is %d, count is %d, context %p\n",
> p_query_rec->status,
> p_query_rec->result_cnt,
> p_query_rec->query_context) );
>
> - p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> + p_irp = IoCsqRemoveNextIrp( &p_csq->csq,
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> if( p_irp == NULL )
> {
> goto exit;
> }
>
> #pragma warning( disable:4305 )
> - InterlockedExchangePointer(
> &h_qp->p_irp_queue->h_query, NULL );
> + InterlockedExchangePointer( &p_csq->h_query, NULL );
> #pragma warning( default:4305 )
>
> if( p_query_rec->status != IB_SUCCESS ||
> p_query_rec->result_cnt == 0 )
> {
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state != NDI_CM_INVALID )
> + p_csq->state = NDI_CM_IDLE;
> + __ndi_release_lock( &p_csq->csq, irql );
> switch( p_query_rec->status )
> {
> case IB_TIMEOUT:
> @@ -1129,7 +1257,7 @@ __ndi_pr_query_cb(
> status = STATUS_HOST_UNREACHABLE;
> break;
> }
> - __ndi_complete_irp( h_qp, p_irp, status );
> + __ndi_complete_irp( p_csq, p_irp, status );
> goto exit;
> }
>
> @@ -1148,15 +1276,15 @@ __ndi_pr_query_cb(
> p_irp->Tail.Overlay.DriverContext[1] = p_path_rec;
>
> status = IoCsqInsertIrpEx(
> - &h_qp->p_irp_queue->csq,
> + &p_csq->csq,
> p_irp,
> NULL,
> (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT
> );
> - if( status != STATUS_SUCCESS )
> + if( !NT_SUCCESS( status ) )
> {
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
> - __ndi_complete_irp( h_qp, p_irp, status );
> + __ndi_complete_irp( p_csq, p_irp, status );
> }
> else
> {
> @@ -1164,14 +1292,14 @@ __ndi_pr_query_cb(
> * Release the previous reference because
> IoCsqInsertIrpEx
> * took a new one.
> */
> - deref_al_obj( &h_qp->obj ); /* Release IRP
> reference. */
> + nd_csq_release( p_csq ); /* Release IRP reference. */
> }
>
> exit:
> if( p_query_rec->p_result_mad )
> ib_put_mad( p_query_rec->p_result_mad );
>
> - deref_al_obj( &h_qp->obj ); /* release path query
> reference */
> + nd_csq_release( p_csq ); /* release path query
> reference */
> AL_EXIT( AL_DBG_NDI );
> }
>
> @@ -1190,16 +1318,16 @@ __ndi_pr_query(
> ib_api_status_t status;
> ual_ndi_req_cm_ioctl_in_t *p_req =
> (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
> - ib_qp_handle_t h_qp =
> (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
> + nd_csq_t* p_csq =
> (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];
> ib_gid_pair_t gids;
>
> AL_ENTER( AL_DBG_NDI );
>
> - if ( h_qp->p_irp_queue->state != NDI_CM_IDLE )
> + if ( p_csq->state != NDI_CM_IDLE )
> {
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("STATUS_CONNECTION_ACTIVE: h_qp
> %#I64x, uhdl %#I64x, ref_cnt %d\n",
> - (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> + ("STATUS_CONNECTION_ACTIVE: CID=%d,
> uhdl %#I64x, ref_cnt %d\n",
> + p_csq->cid, p_csq->h_qp, p_csq->ref_cnt ) );
> return STATUS_CONNECTION_ACTIVE;
> }
>
> @@ -1212,41 +1340,50 @@ __ndi_pr_query(
> query_req.timeout_ms = g_sa_timeout;
> query_req.retry_cnt = g_sa_retries;
> query_req.flags = 0; /* IB_FLAGS_SYNC */
> - query_req.query_context = h_qp;
> + query_req.query_context = p_csq;
> query_req.pfn_query_cb = __ndi_pr_query_cb;
>
> AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> ("Query for path from %I64x to %I64x\n",
> p_req->guid, ib_gid_get_guid( &p_req->path.dgid )) );
>
> - ref_al_obj( &h_qp->obj ); /* take path
> query reference */
> - status = ib_query( qp_get_al( h_qp ), &query_req,
> &h_qp->p_irp_queue->h_query );
> + nd_csq_ref( p_csq ); /* take path query
> reference */
> + status = ib_query( p_csq->h_al, &query_req, &p_csq->h_query );
> if( status != IB_SUCCESS )
> {
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> + p_csq->state = NDI_CM_IDLE;
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR, ("ib_query failed (%d)\n", status) );
> - deref_al_obj( &h_qp->obj ); /* release
> path query reference */
> + nd_csq_release( p_csq ); /* release
> path query reference */
> return ib_to_ntstatus( status );
> }
>
> AL_EXIT( AL_DBG_NDI );
> - return STATUS_SUCCESS;
> + return STATUS_PENDING;
> }
>
>
> NTSTATUS
> ndi_req_cm(
> - IN ib_qp_handle_t const
> h_qp,
> + IN ib_al_handle_t
> h_al,
> IN IRP
> *p_irp
> )
> {
> NTSTATUS status;
> + nd_csq_t* p_csq;
> ual_ndi_req_cm_ioctl_in_t *p_req =
> (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
>
> AL_ENTER( AL_DBG_NDI );
>
> - p_irp->Tail.Overlay.DriverContext[0] = (ib_qp_t*)h_qp;
> + p_csq = kal_cep_get_context( h_al, p_req->cid,
> nd_cm_handler, nd_csq_ref );
> + if( p_csq == NULL )
> + {
> + status = nd_csq_init( h_al, p_req->cid,
> p_req->h_qp, &p_csq );
> + if( status != STATUS_SUCCESS )
> + goto err;
> + }
> +
> + p_irp->Tail.Overlay.DriverContext[0] = p_csq;
>
> if( p_req->path.dlid != 0 )
> {
> @@ -1260,7 +1397,7 @@ ndi_req_cm(
>
> p_irp->Tail.Overlay.DriverContext[1] = &p_req->path;
> status = IoCsqInsertIrpEx(
> - &h_qp->p_irp_queue->csq,
> + &p_csq->csq,
> p_irp,
> NULL,
> (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT
> @@ -1269,15 +1406,15 @@ ndi_req_cm(
> else
> {
> status = IoCsqInsertIrpEx(
> - &h_qp->p_irp_queue->csq,
> + &p_csq->csq,
> p_irp,
> NULL,
> (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_QPR_SENT
> );
> }
> - if( status == STATUS_SUCCESS )
> - status = STATUS_PENDING;
>
> + nd_csq_release( p_csq );
> +err:
> AL_EXIT( AL_DBG_NDI );
> return status;
> }
> @@ -1295,7 +1432,7 @@ __ndi_do_rtu(
> IN PIRP
> p_irp )
> {
> ib_api_status_t status;
> - ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
> + nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];
> KIRQL irql;
> NTSTATUS nt_status;
>
> @@ -1308,67 +1445,67 @@ __ndi_do_rtu(
> {
> IoFreeWorkItem(
> p_irp->Tail.Overlay.DriverContext[1] );
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
> - deref_al_obj( &h_qp->obj ); /* Release work
> item reference. */
> + nd_csq_release( p_csq ); /* Release work item
> reference. */
> }
>
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_REP_RCVD )
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state != NDI_CM_CONNECTING_REP_RCVD )
> {
> + __ndi_release_lock( &p_csq->csq, irql );
> nt_status = STATUS_CONNECTION_ABORTED;
> goto exit;
> }
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_release_lock( &p_csq->csq, irql );
>
> /* change the QP state to RTS */
> - status = __ndi_qp2rts( h_qp, p_irp );
> -
> + status = __ndi_qp2rts( p_csq, p_irp );
> if ( status != IB_SUCCESS )
> {
> goto err;
> }
>
> /* send RTU */
> - status = al_cep_rtu( qp_get_al( h_qp ),
> ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );
> + status = al_cep_rtu( p_csq->h_al, p_csq->cid, NULL, 0 );
> if( status != IB_SUCCESS )
> {
> err:
> - /* Reject and abort the connection. */
> - al_cep_rej(
> - qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid,
> - IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> -
> - __cep_timewait_qp( h_qp );
> + /*
> + * Reject the connection. Note that we don't
> free the CEP since the
> + * usermode INDConnector object references
> it, and the CEP will be
> + * freed when that object is freed.
> + */
> + al_cep_rej( p_csq->h_al, p_csq->cid,
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
>
> - al_destroy_cep( qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> + __cep_timewait_qp( p_csq );
>
> AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> ("al_cep_rtu returned %s.\n",
> ib_get_err_str( status )) );
>
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state != NDI_CM_INVALID )
> + p_csq->state = NDI_CM_IDLE;
> + __ndi_release_lock( &p_csq->csq, irql );
>
> nt_status = STATUS_CONNECTION_ABORTED;
> goto exit;
> }
>
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state == NDI_CM_CONNECTING_REP_RCVD )
> - h_qp->p_irp_queue->state = NDI_CM_CONNECTED;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state == NDI_CM_CONNECTING_REP_RCVD )
> + p_csq->state = NDI_CM_CONNECTED;
> + __ndi_release_lock( &p_csq->csq, irql );
>
> nt_status = STATUS_SUCCESS;
>
> exit:
> - __ndi_complete_irp( h_qp, p_irp, nt_status );
> + __ndi_complete_irp( p_csq, p_irp, nt_status );
> AL_EXIT( AL_DBG_NDI );
> }
>
>
> cl_status_t
> ndi_rtu_cm(
> - IN ib_qp_handle_t const
> h_qp,
> + IN nd_csq_t
> *p_csq,
> IN PIRP
> p_irp
> )
> {
> @@ -1376,16 +1513,16 @@ ndi_rtu_cm(
>
> AL_ENTER( AL_DBG_NDI );
>
> - p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> + p_irp->Tail.Overlay.DriverContext[0] = p_csq;
> + nd_csq_ref( p_csq ); /* Take IRP reference. */
> p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
> p_irp->Tail.Overlay.DriverContext[1] =
> IoAllocateWorkItem( p_io_stack->DeviceObject );
> - ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
>
> IoMarkIrpPending( p_irp );
> if ( p_irp->Tail.Overlay.DriverContext[1] )
> { /* asyncronous performing */
> /* take a ref to prevent QP destroy before
> calling work item */
> - ref_al_obj( &h_qp->obj ); /* Take work item
> reference. */
> + nd_csq_ref( p_csq ); /* Take work item reference. */
> IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],
> __ndi_do_rtu, DelayedWorkQueue, p_irp );
> }
> @@ -1410,73 +1547,75 @@ __ndi_do_rep(
> IN DEVICE_OBJECT*
> p_dev_obj,
> IN PIRP
> p_irp )
> {
> - ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
> + nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];
> ib_api_status_t status;
> - ual_ndi_rep_cm_ioctl_in_t *p_rep;
> KIRQL irql;
> NTSTATUS nt_status;
>
> UNUSED_PARAM(p_dev_obj);
>
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID =
> %d\n", p_csq->cid) );
>
> /* free the work item if any */
> CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] != NULL );
> IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
> - deref_al_obj( &h_qp->obj ); /* Release work item reference. */
> -
> - p_rep = (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
>
> /* change the QP state to RTS */
> - status = __ndi_qp2rts( h_qp, p_irp );
> + status = __ndi_qp2rts( p_csq, p_irp );
> if ( status != IB_SUCCESS )
> {
> goto err;
> }
>
> /* send REP */
> - status = al_cep_send_rep ( qp_get_al( h_qp ), p_rep->cid );
> + status = al_cep_send_rep ( p_csq->h_al, p_csq->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:
> - /* Reject and abort the connection. */
> - al_cep_rej( qp_get_al( h_qp ), p_rep->cid,
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> + /*
> + * Reject the connection. Note that we don't
> free the CEP since the
> + * usermode INDConnector object references
> it, and the CEP will be
> + * freed when that object is freed.
> + */
> + al_cep_rej( p_csq->h_al, p_csq->cid,
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
>
> /* transit QP to error state */
> - __cep_timewait_qp( h_qp );
> -
> - al_destroy_cep( qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> + __cep_timewait_qp( p_csq );
>
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> ("al_cep_rtu returned %s.\n",
> ib_get_err_str( status )) );
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> - h_qp->p_irp_queue->state = NDI_CM_IDLE;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> - if (status == IB_INVALID_STATE)
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state != NDI_CM_INVALID )
> + p_csq->state = NDI_CM_IDLE;
> + __ndi_release_lock( &p_csq->csq, irql );
> + if (status == IB_INVALID_STATE )
> nt_status = STATUS_CONNECTION_ABORTED;
> + /* The HCA driver will return
> IB_INVALID_PARAMETER if the QP is in the wrong state. */
> + else if( status == IB_INVALID_HANDLE ||
> status == IB_INVALID_PARAMETER )
> + nt_status = STATUS_CANCELLED;
> else
> - nt_status =STATUS_INSUFFICIENT_RESOURCES;
> + nt_status = STATUS_INSUFFICIENT_RESOURCES;
> goto exit;
> }
>
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - if( h_qp->p_irp_queue->state == NDI_CM_CONNECTING_REP_SENT )
> - h_qp->p_irp_queue->state = NDI_CM_CONNECTED;
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + if( p_csq->state == NDI_CM_CONNECTING_REP_SENT )
> + p_csq->state = NDI_CM_CONNECTED;
> + __ndi_release_lock( &p_csq->csq, irql );
> nt_status = STATUS_SUCCESS;
>
> exit:
> - __ndi_complete_irp( h_qp, p_irp, nt_status );
> + __ndi_complete_irp( p_csq, p_irp, nt_status );
> + nd_csq_release( p_csq ); /* Release work item reference. */
> AL_EXIT( AL_DBG_NDI );
> }
>
> static void
> __ndi_fill_cm_rep(
> - IN ib_qp_handle_t const
> h_qp,
> + IN net32_t
> qpn,
> IN ual_ndi_rep_cm_ioctl_in_t
> *p_rep,
> OUT iba_cm_rep
> *p_cm_rep)
> {
> @@ -1487,7 +1626,7 @@ __ndi_fill_cm_rep(
> p_cm_rep->p_pdata = p_rep->pdata;
> p_cm_rep->pdata_len = sizeof(p_rep->pdata);
>
> - p_cm_rep->qpn = h_qp->num;
> + p_cm_rep->qpn = qpn;
>
> p_cm_rep->init_depth = p_rep->init_depth;
> p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;
> @@ -1500,20 +1639,29 @@ __ndi_fill_cm_rep(
>
> NTSTATUS
> __ndi_send_rep(
> - IN ib_qp_handle_t
> h_qp,
> + IN nd_csq_t
> *p_csq,
> IN PIRP
> p_irp )
> {
> IO_STACK_LOCATION *p_io_stack;
> + ib_qp_handle_t h_qp;
> iba_cm_rep cm_rep;
> - ib_qp_mod_t qp_mod;
> ib_api_status_t status;
> ual_ndi_rep_cm_ioctl_in_t *p_rep =
> (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
>
> - AL_ENTER( AL_DBG_NDI );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("[ CID = %d\n", p_csq->cid) );
>
> - if( h_qp->p_irp_queue->state != NDI_CM_IDLE )
> + switch( p_csq->state )
> {
> + case NDI_CM_CONNECTING_REQ_RCVD:
> + break;
> +
> + case NDI_CM_CONNECTED_DREQ_RCVD:
> + AL_EXIT( AL_DBG_NDI );
> + return STATUS_CONNECTION_ABORTED;
> +
> + default:
> AL_EXIT( AL_DBG_NDI );
> return STATUS_CONNECTION_ACTIVE;
> }
> @@ -1525,26 +1673,36 @@ __ndi_send_rep(
> AL_EXIT( AL_DBG_NDI );
> return STATUS_NO_MEMORY;
> }
> - ref_al_obj( &h_qp->obj ); /* Take work item reference. */
> + nd_csq_ref( p_csq ); /* Take work item reference. */
>
> - /* Format ib_cm_req_t structure */
> - __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );
> + h_qp = CONTAINING_RECORD(
> + al_hdl_ref( p_csq->h_al, p_csq->h_qp,
> AL_OBJ_TYPE_H_QP ),
> + ib_qp_t,
> + obj );
> + if( !h_qp )
> + {
> + /* The QP was valid when the IOCTL first came in... */
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> + ("Invalid QP: %I64d\n", p_rep->h_qp) );
> + status = IB_INVALID_HANDLE;
> + goto err;
> + }
>
> - ref_al_obj( &h_qp->obj ); /* Take CEP reference. */
> + /* Format ib_cm_req_t structure */
> + __ndi_fill_cm_rep( h_qp->num, p_rep, &cm_rep );
> + deref_al_obj( &h_qp->obj );
>
> /* prepare Passive CEP for connection */
> - status = kal_cep_config_pre_rep_copy_cid(
> - qp_get_al( h_qp ), p_rep->cid,
> __ndi_cm_handler, &h_qp->obj, deref_al_obj,
> - &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT,
> &((al_conn_qp_t*)h_qp)->cid, &qp_mod);
> + status = kal_cep_pre_rep(
> + p_csq->h_al, p_csq->cid, &cm_rep,
> QP_ATTRIB_RNR_NAK_TIMEOUT, NULL );
> if( status != IB_SUCCESS )
> {
> + AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> + ("kal_cep_pre_rep returned %s.\n",
> ib_get_err_str( status )) );
> +err:
> IoFreeWorkItem(
> p_irp->Tail.Overlay.DriverContext[1] );
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
> - deref_al_obj( &h_qp->obj ); /* Release work
> item reference. */
> - al_destroy_cep( qp_get_al( h_qp ),
> &p_rep->cid, FALSE );
> - deref_al_obj( &h_qp->obj ); /* Release CEP
> reference. */
> - AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("kal_cep_config_pre_rep_copy_cid
> returned %s.\n", ib_get_err_str( status )) );
> + nd_csq_release( p_csq ); /* Release work item
> reference. */
> switch (status)
> {
> case IB_INVALID_HANDLE:
> @@ -1560,7 +1718,7 @@ __ndi_send_rep(
>
> AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> ("Prepared Passive CEP with cid %d, h_al %p,
> context %p\n",
> - p_rep->cid, qp_get_al( h_qp ), h_qp ) );
> + p_csq->cid, p_csq->h_al, h_qp ) );
>
> /*
> * transfer work to a worker thread so that QP
> transitions can be done
> @@ -1570,39 +1728,52 @@ __ndi_send_rep(
> __ndi_do_rep, DelayedWorkQueue, p_irp );
>
> AL_EXIT( AL_DBG_NDI );
> - return STATUS_SUCCESS;
> + return STATUS_PENDING;
> }
>
>
> NTSTATUS
> ndi_rep_cm(
> - IN ib_qp_handle_t const
> h_qp,
> + IN ib_al_handle_t
> h_al,
> IN PIRP
> p_irp
> )
> {
> NTSTATUS status;
> + nd_csq_t* p_csq;
> + ual_ndi_rep_cm_ioctl_in_t *p_rep =
> + (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
> KIRQL irql;
>
> AL_ENTER( AL_DBG_NDI );
>
> - p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> + p_csq = kal_cep_get_context( h_al, p_rep->cid,
> nd_cm_handler, nd_csq_ref );
> + if( p_csq == NULL )
> + {
> + status = STATUS_CONNECTION_ABORTED;
> + goto err;
> + }
>
> - __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> - status = __ndi_send_rep( h_qp, p_irp );
> - if( status == STATUS_SUCCESS )
> + p_csq->h_qp = p_rep->h_qp;
> +
> + p_irp->Tail.Overlay.DriverContext[0] = p_csq;
> +
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + status = __ndi_send_rep( p_csq, p_irp );
> + if( status == STATUS_PENDING )
> {
> /*
> * We're going to keep the IRP dangling for a
> bit - take a reference
> * on the QP until it completes.
> */
> - ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
> - h_qp->p_irp_queue->state = NDI_CM_CONNECTING_REP_SENT;
> + nd_csq_ref( p_csq ); /* Take IRP reference. */
> + p_csq->state = NDI_CM_CONNECTING_REP_SENT;
> IoMarkIrpPending( p_irp );
> - status = STATUS_PENDING;
> }
> - __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> + __ndi_release_lock( &p_csq->csq, irql );
>
> - AL_EXIT( AL_DBG_NDI );
> + nd_csq_release( p_csq );
> +err:
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("]
> returning %08x\n", status) );
> return status;
> }
>
> @@ -1620,19 +1791,19 @@ __ndi_send_dreq(
> IN IRP*
> p_irp
> )
> {
> - ib_qp_handle_t h_qp =
> (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
> + nd_csq_t *p_csq =
> (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];
> IO_STACK_LOCATION *p_io_stack;
> ib_api_status_t status;
> NTSTATUS nt_status;
>
> AL_ENTER( AL_DBG_NDI );
>
> - if ( h_qp->p_irp_queue->state != NDI_CM_CONNECTED &&
> - h_qp->p_irp_queue->state !=
> NDI_CM_CONNECTED_DREQ_RCVD )
> + if ( p_csq->state != NDI_CM_CONNECTED &&
> + p_csq->state != NDI_CM_CONNECTED_DREQ_RCVD )
> {
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("STATUS_CONNECTION_ACTIVE: h_qp
> %#I64x, uhdl %#I64x, ref_cnt %d\n",
> - (uint64_t)(ULONG_PTR)h_qp,
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> + ("STATUS_CONNECTION_ACTIVE: CID = %d,
> uhdl %#I64x, ref_cnt %d\n",
> + p_csq->cid, p_csq->h_qp, p_csq->ref_cnt ) );
> return STATUS_CONNECTION_INVALID;
> }
>
> @@ -1648,24 +1819,26 @@ __ndi_send_dreq(
> AL_EXIT( AL_DBG_NDI );
> return STATUS_NO_MEMORY;
> }
> - ref_al_obj( &h_qp->obj ); /* Take work item reference. */
> + nd_csq_ref( p_csq ); /* Take work item reference. */
>
> - status = al_cep_dreq( qp_get_al( h_qp ),
> ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );
> + status = al_cep_dreq( p_csq->h_al, p_csq->cid, NULL, 0 );
> switch( status )
> {
> case IB_INVALID_STATE:
> - /* We might have just received a DREQ, so try
> sending a DREP. */
> - __ndi_queue_drep( p_irp );
> - IoMarkIrpPending( p_irp );
> /*
> * We're going to keep the IRP dangling for a
> bit - take a reference
> - * on the QP until it completes.
> + * on the CSQ until it completes.
> */
> - ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
> + nd_csq_ref( p_csq ); /* Take IRP reference. */
> + /* We might have just received a DREQ, so try
> sending a DREP. */
> + IoMarkIrpPending( p_irp );
> + __ndi_queue_drep( p_irp );
> + AL_EXIT( AL_DBG_NDI );
> + return STATUS_INVALID_DEVICE_STATE;
>
> case IB_SUCCESS:
> AL_EXIT( AL_DBG_NDI );
> - return( ib_to_ntstatus( status ) );
> + return STATUS_PENDING;
>
> case IB_INVALID_HANDLE:
> nt_status = STATUS_CONNECTION_INVALID;
> @@ -1675,7 +1848,7 @@ __ndi_send_dreq(
> }
> IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
> p_irp->Tail.Overlay.DriverContext[1] = NULL;
> - deref_al_obj( &h_qp->obj ); /* Release work item reference. */
> + nd_csq_release( p_csq ); /* Release work item reference. */
> AL_EXIT( AL_DBG_NDI );
> return nt_status;
> }
> @@ -1683,7 +1856,7 @@ __ndi_send_dreq(
>
> NTSTATUS
> ndi_dreq_cm(
> - IN ib_qp_handle_t const
> h_qp,
> + IN nd_csq_t*
> p_csq,
> IN PIRP
> p_irp
> )
> {
> @@ -1691,10 +1864,10 @@ ndi_dreq_cm(
>
> AL_ENTER( AL_DBG_NDI );
>
> - p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> + p_irp->Tail.Overlay.DriverContext[0] = p_csq;
>
> status = IoCsqInsertIrpEx(
> - &h_qp->p_irp_queue->csq,
> + &p_csq->csq,
> p_irp,
> NULL,
> (VOID*)(ULONG_PTR)NDI_CM_DISCONNECTING
> @@ -1706,10 +1879,136 @@ ndi_dreq_cm(
> * The IRP should never be queued if the work item is
> queued, so
> * we trap the special error code for INVALID_STATE.
> */
> - if( status == STATUS_SUCCESS || status ==
> STATUS_INVALID_DEVICE_STATE )
> + if( status == STATUS_INVALID_DEVICE_STATE )
> status = STATUS_PENDING;
>
> AL_EXIT( AL_DBG_NDI );
> return status;
> }
> +
> +
> +NTSTATUS
> +ndi_listen_cm(
> + IN ib_al_handle_t
> h_al,
> + IN ib_cep_listen_t
> *p_listen,
> + OUT net32_t
> *p_cid,
> + OUT size_t
> *p_ret_bytes
> + )
> +{
> + NTSTATUS status;
> + net32_t cid;
> + ib_api_status_t ib_status;
> + nd_csq_t *p_csq;
> + KIRQL irql;
> +
> + AL_ENTER( AL_DBG_NDI );
> +
> + ib_status = al_create_cep( h_al, NULL, NULL, NULL, &cid );
> + if( ib_status != IB_SUCCESS )
> + {
> + AL_EXIT( AL_DBG_NDI );
> + return ib_to_ntstatus( ib_status );
> + }
> +
> + status = nd_csq_init( h_al, cid, 0, &p_csq );
> + if( status != STATUS_SUCCESS )
> + {
> + kal_cep_destroy( h_al, cid, STATUS_SUCCESS );
> + AL_EXIT( AL_DBG_NDI );
> + return status;
> + }
> +
> + __ndi_acquire_lock( &p_csq->csq, &irql );
> + p_csq->state = NDI_CM_LISTEN;
> + __ndi_release_lock( &p_csq->csq, irql );
> +
> + if( (p_listen->svc_id & 0xFFFF) == 0 )
> + {
> + p_listen->svc_id |= (USHORT)cid | (USHORT)(cid >> 16);
> + }
> +
> + ib_status = al_cep_listen( h_al, cid, p_listen );
> + if( ib_status == IB_SUCCESS )
> + {
> + *p_cid = cid;
> + *p_ret_bytes = sizeof(*p_cid);
> + }
> +
> + nd_csq_release( p_csq );
> + status = ib_to_ntstatus( ib_status );
> + AL_EXIT( AL_DBG_NDI );
> + return status;
> +}
> +
> +
> +NTSTATUS
> +__ndi_get_req(
> + IN nd_csq_t
> *p_csq,
> + IN IRP*
> p_irp
> + )
> +{
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID =
> %d\n", p_csq->cid) );
> +
> + if( p_csq->state != NDI_CM_LISTEN )
> + {
> + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_NDI,
> + ("] Invalid state (%d).\n", p_csq->state) );
> + return STATUS_INVALID_DEVICE_REQUEST;
> + }
> +
> + /* Check the MAD list. */
> + if( p_csq->p_mad_head != NULL )
> + {
> + ib_mad_element_t* p_mad = p_csq->p_mad_head;
> + net32_t cid =
> (net32_t)(ULONG_PTR)p_mad->send_context1;
> + p_csq->p_mad_head = p_mad->p_next;
> + p_mad->p_next = NULL;
> +
> + *(net32_t*)cl_ioctl_out_buf( p_irp ) = cid;
> + p_irp->IoStatus.Information = sizeof(net32_t);
> + p_irp->IoStatus.Status = STATUS_SUCCESS;
> + IoMarkIrpPending( p_irp );
> + IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> + ib_put_mad( p_mad );
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> ("] Returned new CID = %d\n", cid) );
> + return STATUS_INVALID_DEVICE_STATE;
> + }
> +
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("]
> Queueing IRP\n") );
> + return STATUS_PENDING;
> +}
> +
> +
> +NTSTATUS
> +ndi_get_req_cm(
> + IN nd_csq_t
> *p_csq,
> + IN PIRP
> p_irp
> + )
> +{
> + NTSTATUS status;
> +
> + AL_ENTER( AL_DBG_NDI );
> +
> + status = IoCsqInsertIrpEx(
> + &p_csq->csq,
> + p_irp,
> + NULL,
> + (VOID*)(ULONG_PTR)NDI_CM_LISTEN
> + );
> +
> + /*
> + * __ndi_get_req will return
> STATUS_INVALID_DEVICE_STATE to prevent the IRP
> + * from being inserted into the CSQ because the IRP
> was immediately completed.
> + * In this case, we need to return STATUS_PENDING.
> + */
> + if( status == STATUS_INVALID_DEVICE_STATE )
> + {
> + status = STATUS_PENDING;
> + }
> +
> + AL_EXIT( AL_DBG_NDI );
> + return status;
> +}
> +
> +
>
> Index: core/al/kernel/al_ndi_cm.h
> ===================================================================
> --- core/al/kernel/al_ndi_cm.h (revision 2061)
> +++ core/al/kernel/al_ndi_cm.h (working copy)
> @@ -64,8 +64,10 @@
> typedef enum _ndi_cm_state
> {
> NDI_CM_IDLE,
> + NDI_CM_LISTEN,
> NDI_CM_CONNECTING_QPR_SENT, // QPR = Query path record
> NDI_CM_CONNECTING_REQ_SENT,
> + NDI_CM_CONNECTING_REQ_RCVD,
> NDI_CM_CONNECTING_REP_SENT,
> NDI_CM_CONNECTING_REP_RCVD,
> NDI_CM_CONNECTED,
> @@ -77,16 +79,27 @@ typedef enum _ndi_cm_state
>
> typedef struct _ib_qp ib_qp_t;
>
> -typedef struct _ndi_qp_csq
> +typedef struct _nd_csq
> {
> IO_CSQ csq;
> LIST_ENTRY queue;
> - ib_qp_t* h_qp;
> - ib_query_handle_t h_query;
> + ib_al_handle_t h_al;
> + union {
> + uint64_t h_qp;
> + ib_mad_element_t *p_mad_head;
> + };
> + union {
> + ib_query_handle_t h_query;
> + ib_mad_element_t *p_mad_tail;
> + };
> + net32_t cid;
> ndi_cm_state_t state;
> PIO_WORKITEM p_workitem;
> + volatile LONG ref_cnt;
> + KSPIN_LOCK lock;
> +
> +} nd_csq_t;
>
> -} ndi_qp_csq_t;
>
> ib_api_status_t
> ndi_modify_qp(
> @@ -95,41 +108,59 @@ ndi_modify_qp(
> IN const uint32_t
> buf_size,
> IN uint8_t* const
> p_outbuf);
>
> +void
> +nd_csq_ref( nd_csq_t* p_csq );
> +
> +void
> +nd_csq_release( nd_csq_t* p_csq );
> +
> +void
> +nd_cm_handler(
> + IN const ib_al_handle_t
> h_al,
> + IN const net32_t
> cid );
> +
> NTSTATUS
> ndi_req_cm(
> - IN ib_qp_handle_t const h_qp,
> - IN cl_ioctl_handle_t
> h_ioctl
> + IN ib_al_handle_t
> h_al,
> + IN PIRP
> p_irp
> );
>
> NTSTATUS
> ndi_rep_cm(
> - IN ib_qp_handle_t const h_qp,
> + IN ib_al_handle_t
> h_al,
> IN PIRP
> p_irp
> );
>
> cl_status_t
> ndi_rtu_cm(
> - IN ib_qp_handle_t const h_qp,
> + IN nd_csq_t
> *p_csq,
> IN PIRP
> p_irp
> );
>
> NTSTATUS
> ndi_dreq_cm(
> - IN ib_qp_handle_t const h_qp,
> + IN nd_csq_t
> *p_csq,
> IN PIRP
> p_irp
> );
> -
> -NTSTATUS
> -ndi_qp_init(
> - IN ib_qp_handle_t
> h_qp );
>
> void
> -ndi_qp_destroy(
> - IN ib_qp_handle_t
> h_qp );
> +ndi_cancel_cm_irps(
> + IN nd_csq_t
> *p_csq
> + );
>
> -void
> -ndi_qp_free(
> - IN ib_qp_handle_t
> h_qp );
> +NTSTATUS
> +ndi_listen_cm(
> + IN ib_al_handle_t
> h_al,
> + IN ib_cep_listen_t
> *p_listen,
> + OUT net32_t
> *p_cid,
> + OUT size_t
> *p_ret_bytes
> + );
> +
> +NTSTATUS
> +ndi_get_req_cm(
> + IN nd_csq_t
> *p_csq,
> + IN PIRP
> p_irp
> + );
>
> #endif
>
> Index: core/al/kernel/al_cm.c
> ===================================================================
> --- core/al/kernel/al_cm.c (revision 2061)
> +++ core/al/kernel/al_cm.c (working copy)
> @@ -90,7 +90,7 @@ cm_cep_handler(const ib_al_handle_t h_al
>
> id = cm_alloc_id(listen_id->callback,
> listen_id);
> if (id == NULL) {
> - kal_cep_destroy(h_al, new_cid);
> + kal_cep_destroy(h_al,
> new_cid, STATUS_NO_MORE_ENTRIES);
> ib_put_mad(mad);
> continue;
> }
> @@ -103,7 +103,7 @@ cm_cep_handler(const ib_al_handle_t h_al
> status = id->callback(id, &event);
> if (!NT_SUCCESS(status)) {
> kal_cep_config(h_al, new_cid, NULL,
> NULL, NULL);
> - kal_cep_destroy(h_al, id->cid);
> + kal_cep_destroy(h_al, id->cid, status);
> cm_free_id(id);
> }
> ib_put_mad(mad);
> @@ -139,7 +139,7 @@ cm_destroy_id(iba_cm_id *p_id)
> iba_cm_id_priv *id;
>
> id = CONTAINING_RECORD(p_id, iba_cm_id_priv, id);
> - kal_cep_destroy(gh_al, p_id->cid);
> + kal_cep_destroy(gh_al, p_id->cid, STATUS_SUCCESS);
> KeWaitForSingleObject(&id->destroy_event, Executive,
> KernelMode, FALSE, NULL);
> cm_free_id(p_id);
> }
> Index: core/al/kernel/al_proxy_cep.c
> ===================================================================
> --- core/al/kernel/al_proxy_cep.c (revision 2061)
> +++ core/al/kernel/al_proxy_cep.c (working copy)
> @@ -53,7 +53,6 @@ proxy_create_cep(
> OUT size_t
> *p_ret_bytes )
> {
> al_dev_open_context_t *p_context;
> - void* user_context;
> ual_create_cep_ioctl_t *p_ioctl;
>
> AL_ENTER( AL_DBG_CM );
> @@ -62,19 +61,13 @@ proxy_create_cep(
> p_ioctl = (ual_create_cep_ioctl_t*)cl_ioctl_out_buf(
> h_ioctl );
>
> /* Validate user parameters. */
> - if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint64_t) ||
> - cl_ioctl_out_size( h_ioctl ) !=
> sizeof(ual_create_cep_ioctl_t) )
> + if( cl_ioctl_out_size( h_ioctl ) !=
> sizeof(ual_create_cep_ioctl_t) )
> {
> AL_EXIT( AL_DBG_CM );
> return CL_INVALID_PARAMETER;
> }
> -
> - user_context = *(void**)cl_ioctl_in_buf( h_ioctl );
> -
> /* We use IRPs as notification mechanism so the
> callback is NULL. */
> - p_ioctl->cid = AL_INVALID_CID;
> - p_ioctl->status = al_create_cep( p_context->h_al, NULL,
> - user_context, NULL, &p_ioctl->cid );
> + p_ioctl->status = kal_cep_alloc( p_context->h_al,
> &p_ioctl->cid );
>
> *p_ret_bytes = sizeof(ual_create_cep_ioctl_t);
>
> @@ -862,37 +855,6 @@ proxy_cep_get_event(
> }
>
>
> -static cl_status_t
> -proxy_cep_get_req_cid(
> - IN void
> *p_open_context,
> - IN cl_ioctl_handle_t h_ioctl,
> - OUT size_t
> *p_ret_bytes )
> -{
> - cl_status_t cl_status;
> - al_dev_open_context_t *p_context;
> - UNUSED_PARAM(p_ret_bytes);
> -
> - AL_ENTER( AL_DBG_CM );
> -
> - p_context = (al_dev_open_context_t*)p_open_context;
> -
> - /* Validate user parameters. */
> - if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint32_t) ||
> - cl_ioctl_out_size( h_ioctl ) != sizeof(uint32_t) )
> - {
> - AL_EXIT( AL_DBG_CM );
> - return CL_INVALID_PARAMETER;
> - }
> -
> - /* get CID */
> - cl_status = al_cep_get_cid( p_context->h_al,
> - *(uint32_t*)cl_ioctl_in_buf( h_ioctl ), h_ioctl );
> -
> - AL_EXIT( AL_DBG_CM );
> - return cl_status;
> -}
> -
> -
>
> static cl_status_t
> proxy_cep_get_pdata(
> @@ -902,8 +864,8 @@ proxy_cep_get_pdata(
> {
> al_dev_open_context_t *p_context;
> ual_cep_get_pdata_ioctl_t *p_ioctl;
> - al_conn_qp_t *p_qp;
> NTSTATUS status;
> + net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -922,23 +884,9 @@ proxy_cep_get_pdata(
> return CL_INVALID_PARAMETER;
> }
>
> - if ( p_ioctl->in.h_qp )
> - {
> - /* Get the kernel QP handle. */
> - p_qp = (al_conn_qp_t*)al_hdl_ref(
> - p_context->h_al, p_ioctl->in.h_qp,
> AL_OBJ_TYPE_H_QP );
> - if( !p_qp )
> - {
> - AL_PRINT_EXIT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR,
> - ("Invalid QP handle\n"));
> - return CL_CONNECTION_INVALID;
> - }
> - p_ioctl->in.cid = p_qp->cid;
> - deref_al_obj( &p_qp->qp.obj );
> - }
> -
> + cid = p_ioctl->in.cid;
> p_ioctl->out.pdata_len = sizeof(p_ioctl->out.pdata);
> - status = al_cep_get_pdata( p_context->h_al, p_ioctl->in.cid,
> + status = al_cep_get_pdata( p_context->h_al, cid,
> &p_ioctl->out.init_depth, &p_ioctl->out.resp_res,
> (uint8_t*)&p_ioctl->out.pdata_len,
> p_ioctl->out.pdata );
>
> @@ -953,6 +901,7 @@ proxy_cep_get_pdata(
> return status;
> }
>
> +
> cl_status_t cep_ioctl(
> IN cl_ioctl_handle_t h_ioctl,
> OUT size_t
> *p_ret_bytes )
> @@ -1035,9 +984,6 @@ cl_status_t cep_ioctl(
> break;
> case UAL_CEP_POLL:
> cl_status = proxy_cep_poll( p_context,
> h_ioctl, p_ret_bytes );
> - break;
> - case UAL_CEP_GET_REQ_CID:
> - cl_status = proxy_cep_get_req_cid( p_context,
> h_ioctl, p_ret_bytes );
> break;
> case UAL_CEP_GET_PDATA:
> cl_status = proxy_cep_get_pdata( p_context,
> h_ioctl, p_ret_bytes );
> Index: core/al/kernel/al_proxy_ndi.c
> ===================================================================
> --- core/al/kernel/al_proxy_ndi.c (revision 2061)
> +++ core/al/kernel/al_proxy_ndi.c (working copy)
> @@ -322,7 +322,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))
> + if( cl_ioctl_in_size( h_ioctl ) <
> sizeof(ual_ndi_req_cm_ioctl_in_t) )
> {
> cl_status = CL_INVALID_PARAMETER;
> goto exit;
> @@ -351,7 +351,7 @@ __ndi_req_cm(
> }
>
> /* perform the ioctl */
> - cl_status = ndi_req_cm( h_qp, h_ioctl );
> + cl_status = ndi_req_cm( p_context->h_al, h_ioctl );
>
> err:
> deref_al_obj( &h_qp->obj );
> @@ -370,7 +370,6 @@ __ndi_rep_cm(
> cl_status_t cl_status;
> ib_qp_handle_t h_qp = NULL;
> al_dev_open_context_t *p_context;
> - 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);
> @@ -386,6 +385,9 @@ __ndi_rep_cm(
> goto exit;
> }
>
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("CID = %d\n", p_rep->cid) );
> +
> /* Get and validate QP handle */
> h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al,
> p_rep->h_qp, AL_OBJ_TYPE_H_QP );
> if( !h_qp )
> @@ -406,12 +408,9 @@ __ndi_rep_cm(
> cl_status = CL_INVALID_PARAMETER;
> goto err;
> }
> -
> - /* Get and validate CID */
> - cid = p_rep->cid;
>
> /* perform the ioctls */
> - cl_status = ndi_rep_cm( h_qp, h_ioctl );
> + cl_status = ndi_rep_cm( p_context->h_al, h_ioctl );
>
> err:
> deref_al_obj( &h_qp->obj );
> @@ -455,7 +454,6 @@ __ndi_rej_cm(
> goto exit;
> }
>
> - al_destroy_cep( p_context->h_al, &p_rej->cid, FALSE );
> ntstatus = STATUS_SUCCESS;
>
> exit:
> @@ -470,10 +468,8 @@ __ndi_rtu_cm(
> OUT size_t
> *p_ret_bytes )
> {
> cl_status_t cl_status;
> - ib_qp_handle_t h_qp = NULL;
> + nd_csq_t* p_csq;
> al_dev_open_context_t *p_context;
> - ual_ndi_rtu_cm_ioctl_in_t *p_rtu =
> - (ual_ndi_rtu_cm_ioctl_in_t*)cl_ioctl_in_buf(
> h_ioctl );
>
> UNUSED_PARAM(p_ret_bytes);
>
> @@ -482,32 +478,28 @@ __ndi_rtu_cm(
> p_context = (al_dev_open_context_t*)p_open_context;
>
> /* Validate user parameters. */
> - if( cl_ioctl_in_size( h_ioctl ) <
> sizeof(ual_ndi_rtu_cm_ioctl_in_t))
> + if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )
> {
> cl_status = CL_INVALID_PARAMETER;
> goto exit;
> }
>
> - /* Validate QP handle */
> - h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al,
> p_rtu->h_qp, AL_OBJ_TYPE_H_QP );
> - if( !h_qp )
> + p_csq = kal_cep_get_context(
> + p_context->h_al,
> + *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> + nd_cm_handler,
> + nd_csq_ref
> + );
> + if( p_csq == NULL )
> {
> cl_status = CL_INVALID_HANDLE;
> goto exit;
> }
>
> - /* Check QP type */
> - if( h_qp->type != IB_QPT_RELIABLE_CONN )
> - {
> - cl_status = CL_INVALID_HANDLE;
> - goto err;
> - }
> -
> /* perform the ioctl */
> - cl_status = ndi_rtu_cm( h_qp, h_ioctl );
> + cl_status = ndi_rtu_cm( p_csq, h_ioctl );
>
> -err:
> - deref_al_obj( &h_qp->obj );
> + nd_csq_release( p_csq );
>
> exit:
> AL_EXIT( AL_DBG_NDI );
> @@ -521,7 +513,7 @@ __ndi_dreq_cm(
> OUT size_t
> *p_ret_bytes )
> {
> cl_status_t cl_status;
> - ib_qp_handle_t h_qp = NULL;
> + nd_csq_t *p_csq;
> al_dev_open_context_t *p_context;
>
> UNUSED_PARAM(p_ret_bytes);
> @@ -531,37 +523,206 @@ __ndi_dreq_cm(
> p_context = (al_dev_open_context_t*)p_open_context;
>
> /* Validate user parameters. */
> - if( cl_ioctl_in_size( h_ioctl ) < sizeof(uint64_t))
> + if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )
> {
> cl_status = CL_INVALID_PARAMETER;
> goto exit;
> }
>
> - /* Validate QP handle */
> - h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al,
> - *(uint64_t*)cl_ioctl_in_buf( h_ioctl ),
> AL_OBJ_TYPE_H_QP );
> - if( !h_qp )
> + /* Validate CID */
> + p_csq = (nd_csq_t*)kal_cep_get_context(
> + p_context->h_al,
> + *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> + nd_cm_handler,
> + nd_csq_ref
> + );
> +
> + if( p_csq == NULL )
> {
> cl_status = CL_CONNECTION_INVALID;
> goto exit;
> }
>
> - /* Check QP type */
> - if( h_qp->type != IB_QPT_RELIABLE_CONN )
> + /* perform the ioctl */
> + cl_status = ndi_dreq_cm( p_csq, h_ioctl );
> +
> + nd_csq_release( p_csq );
> +
> +exit:
> + AL_EXIT( AL_DBG_NDI );
> + return cl_status;
> +}
> +
> +static NTSTATUS
> +__ndi_notify_dreq_cm(
> + IN void
> *p_open_context,
> + IN cl_ioctl_handle_t h_ioctl,
> + OUT size_t
> *p_ret_bytes )
> +{
> + NTSTATUS status;
> + nd_csq_t *p_csq;
> + al_dev_open_context_t *p_context;
> +
> + 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(net32_t) )
> {
> - cl_status = CL_CONNECTION_INVALID;
> - goto err;
> + status = STATUS_INVALID_PARAMETER;
> + goto exit;
> + }
> +
> + /* Validate CID */
> + p_csq = (nd_csq_t*)kal_cep_get_context(
> + p_context->h_al,
> + *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> + nd_cm_handler,
> + nd_csq_ref
> + );
> +
> + if( p_csq == NULL )
> + {
> + status = STATUS_CONNECTION_INVALID;
> + goto exit;
> }
>
> /* perform the ioctl */
> - cl_status = ndi_dreq_cm( h_qp, h_ioctl );
> + status = IoCsqInsertIrpEx(
> + &p_csq->csq,
> + h_ioctl,
> + NULL,
> + (VOID*)(ULONG_PTR)NDI_CM_CONNECTED_DREQ_RCVD
> + );
>
> -err:
> - deref_al_obj( &h_qp->obj );
> + nd_csq_release( p_csq );
>
> exit:
> AL_EXIT( AL_DBG_NDI );
> - return cl_status;
> + return status;
> +}
> +
> +static cl_status_t
> +__ndi_cancel_cm_irps(
> + IN void
> *p_open_context,
> + IN cl_ioctl_handle_t h_ioctl,
> + OUT size_t
> *p_ret_bytes )
> +{
> + nd_csq_t *p_csq;
> + al_dev_open_context_t *p_context;
> +
> + 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(net32_t) )
> + {
> + AL_EXIT( AL_DBG_NDI );
> + return STATUS_INVALID_PARAMETER;
> + }
> +
> + /* Validate CID */
> + p_csq = (nd_csq_t*)kal_cep_get_context(
> + p_context->h_al,
> + *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> + nd_cm_handler,
> + nd_csq_ref
> + );
> +
> + if( p_csq == NULL )
> + {
> + AL_EXIT( AL_DBG_NDI );
> + return STATUS_UNSUCCESSFUL;
> + }
> +
> + /* perform the ioctl */
> + ndi_cancel_cm_irps( p_csq );
> + nd_csq_release( p_csq );
> +
> + AL_EXIT( AL_DBG_NDI );
> + return STATUS_SUCCESS;
> +}
> +
> +static cl_status_t
> +__ndi_listen_cm(
> + IN void
> *p_open_context,
> + IN cl_ioctl_handle_t h_ioctl,
> + OUT size_t
> *p_ret_bytes )
> +{
> + al_dev_open_context_t *p_context;
> + ual_cep_listen_ioctl_t *p_listen =
> + (ual_cep_listen_ioctl_t*)cl_ioctl_in_buf( h_ioctl );
> + net32_t* p_cid =
> + (net32_t*)cl_ioctl_out_buf( h_ioctl );
> +
> + 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(*p_listen) ||
> + cl_ioctl_out_size( h_ioctl ) != sizeof(*p_cid) )
> + {
> + AL_EXIT( AL_DBG_NDI );
> + return CL_INVALID_PARAMETER;
> + }
> +
> + /* Set the private data compare buffer to our kernel copy. */
> + if( p_listen->cep_listen.p_cmp_buf )
> + p_listen->cep_listen.p_cmp_buf = p_listen->compare;
> +
> + AL_EXIT( AL_DBG_NDI );
> + return ndi_listen_cm( p_context->h_al,
> &p_listen->cep_listen, p_cid, p_ret_bytes );
> +}
> +
> +static cl_status_t
> +__ndi_get_req_cm(
> + IN void
> *p_open_context,
> + IN cl_ioctl_handle_t h_ioctl,
> + OUT size_t
> *p_ret_bytes )
> +{
> + al_dev_open_context_t *p_context;
> + nd_csq_t *p_csq;
> + NTSTATUS status;
> +
> + AL_ENTER( AL_DBG_NDI );
> +
> + UNREFERENCED_PARAMETER( p_ret_bytes );
> +
> + p_context = (al_dev_open_context_t*)p_open_context;
> +
> + /* Validate user parameters. */
> + if( cl_ioctl_in_size( h_ioctl ) != sizeof(net32_t) ||
> + cl_ioctl_out_size( h_ioctl ) != sizeof(net32_t) )
> + {
> + AL_EXIT( AL_DBG_NDI );
> + return CL_INVALID_PARAMETER;
> + }
> +
> + /* Validate CID */
> + p_csq = (nd_csq_t*)kal_cep_get_context(
> + p_context->h_al,
> + *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> + nd_cm_handler,
> + nd_csq_ref
> + );
> +
> + if( p_csq == NULL )
> + {
> + AL_EXIT( AL_DBG_NDI );
> + return STATUS_UNSUCCESSFUL;
> + }
> +
> + status = ndi_get_req_cm( p_csq, h_ioctl );
> + nd_csq_release( p_csq );
> + AL_EXIT( AL_DBG_NDI );
> + return status;
> }
>
> cl_status_t
> @@ -621,9 +782,23 @@ ndi_ioctl(
> h_ioctl->IoStatus.Status = CL_SUCCESS;
> h_ioctl->IoStatus.Information = 0;
>
> + AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> + ("UAL_NDI_NOOP completed with
> %08x\n", h_ioctl->IoStatus.Status) );
> IoCompleteRequest( h_ioctl, IO_NETWORK_INCREMENT );
> cl_status = CL_PENDING;
> break;
> + case UAL_NDI_NOTIFY_DREQ:
> + cl_status = __ndi_notify_dreq_cm( p_context,
> h_ioctl, p_ret_bytes );
> + break;
> + case UAL_NDI_CANCEL_CM_IRPS:
> + cl_status = __ndi_cancel_cm_irps( p_context,
> h_ioctl, p_ret_bytes );
> + break;
> + case UAL_NDI_LISTEN_CM:
> + cl_status = __ndi_listen_cm( p_context,
> h_ioctl, p_ret_bytes );
> + break;
> + case UAL_NDI_GET_REQ_CM:
> + cl_status = __ndi_get_req_cm( p_context,
> h_ioctl, p_ret_bytes );
> + break;
> default:
> cl_status = CL_INVALID_PARAMETER;
> break;
> Index: core/al/al_qp.h
> ===================================================================
> --- core/al/al_qp.h (revision 2061)
> +++ core/al/al_qp.h (working copy)
> @@ -135,10 +135,6 @@ typedef struct _ib_qp
> IN const ib_qp_handle_t
> h_qp,
> IN const ib_mcast_req_t* const
> p_mcast_req );
>
> -#ifdef CL_KERNEL
> - ndi_qp_csq_t *p_irp_queue;
> -#endif
> -
> } ib_qp_t;
>
>
> Index: core/al/al_cm_cep.h
> ===================================================================
> --- core/al/al_cm_cep.h (revision 2061)
> +++ core/al/al_cm_cep.h (working copy)
> @@ -116,7 +116,7 @@ kal_cep_alloc(
> IN ib_al_handle_t
> h_al,
> IN OUT net32_t* const
> p_cid );
>
> -void
> +ib_api_status_t
> kal_cep_config(
> IN ib_al_handle_t
> h_al,
> IN net32_t
> cid,
> @@ -184,22 +184,11 @@ kal_cep_pre_rep(
> IN uint8_t
> rnr_nak_timeout,
> IN OUT ib_qp_mod_t* const
> p_init OPTIONAL );
>
> -ib_api_status_t
> -kal_cep_config_pre_rep_copy_cid(
> - IN ib_al_handle_t
> h_al,
> - IN net32_t
> cid,
> - IN al_pfn_cep_cb_t
> pfn_cb,
> - IN void*
> context,
> - IN ib_pfn_destroy_cb_t
> pfn_destroy_cb,
> - IN const iba_cm_rep* const
> p_cm_rep,
> - IN uint8_t
> rnr_nak_timeout,
> - IN OUT net32_t* const
> p_cid,
> - OUT ib_qp_mod_t* const
> p_init );
> -
> void
> kal_cep_destroy(
> IN ib_al_handle_t
> h_al,
> - IN net32_t
> cid );
> + IN net32_t
> cid,
> + IN NTSTATUS
> status );
> #endif
>
> ib_api_status_t
> @@ -337,13 +326,6 @@ al_cep_queue_irp(
> IN IRP* const
> p_irp );
>
> NTSTATUS
> -al_cep_get_cid(
> - IN ib_al_handle_t
> h_al,
> - IN net32_t const
> cid,
> - IN PIRP
> h_ioctl
> - );
> -
> -NTSTATUS
> al_cep_get_pdata(
> IN ib_al_handle_t
> h_al,
> IN net32_t
> cid,
> @@ -352,6 +334,12 @@ al_cep_get_pdata(
> IN OUT uint8_t
> *p_psize,
> OUT uint8_t*
> pdata );
>
> +void*
> +kal_cep_get_context(
> + IN ib_al_handle_t
> h_al,
> + IN net32_t
> cid,
> + IN al_pfn_cep_cb_t
> pfn_cb,
> + IN ib_pfn_destroy_cb_t
> pfn_addref );
> #endif /* CL_KERNEL */
>
>
> Index: core/al/al_dev.h
> ===================================================================
> --- core/al/al_dev.h (revision 2061)
> +++ core/al/al_dev.h (working copy)
> @@ -55,7 +55,7 @@
> #define AL_DEVICE_NAME L"\\Device\\ibal"
> #define ALDEV_KEY (0x3B) /* Matches
> FILE_DEVICE_INFINIBAND from wdm.h */
>
> -#define AL_IOCTL_VERSION (11)
> +#define AL_IOCTL_VERSION (12)
>
> /* max number of devices with non-default pkey */
> #define MAX_NUM_PKEY 16
> @@ -353,7 +353,6 @@ typedef enum _ual_cep_ops
> ual_cep_get_timewait,
> ual_cep_get_event,
> ual_cep_poll,
> - ual_cep_get_req_cid,
> ual_cep_get_pdata,
>
> al_cep_maxops
> @@ -408,6 +407,9 @@ typedef enum _al_ndi_ops
> ual_ndi_dreq_cm_ioctl_cmd,
> ual_ndi_noop,
> ual_ndi_notify_dreq_cmd,
> + ual_ndi_cancel_cm_irps,
> + ual_ndi_listen_cm_cmd,
> + ual_ndi_get_req_cm_cmd,
>
> al_ndi_maxops
>
> @@ -440,6 +442,9 @@ typedef enum _al_ioc_device_config
> #define UAL_NDI_DREQ_CM
> IOCTL_CODE(ALDEV_KEY, ual_ndi_dreq_cm_ioctl_cmd)
> #define UAL_NDI_NOOP IOCTL_CODE(ALDEV_KEY, ual_ndi_noop)
> #define UAL_NDI_NOTIFY_DREQ IOCTL_CODE(ALDEV_KEY,
> ual_ndi_notify_dreq_cmd)
> +#define UAL_NDI_CANCEL_CM_IRPS IOCTL_CODE(ALDEV_KEY,
> ual_ndi_cancel_cm_irps)
> +#define UAL_NDI_LISTEN_CM IOCTL_CODE(ALDEV_KEY,
> ual_ndi_listen_cm_cmd)
> +#define UAL_NDI_GET_REQ_CM IOCTL_CODE(ALDEV_KEY,
> ual_ndi_get_req_cm_cmd)
>
> /*
> * Various Operation Allowable on the System Helper
> @@ -541,7 +546,6 @@ typedef enum _al_ioc_device_config
> #define UAL_CEP_GET_TIMEWAIT IOCTL_CODE(ALDEV_KEY,
> ual_cep_get_timewait)
> #define UAL_CEP_GET_EVENT IOCTL_CODE(ALDEV_KEY,
> ual_cep_get_event)
> #define UAL_CEP_POLL IOCTL_CODE(ALDEV_KEY, ual_cep_poll)
> -#define UAL_CEP_GET_REQ_CID IOCTL_CODE(ALDEV_KEY,
> ual_cep_get_req_cid)
> #define UAL_CEP_GET_PDATA IOCTL_CODE(ALDEV_KEY,
> ual_cep_get_pdata)
>
>
> Index: core/al/al_qp.c
> ===================================================================
> --- core/al/al_qp.c (revision 2061)
> +++ core/al/al_qp.c (working copy)
> @@ -327,10 +327,6 @@ create_qp(
> break;
> }
> status = init_conn_qp( (al_conn_qp_t*)h_qp,
> h_pd, p_qp_create, p_umv_buf );
> -#ifdef CL_KERNEL
> - if( status == IB_SUCCESS && !NT_SUCCESS(
> ndi_qp_init(h_qp) ) )
> - status = IB_ERROR;
> -#endif
> break;
>
> case IB_QPT_UNRELIABLE_DGRM:
> @@ -1117,9 +1113,6 @@ destroying_qp(
> case IB_QPT_RELIABLE_CONN:
> case IB_QPT_UNRELIABLE_CONN:
> al_destroy_cep( h_qp->obj.h_al,
> &((al_conn_qp_t*)h_qp)->cid, FALSE );
> -#ifdef CL_KERNEL
> - ndi_qp_destroy( h_qp );
> -#endif
>
> /* Fall through. */
> case IB_QPT_UNRELIABLE_DGRM:
> @@ -1236,10 +1229,6 @@ free_qp(
>
> CL_ASSERT( p_obj );
> h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );
> -
> -#ifdef CL_KERNEL
> - ndi_qp_free( h_qp );
> -#endif
>
> destroy_al_obj( p_obj );
> cl_free( h_qp );
> Index: core/al/user/ual_cm_cep.c
> ===================================================================
> --- core/al/user/ual_cm_cep.c (revision 2061)
> +++ core/al/user/ual_cm_cep.c (working copy)
> @@ -272,9 +272,8 @@ __create_ucep(
> /* Create a kernel CEP only if we don't already have a CID. */
> if( cid == AL_INVALID_CID )
> {
> - uint64_t cep_context = (ULONG_PTR)context;
> - if( !DeviceIoControl( g_al_device,
> UAL_CREATE_CEP, &cep_context,
> - sizeof(cep_context), &ioctl,
> sizeof(ioctl), &bytes_ret, NULL ) ||
> + if( !DeviceIoControl( g_al_device,
> UAL_CREATE_CEP, NULL,
> + 0, &ioctl, sizeof(ioctl), &bytes_ret,
> NULL ) ||
> bytes_ret != sizeof(ioctl) )
> {
> __destroy_ucep( p_cep );
> Index: inc/iba/ib_al_ioctl.h
> ===================================================================
> --- inc/iba/ib_al_ioctl.h (revision 2061)
> +++ inc/iba/ib_al_ioctl.h (working copy)
> @@ -3089,7 +3089,6 @@ typedef union _ual_cep_get_pdata_ioctl
> {
> struct _ual_cep_get_pdata_ioctl_in
> {
> - uint64_t h_qp;
> net32_t cid;
>
> } in;
> @@ -3106,9 +3105,6 @@ typedef union _ual_cep_get_pdata_ioctl
> } ual_cep_get_pdata_ioctl_t;
> /*
> * FIELDS
> -* h_qp
> -* A handle to the QP to modify.
> -*
> * in.cid
> * The CID for the target CEP.
> *
> @@ -3483,6 +3479,7 @@ typedef struct _ual_ndi_req_cm_ioctl_in
> ib_path_rec_t path;
> uint64_t h_qp;
> net64_t guid;
> + net32_t cid;
> uint16_t dst_port;
> uint8_t resp_res;
> uint8_t init_depth;
> @@ -3493,7 +3490,7 @@ typedef struct _ual_ndi_req_cm_ioctl_in
> } ual_ndi_req_cm_ioctl_in_t;
> /*
> * NOTES
> -* The output parameter is the new QP state (RTS).
> +* There is no output parameter.
> *
> * FIELDS
> * h_qp
> @@ -3502,6 +3499,9 @@ typedef struct _ual_ndi_req_cm_ioctl_in
> * guid
> * Local port GUID to which to bind to.
> *
> +* cid
> +* CID of the CEP to use for the connection request.
> +*
> * dst_port
> * Destination port number.
> *
> @@ -3600,38 +3600,6 @@ typedef struct _ual_ndi_rej_cm_ioctl_in
> *
> * pdata
> * Private data in format RDMA CM
> -*
> -*****/
> -
> -
> -/****s* User-mode Access Layer/ual_ndi_rtu_cm_ioctl_in_t
> -* NAME
> -* ual_ndi_rtu_cm_ioctl_in_t
> -*
> -* DESCRIPTION
> -* IOCTL structure containing the input parameters
> -* sending CM RTU response .
> -*
> -* SYNOPSIS
> -*/
> -typedef struct _ual_ndi_rtu_cm_ioctl_in
> -{
> - uint64_t h_qp;
> -
> -} ual_ndi_rtu_cm_ioctl_in_t;
> -/*
> -* NOTES
> -* The output parameter is the new QP state (RTS).
> -*
> -* FIELDS
> -* h_qp
> -* A handle to the QP to modify.
> -*
> -* init_depth
> -* The maximum number of outstanding RDMA
> read/atomic operations.
> -*
> -* resp_res
> -* The maximum number of RDMA read/atomic
> operations from the recipient.
> *
> *****/
>
>
More information about the ofw
mailing list