[ofw] [PATCH] Fix race reading/setting connection ID

Fab Tillier ftillier at windows.microsoft.com
Tue Jul 1 17:02:47 PDT 2008


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;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: cep_cid.patch
Type: application/octet-stream
Size: 36435 bytes
Desc: cep_cid.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080701/b7fd5411/attachment.obj>


More information about the ofw mailing list