[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