From ab7ee43174ab7858d839552bd031475af2da21b5 Mon Sep 17 00:00:00 2001 From: leonidk Date: Tue, 9 Oct 2007 18:46:56 +0000 Subject: [PATCH] [IBAL] added new IOCTLs GET_CID and REQ_CM git-svn-id: svn://openib.tc.cornell.edu/gen1@851 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- branches/Ndi/core/al/al_cq.c | 5 +- branches/Ndi/core/al/al_cq.h | 8 +- branches/Ndi/core/al/al_dev.h | 8 + branches/Ndi/core/al/al_qp.c | 8 + branches/Ndi/core/al/al_qp.h | 7 +- branches/Ndi/core/al/kernel/SOURCES | 2 + branches/Ndi/core/al/kernel/al_cm_cep.c | 10 +- branches/Ndi/core/al/kernel/al_cm_rdma.h | 2 - branches/Ndi/core/al/kernel/al_ndi_cm.c | 910 +++++++++++++++++++++ branches/Ndi/core/al/kernel/al_ndi_cm.h | 149 ++++ branches/Ndi/core/al/kernel/al_ndi_cq.c | 280 +++++++ branches/Ndi/core/al/kernel/al_ndi_cq.h | 62 ++ branches/Ndi/core/al/kernel/al_proxy_ndi.c | 504 ++++++------ branches/Ndi/core/al/kernel/al_proxy_ndi.h | 12 +- branches/Ndi/inc/iba/ib_al_ioctl.h | 146 +++- branches/Ndi/inc/iba/ib_types.h | 1 + branches/Ndi/inc/user/iba/ib_uvp.h | 44 + 17 files changed, 1887 insertions(+), 271 deletions(-) create mode 100644 branches/Ndi/core/al/kernel/al_ndi_cm.c create mode 100644 branches/Ndi/core/al/kernel/al_ndi_cm.h create mode 100644 branches/Ndi/core/al/kernel/al_ndi_cq.c create mode 100644 branches/Ndi/core/al/kernel/al_ndi_cq.h diff --git a/branches/Ndi/core/al/al_cq.c b/branches/Ndi/core/al/al_cq.c index a1933f3d..d297d2e8 100644 --- a/branches/Ndi/core/al/al_cq.c +++ b/branches/Ndi/core/al/al_cq.c @@ -99,8 +99,7 @@ create_cq( } #ifdef CL_KERNEL - /* cancel pending IRPS for NDI type CQ */ - if( !NT_SUCCESS( proxy_ndi_cq_init( h_cq ) ) ) + if( !NT_SUCCESS( ndi_cq_init( h_cq ) ) ) { free_cq( &h_cq->obj ); return IB_ERROR; @@ -223,7 +222,7 @@ destroying_cq( #ifdef CL_KERNEL /* cancel pending IRPS for NDI type CQ */ - proxy_ndi_flush_ques( h_cq ); + ndi_cq_flush_ques( h_cq ); #endif } diff --git a/branches/Ndi/core/al/al_cq.h b/branches/Ndi/core/al/al_cq.h index 0a330287..d3e6c52f 100644 --- a/branches/Ndi/core/al/al_cq.h +++ b/branches/Ndi/core/al/al_cq.h @@ -64,12 +64,12 @@ typedef ib_api_status_t typedef struct _ib_cq ib_cq_t; -typedef struct _ndi_io_csq +typedef struct _ndi_cq_csq { IO_CSQ csq; ib_cq_t* h_cq; LIST_ENTRY que; -} ndi_io_csq_t; +} ndi_cq_csq_t; #endif @@ -107,8 +107,8 @@ typedef struct _ib_cq /* NDI CQ fields */ #ifdef CL_KERNEL - ndi_io_csq_t compl; - ndi_io_csq_t error; + ndi_cq_csq_t compl; + ndi_cq_csq_t error; #endif } ib_cq_t; diff --git a/branches/Ndi/core/al/al_dev.h b/branches/Ndi/core/al/al_dev.h index 5529c050..eab5ada5 100644 --- a/branches/Ndi/core/al/al_dev.h +++ b/branches/Ndi/core/al/al_dev.h @@ -383,6 +383,10 @@ typedef enum _al_ndi_ops ual_ndi_create_cq_ioctl_cmd, ual_ndi_notify_cq_ioctl_cmd, ual_ndi_cancel_cq_ioctl_cmd, + ual_ndi_get_cid_ioctl_cmd, + ual_ndi_req_cm_ioctl_cmd, + ual_ndi_rep_cm_ioctl_cmd, + ual_ndi_rtu_cm_ioctl_cmd, al_ndi_maxops @@ -398,6 +402,10 @@ typedef enum _al_ndi_ops #define UAL_NDI_CREATE_CQ IOCTL_CODE(ALDEV_KEY, ual_ndi_create_cq_ioctl_cmd) #define UAL_NDI_NOTIFY_CQ IOCTL_CODE(ALDEV_KEY, ual_ndi_notify_cq_ioctl_cmd) #define UAL_NDI_CANCEL_CQ IOCTL_CODE(ALDEV_KEY, ual_ndi_cancel_cq_ioctl_cmd) +#define UAL_NDI_GET_CID IOCTL_CODE(ALDEV_KEY, ual_ndi_get_cid_ioctl_cmd) +#define UAL_NDI_REQ_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_req_cm_ioctl_cmd) +#define UAL_NDI_REP_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_rep_cm_ioctl_cmd) +#define UAL_NDI_RTU_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_rtu_cm_ioctl_cmd) /* * Various Opration Allowable on the System Helper diff --git a/branches/Ndi/core/al/al_qp.c b/branches/Ndi/core/al/al_qp.c index 69aa89b4..36e5f8a0 100644 --- a/branches/Ndi/core/al/al_qp.c +++ b/branches/Ndi/core/al/al_qp.c @@ -61,6 +61,7 @@ #include "al_verbs.h" #include "ib_common.h" +#include "kernel\al_proxy_ndi.h" #define UNBOUND_PORT_GUID 0 @@ -325,6 +326,10 @@ 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( NT_SUCCESS( status ) ) + status = ndi_qp_init( h_qp ); +#endif break; case IB_QPT_UNRELIABLE_DGRM: @@ -1123,6 +1128,9 @@ destroying_qp( deref_al_obj( &h_qp->obj ); } } +#ifdef CL_KERNEL + ndi_qp_deinit( h_qp ); +#endif /* Fall through. */ case IB_QPT_UNRELIABLE_DGRM: diff --git a/branches/Ndi/core/al/al_qp.h b/branches/Ndi/core/al/al_qp.h index 8b18d580..4c94dbb0 100644 --- a/branches/Ndi/core/al/al_qp.h +++ b/branches/Ndi/core/al/al_qp.h @@ -44,6 +44,7 @@ #include "al_mcast.h" #ifdef CL_KERNEL #include "al_smi.h" +#include "al_ndi_cm.h" #endif /* CL_KERNEL */ @@ -137,7 +138,7 @@ typedef struct _ib_qp cl_obj_rel_t recv_cq_rel; cl_obj_rel_t send_cq_rel; - ib_srq_handle_t h_srq; + ib_srq_handle_t h_srq; cl_obj_rel_t srq_rel; ib_pfn_event_cb_t pfn_event_cb; @@ -152,6 +153,10 @@ typedef struct _ib_qp ib_pfn_init_dgrm_svc_t pfn_init_dgrm_svc; ib_pfn_join_mcast_t pfn_join_mcast; +#ifdef CL_KERNEL + ndi_qp_csq_t *p_irp_que; +#endif + } ib_qp_t; diff --git a/branches/Ndi/core/al/kernel/SOURCES b/branches/Ndi/core/al/kernel/SOURCES index b36e48f5..6d682e3b 100644 --- a/branches/Ndi/core/al/kernel/SOURCES +++ b/branches/Ndi/core/al/kernel/SOURCES @@ -30,6 +30,8 @@ SOURCES= ibal.rc \ al_proxy_subnet.c \ al_proxy_verbs.c \ al_proxy_ndi.c \ + al_ndi_cq.c \ + al_ndi_cm.c \ al_sa_req.c \ al_smi.c \ ..\al.c \ diff --git a/branches/Ndi/core/al/kernel/al_cm_cep.c b/branches/Ndi/core/al/kernel/al_cm_cep.c index d4417683..c1b7bde7 100644 --- a/branches/Ndi/core/al/kernel/al_cm_cep.c +++ b/branches/Ndi/core/al/kernel/al_cm_cep.c @@ -1628,10 +1628,9 @@ __dreq_handler( if( status != IB_SUCCESS ) break; - status = __format_drep( p_cep, NULL, 0, (mad_cm_drep_t*)p_mad->p_mad_buf ); - if( status != IB_SUCCESS ) - break; - + p_mad->p_mad_buf->attr_id = CM_DREP_ATTR_ID; + /* __format_drep returns always SUCCESS while no private data */ + __format_drep( p_cep, NULL, 0, (mad_cm_drep_t*)p_mad->p_mad_buf ); __cep_send_mad( p_port_cep, p_mad ); break; @@ -3907,7 +3906,8 @@ __cleanup_cep( case CEP_STATE_LISTEN: /* Remove from listen map. */ cl_rbmap_remove_item( &gp_cep_mgr->listen_map, &p_cep->listen_item ); - if( !p_cep->p_cmp_buf ) + + if( p_cep->p_cmp_buf ) { cl_free( p_cep->p_cmp_buf ); p_cep->p_cmp_buf = NULL; diff --git a/branches/Ndi/core/al/kernel/al_cm_rdma.h b/branches/Ndi/core/al/kernel/al_cm_rdma.h index 953e0c5f..9d88c1cf 100644 --- a/branches/Ndi/core/al/kernel/al_cm_rdma.h +++ b/branches/Ndi/core/al/kernel/al_cm_rdma.h @@ -47,7 +47,5 @@ typedef struct _cm_rdma_req } PACK_SUFFIX cm_rdma_req_t; #define IB_REQ_CM_RDMA_SID_PREFIX 0x0000000001000000 -#define IB_REQ_CM_RDMA_SID_IP_PROT 252 /* a voluntary value */ -#define IB_REQ_CM_RDMA_SID_BASE (IB_REQ_CM_RDMA_SID_PREFIX + (IB_REQ_CM_RDMA_SID_IP_PROT<<16)) #endif diff --git a/branches/Ndi/core/al/kernel/al_ndi_cm.c b/branches/Ndi/core/al/kernel/al_ndi_cm.c new file mode 100644 index 00000000..5586e64d --- /dev/null +++ b/branches/Ndi/core/al/kernel/al_ndi_cm.c @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: al_proxy_verbs.c 548 2006-11-27 20:03:51Z leonidk $ + */ + + +#include +#include +#include +#include "al.h" +#include "al_debug.h" + +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "al_ndi_cm.tmh" +#endif + +#include "al_dev.h" +/* Get the internal definitions of apis for the proxy */ +#include "al_ca.h" +#include "ib_common.h" +#include "al_qp.h" +#include "al_cm_rdma.h" +#include "al_cm_conn.h" +#include "al_cm_cep.h" +#include "al_ndi_cm.h" + +uint32_t g_sa_timeout = 500; +uint32_t g_sa_retries = 4; +uint8_t g_qp_retries = QP_ATTRIB_RETRY_COUNT; +uint8_t g_pkt_life_modifier = 0; +uint8_t g_max_cm_retries = CM_RETRIES; + +/******************************************************************* + * + * CSQ + * + ******************************************************************/ + +static VOID __ndi_insert_irp( + IN PIO_CSQ Csq, + IN PIRP Irp + ) +{ + ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq; + + AL_ENTER( AL_DBG_NDI ); + InsertTailList( &p_ndi_csq->que, &Irp->Tail.Overlay.ListEntry ); + AL_EXIT( AL_DBG_NDI ); +} + +static VOID __ndi_remove_irp( + IN PIO_CSQ Csq, + IN PIRP Irp + ) +{ + UNUSED_PARAM( Csq ); + + AL_ENTER( AL_DBG_NDI ); + RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); + AL_EXIT( AL_DBG_NDI ); +} + +static PIRP __ndi_peek_next_irp( + IN PIO_CSQ Csq, + IN PIRP Irp, + IN PVOID PeekContext + ) +{ + PIRP nextIrp = NULL; + PLIST_ENTRY nextEntry; + PLIST_ENTRY listHead; + ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq; + + AL_ENTER( AL_DBG_NDI ); + + listHead = &p_ndi_csq->que; + + // + // If the IRP is NULL, we will start peeking from the listhead, else + // we will start from that IRP onwards. This is done under the + // assumption that new IRPs are always inserted at the tail. + // + + if(Irp == NULL) + nextEntry = listHead->Flink; + else + nextEntry = Irp->Tail.Overlay.ListEntry.Flink; + + while(nextEntry != listHead) { + nextIrp = CONTAINING_RECORD(nextEntry, IRP, Tail.Overlay.ListEntry); + + // + // If context is present, continue until you find a matching one. + // Else you break out as you got next one. + // + + if(PeekContext) + { + /* for now PeekContext is not used */ + } + else + { + break; + } + + nextIrp = NULL; + nextEntry = nextEntry->Flink; + } + + AL_EXIT( AL_DBG_NDI ); + return nextIrp; +} + +static VOID __ndi_acquire_lock( + IN PIO_CSQ Csq, + OUT PKIRQL 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 ); + + AL_ENTER( AL_DBG_NDI ); + cl_spinlock_acquire( &h_qp->obj.lock ); + AL_EXIT( AL_DBG_NDI ); +} + +static VOID __ndi_release_lock( + IN PIO_CSQ Csq, + 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 ); + + AL_ENTER( AL_DBG_NDI ); + cl_spinlock_release( &h_qp->obj.lock ); + AL_EXIT( AL_DBG_NDI ); +} + +static VOID __ndi_complete_cancelled_irp( + IN PIO_CSQ Csq, + IN PIRP Irp + ) +{ + ndi_qp_csq_t *p_ndi_csq = (ndi_qp_csq_t*)Csq; + ib_qp_handle_t h_qp = p_ndi_csq->h_qp; + + AL_ENTER( AL_DBG_NDI ); + + if ( (p_ndi_csq->state == NDI_CM_CONNECTING_REQ_SENT) ) + { + /* Cleanup from issuing CM REQ. */ + net32_t cid; + + ref_al_obj( &h_qp->obj ); + cid = cl_atomic_xchg( &((al_conn_qp_t*)h_qp)->cid, AL_INVALID_CID ); + if( cid == AL_INVALID_CID || al_destroy_cep( qp_get_al( h_qp ), cid, deref_al_obj ) != IB_SUCCESS ) + { + deref_al_obj( &h_qp->obj ); + } + } + + if ( (p_ndi_csq->state == NDI_CM_CONNECTING_ATS_SENT) || (p_ndi_csq->state == NDI_CM_CONNECTING_QPR_SENT) ) + { + /* Cleanup from issuing the query.will be performed in callbacks and then ioctl will be completed */ + p_ndi_csq->irp_cancelled = TRUE; + goto exit; + } + + cl_ioctl_complete( Irp, CL_CANCELED, 0 ); + deref_al_obj( &h_qp->obj ); +exit: + AL_EXIT( AL_DBG_NDI ); +} + +/* flush a queue of pending requests */ + +#pragma warning(disable:4706) +static inline void __ndi_flush_que( + IN ndi_qp_csq_t* p_ndi_csq, + IN NTSTATUS completion_code + ) +{ + PIRP Irp; + while( Irp = IoCsqRemoveNextIrp( &p_ndi_csq->csq, NULL ) ) + { + cl_ioctl_complete( Irp, completion_code, 0 ); + deref_al_obj( &p_ndi_csq->h_qp->obj ); + } +} +#pragma warning(default:4706) + +void +ndi_qp_flush_ques( + IN ib_qp_handle_t h_qp + ) +{ + AL_ENTER( AL_DBG_NDI ); + __ndi_flush_que( h_qp->p_irp_que, STATUS_CANCELLED ); + AL_EXIT( AL_DBG_NDI ); +} + + + +NTSTATUS +ndi_qp_init( + IN ib_qp_handle_t h_qp ) +{ + + NTSTATUS status; + + AL_ENTER( AL_DBG_NDI ); + + h_qp->p_irp_que = (ndi_qp_csq_t*)cl_zalloc(sizeof(ndi_qp_csq_t)); + if (!h_qp->p_irp_que) + { + status = STATUS_NO_MEMORY; + goto exit; + } + + status = IoCsqInitialize( &h_qp->p_irp_que->csq, + __ndi_insert_irp, __ndi_remove_irp, + __ndi_peek_next_irp, __ndi_acquire_lock, + __ndi_release_lock, __ndi_complete_cancelled_irp ); + if ( !NT_SUCCESS( status ) ) + goto exit; + + InitializeListHead( &h_qp->p_irp_que->que ); + h_qp->p_irp_que->h_qp = h_qp; + h_qp->p_irp_que->h_query = NULL; + h_qp->p_irp_que->state = NDI_CM_IDLE; + status = STATUS_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return status; +} + +void +ndi_qp_deinit( + IN ib_qp_handle_t h_qp ) +{ + if (h_qp->p_irp_que) + { + /* cancel pending IRPS for NDI type CQ */ + ndi_qp_flush_ques( h_qp ); + + /* free NDI context */ + cl_free( h_qp->p_irp_que ); + h_qp->p_irp_que = NULL; + } +} + + +/******************************************************************* + * + * Helpers + * + ******************************************************************/ + +static char * State2String(ndi_cm_state_t state) +{ + switch (state) + { + case NDI_CM_IDLE : return "NDI_CM_IDLE"; + case NDI_CM_CONNECTING_ATS_SENT : return "NDI_CM_CONNECTING_ATS_SENT"; + case NDI_CM_CONNECTING_QPR_SENT : return "NDI_CM_CONNECTING_QPR_SENT"; + case NDI_CM_CONNECTING_REQ_SENT : return "NDI_CM_CONNECTING_REQ_SENT"; + case NDI_CM_CONNECTING_REP_RCVD : return "NDI_CM_CONNECTING_REP_RCVD"; + case NDI_CM_CONNECTING_REJ_RCVD : return "NDI_CM_CONNECTING_REJ_RCVD"; + case NDI_CM_CONNECTING_RTU_SENT : return "NDI_CM_CONNECTING_RTU_SENT"; + case NDI_CM_CONNECTED : return "NDI_CM_CONNECTED"; + case NDI_CM_BOUND : return "NDI_CM_BOUND"; + case NDI_CM_LISTENING : return "NDI_CM_LISTENING"; + case NDI_CM_REP_SENT : return "NDI_CM_REP_SENT"; + case NDI_CM_CONNECTED_DREP_SENT : return "NDI_CM_CONNECTED_DREP_SENT"; + case NDI_CM_CONNECTED_DREQ_SENT : return "NDI_CM_CONNECTED_DREQ_SENT"; + default : + ASSERT(FALSE); + } + return "Unknown state"; +} + + + +/******************************************************************* + * + * REQ CM request + * + ******************************************************************/ + + +/* + * A user-specified callback that is invoked after receiving a connection + * request reply message (REP). + */ + + +static void +__ndi_proc_rep( + IN ib_cm_handle_t* const p_cm, + IN mad_cm_rep_t* const p_rep ) +{ + NTSTATUS status; + cl_ioctl_handle_t h_ioctl; + ndi_rep_rec_t *p_rep_rec = &p_cm->h_qp->p_irp_que->mad_info.rep; + ndi_qp_csq_t *p_ndi_csq = p_cm->h_qp->p_irp_que; + + AL_ENTER( AL_DBG_NDI ); + + AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_NDI ,("h_qp = 0x%p\n", p_cm->h_qp)); + + /* fill the rec data */ + memcpy( p_rep_rec->pdata, p_rep->pdata, sizeof(p_rep_rec->pdata) ); + + if ( p_ndi_csq->state != NDI_CM_CONNECTING_REQ_SENT) + { + // This is not the state that we waited for, not much that we can do + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("Not the expected state %s\n", State2String( p_ndi_csq->state ))); + ASSERT(FALSE); + goto exit; + } + + p_ndi_csq->state = NDI_CM_CONNECTING_REP_RCVD; + status = STATUS_SUCCESS; + + h_ioctl = IoCsqRemoveNextIrp( &p_ndi_csq->csq, NULL ); + if (!h_ioctl) + goto exit; + cl_ioctl_complete( h_ioctl, status, 0 ); + deref_al_obj( &p_cm->h_qp->obj ); +exit: + AL_EXIT( AL_DBG_NDI ); +} + +/* + * A user-specified callback that is invoked after receiving a connection + * rejection message (REJ). + */ + + +void +__ndi_proc_rej( + IN const ib_cm_handle_t* const p_cm, + IN const mad_cm_rej_t* const p_rej ) +{ + net32_t cid; + NTSTATUS status; + cl_ioctl_handle_t h_ioctl; + ndi_rej_rec_t *p_rej_rec; + ndi_qp_csq_t *p_ndi_csq; + + AL_ENTER( AL_DBG_NDI ); + + if( !p_cm->h_qp ) + goto exit; + p_rej_rec = &p_cm->h_qp->p_irp_que->mad_info.rej; + p_ndi_csq = p_cm->h_qp->p_irp_que; + + /* fill the rej data */ + memcpy( p_rej_rec->pdata, p_rej->pdata, sizeof(p_rej_rec->pdata)); + + AL_PRINT(TRACE_LEVEL_INFORMATION, AL_DBG_NDI, + ("h_qp %p connect reject, reason=%d\n", p_cm->h_qp, cl_ntoh16(p_rej->reason) ) ); + + //TODO: do we need to do it here ? Can we do it from DISPATCH_LEVEL ? + ref_al_obj( &p_cm->h_qp->obj ); + cid = cl_atomic_xchg( &((al_conn_qp_t*)p_cm->h_qp)->cid, AL_INVALID_CID ); + CL_ASSERT( cid == p_cm->cid || cid == AL_INVALID_CID ); + if( cid == AL_INVALID_CID || + al_destroy_cep( p_cm->h_al, cid, deref_al_obj ) != IB_SUCCESS ) + { + deref_al_obj( &p_cm->h_qp->obj ); + } + + if ( p_ndi_csq->state != NDI_CM_CONNECTING_REQ_SENT) + { + // This is not the state that we waited for, not much that we can + // do. (This might happen in shutdown) + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("Not the expected state %s\n", State2String( p_ndi_csq->state ))); + ASSERT(FALSE); + goto exit; + } + + p_ndi_csq->state = NDI_CM_CONNECTING_REJ_RCVD; + status = (p_rej->reason == IB_REJ_TIMEOUT) ? STATUS_TIMEOUT : STATUS_CONNECTION_REFUSED; + + h_ioctl = IoCsqRemoveNextIrp( &p_ndi_csq->csq, NULL ); + if (!h_ioctl) + goto exit; + cl_ioctl_complete( h_ioctl, status, 0 ); + deref_al_obj( &p_cm->h_qp->obj ); +exit: + AL_EXIT( AL_DBG_NDI ); +} + + + +static void +__ndi_proc_conn( + IN ib_cm_handle_t* const p_cm, + IN ib_mad_t* const p_mad ) +{ + AL_ENTER( AL_DBG_CM ); + + /* Success indicates a receive. */ + switch( p_mad->attr_id ) + { + case CM_REP_ATTR_ID: + CL_ASSERT( ((al_conn_qp_t*)p_cm->h_qp)->cid == (int32_t)p_cm->cid || + ((al_conn_qp_t*)p_cm->h_qp)->cid == AL_INVALID_CID ); + __ndi_proc_rep( p_cm, (mad_cm_rep_t*)p_mad ); + break; + + case CM_REJ_ATTR_ID: + __ndi_proc_rej( p_cm, (mad_cm_rej_t*)p_mad ); + break; + +#if 0 + case CM_REQ_ATTR_ID: + CL_ASSERT( ((al_conn_qp_t*)p_cm->h_qp)->cid == (int32_t)p_cm->cid || + ((al_conn_qp_t*)p_cm->h_qp)->cid == AL_INVALID_CID ); + __proc_peer_req( p_cm, (mad_cm_req_t*)p_mad ); + break; + + case CM_RTU_ATTR_ID: + CL_ASSERT( ((al_conn_qp_t*)p_cm->h_qp)->cid == (int32_t)p_cm->cid || + ((al_conn_qp_t*)p_cm->h_qp)->cid == AL_INVALID_CID ); + __proc_rtu( p_cm, (mad_cm_rtu_t*)p_mad ); + break; + + case CM_DREQ_ATTR_ID: + CL_ASSERT( ((al_conn_qp_t*)p_cm->h_qp)->cid == (int32_t)p_cm->cid || + ((al_conn_qp_t*)p_cm->h_qp)->cid == AL_INVALID_CID ); + __proc_dreq( p_cm, (mad_cm_dreq_t*)p_mad ); + break; + + case CM_DREP_ATTR_ID: + CL_ASSERT( ((al_conn_qp_t*)p_cm->h_qp)->cid == (int32_t)p_cm->cid || + ((al_conn_qp_t*)p_cm->h_qp)->cid == AL_INVALID_CID ); + __proc_drep( p_cm, (mad_cm_drep_t*)p_mad ); + break; +#endif + + default: + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("Invalid CM recv MAD attribute ID %d.\n", p_mad->attr_id) ); + } + + AL_EXIT( AL_DBG_CM ); +} + +static void +__ndi_cm_handler( + IN const ib_al_handle_t h_al, + IN const net32_t cid ) +{ + ib_api_status_t status; + void* __ptr64 context; + net32_t new_cid; + ib_mad_element_t *p_mad; + ib_cm_handle_t h_cm; + + AL_ENTER( AL_DBG_CM ); + + for( status = al_cep_poll( h_al, cid, &context, &new_cid, &p_mad ); + status == IB_SUCCESS; + status = al_cep_poll( h_al, cid, &context, &new_cid, &p_mad ) ) + { +#if 0 + /* Something to do - WOOT!!! */ + if( new_cid != AL_INVALID_CID ) + { + __proc_listen( (al_listen_t* __ptr64)context, + new_cid, ib_get_mad_buf( p_mad ) ); + } + else if( p_mad->status != IB_SUCCESS ) + { + /* Context is a QP handle, and a sent MAD timed out. */ + __proc_failed_send( + (ib_qp_handle_t)context, ib_get_mad_buf( p_mad ) ); + } + else +#endif + { + h_cm.h_al = h_al; + h_cm.cid = cid; + h_cm.h_qp = (ib_qp_handle_t)context; + __ndi_proc_conn( &h_cm, ib_get_mad_buf( p_mad ) ); + } + ib_put_mad( p_mad ); + } +} + +static void +__ndi_fill_cm_req( + IN ib_qp_handle_t const h_qp, + IN ual_ndi_req_cm_ioctl_in_t *p_req, + IN ib_path_rec_t *p_path_rec, + IN ib_cm_req_t *p_cm_req) +{ + cm_rdma_req_t *p_rdma = (cm_rdma_req_t*)p_req->pdata; + + 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; + + p_cm_req->p_req_pdata = (uint8_t *)p_rdma; + p_cm_req->req_length = sizeof(cm_rdma_req_t); + + p_cm_req->qp_type = IB_QPT_RELIABLE_CONN; + p_cm_req->h_qp = h_qp; + p_cm_req->resp_res = QP_ATTRIB_RESPONDER_RESOURCES; + p_cm_req->init_depth = QP_ATTRIB_INITIATOR_DEPTH; + + p_cm_req->remote_resp_timeout = + ib_path_rec_pkt_life( p_path_rec ) + CM_REMOTE_TIMEOUT; + if( p_cm_req->remote_resp_timeout > 0x1F ) + p_cm_req->remote_resp_timeout = 0x1F; + else if( p_cm_req->remote_resp_timeout < CM_MIN_REMOTE_TIMEOUT ) + p_cm_req->remote_resp_timeout = CM_MIN_REMOTE_TIMEOUT; + + p_cm_req->flow_ctrl = TRUE; /* HCAs must support end-to-end flow control. */ + + p_cm_req->local_resp_timeout = + ib_path_rec_pkt_life( p_path_rec ) + CM_LOCAL_TIMEOUT; + if( p_cm_req->local_resp_timeout > 0x1F ) + p_cm_req->local_resp_timeout = 0x1F; + 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 ); +} + +static void AL_API +__ndi_pr_query_cb( + ib_query_rec_t *p_query_rec ) +{ + ib_api_status_t status; + cl_ioctl_handle_t h_ioctl; + ib_cm_req_t cm_req; + uint8_t pkt_life; + ib_qp_mod_t qp_mod; + ib_path_rec_t *p_path_rec = ib_get_query_path_rec( p_query_rec->p_result_mad, 0 ); + ual_ndi_req_cm_ioctl_in_t *p_req = (ual_ndi_req_cm_ioctl_in_t* __ptr64)p_query_rec->query_context; + ib_qp_handle_t h_qp = (ib_qp_handle_t)p_req->h_qp; + net32_t cid; + + AL_ENTER( AL_DBG_NDI ); + + AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI, + ("status is %d, count is %d\n", p_query_rec->status, + p_query_rec->result_cnt) ); + + h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL ); + if (!h_ioctl) + goto exit; + + if ( h_qp->p_irp_que->irp_cancelled ) + goto err_irp_complete; + + if( p_query_rec->status != IB_SUCCESS || !p_query_rec->result_cnt ) + goto err_irp_complete; + + /* Path Record has been received ! */ + + /* fix packet life */ + CL_ASSERT( p_path_rec ); + pkt_life = ib_path_rec_pkt_life( p_path_rec ) + g_pkt_life_modifier; + if( pkt_life > 0x1F ) + pkt_life = 0x1F; + + p_path_rec->pkt_life &= IB_PATH_REC_SELECTOR_MASK; + p_path_rec->pkt_life |= pkt_life; + + /* Copy the path record */ + h_qp->p_irp_que->path_rec = *p_path_rec; + + /* Get a CEP and bind it to the QP. */ + status = al_create_cep( qp_get_al( h_qp ), __ndi_cm_handler, h_qp, &cid ); + if( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_create_cep returned %s.\n", ib_get_err_str( status )) ); + goto err_irp_complete; + } + + /* Format ib_cm_req_t structure */ + __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req ); + + /* prepare CEP for connection */ + status = al_cep_pre_req( qp_get_al( h_qp ), + ((al_conn_qp_t*)h_qp)->cid, &cm_req, &qp_mod ); + if( status != IB_SUCCESS ) + { + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("al_cep_pre_req returned %s.\n", ib_get_err_str( status )) ); + goto err_cep_destroy; + } + + /* insert IRP in the queue */ + h_qp->p_irp_que->state = NDI_CM_CONNECTING_REQ_SENT; + IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL ); + + /* send CM REQ */ + status = al_cep_send_req( qp_get_al( h_qp ), cid ); + if( status != IB_SUCCESS ) + goto err_irp_remove; + + /* SUCCESS ! */ + goto exit; + +err_irp_remove: + h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL ); + +err_cep_destroy: + al_destroy_cep( qp_get_al( h_qp ), cid, NULL ); + +err_irp_complete: + cl_ioctl_complete( h_ioctl, STATUS_HOST_UNREACHABLE, 0 ); + deref_al_obj( &h_qp->obj ); + +exit: + if( p_query_rec->p_result_mad ) + ib_put_mad( p_query_rec->p_result_mad ); + + AL_EXIT( AL_DBG_NDI ); +} + + + +/* Synchronously query the SA for a GUID. Return 0 on success. */ +cl_status_t +__ndi_pr_query( + IN cl_ioctl_handle_t h_ioctl, + IN ib_query_rec_t *p_query_rec ) +{ + cl_status_t cl_status; + ib_service_record_t *service_record; + ib_gid_pair_t user_query; + ib_query_handle_t query_handle; + ib_query_req_t query_req; + ib_api_status_t status; + ib_net64_t dest_port_guid; + ual_ndi_req_cm_ioctl_in_t *p_req = (ual_ndi_req_cm_ioctl_in_t* __ptr64)p_query_rec->query_context; + ib_qp_handle_t h_qp = (ib_qp_handle_t)p_req->h_qp; + + AL_ENTER( AL_DBG_NDI ); + + service_record = ib_get_query_svc_rec( p_query_rec->p_result_mad, 0 ); + dest_port_guid = ib_gid_get_guid( &service_record->service_gid ); + + CL_ASSERT( service_record != NULL ); + + query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS; + query_req.p_query_input = &user_query; + query_req.port_guid = p_req->guid; + query_req.timeout_ms = g_sa_timeout; + query_req.retry_cnt = g_sa_retries; + query_req.flags = 0; /* IB_FLAGS_SYNC */ + query_req.query_context = p_req; + query_req.pfn_query_cb = __ndi_pr_query_cb; + + ib_gid_set_default( &user_query.src_gid, p_req->guid ); + ib_gid_set_default( &user_query.dest_gid, dest_port_guid ); + + AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_ERROR, + ("Query for path from %I64x to %I64x\n", + p_req->guid, dest_port_guid) ); + + /* insert IRP in the queue */ + h_qp->p_irp_que->state = NDI_CM_CONNECTING_QPR_SENT; + IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL ); + + status = ib_query( qp_get_al( h_qp ), &query_req, &query_handle ); + + if( status != IB_SUCCESS ) + { + h_qp->p_irp_que->state = NDI_CM_IDLE; + IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL ); + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) ); + cl_status = CL_ERROR; + goto exit; + } + + cl_status = CL_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + + +static void AL_API +__ndi_ats_query_cb( + IN ib_query_rec_t *p_query_rec ) +{ + cl_ioctl_handle_t h_ioctl; + cl_status_t cl_status; + ual_ndi_req_cm_ioctl_in_t *p_req = (ual_ndi_req_cm_ioctl_in_t* __ptr64)p_query_rec->query_context; + ib_qp_handle_t h_qp = (ib_qp_handle_t)p_req->h_qp; + + AL_ENTER( AL_DBG_NDI ); + + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, + ("status is %d, count is %d\n", p_query_rec->status, + p_query_rec->result_cnt) ); + + h_ioctl = IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL ); + if (!h_ioctl) + goto exit; + + if ( h_qp->p_irp_que->irp_cancelled ) + goto err_irp_complete; + + if( p_query_rec->status != IB_SUCCESS || !p_query_rec->result_cnt ) + goto err_irp_complete; + + cl_status = __ndi_pr_query( h_ioctl, p_query_rec ); + if (cl_status != CL_SUCCESS) + goto err_irp_complete; + + /* SUCCESS */ + goto exit; + +err_irp_complete: + cl_ioctl_complete( h_ioctl, STATUS_HOST_UNREACHABLE, 0 ); + deref_al_obj( &h_qp->obj ); + +exit: + if( p_query_rec->p_result_mad ) + ib_put_mad( p_query_rec->p_result_mad ); + + AL_EXIT( AL_DBG_NDI ); +} + +/* Synchronously query the SA for a GUID. Return 0 on success. */ +cl_status_t +__ndi_ats_query( + IN ib_qp_handle_t const h_qp, + IN cl_ioctl_handle_t h_ioctl, + IN ual_ndi_req_cm_ioctl_in_t *p_req ) +{ + ib_user_query_t user_query; + ib_service_record_t service_record; + ib_query_req_t query_req; + ib_api_status_t status; + cl_status_t cl_status; + cm_rdma_req_t *p_rdma = (cm_rdma_req_t*)p_req->pdata; + + AL_ENTER( AL_DBG_NDI ); + + query_req.query_type = IB_QUERY_USER_DEFINED; + query_req.p_query_input = &user_query; + query_req.port_guid = p_req->guid; + query_req.timeout_ms = g_sa_timeout; + query_req.retry_cnt = g_sa_retries; + query_req.flags = 0; /* IB_FLAGS_SYNC */ + query_req.query_context = p_req; + query_req.pfn_query_cb = __ndi_ats_query_cb; + + /* TODO: which method one is correct? */ + user_query.method = IB_MAD_METHOD_GETTABLE; + //user_query.method = IB_MAD_METHOD_GET; + user_query.attr_id = IB_MAD_ATTR_SERVICE_RECORD; + user_query.attr_size = sizeof(ib_service_record_t); + user_query.comp_mask = + IB_SR_COMPMASK_SPKEY | + IB_SR_COMPMASK_SLEASE | + IB_SR_COMPMASK_SNAME | + IB_SR_COMPMASK_SDATA8_12 | + IB_SR_COMPMASK_SDATA8_13 | IB_SR_COMPMASK_SDATA8_14 | IB_SR_COMPMASK_SDATA8_15; + + user_query.p_attr = &service_record; + + memset( &service_record, 0, sizeof(service_record) ); + service_record.service_pkey = cl_hton16( IB_DEFAULT_PKEY ); + service_record.service_data8[12] = (uint8_t) (p_rdma->dst_ip_addr[4] >> 0); + service_record.service_data8[13] = (uint8_t) (p_rdma->dst_ip_addr[4] >> 8); + service_record.service_data8[14] = (uint8_t) (p_rdma->dst_ip_addr[4] >> 16); + service_record.service_data8[15] = (uint8_t) (p_rdma->dst_ip_addr[4] >> 24); + service_record.service_lease = 0xFFFFFFFF; + strcpy( (void*)service_record.service_name, ATS_NAME ); + + /* insert IRP in the queue */ + ref_al_obj( &h_qp->obj ); + h_qp->p_irp_que->state = NDI_CM_CONNECTING_ATS_SENT; + IoCsqInsertIrp( &h_qp->p_irp_que->csq, h_ioctl, NULL ); + + /* query SA */ + status = ib_query( qp_get_al( h_qp ), &query_req, &h_qp->p_irp_que->h_query ); + if( status != IB_SUCCESS ) + { + h_qp->p_irp_que->state = NDI_CM_IDLE; + IoCsqRemoveNextIrp( &h_qp->p_irp_que->csq, NULL ); + AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("ib_query failed (%d)\n", status) ); + cl_status = CL_ERROR; + goto exit; + } + + cl_status = CL_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + +cl_status_t +ndi_req_cm( + IN ib_qp_handle_t const h_qp, + IN cl_ioctl_handle_t h_ioctl, + IN ual_ndi_req_cm_ioctl_in_t *p_req + ) +{ + cl_status_t cl_status; + + AL_ENTER( AL_DBG_NDI ); + + /* check outstanding request */ + __ndi_acquire_lock( &h_qp->p_irp_que->csq, NULL); + if (!__ndi_peek_next_irp( &h_qp->p_irp_que->csq, NULL, NULL )) + { + cl_status = STATUS_CONNECTION_ACTIVE; + __ndi_release_lock( &h_qp->p_irp_que->csq, 0 ); + goto exit; + } + __ndi_release_lock( &h_qp->p_irp_que->csq, 0 ); + + /* send ATS request */ + cl_status = __ndi_ats_query( h_qp, h_ioctl, p_req ); + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + + +/******************************************************************* + * + * REP CM request + * + ******************************************************************/ + + +cl_status_t +ndi_rep_cm( + IN ib_qp_handle_t const h_qp, + IN net32_t const cid, + IN cl_ioctl_handle_t h_ioctl, + IN ual_ndi_rep_cm_ioctl_in_t *p_ndi_rep_cm + ) +{ + cl_status_t cl_status = STATUS_SUCCESS; + + UNUSED_PARAM(h_qp); + UNUSED_PARAM(cid); + UNUSED_PARAM(h_ioctl); + UNUSED_PARAM(p_ndi_rep_cm); + + AL_ENTER( AL_DBG_NDI ); + + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + + + diff --git a/branches/Ndi/core/al/kernel/al_ndi_cm.h b/branches/Ndi/core/al/kernel/al_ndi_cm.h new file mode 100644 index 00000000..5a478ead --- /dev/null +++ b/branches/Ndi/core/al/kernel/al_ndi_cm.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: al_proxy.h 33 2005-07-11 19:51:17Z ftillier $ + */ + +/* + * Abstract: + * This header file defines data structures for the kernel-mode NDI support + * + * Environment: + * Kernel . + */ + + +#ifndef _AL_NDI_CM_H_ +#define _AL_NDI_CM_H_ + +#include "complib/cl_ioctl_osd.h" + +/* QP creation parameters */ +#define QP_ATTRIB_RESPONDER_RESOURCES 4 +#define QP_ATTRIB_INITIATOR_DEPTH 4 +#define QP_ATTRIB_RETRY_COUNT 6 +#define QP_ATTRIB_RNR_RETRY 7 +#define QP_ATTRIB_RNR_NAK_TIMEOUT 8 /* 16 ms */ + +#define QP_ATTRIB_SQ_DEPTH 16 + +/* CM timeouts */ +#define CM_MIN_LOCAL_TIMEOUT (18) +#define CM_LOCAL_TIMEOUT (1) +#define CM_MIN_REMOTE_TIMEOUT (18) +#define CM_REMOTE_TIMEOUT (2) +#define CM_RETRIES 4 + +typedef enum _ndi_cm_state +{ + NDI_CM_IDLE, + NDI_CM_CONNECTING_ATS_SENT, // ATS = Address Translation Service + NDI_CM_CONNECTING_QPR_SENT, // QPR = Query path record + NDI_CM_CONNECTING_REQ_SENT, + NDI_CM_CONNECTING_REP_RCVD, + NDI_CM_CONNECTING_REJ_RCVD, + NDI_CM_CONNECTING_RTU_SENT, + NDI_CM_CONNECTED, + NDI_CM_BOUND, + NDI_CM_LISTENING, + NDI_CM_REP_SENT, + NDI_CM_CONNECTED_DREP_SENT, + NDI_CM_CONNECTED_DREQ_SENT, +} ndi_cm_state_t; + +typedef struct _ib_qp ib_qp_t; + +typedef struct _ndi_rep_rec +{ + uint8_t pdata[IB_REP_CM_RDMA_PDATA_SIZE]; +} ndi_rep_rec_t; + +typedef struct _ndi_rej_rec +{ + uint8_t pdata[IB_REP_CM_RDMA_PDATA_SIZE]; +} ndi_rej_rec_t; + +#pragma warning(disable:4201) +typedef struct _ndi_mad_info +{ + union + { + ndi_rep_rec_t rep; + ndi_rej_rec_t rej; + }; +} ndi_mad_info_t; +#pragma warning(default:4201) + +typedef struct _ndi_qp_csq +{ + IO_CSQ csq; + ib_qp_t* h_qp; + ib_query_handle_t h_query; + ib_path_rec_t path_rec; + LIST_ENTRY que; + ndi_cm_state_t state; + boolean_t shutdown_called; + boolean_t close_called; + boolean_t disconnect_sent; + boolean_t irp_cancelled; + ndi_mad_info_t mad_info; + uint32_t resv; +} ndi_qp_csq_t; + + +cl_status_t +ndi_req_cm( + IN ib_qp_handle_t const h_qp, + IN cl_ioctl_handle_t h_ioctl, + IN ual_ndi_req_cm_ioctl_in_t *p_req + ); + +cl_status_t +ndi_rep_cm( + IN ib_qp_handle_t const h_qp, + IN net32_t const cid, + IN cl_ioctl_handle_t h_ioctl, + IN ual_ndi_rep_cm_ioctl_in_t *p_ndi_rep_cm + ); + +void +ndi_qp_flush_ques( + IN ib_qp_handle_t h_qp ); + + +NTSTATUS +ndi_qp_init( + IN ib_qp_handle_t h_qp ); + +void +ndi_qp_deinit( + IN ib_qp_handle_t h_qp ); + +#endif + diff --git a/branches/Ndi/core/al/kernel/al_ndi_cq.c b/branches/Ndi/core/al/kernel/al_ndi_cq.c new file mode 100644 index 00000000..b4ef65b5 --- /dev/null +++ b/branches/Ndi/core/al/kernel/al_ndi_cq.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: al_proxy_verbs.c 548 2006-11-27 20:03:51Z leonidk $ + */ + + +#include +#include +#include +#include "al.h" +#include "al_debug.h" + +#if defined(EVENT_TRACING) +#ifdef offsetof +#undef offsetof +#endif +#include "al_ndi_cq.tmh" +#endif + +#include "al_dev.h" +/* Get the internal definitions of apis for the proxy */ +#include "al_ca.h" +#include "al_cq.h" +#include "ib_common.h" + +/******************************************************************* + * + * Helpers + * + ******************************************************************/ + +#pragma warning(disable:4706) +static inline void __ndi_flush_que( + IN ndi_cq_csq_t* p_ndi_csq, + IN NTSTATUS completion_code + ) +{ + PIRP Irp; + while( Irp = IoCsqRemoveNextIrp( &p_ndi_csq->csq, NULL ) ) + { + cl_ioctl_complete( Irp, completion_code, 0 ); + deref_al_obj( &p_ndi_csq->h_cq->obj ); + } +} +#pragma warning(default:4706) + +/******************************************************************* + * + * Callbacks + * + ******************************************************************/ + +void ndi_cq_compl_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ) +{ + UNUSED_PARAM( cq_context ); + AL_ENTER( AL_DBG_NDI ); + __ndi_flush_que( &h_cq->compl, STATUS_SUCCESS ); + AL_EXIT( AL_DBG_NDI ); +} + +void ndi_cq_error_cb( + IN ib_async_event_rec_t *p_err_rec) +{ + ib_cq_handle_t h_cq = p_err_rec->handle.h_cq; + AL_ENTER( AL_DBG_NDI ); + __ndi_flush_que( &h_cq->compl, STATUS_INTERNAL_ERROR ); + __ndi_flush_que( &h_cq->error, STATUS_INTERNAL_ERROR ); + AL_EXIT( AL_DBG_NDI ); +} + +/******************************************************************* + * + * Public routines + * + ******************************************************************/ + +/* flush a queue of pending requests */ +void +ndi_cq_flush_ques( + IN ib_cq_handle_t h_cq + ) +{ + AL_ENTER( AL_DBG_NDI ); + if ( h_cq->pfn_user_comp_cb == ndi_cq_compl_cb ) + { + __ndi_flush_que( &h_cq->compl, STATUS_CANCELLED ); + __ndi_flush_que( &h_cq->error, STATUS_CANCELLED ); + } + AL_EXIT( AL_DBG_NDI ); +} + + +/******************************************************************* + * + * CSQ + * + ******************************************************************/ + +static VOID __ndi_insert_irp( + IN PIO_CSQ Csq, + IN PIRP Irp + ) +{ + ndi_cq_csq_t *p_ndi_csq = (ndi_cq_csq_t*)Csq; + + AL_ENTER( AL_DBG_NDI ); + InsertTailList( &p_ndi_csq->que, &Irp->Tail.Overlay.ListEntry ); + AL_EXIT( AL_DBG_NDI ); +} + +static VOID __ndi_remove_irp( + IN PIO_CSQ Csq, + IN PIRP Irp + ) +{ + UNUSED_PARAM( Csq ); + + AL_ENTER( AL_DBG_NDI ); + RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); + AL_EXIT( AL_DBG_NDI ); +} + +static PIRP __ndi_peek_next_irp( + IN PIO_CSQ Csq, + IN PIRP Irp, + IN PVOID PeekContext + ) +{ + PIRP nextIrp = NULL; + PLIST_ENTRY nextEntry; + PLIST_ENTRY listHead; + ndi_cq_csq_t *p_ndi_csq = (ndi_cq_csq_t*)Csq; + + AL_ENTER( AL_DBG_NDI ); + + listHead = &p_ndi_csq->que; + + // + // If the IRP is NULL, we will start peeking from the listhead, else + // we will start from that IRP onwards. This is done under the + // assumption that new IRPs are always inserted at the tail. + // + + if(Irp == NULL) + nextEntry = listHead->Flink; + else + nextEntry = Irp->Tail.Overlay.ListEntry.Flink; + + while(nextEntry != listHead) { + nextIrp = CONTAINING_RECORD(nextEntry, IRP, Tail.Overlay.ListEntry); + + // + // If context is present, continue until you find a matching one. + // Else you break out as you got next one. + // + + if(PeekContext) + { + /* for now PeekContext is not used */ + } + else + { + break; + } + + nextIrp = NULL; + nextEntry = nextEntry->Flink; + } + + AL_EXIT( AL_DBG_NDI ); + return nextIrp; +} + +static VOID __ndi_acquire_lock( + IN PIO_CSQ Csq, + OUT PKIRQL Irql + ) +{ + ndi_cq_csq_t *p_ndi_csq = (ndi_cq_csq_t*)Csq; + ib_cq_handle_t h_cq = p_ndi_csq->h_cq; + UNUSED_PARAM( Irql ); + + AL_ENTER( AL_DBG_NDI ); + cl_spinlock_acquire( &h_cq->obj.lock ); + AL_EXIT( AL_DBG_NDI ); +} + +static VOID __ndi_release_lock( + IN PIO_CSQ Csq, + IN KIRQL Irql + ) +{ + ndi_cq_csq_t *p_ndi_csq = (ndi_cq_csq_t*)Csq; + ib_cq_handle_t h_cq = p_ndi_csq->h_cq; + UNUSED_PARAM( Irql ); + + AL_ENTER( AL_DBG_NDI ); + cl_spinlock_release( &h_cq->obj.lock ); + AL_EXIT( AL_DBG_NDI ); +} + +static VOID __ndi_complete_cancelled_irp( + IN PIO_CSQ Csq, + IN PIRP Irp + ) +{ + ndi_cq_csq_t *p_ndi_csq = (ndi_cq_csq_t*)Csq; + ib_cq_handle_t h_cq = p_ndi_csq->h_cq; + + AL_ENTER( AL_DBG_NDI ); + cl_ioctl_complete( Irp, CL_CANCELED, 0 ); + deref_al_obj( &h_cq->obj ); + AL_EXIT( AL_DBG_NDI ); +} + +NTSTATUS +ndi_cq_init( + IN ib_cq_handle_t h_cq ) +{ + + NTSTATUS status; + + AL_ENTER( AL_DBG_NDI ); + + status = IoCsqInitialize( &h_cq->compl.csq, + __ndi_insert_irp, __ndi_remove_irp, + __ndi_peek_next_irp, __ndi_acquire_lock, + __ndi_release_lock, __ndi_complete_cancelled_irp ); + if ( !NT_SUCCESS( status ) ) + goto exit; + + status = IoCsqInitialize( &h_cq->error.csq, + __ndi_insert_irp, __ndi_remove_irp, + __ndi_peek_next_irp, __ndi_acquire_lock, + __ndi_release_lock, __ndi_complete_cancelled_irp ); + if ( !NT_SUCCESS( status ) ) + goto exit; + + InitializeListHead( &h_cq->compl.que ); + InitializeListHead( &h_cq->error.que ); + h_cq->compl.h_cq = h_cq; + h_cq->error.h_cq = h_cq; + status = STATUS_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return status; +} + + + diff --git a/branches/Ndi/core/al/kernel/al_ndi_cq.h b/branches/Ndi/core/al/kernel/al_ndi_cq.h new file mode 100644 index 00000000..466722d0 --- /dev/null +++ b/branches/Ndi/core/al/kernel/al_ndi_cq.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005 SilverStorm Technologies. All rights reserved. + * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. + * + * This software is available to you under the OpenIB.org BSD license + * below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * $Id: al_proxy.h 33 2005-07-11 19:51:17Z ftillier $ + */ + +/* + * Abstract: + * This header file defines data structures for the kernel-mode NDI support + * + * Environment: + * Kernel . + */ + + +#ifndef _AL_NDI_CQ_H_ +#define _AL_NDI_CQ_H_ + +void +ndi_cq_flush_ques( + IN ib_cq_handle_t h_cq ); + +NTSTATUS +ndi_cq_init( + IN ib_cq_handle_t h_cq ); + +void +ndi_cq_compl_cb( + IN const ib_cq_handle_t h_cq, + IN void *cq_context ); + +void +ndi_cq_error_cb( + IN ib_async_event_rec_t *p_err_rec ); + +#endif diff --git a/branches/Ndi/core/al/kernel/al_proxy_ndi.c b/branches/Ndi/core/al/kernel/al_proxy_ndi.c index 6af10b05..86f4226e 100644 --- a/branches/Ndi/core/al/kernel/al_proxy_ndi.c +++ b/branches/Ndi/core/al/kernel/al_proxy_ndi.c @@ -35,7 +35,9 @@ #include #include #include "al.h" +#include "al_qp.h" #include "al_debug.h" +#include "al_cm_cep.h" #if defined(EVENT_TRACING) #ifdef offsetof @@ -47,237 +49,10 @@ #include "al_dev.h" /* Get the internal definitions of apis for the proxy */ #include "al_ca.h" -#include "al_pd.h" -#include "al_cq.h" #include "ib_common.h" #include "al_proxy_ndi.h" - -/******************************************************************* - * - * Helpers - * - ******************************************************************/ - -#pragma warning(disable:4706) -static inline void __ndi_flush_que( - IN ndi_io_csq_t* p_ndi_csq, - IN NTSTATUS completion_code - ) -{ - PIRP Irp; - while( Irp = IoCsqRemoveNextIrp( &p_ndi_csq->csq, NULL ) ) - { - cl_ioctl_complete( Irp, completion_code, 0 ); - deref_al_obj( &p_ndi_csq->h_cq->obj ); - } -} -#pragma warning(default:4706) - -/******************************************************************* - * - * Callbacks - * - ******************************************************************/ - -static void __ndi_cq_compl_cb( - IN const ib_cq_handle_t h_cq, - IN void *cq_context ) -{ - UNUSED_PARAM( cq_context ); - AL_ENTER( AL_DBG_NDI ); - __ndi_flush_que( &h_cq->compl, STATUS_SUCCESS ); - AL_EXIT( AL_DBG_NDI ); -} - -static void __ndi_cq_error_cb( - IN ib_async_event_rec_t *p_err_rec) -{ - ib_cq_handle_t h_cq = p_err_rec->handle.h_cq; - AL_ENTER( AL_DBG_NDI ); - __ndi_flush_que( &h_cq->compl, STATUS_INTERNAL_ERROR ); - __ndi_flush_que( &h_cq->error, STATUS_INTERNAL_ERROR ); - AL_EXIT( AL_DBG_NDI ); -} - -/******************************************************************* - * - * Public routines - * - ******************************************************************/ - -/* flush a queue of pending requests */ -void -proxy_ndi_flush_ques( - IN ib_cq_handle_t h_cq - ) -{ - AL_ENTER( AL_DBG_NDI ); - if ( h_cq->pfn_user_comp_cb == __ndi_cq_compl_cb ) - { - __ndi_flush_que( &h_cq->compl, STATUS_CANCELLED ); - __ndi_flush_que( &h_cq->error, STATUS_CANCELLED ); - } - AL_EXIT( AL_DBG_NDI ); -} - - -/******************************************************************* - * - * CSQ - * - ******************************************************************/ - -static VOID __ndi_insert_irp( - IN PIO_CSQ Csq, - IN PIRP Irp - ) -{ - ndi_io_csq_t *p_ndi_csq = (ndi_io_csq_t*)Csq; - - AL_ENTER( AL_DBG_NDI ); - InsertTailList( &p_ndi_csq->que, &Irp->Tail.Overlay.ListEntry ); - AL_EXIT( AL_DBG_NDI ); -} - -static VOID __ndi_remove_irp( - IN PIO_CSQ Csq, - IN PIRP Irp - ) -{ - UNUSED_PARAM( Csq ); - - AL_ENTER( AL_DBG_NDI ); - RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); - AL_EXIT( AL_DBG_NDI ); -} - -static PIRP __ndi_peek_next_irp( - IN PIO_CSQ Csq, - IN PIRP Irp, - IN PVOID PeekContext - ) -{ - PIRP nextIrp = NULL; - PLIST_ENTRY nextEntry; - PLIST_ENTRY listHead; - ndi_io_csq_t *p_ndi_csq = (ndi_io_csq_t*)Csq; - - AL_ENTER( AL_DBG_NDI ); - - listHead = &p_ndi_csq->que; - - // - // If the IRP is NULL, we will start peeking from the listhead, else - // we will start from that IRP onwards. This is done under the - // assumption that new IRPs are always inserted at the tail. - // - - if(Irp == NULL) - nextEntry = listHead->Flink; - else - nextEntry = Irp->Tail.Overlay.ListEntry.Flink; - - while(nextEntry != listHead) { - nextIrp = CONTAINING_RECORD(nextEntry, IRP, Tail.Overlay.ListEntry); - - // - // If context is present, continue until you find a matching one. - // Else you break out as you got next one. - // - - if(PeekContext) - { - /* for now PeekContext is not used */ - } - else - { - break; - } - - nextIrp = NULL; - nextEntry = nextEntry->Flink; - } - - AL_EXIT( AL_DBG_NDI ); - return nextIrp; -} - -static VOID __ndi_acquire_lock( - IN PIO_CSQ Csq, - OUT PKIRQL Irql - ) -{ - ndi_io_csq_t *p_ndi_csq = (ndi_io_csq_t*)Csq; - ib_cq_handle_t h_cq = p_ndi_csq->h_cq; - UNUSED_PARAM( Irql ); - - AL_ENTER( AL_DBG_NDI ); - cl_spinlock_acquire( &h_cq->obj.lock ); - AL_EXIT( AL_DBG_NDI ); -} - -static VOID __ndi_release_lock( - IN PIO_CSQ Csq, - IN KIRQL Irql - ) -{ - ndi_io_csq_t *p_ndi_csq = (ndi_io_csq_t*)Csq; - ib_cq_handle_t h_cq = p_ndi_csq->h_cq; - UNUSED_PARAM( Irql ); - - AL_ENTER( AL_DBG_NDI ); - cl_spinlock_release( &h_cq->obj.lock ); - AL_EXIT( AL_DBG_NDI ); -} - -static VOID __ndi_complete_cancelled_irp( - IN PIO_CSQ Csq, - IN PIRP Irp - ) -{ - ndi_io_csq_t *p_ndi_csq = (ndi_io_csq_t*)Csq; - ib_cq_handle_t h_cq = p_ndi_csq->h_cq; - - AL_ENTER( AL_DBG_NDI ); - cl_ioctl_complete( Irp, CL_CANCELED, 0 ); - deref_al_obj( &h_cq->obj ); - AL_EXIT( AL_DBG_NDI ); -} - -NTSTATUS -proxy_ndi_cq_init( - IN ib_cq_handle_t h_cq ) -{ - - NTSTATUS status; - - AL_ENTER( AL_DBG_NDI ); - - status = IoCsqInitialize( &h_cq->compl.csq, - __ndi_insert_irp, __ndi_remove_irp, - __ndi_peek_next_irp, __ndi_acquire_lock, - __ndi_release_lock, __ndi_complete_cancelled_irp ); - if ( !NT_SUCCESS( status ) ) - goto exit; - - status = IoCsqInitialize( &h_cq->error.csq, - __ndi_insert_irp, __ndi_remove_irp, - __ndi_peek_next_irp, __ndi_acquire_lock, - __ndi_release_lock, __ndi_complete_cancelled_irp ); - if ( !NT_SUCCESS( status ) ) - goto exit; - - InitializeListHead( &h_cq->compl.que ); - InitializeListHead( &h_cq->error.que ); - h_cq->compl.h_cq = h_cq; - h_cq->error.h_cq = h_cq; - status = STATUS_SUCCESS; - -exit: - AL_EXIT( AL_DBG_NDI ); - return status; -} - +#include "al_ndi_cm.h" +#include "al_cm_rdma.h" /******************************************************************* * @@ -305,15 +80,15 @@ __ndi_create_cq( ib_api_status_t status; ib_pfn_event_cb_t pfn_ev; - AL_ENTER( AL_DBG_CQ ); + AL_ENTER( AL_DBG_NDI ); /* Validate input buffers. */ if( !cl_ioctl_in_buf( h_ioctl ) || !cl_ioctl_out_buf( h_ioctl ) || cl_ioctl_in_size( h_ioctl ) != sizeof(p_ioctl->in) || cl_ioctl_out_size( h_ioctl ) != sizeof(p_ioctl->out) ) { - AL_EXIT( AL_DBG_CQ ); - return CL_INVALID_PARAMETER; + status = CL_INVALID_PARAMETER; + goto exit; } /* Validate CA handle */ @@ -328,9 +103,9 @@ __ndi_create_cq( cq_create.size = p_ioctl->in.size; /* Override with proxy's cq callback */ - cq_create.pfn_comp_cb = __ndi_cq_compl_cb; + cq_create.pfn_comp_cb = ndi_cq_compl_cb; cq_create.h_wait_obj = NULL; - pfn_ev = __ndi_cq_error_cb; + pfn_ev = ndi_cq_error_cb; status = cpyin_umvbuf( &p_ioctl->in.umv_buf, &p_umv_buf ); if( status != IB_SUCCESS ) @@ -371,7 +146,8 @@ proxy_create_cq_err1: p_ioctl->out.status = status; *p_ret_bytes = sizeof(p_ioctl->out); - AL_EXIT( AL_DBG_CQ ); +exit: + AL_EXIT( AL_DBG_NDI ); return CL_SUCCESS; } @@ -383,17 +159,17 @@ __ndi_notify_cq( OUT size_t *p_ret_bytes ) { cl_status_t cl_status; - ual_ndi_notify_cq_ioctl_cmd_in_t *p_ioctl; + ual_ndi_notify_cq_ioctl_in_t *p_ioctl; al_dev_open_context_t *p_context; ib_cq_handle_t h_cq; AL_ENTER( AL_DBG_NDI ); p_context = (al_dev_open_context_t*)p_open_context; - p_ioctl = (ual_ndi_notify_cq_ioctl_cmd_in_t*)cl_ioctl_in_buf( h_ioctl ); + p_ioctl = (ual_ndi_notify_cq_ioctl_in_t*)cl_ioctl_in_buf( h_ioctl ); /* Validate user parameters. */ - if( cl_ioctl_in_size( h_ioctl ) != sizeof(ual_ndi_notify_cq_ioctl_cmd_in_t) ) + if( cl_ioctl_in_size( h_ioctl ) != sizeof(ual_ndi_notify_cq_ioctl_in_t) ) { cl_status = CL_INVALID_PARAMETER; goto exit; @@ -462,9 +238,247 @@ __ndi_cancel_cq( } /* flush IRP queues */ - proxy_ndi_flush_ques( h_cq ); + ndi_cq_flush_ques( h_cq ); + + *p_ret_bytes = 0; + cl_status = CL_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + + +static cl_status_t +__ndi_get_cid( + IN void *p_open_context, + IN cl_ioctl_handle_t h_ioctl, + OUT size_t *p_ret_bytes ) +{ + cl_status_t cl_status; + ib_qp_handle_t h_qp; + al_dev_open_context_t *p_context; + uint32_t cid; + + 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(uint64_t) || + cl_ioctl_out_size( h_ioctl ) != sizeof(atomic32_t) ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Validate CQ 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 ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Check QP type */ + if( h_qp->type != IB_QPT_RELIABLE_CONN ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* get CID */ + cid = (uint32_t)((al_conn_qp_t*)h_qp)->cid; + if( cid == AL_INVALID_CID ) + { + cl_status = CL_INVALID_STATE; + goto exit; + } + + /* return CID */ + *(uint32_t*)cl_ioctl_out_buf( h_ioctl ) = cid; + + *p_ret_bytes = sizeof(uint32_t); + cl_status = CL_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + +static cl_status_t +__ndi_req_cm( + IN void *p_open_context, + IN cl_ioctl_handle_t h_ioctl, + OUT size_t *p_ret_bytes ) +{ + cl_status_t cl_status; + ib_qp_handle_t h_qp; + al_dev_open_context_t *p_context; + ual_ndi_req_cm_ioctl_in_t *p_req = + (ual_ndi_req_cm_ioctl_in_t*)cl_ioctl_in_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(ual_ndi_req_cm_ioctl_in_t) + p_req->pdata_size)) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Validate CQ 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 ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Check QP type */ + if( h_qp->type != IB_QPT_RELIABLE_CONN ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + p_req->h_qp = (uint64_t)h_qp; + + /* perform the ioctl */ + cl_status = ndi_req_cm( h_qp, h_ioctl, p_req ); + if (cl_status != CL_SUCCESS) + goto exit; + + cl_status = CL_PENDING; *p_ret_bytes = 0; + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + +static cl_status_t +__ndi_rep_cm( + IN void *p_open_context, + IN cl_ioctl_handle_t h_ioctl, + OUT size_t *p_ret_bytes ) +{ + cl_status_t cl_status; + ib_qp_handle_t h_qp; + al_dev_open_context_t *p_context; + ual_ndi_rep_cm_ioctl_in_t * p_ndi_rep_cm; + 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 ); + + 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(ual_ndi_req_cm_ioctl_in_t) + p_rep->pdata_size)) || + (p_rep->pdata_size < sizeof(cm_rdma_req_t)) || + cl_ioctl_out_size( h_ioctl ) != sizeof(atomic32_t) ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Get and validate QP handle */ + p_ndi_rep_cm = (ual_ndi_rep_cm_ioctl_in_t *)cl_ioctl_in_buf( h_ioctl ); + h_qp = (ib_qp_handle_t)al_hdl_ref( p_context->h_al, p_ndi_rep_cm->h_qp, AL_OBJ_TYPE_H_QP ); + + if( !h_qp ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + if( h_qp->type != IB_QPT_RELIABLE_CONN ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Get and validate CID */ + cid = p_ndi_rep_cm->cid; + + /* perform the ioctls */ + cl_status = ndi_rep_cm( h_qp, cid, h_ioctl, p_ndi_rep_cm ); + if( cl_status != CL_SUCCESS ) + goto exit; + + /* return QP state */ + *(uint32_t*)cl_ioctl_out_buf( h_ioctl ) = p_ndi_rep_cm->qp_state; + + *p_ret_bytes = sizeof(uint32_t); + cl_status = CL_SUCCESS; + +exit: + AL_EXIT( AL_DBG_NDI ); + return cl_status; +} + + +static cl_status_t +__ndi_rtu_cm( + IN void *p_open_context, + IN cl_ioctl_handle_t h_ioctl, + OUT size_t *p_ret_bytes ) +{ + cl_status_t cl_status; + ib_qp_handle_t h_qp; + al_dev_open_context_t *p_context; + atomic32_t cid; + + 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(uint64_t) || + cl_ioctl_out_size( h_ioctl ) != sizeof(atomic32_t) ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Validate CQ 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 ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* Check QP type */ + if( h_qp->type != IB_QPT_RELIABLE_CONN ) + { + cl_status = CL_INVALID_PARAMETER; + goto exit; + } + + /* get CID */ + cid = ((al_conn_qp_t*)h_qp)->cid; + if( cid == AL_INVALID_CID ) + { + cl_status = CL_INVALID_STATE; + goto exit; + } + + /* return CID */ + *(atomic32_t*)cl_ioctl_out_buf( h_ioctl ) = cid; + + *p_ret_bytes = sizeof(atomic32_t); cl_status = CL_SUCCESS; exit: @@ -503,6 +517,18 @@ ndi_ioctl( case UAL_NDI_CANCEL_CQ: cl_status = __ndi_cancel_cq( p_context, h_ioctl, p_ret_bytes ); break; + case UAL_NDI_GET_CID: + cl_status = __ndi_get_cid( p_context, h_ioctl, p_ret_bytes ); + break; + case UAL_NDI_REQ_CM: + cl_status = __ndi_req_cm( p_context, h_ioctl, p_ret_bytes ); + break; + case UAL_NDI_REP_CM: + cl_status = __ndi_rep_cm( p_context, h_ioctl, p_ret_bytes ); + break; + case UAL_NDI_RTU_CM: + cl_status = __ndi_rtu_cm( p_context, h_ioctl, p_ret_bytes ); + break; default: cl_status = CL_INVALID_PARAMETER; break; diff --git a/branches/Ndi/core/al/kernel/al_proxy_ndi.h b/branches/Ndi/core/al/kernel/al_proxy_ndi.h index 16d11d9c..d1089d9d 100644 --- a/branches/Ndi/core/al/kernel/al_proxy_ndi.h +++ b/branches/Ndi/core/al/kernel/al_proxy_ndi.h @@ -46,6 +46,9 @@ #include "complib/cl_ioctl_osd.h" #include "al_cq.h" +#include "al_ndi_cq.h" +#include "al_qp.h" +#include "al_ndi_cm.h" /* functions from al_proxy_verbs.c */ ib_api_status_t @@ -62,15 +65,6 @@ void free_umvbuf( IN ci_umv_buf_t *p_umv_buf ); -/* functions from al_proxy_ndi.c */ - -void -proxy_ndi_flush_ques( - IN ib_cq_handle_t h_cq ); - -NTSTATUS -proxy_ndi_cq_init( - IN ib_cq_handle_t h_cq ); #endif diff --git a/branches/Ndi/inc/iba/ib_al_ioctl.h b/branches/Ndi/inc/iba/ib_al_ioctl.h index 05364773..cba000d3 100644 --- a/branches/Ndi/inc/iba/ib_al_ioctl.h +++ b/branches/Ndi/inc/iba/ib_al_ioctl.h @@ -3410,9 +3410,9 @@ typedef enum _ND_CQ_NOTIFY_TYPE } ND_CQ_NOTIFY_TYPE; -/****s* User-mode Access Layer/ual_ndi_notify_cq_ioctl_cmd_in_t +/****s* User-mode Access Layer/ual_ndi_notify_cq_ioctl_in_t * NAME -* ual_ndi_notify_cq_ioctl_cmd_in_t +* ual_ndi_notify_cq_ioctl_in_t * * DESCRIPTION * IOCTL structure containing the input parameters for requesting @@ -3420,27 +3420,157 @@ typedef enum _ND_CQ_NOTIFY_TYPE * * SYNOPSIS */ -typedef struct _ual_ndi_notify_cq_ioctl_cmd_in +typedef struct _ual_ndi_notify_cq_ioctl_in { uint64_t h_cq; ND_CQ_NOTIFY_TYPE notify_type; -} ual_ndi_notify_cq_ioctl_cmd_in_t; +} ual_ndi_notify_cq_ioctl_in_t; /* * NOTES * This is an asynchronous IOCTL. * -* The output parameters are a ual_rearm_pnp_ioctl_out_t. -* * FIELDS -* in.h_cq +* h_cq * A handle to the CQ to modify. * -* in.notify_type +* notify_type * Type of notification, requested. * *****/ +/****s* User-mode Access Layer/ual_ndi_req_cm_ioctl_in_t +* NAME +* ual_ndi_req_cm_ioctl_in_t +* +* DESCRIPTION +* IOCTL structure containing the input parameters +* sending CM REQ . +* +* SYNOPSIS +*/ +#pragma warning( disable : 4200) +typedef struct _ual_ndi_req_cm_ioctl_in +{ + uint64_t h_qp; + net64_t guid; + uint16_t dst_port; + uint8_t prot; + uint8_t reserve[5]; + uint32_t pdata_size; + uint8_t pdata[0]; + +} ual_ndi_req_cm_ioctl_in_t; +#pragma warning( default : 4200) +/* +* NOTES +* The output parameter is the new QP state (RTS). +* +* FIELDS +* h_qp +* A handle to the QP to modify. +* +* guid +* Local port GUID to which to bind to. +* +* dst_port +* Destination port number. +* +* prot +* Protocol. +* +* pdata_size +* The size of following private RDMA CM data +* +*****/ + +/****s* User-mode Access Layer/ual_ndi_rep_cm_ioctl_in_t +* NAME +* ual_ndi_rep_cm_ioctl_in_t +* +* DESCRIPTION +* IOCTL structure containing the input parameters +* sending CM RTU response . +* +* SYNOPSIS +*/ +#pragma warning( disable : 4200) +typedef struct _ual_ndi_rep_cm_ioctl_in +{ + uint64_t h_qp; + net32_t cid; + uint32_t qp_state; + uint8_t init_depth; + uint8_t resp_res; + uint8_t reserve[2]; + uint32_t pdata_size; + uint8_t pdata[0]; + +} ual_ndi_rep_cm_ioctl_in_t; +#pragma warning( default : 4200) +/* +* NOTES +* The output parameter is the new QP state (RTS). +* +* FIELDS +* h_qp +* A handle to the QP to modify. +* +* cid +* Connection ID. +* +* qp_state +* UVP QP state, that is to be set in case of success. +* +* init_depth +* The maximum number of outstanding RDMA read/atomic operations. +* +* resp_res +* The maximum number of RDMA read/atomic operations from the recipient. +* +* pdata_size +* The size of following private data +* +*****/ + +/****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 +*/ +#pragma warning( disable : 4200) +typedef struct _ual_ndi_rtu_cm_ioctl_in +{ + uint64_t h_qp; + uint32_t qp_state; + uint8_t init_depth; + uint8_t resp_res; + +} ual_ndi_rtu_cm_ioctl_in_t; +#pragma warning( default : 4200) +/* +* NOTES +* The output parameter is the new QP state (RTS). +* +* FIELDS +* h_qp +* A handle to the QP to modify. +* +* qp_state +* UVP QP state, that is to be set in case of success. +* +* init_depth +* The maximum number of outstanding RDMA read/atomic operations. +* +* resp_res +* The maximum number of RDMA read/atomic operations from the recipient. +* +*****/ diff --git a/branches/Ndi/inc/iba/ib_types.h b/branches/Ndi/inc/iba/ib_types.h index 2442e3b5..0288f6a1 100644 --- a/branches/Ndi/inc/iba/ib_types.h +++ b/branches/Ndi/inc/iba/ib_types.h @@ -8395,6 +8395,7 @@ typedef struct _ib_ioc_info * Defines the size of user available data in communication management MADs */ #define IB_REQ_CM_RDMA_PDATA_SIZE 56 +#define IB_REP_CM_RDMA_PDATA_SIZE 148 #define IB_REQ_PDATA_SIZE 92 #define IB_MRA_PDATA_SIZE 222 #define IB_REJ_PDATA_SIZE 148 diff --git a/branches/Ndi/inc/user/iba/ib_uvp.h b/branches/Ndi/inc/user/iba/ib_uvp.h index 33be7520..59020582 100644 --- a/branches/Ndi/inc/user/iba/ib_uvp.h +++ b/branches/Ndi/inc/user/iba/ib_uvp.h @@ -1891,6 +1891,45 @@ typedef void * ********/ +/****f* user-mode Verbs/uvp_post_destroy_qp_t +* NAME +* uvp_pre_get_qp_state_t -- Get QP state location and size. +* +* SYNOPSIS +*/ + +typedef void +(AL_API *uvp_pre_get_qp_state_t) ( + IN const ib_qp_handle_t h_uvp_qp, + OUT uint32_t** pp_qp_state, + OUT uint32_t* p_size + ); + +/* +* DESCRIPTION +* uvp_pre_get_qp_state_t() is implemented by vendor. +* UAL invokes this pre-ioctl routine to enable KAL to change QP state +* It is used after quick QP modify operation. +* There is no uvp_post_get_qp_state_t function. +* +* PARAMETERS +* h_uvp_qp +* [in] Vendor's Handle to the qp (in user-mode library) +* that needs to be destroyed. +* pp_qp_state +* [out] pointer to QP state internal variable; +* p_size +* [out] pointer to the size of QP state internal variable; +* +* RETURN VALUE +* +* PORTABILITY +* User mode. +* +* SEE ALSO +* +********/ + /********/ /****f* user-mode Verbs/uvp_pre_create_cq @@ -3194,6 +3233,8 @@ typedef struct _uvp_interface */ uint32_t version; + /* Version 1.00 APIs */ + /* * HCA Access Verbs */ @@ -3323,6 +3364,9 @@ typedef struct _uvp_interface uvp_pre_detach_mcast pre_detach_mcast; uvp_post_detach_mcast post_detach_mcast; + /* Version 1.01 APIs */ + uvp_pre_get_qp_state_t pre_get_qp_state; + } uvp_interface_t; /********/ -- 2.41.0