[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