}\r
\r
#ifdef CL_KERNEL\r
- /* cancel pending IRPS for NDI type CQ */\r
- if( !NT_SUCCESS( proxy_ndi_cq_init( h_cq ) ) )\r
+ if( !NT_SUCCESS( ndi_cq_init( h_cq ) ) )\r
{\r
free_cq( &h_cq->obj );\r
return IB_ERROR;\r
\r
#ifdef CL_KERNEL\r
/* cancel pending IRPS for NDI type CQ */\r
- proxy_ndi_flush_ques( h_cq );\r
+ ndi_cq_flush_ques( h_cq );\r
#endif\r
\r
}\r
\r
typedef struct _ib_cq ib_cq_t;\r
\r
-typedef struct _ndi_io_csq\r
+typedef struct _ndi_cq_csq\r
{\r
IO_CSQ csq;\r
ib_cq_t* h_cq;\r
LIST_ENTRY que;\r
-} ndi_io_csq_t;\r
+} ndi_cq_csq_t;\r
\r
#endif\r
\r
\r
/* NDI CQ fields */\r
#ifdef CL_KERNEL\r
- ndi_io_csq_t compl;\r
- ndi_io_csq_t error;\r
+ ndi_cq_csq_t compl;\r
+ ndi_cq_csq_t error;\r
#endif\r
\r
} ib_cq_t;\r
ual_ndi_create_cq_ioctl_cmd,\r
ual_ndi_notify_cq_ioctl_cmd,\r
ual_ndi_cancel_cq_ioctl_cmd,\r
+ ual_ndi_get_cid_ioctl_cmd,\r
+ ual_ndi_req_cm_ioctl_cmd,\r
+ ual_ndi_rep_cm_ioctl_cmd,\r
+ ual_ndi_rtu_cm_ioctl_cmd,\r
\r
al_ndi_maxops\r
\r
#define UAL_NDI_CREATE_CQ IOCTL_CODE(ALDEV_KEY, ual_ndi_create_cq_ioctl_cmd)\r
#define UAL_NDI_NOTIFY_CQ IOCTL_CODE(ALDEV_KEY, ual_ndi_notify_cq_ioctl_cmd)\r
#define UAL_NDI_CANCEL_CQ IOCTL_CODE(ALDEV_KEY, ual_ndi_cancel_cq_ioctl_cmd)\r
+#define UAL_NDI_GET_CID IOCTL_CODE(ALDEV_KEY, ual_ndi_get_cid_ioctl_cmd)\r
+#define UAL_NDI_REQ_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_req_cm_ioctl_cmd)\r
+#define UAL_NDI_REP_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_rep_cm_ioctl_cmd)\r
+#define UAL_NDI_RTU_CM IOCTL_CODE(ALDEV_KEY, ual_ndi_rtu_cm_ioctl_cmd)\r
\r
/*\r
* Various Opration Allowable on the System Helper\r
#include "al_verbs.h"\r
\r
#include "ib_common.h"\r
+#include "kernel\al_proxy_ndi.h"\r
\r
\r
#define UNBOUND_PORT_GUID 0\r
break;\r
}\r
status = init_conn_qp( (al_conn_qp_t*)h_qp, h_pd, p_qp_create, p_umv_buf );\r
+#ifdef CL_KERNEL\r
+ if( NT_SUCCESS( status ) )\r
+ status = ndi_qp_init( h_qp );\r
+#endif\r
break;\r
\r
case IB_QPT_UNRELIABLE_DGRM:\r
deref_al_obj( &h_qp->obj );\r
}\r
}\r
+#ifdef CL_KERNEL\r
+ ndi_qp_deinit( h_qp );\r
+#endif\r
\r
/* Fall through. */\r
case IB_QPT_UNRELIABLE_DGRM:\r
#include "al_mcast.h"\r
#ifdef CL_KERNEL\r
#include "al_smi.h"\r
+#include "al_ndi_cm.h"\r
#endif /* CL_KERNEL */\r
\r
\r
cl_obj_rel_t recv_cq_rel;\r
cl_obj_rel_t send_cq_rel;\r
\r
- ib_srq_handle_t h_srq;\r
+ ib_srq_handle_t h_srq;\r
cl_obj_rel_t srq_rel;\r
\r
ib_pfn_event_cb_t pfn_event_cb;\r
ib_pfn_init_dgrm_svc_t pfn_init_dgrm_svc;\r
ib_pfn_join_mcast_t pfn_join_mcast;\r
\r
+#ifdef CL_KERNEL\r
+ ndi_qp_csq_t *p_irp_que;\r
+#endif\r
+\r
} ib_qp_t;\r
\r
\r
al_proxy_subnet.c \\r
al_proxy_verbs.c \\r
al_proxy_ndi.c \\r
+ al_ndi_cq.c \\r
+ al_ndi_cm.c \\r
al_sa_req.c \\r
al_smi.c \\r
..\al.c \\r
if( status != IB_SUCCESS )\r
break;\r
\r
- status = __format_drep( p_cep, NULL, 0, (mad_cm_drep_t*)p_mad->p_mad_buf );\r
- if( status != IB_SUCCESS )\r
- break;\r
-\r
+ p_mad->p_mad_buf->attr_id = CM_DREP_ATTR_ID;\r
+ /* __format_drep returns always SUCCESS while no private data */\r
+ __format_drep( p_cep, NULL, 0, (mad_cm_drep_t*)p_mad->p_mad_buf );\r
__cep_send_mad( p_port_cep, p_mad );\r
break;\r
\r
case CEP_STATE_LISTEN:\r
/* Remove from listen map. */\r
cl_rbmap_remove_item( &gp_cep_mgr->listen_map, &p_cep->listen_item );\r
- if( !p_cep->p_cmp_buf )\r
+\r
+ if( p_cep->p_cmp_buf )\r
{\r
cl_free( p_cep->p_cmp_buf );\r
p_cep->p_cmp_buf = NULL;\r
} 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
--- /dev/null
+/*
+ * 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 <complib/comp_lib.h>
+#include <iba/ib_al.h>
+#include <iba/ib_al_ioctl.h>
+#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;
+}
+
+
+
--- /dev/null
+/*
+ * 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
+
--- /dev/null
+/*
+ * 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 <complib/comp_lib.h>
+#include <iba/ib_al.h>
+#include <iba/ib_al_ioctl.h>
+#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;
+}
+
+
+
--- /dev/null
+/*
+ * 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
#include <iba/ib_al.h>
#include <iba/ib_al_ioctl.h>
#include "al.h"
+#include "al_qp.h"
#include "al_debug.h"
+#include "al_cm_cep.h"
#if defined(EVENT_TRACING)
#ifdef offsetof
#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"
/*******************************************************************
*
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 */
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 )
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;
}
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;
}
/* 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:
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;
#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
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
\r
} ND_CQ_NOTIFY_TYPE;\r
\r
-/****s* User-mode Access Layer/ual_ndi_notify_cq_ioctl_cmd_in_t\r
+/****s* User-mode Access Layer/ual_ndi_notify_cq_ioctl_in_t\r
* NAME\r
-* ual_ndi_notify_cq_ioctl_cmd_in_t\r
+* ual_ndi_notify_cq_ioctl_in_t\r
*\r
* DESCRIPTION\r
* IOCTL structure containing the input parameters for requesting\r
*\r
* SYNOPSIS\r
*/\r
-typedef struct _ual_ndi_notify_cq_ioctl_cmd_in\r
+typedef struct _ual_ndi_notify_cq_ioctl_in\r
{\r
uint64_t h_cq;\r
ND_CQ_NOTIFY_TYPE notify_type;\r
\r
-} ual_ndi_notify_cq_ioctl_cmd_in_t;\r
+} ual_ndi_notify_cq_ioctl_in_t;\r
/*\r
* NOTES\r
* This is an asynchronous IOCTL.\r
*\r
-* The output parameters are a ual_rearm_pnp_ioctl_out_t.\r
-*\r
* FIELDS\r
-* in.h_cq\r
+* h_cq\r
* A handle to the CQ to modify.\r
*\r
-* in.notify_type\r
+* notify_type\r
* Type of notification, requested.\r
*\r
*****/\r
\r
+/****s* User-mode Access Layer/ual_ndi_req_cm_ioctl_in_t\r
+* NAME\r
+* ual_ndi_req_cm_ioctl_in_t\r
+*\r
+* DESCRIPTION\r
+* IOCTL structure containing the input parameters \r
+* sending CM REQ .\r
+*\r
+* SYNOPSIS\r
+*/\r
+#pragma warning( disable : 4200)\r
+typedef struct _ual_ndi_req_cm_ioctl_in\r
+{\r
+ uint64_t h_qp;\r
+ net64_t guid;\r
+ uint16_t dst_port;\r
+ uint8_t prot;\r
+ uint8_t reserve[5];\r
+ uint32_t pdata_size;\r
+ uint8_t pdata[0];\r
+\r
+} ual_ndi_req_cm_ioctl_in_t;\r
+#pragma warning( default : 4200)\r
+/*\r
+* NOTES\r
+* The output parameter is the new QP state (RTS).\r
+*\r
+* FIELDS\r
+* h_qp\r
+* A handle to the QP to modify.\r
+*\r
+* guid\r
+* Local port GUID to which to bind to.\r
+*\r
+* dst_port\r
+* Destination port number.\r
+*\r
+* prot\r
+* Protocol.\r
+*\r
+* pdata_size\r
+* The size of following private RDMA CM data\r
+*\r
+*****/\r
+\r
+/****s* User-mode Access Layer/ual_ndi_rep_cm_ioctl_in_t\r
+* NAME\r
+* ual_ndi_rep_cm_ioctl_in_t\r
+*\r
+* DESCRIPTION\r
+* IOCTL structure containing the input parameters \r
+* sending CM RTU response .\r
+*\r
+* SYNOPSIS\r
+*/\r
+#pragma warning( disable : 4200)\r
+typedef struct _ual_ndi_rep_cm_ioctl_in\r
+{\r
+ uint64_t h_qp;\r
+ net32_t cid;\r
+ uint32_t qp_state;\r
+ uint8_t init_depth;\r
+ uint8_t resp_res;\r
+ uint8_t reserve[2];\r
+ uint32_t pdata_size;\r
+ uint8_t pdata[0];\r
+\r
+} ual_ndi_rep_cm_ioctl_in_t;\r
+#pragma warning( default : 4200)\r
+/*\r
+* NOTES\r
+* The output parameter is the new QP state (RTS).\r
+*\r
+* FIELDS\r
+* h_qp\r
+* A handle to the QP to modify.\r
+*\r
+* cid\r
+* Connection ID.\r
+*\r
+* qp_state\r
+* UVP QP state, that is to be set in case of success.\r
+*\r
+* init_depth\r
+* The maximum number of outstanding RDMA read/atomic operations.\r
+*\r
+* resp_res\r
+* The maximum number of RDMA read/atomic operations from the recipient.\r
+*\r
+* pdata_size\r
+* The size of following private data\r
+*\r
+*****/\r
+\r
+/****s* User-mode Access Layer/ual_ndi_rtu_cm_ioctl_in_t\r
+* NAME\r
+* ual_ndi_rtu_cm_ioctl_in_t\r
+*\r
+* DESCRIPTION\r
+* IOCTL structure containing the input parameters \r
+* sending CM RTU response .\r
+*\r
+* SYNOPSIS\r
+*/\r
+#pragma warning( disable : 4200)\r
+typedef struct _ual_ndi_rtu_cm_ioctl_in\r
+{\r
+ uint64_t h_qp;\r
+ uint32_t qp_state;\r
+ uint8_t init_depth;\r
+ uint8_t resp_res;\r
+\r
+} ual_ndi_rtu_cm_ioctl_in_t;\r
+#pragma warning( default : 4200)\r
+/*\r
+* NOTES\r
+* The output parameter is the new QP state (RTS).\r
+*\r
+* FIELDS\r
+* h_qp\r
+* A handle to the QP to modify.\r
+*\r
+* qp_state\r
+* UVP QP state, that is to be set in case of success.\r
+*\r
+* init_depth\r
+* The maximum number of outstanding RDMA read/atomic operations.\r
+*\r
+* resp_res\r
+* The maximum number of RDMA read/atomic operations from the recipient.\r
+*\r
+*****/\r
\r
\r
\r
* Defines the size of user available data in communication management MADs\r
*/\r
#define IB_REQ_CM_RDMA_PDATA_SIZE 56\r
+#define IB_REP_CM_RDMA_PDATA_SIZE 148\r
#define IB_REQ_PDATA_SIZE 92\r
#define IB_MRA_PDATA_SIZE 222\r
#define IB_REJ_PDATA_SIZE 148\r
*\r
********/\r
\r
+/****f* user-mode Verbs/uvp_post_destroy_qp_t\r
+* NAME\r
+* uvp_pre_get_qp_state_t -- Get QP state location and size.\r
+*\r
+* SYNOPSIS\r
+*/\r
+\r
+typedef void\r
+(AL_API *uvp_pre_get_qp_state_t) (\r
+ IN const ib_qp_handle_t h_uvp_qp,\r
+ OUT uint32_t** pp_qp_state,\r
+ OUT uint32_t* p_size\r
+ );\r
+\r
+/*\r
+* DESCRIPTION\r
+* uvp_pre_get_qp_state_t() is implemented by vendor. \r
+* UAL invokes this pre-ioctl routine to enable KAL to change QP state\r
+* It is used after quick QP modify operation.\r
+* There is no uvp_post_get_qp_state_t function.\r
+*\r
+* PARAMETERS\r
+* h_uvp_qp\r
+* [in] Vendor's Handle to the qp (in user-mode library)\r
+* that needs to be destroyed.\r
+* pp_qp_state\r
+* [out] pointer to QP state internal variable;\r
+* p_size\r
+* [out] pointer to the size of QP state internal variable;\r
+*\r
+* RETURN VALUE\r
+*\r
+* PORTABILITY\r
+* User mode.\r
+*\r
+* SEE ALSO\r
+*\r
+********/\r
+\r
/********/\r
\r
/****f* user-mode Verbs/uvp_pre_create_cq\r
*/\r
uint32_t version;\r
\r
+ /* Version 1.00 APIs */\r
+\r
/*\r
* HCA Access Verbs\r
*/\r
uvp_pre_detach_mcast pre_detach_mcast;\r
uvp_post_detach_mcast post_detach_mcast;\r
\r
+ /* Version 1.01 APIs */\r
+ uvp_pre_get_qp_state_t pre_get_qp_state;\r
+ \r
} uvp_interface_t;\r
\r
/********/\r