[ofw] [PATCH] Fix ND CM IOCTL handling
Fab Tillier
ftillier at windows.microsoft.com
Tue Jul 8 15:50:34 PDT 2008
This patch fixes ND CM IOCTL handling to work properly at scale. There were several race conditions in the old code. This is unfortunately a pretty large patch, largely due to the IOCTL handling being effectively re-written.
Signed-off-by: Fab Tillier <ftillier at microsoft.com>
diff -up -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\al\al_dev.h trunk\core\al\al_dev.h
--- old\core\al\al_dev.h Wed Jul 02 09:53:25 2008
+++ trunk\core\al\al_dev.h Tue Jul 08 15:08:50 2008
@@ -55,7 +55,7 @@
#define AL_DEVICE_NAME L"\\Device\\ibal"
#define ALDEV_KEY (0x3B) /* Matches FILE_DEVICE_INFINIBAND from wdm.h */
-#define AL_IOCTL_VERSION (7)
+#define AL_IOCTL_VERSION (8)
/* max number of devices with non-default pkey */
#define MAX_NUM_PKEY 16
@@ -404,6 +404,7 @@ typedef enum _al_ndi_ops
ual_ndi_rej_cm_ioctl_cmd,
ual_ndi_dreq_cm_ioctl_cmd,
ual_ndi_noop,
+ ual_ndi_notify_dreq_cmd,
al_ndi_maxops
@@ -426,6 +427,7 @@ typedef enum _al_ndi_ops
#define UAL_NDI_REJ_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_rej_cm_ioctl_cmd)
#define UAL_NDI_DREQ_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_dreq_cm_ioctl_cmd)
#define UAL_NDI_NOOP IOCTL_CODE(ALDEV_KEY, ual_ndi_noop)
+#define UAL_NDI_NOTIFY_DREQ IOCTL_CODE(ALDEV_KEY, ual_ndi_notify_dreq_cmd)
/*
* Various Operation Allowable on the System Helper
diff -up -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\al\al_proxy.h trunk\core\al\al_proxy.h
--- old\core\al\al_proxy.h Tue Jul 01 11:17:08 2008
+++ trunk\core\al\al_proxy.h Tue Jul 08 15:13:21 2008
@@ -257,5 +257,7 @@ ib_api_status_t
proxy_pnp_port_cb(
IN ib_pnp_rec_t *p_pnp_rec );
-
+NTSTATUS
+ib_to_ntstatus(
+ IN ib_api_status_t ib_status );
#endif /* _AL_PROXY_H_ */
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 Wed Jul 02 09:53:25 2008
+++ trunk\core\al\al_qp.h Tue Jul 08 15:08:50 2008
@@ -155,7 +155,7 @@ typedef struct _ib_qp
ib_pfn_join_mcast_t pfn_join_mcast;
#ifdef CL_KERNEL
- ndi_qp_csq_t *p_irp_que;
+ ndi_qp_csq_t *p_irp_queue;
#endif
} ib_qp_t;
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 Wed Jul 02 09:53:24 2008
+++ trunk\core\al\kernel\al_ndi_cm.c Tue Jul 08 15:10:02 2008
@@ -61,6 +61,37 @@ uint8_t g_qp_retries = QP_ATTRIB_RETRY
uint8_t g_pkt_life_modifier = 0;
uint8_t g_max_cm_retries = CM_RETRIES;
+NTSTATUS
+__ndi_ats_query(
+ IN IRP* p_irp
+ );
+
+NTSTATUS
+__ndi_pr_query(
+ IN IRP* p_irp
+ );
+
+NTSTATUS
+__ndi_send_req(
+ IN IRP* p_irp
+ );
+
+NTSTATUS
+__ndi_send_rep(
+ IN ib_qp_handle_t h_qp,
+ IN PIRP p_irp
+ );
+
+NTSTATUS
+__ndi_send_dreq(
+ IN IRP* p_irp
+ );
+
+static void
+__ndi_queue_drep(
+ IN IRP *p_irp
+ );
+
/*******************************************************************
*
* Helpers
@@ -72,57 +103,50 @@ static char * State2String(ndi_cm_state_
switch (state)
{
case NDI_CM_IDLE : return "NDI_CM_IDLE";
- case NDI_CM_CONNECTING_ATS_SENT : return "NDI_CM_CONNECTING_ATS_SENT";
- case NDI_CM_CONNECTING_QPR_SENT : return "NDI_CM_CONNECTING_QPR_SENT";
- case NDI_CM_CONNECTING_REQ_SENT : return "NDI_CM_CONNECTING_REQ_SENT";
- case NDI_CM_CONNECTING_REP_RCVD : return "NDI_CM_CONNECTING_REP_RCVD";
- case NDI_CM_CONNECTING_REJ_RCVD : return "NDI_CM_CONNECTING_REJ_RCVD";
+ case NDI_CM_CONNECTING_ATS_SENT : return "NDI_CM_CONNECTING_ATS_SENT";
+ case NDI_CM_CONNECTING_QPR_SENT : return "NDI_CM_CONNECTING_QPR_SENT";
+ case NDI_CM_CONNECTING_REQ_SENT : return "NDI_CM_CONNECTING_REQ_SENT";
+ case NDI_CM_CONNECTING_REP_SENT : return "NDI_CM_CONNECTING_REP_SENT";
+ case NDI_CM_CONNECTING_REP_RCVD : return "NDI_CM_CONNECTING_REP_RCVD";
case NDI_CM_CONNECTED : return "NDI_CM_CONNECTED";
- case NDI_CM_BOUND : return "NDI_CM_BOUND";
- case NDI_CM_LISTENING : return "NDI_CM_LISTENING";
- case NDI_CM_REP_SENT : return "NDI_CM_REP_SENT";
- case NDI_CM_CONNECTED_DREP_SENT : return "NDI_CM_CONNECTED_DREP_SENT";
- case NDI_CM_CONNECTED_DREQ_SENT : return "NDI_CM_CONNECTED_DREQ_SENT";
+ case NDI_CM_DISCONNECTING : return "NDI_CM_DISCONNECTING";
+ case NDI_CM_CONNECTED_DREQ_RCVD : return "NDI_CM_CONNECTED_DREQ_RCVD";
+ case NDI_CM_INVALID : return "NDI_CM_CONNECTING_REP_SENT";
default :
ASSERT(FALSE);
}
return "Unknown state";
}
+
static inline void
__ndi_complete_irp(
- IN ib_qp_handle_t FUNC_PTR64 h_qp,
- IN PIRP Irp,
- IN NTSTATUS code
+ IN ib_qp_handle_t h_qp,
+ IN PIRP p_irp,
+ IN NTSTATUS status
)
{
AL_ENTER( AL_DBG_NDI );
- CL_ASSERT( Irp );
+ CL_ASSERT( p_irp );
+ CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] == NULL );
- cl_ioctl_complete( Irp, code, 0 );
- deref_al_obj( &h_qp->obj ); /* release IRP life reference */
- h_qp->p_irp_que->h_ioctl = NULL; /* mark IRP as cancelled */
+ p_irp->IoStatus.Status = status;
+ if( status == STATUS_SUCCESS )
+ {
+ p_irp->IoStatus.Information = cl_ioctl_out_size( p_irp );
+ IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
+ }
+ else
+ {
+ p_irp->IoStatus.Information = 0;
+ IoCompleteRequest( p_irp, 0 );
+ }
+ deref_al_obj( &h_qp->obj ); /* Release IRP reference */
AL_EXIT( AL_DBG_NDI );
}
-static inline void
-__ndi_complete_irp_ex(
- IN ib_qp_handle_t FUNC_PTR64 h_qp,
- IN NTSTATUS code,
- IN ndi_cm_state_t new_state
- )
-{
- PIRP Irp;
-
- AL_ENTER( AL_DBG_NDI );
- h_qp->p_irp_que->state = new_state;
- Irp = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
- if ( Irp )
- __ndi_complete_irp( h_qp, Irp, code );
- AL_EXIT( AL_DBG_NDI );
-}
/*
* Transition the QP to the error state to flush all oustanding work
@@ -243,16 +267,52 @@ exit:
*
******************************************************************/
-static VOID __ndi_insert_irp(
- IN PIO_CSQ Csq,
- IN PIRP Irp
+
+static NTSTATUS __ndi_insert_irp_ex(
+ IN PIO_CSQ pCsq,
+ IN PIRP pIrp,
+ IN VOID *Context
)
{
- ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
+ NTSTATUS status;
+ ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)pCsq;
AL_ENTER( AL_DBG_NDI );
- InsertTailList( &p_ndi_csq->que, &Irp->Tail.Overlay.ListEntry );
+ switch( (ULONG_PTR)Context )
+ {
+ case NDI_CM_CONNECTING_ATS_SENT:
+ status = __ndi_ats_query( pIrp );
+ break;
+
+ case NDI_CM_CONNECTING_QPR_SENT:
+ status = __ndi_pr_query( pIrp );
+ break;
+
+ case NDI_CM_CONNECTING_REQ_SENT:
+ status = __ndi_send_req( pIrp );
+ break;
+
+ case NDI_CM_CONNECTING_REP_SENT:
+ status = __ndi_send_rep( p_ndi_csq->h_qp, pIrp );
+ break;
+
+ case NDI_CM_DISCONNECTING:
+ status = __ndi_send_dreq( pIrp );
+ break;
+
+ default:
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ ASSERT( FALSE );
+ }
+
+ if( status == STATUS_SUCCESS )
+ {
+ p_ndi_csq->state = (ndi_cm_state_t)(ULONG_PTR)Context;
+ InsertTailList( &p_ndi_csq->queue, &pIrp->Tail.Overlay.ListEntry );
+ ref_al_obj( &p_ndi_csq->h_qp->obj ); /* Take IRP reference. */
+ }
AL_EXIT( AL_DBG_NDI );
+ return status;
}
static VOID __ndi_remove_irp(
@@ -280,7 +340,7 @@ static PIRP __ndi_peek_next_irp(
AL_ENTER( AL_DBG_NDI );
- listHead = &p_ndi_csq->que;
+ listHead = &p_ndi_csq->queue;
//
// If the IRP is NULL, we will start peeking from the listhead, else
@@ -303,11 +363,13 @@ static PIRP __ndi_peek_next_irp(
if(PeekContext)
{
- /* for now PeekContext is not used */
- }
+ if( cl_ioctl_ctl_code( nextIrp ) == (ULONG_PTR)PeekContext )
+ break;
+ }
else
{
- break;
+ if( cl_ioctl_ctl_code( nextIrp ) != UAL_NDI_NOTIFY_DREQ )
+ break;
}
nextIrp = NULL;
@@ -348,70 +410,56 @@ static VOID __ndi_release_lock(
static VOID __ndi_complete_cancelled_irp(
IN PIO_CSQ Csq,
- IN PIRP Irp
+ IN PIRP p_irp
)
{
ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
+ KIRQL irql;
AL_ENTER( AL_DBG_NDI );
- switch (p_ndi_csq->state)
+ switch( cl_ioctl_ctl_code( p_irp ) )
{
- case NDI_CM_CONNECTING_REQ_SENT:
- /* Cleanup from issuing CM REQ. */
+ case UAL_NDI_REQ_CM:
+ __ndi_acquire_lock( Csq, &irql );
+ if( p_ndi_csq->state != NDI_CM_INVALID )
+ {
+ switch( p_ndi_csq->state )
+ {
+ case NDI_CM_CONNECTING_ATS_SENT:
+ case NDI_CM_CONNECTING_QPR_SENT:
+ /*
+ * Note that al_cancel_sa_req must be synchronized with any potential
+ * SA callback.
+ */
+ al_cancel_sa_req( &h_qp->p_irp_queue->h_query->sa_req );
+ break;
+
+ default:
+ CL_ASSERT( p_ndi_csq->state == NDI_CM_CONNECTING_ATS_SENT ||
+ p_ndi_csq->state == NDI_CM_CONNECTING_QPR_SENT ||
+ p_ndi_csq->state == NDI_CM_CONNECTING_REQ_SENT );
+ }
+ p_ndi_csq->state = NDI_CM_IDLE;
+ }
+ /* Always try to destroy the CEP. The CEP manager handles invalid CIDs. */
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:
- case NDI_CM_CONNECTING_QPR_SENT:
- al_cancel_sa_req( &h_qp->p_irp_que->h_query->sa_req );
- break;
-
- default:
- /* fall through */
- break;
- }
- //TODO: is it always true ?
- p_ndi_csq->state = NDI_CM_IDLE;
- __ndi_complete_irp( h_qp, Irp, CL_CANCELED );
+ __ndi_release_lock( Csq, irql );
- AL_EXIT( AL_DBG_NDI );
-}
+ __fallthrough;
-/* flush a queue of pending requests */
+ case UAL_NDI_NOTIFY_DREQ:
+ __ndi_complete_irp( h_qp, p_irp, STATUS_CANCELLED );
+ break;
-#pragma warning(disable:4706)
-static inline void __ndi_flush_que(
- IN ndi_qp_csq_t* p_ndi_csq,
- IN NTSTATUS completion_code
- )
-{
- PIRP Irp;
- while( Irp = IoCsqRemoveNextIrp( &p_ndi_csq->csq, NULL ) )
- {
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
- ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
- (uint64_t)p_ndi_csq->h_qp, p_ndi_csq->h_qp->obj.hdl,
- p_ndi_csq->h_qp->obj.ref_cnt ) );
- cl_ioctl_complete( Irp, completion_code, 0 );
- deref_al_obj( &p_ndi_csq->h_qp->obj ); /* release IRP life reference */
+ case UAL_NDI_DREQ_CM:
+ __ndi_queue_drep( p_irp );
+ break;
}
-}
-#pragma warning(default:4706)
-void
-ndi_qp_flush_ques(
- IN ib_qp_handle_t FUNC_PTR64 h_qp
- )
-{
- AL_ENTER( AL_DBG_NDI );
- __ndi_flush_que( h_qp->p_irp_que, STATUS_CANCELLED );
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
- ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
- (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
AL_EXIT( AL_DBG_NDI );
}
@@ -434,24 +482,24 @@ ndi_qp_init(
goto exit;
}
- h_qp->p_irp_que = (ndi_qp_csq_t*)cl_zalloc(sizeof(ndi_qp_csq_t));
- if (!h_qp->p_irp_que)
+ h_qp->p_irp_queue = (ndi_qp_csq_t*)cl_zalloc(sizeof(ndi_qp_csq_t));
+ if (!h_qp->p_irp_queue)
{
status = STATUS_NO_MEMORY;
goto exit;
}
- status = IoCsqInitialize( &h_qp->p_irp_que->csq,
- __ndi_insert_irp, __ndi_remove_irp,
+ status = IoCsqInitializeEx( &h_qp->p_irp_queue->csq,
+ __ndi_insert_irp_ex, __ndi_remove_irp,
__ndi_peek_next_irp, __ndi_acquire_lock,
__ndi_release_lock, __ndi_complete_cancelled_irp );
if ( !NT_SUCCESS( status ) )
goto exit;
- InitializeListHead( &h_qp->p_irp_que->que );
- h_qp->p_irp_que->h_qp = h_qp;
- h_qp->p_irp_que->h_query = NULL;
- h_qp->p_irp_que->state = NDI_CM_IDLE;
+ InitializeListHead( &h_qp->p_irp_queue->queue );
+ h_qp->p_irp_queue->h_qp = h_qp;
+ h_qp->p_irp_queue->h_query = NULL;
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
status = STATUS_SUCCESS;
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
@@ -463,42 +511,95 @@ exit:
return status;
}
+#pragma warning(disable:4706)
void
ndi_qp_destroy(
- IN ib_qp_handle_t FUNC_PTR64 h_qp )
+ IN ib_qp_handle_t h_qp )
{
+ KIRQL irql;
+ PIRP Irp;
+
AL_ENTER( AL_DBG_NDI );
- if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_que)
+ if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)
{
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
- ("Destroying h_qp %#I64x, uhdl %#I64x, h_ioctl %p, cid %d\n",
- (uint64_t)h_qp, h_qp->obj.hdl, h_qp->p_irp_que->h_ioctl, ((al_conn_qp_t*)h_qp)->cid ) );
+ ("Destroying h_qp %#I64x, uhdl %#I64x, cid %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, ((al_conn_qp_t*)h_qp)->cid ) );
+
+ /* Move the state before flushing, so that all new IRPs fail to queue. */
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ h_qp->p_irp_queue->state = NDI_CM_INVALID;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
/* cancel pending IRPS for NDI type CQ */
- ndi_qp_flush_ques( h_qp );
+ AL_ENTER( AL_DBG_NDI );
+ while( Irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, NULL ) )
+ {
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
+ ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
+
+ __ndi_complete_cancelled_irp( &h_qp->p_irp_queue->csq, Irp );
+ }
+ while( Irp = IoCsqRemoveNextIrp(
+ &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ ) )
+ {
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
+ ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
+
+ __ndi_complete_cancelled_irp( &h_qp->p_irp_queue->csq, Irp );
+ }
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
+ ("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
}
AL_EXIT( AL_DBG_NDI );
}
+#pragma warning(default:4706)
+
void
ndi_qp_free(
- IN ib_qp_handle_t FUNC_PTR64 h_qp )
+ IN ib_qp_handle_t h_qp )
{
AL_ENTER( AL_DBG_NDI );
- if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_que)
+ if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)
{
/* free NDI context */
- cl_free( h_qp->p_irp_que );
- h_qp->p_irp_que = NULL;
+ cl_free( h_qp->p_irp_queue );
+ h_qp->p_irp_queue = NULL;
}
AL_EXIT( AL_DBG_NDI );
}
+static inline void
+__ndi_complete_req_irp(
+ IN ib_qp_handle_t h_qp,
+ IN NTSTATUS code
+ )
+{
+ PIRP Irp;
+ KIRQL irql;
+
+ AL_ENTER( AL_DBG_NDI );
+ Irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
+ if ( Irp )
+ {
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+ __ndi_complete_irp( h_qp, Irp, code );
+ }
+ AL_EXIT( AL_DBG_NDI );
+}
+
/*******************************************************************
*
* REQ CM request
@@ -506,42 +607,57 @@ ndi_qp_free(
******************************************************************/
static void
-__ndi_req_cm_wi(
- IN DEVICE_OBJECT* p_dev_obj,
- IN void* context )
+__ndi_notify_dreq(
+ IN ib_qp_handle_t const h_qp )
{
- NTSTATUS status;
- ib_qp_handle_t VOID_PTR64 h_qp = (ib_qp_handle_t VOID_PTR64)context;
- UNUSED_PARAM(p_dev_obj);
+ IRP *p_irp = IoCsqRemoveNextIrp(
+ &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
- AL_ENTER( AL_DBG_NDI );
+ if( p_irp )
+ {
+ __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );
+ }
+}
- IoFreeWorkItem( h_qp->p_irp_que->p_workitem );
- __cep_timewait_qp( h_qp );
-
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- status = (h_qp->p_irp_que->state == NDI_CM_CONNECTED) ? STATUS_CONNECTION_DISCONNECTED : STATUS_CONNECTION_REFUSED;
- __ndi_complete_irp( h_qp, h_qp->p_irp_que->h_ioctl, status );
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
+static void
+__ndi_proc_dreq(
+ IN ib_qp_handle_t const h_qp )
+{
+ IRP *p_irp;
+ KIRQL irql;
+ ndi_cm_state_t old_state;
- AL_EXIT( AL_DBG_NDI );
+ __ndi_notify_dreq( h_qp );
+
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ old_state = h_qp->p_irp_queue->state;
+ if( old_state == NDI_CM_CONNECTED )
+ {
+ h_qp->p_irp_queue->state = NDI_CM_CONNECTED_DREQ_RCVD;
+ }
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+
+ p_irp = IoCsqRemoveNextIrp(
+ &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
+ if( p_irp != NULL )
+ {
+ __ndi_queue_drep( p_irp );
+ }
}
+
/*
* A user-specified callback that is invoked after receiving a connection
* rejection message (REJ).
*/
-
-
static void
__ndi_proc_rej(
- IN const ib_cm_handle_t* const p_cm,
+ IN ib_qp_handle_t const h_qp,
IN const mad_cm_rej_t* const p_rej )
{
- 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;
+ KIRQL irql;
+ IRP* p_irp;
AL_ENTER( AL_DBG_NDI );
@@ -549,195 +665,190 @@ __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) ) );
- al_destroy_cep(
- p_cm->h_al, &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );
-
- switch (p_ndi_csq->state)
+ p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, NULL );
+ __ndi_notify_dreq( h_qp );
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( p_irp != NULL )
{
- case NDI_CM_CONNECTING_REQ_SENT:
- status = (p_rej->reason == IB_REJ_TIMEOUT) ? STATUS_TIMEOUT : STATUS_CONNECTION_REFUSED;
- __ndi_complete_irp_ex( h_qp, status, NDI_CM_CONNECTING_REJ_RCVD );
- break;
-
- case NDI_CM_CONNECTED:
- case NDI_CM_REP_SENT:
- /* a race: the passive side's REP times out, but active side has sent the RTU.
- We are treating this case it like a DREQ */
+ switch( cl_ioctl_ctl_code( p_irp ) )
{
- IO_STACK_LOCATION *p_io_stack;
- cl_ioctl_handle_t h_ioctl;
-
- h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
- if (!h_ioctl)
- { /* IRP has been cancelled */
- // TODO: no QP flash
- AL_PRINT(TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,
- ( "IRP cancelled: Can't flush the QP %p, ndi_state %d\n",
- h_qp, p_ndi_csq->state ) );
- h_qp->p_irp_que->state = NDI_CM_IDLE;
-// ASSERT(FALSE);
- }
+ case UAL_NDI_REQ_CM:
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ if( p_rej->reason == IB_REJ_TIMEOUT )
+ __ndi_complete_irp( h_qp, p_irp, STATUS_TIMEOUT );
else
- {
- p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl );
- h_qp->p_irp_que->p_workitem = IoAllocateWorkItem( p_io_stack->DeviceObject );
- if ( h_qp->p_irp_que->p_workitem )
- { /* asyncronous performing */
- IoQueueWorkItem( h_qp->p_irp_que->p_workitem,
- __ndi_req_cm_wi, DelayedWorkQueue, h_qp );
- }
- else
- { /* syncronous performing */
- // TODO: no QP flash
- AL_PRINT(TRACE_LEVEL_ERROR ,AL_DBG_ERROR ,
- ( "Can't flush the QP %p, ndi_state %d\n",
- h_qp, p_ndi_csq->state ) );
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- status = (h_qp->p_irp_que->state == NDI_CM_CONNECTED) ? STATUS_CONNECTION_DISCONNECTED : STATUS_CONNECTION_REFUSED;
- __ndi_complete_irp( h_qp, h_ioctl, status );
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
- h_qp->p_irp_que->h_ioctl = NULL;
- }
- }
+ __ndi_complete_irp( h_qp, p_irp, STATUS_CONNECTION_REFUSED );
+
+ al_destroy_cep(
+ qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );
+ break;
+
+ // TODO: REP IRPs never get queued in the CSQ. Can we delete?
+ //case UAL_NDI_REP_CM:
+ // if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ // h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ // __ndi_complete_irp( h_qp, p_irp, STATUS_CONNECTION_ABORTED );
+ // al_destroy_cep(
+ // qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );
+ // break;
+
+ case UAL_NDI_DREQ_CM:
+ __ndi_queue_drep( p_irp );
break;
}
-
- default:
- // This is not the state that we waited for, not much that we can
- // do. (This might happen in shutdown)
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("Not the expected state %s\n", State2String( p_ndi_csq->state )));
- ASSERT(FALSE);
- break;
}
-
+ else if( h_qp->p_irp_queue->state == NDI_CM_CONNECTED )
+ {
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_CONNECTED_DREQ_RCVD;
+ }
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+
AL_EXIT( AL_DBG_NDI );
}
+
static void
__ndi_proc_rep(
- IN ib_cm_handle_t* const p_cm,
- IN mad_cm_rep_t* const p_rep )
+ IN ib_qp_handle_t const h_qp,
+ IN net32_t cid )
{
- ndi_qp_csq_t *p_ndi_csq = p_cm->h_qp->p_irp_que;
+ ndi_qp_csq_t *p_ndi_csq = h_qp->p_irp_queue;
+ IRP* p_irp;
+ KIRQL irql;
AL_ENTER( AL_DBG_NDI );
- UNREFERENCED_PARAMETER( p_rep );
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("h_qp = 0x%p\n", h_qp));
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("h_qp = 0x%p\n", p_cm->h_qp));
-
- if ( p_ndi_csq->state != NDI_CM_CONNECTING_REQ_SENT)
+ p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
+ __ndi_acquire_lock( &p_ndi_csq->csq, &irql );
+ if( p_irp == NULL )
{
- // This is not the state that we waited for, not much that we can do
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("Not the expected state %s\n", State2String( p_ndi_csq->state )));
- ASSERT(FALSE);
- goto exit;
+ CL_ASSERT( IsListEmpty( &h_qp->p_irp_queue->queue ) );
+ al_cep_rej( qp_get_al( h_qp ), cid, IB_REJ_INVALID_COMM_INSTANCE, NULL, 0, NULL, 0 );
}
+ else
+ {
+ p_ndi_csq->state = NDI_CM_CONNECTING_REP_RCVD;
- __ndi_complete_irp_ex( p_cm->h_qp, STATUS_SUCCESS, NDI_CM_CONNECTING_REP_RCVD );
+ __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );
+ }
+ __ndi_release_lock( &p_ndi_csq->csq, irql );
-exit:
AL_EXIT( AL_DBG_NDI );
+ return;
}
-typedef struct _ndi_async_dreq
-{
- cl_async_proc_item_t item;
- ib_cm_handle_t cm;
-
-} ndi_async_dreq_t;
-static void
-__ndi_proc_dreq_async(
- IN cl_async_proc_item_t *p_item )
+void
+__ndi_do_drep(
+ IN DEVICE_OBJECT* p_dev_obj,
+ IN PIRP p_irp )
{
+ ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
ib_qp_mod_t qp_mod;
ib_api_status_t status;
- ib_cm_drep_t cm_drep = { NULL, 0 };
- ndi_async_dreq_t *p_async_dreq = PARENT_STRUCT( p_item, ndi_async_dreq_t, item );
+ uint64_t timewait_us;
+ KIRQL irql;
+ NTSTATUS nt_status;
+
+ UNREFERENCED_PARAMETER( p_dev_obj );
AL_ENTER( AL_DBG_NDI );
- /* bring QP to error state */
- cl_memclr( &qp_mod, sizeof(qp_mod) );
- qp_mod.req_state = IB_QPS_ERROR;
+ CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] );
+ IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
+ deref_al_obj( &h_qp->obj ); /* Release work item reference. */
- status = modify_qp( p_async_dreq->cm.h_qp, &qp_mod, NULL );
- if ( status != IB_SUCCESS )
+ status = al_cep_get_timewait( qp_get_al( h_qp ),
+ ((al_conn_qp_t*)h_qp)->cid, &timewait_us );
+
+ if (status != IB_SUCCESS)
{
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("al_modify_qp to ERROR returned %s.\n", ib_get_err_str(status) ) );
+ nt_status = STATUS_CONNECTION_INVALID;
goto exit;
}
- status = al_cep_drep( p_async_dreq->cm.h_al,
- ((al_conn_qp_t*)p_async_dreq->cm.h_qp)->cid, &cm_drep);
+ /* Store the timestamp after which the QP exits timewait. */
+ h_qp->timewait = cl_get_time_stamp() + timewait_us;
+
+ 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) );
+ qp_mod.req_state = IB_QPS_ERROR;
+
+ status = ndi_modify_qp( h_qp, &qp_mod,
+ cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) );
if ( status != IB_SUCCESS )
{
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("al_cep_drep returned %s.\n", ib_get_err_str(status) ) );
+ ("ndi_modify_qp to ERROR returned %s.\n", ib_get_err_str(status) ) );
}
- //TODO: what state is to be set here ?
- //p_async_dreq->cm.h_qp->p_irp_que->state = NDI_CM_IDLE;
+
+ nt_status = ib_to_ntstatus( status );
exit:
- deref_al_obj( &p_async_dreq->cm.h_qp->obj );
- cl_free( p_async_dreq );
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+
+ __ndi_complete_irp( h_qp, p_irp, nt_status );
AL_EXIT( AL_DBG_NDI );
}
+
static void
-__ndi_proc_dreq(
- IN ib_cm_handle_t* const p_cm,
- IN mad_cm_dreq_t* const p_dreq )
+__ndi_queue_drep(
+ IN IRP *p_irp )
{
- ndi_async_dreq_t *p_async_dreq;
- UNUSED_PARAM(p_dreq);
+ CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] != NULL );
+ IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],
+ __ndi_do_drep, DelayedWorkQueue, p_irp );
+}
- AL_ENTER( AL_DBG_NDI );
- AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_NDI ,("h_qp = 0x%p\n", p_cm->h_qp));
+static void
+__ndi_proc_drep(
+ IN ib_qp_handle_t const h_qp )
+{
+ IRP* p_irp;
+
+ AL_ENTER( AL_DBG_NDI );
- p_async_dreq = (ndi_async_dreq_t*)cl_zalloc( sizeof(ndi_async_dreq_t) );
- if( !p_async_dreq )
+ p_irp = IoCsqRemoveNextIrp(
+ &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
+ if( p_irp != NULL )
{
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("failed to cl_zalloc ndi_async_dreq_t (%d bytes)\n",
- sizeof(ndi_async_dreq_t)) );
- ASSERT(FALSE);
- goto exit;
+ __ndi_queue_drep( p_irp );
}
- ref_al_obj( &p_cm->h_qp->obj );
- p_async_dreq->cm = *p_cm;
- p_async_dreq->item.pfn_callback = __ndi_proc_dreq_async;
-
- /* Queue the MAD for asynchronous processing. */
- cl_async_proc_queue( gp_async_proc_mgr, &p_async_dreq->item );
-
-exit:
AL_EXIT( AL_DBG_NDI );
}
+
static void
__ndi_cm_handler(
- IN const ib_al_handle_t FUNC_PTR64 h_al,
+ IN const ib_al_handle_t h_al,
IN const net32_t cid )
{
- void* VOID_PTR64 context;
+ void* context;
net32_t new_cid;
ib_mad_element_t *p_mad_el;
- ib_cm_handle_t h_cm;
AL_ENTER( AL_DBG_NDI );
while( al_cep_poll( h_al, cid, &context, &new_cid, &p_mad_el ) == IB_SUCCESS )
{
ib_mad_t*p_mad = ib_get_mad_buf( p_mad_el );
- ib_qp_handle_t VOID_PTR64 h_qp = (ib_qp_handle_t VOID_PTR64)context;
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)context;
if( p_mad_el->status != IB_SUCCESS )
{
@@ -747,17 +858,21 @@ __ndi_cm_handler(
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
("REQ timeouted for CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
cid, h_al, h_qp, new_cid ) );
- __ndi_complete_irp_ex( h_qp, STATUS_TIMEOUT, NDI_CM_IDLE );
+ __ndi_complete_req_irp( h_qp, STATUS_TIMEOUT );
break;
case CM_REP_ATTR_ID:
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
("REP timeouted for CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
cid, h_al, h_qp, new_cid ) );
- __ndi_complete_irp_ex( h_qp, STATUS_CONNECTION_ABORTED, NDI_CM_IDLE );
+ // TODO: REP IRPs don't get queued int he IRP queue, so don't complete some random IRP (like a DREQ)
+ //__ndi_complete_irp_ex( h_qp, STATUS_CONNECTION_ABORTED );
break;
case CM_DREQ_ATTR_ID:
+ __ndi_proc_drep( h_qp );
+ break;
+
default:
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("Unhandled MAD attr ID %d for CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
@@ -767,10 +882,6 @@ __ndi_cm_handler(
}
else
{
- h_cm.h_al = h_al;
- h_cm.h_qp = h_qp;
- h_cm.cid = cid;
-
switch( p_mad->attr_id )
{
case CM_REP_ATTR_ID:
@@ -780,14 +891,14 @@ __ndi_cm_handler(
CL_ASSERT( ((al_conn_qp_t*)h_qp)->cid == (int32_t)cid ||
((al_conn_qp_t*)h_qp)->cid == AL_INVALID_CID ||
((al_conn_qp_t*)h_qp)->cid == AL_RESERVED_CID );
- __ndi_proc_rep( &h_cm, (mad_cm_rep_t*)p_mad );
+ __ndi_proc_rep( h_qp, cid );
break;
case CM_REJ_ATTR_ID:
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
("REJ received for CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
cid, h_al, h_qp, new_cid ) );
- __ndi_proc_rej( &h_cm, (mad_cm_rej_t*)p_mad );
+ __ndi_proc_rej( h_qp, (mad_cm_rej_t*)p_mad );
break;
case CM_DREQ_ATTR_ID:
@@ -797,7 +908,11 @@ __ndi_cm_handler(
CL_ASSERT( ((al_conn_qp_t*)h_qp)->cid == (int32_t)cid ||
((al_conn_qp_t*)h_qp)->cid == AL_INVALID_CID ||
((al_conn_qp_t*)h_qp)->cid == AL_RESERVED_CID );
- __ndi_proc_dreq( &h_cm, (mad_cm_dreq_t*)p_mad );
+ __ndi_proc_dreq( h_qp );
+ break;
+
+ case CM_DREP_ATTR_ID:
+ __ndi_proc_drep( h_qp );
break;
default:
@@ -859,57 +974,47 @@ __ndi_fill_cm_req(
AL_EXIT( AL_DBG_NDI );
}
-static void AL_API
-__ndi_pr_query_cb(
- ib_query_rec_t *p_query_rec )
+
+NTSTATUS
+__ndi_send_req(
+ IN IRP* p_irp
+ )
{
ib_api_status_t status;
- cl_ioctl_handle_t h_ioctl;
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
+ ib_path_rec_t *p_path_rec = p_irp->Tail.Overlay.DriverContext[1];
+ ual_ndi_req_cm_ioctl_in_t *p_req =
+ (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
+ NTSTATUS nt_status;
ib_cm_req_t cm_req;
- 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* __ptr64)p_query_rec->query_context;
- ib_qp_handle_t h_qp = (ib_qp_handle_t)(ULONG_PTR)p_req->h_qp;
AL_ENTER( AL_DBG_NDI );
- AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
- ("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 || status != IB_SUCCESS || !p_query_rec->result_cnt )
- goto err_irp_complete;
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
- /* Path Record has been received ! */
- p_path_rec = ib_get_query_path_rec( p_query_rec->p_result_mad, 0 );
-
- /* fix packet life */
- CL_ASSERT( p_path_rec );
- pkt_life = ib_path_rec_pkt_life( p_path_rec ) + g_pkt_life_modifier;
- if( pkt_life > 0x1F )
- pkt_life = 0x1F;
-
- p_path_rec->pkt_life &= IB_PATH_REC_SELECTOR_MASK;
- p_path_rec->pkt_life |= pkt_life;
+ if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_QPR_SENT )
+ {
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
+ ("Unexpected state: %d\n", h_qp->p_irp_queue->state) );
+ return STATUS_CONNECTION_ABORTED;
+ }
/* Get a CEP and bind it to the QP. */
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,
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("al_create_cep returned %s.\n", ib_get_err_str( status )) );
- goto err_irp_complete;
+ return STATUS_INSUFFICIENT_RESOURCES;
}
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
("Created Active CEP with cid %d, h_al %p, context %p\n",
((al_conn_qp_t*)h_qp)->cid, qp_get_al( h_qp ), h_qp ) );
- /* Take a reference on behalf of the CEP. */
- ref_al_obj( &h_qp->obj );
+ ref_al_obj( &h_qp->obj ); /* Take CEP reference. */
/* Format ib_cm_req_t structure */
__ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );
@@ -917,113 +1022,195 @@ __ndi_pr_query_cb(
/* prepare CEP for connection */
status = al_cep_pre_req( qp_get_al( h_qp ),
((al_conn_qp_t*)h_qp)->cid, &cm_req, &qp_mod );
- if( status != IB_SUCCESS )
+ if( status != STATUS_SUCCESS )
{
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("al_cep_pre_req returned %s.\n", ib_get_err_str( status )) );
- goto err_cep_destroy;
+ goto error;
}
- /* insert IRP in the queue */
- h_qp->p_irp_que->state = NDI_CM_CONNECTING_REQ_SENT;
- IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL );
-
/* send CM REQ */
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;
-
- /* we can release it now. In case of QP destroy __destroying_qp will remove CEP */
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
+ {
+ AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
+ ("al_cep_send_req returned %s.\n", ib_get_err_str( status )) );
+ goto error;
+ }
/* SUCCESS ! */
- goto exit;
-
-err_irp_remove:
- h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
+ AL_EXIT( AL_DBG_NDI );
+ return STATUS_SUCCESS;
-err_cep_destroy:
+error:
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 )
+ switch( status )
{
+ case IB_INVALID_HANDLE:
+ nt_status = STATUS_CANCELLED;
+ break;
+
+ case IB_INVALID_STATE:
+ nt_status = STATUS_CONNECTION_ABORTED;
+ break;
+
+ default:
+ nt_status = ib_to_ntstatus( status );
+ }
+
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ AL_EXIT( AL_DBG_NDI );
+ return nt_status;
+}
+
+
+static void AL_API
+__ndi_pr_query_cb(
+ ib_query_rec_t *p_query_rec )
+{
+ ib_api_status_t status;
+ cl_ioctl_handle_t p_irp;
+ uint8_t pkt_life;
+ ib_path_rec_t *p_path_rec;
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)p_query_rec->query_context;
+ NTSTATUS nt_status;
+ KIRQL irql;
+
+ AL_ENTER( AL_DBG_NDI );
+
+ AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
+ ("status is %d, count is %d, context %p\n", p_query_rec->status,
+ p_query_rec->result_cnt, p_query_rec->query_context) );
+
+ p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
+ if( p_irp == NULL )
+ {
+ goto exit;
+ }
+
+ status = p_query_rec->status;
+ if( status != IB_SUCCESS || !p_query_rec->result_cnt )
+ {
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
switch( status )
{
case IB_TIMEOUT:
- __ndi_complete_irp( h_qp, h_ioctl, STATUS_TIMEOUT );
+ __ndi_complete_irp( h_qp, p_irp, STATUS_TIMEOUT );
break;
- case IB_INVALID_STATE:
- __ndi_complete_irp( h_qp, h_ioctl, STATUS_CONNECTION_ACTIVE );
+ case IB_CANCELED:
+ __ndi_complete_irp( h_qp, p_irp, STATUS_CANCELLED );
break;
default:
- __ndi_complete_irp( h_qp, h_ioctl, STATUS_HOST_UNREACHABLE );
+ __ndi_complete_irp( h_qp, p_irp, STATUS_HOST_UNREACHABLE );
}
+ goto exit;
}
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
-exit:
- cl_free( p_req );
+ /* Path Record has been received ! */
+ p_path_rec = ib_get_query_path_rec( p_query_rec->p_result_mad, 0 );
+
+ /* fix packet life */
+ CL_ASSERT( p_path_rec );
+ pkt_life = ib_path_rec_pkt_life( p_path_rec ) + g_pkt_life_modifier;
+ if( pkt_life > 0x1F )
+ pkt_life = 0x1F;
+
+ p_path_rec->pkt_life &= IB_PATH_REC_SELECTOR_MASK;
+ p_path_rec->pkt_life |= pkt_life;
+
+ p_irp->Tail.Overlay.DriverContext[1] = p_path_rec;
+
+ nt_status = IoCsqInsertIrpEx(
+ &h_qp->p_irp_queue->csq,
+ p_irp,
+ NULL,
+ (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT
+ );
+ if( nt_status != STATUS_SUCCESS )
+ {
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
+ __ndi_complete_irp( h_qp, p_irp, nt_status );
+ }
+ else
+ {
+ /*
+ * Release the previous reference because IoCsqInsertIrpEx
+ * took a new one.
+ */
+ deref_al_obj( &h_qp->obj ); /* Release IRP reference. */
+ }
+
+exit:
+
if( p_query_rec->p_result_mad )
ib_put_mad( p_query_rec->p_result_mad );
+ deref_al_obj( &h_qp->obj ); /* release path query reference */
AL_EXIT( AL_DBG_NDI );
}
-/* Synchronously query the SA for a GUID. Return 0 on success. */
-void
+/*
+ * Send asynchronous query to the SA for a path record.
+ *
+ * Called from the __ndi_insert_irp_ex function, so the CSQ lock is held.
+ */
+NTSTATUS
__ndi_pr_query(
- IN cl_ioctl_handle_t h_ioctl,
- IN ual_ndi_req_cm_ioctl_in_t *p_req,
- IN ib_gid_t *p_dest_gid )
+ IN IRP* p_irp
+ )
{
- ib_gid_pair_t user_query;
ib_query_req_t query_req;
ib_api_status_t status;
- ib_qp_handle_t VOID_PTR64 h_qp = (ib_qp_handle_t VOID_PTR64)HDL_TO_PTR(p_req->h_qp);
+ ual_ndi_req_cm_ioctl_in_t *p_req =
+ (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
AL_ENTER( AL_DBG_NDI );
+ if ( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_ATS_SENT )
+ {
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
+ ("STATUS_CONNECTION_ACTIVE: h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
+ return STATUS_CONNECTION_ABORTED;
+ }
+
query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS;
- query_req.p_query_input = &user_query;
+ query_req.p_query_input = &p_req->gids;
query_req.port_guid = p_req->guid;
query_req.timeout_ms = g_sa_timeout;
query_req.retry_cnt = g_sa_retries;
query_req.flags = 0; /* IB_FLAGS_SYNC */
- query_req.query_context = p_req;
+ query_req.query_context = h_qp;
query_req.pfn_query_cb = __ndi_pr_query_cb;
- user_query.src_gid.unicast.prefix = p_dest_gid->unicast.prefix;
- user_query.src_gid.unicast.interface_id = p_req->guid;
- user_query.dest_gid = *p_dest_gid;
-
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
("Query for path from %I64x to %I64x\n",
- p_req->guid, ib_gid_get_guid( p_dest_gid )) );
+ p_req->guid, ib_gid_get_guid( &p_req->gids.dest_gid )) );
- /* insert IRP in the queue */
- h_qp->p_irp_que->state = NDI_CM_CONNECTING_QPR_SENT;
- IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL );
+ ref_al_obj( &h_qp->obj ); /* take path query reference */
- status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_que->h_query );
+ status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_queue->h_query );
if( status != IB_SUCCESS )
{
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) );
- cl_free( p_req );
- __ndi_complete_irp_ex( h_qp, CL_ERROR, NDI_CM_IDLE );
- /* relase additional reference, taken in __ndi_ats_query */
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) );
+ deref_al_obj( &h_qp->obj ); /* release path query reference */
+ return ib_to_ntstatus( status );
}
AL_EXIT( AL_DBG_NDI );
+ return STATUS_SUCCESS;
}
@@ -1031,10 +1218,12 @@ static void AL_API
__ndi_ats_query_cb(
IN ib_query_rec_t *p_query_rec )
{
- cl_ioctl_handle_t h_ioctl;
+ cl_ioctl_handle_t p_irp;
ib_service_record_t *service_record;
- 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);
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)p_query_rec->query_context;
+ ual_ndi_req_cm_ioctl_in_t *p_req;
+ KIRQL irql;
+ NTSTATUS status;
AL_ENTER( AL_DBG_NDI );
@@ -1042,59 +1231,99 @@ __ndi_ats_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) );
- h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
- if( !h_ioctl || p_query_rec->status != IB_SUCCESS || !p_query_rec->result_cnt )
+ p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
+ if( p_irp == NULL )
+ {
+ goto exit;
+ }
+
+ if( p_query_rec->status != IB_SUCCESS || !p_query_rec->result_cnt )
{
- NTSTATUS status;
- if( p_query_rec->status == IB_TIMEOUT )
- {
- status = STATUS_TIMEOUT;
- }
- else
- {
- status = STATUS_HOST_UNREACHABLE;
- }
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- if ( h_ioctl )
- __ndi_complete_irp( h_qp, h_ioctl, status );
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
- cl_free( p_req );
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+
+ if( p_query_rec->status == IB_TIMEOUT )
+ {
+ __ndi_complete_irp( h_qp, p_irp, STATUS_TIMEOUT );
+ }
+ else
+ {
+ __ndi_complete_irp( h_qp, p_irp, STATUS_HOST_UNREACHABLE );
+ }
+
goto exit; /* ATS request failed */
}
/* send Path Request */
service_record = ib_get_query_svc_rec( p_query_rec->p_result_mad, 0 );
- __ndi_pr_query( h_ioctl, p_req, &service_record->service_gid );
+ p_req = (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
+ p_req->gids.src_gid.unicast.prefix = service_record->service_gid.unicast.prefix;
+ p_req->gids.src_gid.unicast.interface_id = p_req->guid;
+ p_req->gids.dest_gid = service_record->service_gid;
+ status = IoCsqInsertIrpEx(
+ &h_qp->p_irp_queue->csq,
+ p_irp,
+ NULL,
+ (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_QPR_SENT
+ );
+ if( status != STATUS_SUCCESS )
+ {
+ __ndi_complete_irp( h_qp, p_irp, status );
+ }
+ else
+ {
+ /*
+ * Release the previous reference because IoCsqInsertIrpEx
+ * took a new one.
+ */
+ deref_al_obj( &h_qp->obj ); /* Release IRP reference. */
+ }
exit:
if( p_query_rec->p_result_mad )
ib_put_mad( p_query_rec->p_result_mad );
+ deref_al_obj( &h_qp->obj ); /* release ATS query reference */
AL_EXIT( AL_DBG_NDI );
}
-/* Send asynchronous query to SA for a GUID. Return STATUS_PENDING on success. */
+/*
+ * Send asynchronous query to the SA for an ATS record.
+ *
+ * Called from the __ndi_insert_irp_ex function, so the CSQ lock is held.
+ */
NTSTATUS
__ndi_ats_query(
- IN ib_qp_handle_t FUNC_PTR64 const h_qp,
- IN cl_ioctl_handle_t h_ioctl,
- IN ual_ndi_req_cm_ioctl_in_t *p_req )
+ IN IRP* p_irp
+ )
{
ib_user_query_t user_query;
ib_service_record_t service_record;
ib_query_req_t query_req;
ib_api_status_t status;
- NTSTATUS nt_status = STATUS_PENDING;
+ ual_ndi_req_cm_ioctl_in_t *p_req =
+ (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
AL_ENTER( AL_DBG_NDI );
+ if ( h_qp->p_irp_queue->state != NDI_CM_IDLE )
+ {
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
+ ("STATUS_CONNECTION_ACTIVE: h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
+ return STATUS_CONNECTION_ACTIVE;
+ }
+
query_req.query_type = IB_QUERY_USER_DEFINED;
query_req.p_query_input = &user_query;
query_req.port_guid = p_req->guid;
query_req.timeout_ms = g_sa_timeout;
query_req.retry_cnt = g_sa_retries;
query_req.flags = 0; /* IB_FLAGS_SYNC */
- query_req.query_context = p_req;
+ query_req.query_context = h_qp;
query_req.pfn_query_cb = __ndi_ats_query_cb;
/* TODO: which method one is correct? */
@@ -1135,81 +1364,45 @@ __ndi_ats_query(
("h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
(uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
- // preserve QP for the life of this IOCTL
- ref_al_obj( &h_qp->obj ); /* take IRP life reference */
-
- /* insert IRP in the queue */
- IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL );
-
- /* prevent destroying QP after cancelling of the IRP and before ib_query calback*/
- ref_al_obj( &h_qp->obj ); /* take IRP SA reference */
+ ref_al_obj( &h_qp->obj ); /* take ATS query reference */
/* query SA */
- status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_que->h_query );
+ status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_queue->h_query );
if( status != IB_SUCCESS )
{
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) );
- deref_al_obj( &h_qp->obj ); /* release IRP SA reference */
- h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL );
- if ( h_ioctl )
- { /* IOCTL should be released in the caller */
- deref_al_obj( &h_qp->obj ); /* release IRP life reference */
- nt_status = STATUS_DRIVER_INTERNAL_ERROR;
- }
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) );
+ deref_al_obj( &h_qp->obj ); /* release ATS query reference */
+ return STATUS_UNSUCCESSFUL;
}
AL_EXIT( AL_DBG_NDI );
- return nt_status;
+ return STATUS_SUCCESS;
}
+
NTSTATUS
ndi_req_cm(
- IN ib_qp_handle_t FUNC_PTR64 const h_qp,
- IN cl_ioctl_handle_t h_ioctl,
- IN ual_ndi_req_cm_ioctl_in_t *p_req
+ IN ib_qp_handle_t const h_qp,
+ IN IRP *p_irp
)
{
NTSTATUS nt_status;
AL_ENTER( AL_DBG_NDI );
- /* check outstanding request */
- __ndi_acquire_lock( &h_qp->p_irp_que->csq, NULL);
- if ( h_qp->p_irp_que->h_ioctl )
- {
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("STATUS_CONNECTION_ACTIVE: h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
- (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
- nt_status = STATUS_CONNECTION_ACTIVE;
- __ndi_release_lock( &h_qp->p_irp_que->csq, 0 );
- goto exit;
- }
- if ( h_qp->p_irp_que->state != NDI_CM_IDLE )
- {
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("STATUS_INVALID_DEVICE_STATE: h_qp %I64x, ref_cnt %d, state %d\n",
- (uint64_t)h_qp, h_qp->obj.ref_cnt, h_qp->p_irp_que->state ) );
- nt_status = STATUS_INVALID_DEVICE_STATE;
- __ndi_release_lock( &h_qp->p_irp_que->csq, 0 );
- goto exit;
- }
- h_qp->p_irp_que->h_ioctl = h_ioctl; /* mark IRP as present */
- h_qp->p_irp_que->state = NDI_CM_CONNECTING_ATS_SENT;
- __ndi_release_lock( &h_qp->p_irp_que->csq, 0 );
+ p_irp->Tail.Overlay.DriverContext[0] = (ib_qp_t*)h_qp;
- /* send ATS request */
- nt_status = __ndi_ats_query( h_qp, h_ioctl, p_req );
+ nt_status = IoCsqInsertIrpEx(
+ &h_qp->p_irp_queue->csq,
+ p_irp,
+ NULL,
+ (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_ATS_SENT
+ );
+ if( nt_status == STATUS_SUCCESS )
+ nt_status = STATUS_PENDING;
-exit:
- if ( nt_status != STATUS_PENDING )
- {
- cl_free( p_req );
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- h_qp->p_irp_que->h_ioctl = NULL; /* mark IRP as present */
- cl_ioctl_complete( h_ioctl, nt_status, 0 );
- }
AL_EXIT( AL_DBG_NDI );
- return STATUS_PENDING;
+ return nt_status;
}
@@ -1220,13 +1413,14 @@ exit:
******************************************************************/
static void
-__ndi_rtu_cm(
+__ndi_do_rtu(
IN DEVICE_OBJECT* p_dev_obj,
IN PIRP p_irp )
{
- NTSTATUS nt_status;
ib_api_status_t status;
ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
+ KIRQL irql;
+ NTSTATUS nt_status;
UNUSED_PARAM(p_dev_obj);
@@ -1234,10 +1428,23 @@ __ndi_rtu_cm(
/* free the work item if any */
if ( p_irp->Tail.Overlay.DriverContext[1] )
+ {
IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
+ deref_al_obj( &h_qp->obj ); /* Release work item reference. */
+ }
+
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_REP_RCVD )
+ {
+ nt_status = STATUS_CONNECTION_ABORTED;
+ goto exit;
+ }
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
/* change the QP state to RTS */
status = __ndi_qp2rts( h_qp, p_irp );
+
if ( status != IB_SUCCESS )
{
goto err;
@@ -1260,29 +1467,32 @@ err:
AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- nt_status = STATUS_DRIVER_INTERNAL_ERROR;
- p_irp->IoStatus.Information = 0;
+
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+
+ nt_status = STATUS_CONNECTION_ABORTED;
goto exit;
}
- p_irp->IoStatus.Information = sizeof(uint32_t);;
- h_qp->p_irp_que->state = NDI_CM_CONNECTED;
- nt_status = STATUS_SUCCESS;
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state == NDI_CM_CONNECTING_REP_RCVD )
+ h_qp->p_irp_queue->state = NDI_CM_CONNECTED;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
-exit:
- /* release the reference only for async case */
- if ( p_irp->Tail.Overlay.DriverContext[1] )
- deref_al_obj( &h_qp->obj );
+ nt_status = STATUS_SUCCESS;
- p_irp->IoStatus.Status = nt_status;
- IoCompleteRequest( p_irp, IO_NO_INCREMENT );
+exit:
+ __ndi_complete_irp( h_qp, p_irp, nt_status );
AL_EXIT( AL_DBG_NDI );
}
+
cl_status_t
ndi_rtu_cm(
- IN ib_qp_handle_t FUNC_PTR64 const h_qp,
+ IN ib_qp_handle_t const h_qp,
IN PIRP p_irp
)
{
@@ -1293,18 +1503,19 @@ ndi_rtu_cm(
p_irp->Tail.Overlay.DriverContext[0] = h_qp;
p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
p_irp->Tail.Overlay.DriverContext[1] = IoAllocateWorkItem( p_io_stack->DeviceObject );
+ ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
+
if ( p_irp->Tail.Overlay.DriverContext[1] )
{ /* asyncronous performing */
/* take a ref to prevent QP destroy before calling work item */
- ref_al_obj( &h_qp->obj );
+ ref_al_obj( &h_qp->obj ); /* Take work item reference. */
IoMarkIrpPending( p_irp );
IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],
- __ndi_rtu_cm, DelayedWorkQueue, p_irp );
+ __ndi_do_rtu, DelayedWorkQueue, p_irp );
}
else
{ /* syncronous performing */
- p_irp->Tail.Overlay.DriverContext[1] = NULL;
- __ndi_rtu_cm( p_io_stack->DeviceObject, p_irp );
+ __ndi_do_rtu( p_io_stack->DeviceObject, p_irp );
}
AL_EXIT( AL_DBG_NDI );
@@ -1319,29 +1530,32 @@ ndi_rtu_cm(
******************************************************************/
static void
-__ndi_rep_cm(
+__ndi_do_rep(
IN DEVICE_OBJECT* p_dev_obj,
- IN PIRP p_irp )
+ IN PIRP p_irp )
{
- NTSTATUS nt_status;
+ ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
ib_api_status_t status;
- ib_qp_handle_t VOID_PTR64 h_qp = p_irp->Tail.Overlay.DriverContext[0];
- ual_ndi_rep_cm_ioctl_in_t *p_rep =
- (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
+ ual_ndi_rep_cm_ioctl_in_t *p_rep;
+ KIRQL irql;
+ NTSTATUS nt_status;
UNUSED_PARAM(p_dev_obj);
AL_ENTER( AL_DBG_NDI );
/* free the work item if any */
- if ( p_irp->Tail.Overlay.DriverContext[1] )
- IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
+ CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] != NULL );
+ IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
+ deref_al_obj( &h_qp->obj ); /* Release work item reference. */
+
+ p_rep = (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
/* change the QP state to RTS */
status = __ndi_qp2rts( h_qp, p_irp );
if ( status != IB_SUCCESS )
{
- nt_status = STATUS_CONNECTION_ABORTED;
goto err;
}
@@ -1351,10 +1565,6 @@ __ndi_rep_cm(
{
AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("al_cep_send_rep returned %s\n", ib_get_err_str(status)) );
- if (status == IB_INSUFFICIENT_RESOURCES)
- nt_status = STATUS_INSUFFICIENT_RESOURCES;
- else
- nt_status = STATUS_CONNECTION_ABORTED;
err:
/* Reject and abort the connection. */
al_cep_rej( qp_get_al( h_qp ), p_rep->cid, IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
@@ -1367,28 +1577,31 @@ err:
AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("al_cep_rtu returned %s.\n", ib_get_err_str( status )) );
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- p_irp->IoStatus.Information = 0;
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
+ h_qp->p_irp_queue->state = NDI_CM_IDLE;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
+ if (status == IB_INVALID_STATE)
+ nt_status = STATUS_CONNECTION_ABORTED;
+ else
+ nt_status =STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
- p_irp->IoStatus.Information = cl_ioctl_out_size( p_irp );
- h_qp->p_irp_que->state = NDI_CM_CONNECTED;
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ if( h_qp->p_irp_queue->state == NDI_CM_CONNECTING_REP_SENT )
+ h_qp->p_irp_queue->state = NDI_CM_CONNECTED;
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
nt_status = STATUS_SUCCESS;
-exit:
- /* release the reference only for async case */
- if ( p_irp->Tail.Overlay.DriverContext[1] )
- deref_al_obj( &h_qp->obj );
-
- p_irp->IoStatus.Status = nt_status;
- IoCompleteRequest( p_irp, IO_NO_INCREMENT );
+exit:
+ __ndi_complete_irp( h_qp, p_irp, nt_status );
AL_EXIT( AL_DBG_NDI );
}
static void
__ndi_fill_cm_rep(
- IN ib_qp_handle_t FUNC_PTR64 const h_qp,
+ IN ib_qp_handle_t const h_qp,
IN ual_ndi_rep_cm_ioctl_in_t *p_rep,
OUT ib_cm_rep_t *p_cm_rep)
{
@@ -1413,141 +1626,220 @@ __ndi_fill_cm_rep(
AL_EXIT( AL_DBG_NDI );
}
+
NTSTATUS
-ndi_rep_cm(
- 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
- )
+__ndi_send_rep(
+ IN ib_qp_handle_t h_qp,
+ IN PIRP p_irp )
{
IO_STACK_LOCATION *p_io_stack;
ib_cm_rep_t cm_rep;
ib_qp_mod_t qp_mod;
ib_api_status_t status;
- NTSTATUS nt_status;
+ ual_ndi_rep_cm_ioctl_in_t *p_rep =
+ (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
AL_ENTER( AL_DBG_NDI );
+ if( h_qp->p_irp_queue->state != NDI_CM_IDLE )
+ {
+ AL_EXIT( AL_DBG_NDI );
+ return STATUS_CONNECTION_ACTIVE;
+ }
+
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
+ p_irp->Tail.Overlay.DriverContext[1] = IoAllocateWorkItem( p_io_stack->DeviceObject );
+ if( p_irp->Tail.Overlay.DriverContext[1] == NULL )
+ {
+ AL_EXIT( AL_DBG_NDI );
+ return STATUS_NO_MEMORY;
+ }
+ ref_al_obj( &h_qp->obj ); /* Take work item reference. */
+
/* Format ib_cm_req_t structure */
__ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );
+ ref_al_obj( &h_qp->obj ); /* Take CEP reference. */
+
/* 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_get_al( h_qp ), p_rep->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,
+ IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
+ deref_al_obj( &h_qp->obj ); /* Release work item reference. */
+ al_destroy_cep( qp_get_al( h_qp ), &p_rep->cid, FALSE, NULL );
+ deref_al_obj( &h_qp->obj ); /* Release CEP reference. */
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
("al_cep_pre_rep_ex returned %s.\n", ib_get_err_str( status )) );
switch (status)
{
case IB_INVALID_HANDLE:
- nt_status = STATUS_CANCELLED;
- break;
+ return STATUS_CANCELLED;
case IB_INVALID_STATE:
- nt_status = STATUS_CONNECTION_ABORTED;
- break;
+ return STATUS_CONNECTION_ABORTED;
case IB_RESOURCE_BUSY:
- nt_status = STATUS_CONNECTION_ACTIVE;
- break;
+ return STATUS_CONNECTION_ACTIVE;
default:
- nt_status = STATUS_INSUFFICIENT_RESOURCES;
- break;
+ return ib_to_ntstatus( status );
}
- 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 ) );
+ p_rep->cid, qp_get_al( h_qp ), h_qp ) );
+
+ /*
+ * transfer work to a worker thread so that QP transitions can be done
+ * at PASSIVE_LEVEL
+ */
+ IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],
+ __ndi_do_rep, DelayedWorkQueue, p_irp );
+
+ AL_EXIT( AL_DBG_NDI );
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+ndi_rep_cm(
+ IN ib_qp_handle_t const h_qp,
+ IN PIRP p_irp
+ )
+{
+ NTSTATUS status;
+ KIRQL irql;
+
+ AL_ENTER( AL_DBG_NDI );
- /* transfer work to a work the thread */
p_irp->Tail.Overlay.DriverContext[0] = h_qp;
- p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
- p_irp->Tail.Overlay.DriverContext[1] = IoAllocateWorkItem( p_io_stack->DeviceObject );
- if ( p_irp->Tail.Overlay.DriverContext[1] )
- { /* asyncronous performing */
- /* take a ref to prevent QP destroy before calling work item */
- ref_al_obj( &h_qp->obj );
+
+ __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
+ status = __ndi_send_rep( h_qp, p_irp );
+ if( status == STATUS_SUCCESS )
+ {
+ /*
+ * We're going to keep the IRP dangling for a bit - take a reference
+ * on the QP until it completes.
+ */
+ ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
+ h_qp->p_irp_queue->state = NDI_CM_CONNECTING_REP_SENT;
IoMarkIrpPending( p_irp );
- IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],
- __ndi_rep_cm, DelayedWorkQueue, p_irp );
- }
- else
- { /* syncronous performing */
- __ndi_rep_cm( p_io_stack->DeviceObject, p_irp );
+ status = STATUS_PENDING;
}
+ __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
-exit:
AL_EXIT( AL_DBG_NDI );
- return CL_PENDING;
+ return status;
}
+
/*******************************************************************
*
* DREQ CM request
*
******************************************************************/
+
NTSTATUS
-ndi_dreq_cm(
- IN ib_qp_handle_t FUNC_PTR64 const h_qp,
- IN PIRP p_irp
+__ndi_send_dreq(
+ IN IRP* p_irp
)
{
- ib_qp_mod_t qp_mod;
+ ib_qp_handle_t h_qp = (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
+ IO_STACK_LOCATION *p_io_stack;
ib_api_status_t status;
NTSTATUS nt_status;
- uint64_t timewait_us;
AL_ENTER( AL_DBG_NDI );
- status = al_cep_get_timewait( qp_get_al( h_qp ),
- ((al_conn_qp_t*)h_qp)->cid, &timewait_us );
-
- if (status != IB_SUCCESS)
+ if ( h_qp->p_irp_queue->state != NDI_CM_CONNECTED &&
+ h_qp->p_irp_queue->state != NDI_CM_CONNECTED_DREQ_RCVD )
{
- nt_status = STATUS_CONNECTION_INVALID;
- goto exit;
+ AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
+ ("STATUS_CONNECTION_ACTIVE: h_qp %#I64x, uhdl %#I64x, ref_cnt %d\n",
+ (uint64_t)h_qp, h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
+ return STATUS_CONNECTION_INVALID;
}
- al_destroy_cep(
- qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE, deref_al_obj );
+ /*
+ * Allocate a work item to perform the QP transition when disconnection
+ * completes (or the IRP is cancelled). We allocate here to trap errors
+ * properly.
+ */
+ p_io_stack = IoGetCurrentIrpStackLocation( p_irp );
+ p_irp->Tail.Overlay.DriverContext[1] = IoAllocateWorkItem( p_io_stack->DeviceObject );
+ if( p_irp->Tail.Overlay.DriverContext[1] == NULL )
+ {
+ AL_EXIT( AL_DBG_NDI );
+ return STATUS_NO_MEMORY;
+ }
+ ref_al_obj( &h_qp->obj ); /* Take work item reference. */
- /* bring QP to error state */
- cl_memclr( &qp_mod, sizeof(qp_mod) );
- qp_mod.req_state = IB_QPS_ERROR;
-
- status = ndi_modify_qp( h_qp, &qp_mod,
- cl_ioctl_out_size( p_irp ), cl_ioctl_out_buf( p_irp ) );
- if ( status != IB_SUCCESS )
+ status = al_cep_dreq( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );
+ switch( status )
{
- AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
- ("ndi_modify_qp to ERROR returned %s.\n", ib_get_err_str(status) ) );
+ case IB_INVALID_STATE:
+ /* We might have just received a DREQ, so try sending a DREP. */
+ __ndi_queue_drep( p_irp );
+ IoMarkIrpPending( p_irp );
+ /*
+ * We're going to keep the IRP dangling for a bit - take a reference
+ * on the QP until it completes.
+ */
+ ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
+
+ case IB_SUCCESS:
+ AL_EXIT( AL_DBG_NDI );
+ return( ib_to_ntstatus( status ) );
+
+ case IB_INVALID_HANDLE:
nt_status = STATUS_CONNECTION_INVALID;
- goto exit;
+ break;
+ default:
+ nt_status = ib_to_ntstatus( status );
}
+ IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
+ p_irp->Tail.Overlay.DriverContext[1] = NULL;
+ deref_al_obj( &h_qp->obj ); /* Release work item reference. */
+ AL_EXIT( AL_DBG_NDI );
+ return nt_status;
+}
- /* Store the timestamp after which the QP exits timewait. */
- h_qp->timewait = cl_get_time_stamp() + timewait_us;
- nt_status = STATUS_SUCCESS;
+NTSTATUS
+ndi_dreq_cm(
+ IN ib_qp_handle_t const h_qp,
+ IN PIRP p_irp
+ )
+{
+ NTSTATUS status;
-exit:
- h_qp->p_irp_que->state = NDI_CM_IDLE;
- cl_ioctl_complete( p_irp, nt_status, cl_ioctl_out_size( p_irp ) );
+ AL_ENTER( AL_DBG_NDI );
+
+ p_irp->Tail.Overlay.DriverContext[0] = h_qp;
+
+ status = IoCsqInsertIrpEx(
+ &h_qp->p_irp_queue->csq,
+ p_irp,
+ NULL,
+ (VOID*)(ULONG_PTR)NDI_CM_DISCONNECTING
+ );
+ /*
+ * Note that if al_cep_dreq returned IB_INVALID_STATE, we queued the
+ * work item and will try sending the DREP and move the QP to error.
+ *
+ * The IRP should never be queued if the work item is queued, so
+ * we trap the special error code for INVALID_STATE.
+ */
+ if( status == STATUS_SUCCESS || status == STATUS_INVALID_DEVICE_STATE )
+ status = STATUS_PENDING;
AL_EXIT( AL_DBG_NDI );
- return STATUS_EVENT_DONE; /* CL_COMPLETED */
+ return status;
}
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 Wed Jul 02 09:53:24 2008
+++ trunk\core\al\kernel\al_ndi_cm.h Tue Jul 08 15:08:50 2008
@@ -67,14 +67,13 @@ typedef enum _ndi_cm_state
NDI_CM_CONNECTING_ATS_SENT, // ATS = Address Translation Service
NDI_CM_CONNECTING_QPR_SENT, // QPR = Query path record
NDI_CM_CONNECTING_REQ_SENT,
+ NDI_CM_CONNECTING_REP_SENT,
NDI_CM_CONNECTING_REP_RCVD,
- NDI_CM_CONNECTING_REJ_RCVD,
NDI_CM_CONNECTED,
- NDI_CM_BOUND,
- NDI_CM_LISTENING,
- NDI_CM_REP_SENT,
- NDI_CM_CONNECTED_DREP_SENT,
- NDI_CM_CONNECTED_DREQ_SENT,
+ NDI_CM_DISCONNECTING,
+ NDI_CM_CONNECTED_DREQ_RCVD,
+ NDI_CM_INVALID
+
} ndi_cm_state_t;
typedef struct _ib_qp ib_qp_t;
@@ -82,12 +81,12 @@ typedef struct _ib_qp ib_qp_t;
typedef struct _ndi_qp_csq
{
IO_CSQ csq;
+ LIST_ENTRY queue;
ib_qp_t* h_qp;
ib_query_handle_t h_query;
- LIST_ENTRY que;
ndi_cm_state_t state;
PIO_WORKITEM p_workitem;
- PIRP h_ioctl;
+
} ndi_qp_csq_t;
ib_api_status_t
@@ -100,16 +99,13 @@ ndi_modify_qp(
NTSTATUS
ndi_req_cm(
IN ib_qp_handle_t const h_qp,
- IN cl_ioctl_handle_t h_ioctl,
- IN ual_ndi_req_cm_ioctl_in_t *p_req
+ IN cl_ioctl_handle_t h_ioctl
);
NTSTATUS
ndi_rep_cm(
IN ib_qp_handle_t const h_qp,
- IN net32_t cid,
- IN cl_ioctl_handle_t h_ioctl,
- IN ual_ndi_rep_cm_ioctl_in_t *p_ndi_rep_cm
+ IN PIRP p_irp
);
cl_status_t
@@ -123,11 +119,6 @@ ndi_dreq_cm(
IN ib_qp_handle_t const h_qp,
IN PIRP p_irp
);
-
-void
-ndi_qp_flush_ques(
- IN ib_qp_handle_t FUNC_PTR64 h_qp );
-
NTSTATUS
ndi_qp_init(
diff -up -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\al\kernel\al_proxy.c trunk\core\al\kernel\al_proxy.c
--- old\core\al\kernel\al_proxy.c Tue Jul 01 11:17:08 2008
+++ trunk\core\al\kernel\al_proxy.c Tue Jul 08 15:13:21 2008
@@ -1204,3 +1204,84 @@ al_ioctl(
AL_EXIT( AL_DBG_DEV );
return cl_status;
}
+
+
+NTSTATUS
+ib_to_ntstatus(
+ IN ib_api_status_t ib_status )
+{
+ switch( ib_status )
+ {
+ case IB_SUCCESS:
+ return STATUS_SUCCESS;
+ case IB_INSUFFICIENT_RESOURCES:
+ case IB_MAX_MCAST_QPS_REACHED:
+ return STATUS_INSUFFICIENT_RESOURCES;
+ case IB_INSUFFICIENT_MEMORY:
+ return STATUS_NO_MEMORY;
+ case IB_INVALID_PARAMETER:
+ case IB_INVALID_SETTING:
+ case IB_INVALID_PKEY:
+ case IB_INVALID_LKEY:
+ case IB_INVALID_RKEY:
+ case IB_INVALID_MAX_WRS:
+ case IB_INVALID_MAX_SGE:
+ case IB_INVALID_CQ_SIZE:
+ case IB_INVALID_SRQ_SIZE:
+ case IB_INVALID_SERVICE_TYPE:
+ case IB_INVALID_GID:
+ case IB_INVALID_LID:
+ case IB_INVALID_GUID:
+ case IB_INVALID_WR_TYPE:
+ case IB_INVALID_PORT:
+ case IB_INVALID_INDEX:
+ return STATUS_INVALID_PARAMETER;
+ case IB_NO_MATCH:
+ case IB_NOT_FOUND:
+ return STATUS_NOT_FOUND;
+ case IB_TIMEOUT:
+ return STATUS_TIMEOUT;
+ case IB_CANCELED:
+ return STATUS_CANCELLED;
+ case IB_INTERRUPTED:
+ case IB_NOT_DONE:
+ return STATUS_ABANDONED;
+ case IB_INVALID_PERMISSION:
+ return STATUS_ACCESS_DENIED;
+ case IB_UNSUPPORTED:
+ case IB_QP_IN_TIMEWAIT:
+ case IB_EE_IN_TIMEWAIT:
+ return STATUS_INVALID_DEVICE_REQUEST;
+ case IB_OVERFLOW:
+ return STATUS_BUFFER_OVERFLOW;
+ case IB_INVALID_QP_STATE:
+ case IB_INVALID_APM_STATE:
+ case IB_INVALID_PORT_STATE:
+ case IB_INVALID_STATE:
+ return STATUS_INVALID_DEVICE_STATE;
+ case IB_RESOURCE_BUSY:
+ return STATUS_DEVICE_BUSY;
+ case IB_INVALID_CA_HANDLE:
+ case IB_INVALID_AV_HANDLE:
+ case IB_INVALID_CQ_HANDLE:
+ case IB_INVALID_QP_HANDLE:
+ case IB_INVALID_SRQ_HANDLE:
+ case IB_INVALID_PD_HANDLE:
+ case IB_INVALID_MR_HANDLE:
+ case IB_INVALID_FMR_HANDLE:
+ case IB_INVALID_MW_HANDLE:
+ case IB_INVALID_MCAST_HANDLE:
+ case IB_INVALID_CALLBACK:
+ case IB_INVALID_AL_HANDLE:
+ case IB_INVALID_HANDLE:
+ return STATUS_INVALID_HANDLE;
+ case IB_VERBS_PROCESSING_DONE:
+ return STATUS_EVENT_DONE;
+ case IB_PENDING:
+ return STATUS_PENDING;
+ case IB_ERROR:
+ case IB_REMOTE_ERROR:
+ default:
+ return STATUS_UNSUCCESSFUL;
+ }
+}
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 Wed Jul 02 09:53:25 2008
+++ trunk\core\al\kernel\al_proxy_ndi.c Tue Jul 08 15:08:50 2008
@@ -313,7 +313,7 @@ __ndi_req_cm(
cl_status_t cl_status;
ib_qp_handle_t h_qp = NULL;
al_dev_open_context_t *p_context;
- ual_ndi_req_cm_ioctl_in_t *p_parm, *p_req =
+ ual_ndi_req_cm_ioctl_in_t *p_req =
(ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl );
UNUSED_PARAM(p_ret_bytes);
@@ -340,33 +340,23 @@ __ndi_req_cm(
if( h_qp->type != IB_QPT_RELIABLE_CONN )
{
cl_status = CL_INVALID_HANDLE;
- goto exit;
+ goto err;
}
/* Check psize */
if ( p_req->pdata_size > sizeof(p_req->pdata) )
{
cl_status = CL_INVALID_PARAMETER;
- goto exit;
- }
-
- /* copy request parameters a side to prevent problems from cancelled IRP */
- p_parm = cl_zalloc( sizeof(ual_ndi_req_cm_ioctl_in_t) );
- if (!p_parm )
- {
- cl_status = CL_INSUFFICIENT_MEMORY;
- goto exit;
+ goto err;
}
- RtlCopyMemory( p_parm, p_req, sizeof(ual_ndi_req_cm_ioctl_in_t) );
- p_parm->h_qp = (uint64_t)h_qp;
/* perform the ioctl */
- cl_status = ndi_req_cm( h_qp, h_ioctl, p_parm );
+ cl_status = ndi_req_cm( h_qp, h_ioctl );
-exit:
- if (h_qp)
- deref_al_obj( &h_qp->obj );
+err:
+ deref_al_obj( &h_qp->obj );
+exit:
AL_EXIT( AL_DBG_NDI );
return cl_status;
}
@@ -390,8 +380,7 @@ __ndi_rep_cm(
p_context = (al_dev_open_context_t*)p_open_context;
/* Validate user parameters. */
- if( (cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_rep_cm_ioctl_in_t)) ||
- cl_ioctl_out_size( h_ioctl ) < sizeof(net32_t) )
+ if( (cl_ioctl_in_size( h_ioctl ) < sizeof(ual_ndi_rep_cm_ioctl_in_t)) )
{
cl_status = CL_INVALID_PARAMETER;
goto exit;
@@ -408,26 +397,26 @@ __ndi_rep_cm(
if( h_qp->type != IB_QPT_RELIABLE_CONN )
{
cl_status = CL_INVALID_HANDLE;
- goto exit;
+ goto err;
}
/* Check psize */
if ( p_rep->pdata_size >= sizeof(p_rep->pdata) )
{
cl_status = CL_INVALID_PARAMETER;
- goto exit;
+ goto err;
}
/* Get and validate CID */
cid = p_rep->cid;
/* perform the ioctls */
- cl_status = ndi_rep_cm( h_qp, cid, h_ioctl, p_rep );
+ cl_status = ndi_rep_cm( h_qp, h_ioctl );
-exit:
- if (h_qp)
- deref_al_obj( &h_qp->obj );
+err:
+ deref_al_obj( &h_qp->obj );
+exit:
AL_EXIT( AL_DBG_NDI );
return cl_status;
}
diff -up -r -X trunk\docs\dontdiff.txt -I \$Id: old\inc\iba\ib_al_ioctl.h trunk\inc\iba\ib_al_ioctl.h
--- old\inc\iba\ib_al_ioctl.h Wed Jul 02 09:53:25 2008
+++ trunk\inc\iba\ib_al_ioctl.h Tue Jul 08 15:08:50 2008
@@ -3512,6 +3512,7 @@ typedef struct _ual_ndi_notify_cq_ioctl_
*/
typedef struct _ual_ndi_req_cm_ioctl_in
{
+ ib_gid_pair_t gids;
uint64_t h_qp;
net64_t guid;
uint16_t dst_port;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nd_ioctl.patch
Type: application/octet-stream
Size: 69923 bytes
Desc: nd_ioctl.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080708/e93e1a9b/attachment.obj>
More information about the ofw
mailing list