ib/cm: export cm only interface
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 24 Jan 2009 19:15:03 +0000 (19:15 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Sat, 24 Jan 2009 19:15:03 +0000 (19:15 +0000)
To support WinVerbs and a future OFED libibcm compatibility library (requires
a new library and driver), export a new IB CM interface.  The interface sits
above the existing communication endpoint (CEP) manager.  This allows the
interface to export only IB CM functionality.

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1874 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

core/al/al_cm_cep.h
core/al/kernel/SOURCES
core/al/kernel/al_cm.c [new file with mode: 0644]
core/al/kernel/al_cm_cep.c
core/al/kernel/al_ndi_cm.c
core/bus/kernel/bus_pnp.c
inc/kernel/iba/ib_cm_ifc.h [new file with mode: 0644]

index b4aad3f..a7011d4 100644 (file)
 #ifndef _AL_CM_CEP_H_\r
 #define _AL_CM_CEP_H_\r
 \r
-\r
 #include <iba/ib_al.h>\r
 #include "al_common.h"\r
 \r
+#ifdef CL_KERNEL\r
+#include <iba/ib_cm_ifc.h>\r
+#endif\r
 \r
 #define CEP_EVENT_TIMEOUT      0x80000000\r
 #define CEP_EVENT_RECV         0x40000000\r
@@ -108,6 +110,21 @@ al_create_cep(
 * event notification.\r
 *********/\r
 \r
+#ifdef CL_KERNEL\r
+ib_api_status_t\r
+kal_cep_alloc(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN      OUT                     net32_t* const                          p_cid );\r
+\r
+void\r
+kal_cep_config(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN                              al_pfn_cep_cb_t                         pfn_cb,\r
+       IN                              void*                                           context,\r
+       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb );\r
+#endif\r
+\r
 /* Destruction is asynchronous. */\r
 void\r
 al_destroy_cep(\r
@@ -124,6 +141,16 @@ al_cep_listen(
        IN                              ib_cep_listen_t* const          p_listen_info );\r
 \r
 \r
+#ifdef CL_KERNEL\r
+ib_api_status_t\r
+kal_cep_pre_req(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN              const   iba_cm_req* const                       p_cm_req,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
+       IN      OUT                     ib_qp_mod_t* const                      p_init OPTIONAL );\r
+#endif\r
+\r
 ib_api_status_t\r
 al_cep_pre_req(\r
        IN                              ib_al_handle_t                          h_al,\r
@@ -148,22 +175,52 @@ al_cep_pre_rep(
        IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init );\r
 \r
+#ifdef CL_KERNEL\r
+ib_api_status_t\r
+kal_cep_pre_rep(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
+       IN      OUT                     ib_qp_mod_t* const                      p_init OPTIONAL );\r
+\r
 ib_api_status_t\r
-al_cep_pre_rep_ex(\r
+kal_cep_config_pre_rep_copy_cid(\r
        IN                              ib_al_handle_t                          h_al,\r
        IN                              net32_t                                         cid,\r
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
-       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb OPTIONAL,\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
        IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init );\r
 \r
+void\r
+kal_cep_destroy(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid );\r
+#endif\r
+\r
 ib_api_status_t\r
 al_cep_send_rep(\r
        IN                              ib_al_handle_t                          h_al,\r
        IN                              net32_t                                         cid );\r
 \r
+#ifdef CL_KERNEL\r
+void\r
+kal_cep_format_event(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN                              ib_mad_element_t                        *p_mad,\r
+       IN      OUT                     iba_cm_event                            *p_event);\r
+\r
+ib_api_status_t\r
+al_cep_get_init_attr(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+               OUT                     ib_qp_mod_t* const                      p_init );\r
+#endif\r
 \r
 ib_api_status_t\r
 al_cep_get_rtr_attr(\r
@@ -271,6 +328,7 @@ al_cep_poll(
 \r
 \r
 #ifdef CL_KERNEL\r
+void cm_get_interface(iba_cm_interface *p_ifc);\r
 \r
 NTSTATUS\r
 al_cep_queue_irp(\r
index 5f2e33f..0a80f7e 100644 (file)
@@ -13,6 +13,7 @@ ENABLE_EVENT_TRACING=1
 \r
 SOURCES= ibal.rc                       \\r
        al_ci_ca.c                              \\r
+       al_cm.c                                 \\r
        al_cm_cep.c                             \\r
        al_dev.c                                \\r
        al_ioc_pnp.c                    \\r
diff --git a/core/al/kernel/al_cm.c b/core/al/kernel/al_cm.c
new file mode 100644 (file)
index 0000000..3142462
--- /dev/null
@@ -0,0 +1,362 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#include <iba/ib_cm_ifc.h>\r
+#include "al_cm_cep.h"\r
+#include "al_mgr.h"\r
+#include "al_proxy.h"\r
+#include "al_cm_conn.h"\r
+#include "al_cm_sidr.h"\r
+\r
+typedef struct _iba_cm_id_priv\r
+{\r
+       iba_cm_id       id;\r
+       KEVENT          destroy_event;  \r
+\r
+}      iba_cm_id_priv;\r
+\r
+static iba_cm_id*\r
+cm_alloc_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),\r
+                       void *context)\r
+{\r
+       iba_cm_id_priv  *id;\r
+\r
+       id = ExAllocatePoolWithTag(NonPagedPool, sizeof(iba_cm_id_priv), 'mcbi');\r
+       if (id == NULL) {\r
+               return NULL;\r
+       }\r
+\r
+       KeInitializeEvent(&id->destroy_event, NotificationEvent, FALSE);\r
+       id->id.callback = callback;\r
+       id->id.context = context;\r
+       return &id->id;\r
+}\r
+\r
+static void\r
+cm_free_id(iba_cm_id *id)\r
+{\r
+       ExFreePool(CONTAINING_RECORD(id, iba_cm_id_priv, id));\r
+}\r
+\r
+static void\r
+cm_destroy_handler(void *context)\r
+{\r
+       iba_cm_id_priv  *id = context;\r
+       KeSetEvent(&id->destroy_event, 0, FALSE);\r
+}\r
+\r
+static void\r
+cm_cep_handler(const ib_al_handle_t h_al, const net32_t cid)\r
+{\r
+       void                            *context;\r
+       net32_t                         new_cid;\r
+       ib_mad_element_t        *mad;\r
+       iba_cm_id                       *id, *listen_id;\r
+       iba_cm_event            event;\r
+       NTSTATUS                        status;\r
+\r
+       while (al_cep_poll(h_al, cid, &context, &new_cid, &mad) == IB_SUCCESS) {\r
+\r
+               if (new_cid == AL_INVALID_CID) {\r
+                       id = (iba_cm_id *) context;\r
+               } else {\r
+                       listen_id = (iba_cm_id *) context;\r
+\r
+                       id = cm_alloc_id(listen_id->callback, listen_id);\r
+                       if (id == NULL) {\r
+                               kal_cep_destroy(h_al, new_cid);\r
+                               ib_put_mad(mad);\r
+                               continue;\r
+                       }\r
+\r
+                       kal_cep_config(h_al, new_cid, cm_cep_handler, id, cm_destroy_handler);\r
+                       id->cid = new_cid;\r
+               }\r
+\r
+               kal_cep_format_event(h_al, id->cid, mad, &event);\r
+               status = id->callback(id, &event);\r
+               if (!NT_SUCCESS(status)) {\r
+                       kal_cep_config(h_al, new_cid, NULL, NULL, NULL);\r
+                       kal_cep_destroy(h_al, id->cid);\r
+                       cm_free_id(id);\r
+               }\r
+               ib_put_mad(mad);\r
+       }\r
+}\r
+\r
+static NTSTATUS\r
+cm_create_id(NTSTATUS (*callback)(iba_cm_id *p_id, iba_cm_event *p_event),\r
+                        void *context, iba_cm_id **pp_id)\r
+{\r
+       iba_cm_id               *id;\r
+       ib_api_status_t ib_status;\r
+\r
+       id = cm_alloc_id(callback, context);\r
+       if (id == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       ib_status = kal_cep_alloc(gh_al, &id->cid);\r
+       if (ib_status != IB_SUCCESS) {\r
+               cm_free_id(id);\r
+               return ib_to_ntstatus(ib_status);\r
+       }\r
+\r
+       kal_cep_config(gh_al, id->cid, cm_cep_handler, id, cm_destroy_handler);\r
+       *pp_id = id;\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static void\r
+cm_destroy_id(iba_cm_id *p_id)\r
+{\r
+       iba_cm_id_priv  *id;\r
+\r
+       id = CONTAINING_RECORD(p_id, iba_cm_id_priv, id);\r
+       kal_cep_destroy(gh_al, p_id->cid);\r
+       KeWaitForSingleObject(&id->destroy_event, Executive, KernelMode, FALSE, NULL);\r
+       cm_free_id(p_id);\r
+}\r
+\r
+static NTSTATUS\r
+cm_listen(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,\r
+                 uint8_t compare_len, uint8_t compare_offset)\r
+{\r
+       ib_cep_listen_t info;\r
+       ib_api_status_t ib_status;\r
+\r
+       info.svc_id = service_id;\r
+       info.port_guid = IB_ALL_PORTS;\r
+       info.p_cmp_buf = p_compare_buf;\r
+       info.cmp_len = compare_len;\r
+       info.cmp_offset = compare_offset;\r
+       \r
+       ib_status = al_cep_listen(gh_al, p_id->cid, &info);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_req(iba_cm_id *p_id, iba_cm_req *p_req)\r
+{\r
+       ib_api_status_t ib_status;\r
+       \r
+       ib_status = kal_cep_pre_req(gh_al, p_id->cid, p_req, 0, NULL);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return ib_to_ntstatus(ib_status);\r
+       }\r
+\r
+       ib_status = al_cep_send_req(gh_al, p_id->cid);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_rep(iba_cm_id *p_id, iba_cm_rep *p_rep)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = kal_cep_pre_rep(gh_al, p_id->cid, p_rep, 0, NULL);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return ib_to_ntstatus(ib_status);\r
+       }\r
+\r
+       ib_status = al_cep_send_rep(gh_al, p_id->cid);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_rtu(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = al_cep_rtu(gh_al, p_id->cid, p_pdata, pdata_len);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_dreq(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = al_cep_dreq(gh_al, p_id->cid, p_pdata, pdata_len);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_drep(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = al_cep_drep(gh_al, p_id->cid, p_pdata, pdata_len);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_rej(iba_cm_id *p_id, ib_rej_status_t status,\r
+                       void *p_ari, uint8_t ari_len,\r
+                       void *p_pdata, uint8_t pdata_len)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = al_cep_rej(gh_al, p_id->cid, status, p_ari, ari_len,\r
+                                                  p_pdata, pdata_len);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_mra(iba_cm_id *p_id, uint8_t service_timeout,\r
+                       void *p_pdata, uint8_t pdata_len)\r
+{\r
+       ib_cm_mra_t             mra;\r
+       ib_api_status_t ib_status;\r
+\r
+       mra.svc_timeout = service_timeout;\r
+       mra.p_mra_pdata = p_pdata;\r
+       mra.mra_length = pdata_len;\r
+\r
+       ib_status = al_cep_mra(gh_al, p_id->cid, &mra);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_lap(iba_cm_id *p_id, iba_cm_lap *p_lap)\r
+{\r
+       ib_cm_lap_t             lap;\r
+       ib_api_status_t ib_status;\r
+\r
+       RtlZeroMemory(&lap, sizeof lap);\r
+       lap.p_lap_pdata = p_lap->p_pdata;\r
+       lap.lap_length = p_lap->pdata_len;\r
+       lap.remote_resp_timeout = p_lap->remote_resp_timeout;\r
+       lap.p_alt_path = p_lap->p_alt_path;\r
+\r
+       ib_status = al_cep_lap(gh_al, p_id->cid, &lap);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_apr(iba_cm_id *p_id, iba_cm_apr *p_apr)\r
+{\r
+       ib_cm_apr_t             apr;\r
+       ib_qp_mod_t             attr;\r
+       ib_api_status_t ib_status;\r
+\r
+       RtlZeroMemory(&apr, sizeof apr);\r
+       apr.p_apr_pdata = p_apr->p_pdata;\r
+       apr.apr_length = p_apr->pdata_len;\r
+       apr.apr_status = p_apr->status;\r
+       apr.info_length = p_apr->info_length;\r
+       apr.p_info = p_apr->p_info;\r
+\r
+       ib_status = al_cep_pre_apr(gh_al, p_id->cid, &apr, &attr);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return ib_to_ntstatus(ib_status);\r
+       }\r
+\r
+       ib_status = al_cep_send_apr(gh_al, p_id->cid);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_sidr_req(iba_cm_id *p_id, iba_cm_sidr_req *p_req)\r
+{\r
+       UNUSED_PARAM(p_id);\r
+       UNUSED_PARAM(p_req);\r
+\r
+       return STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+static NTSTATUS\r
+cm_send_sidr_rep(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep)\r
+{\r
+       UNUSED_PARAM(p_id);\r
+       UNUSED_PARAM(p_rep);\r
+\r
+       return STATUS_NOT_SUPPORTED;\r
+}\r
+\r
+static NTSTATUS\r
+cm_get_qp_attr(iba_cm_id *p_id, ib_qp_state_t state, ib_qp_mod_t *p_attr)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       switch (state) {\r
+       case IB_QPS_INIT:\r
+               ib_status = al_cep_get_init_attr(gh_al, p_id->cid, p_attr);\r
+               break;\r
+       case IB_QPS_RTR:\r
+               ib_status = al_cep_get_rtr_attr(gh_al, p_id->cid, p_attr);\r
+               break;\r
+       case IB_QPS_RTS:\r
+               ib_status = al_cep_get_rts_attr(gh_al, p_id->cid, p_attr);\r
+               break;\r
+       default:\r
+               return STATUS_INVALID_PARAMETER;\r
+       }\r
+\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_migrate(iba_cm_id *p_id)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = al_cep_migrate(gh_al, p_id->cid);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+static NTSTATUS\r
+cm_establish(iba_cm_id *p_id)\r
+{\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = al_cep_established(gh_al, p_id->cid);\r
+       return ib_to_ntstatus(ib_status);\r
+}\r
+\r
+void cm_get_interface(iba_cm_interface *p_ifc)\r
+{\r
+       p_ifc->create_id = cm_create_id;\r
+       p_ifc->destroy_id = cm_destroy_id;\r
+       p_ifc->listen = cm_listen;\r
+       p_ifc->send_req = cm_send_req;\r
+       p_ifc->send_rep = cm_send_rep;\r
+       p_ifc->send_rtu = cm_send_rtu;\r
+       p_ifc->send_dreq = cm_send_dreq;\r
+       p_ifc->send_drep = cm_send_drep;\r
+       p_ifc->send_rej = cm_send_rej;\r
+       p_ifc->send_mra = cm_send_mra;\r
+       p_ifc->send_lap = cm_send_lap;\r
+       p_ifc->send_apr = cm_send_apr;\r
+       p_ifc->send_sidr_req = cm_send_sidr_req;\r
+       p_ifc->send_sidr_rep = cm_send_sidr_rep;\r
+       p_ifc->get_qp_attr = cm_get_qp_attr;\r
+       p_ifc->migrate = cm_migrate;\r
+       p_ifc->established = cm_establish;\r
+}\r
index d5cc4e2..1253fa8 100644 (file)
@@ -36,6 +36,7 @@
 #include <complib/cl_rbmap.h>\r
 #include <complib/cl_qmap.h>\r
 #include <complib/cl_spinlock.h>\r
+#include <iba/ib_cm_ifc.h>\r
 #include "al_common.h"\r
 #include "al_cm_cep.h"\r
 #include "al_cm_conn.h"\r
@@ -333,7 +334,6 @@ typedef struct _al_kcep
        ib_mad_svc_handle_t                     h_mad_svc;\r
        ib_mad_element_t                        *p_send_mad;\r
 \r
-       /* Number of outstanding MADs.  Delays destruction of CEP destruction. */\r
        atomic32_t                                      ref_cnt;\r
 \r
        /* MAD transaction ID to use when sending MADs. */\r
@@ -367,7 +367,7 @@ typedef struct _al_kcep
        }       mads;\r
 \r
        /*\r
-        * NDI stuff\r
+        * NDI stuff - TODO: manage above core kernel CM code\r
         */\r
 \r
        /* IRP list head */\r
@@ -1064,7 +1064,8 @@ __req_handler(
 \r
        KeAcquireInStackQueuedSpinLockAtDpcLevel( &gp_cep_mgr->lock, &hdl );\r
 \r
-       if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN )\r
+       if( conn_req_get_qp_type( p_req ) > IB_QPT_UNRELIABLE_CONN ||\r
+               conn_req_get_lcl_qpn( p_req ) == 0 )\r
        {\r
                /* Reserved value.  Reject. */\r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid transport type received.\n") );\r
@@ -3410,6 +3411,7 @@ __cep_queue_mad(
                return IB_INVALID_STATE;\r
        }\r
 \r
+       // TODO: Remove - manage above core kernel CM code\r
        /* NDI connection request case */\r
        if ( p_cep->state == CEP_STATE_LISTEN &&\r
                (p_cep->sid & ~0x0ffffffI64) == IB_REQ_CM_RDMA_SID_PREFIX )\r
@@ -3650,6 +3652,47 @@ __bind_cep(
        cl_spinlock_release( &h_al->obj.lock );\r
 }\r
 \r
+ib_api_status_t\r
+kal_cep_alloc(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN      OUT                     net32_t* const                          p_cid )\r
+{\r
+       kcep_t                          *p_cep;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       p_cep = __create_cep();\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       if( !p_cep )\r
+               return IB_INSUFFICIENT_MEMORY;\r
+\r
+       __bind_cep(p_cep, h_al, NULL, NULL);\r
+       *p_cid = p_cep->cid;\r
+       return IB_SUCCESS;\r
+}\r
+\r
+void\r
+kal_cep_config(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN                              al_pfn_cep_cb_t                         pfn_cb,\r
+       IN                              void*                                           context,\r
+       IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb )\r
+{\r
+       kcep_t                          *p_cep;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       p_cep = __lookup_cep( h_al, cid );\r
+       CL_ASSERT( p_cep );\r
+\r
+       p_cep->pfn_cb = pfn_cb;\r
+       p_cep->context = context;\r
+       p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
+\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+}\r
 \r
 static inline void\r
 __unbind_cep(\r
@@ -3967,10 +4010,12 @@ __cleanup_cep(
                        sizeof(p_cep->local_ca_guid), NULL, 0 );\r
                break;\r
 \r
-       case CEP_STATE_ESTABLISHED:\r
-       case CEP_STATE_LAP_RCVD:\r
        case CEP_STATE_LAP_SENT:\r
        case CEP_STATE_LAP_MRA_RCVD:\r
+               ib_cancel_mad( p_cep->h_mad_svc, p_cep->p_send_mad );\r
+               /* fall through */\r
+       case CEP_STATE_ESTABLISHED:\r
+       case CEP_STATE_LAP_RCVD:\r
        case CEP_STATE_LAP_MRA_SENT:\r
        case CEP_STATE_PRE_APR:\r
        case CEP_STATE_PRE_APR_MRA_SENT:\r
@@ -3980,9 +4025,9 @@ __cleanup_cep(
                /* Fall through. */\r
 \r
        case CEP_STATE_DREQ_SENT:\r
+               ib_cancel_mad( p_cep->h_mad_svc, p_cep->p_send_mad );\r
                p_cep->state = CEP_STATE_DREQ_DESTROY;\r
-               AL_EXIT( AL_DBG_CM );\r
-               return cl_atomic_dec( &p_cep->ref_cnt );\r
+               goto out;\r
 \r
        case CEP_STATE_DREQ_RCVD:\r
                /* Send the DREP. */\r
@@ -4017,13 +4062,13 @@ __cleanup_cep(
        case CEP_STATE_TIMEWAIT:\r
                /* Already in timewait - so all is good. */\r
                p_cep->state = CEP_STATE_DESTROY;\r
-               AL_EXIT( AL_DBG_CM );\r
-               return cl_atomic_dec( &p_cep->ref_cnt );\r
+               goto out;\r
        }\r
 \r
        p_cep->state = CEP_STATE_DESTROY;\r
        __insert_timewait( p_cep );\r
 \r
+out:\r
        AL_EXIT( AL_DBG_CM );\r
        return cl_atomic_dec( &p_cep->ref_cnt );\r
 }\r
@@ -4064,40 +4109,19 @@ al_create_cep(
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,\r
        IN      OUT                     net32_t* const                          p_cid )\r
 {\r
-       kcep_t                          *p_cep;\r
-       KLOCK_QUEUE_HANDLE      hdl;\r
+       ib_api_status_t status;\r
 \r
        AL_ENTER( AL_DBG_CM );\r
+       CL_ASSERT( h_al );\r
 \r
-       CL_ASSERT( p_cid );\r
-\r
-       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
-       if( *p_cid != AL_INVALID_CID )\r
+       status = kal_cep_alloc(h_al, p_cid);\r
+       if ( status == IB_SUCCESS )\r
        {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               return IB_RESOURCE_BUSY;\r
+               kal_cep_config(h_al, *p_cid, pfn_cb, context, pfn_destroy_cb);\r
        }\r
-       p_cep = __create_cep();\r
-       if( !p_cep )\r
-       {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Failed to allocate CEP.\n") );\r
-               return IB_INSUFFICIENT_MEMORY;\r
-       }\r
-\r
-       __bind_cep( p_cep, h_al, pfn_cb, context );\r
-\r
-       p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
-       *p_cid = p_cep->cid;\r
-\r
-       KeReleaseInStackQueuedSpinLock( &hdl );\r
-\r
-       AL_PRINT(TRACE_LEVEL_INFORMATION ,AL_DBG_CM ,\r
-               ("Created CEP with cid %d, h_al %p, context %p \n", \r
-               p_cep->cid, h_al, p_cep->context ));\r
 \r
        AL_EXIT( AL_DBG_CM );\r
-       return IB_SUCCESS;\r
+       return status;\r
 }\r
 \r
 \r
@@ -4107,7 +4131,7 @@ al_destroy_cep(
        IN      OUT                     net32_t* const                          p_cid,\r
        IN                              boolean_t                                       reusable )\r
 {\r
-    net32_t             cid = *p_cid;\r
+    net32_t             cid;\r
        kcep_t                          *p_cep;\r
        KLOCK_QUEUE_HANDLE      hdl;\r
        void                            *context;\r
@@ -4123,6 +4147,7 @@ al_destroy_cep(
         * will succeed for it.\r
         */\r
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       cid = *p_cid;\r
        p_cep = __lookup_cep( h_al, cid );\r
        if( !p_cep )\r
        {\r
@@ -4169,10 +4194,6 @@ al_destroy_cep(
 \r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
 \r
-       /*\r
-        * Done waiting.  Release the reference so the timewait timer callback\r
-        * can finish cleaning up.\r
-        */\r
        if( !ref_cnt && pfn_destroy_cb )\r
                pfn_destroy_cb( context );\r
 \r
@@ -4183,6 +4204,14 @@ al_destroy_cep(
        AL_EXIT( AL_DBG_CM );\r
 }\r
 \r
+void\r
+kal_cep_destroy(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid )\r
+{\r
+       al_destroy_cep(h_al, &cid, FALSE);\r
+}\r
+\r
 \r
 ib_api_status_t\r
 al_cep_listen(\r
@@ -4433,8 +4462,9 @@ __format_req_path(
 \r
 static ib_api_status_t\r
 __format_req(\r
+       IN                              cep_agent_t* const                      p_port_cep,\r
        IN                              kcep_t* const                           p_cep,\r
-       IN              const   ib_cm_req_t* const                      p_cm_req )\r
+       IN              const   iba_cm_req* const                       p_cm_req )\r
 {\r
        ib_api_status_t status;\r
        mad_cm_req_t*   p_req;\r
@@ -4453,14 +4483,14 @@ __format_req(
 \r
        p_req = (mad_cm_req_t*)p_cep->p_mad->p_mad_buf;\r
 \r
-       ci_ca_lock_attr( p_cm_req->h_qp->obj.p_ci_ca );\r
+       ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
        /*\r
         * Store the local CA's ack timeout for use when computing\r
         * the local ACK timeout.\r
         */\r
        p_cep->local_ack_delay =\r
-               p_cm_req->h_qp->obj.p_ci_ca->p_pnp_attr->local_ack_delay;\r
-       ci_ca_unlock_attr( p_cm_req->h_qp->obj.p_ci_ca );\r
+               p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->local_ack_delay;\r
+       ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
 \r
        /* Format the primary path. */\r
        __format_req_path( p_cm_req->p_primary_path,\r
@@ -4479,16 +4509,16 @@ __format_req(
 \r
        /* Set the local communication in the REQ. */\r
        p_req->local_comm_id = p_cep->local_comm_id;\r
-       p_req->sid = p_cm_req->svc_id;\r
-       p_req->local_ca_guid = p_cm_req->h_qp->obj.p_ci_ca->verbs.guid;\r
+       p_req->sid = p_cm_req->service_id;\r
+       p_req->local_ca_guid = p_port_cep->h_ca->obj.p_ci_ca->verbs.guid;\r
 \r
        conn_req_set_lcl_qpn( p_cep->local_qpn, p_req );\r
        conn_req_set_resp_res( p_cm_req->resp_res, p_req );\r
        conn_req_set_init_depth( p_cm_req->init_depth, p_req );\r
        conn_req_set_remote_resp_timeout( p_cm_req->remote_resp_timeout, p_req );\r
-       conn_req_set_qp_type( p_cm_req->h_qp->type, p_req );\r
+       conn_req_set_qp_type( p_cm_req->qp_type, p_req );\r
        conn_req_set_flow_ctrl( p_cm_req->flow_ctrl, p_req );\r
-       conn_req_set_starting_psn( p_cep->rq_psn, p_req );\r
+       conn_req_set_starting_psn( p_cm_req->starting_psn, p_req );\r
 \r
        conn_req_set_lcl_resp_timeout( p_cm_req->local_resp_timeout, p_req );\r
        conn_req_set_retry_cnt( p_cm_req->retry_cnt, p_req );\r
@@ -4500,7 +4530,7 @@ __format_req(
 \r
        conn_req_set_max_cm_retries( p_cm_req->max_cm_retries, p_req );\r
        status = conn_req_set_pdata(\r
-               p_cm_req->p_req_pdata, p_cm_req->req_length, p_req );\r
+               p_cm_req->p_pdata, p_cm_req->pdata_len, p_req );\r
 \r
        conn_req_clr_rsvd_fields( p_req );\r
 \r
@@ -4512,7 +4542,8 @@ __format_req(
 static ib_api_status_t\r
 __save_user_req(\r
        IN                              kcep_t* const                           p_cep,\r
-       IN              const   ib_cm_req_t* const                      p_cm_req,\r
+       IN              const   iba_cm_req* const                       p_cm_req,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
                OUT                     cep_agent_t** const                     pp_port_cep )\r
 {\r
        cep_agent_t             *p_port_cep;\r
@@ -4525,40 +4556,12 @@ __save_user_req(
                return IB_INVALID_SETTING;\r
        }\r
 \r
-       p_cep->sid = p_cm_req->svc_id;\r
-\r
+       p_cep->sid = p_cm_req->service_id;\r
        p_cep->idx_primary = 0;\r
-\r
-       p_cep->p2p = (p_cm_req->pfn_cm_req_cb != NULL);\r
-\r
-       if( p_cm_req->p_compare_buffer )\r
-       {\r
-               if( !p_cm_req->compare_length ||\r
-                       (p_cm_req->compare_offset + p_cm_req->compare_length) >\r
-                       IB_REQ_PDATA_SIZE )\r
-               {\r
-                       AL_EXIT( AL_DBG_CM );\r
-                       return IB_INVALID_SETTING;\r
-               }\r
-               p_cep->p_cmp_buf = cl_malloc( p_cm_req->compare_length );\r
-               if( !p_cep->p_cmp_buf )\r
-               {\r
-                       AL_EXIT( AL_DBG_CM );\r
-                       return IB_INSUFFICIENT_MEMORY;\r
-               }\r
-\r
-               cl_memcpy( p_cep->p_cmp_buf,\r
-                       p_cm_req->p_compare_buffer, p_cm_req->compare_length );\r
-\r
-               p_cep->cmp_len = p_cm_req->compare_length;\r
-               p_cep->cmp_offset = p_cm_req->compare_offset;\r
-       }\r
-       else\r
-       {\r
-               p_cep->p_cmp_buf = NULL;\r
-               p_cep->cmp_len = 0;\r
-               p_cep->cmp_offset = 0;\r
-       }\r
+       p_cep->p2p = FALSE;\r
+       p_cep->p_cmp_buf = NULL;\r
+       p_cep->cmp_len = 0;\r
+       p_cep->cmp_offset = 0;\r
        p_cep->was_active = TRUE;\r
 \r
        /* Validate the primary path. */\r
@@ -4571,15 +4574,6 @@ __save_user_req(
 \r
        p_cep->av[0].attr.conn.seq_err_retry_cnt = p_cm_req->retry_cnt;\r
 \r
-       /* Make sure the paths will work on the desired QP. */\r
-       if( p_port_cep->h_ca->obj.p_ci_ca->verbs.guid !=\r
-               p_cm_req->h_qp->obj.p_ci_ca->verbs.guid )\r
-       {\r
-               AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("Primary path not realizable on given QP.\n") );\r
-               return IB_INVALID_SETTING;\r
-       }\r
-\r
        p_cep->local_ca_guid = p_port_cep->h_ca->obj.p_ci_ca->verbs.guid;\r
 \r
        *pp_port_cep = p_port_cep;\r
@@ -4644,7 +4638,7 @@ __save_user_req(
        p_cep->remote_comm_id = 0;\r
 \r
        /* Cache the local QPN. */\r
-       p_cep->local_qpn = p_cm_req->h_qp->num;\r
+       p_cep->local_qpn = p_cm_req->qpn;\r
        p_cep->remote_ca_guid = 0;\r
        p_cep->remote_qpn = 0;\r
 \r
@@ -4662,9 +4656,9 @@ __save_user_req(
         */\r
        p_cep->timewait_time.QuadPart = 0;\r
 \r
-       p_cep->rq_psn = p_cep->local_qpn;\r
+       p_cep->rq_psn = p_cm_req->starting_psn;\r
 \r
-       p_cep->rnr_nak_timeout = p_cm_req->rnr_nak_timeout;\r
+       p_cep->rnr_nak_timeout = rnr_nak_timeout;\r
 \r
        AL_EXIT( AL_DBG_CM );\r
        return IB_SUCCESS;\r
@@ -4672,11 +4666,12 @@ __save_user_req(
 \r
 \r
 ib_api_status_t\r
-al_cep_pre_req(\r
+kal_cep_pre_req(\r
        IN                              ib_al_handle_t                          h_al,\r
        IN                              net32_t                                         cid,\r
-       IN              const   ib_cm_req_t* const                      p_cm_req,\r
-               OUT                     ib_qp_mod_t* const                      p_init )\r
+       IN              const   iba_cm_req* const                       p_cm_req,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
+       IN      OUT                     ib_qp_mod_t* const                      p_init OPTIONAL )\r
 {\r
        ib_api_status_t         status;\r
        kcep_t                          *p_cep;\r
@@ -4687,14 +4682,6 @@ al_cep_pre_req(
 \r
        CL_ASSERT( h_al );\r
        CL_ASSERT( p_cm_req );\r
-       CL_ASSERT( p_init );\r
-\r
-       /* TODO: Code P2P support. */\r
-       if( p_cm_req->pfn_cm_req_cb )\r
-       {\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_UNSUPPORTED;\r
-       }\r
 \r
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
        p_cep = __lookup_cep( h_al, cid );\r
@@ -4713,7 +4700,7 @@ al_cep_pre_req(
                p_cep->p_mad = NULL;\r
                /* Fall through. */\r
        case CEP_STATE_IDLE:\r
-               status = __save_user_req( p_cep, p_cm_req, &p_port_cep );\r
+               status = __save_user_req( p_cep, p_cm_req, rnr_nak_timeout, &p_port_cep );\r
                if( status != IB_SUCCESS )\r
                        break;\r
 \r
@@ -4722,7 +4709,7 @@ al_cep_pre_req(
                if( status != IB_SUCCESS )\r
                        break;\r
 \r
-               status = __format_req( p_cep, p_cm_req );\r
+               status = __format_req( p_port_cep, p_cep, p_cm_req );\r
                if( status != IB_SUCCESS )\r
                {\r
                        AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid pdata length.\n") );\r
@@ -4732,14 +4719,16 @@ al_cep_pre_req(
                }\r
 \r
                /* Format the INIT qp modify attributes. */\r
-               p_init->req_state = IB_QPS_INIT;\r
-               p_init->state.init.primary_port =\r
-                       p_cep->av[p_cep->idx_primary].attr.port_num;\r
-               p_init->state.init.qkey = 0;\r
-               p_init->state.init.pkey_index =\r
-                       p_cep->av[p_cep->idx_primary].pkey_index;\r
-               p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
+               if( p_init )\r
+               {\r
+                       p_init->req_state = IB_QPS_INIT;\r
+                       p_init->state.init.primary_port =\r
+                               p_cep->av[p_cep->idx_primary].attr.port_num;\r
+                       p_init->state.init.qkey = 0;\r
+                       p_init->state.init.pkey_index =\r
+                               p_cep->av[p_cep->idx_primary].pkey_index;\r
+                       p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+               }\r
                p_cep->state = CEP_STATE_PRE_REQ;\r
                break;\r
 \r
@@ -4757,6 +4746,40 @@ al_cep_pre_req(
        return status;\r
 }\r
 \r
+ib_api_status_t\r
+al_cep_pre_req(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN              const   ib_cm_req_t* const                      p_cm_req,\r
+               OUT                     ib_qp_mod_t* const                      p_init )\r
+{\r
+       iba_cm_req req;\r
+       \r
+       RtlZeroMemory(&req, sizeof req);\r
+       req.service_id = p_cm_req->svc_id;\r
+\r
+       req.p_primary_path = p_cm_req->p_primary_path;\r
+       req.p_alt_path = p_cm_req->p_alt_path;\r
+\r
+       req.qpn = p_cm_req->h_qp->num;\r
+       req.qp_type = p_cm_req->qp_type;\r
+       req.starting_psn = req.qpn;\r
+\r
+       req.p_pdata = (void *) p_cm_req->p_req_pdata;\r
+       req.pdata_len = p_cm_req->req_length;\r
+\r
+       req.max_cm_retries = p_cm_req->max_cm_retries;\r
+       req.resp_res = p_cm_req->resp_res;\r
+       req.init_depth = p_cm_req->init_depth;\r
+       req.remote_resp_timeout = p_cm_req->remote_resp_timeout;\r
+       req.flow_ctrl = (uint8_t) p_cm_req->flow_ctrl;\r
+       req.local_resp_timeout = p_cm_req->local_resp_timeout;\r
+       req.rnr_retry_cnt = p_cm_req->rnr_retry_cnt;\r
+       req.retry_cnt = p_cm_req->retry_cnt;\r
+       req.srq = (uint8_t) (p_cm_req->h_qp->h_srq != NULL);\r
+\r
+       return kal_cep_pre_req(h_al, cid, &req, p_cm_req->rnr_nak_timeout, p_init);\r
+}\r
 \r
 ib_api_status_t\r
 al_cep_send_req(\r
@@ -4817,31 +4840,32 @@ al_cep_send_req(
 \r
 static void\r
 __save_user_rep(\r
+       IN                              cep_agent_t* const                      p_port_cep,\r
        IN                              kcep_t* const                           p_cep,\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep )\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN                              uint8_t                                         rnr_nak_timeout )\r
 {\r
        AL_ENTER( AL_DBG_CM );\r
 \r
-       /* Cache the local QPN. */\r
-       p_cep->local_qpn = p_cm_rep->h_qp->num;\r
-       p_cep->rq_psn = p_cep->local_qpn;\r
+       p_cep->local_qpn = p_cm_rep->qpn;\r
+       p_cep->rq_psn = p_cm_rep->starting_psn;\r
        p_cep->init_depth = p_cm_rep->init_depth;\r
 \r
-       ci_ca_lock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+       ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
        /* Check the CA's responder resource max and trim if necessary. */\r
-       if( (p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res <\r
-               p_cep->resp_res) )\r
+       if( p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res <\r
+               p_cep->resp_res )\r
        {\r
                /*\r
                 * The CA cannot handle the requested responder resources.\r
                 * Set the response to the CA's maximum.\r
                 */\r
                p_cep->resp_res = \r
-                       p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res;\r
+                       p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->max_qp_resp_res;\r
        }\r
-       ci_ca_unlock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+       ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
 \r
-       p_cep->rnr_nak_timeout = p_cm_rep->rnr_nak_timeout;\r
+       p_cep->rnr_nak_timeout = rnr_nak_timeout;\r
 \r
        AL_EXIT( AL_DBG_CM );\r
 }\r
@@ -4849,8 +4873,9 @@ __save_user_rep(
 \r
 static ib_api_status_t\r
 __format_rep(\r
+       IN                              cep_agent_t* const                      p_port_cep,\r
        IN                              kcep_t* const                           p_cep,\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep )\r
+       IN              const   iba_cm_rep* const                       p_cm_rep )\r
 {\r
        ib_api_status_t         status;\r
        mad_cm_rep_t            *p_rep;\r
@@ -4898,10 +4923,10 @@ __format_rep(
 \r
        p_rep->resp_resources = p_cep->resp_res;\r
 \r
-       ci_ca_lock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+       ci_ca_lock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
        conn_rep_set_target_ack_delay(\r
-               p_cm_rep->h_qp->obj.p_ci_ca->p_pnp_attr->local_ack_delay, p_rep );\r
-       ci_ca_unlock_attr( p_cm_rep->h_qp->obj.p_ci_ca );\r
+               p_port_cep->h_ca->obj.p_ci_ca->p_pnp_attr->local_ack_delay, p_rep );\r
+       ci_ca_unlock_attr( p_port_cep->h_ca->obj.p_ci_ca );\r
 \r
        p_rep->initiator_depth = p_cep->init_depth;\r
 \r
@@ -4915,7 +4940,7 @@ __format_rep(
        p_rep->local_ca_guid = p_cep->local_ca_guid;\r
 \r
        status = conn_rep_set_pdata(\r
-               p_cm_rep->p_rep_pdata, p_cm_rep->rep_length, p_rep );\r
+               p_cm_rep->p_pdata, p_cm_rep->pdata_len, p_rep );\r
 \r
        conn_rep_clr_rsvd_fields( p_rep );\r
 \r
@@ -4925,12 +4950,12 @@ __format_rep(
 \r
 \r
 \r
-ib_api_status_t\r
+static ib_api_status_t\r
 __al_cep_pre_rep(\r
        IN                              kcep_t                                          *p_cep,\r
-       IN                              void*                                           context,\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
-               OUT                     ib_qp_mod_t* const                      p_init )\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
+               OUT                     ib_qp_mod_t* const                      p_init OPTIONAL )\r
 {\r
        ib_api_status_t         status;\r
        cep_agent_t                     *p_port_cep;\r
@@ -4938,7 +4963,6 @@ __al_cep_pre_rep(
        AL_ENTER( AL_DBG_CM );\r
 \r
        CL_ASSERT( p_cm_rep );\r
-       CL_ASSERT( p_init );\r
 \r
        switch( p_cep->state )\r
        {\r
@@ -4956,9 +4980,9 @@ __al_cep_pre_rep(
                if( status != IB_SUCCESS )\r
                        break;\r
 \r
-               __save_user_rep( p_cep, p_cm_rep );\r
+               __save_user_rep( p_port_cep, p_cep, p_cm_rep, rnr_nak_timeout );\r
 \r
-               status = __format_rep( p_cep, p_cm_rep );\r
+               status = __format_rep( p_port_cep, p_cep, p_cm_rep );\r
                if( status != IB_SUCCESS )\r
                {\r
                        ib_put_mad( p_cep->p_mad );\r
@@ -4967,16 +4991,16 @@ __al_cep_pre_rep(
                }\r
 \r
                /* Format the INIT qp modify attributes. */\r
-               p_init->req_state = IB_QPS_INIT;\r
-               p_init->state.init.primary_port =\r
-                       p_cep->av[p_cep->idx_primary].attr.port_num;\r
-               p_init->state.init.qkey = 0;\r
-               p_init->state.init.pkey_index =\r
-                       p_cep->av[p_cep->idx_primary].pkey_index;\r
-               p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
-               p_cep->context = context;\r
-\r
+               if( p_init )\r
+               {\r
+                       p_init->req_state = IB_QPS_INIT;\r
+                       p_init->state.init.primary_port =\r
+                               p_cep->av[p_cep->idx_primary].attr.port_num;\r
+                       p_init->state.init.qkey = 0;\r
+                       p_init->state.init.pkey_index =\r
+                               p_cep->av[p_cep->idx_primary].pkey_index;\r
+                       p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+               }\r
                /* Just OR in the PREP bit into the state. */\r
                p_cep->state |= CEP_STATE_PREP;\r
                break;\r
@@ -5001,92 +5025,124 @@ al_cep_pre_rep(
        IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
-       ib_api_status_t         status;\r
        kcep_t                          *p_cep;\r
+       iba_cm_rep                      rep;\r
        KLOCK_QUEUE_HANDLE      hdl;\r
+       ib_api_status_t         status;\r
 \r
-       AL_ENTER( AL_DBG_CM );\r
+       RtlZeroMemory(&rep, sizeof rep);\r
+       rep.qpn = p_cm_rep->h_qp->num;\r
+       rep.starting_psn = rep.qpn;\r
 \r
-       CL_ASSERT( h_al );\r
-       CL_ASSERT( p_cm_rep );\r
-       CL_ASSERT( p_init );\r
+       rep.p_pdata = (void *) p_cm_rep->p_rep_pdata;\r
+       rep.pdata_len = p_cm_rep->rep_length;\r
 \r
-       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
-       if( *p_cid != AL_INVALID_CID )\r
-       {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_RESOURCE_BUSY;\r
-       }\r
+       rep.failover_accepted = p_cm_rep->failover_accepted;\r
+       rep.init_depth = p_cm_rep->init_depth;\r
+       rep.flow_ctrl = (uint8_t) p_cm_rep->flow_ctrl;\r
+       rep.rnr_retry_cnt = p_cm_rep->rnr_retry_cnt;\r
+       rep.srq = (uint8_t) (p_cm_rep->h_qp->h_srq != NULL);\r
 \r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
        p_cep = __lookup_cep( h_al, cid );\r
-       if!p_cep )\r
+       if (!p_cep )\r
        {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_INVALID_HANDLE;\r
+               status = IB_INVALID_HANDLE;\r
+               goto out;\r
        }\r
 \r
-       status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
-\r
-       if( status == IB_SUCCESS )\r
+       rep.resp_res = p_cep->resp_res;\r
+       status = __al_cep_pre_rep( p_cep, &rep, p_cm_rep->rnr_nak_timeout, p_init );\r
+       if ( status == IB_SUCCESS )\r
        {\r
+               p_cep->context = context;\r
                p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
                *p_cid = cid;\r
        }\r
 \r
+out:\r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
-       AL_EXIT( AL_DBG_CM );\r
        return status;\r
 }\r
 \r
 \r
 ib_api_status_t\r
-al_cep_pre_rep_ex(\r
+kal_cep_config_pre_rep_copy_cid(\r
        IN                              ib_al_handle_t                          h_al,\r
        IN                              net32_t                                         cid,\r
        IN                              al_pfn_cep_cb_t                         pfn_cb,\r
        IN                              void*                                           context,\r
        IN                              ib_pfn_destroy_cb_t                     pfn_destroy_cb,\r
-       IN              const   ib_cm_rep_t* const                      p_cm_rep,\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
        IN      OUT                     net32_t* const                          p_cid,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
-       ib_api_status_t         status;\r
        kcep_t                          *p_cep;\r
        KLOCK_QUEUE_HANDLE      hdl;\r
-\r
-       AL_ENTER( AL_DBG_CM );\r
+       ib_api_status_t         status;\r
 \r
        CL_ASSERT( h_al );\r
        CL_ASSERT( p_cm_rep );\r
        CL_ASSERT( p_init );\r
 \r
        KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
-       if( *p_cid != AL_INVALID_CID )\r
+       if (*p_cid != AL_INVALID_CID)\r
        {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_RESOURCE_BUSY;\r
+               status = IB_RESOURCE_BUSY;\r
+               goto out;\r
        }\r
 \r
        p_cep = __lookup_cep( h_al, cid );\r
-       if!p_cep )\r
+       if (!p_cep )\r
        {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_INVALID_HANDLE;\r
+               status = IB_INVALID_HANDLE;\r
+               goto out;\r
        }\r
 \r
-       status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
-\r
-       if( status == IB_SUCCESS )\r
+       status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );\r
+       if ( status == IB_SUCCESS )\r
        {\r
                p_cep->pfn_cb = pfn_cb;\r
+               p_cep->context = context;\r
                p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
                *p_cid = cid;\r
        }\r
 \r
+out:\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       return status;\r
+}\r
+\r
+\r
+ib_api_status_t\r
+kal_cep_pre_rep(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN                              uint8_t                                         rnr_nak_timeout,\r
+               OUT                     ib_qp_mod_t* const                      p_init OPTIONAL )\r
+{\r
+       ib_api_status_t         status;\r
+       kcep_t                          *p_cep;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       AL_ENTER( AL_DBG_CM );\r
+\r
+       CL_ASSERT( h_al );\r
+       CL_ASSERT( p_cm_rep );\r
+\r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       p_cep = __lookup_cep( h_al, cid );\r
+       if( !p_cep )\r
+       {\r
+               status = IB_INVALID_HANDLE;\r
+               goto out;\r
+       }\r
+\r
+       status = __al_cep_pre_rep( p_cep, p_cm_rep, rnr_nak_timeout, p_init );\r
+\r
+out:\r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
        AL_EXIT( AL_DBG_CM );\r
        return status;\r
@@ -5110,9 +5166,8 @@ al_cep_send_rep(
        p_cep = __lookup_cep( h_al, cid );\r
        if( !p_cep )\r
        {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               AL_EXIT( AL_DBG_CM );\r
-               return IB_INVALID_HANDLE;\r
+               status = IB_INVALID_HANDLE;\r
+               goto out;\r
        }\r
 \r
        switch( p_cep->state )\r
@@ -5123,7 +5178,9 @@ al_cep_send_rep(
                p_port_cep = __get_cep_agent( p_cep );\r
                if( !p_port_cep )\r
                {\r
+                       // Why call ib_put_mad() here but not below?\r
                        ib_put_mad( p_cep->p_mad );\r
+                       // Why call __remove_cep() below but not here?\r
                        p_cep->state = CEP_STATE_IDLE;\r
                        status = IB_INSUFFICIENT_RESOURCES;\r
                }\r
@@ -5148,6 +5205,7 @@ al_cep_send_rep(
                        ("Invalid state: %d\n", p_cep->state) );\r
                status = IB_INVALID_STATE;\r
        }\r
+out:\r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
        AL_EXIT( AL_DBG_CM );\r
        return status;\r
@@ -5975,6 +6033,263 @@ al_cep_established(
        return status;\r
 }\r
 \r
+static void\r
+__format_path(ib_path_rec_t *p_path, req_path_info_t *p_info,\r
+                         ib_net16_t pkey, uint8_t mtu)\r
+{\r
+       p_path->resv0 = 0;\r
+       p_path->dgid = p_info->local_gid;\r
+       p_path->sgid = p_info->remote_gid;\r
+       p_path->dlid = p_info->local_lid;\r
+       p_path->slid = p_info->remote_lid;\r
+       ib_path_rec_set_hop_flow_raw(p_path, p_info->hop_limit, \r
+                                                                conn_req_path_get_flow_lbl(p_info), 0);\r
+       p_path->tclass = p_info->traffic_class;\r
+       p_path->num_path = 0;\r
+       p_path->pkey = pkey;\r
+       p_path->sl = conn_req_path_get_svc_lvl(p_info);\r
+       p_path->mtu = mtu;\r
+       p_path->rate = conn_req_path_get_pkt_rate(p_info);\r
+       p_path->pkt_life = conn_req_path_get_lcl_ack_timeout(p_info);\r
+       p_path->preference = 0;\r
+       p_path->resv1 = 0;\r
+       p_path->resv2 = 0;\r
+}\r
+\r
+static void\r
+__format_event_req(kcep_t *p_cep, mad_cm_req_t *p_mad, iba_cm_req_event *p_req)\r
+{\r
+       p_req->local_ca_guid = p_cep->local_ca_guid;\r
+       p_req->remote_ca_guid = p_cep->remote_ca_guid;\r
+       p_req->pkey_index = p_cep->av[0].pkey_index;\r
+       p_req->port_num = p_cep->av[0].attr.port_num;\r
+       p_req->req.service_id = p_mad->sid;\r
+\r
+       p_req->req.qpn = conn_req_get_lcl_qpn(p_mad);\r
+       p_req->req.qp_type = conn_req_get_qp_type(p_mad);\r
+       p_req->req.starting_psn = conn_req_get_starting_psn(p_mad);\r
+\r
+       p_req->req.p_pdata = p_mad->pdata;\r
+       p_req->req.pdata_len = IB_REQ_PDATA_SIZE;\r
+\r
+       p_req->req.max_cm_retries = conn_req_get_max_cm_retries(p_mad);\r
+       p_req->req.resp_res = conn_req_get_init_depth(p_mad);\r
+       p_req->req.init_depth = conn_req_get_resp_res(p_mad);\r
+       p_req->req.remote_resp_timeout = conn_req_get_resp_timeout(p_mad);\r
+       p_req->req.flow_ctrl = (uint8_t) conn_req_get_flow_ctrl(p_mad);\r
+       p_req->req.local_resp_timeout = conn_req_get_lcl_resp_timeout(p_mad);\r
+       p_req->req.rnr_retry_cnt = conn_req_get_rnr_retry_cnt(p_mad);\r
+       p_req->req.retry_cnt = conn_req_get_retry_cnt(p_mad);\r
+       p_req->req.srq = 0; // TODO: fix mad_cm_req_t\r
+\r
+       // We can re-use the MAD buffer if we're careful to read out the data\r
+       // that we need before it's overwritten.\r
+       p_req->req.p_primary_path = (ib_path_rec_t *) p_mad;\r
+       __format_path(p_req->req.p_primary_path, &p_mad->primary_path,\r
+                                 p_mad->pkey, conn_req_get_mtu(p_mad));\r
+\r
+       if (p_mad->alternate_path.remote_lid != 0) {\r
+               p_req->req.p_alt_path = p_req->req.p_primary_path + 1;\r
+               __format_path(p_req->req.p_alt_path, &p_mad->alternate_path,\r
+                                         p_req->req.p_primary_path->pkey,\r
+                                         p_req->req.p_primary_path->mtu);\r
+       } else {\r
+               p_req->req.p_alt_path = NULL;\r
+       }\r
+}\r
+\r
+static void\r
+__format_event_rep(mad_cm_rep_t *p_mad, iba_cm_rep_event *p_rep)\r
+{\r
+       p_rep->ca_guid = p_mad->local_ca_guid;\r
+       p_rep->target_ack_delay = conn_rep_get_target_ack_delay(p_mad);\r
+       p_rep->rep.qpn = conn_rep_get_lcl_qpn(p_mad);\r
+       p_rep->rep.starting_psn = conn_rep_get_starting_psn(p_mad);\r
+\r
+       p_rep->rep.p_pdata = p_mad->pdata;\r
+       p_rep->rep.pdata_len = IB_REP_PDATA_SIZE;\r
+\r
+       p_rep->rep.failover_accepted = conn_rep_get_failover(p_mad);\r
+       p_rep->rep.resp_res = p_mad->initiator_depth;\r
+       p_rep->rep.init_depth = p_mad->resp_resources;\r
+       p_rep->rep.flow_ctrl = (uint8_t) conn_rep_get_e2e_flow_ctl(p_mad);\r
+       p_rep->rep.rnr_retry_cnt = conn_rep_get_rnr_retry_cnt(p_mad);\r
+}\r
+\r
+static void\r
+__format_event_rej(mad_cm_rej_t *p_mad, iba_cm_rej_event *p_rej)\r
+{\r
+       p_rej->ari = p_mad->ari;\r
+       p_rej->p_pdata = p_mad->pdata;\r
+       p_rej->reason = p_mad->reason;\r
+       p_rej->ari_length = conn_rej_get_ari_len(p_mad);\r
+       p_rej->pdata_len = IB_MRA_PDATA_SIZE;\r
+}\r
+\r
+static void\r
+__format_event_mra(mad_cm_mra_t *p_mad, iba_cm_mra_event *p_mra)\r
+{\r
+       p_mra->p_pdata = p_mad->pdata;\r
+       p_mra->pdata_len = IB_MRA_PDATA_SIZE;\r
+       p_mra->service_timeout = conn_mra_get_svc_timeout(p_mad);\r
+}\r
+\r
+static void\r
+__format_event_pdata(kcep_t *p_cep, iba_cm_pdata *p_pdata)\r
+{\r
+       p_pdata->p_pdata = p_cep->pdata;\r
+       p_pdata->pdata_len = p_cep->psize;\r
+}\r
+\r
+/*\r
+ * Called after polling a MAD from a CEP to parse the received CM message\r
+ * into readable event data.\r
+ */\r
+void\r
+kal_cep_format_event(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+       IN                              ib_mad_element_t                        *p_mad,\r
+       IN      OUT                     iba_cm_event                            *p_event)\r
+{\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+       kcep_t                          *p_cep;\r
+       \r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       p_cep = __lookup_cep( h_al, cid );\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       switch (p_mad->p_mad_buf->attr_id) {\r
+       case CM_REQ_ATTR_ID:\r
+               if (p_mad->status == IB_SUCCESS) {\r
+                       p_event->type = iba_cm_req_received;\r
+                       __format_event_req(p_cep, (mad_cm_req_t*) p_mad->p_mad_buf, &p_event->data.req);\r
+               } else {\r
+                       p_event->type = iba_cm_req_error;\r
+               }\r
+               break;\r
+       case CM_REP_ATTR_ID:\r
+               if (p_mad->status == IB_SUCCESS) {\r
+                       p_event->type = iba_cm_rep_received;\r
+                       __format_event_rep((mad_cm_rep_t*) p_mad->p_mad_buf, &p_event->data.rep);\r
+               } else {\r
+                       p_event->type = iba_cm_rep_error;\r
+               }\r
+               break;\r
+       case CM_RTU_ATTR_ID:\r
+               p_event->type = iba_cm_rtu_received;\r
+               __format_event_pdata(p_cep, &p_event->data.rtu);\r
+               break;\r
+       case CM_DREQ_ATTR_ID:\r
+               if (p_mad->status == IB_SUCCESS) {\r
+                       p_event->type = iba_cm_dreq_received;\r
+                       __format_event_pdata(p_cep, &p_event->data.dreq);\r
+               } else {\r
+                       p_event->type = iba_cm_dreq_error;\r
+               }\r
+               break;\r
+       case CM_DREP_ATTR_ID:\r
+               p_event->type = iba_cm_drep_received;\r
+               __format_event_pdata(p_cep, &p_event->data.drep);\r
+               break;\r
+       case CM_REJ_ATTR_ID:\r
+               p_event->type = iba_cm_rej_received;\r
+               __format_event_rej((mad_cm_rej_t*) p_mad->p_mad_buf, &p_event->data.rej);\r
+               break;\r
+       case CM_MRA_ATTR_ID:\r
+               p_event->type = iba_cm_mra_received;\r
+               __format_event_mra((mad_cm_mra_t*) p_mad->p_mad_buf, &p_event->data.mra);\r
+               break;\r
+       case CM_LAP_ATTR_ID:\r
+               if (p_mad->status == IB_SUCCESS) {\r
+                       p_event->type = iba_cm_lap_received;\r
+                       // TODO: format lap event\r
+               } else {\r
+                       p_event->type = iba_cm_lap_error;\r
+               }\r
+               break;\r
+       case CM_APR_ATTR_ID:\r
+               p_event->type = iba_cm_apr_received;;\r
+               // TODO: format apr event\r
+               break;\r
+       case CM_SIDR_REQ_ATTR_ID:\r
+               if (p_mad->status == IB_SUCCESS) {\r
+                       p_event->type = iba_cm_sidr_req_received;\r
+                       // TODO: format sidr req event\r
+               } else {\r
+                       p_event->type = iba_cm_sidr_req_error;\r
+               }\r
+               break;\r
+       case CM_SIDR_REP_ATTR_ID:\r
+               p_event->type = iba_cm_sidr_rep_received;\r
+               // TODO: format sidr rep event\r
+               break;\r
+       default:\r
+               CL_ASSERT(0);\r
+       }\r
+}\r
+\r
+\r
+ib_api_status_t\r
+al_cep_get_init_attr(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN                              net32_t                                         cid,\r
+               OUT                     ib_qp_mod_t* const                      p_init )\r
+{\r
+       ib_api_status_t         status;\r
+       kcep_t                          *p_cep;\r
+       KLOCK_QUEUE_HANDLE      hdl;\r
+\r
+       AL_ENTER( AL_DBG_CM );\r
+\r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       p_cep = __lookup_cep( h_al, cid );\r
+       if( !p_cep )\r
+       {\r
+               status = IB_INVALID_HANDLE;\r
+               goto out;\r
+       }\r
+\r
+       switch( p_cep->state )\r
+       {\r
+       case CEP_STATE_PRE_REQ:\r
+       case CEP_STATE_REQ_RCVD:\r
+       case CEP_STATE_PRE_REP:\r
+       case CEP_STATE_REQ_SENT:\r
+       case CEP_STATE_REQ_MRA_RCVD:\r
+       case CEP_STATE_REQ_MRA_SENT:\r
+       case CEP_STATE_PRE_REP_MRA_SENT:\r
+       case CEP_STATE_REP_RCVD:\r
+       case CEP_STATE_REP_SENT:\r
+       case CEP_STATE_REP_MRA_RCVD:\r
+       case CEP_STATE_REP_MRA_SENT:\r
+       case CEP_STATE_ESTABLISHED:\r
+               /* Format the INIT qp modify attributes. */\r
+               cl_memclr(p_init, sizeof(ib_qp_mod_t));\r
+               p_init->req_state = IB_QPS_INIT;\r
+               p_init->state.init.primary_port =\r
+                       p_cep->av[p_cep->idx_primary].attr.port_num;\r
+               p_init->state.init.pkey_index =\r
+                       p_cep->av[p_cep->idx_primary].pkey_index;\r
+               p_init->state.init.access_ctrl = IB_AC_LOCAL_WRITE;\r
+               if ( p_cep->resp_res )\r
+               {\r
+                       p_init->state.init.access_ctrl |= IB_AC_RDMA_READ |\r
+                                                                                         IB_AC_RDMA_WRITE |\r
+                                                                                         IB_AC_ATOMIC;\r
+               }\r
+               status = IB_SUCCESS;\r
+               break;\r
+       default:\r
+               status = IB_INVALID_STATE;\r
+               break;\r
+       }\r
+\r
+out:\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       AL_EXIT( AL_DBG_CM );\r
+       return status;\r
+}\r
 \r
 ib_api_status_t\r
 al_cep_get_rtr_attr(\r
@@ -6002,6 +6317,8 @@ al_cep_get_rtr_attr(
 \r
        switch( p_cep->state )\r
        {\r
+       case CEP_STATE_REQ_RCVD:\r
+       case CEP_STATE_REQ_MRA_SENT:\r
        case CEP_STATE_PRE_REP:\r
        case CEP_STATE_PRE_REP_MRA_SENT:\r
        case CEP_STATE_REP_SENT:\r
index 47e11ea..4638e07 100644 (file)
@@ -981,6 +981,7 @@ __ndi_send_req(
        NTSTATUS nt_status;\r
        ib_cm_req_t cm_req;\r
        ib_qp_mod_t qp_mod;\r
+       al_conn_qp_t *p_qp;\r
 \r
        AL_ENTER( AL_DBG_NDI );\r
 \r
@@ -995,19 +996,28 @@ __ndi_send_req(
        }\r
 \r
        /* Get a CEP and bind it to the QP. */\r
-       status = al_create_cep(\r
-               qp_get_al( h_qp ), __ndi_cm_handler, h_qp, deref_al_obj,\r
-               &((al_conn_qp_t*)h_qp)->cid );\r
+       p_qp = (al_conn_qp_t*)h_qp;\r
+       cl_spinlock_acquire( &h_qp->obj.lock );\r
+       if( h_qp->obj.state != CL_DESTROYING && p_qp->cid == AL_INVALID_CID )\r
+       {\r
+               status = al_create_cep( qp_get_al( h_qp ), __ndi_cm_handler,\r
+                                                               &h_qp->obj, deref_al_obj, &p_qp->cid );\r
+       }\r
+       else \r
+       {\r
+               status = IB_RESOURCE_BUSY;\r
+       }\r
+       cl_spinlock_release( &h_qp->obj.lock );\r
        if( status != IB_SUCCESS )\r
        {\r
                h_qp->p_irp_queue->state = NDI_CM_IDLE;\r
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
                        ("al_create_cep returned %s.\n", ib_get_err_str( status )) );\r
-               return STATUS_INSUFFICIENT_RESOURCES;\r
+               return ib_to_ntstatus( status );\r
        }\r
        AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
                ("Created Active CEP with cid %d, h_al %p, context %p\n",\r
-               ((al_conn_qp_t*)h_qp)->cid, qp_get_al( h_qp ), h_qp ) );\r
+               p_qp->cid, qp_get_al( h_qp ), h_qp ) );\r
 \r
        ref_al_obj( &h_qp->obj ); /* Take CEP reference. */\r
 \r
@@ -1015,8 +1025,7 @@ __ndi_send_req(
        __ndi_fill_cm_req( h_qp, p_req, p_path_rec, &cm_req );\r
 \r
        /* prepare CEP for connection */\r
-       status = al_cep_pre_req( qp_get_al( h_qp ),\r
-               ((al_conn_qp_t*)h_qp)->cid, &cm_req, &qp_mod );\r
+       status = al_cep_pre_req( qp_get_al( h_qp ), p_qp->cid, &cm_req, &qp_mod );\r
        if( status != STATUS_SUCCESS )\r
        {\r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
@@ -1025,7 +1034,7 @@ __ndi_send_req(
        }\r
 \r
        /* send CM REQ */\r
-       status = al_cep_send_req( qp_get_al( h_qp ), ((al_conn_qp_t*)h_qp)->cid );\r
+       status = al_cep_send_req( qp_get_al( h_qp ), p_qp->cid );\r
        if( status != IB_SUCCESS )\r
        {\r
                AL_PRINT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
@@ -1038,7 +1047,7 @@ __ndi_send_req(
        return STATUS_SUCCESS;\r
 \r
 error:\r
-       al_destroy_cep( qp_get_al( h_qp ), &((al_conn_qp_t*)h_qp)->cid, TRUE );\r
+       al_destroy_cep( qp_get_al( h_qp ), &p_qp->cid, TRUE );\r
        \r
        switch( status )\r
        {\r
@@ -1469,24 +1478,20 @@ static void
 __ndi_fill_cm_rep(\r
        IN              ib_qp_handle_t  const                           h_qp,\r
        IN              ual_ndi_rep_cm_ioctl_in_t                       *p_rep,\r
-               OUT     ib_cm_rep_t                                                     *p_cm_rep)\r
+               OUT     iba_cm_rep                                                      *p_cm_rep)\r
 {\r
        AL_ENTER( AL_DBG_NDI );\r
 \r
-       memset( p_cm_rep, 0, sizeof(ib_cm_rep_t) );\r
+       memset( p_cm_rep, 0, sizeof(*p_cm_rep) );\r
 \r
-       p_cm_rep->p_rep_pdata = p_rep->pdata;\r
-       p_cm_rep->rep_length = sizeof(p_rep->pdata);\r
+       p_cm_rep->p_pdata = p_rep->pdata;\r
+       p_cm_rep->pdata_len = sizeof(p_rep->pdata);\r
 \r
-       p_cm_rep->qp_type = IB_QPT_RELIABLE_CONN;\r
-       p_cm_rep->h_qp = h_qp;\r
+       p_cm_rep->qpn = h_qp->num;\r
 \r
-       p_cm_rep->access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
        p_cm_rep->init_depth = p_rep->init_depth;\r
-       p_cm_rep->target_ack_delay = 10;\r
        p_cm_rep->failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
        p_cm_rep->flow_ctrl = TRUE;     /* HCAs must support end-to-end flow control. */\r
-       p_cm_rep->rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;\r
        p_cm_rep->rnr_retry_cnt = QP_ATTRIB_RNR_RETRY;\r
 \r
        AL_EXIT( AL_DBG_NDI );\r
@@ -1499,7 +1504,7 @@ __ndi_send_rep(
        IN              PIRP                                                            p_irp )\r
 {\r
        IO_STACK_LOCATION       *p_io_stack;\r
-       ib_cm_rep_t cm_rep;\r
+       iba_cm_rep cm_rep;\r
        ib_qp_mod_t qp_mod;\r
        ib_api_status_t status;\r
        ual_ndi_rep_cm_ioctl_in_t *p_rep = \r
@@ -1528,9 +1533,9 @@ __ndi_send_rep(
        ref_al_obj( &h_qp->obj ); /* Take CEP reference. */\r
 \r
        /* prepare Passive CEP for connection */\r
-       status = al_cep_pre_rep_ex(\r
-               qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, h_qp, deref_al_obj,\r
-               &cm_rep, &((al_conn_qp_t*)h_qp)->cid, &qp_mod );\r
+       status = kal_cep_config_pre_rep_copy_cid(\r
+               qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler, &h_qp->obj, deref_al_obj,\r
+               &cm_rep, QP_ATTRIB_RNR_NAK_TIMEOUT, &((al_conn_qp_t*)h_qp)->cid, &qp_mod);\r
        if( status != IB_SUCCESS )\r
        {\r
                IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
@@ -1539,7 +1544,7 @@ __ndi_send_rep(
                al_destroy_cep( qp_get_al( h_qp ), &p_rep->cid, FALSE );\r
                deref_al_obj( &h_qp->obj ); /* Release CEP reference. */\r
                AL_PRINT_EXIT( TRACE_LEVEL_ERROR, AL_DBG_ERROR,\r
-                       ("al_cep_pre_rep_ex returned %s.\n", ib_get_err_str( status )) );\r
+                       ("kal_cep_config_pre_rep_copy_cid returned %s.\n", ib_get_err_str( status )) );\r
                switch (status)\r
                {\r
                        case IB_INVALID_HANDLE:\r
index e6b3875..3f95afc 100644 (file)
 #include "complib/cl_memory.h"\r
 #include <initguid.h>\r
 #include "iba/ib_ci_ifc.h"\r
+#include "iba/ib_cm_ifc.h"\r
+#include "al_cm_cep.h"\r
 \r
 \r
 /* Interface names are generated by IoRegisterDeviceInterface. */\r
 static UNICODE_STRING  al_ifc_name;\r
 static UNICODE_STRING  ci_ifc_name;\r
+static UNICODE_STRING  cm_ifc_name;\r
 \r
 KEVENT                                 g_ControlEvent;\r
 ULONG                                  g_bfi_InstanceCount;\r
@@ -101,6 +104,11 @@ __query_ci_ifc(
        IN                              DEVICE_OBJECT* const            p_dev_obj,\r
        IN                              IO_STACK_LOCATION* const        p_io_stack );\r
 \r
+static NTSTATUS\r
+__query_cm_ifc(\r
+       IN                              DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                              IO_STACK_LOCATION* const        p_io_stack );\r
+\r
 static NTSTATUS\r
 fdo_query_interface(\r
        IN                              DEVICE_OBJECT* const            p_dev_obj,\r
@@ -130,6 +138,7 @@ __fdo_set_power(
 #pragma alloc_text (PAGE, fdo_query_bus_relations)\r
 #pragma alloc_text (PAGE, __query_al_ifc)\r
 #pragma alloc_text (PAGE, __query_ci_ifc)\r
+#pragma alloc_text (PAGE, __query_cm_ifc)\r
 #pragma alloc_text (PAGE, __get_relations)\r
 #pragma alloc_text (PAGE, fdo_query_interface)\r
 #pragma alloc_text (PAGE_PNP, __fdo_query_power)\r
@@ -211,16 +220,15 @@ bus_add_device(
                {\r
                        BUS_PRINT( BUS_DBG_ERROR, \r
                                ("Failed to create ControlDeviceObject, status %x.\n",status) );\r
-                       goto bail;\r
+                       goto err1;\r
                }\r
                IoDeleteSymbolicLink( &dos_name );\r
                status = IoCreateSymbolicLink( &dos_name, &dev_name );\r
                if( !NT_SUCCESS(status) )\r
                {\r
-                       IoDeleteDevice( p_dev_obj );\r
                        BUS_PRINT( BUS_DBG_ERROR,\r
                                ("Failed to create symlink for dos name.\n") );\r
-                       goto bail;\r
+                       goto err2;\r
                }\r
        }\r
        else {\r
@@ -231,7 +239,7 @@ bus_add_device(
                {\r
                        BUS_PRINT( BUS_DBG_ERROR, \r
                                ("Failed to create bus root FDO device.\n") );\r
-                       goto bail;\r
+                       goto err1;\r
                }\r
        }\r
 \r
@@ -242,10 +250,9 @@ bus_add_device(
        p_next_do = IoAttachDeviceToDeviceStack( p_dev_obj, p_pdo );\r
        if( !p_next_do )\r
        {\r
-               IoDeleteDevice( p_dev_obj );\r
                BUS_PRINT( BUS_DBG_ERROR, ("IoAttachToDeviceStack failed.\n") );\r
                status = STATUS_NO_SUCH_DEVICE;\r
-               goto bail;\r
+               goto err2;\r
        }\r
 \r
        cl_init_pnp_po_ext( p_dev_obj, p_next_do, p_pdo, bus_globals.dbg_lvl,\r
@@ -265,13 +272,11 @@ bus_add_device(
                                                                                &al_ifc_name );\r
        if( !NT_SUCCESS( status ) )\r
        {\r
-               IoDetachDevice( p_ext->cl_ext.p_next_do );\r
-               IoDeleteDevice( p_dev_obj );\r
                BUS_PRINT( BUS_DBG_ERROR, \r
                        ("IoRegisterDeviceInterface for upper interface returned %08x\n",\r
                        status) );\r
                status = STATUS_NO_SUCH_DEVICE;\r
-               goto bail;\r
+               goto err3;\r
        }\r
 \r
        /* Register the lower (CI) interface (the one used by HCA VPDs). */\r
@@ -279,13 +284,22 @@ bus_add_device(
                                                                                &ci_ifc_name );\r
        if( !NT_SUCCESS( status ) )\r
        {\r
-               IoDetachDevice( p_ext->cl_ext.p_next_do );\r
-               IoDeleteDevice( p_dev_obj );\r
                BUS_PRINT( BUS_DBG_ERROR, \r
                        ("IoRegisterDeviceInterface for lower interface returned %08x\n",\r
                        status) );\r
                status = STATUS_NO_SUCH_DEVICE;\r
-               goto bail;\r
+               goto err3;\r
+       }\r
+\r
+       status = IoRegisterDeviceInterface( p_pdo, &GUID_INFINIBAND_INTERFACE_CM, NULL,\r
+                                                                               &cm_ifc_name );\r
+       if( !NT_SUCCESS( status ) )\r
+       {\r
+               BUS_PRINT( BUS_DBG_ERROR, \r
+                       ("IoRegisterDeviceInterface for cm interface returned %08x\n",\r
+                       status) );\r
+               status = STATUS_NO_SUCH_DEVICE;\r
+               goto err3;\r
        }\r
 \r
 adxit:\r
@@ -294,7 +308,11 @@ adxit:
        BUS_EXIT( BUS_DBG_PNP );\r
        return STATUS_SUCCESS;\r
 \r
-bail:\r
+err3:\r
+       IoDetachDevice( p_ext->cl_ext.p_next_do );\r
+err2:\r
+       IoDeleteDevice( p_dev_obj );\r
+err1:\r
        BUS_PRINT( BUS_DBG_PNP, ("%s exit status 0x%x\n", p_bfi->whoami,status) );\r
        ic = free_bfi(p_bfi);\r
        /* if last Bus filter, then cleanup */\r
@@ -374,6 +392,9 @@ fdo_start(
 \r
                status = IoSetDeviceInterfaceState( &ci_ifc_name, TRUE );\r
                ASSERT( NT_SUCCESS( status ) );\r
+\r
+               status = IoSetDeviceInterfaceState( &cm_ifc_name, TRUE );\r
+               ASSERT( NT_SUCCESS( status ) );\r
        }\r
 \r
        BUS_PRINT(BUS_DBG_PNP,\r
@@ -490,8 +511,11 @@ fdo_release_resources(
        ASSERT( NT_SUCCESS( status ) );\r
        status = IoSetDeviceInterfaceState( &ci_ifc_name, FALSE );\r
        ASSERT( NT_SUCCESS( status ) );\r
+       status = IoSetDeviceInterfaceState( &cm_ifc_name, FALSE );\r
+       ASSERT( NT_SUCCESS( status ) );\r
 \r
        /* Release the memory allocated for the interface symbolic names. */\r
+       RtlFreeUnicodeString( &cm_ifc_name );\r
        RtlFreeUnicodeString( &ci_ifc_name );\r
        RtlFreeUnicodeString( &al_ifc_name );\r
 \r
@@ -908,6 +932,47 @@ __query_ci_ifc(
 }\r
 \r
 \r
+static NTSTATUS\r
+__query_cm_ifc(\r
+       IN                                      DEVICE_OBJECT* const            p_dev_obj,\r
+       IN                                      IO_STACK_LOCATION* const        p_io_stack )\r
+{\r
+       INFINIBAND_INTERFACE_CM *p_ifc;\r
+\r
+       BUS_ENTER( BUS_DBG_PNP );\r
+\r
+       if( p_io_stack->Parameters.QueryInterface.Version != IbaCmVersion(1, 0) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, ("Incorrect interface version (%d)\n",\r
+                       p_io_stack->Parameters.QueryInterface.Version ) );\r
+               return STATUS_NOT_SUPPORTED;\r
+       }\r
+\r
+       if( p_io_stack->Parameters.QueryInterface.Size < sizeof(INFINIBAND_INTERFACE_CM) )\r
+       {\r
+               BUS_TRACE_EXIT( BUS_DBG_PNP, \r
+                       ("Buffer too small (%d given, %d required).\n",\r
+                       p_io_stack->Parameters.QueryInterface.Size, sizeof(INFINIBAND_INTERFACE_CM)) );\r
+               return STATUS_BUFFER_TOO_SMALL;\r
+       }\r
+\r
+       /* Copy the interface. */\r
+       p_ifc = (INFINIBAND_INTERFACE_CM*)p_io_stack->Parameters.QueryInterface.Interface;\r
+\r
+       p_ifc->InterfaceHeader.Size = sizeof(INFINIBAND_INTERFACE_CM);\r
+       p_ifc->InterfaceHeader.Version = IbaCmVersion(1, 0);\r
+       p_ifc->InterfaceHeader.Context = p_dev_obj;\r
+       p_ifc->InterfaceHeader.InterfaceReference = al_ref_ifc;\r
+       p_ifc->InterfaceHeader.InterfaceDereference = al_deref_ifc;\r
+       cm_get_interface(&p_ifc->CM);\r
+\r
+       /* take the reference before returning. */\r
+       al_ref_ifc( p_dev_obj );\r
+       BUS_EXIT( BUS_DBG_PNP );\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+\r
 static NTSTATUS\r
 fdo_query_interface(\r
        IN                                      DEVICE_OBJECT* const    p_dev_obj,\r
@@ -934,6 +999,11 @@ fdo_query_interface(
        {\r
                status = __query_ci_ifc( p_dev_obj, p_io_stack );\r
        }\r
+       else if( IsEqualGUID( p_io_stack->Parameters.QueryInterface.InterfaceType,\r
+               &GUID_INFINIBAND_INTERFACE_CM ) )\r
+       {\r
+               status = __query_cm_ifc( p_dev_obj, p_io_stack );\r
+       }\r
        else\r
        {\r
                status = p_irp->IoStatus.Status;\r
diff --git a/inc/kernel/iba/ib_cm_ifc.h b/inc/kernel/iba/ib_cm_ifc.h
new file mode 100644 (file)
index 0000000..0949482
--- /dev/null
@@ -0,0 +1,296 @@
+/*\r
+ * Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ */\r
+\r
+#ifndef _ib_cm_ifc_h_\r
+#define _ib_cm_ifc_h_\r
+\r
+#include <initguid.h>\r
+#include <iba/ib_al_ifc.h>\r
+#include <iba/ib_types.h>\r
+#include <iba/ib_al.h>\r
+\r
+struct _iba_cm_event;\r
+\r
+typedef struct _iba_cm_id\r
+{\r
+       void            *context;\r
+       NTSTATUS        (*callback)(struct _iba_cm_id *p_id, struct _iba_cm_event *p_event);\r
+       net32_t         cid;\r
+\r
+}      iba_cm_id;\r
+\r
+typedef struct _iba_cm_req\r
+{\r
+       ib_net64_t                                      service_id;\r
+\r
+       ib_path_rec_t                           *p_primary_path;\r
+       ib_path_rec_t                           *p_alt_path;\r
+\r
+       net32_t                                         qpn;\r
+       ib_qp_type_t                            qp_type;\r
+       net32_t                                         starting_psn;\r
+\r
+       void                                            *p_pdata;\r
+       uint8_t                                         pdata_len;\r
+\r
+       uint8_t                                         max_cm_retries;\r
+       uint8_t                                         resp_res;\r
+       uint8_t                                         init_depth;\r
+       uint8_t                                         remote_resp_timeout;\r
+       uint8_t                                         flow_ctrl;\r
+       uint8_t                                         local_resp_timeout;\r
+       uint8_t                                         rnr_retry_cnt;\r
+       uint8_t                                         retry_cnt;\r
+       uint8_t                                         srq;\r
+\r
+}      iba_cm_req;\r
+\r
+typedef struct _iba_cm_req_event\r
+{\r
+       iba_cm_req                                      req;\r
+       net64_t                                         local_ca_guid;\r
+       net64_t                                         remote_ca_guid;\r
+       uint16_t                                        pkey_index;\r
+       uint8_t                                         port_num;\r
+\r
+}      iba_cm_req_event;\r
+\r
+typedef struct _iba_cm_rep\r
+{\r
+       net32_t                                         qpn;\r
+       net32_t                                         starting_psn;\r
+\r
+       void                                            *p_pdata;\r
+       uint8_t                                         pdata_len;\r
+\r
+       ib_cm_failover_t                        failover_accepted;\r
+       uint8_t                                         resp_res;\r
+       uint8_t                                         init_depth;\r
+       uint8_t                                         flow_ctrl;\r
+       uint8_t                                         rnr_retry_cnt;\r
+       uint8_t                                         srq;\r
+\r
+}      iba_cm_rep;\r
+\r
+typedef struct _iba_cm_rep_event\r
+{\r
+       iba_cm_rep                                      rep;\r
+       net64_t                                         ca_guid;\r
+       uint8_t                                         target_ack_delay;\r
+\r
+}      iba_cm_rep_event;\r
+\r
+typedef struct _iba_cm_pdata\r
+{\r
+       void                                            *p_pdata;\r
+       uint8_t                                         pdata_len;\r
+\r
+}      iba_cm_pdata;\r
+typedef iba_cm_pdata                   iba_cm_rtu_event;\r
+typedef iba_cm_pdata                   iba_cm_dreq_event;\r
+typedef iba_cm_pdata                   iba_cm_drep_event;\r
+\r
+typedef struct _iba_cm_rej_event\r
+{\r
+       void                                            *ari;\r
+       void                                            *p_pdata;\r
+       ib_rej_status_t                         reason;\r
+       uint8_t                                         ari_length;\r
+       uint8_t                                         pdata_len;\r
+       \r
+}      iba_cm_rej_event;\r
+\r
+typedef struct _iba_cm_mra_event\r
+{\r
+       void                                            *p_pdata;\r
+       uint8_t                                         pdata_len;\r
+       uint8_t                                         service_timeout;\r
+\r
+}      iba_cm_mra_event;\r
+\r
+typedef struct _iba_cm_lap\r
+{\r
+       ib_path_rec_t                           *p_alt_path;\r
+       void                                            *p_pdata;\r
+       uint8_t                                         pdata_len;\r
+       uint8_t                                         remote_resp_timeout;\r
+\r
+}      iba_cm_lap;\r
+typedef iba_cm_lap iba_cm_lap_event;\r
+\r
+typedef struct _iba_cm_apr\r
+{\r
+       void                                            *p_pdata;\r
+       ib_apr_info_t                           *p_info;\r
+       uint8_t                                         pdata_len;\r
+       uint8_t                                         info_length;\r
+       ib_apr_status_t                         status;\r
+\r
+}      iba_cm_apr;\r
+typedef iba_cm_apr iba_cm_apr_event;\r
+\r
+typedef struct _iba_cm_sidr_req\r
+{\r
+       ib_net64_t                                      service_id;\r
+       ib_path_rec_t                           *p_path;\r
+       void                                            *p_pdata;\r
+       uint8_t                                         pdata_len;\r
+       uint8_t                                         max_cm_retries;\r
+       uint32_t                                        timeout;\r
+\r
+}      iba_cm_sidr_req;\r
+\r
+typedef struct _iba_cm_sidr_req_event\r
+{\r
+       iba_cm_sidr_req                         sidr_req;\r
+       net64_t                                         ca_guid;\r
+       uint16_t                                        pkey_index;\r
+       uint8_t                                         port_num;\r
+\r
+}      iba_cm_sidr_req_event;\r
+\r
+typedef struct _iba_cm_sidr_rep\r
+{\r
+       net32_t                                         qpn;\r
+       net32_t                                         qkey;\r
+       void                                            *p_pdata;\r
+       void                                            *p_info;\r
+       uint8_t                                         pdata_len;\r
+       uint8_t                                         info_len;\r
+       ib_sidr_status_t                        status;\r
+\r
+}      iba_cm_sidr_rep;\r
+typedef iba_cm_sidr_rep iba_cm_sidr_rep_event;\r
+\r
+typedef enum _iba_cm_event_type\r
+{\r
+       iba_cm_req_error,\r
+       iba_cm_req_received,\r
+       iba_cm_rep_error,\r
+       iba_cm_rep_received,\r
+       iba_cm_rtu_received,\r
+       iba_cm_dreq_error,\r
+       iba_cm_dreq_received,\r
+       iba_cm_drep_received,\r
+       iba_cm_rej_received,\r
+       iba_cm_mra_received,\r
+       iba_cm_lap_error,\r
+       iba_cm_lap_received,\r
+       iba_cm_apr_received,\r
+       iba_cm_sidr_req_error,\r
+       iba_cm_sidr_req_received,\r
+       iba_cm_sidr_rep_received\r
+\r
+}      iba_cm_event_type;\r
+\r
+typedef struct _iba_cm_event\r
+{\r
+       iba_cm_event_type                       type;\r
+       union\r
+       {\r
+               iba_cm_req_event                req;\r
+               iba_cm_rep_event                rep;\r
+               iba_cm_rtu_event                rtu;\r
+               iba_cm_dreq_event               dreq;\r
+               iba_cm_drep_event               drep;\r
+               iba_cm_rej_event                rej;\r
+               iba_cm_mra_event                mra;\r
+               iba_cm_lap_event                lap;\r
+               iba_cm_apr_event                apr;\r
+               iba_cm_sidr_req_event   sidr_req;\r
+               iba_cm_sidr_rep_event   sidr_rep;\r
+\r
+       }       data;\r
+\r
+}      iba_cm_event;\r
+\r
+typedef struct _iba_cm_interface\r
+{\r
+       NTSTATUS                (*create_id)(NTSTATUS (*callback)(iba_cm_id *p_id,\r
+                                                                                                         iba_cm_event *p_event),\r
+                                                                void *context, iba_cm_id **pp_id);\r
+       void                    (*destroy_id)(iba_cm_id *p_id);\r
+\r
+       NTSTATUS                (*listen)(iba_cm_id *p_id, net64_t service_id, void *p_compare_buf,\r
+                                                         uint8_t compare_len, uint8_t compare_offset);\r
+\r
+       NTSTATUS                (*send_req)(iba_cm_id *p_id, iba_cm_req *p_req);\r
+       NTSTATUS                (*send_rep)(iba_cm_id *p_id, iba_cm_rep *p_rep);\r
+       NTSTATUS                (*send_rtu)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);\r
+\r
+       NTSTATUS                (*send_dreq)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);\r
+       NTSTATUS                (*send_drep)(iba_cm_id *p_id, void *p_pdata, uint8_t pdata_len);\r
+\r
+       NTSTATUS                (*send_rej)(iba_cm_id *p_id, ib_rej_status_t status,\r
+                                                               void *p_ari, uint8_t ari_len,\r
+                                                               void *p_pdata, uint8_t pdata_len);\r
+       NTSTATUS                (*send_mra)(iba_cm_id *p_id, uint8_t service_timeout,\r
+                                                               void *p_pdata, uint8_t pdata_len);\r
+\r
+       NTSTATUS                (*send_lap)(iba_cm_id *p_id, iba_cm_lap *p_lap);\r
+       NTSTATUS                (*send_apr)(iba_cm_id *p_id, iba_cm_apr *p_apr);\r
+\r
+       NTSTATUS                (*send_sidr_req)(iba_cm_id *p_id, iba_cm_sidr_req *p_req);\r
+       NTSTATUS                (*send_sidr_rep)(iba_cm_id *p_id, iba_cm_sidr_rep *p_rep);\r
+\r
+       NTSTATUS                (*get_qp_attr)(iba_cm_id *p_id, ib_qp_state_t state,\r
+                                                                  ib_qp_mod_t *p_attr);\r
+\r
+       NTSTATUS                (*migrate)(iba_cm_id *p_id);\r
+       NTSTATUS                (*established)(iba_cm_id *p_id);\r
+\r
+}      iba_cm_interface;\r
+\r
+static inline USHORT IbaCmVersion(UINT8 Major, UINT8 Minor)\r
+{\r
+       return ((USHORT) Major << 8) | ((USHORT) Minor);\r
+}\r
+\r
+static inline UINT8 IbaCmVersionMajor(USHORT Version)\r
+{\r
+       return (UINT8) (Version >> 8);\r
+}\r
+\r
+static inline UINT8 IbaCmVersionMinor(USHORT Version)\r
+{\r
+       return (UINT8) Version;\r
+}\r
+\r
+// {EACC1466-BB2D-4478-B5BE-40EDF7EE08AB}\r
+DEFINE_GUID(GUID_INFINIBAND_INTERFACE_CM, 0xeacc1466, 0xbb2d, 0x4478,\r
+                       0xb5, 0xbe, 0x40, 0xed, 0xf7, 0xee, 0x8, 0xab);\r
+\r
+typedef struct _INFINIBAND_INTERFACE_CM\r
+{\r
+       INTERFACE                       InterfaceHeader;\r
+       iba_cm_interface        CM;\r
+\r
+}      INFINIBAND_INTERFACE_CM;\r
+\r
+#endif // _ib_cm_ifc_h_
\ No newline at end of file