[IBAL] IBAL has two reserved CID values that it stores in the QPs - AL_INVALID_CID...
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 2 Jul 2008 13:32:47 +0000 (13:32 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 2 Jul 2008 13:32:47 +0000 (13:32 +0000)
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@microsoft.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1326 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

core/al/al_cm_cep.h
core/al/al_cm_qp.c
core/al/al_qp.c
core/al/al_qp.h
core/al/kernel/al_cm_cep.c
core/al/kernel/al_ndi_cm.c
core/al/kernel/al_ndi_cm.h
core/al/kernel/al_proxy_cep.c
core/al/kernel/al_proxy_ndi.c
core/al/user/ual_cm_cep.c

index 0f94b0a..6011827 100644 (file)
@@ -95,10 +95,10 @@ al_cep_cleanup_al(
 \r
 ib_api_status_t\r
 al_create_cep(\r
-       IN                              ib_al_handle_t FUNC_PTR64                               h_al,\r
+       IN                              ib_al_handle_t                          h_al,\r
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
-       IN                              void* FUNC_PTR64                                context,\r
-               OUT                     net32_t* const                          p_cid );\r
+       IN                              void*                                           context,\r
+       IN      OUT                     net32_t* const                          p_cid );\r
 /*\r
 * NOTES\r
 *      This function may be invoked at DISPATCH_LEVEL\r
@@ -107,12 +107,12 @@ al_create_cep(
 * event notification.\r
 *********/\r
 \r
-\r
 /* Destruction is asynchronous. */\r
-ib_api_status_t\r
+void\r
 al_destroy_cep(\r
-       IN                              ib_al_handle_t FUNC_PTR64                               h_al,\r
-       IN                              net32_t                                         cid,\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
+       IN                              boolean_t                                       reusable,\r
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb );\r
 /*\r
 *********/\r
@@ -144,6 +144,7 @@ al_cep_pre_rep(
        IN                              net32_t                                         cid,\r
        IN                              void*                                           context,\r
        IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init );\r
 \r
 ib_api_status_t\r
@@ -153,6 +154,7 @@ al_cep_pre_rep_ex(
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
        IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init );\r
 \r
 ib_api_status_t\r
index a897336..457a17d 100644 (file)
@@ -261,7 +261,7 @@ __listen_req(
 static void\r
 __proc_listen(\r
        IN                              al_listen_t* const                      p_listen,\r
-       IN              const   net32_t                                         new_cid,\r
+       IN                              net32_t                                         new_cid,\r
        IN              const   ib_mad_t* const                         p_mad )\r
 {\r
        AL_ENTER( AL_DBG_CM );\r
@@ -280,7 +280,7 @@ __proc_listen(
                CL_ASSERT( p_mad->attr_id == CM_REQ_ATTR_ID ||\r
                        p_mad->attr_id == CM_SIDR_REQ_ATTR_ID );\r
                /* Destroy the new CEP as it won't ever be reported to the user. */\r
-               al_destroy_cep( p_listen->obj.h_al, new_cid, NULL );\r
+               al_destroy_cep( p_listen->obj.h_al, &new_cid, FALSE, NULL );\r
        }\r
 \r
        AL_EXIT( AL_DBG_CM );\r
@@ -302,7 +302,6 @@ __proc_conn_timeout(
        IN              const   ib_qp_handle_t                          h_qp )\r
 {\r
        ib_cm_rej_rec_t         rej_rec;\r
-       net32_t                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -317,22 +316,15 @@ __proc_conn_timeout(
        rej_rec.qp_context = h_qp->obj.context;\r
        rej_rec.rej_status = IB_REJ_TIMEOUT;\r
 \r
-       ref_al_obj( &h_qp->obj );\r
-\r
        /* Unbind the QP from the CEP. */\r
        __cep_timewait_qp( h_qp );\r
 \r
-       cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
+       al_destroy_cep(\r
+               h_qp->obj.h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
 \r
        /* Invoke the callback. */\r
        ((al_conn_qp_t*)h_qp)->pfn_cm_rej_cb( &rej_rec );\r
 \r
-       if( cid == AL_INVALID_CID ||\r
-               al_destroy_cep( h_qp->obj.h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-       {\r
-               deref_al_obj( &h_qp->obj );\r
-       }\r
-\r
        AL_EXIT( AL_DBG_CM );\r
 }\r
 \r
@@ -373,7 +365,6 @@ __proc_dconn_timeout(
        IN              const   ib_qp_handle_t                          h_qp )\r
 {\r
        ib_cm_drep_rec_t        drep_rec;\r
-       net32_t                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -383,21 +374,14 @@ __proc_dconn_timeout(
        drep_rec.qp_context = h_qp->obj.context;\r
        drep_rec.cm_status = IB_TIMEOUT;\r
 \r
-       ref_al_obj( &h_qp->obj );\r
-\r
        __cep_timewait_qp( h_qp );\r
 \r
-       cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
+       al_destroy_cep(\r
+               h_qp->obj.h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
 \r
        /* Call the user back. */\r
        ((al_conn_qp_t*)h_qp)->pfn_cm_drep_cb( &drep_rec );\r
 \r
-       if( cid == AL_INVALID_CID ||\r
-               al_destroy_cep( h_qp->obj.h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-       {\r
-               deref_al_obj( &h_qp->obj );\r
-       }\r
-\r
        AL_EXIT( AL_DBG_CM );\r
 }\r
 \r
@@ -503,7 +487,6 @@ __proc_rej(
        IN              const   mad_cm_rej_t* const                     p_rej )\r
 {\r
        ib_cm_rej_rec_t rej_rec;\r
-       net32_t                 cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -520,21 +503,14 @@ __proc_rej(
                rej_rec.ari_length = conn_rej_get_ari_len( p_rej );\r
                rej_rec.rej_status = p_rej->reason;\r
 \r
-               ref_al_obj( &p_cm->h_qp->obj );\r
-\r
                /*\r
                 * Unbind the QP from the connection object.  This allows the QP to\r
                 * be immediately reused in another connection request.\r
                 */\r
                __cep_timewait_qp( p_cm->h_qp );\r
 \r
-               cid = cl_atomic_xchg( &((al_conn_qp_t*)p_cm->h_qp)->cid, AL_INVALID_CID );\r
-               CL_ASSERT( cid == p_cm->cid || cid == AL_INVALID_CID || cid == AL_RESERVED_CID );\r
-               if( cid == AL_INVALID_CID ||\r
-                       al_destroy_cep( p_cm->h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-               {\r
-                       deref_al_obj( &p_cm->h_qp->obj );\r
-               }\r
+               al_destroy_cep(\r
+                       p_cm->h_al, &((al_conn_qp_t*)p_cm->h_qp)->cid, TRUE, deref_al_obj );\r
 \r
                /* Call the user back. */\r
                ((al_conn_qp_t*)p_cm->h_qp)->pfn_cm_rej_cb( &rej_rec );\r
@@ -619,7 +595,6 @@ __proc_drep(
        IN                              mad_cm_drep_t* const            p_drep )\r
 {\r
        ib_cm_drep_rec_t        drep_rec;\r
-       net32_t                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -631,25 +606,10 @@ __proc_drep(
        drep_rec.h_qp = p_cm->h_qp;\r
        drep_rec.qp_context = p_cm->h_qp->obj.context;\r
 \r
-       ref_al_obj( &p_cm->h_qp->obj );\r
-\r
        __cep_timewait_qp( p_cm->h_qp );\r
 \r
-       cid = cl_atomic_xchg( &((al_conn_qp_t*)p_cm->h_qp)->cid, AL_INVALID_CID );\r
-       if( cid != AL_INVALID_CID )\r
-       {\r
-               CL_ASSERT( cid == p_cm->cid || cid == AL_RESERVED_CID );\r
-\r
-               if( al_destroy_cep(\r
-                       p_cm->h_al, p_cm->cid, deref_al_obj ) != IB_SUCCESS )\r
-               {\r
-                       deref_al_obj( &p_cm->h_qp->obj );\r
-               }\r
-       }\r
-       else\r
-       {\r
-               deref_al_obj( &p_cm->h_qp->obj );\r
-       }\r
+       al_destroy_cep(\r
+               p_cm->h_al, &((al_conn_qp_t*)p_cm->h_qp)->cid, TRUE, deref_al_obj );\r
 \r
        ((al_conn_qp_t*)p_cm->h_qp)->pfn_cm_drep_cb( &drep_rec );\r
 \r
@@ -1060,7 +1020,6 @@ __cep_conn_req(
        //cl_event_t                    sync_event;\r
        //cl_event_t                    *p_sync_event = NULL;\r
        al_conn_qp_t            *p_qp;\r
-       net32_t                         cid, old_cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -1082,7 +1041,7 @@ __cep_conn_req(
        p_qp = (al_conn_qp_t*)p_cm_req->h_qp;\r
 \r
        /* Get a CEP and bind it to the QP. */\r
-       status = al_create_cep( h_al, __cm_handler, p_cm_req->h_qp, &cid );\r
+       status = al_create_cep( h_al, __cm_handler, p_qp, &p_qp->cid );\r
        if( status != IB_SUCCESS )\r
        {\r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
@@ -1090,14 +1049,8 @@ __cep_conn_req(
                goto done;\r
        }\r
 \r
-       /* See if this QP has already been connected. */\r
-       old_cid = cl_atomic_comp_xchg( &p_qp->cid, AL_INVALID_CID, cid );\r
-       if( old_cid != AL_INVALID_CID )\r
-       {\r
-               al_destroy_cep( h_al, cid, NULL );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_INVALID_STATE;\r
-       }\r
+       /* Take a reference on behalf of the CEP. */\r
+       ref_al_obj( &p_qp->qp.obj );\r
 \r
        status = __cep_pre_req( p_cm_req );\r
        if( status != IB_SUCCESS )\r
@@ -1123,10 +1076,7 @@ __cep_conn_req(
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
                        ("al_cep_send_req returned %s.\n", ib_get_err_str(status)) );\r
 err:\r
-               ref_al_obj( &p_qp->qp.obj );\r
-               cl_atomic_xchg( &p_qp->cid, AL_INVALID_CID );\r
-               if( al_destroy_cep( h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-                       deref_al_obj( &p_qp->qp.obj );\r
+               al_destroy_cep( h_al, &p_qp->cid, TRUE, deref_al_obj );\r
        }\r
 \r
        /* wait on event if synchronous operation */\r
@@ -1322,22 +1272,35 @@ __cep_conn_rep(
        IN      const           ib_cm_rep_t* const                      p_cm_rep )\r
 {\r
        ib_api_status_t         status;\r
-       net32_t                         cid;\r
        ib_qp_mod_t                     qp_mod;\r
-       boolean_t                       qp_linked = FALSE;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
-       cid = cl_atomic_comp_xchg(\r
-               &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, AL_INVALID_CID, h_cm.cid );\r
-\r
-       if( cid != AL_INVALID_CID )\r
+       status = al_cep_pre_rep(\r
+               h_cm.h_al, h_cm.cid, p_cm_rep->h_qp, p_cm_rep,\r
+               &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, &qp_mod );\r
+       switch( status )\r
        {\r
+       case IB_SUCCESS:\r
+               break;\r
+\r
+       case IB_RESOURCE_BUSY:\r
                /* We don't destroy the CEP to allow the user to retry accepting. */\r
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("QP already connected.\n") );\r
                return IB_INVALID_QP_HANDLE;\r
+\r
+       default:\r
+               al_cep_rej( h_cm.h_al, h_cm.cid, IB_REJ_INSUF_RESOURCES, NULL, 0, NULL, 0 );\r
+               al_destroy_cep( h_cm.h_al, &h_cm.cid, FALSE, NULL );\r
+\r
+               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
+                       ("al_cep_pre_rep returned %s.\n", ib_get_err_str( status )) );\r
+               return status;\r
        }\r
 \r
+       /* Take a reference on behalf of the CEP. */\r
+       ref_al_obj( &p_cm_rep->h_qp->obj );\r
+\r
        /* Store the CM callbacks. */\r
        ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_rej_cb = p_cm_rep->pfn_cm_rej_cb;\r
        ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_mra_cb = p_cm_rep->pfn_cm_mra_cb;\r
@@ -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;\r
        ((al_conn_qp_t*)p_cm_rep->h_qp)->pfn_cm_dreq_cb = p_cm_rep->pfn_cm_dreq_cb;\r
 \r
-       status = al_cep_pre_rep(\r
-               h_cm.h_al, h_cm.cid, p_cm_rep->h_qp, p_cm_rep, &qp_mod );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("al_cep_pre_rep returned %s.\n", ib_get_err_str( status )) );\r
-               goto err;\r
-       }\r
-\r
-       /* The QP has been set as the context for the CEP. */\r
-       qp_linked = TRUE;\r
-\r
        /* Transition QP through state machine */\r
        status = __cep_pre_rep( h_cm, &qp_mod, p_cm_rep );\r
        if( status != IB_SUCCESS )\r
@@ -1372,23 +1323,11 @@ __cep_conn_rep(
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
                        ("al_cep_send_rep returned %s\n", ib_get_err_str(status)) );\r
 err:\r
-               cl_atomic_xchg(\r
-                       &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, AL_INVALID_CID );\r
 \r
                /* Reject and abort the connection. */\r
                al_cep_rej( h_cm.h_al, h_cm.cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
-\r
-               if( qp_linked )\r
-               {\r
-                       ref_al_obj( &p_cm_rep->h_qp->obj );\r
-\r
-                       if( al_destroy_cep( h_cm.h_al, h_cm.cid, deref_al_obj ) != IB_SUCCESS )\r
-                               deref_al_obj( &p_cm_rep->h_qp->obj );\r
-               }\r
-               else\r
-               {\r
-                       al_destroy_cep( h_cm.h_al, h_cm.cid, NULL );\r
-               }\r
+               al_destroy_cep(\r
+                       h_cm.h_al, &((al_conn_qp_t*)p_cm_rep->h_qp)->cid, TRUE, deref_al_obj );\r
        }\r
 \r
        AL_EXIT( AL_DBG_CM );\r
@@ -1402,6 +1341,7 @@ ib_cm_rep(
        IN              const   ib_cm_rep_t* const                      p_cm_rep )\r
 {\r
        ib_api_status_t         status;\r
+       net32_t                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -1448,9 +1388,10 @@ ib_cm_rep(
 \r
        if( status != IB_SUCCESS )\r
        {\r
+               cid = h_cm_req.cid;\r
                al_cep_rej(\r
                        h_cm_req.h_al, h_cm_req.cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
-               al_destroy_cep( h_cm_req.h_al, h_cm_req.cid, NULL );\r
+               al_destroy_cep( h_cm_req.h_al, &cid, FALSE, NULL );\r
 \r
                AL_EXIT( AL_DBG_CM );\r
                return status;\r
@@ -1472,7 +1413,6 @@ ib_cm_rtu(
        IN              const   ib_cm_rtu_t* const                      p_cm_rtu )\r
 {\r
        ib_api_status_t         status;\r
-       net32_t                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -1519,20 +1459,8 @@ err:
 \r
                __cep_timewait_qp( h_cm_rep.h_qp );\r
 \r
-               cid = cl_atomic_xchg(\r
-                       &((al_conn_qp_t*)h_cm_rep.h_qp)->cid, AL_INVALID_CID );\r
-\r
-               if( cid != AL_INVALID_CID )\r
-               {\r
-                       CL_ASSERT( cid == h_cm_rep.cid );\r
-\r
-                       ref_al_obj( &h_cm_rep.h_qp->obj );\r
-                       if( al_destroy_cep(\r
-                               h_cm_rep.h_al, h_cm_rep.cid, deref_al_obj ) != IB_SUCCESS )\r
-                       {\r
-                               deref_al_obj( &h_cm_rep.h_qp->obj );\r
-                       }\r
-               }\r
+               al_destroy_cep(\r
+                       h_cm_rep.h_al, &((al_conn_qp_t*)h_cm_rep.h_qp)->cid, TRUE, deref_al_obj );\r
 \r
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
                        ("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );\r
@@ -1595,18 +1523,13 @@ ib_cm_rej(
        {\r
                __cep_timewait_qp( h_cm.h_qp );\r
 \r
-               cid = cl_atomic_xchg(\r
-                       &((al_conn_qp_t*)h_cm.h_qp)->cid, AL_INVALID_CID );\r
-               if( cid != AL_INVALID_CID )\r
-               {\r
-                       ref_al_obj( &h_cm.h_qp->obj );\r
-                       if( al_destroy_cep( h_cm.h_al, h_cm.cid, deref_al_obj ) != IB_SUCCESS )\r
-                               deref_al_obj( &h_cm.h_qp->obj );\r
-               }\r
+               al_destroy_cep(\r
+                       h_cm.h_al, &((al_conn_qp_t*)h_cm.h_qp)->cid, TRUE, deref_al_obj );\r
        }\r
        else\r
        {\r
-               al_destroy_cep( h_cm.h_al, h_cm.cid, NULL );\r
+               cid = h_cm.cid;\r
+               al_destroy_cep( h_cm.h_al, &cid, FALSE, NULL );\r
        }\r
 \r
        AL_EXIT( AL_DBG_CM );\r
@@ -1619,7 +1542,6 @@ ib_cm_dreq(
        IN              const   ib_cm_dreq_t* const                     p_cm_dreq )\r
 {\r
        ib_api_status_t status;\r
-       net32_t                 cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -1677,14 +1599,8 @@ ib_cm_dreq(
                 */\r
                __cep_timewait_qp( p_cm_dreq->h_qp );\r
 \r
-               cid = cl_atomic_xchg(\r
-                       &((al_conn_qp_t*)p_cm_dreq->h_qp)->cid, AL_INVALID_CID );\r
-               ref_al_obj( &p_cm_dreq->h_qp->obj );\r
-               if( cid == AL_INVALID_CID || al_destroy_cep(\r
-                       p_cm_dreq->h_qp->obj.h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-               {\r
-                       deref_al_obj( &p_cm_dreq->h_qp->obj );\r
-               }\r
+               al_destroy_cep( p_cm_dreq->h_qp->obj.h_al,\r
+                       &((al_conn_qp_t*)p_cm_dreq->h_qp)->cid, TRUE, deref_al_obj );\r
                status = IB_SUCCESS;\r
        }\r
 \r
@@ -1700,7 +1616,6 @@ ib_cm_drep(
        IN              const   ib_cm_drep_t* const                     p_cm_drep )\r
 {\r
        ib_api_status_t         status;\r
-       net32_t                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -1730,18 +1645,8 @@ ib_cm_drep(
        case IB_SUCCESS:\r
                __cep_timewait_qp( h_cm_dreq.h_qp );\r
 \r
-               cid = cl_atomic_xchg(\r
-                       &((al_conn_qp_t*)h_cm_dreq.h_qp)->cid, AL_INVALID_CID );\r
-               if( cid != AL_INVALID_CID )\r
-               {\r
-                       CL_ASSERT( cid == h_cm_dreq.cid );\r
-                       ref_al_obj( &h_cm_dreq.h_qp->obj );\r
-                       if( al_destroy_cep(\r
-                               h_cm_dreq.h_al, h_cm_dreq.cid, deref_al_obj ) != IB_SUCCESS )\r
-                       {\r
-                               deref_al_obj( &h_cm_dreq.h_qp->obj );\r
-                       }\r
-               }\r
+               al_destroy_cep( h_cm_dreq.h_al,\r
+                       &((al_conn_qp_t*)h_cm_dreq.h_qp)->cid, TRUE, deref_al_obj );\r
        }\r
 \r
        AL_EXIT( AL_DBG_CM );\r
@@ -1887,20 +1792,13 @@ static void
 __destroying_listen(\r
        IN                              al_obj_t*                                       p_obj )\r
 {\r
-       ib_api_status_t status;\r
        al_listen_t             *p_listen;\r
 \r
        p_listen = PARENT_STRUCT( p_obj, al_listen_t, obj );\r
 \r
        /* Destroy the listen's CEP. */\r
-       status = al_destroy_cep(\r
-               p_obj->h_al, p_listen->cid, deref_al_obj );\r
-       if( status != IB_SUCCESS )\r
-       {\r
-               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("al_destroy_cep returned %s.\n", ib_get_err_str( status )) );\r
-               deref_al_obj( p_obj );\r
-       }\r
+       al_destroy_cep(\r
+               p_obj->h_al, &p_listen->cid, TRUE, deref_al_obj );\r
 }\r
 \r
 \r
@@ -1965,6 +1863,7 @@ __cep_listen(
        }\r
 \r
        /* Create a CEP to listen on. */\r
+    p_listen->cid = AL_INVALID_CID;\r
        status = al_create_cep( h_al, __cm_handler, p_listen, &p_listen->cid );\r
        if( status != IB_SUCCESS )\r
        {\r
index 4e081bb..ca787c9 100644 (file)
@@ -1048,7 +1048,6 @@ destroying_qp(
        ib_qp_handle_t                  h_qp;\r
        al_mad_qp_t                             *p_mad_qp;\r
        al_qp_alias_t                   *p_qp_alias;\r
-       net32_t                                 cid;\r
 \r
        CL_ASSERT( p_obj );\r
        h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );\r
@@ -1117,17 +1116,7 @@ destroying_qp(
 \r
        case IB_QPT_RELIABLE_CONN:\r
        case IB_QPT_UNRELIABLE_CONN:\r
-               cid = cl_atomic_xchg(\r
-                       &((al_conn_qp_t*)h_qp)->cid, AL_RESERVED_CID );\r
-               if( cid != AL_INVALID_CID )\r
-               {\r
-                       ref_al_obj( &h_qp->obj );\r
-                       if( al_destroy_cep(\r
-                               h_qp->obj.h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-                       {\r
-                               deref_al_obj( &h_qp->obj );\r
-                       }\r
-               }\r
+               al_destroy_cep( h_qp->obj.h_al, &((al_conn_qp_t*)h_qp)->cid, FALSE, deref_al_obj );\r
 #ifdef CL_KERNEL\r
                ndi_qp_destroy( h_qp );\r
 #endif\r
index 5ae7093..95a0bd9 100644 (file)
@@ -170,7 +170,7 @@ typedef struct _al_conn_qp
 \r
        ib_cm_handle_t                          p_conn;\r
 \r
-       atomic32_t                                      cid;\r
+       net32_t                                         cid;\r
 \r
        /* Callback table. */\r
        ib_pfn_cm_req_cb_t                      pfn_cm_req_cb;\r
index 1db46ce..91d79a6 100644 (file)
@@ -4060,7 +4060,7 @@ al_create_cep(
        IN                              ib_al_handle_t                          h_al,\r
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
-               OUT                     net32_t* const                          p_cid )\r
+       IN      OUT                     net32_t* const                          p_cid )\r
 {\r
        kcep_t                          *p_cep;\r
        KLOCK_QUEUE_HANDLE      hdl;\r
@@ -4070,6 +4070,11 @@ al_create_cep(
        CL_ASSERT( p_cid );\r
 \r
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       if( *p_cid != AL_INVALID_CID )\r
+       {\r
+               KeReleaseInStackQueuedSpinLock( &hdl );\r
+               return IB_RESOURCE_BUSY;\r
+       }\r
        p_cep = __create_cep();\r
        if( !p_cep )\r
        {\r
@@ -4077,12 +4082,13 @@ al_create_cep(
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Failed to allocate CEP.\n") );\r
                return IB_INSUFFICIENT_MEMORY;\r
        }\r
-       KeReleaseInStackQueuedSpinLock( &hdl );\r
 \r
        __bind_cep( p_cep, h_al, pfn_cb, context );\r
 \r
        *p_cid = p_cep->cid;\r
 \r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
        AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_CM ,\r
                ("Created CEP with cid %d, h_al %p, context %p \n", \r
                p_cep->cid, h_al, p_cep->context ));\r
@@ -4092,12 +4098,14 @@ al_create_cep(
 }\r
 \r
 \r
-ib_api_status_t\r
+void\r
 al_destroy_cep(\r
        IN                              ib_al_handle_t                          h_al,\r
-       IN                              net32_t                                         cid,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
+       IN                              boolean_t                                       reusable,\r
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb )\r
 {\r
+    net32_t             cid = *p_cid;\r
        kcep_t                          *p_cep;\r
        KLOCK_QUEUE_HANDLE      hdl;\r
        void                            *context;\r
@@ -4116,12 +4124,16 @@ al_destroy_cep(
        if( !p_cep )\r
        {\r
                /* Invalid handle. */\r
+        if( !reusable )\r
+            *p_cid = AL_RESERVED_CID;\r
+\r
                KeReleaseInStackQueuedSpinLock( &hdl );\r
                AL_EXIT( AL_DBG_CM );\r
-               return IB_INVALID_PARAMETER;\r
+               return;\r
        }\r
 \r
        context = p_cep->context;\r
+\r
        p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
 \r
        /* Cancel any queued IRP */\r
@@ -4148,6 +4160,11 @@ al_destroy_cep(
 \r
        __unbind_cep( p_cep );\r
        ref_cnt = __cleanup_cep( p_cep );\r
+    if( reusable )\r
+        *p_cid = AL_INVALID_CID;\r
+    else\r
+        *p_cid = AL_RESERVED_CID;\r
+\r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
 \r
        /*\r
@@ -4162,7 +4179,6 @@ al_destroy_cep(
                cid, h_al, context ));\r
 \r
        AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
 }\r
 \r
 \r
@@ -4979,6 +4995,7 @@ al_cep_pre_rep(
        IN                              net32_t                                         cid,\r
        IN                              void*                                           context,\r
        IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
        ib_api_status_t         status;\r
@@ -4992,6 +5009,13 @@ al_cep_pre_rep(
        CL_ASSERT( p_init );\r
 \r
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       if( *p_cid != AL_INVALID_CID )\r
+       {\r
+               KeReleaseInStackQueuedSpinLock( &hdl );\r
+               AL_EXIT( AL_DBG_CM );\r
+               return IB_RESOURCE_BUSY;\r
+       }\r
+\r
        p_cep = __lookup_cep( h_al, cid );\r
        if( !p_cep )\r
        {\r
@@ -5002,6 +5026,11 @@ al_cep_pre_rep(
 \r
        status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
 \r
+       if( status == IB_SUCCESS )\r
+       {\r
+               *p_cid = cid;\r
+       }\r
+\r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
        AL_EXIT( AL_DBG_CM );\r
        return status;\r
@@ -5015,6 +5044,7 @@ al_cep_pre_rep_ex(
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
        IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
        ib_api_status_t         status;\r
@@ -5028,6 +5058,13 @@ al_cep_pre_rep_ex(
        CL_ASSERT( p_init );\r
 \r
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       if( *p_cid != AL_INVALID_CID )\r
+       {\r
+               KeReleaseInStackQueuedSpinLock( &hdl );\r
+               AL_EXIT( AL_DBG_CM );\r
+               return IB_RESOURCE_BUSY;\r
+       }\r
+\r
        p_cep = __lookup_cep( h_al, cid );\r
        if( !p_cep )\r
        {\r
@@ -5038,9 +5075,10 @@ al_cep_pre_rep_ex(
 \r
        status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
 \r
-       if (status == IB_SUCCESS)\r
+       if( status == IB_SUCCESS )\r
        {\r
                p_cep->pfn_cb = pfn_cb;\r
+               *p_cid = cid;\r
        }\r
 \r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
@@ -6267,7 +6305,7 @@ al_cep_cleanup_al(
                 */\r
                cid = PARENT_STRUCT( p_item, kcep_t, al_item )->cid;\r
                cl_spinlock_release( &h_al->obj.lock );\r
-               al_destroy_cep( h_al, cid, NULL );\r
+               al_destroy_cep( h_al, &cid, FALSE, NULL );\r
                cl_spinlock_acquire( &h_al->obj.lock );\r
        }\r
        cl_spinlock_release( &h_al->obj.lock );\r
index d23d92c..1ee4974 100644 (file)
@@ -352,8 +352,7 @@ static VOID __ndi_complete_cancelled_irp(
        )\r
 {\r
        ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;\r
-       ib_qp_handle_t VOID_PTR64 h_qp = p_ndi_csq->h_qp;\r
-       net32_t cid;\r
+       ib_qp_handle_t h_qp = p_ndi_csq->h_qp;\r
 \r
        AL_ENTER( AL_DBG_NDI );\r
 \r
@@ -361,12 +360,8 @@ static VOID __ndi_complete_cancelled_irp(
        {\r
        case NDI_CM_CONNECTING_REQ_SENT:\r
                /* Cleanup from issuing CM REQ. */\r
-               ref_al_obj( &h_qp->obj );\r
-               cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
-               if( cid == AL_INVALID_CID || al_destroy_cep( qp_get_al( h_qp ), cid, deref_al_obj ) != IB_SUCCESS )\r
-               {\r
-                       deref_al_obj( &h_qp->obj );\r
-               }\r
+               al_destroy_cep(\r
+                       qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
                break;\r
 \r
        case NDI_CM_CONNECTING_ATS_SENT:\r
@@ -544,7 +539,6 @@ __ndi_proc_rej(
        IN              const   ib_cm_handle_t* const           p_cm,\r
        IN              const   mad_cm_rej_t* const             p_rej )\r
 {\r
-       net32_t cid;\r
        NTSTATUS status;\r
        ib_qp_handle_t VOID_PTR64       h_qp = p_cm->h_qp;\r
        ndi_qp_csq_t *p_ndi_csq = h_qp->p_irp_que;\r
@@ -555,14 +549,8 @@ __ndi_proc_rej(
                ("p_rej %p, h_qp %#I64x, uhdl %#I64x, connect reject, reason=%hd\n", \r
                p_rej, (uint64_t)h_qp, h_qp->obj.hdl, cl_ntoh16(p_rej->reason) ) );\r
 \r
-       ref_al_obj( &h_qp->obj );\r
-       cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
-       CL_ASSERT( cid == p_cm->cid || cid == AL_RESERVED_CID || cid == AL_INVALID_CID );\r
-       if( cid == AL_INVALID_CID ||\r
-               al_destroy_cep( p_cm->h_al, cid, deref_al_obj ) != IB_SUCCESS )\r
-       {\r
-               deref_al_obj( &h_qp->obj );\r
-       }\r
+       al_destroy_cep(\r
+               p_cm->h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
 \r
        switch (p_ndi_csq->state)\r
        {\r
@@ -881,9 +869,8 @@ __ndi_pr_query_cb(
        uint8_t pkt_life;\r
        ib_qp_mod_t qp_mod;\r
        ib_path_rec_t *p_path_rec;\r
-       ual_ndi_req_cm_ioctl_in_t *p_req = (ual_ndi_req_cm_ioctl_in_t* VOID_PTR64)p_query_rec->query_context;\r
-       ib_qp_handle_t VOID_PTR64 h_qp = (ib_qp_handle_t VOID_PTR64)HDL_TO_PTR(p_req->h_qp);\r
-       net32_t cid, old_cid;\r
+       ual_ndi_req_cm_ioctl_in_t *p_req = (ual_ndi_req_cm_ioctl_in_t* __ptr64)p_query_rec->query_context;\r
+       ib_qp_handle_t h_qp = (ib_qp_handle_t)(ULONG_PTR)p_req->h_qp;\r
 \r
        AL_ENTER( AL_DBG_NDI );\r
 \r
@@ -891,8 +878,9 @@ __ndi_pr_query_cb(
                ("status is %d, count is %d, context %p\n", p_query_rec->status,\r
                p_query_rec->result_cnt, p_query_rec->query_context) );\r
 \r
+       status = p_query_rec->status;\r
        h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );\r
-       if( !h_ioctl || p_query_rec->status != IB_SUCCESS || !p_query_rec->result_cnt )\r
+       if( !h_ioctl || status != IB_SUCCESS || !p_query_rec->result_cnt )\r
                goto err_irp_complete;\r
 \r
        /* Path Record has been received ! */\r
@@ -908,7 +896,8 @@ __ndi_pr_query_cb(
        p_path_rec->pkt_life |= pkt_life;\r
 \r
        /* Get a CEP and bind it to the QP. */\r
-       status = al_create_cep( qp_get_al( h_qp ), __ndi_cm_handler, h_qp, &cid );\r
+       status = al_create_cep(\r
+               qp_get_al( h_qp ), __ndi_cm_handler, h_qp, &((al_conn_qp_t*)h_qp)->cid );\r
        if( status != IB_SUCCESS )\r
        {\r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
@@ -917,12 +906,10 @@ __ndi_pr_query_cb(
        }\r
        AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
                ("Created Active CEP with cid %d, h_al %p, context %p\n",\r
-               cid, qp_get_al( h_qp ), h_qp ) );\r
+               ((al_conn_qp_t*)h_qp)->cid, qp_get_al( h_qp ), h_qp ) );\r
 \r
-       /* See if this QP has already been connected. */\r
-       old_cid = cl_atomic_comp_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID, cid );\r
-       if( old_cid != AL_INVALID_CID || h_qp->obj.state == CL_DESTROYING )\r
-               goto err_cep_destroy;\r
+       /* Take a reference on behalf of the CEP. */\r
+       ref_al_obj( &h_qp->obj );\r
 \r
        /* Format ib_cm_req_t structure */\r
        __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );\r
@@ -942,7 +929,7 @@ __ndi_pr_query_cb(
        IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL );\r
 \r
        /* send CM REQ */\r
-       status = al_cep_send_req( qp_get_al( h_qp ), cid );\r
+       status = al_cep_send_req( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid );\r
        if( status != IB_SUCCESS )\r
                goto err_irp_remove;\r
 \r
@@ -956,22 +943,28 @@ err_irp_remove:
        h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );\r
 \r
 err_cep_destroy:\r
-       al_destroy_cep( qp_get_al( h_qp ), cid, NULL );\r
+       al_destroy_cep(\r
+               qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
        \r
 err_irp_complete:\r
        h_qp->p_irp_que->state = NDI_CM_IDLE;   \r
        /* the IRP "has" 2 QP references, taken in __ndi_ats_query */\r
        if ( h_ioctl )\r
-    {\r
-        if( p_query_rec->status == IB_TIMEOUT )\r
-        {\r
+       {\r
+               switch( status )\r
+               {\r
+               case IB_TIMEOUT:\r
                        __ndi_complete_irp( h_qp, h_ioctl, STATUS_TIMEOUT );\r
-        }\r
-        else\r
-        {\r
+                       break;\r
+\r
+               case IB_INVALID_STATE:\r
+                       __ndi_complete_irp( h_qp, h_ioctl, STATUS_CONNECTION_ACTIVE );\r
+                       break;\r
+\r
+               default:\r
                        __ndi_complete_irp( h_qp, h_ioctl, STATUS_HOST_UNREACHABLE );\r
-        }\r
-    }\r
+               }\r
+       }\r
        deref_al_obj( &h_qp->obj );     /* release IRP SA reference */\r
 \r
 exit:  \r
@@ -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 );\r
        if( status != IB_SUCCESS )\r
        {\r
-               net32_t                         cid;\r
 err:\r
                /* Reject and abort the connection. */\r
                al_cep_rej(\r
@@ -1263,16 +1255,8 @@ err:
 \r
                __cep_timewait_qp( h_qp );\r
 \r
-               cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
-\r
-               if( cid != AL_INVALID_CID )\r
-               {\r
-                       ref_al_obj( &h_qp->obj );\r
-                       if( al_destroy_cep( qp_get_al( h_qp ), cid, deref_al_obj ) != IB_SUCCESS )\r
-                       {\r
-                               deref_al_obj( &h_qp->obj );\r
-                       }\r
-               }\r
+               al_destroy_cep(\r
+                       qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
 \r
                AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
                        ("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );\r
@@ -1372,17 +1356,14 @@ __ndi_rep_cm(
                else\r
                        nt_status = STATUS_CONNECTION_ABORTED;\r
 err:\r
-               cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
-\r
                /* Reject and abort the connection. */\r
                al_cep_rej( qp_get_al( h_qp ), p_rep->cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );\r
 \r
                /* transit QP to error state */\r
                __cep_timewait_qp( h_qp );\r
 \r
-               ref_al_obj( &h_qp->obj );\r
-               if( al_destroy_cep( qp_get_al( h_qp ), p_rep->cid, deref_al_obj ) != IB_SUCCESS )\r
-                       deref_al_obj( &h_qp->obj );\r
+               al_destroy_cep(\r
+                       qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
 \r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
                        ("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );\r
@@ -1434,8 +1415,8 @@ __ndi_fill_cm_rep(
 \r
 NTSTATUS\r
 ndi_rep_cm(\r
-       IN              ib_qp_handle_t FUNC_PTR64       const                           h_qp,\r
-       IN              net32_t                 const                           cid,\r
+       IN              ib_qp_handle_t  const                           h_qp,\r
+       IN              net32_t                                                         cid,\r
        IN              PIRP                                                            p_irp,\r
        IN              ual_ndi_rep_cm_ioctl_in_t                       *p_rep\r
        )\r
@@ -1443,7 +1424,6 @@ ndi_rep_cm(
        IO_STACK_LOCATION       *p_io_stack;\r
        ib_cm_rep_t cm_rep;\r
        ib_qp_mod_t qp_mod;\r
-       net32_t old_cid;\r
        ib_api_status_t status;\r
        NTSTATUS nt_status;\r
 \r
@@ -1453,7 +1433,9 @@ ndi_rep_cm(
        __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );\r
 \r
        /* prepare Passive CEP for connection */\r
-       status = al_cep_pre_rep_ex( qp_get_al( h_qp ), cid, __ndi_cm_handler, h_qp, &cm_rep, &qp_mod );\r
+       status = al_cep_pre_rep_ex(\r
+               qp_get_al( h_qp ), cid, __ndi_cm_handler, h_qp, &cm_rep,\r
+               &((al_conn_qp_t*)h_qp)->cid, &qp_mod );\r
        if( status != IB_SUCCESS )\r
        {\r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
@@ -1466,25 +1448,27 @@ ndi_rep_cm(
                        case IB_INVALID_STATE:\r
                                nt_status = STATUS_CONNECTION_ABORTED;\r
                                break;\r
+                       case IB_RESOURCE_BUSY:\r
+                               nt_status = STATUS_CONNECTION_ACTIVE;\r
+                               break;\r
                        default:\r
                                nt_status = STATUS_INSUFFICIENT_RESOURCES;\r
                                break;\r
                }\r
-               goto err_cep_destroy;\r
+               al_destroy_cep( qp_get_al( h_qp ), &cid, FALSE, NULL );\r
+               \r
+               h_qp->p_irp_que->state = NDI_CM_IDLE;   \r
+               cl_ioctl_complete( p_irp, nt_status, 0 );\r
+               goto exit;\r
        }\r
 \r
+       /* Take a reference on behalf of the CEP. */\r
+       ref_al_obj( &h_qp->obj );\r
+\r
        AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
                ("Prepared Passive CEP with cid %d, h_al %p, context %p\n",\r
                cid, qp_get_al( h_qp ), h_qp ) );\r
 \r
-       /* See if this QP has already been connected. */\r
-       old_cid = cl_atomic_comp_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID, cid );\r
-       if( old_cid != AL_INVALID_CID )\r
-       {\r
-               nt_status = STATUS_CONNECTION_ACTIVE;\r
-               goto err_cep_destroy;\r
-       }\r
-\r
        /* transfer work to a work the thread */\r
        p_irp->Tail.Overlay.DriverContext[0] = h_qp;\r
        p_io_stack = IoGetCurrentIrpStackLocation( p_irp );\r
@@ -1501,13 +1485,6 @@ ndi_rep_cm(
        { /* syncronous performing */\r
                __ndi_rep_cm( p_io_stack->DeviceObject, p_irp );\r
        }\r
-       goto exit;\r
-\r
-err_cep_destroy:\r
-       al_destroy_cep( qp_get_al( h_qp ), cid, NULL );\r
-       \r
-       h_qp->p_irp_que->state = NDI_CM_IDLE;   \r
-       cl_ioctl_complete( p_irp, nt_status, 0 );\r
 \r
 exit:\r
        AL_EXIT( AL_DBG_NDI );\r
@@ -1528,7 +1505,6 @@ ndi_dreq_cm(
        )\r
 {\r
        ib_qp_mod_t qp_mod;\r
-       net32_t cid;\r
        ib_api_status_t status;\r
        NTSTATUS nt_status;\r
        uint64_t timewait_us;\r
@@ -1544,16 +1520,8 @@ ndi_dreq_cm(
                goto exit;\r
        }\r
 \r
-       cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID );\r
-\r
-       if( cid != AL_INVALID_CID )\r
-       {\r
-               ref_al_obj( &h_qp->obj );\r
-               if( al_destroy_cep( qp_get_al( h_qp ), cid, deref_al_obj ) != IB_SUCCESS )\r
-               {\r
-                       deref_al_obj( &h_qp->obj );\r
-               }\r
-       }\r
+       al_destroy_cep(\r
+               qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );\r
 \r
        /* bring QP to error state */\r
        cl_memclr( &qp_mod, sizeof(qp_mod) );\r
index c43d9da..8e6c50d 100644 (file)
@@ -107,7 +107,7 @@ ndi_req_cm(
 NTSTATUS\r
 ndi_rep_cm(\r
        IN              ib_qp_handle_t  const                   h_qp,\r
-       IN              net32_t                 const                   cid,\r
+       IN              net32_t                                                 cid,\r
        IN              cl_ioctl_handle_t                               h_ioctl,\r
        IN              ual_ndi_rep_cm_ioctl_in_t               *p_ndi_rep_cm\r
        );\r
index 17422ef..673e9d9 100644 (file)
@@ -72,6 +72,7 @@ proxy_create_cep(
        p_user_context = cl_ioctl_in_buf( h_ioctl );\r
 \r
        /* We use IRPs as notification mechanism so the callback is NULL. */\r
+       p_ioctl->cid = AL_INVALID_CID;\r
        p_ioctl->status = al_create_cep( p_context->h_al, NULL,\r
                *p_user_context, &p_ioctl->cid );\r
 \r
@@ -123,7 +124,7 @@ proxy_destroy_cep(
        }\r
 \r
        al_destroy_cep( p_context->h_al,\r
-               *(net32_t*)cl_ioctl_in_buf( h_ioctl ), NULL );\r
+               (net32_t*)cl_ioctl_in_buf( h_ioctl ), TRUE, NULL );\r
 \r
        AL_EXIT( AL_DBG_CM );\r
        return CL_SUCCESS;\r
@@ -269,6 +270,7 @@ proxy_cep_pre_rep(
        al_dev_open_context_t           *p_context;\r
        ual_cep_rep_ioctl_t                     *p_ioctl;\r
        ib_qp_handle_t                          h_qp;\r
+       net32_t                                         cid;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
 \r
@@ -299,8 +301,9 @@ proxy_cep_pre_rep(
 \r
        p_ioctl->in.cm_rep.h_qp = h_qp;\r
 \r
+       cid = AL_INVALID_CID;\r
        p_ioctl->out.status = al_cep_pre_rep( p_context->h_al, p_ioctl->in.cid,\r
-               p_ioctl->in.context, &p_ioctl->in.cm_rep, &p_ioctl->out.init );\r
+               p_ioctl->in.context, &p_ioctl->in.cm_rep, &cid, &p_ioctl->out.init );\r
 \r
        deref_al_obj( &h_qp->obj );\r
 \r
index 7b11962..20eacde 100644 (file)
@@ -469,7 +469,7 @@ __ndi_rej_cm(
                goto exit;\r
        }\r
 \r
-       al_destroy_cep( p_context->h_al, cid, NULL );\r
+       al_destroy_cep( p_context->h_al, &cid, FALSE, NULL );\r
        h_ioctl->IoStatus.Status = STATUS_SUCCESS;\r
 \r
 exit:\r
index fe30b48..313575b 100644 (file)
@@ -221,7 +221,7 @@ al_cep_cleanup_al(
                 */\r
                cid = PARENT_STRUCT( p_item, ucep_t, al_item )->cid;\r
                cl_spinlock_release( &h_al->obj.lock );\r
-               al_destroy_cep( h_al, cid, NULL );\r
+               al_destroy_cep( h_al, &cid, FALSE, NULL );\r
                cl_spinlock_acquire( &h_al->obj.lock );\r
        }\r
        cl_spinlock_release( &h_al->obj.lock );\r
@@ -246,7 +246,7 @@ __create_ucep(
        IN                              net32_t                                         cid,\r
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
-               OUT                     net32_t* const                          p_cid )\r
+       IN      OUT                     net32_t* const                          p_cid )\r
 {\r
        ucep_t                                  *p_cep;\r
        DWORD                                   bytes_ret;\r
@@ -326,11 +326,20 @@ __create_ucep(
 \r
        /* Track the CEP in its owning AL instance. */\r
        cl_spinlock_acquire( &h_al->obj.lock );\r
-       cl_qlist_insert_tail( &h_al->cep_list, &p_cep->al_item );\r
-       cl_spinlock_release( &h_al->obj.lock );\r
-\r
        if( p_cid )\r
+       {\r
+               if( *p_cid != AL_INVALID_CID )\r
+               {\r
+                       cl_spinlock_release( &h_al->obj.lock );\r
+                       al_destroy_cep( h_al, &cid, TRUE, NULL );\r
+                       return IB_INVALID_STATE;\r
+               }\r
                *p_cid = p_cep->cid;\r
+       }\r
+\r
+       cl_qlist_insert_tail( &h_al->cep_list, &p_cep->al_item );\r
+\r
+       cl_spinlock_release( &h_al->obj.lock );\r
 \r
        AL_EXIT( AL_DBG_CM );\r
        return IB_SUCCESS;\r
@@ -342,7 +351,7 @@ al_create_cep(
        IN                              ib_al_handle_t                          h_al,\r
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
-               OUT                     net32_t* const                          p_cid )\r
+       IN      OUT                     net32_t* const                          p_cid )\r
 {\r
        ib_api_status_t         status;\r
 \r
@@ -359,10 +368,11 @@ al_create_cep(
  * Note that destroy_cep is synchronous.  It does however handle the case\r
  * where a user calls it from a callback context.\r
  */\r
-ib_api_status_t\r
+void\r
 al_destroy_cep(\r
        IN                              ib_al_handle_t                          h_al,\r
-       IN                              net32_t                                         cid,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
+       IN                              boolean_t                                       reusable,\r
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL )\r
 {\r
        ucep_t          *p_cep;\r
@@ -373,20 +383,23 @@ al_destroy_cep(
        CL_ASSERT( h_al );\r
 \r
        cl_spinlock_acquire( &gp_cep_mgr->obj.lock );\r
-       if( cid < cl_ptr_vector_get_size( &gp_cep_mgr->cep_vector ) )\r
+       if( *p_cid < cl_ptr_vector_get_size( &gp_cep_mgr->cep_vector ) )\r
        {\r
-               p_cep = cl_ptr_vector_get( &gp_cep_mgr->cep_vector, cid );\r
+               p_cep = cl_ptr_vector_get( &gp_cep_mgr->cep_vector, *p_cid );\r
                if( p_cep && p_cep->h_al == h_al )\r
-                       cl_ptr_vector_set( &gp_cep_mgr->cep_vector, cid, NULL );\r
+                       cl_ptr_vector_set( &gp_cep_mgr->cep_vector, *p_cid, NULL );\r
                else\r
                        goto invalid;\r
        }\r
        else\r
        {\r
 invalid:\r
+               if( !reusable )\r
+                       *p_cid = AL_RESERVED_CID;\r
+\r
                cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
                AL_EXIT( AL_DBG_CM );\r
-               return IB_INVALID_PARAMETER;\r
+               return;\r
        }\r
 \r
        /*\r
@@ -395,7 +408,10 @@ invalid:
         */\r
        DeviceIoControl( g_al_device, UAL_DESTROY_CEP, &p_cep->cid,\r
                sizeof(p_cep->cid), NULL, 0, &bytes_ret, NULL );\r
-       p_cep->cid = AL_INVALID_CID;\r
+       if( reusable )\r
+               *p_cid = AL_INVALID_CID;\r
+       else\r
+               *p_cid = AL_RESERVED_CID;\r
 \r
        cl_spinlock_release( &gp_cep_mgr->obj.lock );\r
 \r
@@ -407,6 +423,7 @@ invalid:
         */\r
        cl_spinlock_acquire( &h_al->obj.lock );\r
        cl_qlist_remove_item( &h_al->cep_list, &p_cep->al_item );\r
+\r
        cl_spinlock_release( &h_al->obj.lock );\r
 \r
        if( !cl_atomic_dec( &p_cep->ref_cnt ) )\r
@@ -416,7 +433,6 @@ invalid:
        }\r
 \r
        AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
 }\r
 \r
 \r
@@ -590,6 +606,7 @@ al_cep_pre_rep(
        IN                              net32_t                                         cid,\r
        IN                              void*                                           context,\r
        IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
        ucep_t                                  *p_cep;\r
@@ -657,7 +674,16 @@ al_cep_pre_rep(
        }\r
 \r
        if( ioctl.out.status == IB_SUCCESS )\r
+       {\r
+               cl_spinlock_acquire( &h_al->obj.lock );\r
+               if( *p_cid != AL_INVALID_CID )\r
+               {\r
+                       cl_spinlock_release( &h_al->obj.lock );\r
+                       return IB_INVALID_STATE;\r
+               }\r
+               *p_cid = p_cep->cid;\r
                *p_init = ioctl.out.init;\r
+       }\r
 \r
        AL_EXIT( AL_DBG_CM );\r
        return ioctl.out.status;\r