[ofw] [PATCH] Fix ND CM IOCTL handling
Leonid Keller
leonid at mellanox.co.il
Wed Jul 9 03:33:58 PDT 2008
Applied in 1355. Thank you.
> -----Original Message-----
> From: ofw-bounces at lists.openfabrics.org
> [mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Fab Tillier
> Sent: Wednesday, July 09, 2008 1:51 AM
> To: ofw at lists.openfabrics.org
> Subject: [ofw] [PATCH] Fix ND CM IOCTL handling
>
> 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;
>
More information about the ofw
mailing list