]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
winverbs: rdma cm support added
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 14 Jan 2009 07:13:12 +0000 (07:13 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Wed, 14 Jan 2009 07:13:12 +0000 (07:13 +0000)
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1@1820 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

66 files changed:
branches/winverbs/core/al/al_cm_cep.h
branches/winverbs/core/al/al_mad.c
branches/winverbs/core/al/al_qp.h
branches/winverbs/core/al/kernel/SOURCES
branches/winverbs/core/al/kernel/al_cm.c [new file with mode: 0644]
branches/winverbs/core/al/kernel/al_cm_cep.c
branches/winverbs/core/al/kernel/al_ndi_cm.c
branches/winverbs/core/al/kernel/al_sa_req.c
branches/winverbs/core/bus/kernel/bus_pnp.c
branches/winverbs/core/winmad/kernel/wm_driver.c
branches/winverbs/core/winmad/user/SOURCES
branches/winverbs/core/winverbs/kernel/SOURCES
branches/winverbs/core/winverbs/kernel/winverbs.inx
branches/winverbs/core/winverbs/kernel/wv_cq.c
branches/winverbs/core/winverbs/kernel/wv_driver.c
branches/winverbs/core/winverbs/kernel/wv_driver.h
branches/winverbs/core/winverbs/kernel/wv_ep.c [new file with mode: 0644]
branches/winverbs/core/winverbs/kernel/wv_ep.h
branches/winverbs/core/winverbs/kernel/wv_provider.c
branches/winverbs/core/winverbs/kernel/wv_provider.h
branches/winverbs/core/winverbs/kernel/wv_qp.c
branches/winverbs/core/winverbs/kernel/wv_qp.h
branches/winverbs/core/winverbs/kernel/wv_srq.c
branches/winverbs/core/winverbs/user/SOURCES
branches/winverbs/core/winverbs/user/wv_cq.cpp
branches/winverbs/core/winverbs/user/wv_device.cpp
branches/winverbs/core/winverbs/user/wv_device.h
branches/winverbs/core/winverbs/user/wv_ep.cpp
branches/winverbs/core/winverbs/user/wv_ep.h
branches/winverbs/core/winverbs/user/wv_listen.cpp
branches/winverbs/core/winverbs/user/wv_listen.h
branches/winverbs/core/winverbs/user/wv_pd.cpp
branches/winverbs/core/winverbs/user/wv_provider.cpp
branches/winverbs/core/winverbs/user/wv_provider.h
branches/winverbs/core/winverbs/user/wv_qp.cpp
branches/winverbs/core/winverbs/user/wv_srq.cpp
branches/winverbs/core/winverbs/wv_ioctl.h
branches/winverbs/hw/mlx4/kernel/hca/qp.c
branches/winverbs/hw/mthca/kernel/hca_verbs.c
branches/winverbs/inc/kernel/iba/ib_cm_ifc.h [new file with mode: 0644]
branches/winverbs/inc/kernel/iba/ib_rdma_cm.h [new file with mode: 0644]
branches/winverbs/inc/user/rdma/winverbs.h
branches/winverbs/tests/wvtests/user/SOURCES
branches/winverbs/tests/wvtests/user/wv_main.cpp
branches/winverbs/tools/dirs
branches/winverbs/ulp/dirs
branches/winverbs/ulp/libibverbs/src/Sources
branches/winverbs/ulp/libibverbs/src/device.cpp
branches/winverbs/ulp/libibverbs/src/verbs.cpp
branches/winverbs/ulp/librdmacm/AUTHORS [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/COPYING [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/dirs [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/examples/cmatose/SOURCES [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/examples/cmatose/cmatose.c [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/examples/cmatose/makefile [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/examples/dirs [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/examples/rping/rping.c [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/include/rdma/rdma_cma.h [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/Sources [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/cma.cpp [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/cma.h [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/cma.rc [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/cma_export.def [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/cma_exports.src [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/cma_main.cpp [new file with mode: 0644]
branches/winverbs/ulp/librdmacm/src/makefile [new file with mode: 0644]

index b4aad3fa4a18119cb08dbed62877d5b572a91603..e3159d7971c8e0e9d3716490445ae18bdb8e8647 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_alloc_cep(\r
+       IN                              ib_al_handle_t                          h_al,\r
+       IN      OUT                     net32_t* const                          p_cid );\r
+\r
+ib_api_status_t\r
+kal_config_cep(\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,15 @@ 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      OUT                     ib_qp_mod_t* const                      p_init );\r
+#endif\r
+\r
 ib_api_status_t\r
 al_cep_pre_req(\r
        IN                              ib_al_handle_t                          h_al,\r
@@ -148,22 +174,39 @@ 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
-al_cep_pre_rep_ex(\r
+kal_cep_pre_rep(\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      OUT                     net32_t* const                          p_cid,\r
-               OUT                     ib_qp_mod_t* const                      p_init );\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
+       IN      OUT                     ib_qp_mod_t* const                      p_init );\r
+\r
+void\r
+kal_destroy_cep(\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 +314,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 77641f333f742d83e000d6d61ff8749e265f0cff..05121bac221e48ad73a4ecc49d196e8e3322ad4d 100644 (file)
@@ -2129,7 +2129,8 @@ __mad_svc_match_recv(
 \r
                /* Match on the transaction ID, ignoring internally generated sends. */\r
                AL_EXIT( AL_DBG_MAD_SVC );\r
-               if( (p_recv_hdr->trans_id == h_send->mad_wr.client_tid) &&\r
+               if( al_get_user_tid(p_recv_hdr->trans_id) ==\r
+                       al_get_user_tid(h_send->mad_wr.client_tid) &&\r
                         !__is_internal_send( h_mad_svc->svc_type, h_send->p_send_mad ) )\r
                {\r
                        return h_send;\r
index bb6d8ad730a98113d9a5f9f404ec546c5a5838d0..b8847849ba35f25c0278090577839b17e2c50bcb 100644 (file)
 #endif /* CL_KERNEL */\r
 \r
 \r
-typedef ib_api_status_t\r
-(*ib_pfn_modify_qp_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN              const   ib_qp_mod_t* const                      p_qp_mod,\r
-       IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_post_send_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_send_wr_t* const                     p_send_wr,\r
-       IN                              ib_send_wr_t                            **pp_send_failure OPTIONAL );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_post_recv_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              ib_recv_wr_t* const                     p_recv_wr,\r
-       IN                              ib_recv_wr_t                            **p_recv_failure OPTIONAL );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_init_dgrm_svc_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN              const   ib_dgrm_info_t* const           p_dgrm_info );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_reg_mad_svc_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN              const   ib_mad_svc_t* const                     p_mad_svc,\r
-               OUT                     ib_mad_svc_handle_t* const      ph_mad_svc );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_dereg_mad_svc_t)(\r
-       IN              const   ib_mad_svc_handle_t                     h_mad_svc );\r
-\r
-typedef void\r
-(*ib_pfn_queue_mad_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN                              al_mad_wr_t* const                      p_mad_wr );\r
-\r
-typedef void\r
-(*ib_pfn_resume_mad_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_join_mcast_t)(\r
-       IN              const   ib_qp_handle_t                          h_qp,\r
-       IN              const   ib_mcast_req_t* const           p_mcast_req );\r
-\r
-typedef ib_api_status_t\r
-(*ib_pfn_leave_mcast_t)(\r
-       IN              const   ib_mcast_handle_t                       h_mcast );\r
-\r
-\r
 /*\r
  * Queue pair information required by the access layer.  This structure\r
  * is referenced by a user's QP handle.\r
@@ -132,7 +80,11 @@ typedef struct _ib_qp
         * handle.\r
         */\r
        ib_qp_handle_t                          h_ud_send_qp;\r
-       ib_pfn_post_send_t                      pfn_ud_post_send;\r
+       ib_api_status_t\r
+       (*pfn_ud_post_send)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN                              ib_send_wr_t* const                     p_send_wr,\r
+               IN                              ib_send_wr_t                            **pp_send_failure OPTIONAL );\r
 \r
        ib_cq_handle_t                          h_recv_cq;\r
        ib_cq_handle_t                          h_send_cq;\r
@@ -144,15 +96,44 @@ typedef struct _ib_qp
 \r
        ib_pfn_event_cb_t                       pfn_event_cb;\r
 \r
-       ib_pfn_modify_qp_t                      pfn_modify_qp;\r
-       ib_pfn_post_recv_t                      pfn_post_recv;\r
-       ib_pfn_post_send_t                      pfn_post_send;\r
-       ib_pfn_reg_mad_svc_t            pfn_reg_mad_svc;\r
-       ib_pfn_dereg_mad_svc_t          pfn_dereg_mad_svc;\r
-       ib_pfn_queue_mad_t                      pfn_queue_mad;\r
-       ib_pfn_resume_mad_t                     pfn_resume_mad;\r
-       ib_pfn_init_dgrm_svc_t          pfn_init_dgrm_svc;\r
-       ib_pfn_join_mcast_t                     pfn_join_mcast;\r
+       ib_api_status_t\r
+       (*pfn_modify_qp)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN              const   ib_qp_mod_t* const                      p_qp_mod,\r
+               IN      OUT                     ci_umv_buf_t* const                     p_umv_buf );\r
+       ib_api_status_t\r
+       (*pfn_post_recv)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN                              ib_recv_wr_t* const                     p_recv_wr,\r
+               IN                              ib_recv_wr_t                            **p_recv_failure OPTIONAL );\r
+       ib_api_status_t\r
+       (*pfn_post_send)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN                              ib_send_wr_t* const                     p_send_wr,\r
+               IN                              ib_send_wr_t                            **pp_send_failure OPTIONAL );\r
+       ib_api_status_t\r
+       (*pfn_reg_mad_svc)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN              const   ib_mad_svc_t* const                     p_mad_svc,\r
+                       OUT                     ib_mad_svc_handle_t* const      ph_mad_svc );\r
+       ib_api_status_t\r
+       (*pfn_dereg_mad_svc)(\r
+               IN              const   ib_mad_svc_handle_t                     h_mad_svc );\r
+       void\r
+       (*pfn_queue_mad)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN                              al_mad_wr_t* const                      p_mad_wr );\r
+       void\r
+       (*pfn_resume_mad)(\r
+               IN              const   ib_qp_handle_t                          h_qp );\r
+       ib_api_status_t\r
+       (*pfn_init_dgrm_svc)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN              const   ib_dgrm_info_t* const           p_dgrm_info );\r
+       ib_api_status_t\r
+       (*pfn_join_mcast)(\r
+               IN              const   ib_qp_handle_t                          h_qp,\r
+               IN              const   ib_mcast_req_t* const           p_mcast_req );\r
 \r
 #ifdef CL_KERNEL\r
        ndi_qp_csq_t                            *p_irp_queue;\r
index 5f2e33f68c08122c93ad976f7e638631af08108d..0a80f7eb7effd05d599d37c4a1c0353d18af0cb6 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/branches/winverbs/core/al/kernel/al_cm.c b/branches/winverbs/core/al/kernel/al_cm.c
new file mode 100644 (file)
index 0000000..5ab99ee
--- /dev/null
@@ -0,0 +1,365 @@
+/*\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_destroy_cep(h_al, new_cid);\r
+                               ib_put_mad(mad);\r
+                               continue;\r
+                       }\r
+\r
+                       kal_config_cep(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_config_cep(h_al, new_cid, NULL, NULL, NULL);\r
+                       kal_destroy_cep(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_alloc_cep(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_config_cep(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_destroy_cep(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_qp_mod_t             attr;\r
+       ib_api_status_t ib_status;\r
+       \r
+       attr.state.rtr.rnr_nak_timeout = 0;\r
+       ib_status = kal_cep_pre_req(gh_al, p_id->cid, p_req, &attr);\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_qp_mod_t             attr;\r
+       ib_api_status_t ib_status;\r
+\r
+       ib_status = kal_cep_pre_rep(gh_al, p_id->cid, p_rep, &attr);\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 d5cc4e2966f8aad091442fc58d4c8a767d936dc5..467cfaa9564868b36a416d389995a2670d5fd47e 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,60 @@ __bind_cep(
        cl_spinlock_release( &h_al->obj.lock );\r
 }\r
 \r
+ib_api_status_t\r
+kal_alloc_cep(\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
+       ib_api_status_t         status = IB_SUCCESS;\r
+\r
+       KeAcquireInStackQueuedSpinLock( &gp_cep_mgr->lock, &hdl );\r
+       p_cep = __create_cep();\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+\r
+       if( p_cep )\r
+       {\r
+               __bind_cep(p_cep, h_al, NULL, NULL);\r
+               *p_cid = p_cep->cid;\r
+       }\r
+       else\r
+       {\r
+               status = IB_INSUFFICIENT_MEMORY;\r
+       }\r
+\r
+       return status;\r
+}\r
+\r
+ib_api_status_t\r
+kal_config_cep(\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
+       ib_api_status_t         status = IB_SUCCESS;\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_PARAMETER;\r
+               goto out;\r
+       }\r
+\r
+       p_cep->pfn_cb = pfn_cb;\r
+       p_cep->context = context;\r
+       p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
+\r
+out:\r
+       KeReleaseInStackQueuedSpinLock( &hdl );\r
+       return status;\r
+}\r
 \r
 static inline void\r
 __unbind_cep(\r
@@ -3967,10 +4023,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 +4038,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 +4075,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 +4122,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_alloc_cep(h_al, p_cid);\r
+       if ( status == IB_SUCCESS )\r
        {\r
-               KeReleaseInStackQueuedSpinLock( &hdl );\r
-               return IB_RESOURCE_BUSY;\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
+               kal_config_cep(h_al, *p_cid, pfn_cb, context, pfn_destroy_cb);\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
@@ -4169,10 +4206,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 +4216,14 @@ al_destroy_cep(
        AL_EXIT( AL_DBG_CM );\r
 }\r
 \r
+void\r
+kal_destroy_cep(\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 +4474,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 +4495,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 +4521,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 +4542,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 +4554,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 +4568,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 +4586,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 +4650,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 +4668,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 +4678,11 @@ __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      OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
        ib_api_status_t         status;\r
        kcep_t                          *p_cep;\r
@@ -4689,13 +4695,6 @@ al_cep_pre_req(
        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
        if( !p_cep )\r
@@ -4713,7 +4712,8 @@ 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,\r
+                                                                 p_init->state.rtr.rnr_nak_timeout, &p_port_cep );\r
                if( status != IB_SUCCESS )\r
                        break;\r
 \r
@@ -4722,7 +4722,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
@@ -4757,6 +4757,42 @@ 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
+       p_init->state.rtr.rnr_nak_timeout = p_cm_req->rnr_nak_timeout;\r
+\r
+       return kal_cep_pre_req(h_al, cid, &req, p_init);\r
+}\r
 \r
 ib_api_status_t\r
 al_cep_send_req(\r
@@ -4817,31 +4853,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 +4886,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 +4936,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 +4953,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,11 +4963,10 @@ __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
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
        ib_api_status_t         status;\r
@@ -4956,9 +4993,10 @@ __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,\r
+                                                p_init->state.rtr.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
@@ -4975,8 +5013,6 @@ __al_cep_pre_rep(
                        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
                /* Just OR in the PREP bit into the state. */\r
                p_cep->state |= CEP_STATE_PREP;\r
                break;\r
@@ -5001,55 +5037,54 @@ 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
+       p_init->state.rtr.rnr_nak_timeout = p_cm_rep->rnr_nak_timeout;\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_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_pre_rep(\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      OUT                     net32_t* const                          p_cid,\r
+       IN              const   iba_cm_rep* const                       p_cm_rep,\r
                OUT                     ib_qp_mod_t* const                      p_init )\r
 {\r
        ib_api_status_t         status;\r
@@ -5063,30 +5098,16 @@ al_cep_pre_rep_ex(
        CL_ASSERT( p_init );\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
-\r
        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
-       status = __al_cep_pre_rep( p_cep, context, p_cm_rep, p_init );\r
-\r
-       if( status == IB_SUCCESS )\r
-       {\r
-               p_cep->pfn_cb = pfn_cb;\r
-               p_cep->pfn_destroy_cb = pfn_destroy_cb;\r
-               *p_cid = cid;\r
-       }\r
+       status = __al_cep_pre_rep( p_cep, p_cm_rep, p_init );\r
 \r
+out:\r
        KeReleaseInStackQueuedSpinLock( &hdl );\r
        AL_EXIT( AL_DBG_CM );\r
        return status;\r
@@ -5110,9 +5131,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 +5143,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 +5170,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 +5998,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 +6282,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 47e11ea2d7f231052c6541118912d8cfc3796edc..6339a879245608b65754cf82400c6a58fa9d6ed6 100644 (file)
@@ -1469,24 +1469,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(iba_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 +1495,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
@@ -1524,13 +1520,18 @@ __ndi_send_rep(
 \r
        /* Format ib_cm_req_t structure */\r
        __ndi_fill_cm_rep( h_qp, p_rep, &cm_rep );\r
+       qp_mod.state.rtr.rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;\r
 \r
        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_config_cep(qp_get_al( h_qp ), p_rep->cid, __ndi_cm_handler,\r
+                                                       h_qp, deref_al_obj);\r
+       if ( status == IB_SUCCESS )\r
+       {\r
+               status = kal_cep_pre_rep(qp_get_al( h_qp ), p_rep->cid,\r
+                                                                &cm_rep, &qp_mod );\r
+       }\r
        if( status != IB_SUCCESS )\r
        {\r
                IoFreeWorkItem( p_irp->Tail.Overlay.DriverContext[1] );\r
@@ -1539,7 +1540,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_pre_rep returned %s.\n", ib_get_err_str( status )) );\r
                switch (status)\r
                {\r
                        case IB_INVALID_HANDLE:\r
@@ -1552,6 +1553,10 @@ __ndi_send_rep(
                                return ib_to_ntstatus( status );\r
                }\r
        }\r
+       else\r
+       {\r
+               ((al_conn_qp_t*)h_qp)->cid = p_rep->cid;\r
+       }\r
 \r
        AL_PRINT( TRACE_LEVEL_INFORMATION, AL_DBG_NDI,\r
                ("Prepared Passive CEP with cid %d, h_al %p, context %p\n",\r
index 05a0f4b24e66f3500f671e95f0970b694afb243b..05418d7694002f0e41ef979c9ca40c2b14913b10 100644 (file)
@@ -507,7 +507,7 @@ init_sa_req_svc(
        /* Create an address vector for the SA. */\r
        av_attr.port_num = p_sa_req_svc->port_num;\r
        av_attr.sl = p_sa_req_svc->sm_sl;\r
-       av_attr.dlid = 1;\r
+       av_attr.dlid = cl_hton16(1);\r
        av_attr.grh_valid = FALSE;\r
        av_attr.static_rate = IB_PATH_RECORD_RATE_10_GBS;\r
        av_attr.path_bits = 0;\r
index c5cb4371362bba06939fa2bdc179d923a7f0c70c..88f19d444752b85e1a9b4185feaaa5ee7dd480ac 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
index 8ac92b66bca138add8aa9af5c4a3227306855ade..52245ab4d6942243569af36dedda477239cbbcb0 100644 (file)
@@ -46,9 +46,6 @@ static LIST_ENTRY             DevList;
 static LIST_ENTRY              ProvList;\r
 static KGUARDED_MUTEX  Lock;\r
 \r
-static EVT_WDF_DRIVER_DEVICE_ADD                       WmIbDeviceAdd;\r
-static EVT_WDF_OBJECT_CONTEXT_CLEANUP          WmIbDeviceCleanup;\r
-static EVT_WDF_DEVICE_D0_ENTRY                         WmPowerD0Entry;\r
 static EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL      WmIoDeviceControl;\r
 static EVT_WDF_IO_QUEUE_IO_READ                                WmIoRead;\r
 static EVT_WDF_IO_QUEUE_IO_WRITE                       WmIoWrite;\r
@@ -296,6 +293,10 @@ static NTSTATUS WmPowerD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE Previous
        NTSTATUS                status;\r
 \r
        dev = WmIbDeviceGetContext(Device);\r
+       RtlZeroMemory(dev, sizeof *dev);\r
+       dev->Ref = 1;\r
+       KeInitializeEvent(&dev->Event, NotificationEvent, FALSE);\r
+\r
        status = WdfFdoQueryForInterface(Device, &GUID_RDMA_INTERFACE_VERBS,\r
                                                                         (PINTERFACE) &dev->VerbsInterface,\r
                                                                         sizeof(dev->VerbsInterface), VerbsVersion(2, 0),\r
@@ -332,37 +333,7 @@ static NTSTATUS WmPowerD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE Previous
        return STATUS_SUCCESS;\r
 }\r
 \r
-static NTSTATUS WmIbDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)\r
-{\r
-       WDF_OBJECT_ATTRIBUTES                   attr;\r
-       WDF_PNPPOWER_EVENT_CALLBACKS    power;\r
-       WDFDEVICE                                               dev;\r
-       WM_IB_DEVICE                                    *pdev;\r
-       NTSTATUS                                                status;\r
-\r
-       WdfFdoInitSetFilter(DeviceInit);\r
-\r
-       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WM_IB_DEVICE);\r
-       attr.EvtCleanupCallback = WmIbDeviceCleanup;\r
-\r
-       WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&power);\r
-       power.EvtDeviceD0Entry = WmPowerD0Entry;\r
-       WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &power);\r
-\r
-       status = WdfDeviceCreate(&DeviceInit, &attr, &dev);\r
-       if (!NT_SUCCESS(status)) {\r
-               return status;\r
-       }\r
-\r
-       pdev = WmIbDeviceGetContext(dev);\r
-       RtlZeroMemory(pdev, sizeof *pdev);\r
-       pdev->Ref = 1;\r
-       KeInitializeEvent(&pdev->Event, NotificationEvent, FALSE);\r
-\r
-       return STATUS_SUCCESS;\r
-}\r
-\r
-static VOID WmIbDeviceCleanup(WDFDEVICE Device)\r
+static NTSTATUS WmPowerD0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState)\r
 {\r
        WM_PROVIDER                     *prov;\r
        WM_IB_DEVICE            *pdev;\r
@@ -371,7 +342,7 @@ static VOID WmIbDeviceCleanup(WDFDEVICE Device)
        BOOLEAN                         destroy;\r
        WDFDEVICE                       ctrldev;\r
 \r
-       pdev = (WmIbDeviceGetContext(Device));\r
+       pdev = WmIbDeviceGetContext(Device);\r
 \r
        KeAcquireGuardedMutex(&Lock);\r
        RemoveEntryList(&pdev->Entry);\r
@@ -396,6 +367,31 @@ static VOID WmIbDeviceCleanup(WDFDEVICE Device)
        if (destroy) {\r
                WdfObjectDelete(ctrldev);\r
        }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WmIbDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)\r
+{\r
+       WDF_OBJECT_ATTRIBUTES                   attr;\r
+       WDF_PNPPOWER_EVENT_CALLBACKS    power;\r
+       WDFDEVICE                                               dev;\r
+       NTSTATUS                                                status;\r
+\r
+       WdfFdoInitSetFilter(DeviceInit);\r
+\r
+       WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, WM_IB_DEVICE);\r
+       WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&power);\r
+       power.EvtDeviceD0Entry = WmPowerD0Entry;\r
+       power.EvtDeviceD0Exit = WmPowerD0Exit;\r
+       WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &power);\r
+\r
+       status = WdfDeviceCreate(&DeviceInit, &attr, &dev);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
 }\r
 \r
 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)\r
index f66b99ca08b26e889995dc2ebea87339c3427eae..7fed2a1564349e152304ae7dd98ab0d4480fe2b9 100644 (file)
@@ -14,7 +14,7 @@ DLLDEF = $(OBJ_PATH)\$O\wm_exports.def
 !endif\r
 \r
 DLLENTRY = DllMain\r
-USE_MSVCRT=1\r
+USE_MSVCRT = 1\r
 \r
 SOURCES = \\r
        winmad.rc               \\r
index 721f76f47494dd837d764af3bf53c61d47bbc89d..3322a7d6ec7a80eb96c42d8927d97080a80e00f7 100644 (file)
@@ -19,7 +19,8 @@ SOURCES = \
        wv_cq.c                 \\r
        wv_pd.c                 \\r
        wv_srq.c                \\r
-       wv_qp.c\r
+       wv_qp.c                 \\r
+       wv_ep.c\r
 \r
 INCLUDES = ..;..\..\..\inc;..\..\..\inc\kernel;..\..\..\inc\user;..\..\..\etc\kernel;\r
 \r
index c9c093089ffb2707c09455ae591336d76dfffc5b..225df71ce2d07582e374112fa8612721e16a7218 100644 (file)
@@ -29,7 +29,7 @@
 \r
 [Version]\r
 Signature = "$WINDOWS NT$"\r
-Class=InfiniBandController\r
+Class = InfiniBandController\r
 ClassGUID = {58517E00-D3CF-40c9-A679-CEE5752F4491}\r
 Provider = %OFA%\r
 DriverVer = 05/20/2008\r
index 3c153336b177e1895a72b57fede2dabf15a90484..6adcd15a57ceeafda7958a6e0d05c1c5da257588 100644 (file)
@@ -67,33 +67,18 @@ void WvCqRelease(WV_COMPLETION_QUEUE *pCq)
        WvCqPut(pCq);\r
 }\r
 \r
-static void WvCqCompleteRequests(WDFQUEUE Queue, NTSTATUS ReqStatus)\r
-{\r
-       WDFREQUEST      request;\r
-       NTSTATUS        status;\r
-\r
-       WdfObjectAcquireLock(Queue);\r
-       status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
-\r
-       while (NT_SUCCESS(status)) {\r
-               WdfRequestComplete(request, ReqStatus);\r
-               status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
-       }\r
-       WdfObjectReleaseLock(Queue);\r
-}\r
-\r
 static void WvCqEventHandler(ib_event_rec_t *pEvent)\r
 {\r
        WV_COMPLETION_QUEUE     *cq = pEvent->context;\r
-       WvCqCompleteRequests(cq->Queue, STATUS_UNEXPECTED_IO_ERROR);\r
-       WvCqCompleteRequests(cq->ErrorQueue, STATUS_UNEXPECTED_IO_ERROR);\r
+       WvFlushQueue(cq->Queue, STATUS_UNEXPECTED_IO_ERROR);\r
+       WvFlushQueue(cq->ErrorQueue, STATUS_UNEXPECTED_IO_ERROR);\r
 }\r
 \r
 static void WvCqHandler(void *Context)\r
 {\r
        WV_COMPLETION_QUEUE     *cq = Context;\r
 \r
-       WvCqCompleteRequests(cq->Queue, STATUS_SUCCESS);\r
+       WvFlushQueue(cq->Queue, STATUS_SUCCESS);\r
 }\r
 \r
 static NTSTATUS WvCqAlloc(WV_DEVICE *pDevice, UINT32 *pSize,\r
@@ -341,8 +326,8 @@ void WvCqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)
                goto out;\r
        }\r
 \r
-       WvCqCompleteRequests(cq->Queue, STATUS_CANCELLED);\r
-       WvCqCompleteRequests(cq->ErrorQueue, STATUS_CANCELLED);\r
+       WvFlushQueue(cq->Queue, STATUS_CANCELLED);\r
+       WvFlushQueue(cq->ErrorQueue, STATUS_CANCELLED);\r
        WvCqRelease(cq);\r
 \r
 out:\r
index fb457f264ce7dc1ccec698e48df777a4beec5de7..7824b4bf6beb7736f508ae6c67fd3c9e0db64004 100644 (file)
@@ -54,6 +54,9 @@ WDFDEVICE                             ControlDevice;
 static LIST_ENTRY              DevList;\r
 static LIST_ENTRY              ProvList;\r
 static KGUARDED_MUTEX  Lock;\r
+ULONG                                  RandomSeed;\r
+\r
+INFINIBAND_INTERFACE_CM        IbCmInterface;\r
 \r
 static EVT_WDF_DRIVER_DEVICE_ADD                       WvRdmaDeviceAdd;\r
 static EVT_WDF_OBJECT_CONTEXT_CLEANUP          WvRdmaDeviceCleanup;\r
@@ -88,6 +91,44 @@ void WvRdmaDevicePut(WV_RDMA_DEVICE *pDevice)
        }\r
 }\r
 \r
+\r
+void WvCompleteRequests(WDFQUEUE Queue, NTSTATUS ReqStatus)\r
+{\r
+       WDFREQUEST      request;\r
+       NTSTATUS        status;\r
+\r
+       status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(request, ReqStatus);\r
+               status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
+       }\r
+}\r
+\r
+void WvFlushQueue(WDFQUEUE Queue, NTSTATUS ReqStatus)\r
+{\r
+       WdfObjectAcquireLock(Queue);\r
+       WvCompleteRequests(Queue, ReqStatus);\r
+       WdfObjectReleaseLock(Queue);\r
+}\r
+\r
+void WvCompleteRequestsWithInformation(WDFQUEUE Queue, NTSTATUS ReqStatus)\r
+{\r
+       WDFREQUEST      request;\r
+       NTSTATUS        status;\r
+       UINT8           *out;\r
+       size_t          outlen;\r
+\r
+       status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               outlen = 0;\r
+               WdfRequestRetrieveOutputBuffer(request, 0, &out, &outlen);\r
+               WdfRequestCompleteWithInformation(request, ReqStatus, outlen);\r
+               status = WdfIoQueueRetrieveNextRequest(Queue, &request);\r
+       }\r
+}\r
+\r
 static void WvGuidQuery(WDFREQUEST Request)\r
 {\r
        WV_IO_GUID_LIST *list;\r
@@ -281,77 +322,53 @@ static VOID WvIoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request,
        case WV_IOCTL_QP_CANCEL:\r
                WvQpCancel(prov, Request);\r
                break;\r
-       case WV_IOCTL_ADDRESS_QUERY:\r
-               //WvAddressQuery(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
-               break;\r
        case WV_IOCTL_EP_CREATE:\r
-               //WvEpCreate(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpCreate(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_DESTROY:\r
-               //WvEpDestroy(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpDestroy(prov, Request);\r
+               break;\r
+       case WV_IOCTL_EP_MODIFY:\r
+               WvEpModify(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_BIND:\r
-               //WvEpBind(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpBind(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_REJECT:\r
-               //WvEpReject(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpReject(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_CONNECT:\r
-               //WvEpConnect(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpConnect(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_ACCEPT:\r
-               //WvEpAccept(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpAccept(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_DISCONNECT:\r
-               //WvEpDisconnect(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpDisconnect(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_DISCONNECT_NOTIFY:\r
-               //WvEpDisconnectNotify(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpDisconnectNotify(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_QUERY:\r
-               //WvEpQuery(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpQuery(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_LOOKUP:\r
-               //WvEpLookup(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpLookup(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_MULTICAST_JOIN:\r
-               //WvEpMulticastJoin(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpMulticastJoin(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_MULTICAST_LEAVE:\r
-               //WvEpMulticastLeave(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpMulticastLeave(prov, Request);\r
                break;\r
        case WV_IOCTL_EP_CANCEL:\r
-               //WvEpCancel(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+               WvEpCancel(prov, Request);\r
                break;\r
-       case WV_IOCTL_LISTEN:\r
-               //WvListen(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+       case WV_IOCTL_EP_LISTEN:\r
+               WvEpListen(prov, Request);\r
                break;\r
-       case WV_IOCTL_LISTEN_DESTROY:\r
-               //WvListenDestroy(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
-               break;\r
-       case WV_IOCTL_LISTEN_GET_REQUEST:\r
-               //WvListenGetRequest(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
-               break;\r
-       case WV_IOCTL_LISTEN_CANCEL:\r
-               //WvListenCancel(prov, Request);\r
-               WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+       case WV_IOCTL_EP_GET_REQUEST:\r
+               WvEpGetRequest(prov, Request);\r
                break;\r
        default:\r
                WdfRequestComplete(Request, STATUS_PROCEDURE_NOT_FOUND);\r
@@ -363,9 +380,8 @@ static VOID WvFileCreate(WDFDEVICE Device, WDFREQUEST Request,
                                                 WDFFILEOBJECT FileObject)\r
 {\r
        WV_PROVIDER     *prov = WvProviderGetContext(FileObject);\r
-       UNREFERENCED_PARAMETER(Device);\r
 \r
-       WvProviderInit(prov);\r
+       WvProviderInit(Device, prov);\r
        KeAcquireGuardedMutex(&Lock);\r
        InsertHeadList(&ProvList, &prov->Entry);\r
        KeReleaseGuardedMutex(&Lock);\r
@@ -471,9 +487,13 @@ static NTSTATUS WvPowerD0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE Previous
 \r
        if (create) {\r
                WvCreateControlDevice(WdfGetDriver());\r
+               status = WdfFdoQueryForInterface(Device, &GUID_INFINIBAND_INTERFACE_CM,\r
+                                                                                (PINTERFACE) &IbCmInterface,\r
+                                                                                sizeof(IbCmInterface),\r
+                                                                                IbaCmVersion(1, 0), NULL);\r
        }\r
 \r
-       return STATUS_SUCCESS;\r
+       return status;\r
 }\r
 \r
 static NTSTATUS WvRdmaDeviceAdd(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)\r
@@ -535,8 +555,13 @@ static VOID WvRdmaDeviceCleanup(WDFDEVICE Device)
                KeWaitForSingleObject(&pdev->Event, Executive, KernelMode, FALSE, NULL);\r
        }\r
 \r
-       pdev->Interface.InterfaceHeader.\r
-               InterfaceDereference(pdev->Interface.InterfaceHeader.Context);\r
+       if (IbCmInterface.CM.create_id != NULL) {\r
+               IbCmInterface.InterfaceHeader.InterfaceDereference(IbCmInterface.\r
+                                                                                                                  InterfaceHeader.Context);\r
+       }\r
+\r
+       pdev->Interface.InterfaceHeader.InterfaceDereference(pdev->Interface.\r
+                                                                                                                InterfaceHeader.Context);\r
 \r
        if (destroy) {\r
                WdfObjectDelete(ctrldev);\r
@@ -552,6 +577,7 @@ NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
        InitializeListHead(&DevList);\r
        InitializeListHead(&ProvList);\r
        KeInitializeGuardedMutex(&Lock);\r
+       RandomSeed = (ULONG) (ULONG_PTR) DriverObject;\r
 \r
        WDF_DRIVER_CONFIG_INIT(&config, WvRdmaDeviceAdd);\r
        status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES,\r
index 22d9ae66fecf51baf14d44b6a6a76aa33d88481a..a9e884e5b99aa5629e20289952ef198eaf7bd79d 100644 (file)
 \r
 #include <iba\ib_types.h>\r
 #include <iba\ib_ci.h>\r
+#include <iba\ib_cm_ifc.h>\r
 #include <rdma\verbs.h>\r
 #include "wv_ioctl.h"\r
 \r
 #if WINVER <= _WIN32_WINNT_WINXP\r
-#define KGUARDED_MUTEX FAST_MUTEX\r
+#define KGUARDED_MUTEX                  FAST_MUTEX\r
 #define KeInitializeGuardedMutex ExInitializeFastMutex\r
-#define KeAcquireGuardedMutex ExAcquireFastMutex\r
-#define KeReleaseGuardedMutex ExReleaseFastMutex\r
+#define KeAcquireGuardedMutex   ExAcquireFastMutex\r
+#define KeReleaseGuardedMutex   ExReleaseFastMutex\r
 #endif\r
 \r
-extern WDFDEVICE                       ControlDevice;\r
+extern WDFDEVICE                               ControlDevice;\r
+extern INFINIBAND_INTERFACE_CM IbCmInterface;\r
+extern ULONG                                   RandomSeed;\r
 \r
 typedef struct _WV_RDMA_DEVICE\r
 {\r
@@ -74,4 +77,8 @@ static inline void WvInitVerbsData(ci_umv_buf_t *pVerbsData, UINT32 Command,
        pVerbsData->status = 0;\r
 }\r
 \r
+void WvCompleteRequests(WDFQUEUE Queue, NTSTATUS ReqStatus);\r
+void WvFlushQueue(WDFQUEUE Queue, NTSTATUS ReqStatus);\r
+void WvCompleteRequestsWithInformation(WDFQUEUE Queue, NTSTATUS ReqStatus);\r
+\r
 #endif // _WV_DRIVER_H_\r
diff --git a/branches/winverbs/core/winverbs/kernel/wv_ep.c b/branches/winverbs/core/winverbs/kernel/wv_ep.c
new file mode 100644 (file)
index 0000000..d426a72
--- /dev/null
@@ -0,0 +1,1084 @@
+/*\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 AWV\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 <ntifs.h>\r
+#include <iba/ib_rdma_cm.h>\r
+\r
+#include "wv_ep.h"\r
+#include "wv_qp.h"\r
+#include "wv_ioctl.h"\r
+#include "wv_driver.h"\r
+\r
+#define WV_AF_INET     2\r
+#define WV_AF_INET6    23\r
+\r
+static void WvEpGet(WV_ENDPOINT *pEndpoint)\r
+{\r
+       InterlockedIncrement(&pEndpoint->Ref);\r
+}\r
+\r
+static void WvEpPut(WV_ENDPOINT *pEndpoint)\r
+{\r
+       if (InterlockedDecrement(&pEndpoint->Ref) == 0) {\r
+               KeSetEvent(&pEndpoint->Event, 0, FALSE);\r
+       }\r
+}\r
+\r
+WV_ENDPOINT *WvEpAcquire(WV_PROVIDER *pProvider, UINT64 Id)\r
+{\r
+       WV_ENDPOINT *ep;\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       ep = IndexListAt(&pProvider->EpIndex, (SIZE_T) Id);\r
+       if (ep != NULL) {\r
+               WvEpGet(ep);\r
+       } else {\r
+               ep = NULL;\r
+               WvProviderEnableRemove(pProvider);\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       return ep;\r
+}\r
+\r
+void WvEpRelease(WV_ENDPOINT *pEndpoint)\r
+{\r
+       WvProviderEnableRemove(pEndpoint->pProvider);\r
+       WvEpPut(pEndpoint);\r
+}\r
+\r
+static NTSTATUS WvEpAllocate(WV_PROVIDER *pProvider, UINT16 EpType,\r
+                                                        WV_ENDPOINT **ppEndpoint)\r
+{\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+       WDF_IO_QUEUE_CONFIG     config;\r
+\r
+       ep = ExAllocatePoolWithTag(NonPagedPool, sizeof(WV_ENDPOINT), 'pevw');\r
+       if (ep == NULL) {\r
+               return STATUS_NO_MEMORY;\r
+       }\r
+\r
+       RtlZeroMemory(ep, sizeof(WV_ENDPOINT));\r
+       ep->Ref = 1;\r
+       ep->pProvider = pProvider;\r
+       ep->EpType = EpType;\r
+       KeInitializeEvent(&ep->Event, NotificationEvent, FALSE);\r
+       InitializeListHead(&ep->Entry);\r
+\r
+       WDF_IO_QUEUE_CONFIG_INIT(&config, WdfIoQueueDispatchManual);\r
+       status = WdfIoQueueCreate(ControlDevice, &config,\r
+                                                         WDF_NO_OBJECT_ATTRIBUTES, &ep->Queue);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err;\r
+       }\r
+\r
+       *ppEndpoint = ep;\r
+       return STATUS_SUCCESS;\r
+\r
+err:\r
+       ExFreePool(ep);\r
+       return status;\r
+}\r
+\r
+void WvEpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *pId;\r
+       UINT64                          *type;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &type, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(UINT64), &pId, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       status = WvEpAllocate(pProvider, (UINT16) *type, &ep);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto err1;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       *pId = IndexListInsertHead(&pProvider->EpIndex, ep);\r
+       if (*pId == 0) {\r
+               status = STATUS_NO_MEMORY;\r
+               goto err2;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       WdfRequestCompleteWithInformation(Request, status, sizeof(UINT64));\r
+       return;\r
+\r
+err2:\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+       WvEpFree(ep);\r
+err1:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ENDPOINT             *ep;\r
+       UINT64                  *id;\r
+       NTSTATUS                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       KeAcquireGuardedMutex(&pProvider->Lock);\r
+       WvProviderDisableRemove(pProvider);\r
+       ep = IndexListAt(&pProvider->EpIndex, (SIZE_T) *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+       } else if (ep->Ref > 1) {\r
+               status = STATUS_ACCESS_DENIED;\r
+       } else {\r
+               IndexListRemove(&pProvider->EpIndex, (SIZE_T) *id);\r
+               status = STATUS_SUCCESS;\r
+       }\r
+       KeReleaseGuardedMutex(&pProvider->Lock);\r
+\r
+       if (NT_SUCCESS(status)) {\r
+               WvEpFree(ep);\r
+       }\r
+       WvProviderEnableRemove(pProvider);\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpFree(WV_ENDPOINT *pEndpoint)\r
+{\r
+       if (pEndpoint->pIbCmId != NULL) {\r
+               IbCmInterface.CM.destroy_id(pEndpoint->pIbCmId);\r
+       }\r
+\r
+       if (InterlockedDecrement(&pEndpoint->Ref) > 0) {\r
+               KeWaitForSingleObject(&pEndpoint->Event, Executive, KernelMode, FALSE, NULL);\r
+       }\r
+\r
+       WdfIoQueuePurgeSynchronously(pEndpoint->Queue);\r
+       WdfObjectDelete(pEndpoint->Queue);\r
+       ExFreePool(pEndpoint);\r
+}\r
+\r
+void WvEpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_IO_EP_ATTRIBUTES     *pattr;\r
+       WV_ENDPOINT                     *ep;\r
+       size_t                          len = 0;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_EP_ATTRIBUTES),\r
+                                                                                       &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       *pattr = ep->Attributes;\r
+       WvEpRelease(ep);\r
+       len = sizeof(WV_IO_EP_ATTRIBUTES);\r
+\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+void WvEpModify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                                *pId;\r
+       size_t                                  inlen;\r
+       WV_ENDPOINT                             *ep;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &pId, &inlen);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       if (pId->Data != WV_IO_EP_OPTION_ROUTE) {\r
+               status = STATUS_INVALID_PARAMETER;\r
+               goto complete;\r
+       }\r
+\r
+       if (inlen < sizeof(WV_IO_ID) + sizeof(ib_path_rec_t)) {\r
+               status = STATUS_BUFFER_TOO_SMALL;\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pId->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpAddressBound) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       RtlCopyMemory(&ep->Route, pId + 1, sizeof ep->Route);\r
+       ep->State = WvEpRouteResolved;\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpBind(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_EP_BIND           *pattr;\r
+       WV_ENDPOINT                     *ep;\r
+       size_t                          len = 0;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_BIND),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+       status = WdfRequestRetrieveOutputBuffer(Request, sizeof(WV_IO_EP_BIND),\r
+                                                                                       &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpIdle) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       ep->Attributes.LocalAddress = pattr->Address;\r
+       ep->Attributes.Device = pattr->Device;\r
+       len = sizeof(WV_IO_EP_BIND);\r
+       ep->State = WvEpAddressBound;\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestCompleteWithInformation(Request, status, len);\r
+}\r
+\r
+static UINT64 WvGetServiceId(UINT16 EpType, WV_IO_SOCKADDR_DATA *pAddress)\r
+{\r
+       return RtlUlonglongByteSwap(((UINT64)EpType << 16) +\r
+                  RtlUshortByteSwap(pAddress->SockAddr.In.SinPort));\r
+}\r
+\r
+static int WvAnyAddress(WV_IO_SOCKADDR_DATA *pAddress)\r
+{\r
+       if (pAddress->SockAddr.Sa.SaFamily == WV_AF_INET) {\r
+               return (pAddress->SockAddr.In.SinAddr == 0) ||\r
+                          ((pAddress->SockAddr.In.SinAddr & 0xff) == 0x7f);\r
+       } else {\r
+               return (RtlCompareMemoryUlong(pAddress->SockAddr.In6.Sin6Addr, 16, 0) == 16);\r
+       }\r
+}\r
+\r
+static void WvFormatCmaHeader(IB_CMA_HEADER *pHeader,\r
+                                                         WV_IO_SOCKADDR_DATA *pLocalAddress,\r
+                                                         WV_IO_SOCKADDR_DATA *pPeerAddress)\r
+{\r
+       pHeader->CmaVersion = IB_CMA_VERSION;\r
+       if (pLocalAddress->SockAddr.Sa.SaFamily == WV_AF_INET) {\r
+               pHeader->IpVersion = 4 << 4;\r
+               pHeader->SrcAddress.Ip4.Address = pLocalAddress->SockAddr.In.SinAddr;\r
+               pHeader->DstAddress.Ip4.Address = pPeerAddress->SockAddr.In.SinAddr;\r
+               pHeader->Port = pLocalAddress->SockAddr.In.SinPort;\r
+       } else {\r
+               pHeader->IpVersion = 6 << 4;\r
+               RtlCopyMemory(pHeader->SrcAddress.Ip6Address,\r
+                                         pLocalAddress->SockAddr.In6.Sin6Addr, 16);\r
+               RtlCopyMemory(pHeader->DstAddress.Ip6Address,\r
+                                         pPeerAddress->SockAddr.In6.Sin6Addr, 16);\r
+               pHeader->Port = pLocalAddress->SockAddr.In6.Sin6Port;\r
+       }\r
+}\r
+\r
+static void WvEpSaveReply(WV_ENDPOINT *pEndpoint, iba_cm_rep_event *pReply)\r
+{\r
+       UINT8   len;\r
+\r
+       len = sizeof(pEndpoint->Attributes.Param.Connect.Data);\r
+       RtlCopyMemory(pEndpoint->Attributes.Param.Connect.Data, pReply->rep.p_pdata, len);\r
+       pEndpoint->Attributes.Param.Connect.DataLength = len;\r
+       pEndpoint->Attributes.Param.Connect.InitiatorDepth = pReply->rep.resp_res;\r
+       pEndpoint->Attributes.Param.Connect.ResponderResources = pReply->rep.init_depth;\r
+       pEndpoint->Attributes.Param.Connect.RnrRetryCount = pReply->rep.rnr_retry_cnt;\r
+}\r
+\r
+static NTSTATUS WvEpIbCmHandler(iba_cm_id *pId, iba_cm_event *pEvent)\r
+{\r
+       WV_ENDPOINT     *ep;\r
+\r
+       ep = pId->context;\r
+       switch (pEvent->type) {\r
+       case iba_cm_req_error:\r
+       case iba_cm_rep_error:\r
+       case iba_cm_dreq_error:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_IO_TIMEOUT);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_rep_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpActiveConnect) {\r
+                       WvEpSaveReply(ep, &pEvent->data.rep);\r
+                       WvCompleteRequests(ep->Queue, STATUS_SUCCESS);\r
+               }\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_rtu_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpPassiveConnect) {\r
+                       WvCompleteRequestsWithInformation(ep->Queue, STATUS_SUCCESS);\r
+                       ep->State = WvEpConnected;\r
+               }\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_dreq_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               if (ep->State == WvEpConnected) {\r
+                       ep->State = WvEpPassiveDisconnect;\r
+               } else {\r
+                       ep->State = WvEpDisconnected;\r
+                       IbCmInterface.CM.send_drep(pId, NULL, 0);\r
+               }\r
+               WvCompleteRequests(ep->Queue, STATUS_CONNECTION_DISCONNECTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_drep_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_CONNECTION_DISCONNECTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_rej_received:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_REQUEST_NOT_ACCEPTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       case iba_cm_mra_received:\r
+               break;\r
+       default:\r
+               WdfObjectAcquireLock(ep->Queue);\r
+               ep->State = WvEpDisconnected;\r
+               WvCompleteRequests(ep->Queue, STATUS_NOT_IMPLEMENTED);\r
+               WdfObjectReleaseLock(ep->Queue);\r
+               break;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_EP_CONNECT        *pattr;\r
+       WV_ENDPOINT                     *ep;\r
+       WV_QUEUE_PAIR           *qp;\r
+       iba_cm_req                      req;\r
+       NTSTATUS                        status;\r
+       UINT8                           data[IB_REQ_PDATA_SIZE];\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_CONNECT),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       if (pattr->Param.DataLength > sizeof(pattr->Param.Data)) {\r
+               status = STATUS_INVALID_BUFFER_SIZE;\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       qp = WvQpAcquire(pProvider, pattr->QpId);\r
+       if (qp == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto release;\r
+       }\r
+\r
+       ep->Attributes.PeerAddress = pattr->PeerAddress;\r
+       WvFormatCmaHeader((IB_CMA_HEADER *) data, &ep->Attributes.LocalAddress,\r
+                                         &ep->Attributes.PeerAddress);\r
+\r
+       req.service_id = WvGetServiceId(ep->EpType, &ep->Attributes.PeerAddress);\r
+       req.p_primary_path = &ep->Route;\r
+       req.p_alt_path = NULL;\r
+       req.qpn = qp->Qpn;\r
+       req.qp_type = IB_QPT_RELIABLE_CONN;\r
+       req.starting_psn = (net32_t) RtlRandomEx(&RandomSeed);\r
+       req.p_pdata = data;\r
+       RtlCopyMemory(data + sizeof(IB_CMA_HEADER), pattr->Param.Data,\r
+                                 pattr->Param.DataLength);\r
+       req.pdata_len = sizeof(IB_CMA_HEADER) + pattr->Param.DataLength;\r
+       req.max_cm_retries = IB_CMA_MAX_CM_RETRIES;\r
+       req.resp_res = (UINT8) pattr->Param.ResponderResources;\r
+       req.init_depth = (UINT8) pattr->Param.InitiatorDepth;\r
+       req.remote_resp_timeout = IB_CMA_CM_RESPONSE_TIMEOUT;\r
+       req.flow_ctrl = 1;\r
+       req.local_resp_timeout = IB_CMA_CM_RESPONSE_TIMEOUT;\r
+       req.rnr_retry_cnt = pattr->Param.RnrRetryCount;\r
+       req.retry_cnt = pattr->Param.RetryCount;\r
+       req.srq = (qp->pSrq != NULL);\r
+\r
+       WvQpRelease(qp);\r
+       RtlCopyMemory(&ep->Attributes.Param.Connect, &pattr->Param,\r
+                                 sizeof(pattr->Param));\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpRouteResolved) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       status = IbCmInterface.CM.create_id(WvEpIbCmHandler, ep, &ep->pIbCmId);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release;\r
+       }\r
+\r
+       ep->State = WvEpActiveConnect;\r
+       status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
+       if (NT_SUCCESS(status)) {\r
+               status = IbCmInterface.CM.send_req(ep->pIbCmId, &req);\r
+       }\r
+\r
+       if (!NT_SUCCESS(status)) {\r
+               ep->State = WvEpDisconnected;\r
+       }\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+static NTSTATUS WvEpModifyQpRtr(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp,\r
+                                                               UINT64 ResponderResources, UINT32 Psn,\r
+                                                               UINT8 *pVerbsData, UINT32 VerbsSize)\r
+{\r
+       ib_qp_mod_t                     attr;\r
+       ib_api_status_t         ib_status;\r
+       NTSTATUS                        status;\r
+\r
+       status =IbCmInterface.CM.get_qp_attr(pEndpoint->pIbCmId, IB_QPS_INIT, &attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       \r
+       ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
+                                                                                  VerbsSize, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       status = IbCmInterface.CM.get_qp_attr(pEndpoint->pIbCmId, IB_QPS_RTR, &attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       \r
+       if (pEndpoint->State == WvEpPassiveConnect) {\r
+               attr.state.rtr.resp_res = (UINT8) ResponderResources;\r
+               attr.state.rtr.rq_psn = Psn;\r
+       }\r
+\r
+       ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
+                                                                                  VerbsSize, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WvEpModifyQpRts(WV_ENDPOINT *pEndpoint, WV_QUEUE_PAIR *pQp,\r
+                                                               UINT64 InitiatorDepth,\r
+                                                               UINT8 *pVerbsData, UINT32 VerbsSize)\r
+{\r
+       ib_qp_mod_t                     attr;\r
+       ib_api_status_t         ib_status;\r
+       NTSTATUS                        status;\r
+\r
+       status = IbCmInterface.CM.get_qp_attr(pEndpoint->pIbCmId, IB_QPS_RTS, &attr);\r
+       if (!NT_SUCCESS(status)) {\r
+               return status;\r
+       }\r
+       \r
+       if (pEndpoint->State == WvEpPassiveConnect) {\r
+               attr.state.rts.init_depth = (UINT8) InitiatorDepth;\r
+       }\r
+\r
+       ib_status = pQp->pVerbs->ndi_modify_qp(pQp->hVerbsQp, &attr, NULL,\r
+                                                                                  VerbsSize, pVerbsData);\r
+       if (ib_status != IB_SUCCESS) {\r
+               return STATUS_UNSUCCESSFUL;\r
+       }\r
+\r
+       return STATUS_SUCCESS;\r
+}\r
+\r
+static NTSTATUS WvEpAcceptActive(WDFREQUEST Request, UINT8 *pVerbsData, size_t VerbsSize,\r
+                                                                WV_ENDPOINT *pEndpoint, WV_IO_EP_ACCEPT *pAttr)\r
+{\r
+       WV_QUEUE_PAIR           *qp;\r
+       NTSTATUS                        status;\r
+\r
+       qp = WvQpAcquire(pEndpoint->pProvider, pAttr->QpId);\r
+       if (qp == NULL) {\r
+               return STATUS_NOT_FOUND;\r
+       }\r
+\r
+       status = WvEpModifyQpRtr(pEndpoint, qp, 0, 0, pVerbsData, VerbsSize);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WvEpModifyQpRts(pEndpoint, qp, 0, pVerbsData, VerbsSize);\r
+       }\r
+\r
+       WvQpRelease(qp);\r
+\r
+       WdfObjectAcquireLock(pEndpoint->Queue);\r
+       if (pEndpoint->State != WvEpActiveConnect) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       pEndpoint->State = WvEpConnected;\r
+       status = IbCmInterface.CM.send_rtu(pEndpoint->pIbCmId, pAttr->Param.Data,\r
+                                                                          pAttr->Param.DataLength);\r
+       if (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, STATUS_SUCCESS);\r
+       } else {\r
+               pEndpoint->State = WvEpDisconnected;\r
+       }\r
+\r
+release:\r
+       WdfObjectReleaseLock(pEndpoint->Queue);\r
+       return status;\r
+}\r
+\r
+static NTSTATUS WvEpAcceptPassive(WDFREQUEST Request, UINT8 *pVerbsData, size_t VerbsSize,\r
+                                                                 WV_ENDPOINT *pEndpoint, WV_IO_EP_ACCEPT *pAttr)\r
+{\r
+       WV_QUEUE_PAIR           *qp;\r
+       iba_cm_rep                      rep;\r
+       NTSTATUS                        status;\r
+\r
+       qp = WvQpAcquire(pEndpoint->pProvider, pAttr->QpId);\r
+       if (qp == NULL) {\r
+               return STATUS_NOT_FOUND;\r
+       }\r
+\r
+       rep.qpn = qp->Qpn;\r
+       rep.starting_psn = (net32_t) RtlRandomEx(&RandomSeed);\r
+       rep.p_pdata = pAttr->Param.Data;\r
+       rep.pdata_len = pAttr->Param.DataLength;\r
+       rep.failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
+       rep.resp_res = (UINT8) pAttr->Param.ResponderResources;\r
+       rep.init_depth = (UINT8) pAttr->Param.InitiatorDepth;\r
+       rep.flow_ctrl = 1;\r
+       rep.rnr_retry_cnt = pAttr->Param.RnrRetryCount;\r
+       rep.srq = (qp->pSrq != NULL);\r
+\r
+       status = WvEpModifyQpRtr(pEndpoint, qp, pAttr->Param.ResponderResources,\r
+                                                        rep.starting_psn, pVerbsData, VerbsSize);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WvEpModifyQpRts(pEndpoint, qp, pAttr->Param.InitiatorDepth,\r
+                                                                pVerbsData, VerbsSize);\r
+       }\r
+\r
+       WvQpRelease(qp);\r
+\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       WdfObjectAcquireLock(pEndpoint->Queue);\r
+       if (pEndpoint->State != WvEpPassiveConnect) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       status = IbCmInterface.CM.send_rep(pEndpoint->pIbCmId, &rep);\r
+       if (NT_SUCCESS(status)) {\r
+               status = WdfRequestForwardToIoQueue(Request, pEndpoint->Queue);\r
+       }\r
+       \r
+       if (!NT_SUCCESS(status)) {\r
+               pEndpoint->State = WvEpDisconnected;\r
+       }\r
+\r
+release:\r
+       WdfObjectReleaseLock(pEndpoint->Queue);\r
+out:\r
+       return status;\r
+}\r
+\r
+void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_EP_ACCEPT         *pattr;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+       UINT8                           *out;\r
+       size_t                          outlen;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_ACCEPT),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       status = WdfRequestRetrieveOutputBuffer(Request, 0, &out, &outlen);\r
+       if (!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL) {\r
+               goto complete;\r
+       }\r
+\r
+       if (pattr->Param.DataLength > sizeof(pattr->Param.Data)) {\r
+               status = STATUS_INVALID_BUFFER_SIZE;\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       switch (ep->State) {\r
+       case WvEpActiveConnect:\r
+               status = WvEpAcceptActive(Request, out, outlen, ep, pattr);\r
+               break;\r
+       case WvEpPassiveConnect:\r
+               status = WvEpAcceptPassive(Request, out, outlen, ep, pattr);\r
+               break;\r
+       default:\r
+               status = STATUS_NOT_SUPPORTED;\r
+               break;\r
+       }\r
+\r
+       WvEpRelease(ep);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_IO_ID                        *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+       size_t                          len;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_ID), &id, &len);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, id->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpActiveConnect && ep->State != WvEpPassiveConnect) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       ep->State = WvEpDisconnected;\r
+       status = IbCmInterface.CM.send_rej(ep->pIbCmId, IB_REJ_USER_DEFINED,\r
+                                                                          NULL, 0, id + 1, len - sizeof(WV_IO_ID));\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       switch (ep->State) {\r
+       case WvEpConnected:\r
+               ep->State = WvEpActiveDisconnect;\r
+               status = IbCmInterface.CM.send_dreq(ep->pIbCmId, NULL, 0);\r
+               break;\r
+       case WvEpPassiveDisconnect:\r
+               ep->State = WvEpDisconnected;\r
+               IbCmInterface.CM.send_drep(ep->pIbCmId, NULL, 0);\r
+               status = STATUS_SUCCESS;\r
+               break;\r
+       default:\r
+               status = STATUS_NOT_SUPPORTED;\r
+               break;\r
+       }\r
+\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpDisconnectNotify(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       switch (ep->State) {\r
+       case WvEpConnected:\r
+       case WvEpActiveDisconnect:\r
+               status = WdfRequestForwardToIoQueue(Request, ep->Queue);\r
+               break;\r
+       case WvEpPassiveDisconnect:\r
+       case WvEpDisconnected:\r
+               status = STATUS_CONNECTION_DISCONNECTED;\r
+               break;\r
+       default:\r
+               status = STATUS_NOT_SUPPORTED;\r
+               break;\r
+       }\r
+       WdfObjectReleaseLock(ep->Queue);\r
+\r
+       WvEpRelease(ep);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+static NTSTATUS WvEpIbListenHandler(iba_cm_id *pId, iba_cm_event *pEvent)\r
+{\r
+       WV_ENDPOINT             *listen, *ep;\r
+       WDFREQUEST              request;\r
+       NTSTATUS                status;\r
+       IB_CMA_HEADER   *hdr;\r
+\r
+       listen = ((iba_cm_id *) pId->context)->context;\r
+\r
+       WdfObjectAcquireLock(listen->Queue);\r
+       status = WdfIoQueueRetrieveNextRequest(listen->Queue, &request);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release;\r
+       }\r
+\r
+       ep = CONTAINING_RECORD(RemoveHeadList(&listen->Entry), WV_ENDPOINT, Entry);\r
+       ep->pIbCmId = pId;\r
+       pId->callback = WvEpIbCmHandler;\r
+       pId->context = ep;\r
+\r
+       hdr = pEvent->data.req.req.p_pdata;\r
+       if (hdr->IpVersion == 4) {\r
+               ep->Attributes.LocalAddress.SockAddr.In.SinFamily = WV_AF_INET;\r
+               ep->Attributes.LocalAddress.SockAddr.In.SinAddr = hdr->DstAddress.Ip4.Address;\r
+               ep->Attributes.PeerAddress.SockAddr.In.SinFamily = WV_AF_INET;\r
+               ep->Attributes.PeerAddress.SockAddr.In.SinAddr = hdr->SrcAddress.Ip4.Address;\r
+       } else {\r
+               ep->Attributes.LocalAddress.SockAddr.In6.Sin6Family = WV_AF_INET6; \r
+               RtlCopyMemory(ep->Attributes.LocalAddress.SockAddr.In6.Sin6Addr,\r
+                                         hdr->DstAddress.Ip6Address, 16);\r
+               ep->Attributes.PeerAddress.SockAddr.In6.Sin6Family = WV_AF_INET6;\r
+               RtlCopyMemory(ep->Attributes.PeerAddress.SockAddr.In6.Sin6Addr,\r
+                                         hdr->SrcAddress.Ip6Address, 16);\r
+       }\r
+       ep->Attributes.Device.DeviceGuid = pEvent->data.req.local_ca_guid;\r
+       ep->Attributes.Device.Pkey = pEvent->data.req.req.p_primary_path->pkey;\r
+       ep->Attributes.Device.PortNumber = pEvent->data.req.port_num;\r
+       ep->Attributes.Param.Connect.ResponderResources = pEvent->data.req.req.resp_res;\r
+       ep->Attributes.Param.Connect.InitiatorDepth = pEvent->data.req.req.init_depth;\r
+       ep->Attributes.Param.Connect.RetryCount = pEvent->data.req.req.retry_cnt;\r
+       ep->Attributes.Param.Connect.RnrRetryCount = pEvent->data.req.req.rnr_retry_cnt;\r
+       ep->Attributes.Param.Connect.DataLength = sizeof(ep->Attributes.Param.Connect.Data);\r
+       RtlCopyMemory(ep->Attributes.Param.Connect.Data, hdr + 1,\r
+                                 sizeof(ep->Attributes.Param.Connect.Data));\r
+       ep->Route = *pEvent->data.req.req.p_primary_path;\r
+\r
+       ep->State = WvEpPassiveConnect;\r
+       WvEpPut(ep);\r
+\r
+       WdfRequestComplete(request, STATUS_SUCCESS);\r
+release:\r
+       WdfObjectReleaseLock(listen->Queue);\r
+       return status;\r
+}\r
+\r
+void WvEpListen(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ENDPOINT                     *ep;\r
+       WV_IO_EP_LISTEN         *pattr;\r
+       NTSTATUS                        status;\r
+       void                            *buf;\r
+       UINT8                           offset, len;\r
+       UINT64                          sid;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_LISTEN),\r
+                                                                                  &pattr, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, pattr->Id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       if (WvAnyAddress(&ep->Attributes.LocalAddress)) {\r
+               buf = NULL;\r
+               offset = 0;\r
+               len = 0;\r
+       } else {\r
+               if (ep->Attributes.LocalAddress.SockAddr.Sa.SaFamily == WV_AF_INET) {\r
+                       buf = &ep->Attributes.LocalAddress.SockAddr.In.SinAddr;\r
+                       len = sizeof ep->Attributes.LocalAddress.SockAddr.In.SinAddr;\r
+                       offset = FIELD_OFFSET(IB_CMA_HEADER, DstAddress.Ip4.Address);\r
+               } else {\r
+                       buf = ep->Attributes.LocalAddress.SockAddr.In6.Sin6Addr;\r
+                       len = sizeof ep->Attributes.LocalAddress.SockAddr.In6.Sin6Addr;\r
+                       offset = FIELD_OFFSET(IB_CMA_HEADER, DstAddress.Ip6Address);\r
+               }\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State != WvEpAddressBound) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release;\r
+       }\r
+\r
+       status = IbCmInterface.CM.create_id(WvEpIbListenHandler, ep, &ep->pIbCmId);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release;\r
+       }\r
+\r
+       ep->Attributes.Param.Backlog = pattr->Backlog;\r
+       ep->State = WvEpListening;\r
+       sid = WvGetServiceId(ep->EpType, &ep->Attributes.LocalAddress);\r
+       status = IbCmInterface.CM.listen(ep->pIbCmId, sid, buf, len, offset);\r
+\r
+release:\r
+       WdfObjectReleaseLock(ep->Queue);\r
+       WvEpRelease(ep);\r
+complete:\r
+       WdfRequestComplete(Request, status);\r
+}\r
+\r
+void WvEpGetRequest(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       WV_ENDPOINT                             *listen, *ep;\r
+       WV_IO_EP_GET_REQUEST    *req;\r
+       NTSTATUS                                status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(WV_IO_EP_GET_REQUEST),\r
+                                                                                  &req, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto complete;\r
+       }\r
+\r
+       listen = WvEpAcquire(pProvider, req->Id);\r
+       if (listen == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto complete;\r
+       }\r
+\r
+       if (listen->State != WvEpListening) {\r
+               status = STATUS_NOT_SUPPORTED;\r
+               goto release1;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, req->EpId);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto release1;\r
+       }\r
+\r
+       WdfObjectAcquireLock(ep->Queue);\r
+       if (ep->State == WvEpIdle) {\r
+               ep->State = WvEpQueued;\r
+       } else {\r
+               status = STATUS_CONNECTION_IN_USE;\r
+       }\r
+       WdfObjectReleaseLock(ep->Queue);\r
+\r
+       if (!NT_SUCCESS(status)) {\r
+               goto release2;\r
+       }\r
+\r
+       WdfObjectAcquireLock(listen->Queue);\r
+       status = WdfRequestForwardToIoQueue(Request, listen->Queue);\r
+       if (NT_SUCCESS(status)) {\r
+               InsertTailList(&listen->Entry, &ep->Entry);\r
+               WvEpGet(ep);\r
+       }\r
+       WdfObjectReleaseLock(listen->Queue);\r
+\r
+release2:\r
+       WvEpRelease(ep);\r
+release1:\r
+       WvEpRelease(listen);\r
+complete:\r
+       if (!NT_SUCCESS(status)) {\r
+               WdfRequestComplete(Request, status);\r
+       }\r
+}\r
+\r
+void WvEpLookup(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UNUSED_PARAM(pProvider);\r
+       WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+}\r
+\r
+void WvEpMulticastJoin(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UNUSED_PARAM(pProvider);\r
+       WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+}\r
+\r
+void WvEpMulticastLeave(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UNUSED_PARAM(pProvider);\r
+       WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);\r
+}\r
+\r
+//\r
+// Note that the framework may have already canceled outstanding requests.\r
+//\r
+void WvEpCancelListen(WV_ENDPOINT *pListen)\r
+{\r
+       WV_ENDPOINT                     *ep;\r
+       WDFREQUEST                      request;\r
+       NTSTATUS                        status;\r
+\r
+       WdfObjectAcquireLock(pListen->Queue);\r
+       status = WdfIoQueueRetrieveNextRequest(pListen->Queue, &request);\r
+\r
+       while (NT_SUCCESS(status)) {\r
+               WdfRequestComplete(request, STATUS_CANCELLED);\r
+               status = WdfIoQueueRetrieveNextRequest(pListen->Queue, &request);\r
+       }\r
+\r
+       while (!IsListEmpty(&pListen->Entry)) {\r
+               ep = CONTAINING_RECORD(RemoveHeadList(&pListen->Entry), WV_ENDPOINT, Entry);\r
+               ep->State = WvEpIdle;\r
+               WvEpPut(ep);\r
+       }\r
+\r
+       WdfObjectReleaseLock(pListen->Queue);\r
+}\r
+\r
+void WvEpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)\r
+{\r
+       UINT64                          *id;\r
+       WV_ENDPOINT                     *ep;\r
+       NTSTATUS                        status;\r
+\r
+       status = WdfRequestRetrieveInputBuffer(Request, sizeof(UINT64), &id, NULL);\r
+       if (!NT_SUCCESS(status)) {\r
+               goto out;\r
+       }\r
+\r
+       ep = WvEpAcquire(pProvider, *id);\r
+       if (ep == NULL) {\r
+               status = STATUS_NOT_FOUND;\r
+               goto out;\r
+       }\r
+\r
+       if (ep->State == WvEpListening) {\r
+               WvEpCancelListen(ep);\r
+       } else {\r
+               WvFlushQueue(ep->Queue, STATUS_CANCELLED);\r
+       }\r
+       WvEpRelease(ep);\r
+\r
+out:\r
+       WdfRequestComplete(Request, status);\r
+}\r
index faaad5e065ad6dae4056b07d9a96067956af61ec..703a9644c8871d99b9b8aa3a771f050058913cdd 100644 (file)
 #ifndef _WV_EP_H_\r
 #define _WV_EP_H_\r
 \r
+#include <ntddk.h>\r
 #include <wdm.h>\r
+\r
 #include <iba\ib_types.h>\r
 #include <iba\ib_ci.h>\r
 #include "wv_provider.h"\r
+#include "wv_ioctl.h"\r
 \r
-typedef struct _WV_CONNECT_ENDPOINT\r
+typedef enum _WV_ENDPOINT_STATE\r
 {\r
-       WV_PROVIDER             *pProvider;\r
-       UINT64                  Id;\r
-       LONG                    nRef;\r
+       WvEpIdle,\r
+       WvEpAddressBound,\r
+       WvEpListening,\r
+       WvEpQueued,\r
+       WvEpRouteResolved,\r
+       WvEpPassiveConnect,\r
+       WvEpActiveConnect,\r
+       WvEpConnected,\r
+       WvEpActiveDisconnect,\r
+       WvEpPassiveDisconnect,\r
+       WvEpDisconnected\r
 \r
-}      WV_CONNECT_ENDPOINT;\r
+}      WV_ENDPOINT_STATE;\r
 \r
-typedef struct _WV_DATAGRAM_ENDPOINT\r
+typedef struct _WV_ENDPOINT\r
 {\r
-       WV_PROVIDER             *pProvider;\r
-       UINT64                  Id;\r
-       LONG                    m_nRef;\r
+       WV_PROVIDER                     *pProvider;\r
+       LIST_ENTRY                      Entry;\r
+       WV_ENDPOINT_STATE       State;\r
+\r
+       iba_cm_id                       *pIbCmId;\r
+       WV_IO_EP_ATTRIBUTES     Attributes;\r
+       ib_path_rec_t           Route;\r
+\r
+       UINT16                          EpType;\r
+       KEVENT                          Event;\r
+       LONG                            Ref;\r
+       WDFQUEUE                        Queue;\r
+\r
+}      WV_ENDPOINT;\r
+\r
+void WvEpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpFree(WV_ENDPOINT *pEndpoint);\r
+void WvEpCancelListen(WV_ENDPOINT *pEndpoint);\r
+\r
+void WvEpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpModify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpBind(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpCancel(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+void WvEpConnect(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpAccept(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpReject(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpDisconnect(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpDisconnectNotify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+\r
+void WvEpListen(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpGetRequest(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
 \r
-}      WV_DATAGRAM_ENDPOINT;\r
+void WvEpLookup(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpMulticastJoin(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
+void WvEpMulticastLeave(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
 \r
 #endif // _WV_EP_H_\r
index 04116418f762a171faa2579b5edcc05c03c86f5d..dbf22866be34ad71888e70145cd04b410f7b089d 100644 (file)
@@ -38,6 +38,7 @@
 #include "wv_srq.h"\r
 #include "wv_cq.h"\r
 #include "wv_qp.h"\r
+#include "wv_ep.h"\r
 \r
 void WvProviderGet(WV_PROVIDER *pProvider)\r
 {\r
@@ -51,7 +52,7 @@ void WvProviderPut(WV_PROVIDER *pProvider)
        }\r
 }\r
 \r
-void WvProviderInit(WV_PROVIDER *pProvider)\r
+void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider)\r
 {\r
        IndexListInit(&pProvider->DevIndex);\r
        IndexListInit(&pProvider->CqIndex);\r
@@ -60,6 +61,7 @@ void WvProviderInit(WV_PROVIDER *pProvider)
        IndexListInit(&pProvider->QpIndex);\r
        IndexListInit(&pProvider->MwIndex);\r
        IndexListInit(&pProvider->AhIndex);\r
+       IndexListInit(&pProvider->EpIndex);\r
 \r
        KeInitializeGuardedMutex(&pProvider->Lock);\r
        pProvider->Ref = 1;\r
@@ -81,7 +83,19 @@ void WvProviderCleanup(WV_PROVIDER *pProvider)
        WV_QUEUE_PAIR                   *qp;\r
        WV_MEMORY_WINDOW                *mw;\r
        WV_ADDRESS_HANDLE               *ah;\r
+       WV_ENDPOINT                             *ep;\r
+       SIZE_T                                  i;\r
 \r
+       IndexListForEach(&pProvider->EpIndex, i) {\r
+               ep = (WV_ENDPOINT *) IndexListAt(&pProvider->EpIndex, i);\r
+               if (ep->State == WvEpListening) {\r
+                       WvEpCancelListen(ep);\r
+               }\r
+       }\r
+       while ((ep = IndexListRemoveHead(&pProvider->EpIndex)) != NULL) {\r
+               RemoveEntryList(&ep->Entry);\r
+               WvEpFree(ep);\r
+       }\r
        while ((ah = IndexListRemoveHead(&pProvider->AhIndex)) != NULL) {\r
                RemoveEntryList(&ah->Entry);\r
                WvAhFree(ah);\r
@@ -114,6 +128,7 @@ void WvProviderCleanup(WV_PROVIDER *pProvider)
                KeWaitForSingleObject(&pProvider->Event, Executive, KernelMode, FALSE, NULL);\r
        }\r
 \r
+       IndexListDestroy(&pProvider->EpIndex);\r
        IndexListDestroy(&pProvider->AhIndex);\r
        IndexListDestroy(&pProvider->MwIndex);\r
        IndexListDestroy(&pProvider->QpIndex);\r
index efcea2956f62c9538d1b881c850887e79ff71466..2054551fb686d82301ddb584260a2b3737c6fcb8 100644 (file)
@@ -53,6 +53,7 @@ typedef struct _WV_PROVIDER
        INDEX_LIST              QpIndex;\r
        INDEX_LIST              MwIndex;\r
        INDEX_LIST              AhIndex;\r
+       INDEX_LIST              EpIndex;\r
 \r
        KGUARDED_MUTEX  Lock;\r
        LONG                    Ref;\r
@@ -67,7 +68,7 @@ typedef struct _WV_PROVIDER
 \r
 void WvProviderGet(WV_PROVIDER *pProvider);\r
 void WvProviderPut(WV_PROVIDER *pProvider);\r
-void WvProviderInit(WV_PROVIDER *pProvider);\r
+void WvProviderInit(WDFDEVICE Device, WV_PROVIDER *pProvider);\r
 void WvProviderCleanup(WV_PROVIDER *pProvider);\r
 \r
 void WvProviderRemoveHandler(WV_PROVIDER *pProvider, WV_RDMA_DEVICE *pDevice);\r
index 3d1ed9d924cbdea818de602fa98a49ae1a1e349a..04d92dbdf23a884a6918f7e03f7f84af70f8b12a 100644 (file)
@@ -458,6 +458,7 @@ void WvQpCreate(WV_PROVIDER *pProvider, WDFREQUEST Request)
                goto err3;\r
        }\r
 \r
+       qp->Qpn = ib_attr.num;\r
        KeAcquireGuardedMutex(&pProvider->Lock);\r
        outattr->Id.Id = IndexListInsertHead(&pProvider->QpIndex, qp);\r
        if (outattr->Id.Id == 0) {\r
index 680a6e4430bc18ca5dc30951f30f4f174aea5548..449de59424dcad4247825164186feec486eb507e 100644 (file)
@@ -51,6 +51,7 @@ typedef struct _WV_QUEUE_PAIR
        WV_SHARED_RECEIVE_QUEUE *pSrq;\r
        ci_interface_t                  *pVerbs;\r
        ib_qp_handle_t                  hVerbsQp;\r
+       UINT32                                  Qpn;\r
        LIST_ENTRY                              Entry;\r
        LIST_ENTRY                              McList;\r
 \r
@@ -64,6 +65,9 @@ void WvQpDestroy(WV_PROVIDER *pProvider, WDFREQUEST Request);
 void WvQpFree(WV_QUEUE_PAIR *pQp);\r
 void WvQpRemoveHandler(WV_QUEUE_PAIR *pQp);\r
 \r
+WV_QUEUE_PAIR *WvQpAcquire(WV_PROVIDER *pProvider, UINT64 Id);\r
+void WvQpRelease(WV_QUEUE_PAIR *pQp);\r
+\r
 void WvQpModify(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
 void WvQpQuery(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
 void WvQpAttach(WV_PROVIDER *pProvider, WDFREQUEST Request);\r
index 2be9e56fa483ec4b6ef0ee0580a931ae1cbed0c6..e2379ee0bd9ca8d14be3e23de6520288a5a633b1 100644 (file)
@@ -75,32 +75,19 @@ static void WvVerbsConvertSrq(ib_srq_attr_t *pVerbsAttr,
        pVerbsAttr->srq_limit = pAttr->SrqLimit;\r
 }\r
 \r
-static void WvSrqCompleteRequests(WV_SHARED_RECEIVE_QUEUE *pSrq, NTSTATUS ReqStatus)\r
-{\r
-       WDFREQUEST      request;\r
-       NTSTATUS        status;\r
-\r
-       WdfObjectAcquireLock(pSrq->Queue);\r
-       status = WdfIoQueueRetrieveNextRequest(pSrq->Queue, &request);\r
-\r
-       while (NT_SUCCESS(status)) {\r
-               WdfRequestComplete(request, ReqStatus);\r
-               status = WdfIoQueueRetrieveNextRequest(pSrq->Queue, &request);\r
-       }\r
-       WdfObjectReleaseLock(pSrq->Queue);\r
-}\r
-\r
 static void WvSrqEventHandler(ib_event_rec_t *pEvent)\r
 {\r
+       WV_SHARED_RECEIVE_QUEUE *srq = pEvent->context;\r
+\r
        switch (pEvent->type) {\r
        case IB_AE_SRQ_LIMIT_REACHED:\r
-               WvSrqCompleteRequests(pEvent->context, STATUS_ALERTED);\r
+               WvFlushQueue(srq->Queue, STATUS_ALERTED);\r
                break;\r
        case IB_AE_SRQ_QP_LAST_WQE_REACHED:\r
-               WvSrqCompleteRequests(pEvent->context, STATUS_NOTIFY_CLEANUP);\r
+               WvFlushQueue(srq->Queue, STATUS_NOTIFY_CLEANUP);\r
                break;\r
        default:\r
-               WvSrqCompleteRequests(pEvent->context, STATUS_UNEXPECTED_IO_ERROR);\r
+               WvFlushQueue(srq->Queue, STATUS_UNEXPECTED_IO_ERROR);\r
                break;\r
        }\r
 }\r
@@ -383,7 +370,7 @@ void WvSrqCancel(WV_PROVIDER *pProvider, WDFREQUEST Request)
                goto out;\r
        }\r
 \r
-       WvSrqCompleteRequests(srq, STATUS_CANCELLED);\r
+       WvFlushQueue(srq->Queue, STATUS_CANCELLED);\r
        WvSrqRelease(srq);\r
 \r
 out:\r
index 101315eb4ed9bb316b268abb27d9d261809e16a4..33fa8837522ec9b52eb32077dfafb649c3604040 100644 (file)
@@ -14,7 +14,7 @@ DLLDEF = $(OBJ_PATH)\$O\wv_exports.def
 !endif\r
 \r
 DLLENTRY = DllMain\r
-USE_NTDLL = 1\r
+USE_MSVCRT = 1\r
 \r
 SOURCES = \\r
        winverbs.rc             \\r
@@ -23,7 +23,6 @@ SOURCES = \
        wv_cq.cpp               \\r
        wv_device.cpp   \\r
        wv_ep.cpp               \\r
-       wv_listen.cpp   \\r
        wv_pd.cpp               \\r
        wv_provider.cpp \\r
        wv_qp.cpp               \\r
@@ -36,4 +35,5 @@ USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_WV_SYMBOLS
 \r
 TARGETLIBS = \\r
        $(SDK_LIB_PATH)\kernel32.lib    \\r
-       $(SDK_LIB_PATH)\uuid.lib\r
+       $(SDK_LIB_PATH)\uuid.lib                \\r
+       $(SDK_LIB_PATH)\ws2_32.lib\r
index fafce977886620ec3e3273f751579967c086a08b..9ce1d9a338f5d3242c1650d2d8527d76f1b1e4f5 100644 (file)
@@ -99,7 +99,7 @@ CWVCompletionQueue::~CWVCompletionQueue()
        DWORD   bytes;\r
        HRESULT hr;\r
 \r
-       if (m_Id != NULL) {\r
+       if (m_Id != 0) {\r
                m_pVerbs->pre_destroy_cq(m_hVerbsCq);\r
                hr = WvDeviceIoControl(m_hFile, WV_IOCTL_CQ_DESTROY, &m_Id, sizeof m_Id,\r
                                                           NULL, 0, &bytes, NULL) ?\r
index a90b2145c3f9977c426d0fabd74c9324299cadf6..c3268206d0c7a6e7ef077df319bf6c11d9ef8389 100644 (file)
@@ -293,7 +293,7 @@ out:
 }\r
 \r
 STDMETHODIMP CWVDevice::\r
-FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex)\r
+FindGid(UINT8 PortNumber, WV_GID *pGid, DWORD *pIndex)\r
 {\r
        WV_GID  gid;\r
        DWORD   index;\r
@@ -302,16 +302,16 @@ FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex)
        for (index = 0; true; index++) {\r
                hr = QueryGid(PortNumber, index, &gid);\r
                if (FAILED(hr)) {\r
-                       break;\r
+                       return hr;\r
                }\r
 \r
-               if (RtlCompareMemory(pGid, &gid, sizeof(gid)) == sizeof(gid)) {\r
+               if (RtlEqualMemory(pGid, &gid, sizeof(gid))) {\r
                        *pIndex = (UINT16) index;\r
-                       break;\r
+                       return WV_SUCCESS;\r
                }\r
        }\r
 \r
-       return hr;\r
+       return WV_INVALID_ADDRESS;\r
 }\r
 \r
 STDMETHODIMP CWVDevice::\r
@@ -352,6 +352,28 @@ out:
        return hr;\r
 }\r
 \r
+STDMETHODIMP CWVDevice::\r
+FindPkey(UINT8 PortNumber, NET16 Pkey, DWORD *pIndex)\r
+{\r
+       NET16   key;\r
+       DWORD   index;\r
+       HRESULT hr;\r
+\r
+       for (index = 0; true; index++) {\r
+               hr = QueryPkey(PortNumber, index, &key);\r
+               if (FAILED(hr)) {\r
+                       return hr;\r
+               }\r
+\r
+               if (Pkey == key) {\r
+                       *pIndex = (UINT16) index;\r
+                       return WV_SUCCESS;\r
+               }\r
+       }\r
+\r
+       return WV_INVALID_ADDRESS;\r
+}\r
+\r
 STDMETHODIMP CWVDevice::\r
 CreateCompletionQueue(SIZE_T *pEntries, IWVCompletionQueue** ppCq)\r
 {\r
index 613bab93bb31ee3c95134ad48823a1d14f437bb6..aa2350b39237a08507597e38b6813a1922080f4c 100644 (file)
@@ -55,7 +55,9 @@ public:
        STDMETHODIMP Query(WV_DEVICE_ATTRIBUTES* pAttributes);\r
        STDMETHODIMP QueryPort(UINT8 PortNumber, WV_PORT_ATTRIBUTES* pAttributes);\r
        STDMETHODIMP QueryGid(UINT8 PortNumber, DWORD Index, WV_GID* pGid);\r
+       STDMETHODIMP FindGid(UINT8 PortNumber, WV_GID *pGid, DWORD *pIndex);\r
        STDMETHODIMP QueryPkey(UINT8 PortNumber, DWORD Index, NET16* pPkey);\r
+       STDMETHODIMP FindPkey(UINT8 PortNumber, NET16 Pkey, DWORD *pIndex);\r
        STDMETHODIMP CreateCompletionQueue(SIZE_T *pEntries, IWVCompletionQueue** ppCq);\r
        STDMETHODIMP AllocateProtectionDomain(IWVProtectionDomain** ppPd);\r
        STDMETHODIMP Notify(UINT8 PortNumber, OVERLAPPED* pOverlapped, DWORD* pFlags);\r
@@ -94,7 +96,6 @@ public:
                *ppDevice = NULL;\r
                return hr;\r
        }\r
-       STDMETHODIMP FindGidIndex(UINT8 PortNumber, WV_GID *pGid, UINT16 *pIndex);\r
 \r
        CWVProvider             *m_pProvider;\r
        uvp_interface_t m_Verbs;\r
index 832abbc473a0baf90414c5234da9c33ad0546cbb..6d7fec67d536949d3cdc278af31227c22dacf500 100644 (file)
 #include "wv_memory.h"\r
 #include "wv_ep.h"\r
 #include "wv_ioctl.h"\r
+#include "wv_qp.h"\r
+\r
+static void WvIoConvertConnParam(WV_IO_CONNECT_PARAM *pIoParam,\r
+                                                                WV_CONNECT_PARAM *pParam)\r
+{\r
+       pIoParam->DataLength = (UINT8) pParam->DataLength;\r
+       pIoParam->ResponderResources = pParam->ResponderResources;\r
+       pIoParam->InitiatorDepth = pParam->InitiatorDepth;\r
+       pIoParam->RetryCount = pParam->RetryCount;\r
+       pIoParam->RnrRetryCount = pParam->RnrRetryCount;\r
+       RtlZeroMemory(pIoParam->Reserved, sizeof pIoParam->Reserved);\r
+       RtlCopyMemory(pIoParam->Data, pParam->Data, pParam->DataLength);\r
+}\r
 \r
 CWVConnectEndpoint::CWVConnectEndpoint(CWVProvider *pProvider)\r
 {\r
        pProvider->AddRef();\r
        m_pProvider = pProvider;\r
        m_hFile = pProvider->m_hFile;\r
+       m_Socket = INVALID_SOCKET;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Allocate(void)\r
+{\r
+       UINT64                  EpType;\r
+       DWORD                   bytes;\r
+       HRESULT                 hr;\r
+\r
+       EpType = WV_IO_EP_TYPE_CONNECT;\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,\r
+                                                 &m_Id, sizeof m_Id, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
 }\r
 \r
 CWVConnectEndpoint::~CWVConnectEndpoint()\r
 {\r
+       DWORD   bytes;\r
+\r
+       if (m_Id != 0) {\r
+               WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,\r
+                                                 NULL, 0, &bytes, NULL);\r
+       }\r
+\r
+       if (m_Socket != INVALID_SOCKET) {\r
+               closesocket(m_Socket);\r
+       }\r
        m_pProvider->Release();\r
 }\r
 \r
@@ -88,64 +130,263 @@ GetOverlappedResult(OVERLAPPED *pOverlapped,
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
-BindAddress(const struct sockaddr* pAddress)\r
+Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength)\r
 {\r
-       UNREFERENCED_PARAMETER(pAddress);\r
+       WV_IO_ID                        *pId;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+       CWVBuffer                       buf;\r
+\r
+       bytes = sizeof WV_IO_ID + OptionLength;\r
+       pId = (WV_IO_ID *) buf.Get(bytes);\r
+       if (pId == NULL) {\r
+               return WV_NO_MEMORY;\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       pId->Id = m_Id;\r
+       pId->Data = Option;\r
+       RtlCopyMemory(pId + 1, pOptionData, OptionLength);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_MODIFY, pId, bytes,\r
+                                                 NULL, 0, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       buf.Put();\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
-Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength)\r
+BindAddress(SOCKADDR* pAddress)\r
 {\r
-       UNREFERENCED_PARAMETER(pPrivateData);\r
-       UNREFERENCED_PARAMETER(PrivateDataLength);\r
+       WV_IO_EP_BIND           attr;\r
+       BOOLEAN                         any;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+\r
+       if (pAddress->sa_family == AF_INET) {\r
+               any = (((SOCKADDR_IN *) pAddress)->sin_addr.S_un.S_addr == INADDR_ANY);\r
+               bytes = sizeof(SOCKADDR_IN);\r
+       } else {\r
+               any = IN6ADDR_ISANY((SOCKADDR_IN6 *) pAddress);\r
+               bytes = sizeof(SOCKADDR_IN6);\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       if (any) {\r
+               RtlZeroMemory(&attr.Device, sizeof attr.Device);\r
+       } else {\r
+               hr = m_pProvider->TranslateAddress(pAddress, (WV_DEVICE_ADDRESS *) &attr.Device);\r
+               if (FAILED(hr)) {\r
+                       return hr;\r
+               }\r
+       }\r
+\r
+       m_Socket = socket(pAddress->sa_family, SOCK_STREAM, IPPROTO_TCP);\r
+       if (m_Socket == INVALID_SOCKET) {\r
+               return WSAGetLastError();\r
+       }\r
+\r
+       hr = bind(m_Socket, pAddress, bytes);\r
+       if (FAILED(hr)) {\r
+               goto err;\r
+       }\r
+\r
+       attr.Id = m_Id;\r
+       RtlCopyMemory(&attr.Address, pAddress, bytes);\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_BIND, &attr, sizeof attr,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+               goto err;\r
+       }\r
+\r
+       return WV_SUCCESS;\r
+\r
+err:\r
+       closesocket(m_Socket);\r
+       m_Socket = INVALID_SOCKET;\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
-Connect(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
+Listen(SIZE_T Backlog)\r
 {\r
-       UNREFERENCED_PARAMETER(pQp);\r
-       UNREFERENCED_PARAMETER(pParam);\r
-       UNREFERENCED_PARAMETER(pOverlapped);\r
+       WV_IO_EP_LISTEN         attr;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+\r
+       attr.Id = m_Id;\r
+       attr.Backlog = Backlog;\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_LISTEN, &attr, sizeof attr,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       } else {\r
+               hr = WV_SUCCESS;\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Reject(const VOID* pUserData, SIZE_T UserDataLength)\r
+{\r
+       WV_IO_ID                        *pId;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+       CWVBuffer                       buf;\r
+\r
+       bytes = sizeof WV_IO_ID + UserDataLength;\r
+       pId = (WV_IO_ID *) buf.Get(bytes);\r
+       if (pId == NULL) {\r
+               return WV_NO_MEMORY;\r
+       }\r
+\r
+       pId->Id = m_Id;\r
+       RtlCopyMemory(pId + 1, pUserData, UserDataLength);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_REJECT, pId, bytes,\r
+                                                 NULL, 0, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       buf.Put();\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+GetRequest(IWVConnectEndpoint* pEndpoint, OVERLAPPED* pOverlapped)\r
+{\r
+       WV_IO_EP_GET_REQUEST    req;\r
+       DWORD                                   bytes;\r
+       HRESULT                                 hr;\r
+\r
+       req.Id = m_Id;\r
+       req.EpId = ((CWVConnectEndpoint *) pEndpoint)->m_Id;\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_GET_REQUEST,\r
+                                                 &req, sizeof req, NULL, 0, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVConnectEndpoint::\r
+Connect(IWVConnectQueuePair* pQp, const SOCKADDR* pAddress,\r
+               WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
+{\r
+       WV_IO_EP_CONNECT        attr;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+\r
+       attr.Id = m_Id;\r
+       attr.QpId = ((CWVConnectQueuePair *) pQp)->m_Id;\r
+\r
+       if (pAddress->sa_family == AF_INET) {\r
+               RtlCopyMemory(&attr.PeerAddress, pAddress, sizeof(SOCKADDR_IN));\r
+       } else {\r
+               RtlCopyMemory(&attr.PeerAddress, pAddress, sizeof(SOCKADDR_IN6));\r
+       }\r
+       WvIoConvertConnParam(&attr.Param, pParam);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CONNECT, &attr, sizeof attr,\r
+                                                 NULL, 0, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
 Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped)\r
 {\r
-       UNREFERENCED_PARAMETER(pQp);\r
-       UNREFERENCED_PARAMETER(pParam);\r
-       UNREFERENCED_PARAMETER(pOverlapped);\r
+       CWVConnectQueuePair     *qp = (CWVConnectQueuePair *) pQp;\r
+       WV_IO_EP_ACCEPT         attr;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+       void                            *pout;\r
+       DWORD                           size;\r
+\r
+       attr.Id = m_Id;\r
+       attr.QpId = qp->m_Id;\r
+       qp->m_pVerbs->nd_modify_qp(qp->m_hVerbsQp, &pout, &size);\r
+       WvIoConvertConnParam(&attr.Param, pParam);\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_ACCEPT, &attr, sizeof attr,\r
+                                                 pout, size, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
-Disconnect(OVERLAPPED* pOverlapped)\r
+Disconnect(void)\r
 {\r
-       UNREFERENCED_PARAMETER(pOverlapped);\r
+       DWORD           bytes;\r
+       HRESULT         hr;\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT,\r
+                                                 &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
 NotifyDisconnect(OVERLAPPED* pOverlapped)\r
 {\r
-       UNREFERENCED_PARAMETER(pOverlapped);\r
+       DWORD           bytes;\r
+       HRESULT         hr;\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DISCONNECT_NOTIFY,\r
+                                                 &m_Id, sizeof m_Id, NULL, 0, &bytes, pOverlapped)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVConnectEndpoint::\r
 Query(WV_CONNECT_ATTRIBUTES* pAttributes)\r
 {\r
-       UNREFERENCED_PARAMETER(pAttributes);\r
+       WV_IO_EP_ATTRIBUTES     attr;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
 \r
-       return E_NOTIMPL;\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_QUERY, &m_Id, sizeof m_Id,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       RtlCopyMemory(&pAttributes->LocalAddress, &attr.LocalAddress,\r
+                                 sizeof pAttributes->LocalAddress);\r
+       RtlCopyMemory(&pAttributes->PeerAddress, &attr.PeerAddress,\r
+                                 sizeof pAttributes->PeerAddress);\r
+       RtlCopyMemory(&pAttributes->Device, &attr.Device, sizeof pAttributes->Device);\r
+       pAttributes->Param.DataLength = attr.Param.Connect.DataLength;\r
+       pAttributes->Param.ResponderResources = (SIZE_T) attr.Param.Connect.ResponderResources;\r
+       pAttributes->Param.InitiatorDepth = (SIZE_T) attr.Param.Connect.InitiatorDepth;\r
+       pAttributes->Param.RetryCount = attr.Param.Connect.RetryCount;\r
+       pAttributes->Param.RnrRetryCount = attr.Param.Connect.RnrRetryCount;\r
+       RtlCopyMemory(pAttributes->Param.Data, attr.Param.Connect.Data, attr.Param.Connect.DataLength);\r
+\r
+       return WV_SUCCESS;\r
 }\r
 \r
 \r
@@ -155,9 +396,33 @@ CWVDatagramEndpoint::CWVDatagramEndpoint(CWVProvider *pProvider)
        m_pProvider = pProvider;\r
        m_hFile = pProvider->m_hFile;\r
 }\r
+       \r
+STDMETHODIMP CWVDatagramEndpoint::\r
+Allocate(void)\r
+{\r
+       UINT64                  EpType;\r
+       DWORD                   bytes;\r
+       HRESULT                 hr;\r
+\r
+       EpType = WV_IO_EP_TYPE_DATAGRAM;\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,\r
+                                                 &m_Id, sizeof m_Id, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
+}\r
 \r
 CWVDatagramEndpoint::~CWVDatagramEndpoint()\r
 {\r
+       DWORD   bytes;\r
+\r
+       if (m_Id != 0) {\r
+               WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,\r
+                                                 NULL, 0, &bytes, NULL);\r
+       }\r
        m_pProvider->Release();\r
 }\r
 \r
@@ -206,7 +471,17 @@ GetOverlappedResult(OVERLAPPED *pOverlapped,
 }\r
 \r
 STDMETHODIMP CWVDatagramEndpoint::\r
-BindAddress(const struct sockaddr* pAddress)\r
+Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength)\r
+{\r
+       UNREFERENCED_PARAMETER(Option);\r
+       UNREFERENCED_PARAMETER(pOptionData);\r
+       UNREFERENCED_PARAMETER(OptionLength);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+BindAddress(SOCKADDR* pAddress)\r
 {\r
        UNREFERENCED_PARAMETER(pAddress);\r
 \r
@@ -214,21 +489,38 @@ BindAddress(const struct sockaddr* pAddress)
 }\r
 \r
 STDMETHODIMP CWVDatagramEndpoint::\r
-Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength)\r
+Listen(SIZE_T Backlog)\r
 {\r
-       UNREFERENCED_PARAMETER(pPrivateData);\r
-       UNREFERENCED_PARAMETER(PrivateDataLength);\r
+       UNREFERENCED_PARAMETER(Backlog);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+Reject(const VOID* pUserData, SIZE_T UserDataLength)\r
+{\r
+       UNREFERENCED_PARAMETER(pUserData);\r
+       UNREFERENCED_PARAMETER(UserDataLength);\r
+\r
+       return E_NOTIMPL;\r
+}\r
+\r
+STDMETHODIMP CWVDatagramEndpoint::\r
+GetRequest(IWVDatagramEndpoint* pEndpoint, OVERLAPPED* pOverlapped)\r
+{\r
+       UNREFERENCED_PARAMETER(pEndpoint);\r
+       UNREFERENCED_PARAMETER(pOverlapped);\r
 \r
        return E_NOTIMPL;\r
 }\r
 \r
 STDMETHODIMP CWVDatagramEndpoint::\r
-Lookup(const struct sockaddr* pAddress, const VOID* pPrivateData,\r
-          SIZE_T PrivateDataLength, OVERLAPPED* pOverlapped)\r
+Lookup(const SOCKADDR* pAddress, const VOID* pUserData,\r
+          SIZE_T UserDataLength, OVERLAPPED* pOverlapped)\r
 {\r
        UNREFERENCED_PARAMETER(pAddress);\r
-       UNREFERENCED_PARAMETER(pPrivateData);\r
-       UNREFERENCED_PARAMETER(PrivateDataLength);\r
+       UNREFERENCED_PARAMETER(pUserData);\r
+       UNREFERENCED_PARAMETER(UserDataLength);\r
        UNREFERENCED_PARAMETER(pOverlapped);\r
 \r
        return E_NOTIMPL;\r
@@ -244,7 +536,7 @@ Accept(WV_DATAGRAM_PARAM* pParam, OVERLAPPED* pOverlapped)
 }\r
 \r
 STDMETHODIMP CWVDatagramEndpoint::\r
-JoinMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)\r
+JoinMulticast(const SOCKADDR* pAddress, OVERLAPPED* pOverlapped)\r
 {\r
        UNREFERENCED_PARAMETER(pAddress);\r
        UNREFERENCED_PARAMETER(pOverlapped);\r
@@ -253,7 +545,7 @@ JoinMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)
 }\r
 \r
 STDMETHODIMP CWVDatagramEndpoint::\r
-LeaveMulticast(const struct sockaddr* pAddress, OVERLAPPED* pOverlapped)\r
+LeaveMulticast(const SOCKADDR* pAddress, OVERLAPPED* pOverlapped)\r
 {\r
        UNREFERENCED_PARAMETER(pAddress);\r
        UNREFERENCED_PARAMETER(pOverlapped);\r
index ab2fd14e10680eaaf533ba7e23c793e6fce43339..1d3ee5f93401dc0e8562241bd84b41832471fee0 100644 (file)
@@ -50,15 +50,18 @@ public:
                                                                         DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
 \r
        // IWVEndpoint methods\r
-       STDMETHODIMP BindAddress(const struct sockaddr* pAddress);\r
-       STDMETHODIMP Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength);\r
+       STDMETHODIMP Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength);\r
+       STDMETHODIMP BindAddress(SOCKADDR* pAddress);\r
+       STDMETHODIMP Listen(SIZE_T Backlog);\r
+       STDMETHODIMP Reject(const VOID* pUserData, SIZE_T UserDataLength);\r
 \r
        // IWVConnectEndpoint methods\r
-       STDMETHODIMP Connect(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,\r
-                                                OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP GetRequest(IWVConnectEndpoint* pEndpoint, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Connect(IWVConnectQueuePair* pQp, const SOCKADDR* pAddress,\r
+                                                WV_CONNECT_PARAM* pParam, OVERLAPPED* pOverlapped);\r
        STDMETHODIMP Accept(IWVConnectQueuePair* pQp, WV_CONNECT_PARAM* pParam,\r
                                                OVERLAPPED* pOverlapped);\r
-       STDMETHODIMP Disconnect(OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Disconnect();\r
        STDMETHODIMP NotifyDisconnect(OVERLAPPED* pOverlapped);\r
        STDMETHODIMP Query(WV_CONNECT_ATTRIBUTES* pAttributes);\r
 \r
@@ -82,6 +85,11 @@ public:
                        goto err2;\r
                }\r
 \r
+               hr = ep->Allocate();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
                *ppConnectEndpoint = ep;\r
                return WV_SUCCESS;\r
 \r
@@ -93,6 +101,11 @@ public:
        }\r
 \r
        CWVProvider             *m_pProvider;\r
+\r
+protected:\r
+       SOCKET                  m_Socket;\r
+\r
+       STDMETHODIMP Allocate();\r
 };\r
 \r
 class CWVDatagramEndpoint : IWVDatagramEndpoint, public CWVBase\r
@@ -109,16 +122,19 @@ public:
                                                                         DWORD *pNumberOfBytesTransferred, BOOL bWait);\r
 \r
        // IWVEndpoint methods\r
-       STDMETHODIMP BindAddress(const struct sockaddr* pAddress);\r
-       STDMETHODIMP Reject(const VOID* pPrivateData, SIZE_T PrivateDataLength);\r
+       STDMETHODIMP Modify(DWORD Option, const VOID* pOptionData, SIZE_T OptionLength);\r
+       STDMETHODIMP BindAddress(SOCKADDR* pAddress);\r
+       STDMETHODIMP Listen(SIZE_T Backlog);\r
+       STDMETHODIMP Reject(const VOID* pUserData, SIZE_T UserDataLength);\r
 \r
        // IWVDatagramEndpoint methods\r
-       STDMETHODIMP Lookup(const struct sockaddr* pAddress, const VOID* pPrivateData,\r
-                                               SIZE_T PrivateDataLength, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP GetRequest(IWVDatagramEndpoint* pEndpoint, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Lookup(const SOCKADDR* pAddress, const VOID* pUserData,\r
+                                               SIZE_T UserDataLength, OVERLAPPED* pOverlapped);\r
        STDMETHODIMP Accept(WV_DATAGRAM_PARAM* pParam, OVERLAPPED* pOverlapped);\r
-       STDMETHODIMP JoinMulticast(const struct sockaddr* pAddress,\r
+       STDMETHODIMP JoinMulticast(const SOCKADDR* pAddress,\r
                                                           OVERLAPPED* pOverlapped);\r
-       STDMETHODIMP LeaveMulticast(const struct sockaddr* pAddress,\r
+       STDMETHODIMP LeaveMulticast(const SOCKADDR* pAddress,\r
                                                                OVERLAPPED* pOverlapped);\r
        STDMETHODIMP Query(WV_DATAGRAM_ATTRIBUTES* pAttributes);\r
 \r
@@ -142,6 +158,11 @@ public:
                        goto err2;\r
                }\r
 \r
+               hr = ep->Allocate();\r
+               if (FAILED(hr)) {\r
+                       goto err2;\r
+               }\r
+\r
                *ppDatagramEndpoint = ep;\r
                return WV_SUCCESS;\r
 \r
@@ -153,6 +174,9 @@ public:
        }\r
 \r
        CWVProvider             *m_pProvider;\r
+\r
+protected:\r
+       STDMETHODIMP Allocate();\r
 };\r
 \r
 #endif // _WV_EP_H_\r
index 6ec7de464e30e8333b5942626e7c3e0caf0648ae..63bbada207c5bb8a2c36bef3c5872f42d7df0e86 100644 (file)
 #include "wv_memory.h"\r
 #include "wv_listen.h"\r
 #include "wv_ioctl.h"\r
+#include "wv_ep.h"\r
 \r
 CWVListen::CWVListen(CWVProvider *pProvider)\r
 {\r
        pProvider->AddRef();\r
        m_pProvider = pProvider;\r
        m_hFile = pProvider->m_hFile;\r
+       m_Socket = INVALID_SOCKET;\r
 }\r
 \r
 CWVListen::~CWVListen()\r
 {\r
+       DWORD   bytes;\r
+\r
+       if (m_Id != 0) {\r
+               WvDeviceIoControl(m_hFile, WV_IOCTL_EP_DESTROY, &m_Id, sizeof m_Id,\r
+                                                 NULL, 0, &bytes, NULL);\r
+       }\r
+\r
+       if (m_Socket != INVALID_SOCKET) {\r
+               closesocket(m_Socket);\r
+       }\r
        m_pProvider->Release();\r
 }\r
 \r
@@ -73,7 +85,7 @@ CancelOverlappedRequests(void)
 {\r
        DWORD   bytes;\r
 \r
-       return WvDeviceIoControl(m_hFile, WV_IOCTL_LISTEN_CANCEL, &m_Id, sizeof m_Id,\r
+       return WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CANCEL, &m_Id, sizeof m_Id,\r
                                                         NULL, 0, &bytes, NULL) ?\r
                                                         WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
 }\r
@@ -87,19 +99,139 @@ GetOverlappedResult(OVERLAPPED *pOverlapped,
 }\r
 \r
 STDMETHODIMP CWVListen::\r
-Listen(const struct sockaddr* pAddress, SIZE_T Backlog)\r
+Allocate(UINT64 EpType)\r
+{\r
+       DWORD   bytes;\r
+       HRESULT hr;\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_CREATE, &EpType, sizeof EpType,\r
+                                                 &m_Id, sizeof m_Id, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+Bind(SOCKADDR* pAddress, WV_EP_TYPE EpType)\r
+{\r
+       WV_IO_EP_BIND           attr;\r
+       BOOLEAN                         any;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+\r
+       if (pAddress->sa_family == AF_INET) {\r
+               any = (((SOCKADDR_IN *) pAddress)->sin_addr.S_un.S_addr == INADDR_ANY);\r
+               bytes = sizeof(SOCKADDR_IN);\r
+       } else {\r
+               any = IN6ADDR_ISANY((SOCKADDR_IN6 *) pAddress);\r
+               bytes = sizeof(SOCKADDR_IN6);\r
+       }\r
+\r
+       if (any == FALSE) {\r
+               hr = m_pProvider->TranslateAddress(pAddress,\r
+                                                                                  (WV_DEVICE_ADDRESS *) &attr.Device);\r
+               if (FAILED(hr)) {\r
+                       return hr;\r
+               }\r
+       }\r
+\r
+       m_Socket = (EpType == WvEpTypeConnect) ?\r
+                          socket(pAddress->sa_family, SOCK_STREAM, IPPROTO_TCP) :\r
+                          socket(pAddress->sa_family, SOCK_DGRAM, IPPROTO_UDP);\r
+       if (m_Socket == INVALID_SOCKET) {\r
+               return WSAGetLastError();\r
+       }\r
+\r
+       hr = bind(m_Socket, pAddress, bytes);\r
+       if (FAILED(hr)) {\r
+               goto err;\r
+       }\r
+\r
+       attr.Id = m_Id;\r
+       RtlCopyMemory(&attr.Address, pAddress, bytes);\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_BIND, &attr, sizeof attr,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+               goto err;\r
+       }\r
+\r
+       return WV_SUCCESS;\r
+\r
+err:\r
+       closesocket(m_Socket);\r
+       m_Socket = INVALID_SOCKET;\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+Listen(SOCKADDR* pAddress, WV_EP_TYPE EpType, SIZE_T Backlog)\r
 {\r
-       UNREFERENCED_PARAMETER(pAddress);\r
-       UNREFERENCED_PARAMETER(Backlog);\r
+       WV_IO_EP_LISTEN         attr;\r
+       BOOLEAN                         any;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+\r
+       hr = Allocate((UINT64) EpType);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       hr = Bind(pAddress, EpType);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       attr.Id = m_Id;\r
+       attr.Backlog = Backlog;\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_LISTEN, &attr, sizeof attr,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVListen::\r
 GetRequest(IWVEndpoint* pEndpoint, OVERLAPPED* pOverlapped)\r
 {\r
-       UNREFERENCED_PARAMETER(pEndpoint);\r
-       UNREFERENCED_PARAMETER(pOverlapped);\r
+       WV_IO_EP_GET_REQUEST    req;\r
+       DWORD                                   bytes;\r
+       HRESULT                                 hr;\r
 \r
-       return E_NOTIMPL;\r
+       req.Id = m_Id;\r
+       req.EpId = ((CWVBase *) pEndpoint)->m_Id;\r
+\r
+       if (WvDeviceIoControl(m_hFile, WV_IOCTL_EP_GET_REQUEST,\r
+                                                 &req, sizeof req, NULL, 0, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+STDMETHODIMP CWVListen::\r
+Query(WV_LISTEN_ATTRIBUTES* pAttributes)\r
+{\r
+       WV_IO_EP_ATTRIBUTES     attr;\r
+       DWORD                           bytes;\r
+       HRESULT                         hr;\r
+\r
+       if (!WvDeviceIoControl(m_hFile, WV_IOCTL_EP_QUERY, &m_Id, sizeof m_Id,\r
+                                                  &attr, sizeof attr, &bytes, NULL)) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       RtlCopyMemory(&pAttributes->LocalAddress, &attr.LocalAddress,\r
+                                 sizeof pAttributes->LocalAddress);\r
+       RtlCopyMemory(&pAttributes->Device, &attr.Device, sizeof pAttributes->Device);\r
+       pAttributes->Backlog = attr.Param.Backlog;\r
+\r
+       return WV_SUCCESS;\r
 }\r
index 55bcc55bb292789386a9d172c924d9bc18953465..97ea201d8bae4ff281a14fcc6b03f1d0ae6cc4bd 100644 (file)
@@ -51,15 +51,16 @@ public:
 \r
        // IWVListen methods\r
        STDMETHODIMP GetRequest(IWVEndpoint* pEndpoint, OVERLAPPED* pOverlapped);\r
+       STDMETHODIMP Query(WV_LISTEN_ATTRIBUTES* pAttributes);\r
 \r
-       STDMETHODIMP Listen(const struct sockaddr* pAddress, SIZE_T Backlog);\r
+       STDMETHODIMP Listen(SOCKADDR* pAddress, WV_EP_TYPE EndpointType, SIZE_T Backlog);\r
 \r
        CWVListen(CWVProvider *pProvider);\r
        ~CWVListen();\r
        void Delete() {delete this;}\r
        static STDMETHODIMP\r
-       CreateInstance(CWVProvider *pProvider, const struct sockaddr* pAddress,\r
-                                  SIZE_T Backlog, IWVListen** ppListen)\r
+       CreateInstance(CWVProvider *pProvider, SOCKADDR* pAddress,\r
+                                  WV_EP_TYPE EpType, SIZE_T Backlog, IWVListen** ppListen)\r
        {\r
                HRESULT hr;\r
                CWVListen *listener;\r
@@ -75,7 +76,7 @@ public:
                        goto err2;\r
                }\r
 \r
-               hr = listener->Listen(pAddress, Backlog);\r
+               hr = listener->Listen(pAddress, EpType, Backlog);\r
                if (FAILED(hr)) {\r
                        goto err2;\r
                }\r
@@ -91,6 +92,11 @@ public:
        }\r
 \r
        CWVProvider             *m_pProvider;\r
+\r
+protected:\r
+       SOCKET                  m_Socket;\r
+       STDMETHODIMP    Allocate(UINT64 EpType);\r
+       STDMETHODIMP    Bind(SOCKADDR* pAddress, WV_EP_TYPE EpType);\r
 };\r
 \r
 #endif // _WV_LISTEN_H_
\ No newline at end of file
index 6002bb1d16bbecca40816f3502380ed82c38841f..c7b11a70a05b6eb9861516035a20f82c1d289094 100644 (file)
@@ -97,9 +97,9 @@ CWVProtectionDomain::~CWVProtectionDomain()
        DWORD   bytes;\r
        HRESULT hr;\r
 \r
-       if (m_Id != NULL) {\r
+       if (m_Id != 0) {\r
                m_pVerbs->pre_deallocate_pd(m_hVerbsPd);\r
-               hr = WvDeviceIoControl(m_hFile, WV_IOCTL_PD_ALLOCATE, &m_Id, sizeof m_Id,\r
+               hr = WvDeviceIoControl(m_hFile, WV_IOCTL_PD_DEALLOCATE, &m_Id, sizeof m_Id,\r
                                                           NULL, 0, &bytes, NULL) ?\r
                                                           WV_SUCCESS : HRESULT_FROM_WIN32(GetLastError());\r
                m_pVerbs->post_deallocate_pd(m_hVerbsPd, (ib_api_status_t) hr);\r
@@ -271,7 +271,7 @@ CWVMemoryWindow::~CWVMemoryWindow()
        DWORD   bytes;\r
        HRESULT hr;\r
 \r
-       if (m_Id != NULL) {\r
+       if (m_Id != 0) {\r
                m_pVerbs->pre_destroy_mw(m_hVerbsMw);\r
                hr = WvDeviceIoControl(m_hFile, WV_IOCTL_MW_DEALLOCATE,\r
                                                           &m_Id, sizeof m_Id, NULL, 0, &bytes, NULL) ?\r
@@ -384,7 +384,7 @@ CWVAddressHandle::~CWVAddressHandle()
        HRESULT                 hr;\r
        ib_api_status_t stat;\r
 \r
-       if (m_Id != NULL) {\r
+       if (m_Id != 0) {\r
                stat = m_pVerbs->pre_destroy_av(m_hVerbsAh);\r
                if (stat != IB_VERBS_PROCESSING_DONE) {\r
                        hr = WvDeviceIoControl(m_hFile, WV_IOCTL_AH_DESTROY,\r
@@ -424,16 +424,17 @@ Release(void)
 STDMETHODIMP CWVAddressHandle::\r
 ConvertAv(ib_av_attr_t *pVerbsAv, WV_ADDRESS_VECTOR *pAv)\r
 {\r
+       DWORD index;\r
        HRESULT hr;\r
 \r
        pVerbsAv->grh_valid = pAv->Route.Valid;\r
        if (pVerbsAv->grh_valid) {\r
-               hr = m_pPd->m_pDevice->FindGidIndex(pAv->PortNumber, &pAv->Route.SGid,\r
-                                                                                       &pVerbsAv->grh.resv1);\r
+               hr = m_pPd->m_pDevice->FindGid(pAv->PortNumber, &pAv->Route.SGid, &index);\r
                if (FAILED(hr)) {\r
                        return hr;\r
                }\r
 \r
+               pVerbsAv->grh.resv1 = (UINT16) index;\r
                pVerbsAv->grh.ver_class_flow =\r
                        _byteswap_ulong(_byteswap_ulong(pAv->Route.FlowLabel) |\r
                                                         (pAv->Route.TrafficClass << 20));\r
index 1b12e819f4bd1c3c8b6307e6fcc34926032d8862..c5c5cd4f075b56d6f5a368772428fda4a144cb77 100644 (file)
  */\r
 \r
 #include <iba\ib_al.h>\r
+#include <iba\ib_at_ioctl.h>\r
 \r
 #include "wv_memory.h"\r
 #include "wv_provider.h"\r
 #include "wv_device.h"\r
 #include "wv_ep.h"\r
-#include "wv_listen.h"\r
 #include "wv_ioctl.h"\r
 \r
 CWVProvider::CWVProvider()\r
@@ -45,7 +45,9 @@ CWVProvider::CWVProvider()
 CWVProvider::~CWVProvider()\r
 {\r
        CloseHandle(m_hFile);\r
-       InterlockedDecrement(&WvRef);\r
+       if (InterlockedDecrement(&WvRef) == 0) {\r
+               WSACleanup();\r
+       }\r
 }\r
 \r
 STDMETHODIMP CWVProvider::\r
@@ -132,12 +134,44 @@ out:
 }\r
 \r
 STDMETHODIMP CWVProvider::\r
-QueryAddressList(WV_ADDRESS_LIST* pAddressList, SIZE_T* pBufferSize)\r
+TranslateAddress(SOCKADDR* pAddress, WV_DEVICE_ADDRESS* pDeviceAddress)\r
 {\r
-       UNREFERENCED_PARAMETER(pAddressList);\r
-       UNREFERENCED_PARAMETER(pBufferSize);\r
+       HANDLE hIbat;\r
+       IOCTL_IBAT_IP_TO_PORT_IN addr;\r
+       IBAT_PORT_RECORD port;\r
+       DWORD bytes;\r
+       HRESULT hr;\r
+\r
+       hIbat = CreateFileW(IBAT_WIN32_NAME, GENERIC_READ | GENERIC_WRITE,\r
+                                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,\r
+                                               OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);\r
+       if (hIbat == INVALID_HANDLE_VALUE) {\r
+               return HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
+\r
+       addr.Version = IBAT_IOCTL_VERSION;\r
+       if (pAddress->sa_family == AF_INET) {\r
+               addr.Address.IpVersion = 4;\r
+               RtlCopyMemory(addr.Address.Address + 12,\r
+                                         &((SOCKADDR_IN *)pAddress)->sin_addr, 4);\r
+       } else {\r
+               addr.Address.IpVersion = 6;\r
+               RtlCopyMemory(addr.Address.Address,\r
+                                         &((SOCKADDR_IN6 *)pAddress)->sin6_addr, 16);\r
+       }\r
+\r
+       if (DeviceIoControl(hIbat, IOCTL_IBAT_IP_TO_PORT,\r
+                                               &addr, sizeof addr, &port, sizeof port, &bytes, NULL)) {\r
+               hr = WV_SUCCESS;\r
+               pDeviceAddress->DeviceGuid = port.CaGuid;\r
+               pDeviceAddress->Pkey = port.PKey;\r
+               pDeviceAddress->PortNumber = port.PortNum;\r
+       } else {\r
+               hr = HRESULT_FROM_WIN32(GetLastError());\r
+       }\r
 \r
-       return E_NOTIMPL;\r
+       CloseHandle(hIbat);\r
+       return hr;\r
 }\r
 \r
 STDMETHODIMP CWVProvider::\r
@@ -157,9 +191,3 @@ CreateDatagramEndpoint(IWVDatagramEndpoint** ppDatagramEndpoint)
 {\r
        return CWVDatagramEndpoint::CreateInstance(this, ppDatagramEndpoint);\r
 }\r
-\r
-STDMETHODIMP CWVProvider::\r
-CreateListen(const struct sockaddr* pAddress, SIZE_T Backlog, IWVListen** ppListen)\r
-{\r
-       return CWVListen::CreateInstance(this, pAddress, Backlog, ppListen);\r
-}\r
index c7635f3b349d1e0d3bf11d7014201594bc07f226..581f83cd1665768c90c4e7080c1ce5384e5f73d4 100644 (file)
@@ -49,23 +49,30 @@ public:
        STDMETHODIMP_(HANDLE) GetFileHandle();\r
        STDMETHODIMP QueryDeviceList(NET64* pGuidList, SIZE_T* pBufferSize);\r
        STDMETHODIMP QueryDevice(NET64 Guid, WV_DEVICE_ATTRIBUTES* pAttributes);\r
-       STDMETHODIMP QueryAddressList(WV_ADDRESS_LIST* pAddressList, SIZE_T* pBufferSize);\r
+       STDMETHODIMP TranslateAddress(SOCKADDR* pAddress,\r
+                                                                 WV_DEVICE_ADDRESS* pDeviceAddress);\r
 \r
        STDMETHODIMP OpenDevice(NET64 Guid, IWVDevice** ppDevice);\r
 \r
        STDMETHODIMP CreateConnectEndpoint(IWVConnectEndpoint** ppConnectEndpoint);\r
        STDMETHODIMP CreateDatagramEndpoint(IWVDatagramEndpoint** ppDatagramEndpoint);\r
-       STDMETHODIMP CreateListen(const struct sockaddr* pAddress,\r
-                                                         SIZE_T backlog, IWVListen** ppListen);\r
 \r
        CWVProvider();\r
        ~CWVProvider();\r
        void Delete() {delete this;}\r
        static STDMETHODIMP CreateInstance(IWVProvider** ppProvider)\r
        {\r
+               WSADATA wsadata;\r
                HRESULT hr;\r
                CWVProvider *wv;\r
 \r
+               if (WvRef == 0) {\r
+                       hr = WSAStartup(MAKEWORD(2, 2), &wsadata);\r
+                       if (FAILED(hr)) {\r
+                               return hr;\r
+                       }\r
+               }\r
+\r
                wv = new CWVProvider;\r
                if (wv == NULL) {\r
                        hr = WV_NO_MEMORY;\r
index ac4a75ae32dc32b5aaaae61144320c425ce944ce..5946ac825eb09d64ce4d4d3984d3ebaa37719853 100644 (file)
@@ -194,6 +194,7 @@ static void WvIoConvertQpAttr(WV_IO_QP_ATTRIBUTES *pIoAttr,
 \r
        pIoAttr->AccessFlags = (UINT8) pAttr->AccessFlags;\r
        pIoAttr->QpFlags = (UINT8) pAttr->QpFlags;\r
+       RtlZeroMemory(pIoAttr->Reserved, sizeof pIoAttr->Reserved);\r
 }\r
 \r
 CWVQueuePair::CWVQueuePair(CWVProtectionDomain *pPd)\r
@@ -298,7 +299,7 @@ CWVQueuePair::~CWVQueuePair()
        DWORD   bytes;\r
        HRESULT hr;\r
 \r
-       if (m_Id != NULL) {\r
+       if (m_Id != 0) {\r
                m_pVerbs->pre_destroy_qp(m_hVerbsQp);\r
                hr = WvDeviceIoControl(m_hFile, WV_IOCTL_QP_DESTROY, &m_Id, sizeof m_Id,\r
                                                           NULL, 0, &bytes, NULL) ?\r
index 0c9650f3d96a49be9f19995fa66754a0538b67f8..32d5ebe046d336a04e595ea15178db09d9d5a620 100644 (file)
@@ -73,6 +73,7 @@ Create(SIZE_T MaxWr, SIZE_T MaxSge, SIZE_T SrqLimit)
        pattr->MaxSge = attr.max_sge;\r
        pattr->MaxWr = attr.max_wr;\r
        pattr->SrqLimit = attr.srq_limit;\r
+       pattr->Reserved = 0;\r
        RtlCopyMemory(pattr + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
                                  verbsData.input_size);\r
 \r
@@ -102,7 +103,7 @@ CWVSharedReceiveQueue::~CWVSharedReceiveQueue()
        DWORD   bytes;\r
        HRESULT hr;\r
 \r
-       if (m_Id != NULL) {\r
+       if (m_Id != 0) {\r
                m_pVerbs->pre_destroy_srq(m_hVerbsSrq);\r
                hr = WvDeviceIoControl(m_hFile, WV_IOCTL_SRQ_DESTROY, &m_Id, sizeof m_Id,\r
                                                           NULL, 0, &bytes, NULL) ?\r
@@ -180,6 +181,7 @@ Query(SIZE_T* pMaxWr, SIZE_T* pMaxSge, SIZE_T* pSrqLimit)
 \r
        pattr->Id.Id = m_Id;\r
        pattr->Id.VerbInfo = verbsData.command;\r
+       pattr->Reserved = 0;\r
        RtlCopyMemory(pattr + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
                                  verbsData.input_size);\r
 \r
@@ -241,6 +243,7 @@ Modify(SIZE_T MaxWr, SIZE_T SrqLimit)
        pattr->Id.VerbInfo = verbsData.command;\r
        pattr->MaxWr = attr.max_wr;\r
        pattr->SrqLimit = attr.srq_limit;\r
+       pattr->Reserved = 0;\r
        RtlCopyMemory(pattr + 1, (void *) (ULONG_PTR) verbsData.p_inout_buf,\r
                                  verbsData.input_size);\r
 \r
index 5086e79b161e16e953a0b60c38de682d1320485e..088cadeb482d6a02891b2fed9863cbacb9dfcd8f 100644 (file)
@@ -81,9 +81,9 @@ enum {
        WV_IO_FUNCTION_QP_ATTACH,\r
        WV_IO_FUNCTION_QP_DETACH,\r
        WV_IO_FUNCTION_QP_CANCEL,\r
-       WV_IO_FUNCTION_ADDRESS_QUERY,\r
        WV_IO_FUNCTION_EP_CREATE,\r
        WV_IO_FUNCTION_EP_DESTROY,\r
+       WV_IO_FUNCTION_EP_MODIFY,\r
        WV_IO_FUNCTION_EP_BIND,\r
        WV_IO_FUNCTION_EP_REJECT,\r
        WV_IO_FUNCTION_EP_CONNECT,\r
@@ -95,10 +95,8 @@ enum {
        WV_IO_FUNCTION_EP_MULTICAST_JOIN,\r
        WV_IO_FUNCTION_EP_MULTICAST_LEAVE,\r
        WV_IO_FUNCTION_EP_CANCEL,\r
-       WV_IO_FUNCTION_LISTEN,\r
-       WV_IO_FUNCTION_LISTEN_DESTROY,\r
-       WV_IO_FUNCTION_LISTEN_GET_REQUEST,\r
-       WV_IO_FUNCTION_LISTEN_CANCEL,\r
+       WV_IO_FUNCTION_EP_LISTEN,\r
+       WV_IO_FUNCTION_EP_GET_REQUEST,\r
        WV_IO_FUNCTION_MAX\r
 };\r
 \r
@@ -230,7 +228,7 @@ enum {
 #define WV_IOCTL_QP_QUERY                              WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_QP_QUERY)\r
 \r
-// WV_IO_QP_ATTRIBUTES / none\r
+// WV_IO_QP_ATTRIBUTES / verbs specific\r
 #define WV_IOCTL_QP_MODIFY                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_QP_MODIFY)\r
 \r
@@ -246,43 +244,69 @@ enum {
 #define WV_IOCTL_QP_CANCEL                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_QP_CANCEL)\r
 \r
-// TODO\r
-#define WV_IOCTL_ADDRESS_QUERY                 WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
-                                                                                                WV_IO_FUNCTION_ADDRESS_QUERY)\r
+// UINT64 EpType / UINT64 Id\r
 #define WV_IOCTL_EP_CREATE                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_CREATE)\r
+\r
+// UINT64 Id / none\r
 #define WV_IOCTL_EP_DESTROY                            WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_DESTROY)\r
+\r
+// WV_IO_ID + UINT8[] / none\r
+#define WV_IOCTL_EP_MODIFY                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
+                                                                                                WV_IO_FUNCTION_EP_MODIFY)\r
+\r
+// WV_IO_EP_BIND / WV_IO_EP_BIND\r
 #define WV_IOCTL_EP_BIND                               WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_BIND)\r
+\r
+// WV_IO_ID + UINT8[] / none\r
 #define WV_IOCTL_EP_REJECT                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_REJECT)\r
+\r
+// WV_IO_EP_CONNECT / none\r
 #define WV_IOCTL_EP_CONNECT                            WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_CONNECT)\r
+\r
+// WV_IO_EP_ACCEPT / verbs specific\r
 #define WV_IOCTL_EP_ACCEPT                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_ACCEPT)\r
+\r
+// UINT64 Id / none\r
 #define WV_IOCTL_EP_DISCONNECT                 WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_DISCONNECT)\r
+\r
+// UINT64 Id / none\r
 #define WV_IOCTL_EP_DISCONNECT_NOTIFY  WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_DISCONNECT_NOTIFY)\r
+\r
+// UINT64 Id / WV_IO_EP_ATTRIBUTES\r
 #define WV_IOCTL_EP_QUERY                              WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_QUERY)\r
+\r
+// TODO\r
 #define WV_IOCTL_EP_LOOKUP                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_LOOKUP)\r
+\r
+// TODO\r
 #define WV_IOCTL_EP_MULTICAST_JOIN             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_MULTICAST_JOIN)\r
+\r
+// TODO\r
 #define WV_IOCTL_EP_MULTICAST_LEAVE            WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_MULTICAST_LEAVE)\r
+\r
+// UINT64 Id / none\r
 #define WV_IOCTL_EP_CANCEL                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
                                                                                                 WV_IO_FUNCTION_EP_CANCEL)\r
-#define WV_IOCTL_LISTEN                                        WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
-                                                                                                WV_IO_FUNCTION_LISTEN)\r
-#define WV_IOCTL_LISTEN_DESTROY                        WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
-                                                                                                WV_IO_FUNCTION_LISTEN_DESTROY)\r
-#define WV_IOCTL_LISTEN_GET_REQUEST            WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
-                                                                                                WV_IO_FUNCTION_LISTEN_GET_REQUEST)\r
-#define WV_IOCTL_LISTEN_CANCEL                 WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
-                                                                                                WV_IO_FUNCTION_LISTEN_CANCEL)\r
+\r
+// WV_IO_EP_LISTEN / none\r
+#define WV_IOCTL_EP_LISTEN                             WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
+                                                                                                WV_IO_FUNCTION_EP_LISTEN)\r
+\r
+// WV_IO_EP_GET_REQUEST / none\r
+#define WV_IOCTL_EP_GET_REQUEST                        WV_IOCTL(WV_IO_FUNCTION_BASE + \\r
+                                                                                                WV_IO_FUNCTION_EP_GET_REQUEST)\r
 \r
 #define WV_IOCTL_MIN                                   WV_IO_FUNCTION_BASE + WV_IO_FUNCTION_MIN\r
 #define WV_IOCTL_MAX                                   WV_IO_FUNCTION_BASE + WV_IO_FUNCTION_MAX\r
@@ -592,20 +616,125 @@ typedef struct _WV_IO_QP_MULTICAST
 \r
 }      WV_IO_QP_MULTICAST;\r
 \r
-// TODO:\r
-//WV_IO_ADDRESS_QUERY\r
-//WV_IO_EP_CREATE\r
-//WV_IO_EP_BIND\r
-//WV_IO_EP_REJECT\r
-//WV_IO_EP_CONNECT\r
-//WV_IO_EP_ACCEPT\r
-//WV_IO_EP_DISCONNECT\r
-//WV_IO_EP_DISCONNECT_NOTIFY\r
-//WV_IO_EP_QUERY\r
-//WV_IO_EP_LOOKUP\r
-//WV_IO_EP_MULTICAST_JOIN\r
-//WV_IO_EP_MULTICAST_LEAVE\r
-//WV_IO_LISTEN\r
-//WV_IO_LISTEN_GET_REQUEST\r
+// Windows kernel does not define sockaddr* pre-Vista\r
+typedef struct _WV_IO_SOCKADDR\r
+{\r
+       UINT16                  SaFamily;\r
+       UINT8                   SaData[14];\r
+\r
+}      WV_IO_SOCKADDR;\r
+\r
+typedef struct _WV_IO_SOCKADDR_IN\r
+{\r
+       UINT16                  SinFamily;\r
+       UINT16                  SinPort;\r
+       UINT32                  SinAddr;\r
+       UINT8                   SinZero[8];\r
+\r
+}      WV_IO_SOCKADDR_IN;\r
+\r
+typedef struct _WV_IO_SOCKADDR_IN6\r
+{\r
+       UINT16                  Sin6Family;\r
+       UINT16                  Sin6Port;\r
+       UINT32                  Sin6FlowInfo;\r
+       UINT8                   Sin6Addr[16];\r
+       UINT32                  Sin6ScopeId;\r
+\r
+}      WV_IO_SOCKADDR_IN6;\r
+\r
+typedef struct _WV_IO_SOCKADDR_DATA\r
+{\r
+       union\r
+       {\r
+               WV_IO_SOCKADDR          Sa;\r
+               WV_IO_SOCKADDR_IN       In;\r
+               WV_IO_SOCKADDR_IN6      In6;\r
+\r
+       }       SockAddr;\r
+\r
+       UINT32                                  Reserved;\r
+\r
+}      WV_IO_SOCKADDR_DATA;\r
+\r
+typedef struct _WV_IO_DEVICE_ADDRESS\r
+{\r
+       NET64                   DeviceGuid;\r
+       NET16                   Pkey;\r
+       UINT8                   PortNumber;\r
+       UINT8                   Reserved[5];\r
+\r
+}      WV_IO_DEVICE_ADDRESS;\r
+\r
+typedef struct _WV_IO_EP_BIND\r
+{\r
+       UINT64                                  Id;\r
+       WV_IO_SOCKADDR_DATA             Address;\r
+       WV_IO_DEVICE_ADDRESS    Device;\r
+\r
+}      WV_IO_EP_BIND;\r
+\r
+#define WV_IO_EP_OPTION_ROUTE          0x00000001\r
+\r
+#define WV_IO_EP_TYPE_CONNECT          0x0106\r
+#define WV_IO_EP_TYPE_DATAGRAM         0x0111\r
+\r
+typedef struct _WV_IO_EP_LISTEN\r
+{\r
+       UINT64                  Id;\r
+       UINT64                  Backlog;\r
+\r
+}      WV_IO_EP_LISTEN;\r
+\r
+typedef struct _WV_IO_EP_GET_REQUEST\r
+{\r
+       UINT64                  Id;\r
+       UINT64                  EpId;\r
+\r
+}      WV_IO_EP_GET_REQUEST;\r
+\r
+typedef struct _WV_IO_CONNECT_PARAM\r
+{\r
+       UINT64                  ResponderResources;\r
+       UINT64                  InitiatorDepth;\r
+       UINT8                   RetryCount;\r
+       UINT8                   RnrRetryCount;\r
+       UINT8                   DataLength;\r
+       UINT8                   Reserved[5];\r
+       UINT8                   Data[56];\r
+\r
+}      WV_IO_CONNECT_PARAM;\r
+\r
+typedef struct _WV_IO_EP_CONNECT\r
+{\r
+       UINT64                                  Id;\r
+       UINT64                                  QpId;\r
+       WV_IO_SOCKADDR_DATA             PeerAddress;\r
+       WV_IO_CONNECT_PARAM             Param;\r
+\r
+}      WV_IO_EP_CONNECT;\r
+\r
+typedef struct _WV_IO_EP_ACCEPT\r
+{\r
+       UINT64                                  Id;\r
+       UINT64                                  QpId;\r
+       WV_IO_CONNECT_PARAM             Param;\r
+\r
+}      WV_IO_EP_ACCEPT;\r
+\r
+typedef struct _WV_IO_EP_ATTRIBUTES\r
+{\r
+       WV_IO_SOCKADDR_DATA             LocalAddress;\r
+       WV_IO_SOCKADDR_DATA             PeerAddress;\r
+       WV_IO_DEVICE_ADDRESS    Device;\r
+\r
+       union {\r
+               WV_IO_CONNECT_PARAM     Connect;\r
+               UINT64                          Backlog;\r
+\r
+       }       Param;\r
+\r
+\r
+}      WV_IO_EP_ATTRIBUTES;\r
 \r
 #endif // _WV_IOCTL_H_\r
index 71d31697a90ab4f4d2cb96cfbeb0259caf8ca519..2e7a16a6047e8df451cd39028be4332c6ebabd11 100644 (file)
@@ -326,6 +326,11 @@ mlnx_ndi_modify_qp (
 \r
        HCA_ENTER(HCA_DBG_QP);\r
 \r
+       if (buf_size < sizeof(resp.qp_state)) {\r
+               status = IB_INVALID_PARAMETER;\r
+               goto out;\r
+       }\r
+\r
        /* imitate umv_buf */\r
        umv_buf.command = TRUE; /* special case for NDI. Usually it's TRUE */\r
        umv_buf.input_size = 0;\r
@@ -339,6 +344,7 @@ mlnx_ndi_modify_qp (
                *p_outbuf = resp.qp_state;\r
        }\r
 \r
+out:\r
        HCA_EXIT(HCA_DBG_QP);\r
        return status;\r
 }\r
index 3bd5acc53f6f6522a8ca637d348f321a522a7c18..ca3acf58f09909edbe7826bae2d741bfe2a9609b 100644 (file)
@@ -1266,6 +1266,11 @@ mlnx_ndi_modify_qp (
 \r
        HCA_ENTER(HCA_DBG_QP);\r
 \r
+       if (buf_size < sizeof(resp.qp_state)) {\r
+               status = IB_INVALID_PARAMETER;\r
+               goto out;\r
+       }\r
+\r
        /* imitate umv_buf */\r
        umv_buf.command = TRUE; /* special case for NDI. Usually it's TRUE */\r
        umv_buf.input_size = 0;\r
@@ -1279,6 +1284,7 @@ mlnx_ndi_modify_qp (
                *p_outbuf = resp.qp_state;\r
        }\r
 \r
+out:\r
        HCA_EXIT(HCA_DBG_QP);\r
        return status;\r
 }\r
diff --git a/branches/winverbs/inc/kernel/iba/ib_cm_ifc.h b/branches/winverbs/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
diff --git a/branches/winverbs/inc/kernel/iba/ib_rdma_cm.h b/branches/winverbs/inc/kernel/iba/ib_rdma_cm.h
new file mode 100644 (file)
index 0000000..b6f01f1
--- /dev/null
@@ -0,0 +1,65 @@
+/*\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
+#pragma once\r
+\r
+#ifndef _IB_RDMA_CM_H_\r
+#define _IB_RDMA_CM_H_\r
+\r
+#include <ntddk.h>\r
+\r
+#define IB_CMA_VERSION 0x00\r
+\r
+#define IB_CMA_SERVICE_ID       0x0000000001000000\r
+#define IB_CMA_SERVICE_ID_MASK  0xFFFFFFFFFF000000\r
+#define IB_CMA_CM_RESPONSE_TIMEOUT                             20\r
+#define IB_CMA_MAX_CM_RETRIES                                  15\r
+\r
+typedef union _IB_CMA_IP_ADDRESS\r
+{\r
+       UINT8                           Ip6Address[16];\r
+       struct {\r
+               UINT32                  Pad[3];\r
+               UINT32                  Address;\r
+\r
+       }       Ip4;\r
+\r
+}      IB_CMA_IP_ADDRESS;\r
+\r
+typedef struct _IB_CMA_HEADER\r
+{\r
+       UINT8                           CmaVersion;\r
+       UINT8                           IpVersion;              // IP Version: 7:4\r
+       UINT16                          Port;\r
+       IB_CMA_IP_ADDRESS       SrcAddress;\r
+       IB_CMA_IP_ADDRESS       DstAddress;\r
+\r
+}      IB_CMA_HEADER;\r
+\r
+#endif // _IB_RDMA_CM_H_
\ No newline at end of file
index 19a6fcebf6f80dd5c527075f69eb6ca585edf187..27cb92098f12c63b9bb73215262257205f6f2143 100644 (file)
@@ -35,6 +35,7 @@
 #include <initguid.h>\r
 \r
 #include <winsock2.h>\r
+#include <ws2tcpip.h>\r
 #include <unknwn.h>\r
 #include <rdma\wvstatus.h>\r
 \r
@@ -156,21 +157,13 @@ typedef struct _WV_PORT_ATTRIBUTES
 \r
 }      WV_PORT_ATTRIBUTES;\r
 \r
-typedef struct _WV_ADDRESS\r
+typedef struct _WV_DEVICE_ADDRESS\r
 {\r
-       SOCKET_ADDRESS  Address;\r
-       NET64                   DeviceGuid;\r
-       NET16                   Pkey;\r
-       UINT8                   PortNumber;\r
-\r
-}      WV_ADDRESS;\r
-\r
-typedef struct _WV_ADDRESS_LIST\r
-{\r
-       SIZE_T                  Count;\r
-       WV_ADDRESS              Address[1];\r
+       NET64                           DeviceGuid;\r
+       NET16                           Pkey;\r
+       UINT8                           PortNumber;\r
 \r
-}      WV_ADDRESS_LIST;\r
+}      WV_DEVICE_ADDRESS;\r
 \r
 // Port notification flags\r
 #define WV_EVENT_ERROR                         0x00000001\r
@@ -476,8 +469,6 @@ typedef struct _WV_QP_ATTRIBUTES
 \r
 #define WV_CM_UDP_QKEY 0x01234567\r
 \r
-#pragma warning(push)\r
-#pragma warning(disable: 4200)\r
 typedef struct _WV_CONNECT_PARAM\r
 {\r
        SIZE_T                          DataLength;\r
@@ -486,7 +477,7 @@ typedef struct _WV_CONNECT_PARAM
        UINT8                           RetryCount;                     // Ignored when accepting\r
        UINT8                           RnrRetryCount;\r
        UINT8                           Reserved[2];\r
-       UINT8                           Data[];\r
+       UINT8                           Data[56];\r
 \r
 }      WV_CONNECT_PARAM;\r
 \r
@@ -496,27 +487,39 @@ typedef struct _WV_DATAGRAM_PARAM
        WV_ADDRESS_VECTOR       AddressVector;\r
        NET32                           Qpn;\r
        NET32                           Qkey;\r
-       UINT8                           Data[];\r
+       UINT8                           Data[56];\r
 \r
 }      WV_DATAGRAM_PARAM;\r
-#pragma warning(pop)\r
+\r
+typedef union _WV_SOCKADDR\r
+{\r
+       SOCKADDR                        Sa;\r
+       SOCKADDR_IN                     Sin;\r
+       SOCKADDR_IN6            Sin6;\r
+\r
+}      WV_SOCKADDR;\r
 \r
 typedef struct _WV_CONNECT_ATTRIBUTES\r
 {\r
-       WV_ADDRESS                      LocalAddress;\r
-       SOCKET_ADDRESS          PeerAddress;\r
+       WV_SOCKADDR                     LocalAddress;\r
+       WV_SOCKADDR                     PeerAddress;\r
+       WV_DEVICE_ADDRESS       Device;\r
        WV_CONNECT_PARAM        Param;\r
 \r
 }      WV_CONNECT_ATTRIBUTES;\r
 \r
 typedef struct _WV_DATAGRAM_ATTRIBUTES\r
 {\r
-       WV_ADDRESS                      LocalAddress;\r
-       SOCKET_ADDRESS          PeerAddress;            // Specify when querying\r
+       WV_SOCKADDR                     LocalAddress;\r
+       WV_SOCKADDR                     PeerAddress;            // Specify when querying\r
+       WV_DEVICE_ADDRESS       Device;\r
        WV_DATAGRAM_PARAM       Param;\r
 \r
 }      WV_DATAGRAM_ATTRIBUTES;\r
 \r
+// Endpoint options\r
+#define WV_EP_OPTION_ROUTE                             0x00000001\r
+\r
 #undef INTERFACE\r
 #define INTERFACE IWVOverlapped\r
 // {64687592-aa67-4b55-bc4b-e189bdd2fc4f}\r
@@ -1126,15 +1129,27 @@ DECLARE_INTERFACE_(IWVEndpoint, IWVOverlapped)
                ) PURE;\r
 \r
        // IWVEndpoint methods\r
+       STDMETHOD(Modify)(\r
+               THIS_\r
+               __in DWORD Option,\r
+               __in_bcount_opt(OptionLength) const VOID* pOptionData,\r
+               __in SIZE_T OptionLength\r
+               ) PURE;\r
+\r
        STDMETHOD(BindAddress)(\r
                THIS_\r
-               __in const struct sockaddr* pAddress\r
+               __in SOCKADDR* pAddress\r
+               ) PURE;\r
+\r
+       STDMETHOD(Listen)(\r
+               THIS_\r
+               __in SIZE_T Backlog\r
                ) PURE;\r
 \r
        STDMETHOD(Reject)(\r
                THIS_\r
-               __in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,\r
-               __in SIZE_T PrivateDataLength\r
+               __in_bcount_opt(UserDataLength) const VOID* pUserData,\r
+               __in SIZE_T UserDataLength\r
                ) PURE;\r
 };\r
 \r
@@ -1175,21 +1190,40 @@ DECLARE_INTERFACE_(IWVConnectEndpoint, IWVEndpoint)
                ) PURE;\r
 \r
        // IWVEndpoint methods\r
+       __override STDMETHOD(Modify)(\r
+               THIS_\r
+               __in DWORD Option,\r
+               __in_bcount_opt(OptionLength) const VOID* pOptionData,\r
+               __in SIZE_T OptionLength\r
+               ) PURE;\r
+\r
        __override STDMETHOD(BindAddress)(\r
                THIS_\r
-               __in const struct sockaddr* pAddress\r
+               __in SOCKADDR* pAddress\r
+               ) PURE;\r
+\r
+       __override STDMETHOD(Listen)(\r
+               THIS_\r
+               __in SIZE_T Backlog\r
                ) PURE;\r
 \r
        __override STDMETHOD(Reject)(\r
                THIS_\r
-               __in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,\r
-               __in SIZE_T PrivateDataLength\r
+               __in_bcount_opt(UserDataLength) const VOID* pUserData,\r
+               __in SIZE_T UserDataLength\r
                ) PURE;\r
 \r
        // IWVConnectEndpoint methods\r
+       STDMETHOD(GetRequest)(\r
+               THIS_\r
+               __in IWVConnectEndpoint* pEndpoint,\r
+               __in_opt OVERLAPPED* pOverlapped\r
+               ) PURE;\r
+\r
        STDMETHOD(Connect)(\r
                THIS_\r
                __in IWVConnectQueuePair* pQp,\r
+               __in const SOCKADDR* pAddress,\r
                __in WV_CONNECT_PARAM* pParam,\r
                __in_opt OVERLAPPED* pOverlapped\r
                ) PURE;\r
@@ -1202,8 +1236,7 @@ DECLARE_INTERFACE_(IWVConnectEndpoint, IWVEndpoint)
                ) PURE;\r
 \r
        STDMETHOD(Disconnect)(\r
-               THIS_\r
-               __in_opt OVERLAPPED* pOverlapped\r
+               THIS\r
                ) PURE;\r
 \r
        STDMETHOD(NotifyDisconnect)(\r
@@ -1254,23 +1287,41 @@ DECLARE_INTERFACE_(IWVDatagramEndpoint, IWVEndpoint)
                ) PURE;\r
 \r
        // IWVEndpoint methods\r
+       __override STDMETHOD(Modify)(\r
+               THIS_\r
+               __in DWORD Option,\r
+               __in_bcount_opt(OptionLength) const VOID* pOptionData,\r
+               __in SIZE_T OptionLength\r
+               ) PURE;\r
+\r
        __override STDMETHOD(BindAddress)(\r
                THIS_\r
-               __in const struct sockaddr* pAddress\r
+               __in SOCKADDR* pAddress\r
+               ) PURE;\r
+\r
+       __override STDMETHOD(Listen)(\r
+               THIS_\r
+               __in SIZE_T Backlog\r
                ) PURE;\r
 \r
        __override STDMETHOD(Reject)(\r
                THIS_\r
-               __in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,\r
-               __in SIZE_T PrivateDataLength\r
+               __in_bcount_opt(UserDataLength) const VOID* pUserData,\r
+               __in SIZE_T UserDataLength\r
                ) PURE;\r
 \r
        // IWVDatagramEndpoint methods\r
+       STDMETHOD(GetRequest)(\r
+               THIS_\r
+               __in IWVDatagramEndpoint* pEndpoint,\r
+               __in_opt OVERLAPPED* pOverlapped\r
+               ) PURE;\r
+\r
        STDMETHOD(Lookup)(\r
                THIS_\r
-               __in const struct sockaddr* pAddress,\r
-               __in_bcount_opt(PrivateDataLength) const VOID* pPrivateData,\r
-               __in SIZE_T PrivateDataLength,\r
+               __in const SOCKADDR* pAddress,\r
+               __in_bcount_opt(UserDataLength) const VOID* pUserData,\r
+               __in SIZE_T UserDataLength,\r
                __in_opt OVERLAPPED* pOverlapped\r
                ) PURE;\r
 \r
@@ -1282,13 +1333,13 @@ DECLARE_INTERFACE_(IWVDatagramEndpoint, IWVEndpoint)
 \r
        STDMETHOD(JoinMulticast)(\r
                THIS_\r
-               __in const struct sockaddr* pAddress,\r
+               __in const SOCKADDR* pAddress,\r
                __in_opt OVERLAPPED* pOverlapped\r
                ) PURE;\r
 \r
        STDMETHOD(LeaveMulticast)(\r
                THIS_\r
-               __in const struct sockaddr* pAddress,\r
+               __in const SOCKADDR* pAddress,\r
                __in_opt OVERLAPPED* pOverlapped\r
                ) PURE;\r
 \r
@@ -1299,50 +1350,6 @@ DECLARE_INTERFACE_(IWVDatagramEndpoint, IWVEndpoint)
 };\r
 \r
 \r
-#undef INTERFACE\r
-#define INTERFACE IWVListen\r
-// {5b839fd4-7410-441f-a2d9-5d75b1d8599b}\r
-DEFINE_GUID(IID_IWVListen, 0x5b839fd4, 0x7410, 0x441f,\r
-                       0xa2, 0xd9, 0x5d, 0x75, 0xb1, 0xd8, 0x59, 0x9b);\r
-\r
-DECLARE_INTERFACE_(IWVListen, IWVOverlapped)\r
-{\r
-       // IUnknown methods\r
-       __override STDMETHOD(QueryInterface)(\r
-               THIS_\r
-               REFIID riid,\r
-               LPVOID FAR* ppvObj\r
-               ) PURE;\r
-\r
-       __override STDMETHOD_(ULONG,AddRef)(\r
-               THIS\r
-               ) PURE;\r
-\r
-       __override STDMETHOD_(ULONG,Release)(\r
-               THIS\r
-               ) PURE;\r
-\r
-       // IWVOverlapped methods\r
-       __override STDMETHOD(CancelOverlappedRequests)(\r
-               THIS\r
-               ) PURE;\r
-\r
-       __override STDMETHOD(GetOverlappedResult)(\r
-               THIS_\r
-               __inout_opt OVERLAPPED *pOverlapped,\r
-               __out DWORD *pNumberOfBytesTransferred,\r
-               __in BOOL bWait\r
-               ) PURE;\r
-\r
-       // IWVListen methods\r
-       STDMETHOD(GetRequest)(\r
-               THIS_\r
-               __in IWVEndpoint* pEndpoint,\r
-               __in_opt OVERLAPPED* pOverlapped\r
-               ) PURE;\r
-};\r
-\r
-\r
 #undef INTERFACE\r
 #define INTERFACE IWVDevice\r
 // {244af78c-b1ac-40e4-9896-271d58d591b8}\r
@@ -1397,6 +1404,13 @@ DECLARE_INTERFACE_(IWVDevice, IWVOverlapped)
                __out WV_GID* pGid\r
                ) PURE;\r
 \r
+       STDMETHOD(FindGid)(\r
+               THIS_\r
+               __in UINT8 PortNumber,\r
+               __in WV_GID* pGid,\r
+               __out DWORD* pIndex\r
+               ) PURE;\r
+\r
        STDMETHOD(QueryPkey)(\r
                THIS_\r
                __in UINT8 PortNumber,\r
@@ -1404,6 +1418,13 @@ DECLARE_INTERFACE_(IWVDevice, IWVOverlapped)
                __out NET16* pPkey\r
                ) PURE;\r
 \r
+       STDMETHOD(FindPkey)(\r
+               THIS_\r
+               __in UINT8 PortNumber,\r
+               __in NET16 Pkey,\r
+               __out DWORD* pIndex\r
+               ) PURE;\r
+\r
        STDMETHOD(CreateCompletionQueue)(\r
                THIS_\r
                __inout SIZE_T *pEntries,\r
@@ -1426,9 +1447,9 @@ DECLARE_INTERFACE_(IWVDevice, IWVOverlapped)
 \r
 #undef INTERFACE\r
 #define INTERFACE IWVProvider\r
-// {6901010c-17af-4894-a1dc-794d3611f262}\r
-DEFINE_GUID(IID_IWVProvider, 0x6901010c, 0x17af, 0x4894,\r
-                       0xa1, 0xdc, 0x79, 0x4d, 0x36, 0x11, 0xf2, 0x62);\r
+// {060E95D6-EC54-43b2-83FC-B578FD037259}\r
+DEFINE_GUID(IID_IWVProvider, 0x60e95d6, 0xec54, 0x43b2,\r
+                       0x83, 0xfc, 0xb5, 0x78, 0xfd, 0x3, 0x72, 0x59);\r
 \r
 DECLARE_INTERFACE_(IWVProvider, IUnknown)\r
 {\r
@@ -1464,10 +1485,10 @@ DECLARE_INTERFACE_(IWVProvider, IUnknown)
                __out WV_DEVICE_ATTRIBUTES* pAttributes\r
                ) PURE;\r
 \r
-       STDMETHOD(QueryAddressList)(\r
+       STDMETHOD(TranslateAddress)(\r
                THIS_\r
-               __inout_bcount_part_opt(*pBufferSize, *pBufferSize) WV_ADDRESS_LIST* pAddressList,\r
-               __inout SIZE_T* pBufferSize\r
+               __in SOCKADDR* pAddress,\r
+               __out WV_DEVICE_ADDRESS* pDeviceAddress\r
                ) PURE;\r
 \r
        STDMETHOD(OpenDevice)(\r
@@ -1485,13 +1506,6 @@ DECLARE_INTERFACE_(IWVProvider, IUnknown)
                THIS_\r
                __deref_out IWVDatagramEndpoint** ppDatagramEndpoint\r
                ) PURE;\r
-\r
-       STDMETHOD(CreateListen)(\r
-               THIS_\r
-               __in const struct sockaddr* pAddress,\r
-               __in SIZE_T Backlog,\r
-               __deref_out IWVListen** ppListen\r
-               ) PURE;\r
 };\r
 \r
 __declspec(dllexport) HRESULT WvGetObject(REFIID riid, LPVOID FAR* ppvObj);\r
index b28d5000232f3f2fe27e05a19f9be481d05732fb..926f782596803a72cd632670ecf23db6d4bd0c6b 100644 (file)
@@ -12,7 +12,6 @@ USE_NATIVE_EH = 1
 SOURCES =                      \\r
        wv_main.cpp             \\r
        wv_device.cpp   \\r
-       wv_listen.cpp   \\r
        wv_connect.cpp  \\r
        wv_datagram.cpp \\r
        wv_pd.cpp               \\r
index f90bb33e967eed6bafcb19dd8d3304cb0260bddd..66e28776de557b2781b56128e2ed9ec1f4989c21 100644 (file)
@@ -112,7 +112,6 @@ static void ShowUsage()
        cout << "<interface> is one of the following:" << endl;\r
        cout << "\t" << "provider" << endl;\r
        cout << "\t" << "device" << endl;\r
-       cout << "\t" << "listen" << endl;\r
        cout << "\t" << "connect" << endl;\r
        cout << "\t" << "datagram" << endl;\r
        cout << "\t" << "pd" << endl;\r
@@ -133,8 +132,6 @@ int __cdecl main(int argc, char *argv[])
                hr = ProviderTest(argc - 1, &argv[1]);\r
        } else if (strcmp("device", argv[1]) == 0) {\r
                hr = DeviceTest(argc - 1, &argv[1]);\r
-       } else if (strcmp("listen", argv[1]) == 0) {\r
-               hr = ListenTest(argc - 1, &argv[1]);\r
        } else if (strcmp("connect", argv[1]) == 0) {\r
                hr = ConnectTest(argc - 1, &argv[1]);\r
        } else if (strcmp("datagram", argv[1]) == 0) {\r
index e2fa5ca0f255d8d8d84c25ecd4cc48d71a51bcba..ed03e60ef96a53ac501b3ef594f81cefe779c61b 100644 (file)
@@ -1,7 +1,8 @@
 DIRS=\\r
-       coinstaller     \\r
-       wsdinstall      \\r
-       vstat           \\r
-       nsc                     \\r
-       perftests       \\r
+       coinstaller                     \\r
+       wsdinstall                      \\r
+       vstat                           \\r
+       nsc                                     \\r
+       perftests                       \\r
+       infiniband_diags        \\r
        part_man\r
index 3410deb669bcff000fe61926e5f6068d84b6c926..690b4c72d0451e0610c89f7306a9a4a21b2fce90 100644 (file)
@@ -6,4 +6,6 @@ DIRS=\
        wsd             \\r
        qlgcvnic        \\r
        libibverbs      \\r
+       libibumad       \\r
+       libibmad        \\r
        nd\r
index 04980b2603681ad5bde2453be87c51fb88657acd..aef0946839fe836ac1bd39e8338164c190d5c52b 100644 (file)
@@ -14,7 +14,7 @@ DLLDEF = $(OBJ_PATH)\$O\ibv_exports.def
 !endif\r
 \r
 DLLENTRY = DllMain\r
-USE_NTDLL = 1\r
+USE_MSVCRT=1\r
 \r
 SOURCES = \\r
        ibverbs.rc              \\r
index 6b29b2950955198d25da0b7b26180f881c08bbbe..af633386eba00e30688591f80a149932e364b33a 100644 (file)
@@ -58,6 +58,22 @@ struct verbs_context
        uint8_t                         event_port_index;\r
 };\r
 \r
+__declspec(dllexport)\r
+IWVProvider *ibv_get_winverbs(void)\r
+{\r
+       HRESULT hr;\r
+\r
+       if (prov == NULL) {\r
+               hr = WvGetObject(IID_IWVProvider, (LPVOID*) &prov);\r
+               if (FAILED(hr)) {\r
+                       return NULL;\r
+               }\r
+       }\r
+\r
+       prov->AddRef();\r
+       return prov;\r
+}\r
+\r
 __declspec(dllexport)\r
 struct ibv_device **ibv_get_device_list(int *num)\r
 {\r
index 9fab212a655f7678004f588ca9fc5fa28f2c6d88..e101d12d905c23dc43390ed21d8320ce672e9d1f 100644 (file)
@@ -391,6 +391,7 @@ static void ibv_comp_channel_remove_cq(struct ibv_comp_channel *channel,
        vchan->count--;\r
        vchan->cq[cq->channel_index] = vchan->cq[vchan->count];\r
        vchan->event[cq->channel_index] = vchan->event[vchan->count];\r
+       vchan->cq[cq->channel_index]->channel_index = cq->channel_index;\r
        LeaveCriticalSection(&vchan->lock);\r
 }\r
 \r
diff --git a/branches/winverbs/ulp/librdmacm/AUTHORS b/branches/winverbs/ulp/librdmacm/AUTHORS
new file mode 100644 (file)
index 0000000..589c93d
--- /dev/null
@@ -0,0 +1 @@
+Sean Hefty             <sean.hefty@intel.com>\r
diff --git a/branches/winverbs/ulp/librdmacm/COPYING b/branches/winverbs/ulp/librdmacm/COPYING
new file mode 100644 (file)
index 0000000..4136760
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2008 Intel Corporation.  All rights reserved.\r
+\r
+This software is available to you under the OpenFabrics.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 AWV\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
diff --git a/branches/winverbs/ulp/librdmacm/dirs b/branches/winverbs/ulp/librdmacm/dirs
new file mode 100644 (file)
index 0000000..b105190
--- /dev/null
@@ -0,0 +1,3 @@
+DIRS =                 \\r
+       src                     \\r
+       examples\r
diff --git a/branches/winverbs/ulp/librdmacm/examples/cmatose/SOURCES b/branches/winverbs/ulp/librdmacm/examples/cmatose/SOURCES
new file mode 100644 (file)
index 0000000..cfe59ff
--- /dev/null
@@ -0,0 +1,30 @@
+TARGETNAME = rdma_cmatose\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = cmatose.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\inc;..\..\..\..\inc\user;..\..\..\libibverbs\include;\r
+\r
+TARGETLIBS =                                           \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib              \\r
+       $(SDK_LIB_PATH)\ole32.lib               \\r
+       $(SDK_LIB_PATH)\ws2_32.lib              \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\libibverbs.lib  \\r
+       $(TARGETPATH)\*\librdmacm.lib\r
+!else\r
+       $(TARGETPATH)\*\libibverbsd.lib \\r
+       $(TARGETPATH)\*\librdmacmd.lib\r
+!endif\r
+\r
diff --git a/branches/winverbs/ulp/librdmacm/examples/cmatose/cmatose.c b/branches/winverbs/ulp/librdmacm/examples/cmatose/cmatose.c
new file mode 100644 (file)
index 0000000..c42341f
--- /dev/null
@@ -0,0 +1,720 @@
+/*\r
+ * Copyright (c) 2005-2009 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 AWV\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 <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ws2tcpip.h>\r
+#include <winsock2.h>\r
+#include <time.h>\r
+\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#include <rdma/rdma_cma.h>\r
+\r
+struct cmatest_node {\r
+       int                     id;\r
+       struct rdma_cm_id       *cma_id;\r
+       int                     connected;\r
+       struct ibv_pd           *pd;\r
+       struct ibv_cq           *cq;\r
+       struct ibv_mr           *mr;\r
+       void                    *mem;\r
+};\r
+\r
+struct cmatest {\r
+       struct rdma_event_channel *channel;\r
+       struct cmatest_node     *nodes;\r
+       int                     conn_index;\r
+       int                     connects_left;\r
+       int                     disconnects_left;\r
+\r
+       struct sockaddr_in      dst_in;\r
+       struct sockaddr         *dst_addr;\r
+       struct sockaddr_in      src_in;\r
+       struct sockaddr         *src_addr;\r
+};\r
+\r
+static struct cmatest test;\r
+static int connections = 1;\r
+static int message_size = 100;\r
+static int message_count = 10;\r
+static uint16_t port = 7471;\r
+static uint8_t set_tos = 0;\r
+static uint8_t tos;\r
+static uint8_t migrate = 0;\r
+static char *dst_addr;\r
+static char *src_addr;\r
+\r
+static int create_message(struct cmatest_node *node)\r
+{\r
+       if (!message_size)\r
+               message_count = 0;\r
+\r
+       if (!message_count)\r
+               return 0;\r
+\r
+       node->mem = malloc(message_size);\r
+       if (!node->mem) {\r
+               printf("failed message allocation\n");\r
+               return -1;\r
+       }\r
+       node->mr = ibv_reg_mr(node->pd, node->mem, message_size,\r
+                            IBV_ACCESS_LOCAL_WRITE);\r
+       if (!node->mr) {\r
+               printf("failed to reg MR\n");\r
+               goto err;\r
+       }\r
+       return 0;\r
+err:\r
+       free(node->mem);\r
+       return -1;\r
+}\r
+\r
+static int init_node(struct cmatest_node *node)\r
+{\r
+       struct ibv_qp_init_attr init_qp_attr;\r
+       int cqe, ret;\r
+\r
+       node->pd = ibv_alloc_pd(node->cma_id->verbs);\r
+       if (!node->pd) {\r
+               ret = -1;\r
+               printf("cmatose: unable to allocate PD\n");\r
+               goto out;\r
+       }\r
+\r
+       cqe = message_count ? message_count * 2 : 2;\r
+       node->cq = ibv_create_cq(node->cma_id->verbs, cqe, node, 0, 0);\r
+       if (!node->cq) {\r
+               ret = -1;\r
+               printf("cmatose: unable to create CQ\n");\r
+               goto out;\r
+       }\r
+\r
+       memset(&init_qp_attr, 0, sizeof init_qp_attr);\r
+       init_qp_attr.cap.max_send_wr = message_count ? message_count : 1;\r
+       init_qp_attr.cap.max_recv_wr = message_count ? message_count : 1;\r
+       init_qp_attr.cap.max_send_sge = 1;\r
+       init_qp_attr.cap.max_recv_sge = 1;\r
+       init_qp_attr.qp_context = node;\r
+       init_qp_attr.sq_sig_all = 1;\r
+       init_qp_attr.qp_type = IBV_QPT_RC;\r
+       init_qp_attr.send_cq = node->cq;\r
+       init_qp_attr.recv_cq = node->cq;\r
+       ret = rdma_create_qp(node->cma_id, node->pd, &init_qp_attr);\r
+       if (ret) {\r
+               printf("cmatose: unable to create QP: 0x%x\n", ret);\r
+               goto out;\r
+       }\r
+\r
+       ret = create_message(node);\r
+       if (ret) {\r
+               printf("cmatose: failed to create messages: 0x%x\n", ret);\r
+               goto out;\r
+       }\r
+out:\r
+       return ret;\r
+}\r
+\r
+static int post_recvs(struct cmatest_node *node)\r
+{\r
+       struct ibv_recv_wr recv_wr, *recv_failure;\r
+       struct ibv_sge sge;\r
+       int i, ret = 0;\r
+\r
+       if (!message_count)\r
+               return 0;\r
+\r
+       recv_wr.next = NULL;\r
+       recv_wr.sg_list = &sge;\r
+       recv_wr.num_sge = 1;\r
+       recv_wr.wr_id = (uintptr_t) node;\r
+\r
+       sge.length = message_size;\r
+       sge.lkey = node->mr->lkey;\r
+       sge.addr = (uintptr_t) node->mem;\r
+\r
+       for (i = 0; i < message_count && !ret; i++ ) {\r
+               ret = ibv_post_recv(node->cma_id->qp, &recv_wr, &recv_failure);\r
+               if (ret) {\r
+                       printf("failed to post receives: 0x%x\n", ret);\r
+                       break;\r
+               }\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int post_sends(struct cmatest_node *node)\r
+{\r
+       struct ibv_send_wr send_wr, *bad_send_wr;\r
+       struct ibv_sge sge;\r
+       int i, ret = 0;\r
+\r
+       if (!node->connected || !message_count)\r
+               return 0;\r
+\r
+       send_wr.next = NULL;\r
+       send_wr.sg_list = &sge;\r
+       send_wr.num_sge = 1;\r
+       send_wr.opcode = IBV_WR_SEND;\r
+       send_wr.send_flags = 0;\r
+       send_wr.wr_id = (ULONG_PTR) node;\r
+\r
+       sge.length = message_size;\r
+       sge.lkey = node->mr->lkey;\r
+       sge.addr = (uintptr_t) node->mem;\r
+\r
+       for (i = 0; i < message_count && !ret; i++) {\r
+               ret = ibv_post_send(node->cma_id->qp, &send_wr, &bad_send_wr);\r
+               if (ret) \r
+                       printf("failed to post sends: 0x%x\n", ret);\r
+       }\r
+       return ret;\r
+}\r
+\r
+static void connect_error(void)\r
+{\r
+       test.disconnects_left--;\r
+       test.connects_left--;\r
+}\r
+\r
+static int addr_handler(struct cmatest_node *node)\r
+{\r
+       int ret;\r
+\r
+       if (set_tos) {\r
+               ret = rdma_set_option(node->cma_id, RDMA_OPTION_ID,\r
+                                     RDMA_OPTION_ID_TOS, &tos, sizeof tos);\r
+               if (ret)\r
+                       printf("cmatose: set TOS option failed: 0x%x\n", ret);\r
+       }\r
+\r
+       ret = rdma_resolve_route(node->cma_id, 2000);\r
+       if (ret) {\r
+               printf("cmatose: resolve route failed: 0x%x\n", ret);\r
+               connect_error();\r
+       }\r
+       return ret;\r
+}\r
+\r
+static int route_handler(struct cmatest_node *node)\r
+{\r
+       struct rdma_conn_param conn_param;\r
+       int ret;\r
+\r
+       ret = init_node(node);\r
+       if (ret)\r
+               goto err;\r
+\r
+       ret = post_recvs(node);\r
+       if (ret)\r
+               goto err;\r
+\r
+       memset(&conn_param, 0, sizeof conn_param);\r
+       conn_param.responder_resources = 1;\r
+       conn_param.initiator_depth = 1;\r
+       conn_param.retry_count = 5;\r
+       ret = rdma_connect(node->cma_id, &conn_param);\r
+       if (ret) {\r
+               printf("cmatose: failure connecting: 0x%x\n", ret);\r
+               goto err;\r
+       }\r
+       return 0;\r
+err:\r
+       connect_error();\r
+       return ret;\r
+}\r
+\r
+static int connect_handler(struct rdma_cm_id *cma_id)\r
+{\r
+       struct cmatest_node *node;\r
+       struct rdma_conn_param conn_param;\r
+       int ret;\r
+\r
+       if (test.conn_index == connections) {\r
+               ret = -1;\r
+               goto err1;\r
+       }\r
+       node = &test.nodes[test.conn_index++];\r
+\r
+       node->cma_id = cma_id;\r
+       cma_id->context = node;\r
+\r
+       ret = init_node(node);\r
+       if (ret)\r
+               goto err2;\r
+\r
+       ret = post_recvs(node);\r
+       if (ret)\r
+               goto err2;\r
+\r
+       memset(&conn_param, 0, sizeof conn_param);\r
+       conn_param.responder_resources = 1;\r
+       conn_param.initiator_depth = 1;\r
+       ret = rdma_accept(node->cma_id, &conn_param);\r
+       if (ret) {\r
+               printf("cmatose: failure accepting: 0x%x\n", ret);\r
+               goto err2;\r
+       }\r
+       return 0;\r
+\r
+err2:\r
+       node->cma_id = NULL;\r
+       connect_error();\r
+err1:\r
+       printf("cmatose: failing connection request\n");\r
+       rdma_reject(cma_id, NULL, 0);\r
+       return ret;\r
+}\r
+\r
+static int cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event)\r
+{\r
+       int ret = 0;\r
+\r
+       switch (event->event) {\r
+       case RDMA_CM_EVENT_ADDR_RESOLVED:\r
+               ret = addr_handler(cma_id->context);\r
+               break;\r
+       case RDMA_CM_EVENT_ROUTE_RESOLVED:\r
+               ret = route_handler(cma_id->context);\r
+               break;\r
+       case RDMA_CM_EVENT_CONNECT_REQUEST:\r
+               ret = connect_handler(cma_id);\r
+               break;\r
+       case RDMA_CM_EVENT_ESTABLISHED:\r
+               ((struct cmatest_node *) cma_id->context)->connected = 1;\r
+               test.connects_left--;\r
+               break;\r
+       case RDMA_CM_EVENT_ADDR_ERROR:\r
+       case RDMA_CM_EVENT_ROUTE_ERROR:\r
+       case RDMA_CM_EVENT_CONNECT_ERROR:\r
+       case RDMA_CM_EVENT_UNREACHABLE:\r
+       case RDMA_CM_EVENT_REJECTED:\r
+               printf("cmatose: event: %s, error: 0x%x\n",\r
+                      rdma_event_str(event->event), event->status);\r
+               connect_error();\r
+               break;\r
+       case RDMA_CM_EVENT_DISCONNECTED:\r
+               rdma_disconnect(cma_id);\r
+               test.disconnects_left--;\r
+               break;\r
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:\r
+               /* Cleanup will occur after test completes. */\r
+               break;\r
+       default:\r
+               break;\r
+       }\r
+       return ret;\r
+}\r
+\r
+static void destroy_node(struct cmatest_node *node)\r
+{\r
+       if (!node->cma_id)\r
+               return;\r
+\r
+       if (node->cma_id->qp)\r
+               rdma_destroy_qp(node->cma_id);\r
+\r
+       if (node->cq)\r
+               ibv_destroy_cq(node->cq);\r
+\r
+       if (node->mem) {\r
+               ibv_dereg_mr(node->mr);\r
+               free(node->mem);\r
+       }\r
+\r
+       if (node->pd)\r
+               ibv_dealloc_pd(node->pd);\r
+\r
+       /* Destroy the RDMA ID after all device resources */\r
+       rdma_destroy_id(node->cma_id);\r
+}\r
+\r
+static int alloc_nodes(void)\r
+{\r
+       int ret, i;\r
+\r
+       test.nodes = malloc(sizeof *test.nodes * connections);\r
+       if (!test.nodes) {\r
+               printf("cmatose: unable to allocate memory for test nodes\n");\r
+               return -1;\r
+       }\r
+       memset(test.nodes, 0, sizeof *test.nodes * connections);\r
+\r
+       for (i = 0; i < connections; i++) {\r
+               test.nodes[i].id = i;\r
+               if (dst_addr) {\r
+                       ret = rdma_create_id(test.channel,\r
+                                            &test.nodes[i].cma_id,\r
+                                            &test.nodes[i], RDMA_PS_TCP);\r
+                       if (ret)\r
+                               goto err;\r
+               }\r
+       }\r
+       return 0;\r
+err:\r
+       while (--i >= 0)\r
+               rdma_destroy_id(test.nodes[i].cma_id);\r
+       free(test.nodes);\r
+       return ret;\r
+}\r
+\r
+static void destroy_nodes(void)\r
+{\r
+       int i;\r
+\r
+       for (i = 0; i < connections; i++)\r
+               destroy_node(&test.nodes[i]);\r
+       free(test.nodes);\r
+}\r
+\r
+static int poll_cqs(void)\r
+{\r
+       struct ibv_wc wc[8];\r
+       int done, i, ret;\r
+\r
+       for (i = 0; i < connections; i++) {\r
+               if (!test.nodes[i].connected)\r
+                       continue;\r
+\r
+               for (done = 0; done < message_count; done += ret) {\r
+                       ret = ibv_poll_cq(test.nodes[i].cq, 8, wc);\r
+                       if (ret < 0) {\r
+                               printf("cmatose: failed polling CQ: 0x%x\n", ret);\r
+                               return ret;\r
+                       }\r
+               }\r
+       }\r
+       return 0;\r
+}\r
+\r
+static int connect_events(void)\r
+{\r
+       struct rdma_cm_event *event;\r
+       int err = 0, ret = 0;\r
+\r
+       while (test.connects_left && !err) {\r
+               err = rdma_get_cm_event(test.channel, &event);\r
+               if (!err) {\r
+                       cma_handler(event->id, event);\r
+                       rdma_ack_cm_event(event);\r
+               } else {\r
+                       printf("cmatose: failure in rdma_get_cm_event in connect events\n");\r
+                       ret = err;\r
+               }\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static int disconnect_events(void)\r
+{\r
+       struct rdma_cm_event *event;\r
+       int err = 0, ret = 0;\r
+\r
+       while (test.disconnects_left && !err) {\r
+               err = rdma_get_cm_event(test.channel, &event);\r
+               if (!err) {\r
+                       cma_handler(event->id, event);\r
+                       rdma_ack_cm_event(event);\r
+               } else {\r
+                       printf("cmatose: failure in rdma_get_cm_event in disconnect events\n");\r
+                       ret = err;\r
+               }\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static int migrate_channel(struct rdma_cm_id *listen_id)\r
+{\r
+       struct rdma_event_channel *channel;\r
+       int i, ret;\r
+\r
+       printf("migrating to new event channel\n");\r
+\r
+       channel = rdma_create_event_channel();\r
+       if (!channel) {\r
+               printf("cmatose: failed to create event channel\n");\r
+               return -1;\r
+       }\r
+\r
+       ret = 0;\r
+       if (listen_id)\r
+               ret = rdma_migrate_id(listen_id, channel);\r
+\r
+       for (i = 0; i < connections && !ret; i++)\r
+               ret = rdma_migrate_id(test.nodes[i].cma_id, channel);\r
+\r
+       if (!ret) {\r
+               rdma_destroy_event_channel(test.channel);\r
+               test.channel = channel;\r
+       } else\r
+               printf("cmatose: failure migrating to channel: 0x%x\n", ret);\r
+\r
+       return ret;\r
+}\r
+\r
+static int get_addr(char *dst, struct sockaddr_in *addr)\r
+{\r
+       struct addrinfo *res;\r
+       int ret;\r
+\r
+       ret = getaddrinfo(dst, NULL, NULL, &res);\r
+       if (ret) {\r
+               printf("getaddrinfo failed - invalid hostname or IP address\n");\r
+               return ret;\r
+       }\r
+\r
+       if (res->ai_family != PF_INET) {\r
+               ret = -1;\r
+               goto out;\r
+       }\r
+\r
+       *addr = *(struct sockaddr_in *) res->ai_addr;\r
+out:\r
+       freeaddrinfo(res);\r
+       return ret;\r
+}\r
+\r
+static int run_server(void)\r
+{\r
+       struct rdma_cm_id *listen_id;\r
+       int i, ret;\r
+\r
+       printf("cmatose: starting server\n");\r
+       ret = rdma_create_id(test.channel, &listen_id, &test, RDMA_PS_TCP);\r
+       if (ret) {\r
+               printf("cmatose: listen request failed\n");\r
+               return ret;\r
+       }\r
+\r
+       if (src_addr) {\r
+               ret = get_addr(src_addr, &test.src_in);\r
+               if (ret)\r
+                       goto out;\r
+       } else\r
+               test.src_in.sin_family = PF_INET;\r
+\r
+       test.src_in.sin_port = port;\r
+       ret = rdma_bind_addr(listen_id, test.src_addr);\r
+       if (ret) {\r
+               printf("cmatose: bind address failed: 0x%x\n", ret);\r
+               goto out;\r
+       }\r
+\r
+       ret = rdma_listen(listen_id, 0);\r
+       if (ret) {\r
+               printf("cmatose: failure trying to listen: 0x%x\n", ret);\r
+               goto out;\r
+       }\r
+\r
+       ret = connect_events();\r
+       if (ret)\r
+               goto out;\r
+\r
+       if (message_count) {\r
+               printf("initiating data transfers\n");\r
+               for (i = 0; i < connections; i++) {\r
+                       ret = post_sends(&test.nodes[i]);\r
+                       if (ret)\r
+                               goto out;\r
+               }\r
+\r
+               printf("completing sends\n");\r
+               ret = poll_cqs();\r
+               if (ret)\r
+                       goto out;\r
+\r
+               printf("receiving data transfers\n");\r
+               ret = poll_cqs();\r
+               if (ret)\r
+                       goto out;\r
+               printf("data transfers complete\n");\r
+\r
+       }\r
+\r
+       if (migrate) {\r
+               ret = migrate_channel(listen_id);\r
+               if (ret)\r
+                       goto out;\r
+       }\r
+\r
+       printf("cmatose: disconnecting\n");\r
+       for (i = 0; i < connections; i++) {\r
+               if (!test.nodes[i].connected)\r
+                       continue;\r
+\r
+               test.nodes[i].connected = 0;\r
+               rdma_disconnect(test.nodes[i].cma_id);\r
+       }\r
+\r
+       ret = disconnect_events();\r
+\r
+       printf("disconnected\n");\r
+\r
+out:\r
+       rdma_destroy_id(listen_id);\r
+       return ret;\r
+}\r
+\r
+static int run_client(void)\r
+{\r
+       int i, ret, ret2;\r
+\r
+       printf("cmatose: starting client\n");\r
+       if (src_addr) {\r
+               ret = get_addr(src_addr, &test.src_in);\r
+               if (ret)\r
+                       return ret;\r
+       }\r
+\r
+       ret = get_addr(dst_addr, &test.dst_in);\r
+       if (ret)\r
+               return ret;\r
+\r
+       test.dst_in.sin_port = port;\r
+\r
+       printf("cmatose: connecting\n");\r
+       for (i = 0; i < connections; i++) {\r
+               ret = rdma_resolve_addr(test.nodes[i].cma_id,\r
+                                       src_addr ? test.src_addr : NULL,\r
+                                       test.dst_addr, 2000);\r
+               if (ret) {\r
+                       printf("cmatose: failure getting addr: 0x%x\n", ret);\r
+                       connect_error();\r
+                       return ret;\r
+               }\r
+       }\r
+\r
+       ret = connect_events();\r
+       if (ret)\r
+               goto disc;\r
+\r
+       if (message_count) {\r
+               printf("receiving data transfers\n");\r
+               ret = poll_cqs();\r
+               if (ret)\r
+                       goto disc;\r
+\r
+               printf("sending replies\n");\r
+               for (i = 0; i < connections; i++) {\r
+                       ret = post_sends(&test.nodes[i]);\r
+                       if (ret)\r
+                               goto disc;\r
+               }\r
+\r
+               printf("data transfers complete\n");\r
+       }\r
+\r
+       ret = 0;\r
+\r
+       if (migrate) {\r
+               ret = migrate_channel(NULL);\r
+               if (ret)\r
+                       goto out;\r
+       }\r
+disc:\r
+       ret2 = disconnect_events();\r
+       if (ret2)\r
+               ret = ret2;\r
+out:\r
+       return ret;\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+       int op, ret;\r
+\r
+       while ((op = getopt(argc, argv, "s:b:c:C:S:t:p:m")) != -1) {\r
+               switch (op) {\r
+               case 's':\r
+                       dst_addr = optarg;\r
+                       break;\r
+               case 'b':\r
+                       src_addr = optarg;\r
+                       break;\r
+               case 'c':\r
+                       connections = atoi(optarg);\r
+                       break;\r
+               case 'C':\r
+                       message_count = atoi(optarg);\r
+                       break;\r
+               case 'S':\r
+                       message_size = atoi(optarg);\r
+                       break;\r
+               case 't':\r
+                       set_tos = 1;\r
+                       tos = (uint8_t) atoi(optarg);\r
+                       break;\r
+               case 'p':\r
+                       port = (uint16_t) atoi(optarg);\r
+                       break;\r
+               case 'm':\r
+                       migrate = 1;\r
+                       break;\r
+               default:\r
+                       printf("usage: %s\n", argv[0]);\r
+                       printf("\t[-s server_address]\n");\r
+                       printf("\t[-b bind_address]\n");\r
+                       printf("\t[-c connections]\n");\r
+                       printf("\t[-C message_count]\n");\r
+                       printf("\t[-S message_size]\n");\r
+                       printf("\t[-t type_of_service]\n");\r
+                       printf("\t[-p port_number]\n");\r
+                       printf("\t[-m(igrate)]\n");\r
+                       exit(1);\r
+               }\r
+       }\r
+\r
+       test.dst_addr = (struct sockaddr *) &test.dst_in;\r
+       test.src_addr = (struct sockaddr *) &test.src_in;\r
+       test.connects_left = connections;\r
+       test.disconnects_left = connections;\r
+\r
+       test.channel = rdma_create_event_channel();\r
+       if (!test.channel) {\r
+               printf("failed to create event channel\n");\r
+               exit(1);\r
+       }\r
+\r
+       if (alloc_nodes())\r
+               exit(1);\r
+\r
+       if (dst_addr)\r
+               ret = run_client();\r
+       else\r
+               ret = run_server();\r
+\r
+       printf("test complete\n");\r
+       destroy_nodes();\r
+       rdma_destroy_event_channel(test.channel);\r
+\r
+       printf("return status 0x%x\n", ret);\r
+       return ret;\r
+}\r
diff --git a/branches/winverbs/ulp/librdmacm/examples/cmatose/makefile b/branches/winverbs/ulp/librdmacm/examples/cmatose/makefile
new file mode 100644 (file)
index 0000000..a0c0627
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\..\inc\openib.def\r
diff --git a/branches/winverbs/ulp/librdmacm/examples/dirs b/branches/winverbs/ulp/librdmacm/examples/dirs
new file mode 100644 (file)
index 0000000..2bdf906
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS =                 \\r
+       cmatose\r
diff --git a/branches/winverbs/ulp/librdmacm/examples/rping/rping.c b/branches/winverbs/ulp/librdmacm/examples/rping/rping.c
new file mode 100644 (file)
index 0000000..f0d7572
--- /dev/null
@@ -0,0 +1,1105 @@
+/*\r
+ * Copyright (c) 2005 Ammasso, Inc. All rights reserved.\r
+ * Copyright (c) 2006 Open Grid Computing, Inc. All rights reserved.\r
+ * Copyright (c) 2009 Intel Corp.  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 AWV\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 <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <ws2tcpip.h>\r
+#include <winsock2.h>\r
+#include <time.h>\r
+\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#include <rdma/rdma_cma.h>\r
+\r
+#include <rdma/rdma_cma.h>\r
+\r
+static int debug = 0;\r
+#define DEBUG_LOG if (debug) printf\r
+\r
+/*\r
+ * rping "ping/pong" loop:\r
+ *     client sends source rkey/addr/len\r
+ *     server receives source rkey/add/len\r
+ *     server rdma reads "ping" data from source\r
+ *     server sends "go ahead" on rdma read completion\r
+ *     client sends sink rkey/addr/len\r
+ *     server receives sink rkey/addr/len\r
+ *     server rdma writes "pong" data to sink\r
+ *     server sends "go ahead" on rdma write completion\r
+ *     <repeat loop>\r
+ */\r
+\r
+/*\r
+ * These states are used to signal events between the completion handler\r
+ * and the main client or server thread.\r
+ *\r
+ * Once CONNECTED, they cycle through RDMA_READ_ADV, RDMA_WRITE_ADV, \r
+ * and RDMA_WRITE_COMPLETE for each ping.\r
+ */\r
+enum test_state {\r
+       IDLE = 1,\r
+       CONNECT_REQUEST,\r
+       ADDR_RESOLVED,\r
+       ROUTE_RESOLVED,\r
+       CONNECTED,\r
+       RDMA_READ_ADV,\r
+       RDMA_READ_COMPLETE,\r
+       RDMA_WRITE_ADV,\r
+       RDMA_WRITE_COMPLETE,\r
+       RDMA_ERROR\r
+};\r
+\r
+struct rping_rdma_info {\r
+       uint64_t buf;\r
+       uint32_t rkey;\r
+       uint32_t size;\r
+};\r
+\r
+#define RPING_SQ_DEPTH 16\r
+\r
+#define RPING_MSG_FMT           "rdma-ping-%d: "\r
+#define RPING_MIN_BUFSIZE       16\r
+\r
+/*\r
+ * Control block struct.\r
+ */\r
+struct rping_cb {\r
+       int server;                     /* 0 iff client */\r
+       pthread_t cqthread;\r
+       struct ibv_comp_channel *channel;\r
+       struct ibv_cq *cq;\r
+       struct ibv_pd *pd;\r
+       struct ibv_qp *qp;\r
+\r
+       struct ibv_recv_wr rq_wr;       /* recv work request record */\r
+       struct ibv_sge recv_sgl;        /* recv single SGE */\r
+       struct rping_rdma_info recv_buf;/* malloc'd buffer */\r
+       struct ibv_mr *recv_mr;         /* MR associated with this buffer */\r
+\r
+       struct ibv_send_wr sq_wr;       /* send work request record */\r
+       struct ibv_sge send_sgl;\r
+       struct rping_rdma_info send_buf;/* single send buf */\r
+       struct ibv_mr *send_mr;\r
+\r
+       struct ibv_send_wr rdma_sq_wr;  /* rdma work request record */\r
+       struct ibv_sge rdma_sgl;        /* rdma single SGE */\r
+       char *rdma_buf;                 /* used as rdma sink */\r
+       struct ibv_mr *rdma_mr;\r
+\r
+       uint32_t remote_rkey;           /* remote guys RKEY */\r
+       uint64_t remote_addr;           /* remote guys TO */\r
+       uint32_t remote_len;            /* remote guys LEN */\r
+\r
+       char *start_buf;                /* rdma read src */\r
+       struct ibv_mr *start_mr;\r
+\r
+       enum test_state state;          /* used for cond/signalling */\r
+       sem_t sem;\r
+\r
+       struct sockaddr_in sin;\r
+       uint16_t port;                  /* dst port in NBO */\r
+       int verbose;                    /* verbose logging */\r
+       int count;                      /* ping count */\r
+       int size;                       /* ping data size */\r
+       int validate;                   /* validate ping data */\r
+\r
+       /* CM stuff */\r
+       pthread_t cmthread;\r
+       struct rdma_event_channel *cm_channel;\r
+       struct rdma_cm_id *cm_id;       /* connection on client side,*/\r
+                                       /* listener on service side. */\r
+       struct rdma_cm_id *child_cm_id; /* connection on server side */\r
+};\r
+\r
+static int rping_cma_event_handler(struct rdma_cm_id *cma_id,\r
+                                   struct rdma_cm_event *event)\r
+{\r
+       int ret = 0;\r
+       struct rping_cb *cb = cma_id->context;\r
+\r
+       DEBUG_LOG("cma_event type %s cma_id %p (%s)\n",\r
+                 rdma_event_str(event->event), cma_id,\r
+                 (cma_id == cb->cm_id) ? "parent" : "child");\r
+\r
+       switch (event->event) {\r
+       case RDMA_CM_EVENT_ADDR_RESOLVED:\r
+               cb->state = ADDR_RESOLVED;\r
+               ret = rdma_resolve_route(cma_id, 2000);\r
+               if (ret) {\r
+                       cb->state = RDMA_ERROR;\r
+                       fprintf(stderr, "rdma_resolve_route error %d\n", ret);\r
+                       sem_post(&cb->sem);\r
+               }\r
+               break;\r
+\r
+       case RDMA_CM_EVENT_ROUTE_RESOLVED:\r
+               cb->state = ROUTE_RESOLVED;\r
+               sem_post(&cb->sem);\r
+               break;\r
+\r
+       case RDMA_CM_EVENT_CONNECT_REQUEST:\r
+               cb->state = CONNECT_REQUEST;\r
+               cb->child_cm_id = cma_id;\r
+               DEBUG_LOG("child cma %p\n", cb->child_cm_id);\r
+               sem_post(&cb->sem);\r
+               break;\r
+\r
+       case RDMA_CM_EVENT_ESTABLISHED:\r
+               DEBUG_LOG("ESTABLISHED\n");\r
+\r
+               /*\r
+                * Server will wake up when first RECV completes.\r
+                */\r
+               if (!cb->server) {\r
+                       cb->state = CONNECTED;\r
+               }\r
+               sem_post(&cb->sem);\r
+               break;\r
+\r
+       case RDMA_CM_EVENT_ADDR_ERROR:\r
+       case RDMA_CM_EVENT_ROUTE_ERROR:\r
+       case RDMA_CM_EVENT_CONNECT_ERROR:\r
+       case RDMA_CM_EVENT_UNREACHABLE:\r
+       case RDMA_CM_EVENT_REJECTED:\r
+               fprintf(stderr, "cma event %s, error %d\n",\r
+                       rdma_event_str(event->event), event->status);\r
+               sem_post(&cb->sem);\r
+               ret = -1;\r
+               break;\r
+\r
+       case RDMA_CM_EVENT_DISCONNECTED:\r
+               fprintf(stderr, "%s DISCONNECT EVENT...\n",\r
+                       cb->server ? "server" : "client");\r
+               sem_post(&cb->sem);\r
+               break;\r
+\r
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:\r
+               fprintf(stderr, "cma detected device removal!!!!\n");\r
+               ret = -1;\r
+               break;\r
+\r
+       default:\r
+               fprintf(stderr, "unhandled event: %s, ignoring\n",\r
+                       rdma_event_str(event->event));\r
+               break;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static int server_recv(struct rping_cb *cb, struct ibv_wc *wc)\r
+{\r
+       if (wc->byte_len != sizeof(cb->recv_buf)) {\r
+               fprintf(stderr, "Received bogus data, size %d\n", wc->byte_len);\r
+               return -1;\r
+       }\r
+\r
+       cb->remote_rkey = ntohl(cb->recv_buf.rkey);\r
+       cb->remote_addr = ntohll(cb->recv_buf.buf);\r
+       cb->remote_len  = ntohl(cb->recv_buf.size);\r
+       DEBUG_LOG("Received rkey %x addr %" PRIx64 " len %d from peer\n",\r
+                 cb->remote_rkey, cb->remote_addr, cb->remote_len);\r
+\r
+       if (cb->state <= CONNECTED || cb->state == RDMA_WRITE_COMPLETE)\r
+               cb->state = RDMA_READ_ADV;\r
+       else\r
+               cb->state = RDMA_WRITE_ADV;\r
+\r
+       return 0;\r
+}\r
+\r
+static int client_recv(struct rping_cb *cb, struct ibv_wc *wc)\r
+{\r
+       if (wc->byte_len != sizeof(cb->recv_buf)) {\r
+               fprintf(stderr, "Received bogus data, size %d\n", wc->byte_len);\r
+               return -1;\r
+       }\r
+\r
+       if (cb->state == RDMA_READ_ADV)\r
+               cb->state = RDMA_WRITE_ADV;\r
+       else\r
+               cb->state = RDMA_WRITE_COMPLETE;\r
+\r
+       return 0;\r
+}\r
+\r
+static int rping_cq_event_handler(struct rping_cb *cb)\r
+{\r
+       struct ibv_wc wc;\r
+       struct ibv_recv_wr *bad_wr;\r
+       int ret;\r
+\r
+       while ((ret = ibv_poll_cq(cb->cq, 1, &wc)) == 1) {\r
+               ret = 0;\r
+\r
+               if (wc.status) {\r
+                       fprintf(stderr, "cq completion failed status %d\n",\r
+                               wc.status);\r
+                       if (wc.status != IBV_WC_WR_FLUSH_ERR)\r
+                               ret = -1;\r
+                       goto error;\r
+               }\r
+\r
+               switch (wc.opcode) {\r
+               case IBV_WC_SEND:\r
+                       DEBUG_LOG("send completion\n");\r
+                       break;\r
+\r
+               case IBV_WC_RDMA_WRITE:\r
+                       DEBUG_LOG("rdma write completion\n");\r
+                       cb->state = RDMA_WRITE_COMPLETE;\r
+                       sem_post(&cb->sem);\r
+                       break;\r
+\r
+               case IBV_WC_RDMA_READ:\r
+                       DEBUG_LOG("rdma read completion\n");\r
+                       cb->state = RDMA_READ_COMPLETE;\r
+                       sem_post(&cb->sem);\r
+                       break;\r
+\r
+               case IBV_WC_RECV:\r
+                       DEBUG_LOG("recv completion\n");\r
+                       ret = cb->server ? server_recv(cb, &wc) :\r
+                                          client_recv(cb, &wc);\r
+                       if (ret) {\r
+                               fprintf(stderr, "recv wc error: %d\n", ret);\r
+                               goto error;\r
+                       }\r
+\r
+                       ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);\r
+                       if (ret) {\r
+                               fprintf(stderr, "post recv error: %d\n", ret);\r
+                               goto error;\r
+                       }\r
+                       sem_post(&cb->sem);\r
+                       break;\r
+\r
+               default:\r
+                       DEBUG_LOG("unknown!!!!! completion\n");\r
+                       ret = -1;\r
+                       goto error;\r
+               }\r
+       }\r
+       if (ret) {\r
+               fprintf(stderr, "poll error %d\n", ret);\r
+               goto error;\r
+       }\r
+       return 0;\r
+\r
+error:\r
+       cb->state = RDMA_ERROR;\r
+       sem_post(&cb->sem);\r
+       return ret;\r
+}\r
+\r
+static int rping_accept(struct rping_cb *cb)\r
+{\r
+       struct rdma_conn_param conn_param;\r
+       int ret;\r
+\r
+       DEBUG_LOG("accepting client connection request\n");\r
+\r
+       memset(&conn_param, 0, sizeof conn_param);\r
+       conn_param.responder_resources = 1;\r
+       conn_param.initiator_depth = 1;\r
+\r
+       ret = rdma_accept(cb->child_cm_id, &conn_param);\r
+       if (ret) {\r
+               fprintf(stderr, "rdma_accept error: %d\n", ret);\r
+               return ret;\r
+       }\r
+\r
+       sem_wait(&cb->sem);\r
+       if (cb->state == RDMA_ERROR) {\r
+               fprintf(stderr, "wait for CONNECTED state %d\n", cb->state);\r
+               return -1;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void rping_setup_wr(struct rping_cb *cb)\r
+{\r
+       cb->recv_sgl.addr = (uint64_t) (unsigned long) &cb->recv_buf;\r
+       cb->recv_sgl.length = sizeof cb->recv_buf;\r
+       cb->recv_sgl.lkey = cb->recv_mr->lkey;\r
+       cb->rq_wr.sg_list = &cb->recv_sgl;\r
+       cb->rq_wr.num_sge = 1;\r
+\r
+       cb->send_sgl.addr = (uint64_t) (unsigned long) &cb->send_buf;\r
+       cb->send_sgl.length = sizeof cb->send_buf;\r
+       cb->send_sgl.lkey = cb->send_mr->lkey;\r
+\r
+       cb->sq_wr.opcode = IBV_WR_SEND;\r
+       cb->sq_wr.send_flags = IBV_SEND_SIGNALED;\r
+       cb->sq_wr.sg_list = &cb->send_sgl;\r
+       cb->sq_wr.num_sge = 1;\r
+\r
+       cb->rdma_sgl.addr = (uint64_t) (unsigned long) cb->rdma_buf;\r
+       cb->rdma_sgl.lkey = cb->rdma_mr->lkey;\r
+       cb->rdma_sq_wr.send_flags = IBV_SEND_SIGNALED;\r
+       cb->rdma_sq_wr.sg_list = &cb->rdma_sgl;\r
+       cb->rdma_sq_wr.num_sge = 1;\r
+}\r
+\r
+static int rping_setup_buffers(struct rping_cb *cb)\r
+{\r
+       int ret;\r
+\r
+       DEBUG_LOG("rping_setup_buffers called on cb %p\n", cb);\r
+\r
+       cb->recv_mr = ibv_reg_mr(cb->pd, &cb->recv_buf, sizeof cb->recv_buf,\r
+                                IBV_ACCESS_LOCAL_WRITE);\r
+       if (!cb->recv_mr) {\r
+               fprintf(stderr, "recv_buf reg_mr failed\n");\r
+               return errno;\r
+       }\r
+\r
+       cb->send_mr = ibv_reg_mr(cb->pd, &cb->send_buf, sizeof cb->send_buf, 0);\r
+       if (!cb->send_mr) {\r
+               fprintf(stderr, "send_buf reg_mr failed\n");\r
+               ret = errno;\r
+               goto err1;\r
+       }\r
+\r
+       cb->rdma_buf = malloc(cb->size);\r
+       if (!cb->rdma_buf) {\r
+               fprintf(stderr, "rdma_buf malloc failed\n");\r
+               ret = -ENOMEM;\r
+               goto err2;\r
+       }\r
+\r
+       cb->rdma_mr = ibv_reg_mr(cb->pd, cb->rdma_buf, cb->size,\r
+                                IBV_ACCESS_LOCAL_WRITE |\r
+                                IBV_ACCESS_REMOTE_READ |\r
+                                IBV_ACCESS_REMOTE_WRITE);\r
+       if (!cb->rdma_mr) {\r
+               fprintf(stderr, "rdma_buf reg_mr failed\n");\r
+               ret = errno;\r
+               goto err3;\r
+       }\r
+\r
+       if (!cb->server) {\r
+               cb->start_buf = malloc(cb->size);\r
+               if (!cb->start_buf) {\r
+                       fprintf(stderr, "start_buf malloc failed\n");\r
+                       ret = -ENOMEM;\r
+                       goto err4;\r
+               }\r
+\r
+               cb->start_mr = ibv_reg_mr(cb->pd, cb->start_buf, cb->size,\r
+                                         IBV_ACCESS_LOCAL_WRITE | \r
+                                         IBV_ACCESS_REMOTE_READ |\r
+                                         IBV_ACCESS_REMOTE_WRITE);\r
+               if (!cb->start_mr) {\r
+                       fprintf(stderr, "start_buf reg_mr failed\n");\r
+                       ret = errno;\r
+                       goto err5;\r
+               }\r
+       }\r
+\r
+       rping_setup_wr(cb);\r
+       DEBUG_LOG("allocated & registered buffers...\n");\r
+       return 0;\r
+\r
+err5:\r
+       free(cb->start_buf);\r
+err4:\r
+       ibv_dereg_mr(cb->rdma_mr);\r
+err3:\r
+       free(cb->rdma_buf);\r
+err2:\r
+       ibv_dereg_mr(cb->send_mr);\r
+err1:\r
+       ibv_dereg_mr(cb->recv_mr);\r
+       return ret;\r
+}\r
+\r
+static void rping_free_buffers(struct rping_cb *cb)\r
+{\r
+       DEBUG_LOG("rping_free_buffers called on cb %p\n", cb);\r
+       ibv_dereg_mr(cb->recv_mr);\r
+       ibv_dereg_mr(cb->send_mr);\r
+       ibv_dereg_mr(cb->rdma_mr);\r
+       free(cb->rdma_buf);\r
+       if (!cb->server) {\r
+               ibv_dereg_mr(cb->start_mr);\r
+               free(cb->start_buf);\r
+       }\r
+}\r
+\r
+static int rping_create_qp(struct rping_cb *cb)\r
+{\r
+       struct ibv_qp_init_attr init_attr;\r
+       int ret;\r
+\r
+       memset(&init_attr, 0, sizeof(init_attr));\r
+       init_attr.cap.max_send_wr = RPING_SQ_DEPTH;\r
+       init_attr.cap.max_recv_wr = 2;\r
+       init_attr.cap.max_recv_sge = 1;\r
+       init_attr.cap.max_send_sge = 1;\r
+       init_attr.qp_type = IBV_QPT_RC;\r
+       init_attr.send_cq = cb->cq;\r
+       init_attr.recv_cq = cb->cq;\r
+\r
+       if (cb->server) {\r
+               ret = rdma_create_qp(cb->child_cm_id, cb->pd, &init_attr);\r
+               if (!ret)\r
+                       cb->qp = cb->child_cm_id->qp;\r
+       } else {\r
+               ret = rdma_create_qp(cb->cm_id, cb->pd, &init_attr);\r
+               if (!ret)\r
+                       cb->qp = cb->cm_id->qp;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static void rping_free_qp(struct rping_cb *cb)\r
+{\r
+       ibv_destroy_qp(cb->qp);\r
+       ibv_destroy_cq(cb->cq);\r
+       ibv_destroy_comp_channel(cb->channel);\r
+       ibv_dealloc_pd(cb->pd);\r
+}\r
+\r
+static int rping_setup_qp(struct rping_cb *cb, struct rdma_cm_id *cm_id)\r
+{\r
+       int ret;\r
+\r
+       cb->pd = ibv_alloc_pd(cm_id->verbs);\r
+       if (!cb->pd) {\r
+               fprintf(stderr, "ibv_alloc_pd failed\n");\r
+               return errno;\r
+       }\r
+       DEBUG_LOG("created pd %p\n", cb->pd);\r
+\r
+       cb->channel = ibv_create_comp_channel(cm_id->verbs);\r
+       if (!cb->channel) {\r
+               fprintf(stderr, "ibv_create_comp_channel failed\n");\r
+               ret = errno;\r
+               goto err1;\r
+       }\r
+       DEBUG_LOG("created channel %p\n", cb->channel);\r
+\r
+       cb->cq = ibv_create_cq(cm_id->verbs, RPING_SQ_DEPTH * 2, cb,\r
+                               cb->channel, 0);\r
+       if (!cb->cq) {\r
+               fprintf(stderr, "ibv_create_cq failed\n");\r
+               ret = errno;\r
+               goto err2;\r
+       }\r
+       DEBUG_LOG("created cq %p\n", cb->cq);\r
+\r
+       ret = ibv_req_notify_cq(cb->cq, 0);\r
+       if (ret) {\r
+               fprintf(stderr, "ibv_create_cq failed\n");\r
+               ret = errno;\r
+               goto err3;\r
+       }\r
+\r
+       ret = rping_create_qp(cb);\r
+       if (ret) {\r
+               fprintf(stderr, "rping_create_qp failed: %d\n", ret);\r
+               goto err3;\r
+       }\r
+       DEBUG_LOG("created qp %p\n", cb->qp);\r
+       return 0;\r
+\r
+err3:\r
+       ibv_destroy_cq(cb->cq);\r
+err2:\r
+       ibv_destroy_comp_channel(cb->channel);\r
+err1:\r
+       ibv_dealloc_pd(cb->pd);\r
+       return ret;\r
+}\r
+\r
+static void *cm_thread(void *arg)\r
+{\r
+       struct rping_cb *cb = arg;\r
+       struct rdma_cm_event *event;\r
+       int ret;\r
+\r
+       while (1) {\r
+               ret = rdma_get_cm_event(cb->cm_channel, &event);\r
+               if (ret) {\r
+                       fprintf(stderr, "rdma_get_cm_event err %d\n", ret);\r
+                       exit(ret);\r
+               }\r
+               ret = rping_cma_event_handler(event->id, event);\r
+               rdma_ack_cm_event(event);\r
+               if (ret)\r
+                       exit(ret);\r
+       }\r
+}\r
+\r
+static void *cq_thread(void *arg)\r
+{\r
+       struct rping_cb *cb = arg;\r
+       struct ibv_cq *ev_cq;\r
+       void *ev_ctx;\r
+       int ret;\r
+       \r
+       DEBUG_LOG("cq_thread started.\n");\r
+\r
+       while (1) {     \r
+               pthread_testcancel();\r
+\r
+               ret = ibv_get_cq_event(cb->channel, &ev_cq, &ev_ctx);\r
+               if (ret) {\r
+                       fprintf(stderr, "Failed to get cq event!\n");\r
+                       pthread_exit(NULL);\r
+               }\r
+               if (ev_cq != cb->cq) {\r
+                       fprintf(stderr, "Unknown CQ!\n");\r
+                       pthread_exit(NULL);\r
+               }\r
+               ret = ibv_req_notify_cq(cb->cq, 0);\r
+               if (ret) {\r
+                       fprintf(stderr, "Failed to set notify!\n");\r
+                       pthread_exit(NULL);\r
+               }\r
+               ret = rping_cq_event_handler(cb);\r
+               ibv_ack_cq_events(cb->cq, 1);\r
+               if (ret)\r
+                       pthread_exit(NULL);\r
+       }\r
+}\r
+\r
+static void rping_format_send(struct rping_cb *cb, char *buf, struct ibv_mr *mr)\r
+{\r
+       struct rping_rdma_info *info = &cb->send_buf;\r
+\r
+       info->buf = htonll((uint64_t) (unsigned long) buf);\r
+       info->rkey = htonl(mr->rkey);\r
+       info->size = htonl(cb->size);\r
+\r
+       DEBUG_LOG("RDMA addr %" PRIx64" rkey %x len %d\n",\r
+                 ntohll(info->buf), ntohl(info->rkey), ntohl(info->size));\r
+}\r
+\r
+static int rping_test_server(struct rping_cb *cb)\r
+{\r
+       struct ibv_send_wr *bad_wr;\r
+       int ret;\r
+\r
+       while (1) {\r
+               /* Wait for client's Start STAG/TO/Len */\r
+               sem_wait(&cb->sem);\r
+               if (cb->state != RDMA_READ_ADV) {\r
+                       fprintf(stderr, "wait for RDMA_READ_ADV state %d\n",\r
+                               cb->state);\r
+                       ret = -1;\r
+                       break;\r
+               }\r
+\r
+               DEBUG_LOG("server received sink adv\n");\r
+\r
+               /* Issue RDMA Read. */\r
+               cb->rdma_sq_wr.opcode = IBV_WR_RDMA_READ;\r
+               cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey;\r
+               cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr;\r
+               cb->rdma_sq_wr.sg_list->length = cb->remote_len;\r
+\r
+               ret = ibv_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr);\r
+               if (ret) {\r
+                       fprintf(stderr, "post send error %d\n", ret);\r
+                       break;\r
+               }\r
+               DEBUG_LOG("server posted rdma read req \n");\r
+\r
+               /* Wait for read completion */\r
+               sem_wait(&cb->sem);\r
+               if (cb->state != RDMA_READ_COMPLETE) {\r
+                       fprintf(stderr, "wait for RDMA_READ_COMPLETE state %d\n",\r
+                               cb->state);\r
+                       ret = -1;\r
+                       break;\r
+               }\r
+               DEBUG_LOG("server received read complete\n");\r
+\r
+               /* Display data in recv buf */\r
+               if (cb->verbose)\r
+                       printf("server ping data: %s\n", cb->rdma_buf);\r
+\r
+               /* Tell client to continue */\r
+               ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);\r
+               if (ret) {\r
+                       fprintf(stderr, "post send error %d\n", ret);\r
+                       break;\r
+               }\r
+               DEBUG_LOG("server posted go ahead\n");\r
+\r
+               /* Wait for client's RDMA STAG/TO/Len */\r
+               sem_wait(&cb->sem);\r
+               if (cb->state != RDMA_WRITE_ADV) {\r
+                       fprintf(stderr, "wait for RDMA_WRITE_ADV state %d\n",\r
+                               cb->state);\r
+                       ret = -1;\r
+                       break;\r
+               }\r
+               DEBUG_LOG("server received sink adv\n");\r
+\r
+               /* RDMA Write echo data */\r
+               cb->rdma_sq_wr.opcode = IBV_WR_RDMA_WRITE;\r
+               cb->rdma_sq_wr.wr.rdma.rkey = cb->remote_rkey;\r
+               cb->rdma_sq_wr.wr.rdma.remote_addr = cb->remote_addr;\r
+               cb->rdma_sq_wr.sg_list->length = strlen(cb->rdma_buf) + 1;\r
+               DEBUG_LOG("rdma write from lkey %x laddr %" PRIx64 " len %d\n",\r
+                         cb->rdma_sq_wr.sg_list->lkey,\r
+                         cb->rdma_sq_wr.sg_list->addr,\r
+                         cb->rdma_sq_wr.sg_list->length);\r
+\r
+               ret = ibv_post_send(cb->qp, &cb->rdma_sq_wr, &bad_wr);\r
+               if (ret) {\r
+                       fprintf(stderr, "post send error %d\n", ret);\r
+                       break;\r
+               }\r
+\r
+               /* Wait for completion */\r
+               ret = sem_wait(&cb->sem);\r
+               if (cb->state != RDMA_WRITE_COMPLETE) {\r
+                       fprintf(stderr, "wait for RDMA_WRITE_COMPLETE state %d\n",\r
+                               cb->state);\r
+                       ret = -1;\r
+                       break;\r
+               }\r
+               DEBUG_LOG("server rdma write complete \n");\r
+\r
+               /* Tell client to begin again */\r
+               ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);\r
+               if (ret) {\r
+                       fprintf(stderr, "post send error %d\n", ret);\r
+                       break;\r
+               }\r
+               DEBUG_LOG("server posted go ahead\n");\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static int rping_bind_server(struct rping_cb *cb)\r
+{\r
+       int ret;\r
+\r
+       cb->sin.sin_port = cb->port;\r
+       ret = rdma_bind_addr(cb->cm_id, (struct sockaddr *) &cb->sin);\r
+       if (ret) {\r
+               fprintf(stderr, "rdma_bind_addr error %d\n", ret);\r
+               return ret;\r
+       }\r
+       DEBUG_LOG("rdma_bind_addr successful\n");\r
+\r
+       DEBUG_LOG("rdma_listen\n");\r
+       ret = rdma_listen(cb->cm_id, 3);\r
+       if (ret) {\r
+               fprintf(stderr, "rdma_listen failed: %d\n", ret);\r
+               return ret;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static struct rping_cb *clone_cb(struct rping_cb *listening_cb)\r
+{\r
+       struct rping_cb *cb = malloc(sizeof *cb);\r
+       if (!cb)\r
+               return NULL;\r
+       *cb = *listening_cb;\r
+       cb->child_cm_id->context = cb;\r
+       return cb;\r
+}\r
+\r
+static void free_cb(struct rping_cb *cb)\r
+{\r
+       free(cb);\r
+}\r
+\r
+static int rping_run_server(struct rping_cb *cb)\r
+{\r
+       struct ibv_recv_wr *bad_wr;\r
+       int ret;\r
+\r
+       ret = rping_bind_server(cb);\r
+       if (ret)\r
+               return ret;\r
+\r
+       sem_wait(&cb->sem);\r
+       if (cb->state != CONNECT_REQUEST) {\r
+               fprintf(stderr, "wait for CONNECT_REQUEST state %d\n",\r
+                       cb->state);\r
+               return -1;\r
+       }\r
+\r
+       ret = rping_setup_qp(cb, cb->child_cm_id);\r
+       if (ret) {\r
+               fprintf(stderr, "setup_qp failed: %d\n", ret);\r
+               return ret;\r
+       }\r
+\r
+       ret = rping_setup_buffers(cb);\r
+       if (ret) {\r
+               fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);\r
+               goto err1;\r
+       }\r
+\r
+       ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);\r
+       if (ret) {\r
+               fprintf(stderr, "ibv_post_recv failed: %d\n", ret);\r
+               goto err2;\r
+       }\r
+\r
+       pthread_create(&cb->cqthread, NULL, cq_thread, cb);\r
+\r
+       ret = rping_accept(cb);\r
+       if (ret) {\r
+               fprintf(stderr, "connect error %d\n", ret);\r
+               goto err2;\r
+       }\r
+\r
+       rping_test_server(cb);\r
+       rdma_disconnect(cb->child_cm_id);\r
+       rdma_destroy_id(cb->child_cm_id);\r
+err2:\r
+       rping_free_buffers(cb);\r
+err1:\r
+       rping_free_qp(cb);\r
+\r
+       return ret;\r
+}\r
+\r
+static int rping_test_client(struct rping_cb *cb)\r
+{\r
+       int ping, start, cc, i, ret = 0;\r
+       struct ibv_send_wr *bad_wr;\r
+       unsigned char c;\r
+\r
+       start = 65;\r
+       for (ping = 0; !cb->count || ping < cb->count; ping++) {\r
+               cb->state = RDMA_READ_ADV;\r
+\r
+               /* Put some ascii text in the buffer. */\r
+               cc = sprintf(cb->start_buf, RPING_MSG_FMT, ping);\r
+               for (i = cc, c = start; i < cb->size; i++) {\r
+                       cb->start_buf[i] = c;\r
+                       c++;\r
+                       if (c > 122)\r
+                               c = 65;\r
+               }\r
+               start++;\r
+               if (start > 122)\r
+                       start = 65;\r
+               cb->start_buf[cb->size - 1] = 0;\r
+\r
+               rping_format_send(cb, cb->start_buf, cb->start_mr);\r
+               ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);\r
+               if (ret) {\r
+                       fprintf(stderr, "post send error %d\n", ret);\r
+                       break;\r
+               }\r
+\r
+               /* Wait for server to ACK */\r
+               sem_wait(&cb->sem);\r
+               if (cb->state != RDMA_WRITE_ADV) {\r
+                       fprintf(stderr, "wait for RDMA_WRITE_ADV state %d\n",\r
+                               cb->state);\r
+                       ret = -1;\r
+                       break;\r
+               }\r
+\r
+               rping_format_send(cb, cb->rdma_buf, cb->rdma_mr);\r
+               ret = ibv_post_send(cb->qp, &cb->sq_wr, &bad_wr);\r
+               if (ret) {\r
+                       fprintf(stderr, "post send error %d\n", ret);\r
+                       break;\r
+               }\r
+\r
+               /* Wait for the server to say the RDMA Write is complete. */\r
+               sem_wait(&cb->sem);\r
+               if (cb->state != RDMA_WRITE_COMPLETE) {\r
+                       fprintf(stderr, "wait for RDMA_WRITE_COMPLETE state %d\n",\r
+                               cb->state);\r
+                       ret = -1;\r
+                       break;\r
+               }\r
+\r
+               if (cb->validate)\r
+                       if (memcmp(cb->start_buf, cb->rdma_buf, cb->size)) {\r
+                               fprintf(stderr, "data mismatch!\n");\r
+                               ret = -1;\r
+                               break;\r
+                       }\r
+\r
+               if (cb->verbose)\r
+                       printf("ping data: %s\n", cb->rdma_buf);\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static int rping_connect_client(struct rping_cb *cb)\r
+{\r
+       struct rdma_conn_param conn_param;\r
+       int ret;\r
+\r
+       memset(&conn_param, 0, sizeof conn_param);\r
+       conn_param.responder_resources = 1;\r
+       conn_param.initiator_depth = 1;\r
+       conn_param.retry_count = 10;\r
+\r
+       ret = rdma_connect(cb->cm_id, &conn_param);\r
+       if (ret) {\r
+               fprintf(stderr, "rdma_connect error %d\n", ret);\r
+               return ret;\r
+       }\r
+\r
+       sem_wait(&cb->sem);\r
+       if (cb->state != CONNECTED) {\r
+               fprintf(stderr, "wait for CONNECTED state %d\n", cb->state);\r
+               return -1;\r
+       }\r
+\r
+       DEBUG_LOG("rmda_connect successful\n");\r
+       return 0;\r
+}\r
+\r
+static int rping_bind_client(struct rping_cb *cb)\r
+{\r
+       int ret;\r
+\r
+       cb->sin.sin_port = cb->port;\r
+       ret = rdma_resolve_addr(cb->cm_id, NULL, (struct sockaddr *) &cb->sin, 2000);\r
+       if (ret) {\r
+               fprintf(stderr, "rdma_resolve_addr error %d\n", ret);\r
+               return ret;\r
+       }\r
+\r
+       sem_wait(&cb->sem);\r
+       if (cb->state != ROUTE_RESOLVED) {\r
+               fprintf(stderr, "waiting for addr/route resolution state %d\n",\r
+                       cb->state);\r
+               return -1;\r
+       }\r
+\r
+       DEBUG_LOG("rdma_resolve_addr - rdma_resolve_route successful\n");\r
+       return 0;\r
+}\r
+\r
+static int rping_run_client(struct rping_cb *cb)\r
+{\r
+       struct ibv_recv_wr *bad_wr;\r
+       int ret;\r
+\r
+       ret = rping_bind_client(cb);\r
+       if (ret)\r
+               return ret;\r
+\r
+       ret = rping_setup_qp(cb, cb->cm_id);\r
+       if (ret) {\r
+               fprintf(stderr, "setup_qp failed: %d\n", ret);\r
+               return ret;\r
+       }\r
+\r
+       ret = rping_setup_buffers(cb);\r
+       if (ret) {\r
+               fprintf(stderr, "rping_setup_buffers failed: %d\n", ret);\r
+               goto err1;\r
+       }\r
+\r
+       ret = ibv_post_recv(cb->qp, &cb->rq_wr, &bad_wr);\r
+       if (ret) {\r
+               fprintf(stderr, "ibv_post_recv failed: %d\n", ret);\r
+               goto err2;\r
+       }\r
+\r
+       pthread_create(&cb->cqthread, NULL, cq_thread, cb);\r
+\r
+       ret = rping_connect_client(cb);\r
+       if (ret) {\r
+               fprintf(stderr, "connect error %d\n", ret);\r
+               goto err2;\r
+       }\r
+\r
+       rping_test_client(cb);\r
+       rdma_disconnect(cb->cm_id);\r
+err2:\r
+       rping_free_buffers(cb);\r
+err1:\r
+       rping_free_qp(cb);\r
+\r
+       return ret;\r
+}\r
+\r
+static int get_addr(char *dst, struct sockaddr_in *addr)\r
+{\r
+       struct addrinfo *res;\r
+       int ret;\r
+\r
+       ret = getaddrinfo(dst, NULL, NULL, &res);\r
+       if (ret) {\r
+               printf("getaddrinfo failed - invalid hostname or IP address\n");\r
+               return ret;\r
+       }\r
+\r
+       if (res->ai_family != PF_INET) {\r
+               ret = -1;\r
+               goto out;\r
+       }\r
+\r
+       *addr = *(struct sockaddr_in *) res->ai_addr;\r
+out:\r
+       freeaddrinfo(res);\r
+       return ret;\r
+}\r
+\r
+static void usage()\r
+{\r
+       printf("rdma_rping -s [-vVd] [-S size] [-C count] [-a addr] [-p port]\n");\r
+       printf("rdma_rping -c [-vVd] [-S size] [-C count] -a addr [-p port]\n");\r
+       printf("\t-c\t\tclient side\n");\r
+       printf("\t-s\t\tserver side\n");\r
+       printf("\t-v\t\tdisplay ping data to stdout\n");\r
+       printf("\t-V\t\tvalidate ping data\n");\r
+       printf("\t-d\t\tdebug printfs\n");\r
+       printf("\t-S size \tping data size\n");\r
+       printf("\t-C count\tping count times\n");\r
+       printf("\t-a addr\t\taddress\n");\r
+       printf("\t-p port\t\tport\n");\r
+}\r
+\r
+int main(int argc, char *argv[])\r
+{\r
+       struct rping_cb *cb;\r
+       int op;\r
+       int ret = 0;\r
+\r
+       cb = malloc(sizeof(*cb));\r
+       if (!cb)\r
+               return -ENOMEM;\r
+\r
+       memset(cb, 0, sizeof(*cb));\r
+       cb->server = -1;\r
+       cb->state = IDLE;\r
+       cb->size = 64;\r
+       cb->sin.sin_family = PF_INET;\r
+       cb->port = htons(7174);\r
+       sem_init(&cb->sem, 0, 0);\r
+\r
+       opterr = 0;\r
+       while ((op=getopt(argc, argv, "a:Pp:C:S:t:scvVd")) != -1) {\r
+               switch (op) {\r
+               case 'a':\r
+                       ret = get_addr(optarg, &cb->sin);\r
+                       break;\r
+               case 'p':\r
+                       cb->port = htons(atoi(optarg));\r
+                       DEBUG_LOG("port %d\n", (int) atoi(optarg));\r
+                       break;\r
+               case 's':\r
+                       cb->server = 1;\r
+                       DEBUG_LOG("server\n");\r
+                       break;\r
+               case 'c':\r
+                       cb->server = 0;\r
+                       DEBUG_LOG("client\n");\r
+                       break;\r
+               case 'S':\r
+                       cb->size = atoi(optarg);\r
+                       if (cb->size < RPING_MIN_BUFSIZE) {\r
+                               fprintf(stderr, "Invalid size (minimum is %d) " RPING_MIN_BUFSIZE);\r
+                               ret = EINVAL;\r
+                       } else\r
+                               DEBUG_LOG("size %d\n", (int) atoi(optarg));\r
+                       break;\r
+               case 'C':\r
+                       cb->count = atoi(optarg);\r
+                       if (cb->count < 0) {\r
+                               fprintf(stderr, "Invalid count %d\n", cb->count);\r
+                               ret = EINVAL;\r
+                       } else\r
+                               DEBUG_LOG("count %d\n", (int) cb->count);\r
+                       break;\r
+               case 'v':\r
+                       cb->verbose++;\r
+                       DEBUG_LOG("verbose\n");\r
+                       break;\r
+               case 'V':\r
+                       cb->validate++;\r
+                       DEBUG_LOG("validate data\n");\r
+                       break;\r
+               case 'd':\r
+                       debug++;\r
+                       break;\r
+               default:\r
+                       usage();\r
+                       ret = EINVAL;\r
+                       goto out;\r
+               }\r
+       }\r
+       if (ret)\r
+               goto out;\r
+\r
+       if (cb->server == -1) {\r
+               usage();\r
+               ret = EINVAL;\r
+               goto out;\r
+       }\r
+\r
+       cb->cm_channel = rdma_create_event_channel();\r
+       if (!cb->cm_channel) {\r
+               ret = errno;\r
+               fprintf(stderr, "rdma_create_event_channel error %d\n", ret);\r
+               goto out;\r
+       }\r
+\r
+       ret = rdma_create_id(cb->cm_channel, &cb->cm_id, cb, RDMA_PS_TCP);\r
+       if (ret) {\r
+               ret = errno;\r
+               fprintf(stderr, "rdma_create_id error %d\n", ret);\r
+               goto out2;\r
+       }\r
+       DEBUG_LOG("created cm_id %p\n", cb->cm_id);\r
+\r
+       pthread_create(&cb->cmthread, NULL, cm_thread, cb);\r
+\r
+       if (cb->server)\r
+               ret = rping_run_server(cb);\r
+       else\r
+               ret = rping_run_client(cb);\r
+\r
+       DEBUG_LOG("destroy cm_id %p\n", cb->cm_id);\r
+       rdma_destroy_id(cb->cm_id);\r
+out2:\r
+       rdma_destroy_event_channel(cb->cm_channel);\r
+out:\r
+       free(cb);\r
+       return ret;\r
+}\r
diff --git a/branches/winverbs/ulp/librdmacm/include/rdma/rdma_cma.h b/branches/winverbs/ulp/librdmacm/include/rdma/rdma_cma.h
new file mode 100644 (file)
index 0000000..3a5a4bb
--- /dev/null
@@ -0,0 +1,637 @@
+/*\r
+ * Copyright (c) 2005-2009 Intel Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenFabrics.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 AWV\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
+#pragma once\r
+\r
+#if !defined(RDMA_CMA_H)\r
+#define RDMA_CMA_H\r
+\r
+#include <windows.h>\r
+#include <infiniband\verbs.h>\r
+#include <rdma\winverbs.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+/*\r
+ * Interfaces based on librdmacm 1.0.8.\r
+ */\r
+\r
+typedef unsigned __int8                uint8_t;\r
+typedef unsigned __int16       uint16_t;\r
+typedef unsigned __int32       uint32_t;\r
+typedef unsigned __int64       uint64_t;\r
+\r
+/*\r
+ * Upon receiving a device removal event, users must destroy the associated\r
+ * RDMA identifier and release all resources allocated with the device.\r
+ */\r
+enum rdma_cm_event_type\r
+{\r
+       RDMA_CM_EVENT_ADDR_RESOLVED,\r
+       RDMA_CM_EVENT_ADDR_ERROR,\r
+       RDMA_CM_EVENT_ROUTE_RESOLVED,\r
+       RDMA_CM_EVENT_ROUTE_ERROR,\r
+       RDMA_CM_EVENT_CONNECT_REQUEST,\r
+       RDMA_CM_EVENT_CONNECT_RESPONSE,\r
+       RDMA_CM_EVENT_CONNECT_ERROR,\r
+       RDMA_CM_EVENT_UNREACHABLE,\r
+       RDMA_CM_EVENT_REJECTED,\r
+       RDMA_CM_EVENT_ESTABLISHED,\r
+       RDMA_CM_EVENT_DISCONNECTED,\r
+       RDMA_CM_EVENT_DEVICE_REMOVAL,\r
+       RDMA_CM_EVENT_MULTICAST_JOIN,\r
+       RDMA_CM_EVENT_MULTICAST_ERROR,\r
+       RDMA_CM_EVENT_ADDR_CHANGE,\r
+       RDMA_CM_EVENT_TIMEWAIT_EXIT\r
+};\r
+\r
+enum rdma_port_space\r
+{\r
+       RDMA_PS_IPOIB   = 0x0002,\r
+       RDMA_PS_TCP             = 0x0106,\r
+       RDMA_PS_UDP             = 0x0111,\r
+};\r
+\r
+/*\r
+ * Global qkey value for UDP QPs and multicast groups created via the \r
+ * RDMA CM.\r
+ */\r
+#define RDMA_UDP_QKEY 0x01234567\r
+\r
+struct ib_addr\r
+{\r
+       union ibv_gid   sgid;\r
+       union ibv_gid   dgid;\r
+       uint16_t                pkey;\r
+};\r
+\r
+struct rdma_addr\r
+{\r
+       struct sockaddr         src_addr;\r
+       uint8_t                         src_pad[sizeof(SOCKADDR_IN6) -\r
+                                                               sizeof(struct sockaddr)];\r
+       struct sockaddr         dst_addr;\r
+       uint8_t                         dst_pad[sizeof(SOCKADDR_IN6) -\r
+                                                               sizeof(struct sockaddr)];\r
+       union\r
+       {\r
+               struct ib_addr  ibaddr;\r
+       }       addr;\r
+};\r
+\r
+struct ibv_sa_path_rec\r
+{\r
+       uint8_t                         data[64];\r
+};\r
+\r
+struct rdma_route\r
+{\r
+       struct rdma_addr                addr;\r
+       struct ibv_sa_path_rec  *path_rec;\r
+       int                                             num_paths;\r
+};\r
+\r
+struct rdma_event_channel\r
+{\r
+       uint32_t                timeout;\r
+};\r
+\r
+struct rdma_cm_id\r
+{\r
+       struct ibv_context                      *verbs;\r
+       struct rdma_event_channel       *channel;\r
+       void                                            *context;\r
+       struct ibv_qp                           *qp;\r
+       struct rdma_route                       route;\r
+       enum rdma_port_space            ps;\r
+       uint8_t                                         port_num;\r
+\r
+       union {\r
+               IWVConnectEndpoint              *connect;\r
+               IWVDatagramEndpoint             *datagram;\r
+       }       ep;\r
+       OVERLAPPED                                      overlap;\r
+       uint32_t                                        events_completed;\r
+};\r
+\r
+struct rdma_conn_param\r
+{\r
+       const void *private_data;\r
+       uint8_t private_data_len;\r
+       uint8_t responder_resources;\r
+       uint8_t initiator_depth;\r
+       uint8_t flow_control;\r
+       uint8_t retry_count;            /* ignored when accepting */\r
+       uint8_t rnr_retry_count;\r
+       /* Fields below ignored if a QP is created on the rdma_cm_id. */\r
+       uint8_t srq;\r
+       uint32_t qp_num;\r
+};\r
+\r
+struct rdma_ud_param\r
+{\r
+       const void *private_data;\r
+       uint8_t private_data_len;\r
+       struct ibv_ah_attr ah_attr;\r
+       uint32_t qp_num;\r
+       uint32_t qkey;\r
+};\r
+\r
+struct rdma_cm_event\r
+{\r
+       struct rdma_cm_id               *id;\r
+       struct rdma_cm_id               *listen_id;\r
+       enum rdma_cm_event_type  event;\r
+       int                                              status;\r
+       union\r
+       {\r
+               struct rdma_conn_param conn;\r
+               struct rdma_ud_param   ud;\r
+\r
+       }       param;\r
+};\r
+\r
+/**\r
+ * rdma_create_event_channel - Open a channel used to report communication events.\r
+ * Description:\r
+ *   Asynchronous events are reported to users through event channels.  Each\r
+ *   event channel maps to a file descriptor.\r
+ * Notes:\r
+ *   All created event channels must be destroyed by calling\r
+ *   rdma_destroy_event_channel.  Users should call rdma_get_cm_event to\r
+ *   retrieve events on an event channel.\r
+ * See also:\r
+ *   rdma_get_cm_event, rdma_destroy_event_channel\r
+ */\r
+__declspec(dllexport)\r
+struct rdma_event_channel *rdma_create_event_channel(void);\r
+\r
+/**\r
+ * rdma_destroy_event_channel - Close an event communication channel.\r
+ * @channel: The communication channel to destroy.\r
+ * Description:\r
+ *   Release all resources associated with an event channel and closes the\r
+ *   associated file descriptor.\r
+ * Notes:\r
+ *   All rdma_cm_id's associated with the event channel must be destroyed,\r
+ *   and all returned events must be acked before calling this function.\r
+ * See also:\r
+ *  rdma_create_event_channel, rdma_get_cm_event, rdma_ack_cm_event\r
+ */\r
+__declspec(dllexport)\r
+void rdma_destroy_event_channel(struct rdma_event_channel *channel);\r
+\r
+/**\r
+ * rdma_create_id - Allocate a communication identifier.\r
+ * @channel: The communication channel that events associated with the\r
+ *   allocated rdma_cm_id will be reported on.\r
+ * @id: A reference where the allocated communication identifier will be\r
+ *   returned.\r
+ * @context: User specified context associated with the rdma_cm_id.\r
+ * @ps: RDMA port space.\r
+ * Description:\r
+ *   Creates an identifier that is used to track communication information.\r
+ * Notes:\r
+ *   Rdma_cm_id's are conceptually equivalent to a socket for RDMA\r
+ *   communication.  The difference is that RDMA communication requires\r
+ *   explicitly binding to a specified RDMA device before communication\r
+ *   can occur, and most operations are asynchronous in nature.  Communication\r
+ *   events on an rdma_cm_id are reported through the associated event\r
+ *   channel.  Users must release the rdma_cm_id by calling rdma_destroy_id.\r
+ * See also:\r
+ *   rdma_create_event_channel, rdma_destroy_id, rdma_get_devices,\r
+ *   rdma_bind_addr, rdma_resolve_addr, rdma_connect, rdma_listen,\r
+ */\r
+__declspec(dllexport)\r
+int rdma_create_id(struct rdma_event_channel *channel,\r
+                                  struct rdma_cm_id **id, void *context,\r
+                                  enum rdma_port_space ps);\r
+\r
+/**\r
+ * rdma_destroy_id - Release a communication identifier.\r
+ * @id: The communication identifier to destroy.\r
+ * Description:\r
+ *   Destroys the specified rdma_cm_id and cancels any outstanding\r
+ *   asynchronous operation.\r
+ * Notes:\r
+ *   Users must free any associated QP with the rdma_cm_id before\r
+ *   calling this routine and ack an related events.\r
+ * See also:\r
+ *   rdma_create_id, rdma_destroy_qp, rdma_ack_cm_event\r
+ */\r
+__declspec(dllexport)\r
+int rdma_destroy_id(struct rdma_cm_id *id);\r
+\r
+/**\r
+ * rdma_bind_addr - Bind an RDMA identifier to a source address.\r
+ * @id: RDMA identifier.\r
+ * @addr: Local address information.  Wildcard values are permitted.\r
+ * Description:\r
+ *   Associates a source address with an rdma_cm_id.  The address may be\r
+ *   wildcarded.  If binding to a specific local address, the rdma_cm_id\r
+ *   will also be bound to a local RDMA device.\r
+ * Notes:\r
+ *   Typically, this routine is called before calling rdma_listen to bind\r
+ *   to a specific port number, but it may also be called on the active side\r
+ *   of a connection before calling rdma_resolve_addr to bind to a specific\r
+ *   address.\r
+ * See also:\r
+ *   rdma_create_id, rdma_listen, rdma_resolve_addr, rdma_create_qp\r
+ */\r
+__declspec(dllexport)\r
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr);\r
+\r
+/**\r
+ * rdma_resolve_addr - Resolve destination and optional source addresses.\r
+ * @id: RDMA identifier.\r
+ * @src_addr: Source address information.  This parameter may be NULL.\r
+ * @dst_addr: Destination address information.\r
+ * @timeout_ms: Time to wait for resolution to complete.\r
+ * Description:\r
+ *   Resolve destination and optional source addresses from IP addresses\r
+ *   to an RDMA address.  If successful, the specified rdma_cm_id will\r
+ *   be bound to a local device.\r
+ * Notes:\r
+ *   This call is used to map a given destination IP address to a usable RDMA\r
+ *   address.  If a source address is given, the rdma_cm_id is bound to that\r
+ *   address, the same as if rdma_bind_addr were called.  If no source\r
+ *   address is given, and the rdma_cm_id has not yet been bound to a device,\r
+ *   then the rdma_cm_id will be bound to a source address based on the\r
+ *   local routing tables.  After this call, the rdma_cm_id will be bound to\r
+ *   an RDMA device.  This call is typically made from the active side of a\r
+ *   connection before calling rdma_resolve_route and rdma_connect.\r
+ * See also:\r
+ *   rdma_create_id, rdma_resolve_route, rdma_connect, rdma_create_qp,\r
+ *   rdma_get_cm_event, rdma_bind_addr\r
+ */\r
+__declspec(dllexport)\r
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,\r
+                                         struct sockaddr *dst_addr, int timeout_ms);\r
+\r
+/**\r
+ * rdma_resolve_route - Resolve the route information needed to establish a connection.\r
+ * @id: RDMA identifier.\r
+ * @timeout_ms: Time to wait for resolution to complete.\r
+ * Description:\r
+ *   Resolves an RDMA route to the destination address in order to establish\r
+ *   a connection.  The destination address must have already been resolved\r
+ *   by calling rdma_resolve_addr.\r
+ * Notes:\r
+ *   This is called on the client side of a connection after calling\r
+ *   rdma_resolve_addr, but before calling rdma_connect.\r
+ * See also:\r
+ *   rdma_resolve_addr, rdma_connect, rdma_get_cm_event\r
+ */\r
+__declspec(dllexport)\r
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms);\r
+\r
+/**\r
+ * rdma_create_qp - Allocate a QP.\r
+ * @id: RDMA identifier.\r
+ * @pd: protection domain for the QP.\r
+ * @qp_init_attr: initial QP attributes.\r
+ * Description:\r
+ *  Allocate a QP associated with the specified rdma_cm_id and transition it\r
+ *  for sending and receiving.\r
+ * Notes:\r
+ *   The rdma_cm_id must be bound to a local RDMA device before calling this\r
+ *   function, and the protection domain must be for that same device.\r
+ *   QPs allocated to an rdma_cm_id are automatically transitioned by the\r
+ *   librdmacm through their states.  After being allocated, the QP will be\r
+ *   ready to handle posting of receives.  If the QP is unconnected, it will\r
+ *   be ready to post sends.\r
+ * See also:\r
+ *   rdma_bind_addr, rdma_resolve_addr, rdma_destroy_qp, ibv_create_qp,\r
+ *   ibv_modify_qp\r
+ */\r
+__declspec(dllexport)\r
+int rdma_create_qp(struct rdma_cm_id *id, struct ibv_pd *pd,\r
+                                  struct ibv_qp_init_attr *qp_init_attr);\r
+\r
+/**\r
+ * rdma_destroy_qp - Deallocate a QP.\r
+ * @id: RDMA identifier.\r
+ * Description:\r
+ *   Destroy a QP allocated on the rdma_cm_id.\r
+ * Notes:\r
+ *   Users must destroy any QP associated with an rdma_cm_id before\r
+ *   destroying the ID.\r
+ * See also:\r
+ *   rdma_create_qp, rdma_destroy_id, ibv_destroy_qp\r
+ */\r
+__declspec(dllexport)\r
+void rdma_destroy_qp(struct rdma_cm_id *id);\r
+\r
+/**\r
+ * rdma_connect - Initiate an active connection request.\r
+ * @id: RDMA identifier.\r
+ * @conn_param: connection parameters.\r
+ * Description:\r
+ *   For a connected rdma_cm_id, this call initiates a connection request\r
+ *   to a remote destination.  For an unconnected rdma_cm_id, it initiates\r
+ *   a lookup of the remote QP providing the datagram service.\r
+ * Notes:\r
+ *   Users must have resolved a route to the destination address\r
+ *   by having called rdma_resolve_route before calling this routine.\r
+ * See also:\r
+ *   rdma_resolve_route, rdma_disconnect, rdma_listen, rdma_get_cm_event\r
+ */\r
+__declspec(dllexport)\r
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);\r
+\r
+/**\r
+ * rdma_listen - Listen for incoming connection requests.\r
+ * @id: RDMA identifier.\r
+ * @backlog: backlog of incoming connection requests.\r
+ * Description:\r
+ *   Initiates a listen for incoming connection requests or datagram service\r
+ *   lookup.  The listen will be restricted to the locally bound source\r
+ *   address.\r
+ * Notes:\r
+ *   Users must have bound the rdma_cm_id to a local address by calling\r
+ *   rdma_bind_addr before calling this routine.  If the rdma_cm_id is\r
+ *   bound to a specific IP address, the listen will be restricted to that\r
+ *   address and the associated RDMA device.  If the rdma_cm_id is bound\r
+ *   to an RDMA port number only, the listen will occur across all RDMA\r
+ *   devices.\r
+ * See also:\r
+ *   rdma_bind_addr, rdma_connect, rdma_accept, rdma_reject, rdma_get_cm_event\r
+ */\r
+__declspec(dllexport)\r
+int rdma_listen(struct rdma_cm_id *id, int backlog);\r
+\r
+/**\r
+ * rdma_accept - Called to accept a connection request.\r
+ * @id: Connection identifier associated with the request.\r
+ * @conn_param: Information needed to establish the connection.\r
+ * Description:\r
+ *   Called from the listening side to accept a connection or datagram\r
+ *   service lookup request.\r
+ * Notes:\r
+ *   Unlike the socket accept routine, rdma_accept is not called on a\r
+ *   listening rdma_cm_id.  Instead, after calling rdma_listen, the user\r
+ *   waits for a connection request event to occur.  Connection request\r
+ *   events give the user a newly created rdma_cm_id, similar to a new\r
+ *   socket, but the rdma_cm_id is bound to a specific RDMA device.\r
+ *   rdma_accept is called on the new rdma_cm_id.\r
+ * See also:\r
+ *   rdma_listen, rdma_reject, rdma_get_cm_event\r
+ */\r
+__declspec(dllexport)\r
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param);\r
+\r
+/**\r
+ * rdma_reject - Called to reject a connection request.\r
+ * @id: Connection identifier associated with the request.\r
+ * @private_data: Optional private data to send with the reject message.\r
+ * @private_data_len: Size of the private_data to send, in bytes.\r
+ * Description:\r
+ *   Called from the listening side to reject a connection or datagram\r
+ *   service lookup request.\r
+ * Notes:\r
+ *   After receiving a connection request event, a user may call rdma_reject\r
+ *   to reject the request.  If the underlying RDMA transport supports\r
+ *   private data in the reject message, the specified data will be passed to\r
+ *   the remote side.\r
+ * See also:\r
+ *   rdma_listen, rdma_accept, rdma_get_cm_event\r
+ */\r
+__declspec(dllexport)\r
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,\r
+                               uint8_t private_data_len);\r
+\r
+/**\r
+ * rdma_notify - Notifies the librdmacm of an asynchronous event.\r
+ * @id: RDMA identifier.\r
+ * @event: Asynchronous event.\r
+ * Description:\r
+ *   Used to notify the librdmacm of asynchronous events that have occurred\r
+ *   on a QP associated with the rdma_cm_id.\r
+ * Notes:\r
+ *   Asynchronous events that occur on a QP are reported through the user's\r
+ *   device event handler.  This routine is used to notify the librdmacm of\r
+ *   communication events.  In most cases, use of this routine is not\r
+ *   necessary, however if connection establishment is done out of band\r
+ *   (such as done through Infiniband), it's possible to receive data on a\r
+ *   QP that is not yet considered connected.  This routine forces the\r
+ *   connection into an established state in this case in order to handle\r
+ *   the rare situation where the connection never forms on its own.\r
+ *   Events that should be reported to the CM are: IB_EVENT_COMM_EST.\r
+ * See also:\r
+ *   rdma_connect, rdma_accept, rdma_listen\r
+ */\r
+__declspec(dllexport)\r
+int rdma_notify(struct rdma_cm_id *id, enum ibv_event_type event);\r
+\r
+/**\r
+ * rdma_disconnect - This function disconnects a connection.\r
+ * @id: RDMA identifier.\r
+ * Description:\r
+ *   Disconnects a connection and transitions any associated QP to the\r
+ *   error state.\r
+ * See also:\r
+ *   rdma_connect, rdma_listen, rdma_accept\r
+ */\r
+__declspec(dllexport)\r
+int rdma_disconnect(struct rdma_cm_id *id);\r
+\r
+/**\r
+ * rdma_join_multicast - Joins a multicast group.\r
+ * @id: Communication identifier associated with the request.\r
+ * @addr: Multicast address identifying the group to join.\r
+ * @context: User-defined context associated with the join request.\r
+ * Description:\r
+ *   Joins a multicast group and attaches an associated QP to the group.\r
+ * Notes:\r
+ *   Before joining a multicast group, the rdma_cm_id must be bound to\r
+ *   an RDMA device by calling rdma_bind_addr or rdma_resolve_addr.  Use of\r
+ *   rdma_resolve_addr requires the local routing tables to resolve the\r
+ *   multicast address to an RDMA device.  The user must call\r
+ *   rdma_leave_multicast to leave the multicast group and release any\r
+ *   multicast resources.  The context is returned to the user through\r
+ *   the private_data field in the rdma_cm_event.\r
+ * See also:\r
+ *   rdma_leave_multicast, rdma_bind_addr, rdma_resolve_addr, rdma_create_qp\r
+ */\r
+__declspec(dllexport)\r
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,\r
+                                               void *context);\r
+\r
+/**\r
+ * rdma_leave_multicast - Leaves a multicast group.\r
+ * @id: Communication identifier associated with the request.\r
+ * @addr: Multicast address identifying the group to leave.\r
+ * Description:\r
+ *   Leaves a multicast group and detaches an associated QP from the group.\r
+ * Notes:\r
+ *   Calling this function before a group has been fully joined results in\r
+ *   canceling the join operation.  Users should be aware that messages\r
+ *   received from the multicast group may stilled be queued for\r
+ *   completion processing immediately after leaving a multicast group.\r
+ *   Destroying an rdma_cm_id will automatically leave all multicast groups.\r
+ * See also:\r
+ *   rdma_join_multicast, rdma_destroy_qp\r
+ */\r
+__declspec(dllexport)\r
+int rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr);\r
+\r
+/**\r
+ * rdma_get_cm_event - Retrieves the next pending communication event.\r
+ * @channel: Event channel to check for events.\r
+ * @event: Allocated information about the next communication event.\r
+ * Description:\r
+ *   Retrieves a communication event.  If no events are pending, by default,\r
+ *   the call will block until an event is received.\r
+ * Notes:\r
+ *   The default synchronous behavior of this routine can be changed by\r
+ *   modifying the file descriptor associated with the given channel.  All\r
+ *   events that are reported must be acknowledged by calling rdma_ack_cm_event.\r
+ *   Destruction of an rdma_cm_id will block until related events have been\r
+ *   acknowledged.\r
+ * See also:\r
+ *   rdma_ack_cm_event, rdma_create_event_channel, rdma_event_str\r
+ */\r
+__declspec(dllexport)\r
+int rdma_get_cm_event(struct rdma_event_channel *channel,\r
+                                         struct rdma_cm_event **event);\r
+\r
+/**\r
+ * rdma_ack_cm_event - Free a communication event.\r
+ * @event: Event to be released.\r
+ * Description:\r
+ *   All events which are allocated by rdma_get_cm_event must be released,\r
+ *   there should be a one-to-one correspondence between successful gets\r
+ *   and acks.\r
+ * See also:\r
+ *   rdma_get_cm_event, rdma_destroy_id\r
+ */\r
+__declspec(dllexport)\r
+int rdma_ack_cm_event(struct rdma_cm_event *event);\r
+\r
+static uint16_t rdma_get_src_port(struct rdma_cm_id *id)\r
+{\r
+       return  id->route.addr.src_addr.sa_family == PF_INET6 ?\r
+               ((struct sockaddr_in6 *) &id->route.addr.src_addr)->sin6_port :\r
+               ((struct sockaddr_in *) &id->route.addr.src_addr)->sin_port;\r
+}\r
+\r
+static uint16_t rdma_get_dst_port(struct rdma_cm_id *id)\r
+{\r
+       return  id->route.addr.dst_addr.sa_family == PF_INET6 ?\r
+               ((struct sockaddr_in6 *) &id->route.addr.dst_addr)->sin6_port :\r
+               ((struct sockaddr_in *) &id->route.addr.dst_addr)->sin_port;\r
+}\r
+\r
+static struct sockaddr *rdma_get_local_addr(struct rdma_cm_id *id)\r
+{\r
+       return &id->route.addr.src_addr;\r
+}\r
+\r
+static struct sockaddr *rdma_get_peer_addr(struct rdma_cm_id *id)\r
+{\r
+       return &id->route.addr.dst_addr;\r
+}\r
+\r
+/**\r
+ * rdma_get_devices - Get list of RDMA devices currently available.\r
+ * @num_devices: If non-NULL, set to the number of devices returned.\r
+ * Description:\r
+ *   Return a NULL-terminated array of opened RDMA devices.  Callers can use\r
+ *   this routine to allocate resources on specific RDMA devices that will be\r
+ *   shared across multiple rdma_cm_id's.\r
+ * Notes:\r
+ *   The returned array must be released by calling rdma_free_devices.  Devices\r
+ *   remain opened while the librdmacm is loaded.\r
+ * See also:\r
+ *   rdma_free_devices\r
+ */\r
+__declspec(dllexport)\r
+struct ibv_context **rdma_get_devices(int *num_devices);\r
+\r
+/**\r
+ * rdma_free_devices - Frees the list of devices returned by rdma_get_devices.\r
+ * @list: List of devices returned from rdma_get_devices.\r
+ * Description:\r
+ *   Frees the device array returned by rdma_get_devices.\r
+ * See also:\r
+ *   rdma_get_devices\r
+ */\r
+__declspec(dllexport)\r
+void rdma_free_devices(struct ibv_context **list);\r
+\r
+/**\r
+ * rdma_event_str - Returns a string representation of an rdma cm event.\r
+ * @event: Asynchronous event.\r
+ * Description:\r
+ *   Returns a string representation of an asynchronous event.\r
+ * See also:\r
+ *   rdma_get_cm_event\r
+ */\r
+__declspec(dllexport)\r
+const char *rdma_event_str(enum rdma_cm_event_type event);\r
+\r
+/* Option levels */\r
+enum\r
+{\r
+       RDMA_OPTION_ID          = 0\r
+};\r
+\r
+/* Option details */\r
+enum\r
+{\r
+       RDMA_OPTION_ID_TOS      = 0     /* uint8_t: RFC 2474 */\r
+};\r
+\r
+/**\r
+ * rdma_set_option - Set options for an rdma_cm_id.\r
+ * @id: Communication identifier to set option for.\r
+ * @level: Protocol level of the option to set.\r
+ * @optname: Name of the option to set.\r
+ * @optval: Reference to the option data.\r
+ * @optlen: The size of the %optval buffer.\r
+ */\r
+__declspec(dllexport)\r
+int rdma_set_option(struct rdma_cm_id *id, int level, int optname,\r
+                                       void *optval, size_t optlen);\r
+\r
+/**\r
+ * rdma_migrate_id - Move an rdma_cm_id to a new event channel.\r
+ * @id: Communication identifier to migrate.\r
+ * @channel: New event channel for rdma_cm_id events.\r
+ */\r
+__declspec(dllexport)\r
+int rdma_migrate_id(struct rdma_cm_id *id, struct rdma_event_channel *channel);\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif /* RDMA_CMA_H */\r
diff --git a/branches/winverbs/ulp/librdmacm/src/Sources b/branches/winverbs/ulp/librdmacm/src/Sources
new file mode 100644 (file)
index 0000000..3a77169
--- /dev/null
@@ -0,0 +1,40 @@
+!if $(FREEBUILD)\r
+TARGETNAME = librdmacm\r
+!else\r
+TARGETNAME = librdmacmd\r
+!endif\r
+\r
+TARGETPATH = ..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = DYNLINK\r
+\r
+!if $(_NT_TOOLS_VERSION) == 0x700\r
+DLLDEF = $O\cma_exports.def\r
+!else\r
+DLLDEF = $(OBJ_PATH)\$O\cma_exports.def\r
+!endif\r
+\r
+DLLENTRY = DllMain\r
+USE_MSVCRT = 1\r
+\r
+SOURCES =                      \\r
+       cma.rc                  \\r
+       cma_main.cpp    \\r
+       cma.cpp\r
+\r
+INCLUDES = ..\include;..\..\..\inc;..\..\..\inc\user;..\..\libibverbs\include\r
+\r
+USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_CMA_SYMBOLS\r
+\r
+TARGETLIBS = \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\uuid.lib                \\r
+       $(SDK_LIB_PATH)\ws2_32.lib              \\r
+       $(SDK_LIB_PATH)\iphlpapi.lib    \\r
+       $(TARGETPATH)\*\ibat.lib                \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\libibverbs.lib  \\r
+       $(TARGETPATH)\*\winverbs.lib\r
+!else\r
+       $(TARGETPATH)\*\libibverbsd.lib \\r
+       $(TARGETPATH)\*\winverbsd.lib\r
+!endif\r
diff --git a/branches/winverbs/ulp/librdmacm/src/cma.cpp b/branches/winverbs/ulp/librdmacm/src/cma.cpp
new file mode 100644 (file)
index 0000000..965c292
--- /dev/null
@@ -0,0 +1,1077 @@
+/*\r
+ * Copyright (c) 2005-2009 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 AWV\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 <windows.h>\r
+#include <winsock2.h>\r
+#include <stdio.h>\r
+#include <iphlpapi.h>\r
+\r
+#include <rdma/rdma_cma.h>\r
+#include <infiniband/verbs.h>\r
+#include <iba/ibat.h>\r
+#include "cma.h"\r
+\r
+IWVProvider *prov;\r
+__declspec(dllexport)\r
+IWVProvider *ibv_get_winverbs(void);\r
+\r
+enum cma_state\r
+{\r
+       cma_idle,\r
+       cma_listening,\r
+       cma_get_request,\r
+       cma_addr_resolve,\r
+       cma_route_resolve,\r
+       cma_passive_connect,\r
+       cma_active_connect,\r
+       cma_active_accept,\r
+       cma_accepting,\r
+       cma_connected,\r
+       cma_active_disconnect,\r
+       cma_passive_disconnect,\r
+       cma_disconnected\r
+};\r
+\r
+#define CMA_DEFAULT_BACKLOG            16\r
+\r
+struct cma_id_private\r
+{\r
+       struct rdma_cm_id                       id;\r
+       enum cma_state                          state;\r
+       int                                                     channel_index;\r
+       struct cma_device                       *cma_dev;\r
+       int                                                     backlog;\r
+       int                                                     index;\r
+       struct rdma_cm_id                       **req_list;\r
+};\r
+\r
+struct cma_event_channel\r
+{\r
+       struct rdma_event_channel       channel;\r
+       CRITICAL_SECTION                        lock;\r
+       struct cma_id_private           *id[MAXIMUM_WAIT_OBJECTS];\r
+       HANDLE                                          event[MAXIMUM_WAIT_OBJECTS];\r
+       int                                                     count;\r
+};\r
+\r
+struct cma_device\r
+{\r
+       struct ibv_context      *verbs;\r
+       uint64_t                        guid;\r
+       int                                     port_cnt;\r
+       uint8_t                         max_initiator_depth;\r
+       uint8_t                         max_responder_resources;\r
+};\r
+\r
+struct cma_event {\r
+       struct rdma_cm_event    event;\r
+       uint8_t                                 private_data[56];\r
+       struct cma_id_private   *id_priv;\r
+};\r
+\r
+static struct cma_device *cma_dev_array;\r
+static int cma_dev_cnt;\r
+\r
+static void ucma_cleanup(void)\r
+{\r
+       if (cma_dev_cnt > 0) {\r
+               while (cma_dev_cnt > 0) {\r
+                       ibv_close_device(cma_dev_array[--cma_dev_cnt].verbs);\r
+               }\r
+               delete cma_dev_array;\r
+               cma_dev_cnt = 0;\r
+       }\r
+       if (prov != NULL) {\r
+               prov->Release();\r
+               prov = NULL;\r
+       }\r
+}\r
+\r
+static int ucma_init(void)\r
+{\r
+       struct ibv_device **dev_list = NULL;\r
+       struct cma_device *cma_dev;\r
+       struct ibv_device_attr attr;\r
+       int i, ret;\r
+\r
+       EnterCriticalSection(&lock);\r
+       if (cma_dev_cnt > 0) {\r
+               goto out;\r
+       }\r
+\r
+       prov = ibv_get_winverbs();\r
+       if (prov == NULL) {\r
+               ret = -1;\r
+               goto err;\r
+       }\r
+\r
+       dev_list = ibv_get_device_list(&cma_dev_cnt);\r
+       if (dev_list == NULL) {\r
+               ret = -1;\r
+               goto err;\r
+       }\r
+\r
+       cma_dev_array = new struct cma_device[cma_dev_cnt];\r
+       if (cma_dev_array == NULL) {\r
+               ret = -1;\r
+               goto err;\r
+       }\r
+\r
+       for (i = 0; dev_list[i]; ++i) {\r
+               cma_dev = &cma_dev_array[i];\r
+\r
+               cma_dev->guid = ibv_get_device_guid(dev_list[i]);\r
+               cma_dev->verbs = ibv_open_device(dev_list[i]);\r
+               if (cma_dev->verbs == NULL) {\r
+                       ret = -1;\r
+                       goto err;\r
+               }\r
+\r
+               ret = ibv_query_device(cma_dev->verbs, &attr);\r
+               if (ret) {\r
+                       goto err;\r
+               }\r
+\r
+               cma_dev->port_cnt = attr.phys_port_cnt;\r
+               cma_dev->max_initiator_depth = (uint8_t) attr.max_qp_init_rd_atom;\r
+               cma_dev->max_responder_resources = (uint8_t) attr.max_qp_rd_atom;\r
+       }\r
+       ibv_free_device_list(dev_list);\r
+out:\r
+       LeaveCriticalSection(&lock);\r
+       return 0;\r
+\r
+err:\r
+       ucma_cleanup();\r
+       LeaveCriticalSection(&lock);\r
+       if (dev_list) {\r
+               ibv_free_device_list(dev_list);\r
+       }\r
+       return ret;\r
+}\r
+\r
+__declspec(dllexport)\r
+struct ibv_context **rdma_get_devices(int *num_devices)\r
+{\r
+       struct ibv_context **devs = NULL;\r
+       int i;\r
+\r
+       if (!cma_dev_cnt && ucma_init()) {\r
+               goto out;\r
+       }\r
+\r
+       devs = new struct ibv_context *[cma_dev_cnt + 1];\r
+       if (devs == NULL) {\r
+               goto out;\r
+       }\r
+\r
+       for (i = 0; i < cma_dev_cnt; i++) {\r
+               devs[i] = cma_dev_array[i].verbs;\r
+       }\r
+       devs[i] = NULL;\r
+out:\r
+       if (num_devices != NULL) {\r
+               *num_devices = devs ? cma_dev_cnt : 0;\r
+       }\r
+       return devs;\r
+}\r
+\r
+__declspec(dllexport)\r
+void rdma_free_devices(struct ibv_context **list)\r
+{\r
+       delete list;\r
+}\r
+\r
+__declspec(dllexport)\r
+struct rdma_event_channel *rdma_create_event_channel(void)\r
+{\r
+       struct cma_event_channel *chan;\r
+\r
+       if (!cma_dev_cnt && ucma_init()) {\r
+               return NULL;\r
+       }\r
+\r
+       chan = new struct cma_event_channel;\r
+       if (chan == NULL) {\r
+               return NULL;\r
+       }\r
+\r
+       InitializeCriticalSection(&chan->lock);\r
+       chan->count = 0;\r
+       chan->channel.timeout = INFINITE;\r
+\r
+       return &chan->channel;\r
+}\r
+\r
+__declspec(dllexport)\r
+void rdma_destroy_event_channel(struct rdma_event_channel *channel)\r
+{\r
+       struct cma_event_channel *chan;\r
+\r
+       chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
+       DeleteCriticalSection(&chan->lock);     \r
+       delete chan;\r
+}\r
+\r
+static int cma_event_channel_insert_id(struct rdma_event_channel *channel,\r
+                                                                          struct cma_id_private *id_priv)\r
+{\r
+       struct cma_event_channel *chan;\r
+       int ret = 0;\r
+\r
+       chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
+\r
+       EnterCriticalSection(&chan->lock);\r
+       if (chan->count == MAXIMUM_WAIT_OBJECTS) {\r
+               ret = -1;\r
+               goto out;\r
+       }\r
+\r
+       chan->id[chan->count] = id_priv;\r
+       chan->event[chan->count] = id_priv->id.overlap.hEvent;\r
+       id_priv->channel_index = chan->count++;\r
+out:\r
+       LeaveCriticalSection(&chan->lock);\r
+       return ret;\r
+}\r
+\r
+/*\r
+ * TODO: we cannot call cma_event_channel_remove_id() while another\r
+ * thread is calling rdma_get_event().  If this is needed, then we\r
+ * need to halt the rdma_get_event() thread, modify the event list,\r
+ * then restart the rdma_get_event() thread.\r
+ */\r
+static void cma_event_channel_remove_id(struct rdma_event_channel *channel,\r
+                                                                               struct cma_id_private *id_priv)\r
+{\r
+       struct cma_event_channel *chan;\r
+\r
+       chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
+\r
+       EnterCriticalSection(&chan->lock);\r
+       chan->count--;\r
+       chan->id[id_priv->channel_index] = chan->id[chan->count];\r
+       chan->event[id_priv->channel_index] = chan->event[chan->count];\r
+       chan->id[id_priv->channel_index]->channel_index = id_priv->channel_index;\r
+       LeaveCriticalSection(&chan->lock);\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_create_id(struct rdma_event_channel *channel,\r
+                                  struct rdma_cm_id **id, void *context,\r
+                                  enum rdma_port_space ps)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       HRESULT hr;\r
+\r
+       hr = cma_dev_cnt ? 0 : ucma_init();\r
+       if (hr) {\r
+               return hr;\r
+       }\r
+\r
+       id_priv = new struct cma_id_private;\r
+       if (id_priv == NULL) {\r
+               return NULL;\r
+       }\r
+\r
+       RtlZeroMemory(id_priv, sizeof(struct cma_id_private));\r
+       id_priv->id.overlap.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
+       if (id_priv->id.overlap.hEvent == NULL) {\r
+               goto err1;\r
+       }\r
+\r
+       id_priv->id.context = context;\r
+       id_priv->id.channel = channel;\r
+       id_priv->id.ps = ps;\r
+\r
+       if (ps == RDMA_PS_TCP) {\r
+               hr = prov->CreateConnectEndpoint(&id_priv->id.ep.connect);\r
+       } else {\r
+               hr = prov->CreateDatagramEndpoint(&id_priv->id.ep.datagram);\r
+       }\r
+       if (FAILED(hr)) {\r
+               goto err2;\r
+       }\r
+\r
+       hr = cma_event_channel_insert_id(channel, id_priv);\r
+       if (FAILED(hr)) {\r
+               goto err3;\r
+       }\r
+\r
+       *id = &id_priv->id;\r
+       return 0;\r
+\r
+err3:\r
+       if (ps == RDMA_PS_TCP) {\r
+               id_priv->id.ep.connect->Release();\r
+       } else {\r
+               id_priv->id.ep.datagram->Release();\r
+       }\r
+err2:\r
+       CloseHandle(id_priv->id.overlap.hEvent);\r
+err1:\r
+       delete id_priv;\r
+       return -1;\r
+}\r
+\r
+static void ucma_destroy_listen(struct cma_id_private *id_priv)\r
+{\r
+       while (--id_priv->backlog >= 0) {\r
+               if (id_priv->req_list[id_priv->backlog] != NULL) {\r
+                       rdma_destroy_id(id_priv->req_list[id_priv->backlog]);\r
+               }\r
+       }\r
+\r
+       delete id_priv->req_list;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_destroy_id(struct rdma_cm_id *id)\r
+{\r
+       struct cma_id_private   *id_priv;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       if (id->ps == RDMA_PS_TCP) {\r
+               id->ep.connect->CancelOverlappedRequests();\r
+       } else {\r
+               id->ep.datagram->CancelOverlappedRequests();\r
+       }\r
+\r
+       cma_event_channel_remove_id(id->channel, id_priv);\r
+\r
+       if (id_priv->backlog > 0) {\r
+               ucma_destroy_listen(id_priv);\r
+       }\r
+\r
+       if (id_priv->id.ps == RDMA_PS_TCP) {\r
+               id_priv->id.ep.connect->Release();\r
+       } else {\r
+               id_priv->id.ep.datagram->Release();\r
+       }\r
+\r
+       delete id_priv;\r
+       return 0;\r
+}\r
+\r
+static int ucma_addrlen(struct sockaddr *addr)\r
+{\r
+       if (addr->sa_family == PF_INET) {\r
+               return sizeof(struct sockaddr_in);\r
+       } else {\r
+               return sizeof(struct sockaddr_in6);\r
+       }\r
+}\r
+\r
+static int ucma_get_device(struct cma_id_private *id_priv, uint64_t guid)\r
+{\r
+       struct cma_device *cma_dev;\r
+       int i;\r
+\r
+       for (i = 0; i < cma_dev_cnt; i++) {\r
+               cma_dev = &cma_dev_array[i];\r
+               if (cma_dev->guid == guid) {\r
+                       id_priv->cma_dev = cma_dev;\r
+                       id_priv->id.verbs = cma_dev->verbs;\r
+                       return 0;\r
+               }\r
+       }\r
+       return -1;\r
+}\r
+\r
+static int ucma_query_connect(struct rdma_cm_id *id, struct rdma_conn_param *param)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       WV_CONNECT_ATTRIBUTES attr;\r
+       HRESULT hr;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       hr = id->ep.connect->Query(&attr);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       RtlCopyMemory(&id->route.addr.src_addr, &attr.LocalAddress,\r
+                                 sizeof attr.LocalAddress);\r
+       RtlCopyMemory(&id->route.addr.dst_addr, &attr.PeerAddress,\r
+                                 sizeof attr.PeerAddress);\r
+\r
+       if (param != NULL) {\r
+               RtlCopyMemory((void *) param->private_data, attr.Param.Data,\r
+                                         attr.Param.DataLength);\r
+               param->private_data_len = (uint8_t) attr.Param.DataLength;\r
+               param->responder_resources = (uint8_t) attr.Param.ResponderResources;\r
+               param->initiator_depth = (uint8_t) attr.Param.InitiatorDepth;\r
+               param->flow_control = 1;\r
+               param->retry_count = attr.Param.RetryCount;\r
+               param->rnr_retry_count = attr.Param.RnrRetryCount;\r
+       }\r
+\r
+       if (id_priv->cma_dev == NULL && attr.Device.DeviceGuid != 0) {\r
+               hr = ucma_get_device(id_priv, attr.Device.DeviceGuid);\r
+               if (FAILED(hr)) {\r
+                       return hr;\r
+               }\r
+\r
+               id->route.addr.addr.ibaddr.pkey = attr.Device.Pkey;\r
+               id_priv->id.port_num = attr.Device.PortNumber;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int ucma_query_datagram(struct rdma_cm_id *id, struct rdma_ud_param *param)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       WV_DATAGRAM_ATTRIBUTES attr;\r
+       HRESULT hr;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       hr = id->ep.datagram->Query(&attr);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       RtlCopyMemory(&id->route.addr.src_addr, &attr.LocalAddress,\r
+                                 sizeof attr.LocalAddress);\r
+       RtlCopyMemory(&id->route.addr.dst_addr, &attr.PeerAddress,\r
+                                 sizeof attr.PeerAddress);\r
+\r
+       if (param != NULL) {\r
+               RtlCopyMemory((void *) param->private_data, attr.Param.Data,\r
+                                         attr.Param.DataLength);\r
+               param->private_data_len = (uint8_t) attr.Param.DataLength;\r
+               // ucma_convert_av(&attr.Param.AddressVector, param->ah_attr)\r
+               param->qp_num = attr.Param.Qpn;\r
+               param->qkey = attr.Param.Qkey;\r
+       }\r
+\r
+       if (id_priv->cma_dev == NULL && attr.Device.DeviceGuid != 0) {\r
+               hr = ucma_get_device(id_priv, attr.Device.DeviceGuid);\r
+               if (FAILED(hr))\r
+                       return hr;\r
+               id->route.addr.addr.ibaddr.pkey = attr.Device.Pkey;\r
+               id_priv->id.port_num = attr.Device.PortNumber;\r
+       }\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)\r
+{\r
+       HRESULT hr;\r
+\r
+       if (id->ps == RDMA_PS_TCP) {\r
+               hr = id->ep.connect->BindAddress(addr);\r
+               if (SUCCEEDED(hr)) {\r
+                       hr = ucma_query_connect(id, NULL);\r
+               }\r
+       } else {\r
+               hr = id->ep.datagram->BindAddress(addr);\r
+               if (SUCCEEDED(hr)) {\r
+                       hr = ucma_query_datagram(id, NULL);\r
+               }\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_resolve_addr(struct rdma_cm_id *id, struct sockaddr *src_addr,\r
+                                         struct sockaddr *dst_addr, int timeout_ms)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       WV_SOCKADDR addr;\r
+       SOCKET s;\r
+       DWORD size;\r
+       HRESULT hr;\r
+\r
+       if (src_addr == NULL) {\r
+               if (id->ps == RDMA_PS_TCP) {\r
+                       s = socket(dst_addr->sa_family, SOCK_STREAM, IPPROTO_TCP);\r
+               } else {\r
+                       s = socket(dst_addr->sa_family, SOCK_DGRAM, IPPROTO_UDP);\r
+               }\r
+               if (s == INVALID_SOCKET) {\r
+                       return WSAGetLastError();\r
+               }\r
+\r
+               hr = WSAIoctl(s, SIO_ROUTING_INTERFACE_QUERY, dst_addr, ucma_addrlen(dst_addr),\r
+                                         &addr, sizeof addr, &size, NULL, NULL);\r
+               closesocket(s);\r
+               if (FAILED(hr)) {\r
+                       return WSAGetLastError();\r
+               }\r
+               src_addr = &addr.Sa;\r
+       }\r
+\r
+       hr = rdma_bind_addr(id, src_addr);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       RtlCopyMemory(&id->route.addr.dst_addr, dst_addr, ucma_addrlen(dst_addr));\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       id_priv->state = cma_addr_resolve;\r
+       SetEvent(id->overlap.hEvent);\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       IBAT_PATH_BLOB path;\r
+       HRESULT hr;\r
+\r
+       hr = IBAT::Resolve(&id->route.addr.src_addr, &id->route.addr.dst_addr, &path);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       hr = (id->ps == RDMA_PS_TCP) ?\r
+                id->ep.connect->Modify(WV_EP_OPTION_ROUTE, &path, sizeof path) :\r
+                id->ep.datagram->Modify(WV_EP_OPTION_ROUTE, &path, sizeof path);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       id_priv->state = cma_route_resolve;\r
+       SetEvent(id->overlap.hEvent);\r
+       return 0;\r
+}\r
+\r
+static int ucma_modify_qp_init(struct cma_id_private *id_priv, struct ibv_qp *qp)\r
+{\r
+       struct ibv_qp_attr qp_attr;\r
+       DWORD index;\r
+       HRESULT hr;\r
+\r
+       RtlZeroMemory(&qp_attr, sizeof qp_attr);\r
+       qp_attr.qp_state = IBV_QPS_INIT;\r
+       qp_attr.port_num = id_priv->id.port_num;\r
+       hr = qp->context->cmd_if->FindPkey(id_priv->id.port_num,\r
+                                                                          id_priv->id.route.addr.addr.ibaddr.pkey,\r
+                                                                          &index);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       qp_attr.pkey_index = (uint16_t) index;\r
+       return ibv_modify_qp(qp, &qp_attr, (enum ibv_qp_attr_mask)\r
+                                                (IBV_QP_STATE | IBV_QP_PKEY_INDEX | IBV_QP_PORT));\r
+}\r
+\r
+static int ucma_init_ud_qp(struct cma_id_private *id_priv, struct ibv_qp *qp)\r
+{\r
+       struct ibv_qp_attr qp_attr;\r
+       int qp_attr_mask, ret;\r
+\r
+       ret = ucma_modify_qp_init(id_priv, qp);\r
+       if (ret) {\r
+               return ret;\r
+       }\r
+\r
+       qp_attr.qp_state = IBV_QPS_RTR;\r
+       ret = ibv_modify_qp(qp, &qp_attr, IBV_QP_STATE);\r
+       if (ret) {\r
+               return ret;\r
+       }\r
+\r
+       qp_attr.qp_state = IBV_QPS_RTS;\r
+       qp_attr.sq_psn = 0;\r
+       return ibv_modify_qp(qp, &qp_attr, (enum ibv_qp_attr_mask)\r
+                                                (IBV_QP_STATE | IBV_QP_SQ_PSN));\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_create_qp(struct rdma_cm_id *id, struct ibv_pd *pd,\r
+                                  struct ibv_qp_init_attr *qp_init_attr)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       struct ibv_qp *qp;\r
+       int ret;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       if (id->verbs != pd->context) {\r
+               return -1;\r
+       }\r
+\r
+       qp = ibv_create_qp(pd, qp_init_attr);\r
+       if (!qp) {\r
+               return -1;\r
+       }\r
+\r
+       if (id->ps == RDMA_PS_TCP) {\r
+               ret = ucma_modify_qp_init(id_priv, qp);\r
+       } else {\r
+               ret = ucma_init_ud_qp(id_priv, qp);\r
+       }\r
+       if (ret) {\r
+               goto err;\r
+       }\r
+\r
+       id->qp = qp;\r
+       return 0;\r
+err:\r
+       ibv_destroy_qp(qp);\r
+       return ret;\r
+}\r
+\r
+__declspec(dllexport)\r
+void rdma_destroy_qp(struct rdma_cm_id *id)\r
+{\r
+       ibv_destroy_qp(id->qp);\r
+}\r
+\r
+static int ucma_valid_param(struct cma_id_private *id_priv,\r
+                                                       struct rdma_conn_param *conn_param)\r
+{\r
+       if (id_priv->id.ps != RDMA_PS_TCP) {\r
+               return 0;\r
+       }\r
+\r
+       if ((conn_param->responder_resources > id_priv->cma_dev->max_responder_resources) ||\r
+               (conn_param->initiator_depth > id_priv->cma_dev->max_initiator_depth)) {\r
+               return -1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       WV_CONNECT_PARAM attr;\r
+       HRESULT hr;\r
+       \r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       hr = ucma_valid_param(id_priv, conn_param);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       RtlZeroMemory(&attr, sizeof attr);\r
+       attr.ResponderResources = conn_param->responder_resources;\r
+       attr.InitiatorDepth = conn_param->initiator_depth;\r
+       attr.RetryCount = conn_param->retry_count;\r
+       attr.RnrRetryCount = conn_param->rnr_retry_count;\r
+       if ((attr.DataLength = conn_param->private_data_len)) {\r
+               RtlCopyMemory(attr.Data, conn_param->private_data, attr.DataLength);\r
+       }\r
+\r
+       id_priv->state = cma_active_connect;\r
+       hr = id->ep.connect->Connect(id->qp->conn_handle, &id->route.addr.dst_addr,\r
+                                                                &attr, &id->overlap);\r
+       if (FAILED(hr) && hr != WV_IO_PENDING) {\r
+               id_priv->state = cma_route_resolve;\r
+               return hr;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+static int ucma_get_request(struct cma_id_private *listen, int index)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       HRESULT hr;\r
+\r
+       hr = rdma_create_id(listen->id.channel, &listen->req_list[index],\r
+                                               listen, listen->id.ps);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       id_priv = CONTAINING_RECORD(listen->req_list[index], struct cma_id_private, id);\r
+       id_priv->index = index;\r
+       id_priv->state = cma_get_request;\r
+\r
+       if (listen->id.ps == RDMA_PS_TCP) {\r
+               hr = listen->id.ep.connect->GetRequest(id_priv->id.ep.connect,\r
+                                                                                          &id_priv->id.overlap);\r
+       } else {\r
+               hr = listen->id.ep.datagram->GetRequest(id_priv->id.ep.datagram,\r
+                                                                                               &id_priv->id.overlap);\r
+       }\r
+\r
+       return (FAILED(hr) && hr != WV_IO_PENDING) ? hr : 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_listen(struct rdma_cm_id *id, int backlog)\r
+{\r
+       struct cma_id_private *id_priv, *req_id;\r
+       HRESULT hr;\r
+       int i;\r
+\r
+       if (backlog <= 0 || backlog > CMA_DEFAULT_BACKLOG) {\r
+               backlog = CMA_DEFAULT_BACKLOG;\r
+       }\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       id_priv->req_list = new struct rdma_cm_id*[backlog];\r
+       if (id_priv->req_list == NULL) {\r
+               return -1;\r
+       }\r
+\r
+       RtlZeroMemory(id_priv->req_list, sizeof(struct rdma_cm_id *) * backlog);\r
+       id_priv->backlog = backlog;\r
+\r
+       id_priv->state = cma_listening;\r
+       hr = (id->ps == RDMA_PS_TCP) ?\r
+                id->ep.connect->Listen(backlog) : id->ep.datagram->Listen(backlog);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       for (i = 0; i < backlog; i++) {\r
+               hr = ucma_get_request(id_priv, i);\r
+               if (FAILED(hr)) {\r
+                       return hr;\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       WV_CONNECT_PARAM attr;\r
+       HRESULT hr;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       hr = ucma_valid_param(id_priv, conn_param);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       RtlZeroMemory(&attr, sizeof attr);\r
+       attr.ResponderResources = conn_param->responder_resources;\r
+       attr.InitiatorDepth = conn_param->initiator_depth;\r
+       attr.RetryCount = conn_param->retry_count;\r
+       attr.RnrRetryCount = conn_param->rnr_retry_count;\r
+       if ((attr.DataLength = conn_param->private_data_len)) {\r
+               RtlCopyMemory(attr.Data, conn_param->private_data, attr.DataLength);\r
+       }\r
+\r
+       id_priv->state = cma_accepting;\r
+       hr = id->ep.connect->Accept(id->qp->conn_handle, &attr, &id->overlap);\r
+       if (FAILED(hr) && hr != WV_IO_PENDING) {\r
+               id_priv->state = cma_disconnected;\r
+               return hr;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_reject(struct rdma_cm_id *id, const void *private_data,\r
+                               uint8_t private_data_len)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       HRESULT hr;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       id_priv->state = cma_disconnected;\r
+       hr = id->ep.connect->Reject(private_data, private_data_len);\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_notify(struct rdma_cm_id *id, enum ibv_event_type event)\r
+{\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_disconnect(struct rdma_cm_id *id)\r
+{\r
+       struct cma_id_private *id_priv;\r
+       HRESULT hr;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       if (id_priv->state == cma_connected) {\r
+               id_priv->state = cma_active_disconnect;\r
+       } else {\r
+               id_priv->state = cma_disconnected;\r
+       }\r
+       hr = id->ep.connect->Disconnect();\r
+       if (FAILED(hr)) {\r
+               return hr;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_ack_cm_event(struct rdma_cm_event *event)\r
+{\r
+       struct cma_event *evt;\r
+\r
+       evt = CONTAINING_RECORD(event, struct cma_event, event);\r
+       delete evt;\r
+       return 0;\r
+}\r
+\r
+static int ucma_process_conn_req(struct cma_event *event)\r
+{\r
+       struct cma_id_private *listen;\r
+       HRESULT hr = 0;\r
+\r
+       listen = (struct cma_id_private *) event->id_priv->id.context;\r
+\r
+       if (SUCCEEDED(event->event.status)) {\r
+               event->event.status = ucma_query_connect(&event->id_priv->id,\r
+                                                                                                &event->event.param.conn);\r
+       }\r
+\r
+       if (SUCCEEDED(event->event.status)) {\r
+               event->event.event = RDMA_CM_EVENT_CONNECT_REQUEST;\r
+               event->id_priv->state = cma_passive_connect;\r
+\r
+               listen->req_list[event->id_priv->index] = NULL;\r
+               ucma_get_request(listen, event->id_priv->index);\r
+       } else {\r
+               hr = listen->id.ep.connect->GetRequest(event->id_priv->id.ep.connect,\r
+                                                                                          &event->id_priv->id.overlap);\r
+               if (hr == WV_IO_PENDING) {\r
+                       hr = 0;\r
+               }\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+static int ucma_process_conn_resp(struct cma_event *event)\r
+{\r
+       struct rdma_cm_id       *id;\r
+       WV_CONNECT_PARAM        attr;\r
+       HRESULT                         hr;\r
+\r
+       if (FAILED(event->event.status)) {\r
+               goto err;\r
+       }\r
+\r
+       RtlZeroMemory(&attr, sizeof(attr));\r
+       event->id_priv->state = cma_accepting;\r
+\r
+       id = &event->id_priv->id;\r
+       hr = id->ep.connect->Accept(id->qp->conn_handle, &attr, &id->overlap);\r
+       if (FAILED(hr) && hr != WV_IO_PENDING) {\r
+               event->event.status = hr;\r
+               goto err;\r
+       }\r
+\r
+       return WV_IO_PENDING;\r
+\r
+err:\r
+       event->event.event = RDMA_CM_EVENT_CONNECT_ERROR;\r
+       event->id_priv->state = cma_disconnected;\r
+       return 0;\r
+}\r
+\r
+static void ucma_process_establish(struct cma_event *event)\r
+{\r
+       if (SUCCEEDED(event->event.status)) {\r
+               event->event.event = RDMA_CM_EVENT_ESTABLISHED;\r
+               event->id_priv->state = cma_connected;\r
+\r
+               event->id_priv->id.ep.connect->NotifyDisconnect(&event->id_priv->id.overlap);\r
+       } else {\r
+               event->event.event = RDMA_CM_EVENT_CONNECT_ERROR;\r
+               event->id_priv->state = cma_disconnected;\r
+       }\r
+}\r
+\r
+static int ucma_process_event(struct cma_event *event)\r
+{\r
+       WV_CONNECT_ATTRIBUTES attr;\r
+       HRESULT hr = 0;\r
+\r
+       switch (event->id_priv->state) {\r
+       case cma_get_request:\r
+               hr = ucma_process_conn_req(event);\r
+               break;\r
+       case cma_addr_resolve:\r
+               event->event.event = RDMA_CM_EVENT_ADDR_RESOLVED;\r
+               break;\r
+       case cma_route_resolve:\r
+               event->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;\r
+               break;\r
+       case cma_active_connect:\r
+               hr = ucma_process_conn_resp(event);\r
+               break;\r
+       case cma_accepting:\r
+               ucma_process_establish(event);\r
+               break;\r
+       case cma_connected:\r
+               event->event.event = RDMA_CM_EVENT_DISCONNECTED;\r
+               event->id_priv->state = cma_passive_disconnect;\r
+               break;\r
+       case cma_active_disconnect:\r
+               event->event.event = RDMA_CM_EVENT_DISCONNECTED;\r
+               event->id_priv->state = cma_disconnected;\r
+               break;\r
+       default:\r
+               return -1;\r
+       }\r
+\r
+       return hr;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_get_cm_event(struct rdma_event_channel *channel,\r
+                                         struct rdma_cm_event **event)\r
+{\r
+       struct cma_event_channel *chan;\r
+       struct cma_event *evt;\r
+       struct cma_id_private *id_priv;\r
+       struct rdma_cm_id *id;\r
+       DWORD bytes;\r
+       HRESULT hr;\r
+\r
+       evt = new struct cma_event;\r
+       if (evt == NULL) {\r
+               return -1;\r
+       }\r
+\r
+       do {\r
+               RtlZeroMemory(evt, sizeof(struct cma_event));\r
+\r
+               chan = CONTAINING_RECORD(channel, struct cma_event_channel, channel);\r
+               hr = WaitForMultipleObjects(chan->count, chan->event, FALSE,\r
+                                                                       chan->channel.timeout);\r
+               if (hr == WAIT_TIMEOUT) {\r
+                       return hr;\r
+               } else if (hr == WAIT_FAILED) {\r
+                       return HRESULT_FROM_WIN32(GetLastError());\r
+               }\r
+\r
+               EnterCriticalSection(&chan->lock);\r
+               evt->id_priv = chan->id[hr];\r
+               LeaveCriticalSection(&chan->lock);\r
+\r
+               id = &evt->id_priv->id;\r
+               evt->event.id = id;\r
+               evt->event.param.conn.private_data = evt->private_data;\r
+               if (id->ep.connect->GetOverlappedResult(&id->overlap, &bytes, FALSE) == 0) {\r
+                       evt->event.status = HRESULT_FROM_WIN32(GetLastError());\r
+               }\r
+\r
+               hr = ucma_process_event(evt);\r
+       } while (FAILED(hr));\r
+       \r
+       *event = &evt->event;\r
+       return 0;\r
+}\r
+\r
+\r
+__declspec(dllexport)\r
+int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,\r
+                                               void *context)\r
+{\r
+       return WV_NOT_SUPPORTED;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)\r
+{\r
+       return WV_NOT_SUPPORTED;\r
+}\r
+\r
+__declspec(dllexport)\r
+const char *rdma_event_str(enum rdma_cm_event_type event)\r
+{\r
+       switch (event) {\r
+       case RDMA_CM_EVENT_ADDR_RESOLVED:\r
+               return "RDMA_CM_EVENT_ADDR_RESOLVED";\r
+       case RDMA_CM_EVENT_ADDR_ERROR:\r
+               return "RDMA_CM_EVENT_ADDR_ERROR";\r
+       case RDMA_CM_EVENT_ROUTE_RESOLVED:\r
+               return "RDMA_CM_EVENT_ROUTE_RESOLVED";\r
+       case RDMA_CM_EVENT_ROUTE_ERROR:\r
+               return "RDMA_CM_EVENT_ROUTE_ERROR";\r
+       case RDMA_CM_EVENT_CONNECT_REQUEST:\r
+               return "RDMA_CM_EVENT_CONNECT_REQUEST";\r
+       case RDMA_CM_EVENT_CONNECT_RESPONSE:\r
+               return "RDMA_CM_EVENT_CONNECT_RESPONSE";\r
+       case RDMA_CM_EVENT_CONNECT_ERROR:\r
+               return "RDMA_CM_EVENT_CONNECT_ERROR";\r
+       case RDMA_CM_EVENT_UNREACHABLE:\r
+               return "RDMA_CM_EVENT_UNREACHABLE";\r
+       case RDMA_CM_EVENT_REJECTED:\r
+               return "RDMA_CM_EVENT_REJECTED";\r
+       case RDMA_CM_EVENT_ESTABLISHED:\r
+               return "RDMA_CM_EVENT_ESTABLISHED";\r
+       case RDMA_CM_EVENT_DISCONNECTED:\r
+               return "RDMA_CM_EVENT_DISCONNECTED";\r
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:\r
+               return "RDMA_CM_EVENT_DEVICE_REMOVAL";\r
+       case RDMA_CM_EVENT_MULTICAST_JOIN:\r
+               return "RDMA_CM_EVENT_MULTICAST_JOIN";\r
+       case RDMA_CM_EVENT_MULTICAST_ERROR:\r
+               return "RDMA_CM_EVENT_MULTICAST_ERROR";\r
+       case RDMA_CM_EVENT_ADDR_CHANGE:\r
+               return "RDMA_CM_EVENT_ADDR_CHANGE";\r
+       case RDMA_CM_EVENT_TIMEWAIT_EXIT:\r
+               return "RDMA_CM_EVENT_TIMEWAIT_EXIT";\r
+       default:\r
+               return "UNKNOWN EVENT";\r
+       }\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_set_option(struct rdma_cm_id *id, int level, int optname,\r
+                                       void *optval, size_t optlen)\r
+{\r
+       return WV_NOT_SUPPORTED;\r
+}\r
+\r
+__declspec(dllexport)\r
+int rdma_migrate_id(struct rdma_cm_id *id, struct rdma_event_channel *channel)\r
+{\r
+       struct cma_id_private *id_priv;\r
+\r
+       id_priv = CONTAINING_RECORD(id, struct cma_id_private, id);\r
+       cma_event_channel_remove_id(id->channel, id_priv);\r
+       /*\r
+        * TODO: To support calling this routine while processing events on the old\r
+        * channel, we need to wait for all old events to be acknowledged.\r
+        */\r
+       id->channel = channel;\r
+       cma_event_channel_insert_id(channel, id_priv);\r
+\r
+       return 0;\r
+}\r
diff --git a/branches/winverbs/ulp/librdmacm/src/cma.h b/branches/winverbs/ulp/librdmacm/src/cma.h
new file mode 100644 (file)
index 0000000..fb65026
--- /dev/null
@@ -0,0 +1,46 @@
+/*\r
+ * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.\r
+ * Copyright (c) 2008-2009 Intel Corp.  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 AWV\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 CMA_H\r
+#define CMA_H\r
+\r
+extern CRITICAL_SECTION lock;\r
+\r
+__inline void* __cdecl operator new(size_t size)\r
+{\r
+       return HeapAlloc(GetProcessHeap(), 0, size);\r
+}\r
+\r
+__inline void __cdecl operator delete(void *pObj)\r
+{\r
+       HeapFree(GetProcessHeap(), 0, pObj);\r
+}\r
+\r
+#endif /* CMA_H */\r
diff --git a/branches/winverbs/ulp/librdmacm/src/cma.rc b/branches/winverbs/ulp/librdmacm/src/cma.rc
new file mode 100644 (file)
index 0000000..fd20545
--- /dev/null
@@ -0,0 +1,46 @@
+/*\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
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                   VFT_DLL\r
+#define VER_FILESUBTYPE                        VFT2_UNKNOWN\r
+\r
+#ifdef _DEBUG_\r
+#define VER_FILEDESCRIPTION_STR                "LibRdmaCm (Debug)"\r
+#define VER_INTERNALNAME_STR           "librdmacmd.dll"\r
+#define VER_ORIGINALFILENAME_STR       "librdmacmd.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "LibRdmaCm"\r
+#define VER_INTERNALNAME_STR           "librdmacm.dll"\r
+#define VER_ORIGINALFILENAME_STR       "librdmacm.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
diff --git a/branches/winverbs/ulp/librdmacm/src/cma_export.def b/branches/winverbs/ulp/librdmacm/src/cma_export.def
new file mode 100644 (file)
index 0000000..7a2b1ec
--- /dev/null
@@ -0,0 +1,34 @@
+/*\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 AWV\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
+LIBRARY        LIBRDMACM.DLL\r
+\r
+EXPORTS\r
+       DllCanUnloadNow         PRIVATE\r
+       DllGetClassObject       PRIVATE\r
diff --git a/branches/winverbs/ulp/librdmacm/src/cma_exports.src b/branches/winverbs/ulp/librdmacm/src/cma_exports.src
new file mode 100644 (file)
index 0000000..853173b
--- /dev/null
@@ -0,0 +1,33 @@
+#if DBG\r
+LIBRARY librdmacmd.dll\r
+#else\r
+LIBRARY librdmacm.dll\r
+#endif\r
+\r
+#ifndef _WIN64\r
+EXPORTS\r
+rdma_create_event_channel\r
+rdma_destroy_event_channel\r
+rdma_create_id\r
+rdma_destroy_id\r
+rdma_bind_addr\r
+rdma_resolve_addr\r
+rdma_resolve_route\r
+rdma_create_qp\r
+rdma_destroy_qp\r
+rdma_connect\r
+rdma_listen\r
+rdma_accept\r
+rdma_reject\r
+rdma_notify\r
+rdma_disconnect\r
+rdma_join_multicast\r
+rdma_leave_multicast\r
+rdma_get_cm_event\r
+rdma_ack_cm_event\r
+rdma_get_devices\r
+rdma_free_devices\r
+rdma_event_str\r
+rdma_set_option\r
+rdma_migrate_id\r
+#endif\r
diff --git a/branches/winverbs/ulp/librdmacm/src/cma_main.cpp b/branches/winverbs/ulp/librdmacm/src/cma_main.cpp
new file mode 100644 (file)
index 0000000..2daead7
--- /dev/null
@@ -0,0 +1,44 @@
+/*\r
+ * Copyright (c) 2008-2009 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 AWV\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 <windows.h>\r
+#include "cma.h"\r
+\r
+CRITICAL_SECTION lock;\r
+\r
+BOOLEAN WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)\r
+{\r
+       UNREFERENCED_PARAMETER(hInstance);\r
+       UNREFERENCED_PARAMETER(dwReason);\r
+       UNREFERENCED_PARAMETER(lpReserved);\r
+\r
+       InitializeCriticalSection(&lock);\r
+\r
+       return TRUE;\r
+}\r
diff --git a/branches/winverbs/ulp/librdmacm/src/makefile b/branches/winverbs/ulp/librdmacm/src/makefile
new file mode 100644 (file)
index 0000000..bffacaa
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r