[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