[ofw] [PATCH] Fix race reading/setting connection ID
Leonid Keller
leonid at mellanox.co.il
Wed Jul 2 06:37:14 PDT 2008
Applied in 1326. Thank you.
> -----Original Message-----
> From: ofw-bounces at lists.openfabrics.org
> [mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Fab Tillier
> Sent: Wednesday, July 02, 2008 3:03 AM
> To: ofw at lists.openfabrics.org
> Subject: [ofw] [PATCH] Fix race reading/setting connection ID
>
> IBAL has two reserved CID values that it stores in the QPs -
> AL_INVALID_CID, meaning that there is no CEP associated with
> the QP but that one can be associated, and AL_RESERVED_CID,
> which means no CEP is associated, and none should be because
> the QP is being destroyed.
>
> The code uses atomic operations to check for/set
> AL_INVALID_CID or AL_RESERVED_CID. Since there are two
> possible 'special' values, atomics can't be used reliably.
>
> There has been a report of this related to SRP and BSODs.
>
> Additionally, the code would provide the destroy callback
> when destroying the CEP. However, the CEP can be destroyed
> through different paths, and it's important to make sure the
> destroy callback is invoked always so that reference counts
> can be properly released.
>
> This patch pushes all assignments and checks for special
> values into the CEP manager, protected by the CEP manager's
> lock that it holds when performing the CEP lookup. It also
> changes the semantics of creation/destruction of the CEPs to
> provide the destroy callback when the CEP is created or bound
> to an object (the binding path is for the passive side of a
> connection).
>
> Signed-off-by: Fab Tillier <ftillier at microsoft.com>
>
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\al_cm_cep.h trunk\core\al\al_cm_cep.h
> --- old\core\al\al_cm_cep.h Tue Jul 01 16:52:15 2008
> +++ trunk\core\al\al_cm_cep.h Tue Jul 01 16:52:27 2008
> @@ -95,10 +95,10 @@ al_cep_cleanup_al(
>
> ib_api_status_t
> al_create_cep(
> - IN ib_al_handle_t
> FUNC_PTR64 h_al,
> + IN ib_al_handle_t
> h_al,
> IN al_pfn_cep_cb_t
> pfn_cb,
> - IN void* FUNC_PTR64
> context,
> - OUT net32_t* const
> p_cid );
> + IN void*
> context,
> + IN OUT net32_t* const
> p_cid );
> /*
> * NOTES
> * This function may be invoked at DISPATCH_LEVEL
> @@ -107,12 +107,12 @@ al_create_cep(
> * event notification.
> *********/
>
> -
> /* Destruction is asynchronous. */
> -ib_api_status_t
> +void
> al_destroy_cep(
> - IN ib_al_handle_t
> FUNC_PTR64 h_al,
> - IN net32_t
> cid,
> + IN ib_al_handle_t
> h_al,
> + IN OUT net32_t* const
> p_cid,
> + IN boolean_t
> reusable,
> IN ib_pfn_destroy_cb_t
> pfn_destroy_cb );
> /*
> *********/
> @@ -144,6 +144,7 @@ al_cep_pre_rep(
> IN net32_t
> cid,
> IN void*
> context,
> IN const ib_cm_rep_t* const
> p_cm_rep,
> + IN OUT net32_t* const
> p_cid,
> OUT ib_qp_mod_t* const
> p_init );
>
> ib_api_status_t
> @@ -153,6 +154,7 @@ al_cep_pre_rep_ex(
> IN al_pfn_cep_cb_t
> pfn_cb,
> IN void*
> context,
> IN const ib_cm_rep_t* const
> p_cm_rep,
> + IN OUT net32_t* const
> p_cid,
> OUT ib_qp_mod_t* const
> p_init );
>
> ib_api_status_t
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\al_cm_qp.c trunk\core\al\al_cm_qp.c
> --- old\core\al\al_cm_qp.c Tue Jul 01 10:36:06 2008
> +++ trunk\core\al\al_cm_qp.c Tue Jul 01 16:52:27 2008
> @@ -261,7 +261,7 @@ __listen_req(
> static void
> __proc_listen(
> IN al_listen_t* const
> p_listen,
> - IN const net32_t
> new_cid,
> + IN net32_t
> new_cid,
> IN const ib_mad_t* const
> p_mad )
> {
> AL_ENTER( AL_DBG_CM );
> @@ -280,7 +280,7 @@ __proc_listen(
> CL_ASSERT( p_mad->attr_id == CM_REQ_ATTR_ID ||
> p_mad->attr_id == CM_SIDR_REQ_ATTR_ID );
> /* Destroy the new CEP as it won't ever be
> reported to the user. */
> - al_destroy_cep( p_listen->obj.h_al, new_cid, NULL );
> + al_destroy_cep( p_listen->obj.h_al, &new_cid, FALSE,
> + NULL );
> }
>
> AL_EXIT( AL_DBG_CM );
> @@ -302,7 +302,6 @@ __proc_conn_timeout(
> IN const ib_qp_handle_t
> h_qp )
> {
> ib_cm_rej_rec_t rej_rec;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -317,22 +316,15 @@ __proc_conn_timeout(
> rej_rec.qp_context = h_qp->obj.context;
> rej_rec.rej_status = IB_REJ_TIMEOUT;
>
> - ref_al_obj( &h_qp->obj );
> -
> /* Unbind the QP from the CEP. */
> __cep_timewait_qp( h_qp );
>
> - cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid,
> AL_INVALID_CID );
> + al_destroy_cep(
> + h_qp->obj.h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE,
> + deref_al_obj );
>
> /* Invoke the callback. */
> ((al_conn_qp_t*)h_qp)->pfn_cm_rej_cb( &rej_rec );
>
> - if( cid == AL_INVALID_CID ||
> - al_destroy_cep( h_qp->obj.h_al, cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> -
> AL_EXIT( AL_DBG_CM );
> }
>
> @@ -373,7 +365,6 @@ __proc_dconn_timeout(
> IN const ib_qp_handle_t
> h_qp )
> {
> ib_cm_drep_rec_t drep_rec;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -383,21 +374,14 @@ __proc_dconn_timeout(
> drep_rec.qp_context = h_qp->obj.context;
> drep_rec.cm_status = IB_TIMEOUT;
>
> - ref_al_obj( &h_qp->obj );
> -
> __cep_timewait_qp( h_qp );
>
> - cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid,
> AL_INVALID_CID );
> + al_destroy_cep(
> + h_qp->obj.h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE,
> + deref_al_obj );
>
> /* Call the user back. */
> ((al_conn_qp_t*)h_qp)->pfn_cm_drep_cb( &drep_rec );
>
> - if( cid == AL_INVALID_CID ||
> - al_destroy_cep( h_qp->obj.h_al, cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> -
> AL_EXIT( AL_DBG_CM );
> }
>
> @@ -503,7 +487,6 @@ __proc_rej(
> IN const mad_cm_rej_t* const
> p_rej )
> {
> ib_cm_rej_rec_t rej_rec;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -520,21 +503,14 @@ __proc_rej(
> rej_rec.ari_length = conn_rej_get_ari_len( p_rej );
> rej_rec.rej_status = p_rej->reason;
>
> - ref_al_obj( &p_cm->h_qp->obj );
> -
> /*
> * Unbind the QP from the connection object.
> This allows the QP to
> * be immediately reused in another
> connection request.
> */
> __cep_timewait_qp( p_cm->h_qp );
>
> - cid = cl_atomic_xchg(
> &((al_conn_qp_t*)p_cm->h_qp)->cid, AL_INVALID_CID );
> - CL_ASSERT( cid == p_cm->cid || cid ==
> AL_INVALID_CID || cid == AL_RESERVED_CID );
> - if( cid == AL_INVALID_CID ||
> - al_destroy_cep( p_cm->h_al, cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &p_cm->h_qp->obj );
> - }
> + al_destroy_cep(
> + p_cm->h_al,
> &((al_conn_qp_t*)p_cm->h_qp)->cid,
> + TRUE, deref_al_obj );
>
> /* Call the user back. */
> ((al_conn_qp_t*)p_cm->h_qp)->pfn_cm_rej_cb(
> &rej_rec ); @@ -619,7 +595,6 @@ __proc_drep(
> IN mad_cm_drep_t* const
> p_drep )
> {
> ib_cm_drep_rec_t drep_rec;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -631,25 +606,10 @@ __proc_drep(
> drep_rec.h_qp = p_cm->h_qp;
> drep_rec.qp_context = p_cm->h_qp->obj.context;
>
> - ref_al_obj( &p_cm->h_qp->obj );
> -
> __cep_timewait_qp( p_cm->h_qp );
>
> - cid = cl_atomic_xchg(
> &((al_conn_qp_t*)p_cm->h_qp)->cid, AL_INVALID_CID );
> - if( cid != AL_INVALID_CID )
> - {
> - CL_ASSERT( cid == p_cm->cid || cid ==
> AL_RESERVED_CID );
> -
> - if( al_destroy_cep(
> - p_cm->h_al, p_cm->cid, deref_al_obj )
> != IB_SUCCESS )
> - {
> - deref_al_obj( &p_cm->h_qp->obj );
> - }
> - }
> - else
> - {
> - deref_al_obj( &p_cm->h_qp->obj );
> - }
> + al_destroy_cep(
> + p_cm->h_al, &((al_conn_qp_t*)p_cm->h_qp)->cid, TRUE,
> + deref_al_obj );
>
> ((al_conn_qp_t*)p_cm->h_qp)->pfn_cm_drep_cb( &drep_rec );
>
> @@ -1060,7 +1020,6 @@ __cep_conn_req(
> //cl_event_t sync_event;
> //cl_event_t *p_sync_event = NULL;
> al_conn_qp_t *p_qp;
> - net32_t cid, old_cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -1082,7 +1041,7 @@ __cep_conn_req(
> p_qp = (al_conn_qp_t*)p_cm_req->h_qp;
>
> /* Get a CEP and bind it to the QP. */
> - status = al_create_cep( h_al, __cm_handler,
> p_cm_req->h_qp, &cid );
> + status = al_create_cep( h_al, __cm_handler, p_qp,
> &p_qp->cid );
> if( status != IB_SUCCESS )
> {
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, @@
> -1090,14 +1049,8 @@ __cep_conn_req(
> goto done;
> }
>
> - /* See if this QP has already been connected. */
> - old_cid = cl_atomic_comp_xchg( &p_qp->cid,
> AL_INVALID_CID, cid );
> - if( old_cid != AL_INVALID_CID )
> - {
> - al_destroy_cep( h_al, cid, NULL );
> - AL_EXIT( AL_DBG_CM );
> - return IB_INVALID_STATE;
> - }
> + /* Take a reference on behalf of the CEP. */
> + ref_al_obj( &p_qp->qp.obj );
>
> status = __cep_pre_req( p_cm_req );
> if( status != IB_SUCCESS )
> @@ -1123,10 +1076,7 @@ __cep_conn_req(
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> ("al_cep_send_req returned %s.\n",
> ib_get_err_str(status)) );
> err:
> - ref_al_obj( &p_qp->qp.obj );
> - cl_atomic_xchg( &p_qp->cid, AL_INVALID_CID );
> - if( al_destroy_cep( h_al, cid, deref_al_obj )
> != IB_SUCCESS )
> - deref_al_obj( &p_qp->qp.obj );
> + al_destroy_cep( h_al, &p_qp->cid, TRUE,
> deref_al_obj );
> }
>
> /* wait on event if synchronous operation */ @@
> -1322,22 +1272,35 @@ __cep_conn_rep(
> IN const ib_cm_rep_t* const
> p_cm_rep )
> {
> ib_api_status_t status;
> - net32_t cid;
> ib_qp_mod_t qp_mod;
> - boolean_t qp_linked = FALSE;
>
> AL_ENTER( AL_DBG_CM );
>
> - cid = cl_atomic_comp_xchg(
> - &((al_conn_qp_t*)p_cm_rep->h_qp)->cid,
> AL_INVALID_CID, h_cm.cid );
> -
> - if( cid != AL_INVALID_CID )
> + status = al_cep_pre_rep(
> + h_cm.h_al, h_cm.cid, p_cm_rep->h_qp, p_cm_rep,
> + &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, &qp_mod );
> + switch( status )
> {
> + case IB_SUCCESS:
> + break;
> +
> + case IB_RESOURCE_BUSY:
> /* We don't destroy the CEP to allow the user
> to retry accepting. */
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR, ("QP already connected.\n") );
> return IB_INVALID_QP_HANDLE;
> +
> + default:
> + al_cep_rej( h_cm.h_al, h_cm.cid,
> IB_REJ_INSUF_RESOURCES, NULL, 0, NULL, 0 );
> + al_destroy_cep( h_cm.h_al, &h_cm.cid, FALSE, NULL );
> +
> + AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> + ("al_cep_pre_rep returned %s.\n",
> ib_get_err_str( status )) );
> + return status;
> }
>
> + /* Take a reference on behalf of the CEP. */
> + ref_al_obj( &p_cm_rep->h_qp->obj );
> +
> /* Store the CM callbacks. */
> ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_rej_cb =
> p_cm_rep->pfn_cm_rej_cb;
> ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_mra_cb =
> p_cm_rep->pfn_cm_mra_cb; @@ -1345,18 +1308,6 @@ __cep_conn_rep(
> ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_lap_cb =
> p_cm_rep->pfn_cm_lap_cb;
> ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_dreq_cb =
> p_cm_rep->pfn_cm_dreq_cb;
>
> - status = al_cep_pre_rep(
> - h_cm.h_al, h_cm.cid, p_cm_rep->h_qp,
> p_cm_rep, &qp_mod );
> - if( status != IB_SUCCESS )
> - {
> - AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("al_cep_pre_rep returned %s.\n",
> ib_get_err_str( status )) );
> - goto err;
> - }
> -
> - /* The QP has been set as the context for the CEP. */
> - qp_linked = TRUE;
> -
> /* Transition QP through state machine */
> status = __cep_pre_rep( h_cm, &qp_mod, p_cm_rep );
> if( status != IB_SUCCESS )
> @@ -1372,23 +1323,11 @@ __cep_conn_rep(
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> ("al_cep_send_rep returned %s\n",
> ib_get_err_str(status)) );
> err:
> - cl_atomic_xchg(
> -
> &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, AL_INVALID_CID );
>
> /* Reject and abort the connection. */
> al_cep_rej( h_cm.h_al, h_cm.cid,
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> -
> - if( qp_linked )
> - {
> - ref_al_obj( &p_cm_rep->h_qp->obj );
> -
> - if( al_destroy_cep( h_cm.h_al,
> h_cm.cid, deref_al_obj ) != IB_SUCCESS )
> - deref_al_obj( &p_cm_rep->h_qp->obj );
> - }
> - else
> - {
> - al_destroy_cep( h_cm.h_al, h_cm.cid, NULL );
> - }
> + al_destroy_cep(
> + h_cm.h_al,
> + &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, TRUE, deref_al_obj );
> }
>
> AL_EXIT( AL_DBG_CM );
> @@ -1402,6 +1341,7 @@ ib_cm_rep(
> IN const ib_cm_rep_t* const
> p_cm_rep )
> {
> ib_api_status_t status;
> + net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -1448,9 +1388,10 @@ ib_cm_rep(
>
> if( status != IB_SUCCESS )
> {
> + cid = h_cm_req.cid;
> al_cep_rej(
> h_cm_req.h_al, h_cm_req.cid,
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> - al_destroy_cep( h_cm_req.h_al, h_cm_req.cid, NULL );
> + al_destroy_cep( h_cm_req.h_al, &cid, FALSE, NULL );
>
> AL_EXIT( AL_DBG_CM );
> return status;
> @@ -1472,7 +1413,6 @@ ib_cm_rtu(
> IN const ib_cm_rtu_t* const
> p_cm_rtu )
> {
> ib_api_status_t status;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -1519,20 +1459,8 @@ err:
>
> __cep_timewait_qp( h_cm_rep.h_qp );
>
> - cid = cl_atomic_xchg(
> - &((al_conn_qp_t*)h_cm_rep.h_qp)->cid,
> AL_INVALID_CID );
> -
> - if( cid != AL_INVALID_CID )
> - {
> - CL_ASSERT( cid == h_cm_rep.cid );
> -
> - ref_al_obj( &h_cm_rep.h_qp->obj );
> - if( al_destroy_cep(
> - h_cm_rep.h_al, h_cm_rep.cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_cm_rep.h_qp->obj );
> - }
> - }
> + al_destroy_cep(
> + h_cm_rep.h_al,
> + &((al_conn_qp_t*)h_cm_rep.h_qp)->cid, TRUE, deref_al_obj );
>
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> ("al_cep_rtu returned %s.\n",
> ib_get_err_str( status )) ); @@ -1595,18 +1523,13 @@ ib_cm_rej(
> {
> __cep_timewait_qp( h_cm.h_qp );
>
> - cid = cl_atomic_xchg(
> - &((al_conn_qp_t*)h_cm.h_qp)->cid,
> AL_INVALID_CID );
> - if( cid != AL_INVALID_CID )
> - {
> - ref_al_obj( &h_cm.h_qp->obj );
> - if( al_destroy_cep( h_cm.h_al,
> h_cm.cid, deref_al_obj ) != IB_SUCCESS )
> - deref_al_obj( &h_cm.h_qp->obj );
> - }
> + al_destroy_cep(
> + h_cm.h_al, &((al_conn_qp_t*)h_cm.h_qp)->cid,
> + TRUE, deref_al_obj );
> }
> else
> {
> - al_destroy_cep( h_cm.h_al, h_cm.cid, NULL );
> + cid = h_cm.cid;
> + al_destroy_cep( h_cm.h_al, &cid, FALSE, NULL );
> }
>
> AL_EXIT( AL_DBG_CM );
> @@ -1619,7 +1542,6 @@ ib_cm_dreq(
> IN const ib_cm_dreq_t* const
> p_cm_dreq )
> {
> ib_api_status_t status;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -1677,14 +1599,8 @@ ib_cm_dreq(
> */
> __cep_timewait_qp( p_cm_dreq->h_qp );
>
> - cid = cl_atomic_xchg(
> -
> &((al_conn_qp_t*)p_cm_dreq->h_qp)->cid, AL_INVALID_CID );
> - ref_al_obj( &p_cm_dreq->h_qp->obj );
> - if( cid == AL_INVALID_CID || al_destroy_cep(
> - p_cm_dreq->h_qp->obj.h_al, cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &p_cm_dreq->h_qp->obj );
> - }
> + al_destroy_cep( p_cm_dreq->h_qp->obj.h_al,
> + &((al_conn_qp_t*)p_cm_dreq->h_qp)->cid, TRUE,
> + deref_al_obj );
> status = IB_SUCCESS;
> }
>
> @@ -1700,7 +1616,6 @@ ib_cm_drep(
> IN const ib_cm_drep_t* const
> p_cm_drep )
> {
> ib_api_status_t status;
> - net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -1730,18 +1645,8 @@ ib_cm_drep(
> case IB_SUCCESS:
> __cep_timewait_qp( h_cm_dreq.h_qp );
>
> - cid = cl_atomic_xchg(
> -
> &((al_conn_qp_t*)h_cm_dreq.h_qp)->cid, AL_INVALID_CID );
> - if( cid != AL_INVALID_CID )
> - {
> - CL_ASSERT( cid == h_cm_dreq.cid );
> - ref_al_obj( &h_cm_dreq.h_qp->obj );
> - if( al_destroy_cep(
> - h_cm_dreq.h_al,
> h_cm_dreq.cid, deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_cm_dreq.h_qp->obj );
> - }
> - }
> + al_destroy_cep( h_cm_dreq.h_al,
> + &((al_conn_qp_t*)h_cm_dreq.h_qp)->cid, TRUE,
> + deref_al_obj );
> }
>
> AL_EXIT( AL_DBG_CM );
> @@ -1887,20 +1792,13 @@ static void
> __destroying_listen(
> IN al_obj_t*
> p_obj )
> {
> - ib_api_status_t status;
> al_listen_t *p_listen;
>
> p_listen = PARENT_STRUCT( p_obj, al_listen_t, obj );
>
> /* Destroy the listen's CEP. */
> - status = al_destroy_cep(
> - p_obj->h_al, p_listen->cid, deref_al_obj );
> - if( status != IB_SUCCESS )
> - {
> - AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> - ("al_destroy_cep returned %s.\n",
> ib_get_err_str( status )) );
> - deref_al_obj( p_obj );
> - }
> + al_destroy_cep(
> + p_obj->h_al, &p_listen->cid, TRUE, deref_al_obj );
> }
>
>
> @@ -1965,6 +1863,7 @@ __cep_listen(
> }
>
> /* Create a CEP to listen on. */
> + p_listen->cid = AL_INVALID_CID;
> status = al_create_cep( h_al, __cm_handler, p_listen,
> &p_listen->cid );
> if( status != IB_SUCCESS )
> {
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\al_qp.c trunk\core\al\al_qp.c
> --- old\core\al\al_qp.c Tue Jul 01 10:36:06 2008
> +++ trunk\core\al\al_qp.c Tue Jul 01 16:52:27 2008
> @@ -1048,7 +1048,6 @@ destroying_qp(
> ib_qp_handle_t h_qp;
> al_mad_qp_t *p_mad_qp;
> al_qp_alias_t *p_qp_alias;
> - net32_t cid;
>
> CL_ASSERT( p_obj );
> h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj ); @@
> -1117,17 +1116,7 @@ destroying_qp(
>
> case IB_QPT_RELIABLE_CONN:
> case IB_QPT_UNRELIABLE_CONN:
> - cid = cl_atomic_xchg(
> - &((al_conn_qp_t*)h_qp)->cid,
> AL_RESERVED_CID );
> - if( cid != AL_INVALID_CID )
> - {
> - ref_al_obj( &h_qp->obj );
> - if( al_destroy_cep(
> - h_qp->obj.h_al, cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> - }
> + al_destroy_cep( h_qp->obj.h_al,
> + &((al_conn_qp_t*)h_qp)->cid, FALSE, deref_al_obj );
> #ifdef CL_KERNEL
> ndi_qp_destroy( h_qp );
> #endif
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\al_qp.h trunk\core\al\al_qp.h
> --- old\core\al\al_qp.h Tue Jul 01 10:36:06 2008
> +++ trunk\core\al\al_qp.h Tue Jul 01 16:52:27 2008
> @@ -170,7 +170,7 @@ typedef struct _al_conn_qp
>
> ib_cm_handle_t p_conn;
>
> - atomic32_t cid;
> + net32_t cid;
>
> /* Callback table. */
> ib_pfn_cm_req_cb_t pfn_cm_req_cb;
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\kernel\al_cm_cep.c trunk\core\al\kernel\al_cm_cep.c
> --- old\core\al\kernel\al_cm_cep.c Tue Jul 01 16:52:15 2008
> +++ trunk\core\al\kernel\al_cm_cep.c Tue Jul 01 16:52:27 2008
> @@ -4067,7 +4067,7 @@ al_create_cep(
> IN ib_al_handle_t
> h_al,
> IN al_pfn_cep_cb_t
> pfn_cb,
> IN void*
> context,
> - OUT net32_t* const
> p_cid )
> + IN OUT net32_t* const
> p_cid )
> {
> kcep_t *p_cep;
> KLOCK_QUEUE_HANDLE hdl;
> @@ -4077,6 +4077,11 @@ al_create_cep(
> CL_ASSERT( p_cid );
>
> KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> + if( *p_cid != AL_INVALID_CID )
> + {
> + KeReleaseInStackQueuedSpinLock( &hdl );
> + return IB_RESOURCE_BUSY;
> + }
> p_cep = __create_cep();
> if( !p_cep )
> {
> @@ -4084,12 +4089,13 @@ al_create_cep(
> AL_PRINT_EXIT( TRACE_LEVEL_ERROR,
> AL_DBG_ERROR, ("Failed to allocate CEP.\n") );
> return IB_INSUFFICIENT_MEMORY;
> }
> - KeReleaseInStackQueuedSpinLock( &hdl );
>
> __bind_cep( p_cep, h_al, pfn_cb, context );
>
> *p_cid = p_cep->cid;
>
> + KeReleaseInStackQueuedSpinLock( &hdl );
> +
> AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_CM ,
> ("Created CEP with cid %d, h_al %p, context %p \n",
> p_cep->cid, h_al, p_cep->context )); @@
> -4099,12 +4105,14 @@ al_create_cep( }
>
>
> -ib_api_status_t
> +void
> al_destroy_cep(
> IN ib_al_handle_t
> h_al,
> - IN net32_t
> cid,
> + IN OUT net32_t* const
> p_cid,
> + IN boolean_t
> reusable,
> IN ib_pfn_destroy_cb_t
> pfn_destroy_cb )
> {
> + net32_t cid = *p_cid;
> kcep_t *p_cep;
> KLOCK_QUEUE_HANDLE hdl;
> void *context;
> @@ -4123,12 +4131,16 @@ al_destroy_cep(
> if( !p_cep )
> {
> /* Invalid handle. */
> + if( !reusable )
> + *p_cid = AL_RESERVED_CID;
> +
> KeReleaseInStackQueuedSpinLock( &hdl );
> AL_EXIT( AL_DBG_CM );
> - return IB_INVALID_PARAMETER;
> + return;
> }
>
> context = p_cep->context;
> +
> p_cep->pfn_destroy_cb = pfn_destroy_cb;
>
> /* Cancel any queued IRP */
> @@ -4155,6 +4167,11 @@ al_destroy_cep(
>
> __unbind_cep( p_cep );
> ref_cnt = __cleanup_cep( p_cep );
> + if( reusable )
> + *p_cid = AL_INVALID_CID;
> + else
> + *p_cid = AL_RESERVED_CID;
> +
> KeReleaseInStackQueuedSpinLock( &hdl );
>
> /*
> @@ -4169,7 +4186,6 @@ al_destroy_cep(
> cid, h_al, context ));
>
> AL_EXIT( AL_DBG_CM );
> - return IB_SUCCESS;
> }
>
>
> @@ -4986,6 +5002,7 @@ al_cep_pre_rep(
> IN net32_t
> cid,
> IN void*
> context,
> IN const ib_cm_rep_t* const
> p_cm_rep,
> + IN OUT net32_t* const
> p_cid,
> OUT ib_qp_mod_t* const
> p_init )
> {
> ib_api_status_t status;
> @@ -4999,6 +5016,13 @@ al_cep_pre_rep(
> CL_ASSERT( p_init );
>
> KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> + if( *p_cid != AL_INVALID_CID )
> + {
> + KeReleaseInStackQueuedSpinLock( &hdl );
> + AL_EXIT( AL_DBG_CM );
> + return IB_RESOURCE_BUSY;
> + }
> +
> p_cep = __lookup_cep( h_al, cid );
> if( !p_cep )
> {
> @@ -5009,6 +5033,11 @@ al_cep_pre_rep(
>
> status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );
>
> + if( status == IB_SUCCESS )
> + {
> + *p_cid = cid;
> + }
> +
> KeReleaseInStackQueuedSpinLock( &hdl );
> AL_EXIT( AL_DBG_CM );
> return status;
> @@ -5022,6 +5051,7 @@ al_cep_pre_rep_ex(
> IN al_pfn_cep_cb_t
> pfn_cb,
> IN void*
> context,
> IN const ib_cm_rep_t* const
> p_cm_rep,
> + IN OUT net32_t* const
> p_cid,
> OUT ib_qp_mod_t* const
> p_init )
> {
> ib_api_status_t status;
> @@ -5035,6 +5065,13 @@ al_cep_pre_rep_ex(
> CL_ASSERT( p_init );
>
> KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> + if( *p_cid != AL_INVALID_CID )
> + {
> + KeReleaseInStackQueuedSpinLock( &hdl );
> + AL_EXIT( AL_DBG_CM );
> + return IB_RESOURCE_BUSY;
> + }
> +
> p_cep = __lookup_cep( h_al, cid );
> if( !p_cep )
> {
> @@ -5045,9 +5082,10 @@ al_cep_pre_rep_ex(
>
> status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );
>
> - if (status == IB_SUCCESS)
> + if( status == IB_SUCCESS )
> {
> p_cep->pfn_cb = pfn_cb;
> + *p_cid = cid;
> }
>
> KeReleaseInStackQueuedSpinLock( &hdl ); @@ -6274,7
> +6312,7 @@ al_cep_cleanup_al(
> */
> cid = PARENT_STRUCT( p_item, kcep_t, al_item )->cid;
> cl_spinlock_release( &h_al->obj.lock );
> - al_destroy_cep( h_al, cid, NULL );
> + al_destroy_cep( h_al, &cid, FALSE, NULL );
> cl_spinlock_acquire( &h_al->obj.lock );
> }
> cl_spinlock_release( &h_al->obj.lock ); diff -up -r
> -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\kernel\al_ndi_cm.c trunk\core\al\kernel\al_ndi_cm.c
> --- old\core\al\kernel\al_ndi_cm.c Tue Jul 01 16:52:16 2008
> +++ trunk\core\al\kernel\al_ndi_cm.c Tue Jul 01 16:52:27 2008
> @@ -352,8 +352,7 @@ static VOID __ndi_complete_cancelled_irp
> )
> {
> ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> - ib_qp_handle_t VOID_PTR64 h_qp = p_ndi_csq->h_qp;
> - net32_t cid;
> + ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
>
> AL_ENTER( AL_DBG_NDI );
>
> @@ -361,12 +360,8 @@ static VOID __ndi_complete_cancelled_irp
> {
> case NDI_CM_CONNECTING_REQ_SENT:
> /* Cleanup from issuing CM REQ. */
> - ref_al_obj( &h_qp->obj );
> - cid = cl_atomic_xchg(
> &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );
> - if( cid == AL_INVALID_CID || al_destroy_cep(
> qp_get_al( h_qp ), cid, deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> + al_destroy_cep(
> + qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid,
> + TRUE, deref_al_obj );
> break;
>
> case NDI_CM_CONNECTING_ATS_SENT:
> @@ -544,7 +539,6 @@ __ndi_proc_rej(
> IN const ib_cm_handle_t* const p_cm,
> IN const mad_cm_rej_t* const
> p_rej )
> {
> - net32_t cid;
> NTSTATUS status;
> ib_qp_handle_t VOID_PTR64 h_qp = p_cm->h_qp;
> ndi_qp_csq_t *p_ndi_csq = h_qp->p_irp_que; @@ -555,14
> +549,8 @@ __ndi_proc_rej(
> ("p_rej %p, h_qp %#I64x, uhdl %#I64x, connect
> reject, reason=%hd\n",
> p_rej, (uint64_t)h_qp, h_qp->obj.hdl,
> cl_ntoh16(p_rej->reason) ) );
>
> - ref_al_obj( &h_qp->obj );
> - cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid,
> AL_INVALID_CID );
> - CL_ASSERT( cid == p_cm->cid || cid == AL_RESERVED_CID
> || cid == AL_INVALID_CID );
> - if( cid == AL_INVALID_CID ||
> - al_destroy_cep( p_cm->h_al, cid, deref_al_obj
> ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> + al_destroy_cep(
> + p_cm->h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE,
> + deref_al_obj );
>
> switch (p_ndi_csq->state)
> {
> @@ -881,9 +869,8 @@ __ndi_pr_query_cb(
> uint8_t pkt_life;
> ib_qp_mod_t qp_mod;
> ib_path_rec_t *p_path_rec;
> - ual_ndi_req_cm_ioctl_in_t *p_req =
> (ual_ndi_req_cm_ioctl_in_t* VOID_PTR64)p_query_rec->query_context;
> - ib_qp_handle_t VOID_PTR64 h_qp = (ib_qp_handle_t
> VOID_PTR64)HDL_TO_PTR(p_req->h_qp);
> - net32_t cid, old_cid;
> + ual_ndi_req_cm_ioctl_in_t *p_req =
> (ual_ndi_req_cm_ioctl_in_t* __ptr64)p_query_rec->query_context;
> + ib_qp_handle_t h_qp = (ib_qp_handle_t)p_req->h_qp;
>
> AL_ENTER( AL_DBG_NDI );
>
> @@ -891,8 +878,9 @@ __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) );
>
> + status = p_query_rec->status;
> h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
> - if( !h_ioctl || p_query_rec->status != IB_SUCCESS ||
> !p_query_rec->result_cnt )
> + if( !h_ioctl || status != IB_SUCCESS ||
> !p_query_rec->result_cnt
> + )
> goto err_irp_complete;
>
> /* Path Record has been received ! */ @@ -908,7
> +896,8 @@ __ndi_pr_query_cb(
> p_path_rec->pkt_life |= pkt_life;
>
> /* Get a CEP and bind it to the QP. */
> - status = al_create_cep( qp_get_al( h_qp ),
> __ndi_cm_handler, h_qp, &cid );
> + status = al_create_cep(
> + qp_get_al( h_qp ), __ndi_cm_handler, h_qp,
> + &((al_conn_qp_t*)h_qp)->cid );
> if( status != IB_SUCCESS )
> {
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, @@
> -917,12 +906,10 @@ __ndi_pr_query_cb(
> }
> AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> ("Created Active CEP with cid %d, h_al %p,
> context %p\n",
> - cid, qp_get_al( h_qp ), h_qp ) );
> + ((al_conn_qp_t*)h_qp)->cid, qp_get_al( h_qp
> ), h_qp ) );
>
> - /* See if this QP has already been connected. */
> - old_cid = cl_atomic_comp_xchg(
> &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID, cid );
> - if( old_cid != AL_INVALID_CID || h_qp->obj.state ==
> CL_DESTROYING )
> - goto err_cep_destroy;
> + /* Take a reference on behalf of the CEP. */
> + ref_al_obj( &h_qp->obj );
>
> /* Format ib_cm_req_t structure */
> __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req
> ); @@ -942,7 +929,7 @@ __ndi_pr_query_cb(
> IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL );
>
> /* send CM REQ */
> - status = al_cep_send_req( qp_get_al( h_qp ), cid );
> + status = al_cep_send_req( qp_get_al( h_qp ),
> + ((al_conn_qp_t*)h_qp)->cid );
> if( status != IB_SUCCESS )
> goto err_irp_remove;
>
> @@ -956,22 +943,28 @@ err_irp_remove:
> h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
>
> err_cep_destroy:
> - al_destroy_cep( qp_get_al( h_qp ), cid, NULL );
> + al_destroy_cep(
> + qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE,
> + deref_al_obj );
>
> err_irp_complete:
> h_qp->p_irp_que->state = NDI_CM_IDLE;
> /* the IRP "has" 2 QP references, taken in __ndi_ats_query */
> if ( h_ioctl )
> - {
> - if( p_query_rec->status == IB_TIMEOUT )
> - {
> + {
> + switch( status )
> + {
> + case IB_TIMEOUT:
> __ndi_complete_irp( h_qp, h_ioctl,
> STATUS_TIMEOUT );
> - }
> - else
> - {
> + break;
> +
> + case IB_INVALID_STATE:
> + __ndi_complete_irp( h_qp, h_ioctl,
> STATUS_CONNECTION_ACTIVE );
> + break;
> +
> + default:
> __ndi_complete_irp( h_qp, h_ioctl,
> STATUS_HOST_UNREACHABLE );
> - }
> - }
> + }
> + }
> deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
>
> exit:
> @@ -1254,7 +1247,6 @@ __ndi_rtu_cm(
> status = al_cep_rtu( qp_get_al( h_qp ),
> ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );
> if( status != IB_SUCCESS )
> {
> - net32_t cid;
> err:
> /* Reject and abort the connection. */
> al_cep_rej(
> @@ -1263,16 +1255,8 @@ err:
>
> __cep_timewait_qp( h_qp );
>
> - cid = cl_atomic_xchg(
> &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );
> -
> - if( cid != AL_INVALID_CID )
> - {
> - ref_al_obj( &h_qp->obj );
> - if( al_destroy_cep( qp_get_al( h_qp
> ), cid, deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> - }
> + al_destroy_cep(
> + qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid,
> + TRUE, deref_al_obj );
>
> AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> ("al_cep_rtu returned %s.\n",
> ib_get_err_str( status )) ); @@ -1372,17 +1356,14 @@ __ndi_rep_cm(
> else
> nt_status = STATUS_CONNECTION_ABORTED;
> err:
> - cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid,
> AL_INVALID_CID );
> -
> /* Reject and abort the connection. */
> al_cep_rej( qp_get_al( h_qp ), p_rep->cid,
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
>
> /* transit QP to error state */
> __cep_timewait_qp( h_qp );
>
> - ref_al_obj( &h_qp->obj );
> - if( al_destroy_cep( qp_get_al( h_qp ),
> p_rep->cid, deref_al_obj ) != IB_SUCCESS )
> - deref_al_obj( &h_qp->obj );
> + al_destroy_cep(
> + qp_get_al( h_qp ),
> &((al_conn_qp_t*)h_qp)->cid,
> + TRUE, deref_al_obj );
>
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> ("al_cep_rtu returned %s.\n",
> ib_get_err_str( status )) ); @@ -1434,8 +1415,8 @@ __ndi_fill_cm_rep(
>
> NTSTATUS
> ndi_rep_cm(
> - IN ib_qp_handle_t FUNC_PTR64 const
> h_qp,
> - IN net32_t const
> cid,
> + IN ib_qp_handle_t const
> h_qp,
> + IN net32_t
> cid,
> IN PIRP
> p_irp,
> IN ual_ndi_rep_cm_ioctl_in_t
> *p_rep
> )
> @@ -1443,7 +1424,6 @@ ndi_rep_cm(
> IO_STACK_LOCATION *p_io_stack;
> ib_cm_rep_t cm_rep;
> ib_qp_mod_t qp_mod;
> - net32_t old_cid;
> ib_api_status_t status;
> NTSTATUS nt_status;
>
> @@ -1453,7 +1433,9 @@ ndi_rep_cm(
> __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );
>
> /* prepare Passive CEP for connection */
> - status = al_cep_pre_rep_ex( qp_get_al( h_qp ), cid,
> __ndi_cm_handler, h_qp, &cm_rep, &qp_mod );
> + status = al_cep_pre_rep_ex(
> + qp_get_al( h_qp ), cid, __ndi_cm_handler,
> h_qp, &cm_rep,
> + &((al_conn_qp_t*)h_qp)->cid, &qp_mod );
> if( status != IB_SUCCESS )
> {
> AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, @@
> -1466,25 +1448,27 @@ ndi_rep_cm(
> case IB_INVALID_STATE:
> nt_status = STATUS_CONNECTION_ABORTED;
> break;
> + case IB_RESOURCE_BUSY:
> + nt_status = STATUS_CONNECTION_ACTIVE;
> + break;
> default:
> nt_status =
> STATUS_INSUFFICIENT_RESOURCES;
> break;
> }
> - goto err_cep_destroy;
> + al_destroy_cep( qp_get_al( h_qp ), &cid,
> FALSE, NULL );
> +
> + h_qp->p_irp_que->state = NDI_CM_IDLE;
> + cl_ioctl_complete( p_irp, nt_status, 0 );
> + goto exit;
> }
>
> + /* Take a reference on behalf of the CEP. */
> + ref_al_obj( &h_qp->obj );
> +
> AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> ("Prepared Passive CEP with cid %d, h_al %p,
> context %p\n",
> cid, qp_get_al( h_qp ), h_qp ) );
>
> - /* See if this QP has already been connected. */
> - old_cid = cl_atomic_comp_xchg(
> &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID, cid );
> - if( old_cid != AL_INVALID_CID )
> - {
> - nt_status = STATUS_CONNECTION_ACTIVE;
> - goto err_cep_destroy;
> - }
> -
> /* transfer work to a work the thread */
> p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
> @@ -1501,13 +1485,6 @@ ndi_rep_cm(
> { /* syncronous performing */
> __ndi_rep_cm( p_io_stack->DeviceObject, p_irp );
> }
> - goto exit;
> -
> -err_cep_destroy:
> - al_destroy_cep( qp_get_al( h_qp ), cid, NULL );
> -
> - h_qp->p_irp_que->state = NDI_CM_IDLE;
> - cl_ioctl_complete( p_irp, nt_status, 0 );
>
> exit:
> AL_EXIT( AL_DBG_NDI );
> @@ -1528,7 +1505,6 @@ ndi_dreq_cm(
> )
> {
> ib_qp_mod_t qp_mod;
> - net32_t cid;
> ib_api_status_t status;
> NTSTATUS nt_status;
> uint64_t timewait_us;
> @@ -1544,16 +1520,8 @@ ndi_dreq_cm(
> goto exit;
> }
>
> - cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid,
> AL_INVALID_CID );
> -
> - if( cid != AL_INVALID_CID )
> - {
> - ref_al_obj( &h_qp->obj );
> - if( al_destroy_cep( qp_get_al( h_qp ), cid,
> deref_al_obj ) != IB_SUCCESS )
> - {
> - deref_al_obj( &h_qp->obj );
> - }
> - }
> + al_destroy_cep(
> + qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE,
> + deref_al_obj );
>
> /* bring QP to error state */
> cl_memclr( &qp_mod, sizeof(qp_mod) ); diff -up -r -X
> trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\kernel\al_ndi_cm.h trunk\core\al\kernel\al_ndi_cm.h
> --- old\core\al\kernel\al_ndi_cm.h Mon Jun 30 14:50:58 2008
> +++ trunk\core\al\kernel\al_ndi_cm.h Tue Jul 01 16:52:27 2008
> @@ -107,7 +107,7 @@ ndi_req_cm(
> NTSTATUS
> ndi_rep_cm(
> IN ib_qp_handle_t const h_qp,
> - IN net32_t const
> cid,
> + IN net32_t
> cid,
> IN cl_ioctl_handle_t
> h_ioctl,
> IN ual_ndi_rep_cm_ioctl_in_t
> *p_ndi_rep_cm
> );
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\kernel\al_proxy_cep.c trunk\core\al\kernel\al_proxy_cep.c
> --- old\core\al\kernel\al_proxy_cep.c Tue Jul 01 16:52:15 2008
> +++ trunk\core\al\kernel\al_proxy_cep.c Tue Jul 01 16:52:27 2008
> @@ -72,6 +72,7 @@ proxy_create_cep(
> p_user_context = 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,
> *p_user_context, &p_ioctl->cid );
>
> @@ -123,7 +124,7 @@ proxy_destroy_cep(
> }
>
> al_destroy_cep( p_context->h_al,
> - *(net32_t*)cl_ioctl_in_buf( h_ioctl ), NULL );
> + (net32_t*)cl_ioctl_in_buf( h_ioctl ), TRUE, NULL );
>
> AL_EXIT( AL_DBG_CM );
> return CL_SUCCESS;
> @@ -269,6 +270,7 @@ proxy_cep_pre_rep(
> al_dev_open_context_t *p_context;
> ual_cep_rep_ioctl_t *p_ioctl;
> ib_qp_handle_t h_qp;
> + net32_t cid;
>
> AL_ENTER( AL_DBG_CM );
>
> @@ -299,8 +301,9 @@ proxy_cep_pre_rep(
>
> p_ioctl->in.cm_rep.h_qp = h_qp;
>
> + cid = AL_INVALID_CID;
> p_ioctl->out.status = al_cep_pre_rep(
> p_context->h_al, p_ioctl->in.cid,
> - p_ioctl->in.context, &p_ioctl->in.cm_rep,
> &p_ioctl->out.init );
> + p_ioctl->in.context, &p_ioctl->in.cm_rep, &cid,
> + &p_ioctl->out.init );
>
> deref_al_obj( &h_qp->obj );
>
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\kernel\al_proxy_ndi.c trunk\core\al\kernel\al_proxy_ndi.c
> --- old\core\al\kernel\al_proxy_ndi.c Tue Jul 01 16:52:15 2008
> +++ trunk\core\al\kernel\al_proxy_ndi.c Tue Jul 01 16:52:27 2008
> @@ -469,7 +469,7 @@ __ndi_rej_cm(
> goto exit;
> }
>
> - al_destroy_cep( p_context->h_al, cid, NULL );
> + al_destroy_cep( p_context->h_al, &cid, FALSE, NULL );
> h_ioctl->IoStatus.Status = STATUS_SUCCESS;
>
> exit:
> diff -up -r -X trunk\docs\dontdiff.txt -I \$Id:
> old\core\al\user\ual_cm_cep.c trunk\core\al\user\ual_cm_cep.c
> --- old\core\al\user\ual_cm_cep.c Tue Jul 01 10:36:06 2008
> +++ trunk\core\al\user\ual_cm_cep.c Tue Jul 01 16:52:27 2008
> @@ -221,7 +221,7 @@ al_cep_cleanup_al(
> */
> cid = PARENT_STRUCT( p_item, ucep_t, al_item )->cid;
> cl_spinlock_release( &h_al->obj.lock );
> - al_destroy_cep( h_al, cid, NULL );
> + al_destroy_cep( h_al, &cid, FALSE, NULL );
> cl_spinlock_acquire( &h_al->obj.lock );
> }
> cl_spinlock_release( &h_al->obj.lock ); @@ -246,7
> +246,7 @@ __create_ucep(
> IN net32_t
> cid,
> IN al_pfn_cep_cb_t
> pfn_cb,
> IN void*
> context,
> - OUT net32_t* const
> p_cid )
> + IN OUT net32_t* const
> p_cid )
> {
> ucep_t *p_cep;
> DWORD bytes_ret;
> @@ -326,11 +326,20 @@ __create_ucep(
>
> /* Track the CEP in its owning AL instance. */
> cl_spinlock_acquire( &h_al->obj.lock );
> - cl_qlist_insert_tail( &h_al->cep_list, &p_cep->al_item );
> - cl_spinlock_release( &h_al->obj.lock );
> -
> if( p_cid )
> + {
> + if( *p_cid != AL_INVALID_CID )
> + {
> + cl_spinlock_release( &h_al->obj.lock );
> + al_destroy_cep( h_al, &cid, TRUE, NULL );
> + return IB_INVALID_STATE;
> + }
> *p_cid = p_cep->cid;
> + }
> +
> + cl_qlist_insert_tail( &h_al->cep_list, &p_cep->al_item );
> +
> + cl_spinlock_release( &h_al->obj.lock );
>
> AL_EXIT( AL_DBG_CM );
> return IB_SUCCESS;
> @@ -342,7 +351,7 @@ al_create_cep(
> IN ib_al_handle_t
> h_al,
> IN al_pfn_cep_cb_t
> pfn_cb,
> IN void*
> context,
> - OUT net32_t* const
> p_cid )
> + IN OUT net32_t* const
> p_cid )
> {
> ib_api_status_t status;
>
> @@ -359,10 +368,11 @@ al_create_cep(
> * Note that destroy_cep is synchronous. It does however
> handle the case
> * where a user calls it from a callback context.
> */
> -ib_api_status_t
> +void
> al_destroy_cep(
> IN ib_al_handle_t
> h_al,
> - IN net32_t
> cid,
> + IN OUT net32_t* const
> p_cid,
> + IN boolean_t
> reusable,
> IN ib_pfn_destroy_cb_t
> pfn_destroy_cb OPTIONAL )
> {
> ucep_t *p_cep;
> @@ -373,20 +383,23 @@ al_destroy_cep(
> CL_ASSERT( h_al );
>
> cl_spinlock_acquire( &gp_cep_mgr->obj.lock );
> - if( cid < cl_ptr_vector_get_size( &gp_cep_mgr->cep_vector ) )
> + if( *p_cid < cl_ptr_vector_get_size(
> &gp_cep_mgr->cep_vector ) )
> {
> - p_cep = cl_ptr_vector_get(
> &gp_cep_mgr->cep_vector, cid );
> + p_cep = cl_ptr_vector_get( &gp_cep_mgr->cep_vector,
> + *p_cid );
> if( p_cep && p_cep->h_al == h_al )
> - cl_ptr_vector_set(
> &gp_cep_mgr->cep_vector, cid, NULL );
> + cl_ptr_vector_set( &gp_cep_mgr->cep_vector,
> + *p_cid, NULL );
> else
> goto invalid;
> }
> else
> {
> invalid:
> + if( !reusable )
> + *p_cid = AL_RESERVED_CID;
> +
> cl_spinlock_release( &gp_cep_mgr->obj.lock );
> AL_EXIT( AL_DBG_CM );
> - return IB_INVALID_PARAMETER;
> + return;
> }
>
> /*
> @@ -395,7 +408,10 @@ invalid:
> */
> DeviceIoControl( g_al_device, UAL_DESTROY_CEP, &p_cep->cid,
> sizeof(p_cep->cid), NULL, 0, &bytes_ret, NULL );
> - p_cep->cid = AL_INVALID_CID;
> + if( reusable )
> + *p_cid = AL_INVALID_CID;
> + else
> + *p_cid = AL_RESERVED_CID;
>
> cl_spinlock_release( &gp_cep_mgr->obj.lock );
>
> @@ -407,6 +423,7 @@ invalid:
> */
> cl_spinlock_acquire( &h_al->obj.lock );
> cl_qlist_remove_item( &h_al->cep_list, &p_cep->al_item );
> +
> cl_spinlock_release( &h_al->obj.lock );
>
> if( !cl_atomic_dec( &p_cep->ref_cnt ) ) @@ -416,7
> +433,6 @@ invalid:
> }
>
> AL_EXIT( AL_DBG_CM );
> - return IB_SUCCESS;
> }
>
>
> @@ -590,6 +606,7 @@ al_cep_pre_rep(
> IN net32_t
> cid,
> IN void*
> context,
> IN const ib_cm_rep_t* const
> p_cm_rep,
> + IN OUT net32_t* const
> p_cid,
> OUT ib_qp_mod_t* const
> p_init )
> {
> ucep_t *p_cep;
> @@ -657,7 +674,16 @@ al_cep_pre_rep(
> }
>
> if( ioctl.out.status == IB_SUCCESS )
> + {
> + cl_spinlock_acquire( &h_al->obj.lock );
> + if( *p_cid != AL_INVALID_CID )
> + {
> + cl_spinlock_release( &h_al->obj.lock );
> + return IB_INVALID_STATE;
> + }
> + *p_cid = p_cep->cid;
> *p_init = ioctl.out.init;
> + }
>
> AL_EXIT( AL_DBG_CM );
> return ioctl.out.status;
>
>
More information about the ofw
mailing list