[ofw] [PATCH] Fix ND connection establishment races

Leonid Keller leonid at mellanox.co.il
Sun Apr 5 08:25:59 PDT 2009


Applied in 2079, thank you. 

> -----Original Message-----
> From: ofw-bounces at lists.openfabrics.org 
> [mailto:ofw-bounces at lists.openfabrics.org] On Behalf Of Fab Tillier
> Sent: Thursday, March 26, 2009 11:05 PM
> To: ofw at lists.openfabrics.org
> Subject: [ofw] [PATCH] Fix ND connection establishment races
> 
> Hi Folks,
> 
> This patch fixes issues with connection establishment for 
> NetworkDirect.  The root cause of the issue is 'too many 
> cooks' - CIDs exposed to user-mode should not be destroyed in 
> the kernel code without explicit request from the user.  
> Otherwise, the CID can get recycled in the kernel for the 
> same process and improperly freed when the stale CID is 
> released by the application (multiple connection objects in 
> the app have the same CID.)
> 
> Unfortunately, the fix is not simple.  The QP references the 
> CEP, so QP destruction frees the CEP, even if there's a 
> reference to that CEP left in the application.  Removing the 
> CEP reference form the QP solves this problem, but deadlocks 
> the app if it destroys the QP before the CEP, since the QP is 
> used to queue connection-related IRPs, and the CEP uses the 
> QP as its context and so holds a reference on it.
> 
> This patch does the following:
> - Remove CEP reference for ND related QP.
> - Remove ND connection related IRP queue from QP.
> - Remove ND IRP handling from CEP manager.
> - Add a function to CEP manager to reference the context 
> associated with a CEP if the context is non-NULL.
> - Move ND connection related IRP management into al_ndi_cm.c, 
> in nd_csq_t structure.
> 
> As part of testing, I needed to add NotifyDisconnect 
> functionality, so this is also included in the patch.
> 
> Note that the patch depends on Sean's previous patch to 
> change kal_cep_destroy to allow silently dropping a REQ.  I 
> did not remove Sean's previous changes from this patch, so 
> they are duplicated here.  This allows the patch to be 
> applied and build.
> 
> I tested an earlier version of this, before I went through 
> and did some minor cosmetic cleanup.  I wanted to send this 
> patch to get the review process going, and will report back 
> when I finish retesting.
> 
> Sorry for the big patch, I couldn't find a good way to split 
> it up into smaller chunks.
> 
> -Fab
> 
> Signed-off-by: Fab Tillier <ftillier at microsoft.com>
> 
> Index: core/al/kernel/al_cm_cep.c
> ===================================================================
> --- core/al/kernel/al_cm_cep.c  (revision 2061)
> +++ core/al/kernel/al_cm_cep.c  (working copy)
> @@ -370,9 +370,6 @@ typedef struct _al_kcep
>          * NDI stuff - TODO: manage above core kernel CM code
>          */
> 
> -       /* IRP list head */
> -       LIST_ENTRY                                      irp_que;
> -
>         /* private data of REQ, REP, REJ CM requests */
>         uint8_t                                         psize;
>         uint8_t                                         
> pdata[IB_REP_PDATA_SIZE];
> @@ -3382,24 +3379,6 @@ create_cep_mgr(
>  * CEP manager API
>  
> **************************************************************
> ****************/
> 
> -static inline void
> -__complete_ndi_irp(
> -       IN                              PIRP                  
>                           p_irp,
> -       IN                              ib_mad_element_t*     
>                   p_mad )
> -{
> -       net32_t* p_new_cid = (net32_t*)cl_ioctl_out_buf( p_irp );
> -       kcep_t* p_cep = (kcep_t*)p_mad->send_context1;
> -
> -       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM,
> -               ("Completing al_cep_get_cid IRP with CID = 
> %d\n", p_cep->cid) );
> -
> -       *p_new_cid = p_cep->cid;
> -       p_irp->IoStatus.Information = sizeof(uint32_t);
> -       p_irp->IoStatus.Status = STATUS_SUCCESS;
> -       IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> -       ib_put_mad( p_mad );
> -}
> -
> 
>  /* Called with the CEP and CEP manager locks held */
>  static ib_api_status_t
> @@ -3422,8 +3401,6 @@ __cep_queue_mad(
>         if ( p_cep->state == CEP_STATE_LISTEN &&
>                 (p_cep->sid & ~0x0ffffffI64) == 
> IB_REQ_CM_RDMA_SID_PREFIX )
>         { /* Try to complete pending IRP, if any */
> -               PIRP p_irp;
> -               PLIST_ENTRY p_list_entry;
>                 mad_cm_req_t* p_req = 
> (mad_cm_req_t*)ib_get_mad_buf( p_mad );
>                 ib_cm_rdma_req_t *p_rdma_req = 
> (ib_cm_rdma_req_t *)p_req->pdata;
> 
> @@ -3437,24 +3414,6 @@ __cep_queue_mad(
>                                 p_rdma_req->maj_min_ver, 
> p_rdma_req->ipv ) );
>                         return IB_UNSUPPORTED;
>                 }
> -
> -               /* get a pending IRP */
> -               if ( !IsListEmpty( &p_cep->irp_que ) )
> -               {
> -                       // get IRP
> -                       p_list_entry = RemoveHeadList( 
> &p_cep->irp_que );
> -                       p_irp = (PIRP)CONTAINING_RECORD( 
> p_list_entry, IRP, Tail.Overlay.ListEntry );
> -
> -                       // complete GetConnectionReq IRP
> -#pragma warning(push, 3)
> -                       IoSetCancelRoutine( p_irp, NULL );
> -#pragma warning(pop)
> -
> -                       __complete_ndi_irp( p_irp, p_mad );
> -
> -                       AL_EXIT( AL_DBG_CM );
> -                       return IB_PENDING;
> -               }
>         }
> 
>         /* Queue this MAD for processing. */
> @@ -3628,8 +3587,6 @@ __create_cep()
> 
>         p_cep->p_cid->p_cep = p_cep;
> 
> -       InitializeListHead( &p_cep->irp_que );
> -
>         ref_al_obj( &gp_cep_mgr->obj );
> 
>         AL_EXIT( AL_DBG_CM );
> @@ -3682,7 +3639,7 @@ kal_cep_alloc(
>         return IB_SUCCESS;
>  }
> 
> -void
> +ib_api_status_t
>  kal_cep_config(
>         IN                              ib_al_handle_t        
>                   h_al,
>         IN                              net32_t               
>                           cid,
> @@ -3695,13 +3652,18 @@ kal_cep_config(
> 
>         KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
>         p_cep = __lookup_cep( h_al, cid );
> -       CL_ASSERT( p_cep );
> +       if( p_cep == NULL )
> +       {
> +               KeReleaseInStackQueuedSpinLock( &hdl );
> +               return IB_INVALID_HANDLE;
> +       }
> 
>         p_cep->pfn_cb = pfn_cb;
>         p_cep->context = context;
>         p_cep->pfn_destroy_cb = pfn_destroy_cb;
> 
>         KeReleaseInStackQueuedSpinLock( &hdl );
> +       return IB_SUCCESS;
>  }
> 
>  static inline void
> @@ -4128,7 +4090,7 @@ al_create_cep(
>         status = kal_cep_alloc(h_al, p_cid);
>         if ( status == IB_SUCCESS )
>         {
> -               kal_cep_config(h_al, *p_cid, pfn_cb, context, 
> pfn_destroy_cb);
> +               status = kal_cep_config(h_al, *p_cid, pfn_cb, 
> context, pfn_destroy_cb);
>         }
> 
>         AL_EXIT( AL_DBG_CM );
> @@ -4174,28 +4136,6 @@ al_destroy_cep(
>         context = p_cep->context;
>         pfn_destroy_cb = p_cep->pfn_destroy_cb;
> 
> -       /* Cancel any queued IRP */
> -       __cep_complete_irp( p_cep, STATUS_CANCELLED, 
> IO_NO_INCREMENT );
> -
> -    while( !IsListEmpty( &p_cep->irp_que ) )
> -    {
> -        LIST_ENTRY* p_list_entry;
> -        IRP* p_irp;
> -
> -        // get IRP
> -        p_list_entry = RemoveHeadList( &p_cep->irp_que );
> -        p_irp = (PIRP)CONTAINING_RECORD( p_list_entry, IRP, 
> Tail.Overlay.ListEntry );
> -
> -        // complete GetConnectionReq IRP
> -#pragma warning(push, 3)
> -        IoSetCancelRoutine( p_irp, NULL );
> -#pragma warning(pop)
> -
> -        p_irp->IoStatus.Information = 0;
> -        p_irp->IoStatus.Status = STATUS_CANCELLED;
> -        IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> -    }
> -
>         __unbind_cep( p_cep );
>         ref_cnt = __cleanup_cep( p_cep );
>      if( reusable )
> @@ -4218,9 +4158,35 @@ al_destroy_cep(
>  void
>  kal_cep_destroy(
>         IN                              ib_al_handle_t        
>                   h_al,
> -       IN                              net32_t               
>                           cid )
> +       IN                              net32_t               
>                           cid,
> +       IN                              NTSTATUS              
>                           status )
>  {
> -       al_destroy_cep(h_al, &cid, FALSE);
> +       KLOCK_QUEUE_HANDLE      hdl;
> +       kcep_t                          *p_cep;
> +    ib_pfn_destroy_cb_t pfn_destroy_cb;
> +       void                            *context;
> +       int32_t                         ref_cnt;
> +
> +       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> +       p_cep = __lookup_cep( h_al, cid );
> +       CL_ASSERT( p_cep );
> +
> +       context = p_cep->context;
> +       pfn_destroy_cb = p_cep->pfn_destroy_cb;
> +
> +       __unbind_cep( p_cep );
> +       /* Drop new REQs so they can be retried when 
> resources may be available */
> +       if( status == STATUS_NO_MORE_ENTRIES &&
> +               (p_cep->state == CEP_STATE_REQ_RCVD ||
> +                p_cep->state == CEP_STATE_REQ_MRA_SENT) )
> +       {
> +               p_cep->state = CEP_STATE_IDLE;
> +       }
> +       ref_cnt = __cleanup_cep( p_cep );
> +       KeReleaseInStackQueuedSpinLock( &hdl );
> +
> +       if( !ref_cnt && pfn_destroy_cb )
> +               pfn_destroy_cb( context );
>  }
> 
> 
> @@ -5078,55 +5044,6 @@ out:
> 
> 
>  ib_api_status_t
> -kal_cep_config_pre_rep_copy_cid(
> -       IN                              ib_al_handle_t        
>                   h_al,
> -       IN                              net32_t               
>                           cid,
> -       IN                              al_pfn_cep_cb_t       
>                   pfn_cb,
> -       IN                              void*                 
>                           context,
> -       IN                              ib_pfn_destroy_cb_t   
>                   pfn_destroy_cb,
> -       IN              const   iba_cm_rep* const             
>           p_cm_rep,
> -       IN                              uint8_t               
>                           rnr_nak_timeout,
> -       IN      OUT                     net32_t* const        
>                   p_cid,
> -               OUT                     ib_qp_mod_t* const    
>                   p_init )
> -{
> -       kcep_t                          *p_cep;
> -       KLOCK_QUEUE_HANDLE      hdl;
> -       ib_api_status_t         status;
> -
> -       CL_ASSERT( h_al );
> -       CL_ASSERT( p_cm_rep );
> -       CL_ASSERT( p_init );
> -
> -       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> -       if (*p_cid != AL_INVALID_CID)
> -       {
> -               status = IB_RESOURCE_BUSY;
> -               goto out;
> -       }
> -
> -       p_cep = __lookup_cep( h_al, cid );
> -       if (!p_cep )
> -       {
> -               status = IB_INVALID_HANDLE;
> -               goto out;
> -       }
> -
> -       status = __al_cep_pre_rep( p_cep, p_cm_rep, 
> rnr_nak_timeout, p_init );
> -       if ( status == IB_SUCCESS )
> -       {
> -               p_cep->pfn_cb = pfn_cb;
> -               p_cep->context = context;
> -               p_cep->pfn_destroy_cb = pfn_destroy_cb;
> -               *p_cid = cid;
> -       }
> -
> -out:
> -       KeReleaseInStackQueuedSpinLock( &hdl );
> -       return status;
> -}
> -
> -
> -ib_api_status_t
>  kal_cep_pre_rep(
>         IN                              ib_al_handle_t        
>                   h_al,
>         IN                              net32_t               
>                           cid,
> @@ -6678,60 +6595,6 @@ __cep_cancel_ndi_irp(
>         AL_EXIT( AL_DBG_CM );
>  }
> 
> -NTSTATUS
> -al_cep_get_cid(
> -       IN              ib_al_handle_t                        
>                   h_al,
> -       IN              net32_t                 const         
>                   cid,
> -       IN              PIRP                                  
>                           p_irp
> -       )
> -{
> -       kcep_t *p_cep;
> -       NTSTATUS nt_status;
> -       KLOCK_QUEUE_HANDLE hdl;
> -       ib_mad_element_t* p_mad = NULL;
> -
> -       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("[ CID = 
> %d\n", cid) );
> -       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> -
> -       p_cep = __lookup_cep( h_al, cid );
> -       if( !p_cep )
> -       {
> -               p_irp->IoStatus.Information = 0;
> -               p_irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
> -               IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> -               nt_status = STATUS_EVENT_DONE;
> -               goto exit;
> -       }
> -
> -       if( !p_cep->p_mad_head )
> -       { /* no pending MADs - queue the IRP */
> -               p_cep->signalled = FALSE;
> -               InsertTailList( &p_cep->irp_que, 
> &p_irp->Tail.Overlay.ListEntry );
> -               p_irp->Tail.Overlay.DriverContext[0] = 
> (void*)(size_t)cid;
> -               p_irp->Tail.Overlay.DriverContext[1] = (void*)h_al;
> -#pragma warning(push, 3)
> -               IoSetCancelRoutine( p_irp, __cep_cancel_ndi_irp );
> -#pragma warning(pop)
> -               IoMarkIrpPending( p_irp );
> -               nt_status = STATUS_PENDING;
> -               goto exit;
> -       }
> -
> -       /* Set the MAD. */
> -       p_mad = p_cep->p_mad_head;
> -       p_cep->p_mad_head = p_mad->p_next;
> -       p_mad->p_next = NULL;
> -
> -       /* complete the IRP */
> -       __complete_ndi_irp( p_irp, p_mad );
> -       nt_status = STATUS_EVENT_DONE;
> -
> -exit:
> -       KeReleaseInStackQueuedSpinLock( &hdl );
> -       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("] 
> returned %08x\n", nt_status) );
> -       return nt_status;
> -}
> -
> 
>  NTSTATUS
>  al_cep_get_pdata(
> @@ -6778,4 +6641,58 @@ al_cep_get_pdata(
>         KeReleaseInStackQueuedSpinLock( &hdl );
>         AL_EXIT( AL_DBG_CM );
>         return STATUS_SUCCESS;
> +}
> +
> +
> +/*
> + * This function is designed to support moving the 
> NetorkDirect IRP queue to the CEP
> + * without performing major surgery on the CEP manager.
> + *
> + * It retrieves the context associated with a CEP, using the 
> pfn_addref function
> + * to prevent the context from being destroyed after it is returned.
> + *
> + * It returns NULL if there is no context, requiring 
> contexts to be pointers.
> + */
> +void*
> +kal_cep_get_context(
> +       IN                              ib_al_handle_t        
>                   h_al,
> +       IN                              net32_t               
>                           cid,
> +       IN                              al_pfn_cep_cb_t       
>                   pfn_cb,
> +       IN                              ib_pfn_destroy_cb_t   
>                   pfn_addref )
> +{
> +       kcep_t                          *p_cep;
> +       void*                           context = NULL;
> +       KLOCK_QUEUE_HANDLE      hdl;
> +
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("[ CID = 
> %d\n", cid) );
> +
> +       CL_ASSERT( h_al );
> +       CL_ASSERT( pfn_addref );
> +
> +       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );
> +       p_cep = __lookup_cep( h_al, cid );
> +       if( !p_cep )
> +       {
> +               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> +                       ("CEP not found for cid %d, h_al 
> %p\n", cid, h_al ));
> +               goto out;
> +       }
> +
> +       if( p_cep->pfn_cb != pfn_cb )
> +       {
> +               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> +                       ("CEP callback mismatch for cid %d, 
> h_al %p\n", cid, h_al ));
> +               goto out;
> +       }
> +
> +       context = p_cep->context;
> +       if( context != NULL )
> +       {
> +               pfn_addref( context );
> +       }
> +
> +out:
> +       KeReleaseInStackQueuedSpinLock( &hdl );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_CM, ("] 
> returning %p\n", context) );
> +       return context;
>  }
> Index: core/al/kernel/al_ndi_cm.c
> ===================================================================
> --- core/al/kernel/al_ndi_cm.c  (revision 2061)
> +++ core/al/kernel/al_ndi_cm.c  (working copy)
> @@ -81,7 +81,7 @@ __ndi_send_req(
> 
>  NTSTATUS
>  __ndi_send_rep(
> -       IN              ib_qp_handle_t                        
>                   h_qp,
> +       IN              nd_csq_t                              
>                           *p_csq,
>         IN              PIRP                                  
>                           p_irp
>         );
> 
> @@ -90,11 +90,18 @@ __ndi_send_dreq(
>         IN              IRP*                                  
>                           p_irp
>         );
> 
> +NTSTATUS
> +__ndi_get_req(
> +       IN              nd_csq_t                              
>                           *p_csq,
> +       IN              IRP*                                  
>                           p_irp
> +       );
> +
>  static void
>  __ndi_queue_drep(
>         IN                              IRP                   
>                                   *p_irp
>         );
> 
> +
>  /*******************************************************************
>   *
>   * Helpers
> @@ -123,12 +130,12 @@ static char * State2String(ndi_cm_state_
> 
>  static inline void
>  __ndi_complete_irp(
> -       IN      ib_qp_handle_t                                
>                   h_qp,
> +       IN      nd_csq_t*                                     
>                           p_csq,
>         IN      PIRP                                          
>                           p_irp,
>         IN      NTSTATUS                                      
>                           status
>         )
>  {
> -       AL_ENTER( AL_DBG_NDI );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = 
> %d\n", p_csq->cid) );
> 
>         CL_ASSERT( p_irp );
>         CL_ASSERT( p_irp->Tail.Overlay.DriverContext[1] == NULL );
> @@ -144,7 +151,7 @@ __ndi_complete_irp(
>                 p_irp->IoStatus.Information = 0;
>                 IoCompleteRequest( p_irp, 0 );
>         }
> -       deref_al_obj( &h_qp->obj ); /* Release IRP reference */
> +       nd_csq_release( p_csq ); /* Release IRP reference */
> 
>         AL_EXIT( AL_DBG_NDI );
>  }
> @@ -159,23 +166,28 @@ __ndi_complete_irp(
>   */
>  static void
>  __cep_timewait_qp(
> -       IN              const   ib_qp_handle_t                
>           h_qp )
> +       IN                              nd_csq_t              
>                           *p_csq )
>  {
>         uint64_t                        timewait = 0;
> +       ib_qp_handle_t          h_qp;
>         ib_qp_mod_t                     qp_mod;
>         ib_api_status_t         status;
> 
>         AL_ENTER( AL_DBG_CM );
> 
> -       CL_ASSERT( h_qp );
> +       CL_ASSERT( p_csq != NULL );
> 
>         /*
>          * The CM should have set the proper timewait 
> time-out value.  Reset
>          * the QP and let it enter the timewait state.
>          */
> -       if( al_cep_get_timewait( h_qp->obj.h_al,
> -               ((al_conn_qp_t*)h_qp)->cid, &timewait ) == 
> IB_SUCCESS )
> +       if( al_cep_get_timewait( p_csq->h_al, p_csq->cid, 
> &timewait ) == IB_SUCCESS )
>         {
> +               h_qp = CONTAINING_RECORD(
> +                       al_hdl_ref( p_csq->h_al, p_csq->h_qp, 
> AL_OBJ_TYPE_H_QP ),
> +                       ib_qp_t,
> +                       obj );
> +
>                 /* Special checks on the QP state for error 
> handling - see above. */
>                 if( !h_qp || !AL_OBJ_IS_TYPE( h_qp, 
> AL_OBJ_TYPE_H_QP ) ||
>                         ( (h_qp->obj.state != CL_INITIALIZED) &&
> @@ -192,16 +204,16 @@ __cep_timewait_qp(
>                 status = h_qp->pfn_modify_qp( h_qp, &qp_mod, NULL );
>                 if( status != IB_SUCCESS )
>                 {
> -                       AL_PRINT_EXIT( TRACE_LEVEL_ERROR, 
> AL_DBG_ERROR,
> +                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
>                                 ("pfn_modify_qp to 
> IB_QPS_ERROR returned %s\n",
>                                 ib_get_err_str( status )) );
> -                       return;
>                 }
> -
> -#ifdef CL_KERNEL
> -               /* Store the timestamp after which the QP 
> exits timewait. */
> -               h_qp->timewait = cl_get_time_stamp() + timewait;
> -#endif /* CL_KERNEL */
> +               else
> +               {
> +                       /* Store the timestamp after which 
> the QP exits timewait. */
> +                       h_qp->timewait = cl_get_time_stamp() 
> + timewait;
> +               }
> +               deref_al_obj( &h_qp->obj );
>         }
> 
>         AL_EXIT( AL_DBG_CM );
> @@ -209,22 +221,39 @@ __cep_timewait_qp(
> 
>  static ib_api_status_t
>  __ndi_qp2rts(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              nd_csq_t*                             
>                           p_csq,
>         IN              PIRP                                  
>                           p_irp
>         )
>  {
>         ib_api_status_t status;
> +       ib_qp_handle_t h_qp;
>         ib_qp_mod_t qp_mod;
> 
> -       AL_ENTER( AL_DBG_NDI );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("[ CID = %d\n", p_csq->cid) );
> +
> +       h_qp = CONTAINING_RECORD(
> +               al_hdl_ref( p_csq->h_al, p_csq->h_qp, 
> AL_OBJ_TYPE_H_QP ),
> +               ib_qp_t,
> +               obj );
> +       if( h_qp == NULL )
> +       {
> +               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> +                       ("Bad QP %I64d\n", p_csq->h_qp) );
> +               status = IB_INVALID_HANDLE;
> +               goto err;
> +       }
> +
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("QP %p state %d\n", h_qp, h_qp->state) );
> 
>         /* fill required qp attributes */
> -       status = al_cep_get_rtr_attr( qp_get_al( h_qp ),
> -               ((al_conn_qp_t*)h_qp)->cid, &qp_mod );
> +       status = al_cep_get_rtr_attr( p_csq->h_al, 
> p_csq->cid, &qp_mod );
>         if ( status != IB_SUCCESS )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("al_cep_get_rtr_attr returned %s\n", 
> ib_get_err_str( status )) );
> +                       ("al_cep_get_rtr_attr for CID %d 
> returned %s\n",
> +                       p_csq->cid, ib_get_err_str( status )) );
>                 goto exit;
>         }
> 
> @@ -234,17 +263,18 @@ __ndi_qp2rts(
>         if ( status != IB_SUCCESS )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("ndi_modify_qp to RTR returned 
> %s.\n", ib_get_err_str(status) ) );
> +                       ("ndi_modify_qp %p from %d to RTR 
> returned %s.\n",
> +                       h_qp, h_qp->state, ib_get_err_str(status) ) );
>                 goto exit;
>         }
> 
>         /* fill required qp attributes */
> -       status = al_cep_get_rts_attr( qp_get_al( h_qp ),
> -               ((al_conn_qp_t*)h_qp)->cid, &qp_mod );
> +       status = al_cep_get_rts_attr( p_csq->h_al, 
> p_csq->cid, &qp_mod );
>         if ( status != IB_SUCCESS )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("al_cep_get_rts_attr returned %s\n", 
> ib_get_err_str( status )) );
> +                       ("al_cep_get_rts_attr for CID %d 
> returned %s\n",
> +                       p_csq->cid, ib_get_err_str( status )) );
>                 goto exit;
>         }
> 
> @@ -254,10 +284,13 @@ __ndi_qp2rts(
>         if ( status != IB_SUCCESS )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("ndi_modify_qp to RTS returned 
> %s.\n", ib_get_err_str(status) ) );
> +                       ("ndi_modify_qp %p from %d to RTS 
> returned %s.\n",
> +                       h_qp, h_qp->state, ib_get_err_str(status) ) );
>         }
> 
>  exit:
> +       deref_al_obj( &h_qp->obj );
> +err:
>         AL_EXIT( AL_DBG_NDI );
>         return status;
>  }
> @@ -277,11 +310,15 @@ static NTSTATUS __ndi_insert_irp_ex(
>         )
>  {
>         NTSTATUS status;
> -       ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)pCsq;
> +       nd_csq_t *p_ndi_csq = CONTAINING_RECORD( pCsq, 
> nd_csq_t, csq );
> 
> -       AL_ENTER( AL_DBG_NDI );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = 
> %d\n", p_ndi_csq->cid) );
>         switch( (ULONG_PTR)Context )
>         {
> +       case NDI_CM_LISTEN:
> +               status = __ndi_get_req( p_ndi_csq, pIrp );
> +               break;
> +
>         case NDI_CM_CONNECTING_QPR_SENT:
>                 status = __ndi_pr_query( pIrp );
>                 break;
> @@ -290,24 +327,38 @@ static NTSTATUS __ndi_insert_irp_ex(
>                 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;
> 
> +       case NDI_CM_CONNECTED_DREQ_RCVD:
> +               if( p_ndi_csq->state == NDI_CM_LISTEN )
> +               {
> +                       AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_NDI,
> +                               ("] Invalid state (%d).\n", 
> p_ndi_csq->state) );
> +                       return STATUS_INVALID_DEVICE_REQUEST;
> +               }
> +
> +               /*
> +                * Overwrite the context so that the state change
> +                * below turns into a noop.
> +                */
> +               Context = (VOID*)(ULONG_PTR)p_ndi_csq->state;
> +               status = STATUS_PENDING;
> +               break;
> +
>         default:
>                 status = STATUS_INVALID_DEVICE_REQUEST;
>                 ASSERT( FALSE );
>         }
> 
> -       if( status == STATUS_SUCCESS )
> +       ASSERT( status == STATUS_PENDING || !NT_SUCCESS( status ) );
> +       if( NT_SUCCESS( status ) )
>         {
> +               AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, 
> ("] Queueing IRP\n") );
>                 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. */
> +               nd_csq_ref( p_ndi_csq ); /* Take IRP reference. */
>         }
>         AL_EXIT( AL_DBG_NDI );
>         return status;
> @@ -334,7 +385,7 @@ static PIRP __ndi_peek_next_irp(
>         PIRP nextIrp = NULL;
>         PLIST_ENTRY nextEntry;
>         PLIST_ENTRY listHead;
> -       ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> +       nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> @@ -380,16 +431,12 @@ static PIRP __ndi_peek_next_irp(
> 
>  static VOID __ndi_acquire_lock(
>         IN      PIO_CSQ                                       
>                           Csq,
> -       OUT     PKIRQL                                        
>                           Irql
> +       OUT     PKIRQL                                        
>                           pIrql
>         )
>  {
> -       ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> -       ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
> -       UNUSED_PARAM( Irql );
> +       nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
> 
> -       AL_ENTER( AL_DBG_NDI );
> -       cl_spinlock_acquire( &h_qp->obj.lock );
> -       AL_EXIT( AL_DBG_NDI );
> +       KeAcquireSpinLock( &p_ndi_csq->lock, pIrql );
>  }
> 
>  static VOID __ndi_release_lock(
> @@ -397,13 +444,9 @@ static VOID __ndi_release_lock(
>         IN      KIRQL                                         
>                           Irql
>         )
>  {
> -       ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq;
> -       ib_qp_handle_t h_qp = p_ndi_csq->h_qp;
> -       UNUSED_PARAM( Irql );
> +       nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
> 
> -       AL_ENTER( AL_DBG_NDI );
> -       cl_spinlock_release( &h_qp->obj.lock );
> -       AL_EXIT( AL_DBG_NDI );
> +       KeReleaseSpinLock( &p_ndi_csq->lock, Irql );
>  }
> 
>  static VOID __ndi_complete_cancelled_irp(
> @@ -411,8 +454,7 @@ static VOID __ndi_complete_cancelled_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;
> +       nd_csq_t *p_ndi_csq = (nd_csq_t*)Csq;
>         KIRQL irql;
>         ib_query_handle_t h_query;
> 
> @@ -427,14 +469,11 @@ static VOID __ndi_complete_cancelled_irp
>                  * SA callback by the CSQ lock.
>                  */
>  #pragma warning( disable:4305 )
> -               h_query = InterlockedExchangePointer( 
> &h_qp->p_irp_queue->h_query, NULL );
> +               h_query = InterlockedExchangePointer( 
> &p_ndi_csq->h_query, NULL );
>  #pragma warning( default:4305 )
>                 if( h_query != NULL )
>                         al_cancel_sa_req( &h_query->sa_req );
> 
> -               /* 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 );
> -
>                 if( p_ndi_csq->state != NDI_CM_INVALID )
>                         p_ndi_csq->state = NDI_CM_IDLE;
> 
> @@ -443,7 +482,8 @@ static VOID __ndi_complete_cancelled_irp
>                 __fallthrough;
> 
>         case UAL_NDI_NOTIFY_DREQ:
> -               __ndi_complete_irp( h_qp, p_irp, STATUS_CANCELLED );
> +       case UAL_NDI_GET_REQ_CM:
> +               __ndi_complete_irp( p_ndi_csq, p_irp, 
> STATUS_CANCELLED );
>                 break;
> 
>         case UAL_NDI_DREQ_CM:
> @@ -457,138 +497,158 @@ static VOID __ndi_complete_cancelled_irp
> 
> 
>  NTSTATUS
> -ndi_qp_init(
> -       IN                              ib_qp_handle_t        
>                   h_qp )
> +nd_csq_init(
> +       IN                              ib_al_handle_t        
>                   h_al,
> +       IN                              net32_t               
>                           cid,
> +       IN                              uint64_t              
>                           h_qp,
> +               OUT                     nd_csq_t              
>                           **pp_csq )
>  {
> -
> +       nd_csq_t *p_nd_csq;
>         NTSTATUS status;
> +       ib_api_status_t ib_status;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       if ( h_qp->type != IB_QPT_RELIABLE_CONN )
> -       {
> -               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                       ("Only RC QP type is supported \n"));
> -               status = STATUS_SUCCESS;
> -               goto exit;
> -       }
> -
> -       h_qp->p_irp_queue = 
> (ndi_qp_csq_t*)cl_zalloc(sizeof(ndi_qp_csq_t));
> -       if (!h_qp->p_irp_queue)
> +       p_nd_csq = (nd_csq_t*)cl_zalloc( sizeof(*p_nd_csq) );
> +       if( p_nd_csq == NULL )
>         {
>                 status = STATUS_NO_MEMORY;
>                 goto exit;
>         }
> 
> -       status = IoCsqInitializeEx( &h_qp->p_irp_queue->csq,
> +       KeInitializeSpinLock( &p_nd_csq->lock );
> +       InitializeListHead( &p_nd_csq->queue );
> +       p_nd_csq->h_al = h_al;
> +       p_nd_csq->h_qp = h_qp;
> +       p_nd_csq->h_query = NULL;
> +       p_nd_csq->state = NDI_CM_IDLE;
> +       p_nd_csq->cid = cid;
> +
> +       status = IoCsqInitializeEx( &p_nd_csq->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 ) )
> +       {
> +               cl_free( p_nd_csq );
>                 goto exit;
> +       }
> 
> -       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;
> +       /*
> +        * One reference for the CEP, one for the caller (so 
> that if the CEP
> +        * gets destroyed we don't blow up.)
> +        */
> +       p_nd_csq->ref_cnt = 2;
> +
> +       ib_status = kal_cep_config(
> +               h_al, cid, nd_cm_handler, p_nd_csq, nd_csq_release );
> +
> +       if( ib_status != IB_SUCCESS )
> +       {
> +               status = STATUS_UNSUCCESSFUL;
> +               cl_free( p_nd_csq );
> +               goto exit;
> +       }
> +
> +       *pp_csq = p_nd_csq;
>         status = STATUS_SUCCESS;
> 
> -AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -       ("Creating h_qp %#I64x, uhdl %#I64x \n",
> -       (uint64_t)(ULONG_PTR)h_qp, h_qp->obj.hdl ) );
> +       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> +               ("Creating CSQ %p, uhdl %#I64x \n", p_nd_csq, h_qp) );
> 
>  exit:
>         AL_EXIT( AL_DBG_NDI );
>         return status;
>  }
> 
> -#pragma warning(disable:4706)
> +
>  void
> -ndi_qp_destroy(
> -       IN              ib_qp_handle_t                        
>           h_qp )
> +ndi_cancel_cm_irps(
> +       IN                              nd_csq_t              
>                           *p_nd_csq )
>  {
> -       KIRQL irql;
>         PIRP Irp;
> 
> -       AL_ENTER( AL_DBG_NDI );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("[ CSQ %p (CID = %d)\n",
> +               p_nd_csq, p_nd_csq->cid ) );
> 
> -       if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)
> +       /* cancel pending IRPS for NDI type CQ */
> +       AL_ENTER( AL_DBG_NDI );
> +       for( Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, NULL );
> +               Irp != NULL;
> +               Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, NULL ) )
>         {
> -               AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                       ("Destroying h_qp %#I64x, uhdl 
> %#I64x, cid %d\n",
> -                       (uint64_t)(ULONG_PTR)h_qp, 
> h_qp->obj.hdl, ((al_conn_qp_t*)h_qp)->cid ) );
> +               __ndi_complete_cancelled_irp( &p_nd_csq->csq, Irp );
> +       }
> +       for( Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
> +               Irp != NULL;
> +               Irp = IoCsqRemoveNextIrp( &p_nd_csq->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ ) )
> +       {
> +               __ndi_complete_cancelled_irp( &p_nd_csq->csq, Irp );
> +       }
> 
> -               /* 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 );
> +       AL_EXIT( AL_DBG_NDI );
> +}
> 
> -               /* cancel pending IRPS for NDI type CQ */
> -               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)(ULONG_PTR)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)(ULONG_PTR)h_qp, 
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> +void
> +nd_csq_destroy(
> +       IN                              nd_csq_t              
>                           *p_nd_csq )
> +{
> +       KIRQL irql;
> 
> -                       __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)(ULONG_PTR)h_qp, 
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> -       }
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("[ CSQ %p (CID = %d)\n",
> +               p_nd_csq, p_nd_csq->cid ) );
> +
> +       /* Move the state before flushing, so that all new 
> IRPs fail to queue. */
> +       __ndi_acquire_lock( &p_nd_csq->csq, &irql );
> +       p_nd_csq->state = NDI_CM_INVALID;
> +       __ndi_release_lock( &p_nd_csq->csq, irql );
> +
> +       /* cancel pending IRPS */
> +       ndi_cancel_cm_irps( p_nd_csq );
> +
> +       cl_free( p_nd_csq );
> 
>         AL_EXIT( AL_DBG_NDI );
>  }
> -#pragma warning(default:4706)
> 
> 
>  void
> -ndi_qp_free(
> -       IN              ib_qp_handle_t                        
>           h_qp )
> +nd_csq_ref( nd_csq_t* p_csq )
>  {
> -       AL_ENTER( AL_DBG_NDI );
> +       InterlockedIncrement( &p_csq->ref_cnt );
> +}
> 
> -       if (h_qp->type == IB_QPT_RELIABLE_CONN && h_qp->p_irp_queue)
> +
> +void
> +nd_csq_release( nd_csq_t* p_csq )
> +{
> +       if( InterlockedDecrement( &p_csq->ref_cnt ) == 0 )
>         {
> -               /* free NDI context */
> -               cl_free( h_qp->p_irp_queue );
> -               h_qp->p_irp_queue = NULL;
> +               nd_csq_destroy( p_csq );
>         }
> -
> -       AL_EXIT( AL_DBG_NDI );
>  }
> 
> 
>  static inline void
> -__ndi_complete_req_irp(
> -       IN      ib_qp_handle_t                                
>                   h_qp,
> -       IN      NTSTATUS                                      
>                           code
> -       )
> +__ndi_timeout_req_irp(
> +       __in nd_csq_t* p_csq )
>  {
>         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 )
> +       Irp = IoCsqRemoveNextIrp( &p_csq->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 );
> +               __ndi_acquire_lock( &p_csq->csq, &irql );
> +               if( p_csq->state != NDI_CM_INVALID )
> +                       p_csq->state = NDI_CM_IDLE;
> +               __ndi_release_lock( &p_csq->csq, irql );
> +               __ndi_complete_irp( p_csq, Irp, STATUS_TIMEOUT );
>         }
> -       al_destroy_cep( qp_get_al( h_qp ), 
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
>         AL_EXIT( AL_DBG_NDI );
>  }
> 
> @@ -600,38 +660,41 @@ __ndi_complete_req_irp(
> 
>  static void
>  __ndi_notify_dreq(
> -       IN                              ib_qp_handle_t const  
>           h_qp )
> +       __in nd_csq_t* p_csq )
>  {
> -       IRP *p_irp = IoCsqRemoveNextIrp(
> -               &h_qp->p_irp_queue->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
> -
> -       if( p_irp )
> +       IRP *p_irp;
> +       do
>         {
> -               __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );
> -       }
> +               p_irp = IoCsqRemoveNextIrp(
> +                       &p_csq->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_NOTIFY_DREQ );
> +
> +               if( p_irp )
> +               {
> +                       __ndi_complete_irp( p_csq, p_irp, 
> STATUS_SUCCESS );
> +               }
> +
> +       } while ( p_irp );
>  }
> 
> 
>  static void
>  __ndi_proc_dreq(
> -       IN                              ib_qp_handle_t const  
>           h_qp )
> +       IN                              nd_csq_t              
>                           *p_csq)
>  {
>         IRP *p_irp;
>         KIRQL irql;
> -       ndi_cm_state_t old_state;
> 
> -       __ndi_notify_dreq( h_qp );
> +       __ndi_notify_dreq( p_csq );
> 
> -       __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> -       old_state = h_qp->p_irp_queue->state;
> -       if( old_state == NDI_CM_CONNECTED )
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
> +       if( p_csq->state == NDI_CM_CONNECTED )
>         {
> -               h_qp->p_irp_queue->state = NDI_CM_CONNECTED_DREQ_RCVD;
> +               p_csq->state = NDI_CM_CONNECTED_DREQ_RCVD;
>         }
> -       __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> +       __ndi_release_lock( &p_csq->csq, irql );
> 
>         p_irp = IoCsqRemoveNextIrp(
> -               &h_qp->p_irp_queue->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
> +               &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
>         if( p_irp != NULL )
>         {
>                 __ndi_queue_drep( p_irp );
> @@ -645,7 +708,7 @@ __ndi_proc_dreq(
>   */
>  static void
>  __ndi_proc_rej(
> -       IN                              ib_qp_handle_t const  
>           h_qp,
> +       IN                              nd_csq_t*             
>                           p_csq,
>         IN              const   mad_cm_rej_t* const           
>           p_rej )
>  {
>         KIRQL irql;
> @@ -654,73 +717,135 @@ __ndi_proc_rej(
>         AL_ENTER( AL_DBG_NDI );
> 
>         AL_PRINT(TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -               ("p_rej %p, h_qp %#I64x, uhdl %#I64x, connect 
> reject, reason=%hd\n",
> -               p_rej, (uint64_t)(ULONG_PTR)h_qp, 
> h_qp->obj.hdl, cl_ntoh16(p_rej->reason) ) );
> +               ("p_rej %p, CID=%d, uhdl %#I64x, connect 
> reject, reason=%hd\n",
> +               p_rej, p_csq->cid, p_csq->h_qp, 
> cl_ntoh16(p_rej->reason) ) );
> 
> -       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 );
> +       p_irp = IoCsqRemoveNextIrp( &p_csq->csq, NULL );
> +       __ndi_notify_dreq( p_csq );
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
>         if( p_irp != NULL )
>         {
>                 switch( cl_ioctl_ctl_code( p_irp ) )
>                 {
>                 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 );
> +                       if( p_csq->state != NDI_CM_INVALID )
> +                               p_csq->state = NDI_CM_IDLE;
> +                       if( p_rej->reason == IB_REJ_USER_DEFINED )
> +                               __ndi_complete_irp( p_csq, 
> p_irp, STATUS_CONNECTION_REFUSED );
>                         else
> -                               __ndi_complete_irp( h_qp, 
> p_irp, STATUS_CONNECTION_REFUSED );
> +                               __ndi_complete_irp( p_csq, 
> p_irp, STATUS_TIMEOUT );
> 
> -                       al_destroy_cep(
> -                               qp_get_al( h_qp ), 
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> +                       /* We leave the CEP active so that 
> the private data can be retrieved. */
>                         break;
> 
>                 case UAL_NDI_DREQ_CM:
>                         __ndi_queue_drep( p_irp );
>                         break;
> +
> +               case UAL_NDI_NOTIFY_DREQ:
> +                       __ndi_complete_irp( p_csq, p_irp, 
> STATUS_CONNECTION_ABORTED );
> +                       break;
> +
> +               default:
> +                       ASSERT( cl_ioctl_ctl_code( p_irp ) == 
> UAL_NDI_REQ_CM ||
> +                               cl_ioctl_ctl_code( p_irp ) == 
> UAL_NDI_DREQ_CM ||
> +                               cl_ioctl_ctl_code( p_irp ) == 
> UAL_NDI_NOTIFY_DREQ );
>                 }
>         }
> -       else if( h_qp->p_irp_queue->state == NDI_CM_CONNECTED )
> +       else if( p_csq->state == NDI_CM_CONNECTED || 
> p_csq->state == NDI_CM_CONNECTING_REQ_RCVD )
>         {
> -               if( h_qp->p_irp_queue->state != NDI_CM_INVALID )
> -                       h_qp->p_irp_queue->state = 
> NDI_CM_CONNECTED_DREQ_RCVD;
> +               p_csq->state = NDI_CM_CONNECTED_DREQ_RCVD;
> +       }
> +       __ndi_release_lock( &p_csq->csq, irql );
> +
> +       AL_EXIT( AL_DBG_NDI );
> +}
> +
> +
> +static void
> +__ndi_proc_req(
> +       IN                              nd_csq_t*             
>                           p_csq,
> +       IN                              net32_t               
>                           new_cid,
> +       IN                              ib_mad_element_t      
>                   *p_mad )
> +{
> +       IRP* p_irp;
> +       KIRQL irql;
> +       NTSTATUS status;
> +       nd_csq_t* p_new_csq;
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("CID 
> = %d\n", p_csq->cid));
> +
> +       status = nd_csq_init( p_csq->h_al, new_cid, 0, &p_new_csq );
> +       if( status != STATUS_SUCCESS )
> +       {
> +               // Ignore the request.
> +               kal_cep_destroy( p_csq->h_al, new_cid, 
> STATUS_NO_MORE_ENTRIES );
> +               ib_put_mad( p_mad );
> +               return;
> +       }
> +
> +       __ndi_acquire_lock( &p_new_csq->csq, &irql );
> +       p_new_csq->state = NDI_CM_CONNECTING_REQ_RCVD;
> +       __ndi_release_lock( &p_new_csq->csq, irql );
> +       nd_csq_release( p_new_csq );
> +
> +       p_irp = IoCsqRemoveNextIrp( &p_csq->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_GET_REQ_CM );
> +       if( p_irp == NULL )
> +       {
> +               p_mad->send_context1 = (VOID*)(ULONG_PTR)new_cid;
> +               __ndi_acquire_lock( &p_csq->csq, &irql );
> +               if( p_csq->p_mad_head == NULL )
> +               {
> +                       p_csq->p_mad_head = p_mad;
> +               }
> +               else
> +               {
> +                       p_csq->p_mad_tail->p_next = p_mad;
> +               }
> +               p_csq->p_mad_tail = p_mad;
> +               __ndi_release_lock( &p_csq->csq, irql );
> +       }
> +       else
> +       {
> +               *(net32_t*)cl_ioctl_out_buf( p_irp ) = new_cid;
> +               __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );
> +               ib_put_mad( p_mad );
>         }
> -       __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> 
>         AL_EXIT( AL_DBG_NDI );
> +       return;
>  }
> 
> 
>  static void
>  __ndi_proc_rep(
> -       IN                              ib_qp_handle_t const  
>           h_qp,
> -       IN                              net32_t               
>                           cid )
> +       IN                              nd_csq_t*             
>                           p_csq )
>  {
> -       ndi_qp_csq_t *p_ndi_csq = h_qp->p_irp_queue;
>         IRP* p_irp;
>         KIRQL irql;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("h_qp 
> = 0x%p\n", h_qp));
> +       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI ,("CID 
> = %d\n", p_csq->cid));
> 
> -       p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> -       __ndi_acquire_lock( &p_ndi_csq->csq, &irql );
> +       p_irp = IoCsqRemoveNextIrp( &p_csq->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
>         if( p_irp == NULL )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("Not the expected state %s\n", 
> State2String( p_ndi_csq->state )));
> -               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 );
> +                       ("Not the expected state %s\n", 
> State2String( p_csq->state )));
> +               CL_ASSERT( IsListEmpty( &p_csq->queue ) );
> +               al_cep_rej( p_csq->h_al, p_csq->cid, 
> IB_REJ_INVALID_COMM_INSTANCE, NULL, 0, NULL, 0 );
>         }
>         else
>         {
> -               p_ndi_csq->state = NDI_CM_CONNECTING_REP_RCVD;
> +               p_csq->state = NDI_CM_CONNECTING_REP_RCVD;
> 
> -               __ndi_complete_irp( h_qp, p_irp, STATUS_SUCCESS );
> +               __ndi_complete_irp( p_csq, p_irp, STATUS_SUCCESS );
>         }
> -       __ndi_release_lock( &p_ndi_csq->csq, irql );
> +       __ndi_release_lock( &p_csq->csq, irql );
> 
>         AL_EXIT( AL_DBG_NDI );
>         return;
> @@ -732,7 +857,8 @@ __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];
> +       nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];
> +       ib_qp_handle_t h_qp;
>         ib_qp_mod_t qp_mod;
>         ib_api_status_t status;
>         uint64_t timewait_us;
> @@ -746,11 +872,8 @@ __ndi_do_drep(
>         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 = al_cep_get_timewait( qp_get_al( h_qp ),
> -               ((al_conn_qp_t*)h_qp)->cid, &timewait_us );
> 
> +       status = al_cep_get_timewait( p_csq->h_al, 
> p_csq->cid, &timewait_us );
>         if (status != IB_SUCCESS)
>         {
>                 nt_status = STATUS_CONNECTION_INVALID;
> @@ -758,31 +881,44 @@ __ndi_do_drep(
>         }
> 
>         /* Store the timestamp after which the QP exits timewait. */
> -       h_qp->timewait = cl_get_time_stamp() + timewait_us;
> +       h_qp = CONTAINING_RECORD(
> +               al_hdl_ref( p_csq->h_al, p_csq->h_qp, 
> AL_OBJ_TYPE_H_QP ),
> +               ib_qp_t,
> +               obj );
> +       if( h_qp != NULL )
> +       {
> +               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 );
> +       /* Send the DREP. */
> +       al_cep_drep( p_csq->h_al, p_csq->cid, NULL, 0 );
> 
>         /* 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 )
> +       if( h_qp != NULL )
>         {
> -               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("ndi_modify_qp to ERROR returned 
> %s.\n", ib_get_err_str(status) ) );
> +               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,
> +                               ("ndi_modify_qp to ERROR 
> returned %s.\n", ib_get_err_str(status) ) );
> +               }
> +               deref_al_obj( &h_qp->obj );
>         }
> 
>         nt_status = ib_to_ntstatus( status );
> 
>  exit:
> -       __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_acquire_lock( &p_csq->csq, &irql );
> +       if( p_csq->state != NDI_CM_INVALID )
> +               p_csq->state = NDI_CM_IDLE;
> +       __ndi_release_lock( &p_csq->csq, irql );
> 
> -       __ndi_complete_irp( h_qp, p_irp, nt_status );
> +       __ndi_complete_irp( p_csq, p_irp, nt_status );
> +       nd_csq_release( p_csq ); /* Release work item reference. */
>         AL_EXIT( AL_DBG_NDI );
>  }
> 
> @@ -799,16 +935,17 @@ __ndi_queue_drep(
> 
>  static void
>  __ndi_proc_drep(
> -       IN                              ib_qp_handle_t const  
>           h_qp )
> +       IN                              nd_csq_t*             
>                           p_csq )
>  {
>         IRP* p_irp;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
>         p_irp = IoCsqRemoveNextIrp(
> -               &h_qp->p_irp_queue->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
> +               &p_csq->csq, (VOID*)(ULONG_PTR)UAL_NDI_DREQ_CM );
>         if( p_irp != NULL )
>         {
> +               CL_ASSERT( 
> p_irp->Tail.Overlay.DriverContext[0] == p_csq );
>                 __ndi_queue_drep( p_irp );
>         }
> 
> @@ -816,8 +953,8 @@ __ndi_proc_drep(
>  }
> 
> 
> -static void
> -__ndi_cm_handler(
> +void
> +nd_cm_handler(
>         IN              const   ib_al_handle_t                
>           h_al,
>         IN              const   net32_t                       
>                   cid )
>  {
> @@ -829,8 +966,11 @@ __ndi_cm_handler(
> 
>         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 h_qp = (ib_qp_handle_t)context;
> +               ib_mad_t* p_mad = ib_get_mad_buf( p_mad_el );
> +               nd_csq_t* p_csq = (nd_csq_t*)context;
> +
> +               CL_ASSERT( p_csq != NULL );
> +               CL_ASSERT( p_csq->cid == cid );
> 
>                 if( p_mad_el->status != IB_SUCCESS )
>                 {
> @@ -838,28 +978,28 @@ __ndi_cm_handler(
>                         {
>                         case CM_REQ_ATTR_ID:
>                                 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_req_irp( h_qp, 
> STATUS_TIMEOUT );
> +                                       ("REQ timed out for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_timeout_req_irp( p_csq );
>                                 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 ) );
> +                                       ("REP timed out for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
>                                 break;
> 
>                         case CM_DREQ_ATTR_ID:
>                                 AL_PRINT( 
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                                       ("DREQ timeouted for 
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> -                                       cid, h_al, h_qp, new_cid ) );
> -                               __ndi_proc_drep( h_qp );
> +                                       ("DREQ timed out for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_proc_drep( p_csq );
>                                 break;
> 
>                         default:
>                                 AL_PRINT( TRACE_LEVEL_ERROR, 
> AL_DBG_ERROR,
>                                         ("Unhandled failed 
> MAD attr ID %d for CEP with cid %d, h_al %p, context %p, 
> new_cid %d .\n",
> -                                       p_mad->attr_id, cid, 
> h_al, h_qp, new_cid ) );
> +                                       p_mad->attr_id, cid, 
> h_al, p_csq, new_cid ) );
>                                 break;
>                         }
>                 }
> @@ -867,50 +1007,51 @@ __ndi_cm_handler(
>                 {
>                         switch( p_mad->attr_id )
>                         {
> +                       case CM_REQ_ATTR_ID:
> +                               AL_PRINT( 
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> +                                       ("REQ received for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_proc_req( p_csq, 
> new_cid, p_mad_el );
> +                               continue;
> +
>                         case CM_REP_ATTR_ID:
>                                 AL_PRINT( 
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                                       ("REP received for 
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> -                                       cid, h_al, h_qp, new_cid ) );
> -                               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_qp, cid );
> +                                       ("REP received for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_proc_rep( p_csq );
>                                 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_qp, 
> (mad_cm_rej_t*)p_mad );
> +                                       ("REJ received for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_proc_rej( p_csq, 
> (mad_cm_rej_t*)p_mad );
>                                 break;
> 
>                         case CM_DREQ_ATTR_ID:
>                                 AL_PRINT( 
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                                       ("DREQ received for 
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> -                                       cid, h_al, h_qp, new_cid ) );
> -                               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_qp );
> +                                       ("DREQ received for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_proc_dreq( p_csq );
>                                 break;
> 
>                         case CM_DREP_ATTR_ID:
>                                 AL_PRINT( 
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                                       ("DREP received for 
> CEP with cid %d, h_al %p, context %p, new_cid %d .\n",
> -                                       cid, h_al, h_qp, new_cid ) );
> -                               __ndi_proc_drep( h_qp );
> +                                       ("DREP received for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
> +                               __ndi_proc_drep( p_csq );
>                                 break;
> 
>                         case CM_RTU_ATTR_ID:
>                                 AL_PRINT( 
> TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -                                       ("RTU received for 
> CEP with cid %d, h_al %p, context %p, new_cid %d.\n",
> -                                       cid, h_al, h_qp, new_cid ) );
> +                                       ("RTU received for 
> CEP with cid %d, h_al %p, context %p.\n",
> +                                       cid, h_al, p_csq ) );
>                                 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",
> -                                       p_mad->attr_id, cid, 
> h_al, h_qp, new_cid ) );
> +                                       p_mad->attr_id, cid, 
> h_al, p_csq, new_cid ) );
>                         }
>                 }
> 
> @@ -922,24 +1063,26 @@ __ndi_cm_handler(
> 
>  static void
>  __ndi_fill_cm_req(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              net32_t                               
>                           qpn,
>         IN              ual_ndi_req_cm_ioctl_in_t             
>           *p_req,
>         IN              ib_path_rec_t                         
>                   *p_path_rec,
> -               OUT     ib_cm_req_t                           
>                           *p_cm_req)
> +               OUT     iba_cm_req                            
>                           *p_cm_req)
>  {
>         AL_ENTER( AL_DBG_NDI );
> 
> -       memset( p_cm_req, 0, sizeof(ib_cm_req_t) );
> -
> -       p_cm_req->svc_id = IB_REQ_CM_RDMA_SID_PREFIX | 
> (p_req->prot << 16) | p_req->dst_port;
> -       p_cm_req->max_cm_retries = g_max_cm_retries;
> -       p_cm_req->p_primary_path = p_path_rec;
> +       memset( p_cm_req, 0, sizeof(*p_cm_req) );
> 
> -       p_cm_req->p_req_pdata = (uint8_t *)&p_req->pdata;
> -       p_cm_req->req_length = sizeof(p_req->pdata);
> +       p_cm_req->service_id = IB_REQ_CM_RDMA_SID_PREFIX | 
> (p_req->prot << 16) | p_req->dst_port;
> +       p_cm_req->p_primary_path = p_path_rec;
> 
> +       p_cm_req->qpn = qpn;
>         p_cm_req->qp_type = IB_QPT_RELIABLE_CONN;
> -       p_cm_req->h_qp = h_qp;
> +       p_cm_req->starting_psn = qpn;
> +
> +       p_cm_req->p_pdata = (uint8_t *)&p_req->pdata;
> +       p_cm_req->pdata_len = sizeof(p_req->pdata);
> +
> +       p_cm_req->max_cm_retries = g_max_cm_retries;
>         p_cm_req->resp_res = p_req->resp_res;
>         p_cm_req->init_depth = p_req->init_depth;
> 
> @@ -959,10 +1102,8 @@ __ndi_fill_cm_req(
>         else if( p_cm_req->local_resp_timeout < CM_MIN_LOCAL_TIMEOUT )
>                 p_cm_req->local_resp_timeout = CM_MIN_LOCAL_TIMEOUT;
> 
> -       p_cm_req->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;
>         p_cm_req->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY;
>         p_cm_req->retry_cnt = g_qp_retries;
> -       p_cm_req->p_alt_path = NULL;
> 
>         AL_EXIT( AL_DBG_NDI );
>  }
> @@ -974,58 +1115,47 @@ __ndi_send_req(
>         )
>  {
>         ib_api_status_t status;
> -       ib_qp_handle_t h_qp = 
> (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
> +       nd_csq_t* p_csq = 
> (nd_csq_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;
> -       ib_qp_mod_t qp_mod;
> -       al_conn_qp_t *p_qp;
> +       ib_qp_handle_t h_qp;
> +       iba_cm_req cm_req;
> 
> -       AL_ENTER( AL_DBG_NDI );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("[ CID = %d, h_al %p, context %p\n",
> +               p_req->cid, p_csq->h_al, p_csq) );
> 
>         p_irp->Tail.Overlay.DriverContext[1] = NULL;
> 
> -       if( h_qp->p_irp_queue->state != NDI_CM_CONNECTING_QPR_SENT &&
> -               h_qp->p_irp_queue->state != NDI_CM_IDLE )
> +       if( p_csq->state != NDI_CM_CONNECTING_QPR_SENT &&
> +               p_csq->state != NDI_CM_IDLE )
>         {
>                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("Unexpected state: %d\n", 
> h_qp->p_irp_queue->state) );
> +                       ("Unexpected state: %d\n", p_csq->state) );
>                 return STATUS_CONNECTION_ACTIVE;
>         }
> 
> -       /* Get a CEP and bind it to the QP. */
> -       p_qp = (al_conn_qp_t*)h_qp;
> -       cl_spinlock_acquire( &h_qp->obj.lock );
> -       if( h_qp->obj.state != CL_DESTROYING && p_qp->cid == 
> AL_INVALID_CID )
> -       {
> -               status = al_create_cep( qp_get_al( h_qp ), 
> __ndi_cm_handler,
> -                                                             
>   &h_qp->obj, deref_al_obj, &p_qp->cid );
> -       }
> -       else
> -       {
> -               status = IB_RESOURCE_BUSY;
> -       }
> -       cl_spinlock_release( &h_qp->obj.lock );
> -       if( status != IB_SUCCESS )
> +       h_qp = CONTAINING_RECORD(
> +               al_hdl_ref( p_csq->h_al, p_req->h_qp, 
> AL_OBJ_TYPE_H_QP ),
> +               ib_qp_t,
> +               obj );
> +       if( !h_qp )
>         {
> -               h_qp->p_irp_queue->state = NDI_CM_IDLE;
> +               /* The QP was valid when the IOCTL first came in... */
>                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("al_create_cep returned %s.\n", 
> ib_get_err_str( status )) );
> -               return ib_to_ntstatus( status );
> +                       ("Invalid QP: %I64d\n", p_req->h_qp) );
> +               return STATUS_CONNECTION_ABORTED;
>         }
> -       AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
> -               ("Created Active CEP with cid %d, h_al %p, 
> context %p\n",
> -               p_qp->cid, qp_get_al( h_qp ), h_qp ) );
> -
> -       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 );
> +       __ndi_fill_cm_req( h_qp->num, p_req, p_path_rec, &cm_req );
> +       deref_al_obj( &h_qp->obj );
> 
>         /* prepare CEP for connection */
> -       status = al_cep_pre_req( qp_get_al( h_qp ), 
> p_qp->cid, &cm_req, &qp_mod );
> +       status = kal_cep_pre_req(
> +               p_csq->h_al, p_csq->cid, &cm_req, 
> QP_ATTRIB_RNR_NAK_TIMEOUT, NULL );
>         if( status != STATUS_SUCCESS )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> @@ -1034,7 +1164,7 @@ __ndi_send_req(
>         }
> 
>         /* send CM REQ */
> -       status = al_cep_send_req( qp_get_al( h_qp ), p_qp->cid );
> +       status = al_cep_send_req( p_csq->h_al, p_csq->cid );
>         if( status != IB_SUCCESS )
>         {
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> @@ -1044,11 +1174,9 @@ __ndi_send_req(
> 
>         /* SUCCESS ! */
>         AL_EXIT( AL_DBG_NDI );
> -       return STATUS_SUCCESS;
> +       return STATUS_PENDING;
> 
>  error:
> -       al_destroy_cep( qp_get_al( h_qp ), &p_qp->cid, TRUE );
> -
>         switch( status )
>         {
>         case IB_INVALID_HANDLE:
> @@ -1063,7 +1191,7 @@ error:
>                 nt_status = ib_to_ntstatus( status );
>         }
> 
> -       h_qp->p_irp_queue->state = NDI_CM_IDLE;
> +       p_csq->state = NDI_CM_IDLE;
>         AL_EXIT( AL_DBG_NDI );
>         return nt_status;
>  }
> @@ -1076,7 +1204,7 @@ __ndi_pr_query_cb(
>         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;
> +       nd_csq_t* p_csq = (nd_csq_t*)p_query_rec->query_context;
>         NTSTATUS status;
>         KIRQL irql;
> 
> @@ -1086,22 +1214,22 @@ __ndi_pr_query_cb(
>                 ("status is %d, count is %d, context %p\n", 
> p_query_rec->status,
>                 p_query_rec->result_cnt, 
> p_query_rec->query_context) );
> 
> -       p_irp = IoCsqRemoveNextIrp( &h_qp->p_irp_queue->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
> +       p_irp = IoCsqRemoveNextIrp( &p_csq->csq, 
> (VOID*)(ULONG_PTR)UAL_NDI_REQ_CM );
>         if( p_irp == NULL )
>         {
>                 goto exit;
>         }
> 
>  #pragma warning( disable:4305 )
> -       InterlockedExchangePointer( 
> &h_qp->p_irp_queue->h_query, NULL );
> +       InterlockedExchangePointer( &p_csq->h_query, NULL );
>  #pragma warning( default:4305 )
> 
>         if( p_query_rec->status != IB_SUCCESS || 
> p_query_rec->result_cnt == 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 );
> +               __ndi_acquire_lock( &p_csq->csq, &irql );
> +               if( p_csq->state != NDI_CM_INVALID )
> +                       p_csq->state = NDI_CM_IDLE;
> +               __ndi_release_lock( &p_csq->csq, irql );
>                 switch( p_query_rec->status )
>                 {
>                 case IB_TIMEOUT:
> @@ -1129,7 +1257,7 @@ __ndi_pr_query_cb(
>                         status = STATUS_HOST_UNREACHABLE;
>                         break;
>                 }
> -               __ndi_complete_irp( h_qp, p_irp, status );
> +               __ndi_complete_irp( p_csq, p_irp, status );
>                 goto exit;
>         }
> 
> @@ -1148,15 +1276,15 @@ __ndi_pr_query_cb(
>         p_irp->Tail.Overlay.DriverContext[1] = p_path_rec;
> 
>         status = IoCsqInsertIrpEx(
> -               &h_qp->p_irp_queue->csq,
> +               &p_csq->csq,
>                 p_irp,
>                 NULL,
>                 (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT
>                 );
> -       if( status != STATUS_SUCCESS )
> +       if( !NT_SUCCESS( status ) )
>         {
>                 p_irp->Tail.Overlay.DriverContext[1] = NULL;
> -               __ndi_complete_irp( h_qp, p_irp, status );
> +               __ndi_complete_irp( p_csq, p_irp, status );
>         }
>         else
>         {
> @@ -1164,14 +1292,14 @@ __ndi_pr_query_cb(
>                  * Release the previous reference because 
> IoCsqInsertIrpEx
>                  * took a new one.
>                  */
> -               deref_al_obj( &h_qp->obj ); /* Release IRP 
> reference. */
> +               nd_csq_release( p_csq ); /* 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 */
> +       nd_csq_release( p_csq );        /* release path query 
> reference */
>         AL_EXIT( AL_DBG_NDI );
>  }
> 
> @@ -1190,16 +1318,16 @@ __ndi_pr_query(
>         ib_api_status_t status;
>         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];
> +       nd_csq_t* p_csq = 
> (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];
>      ib_gid_pair_t gids;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       if ( h_qp->p_irp_queue->state != NDI_CM_IDLE )
> +       if ( p_csq->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)(ULONG_PTR)h_qp, 
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> +                       ("STATUS_CONNECTION_ACTIVE: CID=%d, 
> uhdl %#I64x, ref_cnt %d\n",
> +                       p_csq->cid, p_csq->h_qp, p_csq->ref_cnt ) );
>                 return STATUS_CONNECTION_ACTIVE;
>         }
> 
> @@ -1212,41 +1340,50 @@ __ndi_pr_query(
>         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 = h_qp;
> +       query_req.query_context = p_csq;
>         query_req.pfn_query_cb = __ndi_pr_query_cb;
> 
>         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
>                 ("Query for path from %I64x to %I64x\n",
>                 p_req->guid, ib_gid_get_guid( &p_req->path.dgid )) );
> 
> -       ref_al_obj( &h_qp->obj );               /* take path 
> query reference */
> -       status = ib_query( qp_get_al( h_qp ), &query_req, 
> &h_qp->p_irp_queue->h_query );
> +       nd_csq_ref( p_csq );            /* take path query 
> reference */
> +       status = ib_query( p_csq->h_al, &query_req, &p_csq->h_query );
>         if( status != IB_SUCCESS )
>         {
> -               h_qp->p_irp_queue->state = NDI_CM_IDLE;
> +               p_csq->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 */
> +               nd_csq_release( p_csq );        /* release 
> path query reference */
>                 return ib_to_ntstatus( status );
>         }
> 
>         AL_EXIT( AL_DBG_NDI );
> -       return STATUS_SUCCESS;
> +       return STATUS_PENDING;
>  }
> 
> 
>  NTSTATUS
>  ndi_req_cm(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              ib_al_handle_t                        
>                   h_al,
>         IN              IRP                                   
>                                   *p_irp
>         )
>  {
>         NTSTATUS status;
> +       nd_csq_t* p_csq;
>         ual_ndi_req_cm_ioctl_in_t *p_req =
>                 (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       p_irp->Tail.Overlay.DriverContext[0] = (ib_qp_t*)h_qp;
> +       p_csq = kal_cep_get_context( h_al, p_req->cid, 
> nd_cm_handler, nd_csq_ref );
> +       if( p_csq == NULL )
> +       {
> +               status = nd_csq_init( h_al, p_req->cid, 
> p_req->h_qp, &p_csq );
> +               if( status != STATUS_SUCCESS )
> +                       goto err;
> +       }
> +
> +       p_irp->Tail.Overlay.DriverContext[0] = p_csq;
> 
>      if( p_req->path.dlid != 0 )
>      {
> @@ -1260,7 +1397,7 @@ ndi_req_cm(
> 
>             p_irp->Tail.Overlay.DriverContext[1] = &p_req->path;
>             status = IoCsqInsertIrpEx(
> -                   &h_qp->p_irp_queue->csq,
> +                   &p_csq->csq,
>                     p_irp,
>                     NULL,
>                     (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_REQ_SENT
> @@ -1269,15 +1406,15 @@ ndi_req_cm(
>      else
>      {
>             status = IoCsqInsertIrpEx(
> -                   &h_qp->p_irp_queue->csq,
> +                   &p_csq->csq,
>                     p_irp,
>                     NULL,
>                     (VOID*)(ULONG_PTR)NDI_CM_CONNECTING_QPR_SENT
>                     );
>      }
> -       if( status == STATUS_SUCCESS )
> -               status = STATUS_PENDING;
> 
> +       nd_csq_release( p_csq );
> +err:
>         AL_EXIT( AL_DBG_NDI );
>         return status;
>  }
> @@ -1295,7 +1432,7 @@ __ndi_do_rtu(
>         IN                              PIRP                  
>                           p_irp )
>  {
>         ib_api_status_t status;
> -       ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
> +       nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];
>         KIRQL irql;
>         NTSTATUS nt_status;
> 
> @@ -1308,67 +1445,67 @@ __ndi_do_rtu(
>         {
>                 IoFreeWorkItem( 
> p_irp->Tail.Overlay.DriverContext[1] );
>                 p_irp->Tail.Overlay.DriverContext[1] = NULL;
> -               deref_al_obj( &h_qp->obj ); /* Release work 
> item reference. */
> +               nd_csq_release( p_csq ); /* 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 )
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
> +       if( p_csq->state != NDI_CM_CONNECTING_REP_RCVD )
>         {
> +               __ndi_release_lock( &p_csq->csq, irql );
>                 nt_status = STATUS_CONNECTION_ABORTED;
>                 goto exit;
>         }
> -       __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> +       __ndi_release_lock( &p_csq->csq, irql );
> 
>         /* change the QP state to RTS */
> -       status = __ndi_qp2rts( h_qp, p_irp );
> -
> +       status = __ndi_qp2rts( p_csq, p_irp );
>         if ( status != IB_SUCCESS )
>         {
>                 goto err;
>         }
> 
>         /* send RTU */
> -       status = al_cep_rtu( qp_get_al( h_qp ), 
> ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );
> +       status = al_cep_rtu( p_csq->h_al, p_csq->cid, NULL, 0 );
>         if( status != IB_SUCCESS )
>         {
>  err:
> -               /* Reject and abort the connection. */
> -               al_cep_rej(
> -                       qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid,
> -                       IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> -
> -               __cep_timewait_qp( h_qp );
> +               /*
> +                * Reject the connection.  Note that we don't 
> free the CEP since the
> +                * usermode INDConnector object references 
> it, and the CEP will be
> +                * freed when that object is freed.
> +                */
> +               al_cep_rej( p_csq->h_al, p_csq->cid, 
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> 
> -               al_destroy_cep( qp_get_al( h_qp ), 
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> +               __cep_timewait_qp( p_csq );
> 
>                 AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
>                         ("al_cep_rtu returned %s.\n", 
> ib_get_err_str( status )) );
> 
> -               __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_acquire_lock( &p_csq->csq, &irql );
> +               if( p_csq->state != NDI_CM_INVALID )
> +                       p_csq->state = NDI_CM_IDLE;
> +               __ndi_release_lock( &p_csq->csq, irql );
> 
>                 nt_status = STATUS_CONNECTION_ABORTED;
>                 goto exit;
>         }
> 
> -       __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 );
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
> +       if( p_csq->state == NDI_CM_CONNECTING_REP_RCVD )
> +               p_csq->state = NDI_CM_CONNECTED;
> +       __ndi_release_lock( &p_csq->csq, irql );
> 
>         nt_status = STATUS_SUCCESS;
> 
>  exit:
> -       __ndi_complete_irp( h_qp, p_irp, nt_status );
> +       __ndi_complete_irp( p_csq, p_irp, nt_status );
>         AL_EXIT( AL_DBG_NDI );
>  }
> 
> 
>  cl_status_t
>  ndi_rtu_cm(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              nd_csq_t                              
>                           *p_csq,
>         IN              PIRP                                  
>                           p_irp
>         )
>  {
> @@ -1376,16 +1513,16 @@ ndi_rtu_cm(
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> +       p_irp->Tail.Overlay.DriverContext[0] = p_csq;
> +       nd_csq_ref( p_csq ); /* Take IRP reference. */
>         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. */
> 
>         IoMarkIrpPending( p_irp );
>         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 ); /* Take work item 
> reference. */
> +               nd_csq_ref( p_csq ); /* Take work item reference. */
>                 IoQueueWorkItem( p_irp->Tail.Overlay.DriverContext[1],
>                         __ndi_do_rtu, DelayedWorkQueue, p_irp );
>         }
> @@ -1410,73 +1547,75 @@ __ndi_do_rep(
>         IN                              DEVICE_OBJECT*        
>                   p_dev_obj,
>         IN              PIRP                                  
>                           p_irp )
>  {
> -       ib_qp_handle_t h_qp = p_irp->Tail.Overlay.DriverContext[0];
> +       nd_csq_t* p_csq = p_irp->Tail.Overlay.DriverContext[0];
>         ib_api_status_t status;
> -       ual_ndi_rep_cm_ioctl_in_t *p_rep;
>         KIRQL irql;
>         NTSTATUS nt_status;
> 
>         UNUSED_PARAM(p_dev_obj);
> 
> -       AL_ENTER( AL_DBG_NDI );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = 
> %d\n", p_csq->cid) );
> 
>         /* free the work item if any */
>         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 );
> +       status = __ndi_qp2rts( p_csq, p_irp );
>         if ( status != IB_SUCCESS )
>         {
>                 goto err;
>         }
> 
>         /* send REP */
> -       status = al_cep_send_rep ( qp_get_al( h_qp ), p_rep->cid );
> +       status = al_cep_send_rep ( p_csq->h_al, p_csq->cid );
>         if( status != IB_SUCCESS )
>         {
>                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
>                         ("al_cep_send_rep returned %s\n", 
> ib_get_err_str(status)) );
>  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 );
> +               /*
> +                * Reject the connection.  Note that we don't 
> free the CEP since the
> +                * usermode INDConnector object references 
> it, and the CEP will be
> +                * freed when that object is freed.
> +                */
> +               al_cep_rej( p_csq->h_al, p_csq->cid, 
> IB_REJ_INSUF_QP, NULL, 0, NULL, 0 );
> 
>                 /* transit QP to error state */
> -               __cep_timewait_qp( h_qp );
> -
> -               al_destroy_cep( qp_get_al( h_qp ), 
> &((al_conn_qp_t*)h_qp)->cid, TRUE );
> +               __cep_timewait_qp( p_csq );
> 
>                 AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
>                         ("al_cep_rtu returned %s.\n", 
> ib_get_err_str( status )) );
> -               __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)
> +               __ndi_acquire_lock( &p_csq->csq, &irql );
> +               if( p_csq->state != NDI_CM_INVALID )
> +                       p_csq->state = NDI_CM_IDLE;
> +               __ndi_release_lock( &p_csq->csq, irql );
> +               if (status == IB_INVALID_STATE )
>                         nt_status = STATUS_CONNECTION_ABORTED;
> +               /* The HCA driver will return 
> IB_INVALID_PARAMETER if the QP is in the wrong state. */
> +               else if( status == IB_INVALID_HANDLE || 
> status == IB_INVALID_PARAMETER )
> +                       nt_status = STATUS_CANCELLED;
>                 else
> -                       nt_status =STATUS_INSUFFICIENT_RESOURCES;
> +                       nt_status = STATUS_INSUFFICIENT_RESOURCES;
>                 goto exit;
>         }
> 
> -       __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 );
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
> +       if( p_csq->state == NDI_CM_CONNECTING_REP_SENT )
> +               p_csq->state = NDI_CM_CONNECTED;
> +       __ndi_release_lock( &p_csq->csq, irql );
>         nt_status = STATUS_SUCCESS;
> 
>  exit:
> -       __ndi_complete_irp( h_qp, p_irp, nt_status );
> +       __ndi_complete_irp( p_csq, p_irp, nt_status );
> +       nd_csq_release( p_csq ); /* Release work item reference. */
>         AL_EXIT( AL_DBG_NDI );
>  }
> 
>  static void
>  __ndi_fill_cm_rep(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              net32_t                               
>                           qpn,
>         IN              ual_ndi_rep_cm_ioctl_in_t             
>           *p_rep,
>                 OUT     iba_cm_rep                            
>                           *p_cm_rep)
>  {
> @@ -1487,7 +1626,7 @@ __ndi_fill_cm_rep(
>         p_cm_rep->p_pdata = p_rep->pdata;
>         p_cm_rep->pdata_len = sizeof(p_rep->pdata);
> 
> -       p_cm_rep->qpn = h_qp->num;
> +       p_cm_rep->qpn = qpn;
> 
>         p_cm_rep->init_depth = p_rep->init_depth;
>         p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;
> @@ -1500,20 +1639,29 @@ __ndi_fill_cm_rep(
> 
>  NTSTATUS
>  __ndi_send_rep(
> -       IN              ib_qp_handle_t                        
>                   h_qp,
> +       IN              nd_csq_t                              
>                           *p_csq,
>         IN              PIRP                                  
>                           p_irp )
>  {
>         IO_STACK_LOCATION       *p_io_stack;
> +       ib_qp_handle_t h_qp;
>         iba_cm_rep cm_rep;
> -       ib_qp_mod_t qp_mod;
>         ib_api_status_t 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 );
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("[ CID = %d\n", p_csq->cid) );
> 
> -       if( h_qp->p_irp_queue->state != NDI_CM_IDLE )
> +       switch( p_csq->state )
>         {
> +       case NDI_CM_CONNECTING_REQ_RCVD:
> +               break;
> +
> +       case NDI_CM_CONNECTED_DREQ_RCVD:
> +               AL_EXIT( AL_DBG_NDI );
> +               return STATUS_CONNECTION_ABORTED;
> +
> +       default:
>                 AL_EXIT( AL_DBG_NDI );
>                 return STATUS_CONNECTION_ACTIVE;
>         }
> @@ -1525,26 +1673,36 @@ __ndi_send_rep(
>                 AL_EXIT( AL_DBG_NDI );
>                 return STATUS_NO_MEMORY;
>         }
> -       ref_al_obj( &h_qp->obj ); /* Take work item reference. */
> +       nd_csq_ref( p_csq ); /* Take work item reference. */
> 
> -       /* Format ib_cm_req_t structure */
> -       __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );
> +       h_qp = CONTAINING_RECORD(
> +               al_hdl_ref( p_csq->h_al, p_csq->h_qp, 
> AL_OBJ_TYPE_H_QP ),
> +               ib_qp_t,
> +               obj );
> +       if( !h_qp )
> +       {
> +               /* The QP was valid when the IOCTL first came in... */
> +               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> +                       ("Invalid QP: %I64d\n", p_rep->h_qp) );
> +               status = IB_INVALID_HANDLE;
> +               goto err;
> +       }
> 
> -       ref_al_obj( &h_qp->obj ); /* Take CEP reference. */
> +       /* Format ib_cm_req_t structure */
> +       __ndi_fill_cm_rep( h_qp->num, p_rep, &cm_rep );
> +       deref_al_obj( &h_qp->obj );
> 
>         /* prepare Passive CEP for connection */
> -       status = kal_cep_config_pre_rep_copy_cid(
> -               qp_get_al( h_qp ), p_rep->cid, 
> __ndi_cm_handler, &h_qp->obj, deref_al_obj,
> -               &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT, 
> &((al_conn_qp_t*)h_qp)->cid, &qp_mod);
> +       status = kal_cep_pre_rep(
> +               p_csq->h_al, p_csq->cid, &cm_rep, 
> QP_ATTRIB_RNR_NAK_TIMEOUT, NULL );
>         if( status != IB_SUCCESS )
>         {
> +               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> +                       ("kal_cep_pre_rep returned %s.\n", 
> ib_get_err_str( status )) );
> +err:
>                 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 );
> -               deref_al_obj( &h_qp->obj ); /* Release CEP 
> reference. */
> -               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("kal_cep_config_pre_rep_copy_cid 
> returned %s.\n", ib_get_err_str( status )) );
> +               nd_csq_release( p_csq ); /* Release work item 
> reference. */
>                 switch (status)
>                 {
>                         case IB_INVALID_HANDLE:
> @@ -1560,7 +1718,7 @@ __ndi_send_rep(
> 
>         AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,
>                 ("Prepared Passive CEP with cid %d, h_al %p, 
> context %p\n",
> -               p_rep->cid, qp_get_al( h_qp ), h_qp ) );
> +               p_csq->cid, p_csq->h_al, h_qp ) );
> 
>         /*
>          * transfer work to a worker thread so that QP 
> transitions can be done
> @@ -1570,39 +1728,52 @@ __ndi_send_rep(
>                 __ndi_do_rep, DelayedWorkQueue, p_irp );
> 
>         AL_EXIT( AL_DBG_NDI );
> -       return STATUS_SUCCESS;
> +       return STATUS_PENDING;
>  }
> 
> 
>  NTSTATUS
>  ndi_rep_cm(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              ib_al_handle_t                        
>                   h_al,
>         IN              PIRP                                  
>                           p_irp
>         )
>  {
>         NTSTATUS status;
> +       nd_csq_t* p_csq;
> +       ual_ndi_rep_cm_ioctl_in_t *p_rep =
> +               (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( p_irp );
>         KIRQL irql;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> +       p_csq = kal_cep_get_context( h_al, p_rep->cid, 
> nd_cm_handler, nd_csq_ref );
> +       if( p_csq == NULL )
> +       {
> +               status = STATUS_CONNECTION_ABORTED;
> +               goto err;
> +       }
> 
> -       __ndi_acquire_lock( &h_qp->p_irp_queue->csq, &irql );
> -       status = __ndi_send_rep( h_qp, p_irp );
> -       if( status == STATUS_SUCCESS )
> +       p_csq->h_qp = p_rep->h_qp;
> +
> +       p_irp->Tail.Overlay.DriverContext[0] = p_csq;
> +
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
> +       status = __ndi_send_rep( p_csq, p_irp );
> +       if( status == STATUS_PENDING )
>         {
>                 /*
>                  * 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;
> +               nd_csq_ref( p_csq ); /* Take IRP reference. */
> +               p_csq->state = NDI_CM_CONNECTING_REP_SENT;
>                 IoMarkIrpPending( p_irp );
> -               status = STATUS_PENDING;
>         }
> -       __ndi_release_lock( &h_qp->p_irp_queue->csq, irql );
> +       __ndi_release_lock( &p_csq->csq, irql );
> 
> -       AL_EXIT( AL_DBG_NDI );
> +       nd_csq_release( p_csq );
> +err:
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("] 
> returning %08x\n", status) );
>         return status;
>  }
> 
> @@ -1620,19 +1791,19 @@ __ndi_send_dreq(
>         IN              IRP*                                  
>                           p_irp
>         )
>  {
> -       ib_qp_handle_t h_qp = 
> (ib_qp_handle_t)p_irp->Tail.Overlay.DriverContext[0];
> +       nd_csq_t *p_csq = 
> (nd_csq_t*)p_irp->Tail.Overlay.DriverContext[0];
>         IO_STACK_LOCATION       *p_io_stack;
>         ib_api_status_t status;
>         NTSTATUS nt_status;
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       if ( h_qp->p_irp_queue->state != NDI_CM_CONNECTED &&
> -               h_qp->p_irp_queue->state != 
> NDI_CM_CONNECTED_DREQ_RCVD )
> +       if ( p_csq->state != NDI_CM_CONNECTED &&
> +               p_csq->state != NDI_CM_CONNECTED_DREQ_RCVD )
>         {
>                 AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,
> -                       ("STATUS_CONNECTION_ACTIVE: h_qp 
> %#I64x, uhdl %#I64x, ref_cnt %d\n",
> -                       (uint64_t)(ULONG_PTR)h_qp, 
> h_qp->obj.hdl, h_qp->obj.ref_cnt ) );
> +                       ("STATUS_CONNECTION_ACTIVE: CID = %d, 
> uhdl %#I64x, ref_cnt %d\n",
> +                       p_csq->cid, p_csq->h_qp, p_csq->ref_cnt ) );
>                 return STATUS_CONNECTION_INVALID;
>         }
> 
> @@ -1648,24 +1819,26 @@ __ndi_send_dreq(
>                 AL_EXIT( AL_DBG_NDI );
>                 return STATUS_NO_MEMORY;
>         }
> -       ref_al_obj( &h_qp->obj ); /* Take work item reference. */
> +       nd_csq_ref( p_csq ); /* Take work item reference. */
> 
> -       status = al_cep_dreq( qp_get_al( h_qp ), 
> ((al_conn_qp_t*)h_qp)->cid, NULL, 0 );
> +       status = al_cep_dreq( p_csq->h_al, p_csq->cid, NULL, 0 );
>         switch( 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.
> +                * on the CSQ until it completes.
>                  */
> -               ref_al_obj( &h_qp->obj ); /* Take IRP reference. */
> +               nd_csq_ref( p_csq ); /* Take IRP reference. */
> +               /* We might have just received a DREQ, so try 
> sending a DREP. */
> +               IoMarkIrpPending( p_irp );
> +               __ndi_queue_drep( p_irp );
> +               AL_EXIT( AL_DBG_NDI );
> +               return STATUS_INVALID_DEVICE_STATE;
> 
>         case IB_SUCCESS:
>                 AL_EXIT( AL_DBG_NDI );
> -               return( ib_to_ntstatus( status ) );
> +               return STATUS_PENDING;
> 
>         case IB_INVALID_HANDLE:
>                 nt_status = STATUS_CONNECTION_INVALID;
> @@ -1675,7 +1848,7 @@ __ndi_send_dreq(
>         }
>         IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );
>         p_irp->Tail.Overlay.DriverContext[1] = NULL;
> -       deref_al_obj( &h_qp->obj ); /* Release work item reference. */
> +       nd_csq_release( p_csq ); /* Release work item reference. */
>         AL_EXIT( AL_DBG_NDI );
>         return nt_status;
>  }
> @@ -1683,7 +1856,7 @@ __ndi_send_dreq(
> 
>  NTSTATUS
>  ndi_dreq_cm(
> -       IN              ib_qp_handle_t  const                 
>           h_qp,
> +       IN              nd_csq_t*                             
>                           p_csq,
>         IN              PIRP                                  
>                           p_irp
>         )
>  {
> @@ -1691,10 +1864,10 @@ ndi_dreq_cm(
> 
>         AL_ENTER( AL_DBG_NDI );
> 
> -       p_irp->Tail.Overlay.DriverContext[0] = h_qp;
> +       p_irp->Tail.Overlay.DriverContext[0] = p_csq;
> 
>         status = IoCsqInsertIrpEx(
> -               &h_qp->p_irp_queue->csq,
> +               &p_csq->csq,
>                 p_irp,
>                 NULL,
>                 (VOID*)(ULONG_PTR)NDI_CM_DISCONNECTING
> @@ -1706,10 +1879,136 @@ ndi_dreq_cm(
>          * 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 )
> +       if( status == STATUS_INVALID_DEVICE_STATE )
>                 status = STATUS_PENDING;
> 
>         AL_EXIT( AL_DBG_NDI );
>         return status;
>  }
> +
> +
> +NTSTATUS
> +ndi_listen_cm(
> +       IN              ib_al_handle_t                        
>           h_al,
> +       IN              ib_cep_listen_t                       
>           *p_listen,
> +               OUT     net32_t                               
>                   *p_cid,
> +               OUT     size_t                                
>                   *p_ret_bytes
> +       )
> +{
> +       NTSTATUS status;
> +       net32_t cid;
> +       ib_api_status_t ib_status;
> +       nd_csq_t *p_csq;
> +       KIRQL irql;
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       ib_status = al_create_cep( h_al, NULL, NULL, NULL, &cid );
> +       if( ib_status != IB_SUCCESS )
> +       {
> +               AL_EXIT( AL_DBG_NDI );
> +               return ib_to_ntstatus( ib_status );
> +       }
> +
> +       status = nd_csq_init( h_al, cid, 0, &p_csq );
> +       if( status != STATUS_SUCCESS )
> +       {
> +               kal_cep_destroy( h_al, cid, STATUS_SUCCESS );
> +               AL_EXIT( AL_DBG_NDI );
> +               return status;
> +       }
> +
> +       __ndi_acquire_lock( &p_csq->csq, &irql );
> +       p_csq->state = NDI_CM_LISTEN;
> +       __ndi_release_lock( &p_csq->csq, irql );
> +
> +       if( (p_listen->svc_id & 0xFFFF) == 0 )
> +       {
> +               p_listen->svc_id |= (USHORT)cid | (USHORT)(cid >> 16);
> +       }
> +
> +       ib_status = al_cep_listen( h_al, cid, p_listen );
> +       if( ib_status == IB_SUCCESS )
> +       {
> +               *p_cid = cid;
> +               *p_ret_bytes = sizeof(*p_cid);
> +       }
> +
> +       nd_csq_release( p_csq );
> +       status = ib_to_ntstatus( ib_status );
> +       AL_EXIT( AL_DBG_NDI );
> +       return status;
> +}
> +
> +
> +NTSTATUS
> +__ndi_get_req(
> +       IN              nd_csq_t                              
>                           *p_csq,
> +       IN              IRP*                                  
>                           p_irp
> +       )
> +{
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("[ CID = 
> %d\n", p_csq->cid) );
> +
> +       if( p_csq->state != NDI_CM_LISTEN )
> +       {
> +               AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_NDI,
> +                       ("] Invalid state (%d).\n", p_csq->state) );
> +               return STATUS_INVALID_DEVICE_REQUEST;
> +       }
> +
> +       /* Check the MAD list. */
> +       if( p_csq->p_mad_head != NULL )
> +       {
> +               ib_mad_element_t* p_mad = p_csq->p_mad_head;
> +               net32_t cid = 
> (net32_t)(ULONG_PTR)p_mad->send_context1;
> +               p_csq->p_mad_head = p_mad->p_next;
> +               p_mad->p_next = NULL;
> +
> +               *(net32_t*)cl_ioctl_out_buf( p_irp ) = cid;
> +               p_irp->IoStatus.Information = sizeof(net32_t);
> +               p_irp->IoStatus.Status = STATUS_SUCCESS;
> +               IoMarkIrpPending( p_irp );
> +               IoCompleteRequest( p_irp, IO_NETWORK_INCREMENT );
> +               ib_put_mad( p_mad );
> +               AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, 
> ("] Returned new CID = %d\n", cid) );
> +               return STATUS_INVALID_DEVICE_STATE;
> +       }
> +
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI, ("] 
> Queueing IRP\n") );
> +       return STATUS_PENDING;
> +}
> +
> +
> +NTSTATUS
> +ndi_get_req_cm(
> +       IN              nd_csq_t                              
>                   *p_csq,
> +       IN              PIRP                                  
>                   p_irp
> +       )
> +{
> +       NTSTATUS status;
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       status = IoCsqInsertIrpEx(
> +               &p_csq->csq,
> +               p_irp,
> +               NULL,
> +               (VOID*)(ULONG_PTR)NDI_CM_LISTEN
> +               );
> +
> +       /*
> +        * __ndi_get_req will return 
> STATUS_INVALID_DEVICE_STATE to prevent the IRP
> +        * from being inserted into the CSQ because the IRP 
> was immediately completed.
> +        * In this case, we need to return STATUS_PENDING.
> +        */
> +       if( status == STATUS_INVALID_DEVICE_STATE )
> +       {
> +               status = STATUS_PENDING;
> +       }
> +
> +       AL_EXIT( AL_DBG_NDI );
> +       return status;
> +}
> +
> +
> 
> Index: core/al/kernel/al_ndi_cm.h
> ===================================================================
> --- core/al/kernel/al_ndi_cm.h  (revision 2061)
> +++ core/al/kernel/al_ndi_cm.h  (working copy)
> @@ -64,8 +64,10 @@
>  typedef enum _ndi_cm_state
>  {
>         NDI_CM_IDLE,
> +       NDI_CM_LISTEN,
>         NDI_CM_CONNECTING_QPR_SENT, // QPR = Query path record
>         NDI_CM_CONNECTING_REQ_SENT,
> +       NDI_CM_CONNECTING_REQ_RCVD,
>         NDI_CM_CONNECTING_REP_SENT,
>         NDI_CM_CONNECTING_REP_RCVD,
>         NDI_CM_CONNECTED,
> @@ -77,16 +79,27 @@ typedef enum _ndi_cm_state
> 
>  typedef struct _ib_qp  ib_qp_t;
> 
> -typedef struct _ndi_qp_csq
> +typedef struct _nd_csq
>  {
>         IO_CSQ                                          csq;
>         LIST_ENTRY                                      queue;
> -       ib_qp_t*                                        h_qp;
> -       ib_query_handle_t                       h_query;
> +       ib_al_handle_t                          h_al;
> +       union {
> +               uint64_t                                h_qp;
> +               ib_mad_element_t                *p_mad_head;
> +       };
> +       union {
> +               ib_query_handle_t               h_query;
> +               ib_mad_element_t                *p_mad_tail;
> +       };
> +       net32_t                                         cid;
>         ndi_cm_state_t                          state;
>         PIO_WORKITEM                            p_workitem;
> +       volatile LONG                           ref_cnt;
> +       KSPIN_LOCK                                      lock;
> +
> +} nd_csq_t;
> 
> -} ndi_qp_csq_t;
> 
>  ib_api_status_t
>  ndi_modify_qp(
> @@ -95,41 +108,59 @@ ndi_modify_qp(
>         IN              const   uint32_t                      
>                   buf_size,
>         IN                              uint8_t* const        
>                   p_outbuf);
> 
> +void
> +nd_csq_ref( nd_csq_t* p_csq );
> +
> +void
> +nd_csq_release( nd_csq_t* p_csq );
> +
> +void
> +nd_cm_handler(
> +       IN              const   ib_al_handle_t                
>           h_al,
> +       IN              const   net32_t                       
>                   cid );
> +
>  NTSTATUS
>  ndi_req_cm(
> -       IN              ib_qp_handle_t  const                   h_qp,
> -       IN              cl_ioctl_handle_t                     
>           h_ioctl
> +       IN              ib_al_handle_t                        
>           h_al,
> +       IN              PIRP                                  
>                   p_irp
>         );
> 
>  NTSTATUS
>  ndi_rep_cm(
> -       IN              ib_qp_handle_t  const                   h_qp,
> +       IN              ib_al_handle_t                        
>           h_al,
>         IN              PIRP                                  
>                   p_irp
>         );
> 
>  cl_status_t
>  ndi_rtu_cm(
> -       IN              ib_qp_handle_t  const                   h_qp,
> +       IN              nd_csq_t                              
>                   *p_csq,
>         IN              PIRP                                  
>                   p_irp
>         );
> 
>  NTSTATUS
>  ndi_dreq_cm(
> -       IN              ib_qp_handle_t  const                   h_qp,
> +       IN              nd_csq_t                              
>                   *p_csq,
>         IN              PIRP                                  
>                   p_irp
>         );
> -
> -NTSTATUS
> -ndi_qp_init(
> -       IN              ib_qp_handle_t                        
>           h_qp );
> 
>  void
> -ndi_qp_destroy(
> -       IN              ib_qp_handle_t                        
>           h_qp );
> +ndi_cancel_cm_irps(
> +       IN              nd_csq_t                              
>                   *p_csq
> +       );
> 
> -void
> -ndi_qp_free(
> -       IN              ib_qp_handle_t                        
>           h_qp );
> +NTSTATUS
> +ndi_listen_cm(
> +       IN              ib_al_handle_t                        
>           h_al,
> +       IN              ib_cep_listen_t                       
>           *p_listen,
> +               OUT     net32_t                               
>                   *p_cid,
> +               OUT     size_t                                
>                   *p_ret_bytes
> +       );
> +
> +NTSTATUS
> +ndi_get_req_cm(
> +       IN              nd_csq_t                              
>                   *p_csq,
> +       IN              PIRP                                  
>                   p_irp
> +       );
> 
>  #endif
> 
> Index: core/al/kernel/al_cm.c
> ===================================================================
> --- core/al/kernel/al_cm.c      (revision 2061)
> +++ core/al/kernel/al_cm.c      (working copy)
> @@ -90,7 +90,7 @@ cm_cep_handler(const ib_al_handle_t h_al
> 
>                         id = cm_alloc_id(listen_id->callback, 
> listen_id);
>                         if (id == NULL) {
> -                               kal_cep_destroy(h_al, new_cid);
> +                               kal_cep_destroy(h_al, 
> new_cid, STATUS_NO_MORE_ENTRIES);
>                                 ib_put_mad(mad);
>                                 continue;
>                         }
> @@ -103,7 +103,7 @@ cm_cep_handler(const ib_al_handle_t h_al
>                 status = id->callback(id, &event);
>                 if (!NT_SUCCESS(status)) {
>                         kal_cep_config(h_al, new_cid, NULL, 
> NULL, NULL);
> -                       kal_cep_destroy(h_al, id->cid);
> +                       kal_cep_destroy(h_al, id->cid, status);
>                         cm_free_id(id);
>                 }
>                 ib_put_mad(mad);
> @@ -139,7 +139,7 @@ cm_destroy_id(iba_cm_id *p_id)
>         iba_cm_id_priv  *id;
> 
>         id = CONTAINING_RECORD(p_id, iba_cm_id_priv, id);
> -       kal_cep_destroy(gh_al, p_id->cid);
> +       kal_cep_destroy(gh_al, p_id->cid, STATUS_SUCCESS);
>         KeWaitForSingleObject(&id->destroy_event, Executive, 
> KernelMode, FALSE, NULL);
>         cm_free_id(p_id);
>  }
> Index: core/al/kernel/al_proxy_cep.c
> ===================================================================
> --- core/al/kernel/al_proxy_cep.c       (revision 2061)
> +++ core/al/kernel/al_proxy_cep.c       (working copy)
> @@ -53,7 +53,6 @@ proxy_create_cep(
>                 OUT     size_t                                
>   *p_ret_bytes )
>  {
>         al_dev_open_context_t           *p_context;
> -       void*                                           user_context;
>         ual_create_cep_ioctl_t          *p_ioctl;
> 
>         AL_ENTER( AL_DBG_CM );
> @@ -62,19 +61,13 @@ proxy_create_cep(
>         p_ioctl = (ual_create_cep_ioctl_t*)cl_ioctl_out_buf( 
> h_ioctl );
> 
>         /* Validate user parameters. */
> -       if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint64_t) ||
> -               cl_ioctl_out_size( h_ioctl ) != 
> sizeof(ual_create_cep_ioctl_t) )
> +       if( cl_ioctl_out_size( h_ioctl ) != 
> sizeof(ual_create_cep_ioctl_t) )
>         {
>                 AL_EXIT( AL_DBG_CM );
>                 return CL_INVALID_PARAMETER;
>         }
> -
> -       user_context = *(void**)cl_ioctl_in_buf( h_ioctl );
> -
>         /* We use IRPs as notification mechanism so the 
> callback is NULL. */
> -       p_ioctl->cid = AL_INVALID_CID;
> -       p_ioctl->status = al_create_cep( p_context->h_al, NULL,
> -               user_context, NULL, &p_ioctl->cid );
> +       p_ioctl->status = kal_cep_alloc( p_context->h_al, 
> &p_ioctl->cid );
> 
>         *p_ret_bytes = sizeof(ual_create_cep_ioctl_t);
> 
> @@ -862,37 +855,6 @@ proxy_cep_get_event(
>  }
> 
> 
> -static cl_status_t
> -proxy_cep_get_req_cid(
> -       IN              void                                  
>   *p_open_context,
> -       IN              cl_ioctl_handle_t               h_ioctl,
> -               OUT     size_t                                
>   *p_ret_bytes )
> -{
> -       cl_status_t cl_status;
> -       al_dev_open_context_t *p_context;
> -       UNUSED_PARAM(p_ret_bytes);
> -
> -       AL_ENTER( AL_DBG_CM );
> -
> -       p_context = (al_dev_open_context_t*)p_open_context;
> -
> -       /* Validate user parameters. */
> -       if( cl_ioctl_in_size( h_ioctl ) != sizeof(uint32_t) ||
> -               cl_ioctl_out_size( h_ioctl ) != sizeof(uint32_t) )
> -       {
> -               AL_EXIT( AL_DBG_CM );
> -               return CL_INVALID_PARAMETER;
> -       }
> -
> -       /* get CID */
> -       cl_status = al_cep_get_cid( p_context->h_al,
> -               *(uint32_t*)cl_ioctl_in_buf( h_ioctl ), h_ioctl );
> -
> -       AL_EXIT( AL_DBG_CM );
> -       return cl_status;
> -}
> -
> -
> 
>  static cl_status_t
>  proxy_cep_get_pdata(
> @@ -902,8 +864,8 @@ proxy_cep_get_pdata(
>  {
>         al_dev_open_context_t           *p_context;
>         ual_cep_get_pdata_ioctl_t       *p_ioctl;
> -       al_conn_qp_t                            *p_qp;
>         NTSTATUS                    status;
> +       net32_t                                         cid;
> 
>         AL_ENTER( AL_DBG_CM );
> 
> @@ -922,23 +884,9 @@ proxy_cep_get_pdata(
>                 return CL_INVALID_PARAMETER;
>         }
> 
> -       if ( p_ioctl->in.h_qp )
> -       {
> -               /* Get the kernel QP handle. */
> -               p_qp = (al_conn_qp_t*)al_hdl_ref(
> -                       p_context->h_al, p_ioctl->in.h_qp, 
> AL_OBJ_TYPE_H_QP );
> -               if( !p_qp )
> -               {
> -                       AL_PRINT_EXIT( TRACE_LEVEL_ERROR, 
> AL_DBG_ERROR,
> -                               ("Invalid QP handle\n"));
> -                       return CL_CONNECTION_INVALID;
> -               }
> -               p_ioctl->in.cid = p_qp->cid;
> -               deref_al_obj( &p_qp->qp.obj );
> -       }
> -
> +       cid = p_ioctl->in.cid;
>         p_ioctl->out.pdata_len = sizeof(p_ioctl->out.pdata);
> -       status = al_cep_get_pdata( p_context->h_al, p_ioctl->in.cid,
> +       status = al_cep_get_pdata( p_context->h_al, cid,
>          &p_ioctl->out.init_depth, &p_ioctl->out.resp_res,
>                 (uint8_t*)&p_ioctl->out.pdata_len, 
> p_ioctl->out.pdata );
> 
> @@ -953,6 +901,7 @@ proxy_cep_get_pdata(
>         return status;
>  }
> 
> +
>  cl_status_t cep_ioctl(
>         IN              cl_ioctl_handle_t               h_ioctl,
>                 OUT     size_t                                
>   *p_ret_bytes )
> @@ -1035,9 +984,6 @@ cl_status_t cep_ioctl(
>                 break;
>         case UAL_CEP_POLL:
>                 cl_status = proxy_cep_poll( p_context, 
> h_ioctl, p_ret_bytes );
> -               break;
> -       case UAL_CEP_GET_REQ_CID:
> -               cl_status = proxy_cep_get_req_cid( p_context, 
> h_ioctl, p_ret_bytes );
>                 break;
>         case UAL_CEP_GET_PDATA:
>                 cl_status = proxy_cep_get_pdata( p_context, 
> h_ioctl, p_ret_bytes );
> Index: core/al/kernel/al_proxy_ndi.c
> ===================================================================
> --- core/al/kernel/al_proxy_ndi.c       (revision 2061)
> +++ core/al/kernel/al_proxy_ndi.c       (working copy)
> @@ -322,7 +322,7 @@ __ndi_req_cm(
>         p_context = (al_dev_open_context_t*)p_open_context;
> 
>         /* Validate user parameters. */
> -       if( cl_ioctl_in_size( h_ioctl ) < 
> sizeof(ual_ndi_req_cm_ioctl_in_t))
> +       if( cl_ioctl_in_size( h_ioctl ) < 
> sizeof(ual_ndi_req_cm_ioctl_in_t) )
>         {
>                 cl_status = CL_INVALID_PARAMETER;
>                 goto exit;
> @@ -351,7 +351,7 @@ __ndi_req_cm(
>         }
> 
>         /* perform the ioctl */
> -       cl_status = ndi_req_cm( h_qp, h_ioctl );
> +       cl_status = ndi_req_cm( p_context->h_al, h_ioctl );
> 
>  err:
>         deref_al_obj( &h_qp->obj );
> @@ -370,7 +370,6 @@ __ndi_rep_cm(
>         cl_status_t cl_status;
>         ib_qp_handle_t h_qp = NULL;
>         al_dev_open_context_t *p_context;
> -       net32_t cid;
>         ual_ndi_rep_cm_ioctl_in_t *p_rep =
>                 (ual_ndi_rep_cm_ioctl_in_t*)cl_ioctl_in_buf( 
> h_ioctl );
>         UNUSED_PARAM(p_ret_bytes);
> @@ -386,6 +385,9 @@ __ndi_rep_cm(
>                 goto exit;
>         }
> 
> +       AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +               ("CID = %d\n", p_rep->cid) );
> +
>         /* Get and validate QP handle */
>         h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, 
> p_rep->h_qp, AL_OBJ_TYPE_H_QP );
>         if( !h_qp )
> @@ -406,12 +408,9 @@ __ndi_rep_cm(
>                 cl_status = CL_INVALID_PARAMETER;
>                 goto err;
>         }
> -
> -       /* Get and validate CID */
> -       cid = p_rep->cid;
> 
>         /* perform the ioctls */
> -       cl_status = ndi_rep_cm( h_qp, h_ioctl );
> +       cl_status = ndi_rep_cm( p_context->h_al, h_ioctl );
> 
>  err:
>         deref_al_obj( &h_qp->obj );
> @@ -455,7 +454,6 @@ __ndi_rej_cm(
>                 goto exit;
>         }
> 
> -       al_destroy_cep( p_context->h_al, &p_rej->cid, FALSE );
>         ntstatus = STATUS_SUCCESS;
> 
>  exit:
> @@ -470,10 +468,8 @@ __ndi_rtu_cm(
>                 OUT     size_t                                
>   *p_ret_bytes )
>  {
>         cl_status_t cl_status;
> -       ib_qp_handle_t h_qp = NULL;
> +       nd_csq_t* p_csq;
>         al_dev_open_context_t *p_context;
> -       ual_ndi_rtu_cm_ioctl_in_t *p_rtu =
> -               (ual_ndi_rtu_cm_ioctl_in_t*)cl_ioctl_in_buf( 
> h_ioctl );
> 
>         UNUSED_PARAM(p_ret_bytes);
> 
> @@ -482,32 +478,28 @@ __ndi_rtu_cm(
>         p_context = (al_dev_open_context_t*)p_open_context;
> 
>         /* Validate user parameters. */
> -       if( cl_ioctl_in_size( h_ioctl ) < 
> sizeof(ual_ndi_rtu_cm_ioctl_in_t))
> +       if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )
>         {
>                 cl_status = CL_INVALID_PARAMETER;
>                 goto exit;
>         }
> 
> -       /* Validate QP handle */
> -       h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, 
> p_rtu->h_qp, AL_OBJ_TYPE_H_QP );
> -       if( !h_qp )
> +       p_csq = kal_cep_get_context(
> +               p_context->h_al,
> +               *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> +               nd_cm_handler,
> +               nd_csq_ref
> +               );
> +       if( p_csq == NULL )
>         {
>                 cl_status = CL_INVALID_HANDLE;
>                 goto exit;
>         }
> 
> -       /* Check QP type */
> -       if( h_qp->type != IB_QPT_RELIABLE_CONN )
> -       {
> -               cl_status = CL_INVALID_HANDLE;
> -               goto err;
> -       }
> -
>         /* perform the ioctl */
> -       cl_status = ndi_rtu_cm( h_qp, h_ioctl );
> +       cl_status = ndi_rtu_cm( p_csq, h_ioctl );
> 
> -err:
> -       deref_al_obj( &h_qp->obj );
> +       nd_csq_release( p_csq );
> 
>  exit:
>         AL_EXIT( AL_DBG_NDI );
> @@ -521,7 +513,7 @@ __ndi_dreq_cm(
>                 OUT     size_t                                
>   *p_ret_bytes )
>  {
>         cl_status_t cl_status;
> -       ib_qp_handle_t h_qp = NULL;
> +       nd_csq_t *p_csq;
>         al_dev_open_context_t *p_context;
> 
>         UNUSED_PARAM(p_ret_bytes);
> @@ -531,37 +523,206 @@ __ndi_dreq_cm(
>         p_context = (al_dev_open_context_t*)p_open_context;
> 
>         /* Validate user parameters. */
> -       if( cl_ioctl_in_size( h_ioctl ) < sizeof(uint64_t))
> +       if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )
>         {
>                 cl_status = CL_INVALID_PARAMETER;
>                 goto exit;
>         }
> 
> -       /* Validate QP handle */
> -       h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al,
> -               *(uint64_t*)cl_ioctl_in_buf( h_ioctl ), 
> AL_OBJ_TYPE_H_QP );
> -       if( !h_qp )
> +       /* Validate CID */
> +       p_csq = (nd_csq_t*)kal_cep_get_context(
> +               p_context->h_al,
> +               *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> +               nd_cm_handler,
> +               nd_csq_ref
> +               );
> +
> +       if( p_csq == NULL )
>         {
>                 cl_status = CL_CONNECTION_INVALID;
>                 goto exit;
>         }
> 
> -       /* Check QP type */
> -       if( h_qp->type != IB_QPT_RELIABLE_CONN )
> +       /* perform the ioctl */
> +       cl_status = ndi_dreq_cm( p_csq, h_ioctl );
> +
> +       nd_csq_release( p_csq );
> +
> +exit:
> +       AL_EXIT( AL_DBG_NDI );
> +       return cl_status;
> +}
> +
> +static NTSTATUS
> +__ndi_notify_dreq_cm(
> +       IN              void                                  
>   *p_open_context,
> +       IN              cl_ioctl_handle_t               h_ioctl,
> +               OUT     size_t                                
>   *p_ret_bytes )
> +{
> +       NTSTATUS status;
> +       nd_csq_t *p_csq;
> +       al_dev_open_context_t *p_context;
> +
> +       UNUSED_PARAM(p_ret_bytes);
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       p_context = (al_dev_open_context_t*)p_open_context;
> +
> +       /* Validate user parameters. */
> +       if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )
>         {
> -               cl_status = CL_CONNECTION_INVALID;
> -               goto err;
> +               status = STATUS_INVALID_PARAMETER;
> +               goto exit;
> +       }
> +
> +       /* Validate CID */
> +       p_csq = (nd_csq_t*)kal_cep_get_context(
> +               p_context->h_al,
> +               *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> +               nd_cm_handler,
> +               nd_csq_ref
> +               );
> +
> +       if( p_csq == NULL )
> +       {
> +               status = STATUS_CONNECTION_INVALID;
> +               goto exit;
>         }
> 
>         /* perform the ioctl */
> -       cl_status = ndi_dreq_cm( h_qp, h_ioctl );
> +       status = IoCsqInsertIrpEx(
> +               &p_csq->csq,
> +               h_ioctl,
> +               NULL,
> +               (VOID*)(ULONG_PTR)NDI_CM_CONNECTED_DREQ_RCVD
> +               );
> 
> -err:
> -       deref_al_obj( &h_qp->obj );
> +       nd_csq_release( p_csq );
> 
>  exit:
>         AL_EXIT( AL_DBG_NDI );
> -       return cl_status;
> +       return status;
> +}
> +
> +static cl_status_t
> +__ndi_cancel_cm_irps(
> +       IN              void                                  
>   *p_open_context,
> +       IN              cl_ioctl_handle_t               h_ioctl,
> +               OUT     size_t                                
>   *p_ret_bytes )
> +{
> +       nd_csq_t *p_csq;
> +       al_dev_open_context_t *p_context;
> +
> +       UNUSED_PARAM(p_ret_bytes);
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       p_context = (al_dev_open_context_t*)p_open_context;
> +
> +       /* Validate user parameters. */
> +       if( cl_ioctl_in_size( h_ioctl ) < sizeof(net32_t) )
> +       {
> +               AL_EXIT( AL_DBG_NDI );
> +               return STATUS_INVALID_PARAMETER;
> +       }
> +
> +       /* Validate CID */
> +       p_csq = (nd_csq_t*)kal_cep_get_context(
> +               p_context->h_al,
> +               *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> +               nd_cm_handler,
> +               nd_csq_ref
> +               );
> +
> +       if( p_csq == NULL )
> +       {
> +               AL_EXIT( AL_DBG_NDI );
> +               return STATUS_UNSUCCESSFUL;
> +       }
> +
> +       /* perform the ioctl */
> +       ndi_cancel_cm_irps( p_csq );
> +       nd_csq_release( p_csq );
> +
> +       AL_EXIT( AL_DBG_NDI );
> +       return STATUS_SUCCESS;
> +}
> +
> +static cl_status_t
> +__ndi_listen_cm(
> +       IN              void                                  
>   *p_open_context,
> +       IN              cl_ioctl_handle_t               h_ioctl,
> +               OUT     size_t                                
>   *p_ret_bytes )
> +{
> +       al_dev_open_context_t *p_context;
> +       ual_cep_listen_ioctl_t *p_listen =
> +               (ual_cep_listen_ioctl_t*)cl_ioctl_in_buf( h_ioctl );
> +       net32_t* p_cid =
> +               (net32_t*)cl_ioctl_out_buf( h_ioctl );
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       p_context = (al_dev_open_context_t*)p_open_context;
> +
> +       /* Validate user parameters. */
> +       if( cl_ioctl_in_size( h_ioctl ) < sizeof(*p_listen) ||
> +               cl_ioctl_out_size( h_ioctl ) != sizeof(*p_cid) )
> +       {
> +               AL_EXIT( AL_DBG_NDI );
> +               return CL_INVALID_PARAMETER;
> +       }
> +
> +       /* Set the private data compare buffer to our kernel copy. */
> +       if( p_listen->cep_listen.p_cmp_buf )
> +               p_listen->cep_listen.p_cmp_buf = p_listen->compare;
> +
> +       AL_EXIT( AL_DBG_NDI );
> +       return ndi_listen_cm( p_context->h_al, 
> &p_listen->cep_listen, p_cid, p_ret_bytes );
> +}
> +
> +static cl_status_t
> +__ndi_get_req_cm(
> +       IN              void                                  
>   *p_open_context,
> +       IN              cl_ioctl_handle_t               h_ioctl,
> +               OUT     size_t                                
>   *p_ret_bytes )
> +{
> +       al_dev_open_context_t *p_context;
> +       nd_csq_t *p_csq;
> +       NTSTATUS status;
> +
> +       AL_ENTER( AL_DBG_NDI );
> +
> +       UNREFERENCED_PARAMETER( p_ret_bytes );
> +
> +       p_context = (al_dev_open_context_t*)p_open_context;
> +
> +       /* Validate user parameters. */
> +       if( cl_ioctl_in_size( h_ioctl ) != sizeof(net32_t) ||
> +               cl_ioctl_out_size( h_ioctl ) != sizeof(net32_t) )
> +       {
> +               AL_EXIT( AL_DBG_NDI );
> +               return CL_INVALID_PARAMETER;
> +       }
> +
> +       /* Validate CID */
> +       p_csq = (nd_csq_t*)kal_cep_get_context(
> +               p_context->h_al,
> +               *(net32_t*)cl_ioctl_in_buf( h_ioctl ),
> +               nd_cm_handler,
> +               nd_csq_ref
> +               );
> +
> +       if( p_csq == NULL )
> +       {
> +               AL_EXIT( AL_DBG_NDI );
> +               return STATUS_UNSUCCESSFUL;
> +       }
> +
> +       status = ndi_get_req_cm( p_csq, h_ioctl );
> +       nd_csq_release( p_csq );
> +       AL_EXIT( AL_DBG_NDI );
> +       return status;
>  }
> 
>  cl_status_t
> @@ -621,9 +782,23 @@ ndi_ioctl(
>              h_ioctl->IoStatus.Status = CL_SUCCESS;
>          h_ioctl->IoStatus.Information = 0;
> 
> +               AL_PRINT( TRACE_LEVEL_VERBOSE, AL_DBG_NDI,
> +                       ("UAL_NDI_NOOP completed with 
> %08x\n", h_ioctl->IoStatus.Status) );
>          IoCompleteRequest( h_ioctl, IO_NETWORK_INCREMENT );
>          cl_status = CL_PENDING;
>          break;
> +       case UAL_NDI_NOTIFY_DREQ:
> +               cl_status = __ndi_notify_dreq_cm( p_context, 
> h_ioctl, p_ret_bytes );
> +               break;
> +       case UAL_NDI_CANCEL_CM_IRPS:
> +               cl_status = __ndi_cancel_cm_irps( p_context, 
> h_ioctl, p_ret_bytes );
> +               break;
> +       case UAL_NDI_LISTEN_CM:
> +               cl_status = __ndi_listen_cm( p_context, 
> h_ioctl, p_ret_bytes );
> +               break;
> +       case UAL_NDI_GET_REQ_CM:
> +               cl_status = __ndi_get_req_cm( p_context, 
> h_ioctl, p_ret_bytes );
> +               break;
>         default:
>                 cl_status = CL_INVALID_PARAMETER;
>                 break;
> Index: core/al/al_qp.h
> ===================================================================
> --- core/al/al_qp.h     (revision 2061)
> +++ core/al/al_qp.h     (working copy)
> @@ -135,10 +135,6 @@ typedef struct _ib_qp
>                 IN              const   ib_qp_handle_t        
>                   h_qp,
>                 IN              const   ib_mcast_req_t* const 
>           p_mcast_req );
> 
> -#ifdef CL_KERNEL
> -       ndi_qp_csq_t                            *p_irp_queue;
> -#endif
> -
>  }      ib_qp_t;
> 
> 
> Index: core/al/al_cm_cep.h
> ===================================================================
> --- core/al/al_cm_cep.h (revision 2061)
> +++ core/al/al_cm_cep.h (working copy)
> @@ -116,7 +116,7 @@ kal_cep_alloc(
>         IN                              ib_al_handle_t        
>                   h_al,
>         IN      OUT                     net32_t* const        
>                   p_cid );
> 
> -void
> +ib_api_status_t
>  kal_cep_config(
>         IN                              ib_al_handle_t        
>                   h_al,
>         IN                              net32_t               
>                           cid,
> @@ -184,22 +184,11 @@ kal_cep_pre_rep(
>         IN                              uint8_t               
>                           rnr_nak_timeout,
>         IN      OUT                     ib_qp_mod_t* const    
>                   p_init OPTIONAL );
> 
> -ib_api_status_t
> -kal_cep_config_pre_rep_copy_cid(
> -       IN                              ib_al_handle_t        
>                   h_al,
> -       IN                              net32_t               
>                           cid,
> -       IN                              al_pfn_cep_cb_t       
>                   pfn_cb,
> -       IN                              void*                 
>                           context,
> -       IN                              ib_pfn_destroy_cb_t   
>                   pfn_destroy_cb,
> -       IN              const   iba_cm_rep* const             
>           p_cm_rep,
> -       IN                              uint8_t               
>                           rnr_nak_timeout,
> -       IN      OUT                     net32_t* const        
>                   p_cid,
> -               OUT                     ib_qp_mod_t* const    
>                   p_init );
> -
>  void
>  kal_cep_destroy(
>         IN                              ib_al_handle_t        
>                   h_al,
> -       IN                              net32_t               
>                           cid );
> +       IN                              net32_t               
>                           cid,
> +       IN                              NTSTATUS              
>                           status );
>  #endif
> 
>  ib_api_status_t
> @@ -337,13 +326,6 @@ al_cep_queue_irp(
>         IN                              IRP* const            
>                           p_irp );
> 
>  NTSTATUS
> -al_cep_get_cid(
> -       IN              ib_al_handle_t                        
>                   h_al,
> -       IN              net32_t                 const         
>                   cid,
> -       IN              PIRP                                  
>                           h_ioctl
> -       );
> -
> -NTSTATUS
>  al_cep_get_pdata(
>         IN                              ib_al_handle_t        
>                   h_al,
>         IN                              net32_t               
>                           cid,
> @@ -352,6 +334,12 @@ al_cep_get_pdata(
>         IN      OUT                     uint8_t               
>                           *p_psize,
>                 OUT                     uint8_t*              
>                           pdata );
> 
> +void*
> +kal_cep_get_context(
> +       IN                              ib_al_handle_t        
>                   h_al,
> +       IN                              net32_t               
>                           cid,
> +       IN                              al_pfn_cep_cb_t       
>                   pfn_cb,
> +       IN                              ib_pfn_destroy_cb_t   
>                   pfn_addref );
>  #endif /* CL_KERNEL */
> 
> 
> Index: core/al/al_dev.h
> ===================================================================
> --- core/al/al_dev.h    (revision 2061)
> +++ core/al/al_dev.h    (working copy)
> @@ -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                       (11)
> +#define AL_IOCTL_VERSION                       (12)
> 
>  /* max number of devices with non-default pkey */
>  #define        MAX_NUM_PKEY    16
> @@ -353,7 +353,6 @@ typedef enum _ual_cep_ops
>         ual_cep_get_timewait,
>         ual_cep_get_event,
>         ual_cep_poll,
> -       ual_cep_get_req_cid,
>         ual_cep_get_pdata,
> 
>         al_cep_maxops
> @@ -408,6 +407,9 @@ typedef enum _al_ndi_ops
>         ual_ndi_dreq_cm_ioctl_cmd,
>      ual_ndi_noop,
>      ual_ndi_notify_dreq_cmd,
> +       ual_ndi_cancel_cm_irps,
> +       ual_ndi_listen_cm_cmd,
> +       ual_ndi_get_req_cm_cmd,
> 
>         al_ndi_maxops
> 
> @@ -440,6 +442,9 @@ typedef enum _al_ioc_device_config
>  #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)
> +#define UAL_NDI_CANCEL_CM_IRPS IOCTL_CODE(ALDEV_KEY, 
> ual_ndi_cancel_cm_irps)
> +#define UAL_NDI_LISTEN_CM              IOCTL_CODE(ALDEV_KEY, 
> ual_ndi_listen_cm_cmd)
> +#define UAL_NDI_GET_REQ_CM             IOCTL_CODE(ALDEV_KEY, 
> ual_ndi_get_req_cm_cmd)
> 
>  /*
>   * Various Operation Allowable on the System Helper
> @@ -541,7 +546,6 @@ typedef enum _al_ioc_device_config
>  #define UAL_CEP_GET_TIMEWAIT   IOCTL_CODE(ALDEV_KEY, 
> ual_cep_get_timewait)
>  #define UAL_CEP_GET_EVENT      IOCTL_CODE(ALDEV_KEY, 
> ual_cep_get_event)
>  #define UAL_CEP_POLL           IOCTL_CODE(ALDEV_KEY, ual_cep_poll)
> -#define UAL_CEP_GET_REQ_CID    IOCTL_CODE(ALDEV_KEY, 
> ual_cep_get_req_cid)
>  #define UAL_CEP_GET_PDATA      IOCTL_CODE(ALDEV_KEY, 
> ual_cep_get_pdata)
> 
> 
> Index: core/al/al_qp.c
> ===================================================================
> --- core/al/al_qp.c     (revision 2061)
> +++ core/al/al_qp.c     (working copy)
> @@ -327,10 +327,6 @@ create_qp(
>                         break;
>                 }
>                 status = init_conn_qp( (al_conn_qp_t*)h_qp, 
> h_pd, p_qp_create, p_umv_buf );
> -#ifdef CL_KERNEL
> -               if( status == IB_SUCCESS && !NT_SUCCESS( 
> ndi_qp_init(h_qp) ) )
> -                       status = IB_ERROR;
> -#endif
>                 break;
> 
>         case IB_QPT_UNRELIABLE_DGRM:
> @@ -1117,9 +1113,6 @@ destroying_qp(
>         case IB_QPT_RELIABLE_CONN:
>         case IB_QPT_UNRELIABLE_CONN:
>                 al_destroy_cep( h_qp->obj.h_al, 
> &((al_conn_qp_t*)h_qp)->cid, FALSE );
> -#ifdef CL_KERNEL
> -               ndi_qp_destroy( h_qp );
> -#endif
> 
>                 /* Fall through. */
>         case IB_QPT_UNRELIABLE_DGRM:
> @@ -1236,10 +1229,6 @@ free_qp(
> 
>         CL_ASSERT( p_obj );
>         h_qp = PARENT_STRUCT( p_obj, ib_qp_t, obj );
> -
> -#ifdef CL_KERNEL
> -       ndi_qp_free( h_qp );
> -#endif
> 
>         destroy_al_obj( p_obj );
>         cl_free( h_qp );
> Index: core/al/user/ual_cm_cep.c
> ===================================================================
> --- core/al/user/ual_cm_cep.c   (revision 2061)
> +++ core/al/user/ual_cm_cep.c   (working copy)
> @@ -272,9 +272,8 @@ __create_ucep(
>         /* Create a kernel CEP only if we don't already have a CID. */
>         if( cid == AL_INVALID_CID )
>         {
> -               uint64_t cep_context = (ULONG_PTR)context;
> -               if( !DeviceIoControl( g_al_device, 
> UAL_CREATE_CEP, &cep_context,
> -                       sizeof(cep_context), &ioctl, 
> sizeof(ioctl), &bytes_ret, NULL ) ||
> +               if( !DeviceIoControl( g_al_device, 
> UAL_CREATE_CEP, NULL,
> +                       0, &ioctl, sizeof(ioctl), &bytes_ret, 
> NULL ) ||
>                         bytes_ret != sizeof(ioctl) )
>                 {
>                         __destroy_ucep( p_cep );
> Index: inc/iba/ib_al_ioctl.h
> ===================================================================
> --- inc/iba/ib_al_ioctl.h       (revision 2061)
> +++ inc/iba/ib_al_ioctl.h       (working copy)
> @@ -3089,7 +3089,6 @@ typedef union _ual_cep_get_pdata_ioctl
>  {
>         struct _ual_cep_get_pdata_ioctl_in
>         {
> -               uint64_t                                h_qp;
>                 net32_t                                 cid;
> 
>         }       in;
> @@ -3106,9 +3105,6 @@ typedef union _ual_cep_get_pdata_ioctl
>  }      ual_cep_get_pdata_ioctl_t;
>  /*
>  * FIELDS
> -*      h_qp
> -*              A handle to the QP to modify.
> -*
>  *      in.cid
>  *              The CID for the target CEP.
>  *
> @@ -3483,6 +3479,7 @@ typedef struct _ual_ndi_req_cm_ioctl_in
>      ib_path_rec_t               path;
>         uint64_t                                        h_qp;
>         net64_t                                         guid;
> +       net32_t                                         cid;
>         uint16_t                                        dst_port;
>      uint8_t                     resp_res;
>      uint8_t                     init_depth;
> @@ -3493,7 +3490,7 @@ typedef struct _ual_ndi_req_cm_ioctl_in
>  }      ual_ndi_req_cm_ioctl_in_t;
>  /*
>  * NOTES
> -*      The output parameter is the new QP state (RTS).
> +*      There is no output parameter.
>  *
>  * FIELDS
>  *      h_qp
> @@ -3502,6 +3499,9 @@ typedef struct _ual_ndi_req_cm_ioctl_in
>  *      guid
>  *              Local port GUID to which to bind to.
>  *
> +*      cid
> +*              CID of the CEP to use for the connection request.
> +*
>  *      dst_port
>  *              Destination port number.
>  *
> @@ -3600,38 +3600,6 @@ typedef struct _ual_ndi_rej_cm_ioctl_in
>  *
>  *      pdata
>  *              Private data in format RDMA CM
> -*
> -*****/
> -
> -
> -/****s* User-mode Access Layer/ual_ndi_rtu_cm_ioctl_in_t
> -* NAME
> -*      ual_ndi_rtu_cm_ioctl_in_t
> -*
> -* DESCRIPTION
> -*      IOCTL structure containing the input parameters
> -*      sending CM RTU response .
> -*
> -* SYNOPSIS
> -*/
> -typedef struct _ual_ndi_rtu_cm_ioctl_in
> -{
> -       uint64_t                                        h_qp;
> -
> -}      ual_ndi_rtu_cm_ioctl_in_t;
> -/*
> -* NOTES
> -*      The output parameter is the new QP state (RTS).
> -*
> -* FIELDS
> -*      h_qp
> -*              A handle to the QP to modify.
> -*
> -*      init_depth
> -*              The maximum number of outstanding RDMA 
> read/atomic operations.
> -*
> -*      resp_res
> -*              The maximum number of RDMA read/atomic 
> operations from the recipient.
>  *
>  *****/
> 
> 



More information about the ofw mailing list