[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