]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
dapl2: update
authorSean Hefty <sean.hefty@intel.com>
Thu, 4 Mar 2010 22:13:53 +0000 (22:13 +0000)
committerSean Hefty <sean.hefty@intel.com>
Thu, 4 Mar 2010 22:13:53 +0000 (22:13 +0000)
Update to commit 4b939076aa32bb52957fcc6791e187c9433d4c24 + ibal provider fixes for WOF2-2 support.  This synchronizes the trunk with the WOF2-2 branch.

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

39 files changed:
trunk/ulp/dapl2/COPYING
trunk/ulp/dapl2/ChangeLog
trunk/ulp/dapl2/Makefile.am
trunk/ulp/dapl2/configure.in
trunk/ulp/dapl2/dapl.spec.in
trunk/ulp/dapl2/dapl/common/dapl_adapter_util.h
trunk/ulp/dapl2/dapl/common/dapl_cr_callback.c
trunk/ulp/dapl2/dapl/common/dapl_cr_util.c
trunk/ulp/dapl2/dapl/common/dapl_cr_util.h
trunk/ulp/dapl2/dapl/common/dapl_ep_connect.c
trunk/ulp/dapl2/dapl/common/dapl_ep_free.c
trunk/ulp/dapl2/dapl/common/dapl_ep_util.c
trunk/ulp/dapl2/dapl/common/dapl_ep_util.h
trunk/ulp/dapl2/dapl/common/dapl_evd_connection_callb.c
trunk/ulp/dapl2/dapl/common/dapl_evd_util.c
trunk/ulp/dapl2/dapl/common/dapl_evd_util.h
trunk/ulp/dapl2/dapl/common/dapl_ia_query.c
trunk/ulp/dapl2/dapl/ibal/dapl_ibal_cm.c
trunk/ulp/dapl2/dapl/ibal/dapl_ibal_qp.c
trunk/ulp/dapl2/dapl/ibal/dapl_ibal_util.h
trunk/ulp/dapl2/dapl/ibal/udapl.rc
trunk/ulp/dapl2/dapl/include/dapl.h
trunk/ulp/dapl2/dapl/openib_cma/cm.c
trunk/ulp/dapl2/dapl/openib_cma/dapl_ib_util.h
trunk/ulp/dapl2/dapl/openib_cma/device.c
trunk/ulp/dapl2/dapl/openib_cma/linux/openib_osd.h
trunk/ulp/dapl2/dapl/openib_cma/windows/openib_osd.h
trunk/ulp/dapl2/dapl/openib_common/dapl_ib_common.h
trunk/ulp/dapl2/dapl/openib_common/mem.c
trunk/ulp/dapl2/dapl/openib_common/qp.c
trunk/ulp/dapl2/dapl/openib_common/util.c
trunk/ulp/dapl2/dapl/openib_scm/cm.c
trunk/ulp/dapl2/dapl/openib_scm/dapl_ib_util.h
trunk/ulp/dapl2/dapl/openib_scm/device.c
trunk/ulp/dapl2/dapl/openib_ucm/cm.c
trunk/ulp/dapl2/dapl/openib_ucm/dapl_ib_util.h
trunk/ulp/dapl2/dapl/openib_ucm/device.c
trunk/ulp/dapl2/test/dapltest/scripts/dt-cli.bat
trunk/ulp/dapl2/test/dapltest/scripts/dt-svr.bat

index 2012c043d56371401d370ba448f7043b56567bf7..35ba3196ab6eb298ca92fd174128256f145c0bf4 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
 # Copyright (c) 2005 Voltaire Inc.  All rights reserved.
-# Copyright (c) 2005 Intel Corporation. All rights reserved.
+# Copyright (c) 2005-2010 Intel Corporation. All rights reserved.
 # Copyright (c) 2004-2005, Mellanox Technologies, Inc. All rights reserved. 
 # Copyright (c) 2003 Topspin Corporation.  All rights reserved. 
 # Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
@@ -9,19 +9,13 @@
 # This Software is licensed under one of the following licenses:
 #
 # 1) under the terms of the "Common Public License 1.0" a copy of which is
-#    in the file LICENSE.txt in the root directory. The license is also
-#    available from the Open Source Initiative, see
-#    http://www.opensource.org/licenses/cpl.php.
+#    in the file LICENSE.txt in the root directory. 
 #
 # 2) under the terms of the "The BSD License" a copy of which is in the file
-#    LICENSE2.txt in the root directory. The license is also available from
-#    the Open Source Initiative, see
-#    http://www.opensource.org/licenses/bsd-license.php.
+#    LICENSE2.txt in the root directory. 
 #
 # 3) under the terms of the "GNU General Public License (GPL) Version 2" a 
-#    copy of which is in the file LICENSE3.txt in the root directory. The 
-#    license is also available from the Open Source Initiative, see
-#    http://www.opensource.org/licenses/gpl-license.php.
+#    copy of which is in the file LICENSE3.txt in the root directory. 
 #
 # Licensee has the right to choose one of the above licenses.
 #
@@ -32,5 +26,3 @@
 # notice, one of the license notices in the documentation
 # and/or other materials provided with the distribution.
 #
-
-
index ca4cb4f0352b69dec604faa9b5d0806890a02bbd..abc9cc7bb5c100aca4cba1781935f0aec7aa6148 100644 (file)
@@ -1,3 +1,202 @@
+commit 454c27b1f357c7c3070e459b25d12929f86304ca
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Mon Feb 22 09:42:17 2010 -0800
+
+    windows: add scm makefile
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 66ac48d5280bcf0453760c6e22909de6b8519b6d
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Mon Feb 22 09:41:13 2010 -0800
+
+    Windows does not require rdma_cma_abi.h, move the include from common code and to OSD file.
+    
+    Signed-off-by: stan smith <stan.smith@intel.com>
+
+commit c05c41c31f01e1ddef91e92998ca66d258fafe3d
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Fri Feb 19 14:52:01 2010 -0800
+
+    Windows patch to fix IB_INVALID_HANDLE name collision
+    
+    signed-off-by: stan smith <stan.smith@intel.com>
+
+commit 712e7e5ba71f8a4344dfff481a9be870eefefe25
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Mon Feb 8 13:49:35 2010 -0800
+
+    scm: dat_ep_connect fails on 32bit servers
+    
+    memcpy for remote IA address uses incorrect sizeof for a pointer type.
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 3040fa78d7d22c8f76c88dc77cedde09f016eb67
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Fri Feb 5 11:51:16 2010 -0800
+
+    undefined symbol: dapls_print_cm_list
+    
+    call prototype should be dependent on DAPL_COUNTERS.
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit cbeebe422b952d679f49429be8ba045a62d7f4ac
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Fri Feb 5 11:39:21 2010 -0800
+
+    Cleanup CM object lock before freeing CM object memory
+    
+    Running windows application verifiier for uDAPL validation
+    for all 3 providers. Cleanup memory lock leaks found
+    by verifier.
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 855a8e4aa83fa2e4f7847122415106f49286f4ca
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Wed Feb 3 16:21:30 2010 -0800
+
+    destroy verbs completion channels created via ia_open or ep_create.
+    
+    Completion channels are created with ia_open for CNO events and
+    with ep_create in cases where DAT allows EP(qp) to be created with
+    no EVD(cq) and IB doesn't. These completion channels need to be
+    destroyed at close along with a CQ for the EP without CQ case.
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 4da540591148e47dd912851cc7314776f2f7622e
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Wed Feb 3 11:06:45 2010 -0800
+
+    Update Copyright file and include the 3 license files in distribution
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 9011abd4b1470c65bfe81eef5a2f3a81060cec81
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Tue Feb 2 14:43:03 2010 -0800
+
+    When copying private_data out of rdma_cm events, use the
+    reported private_data_len for the size, and not IB maximums.
+    This fixes a bug running over the librdmacm on windows, where
+    DAPL accessed invalid memory.
+    
+    Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 5da33bb3b9c230c08492f85d13caa330ce65906e
+Author: Sean Hefty <sean.hefty@intel.com>
+Date:   Thu Jan 28 10:19:20 2010 -0800
+
+    dapl/cma: fix referencing freed address
+    
+    DAPL uses a pointer to reference the local and remote addresses
+    of an endpoint.  It expects that those addresses are located
+    in memory that is always accessible.  Typically, for the local
+    address, the pointer references the address stored with the DAPL
+    HCA device.  However, for the cma provider, it changes this pointer
+    to reference the address stored with the rdma_cm_id.
+    
+    This causes a problem when that endpoint is connected on the
+    passive side of a connection.  When connect requests are given
+    to DAPL, a new rdma_cm_id is associated with the request.  The
+    DAPL code replaces the current rdma_cm_id associated with a
+    user's endpoint with the new rdma_cm_id.  The old rdma_cm_id is
+    then deleted.  But the endpoint's local address pointer still
+    references the address stored with the old rdma_cm_id.  The
+    result is that any reference to the address will access freed
+    memory.
+    
+    Fix this by keeping the local address pointer always pointing
+    to the address associated with the DAPL HCA device.  This is about
+    the best that can be done given the DAPL interface design.
+    
+    Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+commit 66dbb5f20bf494eb3f5041655b478059165c5f1b
+Author: Sean Hefty <sean.hefty@intel.com>
+Date:   Tue Jan 26 15:13:03 2010 -0800
+
+    dapl: move close device after async thread is done
+    
+    using it
+    
+    Before calling ibv_close_device, wait for the asynchronous
+    processing thread to finish using the device.  This prevents
+    a use after free error.
+    
+    Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+commit 560b235adc799fa710571ca63cbc3e4fa6374ff2
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Mon Jan 11 09:03:10 2010 -0800
+
+    Release 2.0.26-1
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 73dfb32ace6aff2fdb21e54689342fd551822286
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Tue Dec 22 14:00:33 2009 -0800
+
+    openib_common: add check for both gid and global routing in RTR
+    
+    check for valid gid pointer along with global route setting
+    during transition to RTR. Add more GID information to
+    debug print statement in qp modify call.
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 7aab18fd8ff3f201b0a4b6c76896667b29f103c4
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Fri Dec 4 12:31:22 2009 -0800
+
+    openib_common: remote memory read privilege set multi times
+    
+    duplicate setting of read privilege in dapls_convert_privileges
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 016e2c40b8ac2fe18993e9fb7122ecb9b439e5eb
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Fri Dec 4 12:25:30 2009 -0800
+
+    ucm, scm: DAPL_GLOBAL_ROUTING enabled causes segv
+    
+    socket cm and ud cm providers support QP modify with is_global
+    set and GRH. New v2 providers didn't pass GID information
+    in modify_qp RTR call and incorrectly byte swapped the already
+    network order GID. Add debug print of GID during global modify.
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 7b0c596c7b4ad619f65da9f79dcbc4376e651dde
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Tue Nov 24 22:16:58 2009 -0800
+
+    Release 2.0.25-1
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 3197bffff478ad7ff5eff9220fa0528e42e6b56e
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Tue Nov 24 22:15:46 2009 -0800
+
+    winof scm: initialize opt for NODELAY setsockopt
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 8559ec069329249592f367b5b8f61427cbad0a46
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date:   Tue Nov 24 11:29:46 2009 -0800
+
+    Release 2.0.25
+    
+    Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
 commit 0983c66cbd9511128c1fa221470c4c983903e420
 Author: Arlin Davis <arlin.r.davis@intel.com>
 Date:   Tue Nov 24 08:58:44 2009 -0800
index 23f33e810d4524242c7e6dc367cc7a2435868602..bf828537951e79e4765c5e3ac287d514e4e73648 100644 (file)
@@ -505,6 +505,9 @@ EXTRA_DIST = dat/common/dat_dictionary.h \
             dapl/udapl/libdaplofa.map \
             dapl/udapl/libdaploscm.map \
             dapl/udapl/libdaploucm.map \
+            LICENSE.txt \
+            LICENSE2.txt \
+            LICENSE3.txt \
             dapl.spec.in \
             $(man_MANS) \
             test/dapltest/include/dapl_bpool.h \
index c704145974b30dc24cdfcf68df945ee508a8d026..0979cae56ace519dd3795fa034bbdeb81c65e401 100644 (file)
@@ -1,11 +1,11 @@
 dnl Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.57)
-AC_INIT(dapl, 2.0.25, linux-rdma@vger.kernel.org)
+AC_INIT(dapl, 2.0.27, linux-rdma@vger.kernel.org)
 AC_CONFIG_SRCDIR([dat/udat/udat.c])
 AC_CONFIG_AUX_DIR(config)
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(dapl, 2.0.25)
+AM_INIT_AUTOMAKE(dapl, 2.0.27)
 
 AM_PROG_LIBTOOL
 
index ae2038286b0af5cc49ed5c89c692a663bd34eb2b..0f2c38089c53af99dbf3992c26d20e63c8a73270 100644 (file)
@@ -121,7 +121,7 @@ fi
 %files
 %defattr(-,root,root,-)
 %{_libdir}/libda*.so.*
-%doc AUTHORS README ChangeLog
+%doc AUTHORS README COPYING ChangeLog LICENSE.txt LICENSE2.txt LICENSE3.txt
 
 %files devel
 %defattr(-,root,root,-)
@@ -140,6 +140,12 @@ fi
 %{_mandir}/man5/*.5*
 
 %changelog
+* Tue Feb 23 2010 Arlin Davis <ardavis@ichips.intel.com> - 2.0.27
+- DAT/DAPL Version 2.0.27 Release 1, OFED 1.5.1  
+
+* Tue Jan 11 2010 Arlin Davis <ardavis@ichips.intel.com> - 2.0.26
+- DAT/DAPL Version 2.0.26 Release 1, OFED 1.5, OFED 1.5-RDMAoE  
+
 * Tue Nov 24 2009 Arlin Davis <ardavis@ichips.intel.com> - 2.0.25
 - DAT/DAPL Version 2.0.25 Release 1, OFED 1.5 RC3 
 
index 4190eb81c7c1941d172deebdce780adabf496270..92cb9b72ba7d42f343e1c250070548db21d28c86 100644 (file)
-/*\r
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    in the file LICENSE.txt in the root directory. The license is also\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is in the file\r
- *    LICENSE2.txt in the root directory. The license is also available from\r
- *    the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a \r
- *    copy of which is in the file LICENSE3.txt in the root directory. The \r
- *    license is also available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- * \r
- * HEADER: dapl_adapter_util.h\r
- *\r
- * PURPOSE: Utility defs & routines for the adapter data structure\r
- *\r
- * $Id: dapl_adapter_util.h 1317 2005-04-25 17:29:42Z jlentini $\r
- *\r
- **********************************************************************/\r
-\r
-#ifndef _DAPL_ADAPTER_UTIL_H_\r
-#define _DAPL_ADAPTER_UTIL_H_\r
-\r
-\r
-typedef enum async_handler_type\r
-{\r
-    DAPL_ASYNC_UNAFILIATED,\r
-       DAPL_ASYNC_CQ_ERROR,\r
-       DAPL_ASYNC_CQ_COMPLETION,\r
-       DAPL_ASYNC_QP_ERROR\r
-} DAPL_ASYNC_HANDLER_TYPE;\r
-\r
-\r
-int dapls_ib_init (void);\r
-\r
-int dapls_ib_release (void);\r
-\r
-DAT_RETURN dapls_ib_enum_hcas (\r
-        IN   const char                 *vendor, \r
-       OUT  DAPL_HCA_NAME              **hca_names,\r
-       OUT  DAT_COUNT                  *total_hca_count);\r
-\r
-DAT_RETURN dapls_ib_get_instance_data(\r
-       IN  DAPL_HCA_NAME hca_name, \r
-       OUT char *instance);\r
-\r
-DAT_RETURN dapls_ib_open_hca (\r
-       IN   char                      *namestr,\r
-       IN   DAPL_HCA                  *hca_ptr);\r
-\r
-DAT_RETURN dapls_ib_close_hca (\r
-       IN   DAPL_HCA                  *hca_ptr);\r
-\r
-DAT_RETURN dapls_ib_qp_alloc (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EP                     *ep_ptr,\r
-       IN  DAPL_EP                     *ep_ctx_ptr);\r
-\r
-DAT_RETURN dapls_ib_qp_free (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EP                     *ep_ptr);\r
-\r
-DAT_RETURN dapls_ib_qp_modify (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EP                     *ep_ptr,\r
-       IN  DAT_EP_ATTR                 *ep_attr);\r
-\r
-DAT_RETURN dapls_ib_connect (\r
-       IN  DAT_EP_HANDLE               ep_handle,\r
-       IN  DAT_IA_ADDRESS_PTR          remote_ia_address,\r
-       IN  DAT_CONN_QUAL               remote_conn_qual,\r
-       IN  DAT_COUNT                   private_data_size,\r
-       IN  DAT_PVOID                   private_data);\r
-\r
-DAT_RETURN dapls_ib_disconnect (\r
-       IN  DAPL_EP                     *ep_ptr,\r
-       IN  DAT_CLOSE_FLAGS             close_flags);\r
-\r
-DAT_RETURN dapls_ib_setup_conn_listener (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAT_UINT64                  ServiceID,\r
-       IN  DAPL_SP                     *sp_ptr);\r
-\r
-DAT_RETURN dapls_ib_remove_conn_listener (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_SP                     *sp_ptr);\r
-\r
-DAT_RETURN dapls_ib_accept_connection (\r
-       IN  DAT_CR_HANDLE               cr_handle,\r
-       IN  DAT_EP_HANDLE               ep_handle,\r
-       IN  DAT_COUNT                   private_data_size,\r
-       IN  const DAT_PVOID             private_data);\r
-\r
-DAT_RETURN dapls_ib_reject_connection (\r
-       IN  dp_ib_cm_handle_t           cm_handle,\r
-       IN  int                         reject_reason,\r
-       IN  DAT_COUNT                   private_data_size,\r
-       IN  const DAT_PVOID             private_data);\r
-\r
-DAT_RETURN dapls_ib_setup_async_callback (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_ASYNC_HANDLER_TYPE     handler_type,\r
-       IN  DAPL_EVD                    *evd_ptr,\r
-       IN  ib_async_handler_t          callback,\r
-       IN  void                        *context);\r
-\r
-DAT_RETURN dapls_ib_cq_alloc (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EVD                    *evd_ptr,\r
-       IN  DAT_COUNT                   *cqlen);\r
-\r
-DAT_RETURN dapls_ib_cq_free (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EVD                    *evd_ptr);\r
-\r
-DAT_RETURN dapls_set_cq_notify (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EVD                    *evd_ptr);\r
-\r
-DAT_RETURN dapls_ib_cq_resize (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_EVD                    *evd_ptr,\r
-       IN  DAT_COUNT                   *cqlen);\r
-\r
-DAT_RETURN dapls_ib_pd_alloc (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       IN  DAPL_PZ                     *pz);\r
-\r
-DAT_RETURN dapls_ib_pd_free (\r
-       IN  DAPL_PZ                     *pz);\r
-\r
-DAT_RETURN dapls_ib_mr_register (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-        IN  DAPL_LMR                   *lmr,\r
-       IN  DAT_PVOID                   virt_addr,\r
-       IN  DAT_VLEN                    length,\r
-       IN  DAT_MEM_PRIV_FLAGS          privileges,\r
-       IN  DAT_VA_TYPE                 va_type);\r
-\r
-#if defined(__KDAPL__)\r
-DAT_RETURN dapls_ib_mr_register_physical (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-       INOUT  DAPL_LMR                 *lmr,\r
-       IN  DAT_PADDR                   phys_addr,\r
-       IN  DAT_VLEN                    length,\r
-       IN  DAT_MEM_PRIV_FLAGS          privileges);\r
-#endif /* __KDAPL__ */\r
-\r
-DAT_RETURN dapls_ib_mr_deregister (\r
-       IN  DAPL_LMR                    *lmr);\r
-\r
-DAT_RETURN dapls_ib_mr_register_shared (\r
-       IN  DAPL_IA                     *ia_ptr,\r
-        IN  DAPL_LMR                   *lmr,\r
-       IN  DAT_MEM_PRIV_FLAGS          privileges,\r
-       IN  DAT_VA_TYPE                 va_type);\r
-\r
-DAT_RETURN dapls_ib_mw_alloc (\r
-       IN  DAPL_RMR                    *rmr);\r
-\r
-DAT_RETURN dapls_ib_mw_free (\r
-       IN  DAPL_RMR                    *rmr);\r
-\r
-DAT_RETURN dapls_ib_mw_bind (\r
-       IN  DAPL_RMR                    *rmr,\r
-       IN  DAPL_LMR                    *lmr,\r
-       IN  DAPL_EP                     *ep,\r
-       IN  DAPL_COOKIE                 *cookie,\r
-       IN  DAT_VADDR                   virtual_address,\r
-       IN  DAT_VLEN                    length,\r
-       IN  DAT_MEM_PRIV_FLAGS          mem_priv,\r
-       IN  DAT_BOOLEAN                 is_signaled);\r
-\r
-DAT_RETURN dapls_ib_mw_unbind (\r
-       IN  DAPL_RMR                    *rmr,\r
-       IN  DAPL_EP                     *ep,\r
-       IN  DAPL_COOKIE                 *cookie,\r
-       IN  DAT_BOOLEAN                 is_signaled);\r
-\r
-DAT_RETURN dapls_ib_query_hca (\r
-       IN  DAPL_HCA                    *hca_ptr,\r
-       OUT DAT_IA_ATTR                 *ia_attr,\r
-       OUT DAT_EP_ATTR                 *ep_attr,\r
-       OUT DAT_SOCK_ADDR6              *ip_addr);\r
-\r
-DAT_RETURN dapls_ib_completion_poll (\r
-       IN  DAPL_HCA                    *hca_ptr,\r
-       IN  DAPL_EVD                    *evd_ptr,\r
-       IN  ib_work_completion_t        *cqe_ptr);\r
-\r
-DAT_RETURN dapls_ib_completion_notify (\r
-       IN  ib_hca_handle_t             hca_handle,\r
-       IN  DAPL_EVD                    *evd_ptr,\r
-       IN  ib_notification_type_t      type);\r
-\r
-DAT_DTO_COMPLETION_STATUS dapls_ib_get_dto_status (\r
-       IN  ib_work_completion_t        *cqe_ptr);\r
-\r
-void dapls_ib_reinit_ep (\r
-       IN  DAPL_EP                     *ep_ptr);\r
-\r
-void dapls_ib_disconnect_clean (\r
-       IN  DAPL_EP                     *ep_ptr,\r
-       IN  DAT_BOOLEAN                 passive,\r
-       IN  const ib_cm_events_t        ib_cm_event);\r
-\r
-DAT_RETURN dapls_ib_get_async_event (\r
-       IN  ib_error_record_t           *cause_ptr,\r
-       OUT DAT_EVENT_NUMBER            *async_event);\r
-\r
-DAT_EVENT_NUMBER dapls_ib_get_dat_event (\r
-       IN  const ib_cm_events_t        ib_cm_event,\r
-       IN  DAT_BOOLEAN                 active);\r
-\r
-ib_cm_events_t dapls_ib_get_cm_event (\r
-       IN  DAT_EVENT_NUMBER            dat_event_num);\r
-\r
-DAT_RETURN dapls_ib_cm_remote_addr (\r
-       IN  DAT_HANDLE                  dat_handle,\r
-       OUT DAT_SOCK_ADDR6              *remote_ia_address);\r
-\r
-int dapls_ib_private_data_size(\r
-       IN DAPL_HCA                     *hca_ptr);\r
-\r
-void \r
-dapls_query_provider_specific_attr(\r
-       IN DAPL_IA                      *ia_ptr,\r
-       IN DAT_PROVIDER_ATTR            *attr_ptr );\r
-\r
-DAT_RETURN\r
-dapls_evd_dto_wakeup (\r
-       IN DAPL_EVD                     *evd_ptr);\r
-\r
-DAT_RETURN\r
-dapls_evd_dto_wait (\r
-       IN DAPL_EVD                     *evd_ptr,\r
-       IN uint32_t                     timeout);\r
-\r
-#ifdef DAT_EXTENSIONS\r
-void\r
-dapls_cqe_to_event_extension(\r
-       IN DAPL_EP                      *ep_ptr,\r
-       IN DAPL_COOKIE                  *cookie,\r
-       IN ib_work_completion_t         *cqe_ptr,\r
-       IN DAT_EVENT                    *event_ptr);\r
-#endif\r
-\r
-/*\r
- * Values for provider DAT_NAMED_ATTR\r
- */\r
-#define IB_QP_STATE            1       /* QP state change request */\r
-\r
-\r
-#ifdef IBAPI\r
-#include "dapl_ibapi_dto.h"\r
-#elif VAPI\r
-#include "dapl_vapi_dto.h"\r
-#elif __OPENIB__\r
-#include "dapl_openib_dto.h"\r
-#elif DUMMY\r
-#include "dapl_dummy_dto.h"\r
-#elif OPENIB\r
-#include "dapl_ib_dto.h"\r
-#else\r
-#include "dapl_ibal_dto.h"\r
-#endif\r
-\r
-\r
-#endif /*  _DAPL_ADAPTER_UTIL_H_ */\r
+/*
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    in the file LICENSE.txt in the root directory. The license is also
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is in the file
+ *    LICENSE2.txt in the root directory. The license is also available from
+ *    the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a 
+ *    copy of which is in the file LICENSE3.txt in the root directory. The 
+ *    license is also available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ * 
+ * HEADER: dapl_adapter_util.h
+ *
+ * PURPOSE: Utility defs & routines for the adapter data structure
+ *
+ * $Id: dapl_adapter_util.h 1317 2005-04-25 17:29:42Z jlentini $
+ *
+ **********************************************************************/
+
+#ifndef _DAPL_ADAPTER_UTIL_H_
+#define _DAPL_ADAPTER_UTIL_H_
+
+
+typedef enum async_handler_type
+{
+    DAPL_ASYNC_UNAFILIATED,
+       DAPL_ASYNC_CQ_ERROR,
+       DAPL_ASYNC_CQ_COMPLETION,
+       DAPL_ASYNC_QP_ERROR
+} DAPL_ASYNC_HANDLER_TYPE;
+
+
+int dapls_ib_init (void);
+
+int dapls_ib_release (void);
+
+DAT_RETURN dapls_ib_enum_hcas (
+        IN   const char                 *vendor, 
+       OUT  DAPL_HCA_NAME              **hca_names,
+       OUT  DAT_COUNT                  *total_hca_count);
+
+DAT_RETURN dapls_ib_get_instance_data(
+       IN  DAPL_HCA_NAME hca_name, 
+       OUT char *instance);
+
+DAT_RETURN dapls_ib_open_hca (
+       IN   char                      *namestr,
+       IN   DAPL_HCA                  *hca_ptr);
+
+DAT_RETURN dapls_ib_close_hca (
+       IN   DAPL_HCA                  *hca_ptr);
+
+DAT_RETURN dapls_ib_qp_alloc (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EP                     *ep_ptr,
+       IN  DAPL_EP                     *ep_ctx_ptr);
+
+DAT_RETURN dapls_ib_qp_free (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EP                     *ep_ptr);
+
+DAT_RETURN dapls_ib_qp_modify (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EP                     *ep_ptr,
+       IN  DAT_EP_ATTR                 *ep_attr);
+
+DAT_RETURN dapls_ib_connect (
+       IN  DAT_EP_HANDLE               ep_handle,
+       IN  DAT_IA_ADDRESS_PTR          remote_ia_address,
+       IN  DAT_CONN_QUAL               remote_conn_qual,
+       IN  DAT_COUNT                   private_data_size,
+       IN  DAT_PVOID                   private_data);
+
+DAT_RETURN dapls_ib_disconnect (
+       IN  DAPL_EP                     *ep_ptr,
+       IN  DAT_CLOSE_FLAGS             close_flags);
+
+DAT_RETURN dapls_ib_setup_conn_listener (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAT_UINT64                  ServiceID,
+       IN  DAPL_SP                     *sp_ptr);
+
+DAT_RETURN dapls_ib_remove_conn_listener (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_SP                     *sp_ptr);
+
+DAT_RETURN dapls_ib_accept_connection (
+       IN  DAT_CR_HANDLE               cr_handle,
+       IN  DAT_EP_HANDLE               ep_handle,
+       IN  DAT_COUNT                   private_data_size,
+       IN  const DAT_PVOID             private_data);
+
+DAT_RETURN dapls_ib_reject_connection (
+       IN  dp_ib_cm_handle_t           cm_handle,
+       IN  int                         reject_reason,
+       IN  DAT_COUNT                   private_data_size,
+       IN  const DAT_PVOID             private_data);
+
+DAT_RETURN dapls_ib_setup_async_callback (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_ASYNC_HANDLER_TYPE     handler_type,
+       IN  DAPL_EVD                    *evd_ptr,
+       IN  ib_async_handler_t          callback,
+       IN  void                        *context);
+
+DAT_RETURN dapls_ib_cq_alloc (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EVD                    *evd_ptr,
+       IN  DAT_COUNT                   *cqlen);
+
+DAT_RETURN dapls_ib_cq_free (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EVD                    *evd_ptr);
+
+DAT_RETURN dapls_set_cq_notify (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EVD                    *evd_ptr);
+
+DAT_RETURN dapls_ib_cq_resize (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_EVD                    *evd_ptr,
+       IN  DAT_COUNT                   *cqlen);
+
+DAT_RETURN dapls_ib_pd_alloc (
+       IN  DAPL_IA                     *ia_ptr,
+       IN  DAPL_PZ                     *pz);
+
+DAT_RETURN dapls_ib_pd_free (
+       IN  DAPL_PZ                     *pz);
+
+DAT_RETURN dapls_ib_mr_register (
+       IN  DAPL_IA                     *ia_ptr,
+        IN  DAPL_LMR                   *lmr,
+       IN  DAT_PVOID                   virt_addr,
+       IN  DAT_VLEN                    length,
+       IN  DAT_MEM_PRIV_FLAGS          privileges,
+       IN  DAT_VA_TYPE                 va_type);
+
+#if defined(__KDAPL__)
+DAT_RETURN dapls_ib_mr_register_physical (
+       IN  DAPL_IA                     *ia_ptr,
+       INOUT  DAPL_LMR                 *lmr,
+       IN  DAT_PADDR                   phys_addr,
+       IN  DAT_VLEN                    length,
+       IN  DAT_MEM_PRIV_FLAGS          privileges);
+#endif /* __KDAPL__ */
+
+DAT_RETURN dapls_ib_mr_deregister (
+       IN  DAPL_LMR                    *lmr);
+
+DAT_RETURN dapls_ib_mr_register_shared (
+       IN  DAPL_IA                     *ia_ptr,
+        IN  DAPL_LMR                   *lmr,
+       IN  DAT_MEM_PRIV_FLAGS          privileges,
+       IN  DAT_VA_TYPE                 va_type);
+
+DAT_RETURN dapls_ib_mw_alloc (
+       IN  DAPL_RMR                    *rmr);
+
+DAT_RETURN dapls_ib_mw_free (
+       IN  DAPL_RMR                    *rmr);
+
+DAT_RETURN dapls_ib_mw_bind (
+       IN  DAPL_RMR                    *rmr,
+       IN  DAPL_LMR                    *lmr,
+       IN  DAPL_EP                     *ep,
+       IN  DAPL_COOKIE                 *cookie,
+       IN  DAT_VADDR                   virtual_address,
+       IN  DAT_VLEN                    length,
+       IN  DAT_MEM_PRIV_FLAGS          mem_priv,
+       IN  DAT_BOOLEAN                 is_signaled);
+
+DAT_RETURN dapls_ib_mw_unbind (
+       IN  DAPL_RMR                    *rmr,
+       IN  DAPL_EP                     *ep,
+       IN  DAPL_COOKIE                 *cookie,
+       IN  DAT_BOOLEAN                 is_signaled);
+
+DAT_RETURN dapls_ib_query_hca (
+       IN  DAPL_HCA                    *hca_ptr,
+       OUT DAT_IA_ATTR                 *ia_attr,
+       OUT DAT_EP_ATTR                 *ep_attr,
+       OUT DAT_SOCK_ADDR6              *ip_addr);
+
+DAT_RETURN dapls_ib_completion_poll (
+       IN  DAPL_HCA                    *hca_ptr,
+       IN  DAPL_EVD                    *evd_ptr,
+       IN  ib_work_completion_t        *cqe_ptr);
+
+DAT_RETURN dapls_ib_completion_notify (
+       IN  ib_hca_handle_t             hca_handle,
+       IN  DAPL_EVD                    *evd_ptr,
+       IN  ib_notification_type_t      type);
+
+DAT_DTO_COMPLETION_STATUS dapls_ib_get_dto_status (
+       IN  ib_work_completion_t        *cqe_ptr);
+
+void dapls_ib_reinit_ep (
+       IN  DAPL_EP                     *ep_ptr);
+
+void dapls_ib_disconnect_clean (
+       IN  DAPL_EP                     *ep_ptr,
+       IN  DAT_BOOLEAN                 passive,
+       IN  const ib_cm_events_t        ib_cm_event);
+
+DAT_RETURN dapls_ib_get_async_event (
+       IN  ib_error_record_t           *cause_ptr,
+       OUT DAT_EVENT_NUMBER            *async_event);
+
+DAT_EVENT_NUMBER dapls_ib_get_dat_event (
+       IN  const ib_cm_events_t        ib_cm_event,
+       IN  DAT_BOOLEAN                 active);
+
+ib_cm_events_t dapls_ib_get_cm_event (
+       IN  DAT_EVENT_NUMBER            dat_event_num);
+
+DAT_RETURN dapls_ib_cm_remote_addr (
+       IN  DAT_HANDLE                  dat_handle,
+       OUT DAT_SOCK_ADDR6              *remote_ia_address);
+
+int dapls_ib_private_data_size(
+       IN DAPL_HCA                     *hca_ptr);
+
+void 
+dapls_query_provider_specific_attr(
+       IN DAPL_IA                      *ia_ptr,
+       IN DAT_PROVIDER_ATTR            *attr_ptr );
+
+DAT_RETURN
+dapls_evd_dto_wakeup (
+       IN DAPL_EVD                     *evd_ptr);
+
+DAT_RETURN
+dapls_evd_dto_wait (
+       IN DAPL_EVD                     *evd_ptr,
+       IN uint32_t                     timeout);
+
+#ifdef DAT_EXTENSIONS
+void
+dapls_cqe_to_event_extension(
+       IN DAPL_EP                      *ep_ptr,
+       IN DAPL_COOKIE                  *cookie,
+       IN ib_work_completion_t         *cqe_ptr,
+       IN DAT_EVENT                    *event_ptr);
+#endif
+
+/*
+ * Values for provider DAT_NAMED_ATTR
+ */
+#define IB_QP_STATE            1       /* QP state change request */
+
+
+#ifdef IBAPI
+#include "dapl_ibapi_dto.h"
+#elif VAPI
+#include "dapl_vapi_dto.h"
+#elif __OPENIB__
+#include "dapl_openib_dto.h"
+#elif DUMMY
+#include "dapl_dummy_dto.h"
+#elif OPENIB
+#include "dapl_ib_dto.h"
+#else
+#include "dapl_ibal_dto.h"
+#endif
+
+
+#endif /*  _DAPL_ADAPTER_UTIL_H_ */
index 6268cc6f2ae8b6b2cbcf0a46e90718f4229f5d2e..3997b38266aafbd692bdab3202c043d8d7bdc0ad 100644 (file)
-/*\r
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- *\r
- * MODULE: dapls_cr_callback.c\r
- *\r
- * PURPOSE: implements passive side connection callbacks\r
- *\r
- * Description: Accepts asynchronous callbacks from the Communications Manager\r
- *              for EVDs that have been specified as the connection_evd.\r
- *\r
- * $Id:$\r
- **********************************************************************/\r
-\r
-#include "dapl.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_cr_util.h"\r
-#include "dapl_ia_util.h"\r
-#include "dapl_sp_util.h"\r
-#include "dapl_ep_util.h"\r
-#include "dapl_adapter_util.h"\r
-\r
-/*\r
- * Prototypes\r
- */\r
-DAT_RETURN dapli_connection_request(IN dp_ib_cm_handle_t ib_cm_handle,\r
-                                   IN DAPL_SP * sp_ptr,\r
-                                   IN DAPL_PRIVATE * prd_ptr,\r
-                                   IN int private_data_size,\r
-                                   IN DAPL_EVD * evd_ptr);\r
-\r
-DAPL_EP *dapli_get_sp_ep(IN dp_ib_cm_handle_t ib_cm_handle,\r
-                        IN DAPL_SP * sp_ptr,\r
-                        IN DAT_EVENT_NUMBER dat_event_num);\r
-\r
-/*\r
- * dapls_cr_callback\r
- *\r
- * The callback function registered with verbs for passive side of\r
- * connection requests. The interface is specified by cm_api.h\r
- *\r
- *\r
- * Input:\r
- *     ib_cm_handle,           Handle to CM\r
- *     ib_cm_event             Specific CM event\r
- *     instant_data            Private data with DAT ADDRESS header\r
- *     context                 SP pointer\r
- *\r
- * Output:\r
- *     None\r
- *\r
- */\r
-void dapls_cr_callback(IN dp_ib_cm_handle_t ib_cm_handle, IN const ib_cm_events_t ib_cm_event,\r
-                      IN const void *private_data_ptr, IN const int private_data_size,\r
-                      IN const void *context)\r
-{\r
-       DAPL_EP *ep_ptr;\r
-       DAPL_EVD *evd_ptr;\r
-       DAPL_SP *sp_ptr;\r
-       DAPL_PRIVATE *prd_ptr;\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
-                    "--> dapl_cr_callback! context: %p event: %x cm_handle %p\n",\r
-                    context, ib_cm_event, (void *)ib_cm_handle);\r
-\r
-       /*\r
-        * Passive side of the connection, context is a SP and\r
-        * we need to look up the EP.\r
-        */\r
-       sp_ptr = (DAPL_SP *) context;\r
-       /*\r
-        * The context pointer could have been cleaned up in a racing\r
-        * CM callback, check to see if we should just exit here\r
-        */\r
-       if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) {\r
-               return;\r
-       }\r
-       dapl_os_assert(sp_ptr->header.magic == DAPL_MAGIC_PSP ||\r
-                      sp_ptr->header.magic == DAPL_MAGIC_RSP);\r
-\r
-       /* Obtain the event number from the provider layer */\r
-       dat_event_num = dapls_ib_get_dat_event(ib_cm_event, DAT_FALSE);\r
-\r
-       /*\r
-        * CONNECT_REQUEST events create an event on the PSP\r
-        * EVD, which will trigger connection processing. The\r
-        * sequence is:\r
-        *    CONNECT_REQUEST         Event to SP\r
-        *    CONNECTED               Event to EP\r
-        *    DISCONNECT              Event to EP\r
-        *\r
-        * Obtain the EP if required and set an event up on the correct\r
-        * EVD.\r
-        */\r
-       if (dat_event_num == DAT_CONNECTION_REQUEST_EVENT) {\r
-               ep_ptr = NULL;\r
-               evd_ptr = sp_ptr->evd_handle;\r
-       } else {\r
-               /* see if there is an EP connected with this CM handle */\r
-               ep_ptr = dapli_get_sp_ep(ib_cm_handle, sp_ptr, dat_event_num);\r
-\r
-               /* if we lost a race with the CM just exit. */\r
-               if (ep_ptr == NULL) {\r
-                       return;\r
-               }\r
-\r
-               evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;\r
-               /* if something has happened to our EVD, bail. */\r
-               if (evd_ptr == NULL) {\r
-                       return;\r
-               }\r
-       }\r
-\r
-       prd_ptr = (DAPL_PRIVATE *) private_data_ptr;\r
-\r
-       dat_status = DAT_INTERNAL_ERROR;        /* init to ERR */\r
-\r
-       switch (dat_event_num) {\r
-       case DAT_CONNECTION_REQUEST_EVENT:\r
-               {\r
-                       /*\r
-                        * Requests arriving on a disabled SP are immediatly rejected\r
-                        */\r
-\r
-                       dapl_os_lock(&sp_ptr->header.lock);\r
-                       if (sp_ptr->listening == DAT_FALSE) {\r
-                               dapl_os_unlock(&sp_ptr->header.lock);\r
-                               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                                            "---> dapls_cr_callback: conn event on down SP\n");\r
-                               (void)dapls_ib_reject_connection(ib_cm_handle,\r
-                                                                DAT_CONNECTION_EVENT_UNREACHABLE,\r
-                                                                0, NULL);\r
-\r
-                               return;\r
-                       }\r
-\r
-                       if (sp_ptr->header.handle_type == DAT_HANDLE_TYPE_RSP) {\r
-                               /*\r
-                                * RSP connections only allow a single connection. Close\r
-                                * it down NOW so we reject any further connections.\r
-                                */\r
-                               sp_ptr->listening = DAT_FALSE;\r
-                       }\r
-                       dapl_os_unlock(&sp_ptr->header.lock);\r
-\r
-                       /*\r
-                        * Only occurs on the passive side of a connection\r
-                        * dapli_connection_request will post the connection\r
-                        * event if appropriate.\r
-                        */\r
-                       dat_status = dapli_connection_request(ib_cm_handle,\r
-                                                             sp_ptr, prd_ptr, private_data_size, evd_ptr);\r
-                       /* Set evd_ptr = NULL so we don't generate an event below */\r
-                       evd_ptr = NULL;\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_EVENT_ESTABLISHED:\r
-               {\r
-                       /* This is just a notification the connection is now\r
-                        * established, there isn't any private data to deal with.\r
-                        *\r
-                        * Update the EP state and cache a copy of the cm handle,\r
-                        * then let the user know we are ready to go.\r
-                        */\r
-                       dapl_os_lock(&ep_ptr->header.lock);\r
-                       if (ep_ptr->header.magic != DAPL_MAGIC_EP ||\r
-                           ep_ptr->param.ep_state !=\r
-                           DAT_EP_STATE_COMPLETION_PENDING) {\r
-                               /* If someone pulled the plug on the EP or connection,\r
-                                * just exit\r
-                                */\r
-                               dapl_os_unlock(&ep_ptr->header.lock);\r
-                               dat_status = DAT_SUCCESS;\r
-                               /* Set evd_ptr = NULL so we don't generate an event below */\r
-                               evd_ptr = NULL;\r
-\r
-                               break;\r
-                       }\r
-\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;\r
-                       ep_ptr->cm_handle = ib_cm_handle;\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_EVENT_DISCONNECTED:\r
-               {\r
-                       /*\r
-                        * EP is now fully disconnected; initiate any post processing\r
-                        * to reset the underlying QP and get the EP ready for\r
-                        * another connection\r
-                        */\r
-                       dapl_os_lock(&ep_ptr->header.lock);\r
-                       if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED) {\r
-                               /* The disconnect has already occurred, we are now\r
-                                * cleaned up and ready to exit\r
-                                */\r
-                               dapl_os_unlock(&ep_ptr->header.lock);\r
-                               return;\r
-                       }\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,\r
-                                                 ib_cm_event);\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:\r
-       case DAT_CONNECTION_EVENT_PEER_REJECTED:\r
-       case DAT_CONNECTION_EVENT_UNREACHABLE:\r
-               {\r
-                       /*\r
-                        * After posting an accept the requesting node has\r
-                        * stopped talking.\r
-                        */\r
-                       dapl_os_lock(&ep_ptr->header.lock);\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-                       ep_ptr->cm_handle = IB_INVALID_HANDLE;\r
-                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,\r
-                                                 ib_cm_event);\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_EVENT_BROKEN:\r
-               {\r
-                       dapl_os_lock(&ep_ptr->header.lock);\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,\r
-                                                 ib_cm_event);\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       default:\r
-               {\r
-                       evd_ptr = NULL;\r
-                       dapl_os_assert(0);      /* shouldn't happen */\r
-                       break;\r
-               }\r
-       }\r
-\r
-       if (evd_ptr != NULL) {\r
-               dat_status = dapls_evd_post_connection_event(evd_ptr,\r
-                                                            dat_event_num,\r
-                                                            (DAT_HANDLE)\r
-                                                            ep_ptr, 0, NULL);\r
-       }\r
-\r
-       if (dat_status != DAT_SUCCESS) {\r
-               /* The event post failed; take appropriate action.  */\r
-               (void)dapls_ib_reject_connection(ib_cm_handle,\r
-                                                DAT_CONNECTION_EVENT_BROKEN,\r
-                                                0, NULL);\r
-\r
-               return;\r
-       }\r
-}\r
-\r
-/*\r
- * dapli_connection_request\r
- *\r
- * Process a connection request on the Passive side of a connection.\r
- * Create a CR record and link it on to the SP so we can update it\r
- * and free it later. Create an EP if specified by the PSP flags.\r
- *\r
- * Input:\r
- *     ib_cm_handle,\r
- *     sp_ptr\r
- *     event_ptr\r
- *     prd_ptr\r
- *\r
- * Output:\r
- *     None\r
- *\r
- * Returns\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_SUCCESS\r
- *\r
- */\r
-DAT_RETURN\r
-dapli_connection_request(IN dp_ib_cm_handle_t ib_cm_handle,\r
-                        IN DAPL_SP * sp_ptr,\r
-                        IN DAPL_PRIVATE * prd_ptr, IN int private_data_size,\r
-                        IN DAPL_EVD * evd_ptr)\r
-{\r
-       DAT_RETURN dat_status;\r
-\r
-       DAPL_CR *cr_ptr;\r
-       DAPL_EP *ep_ptr;\r
-       DAPL_IA *ia_ptr;\r
-       DAT_SP_HANDLE sp_handle;\r
-\r
-       cr_ptr = dapls_cr_alloc(sp_ptr->header.owner_ia);\r
-       if (cr_ptr == NULL) {\r
-               /* Invoking function will call dapls_ib_cm_reject() */\r
-               return DAT_INSUFFICIENT_RESOURCES;\r
-       }\r
-\r
-       /*\r
-        * Set up the CR\r
-        */\r
-       cr_ptr->sp_ptr = sp_ptr;        /* maintain sp_ptr in case of reject */\r
-       cr_ptr->param.remote_port_qual = 0;\r
-       cr_ptr->ib_cm_handle = ib_cm_handle;\r
-#ifdef IBHOSTS_NAMING\r
-       /*\r
-        * Special case: pull the remote HCA address from the private data\r
-        * prefix. This is a spec violation as it introduces a protocol, but\r
-        * some implementations may find it necessary for a time.\r
-        */\r
-       cr_ptr->remote_ia_address = prd_ptr->hca_address;\r
-#endif                         /* IBHOSTS_NAMING */\r
-       cr_ptr->param.remote_ia_address_ptr =\r
-           (DAT_IA_ADDRESS_PTR) & cr_ptr->remote_ia_address;\r
-       /*\r
-        * Copy the remote address and private data out of the private_data\r
-        * payload and put them in a local structure\r
-        */\r
-\r
-       /* Private data size will be determined by the provider layer */\r
-       cr_ptr->param.private_data = cr_ptr->private_data;\r
-       cr_ptr->param.private_data_size = private_data_size;\r
-       if (cr_ptr->param.private_data_size > 0) {\r
-               dapl_os_memcpy(cr_ptr->private_data,\r
-                              prd_ptr->private_data,\r
-                              DAPL_MIN(cr_ptr->param.private_data_size,\r
-                                       DAPL_MAX_PRIVATE_DATA_SIZE));\r
-       }\r
-\r
-       /* EP will be NULL unless RSP service point */\r
-       ep_ptr = (DAPL_EP *) sp_ptr->ep_handle;\r
-\r
-       if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {\r
-               /*\r
-                * Never true for RSP connections\r
-                *\r
-                * Create an EP for the user. If we can't allocate an\r
-                * EP we are out of resources and need to tell the\r
-                * requestor that we cant help them.\r
-                */\r
-               ia_ptr = sp_ptr->header.owner_ia;\r
-               ep_ptr = dapl_ep_alloc(ia_ptr, NULL);\r
-               if (ep_ptr == NULL) {\r
-                       dapls_cr_free(cr_ptr);\r
-                       /* Invoking function will call dapls_ib_cm_reject() */\r
-                       return DAT_INSUFFICIENT_RESOURCES;\r
-               }\r
-               ep_ptr->param.ia_handle = ia_ptr;\r
-               ep_ptr->param.local_ia_address_ptr =\r
-                   (DAT_IA_ADDRESS_PTR) & ia_ptr->hca_ptr->hca_address;\r
-\r
-               /* Link the EP onto the IA */\r
-               dapl_ia_link_ep(ia_ptr, ep_ptr);\r
-       }\r
-\r
-       cr_ptr->param.local_ep_handle = ep_ptr;\r
-\r
-       if (ep_ptr != NULL) {\r
-               /* Assign valid EP fields: RSP and PSP_PROVIDER_FLAG only */\r
-               if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {\r
-                       ep_ptr->param.ep_state =\r
-                           DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING;\r
-               } else {\r
-                       /* RSP */\r
-                       dapl_os_assert(sp_ptr->header.handle_type ==\r
-                                      DAT_HANDLE_TYPE_RSP);\r
-                       ep_ptr->param.ep_state =\r
-                           DAT_EP_STATE_PASSIVE_CONNECTION_PENDING;\r
-               }\r
-               ep_ptr->cm_handle = ib_cm_handle;\r
-       }\r
-\r
-       /* link the CR onto the SP so we can pick it up later */\r
-       dapl_sp_link_cr(sp_ptr, cr_ptr);\r
-\r
-       /* Post the event.  */\r
-       /* assign sp_ptr to union to avoid typecast errors from some compilers */\r
-       sp_handle.psp_handle = (DAT_PSP_HANDLE) sp_ptr;\r
-\r
-       dat_status = dapls_evd_post_cr_arrival_event(evd_ptr,\r
-                                                    DAT_CONNECTION_REQUEST_EVENT,\r
-                                                    sp_handle,\r
-                                                    (DAT_IA_ADDRESS_PTR)\r
-                                                    & sp_ptr->header.owner_ia->\r
-                                                    hca_ptr->hca_address,\r
-                                                    sp_ptr->conn_qual,\r
-                                                    (DAT_CR_HANDLE) cr_ptr);\r
-\r
-       if (dat_status != DAT_SUCCESS) {\r
-               dapls_cr_free(cr_ptr);\r
-               (void)dapls_ib_reject_connection(ib_cm_handle,\r
-                                                DAT_CONNECTION_EVENT_BROKEN,\r
-                                                0, NULL);\r
-\r
-               /* Take the CR off the list, we can't use it */\r
-               dapl_os_lock(&sp_ptr->header.lock);\r
-               dapl_sp_remove_cr(sp_ptr, cr_ptr);\r
-               dapl_os_unlock(&sp_ptr->header.lock);\r
-               return DAT_INSUFFICIENT_RESOURCES;\r
-       }\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapli_get_sp_ep\r
- *\r
- * Passive side of a connection is now fully established. Clean\r
- * up resources and obtain the EP pointer associated with a CR in\r
- * the SP\r
- *\r
- * Input:\r
- *     ib_cm_handle,\r
- *     sp_ptr\r
- *     connection_event\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns\r
- *     ep_ptr\r
- *\r
- */\r
-DAPL_EP *dapli_get_sp_ep(IN dp_ib_cm_handle_t ib_cm_handle,\r
-                        IN DAPL_SP * sp_ptr, IN DAT_EVENT_NUMBER dat_event_num)\r
-{\r
-       DAPL_CR *cr_ptr;\r
-       DAPL_EP *ep_ptr;\r
-\r
-       /*\r
-        * acquire the lock, we may be racing with other threads here\r
-        */\r
-       dapl_os_lock(&sp_ptr->header.lock);\r
-\r
-       /* Verify under lock that the SP is still valid */\r
-       if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) {\r
-               dapl_os_unlock(&sp_ptr->header.lock);\r
-               return NULL;\r
-       }\r
-       /*\r
-        * There are potentially multiple connections in progress. Need to\r
-        * go through the list and find the one we are interested\r
-        * in. There is no guarantee of order. dapl_sp_search_cr\r
-        * leaves the CR on the SP queue.\r
-        */\r
-       cr_ptr = dapl_sp_search_cr(sp_ptr, ib_cm_handle);\r
-       if (cr_ptr == NULL) {\r
-               dapl_os_unlock(&sp_ptr->header.lock);\r
-               return NULL;\r
-       }\r
-\r
-       ep_ptr = (DAPL_EP *) cr_ptr->param.local_ep_handle;\r
-\r
-       /* Quick check to ensure our EP is still valid */\r
-       if ((DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP))) {\r
-               ep_ptr = NULL;\r
-       }\r
-\r
-       /* The CR record is discarded in all except for the CONNECTED case,\r
-        * as it will have no further relevance.\r
-        */\r
-       if (dat_event_num != DAT_CONNECTION_EVENT_ESTABLISHED) {\r
-               /* Remove the CR from the queue */\r
-               dapl_sp_remove_cr(sp_ptr, cr_ptr);\r
-\r
-               if (ep_ptr != NULL) {\r
-                       ep_ptr->cr_ptr = NULL;\r
-               }\r
-\r
-               /*\r
-                * If this SP has been removed from service, free it\r
-                * up after the last CR is removed\r
-                */\r
-               if (sp_ptr->listening != DAT_TRUE && sp_ptr->cr_list_count == 0\r
-                   && sp_ptr->state != DAPL_SP_STATE_FREE) {\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                                    "--> dapli_get_sp_ep! disconnect dump sp: %p \n",\r
-                                    sp_ptr);\r
-                       /* Decrement the ref count on the EVD */\r
-                       if (sp_ptr->evd_handle) {\r
-                               dapl_os_atomic_dec(&\r
-                                                  ((DAPL_EVD *) sp_ptr->\r
-                                                   evd_handle)->evd_ref_count);\r
-                               sp_ptr->evd_handle = NULL;\r
-                       }\r
-                       sp_ptr->state = DAPL_SP_STATE_FREE;\r
-                       dapl_os_unlock(&sp_ptr->header.lock);\r
-                       (void)dapls_ib_remove_conn_listener(sp_ptr->header.\r
-                                                           owner_ia, sp_ptr);\r
-                       dapls_ia_unlink_sp((DAPL_IA *) sp_ptr->header.owner_ia,\r
-                                          sp_ptr);\r
-                       dapls_sp_free_sp(sp_ptr);\r
-                       dapls_cr_free(cr_ptr);\r
-                       goto skip_unlock;\r
-               }\r
-\r
-               dapl_os_unlock(&sp_ptr->header.lock);\r
-               /* free memory outside of the lock */\r
-               dapls_cr_free(cr_ptr);\r
-       } else {\r
-               dapl_os_unlock(&sp_ptr->header.lock);\r
-       }\r
-\r
-      skip_unlock:\r
-       return ep_ptr;\r
-}\r
-\r
-/*\r
- * Local variables:\r
- *  c-indent-level: 4\r
- *  c-basic-offset: 4\r
- *  c-brace-offset: -4\r
- *  tab-width: 8\r
- * End:\r
- */\r
+/*
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ *
+ * MODULE: dapls_cr_callback.c
+ *
+ * PURPOSE: implements passive side connection callbacks
+ *
+ * Description: Accepts asynchronous callbacks from the Communications Manager
+ *              for EVDs that have been specified as the connection_evd.
+ *
+ * $Id:$
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_evd_util.h"
+#include "dapl_cr_util.h"
+#include "dapl_ia_util.h"
+#include "dapl_sp_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_adapter_util.h"
+
+/*
+ * Prototypes
+ */
+DAT_RETURN dapli_connection_request(IN dp_ib_cm_handle_t ib_cm_handle,
+                                   IN DAPL_SP * sp_ptr,
+                                   IN DAPL_PRIVATE * prd_ptr,
+                                   IN int private_data_size,
+                                   IN DAPL_EVD * evd_ptr);
+
+DAPL_EP *dapli_get_sp_ep(IN dp_ib_cm_handle_t ib_cm_handle,
+                        IN DAPL_SP * sp_ptr,
+                        IN DAT_EVENT_NUMBER dat_event_num);
+
+/*
+ * dapls_cr_callback
+ *
+ * The callback function registered with verbs for passive side of
+ * connection requests. The interface is specified by cm_api.h
+ *
+ *
+ * Input:
+ *     ib_cm_handle,           Handle to CM
+ *     ib_cm_event             Specific CM event
+ *     instant_data            Private data with DAT ADDRESS header
+ *     context                 SP pointer
+ *
+ * Output:
+ *     None
+ *
+ */
+void dapls_cr_callback(IN dp_ib_cm_handle_t ib_cm_handle, IN const ib_cm_events_t ib_cm_event,
+                       IN const void *private_data_ptr, IN const int private_data_size,
+                       IN const void *context)
+{
+       DAPL_EP *ep_ptr;
+       DAPL_EVD *evd_ptr;
+       DAPL_SP *sp_ptr;
+       DAPL_PRIVATE *prd_ptr;
+       DAT_EVENT_NUMBER dat_event_num;
+       DAT_RETURN dat_status;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+                    "--> dapl_cr_callback! context: %p event: %x cm_handle %p\n",
+                    context, ib_cm_event, (void *)ib_cm_handle);
+
+       /*
+        * Passive side of the connection, context is a SP and
+        * we need to look up the EP.
+        */
+       sp_ptr = (DAPL_SP *) context;
+       /*
+        * The context pointer could have been cleaned up in a racing
+        * CM callback, check to see if we should just exit here
+        */
+       if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) {
+               return;
+       }
+       dapl_os_assert(sp_ptr->header.magic == DAPL_MAGIC_PSP ||
+                      sp_ptr->header.magic == DAPL_MAGIC_RSP);
+
+       /* Obtain the event number from the provider layer */
+       dat_event_num = dapls_ib_get_dat_event(ib_cm_event, DAT_FALSE);
+
+       /*
+        * CONNECT_REQUEST events create an event on the PSP
+        * EVD, which will trigger connection processing. The
+        * sequence is:
+        *    CONNECT_REQUEST         Event to SP
+        *    CONNECTED               Event to EP
+        *    DISCONNECT              Event to EP
+        *
+        * Obtain the EP if required and set an event up on the correct
+        * EVD.
+        */
+       if (dat_event_num == DAT_CONNECTION_REQUEST_EVENT) {
+               ep_ptr = NULL;
+               evd_ptr = sp_ptr->evd_handle;
+       } else {
+               /* see if there is an EP connected with this CM handle */
+               ep_ptr = dapli_get_sp_ep(ib_cm_handle, sp_ptr, dat_event_num);
+
+               /* if we lost a race with the CM just exit. */
+               if (ep_ptr == NULL) {
+                       return;
+               }
+
+               evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;
+               /* if something has happened to our EVD, bail. */
+               if (evd_ptr == NULL) {
+                       return;
+               }
+       }
+
+       prd_ptr = (DAPL_PRIVATE *) private_data_ptr;
+
+       dat_status = DAT_INTERNAL_ERROR;        /* init to ERR */
+
+       switch (dat_event_num) {
+       case DAT_CONNECTION_REQUEST_EVENT:
+               {
+                       /*
+                        * Requests arriving on a disabled SP are immediatly rejected
+                        */
+
+                       dapl_os_lock(&sp_ptr->header.lock);
+                       if (sp_ptr->listening == DAT_FALSE) {
+                               dapl_os_unlock(&sp_ptr->header.lock);
+                               dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                                            "---> dapls_cr_callback: conn event on down SP\n");
+                               (void)dapls_ib_reject_connection(ib_cm_handle,
+                                                                DAT_CONNECTION_EVENT_UNREACHABLE,
+                                                                0, NULL);
+
+                               return;
+                       }
+
+                       if (sp_ptr->header.handle_type == DAT_HANDLE_TYPE_RSP) {
+                               /*
+                                * RSP connections only allow a single connection. Close
+                                * it down NOW so we reject any further connections.
+                                */
+                               sp_ptr->listening = DAT_FALSE;
+                       }
+                       dapl_os_unlock(&sp_ptr->header.lock);
+
+                       /*
+                        * Only occurs on the passive side of a connection
+                        * dapli_connection_request will post the connection
+                        * event if appropriate.
+                        */
+                       dat_status = dapli_connection_request(ib_cm_handle,
+                                                             sp_ptr, prd_ptr, private_data_size, evd_ptr);
+                       /* Set evd_ptr = NULL so we don't generate an event below */
+                       evd_ptr = NULL;
+
+                       break;
+               }
+       case DAT_CONNECTION_EVENT_ESTABLISHED:
+               {
+                       /* This is just a notification the connection is now
+                        * established, there isn't any private data to deal with.
+                        *
+                        * Update the EP state and cache a copy of the cm handle,
+                        * then let the user know we are ready to go.
+                        */
+                       dapl_os_lock(&ep_ptr->header.lock);
+                       if (ep_ptr->header.magic != DAPL_MAGIC_EP ||
+                           ep_ptr->param.ep_state !=
+                           DAT_EP_STATE_COMPLETION_PENDING) {
+                               /* If someone pulled the plug on the EP or connection,
+                                * just exit
+                                */
+                               dapl_os_unlock(&ep_ptr->header.lock);
+                               dat_status = DAT_SUCCESS;
+                               /* Set evd_ptr = NULL so we don't generate an event below */
+                               evd_ptr = NULL;
+
+                               break;
+                       }
+
+                       ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       case DAT_CONNECTION_EVENT_DISCONNECTED:
+               {
+                       /*
+                        * EP is now fully disconnected; initiate any post processing
+                        * to reset the underlying QP and get the EP ready for
+                        * another connection
+                        */
+                       dapl_os_lock(&ep_ptr->header.lock);
+                       if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED) {
+                               /* The disconnect has already occurred, we are now
+                                * cleaned up and ready to exit
+                                */
+                               dapl_os_unlock(&ep_ptr->header.lock);
+                               return;
+                       }
+                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
+                                                 ib_cm_event);
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:
+       case DAT_CONNECTION_EVENT_PEER_REJECTED:
+       case DAT_CONNECTION_EVENT_UNREACHABLE:
+               {
+                       /*
+                        * After posting an accept the requesting node has
+                        * stopped talking.
+                        */
+                       dapl_os_lock(&ep_ptr->header.lock);
+                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
+                                                 ib_cm_event);
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       case DAT_CONNECTION_EVENT_BROKEN:
+               {
+                       dapl_os_lock(&ep_ptr->header.lock);
+                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
+                                                 ib_cm_event);
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       default:
+               {
+                       evd_ptr = NULL;
+                       dapl_os_assert(0);      /* shouldn't happen */
+                       break;
+               }
+       }
+
+       if (evd_ptr != NULL) {
+               dat_status = dapls_evd_post_connection_event(evd_ptr,
+                                                            dat_event_num,
+                                                            (DAT_HANDLE)
+                                                            ep_ptr, 0, NULL);
+       }
+
+       if (dat_status != DAT_SUCCESS) {
+               /* The event post failed; take appropriate action.  */
+               (void)dapls_ib_reject_connection(ib_cm_handle,
+                                                DAT_CONNECTION_EVENT_BROKEN,
+                                                0, NULL);
+
+               return;
+       }
+}
+
+/*
+ * dapli_connection_request
+ *
+ * Process a connection request on the Passive side of a connection.
+ * Create a CR record and link it on to the SP so we can update it
+ * and free it later. Create an EP if specified by the PSP flags.
+ *
+ * Input:
+ *     ib_cm_handle,
+ *     sp_ptr
+ *     event_ptr
+ *     prd_ptr
+ *
+ * Output:
+ *     None
+ *
+ * Returns
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_SUCCESS
+ *
+ */
+DAT_RETURN
+dapli_connection_request(IN dp_ib_cm_handle_t ib_cm_handle,
+                        IN DAPL_SP * sp_ptr,
+                        IN DAPL_PRIVATE * prd_ptr, IN int private_data_size,
+                        IN DAPL_EVD * evd_ptr)
+{
+       DAT_RETURN dat_status;
+
+       DAPL_CR *cr_ptr;
+       DAPL_EP *ep_ptr;
+       DAPL_IA *ia_ptr;
+       DAT_SP_HANDLE sp_handle;
+
+       cr_ptr = dapls_cr_alloc(sp_ptr->header.owner_ia);
+       if (cr_ptr == NULL) {
+               /* Invoking function will call dapls_ib_cm_reject() */
+               return DAT_INSUFFICIENT_RESOURCES;
+       }
+
+       /*
+        * Set up the CR
+        */
+       cr_ptr->sp_ptr = sp_ptr;        /* maintain sp_ptr in case of reject */
+       cr_ptr->param.remote_port_qual = 0;
+       cr_ptr->ib_cm_handle = ib_cm_handle;
+#ifdef IBHOSTS_NAMING
+       /*
+        * Special case: pull the remote HCA address from the private data
+        * prefix. This is a spec violation as it introduces a protocol, but
+        * some implementations may find it necessary for a time.
+        */
+       cr_ptr->remote_ia_address = prd_ptr->hca_address;
+#endif                         /* IBHOSTS_NAMING */
+       cr_ptr->param.remote_ia_address_ptr =
+           (DAT_IA_ADDRESS_PTR) & cr_ptr->remote_ia_address;
+       /*
+        * Copy the remote address and private data out of the private_data
+        * payload and put them in a local structure
+        */
+
+       /* Private data size will be determined by the provider layer */
+       cr_ptr->param.private_data = cr_ptr->private_data;
+       cr_ptr->param.private_data_size = private_data_size;
+       if (cr_ptr->param.private_data_size > 0) {
+               dapl_os_memcpy(cr_ptr->private_data,
+                              prd_ptr->private_data,
+                              DAPL_MIN(cr_ptr->param.private_data_size,
+                                       DAPL_MAX_PRIVATE_DATA_SIZE));
+       }
+
+       /* EP will be NULL unless RSP service point */
+       ep_ptr = (DAPL_EP *) sp_ptr->ep_handle;
+
+       if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {
+               /*
+                * Never true for RSP connections
+                *
+                * Create an EP for the user. If we can't allocate an
+                * EP we are out of resources and need to tell the
+                * requestor that we cant help them.
+                */
+               ia_ptr = sp_ptr->header.owner_ia;
+               ep_ptr = dapl_ep_alloc(ia_ptr, NULL);
+               if (ep_ptr == NULL) {
+                       dapls_cr_free(cr_ptr);
+                       /* Invoking function will call dapls_ib_cm_reject() */
+                       return DAT_INSUFFICIENT_RESOURCES;
+               }
+               ep_ptr->param.ia_handle = ia_ptr;
+               ep_ptr->param.local_ia_address_ptr =
+                   (DAT_IA_ADDRESS_PTR) & ia_ptr->hca_ptr->hca_address;
+
+               /* Link the EP onto the IA */
+               dapl_ia_link_ep(ia_ptr, ep_ptr);
+       }
+
+       cr_ptr->param.local_ep_handle = ep_ptr;
+
+       if (ep_ptr != NULL) {
+               /* Assign valid EP fields: RSP and PSP_PROVIDER_FLAG only */
+               if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {
+                       ep_ptr->param.ep_state =
+                           DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING;
+               } else {
+                       /* RSP */
+                       dapl_os_assert(sp_ptr->header.handle_type ==
+                                      DAT_HANDLE_TYPE_RSP);
+                       ep_ptr->param.ep_state =
+                           DAT_EP_STATE_PASSIVE_CONNECTION_PENDING;
+               }
+               dapl_ep_link_cm(ep_ptr, ib_cm_handle);
+       }
+
+       /* link the CR onto the SP so we can pick it up later */
+       dapl_sp_link_cr(sp_ptr, cr_ptr);
+
+       /* Post the event.  */
+       /* assign sp_ptr to union to avoid typecast errors from some compilers */
+       sp_handle.psp_handle = (DAT_PSP_HANDLE) sp_ptr;
+
+       dat_status = dapls_evd_post_cr_arrival_event(evd_ptr,
+                                                    DAT_CONNECTION_REQUEST_EVENT,
+                                                    sp_handle,
+                                                    (DAT_IA_ADDRESS_PTR)
+                                                    & sp_ptr->header.owner_ia->
+                                                    hca_ptr->hca_address,
+                                                    sp_ptr->conn_qual,
+                                                    (DAT_CR_HANDLE) cr_ptr);
+
+       if (dat_status != DAT_SUCCESS) {
+               dapls_cr_free(cr_ptr);
+               (void)dapls_ib_reject_connection(ib_cm_handle,
+                                                DAT_CONNECTION_EVENT_BROKEN,
+                                                0, NULL);
+
+               /* Take the CR off the list, we can't use it */
+               dapl_os_lock(&sp_ptr->header.lock);
+               dapl_sp_remove_cr(sp_ptr, cr_ptr);
+               dapl_os_unlock(&sp_ptr->header.lock);
+               return DAT_INSUFFICIENT_RESOURCES;
+       }
+
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapli_get_sp_ep
+ *
+ * Passive side of a connection is now fully established. Clean
+ * up resources and obtain the EP pointer associated with a CR in
+ * the SP
+ *
+ * Input:
+ *     ib_cm_handle,
+ *     sp_ptr
+ *     connection_event
+ *
+ * Output:
+ *     none
+ *
+ * Returns
+ *     ep_ptr
+ *
+ */
+DAPL_EP *dapli_get_sp_ep(IN dp_ib_cm_handle_t ib_cm_handle,
+                        IN DAPL_SP * sp_ptr, IN DAT_EVENT_NUMBER dat_event_num)
+{
+       DAPL_CR *cr_ptr;
+       DAPL_EP *ep_ptr;
+
+       /*
+        * acquire the lock, we may be racing with other threads here
+        */
+       dapl_os_lock(&sp_ptr->header.lock);
+
+       /* Verify under lock that the SP is still valid */
+       if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) {
+               dapl_os_unlock(&sp_ptr->header.lock);
+               return NULL;
+       }
+       /*
+        * There are potentially multiple connections in progress. Need to
+        * go through the list and find the one we are interested
+        * in. There is no guarantee of order. dapl_sp_search_cr
+        * leaves the CR on the SP queue.
+        */
+       cr_ptr = dapl_sp_search_cr(sp_ptr, ib_cm_handle);
+       if (cr_ptr == NULL) {
+               dapl_os_unlock(&sp_ptr->header.lock);
+               return NULL;
+       }
+
+       ep_ptr = (DAPL_EP *) cr_ptr->param.local_ep_handle;
+
+       /* Quick check to ensure our EP is still valid */
+       if ((DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP))) {
+               ep_ptr = NULL;
+       }
+
+       /* The CR record is discarded in all except for the CONNECTED case,
+        * as it will have no further relevance.
+        */
+       if (dat_event_num != DAT_CONNECTION_EVENT_ESTABLISHED) {
+               /* Remove the CR from the queue */
+               dapl_sp_remove_cr(sp_ptr, cr_ptr);
+
+               if (ep_ptr != NULL) {
+                       ep_ptr->cr_ptr = NULL;
+               }
+
+               /*
+                * If this SP has been removed from service, free it
+                * up after the last CR is removed
+                */
+               if (sp_ptr->listening != DAT_TRUE && sp_ptr->cr_list_count == 0
+                   && sp_ptr->state != DAPL_SP_STATE_FREE) {
+                       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                                    "--> dapli_get_sp_ep! disconnect dump sp: %p \n",
+                                    sp_ptr);
+                       /* Decrement the ref count on the EVD */
+                       if (sp_ptr->evd_handle) {
+                               dapl_os_atomic_dec(&
+                                                  ((DAPL_EVD *) sp_ptr->
+                                                   evd_handle)->evd_ref_count);
+                               sp_ptr->evd_handle = NULL;
+                       }
+                       sp_ptr->state = DAPL_SP_STATE_FREE;
+                       dapl_os_unlock(&sp_ptr->header.lock);
+                       (void)dapls_ib_remove_conn_listener(sp_ptr->header.
+                                                           owner_ia, sp_ptr);
+                       dapls_ia_unlink_sp((DAPL_IA *) sp_ptr->header.owner_ia,
+                                          sp_ptr);
+                       dapls_sp_free_sp(sp_ptr);
+                       dapls_cr_free(cr_ptr);
+                       goto skip_unlock;
+               }
+
+               dapl_os_unlock(&sp_ptr->header.lock);
+               /* free memory outside of the lock */
+               dapls_cr_free(cr_ptr);
+       } else {
+               dapl_os_unlock(&sp_ptr->header.lock);
+       }
+
+      skip_unlock:
+       return ep_ptr;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  c-brace-offset: -4
+ *  tab-width: 8
+ * End:
+ */
index 39b61addafa636b8d419767b533e056a5855e43c..2479479cc739aa020f4b4d9875489746f1cd54eb 100644 (file)
-/*
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- *    copy of which is available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/**********************************************************************
- * 
- * MODULE: dapl_cr_util.c
- *
- * PURPOSE: Manage CR (Connection Request) structure
- *
- * $Id:$
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_cr_util.h"
-
-/*
- * dapls_cr_create
- *
- * Create a CR. Part of the passive side of a connection
- *
- * Input:
- *     ia_ptr
- *
- * Returns:
- *     DAPL_CR
- *
- */
-
-DAPL_CR *dapls_cr_alloc(DAPL_IA * ia_ptr)
-{
-       DAPL_CR *cr_ptr;
-
-       /* Allocate EP */
-       cr_ptr = (DAPL_CR *) dapl_os_alloc(sizeof(DAPL_CR));
-       if (cr_ptr == NULL) {
-               return (NULL);
-       }
-
-       /* zero the structure */
-       dapl_os_memzero(cr_ptr, sizeof(DAPL_CR));
-
-       /*
-        * initialize the header
-        */
-       cr_ptr->header.provider = ia_ptr->header.provider;
-       cr_ptr->header.magic = DAPL_MAGIC_CR;
-       cr_ptr->header.handle_type = DAT_HANDLE_TYPE_CR;
-       cr_ptr->header.owner_ia = ia_ptr;
-       cr_ptr->header.user_context.as_64 = 0;
-       cr_ptr->header.user_context.as_ptr = NULL;
-       dapl_llist_init_entry(&cr_ptr->header.ia_list_entry);
-       dapl_os_lock_init(&cr_ptr->header.lock);
-
-       return (cr_ptr);
-}
-
-/*
- * dapls_cr_free
- *
- * Free the passed in EP structure.
- *
- * Input:
- *     entry point pointer
- *
- * Output:
- *     none
- *
- * Returns:
- *     none
- *
- */
-void dapls_cr_free(IN DAPL_CR * cr_ptr)
-{
-       dapl_os_assert(cr_ptr->header.magic == DAPL_MAGIC_CR ||
-                      cr_ptr->header.magic == DAPL_MAGIC_CR_DESTROYED);
-
-       cr_ptr->header.magic = DAPL_MAGIC_INVALID;      /* reset magic to prevent reuse */
-       dapl_os_free(cr_ptr, sizeof(DAPL_CR));
-}
+/*\r
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ *    available from the Open Source Initiative, see\r
+ *    http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is\r
+ *    available from the Open Source Initiative, see\r
+ *    http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
+ *    copy of which is available from the Open Source Initiative, see\r
+ *    http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_cr_util.c\r
+ *\r
+ * PURPOSE: Manage CR (Connection Request) structure\r
+ *\r
+ * $Id:$\r
+ **********************************************************************/\r
+\r
+#include "dapl.h"\r
+#include "dapl_cr_util.h"\r
+\r
+/*\r
+ * dapls_cr_create\r
+ *\r
+ * Create a CR. Part of the passive side of a connection\r
+ *\r
+ * Input:\r
+ *     ia_ptr\r
+ *\r
+ * Returns:\r
+ *     DAPL_CR\r
+ *\r
+ */\r
+\r
+DAPL_CR *dapls_cr_alloc(DAPL_IA * ia_ptr)\r
+{\r
+       DAPL_CR *cr_ptr;\r
+\r
+       /* Allocate EP */\r
+       cr_ptr = (DAPL_CR *) dapl_os_alloc(sizeof(DAPL_CR));\r
+       if (cr_ptr == NULL) {\r
+               return (NULL);\r
+       }\r
+\r
+       /* zero the structure */\r
+       dapl_os_memzero(cr_ptr, sizeof(DAPL_CR));\r
+\r
+       /*\r
+        * initialize the header\r
+        */\r
+       cr_ptr->header.provider = ia_ptr->header.provider;\r
+       cr_ptr->header.magic = DAPL_MAGIC_CR;\r
+       cr_ptr->header.handle_type = DAT_HANDLE_TYPE_CR;\r
+       cr_ptr->header.owner_ia = ia_ptr;\r
+       cr_ptr->header.user_context.as_64 = 0;\r
+       cr_ptr->header.user_context.as_ptr = NULL;\r
+       dapl_llist_init_entry(&cr_ptr->header.ia_list_entry);\r
+       dapl_os_lock_init(&cr_ptr->header.lock);\r
+\r
+       return (cr_ptr);\r
+}\r
+\r
+/*\r
+ * dapls_cr_free\r
+ *\r
+ * Free the passed in CR structure.\r
+ *\r
+ * Input:\r
+ *     entry point pointer\r
+ *\r
+ * Output:\r
+ *     none\r
+ *\r
+ * Returns:\r
+ *     none\r
+ *\r
+ */\r
+void dapls_cr_free(IN DAPL_CR * cr_ptr)\r
+{\r
+       dapl_os_assert(cr_ptr->header.magic == DAPL_MAGIC_CR ||\r
+                      cr_ptr->header.magic == DAPL_MAGIC_CR_DESTROYED);\r
+\r
+       cr_ptr->header.magic = DAPL_MAGIC_INVALID;      /* reset magic to prevent reuse */\r
+       dapl_os_free(cr_ptr, sizeof(DAPL_CR));\r
+}\r
index 27bcca9b3901227ccac6ff0285f5a2f5bd52f3fd..cec980ffbabf5b83418d4599282b07d3828dc770 100644 (file)
@@ -1,59 +1,59 @@
-/*\r
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- * \r
- * HEADER: dapl_cr_util.h\r
- *\r
- * PURPOSE: Utility defs & routines for the CR data structure\r
- *\r
- * $Id:$\r
- *\r
- **********************************************************************/\r
-\r
-#ifndef _DAPL_CR_UTIL_H_\r
-#define _DAPL_CR_UTIL_H_\r
-\r
-#include "dapl.h" \r
-\r
-DAPL_CR        *\r
-dapls_cr_alloc (\r
-       DAPL_IA         *ia_ptr );\r
-\r
-void\r
-dapls_cr_free (\r
-       IN DAPL_CR              *cr_ptr );\r
-\r
-void\r
-dapls_cr_callback (\r
-    IN    dp_ib_cm_handle_t     ib_cm_handle,\r
-    IN    const ib_cm_events_t  ib_cm_event,\r
-    IN   const void            *private_data_ptr,\r
-    IN    const int            private_data_size,\r
-    IN    const void           *context);\r
-\r
-#endif /* _DAPL_CR_UTIL_H_ */\r
+/*
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ * 
+ * HEADER: dapl_cr_util.h
+ *
+ * PURPOSE: Utility defs & routines for the CR data structure
+ *
+ * $Id:$
+ *
+ **********************************************************************/
+
+#ifndef _DAPL_CR_UTIL_H_
+#define _DAPL_CR_UTIL_H_
+
+#include "dapl.h" 
+
+DAPL_CR        *
+dapls_cr_alloc (
+       DAPL_IA         *ia_ptr );
+
+void
+dapls_cr_free (
+       IN DAPL_CR              *cr_ptr );
+
+void
+dapls_cr_callback (
+    IN    dp_ib_cm_handle_t     ib_cm_handle,
+    IN    const ib_cm_events_t  ib_cm_event,
+    IN   const void            *private_data_ptr,
+    IN    const int            private_data_size,
+    IN    const void           *context);
+
+#endif /* _DAPL_CR_UTIL_H_ */
index a14785bdeae577e6f42b79cc3505a10fd23e44fc..1f193ae31953c9c6381e4b53674fb43438d1dc9d 100644 (file)
-/*\r
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- *\r
- * MODULE: dapl_ep_connect.c\r
- *\r
- * PURPOSE: Endpoint management\r
- *\r
- * $Id:$\r
- **********************************************************************/\r
-\r
-#include "dapl.h"\r
-#include "dapl_ep_util.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_timer_util.h"\r
-\r
-/*\r
- * dapl_ep_connect\r
- *\r
- * Request a connection be established between the local Endpoint\r
- * and a remote Endpoint. This operation is used by the active/client\r
- * side of a connection\r
- *\r
- * Input:\r
- *     ep_handle\r
- *     remote_ia_address\r
- *     remote_conn_qual\r
- *     timeout\r
- *     private_data_size\r
- *     privaet_data\r
- *     qos\r
- *     connect_flags\r
- *\r
- * Output:\r
- *     None\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOUCRES\r
- *     DAT_INVALID_PARAMETER\r
- *     DAT_MODLE_NOT_SUPPORTED\r
- */\r
-DAT_RETURN DAT_API\r
-dapl_ep_connect(IN DAT_EP_HANDLE ep_handle,\r
-               IN DAT_IA_ADDRESS_PTR remote_ia_address,\r
-               IN DAT_CONN_QUAL remote_conn_qual,\r
-               IN DAT_TIMEOUT timeout,\r
-               IN DAT_COUNT private_data_size,\r
-               IN const DAT_PVOID private_data,\r
-               IN DAT_QOS qos, IN DAT_CONNECT_FLAGS connect_flags)\r
-{\r
-       DAPL_EP *ep_ptr;\r
-       DAPL_EP alloc_ep;\r
-       DAT_RETURN dat_status;\r
-       DAT_COUNT req_hdr_size;\r
-       void *private_data_ptr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,\r
-                    "dapl_ep_connect (%p, {%u.%u.%u.%u}, %X, %d, %d, %p, %x, %x)\n",\r
-                    ep_handle,\r
-                    remote_ia_address->sa_data[2],\r
-                    remote_ia_address->sa_data[3],\r
-                    remote_ia_address->sa_data[4],\r
-                    remote_ia_address->sa_data[5],\r
-                    remote_conn_qual,\r
-                    timeout,\r
-                    private_data_size, private_data, qos, connect_flags);\r
-\r
-       dat_status = DAT_SUCCESS;\r
-       ep_ptr = (DAPL_EP *) ep_handle;\r
-\r
-       /*\r
-        * Verify parameter & state. The connection handle must be good\r
-        * at this point.\r
-        */\r
-       if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) {\r
-               dat_status =\r
-                   DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);\r
-               goto bail;\r
-       }\r
-\r
-       if (DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)) {\r
-               dat_status =\r
-                   DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CONN);\r
-               goto bail;\r
-       }\r
-\r
-       /* Can't do a connection in 0 time, reject outright */\r
-       if (timeout == 0) {\r
-               dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);\r
-               goto bail;\r
-       }\r
-       DAPL_CNTR(ep_ptr, DCNT_EP_CONNECT);\r
-\r
-       /*\r
-        * If the endpoint needs a QP, associated the QP with it.\r
-        * This needs to be done carefully, in order to:\r
-        *  * Avoid allocating under a lock.\r
-        *  * Not step on data structures being altered by\r
-        *    routines with which we are racing.\r
-        * So we:\r
-        *  * Confirm that a new QP is needed and is not forbidden by the\r
-        *    current state.\r
-        *  * Allocate it into a separate EP.\r
-        *  * Take the EP lock.\r
-        *  * Reconfirm that the EP is in a state where it needs a QP.\r
-        *  * Assign the QP and release the lock.\r
-        */\r
-       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {\r
-               if (ep_ptr->param.pz_handle == NULL\r
-                   || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ))\r
-               {\r
-                       dat_status =\r
-                           DAT_ERROR(DAT_INVALID_STATE,\r
-                                     DAT_INVALID_STATE_EP_NOTREADY);\r
-                       goto bail;\r
-               }\r
-               alloc_ep = *ep_ptr;\r
-\r
-               dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,\r
-                                              &alloc_ep, ep_ptr);\r
-               if (dat_status != DAT_SUCCESS) {\r
-                       dat_status =\r
-                           DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
-                                     DAT_RESOURCE_MEMORY);\r
-                       goto bail;\r
-               }\r
-\r
-               dapl_os_lock(&ep_ptr->header.lock);\r
-               /*\r
-                * PZ shouldn't have changed since we're only racing with\r
-                * dapl_cr_accept()\r
-                */\r
-               if (ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED) {\r
-                       /* Bail, cleaning up.  */\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-                       dat_status = dapls_ib_qp_free(ep_ptr->header.owner_ia,\r
-                                                     &alloc_ep);\r
-                       if (dat_status != DAT_SUCCESS) {\r
-                               dapl_dbg_log(DAPL_DBG_TYPE_WARN,\r
-                                            "ep_connect: ib_qp_free failed with %x\n",\r
-                                            dat_status);\r
-                       }\r
-                       dat_status =\r
-                           DAT_ERROR(DAT_INVALID_STATE,\r
-                                     dapls_ep_state_subtype(ep_ptr));\r
-                       goto bail;\r
-               }\r
-\r
-               ep_ptr->qp_handle = alloc_ep.qp_handle;\r
-               ep_ptr->qpn = alloc_ep.qpn;\r
-               ep_ptr->qp_state = alloc_ep.qp_state;\r
-\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-       }\r
-\r
-       /*\r
-        * We do state checks and transitions under lock.\r
-        * The only code we're racing against is dapl_cr_accept.\r
-        */\r
-       dapl_os_lock(&ep_ptr->header.lock);\r
-\r
-       /*\r
-        * Verify the attributes of the EP handle before we connect it. Test\r
-        * all of the handles to make sure they are currently valid.\r
-        * Specifically:\r
-        *   pz_handle              required\r
-        *   recv_evd_handle        optional, but must be valid\r
-        *   request_evd_handle     optional, but must be valid\r
-        *   connect_evd_handle     required\r
-        */\r
-       if (ep_ptr->param.pz_handle == NULL\r
-           || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ)\r
-           /* test connect handle */\r
-           || ep_ptr->param.connect_evd_handle == NULL\r
-           || DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)\r
-           || !(((DAPL_EVD *) ep_ptr->param.connect_evd_handle)->\r
-                evd_flags & DAT_EVD_CONNECTION_FLAG)\r
-           /* test optional completion handles */\r
-           || (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL &&\r
-               (DAPL_BAD_HANDLE\r
-                (ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD)))\r
-           || (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL\r
-               &&\r
-               (DAPL_BAD_HANDLE\r
-                (ep_ptr->param.request_evd_handle, DAPL_MAGIC_EVD)))) {\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               dat_status =\r
-                   DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_EP_NOTREADY);\r
-               goto bail;\r
-       }\r
-\r
-       /* Check both the EP state and the QP state: if we don't have a QP\r
-        *  we need to attach one now.\r
-        */\r
-       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {\r
-               dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,\r
-                                              ep_ptr, ep_ptr);\r
-\r
-               if (dat_status != DAT_SUCCESS) {\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-                       dat_status =\r
-                           DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
-                                     DAT_RESOURCE_TEP);\r
-                       goto bail;\r
-               }\r
-       }\r
-\r
-       if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED &&\r
-           ep_ptr->param.ep_attr.service_type == DAT_SERVICE_TYPE_RC) {\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               dat_status =\r
-                   DAT_ERROR(DAT_INVALID_STATE,\r
-                             dapls_ep_state_subtype(ep_ptr));\r
-               goto bail;\r
-       }\r
-\r
-       if (qos != DAT_QOS_BEST_EFFORT ||\r
-           connect_flags != DAT_CONNECT_DEFAULT_FLAG) {\r
-               /*\r
-                * At this point we only support one QOS level\r
-                */\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               dat_status = DAT_ERROR(DAT_MODEL_NOT_SUPPORTED, 0);\r
-               goto bail;\r
-       }\r
-\r
-       /*\r
-        * Verify the private data size doesn't exceed the max\r
-        * req_hdr_size will evaluate to 0 unless IBHOSTS_NAMING is enabled.\r
-        */\r
-       req_hdr_size = (sizeof(DAPL_PRIVATE) - DAPL_MAX_PRIVATE_DATA_SIZE);\r
-\r
-       /* transition the state before requesting a connection to avoid\r
-        * race conditions\r
-        */\r
-       ep_ptr->param.ep_state = DAT_EP_STATE_ACTIVE_CONNECTION_PENDING;\r
-\r
-       /*\r
-        * At this point we're committed, and done with the endpoint\r
-        * except for the connect, so we can drop the lock.\r
-        */\r
-       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-#ifdef IBHOSTS_NAMING\r
-       /*\r
-        * Special case: put the remote HCA address into the private data\r
-        * prefix. This is a spec violation as it introduces a protocol, but\r
-        * some implementations may find it necessary for a time.\r
-        * Copy the private data into the EP area so the data is contiguous.\r
-        * If the provider needs to pad the buffer with NULLs, it happens at\r
-        * the provider layer.\r
-        */\r
-       dapl_os_memcpy(&ep_ptr->hca_address,\r
-                      &ep_ptr->header.owner_ia->hca_ptr->hca_address,\r
-                      sizeof(DAT_SOCK_ADDR));\r
-       dapl_os_memcpy(ep_ptr->private.private_data, private_data,\r
-                      private_data_size);\r
-       private_data_ptr = (void *)&ep_ptr->private.private_data;\r
-#else\r
-       private_data_ptr = private_data;\r
-#endif                         /* IBHOSTS_NAMING */\r
-\r
-       /* Copy the connection qualifiers */\r
-       dapl_os_memcpy(ep_ptr->param.remote_ia_address_ptr,\r
-                      remote_ia_address, sizeof(DAT_SOCK_ADDR));\r
-       ep_ptr->param.remote_port_qual = remote_conn_qual;\r
-\r
-       dat_status = dapls_ib_connect(ep_handle,\r
-                                     remote_ia_address,\r
-                                     remote_conn_qual,\r
-                                     private_data_size + req_hdr_size,\r
-                                     private_data_ptr);\r
-\r
-       if (dat_status != DAT_SUCCESS) {\r
-               ep_ptr->param.ep_state = DAT_EP_STATE_UNCONNECTED;\r
-\r
-               /*\r
-                * Some implementations provide us with an error code that the\r
-                * remote destination is unreachable, but DAT doesn't have a\r
-                * synchronous error code to communicate this. So the provider\r
-                * layer generates an INTERNAL_ERROR with a subtype; when\r
-                * this happens, return SUCCESS and generate the event\r
-                */\r
-               if (dat_status == DAT_ERROR(DAT_INTERNAL_ERROR, 1)) {\r
-                       dapls_evd_post_connection_event((DAPL_EVD *) ep_ptr->\r
-                                                       param.\r
-                                                       connect_evd_handle,\r
-                                                       DAT_CONNECTION_EVENT_UNREACHABLE,\r
-                                                       (DAT_HANDLE) ep_ptr, 0,\r
-                                                       0);\r
-                       dat_status = DAT_SUCCESS;\r
-               }\r
-       } else {\r
-               /*\r
-                * Acquire the lock and recheck the state of the EP; this\r
-                * thread could have been descheduled after issuing the connect\r
-                * request and the EP is now connected. Set up a timer if\r
-                * necessary.\r
-                */\r
-               dapl_os_lock(&ep_ptr->header.lock);\r
-               if (ep_ptr->param.ep_state ==\r
-                   DAT_EP_STATE_ACTIVE_CONNECTION_PENDING\r
-                   && timeout != DAT_TIMEOUT_INFINITE) {\r
-                       ep_ptr->cxn_timer =\r
-                           (DAPL_OS_TIMER *)\r
-                           dapl_os_alloc(sizeof(DAPL_OS_TIMER));\r
-\r
-                       dapls_timer_set(ep_ptr->cxn_timer,\r
-                                       dapls_ep_timeout, ep_ptr, timeout);\r
-               }\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-       }\r
-\r
-      bail:\r
-       dapl_dbg_log(DAPL_DBG_TYPE_RTN | DAPL_DBG_TYPE_CM,\r
-                    "dapl_ep_connect () returns 0x%x\n", dat_status);\r
-\r
-       return dat_status;\r
-}\r
-\r
-/*\r
- * dapl_ep_common_connect\r
- *\r
- * DAPL Requirements Version 2.0, 6.6.x\r
- *\r
- * Requests that a connection be established\r
- * between the local Endpoint and a remote Endpoint specified by the\r
- * remote_ia_address. This operation is used by the active/client side\r
- * Consumer of the Connection establishment model.\r
- *\r
- * EP must be properly configured for this operation. The EP Communicator\r
- * must be specified. As part of the successful completion of this operation,\r
- * the local Endpoint is bound to a local IA Address if it had these assigned\r
- * before.\r
- * \r
- * The local IP Address, port and protocol are passed to the remote side of\r
- * the requested connection and is available to the remote Consumer in the\r
- * Connection Request of the DAT_CONNECTION_REQUEST_EVENT.\r
- * \r
- * The Consumer-provided private_data is passed to the remote side and is\r
- * provided to the remote Consumer in the Connection Request. Consumers\r
- * can encapsulate any local Endpoint attributes that remote Consumers\r
- * need to know as part of an upper-level protocol.\r
- *\r
- * Input:\r
- *     ep_handle\r
- *     remote_ia_address\r
- *     timeout\r
- *     private_data_size\r
- *     private_date pointer\r
- *\r
- * Output:\r
- *     none\r
- * \r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INVALID_PARAMETER\r
- *     DAT_INVALID_HANDLE\r
- *     DAT_INVALID_STATE\r
- *     DAT_MODEL_NOT_SUPPORTED\r
- */\r
-DAT_RETURN DAT_API dapl_ep_common_connect(IN DAT_EP_HANDLE ep, /* ep_handle            */\r
-                                         IN DAT_IA_ADDRESS_PTR remote_addr,    /* remote_ia_address    */\r
-                                         IN DAT_TIMEOUT timeout,       /* timeout              */\r
-                                         IN DAT_COUNT pdata_size,      /* private_data_size    */\r
-                                         IN const DAT_PVOID pdata)\r
-{                              /* private_data         */\r
-       return DAT_MODEL_NOT_SUPPORTED;\r
-}\r
-\r
-/*\r
- * Local variables:\r
- *  c-indent-level: 4\r
- *  c-basic-offset: 4\r
- *  tab-width: 8\r
- * End:\r
- */\r
+/*
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ *
+ * MODULE: dapl_ep_connect.c
+ *
+ * PURPOSE: Endpoint management
+ *
+ * $Id:$
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_ep_util.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_timer_util.h"
+
+/*
+ * dapl_ep_connect
+ *
+ * Request a connection be established between the local Endpoint
+ * and a remote Endpoint. This operation is used by the active/client
+ * side of a connection
+ *
+ * Input:
+ *     ep_handle
+ *     remote_ia_address
+ *     remote_conn_qual
+ *     timeout
+ *     private_data_size
+ *     privaet_data
+ *     qos
+ *     connect_flags
+ *
+ * Output:
+ *     None
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOUCRES
+ *     DAT_INVALID_PARAMETER
+ *     DAT_MODLE_NOT_SUPPORTED
+ */
+DAT_RETURN DAT_API
+dapl_ep_connect(IN DAT_EP_HANDLE ep_handle,
+               IN DAT_IA_ADDRESS_PTR remote_ia_address,
+               IN DAT_CONN_QUAL remote_conn_qual,
+               IN DAT_TIMEOUT timeout,
+               IN DAT_COUNT private_data_size,
+               IN const DAT_PVOID private_data,
+               IN DAT_QOS qos, IN DAT_CONNECT_FLAGS connect_flags)
+{
+       DAPL_EP *ep_ptr;
+       DAPL_EP alloc_ep;
+       DAT_RETURN dat_status;
+       DAT_COUNT req_hdr_size;
+       void *private_data_ptr;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,
+                    "dapl_ep_connect (%p, {%u.%u.%u.%u}, %X, %d, %d, %p, %x, %x)\n",
+                    ep_handle,
+                    remote_ia_address->sa_data[2],
+                    remote_ia_address->sa_data[3],
+                    remote_ia_address->sa_data[4],
+                    remote_ia_address->sa_data[5],
+                    remote_conn_qual,
+                    timeout,
+                    private_data_size, private_data, qos, connect_flags);
+
+       dat_status = DAT_SUCCESS;
+       ep_ptr = (DAPL_EP *) ep_handle;
+
+       /*
+        * Verify parameter & state. The connection handle must be good
+        * at this point.
+        */
+       if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) {
+               dat_status =
+                   DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);
+               goto bail;
+       }
+
+       if (DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)) {
+               dat_status =
+                   DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CONN);
+               goto bail;
+       }
+
+       /* Can't do a connection in 0 time, reject outright */
+       if (timeout == 0) {
+               dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
+               goto bail;
+       }
+       DAPL_CNTR(ep_ptr, DCNT_EP_CONNECT);
+
+       /*
+        * If the endpoint needs a QP, associated the QP with it.
+        * This needs to be done carefully, in order to:
+        *  * Avoid allocating under a lock.
+        *  * Not step on data structures being altered by
+        *    routines with which we are racing.
+        * So we:
+        *  * Confirm that a new QP is needed and is not forbidden by the
+        *    current state.
+        *  * Allocate it into a separate EP.
+        *  * Take the EP lock.
+        *  * Reconfirm that the EP is in a state where it needs a QP.
+        *  * Assign the QP and release the lock.
+        */
+       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
+               if (ep_ptr->param.pz_handle == NULL
+                   || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ))
+               {
+                       dat_status =
+                           DAT_ERROR(DAT_INVALID_STATE,
+                                     DAT_INVALID_STATE_EP_NOTREADY);
+                       goto bail;
+               }
+               alloc_ep = *ep_ptr;
+
+               dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
+                                              &alloc_ep, ep_ptr);
+               if (dat_status != DAT_SUCCESS) {
+                       dat_status =
+                           DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
+                                     DAT_RESOURCE_MEMORY);
+                       goto bail;
+               }
+
+               dapl_os_lock(&ep_ptr->header.lock);
+               /*
+                * PZ shouldn't have changed since we're only racing with
+                * dapl_cr_accept()
+                */
+               if (ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED) {
+                       /* Bail, cleaning up.  */
+                       dapl_os_unlock(&ep_ptr->header.lock);
+                       dat_status = dapls_ib_qp_free(ep_ptr->header.owner_ia,
+                                                     &alloc_ep);
+                       if (dat_status != DAT_SUCCESS) {
+                               dapl_dbg_log(DAPL_DBG_TYPE_WARN,
+                                            "ep_connect: ib_qp_free failed with %x\n",
+                                            dat_status);
+                       }
+                       dat_status =
+                           DAT_ERROR(DAT_INVALID_STATE,
+                                     dapls_ep_state_subtype(ep_ptr));
+                       goto bail;
+               }
+
+               ep_ptr->qp_handle = alloc_ep.qp_handle;
+               ep_ptr->qpn = alloc_ep.qpn;
+               ep_ptr->qp_state = alloc_ep.qp_state;
+
+               dapl_os_unlock(&ep_ptr->header.lock);
+       }
+
+       /*
+        * We do state checks and transitions under lock.
+        * The only code we're racing against is dapl_cr_accept.
+        */
+       dapl_os_lock(&ep_ptr->header.lock);
+
+       /*
+        * Verify the attributes of the EP handle before we connect it. Test
+        * all of the handles to make sure they are currently valid.
+        * Specifically:
+        *   pz_handle              required
+        *   recv_evd_handle        optional, but must be valid
+        *   request_evd_handle     optional, but must be valid
+        *   connect_evd_handle     required
+        */
+       if (ep_ptr->param.pz_handle == NULL
+           || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ)
+           /* test connect handle */
+           || ep_ptr->param.connect_evd_handle == NULL
+           || DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)
+           || !(((DAPL_EVD *) ep_ptr->param.connect_evd_handle)->
+                evd_flags & DAT_EVD_CONNECTION_FLAG)
+           /* test optional completion handles */
+           || (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL &&
+               (DAPL_BAD_HANDLE
+                (ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD)))
+           || (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL
+               &&
+               (DAPL_BAD_HANDLE
+                (ep_ptr->param.request_evd_handle, DAPL_MAGIC_EVD)))) {
+               dapl_os_unlock(&ep_ptr->header.lock);
+               dat_status =
+                   DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_EP_NOTREADY);
+               goto bail;
+       }
+
+       /* Check both the EP state and the QP state: if we don't have a QP
+        *  we need to attach one now.
+        */
+       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
+               dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
+                                              ep_ptr, ep_ptr);
+
+               if (dat_status != DAT_SUCCESS) {
+                       dapl_os_unlock(&ep_ptr->header.lock);
+                       dat_status =
+                           DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
+                                     DAT_RESOURCE_TEP);
+                       goto bail;
+               }
+       }
+
+       if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED &&
+           ep_ptr->param.ep_attr.service_type == DAT_SERVICE_TYPE_RC) {
+               dapl_os_unlock(&ep_ptr->header.lock);
+               dat_status =
+                   DAT_ERROR(DAT_INVALID_STATE,
+                             dapls_ep_state_subtype(ep_ptr));
+               goto bail;
+       }
+
+       if (qos != DAT_QOS_BEST_EFFORT ||
+           connect_flags != DAT_CONNECT_DEFAULT_FLAG) {
+               /*
+                * At this point we only support one QOS level
+                */
+               dapl_os_unlock(&ep_ptr->header.lock);
+               dat_status = DAT_ERROR(DAT_MODEL_NOT_SUPPORTED, 0);
+               goto bail;
+       }
+
+       /*
+        * Verify the private data size doesn't exceed the max
+        * req_hdr_size will evaluate to 0 unless IBHOSTS_NAMING is enabled.
+        */
+       req_hdr_size = (sizeof(DAPL_PRIVATE) - DAPL_MAX_PRIVATE_DATA_SIZE);
+
+       /* transition the state before requesting a connection to avoid
+        * race conditions
+        */
+       ep_ptr->param.ep_state = DAT_EP_STATE_ACTIVE_CONNECTION_PENDING;
+
+       /*
+        * At this point we're committed, and done with the endpoint
+        * except for the connect, so we can drop the lock.
+        */
+       dapl_os_unlock(&ep_ptr->header.lock);
+
+#ifdef IBHOSTS_NAMING
+       /*
+        * Special case: put the remote HCA address into the private data
+        * prefix. This is a spec violation as it introduces a protocol, but
+        * some implementations may find it necessary for a time.
+        * Copy the private data into the EP area so the data is contiguous.
+        * If the provider needs to pad the buffer with NULLs, it happens at
+        * the provider layer.
+        */
+       dapl_os_memcpy(&ep_ptr->hca_address,
+                      &ep_ptr->header.owner_ia->hca_ptr->hca_address,
+                      sizeof(DAT_SOCK_ADDR));
+       dapl_os_memcpy(ep_ptr->private.private_data, private_data,
+                      private_data_size);
+       private_data_ptr = (void *)&ep_ptr->private.private_data;
+#else
+       private_data_ptr = private_data;
+#endif                         /* IBHOSTS_NAMING */
+
+       /* Copy the connection qualifiers */
+       dapl_os_memcpy(ep_ptr->param.remote_ia_address_ptr,
+                      remote_ia_address, sizeof(DAT_SOCK_ADDR));
+       ep_ptr->param.remote_port_qual = remote_conn_qual;
+
+       dat_status = dapls_ib_connect(ep_handle,
+                                     remote_ia_address,
+                                     remote_conn_qual,
+                                     private_data_size + req_hdr_size,
+                                     private_data_ptr);
+
+       if (dat_status != DAT_SUCCESS) {
+               ep_ptr->param.ep_state = DAT_EP_STATE_UNCONNECTED;
+
+               /*
+                * Some implementations provide us with an error code that the
+                * remote destination is unreachable, but DAT doesn't have a
+                * synchronous error code to communicate this. So the provider
+                * layer generates an INTERNAL_ERROR with a subtype; when
+                * this happens, return SUCCESS and generate the event
+                */
+               if (dat_status == DAT_ERROR(DAT_INTERNAL_ERROR, 1)) {
+                       dapls_evd_post_connection_event((DAPL_EVD *) ep_ptr->
+                                                       param.
+                                                       connect_evd_handle,
+                                                       DAT_CONNECTION_EVENT_UNREACHABLE,
+                                                       (DAT_HANDLE) ep_ptr, 0,
+                                                       0);
+                       dat_status = DAT_SUCCESS;
+               }
+       } else {
+               /*
+                * Acquire the lock and recheck the state of the EP; this
+                * thread could have been descheduled after issuing the connect
+                * request and the EP is now connected. Set up a timer if
+                * necessary.
+                */
+               dapl_os_lock(&ep_ptr->header.lock);
+               if (ep_ptr->param.ep_state ==
+                   DAT_EP_STATE_ACTIVE_CONNECTION_PENDING
+                   && timeout != DAT_TIMEOUT_INFINITE) {
+                       ep_ptr->cxn_timer =
+                           (DAPL_OS_TIMER *)
+                           dapl_os_alloc(sizeof(DAPL_OS_TIMER));
+
+                       dapls_timer_set(ep_ptr->cxn_timer,
+                                       dapls_ep_timeout, ep_ptr, timeout);
+
+                       dapl_log(DAPL_DBG_TYPE_WARN, " dapl_ep_connect timeout = %d us\n", timeout);
+               }
+               dapl_os_unlock(&ep_ptr->header.lock);
+       }
+
+      bail:
+       dapl_dbg_log(DAPL_DBG_TYPE_RTN | DAPL_DBG_TYPE_CM,
+                    "dapl_ep_connect () returns 0x%x\n", dat_status);
+
+       return dat_status;
+}
+
+/*
+ * dapl_ep_common_connect
+ *
+ * DAPL Requirements Version 2.0, 6.6.x
+ *
+ * Requests that a connection be established
+ * between the local Endpoint and a remote Endpoint specified by the
+ * remote_ia_address. This operation is used by the active/client side
+ * Consumer of the Connection establishment model.
+ *
+ * EP must be properly configured for this operation. The EP Communicator
+ * must be specified. As part of the successful completion of this operation,
+ * the local Endpoint is bound to a local IA Address if it had these assigned
+ * before.
+ * 
+ * The local IP Address, port and protocol are passed to the remote side of
+ * the requested connection and is available to the remote Consumer in the
+ * Connection Request of the DAT_CONNECTION_REQUEST_EVENT.
+ * 
+ * The Consumer-provided private_data is passed to the remote side and is
+ * provided to the remote Consumer in the Connection Request. Consumers
+ * can encapsulate any local Endpoint attributes that remote Consumers
+ * need to know as part of an upper-level protocol.
+ *
+ * Input:
+ *     ep_handle
+ *     remote_ia_address
+ *     timeout
+ *     private_data_size
+ *     private_date pointer
+ *
+ * Output:
+ *     none
+ * 
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INVALID_PARAMETER
+ *     DAT_INVALID_HANDLE
+ *     DAT_INVALID_STATE
+ *     DAT_MODEL_NOT_SUPPORTED
+ */
+DAT_RETURN DAT_API dapl_ep_common_connect(IN DAT_EP_HANDLE ep, /* ep_handle            */
+                                         IN DAT_IA_ADDRESS_PTR remote_addr,    /* remote_ia_address    */
+                                         IN DAT_TIMEOUT timeout,       /* timeout              */
+                                         IN DAT_COUNT pdata_size,      /* private_data_size    */
+                                         IN const DAT_PVOID pdata)
+{                              /* private_data         */
+       return DAT_MODEL_NOT_SUPPORTED;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
index fd9fcc7e3120c564145dc8cd6e119bab879f10b9..8708e6fc63cb4aa18e568286165bb489fa0663dc 100644 (file)
@@ -66,6 +66,7 @@ DAT_RETURN DAT_API dapl_ep_free(IN DAT_EP_HANDLE ep_handle)
        DAPL_EP *ep_ptr;
        DAPL_IA *ia_ptr;
        DAT_EP_PARAM *param;
+       dp_ib_cm_handle_t cm_ptr, next_cm_ptr;
        ib_qp_state_t save_qp_state;
        DAT_RETURN dat_status = DAT_SUCCESS;
 
@@ -187,6 +188,20 @@ DAT_RETURN DAT_API dapl_ep_free(IN DAT_EP_HANDLE ep_handle)
                }
        }
 
+       /* Free all CM objects */
+       cm_ptr = (dapl_llist_is_empty(&ep_ptr->cm_list_head)
+                 ? NULL : dapl_llist_peek_head(&ep_ptr->cm_list_head));
+       while (cm_ptr != NULL) {
+                dapl_log(DAPL_DBG_TYPE_EP,
+                        "dapl_ep_free: Free CM: EP=%p CM=%p\n",
+                        ep_ptr, cm_ptr);
+
+               next_cm_ptr = dapl_llist_next_entry(&ep_ptr->cm_list_head,
+                                                   &cm_ptr->list_entry);
+               dapls_cm_free(cm_ptr); /* blocking call */
+               cm_ptr = next_cm_ptr;
+       }
+
        /* Free the resource */
        dapl_ep_dealloc(ep_ptr);
 
index 48dee1ea45750aceee755a6081b0aeccb43f0d90..e6432b98992ce18de3bb977f9eca150ef0e72a2a 100644 (file)
@@ -141,6 +141,7 @@ DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr)
        ep_ptr->header.user_context.as_ptr = NULL;\r
 \r
        dapl_llist_init_entry(&ep_ptr->header.ia_list_entry);\r
+       dapl_llist_init_head(&ep_ptr->cm_list_head);\r
        dapl_os_lock_init(&ep_ptr->header.lock);\r
 \r
        /*\r
@@ -161,7 +162,6 @@ DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr)
        ep_ptr->qp_handle = IB_INVALID_HANDLE;\r
        ep_ptr->qpn = 0;\r
        ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;\r
-       ep_ptr->cm_handle = IB_INVALID_HANDLE;\r
 \r
        if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->req_buffer,\r
                                           ep_ptr,\r
@@ -214,13 +214,6 @@ void dapl_ep_dealloc(IN DAPL_EP * ep_ptr)
        if (NULL != ep_ptr->cxn_timer) {\r
                dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));\r
        }\r
-#if defined(_WIN32) || defined(_WIN64)\r
-       if (ep_ptr->ibal_cm_handle) {\r
-               dapl_os_free(ep_ptr->ibal_cm_handle,\r
-                            sizeof(*ep_ptr->ibal_cm_handle));\r
-               ep_ptr->ibal_cm_handle = NULL;\r
-       }\r
-#endif\r
 \r
 #ifdef DAPL_COUNTERS\r
        dapl_os_free(ep_ptr->cntrs, sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);\r
@@ -417,7 +410,7 @@ void dapls_ep_timeout(uintptr_t arg)
         * The disconnect_clean interface requires the provided dependent \r
         *cm event number.\r
         */\r
-       ib_cm_event = dapls_ib_get_cm_event(DAT_CONNECTION_EVENT_DISCONNECTED);\r
+       ib_cm_event = dapls_ib_get_cm_event(DAT_CONNECTION_EVENT_TIMED_OUT);\r
        dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);\r
 \r
        (void)dapls_evd_post_connection_event((DAPL_EVD *) ep_ptr->param.\r
@@ -537,6 +530,7 @@ dapl_ep_legacy_post_disconnect(DAPL_EP * ep_ptr,
 {\r
        ib_cm_events_t ib_cm_event;\r
        DAPL_CR *cr_ptr;\r
+       dp_ib_cm_handle_t cm_ptr;\r
 \r
        /*\r
         * Acquire the lock and make sure we didn't get a callback\r
@@ -557,6 +551,8 @@ dapl_ep_legacy_post_disconnect(DAPL_EP * ep_ptr,
                    dapls_ib_get_cm_event(DAT_CONNECTION_EVENT_DISCONNECTED);\r
 \r
                cr_ptr = ep_ptr->cr_ptr;\r
+               cm_ptr = (dapl_llist_is_empty(&ep_ptr->cm_list_head)\r
+                         ? NULL : dapl_llist_peek_head(&ep_ptr->cm_list_head));\r
                dapl_os_unlock(&ep_ptr->header.lock);\r
 \r
                if (cr_ptr != NULL) {\r
@@ -567,7 +563,7 @@ dapl_ep_legacy_post_disconnect(DAPL_EP * ep_ptr,
                        dapls_cr_callback(cr_ptr->ib_cm_handle,\r
                                          ib_cm_event, NULL, 0, cr_ptr->sp_ptr);\r
                } else {\r
-                       dapl_evd_connection_callback(ep_ptr->cm_handle,\r
+                       dapl_evd_connection_callback(cm_ptr,\r
                                                     ib_cm_event,\r
                                                     NULL, 0, (void *)ep_ptr);\r
                }\r
@@ -576,6 +572,40 @@ dapl_ep_legacy_post_disconnect(DAPL_EP * ep_ptr,
        }\r
 }\r
 \r
+/*\r
+ * dapl_ep_link_cm\r
+ *\r
+ * Add linking of provider's CM object to a EP structure\r
+ * This enables multiple CM's per EP, and syncronization\r
+ *\r
+ * Input:\r
+ *     DAPL_EP *ep_ptr\r
+ *     dp_ib_cm_handle_t *cm_ptr  defined in provider's dapl_util.h\r
+ *\r
+ *     CM objects linked with EP using  ->list_entry\r
+ * Output:\r
+ *     none\r
+ *\r
+ * Returns:\r
+ *     none\r
+ *\r
+ */\r
+void dapl_ep_link_cm(IN DAPL_EP *ep_ptr, IN dp_ib_cm_handle_t cm_ptr)\r
+{\r
+       dapl_os_lock(&ep_ptr->header.lock);\r
+       dapls_cm_acquire(cm_ptr);\r
+       dapl_llist_add_tail(&ep_ptr->cm_list_head, &cm_ptr->list_entry, cm_ptr);\r
+       dapl_os_unlock(&ep_ptr->header.lock);\r
+}\r
+\r
+void dapl_ep_unlink_cm(IN DAPL_EP *ep_ptr, IN dp_ib_cm_handle_t cm_ptr)\r
+{\r
+       dapl_os_lock(&ep_ptr->header.lock);\r
+       dapl_llist_remove_entry(&ep_ptr->cm_list_head, &cm_ptr->list_entry);\r
+       dapls_cm_release(cm_ptr);\r
+       dapl_os_unlock(&ep_ptr->header.lock);\r
+}\r
+\r
 /*\r
  * Local variables:\r
  *  c-indent-level: 4\r
index 7ac40614c42bac2be21a647460722f507fff1246..31d0e2333897ee33011392e0facb52b7c4a30167 100644 (file)
@@ -83,5 +83,23 @@ dapl_ep_legacy_post_disconnect(
     DAT_CLOSE_FLAGS    disconnect_flags);
 
 extern char *dapl_get_ep_state_str(DAT_EP_STATE state);
+
+extern void dapl_ep_link_cm(IN DAPL_EP *ep_ptr, 
+                           IN dp_ib_cm_handle_t cm_ptr);
+
+extern void dapl_ep_unlink_cm(IN DAPL_EP *ep_ptr, 
+                             IN dp_ib_cm_handle_t cm_ptr);
+
+STATIC _INLINE_ dp_ib_cm_handle_t dapl_get_cm_from_ep(IN DAPL_EP *ep_ptr)
+{
+       dp_ib_cm_handle_t cm_ptr;
+
+       dapl_os_lock(&ep_ptr->header.lock);
+       cm_ptr = (dapl_llist_is_empty(&ep_ptr->cm_list_head)
+                 ? NULL : dapl_llist_peek_head(&ep_ptr->cm_list_head));
+       dapl_os_unlock(&ep_ptr->header.lock);
+
+       return cm_ptr;
+}
  
 #endif /*  _DAPL_EP_UTIL_H_ */
index 841b28d03d1f4ed853c8e55469d790c687684507..3166702cb0c71fa2ef662bb8d4d9488d342cb52d 100644 (file)
-/*\r
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- *\r
- * MODULE: dapl_evd_connection_callback.c\r
- *\r
- * PURPOSE: implements connection callbacks\r
- *\r
- * Description: Accepts asynchronous callbacks from the Communications Manager\r
- *              for EVDs that have been specified as the connection_evd.\r
- *\r
- * $Id:$\r
- **********************************************************************/\r
-\r
-#include "dapl.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_ep_util.h"\r
-#include "dapl_timer_util.h"\r
-\r
-/*\r
- * dapl_evd_connection_callback\r
- *\r
- * Connection callback function for ACTIVE connection requests; callbacks\r
- * generated by the Connection Manager in response to issuing a\r
- * connect call.\r
- *\r
- * Input:\r
- *     ib_cm_handle,\r
- *     ib_cm_event\r
- *     private_data_ptr\r
- *     context (evd)\r
- *     cr_pp\r
- *\r
- * Output:\r
- *     None\r
- *\r
- */\r
-\r
-void\r
-dapl_evd_connection_callback(IN dp_ib_cm_handle_t ib_cm_handle,\r
-                            IN const ib_cm_events_t ib_cm_event,\r
-                            IN const void *private_data_ptr,\r
-                            IN const int private_data_size,\r
-                            IN const void *context)\r
-{\r
-       DAPL_EP *ep_ptr;\r
-       DAPL_EVD *evd_ptr;\r
-       DAPL_PRIVATE *prd_ptr;\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
-                    "--> dapl_evd_connection_callback: ctxt: %p event: %x cm_handle %p\n",\r
-                    context, ib_cm_event, (void *)ib_cm_handle);\r
-\r
-       /*\r
-        * Determine the type of handle passed back to us in the context\r
-        * and sort out key parameters.\r
-        */\r
-       if (context == NULL\r
-           || ((DAPL_HEADER *) context)->magic != DAPL_MAGIC_EP) {\r
-               return;\r
-       }\r
-\r
-       /*\r
-        * Active side of the connection, context is an EP and\r
-        * PSP is irrelevant.\r
-        */\r
-       ep_ptr = (DAPL_EP *) context;\r
-       evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;\r
-       DAPL_CNTR(evd_ptr, DCNT_EVD_CONN_CALLBACK);\r
-\r
-       prd_ptr = (DAPL_PRIVATE *) private_data_ptr;\r
-       /*\r
-        * All operations effect the EP, so lock it once and unlock\r
-        * when necessary\r
-        */\r
-       dapl_os_lock(&ep_ptr->header.lock);\r
-\r
-       /*\r
-        * If a connection timer has been set up on this EP, cancel it now\r
-        */\r
-       if (ep_ptr->cxn_timer != NULL) {\r
-               dapls_timer_cancel(ep_ptr->cxn_timer);\r
-               dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));\r
-               ep_ptr->cxn_timer = NULL;\r
-       }\r
-\r
-       /* Obtain the event number from the provider layer */\r
-       dat_event_num = dapls_ib_get_dat_event(ib_cm_event, DAT_FALSE);\r
-\r
-       switch (dat_event_num) {\r
-       case DAT_CONNECTION_EVENT_ESTABLISHED:\r
-               {\r
-                       /* If we don't have an EP at this point we are very screwed\r
-                        * up\r
-                        */\r
-                       if (ep_ptr->param.ep_state !=\r
-                           DAT_EP_STATE_ACTIVE_CONNECTION_PENDING) {\r
-                               /* If someone pulled the plug on the connection, just\r
-                                * exit\r
-                                */\r
-                               dapl_os_unlock(&ep_ptr->header.lock);\r
-                               dat_status = DAT_SUCCESS;\r
-                               break;\r
-                       }\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;\r
-                       ep_ptr->cm_handle = ib_cm_handle;\r
-\r
-                       if (private_data_size > 0) {\r
-                               /* copy in the private data */\r
-                               dapl_os_memcpy(ep_ptr->private.private_data,\r
-                                              prd_ptr->private_data,\r
-                                              DAPL_MIN(private_data_size,\r
-                                                       DAPL_MAX_PRIVATE_DATA_SIZE));\r
-                       }\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_EVENT_PEER_REJECTED:\r
-               {\r
-                       /* peer reject may include private data */\r
-\r
-                       if (private_data_size > 0)\r
-                               dapl_os_memcpy(ep_ptr->private.private_data,\r
-                                              prd_ptr->private_data,\r
-                                              DAPL_MIN(private_data_size,\r
-                                                       DAPL_MAX_PRIVATE_DATA_SIZE));\r
-\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
-                                    "dapl_evd_connection_callback PEER REJ pd=%p sz=%d\n",\r
-                                    prd_ptr, private_data_size);\r
-               }\r
-       case DAT_CONNECTION_EVENT_DISCONNECTED:\r
-       case DAT_CONNECTION_EVENT_UNREACHABLE:\r
-       case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:\r
-               {\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-                       dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE,\r
-                                                 ib_cm_event);\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_EVENT_BROKEN:\r
-       case DAT_CONNECTION_EVENT_TIMED_OUT:\r
-               {\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,\r
-                                                 ib_cm_event);\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-                       break;\r
-               }\r
-       case DAT_CONNECTION_REQUEST_EVENT:\r
-       default:\r
-               {\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-                       evd_ptr = NULL;\r
-\r
-                       dapl_os_assert(0);      /* shouldn't happen */\r
-                       break;\r
-               }\r
-       }\r
-\r
-       /*\r
-        * Post the event\r
-        * If the EP has been freed, the evd_ptr will be NULL\r
-        */\r
-       if (evd_ptr != NULL) {\r
-               dat_status = dapls_evd_post_connection_event(evd_ptr, dat_event_num, (DAT_HANDLE) ep_ptr, private_data_size,    /* CONNECTED or REJECT */\r
-                                                            ep_ptr->private.\r
-                                                            private_data);\r
-\r
-               if (dat_status != DAT_SUCCESS &&\r
-                   dat_event_num == DAT_CONNECTION_EVENT_ESTABLISHED) {\r
-                       /* We can't tell the user we are connected, something\r
-                        * is wrong locally. Just kill the connection and\r
-                        * reset the state to DISCONNECTED as we don't\r
-                        * expect a callback on an ABRUPT disconnect.\r
-                        */\r
-                       dapls_ib_disconnect(ep_ptr, DAT_CLOSE_ABRUPT_FLAG);\r
-                       dapl_os_lock(&ep_ptr->header.lock);\r
-                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-                       dapl_os_unlock(&ep_ptr->header.lock);\r
-               }\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
-                    "dapl_evd_connection_callback () returns\n");\r
-\r
-}\r
-\r
-/*\r
- * Local variables:\r
- *  c-indent-level: 4\r
- *  c-basic-offset: 4\r
- *  tab-width: 8\r
- * End:\r
- */\r
+/*
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ *
+ * MODULE: dapl_evd_connection_callback.c
+ *
+ * PURPOSE: implements connection callbacks
+ *
+ * Description: Accepts asynchronous callbacks from the Communications Manager
+ *              for EVDs that have been specified as the connection_evd.
+ *
+ * $Id:$
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_evd_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_timer_util.h"
+
+/*
+ * dapl_evd_connection_callback
+ *
+ * Connection callback function for ACTIVE connection requests; callbacks
+ * generated by the Connection Manager in response to issuing a
+ * connect call.
+ *
+ * Input:
+ *     ib_cm_handle,
+ *     ib_cm_event
+ *     private_data_ptr
+ *     context (evd)
+ *     cr_pp
+ *
+ * Output:
+ *     None
+ *
+ */
+
+void
+dapl_evd_connection_callback(IN dp_ib_cm_handle_t ib_cm_handle,
+                            IN const ib_cm_events_t ib_cm_event,
+                            IN const void *private_data_ptr,
+                            IN const int private_data_size,
+                            IN const void *context)
+{
+       DAPL_EP *ep_ptr;
+       DAPL_EVD *evd_ptr;
+       DAPL_PRIVATE *prd_ptr;
+       DAT_EVENT_NUMBER dat_event_num;
+       DAT_RETURN dat_status;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+                    "--> dapl_evd_connection_callback: ctxt: %p event: %x cm_handle %p\n",
+                    context, ib_cm_event, (void *)ib_cm_handle);
+
+       /*
+        * Determine the type of handle passed back to us in the context
+        * and sort out key parameters.
+        */
+       if (context == NULL
+           || ((DAPL_HEADER *) context)->magic != DAPL_MAGIC_EP) {
+               return;
+       }
+
+       /*
+        * Active side of the connection, context is an EP and
+        * PSP is irrelevant.
+        */
+       ep_ptr = (DAPL_EP *) context;
+       evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;
+       DAPL_CNTR(evd_ptr, DCNT_EVD_CONN_CALLBACK);
+
+       prd_ptr = (DAPL_PRIVATE *) private_data_ptr;
+       /*
+        * All operations effect the EP, so lock it once and unlock
+        * when necessary
+        */
+       dapl_os_lock(&ep_ptr->header.lock);
+
+       /*
+        * If a connection timer has been set up on this EP, cancel it now
+        */
+       if (ep_ptr->cxn_timer != NULL) {
+               dapls_timer_cancel(ep_ptr->cxn_timer);
+               dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));
+               ep_ptr->cxn_timer = NULL;
+       }
+
+       /* Obtain the event number from the provider layer */
+       dat_event_num = dapls_ib_get_dat_event(ib_cm_event, DAT_FALSE);
+
+       switch (dat_event_num) {
+       case DAT_CONNECTION_EVENT_ESTABLISHED:
+               {
+                       /* If we don't have an EP at this point we are very screwed
+                        * up
+                        */
+                       if (ep_ptr->param.ep_state !=
+                           DAT_EP_STATE_ACTIVE_CONNECTION_PENDING) {
+                               /* If someone pulled the plug on the connection, just
+                                * exit
+                                */
+                               dapl_os_unlock(&ep_ptr->header.lock);
+                               dat_status = DAT_SUCCESS;
+                               break;
+                       }
+                       ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;
+
+                       if (private_data_size > 0) {
+                               /* copy in the private data */
+                               dapl_os_memcpy(ep_ptr->private.private_data,
+                                              prd_ptr->private_data,
+                                              DAPL_MIN(private_data_size,
+                                                       DAPL_MAX_PRIVATE_DATA_SIZE));
+                       }
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       case DAT_CONNECTION_EVENT_PEER_REJECTED:
+               {
+                       /* peer reject may include private data */
+
+                       if (private_data_size > 0)
+                               dapl_os_memcpy(ep_ptr->private.private_data,
+                                              prd_ptr->private_data,
+                                              DAPL_MIN(private_data_size,
+                                                       DAPL_MAX_PRIVATE_DATA_SIZE));
+
+                       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+                                    "dapl_evd_connection_callback PEER REJ pd=%p sz=%d\n",
+                                    prd_ptr, private_data_size);
+               }
+       case DAT_CONNECTION_EVENT_DISCONNECTED:
+       case DAT_CONNECTION_EVENT_UNREACHABLE:
+       case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:
+               {
+                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+                       dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE,
+                                                 ib_cm_event);
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       case DAT_CONNECTION_EVENT_BROKEN:
+       case DAT_CONNECTION_EVENT_TIMED_OUT:
+               {
+                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+                       dapls_ib_disconnect_clean(ep_ptr, DAT_FALSE,
+                                                 ib_cm_event);
+                       dapl_os_unlock(&ep_ptr->header.lock);
+
+                       break;
+               }
+       case DAT_CONNECTION_REQUEST_EVENT:
+       default:
+               {
+                       dapl_os_unlock(&ep_ptr->header.lock);
+                       evd_ptr = NULL;
+
+                       dapl_os_assert(0);      /* shouldn't happen */
+                       break;
+               }
+       }
+
+       /*
+        * Post the event
+        * If the EP has been freed, the evd_ptr will be NULL
+        */
+       if (evd_ptr != NULL) {
+               dat_status = dapls_evd_post_connection_event(evd_ptr, dat_event_num, (DAT_HANDLE) ep_ptr, private_data_size,    /* CONNECTED or REJECT */
+                                                            ep_ptr->private.
+                                                            private_data);
+
+               if (dat_status != DAT_SUCCESS &&
+                   dat_event_num == DAT_CONNECTION_EVENT_ESTABLISHED) {
+                       /* We can't tell the user we are connected, something
+                        * is wrong locally. Just kill the connection and
+                        * reset the state to DISCONNECTED as we don't
+                        * expect a callback on an ABRUPT disconnect.
+                        */
+                       dapls_ib_disconnect(ep_ptr, DAT_CLOSE_ABRUPT_FLAG);
+                       dapl_os_lock(&ep_ptr->header.lock);
+                       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+                       dapl_os_unlock(&ep_ptr->header.lock);
+               }
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+                    "dapl_evd_connection_callback () returns\n");
+
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
index cc0aa17c6e0e7ff3d57e772075866265f3ec7c5a..14a10c79fc4f840192a9811ac9bdeaaf7940d37a 100644 (file)
@@ -1077,7 +1077,7 @@ dapls_evd_post_cr_event_ext(IN DAPL_SP * sp_ptr,
                        ep_ptr->param.ep_state =
                            DAT_EP_STATE_PASSIVE_CONNECTION_PENDING;
                }
-               ep_ptr->cm_handle = ib_cm_handle;
+               dapl_ep_link_cm(ep_ptr, ib_cm_handle);
        }
 
        /* link the CR onto the SP so we can pick it up later */
index 78a75a91edc0d49d05250c77c200ac8c5923b785..e5a7c3f655d6371bdd5f24b1020c2fa376d176f3 100644 (file)
-/*\r
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- * \r
- * HEADER: dapl_evd_util.h\r
- *\r
- * PURPOSE: Utility defs & routines for the EVD data structure\r
- *\r
- * $Id:$\r
- *\r
- **********************************************************************/\r
-\r
-#ifndef _DAPL_EVD_UTIL_H_\r
-#define _DAPL_EVD_UTIL_H_\r
-\r
-#include "dapl.h"\r
-\r
-DAT_RETURN\r
-dapls_evd_internal_create (\r
-    IN DAPL_IA         *ia_ptr, \r
-    IN DAPL_CNO                *cno_ptr,\r
-    IN DAT_COUNT       min_qlen,\r
-    IN DAT_EVD_FLAGS   evd_flags,\r
-    OUT DAPL_EVD       **evd_ptr_ptr) ;\r
-\r
-DAPL_EVD *\r
-dapls_evd_alloc ( \r
-    IN DAPL_IA         *ia_ptr,\r
-    IN DAPL_CNO                *cno_ptr,\r
-    IN DAT_EVD_FLAGS   evd_flags,\r
-    IN DAT_COUNT       qlen) ;\r
-\r
-DAT_RETURN\r
-dapls_evd_dealloc ( \r
-    IN DAPL_EVD        *evd_ptr) ;\r
-\r
-DAT_RETURN dapls_evd_event_realloc (\r
-    IN DAPL_EVD                *evd_ptr,\r
-    IN DAT_COUNT       qlen);\r
-\r
-/*\r
- * Each of these functions will retrieve a free event from\r
- * the specified EVD, fill in the elements of that event, and\r
- * post the event back to the EVD.  If there is no EVD available,\r
- * an overflow event will be posted to the async EVD associated\r
- * with the EVD.\r
- *\r
- * DAT_INSUFFICIENT_RESOURCES will be returned on overflow,\r
- * DAT_SUCCESS otherwise.\r
- */\r
-\r
-DAT_RETURN\r
-dapls_evd_post_cr_arrival_event (\r
-    IN DAPL_EVD                                *evd_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN DAT_SP_HANDLE                   sp_handle,\r
-    DAT_IA_ADDRESS_PTR                 ia_address_ptr,\r
-    DAT_CONN_QUAL                      conn_qual,\r
-    DAT_CR_HANDLE                      cr_handle);\r
-    \r
-DAT_RETURN\r
-dapls_evd_post_connection_event (\r
-    IN DAPL_EVD                                *evd_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN DAT_EP_HANDLE                   ep_handle,\r
-    IN DAT_COUNT                       private_data_size,\r
-    IN DAT_PVOID                       private_data);\r
-\r
-DAT_RETURN\r
-dapls_evd_post_async_error_event (\r
-    IN DAPL_EVD                                *evd_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN DAT_IA_HANDLE                   ia_handle);\r
-\r
-DAT_RETURN\r
-dapls_evd_post_software_event (\r
-    IN DAPL_EVD                                *evd_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN DAT_PVOID                       pointer);\r
-\r
-DAT_RETURN\r
-dapls_evd_post_generic_event (\r
-    IN DAPL_EVD                                *evd_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN DAT_EVENT_DATA                  *data);\r
-\r
-#ifdef DAT_EXTENSIONS\r
-DAT_RETURN\r
-dapls_evd_post_cr_event_ext (\r
-    IN DAPL_SP                         *sp_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN dp_ib_cm_handle_t               ib_cm_handle,\r
-    IN DAT_COUNT                       p_size,\r
-    IN DAT_PVOID                       p_data,\r
-    IN DAT_PVOID                       ext_data);\r
-\r
-DAT_RETURN\r
-dapls_evd_post_connection_event_ext (\r
-    IN DAPL_EVD                                *evd_ptr,\r
-    IN DAT_EVENT_NUMBER                        event_number,\r
-    IN DAT_EP_HANDLE                   ep_handle,\r
-    IN DAT_COUNT                       private_data_size,\r
-    IN DAT_PVOID                       private_data,\r
-    IN DAT_PVOID                       ext_data);\r
-#endif\r
-\r
-/*************************************\r
- * dapl internal callbacks functions *\r
- *************************************/\r
-\r
-/* connection verb callback */\r
-extern void dapl_evd_connection_callback (\r
-    IN dp_ib_cm_handle_t       ib_cm_handle,\r
-    IN const ib_cm_events_t    ib_cm_events,\r
-    IN const void              *private_data_ptr,\r
-    IN const int               private_data_size,\r
-    IN const void *            context );\r
-\r
-/* dto verb callback */\r
-extern void dapl_evd_dto_callback (\r
-    IN  ib_hca_handle_t        ib_hca_handle, \r
-    IN  ib_cq_handle_t                 ib_cq_handle, \r
-    IN  void*                  context);\r
-\r
-/* async verb callbacks */\r
-extern void dapl_evd_un_async_error_callback (\r
-    IN ib_hca_handle_t         ib_hca_handle,\r
-    IN ib_error_record_t *     cause_ptr,\r
-    IN void *                  context);\r
-\r
-extern void dapl_evd_cq_async_error_callback (\r
-    IN ib_hca_handle_t         ib_hca_handle,\r
-    IN ib_cq_handle_t          ib_cq_handle,\r
-    IN ib_error_record_t *     cause_ptr,\r
-    IN void *                  context);\r
-\r
-extern void dapl_evd_qp_async_error_callback (\r
-    IN ib_hca_handle_t         ib_hca_handle,\r
-    IN ib_qp_handle_t          ib_qp_handle,\r
-    IN ib_error_record_t *     cause_ptr,\r
-    IN void *                  context);\r
-\r
-extern void dapls_evd_copy_cq (\r
-    DAPL_EVD                   *evd_ptr);\r
-\r
-extern DAT_RETURN dapls_evd_cq_poll_to_event (\r
-    IN DAPL_EVD                *evd_ptr,\r
-    OUT DAT_EVENT              *event);\r
-\r
-#endif\r
+/*
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ * 
+ * HEADER: dapl_evd_util.h
+ *
+ * PURPOSE: Utility defs & routines for the EVD data structure
+ *
+ * $Id:$
+ *
+ **********************************************************************/
+
+#ifndef _DAPL_EVD_UTIL_H_
+#define _DAPL_EVD_UTIL_H_
+
+#include "dapl.h"
+
+DAT_RETURN
+dapls_evd_internal_create (
+    IN DAPL_IA         *ia_ptr, 
+    IN DAPL_CNO                *cno_ptr,
+    IN DAT_COUNT       min_qlen,
+    IN DAT_EVD_FLAGS   evd_flags,
+    OUT DAPL_EVD       **evd_ptr_ptr) ;
+
+DAPL_EVD *
+dapls_evd_alloc ( 
+    IN DAPL_IA         *ia_ptr,
+    IN DAPL_CNO                *cno_ptr,
+    IN DAT_EVD_FLAGS   evd_flags,
+    IN DAT_COUNT       qlen) ;
+
+DAT_RETURN
+dapls_evd_dealloc ( 
+    IN DAPL_EVD        *evd_ptr) ;
+
+DAT_RETURN dapls_evd_event_realloc (
+    IN DAPL_EVD                *evd_ptr,
+    IN DAT_COUNT       qlen);
+
+/*
+ * Each of these functions will retrieve a free event from
+ * the specified EVD, fill in the elements of that event, and
+ * post the event back to the EVD.  If there is no EVD available,
+ * an overflow event will be posted to the async EVD associated
+ * with the EVD.
+ *
+ * DAT_INSUFFICIENT_RESOURCES will be returned on overflow,
+ * DAT_SUCCESS otherwise.
+ */
+
+DAT_RETURN
+dapls_evd_post_cr_arrival_event (
+    IN DAPL_EVD                                *evd_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN DAT_SP_HANDLE                   sp_handle,
+    DAT_IA_ADDRESS_PTR                 ia_address_ptr,
+    DAT_CONN_QUAL                      conn_qual,
+    DAT_CR_HANDLE                      cr_handle);
+    
+DAT_RETURN
+dapls_evd_post_connection_event (
+    IN DAPL_EVD                                *evd_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN DAT_EP_HANDLE                   ep_handle,
+    IN DAT_COUNT                       private_data_size,
+    IN DAT_PVOID                       private_data);
+
+DAT_RETURN
+dapls_evd_post_async_error_event (
+    IN DAPL_EVD                                *evd_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN DAT_IA_HANDLE                   ia_handle);
+
+DAT_RETURN
+dapls_evd_post_software_event (
+    IN DAPL_EVD                                *evd_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN DAT_PVOID                       pointer);
+
+DAT_RETURN
+dapls_evd_post_generic_event (
+    IN DAPL_EVD                                *evd_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN DAT_EVENT_DATA                  *data);
+
+#ifdef DAT_EXTENSIONS
+DAT_RETURN
+dapls_evd_post_cr_event_ext (
+    IN DAPL_SP                         *sp_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN dp_ib_cm_handle_t               ib_cm_handle,
+    IN DAT_COUNT                       p_size,
+    IN DAT_PVOID                       p_data,
+    IN DAT_PVOID                       ext_data);
+
+DAT_RETURN
+dapls_evd_post_connection_event_ext (
+    IN DAPL_EVD                                *evd_ptr,
+    IN DAT_EVENT_NUMBER                        event_number,
+    IN DAT_EP_HANDLE                   ep_handle,
+    IN DAT_COUNT                       private_data_size,
+    IN DAT_PVOID                       private_data,
+    IN DAT_PVOID                       ext_data);
+#endif
+
+/*************************************
+ * dapl internal callbacks functions *
+ *************************************/
+
+/* connection verb callback */
+extern void dapl_evd_connection_callback (
+    IN dp_ib_cm_handle_t       ib_cm_handle,
+    IN const ib_cm_events_t    ib_cm_events,
+    IN const void              *private_data_ptr,
+    IN const int               private_data_size,
+    IN const void *            context );
+
+/* dto verb callback */
+extern void dapl_evd_dto_callback (
+    IN  ib_hca_handle_t        ib_hca_handle, 
+    IN  ib_cq_handle_t                 ib_cq_handle, 
+    IN  void*                  context);
+
+/* async verb callbacks */
+extern void dapl_evd_un_async_error_callback (
+    IN ib_hca_handle_t         ib_hca_handle,
+    IN ib_error_record_t *     cause_ptr,
+    IN void *                  context);
+
+extern void dapl_evd_cq_async_error_callback (
+    IN ib_hca_handle_t         ib_hca_handle,
+    IN ib_cq_handle_t          ib_cq_handle,
+    IN ib_error_record_t *     cause_ptr,
+    IN void *                  context);
+
+extern void dapl_evd_qp_async_error_callback (
+    IN ib_hca_handle_t         ib_hca_handle,
+    IN ib_qp_handle_t          ib_qp_handle,
+    IN ib_error_record_t *     cause_ptr,
+    IN void *                  context);
+
+extern void dapls_evd_copy_cq (
+    DAPL_EVD                   *evd_ptr);
+
+extern DAT_RETURN dapls_evd_cq_poll_to_event (
+    IN DAPL_EVD                *evd_ptr,
+    OUT DAT_EVENT              *event);
+
+#endif
index 093ed1c29ad59187025bb284aadd25ca9cd30026..d530d72d9825ac65908107125787fb4e03c8dace 100644 (file)
-/*\r
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- * \r
- * MODULE: dapl_ia_query.c\r
- *\r
- * PURPOSE: Interface Adapter management\r
- * Description: Interfaces in this file are completely described in\r
- *             the DAPL 1.1 API, Chapter 6, section 2\r
- *\r
- * $Id:$\r
- **********************************************************************/\r
-\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_vendor.h"\r
-\r
-/*\r
- * dapl_ia_query\r
- *\r
- * DAPL Requirements Version xxx, 6.2.1.3\r
- *\r
- * Provide the consumer with Interface Adapter and Provider parameters.\r
- *\r
- * Input:\r
- *     ia_handle\r
- *     ia_mask\r
- *     provider_mask\r
- *\r
- * Output:\r
- *     async_evd_handle\r
- *     ia_parameters\r
- *     provider_parameters\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_PARAMETER\r
- */\r
-DAT_RETURN DAT_API\r
-dapl_ia_query(IN DAT_IA_HANDLE ia_handle,\r
-             OUT DAT_EVD_HANDLE * async_evd_handle,\r
-             IN DAT_IA_ATTR_MASK ia_attr_mask,\r
-             OUT DAT_IA_ATTR * ia_attr,\r
-             IN DAT_PROVIDER_ATTR_MASK provider_attr_mask,\r
-             OUT DAT_PROVIDER_ATTR * provider_attr)\r
-{\r
-       DAPL_IA *ia_ptr;\r
-       DAT_RETURN dat_status;\r
-       struct evd_merge_type {\r
-               DAT_BOOLEAN array[6][6];\r
-       } *evd_merge;\r
-       DAT_BOOLEAN val;\r
-       int i;\r
-       int j;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_API,\r
-                    "dapl_ia_query (%p, %p, 0x%llx, %p, 0x%x, %p)\n",\r
-                    ia_handle,\r
-                    async_evd_handle,\r
-                    ia_attr_mask, ia_attr, provider_attr_mask, provider_attr);\r
-\r
-       ia_ptr = (DAPL_IA *) ia_handle;\r
-       dat_status = DAT_SUCCESS;\r
-\r
-       if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) {\r
-               dat_status =\r
-                   DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA);\r
-               goto bail;\r
-       }\r
-\r
-       if (NULL != async_evd_handle) {\r
-               *async_evd_handle = ia_ptr->async_error_evd;\r
-       }\r
-\r
-       if (ia_attr_mask & DAT_IA_FIELD_ALL) {\r
-               if (NULL == ia_attr) {\r
-                       dat_status =\r
-                           DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);\r
-                       goto bail;\r
-               }\r
-\r
-               /*\r
-                * Obtain parameters from the HCA.  Protect against multiple\r
-                * IAs beating on the HCA at the same time.\r
-                */\r
-               dat_status =\r
-                   dapls_ib_query_hca(ia_ptr->hca_ptr, ia_attr, NULL, NULL);\r
-               if (dat_status != DAT_SUCCESS) {\r
-                       goto bail;\r
-               }\r
-       }\r
-\r
-       if (ia_attr_mask & ~DAT_IA_FIELD_ALL) {\r
-               dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);\r
-               goto bail;\r
-       }\r
-\r
-       if (provider_attr_mask & DAT_PROVIDER_FIELD_ALL) {\r
-               if (NULL == provider_attr) {\r
-                       dat_status =\r
-                           DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG6);\r
-                       goto bail;\r
-               }\r
-\r
-               strncpy(provider_attr->provider_name,\r
-                       ia_ptr->header.provider->device_name,\r
-                       DAT_NAME_MAX_LENGTH);\r
-               provider_attr->provider_version_major = VN_PROVIDER_MAJOR;\r
-               provider_attr->provider_version_minor = VN_PROVIDER_MINOR;\r
-               provider_attr->dapl_version_major = DAT_VERSION_MAJOR;\r
-               provider_attr->dapl_version_minor = DAT_VERSION_MINOR;\r
-               provider_attr->lmr_mem_types_supported =\r
-                   DAT_MEM_TYPE_VIRTUAL | DAT_MEM_TYPE_LMR;\r
-#if VN_MEM_SHARED_VIRTUAL_SUPPORT > 0 && !defined(__KDAPL__)\r
-               provider_attr->lmr_mem_types_supported |=\r
-                   DAT_MEM_TYPE_SHARED_VIRTUAL;\r
-#endif\r
-               provider_attr->iov_ownership_on_return = DAT_IOV_CONSUMER;\r
-               provider_attr->dat_qos_supported = DAT_QOS_BEST_EFFORT;\r
-               provider_attr->completion_flags_supported =\r
-                   DAT_COMPLETION_DEFAULT_FLAG;\r
-               provider_attr->is_thread_safe = DAT_FALSE;\r
-               /*\r
-                * N.B. The second part of the following equation will evaluate\r
-                *      to 0 unless IBHOSTS_NAMING is enabled.\r
-                */\r
-               provider_attr->max_private_data_size =\r
-                   dapls_ib_private_data_size(ia_ptr->hca_ptr) -\r
-                   (sizeof(DAPL_PRIVATE) - DAPL_MAX_PRIVATE_DATA_SIZE);\r
-               provider_attr->supports_multipath = DAT_FALSE;\r
-               provider_attr->ep_creator = DAT_PSP_CREATES_EP_NEVER;\r
-               provider_attr->optimal_buffer_alignment = DAT_OPTIMAL_ALIGNMENT;\r
-               /* The value of pz_support may vary by transport */\r
-               provider_attr->num_provider_specific_attr = 0;\r
-               provider_attr->provider_specific_attr = NULL;\r
-#if !defined(__KDAPL__)\r
-               provider_attr->pz_support = DAT_PZ_UNIQUE;\r
-#endif                         /* !KDAPL */\r
-\r
-               /*\r
-                *  Query for provider specific attributes\r
-                */\r
-               dapls_query_provider_specific_attr(ia_ptr, provider_attr);\r
-\r
-               /*\r
-                * Set up evd_stream_merging_supported options. Note there is\r
-                * one bit per allowable combination, using the ordinal\r
-                * position of the DAT_EVD_FLAGS as positions in the\r
-                * array. e.g.\r
-                * [0][0] is DAT_EVD_SOFTWARE_FLAG | DAT_EVD_SOFTWARE_FLAG,\r
-                * [0][1] is DAT_EVD_SOFTWARE_FLAG | DAT_EVD_CR_FLAG, and\r
-                * [2][4] is DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG\r
-                *\r
-                * Most combinations are true, so initialize the array that way.\r
-                * Then finish by resetting the bad combinations.\r
-                *\r
-                * DAT_EVD_ASYNC_FLAG is not supported. InfiniBand only allows\r
-                * a single asynchronous event handle per HCA, and the first\r
-                * dat_ia_open forces the creation of the only one that can be\r
-                * used. We disallow the user from creating an ASYNC EVD here.\r
-                */\r
-\r
-               evd_merge =\r
-                   (struct evd_merge_type *)&provider_attr->\r
-                   evd_stream_merging_supported[0][0];\r
-               val = DAT_TRUE;\r
-               for (i = 0; i < 6; i++) {\r
-                       if (i > 4) {\r
-                               /* ASYNC EVD is 5, so entire row will be 0 */\r
-                               val = DAT_FALSE;\r
-                       }\r
-                       for (j = 0; j < 5; j++) {\r
-                               evd_merge->array[i][j] = val;\r
-                       }\r
-                       /* Set the ASYNC_EVD column to FALSE */\r
-                       evd_merge->array[i][5] = DAT_FALSE;\r
-               }\r
-\r
-#ifndef DAPL_MERGE_CM_DTO\r
-               /*\r
-                * If an implementation supports CM and DTO completions on\r
-                * the same EVD then DAPL_MERGE_CM_DTO should be set to\r
-                * skip the following code\r
-                */\r
-               /* DAT_EVD_DTO_FLAG | DAT_EVD_CONNECTION_FLAG */\r
-               evd_merge->array[2][3] = DAT_FALSE;\r
-               /* DAT_EVD_CONNECTION_FLAG | DAT_EVD_DTO_FLAG */\r
-               evd_merge->array[3][2] = DAT_FALSE;\r
-#endif                         /* DAPL_MERGE_CM_DTO */\r
-       }\r
-\r
-      bail:\r
-       if (dat_status != DAT_SUCCESS) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_RTN,\r
-                            "dapl_ia_query () returns 0x%x\n", dat_status);\r
-       }\r
-\r
-       return dat_status;\r
-}\r
-\r
-/*\r
- * Local variables:\r
- *  c-indent-level: 4\r
- *  c-basic-offset: 4\r
- *  tab-width: 8\r
- * End:\r
- */\r
+/*
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ * 
+ * MODULE: dapl_ia_query.c
+ *
+ * PURPOSE: Interface Adapter management
+ * Description: Interfaces in this file are completely described in
+ *             the DAPL 1.1 API, Chapter 6, section 2
+ *
+ * $Id:$
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_vendor.h"
+
+/*
+ * dapl_ia_query
+ *
+ * DAPL Requirements Version xxx, 6.2.1.3
+ *
+ * Provide the consumer with Interface Adapter and Provider parameters.
+ *
+ * Input:
+ *     ia_handle
+ *     ia_mask
+ *     provider_mask
+ *
+ * Output:
+ *     async_evd_handle
+ *     ia_parameters
+ *     provider_parameters
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_PARAMETER
+ */
+DAT_RETURN DAT_API
+dapl_ia_query(IN DAT_IA_HANDLE ia_handle,
+             OUT DAT_EVD_HANDLE * async_evd_handle,
+             IN DAT_IA_ATTR_MASK ia_attr_mask,
+             OUT DAT_IA_ATTR * ia_attr,
+             IN DAT_PROVIDER_ATTR_MASK provider_attr_mask,
+             OUT DAT_PROVIDER_ATTR * provider_attr)
+{
+       DAPL_IA *ia_ptr;
+       DAT_RETURN dat_status;
+       struct evd_merge_type {
+               DAT_BOOLEAN array[6][6];
+       } *evd_merge;
+       DAT_BOOLEAN val;
+       int i;
+       int j;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_API,
+                    "dapl_ia_query (%p, %p, 0x%llx, %p, 0x%x, %p)\n",
+                    ia_handle,
+                    async_evd_handle,
+                    ia_attr_mask, ia_attr, provider_attr_mask, provider_attr);
+
+       ia_ptr = (DAPL_IA *) ia_handle;
+       dat_status = DAT_SUCCESS;
+
+       if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) {
+               dat_status =
+                   DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA);
+               goto bail;
+       }
+
+       if (NULL != async_evd_handle) {
+               *async_evd_handle = ia_ptr->async_error_evd;
+       }
+
+       if (ia_attr_mask & DAT_IA_FIELD_ALL) {
+               if (NULL == ia_attr) {
+                       dat_status =
+                           DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
+                       goto bail;
+               }
+
+               /*
+                * Obtain parameters from the HCA.  Protect against multiple
+                * IAs beating on the HCA at the same time.
+                */
+               dat_status =
+                   dapls_ib_query_hca(ia_ptr->hca_ptr, ia_attr, NULL, NULL);
+               if (dat_status != DAT_SUCCESS) {
+                       goto bail;
+               }
+       }
+
+       if (ia_attr_mask & ~DAT_IA_FIELD_ALL) {
+               dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
+               goto bail;
+       }
+
+       if (provider_attr_mask & DAT_PROVIDER_FIELD_ALL) {
+               if (NULL == provider_attr) {
+                       dat_status =
+                           DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG6);
+                       goto bail;
+               }
+
+               strncpy(provider_attr->provider_name,
+                       ia_ptr->header.provider->device_name,
+                       DAT_NAME_MAX_LENGTH);
+               provider_attr->provider_version_major = VN_PROVIDER_MAJOR;
+               provider_attr->provider_version_minor = VN_PROVIDER_MINOR;
+               provider_attr->dapl_version_major = DAT_VERSION_MAJOR;
+               provider_attr->dapl_version_minor = DAT_VERSION_MINOR;
+               provider_attr->lmr_mem_types_supported =
+                   DAT_MEM_TYPE_VIRTUAL | DAT_MEM_TYPE_LMR;
+#if VN_MEM_SHARED_VIRTUAL_SUPPORT > 0 && !defined(__KDAPL__)
+               provider_attr->lmr_mem_types_supported |=
+                   DAT_MEM_TYPE_SHARED_VIRTUAL;
+#endif
+               provider_attr->iov_ownership_on_return = DAT_IOV_CONSUMER;
+               provider_attr->dat_qos_supported = DAT_QOS_BEST_EFFORT;
+               provider_attr->completion_flags_supported =
+                   DAT_COMPLETION_DEFAULT_FLAG;
+               provider_attr->is_thread_safe = DAT_FALSE;
+               /*
+                * N.B. The second part of the following equation will evaluate
+                *      to 0 unless IBHOSTS_NAMING is enabled.
+                */
+               provider_attr->max_private_data_size =
+                   dapls_ib_private_data_size(ia_ptr->hca_ptr) -
+                   (sizeof(DAPL_PRIVATE) - DAPL_MAX_PRIVATE_DATA_SIZE);
+               provider_attr->supports_multipath = DAT_FALSE;
+               provider_attr->ep_creator = DAT_PSP_CREATES_EP_NEVER;
+               provider_attr->optimal_buffer_alignment = DAT_OPTIMAL_ALIGNMENT;
+               /* The value of pz_support may vary by transport */
+               provider_attr->num_provider_specific_attr = 0;
+               provider_attr->provider_specific_attr = NULL;
+#if !defined(__KDAPL__)
+               provider_attr->pz_support = DAT_PZ_UNIQUE;
+#endif                         /* !KDAPL */
+
+               /*
+                *  Query for provider specific attributes
+                */
+               dapls_query_provider_specific_attr(ia_ptr, provider_attr);
+
+               /*
+                * Set up evd_stream_merging_supported options. Note there is
+                * one bit per allowable combination, using the ordinal
+                * position of the DAT_EVD_FLAGS as positions in the
+                * array. e.g.
+                * [0][0] is DAT_EVD_SOFTWARE_FLAG | DAT_EVD_SOFTWARE_FLAG,
+                * [0][1] is DAT_EVD_SOFTWARE_FLAG | DAT_EVD_CR_FLAG, and
+                * [2][4] is DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG
+                *
+                * Most combinations are true, so initialize the array that way.
+                * Then finish by resetting the bad combinations.
+                *
+                * DAT_EVD_ASYNC_FLAG is not supported. InfiniBand only allows
+                * a single asynchronous event handle per HCA, and the first
+                * dat_ia_open forces the creation of the only one that can be
+                * used. We disallow the user from creating an ASYNC EVD here.
+                */
+
+               evd_merge =
+                   (struct evd_merge_type *)&provider_attr->
+                   evd_stream_merging_supported[0][0];
+               val = DAT_TRUE;
+               for (i = 0; i < 6; i++) {
+                       if (i > 4) {
+                               /* ASYNC EVD is 5, so entire row will be 0 */
+                               val = DAT_FALSE;
+                       }
+                       for (j = 0; j < 5; j++) {
+                               evd_merge->array[i][j] = val;
+                       }
+                       /* Set the ASYNC_EVD column to FALSE */
+                       evd_merge->array[i][5] = DAT_FALSE;
+               }
+
+#ifndef DAPL_MERGE_CM_DTO
+               /*
+                * If an implementation supports CM and DTO completions on
+                * the same EVD then DAPL_MERGE_CM_DTO should be set to
+                * skip the following code
+                */
+               /* DAT_EVD_DTO_FLAG | DAT_EVD_CONNECTION_FLAG */
+               evd_merge->array[2][3] = DAT_FALSE;
+               /* DAT_EVD_CONNECTION_FLAG | DAT_EVD_DTO_FLAG */
+               evd_merge->array[3][2] = DAT_FALSE;
+#endif                         /* DAPL_MERGE_CM_DTO */
+       }
+
+      bail:
+       if (dat_status != DAT_SUCCESS) {
+               dapl_dbg_log(DAPL_DBG_TYPE_RTN,
+                            "dapl_ia_query () returns 0x%x\n", dat_status);
+       }
+
+       return dat_status;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
index 7d42b49f45a7d212ac3063ed65df98d54ecc9b4f..a35b1188cebacf3d2528e2fe6c017865ff6bbb1c 100644 (file)
@@ -16,7 +16,7 @@
  *\r
  * PURPOSE: IB Connection routines for access to IBAL APIs\r
  *\r
- * $Id$\r
+ * $Id: dapl_ibal_cm.c 584 2007-02-07 13:12:18Z sleybo $\r
  *\r
  **********************************************************************/\r
 \r
@@ -94,7 +94,7 @@ void dapli_print_private_data( char *prefix, const uint8_t *pd, int len )
     if ( !pd || len <= 0 )\r
        return;\r
 \r
-    dapl_log ( DAPL_DBG_TYPE_CM, "--> %s: private_data:\n    ",prefix);\r
+    dapl_log ( DAPL_DBG_TYPE_CM, "--> %s: private_data(len %d)\n    ",prefix,len);\r
 \r
     if (len > IB_MAX_REP_PDATA_SIZE)\r
     {\r
@@ -107,13 +107,70 @@ void dapli_print_private_data( char *prefix, const uint8_t *pd, int len )
     for ( i = 0 ; i < len; i++ )\r
     {\r
        dapl_log ( DAPL_DBG_TYPE_CM, "%2x ", pd[i]);\r
-       if ( ((i+1) % 20) == 0 ) \r
+       if ( ((i+1) % 5) == 0 ) \r
            dapl_log ( DAPL_DBG_TYPE_CM, "\n    ");\r
     }\r
    dapl_log ( DAPL_DBG_TYPE_CM, "\n");\r
 }\r
 #endif\r
 \r
+/* EP-CM linking support */\r
+dp_ib_cm_handle_t ibal_cm_alloc(void)\r
+{\r
+       dp_ib_cm_handle_t cm_ptr;\r
+\r
+       /* Allocate CM, init lock, and initialize */\r
+       if ((cm_ptr = dapl_os_alloc(sizeof(*cm_ptr))) == NULL)\r
+               return NULL;\r
+\r
+       (void)dapl_os_memzero(cm_ptr, sizeof(*cm_ptr));\r
+       cm_ptr->ref_count = 1;\r
+\r
+       if (dapl_os_lock_init(&cm_ptr->lock)) {\r
+               dapl_os_free(cm_ptr, sizeof(*cm_ptr));\r
+               return NULL;\r
+       }\r
+\r
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm_ptr->list_entry);\r
+       \r
+       return cm_ptr;\r
+}\r
+\r
+/* free CM object resources */\r
+static void ibal_cm_dealloc(dp_ib_cm_handle_t cm_ptr) \r
+{\r
+       dapl_os_assert(!cm_ptr->ref_count);\r
+       dapl_os_lock_destroy(&cm_ptr->lock);\r
+       dapl_os_free(cm_ptr, sizeof(*cm_ptr));\r
+}\r
+\r
+void dapls_cm_acquire(dp_ib_cm_handle_t cm_ptr)\r
+{\r
+       dapl_os_lock(&cm_ptr->lock);\r
+       cm_ptr->ref_count++;\r
+       dapl_os_unlock(&cm_ptr->lock);\r
+}\r
+\r
+void dapls_cm_release(dp_ib_cm_handle_t cm_ptr)\r
+{\r
+       dapl_os_lock(&cm_ptr->lock);\r
+       cm_ptr->ref_count--;\r
+       if (cm_ptr->ref_count) {\r
+                dapl_os_unlock(&cm_ptr->lock);\r
+               return;\r
+       }\r
+       dapl_os_unlock(&cm_ptr->lock);\r
+       ibal_cm_dealloc(cm_ptr);\r
+}\r
+\r
+/* blocking: called from user thread dapl_ep_free() only */\r
+void dapls_cm_free(dp_ib_cm_handle_t cm_ptr)\r
+{\r
+       dapl_ep_unlink_cm(cm_ptr->ep, cm_ptr);\r
+\r
+       /* final reference, alloc */\r
+       dapls_cm_release(cm_ptr);\r
+}\r
 \r
 static void \r
 dapli_ib_cm_apr_cb (\r
@@ -147,6 +204,7 @@ dapli_ib_cm_dreq_cb (
     ib_cm_drep_t        cm_drep;\r
     DAPL_EP             *ep_ptr;\r
     int                        bail=10;\r
+    dp_ib_cm_handle_t  cm_ptr;\r
     \r
     dapl_os_assert (p_cm_dreq_rec);\r
 \r
@@ -168,6 +226,14 @@ dapli_ib_cm_dreq_cb (
                       DAPL_MAGIC_EP );\r
         return;\r
     }\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);\r
+        return;\r
+    }\r
+    dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_dreq_rec->h_cm_dreq.h_qp);\r
 \r
     dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
                   "--> %s() EP %p, %s sent_discreq %s\n",\r
@@ -210,10 +276,8 @@ dapli_ib_cm_dreq_cb (
           \r
     if (ep_ptr->cr_ptr)\r
     {\r
-        dapl_os_assert(ep_ptr->ibal_cm_handle->cid\r
-                                             == p_cm_dreq_rec->h_cm_dreq.cid);\r
         /* passive side */\r
-        dapls_cr_callback ( ep_ptr->cm_handle,\r
+        dapls_cr_callback ( cm_ptr,\r
                             IB_CME_DISCONNECTED,\r
                             (void * __ptr64) p_cm_dreq_rec->p_dreq_pdata,\r
                            IB_DREQ_PDATA_SIZE,\r
@@ -223,7 +287,7 @@ dapli_ib_cm_dreq_cb (
     {\r
         /* active side */\r
         dapl_evd_connection_callback (\r
-                                  (dp_ib_cm_handle_t) &p_cm_dreq_rec->h_cm_dreq,\r
+                                  cm_ptr,\r
                                   IB_CME_DISCONNECTED,\r
                                   (void * __ptr64)\r
                                   p_cm_dreq_rec->p_dreq_pdata,\r
@@ -242,6 +306,7 @@ dapli_ib_cm_drep_cb (
         IN    ib_cm_drep_rec_t          *p_cm_drep_rec )\r
 {\r
     DAPL_EP            *ep_ptr;\r
+    dp_ib_cm_handle_t  cm_ptr;\r
     \r
     dapl_os_assert (p_cm_drep_rec != NULL);\r
 \r
@@ -260,11 +325,19 @@ dapli_ib_cm_drep_cb (
                   "--> %s: BAD EP Handle EP=%lx\n", __FUNCTION__,ep_ptr); \r
         return;\r
     }\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);\r
+        return;\r
+    }\r
+    dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_drep_rec->h_qp);\r
     \r
     dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
        "--> DiCDpcb: EP %p state %s cm_hdl %p\n",ep_ptr,\r
                   dapl_get_ep_state_str(ep_ptr->param.ep_state),\r
-                  ep_ptr->cm_handle);\r
+                  cm_ptr);\r
 \r
     if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED )\r
     {\r
@@ -274,17 +347,10 @@ dapli_ib_cm_drep_cb (
         return;\r
     }\r
 \r
-    if (ep_ptr->cm_handle == DAPL_IB_INVALID_HANDLE )\r
-    {\r
-         dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
-                  "--> %s: Invalid EP->CM handle?\n", __FUNCTION__); \r
-        return;\r
-    }\r
-\r
     if (ep_ptr->cr_ptr)\r
     {\r
         /* passive connection side */\r
-        dapls_cr_callback ( ep_ptr->cm_handle,\r
+        dapls_cr_callback ( cm_ptr,\r
                             IB_CME_DISCONNECTED,\r
                            (void * __ptr64) p_cm_drep_rec->p_drep_pdata,\r
                           IB_DREP_PDATA_SIZE,\r
@@ -294,7 +360,7 @@ dapli_ib_cm_drep_cb (
     {\r
         /* active connection side */\r
         dapl_evd_connection_callback (\r
-                                   ep_ptr->cm_handle,\r
+                                   cm_ptr,\r
                                    IB_CME_DISCONNECTED,\r
                                    (void * __ptr64) p_cm_drep_rec->p_drep_pdata,\r
                                   IB_DREP_PDATA_SIZE,\r
@@ -316,6 +382,7 @@ dapli_ib_cm_rep_cb (
     DAPL_PRIVATE        *prd_ptr;\r
     DAPL_EP             *ep_ptr;\r
     dapl_ibal_ca_t      *p_ca;\r
+    dp_ib_cm_handle_t  cm_ptr;\r
         \r
     dapl_os_assert (p_cm_rep_rec != NULL);\r
 \r
@@ -327,8 +394,17 @@ dapli_ib_cm_rep_cb (
                       __FUNCTION__, ep_ptr);\r
         return;\r
     }\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);\r
+        return;\r
+    }\r
+    dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_rep_rec->h_cm_rep.h_qp);\r
+\r
     dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
-                  "--> DiCRpcb: EP %lx local_max_rdma_read_in %d\n", \r
+                  "--> DiCRpcb: EP %lx local_max_rdma_read_in %d\n", \r
                   ep_ptr, p_cm_rep_rec->resp_res);\r
 \r
     p_ca   = (dapl_ibal_ca_t *) \r
@@ -372,7 +448,7 @@ dapli_ib_cm_rep_cb (
 #endif\r
 \r
     dapl_evd_connection_callback ( \r
-                            (dp_ib_cm_handle_t)&p_cm_rep_rec->h_cm_rep,\r
+                            cm_ptr,\r
                             cm_cb_op,\r
                             (void *) prd_ptr,\r
                            IB_REP_PDATA_SIZE,\r
@@ -386,6 +462,7 @@ dapli_ib_cm_rej_cb (
 {\r
     DAPL_EP         *ep_ptr;\r
     ib_cm_events_t  cm_event;\r
+    dp_ib_cm_handle_t  cm_ptr;\r
 \r
     dapl_os_assert (p_cm_rej_rec);\r
 \r
@@ -397,6 +474,14 @@ dapli_ib_cm_rej_cb (
                       __FUNCTION__, ep_ptr);\r
         return;\r
     }\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR, \r
+                      "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);\r
+        return;\r
+    }\r
+    dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_rej_rec->h_qp);\r
 \r
     dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
                   "--> DiCRjcb: EP = %lx QP = %lx rej reason = 0x%x\n", \r
@@ -456,7 +541,7 @@ dapli_ib_cm_rej_cb (
 \r
     if (ep_ptr->cr_ptr)\r
     {\r
-        dapls_cr_callback ( ep_ptr->cm_handle,\r
+        dapls_cr_callback ( cm_ptr,\r
                             cm_event,\r
                             (void * __ptr64) p_cm_rej_rec->p_rej_pdata,\r
                            IB_REJ_PDATA_SIZE,\r
@@ -465,7 +550,7 @@ dapli_ib_cm_rej_cb (
     else\r
     {\r
         dapl_evd_connection_callback (\r
-                                   ep_ptr->cm_handle,\r
+                                   cm_ptr,\r
                                    cm_event,\r
                                    (void * __ptr64) p_cm_rej_rec->p_rej_pdata,\r
                                   IB_REJ_PDATA_SIZE,\r
@@ -481,12 +566,7 @@ dapli_ib_cm_req_cb ( IN  ib_cm_req_rec_t  *p_cm_req_rec )
 {\r
     DAPL_SP              *sp_ptr;\r
     DAT_SOCK_ADDR6       dest_ia_addr;\r
-    dp_ib_cm_handle_t    cm_handle;\r
-\r
-    struct ibal_cr_data {\r
-        ib_cm_handle_t   cm_hdl;\r
-        DAT_SOCK_ADDR6   dst_ip_addr;\r
-    } *crd;\r
+    dp_ib_cm_handle_t    cm_ptr;\r
 \r
     dapl_os_assert (p_cm_req_rec);\r
 \r
@@ -517,8 +597,8 @@ dapli_ib_cm_req_cb ( IN  ib_cm_req_rec_t  *p_cm_req_rec )
      * EP struct deallocation is where this memory is released or prior in the\r
      * error case.\r
      */\r
-    crd = dapl_os_alloc ( sizeof(struct ibal_cr_data) );\r
-    if ( !crd )\r
+    cm_ptr = ibal_cm_alloc();\r
+    if (!cm_ptr)\r
     {\r
         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
                        "%s: FAILED to alloc IB CM handle storage?\n",\r
@@ -526,9 +606,6 @@ dapli_ib_cm_req_cb ( IN  ib_cm_req_rec_t  *p_cm_req_rec )
         return;\r
     }\r
 \r
-    cm_handle = &crd->cm_hdl;\r
-    dapl_os_memzero ( (void*)crd, sizeof(*crd) );\r
-\r
     /*\r
      * Save the cm_srvc_handle to avoid the race condition between\r
      * the return of the ib_cm_listen and the notification of a conn req\r
@@ -577,6 +654,16 @@ dapli_ib_cm_req_cb ( IN  ib_cm_req_rec_t  *p_cm_req_rec )
 \r
 #endif /* NO_NAME_SERVICE */\r
 \r
+    /* preserve CR cm handle data */\r
+    dapl_os_memcpy( (void*)&cm_ptr->ib_cm,\r
+                    (void*)&p_cm_req_rec->h_cm_req,\r
+                    sizeof(ib_cm_handle_t));\r
+\r
+    /* preserve remote IP address */\r
+    dapl_os_memcpy( (void*)&cm_ptr->dst_ip_addr,\r
+                    (void*)&dest_ia_addr,\r
+                    sizeof(dest_ia_addr));\r
+\r
 #if defined(DAPL_DBG)\r
     {\r
         char ipa[20];\r
@@ -584,23 +671,13 @@ dapli_ib_cm_req_cb ( IN  ib_cm_req_rec_t  *p_cm_req_rec )
         //rval = ((struct sockaddr_in *) (&dest_ia_addr))->sin_addr.s_addr;\r
 \r
         dapl_dbg_log (DAPL_DBG_TYPE_CM|DAPL_DBG_TYPE_CALLBACK, \r
-                      "%s: query SA for RemoteAddr: %s\n",\r
-                      __FUNCTION__,\r
-                      dapli_get_ip_addr_str( (DAT_SOCK_ADDR6*)\r
-                                                         &dest_ia_addr, ipa) );\r
+                      "%s: query SA (CM %lx)->dst_ip_addr: %s\n",\r
+                      __FUNCTION__,cm_ptr,\r
+                      dapli_get_ip_addr_str(\r
+                               (DAT_SOCK_ADDR6*) &cm_ptr->dst_ip_addr, ipa) );\r
     }\r
 #endif\r
 \r
-    /* preserve CR cm handle data */\r
-    dapl_os_memcpy( (void*)cm_handle,\r
-                    (void*)&p_cm_req_rec->h_cm_req,\r
-                    sizeof(ib_cm_handle_t) );\r
-\r
-    /* preserve remote IP address */\r
-    dapl_os_memcpy( (void*)&crd->dst_ip_addr,\r
-                    (void*)&dest_ia_addr,\r
-                    sizeof(dest_ia_addr) );\r
-\r
     /* FIXME - Vu\r
      * We have NOT used/saved the primary and alternative path record\r
      * ie. p_cm_req_rec->p_primary_path and p_cm_req_rec->p_alt_path\r
@@ -614,10 +691,10 @@ dapli_ib_cm_req_cb ( IN  ib_cm_req_rec_t  *p_cm_req_rec )
                   __FUNCTION__, sp_ptr, p_cm_req_rec->resp_res,\r
                   p_cm_req_rec->p_req_pdata);\r
 \r
-    dapls_cr_callback ( cm_handle,\r
+    dapls_cr_callback ( cm_ptr,\r
                         IB_CME_CONNECTION_REQUEST_PENDING,\r
                         (void * __ptr64) p_cm_req_rec->p_req_pdata,\r
-                       IB_REQ_PDATA_SIZE,\r
+                                               IB_REQ_PDATA_SIZE,\r
                         (void * __ptr64) sp_ptr );\r
 }\r
 \r
@@ -627,7 +704,7 @@ dapli_ib_cm_mra_cb (
         IN    ib_cm_mra_rec_t          *p_cm_mra_rec )\r
 {\r
        UNUSED_PARAM( p_cm_mra_rec );\r
-    dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK, \r
+       dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK, \r
                        "--> DiCMcb: CM callback MRA\n");\r
 }\r
 \r
@@ -635,7 +712,8 @@ static void
 dapli_ib_cm_rtu_cb (\r
         IN    ib_cm_rtu_rec_t          *p_cm_rtu_rec )\r
 {\r
-    DAPL_EP         *ep_ptr;\r
+    DAPL_EP            *ep_ptr;\r
+    dp_ib_cm_handle_t  cm_ptr;\r
 \r
     dapl_os_assert (p_cm_rtu_rec != NULL);\r
    \r
@@ -647,9 +725,18 @@ dapli_ib_cm_rtu_cb (
                       __FUNCTION__, ep_ptr);\r
         return;\r
     }\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);\r
+        return;\r
+    }\r
+    dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_rtu_rec->h_qp);\r
 \r
     dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK, \r
-                  "--> DiCRucb: EP %lx QP %lx\n", ep_ptr, ep_ptr->qp_handle); \r
+                  "--> DiCRucb: EP %lx QP %lx CR %lx\n",\r
+                  ep_ptr, ep_ptr->qp_handle, ep_ptr->cr_ptr); \r
 \r
     if (ep_ptr->cr_ptr)\r
     {\r
@@ -657,7 +744,8 @@ dapli_ib_cm_rtu_cb (
 \r
         sp_ptr = ((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr;\r
 \r
-        dapls_cr_callback ( ep_ptr->cm_handle,\r
+        /* passive connection side */\r
+        dapls_cr_callback ( cm_ptr,\r
                             IB_CME_CONNECTED,\r
                             (void * __ptr64) p_cm_rtu_rec->p_rtu_pdata,\r
                             IB_RTU_PDATA_SIZE,\r
@@ -667,7 +755,7 @@ dapli_ib_cm_rtu_cb (
     else\r
     {\r
         dapl_evd_connection_callback ( \r
-                            ep_ptr->cm_handle,\r
+                            cm_ptr,\r
                             IB_CME_CONNECTED,\r
                             (void * __ptr64) p_cm_rtu_rec->p_rtu_pdata,\r
                            IB_RTU_PDATA_SIZE,\r
@@ -698,18 +786,21 @@ dapls_ib_cm_remote_addr (
 {\r
 \r
     DAPL_HEADER        *header;\r
-    void               *vp;\r
+    dp_ib_cm_handle_t  cm;\r
     char               ipa[20];\r
+    char               *rtype;\r
 \r
     header = (DAPL_HEADER *)dat_handle;\r
 \r
     if (header->magic == DAPL_MAGIC_EP) \r
     {\r
-       vp = &((DAPL_EP *) dat_handle)->remote_ia_address;\r
+       cm = dapl_get_cm_from_ep((DAPL_EP *)dat_handle);\r
+       rtype = "EP";\r
     }\r
     else if (header->magic == DAPL_MAGIC_CR) \r
     {\r
-       vp = &((DAPL_CR *) dat_handle)->remote_ia_address;\r
+       cm = ((DAPL_CR *) dat_handle)->ib_cm_handle;\r
+       rtype = "CR";\r
     }\r
     else \r
     {\r
@@ -719,10 +810,10 @@ dapls_ib_cm_remote_addr (
        return DAT_INVALID_HANDLE;\r
     }\r
 \r
-    dapl_os_memcpy( remote_address, vp, sizeof(DAT_SOCK_ADDR6) );\r
+    dapl_os_memcpy( remote_address, &cm->dst_ip_addr, sizeof(DAT_SOCK_ADDR6) );\r
 \r
-    dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s: returns %s\n",\r
-                   __FUNCTION__,\r
+    dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s: returns %s remote Addrs %s\n",\r
+                   __FUNCTION__, rtype,\r
                    dapli_get_ip_addr_str((DAT_SOCK_ADDR6*)remote_address,ipa) );\r
 \r
     return DAT_SUCCESS;\r
@@ -1011,7 +1102,8 @@ dapls_ib_disconnect ( IN   DAPL_EP           *ep_ptr,
                       IN   DAT_CLOSE_FLAGS   disconnect_flags )\r
 {\r
     ib_api_status_t    ib_status = IB_SUCCESS;\r
-    ib_cm_dreq_t                   cm_dreq;\r
+    ib_cm_dreq_t       cm_dreq;\r
+    dp_ib_cm_handle_t  cm_ptr;\r
 \r
     dapl_os_assert(ep_ptr);\r
 \r
@@ -1021,14 +1113,14 @@ dapls_ib_disconnect ( IN   DAPL_EP           *ep_ptr,
                   "--> %s: BAD EP Magic EP=%lx\n", __FUNCTION__,ep_ptr); \r
         return DAT_SUCCESS;\r
     }\r
-\r
-    if (ep_ptr->cm_handle == DAPL_IB_INVALID_HANDLE )\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr)\r
     {\r
-         dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
-                  "--> %s: Invalid EP->CM handle, OK.\n", __FUNCTION__); \r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR, \r
+                      "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);\r
         return DAT_SUCCESS;\r
     }\r
-\r
\r
     dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
        "--> %s() EP %p %s rx_drq %d tx_drq %d Close %s\n", __FUNCTION__,\r
        ep_ptr, dapl_get_ep_state_str(ep_ptr->param.ep_state),\r
@@ -1314,12 +1406,12 @@ dapls_ib_reject_connection ( IN  dp_ib_cm_handle_t   ib_cm_handle,
     dapli_print_private_data("DsRjC",private_data,private_data_size);\r
 #endif\r
 \r
-    ib_status = ib_cm_rej ( *ib_cm_handle, &cm_rej);\r
+    ib_status = ib_cm_rej(ib_cm_handle->ib_cm, &cm_rej);\r
 \r
     if (ib_status != IB_SUCCESS)\r
     {\r
         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
-                       "--> DsRjC: cm_handle %lx reject failed %s\n", \r
+                       "--> DsRjC: cm_handle %p reject failed %s\n", \r
                        ib_cm_handle, ib_get_err_str(ib_status) );\r
     }\r
 \r
@@ -1390,6 +1482,7 @@ dapls_ib_accept_connection (
     dapl_ibal_port_t       *p_active_port;\r
     ib_cm_rep_t            cm_rep;\r
     ib_qp_attr_t           qpa;\r
+    dp_ib_cm_handle_t      cm_ptr;\r
 \r
     cr_ptr = (DAPL_CR *) cr_handle;\r
     ep_ptr = (DAPL_EP *) ep_handle;\r
@@ -1426,28 +1519,36 @@ dapls_ib_accept_connection (
     }\r
 \r
     cr_ptr->param.local_ep_handle = ep_handle;\r
-    ep_ptr->cm_handle             = cr_ptr->ib_cm_handle;\r
+\r
     /*\r
      * assume ownership, in that once the EP is released the dynamic\r
      * memory containing the IBAL CM handle (ib_cm_handle_t) struct will\r
      * be released; see dapl_ep_dealloc().\r
      */\r
-    ep_ptr->ibal_cm_handle        = cr_ptr->ib_cm_handle;\r
-\r
+   \r
+    /* EP-CM, save/release CR CM object, use EP CM object already linked */\r
+    cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
+    if (!cm_ptr) {\r
+       dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+                       "--> DsIBAC: CM linking to EP %p not available\n",\r
+                       ep_ptr);\r
+       return (DAT_INVALID_STATE);\r
+    }\r
+     \r
     /* set remote IP addr fields. IP addr data is deduced from Connection\r
      * Request record (gid/lib) and stashed away for use here. DAPL 1.1\r
      * had an interface for passing the IP info down, interface went away\r
      * in 2.0?\r
      */\r
     dapl_os_memcpy( (void*)&ep_ptr->remote_ia_address,\r
-                    (void*)(ep_ptr->cm_handle+1),\r
+                    (void*)&cr_ptr->ib_cm_handle->dst_ip_addr,\r
                     sizeof(DAT_SOCK_ADDR6) );\r
 \r
     dapl_os_memcpy( (void*)&cr_ptr->remote_ia_address,\r
                     (void*)&ep_ptr->remote_ia_address,\r
                     sizeof(DAT_SOCK_ADDR6) );\r
 \r
-#if defined(DAPL_DBG) && 0\r
+#if defined(DAPL_DBG)\r
     {\r
         char ipa[20];\r
 \r
@@ -1455,11 +1556,21 @@ dapls_ib_accept_connection (
                       "%s: EP(%lx) RemoteAddr: %s\n",\r
                       __FUNCTION__, ep_ptr,\r
                      dapli_get_ip_addr_str(\r
-                             (DAT_SOCK_ADDR6*)&ep_ptr->remote_ia_address, ipa));\r
+                            (DAT_SOCK_ADDR6*)&ep_ptr->remote_ia_address, ipa) );\r
     }\r
 #endif\r
 \r
-    ep_ptr->qp_state      = IB_QPS_INIT;\r
+    dapl_os_memcpy( (void*)&cm_ptr->dst_ip_addr,\r
+                    (void*)&cr_ptr->ib_cm_handle->dst_ip_addr,\r
+                    sizeof(DAT_SOCK_ADDR6) );\r
+\r
+    /* get h_al and connection ID from CR CM object, h_qp already set */\r
+    cm_ptr->ib_cm.cid = cr_ptr->ib_cm_handle->ib_cm.cid; \r
+    cm_ptr->ib_cm.h_al = cr_ptr->ib_cm_handle->ib_cm.h_al;\r
+    dapls_cm_release(cr_ptr->ib_cm_handle);\r
+\r
+    cr_ptr->ib_cm_handle = cm_ptr; /* for dapli_get_sp_ep() upcall */\r
+\r
     ep_ptr->cr_ptr        = cr_ptr;\r
 \r
     dapl_os_memzero ( (void*)&cm_rep, sizeof (ib_cm_rep_t) );\r
@@ -1526,19 +1637,13 @@ dapls_ib_accept_connection (
                 cm_rep.access_ctrl, cm_rep.init_depth,cm_rep.qp_type,\r
                  dapls_cb_pending(&ep_ptr->req_buffer));\r
 \r
-    ib_status = ib_cm_rep ( *ep_ptr->cm_handle, &cm_rep );\r
+    ib_status = ib_cm_rep ( cm_ptr->ib_cm, &cm_rep );\r
 \r
     if (ib_status != IB_SUCCESS)\r
     {\r
        dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
                        "--> DsIBAC: EP %lx QP %lx CR reply failed '%s'\n",\r
                        ep_ptr, ep_ptr->qp_handle, ib_get_err_str(ib_status) );\r
-\r
-        /* errors not perculated back to CR callback which allocated the\r
-         * memory, free it here on error.\r
-         */\r
-        dapl_os_free ( (void*)ep_ptr->ibal_cm_handle, sizeof(ib_cm_handle_t) );\r
-        ep_ptr->ibal_cm_handle = NULL;\r
     }\r
  \r
     return ( dapl_ib_status_convert ( ib_status ) );\r
@@ -1589,11 +1694,6 @@ dapls_ib_disconnect_clean (
     \r
     ep_ptr->sent_discreq = DAT_FALSE;\r
     ep_ptr->recv_discreq = DAT_FALSE;\r
-    if ( ep_ptr->ibal_cm_handle )\r
-    {\r
-        dapl_os_free ( (void*)ep_ptr->ibal_cm_handle, sizeof(ib_cm_handle_t) );\r
-    }\r
-    ep_ptr->ibal_cm_handle = NULL;\r
 \r
     /* \r
      * Query the QP to get the current state */\r
@@ -1653,7 +1753,7 @@ dapls_ib_cr_handoff (
     \r
     cr_ptr = (DAPL_CR *) cr_handle;\r
 \r
-    if (cr_ptr->ib_cm_handle->cid == 0xFFFFFFFF)\r
+    if (cr_ptr->ib_cm_handle->ib_cm.cid == 0xFFFFFFFF)\r
     {\r
         dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
                        "--> DsCH: CR = %lx invalid cm handle\n", cr_ptr);\r
@@ -1667,7 +1767,7 @@ dapls_ib_cr_handoff (
         return DAT_INVALID_PARAMETER;\r
     }\r
 \r
-    ib_status = ib_cm_handoff (*cr_ptr->ib_cm_handle, handoff_serv_id);\r
+    ib_status = ib_cm_handoff (cr_ptr->ib_cm_handle->ib_cm, handoff_serv_id);\r
 \r
     if (ib_status != IB_SUCCESS)\r
     {\r
index cc8c394a08911166dbb7a7476e897d4e65cd652f..eff6d11445462776963f35acfc9d963f7a80b837 100644 (file)
-
-/*
- * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.
- * Copyright (c) 2002, Network Appliance, Inc. All rights reserved. 
- * 
- * This Software is licensed under the terms of the "Common Public
- * License" a copy of which is in the file LICENSE.txt in the root
- * directory. The license is also available from the Open Source
- * Initiative, see http://www.opensource.org/licenses/cpl.php.
- *
- */
-
-/**********************************************************************
- * 
- * MODULE: dapl_ibal_qp.c
- *
- * PURPOSE: IB QP routines  for access to IBAL APIs
- *
- * $Id: dapl_ibal_qp.c 33 2005-07-11 19:51:17Z ftillier $
- *
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_adapter_util.h"
-#include "dapl_evd_util.h"
-#include "dapl_ibal_util.h"
-
-#define DAPL_IBAL_QKEY              0
-#define DAPL_IBAL_START_PSN         0
-
-extern DAT_RETURN
-dapls_ib_cq_late_alloc ( IN  ib_pd_handle_t        pd_handle,
-                         IN  DAPL_EVD              *evd_ptr );
-
-static void
-dapli_ib_qp_async_error_cb( IN  ib_async_event_rec_t* p_err_rec )
-{
-       DAPL_EP                 *ep_ptr = (DAPL_EP *)p_err_rec->context;
-       DAPL_EVD                *evd_ptr;
-       DAPL_IA                 *ia_ptr;
-       dapl_ibal_ca_t          *p_ca;
-        dapl_ibal_evd_cb_t     *evd_cb;
-
-        dapl_dbg_log (DAPL_DBG_TYPE_ERR,"--> DiQpAEC QP event %s qp ctx %p\n", 
-               ib_get_async_event_str(p_err_rec->code), p_err_rec->context);
-        dapl_dbg_log (DAPL_DBG_TYPE_ERR,"--> DiQpAEC qp_handle %p qpn %u\n", 
-               ((DAPL_EP *)p_err_rec->context)->qp_handle, 
-               ((DAPL_EP *)p_err_rec->context)->qpn);
-
-       /*
-        * Verify handles EP, EVD, and hca_handle
-        */
-       if (DAPL_BAD_HANDLE (ep_ptr, DAPL_MAGIC_EP ) ||
-           DAPL_BAD_HANDLE (ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD))
-       {
-               dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                               "--> DiQpAEC: invalid EP %p \n", ep_ptr);
-               return;
-       }
-       ia_ptr = ep_ptr->header.owner_ia;
-       evd_ptr = ia_ptr->async_error_evd;
-
-       if (DAPL_BAD_HANDLE (evd_ptr, DAPL_MAGIC_EVD) ||
-           ! (evd_ptr->evd_flags & DAT_EVD_ASYNC_FLAG))
-       {
-               dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                               "--> DiQpAEC: invalid EVD %p \n", evd_ptr);
-               return;
-       }
-       p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;
-       if (p_ca == NULL)
-       {
-               dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                               "--> DiQpAEC: can't find %s HCA\n", 
-                               (ia_ptr->header.provider)->device_name);
-               return;
-       }
-
-       /* find QP error callback using ia_ptr for context */
-       evd_cb = dapli_find_evd_cb_by_context (ia_ptr, p_ca);
-       if ((evd_cb == NULL) || (evd_cb->pfn_async_qp_err_cb == NULL))
-       {
-               dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                       "--> DiQpAEC: no ERROR cb on p_ca %p found\n", p_ca);
-               return;
-       }
-
-       dapl_os_lock (&ep_ptr->header.lock);
-       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING;
-       dapl_os_unlock (&ep_ptr->header.lock);
-
-       /* force disconnect, QP error state, to insure DTO's get flushed */
-       dapls_ib_disconnect ( ep_ptr, DAT_CLOSE_ABRUPT_FLAG );
-       
-       /* maps to dapl_evd_qp_async_error_callback(), context is EP */
-       evd_cb->pfn_async_qp_err_cb(    (ib_hca_handle_t)p_ca, 
-                                    ep_ptr->qp_handle,
-                                       (ib_error_record_t*)&p_err_rec->code,
-                                    ep_ptr );
-}
-
-/*
- * dapls_ib_qp_alloc
- *
- * Alloc a QP
- *
- * Input:
- *        *ia_ptr                pointer to DAPL IA
- *        *ep_ptr                pointer to DAPL EP
- *        *ep_ctx_ptr            pointer to DAPL EP context
- *
- * Output:
- *         none
- *
- * Returns:
- *        DAT_SUCCESS
- *        DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_qp_alloc (
-        IN  DAPL_IA                *ia_ptr,
-        IN  DAPL_EP                *ep_ptr,
-       IN  DAPL_EP                *ep_ctx_ptr)
-{
-    DAT_EP_ATTR           *attr;
-    DAPL_EVD              *recv_evd_ptr, *request_evd_ptr;
-    DAT_RETURN            dat_status;
-    ib_api_status_t       ib_status;
-    ib_qp_create_t        qp_create;
-    ib_pd_handle_t        ib_pd_handle;
-    ib_cq_handle_t        cq_recv;
-    ib_cq_handle_t        cq_send;
-    dapl_ibal_ca_t        *p_ca;
-    dapl_ibal_port_t      *p_active_port;
-    ib_qp_attr_t           qp_attr;
-
-    attr = &ep_ptr->param.ep_attr;
-
-    dapl_os_assert ( ep_ptr->param.pz_handle != NULL );
-
-    ib_pd_handle    = ((DAPL_PZ *)ep_ptr->param.pz_handle)->pd_handle;
-    dapl_os_assert(ib_pd_handle);
-    recv_evd_ptr    = (DAPL_EVD *) ep_ptr->param.recv_evd_handle;
-    request_evd_ptr = (DAPL_EVD *) ep_ptr->param.request_evd_handle;
-    
-    cq_recv = IB_INVALID_HANDLE;
-    cq_send = IB_INVALID_HANDLE;
-
-    dapl_os_assert ( recv_evd_ptr != DAT_HANDLE_NULL );
-    {
-        cq_recv = (ib_cq_handle_t) recv_evd_ptr->ib_cq_handle;
-        
-        if ((cq_recv == IB_INVALID_HANDLE) && 
-            ( 0 != (recv_evd_ptr->evd_flags & ~DAT_EVD_SOFTWARE_FLAG) ))
-        {
-            dat_status = dapls_ib_cq_late_alloc ( ib_pd_handle, recv_evd_ptr);
-            if (dat_status != DAT_SUCCESS)
-            {
-                dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                              "--> %s: failed to create CQ\n","DsQA");
-                return (dat_status);
-            }
-
-            dat_status = dapls_set_cq_notify (ia_ptr, recv_evd_ptr);
-
-            if (dat_status != DAT_SUCCESS)
-            {
-                dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                              "--> %s: failed to enable notify CQ\n","DsQA");
-                return (dat_status);
-            }
-        
-            cq_recv = (ib_cq_handle_t) recv_evd_ptr->ib_cq_handle;
-            dapl_dbg_log (DAPL_DBG_TYPE_EP, 
-                          "--> DsQA: alloc_recv_CQ = %p\n", cq_recv); 
-        
-        }
-    }
-
-    dapl_os_assert ( request_evd_ptr != DAT_HANDLE_NULL );
-    {
-        cq_send = (ib_cq_handle_t) request_evd_ptr->ib_cq_handle;
-        
-        if ((cq_send == IB_INVALID_HANDLE) && 
-            ( 0 != (request_evd_ptr->evd_flags & ~DAT_EVD_SOFTWARE_FLAG) ))
-        {
-            dat_status = dapls_ib_cq_late_alloc (ib_pd_handle, request_evd_ptr);
-            if (dat_status != DAT_SUCCESS)
-            {
-                dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                              "--> %s: failed to create CQ\n","DsQA");
-                return (dat_status);
-            }
-
-            dat_status = dapls_set_cq_notify (ia_ptr, request_evd_ptr);
-
-            if (dat_status != DAT_SUCCESS)
-            {
-                dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                              "--> %s: failed to enable notify CQ\n","DsQA");
-                return (dat_status);
-            }
-
-            cq_send = (ib_cq_handle_t) request_evd_ptr->ib_cq_handle;
-            dapl_dbg_log (DAPL_DBG_TYPE_EP, 
-                          "--> DsQA: alloc_send_CQ = %p\n", cq_send); 
-        }
-    }
-
-    /*
-     * Get the CA structure
-     */
-    p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;
-
-    dapl_os_memzero (&qp_create, sizeof (qp_create));
-    qp_create.qp_type     = IB_QPT_RELIABLE_CONN;
-    qp_create.sq_depth    = attr->max_request_dtos;
-    qp_create.rq_depth    = attr->max_recv_dtos;
-    qp_create.sq_sge      = attr->max_recv_iov;
-    qp_create.rq_sge      = attr->max_request_iov;                       
-    qp_create.h_sq_cq     = cq_send;
-    qp_create.h_rq_cq     = cq_recv;
-    qp_create.sq_signaled = FALSE;
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, 
-                  "--> DsQA: sqd,iov=%d,%d rqd,iov=%d,%d\n", 
-                  attr->max_request_dtos, attr->max_request_iov,
-                  attr->max_recv_dtos, attr->max_recv_iov); 
-    
-    ib_status = ib_create_qp ( 
-                       ib_pd_handle,
-                       &qp_create,
-                       (void *) ep_ctx_ptr /* context */,
-                       dapli_ib_qp_async_error_cb,
-                       &ep_ptr->qp_handle);
-
-    if (ib_status != IB_SUCCESS)
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsQA: Create QP failed = %s\n",
-                      ib_get_err_str(ib_status));
-       return (DAT_INSUFFICIENT_RESOURCES);
-    }
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQA: EP=%p, tEVD=%p, rEVD=%p QP=%p\n",
-                  ep_ptr, ep_ptr->param.request_evd_handle,
-                  ep_ptr->param.recv_evd_handle,
-                  ep_ptr->qp_handle ); 
-
-    ep_ptr->qp_state = IB_QPS_RESET;
-
-    p_active_port = dapli_ibal_get_port(p_ca,(uint8_t)ia_ptr->hca_ptr->port_num);
-
-    if (NULL == p_active_port)
-    {
-        dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                      "--> DsQA: Port %d is not available = %d\n",
-                      ia_ptr->hca_ptr->port_num, __LINE__);
-        return (DAT_INVALID_STATE);
-    }
-
-    ib_status = dapls_modify_qp_state_to_init ( ep_ptr->qp_handle, 
-                                               &ep_ptr->param.ep_attr,
-                                                p_active_port );
-
-    if ( ib_status != IB_SUCCESS )
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                      "--> DsQA: Change QP state to INIT failed = %s\n",
-                      ib_get_err_str(ib_status));
-       return (DAT_INVALID_HANDLE);
-    }
-    ib_status = ib_query_qp ( ep_ptr->qp_handle, &qp_attr );
-
-    ep_ptr->qp_state = qp_attr.state;
-    ep_ptr->qpn = qp_attr.num;
-    
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQAQA: EP:%p new_QP %p state %s\n",
-                  ep_ptr,
-                  ep_ptr->qp_handle,
-                  ib_get_port_state_str(ep_ptr->qp_state));
-
-    return (DAT_SUCCESS);
-}
-
-
-/*
- * dapls_ib_qp_free
- *
- * Free a QP
- *
- * Input:
- *        *ia_ptr                pointer to IA structure
- *        *ep_ptr                pointer to EP structure
- *
- * Output:
- *         none
- *
- * Returns:
- *         none
- *
- */
-DAT_RETURN
-dapls_ib_qp_free (
-        IN  DAPL_IA                *ia_ptr,
-        IN  DAPL_EP                *ep_ptr )
-{
-
-       ib_qp_handle_t          qp_handle;
-       UNREFERENCED_PARAMETER(ia_ptr);
-
-       dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQF: free %p, state %s\n", 
-                      ep_ptr->qp_handle,
-                      ib_get_port_state_str(ep_ptr->qp_state));
-
-       if (( ep_ptr->qp_handle != IB_INVALID_HANDLE ) &&
-           ( ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED ))
-       {
-               qp_handle = ep_ptr->qp_handle;
-               ep_ptr->qp_handle = IB_INVALID_HANDLE;
-               ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;
-               ib_destroy_qp ( qp_handle, NULL /* callback */);
-               dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQF: freed QP %p\n",
-                               qp_handle ); 
-       }
-
-    return DAT_SUCCESS;
-}
-
-
-/*
- * dapls_ib_qp_modify
- *
- * Set the QP to the parameters specified in an EP_PARAM
- *
- * We can't be sure what state the QP is in so we first obtain the state
- * from the driver. The EP_PARAM structure that is provided has been
- * sanitized such that only non-zero values are valid.
- *
- * Input:
- *        *ia_ptr                pointer to DAPL IA
- *        *ep_ptr                pointer to DAPL EP
- *        *ep_attr               pointer to DAT EP attribute
- *
- * Output:
- *         none
- *
- * Returns:
- *         DAT_SUCCESS
- *        DAT_INSUFFICIENT_RESOURCES
- *        DAT_INVALID_PARAMETER
- *
- */
-DAT_RETURN
-dapls_ib_qp_modify (
-        IN  DAPL_IA                        *ia_ptr,
-        IN  DAPL_EP                        *ep_ptr,
-        IN  DAT_EP_ATTR                    *ep_attr )
-{
-    ib_qp_attr_t                  qp_attr;
-    ib_api_status_t               ib_status;
-    ib_qp_handle_t                qp_handle;
-    ib_qp_state_t                 qp_state;
-    ib_qp_mod_t                   qp_mod;
-    ib_av_attr_t                  *p_av_attr;
-    ib_qp_opts_t                  *p_qp_opts;
-    uint32_t                      *p_sq_depth, *p_rq_depth;
-    DAT_BOOLEAN                   need_modify;
-    DAT_RETURN                    dat_status;
-
-    qp_handle     = ep_ptr->qp_handle;
-    need_modify   = DAT_FALSE;
-    dat_status    = DAT_SUCCESS;
-    if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )
-    {
-       dat_status = DAT_INVALID_HANDLE;
-       goto bail;
-    }
-    /* 
-     * Query the QP to get the current state.
-     */
-    ib_status = ib_query_qp ( qp_handle, &qp_attr );
-                       
-    if ( ib_status != IB_SUCCESS )
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsIQM: Query QP failed = %s\n",
-                       ib_get_err_str(ib_status));
-        dat_status = DAT_INTERNAL_ERROR;
-        goto bail;
-    }
-
-    qp_state = qp_attr.state;
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM: modify qp state=%d\n",qp_state);
-    /*
-     * Check if we have the right qp_state or not
-     */
-    if ( (qp_state != IB_QPS_RTR ) && (qp_state != IB_QPS_RTS ) )
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_EP,
-                      "--> DsIQM: postpone to modify qp to EP values later\n");
-        dat_status = DAT_SUCCESS;
-        goto bail;
-    }
-
-    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));
-
-    if (qp_state == IB_QPS_RTR)
-    {
-        p_av_attr   = &qp_mod.state.rtr.primary_av;
-        p_qp_opts   = &qp_mod.state.rtr.opts;
-        p_sq_depth  = &qp_mod.state.rtr.sq_depth;
-        p_rq_depth  = &qp_mod.state.rtr.rq_depth;
-    }
-    else
-    {
-        /*
-        * RTS does not have primary_av field
-        */
-        p_av_attr   = &qp_mod.state.rts.alternate_av;
-        p_qp_opts   = &qp_mod.state.rts.opts;
-        p_sq_depth  = &qp_mod.state.rts.sq_depth;
-        p_rq_depth  = &qp_mod.state.rts.rq_depth;
-    }
-
-    if ( (ep_attr->max_recv_dtos > 0) &&
-               ((DAT_UINT32)ep_attr->max_recv_dtos != qp_attr.rq_depth) )
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_EP,"--> DsIQM: rq_depth modified (%d,%d)\n",
-                       qp_attr.rq_depth, ep_attr->max_recv_dtos);
-
-        *p_rq_depth = ep_attr->max_recv_dtos;
-        *p_qp_opts |= IB_MOD_QP_RQ_DEPTH;
-        need_modify = DAT_TRUE;
-    }
-
-    if ( (ep_attr->max_request_dtos > 0) &&
-               ((DAT_UINT32)ep_attr->max_request_dtos != qp_attr.sq_depth) ) 
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_EP,
-                       "--> DsIQM: sq_depth modified (%d,%d)\n",
-                       qp_attr.sq_depth, ep_attr->max_request_dtos);
-
-        *p_sq_depth = ep_attr->max_request_dtos;
-        *p_qp_opts |= IB_MOD_QP_SQ_DEPTH;
-        need_modify = DAT_TRUE;
-    }
-
-    qp_mod.req_state  = qp_state;
-
-    if ( need_modify == DAT_TRUE )
-    {
-       ib_status = ib_modify_qp (qp_handle, &qp_mod);
-        if ( ib_status != IB_SUCCESS)
-        {
-           dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: ib_status = %d\n",
-                          "DsIQM", ib_status);
-           dat_status = DAT_INTERNAL_ERROR;
-        }
-    }
-
-bail:
-
-    return dat_status;
-}
-
-
-ib_api_status_t 
-dapls_modify_qp_state_to_error ( ib_qp_handle_t  qp_handle )
-{
-    ib_qp_mod_t      qp_mod;
-    ib_api_status_t  ib_status;
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_Err: QP state change --> Err\n");
-
-    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));
-
-    qp_mod.req_state  = IB_QPS_ERROR;
-
-    ib_status = ib_modify_qp (qp_handle, &qp_mod);
-
-    return (ib_status);
-}
-
-
-ib_api_status_t 
-dapls_modify_qp_state_to_reset ( ib_qp_handle_t  qp_handle )
-{
-    ib_qp_mod_t      qp_mod;
-    ib_api_status_t  ib_status;
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_RESET: QP state change\n");
-
-    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));
-
-    qp_mod.req_state  = IB_QPS_RESET;
-
-    ib_status = ib_modify_qp (qp_handle, &qp_mod);
-
-    return (ib_status);
-}
-
-
-ib_api_status_t 
-dapls_modify_qp_state_to_init (
-        IN    ib_qp_handle_t         qp_handle,
-        IN    DAT_EP_ATTR            *p_attr,
-        IN    dapl_ibal_port_t       *p_port )
-{
-    ib_qp_mod_t                   qp_mod;
-    ib_api_status_t               ib_status;
-
-    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));
-
-    qp_mod.req_state               = IB_QPS_INIT;
-    qp_mod.state.init.primary_port = p_port->p_attr->port_num;
-    qp_mod.state.init.qkey         = DAPL_IBAL_QKEY;
-    qp_mod.state.init.pkey_index   = 0;
-    qp_mod.state.init.access_ctrl = IB_AC_LOCAL_WRITE |
-                                       IB_AC_RDMA_WRITE |
-                                       IB_AC_MW_BIND |
-                                       IB_AC_ATOMIC;
-    if ((p_attr->max_rdma_read_in > 0) || (p_attr->max_rdma_read_out > 0))
-    {
-       qp_mod.state.init.access_ctrl |= IB_AC_RDMA_READ;
-    }
-    ib_status = ib_modify_qp (qp_handle, &qp_mod);
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_INIT: QP(%p) state change, %s\n",
-                  qp_handle, ib_get_err_str(ib_status));
-
-    return (ib_status);
-}
-
-
-ib_api_status_t 
-dapls_modify_qp_state_to_rtr (
-        ib_qp_handle_t          qp_handle,
-        ib_net32_t              dest_qp,
-        ib_lid_t                dest_lid,
-        dapl_ibal_port_t        *p_port)
-{
-    ib_qp_mod_t                 qp_mod;
-    ib_api_status_t             ib_status;
-
-    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));
-
-    qp_mod.req_state                        = IB_QPS_RTR;
-    qp_mod.state.rtr.rq_psn                 = DAPL_IBAL_START_PSN;
-    qp_mod.state.rtr.dest_qp                = dest_qp;
-    qp_mod.state.rtr.primary_av.port_num    = p_port->p_attr->port_num;
-    qp_mod.state.rtr.primary_av.sl          = 0;
-    qp_mod.state.rtr.primary_av.dlid        = dest_lid;
-    qp_mod.state.rtr.primary_av.grh_valid   = 0; /* FALSE */
-    qp_mod.state.rtr.primary_av.static_rate = IB_PATH_RECORD_RATE_10_GBS;
-    qp_mod.state.rtr.primary_av.path_bits   = 0;
-    qp_mod.state.rtr.primary_av.conn.path_mtu = p_port->p_attr->mtu;
-    qp_mod.state.rtr.primary_av.conn.local_ack_timeout = 7;
-    qp_mod.state.rtr.primary_av.conn.seq_err_retry_cnt = 7;
-    qp_mod.state.rtr.primary_av.conn.rnr_retry_cnt = IB_RNR_RETRY_CNT;
-    qp_mod.state.rtr.resp_res               = 4; // in-flight RDMAs
-    qp_mod.state.rtr.rnr_nak_timeout        = IB_RNR_NAK_TIMEOUT;
-    ib_status = ib_modify_qp (qp_handle, &qp_mod);
-    
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_RTR: QP(%p) state change %s\n",
-                  qp_handle, ib_get_err_str(ib_status));
-
-    return (ib_status);
-}
-
-ib_api_status_t 
-dapls_modify_qp_state_to_rts ( ib_qp_handle_t  qp_handle )
-{
-    ib_qp_mod_t        qp_mod;
-    ib_api_status_t    ib_status;
-
-    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));
-
-    qp_mod.req_state                   = IB_QPS_RTS;
-    qp_mod.state.rts.sq_psn            = DAPL_IBAL_START_PSN;
-    qp_mod.state.rts.retry_cnt         = 7;
-    qp_mod.state.rts.rnr_retry_cnt     = IB_RNR_RETRY_CNT;
-    qp_mod.state.rtr.rnr_nak_timeout   = IB_RNR_NAK_TIMEOUT;
-    qp_mod.state.rts.local_ack_timeout = 7;
-    qp_mod.state.rts.init_depth        = 4; 
-
-    ib_status = ib_modify_qp (qp_handle, &qp_mod);
-
-    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_RTS: QP(%p) state change %s\n",
-                  qp_handle, ib_get_err_str(ib_status));
-
-    return (ib_status);
-}
-
-
-/*
- * dapls_ib_reinit_ep
- *
- * Move the QP to INIT state again.
- *
- * Input:
- *     ep_ptr          DAPL_EP
- *
- * Output:
- *     none
- *
- * Returns:
- *     void
- *
- */
-void
-dapls_ib_reinit_ep ( IN DAPL_EP  *ep_ptr )
-{
-    DAPL_IA                  *ia_ptr;
-    ib_api_status_t          ib_status;
-    dapl_ibal_ca_t           *p_ca;
-    dapl_ibal_port_t         *p_active_port;
-       
-    dapl_dbg_log (DAPL_DBG_TYPE_EP,
-                  "--> DsIQM_REINIT: EP(%p) QP(%p) state change\n", 
-                  ep_ptr, ep_ptr->qp_handle );
-
-    if ( ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECTED )
-    {
-       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsIRE: EP invalid state(%d)\n",
-                      ep_ptr->param.ep_state);
-       return /*DAT_INVALID_STATE*/;
-    }
-
-    ia_ptr = ep_ptr->header.owner_ia;
-
-    /* Re-create QP if cleaned up, alloc will return init state */
-    if ( ep_ptr->qp_handle == IB_INVALID_HANDLE )
-    {
-        dapl_dbg_log (DAPL_DBG_TYPE_EP,
-                      "--> DsIRE: !EP(%p)->qp_handle, re-create QP\n",ep_ptr);
-        ib_status = dapls_ib_qp_alloc ( ia_ptr, ep_ptr, ep_ptr );
-        if ( ib_status != IB_SUCCESS )
-        {
-            dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                      "--> DsIRE: failed to move qp to RESET status = %s\n", 
-                      ib_get_err_str(ib_status));
-        }
-        return /*ib_status*/;
-    }
-
-    ib_status = dapls_modify_qp_state_to_reset (ep_ptr->qp_handle);
-
-    if ( ib_status != IB_SUCCESS )
-    {
-        dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                      "--> DsIRE: failed to move qp to RESET status = %s\n", 
-                      ib_get_err_str(ib_status));
-        return /*DAT_INTERNAL_ERROR*/;
-    }
-
-    ep_ptr->qp_state = IB_QPS_RESET;
-
-    p_ca   = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;
-    p_active_port = dapli_ibal_get_port ( p_ca,
-                                          (uint8_t)ia_ptr->hca_ptr->port_num );
-    if (NULL == p_active_port)
-    {
-        dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                     "--> DsIRE: Port %d is not available = %d\n",
-                     ia_ptr->hca_ptr->port_num, __LINE__);
-        return /*DAT_INTERNAL_ERROR*/;
-    }
-
-       /* May fail if QP still RESET and in timewait, keep in reset state */
-    ib_status = dapls_modify_qp_state_to_init ( ep_ptr->qp_handle,
-                                                &ep_ptr->param.ep_attr,
-                                                p_active_port);
-    if ( ib_status != IB_SUCCESS )
-    {
-        ep_ptr->qp_state = IB_QPS_RESET;
-
-        dapl_dbg_log (DAPL_DBG_TYPE_ERR,
-                      "--> DsIRE: failed to move qp to INIT status %s\n", 
-                      ib_get_err_str(ib_status));
-        return /*DAT_INTERNAL_ERROR*/;
-    }
-    ep_ptr->qp_state = IB_QPS_INIT;
-}
-
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 8
- * End:
- */
-
+\r
+/*\r
+ * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.\r
+ * Copyright (c) 2002, Network Appliance, Inc. All rights reserved. \r
+ * \r
+ * This Software is licensed under the terms of the "Common Public\r
+ * License" a copy of which is in the file LICENSE.txt in the root\r
+ * directory. The license is also available from the Open Source\r
+ * Initiative, see http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_ibal_qp.c\r
+ *\r
+ * PURPOSE: IB QP routines  for access to IBAL APIs\r
+ *\r
+ * $Id: dapl_ibal_qp.c 33 2005-07-11 19:51:17Z ftillier $\r
+ *\r
+ **********************************************************************/\r
+\r
+#include "dapl.h"\r
+#include "dapl_adapter_util.h"\r
+#include "dapl_evd_util.h"\r
+#include "dapl_ibal_util.h"\r
+#include "dapl_ep_util.h"\r
+\r
+#define DAPL_IBAL_QKEY              0\r
+#define DAPL_IBAL_START_PSN         0\r
+\r
+extern DAT_RETURN\r
+dapls_ib_cq_late_alloc ( IN  ib_pd_handle_t        pd_handle,\r
+                         IN  DAPL_EVD              *evd_ptr );\r
+\r
+static void\r
+dapli_ib_qp_async_error_cb( IN  ib_async_event_rec_t* p_err_rec )\r
+{\r
+       DAPL_EP                 *ep_ptr = (DAPL_EP *)p_err_rec->context;\r
+       DAPL_EVD                *evd_ptr;\r
+       DAPL_IA                 *ia_ptr;\r
+       dapl_ibal_ca_t          *p_ca;\r
+        dapl_ibal_evd_cb_t     *evd_cb;\r
+\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,"--> DiQpAEC QP event %s qp ctx %p\n", \r
+               ib_get_async_event_str(p_err_rec->code), p_err_rec->context);\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,"--> DiQpAEC qp_handle %p qpn %u\n", \r
+               ((DAPL_EP *)p_err_rec->context)->qp_handle, \r
+               ((DAPL_EP *)p_err_rec->context)->qpn);\r
+\r
+       /*\r
+        * Verify handles EP, EVD, and hca_handle\r
+        */\r
+       if (DAPL_BAD_HANDLE (ep_ptr, DAPL_MAGIC_EP ) ||\r
+           DAPL_BAD_HANDLE (ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD))\r
+       {\r
+               dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                               "--> DiQpAEC: invalid EP %p \n", ep_ptr);\r
+               return;\r
+       }\r
+       ia_ptr = ep_ptr->header.owner_ia;\r
+       evd_ptr = ia_ptr->async_error_evd;\r
+\r
+       if (DAPL_BAD_HANDLE (evd_ptr, DAPL_MAGIC_EVD) ||\r
+           ! (evd_ptr->evd_flags & DAT_EVD_ASYNC_FLAG))\r
+       {\r
+               dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                               "--> DiQpAEC: invalid EVD %p \n", evd_ptr);\r
+               return;\r
+       }\r
+       p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
+       if (p_ca == NULL)\r
+       {\r
+               dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                               "--> DiQpAEC: can't find %s HCA\n", \r
+                               (ia_ptr->header.provider)->device_name);\r
+               return;\r
+       }\r
+\r
+       /* find QP error callback using ia_ptr for context */\r
+       evd_cb = dapli_find_evd_cb_by_context (ia_ptr, p_ca);\r
+       if ((evd_cb == NULL) || (evd_cb->pfn_async_qp_err_cb == NULL))\r
+       {\r
+               dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                       "--> DiQpAEC: no ERROR cb on p_ca %p found\n", p_ca);\r
+               return;\r
+       }\r
+\r
+       dapl_os_lock (&ep_ptr->header.lock);\r
+       ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING;\r
+       dapl_os_unlock (&ep_ptr->header.lock);\r
+\r
+       /* force disconnect, QP error state, to insure DTO's get flushed */\r
+       dapls_ib_disconnect ( ep_ptr, DAT_CLOSE_ABRUPT_FLAG );\r
+       \r
+       /* maps to dapl_evd_qp_async_error_callback(), context is EP */\r
+       evd_cb->pfn_async_qp_err_cb(    (ib_hca_handle_t)p_ca, \r
+                                    ep_ptr->qp_handle,\r
+                                       (ib_error_record_t*)&p_err_rec->code,\r
+                                    ep_ptr );\r
+}\r
+\r
+/*\r
+ * dapls_ib_qp_alloc\r
+ *\r
+ * Alloc a QP\r
+ *\r
+ * Input:\r
+ *        *ia_ptr                pointer to DAPL IA\r
+ *        *ep_ptr                pointer to DAPL EP\r
+ *        *ep_ctx_ptr            pointer to DAPL EP context\r
+ *\r
+ * Output:\r
+ *         none\r
+ *\r
+ * Returns:\r
+ *        DAT_SUCCESS\r
+ *        DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_qp_alloc (\r
+        IN  DAPL_IA                *ia_ptr,\r
+        IN  DAPL_EP                *ep_ptr,\r
+       IN  DAPL_EP                *ep_ctx_ptr)\r
+{\r
+    DAT_EP_ATTR           *attr;\r
+    DAPL_EVD              *recv_evd_ptr, *request_evd_ptr;\r
+    DAT_RETURN            dat_status;\r
+    ib_api_status_t       ib_status;\r
+    ib_qp_create_t        qp_create;\r
+    ib_pd_handle_t        ib_pd_handle;\r
+    ib_cq_handle_t        cq_recv;\r
+    ib_cq_handle_t        cq_send;\r
+    dapl_ibal_ca_t        *p_ca;\r
+    dapl_ibal_port_t      *p_active_port;\r
+    ib_qp_attr_t          qp_attr;\r
+    dp_ib_cm_handle_t     cm_ptr;\r
+\r
+    attr = &ep_ptr->param.ep_attr;\r
+\r
+    dapl_os_assert ( ep_ptr->param.pz_handle != NULL );\r
+\r
+    ib_pd_handle    = ((DAPL_PZ *)ep_ptr->param.pz_handle)->pd_handle;\r
+    dapl_os_assert(ib_pd_handle);\r
+    recv_evd_ptr    = (DAPL_EVD *) ep_ptr->param.recv_evd_handle;\r
+    request_evd_ptr = (DAPL_EVD *) ep_ptr->param.request_evd_handle;\r
+    \r
+    cq_recv = IB_INVALID_HANDLE;\r
+    cq_send = IB_INVALID_HANDLE;\r
+\r
+    dapl_os_assert ( recv_evd_ptr != DAT_HANDLE_NULL );\r
+    {\r
+        cq_recv = (ib_cq_handle_t) recv_evd_ptr->ib_cq_handle;\r
+        \r
+        if ((cq_recv == IB_INVALID_HANDLE) && \r
+            ( 0 != (recv_evd_ptr->evd_flags & ~DAT_EVD_SOFTWARE_FLAG) ))\r
+        {\r
+            dat_status = dapls_ib_cq_late_alloc ( ib_pd_handle, recv_evd_ptr);\r
+            if (dat_status != DAT_SUCCESS)\r
+            {\r
+                dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                              "--> %s: failed to create CQ\n","DsQA");\r
+                return (dat_status);\r
+            }\r
+\r
+            dat_status = dapls_set_cq_notify (ia_ptr, recv_evd_ptr);\r
+\r
+            if (dat_status != DAT_SUCCESS)\r
+            {\r
+                dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                              "--> %s: failed to enable notify CQ\n","DsQA");\r
+                return (dat_status);\r
+            }\r
+        \r
+            cq_recv = (ib_cq_handle_t) recv_evd_ptr->ib_cq_handle;\r
+            dapl_dbg_log (DAPL_DBG_TYPE_EP, \r
+                          "--> DsQA: alloc_recv_CQ = %p\n", cq_recv); \r
+        \r
+        }\r
+    }\r
+\r
+    dapl_os_assert ( request_evd_ptr != DAT_HANDLE_NULL );\r
+    {\r
+        cq_send = (ib_cq_handle_t) request_evd_ptr->ib_cq_handle;\r
+        \r
+        if ((cq_send == IB_INVALID_HANDLE) && \r
+            ( 0 != (request_evd_ptr->evd_flags & ~DAT_EVD_SOFTWARE_FLAG) ))\r
+        {\r
+            dat_status = dapls_ib_cq_late_alloc (ib_pd_handle, request_evd_ptr);\r
+            if (dat_status != DAT_SUCCESS)\r
+            {\r
+                dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                              "--> %s: failed to create CQ\n","DsQA");\r
+                return (dat_status);\r
+            }\r
+\r
+            dat_status = dapls_set_cq_notify (ia_ptr, request_evd_ptr);\r
+\r
+            if (dat_status != DAT_SUCCESS)\r
+            {\r
+                dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                              "--> %s: failed to enable notify CQ\n","DsQA");\r
+                return (dat_status);\r
+            }\r
+\r
+            cq_send = (ib_cq_handle_t) request_evd_ptr->ib_cq_handle;\r
+            dapl_dbg_log (DAPL_DBG_TYPE_EP, \r
+                          "--> DsQA: alloc_send_CQ = %p\n", cq_send); \r
+        }\r
+    }\r
+\r
+    /*\r
+     * Get the CA structure\r
+     */\r
+    p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
+\r
+    dapl_os_memzero (&qp_create, sizeof (qp_create));\r
+    qp_create.qp_type     = IB_QPT_RELIABLE_CONN;\r
+    qp_create.sq_depth    = attr->max_request_dtos;\r
+    qp_create.rq_depth    = attr->max_recv_dtos;\r
+    qp_create.sq_sge      = attr->max_recv_iov;\r
+    qp_create.rq_sge      = attr->max_request_iov;                       \r
+    qp_create.h_sq_cq     = cq_send;\r
+    qp_create.h_rq_cq     = cq_recv;\r
+    qp_create.sq_signaled = FALSE;\r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, \r
+                  "--> DsQA: sqd,iov=%d,%d rqd,iov=%d,%d\n", \r
+                  attr->max_request_dtos, attr->max_request_iov,\r
+                  attr->max_recv_dtos, attr->max_recv_iov); \r
+    \r
+    ib_status = ib_create_qp ( \r
+                       ib_pd_handle,\r
+                       &qp_create,\r
+                       (void *) ep_ctx_ptr /* context */,\r
+                       dapli_ib_qp_async_error_cb,\r
+                       &ep_ptr->qp_handle);\r
+\r
+    if (ib_status != IB_SUCCESS)\r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsQA: Create QP failed = %s\n",\r
+                      ib_get_err_str(ib_status));\r
+       return (DAT_INSUFFICIENT_RESOURCES);\r
+    }\r
+    /* EP-CM linking */\r
+    cm_ptr = ibal_cm_alloc();\r
+    if (!cm_ptr) \r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsQA: Create CM failed\n");\r
+       return (DAT_INSUFFICIENT_RESOURCES);\r
+    }\r
+    cm_ptr->ib_cm.h_qp = ep_ptr->qp_handle;\r
+    cm_ptr->ep = ep_ptr;\r
+    dapl_ep_link_cm(ep_ptr, cm_ptr); \r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQA: EP=%p, tEVD=%p, rEVD=%p QP=%p\n",\r
+                  ep_ptr, ep_ptr->param.request_evd_handle,\r
+                  ep_ptr->param.recv_evd_handle,\r
+                  ep_ptr->qp_handle ); \r
+\r
+    ep_ptr->qp_state = IB_QPS_RESET;\r
+\r
+    p_active_port = dapli_ibal_get_port(p_ca,(uint8_t)ia_ptr->hca_ptr->port_num);\r
+\r
+    if (NULL == p_active_port)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> DsQA: Port %d is not available = %d\n",\r
+                      ia_ptr->hca_ptr->port_num, __LINE__);\r
+        return (DAT_INVALID_STATE);\r
+    }\r
+\r
+    ib_status = dapls_modify_qp_state_to_init ( ep_ptr->qp_handle, \r
+                                               &ep_ptr->param.ep_attr,\r
+                                                p_active_port );\r
+\r
+    if ( ib_status != IB_SUCCESS )\r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> DsQA: Change QP state to INIT failed = %s\n",\r
+                      ib_get_err_str(ib_status));\r
+       return (DAT_INVALID_HANDLE);\r
+    }\r
+    ib_status = ib_query_qp ( ep_ptr->qp_handle, &qp_attr );\r
+\r
+    ep_ptr->qp_state = qp_attr.state;\r
+    ep_ptr->qpn = qp_attr.num;\r
+    \r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQAQA: EP:%p new_QP %p state %s\n",\r
+                  ep_ptr,\r
+                  ep_ptr->qp_handle,\r
+                  ib_get_port_state_str(ep_ptr->qp_state));\r
+\r
+    return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_qp_free\r
+ *\r
+ * Free a QP\r
+ *\r
+ * Input:\r
+ *        *ia_ptr                pointer to IA structure\r
+ *        *ep_ptr                pointer to EP structure\r
+ *\r
+ * Output:\r
+ *         none\r
+ *\r
+ * Returns:\r
+ *         none\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_qp_free (\r
+        IN  DAPL_IA                *ia_ptr,\r
+        IN  DAPL_EP                *ep_ptr )\r
+{\r
+\r
+       ib_qp_handle_t          qp_handle;\r
+       UNREFERENCED_PARAMETER(ia_ptr);\r
+\r
+       dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQF: free %p, state %s\n", \r
+                      ep_ptr->qp_handle,\r
+                      ib_get_port_state_str(ep_ptr->qp_state));\r
+\r
+       if (( ep_ptr->qp_handle != IB_INVALID_HANDLE ) &&\r
+           ( ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED ))\r
+       {\r
+               qp_handle = ep_ptr->qp_handle;\r
+               ep_ptr->qp_handle = IB_INVALID_HANDLE;\r
+               ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;\r
+               ib_destroy_qp ( qp_handle, NULL /* callback */);\r
+               dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsQF: freed QP %p\n",\r
+                               qp_handle ); \r
+       }\r
+\r
+    return DAT_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_qp_modify\r
+ *\r
+ * Set the QP to the parameters specified in an EP_PARAM\r
+ *\r
+ * We can't be sure what state the QP is in so we first obtain the state\r
+ * from the driver. The EP_PARAM structure that is provided has been\r
+ * sanitized such that only non-zero values are valid.\r
+ *\r
+ * Input:\r
+ *        *ia_ptr                pointer to DAPL IA\r
+ *        *ep_ptr                pointer to DAPL EP\r
+ *        *ep_attr               pointer to DAT EP attribute\r
+ *\r
+ * Output:\r
+ *         none\r
+ *\r
+ * Returns:\r
+ *         DAT_SUCCESS\r
+ *        DAT_INSUFFICIENT_RESOURCES\r
+ *        DAT_INVALID_PARAMETER\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_qp_modify (\r
+        IN  DAPL_IA                        *ia_ptr,\r
+        IN  DAPL_EP                        *ep_ptr,\r
+        IN  DAT_EP_ATTR                    *ep_attr )\r
+{\r
+    ib_qp_attr_t                  qp_attr;\r
+    ib_api_status_t               ib_status;\r
+    ib_qp_handle_t                qp_handle;\r
+    ib_qp_state_t                 qp_state;\r
+    ib_qp_mod_t                   qp_mod;\r
+    ib_av_attr_t                  *p_av_attr;\r
+    ib_qp_opts_t                  *p_qp_opts;\r
+    uint32_t                      *p_sq_depth, *p_rq_depth;\r
+    DAT_BOOLEAN                   need_modify;\r
+    DAT_RETURN                    dat_status;\r
+\r
+    qp_handle     = ep_ptr->qp_handle;\r
+    need_modify   = DAT_FALSE;\r
+    dat_status    = DAT_SUCCESS;\r
+    if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )\r
+    {\r
+       dat_status = DAT_INVALID_HANDLE;\r
+       goto bail;\r
+    }\r
+    /* \r
+     * Query the QP to get the current state.\r
+     */\r
+    ib_status = ib_query_qp ( qp_handle, &qp_attr );\r
+                       \r
+    if ( ib_status != IB_SUCCESS )\r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsIQM: Query QP failed = %s\n",\r
+                       ib_get_err_str(ib_status));\r
+        dat_status = DAT_INTERNAL_ERROR;\r
+        goto bail;\r
+    }\r
+\r
+    qp_state = qp_attr.state;\r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM: modify qp state=%d\n",qp_state);\r
+    /*\r
+     * Check if we have the right qp_state or not\r
+     */\r
+    if ( (qp_state != IB_QPS_RTR ) && (qp_state != IB_QPS_RTS ) )\r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_EP,\r
+                      "--> DsIQM: postpone to modify qp to EP values later\n");\r
+        dat_status = DAT_SUCCESS;\r
+        goto bail;\r
+    }\r
+\r
+    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));\r
+\r
+    if (qp_state == IB_QPS_RTR)\r
+    {\r
+        p_av_attr   = &qp_mod.state.rtr.primary_av;\r
+        p_qp_opts   = &qp_mod.state.rtr.opts;\r
+        p_sq_depth  = &qp_mod.state.rtr.sq_depth;\r
+        p_rq_depth  = &qp_mod.state.rtr.rq_depth;\r
+    }\r
+    else\r
+    {\r
+        /*\r
+        * RTS does not have primary_av field\r
+        */\r
+        p_av_attr   = &qp_mod.state.rts.alternate_av;\r
+        p_qp_opts   = &qp_mod.state.rts.opts;\r
+        p_sq_depth  = &qp_mod.state.rts.sq_depth;\r
+        p_rq_depth  = &qp_mod.state.rts.rq_depth;\r
+    }\r
+\r
+    if ( (ep_attr->max_recv_dtos > 0) &&\r
+               ((DAT_UINT32)ep_attr->max_recv_dtos != qp_attr.rq_depth) )\r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_EP,"--> DsIQM: rq_depth modified (%d,%d)\n",\r
+                       qp_attr.rq_depth, ep_attr->max_recv_dtos);\r
+\r
+        *p_rq_depth = ep_attr->max_recv_dtos;\r
+        *p_qp_opts |= IB_MOD_QP_RQ_DEPTH;\r
+        need_modify = DAT_TRUE;\r
+    }\r
+\r
+    if ( (ep_attr->max_request_dtos > 0) &&\r
+               ((DAT_UINT32)ep_attr->max_request_dtos != qp_attr.sq_depth) ) \r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_EP,\r
+                       "--> DsIQM: sq_depth modified (%d,%d)\n",\r
+                       qp_attr.sq_depth, ep_attr->max_request_dtos);\r
+\r
+        *p_sq_depth = ep_attr->max_request_dtos;\r
+        *p_qp_opts |= IB_MOD_QP_SQ_DEPTH;\r
+        need_modify = DAT_TRUE;\r
+    }\r
+\r
+    qp_mod.req_state  = qp_state;\r
+\r
+    if ( need_modify == DAT_TRUE )\r
+    {\r
+       ib_status = ib_modify_qp (qp_handle, &qp_mod);\r
+        if ( ib_status != IB_SUCCESS)\r
+        {\r
+           dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: ib_status = %d\n",\r
+                          "DsIQM", ib_status);\r
+           dat_status = DAT_INTERNAL_ERROR;\r
+        }\r
+    }\r
+\r
+bail:\r
+\r
+    return dat_status;\r
+}\r
+\r
+\r
+ib_api_status_t \r
+dapls_modify_qp_state_to_error ( ib_qp_handle_t  qp_handle )\r
+{\r
+    ib_qp_mod_t      qp_mod;\r
+    ib_api_status_t  ib_status;\r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_Err: QP state change --> Err\n");\r
+\r
+    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));\r
+\r
+    qp_mod.req_state  = IB_QPS_ERROR;\r
+\r
+    ib_status = ib_modify_qp (qp_handle, &qp_mod);\r
+\r
+    return (ib_status);\r
+}\r
+\r
+\r
+ib_api_status_t \r
+dapls_modify_qp_state_to_reset ( ib_qp_handle_t  qp_handle )\r
+{\r
+    ib_qp_mod_t      qp_mod;\r
+    ib_api_status_t  ib_status;\r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_RESET: QP state change\n");\r
+\r
+    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));\r
+\r
+    qp_mod.req_state  = IB_QPS_RESET;\r
+\r
+    ib_status = ib_modify_qp (qp_handle, &qp_mod);\r
+\r
+    return (ib_status);\r
+}\r
+\r
+\r
+ib_api_status_t \r
+dapls_modify_qp_state_to_init (\r
+        IN    ib_qp_handle_t         qp_handle,\r
+        IN    DAT_EP_ATTR            *p_attr,\r
+        IN    dapl_ibal_port_t       *p_port )\r
+{\r
+    ib_qp_mod_t                   qp_mod;\r
+    ib_api_status_t               ib_status;\r
+\r
+    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));\r
+\r
+    qp_mod.req_state               = IB_QPS_INIT;\r
+    qp_mod.state.init.primary_port = p_port->p_attr->port_num;\r
+    qp_mod.state.init.qkey         = DAPL_IBAL_QKEY;\r
+    qp_mod.state.init.pkey_index   = 0;\r
+    qp_mod.state.init.access_ctrl = IB_AC_LOCAL_WRITE |\r
+                                       IB_AC_RDMA_WRITE |\r
+                                       IB_AC_MW_BIND |\r
+                                       IB_AC_ATOMIC;\r
+    if ((p_attr->max_rdma_read_in > 0) || (p_attr->max_rdma_read_out > 0))\r
+    {\r
+       qp_mod.state.init.access_ctrl |= IB_AC_RDMA_READ;\r
+    }\r
+    ib_status = ib_modify_qp (qp_handle, &qp_mod);\r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_INIT: QP(%p) state change, %s\n",\r
+                  qp_handle, ib_get_err_str(ib_status));\r
+\r
+    return (ib_status);\r
+}\r
+\r
+\r
+ib_api_status_t \r
+dapls_modify_qp_state_to_rtr (\r
+        ib_qp_handle_t          qp_handle,\r
+        ib_net32_t              dest_qp,\r
+        ib_lid_t                dest_lid,\r
+        dapl_ibal_port_t        *p_port)\r
+{\r
+    ib_qp_mod_t                 qp_mod;\r
+    ib_api_status_t             ib_status;\r
+\r
+    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));\r
+\r
+    qp_mod.req_state                        = IB_QPS_RTR;\r
+    qp_mod.state.rtr.rq_psn                 = DAPL_IBAL_START_PSN;\r
+    qp_mod.state.rtr.dest_qp                = dest_qp;\r
+    qp_mod.state.rtr.primary_av.port_num    = p_port->p_attr->port_num;\r
+    qp_mod.state.rtr.primary_av.sl          = 0;\r
+    qp_mod.state.rtr.primary_av.dlid        = dest_lid;\r
+    qp_mod.state.rtr.primary_av.grh_valid   = 0; /* FALSE */\r
+    qp_mod.state.rtr.primary_av.static_rate = IB_PATH_RECORD_RATE_10_GBS;\r
+    qp_mod.state.rtr.primary_av.path_bits   = 0;\r
+    qp_mod.state.rtr.primary_av.conn.path_mtu = p_port->p_attr->mtu;\r
+    qp_mod.state.rtr.primary_av.conn.local_ack_timeout = 7;\r
+    qp_mod.state.rtr.primary_av.conn.seq_err_retry_cnt = 7;\r
+    qp_mod.state.rtr.primary_av.conn.rnr_retry_cnt = IB_RNR_RETRY_CNT;\r
+    qp_mod.state.rtr.resp_res               = 4; // in-flight RDMAs\r
+    qp_mod.state.rtr.rnr_nak_timeout        = IB_RNR_NAK_TIMEOUT;\r
\r
+    ib_status = ib_modify_qp (qp_handle, &qp_mod);\r
+    \r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_RTR: QP(%p) state change %s\n",\r
+                  qp_handle, ib_get_err_str(ib_status));\r
+\r
+    return (ib_status);\r
+}\r
+\r
+ib_api_status_t \r
+dapls_modify_qp_state_to_rts ( ib_qp_handle_t  qp_handle )\r
+{\r
+    ib_qp_mod_t        qp_mod;\r
+    ib_api_status_t    ib_status;\r
+\r
+    dapl_os_memzero (&qp_mod, sizeof (ib_qp_mod_t));\r
+\r
+    qp_mod.req_state                   = IB_QPS_RTS;\r
+    qp_mod.state.rts.sq_psn            = DAPL_IBAL_START_PSN;\r
+    qp_mod.state.rts.retry_cnt         = 7;\r
+    qp_mod.state.rts.rnr_retry_cnt     = IB_RNR_RETRY_CNT;\r
+    qp_mod.state.rtr.rnr_nak_timeout   = IB_RNR_NAK_TIMEOUT;\r
+    qp_mod.state.rts.local_ack_timeout = 7;\r
+    qp_mod.state.rts.init_depth        = 4; \r
+\r
+    ib_status = ib_modify_qp (qp_handle, &qp_mod);\r
+\r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsIQM_RTS: QP(%p) state change %s\n",\r
+                  qp_handle, ib_get_err_str(ib_status));\r
+\r
+    return (ib_status);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_reinit_ep\r
+ *\r
+ * Move the QP to INIT state again.\r
+ *\r
+ * Input:\r
+ *     ep_ptr          DAPL_EP\r
+ *\r
+ * Output:\r
+ *     none\r
+ *\r
+ * Returns:\r
+ *     void\r
+ *\r
+ */\r
+void\r
+dapls_ib_reinit_ep ( IN DAPL_EP  *ep_ptr )\r
+{\r
+    DAPL_IA                  *ia_ptr;\r
+    ib_api_status_t          ib_status;\r
+    dapl_ibal_ca_t           *p_ca;\r
+    dapl_ibal_port_t         *p_active_port;\r
+       \r
+    dapl_dbg_log (DAPL_DBG_TYPE_EP,\r
+                  "--> DsIQM_REINIT: EP(%p) QP(%p) state change\n", \r
+                  ep_ptr, ep_ptr->qp_handle );\r
+\r
+    if ( ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECTED )\r
+    {\r
+       dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsIRE: EP invalid state(%d)\n",\r
+                      ep_ptr->param.ep_state);\r
+       return /*DAT_INVALID_STATE*/;\r
+    }\r
+\r
+    ia_ptr = ep_ptr->header.owner_ia;\r
+\r
+    /* Re-create QP if cleaned up, alloc will return init state */\r
+    if ( ep_ptr->qp_handle == IB_INVALID_HANDLE )\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_EP,\r
+                      "--> DsIRE: !EP(%p)->qp_handle, re-create QP\n",ep_ptr);\r
+        ib_status = dapls_ib_qp_alloc ( ia_ptr, ep_ptr, ep_ptr );\r
+        if ( ib_status != IB_SUCCESS )\r
+        {\r
+            dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> DsIRE: failed to move qp to RESET status = %s\n", \r
+                      ib_get_err_str(ib_status));\r
+        }\r
+        return /*ib_status*/;\r
+    }\r
+\r
+    ib_status = dapls_modify_qp_state_to_reset (ep_ptr->qp_handle);\r
+\r
+    if ( ib_status != IB_SUCCESS )\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> DsIRE: failed to move qp to RESET status = %s\n", \r
+                      ib_get_err_str(ib_status));\r
+        return /*DAT_INTERNAL_ERROR*/;\r
+    }\r
+\r
+    ep_ptr->qp_state = IB_QPS_RESET;\r
+\r
+    p_ca   = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
+    p_active_port = dapli_ibal_get_port ( p_ca,\r
+                                          (uint8_t)ia_ptr->hca_ptr->port_num );\r
+    if (NULL == p_active_port)\r
+    {\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                     "--> DsIRE: Port %d is not available = %d\n",\r
+                     ia_ptr->hca_ptr->port_num, __LINE__);\r
+        return /*DAT_INTERNAL_ERROR*/;\r
+    }\r
+\r
+       /* May fail if QP still RESET and in timewait, keep in reset state */\r
+    ib_status = dapls_modify_qp_state_to_init ( ep_ptr->qp_handle,\r
+                                                &ep_ptr->param.ep_attr,\r
+                                                p_active_port);\r
+    if ( ib_status != IB_SUCCESS )\r
+    {\r
+        ep_ptr->qp_state = IB_QPS_RESET;\r
+\r
+        dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+                      "--> DsIRE: failed to move qp to INIT status %s\n", \r
+                      ib_get_err_str(ib_status));\r
+        return /*DAT_INTERNAL_ERROR*/;\r
+    }\r
+    ep_ptr->qp_state = IB_QPS_INIT;\r
+}\r
+\r
+\r
+/*\r
+ * Local variables:\r
+ *  c-indent-level: 4\r
+ *  c-basic-offset: 4\r
+ *  tab-width: 8\r
+ * End:\r
+ */\r
+\r
index a73d6c15ebc5a4ad3d3e26709673642bfe91a4b2..d5d6b4c4478f31ad8821b164e6f1ebb67de408b0 100644 (file)
-
-/*
- * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.
- * Copyright (c) 2002, Network Appliance, Inc. All rights reserved. 
- * 
- * This Software is licensed under the terms of the "Common Public
- * License" a copy of which is in the file LICENSE.txt in the root
- * directory. The license is also available from the Open Source
- * Initiative, see http://www.opensource.org/licenses/cpl.php.
- *
- */
-
-/**********************************************************************
- * 
- * MODULE: dapl_ibal_util.h
- *
- * PURPOSE: Utility defs & routines for access to openib-windows IBAL APIs
- *
- * $Id: dapl_ibal_util.h 33 2005-07-11 19:51:17Z ftillier $
- *
- **********************************************************************/
-
-#ifndef _DAPL_IBAL_UTIL_H_
-#define _DAPL_IBAL_UTIL_H_
-
-#include <iba/ib_al.h>
-#include <complib/cl_spinlock.h>
-#include <complib/cl_qlist.h>
-#include <complib/cl_atomic.h>
-
-#ifdef DAT_EXTENSIONS
-#include <dat2\dat_ib_extensions.h>
-#endif
-
-/*
- * Typedefs to map IBAL types to more generic 'ib' types
- */
-#ifdef SOCK_CM
-typedef  struct ib_cm_handle           *dp_ib_cm_handle_t;
-typedef  struct ib_cm_handle           *ib_cm_srvc_handle_t;
-#else
-typedef  ib_cm_handle_t                *dp_ib_cm_handle_t;
-typedef  ib_listen_handle_t            ib_cm_srvc_handle_t;
-#endif
-
-typedef  ib_net64_t                    IB_HCA_NAME;
-typedef  ib_ca_handle_t                ib_hca_handle_t;
-typedef  DAT_PVOID                     ib_cqd_handle_t;
-typedef  ib_async_event_rec_t          ib_error_record_t;
-typedef  ib_wr_type_t                  ib_send_op_type_t;
-typedef  ib_wc_t                       ib_work_completion_t;
-typedef  uint32_t                      ib_hca_port_t;
-typedef  uint32_t                      ib_uint32_t;
-typedef  ib_local_ds_t                 ib_data_segment_t;
-
-typedef  unsigned __int3264            cl_dev_handle_t;
-
-
-typedef void (*ib_async_handler_t)(
-    IN    ib_hca_handle_t    ib_hca_handle,
-    IN    ib_error_record_t  *err_code,
-    IN    void               *context);
-
-typedef void (*ib_async_qp_handler_t)(
-    IN    ib_hca_handle_t    ib_hca_handle,
-    IN    ib_qp_handle_t     ib_qp_handle,
-    IN    ib_error_record_t  *err_code,
-    IN    void               *context);
-
-typedef void (*ib_async_cq_handler_t)(
-    IN    ib_hca_handle_t    ib_hca_handle,
-    IN    ib_cq_handle_t     ib_cq_handle,
-    IN    ib_error_record_t  *err_code,
-    IN    void               *context);
-
-typedef ib_net64_t   ib_guid_t;
-typedef ib_net16_t   ib_lid_t;
-typedef boolean_t    ib_bool_t;
-
-typedef struct _GID
-{
-    uint64_t gid_prefix;
-    uint64_t guid;
-} GID;
-
-typedef enum 
-{
-    IB_CME_CONNECTED,
-    IB_CME_DISCONNECTED,
-    IB_CME_DISCONNECTED_ON_LINK_DOWN,
-    IB_CME_CONNECTION_REQUEST_PENDING,
-    IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,
-    IB_CME_DESTINATION_REJECT,
-    IB_CME_DESTINATION_REJECT_PRIVATE_DATA,
-    IB_CME_DESTINATION_UNREACHABLE,
-    IB_CME_TOO_MANY_CONNECTION_REQUESTS,
-    IB_CME_LOCAL_FAILURE,
-    IB_CME_REPLY_RECEIVED,
-    IB_CME_REPLY_RECEIVED_PRIVATE_DATA,
-    IB_CM_LOCAL_FAILURE
-} ib_cm_events_t;
-
-
-typedef enum
-{
-    IB_NOTIFY_ON_NEXT_COMP,
-    IB_NOTIFY_ON_SOLIC_COMP
-} ib_notification_type_t;
-
-typedef struct _ib_hca_name
-{
-    DAT_NAME_PTR hca_name[DAT_NAME_MAX_LENGTH];
-} ib_hca_name_t;
-
-
-#define          IB_INVALID_HANDLE             NULL
-#define          true                          TRUE
-#define          false                         FALSE
-
-#define          IB_MAX_REQ_PDATA_SIZE      92
-#define          IB_MAX_REP_PDATA_SIZE      196
-#define          IB_MAX_REJ_PDATA_SIZE      148
-#define          IB_MAX_DREQ_PDATA_SIZE     220
-#define          IB_MAX_DREP_PDATA_SIZE     224
-
-
-/* Resource Not Ready
-       1-6 is an actual retry count which is decremented to zero before
-        an error condition is set.
-    7 is 'magic' in that it implies Infinite retry, just keeps trying.
-*/
-#define                IB_RNR_RETRY_CNT   7
-
-/*
-IB 1.2 spec, page 331, table 45, RNR NAK timeout encoding (5-bits)
-00000=655.36ms(milliseconds)
-00001=0.01ms
-00010=0.02ms
-00011=0.03ms
-00100=0.04ms
-00101=0.06ms
-00110=0.08ms
-00111=0.12ms
-
-11100=163.84ms 28d
-11101=245.76ms 29d
-11110=327.68ms 30d
-11111=491.52ms 31d
-*/
-#define                IB_RNR_NAK_TIMEOUT   0
-
-
-typedef void
-(*dapl_ibal_pfn_destructor_t)(
-    IN    void*    context );
-
-typedef struct _dapl_ibal_refs
-{
-    atomic32_t                      count;        // number of references
-    void*                         context;     // context for destructor
-    dapl_ibal_pfn_destructor_t    destructor;   // called when reference goes to zero
-
-} dapl_ibal_refs_t;
-
-
-typedef struct _dapl_ibal_root
-{
-    ib_al_handle_t        h_al;        // handle to Access Layer
-    cl_spinlock_t         ca_lock;     // CA list lock
-    cl_qlist_t            ca_head;     // list head of CAs
-    boolean_t             shutdown;    // when true, driver is shutting down
-    boolean_t             initialized;    // when true, lib is initialized 
-
-} dapl_ibal_root_t;
-
-
-typedef struct _dapl_ibal_ca
-{
-    cl_list_item_t    next;        // peer CA list
-    ib_ca_handle_t    h_ca;        // handle to open CA
-    ib_ca_attr_t      *p_ca_attr;  // CA attributes
-    uint32_t          ca_attr_size;// size of ca attribute
-    dapl_ibal_refs_t  refs;        // reference counting
-    cl_spinlock_t     port_lock;   // port list lock
-    cl_qlist_t        port_head;   // port list head for this CA
-    cl_spinlock_t     evd_cb_lock; // EVD async error cb list lock
-    cl_qlist_t        evd_cb_head; // EVD async error cb list head for this CA
-    cl_dev_handle_t   mlnx_device;
-    DAT_PVOID         *ia_ptr;     // hook for CA async callbacks
-} dapl_ibal_ca_t;
-
-
-typedef struct _dapl_ibal_port
-{
-    cl_list_item_t    next;            // peer CA list
-    dapl_ibal_ca_t    *ca;             // pointer to parent CA
-    ib_port_attr_t    *p_attr;         // port attributes
-    dapl_ibal_refs_t  refs;            // reference counting
-} dapl_ibal_port_t;
-
-typedef struct _dapl_ibal_evd_cb
-{
-    cl_list_item_t     next;        // peer CA list
-    ib_async_handler_t pfn_async_err_cb;
-    ib_async_qp_handler_t  pfn_async_qp_err_cb;
-    ib_async_cq_handler_t  pfn_async_cq_err_cb;
-    void               *context;
-} dapl_ibal_evd_cb_t;
-
-/*
- * Definitions to map DTO OPs to IBAL Work-Request ops.
- */
-#define    OP_BAD_OPCODE      0
-#define    OP_RDMA_READ       WR_RDMA_READ
-#define    OP_RDMA_WRITE      WR_RDMA_WRITE
-#define    OP_SEND            WR_SEND
-#define    OP_COMP_AND_SWAP   WR_COMPARE_SWAP
-#define    OP_FETCH_AND_ADD   WR_FETCH_ADD
-
-#define    OP_RECEIVE         8                /* (8)  */
-#define    OP_BIND_MW         9                /* no-equivalent */
-#define    OP_RDMA_WRITE_IMM  10       /* RDMA_WRITE+Immediate data */
-#define    OP_RECEIVE_IMM     11       /* no-equivalent */
-
-/*
- * Definitions to map QP state
- */
-#define IB_QP_STATE_RESET    IB_QPS_RESET
-#define IB_QP_STATE_INIT     IB_QPS_INIT
-#define IB_QP_STATE_RTR      IB_QPS_RTR
-#define IB_QP_STATE_RTS      IB_QPS_RTS
-#define IB_QP_STATE_SQE      IB_QPS_SQERR
-#define IB_QP_STATE_SQD      IB_QPS_SQD
-#define IB_QP_STATE_ERROR    IB_QPS_ERROR
-
-/*
- * Definitions to map Memory OPs
- */
-#define IB_ACCESS_LOCAL_WRITE      IB_AC_LOCAL_WRITE
-#define IB_ACCESS_REMOTE_READ      IB_AC_RDMA_READ
-#define IB_ACCESS_REMOTE_WRITE     IB_AC_RDMA_WRITE
-#define IB_ACCESS_REMOTE_ATOMIC    IB_AC_ATOMIC
-#define IB_ACCESS_MEM_WINDOW_BIND  IB_AC_MW_BIND
-
-/*
- * CQE status 
- */
-enum _dapl_comp_status
-{
-       IB_COMP_ST_SUCCESS              = IB_WCS_SUCCESS,
-       IB_COMP_ST_LOCAL_LEN_ERR        = IB_WCS_LOCAL_LEN_ERR,
-       IB_COMP_ST_LOCAL_OP_ERR         = IB_WCS_LOCAL_OP_ERR,
-       IB_COMP_ST_LOCAL_PROTECT_ERR    = IB_WCS_LOCAL_PROTECTION_ERR,
-       IB_COMP_ST_WR_FLUSHED_ERR       = IB_WCS_WR_FLUSHED_ERR,
-       IB_COMP_ST_MW_BIND_ERR          = IB_WCS_MEM_WINDOW_BIND_ERR,
-       IB_COMP_ST_REM_ACC_ERR          = IB_WCS_REM_ACCESS_ERR,
-       IB_COMP_ST_REM_OP_ERR           = IB_WCS_REM_OP_ERR,
-       IB_COMP_ST_RNR_COUNTER          = IB_WCS_RNR_RETRY_ERR,
-       IB_COMP_ST_TRANSP_COUNTER       = IB_WCS_TIMEOUT_RETRY_ERR,
-       IB_COMP_ST_REM_REQ_ERR          = IB_WCS_REM_INVALID_REQ_ERR,
-       IB_COMP_ST_BAD_RESPONSE_ERR     = IB_WCS_UNMATCHED_RESPONSE,
-       IB_COMP_ST_EE_STATE_ERR,
-       IB_COMP_ST_EE_CTX_NO_ERR
-};
-
-
-/*
- * Macro to check the state of an EP/QP
- */
-#define DAPLIB_NEEDS_INIT(ep)  ((ep)->qp_state == IB_QPS_ERROR)
-
-
-/*
- * Resolve IBAL return codes to their DAPL equivelent.
- * Do not return invalid Handles, the user is not able
- * to deal with them.
- */
-STATIC _INLINE_ DAT_RETURN 
-dapl_ib_status_convert (
-    IN     int32_t     ib_status)
-{
-    switch ( ib_status )
-    {
-    case IB_SUCCESS:
-    {
-        return DAT_SUCCESS;
-    }
-    case IB_INSUFFICIENT_RESOURCES:
-    case IB_INSUFFICIENT_MEMORY:
-    case IB_RESOURCE_BUSY:
-    {
-        return DAT_INSUFFICIENT_RESOURCES;
-    }
-    case IB_INVALID_CA_HANDLE:
-    case IB_INVALID_CQ_HANDLE:
-    case IB_INVALID_QP_HANDLE:
-    case IB_INVALID_PD_HANDLE:
-    case IB_INVALID_MR_HANDLE:
-    case IB_INVALID_MW_HANDLE:
-    case IB_INVALID_AL_HANDLE:
-    case IB_INVALID_AV_HANDLE:
-    {
-        return DAT_INVALID_HANDLE;
-    }
-    case IB_INVALID_PKEY:
-    {
-        return DAT_PROTECTION_VIOLATION;
-    }
-    case IB_INVALID_LKEY:
-    case IB_INVALID_RKEY:
-    case IB_INVALID_PERMISSION:
-    {
-        return DAT_PRIVILEGES_VIOLATION;
-    }
-    case IB_INVALID_MAX_WRS:
-    case IB_INVALID_MAX_SGE:
-    case IB_INVALID_CQ_SIZE:
-    case IB_INVALID_SETTING:
-    case IB_INVALID_SERVICE_TYPE:
-    case IB_INVALID_GID:
-    case IB_INVALID_LID:
-    case IB_INVALID_GUID:
-    case IB_INVALID_PARAMETER:
-    {
-        return DAT_INVALID_PARAMETER;
-    }
-    case IB_INVALID_QP_STATE:
-    case IB_INVALID_APM_STATE:
-    case IB_INVALID_PORT_STATE:
-    case IB_INVALID_STATE:
-    {
-        return DAT_INVALID_STATE;
-    }
-    case IB_NOT_FOUND:
-    {
-        return DAT_QUEUE_EMPTY;
-    }
-    case IB_OVERFLOW:
-    {
-        return DAT_QUEUE_FULL;
-    }
-    case IB_UNSUPPORTED:
-    {
-        return DAT_NOT_IMPLEMENTED;
-    }
-    case IB_TIMEOUT:
-    {
-        return DAT_TIMEOUT_EXPIRED;
-    }
-    case IB_CANCELED:
-    {
-        return DAT_ABORT;
-    }
-    default:
-    {
-        return DAT_INTERNAL_ERROR;
-    }
-    }
-}
-   
-#define TAKE_LOCK( lock ) \
-        cl_spinlock_acquire( &(lock) )
-
-#define RELEASE_LOCK( lock ) \
-        cl_spinlock_release( &(lock) )
-
-#define LOCK_INSERT_HEAD( lock, head, item ) \
-{ \
-        TAKE_LOCK( lock ); \
-        cl_qlist_insert_head( &head, (cl_list_item_t*)(&item) ); \
-        RELEASE_LOCK( lock ); \
-}
-
-#define LOCK_INSERT_TAIL( lock, tail, item ) \
-{ \
-        TAKE_LOCK( lock ); \
-        cl_qlist_insert_tail( &tail, (cl_list_item_t*)(&item) ); \
-        RELEASE_LOCK( lock ); \
-}
-
-#define INIT_REFERENCE( p_ref, n, con, destruct ) \
-{ \
-        (p_ref)->count = n; \
-        (p_ref)->context = con; \
-        (p_ref)->destructor = destruct; \
-}
-
-#define TAKE_REFERENCE( p_ref ) \
-        cl_atomic_inc( &(p_ref)->count )
-
-#define REMOVE_REFERENCE( p_ref ) \
-{ \
-        if ( cl_atomic_dec( &(p_ref)->count ) == 0 ) \
-            if ( (p_ref)->destructor ) \
-                (p_ref)->destructor( (p_ref)->context ); \
-}
-
-/* 
- * dapl_llist_entry in dapl.h but dapl.h depends on provider 
- * typedef's in this file first. move dapl_llist_entry out of dapl.h
- */
-struct ib_llist_entry
-{
-    struct dapl_llist_entry    *flink;
-    struct dapl_llist_entry    *blink;
-    void                       *data;
-    struct dapl_llist_entry    *list_head;
-};
-
-#ifdef SOCK_CM
-
-typedef enum
-{
-       IB_THREAD_INIT,
-       IB_THREAD_RUN,
-       IB_THREAD_CANCEL,
-       IB_THREAD_EXIT
-
-} ib_thread_state_t;
-
-typedef enum scm_state 
-{
-       SCM_INIT,
-       SCM_LISTEN,
-       SCM_CONN_PENDING,
-       SCM_ACCEPTING,
-       SCM_ACCEPTED,
-       SCM_REJECTED,
-       SCM_CONNECTED,
-       SCM_DISCONNECTED,
-       SCM_DESTROY
-
-} SCM_STATE;
-
-#endif /* SOCK_CM */
-
-typedef struct _ib_hca_transport
-{ 
-#ifdef SOCK_CM
-    int                                max_inline_send;
-    ib_thread_state_t          cr_state;       /* CR thread */
-    DAPL_OS_THREAD             thread;         /* CR thread */
-    DAPL_OS_LOCK               lock;           /* CR serialization */
-    struct ib_llist_entry      *list;          /* Connection Requests */
-#endif
-    struct dapl_hca            *d_hca;
-    DAPL_OS_WAIT_OBJECT                wait_object;
-    DAPL_ATOMIC                        handle_ref_count; /* # of ia_opens on handle */
-    ib_cqd_handle_t            ib_cqd_handle;    /* cq domain handle */
-
-    /* Name service support */
-    void                       *name_service_handle;
-
-} ib_hca_transport_t;
-
-/* provider specfic fields for shared memory support */
-typedef uint32_t ib_shm_transport_t;
-
-#ifdef SOCK_CM
-
-/* inline send rdma threshold */
-#define        INLINE_SEND_DEFAULT     128
-
-/* CM mappings use SOCKETS */
-
-/* destination info exchanged between dapl, define wire protocol version */
-#define DSCM_VER 2
-
-typedef struct _ib_qp_cm
-{ 
-       ib_net16_t      ver;
-       ib_net16_t      rej;
-       ib_net16_t              lid;
-       ib_net16_t              port;
-       ib_net32_t      qpn;
-       ib_net32_t              p_size;
-       DAT_SOCK_ADDR6          ia_address;
-       GID             gid;
-
-} ib_qp_cm_t;
-
-struct ib_cm_handle
-{ 
-       struct ib_llist_entry   entry;
-       DAPL_OS_LOCK            lock;
-       SCM_STATE               state;
-       int                     socket;
-       int                     l_socket; 
-       struct dapl_hca         *hca;
-       DAT_HANDLE              sp;     
-       DAT_HANDLE              cr;
-       struct dapl_ep          *ep;
-       ib_qp_cm_t              dst;
-       unsigned char           p_data[256];
-};
-
-DAT_RETURN dapli_init_sock_cm ( IN DAPL_HCA  *hca_ptr );
-
-#endif /* SOCK_CM */
-
-/*
- * Prototype
- */
-
-extern ib_api_status_t 
-dapls_modify_qp_state_to_error (
-        ib_qp_handle_t                qp_handle );
-
-extern ib_api_status_t 
-dapls_modify_qp_state_to_reset (
-    ib_qp_handle_t);
-
-extern ib_api_status_t 
-dapls_modify_qp_state_to_init ( 
-    ib_qp_handle_t, DAT_EP_ATTR *, dapl_ibal_port_t *);
-
-extern ib_api_status_t 
-dapls_modify_qp_state_to_rtr (
-    ib_qp_handle_t, ib_net32_t, ib_lid_t, dapl_ibal_port_t *);
-
-extern ib_api_status_t 
-dapls_modify_qp_state_to_rts (
-    ib_qp_handle_t);
-
-extern void
-dapli_ibal_ca_async_error_callback(
-    IN    ib_async_event_rec_t* p_err_rec );
-
-extern dapl_ibal_port_t *
-dapli_ibal_get_port (
-    IN   dapl_ibal_ca_t    *p_ca,
-    IN   uint8_t           port_num);
-
-extern int32_t dapls_ib_init (void);
-extern int32_t dapls_ib_release (void);
-
-extern dapl_ibal_evd_cb_t *
-dapli_find_evd_cb_by_context(
-    IN    void           *context,
-    IN    dapl_ibal_ca_t *ca);
-
-extern IB_HCA_NAME
-dapl_ib_convert_name(IN  char    *name);
-
-
-STATIC _INLINE_ int32_t
-dapli_ibal_convert_privileges (IN  DAT_MEM_PRIV_FLAGS  privileges )
-{
-    int32_t value = DAT_MEM_PRIV_NONE_FLAG;
-
-    /*
-     *    if (DAT_MEM_PRIV_LOCAL_READ_FLAG & privileges)
-     *       do nothing
-     */
-    if (DAT_MEM_PRIV_LOCAL_WRITE_FLAG & privileges)
-       value |= IB_ACCESS_LOCAL_WRITE;
-
-    if (DAT_MEM_PRIV_REMOTE_WRITE_FLAG & privileges)
-       value |= IB_ACCESS_REMOTE_WRITE;
-
-    if (DAT_MEM_PRIV_REMOTE_READ_FLAG & privileges)
-       value |= IB_ACCESS_REMOTE_READ;
-
-#ifdef DAT_EXTENSIONS
-    if (DAT_IB_MEM_PRIV_REMOTE_ATOMIC & privileges) 
-        value |= IB_ACCESS_REMOTE_ATOMIC;
-#endif
-
-#ifdef DAPL_DBG
-    if (value == DAT_MEM_PRIV_NONE_FLAG)
-    {
-       dapl_dbg_log(DAPL_DBG_TYPE_ERR,"%s() Unknown DAT_MEM_PRIV_ 0x%x\n",
-                     __FUNCTION__,privileges);
-    }
-#endif
-    return value;
-}
-
-#define dapl_rmr_convert_privileges(p) dapli_ibal_convert_privileges(p)
-#define dapl_lmr_convert_privileges(p) dapli_ibal_convert_privileges(p)
-
-#endif /*  _DAPL_IBAL_UTIL_H_ */
+\r
+/*\r
+ * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.\r
+ * Copyright (c) 2002, Network Appliance, Inc. All rights reserved. \r
+ * \r
+ * This Software is licensed under the terms of the "Common Public\r
+ * License" a copy of which is in the file LICENSE.txt in the root\r
+ * directory. The license is also available from the Open Source\r
+ * Initiative, see http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_ibal_util.h\r
+ *\r
+ * PURPOSE: Utility defs & routines for access to openib-windows IBAL APIs\r
+ *\r
+ * $Id: dapl_ibal_util.h 33 2005-07-11 19:51:17Z ftillier $\r
+ *\r
+ **********************************************************************/\r
+\r
+#ifndef _DAPL_IBAL_UTIL_H_\r
+#define _DAPL_IBAL_UTIL_H_\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_atomic.h>\r
+\r
+#ifdef DAT_EXTENSIONS\r
+#include <dat2\dat_ib_extensions.h>\r
+#endif\r
+\r
+/*\r
+ * Typedefs to map IBAL types to more generic 'ib' types\r
+ */\r
+#ifdef SOCK_CM\r
+typedef  struct ib_cm_handle           *dp_ib_cm_handle_t;\r
+typedef  struct ib_cm_handle           *ib_cm_srvc_handle_t;\r
+#else\r
+\r
+/* EP-CM linking requires list_entry, protected ref counting */\r
+typedef struct dapl_ibal_cm\r
+{ \r
+       struct dapl_llist_entry list_entry;\r
+       DAPL_OS_LOCK            lock;\r
+       int                     ref_count;\r
+       DAT_SOCK_ADDR6          dst_ip_addr; \r
+       ib_cm_handle_t          ib_cm;  /* h_al, h_qp, cid */\r
+       DAPL_EP                 *ep;\r
+\r
+} dapl_ibal_cm_t;\r
+\r
+typedef  dapl_ibal_cm_t                *dp_ib_cm_handle_t;\r
+typedef  ib_listen_handle_t            ib_cm_srvc_handle_t;\r
+\r
+/* EP-CM linking prototypes */\r
+extern void dapls_cm_acquire(dp_ib_cm_handle_t cm_ptr);\r
+extern void dapls_cm_release(dp_ib_cm_handle_t cm_ptr);\r
+extern void dapls_cm_free(dp_ib_cm_handle_t cm_ptr);\r
+extern dp_ib_cm_handle_t ibal_cm_alloc(void);\r
+\r
+#endif\r
+\r
+typedef  ib_net64_t                    IB_HCA_NAME;\r
+typedef  ib_ca_handle_t                ib_hca_handle_t;\r
+typedef  DAT_PVOID                     ib_cqd_handle_t;\r
+typedef  ib_async_event_rec_t          ib_error_record_t;\r
+typedef  ib_wr_type_t                  ib_send_op_type_t;\r
+typedef  ib_wc_t                       ib_work_completion_t;\r
+typedef  uint32_t                      ib_hca_port_t;\r
+typedef  uint32_t                      ib_uint32_t;\r
+typedef  ib_local_ds_t                 ib_data_segment_t;\r
+\r
+typedef  unsigned __int3264            cl_dev_handle_t;\r
+\r
+\r
+typedef void (*ib_async_handler_t)(\r
+    IN    ib_hca_handle_t    ib_hca_handle,\r
+    IN    ib_error_record_t  *err_code,\r
+    IN    void               *context);\r
+\r
+typedef void (*ib_async_qp_handler_t)(\r
+    IN    ib_hca_handle_t    ib_hca_handle,\r
+    IN    ib_qp_handle_t     ib_qp_handle,\r
+    IN    ib_error_record_t  *err_code,\r
+    IN    void               *context);\r
+\r
+typedef void (*ib_async_cq_handler_t)(\r
+    IN    ib_hca_handle_t    ib_hca_handle,\r
+    IN    ib_cq_handle_t     ib_cq_handle,\r
+    IN    ib_error_record_t  *err_code,\r
+    IN    void               *context);\r
+\r
+typedef ib_net64_t   ib_guid_t;\r
+typedef ib_net16_t   ib_lid_t;\r
+typedef boolean_t    ib_bool_t;\r
+\r
+typedef struct _GID\r
+{\r
+    uint64_t gid_prefix;\r
+    uint64_t guid;\r
+} GID;\r
+\r
+typedef enum \r
+{\r
+    IB_CME_CONNECTED,\r
+    IB_CME_DISCONNECTED,\r
+    IB_CME_DISCONNECTED_ON_LINK_DOWN,\r
+    IB_CME_CONNECTION_REQUEST_PENDING,\r
+    IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,\r
+    IB_CME_DESTINATION_REJECT,\r
+    IB_CME_DESTINATION_REJECT_PRIVATE_DATA,\r
+    IB_CME_DESTINATION_UNREACHABLE,\r
+    IB_CME_TOO_MANY_CONNECTION_REQUESTS,\r
+    IB_CME_LOCAL_FAILURE,\r
+    IB_CME_REPLY_RECEIVED,\r
+    IB_CME_REPLY_RECEIVED_PRIVATE_DATA,\r
+    IB_CM_LOCAL_FAILURE\r
+} ib_cm_events_t;\r
+\r
+\r
+typedef enum\r
+{\r
+    IB_NOTIFY_ON_NEXT_COMP,\r
+    IB_NOTIFY_ON_SOLIC_COMP\r
+} ib_notification_type_t;\r
+\r
+typedef struct _ib_hca_name\r
+{\r
+    DAT_NAME_PTR hca_name[DAT_NAME_MAX_LENGTH];\r
+} ib_hca_name_t;\r
+\r
+\r
+#define          IB_INVALID_HANDLE             NULL\r
+#define          true                          TRUE\r
+#define          false                         FALSE\r
+\r
+#define          IB_MAX_REQ_PDATA_SIZE      92\r
+#define          IB_MAX_REP_PDATA_SIZE      196\r
+#define          IB_MAX_REJ_PDATA_SIZE      148\r
+#define          IB_MAX_DREQ_PDATA_SIZE     220\r
+#define          IB_MAX_DREP_PDATA_SIZE     224\r
+\r
+\r
+/* Resource Not Ready\r
+       1-6 is an actual retry count which is decremented to zero before\r
+        an error condition is set.\r
+    7 is 'magic' in that it implies Infinite retry, just keeps trying.\r
+*/\r
+#define                IB_RNR_RETRY_CNT   7\r
+\r
+/*\r
+IB 1.2 spec, page 331, table 45, RNR NAK timeout encoding (5-bits)\r
\r
+00000=655.36ms(milliseconds)\r
+00001=0.01ms\r
+00010=0.02ms\r
+00011=0.03ms\r
+00100=0.04ms\r
+00101=0.06ms\r
+00110=0.08ms\r
+00111=0.12ms\r
+\r
+11100=163.84ms 28d\r
+11101=245.76ms 29d\r
+11110=327.68ms 30d\r
+11111=491.52ms 31d\r
+*/\r
+#define                IB_RNR_NAK_TIMEOUT   0\r
+\r
+\r
+typedef void\r
+(*dapl_ibal_pfn_destructor_t)(\r
+    IN    void*    context );\r
+\r
+typedef struct _dapl_ibal_refs\r
+{\r
+    atomic32_t                      count;        // number of references\r
+    void*                         context;     // context for destructor\r
+    dapl_ibal_pfn_destructor_t    destructor;   // called when reference goes to zero\r
+\r
+} dapl_ibal_refs_t;\r
+\r
+\r
+typedef struct _dapl_ibal_root\r
+{\r
+    ib_al_handle_t        h_al;        // handle to Access Layer\r
+    cl_spinlock_t         ca_lock;     // CA list lock\r
+    cl_qlist_t            ca_head;     // list head of CAs\r
+    boolean_t             shutdown;    // when true, driver is shutting down\r
+    boolean_t             initialized;    // when true, lib is initialized \r
+\r
+} dapl_ibal_root_t;\r
+\r
+\r
+typedef struct _dapl_ibal_ca\r
+{\r
+    cl_list_item_t    next;        // peer CA list\r
+    ib_ca_handle_t    h_ca;        // handle to open CA\r
+    ib_ca_attr_t      *p_ca_attr;  // CA attributes\r
+    uint32_t          ca_attr_size;// size of ca attribute\r
+    dapl_ibal_refs_t  refs;        // reference counting\r
+    cl_spinlock_t     port_lock;   // port list lock\r
+    cl_qlist_t        port_head;   // port list head for this CA\r
+    cl_spinlock_t     evd_cb_lock; // EVD async error cb list lock\r
+    cl_qlist_t        evd_cb_head; // EVD async error cb list head for this CA\r
+    cl_dev_handle_t   mlnx_device;\r
+    DAT_PVOID         *ia_ptr;     // hook for CA async callbacks\r
+} dapl_ibal_ca_t;\r
+\r
+\r
+typedef struct _dapl_ibal_port\r
+{\r
+    cl_list_item_t    next;            // peer CA list\r
+    dapl_ibal_ca_t    *ca;             // pointer to parent CA\r
+    ib_port_attr_t    *p_attr;         // port attributes\r
+    dapl_ibal_refs_t  refs;            // reference counting\r
+} dapl_ibal_port_t;\r
+\r
+typedef struct _dapl_ibal_evd_cb\r
+{\r
+    cl_list_item_t     next;        // peer CA list\r
+    ib_async_handler_t pfn_async_err_cb;\r
+    ib_async_qp_handler_t  pfn_async_qp_err_cb;\r
+    ib_async_cq_handler_t  pfn_async_cq_err_cb;\r
+    void               *context;\r
+} dapl_ibal_evd_cb_t;\r
+\r
+/*\r
+ * Definitions to map DTO OPs to IBAL Work-Request ops.\r
+ */\r
+#define    OP_BAD_OPCODE      0\r
+#define    OP_RDMA_READ       WR_RDMA_READ\r
+#define    OP_RDMA_WRITE      WR_RDMA_WRITE\r
+#define    OP_SEND            WR_SEND\r
+#define    OP_COMP_AND_SWAP   WR_COMPARE_SWAP\r
+#define    OP_FETCH_AND_ADD   WR_FETCH_ADD\r
+\r
+#define    OP_RECEIVE         8                /* (8)  */\r
+#define    OP_BIND_MW         9                /* no-equivalent */\r
+#define    OP_RDMA_WRITE_IMM  10       /* RDMA_WRITE+Immediate data */\r
+#define    OP_RECEIVE_IMM     11       /* no-equivalent */\r
+\r
+/*\r
+ * Definitions to map QP state\r
+ */\r
+#define IB_QP_STATE_RESET    IB_QPS_RESET\r
+#define IB_QP_STATE_INIT     IB_QPS_INIT\r
+#define IB_QP_STATE_RTR      IB_QPS_RTR\r
+#define IB_QP_STATE_RTS      IB_QPS_RTS\r
+#define IB_QP_STATE_SQE      IB_QPS_SQERR\r
+#define IB_QP_STATE_SQD      IB_QPS_SQD\r
+#define IB_QP_STATE_ERROR    IB_QPS_ERROR\r
+\r
+/*\r
+ * Definitions to map Memory OPs\r
+ */\r
+#define IB_ACCESS_LOCAL_WRITE      IB_AC_LOCAL_WRITE\r
+#define IB_ACCESS_REMOTE_READ      IB_AC_RDMA_READ\r
+#define IB_ACCESS_REMOTE_WRITE     IB_AC_RDMA_WRITE\r
+#define IB_ACCESS_REMOTE_ATOMIC    IB_AC_ATOMIC\r
+#define IB_ACCESS_MEM_WINDOW_BIND  IB_AC_MW_BIND\r
+\r
+/*\r
+ * CQE status \r
+ */\r
+enum _dapl_comp_status\r
+{\r
+       IB_COMP_ST_SUCCESS              = IB_WCS_SUCCESS,\r
+       IB_COMP_ST_LOCAL_LEN_ERR        = IB_WCS_LOCAL_LEN_ERR,\r
+       IB_COMP_ST_LOCAL_OP_ERR         = IB_WCS_LOCAL_OP_ERR,\r
+       IB_COMP_ST_LOCAL_PROTECT_ERR    = IB_WCS_LOCAL_PROTECTION_ERR,\r
+       IB_COMP_ST_WR_FLUSHED_ERR       = IB_WCS_WR_FLUSHED_ERR,\r
+       IB_COMP_ST_MW_BIND_ERR          = IB_WCS_MEM_WINDOW_BIND_ERR,\r
+       IB_COMP_ST_REM_ACC_ERR          = IB_WCS_REM_ACCESS_ERR,\r
+       IB_COMP_ST_REM_OP_ERR           = IB_WCS_REM_OP_ERR,\r
+       IB_COMP_ST_RNR_COUNTER          = IB_WCS_RNR_RETRY_ERR,\r
+       IB_COMP_ST_TRANSP_COUNTER       = IB_WCS_TIMEOUT_RETRY_ERR,\r
+       IB_COMP_ST_REM_REQ_ERR          = IB_WCS_REM_INVALID_REQ_ERR,\r
+       IB_COMP_ST_BAD_RESPONSE_ERR     = IB_WCS_UNMATCHED_RESPONSE,\r
+       IB_COMP_ST_EE_STATE_ERR,\r
+       IB_COMP_ST_EE_CTX_NO_ERR\r
+};\r
+\r
+\r
+/*\r
+ * Macro to check the state of an EP/QP\r
+ */\r
+#define DAPLIB_NEEDS_INIT(ep)  ((ep)->qp_state == IB_QPS_ERROR)\r
+\r
+\r
+/*\r
+ * Resolve IBAL return codes to their DAPL equivelent.\r
+ * Do not return invalid Handles, the user is not able\r
+ * to deal with them.\r
+ */\r
+STATIC _INLINE_ DAT_RETURN \r
+dapl_ib_status_convert (\r
+    IN     int32_t     ib_status)\r
+{\r
+    switch ( ib_status )\r
+    {\r
+    case IB_SUCCESS:\r
+    {\r
+        return DAT_SUCCESS;\r
+    }\r
+    case IB_INSUFFICIENT_RESOURCES:\r
+    case IB_INSUFFICIENT_MEMORY:\r
+    case IB_RESOURCE_BUSY:\r
+    {\r
+        return DAT_INSUFFICIENT_RESOURCES;\r
+    }\r
+    case IB_INVALID_CA_HANDLE:\r
+    case IB_INVALID_CQ_HANDLE:\r
+    case IB_INVALID_QP_HANDLE:\r
+    case IB_INVALID_PD_HANDLE:\r
+    case IB_INVALID_MR_HANDLE:\r
+    case IB_INVALID_MW_HANDLE:\r
+    case IB_INVALID_AL_HANDLE:\r
+    case IB_INVALID_AV_HANDLE:\r
+    {\r
+        return DAT_INVALID_HANDLE;\r
+    }\r
+    case IB_INVALID_PKEY:\r
+    {\r
+        return DAT_PROTECTION_VIOLATION;\r
+    }\r
+    case IB_INVALID_LKEY:\r
+    case IB_INVALID_RKEY:\r
+    case IB_INVALID_PERMISSION:\r
+    {\r
+        return DAT_PRIVILEGES_VIOLATION;\r
+    }\r
+    case IB_INVALID_MAX_WRS:\r
+    case IB_INVALID_MAX_SGE:\r
+    case IB_INVALID_CQ_SIZE:\r
+    case IB_INVALID_SETTING:\r
+    case IB_INVALID_SERVICE_TYPE:\r
+    case IB_INVALID_GID:\r
+    case IB_INVALID_LID:\r
+    case IB_INVALID_GUID:\r
+    case IB_INVALID_PARAMETER:\r
+    {\r
+        return DAT_INVALID_PARAMETER;\r
+    }\r
+    case IB_INVALID_QP_STATE:\r
+    case IB_INVALID_APM_STATE:\r
+    case IB_INVALID_PORT_STATE:\r
+    case IB_INVALID_STATE:\r
+    {\r
+        return DAT_INVALID_STATE;\r
+    }\r
+    case IB_NOT_FOUND:\r
+    {\r
+        return DAT_QUEUE_EMPTY;\r
+    }\r
+    case IB_OVERFLOW:\r
+    {\r
+        return DAT_QUEUE_FULL;\r
+    }\r
+    case IB_UNSUPPORTED:\r
+    {\r
+        return DAT_NOT_IMPLEMENTED;\r
+    }\r
+    case IB_TIMEOUT:\r
+    {\r
+        return DAT_TIMEOUT_EXPIRED;\r
+    }\r
+    case IB_CANCELED:\r
+    {\r
+        return DAT_ABORT;\r
+    }\r
+    default:\r
+    {\r
+        return DAT_INTERNAL_ERROR;\r
+    }\r
+    }\r
+}\r
+   \r
+#define TAKE_LOCK( lock ) \\r
+        cl_spinlock_acquire( &(lock) )\r
+\r
+#define RELEASE_LOCK( lock ) \\r
+        cl_spinlock_release( &(lock) )\r
+\r
+#define LOCK_INSERT_HEAD( lock, head, item ) \\r
+{ \\r
+        TAKE_LOCK( lock ); \\r
+        cl_qlist_insert_head( &head, (cl_list_item_t*)(&item) ); \\r
+        RELEASE_LOCK( lock ); \\r
+}\r
+\r
+#define LOCK_INSERT_TAIL( lock, tail, item ) \\r
+{ \\r
+        TAKE_LOCK( lock ); \\r
+        cl_qlist_insert_tail( &tail, (cl_list_item_t*)(&item) ); \\r
+        RELEASE_LOCK( lock ); \\r
+}\r
+\r
+#define INIT_REFERENCE( p_ref, n, con, destruct ) \\r
+{ \\r
+        (p_ref)->count = n; \\r
+        (p_ref)->context = con; \\r
+        (p_ref)->destructor = destruct; \\r
+}\r
+\r
+#define TAKE_REFERENCE( p_ref ) \\r
+        cl_atomic_inc( &(p_ref)->count )\r
+\r
+#define REMOVE_REFERENCE( p_ref ) \\r
+{ \\r
+        if ( cl_atomic_dec( &(p_ref)->count ) == 0 ) \\r
+            if ( (p_ref)->destructor ) \\r
+                (p_ref)->destructor( (p_ref)->context ); \\r
+}\r
+\r
+/* \r
+ * dapl_llist_entry in dapl.h but dapl.h depends on provider \r
+ * typedef's in this file first. move dapl_llist_entry out of dapl.h\r
+ */\r
+struct ib_llist_entry\r
+{\r
+    struct dapl_llist_entry    *flink;\r
+    struct dapl_llist_entry    *blink;\r
+    void                       *data;\r
+    struct dapl_llist_entry    *list_head;\r
+};\r
+\r
+#ifdef SOCK_CM\r
+\r
+typedef enum\r
+{\r
+       IB_THREAD_INIT,\r
+       IB_THREAD_RUN,\r
+       IB_THREAD_CANCEL,\r
+       IB_THREAD_EXIT\r
+\r
+} ib_thread_state_t;\r
+\r
+typedef enum scm_state \r
+{\r
+       SCM_INIT,\r
+       SCM_LISTEN,\r
+       SCM_CONN_PENDING,\r
+       SCM_ACCEPTING,\r
+       SCM_ACCEPTED,\r
+       SCM_REJECTED,\r
+       SCM_CONNECTED,\r
+       SCM_DISCONNECTED,\r
+       SCM_DESTROY\r
+\r
+} SCM_STATE;\r
+\r
+#endif /* SOCK_CM */\r
+\r
+typedef struct _ib_hca_transport\r
+{ \r
+#ifdef SOCK_CM\r
+    int                                max_inline_send;\r
+    ib_thread_state_t          cr_state;       /* CR thread */\r
+    DAPL_OS_THREAD             thread;         /* CR thread */\r
+    DAPL_OS_LOCK               lock;           /* CR serialization */\r
+    struct ib_llist_entry      *list;          /* Connection Requests */\r
+#endif\r
+    struct dapl_hca            *d_hca;\r
+    DAPL_OS_WAIT_OBJECT                wait_object;\r
+    DAPL_ATOMIC                        handle_ref_count; /* # of ia_opens on handle */\r
+    ib_cqd_handle_t            ib_cqd_handle;    /* cq domain handle */\r
+\r
+    /* Name service support */\r
+    void                       *name_service_handle;\r
+\r
+} ib_hca_transport_t;\r
+\r
+/* provider specfic fields for shared memory support */\r
+typedef uint32_t ib_shm_transport_t;\r
+\r
+#ifdef SOCK_CM\r
+\r
+/* inline send rdma threshold */\r
+#define        INLINE_SEND_DEFAULT     128\r
+\r
+/* CM mappings use SOCKETS */\r
+\r
+/* destination info exchanged between dapl, define wire protocol version */\r
+#define DSCM_VER 2\r
+\r
+typedef struct _ib_qp_cm\r
+{ \r
+       ib_net16_t      ver;\r
+       ib_net16_t      rej;\r
+       ib_net16_t              lid;\r
+       ib_net16_t              port;\r
+       ib_net32_t      qpn;\r
+       ib_net32_t              p_size;\r
+       DAT_SOCK_ADDR6          ia_address;\r
+       GID             gid;\r
+\r
+} ib_qp_cm_t;\r
+\r
+struct ib_cm_handle\r
+{ \r
+       struct ib_llist_entry   entry;\r
+       DAPL_OS_LOCK            lock;\r
+       SCM_STATE               state;\r
+       int                     socket;\r
+       int                     l_socket; \r
+       struct dapl_hca         *hca;\r
+       DAT_HANDLE              sp;     \r
+       DAT_HANDLE              cr;\r
+       struct dapl_ep          *ep;\r
+       ib_qp_cm_t              dst;\r
+       unsigned char           p_data[256];\r
+};\r
+\r
+DAT_RETURN dapli_init_sock_cm ( IN DAPL_HCA  *hca_ptr );\r
+\r
+#endif /* SOCK_CM */\r
+\r
+/*\r
+ * Prototype\r
+ */\r
+\r
+extern ib_api_status_t \r
+dapls_modify_qp_state_to_error (\r
+        ib_qp_handle_t                qp_handle );\r
+\r
+extern ib_api_status_t \r
+dapls_modify_qp_state_to_reset (\r
+    ib_qp_handle_t);\r
+\r
+extern ib_api_status_t \r
+dapls_modify_qp_state_to_init ( \r
+    ib_qp_handle_t, DAT_EP_ATTR *, dapl_ibal_port_t *);\r
+\r
+extern ib_api_status_t \r
+dapls_modify_qp_state_to_rtr (\r
+    ib_qp_handle_t, ib_net32_t, ib_lid_t, dapl_ibal_port_t *);\r
+\r
+extern ib_api_status_t \r
+dapls_modify_qp_state_to_rts (\r
+    ib_qp_handle_t);\r
+\r
+extern void\r
+dapli_ibal_ca_async_error_callback(\r
+    IN    ib_async_event_rec_t* p_err_rec );\r
+\r
+extern dapl_ibal_port_t *\r
+dapli_ibal_get_port (\r
+    IN   dapl_ibal_ca_t    *p_ca,\r
+    IN   uint8_t           port_num);\r
+\r
+extern int32_t dapls_ib_init (void);\r
+extern int32_t dapls_ib_release (void);\r
+\r
+extern dapl_ibal_evd_cb_t *\r
+dapli_find_evd_cb_by_context(\r
+    IN    void           *context,\r
+    IN    dapl_ibal_ca_t *ca);\r
+\r
+extern IB_HCA_NAME\r
+dapl_ib_convert_name(IN  char    *name);\r
+\r
+STATIC _INLINE_ int32_t\r
+dapli_ibal_convert_privileges (IN  DAT_MEM_PRIV_FLAGS  privileges )\r
+{\r
+    int32_t value = DAT_MEM_PRIV_NONE_FLAG;\r
+\r
+    /*\r
+     *    if (DAT_MEM_PRIV_LOCAL_READ_FLAG & privileges)\r
+     *       do nothing\r
+     */\r
+    if (DAT_MEM_PRIV_LOCAL_WRITE_FLAG & privileges)\r
+       value |= IB_ACCESS_LOCAL_WRITE;\r
+\r
+    if (DAT_MEM_PRIV_REMOTE_WRITE_FLAG & privileges)\r
+       value |= IB_ACCESS_REMOTE_WRITE;\r
+\r
+    if (DAT_MEM_PRIV_REMOTE_READ_FLAG & privileges)\r
+       value |= IB_ACCESS_REMOTE_READ;\r
+\r
+#ifdef DAT_EXTENSIONS\r
+    if (DAT_IB_MEM_PRIV_REMOTE_ATOMIC & privileges) \r
+        value |= IB_ACCESS_REMOTE_ATOMIC;\r
+#endif\r
+\r
+#ifdef DAPL_DBG\r
+    if (value == DAT_MEM_PRIV_NONE_FLAG)\r
+    {\r
+       dapl_dbg_log(DAPL_DBG_TYPE_ERR,"%s() Unknown DAT_MEM_PRIV_ 0x%x\n",\r
+                     __FUNCTION__,privileges);\r
+    }\r
+#endif\r
+    return value;\r
+}\r
+\r
+#define dapl_rmr_convert_privileges(p) dapli_ibal_convert_privileges(p)\r
+#define dapl_lmr_convert_privileges(p) dapli_ibal_convert_privileges(p)\r
+\r
+#endif /*  _DAPL_IBAL_UTIL_H_ */\r
index e5fc1ace17c696daf1894e2271634d131da1f8fd..464608472a98479338d0738f203663f9dbd70077 100644 (file)
@@ -1,48 +1,48 @@
-/*
- * Copyright (c) 2007 Intel Corporation.  All rights reserved.
- *
- * This software is available to you under the OpenIB.org BSD license
- * below:
- *
- *     Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *      - Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *
- *      - Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * $Id$
- */
-
-
-#include <oib_ver.h>
-
-#define VER_FILETYPE                   VFT_DLL
-#define VER_FILESUBTYPE                        VFT2_UNKNOWN
-
-#if DBG
-#define VER_FILEDESCRIPTION_STR                "Direct Access Provider Library v2.0 (IBAL) (Debug)"
-#define VER_INTERNALNAME_STR           "dapl2d.dll"
-#define VER_ORIGINALFILENAME_STR       "dapl2d.dll"
-#else
-#define VER_FILEDESCRIPTION_STR                "Direct Access Provider Library v2.0 (IBAL)"
-#define VER_INTERNALNAME_STR           "dapl2.dll"
-#define VER_ORIGINALFILENAME_STR       "dapl2.dll"
-#endif
-
-#include <common.ver>
+/*\r
+ * Copyright (c) 2007 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
+ * $Id$\r
+ */\r
+\r
+\r
+#include <oib_ver.h>\r
+\r
+#define VER_FILETYPE                   VFT_DLL\r
+#define VER_FILESUBTYPE                        VFT2_UNKNOWN\r
+\r
+#if DBG\r
+#define VER_FILEDESCRIPTION_STR                "Direct Access Provider Library v2.0 (IBAL) (Debug)"\r
+#define VER_INTERNALNAME_STR           "dapl2d.dll"\r
+#define VER_ORIGINALFILENAME_STR       "dapl2d.dll"\r
+#else\r
+#define VER_FILEDESCRIPTION_STR                "Direct Access Provider Library v2.0 (IBAL)"\r
+#define VER_INTERNALNAME_STR           "dapl2.dll"\r
+#define VER_ORIGINALFILENAME_STR       "dapl2.dll"\r
+#endif\r
+\r
+#include <common.ver>\r
index a36b110733d561d97fb0d5255ed3e598e10b46bf..4439ec58fab456a4879682d48e1049a6f3679ea3 100644 (file)
-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- *    in the file LICENSE.txt in the root directory. The license is also
- *    available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is in the file
- *    LICENSE2.txt in the root directory. The license is also available from
- *    the Open Source Initiative, see
- *    http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a 
- *    copy of which is in the file LICENSE3.txt in the root directory. The 
- *    license is also available from the Open Source Initiative, see
- *    http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/**********************************************************************
- *
- * MODULE: dapl.h
- *
- * PURPOSE: defines common data structures for the DAPL reference implemenation
- *
- * Description: This file describes the working data structures used within
- *              DAPL RI.
- *
- *
- * $Id: dapl.h 1317 2005-04-25 17:29:42Z jlentini $
- **********************************************************************/
-
-#ifndef _DAPL_H_
-#define _DAPL_H_
-
-#if defined(__KERNEL__)
-#include <dat2/kdat.h>
-#else
-#include <dat2/udat.h>
-#endif /* defined(__KERNEL__) */
-#include <dat2/dat_registry.h>
-#include "dapl_osd.h"
-#include "dapl_debug.h"
-
-
-
-/*********************************************************************
- *                                                                   *
- * Enumerations                                                      *
- *                                                                   *
- *********************************************************************/
-
-typedef enum dapl_magic
-{
-    /* magic number values for verification & debug */
-    DAPL_MAGIC_IA      = 0xCafeF00d,
-    DAPL_MAGIC_EVD     = 0xFeedFace,
-    DAPL_MAGIC_EP      = 0xDeadBabe,
-    DAPL_MAGIC_LMR     = 0xBeefCafe,
-    DAPL_MAGIC_RMR      = 0xABadCafe,
-    DAPL_MAGIC_PZ      = 0xDeafBeef,
-    DAPL_MAGIC_PSP     = 0xBeadeD0c,
-    DAPL_MAGIC_RSP     = 0xFab4Feed,
-    DAPL_MAGIC_SRQ     = 0xC001Babe,
-    DAPL_MAGIC_CR      = 0xBe12Cee1,
-    DAPL_MAGIC_CR_DESTROYED = 0xB12bDead,
-    DAPL_MAGIC_CNO     = 0xDeadF00d,
-    DAPL_MAGIC_INVALID  = 0xFFFFFFFF
-} DAPL_MAGIC;
-
-typedef enum dapl_evd_state
-{
-    DAPL_EVD_STATE_TERMINAL,
-    DAPL_EVD_STATE_INITIAL,
-    DAPL_EVD_STATE_OPEN,
-    DAPL_EVD_STATE_WAITED,
-    DAPL_EVD_STATE_DEAD        = 0xDEAD
-} DAPL_EVD_STATE;
-
-typedef enum dapl_evd_completion
-{
-    DAPL_EVD_STATE_INIT,
-    DAPL_EVD_STATE_SOLICITED_WAIT,
-    DAPL_EVD_STATE_THRESHOLD,
-    DAPL_EVD_STATE_UNSIGNALLED
-} DAPL_EVD_COMPLETION;
-
-typedef enum dapl_cno_state
-{
-    DAPL_CNO_STATE_UNTRIGGERED,
-    DAPL_CNO_STATE_TRIGGERED,
-    DAPL_CNO_STATE_DEAD = 0xDeadFeed,
-} DAPL_CNO_STATE;
-
-typedef enum dapl_qp_state
-{
-    DAPL_QP_STATE_UNCONNECTED,
-    DAPL_QP_STATE_RESERVED,
-    DAPL_QP_STATE_PASSIVE_CONNECTION_PENDING,
-    DAPL_QP_STATE_ACTIVE_CONNECTION_PENDING,
-    DAPL_QP_STATE_TENTATIVE_CONNECTION_PENDING,
-    DAPL_QP_STATE_CONNECTED,
-    DAPL_QP_STATE_DISCONNECT_PENDING,
-    DAPL_QP_STATE_ERROR,
-    DAPL_QP_STATE_NOT_REUSABLE,
-    DAPL_QP_STATE_FREE
-} DAPL_QP_STATE;
-
-
-/*********************************************************************
- *                                                                   *
- * Constants                                                         *
- *                                                                   *
- *********************************************************************/
-
-/*
- * number of HCAs allowed
- */
-#define DAPL_MAX_HCA_COUNT             4
-
-/*
- * Configures the RMR bind evd restriction
- */
-
-#define DAPL_RMR_BIND_EVD_RESTRICTION  DAT_RMR_EVD_SAME_AS_REQUEST_EVD
-
-/*
- * special qp_state indicating the EP does not have a QP attached yet
- */
-#define DAPL_QP_STATE_UNATTACHED       0xFFF0
-
-#define DAPL_MAX_PRIVATE_DATA_SIZE     256
-
-/*********************************************************************
- *                                                                   *
- * Macros                                                            *
- *                                                                   *
- *********************************************************************/
-
-#if defined (sun) || defined(__sun) || defined(_sun_) || defined (__solaris__) 
-#define DAPL_BAD_PTR(a) ((unsigned long)(a) & 3)
-#elif defined(__linux__)
-#define DAPL_BAD_PTR(a) ((unsigned long)(a) & 3)
-#elif defined(_WIN64)
-#define DAPL_BAD_PTR(a) ((unsigned long)((DAT_UINT64)(a)) & 3)
-#elif defined(_WIN32)
-#define DAPL_BAD_PTR(a) ((unsigned long)((DAT_UINT64)(a)) & 3)
-#endif
-
-/*
- * Simple macro to verify a handle is bad. Conditions:
- * - pointer is NULL
- * - pointer is not word aligned
- * - pointer's magic number is wrong
- */
-
-#define DAPL_BAD_HANDLE(h, magicNum) (                         \
-           ((h) == NULL) ||                                    \
-           DAPL_BAD_PTR(h) ||                                  \
-           (((DAPL_HEADER *)(h))->magic != (magicNum)))
-
-#define DAPL_MIN(a, b)        ((a < b) ? (a) : (b))
-#define DAPL_MAX(a, b)        ((a > b) ? (a) : (b))
-
-#if NDEBUG > 0
-#define DEBUG_IS_BAD_HANDLE(h, magicNum) (DAPL_BAD_HANDLE(h, magicNum))
-#else
-#define DEBUG_IS_BAD_HANDLE(h, magicNum) (0)
-#endif
-
-#define DAT_ERROR(Type, SubType) ((DAT_RETURN)(DAT_CLASS_ERROR | Type | SubType))
-
-/*********************************************************************
- *                                                                   *
- * Typedefs                                                          *
- *                                                                   *
- *********************************************************************/
-
-typedef struct dapl_llist_entry                DAPL_LLIST_ENTRY;
-typedef DAPL_LLIST_ENTRY *             DAPL_LLIST_HEAD;
-typedef struct dapl_ring_buffer                DAPL_RING_BUFFER;
-typedef struct dapl_cookie_buffer      DAPL_COOKIE_BUFFER;
-
-typedef struct dapl_hash_table          DAPL_HASH_TABLE;
-typedef struct dapl_hash_table *        DAPL_HASH_TABLEP;
-typedef DAT_UINT64                      DAPL_HASH_KEY;
-typedef void *                          DAPL_HASH_DATA;
-
-typedef struct dapl_hca                        DAPL_HCA;
-
-typedef struct dapl_header             DAPL_HEADER;
-
-typedef struct dapl_ia                 DAPL_IA;
-typedef struct dapl_cno                        DAPL_CNO;
-typedef struct dapl_evd                DAPL_EVD;
-typedef struct dapl_ep                         DAPL_EP;
-typedef struct dapl_srq                        DAPL_SRQ;
-typedef struct dapl_pz                 DAPL_PZ;
-typedef struct dapl_lmr                        DAPL_LMR;
-typedef struct dapl_rmr                        DAPL_RMR;
-typedef struct dapl_sp                 DAPL_SP;
-typedef struct dapl_cr                 DAPL_CR;
-
-typedef struct dapl_cookie             DAPL_COOKIE;
-typedef struct dapl_dto_cookie         DAPL_DTO_COOKIE;
-typedef struct dapl_rmr_cookie         DAPL_RMR_COOKIE;
-
-typedef struct dapl_private            DAPL_PRIVATE;
-
-
-
-/*********************************************************************
- *                                                                   *
- * Structures                                                        *
- *                                                                   *
- *********************************************************************/
-
-struct dapl_llist_entry
-{
-    struct dapl_llist_entry    *flink;
-    struct dapl_llist_entry    *blink;
-    void                       *data;
-    DAPL_LLIST_HEAD            *list_head; /* for consistency checking */
-};
-
-struct dapl_ring_buffer
-{
-    void               **base;         /* base of element array */
-    DAT_COUNT          lim;            /* mask, number of entries - 1 */
-    DAPL_ATOMIC                head;           /* head pointer index */
-    DAPL_ATOMIC                tail;           /* tail pointer index */
-};
-
-struct dapl_cookie_buffer
-{
-    DAPL_COOKIE                *pool;
-    DAT_COUNT          pool_size;
-    DAPL_ATOMIC                head;
-    DAPL_ATOMIC                tail;
-};
-
-#ifdef IBAPI
-#include "dapl_ibapi_util.h"
-#elif VAPI
-#include "dapl_vapi_util.h"
-#elif __OPENIB__
-#include "dapl_openib_util.h"
-#include "dapl_openib_cm.h"
-#elif DUMMY
-#include "dapl_dummy_util.h"
-#elif OPENIB
-#include "dapl_ib_util.h"
-#else /* windows - IBAL and/or IBAL+Sock_CM */
-#include "dapl_ibal_util.h"
-#endif
-
-struct dapl_hca
-{
-    DAPL_OS_LOCK       lock;
-    DAPL_LLIST_HEAD    ia_list_head;      /* list of all open IAs */
-    DAPL_ATOMIC                handle_ref_count;  /* count of ia_opens on handle */
-    DAPL_EVD           *async_evd;
-    DAPL_EVD           *async_error_evd;
-    DAT_SOCK_ADDR6     hca_address;       /* local address of HCA*/
-    char               *name;             /* provider name */
-    ib_hca_handle_t    ib_hca_handle;
-    unsigned long       port_num;         /* physical port number */
-    ib_hca_transport_t  ib_trans;         /* Values specific transport API */
-    /* Memory Subsystem Support */
-    DAPL_HASH_TABLE    *lmr_hash_table;
-    /* Limits & useful HCA attributes */
-    DAT_IA_ATTR                ia_attr;
-};
-
-/* DAPL Objects always have the following header */
-struct dapl_header
-{
-    DAT_PROVIDER       *provider;      /* required by DAT - must be first */
-    DAPL_MAGIC         magic;          /* magic number for verification */
-    DAT_HANDLE_TYPE    handle_type;    /* struct type */
-    DAPL_IA            *owner_ia;      /* ia which owns this stuct */
-    DAPL_LLIST_ENTRY   ia_list_entry;  /* link entry on ia struct */
-    DAT_CONTEXT                user_context;   /* user context - opaque to DAPL */
-    DAPL_OS_LOCK       lock;           /* lock - in header for easier macros */
-};
-
-/* DAPL_IA maps to DAT_IA_HANDLE */
-struct dapl_ia
-{
-    DAPL_HEADER                header;
-    DAPL_HCA           *hca_ptr;
-    DAPL_EVD           *async_error_evd;
-    DAT_BOOLEAN                cleanup_async_error_evd;
-
-    DAPL_LLIST_ENTRY   hca_ia_list_entry;      /* HCAs list of IAs */
-    DAPL_LLIST_HEAD    ep_list_head;           /* EP queue */
-    DAPL_LLIST_HEAD    lmr_list_head;          /* LMR queue */
-    DAPL_LLIST_HEAD    rmr_list_head;          /* RMR queue */
-    DAPL_LLIST_HEAD    pz_list_head;           /* PZ queue */
-    DAPL_LLIST_HEAD    evd_list_head;          /* EVD queue */
-    DAPL_LLIST_HEAD    cno_list_head;          /* CNO queue */
-    DAPL_LLIST_HEAD    psp_list_head;          /* PSP queue */
-    DAPL_LLIST_HEAD    rsp_list_head;          /* RSP queue */
-    DAPL_LLIST_HEAD    srq_list_head;          /* SRQ queue */
-#ifdef DAPL_COUNTERS
-    void               *cntrs;
-#endif
-};
-
-/* DAPL_CNO maps to DAT_CNO_HANDLE */
-struct dapl_cno
-{
-    DAPL_HEADER        header;
-
-    /* A CNO cannot be freed while it is referenced elsewhere.  */
-    DAPL_ATOMIC                        cno_ref_count;
-    DAPL_CNO_STATE             cno_state;
-
-    DAT_COUNT                  cno_waiters;
-    DAPL_EVD                   *cno_evd_triggered;
-#if defined(__KERNEL__)
-    DAT_UPCALL_OBJECT          cno_upcall;
-    DAT_UPCALL_POLICY          cno_upcall_policy;
-#else
-    DAT_OS_WAIT_PROXY_AGENT    cno_wait_agent;
-#endif /* defined(__KERNEL__) */
-
-    DAPL_OS_WAIT_OBJECT                cno_wait_object;
-};
-
-/* DAPL_EVD maps to DAT_EVD_HANDLE */
-struct dapl_evd
-{
-    DAPL_HEADER                header;
-
-    DAPL_EVD_STATE     evd_state;
-    DAT_EVD_FLAGS      evd_flags;
-    DAT_BOOLEAN                evd_enabled; /* For attached CNO.  */
-    DAT_BOOLEAN                evd_waitable; /* EVD state.  */
-
-    /* Derived from evd_flags; see dapls_evd_internal_create.  */
-    DAT_BOOLEAN                evd_producer_locking_needed;
-
-    /* Every EVD has a CQ unless it is a SOFTWARE_EVENT only EVD */
-    ib_cq_handle_t     ib_cq_handle;
-
-    /* An Event Dispatcher cannot be freed while
-     * it is referenced elsewhere.
-     */
-    DAPL_ATOMIC                evd_ref_count;
-
-    /* Set if there has been a catastrophic overflow */
-    DAT_BOOLEAN                catastrophic_overflow;
-
-    /* the actual events */
-    DAT_COUNT          qlen;
-    DAT_EVENT          *events;
-    DAPL_RING_BUFFER   free_event_queue;
-    DAPL_RING_BUFFER   pending_event_queue;
-
-    /* CQ Completions are not placed into 'deferred_events'
-     ** rather they are simply left on the Completion Queue
-     ** and the fact that there was a notification is flagged.
-     */
-    DAT_BOOLEAN                cq_notified;
-    DAPL_OS_TICKS      cq_notified_when;
-
-    DAT_COUNT          cno_active_count;
-    DAPL_CNO           *cno_ptr;
-
-    DAPL_OS_WAIT_OBJECT        wait_object;
-
-    DAT_COUNT          threshold;
-    DAPL_EVD_COMPLETION        completion_type;
-
-#ifdef DAPL_COUNTERS
-    void               *cntrs;
-#endif
-};
-
-/* DAPL_PRIVATE used to pass private data in a connection */
-struct dapl_private
-{
-#ifdef IBHOSTS_NAMING
-    DAT_SOCK_ADDR6             hca_address;    /* local address of HCA*/
-#endif /* IBHOSTS_NAMING */
-    unsigned char              private_data[DAPL_MAX_PRIVATE_DATA_SIZE];
-};
-
-/* uDAPL timer entry, used to queue timeouts */
-struct dapl_timer_entry
-{
-    DAPL_LLIST_ENTRY           list_entry;     /* link entry on ia struct */
-    DAPL_OS_TIMEVAL            expires;
-    void                       (*function) (uintptr_t);
-    void                       *data;
-};
-
-#ifdef DAPL_DBG_IO_TRC
-
-#define DBG_IO_TRC_QLEN   32           /* length of trace buffer        */
-#define DBG_IO_TRC_IOV 3               /* iov elements we keep track of */
-
-struct io_buf_track
-{
-    Ib_send_op_type            op_type;
-    DAPL_COOKIE                        *cookie;
-    DAT_LMR_TRIPLET            iov[DBG_IO_TRC_IOV];
-    DAT_RMR_TRIPLET            remote_iov;
-    unsigned int               done;   /* count to track completion ordering */
-    int                                status;
-    void                       *wqe;
-};
-
-#endif /* DAPL_DBG_IO_TRC */
-
-/* DAPL_EP maps to DAT_EP_HANDLE */
-struct dapl_ep
-{
-    DAPL_HEADER                        header;
-    /* What the DAT Consumer asked for */
-    DAT_EP_PARAM               param;
-
-    /* The RC Queue Pair (IBM OS API) */
-    ib_qp_handle_t             qp_handle;
-    unsigned int               qpn;    /* qp number */
-    ib_qp_state_t              qp_state;
-
-    /* communications manager handle (IBM OS API) */
-    dp_ib_cm_handle_t          cm_handle;
-
-    /* store the remote IA address here, reference from the param
-     * struct which only has a pointer, no storage
-     */
-    DAT_SOCK_ADDR6             remote_ia_address;
-
-    /* For passive connections we maintain a back pointer to the CR */
-    void *                     cr_ptr;
-
-    /* pointer to connection timer, if set */
-    struct dapl_timer_entry    *cxn_timer;
-
-    /* private data container */
-    DAPL_PRIVATE               private;
-
-    /* DTO data */
-    DAPL_ATOMIC                        req_count;
-    DAPL_ATOMIC                        recv_count;
-
-    DAPL_COOKIE_BUFFER req_buffer;
-    DAPL_COOKIE_BUFFER recv_buffer;
-
-#ifdef DAPL_DBG_IO_TRC
-    int                        ibt_dumped;
-    struct io_buf_track *ibt_base;
-    DAPL_RING_BUFFER   ibt_queue;
-#endif /* DAPL_DBG_IO_TRC */
-#if defined(_WIN32) || defined(_WIN64)
-    DAT_BOOLEAN         recv_discreq;
-    DAT_BOOLEAN         sent_discreq;
-    dp_ib_cm_handle_t   ibal_cm_handle;
-#endif
-#ifdef DAPL_COUNTERS
-    void               *cntrs;
-#endif
-};
-
-/* DAPL_SRQ maps to DAT_SRQ_HANDLE */
-struct dapl_srq
-{
-    DAPL_HEADER                header;
-    DAT_SRQ_PARAM      param;
-    DAPL_ATOMIC                srq_ref_count;
-    DAPL_COOKIE_BUFFER recv_buffer;
-    DAPL_ATOMIC                recv_count;
-};
-
-/* DAPL_PZ maps to DAT_PZ_HANDLE */
-struct dapl_pz
-{
-    DAPL_HEADER                header;
-    ib_pd_handle_t     pd_handle;
-    DAPL_ATOMIC                pz_ref_count;
-};
-
-/* DAPL_LMR maps to DAT_LMR_HANDLE */
-struct dapl_lmr
-{
-    DAPL_HEADER                header;
-    DAT_LMR_PARAM      param;
-    ib_mr_handle_t     mr_handle;
-    DAPL_ATOMIC                lmr_ref_count;
-#if !defined(__KDAPL__)
-    char               shmid[DAT_LMR_COOKIE_SIZE]; /* shared memory ID */
-    ib_shm_transport_t ib_trans;       /* provider specific data */
-#endif /* !__KDAPL__ */
-};
-
-/* DAPL_RMR maps to DAT_RMR_HANDLE */
-struct dapl_rmr
-{
-    DAPL_HEADER                header;
-    DAT_RMR_PARAM      param;
-    DAPL_EP             *ep;
-    DAPL_PZ             *pz;
-    DAPL_LMR            *lmr;
-    ib_mw_handle_t     mw_handle;
-};
-
-/* SP types, indicating the state and queue */
-typedef enum dapl_sp_state
-{
-    DAPL_SP_STATE_FREE,
-    DAPL_SP_STATE_PSP_LISTENING,
-    DAPL_SP_STATE_PSP_PENDING,
-    DAPL_SP_STATE_RSP_LISTENING,
-    DAPL_SP_STATE_RSP_PENDING
-} DAPL_SP_STATE;
-
-/* DAPL_SP maps to DAT_PSP_HANDLE and DAT_RSP_HANDLE */
-struct dapl_sp
-{
-    DAPL_HEADER                header;
-    DAPL_SP_STATE      state;          /* type and queue of the SP */
-
-    /* PSP/RSP PARAM fields */
-    DAT_CONN_QUAL       conn_qual;
-    DAT_EVD_HANDLE      evd_handle;
-    DAT_PSP_FLAGS       psp_flags;
-    DAT_EP_HANDLE       ep_handle;
-
-     /* maintenence fields */
-    DAT_BOOLEAN                listening;      /* PSP is registered & active */
-    ib_cm_srvc_handle_t        cm_srvc_handle; /* Used by Mellanox CM */
-    DAPL_LLIST_HEAD    cr_list_head;   /* CR pending queue */
-    DAT_COUNT          cr_list_count;  /* count of CRs on queue */
-#if defined(_VENDOR_IBAL_)
-    DAPL_OS_WAIT_OBJECT wait_object;    /* cancel & destroy. */
-#endif
-};
-
-/* DAPL_CR maps to DAT_CR_HANDLE */
-struct dapl_cr
-{
-    DAPL_HEADER                header;
-
-    /* for convenience the data is kept as a DAT_CR_PARAM.
-     * however, the "local_endpoint" field is always NULL
-     * so this wastes a pointer. This is probably ok to
-     * simplify code, espedially dat_cr_query.
-     */
-    DAT_CR_PARAM       param;
-    /* IB specific fields */
-    dp_ib_cm_handle_t  ib_cm_handle;
-
-    DAT_SOCK_ADDR6     remote_ia_address;
-    /* Assuming that the maximum private data size is small.
-     * If it gets large, use of a pointer may be appropriate.
-     */
-    unsigned char      private_data[DAPL_MAX_PRIVATE_DATA_SIZE];
-    /*
-     * Need to be able to associate the CR back to the PSP for
-     * dapl_cr_reject.
-     */
-    DAPL_SP            *sp_ptr;
-};
-
-typedef enum dapl_dto_type
-{
-    DAPL_DTO_TYPE_SEND,
-    DAPL_DTO_TYPE_RECV,
-    DAPL_DTO_TYPE_RDMA_WRITE,
-    DAPL_DTO_TYPE_RDMA_READ,
-#ifdef DAT_EXTENSIONS
-    DAPL_DTO_TYPE_EXTENSION,
-#endif
-} DAPL_DTO_TYPE;
-
-typedef enum dapl_cookie_type
-{
-    DAPL_COOKIE_TYPE_NULL,
-    DAPL_COOKIE_TYPE_DTO,
-    DAPL_COOKIE_TYPE_RMR,
-} DAPL_COOKIE_TYPE;
-
-/* DAPL_DTO_COOKIE used as context for DTO WQEs */
-struct dapl_dto_cookie
-{
-    DAPL_DTO_TYPE              type;
-    DAT_DTO_COOKIE             cookie;
-    DAT_COUNT                  size;   /* used for SEND and RDMA write */
-};
-
-/* DAPL_RMR_COOKIE used as context for bind WQEs */
-struct dapl_rmr_cookie
-{
-    DAPL_RMR                   *rmr;
-    DAT_RMR_COOKIE              cookie;
-};
-
-/* DAPL_COOKIE used as context for WQEs */
-struct dapl_cookie
-{
-    DAPL_COOKIE_TYPE           type; /* Must be first, to define struct.  */
-    DAPL_EP                    *ep;
-    DAT_COUNT                  index;
-    union
-    {
-       DAPL_DTO_COOKIE         dto;
-       DAPL_RMR_COOKIE         rmr;
-    } val;
-};
-
-/*
- * Private Data operations. Used to obtain the size of the private
- * data from the provider layer.
- */
-typedef enum dapl_private_data_op
-{
-    DAPL_PDATA_CONN_REQ  = 0,          /* connect request    */
-    DAPL_PDATA_CONN_REP  = 1,          /* connect reply      */
-    DAPL_PDATA_CONN_REJ  = 2,          /* connect reject     */
-    DAPL_PDATA_CONN_DREQ = 3,          /* disconnect request */
-    DAPL_PDATA_CONN_DREP = 4,          /* disconnect reply   */
-} DAPL_PDATA_OP;
-
-
-/*
- * Generic HCA name field
- */
-#define DAPL_HCA_NAME_MAX_LEN 260
-typedef char DAPL_HCA_NAME[DAPL_HCA_NAME_MAX_LEN+1];
-
-#ifdef IBHOSTS_NAMING
-
-/*
- * Simple mapping table to match IP addresses to GIDs. Loaded
- * by dapl_init.
- */
-typedef struct _dapl_gid_map_table
-{
-    uint32_t           ip_address;
-    ib_gid_t           gid;
-} DAPL_GID_MAP;
-
-#endif /* IBHOSTS_NAMING */
-
-/*
- * IBTA defined reason for reject message: See IBTA 1.1 specification,
- * 12.6.7.2 REJECTION REASON section.
- */
-#define IB_CM_REJ_REASON_CONSUMER_REJ            0x001C
-
-
-#if defined(DAPL_DBG_IO_TRC)
-/*********************************************************************
- *                                                                   *
- * Debug I/O tracing support prototypes                              *
- *                                                                   *
- *********************************************************************/
-/*
- * I/O tracing support
- */
-void dapls_io_trc_alloc (
-    DAPL_EP                    *ep_ptr);
-
-void dapls_io_trc_update_completion (
-    DAPL_EP                    *ep_ptr,
-    DAPL_COOKIE                        *cookie,
-    ib_uint32_t                        ib_status );
-
-void dapls_io_trc_dump (
-    DAPL_EP                    *ep_ptr,
-    ib_work_completion_t       *cqe_ptr,
-    ib_uint32_t                        ib_status);
-
-#else /* DAPL_DBG_IO_TRC */
-
-#define dapls_io_trc_alloc(a)
-#define dapls_io_trc_update_completion(a, b, c)
-#define dapls_io_trc_dump(a, b, c)
-
-#endif /* DAPL_DBG_IO_TRC */
-
-
-/*********************************************************************
- *                                                                   *
- * Function Prototypes                                               *
- *                                                                   *
- *********************************************************************/
-
-typedef void (*DAPL_CONNECTION_STATE_HANDLER) (
-       IN      DAPL_EP *,
-       IN      ib_cm_events_t,
-       IN      const void *,
-       OUT     DAT_EVENT *);
-
-/*
- * DAT Mandated functions
- */
-
-extern DAT_RETURN DAT_API dapl_ia_open (
-       IN      const DAT_NAME_PTR,     /* name */
-       IN      DAT_COUNT,              /* asynch_evd_qlen */
-       INOUT   DAT_EVD_HANDLE *,       /* asynch_evd_handle */
-       OUT     DAT_IA_HANDLE *);       /* ia_handle */
-
-extern DAT_RETURN DAT_API dapl_ia_close (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_CLOSE_FLAGS );      /* ia_flags */
-
-
-extern DAT_RETURN DAT_API dapl_ia_query (
-       IN      DAT_IA_HANDLE,          /* ia handle */
-       OUT     DAT_EVD_HANDLE *,       /* async_evd_handle */
-       IN      DAT_IA_ATTR_MASK,       /* ia_params_mask */
-       OUT     DAT_IA_ATTR *,          /* ia_params */
-       IN      DAT_PROVIDER_ATTR_MASK, /* provider_params_mask */
-       OUT     DAT_PROVIDER_ATTR * );  /* provider_params */
-
-
-/* helper functions */
-
-extern DAT_RETURN DAT_API dapl_set_consumer_context (
-       IN      DAT_HANDLE,                     /* dat handle */
-       IN      DAT_CONTEXT);                   /* context */
-
-extern DAT_RETURN DAT_API dapl_get_consumer_context (
-       IN      DAT_HANDLE,                     /* dat handle */
-       OUT     DAT_CONTEXT * );                /* context */
-
-extern DAT_RETURN DAT_API dapl_get_handle_type (
-       IN      DAT_HANDLE,
-       OUT     DAT_HANDLE_TYPE * );
-
-/* CNO functions */
-
-#if !defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_cno_create (
-       IN      DAT_IA_HANDLE,                  /* ia_handle */
-       IN      DAT_OS_WAIT_PROXY_AGENT,        /* agent */
-       OUT     DAT_CNO_HANDLE *);              /* cno_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_modify_agent (
-       IN      DAT_CNO_HANDLE,                 /* cno_handle */
-       IN      DAT_OS_WAIT_PROXY_AGENT);       /* agent */
-
-extern DAT_RETURN DAT_API dapl_cno_query (
-       IN      DAT_CNO_HANDLE,         /* cno_handle */
-       IN      DAT_CNO_PARAM_MASK,     /* cno_param_mask */
-       OUT     DAT_CNO_PARAM * );      /* cno_param */
-
-extern DAT_RETURN DAT_API dapl_cno_free (
-       IN      DAT_CNO_HANDLE);        /* cno_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_wait (
-       IN      DAT_CNO_HANDLE,         /* cno_handle */
-       IN      DAT_TIMEOUT,            /* timeout */
-       OUT     DAT_EVD_HANDLE *);      /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_fd_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle            */
-       OUT     DAT_FD *,               /* file_descriptor      */
-       OUT     DAT_CNO_HANDLE *);      /* cno_handle           */
-
-extern DAT_RETURN DAT_API dapl_cno_trigger (
-       IN      DAT_CNO_HANDLE,         /* cno_handle */
-       OUT     DAT_EVD_HANDLE *);      /* evd_handle */
-
-#endif /* !defined(__KERNEL__) */
-
-/* CR Functions */
-
-extern DAT_RETURN DAT_API dapl_cr_query (
-       IN      DAT_CR_HANDLE,          /* cr_handle */
-       IN      DAT_CR_PARAM_MASK,      /* cr_args_mask */
-       OUT     DAT_CR_PARAM * );       /* cwr_args */
-
-extern DAT_RETURN DAT_API dapl_cr_accept (
-       IN      DAT_CR_HANDLE,          /* cr_handle */
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_COUNT,              /* private_data_size */
-       IN      const DAT_PVOID );      /* private_data */
-
-extern DAT_RETURN DAT_API dapl_cr_reject (
-       IN      DAT_CR_HANDLE,          /* cr_handle            */
-       IN      DAT_COUNT,              /* private_data_size    */
-       IN      const DAT_PVOID );      /* private_data         */
-
-extern DAT_RETURN DAT_API dapl_cr_handoff (
-       IN DAT_CR_HANDLE,               /* cr_handle */
-       IN DAT_CONN_QUAL);              /* handoff */
-
-/* EVD Functions */
-
-#if defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_ia_memtype_hint (
-       IN    DAT_IA_HANDLE,            /* ia_handle */
-       IN    DAT_MEM_TYPE,             /* mem_type */
-       IN    DAT_VLEN,                 /* length */
-       IN    DAT_MEM_OPT,              /* mem_optimization */
-       OUT   DAT_VLEN *,               /* suggested_length */
-       OUT   DAT_VADDR *);             /* suggested_alignment */
-
-extern DAT_RETURN DAT_API dapl_evd_kcreate (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_COUNT,              /* evd_min_qlen */
-       IN      DAT_UPCALL_POLICY,      /* upcall_policy */
-       IN      const DAT_UPCALL_OBJECT *, /* upcall */
-       IN      DAT_EVD_FLAGS,          /* evd_flags */
-       OUT     DAT_EVD_HANDLE * );     /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_evd_kquery (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_EVD_PARAM_MASK,     /* evd_args_mask */
-       OUT     DAT_EVD_PARAM * );      /* evd_args */
-
-#else
-extern DAT_RETURN DAT_API dapl_evd_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_COUNT,              /* evd_min_qlen */
-       IN      DAT_CNO_HANDLE,         /* cno_handle */
-       IN      DAT_EVD_FLAGS,          /* evd_flags */
-       OUT     DAT_EVD_HANDLE * );     /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_evd_query (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_EVD_PARAM_MASK,     /* evd_args_mask */
-       OUT     DAT_EVD_PARAM * );      /* evd_args */
-#endif /* defined(__KERNEL__) */
-
-#if defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_evd_modify_upcall (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_UPCALL_POLICY,      /* upcall_policy */
-       IN      const DAT_UPCALL_OBJECT * ); /* upcall */
-
-#else
-
-extern DAT_RETURN DAT_API dapl_evd_modify_cno (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_CNO_HANDLE);        /* cno_handle */
-#endif
-
-extern DAT_RETURN DAT_API dapl_evd_enable (
-       IN      DAT_EVD_HANDLE);        /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_evd_disable (
-       IN      DAT_EVD_HANDLE);        /* evd_handle */
-
-#if !defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_evd_wait (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_TIMEOUT,            /* timeout */
-       IN      DAT_COUNT,              /* threshold */
-       OUT     DAT_EVENT *,            /* event */
-       OUT     DAT_COUNT *);           /* nmore */
-#endif /* !defined(__KERNEL__) */
-
-extern DAT_RETURN DAT_API dapl_evd_resize (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_COUNT );            /* evd_qlen */
-
-extern DAT_RETURN DAT_API dapl_evd_post_se (
-       DAT_EVD_HANDLE,                 /* evd_handle */
-       const DAT_EVENT * );            /* event */
-
-extern DAT_RETURN DAT_API dapl_evd_dequeue (
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       OUT     DAT_EVENT * );          /* event */
-
-extern DAT_RETURN DAT_API dapl_evd_free (
-       IN      DAT_EVD_HANDLE );
-
-extern DAT_RETURN DAT_API
-dapl_evd_set_unwaitable (
-       IN      DAT_EVD_HANDLE  evd_handle );
-
-extern DAT_RETURN DAT_API
-dapl_evd_clear_unwaitable (
-       IN      DAT_EVD_HANDLE  evd_handle );
-
-/* EP functions */
-
-extern DAT_RETURN DAT_API dapl_ep_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_PZ_HANDLE,          /* pz_handle */
-       IN      DAT_EVD_HANDLE,         /* in_dto_completion_evd_handle */
-       IN      DAT_EVD_HANDLE,         /* out_dto_completion_evd_handle */
-       IN      DAT_EVD_HANDLE,         /* connect_evd_handle */
-       IN      const DAT_EP_ATTR *,    /* ep_parameters */
-       OUT     DAT_EP_HANDLE * );      /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_query (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_EP_PARAM_MASK,      /* ep_args_mask */
-       OUT     DAT_EP_PARAM * );       /* ep_args */
-
-extern DAT_RETURN DAT_API dapl_ep_modify (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_EP_PARAM_MASK,      /* ep_args_mask */
-       IN      const DAT_EP_PARAM * ); /* ep_args */
-
-extern DAT_RETURN DAT_API dapl_ep_connect (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_IA_ADDRESS_PTR,     /* remote_ia_address */
-       IN      DAT_CONN_QUAL,          /* remote_conn_qual */
-       IN      DAT_TIMEOUT,            /* timeout */
-       IN      DAT_COUNT,              /* private_data_size */
-       IN      const DAT_PVOID,        /* private_data  */
-       IN      DAT_QOS,                /* quality_of_service */
-       IN      DAT_CONNECT_FLAGS );    /* connect_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_common_connect (
-       IN      DAT_EP_HANDLE ep,               /* ep_handle            */
-       IN      DAT_IA_ADDRESS_PTR remote_addr, /* remote_ia_address    */
-       IN      DAT_TIMEOUT timeout,            /* timeout              */
-       IN      DAT_COUNT pdata_size,           /* private_data_size    */
-       IN      const DAT_PVOID pdata   );      /* private_data         */
-
-extern DAT_RETURN DAT_API dapl_ep_dup_connect (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_EP_HANDLE,          /* ep_dup_handle */
-       IN      DAT_TIMEOUT,            /* timeout*/
-       IN      DAT_COUNT,              /* private_data_size */
-       IN      const DAT_PVOID,        /* private_data */
-       IN      DAT_QOS);               /* quality_of_service */
-
-extern DAT_RETURN DAT_API dapl_ep_disconnect (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_CLOSE_FLAGS );      /* close_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_send (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_COUNT,              /* num_segments */
-       IN      DAT_LMR_TRIPLET *,      /* local_iov */
-       IN      DAT_DTO_COOKIE,         /* user_cookie */
-       IN      DAT_COMPLETION_FLAGS ); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_recv (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_COUNT,              /* num_segments */
-       IN      DAT_LMR_TRIPLET *,      /* local_iov */
-       IN      DAT_DTO_COOKIE,         /* user_cookie */
-       IN      DAT_COMPLETION_FLAGS ); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_rdma_read (
-       IN      DAT_EP_HANDLE,           /* ep_handle */
-       IN      DAT_COUNT,               /* num_segments */
-       IN      DAT_LMR_TRIPLET *,       /* local_iov */
-       IN      DAT_DTO_COOKIE,          /* user_cookie */
-       IN      const DAT_RMR_TRIPLET *, /* remote_iov */
-       IN      DAT_COMPLETION_FLAGS );  /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_rdma_read_to_rmr (
-       IN      DAT_EP_HANDLE,          /* ep_handle            */
-       IN      const DAT_RMR_TRIPLET *,/* local_iov            */
-       IN      DAT_DTO_COOKIE,         /* user_cookie          */
-       IN      const DAT_RMR_TRIPLET *,/* remote_iov           */
-       IN      DAT_COMPLETION_FLAGS);  /* completion_flags     */
-
-extern DAT_RETURN DAT_API dapl_ep_post_rdma_write (
-       IN      DAT_EP_HANDLE,           /* ep_handle */
-       IN      DAT_COUNT,               /* num_segments */
-       IN      DAT_LMR_TRIPLET *,       /* local_iov */
-       IN      DAT_DTO_COOKIE,          /* user_cookie */
-       IN      const DAT_RMR_TRIPLET *, /* remote_iov */
-       IN      DAT_COMPLETION_FLAGS );  /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_send_with_invalidate (
-       IN      DAT_EP_HANDLE,          /* ep_handle            */
-       IN      DAT_COUNT,              /* num_segments         */
-       IN      DAT_LMR_TRIPLET *,      /* local_iov            */
-       IN      DAT_DTO_COOKIE,         /* user_cookie          */
-       IN      DAT_COMPLETION_FLAGS,   /* completion_flags     */
-       IN      DAT_BOOLEAN,            /* invalidate_flag      */
-       IN      DAT_RMR_CONTEXT);      /* RMR context          */
-
-extern DAT_RETURN DAT_API dapl_ep_get_status (
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       OUT     DAT_EP_STATE *,         /* ep_state */
-       OUT     DAT_BOOLEAN *,          /* in_dto_idle */
-       OUT     DAT_BOOLEAN * );        /* out_dto_idle */
-
-extern DAT_RETURN DAT_API dapl_ep_free (
-       IN      DAT_EP_HANDLE);         /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_reset (
-       IN      DAT_EP_HANDLE);         /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_create_with_srq (
-        IN      DAT_IA_HANDLE,          /* ia_handle            */
-        IN      DAT_PZ_HANDLE,          /* pz_handle            */
-        IN      DAT_EVD_HANDLE,         /* recv_evd_handle      */
-        IN      DAT_EVD_HANDLE,         /* request_evd_handle   */
-        IN      DAT_EVD_HANDLE,         /* connect_evd_handle   */
-        IN      DAT_SRQ_HANDLE,         /* srq_handle           */
-        IN      const DAT_EP_ATTR *,    /* ep_attributes        */
-        OUT     DAT_EP_HANDLE *);       /* ep_handle            */
-
-extern DAT_RETURN DAT_API dapl_ep_recv_query (
-        IN      DAT_EP_HANDLE,          /* ep_handle            */
-        OUT     DAT_COUNT *,            /* nbufs_allocated      */
-        OUT     DAT_COUNT *);           /* bufs_alloc_span      */
-
-extern DAT_RETURN DAT_API dapl_ep_set_watermark (
-        IN      DAT_EP_HANDLE,          /* ep_handle            */
-        IN      DAT_COUNT,              /* soft_high_watermark  */
-        IN      DAT_COUNT);             /* hard_high_watermark  */
-
-/* LMR functions */
-
-#if defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_lmr_kcreate (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_MEM_TYPE,           /* mem_type */
-       IN      DAT_REGION_DESCRIPTION, /* region_description */
-       IN      DAT_VLEN,               /* length */
-       IN      DAT_PZ_HANDLE,          /* pz_handle */
-       IN      DAT_MEM_PRIV_FLAGS,     /* privileges */
-       IN      DAT_VA_TYPE,            /* va_type */
-       IN      DAT_MEM_OPT,            /* optimization */
-       OUT     DAT_LMR_HANDLE *,       /* lmr_handle */
-       OUT     DAT_LMR_CONTEXT *,      /* lmr_context */
-       OUT     DAT_RMR_CONTEXT *,      /* rmr_context          */
-       OUT     DAT_VLEN *,             /* registered_length */
-       OUT     DAT_VADDR * );          /* registered_address */
-#else
-extern DAT_RETURN DAT_API dapl_lmr_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_MEM_TYPE,           /* mem_type */
-       IN      DAT_REGION_DESCRIPTION, /* region_description */
-       IN      DAT_VLEN,               /* length */
-       IN      DAT_PZ_HANDLE,          /* pz_handle */
-       IN      DAT_MEM_PRIV_FLAGS,     /* privileges */
-       IN      DAT_VA_TYPE,            /* va_type */
-       OUT     DAT_LMR_HANDLE *,       /* lmr_handle */
-       OUT     DAT_LMR_CONTEXT *,      /* lmr_context */
-       OUT     DAT_RMR_CONTEXT *,      /* rmr_context          */
-       OUT     DAT_VLEN *,             /* registered_length */
-       OUT     DAT_VADDR * );          /* registered_address */
-#endif /* defined(__KERNEL__) */
-
-extern DAT_RETURN DAT_API dapl_lmr_query (
-       IN      DAT_LMR_HANDLE,
-       IN      DAT_LMR_PARAM_MASK,
-       OUT     DAT_LMR_PARAM *);
-
-extern DAT_RETURN DAT_API dapl_lmr_free (
-       IN      DAT_LMR_HANDLE);
-
-extern DAT_RETURN DAT_API dapl_lmr_sync_rdma_read (
-       IN      DAT_IA_HANDLE,          /* ia_handle            */
-       IN      const DAT_LMR_TRIPLET *, /* local_segments      */
-       IN      DAT_VLEN);              /* num_segments         */
-
-extern DAT_RETURN DAT_API dapl_lmr_sync_rdma_write (
-       IN      DAT_IA_HANDLE,          /* ia_handle            */
-       IN      const DAT_LMR_TRIPLET *, /* local_segments      */
-       IN      DAT_VLEN);              /* num_segments         */
-
-/* RMR Functions */
-
-extern DAT_RETURN DAT_API dapl_rmr_create (
-       IN      DAT_PZ_HANDLE,          /* pz_handle */
-       OUT     DAT_RMR_HANDLE *);      /* rmr_handle */
-
-extern DAT_RETURN DAT_API dapl_rmr_create_for_ep (
-       IN      DAT_PZ_HANDLE pz_handle,        /* pz_handle    */
-       OUT     DAT_RMR_HANDLE *rmr_handle);    /* rmr_handle   */
-
-extern DAT_RETURN DAT_API dapl_rmr_query (
-       IN      DAT_RMR_HANDLE,         /* rmr_handle */
-       IN      DAT_RMR_PARAM_MASK,     /* rmr_args_mask */
-       OUT     DAT_RMR_PARAM *);       /* rmr_args */
-
-extern DAT_RETURN DAT_API dapl_rmr_bind (
-       IN      DAT_RMR_HANDLE,          /* rmr_handle */
-       IN      DAT_LMR_HANDLE,          /* lmr_handle */
-       IN      const DAT_LMR_TRIPLET *, /* lmr_triplet */
-       IN      DAT_MEM_PRIV_FLAGS,      /* mem_priv */
-       IN      DAT_VA_TYPE,             /* va_type */
-       IN      DAT_EP_HANDLE,           /* ep_handle */
-       IN      DAT_RMR_COOKIE,          /* user_cookie */
-       IN      DAT_COMPLETION_FLAGS,    /* completion_flags */
-       INOUT   DAT_RMR_CONTEXT * );     /* context */
-
-extern DAT_RETURN DAT_API dapl_rmr_free (
-       IN      DAT_RMR_HANDLE);
-
-/* PSP Functions */
-
-extern DAT_RETURN DAT_API dapl_psp_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_CONN_QUAL,          /* conn_qual */
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_PSP_FLAGS,          /* psp_flags */
-       OUT     DAT_PSP_HANDLE * );     /* psp_handle */
-
-extern DAT_RETURN DAT_API dapl_psp_create_any (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       OUT     DAT_CONN_QUAL *,        /* conn_qual */
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       IN      DAT_PSP_FLAGS,          /* psp_flags */
-       OUT     DAT_PSP_HANDLE *);      /* psp_handle */
-
-extern DAT_RETURN DAT_API dapl_psp_query (
-       IN      DAT_PSP_HANDLE,
-       IN      DAT_PSP_PARAM_MASK,
-       OUT     DAT_PSP_PARAM * );
-
-extern DAT_RETURN DAT_API dapl_psp_free (
-       IN      DAT_PSP_HANDLE );       /* psp_handle */
-
-/* RSP Functions */
-
-extern DAT_RETURN DAT_API dapl_rsp_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       IN      DAT_CONN_QUAL,          /* conn_qual */
-       IN      DAT_EP_HANDLE,          /* ep_handle */
-       IN      DAT_EVD_HANDLE,         /* evd_handle */
-       OUT     DAT_RSP_HANDLE * );     /* rsp_handle */
-
-extern DAT_RETURN DAT_API dapl_rsp_query (
-       IN      DAT_RSP_HANDLE,
-       IN      DAT_RSP_PARAM_MASK,
-       OUT     DAT_RSP_PARAM * );
-
-extern DAT_RETURN DAT_API dapl_rsp_free (
-       IN      DAT_RSP_HANDLE );       /* rsp_handle */
-
-/* PZ Functions */
-
-extern DAT_RETURN DAT_API dapl_pz_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle */
-       OUT     DAT_PZ_HANDLE * );      /* pz_handle */
-
-extern DAT_RETURN DAT_API dapl_pz_query (
-       IN      DAT_PZ_HANDLE,          /* pz_handle */
-       IN      DAT_PZ_PARAM_MASK,      /* pz_args_mask */
-       OUT     DAT_PZ_PARAM * );       /* pz_args */
-
-extern DAT_RETURN DAT_API dapl_pz_free (
-       IN      DAT_PZ_HANDLE );        /* pz_handle */
-
-/* SRQ functions */
-
-extern DAT_RETURN DAT_API dapl_srq_create (
-        IN      DAT_IA_HANDLE,          /* ia_handle            */
-        IN      DAT_PZ_HANDLE,          /* pz_handle            */
-        IN      DAT_SRQ_ATTR *,         /* srq_attr             */
-        OUT     DAT_SRQ_HANDLE *);      /* srq_handle           */
-
-extern DAT_RETURN DAT_API dapl_srq_free (
-       IN      DAT_SRQ_HANDLE);        /* srq_handle           */
-
-extern DAT_RETURN DAT_API dapl_srq_post_recv (
-       IN      DAT_SRQ_HANDLE,         /* srq_handle           */
-       IN      DAT_COUNT,              /* num_segments         */
-       IN      DAT_LMR_TRIPLET *,      /* local_iov            */
-       IN      DAT_DTO_COOKIE);        /* user_cookie          */
-
-extern DAT_RETURN DAT_API dapl_srq_query (
-       IN      DAT_SRQ_HANDLE,         /* srq_handle           */
-       IN      DAT_SRQ_PARAM_MASK,     /* srq_param_mask       */
-       OUT     DAT_SRQ_PARAM *);       /* srq_param            */
-
-extern DAT_RETURN DAT_API dapl_srq_resize (
-       IN      DAT_SRQ_HANDLE,         /* srq_handle           */
-       IN      DAT_COUNT);             /* srq_max_recv_dto     */
-
-extern DAT_RETURN DAT_API dapl_srq_set_lw (
-       IN      DAT_SRQ_HANDLE,         /* srq_handle           */
-       IN      DAT_COUNT);             /* low_watermark        */
-
-/* CSP functions */
-extern DAT_RETURN DAT_API dapl_csp_create (
-       IN      DAT_IA_HANDLE,          /* ia_handle      */
-       IN      DAT_COMM *,             /* communicator   */
-       IN      DAT_IA_ADDRESS_PTR,     /* address        */
-       IN      DAT_EVD_HANDLE,         /* evd_handle     */
-       OUT     DAT_CSP_HANDLE *);      /* csp_handle     */
-
-extern DAT_RETURN DAT_API dapl_csp_query (
-       IN      DAT_CSP_HANDLE,         /* csp_handle     */
-       IN      DAT_CSP_PARAM_MASK,     /* csp_param_mask */
-       OUT     DAT_CSP_PARAM *);       /* csp_param      */
-
-extern DAT_RETURN DAT_API dapl_csp_free (
-       IN      DAT_CSP_HANDLE);        /* csp_handle     */
-
-/* HA functions */
-DAT_RETURN DAT_API dapl_ia_ha (
-       IN       DAT_IA_HANDLE,         /* ia_handle */
-       IN const DAT_NAME_PTR,          /* provider  */
-       OUT      DAT_BOOLEAN *);        /* answer    */
-
-#ifdef DAT_EXTENSIONS
-#include <stdarg.h>
-extern DAT_RETURN DAT_API dapl_extensions (
-       IN      DAT_HANDLE,             /* handle */
-       IN      DAT_EXTENDED_OP,        /* extended op */
-       IN      va_list);               /* argument list */
-#endif
-
-/*
- * DAPL internal utility function prototpyes
- */
-
-extern void dapl_llist_init_head (
-    DAPL_LLIST_HEAD *  head);
-
-extern void dapl_llist_init_entry (
-    DAPL_LLIST_ENTRY *         entry);
-
-extern DAT_BOOLEAN dapl_llist_is_empty (
-    DAPL_LLIST_HEAD *  head);
-
-extern void dapl_llist_add_head (
-    DAPL_LLIST_HEAD *  head,
-    DAPL_LLIST_ENTRY *         entry,
-    void *             data);
-
-extern void dapl_llist_add_tail (
-    DAPL_LLIST_HEAD *   head,
-    DAPL_LLIST_ENTRY *  entry,
-    void *             data);
-
-extern void dapl_llist_add_entry (
-    DAPL_LLIST_HEAD * head,
-    DAPL_LLIST_ENTRY * entry,
-    DAPL_LLIST_ENTRY * new_entry,
-    void * data);
-
-extern void * dapl_llist_remove_head (
-    DAPL_LLIST_HEAD *  head);
-
-extern void * dapl_llist_remove_tail (
-    DAPL_LLIST_HEAD *  head);
-
-extern void * dapl_llist_remove_entry (
-    DAPL_LLIST_HEAD *  head,
-    DAPL_LLIST_ENTRY * entry);
-
-extern void * dapl_llist_peek_head (
-    DAPL_LLIST_HEAD *  head);
-
-extern void * dapl_llist_next_entry (
-    IN    DAPL_LLIST_HEAD      *head,
-    IN    DAPL_LLIST_ENTRY     *cur_ent);
-
-extern void dapl_llist_debug_print_list (
-    DAPL_LLIST_HEAD *  head);
-
-
-#endif
+/*\r
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ *    in the file LICENSE.txt in the root directory. The license is also\r
+ *    available from the Open Source Initiative, see\r
+ *    http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is in the file\r
+ *    LICENSE2.txt in the root directory. The license is also available from\r
+ *    the Open Source Initiative, see\r
+ *    http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a \r
+ *    copy of which is in the file LICENSE3.txt in the root directory. The \r
+ *    license is also available from the Open Source Initiative, see\r
+ *    http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ *\r
+ * MODULE: dapl.h\r
+ *\r
+ * PURPOSE: defines common data structures for the DAPL reference implemenation\r
+ *\r
+ * Description: This file describes the working data structures used within\r
+ *              DAPL RI.\r
+ *\r
+ *\r
+ * $Id: dapl.h 1317 2005-04-25 17:29:42Z jlentini $\r
+ **********************************************************************/\r
+\r
+#ifndef _DAPL_H_\r
+#define _DAPL_H_\r
+\r
+#if defined(__KERNEL__)\r
+#include <dat2/kdat.h>\r
+#else\r
+#include <dat2/udat.h>\r
+#endif /* defined(__KERNEL__) */\r
+#include <dat2/dat_registry.h>\r
+#include "dapl_osd.h"\r
+#include "dapl_debug.h"\r
+\r
+\r
+\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Enumerations                                                      *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+\r
+typedef enum dapl_magic\r
+{\r
+    /* magic number values for verification & debug */\r
+    DAPL_MAGIC_IA      = 0xCafeF00d,\r
+    DAPL_MAGIC_EVD     = 0xFeedFace,\r
+    DAPL_MAGIC_EP      = 0xDeadBabe,\r
+    DAPL_MAGIC_LMR     = 0xBeefCafe,\r
+    DAPL_MAGIC_RMR      = 0xABadCafe,\r
+    DAPL_MAGIC_PZ      = 0xDeafBeef,\r
+    DAPL_MAGIC_PSP     = 0xBeadeD0c,\r
+    DAPL_MAGIC_RSP     = 0xFab4Feed,\r
+    DAPL_MAGIC_SRQ     = 0xC001Babe,\r
+    DAPL_MAGIC_CR      = 0xBe12Cee1,\r
+    DAPL_MAGIC_CR_DESTROYED = 0xB12bDead,\r
+    DAPL_MAGIC_CNO     = 0xDeadF00d,\r
+    DAPL_MAGIC_INVALID  = 0xFFFFFFFF\r
+} DAPL_MAGIC;\r
+\r
+typedef enum dapl_evd_state\r
+{\r
+    DAPL_EVD_STATE_TERMINAL,\r
+    DAPL_EVD_STATE_INITIAL,\r
+    DAPL_EVD_STATE_OPEN,\r
+    DAPL_EVD_STATE_WAITED,\r
+    DAPL_EVD_STATE_DEAD        = 0xDEAD\r
+} DAPL_EVD_STATE;\r
+\r
+typedef enum dapl_evd_completion\r
+{\r
+    DAPL_EVD_STATE_INIT,\r
+    DAPL_EVD_STATE_SOLICITED_WAIT,\r
+    DAPL_EVD_STATE_THRESHOLD,\r
+    DAPL_EVD_STATE_UNSIGNALLED\r
+} DAPL_EVD_COMPLETION;\r
+\r
+typedef enum dapl_cno_state\r
+{\r
+    DAPL_CNO_STATE_UNTRIGGERED,\r
+    DAPL_CNO_STATE_TRIGGERED,\r
+    DAPL_CNO_STATE_DEAD = 0xDeadFeed,\r
+} DAPL_CNO_STATE;\r
+\r
+typedef enum dapl_qp_state\r
+{\r
+    DAPL_QP_STATE_UNCONNECTED,\r
+    DAPL_QP_STATE_RESERVED,\r
+    DAPL_QP_STATE_PASSIVE_CONNECTION_PENDING,\r
+    DAPL_QP_STATE_ACTIVE_CONNECTION_PENDING,\r
+    DAPL_QP_STATE_TENTATIVE_CONNECTION_PENDING,\r
+    DAPL_QP_STATE_CONNECTED,\r
+    DAPL_QP_STATE_DISCONNECT_PENDING,\r
+    DAPL_QP_STATE_ERROR,\r
+    DAPL_QP_STATE_NOT_REUSABLE,\r
+    DAPL_QP_STATE_FREE\r
+} DAPL_QP_STATE;\r
+\r
+\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Constants                                                         *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+\r
+/*\r
+ * number of HCAs allowed\r
+ */\r
+#define DAPL_MAX_HCA_COUNT             4\r
+\r
+/*\r
+ * Configures the RMR bind evd restriction\r
+ */\r
+\r
+#define DAPL_RMR_BIND_EVD_RESTRICTION  DAT_RMR_EVD_SAME_AS_REQUEST_EVD\r
+\r
+/*\r
+ * special qp_state indicating the EP does not have a QP attached yet\r
+ */\r
+#define DAPL_QP_STATE_UNATTACHED       0xFFF0\r
+\r
+#define DAPL_MAX_PRIVATE_DATA_SIZE     256\r
+\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Macros                                                            *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+\r
+#if defined (sun) || defined(__sun) || defined(_sun_) || defined (__solaris__) \r
+#define DAPL_BAD_PTR(a) ((unsigned long)(a) & 3)\r
+#elif defined(__linux__)\r
+#define DAPL_BAD_PTR(a) ((unsigned long)(a) & 3)\r
+#elif defined(_WIN64)\r
+#define DAPL_BAD_PTR(a) ((unsigned long)((DAT_UINT64)(a)) & 3)\r
+#elif defined(_WIN32)\r
+#define DAPL_BAD_PTR(a) ((unsigned long)((DAT_UINT64)(a)) & 3)\r
+#endif\r
+\r
+/*\r
+ * Simple macro to verify a handle is bad. Conditions:\r
+ * - pointer is NULL\r
+ * - pointer is not word aligned\r
+ * - pointer's magic number is wrong\r
+ */\r
+\r
+#define DAPL_BAD_HANDLE(h, magicNum) (                         \\r
+           ((h) == NULL) ||                                    \\r
+           DAPL_BAD_PTR(h) ||                                  \\r
+           (((DAPL_HEADER *)(h))->magic != (magicNum)))\r
+\r
+#define DAPL_MIN(a, b)        ((a < b) ? (a) : (b))\r
+#define DAPL_MAX(a, b)        ((a > b) ? (a) : (b))\r
+\r
+#if NDEBUG > 0\r
+#define DEBUG_IS_BAD_HANDLE(h, magicNum) (DAPL_BAD_HANDLE(h, magicNum))\r
+#else\r
+#define DEBUG_IS_BAD_HANDLE(h, magicNum) (0)\r
+#endif\r
+\r
+#define DAT_ERROR(Type, SubType) ((DAT_RETURN)(DAT_CLASS_ERROR | Type | SubType))\r
+\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Typedefs                                                          *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+\r
+typedef struct dapl_llist_entry                DAPL_LLIST_ENTRY;\r
+typedef DAPL_LLIST_ENTRY *             DAPL_LLIST_HEAD;\r
+typedef struct dapl_ring_buffer                DAPL_RING_BUFFER;\r
+typedef struct dapl_cookie_buffer      DAPL_COOKIE_BUFFER;\r
+\r
+typedef struct dapl_hash_table          DAPL_HASH_TABLE;\r
+typedef struct dapl_hash_table *        DAPL_HASH_TABLEP;\r
+typedef DAT_UINT64                      DAPL_HASH_KEY;\r
+typedef void *                          DAPL_HASH_DATA;\r
+\r
+typedef struct dapl_hca                        DAPL_HCA;\r
+\r
+typedef struct dapl_header             DAPL_HEADER;\r
+\r
+typedef struct dapl_ia                 DAPL_IA;\r
+typedef struct dapl_cno                        DAPL_CNO;\r
+typedef struct dapl_evd                DAPL_EVD;\r
+typedef struct dapl_ep                         DAPL_EP;\r
+typedef struct dapl_srq                        DAPL_SRQ;\r
+typedef struct dapl_pz                 DAPL_PZ;\r
+typedef struct dapl_lmr                        DAPL_LMR;\r
+typedef struct dapl_rmr                        DAPL_RMR;\r
+typedef struct dapl_sp                 DAPL_SP;\r
+typedef struct dapl_cr                 DAPL_CR;\r
+\r
+typedef struct dapl_cookie             DAPL_COOKIE;\r
+typedef struct dapl_dto_cookie         DAPL_DTO_COOKIE;\r
+typedef struct dapl_rmr_cookie         DAPL_RMR_COOKIE;\r
+\r
+typedef struct dapl_private            DAPL_PRIVATE;\r
+\r
+\r
+\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Structures                                                        *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+\r
+struct dapl_llist_entry\r
+{\r
+    struct dapl_llist_entry    *flink;\r
+    struct dapl_llist_entry    *blink;\r
+    void                       *data;\r
+    DAPL_LLIST_HEAD            *list_head; /* for consistency checking */\r
+};\r
+\r
+struct dapl_ring_buffer\r
+{\r
+    void               **base;         /* base of element array */\r
+    DAT_COUNT          lim;            /* mask, number of entries - 1 */\r
+    DAPL_ATOMIC                head;           /* head pointer index */\r
+    DAPL_ATOMIC                tail;           /* tail pointer index */\r
+};\r
+\r
+struct dapl_cookie_buffer\r
+{\r
+    DAPL_COOKIE                *pool;\r
+    DAT_COUNT          pool_size;\r
+    DAPL_ATOMIC                head;\r
+    DAPL_ATOMIC                tail;\r
+};\r
+\r
+#ifdef IBAPI\r
+#include "dapl_ibapi_util.h"\r
+#elif VAPI\r
+#include "dapl_vapi_util.h"\r
+#elif __OPENIB__\r
+#include "dapl_openib_util.h"\r
+#include "dapl_openib_cm.h"\r
+#elif DUMMY\r
+#include "dapl_dummy_util.h"\r
+#elif OPENIB\r
+#include "dapl_ib_util.h"\r
+#else /* windows - IBAL and/or IBAL+Sock_CM */\r
+#include "dapl_ibal_util.h"\r
+#endif\r
+\r
+struct dapl_hca\r
+{\r
+    DAPL_OS_LOCK       lock;\r
+    DAPL_LLIST_HEAD    ia_list_head;      /* list of all open IAs */\r
+    DAPL_ATOMIC                handle_ref_count;  /* count of ia_opens on handle */\r
+    DAPL_EVD           *async_evd;\r
+    DAPL_EVD           *async_error_evd;\r
+    DAT_SOCK_ADDR6     hca_address;       /* local address of HCA*/\r
+    char               *name;             /* provider name */\r
+    ib_hca_handle_t    ib_hca_handle;\r
+    unsigned long       port_num;         /* physical port number */\r
+    ib_hca_transport_t  ib_trans;         /* Values specific transport API */\r
+    /* Memory Subsystem Support */\r
+    DAPL_HASH_TABLE    *lmr_hash_table;\r
+    /* Limits & useful HCA attributes */\r
+    DAT_IA_ATTR                ia_attr;\r
+};\r
+\r
+/* DAPL Objects always have the following header */\r
+struct dapl_header\r
+{\r
+    DAT_PROVIDER       *provider;      /* required by DAT - must be first */\r
+    DAPL_MAGIC         magic;          /* magic number for verification */\r
+    DAT_HANDLE_TYPE    handle_type;    /* struct type */\r
+    DAPL_IA            *owner_ia;      /* ia which owns this stuct */\r
+    DAPL_LLIST_ENTRY   ia_list_entry;  /* link entry on ia struct */\r
+    DAT_CONTEXT                user_context;   /* user context - opaque to DAPL */\r
+    DAPL_OS_LOCK       lock;           /* lock - in header for easier macros */\r
+};\r
+\r
+/* DAPL_IA maps to DAT_IA_HANDLE */\r
+struct dapl_ia\r
+{\r
+    DAPL_HEADER                header;\r
+    DAPL_HCA           *hca_ptr;\r
+    DAPL_EVD           *async_error_evd;\r
+    DAT_BOOLEAN                cleanup_async_error_evd;\r
+\r
+    DAPL_LLIST_ENTRY   hca_ia_list_entry;      /* HCAs list of IAs */\r
+    DAPL_LLIST_HEAD    ep_list_head;           /* EP queue */\r
+    DAPL_LLIST_HEAD    lmr_list_head;          /* LMR queue */\r
+    DAPL_LLIST_HEAD    rmr_list_head;          /* RMR queue */\r
+    DAPL_LLIST_HEAD    pz_list_head;           /* PZ queue */\r
+    DAPL_LLIST_HEAD    evd_list_head;          /* EVD queue */\r
+    DAPL_LLIST_HEAD    cno_list_head;          /* CNO queue */\r
+    DAPL_LLIST_HEAD    psp_list_head;          /* PSP queue */\r
+    DAPL_LLIST_HEAD    rsp_list_head;          /* RSP queue */\r
+    DAPL_LLIST_HEAD    srq_list_head;          /* SRQ queue */\r
+#ifdef DAPL_COUNTERS\r
+    void               *cntrs;\r
+#endif\r
+};\r
+\r
+/* DAPL_CNO maps to DAT_CNO_HANDLE */\r
+struct dapl_cno\r
+{\r
+    DAPL_HEADER        header;\r
+\r
+    /* A CNO cannot be freed while it is referenced elsewhere.  */\r
+    DAPL_ATOMIC                        cno_ref_count;\r
+    DAPL_CNO_STATE             cno_state;\r
+\r
+    DAT_COUNT                  cno_waiters;\r
+    DAPL_EVD                   *cno_evd_triggered;\r
+#if defined(__KERNEL__)\r
+    DAT_UPCALL_OBJECT          cno_upcall;\r
+    DAT_UPCALL_POLICY          cno_upcall_policy;\r
+#else\r
+    DAT_OS_WAIT_PROXY_AGENT    cno_wait_agent;\r
+#endif /* defined(__KERNEL__) */\r
+\r
+    DAPL_OS_WAIT_OBJECT                cno_wait_object;\r
+};\r
+\r
+/* DAPL_EVD maps to DAT_EVD_HANDLE */\r
+struct dapl_evd\r
+{\r
+    DAPL_HEADER                header;\r
+\r
+    DAPL_EVD_STATE     evd_state;\r
+    DAT_EVD_FLAGS      evd_flags;\r
+    DAT_BOOLEAN                evd_enabled; /* For attached CNO.  */\r
+    DAT_BOOLEAN                evd_waitable; /* EVD state.  */\r
+\r
+    /* Derived from evd_flags; see dapls_evd_internal_create.  */\r
+    DAT_BOOLEAN                evd_producer_locking_needed;\r
+\r
+    /* Every EVD has a CQ unless it is a SOFTWARE_EVENT only EVD */\r
+    ib_cq_handle_t     ib_cq_handle;\r
+\r
+    /* An Event Dispatcher cannot be freed while\r
+     * it is referenced elsewhere.\r
+     */\r
+    DAPL_ATOMIC                evd_ref_count;\r
+\r
+    /* Set if there has been a catastrophic overflow */\r
+    DAT_BOOLEAN                catastrophic_overflow;\r
+\r
+    /* the actual events */\r
+    DAT_COUNT          qlen;\r
+    DAT_EVENT          *events;\r
+    DAPL_RING_BUFFER   free_event_queue;\r
+    DAPL_RING_BUFFER   pending_event_queue;\r
+\r
+    /* CQ Completions are not placed into 'deferred_events'\r
+     ** rather they are simply left on the Completion Queue\r
+     ** and the fact that there was a notification is flagged.\r
+     */\r
+    DAT_BOOLEAN                cq_notified;\r
+    DAPL_OS_TICKS      cq_notified_when;\r
+\r
+    DAT_COUNT          cno_active_count;\r
+    DAPL_CNO           *cno_ptr;\r
+\r
+    DAPL_OS_WAIT_OBJECT        wait_object;\r
+\r
+    DAT_COUNT          threshold;\r
+    DAPL_EVD_COMPLETION        completion_type;\r
+\r
+#ifdef DAPL_COUNTERS\r
+    void               *cntrs;\r
+#endif\r
+};\r
+\r
+/* DAPL_PRIVATE used to pass private data in a connection */\r
+struct dapl_private\r
+{\r
+#ifdef IBHOSTS_NAMING\r
+    DAT_SOCK_ADDR6             hca_address;    /* local address of HCA*/\r
+#endif /* IBHOSTS_NAMING */\r
+    unsigned char              private_data[DAPL_MAX_PRIVATE_DATA_SIZE];\r
+};\r
+\r
+/* uDAPL timer entry, used to queue timeouts */\r
+struct dapl_timer_entry\r
+{\r
+    DAPL_LLIST_ENTRY           list_entry;     /* link entry on ia struct */\r
+    DAPL_OS_TIMEVAL            expires;\r
+    void                       (*function) (uintptr_t);\r
+    void                       *data;\r
+};\r
+\r
+#ifdef DAPL_DBG_IO_TRC\r
+\r
+#define DBG_IO_TRC_QLEN   32           /* length of trace buffer        */\r
+#define DBG_IO_TRC_IOV 3               /* iov elements we keep track of */\r
+\r
+struct io_buf_track\r
+{\r
+    Ib_send_op_type            op_type;\r
+    DAPL_COOKIE                        *cookie;\r
+    DAT_LMR_TRIPLET            iov[DBG_IO_TRC_IOV];\r
+    DAT_RMR_TRIPLET            remote_iov;\r
+    unsigned int               done;   /* count to track completion ordering */\r
+    int                                status;\r
+    void                       *wqe;\r
+};\r
+\r
+#endif /* DAPL_DBG_IO_TRC */\r
+\r
+/* DAPL_EP maps to DAT_EP_HANDLE */\r
+struct dapl_ep\r
+{\r
+    DAPL_HEADER                        header;\r
+    /* What the DAT Consumer asked for */\r
+    DAT_EP_PARAM               param;\r
+\r
+    /* The RC Queue Pair (IBM OS API) */\r
+    ib_qp_handle_t             qp_handle;\r
+    unsigned int               qpn;    /* qp number */\r
+    ib_qp_state_t              qp_state;\r
+\r
+    /* communications manager handle (IBM OS API) */\r
+   // dp_ib_cm_handle_t                cm_handle;\r
+\r
+    /* Add support for multiple CM object ownership */\r
+    DAPL_LLIST_HEAD            cm_list_head;   \r
+\r
+    /* store the remote IA address here, reference from the param\r
+     * struct which only has a pointer, no storage\r
+     */\r
+    DAT_SOCK_ADDR6             remote_ia_address;\r
+\r
+    /* For passive connections we maintain a back pointer to the CR */\r
+    void *                     cr_ptr;\r
+\r
+    /* pointer to connection timer, if set */\r
+    struct dapl_timer_entry    *cxn_timer;\r
+\r
+    /* private data container */\r
+    DAPL_PRIVATE               private;\r
+\r
+    /* DTO data */\r
+    DAPL_ATOMIC                        req_count;\r
+    DAPL_ATOMIC                        recv_count;\r
+\r
+    DAPL_COOKIE_BUFFER req_buffer;\r
+    DAPL_COOKIE_BUFFER recv_buffer;\r
+\r
+#ifdef DAPL_DBG_IO_TRC\r
+    int                        ibt_dumped;\r
+    struct io_buf_track *ibt_base;\r
+    DAPL_RING_BUFFER   ibt_queue;\r
+#endif /* DAPL_DBG_IO_TRC */\r
+#if defined(_WIN32) || defined(_WIN64)\r
+    DAT_BOOLEAN         recv_discreq;\r
+    DAT_BOOLEAN         sent_discreq;\r
+#endif\r
+#ifdef DAPL_COUNTERS\r
+    void               *cntrs;\r
+#endif\r
+};\r
+\r
+/* DAPL_SRQ maps to DAT_SRQ_HANDLE */\r
+struct dapl_srq\r
+{\r
+    DAPL_HEADER                header;\r
+    DAT_SRQ_PARAM      param;\r
+    DAPL_ATOMIC                srq_ref_count;\r
+    DAPL_COOKIE_BUFFER recv_buffer;\r
+    DAPL_ATOMIC                recv_count;\r
+};\r
+\r
+/* DAPL_PZ maps to DAT_PZ_HANDLE */\r
+struct dapl_pz\r
+{\r
+    DAPL_HEADER                header;\r
+    ib_pd_handle_t     pd_handle;\r
+    DAPL_ATOMIC                pz_ref_count;\r
+};\r
+\r
+/* DAPL_LMR maps to DAT_LMR_HANDLE */\r
+struct dapl_lmr\r
+{\r
+    DAPL_HEADER                header;\r
+    DAT_LMR_PARAM      param;\r
+    ib_mr_handle_t     mr_handle;\r
+    DAPL_ATOMIC                lmr_ref_count;\r
+#if !defined(__KDAPL__)\r
+    char               shmid[DAT_LMR_COOKIE_SIZE]; /* shared memory ID */\r
+    ib_shm_transport_t ib_trans;       /* provider specific data */\r
+#endif /* !__KDAPL__ */\r
+};\r
+\r
+/* DAPL_RMR maps to DAT_RMR_HANDLE */\r
+struct dapl_rmr\r
+{\r
+    DAPL_HEADER                header;\r
+    DAT_RMR_PARAM      param;\r
+    DAPL_EP             *ep;\r
+    DAPL_PZ             *pz;\r
+    DAPL_LMR            *lmr;\r
+    ib_mw_handle_t     mw_handle;\r
+};\r
+\r
+/* SP types, indicating the state and queue */\r
+typedef enum dapl_sp_state\r
+{\r
+    DAPL_SP_STATE_FREE,\r
+    DAPL_SP_STATE_PSP_LISTENING,\r
+    DAPL_SP_STATE_PSP_PENDING,\r
+    DAPL_SP_STATE_RSP_LISTENING,\r
+    DAPL_SP_STATE_RSP_PENDING\r
+} DAPL_SP_STATE;\r
+\r
+/* DAPL_SP maps to DAT_PSP_HANDLE and DAT_RSP_HANDLE */\r
+struct dapl_sp\r
+{\r
+    DAPL_HEADER                header;\r
+    DAPL_SP_STATE      state;          /* type and queue of the SP */\r
+\r
+    /* PSP/RSP PARAM fields */\r
+    DAT_CONN_QUAL       conn_qual;\r
+    DAT_EVD_HANDLE      evd_handle;\r
+    DAT_PSP_FLAGS       psp_flags;\r
+    DAT_EP_HANDLE       ep_handle;\r
+\r
+     /* maintenence fields */\r
+    DAT_BOOLEAN                listening;      /* PSP is registered & active */\r
+    ib_cm_srvc_handle_t        cm_srvc_handle; /* Used by Mellanox CM */\r
+    DAPL_LLIST_HEAD    cr_list_head;   /* CR pending queue */\r
+    DAT_COUNT          cr_list_count;  /* count of CRs on queue */\r
+#if defined(_VENDOR_IBAL_)\r
+    DAPL_OS_WAIT_OBJECT wait_object;    /* cancel & destroy. */\r
+#endif\r
+};\r
+\r
+/* DAPL_CR maps to DAT_CR_HANDLE */\r
+struct dapl_cr\r
+{\r
+    DAPL_HEADER                header;\r
+\r
+    /* for convenience the data is kept as a DAT_CR_PARAM.\r
+     * however, the "local_endpoint" field is always NULL\r
+     * so this wastes a pointer. This is probably ok to\r
+     * simplify code, espedially dat_cr_query.\r
+     */\r
+    DAT_CR_PARAM       param;\r
+    /* IB specific fields */\r
+    dp_ib_cm_handle_t  ib_cm_handle;\r
+\r
+    DAT_SOCK_ADDR6     remote_ia_address;\r
+    /* Assuming that the maximum private data size is small.\r
+     * If it gets large, use of a pointer may be appropriate.\r
+     */\r
+    unsigned char      private_data[DAPL_MAX_PRIVATE_DATA_SIZE];\r
+    /*\r
+     * Need to be able to associate the CR back to the PSP for\r
+     * dapl_cr_reject.\r
+     */\r
+    DAPL_SP            *sp_ptr;\r
+};\r
+\r
+typedef enum dapl_dto_type\r
+{\r
+    DAPL_DTO_TYPE_SEND,\r
+    DAPL_DTO_TYPE_RECV,\r
+    DAPL_DTO_TYPE_RDMA_WRITE,\r
+    DAPL_DTO_TYPE_RDMA_READ,\r
+#ifdef DAT_EXTENSIONS\r
+    DAPL_DTO_TYPE_EXTENSION,\r
+#endif\r
+} DAPL_DTO_TYPE;\r
+\r
+typedef enum dapl_cookie_type\r
+{\r
+    DAPL_COOKIE_TYPE_NULL,\r
+    DAPL_COOKIE_TYPE_DTO,\r
+    DAPL_COOKIE_TYPE_RMR,\r
+} DAPL_COOKIE_TYPE;\r
+\r
+/* DAPL_DTO_COOKIE used as context for DTO WQEs */\r
+struct dapl_dto_cookie\r
+{\r
+    DAPL_DTO_TYPE              type;\r
+    DAT_DTO_COOKIE             cookie;\r
+    DAT_COUNT                  size;   /* used for SEND and RDMA write */\r
+};\r
+\r
+/* DAPL_RMR_COOKIE used as context for bind WQEs */\r
+struct dapl_rmr_cookie\r
+{\r
+    DAPL_RMR                   *rmr;\r
+    DAT_RMR_COOKIE              cookie;\r
+};\r
+\r
+/* DAPL_COOKIE used as context for WQEs */\r
+struct dapl_cookie\r
+{\r
+    DAPL_COOKIE_TYPE           type; /* Must be first, to define struct.  */\r
+    DAPL_EP                    *ep;\r
+    DAT_COUNT                  index;\r
+    union\r
+    {\r
+       DAPL_DTO_COOKIE         dto;\r
+       DAPL_RMR_COOKIE         rmr;\r
+    } val;\r
+};\r
+\r
+/*\r
+ * Private Data operations. Used to obtain the size of the private\r
+ * data from the provider layer.\r
+ */\r
+typedef enum dapl_private_data_op\r
+{\r
+    DAPL_PDATA_CONN_REQ  = 0,          /* connect request    */\r
+    DAPL_PDATA_CONN_REP  = 1,          /* connect reply      */\r
+    DAPL_PDATA_CONN_REJ  = 2,          /* connect reject     */\r
+    DAPL_PDATA_CONN_DREQ = 3,          /* disconnect request */\r
+    DAPL_PDATA_CONN_DREP = 4,          /* disconnect reply   */\r
+} DAPL_PDATA_OP;\r
+\r
+\r
+/*\r
+ * Generic HCA name field\r
+ */\r
+#define DAPL_HCA_NAME_MAX_LEN 260\r
+typedef char DAPL_HCA_NAME[DAPL_HCA_NAME_MAX_LEN+1];\r
+\r
+#ifdef IBHOSTS_NAMING\r
+\r
+/*\r
+ * Simple mapping table to match IP addresses to GIDs. Loaded\r
+ * by dapl_init.\r
+ */\r
+typedef struct _dapl_gid_map_table\r
+{\r
+    uint32_t           ip_address;\r
+    ib_gid_t           gid;\r
+} DAPL_GID_MAP;\r
+\r
+#endif /* IBHOSTS_NAMING */\r
+\r
+/*\r
+ * IBTA defined reason for reject message: See IBTA 1.1 specification,\r
+ * 12.6.7.2 REJECTION REASON section.\r
+ */\r
+#define IB_CM_REJ_REASON_CONSUMER_REJ            0x001C\r
+\r
+\r
+#if defined(DAPL_DBG_IO_TRC)\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Debug I/O tracing support prototypes                              *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+/*\r
+ * I/O tracing support\r
+ */\r
+void dapls_io_trc_alloc (\r
+    DAPL_EP                    *ep_ptr);\r
+\r
+void dapls_io_trc_update_completion (\r
+    DAPL_EP                    *ep_ptr,\r
+    DAPL_COOKIE                        *cookie,\r
+    ib_uint32_t                        ib_status );\r
+\r
+void dapls_io_trc_dump (\r
+    DAPL_EP                    *ep_ptr,\r
+    ib_work_completion_t       *cqe_ptr,\r
+    ib_uint32_t                        ib_status);\r
+\r
+#else /* DAPL_DBG_IO_TRC */\r
+\r
+#define dapls_io_trc_alloc(a)\r
+#define dapls_io_trc_update_completion(a, b, c)\r
+#define dapls_io_trc_dump(a, b, c)\r
+\r
+#endif /* DAPL_DBG_IO_TRC */\r
+\r
+\r
+/*********************************************************************\r
+ *                                                                   *\r
+ * Function Prototypes                                               *\r
+ *                                                                   *\r
+ *********************************************************************/\r
+\r
+typedef void (*DAPL_CONNECTION_STATE_HANDLER) (\r
+       IN      DAPL_EP *,\r
+       IN      ib_cm_events_t,\r
+       IN      const void *,\r
+       OUT     DAT_EVENT *);\r
+\r
+/*\r
+ * DAT Mandated functions\r
+ */\r
+\r
+extern DAT_RETURN DAT_API dapl_ia_open (\r
+       IN      const DAT_NAME_PTR,     /* name */\r
+       IN      DAT_COUNT,              /* asynch_evd_qlen */\r
+       INOUT   DAT_EVD_HANDLE *,       /* asynch_evd_handle */\r
+       OUT     DAT_IA_HANDLE *);       /* ia_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_ia_close (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_CLOSE_FLAGS );      /* ia_flags */\r
+\r
+\r
+extern DAT_RETURN DAT_API dapl_ia_query (\r
+       IN      DAT_IA_HANDLE,          /* ia handle */\r
+       OUT     DAT_EVD_HANDLE *,       /* async_evd_handle */\r
+       IN      DAT_IA_ATTR_MASK,       /* ia_params_mask */\r
+       OUT     DAT_IA_ATTR *,          /* ia_params */\r
+       IN      DAT_PROVIDER_ATTR_MASK, /* provider_params_mask */\r
+       OUT     DAT_PROVIDER_ATTR * );  /* provider_params */\r
+\r
+\r
+/* helper functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_set_consumer_context (\r
+       IN      DAT_HANDLE,                     /* dat handle */\r
+       IN      DAT_CONTEXT);                   /* context */\r
+\r
+extern DAT_RETURN DAT_API dapl_get_consumer_context (\r
+       IN      DAT_HANDLE,                     /* dat handle */\r
+       OUT     DAT_CONTEXT * );                /* context */\r
+\r
+extern DAT_RETURN DAT_API dapl_get_handle_type (\r
+       IN      DAT_HANDLE,\r
+       OUT     DAT_HANDLE_TYPE * );\r
+\r
+/* CNO functions */\r
+\r
+#if !defined(__KERNEL__)\r
+extern DAT_RETURN DAT_API dapl_cno_create (\r
+       IN      DAT_IA_HANDLE,                  /* ia_handle */\r
+       IN      DAT_OS_WAIT_PROXY_AGENT,        /* agent */\r
+       OUT     DAT_CNO_HANDLE *);              /* cno_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_cno_modify_agent (\r
+       IN      DAT_CNO_HANDLE,                 /* cno_handle */\r
+       IN      DAT_OS_WAIT_PROXY_AGENT);       /* agent */\r
+\r
+extern DAT_RETURN DAT_API dapl_cno_query (\r
+       IN      DAT_CNO_HANDLE,         /* cno_handle */\r
+       IN      DAT_CNO_PARAM_MASK,     /* cno_param_mask */\r
+       OUT     DAT_CNO_PARAM * );      /* cno_param */\r
+\r
+extern DAT_RETURN DAT_API dapl_cno_free (\r
+       IN      DAT_CNO_HANDLE);        /* cno_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_cno_wait (\r
+       IN      DAT_CNO_HANDLE,         /* cno_handle */\r
+       IN      DAT_TIMEOUT,            /* timeout */\r
+       OUT     DAT_EVD_HANDLE *);      /* evd_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_cno_fd_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle            */\r
+       OUT     DAT_FD *,               /* file_descriptor      */\r
+       OUT     DAT_CNO_HANDLE *);      /* cno_handle           */\r
+\r
+extern DAT_RETURN DAT_API dapl_cno_trigger (\r
+       IN      DAT_CNO_HANDLE,         /* cno_handle */\r
+       OUT     DAT_EVD_HANDLE *);      /* evd_handle */\r
+\r
+#endif /* !defined(__KERNEL__) */\r
+\r
+/* CR Functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_cr_query (\r
+       IN      DAT_CR_HANDLE,          /* cr_handle */\r
+       IN      DAT_CR_PARAM_MASK,      /* cr_args_mask */\r
+       OUT     DAT_CR_PARAM * );       /* cwr_args */\r
+\r
+extern DAT_RETURN DAT_API dapl_cr_accept (\r
+       IN      DAT_CR_HANDLE,          /* cr_handle */\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_COUNT,              /* private_data_size */\r
+       IN      const DAT_PVOID );      /* private_data */\r
+\r
+extern DAT_RETURN DAT_API dapl_cr_reject (\r
+       IN      DAT_CR_HANDLE,          /* cr_handle            */\r
+       IN      DAT_COUNT,              /* private_data_size    */\r
+       IN      const DAT_PVOID );      /* private_data         */\r
+\r
+extern DAT_RETURN DAT_API dapl_cr_handoff (\r
+       IN DAT_CR_HANDLE,               /* cr_handle */\r
+       IN DAT_CONN_QUAL);              /* handoff */\r
+\r
+/* EVD Functions */\r
+\r
+#if defined(__KERNEL__)\r
+extern DAT_RETURN DAT_API dapl_ia_memtype_hint (\r
+       IN    DAT_IA_HANDLE,            /* ia_handle */\r
+       IN    DAT_MEM_TYPE,             /* mem_type */\r
+       IN    DAT_VLEN,                 /* length */\r
+       IN    DAT_MEM_OPT,              /* mem_optimization */\r
+       OUT   DAT_VLEN *,               /* suggested_length */\r
+       OUT   DAT_VADDR *);             /* suggested_alignment */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_kcreate (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_COUNT,              /* evd_min_qlen */\r
+       IN      DAT_UPCALL_POLICY,      /* upcall_policy */\r
+       IN      const DAT_UPCALL_OBJECT *, /* upcall */\r
+       IN      DAT_EVD_FLAGS,          /* evd_flags */\r
+       OUT     DAT_EVD_HANDLE * );     /* evd_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_kquery (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_EVD_PARAM_MASK,     /* evd_args_mask */\r
+       OUT     DAT_EVD_PARAM * );      /* evd_args */\r
+\r
+#else\r
+extern DAT_RETURN DAT_API dapl_evd_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_COUNT,              /* evd_min_qlen */\r
+       IN      DAT_CNO_HANDLE,         /* cno_handle */\r
+       IN      DAT_EVD_FLAGS,          /* evd_flags */\r
+       OUT     DAT_EVD_HANDLE * );     /* evd_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_query (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_EVD_PARAM_MASK,     /* evd_args_mask */\r
+       OUT     DAT_EVD_PARAM * );      /* evd_args */\r
+#endif /* defined(__KERNEL__) */\r
+\r
+#if defined(__KERNEL__)\r
+extern DAT_RETURN DAT_API dapl_evd_modify_upcall (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_UPCALL_POLICY,      /* upcall_policy */\r
+       IN      const DAT_UPCALL_OBJECT * ); /* upcall */\r
+\r
+#else\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_modify_cno (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_CNO_HANDLE);        /* cno_handle */\r
+#endif\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_enable (\r
+       IN      DAT_EVD_HANDLE);        /* evd_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_disable (\r
+       IN      DAT_EVD_HANDLE);        /* evd_handle */\r
+\r
+#if !defined(__KERNEL__)\r
+extern DAT_RETURN DAT_API dapl_evd_wait (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_TIMEOUT,            /* timeout */\r
+       IN      DAT_COUNT,              /* threshold */\r
+       OUT     DAT_EVENT *,            /* event */\r
+       OUT     DAT_COUNT *);           /* nmore */\r
+#endif /* !defined(__KERNEL__) */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_resize (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_COUNT );            /* evd_qlen */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_post_se (\r
+       DAT_EVD_HANDLE,                 /* evd_handle */\r
+       const DAT_EVENT * );            /* event */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_dequeue (\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       OUT     DAT_EVENT * );          /* event */\r
+\r
+extern DAT_RETURN DAT_API dapl_evd_free (\r
+       IN      DAT_EVD_HANDLE );\r
+\r
+extern DAT_RETURN DAT_API\r
+dapl_evd_set_unwaitable (\r
+       IN      DAT_EVD_HANDLE  evd_handle );\r
+\r
+extern DAT_RETURN DAT_API\r
+dapl_evd_clear_unwaitable (\r
+       IN      DAT_EVD_HANDLE  evd_handle );\r
+\r
+/* EP functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_PZ_HANDLE,          /* pz_handle */\r
+       IN      DAT_EVD_HANDLE,         /* in_dto_completion_evd_handle */\r
+       IN      DAT_EVD_HANDLE,         /* out_dto_completion_evd_handle */\r
+       IN      DAT_EVD_HANDLE,         /* connect_evd_handle */\r
+       IN      const DAT_EP_ATTR *,    /* ep_parameters */\r
+       OUT     DAT_EP_HANDLE * );      /* ep_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_query (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_EP_PARAM_MASK,      /* ep_args_mask */\r
+       OUT     DAT_EP_PARAM * );       /* ep_args */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_modify (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_EP_PARAM_MASK,      /* ep_args_mask */\r
+       IN      const DAT_EP_PARAM * ); /* ep_args */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_connect (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_IA_ADDRESS_PTR,     /* remote_ia_address */\r
+       IN      DAT_CONN_QUAL,          /* remote_conn_qual */\r
+       IN      DAT_TIMEOUT,            /* timeout */\r
+       IN      DAT_COUNT,              /* private_data_size */\r
+       IN      const DAT_PVOID,        /* private_data  */\r
+       IN      DAT_QOS,                /* quality_of_service */\r
+       IN      DAT_CONNECT_FLAGS );    /* connect_flags */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_common_connect (\r
+       IN      DAT_EP_HANDLE ep,               /* ep_handle            */\r
+       IN      DAT_IA_ADDRESS_PTR remote_addr, /* remote_ia_address    */\r
+       IN      DAT_TIMEOUT timeout,            /* timeout              */\r
+       IN      DAT_COUNT pdata_size,           /* private_data_size    */\r
+       IN      const DAT_PVOID pdata   );      /* private_data         */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_dup_connect (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_EP_HANDLE,          /* ep_dup_handle */\r
+       IN      DAT_TIMEOUT,            /* timeout*/\r
+       IN      DAT_COUNT,              /* private_data_size */\r
+       IN      const DAT_PVOID,        /* private_data */\r
+       IN      DAT_QOS);               /* quality_of_service */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_disconnect (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_CLOSE_FLAGS );      /* close_flags */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_post_send (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_COUNT,              /* num_segments */\r
+       IN      DAT_LMR_TRIPLET *,      /* local_iov */\r
+       IN      DAT_DTO_COOKIE,         /* user_cookie */\r
+       IN      DAT_COMPLETION_FLAGS ); /* completion_flags */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_post_recv (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_COUNT,              /* num_segments */\r
+       IN      DAT_LMR_TRIPLET *,      /* local_iov */\r
+       IN      DAT_DTO_COOKIE,         /* user_cookie */\r
+       IN      DAT_COMPLETION_FLAGS ); /* completion_flags */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_post_rdma_read (\r
+       IN      DAT_EP_HANDLE,           /* ep_handle */\r
+       IN      DAT_COUNT,               /* num_segments */\r
+       IN      DAT_LMR_TRIPLET *,       /* local_iov */\r
+       IN      DAT_DTO_COOKIE,          /* user_cookie */\r
+       IN      const DAT_RMR_TRIPLET *, /* remote_iov */\r
+       IN      DAT_COMPLETION_FLAGS );  /* completion_flags */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_post_rdma_read_to_rmr (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle            */\r
+       IN      const DAT_RMR_TRIPLET *,/* local_iov            */\r
+       IN      DAT_DTO_COOKIE,         /* user_cookie          */\r
+       IN      const DAT_RMR_TRIPLET *,/* remote_iov           */\r
+       IN      DAT_COMPLETION_FLAGS);  /* completion_flags     */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_post_rdma_write (\r
+       IN      DAT_EP_HANDLE,           /* ep_handle */\r
+       IN      DAT_COUNT,               /* num_segments */\r
+       IN      DAT_LMR_TRIPLET *,       /* local_iov */\r
+       IN      DAT_DTO_COOKIE,          /* user_cookie */\r
+       IN      const DAT_RMR_TRIPLET *, /* remote_iov */\r
+       IN      DAT_COMPLETION_FLAGS );  /* completion_flags */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_post_send_with_invalidate (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle            */\r
+       IN      DAT_COUNT,              /* num_segments         */\r
+       IN      DAT_LMR_TRIPLET *,      /* local_iov            */\r
+       IN      DAT_DTO_COOKIE,         /* user_cookie          */\r
+       IN      DAT_COMPLETION_FLAGS,   /* completion_flags     */\r
+       IN      DAT_BOOLEAN,            /* invalidate_flag      */\r
+       IN      DAT_RMR_CONTEXT);      /* RMR context          */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_get_status (\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       OUT     DAT_EP_STATE *,         /* ep_state */\r
+       OUT     DAT_BOOLEAN *,          /* in_dto_idle */\r
+       OUT     DAT_BOOLEAN * );        /* out_dto_idle */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_free (\r
+       IN      DAT_EP_HANDLE);         /* ep_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_reset (\r
+       IN      DAT_EP_HANDLE);         /* ep_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_create_with_srq (\r
+        IN      DAT_IA_HANDLE,          /* ia_handle            */\r
+        IN      DAT_PZ_HANDLE,          /* pz_handle            */\r
+        IN      DAT_EVD_HANDLE,         /* recv_evd_handle      */\r
+        IN      DAT_EVD_HANDLE,         /* request_evd_handle   */\r
+        IN      DAT_EVD_HANDLE,         /* connect_evd_handle   */\r
+        IN      DAT_SRQ_HANDLE,         /* srq_handle           */\r
+        IN      const DAT_EP_ATTR *,    /* ep_attributes        */\r
+        OUT     DAT_EP_HANDLE *);       /* ep_handle            */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_recv_query (\r
+        IN      DAT_EP_HANDLE,          /* ep_handle            */\r
+        OUT     DAT_COUNT *,            /* nbufs_allocated      */\r
+        OUT     DAT_COUNT *);           /* bufs_alloc_span      */\r
+\r
+extern DAT_RETURN DAT_API dapl_ep_set_watermark (\r
+        IN      DAT_EP_HANDLE,          /* ep_handle            */\r
+        IN      DAT_COUNT,              /* soft_high_watermark  */\r
+        IN      DAT_COUNT);             /* hard_high_watermark  */\r
+\r
+/* LMR functions */\r
+\r
+#if defined(__KERNEL__)\r
+extern DAT_RETURN DAT_API dapl_lmr_kcreate (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_MEM_TYPE,           /* mem_type */\r
+       IN      DAT_REGION_DESCRIPTION, /* region_description */\r
+       IN      DAT_VLEN,               /* length */\r
+       IN      DAT_PZ_HANDLE,          /* pz_handle */\r
+       IN      DAT_MEM_PRIV_FLAGS,     /* privileges */\r
+       IN      DAT_VA_TYPE,            /* va_type */\r
+       IN      DAT_MEM_OPT,            /* optimization */\r
+       OUT     DAT_LMR_HANDLE *,       /* lmr_handle */\r
+       OUT     DAT_LMR_CONTEXT *,      /* lmr_context */\r
+       OUT     DAT_RMR_CONTEXT *,      /* rmr_context          */\r
+       OUT     DAT_VLEN *,             /* registered_length */\r
+       OUT     DAT_VADDR * );          /* registered_address */\r
+#else\r
+extern DAT_RETURN DAT_API dapl_lmr_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_MEM_TYPE,           /* mem_type */\r
+       IN      DAT_REGION_DESCRIPTION, /* region_description */\r
+       IN      DAT_VLEN,               /* length */\r
+       IN      DAT_PZ_HANDLE,          /* pz_handle */\r
+       IN      DAT_MEM_PRIV_FLAGS,     /* privileges */\r
+       IN      DAT_VA_TYPE,            /* va_type */\r
+       OUT     DAT_LMR_HANDLE *,       /* lmr_handle */\r
+       OUT     DAT_LMR_CONTEXT *,      /* lmr_context */\r
+       OUT     DAT_RMR_CONTEXT *,      /* rmr_context          */\r
+       OUT     DAT_VLEN *,             /* registered_length */\r
+       OUT     DAT_VADDR * );          /* registered_address */\r
+#endif /* defined(__KERNEL__) */\r
+\r
+extern DAT_RETURN DAT_API dapl_lmr_query (\r
+       IN      DAT_LMR_HANDLE,\r
+       IN      DAT_LMR_PARAM_MASK,\r
+       OUT     DAT_LMR_PARAM *);\r
+\r
+extern DAT_RETURN DAT_API dapl_lmr_free (\r
+       IN      DAT_LMR_HANDLE);\r
+\r
+extern DAT_RETURN DAT_API dapl_lmr_sync_rdma_read (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle            */\r
+       IN      const DAT_LMR_TRIPLET *, /* local_segments      */\r
+       IN      DAT_VLEN);              /* num_segments         */\r
+\r
+extern DAT_RETURN DAT_API dapl_lmr_sync_rdma_write (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle            */\r
+       IN      const DAT_LMR_TRIPLET *, /* local_segments      */\r
+       IN      DAT_VLEN);              /* num_segments         */\r
+\r
+/* RMR Functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_rmr_create (\r
+       IN      DAT_PZ_HANDLE,          /* pz_handle */\r
+       OUT     DAT_RMR_HANDLE *);      /* rmr_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_rmr_create_for_ep (\r
+       IN      DAT_PZ_HANDLE pz_handle,        /* pz_handle    */\r
+       OUT     DAT_RMR_HANDLE *rmr_handle);    /* rmr_handle   */\r
+\r
+extern DAT_RETURN DAT_API dapl_rmr_query (\r
+       IN      DAT_RMR_HANDLE,         /* rmr_handle */\r
+       IN      DAT_RMR_PARAM_MASK,     /* rmr_args_mask */\r
+       OUT     DAT_RMR_PARAM *);       /* rmr_args */\r
+\r
+extern DAT_RETURN DAT_API dapl_rmr_bind (\r
+       IN      DAT_RMR_HANDLE,          /* rmr_handle */\r
+       IN      DAT_LMR_HANDLE,          /* lmr_handle */\r
+       IN      const DAT_LMR_TRIPLET *, /* lmr_triplet */\r
+       IN      DAT_MEM_PRIV_FLAGS,      /* mem_priv */\r
+       IN      DAT_VA_TYPE,             /* va_type */\r
+       IN      DAT_EP_HANDLE,           /* ep_handle */\r
+       IN      DAT_RMR_COOKIE,          /* user_cookie */\r
+       IN      DAT_COMPLETION_FLAGS,    /* completion_flags */\r
+       INOUT   DAT_RMR_CONTEXT * );     /* context */\r
+\r
+extern DAT_RETURN DAT_API dapl_rmr_free (\r
+       IN      DAT_RMR_HANDLE);\r
+\r
+/* PSP Functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_psp_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_CONN_QUAL,          /* conn_qual */\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_PSP_FLAGS,          /* psp_flags */\r
+       OUT     DAT_PSP_HANDLE * );     /* psp_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_psp_create_any (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       OUT     DAT_CONN_QUAL *,        /* conn_qual */\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       IN      DAT_PSP_FLAGS,          /* psp_flags */\r
+       OUT     DAT_PSP_HANDLE *);      /* psp_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_psp_query (\r
+       IN      DAT_PSP_HANDLE,\r
+       IN      DAT_PSP_PARAM_MASK,\r
+       OUT     DAT_PSP_PARAM * );\r
+\r
+extern DAT_RETURN DAT_API dapl_psp_free (\r
+       IN      DAT_PSP_HANDLE );       /* psp_handle */\r
+\r
+/* RSP Functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_rsp_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       IN      DAT_CONN_QUAL,          /* conn_qual */\r
+       IN      DAT_EP_HANDLE,          /* ep_handle */\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle */\r
+       OUT     DAT_RSP_HANDLE * );     /* rsp_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_rsp_query (\r
+       IN      DAT_RSP_HANDLE,\r
+       IN      DAT_RSP_PARAM_MASK,\r
+       OUT     DAT_RSP_PARAM * );\r
+\r
+extern DAT_RETURN DAT_API dapl_rsp_free (\r
+       IN      DAT_RSP_HANDLE );       /* rsp_handle */\r
+\r
+/* PZ Functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_pz_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle */\r
+       OUT     DAT_PZ_HANDLE * );      /* pz_handle */\r
+\r
+extern DAT_RETURN DAT_API dapl_pz_query (\r
+       IN      DAT_PZ_HANDLE,          /* pz_handle */\r
+       IN      DAT_PZ_PARAM_MASK,      /* pz_args_mask */\r
+       OUT     DAT_PZ_PARAM * );       /* pz_args */\r
+\r
+extern DAT_RETURN DAT_API dapl_pz_free (\r
+       IN      DAT_PZ_HANDLE );        /* pz_handle */\r
+\r
+/* SRQ functions */\r
+\r
+extern DAT_RETURN DAT_API dapl_srq_create (\r
+        IN      DAT_IA_HANDLE,          /* ia_handle            */\r
+        IN      DAT_PZ_HANDLE,          /* pz_handle            */\r
+        IN      DAT_SRQ_ATTR *,         /* srq_attr             */\r
+        OUT     DAT_SRQ_HANDLE *);      /* srq_handle           */\r
+\r
+extern DAT_RETURN DAT_API dapl_srq_free (\r
+       IN      DAT_SRQ_HANDLE);        /* srq_handle           */\r
+\r
+extern DAT_RETURN DAT_API dapl_srq_post_recv (\r
+       IN      DAT_SRQ_HANDLE,         /* srq_handle           */\r
+       IN      DAT_COUNT,              /* num_segments         */\r
+       IN      DAT_LMR_TRIPLET *,      /* local_iov            */\r
+       IN      DAT_DTO_COOKIE);        /* user_cookie          */\r
+\r
+extern DAT_RETURN DAT_API dapl_srq_query (\r
+       IN      DAT_SRQ_HANDLE,         /* srq_handle           */\r
+       IN      DAT_SRQ_PARAM_MASK,     /* srq_param_mask       */\r
+       OUT     DAT_SRQ_PARAM *);       /* srq_param            */\r
+\r
+extern DAT_RETURN DAT_API dapl_srq_resize (\r
+       IN      DAT_SRQ_HANDLE,         /* srq_handle           */\r
+       IN      DAT_COUNT);             /* srq_max_recv_dto     */\r
+\r
+extern DAT_RETURN DAT_API dapl_srq_set_lw (\r
+       IN      DAT_SRQ_HANDLE,         /* srq_handle           */\r
+       IN      DAT_COUNT);             /* low_watermark        */\r
+\r
+/* CSP functions */\r
+extern DAT_RETURN DAT_API dapl_csp_create (\r
+       IN      DAT_IA_HANDLE,          /* ia_handle      */\r
+       IN      DAT_COMM *,             /* communicator   */\r
+       IN      DAT_IA_ADDRESS_PTR,     /* address        */\r
+       IN      DAT_EVD_HANDLE,         /* evd_handle     */\r
+       OUT     DAT_CSP_HANDLE *);      /* csp_handle     */\r
+\r
+extern DAT_RETURN DAT_API dapl_csp_query (\r
+       IN      DAT_CSP_HANDLE,         /* csp_handle     */\r
+       IN      DAT_CSP_PARAM_MASK,     /* csp_param_mask */\r
+       OUT     DAT_CSP_PARAM *);       /* csp_param      */\r
+\r
+extern DAT_RETURN DAT_API dapl_csp_free (\r
+       IN      DAT_CSP_HANDLE);        /* csp_handle     */\r
+\r
+/* HA functions */\r
+DAT_RETURN DAT_API dapl_ia_ha (\r
+       IN       DAT_IA_HANDLE,         /* ia_handle */\r
+       IN const DAT_NAME_PTR,          /* provider  */\r
+       OUT      DAT_BOOLEAN *);        /* answer    */\r
+\r
+#ifdef DAT_EXTENSIONS\r
+#include <stdarg.h>\r
+extern DAT_RETURN DAT_API dapl_extensions (\r
+       IN      DAT_HANDLE,             /* handle */\r
+       IN      DAT_EXTENDED_OP,        /* extended op */\r
+       IN      va_list);               /* argument list */\r
+#endif\r
+\r
+/*\r
+ * DAPL internal utility function prototpyes\r
+ */\r
+\r
+extern void dapl_llist_init_head (\r
+    DAPL_LLIST_HEAD *  head);\r
+\r
+extern void dapl_llist_init_entry (\r
+    DAPL_LLIST_ENTRY *         entry);\r
+\r
+extern DAT_BOOLEAN dapl_llist_is_empty (\r
+    DAPL_LLIST_HEAD *  head);\r
+\r
+extern void dapl_llist_add_head (\r
+    DAPL_LLIST_HEAD *  head,\r
+    DAPL_LLIST_ENTRY *         entry,\r
+    void *             data);\r
+\r
+extern void dapl_llist_add_tail (\r
+    DAPL_LLIST_HEAD *   head,\r
+    DAPL_LLIST_ENTRY *  entry,\r
+    void *             data);\r
+\r
+extern void dapl_llist_add_entry (\r
+    DAPL_LLIST_HEAD * head,\r
+    DAPL_LLIST_ENTRY * entry,\r
+    DAPL_LLIST_ENTRY * new_entry,\r
+    void * data);\r
+\r
+extern void * dapl_llist_remove_head (\r
+    DAPL_LLIST_HEAD *  head);\r
+\r
+extern void * dapl_llist_remove_tail (\r
+    DAPL_LLIST_HEAD *  head);\r
+\r
+extern void * dapl_llist_remove_entry (\r
+    DAPL_LLIST_HEAD *  head,\r
+    DAPL_LLIST_ENTRY * entry);\r
+\r
+extern void * dapl_llist_peek_head (\r
+    DAPL_LLIST_HEAD *  head);\r
+\r
+extern void * dapl_llist_next_entry (\r
+    IN    DAPL_LLIST_HEAD      *head,\r
+    IN    DAPL_LLIST_ENTRY     *cur_ent);\r
+\r
+extern void dapl_llist_debug_print_list (\r
+    DAPL_LLIST_HEAD *  head);\r
+\r
+\r
+#endif\r
index bb35c458c2285676499da6507f96e585e6dfadd4..1e846aae4a17e5352c2ff8dd1e4843324caf6049 100644 (file)
-/*\r
- * Copyright (c) 2005 Voltaire Inc.  All rights reserved.\r
- * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.\r
- * Copyright (c) 2004-2005, Mellanox Technologies, Inc. All rights reserved. \r
- * Copyright (c) 2003 Topspin Corporation.  All rights reserved. \r
- * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- *\r
- * MODULE: dapl_ib_cm.c\r
- *\r
- * PURPOSE: The OFED provider - uCMA, name and route resolution\r
- *\r
- * $Id: $\r
- *\r
- **********************************************************************/\r
-\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_cr_util.h"\r
-#include "dapl_name_service.h"\r
-#include "dapl_ib_util.h"\r
-#include "dapl_vendor.h"\r
-#include "dapl_osd.h"\r
-\r
-extern struct rdma_event_channel *g_cm_events;\r
-\r
-/* local prototypes */\r
-static struct dapl_cm_id *dapli_req_recv(struct dapl_cm_id *conn,\r
-                                        struct rdma_cm_event *event);\r
-static void dapli_cm_active_cb(struct dapl_cm_id *conn,\r
-                              struct rdma_cm_event *event);\r
-static void dapli_cm_passive_cb(struct dapl_cm_id *conn,\r
-                               struct rdma_cm_event *event);\r
-static void dapli_addr_resolve(struct dapl_cm_id *conn);\r
-static void dapli_route_resolve(struct dapl_cm_id *conn);\r
-\r
-/* cma requires 16 bit SID, in network order */\r
-#define IB_PORT_MOD 32001\r
-#define IB_PORT_BASE (65535 - IB_PORT_MOD)\r
-#define SID_TO_PORT(SID) \\r
-    (SID > 0xffff ? \\r
-    htons((unsigned short)((SID % IB_PORT_MOD) + IB_PORT_BASE)) :\\r
-    htons((unsigned short)SID))\r
-\r
-#define PORT_TO_SID(p) ntohs(p)\r
-\r
-/* private data header to validate consumer rejects versus abnormal events */\r
-struct dapl_pdata_hdr {\r
-       DAT_UINT32 version;\r
-};\r
-\r
-static void dapli_addr_resolve(struct dapl_cm_id *conn)\r
-{\r
-       int ret;\r
-#ifdef DAPL_DBG\r
-       struct rdma_addr *ipaddr = &conn->cm_id->route.addr;\r
-#endif\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " addr_resolve: cm_id %p SRC %x DST %x\n",\r
-                    conn->cm_id, ntohl(((struct sockaddr_in *)\r
-                                        &ipaddr->src_addr)->sin_addr.s_addr),\r
-                    ntohl(((struct sockaddr_in *)\r
-                           &ipaddr->dst_addr)->sin_addr.s_addr));\r
-\r
-       ret = rdma_resolve_route(conn->cm_id, conn->route_timeout);\r
-       if (ret) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " dapl_cma_connect: rdma_resolve_route ERR 0x%x %s\n",\r
-                        ret, strerror(errno));\r
-               dapl_evd_connection_callback(conn,\r
-                                            IB_CME_LOCAL_FAILURE,\r
-                                            NULL, 0, conn->ep);\r
-       }\r
-}\r
-\r
-static void dapli_route_resolve(struct dapl_cm_id *conn)\r
-{\r
-       int ret;\r
-#ifdef DAPL_DBG\r
-       struct rdma_addr *ipaddr = &conn->cm_id->route.addr;\r
-       struct ib_addr *ibaddr = &conn->cm_id->route.addr.addr.ibaddr;\r
-#endif\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " route_resolve: cm_id %p SRC %x DST %x PORT %d\n",\r
-                    conn->cm_id, ntohl(((struct sockaddr_in *)\r
-                                        &ipaddr->src_addr)->sin_addr.s_addr),\r
-                    ntohl(((struct sockaddr_in *)\r
-                           &ipaddr->dst_addr)->sin_addr.s_addr),\r
-                    ntohs(((struct sockaddr_in *)\r
-                           &ipaddr->dst_addr)->sin_port));\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " route_resolve: SRC GID subnet %016llx id %016llx\n",\r
-                    (unsigned long long)\r
-                    ntohll(ibaddr->sgid.global.subnet_prefix),\r
-                    (unsigned long long)\r
-                    ntohll(ibaddr->sgid.global.interface_id));\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " route_resolve: DST GID subnet %016llx id %016llx\n",\r
-                    (unsigned long long)\r
-                    ntohll(ibaddr->dgid.global.subnet_prefix),\r
-                    (unsigned long long)\r
-                    ntohll(ibaddr->dgid.global.interface_id));\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " route_resolve: cm_id %p pdata %p plen %d rr %d ind %d\n",\r
-                    conn->cm_id,\r
-                    conn->params.private_data,\r
-                    conn->params.private_data_len,\r
-                    conn->params.responder_resources,\r
-                    conn->params.initiator_depth);\r
-\r
-       ret = rdma_connect(conn->cm_id, &conn->params);\r
-       if (ret) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " dapl_cma_connect: rdma_connect ERR %d %s\n",\r
-                        ret, strerror(errno));\r
-               goto bail;\r
-       }\r
-       return;\r
-\r
-      bail:\r
-       dapl_evd_connection_callback(conn,\r
-                                    IB_CME_LOCAL_FAILURE, NULL, 0, conn->ep);\r
-}\r
-\r
-dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep)\r
-{\r
-       dp_ib_cm_handle_t conn;\r
-       struct rdma_cm_id *cm_id;\r
-\r
-       /* Allocate CM and initialize lock */\r
-       if ((conn = dapl_os_alloc(sizeof(*conn))) == NULL)\r
-               return NULL;\r
-\r
-       dapl_os_memzero(conn, sizeof(*conn));\r
-       dapl_os_lock_init(&conn->lock);\r
-       conn->refs++;\r
-\r
-       /* create CM_ID, bind to local device, create QP */\r
-       if (rdma_create_id(g_cm_events, &cm_id, (void *)conn, RDMA_PS_TCP)) {\r
-               dapl_os_lock_destroy(&conn->lock);\r
-               dapl_os_free(conn, sizeof(*conn));\r
-               return NULL;\r
-       }\r
-       conn->cm_id = cm_id;\r
-\r
-       /* setup timers for address and route resolution */\r
-       conn->arp_timeout = dapl_os_get_env_val("DAPL_CM_ARP_TIMEOUT_MS",\r
-                                               IB_ARP_TIMEOUT);\r
-       conn->arp_retries = dapl_os_get_env_val("DAPL_CM_ARP_RETRY_COUNT",\r
-                                               IB_ARP_RETRY_COUNT);\r
-       conn->route_timeout = dapl_os_get_env_val("DAPL_CM_ROUTE_TIMEOUT_MS",\r
-                                                 IB_ROUTE_TIMEOUT);\r
-       conn->route_retries = dapl_os_get_env_val("DAPL_CM_ROUTE_RETRY_COUNT",\r
-                                                 IB_ROUTE_RETRY_COUNT);\r
-       if (ep != NULL) {\r
-               conn->ep = ep;\r
-               conn->hca = ((DAPL_IA *)ep->param.ia_handle)->hca_ptr;\r
-       }\r
-\r
-       return conn;\r
-}\r
-\r
-/* \r
- * Only called from consumer thread via dat_ep_free()\r
- * accept, reject, or connect.\r
- * Cannot be called from callback thread.\r
- * rdma_destroy_id will block until rdma_get_cm_event is acked.\r
- */\r
-void dapls_ib_cm_free(dp_ib_cm_handle_t conn, DAPL_EP *ep)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " destroy_conn: conn %p id %d\n", \r
-                    conn, conn->cm_id);\r
-\r
-       dapl_os_lock(&conn->lock);\r
-       conn->refs--;\r
-       dapl_os_unlock(&conn->lock);\r
-\r
-       /* block until event thread complete */\r
-       while (conn->refs) \r
-               dapl_os_sleep_usec(10000);\r
-       \r
-       if (ep) {\r
-               ep->cm_handle = NULL;\r
-               ep->qp_handle = NULL;\r
-               ep->qp_state = IB_QP_STATE_ERROR;\r
-       }\r
-\r
-       if (conn->cm_id) {\r
-               if (conn->cm_id->qp)\r
-                       rdma_destroy_qp(conn->cm_id);\r
-               rdma_destroy_id(conn->cm_id);\r
-       }\r
-\r
-       dapl_os_lock_destroy(&conn->lock);\r
-       dapl_os_free(conn, sizeof(*conn));\r
-}\r
-\r
-static struct dapl_cm_id *dapli_req_recv(struct dapl_cm_id *conn,\r
-                                        struct rdma_cm_event *event)\r
-{\r
-       struct dapl_cm_id *new_conn;\r
-#ifdef DAPL_DBG\r
-       struct rdma_addr *ipaddr = &event->id->route.addr;\r
-#endif\r
-\r
-       if (conn->sp == NULL) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
-                            " dapli_rep_recv: on invalid listen " "handle\n");\r
-               return NULL;\r
-       }\r
-\r
-       /* allocate new cm_id and merge listen parameters */\r
-       new_conn = dapl_os_alloc(sizeof(*new_conn));\r
-       if (new_conn) {\r
-               (void)dapl_os_memzero(new_conn, sizeof(*new_conn));\r
-               dapl_os_lock_init(&new_conn->lock);\r
-               new_conn->cm_id = event->id;    /* provided by uCMA */\r
-               event->id->context = new_conn;  /* update CM_ID context */\r
-               new_conn->sp = conn->sp;\r
-               new_conn->hca = conn->hca;\r
-               new_conn->refs++;\r
-\r
-               /* Get requesters connect data, setup for accept */\r
-               new_conn->params.responder_resources =\r
-                   DAPL_MIN(event->param.conn.responder_resources,\r
-                            conn->hca->ib_trans.rd_atom_in);\r
-               new_conn->params.initiator_depth =\r
-                   DAPL_MIN(event->param.conn.initiator_depth,\r
-                            conn->hca->ib_trans.rd_atom_out);\r
-\r
-               new_conn->params.flow_control = event->param.conn.flow_control;\r
-               new_conn->params.rnr_retry_count =\r
-                   event->param.conn.rnr_retry_count;\r
-               new_conn->params.retry_count = event->param.conn.retry_count;\r
-\r
-               /* save private data */\r
-               if (event->param.conn.private_data_len) {\r
-                       dapl_os_memcpy(new_conn->p_data,\r
-                                      event->param.conn.private_data,\r
-                                      event->param.conn.private_data_len);\r
-                       new_conn->params.private_data = new_conn->p_data;\r
-                       new_conn->params.private_data_len =\r
-                           event->param.conn.private_data_len;\r
-               }\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM, " passive_cb: "\r
-                            "REQ: SP %p PORT %d LID %d "\r
-                            "NEW CONN %p ID %p pdata %p,%d\n",\r
-                            new_conn->sp, ntohs(((struct sockaddr_in *)\r
-                                                 &ipaddr->src_addr)->sin_port),\r
-                            event->listen_id, new_conn, event->id,\r
-                            event->param.conn.private_data,\r
-                            event->param.conn.private_data_len);\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM, " passive_cb: "\r
-                            "REQ: IP SRC %x PORT %d DST %x PORT %d "\r
-                            "rr %d init %d\n", ntohl(((struct sockaddr_in *)\r
-                                                      &ipaddr->src_addr)->\r
-                                                     sin_addr.s_addr),\r
-                            ntohs(((struct sockaddr_in *)\r
-                                   &ipaddr->src_addr)->sin_port),\r
-                            ntohl(((struct sockaddr_in *)\r
-                                   &ipaddr->dst_addr)->sin_addr.s_addr),\r
-                            ntohs(((struct sockaddr_in *)\r
-                                   &ipaddr->dst_addr)->sin_port),\r
-                            new_conn->params.responder_resources,\r
-                            new_conn->params.initiator_depth);\r
-       }\r
-       return new_conn;\r
-}\r
-\r
-static void dapli_cm_active_cb(struct dapl_cm_id *conn,\r
-                              struct rdma_cm_event *event)\r
-{\r
-       DAPL_OS_LOCK *lock = &conn->lock;\r
-       ib_cm_events_t ib_cm_event;\r
-       const void *pdata = NULL;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " active_cb: conn %p id %d event %d\n",\r
-                    conn, conn->cm_id, event->event);\r
-\r
-       /* There is a chance that we can get events after\r
-        * the consumer calls disconnect in a pending state\r
-        * since the IB CM and uDAPL states are not shared.\r
-        * In some cases, IB CM could generate either a DCONN\r
-        * or CONN_ERR after the consumer returned from\r
-        * dapl_ep_disconnect with a DISCONNECTED event\r
-        * already queued. Check state here and bail to\r
-        * avoid any events after a disconnect.\r
-        */\r
-       if (DAPL_BAD_HANDLE(conn->ep, DAPL_MAGIC_EP))\r
+/*
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.
+ * Copyright (c) 2004-2005, Mellanox Technologies, Inc. All rights reserved. 
+ * Copyright (c) 2003 Topspin Corporation.  All rights reserved. 
+ * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ *
+ * MODULE: dapl_ib_cm.c
+ *
+ * PURPOSE: The OFED provider - uCMA, name and route resolution
+ *
+ * $Id: $
+ *
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_cr_util.h"
+#include "dapl_name_service.h"
+#include "dapl_ib_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_vendor.h"
+#include "dapl_osd.h"
+
+extern struct rdma_event_channel *g_cm_events;
+
+/* local prototypes */
+static struct dapl_cm_id *dapli_req_recv(struct dapl_cm_id *conn,
+                                        struct rdma_cm_event *event);
+static void dapli_cm_active_cb(struct dapl_cm_id *conn,
+                              struct rdma_cm_event *event);
+static void dapli_cm_passive_cb(struct dapl_cm_id *conn,
+                               struct rdma_cm_event *event);
+static void dapli_addr_resolve(struct dapl_cm_id *conn);
+static void dapli_route_resolve(struct dapl_cm_id *conn);
+
+/* cma requires 16 bit SID, in network order */
+#define IB_PORT_MOD 32001
+#define IB_PORT_BASE (65535 - IB_PORT_MOD)
+#define SID_TO_PORT(SID) \
+    (SID > 0xffff ? \
+    htons((unsigned short)((SID % IB_PORT_MOD) + IB_PORT_BASE)) :\
+    htons((unsigned short)SID))
+
+#define PORT_TO_SID(p) ntohs(p)
+
+/* private data header to validate consumer rejects versus abnormal events */
+struct dapl_pdata_hdr {
+       DAT_UINT32 version;
+};
+
+static void dapli_addr_resolve(struct dapl_cm_id *conn)
+{
+       int ret;
+#ifdef DAPL_DBG
+       struct rdma_addr *ipaddr = &conn->cm_id->route.addr;
+#endif
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " addr_resolve: cm_id %p SRC %x DST %x\n",
+                    conn->cm_id, ntohl(((struct sockaddr_in *)
+                                        &ipaddr->src_addr)->sin_addr.s_addr),
+                    ntohl(((struct sockaddr_in *)
+                           &ipaddr->dst_addr)->sin_addr.s_addr));
+
+       ret = rdma_resolve_route(conn->cm_id, conn->route_timeout);
+       if (ret) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " dapl_cma_connect: rdma_resolve_route ERR 0x%x %s\n",
+                        ret, strerror(errno));
+               dapl_evd_connection_callback(conn,
+                                            IB_CME_LOCAL_FAILURE,
+                                            NULL, 0, conn->ep);
+       }
+}
+
+static void dapli_route_resolve(struct dapl_cm_id *conn)
+{
+       int ret;
+#ifdef DAPL_DBG
+       struct rdma_addr *ipaddr = &conn->cm_id->route.addr;
+       struct ib_addr *ibaddr = &conn->cm_id->route.addr.addr.ibaddr;
+#endif
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " route_resolve: cm_id %p SRC %x DST %x PORT %d\n",
+                    conn->cm_id, ntohl(((struct sockaddr_in *)
+                                        &ipaddr->src_addr)->sin_addr.s_addr),
+                    ntohl(((struct sockaddr_in *)
+                           &ipaddr->dst_addr)->sin_addr.s_addr),
+                    ntohs(((struct sockaddr_in *)
+                           &ipaddr->dst_addr)->sin_port));
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " route_resolve: SRC GID subnet %016llx id %016llx\n",
+                    (unsigned long long)
+                    ntohll(ibaddr->sgid.global.subnet_prefix),
+                    (unsigned long long)
+                    ntohll(ibaddr->sgid.global.interface_id));
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " route_resolve: DST GID subnet %016llx id %016llx\n",
+                    (unsigned long long)
+                    ntohll(ibaddr->dgid.global.subnet_prefix),
+                    (unsigned long long)
+                    ntohll(ibaddr->dgid.global.interface_id));
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " route_resolve: cm_id %p pdata %p plen %d rr %d ind %d\n",
+                    conn->cm_id,
+                    conn->params.private_data,
+                    conn->params.private_data_len,
+                    conn->params.responder_resources,
+                    conn->params.initiator_depth);
+
+       ret = rdma_connect(conn->cm_id, &conn->params);
+       if (ret) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " dapl_cma_connect: rdma_connect ERR %d %s\n",
+                        ret, strerror(errno));
+               goto bail;
+       }
+       return;
+
+      bail:
+       dapl_evd_connection_callback(conn,
+                                    IB_CME_LOCAL_FAILURE, NULL, 0, conn->ep);
+}
+
+dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep)
+{
+       dp_ib_cm_handle_t conn;
+       struct rdma_cm_id *cm_id;
+
+       /* Allocate CM and initialize lock */
+       if ((conn = dapl_os_alloc(sizeof(*conn))) == NULL)
+               return NULL;
+
+       dapl_os_memzero(conn, sizeof(*conn));
+       dapl_os_lock_init(&conn->lock);
+       dapls_cm_acquire(conn);
+
+       /* create CM_ID, bind to local device, create QP */
+       if (rdma_create_id(g_cm_events, &cm_id, (void *)conn, RDMA_PS_TCP)) {
+               dapls_cm_release(conn);
+               return NULL;
+       }
+
+       conn->cm_id = cm_id;
+
+       /* setup timers for address and route resolution */
+       conn->arp_timeout = dapl_os_get_env_val("DAPL_CM_ARP_TIMEOUT_MS",
+                                               IB_ARP_TIMEOUT);
+       conn->arp_retries = dapl_os_get_env_val("DAPL_CM_ARP_RETRY_COUNT",
+                                               IB_ARP_RETRY_COUNT);
+       conn->route_timeout = dapl_os_get_env_val("DAPL_CM_ROUTE_TIMEOUT_MS",
+                                                 IB_ROUTE_TIMEOUT);
+       conn->route_retries = dapl_os_get_env_val("DAPL_CM_ROUTE_RETRY_COUNT",
+                                                 IB_ROUTE_RETRY_COUNT);
+       if (ep != NULL) {
+               dapl_ep_link_cm(ep, conn);
+               conn->ep = ep;
+               conn->hca = ((DAPL_IA *)ep->param.ia_handle)->hca_ptr;
+       }
+
+       return conn;
+}
+
+static void dapli_cm_dealloc(dp_ib_cm_handle_t conn) {
+
+       dapl_os_assert(!conn->ref_count);
+       dapl_os_lock_destroy(&conn->lock);
+       dapl_os_free(conn, sizeof(*conn));
+}
+
+void dapls_cm_acquire(dp_ib_cm_handle_t conn)
+{
+       dapl_os_lock(&conn->lock);
+       conn->ref_count++;
+       dapl_os_unlock(&conn->lock);
+}
+
+void dapls_cm_release(dp_ib_cm_handle_t conn)
+{
+       dapl_os_lock(&conn->lock);
+       conn->ref_count--;\r
+       if (conn->ref_count) {\r
+                dapl_os_unlock(&conn->lock);\r
                return;\r
-\r
-       dapl_os_lock(&conn->ep->header.lock);\r
-       if (conn->ep->param.ep_state == DAT_EP_STATE_DISCONNECTED) {\r
-               dapl_os_unlock(&conn->ep->header.lock);\r
-               return;\r
-       }\r
-       if (event->event == RDMA_CM_EVENT_DISCONNECTED)\r
-               conn->ep->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-\r
-       dapl_os_unlock(&conn->ep->header.lock);\r
-       dapl_os_lock(lock);\r
-\r
-       switch (event->event) {\r
-       case RDMA_CM_EVENT_UNREACHABLE:\r
-       case RDMA_CM_EVENT_CONNECT_ERROR:\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                        "dapl_cma_active: CONN_ERR event=0x%x"\r
-                        " status=%d %s DST %s, %d\n",\r
-                        event->event, event->status,\r
-                        (event->status == -ETIMEDOUT) ? "TIMEOUT" : "",\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &conn->cm_id->route.addr.dst_addr)->\r
-                                  sin_addr),\r
-                        ntohs(((struct sockaddr_in *)\r
-                               &conn->cm_id->route.addr.dst_addr)->\r
-                              sin_port));\r
-\r
-               /* per DAT SPEC provider always returns UNREACHABLE */\r
-               ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;\r
-               break;\r
-       case RDMA_CM_EVENT_REJECTED:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " dapli_cm_active_handler: REJECTED reason=%d\n",\r
-                            event->status);\r
-\r
-               /* valid REJ from consumer will always contain private data */\r
-               if (event->status == 28 &&\r
-                   event->param.conn.private_data_len) {\r
-                       ib_cm_event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;\r
-                       pdata =\r
-                           (unsigned char *)event->param.conn.\r
-                           private_data +\r
-                           sizeof(struct dapl_pdata_hdr);\r
-               } else {\r
-                       ib_cm_event = IB_CME_DESTINATION_REJECT;\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                "dapl_cma_active: non-consumer REJ,"\r
-                                " reason=%d, DST %s, %d\n",\r
-                                event->status,\r
-                                inet_ntoa(((struct sockaddr_in *)\r
-                                           &conn->cm_id->route.addr.\r
-                                           dst_addr)->sin_addr),\r
-                                ntohs(((struct sockaddr_in *)\r
-                                       &conn->cm_id->route.addr.\r
-                                       dst_addr)->sin_port));\r
-               }\r
-               break;\r
-       case RDMA_CM_EVENT_ESTABLISHED:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " active_cb: cm_id %d PORT %d CONNECTED to %s!\n",\r
-                            conn->cm_id, ntohs(((struct sockaddr_in *)\r
-                                                &conn->cm_id->route.addr.\r
-                                                dst_addr)->sin_port),\r
-                            inet_ntoa(((struct sockaddr_in *)\r
-                                       &conn->cm_id->route.addr.dst_addr)->\r
-                                      sin_addr));\r
-\r
-               /* setup local and remote ports for ep query */\r
-               conn->ep->param.remote_port_qual =\r
-                   PORT_TO_SID(rdma_get_dst_port(conn->cm_id));\r
-               conn->ep->param.local_port_qual =\r
-                   PORT_TO_SID(rdma_get_src_port(conn->cm_id));\r
-\r
-               ib_cm_event = IB_CME_CONNECTED;\r
-               pdata = event->param.conn.private_data;\r
-               break;\r
-       case RDMA_CM_EVENT_DISCONNECTED:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " active_cb: DISC EVENT - EP %p\n",conn->ep);\r
-               rdma_disconnect(conn->cm_id);   /* required for DREP */\r
-               ib_cm_event = IB_CME_DISCONNECTED;\r
-               /* validate EP handle */\r
-               if (DAPL_BAD_HANDLE(conn->ep, DAPL_MAGIC_EP))\r
-                       conn = NULL;\r
-               break;\r
-       default:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
-                            " dapli_cm_active_cb_handler: Unexpected CM "\r
-                            "event %d on ID 0x%p\n", event->event,\r
-                            conn->cm_id);\r
-               conn = NULL;\r
-               break;\r
        }\r
-\r
-       dapl_os_unlock(lock);\r
-       if (conn)\r
-               dapl_evd_connection_callback(conn, ib_cm_event, pdata,\r
-                                            event->param.conn.private_data_len, conn->ep);\r
-}\r
-\r
-static void dapli_cm_passive_cb(struct dapl_cm_id *conn,\r
-                               struct rdma_cm_event *event)\r
-{\r
-       ib_cm_events_t ib_cm_event;\r
-       struct dapl_cm_id *conn_recv = conn;\r
-       const void *pdata = NULL;\r
-       \r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " passive_cb: conn %p id %d event %d\n",\r
-                    conn, event->id, event->event);\r
-\r
-       dapl_os_lock(&conn->lock);\r
-\r
-       switch (event->event) {\r
-       case RDMA_CM_EVENT_CONNECT_REQUEST:\r
-               /* create new conn object with new conn_id from event */\r
-               conn_recv = dapli_req_recv(conn, event);\r
-               ib_cm_event = IB_CME_CONNECTION_REQUEST_PENDING;\r
-               pdata = event->param.conn.private_data;\r
-               break;\r
-       case RDMA_CM_EVENT_UNREACHABLE:\r
-       case RDMA_CM_EVENT_CONNECT_ERROR:\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                        "dapl_cm_passive: CONN_ERR event=0x%x status=%d %s,"\r
-                        " DST %s,%d\n",\r
-                        event->event, event->status,\r
-                        (event->status == -ETIMEDOUT) ? "TIMEOUT" : "",\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &conn->cm_id->route.addr.dst_addr)->\r
-                                  sin_addr), ntohs(((struct sockaddr_in *)\r
-                                                    &conn->cm_id->route.addr.\r
-                                                    dst_addr)->sin_port));\r
-               ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;\r
-               break;\r
-       case RDMA_CM_EVENT_REJECTED:\r
-               /* will alwasys be abnormal NON-consumer from active side */\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                        "dapl_cm_passive: non-consumer REJ, reason=%d,"\r
-                        " DST %s, %d\n",\r
-                        event->status,\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &conn->cm_id->route.addr.dst_addr)->\r
-                                  sin_addr),\r
-                        ntohs(((struct sockaddr_in *)\r
-                               &conn->cm_id->route.addr.dst_addr)->\r
-                              sin_port));\r
-               ib_cm_event = IB_CME_DESTINATION_REJECT;\r
-               break;\r
-       case RDMA_CM_EVENT_ESTABLISHED:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " passive_cb: cm_id %p PORT %d CONNECTED from 0x%x!\n",\r
-                            conn->cm_id, ntohs(((struct sockaddr_in *)\r
-                                                &conn->cm_id->route.addr.\r
-                                                src_addr)->sin_port),\r
-                            ntohl(((struct sockaddr_in *)\r
-                                   &conn->cm_id->route.addr.dst_addr)->\r
-                                  sin_addr.s_addr));\r
-               ib_cm_event = IB_CME_CONNECTED;\r
-               break;\r
-       case RDMA_CM_EVENT_DISCONNECTED:\r
-               rdma_disconnect(conn->cm_id);   /* required for DREP */\r
-               ib_cm_event = IB_CME_DISCONNECTED;\r
-               /* validate SP handle context */\r
-               if (DAPL_BAD_HANDLE(conn->sp, DAPL_MAGIC_PSP) &&\r
-                   DAPL_BAD_HANDLE(conn->sp, DAPL_MAGIC_RSP))\r
-                       conn_recv = NULL;\r
-               break;\r
-       default:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_ERR, " passive_cb: "\r
-                            "Unexpected CM event %d on ID 0x%p\n",\r
-                            event->event, conn->cm_id);\r
-               conn_recv = NULL;\r
-               break;\r
+       if (conn->cm_id) {
+               if (conn->cm_id->qp)
+                       rdma_destroy_qp(conn->cm_id);
+               rdma_destroy_id(conn->cm_id);
        }\r
-\r
        dapl_os_unlock(&conn->lock);\r
-       if (conn_recv)\r
-               dapls_cr_callback(conn_recv, ib_cm_event, pdata,\r
-                                 event->param.conn.private_data_len, conn_recv->sp);\r
-}\r
-\r
-/************************ DAPL provider entry points **********************/\r
-\r
-/*\r
- * dapls_ib_connect\r
- *\r
- * Initiate a connection with the passive listener on another node\r
- *\r
- * Input:\r
- *     ep_handle,\r
- *     remote_ia_address,\r
- *     remote_conn_qual,\r
- *     prd_size                size of private data and structure\r
- *     prd_prt                 pointer to private data structure\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,\r
-                           IN DAT_IA_ADDRESS_PTR r_addr,\r
-                           IN DAT_CONN_QUAL r_qual,\r
-                           IN DAT_COUNT p_size, IN void *p_data)\r
-{\r
-       struct dapl_ep *ep_ptr = ep_handle;\r
-       struct dapl_cm_id *conn = ep_ptr->cm_handle;\r
-       int ret;\r
-\r
-       /* Sanity check */\r
-       if (NULL == ep_ptr)\r
-               return DAT_SUCCESS;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " connect: rSID 0x%llx rPort %d, pdata %p, ln %d\n",\r
-                    r_qual, ntohs(SID_TO_PORT(r_qual)), p_data, p_size);\r
-\r
-       /* rdma conn and cm_id pre-bound; reference via ep_ptr->cm_handle */\r
-\r
-       /* Setup QP/CM parameters and private data in cm_id */\r
-       (void)dapl_os_memzero(&conn->params, sizeof(conn->params));\r
-       conn->params.responder_resources =\r
-           ep_ptr->param.ep_attr.max_rdma_read_in;\r
-       conn->params.initiator_depth = ep_ptr->param.ep_attr.max_rdma_read_out;\r
-       conn->params.flow_control = 1;\r
-       conn->params.rnr_retry_count = IB_RNR_RETRY_COUNT;\r
-       conn->params.retry_count = IB_RC_RETRY_COUNT;\r
-       if (p_size) {\r
-               dapl_os_memcpy(conn->p_data, p_data, p_size);\r
-               conn->params.private_data = conn->p_data;\r
-               conn->params.private_data_len = p_size;\r
-       }\r
-\r
-       /* copy in remote address, need a copy for retry attempts */\r
-       dapl_os_memcpy(&conn->r_addr, r_addr, sizeof(*r_addr));\r
-\r
-       /* Resolve remote address, src already bound during QP create */\r
-       ((struct sockaddr_in *)&conn->r_addr)->sin_port = SID_TO_PORT(r_qual);\r
-       ((struct sockaddr_in *)&conn->r_addr)->sin_family = AF_INET;\r
-\r
-       ret = rdma_resolve_addr(conn->cm_id, NULL,\r
-                               (struct sockaddr *)&conn->r_addr,\r
-                               conn->arp_timeout);\r
-       if (ret) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " dapl_cma_connect: rdma_resolve_addr ERR 0x%x %s\n",\r
-                        ret, strerror(errno));\r
-               return dapl_convert_errno(errno, "ib_connect");\r
-       }\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " connect: resolve_addr: cm_id %p -> %s port %d\n",\r
-                    conn->cm_id,\r
-                    inet_ntoa(((struct sockaddr_in *)&conn->r_addr)->sin_addr),\r
-                    ((struct sockaddr_in *)&conn->r_addr)->sin_port);\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_disconnect\r
- *\r
- * Disconnect an EP\r
- *\r
- * Input:\r
- *     ep_handle,\r
- *     disconnect_flags\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_disconnect(IN DAPL_EP * ep_ptr, IN DAT_CLOSE_FLAGS close_flags)\r
-{\r
-       dp_ib_cm_handle_t conn = ep_ptr->cm_handle;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " disconnect(ep %p, conn %p, id %d flags %x)\n",\r
-                    ep_ptr, conn, (conn ? conn->cm_id : 0), close_flags);\r
-\r
-       if ((conn == IB_INVALID_HANDLE) || (conn->cm_id == NULL))\r
-               return DAT_SUCCESS;\r
-\r
-       /* no graceful half-pipe disconnect option */\r
-       rdma_disconnect(conn->cm_id);\r
-\r
-       /* \r
-        * DAT event notification occurs from the callback\r
-        * Note: will fire even if DREQ goes unanswered on timeout \r
-        */\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_disconnect_clean\r
- *\r
- * Clean up outstanding connection data. This routine is invoked\r
- * after the final disconnect callback has occurred. Only on the\r
- * ACTIVE side of a connection.\r
- *\r
- * Input:\r
- *     ep_ptr          DAPL_EP\r
- *     active          Indicates active side of connection\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     void\r
- *\r
- */\r
-void\r
-dapls_ib_disconnect_clean(IN DAPL_EP * ep_ptr,\r
-                         IN DAT_BOOLEAN active,\r
-                         IN const ib_cm_events_t ib_cm_event)\r
-{\r
-       /* nothing to do */\r
-       return;\r
-}\r
-\r
-/*\r
- * dapl_ib_setup_conn_listener\r
- *\r
- * Have the CM set up a connection listener.\r
- *\r
- * Input:\r
- *     ibm_hca_handle          HCA handle\r
- *     qp_handle                       QP handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *     DAT_CONN_QUAL_UNAVAILBLE\r
- *     DAT_CONN_QUAL_IN_USE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_setup_conn_listener(IN DAPL_IA * ia_ptr,\r
-                            IN DAT_UINT64 ServiceID, IN DAPL_SP * sp_ptr)\r
-{\r
-       DAT_RETURN dat_status = DAT_SUCCESS;\r
-       ib_cm_srvc_handle_t conn;\r
-       DAT_SOCK_ADDR6 addr;    /* local binding address */\r
-\r
-       /* Allocate CM and initialize lock */\r
-       if ((conn = dapl_os_alloc(sizeof(*conn))) == NULL)\r
-               return DAT_INSUFFICIENT_RESOURCES;\r
-\r
-       dapl_os_memzero(conn, sizeof(*conn));\r
-       dapl_os_lock_init(&conn->lock);\r
-       conn->refs++;\r
-\r
-       /* create CM_ID, bind to local device, create QP */\r
-       if (rdma_create_id\r
-           (g_cm_events, &conn->cm_id, (void *)conn, RDMA_PS_TCP)) {\r
-               dapl_os_lock_destroy(&conn->lock);\r
-               dapl_os_free(conn, sizeof(*conn));\r
-               return (dapl_convert_errno(errno, "setup_listener"));\r
-       }\r
-\r
-       /* open identifies the local device; per DAT specification */\r
-       /* Get family and address then set port to consumer's ServiceID */\r
-       dapl_os_memcpy(&addr, &ia_ptr->hca_ptr->hca_address, sizeof(addr));\r
-       ((struct sockaddr_in *)&addr)->sin_port = SID_TO_PORT(ServiceID);\r
-\r
-       if (rdma_bind_addr(conn->cm_id, (struct sockaddr *)&addr)) {\r
-               if ((errno == EBUSY) || (errno == EADDRINUSE) || \r
-                   (errno == EADDRNOTAVAIL))\r
-                       dat_status = DAT_CONN_QUAL_IN_USE;\r
-               else\r
-                       dat_status =\r
-                           dapl_convert_errno(errno, "setup_listener");\r
-               goto bail;\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " listen(ia_ptr %p SID 0x%llx Port %d sp %p conn %p id %d)\n",\r
-                    ia_ptr, ServiceID, ntohs(SID_TO_PORT(ServiceID)),\r
-                    sp_ptr, conn, conn->cm_id);\r
-\r
-       sp_ptr->cm_srvc_handle = conn;\r
-       conn->sp = sp_ptr;\r
-       conn->hca = ia_ptr->hca_ptr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " listen(conn=%p cm_id=%d)\n",\r
-                    sp_ptr->cm_srvc_handle, conn->cm_id);\r
-\r
-       if (rdma_listen(conn->cm_id, 0)) {      /* max cma backlog */\r
-\r
-               if ((errno == EBUSY) || (errno == EADDRINUSE) ||\r
-                   (errno == EADDRNOTAVAIL))\r
-                       dat_status = DAT_CONN_QUAL_IN_USE;\r
-               else\r
-                       dat_status =\r
-                           dapl_convert_errno(errno, "setup_listener");\r
-               goto bail;\r
-       }\r
-\r
-       /* success */\r
-       return DAT_SUCCESS;\r
-\r
-      bail:\r
-       rdma_destroy_id(conn->cm_id);\r
-       dapl_os_lock_destroy(&conn->lock);\r
-       dapl_os_free(conn, sizeof(*conn));\r
-       return dat_status;\r
-}\r
-\r
-/*\r
- * dapl_ib_remove_conn_listener\r
- *\r
- * Have the CM remove a connection listener.\r
- *\r
- * Input:\r
- *     ia_handle               IA handle\r
- *     ServiceID               IB Channel Service ID\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_STATE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_remove_conn_listener(IN DAPL_IA * ia_ptr, IN DAPL_SP * sp_ptr)\r
-{\r
-       ib_cm_srvc_handle_t conn = sp_ptr->cm_srvc_handle;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " remove_listen(ia_ptr %p sp_ptr %p cm_ptr %p)\n",\r
-                    ia_ptr, sp_ptr, conn);\r
-\r
-       if (conn != IB_INVALID_HANDLE) {\r
-               sp_ptr->cm_srvc_handle = NULL;\r
-               dapls_ib_cm_free(conn, NULL);\r
-       }\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_accept_connection\r
- *\r
- * Perform necessary steps to accept a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *     ep_handle\r
- *     private_data_size\r
- *     private_data\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,\r
-                          IN DAT_EP_HANDLE ep_handle,\r
-                          IN DAT_COUNT p_size, IN const DAT_PVOID p_data)\r
-{\r
-       DAPL_CR *cr_ptr = (DAPL_CR *) cr_handle;\r
-       DAPL_EP *ep_ptr = (DAPL_EP *) ep_handle;\r
-       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;\r
-       struct dapl_cm_id *cr_conn = cr_ptr->ib_cm_handle;\r
-       int ret;\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " accept(cr %p conn %p, id %p, p_data %p, p_sz=%d)\n",\r
-                    cr_ptr, cr_conn, cr_conn->cm_id, p_data, p_size);\r
-\r
-       /* Obtain size of private data structure & contents */\r
-       if (p_size > IB_MAX_REP_PDATA_SIZE) {\r
-               dat_status = DAT_ERROR(DAT_LENGTH_ERROR, DAT_NO_SUBTYPE);\r
-               goto bail;\r
-       }\r
-\r
-       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {\r
-               /* \r
-                * If we are lazy attaching the QP then we may need to\r
-                * hook it up here. Typically, we run this code only for\r
-                * DAT_PSP_PROVIDER_FLAG\r
-                */\r
-               dat_status = dapls_ib_qp_alloc(ia_ptr, ep_ptr, NULL);\r
-               if (dat_status != DAT_SUCCESS) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                " dapl_cma_accept: qp_alloc ERR %d\n",\r
-                                dat_status);\r
-                       goto bail;\r
-               }\r
-       }\r
-\r
-       /* \r
-        * Validate device and port in EP cm_id against inbound \r
-        * CR cm_id. The pre-allocated EP cm_id is already bound to \r
-        * a local device (cm_id and QP) when created. Move the QP\r
-        * to the new cm_id only if device and port numbers match.\r
-        */\r
-       if (ep_ptr->cm_handle->cm_id->verbs == cr_conn->cm_id->verbs &&\r
-           ep_ptr->cm_handle->cm_id->port_num == cr_conn->cm_id->port_num) {\r
-               /* move QP to new cr_conn, remove QP ref in EP cm_id */\r
-               cr_conn->cm_id->qp = ep_ptr->cm_handle->cm_id->qp;\r
-               ep_ptr->cm_handle->cm_id->qp = NULL;\r
-               dapls_ib_cm_free(ep_ptr->cm_handle, NULL);\r
-       } else {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " dapl_cma_accept: ERR dev(%p!=%p) or"\r
-                        " port mismatch(%d!=%d)\n",\r
-                        ep_ptr->cm_handle->cm_id->verbs, cr_conn->cm_id->verbs,\r
-                        ntohs(ep_ptr->cm_handle->cm_id->port_num),\r
-                        ntohs(cr_conn->cm_id->port_num));\r
-               dat_status = DAT_INTERNAL_ERROR;\r
-               goto bail;\r
-       }\r
-\r
-       cr_ptr->param.local_ep_handle = ep_handle;\r
-       cr_conn->params.private_data = p_data;\r
-       cr_conn->params.private_data_len = p_size;\r
-\r
-       ret = rdma_accept(cr_conn->cm_id, &cr_conn->params);\r
-       if (ret) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR, " dapl_cma_accept: ERR %d %s\n",\r
-                        ret, strerror(errno));\r
-               dat_status = dapl_convert_errno(ret, "accept");\r
-               goto bail;\r
-       }\r
-\r
-       /* save accepted conn and EP reference, qp_handle unchanged */\r
-       ep_ptr->cm_handle = cr_conn;\r
-       cr_conn->ep = ep_ptr;\r
-\r
-       /* setup local and remote ports for ep query */\r
-       /* Note: port qual in network order */\r
-       ep_ptr->param.remote_port_qual =\r
-           PORT_TO_SID(rdma_get_dst_port(cr_conn->cm_id));\r
-       ep_ptr->param.local_port_qual =\r
-           PORT_TO_SID(rdma_get_src_port(cr_conn->cm_id));\r
-\r
-       return DAT_SUCCESS;\r
-      bail:\r
-       rdma_reject(cr_conn->cm_id, NULL, 0);\r
-       dapls_ib_cm_free(cr_conn, NULL);\r
-       return dat_status;\r
-}\r
-\r
-/*\r
- * dapls_ib_reject_connection\r
- *\r
- * Reject a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_reject_connection(IN dp_ib_cm_handle_t cm_handle,\r
-                          IN int reason,\r
-                          IN DAT_COUNT private_data_size,\r
-                          IN const DAT_PVOID private_data)\r
-{\r
-       int ret;\r
-       int offset = sizeof(struct dapl_pdata_hdr);\r
-       struct dapl_pdata_hdr pdata_hdr;\r
-\r
-       memset(&pdata_hdr, 0, sizeof pdata_hdr);\r
-       pdata_hdr.version = htonl((DAT_VERSION_MAJOR << 24) |\r
-                                 (DAT_VERSION_MINOR << 16) |\r
-                                 (VN_PROVIDER_MAJOR << 8) |\r
-                                 (VN_PROVIDER_MINOR));\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " reject: handle %p reason %x, ver=%x, data %p, sz=%d\n",\r
-                    cm_handle, reason, ntohl(pdata_hdr.version),\r
-                    private_data, private_data_size);\r
-\r
-       if (cm_handle == IB_INVALID_HANDLE) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
-                            " reject: invalid handle: reason %d\n", reason);\r
-               return DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CR);\r
-       }\r
-\r
-       /* setup pdata_hdr and users data, in CR pdata buffer */\r
-       dapl_os_memcpy(cm_handle->p_data, &pdata_hdr, offset);\r
-       if (private_data_size)\r
-               dapl_os_memcpy(cm_handle->p_data + offset,\r
-                              private_data, private_data_size);\r
-\r
-       /*\r
-        * Always some private data with reject so active peer can\r
-        * determine real application reject from an abnormal \r
-        * application termination\r
-        */\r
-       ret = rdma_reject(cm_handle->cm_id,\r
-                         cm_handle->p_data, offset + private_data_size);\r
-\r
-       dapls_ib_cm_free(cm_handle, NULL);\r
-       return dapl_convert_errno(ret, "reject");\r
-}\r
-\r
-/*\r
- * dapls_ib_cm_remote_addr\r
- *\r
- * Obtain the remote IP address given a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *\r
- * Output:\r
- *     remote_ia_address: where to place the remote address\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_HANDLE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle, OUT DAT_SOCK_ADDR6 * raddr)\r
-{\r
-       DAPL_HEADER *header;\r
-       dp_ib_cm_handle_t ib_cm_handle;\r
-       struct rdma_addr *ipaddr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " remote_addr(cm_handle=%p, r_addr=%p)\n",\r
-                    dat_handle, raddr);\r
-\r
-       header = (DAPL_HEADER *) dat_handle;\r
-\r
-       if (header->magic == DAPL_MAGIC_EP)\r
-               ib_cm_handle = ((DAPL_EP *) dat_handle)->cm_handle;\r
-       else if (header->magic == DAPL_MAGIC_CR)\r
-               ib_cm_handle = ((DAPL_CR *) dat_handle)->ib_cm_handle;\r
-       else\r
-               return DAT_INVALID_HANDLE;\r
-\r
-       /* get remote IP address from cm_id route */\r
-       ipaddr = &ib_cm_handle->cm_id->route.addr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " remote_addr: conn %p id %p SRC %x DST %x PORT %d\n",\r
-                    ib_cm_handle, ib_cm_handle->cm_id,\r
-                    ntohl(((struct sockaddr_in *)\r
-                           &ipaddr->src_addr)->sin_addr.s_addr),\r
-                    ntohl(((struct sockaddr_in *)\r
-                           &ipaddr->dst_addr)->sin_addr.s_addr),\r
-                    ntohs(((struct sockaddr_in *)\r
-                           &ipaddr->dst_addr)->sin_port));\r
-\r
-       dapl_os_memcpy(raddr, &ipaddr->dst_addr, sizeof(DAT_SOCK_ADDR));\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-int dapls_ib_private_data_size(\r
-       IN DAPL_HCA *hca_ptr)\r
-{\r
-       return RDMA_MAX_PRIVATE_DATA;\r
-}\r
-\r
-/*\r
- * Map all CMA event codes to the DAT equivelent.\r
- */\r
-#define DAPL_IB_EVENT_CNT      13\r
-\r
-static struct ib_cm_event_map {\r
-       const ib_cm_events_t ib_cm_event;\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-} ib_cm_event_map[DAPL_IB_EVENT_CNT] = {\r
-       /* 00 */  {\r
-       IB_CME_CONNECTED, DAT_CONNECTION_EVENT_ESTABLISHED},\r
-           /* 01 */  {\r
-       IB_CME_DISCONNECTED, DAT_CONNECTION_EVENT_DISCONNECTED},\r
-           /* 02 */  {\r
-       IB_CME_DISCONNECTED_ON_LINK_DOWN,\r
-                   DAT_CONNECTION_EVENT_DISCONNECTED},\r
-           /* 03 */  {\r
-       IB_CME_CONNECTION_REQUEST_PENDING, DAT_CONNECTION_REQUEST_EVENT},\r
-           /* 04 */  {\r
-       IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,\r
-                   DAT_CONNECTION_REQUEST_EVENT},\r
-           /* 05 */  {\r
-       IB_CME_CONNECTION_REQUEST_ACKED, DAT_CONNECTION_REQUEST_EVENT},\r
-           /* 06 */  {\r
-       IB_CME_DESTINATION_REJECT,\r
-                   DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
-           /* 07 */  {\r
-       IB_CME_DESTINATION_REJECT_PRIVATE_DATA,\r
-                   DAT_CONNECTION_EVENT_PEER_REJECTED},\r
-           /* 08 */  {\r
-       IB_CME_DESTINATION_UNREACHABLE, DAT_CONNECTION_EVENT_UNREACHABLE},\r
-           /* 09 */  {\r
-       IB_CME_TOO_MANY_CONNECTION_REQUESTS,\r
-                   DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
-           /* 10 */  {\r
-       IB_CME_LOCAL_FAILURE, DAT_CONNECTION_EVENT_BROKEN},\r
-           /* 11 */  {\r
-       IB_CME_BROKEN, DAT_CONNECTION_EVENT_BROKEN},\r
-           /* 12 */  {\r
-IB_CME_TIMEOUT, DAT_CONNECTION_EVENT_TIMED_OUT},};\r
-\r
-/*\r
- * dapls_ib_get_cm_event\r
- *\r
- * Return a DAT connection event given a provider CM event.\r
- *\r
- * Input:\r
- *     dat_event_num   DAT event we need an equivelent CM event for\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     ib_cm_event of translated DAPL value\r
- */\r
-DAT_EVENT_NUMBER\r
-dapls_ib_get_dat_event(IN const ib_cm_events_t ib_cm_event,\r
-                      IN DAT_BOOLEAN active)\r
-{\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-       int i;\r
-\r
-       active = active;\r
-\r
-       dat_event_num = 0;\r
-       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {\r
-               if (ib_cm_event == ib_cm_event_map[i].ib_cm_event) {\r
-                       dat_event_num = ib_cm_event_map[i].dat_event_num;\r
-                       break;\r
-               }\r
-       }\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
-                    "dapls_ib_get_dat_event: event(%s) ib=0x%x dat=0x%x\n",\r
-                    active ? "active" : "passive", ib_cm_event, dat_event_num);\r
-\r
-       return dat_event_num;\r
-}\r
-\r
-/*\r
- * dapls_ib_get_dat_event\r
- *\r
- * Return a DAT connection event given a provider CM event.\r
- * \r
- * Input:\r
- *     ib_cm_event     event provided to the dapl callback routine\r
- *     active          switch indicating active or passive connection\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_EVENT_NUMBER of translated provider value\r
- */\r
-ib_cm_events_t dapls_ib_get_cm_event(IN DAT_EVENT_NUMBER dat_event_num)\r
-{\r
-       ib_cm_events_t ib_cm_event;\r
-       int i;\r
-\r
-       ib_cm_event = 0;\r
-       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {\r
-               if (dat_event_num == ib_cm_event_map[i].dat_event_num) {\r
-                       ib_cm_event = ib_cm_event_map[i].ib_cm_event;\r
-                       break;\r
-               }\r
-       }\r
-       return ib_cm_event;\r
-}\r
-\r
-void dapli_cma_event_cb(void)\r
-{\r
-       struct rdma_cm_event *event;\r
-                               \r
-       /* process one CM event, fairness, non-blocking */\r
-       if (!rdma_get_cm_event(g_cm_events, &event)) {\r
-               struct dapl_cm_id *conn;\r
-\r
-               /* set proper conn from cm_id context */\r
-               if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST)\r
-                       conn = (struct dapl_cm_id *)event->listen_id->context;\r
-               else\r
-                       conn = (struct dapl_cm_id *)event->id->context;\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " cm_event: EVENT=%d ID=%p LID=%p CTX=%p\n",\r
-                            event->event, event->id, event->listen_id, conn);\r
-               \r
-               /* cm_free is blocked waiting for ack  */\r
-               dapl_os_lock(&conn->lock);\r
-               if (!conn->refs) {\r
-                       dapl_os_unlock(&conn->lock);\r
-                       rdma_ack_cm_event(event);\r
-                       return;\r
-               }\r
-               conn->refs++;\r
-               dapl_os_unlock(&conn->lock);\r
-\r
-               switch (event->event) {\r
-               case RDMA_CM_EVENT_ADDR_RESOLVED:\r
-                       dapli_addr_resolve(conn);\r
-                       break;\r
-\r
-               case RDMA_CM_EVENT_ROUTE_RESOLVED:\r
-                       dapli_route_resolve(conn);\r
-                       break;\r
-\r
-               case RDMA_CM_EVENT_ADDR_ERROR:\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                "dapl_cma_active: CM ADDR ERROR: ->"\r
-                                " DST %s retry (%d)..\n",\r
-                                inet_ntoa(((struct sockaddr_in *)\r
-                                           &conn->r_addr)->sin_addr),\r
-                                conn->arp_retries);\r
-\r
-                       /* retry address resolution */\r
-                       if ((--conn->arp_retries) &&\r
-                           (event->status == -ETIMEDOUT)) {\r
-                               int ret;\r
-                               ret = rdma_resolve_addr(conn->cm_id, NULL,\r
-                                                       (struct sockaddr *)\r
-                                                       &conn->r_addr,\r
-                                                       conn->arp_timeout);\r
-                               if (!ret)\r
-                                       break;\r
-                               else {\r
-                                       dapl_dbg_log(DAPL_DBG_TYPE_WARN,\r
-                                                    " ERROR: rdma_resolve_addr = "\r
-                                                    "%d %s\n",\r
-                                                    ret, strerror(errno));\r
-                               }\r
-                       }\r
-                       /* retries exhausted or resolve_addr failed */\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                "dapl_cma_active: ARP_ERR, retries(%d)"\r
-                                " exhausted -> DST %s,%d\n",\r
-                                IB_ARP_RETRY_COUNT,\r
-                                inet_ntoa(((struct sockaddr_in *)\r
-                                           &conn->cm_id->route.addr.dst_addr)->\r
-                                          sin_addr),\r
-                                ntohs(((struct sockaddr_in *)\r
-                                       &conn->cm_id->route.addr.dst_addr)->\r
-                                      sin_port));\r
-\r
-                       dapl_evd_connection_callback(conn,\r
-                                                    IB_CME_DESTINATION_UNREACHABLE,\r
-                                                    NULL, 0, conn->ep);\r
-                       break;\r
-\r
-               case RDMA_CM_EVENT_ROUTE_ERROR:\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                "dapl_cma_active: CM ROUTE ERROR: ->"\r
-                                " DST %s retry (%d)..\n",\r
-                                inet_ntoa(((struct sockaddr_in *)\r
-                                           &conn->r_addr)->sin_addr),\r
-                                conn->route_retries);\r
-\r
-                       /* retry route resolution */\r
-                       if ((--conn->route_retries) &&\r
-                           (event->status == -ETIMEDOUT))\r
-                               dapli_addr_resolve(conn);\r
-                       else {\r
-                               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                        "dapl_cma_active: PATH_RECORD_ERR,"\r
-                                        " retries(%d) exhausted, DST %s,%d\n",\r
-                                        IB_ROUTE_RETRY_COUNT,\r
-                                        inet_ntoa(((struct sockaddr_in *)\r
-                                                   &conn->cm_id->route.addr.\r
-                                                   dst_addr)->sin_addr),\r
-                                        ntohs(((struct sockaddr_in *)\r
-                                               &conn->cm_id->route.addr.\r
-                                               dst_addr)->sin_port));\r
-\r
-                               dapl_evd_connection_callback(conn,\r
-                                                            IB_CME_DESTINATION_UNREACHABLE,\r
-                                                            NULL, 0, conn->ep);\r
-                       }\r
-                       break;\r
-\r
-               case RDMA_CM_EVENT_DEVICE_REMOVAL:\r
-                       dapl_evd_connection_callback(conn,\r
-                                                    IB_CME_LOCAL_FAILURE,\r
-                                                    NULL, 0, conn->ep);\r
-                       break;\r
-               case RDMA_CM_EVENT_CONNECT_REQUEST:\r
-               case RDMA_CM_EVENT_CONNECT_ERROR:\r
-               case RDMA_CM_EVENT_UNREACHABLE:\r
-               case RDMA_CM_EVENT_REJECTED:\r
-               case RDMA_CM_EVENT_ESTABLISHED:\r
-               case RDMA_CM_EVENT_DISCONNECTED:\r
-                       /* passive or active */\r
-                       if (conn->sp)\r
-                               dapli_cm_passive_cb(conn, event);\r
-                       else\r
-                               dapli_cm_active_cb(conn, event);\r
-                       break;\r
-               case RDMA_CM_EVENT_CONNECT_RESPONSE:\r
-#ifdef RDMA_CM_EVENT_TIMEWAIT_EXIT\r
-               case RDMA_CM_EVENT_TIMEWAIT_EXIT:\r
-#endif\r
-                       break;\r
-               default:\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                                    " cm_event: UNEXPECTED EVENT=%p ID=%p CTX=%p\n",\r
-                                    event->event, event->id,\r
-                                    event->id->context);\r
-                       break;\r
-               }\r
-               \r
-               /* ack event, unblocks destroy_cm_id in consumer threads */\r
-               rdma_ack_cm_event(event);\r
-\r
-               dapl_os_lock(&conn->lock);\r
-                conn->refs--;\r
-               dapl_os_unlock(&conn->lock);\r
-       } \r
-}\r
-\r
-/*\r
- * Local variables:\r
- *  c-indent-level: 4\r
- *  c-basic-offset: 4\r
- *  tab-width: 8\r
- * End:\r
- */\r
+       dapli_cm_dealloc(conn);\r
+}
+
+/* BLOCKING: called from dapl_ep_free, EP link will be last ref */
+void dapls_cm_free(dp_ib_cm_handle_t conn)
+{
+       dapl_log(DAPL_DBG_TYPE_CM,
+                " cm_free: cm %p ep %p refs=%d\n", 
+                conn, conn->ep, conn->ref_count);
+       
+       dapls_cm_release(conn); /* release alloc ref */
+
+       /* Destroy cm_id, wait until EP is last ref */
+       dapl_os_lock(&conn->lock);
+       if (conn->cm_id) {
+               if (conn->cm_id->qp)
+                       rdma_destroy_qp(conn->cm_id);
+               rdma_destroy_id(conn->cm_id);
+               conn->cm_id = NULL;
+       }
+
+       /* EP linking is last reference */
+       while (conn->ref_count != 1) {
+               dapl_os_unlock(&conn->lock);
+               dapl_os_sleep_usec(10000);
+               dapl_os_lock(&conn->lock);
+       }
+       dapl_os_unlock(&conn->lock);
+
+       /* unlink, dequeue from EP. Final ref so release will destroy */
+       dapl_ep_unlink_cm(conn->ep, conn);
+}
+
+static struct dapl_cm_id *dapli_req_recv(struct dapl_cm_id *conn,
+                                        struct rdma_cm_event *event)
+{
+       struct dapl_cm_id *new_conn;
+#ifdef DAPL_DBG
+       struct rdma_addr *ipaddr = &event->id->route.addr;
+#endif
+
+       if (conn->sp == NULL) {
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+                            " dapli_rep_recv: on invalid listen " "handle\n");
+               return NULL;
+       }
+
+       /* allocate new cm_id and merge listen parameters */
+       new_conn = dapl_os_alloc(sizeof(*new_conn));
+       if (new_conn) {
+               (void)dapl_os_memzero(new_conn, sizeof(*new_conn));
+               dapl_os_lock_init(&new_conn->lock);
+               dapls_cm_acquire(new_conn);
+               new_conn->cm_id = event->id;    /* provided by uCMA */
+               event->id->context = new_conn;  /* update CM_ID context */
+               new_conn->sp = conn->sp;
+               new_conn->hca = conn->hca;
+
+               /* Get requesters connect data, setup for accept */
+               new_conn->params.responder_resources =
+                   DAPL_MIN(event->param.conn.responder_resources,
+                            conn->hca->ib_trans.rd_atom_in);
+               new_conn->params.initiator_depth =
+                   DAPL_MIN(event->param.conn.initiator_depth,
+                            conn->hca->ib_trans.rd_atom_out);
+
+               new_conn->params.flow_control = event->param.conn.flow_control;
+               new_conn->params.rnr_retry_count =
+                   event->param.conn.rnr_retry_count;
+               new_conn->params.retry_count = event->param.conn.retry_count;
+
+               /* save private data */
+               if (event->param.conn.private_data_len) {
+                       dapl_os_memcpy(new_conn->p_data,
+                                      event->param.conn.private_data,
+                                      event->param.conn.private_data_len);
+                       new_conn->params.private_data = new_conn->p_data;
+                       new_conn->params.private_data_len =
+                           event->param.conn.private_data_len;
+               }
+
+               dapl_dbg_log(DAPL_DBG_TYPE_CM, " passive_cb: "
+                            "REQ: SP %p PORT %d LID %d "
+                            "NEW CONN %p ID %p pdata %p,%d\n",
+                            new_conn->sp, ntohs(((struct sockaddr_in *)
+                                                 &ipaddr->src_addr)->sin_port),
+                            event->listen_id, new_conn, event->id,
+                            event->param.conn.private_data,
+                            event->param.conn.private_data_len);
+
+               dapl_dbg_log(DAPL_DBG_TYPE_CM, " passive_cb: "
+                            "REQ: IP SRC %x PORT %d DST %x PORT %d "
+                            "rr %d init %d\n", ntohl(((struct sockaddr_in *)
+                                                      &ipaddr->src_addr)->
+                                                     sin_addr.s_addr),
+                            ntohs(((struct sockaddr_in *)
+                                   &ipaddr->src_addr)->sin_port),
+                            ntohl(((struct sockaddr_in *)
+                                   &ipaddr->dst_addr)->sin_addr.s_addr),
+                            ntohs(((struct sockaddr_in *)
+                                   &ipaddr->dst_addr)->sin_port),
+                            new_conn->params.responder_resources,
+                            new_conn->params.initiator_depth);
+       }
+       return new_conn;
+}
+
+static void dapli_cm_active_cb(struct dapl_cm_id *conn,
+                              struct rdma_cm_event *event)
+{
+       DAPL_OS_LOCK *lock = &conn->lock;
+       ib_cm_events_t ib_cm_event;
+       const void *pdata = NULL;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " active_cb: conn %p id %d event %d\n",
+                    conn, conn->cm_id, event->event);
+
+       /* There is a chance that we can get events after
+        * the consumer calls disconnect in a pending state
+        * since the IB CM and uDAPL states are not shared.
+        * In some cases, IB CM could generate either a DCONN
+        * or CONN_ERR after the consumer returned from
+        * dapl_ep_disconnect with a DISCONNECTED event
+        * already queued. Check state here and bail to
+        * avoid any events after a disconnect.
+        */
+       if (DAPL_BAD_HANDLE(conn->ep, DAPL_MAGIC_EP))
+               return;
+
+       dapl_os_lock(&conn->ep->header.lock);
+       if (conn->ep->param.ep_state == DAT_EP_STATE_DISCONNECTED) {
+               dapl_os_unlock(&conn->ep->header.lock);
+               return;
+       }
+       if (event->event == RDMA_CM_EVENT_DISCONNECTED)
+               conn->ep->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+
+       dapl_os_unlock(&conn->ep->header.lock);
+       dapl_os_lock(lock);
+
+       switch (event->event) {
+       case RDMA_CM_EVENT_UNREACHABLE:
+       case RDMA_CM_EVENT_CONNECT_ERROR:
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                        "dapl_cma_active: CONN_ERR event=0x%x"
+                        " status=%d %s DST %s, %d\n",
+                        event->event, event->status,
+                        (event->status == -ETIMEDOUT) ? "TIMEOUT" : "",
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &conn->cm_id->route.addr.dst_addr)->
+                                  sin_addr),
+                        ntohs(((struct sockaddr_in *)
+                               &conn->cm_id->route.addr.dst_addr)->
+                              sin_port));
+
+               /* per DAT SPEC provider always returns UNREACHABLE */
+               ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;
+               break;
+       case RDMA_CM_EVENT_REJECTED:
+               dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                            " dapli_cm_active_handler: REJECTED reason=%d\n",
+                            event->status);
+
+               /* valid REJ from consumer will always contain private data */
+               if (event->status == 28 &&
+                   event->param.conn.private_data_len) {
+                       ib_cm_event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;
+                       pdata =
+                           (unsigned char *)event->param.conn.
+                           private_data +
+                           sizeof(struct dapl_pdata_hdr);
+               } else {
+                       ib_cm_event = IB_CME_DESTINATION_REJECT;
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                "dapl_cma_active: non-consumer REJ,"
+                                " reason=%d, DST %s, %d\n",
+                                event->status,
+                                inet_ntoa(((struct sockaddr_in *)
+                                           &conn->cm_id->route.addr.
+                                           dst_addr)->sin_addr),
+                                ntohs(((struct sockaddr_in *)
+                                       &conn->cm_id->route.addr.
+                                       dst_addr)->sin_port));
+               }
+               break;
+       case RDMA_CM_EVENT_ESTABLISHED:
+               dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                            " active_cb: cm_id %d PORT %d CONNECTED to %s!\n",
+                            conn->cm_id, ntohs(((struct sockaddr_in *)
+                                                &conn->cm_id->route.addr.
+                                                dst_addr)->sin_port),
+                            inet_ntoa(((struct sockaddr_in *)
+                                       &conn->cm_id->route.addr.dst_addr)->
+                                      sin_addr));
+
+               /* setup local and remote ports for ep query */
+               conn->ep->param.remote_port_qual =
+                   PORT_TO_SID(rdma_get_dst_port(conn->cm_id));
+               conn->ep->param.local_port_qual =
+                   PORT_TO_SID(rdma_get_src_port(conn->cm_id));
+
+               ib_cm_event = IB_CME_CONNECTED;
+               pdata = event->param.conn.private_data;
+               break;
+       case RDMA_CM_EVENT_DISCONNECTED:
+               dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                            " active_cb: DISC EVENT - EP %p\n",conn->ep);
+               rdma_disconnect(conn->cm_id);   /* required for DREP */
+               ib_cm_event = IB_CME_DISCONNECTED;
+               /* validate EP handle */
+               if (DAPL_BAD_HANDLE(conn->ep, DAPL_MAGIC_EP))
+                       conn = NULL;
+               break;
+       default:
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+                            " dapli_cm_active_cb_handler: Unexpected CM "
+                            "event %d on ID 0x%p\n", event->event,
+                            conn->cm_id);
+               conn = NULL;
+               break;
+       }
+
+       dapl_os_unlock(lock);
+       if (conn)
+               dapl_evd_connection_callback(conn, ib_cm_event, pdata,
+                                            event->param.conn.private_data_len, conn->ep);
+}
+
+static void dapli_cm_passive_cb(struct dapl_cm_id *conn,
+                               struct rdma_cm_event *event)
+{
+       ib_cm_events_t ib_cm_event;
+       struct dapl_cm_id *conn_recv = conn;
+       const void *pdata = NULL;
+       
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " passive_cb: conn %p id %d event %d\n",
+                    conn, event->id, event->event);
+
+       dapl_os_lock(&conn->lock);
+
+       switch (event->event) {
+       case RDMA_CM_EVENT_CONNECT_REQUEST:
+               /* create new conn object with new conn_id from event */
+               conn_recv = dapli_req_recv(conn, event);
+               ib_cm_event = IB_CME_CONNECTION_REQUEST_PENDING;
+               pdata = event->param.conn.private_data;
+               break;
+       case RDMA_CM_EVENT_UNREACHABLE:
+       case RDMA_CM_EVENT_CONNECT_ERROR:
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                        "dapl_cm_passive: CONN_ERR event=0x%x status=%d %s,"
+                        " DST %s,%d\n",
+                        event->event, event->status,
+                        (event->status == -ETIMEDOUT) ? "TIMEOUT" : "",
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &conn->cm_id->route.addr.dst_addr)->
+                                  sin_addr), ntohs(((struct sockaddr_in *)
+                                                    &conn->cm_id->route.addr.
+                                                    dst_addr)->sin_port));
+               ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;
+               break;
+       case RDMA_CM_EVENT_REJECTED:
+               /* will alwasys be abnormal NON-consumer from active side */
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                        "dapl_cm_passive: non-consumer REJ, reason=%d,"
+                        " DST %s, %d\n",
+                        event->status,
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &conn->cm_id->route.addr.dst_addr)->
+                                  sin_addr),
+                        ntohs(((struct sockaddr_in *)
+                               &conn->cm_id->route.addr.dst_addr)->
+                              sin_port));
+               ib_cm_event = IB_CME_DESTINATION_REJECT;
+               break;
+       case RDMA_CM_EVENT_ESTABLISHED:
+               dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                            " passive_cb: cm_id %p PORT %d CONNECTED from 0x%x!\n",
+                            conn->cm_id, ntohs(((struct sockaddr_in *)
+                                                &conn->cm_id->route.addr.
+                                                src_addr)->sin_port),
+                            ntohl(((struct sockaddr_in *)
+                                   &conn->cm_id->route.addr.dst_addr)->
+                                  sin_addr.s_addr));
+               ib_cm_event = IB_CME_CONNECTED;
+               break;
+       case RDMA_CM_EVENT_DISCONNECTED:
+               rdma_disconnect(conn->cm_id);   /* required for DREP */
+               ib_cm_event = IB_CME_DISCONNECTED;
+               /* validate SP handle context */
+               if (DAPL_BAD_HANDLE(conn->sp, DAPL_MAGIC_PSP) &&
+                   DAPL_BAD_HANDLE(conn->sp, DAPL_MAGIC_RSP))
+                       conn_recv = NULL;
+               break;
+       default:
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR, " passive_cb: "
+                            "Unexpected CM event %d on ID 0x%p\n",
+                            event->event, conn->cm_id);
+               conn_recv = NULL;
+               break;
+       }
+
+       dapl_os_unlock(&conn->lock);
+       if (conn_recv)
+               dapls_cr_callback(conn_recv, ib_cm_event, pdata,
+                                 event->param.conn.private_data_len, conn_recv->sp);
+}
+
+/************************ DAPL provider entry points **********************/
+
+/*
+ * dapls_ib_connect
+ *
+ * Initiate a connection with the passive listener on another node
+ *
+ * Input:
+ *     ep_handle,
+ *     remote_ia_address,
+ *     remote_conn_qual,
+ *     prd_size                size of private data and structure
+ *     prd_prt                 pointer to private data structure
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,
+                           IN DAT_IA_ADDRESS_PTR r_addr,
+                           IN DAT_CONN_QUAL r_qual,
+                           IN DAT_COUNT p_size, IN void *p_data)
+{
+       struct dapl_ep *ep_ptr = ep_handle;
+       struct dapl_cm_id *conn = dapl_get_cm_from_ep(ep_ptr);
+       int ret;
+       
+       dapl_os_assert(conn != NULL);
+       
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " connect: rSID 0x%llx rPort %d, pdata %p, ln %d\n",
+                    r_qual, ntohs(SID_TO_PORT(r_qual)), p_data, p_size);
+
+       /* rdma conn and cm_id pre-bound; reference via ep_ptr->cm_handle */
+
+       /* Setup QP/CM parameters and private data in cm_id */
+       (void)dapl_os_memzero(&conn->params, sizeof(conn->params));
+       conn->params.responder_resources = 
+               ep_ptr->param.ep_attr.max_rdma_read_in;
+       conn->params.initiator_depth = ep_ptr->param.ep_attr.max_rdma_read_out;
+       conn->params.flow_control = 1;
+       conn->params.rnr_retry_count = IB_RNR_RETRY_COUNT;
+       conn->params.retry_count = IB_RC_RETRY_COUNT;
+       if (p_size) {
+               dapl_os_memcpy(conn->p_data, p_data, p_size);
+               conn->params.private_data = conn->p_data;
+               conn->params.private_data_len = p_size;
+       }
+
+       /* copy in remote address, need a copy for retry attempts */
+       dapl_os_memcpy(&conn->r_addr, r_addr, sizeof(*r_addr));
+
+       /* Resolve remote address, src already bound during QP create */
+       ((struct sockaddr_in *)&conn->r_addr)->sin_port = SID_TO_PORT(r_qual);
+       ((struct sockaddr_in *)&conn->r_addr)->sin_family = AF_INET;
+
+       ret = rdma_resolve_addr(conn->cm_id, NULL,
+                               (struct sockaddr *)&conn->r_addr,
+                               conn->arp_timeout);
+       if (ret) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " dapl_cma_connect: rdma_resolve_addr ERR 0x%x %s\n",
+                        ret, strerror(errno));
+               return dapl_convert_errno(errno, "rdma_resolve_addr");
+       }
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " connect: resolve_addr: cm_id %p -> %s port %d\n",
+                    conn->cm_id,
+                    inet_ntoa(((struct sockaddr_in *)&conn->r_addr)->sin_addr),
+                    ((struct sockaddr_in *)&conn->r_addr)->sin_port);
+
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_disconnect
+ *
+ * Disconnect an EP
+ *
+ * Input:
+ *     ep_handle,
+ *     disconnect_flags
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *
+ */
+DAT_RETURN
+dapls_ib_disconnect(IN DAPL_EP * ep_ptr, IN DAT_CLOSE_FLAGS close_flags)
+{
+       struct dapl_cm_id *conn = dapl_get_cm_from_ep(ep_ptr);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " disconnect(ep %p, conn %p, id %d flags %x)\n",
+                    ep_ptr, conn, (conn ? conn->cm_id : 0), close_flags);
+
+       if ((conn == NULL) || (conn->cm_id == NULL))
+               return DAT_SUCCESS;
+
+       /* no graceful half-pipe disconnect option */
+       rdma_disconnect(conn->cm_id);
+
+       /* 
+        * DAT event notification occurs from the callback
+        * Note: will fire even if DREQ goes unanswered on timeout 
+        */
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_disconnect_clean
+ *
+ * Clean up outstanding connection data. This routine is invoked
+ * after the final disconnect callback has occurred. Only on the
+ * ACTIVE side of a connection.
+ *
+ * Input:
+ *     ep_ptr          DAPL_EP
+ *     active          Indicates active side of connection
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     void
+ *
+ */
+void
+dapls_ib_disconnect_clean(IN DAPL_EP * ep_ptr,
+                         IN DAT_BOOLEAN active,
+                         IN const ib_cm_events_t ib_cm_event)
+{
+       /* nothing to do */
+}
+
+/*
+ * dapl_ib_setup_conn_listener
+ *
+ * Have the CM set up a connection listener.
+ *
+ * Input:
+ *     ibm_hca_handle          HCA handle
+ *     qp_handle                       QP handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *     DAT_CONN_QUAL_UNAVAILBLE
+ *     DAT_CONN_QUAL_IN_USE
+ *
+ */
+DAT_RETURN
+dapls_ib_setup_conn_listener(IN DAPL_IA * ia_ptr,
+                            IN DAT_UINT64 ServiceID, IN DAPL_SP * sp_ptr)
+{
+       DAT_RETURN dat_status = DAT_SUCCESS;
+       ib_cm_srvc_handle_t conn;
+       DAT_SOCK_ADDR6 addr;    /* local binding address */
+
+       /* Allocate CM and initialize lock */
+       if ((conn = dapl_os_alloc(sizeof(*conn))) == NULL)
+               return DAT_INSUFFICIENT_RESOURCES;
+
+       dapl_os_memzero(conn, sizeof(*conn));
+       dapl_os_lock_init(&conn->lock);
+       dapls_cm_acquire(conn);
+
+       /* create CM_ID, bind to local device, create QP */
+       if (rdma_create_id
+           (g_cm_events, &conn->cm_id, (void *)conn, RDMA_PS_TCP)) {
+               dapls_cm_release(conn);
+               return (dapl_convert_errno(errno, "rdma_create_id"));
+       }
+
+       /* open identifies the local device; per DAT specification */
+       /* Get family and address then set port to consumer's ServiceID */
+       dapl_os_memcpy(&addr, &ia_ptr->hca_ptr->hca_address, sizeof(addr));
+       ((struct sockaddr_in *)&addr)->sin_port = SID_TO_PORT(ServiceID);
+
+       if (rdma_bind_addr(conn->cm_id, (struct sockaddr *)&addr)) {
+               if ((errno == EBUSY) || (errno == EADDRINUSE) || 
+                   (errno == EADDRNOTAVAIL))
+                       dat_status = DAT_CONN_QUAL_IN_USE;
+               else
+                       dat_status =
+                           dapl_convert_errno(errno, "rdma_bind_addr");
+               goto bail;
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " listen(ia_ptr %p SID 0x%llx Port %d sp %p conn %p id %d)\n",
+                    ia_ptr, ServiceID, ntohs(SID_TO_PORT(ServiceID)),
+                    sp_ptr, conn, conn->cm_id);
+
+       sp_ptr->cm_srvc_handle = conn;
+       conn->sp = sp_ptr;
+       conn->hca = ia_ptr->hca_ptr;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " listen(conn=%p cm_id=%d)\n",
+                    sp_ptr->cm_srvc_handle, conn->cm_id);
+
+       if (rdma_listen(conn->cm_id, 0)) {      /* max cma backlog */
+
+               if ((errno == EBUSY) || (errno == EADDRINUSE) ||
+                   (errno == EADDRNOTAVAIL))
+                       dat_status = DAT_CONN_QUAL_IN_USE;
+               else
+                       dat_status =
+                           dapl_convert_errno(errno, "rdma_listen");
+               goto bail;
+       }
+
+       /* success */
+       return DAT_SUCCESS;
+
+bail:
+       dapls_cm_release(conn);
+       return dat_status;
+}
+
+/*
+ * dapl_ib_remove_conn_listener
+ *
+ * Have the CM remove a connection listener.
+ *
+ * Input:
+ *     ia_handle               IA handle
+ *     ServiceID               IB Channel Service ID
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_STATE
+ *
+ */
+DAT_RETURN
+dapls_ib_remove_conn_listener(IN DAPL_IA * ia_ptr, IN DAPL_SP * sp_ptr)
+{
+       ib_cm_srvc_handle_t conn = sp_ptr->cm_srvc_handle;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " remove_listen(ia_ptr %p sp_ptr %p conn %p)\n",
+                    ia_ptr, sp_ptr, conn);
+
+       if (conn != IB_INVALID_HANDLE) {
+               sp_ptr->cm_srvc_handle = NULL;
+               dapls_cm_release(conn);
+       }
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_accept_connection
+ *
+ * Perform necessary steps to accept a connection
+ *
+ * Input:
+ *     cr_handle
+ *     ep_handle
+ *     private_data_size
+ *     private_data
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,
+                          IN DAT_EP_HANDLE ep_handle,
+                          IN DAT_COUNT p_size, IN const DAT_PVOID p_data)
+{
+       DAPL_CR *cr_ptr = (DAPL_CR *) cr_handle;
+       DAPL_EP *ep_ptr = (DAPL_EP *) ep_handle;
+       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;
+       struct dapl_cm_id *cr_conn = cr_ptr->ib_cm_handle;
+       struct dapl_cm_id *ep_conn = dapl_get_cm_from_ep(ep_ptr);
+       int ret;
+       DAT_RETURN dat_status;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " accept(cr %p conn %p, id %p, p_data %p, p_sz=%d)\n",
+                    cr_ptr, cr_conn, cr_conn->cm_id, p_data, p_size);
+
+       /* Obtain size of private data structure & contents */
+       if (p_size > IB_MAX_REP_PDATA_SIZE) {
+               dat_status = DAT_ERROR(DAT_LENGTH_ERROR, DAT_NO_SUBTYPE);
+               goto bail;
+       }
+
+       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
+               /* 
+                * If we are lazy attaching the QP then we may need to
+                * hook it up here. Typically, we run this code only for
+                * DAT_PSP_PROVIDER_FLAG
+                */
+               dat_status = dapls_ib_qp_alloc(ia_ptr, ep_ptr, NULL);
+               if (dat_status != DAT_SUCCESS) {
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                " dapl_cma_accept: qp_alloc ERR %d\n",
+                                dat_status);
+                       goto bail;
+               }
+       }
+
+       /* 
+        * Validate device and port in EP cm_id against inbound 
+        * CR cm_id. The pre-allocated EP cm_id is already bound to 
+        * a local device (cm_id and QP) when created. Move the QP
+        * to the new cm_id only if device and port numbers match.
+        */
+       if (ep_conn->cm_id->verbs == cr_conn->cm_id->verbs &&
+           ep_conn->cm_id->port_num == cr_conn->cm_id->port_num) {
+               /* move QP to new cr_conn, remove QP ref in EP cm_id */
+               cr_conn->cm_id->qp = ep_conn->cm_id->qp;
+
+               /* remove old CM to EP linking, destroy CM object */
+               dapl_ep_unlink_cm(ep_ptr, ep_conn);
+               ep_conn->cm_id->qp = NULL;
+               ep_conn->ep = NULL;
+               dapls_cm_release(ep_conn);
+
+               /* add new CM to EP linking, qp_handle unchanged */
+               dapl_ep_link_cm(ep_ptr, cr_conn);
+               cr_conn->ep = ep_ptr;
+       } else {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " dapl_cma_accept: ERR dev(%p!=%p) or"
+                        " port mismatch(%d!=%d)\n",
+                        ep_conn->cm_id->verbs, cr_conn->cm_id->verbs,
+                        ntohs(ep_conn->cm_id->port_num),
+                        ntohs(cr_conn->cm_id->port_num));
+               dat_status = DAT_INTERNAL_ERROR;
+               goto bail;
+       }
+
+       cr_ptr->param.local_ep_handle = ep_handle;
+       cr_conn->params.private_data = p_data;
+       cr_conn->params.private_data_len = p_size;
+
+       ret = rdma_accept(cr_conn->cm_id, &cr_conn->params);
+       if (ret) {
+               dapl_log(DAPL_DBG_TYPE_ERR, " dapl_rdma_accept: ERR %d %s\n",
+                        ret, strerror(errno));
+               dat_status = dapl_convert_errno(errno, "accept");
+               
+               /* remove new cr_conn EP to CM linking */
+               dapl_ep_unlink_cm(ep_ptr, cr_conn);
+               goto bail;
+       }
+
+       /* setup local and remote ports for ep query */
+       /* Note: port qual in network order */
+       ep_ptr->param.remote_port_qual =
+           PORT_TO_SID(rdma_get_dst_port(cr_conn->cm_id));
+       ep_ptr->param.local_port_qual =
+           PORT_TO_SID(rdma_get_src_port(cr_conn->cm_id));
+
+       return DAT_SUCCESS;
+bail:
+       rdma_reject(cr_conn->cm_id, NULL, 0);
+
+       /* no EP linking, ok to destroy */
+       dapls_cm_release(cr_conn);
+       return dat_status;
+}
+
+/*
+ * dapls_ib_reject_connection
+ *
+ * Reject a connection
+ *
+ * Input:
+ *     cr_handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_reject_connection(IN dp_ib_cm_handle_t cm_handle,
+                          IN int reason,
+                          IN DAT_COUNT private_data_size,
+                          IN const DAT_PVOID private_data)
+{
+       int ret;
+       int offset = sizeof(struct dapl_pdata_hdr);
+       struct dapl_pdata_hdr pdata_hdr;
+
+       memset(&pdata_hdr, 0, sizeof pdata_hdr);
+       pdata_hdr.version = htonl((DAT_VERSION_MAJOR << 24) |
+                                 (DAT_VERSION_MINOR << 16) |
+                                 (VN_PROVIDER_MAJOR << 8) |
+                                 (VN_PROVIDER_MINOR));
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " reject: handle %p reason %x, ver=%x, data %p, sz=%d\n",
+                    cm_handle, reason, ntohl(pdata_hdr.version),
+                    private_data, private_data_size);
+
+       if (cm_handle == IB_INVALID_HANDLE) {
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+                            " reject: invalid handle: reason %d\n", reason);
+               return DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CR);
+       }
+
+       /* setup pdata_hdr and users data, in CR pdata buffer */
+       dapl_os_memcpy(cm_handle->p_data, &pdata_hdr, offset);
+       if (private_data_size)
+               dapl_os_memcpy(cm_handle->p_data + offset,
+                              private_data, private_data_size);
+
+       /*
+        * Always some private data with reject so active peer can
+        * determine real application reject from an abnormal 
+        * application termination
+        */
+       ret = rdma_reject(cm_handle->cm_id,
+                         cm_handle->p_data, offset + private_data_size);
+
+       /* no EP linking, ok to destroy */
+       dapls_cm_release(cm_handle);
+       return dapl_convert_errno(ret, "reject");
+}
+
+/*
+ * dapls_ib_cm_remote_addr
+ *
+ * Obtain the remote IP address given a connection
+ *
+ * Input:
+ *     cr_handle
+ *
+ * Output:
+ *     remote_ia_address: where to place the remote address
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_HANDLE
+ *
+ */
+DAT_RETURN
+dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle, OUT DAT_SOCK_ADDR6 * raddr)
+{
+       DAPL_HEADER *header;
+       dp_ib_cm_handle_t conn;
+       struct rdma_addr *ipaddr;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " remote_addr(cm_handle=%p, r_addr=%p)\n",
+                    dat_handle, raddr);
+
+       header = (DAPL_HEADER *) dat_handle;
+
+       if (header->magic == DAPL_MAGIC_EP) 
+               conn = dapl_get_cm_from_ep((DAPL_EP *) dat_handle);
+       else if (header->magic == DAPL_MAGIC_CR)
+               conn = ((DAPL_CR *) dat_handle)->ib_cm_handle;
+       else
+               return DAT_INVALID_HANDLE;
+
+       /* get remote IP address from cm_id route */
+       ipaddr = &conn->cm_id->route.addr;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " remote_addr: conn %p id %p SRC %x DST %x PORT %d\n",
+                    conn, conn->cm_id,
+                    ntohl(((struct sockaddr_in *)
+                           &ipaddr->src_addr)->sin_addr.s_addr),
+                    ntohl(((struct sockaddr_in *)
+                           &ipaddr->dst_addr)->sin_addr.s_addr),
+                    ntohs(((struct sockaddr_in *)
+                           &ipaddr->dst_addr)->sin_port));
+
+       dapl_os_memcpy(raddr, &ipaddr->dst_addr, sizeof(DAT_SOCK_ADDR));
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_private_data_size
+ *
+ * Return the size of max private data 
+ *
+ * Input:
+ *      hca_ptr         hca pointer, needed for transport type
+ *
+ * Output:
+ *     None
+ *
+ * Returns:
+ *     maximum private data rdma_cm will supply from transport.
+ *
+ */
+int dapls_ib_private_data_size(IN DAPL_HCA * hca_ptr)
+{
+       return RDMA_MAX_PRIVATE_DATA;
+}
+
+void dapli_cma_event_cb(void)
+{
+       struct rdma_cm_event *event;
+                               
+       /* process one CM event, fairness, non-blocking */
+       if (!rdma_get_cm_event(g_cm_events, &event)) {
+               struct dapl_cm_id *conn;
+
+               /* set proper conn from cm_id context */
+               if (event->event == RDMA_CM_EVENT_CONNECT_REQUEST)
+                       conn = (struct dapl_cm_id *)event->listen_id->context;
+               else
+                       conn = (struct dapl_cm_id *)event->id->context;
+
+               dapls_cm_acquire(conn);
+               
+               dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                            " cm_event: EVENT=%d ID=%p LID=%p CTX=%p\n",
+                            event->event, event->id, event->listen_id, conn);
+               
+               switch (event->event) {
+               case RDMA_CM_EVENT_ADDR_RESOLVED:
+                       dapli_addr_resolve(conn);
+                       break;
+
+               case RDMA_CM_EVENT_ROUTE_RESOLVED:
+                       dapli_route_resolve(conn);
+                       break;
+
+               case RDMA_CM_EVENT_ADDR_ERROR:
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                "dapl_cma_active: CM ADDR ERROR: ->"
+                                " DST %s retry (%d)..\n",
+                                inet_ntoa(((struct sockaddr_in *)
+                                           &conn->r_addr)->sin_addr),
+                                conn->arp_retries);
+
+                       /* retry address resolution */
+                       if ((--conn->arp_retries) &&
+                           (event->status == -ETIMEDOUT)) {
+                               int ret;
+                               ret = rdma_resolve_addr(conn->cm_id, NULL,
+                                                       (struct sockaddr *)
+                                                       &conn->r_addr,
+                                                       conn->arp_timeout);
+                               if (!ret)
+                                       break;
+                               else {
+                                       dapl_dbg_log(DAPL_DBG_TYPE_WARN,
+                                                    " ERROR: rdma_resolve_addr = "
+                                                    "%d %s\n",
+                                                    ret, strerror(errno));
+                               }
+                       }
+                       /* retries exhausted or resolve_addr failed */
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                "dapl_cma_active: ARP_ERR, retries(%d)"
+                                " exhausted -> DST %s,%d\n",
+                                IB_ARP_RETRY_COUNT,
+                                inet_ntoa(((struct sockaddr_in *)
+                                           &conn->cm_id->route.addr.dst_addr)->
+                                          sin_addr),
+                                ntohs(((struct sockaddr_in *)
+                                       &conn->cm_id->route.addr.dst_addr)->
+                                      sin_port));
+
+                       dapl_evd_connection_callback(conn,
+                                                    IB_CME_DESTINATION_UNREACHABLE,
+                                                    NULL, 0, conn->ep);
+                       break;
+
+               case RDMA_CM_EVENT_ROUTE_ERROR:
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                "dapl_cma_active: CM ROUTE ERROR: ->"
+                                " DST %s retry (%d)..\n",
+                                inet_ntoa(((struct sockaddr_in *)
+                                           &conn->r_addr)->sin_addr),
+                                conn->route_retries);
+
+                       /* retry route resolution */
+                       if ((--conn->route_retries) &&
+                           (event->status == -ETIMEDOUT))
+                               dapli_addr_resolve(conn);
+                       else {
+                               dapl_log(DAPL_DBG_TYPE_ERR,
+                                        "dapl_cma_active: PATH_RECORD_ERR,"
+                                        " retries(%d) exhausted, DST %s,%d\n",
+                                        IB_ROUTE_RETRY_COUNT,
+                                        inet_ntoa(((struct sockaddr_in *)
+                                                   &conn->cm_id->route.addr.
+                                                   dst_addr)->sin_addr),
+                                        ntohs(((struct sockaddr_in *)
+                                               &conn->cm_id->route.addr.
+                                               dst_addr)->sin_port));
+
+                               dapl_evd_connection_callback(conn,
+                                                            IB_CME_DESTINATION_UNREACHABLE,
+                                                            NULL, 0, conn->ep);
+                       }
+                       break;
+
+               case RDMA_CM_EVENT_DEVICE_REMOVAL:
+                       dapl_evd_connection_callback(conn,
+                                                    IB_CME_LOCAL_FAILURE,
+                                                    NULL, 0, conn->ep);
+                       break;
+               case RDMA_CM_EVENT_CONNECT_REQUEST:
+               case RDMA_CM_EVENT_CONNECT_ERROR:
+               case RDMA_CM_EVENT_UNREACHABLE:
+               case RDMA_CM_EVENT_REJECTED:
+               case RDMA_CM_EVENT_ESTABLISHED:
+               case RDMA_CM_EVENT_DISCONNECTED:
+                       /* passive or active */
+                       if (conn->sp)
+                               dapli_cm_passive_cb(conn, event);
+                       else
+                               dapli_cm_active_cb(conn, event);
+                       break;
+               case RDMA_CM_EVENT_CONNECT_RESPONSE:
+#ifdef RDMA_CM_EVENT_TIMEWAIT_EXIT
+               case RDMA_CM_EVENT_TIMEWAIT_EXIT:
+#endif
+                       break;
+               default:
+                       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                                    " cm_event: UNEXPECTED EVENT=%p ID=%p CTX=%p\n",
+                                    event->event, event->id,
+                                    event->id->context);
+                       break;
+               }
+               
+               /* ack event, unblocks destroy_cm_id in consumer threads */
+               rdma_ack_cm_event(event);
+                dapls_cm_release(conn);
+       } 
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
index 309db536f0ec6d3dc261bf75a2d6a9b4ff0c8525..96061b3a80cdd88165e272464552eee37e1cf98b 100644 (file)
@@ -33,7 +33,6 @@
 #define _OPENIB_CMA_ 
 
 #include <infiniband/verbs.h>
-#include <rdma/rdma_cma.h>
 #include "openib_osd.h"
 #include "dapl_ib_common.h"
 
 #define IB_ROUTE_RETRY_COUNT   15      /* 60 sec total */
 #define IB_MAX_AT_RETRY                3
 
-/* CMA private data areas */
+/* CMA private data areas, use CMA max with known transport definitions */
 #define CMA_PDATA_HDR          36
-#define        IB_MAX_REQ_PDATA_SIZE   (92-CMA_PDATA_HDR)
-#define        IB_MAX_REP_PDATA_SIZE   (196-CMA_PDATA_HDR)
-#define        IB_MAX_REJ_PDATA_SIZE   (148-CMA_PDATA_HDR)
-#define        IB_MAX_DREQ_PDATA_SIZE  (220-CMA_PDATA_HDR)
-#define        IB_MAX_DREP_PDATA_SIZE  (224-CMA_PDATA_HDR)
-#define        IWARP_MAX_PDATA_SIZE    (512-CMA_PDATA_HDR)
+#define        IB_MAX_REQ_PDATA_SIZE   DAPL_MIN((92-CMA_PDATA_HDR),RDMA_MAX_PRIVATE_DATA)
+#define        IB_MAX_REP_PDATA_SIZE   DAPL_MIN((196-CMA_PDATA_HDR),RDMA_MAX_PRIVATE_DATA)
+#define        IB_MAX_REJ_PDATA_SIZE   DAPL_MIN((148-CMA_PDATA_HDR),RDMA_MAX_PRIVATE_DATA)
+#define        IB_MAX_DREQ_PDATA_SIZE  DAPL_MIN((220-CMA_PDATA_HDR),RDMA_MAX_PRIVATE_DATA)
+#define        IB_MAX_DREP_PDATA_SIZE  DAPL_MIN((224-CMA_PDATA_HDR),RDMA_MAX_PRIVATE_DATA)
+#define        IWARP_MAX_PDATA_SIZE    DAPL_MIN((512-CMA_PDATA_HDR),RDMA_MAX_PRIVATE_DATA)
 
+/* DAPL CM objects MUST include list_entry, ref_count, event for EP linking */
 struct dapl_cm_id {
+       struct dapl_llist_entry         list_entry;
+       struct dapl_llist_entry         local_entry;
+       DAPL_OS_WAIT_OBJECT             event;
        DAPL_OS_LOCK                    lock;
-       int                             refs;
+       int                             ref_count;
        int                             arp_retries;
        int                             arp_timeout;
        int                             route_retries;
        int                             route_timeout;
-       int                             in_callback;
        struct rdma_cm_id               *cm_id;
        struct dapl_hca                 *hca;
        struct dapl_sp                  *sp;
@@ -122,11 +124,15 @@ void dapli_cma_event_cb(void);
 void dapli_async_event_cb(struct _ib_hca_transport *tp);
 void dapli_cq_event_cb(struct _ib_hca_transport *tp);
 dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep);
-void dapls_ib_cm_free(dp_ib_cm_handle_t cm, DAPL_EP *ep);
+void dapls_cm_acquire(dp_ib_cm_handle_t cm);
+void dapls_cm_release(dp_ib_cm_handle_t cm);
+void dapls_cm_free(dp_ib_cm_handle_t cm_ptr);
 
+#ifdef DAPL_COUNTERS
 STATIC _INLINE_ void dapls_print_cm_list(IN DAPL_IA * ia_ptr)
 {
        return;
 }
+#endif
 
 #endif /*  _DAPL_IB_UTIL_H_ */
index c9d3756d71fc65b5af25680c96714e5e93f60855..12593cf4b38b92a0f038235dd844c2f8e874c726 100644 (file)
-/*\r
- * Copyright (c) 2005-2008 Intel Corporation.  All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/**********************************************************************\r
- * \r
- * MODULE: dapl_ib_util.c\r
- *\r
- * PURPOSE: OFED provider - init, open, close, utilities, work thread\r
- *\r
- * $Id:$\r
- *\r
- **********************************************************************/\r
-\r
-#ifdef RCSID\r
-static const char rcsid[] = "$Id:  $";\r
-#endif\r
-\r
-#include "openib_osd.h"\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_ib_util.h"\r
-#include "dapl_osd.h"\r
-\r
-#include <stdlib.h>\r
-\r
-struct rdma_event_channel *g_cm_events = NULL;\r
-ib_thread_state_t g_ib_thread_state = 0;\r
-DAPL_OS_THREAD g_ib_thread;\r
-DAPL_OS_LOCK g_hca_lock;\r
-struct dapl_llist_entry *g_hca_list;\r
-\r
-#if defined(_WIN64) || defined(_WIN32)\r
-#include "..\..\..\..\..\etc\user\comp_channel.cpp"\r
-#include <rdma\winverbs.h>\r
-\r
-static COMP_SET ufds;\r
-\r
-static int getipaddr_netdev(char *name, char *addr, int addr_len)\r
-{\r
-       IWVProvider *prov;\r
-       WV_DEVICE_ADDRESS devaddr;\r
-       struct addrinfo *res, *ai;\r
-       HRESULT hr;\r
-       int index;\r
-\r
-       if (strncmp(name, "rdma_dev", 8)) {\r
-               return EINVAL;\r
-       }\r
-\r
-       index = atoi(name + 8);\r
-\r
-       hr = WvGetObject(&IID_IWVProvider, (LPVOID *) &prov);\r
-       if (FAILED(hr)) {\r
-               return hr;\r
-       }\r
-\r
-       hr = getaddrinfo("..localmachine", NULL, NULL, &res);\r
-       if (hr) {\r
-               goto release;\r
-       }\r
-\r
-       for (ai = res; ai; ai = ai->ai_next) {\r
-               hr = prov->lpVtbl->TranslateAddress(prov, ai->ai_addr, &devaddr);\r
-               if (SUCCEEDED(hr) && (ai->ai_addrlen <= addr_len) && (index-- == 0)) {\r
-                       memcpy(addr, ai->ai_addr, ai->ai_addrlen);\r
-                       goto free;\r
-               }\r
-       }\r
-       hr = ENODEV;\r
-\r
-free:\r
-       freeaddrinfo(res);\r
-release:\r
-       prov->lpVtbl->Release(prov);\r
-       return hr;\r
-}\r
-\r
-static int dapls_os_init(void)\r
-{\r
-       return CompSetInit(&ufds);\r
-}\r
-\r
-static void dapls_os_release(void)\r
-{\r
-       CompSetCleanup(&ufds);\r
-}\r
-\r
-static int dapls_config_cm_channel(struct rdma_event_channel *channel)\r
-{\r
-       channel->channel.Milliseconds = 0;\r
-       return 0;\r
-}\r
-\r
-static int dapls_config_verbs(struct ibv_context *verbs)\r
-{\r
-       verbs->channel.Milliseconds = 0;\r
-       return 0;\r
-}\r
-\r
-static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
-{\r
-       channel->comp_channel.Milliseconds = 0;\r
-       return 0;\r
-}\r
-\r
-static int dapls_thread_signal(void)\r
-{\r
-       CompSetCancel(&ufds);\r
-       return 0;\r
-}\r
-#else                          // _WIN64 || WIN32\r
-int g_ib_pipe[2];\r
-\r
-static int dapls_os_init(void)\r
-{\r
-       /* create pipe for waking up work thread */\r
-       return pipe(g_ib_pipe);\r
-}\r
-\r
-static void dapls_os_release(void)\r
-{\r
-       /* close pipe? */\r
-}\r
-\r
-/* Get IP address using network device name */\r
-static int getipaddr_netdev(char *name, char *addr, int addr_len)\r
-{\r
-       struct ifreq ifr;\r
-       int skfd, ret, len;\r
-\r
-       /* Fill in the structure */\r
-       snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name);\r
-       ifr.ifr_hwaddr.sa_family = ARPHRD_INFINIBAND;\r
-\r
-       /* Create a socket fd */\r
-       skfd = socket(PF_INET, SOCK_STREAM, 0);\r
-       ret = ioctl(skfd, SIOCGIFADDR, &ifr);\r
-       if (ret)\r
-               goto bail;\r
-\r
-       switch (ifr.ifr_addr.sa_family) {\r
-#ifdef AF_INET6\r
-       case AF_INET6:\r
-               len = sizeof(struct sockaddr_in6);\r
-               break;\r
-#endif\r
-       case AF_INET:\r
-       default:\r
-               len = sizeof(struct sockaddr);\r
-               break;\r
-       }\r
-\r
-       if (len <= addr_len)\r
-               memcpy(addr, &ifr.ifr_addr, len);\r
-       else\r
-               ret = EINVAL;\r
-\r
-      bail:\r
-       close(skfd);\r
-       return ret;\r
-}\r
-\r
-static int dapls_config_fd(int fd)\r
-{\r
-       int opts;\r
-\r
-       opts = fcntl(fd, F_GETFL);\r
-       if (opts < 0 || fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " dapls_config_fd: fcntl on fd %d ERR %d %s\n",\r
-                        fd, opts, strerror(errno));\r
-               return errno;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-static int dapls_config_cm_channel(struct rdma_event_channel *channel)\r
-{\r
-       return dapls_config_fd(channel->fd);\r
-}\r
-\r
-static int dapls_config_verbs(struct ibv_context *verbs)\r
-{\r
-       return dapls_config_fd(verbs->async_fd);\r
-}\r
-\r
-static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
-{\r
-       return dapls_config_fd(channel->fd);\r
-}\r
-\r
-static int dapls_thread_signal(void)\r
-{\r
-       return write(g_ib_pipe[1], "w", sizeof "w");\r
-}\r
-#endif\r
-\r
-/* Get IP address using network name, address, or device name */\r
-static int getipaddr(char *name, char *addr, int len)\r
-{\r
-       struct addrinfo *res;\r
-\r
-       /* assume netdev for first attempt, then network and address type */\r
-       if (getipaddr_netdev(name, addr, len)) {\r
-               if (getaddrinfo(name, NULL, NULL, &res)) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                " open_hca: getaddr_netdev ERROR:"\r
-                                " %s. Is %s configured?\n",\r
-                                strerror(errno), name);\r
-                       return 1;\r
-               } else {\r
-                       if (len >= res->ai_addrlen)\r
-                               memcpy(addr, res->ai_addr, res->ai_addrlen);\r
-                       else {\r
-                               freeaddrinfo(res);\r
-                               return 1;\r
-                       }\r
-                       freeaddrinfo(res);\r
-               }\r
-       }\r
-\r
-       dapl_dbg_log(\r
-               DAPL_DBG_TYPE_UTIL,\r
-               " getipaddr: family %d port %d addr %d.%d.%d.%d\n",\r
-               ((struct sockaddr_in *)addr)->sin_family,\r
-               ((struct sockaddr_in *)addr)->sin_port,\r
-               ((struct sockaddr_in *)addr)->sin_addr.s_addr >> 0 & 0xff,\r
-               ((struct sockaddr_in *)addr)->sin_addr.s_addr >> 8 & 0xff,\r
-               ((struct sockaddr_in *)addr)->sin_addr.s_addr >> 16 & 0xff,\r
-               ((struct sockaddr_in *)addr)->sin_addr.\r
-                s_addr >> 24 & 0xff);\r
-\r
-       return 0;\r
-}\r
-\r
-/*\r
- * dapls_ib_init, dapls_ib_release\r
- *\r
- * Initialize Verb related items for device open\r
- *\r
- * Input:\r
- *     none\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     0 success, -1 error\r
- *\r
- */\r
-int32_t dapls_ib_init(void)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " dapl_ib_init: \n");\r
-\r
-       /* initialize hca_list lock */\r
-       dapl_os_lock_init(&g_hca_lock);\r
-\r
-       /* initialize hca list for CQ events */\r
-       dapl_llist_init_head(&g_hca_list);\r
-\r
-       if (dapls_os_init())\r
-               return 1;\r
-\r
-       return 0;\r
-}\r
-\r
-int32_t dapls_ib_release(void)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " dapl_ib_release: \n");\r
-       dapli_ib_thread_destroy();\r
-       if (g_cm_events != NULL)\r
-               rdma_destroy_event_channel(g_cm_events);\r
-       dapls_os_release();\r
-       return 0;\r
-}\r
-\r
-/*\r
- * dapls_ib_open_hca\r
- *\r
- * Open HCA\r
- *\r
- * Input:\r
- *      *hca_name         pointer to provider device name\r
- *      *ib_hca_handle_p  pointer to provide HCA handle\r
- *\r
- * Output:\r
- *      none\r
- *\r
- * Return:\r
- *      DAT_SUCCESS\r
- *      dapl_convert_errno\r
- *\r
- */\r
-DAT_RETURN dapls_ib_open_hca(IN IB_HCA_NAME hca_name, IN DAPL_HCA * hca_ptr)\r
-{\r
-       struct rdma_cm_id *cm_id = NULL;\r
-       union ibv_gid *gid;\r
-       int ret;\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: %s - %p\n", hca_name, hca_ptr);\r
-\r
-       /* Setup the global cm event channel */\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_cm_events == NULL) {\r
-               g_cm_events = rdma_create_event_channel();\r
-               if (g_cm_events == NULL) {\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
-                                    " open_hca: ERR - RDMA channel %s\n",\r
-                                    strerror(errno));\r
-                       dapl_os_unlock(&g_hca_lock);\r
-                       return DAT_INTERNAL_ERROR;\r
-               }\r
-       }\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: RDMA channel created (%p)\n", g_cm_events);\r
-\r
-       /* HCA name will be hostname or IP address */\r
-       if (getipaddr((char *)hca_name,\r
-                     (char *)&hca_ptr->hca_address, \r
-                     sizeof(DAT_SOCK_ADDR6)))\r
-               return DAT_INVALID_ADDRESS;\r
-\r
-       /* cm_id will bind local device/GID based on IP address */\r
-       if (rdma_create_id(g_cm_events, &cm_id, \r
-                          (void *)hca_ptr, RDMA_PS_TCP)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: rdma_create ERR %s\n", strerror(errno));\r
-               return DAT_INTERNAL_ERROR;\r
-       }\r
-       ret = rdma_bind_addr(cm_id, (struct sockaddr *)&hca_ptr->hca_address);\r
-       if ((ret) || (cm_id->verbs == NULL)) {\r
-               rdma_destroy_id(cm_id);\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: rdma_bind ERR %s."\r
-                        " Is %s configured?\n", strerror(errno), hca_name);\r
-               rdma_destroy_id(cm_id);\r
-               return DAT_INVALID_ADDRESS;\r
-       }\r
-\r
-       /* keep reference to IB device and cm_id */\r
-       hca_ptr->ib_trans.cm_id = cm_id;\r
-       hca_ptr->ib_hca_handle = cm_id->verbs;\r
-       dapls_config_verbs(cm_id->verbs);\r
-       hca_ptr->port_num = cm_id->port_num;\r
-       hca_ptr->ib_trans.ib_dev = cm_id->verbs->device;\r
-       hca_ptr->ib_trans.ib_ctx = cm_id->verbs;\r
-       gid = &cm_id->route.addr.addr.ibaddr.sgid;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: ctx=%p port=%d GID subnet %016llx"\r
-                    " id %016llx\n", cm_id->verbs, cm_id->port_num,\r
-                    (unsigned long long)ntohll(gid->global.subnet_prefix),\r
-                    (unsigned long long)ntohll(gid->global.interface_id));\r
-\r
-       /* support for EVD's with CNO's: one channel via thread */\r
-       hca_ptr->ib_trans.ib_cq =\r
-           ibv_create_comp_channel(hca_ptr->ib_hca_handle);\r
-       if (hca_ptr->ib_trans.ib_cq == NULL) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: ibv_create_comp_channel ERR %s\n",\r
-                        strerror(errno));\r
-               rdma_destroy_id(cm_id);\r
-               return DAT_INTERNAL_ERROR;\r
-       }\r
-       if (dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq)) {\r
-               rdma_destroy_id(cm_id);\r
-               return DAT_INTERNAL_ERROR;\r
-       }\r
-\r
-       /* set inline max with env or default, get local lid and gid 0 */\r
-       if (hca_ptr->ib_hca_handle->device->transport_type\r
-           == IBV_TRANSPORT_IWARP)\r
-               hca_ptr->ib_trans.max_inline_send =\r
-                   dapl_os_get_env_val("DAPL_MAX_INLINE",\r
-                                       INLINE_SEND_IWARP_DEFAULT);\r
-       else\r
-               hca_ptr->ib_trans.max_inline_send =\r
-                   dapl_os_get_env_val("DAPL_MAX_INLINE",\r
-                                       INLINE_SEND_IB_DEFAULT);\r
-\r
-       /* set CM timer defaults */\r
-       hca_ptr->ib_trans.max_cm_timeout =\r
-           dapl_os_get_env_val("DAPL_MAX_CM_RESPONSE_TIME",\r
-                               IB_CM_RESPONSE_TIMEOUT);\r
-       hca_ptr->ib_trans.max_cm_retries =\r
-           dapl_os_get_env_val("DAPL_MAX_CM_RETRIES", IB_CM_RETRIES);\r
-       \r
-       /* set default IB MTU */\r
-       hca_ptr->ib_trans.mtu = dapl_ib_mtu(2048);\r
-\r
-       dat_status = dapli_ib_thread_init();\r
-       if (dat_status != DAT_SUCCESS)\r
-               return dat_status;\r
-       /* \r
-        * Put new hca_transport on list for async and CQ event processing \r
-        * Wakeup work thread to add to polling list\r
-        */\r
-       dapl_llist_init_entry((DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry);\r
-       dapl_os_lock(&g_hca_lock);\r
-       dapl_llist_add_tail(&g_hca_list,\r
-                           (DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry,\r
-                           &hca_ptr->ib_trans.entry);\r
-       if (dapls_thread_signal() == -1)\r
-               dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                        " open_hca: thread wakeup error = %s\n",\r
-                        strerror(errno));\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: %s, %s %d.%d.%d.%d INLINE_MAX=%d\n", hca_name,\r
-                    ((struct sockaddr_in *)\r
-                    &hca_ptr->hca_address)->sin_family == AF_INET ?\r
-                    "AF_INET" : "AF_INET6", \r
-                    ((struct sockaddr_in *)\r
-                    &hca_ptr->hca_address)->sin_addr.s_addr >> 0 & 0xff, \r
-                    ((struct sockaddr_in *)\r
-                    &hca_ptr->hca_address)->sin_addr.s_addr >> 8 & 0xff, \r
-                    ((struct sockaddr_in *)\r
-                    &hca_ptr->hca_address)->sin_addr.s_addr >> 16 & 0xff, \r
-                    ((struct sockaddr_in *)\r
-                    &hca_ptr->hca_address)->sin_addr.s_addr >> 24 & 0xff, \r
-                    hca_ptr->ib_trans.max_inline_send);\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_close_hca\r
- *\r
- * Open HCA\r
- *\r
- * Input:\r
- *      DAPL_HCA   provide CA handle\r
- *\r
- * Output:\r
- *      none\r
- *\r
- * Return:\r
- *      DAT_SUCCESS\r
- *     dapl_convert_errno \r
- *\r
- */\r
-DAT_RETURN dapls_ib_close_hca(IN DAPL_HCA * hca_ptr)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " close_hca: %p->%p\n",\r
-                    hca_ptr, hca_ptr->ib_hca_handle);\r
-\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_ib_thread_state != IB_THREAD_RUN) {\r
-               dapl_os_unlock(&g_hca_lock);\r
-               goto bail;\r
-       }\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       /* \r
-        * Remove hca from async event processing list\r
-        * Wakeup work thread to remove from polling list\r
-        */\r
-       hca_ptr->ib_trans.destroy = 1;\r
-       if (dapls_thread_signal() == -1)\r
-               dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                        " destroy: thread wakeup error = %s\n",\r
-                        strerror(errno));\r
-\r
-       /* wait for thread to remove HCA references */\r
-       while (hca_ptr->ib_trans.destroy != 2) {\r
-               if (dapls_thread_signal() == -1)\r
-                       dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                                " destroy: thread wakeup error = %s\n",\r
-                                strerror(errno));\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread_destroy: wait on hca %p destroy\n");\r
-               dapl_os_sleep_usec(1000);\r
-       }\r
-bail:\r
-       if (hca_ptr->ib_trans.ib_cq)\r
-               ibv_destroy_comp_channel(hca_ptr->ib_trans.ib_cq);\r
-\r
-       if (hca_ptr->ib_trans.ib_cq_empty) {\r
-               struct ibv_comp_channel *channel;\r
-               channel = hca_ptr->ib_trans.ib_cq_empty->channel;\r
-               ibv_destroy_cq(hca_ptr->ib_trans.ib_cq_empty);\r
-               ibv_destroy_comp_channel(channel);\r
-       }\r
-\r
-       if (hca_ptr->ib_hca_handle != IB_INVALID_HANDLE) {\r
-               if (rdma_destroy_id(hca_ptr->ib_trans.cm_id))\r
-                       return (dapl_convert_errno(errno, "ib_close_device"));\r
-               hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;\r
-       }\r
-\r
-       return (DAT_SUCCESS);\r
-}\r
-\r
-\r
-DAT_RETURN dapli_ib_thread_init(void)\r
-{\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " ib_thread_init(%d)\n", dapl_os_getpid());\r
-\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_ib_thread_state != IB_THREAD_INIT) {\r
-               dapl_os_unlock(&g_hca_lock);\r
-               return DAT_SUCCESS;\r
-       }\r
-\r
-       /* uCMA events non-blocking */\r
-       if (dapls_config_cm_channel(g_cm_events)) {\r
-               dapl_os_unlock(&g_hca_lock);\r
-               return (dapl_convert_errno(errno, "create_thread ERR: cm_fd"));\r
-       }\r
-\r
-       g_ib_thread_state = IB_THREAD_CREATE;\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       /* create thread to process inbound connect request */\r
-       dat_status = dapl_os_thread_create(dapli_thread, NULL, &g_ib_thread);\r
-       if (dat_status != DAT_SUCCESS)\r
-               return (dapl_convert_errno(errno,\r
-                                          "create_thread ERR:"\r
-                                          " check resource limits"));\r
-\r
-       /* wait for thread to start */\r
-       dapl_os_lock(&g_hca_lock);\r
-       while (g_ib_thread_state != IB_THREAD_RUN) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread_init: waiting for ib_thread\n");\r
-               dapl_os_unlock(&g_hca_lock);\r
-               dapl_os_sleep_usec(1000);\r
-               dapl_os_lock(&g_hca_lock);\r
-       }\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " ib_thread_init(%d) exit\n", dapl_os_getpid());\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-void dapli_ib_thread_destroy(void)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " ib_thread_destroy(%d)\n", dapl_os_getpid());\r
-       /* \r
-        * wait for async thread to terminate. \r
-        * pthread_join would be the correct method\r
-        * but some applications have some issues\r
-        */\r
-\r
-       /* destroy ib_thread, wait for termination, if not already */\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_ib_thread_state != IB_THREAD_RUN)\r
-               goto bail;\r
-\r
-       g_ib_thread_state = IB_THREAD_CANCEL;\r
-       while ((g_ib_thread_state != IB_THREAD_EXIT)) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread_destroy: waiting for ib_thread\n");\r
-               if (dapls_thread_signal() == -1)\r
-                       dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                                " destroy: thread wakeup error = %s\n",\r
-                                strerror(errno));\r
-               dapl_os_unlock(&g_hca_lock);\r
-               dapl_os_sleep_usec(2000);\r
-               dapl_os_lock(&g_hca_lock);\r
-       }\r
-bail:\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " ib_thread_destroy(%d) exit\n", dapl_os_getpid());\r
-}\r
-\r
-#if defined(_WIN64) || defined(_WIN32)\r
-/* work thread for uAT, uCM, CQ, and async events */\r
-void dapli_thread(void *arg)\r
-{\r
-       struct _ib_hca_transport *hca;\r
-       struct _ib_hca_transport *uhca[8];\r
-       COMP_CHANNEL *channel;\r
-       int ret, idx, cnt;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d,0x%x): ENTER: \n",\r
-                    dapl_os_getpid(), g_ib_thread);\r
-\r
-       dapl_os_lock(&g_hca_lock);\r
-       for (g_ib_thread_state = IB_THREAD_RUN;\r
-            g_ib_thread_state == IB_THREAD_RUN; \r
-            dapl_os_lock(&g_hca_lock)) {\r
-\r
-               CompSetZero(&ufds);\r
-               CompSetAdd(&g_cm_events->channel, &ufds);\r
-\r
-               idx = 0;\r
-               hca = dapl_llist_is_empty(&g_hca_list) ? NULL :\r
-                     dapl_llist_peek_head(&g_hca_list);\r
-\r
-               while (hca) {\r
-                       CompSetAdd(&hca->ib_ctx->channel, &ufds);\r
-                       CompSetAdd(&hca->ib_cq->comp_channel, &ufds);\r
-                       uhca[idx++] = hca;\r
-                       hca = dapl_llist_next_entry(&g_hca_list,\r
-                                                   (DAPL_LLIST_ENTRY *)\r
-                                                   &hca->entry);\r
-               }\r
-               cnt = idx;\r
-\r
-               dapl_os_unlock(&g_hca_lock);\r
-               ret = CompSetPoll(&ufds, INFINITE);\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread(%d) poll_event 0x%x\n",\r
-                            dapl_os_getpid(), ret);\r
-\r
-               dapli_cma_event_cb();\r
-\r
-               /* check and process ASYNC events, per device */\r
-               for (idx = 0; idx < cnt; idx++) {\r
-                       if (uhca[idx]->destroy == 1) {\r
-                               dapl_os_lock(&g_hca_lock);\r
-                               dapl_llist_remove_entry(&g_hca_list,\r
-                                                       (DAPL_LLIST_ENTRY *)\r
-                                                       &uhca[idx]->entry);\r
-                               dapl_os_unlock(&g_hca_lock);\r
-                               uhca[idx]->destroy = 2;\r
-                       } else {\r
-                               dapli_cq_event_cb(uhca[idx]);\r
-                               dapli_async_event_cb(uhca[idx]);\r
-                       }\r
-               }\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d) EXIT\n",\r
-                    dapl_os_getpid());\r
-       g_ib_thread_state = IB_THREAD_EXIT;\r
-       dapl_os_unlock(&g_hca_lock);\r
-}\r
-#else                          // _WIN64 || WIN32\r
-\r
-/* work thread for uAT, uCM, CQ, and async events */\r
-void dapli_thread(void *arg)\r
-{\r
-       struct pollfd ufds[__FD_SETSIZE];\r
-       struct _ib_hca_transport *uhca[__FD_SETSIZE] = { NULL };\r
-       struct _ib_hca_transport *hca;\r
-       int ret, idx, fds;\r
-       char rbuf[2];\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                    " ib_thread(%d,0x%x): ENTER: pipe %d ucma %d\n",\r
-                    dapl_os_getpid(), g_ib_thread, g_ib_pipe[0],\r
-                    g_cm_events->fd);\r
-\r
-       /* Poll across pipe, CM, AT never changes */\r
-       dapl_os_lock(&g_hca_lock);\r
-       g_ib_thread_state = IB_THREAD_RUN;\r
-\r
-       ufds[0].fd = g_ib_pipe[0];      /* pipe */\r
-       ufds[0].events = POLLIN;\r
-       ufds[1].fd = g_cm_events->fd;   /* uCMA */\r
-       ufds[1].events = POLLIN;\r
-\r
-       while (g_ib_thread_state == IB_THREAD_RUN) {\r
-\r
-               /* build ufds after pipe and uCMA events */\r
-               ufds[0].revents = 0;\r
-               ufds[1].revents = 0;\r
-               idx = 1;\r
-\r
-               /*  Walk HCA list and setup async and CQ events */\r
-               if (!dapl_llist_is_empty(&g_hca_list))\r
-                       hca = dapl_llist_peek_head(&g_hca_list);\r
-               else\r
-                       hca = NULL;\r
-\r
-               while (hca) {\r
-\r
-                       /* uASYNC events */\r
-                       ufds[++idx].fd = hca->ib_ctx->async_fd;\r
-                       ufds[idx].events = POLLIN;\r
-                       ufds[idx].revents = 0;\r
-                       uhca[idx] = hca;\r
-\r
-                       /* CQ events are non-direct with CNO's */\r
-                       ufds[++idx].fd = hca->ib_cq->fd;\r
-                       ufds[idx].events = POLLIN;\r
-                       ufds[idx].revents = 0;\r
-                       uhca[idx] = hca;\r
-\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                                    " ib_thread(%d) poll_fd: hca[%d]=%p,"\r
-                                    " async=%d pipe=%d cm=%d \n",\r
-                                    dapl_os_getpid(), hca, ufds[idx - 1].fd,\r
-                                    ufds[0].fd, ufds[1].fd);\r
-\r
-                       hca = dapl_llist_next_entry(&g_hca_list,\r
-                                                   (DAPL_LLIST_ENTRY *)\r
-                                                   &hca->entry);\r
-               }\r
-\r
-               /* unlock, and setup poll */\r
-               fds = idx + 1;\r
-               dapl_os_unlock(&g_hca_lock);\r
-               ret = poll(ufds, fds, -1);\r
-               if (ret <= 0) {\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                                    " ib_thread(%d): ERR %s poll\n",\r
-                                    dapl_os_getpid(), strerror(errno));\r
-                       dapl_os_lock(&g_hca_lock);\r
-                       continue;\r
-               }\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                            " ib_thread(%d) poll_event: "\r
-                            " async=0x%x pipe=0x%x cm=0x%x \n",\r
-                            dapl_os_getpid(), ufds[idx].revents,\r
-                            ufds[0].revents, ufds[1].revents);\r
-\r
-               /* uCMA events */\r
-               if (ufds[1].revents == POLLIN)\r
-                       dapli_cma_event_cb();\r
-\r
-               /* check and process CQ and ASYNC events, per device */\r
-               for (idx = 2; idx < fds; idx++) {\r
-                       if (ufds[idx].revents == POLLIN) {\r
-                               dapli_cq_event_cb(uhca[idx]);\r
-                               dapli_async_event_cb(uhca[idx]);\r
-                       }\r
-               }\r
-\r
-               /* check and process user events, PIPE */\r
-               if (ufds[0].revents == POLLIN) {\r
-                       if (read(g_ib_pipe[0], rbuf, 2) == -1)\r
-                               dapl_log(DAPL_DBG_TYPE_THREAD,\r
-                                        " cr_thread: pipe rd err= %s\n",\r
-                                        strerror(errno));\r
-\r
-                       /* cleanup any device on list marked for destroy */\r
-                       for (idx = 3; idx < fds; idx++) {\r
-                               if (uhca[idx] && uhca[idx]->destroy == 1) {\r
-                                       dapl_os_lock(&g_hca_lock);\r
-                                       dapl_llist_remove_entry(\r
-                                               &g_hca_list,\r
-                                               (DAPL_LLIST_ENTRY*)\r
-                                               &uhca[idx]->entry);\r
-                                       dapl_os_unlock(&g_hca_lock);\r
-                                       uhca[idx]->destroy = 2;\r
-                               }\r
-                       }\r
-               }\r
-               dapl_os_lock(&g_hca_lock);\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " ib_thread(%d) EXIT\n",\r
-                    dapl_os_getpid());\r
-       g_ib_thread_state = IB_THREAD_EXIT;\r
-       dapl_os_unlock(&g_hca_lock);\r
-}\r
-#endif\r
+/*
+ * Copyright (c) 2005-2008 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/**********************************************************************
+ * 
+ * MODULE: dapl_ib_util.c
+ *
+ * PURPOSE: OFED provider - init, open, close, utilities, work thread
+ *
+ * $Id:$
+ *
+ **********************************************************************/
+
+#ifdef RCSID
+static const char rcsid[] = "$Id:  $";
+#endif
+
+#include "openib_osd.h"
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_ib_util.h"
+#include "dapl_osd.h"
+
+#include <stdlib.h>
+
+struct rdma_event_channel *g_cm_events = NULL;
+ib_thread_state_t g_ib_thread_state = 0;
+DAPL_OS_THREAD g_ib_thread;
+DAPL_OS_LOCK g_hca_lock;
+struct dapl_llist_entry *g_hca_list;
+
+#if defined(_WIN64) || defined(_WIN32)
+#include "..\..\..\..\..\etc\user\comp_channel.cpp"
+#include <rdma\winverbs.h>
+
+static COMP_SET ufds;
+
+static int getipaddr_netdev(char *name, char *addr, int addr_len)
+{
+       IWVProvider *prov;
+       WV_DEVICE_ADDRESS devaddr;
+       struct addrinfo *res, *ai;
+       HRESULT hr;
+       int index;
+
+       if (strncmp(name, "rdma_dev", 8)) {
+               return EINVAL;
+       }
+
+       index = atoi(name + 8);
+
+       hr = WvGetObject(&IID_IWVProvider, (LPVOID *) &prov);
+       if (FAILED(hr)) {
+               return hr;
+       }
+
+       hr = getaddrinfo("..localmachine", NULL, NULL, &res);
+       if (hr) {
+               goto release;
+       }
+
+       for (ai = res; ai; ai = ai->ai_next) {
+               hr = prov->lpVtbl->TranslateAddress(prov, ai->ai_addr, &devaddr);
+               if (SUCCEEDED(hr) && (ai->ai_addrlen <= addr_len) && (index-- == 0)) {
+                       memcpy(addr, ai->ai_addr, ai->ai_addrlen);
+                       goto free;
+               }
+       }
+       hr = ENODEV;
+
+free:
+       freeaddrinfo(res);
+release:
+       prov->lpVtbl->Release(prov);
+       return hr;
+}
+
+static int dapls_os_init(void)
+{
+       return CompSetInit(&ufds);
+}
+
+static void dapls_os_release(void)
+{
+       CompSetCleanup(&ufds);
+}
+
+static int dapls_config_cm_channel(struct rdma_event_channel *channel)
+{
+       channel->channel.Milliseconds = 0;
+       return 0;
+}
+
+static int dapls_config_verbs(struct ibv_context *verbs)
+{
+       verbs->channel.Milliseconds = 0;
+       return 0;
+}
+
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)
+{
+       channel->comp_channel.Milliseconds = 0;
+       return 0;
+}
+
+static int dapls_thread_signal(void)
+{
+       CompSetCancel(&ufds);
+       return 0;
+}
+#else                          // _WIN64 || WIN32
+int g_ib_pipe[2];
+
+static int dapls_os_init(void)
+{
+       /* create pipe for waking up work thread */
+       return pipe(g_ib_pipe);
+}
+
+static void dapls_os_release(void)
+{
+       /* close pipe? */
+}
+
+/* Get IP address using network device name */
+static int getipaddr_netdev(char *name, char *addr, int addr_len)
+{
+       struct ifreq ifr;
+       int skfd, ret, len;
+
+       /* Fill in the structure */
+       snprintf(ifr.ifr_name, IFNAMSIZ, "%s", name);
+       ifr.ifr_hwaddr.sa_family = ARPHRD_INFINIBAND;
+
+       /* Create a socket fd */
+       skfd = socket(PF_INET, SOCK_STREAM, 0);
+       ret = ioctl(skfd, SIOCGIFADDR, &ifr);
+       if (ret)
+               goto bail;
+
+       switch (ifr.ifr_addr.sa_family) {
+#ifdef AF_INET6
+       case AF_INET6:
+               len = sizeof(struct sockaddr_in6);
+               break;
+#endif
+       case AF_INET:
+       default:
+               len = sizeof(struct sockaddr);
+               break;
+       }
+
+       if (len <= addr_len)
+               memcpy(addr, &ifr.ifr_addr, len);
+       else
+               ret = EINVAL;
+
+      bail:
+       close(skfd);
+       return ret;
+}
+
+static int dapls_config_fd(int fd)
+{
+       int opts;
+
+       opts = fcntl(fd, F_GETFL);
+       if (opts < 0 || fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " dapls_config_fd: fcntl on fd %d ERR %d %s\n",
+                        fd, opts, strerror(errno));
+               return errno;
+       }
+
+       return 0;
+}
+
+static int dapls_config_cm_channel(struct rdma_event_channel *channel)
+{
+       return dapls_config_fd(channel->fd);
+}
+
+static int dapls_config_verbs(struct ibv_context *verbs)
+{
+       return dapls_config_fd(verbs->async_fd);
+}
+
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)
+{
+       return dapls_config_fd(channel->fd);
+}
+
+static int dapls_thread_signal(void)
+{
+       return write(g_ib_pipe[1], "w", sizeof "w");
+}
+#endif
+
+/* Get IP address using network name, address, or device name */
+static int getipaddr(char *name, char *addr, int len)
+{
+       struct addrinfo *res;
+
+       /* assume netdev for first attempt, then network and address type */
+       if (getipaddr_netdev(name, addr, len)) {
+               if (getaddrinfo(name, NULL, NULL, &res)) {
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                " open_hca: getaddr_netdev ERROR:"
+                                " %s. Is %s configured?\n",
+                                strerror(errno), name);
+                       return 1;
+               } else {
+                       if (len >= res->ai_addrlen)
+                               memcpy(addr, res->ai_addr, res->ai_addrlen);
+                       else {
+                               freeaddrinfo(res);
+                               return 1;
+                       }
+                       freeaddrinfo(res);
+               }
+       }
+
+       dapl_dbg_log(
+               DAPL_DBG_TYPE_UTIL,
+               " getipaddr: family %d port %d addr %d.%d.%d.%d\n",
+               ((struct sockaddr_in *)addr)->sin_family,
+               ((struct sockaddr_in *)addr)->sin_port,
+               ((struct sockaddr_in *)addr)->sin_addr.s_addr >> 0 & 0xff,
+               ((struct sockaddr_in *)addr)->sin_addr.s_addr >> 8 & 0xff,
+               ((struct sockaddr_in *)addr)->sin_addr.s_addr >> 16 & 0xff,
+               ((struct sockaddr_in *)addr)->sin_addr.
+                s_addr >> 24 & 0xff);
+
+       return 0;
+}
+
+/*
+ * dapls_ib_init, dapls_ib_release
+ *
+ * Initialize Verb related items for device open
+ *
+ * Input:
+ *     none
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     0 success, -1 error
+ *
+ */
+int32_t dapls_ib_init(void)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " dapl_ib_init: \n");
+
+       /* initialize hca_list lock */
+       dapl_os_lock_init(&g_hca_lock);
+
+       /* initialize hca list for CQ events */
+       dapl_llist_init_head(&g_hca_list);
+
+       if (dapls_os_init())
+               return 1;
+
+       return 0;
+}
+
+int32_t dapls_ib_release(void)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " dapl_ib_release: \n");
+       dapli_ib_thread_destroy();
+       if (g_cm_events != NULL)
+               rdma_destroy_event_channel(g_cm_events);
+       dapls_os_release();
+       return 0;
+}
+
+/*
+ * dapls_ib_open_hca
+ *
+ * Open HCA
+ *
+ * Input:
+ *      *hca_name         pointer to provider device name
+ *      *ib_hca_handle_p  pointer to provide HCA handle
+ *
+ * Output:
+ *      none
+ *
+ * Return:
+ *      DAT_SUCCESS
+ *      dapl_convert_errno
+ *
+ */
+DAT_RETURN dapls_ib_open_hca(IN IB_HCA_NAME hca_name, IN DAPL_HCA * hca_ptr)
+{
+       struct rdma_cm_id *cm_id = NULL;
+       union ibv_gid *gid;
+       int ret;
+       DAT_RETURN dat_status;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: %s - %p\n", hca_name, hca_ptr);
+
+       /* Setup the global cm event channel */
+       dapl_os_lock(&g_hca_lock);
+       if (g_cm_events == NULL) {
+               g_cm_events = rdma_create_event_channel();
+               if (g_cm_events == NULL) {
+                       dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+                                    " open_hca: ERR - RDMA channel %s\n",
+                                    strerror(errno));
+                       dapl_os_unlock(&g_hca_lock);
+                       return DAT_INTERNAL_ERROR;
+               }
+       }
+       dapl_os_unlock(&g_hca_lock);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: RDMA channel created (%p)\n", g_cm_events);
+
+       /* HCA name will be hostname or IP address */
+       if (getipaddr((char *)hca_name,
+                     (char *)&hca_ptr->hca_address, 
+                     sizeof(DAT_SOCK_ADDR6)))
+               return DAT_INVALID_ADDRESS;
+
+       /* cm_id will bind local device/GID based on IP address */
+       if (rdma_create_id(g_cm_events, &cm_id, 
+                          (void *)hca_ptr, RDMA_PS_TCP)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: rdma_create ERR %s\n", strerror(errno));
+               return DAT_INTERNAL_ERROR;
+       }
+       ret = rdma_bind_addr(cm_id, (struct sockaddr *)&hca_ptr->hca_address);
+       if ((ret) || (cm_id->verbs == NULL)) {
+               rdma_destroy_id(cm_id);
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: rdma_bind ERR %s."
+                        " Is %s configured?\n", strerror(errno), hca_name);
+               rdma_destroy_id(cm_id);
+               return DAT_INVALID_ADDRESS;
+       }
+
+       /* keep reference to IB device and cm_id */
+       hca_ptr->ib_trans.cm_id = cm_id;
+       hca_ptr->ib_hca_handle = cm_id->verbs;
+       dapls_config_verbs(cm_id->verbs);
+       hca_ptr->port_num = cm_id->port_num;
+       hca_ptr->ib_trans.ib_dev = cm_id->verbs->device;
+       hca_ptr->ib_trans.ib_ctx = cm_id->verbs;
+       gid = &cm_id->route.addr.addr.ibaddr.sgid;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: ctx=%p port=%d GID subnet %016llx"
+                    " id %016llx\n", cm_id->verbs, cm_id->port_num,
+                    (unsigned long long)ntohll(gid->global.subnet_prefix),
+                    (unsigned long long)ntohll(gid->global.interface_id));
+
+       /* support for EVD's with CNO's: one channel via thread */
+       hca_ptr->ib_trans.ib_cq =
+           ibv_create_comp_channel(hca_ptr->ib_hca_handle);
+       if (hca_ptr->ib_trans.ib_cq == NULL) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: ibv_create_comp_channel ERR %s\n",
+                        strerror(errno));
+               rdma_destroy_id(cm_id);
+               return DAT_INTERNAL_ERROR;
+       }
+       if (dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq)) {
+               rdma_destroy_id(cm_id);
+               return DAT_INTERNAL_ERROR;
+       }
+
+       /* set inline max with env or default, get local lid and gid 0 */
+       if (hca_ptr->ib_hca_handle->device->transport_type
+           == IBV_TRANSPORT_IWARP)
+               hca_ptr->ib_trans.max_inline_send =
+                   dapl_os_get_env_val("DAPL_MAX_INLINE",
+                                       INLINE_SEND_IWARP_DEFAULT);
+       else
+               hca_ptr->ib_trans.max_inline_send =
+                   dapl_os_get_env_val("DAPL_MAX_INLINE",
+                                       INLINE_SEND_IB_DEFAULT);
+
+       /* set CM timer defaults */
+       hca_ptr->ib_trans.max_cm_timeout =
+           dapl_os_get_env_val("DAPL_MAX_CM_RESPONSE_TIME",
+                               IB_CM_RESPONSE_TIMEOUT);
+       hca_ptr->ib_trans.max_cm_retries =
+           dapl_os_get_env_val("DAPL_MAX_CM_RETRIES", IB_CM_RETRIES);
+       
+       /* set default IB MTU */
+       hca_ptr->ib_trans.mtu = dapl_ib_mtu(2048);
+
+       dat_status = dapli_ib_thread_init();
+       if (dat_status != DAT_SUCCESS)
+               return dat_status;
+       /* 
+        * Put new hca_transport on list for async and CQ event processing 
+        * Wakeup work thread to add to polling list
+        */
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry);
+       dapl_os_lock(&g_hca_lock);
+       dapl_llist_add_tail(&g_hca_list,
+                           (DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry,
+                           &hca_ptr->ib_trans.entry);
+       if (dapls_thread_signal() == -1)
+               dapl_log(DAPL_DBG_TYPE_UTIL,
+                        " open_hca: thread wakeup error = %s\n",
+                        strerror(errno));
+       dapl_os_unlock(&g_hca_lock);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: %s, %s %d.%d.%d.%d INLINE_MAX=%d\n", hca_name,
+                    ((struct sockaddr_in *)
+                    &hca_ptr->hca_address)->sin_family == AF_INET ?
+                    "AF_INET" : "AF_INET6", 
+                    ((struct sockaddr_in *)
+                    &hca_ptr->hca_address)->sin_addr.s_addr >> 0 & 0xff, 
+                    ((struct sockaddr_in *)
+                    &hca_ptr->hca_address)->sin_addr.s_addr >> 8 & 0xff, 
+                    ((struct sockaddr_in *)
+                    &hca_ptr->hca_address)->sin_addr.s_addr >> 16 & 0xff, 
+                    ((struct sockaddr_in *)
+                    &hca_ptr->hca_address)->sin_addr.s_addr >> 24 & 0xff, 
+                    hca_ptr->ib_trans.max_inline_send);
+
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_close_hca
+ *
+ * Open HCA
+ *
+ * Input:
+ *      DAPL_HCA   provide CA handle
+ *
+ * Output:
+ *      none
+ *
+ * Return:
+ *      DAT_SUCCESS
+ *     dapl_convert_errno 
+ *
+ */
+DAT_RETURN dapls_ib_close_hca(IN DAPL_HCA * hca_ptr)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " close_hca: %p->%p\n",
+                    hca_ptr, hca_ptr->ib_hca_handle);
+
+       dapl_os_lock(&g_hca_lock);
+       if (g_ib_thread_state != IB_THREAD_RUN) {
+               dapl_os_unlock(&g_hca_lock);
+               goto bail;
+       }
+       dapl_os_unlock(&g_hca_lock);
+
+       /* 
+        * Remove hca from async event processing list
+        * Wakeup work thread to remove from polling list
+        */
+       hca_ptr->ib_trans.destroy = 1;
+       if (dapls_thread_signal() == -1)
+               dapl_log(DAPL_DBG_TYPE_UTIL,
+                        " destroy: thread wakeup error = %s\n",
+                        strerror(errno));
+
+       /* wait for thread to remove HCA references */
+       while (hca_ptr->ib_trans.destroy != 2) {
+               if (dapls_thread_signal() == -1)
+                       dapl_log(DAPL_DBG_TYPE_UTIL,
+                                " destroy: thread wakeup error = %s\n",
+                                strerror(errno));
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread_destroy: wait on hca %p destroy\n");
+               dapl_os_sleep_usec(1000);
+       }
+bail:
+
+       if (hca_ptr->ib_trans.ib_cq)
+               ibv_destroy_comp_channel(hca_ptr->ib_trans.ib_cq);
+
+       if (hca_ptr->ib_trans.ib_cq_empty) {
+               struct ibv_comp_channel *channel;
+               channel = hca_ptr->ib_trans.ib_cq_empty->channel;
+               ibv_destroy_cq(hca_ptr->ib_trans.ib_cq_empty);
+               ibv_destroy_comp_channel(channel);
+       }
+
+       if (hca_ptr->ib_hca_handle != IB_INVALID_HANDLE) {
+               if (rdma_destroy_id(hca_ptr->ib_trans.cm_id))
+                       return (dapl_convert_errno(errno, "ib_close_device"));
+               hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;
+       }
+
+       return (DAT_SUCCESS);
+}
+
+
+DAT_RETURN dapli_ib_thread_init(void)
+{
+       DAT_RETURN dat_status;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " ib_thread_init(%d)\n", dapl_os_getpid());
+
+       dapl_os_lock(&g_hca_lock);
+       if (g_ib_thread_state != IB_THREAD_INIT) {
+               dapl_os_unlock(&g_hca_lock);
+               return DAT_SUCCESS;
+       }
+
+       /* uCMA events non-blocking */
+       if (dapls_config_cm_channel(g_cm_events)) {
+               dapl_os_unlock(&g_hca_lock);
+               return (dapl_convert_errno(errno, "create_thread ERR: cm_fd"));
+       }
+
+       g_ib_thread_state = IB_THREAD_CREATE;
+       dapl_os_unlock(&g_hca_lock);
+
+       /* create thread to process inbound connect request */
+       dat_status = dapl_os_thread_create(dapli_thread, NULL, &g_ib_thread);
+       if (dat_status != DAT_SUCCESS)
+               return (dapl_convert_errno(errno,
+                                          "create_thread ERR:"
+                                          " check resource limits"));
+
+       /* wait for thread to start */
+       dapl_os_lock(&g_hca_lock);
+       while (g_ib_thread_state != IB_THREAD_RUN) {
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread_init: waiting for ib_thread\n");
+               dapl_os_unlock(&g_hca_lock);
+               dapl_os_sleep_usec(1000);
+               dapl_os_lock(&g_hca_lock);
+       }
+       dapl_os_unlock(&g_hca_lock);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " ib_thread_init(%d) exit\n", dapl_os_getpid());
+
+       return DAT_SUCCESS;
+}
+
+void dapli_ib_thread_destroy(void)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " ib_thread_destroy(%d)\n", dapl_os_getpid());
+       /* 
+        * wait for async thread to terminate. 
+        * pthread_join would be the correct method
+        * but some applications have some issues
+        */
+
+       /* destroy ib_thread, wait for termination, if not already */
+       dapl_os_lock(&g_hca_lock);
+       if (g_ib_thread_state != IB_THREAD_RUN)
+               goto bail;
+
+       g_ib_thread_state = IB_THREAD_CANCEL;
+       while ((g_ib_thread_state != IB_THREAD_EXIT)) {
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread_destroy: waiting for ib_thread\n");
+               if (dapls_thread_signal() == -1)
+                       dapl_log(DAPL_DBG_TYPE_UTIL,
+                                " destroy: thread wakeup error = %s\n",
+                                strerror(errno));
+               dapl_os_unlock(&g_hca_lock);
+               dapl_os_sleep_usec(2000);
+               dapl_os_lock(&g_hca_lock);
+       }
+bail:
+       dapl_os_unlock(&g_hca_lock);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " ib_thread_destroy(%d) exit\n", dapl_os_getpid());
+}
+
+#if defined(_WIN64) || defined(_WIN32)
+/* work thread for uAT, uCM, CQ, and async events */
+void dapli_thread(void *arg)
+{
+       struct _ib_hca_transport *hca;
+       struct _ib_hca_transport *uhca[8];
+       COMP_CHANNEL *channel;
+       int ret, idx, cnt;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d,0x%x): ENTER: \n",
+                    dapl_os_getpid(), g_ib_thread);
+
+       dapl_os_lock(&g_hca_lock);
+       for (g_ib_thread_state = IB_THREAD_RUN;
+            g_ib_thread_state == IB_THREAD_RUN; 
+            dapl_os_lock(&g_hca_lock)) {
+
+               CompSetZero(&ufds);
+               CompSetAdd(&g_cm_events->channel, &ufds);
+
+               idx = 0;
+               hca = dapl_llist_is_empty(&g_hca_list) ? NULL :
+                     dapl_llist_peek_head(&g_hca_list);
+
+               while (hca) {
+                       CompSetAdd(&hca->ib_ctx->channel, &ufds);
+                       CompSetAdd(&hca->ib_cq->comp_channel, &ufds);
+                       uhca[idx++] = hca;
+                       hca = dapl_llist_next_entry(&g_hca_list,
+                                                   (DAPL_LLIST_ENTRY *)
+                                                   &hca->entry);
+               }
+               cnt = idx;
+
+               dapl_os_unlock(&g_hca_lock);
+               ret = CompSetPoll(&ufds, INFINITE);
+
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread(%d) poll_event 0x%x\n",
+                            dapl_os_getpid(), ret);
+
+               dapli_cma_event_cb();
+
+               /* check and process ASYNC events, per device */
+               for (idx = 0; idx < cnt; idx++) {
+                       if (uhca[idx]->destroy == 1) {
+                               dapl_os_lock(&g_hca_lock);
+                               dapl_llist_remove_entry(&g_hca_list,
+                                                       (DAPL_LLIST_ENTRY *)
+                                                       &uhca[idx]->entry);
+                               dapl_os_unlock(&g_hca_lock);
+                               uhca[idx]->destroy = 2;
+                       } else {
+                               dapli_cq_event_cb(uhca[idx]);
+                               dapli_async_event_cb(uhca[idx]);
+                       }
+               }
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d) EXIT\n",
+                    dapl_os_getpid());
+       g_ib_thread_state = IB_THREAD_EXIT;
+       dapl_os_unlock(&g_hca_lock);
+}
+#else                          // _WIN64 || WIN32
+
+/* work thread for uAT, uCM, CQ, and async events */
+void dapli_thread(void *arg)
+{
+       struct pollfd ufds[__FD_SETSIZE];
+       struct _ib_hca_transport *uhca[__FD_SETSIZE] = { NULL };
+       struct _ib_hca_transport *hca;
+       int ret, idx, fds;
+       char rbuf[2];
+
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                    " ib_thread(%d,0x%x): ENTER: pipe %d ucma %d\n",
+                    dapl_os_getpid(), g_ib_thread, g_ib_pipe[0],
+                    g_cm_events->fd);
+
+       /* Poll across pipe, CM, AT never changes */
+       dapl_os_lock(&g_hca_lock);
+       g_ib_thread_state = IB_THREAD_RUN;
+
+       ufds[0].fd = g_ib_pipe[0];      /* pipe */
+       ufds[0].events = POLLIN;
+       ufds[1].fd = g_cm_events->fd;   /* uCMA */
+       ufds[1].events = POLLIN;
+
+       while (g_ib_thread_state == IB_THREAD_RUN) {
+
+               /* build ufds after pipe and uCMA events */
+               ufds[0].revents = 0;
+               ufds[1].revents = 0;
+               idx = 1;
+
+               /*  Walk HCA list and setup async and CQ events */
+               if (!dapl_llist_is_empty(&g_hca_list))
+                       hca = dapl_llist_peek_head(&g_hca_list);
+               else
+                       hca = NULL;
+
+               while (hca) {
+
+                       /* uASYNC events */
+                       ufds[++idx].fd = hca->ib_ctx->async_fd;
+                       ufds[idx].events = POLLIN;
+                       ufds[idx].revents = 0;
+                       uhca[idx] = hca;
+
+                       /* CQ events are non-direct with CNO's */
+                       ufds[++idx].fd = hca->ib_cq->fd;
+                       ufds[idx].events = POLLIN;
+                       ufds[idx].revents = 0;
+                       uhca[idx] = hca;
+
+                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                                    " ib_thread(%d) poll_fd: hca[%d]=%p,"
+                                    " async=%d pipe=%d cm=%d \n",
+                                    dapl_os_getpid(), hca, ufds[idx - 1].fd,
+                                    ufds[0].fd, ufds[1].fd);
+
+                       hca = dapl_llist_next_entry(&g_hca_list,
+                                                   (DAPL_LLIST_ENTRY *)
+                                                   &hca->entry);
+               }
+
+               /* unlock, and setup poll */
+               fds = idx + 1;
+               dapl_os_unlock(&g_hca_lock);
+               ret = poll(ufds, fds, -1);
+               if (ret <= 0) {
+                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                                    " ib_thread(%d): ERR %s poll\n",
+                                    dapl_os_getpid(), strerror(errno));
+                       dapl_os_lock(&g_hca_lock);
+                       continue;
+               }
+
+               dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                            " ib_thread(%d) poll_event: "
+                            " async=0x%x pipe=0x%x cm=0x%x \n",
+                            dapl_os_getpid(), ufds[idx].revents,
+                            ufds[0].revents, ufds[1].revents);
+
+               /* uCMA events */
+               if (ufds[1].revents == POLLIN)
+                       dapli_cma_event_cb();
+
+               /* check and process CQ and ASYNC events, per device */
+               for (idx = 2; idx < fds; idx++) {
+                       if (ufds[idx].revents == POLLIN) {
+                               dapli_cq_event_cb(uhca[idx]);
+                               dapli_async_event_cb(uhca[idx]);
+                       }
+               }
+
+               /* check and process user events, PIPE */
+               if (ufds[0].revents == POLLIN) {
+                       if (read(g_ib_pipe[0], rbuf, 2) == -1)
+                               dapl_log(DAPL_DBG_TYPE_THREAD,
+                                        " cr_thread: pipe rd err= %s\n",
+                                        strerror(errno));
+
+                       /* cleanup any device on list marked for destroy */
+                       for (idx = 3; idx < fds; idx++) {
+                               if (uhca[idx] && uhca[idx]->destroy == 1) {
+                                       dapl_os_lock(&g_hca_lock);
+                                       dapl_llist_remove_entry(
+                                               &g_hca_list,
+                                               (DAPL_LLIST_ENTRY*)
+                                               &uhca[idx]->entry);
+                                       dapl_os_unlock(&g_hca_lock);
+                                       uhca[idx]->destroy = 2;
+                               }
+                       }
+               }
+               dapl_os_lock(&g_hca_lock);
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " ib_thread(%d) EXIT\n",
+                    dapl_os_getpid());
+       g_ib_thread_state = IB_THREAD_EXIT;
+       dapl_os_unlock(&g_hca_lock);
+}
+#endif
index 309972f979500107129e1a41e7169acb39175842..c537df3dcd10836ae6043cfed941d342ddce2b3c 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef OPENIB_OSD_H
 #define OPENIB_OSD_H
 
+#include <rdma/rdma_cma.h>
+#include <rdma/rdma_cma_abi.h>
 #include <byteswap.h>
 #include <sys/poll.h>
 
index 581b9088953e5e507218e184c736225e3e6407d5..3290081c949018a1a7f7196809e83beed06c0ade 100644 (file)
@@ -1,3 +1,4 @@
+#include <rdma/rdma_cma.h>\r
 #include <winsock2.h>\r
 #include <ws2tcpip.h>\r
 \r
index 6c66b2551e5c649a8181e82e8614e40be74537d2..3e32fabf132d7b6a27e06ee0792ffafa7aba0769 100644 (file)
@@ -279,12 +279,13 @@ typedef enum dapl_cm_state
        DCM_REJECTING,
        DCM_REJECTED,
        DCM_CONNECTED,
-       DCM_RELEASED,
+       DCM_RELEASE,
        DCM_DISC_PENDING,
        DCM_DISCONNECTED,
        DCM_DESTROY,
        DCM_RTU_PENDING,
-       DCM_DISC_RECV
+       DCM_DISC_RECV,
+       DCM_FREE,
 
 } DAPL_CM_STATE;
 
@@ -372,14 +373,15 @@ STATIC _INLINE_ char * dapl_cm_state_str(IN int st)
                "CM_REJECTING",
                "CM_REJECTED",
                "CM_CONNECTED",
-               "CM_RELEASED",
+               "CM_RELEASE",
                "CM_DISC_PENDING",
                "CM_DISCONNECTED",
                "CM_DESTROY",
                "CM_RTU_PENDING",
-               "CM_DISC_RECV"
+               "CM_DISC_RECV",
+               "CM_FREE"
         };
-        return ((st < 0 || st > 15) ? "Invalid CM state?" : state[st]);
+        return ((st < 0 || st > 16) ? "Invalid CM state?" : state[st]);
 }
 
 STATIC _INLINE_ char * dapl_cm_op_str(IN int op)
index b286f8c8b7487734952da26157df6fc954157b68..ddf85a4c5f8d71e4b9c01169c41ff96c4378fdb0 100644 (file)
@@ -55,10 +55,6 @@ STATIC _INLINE_ int dapls_convert_privileges(IN DAT_MEM_PRIV_FLAGS privileges)
                access |= IBV_ACCESS_REMOTE_WRITE;
        if (DAT_MEM_PRIV_REMOTE_READ_FLAG & privileges)
                access |= IBV_ACCESS_REMOTE_READ;
-       if (DAT_MEM_PRIV_REMOTE_READ_FLAG & privileges)
-               access |= IBV_ACCESS_REMOTE_READ;
-       if (DAT_MEM_PRIV_REMOTE_READ_FLAG & privileges)
-               access |= IBV_ACCESS_REMOTE_READ;
 #ifdef DAT_EXTENSIONS
        if (DAT_IB_MEM_PRIV_REMOTE_ATOMIC & privileges)
                access |= IBV_ACCESS_REMOTE_ATOMIC;
index c2b5c69f1caa43fe51550a8fd724382a7783d87c..15c1dae530a92770658e712296350df085fa1c82 100644 (file)
-/*\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-\r
-/*\r
- * dapl_ib_qp_alloc\r
- *\r
- * Alloc a QP\r
- *\r
- * Input:\r
- *     *ep_ptr         pointer to EP INFO\r
- *     ib_hca_handle   provider HCA handle\r
- *     ib_pd_handle    provider protection domain handle\r
- *     cq_recv         provider recv CQ handle\r
- *     cq_send         provider send CQ handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_qp_alloc(IN DAPL_IA * ia_ptr,\r
-                 IN DAPL_EP * ep_ptr, IN DAPL_EP * ep_ctx_ptr)\r
-{\r
-       DAT_EP_ATTR *attr;\r
-       DAPL_EVD *rcv_evd, *req_evd;\r
-       ib_cq_handle_t rcv_cq, req_cq;\r
-       ib_pd_handle_t ib_pd_handle;\r
-       struct ibv_qp_init_attr qp_create;\r
-#ifdef _OPENIB_CMA_\r
-       dp_ib_cm_handle_t conn;\r
-#endif\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " qp_alloc: ia_ptr %p ep_ptr %p ep_ctx_ptr %p\n",\r
-                    ia_ptr, ep_ptr, ep_ctx_ptr);\r
-\r
-       attr = &ep_ptr->param.ep_attr;\r
-       ib_pd_handle = ((DAPL_PZ *) ep_ptr->param.pz_handle)->pd_handle;\r
-       rcv_evd = (DAPL_EVD *) ep_ptr->param.recv_evd_handle;\r
-       req_evd = (DAPL_EVD *) ep_ptr->param.request_evd_handle;\r
-\r
-       /* \r
-        * DAT allows usage model of EP's with no EVD's but IB does not. \r
-        * Create a CQ with zero entries under the covers to support and \r
-        * catch any invalid posting. \r
-        */\r
-       if (rcv_evd != DAT_HANDLE_NULL)\r
-               rcv_cq = rcv_evd->ib_cq_handle;\r
-       else if (!ia_ptr->hca_ptr->ib_trans.ib_cq_empty)\r
-               rcv_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;\r
-       else {\r
-               struct ibv_comp_channel *channel;\r
-\r
-               channel = ibv_create_comp_channel(ia_ptr->hca_ptr->ib_hca_handle);\r
-               if (!channel)\r
-                       return (dapl_convert_errno(ENOMEM, "create_cq"));\r
-                 \r
-               /* Call IB verbs to create CQ */\r
-               rcv_cq = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle,\r
-                                      0, NULL, channel, 0);\r
-\r
-               if (rcv_cq == IB_INVALID_HANDLE) {\r
-                       ibv_destroy_comp_channel(channel);\r
-                       return (dapl_convert_errno(ENOMEM, "create_cq"));\r
-               }\r
-\r
-               ia_ptr->hca_ptr->ib_trans.ib_cq_empty = rcv_cq;\r
-       }\r
-       if (req_evd != DAT_HANDLE_NULL)\r
-               req_cq = req_evd->ib_cq_handle;\r
-       else\r
-               req_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;\r
-\r
-       /* \r
-        * IMPLEMENTATION NOTE:\r
-        * uDAPL allows consumers to post buffers on the EP after creation\r
-        * and before a connect request (outbound and inbound). This forces\r
-        * a binding to a device during the hca_open call and requires the\r
-        * consumer to predetermine which device to listen on or connect from.\r
-        * This restriction eliminates any option of listening or connecting \r
-        * over multiple devices. uDAPL should add API's to resolve addresses \r
-        * and bind to the device at the approriate time (before connect \r
-        * and after CR arrives). Discovery should happen at connection time \r
-        * based on addressing and not on static configuration during open.\r
-        */\r
-\r
-#ifdef _OPENIB_CMA_\r
-       /* Allocate CM and initialize lock */\r
-       if ((conn = dapls_ib_cm_create(ep_ptr)) == NULL)\r
-               return (dapl_convert_errno(ENOMEM, "create_cq"));\r
-\r
-       /* open identifies the local device; per DAT specification */\r
-       if (rdma_bind_addr(conn->cm_id,\r
-                          (struct sockaddr *)&ia_ptr->hca_ptr->hca_address))\r
-               return (dapl_convert_errno(EAFNOSUPPORT, "create_cq"));\r
-#endif\r
-       /* Setup attributes and create qp */\r
-       dapl_os_memzero((void *)&qp_create, sizeof(qp_create));\r
-       qp_create.send_cq = req_cq;\r
-       qp_create.cap.max_send_wr = attr->max_request_dtos;\r
-       qp_create.cap.max_send_sge = attr->max_request_iov;\r
-       qp_create.cap.max_inline_data =\r
-           ia_ptr->hca_ptr->ib_trans.max_inline_send;\r
-       qp_create.qp_type = IBV_QPT_RC;\r
-       qp_create.qp_context = (void *)ep_ptr;\r
-\r
-#ifdef DAT_EXTENSIONS \r
-       if (attr->service_type == DAT_IB_SERVICE_TYPE_UD) {\r
-#ifdef _OPENIB_CMA_\r
-               return (DAT_NOT_IMPLEMENTED);\r
-#endif\r
-               qp_create.qp_type = IBV_QPT_UD;\r
-               if (attr->max_message_size >\r
-                   (128 << ia_ptr->hca_ptr->ib_trans.mtu)) {\r
-                       return (DAT_INVALID_PARAMETER | DAT_INVALID_ARG6);\r
-               }\r
-       }\r
-#endif\r
-       \r
-       /* ibv assumes rcv_cq is never NULL, set to req_cq */\r
-       if (rcv_cq == NULL) {\r
-               qp_create.recv_cq = req_cq;\r
-               qp_create.cap.max_recv_wr = 0;\r
-               qp_create.cap.max_recv_sge = 0;\r
-       } else {\r
-               qp_create.recv_cq = rcv_cq;\r
-               qp_create.cap.max_recv_wr = attr->max_recv_dtos;\r
-               qp_create.cap.max_recv_sge = attr->max_recv_iov;\r
-       }\r
-\r
-#ifdef _OPENIB_CMA_\r
-       if (rdma_create_qp(conn->cm_id, ib_pd_handle, &qp_create)) {\r
-               dapls_ib_cm_free(conn, ep_ptr);\r
-               return (dapl_convert_errno(errno, "create_qp"));\r
-       }\r
-       ep_ptr->qp_handle = conn->cm_id->qp;\r
-       ep_ptr->cm_handle = conn;\r
-       ep_ptr->qp_state = IBV_QPS_INIT;\r
-\r
-       ep_ptr->param.local_port_qual = rdma_get_src_port(conn->cm_id);\r
-#else\r
-       ep_ptr->qp_handle = ibv_create_qp(ib_pd_handle, &qp_create);\r
-       if (!ep_ptr->qp_handle)\r
-               return (dapl_convert_errno(ENOMEM, "create_qp"));\r
-               \r
-       /* Setup QP attributes for INIT state on the way out */\r
-       if (dapls_modify_qp_state(ep_ptr->qp_handle,\r
-                                 IBV_QPS_INIT, 0, 0, 0) != DAT_SUCCESS) {\r
-               ibv_destroy_qp(ep_ptr->qp_handle);\r
-               ep_ptr->qp_handle = IB_INVALID_HANDLE;\r
-               return DAT_INTERNAL_ERROR;\r
-       }\r
-#endif\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " qp_alloc: qpn %p sq %d,%d rq %d,%d\n",\r
-                    ep_ptr->qp_handle->qp_num,\r
-                    qp_create.cap.max_send_wr, qp_create.cap.max_send_sge,\r
-                    qp_create.cap.max_recv_wr, qp_create.cap.max_recv_sge);\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapl_ib_qp_free\r
- *\r
- * Free a QP\r
- *\r
- * Input:\r
- *     ia_handle       IA handle\r
- *     *ep_ptr         pointer to EP INFO\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *  dapl_convert_errno\r
- *\r
- */\r
-DAT_RETURN dapls_ib_qp_free(IN DAPL_IA * ia_ptr, IN DAPL_EP * ep_ptr)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " qp_free:  ep_ptr %p qp %p\n",\r
-                    ep_ptr, ep_ptr->qp_handle);\r
-\r
-       if (ep_ptr->cm_handle != NULL) {\r
-               dapls_ib_cm_free(ep_ptr->cm_handle, ep_ptr);\r
-       }\r
-       \r
-       if (ep_ptr->qp_handle != NULL) {\r
-               /* force error state to flush queue, then destroy */\r
-               dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0,0,0);\r
-\r
-               if (ibv_destroy_qp(ep_ptr->qp_handle))\r
-                       return (dapl_convert_errno(errno, "destroy_qp"));\r
-\r
-               ep_ptr->qp_handle = NULL;\r
-       }\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       /* UD endpoints can have many CR associations and will not\r
-        * set ep->cm_handle. Call provider with cm_ptr null to incidate\r
-        * UD type multi CR's for this EP. It will parse internal list\r
-        * and cleanup all associations.\r
-        */\r
-       if (ep_ptr->param.ep_attr.service_type == DAT_IB_SERVICE_TYPE_UD) \r
-               dapls_ib_cm_free(NULL, ep_ptr);\r
-#endif\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapl_ib_qp_modify\r
- *\r
- * Set the QP to the parameters specified in an EP_PARAM\r
- *\r
- * The EP_PARAM structure that is provided has been\r
- * sanitized such that only non-zero values are valid.\r
- *\r
- * Input:\r
- *     ib_hca_handle           HCA handle\r
- *     qp_handle               QP handle\r
- *     ep_attr                 Sanitized EP Params\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_qp_modify(IN DAPL_IA * ia_ptr,\r
-                  IN DAPL_EP * ep_ptr, IN DAT_EP_ATTR * attr)\r
-{\r
-       struct ibv_qp_attr qp_attr;\r
-\r
-       if (ep_ptr->qp_handle == IB_INVALID_HANDLE)\r
-               return DAT_INVALID_PARAMETER;\r
-\r
-       /* \r
-        * EP state, qp_handle state should be an indication\r
-        * of current state but the only way to be sure is with\r
-        * a user mode ibv_query_qp call which is NOT available \r
-        */\r
-\r
-       /* move to error state if necessary */\r
-       if ((ep_ptr->qp_state == IB_QP_STATE_ERROR) &&\r
-           (ep_ptr->qp_handle->state != IBV_QPS_ERR)) {\r
-               return (dapls_modify_qp_state(ep_ptr->qp_handle, \r
-                                             IBV_QPS_ERR, 0, 0, 0));\r
-       }\r
-\r
-       /*\r
-        * Check if we have the right qp_state to modify attributes\r
-        */\r
-       if ((ep_ptr->qp_handle->state != IBV_QPS_RTR) &&\r
-           (ep_ptr->qp_handle->state != IBV_QPS_RTS))\r
-               return DAT_INVALID_STATE;\r
-\r
-       /* Adjust to current EP attributes */\r
-       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
-       qp_attr.cap.max_send_wr = attr->max_request_dtos;\r
-       qp_attr.cap.max_recv_wr = attr->max_recv_dtos;\r
-       qp_attr.cap.max_send_sge = attr->max_request_iov;\r
-       qp_attr.cap.max_recv_sge = attr->max_recv_iov;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "modify_qp: qp %p sq %d,%d, rq %d,%d\n",\r
-                    ep_ptr->qp_handle,\r
-                    qp_attr.cap.max_send_wr, qp_attr.cap.max_send_sge,\r
-                    qp_attr.cap.max_recv_wr, qp_attr.cap.max_recv_sge);\r
-\r
-       if (ibv_modify_qp(ep_ptr->qp_handle, &qp_attr, IBV_QP_CAP)) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
-                            "modify_qp: modify ep %p qp %p failed\n",\r
-                            ep_ptr, ep_ptr->qp_handle);\r
-               return (dapl_convert_errno(errno, "modify_qp_state"));\r
-       }\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_reinit_ep\r
- *\r
- * Move the QP to INIT state again.\r
- *\r
- * Input:\r
- *     ep_ptr          DAPL_EP\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     void\r
- *\r
- */\r
-#if defined(_WIN32) || defined(_WIN64) || defined(_OPENIB_CMA_)\r
-void dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)\r
-{\r
-       /* work around bug in low level driver - 3/24/09 */\r
-       /* RTS -> RESET -> INIT -> ERROR QP transition crashes system */\r
-       if (ep_ptr->qp_handle != IB_INVALID_HANDLE) {\r
-               dapls_ib_qp_free(ep_ptr->header.owner_ia, ep_ptr);\r
-               dapls_ib_qp_alloc(ep_ptr->header.owner_ia, ep_ptr, ep_ptr);\r
-       }\r
-}\r
-#else                          // _WIN32 || _WIN64\r
-void dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)\r
-{\r
-       if (ep_ptr->qp_handle != IB_INVALID_HANDLE &&\r
-           ep_ptr->qp_handle->qp_type != IBV_QPT_UD) {\r
-               /* move to RESET state and then to INIT */\r
-               dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_RESET,0,0,0);\r
-               dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_INIT,0,0,0);\r
-       }\r
-}\r
-#endif                         // _WIN32 || _WIN64\r
-\r
-/* \r
- * Generic QP modify for init, reset, error, RTS, RTR\r
- * For UD, create_ah on RTR, qkey on INIT\r
- * CM msg provides QP attributes, info in network order\r
- */\r
-DAT_RETURN\r
-dapls_modify_qp_state(IN ib_qp_handle_t                qp_handle,\r
-                     IN ib_qp_state_t          qp_state, \r
-                     IN uint32_t               qpn,\r
-                     IN uint16_t               lid,\r
-                     IN ib_gid_handle_t        gid)\r
-{\r
-       struct ibv_qp_attr qp_attr;\r
-       enum ibv_qp_attr_mask mask = IBV_QP_STATE;\r
-       DAPL_EP *ep_ptr = (DAPL_EP *) qp_handle->qp_context;\r
-       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;\r
-       int ret;\r
-\r
-       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
-       qp_attr.qp_state = qp_state;\r
-       \r
-       switch (qp_state) {\r
-       case IBV_QPS_RTR:\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                               " QPS_RTR: type %d qpn 0x%x lid 0x%x"\r
-                               " port %d ep %p qp_state %d \n",\r
-                               qp_handle->qp_type, \r
-                               ntohl(qpn), ntohs(lid), \r
-                               ia_ptr->hca_ptr->port_num,\r
-                               ep_ptr, ep_ptr->qp_state);\r
-\r
-               mask |= IBV_QP_AV |\r
-                       IBV_QP_PATH_MTU |\r
-                       IBV_QP_DEST_QPN |\r
-                       IBV_QP_RQ_PSN |\r
-                       IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER;\r
-\r
-               qp_attr.dest_qp_num = ntohl(qpn);\r
-               qp_attr.rq_psn = 1;\r
-               qp_attr.path_mtu = ia_ptr->hca_ptr->ib_trans.mtu;\r
-               qp_attr.max_dest_rd_atomic =\r
-                       ep_ptr->param.ep_attr.max_rdma_read_out;\r
-               qp_attr.min_rnr_timer =\r
-                       ia_ptr->hca_ptr->ib_trans.rnr_timer;\r
-\r
-               /* address handle. RC and UD */\r
-               qp_attr.ah_attr.dlid = ntohs(lid);\r
-               if (ia_ptr->hca_ptr->ib_trans.global) {\r
-                       qp_attr.ah_attr.is_global = 1;\r
-                       qp_attr.ah_attr.grh.dgid.global.subnet_prefix = \r
-                               ntohll(gid->global.subnet_prefix);\r
-                       qp_attr.ah_attr.grh.dgid.global.interface_id = \r
-                               ntohll(gid->global.interface_id);\r
-                       qp_attr.ah_attr.grh.hop_limit =\r
-                               ia_ptr->hca_ptr->ib_trans.hop_limit;\r
-                       qp_attr.ah_attr.grh.traffic_class =\r
-                               ia_ptr->hca_ptr->ib_trans.tclass;\r
-               }\r
-               qp_attr.ah_attr.sl = 0;\r
-               qp_attr.ah_attr.src_path_bits = 0;\r
-               qp_attr.ah_attr.port_num = ia_ptr->hca_ptr->port_num;\r
-\r
-               /* UD: already in RTR, RTS state */\r
-               if (qp_handle->qp_type == IBV_QPT_UD) {\r
-                       mask = IBV_QP_STATE;\r
-                       if (ep_ptr->qp_state == IBV_QPS_RTR ||\r
-                               ep_ptr->qp_state == IBV_QPS_RTS)\r
-                               return DAT_SUCCESS;\r
-               }\r
-               break;\r
-       case IBV_QPS_RTS:\r
-               if (qp_handle->qp_type == IBV_QPT_RC) {\r
-                       mask |= IBV_QP_SQ_PSN |\r
-                               IBV_QP_TIMEOUT |\r
-                               IBV_QP_RETRY_CNT |\r
-                               IBV_QP_RNR_RETRY | IBV_QP_MAX_QP_RD_ATOMIC;\r
-                       qp_attr.timeout =\r
-                               ia_ptr->hca_ptr->ib_trans.ack_timer;\r
-                       qp_attr.retry_cnt =\r
-                               ia_ptr->hca_ptr->ib_trans.ack_retry;\r
-                       qp_attr.rnr_retry =\r
-                               ia_ptr->hca_ptr->ib_trans.rnr_retry;\r
-                       qp_attr.max_rd_atomic =\r
-                               ep_ptr->param.ep_attr.max_rdma_read_out;\r
-               }\r
-               /* RC and UD */\r
-               qp_attr.qp_state = IBV_QPS_RTS;\r
-               qp_attr.sq_psn = 1;\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                               " QPS_RTS: psn %x rd_atomic %d ack %d "\r
-                               " retry %d rnr_retry %d ep %p qp_state %d\n",\r
-                               qp_attr.sq_psn, qp_attr.max_rd_atomic,\r
-                               qp_attr.timeout, qp_attr.retry_cnt,\r
-                               qp_attr.rnr_retry, ep_ptr,\r
-                               ep_ptr->qp_state);\r
-\r
-               if (qp_handle->qp_type == IBV_QPT_UD) {\r
-                       /* already RTS, multi remote AH's on QP */\r
-                       if (ep_ptr->qp_state == IBV_QPS_RTS)\r
-                               return DAT_SUCCESS;\r
-                       else\r
-                               mask = IBV_QP_STATE | IBV_QP_SQ_PSN;\r
-               }\r
-               break;\r
-       case IBV_QPS_INIT:\r
-               mask |= IBV_QP_PKEY_INDEX | IBV_QP_PORT;\r
-               if (qp_handle->qp_type == IBV_QPT_RC) {\r
-                       mask |= IBV_QP_ACCESS_FLAGS;\r
-                       qp_attr.qp_access_flags =\r
-                               IBV_ACCESS_LOCAL_WRITE |\r
-                               IBV_ACCESS_REMOTE_WRITE |\r
-                               IBV_ACCESS_REMOTE_READ |\r
-                               IBV_ACCESS_REMOTE_ATOMIC |\r
-                               IBV_ACCESS_MW_BIND;\r
-               }\r
-\r
-               if (qp_handle->qp_type == IBV_QPT_UD) {\r
-                       /* already INIT, multi remote AH's on QP */\r
-                       if (ep_ptr->qp_state == IBV_QPS_INIT)\r
-                               return DAT_SUCCESS;\r
-                       mask |= IBV_QP_QKEY;\r
-                       qp_attr.qkey = DAT_UD_QKEY;\r
-               }\r
-\r
-               qp_attr.pkey_index = 0;\r
-               qp_attr.port_num = ia_ptr->hca_ptr->port_num;\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                               " QPS_INIT: pi %x port %x acc %x qkey 0x%x\n",\r
-                               qp_attr.pkey_index, qp_attr.port_num,\r
-                               qp_attr.qp_access_flags, qp_attr.qkey);\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-\r
-       ret = ibv_modify_qp(qp_handle, &qp_attr, mask);\r
-       if (ret == 0) {\r
-               ep_ptr->qp_state = qp_state;\r
-               return DAT_SUCCESS;\r
-       } else {\r
-               return (dapl_convert_errno(errno, "modify_qp_state"));\r
-       }\r
-}\r
-\r
-/* Modify UD type QP from init, rtr, rts, info network order */\r
-DAT_RETURN \r
-dapls_modify_qp_ud(IN DAPL_HCA *hca, IN ib_qp_handle_t qp)\r
-{\r
-       struct ibv_qp_attr qp_attr;\r
-\r
-       /* modify QP, setup and prepost buffers */\r
-       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
-       qp_attr.qp_state = IBV_QPS_INIT;\r
-        qp_attr.pkey_index = 0;\r
-        qp_attr.port_num = hca->port_num;\r
-        qp_attr.qkey = DAT_UD_QKEY;\r
-       if (ibv_modify_qp(qp, &qp_attr, \r
-                         IBV_QP_STATE          |\r
-                         IBV_QP_PKEY_INDEX     |\r
-                          IBV_QP_PORT          |\r
-                          IBV_QP_QKEY)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                       " modify_ud_qp INIT: ERR %s\n", strerror(errno));\r
-               return (dapl_convert_errno(errno, "modify_qp"));\r
-       }\r
-       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
-       qp_attr.qp_state = IBV_QPS_RTR;\r
-       if (ibv_modify_qp(qp, &qp_attr,IBV_QP_STATE)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR, \r
-                       " modify_ud_qp RTR: ERR %s\n", strerror(errno));\r
-               return (dapl_convert_errno(errno, "modify_qp"));\r
-       }\r
-       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
-       qp_attr.qp_state = IBV_QPS_RTS;\r
-       qp_attr.sq_psn = 1;\r
-       if (ibv_modify_qp(qp, &qp_attr, \r
-                         IBV_QP_STATE | IBV_QP_SQ_PSN)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                       " modify_ud_qp RTS: ERR %s\n", strerror(errno));\r
-               return (dapl_convert_errno(errno, "modify_qp"));\r
-       }\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/* Create address handle for remote QP, info in network order */\r
-ib_ah_handle_t \r
-dapls_create_ah(IN DAPL_HCA            *hca,\r
-               IN ib_pd_handle_t       pd,\r
-               IN ib_qp_handle_t       qp,\r
-               IN uint16_t             lid,\r
-               IN ib_gid_handle_t      gid)\r
-{\r
-       struct ibv_qp_attr qp_attr;\r
-       ib_ah_handle_t  ah;\r
-\r
-       if (qp->qp_type != IBV_QPT_UD)\r
-               return NULL;\r
-\r
-       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));\r
-       qp_attr.qp_state = IBV_QP_STATE;\r
-\r
-       /* address handle. RC and UD */\r
-       qp_attr.ah_attr.dlid = ntohs(lid);\r
-       if (gid != NULL) {\r
-               dapl_log(DAPL_DBG_TYPE_CM, "dapl_create_ah: with GID\n");\r
-               qp_attr.ah_attr.is_global = 1;\r
-               qp_attr.ah_attr.grh.dgid.global.subnet_prefix = \r
-                               ntohll(gid->global.subnet_prefix);\r
-               qp_attr.ah_attr.grh.dgid.global.interface_id = \r
-                               ntohll(gid->global.interface_id);\r
-               qp_attr.ah_attr.grh.hop_limit = hca->ib_trans.hop_limit;\r
-               qp_attr.ah_attr.grh.traffic_class = hca->ib_trans.tclass;\r
-       }\r
-       qp_attr.ah_attr.sl = 0;\r
-       qp_attr.ah_attr.src_path_bits = 0;\r
-       qp_attr.ah_attr.port_num = hca->port_num;\r
-\r
-       dapl_log(DAPL_DBG_TYPE_CM, \r
-                       " dapls_create_ah: port %x lid %x pd %p ctx %p handle 0x%x\n", \r
-                       hca->port_num,qp_attr.ah_attr.dlid, pd, pd->context, pd->handle);\r
-\r
-       /* UD: create AH for remote side */\r
-       ah = ibv_create_ah(pd, &qp_attr.ah_attr);\r
-       if (!ah) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                       " create_ah: ERR %s\n", strerror(errno));\r
-               return NULL;\r
-       }\r
-\r
-       dapl_log(DAPL_DBG_TYPE_CM, \r
-                       " dapls_create_ah: AH %p for lid %x\n", \r
-                       ah, qp_attr.ah_attr.dlid);\r
-\r
-       return ah;\r
-}\r
-\r
-/*\r
- * Local variables:\r
- *  c-indent-level: 4\r
- *  c-basic-offset: 4\r
- *  tab-width: 8\r
- * End:\r
- */\r
+/*
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_ep_util.h"
+
+/*
+ * dapl_ib_qp_alloc
+ *
+ * Alloc a QP
+ *
+ * Input:
+ *     *ep_ptr         pointer to EP INFO
+ *     ib_hca_handle   provider HCA handle
+ *     ib_pd_handle    provider protection domain handle
+ *     cq_recv         provider recv CQ handle
+ *     cq_send         provider send CQ handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_qp_alloc(IN DAPL_IA * ia_ptr,
+                 IN DAPL_EP * ep_ptr, IN DAPL_EP * ep_ctx_ptr)
+{
+       DAT_EP_ATTR *attr;
+       DAPL_EVD *rcv_evd, *req_evd;
+       ib_cq_handle_t rcv_cq, req_cq;
+       ib_pd_handle_t ib_pd_handle;
+       struct ibv_qp_init_attr qp_create;
+#ifdef _OPENIB_CMA_
+       dp_ib_cm_handle_t conn;
+#endif
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " qp_alloc: ia_ptr %p ep_ptr %p ep_ctx_ptr %p\n",
+                    ia_ptr, ep_ptr, ep_ctx_ptr);
+
+       attr = &ep_ptr->param.ep_attr;
+       ib_pd_handle = ((DAPL_PZ *) ep_ptr->param.pz_handle)->pd_handle;
+       rcv_evd = (DAPL_EVD *) ep_ptr->param.recv_evd_handle;
+       req_evd = (DAPL_EVD *) ep_ptr->param.request_evd_handle;
+
+       /* 
+        * DAT allows usage model of EP's with no EVD's but IB does not. 
+        * Create a CQ with zero entries under the covers to support and 
+        * catch any invalid posting. 
+        */
+       if (rcv_evd != DAT_HANDLE_NULL)
+               rcv_cq = rcv_evd->ib_cq_handle;
+       else if (!ia_ptr->hca_ptr->ib_trans.ib_cq_empty)
+               rcv_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;
+       else {
+               struct ibv_comp_channel *channel;
+
+               channel = ibv_create_comp_channel(ia_ptr->hca_ptr->ib_hca_handle);
+               if (!channel)
+                       return (dapl_convert_errno(ENOMEM, "create_cq"));
+                 
+               /* Call IB verbs to create CQ */
+               rcv_cq = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle,
+                                      0, NULL, channel, 0);
+
+               if (rcv_cq == IB_INVALID_HANDLE) {
+                       ibv_destroy_comp_channel(channel);
+                       return (dapl_convert_errno(ENOMEM, "create_cq"));
+               }
+
+               ia_ptr->hca_ptr->ib_trans.ib_cq_empty = rcv_cq;
+       }
+       if (req_evd != DAT_HANDLE_NULL)
+               req_cq = req_evd->ib_cq_handle;
+       else
+               req_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;
+
+       /* 
+        * IMPLEMENTATION NOTE:
+        * uDAPL allows consumers to post buffers on the EP after creation
+        * and before a connect request (outbound and inbound). This forces
+        * a binding to a device during the hca_open call and requires the
+        * consumer to predetermine which device to listen on or connect from.
+        * This restriction eliminates any option of listening or connecting 
+        * over multiple devices. uDAPL should add API's to resolve addresses 
+        * and bind to the device at the approriate time (before connect 
+        * and after CR arrives). Discovery should happen at connection time 
+        * based on addressing and not on static configuration during open.
+        */
+
+#ifdef _OPENIB_CMA_
+       /* Allocate CM and initialize lock */
+       if ((conn = dapls_ib_cm_create(ep_ptr)) == NULL)
+               return (dapl_convert_errno(ENOMEM, "cm_create"));
+
+       /* open identifies the local device; per DAT specification */
+       if (rdma_bind_addr(conn->cm_id,
+               (struct sockaddr *)&ia_ptr->hca_ptr->hca_address)) {
+               dapls_cm_free(conn);
+               return (dapl_convert_errno(EAFNOSUPPORT, "rdma_bind_addr"));
+       }
+#endif
+       /* Setup attributes and create qp */
+       dapl_os_memzero((void *)&qp_create, sizeof(qp_create));
+       qp_create.send_cq = req_cq;
+       qp_create.cap.max_send_wr = attr->max_request_dtos;
+       qp_create.cap.max_send_sge = attr->max_request_iov;
+       qp_create.cap.max_inline_data =
+           ia_ptr->hca_ptr->ib_trans.max_inline_send;
+       qp_create.qp_type = IBV_QPT_RC;
+       qp_create.qp_context = (void *)ep_ptr;
+
+#ifdef DAT_EXTENSIONS 
+       if (attr->service_type == DAT_IB_SERVICE_TYPE_UD) {
+#ifdef _OPENIB_CMA_
+               return (DAT_NOT_IMPLEMENTED);
+#endif
+               qp_create.qp_type = IBV_QPT_UD;
+               if (attr->max_message_size >
+                   (128 << ia_ptr->hca_ptr->ib_trans.mtu)) {
+                       return (DAT_INVALID_PARAMETER | DAT_INVALID_ARG6);
+               }
+       }
+#endif
+       
+       /* ibv assumes rcv_cq is never NULL, set to req_cq */
+       if (rcv_cq == NULL) {
+               qp_create.recv_cq = req_cq;
+               qp_create.cap.max_recv_wr = 0;
+               qp_create.cap.max_recv_sge = 0;
+       } else {
+               qp_create.recv_cq = rcv_cq;
+               qp_create.cap.max_recv_wr = attr->max_recv_dtos;
+               qp_create.cap.max_recv_sge = attr->max_recv_iov;
+       }
+
+#ifdef _OPENIB_CMA_
+       if (rdma_create_qp(conn->cm_id, ib_pd_handle, &qp_create)) {
+               dapls_cm_free(conn);
+               return (dapl_convert_errno(errno, "rdma_create_qp"));
+       }
+       ep_ptr->qp_handle = conn->cm_id->qp;
+       ep_ptr->qp_state = IBV_QPS_INIT;
+
+       ep_ptr->param.local_port_qual = rdma_get_src_port(conn->cm_id);
+#else
+       ep_ptr->qp_handle = ibv_create_qp(ib_pd_handle, &qp_create);
+       if (!ep_ptr->qp_handle)
+               return (dapl_convert_errno(ENOMEM, "create_qp"));
+               
+       /* Setup QP attributes for INIT state on the way out */
+       if (dapls_modify_qp_state(ep_ptr->qp_handle,
+                                 IBV_QPS_INIT, 0, 0, 0) != DAT_SUCCESS) {
+               ibv_destroy_qp(ep_ptr->qp_handle);
+               ep_ptr->qp_handle = IB_INVALID_HANDLE;
+               return DAT_INTERNAL_ERROR;
+       }
+#endif
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " qp_alloc: qpn %p sq %d,%d rq %d,%d\n",
+                    ep_ptr->qp_handle->qp_num,
+                    qp_create.cap.max_send_wr, qp_create.cap.max_send_sge,
+                    qp_create.cap.max_recv_wr, qp_create.cap.max_recv_sge);
+
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapl_ib_qp_free
+ *
+ * Free a QP
+ *
+ * Input:
+ *     ia_handle       IA handle
+ *     *ep_ptr         pointer to EP INFO
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *  dapl_convert_errno
+ *
+ */
+DAT_RETURN dapls_ib_qp_free(IN DAPL_IA * ia_ptr, IN DAPL_EP * ep_ptr)
+{
+#ifdef _OPENIB_CMA_
+       dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+
+       dapl_os_lock(&ep_ptr->header.lock);
+       if (cm_ptr && cm_ptr->cm_id->qp) {
+               rdma_destroy_qp(cm_ptr->cm_id);
+               cm_ptr->cm_id->qp = NULL;
+               ep_ptr->qp_handle = NULL;
+       }
+#else
+       dapl_os_lock(&ep_ptr->header.lock);
+       if (ep_ptr->qp_handle != NULL) {
+               /* force error state to flush queue, then destroy */
+               dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0,0,0);
+
+               if (ibv_destroy_qp(ep_ptr->qp_handle)) {
+                       dapl_log(DAPL_DBG_TYPE_ERR, 
+                                " qp_free: ibv_destroy_qp error - %s\n",
+                                strerror(errno));
+               }
+               ep_ptr->qp_handle = NULL;
+       }
+#endif
+       dapl_os_unlock(&ep_ptr->header.lock);
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapl_ib_qp_modify
+ *
+ * Set the QP to the parameters specified in an EP_PARAM
+ *
+ * The EP_PARAM structure that is provided has been
+ * sanitized such that only non-zero values are valid.
+ *
+ * Input:
+ *     ib_hca_handle           HCA handle
+ *     qp_handle               QP handle
+ *     ep_attr                 Sanitized EP Params
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_qp_modify(IN DAPL_IA * ia_ptr,
+                  IN DAPL_EP * ep_ptr, IN DAT_EP_ATTR * attr)
+{
+       struct ibv_qp_attr qp_attr;
+
+       if (ep_ptr->qp_handle == IB_INVALID_HANDLE)
+               return DAT_INVALID_PARAMETER;
+
+       /* 
+        * EP state, qp_handle state should be an indication
+        * of current state but the only way to be sure is with
+        * a user mode ibv_query_qp call which is NOT available 
+        */
+
+       /* move to error state if necessary */
+       if ((ep_ptr->qp_state == IB_QP_STATE_ERROR) &&
+           (ep_ptr->qp_handle->state != IBV_QPS_ERR)) {
+               return (dapls_modify_qp_state(ep_ptr->qp_handle, 
+                                             IBV_QPS_ERR, 0, 0, 0));
+       }
+
+       /*
+        * Check if we have the right qp_state to modify attributes
+        */
+       if ((ep_ptr->qp_handle->state != IBV_QPS_RTR) &&
+           (ep_ptr->qp_handle->state != IBV_QPS_RTS))
+               return DAT_INVALID_STATE;
+
+       /* Adjust to current EP attributes */
+       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
+       qp_attr.cap.max_send_wr = attr->max_request_dtos;
+       qp_attr.cap.max_recv_wr = attr->max_recv_dtos;
+       qp_attr.cap.max_send_sge = attr->max_request_iov;
+       qp_attr.cap.max_recv_sge = attr->max_recv_iov;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    "modify_qp: qp %p sq %d,%d, rq %d,%d\n",
+                    ep_ptr->qp_handle,
+                    qp_attr.cap.max_send_wr, qp_attr.cap.max_send_sge,
+                    qp_attr.cap.max_recv_wr, qp_attr.cap.max_recv_sge);
+
+       if (ibv_modify_qp(ep_ptr->qp_handle, &qp_attr, IBV_QP_CAP)) {
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+                            "modify_qp: modify ep %p qp %p failed\n",
+                            ep_ptr, ep_ptr->qp_handle);
+               return (dapl_convert_errno(errno, "modify_qp_state"));
+       }
+
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_reinit_ep
+ *
+ * Move the QP to INIT state again.
+ *
+ * Input:
+ *     ep_ptr          DAPL_EP
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     void
+ *
+ */
+#if defined(_WIN32) || defined(_WIN64) || defined(_OPENIB_CMA_)
+void dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)
+{
+       dp_ib_cm_handle_t cm_ptr, next_cm_ptr;
+
+       /* work around bug in low level driver - 3/24/09 */
+       /* RTS -> RESET -> INIT -> ERROR QP transition crashes system */
+       if (ep_ptr->qp_handle != IB_INVALID_HANDLE) {
+               dapls_ib_qp_free(ep_ptr->header.owner_ia, ep_ptr);
+               
+               /* free any CM object's created */
+               cm_ptr = (dapl_llist_is_empty(&ep_ptr->cm_list_head)
+                         ? NULL : dapl_llist_peek_head(&ep_ptr->cm_list_head));
+               while (cm_ptr != NULL) {
+                       next_cm_ptr = dapl_llist_next_entry(&ep_ptr->cm_list_head,
+                                                           &cm_ptr->list_entry);
+                       dapls_cm_free(cm_ptr); 
+                       cm_ptr = next_cm_ptr;
+               }
+               dapls_ib_qp_alloc(ep_ptr->header.owner_ia, ep_ptr, ep_ptr);
+       }
+}
+#else                          // _WIN32 || _WIN64
+void dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)
+{
+       if (ep_ptr->qp_handle != IB_INVALID_HANDLE &&
+           ep_ptr->qp_handle->qp_type != IBV_QPT_UD) {
+               /* move to RESET state and then to INIT */
+               dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_RESET,0,0,0);
+               dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_INIT,0,0,0);
+       }
+}
+#endif                         // _WIN32 || _WIN64
+
+/* 
+ * Generic QP modify for init, reset, error, RTS, RTR
+ * For UD, create_ah on RTR, qkey on INIT
+ * CM msg provides QP attributes, info in network order
+ */
+DAT_RETURN
+dapls_modify_qp_state(IN ib_qp_handle_t                qp_handle,
+                     IN ib_qp_state_t          qp_state, 
+                     IN uint32_t               qpn,
+                     IN uint16_t               lid,
+                     IN ib_gid_handle_t        gid)
+{
+       struct ibv_qp_attr qp_attr;
+       enum ibv_qp_attr_mask mask = IBV_QP_STATE;
+       DAPL_EP *ep_ptr = (DAPL_EP *) qp_handle->qp_context;
+       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;
+       int ret;
+
+       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
+       qp_attr.qp_state = qp_state;
+       
+       switch (qp_state) {
+       case IBV_QPS_RTR:
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                               " QPS_RTR: type %d qpn 0x%x gid %p (%d) lid 0x%x"
+                               " port %d ep %p qp_state %d \n",
+                               qp_handle->qp_type, ntohl(qpn), gid, 
+                               ia_ptr->hca_ptr->ib_trans.global,
+                               ntohs(lid), ia_ptr->hca_ptr->port_num,
+                               ep_ptr, ep_ptr->qp_state);
+
+               mask |= IBV_QP_AV |
+                       IBV_QP_PATH_MTU |
+                       IBV_QP_DEST_QPN |
+                       IBV_QP_RQ_PSN |
+                       IBV_QP_MAX_DEST_RD_ATOMIC | IBV_QP_MIN_RNR_TIMER;
+
+               qp_attr.dest_qp_num = ntohl(qpn);
+               qp_attr.rq_psn = 1;
+               qp_attr.path_mtu = ia_ptr->hca_ptr->ib_trans.mtu;
+               qp_attr.max_dest_rd_atomic =
+                       ep_ptr->param.ep_attr.max_rdma_read_out;
+               qp_attr.min_rnr_timer =
+                       ia_ptr->hca_ptr->ib_trans.rnr_timer;
+
+               /* address handle. RC and UD */
+               qp_attr.ah_attr.dlid = ntohs(lid);
+               if (gid && ia_ptr->hca_ptr->ib_trans.global) {
+                       dapl_dbg_log(DAPL_DBG_TYPE_EP, 
+                                    " QPS_RTR: GID Subnet 0x" F64x " ID 0x" F64x "\n", 
+                                    (unsigned long long)htonll(gid->global.subnet_prefix),
+                                    (unsigned long long)htonll(gid->global.interface_id));
+
+                       qp_attr.ah_attr.is_global = 1;
+                       qp_attr.ah_attr.grh.dgid.global.subnet_prefix = 
+                               gid->global.subnet_prefix;
+                       qp_attr.ah_attr.grh.dgid.global.interface_id = 
+                               gid->global.interface_id;
+                       qp_attr.ah_attr.grh.hop_limit =
+                               ia_ptr->hca_ptr->ib_trans.hop_limit;
+                       qp_attr.ah_attr.grh.traffic_class =
+                               ia_ptr->hca_ptr->ib_trans.tclass;
+               }
+               qp_attr.ah_attr.sl = 0;
+               qp_attr.ah_attr.src_path_bits = 0;
+               qp_attr.ah_attr.port_num = ia_ptr->hca_ptr->port_num;
+
+               /* UD: already in RTR, RTS state */
+               if (qp_handle->qp_type == IBV_QPT_UD) {
+                       mask = IBV_QP_STATE;
+                       if (ep_ptr->qp_state == IBV_QPS_RTR ||
+                               ep_ptr->qp_state == IBV_QPS_RTS)
+                               return DAT_SUCCESS;
+               }
+               break;
+       case IBV_QPS_RTS:
+               if (qp_handle->qp_type == IBV_QPT_RC) {
+                       mask |= IBV_QP_SQ_PSN |
+                               IBV_QP_TIMEOUT |
+                               IBV_QP_RETRY_CNT |
+                               IBV_QP_RNR_RETRY | IBV_QP_MAX_QP_RD_ATOMIC;
+                       qp_attr.timeout =
+                               ia_ptr->hca_ptr->ib_trans.ack_timer;
+                       qp_attr.retry_cnt =
+                               ia_ptr->hca_ptr->ib_trans.ack_retry;
+                       qp_attr.rnr_retry =
+                               ia_ptr->hca_ptr->ib_trans.rnr_retry;
+                       qp_attr.max_rd_atomic =
+                               ep_ptr->param.ep_attr.max_rdma_read_out;
+               }
+               /* RC and UD */
+               qp_attr.qp_state = IBV_QPS_RTS;
+               qp_attr.sq_psn = 1;
+
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                               " QPS_RTS: psn %x rd_atomic %d ack %d "
+                               " retry %d rnr_retry %d ep %p qp_state %d\n",
+                               qp_attr.sq_psn, qp_attr.max_rd_atomic,
+                               qp_attr.timeout, qp_attr.retry_cnt,
+                               qp_attr.rnr_retry, ep_ptr,
+                               ep_ptr->qp_state);
+
+               if (qp_handle->qp_type == IBV_QPT_UD) {
+                       /* already RTS, multi remote AH's on QP */
+                       if (ep_ptr->qp_state == IBV_QPS_RTS)
+                               return DAT_SUCCESS;
+                       else
+                               mask = IBV_QP_STATE | IBV_QP_SQ_PSN;
+               }
+               break;
+       case IBV_QPS_INIT:
+               mask |= IBV_QP_PKEY_INDEX | IBV_QP_PORT;
+               if (qp_handle->qp_type == IBV_QPT_RC) {
+                       mask |= IBV_QP_ACCESS_FLAGS;
+                       qp_attr.qp_access_flags =
+                               IBV_ACCESS_LOCAL_WRITE |
+                               IBV_ACCESS_REMOTE_WRITE |
+                               IBV_ACCESS_REMOTE_READ |
+                               IBV_ACCESS_REMOTE_ATOMIC |
+                               IBV_ACCESS_MW_BIND;
+               }
+
+               if (qp_handle->qp_type == IBV_QPT_UD) {
+                       /* already INIT, multi remote AH's on QP */
+                       if (ep_ptr->qp_state == IBV_QPS_INIT)
+                               return DAT_SUCCESS;
+                       mask |= IBV_QP_QKEY;
+                       qp_attr.qkey = DAT_UD_QKEY;
+               }
+
+               qp_attr.pkey_index = 0;
+               qp_attr.port_num = ia_ptr->hca_ptr->port_num;
+
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                               " QPS_INIT: pi %x port %x acc %x qkey 0x%x\n",
+                               qp_attr.pkey_index, qp_attr.port_num,
+                               qp_attr.qp_access_flags, qp_attr.qkey);
+               break;
+       default:
+               break;
+       }
+
+       ret = ibv_modify_qp(qp_handle, &qp_attr, mask);
+       if (ret == 0) {
+               ep_ptr->qp_state = qp_state;
+               return DAT_SUCCESS;
+       } else {
+               return (dapl_convert_errno(errno, "modify_qp_state"));
+       }
+}
+
+/* Modify UD type QP from init, rtr, rts, info network order */
+DAT_RETURN 
+dapls_modify_qp_ud(IN DAPL_HCA *hca, IN ib_qp_handle_t qp)
+{
+       struct ibv_qp_attr qp_attr;
+
+       /* modify QP, setup and prepost buffers */
+       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
+       qp_attr.qp_state = IBV_QPS_INIT;
+        qp_attr.pkey_index = 0;
+        qp_attr.port_num = hca->port_num;
+        qp_attr.qkey = DAT_UD_QKEY;
+       if (ibv_modify_qp(qp, &qp_attr, 
+                         IBV_QP_STATE          |
+                         IBV_QP_PKEY_INDEX     |
+                          IBV_QP_PORT          |
+                          IBV_QP_QKEY)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                       " modify_ud_qp INIT: ERR %s\n", strerror(errno));
+               return (dapl_convert_errno(errno, "modify_qp"));
+       }
+       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
+       qp_attr.qp_state = IBV_QPS_RTR;
+       if (ibv_modify_qp(qp, &qp_attr,IBV_QP_STATE)) {
+               dapl_log(DAPL_DBG_TYPE_ERR, 
+                       " modify_ud_qp RTR: ERR %s\n", strerror(errno));
+               return (dapl_convert_errno(errno, "modify_qp"));
+       }
+       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
+       qp_attr.qp_state = IBV_QPS_RTS;
+       qp_attr.sq_psn = 1;
+       if (ibv_modify_qp(qp, &qp_attr, 
+                         IBV_QP_STATE | IBV_QP_SQ_PSN)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                       " modify_ud_qp RTS: ERR %s\n", strerror(errno));
+               return (dapl_convert_errno(errno, "modify_qp"));
+       }
+       return DAT_SUCCESS;
+}
+
+/* Create address handle for remote QP, info in network order */
+ib_ah_handle_t 
+dapls_create_ah(IN DAPL_HCA            *hca,
+               IN ib_pd_handle_t       pd,
+               IN ib_qp_handle_t       qp,
+               IN uint16_t             lid,
+               IN ib_gid_handle_t      gid)
+{
+       struct ibv_qp_attr qp_attr;
+       ib_ah_handle_t  ah;
+
+       if (qp->qp_type != IBV_QPT_UD)
+               return NULL;
+
+       dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
+       qp_attr.qp_state = IBV_QP_STATE;
+
+       /* address handle. RC and UD */
+       qp_attr.ah_attr.dlid = ntohs(lid);
+       if (gid != NULL) {
+               dapl_log(DAPL_DBG_TYPE_CM, "dapl_create_ah: with GID\n");
+               qp_attr.ah_attr.is_global = 1;
+               qp_attr.ah_attr.grh.dgid.global.subnet_prefix = 
+                               ntohll(gid->global.subnet_prefix);
+               qp_attr.ah_attr.grh.dgid.global.interface_id = 
+                               ntohll(gid->global.interface_id);
+               qp_attr.ah_attr.grh.hop_limit = hca->ib_trans.hop_limit;
+               qp_attr.ah_attr.grh.traffic_class = hca->ib_trans.tclass;
+       }
+       qp_attr.ah_attr.sl = 0;
+       qp_attr.ah_attr.src_path_bits = 0;
+       qp_attr.ah_attr.port_num = hca->port_num;
+
+       dapl_log(DAPL_DBG_TYPE_CM, 
+                       " dapls_create_ah: port %x lid %x pd %p ctx %p handle 0x%x\n", 
+                       hca->port_num,qp_attr.ah_attr.dlid, pd, pd->context, pd->handle);
+
+       /* UD: create AH for remote side */
+       ah = ibv_create_ah(pd, &qp_attr.ah_attr);
+       if (!ah) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                       " create_ah: ERR %s\n", strerror(errno));
+               return NULL;
+       }
+
+       dapl_log(DAPL_DBG_TYPE_CM, 
+                       " dapls_create_ah: AH %p for lid %x\n", 
+                       ah, qp_attr.ah_attr.dlid);
+
+       return ah;
+}
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 8
+ * End:
+ */
index 3963e1f9b1bc9755c9cbae580076fbb46c8b42cd..704d85ad29c529aa132663415f7ef03a7f25a167 100644 (file)
@@ -471,3 +471,110 @@ void dapls_query_provider_specific_attr(IN DAPL_IA * ia_ptr,
        /* set MTU to actual settings */
        ib_attrs[0].value = ia_ptr->hca_ptr->ib_trans.named_attr.value;
 }
+
+/*
+ * Map all socket CM event codes to the DAT equivelent. Common to all providers
+ */
+#define DAPL_IB_EVENT_CNT      13
+
+static struct ib_cm_event_map {
+       const ib_cm_events_t ib_cm_event;
+       DAT_EVENT_NUMBER dat_event_num;
+} ib_cm_event_map[DAPL_IB_EVENT_CNT] = {
+/* 00 */ {IB_CME_CONNECTED, 
+         DAT_CONNECTION_EVENT_ESTABLISHED},
+/* 01 */ {IB_CME_DISCONNECTED, 
+         DAT_CONNECTION_EVENT_DISCONNECTED},
+/* 02 */ {IB_CME_DISCONNECTED_ON_LINK_DOWN,
+         DAT_CONNECTION_EVENT_DISCONNECTED},
+/* 03 */ {IB_CME_CONNECTION_REQUEST_PENDING, 
+         DAT_CONNECTION_REQUEST_EVENT},
+/* 04 */ {IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,
+         DAT_CONNECTION_REQUEST_EVENT},
+/* 05 */ {IB_CME_CONNECTION_REQUEST_ACKED,
+         DAT_CONNECTION_EVENT_ESTABLISHED},
+/* 06 */ {IB_CME_DESTINATION_REJECT,
+         DAT_CONNECTION_EVENT_NON_PEER_REJECTED},
+/* 07 */ {IB_CME_DESTINATION_REJECT_PRIVATE_DATA,
+         DAT_CONNECTION_EVENT_PEER_REJECTED},
+/* 08 */ {IB_CME_DESTINATION_UNREACHABLE, 
+         DAT_CONNECTION_EVENT_UNREACHABLE},
+/* 09 */ {IB_CME_TOO_MANY_CONNECTION_REQUESTS,
+         DAT_CONNECTION_EVENT_NON_PEER_REJECTED},
+/* 10 */ {IB_CME_BROKEN, 
+         DAT_CONNECTION_EVENT_BROKEN},
+/* 11 */ {IB_CME_TIMEOUT, 
+         DAT_CONNECTION_EVENT_TIMED_OUT},
+/* 12 */ {IB_CME_LOCAL_FAILURE,                /* always last */
+         DAT_CONNECTION_EVENT_BROKEN}
+};
+
+/*
+ * dapls_ib_get_cm_event
+ *
+ * Return a DAT connection event given a provider CM event.
+ *
+ * Input:
+ *     dat_event_num   DAT event we need an equivelent CM event for
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     ib_cm_event of translated DAPL value
+ */
+DAT_EVENT_NUMBER
+dapls_ib_get_dat_event(IN const ib_cm_events_t ib_cm_event,
+                      IN DAT_BOOLEAN active)
+{
+       DAT_EVENT_NUMBER dat_event_num;
+       int i;
+
+       active = active;
+
+       if (ib_cm_event > IB_CME_LOCAL_FAILURE)
+               return (DAT_EVENT_NUMBER) 0;
+
+       dat_event_num = 0;
+       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {
+               if (ib_cm_event == ib_cm_event_map[i].ib_cm_event) {
+                       dat_event_num = ib_cm_event_map[i].dat_event_num;
+                       break;
+               }
+       }
+       dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
+                    "dapls_ib_get_dat_event: event translate(%s) ib=0x%x dat=0x%x\n",
+                    active ? "active" : "passive", ib_cm_event, dat_event_num);
+
+       return dat_event_num;
+}
+
+/*
+ * dapls_ib_get_dat_event
+ *
+ * Return a DAT connection event given a provider CM event.
+ * 
+ * Input:
+ *     ib_cm_event     event provided to the dapl callback routine
+ *     active          switch indicating active or passive connection
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_EVENT_NUMBER of translated provider value
+ */
+ib_cm_events_t dapls_ib_get_cm_event(IN DAT_EVENT_NUMBER dat_event_num)
+{
+       ib_cm_events_t ib_cm_event;
+       int i;
+
+       ib_cm_event = 0;
+       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {
+               if (dat_event_num == ib_cm_event_map[i].dat_event_num) {
+                       ib_cm_event = ib_cm_event_map[i].ib_cm_event;
+                       break;
+               }
+       }
+       return ib_cm_event;
+}
index 03ba3acfd70922fd0c71450e4533801c328b88c1..6958b67450be587b61baa163cf2181f5a653d9d8 100644 (file)
-/*\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/***************************************************************************\r
- *\r
- *   Module:            uDAPL\r
- *\r
- *   Filename:          dapl_ib_cm.c\r
- *\r
- *   Author:            Arlin Davis\r
- *\r
- *   Created:           3/10/2005\r
- *\r
- *   Description: \r
- *\r
- *   The uDAPL openib provider - connection management\r
- *\r
- ****************************************************************************\r
- *                Source Control System Information\r
- *\r
- *    $Id: $\r
- *\r
- *     Copyright (c) 2005 Intel Corporation.  All rights reserved.\r
- *\r
- **************************************************************************/\r
-\r
-#if defined(_WIN32)\r
-#define FD_SETSIZE 1024\r
-#define DAPL_FD_SETSIZE FD_SETSIZE\r
-#endif\r
-\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_cr_util.h"\r
-#include "dapl_name_service.h"\r
-#include "dapl_ib_util.h"\r
-#include "dapl_osd.h"\r
-\r
-#if defined(_WIN32) || defined(_WIN64)\r
-enum DAPL_FD_EVENTS {\r
-       DAPL_FD_READ = 0x1,\r
-       DAPL_FD_WRITE = 0x2,\r
-       DAPL_FD_ERROR = 0x4\r
-};\r
-\r
-static int dapl_config_socket(DAPL_SOCKET s)\r
-{\r
-       unsigned long nonblocking = 1;\r
-       int ret, opt;\r
-\r
-       ret = ioctlsocket(s, FIONBIO, &nonblocking);\r
-\r
-       /* no delay for small packets */\r
-       if (!ret)\r
-               ret = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, \r
-                                (char *)&opt, sizeof(opt));\r
-       return ret;\r
-}\r
-\r
-static int dapl_connect_socket(DAPL_SOCKET s, struct sockaddr *addr,\r
-                              int addrlen)\r
-{\r
-       int err;\r
-\r
-       err = connect(s, addr, addrlen);\r
-       if (err == SOCKET_ERROR)\r
-               err = WSAGetLastError();\r
-       return (err == WSAEWOULDBLOCK) ? EAGAIN : err;\r
-}\r
-\r
-struct dapl_fd_set {\r
-       struct fd_set set[3];\r
-};\r
-\r
-static struct dapl_fd_set *dapl_alloc_fd_set(void)\r
-{\r
-       return dapl_os_alloc(sizeof(struct dapl_fd_set));\r
-}\r
-\r
-static void dapl_fd_zero(struct dapl_fd_set *set)\r
-{\r
-       FD_ZERO(&set->set[0]);\r
-       FD_ZERO(&set->set[1]);\r
-       FD_ZERO(&set->set[2]);\r
-}\r
-\r
-static int dapl_fd_set(DAPL_SOCKET s, struct dapl_fd_set *set,\r
-                      enum DAPL_FD_EVENTS event)\r
-{\r
-       FD_SET(s, &set->set[(event == DAPL_FD_READ) ? 0 : 1]);\r
-       FD_SET(s, &set->set[2]);\r
-       return 0;\r
-}\r
-\r
-static enum DAPL_FD_EVENTS dapl_poll(DAPL_SOCKET s, enum DAPL_FD_EVENTS event)\r
-{\r
-       struct fd_set rw_fds;\r
-       struct fd_set err_fds;\r
-       struct timeval tv;\r
-       int ret;\r
-\r
-       FD_ZERO(&rw_fds);\r
-       FD_ZERO(&err_fds);\r
-       FD_SET(s, &rw_fds);\r
-       FD_SET(s, &err_fds);\r
-\r
-       tv.tv_sec = 0;\r
-       tv.tv_usec = 0;\r
-\r
-       if (event == DAPL_FD_READ)\r
-               ret = select(1, &rw_fds, NULL, &err_fds, &tv);\r
-       else\r
-               ret = select(1, NULL, &rw_fds, &err_fds, &tv);\r
-\r
-       if (ret == 0)\r
-               return 0;\r
-       else if (ret == SOCKET_ERROR)\r
-               return DAPL_FD_ERROR;\r
-       else if (FD_ISSET(s, &rw_fds))\r
-               return event;\r
-       else\r
-               return DAPL_FD_ERROR;\r
-}\r
-\r
-static int dapl_select(struct dapl_fd_set *set)\r
-{\r
-       int ret;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: sleep\n");\r
-       ret = select(0, &set->set[0], &set->set[1], &set->set[2], NULL);\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: wakeup\n");\r
-\r
-       if (ret == SOCKET_ERROR)\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " dapl_select: error 0x%x\n", WSAGetLastError());\r
-\r
-       return ret;\r
-}\r
-\r
-static int dapl_socket_errno(void)\r
-{\r
-       int err;\r
-\r
-       err = WSAGetLastError();\r
-       switch (err) {\r
-       case WSAEACCES:\r
-       case WSAEADDRINUSE:\r
-               return EADDRINUSE;\r
-       case WSAECONNRESET:\r
-               return ECONNRESET;\r
-       default:\r
-               return err;\r
-       }\r
-}\r
-#else                          // _WIN32 || _WIN64\r
-enum DAPL_FD_EVENTS {\r
-       DAPL_FD_READ = POLLIN,\r
-       DAPL_FD_WRITE = POLLOUT,\r
-       DAPL_FD_ERROR = POLLERR\r
-};\r
-\r
-static int dapl_config_socket(DAPL_SOCKET s)\r
-{\r
-       int ret, opt = 1;\r
-\r
-       /* non-blocking */\r
-       ret = fcntl(s, F_GETFL);\r
-       if (ret >= 0)\r
-               ret = fcntl(s, F_SETFL, ret | O_NONBLOCK);\r
-\r
-       /* no delay for small packets */\r
-       if (!ret)\r
-               ret = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, \r
-                                (char *)&opt, sizeof(opt));\r
-       return ret;\r
-}\r
-\r
-static int dapl_connect_socket(DAPL_SOCKET s, struct sockaddr *addr,\r
-                              int addrlen)\r
-{\r
-       int ret;\r
-\r
-       ret = connect(s, addr, addrlen);\r
-\r
-       return (errno == EINPROGRESS) ? EAGAIN : ret;\r
-}\r
-\r
-struct dapl_fd_set {\r
-       int index;\r
-       struct pollfd set[DAPL_FD_SETSIZE];\r
-};\r
-\r
-static struct dapl_fd_set *dapl_alloc_fd_set(void)\r
-{\r
-       return dapl_os_alloc(sizeof(struct dapl_fd_set));\r
-}\r
-\r
-static void dapl_fd_zero(struct dapl_fd_set *set)\r
-{\r
-       set->index = 0;\r
-}\r
-\r
-static int dapl_fd_set(DAPL_SOCKET s, struct dapl_fd_set *set,\r
-                      enum DAPL_FD_EVENTS event)\r
-{\r
-       if (set->index == DAPL_FD_SETSIZE - 1) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        "SCM ERR: cm_thread exceeded FD_SETSIZE %d\n",\r
-                        set->index + 1);\r
-               return -1;\r
-       }\r
-\r
-       set->set[set->index].fd = s;\r
-       set->set[set->index].revents = 0;\r
-       set->set[set->index++].events = event;\r
-       return 0;\r
-}\r
-\r
-static enum DAPL_FD_EVENTS dapl_poll(DAPL_SOCKET s, enum DAPL_FD_EVENTS event)\r
-{\r
-       struct pollfd fds;\r
-       int ret;\r
-\r
-       fds.fd = s;\r
-       fds.events = event;\r
-       fds.revents = 0;\r
-       ret = poll(&fds, 1, 0);\r
-       dapl_log(DAPL_DBG_TYPE_CM, " dapl_poll: fd=%d ret=%d, evnts=0x%x\n",\r
-                s, ret, fds.revents);\r
-       if (ret == 0)\r
-               return 0;\r
-       else if (ret < 0 || (fds.revents & (POLLERR | POLLHUP | POLLNVAL))) \r
-               return DAPL_FD_ERROR;\r
-       else \r
-               return event;\r
-}\r
-\r
-static int dapl_select(struct dapl_fd_set *set)\r
-{\r
-       int ret;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: sleep, fds=%d\n", set->index);\r
-       ret = poll(set->set, set->index, -1);\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: wakeup, ret=0x%x\n", ret);\r
-       return ret;\r
-}\r
-\r
-#define dapl_socket_errno() errno\r
-#endif\r
-\r
-dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep)\r
-{\r
-       dp_ib_cm_handle_t cm_ptr;\r
-\r
-       /* Allocate CM, init lock, and initialize */\r
-       if ((cm_ptr = dapl_os_alloc(sizeof(*cm_ptr))) == NULL)\r
-               return NULL;\r
-\r
-       (void)dapl_os_memzero(cm_ptr, sizeof(*cm_ptr));\r
-       if (dapl_os_lock_init(&cm_ptr->lock))\r
-               goto bail;\r
-\r
-       cm_ptr->msg.ver = htons(DCM_VER);\r
-       cm_ptr->socket = DAPL_INVALID_SOCKET;\r
-       cm_ptr->ep = ep;\r
-       return cm_ptr;\r
-bail:\r
-       dapl_os_free(cm_ptr, sizeof(*cm_ptr));\r
-       return NULL;\r
-}\r
-\r
-/* mark for destroy, remove all references, schedule cleanup */\r
-/* cm_ptr == NULL (UD), then multi CR's, kill all associated with EP */\r
-void dapls_ib_cm_free(dp_ib_cm_handle_t cm_ptr, DAPL_EP *ep)\r
-{\r
-       DAPL_IA *ia_ptr;\r
-       DAPL_HCA *hca_ptr = NULL;\r
-       dp_ib_cm_handle_t cr, next_cr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " cm_destroy: cm %p ep %p\n", cm_ptr, ep);\r
-\r
-       if (cm_ptr == NULL)\r
-               goto multi_cleanup;\r
-\r
-       /* to notify cleanup thread */\r
-       hca_ptr = cm_ptr->hca;\r
-\r
-       /* cleanup, never made it to work queue */\r
-       dapl_os_lock(&cm_ptr->lock);\r
-       if (cm_ptr->state == DCM_INIT) {\r
-               if (cm_ptr->socket != DAPL_INVALID_SOCKET) {\r
-                       shutdown(cm_ptr->socket, SHUT_RDWR);\r
-                       closesocket(cm_ptr->socket);\r
-               }\r
-               dapl_os_unlock(&cm_ptr->lock);\r
-               dapl_os_lock_destroy(&cm_ptr->lock);\r
-               dapl_os_free(cm_ptr, sizeof(*cm_ptr));\r
-               return;\r
-       }\r
-\r
-       /* free could be called before disconnect, disc_clean will destroy */\r
-       if (cm_ptr->state == DCM_CONNECTED) {\r
-               dapl_os_unlock(&cm_ptr->lock);\r
-               dapli_socket_disconnect(cm_ptr);\r
+/*
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/***************************************************************************
+ *
+ *   Module:            uDAPL
+ *
+ *   Filename:          dapl_ib_cm.c
+ *
+ *   Author:            Arlin Davis
+ *
+ *   Created:           3/10/2005
+ *
+ *   Description: 
+ *
+ *   The uDAPL openib provider - connection management
+ *
+ ****************************************************************************
+ *                Source Control System Information
+ *
+ *    $Id: $
+ *
+ *     Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ **************************************************************************/
+
+#if defined(_WIN32)
+#define FD_SETSIZE 1024
+#define DAPL_FD_SETSIZE FD_SETSIZE
+#endif
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_cr_util.h"
+#include "dapl_name_service.h"
+#include "dapl_ib_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_osd.h"
+
+#if defined(_WIN32) || defined(_WIN64)
+enum DAPL_FD_EVENTS {
+       DAPL_FD_READ = 0x1,
+       DAPL_FD_WRITE = 0x2,
+       DAPL_FD_ERROR = 0x4
+};
+
+static int dapl_config_socket(DAPL_SOCKET s)
+{
+       unsigned long nonblocking = 1;
+       int ret, opt = 1;
+
+       ret = ioctlsocket(s, FIONBIO, &nonblocking);
+
+       /* no delay for small packets */
+       if (!ret)
+               ret = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, 
+                                (char *)&opt, sizeof(opt));
+       return ret;
+}
+
+static int dapl_connect_socket(DAPL_SOCKET s, struct sockaddr *addr,
+                              int addrlen)
+{
+       int err;
+
+       err = connect(s, addr, addrlen);
+       if (err == SOCKET_ERROR)
+               err = WSAGetLastError();
+       return (err == WSAEWOULDBLOCK) ? EAGAIN : err;
+}
+
+struct dapl_fd_set {
+       struct fd_set set[3];
+};
+
+static struct dapl_fd_set *dapl_alloc_fd_set(void)
+{
+       return dapl_os_alloc(sizeof(struct dapl_fd_set));
+}
+
+static void dapl_fd_zero(struct dapl_fd_set *set)
+{
+       FD_ZERO(&set->set[0]);
+       FD_ZERO(&set->set[1]);
+       FD_ZERO(&set->set[2]);
+}
+
+static int dapl_fd_set(DAPL_SOCKET s, struct dapl_fd_set *set,
+                      enum DAPL_FD_EVENTS event)
+{
+       FD_SET(s, &set->set[(event == DAPL_FD_READ) ? 0 : 1]);
+       FD_SET(s, &set->set[2]);
+       return 0;
+}
+
+static enum DAPL_FD_EVENTS dapl_poll(DAPL_SOCKET s, enum DAPL_FD_EVENTS event)
+{
+       struct fd_set rw_fds;
+       struct fd_set err_fds;
+       struct timeval tv;
+       int ret;
+
+       FD_ZERO(&rw_fds);
+       FD_ZERO(&err_fds);
+       FD_SET(s, &rw_fds);
+       FD_SET(s, &err_fds);
+
+       tv.tv_sec = 0;
+       tv.tv_usec = 0;
+
+       if (event == DAPL_FD_READ)
+               ret = select(1, &rw_fds, NULL, &err_fds, &tv);
+       else
+               ret = select(1, NULL, &rw_fds, &err_fds, &tv);
+
+       if (ret == 0)
+               return 0;
+       else if (ret == SOCKET_ERROR)
+               return DAPL_FD_ERROR;
+       else if (FD_ISSET(s, &rw_fds))
+               return event;
+       else
+               return DAPL_FD_ERROR;
+}
+
+static int dapl_select(struct dapl_fd_set *set)
+{
+       int ret;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: sleep\n");
+       ret = select(0, &set->set[0], &set->set[1], &set->set[2], NULL);
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: wakeup\n");
+
+       if (ret == SOCKET_ERROR)
+               dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                            " dapl_select: error 0x%x\n", WSAGetLastError());
+
+       return ret;
+}
+
+static int dapl_socket_errno(void)
+{
+       int err;
+
+       err = WSAGetLastError();
+       switch (err) {
+       case WSAEACCES:
+       case WSAEADDRINUSE:
+               return EADDRINUSE;
+       case WSAECONNRESET:
+               return ECONNRESET;
+       default:
+               return err;
+       }
+}
+#else                          // _WIN32 || _WIN64
+enum DAPL_FD_EVENTS {
+       DAPL_FD_READ = POLLIN,
+       DAPL_FD_WRITE = POLLOUT,
+       DAPL_FD_ERROR = POLLERR
+};
+
+static int dapl_config_socket(DAPL_SOCKET s)
+{
+       int ret, opt = 1;
+
+       /* non-blocking */
+       ret = fcntl(s, F_GETFL);
+       if (ret >= 0)
+               ret = fcntl(s, F_SETFL, ret | O_NONBLOCK);
+
+       /* no delay for small packets */
+       if (!ret)
+               ret = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, 
+                                (char *)&opt, sizeof(opt));
+       return ret;
+}
+
+static int dapl_connect_socket(DAPL_SOCKET s, struct sockaddr *addr,
+                              int addrlen)
+{
+       int ret;
+
+       ret = connect(s, addr, addrlen);
+
+       return (errno == EINPROGRESS) ? EAGAIN : ret;
+}
+
+struct dapl_fd_set {
+       int index;
+       struct pollfd set[DAPL_FD_SETSIZE];
+};
+
+static struct dapl_fd_set *dapl_alloc_fd_set(void)
+{
+       return dapl_os_alloc(sizeof(struct dapl_fd_set));
+}
+
+static void dapl_fd_zero(struct dapl_fd_set *set)
+{
+       set->index = 0;
+}
+
+static int dapl_fd_set(DAPL_SOCKET s, struct dapl_fd_set *set,
+                      enum DAPL_FD_EVENTS event)
+{
+       if (set->index == DAPL_FD_SETSIZE - 1) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        "SCM ERR: cm_thread exceeded FD_SETSIZE %d\n",
+                        set->index + 1);
+               return -1;
+       }
+
+       set->set[set->index].fd = s;
+       set->set[set->index].revents = 0;
+       set->set[set->index++].events = event;
+       return 0;
+}
+
+static enum DAPL_FD_EVENTS dapl_poll(DAPL_SOCKET s, enum DAPL_FD_EVENTS event)
+{
+       struct pollfd fds;
+       int ret;
+
+       fds.fd = s;
+       fds.events = event;
+       fds.revents = 0;
+       ret = poll(&fds, 1, 0);
+       dapl_log(DAPL_DBG_TYPE_THREAD, " dapl_poll: fd=%d ret=%d, evnts=0x%x\n",
+                s, ret, fds.revents);
+       if (ret == 0)
+               return 0;
+       else if (ret < 0 || (fds.revents & (POLLERR | POLLHUP | POLLNVAL))) 
+               return DAPL_FD_ERROR;
+       else 
+               return event;
+}
+
+static int dapl_select(struct dapl_fd_set *set)
+{
+       int ret;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " dapl_select: sleep, fds=%d\n", set->index);
+       ret = poll(set->set, set->index, -1);
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " dapl_select: wakeup, ret=0x%x\n", ret);
+       return ret;
+}
+
+#define dapl_socket_errno() errno
+#endif
+
+static void dapli_cm_thread_signal(dp_ib_cm_handle_t cm_ptr) 
+{
+       send(cm_ptr->hca->ib_trans.scm[1], "w", sizeof "w", 0);
+}
+
+static void dapli_cm_free(dp_ib_cm_handle_t cm_ptr) 
+{
+       dapl_os_lock(&cm_ptr->lock);
+       cm_ptr->state = DCM_FREE;
+       dapl_os_unlock(&cm_ptr->lock);
+       dapli_cm_thread_signal(cm_ptr);
+}
+
+static void dapli_cm_dealloc(dp_ib_cm_handle_t cm_ptr) 
+{
+       dapl_os_assert(!cm_ptr->ref_count);
+       
+       if (cm_ptr->socket != DAPL_INVALID_SOCKET) {
+               shutdown(cm_ptr->socket, SHUT_RDWR);
+               closesocket(cm_ptr->socket);
+       }
+       if (cm_ptr->ah) 
+               ibv_destroy_ah(cm_ptr->ah);
+       
+       dapl_os_lock_destroy(&cm_ptr->lock);
+       dapl_os_wait_object_destroy(&cm_ptr->event);
+       dapl_os_free(cm_ptr, sizeof(*cm_ptr));
+}
+
+void dapls_cm_acquire(dp_ib_cm_handle_t cm_ptr)
+{
+       dapl_os_lock(&cm_ptr->lock);
+       cm_ptr->ref_count++;
+       dapl_os_unlock(&cm_ptr->lock);
+}
+
+void dapls_cm_release(dp_ib_cm_handle_t cm_ptr)
+{
+       dapl_os_lock(&cm_ptr->lock);
+       cm_ptr->ref_count--;\r
+       if (cm_ptr->ref_count) {\r
+                dapl_os_unlock(&cm_ptr->lock);\r
                return;\r
        }\r
-\r
-       cm_ptr->state = DCM_DESTROY;\r
-       if ((cm_ptr->ep) && (cm_ptr->ep->cm_handle == cm_ptr)) {\r
-               cm_ptr->ep->cm_handle = IB_INVALID_HANDLE;\r
-               cm_ptr->ep = NULL;\r
-       }\r
-\r
-       dapl_os_unlock(&cm_ptr->lock);\r
-       goto notify_thread;\r
-\r
-multi_cleanup:\r
-\r
-       /* \r
-        * UD CR objects are kept active because of direct private data references\r
-        * from CONN events. The cr->socket is closed and marked inactive but the \r
-        * object remains allocated and queued on the CR resource list. There can\r
-        * be multiple CR's associated with a given EP. There is no way to determine \r
-        * when consumer is finished with event until the dat_ep_free.\r
-        *\r
-        * Schedule destruction for all CR's associated with this EP, cr_thread will\r
-        * complete the cleanup with state == DCM_DESTROY. \r
-        */ \r
-       ia_ptr = ep->header.owner_ia;\r
-       dapl_os_lock(&ia_ptr->hca_ptr->ib_trans.lock);\r
-       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)\r
-                                 &ia_ptr->hca_ptr->ib_trans.list))\r
-            next_cr = dapl_llist_peek_head((DAPL_LLIST_HEAD*)\r
-                                           &ia_ptr->hca_ptr->ib_trans.list);\r
-       else\r
-           next_cr = NULL;\r
-\r
-       while (next_cr) {\r
-               cr = next_cr;\r
-               next_cr = dapl_llist_next_entry((DAPL_LLIST_HEAD*)\r
-                                               &ia_ptr->hca_ptr->ib_trans.list,\r
-                                               (DAPL_LLIST_ENTRY*)&cr->entry);\r
-               if (cr->ep == ep)  {\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                                    " qp_free CR: ep %p cr %p\n", ep, cr);\r
-                       dapli_socket_disconnect(cr);\r
-                       dapl_os_lock(&cr->lock);\r
-                       hca_ptr = cr->hca;\r
-                       cr->ep = NULL;\r
-                       if (cr->ah) {\r
-                               ibv_destroy_ah(cr->ah);\r
-                               cr->ah = NULL;\r
-                       }\r
-                       cr->state = DCM_DESTROY;\r
-                       dapl_os_unlock(&cr->lock);\r
-               }\r
-       }\r
-       dapl_os_unlock(&ia_ptr->hca_ptr->ib_trans.lock);\r
-\r
-notify_thread:\r
-\r
-       /* wakeup work thread, if something destroyed */\r
-       if (hca_ptr != NULL) \r
-               send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);\r
-}\r
-\r
-/* queue socket for processing CM work */\r
-static void dapli_cm_queue(struct ib_cm_handle *cm_ptr)\r
-{\r
-       DAPL_HCA *hca = cm_ptr->hca;\r
-\r
-       /* add to work queue for cr thread processing */\r
-       dapl_llist_init_entry((DAPL_LLIST_ENTRY *) & cm_ptr->entry);\r
-       dapl_os_lock(&hca->ib_trans.lock);\r
-       dapl_llist_add_tail(&hca->ib_trans.list,\r
-                           (DAPL_LLIST_ENTRY *) & cm_ptr->entry, cm_ptr);\r
-       dapl_os_unlock(&hca->ib_trans.lock);\r
-\r
-       /* wakeup CM work thread */\r
-       send(hca->ib_trans.scm[1], "w", sizeof "w", 0);\r
-}\r
-\r
-/*\r
- * ACTIVE/PASSIVE: called from CR thread or consumer via ep_disconnect\r
- *                 or from ep_free\r
- */\r
-DAT_RETURN dapli_socket_disconnect(dp_ib_cm_handle_t cm_ptr)\r
-{\r
-       DAPL_EP *ep_ptr = cm_ptr->ep;\r
-       DAT_UINT32 disc_data = htonl(0xdead);\r
-\r
-       if (ep_ptr == NULL)\r
-               return DAT_SUCCESS;\r
-\r
-       dapl_os_lock(&cm_ptr->lock);\r
-       if (cm_ptr->state != DCM_CONNECTED) {\r
-               dapl_os_unlock(&cm_ptr->lock);\r
-               return DAT_SUCCESS;\r
-       }\r
-\r
-       /* send disc date, close socket, schedule destroy */\r
-       dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0,0,0);\r
-       cm_ptr->state = DCM_DISCONNECTED;\r
-       send(cm_ptr->socket, (char *)&disc_data, sizeof(disc_data), 0);\r
-       dapl_os_unlock(&cm_ptr->lock);\r
-\r
-       /* disconnect events for RC's only */\r
-       if (ep_ptr->param.ep_attr.service_type == DAT_SERVICE_TYPE_RC) {\r
-               if (ep_ptr->cr_ptr) {\r
-                       dapls_cr_callback(cm_ptr,\r
-                                         IB_CME_DISCONNECTED,\r
-                                         NULL, 0,\r
-                                         ((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr);\r
-               } else {\r
-                       dapl_evd_connection_callback(ep_ptr->cm_handle,\r
-                                                    IB_CME_DISCONNECTED,\r
-                                                    NULL, 0, ep_ptr);\r
-               }\r
-       }\r
-\r
-       /* scheduled destroy via disconnect clean in callback */\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * ACTIVE: socket connected, send QP information to peer \r
- */\r
-static void dapli_socket_connected(dp_ib_cm_handle_t cm_ptr, int err)\r
-{\r
-       int len, exp;\r
-       struct iovec iov[2];\r
-       struct dapl_ep *ep_ptr = cm_ptr->ep;\r
-\r
-       if (err) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_PENDING: %s ERR %s -> %s %d\n",\r
-                        err == -1 ? "POLL" : "SOCKOPT",\r
-                        err == -1 ? strerror(errno) : strerror(err), \r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                               &cm_ptr->addr)->sin_addr), \r
-                        ntohs(((struct sockaddr_in *)\r
-                               &cm_ptr->addr)->sin_port));\r
-               goto bail;\r
-       }\r
-\r
-       cm_ptr->state = DCM_REP_PENDING;\r
-\r
-       /* send qp info and pdata to remote peer */\r
-       exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;\r
-       iov[0].iov_base = (void *)&cm_ptr->msg;\r
-       iov[0].iov_len = exp;\r
-       if (cm_ptr->msg.p_size) {\r
-               iov[1].iov_base = cm_ptr->msg.p_data;\r
-               iov[1].iov_len = ntohs(cm_ptr->msg.p_size);\r
-               len = writev(cm_ptr->socket, iov, 2);\r
-       } else {\r
-               len = writev(cm_ptr->socket, iov, 1);\r
-       }\r
-\r
-       if (len != (exp + ntohs(cm_ptr->msg.p_size))) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_PENDING len ERR %s, wcnt=%d(%d) -> %s\n",\r
-                        strerror(errno), len, \r
-                        exp + ntohs(cm_ptr->msg.p_size), \r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                  ep_ptr->param.\r
-                                  remote_ia_address_ptr)->sin_addr));\r
-               goto bail;\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " CONN_PENDING: sending SRC lid=0x%x,"\r
-                    " qpn=0x%x, psize=%d\n",\r
-                    ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                    ntohl(cm_ptr->msg.saddr.ib.qpn), \r
-                    ntohs(cm_ptr->msg.p_size));\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " CONN_PENDING: SRC GID subnet %016llx id %016llx\n",\r
-                    (unsigned long long)\r
-                    htonll(*(uint64_t*)&cm_ptr->msg.saddr.ib.gid[0]),\r
-                    (unsigned long long)\r
-                    htonll(*(uint64_t*)&cm_ptr->msg.saddr.ib.gid[8]));\r
-       return;\r
-\r
-bail:\r
-       /* close socket, free cm structure and post error event */\r
-       dapls_ib_cm_free(cm_ptr, cm_ptr->ep);\r
-       dapl_evd_connection_callback(NULL, IB_CME_LOCAL_FAILURE, NULL, 0, ep_ptr);\r
-}\r
-\r
-/*\r
- * ACTIVE: Create socket, connect, defer exchange QP information to CR thread\r
- * to avoid blocking. \r
- */\r
-DAT_RETURN\r
-dapli_socket_connect(DAPL_EP * ep_ptr,\r
-                    DAT_IA_ADDRESS_PTR r_addr,\r
-                    DAT_CONN_QUAL r_qual, DAT_COUNT p_size, DAT_PVOID p_data)\r
-{\r
-       dp_ib_cm_handle_t cm_ptr;\r
-       int ret;\r
-       socklen_t sl;\r
-       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;\r
-       DAT_RETURN dat_ret = DAT_INSUFFICIENT_RESOURCES;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect: r_qual %d p_size=%d\n",\r
-                    r_qual, p_size);\r
-\r
-       cm_ptr = dapls_ib_cm_create(ep_ptr);\r
-       if (cm_ptr == NULL)\r
-               return dat_ret;\r
-\r
-       /* create, connect, sockopt, and exchange QP information */\r
-       if ((cm_ptr->socket =\r
-            socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == DAPL_INVALID_SOCKET) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " connect: socket create ERR %s\n", strerror(errno));\r
-               goto bail;\r
-       }\r
-\r
-       ret = dapl_config_socket(cm_ptr->socket);\r
-       if (ret < 0) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " connect: config socket %d ERR %d %s\n",\r
-                        cm_ptr->socket, ret, strerror(dapl_socket_errno()));\r
-               dat_ret = DAT_INTERNAL_ERROR;\r
-               goto bail;\r
-       }\r
-\r
-       /* save remote address */\r
-       dapl_os_memcpy(&cm_ptr->addr, r_addr, sizeof(r_addr));\r
-\r
-#ifdef DAPL_DBG\r
-       /* DBG: Active PID [0], PASSIVE PID [2]*/\r
-       *(uint16_t*)&cm_ptr->msg.resv[0] = htons((uint16_t)dapl_os_getpid()); \r
-       *(uint16_t*)&cm_ptr->msg.resv[2] = ((struct sockaddr_in *)&cm_ptr->addr)->sin_port;\r
-#endif\r
-       ((struct sockaddr_in *)&cm_ptr->addr)->sin_port = htons(r_qual + 1000);\r
-       ret = dapl_connect_socket(cm_ptr->socket, (struct sockaddr *)&cm_ptr->addr,\r
-                                 sizeof(cm_ptr->addr));\r
-       if (ret && ret != EAGAIN) {\r
-               dat_ret = DAT_INVALID_ADDRESS;\r
-               goto bail;\r
-       }\r
-\r
-       /* REQ: QP info in msg.saddr, IA address in msg.daddr, and pdata */\r
-       cm_ptr->msg.op = ntohs(DCM_REQ);\r
-       cm_ptr->msg.saddr.ib.qpn = htonl(ep_ptr->qp_handle->qp_num);\r
-       cm_ptr->msg.saddr.ib.qp_type = ep_ptr->qp_handle->qp_type;\r
-       cm_ptr->msg.saddr.ib.lid = ia_ptr->hca_ptr->ib_trans.lid;\r
-       dapl_os_memcpy(&cm_ptr->msg.saddr.ib.gid[0], \r
-                      &ia_ptr->hca_ptr->ib_trans.gid, 16);\r
-       \r
-       /* save references */\r
-       cm_ptr->hca = ia_ptr->hca_ptr;\r
-       cm_ptr->ep = ep_ptr;\r
-       \r
-       /* get local address information from socket */\r
-       sl = sizeof(cm_ptr->msg.daddr.so);\r
-       if (getsockname(cm_ptr->socket, (struct sockaddr *)&cm_ptr->msg.daddr.so, &sl)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                       " connect getsockname ERROR: %s -> %s r_qual %d\n",\r
-                       strerror(errno), \r
-                       inet_ntoa(((struct sockaddr_in *)r_addr)->sin_addr),\r
-                       (unsigned int)r_qual);;\r
-       }\r
-\r
-       if (p_size) {\r
-               cm_ptr->msg.p_size = htons(p_size);\r
-               dapl_os_memcpy(cm_ptr->msg.p_data, p_data, p_size);\r
-       }\r
-\r
-       /* connected or pending, either way results via async event */\r
-       if (ret == 0)\r
-               dapli_socket_connected(cm_ptr, 0);\r
-       else\r
-               cm_ptr->state = DCM_CONN_PENDING;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect: p_data=%p %p\n",\r
-                    cm_ptr->msg.p_data, cm_ptr->msg.p_data);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " connect: %s r_qual %d pending, p_sz=%d, %d %d ...\n",\r
-                    inet_ntoa(((struct sockaddr_in *)&cm_ptr->addr)->sin_addr), \r
-                    (unsigned int)r_qual, ntohs(cm_ptr->msg.p_size),\r
-                    cm_ptr->msg.p_data[0], cm_ptr->msg.p_data[1]);\r
-\r
-       dapli_cm_queue(cm_ptr);\r
-       return DAT_SUCCESS;\r
-\r
-bail:\r
-       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                " connect ERROR: %s -> %s r_qual %d\n",\r
-                strerror(errno), \r
-                inet_ntoa(((struct sockaddr_in *)r_addr)->sin_addr),\r
-                (unsigned int)r_qual);\r
-\r
-       /* close socket, free cm structure */\r
-       dapls_ib_cm_free(cm_ptr, NULL);\r
-       return dat_ret;\r
-}\r
-\r
-/*\r
- * ACTIVE: exchange QP information, called from CR thread\r
- */\r
-static void dapli_socket_connect_rtu(dp_ib_cm_handle_t cm_ptr)\r
-{\r
-       DAPL_EP *ep_ptr = cm_ptr->ep;\r
-       int len, exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;\r
-       ib_cm_events_t event = IB_CME_LOCAL_FAILURE;\r
-       socklen_t sl;\r
-\r
-       /* read DST information into cm_ptr, overwrite SRC info */\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect_rtu: recv peer QP data\n");\r
-\r
-       len = recv(cm_ptr->socket, (char *)&cm_ptr->msg, exp, 0);\r
-       if (len != exp || ntohs(cm_ptr->msg.ver) != DCM_VER) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                        " CONN_RTU read: sk %d ERR %s, rcnt=%d, v=%d -> %s PORT L-%x R-%x PID L-%x R-%x\n",\r
-                        cm_ptr->socket, strerror(errno), len, ntohs(cm_ptr->msg.ver),\r
-                        inet_ntoa(((struct sockaddr_in *)&cm_ptr->addr)->sin_addr),\r
-                        ntohs(((struct sockaddr_in *)&cm_ptr->msg.daddr.so)->sin_port),\r
-                        ntohs(((struct sockaddr_in *)&cm_ptr->addr)->sin_port),\r
-                        ntohs(*(uint16_t*)&cm_ptr->msg.resv[0]),\r
-                        ntohs(*(uint16_t*)&cm_ptr->msg.resv[2]));\r
-\r
-               /* Retry; corner case where server tcp stack resets under load */\r
-               if (dapl_socket_errno() == ECONNRESET) {\r
-                       closesocket(cm_ptr->socket);\r
-                       cm_ptr->socket = DAPL_INVALID_SOCKET;\r
-                       dapli_socket_connect(cm_ptr->ep, (DAT_IA_ADDRESS_PTR)&cm_ptr->addr, \r
-                                            ntohs(((struct sockaddr_in *)&cm_ptr->addr)->sin_port) - 1000,\r
-                                            ntohs(cm_ptr->msg.p_size), &cm_ptr->msg.p_data);\r
-                       dapls_ib_cm_free(cm_ptr, NULL);\r
-                       return;\r
-               }\r
-               goto bail;\r
-       }\r
-\r
-       /* keep the QP, address info in network order */\r
-       \r
-       /* save remote address information, in msg.daddr */\r
-       dapl_os_memcpy(&ep_ptr->remote_ia_address,\r
-                      &cm_ptr->msg.daddr.so,\r
-                      sizeof(union dcm_addr));\r
-\r
-       /* save local address information from socket */\r
-       sl = sizeof(cm_ptr->addr);\r
-       getsockname(cm_ptr->socket,(struct sockaddr *)&cm_ptr->addr, &sl);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " CONN_RTU: DST %s %d lid=0x%x,"\r
-                    " qpn=0x%x, qp_type=%d, psize=%d\n",\r
-                    inet_ntoa(((struct sockaddr_in *)\r
-                               &cm_ptr->msg.daddr.so)->sin_addr),\r
-                    ntohs(((struct sockaddr_in *)\r
-                               &cm_ptr->msg.daddr.so)->sin_port),\r
-                    ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                    ntohl(cm_ptr->msg.saddr.ib.qpn), \r
-                    cm_ptr->msg.saddr.ib.qp_type, \r
-                    ntohs(cm_ptr->msg.p_size));\r
-\r
-       /* validate private data size before reading */\r
-       if (ntohs(cm_ptr->msg.p_size) > DCM_MAX_PDATA_SIZE) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_RTU read: psize (%d) wrong -> %s\n",\r
-                        ntohs(cm_ptr->msg.p_size), \r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                  ep_ptr->param.\r
-                                  remote_ia_address_ptr)->sin_addr));\r
-               goto bail;\r
-       }\r
-\r
-       /* read private data into cm_handle if any present */\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP," CONN_RTU: read private data\n");\r
-       exp = ntohs(cm_ptr->msg.p_size);\r
-       if (exp) {\r
-               len = recv(cm_ptr->socket, cm_ptr->msg.p_data, exp, 0);\r
-               if (len != exp) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                " CONN_RTU read pdata: ERR %s, rcnt=%d -> %s\n",\r
-                                strerror(errno), len,\r
-                                inet_ntoa(((struct sockaddr_in *)\r
-                                           ep_ptr->param.\r
-                                           remote_ia_address_ptr)->sin_addr));\r
-                       goto bail;\r
-               }\r
-       }\r
-\r
-       /* check for consumer or protocol stack reject */\r
-       if (ntohs(cm_ptr->msg.op) == DCM_REP)\r
-               event = IB_CME_CONNECTED;\r
-       else if (ntohs(cm_ptr->msg.op) == DCM_REJ_USER) \r
-               event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;\r
-       else  \r
-               event = IB_CME_DESTINATION_REJECT;\r
-       \r
-       if (event != IB_CME_CONNECTED) {\r
-               dapl_log(DAPL_DBG_TYPE_CM,\r
-                        " CONN_RTU: reject from %s %x\n",\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &cm_ptr->msg.daddr.so)->sin_addr),\r
-                        ntohs(((struct sockaddr_in *)\r
-                                &cm_ptr->msg.daddr.so)->sin_port));\r
-               goto bail;\r
-       }\r
-\r
-       /* modify QP to RTR and then to RTS with remote info */\r
-       dapl_os_lock(&ep_ptr->header.lock);\r
-       if (dapls_modify_qp_state(ep_ptr->qp_handle,\r
-                                 IBV_QPS_RTR, \r
-                                 cm_ptr->msg.saddr.ib.qpn,\r
-                                 cm_ptr->msg.saddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_RTU: QPS_RTR ERR %s (%d,%d,%x,%x,%x) -> %s %x\n",\r
-                        strerror(errno), ep_ptr->qp_handle->qp_type,\r
-                        ep_ptr->qp_state, ep_ptr->qp_handle->qp_num,\r
-                        ntohl(cm_ptr->msg.saddr.ib.qpn), \r
-                        ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &cm_ptr->msg.daddr.so)->sin_addr),\r
-                        ntohs(((struct sockaddr_in *)\r
-                                &cm_ptr->msg.daddr.so)->sin_port));\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               goto bail;\r
-       }\r
-       if (dapls_modify_qp_state(ep_ptr->qp_handle,\r
-                                 IBV_QPS_RTS, \r
-                                 cm_ptr->msg.saddr.ib.qpn,\r
-                                 cm_ptr->msg.saddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_RTU: QPS_RTS ERR %s (%d,%d,%x,%x,%x) -> %s %x\n",\r
-                        strerror(errno), ep_ptr->qp_handle->qp_type,\r
-                        ep_ptr->qp_state, ep_ptr->qp_handle->qp_num,\r
-                        ntohl(cm_ptr->msg.saddr.ib.qpn), \r
-                        ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &cm_ptr->msg.daddr.so)->sin_addr),\r
-                        ntohs(((struct sockaddr_in *)\r
-                                &cm_ptr->msg.daddr.so)->sin_port));\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               goto bail;\r
-       }\r
-       dapl_os_unlock(&ep_ptr->header.lock);\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect_rtu: send RTU\n");\r
-\r
-       /* complete handshake after final QP state change, Just ver+op */\r
-       cm_ptr->state = DCM_CONNECTED;\r
-       cm_ptr->msg.op = ntohs(DCM_RTU);\r
-       if (send(cm_ptr->socket, (char *)&cm_ptr->msg, 4, 0) == -1) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_RTU: write error = %s\n", strerror(errno));\r
-               goto bail;\r
-       }\r
-       /* post the event with private data */\r
-       event = IB_CME_CONNECTED;\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " ACTIVE: connected!\n");\r
-\r
-#ifdef DAT_EXTENSIONS\r
-ud_bail:\r
-       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) {\r
-               DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-               ib_pd_handle_t pd_handle = \r
-                       ((DAPL_PZ *)ep_ptr->param.pz_handle)->pd_handle;\r
-\r
-               if (event == IB_CME_CONNECTED) {\r
-                       cm_ptr->ah = dapls_create_ah(cm_ptr->hca, pd_handle,\r
-                                                    ep_ptr->qp_handle,\r
-                                                    cm_ptr->msg.saddr.ib.lid, \r
-                                                    NULL);\r
-                       if (cm_ptr->ah) {\r
-                               /* post UD extended EVENT */\r
-                               xevent.status = 0;\r
-                               xevent.type = DAT_IB_UD_REMOTE_AH;\r
-                               xevent.remote_ah.ah = cm_ptr->ah;\r
-                               xevent.remote_ah.qpn = ntohl(cm_ptr->msg.saddr.ib.qpn);\r
-                               dapl_os_memcpy(&xevent.remote_ah.ia_addr,\r
-                                               &ep_ptr->remote_ia_address,\r
-                                               sizeof(union dcm_addr));\r
-                               event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;\r
-\r
-                               dapl_log(DAPL_DBG_TYPE_CM, \r
-                                       " CONN_RTU: UD AH %p for lid 0x%x"\r
-                                       " qpn 0x%x\n", \r
-                                       cm_ptr->ah, \r
-                                       ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                                       ntohl(cm_ptr->msg.saddr.ib.qpn));\r
-       \r
-                       } else \r
-                               event = DAT_IB_UD_CONNECTION_ERROR_EVENT;\r
-                       \r
-               } else if (event == IB_CME_LOCAL_FAILURE) {\r
-                       event = DAT_IB_UD_CONNECTION_ERROR_EVENT;\r
-               } else  \r
-                       event = DAT_IB_UD_CONNECTION_REJECT_EVENT;\r
-               \r
-               dapls_evd_post_connection_event_ext(\r
-                               (DAPL_EVD *) ep_ptr->param.connect_evd_handle,\r
-                               event,\r
-                               (DAT_EP_HANDLE) ep_ptr,\r
-                               (DAT_COUNT) exp,\r
-                               (DAT_PVOID *) cm_ptr->msg.p_data,\r
-                               (DAT_PVOID *) &xevent);\r
-\r
-               /* done with socket, don't destroy cm_ptr, need pdata */\r
-               closesocket(cm_ptr->socket);\r
-               cm_ptr->socket = DAPL_INVALID_SOCKET;\r
-               cm_ptr->state = DCM_RELEASED;\r
-       } else\r
-#endif\r
-       {\r
-               ep_ptr->cm_handle = cm_ptr; /* only RC, multi CR's on UD */\r
-               dapl_evd_connection_callback(cm_ptr, event, cm_ptr->msg.p_data,\r
-                                            DCM_MAX_PDATA_SIZE, ep_ptr);\r
-       }\r
-       return;\r
-\r
-bail:\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) \r
-               goto ud_bail;\r
-#endif\r
-       /* close socket, and post error event */\r
-       dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0, 0, 0);\r
-       closesocket(cm_ptr->socket);\r
-       cm_ptr->socket = DAPL_INVALID_SOCKET;\r
-       dapl_evd_connection_callback(NULL, event, cm_ptr->msg.p_data,\r
-                                    DCM_MAX_PDATA_SIZE, ep_ptr);\r
-}\r
-\r
-/*\r
- * PASSIVE: Create socket, listen, accept, exchange QP information \r
- */\r
-DAT_RETURN\r
-dapli_socket_listen(DAPL_IA * ia_ptr, DAT_CONN_QUAL serviceID, DAPL_SP * sp_ptr)\r
-{\r
-       struct sockaddr_in addr;\r
-       ib_cm_srvc_handle_t cm_ptr = NULL;\r
-       DAT_RETURN dat_status = DAT_SUCCESS;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " listen(ia_ptr %p ServiceID %d sp_ptr %p)\n",\r
-                    ia_ptr, serviceID, sp_ptr);\r
-\r
-       cm_ptr = dapls_ib_cm_create(NULL);\r
-       if (cm_ptr == NULL)\r
-               return DAT_INSUFFICIENT_RESOURCES;\r
-\r
-       cm_ptr->sp = sp_ptr;\r
-       cm_ptr->hca = ia_ptr->hca_ptr;\r
-\r
-       /* bind, listen, set sockopt, accept, exchange data */\r
-       if ((cm_ptr->socket =\r
-            socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == DAPL_INVALID_SOCKET) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR, " ERR: listen socket create: %s\n",\r
-                        strerror(errno));\r
-               dat_status = DAT_INSUFFICIENT_RESOURCES;\r
-               goto bail;\r
-       }\r
-\r
-       addr.sin_port = htons(serviceID + 1000);\r
-       addr.sin_family = AF_INET;\r
-       addr.sin_addr = ((struct sockaddr_in *) &ia_ptr->hca_ptr->hca_address)->sin_addr;\r
-\r
-       if ((bind(cm_ptr->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0)\r
-           || (listen(cm_ptr->socket, 128) < 0)) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                            " listen: ERROR %s on conn_qual 0x%x\n",\r
-                            strerror(errno), serviceID + 1000);\r
-               if (dapl_socket_errno() == EADDRINUSE)\r
-                       dat_status = DAT_CONN_QUAL_IN_USE;\r
-               else\r
-                       dat_status = DAT_CONN_QUAL_UNAVAILABLE;\r
-               goto bail;\r
-       }\r
-\r
-       /* set cm_handle for this service point, save listen socket */\r
-       sp_ptr->cm_srvc_handle = cm_ptr;\r
-       dapl_os_memcpy(&cm_ptr->addr, &addr, sizeof(addr)); \r
-\r
-       /* queue up listen socket to process inbound CR's */\r
-       cm_ptr->state = DCM_LISTEN;\r
-       dapli_cm_queue(cm_ptr);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " listen: qual 0x%x cr %p s_fd %d\n",\r
-                    ntohs(serviceID + 1000), cm_ptr, cm_ptr->socket);\r
-\r
-       return dat_status;\r
-bail:\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " listen: ERROR on conn_qual 0x%x\n", serviceID + 1000);\r
-       dapls_ib_cm_free(cm_ptr, cm_ptr->ep);\r
-       return dat_status;\r
-}\r
-\r
-/*\r
- * PASSIVE: accept socket \r
- */\r
-static void dapli_socket_accept(ib_cm_srvc_handle_t cm_ptr)\r
-{\r
-       dp_ib_cm_handle_t acm_ptr;\r
-       int ret, len, opt = 1;\r
-       socklen_t sl;\r
-\r
-       /* \r
-        * Accept all CR's on this port to avoid half-connection (SYN_RCV)\r
-        * stalls with many to one connection storms\r
-        */\r
-       do {\r
-               /* Allocate accept CM and initialize */\r
-               if ((acm_ptr = dapls_ib_cm_create(NULL)) == NULL)\r
-                       return;\r
-\r
-               acm_ptr->sp = cm_ptr->sp;\r
-               acm_ptr->hca = cm_ptr->hca;\r
-\r
-               len = sizeof(union dcm_addr);\r
-               acm_ptr->socket = accept(cm_ptr->socket,\r
-                                       (struct sockaddr *)\r
-                                       &acm_ptr->msg.daddr.so,\r
-                                       (socklen_t *) &len);\r
-               if (acm_ptr->socket == DAPL_INVALID_SOCKET) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                               " ACCEPT: ERR %s on FD %d l_cr %p\n",\r
-                               strerror(errno), cm_ptr->socket, cm_ptr);\r
-                       dapls_ib_cm_free(acm_ptr, acm_ptr->ep);\r
-                       return;\r
-               }\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM, " accepting from %s %x\n",\r
-                            inet_ntoa(((struct sockaddr_in *)\r
-                                       &acm_ptr->msg.daddr.so)->sin_addr),\r
-                            ntohs(((struct sockaddr_in *)\r
-                                       &acm_ptr->msg.daddr.so)->sin_port));\r
-\r
-               /* no delay for small packets */\r
-               ret = setsockopt(acm_ptr->socket, IPPROTO_TCP, TCP_NODELAY,\r
-                          (char *)&opt, sizeof(opt));\r
-               if (ret)\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                " ACCEPT: NODELAY setsockopt: 0x%x 0x%x %s\n",\r
-                                ret, dapl_socket_errno(), strerror(dapl_socket_errno()));\r
-               \r
-               /* get local address information from socket */\r
-               sl = sizeof(acm_ptr->addr);\r
-               getsockname(acm_ptr->socket, (struct sockaddr *)&acm_ptr->addr, &sl);\r
-               acm_ptr->state = DCM_ACCEPTING;\r
-               dapli_cm_queue(acm_ptr);\r
-       \r
-       } while (dapl_poll(cm_ptr->socket, DAPL_FD_READ) == DAPL_FD_READ);\r
-}\r
-\r
-/*\r
- * PASSIVE: receive peer QP information, private data, post cr_event \r
- */\r
-static void dapli_socket_accept_data(ib_cm_srvc_handle_t acm_ptr)\r
-{\r
-       int len, exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;\r
-       void *p_data = NULL;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " socket accepted, read QP data\n");\r
-\r
-       /* read in DST QP info, IA address. check for private data */\r
-       len = recv(acm_ptr->socket, (char *)&acm_ptr->msg, exp, 0);\r
-       if (len != exp || ntohs(acm_ptr->msg.ver) != DCM_VER) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT read: ERR %s, rcnt=%d, ver=%d\n",\r
-                        strerror(errno), len, ntohs(acm_ptr->msg.ver));\r
-               goto bail;\r
-       }\r
-\r
-       /* keep the QP, address info in network order */\r
-\r
-       /* validate private data size before reading */\r
-       exp = ntohs(acm_ptr->msg.p_size);\r
-       if (exp > DCM_MAX_PDATA_SIZE) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                            " accept read: psize (%d) wrong\n",\r
-                            acm_ptr->msg.p_size);\r
-               goto bail;\r
-       }\r
-\r
-       /* read private data into cm_handle if any present */\r
-       if (exp) {\r
-               len = recv(acm_ptr->socket, acm_ptr->msg.p_data, exp, 0);\r
-               if (len != exp) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                " accept read pdata: ERR %s, rcnt=%d\n",\r
-                                strerror(errno), len);\r
-                       goto bail;\r
-               }\r
-               p_data = acm_ptr->msg.p_data;\r
-       }\r
-\r
-       acm_ptr->state = DCM_ACCEPTING_DATA;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " ACCEPT: DST %s %x lid=0x%x, qpn=0x%x, psz=%d\n",\r
-                    inet_ntoa(((struct sockaddr_in *)\r
-                               &acm_ptr->msg.daddr.so)->sin_addr), \r
-                    ntohs(((struct sockaddr_in *)\r
-                            &acm_ptr->msg.daddr.so)->sin_port),\r
-                    ntohs(acm_ptr->msg.saddr.ib.lid), \r
-                    ntohl(acm_ptr->msg.saddr.ib.qpn), exp);\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       if (acm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) {\r
-               DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-\r
-               /* post EVENT, modify_qp created ah */\r
-               xevent.status = 0;\r
-               xevent.type = DAT_IB_UD_CONNECT_REQUEST;\r
-\r
-               dapls_evd_post_cr_event_ext(acm_ptr->sp,\r
-                                           DAT_IB_UD_CONNECTION_REQUEST_EVENT,\r
-                                           acm_ptr,\r
-                                           (DAT_COUNT) exp,\r
-                                           (DAT_PVOID *) acm_ptr->msg.p_data,\r
-                                           (DAT_PVOID *) &xevent);\r
-       } else\r
-#endif\r
-               /* trigger CR event and return SUCCESS */\r
-               dapls_cr_callback(acm_ptr,\r
-                                 IB_CME_CONNECTION_REQUEST_PENDING,\r
-                                 p_data, exp, acm_ptr->sp);\r
-       return;\r
-bail:\r
-       /* close socket, free cm structure, active will see close as rej */\r
-       dapls_ib_cm_free(acm_ptr, acm_ptr->ep);\r
-       return;\r
-}\r
-\r
-/*\r
- * PASSIVE: consumer accept, send local QP information, private data, \r
- * queue on work thread to receive RTU information to avoid blocking\r
- * user thread. \r
- */\r
-static DAT_RETURN\r
-dapli_socket_accept_usr(DAPL_EP * ep_ptr,\r
-                       DAPL_CR * cr_ptr, DAT_COUNT p_size, DAT_PVOID p_data)\r
-{\r
-       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;\r
-       dp_ib_cm_handle_t cm_ptr = cr_ptr->ib_cm_handle;\r
-       ib_cm_msg_t local;\r
-       struct iovec iov[2];\r
-       int len, exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;\r
-       DAT_RETURN ret = DAT_INTERNAL_ERROR;\r
-       socklen_t sl;\r
-\r
-       if (p_size > DCM_MAX_PDATA_SIZE) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " accept_usr: psize(%d) too large\n", p_size);\r
-               return DAT_LENGTH_ERROR;\r
-       }\r
-\r
-       /* must have a accepted socket */\r
-       if (cm_ptr->socket == DAPL_INVALID_SOCKET) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " accept_usr: cm socket invalid\n");\r
-               goto bail;\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " ACCEPT_USR: remote lid=0x%x"\r
-                    " qpn=0x%x qp_type %d, psize=%d\n",\r
-                    ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                    ntohl(cm_ptr->msg.saddr.ib.qpn), \r
-                    cm_ptr->msg.saddr.ib.qp_type, \r
-                    ntohs(cm_ptr->msg.p_size));\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD &&\r
-           ep_ptr->qp_handle->qp_type != IBV_QPT_UD) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_USR: ERR remote QP is UD,"\r
-                        ", but local QP is not\n");\r
-               ret = (DAT_INVALID_HANDLE | DAT_INVALID_HANDLE_EP);\r
-               goto bail;\r
-       }\r
-#endif\r
-\r
-       /* modify QP to RTR and then to RTS with remote info already read */\r
-       dapl_os_lock(&ep_ptr->header.lock);\r
-       if (dapls_modify_qp_state(ep_ptr->qp_handle,\r
-                                 IBV_QPS_RTR, \r
-                                 cm_ptr->msg.saddr.ib.qpn,\r
-                                 cm_ptr->msg.saddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_USR: QPS_RTR ERR %s -> %s\n",\r
-                        strerror(errno), \r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                    &cm_ptr->msg.daddr.so)->sin_addr));\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               goto bail;\r
-       }\r
-       if (dapls_modify_qp_state(ep_ptr->qp_handle,\r
-                                 IBV_QPS_RTS, \r
-                                 cm_ptr->msg.saddr.ib.qpn,\r
-                                 cm_ptr->msg.saddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_USR: QPS_RTS ERR %s -> %s\n",\r
-                        strerror(errno), \r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                    &cm_ptr->msg.daddr.so)->sin_addr));\r
-               dapl_os_unlock(&ep_ptr->header.lock);\r
-               goto bail;\r
-       }\r
-       dapl_os_unlock(&ep_ptr->header.lock);\r
-\r
-       /* save remote address information */\r
-       dapl_os_memcpy(&ep_ptr->remote_ia_address,\r
-                      &cm_ptr->msg.daddr.so,\r
-                      sizeof(union dcm_addr));\r
-\r
-       /* send our QP info, IA address, pdata. Don't overwrite dst data */\r
-       local.ver = htons(DCM_VER);\r
-       local.op = htons(DCM_REP);\r
-       local.saddr.ib.qpn = htonl(ep_ptr->qp_handle->qp_num);\r
-       local.saddr.ib.qp_type = ep_ptr->qp_handle->qp_type;\r
-       local.saddr.ib.lid = ia_ptr->hca_ptr->ib_trans.lid;\r
-       dapl_os_memcpy(&local.saddr.ib.gid[0], \r
-                      &ia_ptr->hca_ptr->ib_trans.gid, 16);\r
-       \r
-       /* Get local address information from socket */\r
-       sl = sizeof(local.daddr.so);\r
-       getsockname(cm_ptr->socket, (struct sockaddr *)&local.daddr.so, &sl);\r
-\r
-#ifdef DAPL_DBG\r
-       /* DBG: Active PID [0], PASSIVE PID [2] */\r
-       *(uint16_t*)&cm_ptr->msg.resv[2] = htons((uint16_t)dapl_os_getpid()); \r
-       dapl_os_memcpy(local.resv, cm_ptr->msg.resv, 4); \r
-#endif\r
-\r
-       cm_ptr->ep = ep_ptr;\r
-       cm_ptr->hca = ia_ptr->hca_ptr;\r
-       cm_ptr->state = DCM_ACCEPTED;\r
-\r
-       local.p_size = htons(p_size);\r
-       iov[0].iov_base = (void *)&local;\r
-       iov[0].iov_len = exp;\r
-       \r
-       if (p_size) {\r
-               iov[1].iov_base = p_data;\r
-               iov[1].iov_len = p_size;\r
-               len = writev(cm_ptr->socket, iov, 2);\r
-       } else \r
-               len = writev(cm_ptr->socket, iov, 1);\r
-       \r
-       if (len != (p_size + exp)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_USR: ERR %s, wcnt=%d -> %s\n",\r
-                        strerror(errno), len, \r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                  &cm_ptr->msg.daddr.so)->sin_addr));\r
-               cm_ptr->ep = NULL;\r
-               goto bail;\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " ACCEPT_USR: local lid=0x%x qpn=0x%x psz=%d\n",\r
-                    ntohs(local.saddr.ib.lid),\r
-                    ntohl(local.saddr.ib.qpn), ntohs(local.p_size));\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " ACCEPT_USR: SRC GID subnet %016llx id %016llx\n",\r
-                    (unsigned long long)\r
-                    htonll(*(uint64_t*)&local.saddr.ib.gid[0]),\r
-                    (unsigned long long)\r
-                    htonll(*(uint64_t*)&local.saddr.ib.gid[8]));\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " PASSIVE: accepted!\n");\r
-       return DAT_SUCCESS;\r
-bail:\r
-       dapls_ib_cm_free(cm_ptr, NULL);\r
-       return ret;\r
-}\r
-\r
-/*\r
- * PASSIVE: read RTU from active peer, post CONN event\r
- */\r
-static void dapli_socket_accept_rtu(dp_ib_cm_handle_t cm_ptr)\r
-{\r
-       int len;\r
-       ib_cm_events_t event = IB_CME_CONNECTED;\r
-\r
-       /* complete handshake after final QP state change, VER and OP */\r
-       len = recv(cm_ptr->socket, (char *)&cm_ptr->msg, 4, 0);\r
-       if (len != 4 || ntohs(cm_ptr->msg.op) != DCM_RTU) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_RTU: rcv ERR, rcnt=%d op=%x\n",\r
-                        len, ntohs(cm_ptr->msg.op),\r
-                        inet_ntoa(((struct sockaddr_in *)\r
-                                   &cm_ptr->msg.daddr.so)->sin_addr));\r
-               event = IB_CME_DESTINATION_REJECT;\r
-               goto bail;\r
-       }\r
-\r
-       /* save state and reference to EP, queue for disc event */\r
-       cm_ptr->state = DCM_CONNECTED;\r
-\r
-       /* final data exchange if remote QP state is good to go */\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " PASSIVE: connected!\n");\r
-\r
-#ifdef DAT_EXTENSIONS\r
-ud_bail:\r
-       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) {\r
-               DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-\r
-               ib_pd_handle_t pd_handle = \r
-                       ((DAPL_PZ *)cm_ptr->ep->param.pz_handle)->pd_handle;\r
-               \r
-               if (event == IB_CME_CONNECTED) {\r
-                       cm_ptr->ah = dapls_create_ah(cm_ptr->hca, pd_handle,\r
-                                               cm_ptr->ep->qp_handle,\r
-                                               cm_ptr->msg.saddr.ib.lid, \r
-                                               NULL);\r
-                       if (cm_ptr->ah) { \r
-                               /* post EVENT, modify_qp created ah */\r
-                               xevent.status = 0;\r
-                               xevent.type = DAT_IB_UD_PASSIVE_REMOTE_AH;\r
-                               xevent.remote_ah.ah = cm_ptr->ah;\r
-                               xevent.remote_ah.qpn = ntohl(cm_ptr->msg.saddr.ib.qpn);\r
-                               dapl_os_memcpy(&xevent.remote_ah.ia_addr,\r
-                                       &cm_ptr->msg.daddr.so,\r
-                                       sizeof(union dcm_addr));\r
-                               event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;\r
-                       } else \r
-                               event = DAT_IB_UD_CONNECTION_ERROR_EVENT;\r
-               } else \r
-                       event = DAT_IB_UD_CONNECTION_ERROR_EVENT;\r
-\r
-               dapl_log(DAPL_DBG_TYPE_CM, \r
-                       " CONN_RTU: UD AH %p for lid 0x%x qpn 0x%x\n", \r
-                       cm_ptr->ah, ntohs(cm_ptr->msg.saddr.ib.lid),\r
-                       ntohl(cm_ptr->msg.saddr.ib.qpn));\r
-\r
-               dapls_evd_post_connection_event_ext(\r
-                               (DAPL_EVD *) \r
-                               cm_ptr->ep->param.connect_evd_handle,\r
-                               event,\r
-                               (DAT_EP_HANDLE) cm_ptr->ep,\r
-                               (DAT_COUNT) ntohs(cm_ptr->msg.p_size),\r
-                               (DAT_PVOID *) cm_ptr->msg.p_data,\r
-                               (DAT_PVOID *) &xevent);\r
-\r
-                /* done with socket, don't destroy cm_ptr, need pdata */\r
-                closesocket(cm_ptr->socket);\r
-                cm_ptr->socket = DAPL_INVALID_SOCKET;\r
-               cm_ptr->state = DCM_RELEASED;\r
-       } else \r
-#endif\r
-       {\r
-               cm_ptr->ep->cm_handle = cm_ptr; /* only RC, multi CR's on UD */\r
-               dapls_cr_callback(cm_ptr, event, NULL, 0, cm_ptr->sp);\r
-       }\r
-       return;\r
-      \r
-bail:\r
-#ifdef DAT_EXTENSIONS\r
-       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) \r
-               goto ud_bail;\r
-#endif\r
-       dapls_modify_qp_state(cm_ptr->ep->qp_handle, IBV_QPS_ERR, 0, 0, 0);\r
-       dapls_ib_cm_free(cm_ptr, cm_ptr->ep);\r
-       dapls_cr_callback(cm_ptr, event, NULL, 0, cm_ptr->sp);\r
-}\r
-\r
-/*\r
- * dapls_ib_connect\r
- *\r
- * Initiate a connection with the passive listener on another node\r
- *\r
- * Input:\r
- *     ep_handle,\r
- *     remote_ia_address,\r
- *     remote_conn_qual,\r
- *     prd_size                size of private data and structure\r
- *     prd_prt                 pointer to private data structure\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,\r
-                IN DAT_IA_ADDRESS_PTR remote_ia_address,\r
-                IN DAT_CONN_QUAL remote_conn_qual,\r
-                IN DAT_COUNT private_data_size, IN void *private_data)\r
-{\r
-       DAPL_EP *ep_ptr;\r
-       ib_qp_handle_t qp_ptr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " connect(ep_handle %p ....)\n", ep_handle);\r
-\r
-       ep_ptr = (DAPL_EP *) ep_handle;\r
-       qp_ptr = ep_ptr->qp_handle;\r
-\r
-       return (dapli_socket_connect(ep_ptr, remote_ia_address,\r
-                                    remote_conn_qual,\r
-                                    private_data_size, private_data));\r
-}\r
-\r
-/*\r
- * dapls_ib_disconnect\r
- *\r
- * Disconnect an EP\r
- *\r
- * Input:\r
- *     ep_handle,\r
- *     disconnect_flags\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- */\r
-DAT_RETURN\r
-dapls_ib_disconnect(IN DAPL_EP * ep_ptr, IN DAT_CLOSE_FLAGS close_flags)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "dapls_ib_disconnect(ep_handle %p ....)\n", ep_ptr);\r
-\r
-       /* Transition to error state to flush queue */\r
-        dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0, 0, 0);\r
-       \r
-       if (ep_ptr->cm_handle == NULL ||\r
-           ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED)\r
-               return DAT_SUCCESS;\r
-       else\r
-               return (dapli_socket_disconnect(ep_ptr->cm_handle));\r
-}\r
-\r
-/*\r
- * dapls_ib_disconnect_clean\r
- *\r
- * Clean up outstanding connection data. This routine is invoked\r
- * after the final disconnect callback has occurred. Only on the\r
- * ACTIVE side of a connection. It is also called if dat_ep_connect\r
- * times out using the consumer supplied timeout value.\r
- *\r
- * Input:\r
- *     ep_ptr          DAPL_EP\r
- *     active          Indicates active side of connection\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     void\r
- *\r
- */\r
-void\r
-dapls_ib_disconnect_clean(IN DAPL_EP * ep_ptr,\r
-                         IN DAT_BOOLEAN active,\r
-                         IN const ib_cm_events_t ib_cm_event)\r
-{\r
-       /* NOTE: SCM will only initialize cm_handle with RC type\r
-        * \r
-        * For UD there can many in-flight CR's so you \r
-        * cannot cleanup timed out CR's with EP reference \r
-        * alone since they share the same EP. The common\r
-        * code that handles connection timeout logic needs \r
-        * updated for UD support.\r
-        */\r
-       if (ep_ptr->cm_handle)\r
-               dapls_ib_cm_free(ep_ptr->cm_handle, ep_ptr);\r
-\r
-       return;\r
-}\r
-\r
-/*\r
- * dapl_ib_setup_conn_listener\r
- *\r
- * Have the CM set up a connection listener.\r
- *\r
- * Input:\r
- *     ibm_hca_handle          HCA handle\r
- *     qp_handle                       QP handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *     DAT_CONN_QUAL_UNAVAILBLE\r
- *     DAT_CONN_QUAL_IN_USE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_setup_conn_listener(IN DAPL_IA * ia_ptr,\r
-                            IN DAT_UINT64 ServiceID, IN DAPL_SP * sp_ptr)\r
-{\r
-       return (dapli_socket_listen(ia_ptr, ServiceID, sp_ptr));\r
-}\r
-\r
-/*\r
- * dapl_ib_remove_conn_listener\r
- *\r
- * Have the CM remove a connection listener.\r
- *\r
- * Input:\r
- *     ia_handle               IA handle\r
- *     ServiceID               IB Channel Service ID\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_STATE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_remove_conn_listener(IN DAPL_IA * ia_ptr, IN DAPL_SP * sp_ptr)\r
-{\r
-       ib_cm_srvc_handle_t cm_ptr = sp_ptr->cm_srvc_handle;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "dapls_ib_remove_conn_listener(ia_ptr %p sp_ptr %p cm_ptr %p)\n",\r
-                    ia_ptr, sp_ptr, cm_ptr);\r
-\r
-       /* close accepted socket, free cm_srvc_handle and return */\r
-       if (cm_ptr != NULL) {\r
-               /* cr_thread will free */\r
-               dapl_os_lock(&cm_ptr->lock);\r
-               cm_ptr->state = DCM_DESTROY;\r
-               sp_ptr->cm_srvc_handle = NULL;\r
-               send(cm_ptr->hca->ib_trans.scm[1], "w", sizeof "w", 0);\r
-               dapl_os_unlock(&cm_ptr->lock);\r
-       }\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_accept_connection\r
- *\r
- * Perform necessary steps to accept a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *     ep_handle\r
- *     private_data_size\r
- *     private_data\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,\r
-                          IN DAT_EP_HANDLE ep_handle,\r
-                          IN DAT_COUNT p_size, IN const DAT_PVOID p_data)\r
-{\r
-       DAPL_CR *cr_ptr;\r
-       DAPL_EP *ep_ptr;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "dapls_ib_accept_connection(cr %p ep %p prd %p,%d)\n",\r
-                    cr_handle, ep_handle, p_data, p_size);\r
-\r
-       cr_ptr = (DAPL_CR *) cr_handle;\r
-       ep_ptr = (DAPL_EP *) ep_handle;\r
-\r
-       /* allocate and attach a QP if necessary */\r
-       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {\r
-               DAT_RETURN status;\r
-               status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,\r
-                                          ep_ptr, ep_ptr);\r
-               if (status != DAT_SUCCESS)\r
-                       return status;\r
-       }\r
-       return (dapli_socket_accept_usr(ep_ptr, cr_ptr, p_size, p_data));\r
-}\r
-\r
-/*\r
- * dapls_ib_reject_connection\r
- *\r
- * Reject a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_reject_connection(IN dp_ib_cm_handle_t cm_ptr,\r
-                          IN int reason,\r
-                          IN DAT_COUNT psize, IN const DAT_PVOID pdata)\r
-{\r
-       struct iovec iov[2];\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " reject(cm %p reason %x, pdata %p, psize %d)\n",\r
-                    cm_ptr, reason, pdata, psize);\r
-\r
-        if (psize > DCM_MAX_PDATA_SIZE)\r
-                return DAT_LENGTH_ERROR;\r
-\r
-       dapl_os_lock(&cm_ptr->lock);\r
-\r
-       /* write reject data to indicate reject */\r
-       cm_ptr->msg.op = htons(DCM_REJ_USER);\r
-       cm_ptr->msg.p_size = htons(psize);\r
-       \r
-       iov[0].iov_base = (void *)&cm_ptr->msg;\r
-       iov[0].iov_len = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;\r
-       if (psize) {\r
-               iov[1].iov_base = pdata;\r
-               iov[1].iov_len = psize;\r
-               writev(cm_ptr->socket, iov, 2);\r
-       } else {\r
-               writev(cm_ptr->socket, iov, 1);\r
-       }\r
-\r
-       /* cr_thread will destroy CR */\r
-       cm_ptr->state = DCM_DESTROY;\r
-       send(cm_ptr->hca->ib_trans.scm[1], "w", sizeof "w", 0);\r
        dapl_os_unlock(&cm_ptr->lock);\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_cm_remote_addr\r
- *\r
- * Obtain the remote IP address given a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *\r
- * Output:\r
- *     remote_ia_address: where to place the remote address\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_HANDLE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle,\r
-                       OUT DAT_SOCK_ADDR6 * remote_ia_address)\r
-{\r
-       DAPL_HEADER *header;\r
-       dp_ib_cm_handle_t ib_cm_handle;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "dapls_ib_cm_remote_addr(dat_handle %p, ....)\n",\r
-                    dat_handle);\r
-\r
-       header = (DAPL_HEADER *) dat_handle;\r
-\r
-       if (header->magic == DAPL_MAGIC_EP)\r
-               ib_cm_handle = ((DAPL_EP *) dat_handle)->cm_handle;\r
-       else if (header->magic == DAPL_MAGIC_CR)\r
-               ib_cm_handle = ((DAPL_CR *) dat_handle)->ib_cm_handle;\r
-       else\r
-               return DAT_INVALID_HANDLE;\r
-\r
-       dapl_os_memcpy(remote_ia_address,\r
-                      &ib_cm_handle->msg.daddr.so, sizeof(DAT_SOCK_ADDR6));\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-int dapls_ib_private_data_size(\r
-       IN DAPL_HCA *hca_ptr)\r
-{\r
-       return DCM_MAX_PDATA_SIZE;\r
-}\r
-\r
-/*\r
- * Map all socket CM event codes to the DAT equivelent.\r
- */\r
-#define DAPL_IB_EVENT_CNT      10\r
-\r
-static struct ib_cm_event_map {\r
-       const ib_cm_events_t ib_cm_event;\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-} ib_cm_event_map[DAPL_IB_EVENT_CNT] = {\r
-/* 00 */ {IB_CME_CONNECTED, \r
-         DAT_CONNECTION_EVENT_ESTABLISHED},\r
-/* 01 */ {IB_CME_DISCONNECTED, \r
-         DAT_CONNECTION_EVENT_DISCONNECTED},\r
-/* 02 */ {IB_CME_DISCONNECTED_ON_LINK_DOWN,\r
-         DAT_CONNECTION_EVENT_DISCONNECTED},\r
-/* 03 */ {IB_CME_CONNECTION_REQUEST_PENDING, \r
-         DAT_CONNECTION_REQUEST_EVENT},\r
-/* 04 */ {IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,\r
-         DAT_CONNECTION_REQUEST_EVENT},\r
-/* 05 */ {IB_CME_DESTINATION_REJECT,\r
-         DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
-/* 06 */ {IB_CME_DESTINATION_REJECT_PRIVATE_DATA,\r
-         DAT_CONNECTION_EVENT_PEER_REJECTED},\r
-/* 07 */ {IB_CME_DESTINATION_UNREACHABLE, \r
-         DAT_CONNECTION_EVENT_UNREACHABLE},\r
-/* 08 */ {IB_CME_TOO_MANY_CONNECTION_REQUESTS,\r
-         DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
-/* 09 */ {IB_CME_LOCAL_FAILURE, \r
-         DAT_CONNECTION_EVENT_BROKEN}\r
-};\r
-\r
-/*\r
- * dapls_ib_get_cm_event\r
- *\r
- * Return a DAT connection event given a provider CM event.\r
- *\r
- * Input:\r
- *     dat_event_num   DAT event we need an equivelent CM event for\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     ib_cm_event of translated DAPL value\r
- */\r
-DAT_EVENT_NUMBER\r
-dapls_ib_get_dat_event(IN const ib_cm_events_t ib_cm_event,\r
-                      IN DAT_BOOLEAN active)\r
-{\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-       int i;\r
-\r
-       active = active;\r
-\r
-       if (ib_cm_event > IB_CME_LOCAL_FAILURE)\r
-               return (DAT_EVENT_NUMBER) 0;\r
-\r
-       dat_event_num = 0;\r
-       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {\r
-               if (ib_cm_event == ib_cm_event_map[i].ib_cm_event) {\r
-                       dat_event_num = ib_cm_event_map[i].dat_event_num;\r
-                       break;\r
-               }\r
-       }\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
-                    "dapls_ib_get_dat_event: event translate(%s) ib=0x%x dat=0x%x\n",\r
-                    active ? "active" : "passive", ib_cm_event, dat_event_num);\r
-\r
-       return dat_event_num;\r
-}\r
-\r
-/*\r
- * dapls_ib_get_dat_event\r
- *\r
- * Return a DAT connection event given a provider CM event.\r
- * \r
- * Input:\r
- *     ib_cm_event     event provided to the dapl callback routine\r
- *     active          switch indicating active or passive connection\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_EVENT_NUMBER of translated provider value\r
- */\r
-ib_cm_events_t dapls_ib_get_cm_event(IN DAT_EVENT_NUMBER dat_event_num)\r
-{\r
-       ib_cm_events_t ib_cm_event;\r
-       int i;\r
-\r
-       ib_cm_event = 0;\r
-       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {\r
-               if (dat_event_num == ib_cm_event_map[i].dat_event_num) {\r
-                       ib_cm_event = ib_cm_event_map[i].ib_cm_event;\r
-                       break;\r
-               }\r
-       }\r
-       return ib_cm_event;\r
-}\r
-\r
-/* outbound/inbound CR processing thread to avoid blocking applications */\r
-void cr_thread(void *arg)\r
-{\r
-       struct dapl_hca *hca_ptr = arg;\r
-       dp_ib_cm_handle_t cr, next_cr;\r
-       int opt, ret;\r
-       socklen_t opt_len;\r
-       char rbuf[2];\r
-       struct dapl_fd_set *set;\r
-       enum DAPL_FD_EVENTS event;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cr_thread: ENTER hca %p\n", hca_ptr);\r
-       set = dapl_alloc_fd_set();\r
-       if (!set)\r
-               goto out;\r
-\r
-       dapl_os_lock(&hca_ptr->ib_trans.lock);\r
-       hca_ptr->ib_trans.cr_state = IB_THREAD_RUN;\r
-\r
-       while (1) {\r
-               dapl_fd_zero(set);\r
-               dapl_fd_set(hca_ptr->ib_trans.scm[0], set, DAPL_FD_READ);\r
-\r
-               if (!dapl_llist_is_empty(&hca_ptr->ib_trans.list))\r
-                       next_cr = dapl_llist_peek_head(&hca_ptr->ib_trans.list);\r
-               else\r
-                       next_cr = NULL;\r
-\r
-               while (next_cr) {\r
-                       cr = next_cr;\r
-                       next_cr = dapl_llist_next_entry(&hca_ptr->ib_trans.list,\r
-                                                       (DAPL_LLIST_ENTRY *) &\r
-                                                       cr->entry);\r
-                       dapl_os_lock(&cr->lock);\r
-                       if (cr->state == DCM_DESTROY\r
-                           || hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) {\r
-                               dapl_os_unlock(&cr->lock);\r
-                               dapl_llist_remove_entry(&hca_ptr->ib_trans.list,\r
-                                                       (DAPL_LLIST_ENTRY *) &\r
-                                                       cr->entry);\r
-                               dapl_dbg_log(DAPL_DBG_TYPE_CM, \r
-                                            " CR FREE: %p ep=%p st=%d sock=%d\n", \r
-                                            cr, cr->ep, cr->state, cr->socket);\r
-\r
-                               if (cr->socket != DAPL_INVALID_SOCKET) {\r
-                                       shutdown(cr->socket, SHUT_RDWR);\r
-                                       closesocket(cr->socket);\r
-                               }\r
-                               dapl_os_free(cr, sizeof(*cr));\r
-                               continue;\r
-                       }\r
-                       if (cr->socket == DAPL_INVALID_SOCKET) {\r
-                               dapl_os_unlock(&cr->lock);\r
-                               continue;\r
-                       }\r
-\r
-                       event = (cr->state == DCM_CONN_PENDING) ?\r
-                                               DAPL_FD_WRITE : DAPL_FD_READ;\r
-\r
-                       if (dapl_fd_set(cr->socket, set, event)) {\r
-                               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                        " cr_thread: DESTROY CR st=%d fd %d"\r
-                                        " -> %s\n", cr->state, cr->socket,\r
-                                        inet_ntoa(((struct sockaddr_in *)\r
-                                               &cr->msg.daddr.so)->sin_addr));\r
-                               dapl_os_unlock(&cr->lock);\r
-                               dapl_os_lock_destroy(&cr->lock);\r
-                               dapls_ib_cm_free(cr, cr->ep);\r
-                               continue;\r
-                       }\r
-                       dapl_os_unlock(&cr->lock);\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                                    " poll cr=%p, sck=%d\n", cr, cr->socket);\r
-                       dapl_os_unlock(&hca_ptr->ib_trans.lock);\r
-\r
-                       ret = dapl_poll(cr->socket, event);\r
-\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                                    " poll ret=0x%x cr->state=%d sck=%d\n",\r
-                                    ret, cr->state, cr->socket);\r
-\r
-                       /* data on listen, qp exchange, and on disc req */\r
-                       if ((ret == DAPL_FD_READ) || \r
-                           (cr->state != DCM_CONN_PENDING &&\r
-                            ret == DAPL_FD_ERROR)) {\r
-                               if (cr->socket != DAPL_INVALID_SOCKET) {\r
-                                       switch (cr->state) {\r
-                                       case DCM_LISTEN:\r
-                                               dapli_socket_accept(cr);\r
-                                               break;\r
-                                       case DCM_ACCEPTING:\r
-                                               dapli_socket_accept_data(cr);\r
-                                               break;\r
-                                       case DCM_ACCEPTED:\r
-                                               dapli_socket_accept_rtu(cr);\r
-                                               break;\r
-                                       case DCM_REP_PENDING:\r
-                                               dapli_socket_connect_rtu(cr);\r
-                                               break;\r
-                                       case DCM_CONNECTED:\r
-                                               dapli_socket_disconnect(cr);\r
-                                               break;\r
-                                       default:\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       /* ASYNC connections, writable, readable, error; check status */\r
-                       } else if (ret == DAPL_FD_WRITE ||\r
-                                  (cr->state == DCM_CONN_PENDING && \r
-                                   ret == DAPL_FD_ERROR)) {\r
-\r
-                               if (ret == DAPL_FD_ERROR)\r
-                                       dapl_log(DAPL_DBG_TYPE_ERR, " CONN_PENDING - FD_ERROR\n");\r
-                               \r
-                               opt = 0;\r
-                               opt_len = sizeof(opt);\r
-                               ret = getsockopt(cr->socket, SOL_SOCKET,\r
-                                                SO_ERROR, (char *)&opt,\r
-                                                &opt_len);\r
-                               if (!ret && !opt)\r
-                                       dapli_socket_connected(cr, opt);\r
-                               else\r
-                                       dapli_socket_connected(cr, opt ? opt : dapl_socket_errno());\r
-                       } \r
-                       dapl_os_lock(&hca_ptr->ib_trans.lock);\r
-               }\r
-\r
-               /* set to exit and all resources destroyed */\r
-               if ((hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) &&\r
-                   (dapl_llist_is_empty(&hca_ptr->ib_trans.list)))\r
-                       break;\r
-\r
-               dapl_os_unlock(&hca_ptr->ib_trans.lock);\r
-               dapl_select(set);\r
-\r
-               /* if pipe used to wakeup, consume */\r
-               while (dapl_poll(hca_ptr->ib_trans.scm[0], \r
-                                DAPL_FD_READ) == DAPL_FD_READ) {\r
-                       if (recv(hca_ptr->ib_trans.scm[0], rbuf, 2, 0) == -1)\r
-                               dapl_log(DAPL_DBG_TYPE_CM,\r
-                                        " cr_thread: read pipe error = %s\n",\r
-                                        strerror(errno));\r
-               }\r
-               dapl_os_lock(&hca_ptr->ib_trans.lock);\r
-               \r
-               /* set to exit and all resources destroyed */\r
-               if ((hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) &&\r
-                   (dapl_llist_is_empty(&hca_ptr->ib_trans.list)))\r
-                       break;\r
-       }\r
-\r
-       dapl_os_unlock(&hca_ptr->ib_trans.lock);\r
-       dapl_os_free(set, sizeof(struct dapl_fd_set));\r
-out:\r
-       hca_ptr->ib_trans.cr_state = IB_THREAD_EXIT;\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cr_thread(hca %p) exit\n", hca_ptr);\r
-}\r
-\r
-\r
-#ifdef DAPL_COUNTERS\r
-/* Debug aid: List all Connections in process and state */\r
-void dapls_print_cm_list(IN DAPL_IA *ia_ptr)\r
-{\r
-       /* Print in process CR's for this IA, if debug type set */\r
-       int i = 0;\r
-       dp_ib_cm_handle_t cr, next_cr;\r
-\r
-       dapl_os_lock(&ia_ptr->hca_ptr->ib_trans.lock);\r
-       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)\r
-                                &ia_ptr->hca_ptr->ib_trans.list))\r
-                                next_cr = dapl_llist_peek_head((DAPL_LLIST_HEAD*)\r
-                                &ia_ptr->hca_ptr->ib_trans.list);\r
-       else\r
-               next_cr = NULL;\r
-\r
-        printf("\n DAPL IA CONNECTIONS IN PROCESS:\n");\r
-       while (next_cr) {\r
-               cr = next_cr;\r
-               next_cr = dapl_llist_next_entry((DAPL_LLIST_HEAD*)\r
-                                &ia_ptr->hca_ptr->ib_trans.list,\r
-                               (DAPL_LLIST_ENTRY*)&cr->entry);\r
-\r
-               printf( "  CONN[%d]: sp %p ep %p sock %d %s %s %s %s %s %s PORT L-%x R-%x PID L-%x R-%x\n",\r
-                       i, cr->sp, cr->ep, cr->socket,\r
-                       cr->msg.saddr.ib.qp_type == IBV_QPT_RC ? "RC" : "UD",\r
-                       dapl_cm_state_str(cr->state), dapl_cm_op_str(ntohs(cr->msg.op)),\r
-                       ntohs(cr->msg.op) == DCM_REQ ? /* local address */\r
-                               inet_ntoa(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_addr) :\r
-                               inet_ntoa(((struct sockaddr_in *)&cr->addr)->sin_addr),\r
-                       cr->sp ? "<-" : "->",\r
-                               ntohs(cr->msg.op) == DCM_REQ ? /* remote address */\r
-                               inet_ntoa(((struct sockaddr_in *)&cr->addr)->sin_addr) :\r
-                               inet_ntoa(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_addr),\r
-\r
-                       ntohs(cr->msg.op) == DCM_REQ ? /* local port */\r
-                               ntohs(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_port) :\r
-                               ntohs(((struct sockaddr_in *)&cr->addr)->sin_port),\r
-\r
-                       ntohs(cr->msg.op) == DCM_REQ ? /* remote port */\r
-                               ntohs(((struct sockaddr_in *)&cr->addr)->sin_port) :\r
-                               ntohs(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_port),\r
-\r
-                       cr->sp ? ntohs(*(uint16_t*)&cr->msg.resv[2]) : ntohs(*(uint16_t*)&cr->msg.resv[0]),\r
-                       cr->sp ? ntohs(*(uint16_t*)&cr->msg.resv[0]) : ntohs(*(uint16_t*)&cr->msg.resv[2]));\r
-\r
-               i++;\r
-       }\r
-       printf("\n");\r
-       dapl_os_unlock(&ia_ptr->hca_ptr->ib_trans.lock);\r
-}\r
-#endif\r
+       dapli_cm_dealloc(cm_ptr);\r
+}
+
+static dp_ib_cm_handle_t dapli_cm_alloc(DAPL_EP *ep_ptr)
+{
+       dp_ib_cm_handle_t cm_ptr;
+
+       /* Allocate CM, init lock, and initialize */
+       if ((cm_ptr = dapl_os_alloc(sizeof(*cm_ptr))) == NULL)
+               return NULL;
+
+       (void)dapl_os_memzero(cm_ptr, sizeof(*cm_ptr));
+       if (dapl_os_lock_init(&cm_ptr->lock))
+               goto bail;
+
+       if (dapl_os_wait_object_init(&cm_ptr->event)) {
+               dapl_os_lock_destroy(&cm_ptr->lock);
+               goto bail;
+       }
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm_ptr->list_entry);
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm_ptr->local_entry);
+
+       cm_ptr->msg.ver = htons(DCM_VER);
+       cm_ptr->socket = DAPL_INVALID_SOCKET;
+       dapls_cm_acquire(cm_ptr);
+               
+       /* Link EP and CM */
+       if (ep_ptr != NULL) {
+               dapl_ep_link_cm(ep_ptr, cm_ptr); /* ref++ */
+               cm_ptr->ep = ep_ptr;
+               cm_ptr->hca = ((DAPL_IA *)ep_ptr->param.ia_handle)->hca_ptr;
+       }
+       return cm_ptr;
+bail:
+       dapl_os_free(cm_ptr, sizeof(*cm_ptr));
+       return NULL;
+}
+
+/* queue socket for processing CM work */
+static void dapli_cm_queue(dp_ib_cm_handle_t cm_ptr)
+{
+       /* add to work queue for cr thread processing */
+       dapl_os_lock(&cm_ptr->hca->ib_trans.lock);
+       dapls_cm_acquire(cm_ptr);
+       dapl_llist_add_tail(&cm_ptr->hca->ib_trans.list,
+                           (DAPL_LLIST_ENTRY *)&cm_ptr->local_entry, cm_ptr);
+       dapl_os_unlock(&cm_ptr->hca->ib_trans.lock);
+       dapli_cm_thread_signal(cm_ptr);
+}
+
+/* called with local LIST lock */
+static void dapli_cm_dequeue(dp_ib_cm_handle_t cm_ptr)
+{
+       /* Remove from work queue, cr thread processing */
+       dapl_llist_remove_entry(&cm_ptr->hca->ib_trans.list,
+                               (DAPL_LLIST_ENTRY *)&cm_ptr->local_entry);
+       dapls_cm_release(cm_ptr);
+}
+
+/* BLOCKING: called from dapl_ep_free, EP link will be last ref */
+void dapls_cm_free(dp_ib_cm_handle_t cm_ptr)
+{
+       dapl_log(DAPL_DBG_TYPE_CM,
+                " cm_free: cm %p %s ep %p refs=%d\n", 
+                cm_ptr, dapl_cm_state_str(cm_ptr->state),
+                cm_ptr->ep, cm_ptr->ref_count);
+       
+       /* free from internal workq, wait until EP is last ref */
+       dapl_os_lock(&cm_ptr->lock);
+       cm_ptr->state = DCM_FREE;
+       while (cm_ptr->ref_count != 1) {
+               dapl_os_unlock(&cm_ptr->lock);
+               dapl_os_sleep_usec(10000);
+               dapl_os_lock(&cm_ptr->lock);
+       }
+       dapl_os_unlock(&cm_ptr->lock);
+
+       /* unlink, dequeue from EP. Final ref so release will destroy */
+       dapl_ep_unlink_cm(cm_ptr->ep, cm_ptr);
+}
+
+/*
+ * ACTIVE/PASSIVE: called from CR thread or consumer via ep_disconnect
+ *                 or from ep_free. 
+ */
+DAT_RETURN dapli_socket_disconnect(dp_ib_cm_handle_t cm_ptr)
+{
+       DAT_UINT32 disc_data = htonl(0xdead);
+
+       dapl_os_lock(&cm_ptr->lock);
+       if (cm_ptr->state != DCM_CONNECTED || 
+           cm_ptr->state == DCM_DISCONNECTED) {
+               dapl_os_unlock(&cm_ptr->lock);
+               return DAT_SUCCESS;
+       }
+       cm_ptr->state = DCM_DISCONNECTED;
+       dapl_os_unlock(&cm_ptr->lock);
+       
+       /* send disc date, close socket, schedule destroy */
+       dapls_modify_qp_state(cm_ptr->ep->qp_handle, IBV_QPS_ERR, 0,0,0);
+       send(cm_ptr->socket, (char *)&disc_data, sizeof(disc_data), 0);
+
+       /* disconnect events for RC's only */
+       if (cm_ptr->ep->param.ep_attr.service_type == DAT_SERVICE_TYPE_RC) {
+               if (cm_ptr->ep->cr_ptr) {
+                       dapls_cr_callback(cm_ptr,
+                                         IB_CME_DISCONNECTED,
+                                         NULL, 0, cm_ptr->sp);
+               } else {
+                       dapl_evd_connection_callback(cm_ptr,
+                                                    IB_CME_DISCONNECTED,
+                                                    NULL, 0, cm_ptr->ep);
+               }
+       }
+       
+       /* release from workq */
+       dapli_cm_free(cm_ptr);
+
+       /* scheduled destroy via disconnect clean in callback */
+       return DAT_SUCCESS;
+}
+
+/*
+ * ACTIVE: socket connected, send QP information to peer 
+ */
+static void dapli_socket_connected(dp_ib_cm_handle_t cm_ptr, int err)
+{
+       int len, exp;
+       struct iovec iov[2];
+       struct dapl_ep *ep_ptr = cm_ptr->ep;
+
+       if (err) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_PENDING: %s ERR %s -> %s %d\n",
+                        err == -1 ? "POLL" : "SOCKOPT",
+                        err == -1 ? strerror(errno) : strerror(err), 
+                        inet_ntoa(((struct sockaddr_in *)
+                               &cm_ptr->addr)->sin_addr), 
+                        ntohs(((struct sockaddr_in *)
+                               &cm_ptr->addr)->sin_port));
+               goto bail;
+       }
+
+       cm_ptr->state = DCM_REP_PENDING;
+
+       /* send qp info and pdata to remote peer */
+       exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;
+       iov[0].iov_base = (void *)&cm_ptr->msg;
+       iov[0].iov_len = exp;
+       if (cm_ptr->msg.p_size) {
+               iov[1].iov_base = cm_ptr->msg.p_data;
+               iov[1].iov_len = ntohs(cm_ptr->msg.p_size);
+               len = writev(cm_ptr->socket, iov, 2);
+       } else {
+               len = writev(cm_ptr->socket, iov, 1);
+       }
+
+       if (len != (exp + ntohs(cm_ptr->msg.p_size))) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_PENDING len ERR %s, wcnt=%d(%d) -> %s\n",
+                        strerror(errno), len, 
+                        exp + ntohs(cm_ptr->msg.p_size), 
+                        inet_ntoa(((struct sockaddr_in *)
+                                  ep_ptr->param.
+                                  remote_ia_address_ptr)->sin_addr));
+               goto bail;
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " CONN_PENDING: sending SRC lid=0x%x,"
+                    " qpn=0x%x, psize=%d\n",
+                    ntohs(cm_ptr->msg.saddr.ib.lid),
+                    ntohl(cm_ptr->msg.saddr.ib.qpn), 
+                    ntohs(cm_ptr->msg.p_size));
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " CONN_PENDING: SRC GID subnet %016llx id %016llx\n",
+                    (unsigned long long)
+                    htonll(*(uint64_t*)&cm_ptr->msg.saddr.ib.gid[0]),
+                    (unsigned long long)
+                    htonll(*(uint64_t*)&cm_ptr->msg.saddr.ib.gid[8]));
+       return;
+
+bail:
+       /* mark CM object for cleanup */
+       dapli_cm_free(cm_ptr);
+       dapl_evd_connection_callback(NULL, IB_CME_LOCAL_FAILURE, NULL, 0, ep_ptr);
+}
+
+/*
+ * ACTIVE: Create socket, connect, defer exchange QP information to CR thread
+ * to avoid blocking. 
+ */
+static DAT_RETURN
+dapli_socket_connect(DAPL_EP * ep_ptr,
+                    DAT_IA_ADDRESS_PTR r_addr,
+                    DAT_CONN_QUAL r_qual, DAT_COUNT p_size, DAT_PVOID p_data)
+{
+       dp_ib_cm_handle_t cm_ptr;
+       int ret;
+       socklen_t sl;
+       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;
+       DAT_RETURN dat_ret = DAT_INSUFFICIENT_RESOURCES;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect: r_qual %d p_size=%d\n",
+                    r_qual, p_size);
+
+       cm_ptr = dapli_cm_alloc(ep_ptr);
+       if (cm_ptr == NULL)
+               return dat_ret;
+
+       /* create, connect, sockopt, and exchange QP information */
+       if ((cm_ptr->socket =
+            socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == DAPL_INVALID_SOCKET) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " connect: socket create ERR %s\n", strerror(errno));
+               goto bail;
+       }
+
+       ret = dapl_config_socket(cm_ptr->socket);
+       if (ret < 0) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " connect: config socket %d ERR %d %s\n",
+                        cm_ptr->socket, ret, strerror(dapl_socket_errno()));
+               dat_ret = DAT_INTERNAL_ERROR;
+               goto bail;
+       }
+
+       /* save remote address */
+       dapl_os_memcpy(&cm_ptr->addr, r_addr, sizeof(*r_addr));
+
+#ifdef DAPL_DBG
+       /* DBG: Active PID [0], PASSIVE PID [2]*/
+       *(uint16_t*)&cm_ptr->msg.resv[0] = htons((uint16_t)dapl_os_getpid()); 
+       *(uint16_t*)&cm_ptr->msg.resv[2] = ((struct sockaddr_in *)&cm_ptr->addr)->sin_port;
+#endif
+       ((struct sockaddr_in *)&cm_ptr->addr)->sin_port = htons(r_qual + 1000);
+       ret = dapl_connect_socket(cm_ptr->socket, (struct sockaddr *)&cm_ptr->addr,
+                                 sizeof(cm_ptr->addr));
+       if (ret && ret != EAGAIN) {
+               dat_ret = DAT_INVALID_ADDRESS;
+               goto bail;
+       }
+
+       /* REQ: QP info in msg.saddr, IA address in msg.daddr, and pdata */
+       cm_ptr->hca = ia_ptr->hca_ptr;
+       cm_ptr->msg.op = ntohs(DCM_REQ);
+       cm_ptr->msg.saddr.ib.qpn = htonl(ep_ptr->qp_handle->qp_num);
+       cm_ptr->msg.saddr.ib.qp_type = ep_ptr->qp_handle->qp_type;
+       cm_ptr->msg.saddr.ib.lid = ia_ptr->hca_ptr->ib_trans.lid;
+       dapl_os_memcpy(&cm_ptr->msg.saddr.ib.gid[0], 
+                      &ia_ptr->hca_ptr->ib_trans.gid, 16);
+       
+       /* get local address information from socket */
+       sl = sizeof(cm_ptr->msg.daddr.so);
+       if (getsockname(cm_ptr->socket, (struct sockaddr *)&cm_ptr->msg.daddr.so, &sl)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                       " connect getsockname ERROR: %s -> %s r_qual %d\n",
+                       strerror(errno), 
+                       inet_ntoa(((struct sockaddr_in *)r_addr)->sin_addr),
+                       (unsigned int)r_qual);;
+       }
+
+       if (p_size) {
+               cm_ptr->msg.p_size = htons(p_size);
+               dapl_os_memcpy(cm_ptr->msg.p_data, p_data, p_size);
+       }
+
+       /* connected or pending, either way results via async event */
+       if (ret == 0)
+               dapli_socket_connected(cm_ptr, 0);
+       else
+               cm_ptr->state = DCM_CONN_PENDING;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect: p_data=%p %p\n",
+                    cm_ptr->msg.p_data, cm_ptr->msg.p_data);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " connect: %s r_qual %d pending, p_sz=%d, %d %d ...\n",
+                    inet_ntoa(((struct sockaddr_in *)&cm_ptr->addr)->sin_addr), 
+                    (unsigned int)r_qual, ntohs(cm_ptr->msg.p_size),
+                    cm_ptr->msg.p_data[0], cm_ptr->msg.p_data[1]);
+
+       /* queue up on work thread */
+       dapli_cm_queue(cm_ptr);
+       return DAT_SUCCESS;
+bail:
+       dapl_log(DAPL_DBG_TYPE_ERR,
+                " connect ERROR: %s -> %s r_qual %d\n",
+                strerror(errno), 
+                inet_ntoa(((struct sockaddr_in *)r_addr)->sin_addr),
+                (unsigned int)r_qual);
+
+       /* Never queued, destroy */
+       dapls_cm_release(cm_ptr);
+       return dat_ret;
+}
+
+/*
+ * ACTIVE: exchange QP information, called from CR thread
+ */
+static void dapli_socket_connect_rtu(dp_ib_cm_handle_t cm_ptr)
+{
+       DAPL_EP *ep_ptr = cm_ptr->ep;
+       int len, exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;
+       ib_cm_events_t event = IB_CME_LOCAL_FAILURE;
+       socklen_t sl;
+
+       /* read DST information into cm_ptr, overwrite SRC info */
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect_rtu: recv peer QP data\n");
+
+       len = recv(cm_ptr->socket, (char *)&cm_ptr->msg, exp, 0);
+       if (len != exp || ntohs(cm_ptr->msg.ver) != DCM_VER) {
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                        " CONN_RTU read: sk %d ERR %s, rcnt=%d, v=%d -> %s PORT L-%x R-%x PID L-%x R-%x\n",
+                        cm_ptr->socket, strerror(errno), len, ntohs(cm_ptr->msg.ver),
+                        inet_ntoa(((struct sockaddr_in *)&cm_ptr->addr)->sin_addr),
+                        ntohs(((struct sockaddr_in *)&cm_ptr->msg.daddr.so)->sin_port),
+                        ntohs(((struct sockaddr_in *)&cm_ptr->addr)->sin_port),
+                        ntohs(*(uint16_t*)&cm_ptr->msg.resv[0]),
+                        ntohs(*(uint16_t*)&cm_ptr->msg.resv[2]));
+
+               /* Retry; corner case where server tcp stack resets under load */
+               if (dapl_socket_errno() == ECONNRESET) {
+                       closesocket(cm_ptr->socket);
+                       cm_ptr->socket = DAPL_INVALID_SOCKET;
+                       dapli_socket_connect(cm_ptr->ep, (DAT_IA_ADDRESS_PTR)&cm_ptr->addr, 
+                                            ntohs(((struct sockaddr_in *)&cm_ptr->addr)->sin_port) - 1000,
+                                            ntohs(cm_ptr->msg.p_size), &cm_ptr->msg.p_data);
+                       dapl_ep_unlink_cm(cm_ptr->ep, cm_ptr);
+                       dapli_cm_free(cm_ptr);
+                       return;
+               }
+               goto bail;
+       }
+
+       /* keep the QP, address info in network order */
+       
+       /* save remote address information, in msg.daddr */
+       dapl_os_memcpy(&ep_ptr->remote_ia_address,
+                      &cm_ptr->msg.daddr.so,
+                      sizeof(union dcm_addr));
+
+       /* save local address information from socket */
+       sl = sizeof(cm_ptr->addr);
+       getsockname(cm_ptr->socket,(struct sockaddr *)&cm_ptr->addr, &sl);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " CONN_RTU: DST %s %d lid=0x%x,"
+                    " qpn=0x%x, qp_type=%d, psize=%d\n",
+                    inet_ntoa(((struct sockaddr_in *)
+                               &cm_ptr->msg.daddr.so)->sin_addr),
+                    ntohs(((struct sockaddr_in *)
+                               &cm_ptr->msg.daddr.so)->sin_port),
+                    ntohs(cm_ptr->msg.saddr.ib.lid),
+                    ntohl(cm_ptr->msg.saddr.ib.qpn), 
+                    cm_ptr->msg.saddr.ib.qp_type, 
+                    ntohs(cm_ptr->msg.p_size));
+
+       /* validate private data size before reading */
+       if (ntohs(cm_ptr->msg.p_size) > DCM_MAX_PDATA_SIZE) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_RTU read: psize (%d) wrong -> %s\n",
+                        ntohs(cm_ptr->msg.p_size), 
+                        inet_ntoa(((struct sockaddr_in *)
+                                  ep_ptr->param.
+                                  remote_ia_address_ptr)->sin_addr));
+               goto bail;
+       }
+
+       /* read private data into cm_handle if any present */
+       dapl_dbg_log(DAPL_DBG_TYPE_EP," CONN_RTU: read private data\n");
+       exp = ntohs(cm_ptr->msg.p_size);
+       if (exp) {
+               len = recv(cm_ptr->socket, cm_ptr->msg.p_data, exp, 0);
+               if (len != exp) {
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                " CONN_RTU read pdata: ERR %s, rcnt=%d -> %s\n",
+                                strerror(errno), len,
+                                inet_ntoa(((struct sockaddr_in *)
+                                           ep_ptr->param.
+                                           remote_ia_address_ptr)->sin_addr));
+                       goto bail;
+               }
+       }
+
+       /* check for consumer or protocol stack reject */
+       if (ntohs(cm_ptr->msg.op) == DCM_REP)
+               event = IB_CME_CONNECTED;
+       else if (ntohs(cm_ptr->msg.op) == DCM_REJ_USER) 
+               event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;
+       else  
+               event = IB_CME_DESTINATION_REJECT;
+       
+       if (event != IB_CME_CONNECTED) {
+               dapl_log(DAPL_DBG_TYPE_CM,
+                        " CONN_RTU: reject from %s %x\n",
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &cm_ptr->msg.daddr.so)->sin_addr),
+                        ntohs(((struct sockaddr_in *)
+                                &cm_ptr->msg.daddr.so)->sin_port));
+               goto bail;
+       }
+
+       /* modify QP to RTR and then to RTS with remote info */
+       if (dapls_modify_qp_state(ep_ptr->qp_handle,
+                                 IBV_QPS_RTR, 
+                                 cm_ptr->msg.saddr.ib.qpn,
+                                 cm_ptr->msg.saddr.ib.lid,
+                                 (ib_gid_handle_t)cm_ptr->msg.saddr.ib.gid) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_RTU: QPS_RTR ERR %s (%d,%d,%x,%x,%x) -> %s %x\n",
+                        strerror(errno), ep_ptr->qp_handle->qp_type,
+                        ep_ptr->qp_state, ep_ptr->qp_handle->qp_num,
+                        ntohl(cm_ptr->msg.saddr.ib.qpn), 
+                        ntohs(cm_ptr->msg.saddr.ib.lid),
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &cm_ptr->msg.daddr.so)->sin_addr),
+                        ntohs(((struct sockaddr_in *)
+                                &cm_ptr->msg.daddr.so)->sin_port));
+               goto bail;
+       }
+       if (dapls_modify_qp_state(ep_ptr->qp_handle,
+                                 IBV_QPS_RTS, 
+                                 cm_ptr->msg.saddr.ib.qpn,
+                                 cm_ptr->msg.saddr.ib.lid,
+                                 NULL) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_RTU: QPS_RTS ERR %s (%d,%d,%x,%x,%x) -> %s %x\n",
+                        strerror(errno), ep_ptr->qp_handle->qp_type,
+                        ep_ptr->qp_state, ep_ptr->qp_handle->qp_num,
+                        ntohl(cm_ptr->msg.saddr.ib.qpn), 
+                        ntohs(cm_ptr->msg.saddr.ib.lid),
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &cm_ptr->msg.daddr.so)->sin_addr),
+                        ntohs(((struct sockaddr_in *)
+                                &cm_ptr->msg.daddr.so)->sin_port));
+               goto bail;
+       }
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect_rtu: send RTU\n");
+
+       /* complete handshake after final QP state change, Just ver+op */
+       cm_ptr->state = DCM_CONNECTED;
+       cm_ptr->msg.op = ntohs(DCM_RTU);
+       if (send(cm_ptr->socket, (char *)&cm_ptr->msg, 4, 0) == -1) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_RTU: write error = %s\n", strerror(errno));
+               goto bail;
+       }
+       /* post the event with private data */
+       event = IB_CME_CONNECTED;
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " ACTIVE: connected!\n");
+
+#ifdef DAT_EXTENSIONS
+ud_bail:
+       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) {
+               DAT_IB_EXTENSION_EVENT_DATA xevent;
+               ib_pd_handle_t pd_handle = 
+                       ((DAPL_PZ *)ep_ptr->param.pz_handle)->pd_handle;
+
+               if (event == IB_CME_CONNECTED) {
+                       cm_ptr->ah = dapls_create_ah(cm_ptr->hca, pd_handle,
+                                                    ep_ptr->qp_handle,
+                                                    cm_ptr->msg.saddr.ib.lid, 
+                                                    NULL);
+                       if (cm_ptr->ah) {
+                               /* post UD extended EVENT */
+                               xevent.status = 0;
+                               xevent.type = DAT_IB_UD_REMOTE_AH;
+                               xevent.remote_ah.ah = cm_ptr->ah;
+                               xevent.remote_ah.qpn = ntohl(cm_ptr->msg.saddr.ib.qpn);
+                               dapl_os_memcpy(&xevent.remote_ah.ia_addr,
+                                               &ep_ptr->remote_ia_address,
+                                               sizeof(union dcm_addr));
+                               event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;
+
+                               dapl_log(DAPL_DBG_TYPE_CM, 
+                                       " CONN_RTU: UD AH %p for lid 0x%x"
+                                       " qpn 0x%x\n", 
+                                       cm_ptr->ah, 
+                                       ntohs(cm_ptr->msg.saddr.ib.lid),
+                                       ntohl(cm_ptr->msg.saddr.ib.qpn));
+       
+                       } else 
+                               event = DAT_IB_UD_CONNECTION_ERROR_EVENT;
+                       
+               } else if (event == IB_CME_LOCAL_FAILURE) {
+                       event = DAT_IB_UD_CONNECTION_ERROR_EVENT;
+               } else  
+                       event = DAT_IB_UD_CONNECTION_REJECT_EVENT;
+
+               dapls_evd_post_connection_event_ext(
+                               (DAPL_EVD *) ep_ptr->param.connect_evd_handle,
+                               event,
+                               (DAT_EP_HANDLE) ep_ptr,
+                               (DAT_COUNT) exp,
+                               (DAT_PVOID *) cm_ptr->msg.p_data,
+                               (DAT_PVOID *) &xevent);
+
+               /* cleanup and release from local list */
+               dapli_cm_free(cm_ptr);
+       
+       } else
+#endif
+       {
+               dapl_evd_connection_callback(cm_ptr, event, cm_ptr->msg.p_data,
+                                            DCM_MAX_PDATA_SIZE, ep_ptr);
+       }
+       return;
+
+bail:
+
+#ifdef DAT_EXTENSIONS
+       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) 
+               goto ud_bail;
+#endif
+       /* close socket, and post error event */
+       cm_ptr->state = DCM_REJECTED;
+       dapl_evd_connection_callback(NULL, event, cm_ptr->msg.p_data,
+                                    DCM_MAX_PDATA_SIZE, ep_ptr);
+       dapli_cm_free(cm_ptr);
+}
+
+/*
+ * PASSIVE: Create socket, listen, accept, exchange QP information 
+ */
+DAT_RETURN
+dapli_socket_listen(DAPL_IA * ia_ptr, DAT_CONN_QUAL serviceID, DAPL_SP * sp_ptr)
+{
+       struct sockaddr_in addr;
+       ib_cm_srvc_handle_t cm_ptr = NULL;
+       DAT_RETURN dat_status = DAT_SUCCESS;
+       int opt = 1;\r
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " setup listen(ia_ptr %p ServiceID %d sp_ptr %p)\n",
+                    ia_ptr, serviceID, sp_ptr);
+
+       cm_ptr = dapli_cm_alloc(NULL);
+       if (cm_ptr == NULL)
+               return DAT_INSUFFICIENT_RESOURCES;
+
+       cm_ptr->sp = sp_ptr;
+       cm_ptr->hca = ia_ptr->hca_ptr;
+
+       /* bind, listen, set sockopt, accept, exchange data */
+       if ((cm_ptr->socket =
+            socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == DAPL_INVALID_SOCKET) {
+               dapl_log(DAPL_DBG_TYPE_ERR, " ERR: listen socket create: %s\n",
+                        strerror(errno));
+               dat_status = DAT_INSUFFICIENT_RESOURCES;
+               goto bail;
+       }
+
+       setsockopt(cm_ptr->socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));\r
+       addr.sin_port = htons(serviceID + 1000);
+       addr.sin_family = AF_INET;
+       addr.sin_addr = ((struct sockaddr_in *) &ia_ptr->hca_ptr->hca_address)->sin_addr;
+
+       if ((bind(cm_ptr->socket, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+           || (listen(cm_ptr->socket, 128) < 0)) {
+               dapl_log(DAPL_DBG_TYPE_CM,
+                        " listen: ERROR %s on port %d\n",
+                        strerror(errno), serviceID + 1000);
+               if (dapl_socket_errno() == EADDRINUSE)
+                       dat_status = DAT_CONN_QUAL_IN_USE;
+               else
+                       dat_status = DAT_CONN_QUAL_UNAVAILABLE;
+               goto bail;
+       }
+
+       /* set cm_handle for this service point, save listen socket */
+       sp_ptr->cm_srvc_handle = cm_ptr;
+       dapl_os_memcpy(&cm_ptr->addr, &addr, sizeof(addr)); 
+
+       /* queue up listen socket to process inbound CR's */
+       cm_ptr->state = DCM_LISTEN;
+       dapli_cm_queue(cm_ptr);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " setup listen: port %d cr %p s_fd %d\n",
+                    serviceID + 1000, cm_ptr, cm_ptr->socket);
+
+       return dat_status;
+bail:
+       /* Never queued, destroy here */
+       dapls_cm_release(cm_ptr);
+       return dat_status;
+}
+
+/*
+ * PASSIVE: accept socket 
+ */
+static void dapli_socket_accept(ib_cm_srvc_handle_t cm_ptr)
+{
+       dp_ib_cm_handle_t acm_ptr;
+       int ret, len, opt = 1;
+       socklen_t sl;
+
+       /* 
+        * Accept all CR's on this port to avoid half-connection (SYN_RCV)
+        * stalls with many to one connection storms
+        */
+       do {
+               /* Allocate accept CM and initialize */
+               if ((acm_ptr = dapli_cm_alloc(NULL)) == NULL)
+                       return;
+
+               acm_ptr->sp = cm_ptr->sp;
+               acm_ptr->hca = cm_ptr->hca;
+
+               len = sizeof(union dcm_addr);
+               acm_ptr->socket = accept(cm_ptr->socket,
+                                       (struct sockaddr *)
+                                       &acm_ptr->msg.daddr.so,
+                                       (socklen_t *) &len);
+               if (acm_ptr->socket == DAPL_INVALID_SOCKET) {
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                               " ACCEPT: ERR %s on FD %d l_cr %p\n",
+                               strerror(errno), cm_ptr->socket, cm_ptr);
+                       dapls_cm_release(acm_ptr);
+                       return;
+               }
+               dapl_dbg_log(DAPL_DBG_TYPE_CM, " accepting from %s %x\n",
+                            inet_ntoa(((struct sockaddr_in *)
+                                       &acm_ptr->msg.daddr.so)->sin_addr),
+                            ntohs(((struct sockaddr_in *)
+                                       &acm_ptr->msg.daddr.so)->sin_port));
+
+               /* no delay for small packets */
+               ret = setsockopt(acm_ptr->socket, IPPROTO_TCP, TCP_NODELAY,
+                          (char *)&opt, sizeof(opt));
+               if (ret)
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                " ACCEPT: NODELAY setsockopt: 0x%x 0x%x %s\n",
+                                ret, dapl_socket_errno(), strerror(dapl_socket_errno()));
+               
+               /* get local address information from socket */
+               sl = sizeof(acm_ptr->addr);
+               getsockname(acm_ptr->socket, (struct sockaddr *)&acm_ptr->addr, &sl);
+               acm_ptr->state = DCM_ACCEPTING;
+               dapli_cm_queue(acm_ptr);
+       
+       } while (dapl_poll(cm_ptr->socket, DAPL_FD_READ) == DAPL_FD_READ);
+}
+
+/*
+ * PASSIVE: receive peer QP information, private data, post cr_event 
+ */
+static void dapli_socket_accept_data(ib_cm_srvc_handle_t acm_ptr)
+{
+       int len, exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;
+       void *p_data = NULL;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " socket accepted, read QP data\n");
+
+       /* read in DST QP info, IA address. check for private data */
+       len = recv(acm_ptr->socket, (char *)&acm_ptr->msg, exp, 0);
+       if (len != exp || ntohs(acm_ptr->msg.ver) != DCM_VER) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT read: ERR %s, rcnt=%d, ver=%d\n",
+                        strerror(errno), len, ntohs(acm_ptr->msg.ver));
+               goto bail;
+       }
+
+       /* keep the QP, address info in network order */
+
+       /* validate private data size before reading */
+       exp = ntohs(acm_ptr->msg.p_size);
+       if (exp > DCM_MAX_PDATA_SIZE) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                            " accept read: psize (%d) wrong\n",
+                            acm_ptr->msg.p_size);
+               goto bail;
+       }
+
+       /* read private data into cm_handle if any present */
+       if (exp) {
+               len = recv(acm_ptr->socket, acm_ptr->msg.p_data, exp, 0);
+               if (len != exp) {
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                " accept read pdata: ERR %s, rcnt=%d\n",
+                                strerror(errno), len);
+                       goto bail;
+               }
+               p_data = acm_ptr->msg.p_data;
+       }
+
+       acm_ptr->state = DCM_ACCEPTING_DATA;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " ACCEPT: DST %s %x lid=0x%x, qpn=0x%x, psz=%d\n",
+                    inet_ntoa(((struct sockaddr_in *)
+                               &acm_ptr->msg.daddr.so)->sin_addr), 
+                    ntohs(((struct sockaddr_in *)
+                            &acm_ptr->msg.daddr.so)->sin_port),
+                    ntohs(acm_ptr->msg.saddr.ib.lid), 
+                    ntohl(acm_ptr->msg.saddr.ib.qpn), exp);
+
+#ifdef DAT_EXTENSIONS
+       if (acm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) {
+               DAT_IB_EXTENSION_EVENT_DATA xevent;
+
+               /* post EVENT, modify_qp created ah */
+               xevent.status = 0;
+               xevent.type = DAT_IB_UD_CONNECT_REQUEST;
+
+               dapls_evd_post_cr_event_ext(acm_ptr->sp,
+                                           DAT_IB_UD_CONNECTION_REQUEST_EVENT,
+                                           acm_ptr,
+                                           (DAT_COUNT) exp,
+                                           (DAT_PVOID *) acm_ptr->msg.p_data,
+                                           (DAT_PVOID *) &xevent);
+       } else
+#endif
+               /* trigger CR event and return SUCCESS */
+               dapls_cr_callback(acm_ptr,
+                                 IB_CME_CONNECTION_REQUEST_PENDING,
+                                 p_data, exp, acm_ptr->sp);
+       return;
+bail:
+       /* mark for destroy, active will see socket close as rej */
+       dapli_cm_free(acm_ptr);
+       return;
+}
+
+/*
+ * PASSIVE: consumer accept, send local QP information, private data, 
+ * queue on work thread to receive RTU information to avoid blocking
+ * user thread. 
+ */
+static DAT_RETURN
+dapli_socket_accept_usr(DAPL_EP * ep_ptr,
+                       DAPL_CR * cr_ptr, DAT_COUNT p_size, DAT_PVOID p_data)
+{
+       DAPL_IA *ia_ptr = ep_ptr->header.owner_ia;
+       dp_ib_cm_handle_t cm_ptr = cr_ptr->ib_cm_handle;
+       ib_cm_msg_t local;
+       struct iovec iov[2];
+       int len, exp = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;
+       DAT_RETURN ret = DAT_INTERNAL_ERROR;
+       socklen_t sl;
+
+       if (p_size > DCM_MAX_PDATA_SIZE) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " accept_usr: psize(%d) too large\n", p_size);
+               return DAT_LENGTH_ERROR;
+       }
+
+       /* must have a accepted socket */
+       if (cm_ptr->socket == DAPL_INVALID_SOCKET) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " accept_usr: cm socket invalid\n");
+               goto bail;
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " ACCEPT_USR: remote lid=0x%x"
+                    " qpn=0x%x qp_type %d, psize=%d\n",
+                    ntohs(cm_ptr->msg.saddr.ib.lid),
+                    ntohl(cm_ptr->msg.saddr.ib.qpn), 
+                    cm_ptr->msg.saddr.ib.qp_type, 
+                    ntohs(cm_ptr->msg.p_size));
+
+#ifdef DAT_EXTENSIONS
+       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD &&
+           ep_ptr->qp_handle->qp_type != IBV_QPT_UD) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_USR: ERR remote QP is UD,"
+                        ", but local QP is not\n");
+               ret = (DAT_INVALID_HANDLE | DAT_INVALID_HANDLE_EP);
+               goto bail;
+       }
+#endif
+
+       /* modify QP to RTR and then to RTS with remote info already read */
+       if (dapls_modify_qp_state(ep_ptr->qp_handle,
+                                 IBV_QPS_RTR, 
+                                 cm_ptr->msg.saddr.ib.qpn,
+                                 cm_ptr->msg.saddr.ib.lid,
+                                 (ib_gid_handle_t)cm_ptr->msg.saddr.ib.gid) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_USR: QPS_RTR ERR %s -> %s\n",
+                        strerror(errno), 
+                        inet_ntoa(((struct sockaddr_in *)
+                                    &cm_ptr->msg.daddr.so)->sin_addr));
+               goto bail;
+       }
+       if (dapls_modify_qp_state(ep_ptr->qp_handle,
+                                 IBV_QPS_RTS, 
+                                 cm_ptr->msg.saddr.ib.qpn,
+                                 cm_ptr->msg.saddr.ib.lid,
+                                 NULL) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_USR: QPS_RTS ERR %s -> %s\n",
+                        strerror(errno), 
+                        inet_ntoa(((struct sockaddr_in *)
+                                    &cm_ptr->msg.daddr.so)->sin_addr));
+               goto bail;
+       }
+
+       /* save remote address information */
+       dapl_os_memcpy(&ep_ptr->remote_ia_address,
+                      &cm_ptr->msg.daddr.so,
+                      sizeof(union dcm_addr));
+
+       /* send our QP info, IA address, pdata. Don't overwrite dst data */
+       local.ver = htons(DCM_VER);
+       local.op = htons(DCM_REP);
+       local.saddr.ib.qpn = htonl(ep_ptr->qp_handle->qp_num);
+       local.saddr.ib.qp_type = ep_ptr->qp_handle->qp_type;
+       local.saddr.ib.lid = ia_ptr->hca_ptr->ib_trans.lid;
+       dapl_os_memcpy(&local.saddr.ib.gid[0], 
+                      &ia_ptr->hca_ptr->ib_trans.gid, 16);
+       
+       /* Get local address information from socket */
+       sl = sizeof(local.daddr.so);
+       getsockname(cm_ptr->socket, (struct sockaddr *)&local.daddr.so, &sl);
+
+#ifdef DAPL_DBG
+       /* DBG: Active PID [0], PASSIVE PID [2] */
+       *(uint16_t*)&cm_ptr->msg.resv[2] = htons((uint16_t)dapl_os_getpid()); 
+       dapl_os_memcpy(local.resv, cm_ptr->msg.resv, 4); 
+#endif
+       cm_ptr->hca = ia_ptr->hca_ptr;
+       cm_ptr->state = DCM_ACCEPTED;
+
+       local.p_size = htons(p_size);
+       iov[0].iov_base = (void *)&local;
+       iov[0].iov_len = exp;
+       
+       if (p_size) {
+               iov[1].iov_base = p_data;
+               iov[1].iov_len = p_size;
+               len = writev(cm_ptr->socket, iov, 2);
+       } else 
+               len = writev(cm_ptr->socket, iov, 1);
+       
+       if (len != (p_size + exp)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_USR: ERR %s, wcnt=%d -> %s\n",
+                        strerror(errno), len, 
+                        inet_ntoa(((struct sockaddr_in *)
+                                  &cm_ptr->msg.daddr.so)->sin_addr));
+               goto bail;
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " ACCEPT_USR: local lid=0x%x qpn=0x%x psz=%d\n",
+                    ntohs(local.saddr.ib.lid),
+                    ntohl(local.saddr.ib.qpn), ntohs(local.p_size));
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " ACCEPT_USR: SRC GID subnet %016llx id %016llx\n",
+                    (unsigned long long)
+                    htonll(*(uint64_t*)&local.saddr.ib.gid[0]),
+                    (unsigned long long)
+                    htonll(*(uint64_t*)&local.saddr.ib.gid[8]));
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " PASSIVE: accepted!\n");
+
+       /* Link CM to EP, already queued on work thread */
+       dapl_ep_link_cm(ep_ptr, cm_ptr);
+       cm_ptr->ep = ep_ptr;
+       return DAT_SUCCESS;
+bail:
+       /* schedule cleanup from workq */
+       dapli_cm_free(cm_ptr);
+       return ret;
+}
+
+/*
+ * PASSIVE: read RTU from active peer, post CONN event
+ */
+static void dapli_socket_accept_rtu(dp_ib_cm_handle_t cm_ptr)
+{
+       int len;
+       ib_cm_events_t event = IB_CME_CONNECTED;
+
+       /* complete handshake after final QP state change, VER and OP */
+       len = recv(cm_ptr->socket, (char *)&cm_ptr->msg, 4, 0);
+       if (len != 4 || ntohs(cm_ptr->msg.op) != DCM_RTU) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_RTU: rcv ERR, rcnt=%d op=%x\n",
+                        len, ntohs(cm_ptr->msg.op),
+                        inet_ntoa(((struct sockaddr_in *)
+                                   &cm_ptr->msg.daddr.so)->sin_addr));
+               event = IB_CME_DESTINATION_REJECT;
+               goto bail;
+       }
+
+       /* save state and reference to EP, queue for disc event */
+       cm_ptr->state = DCM_CONNECTED;
+
+       /* final data exchange if remote QP state is good to go */
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " PASSIVE: connected!\n");
+
+#ifdef DAT_EXTENSIONS
+ud_bail:
+       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) {
+               DAT_IB_EXTENSION_EVENT_DATA xevent;
+
+               ib_pd_handle_t pd_handle = 
+                       ((DAPL_PZ *)cm_ptr->ep->param.pz_handle)->pd_handle;
+               
+               if (event == IB_CME_CONNECTED) {
+                       cm_ptr->ah = dapls_create_ah(cm_ptr->hca, pd_handle,
+                                               cm_ptr->ep->qp_handle,
+                                               cm_ptr->msg.saddr.ib.lid, 
+                                               NULL);
+                       if (cm_ptr->ah) { 
+                               /* post EVENT, modify_qp created ah */
+                               xevent.status = 0;
+                               xevent.type = DAT_IB_UD_PASSIVE_REMOTE_AH;
+                               xevent.remote_ah.ah = cm_ptr->ah;
+                               xevent.remote_ah.qpn = ntohl(cm_ptr->msg.saddr.ib.qpn);
+                               dapl_os_memcpy(&xevent.remote_ah.ia_addr,
+                                       &cm_ptr->msg.daddr.so,
+                                       sizeof(union dcm_addr));
+                               event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;
+                       } else 
+                               event = DAT_IB_UD_CONNECTION_ERROR_EVENT;
+               } else 
+                       event = DAT_IB_UD_CONNECTION_ERROR_EVENT;
+
+               dapl_log(DAPL_DBG_TYPE_CM, 
+                       " CONN_RTU: UD AH %p for lid 0x%x qpn 0x%x\n", 
+                       cm_ptr->ah, ntohs(cm_ptr->msg.saddr.ib.lid),
+                       ntohl(cm_ptr->msg.saddr.ib.qpn));
+
+               dapls_evd_post_connection_event_ext(
+                               (DAPL_EVD *) 
+                               cm_ptr->ep->param.connect_evd_handle,
+                               event,
+                               (DAT_EP_HANDLE) cm_ptr->ep,
+                               (DAT_COUNT) ntohs(cm_ptr->msg.p_size),
+                               (DAT_PVOID *) cm_ptr->msg.p_data,
+                               (DAT_PVOID *) &xevent);
+
+                /* cleanup and release from local list, still on EP list */
+               dapli_cm_free(cm_ptr);
+                
+       } else 
+#endif
+       {
+               dapls_cr_callback(cm_ptr, event, NULL, 0, cm_ptr->sp);
+       }
+       return;
+      
+bail:
+#ifdef DAT_EXTENSIONS
+       if (cm_ptr->msg.saddr.ib.qp_type == IBV_QPT_UD) 
+               goto ud_bail;
+#endif
+       cm_ptr->state = DCM_REJECTED;
+       dapls_cr_callback(cm_ptr, event, NULL, 0, cm_ptr->sp);
+       dapli_cm_free(cm_ptr);
+}
+
+/*
+ * dapls_ib_connect
+ *
+ * Initiate a connection with the passive listener on another node
+ *
+ * Input:
+ *     ep_handle,
+ *     remote_ia_address,
+ *     remote_conn_qual,
+ *     prd_size                size of private data and structure
+ *     prd_prt                 pointer to private data structure
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,
+                IN DAT_IA_ADDRESS_PTR remote_ia_address,
+                IN DAT_CONN_QUAL remote_conn_qual,
+                IN DAT_COUNT private_data_size, IN void *private_data)
+{
+       DAPL_EP *ep_ptr = (DAPL_EP *) ep_handle;
+       
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " connect(ep_handle %p ....)\n", ep_handle);
+
+       return (dapli_socket_connect(ep_ptr, remote_ia_address,
+                                    remote_conn_qual,
+                                    private_data_size, private_data));
+}
+
+/*
+ * dapls_ib_disconnect
+ *
+ * Disconnect an EP
+ *
+ * Input:
+ *     ep_handle,
+ *     disconnect_flags
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ */
+DAT_RETURN
+dapls_ib_disconnect(IN DAPL_EP * ep_ptr, IN DAT_CLOSE_FLAGS close_flags)
+{
+       dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+
+       if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED ||
+               ep_ptr->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC) {
+               return DAT_SUCCESS;
+       } 
+       
+       /* RC. Transition to error state to flush queue */
+        dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0, 0, 0);
+
+       return (dapli_socket_disconnect(cm_ptr));
+}
+
+/*
+ * dapls_ib_disconnect_clean
+ *
+ * Clean up outstanding connection data. This routine is invoked
+ * after the final disconnect callback has occurred. Only on the
+ * ACTIVE side of a connection. It is also called if dat_ep_connect
+ * times out using the consumer supplied timeout value.
+ *
+ * Input:
+ *     ep_ptr          DAPL_EP
+ *     active          Indicates active side of connection
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     void
+ *
+ */
+void
+dapls_ib_disconnect_clean(IN DAPL_EP * ep_ptr,
+                         IN DAT_BOOLEAN active,
+                         IN const ib_cm_events_t ib_cm_event)
+{
+       if (ib_cm_event == IB_CME_TIMEOUT) {
+               dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                       "dapls_ib_disc_clean: CONN_TIMEOUT ep %p cm %p %s\n",
+                       ep_ptr, cm_ptr, dapl_cm_state_str(cm_ptr->state));
+               
+               /* schedule release of socket and local resources */
+               dapli_cm_free(cm_ptr);
+       }
+}
+
+/*
+ * dapl_ib_setup_conn_listener
+ *
+ * Have the CM set up a connection listener.
+ *
+ * Input:
+ *     ibm_hca_handle          HCA handle
+ *     qp_handle                       QP handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *     DAT_CONN_QUAL_UNAVAILBLE
+ *     DAT_CONN_QUAL_IN_USE
+ *
+ */
+DAT_RETURN
+dapls_ib_setup_conn_listener(IN DAPL_IA * ia_ptr,
+                            IN DAT_UINT64 ServiceID, IN DAPL_SP * sp_ptr)
+{
+       return (dapli_socket_listen(ia_ptr, ServiceID, sp_ptr));
+}
+
+/*
+ * dapl_ib_remove_conn_listener
+ *
+ * Have the CM remove a connection listener.
+ *
+ * Input:
+ *     ia_handle               IA handle
+ *     ServiceID               IB Channel Service ID
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_STATE
+ *
+ */
+DAT_RETURN
+dapls_ib_remove_conn_listener(IN DAPL_IA * ia_ptr, IN DAPL_SP * sp_ptr)
+{
+       ib_cm_srvc_handle_t cm_ptr = sp_ptr->cm_srvc_handle;
+
+       /* free cm_srvc_handle, release will cleanup */
+       if (cm_ptr != NULL) {
+               /* cr_thread will free */
+               sp_ptr->cm_srvc_handle = NULL;
+               dapli_cm_free(cm_ptr);
+       }
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_accept_connection
+ *
+ * Perform necessary steps to accept a connection
+ *
+ * Input:
+ *     cr_handle
+ *     ep_handle
+ *     private_data_size
+ *     private_data
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,
+                          IN DAT_EP_HANDLE ep_handle,
+                          IN DAT_COUNT p_size, IN const DAT_PVOID p_data)
+{
+       DAPL_CR *cr_ptr;
+       DAPL_EP *ep_ptr;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    "dapls_ib_accept_connection(cr %p ep %p prd %p,%d)\n",
+                    cr_handle, ep_handle, p_data, p_size);
+
+       cr_ptr = (DAPL_CR *) cr_handle;
+       ep_ptr = (DAPL_EP *) ep_handle;
+
+       /* allocate and attach a QP if necessary */
+       if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
+               DAT_RETURN status;
+               status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
+                                          ep_ptr, ep_ptr);
+               if (status != DAT_SUCCESS)
+                       return status;
+       }
+       return (dapli_socket_accept_usr(ep_ptr, cr_ptr, p_size, p_data));
+}
+
+/*
+ * dapls_ib_reject_connection
+ *
+ * Reject a connection
+ *
+ * Input:
+ *     cr_handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_reject_connection(IN dp_ib_cm_handle_t cm_ptr,
+                          IN int reason,
+                          IN DAT_COUNT psize, IN const DAT_PVOID pdata)
+{
+       struct iovec iov[2];
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " reject(cm %p reason %x, pdata %p, psize %d)\n",
+                    cm_ptr, reason, pdata, psize);
+
+        if (psize > DCM_MAX_PDATA_SIZE)
+                return DAT_LENGTH_ERROR;
+
+       /* write reject data to indicate reject */
+       cm_ptr->msg.op = htons(DCM_REJ_USER);
+       cm_ptr->msg.p_size = htons(psize);
+       
+       iov[0].iov_base = (void *)&cm_ptr->msg;
+       iov[0].iov_len = sizeof(ib_cm_msg_t) - DCM_MAX_PDATA_SIZE;
+       if (psize) {
+               iov[1].iov_base = pdata;
+               iov[1].iov_len = psize;
+               writev(cm_ptr->socket, iov, 2);
+       } else {
+               writev(cm_ptr->socket, iov, 1);
+       }
+
+       /* release and cleanup CM object */
+       dapli_cm_free(cm_ptr);
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_cm_remote_addr
+ *
+ * Obtain the remote IP address given a connection
+ *
+ * Input:
+ *     cr_handle
+ *
+ * Output:
+ *     remote_ia_address: where to place the remote address
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_HANDLE
+ *
+ */
+DAT_RETURN
+dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle,
+                       OUT DAT_SOCK_ADDR6 * remote_ia_address)
+{
+       DAPL_HEADER *header;
+       dp_ib_cm_handle_t conn;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    "dapls_ib_cm_remote_addr(dat_handle %p, ....)\n",
+                    dat_handle);
+
+       header = (DAPL_HEADER *) dat_handle;
+
+       if (header->magic == DAPL_MAGIC_EP)
+               conn = dapl_get_cm_from_ep((DAPL_EP *) dat_handle);
+       else if (header->magic == DAPL_MAGIC_CR)
+               conn = ((DAPL_CR *) dat_handle)->ib_cm_handle;
+       else
+               return DAT_INVALID_HANDLE;
+
+       dapl_os_memcpy(remote_ia_address,
+                      &conn->msg.daddr.so, sizeof(DAT_SOCK_ADDR6));
+
+       return DAT_SUCCESS;
+}
+
+int dapls_ib_private_data_size(
+       IN DAPL_HCA *hca_ptr)
+{
+       return DCM_MAX_PDATA_SIZE;
+}
+
+/* outbound/inbound CR processing thread to avoid blocking applications */
+void cr_thread(void *arg)
+{
+       struct dapl_hca *hca_ptr = arg;
+       dp_ib_cm_handle_t cr, next_cr;
+       int opt, ret;
+       socklen_t opt_len;
+       char rbuf[2];
+       struct dapl_fd_set *set;
+       enum DAPL_FD_EVENTS event;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cr_thread: ENTER hca %p\n", hca_ptr);
+       set = dapl_alloc_fd_set();
+       if (!set)
+               goto out;
+
+       dapl_os_lock(&hca_ptr->ib_trans.lock);
+       hca_ptr->ib_trans.cr_state = IB_THREAD_RUN;
+
+       while (1) {
+               dapl_fd_zero(set);
+               dapl_fd_set(hca_ptr->ib_trans.scm[0], set, DAPL_FD_READ);
+
+               if (!dapl_llist_is_empty(&hca_ptr->ib_trans.list))
+                       next_cr = dapl_llist_peek_head(&hca_ptr->ib_trans.list);
+               else
+                       next_cr = NULL;
+
+               while (next_cr) {
+                       cr = next_cr;
+                       next_cr = dapl_llist_next_entry(&hca_ptr->ib_trans.list,
+                                                       (DAPL_LLIST_ENTRY *) 
+                                                       &cr->local_entry);
+                       dapls_cm_acquire(cr); /* hold thread ref */
+                       dapl_os_lock(&cr->lock);
+                       if (cr->state == DCM_FREE || 
+                           hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) {
+                               dapl_log(DAPL_DBG_TYPE_CM, 
+                                        " CM FREE: %p ep=%p st=%s sck=%d refs=%d\n", 
+                                        cr, cr->ep, dapl_cm_state_str(cr->state), 
+                                        cr->socket, cr->ref_count);
+
+                               if (cr->socket != DAPL_INVALID_SOCKET) {
+                                       shutdown(cr->socket, SHUT_RDWR);
+                                       closesocket(cr->socket);
+                                       cr->socket = DAPL_INVALID_SOCKET;
+                               }
+                               dapl_os_unlock(&cr->lock);
+                               dapls_cm_release(cr); /* release alloc ref */
+                               dapli_cm_dequeue(cr); /* release workq ref */
+                               dapls_cm_release(cr); /* release thread ref */
+                               continue;
+                       }
+
+                       event = (cr->state == DCM_CONN_PENDING) ?
+                                       DAPL_FD_WRITE : DAPL_FD_READ;
+
+                       if (dapl_fd_set(cr->socket, set, event)) {
+                               dapl_log(DAPL_DBG_TYPE_ERR,
+                                        " cr_thread: fd_set ERR st=%d fd %d"
+                                        " -> %s\n", cr->state, cr->socket,
+                                        inet_ntoa(((struct sockaddr_in *)
+                                               &cr->msg.daddr.so)->sin_addr));
+                               dapl_os_unlock(&cr->lock);
+                               dapls_cm_release(cr); /* release ref */
+                               continue;
+                       }
+                       dapl_os_unlock(&cr->lock);
+                       dapl_os_unlock(&hca_ptr->ib_trans.lock);
+                       
+                       ret = dapl_poll(cr->socket, event);
+
+                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                                    " poll ret=0x%x %s sck=%d\n",
+                                    ret, dapl_cm_state_str(cr->state), 
+                                    cr->socket);
+
+                       /* data on listen, qp exchange, and on disc req */
+                       if ((ret == DAPL_FD_READ) || 
+                           (cr->state != DCM_CONN_PENDING && ret == DAPL_FD_ERROR)) {
+                               if (cr->socket != DAPL_INVALID_SOCKET) {
+                                       switch (cr->state) {
+                                       case DCM_LISTEN:
+                                               dapli_socket_accept(cr);
+                                               break;
+                                       case DCM_ACCEPTING:
+                                               dapli_socket_accept_data(cr);
+                                               break;
+                                       case DCM_ACCEPTED:
+                                               dapli_socket_accept_rtu(cr);
+                                               break;
+                                       case DCM_REP_PENDING:
+                                               dapli_socket_connect_rtu(cr);
+                                               break;
+                                       case DCM_CONNECTED:
+                                               dapli_socket_disconnect(cr);
+                                               break;
+                                       default:
+                                               break;
+                                       }
+                               }
+                       /* ASYNC connections, writable, readable, error; check status */
+                       } else if (ret == DAPL_FD_WRITE ||
+                                  (cr->state == DCM_CONN_PENDING && 
+                                   ret == DAPL_FD_ERROR)) {
+
+                               if (ret == DAPL_FD_ERROR)
+                                       dapl_log(DAPL_DBG_TYPE_ERR, " CONN_PENDING - FD_ERROR\n");
+                               
+                               opt = 0;
+                               opt_len = sizeof(opt);
+                               ret = getsockopt(cr->socket, SOL_SOCKET,
+                                                SO_ERROR, (char *)&opt,
+                                                &opt_len);
+                               if (!ret && !opt)
+                                       dapli_socket_connected(cr, opt);
+                               else
+                                       dapli_socket_connected(cr, opt ? opt : dapl_socket_errno());
+                       } 
+
+                       dapls_cm_release(cr); /* release ref */
+                       dapl_os_lock(&hca_ptr->ib_trans.lock);
+               }
+
+               /* set to exit and all resources destroyed */
+               if ((hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) &&
+                   (dapl_llist_is_empty(&hca_ptr->ib_trans.list)))
+                       break;
+
+               dapl_os_unlock(&hca_ptr->ib_trans.lock);
+               dapl_select(set);
+
+               /* if pipe used to wakeup, consume */
+               while (dapl_poll(hca_ptr->ib_trans.scm[0], 
+                                DAPL_FD_READ) == DAPL_FD_READ) {
+                       if (recv(hca_ptr->ib_trans.scm[0], rbuf, 2, 0) == -1)
+                               dapl_log(DAPL_DBG_TYPE_THREAD,
+                                        " cr_thread: read pipe error = %s\n",
+                                        strerror(errno));
+               }
+               dapl_os_lock(&hca_ptr->ib_trans.lock);
+               
+               /* set to exit and all resources destroyed */
+               if ((hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) &&
+                   (dapl_llist_is_empty(&hca_ptr->ib_trans.list)))
+                       break;
+       }
+
+       dapl_os_unlock(&hca_ptr->ib_trans.lock);
+       dapl_os_free(set, sizeof(struct dapl_fd_set));
+out:
+       hca_ptr->ib_trans.cr_state = IB_THREAD_EXIT;
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " cr_thread(hca %p) exit\n", hca_ptr);
+}
+
+
+#ifdef DAPL_COUNTERS
+/* Debug aid: List all Connections in process and state */
+void dapls_print_cm_list(IN DAPL_IA *ia_ptr)
+{
+       /* Print in process CR's for this IA, if debug type set */
+       int i = 0;
+       dp_ib_cm_handle_t cr, next_cr;
+
+       dapl_os_lock(&ia_ptr->hca_ptr->ib_trans.lock);
+       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)
+                                &ia_ptr->hca_ptr->ib_trans.list))
+                                next_cr = dapl_llist_peek_head((DAPL_LLIST_HEAD*)
+                                &ia_ptr->hca_ptr->ib_trans.list);
+       else
+               next_cr = NULL;
+
+        printf("\n DAPL IA CONNECTIONS IN PROCESS:\n");
+       while (next_cr) {
+               cr = next_cr;
+               next_cr = dapl_llist_next_entry((DAPL_LLIST_HEAD*)
+                                &ia_ptr->hca_ptr->ib_trans.list,
+                               (DAPL_LLIST_ENTRY*)&cr->local_entry);
+
+               printf( "  CONN[%d]: sp %p ep %p sock %d %s %s %s %s %s %s PORT L-%x R-%x PID L-%x R-%x\n",
+                       i, cr->sp, cr->ep, cr->socket,
+                       cr->msg.saddr.ib.qp_type == IBV_QPT_RC ? "RC" : "UD",
+                       dapl_cm_state_str(cr->state), dapl_cm_op_str(ntohs(cr->msg.op)),
+                       ntohs(cr->msg.op) == DCM_REQ ? /* local address */
+                               inet_ntoa(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_addr) :
+                               inet_ntoa(((struct sockaddr_in *)&cr->addr)->sin_addr),
+                       cr->sp ? "<-" : "->",
+                               ntohs(cr->msg.op) == DCM_REQ ? /* remote address */
+                               inet_ntoa(((struct sockaddr_in *)&cr->addr)->sin_addr) :
+                               inet_ntoa(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_addr),
+
+                       ntohs(cr->msg.op) == DCM_REQ ? /* local port */
+                               ntohs(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_port) :
+                               ntohs(((struct sockaddr_in *)&cr->addr)->sin_port),
+
+                       ntohs(cr->msg.op) == DCM_REQ ? /* remote port */
+                               ntohs(((struct sockaddr_in *)&cr->addr)->sin_port) :
+                               ntohs(((struct sockaddr_in *)&cr->msg.daddr.so)->sin_port),
+
+                       cr->sp ? ntohs(*(uint16_t*)&cr->msg.resv[2]) : ntohs(*(uint16_t*)&cr->msg.resv[0]),
+                       cr->sp ? ntohs(*(uint16_t*)&cr->msg.resv[0]) : ntohs(*(uint16_t*)&cr->msg.resv[2]));
+
+               i++;
+       }
+       printf("\n");
+       dapl_os_unlock(&ia_ptr->hca_ptr->ib_trans.lock);
+}
+#endif
index 138a3dd74c049b00beef23928d8e790f798f1469..497bc64a5ad91c124474206cce7c4001c848630f 100644 (file)
 #include "openib_osd.h"
 #include "dapl_ib_common.h"
 
+/* DAPL CM objects MUST include list_entry, ref_count, event for EP linking */
 struct ib_cm_handle
 { 
-       struct dapl_llist_entry entry;
+       struct dapl_llist_entry list_entry;
+       struct dapl_llist_entry local_entry;
+        DAPL_OS_WAIT_OBJECT    event;
        DAPL_OS_LOCK            lock;
+       int                     ref_count;
        int                     state;
        DAPL_SOCKET             socket;
        struct dapl_hca         *hca;
@@ -45,7 +49,7 @@ struct ib_cm_handle
        DAT_SOCK_ADDR6          addr; 
 };
 
-typedef struct ib_cm_handle    *dp_ib_cm_handle_t;
+typedef struct ib_cm_handle    *dp_ib_cm_handle_t;
 typedef dp_ib_cm_handle_t      ib_cm_srvc_handle_t;
 
 /* Definitions */
@@ -110,9 +114,12 @@ int dapli_cq_thread_init(struct dapl_hca *hca_ptr);
 void dapli_cq_thread_destroy(struct dapl_hca *hca_ptr);
 void dapli_async_event_cb(struct _ib_hca_transport *tp);
 void dapli_cq_event_cb(struct _ib_hca_transport *tp);
-DAT_RETURN dapli_socket_disconnect(dp_ib_cm_handle_t cm_ptr);
-dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep);
-void dapls_ib_cm_free(dp_ib_cm_handle_t cm, DAPL_EP *ep);
+void dapls_cm_acquire(dp_ib_cm_handle_t cm_ptr);
+void dapls_cm_release(dp_ib_cm_handle_t cm_ptr);
+void dapls_cm_free(dp_ib_cm_handle_t cm_ptr);
+
+#ifdef DAPL_COUNTERS
 void dapls_print_cm_list(IN DAPL_IA *ia_ptr);
+#endif
 
 #endif /*  _DAPL_IB_UTIL_H_ */
index 04e992a8ef86dbb1bd317dfeb9da5c41a16d6b4e..eb87a85b977af407df023ebcdff8f6dc2ced030d 100644 (file)
-/*\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-/***************************************************************************\r
- *\r
- *   Module:            uDAPL\r
- *\r
- *   Filename:          dapl_ib_util.c\r
- *\r
- *   Author:            Arlin Davis\r
- *\r
- *   Created:           3/10/2005\r
- *\r
- *   Description: \r
- *\r
- *   The uDAPL openib provider - init, open, close, utilities\r
- *\r
- ****************************************************************************\r
- *                Source Control System Information\r
- *\r
- *    $Id: $\r
- *\r
- *     Copyright (c) 2005 Intel Corporation.  All rights reserved.\r
- *\r
- **************************************************************************/\r
-#ifdef RCSID\r
-static const char rcsid[] = "$Id:  $";\r
-#endif\r
-\r
-#include "openib_osd.h"\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_ib_util.h"\r
-#include "dapl_osd.h"\r
-\r
-#include <stdlib.h>\r
-\r
-ib_thread_state_t g_ib_thread_state = 0;\r
-DAPL_OS_THREAD g_ib_thread;\r
-DAPL_OS_LOCK g_hca_lock;\r
-struct dapl_llist_entry *g_hca_list;\r
-\r
-void dapli_thread(void *arg);\r
-DAT_RETURN  dapli_ib_thread_init(void);\r
-void dapli_ib_thread_destroy(void);\r
-\r
-#if defined(_WIN64) || defined(_WIN32)\r
-#include "..\..\..\..\..\etc\user\comp_channel.cpp"\r
-#include <rdma\winverbs.h>\r
-\r
-static COMP_SET ufds;\r
-\r
-static int dapls_os_init(void)\r
-{\r
-       return CompSetInit(&ufds);\r
-}\r
-\r
-static void dapls_os_release(void)\r
-{\r
-       CompSetCleanup(&ufds);\r
-}\r
-\r
-static int dapls_config_verbs(struct ibv_context *verbs)\r
-{\r
-       verbs->channel.Milliseconds = 0;\r
-       return 0;\r
-}\r
-\r
-static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
-{\r
-       channel->comp_channel.Milliseconds = 0;\r
-       return 0;\r
-}\r
-\r
-static int dapls_thread_signal(void)\r
-{\r
-       CompSetCancel(&ufds);\r
-       return 0;\r
-}\r
-#else                          // _WIN64 || WIN32\r
-int g_ib_pipe[2];\r
-\r
-static int dapls_os_init(void)\r
-{\r
-       /* create pipe for waking up work thread */\r
-       return pipe(g_ib_pipe);\r
-}\r
-\r
-static void dapls_os_release(void)\r
-{\r
-       /* close pipe? */\r
-}\r
-\r
-static int dapls_config_fd(int fd)\r
-{\r
-       int opts;\r
-\r
-       opts = fcntl(fd, F_GETFL);\r
-       if (opts < 0 || fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " dapls_config_fd: fcntl on fd %d ERR %d %s\n",\r
-                        fd, opts, strerror(errno));\r
-               return errno;\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-static int dapls_config_verbs(struct ibv_context *verbs)\r
-{\r
-       return dapls_config_fd(verbs->async_fd);\r
-}\r
-\r
-static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
-{\r
-       return dapls_config_fd(channel->fd);\r
-}\r
-\r
-static int dapls_thread_signal(void)\r
-{\r
-       return write(g_ib_pipe[1], "w", sizeof "w");\r
-}\r
-#endif\r
-\r
-\r
-static int32_t create_cr_pipe(IN DAPL_HCA * hca_ptr)\r
-{\r
-       DAPL_SOCKET listen_socket;\r
-       struct sockaddr_in addr;\r
-       socklen_t addrlen = sizeof(addr);\r
-       int ret;\r
-\r
-       listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
-       if (listen_socket == DAPL_INVALID_SOCKET)\r
-               return 1;\r
-\r
-       memset(&addr, 0, sizeof addr);\r
-       addr.sin_family = AF_INET;\r
-       addr.sin_addr.s_addr = htonl(0x7f000001);\r
-       ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof addr);\r
-       if (ret)\r
-               goto err1;\r
-\r
-       ret = getsockname(listen_socket, (struct sockaddr *)&addr, &addrlen);\r
-       if (ret)\r
-               goto err1;\r
-\r
-       ret = listen(listen_socket, 0);\r
-       if (ret)\r
-               goto err1;\r
-\r
-       hca_ptr->ib_trans.scm[1] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\r
-       if (hca_ptr->ib_trans.scm[1] == DAPL_INVALID_SOCKET)\r
-               goto err1;\r
-\r
-       ret = connect(hca_ptr->ib_trans.scm[1], \r
-                     (struct sockaddr *)&addr, sizeof(addr));\r
-       if (ret)\r
-               goto err2;\r
-\r
-       hca_ptr->ib_trans.scm[0] = accept(listen_socket, NULL, NULL);\r
-       if (hca_ptr->ib_trans.scm[0] == DAPL_INVALID_SOCKET)\r
-               goto err2;\r
-\r
-       closesocket(listen_socket);\r
-       return 0;\r
-\r
-      err2:\r
-       closesocket(hca_ptr->ib_trans.scm[1]);\r
-      err1:\r
-       closesocket(listen_socket);\r
-       return 1;\r
-}\r
-\r
-static void destroy_cr_pipe(IN DAPL_HCA * hca_ptr)\r
-{\r
-       closesocket(hca_ptr->ib_trans.scm[0]);\r
-       closesocket(hca_ptr->ib_trans.scm[1]);\r
-}\r
-\r
-\r
-/*\r
- * dapls_ib_init, dapls_ib_release\r
- *\r
- * Initialize Verb related items for device open\r
- *\r
- * Input:\r
- *     none\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     0 success, -1 error\r
- *\r
- */\r
-int32_t dapls_ib_init(void)\r
-{\r
-       /* initialize hca_list */\r
-       dapl_os_lock_init(&g_hca_lock);\r
-       dapl_llist_init_head(&g_hca_list);\r
-\r
-       if (dapls_os_init())\r
-               return 1;\r
-\r
-       return 0;\r
-}\r
-\r
-int32_t dapls_ib_release(void)\r
-{\r
-       dapli_ib_thread_destroy();\r
-       dapls_os_release();\r
-       return 0;\r
-}\r
-\r
-/*\r
- * dapls_ib_open_hca\r
- *\r
- * Open HCA\r
- *\r
- * Input:\r
- *      *hca_name         pointer to provider device name\r
- *      *ib_hca_handle_p  pointer to provide HCA handle\r
- *\r
- * Output:\r
- *      none\r
- *\r
- * Return:\r
- *      DAT_SUCCESS\r
- *      dapl_convert_errno\r
- *\r
- */\r
-DAT_RETURN dapls_ib_open_hca(IN IB_HCA_NAME hca_name, IN DAPL_HCA * hca_ptr)\r
-{\r
-       struct ibv_device **dev_list;\r
-       struct ibv_port_attr port_attr;\r
-       int i;\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: %s - %p\n", hca_name, hca_ptr);\r
-\r
-       /* get the IP address of the device */\r
-       dat_status = getlocalipaddr((DAT_SOCK_ADDR *) &hca_ptr->hca_address,\r
-                                   sizeof(DAT_SOCK_ADDR6));\r
-       if (dat_status != DAT_SUCCESS)\r
-               return dat_status;\r
-\r
-#ifdef DAPL_DBG\r
-       /* DBG: unused port, set process id, lower 16 bits of pid */\r
-       ((struct sockaddr_in *)&hca_ptr->hca_address)->sin_port = \r
-                                       htons((uint16_t)dapl_os_getpid());\r
-#endif\r
-        /* Get list of all IB devices, find match, open */\r
-       dev_list = ibv_get_device_list(NULL);\r
-       if (!dev_list) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
-                            " open_hca: ibv_get_device_list() failed\n",\r
-                            hca_name);\r
-               return DAT_INTERNAL_ERROR;\r
-       }\r
-\r
-       for (i = 0; dev_list[i]; ++i) {\r
-               hca_ptr->ib_trans.ib_dev = dev_list[i];\r
-               if (!strcmp(ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
-                           hca_name))\r
-                       goto found;\r
-       }\r
-\r
-       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                " open_hca: device %s not found\n", hca_name);\r
-       goto err;\r
-\r
-found:\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " open_hca: Found dev %s %016llx\n",\r
-                    ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
-                    (unsigned long long)\r
-                    ntohll(ibv_get_device_guid(hca_ptr->ib_trans.ib_dev)));\r
-\r
-       hca_ptr->ib_hca_handle = ibv_open_device(hca_ptr->ib_trans.ib_dev);\r
-       if (!hca_ptr->ib_hca_handle) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: dev open failed for %s, err=%s\n",\r
-                        ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
-                        strerror(errno));\r
-               goto err;\r
-       }\r
-       hca_ptr->ib_trans.ib_ctx = hca_ptr->ib_hca_handle;\r
-       dapls_config_verbs(hca_ptr->ib_hca_handle);\r
-\r
-       /* get lid for this hca-port, network order */\r
-       if (ibv_query_port(hca_ptr->ib_hca_handle,\r
-                          (uint8_t) hca_ptr->port_num, &port_attr)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: get lid ERR for %s, err=%s\n",\r
-                        ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
-                        strerror(errno));\r
-               goto err;\r
-       } else {\r
-               hca_ptr->ib_trans.lid = htons(port_attr.lid);\r
-       }\r
-\r
-       /* get gid for this hca-port, network order */\r
-       if (ibv_query_gid(hca_ptr->ib_hca_handle,\r
-                         (uint8_t) hca_ptr->port_num,\r
-                         0, &hca_ptr->ib_trans.gid)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: query GID ERR for %s, err=%s\n",\r
-                        ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
-                        strerror(errno));\r
-               goto err;\r
-       }\r
-\r
-       /* set RC tunables via enviroment or default */\r
-       hca_ptr->ib_trans.max_inline_send =\r
-           dapl_os_get_env_val("DAPL_MAX_INLINE", INLINE_SEND_DEFAULT);\r
-       hca_ptr->ib_trans.ack_retry =\r
-           dapl_os_get_env_val("DAPL_ACK_RETRY", SCM_ACK_RETRY);\r
-       hca_ptr->ib_trans.ack_timer =\r
-           dapl_os_get_env_val("DAPL_ACK_TIMER", SCM_ACK_TIMER);\r
-       hca_ptr->ib_trans.rnr_retry =\r
-           dapl_os_get_env_val("DAPL_RNR_RETRY", SCM_RNR_RETRY);\r
-       hca_ptr->ib_trans.rnr_timer =\r
-           dapl_os_get_env_val("DAPL_RNR_TIMER", SCM_RNR_TIMER);\r
-       hca_ptr->ib_trans.global =\r
-           dapl_os_get_env_val("DAPL_GLOBAL_ROUTING", SCM_GLOBAL);\r
-       hca_ptr->ib_trans.hop_limit =\r
-           dapl_os_get_env_val("DAPL_HOP_LIMIT", SCM_HOP_LIMIT);\r
-       hca_ptr->ib_trans.tclass =\r
-           dapl_os_get_env_val("DAPL_TCLASS", SCM_TCLASS);\r
-       hca_ptr->ib_trans.mtu =\r
-           dapl_ib_mtu(dapl_os_get_env_val("DAPL_IB_MTU", SCM_IB_MTU));\r
-\r
-\r
-       /* EVD events without direct CQ channels, CNO support */\r
-       hca_ptr->ib_trans.ib_cq =\r
-           ibv_create_comp_channel(hca_ptr->ib_hca_handle);\r
-       if (hca_ptr->ib_trans.ib_cq == NULL) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: ibv_create_comp_channel ERR %s\n",\r
-                        strerror(errno));\r
-               goto bail;\r
-       }\r
-       dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq);\r
-       \r
-       dat_status = dapli_ib_thread_init();\r
-       if (dat_status != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: failed to init cq thread lock\n");\r
-               goto bail;\r
-       }\r
-       /* \r
-        * Put new hca_transport on list for async and CQ event processing \r
-        * Wakeup work thread to add to polling list\r
-        */\r
-       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&hca_ptr->ib_trans.entry);\r
-       dapl_os_lock(&g_hca_lock);\r
-       dapl_llist_add_tail(&g_hca_list,\r
-                           (DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry,\r
-                           &hca_ptr->ib_trans.entry);\r
-       if (dapls_thread_signal() == -1)\r
-               dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                        " open_hca: thread wakeup error = %s\n",\r
-                        strerror(errno));\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       /* initialize cr_list lock */\r
-       dat_status = dapl_os_lock_init(&hca_ptr->ib_trans.lock);\r
-       if (dat_status != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: failed to init cr_list lock\n");\r
-               goto bail;\r
-       }\r
-\r
-       /* initialize CM list for listens on this HCA */\r
-       dapl_llist_init_head(&hca_ptr->ib_trans.list);\r
-\r
-       /* initialize pipe, user level wakeup on select */\r
-       if (create_cr_pipe(hca_ptr)) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: failed to init cr pipe - %s\n",\r
-                        strerror(errno));\r
-               goto bail;\r
-       }\r
-\r
-       /* create thread to process inbound connect request */\r
-       hca_ptr->ib_trans.cr_state = IB_THREAD_INIT;\r
-       dat_status = dapl_os_thread_create(cr_thread,\r
-                                          (void *)hca_ptr,\r
-                                          &hca_ptr->ib_trans.thread);\r
-       if (dat_status != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " open_hca: failed to create thread\n");\r
-               goto bail;\r
-       }\r
-\r
-       /* wait for thread */\r
-       while (hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) {\r
-               dapl_os_sleep_usec(1000);\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: devname %s, port %d, hostname_IP %s\n",\r
-                    ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
-                    hca_ptr->port_num, inet_ntoa(((struct sockaddr_in *)\r
-                                                  &hca_ptr->hca_address)->\r
-                                                 sin_addr));\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " open_hca: LID 0x%x GID Subnet 0x" F64x " ID 0x" F64x\r
-                    "\n", ntohs(hca_ptr->ib_trans.lid), (unsigned long long)\r
-                    htonll(hca_ptr->ib_trans.gid.global.subnet_prefix),\r
-                    (unsigned long long)htonll(hca_ptr->ib_trans.gid.global.\r
-                                               interface_id));\r
-\r
-       ibv_free_device_list(dev_list);\r
-       return dat_status;\r
-\r
-      bail:\r
-       ibv_close_device(hca_ptr->ib_hca_handle);\r
-       hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;\r
-      err:\r
-       ibv_free_device_list(dev_list);\r
-       return DAT_INTERNAL_ERROR;\r
-}\r
-\r
-/*\r
- * dapls_ib_close_hca\r
- *\r
- * Open HCA\r
- *\r
- * Input:\r
- *      DAPL_HCA   provide CA handle\r
- *\r
- * Output:\r
- *      none\r
- *\r
- * Return:\r
- *      DAT_SUCCESS\r
- *     dapl_convert_errno \r
- *\r
- */\r
-DAT_RETURN dapls_ib_close_hca(IN DAPL_HCA * hca_ptr)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " close_hca: %p\n", hca_ptr);\r
-\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_ib_thread_state != IB_THREAD_RUN) {\r
-               dapl_os_unlock(&g_hca_lock);\r
-               goto out;\r
-       }\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       /* destroy cr_thread and lock */\r
-       hca_ptr->ib_trans.cr_state = IB_THREAD_CANCEL;\r
-       send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);\r
-       while (hca_ptr->ib_trans.cr_state != IB_THREAD_EXIT) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " close_hca: waiting for cr_thread\n");\r
-               send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);\r
-               dapl_os_sleep_usec(1000);\r
-       }\r
-       dapl_os_lock_destroy(&hca_ptr->ib_trans.lock);\r
-       destroy_cr_pipe(hca_ptr); /* no longer need pipe */\r
-       \r
-       /* \r
-        * Remove hca from async event processing list\r
-        * Wakeup work thread to remove from polling list\r
-        */\r
-       hca_ptr->ib_trans.destroy = 1;\r
-       if (dapls_thread_signal() == -1)\r
-               dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                        " destroy: thread wakeup error = %s\n",\r
-                        strerror(errno));\r
-\r
-       /* wait for thread to remove HCA references */\r
-       while (hca_ptr->ib_trans.destroy != 2) {\r
-               if (dapls_thread_signal() == -1)\r
-                       dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                                " destroy: thread wakeup error = %s\n",\r
-                                strerror(errno));\r
-               dapl_os_sleep_usec(1000);\r
-       }\r
-\r
-out:\r
-       if (hca_ptr->ib_trans.ib_cq)\r
-               ibv_destroy_comp_channel(hca_ptr->ib_trans.ib_cq);\r
-\r
-       if (hca_ptr->ib_trans.ib_cq_empty) {\r
-               struct ibv_comp_channel *channel;\r
-               channel = hca_ptr->ib_trans.ib_cq_empty->channel;\r
-               ibv_destroy_cq(hca_ptr->ib_trans.ib_cq_empty);\r
-               ibv_destroy_comp_channel(channel);\r
-       }\r
-\r
-       if (hca_ptr->ib_hca_handle != IB_INVALID_HANDLE) {\r
-               if (ibv_close_device(hca_ptr->ib_hca_handle))\r
-                       return (dapl_convert_errno(errno, "ib_close_device"));\r
-               hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;\r
-       }\r
-       return (DAT_SUCCESS);\r
-}\r
-\r
-DAT_RETURN dapli_ib_thread_init(void)\r
-{\r
-       DAT_RETURN dat_status;\r
-\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_ib_thread_state != IB_THREAD_INIT) {\r
-               dapl_os_unlock(&g_hca_lock);\r
-               return DAT_SUCCESS;\r
-       }\r
-\r
-       g_ib_thread_state = IB_THREAD_CREATE;\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       /* create thread to process inbound connect request */\r
-       dat_status = dapl_os_thread_create(dapli_thread, NULL, &g_ib_thread);\r
-       if (dat_status != DAT_SUCCESS)\r
-               return (dapl_convert_errno(errno,\r
-                                          "create_thread ERR:"\r
-                                          " check resource limits"));\r
-\r
-       /* wait for thread to start */\r
-       dapl_os_lock(&g_hca_lock);\r
-       while (g_ib_thread_state != IB_THREAD_RUN) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread_init: waiting for ib_thread\n");\r
-               dapl_os_unlock(&g_hca_lock);\r
-               dapl_os_sleep_usec(1000);\r
-               dapl_os_lock(&g_hca_lock);\r
-       }\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-void dapli_ib_thread_destroy(void)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " ib_thread_destroy(%d)\n", dapl_os_getpid());\r
-       /* \r
-        * wait for async thread to terminate. \r
-        * pthread_join would be the correct method\r
-        * but some applications have some issues\r
-        */\r
-\r
-       /* destroy ib_thread, wait for termination, if not already */\r
-       dapl_os_lock(&g_hca_lock);\r
-       if (g_ib_thread_state != IB_THREAD_RUN)\r
-               goto bail;\r
-\r
-       g_ib_thread_state = IB_THREAD_CANCEL;\r
-       while (g_ib_thread_state != IB_THREAD_EXIT) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread_destroy: waiting for ib_thread\n");\r
-               if (dapls_thread_signal() == -1)\r
-                       dapl_log(DAPL_DBG_TYPE_UTIL,\r
-                                " destroy: thread wakeup error = %s\n",\r
-                                strerror(errno));\r
-               dapl_os_unlock(&g_hca_lock);\r
-               dapl_os_sleep_usec(2000);\r
-               dapl_os_lock(&g_hca_lock);\r
-       }\r
-bail:\r
-       dapl_os_unlock(&g_hca_lock);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                    " ib_thread_destroy(%d) exit\n", dapl_os_getpid());\r
-}\r
-\r
-\r
-#if defined(_WIN64) || defined(_WIN32)\r
-/* work thread for uAT, uCM, CQ, and async events */\r
-void dapli_thread(void *arg)\r
-{\r
-       struct _ib_hca_transport *hca;\r
-       struct _ib_hca_transport *uhca[8];\r
-       int ret, idx, cnt;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d,0x%x): ENTER: \n",\r
-                    dapl_os_getpid(), g_ib_thread);\r
-\r
-       dapl_os_lock(&g_hca_lock);\r
-       for (g_ib_thread_state = IB_THREAD_RUN;\r
-            g_ib_thread_state == IB_THREAD_RUN; \r
-            dapl_os_lock(&g_hca_lock)) {\r
-\r
-               CompSetZero(&ufds);\r
-               idx = 0;\r
-               hca = dapl_llist_is_empty(&g_hca_list) ? NULL :\r
-                     dapl_llist_peek_head(&g_hca_list);\r
-\r
-               while (hca) {\r
-                       CompSetAdd(&hca->ib_ctx->channel, &ufds);\r
-                       CompSetAdd(&hca->ib_cq->comp_channel, &ufds);\r
-                       uhca[idx++] = hca;\r
-                       hca = dapl_llist_next_entry(&g_hca_list,\r
-                                                   (DAPL_LLIST_ENTRY *)\r
-                                                   &hca->entry);\r
-               }\r
-               cnt = idx;\r
-\r
-               dapl_os_unlock(&g_hca_lock);\r
-               ret = CompSetPoll(&ufds, INFINITE);\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
-                            " ib_thread(%d) poll_event 0x%x\n",\r
-                            dapl_os_getpid(), ret);\r
-\r
-\r
-               /* check and process ASYNC events, per device */\r
-               for (idx = 0; idx < cnt; idx++) {\r
-                       if (uhca[idx]->destroy == 1) {\r
-                               dapl_os_lock(&g_hca_lock);\r
-                               dapl_llist_remove_entry(&g_hca_list,\r
-                                                       (DAPL_LLIST_ENTRY *)\r
-                                                       &uhca[idx]->entry);\r
-                               dapl_os_unlock(&g_hca_lock);\r
-                               uhca[idx]->destroy = 2;\r
-                       } else {\r
-                               dapli_cq_event_cb(uhca[idx]);\r
-                               dapli_async_event_cb(uhca[idx]);\r
-                       }\r
-               }\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d) EXIT\n",\r
-                    dapl_os_getpid());\r
-       g_ib_thread_state = IB_THREAD_EXIT;\r
-       dapl_os_unlock(&g_hca_lock);\r
-}\r
-#else                          // _WIN64 || WIN32\r
-\r
-/* work thread for uAT, uCM, CQ, and async events */\r
-void dapli_thread(void *arg)\r
-{\r
-       struct pollfd ufds[__FD_SETSIZE];\r
-       struct _ib_hca_transport *uhca[__FD_SETSIZE] = { NULL };\r
-       struct _ib_hca_transport *hca;\r
-       int ret, idx, fds;\r
-       char rbuf[2];\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                    " ib_thread(%d,0x%x): ENTER: pipe %d \n",\r
-                    dapl_os_getpid(), g_ib_thread, g_ib_pipe[0]);\r
-\r
-       /* Poll across pipe, CM, AT never changes */\r
-       dapl_os_lock(&g_hca_lock);\r
-       g_ib_thread_state = IB_THREAD_RUN;\r
-\r
-       ufds[0].fd = g_ib_pipe[0];      /* pipe */\r
-       ufds[0].events = POLLIN;\r
-\r
-       while (g_ib_thread_state == IB_THREAD_RUN) {\r
-\r
-               /* build ufds after pipe and uCMA events */\r
-               ufds[0].revents = 0;\r
-               idx = 0;\r
-\r
-               /*  Walk HCA list and setup async and CQ events */\r
-               if (!dapl_llist_is_empty(&g_hca_list))\r
-                       hca = dapl_llist_peek_head(&g_hca_list);\r
-               else\r
-                       hca = NULL;\r
-\r
-               while (hca) {\r
-\r
-                       /* uASYNC events */\r
-                       ufds[++idx].fd = hca->ib_ctx->async_fd;\r
-                       ufds[idx].events = POLLIN;\r
-                       ufds[idx].revents = 0;\r
-                       uhca[idx] = hca;\r
-\r
-                       /* CQ events are non-direct with CNO's */\r
-                       ufds[++idx].fd = hca->ib_cq->fd;\r
-                       ufds[idx].events = POLLIN;\r
-                       ufds[idx].revents = 0;\r
-                       uhca[idx] = hca;\r
-\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                                    " ib_thread(%d) poll_fd: hca[%d]=%p,"\r
-                                    " async=%d pipe=%d \n",\r
-                                    dapl_os_getpid(), hca, ufds[idx - 1].fd,\r
-                                    ufds[0].fd);\r
-\r
-                       hca = dapl_llist_next_entry(&g_hca_list,\r
-                                                   (DAPL_LLIST_ENTRY *)\r
-                                                   &hca->entry);\r
-               }\r
-\r
-               /* unlock, and setup poll */\r
-               fds = idx + 1;\r
-               dapl_os_unlock(&g_hca_lock);\r
-               ret = poll(ufds, fds, -1);\r
-               if (ret <= 0) {\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                                    " ib_thread(%d): ERR %s poll\n",\r
-                                    dapl_os_getpid(), strerror(errno));\r
-                       dapl_os_lock(&g_hca_lock);\r
-                       continue;\r
-               }\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
-                            " ib_thread(%d) poll_event: "\r
-                            " async=0x%x pipe=0x%x \n",\r
-                            dapl_os_getpid(), ufds[idx].revents,\r
-                            ufds[0].revents);\r
-\r
-               /* check and process CQ and ASYNC events, per device */\r
-               for (idx = 1; idx < fds; idx++) {\r
-                       if (ufds[idx].revents == POLLIN) {\r
-                               dapli_cq_event_cb(uhca[idx]);\r
-                               dapli_async_event_cb(uhca[idx]);\r
-                       }\r
-               }\r
-\r
-               /* check and process user events, PIPE */\r
-               if (ufds[0].revents == POLLIN) {\r
-                       if (read(g_ib_pipe[0], rbuf, 2) == -1)\r
-                               dapl_log(DAPL_DBG_TYPE_THREAD,\r
-                                        " cr_thread: pipe rd err= %s\n",\r
-                                        strerror(errno));\r
-\r
-                       /* cleanup any device on list marked for destroy */\r
-                       for (idx = 1; idx < fds; idx++) {\r
-                               if (uhca[idx] && uhca[idx]->destroy == 1) {\r
-                                       dapl_os_lock(&g_hca_lock);\r
-                                       dapl_llist_remove_entry(\r
-                                               &g_hca_list,\r
-                                               (DAPL_LLIST_ENTRY*)\r
-                                               &uhca[idx]->entry);\r
-                                       dapl_os_unlock(&g_hca_lock);\r
-                                       uhca[idx]->destroy = 2;\r
-                               }\r
-                       }\r
-               }\r
-               dapl_os_lock(&g_hca_lock);\r
-       }\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " ib_thread(%d) EXIT\n",\r
-                    dapl_os_getpid());\r
-       g_ib_thread_state = IB_THREAD_EXIT;\r
-       dapl_os_unlock(&g_hca_lock);\r
-}\r
-#endif\r
+/*
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+/***************************************************************************
+ *
+ *   Module:            uDAPL
+ *
+ *   Filename:          dapl_ib_util.c
+ *
+ *   Author:            Arlin Davis
+ *
+ *   Created:           3/10/2005
+ *
+ *   Description: 
+ *
+ *   The uDAPL openib provider - init, open, close, utilities
+ *
+ ****************************************************************************
+ *                Source Control System Information
+ *
+ *    $Id: $
+ *
+ *     Copyright (c) 2005 Intel Corporation.  All rights reserved.
+ *
+ **************************************************************************/
+#ifdef RCSID
+static const char rcsid[] = "$Id:  $";
+#endif
+
+#include "openib_osd.h"
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_ib_util.h"
+#include "dapl_osd.h"
+
+#include <stdlib.h>
+
+ib_thread_state_t g_ib_thread_state = 0;
+DAPL_OS_THREAD g_ib_thread;
+DAPL_OS_LOCK g_hca_lock;
+struct dapl_llist_entry *g_hca_list;
+
+void dapli_thread(void *arg);
+DAT_RETURN  dapli_ib_thread_init(void);
+void dapli_ib_thread_destroy(void);
+
+#if defined(_WIN64) || defined(_WIN32)
+#include "..\..\..\..\..\etc\user\comp_channel.cpp"
+#include <rdma\winverbs.h>
+
+static COMP_SET ufds;
+
+static int dapls_os_init(void)
+{
+       return CompSetInit(&ufds);
+}
+
+static void dapls_os_release(void)
+{
+       CompSetCleanup(&ufds);
+}
+
+static int dapls_config_verbs(struct ibv_context *verbs)
+{
+       verbs->channel.Milliseconds = 0;
+       return 0;
+}
+
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)
+{
+       channel->comp_channel.Milliseconds = 0;
+       return 0;
+}
+
+static int dapls_thread_signal(void)
+{
+       CompSetCancel(&ufds);
+       return 0;
+}
+#else                          // _WIN64 || WIN32
+int g_ib_pipe[2];
+
+static int dapls_os_init(void)
+{
+       /* create pipe for waking up work thread */
+       return pipe(g_ib_pipe);
+}
+
+static void dapls_os_release(void)
+{
+       /* close pipe? */
+}
+
+static int dapls_config_fd(int fd)
+{
+       int opts;
+
+       opts = fcntl(fd, F_GETFL);
+       if (opts < 0 || fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " dapls_config_fd: fcntl on fd %d ERR %d %s\n",
+                        fd, opts, strerror(errno));
+               return errno;
+       }
+
+       return 0;
+}
+
+static int dapls_config_verbs(struct ibv_context *verbs)
+{
+       return dapls_config_fd(verbs->async_fd);
+}
+
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)
+{
+       return dapls_config_fd(channel->fd);
+}
+
+static int dapls_thread_signal(void)
+{
+       return write(g_ib_pipe[1], "w", sizeof "w");
+}
+#endif
+
+
+static int32_t create_cr_pipe(IN DAPL_HCA * hca_ptr)
+{
+       DAPL_SOCKET listen_socket;
+       struct sockaddr_in addr;
+       socklen_t addrlen = sizeof(addr);
+       int ret;
+
+       listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (listen_socket == DAPL_INVALID_SOCKET)
+               return 1;
+
+       memset(&addr, 0, sizeof addr);
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(0x7f000001);
+       ret = bind(listen_socket, (struct sockaddr *)&addr, sizeof addr);
+       if (ret)
+               goto err1;
+
+       ret = getsockname(listen_socket, (struct sockaddr *)&addr, &addrlen);
+       if (ret)
+               goto err1;
+
+       ret = listen(listen_socket, 0);
+       if (ret)
+               goto err1;
+
+       hca_ptr->ib_trans.scm[1] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       if (hca_ptr->ib_trans.scm[1] == DAPL_INVALID_SOCKET)
+               goto err1;
+
+       ret = connect(hca_ptr->ib_trans.scm[1], 
+                     (struct sockaddr *)&addr, sizeof(addr));
+       if (ret)
+               goto err2;
+
+       hca_ptr->ib_trans.scm[0] = accept(listen_socket, NULL, NULL);
+       if (hca_ptr->ib_trans.scm[0] == DAPL_INVALID_SOCKET)
+               goto err2;
+
+       closesocket(listen_socket);
+       return 0;
+
+      err2:
+       closesocket(hca_ptr->ib_trans.scm[1]);
+      err1:
+       closesocket(listen_socket);
+       return 1;
+}
+
+static void destroy_cr_pipe(IN DAPL_HCA * hca_ptr)
+{
+       closesocket(hca_ptr->ib_trans.scm[0]);
+       closesocket(hca_ptr->ib_trans.scm[1]);
+}
+
+
+/*
+ * dapls_ib_init, dapls_ib_release
+ *
+ * Initialize Verb related items for device open
+ *
+ * Input:
+ *     none
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     0 success, -1 error
+ *
+ */
+int32_t dapls_ib_init(void)
+{
+       /* initialize hca_list */
+       dapl_os_lock_init(&g_hca_lock);
+       dapl_llist_init_head(&g_hca_list);
+
+       if (dapls_os_init())
+               return 1;
+
+       return 0;
+}
+
+int32_t dapls_ib_release(void)
+{
+       dapli_ib_thread_destroy();
+       dapls_os_release();
+       return 0;
+}
+
+/*
+ * dapls_ib_open_hca
+ *
+ * Open HCA
+ *
+ * Input:
+ *      *hca_name         pointer to provider device name
+ *      *ib_hca_handle_p  pointer to provide HCA handle
+ *
+ * Output:
+ *      none
+ *
+ * Return:
+ *      DAT_SUCCESS
+ *      dapl_convert_errno
+ *
+ */
+DAT_RETURN dapls_ib_open_hca(IN IB_HCA_NAME hca_name, IN DAPL_HCA * hca_ptr)
+{
+       struct ibv_device **dev_list;
+       struct ibv_port_attr port_attr;
+       int i;
+       DAT_RETURN dat_status;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: %s - %p\n", hca_name, hca_ptr);
+
+       /* get the IP address of the device */
+       dat_status = getlocalipaddr((DAT_SOCK_ADDR *) &hca_ptr->hca_address,
+                                   sizeof(DAT_SOCK_ADDR6));
+       if (dat_status != DAT_SUCCESS)
+               return dat_status;
+
+#ifdef DAPL_DBG
+       /* DBG: unused port, set process id, lower 16 bits of pid */
+       ((struct sockaddr_in *)&hca_ptr->hca_address)->sin_port = 
+                                       htons((uint16_t)dapl_os_getpid());
+#endif
+        /* Get list of all IB devices, find match, open */
+       dev_list = ibv_get_device_list(NULL);
+       if (!dev_list) {
+               dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+                            " open_hca: ibv_get_device_list() failed\n",
+                            hca_name);
+               return DAT_INTERNAL_ERROR;
+       }
+
+       for (i = 0; dev_list[i]; ++i) {
+               hca_ptr->ib_trans.ib_dev = dev_list[i];
+               if (!strcmp(ibv_get_device_name(hca_ptr->ib_trans.ib_dev),
+                           hca_name))
+                       goto found;
+       }
+
+       dapl_log(DAPL_DBG_TYPE_ERR,
+                " open_hca: device %s not found\n", hca_name);
+       goto err;
+
+found:
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " open_hca: Found dev %s %016llx\n",
+                    ibv_get_device_name(hca_ptr->ib_trans.ib_dev),
+                    (unsigned long long)
+                    ntohll(ibv_get_device_guid(hca_ptr->ib_trans.ib_dev)));
+
+       hca_ptr->ib_hca_handle = ibv_open_device(hca_ptr->ib_trans.ib_dev);
+       if (!hca_ptr->ib_hca_handle) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: dev open failed for %s, err=%s\n",
+                        ibv_get_device_name(hca_ptr->ib_trans.ib_dev),
+                        strerror(errno));
+               goto err;
+       }
+       hca_ptr->ib_trans.ib_ctx = hca_ptr->ib_hca_handle;
+       dapls_config_verbs(hca_ptr->ib_hca_handle);
+
+       /* get lid for this hca-port, network order */
+       if (ibv_query_port(hca_ptr->ib_hca_handle,
+                          (uint8_t) hca_ptr->port_num, &port_attr)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: get lid ERR for %s, err=%s\n",
+                        ibv_get_device_name(hca_ptr->ib_trans.ib_dev),
+                        strerror(errno));
+               goto err;
+       } else {
+               hca_ptr->ib_trans.lid = htons(port_attr.lid);
+       }
+
+       /* get gid for this hca-port, network order */
+       if (ibv_query_gid(hca_ptr->ib_hca_handle,
+                         (uint8_t) hca_ptr->port_num,
+                         0, &hca_ptr->ib_trans.gid)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: query GID ERR for %s, err=%s\n",
+                        ibv_get_device_name(hca_ptr->ib_trans.ib_dev),
+                        strerror(errno));
+               goto err;
+       }
+
+       /* set RC tunables via enviroment or default */
+       hca_ptr->ib_trans.max_inline_send =
+           dapl_os_get_env_val("DAPL_MAX_INLINE", INLINE_SEND_DEFAULT);
+       hca_ptr->ib_trans.ack_retry =
+           dapl_os_get_env_val("DAPL_ACK_RETRY", SCM_ACK_RETRY);
+       hca_ptr->ib_trans.ack_timer =
+           dapl_os_get_env_val("DAPL_ACK_TIMER", SCM_ACK_TIMER);
+       hca_ptr->ib_trans.rnr_retry =
+           dapl_os_get_env_val("DAPL_RNR_RETRY", SCM_RNR_RETRY);
+       hca_ptr->ib_trans.rnr_timer =
+           dapl_os_get_env_val("DAPL_RNR_TIMER", SCM_RNR_TIMER);
+       hca_ptr->ib_trans.global =
+           dapl_os_get_env_val("DAPL_GLOBAL_ROUTING", SCM_GLOBAL);
+       hca_ptr->ib_trans.hop_limit =
+           dapl_os_get_env_val("DAPL_HOP_LIMIT", SCM_HOP_LIMIT);
+       hca_ptr->ib_trans.tclass =
+           dapl_os_get_env_val("DAPL_TCLASS", SCM_TCLASS);
+       hca_ptr->ib_trans.mtu =
+           dapl_ib_mtu(dapl_os_get_env_val("DAPL_IB_MTU", SCM_IB_MTU));
+
+
+       /* EVD events without direct CQ channels, CNO support */
+       hca_ptr->ib_trans.ib_cq =
+           ibv_create_comp_channel(hca_ptr->ib_hca_handle);
+       if (hca_ptr->ib_trans.ib_cq == NULL) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: ibv_create_comp_channel ERR %s\n",
+                        strerror(errno));
+               goto bail;
+       }
+       dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq);
+       
+       dat_status = dapli_ib_thread_init();
+       if (dat_status != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: failed to init cq thread lock\n");
+               goto bail;
+       }
+       /* 
+        * Put new hca_transport on list for async and CQ event processing 
+        * Wakeup work thread to add to polling list
+        */
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&hca_ptr->ib_trans.entry);
+       dapl_os_lock(&g_hca_lock);
+       dapl_llist_add_tail(&g_hca_list,
+                           (DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry,
+                           &hca_ptr->ib_trans.entry);
+       if (dapls_thread_signal() == -1)
+               dapl_log(DAPL_DBG_TYPE_UTIL,
+                        " open_hca: thread wakeup error = %s\n",
+                        strerror(errno));
+       dapl_os_unlock(&g_hca_lock);
+
+       /* initialize cr_list lock */
+       dat_status = dapl_os_lock_init(&hca_ptr->ib_trans.lock);
+       if (dat_status != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: failed to init cr_list lock\n");
+               goto bail;
+       }
+
+       /* initialize CM list for listens on this HCA */
+       dapl_llist_init_head(&hca_ptr->ib_trans.list);
+
+       /* initialize pipe, user level wakeup on select */
+       if (create_cr_pipe(hca_ptr)) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: failed to init cr pipe - %s\n",
+                        strerror(errno));
+               goto bail;
+       }
+
+       /* create thread to process inbound connect request */
+       hca_ptr->ib_trans.cr_state = IB_THREAD_INIT;
+       dat_status = dapl_os_thread_create(cr_thread,
+                                          (void *)hca_ptr,
+                                          &hca_ptr->ib_trans.thread);
+       if (dat_status != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " open_hca: failed to create thread\n");
+               goto bail;
+       }
+
+       /* wait for thread */
+       while (hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) {
+               dapl_os_sleep_usec(1000);
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: devname %s, port %d, hostname_IP %s\n",
+                    ibv_get_device_name(hca_ptr->ib_trans.ib_dev),
+                    hca_ptr->port_num, inet_ntoa(((struct sockaddr_in *)
+                                                  &hca_ptr->hca_address)->
+                                                 sin_addr));
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " open_hca: LID 0x%x GID Subnet 0x" F64x " ID 0x" F64x
+                    "\n", ntohs(hca_ptr->ib_trans.lid), (unsigned long long)
+                    htonll(hca_ptr->ib_trans.gid.global.subnet_prefix),
+                    (unsigned long long)htonll(hca_ptr->ib_trans.gid.global.
+                                               interface_id));
+
+       ibv_free_device_list(dev_list);
+       return dat_status;
+
+      bail:
+       ibv_close_device(hca_ptr->ib_hca_handle);
+       hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;
+      err:
+       ibv_free_device_list(dev_list);
+       return DAT_INTERNAL_ERROR;
+}
+
+/*
+ * dapls_ib_close_hca
+ *
+ * Open HCA
+ *
+ * Input:
+ *      DAPL_HCA   provide CA handle
+ *
+ * Output:
+ *      none
+ *
+ * Return:
+ *      DAT_SUCCESS
+ *     dapl_convert_errno 
+ *
+ */
+DAT_RETURN dapls_ib_close_hca(IN DAPL_HCA * hca_ptr)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " close_hca: %p\n", hca_ptr);
+
+       dapl_os_lock(&g_hca_lock);
+       if (g_ib_thread_state != IB_THREAD_RUN) {
+               dapl_os_unlock(&g_hca_lock);
+               goto out;
+       }
+       dapl_os_unlock(&g_hca_lock);
+
+       /* destroy cr_thread and lock */
+       hca_ptr->ib_trans.cr_state = IB_THREAD_CANCEL;
+       send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);
+       while (hca_ptr->ib_trans.cr_state != IB_THREAD_EXIT) {
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " close_hca: waiting for cr_thread\n");
+               send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);
+               dapl_os_sleep_usec(1000);
+       }
+       dapl_os_lock_destroy(&hca_ptr->ib_trans.lock);
+       destroy_cr_pipe(hca_ptr); /* no longer need pipe */
+       
+       /* 
+        * Remove hca from async event processing list
+        * Wakeup work thread to remove from polling list
+        */
+       hca_ptr->ib_trans.destroy = 1;
+       if (dapls_thread_signal() == -1)
+               dapl_log(DAPL_DBG_TYPE_UTIL,
+                        " destroy: thread wakeup error = %s\n",
+                        strerror(errno));
+
+       /* wait for thread to remove HCA references */
+       while (hca_ptr->ib_trans.destroy != 2) {
+               if (dapls_thread_signal() == -1)
+                       dapl_log(DAPL_DBG_TYPE_UTIL,
+                                " destroy: thread wakeup error = %s\n",
+                                strerror(errno));
+               dapl_os_sleep_usec(1000);
+       }
+
+out:
+       if (hca_ptr->ib_trans.ib_cq)
+               ibv_destroy_comp_channel(hca_ptr->ib_trans.ib_cq);
+
+       if (hca_ptr->ib_trans.ib_cq_empty) {
+               struct ibv_comp_channel *channel;
+               channel = hca_ptr->ib_trans.ib_cq_empty->channel;
+               ibv_destroy_cq(hca_ptr->ib_trans.ib_cq_empty);
+               ibv_destroy_comp_channel(channel);
+       }
+
+       if (hca_ptr->ib_hca_handle != IB_INVALID_HANDLE) {
+               if (ibv_close_device(hca_ptr->ib_hca_handle))
+                       return (dapl_convert_errno(errno, "ib_close_device"));
+               hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;
+       }
+       return (DAT_SUCCESS);
+}
+
+DAT_RETURN dapli_ib_thread_init(void)
+{
+       DAT_RETURN dat_status;
+
+       dapl_os_lock(&g_hca_lock);
+       if (g_ib_thread_state != IB_THREAD_INIT) {
+               dapl_os_unlock(&g_hca_lock);
+               return DAT_SUCCESS;
+       }
+
+       g_ib_thread_state = IB_THREAD_CREATE;
+       dapl_os_unlock(&g_hca_lock);
+
+       /* create thread to process inbound connect request */
+       dat_status = dapl_os_thread_create(dapli_thread, NULL, &g_ib_thread);
+       if (dat_status != DAT_SUCCESS)
+               return (dapl_convert_errno(errno,
+                                          "create_thread ERR:"
+                                          " check resource limits"));
+
+       /* wait for thread to start */
+       dapl_os_lock(&g_hca_lock);
+       while (g_ib_thread_state != IB_THREAD_RUN) {
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread_init: waiting for ib_thread\n");
+               dapl_os_unlock(&g_hca_lock);
+               dapl_os_sleep_usec(1000);
+               dapl_os_lock(&g_hca_lock);
+       }
+       dapl_os_unlock(&g_hca_lock);
+
+       return DAT_SUCCESS;
+}
+
+void dapli_ib_thread_destroy(void)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " ib_thread_destroy(%d)\n", dapl_os_getpid());
+       /* 
+        * wait for async thread to terminate. 
+        * pthread_join would be the correct method
+        * but some applications have some issues
+        */
+
+       /* destroy ib_thread, wait for termination, if not already */
+       dapl_os_lock(&g_hca_lock);
+       if (g_ib_thread_state != IB_THREAD_RUN)
+               goto bail;
+
+       g_ib_thread_state = IB_THREAD_CANCEL;
+       while (g_ib_thread_state != IB_THREAD_EXIT) {
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread_destroy: waiting for ib_thread\n");
+               if (dapls_thread_signal() == -1)
+                       dapl_log(DAPL_DBG_TYPE_UTIL,
+                                " destroy: thread wakeup error = %s\n",
+                                strerror(errno));
+               dapl_os_unlock(&g_hca_lock);
+               dapl_os_sleep_usec(2000);
+               dapl_os_lock(&g_hca_lock);
+       }
+bail:
+       dapl_os_unlock(&g_hca_lock);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                    " ib_thread_destroy(%d) exit\n", dapl_os_getpid());
+}
+
+
+#if defined(_WIN64) || defined(_WIN32)
+/* work thread for uAT, uCM, CQ, and async events */
+void dapli_thread(void *arg)
+{
+       struct _ib_hca_transport *hca;
+       struct _ib_hca_transport *uhca[8];
+       int ret, idx, cnt;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d,0x%x): ENTER: \n",
+                    dapl_os_getpid(), g_ib_thread);
+
+       dapl_os_lock(&g_hca_lock);
+       for (g_ib_thread_state = IB_THREAD_RUN;
+            g_ib_thread_state == IB_THREAD_RUN; 
+            dapl_os_lock(&g_hca_lock)) {
+
+               CompSetZero(&ufds);
+               idx = 0;
+               hca = dapl_llist_is_empty(&g_hca_list) ? NULL :
+                     dapl_llist_peek_head(&g_hca_list);
+
+               while (hca) {
+                       CompSetAdd(&hca->ib_ctx->channel, &ufds);
+                       CompSetAdd(&hca->ib_cq->comp_channel, &ufds);
+                       uhca[idx++] = hca;
+                       hca = dapl_llist_next_entry(&g_hca_list,
+                                                   (DAPL_LLIST_ENTRY *)
+                                                   &hca->entry);
+               }
+               cnt = idx;
+
+               dapl_os_unlock(&g_hca_lock);
+               ret = CompSetPoll(&ufds, INFINITE);
+
+               dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
+                            " ib_thread(%d) poll_event 0x%x\n",
+                            dapl_os_getpid(), ret);
+
+
+               /* check and process ASYNC events, per device */
+               for (idx = 0; idx < cnt; idx++) {
+                       if (uhca[idx]->destroy == 1) {
+                               dapl_os_lock(&g_hca_lock);
+                               dapl_llist_remove_entry(&g_hca_list,
+                                                       (DAPL_LLIST_ENTRY *)
+                                                       &uhca[idx]->entry);
+                               dapl_os_unlock(&g_hca_lock);
+                               uhca[idx]->destroy = 2;
+                       } else {
+                               dapli_cq_event_cb(uhca[idx]);
+                               dapli_async_event_cb(uhca[idx]);
+                       }
+               }
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d) EXIT\n",
+                    dapl_os_getpid());
+       g_ib_thread_state = IB_THREAD_EXIT;
+       dapl_os_unlock(&g_hca_lock);
+}
+#else                          // _WIN64 || WIN32
+
+/* work thread for uAT, uCM, CQ, and async events */
+void dapli_thread(void *arg)
+{
+       struct pollfd ufds[__FD_SETSIZE];
+       struct _ib_hca_transport *uhca[__FD_SETSIZE] = { NULL };
+       struct _ib_hca_transport *hca;
+       int ret, idx, fds;
+       char rbuf[2];
+
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                    " ib_thread(%d,0x%x): ENTER: pipe %d \n",
+                    dapl_os_getpid(), g_ib_thread, g_ib_pipe[0]);
+
+       /* Poll across pipe, CM, AT never changes */
+       dapl_os_lock(&g_hca_lock);
+       g_ib_thread_state = IB_THREAD_RUN;
+
+       ufds[0].fd = g_ib_pipe[0];      /* pipe */
+       ufds[0].events = POLLIN;
+
+       while (g_ib_thread_state == IB_THREAD_RUN) {
+
+               /* build ufds after pipe and uCMA events */
+               ufds[0].revents = 0;
+               idx = 0;
+
+               /*  Walk HCA list and setup async and CQ events */
+               if (!dapl_llist_is_empty(&g_hca_list))
+                       hca = dapl_llist_peek_head(&g_hca_list);
+               else
+                       hca = NULL;
+
+               while (hca) {
+
+                       /* uASYNC events */
+                       ufds[++idx].fd = hca->ib_ctx->async_fd;
+                       ufds[idx].events = POLLIN;
+                       ufds[idx].revents = 0;
+                       uhca[idx] = hca;
+
+                       /* CQ events are non-direct with CNO's */
+                       ufds[++idx].fd = hca->ib_cq->fd;
+                       ufds[idx].events = POLLIN;
+                       ufds[idx].revents = 0;
+                       uhca[idx] = hca;
+
+                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                                    " ib_thread(%d) poll_fd: hca[%d]=%p,"
+                                    " async=%d pipe=%d \n",
+                                    dapl_os_getpid(), hca, ufds[idx - 1].fd,
+                                    ufds[0].fd);
+
+                       hca = dapl_llist_next_entry(&g_hca_list,
+                                                   (DAPL_LLIST_ENTRY *)
+                                                   &hca->entry);
+               }
+
+               /* unlock, and setup poll */
+               fds = idx + 1;
+               dapl_os_unlock(&g_hca_lock);
+               ret = poll(ufds, fds, -1);
+               if (ret <= 0) {
+                       dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                                    " ib_thread(%d): ERR %s poll\n",
+                                    dapl_os_getpid(), strerror(errno));
+                       dapl_os_lock(&g_hca_lock);
+                       continue;
+               }
+
+               dapl_dbg_log(DAPL_DBG_TYPE_THREAD,
+                            " ib_thread(%d) poll_event: "
+                            " async=0x%x pipe=0x%x \n",
+                            dapl_os_getpid(), ufds[idx].revents,
+                            ufds[0].revents);
+
+               /* check and process CQ and ASYNC events, per device */
+               for (idx = 1; idx < fds; idx++) {
+                       if (ufds[idx].revents == POLLIN) {
+                               dapli_cq_event_cb(uhca[idx]);
+                               dapli_async_event_cb(uhca[idx]);
+                       }
+               }
+
+               /* check and process user events, PIPE */
+               if (ufds[0].revents == POLLIN) {
+                       if (read(g_ib_pipe[0], rbuf, 2) == -1)
+                               dapl_log(DAPL_DBG_TYPE_THREAD,
+                                        " cr_thread: pipe rd err= %s\n",
+                                        strerror(errno));
+
+                       /* cleanup any device on list marked for destroy */
+                       for (idx = 1; idx < fds; idx++) {
+                               if (uhca[idx] && uhca[idx]->destroy == 1) {
+                                       dapl_os_lock(&g_hca_lock);
+                                       dapl_llist_remove_entry(
+                                               &g_hca_list,
+                                               (DAPL_LLIST_ENTRY*)
+                                               &uhca[idx]->entry);
+                                       dapl_os_unlock(&g_hca_lock);
+                                       uhca[idx]->destroy = 2;
+                               }
+                       }
+               }
+               dapl_os_lock(&g_hca_lock);
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " ib_thread(%d) EXIT\n",
+                    dapl_os_getpid());
+       g_ib_thread_state = IB_THREAD_EXIT;
+       dapl_os_unlock(&g_hca_lock);
+}
+#endif
index 03fc75277bb994be192a2974163d26d428c39232..2cab529359d25e4d18f91562ce2c6a2d6d1dce64 100644 (file)
-/*\r
- * Copyright (c) 2009 Intel Corporation.  All rights reserved.\r
- *\r
- * This Software is licensed under one of the following licenses:\r
- *\r
- * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/cpl.php.\r
- *\r
- * 2) under the terms of the "The BSD License" a copy of which is\r
- *    available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/bsd-license.php.\r
- *\r
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
- *    copy of which is available from the Open Source Initiative, see\r
- *    http://www.opensource.org/licenses/gpl-license.php.\r
- *\r
- * Licensee has the right to choose one of the above licenses.\r
- *\r
- * Redistributions of source code must retain the above copyright\r
- * notice and one of the license notices.\r
- *\r
- * Redistributions in binary form must reproduce both the above copyright\r
- * notice, one of the license notices in the documentation\r
- * and/or other materials provided with the distribution.\r
- */\r
-\r
-#include "dapl.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_cr_util.h"\r
-#include "dapl_name_service.h"\r
-#include "dapl_ib_util.h"\r
-#include "dapl_osd.h"\r
-\r
-\r
-#if defined(_WIN32)\r
-#include <rdma\winverbs.h>\r
-#else                          // _WIN32\r
-enum DAPL_FD_EVENTS {\r
-       DAPL_FD_READ = POLLIN,\r
-       DAPL_FD_WRITE = POLLOUT,\r
-       DAPL_FD_ERROR = POLLERR\r
-};\r
-\r
-struct dapl_fd_set {\r
-       int index;\r
-       struct pollfd set[DAPL_FD_SETSIZE];\r
-};\r
-\r
-static struct dapl_fd_set *dapl_alloc_fd_set(void)\r
-{\r
-       return dapl_os_alloc(sizeof(struct dapl_fd_set));\r
-}\r
-\r
-static void dapl_fd_zero(struct dapl_fd_set *set)\r
-{\r
-       set->index = 0;\r
-}\r
-\r
-static int dapl_fd_set(DAPL_SOCKET s, struct dapl_fd_set *set,\r
-                      enum DAPL_FD_EVENTS event)\r
-{\r
-       if (set->index == DAPL_FD_SETSIZE - 1) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        "SCM ERR: cm_thread exceeded FD_SETSIZE %d\n",\r
-                        set->index + 1);\r
-               return -1;\r
-       }\r
-\r
-       set->set[set->index].fd = s;\r
-       set->set[set->index].revents = 0;\r
-       set->set[set->index++].events = event;\r
-       return 0;\r
-}\r
-\r
-static enum DAPL_FD_EVENTS dapl_poll(DAPL_SOCKET s, enum DAPL_FD_EVENTS event)\r
-{\r
-       struct pollfd fds;\r
-       int ret;\r
-\r
-       fds.fd = s;\r
-       fds.events = event;\r
-       fds.revents = 0;\r
-       ret = poll(&fds, 1, 0);\r
-       dapl_log(DAPL_DBG_TYPE_CM, " dapl_poll: fd=%d ret=%d, evnts=0x%x\n",\r
-                s, ret, fds.revents);\r
-       if (ret == 0)\r
-               return 0;\r
-       else if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) \r
-               return DAPL_FD_ERROR;\r
-       else \r
-               return fds.revents;\r
-}\r
-\r
-static int dapl_select(struct dapl_fd_set *set, int time_ms)\r
-{\r
-       int ret;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: sleep, fds=%d\n",\r
-                    set->index);\r
-       ret = poll(set->set, set->index, time_ms);\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: wakeup, ret=0x%x\n", ret);\r
-       return ret;\r
-}\r
-#endif\r
-\r
-/* forward declarations */\r
-static int ucm_reply(dp_ib_cm_handle_t cm);\r
-static void ucm_accept(ib_cm_srvc_handle_t cm, ib_cm_msg_t *msg);\r
-static void ucm_connect_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg);\r
-static void ucm_accept_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg);\r
-static int ucm_send(ib_hca_transport_t *tp, ib_cm_msg_t *msg, DAT_PVOID p_data, DAT_COUNT p_size);\r
-static void ucm_disconnect_final(dp_ib_cm_handle_t cm);\r
-DAT_RETURN dapli_cm_disconnect(dp_ib_cm_handle_t cm);\r
-DAT_RETURN dapli_cm_connect(DAPL_EP *ep, dp_ib_cm_handle_t cm);\r
-\r
-#define UCM_SND_BURST  50      \r
-\r
-/* Service ids - port space */\r
-static uint16_t ucm_get_port(ib_hca_transport_t *tp, uint16_t port)\r
-{\r
-       int i = 0;\r
-       \r
-       dapl_os_lock(&tp->plock);\r
-       /* get specific ID */\r
-       if (port) {\r
-               if (tp->sid[port] == 0) {\r
-                       tp->sid[port] = 1;\r
-                       i = port;\r
-               }\r
-               goto done;\r
-       } \r
-       \r
-       /* get any free ID */\r
-       for (i = 0xffff; i > 0; i--) {\r
-               if (tp->sid[i] == 0) {\r
-                       tp->sid[i] = 1;\r
-                       break;\r
-               }\r
-       }\r
-done:\r
-       dapl_os_unlock(&tp->plock);\r
-       return i;\r
-}\r
-\r
-static void ucm_free_port(ib_hca_transport_t *tp, uint16_t port)\r
-{\r
-       dapl_os_lock(&tp->plock);\r
-       tp->sid[port] = 0;\r
-       dapl_os_unlock(&tp->plock);\r
-}\r
-\r
-static void ucm_check_timers(dp_ib_cm_handle_t cm, int *timer)\r
-{\r
-       DAPL_OS_TIMEVAL time;\r
-\r
-        dapl_os_lock(&cm->lock);\r
-       dapl_os_get_time(&time); \r
-       switch (cm->state) {\r
-       case DCM_REP_PENDING: \r
-               *timer = cm->hca->ib_trans.cm_timer; \r
-               /* wait longer each retry */\r
-               if ((time - cm->timer)/1000 > \r
-                   (cm->hca->ib_trans.rep_time << cm->retries)) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                " CM_REQ retry %d [lid, port, qpn]:"\r
-                                " %x %x %x -> %x %x %x Time(ms) %llu > %llu\n", \r
-                                cm->retries, ntohs(cm->msg.saddr.ib.lid), \r
-                                ntohs(cm->msg.sport), ntohl(cm->msg.saddr.ib.qpn), \r
-                                ntohs(cm->msg.daddr.ib.lid), ntohs(cm->msg.dport),\r
-                                ntohl(cm->msg.dqpn), (time - cm->timer)/1000, \r
-                                cm->hca->ib_trans.rep_time << cm->retries);\r
-                       cm->retries++;\r
-                       dapl_os_unlock(&cm->lock);\r
-                       dapli_cm_connect(cm->ep, cm);\r
-                       return;\r
-               }\r
-               break;\r
-       case DCM_RTU_PENDING: \r
-               *timer = cm->hca->ib_trans.cm_timer;  \r
-               if ((time - cm->timer)/1000 > \r
-                   (cm->hca->ib_trans.rtu_time << cm->retries)) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                " CM_REPLY retry %d [lid, port, qpn]:"\r
-                                " %x %x %x -> %x %x %x r_pid %x,%d Time(ms) %llu > %llu\n", \r
-                                cm->retries,\r
-                                ntohs(cm->msg.saddr.ib.lid), \r
-                                ntohs(cm->msg.sport),\r
-                                ntohl(cm->msg.saddr.ib.qpn), \r
-                                ntohs(cm->msg.daddr.ib.lid), \r
-                                ntohs(cm->msg.dport),\r
-                                ntohl(cm->msg.daddr.ib.qpn),  \r
-                                ntohl(*(DAT_UINT32*)cm->msg.resv),\r
-                                ntohl(*(DAT_UINT32*)cm->msg.resv), \r
-                                (time - cm->timer)/1000, cm->hca->ib_trans.rtu_time << cm->retries);\r
-                       cm->retries++;\r
-                       dapl_os_unlock(&cm->lock);\r
-                       ucm_reply(cm);\r
-                       return;\r
-               }\r
-               break;\r
-       case DCM_DISC_PENDING: \r
-               *timer = cm->hca->ib_trans.cm_timer; \r
-               /* wait longer each retry */\r
-               if ((time - cm->timer)/1000 > \r
-                   (cm->hca->ib_trans.rtu_time << cm->retries)) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                " CM_DREQ retry %d [lid, port, qpn]:"\r
-                                " %x %x %x -> %x %x %x r_pid %x,%d Time(ms) %llu > %llu\n", \r
-                                cm->retries,\r
-                                ntohs(cm->msg.saddr.ib.lid), \r
-                                ntohs(cm->msg.sport),\r
-                                ntohl(cm->msg.saddr.ib.qpn), \r
-                                ntohs(cm->msg.daddr.ib.lid), \r
-                                ntohs(cm->msg.dport),\r
-                                ntohl(cm->msg.dqpn), \r
-                                ntohl(*(DAT_UINT32*)cm->msg.resv),\r
-                                ntohl(*(DAT_UINT32*)cm->msg.resv), \r
-                                (time - cm->timer)/1000, cm->hca->ib_trans.rtu_time << cm->retries);\r
-                       cm->retries++;\r
-                       dapl_os_unlock(&cm->lock);\r
-                       dapli_cm_disconnect(cm);\r
-                        return;\r
-               }\r
-               break;\r
-       default:\r
-               break;\r
-       }\r
-       dapl_os_unlock(&cm->lock);\r
-}\r
-\r
-/* SEND CM MESSAGE PROCESSING */\r
-\r
-/* Get CM UD message from send queue, called with s_lock held */\r
-static ib_cm_msg_t *ucm_get_smsg(ib_hca_transport_t *tp)\r
-{\r
-       ib_cm_msg_t *msg = NULL; \r
-       int ret, polled = 0, hd = tp->s_hd;\r
-\r
-       hd++;\r
-retry:\r
-       if (hd == tp->qpe)\r
-               hd = 0;\r
-\r
-       if (hd == tp->s_tl)\r
-               msg = NULL;\r
-       else {\r
-               msg = &tp->sbuf[hd];\r
-               tp->s_hd = hd; /* new hd */\r
-       }\r
-\r
-       /* if empty, process some completions */\r
-       if ((msg == NULL) && (!polled)) {\r
-               struct ibv_wc wc;\r
-\r
-               /* process completions, based on UCM_SND_BURST */\r
-               ret = ibv_poll_cq(tp->scq, 1, &wc);\r
-               if (ret < 0) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                               " get_smsg: cq %p %s\n", \r
-                               tp->scq, strerror(errno));\r
-               }\r
-               /* free up completed sends, update tail */\r
-               if (ret > 0) {\r
-                       tp->s_tl = (int)wc.wr_id;\r
-                       dapl_log(DAPL_DBG_TYPE_CM,\r
-                               " get_smsg: wr_cmp (%d) s_tl=%d\n", \r
-                               wc.status, tp->s_tl);\r
-               }\r
-               polled++;\r
-               goto retry;\r
-       }\r
-       return msg;\r
-}\r
-\r
-/* RECEIVE CM MESSAGE PROCESSING */\r
-\r
-static int ucm_post_rmsg(ib_hca_transport_t *tp, ib_cm_msg_t *msg)\r
-{      \r
-       struct ibv_recv_wr recv_wr, *recv_err;\r
-       struct ibv_sge sge;\r
-        \r
-       recv_wr.next = NULL;\r
-       recv_wr.sg_list = &sge;\r
-       recv_wr.num_sge = 1;\r
-       recv_wr.wr_id = (uint64_t)(uintptr_t) msg;\r
-       sge.length = sizeof(ib_cm_msg_t) + sizeof(struct ibv_grh);\r
-       sge.lkey = tp->mr_rbuf->lkey;\r
-       sge.addr = (uintptr_t)((char *)msg - sizeof(struct ibv_grh));\r
-       \r
-       return (ibv_post_recv(tp->qp, &recv_wr, &recv_err));\r
-}\r
-\r
-static int ucm_reject(ib_hca_transport_t *tp, ib_cm_msg_t *msg)\r
-{\r
-       ib_cm_msg_t     smsg;\r
-\r
-       /* setup op, rearrange the src, dst cm and addr info */\r
-       (void)dapl_os_memzero(&smsg, sizeof(smsg));\r
-       smsg.ver = htons(DCM_VER);\r
-       smsg.op = htons(DCM_REJ_CM);\r
-       smsg.dport = msg->sport;\r
-       smsg.dqpn = msg->sqpn;\r
-       smsg.sport = msg->dport; \r
-       smsg.sqpn = msg->dqpn;\r
-\r
-       dapl_os_memcpy(&smsg.daddr, &msg->saddr, sizeof(union dcm_addr));\r
-       \r
-       /* no dst_addr IB info in REQ, init lid, gid, get type from saddr */\r
-       smsg.saddr.ib.lid = tp->addr.ib.lid; \r
-       smsg.saddr.ib.qp_type = msg->saddr.ib.qp_type;\r
-       dapl_os_memcpy(&smsg.saddr.ib.gid[0],\r
-                      &tp->addr.ib.gid, 16); \r
-\r
-       dapl_os_memcpy(&smsg.saddr, &msg->daddr, sizeof(union dcm_addr));\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, \r
-                    " CM reject -> LID %x, QPN %x PORT %d\n", \r
-                    ntohs(smsg.daddr.ib.lid),\r
-                    ntohl(smsg.dqpn), ntohs(smsg.dport));\r
-\r
-       return (ucm_send(tp, &smsg, NULL, 0));\r
-}\r
-\r
-static void ucm_process_recv(ib_hca_transport_t *tp, \r
-                            ib_cm_msg_t *msg, \r
-                            dp_ib_cm_handle_t cm)\r
-{\r
-       dapl_os_lock(&cm->lock);\r
-       switch (cm->state) {\r
-       case DCM_LISTEN: /* passive */\r
-               dapl_os_unlock(&cm->lock);\r
-               ucm_accept(cm, msg);\r
-               break;\r
-       case DCM_RTU_PENDING: /* passive */\r
-               dapl_os_unlock(&cm->lock);\r
-               ucm_accept_rtu(cm, msg);\r
-               break;\r
-       case DCM_REP_PENDING: /* active */\r
-               dapl_os_unlock(&cm->lock);\r
-               ucm_connect_rtu(cm, msg);\r
-               break;\r
-       case DCM_CONNECTED: /* active and passive */\r
-               /* DREQ, change state and process */\r
-               if (ntohs(msg->op) == DCM_DREQ) {\r
-                       cm->state = DCM_DISC_RECV;\r
-                       dapl_os_unlock(&cm->lock);\r
-                       dapli_cm_disconnect(cm);\r
-                       break;\r
-               } \r
-               /* active: RTU was dropped, resend */\r
-               if (ntohs(msg->op) == DCM_REP) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                               " RESEND RTU: op %s st %s [lid, port, qpn]:"\r
-                               " 0x%x %d 0x%x -> 0x%x %d 0x%x\n", \r
-                               dapl_cm_op_str(ntohs(msg->op)), \r
-                               dapl_cm_state_str(cm->state),\r
-                               ntohs(msg->saddr.ib.lid), \r
-                               ntohs(msg->sport),\r
-                               ntohl(msg->saddr.ib.qpn), \r
-                               ntohs(msg->daddr.ib.lid), \r
-                               ntohs(msg->dport),\r
-                               ntohl(msg->daddr.ib.qpn));  \r
-\r
-                       cm->msg.op = htons(DCM_RTU);\r
-                       ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0);                \r
-               }\r
-               dapl_os_unlock(&cm->lock);\r
-               break;\r
-       case DCM_DISC_PENDING: /* active and passive */\r
-               /* DREQ or DREP, finalize */\r
-               dapl_os_unlock(&cm->lock);\r
-               ucm_disconnect_final(cm);\r
-               break;\r
-       case DCM_DISCONNECTED:\r
-       case DCM_DESTROY:\r
-               /* DREQ dropped, resend */\r
-               if (ntohs(msg->op) == DCM_DREQ) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                               " RESEND DREP: op %s st %s [lid, port, qpn]:"\r
-                               " 0x%x %d 0x%x -> 0x%x %d 0x%x\n", \r
-                               dapl_cm_op_str(ntohs(msg->op)), \r
-                               dapl_cm_state_str(cm->state),\r
-                               ntohs(msg->saddr.ib.lid), \r
-                               ntohs(msg->sport),\r
-                               ntohl(msg->saddr.ib.qpn), \r
-                               ntohs(msg->daddr.ib.lid), \r
-                               ntohs(msg->dport),\r
-                               ntohl(msg->daddr.ib.qpn));  \r
-                       cm->msg.op = htons(DCM_DREP);\r
-                       ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0); \r
-                       \r
-               }\r
-               dapl_os_unlock(&cm->lock);\r
-               break;\r
-       case DCM_RELEASED:\r
-               /* UD reply retried, ignore */\r
-               if (ntohs(msg->op) != DCM_REP) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                               " ucm_recv: UNKNOWN operation"\r
-                               " <- op %d, %s spsp %d sqpn %d\n", \r
-                               ntohs(msg->op), dapl_cm_state_str(cm->state),\r
-                               ntohs(msg->sport), ntohl(msg->sqpn));\r
-               }\r
-               dapl_os_unlock(&cm->lock);\r
-               break;\r
-       default:\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                               " ucm_recv: UNKNOWN state"\r
-                               " <- op %d, %s spsp %d sqpn %d\n", \r
-                               ntohs(msg->op), dapl_cm_state_str(cm->state), \r
-                               ntohs(msg->sport), ntohl(msg->sqpn));\r
-               dapl_os_unlock(&cm->lock);\r
-               break;\r
-       }\r
-}\r
-\r
-/* Find matching CM object for this receive message, return CM reference, timer */\r
-dp_ib_cm_handle_t ucm_cm_find(ib_hca_transport_t *tp, ib_cm_msg_t *msg)\r
-{\r
-       dp_ib_cm_handle_t cm, next, found = NULL;\r
-       struct dapl_llist_entry **list;\r
-       DAPL_OS_LOCK *lock;\r
-       int listenq = 0;\r
-\r
-       /* conn list first, duplicate requests for DCM_REQ */\r
-       list = &tp->list;\r
-       lock = &tp->lock;\r
-\r
-retry_listenq:\r
-       dapl_os_lock(lock);\r
-        if (!dapl_llist_is_empty(list))\r
-               next = dapl_llist_peek_head(list);\r
-       else\r
-               next = NULL;\r
-\r
-       while (next) {\r
-               cm = next;\r
-               next = dapl_llist_next_entry(list,\r
-                                            (DAPL_LLIST_ENTRY *)&cm->entry);\r
-               if (cm->state == DCM_DESTROY)\r
-                       continue;\r
-               \r
-               /* CM sPORT + QPN, match is good enough for listenq */\r
-               if (listenq && \r
-                   cm->msg.sport == msg->dport && \r
-                   cm->msg.sqpn == msg->dqpn) {\r
-                       found = cm;\r
-                       break;\r
-               }        \r
-               /* connectq, check src and dst, check duplicate conn_reqs */\r
-               if (!listenq && \r
-                   cm->msg.sport == msg->dport && cm->msg.sqpn == msg->dqpn && \r
-                   cm->msg.dport == msg->sport && cm->msg.dqpn == msg->sqpn && \r
-                   cm->msg.daddr.ib.lid == msg->saddr.ib.lid) {\r
-                       if (ntohs(msg->op) != DCM_REQ) {\r
-                               found = cm;\r
-                               break; \r
-                       } else {\r
-                               /* duplicate; bail and throw away */\r
-                               dapl_os_unlock(lock);\r
-                               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                        " DUPLICATE: op %s st %s [lid, port, qpn]:"\r
-                                        " 0x%x %d 0x%x <- 0x%x %d 0x%x\n", \r
-                                        dapl_cm_op_str(ntohs(msg->op)), \r
-                                        dapl_cm_state_str(cm->state),\r
-                                        ntohs(msg->daddr.ib.lid), \r
-                                        ntohs(msg->dport),\r
-                                        ntohl(msg->daddr.ib.qpn), \r
-                                        ntohs(msg->saddr.ib.lid), \r
-                                        ntohs(msg->sport),\r
-                                        ntohl(msg->saddr.ib.qpn));  \r
-                               return NULL;\r
-                       }\r
-               }\r
-       }\r
-       dapl_os_unlock(lock);\r
-\r
-       /* no duplicate request on connq, check listenq for new request */\r
-       if (ntohs(msg->op) == DCM_REQ && !listenq && !found) {\r
-               listenq = 1;\r
-               list = &tp->llist;\r
-               lock = &tp->llock;\r
-               goto retry_listenq;\r
-       }\r
-\r
-       /* not match on listenq for valid request, send reject */\r
-       if (ntohs(msg->op) == DCM_REQ && !found)\r
-               ucm_reject(tp, msg);\r
-\r
-       if (!found) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                       " ucm_recv: NO MATCH op %s 0x%x %d i0x%x c0x%x"\r
-                       " < 0x%x %d 0x%x\n", \r
-                       dapl_cm_op_str(ntohs(msg->op)), \r
-                       ntohs(msg->daddr.ib.lid), ntohs(msg->dport), \r
-                       ntohl(msg->daddr.ib.qpn), ntohl(msg->sqpn),\r
-                       ntohs(msg->saddr.ib.lid), ntohs(msg->sport), \r
-                       ntohl(msg->saddr.ib.qpn));\r
-       }\r
-\r
-       return found;\r
-}\r
-\r
-/* Get rmsgs from CM completion queue, 10 at a time */\r
-static void ucm_recv(ib_hca_transport_t *tp)\r
-{\r
-       struct ibv_wc wc[10];\r
-       ib_cm_msg_t *msg;\r
-       dp_ib_cm_handle_t cm;\r
-       int i, ret, notify = 0;\r
-       struct ibv_cq *ibv_cq = NULL;\r
-       DAPL_HCA *hca;\r
-\r
-       /* POLLIN on channel FD */\r
-       ret = ibv_get_cq_event(tp->rch, &ibv_cq, (void *)&hca);\r
-       if (ret == 0) {\r
-               ibv_ack_cq_events(ibv_cq, 1);\r
-       }\r
-retry: \r
-       ret = ibv_poll_cq(tp->rcq, 10, wc);\r
-       if (ret <= 0) {\r
-               if (!ret && !notify) {\r
-                       ibv_req_notify_cq(tp->rcq, 0);\r
-                       notify = 1;\r
-                       goto retry;\r
-               }\r
-               return;\r
-       } else \r
-               notify = 0;\r
-       \r
-       for (i = 0; i < ret; i++) {\r
-               msg = (ib_cm_msg_t*) (uintptr_t) wc[i].wr_id;\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_CM, \r
-                            " ucm_recv: wc status=%d, ln=%d id=%p sqp=%x\n", \r
-                            wc[i].status, wc[i].byte_len, \r
-                            (void*)wc[i].wr_id, wc[i].src_qp);\r
-\r
-               /* validate CM message, version */\r
-               if (ntohs(msg->ver) != DCM_VER) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN,\r
-                                " ucm_recv: UNKNOWN msg %p, ver %d\n", \r
-                                msg, msg->ver);\r
-                       ucm_post_rmsg(tp, msg);\r
-                       continue;\r
-               }\r
-               if (!(cm = ucm_cm_find(tp, msg))) {\r
-                       ucm_post_rmsg(tp, msg);\r
-                       continue;\r
-               }\r
-               \r
-               /* match, process it */\r
-               ucm_process_recv(tp, msg, cm);\r
-               ucm_post_rmsg(tp, msg);\r
-       }\r
-       \r
-       /* finished this batch of WC's, poll and rearm */\r
-       goto retry;\r
-}\r
-\r
-/* ACTIVE/PASSIVE: build and send CM message out of CM object */\r
-static int ucm_send(ib_hca_transport_t *tp, ib_cm_msg_t *msg, DAT_PVOID p_data, DAT_COUNT p_size)\r
-{\r
-       ib_cm_msg_t *smsg = NULL;\r
-       struct ibv_send_wr wr, *bad_wr;\r
-       struct ibv_sge sge;\r
-       int len, ret = -1;\r
-       uint16_t dlid = ntohs(msg->daddr.ib.lid);\r
-\r
-       /* Get message from send queue, copy data, and send */\r
-       dapl_os_lock(&tp->slock);\r
-       if ((smsg = ucm_get_smsg(tp)) == NULL)\r
-               goto bail;\r
-\r
-       len = (sizeof(*msg) - DCM_MAX_PDATA_SIZE);\r
-       dapl_os_memcpy(smsg, msg, len);\r
-       if (p_size) {\r
-               smsg->p_size = ntohs(p_size);\r
-               dapl_os_memcpy(&smsg->p_data, p_data, p_size);\r
-       }\r
-\r
-       wr.next = NULL;\r
-        wr.sg_list = &sge;\r
-        wr.num_sge = 1;\r
-        wr.opcode = IBV_WR_SEND;\r
-        wr.wr_id = (unsigned long)tp->s_hd;\r
-       wr.send_flags = (wr.wr_id % UCM_SND_BURST) ? 0 : IBV_SEND_SIGNALED;\r
-       if (len <= tp->max_inline_send)\r
-               wr.send_flags |= IBV_SEND_INLINE; \r
-\r
-        sge.length = len + p_size;\r
-        sge.lkey = tp->mr_sbuf->lkey;\r
-        sge.addr = (uintptr_t)smsg;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, \r
-               " ucm_send: op %d ln %d lid %x c_qpn %x rport %d\n", \r
-               ntohs(smsg->op), sge.length, htons(smsg->daddr.ib.lid), \r
-               htonl(smsg->dqpn), htons(smsg->dport));\r
-\r
-       /* empty slot, then create AH */\r
-       if (!tp->ah[dlid]) {\r
-               tp->ah[dlid] =  \r
-                       dapls_create_ah(tp->hca, tp->pd, tp->qp, \r
-                                       htons(dlid), NULL);\r
-               if (!tp->ah[dlid])\r
-                       goto bail;\r
-       }\r
-               \r
-       wr.wr.ud.ah = tp->ah[dlid];\r
-       wr.wr.ud.remote_qpn = ntohl(smsg->dqpn);\r
-       wr.wr.ud.remote_qkey = DAT_UD_QKEY;\r
-\r
-       ret = ibv_post_send(tp->qp, &wr, &bad_wr);\r
-bail:\r
-       dapl_os_unlock(&tp->slock);     \r
-       return ret;\r
-}\r
-\r
-/* ACTIVE/PASSIVE: CM objects */\r
-dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep)\r
-{\r
-       dp_ib_cm_handle_t cm;\r
-\r
-       /* Allocate CM, init lock, and initialize */\r
-       if ((cm = dapl_os_alloc(sizeof(*cm))) == NULL)\r
-               return NULL;\r
-\r
-       (void)dapl_os_memzero(cm, sizeof(*cm));\r
-       if (dapl_os_lock_init(&cm->lock))\r
-               goto bail;\r
-\r
-       cm->msg.ver = htons(DCM_VER);\r
-       *(DAT_UINT32*)cm->msg.resv = htonl(dapl_os_getpid()); /* exchange PID for debugging */\r
-       \r
-       /* ACTIVE: init source address QP info from local EP */\r
-       if (ep) {\r
-               DAPL_HCA *hca = ep->header.owner_ia->hca_ptr;\r
-\r
-               cm->msg.sport = htons(ucm_get_port(&hca->ib_trans, 0));\r
-               if (!cm->msg.sport) \r
-                       goto bail;\r
-\r
-               /* IB info in network order */\r
-               cm->ep = ep;\r
-               cm->hca = hca;\r
-               cm->msg.sqpn = htonl(hca->ib_trans.qp->qp_num); /* ucm */\r
-               cm->msg.saddr.ib.qpn = htonl(ep->qp_handle->qp_num); /* ep */\r
-               cm->msg.saddr.ib.qp_type = ep->qp_handle->qp_type;\r
-                cm->msg.saddr.ib.lid = hca->ib_trans.addr.ib.lid; \r
-               dapl_os_memcpy(&cm->msg.saddr.ib.gid[0], \r
-                              &hca->ib_trans.addr.ib.gid, 16);\r
-        }\r
-       return cm;\r
-bail:\r
-       dapl_os_free(cm, sizeof(*cm));\r
-       return NULL;\r
-}\r
-\r
-/* \r
- * UD CR objects are kept active because of direct private data references\r
- * from CONN events. The cr->socket is closed and marked inactive but the \r
- * object remains allocated and queued on the CR resource list. There can\r
- * be multiple CR's associated with a given EP. There is no way to determine \r
- * when consumer is finished with event until the dat_ep_free.\r
- *\r
- * Schedule destruction for all CR's associated with this EP, cr_thread will\r
- * complete the cleanup with state == DCM_DESTROY. \r
- */ \r
-static void ucm_ud_free(DAPL_EP *ep)\r
-{\r
-       DAPL_IA *ia = ep->header.owner_ia;\r
-       DAPL_HCA *hca = NULL;\r
-       ib_hca_transport_t *tp = &ia->hca_ptr->ib_trans;\r
-       dp_ib_cm_handle_t cm, next;\r
-\r
-       dapl_os_lock(&tp->lock);\r
-       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)&tp->list))\r
-            next = dapl_llist_peek_head((DAPL_LLIST_HEAD*)&tp->list);\r
-       else\r
-           next = NULL;\r
-\r
-       while (next) {\r
-               cm = next;\r
-               next = dapl_llist_next_entry((DAPL_LLIST_HEAD*)&tp->list,\r
-                                            (DAPL_LLIST_ENTRY*)&cm->entry);\r
-               if (cm->ep == ep)  {\r
-                       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                                    " qp_free CM: ep %p cm %p\n", ep, cm);\r
-                       dapl_os_lock(&cm->lock);\r
-                       hca = cm->hca;\r
-                       cm->ep = NULL;\r
-                       if (cm->ah) {\r
-                               ibv_destroy_ah(cm->ah);\r
-                               cm->ah = NULL;\r
-                       }\r
-                       cm->state = DCM_DESTROY;\r
-                       dapl_os_unlock(&cm->lock);\r
-               }\r
-       }\r
-       dapl_os_unlock(&tp->lock);\r
-\r
-       /* wakeup work thread if necessary */\r
-       if (hca)\r
-               dapls_thread_signal(&tp->signal);\r
-}\r
-\r
-/* mark for destroy, remove all references, schedule cleanup */\r
-/* cm_ptr == NULL (UD), then multi CR's, kill all associated with EP */\r
-void dapls_ib_cm_free(dp_ib_cm_handle_t cm, DAPL_EP *ep)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " cm_destroy: %s cm %p ep %p\n",\r
-                    cm ? dapl_cm_state_str(cm->state) : "", cm, ep);\r
-\r
-       if (!cm && ep) {\r
-               ucm_ud_free(ep);\r
+/*
+ * Copyright (c) 2009 Intel Corporation.  All rights reserved.
+ *
+ * This Software is licensed under one of the following licenses:
+ *
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/cpl.php.
+ *
+ * 2) under the terms of the "The BSD License" a copy of which is
+ *    available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/bsd-license.php.
+ *
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
+ *    copy of which is available from the Open Source Initiative, see
+ *    http://www.opensource.org/licenses/gpl-license.php.
+ *
+ * Licensee has the right to choose one of the above licenses.
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice and one of the license notices.
+ *
+ * Redistributions in binary form must reproduce both the above copyright
+ * notice, one of the license notices in the documentation
+ * and/or other materials provided with the distribution.
+ */
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_cr_util.h"
+#include "dapl_name_service.h"
+#include "dapl_ib_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_osd.h"
+
+
+#if defined(_WIN32)
+#include <rdma\winverbs.h>
+#else                          // _WIN32
+enum DAPL_FD_EVENTS {
+       DAPL_FD_READ = POLLIN,
+       DAPL_FD_WRITE = POLLOUT,
+       DAPL_FD_ERROR = POLLERR
+};
+
+struct dapl_fd_set {
+       int index;
+       struct pollfd set[DAPL_FD_SETSIZE];
+};
+
+static struct dapl_fd_set *dapl_alloc_fd_set(void)
+{
+       return dapl_os_alloc(sizeof(struct dapl_fd_set));
+}
+
+static void dapl_fd_zero(struct dapl_fd_set *set)
+{
+       set->index = 0;
+}
+
+static int dapl_fd_set(DAPL_SOCKET s, struct dapl_fd_set *set,
+                      enum DAPL_FD_EVENTS event)
+{
+       if (set->index == DAPL_FD_SETSIZE - 1) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        "SCM ERR: cm_thread exceeded FD_SETSIZE %d\n",
+                        set->index + 1);
+               return -1;
+       }
+
+       set->set[set->index].fd = s;
+       set->set[set->index].revents = 0;
+       set->set[set->index++].events = event;
+       return 0;
+}
+
+static enum DAPL_FD_EVENTS dapl_poll(DAPL_SOCKET s, enum DAPL_FD_EVENTS event)
+{
+       struct pollfd fds;
+       int ret;
+
+       fds.fd = s;
+       fds.events = event;
+       fds.revents = 0;
+       ret = poll(&fds, 1, 0);
+       dapl_log(DAPL_DBG_TYPE_CM, " dapl_poll: fd=%d ret=%d, evnts=0x%x\n",
+                s, ret, fds.revents);
+       if (ret == 0)
+               return 0;
+       else if (fds.revents & (POLLERR | POLLHUP | POLLNVAL)) 
+               return DAPL_FD_ERROR;
+       else 
+               return fds.revents;
+}
+
+static int dapl_select(struct dapl_fd_set *set, int time_ms)
+{
+       int ret;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: sleep, fds=%d\n",
+                    set->index);
+       ret = poll(set->set, set->index, time_ms);
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, " dapl_select: wakeup, ret=0x%x\n", ret);
+       return ret;
+}
+#endif
+
+/* forward declarations */
+static int ucm_reply(dp_ib_cm_handle_t cm);
+static void ucm_accept(ib_cm_srvc_handle_t cm, ib_cm_msg_t *msg);
+static void ucm_connect_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg);
+static void ucm_accept_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg);
+static int ucm_send(ib_hca_transport_t *tp, ib_cm_msg_t *msg, DAT_PVOID p_data, DAT_COUNT p_size);
+static void ucm_disconnect_final(dp_ib_cm_handle_t cm);
+DAT_RETURN dapli_cm_disconnect(dp_ib_cm_handle_t cm);
+DAT_RETURN dapli_cm_connect(DAPL_EP *ep, dp_ib_cm_handle_t cm);
+
+#define UCM_SND_BURST  50      
+
+/* Service ids - port space */
+static uint16_t ucm_get_port(ib_hca_transport_t *tp, uint16_t port)
+{
+       int i = 0;
+       
+       dapl_os_lock(&tp->plock);
+       /* get specific ID */
+       if (port) {
+               if (tp->sid[port] == 0) {
+                       tp->sid[port] = 1;
+                       i = port;
+               }
+               goto done;
+       } 
+       
+       /* get any free ID */
+       for (i = 0xffff; i > 0; i--) {
+               if (tp->sid[i] == 0) {
+                       tp->sid[i] = 1;
+                       break;
+               }
+       }
+done:
+       dapl_os_unlock(&tp->plock);
+       return i;
+}
+
+static void ucm_free_port(ib_hca_transport_t *tp, uint16_t port)
+{
+       dapl_os_lock(&tp->plock);
+       tp->sid[port] = 0;
+       dapl_os_unlock(&tp->plock);
+}
+
+static void ucm_check_timers(dp_ib_cm_handle_t cm, int *timer)
+{
+       DAPL_OS_TIMEVAL time;
+
+        dapl_os_lock(&cm->lock);
+       dapl_os_get_time(&time); 
+       switch (cm->state) {
+       case DCM_REP_PENDING: 
+               *timer = cm->hca->ib_trans.cm_timer; 
+               /* wait longer each retry */
+               if ((time - cm->timer)/1000 > 
+                   (cm->hca->ib_trans.rep_time << cm->retries)) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                " CM_REQ retry %d [lid, port, qpn]:"
+                                " %x %x %x -> %x %x %x Time(ms) %llu > %llu\n", 
+                                cm->retries, ntohs(cm->msg.saddr.ib.lid), 
+                                ntohs(cm->msg.sport), ntohl(cm->msg.saddr.ib.qpn), 
+                                ntohs(cm->msg.daddr.ib.lid), ntohs(cm->msg.dport),
+                                ntohl(cm->msg.dqpn), (time - cm->timer)/1000, 
+                                cm->hca->ib_trans.rep_time << cm->retries);
+                       cm->retries++;
+                       dapl_os_unlock(&cm->lock);
+                       dapli_cm_connect(cm->ep, cm);
+                       return;
+               }
+               break;
+       case DCM_RTU_PENDING: 
+               *timer = cm->hca->ib_trans.cm_timer;  
+               if ((time - cm->timer)/1000 > 
+                   (cm->hca->ib_trans.rtu_time << cm->retries)) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                " CM_REPLY retry %d [lid, port, qpn]:"
+                                " %x %x %x -> %x %x %x r_pid %x,%d Time(ms) %llu > %llu\n", 
+                                cm->retries,
+                                ntohs(cm->msg.saddr.ib.lid), 
+                                ntohs(cm->msg.sport),
+                                ntohl(cm->msg.saddr.ib.qpn), 
+                                ntohs(cm->msg.daddr.ib.lid), 
+                                ntohs(cm->msg.dport),
+                                ntohl(cm->msg.daddr.ib.qpn),  
+                                ntohl(*(DAT_UINT32*)cm->msg.resv),
+                                ntohl(*(DAT_UINT32*)cm->msg.resv), 
+                                (time - cm->timer)/1000, cm->hca->ib_trans.rtu_time << cm->retries);
+                       cm->retries++;
+                       dapl_os_unlock(&cm->lock);
+                       ucm_reply(cm);
+                       return;
+               }
+               break;
+       case DCM_DISC_PENDING: 
+               *timer = cm->hca->ib_trans.cm_timer; 
+               /* wait longer each retry */
+               if ((time - cm->timer)/1000 > 
+                   (cm->hca->ib_trans.rtu_time << cm->retries)) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                " CM_DREQ retry %d [lid, port, qpn]:"
+                                " %x %x %x -> %x %x %x r_pid %x,%d Time(ms) %llu > %llu\n", 
+                                cm->retries,
+                                ntohs(cm->msg.saddr.ib.lid), 
+                                ntohs(cm->msg.sport),
+                                ntohl(cm->msg.saddr.ib.qpn), 
+                                ntohs(cm->msg.daddr.ib.lid), 
+                                ntohs(cm->msg.dport),
+                                ntohl(cm->msg.dqpn), 
+                                ntohl(*(DAT_UINT32*)cm->msg.resv),
+                                ntohl(*(DAT_UINT32*)cm->msg.resv), 
+                                (time - cm->timer)/1000, cm->hca->ib_trans.rtu_time << cm->retries);
+                       cm->retries++;
+                       dapl_os_unlock(&cm->lock);
+                       dapli_cm_disconnect(cm);
+                        return;
+               }
+               break;
+       default:
+               break;
+       }
+       dapl_os_unlock(&cm->lock);
+}
+
+/* SEND CM MESSAGE PROCESSING */
+
+/* Get CM UD message from send queue, called with s_lock held */
+static ib_cm_msg_t *ucm_get_smsg(ib_hca_transport_t *tp)
+{
+       ib_cm_msg_t *msg = NULL; 
+       int ret, polled = 0, hd = tp->s_hd;
+
+       hd++;
+retry:
+       if (hd == tp->qpe)
+               hd = 0;
+
+       if (hd == tp->s_tl)
+               msg = NULL;
+       else {
+               msg = &tp->sbuf[hd];
+               tp->s_hd = hd; /* new hd */
+       }
+
+       /* if empty, process some completions */
+       if ((msg == NULL) && (!polled)) {
+               struct ibv_wc wc;
+
+               /* process completions, based on UCM_SND_BURST */
+               ret = ibv_poll_cq(tp->scq, 1, &wc);
+               if (ret < 0) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                               " get_smsg: cq %p %s\n", 
+                               tp->scq, strerror(errno));
+               }
+               /* free up completed sends, update tail */
+               if (ret > 0) {
+                       tp->s_tl = (int)wc.wr_id;
+                       dapl_log(DAPL_DBG_TYPE_CM,
+                               " get_smsg: wr_cmp (%d) s_tl=%d\n", 
+                               wc.status, tp->s_tl);
+               }
+               polled++;
+               goto retry;
+       }
+       return msg;
+}
+
+/* RECEIVE CM MESSAGE PROCESSING */
+
+static int ucm_post_rmsg(ib_hca_transport_t *tp, ib_cm_msg_t *msg)
+{      
+       struct ibv_recv_wr recv_wr, *recv_err;
+       struct ibv_sge sge;
+        
+       recv_wr.next = NULL;
+       recv_wr.sg_list = &sge;
+       recv_wr.num_sge = 1;
+       recv_wr.wr_id = (uint64_t)(uintptr_t) msg;
+       sge.length = sizeof(ib_cm_msg_t) + sizeof(struct ibv_grh);
+       sge.lkey = tp->mr_rbuf->lkey;
+       sge.addr = (uintptr_t)((char *)msg - sizeof(struct ibv_grh));
+       
+       return (ibv_post_recv(tp->qp, &recv_wr, &recv_err));
+}
+
+static int ucm_reject(ib_hca_transport_t *tp, ib_cm_msg_t *msg)
+{
+       ib_cm_msg_t     smsg;
+
+       /* setup op, rearrange the src, dst cm and addr info */
+       (void)dapl_os_memzero(&smsg, sizeof(smsg));
+       smsg.ver = htons(DCM_VER);
+       smsg.op = htons(DCM_REJ_CM);
+       smsg.dport = msg->sport;
+       smsg.dqpn = msg->sqpn;
+       smsg.sport = msg->dport; 
+       smsg.sqpn = msg->dqpn;
+
+       dapl_os_memcpy(&smsg.daddr, &msg->saddr, sizeof(union dcm_addr));
+       
+       /* no dst_addr IB info in REQ, init lid, gid, get type from saddr */
+       smsg.saddr.ib.lid = tp->addr.ib.lid; 
+       smsg.saddr.ib.qp_type = msg->saddr.ib.qp_type;
+       dapl_os_memcpy(&smsg.saddr.ib.gid[0],
+                      &tp->addr.ib.gid, 16); 
+
+       dapl_os_memcpy(&smsg.saddr, &msg->daddr, sizeof(union dcm_addr));
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, 
+                    " CM reject -> LID %x, QPN %x PORT %d\n", 
+                    ntohs(smsg.daddr.ib.lid),
+                    ntohl(smsg.dqpn), ntohs(smsg.dport));
+
+       return (ucm_send(tp, &smsg, NULL, 0));
+}
+
+static void ucm_process_recv(ib_hca_transport_t *tp, 
+                            ib_cm_msg_t *msg, 
+                            dp_ib_cm_handle_t cm)
+{
+       dapl_os_lock(&cm->lock);
+       switch (cm->state) {
+       case DCM_LISTEN: /* passive */
+               dapl_os_unlock(&cm->lock);
+               ucm_accept(cm, msg);
+               break;
+       case DCM_RTU_PENDING: /* passive */
+               dapl_os_unlock(&cm->lock);
+               ucm_accept_rtu(cm, msg);
+               break;
+       case DCM_REP_PENDING: /* active */
+               dapl_os_unlock(&cm->lock);
+               ucm_connect_rtu(cm, msg);
+               break;
+       case DCM_CONNECTED: /* active and passive */
+               /* DREQ, change state and process */
+               if (ntohs(msg->op) == DCM_DREQ) {
+                       cm->state = DCM_DISC_RECV;
+                       dapl_os_unlock(&cm->lock);
+                       dapli_cm_disconnect(cm);
+                       break;
+               } 
+               /* active: RTU was dropped, resend */
+               if (ntohs(msg->op) == DCM_REP) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                               " RESEND RTU: op %s st %s [lid, port, qpn]:"
+                               " 0x%x %d 0x%x -> 0x%x %d 0x%x\n", 
+                               dapl_cm_op_str(ntohs(msg->op)), 
+                               dapl_cm_state_str(cm->state),
+                               ntohs(msg->saddr.ib.lid), 
+                               ntohs(msg->sport),
+                               ntohl(msg->saddr.ib.qpn), 
+                               ntohs(msg->daddr.ib.lid), 
+                               ntohs(msg->dport),
+                               ntohl(msg->daddr.ib.qpn));  
+
+                       cm->msg.op = htons(DCM_RTU);
+                       ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0);                
+               }
+               dapl_os_unlock(&cm->lock);
+               break;
+       case DCM_DISC_PENDING: /* active and passive */
+               /* DREQ or DREP, finalize */
+               dapl_os_unlock(&cm->lock);
+               ucm_disconnect_final(cm);
+               break;
+       case DCM_DISCONNECTED:
+       case DCM_FREE:
+               /* DREQ dropped, resend */
+               if (ntohs(msg->op) == DCM_DREQ) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                               " RESEND DREP: op %s st %s [lid, port, qpn]:"
+                               " 0x%x %d 0x%x -> 0x%x %d 0x%x\n", 
+                               dapl_cm_op_str(ntohs(msg->op)), 
+                               dapl_cm_state_str(cm->state),
+                               ntohs(msg->saddr.ib.lid), 
+                               ntohs(msg->sport),
+                               ntohl(msg->saddr.ib.qpn), 
+                               ntohs(msg->daddr.ib.lid), 
+                               ntohs(msg->dport),
+                               ntohl(msg->daddr.ib.qpn));  
+                       cm->msg.op = htons(DCM_DREP);
+                       ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0); 
+                       
+               }
+               /* UD reply retried ok to ignore, any other print warning */
+               if (ntohs(msg->op) != DCM_REP) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                               " ucm_recv: UNKNOWN operation"
+                               " <- op %d, %s spsp %d sqpn %d\n", 
+                               ntohs(msg->op), dapl_cm_state_str(cm->state),
+                               ntohs(msg->sport), ntohl(msg->sqpn));
+               }
+               dapl_os_unlock(&cm->lock);
+               break;
+       default:
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                               " ucm_recv: UNKNOWN state"
+                               " <- op %d, %s spsp %d sqpn %d\n", 
+                               ntohs(msg->op), dapl_cm_state_str(cm->state), 
+                               ntohs(msg->sport), ntohl(msg->sqpn));
+               dapl_os_unlock(&cm->lock);
+               break;
+       }
+}
+
+/* Find matching CM object for this receive message, return CM reference, timer */
+dp_ib_cm_handle_t ucm_cm_find(ib_hca_transport_t *tp, ib_cm_msg_t *msg)
+{
+       dp_ib_cm_handle_t cm, next, found = NULL;
+       struct dapl_llist_entry **list;
+       DAPL_OS_LOCK *lock;
+       int listenq = 0;
+
+       /* conn list first, duplicate requests for DCM_REQ */
+       list = &tp->list;
+       lock = &tp->lock;
+
+retry_listenq:
+       dapl_os_lock(lock);
+        if (!dapl_llist_is_empty(list))
+               next = dapl_llist_peek_head(list);
+       else
+               next = NULL;
+
+       while (next) {
+               cm = next;
+               next = dapl_llist_next_entry(list,
+                                            (DAPL_LLIST_ENTRY *)&cm->local_entry);
+               if (cm->state == DCM_DESTROY || cm->state == DCM_FREE)
+                       continue;
+               
+               /* CM sPORT + QPN, match is good enough for listenq */
+               if (listenq && 
+                   cm->msg.sport == msg->dport && 
+                   cm->msg.sqpn == msg->dqpn) {
+                       found = cm;
+                       break;
+               }        
+               /* connectq, check src and dst, check duplicate conn_reqs */
+               if (!listenq && 
+                   cm->msg.sport == msg->dport && cm->msg.sqpn == msg->dqpn && 
+                   cm->msg.dport == msg->sport && cm->msg.dqpn == msg->sqpn && 
+                   cm->msg.daddr.ib.lid == msg->saddr.ib.lid) {
+                       if (ntohs(msg->op) != DCM_REQ) {
+                               found = cm;
+                               break; 
+                       } else {
+                               /* duplicate; bail and throw away */
+                               dapl_os_unlock(lock);
+                               dapl_log(DAPL_DBG_TYPE_WARN,
+                                        " DUPLICATE: op %s st %s [lid, port, qpn]:"
+                                        " 0x%x %d 0x%x <- 0x%x %d 0x%x\n", 
+                                        dapl_cm_op_str(ntohs(msg->op)), 
+                                        dapl_cm_state_str(cm->state),
+                                        ntohs(msg->daddr.ib.lid), 
+                                        ntohs(msg->dport),
+                                        ntohl(msg->daddr.ib.qpn), 
+                                        ntohs(msg->saddr.ib.lid), 
+                                        ntohs(msg->sport),
+                                        ntohl(msg->saddr.ib.qpn));  
+                               return NULL;
+                       }
+               }
+       }
+       dapl_os_unlock(lock);
+
+       /* no duplicate request on connq, check listenq for new request */
+       if (ntohs(msg->op) == DCM_REQ && !listenq && !found) {
+               listenq = 1;
+               list = &tp->llist;
+               lock = &tp->llock;
+               goto retry_listenq;
+       }
+
+       /* not match on listenq for valid request, send reject */
+       if (ntohs(msg->op) == DCM_REQ && !found)
+               ucm_reject(tp, msg);
+
+       if (!found) {
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                       " ucm_recv: NO MATCH op %s 0x%x %d i0x%x c0x%x"
+                       " < 0x%x %d 0x%x\n", 
+                       dapl_cm_op_str(ntohs(msg->op)), 
+                       ntohs(msg->daddr.ib.lid), ntohs(msg->dport), 
+                       ntohl(msg->daddr.ib.qpn), ntohl(msg->sqpn),
+                       ntohs(msg->saddr.ib.lid), ntohs(msg->sport), 
+                       ntohl(msg->saddr.ib.qpn));
+       }
+
+       return found;
+}
+
+/* Get rmsgs from CM completion queue, 10 at a time */
+static void ucm_recv(ib_hca_transport_t *tp)
+{
+       struct ibv_wc wc[10];
+       ib_cm_msg_t *msg;
+       dp_ib_cm_handle_t cm;
+       int i, ret, notify = 0;
+       struct ibv_cq *ibv_cq = NULL;
+       DAPL_HCA *hca;
+
+       /* POLLIN on channel FD */
+       ret = ibv_get_cq_event(tp->rch, &ibv_cq, (void *)&hca);
+       if (ret == 0) {
+               ibv_ack_cq_events(ibv_cq, 1);
+       }
+retry: 
+       ret = ibv_poll_cq(tp->rcq, 10, wc);
+       if (ret <= 0) {
+               if (!ret && !notify) {
+                       ibv_req_notify_cq(tp->rcq, 0);
+                       notify = 1;
+                       goto retry;
+               }
+               return;
+       } else 
+               notify = 0;
+       
+       for (i = 0; i < ret; i++) {
+               msg = (ib_cm_msg_t*) (uintptr_t) wc[i].wr_id;
+
+               dapl_dbg_log(DAPL_DBG_TYPE_CM, 
+                            " ucm_recv: wc status=%d, ln=%d id=%p sqp=%x\n", 
+                            wc[i].status, wc[i].byte_len, 
+                            (void*)wc[i].wr_id, wc[i].src_qp);
+
+               /* validate CM message, version */
+               if (ntohs(msg->ver) != DCM_VER) {
+                       dapl_log(DAPL_DBG_TYPE_WARN,
+                                " ucm_recv: UNKNOWN msg %p, ver %d\n", 
+                                msg, msg->ver);
+                       ucm_post_rmsg(tp, msg);
+                       continue;
+               }
+               if (!(cm = ucm_cm_find(tp, msg))) {
+                       ucm_post_rmsg(tp, msg);
+                       continue;
+               }
+               
+               /* match, process it */
+               ucm_process_recv(tp, msg, cm);
+               ucm_post_rmsg(tp, msg);
+       }
+       
+       /* finished this batch of WC's, poll and rearm */
+       goto retry;
+}
+
+/* ACTIVE/PASSIVE: build and send CM message out of CM object */
+static int ucm_send(ib_hca_transport_t *tp, ib_cm_msg_t *msg, DAT_PVOID p_data, DAT_COUNT p_size)
+{
+       ib_cm_msg_t *smsg = NULL;
+       struct ibv_send_wr wr, *bad_wr;
+       struct ibv_sge sge;
+       int len, ret = -1;
+       uint16_t dlid = ntohs(msg->daddr.ib.lid);
+
+       /* Get message from send queue, copy data, and send */
+       dapl_os_lock(&tp->slock);
+       if ((smsg = ucm_get_smsg(tp)) == NULL)
+               goto bail;
+
+       len = (sizeof(*msg) - DCM_MAX_PDATA_SIZE);
+       dapl_os_memcpy(smsg, msg, len);
+       if (p_size) {
+               smsg->p_size = ntohs(p_size);
+               dapl_os_memcpy(&smsg->p_data, p_data, p_size);
+       }
+
+       wr.next = NULL;
+        wr.sg_list = &sge;
+        wr.num_sge = 1;
+        wr.opcode = IBV_WR_SEND;
+        wr.wr_id = (unsigned long)tp->s_hd;
+       wr.send_flags = (wr.wr_id % UCM_SND_BURST) ? 0 : IBV_SEND_SIGNALED;
+       if (len <= tp->max_inline_send)
+               wr.send_flags |= IBV_SEND_INLINE; 
+
+        sge.length = len + p_size;
+        sge.lkey = tp->mr_sbuf->lkey;
+        sge.addr = (uintptr_t)smsg;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, 
+               " ucm_send: op %d ln %d lid %x c_qpn %x rport %d\n", 
+               ntohs(smsg->op), sge.length, htons(smsg->daddr.ib.lid), 
+               htonl(smsg->dqpn), htons(smsg->dport));
+
+       /* empty slot, then create AH */
+       if (!tp->ah[dlid]) {
+               tp->ah[dlid] =  
+                       dapls_create_ah(tp->hca, tp->pd, tp->qp, 
+                                       htons(dlid), NULL);
+               if (!tp->ah[dlid])
+                       goto bail;
+       }
+               
+       wr.wr.ud.ah = tp->ah[dlid];
+       wr.wr.ud.remote_qpn = ntohl(smsg->dqpn);
+       wr.wr.ud.remote_qkey = DAT_UD_QKEY;
+
+       ret = ibv_post_send(tp->qp, &wr, &bad_wr);
+bail:
+       dapl_os_unlock(&tp->slock);     
+       return ret;
+}
+
+/* ACTIVE/PASSIVE: CM objects */
+static void dapli_cm_dealloc(dp_ib_cm_handle_t cm) {
+
+       dapl_os_assert(!cm->ref_count);
+       dapl_os_lock_destroy(&cm->lock);
+       dapl_os_wait_object_destroy(&cm->event);
+       dapl_os_free(cm, sizeof(*cm));
+}
+
+void dapls_cm_acquire(dp_ib_cm_handle_t cm)
+{
+       dapl_os_lock(&cm->lock);
+       cm->ref_count++;
+       dapl_os_unlock(&cm->lock);
+}
+
+void dapls_cm_release(dp_ib_cm_handle_t cm)
+{
+       dapl_os_lock(&cm->lock);
+       cm->ref_count--;\r
+       if (cm->ref_count) {\r
+                dapl_os_unlock(&cm->lock);\r
                return;\r
        }\r
-\r
-       dapl_os_lock(&cm->lock);\r
-\r
-       /* client, release local conn id port */\r
-       if (!cm->sp && cm->msg.sport)\r
-               ucm_free_port(&cm->hca->ib_trans, cm->msg.sport);\r
-\r
-       /* cleanup, never made it to work queue */\r
-       if (cm->state == DCM_INIT) {\r
-               dapl_os_unlock(&cm->lock);\r
-               dapl_os_lock_destroy(&cm->lock);\r
-               dapl_os_free(cm, sizeof(*cm));\r
-               return;\r
-       }\r
-\r
-       /* free could be called before disconnect, disc_clean will destroy */\r
-       if (cm->state == DCM_CONNECTED) {\r
-               dapl_os_unlock(&cm->lock);\r
-               dapli_cm_disconnect(cm);\r
-               return;\r
-       }\r
-\r
-       cm->state = DCM_DESTROY;\r
-       if ((cm->ep) && (cm->ep->cm_handle == cm)) {\r
-               cm->ep->cm_handle = IB_INVALID_HANDLE;\r
-               cm->ep = NULL;\r
-       }\r
-\r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       /* wakeup work thread */\r
-       dapls_thread_signal(&cm->hca->ib_trans.signal);\r
-}\r
-\r
-/* ACTIVE/PASSIVE: queue up connection object on CM list */\r
-static void ucm_queue_conn(dp_ib_cm_handle_t cm)\r
-{\r
-       /* add to work queue, list, for cm thread processing */\r
-       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm->entry);\r
-       dapl_os_lock(&cm->hca->ib_trans.lock);\r
-       dapl_llist_add_tail(&cm->hca->ib_trans.list,\r
-                           (DAPL_LLIST_ENTRY *)&cm->entry, cm);\r
-       dapl_os_unlock(&cm->hca->ib_trans.lock);\r
-       dapls_thread_signal(&cm->hca->ib_trans.signal);\r
-}\r
-\r
-/* PASSIVE: queue up listen object on listen list */\r
-static void ucm_queue_listen(dp_ib_cm_handle_t cm)\r
-{\r
-       /* add to work queue, llist, for cm thread processing */\r
-       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm->entry);\r
-       dapl_os_lock(&cm->hca->ib_trans.llock);\r
-       dapl_llist_add_tail(&cm->hca->ib_trans.llist,\r
-                           (DAPL_LLIST_ENTRY *)&cm->entry, cm);\r
-       dapl_os_unlock(&cm->hca->ib_trans.llock);\r
-}\r
-\r
-static void ucm_dequeue_listen(dp_ib_cm_handle_t cm) {\r
-       dapl_os_lock(&cm->hca->ib_trans.llock);\r
-       dapl_llist_remove_entry(&cm->hca->ib_trans.llist, \r
-                               (DAPL_LLIST_ENTRY *)&cm->entry);\r
-       dapl_os_unlock(&cm->hca->ib_trans.llock);\r
-}\r
-\r
-static void ucm_disconnect_final(dp_ib_cm_handle_t cm) \r
-{\r
-       /* no EP attachment or not RC, nothing to process */\r
-       if (cm->ep == NULL ||\r
-           cm->ep->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC) \r
-               return;\r
-\r
-       dapl_os_lock(&cm->lock);\r
-       if (cm->state == DCM_DISCONNECTED) {\r
-               dapl_os_unlock(&cm->lock);\r
-               return;\r
-       }\r
-               \r
-       cm->state = DCM_DISCONNECTED;\r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       if (cm->sp) \r
-               dapls_cr_callback(cm, IB_CME_DISCONNECTED, NULL, 0, cm->sp);\r
-       else\r
-               dapl_evd_connection_callback(cm, IB_CME_DISCONNECTED, NULL, 0, cm->ep);\r
-}\r
-\r
-/*\r
- * called from consumer thread via ep_disconnect/ep_free or \r
- * from cm_thread when receiving DREQ\r
- */\r
-DAT_RETURN dapli_cm_disconnect(dp_ib_cm_handle_t cm)\r
-{\r
-       int finalize = 1;\r
-\r
-       dapl_os_lock(&cm->lock);\r
-       switch (cm->state) {\r
-       case DCM_CONNECTED:\r
-               /* CONSUMER: move to err state to flush, if not UD */\r
-               if (cm->ep->qp_handle->qp_type != IBV_QPT_UD) \r
-                       dapls_modify_qp_state(cm->ep->qp_handle, IBV_QPS_ERR,0,0,0);\r
-\r
-               /* send DREQ, event after DREP or DREQ timeout */\r
-               cm->state = DCM_DISC_PENDING;\r
-               cm->msg.op = htons(DCM_DREQ);\r
-               finalize = 0; /* wait for DREP, wakeup timer thread */\r
-               dapls_thread_signal(&cm->hca->ib_trans.signal);\r
-               break;\r
-       case DCM_DISC_PENDING:\r
-               /* DREQ timeout, resend until retries exhausted */\r
-               cm->msg.op = htons(DCM_DREQ);\r
-               if (cm->retries >= cm->hca->ib_trans.retries) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR, \r
-                               " CM_DREQ: RETRIES EXHAUSTED:"\r
-                               " 0x%x %d 0x%x -> 0x%x %d 0x%x\n",\r
-                               htons(cm->msg.saddr.ib.lid), \r
-                               htonl(cm->msg.saddr.ib.qpn), \r
-                               htons(cm->msg.sport), \r
-                               htons(cm->msg.daddr.ib.lid), \r
-                               htonl(cm->msg.dqpn), \r
-                               htons(cm->msg.dport));\r
-                       finalize = 1;\r
-               }\r
-               break;\r
-       case DCM_DISC_RECV:\r
-               /* CM_THREAD: move to err state to flush, if not UD */\r
-               if (cm->ep->qp_handle->qp_type != IBV_QPT_UD) \r
-                       dapls_modify_qp_state(cm->ep->qp_handle, IBV_QPS_ERR,0,0,0);\r
-\r
-               /* DREQ received, send DREP and schedule event */\r
-               cm->msg.op = htons(DCM_DREP);\r
-               break;\r
-       default:\r
-               dapl_os_unlock(&cm->lock);\r
-               return DAT_SUCCESS;\r
-       }\r
-       \r
-       dapl_os_get_time(&cm->timer); /* reply expected */\r
-       ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0); \r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       if (finalize)\r
-               ucm_disconnect_final(cm);\r
-       \r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * ACTIVE: get remote CM SID server info from r_addr. \r
- *         send, or resend CM msg via UD CM QP \r
- */\r
-DAT_RETURN\r
-dapli_cm_connect(DAPL_EP *ep, dp_ib_cm_handle_t cm)\r
-{\r
-       dapl_log(DAPL_DBG_TYPE_EP, \r
-                " connect: lid %x i_qpn %x lport %d p_sz=%d -> "\r
-                " lid %x c_qpn %x rport %d\n",\r
-                htons(cm->msg.saddr.ib.lid), htonl(cm->msg.saddr.ib.qpn),\r
-                htons(cm->msg.sport), htons(cm->msg.p_size),\r
-                htons(cm->msg.daddr.ib.lid), htonl(cm->msg.dqpn),\r
-                htons(cm->msg.dport));\r
-\r
-       dapl_os_lock(&cm->lock);\r
-       if (cm->state != DCM_REP_PENDING) {\r
-               dapl_os_unlock(&cm->lock);\r
-               return DAT_INVALID_STATE;\r
-       }\r
-       \r
-       if (cm->retries == cm->hca->ib_trans.retries) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR, \r
-                       " CM_REQ: RETRIES EXHAUSTED:"\r
-                        " 0x%x %d 0x%x -> 0x%x %d 0x%x\n",\r
-                        htons(cm->msg.saddr.ib.lid), \r
-                        htonl(cm->msg.saddr.ib.qpn), \r
-                        htons(cm->msg.sport), \r
-                        htons(cm->msg.daddr.ib.lid), \r
-                        htonl(cm->msg.dqpn), \r
-                        htons(cm->msg.dport));\r
-\r
-               /* update ep->cm reference so we get cleaned up on callback */\r
-               if (cm->msg.saddr.ib.qp_type == IBV_QPT_RC);\r
-                       ep->cm_handle = cm;\r
-\r
-               dapl_os_unlock(&cm->lock);\r
-\r
-#ifdef DAPL_COUNTERS\r
-               /* called from check_timers in cm_thread, cm lock held */\r
-               if (g_dapl_dbg_type & DAPL_DBG_TYPE_CM_LIST) {\r
-                       dapl_os_unlock(&cm->hca->ib_trans.lock);\r
-                       dapls_print_cm_list(ep->header.owner_ia);\r
-                       dapl_os_lock(&cm->hca->ib_trans.lock);\r
-               }\r
-#endif\r
-               dapl_evd_connection_callback(cm, \r
-                                            IB_CME_DESTINATION_UNREACHABLE,\r
-                                            NULL, 0, ep);\r
-               \r
-               return DAT_ERROR(DAT_INVALID_ADDRESS, \r
-                                DAT_INVALID_ADDRESS_UNREACHABLE);\r
+       /* client, release local conn id port */
+       if (!cm->sp && cm->msg.sport)
+               ucm_free_port(&cm->hca->ib_trans, ntohs(cm->msg.sport));
+
+       /* server, release local conn id port */
+       if (cm->sp && cm->msg.dport)
+               ucm_free_port(&cm->hca->ib_trans, ntohs(cm->msg.dport));
+
+       /* clean up any UD address handles */
+       if (cm->ah) {
+               ibv_destroy_ah(cm->ah);
+               cm->ah = NULL;
        }\r
        dapl_os_unlock(&cm->lock);\r
-\r
-       cm->msg.op = htons(DCM_REQ);\r
-       dapl_os_get_time(&cm->timer); /* reply expected */\r
-       if (ucm_send(&cm->hca->ib_trans, &cm->msg, \r
-                    &cm->msg.p_data, ntohs(cm->msg.p_size)))           \r
-               goto bail;\r
-\r
-       /* first time through, put on work queue */\r
-       if (!cm->retries)\r
-               ucm_queue_conn(cm);\r
-\r
-       return DAT_SUCCESS;\r
-\r
-bail:\r
-       dapl_log(DAPL_DBG_TYPE_WARN, \r
-                " connect: ERR %s -> cm_lid %d cm_qpn %d r_psp %d p_sz=%d\n",\r
-                strerror(errno), htons(cm->msg.daddr.ib.lid), \r
-                htonl(cm->msg.dqpn), htons(cm->msg.dport), \r
-                htonl(cm->msg.p_size));\r
-\r
-       /* close socket, free cm structure */\r
-       dapls_ib_cm_free(cm, cm->ep);\r
-       return DAT_INSUFFICIENT_RESOURCES;\r
-}\r
-\r
-/*\r
- * ACTIVE: exchange QP information, called from CR thread\r
- */\r
-static void ucm_connect_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg)\r
-{\r
-       DAPL_EP *ep = cm->ep;\r
-       ib_cm_events_t event = IB_CME_CONNECTED;\r
-\r
-       dapl_os_lock(&cm->lock);\r
-       if (cm->state != DCM_REP_PENDING) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN, \r
-                        " CONN_RTU: UNEXPECTED state:"\r
-                        " op %d, st %s <- lid %d sqpn %d sport %d\n", \r
-                        ntohs(msg->op), dapl_cm_state_str(cm->state), \r
-                        ntohs(msg->saddr.ib.lid), ntohl(msg->saddr.ib.qpn), \r
-                        ntohs(msg->sport));\r
-               dapl_os_unlock(&cm->lock);\r
-               return;\r
-       }\r
-\r
-       /* save remote address information to EP and CM */\r
-       dapl_os_memcpy(&ep->remote_ia_address,\r
-                      &msg->saddr, sizeof(union dcm_addr));\r
-       dapl_os_memcpy(&cm->msg.daddr, \r
-                      &msg->saddr, sizeof(union dcm_addr));\r
-\r
-       /* validate private data size, and copy if necessary */\r
-       if (msg->p_size) {\r
-               if (ntohs(msg->p_size) > DCM_MAX_PDATA_SIZE) {\r
-                       dapl_log(DAPL_DBG_TYPE_WARN, \r
-                                " CONN_RTU: invalid p_size %d:"\r
-                                " st %s <- lid %d sqpn %d spsp %d\n", \r
-                                ntohs(msg->p_size), \r
-                                dapl_cm_state_str(cm->state), \r
-                                ntohs(msg->saddr.ib.lid), \r
-                                ntohl(msg->saddr.ib.qpn), \r
-                                ntohs(msg->sport));\r
-                       dapl_os_unlock(&cm->lock);\r
-                       goto bail;\r
-               }\r
-               dapl_os_memcpy(cm->msg.p_data, \r
-                              msg->p_data, ntohs(msg->p_size));\r
-       }\r
-               \r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " CONN_RTU: DST lid=%x,"\r
-                    " iqp=%x, qp_type=%d, port=%d psize=%d\n",\r
-                    ntohs(cm->msg.daddr.ib.lid),\r
-                    ntohl(cm->msg.daddr.ib.qpn), cm->msg.daddr.ib.qp_type,\r
-                    ntohs(msg->sport), ntohs(msg->p_size));\r
-\r
-       if (ntohs(msg->op) == DCM_REP)\r
-               event = IB_CME_CONNECTED;\r
-       else if (ntohs(msg->op) == DCM_REJ_USER) \r
-               event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;\r
-       else  \r
-               event = IB_CME_DESTINATION_REJECT;\r
-       \r
-       if (event != IB_CME_CONNECTED) {\r
-               cm->state = DCM_REJECTED;\r
-               dapl_os_unlock(&cm->lock);\r
-\r
-#ifdef DAT_EXTENSIONS\r
-               if (cm->msg.daddr.ib.qp_type == IBV_QPT_UD) \r
-                       goto ud_bail;\r
-               else\r
-#endif\r
-               goto bail;\r
-       }\r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       /* modify QP to RTR and then to RTS with remote info */\r
-       dapl_os_lock(&cm->ep->header.lock);\r
-       if (dapls_modify_qp_state(cm->ep->qp_handle,\r
-                                 IBV_QPS_RTR, \r
-                                 cm->msg.daddr.ib.qpn,\r
-                                 cm->msg.daddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_RTU: QPS_RTR ERR %s <- lid %x iqp %x\n",\r
-                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),\r
-                        ntohl(cm->msg.daddr.ib.qpn));\r
-               dapl_os_unlock(&cm->ep->header.lock);\r
-               event = IB_CME_LOCAL_FAILURE;\r
-               goto bail;\r
-       }\r
-       if (dapls_modify_qp_state(cm->ep->qp_handle,\r
-                                 IBV_QPS_RTS, \r
-                                 cm->msg.daddr.ib.qpn,\r
-                                 cm->msg.daddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " CONN_RTU: QPS_RTS ERR %s <- lid %x iqp %x\n",\r
-                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),\r
-                        ntohl(cm->msg.daddr.ib.qpn));\r
-               dapl_os_unlock(&cm->ep->header.lock);\r
-               event = IB_CME_LOCAL_FAILURE;\r
-               goto bail;\r
-       }\r
-       dapl_os_unlock(&cm->ep->header.lock);\r
-       \r
-       /* Send RTU, no private data */\r
-       cm->msg.op = htons(DCM_RTU);\r
-       \r
-       dapl_os_lock(&cm->lock);\r
-       cm->state = DCM_CONNECTED;\r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       if (ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0))            \r
-               goto bail;\r
-\r
-       /* init cm_handle and post the event with private data */\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP, " ACTIVE: connected!\n");\r
-\r
-#ifdef DAT_EXTENSIONS\r
-ud_bail:\r
-       if (cm->msg.daddr.ib.qp_type == IBV_QPT_UD) {\r
-               DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-               uint16_t lid = ntohs(cm->msg.daddr.ib.lid);\r
-               \r
-               /* post EVENT, modify_qp, AH already created, ucm msg */\r
-               xevent.status = 0;\r
-               xevent.type = DAT_IB_UD_REMOTE_AH;\r
-               xevent.remote_ah.qpn = ntohl(cm->msg.daddr.ib.qpn);\r
-               xevent.remote_ah.ah = dapls_create_ah(cm->hca, \r
-                                                     cm->ep->qp_handle->pd, \r
-                                                     cm->ep->qp_handle, \r
-                                                     htons(lid), \r
-                                                     NULL);\r
-               if (xevent.remote_ah.ah == NULL) {\r
-                       event = IB_CME_LOCAL_FAILURE;\r
-                       goto bail;\r
-               }\r
-               cm->ah = xevent.remote_ah.ah; /* keep ref to destroy */\r
-\r
-               dapl_os_memcpy(&xevent.remote_ah.ia_addr,\r
-                              &cm->msg.daddr,\r
-                              sizeof(union dcm_addr));\r
-\r
-               /* remote ia_addr reference includes ucm qpn, not IB qpn */\r
-               ((union dcm_addr*)\r
-                       &xevent.remote_ah.ia_addr)->ib.qpn = cm->msg.dqpn;\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                            " ACTIVE: UD xevent ah %p qpn 0x%x lid 0x%x\n",\r
-                            xevent.remote_ah.ah, xevent.remote_ah.qpn, lid);\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                            " ACTIVE: UD xevent ia_addr qp_type %d"\r
-                            " lid 0x%x qpn 0x%x gid 0x"F64x" 0x"F64x" \n",\r
-                            ((union dcm_addr*)\r
-                               &xevent.remote_ah.ia_addr)->ib.qp_type,\r
-                            ntohs(((union dcm_addr*)\r
-                               &xevent.remote_ah.ia_addr)->ib.lid),\r
-                            ntohl(((union dcm_addr*)\r
-                               &xevent.remote_ah.ia_addr)->ib.qpn),\r
-                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[0]),\r
-                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[8]));\r
-\r
-               if (event == IB_CME_CONNECTED)\r
-                       event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;\r
-               else {\r
-                       xevent.type = DAT_IB_UD_CONNECT_REJECT;\r
-                       event = DAT_IB_UD_CONNECTION_REJECT_EVENT;\r
-               }\r
-\r
-               dapls_evd_post_connection_event_ext(\r
-                               (DAPL_EVD *)cm->ep->param.connect_evd_handle,\r
-                               event,\r
-                               (DAT_EP_HANDLE)ep,\r
-                               (DAT_COUNT)ntohs(cm->msg.p_size),\r
-                               (DAT_PVOID *)cm->msg.p_data,\r
-                               (DAT_PVOID *)&xevent);\r
-\r
-               /* we are done, don't destroy cm_ptr, need pdata */\r
-               dapl_os_lock(&cm->lock);\r
-               cm->state = DCM_RELEASED;\r
-               dapl_os_unlock(&cm->lock);\r
-               \r
-       } else\r
-#endif\r
-       {\r
-               cm->ep->cm_handle = cm; /* only RC, multi CR's on UD */\r
-               dapl_evd_connection_callback(cm,\r
-                                            IB_CME_CONNECTED,\r
-                                            cm->msg.p_data, ntohs(cm->msg.p_size), cm->ep);\r
-       }\r
-       return;\r
-bail:\r
-       if (cm->msg.saddr.ib.qp_type != IBV_QPT_UD) \r
-               dapls_ib_reinit_ep(cm->ep); /* reset QP state */\r
-\r
-       dapl_evd_connection_callback(NULL, event, cm->msg.p_data, ntohs(cm->msg.p_size), cm->ep);\r
-       dapls_ib_cm_free(cm, NULL); \r
-}\r
-\r
-/*\r
- * PASSIVE: Accept on listen CM PSP.\r
- *          create new CM object for this CR, \r
- *         receive peer QP information, private data, \r
- *         and post cr_event \r
- */\r
-static void ucm_accept(ib_cm_srvc_handle_t cm, ib_cm_msg_t *msg)\r
-{\r
-       dp_ib_cm_handle_t acm;\r
-\r
-       /* Allocate accept CM and setup passive references */\r
-       if ((acm = dapls_ib_cm_create(NULL)) == NULL) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN, " accept: ERR cm_create\n");\r
-               return;\r
-       }\r
-\r
-       /* dest CM info from CR msg, source CM info from listen */\r
-       acm->sp = cm->sp;\r
-       acm->hca = cm->hca;\r
-       acm->msg.dport = msg->sport;\r
-       acm->msg.dqpn = msg->sqpn;\r
-       acm->msg.sport = cm->msg.sport; \r
-       acm->msg.sqpn = cm->msg.sqpn;\r
-       acm->msg.p_size = msg->p_size;\r
-\r
-       /* CR saddr is CM daddr info, need EP for local saddr */\r
-       dapl_os_memcpy(&acm->msg.daddr, &msg->saddr, sizeof(union dcm_addr));\r
-       \r
-       dapl_log(DAPL_DBG_TYPE_CM,\r
-                " accept: DST port=%d lid=%x, iqp=%x, psize=%d\n",\r
-                ntohs(acm->msg.dport), ntohs(acm->msg.daddr.ib.lid), \r
-                htonl(acm->msg.daddr.ib.qpn), htons(acm->msg.p_size));\r
-\r
-       /* validate private data size before reading */\r
-       if (ntohs(msg->p_size) > DCM_MAX_PDATA_SIZE) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN, " accept: psize (%d) wrong\n",\r
-                        ntohs(msg->p_size));\r
-               goto bail;\r
-       }\r
-\r
-       /* read private data into cm_handle if any present */\r
-       if (msg->p_size) \r
-               dapl_os_memcpy(acm->msg.p_data, \r
-                              msg->p_data, ntohs(msg->p_size));\r
-               \r
-       acm->state = DCM_ACCEPTING;\r
-       ucm_queue_conn(acm);\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       if (acm->msg.daddr.ib.qp_type == IBV_QPT_UD) {\r
-               DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-\r
-               /* post EVENT, modify_qp created ah */\r
-               xevent.status = 0;\r
-               xevent.type = DAT_IB_UD_CONNECT_REQUEST;\r
-\r
-               dapls_evd_post_cr_event_ext(acm->sp,\r
-                                           DAT_IB_UD_CONNECTION_REQUEST_EVENT,\r
-                                           acm,\r
-                                           (DAT_COUNT)ntohs(acm->msg.p_size),\r
-                                           (DAT_PVOID *)acm->msg.p_data,\r
-                                           (DAT_PVOID *)&xevent);\r
-       } else\r
-#endif\r
-               /* trigger CR event and return SUCCESS */\r
-               dapls_cr_callback(acm,\r
-                                 IB_CME_CONNECTION_REQUEST_PENDING,\r
-                                 acm->msg.p_data, ntohs(msg->p_size), acm->sp);\r
-       return;\r
-\r
-bail:\r
-       /* free cm object */\r
-       dapls_ib_cm_free(acm, NULL);\r
-       return;\r
-}\r
-\r
-/*\r
- * PASSIVE: read RTU from active peer, post CONN event\r
- */\r
-static void ucm_accept_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg)\r
-{\r
-       dapl_os_lock(&cm->lock);\r
-       if ((ntohs(msg->op) != DCM_RTU) || (cm->state != DCM_RTU_PENDING)) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN, \r
-                        " accept_rtu: UNEXPECTED op, state:"\r
-                        " op %d, st %s <- lid %x iqp %x sport %d\n", \r
-                        ntohs(msg->op), dapl_cm_state_str(cm->state), \r
-                        ntohs(msg->saddr.ib.lid), ntohl(msg->saddr.ib.qpn), \r
-                        ntohs(msg->sport));\r
-               dapl_os_unlock(&cm->lock);\r
-               goto bail;\r
-       }\r
-       cm->state = DCM_CONNECTED;\r
-       dapl_os_unlock(&cm->lock);\r
-       \r
-       /* final data exchange if remote QP state is good to go */\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " PASSIVE: connected!\n");\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       if (cm->msg.saddr.ib.qp_type == IBV_QPT_UD) {\r
-               DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-               uint16_t lid = ntohs(cm->msg.daddr.ib.lid);\r
-               \r
-               /* post EVENT, modify_qp, AH already created, ucm msg */\r
-               xevent.status = 0;\r
-               xevent.type = DAT_IB_UD_PASSIVE_REMOTE_AH;\r
-               xevent.remote_ah.qpn = ntohl(cm->msg.daddr.ib.qpn);\r
-               xevent.remote_ah.ah = dapls_create_ah(cm->hca, \r
-                                                     cm->ep->qp_handle->pd, \r
-                                                     cm->ep->qp_handle, \r
-                                                     htons(lid), \r
-                                                     NULL);\r
-               if (xevent.remote_ah.ah == NULL) {\r
-                       dapl_log(DAPL_DBG_TYPE_ERR,\r
-                                " accept_rtu: ERR create_ah"\r
-                                " for qpn 0x%x lid 0x%x\n",\r
-                                xevent.remote_ah.qpn, lid);\r
-                       goto bail;\r
-               }\r
-               cm->ah = xevent.remote_ah.ah; /* keep ref to destroy */\r
-               dapl_os_memcpy(&xevent.remote_ah.ia_addr,\r
-                              &cm->msg.daddr,\r
-                               sizeof(union dcm_addr));\r
-\r
-               /* remote ia_addr reference includes ucm qpn, not IB qpn */\r
-               ((union dcm_addr*)\r
-                       &xevent.remote_ah.ia_addr)->ib.qpn = cm->msg.dqpn;\r
-\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                            " PASSIVE: UD xevent ah %p qpn 0x%x lid 0x%x\n",\r
-                            xevent.remote_ah.ah, xevent.remote_ah.qpn, lid);\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                            " PASSIVE: UD xevent ia_addr qp_type %d"\r
-                            " lid 0x%x qpn 0x%x gid 0x"F64x" 0x"F64x" \n",\r
-                            ((union dcm_addr*)\r
-                               &xevent.remote_ah.ia_addr)->ib.qp_type,\r
-                            ntohs(((union dcm_addr*)\r
-                               &xevent.remote_ah.ia_addr)->ib.lid),\r
-                            ntohl(((union dcm_addr*)\r
-                               &xevent.remote_ah.ia_addr)->ib.qpn),\r
-                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[0]),\r
-                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[8]));\r
-\r
-               dapls_evd_post_connection_event_ext(\r
-                               (DAPL_EVD *)cm->ep->param.connect_evd_handle,\r
-                               DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED,\r
-                               (DAT_EP_HANDLE)cm->ep,\r
-                               (DAT_COUNT)ntohs(cm->msg.p_size),\r
-                               (DAT_PVOID *)cm->msg.p_data,\r
-                               (DAT_PVOID *)&xevent);\r
-\r
-                /* done with CM object, don't destroy cm, need pdata */\r
-               dapl_os_lock(&cm->lock);\r
-                       cm->state = DCM_RELEASED;\r
-               dapl_os_unlock(&cm->lock);\r
-       } else {\r
-#endif\r
-               cm->ep->cm_handle = cm; /* only RC, multi CR's on UD */\r
-               dapls_cr_callback(cm, IB_CME_CONNECTED, NULL, 0, cm->sp);\r
-       }\r
-       return;\r
-bail:\r
-       if (cm->msg.saddr.ib.qp_type != IBV_QPT_UD) \r
-               dapls_ib_reinit_ep(cm->ep);     /* reset QP state */\r
-       dapls_ib_cm_free(cm, cm->ep);\r
-       dapls_cr_callback(cm, IB_CME_LOCAL_FAILURE, NULL, 0, cm->sp);\r
-}\r
-\r
-/*\r
- * PASSIVE: user accepted, send reply message with pdata\r
- */\r
-static int ucm_reply(dp_ib_cm_handle_t cm)\r
-{\r
-       dapl_os_lock(&cm->lock);\r
-       if (cm->state != DCM_RTU_PENDING) {\r
-               dapl_os_unlock(&cm->lock);\r
-               return -1;\r
-       }\r
-\r
-       if (cm->retries == cm->hca->ib_trans.retries) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR, \r
-                        " CM_REPLY: RETRIES EXHAUSTED"\r
-                        " 0x%x %d 0x%x -> 0x%x %d 0x%x\n",\r
-                        htons(cm->msg.saddr.ib.lid), \r
-                        htons(cm->msg.sport), \r
-                        htonl(cm->msg.saddr.ib.qpn), \r
-                        htons(cm->msg.daddr.ib.lid), \r
-                        htons(cm->msg.dport), \r
-                        htonl(cm->msg.daddr.ib.qpn));\r
-                       \r
-               dapl_os_unlock(&cm->lock);\r
-#ifdef DAPL_COUNTERS\r
-               /* called from check_timers in cm_thread, cm lock held */\r
-               if (g_dapl_dbg_type & DAPL_DBG_TYPE_CM_LIST) {\r
-                       dapl_os_unlock(&cm->hca->ib_trans.lock);\r
-                       dapls_print_cm_list(dapl_llist_peek_head(&cm->hca->ia_list_head));\r
-                       dapl_os_lock(&cm->hca->ib_trans.lock);\r
-               }\r
-#endif\r
-#ifdef DAT_EXTENSIONS\r
-               if (cm->msg.saddr.ib.qp_type == IBV_QPT_UD) {\r
-                       DAT_IB_EXTENSION_EVENT_DATA xevent;\r
-                                       \r
-                       /* post REJECT event with CONN_REQ p_data */\r
-                       xevent.status = 0;\r
-                       xevent.type = DAT_IB_UD_CONNECT_ERROR;\r
-                                       \r
-                       dapls_evd_post_connection_event_ext(\r
-                               (DAPL_EVD *)cm->ep->param.connect_evd_handle,\r
-                               DAT_IB_UD_CONNECTION_ERROR_EVENT,\r
-                               (DAT_EP_HANDLE)cm->ep,\r
-                               (DAT_COUNT)ntohs(cm->msg.p_size),\r
-                               (DAT_PVOID *)cm->msg.p_data,\r
-                               (DAT_PVOID *)&xevent);\r
-               } else \r
-#endif\r
-                       dapls_cr_callback(cm, IB_CME_LOCAL_FAILURE, \r
-                                         NULL, 0, cm->sp);\r
-               return -1;\r
-       }\r
-       dapl_os_get_time(&cm->timer); /* RTU expected */\r
-       dapl_os_unlock(&cm->lock);\r
-       if (ucm_send(&cm->hca->ib_trans, &cm->msg, cm->p_data, cm->p_size))             \r
-               return -1;\r
-\r
-       return 0;\r
-}\r
-\r
-\r
-/*\r
- * PASSIVE: consumer accept, send local QP information, private data, \r
- * queue on work thread to receive RTU information to avoid blocking\r
- * user thread. \r
- */\r
-DAT_RETURN\r
-dapli_accept_usr(DAPL_EP *ep, DAPL_CR *cr, DAT_COUNT p_size, DAT_PVOID p_data)\r
-{\r
-       DAPL_IA *ia = ep->header.owner_ia;\r
-       dp_ib_cm_handle_t cm = cr->ib_cm_handle;\r
-\r
-       if (p_size > DCM_MAX_PDATA_SIZE)\r
-               return DAT_LENGTH_ERROR;\r
-\r
-       dapl_os_lock(&cm->lock);\r
-       if (cm->state != DCM_ACCEPTING) {\r
-               dapl_os_unlock(&cm->lock);\r
-               return DAT_INVALID_STATE;\r
-       }\r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " ACCEPT_USR: remote lid=%x"\r
-                    " iqp=%x qp_type %d, psize=%d\n",\r
-                    ntohs(cm->msg.daddr.ib.lid),\r
-                    ntohl(cm->msg.daddr.ib.qpn), cm->msg.daddr.ib.qp_type, \r
-                    p_size);\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
-                    " ACCEPT_USR: remote GID subnet %016llx id %016llx\n",\r
-                    (unsigned long long)\r
-                    htonll(*(uint64_t*)&cm->msg.daddr.ib.gid[0]),\r
-                    (unsigned long long)\r
-                    htonll(*(uint64_t*)&cm->msg.daddr.ib.gid[8]));\r
-\r
-#ifdef DAT_EXTENSIONS\r
-       if (cm->msg.daddr.ib.qp_type == IBV_QPT_UD &&\r
-           ep->qp_handle->qp_type != IBV_QPT_UD) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                            " ACCEPT_USR: ERR remote QP is UD,"\r
-                            ", but local QP is not\n");\r
-               return (DAT_INVALID_HANDLE | DAT_INVALID_HANDLE_EP);\r
-       }\r
-#endif\r
-\r
-       /* modify QP to RTR and then to RTS with remote info already read */\r
-       dapl_os_lock(&ep->header.lock);\r
-       if (dapls_modify_qp_state(ep->qp_handle,\r
-                                 IBV_QPS_RTR, \r
-                                 cm->msg.daddr.ib.qpn,\r
-                                 cm->msg.daddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_USR: QPS_RTR ERR %s -> lid %x qpn %x\n",\r
-                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),\r
-                        ntohl(cm->msg.daddr.ib.qpn));\r
-               dapl_os_unlock(&ep->header.lock);\r
-               goto bail;\r
-       }\r
-       if (dapls_modify_qp_state(ep->qp_handle,\r
-                                 IBV_QPS_RTS, \r
-                                 cm->msg.daddr.ib.qpn,\r
-                                 cm->msg.daddr.ib.lid,\r
-                                 NULL) != DAT_SUCCESS) {\r
-               dapl_log(DAPL_DBG_TYPE_ERR,\r
-                        " ACCEPT_USR: QPS_RTS ERR %s -> lid %x qpn %x\n",\r
-                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),\r
-                        ntohl(cm->msg.daddr.ib.qpn));\r
-               dapl_os_unlock(&ep->header.lock);\r
-               goto bail;\r
-       }\r
-       dapl_os_unlock(&ep->header.lock);\r
-\r
-       /* save remote address information */\r
-       dapl_os_memcpy(&ep->remote_ia_address,\r
-                      &cm->msg.saddr, sizeof(union dcm_addr));\r
-\r
-       /* setup local QP info and type from EP, copy pdata, for reply */\r
-       cm->msg.op = htons(DCM_REP);\r
-       cm->msg.saddr.ib.qpn = htonl(ep->qp_handle->qp_num);\r
-       cm->msg.saddr.ib.qp_type = ep->qp_handle->qp_type;\r
-       cm->msg.saddr.ib.lid = cm->hca->ib_trans.addr.ib.lid; \r
-       dapl_os_memcpy(&cm->msg.saddr.ib.gid[0],\r
-                      &cm->hca->ib_trans.addr.ib.gid, 16); \r
-\r
-       /* \r
-        * UD: deliver p_data with REQ and EST event, keep REQ p_data in \r
-        * cm->msg.p_data and save REPLY accept data in cm->p_data for retries \r
-        */\r
-       cm->p_size = p_size;\r
-       dapl_os_memcpy(&cm->p_data, p_data, p_size);\r
-\r
-       /* save state and setup valid reference to EP, HCA */\r
-       dapl_os_lock(&cm->lock);\r
-       cm->ep = ep;\r
-       cm->hca = ia->hca_ptr;\r
-       cm->state = DCM_RTU_PENDING;\r
-       dapl_os_get_time(&cm->timer); /* RTU expected */\r
-       dapl_os_unlock(&cm->lock);\r
-\r
-       if (ucm_reply(cm))\r
-               goto bail;\r
-       \r
-       dapl_dbg_log(DAPL_DBG_TYPE_CM, " PASSIVE: accepted!\n");\r
-       dapls_thread_signal(&cm->hca->ib_trans.signal);\r
-       return DAT_SUCCESS;\r
-bail:\r
-       if (cm->msg.saddr.ib.qp_type != IBV_QPT_UD)\r
-               dapls_ib_reinit_ep(ep);\r
-\r
-       dapls_ib_cm_free(cm, ep);\r
-       return DAT_INTERNAL_ERROR;\r
-}\r
-\r
-\r
-/*\r
- * dapls_ib_connect\r
- *\r
- * Initiate a connection with the passive listener on another node\r
- *\r
- * Input:\r
- *     ep_handle,\r
- *     remote_ia_address,\r
- *     remote_conn_qual,\r
- *     prd_size                size of private data and structure\r
- *     prd_prt                 pointer to private data structure\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,\r
-                IN DAT_IA_ADDRESS_PTR r_addr,\r
-                IN DAT_CONN_QUAL r_psp,\r
-                IN DAT_COUNT p_size, IN void *p_data)\r
-{\r
-       DAPL_EP *ep = (DAPL_EP *)ep_handle;\r
-       dp_ib_cm_handle_t cm;\r
-       \r
-       /* create CM object, initialize SRC info from EP */\r
-       cm = dapls_ib_cm_create(ep);\r
-       if (cm == NULL)\r
-               return DAT_INSUFFICIENT_RESOURCES;\r
-\r
-       /* remote hca and port: lid, gid, network order */\r
-       dapl_os_memcpy(&cm->msg.daddr, r_addr, sizeof(union dcm_addr));\r
-\r
-       /* remote uCM information, comes from consumer provider r_addr */\r
-       cm->msg.dport = htons((uint16_t)r_psp);\r
-       cm->msg.dqpn = cm->msg.daddr.ib.qpn;\r
-       cm->msg.daddr.ib.qpn = 0; /* don't have a remote qpn until reply */\r
-       \r
-       if (p_size) {\r
-               cm->msg.p_size = htons(p_size);\r
-               dapl_os_memcpy(&cm->msg.p_data, p_data, p_size);\r
-       }\r
-       \r
-       cm->state = DCM_REP_PENDING;\r
-\r
-       /* build connect request, send to remote CM based on r_addr info */\r
-       return(dapli_cm_connect(ep, cm));\r
-}\r
-\r
-/*\r
- * dapls_ib_disconnect\r
- *\r
- * Disconnect an EP\r
- *\r
- * Input:\r
- *     ep_handle,\r
- *     disconnect_flags\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- */\r
-DAT_RETURN\r
-dapls_ib_disconnect(IN DAPL_EP *ep, IN DAT_CLOSE_FLAGS close_flags)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "dapls_ib_disconnect(ep_handle %p ....)\n", ep);\r
-\r
-       if (ep->cm_handle == NULL ||\r
-           ep->param.ep_state == DAT_EP_STATE_DISCONNECTED)\r
-               return DAT_SUCCESS;\r
-       else\r
-               return (dapli_cm_disconnect(ep->cm_handle));\r
-}\r
-\r
-/*\r
- * dapls_ib_disconnect_clean\r
- *\r
- * Clean up outstanding connection data. This routine is invoked\r
- * after the final disconnect callback has occurred. Only on the\r
- * ACTIVE side of a connection. It is also called if dat_ep_connect\r
- * times out using the consumer supplied timeout value.\r
- *\r
- * Input:\r
- *     ep_ptr          DAPL_EP\r
- *     active          Indicates active side of connection\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     void\r
- *\r
- */\r
-void\r
-dapls_ib_disconnect_clean(IN DAPL_EP *ep,\r
-                         IN DAT_BOOLEAN active,\r
-                         IN const ib_cm_events_t ib_cm_event)\r
-{\r
-       /* NOTE: SCM will only initialize cm_handle with RC type\r
-        * \r
-        * For UD there can many in-flight CR's so you \r
-        * cannot cleanup timed out CR's with EP reference \r
-        * alone since they share the same EP. The common\r
-        * code that handles connection timeout logic needs \r
-        * updated for UD support.\r
-        */\r
-       if (ep->cm_handle)\r
-               dapls_ib_cm_free(ep->cm_handle, ep);\r
-\r
-       return;\r
-}\r
-\r
-/*\r
- * dapl_ib_setup_conn_listener\r
- *\r
- * Have the CM set up a connection listener.\r
- *\r
- * Input:\r
- *     ibm_hca_handle          HCA handle\r
- *     qp_handle                       QP handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *     DAT_CONN_QUAL_UNAVAILBLE\r
- *     DAT_CONN_QUAL_IN_USE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_setup_conn_listener(IN DAPL_IA *ia, \r
-                            IN DAT_UINT64 sid, \r
-                            IN DAPL_SP *sp)\r
-{\r
-       ib_cm_srvc_handle_t cm = NULL;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " listen(ia %p ServiceID %d sp %p)\n",\r
-                    ia, sid, sp);\r
-\r
-       /* reserve local port, then allocate CM object */\r
-       if (!ucm_get_port(&ia->hca_ptr->ib_trans, (uint16_t)sid)) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_WARN,\r
-                            " listen: ERROR %s on conn_qual 0x%x\n",\r
-                            strerror(errno), sid);\r
-               return DAT_CONN_QUAL_IN_USE;\r
-       }\r
-\r
-       /* cm_create will setup saddr for listen server */\r
-       if ((cm = dapls_ib_cm_create(NULL)) == NULL)\r
-               return DAT_INSUFFICIENT_RESOURCES;\r
-\r
-       /* LISTEN: init DST address and QP info to local CM server info */\r
-       cm->sp = sp;\r
-       cm->hca = ia->hca_ptr;\r
-       cm->msg.sport = htons((uint16_t)sid);\r
-       cm->msg.sqpn = htonl(ia->hca_ptr->ib_trans.qp->qp_num);\r
-       cm->msg.saddr.ib.qp_type = IBV_QPT_UD;\r
-        cm->msg.saddr.ib.lid = ia->hca_ptr->ib_trans.addr.ib.lid; \r
-       dapl_os_memcpy(&cm->msg.saddr.ib.gid[0],\r
-                      &cm->hca->ib_trans.addr.ib.gid, 16); \r
-       \r
-       /* save cm_handle reference in service point */\r
-       sp->cm_srvc_handle = cm;\r
-\r
-       /* queue up listen socket to process inbound CR's */\r
-       cm->state = DCM_LISTEN;\r
-       ucm_queue_listen(cm);\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * dapl_ib_remove_conn_listener\r
- *\r
- * Have the CM remove a connection listener.\r
- *\r
- * Input:\r
- *     ia_handle               IA handle\r
- *     ServiceID               IB Channel Service ID\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_STATE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_remove_conn_listener(IN DAPL_IA *ia, IN DAPL_SP *sp)\r
-{\r
-       ib_cm_srvc_handle_t cm = sp->cm_srvc_handle;\r
-       ib_hca_transport_t *tp = &ia->hca_ptr->ib_trans;\r
-\r
-       /* free cm_srvc_handle and port, and mark CM for cleanup */\r
-       if (cm) {\r
-               dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " remove_listener(ia %p sp %p cm %p psp=%d)\n",\r
-                    ia, sp, cm, ntohs(cm->msg.dport));\r
-\r
-               sp->cm_srvc_handle = NULL;\r
-               dapl_os_lock(&cm->lock);\r
-               ucm_free_port(tp, ntohs(cm->msg.dport));\r
-               cm->msg.dport = 0;\r
-               cm->state = DCM_DESTROY;\r
-               dapl_os_unlock(&cm->lock);\r
-               ucm_dequeue_listen(cm);\r
-               dapl_os_lock_destroy(&cm->lock);\r
-               dapl_os_free(cm, sizeof(*cm));\r
-       }\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_accept_connection\r
- *\r
- * Perform necessary steps to accept a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *     ep_handle\r
- *     private_data_size\r
- *     private_data\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INSUFFICIENT_RESOURCES\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,\r
-                          IN DAT_EP_HANDLE ep_handle,\r
-                          IN DAT_COUNT p_size, \r
-                          IN const DAT_PVOID p_data)\r
-{\r
-       DAPL_CR *cr = (DAPL_CR *)cr_handle;\r
-       DAPL_EP *ep = (DAPL_EP *)ep_handle;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " accept_connection(cr %p ep %p prd %p,%d)\n",\r
-                    cr, ep, p_data, p_size);\r
-\r
-       /* allocate and attach a QP if necessary */\r
-       if (ep->qp_state == DAPL_QP_STATE_UNATTACHED) {\r
-               DAT_RETURN status;\r
-               status = dapls_ib_qp_alloc(ep->header.owner_ia,\r
-                                          ep, ep);\r
-               if (status != DAT_SUCCESS)\r
-                       return status;\r
-       }\r
-       return (dapli_accept_usr(ep, cr, p_size, p_data));\r
-}\r
-\r
-/*\r
- * dapls_ib_reject_connection\r
- *\r
- * Reject a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INTERNAL_ERROR\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_reject_connection(IN dp_ib_cm_handle_t cm,\r
-                          IN int reason,\r
-                          IN DAT_COUNT psize, IN const DAT_PVOID pdata)\r
-{\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    " reject(cm %p reason %x, pdata %p, psize %d)\n",\r
-                    cm, reason, pdata, psize);\r
-\r
-        if (psize > DCM_MAX_PDATA_SIZE)\r
-                return DAT_LENGTH_ERROR;\r
-\r
-       /* cr_thread will destroy CR, update saddr lid, gid, qp_type info */\r
-       dapl_os_lock(&cm->lock);\r
-       cm->state = DCM_REJECTED;\r
-       cm->msg.saddr.ib.lid = cm->hca->ib_trans.addr.ib.lid; \r
-       cm->msg.saddr.ib.qp_type = cm->msg.daddr.ib.qp_type;\r
-       dapl_os_memcpy(&cm->msg.saddr.ib.gid[0],\r
-                      &cm->hca->ib_trans.addr.ib.gid, 16); \r
-       cm->msg.op = htons(DCM_REJ_USER);\r
-       \r
-       if (ucm_send(&cm->hca->ib_trans, &cm->msg, pdata, psize)) {\r
-               dapl_log(DAPL_DBG_TYPE_WARN,\r
-                        " cm_reject: ERR: %s\n", strerror(errno));\r
-               return DAT_INTERNAL_ERROR;\r
-       }\r
-       dapl_os_unlock(&cm->lock);\r
-               \r
-       /* cleanup and destroy CM resources */ \r
-       dapls_ib_cm_free(cm, NULL);\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-/*\r
- * dapls_ib_cm_remote_addr\r
- *\r
- * Obtain the remote IP address given a connection\r
- *\r
- * Input:\r
- *     cr_handle\r
- *\r
- * Output:\r
- *     remote_ia_address: where to place the remote address\r
- *\r
- * Returns:\r
- *     DAT_SUCCESS\r
- *     DAT_INVALID_HANDLE\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle,\r
-                       OUT DAT_SOCK_ADDR6 * remote_ia_address)\r
-{\r
-       DAPL_HEADER *header;\r
-       dp_ib_cm_handle_t ib_cm_handle;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
-                    "dapls_ib_cm_remote_addr(dat_handle %p, ....)\n",\r
-                    dat_handle);\r
-\r
-       header = (DAPL_HEADER *) dat_handle;\r
-\r
-       if (header->magic == DAPL_MAGIC_EP)\r
-               ib_cm_handle = ((DAPL_EP *) dat_handle)->cm_handle;\r
-       else if (header->magic == DAPL_MAGIC_CR)\r
-               ib_cm_handle = ((DAPL_CR *) dat_handle)->ib_cm_handle;\r
-       else\r
-               return DAT_INVALID_HANDLE;\r
-\r
-       dapl_os_memcpy(remote_ia_address,\r
-                      &ib_cm_handle->msg.daddr, sizeof(DAT_SOCK_ADDR6));\r
-\r
-       return DAT_SUCCESS;\r
-}\r
-\r
-int dapls_ib_private_data_size(\r
-       IN DAPL_HCA *hca_ptr)\r
-{\r
-       return DCM_MAX_PDATA_SIZE;\r
-}\r
-\r
-/*\r
- * Map all socket CM event codes to the DAT equivelent.\r
- */\r
-#define DAPL_IB_EVENT_CNT      10\r
-\r
-static struct ib_cm_event_map {\r
-       const ib_cm_events_t ib_cm_event;\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-} ib_cm_event_map[DAPL_IB_EVENT_CNT] = {\r
-/* 00 */ {IB_CME_CONNECTED, \r
-         DAT_CONNECTION_EVENT_ESTABLISHED},\r
-/* 01 */ {IB_CME_DISCONNECTED, \r
-         DAT_CONNECTION_EVENT_DISCONNECTED},\r
-/* 02 */ {IB_CME_DISCONNECTED_ON_LINK_DOWN,\r
-         DAT_CONNECTION_EVENT_DISCONNECTED},\r
-/* 03 */ {IB_CME_CONNECTION_REQUEST_PENDING, \r
-         DAT_CONNECTION_REQUEST_EVENT},\r
-/* 04 */ {IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,\r
-         DAT_CONNECTION_REQUEST_EVENT},\r
-/* 05 */ {IB_CME_DESTINATION_REJECT,\r
-         DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
-/* 06 */ {IB_CME_DESTINATION_REJECT_PRIVATE_DATA,\r
-         DAT_CONNECTION_EVENT_PEER_REJECTED},\r
-/* 07 */ {IB_CME_DESTINATION_UNREACHABLE, \r
-         DAT_CONNECTION_EVENT_UNREACHABLE},\r
-/* 08 */ {IB_CME_TOO_MANY_CONNECTION_REQUESTS,\r
-         DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
-/* 09 */ {IB_CME_LOCAL_FAILURE, \r
-         DAT_CONNECTION_EVENT_BROKEN}\r
-};\r
-\r
-/*\r
- * dapls_ib_get_cm_event\r
- *\r
- * Return a DAT connection event given a provider CM event.\r
- *\r
- * Input:\r
- *     dat_event_num   DAT event we need an equivelent CM event for\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     ib_cm_event of translated DAPL value\r
- */\r
-DAT_EVENT_NUMBER\r
-dapls_ib_get_dat_event(IN const ib_cm_events_t ib_cm_event,\r
-                      IN DAT_BOOLEAN active)\r
-{\r
-       DAT_EVENT_NUMBER dat_event_num;\r
-       int i;\r
-\r
-       if (ib_cm_event > IB_CME_LOCAL_FAILURE)\r
-               return (DAT_EVENT_NUMBER) 0;\r
-\r
-       dat_event_num = 0;\r
-       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {\r
-               if (ib_cm_event == ib_cm_event_map[i].ib_cm_event) {\r
-                       dat_event_num = ib_cm_event_map[i].dat_event_num;\r
-                       break;\r
-               }\r
-       }\r
-       dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
-                    "dapls_ib_get_dat_event: event translate(%s) ib=0x%x dat=0x%x\n",\r
-                    active ? "active" : "passive", ib_cm_event, dat_event_num);\r
-\r
-       return dat_event_num;\r
-}\r
-\r
-/*\r
- * dapls_ib_get_dat_event\r
- *\r
- * Return a DAT connection event given a provider CM event.\r
- * \r
- * Input:\r
- *     ib_cm_event     event provided to the dapl callback routine\r
- *     active          switch indicating active or passive connection\r
- *\r
- * Output:\r
- *     none\r
- *\r
- * Returns:\r
- *     DAT_EVENT_NUMBER of translated provider value\r
- */\r
-ib_cm_events_t dapls_ib_get_cm_event(IN DAT_EVENT_NUMBER dat_event_num)\r
-{\r
-       ib_cm_events_t ib_cm_event;\r
-       int i;\r
-\r
-       ib_cm_event = 0;\r
-       for (i = 0; i < DAPL_IB_EVENT_CNT; i++) {\r
-               if (dat_event_num == ib_cm_event_map[i].dat_event_num) {\r
-                       ib_cm_event = ib_cm_event_map[i].ib_cm_event;\r
-                       break;\r
-               }\r
-       }\r
-       return ib_cm_event;\r
-}\r
-\r
-#if defined(_WIN32) || defined(_WIN64)\r
-\r
-void cm_thread(void *arg)\r
-{\r
-       struct dapl_hca *hca = arg;\r
-       dp_ib_cm_handle_t cm, next;\r
-       DWORD time_ms;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread: ENTER hca %p\n", hca);\r
-       dapl_os_lock(&hca->ib_trans.lock);\r
-       for (hca->ib_trans.cm_state = IB_THREAD_RUN;\r
-            hca->ib_trans.cm_state == IB_THREAD_RUN ||\r
-            !dapl_llist_is_empty(&hca->ib_trans.list);\r
-            dapl_os_lock(&hca->ib_trans.lock)) {\r
-\r
-               time_ms = INFINITE;\r
-               CompSetZero(&hca->ib_trans.signal.set);\r
-               CompSetAdd(&hca->ib_hca_handle->channel, &hca->ib_trans.signal.set);\r
-               CompSetAdd(&hca->ib_trans.rch->comp_channel, &hca->ib_trans.signal.set);\r
-               CompSetAdd(&hca->ib_trans.ib_cq->comp_channel, &hca->ib_trans.signal.set);\r
-\r
-               next = dapl_llist_is_empty(&hca->ib_trans.list) ? NULL :\r
-                       dapl_llist_peek_head(&hca->ib_trans.list);\r
-\r
-               while (next) {\r
-                       cm = next;\r
-                       next = dapl_llist_next_entry(&hca->ib_trans.list,\r
-                                                    (DAPL_LLIST_ENTRY *)&cm->entry);\r
-                       dapl_os_lock(&cm->lock);\r
-                       if (cm->state == DCM_DESTROY || \r
-                           hca->ib_trans.cm_state != IB_THREAD_RUN) {\r
-                               dapl_llist_remove_entry(&hca->ib_trans.list,\r
-                                                       (DAPL_LLIST_ENTRY *)&cm->entry);\r
-                               dapl_os_unlock(&cm->lock);\r
-                               dapl_os_lock_destroy(&cm->lock);\r
-                               dapl_os_free(cm, sizeof(*cm));\r
-                               continue;\r
-                       }\r
-                       dapl_os_unlock(&cm->lock);\r
-                       ucm_check_timers(cm, &time_ms);\r
-               }\r
-\r
-               dapl_os_unlock(&hca->ib_trans.lock);\r
-\r
-               hca->ib_hca_handle->channel.Milliseconds = time_ms;\r
-               hca->ib_trans.rch->comp_channel.Milliseconds = time_ms;\r
-               hca->ib_trans.ib_cq->comp_channel.Milliseconds = time_ms;\r
-               CompSetPoll(&hca->ib_trans.signal.set, time_ms);\r
-\r
-               hca->ib_hca_handle->channel.Milliseconds = 0;\r
-               hca->ib_trans.rch->comp_channel.Milliseconds = 0;\r
-               hca->ib_trans.ib_cq->comp_channel.Milliseconds = 0;\r
-\r
-               ucm_recv(&hca->ib_trans);\r
-               ucm_async_event(hca);\r
-               dapli_cq_event_cb(&hca->ib_trans);\r
-       }\r
-\r
-       dapl_os_unlock(&hca->ib_trans.lock);\r
-       hca->ib_trans.cm_state = IB_THREAD_EXIT;\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread(hca %p) exit\n", hca);\r
-}\r
-\r
-#else                          // _WIN32 || _WIN64\r
-\r
-void cm_thread(void *arg)\r
-{\r
-       struct dapl_hca *hca = arg;\r
-       dp_ib_cm_handle_t cm, next;\r
-       struct dapl_fd_set *set;\r
-       char rbuf[2];\r
-       int time_ms;\r
-\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread: ENTER hca %p\n", hca);\r
-       set = dapl_alloc_fd_set();\r
-       if (!set)\r
-               goto out;\r
-\r
-       dapl_os_lock(&hca->ib_trans.lock);\r
-       hca->ib_trans.cm_state = IB_THREAD_RUN;\r
-\r
-       while (1) {\r
-               time_ms = -1; /* reset to blocking */\r
-               dapl_fd_zero(set);\r
-               dapl_fd_set(hca->ib_trans.signal.scm[0], set, DAPL_FD_READ);    \r
-               dapl_fd_set(hca->ib_hca_handle->async_fd, set, DAPL_FD_READ);\r
-               dapl_fd_set(hca->ib_trans.rch->fd, set, DAPL_FD_READ);\r
-               dapl_fd_set(hca->ib_trans.ib_cq->fd, set, DAPL_FD_READ);\r
-               \r
-               if (!dapl_llist_is_empty(&hca->ib_trans.list))\r
-                       next = dapl_llist_peek_head(&hca->ib_trans.list);\r
-               else\r
-                       next = NULL;\r
-\r
-               while (next) {\r
-                       cm = next;\r
-                       next = dapl_llist_next_entry(\r
-                                       &hca->ib_trans.list,\r
-                                       (DAPL_LLIST_ENTRY *)&cm->entry);\r
-                       dapl_os_lock(&cm->lock);\r
-                       if (cm->state == DCM_DESTROY || \r
-                           hca->ib_trans.cm_state != IB_THREAD_RUN) {\r
-                               dapl_llist_remove_entry(\r
-                                       &hca->ib_trans.list,\r
-                                       (DAPL_LLIST_ENTRY *)&cm->entry);\r
-                               dapl_os_unlock(&cm->lock);\r
-                               dapl_os_lock_destroy(&cm->lock);\r
-                               dapl_os_free(cm, sizeof(*cm));\r
-                               continue;\r
-                       }\r
-                       dapl_os_unlock(&cm->lock);\r
-                       ucm_check_timers(cm, &time_ms);\r
-               }\r
-\r
-               /* set to exit and all resources destroyed */\r
-               if ((hca->ib_trans.cm_state != IB_THREAD_RUN) &&\r
-                   (dapl_llist_is_empty(&hca->ib_trans.list)))\r
-                       break;\r
-\r
-               dapl_os_unlock(&hca->ib_trans.lock);\r
-               dapl_select(set, time_ms);\r
-\r
-               /* Process events: CM, ASYNC, NOTIFY THREAD */\r
-               if (dapl_poll(hca->ib_trans.rch->fd, \r
-                             DAPL_FD_READ) == DAPL_FD_READ) {\r
-                       ucm_recv(&hca->ib_trans);\r
-               }\r
-               if (dapl_poll(hca->ib_hca_handle->async_fd, \r
-                             DAPL_FD_READ) == DAPL_FD_READ) {\r
-                       ucm_async_event(hca);\r
-               }\r
-               if (dapl_poll(hca->ib_trans.ib_cq->fd, \r
-                             DAPL_FD_READ) == DAPL_FD_READ) {\r
-                       dapli_cq_event_cb(&hca->ib_trans);\r
-               }\r
-               while (dapl_poll(hca->ib_trans.signal.scm[0], \r
-                                DAPL_FD_READ) == DAPL_FD_READ) {\r
-                       recv(hca->ib_trans.signal.scm[0], rbuf, 2, 0);\r
-               }\r
-\r
-               dapl_os_lock(&hca->ib_trans.lock);\r
-               \r
-               /* set to exit and all resources destroyed */\r
-               if ((hca->ib_trans.cm_state != IB_THREAD_RUN) &&\r
-                   (dapl_llist_is_empty(&hca->ib_trans.list)))\r
-                       break;\r
-       }\r
-\r
-       dapl_os_unlock(&hca->ib_trans.lock);\r
-       free(set);\r
-out:\r
-       hca->ib_trans.cm_state = IB_THREAD_EXIT;\r
-       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread(hca %p) exit\n", hca);\r
-}\r
-#endif\r
-\r
-#ifdef DAPL_COUNTERS\r
-/* Debug aid: List all Connections in process and state */\r
-void dapls_print_cm_list(IN DAPL_IA *ia_ptr)\r
-{\r
-       /* Print in process CM's for this IA, if debug type set */\r
-       int i = 0;\r
-       dp_ib_cm_handle_t cm, next_cm;\r
-       struct dapl_llist_entry **list;\r
-       DAPL_OS_LOCK *lock;\r
-       \r
-       /* LISTEN LIST */\r
-       list = &ia_ptr->hca_ptr->ib_trans.llist;\r
-       lock = &ia_ptr->hca_ptr->ib_trans.llock;\r
-\r
-       dapl_os_lock(lock);\r
-       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)list))\r
-               next_cm = dapl_llist_peek_head((DAPL_LLIST_HEAD*)list);\r
-       else\r
-               next_cm = NULL;\r
-\r
-        printf("\n DAPL IA LISTEN/CONNECTIONS IN PROCESS:\n");\r
-       while (next_cm) {\r
-               cm = next_cm;\r
-               next_cm = dapl_llist_next_entry((DAPL_LLIST_HEAD*)list,\r
-                                               (DAPL_LLIST_ENTRY*)&cm->entry);\r
-\r
-               printf( "  LISTEN[%d]: sp %p %s uCM_QP: 0x%x %d 0x%x l_pid %x,%d\n",\r
-                       i, cm->sp, dapl_cm_state_str(cm->state),\r
-                       ntohs(cm->msg.saddr.ib.lid), ntohs(cm->msg.sport),\r
-                       ntohl(cm->msg.sqpn), ntohl(*(DAT_UINT32*)cm->msg.resv), \r
-                       ntohl(*(DAT_UINT32*)cm->msg.resv)); \r
-               i++;\r
-       }\r
-       dapl_os_unlock(lock);\r
-\r
-       /* CONNECTION LIST */\r
-       list = &ia_ptr->hca_ptr->ib_trans.list;\r
-       lock = &ia_ptr->hca_ptr->ib_trans.lock;\r
-\r
-       dapl_os_lock(lock);\r
-       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)list))\r
-               next_cm = dapl_llist_peek_head((DAPL_LLIST_HEAD*)list);\r
-       else\r
-               next_cm = NULL;\r
-\r
-        while (next_cm) {\r
-               cm = next_cm;\r
-               next_cm = dapl_llist_next_entry((DAPL_LLIST_HEAD*)list,\r
-                                               (DAPL_LLIST_ENTRY*)&cm->entry);\r
-\r
-               printf( "  CONN[%d]: ep %p cm %p %s %s"\r
-                       "  %x %x %x %s %x %x %x r_pid %x,%d\n",\r
-                       i, cm->ep, cm,\r
-                       cm->msg.saddr.ib.qp_type == IBV_QPT_RC ? "RC" : "UD",\r
-                       dapl_cm_state_str(cm->state),\r
-                       ntohs(cm->msg.saddr.ib.lid),\r
-                       ntohs(cm->msg.sport),\r
-                       ntohl(cm->msg.saddr.ib.qpn),    \r
-                       cm->sp ? "<-" : "->",\r
-                       ntohs(cm->msg.daddr.ib.lid),\r
-                       ntohs(cm->msg.dport),\r
-                       ntohl(cm->msg.daddr.ib.qpn),\r
-                       ntohs(cm->msg.op) == DCM_REQ ? 0 : ntohl(*(DAT_UINT32*)cm->msg.resv), \r
-                       ntohs(cm->msg.op) == DCM_REQ ? 0 : ntohl(*(DAT_UINT32*)cm->msg.resv)); \r
-               i++;\r
-       }\r
-       printf("\n");\r
-       dapl_os_unlock(lock);\r
-}\r
-#endif\r
+       dapli_cm_dealloc(cm);\r
+}
+
+dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep)
+{
+       dp_ib_cm_handle_t cm;
+
+       /* Allocate CM, init lock, and initialize */
+       if ((cm = dapl_os_alloc(sizeof(*cm))) == NULL)
+               return NULL;
+
+       (void)dapl_os_memzero(cm, sizeof(*cm));
+       if (dapl_os_lock_init(&cm->lock))
+               goto bail;
+       
+       if (dapl_os_wait_object_init(&cm->event)) {
+               dapl_os_lock_destroy(&cm->lock);
+               goto bail;
+       }
+       dapls_cm_acquire(cm);
+
+       cm->msg.ver = htons(DCM_VER);
+       *(DAT_UINT32*)cm->msg.resv = htonl(dapl_os_getpid()); /* exchange PID for debugging */
+       
+       /* ACTIVE: init source address QP info from local EP */
+       if (ep) {
+               DAPL_HCA *hca = ep->header.owner_ia->hca_ptr;
+
+               cm->msg.sport = htons(ucm_get_port(&hca->ib_trans, 0));
+               if (!cm->msg.sport) {
+                       dapl_os_wait_object_destroy(&cm->event);
+                       dapl_os_lock_destroy(&cm->lock);
+                       goto bail;
+               }
+               /* link CM object to EP */
+               dapl_ep_link_cm(ep, cm);
+               cm->hca = hca;
+               cm->ep = ep;
+
+               /* IB info in network order */
+               cm->msg.sqpn = htonl(hca->ib_trans.qp->qp_num); /* ucm */
+               cm->msg.saddr.ib.qpn = htonl(ep->qp_handle->qp_num); /* ep */
+               cm->msg.saddr.ib.qp_type = ep->qp_handle->qp_type;
+                cm->msg.saddr.ib.lid = hca->ib_trans.addr.ib.lid; 
+               dapl_os_memcpy(&cm->msg.saddr.ib.gid[0], 
+                              &hca->ib_trans.addr.ib.gid, 16);
+        }
+       return cm;
+bail:
+       dapl_os_free(cm, sizeof(*cm));
+       return NULL;
+}
+
+/* schedule destruction of CM object */
+void dapli_cm_free(dp_ib_cm_handle_t cm)
+{
+       dapl_os_lock(&cm->lock);
+       cm->state = DCM_FREE;
+       dapls_thread_signal(&cm->hca->ib_trans.signal);
+       dapl_os_unlock(&cm->lock);
+}
+
+/* Blocking, ONLY called from dat_ep_free */
+void dapls_cm_free(dp_ib_cm_handle_t cm)
+{
+       dapl_log(DAPL_DBG_TYPE_CM,
+                " cm_free: cm %p %s ep %p refs=%d\n", 
+                cm, dapl_cm_state_str(cm->state),
+                cm->ep, cm->ref_count);
+       
+       /* free from internal workq, wait until EP is last ref */
+       dapl_os_lock(&cm->lock);
+       cm->state = DCM_FREE;
+       while (cm->ref_count != 1) {
+               dapl_os_unlock(&cm->lock);
+               dapl_os_sleep_usec(10000);
+               dapl_os_lock(&cm->lock);
+       }
+       dapl_os_unlock(&cm->lock);
+
+       /* unlink, dequeue from EP. Final ref so release will destroy */
+       dapl_ep_unlink_cm(cm->ep, cm);
+}
+
+/* ACTIVE/PASSIVE: queue up connection object on CM list */
+static void dapli_queue_conn(dp_ib_cm_handle_t cm)
+{
+       /* add to work queue, list, for cm thread processing */
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm->local_entry);
+       dapl_os_lock(&cm->hca->ib_trans.lock);
+       dapls_cm_acquire(cm);
+       dapl_llist_add_tail(&cm->hca->ib_trans.list,
+                           (DAPL_LLIST_ENTRY *)&cm->local_entry, cm);
+       dapl_os_unlock(&cm->hca->ib_trans.lock);
+       dapls_thread_signal(&cm->hca->ib_trans.signal);
+}
+
+/* PASSIVE: queue up listen object on listen list */
+static void dapli_queue_listen(dp_ib_cm_handle_t cm)
+{
+       /* add to work queue, llist, for cm thread processing */
+       dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm->local_entry);
+       dapl_os_lock(&cm->hca->ib_trans.llock);
+       dapls_cm_acquire(cm);
+       dapl_llist_add_tail(&cm->hca->ib_trans.llist,
+                           (DAPL_LLIST_ENTRY *)&cm->local_entry, cm);
+       dapl_os_unlock(&cm->hca->ib_trans.llock);
+}
+
+static void dapli_dequeue_listen(dp_ib_cm_handle_t cm) 
+{
+       DAPL_HCA *hca = cm->hca;
+
+       dapl_os_lock(&hca->ib_trans.llock);
+       dapl_llist_remove_entry(&hca->ib_trans.llist, 
+                               (DAPL_LLIST_ENTRY *)&cm->local_entry);
+       dapls_cm_release(cm);
+       dapl_os_unlock(&hca->ib_trans.llock);
+}
+
+/* called with local LIST and CM object lock */
+static void dapli_cm_dequeue(dp_ib_cm_handle_t cm)
+{
+       /* Remove from work queue, cr thread processing */
+       dapl_llist_remove_entry(&cm->hca->ib_trans.list,
+                               (DAPL_LLIST_ENTRY *)&cm->local_entry);
+       dapls_cm_release(cm);
+}
+
+static void ucm_disconnect_final(dp_ib_cm_handle_t cm) 
+{
+       /* no EP attachment or not RC, nothing to process */
+       if (cm->ep == NULL ||
+           cm->ep->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC) 
+               return;
+
+       dapl_os_lock(&cm->lock);
+       if (cm->state == DCM_DISCONNECTED) {
+               dapl_os_unlock(&cm->lock);
+               return;
+       }
+               
+       cm->state = DCM_DISCONNECTED;
+       dapl_os_unlock(&cm->lock);
+
+       if (cm->sp) 
+               dapls_cr_callback(cm, IB_CME_DISCONNECTED, NULL, 0, cm->sp);
+       else
+               dapl_evd_connection_callback(cm, IB_CME_DISCONNECTED, NULL, 0, cm->ep);
+
+       /* free local resources, EP ref will prevent destory until dat_ep_free */
+       dapls_cm_release(cm);
+}
+
+/*
+ * called from consumer thread via ep_disconnect/ep_free or 
+ * from cm_thread when receiving DREQ
+ */
+DAT_RETURN dapli_cm_disconnect(dp_ib_cm_handle_t cm)
+{
+       int finalize = 1;
+
+       dapl_os_lock(&cm->lock);
+       switch (cm->state) {
+       case DCM_CONNECTED:
+               /* CONSUMER: move to err state to flush, if not UD */
+               if (cm->ep->qp_handle->qp_type != IBV_QPT_UD) 
+                       dapls_modify_qp_state(cm->ep->qp_handle, IBV_QPS_ERR,0,0,0);
+
+               /* send DREQ, event after DREP or DREQ timeout */
+               cm->state = DCM_DISC_PENDING;
+               cm->msg.op = htons(DCM_DREQ);
+               finalize = 0; /* wait for DREP, wakeup timer thread */
+               dapls_thread_signal(&cm->hca->ib_trans.signal);
+               break;
+       case DCM_DISC_PENDING:
+               /* DREQ timeout, resend until retries exhausted */
+               cm->msg.op = htons(DCM_DREQ);
+               if (cm->retries >= cm->hca->ib_trans.retries) {
+                       dapl_log(DAPL_DBG_TYPE_ERR, 
+                               " CM_DREQ: RETRIES EXHAUSTED:"
+                               " 0x%x %d 0x%x -> 0x%x %d 0x%x\n",
+                               htons(cm->msg.saddr.ib.lid), 
+                               htonl(cm->msg.saddr.ib.qpn), 
+                               htons(cm->msg.sport), 
+                               htons(cm->msg.daddr.ib.lid), 
+                               htonl(cm->msg.dqpn), 
+                               htons(cm->msg.dport));
+                       finalize = 1;
+               }
+               break;
+       case DCM_DISC_RECV:
+               /* CM_THREAD: move to err state to flush, if not UD */
+               if (cm->ep->qp_handle->qp_type != IBV_QPT_UD) 
+                       dapls_modify_qp_state(cm->ep->qp_handle, IBV_QPS_ERR,0,0,0);
+
+               /* DREQ received, send DREP and schedule event */
+               cm->msg.op = htons(DCM_DREP);
+               break;
+       default:
+               dapl_os_unlock(&cm->lock);
+               return DAT_SUCCESS;
+       }
+       
+       dapl_os_get_time(&cm->timer); /* reply expected */
+       ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0); 
+       dapl_os_unlock(&cm->lock);
+
+       if (finalize) 
+               ucm_disconnect_final(cm);
+       
+       return DAT_SUCCESS;
+}
+
+/*
+ * ACTIVE: get remote CM SID server info from r_addr. 
+ *         send, or resend CM msg via UD CM QP 
+ */
+DAT_RETURN
+dapli_cm_connect(DAPL_EP *ep, dp_ib_cm_handle_t cm)
+{
+       dapl_log(DAPL_DBG_TYPE_EP, 
+                " connect: lid %x i_qpn %x lport %d p_sz=%d -> "
+                " lid %x c_qpn %x rport %d\n",
+                htons(cm->msg.saddr.ib.lid), htonl(cm->msg.saddr.ib.qpn),
+                htons(cm->msg.sport), htons(cm->msg.p_size),
+                htons(cm->msg.daddr.ib.lid), htonl(cm->msg.dqpn),
+                htons(cm->msg.dport));
+
+       dapl_os_lock(&cm->lock);
+       if (cm->state != DCM_REP_PENDING) {
+               dapl_os_unlock(&cm->lock);
+               return DAT_INVALID_STATE;
+       }
+       
+       if (cm->retries == cm->hca->ib_trans.retries) {
+               dapl_log(DAPL_DBG_TYPE_ERR, 
+                       " CM_REQ: RETRIES EXHAUSTED:"
+                        " 0x%x %d 0x%x -> 0x%x %d 0x%x\n",
+                        htons(cm->msg.saddr.ib.lid), 
+                        htonl(cm->msg.saddr.ib.qpn), 
+                        htons(cm->msg.sport), 
+                        htons(cm->msg.daddr.ib.lid), 
+                        htonl(cm->msg.dqpn), 
+                        htons(cm->msg.dport));
+
+               dapl_os_unlock(&cm->lock);
+
+#ifdef DAPL_COUNTERS
+               /* called from check_timers in cm_thread, cm lock held */
+               if (g_dapl_dbg_type & DAPL_DBG_TYPE_CM_LIST) {
+                       dapl_os_unlock(&cm->hca->ib_trans.lock);
+                       dapls_print_cm_list(ep->header.owner_ia);
+                       dapl_os_lock(&cm->hca->ib_trans.lock);
+               }
+#endif
+               dapl_evd_connection_callback(cm, 
+                                            IB_CME_DESTINATION_UNREACHABLE,
+                                            NULL, 0, ep);
+               
+               return DAT_ERROR(DAT_INVALID_ADDRESS, 
+                                DAT_INVALID_ADDRESS_UNREACHABLE);
+       }
+       dapl_os_unlock(&cm->lock);
+
+       cm->msg.op = htons(DCM_REQ);
+       dapl_os_get_time(&cm->timer); /* reply expected */
+       if (ucm_send(&cm->hca->ib_trans, &cm->msg, 
+                    &cm->msg.p_data, ntohs(cm->msg.p_size)))           
+               goto bail;
+
+       /* first time through, link EP and CM, put on work queue */
+       if (!cm->retries) {
+               dapli_queue_conn(cm);
+       }
+       return DAT_SUCCESS;
+
+bail:
+       dapl_log(DAPL_DBG_TYPE_WARN, 
+                " connect: ERR %s -> cm_lid %d cm_qpn %d r_psp %d p_sz=%d\n",
+                strerror(errno), htons(cm->msg.daddr.ib.lid), 
+                htonl(cm->msg.dqpn), htons(cm->msg.dport), 
+                htonl(cm->msg.p_size));
+
+       dapli_cm_free(cm);
+       return DAT_INSUFFICIENT_RESOURCES;
+}
+
+/*
+ * ACTIVE: exchange QP information, called from CR thread
+ */
+static void ucm_connect_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg)
+{
+       DAPL_EP *ep = cm->ep;
+       ib_cm_events_t event = IB_CME_CONNECTED;
+
+       dapl_os_lock(&cm->lock);
+       if (cm->state != DCM_REP_PENDING) {
+               dapl_log(DAPL_DBG_TYPE_WARN, 
+                        " CONN_RTU: UNEXPECTED state:"
+                        " op %d, st %s <- lid %d sqpn %d sport %d\n", 
+                        ntohs(msg->op), dapl_cm_state_str(cm->state), 
+                        ntohs(msg->saddr.ib.lid), ntohl(msg->saddr.ib.qpn), 
+                        ntohs(msg->sport));
+               dapl_os_unlock(&cm->lock);
+               return;
+       }
+
+       /* save remote address information to EP and CM */
+       dapl_os_memcpy(&ep->remote_ia_address,
+                      &msg->saddr, sizeof(union dcm_addr));
+       dapl_os_memcpy(&cm->msg.daddr, 
+                      &msg->saddr, sizeof(union dcm_addr));
+
+       /* validate private data size, and copy if necessary */
+       if (msg->p_size) {
+               if (ntohs(msg->p_size) > DCM_MAX_PDATA_SIZE) {
+                       dapl_log(DAPL_DBG_TYPE_WARN, 
+                                " CONN_RTU: invalid p_size %d:"
+                                " st %s <- lid %d sqpn %d spsp %d\n", 
+                                ntohs(msg->p_size), 
+                                dapl_cm_state_str(cm->state), 
+                                ntohs(msg->saddr.ib.lid), 
+                                ntohl(msg->saddr.ib.qpn), 
+                                ntohs(msg->sport));
+                       dapl_os_unlock(&cm->lock);
+                       goto bail;
+               }
+               dapl_os_memcpy(cm->msg.p_data, 
+                              msg->p_data, ntohs(msg->p_size));
+       }
+               
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " CONN_RTU: DST lid=%x,"
+                    " iqp=%x, qp_type=%d, port=%d psize=%d\n",
+                    ntohs(cm->msg.daddr.ib.lid),
+                    ntohl(cm->msg.daddr.ib.qpn), cm->msg.daddr.ib.qp_type,
+                    ntohs(msg->sport), ntohs(msg->p_size));
+
+       if (ntohs(msg->op) == DCM_REP)
+               event = IB_CME_CONNECTED;
+       else if (ntohs(msg->op) == DCM_REJ_USER) 
+               event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;
+       else  
+               event = IB_CME_DESTINATION_REJECT;
+       
+       if (event != IB_CME_CONNECTED) {
+               cm->state = DCM_REJECTED;
+               dapl_os_unlock(&cm->lock);
+
+#ifdef DAT_EXTENSIONS
+               if (cm->msg.daddr.ib.qp_type == IBV_QPT_UD) 
+                       goto ud_bail;
+               else
+#endif
+               goto bail;
+       }
+       dapl_os_unlock(&cm->lock);
+
+       /* modify QP to RTR and then to RTS with remote info */
+       dapl_os_lock(&cm->ep->header.lock);
+       if (dapls_modify_qp_state(cm->ep->qp_handle,
+                                 IBV_QPS_RTR, 
+                                 cm->msg.daddr.ib.qpn,
+                                 cm->msg.daddr.ib.lid,
+                                 (ib_gid_handle_t)cm->msg.daddr.ib.gid) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_RTU: QPS_RTR ERR %s <- lid %x iqp %x\n",
+                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),
+                        ntohl(cm->msg.daddr.ib.qpn));
+               dapl_os_unlock(&cm->ep->header.lock);
+               event = IB_CME_LOCAL_FAILURE;
+               goto bail;
+       }
+       if (dapls_modify_qp_state(cm->ep->qp_handle,
+                                 IBV_QPS_RTS, 
+                                 cm->msg.daddr.ib.qpn,
+                                 cm->msg.daddr.ib.lid,
+                                 NULL) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " CONN_RTU: QPS_RTS ERR %s <- lid %x iqp %x\n",
+                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),
+                        ntohl(cm->msg.daddr.ib.qpn));
+               dapl_os_unlock(&cm->ep->header.lock);
+               event = IB_CME_LOCAL_FAILURE;
+               goto bail;
+       }
+       dapl_os_unlock(&cm->ep->header.lock);
+       
+       /* Send RTU, no private data */
+       cm->msg.op = htons(DCM_RTU);
+       
+       dapl_os_lock(&cm->lock);
+       cm->state = DCM_CONNECTED;
+       dapl_os_unlock(&cm->lock);
+
+       if (ucm_send(&cm->hca->ib_trans, &cm->msg, NULL, 0))            
+               goto bail;
+
+       /* init cm_handle and post the event with private data */
+       dapl_dbg_log(DAPL_DBG_TYPE_EP, " ACTIVE: connected!\n");
+
+#ifdef DAT_EXTENSIONS
+ud_bail:
+       if (cm->msg.daddr.ib.qp_type == IBV_QPT_UD) {
+               DAT_IB_EXTENSION_EVENT_DATA xevent;
+               uint16_t lid = ntohs(cm->msg.daddr.ib.lid);
+               
+               /* post EVENT, modify_qp, AH already created, ucm msg */
+               xevent.status = 0;
+               xevent.type = DAT_IB_UD_REMOTE_AH;
+               xevent.remote_ah.qpn = ntohl(cm->msg.daddr.ib.qpn);
+               xevent.remote_ah.ah = dapls_create_ah(cm->hca, 
+                                                     cm->ep->qp_handle->pd, 
+                                                     cm->ep->qp_handle, 
+                                                     htons(lid), 
+                                                     NULL);
+               if (xevent.remote_ah.ah == NULL) {
+                       event = IB_CME_LOCAL_FAILURE;
+                       goto bail;
+               }
+               cm->ah = xevent.remote_ah.ah; /* keep ref to destroy */
+
+               dapl_os_memcpy(&xevent.remote_ah.ia_addr,
+                              &cm->msg.daddr,
+                              sizeof(union dcm_addr));
+
+               /* remote ia_addr reference includes ucm qpn, not IB qpn */
+               ((union dcm_addr*)
+                       &xevent.remote_ah.ia_addr)->ib.qpn = cm->msg.dqpn;
+
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                            " ACTIVE: UD xevent ah %p qpn 0x%x lid 0x%x\n",
+                            xevent.remote_ah.ah, xevent.remote_ah.qpn, lid);
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                            " ACTIVE: UD xevent ia_addr qp_type %d"
+                            " lid 0x%x qpn 0x%x gid 0x"F64x" 0x"F64x" \n",
+                            ((union dcm_addr*)
+                               &xevent.remote_ah.ia_addr)->ib.qp_type,
+                            ntohs(((union dcm_addr*)
+                               &xevent.remote_ah.ia_addr)->ib.lid),
+                            ntohl(((union dcm_addr*)
+                               &xevent.remote_ah.ia_addr)->ib.qpn),
+                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[0]),
+                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[8]));
+
+               if (event == IB_CME_CONNECTED)
+                       event = DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED;
+               else {
+                       xevent.type = DAT_IB_UD_CONNECT_REJECT;
+                       event = DAT_IB_UD_CONNECTION_REJECT_EVENT;
+               }
+
+               dapls_evd_post_connection_event_ext(
+                               (DAPL_EVD *)cm->ep->param.connect_evd_handle,
+                               event,
+                               (DAT_EP_HANDLE)ep,
+                               (DAT_COUNT)ntohs(cm->msg.p_size),
+                               (DAT_PVOID *)cm->msg.p_data,
+                               (DAT_PVOID *)&xevent);
+
+               /* release cm_ptr, EP refs will prevent destroy */
+               dapli_cm_free(cm);
+                               
+       } else
+#endif
+       {
+               dapl_evd_connection_callback(cm,
+                                            IB_CME_CONNECTED,
+                                            cm->msg.p_data, ntohs(cm->msg.p_size), cm->ep);
+       }
+       return;
+bail:
+       dapl_evd_connection_callback(NULL, event, cm->msg.p_data, ntohs(cm->msg.p_size), cm->ep);
+       dapli_cm_free(cm);
+}
+
+/*
+ * PASSIVE: Accept on listen CM PSP.
+ *          create new CM object for this CR, 
+ *         receive peer QP information, private data, 
+ *         and post cr_event 
+ */
+static void ucm_accept(ib_cm_srvc_handle_t cm, ib_cm_msg_t *msg)
+{
+       dp_ib_cm_handle_t acm;
+
+       /* Allocate accept CM and setup passive references */
+       if ((acm = dapls_ib_cm_create(NULL)) == NULL) {
+               dapl_log(DAPL_DBG_TYPE_WARN, " accept: ERR cm_create\n");
+               return;
+       }
+
+       /* dest CM info from CR msg, source CM info from listen */
+       acm->sp = cm->sp;
+       acm->hca = cm->hca;
+       acm->msg.dport = msg->sport;
+       acm->msg.dqpn = msg->sqpn;
+       acm->msg.sport = cm->msg.sport; 
+       acm->msg.sqpn = cm->msg.sqpn;
+       acm->msg.p_size = msg->p_size;
+
+       /* CR saddr is CM daddr info, need EP for local saddr */
+       dapl_os_memcpy(&acm->msg.daddr, &msg->saddr, sizeof(union dcm_addr));
+       
+       dapl_log(DAPL_DBG_TYPE_CM,
+                " accept: DST port=%d lid=%x, iqp=%x, psize=%d\n",
+                ntohs(acm->msg.dport), ntohs(acm->msg.daddr.ib.lid), 
+                htonl(acm->msg.daddr.ib.qpn), htons(acm->msg.p_size));
+
+       /* validate private data size before reading */
+       if (ntohs(msg->p_size) > DCM_MAX_PDATA_SIZE) {
+               dapl_log(DAPL_DBG_TYPE_WARN, " accept: psize (%d) wrong\n",
+                        ntohs(msg->p_size));
+               goto bail;
+       }
+
+       /* read private data into cm_handle if any present */
+       if (msg->p_size) 
+               dapl_os_memcpy(acm->msg.p_data, 
+                              msg->p_data, ntohs(msg->p_size));
+               
+       acm->state = DCM_ACCEPTING;
+       dapli_queue_conn(acm);
+
+#ifdef DAT_EXTENSIONS
+       if (acm->msg.daddr.ib.qp_type == IBV_QPT_UD) {
+               DAT_IB_EXTENSION_EVENT_DATA xevent;
+
+               /* post EVENT, modify_qp created ah */
+               xevent.status = 0;
+               xevent.type = DAT_IB_UD_CONNECT_REQUEST;
+
+               dapls_evd_post_cr_event_ext(acm->sp,
+                                           DAT_IB_UD_CONNECTION_REQUEST_EVENT,
+                                           acm,
+                                           (DAT_COUNT)ntohs(acm->msg.p_size),
+                                           (DAT_PVOID *)acm->msg.p_data,
+                                           (DAT_PVOID *)&xevent);
+       } else
+#endif
+               /* trigger CR event and return SUCCESS */
+               dapls_cr_callback(acm,
+                                 IB_CME_CONNECTION_REQUEST_PENDING,
+                                 acm->msg.p_data, ntohs(msg->p_size), acm->sp);
+       return;
+
+bail:
+       /* schedule work thread cleanup */
+       dapli_cm_free(acm);
+       return;
+}
+
+/*
+ * PASSIVE: read RTU from active peer, post CONN event
+ */
+static void ucm_accept_rtu(dp_ib_cm_handle_t cm, ib_cm_msg_t *msg)
+{
+       dapl_os_lock(&cm->lock);
+       if ((ntohs(msg->op) != DCM_RTU) || (cm->state != DCM_RTU_PENDING)) {
+               dapl_log(DAPL_DBG_TYPE_WARN, 
+                        " accept_rtu: UNEXPECTED op, state:"
+                        " op %d, st %s <- lid %x iqp %x sport %d\n", 
+                        ntohs(msg->op), dapl_cm_state_str(cm->state), 
+                        ntohs(msg->saddr.ib.lid), ntohl(msg->saddr.ib.qpn), 
+                        ntohs(msg->sport));
+               dapl_os_unlock(&cm->lock);
+               goto bail;
+       }
+       cm->state = DCM_CONNECTED;
+       dapl_os_unlock(&cm->lock);
+       
+       /* final data exchange if remote QP state is good to go */
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, " PASSIVE: connected!\n");
+
+#ifdef DAT_EXTENSIONS
+       if (cm->msg.saddr.ib.qp_type == IBV_QPT_UD) {
+               DAT_IB_EXTENSION_EVENT_DATA xevent;
+               uint16_t lid = ntohs(cm->msg.daddr.ib.lid);
+               
+               /* post EVENT, modify_qp, AH already created, ucm msg */
+               xevent.status = 0;
+               xevent.type = DAT_IB_UD_PASSIVE_REMOTE_AH;
+               xevent.remote_ah.qpn = ntohl(cm->msg.daddr.ib.qpn);
+               xevent.remote_ah.ah = dapls_create_ah(cm->hca, 
+                                                     cm->ep->qp_handle->pd, 
+                                                     cm->ep->qp_handle, 
+                                                     htons(lid), 
+                                                     NULL);
+               if (xevent.remote_ah.ah == NULL) {
+                       dapl_log(DAPL_DBG_TYPE_ERR,
+                                " accept_rtu: ERR create_ah"
+                                " for qpn 0x%x lid 0x%x\n",
+                                xevent.remote_ah.qpn, lid);
+                       goto bail;
+               }
+               cm->ah = xevent.remote_ah.ah; /* keep ref to destroy */
+               dapl_os_memcpy(&xevent.remote_ah.ia_addr,
+                              &cm->msg.daddr,
+                               sizeof(union dcm_addr));
+
+               /* remote ia_addr reference includes ucm qpn, not IB qpn */
+               ((union dcm_addr*)
+                       &xevent.remote_ah.ia_addr)->ib.qpn = cm->msg.dqpn;
+
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                            " PASSIVE: UD xevent ah %p qpn 0x%x lid 0x%x\n",
+                            xevent.remote_ah.ah, xevent.remote_ah.qpn, lid);
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                            " PASSIVE: UD xevent ia_addr qp_type %d"
+                            " lid 0x%x qpn 0x%x gid 0x"F64x" 0x"F64x" \n",
+                            ((union dcm_addr*)
+                               &xevent.remote_ah.ia_addr)->ib.qp_type,
+                            ntohs(((union dcm_addr*)
+                               &xevent.remote_ah.ia_addr)->ib.lid),
+                            ntohl(((union dcm_addr*)
+                               &xevent.remote_ah.ia_addr)->ib.qpn),
+                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[0]),
+                            ntohll(*(uint64_t*)&cm->msg.daddr.ib.gid[8]));
+
+               dapls_evd_post_connection_event_ext(
+                               (DAPL_EVD *)cm->ep->param.connect_evd_handle,
+                               DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED,
+                               (DAT_EP_HANDLE)cm->ep,
+                               (DAT_COUNT)ntohs(cm->msg.p_size),
+                               (DAT_PVOID *)cm->msg.p_data,
+                               (DAT_PVOID *)&xevent);
+
+                /* done with CM object, EP ref will hold object for pdata */
+               dapli_cm_free(cm);
+               
+       } else {
+#endif
+               dapls_cr_callback(cm, IB_CME_CONNECTED, NULL, 0, cm->sp);
+       }
+       return;
+bail:
+       dapls_cr_callback(cm, IB_CME_LOCAL_FAILURE, NULL, 0, cm->sp);
+       dapli_cm_free(cm);
+}
+
+/*
+ * PASSIVE: user accepted, send reply message with pdata
+ */
+static int ucm_reply(dp_ib_cm_handle_t cm)
+{
+       dapl_os_lock(&cm->lock);
+       if (cm->state != DCM_RTU_PENDING) {
+               dapl_os_unlock(&cm->lock);
+               return -1;
+       }
+
+       if (cm->retries == cm->hca->ib_trans.retries) {
+               dapl_log(DAPL_DBG_TYPE_ERR, 
+                        " CM_REPLY: RETRIES EXHAUSTED"
+                        " 0x%x %d 0x%x -> 0x%x %d 0x%x\n",
+                        htons(cm->msg.saddr.ib.lid), 
+                        htons(cm->msg.sport), 
+                        htonl(cm->msg.saddr.ib.qpn), 
+                        htons(cm->msg.daddr.ib.lid), 
+                        htons(cm->msg.dport), 
+                        htonl(cm->msg.daddr.ib.qpn));
+                       
+               dapl_os_unlock(&cm->lock);
+#ifdef DAPL_COUNTERS
+               /* called from check_timers in cm_thread, cm lock held */
+               if (g_dapl_dbg_type & DAPL_DBG_TYPE_CM_LIST) {
+                       dapl_os_unlock(&cm->hca->ib_trans.lock);
+                       dapls_print_cm_list(dapl_llist_peek_head(&cm->hca->ia_list_head));
+                       dapl_os_lock(&cm->hca->ib_trans.lock);
+               }
+#endif
+#ifdef DAT_EXTENSIONS
+               if (cm->msg.saddr.ib.qp_type == IBV_QPT_UD) {
+                       DAT_IB_EXTENSION_EVENT_DATA xevent;
+                                       
+                       /* post REJECT event with CONN_REQ p_data */
+                       xevent.status = 0;
+                       xevent.type = DAT_IB_UD_CONNECT_ERROR;
+                                       
+                       dapls_evd_post_connection_event_ext(
+                               (DAPL_EVD *)cm->ep->param.connect_evd_handle,
+                               DAT_IB_UD_CONNECTION_ERROR_EVENT,
+                               (DAT_EP_HANDLE)cm->ep,
+                               (DAT_COUNT)ntohs(cm->msg.p_size),
+                               (DAT_PVOID *)cm->msg.p_data,
+                               (DAT_PVOID *)&xevent);
+               } else 
+#endif
+                       dapls_cr_callback(cm, IB_CME_LOCAL_FAILURE, 
+                                         NULL, 0, cm->sp);
+               return -1;
+       }
+       dapl_os_get_time(&cm->timer); /* RTU expected */
+       dapl_os_unlock(&cm->lock);
+       if (ucm_send(&cm->hca->ib_trans, &cm->msg, cm->p_data, cm->p_size))             
+               return -1;
+
+       return 0;
+}
+
+
+/*
+ * PASSIVE: consumer accept, send local QP information, private data, 
+ * queue on work thread to receive RTU information to avoid blocking
+ * user thread. 
+ */
+DAT_RETURN
+dapli_accept_usr(DAPL_EP *ep, DAPL_CR *cr, DAT_COUNT p_size, DAT_PVOID p_data)
+{
+       DAPL_IA *ia = ep->header.owner_ia;
+       dp_ib_cm_handle_t cm = cr->ib_cm_handle;
+
+       if (p_size > DCM_MAX_PDATA_SIZE)
+               return DAT_LENGTH_ERROR;
+
+       dapl_os_lock(&cm->lock);
+       if (cm->state != DCM_ACCEPTING) {
+               dapl_os_unlock(&cm->lock);
+               return DAT_INVALID_STATE;
+       }
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " ACCEPT_USR: remote lid=%x"
+                    " iqp=%x qp_type %d, psize=%d\n",
+                    ntohs(cm->msg.daddr.ib.lid),
+                    ntohl(cm->msg.daddr.ib.qpn), cm->msg.daddr.ib.qp_type, 
+                    p_size);
+
+       dapl_dbg_log(DAPL_DBG_TYPE_CM,
+                    " ACCEPT_USR: remote GID subnet %016llx id %016llx\n",
+                    (unsigned long long)
+                    htonll(*(uint64_t*)&cm->msg.daddr.ib.gid[0]),
+                    (unsigned long long)
+                    htonll(*(uint64_t*)&cm->msg.daddr.ib.gid[8]));
+
+#ifdef DAT_EXTENSIONS
+       if (cm->msg.daddr.ib.qp_type == IBV_QPT_UD &&
+           ep->qp_handle->qp_type != IBV_QPT_UD) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                            " ACCEPT_USR: ERR remote QP is UD,"
+                            ", but local QP is not\n");
+               return (DAT_INVALID_HANDLE | DAT_INVALID_HANDLE_EP);
+       }
+#endif
+
+       /* modify QP to RTR and then to RTS with remote info already read */
+       if (dapls_modify_qp_state(ep->qp_handle,
+                                 IBV_QPS_RTR, 
+                                 cm->msg.daddr.ib.qpn,
+                                 cm->msg.daddr.ib.lid,
+                                 (ib_gid_handle_t)cm->msg.daddr.ib.gid) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_USR: QPS_RTR ERR %s -> lid %x qpn %x\n",
+                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),
+                        ntohl(cm->msg.daddr.ib.qpn));
+               dapl_os_unlock(&cm->lock);
+               goto bail;
+       }
+       if (dapls_modify_qp_state(ep->qp_handle,
+                                 IBV_QPS_RTS, 
+                                 cm->msg.daddr.ib.qpn,
+                                 cm->msg.daddr.ib.lid,
+                                 NULL) != DAT_SUCCESS) {
+               dapl_log(DAPL_DBG_TYPE_ERR,
+                        " ACCEPT_USR: QPS_RTS ERR %s -> lid %x qpn %x\n",
+                        strerror(errno), ntohs(cm->msg.daddr.ib.lid),
+                        ntohl(cm->msg.daddr.ib.qpn));
+               dapl_os_unlock(&cm->lock);
+               goto bail;
+       }
+
+       /* save remote address information */
+       dapl_os_memcpy(&ep->remote_ia_address,
+                      &cm->msg.saddr, sizeof(union dcm_addr));
+
+       /* setup local QP info and type from EP, copy pdata, for reply */
+       cm->msg.op = htons(DCM_REP);
+       cm->msg.saddr.ib.qpn = htonl(ep->qp_handle->qp_num);
+       cm->msg.saddr.ib.qp_type = ep->qp_handle->qp_type;
+       cm->msg.saddr.ib.lid = cm->hca->ib_trans.addr.ib.lid; 
+       dapl_os_memcpy(&cm->msg.saddr.ib.gid[0],
+                      &cm->hca->ib_trans.addr.ib.gid, 16); 
+
+       /* 
+        * UD: deliver p_data with REQ and EST event, keep REQ p_data in 
+        * cm->msg.p_data and save REPLY accept data in cm->p_data for retries 
+        */
+       cm->p_size = p_size;
+       dapl_os_memcpy(&cm->p_data, p_data, p_size);
+
+       /* save state and setup valid reference to EP, HCA */
+       dapl_ep_link_cm(ep, cm);
+       cm->ep = ep;
+       cm->hca = ia->hca_ptr;
+       cm->state = DCM_RTU_PENDING;
+       dapl_os_get_time(&cm->timer); /* RTU expected */
+       dapl_os_unlock(&cm->lock);
+
+       if (ucm_reply(cm)) {
+               dapl_ep_link_cm(ep, cm);
+               goto bail;
+       }
+       dapl_dbg_log(DAPL_DBG_TYPE_CM, " PASSIVE: accepted!\n");
+       dapls_thread_signal(&cm->hca->ib_trans.signal);
+       return DAT_SUCCESS;
+bail:
+       dapli_cm_free(cm);
+       return DAT_INTERNAL_ERROR;
+}
+
+
+/*
+ * dapls_ib_connect
+ *
+ * Initiate a connection with the passive listener on another node
+ *
+ * Input:
+ *     ep_handle,
+ *     remote_ia_address,
+ *     remote_conn_qual,
+ *     prd_size                size of private data and structure
+ *     prd_prt                 pointer to private data structure
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,
+                IN DAT_IA_ADDRESS_PTR r_addr,
+                IN DAT_CONN_QUAL r_psp,
+                IN DAT_COUNT p_size, IN void *p_data)
+{
+       DAPL_EP *ep = (DAPL_EP *)ep_handle;
+       dp_ib_cm_handle_t cm;
+       
+       /* create CM object, initialize SRC info from EP */
+       cm = dapls_ib_cm_create(ep);
+       if (cm == NULL)
+               return DAT_INSUFFICIENT_RESOURCES;
+
+       /* remote hca and port: lid, gid, network order */
+       dapl_os_memcpy(&cm->msg.daddr, r_addr, sizeof(union dcm_addr));
+
+       /* remote uCM information, comes from consumer provider r_addr */
+       cm->msg.dport = htons((uint16_t)r_psp);
+       cm->msg.dqpn = cm->msg.daddr.ib.qpn;
+       cm->msg.daddr.ib.qpn = 0; /* don't have a remote qpn until reply */
+       
+       if (p_size) {
+               cm->msg.p_size = htons(p_size);
+               dapl_os_memcpy(&cm->msg.p_data, p_data, p_size);
+       }
+       
+       cm->state = DCM_REP_PENDING;
+
+       /* build connect request, send to remote CM based on r_addr info */
+       return (dapli_cm_connect(ep, cm));
+}
+
+/*
+ * dapls_ib_disconnect
+ *
+ * Disconnect an EP
+ *
+ * Input:
+ *     ep_handle,
+ *     disconnect_flags
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ */
+DAT_RETURN
+dapls_ib_disconnect(IN DAPL_EP *ep_ptr, IN DAT_CLOSE_FLAGS close_flags)
+{
+       dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+
+       if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED ||
+               ep_ptr->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC) {
+               return DAT_SUCCESS;
+       } 
+       
+       /* RC. Transition to error state to flush queue */
+        dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0, 0, 0);
+
+       return (dapli_cm_disconnect(cm_ptr));
+}
+
+/*
+ * dapls_ib_disconnect_clean
+ *
+ * Clean up outstanding connection data. This routine is invoked
+ * after the final disconnect callback has occurred. Only on the
+ * ACTIVE side of a connection. It is also called if dat_ep_connect
+ * times out using the consumer supplied timeout value.
+ *
+ * Input:
+ *     ep_ptr          DAPL_EP
+ *     active          Indicates active side of connection
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     void
+ *
+ */
+void
+dapls_ib_disconnect_clean(IN DAPL_EP *ep,
+                         IN DAT_BOOLEAN active,
+                         IN const ib_cm_events_t ib_cm_event)
+{
+       /* nothing to cleanup */
+}
+
+/*
+ * dapl_ib_setup_conn_listener
+ *
+ * Have the CM set up a connection listener.
+ *
+ * Input:
+ *     ibm_hca_handle          HCA handle
+ *     qp_handle                       QP handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *     DAT_CONN_QUAL_UNAVAILBLE
+ *     DAT_CONN_QUAL_IN_USE
+ *
+ */
+DAT_RETURN
+dapls_ib_setup_conn_listener(IN DAPL_IA *ia, 
+                            IN DAT_UINT64 sid, 
+                            IN DAPL_SP *sp)
+{
+       ib_cm_srvc_handle_t cm = NULL;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " listen(ia %p ServiceID %d sp %p)\n",
+                    ia, sid, sp);
+
+       /* reserve local port, then allocate CM object */
+       if (!ucm_get_port(&ia->hca_ptr->ib_trans, (uint16_t)sid)) {
+               dapl_dbg_log(DAPL_DBG_TYPE_WARN,
+                            " listen: ERROR %s on conn_qual 0x%x\n",
+                            strerror(errno), sid);
+               return DAT_CONN_QUAL_IN_USE;
+       }
+
+       /* cm_create will setup saddr for listen server */
+       if ((cm = dapls_ib_cm_create(NULL)) == NULL)
+               return DAT_INSUFFICIENT_RESOURCES;
+
+       /* LISTEN: init DST address and QP info to local CM server info */
+       cm->sp = sp;
+       cm->hca = ia->hca_ptr;
+       cm->msg.sport = htons((uint16_t)sid);
+       cm->msg.sqpn = htonl(ia->hca_ptr->ib_trans.qp->qp_num);
+       cm->msg.saddr.ib.qp_type = IBV_QPT_UD;
+        cm->msg.saddr.ib.lid = ia->hca_ptr->ib_trans.addr.ib.lid; 
+       dapl_os_memcpy(&cm->msg.saddr.ib.gid[0],
+                      &cm->hca->ib_trans.addr.ib.gid, 16); 
+       
+       /* save cm_handle reference in service point */
+       sp->cm_srvc_handle = cm;
+
+       /* queue up listen socket to process inbound CR's */
+       cm->state = DCM_LISTEN;
+       dapli_queue_listen(cm);
+
+       return DAT_SUCCESS;
+}
+
+
+/*
+ * dapl_ib_remove_conn_listener
+ *
+ * Have the CM remove a connection listener.
+ *
+ * Input:
+ *     ia_handle               IA handle
+ *     ServiceID               IB Channel Service ID
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_STATE
+ *
+ */
+DAT_RETURN
+dapls_ib_remove_conn_listener(IN DAPL_IA *ia, IN DAPL_SP *sp)
+{
+       ib_cm_srvc_handle_t cm = sp->cm_srvc_handle;
+
+       /* free cm_srvc_handle and port, and mark CM for cleanup */
+       if (cm) {
+               dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " remove_listener(ia %p sp %p cm %p psp=%d)\n",
+                    ia, sp, cm, ntohs(cm->msg.dport));
+
+               sp->cm_srvc_handle = NULL;
+               dapli_dequeue_listen(cm);  
+               dapls_cm_release(cm);  /* last ref, dealloc */
+       }
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_accept_connection
+ *
+ * Perform necessary steps to accept a connection
+ *
+ * Input:
+ *     cr_handle
+ *     ep_handle
+ *     private_data_size
+ *     private_data
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INSUFFICIENT_RESOURCES
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,
+                          IN DAT_EP_HANDLE ep_handle,
+                          IN DAT_COUNT p_size, 
+                          IN const DAT_PVOID p_data)
+{
+       DAPL_CR *cr = (DAPL_CR *)cr_handle;
+       DAPL_EP *ep = (DAPL_EP *)ep_handle;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " accept_connection(cr %p ep %p prd %p,%d)\n",
+                    cr, ep, p_data, p_size);
+
+       /* allocate and attach a QP if necessary */
+       if (ep->qp_state == DAPL_QP_STATE_UNATTACHED) {
+               DAT_RETURN status;
+               status = dapls_ib_qp_alloc(ep->header.owner_ia,
+                                          ep, ep);
+               if (status != DAT_SUCCESS)
+                       return status;
+       }
+       return (dapli_accept_usr(ep, cr, p_size, p_data));
+}
+
+/*
+ * dapls_ib_reject_connection
+ *
+ * Reject a connection
+ *
+ * Input:
+ *     cr_handle
+ *
+ * Output:
+ *     none
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INTERNAL_ERROR
+ *
+ */
+DAT_RETURN
+dapls_ib_reject_connection(IN dp_ib_cm_handle_t cm,
+                          IN int reason,
+                          IN DAT_COUNT psize, IN const DAT_PVOID pdata)
+{
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    " reject(cm %p reason %x, pdata %p, psize %d)\n",
+                    cm, reason, pdata, psize);
+
+        if (psize > DCM_MAX_PDATA_SIZE)
+                return DAT_LENGTH_ERROR;
+
+       /* cr_thread will destroy CR, update saddr lid, gid, qp_type info */
+       dapl_os_lock(&cm->lock);
+       cm->state = DCM_REJECTED;
+       cm->msg.saddr.ib.lid = cm->hca->ib_trans.addr.ib.lid; 
+       cm->msg.saddr.ib.qp_type = cm->msg.daddr.ib.qp_type;
+       dapl_os_memcpy(&cm->msg.saddr.ib.gid[0],
+                      &cm->hca->ib_trans.addr.ib.gid, 16); 
+       cm->msg.op = htons(DCM_REJ_USER);
+       
+       if (ucm_send(&cm->hca->ib_trans, &cm->msg, pdata, psize)) {
+               dapl_log(DAPL_DBG_TYPE_WARN,
+                        " cm_reject: ERR: %s\n", strerror(errno));
+               dapl_os_unlock(&cm->lock);
+               return DAT_INTERNAL_ERROR;
+       }
+       dapl_os_unlock(&cm->lock);
+       dapli_cm_free(cm);
+       return DAT_SUCCESS;
+}
+
+/*
+ * dapls_ib_cm_remote_addr
+ *
+ * Obtain the remote IP address given a connection
+ *
+ * Input:
+ *     cr_handle
+ *
+ * Output:
+ *     remote_ia_address: where to place the remote address
+ *
+ * Returns:
+ *     DAT_SUCCESS
+ *     DAT_INVALID_HANDLE
+ *
+ */
+DAT_RETURN
+dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle,
+                       OUT DAT_SOCK_ADDR6 * remote_ia_address)
+{
+       DAPL_HEADER *header;
+       dp_ib_cm_handle_t cm;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_EP,
+                    "dapls_ib_cm_remote_addr(dat_handle %p, ....)\n",
+                    dat_handle);
+
+       header = (DAPL_HEADER *) dat_handle;
+
+       if (header->magic == DAPL_MAGIC_EP)
+               cm = dapl_get_cm_from_ep((DAPL_EP *) dat_handle);
+       else if (header->magic == DAPL_MAGIC_CR)
+               cm = ((DAPL_CR *) dat_handle)->ib_cm_handle;
+       else
+               return DAT_INVALID_HANDLE;
+
+       dapl_os_memcpy(remote_ia_address,
+                      &cm->msg.daddr, sizeof(DAT_SOCK_ADDR6));
+
+       return DAT_SUCCESS;
+}
+
+int dapls_ib_private_data_size(
+       IN DAPL_HCA *hca_ptr)
+{
+       return DCM_MAX_PDATA_SIZE;
+}
+
+#if defined(_WIN32) || defined(_WIN64)
+
+void cm_thread(void *arg)
+{
+       struct dapl_hca *hca = arg;
+       dp_ib_cm_handle_t cm, next;
+       DWORD time_ms;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread: ENTER hca %p\n", hca);
+       dapl_os_lock(&hca->ib_trans.lock);
+       for (hca->ib_trans.cm_state = IB_THREAD_RUN;
+            hca->ib_trans.cm_state == IB_THREAD_RUN ||
+            !dapl_llist_is_empty(&hca->ib_trans.list);
+            dapl_os_lock(&hca->ib_trans.lock)) {
+
+               time_ms = INFINITE;
+               CompSetZero(&hca->ib_trans.signal.set);
+               CompSetAdd(&hca->ib_hca_handle->channel, &hca->ib_trans.signal.set);
+               CompSetAdd(&hca->ib_trans.rch->comp_channel, &hca->ib_trans.signal.set);
+               CompSetAdd(&hca->ib_trans.ib_cq->comp_channel, &hca->ib_trans.signal.set);
+
+               next = dapl_llist_is_empty(&hca->ib_trans.list) ? NULL :
+                       dapl_llist_peek_head(&hca->ib_trans.list);
+
+               while (next) {
+                       cm = next;
+                       next = dapl_llist_next_entry(&hca->ib_trans.list,
+                                                    (DAPL_LLIST_ENTRY *)&cm->local_entry);
+                       dapls_cm_acquire(cm); /* hold thread ref */
+                       dapl_os_lock(&cm->lock);
+                       if (cm->state == DCM_FREE || 
+                           hca->ib_trans.cm_state != IB_THREAD_RUN) {
+                               dapl_os_unlock(&cm->lock);
+                               dapl_log(DAPL_DBG_TYPE_CM, 
+                                        " CM FREE: %p ep=%p st=%s refs=%d\n", 
+                                        cm, cm->ep, dapl_cm_state_str(cm->state), 
+                                        cm->ref_count);
+
+                               dapls_cm_release(cm); /* release alloc ref */
+                               dapli_cm_dequeue(cm); /* release workq ref */
+                               dapls_cm_release(cm); /* release thread ref */
+                               continue;
+                       }
+                       dapl_os_unlock(&cm->lock);
+                       ucm_check_timers(cm, &time_ms);
+                       dapls_cm_release(cm); /* release thread ref */
+               }
+
+               dapl_os_unlock(&hca->ib_trans.lock);
+
+               hca->ib_hca_handle->channel.Milliseconds = time_ms;
+               hca->ib_trans.rch->comp_channel.Milliseconds = time_ms;
+               hca->ib_trans.ib_cq->comp_channel.Milliseconds = time_ms;
+               CompSetPoll(&hca->ib_trans.signal.set, time_ms);
+
+               hca->ib_hca_handle->channel.Milliseconds = 0;
+               hca->ib_trans.rch->comp_channel.Milliseconds = 0;
+               hca->ib_trans.ib_cq->comp_channel.Milliseconds = 0;
+
+               ucm_recv(&hca->ib_trans);
+               ucm_async_event(hca);
+               dapli_cq_event_cb(&hca->ib_trans);
+       }
+
+       dapl_os_unlock(&hca->ib_trans.lock);
+       hca->ib_trans.cm_state = IB_THREAD_EXIT;
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread(hca %p) exit\n", hca);
+}
+
+#else                          // _WIN32 || _WIN64
+
+void cm_thread(void *arg)
+{
+       struct dapl_hca *hca = arg;
+       dp_ib_cm_handle_t cm, next;
+       struct dapl_fd_set *set;
+       char rbuf[2];
+       int time_ms;
+
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread: ENTER hca %p\n", hca);
+       set = dapl_alloc_fd_set();
+       if (!set)
+               goto out;
+
+       dapl_os_lock(&hca->ib_trans.lock);
+       hca->ib_trans.cm_state = IB_THREAD_RUN;
+
+       while (1) {
+               time_ms = -1; /* reset to blocking */
+               dapl_fd_zero(set);
+               dapl_fd_set(hca->ib_trans.signal.scm[0], set, DAPL_FD_READ);    
+               dapl_fd_set(hca->ib_hca_handle->async_fd, set, DAPL_FD_READ);
+               dapl_fd_set(hca->ib_trans.rch->fd, set, DAPL_FD_READ);
+               dapl_fd_set(hca->ib_trans.ib_cq->fd, set, DAPL_FD_READ);
+               
+               if (!dapl_llist_is_empty(&hca->ib_trans.list))
+                       next = dapl_llist_peek_head(&hca->ib_trans.list);
+               else
+                       next = NULL;
+
+               while (next) {
+                       cm = next;
+                       next = dapl_llist_next_entry(
+                                       &hca->ib_trans.list,
+                                       (DAPL_LLIST_ENTRY *)&cm->local_entry);
+                       dapls_cm_acquire(cm); /* hold thread ref */
+                       dapl_os_lock(&cm->lock);
+                       if (cm->state == DCM_FREE || 
+                           hca->ib_trans.cm_state != IB_THREAD_RUN) {
+                               dapl_os_unlock(&cm->lock);
+                               dapl_log(DAPL_DBG_TYPE_CM, 
+                                        " CM FREE: %p ep=%p st=%s refs=%d\n", 
+                                        cm, cm->ep, dapl_cm_state_str(cm->state), 
+                                        cm->ref_count);
+
+                               dapls_cm_release(cm); /* release alloc ref */
+                               dapli_cm_dequeue(cm); /* release workq ref */
+                               dapls_cm_release(cm); /* release thread ref */
+                               continue;
+                       }
+                       dapl_os_unlock(&cm->lock);
+                       ucm_check_timers(cm, &time_ms);
+                       dapls_cm_release(cm); /* release thread ref */
+               }
+
+               /* set to exit and all resources destroyed */
+               if ((hca->ib_trans.cm_state != IB_THREAD_RUN) &&
+                   (dapl_llist_is_empty(&hca->ib_trans.list)))
+                       break;
+
+               dapl_os_unlock(&hca->ib_trans.lock);
+               dapl_select(set, time_ms);
+
+               /* Process events: CM, ASYNC, NOTIFY THREAD */
+               if (dapl_poll(hca->ib_trans.rch->fd, 
+                             DAPL_FD_READ) == DAPL_FD_READ) {
+                       ucm_recv(&hca->ib_trans);
+               }
+               if (dapl_poll(hca->ib_hca_handle->async_fd, 
+                             DAPL_FD_READ) == DAPL_FD_READ) {
+                       ucm_async_event(hca);
+               }
+               if (dapl_poll(hca->ib_trans.ib_cq->fd, 
+                             DAPL_FD_READ) == DAPL_FD_READ) {
+                       dapli_cq_event_cb(&hca->ib_trans);
+               }
+               while (dapl_poll(hca->ib_trans.signal.scm[0], 
+                                DAPL_FD_READ) == DAPL_FD_READ) {
+                       recv(hca->ib_trans.signal.scm[0], rbuf, 2, 0);
+               }
+               dapl_os_lock(&hca->ib_trans.lock);
+               
+               /* set to exit and all resources destroyed */
+               if ((hca->ib_trans.cm_state != IB_THREAD_RUN) &&
+                   (dapl_llist_is_empty(&hca->ib_trans.list)))
+                       break;
+       }
+
+       dapl_os_unlock(&hca->ib_trans.lock);
+       free(set);
+out:
+       hca->ib_trans.cm_state = IB_THREAD_EXIT;
+       dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " cm_thread(hca %p) exit\n", hca);
+}
+#endif
+
+#ifdef DAPL_COUNTERS
+/* Debug aid: List all Connections in process and state */
+void dapls_print_cm_list(IN DAPL_IA *ia_ptr)
+{
+       /* Print in process CM's for this IA, if debug type set */
+       int i = 0;
+       dp_ib_cm_handle_t cm, next_cm;
+       struct dapl_llist_entry **list;
+       DAPL_OS_LOCK *lock;
+       
+       /* LISTEN LIST */
+       list = &ia_ptr->hca_ptr->ib_trans.llist;
+       lock = &ia_ptr->hca_ptr->ib_trans.llock;
+
+       dapl_os_lock(lock);
+       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)list))
+               next_cm = dapl_llist_peek_head((DAPL_LLIST_HEAD*)list);
+       else
+               next_cm = NULL;
+
+        printf("\n DAPL IA LISTEN/CONNECTIONS IN PROCESS:\n");
+       while (next_cm) {
+               cm = next_cm;
+               next_cm = dapl_llist_next_entry((DAPL_LLIST_HEAD*)list,
+                                               (DAPL_LLIST_ENTRY*)&cm->local_entry);
+
+               printf( "  LISTEN[%d]: sp %p %s uCM_QP: 0x%x %d 0x%x l_pid %x,%d\n",
+                       i, cm->sp, dapl_cm_state_str(cm->state),
+                       ntohs(cm->msg.saddr.ib.lid), ntohs(cm->msg.sport),
+                       ntohl(cm->msg.sqpn), ntohl(*(DAT_UINT32*)cm->msg.resv), 
+                       ntohl(*(DAT_UINT32*)cm->msg.resv)); 
+               i++;
+       }
+       dapl_os_unlock(lock);
+
+       /* CONNECTION LIST */
+       list = &ia_ptr->hca_ptr->ib_trans.list;
+       lock = &ia_ptr->hca_ptr->ib_trans.lock;
+
+       dapl_os_lock(lock);
+       if (!dapl_llist_is_empty((DAPL_LLIST_HEAD*)list))
+               next_cm = dapl_llist_peek_head((DAPL_LLIST_HEAD*)list);
+       else
+               next_cm = NULL;
+
+        while (next_cm) {
+               cm = next_cm;
+               next_cm = dapl_llist_next_entry((DAPL_LLIST_HEAD*)list,
+                                               (DAPL_LLIST_ENTRY*)&cm->local_entry);
+
+               printf( "  CONN[%d]: ep %p cm %p %s %s"
+                       "  %x %x %x %s %x %x %x r_pid %x,%d\n",
+                       i, cm->ep, cm,
+                       cm->msg.saddr.ib.qp_type == IBV_QPT_RC ? "RC" : "UD",
+                       dapl_cm_state_str(cm->state),
+                       ntohs(cm->msg.saddr.ib.lid),
+                       ntohs(cm->msg.sport),
+                       ntohl(cm->msg.saddr.ib.qpn),    
+                       cm->sp ? "<-" : "->",
+                       ntohs(cm->msg.daddr.ib.lid),
+                       ntohs(cm->msg.dport),
+                       ntohl(cm->msg.daddr.ib.qpn),
+                       ntohs(cm->msg.op) == DCM_REQ ? 0 : ntohl(*(DAT_UINT32*)cm->msg.resv), 
+                       ntohs(cm->msg.op) == DCM_REQ ? 0 : ntohl(*(DAT_UINT32*)cm->msg.resv)); 
+               i++;
+       }
+       printf("\n");
+       dapl_os_unlock(lock);
+}
+#endif
index 62734590ed375378fd9e5313188ebb5a34b46b4a..de17f040203506af7aae1e05daebc141439ea926 100644 (file)
 #include "openib_osd.h"
 #include "dapl_ib_common.h"
 
+/* DAPL CM objects MUST include list_entry, ref_count, event for EP linking */
 struct ib_cm_handle
 { 
-       struct dapl_llist_entry entry;
+       struct dapl_llist_entry list_entry;
+       struct dapl_llist_entry local_entry;
+       DAPL_OS_WAIT_OBJECT     event;
        DAPL_OS_LOCK            lock;
        DAPL_OS_TIMEVAL         timer;
+        int                    ref_count;
        int                     state;
        int                     retries;
        struct dapl_hca         *hca;
@@ -117,9 +121,13 @@ typedef struct _ib_hca_transport
 void cm_thread(void *arg);
 void ucm_async_event(struct dapl_hca *hca);
 void dapli_cq_event_cb(struct _ib_hca_transport *tp);
-dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep);
-void dapls_ib_cm_free(dp_ib_cm_handle_t cm, DAPL_EP *ep);
+void dapls_cm_acquire(dp_ib_cm_handle_t cm_ptr);
+void dapls_cm_release(dp_ib_cm_handle_t cm_ptr);
+void dapls_cm_free(dp_ib_cm_handle_t cm_ptr);
+
+#ifdef DAPL_COUNTERS
 void dapls_print_cm_list(IN DAPL_IA *ia_ptr);
+#endif
 
 #endif /*  _DAPL_IB_UTIL_H_ */
 
index a9cec73e91204719e28afaa16fcdc9037d94af6e..1f324b352deeaeea560a5d5b9a94b6a3fe29cf0d 100644 (file)
@@ -401,15 +401,15 @@ DAT_RETURN dapls_ib_close_hca(IN DAPL_HCA * hca_ptr)
        destroy_os_signal(hca_ptr);
        ucm_service_destroy(hca_ptr);
 
-       if (hca_ptr->ib_trans.ib_cq)\r
-               ibv_destroy_comp_channel(hca_ptr->ib_trans.ib_cq);\r
-\r
-       if (hca_ptr->ib_trans.ib_cq_empty) {\r
-               struct ibv_comp_channel *channel;\r
-               channel = hca_ptr->ib_trans.ib_cq_empty->channel;\r
-               ibv_destroy_cq(hca_ptr->ib_trans.ib_cq_empty);\r
-               ibv_destroy_comp_channel(channel);\r
-       }\r
+       if (hca_ptr->ib_trans.ib_cq)
+               ibv_destroy_comp_channel(hca_ptr->ib_trans.ib_cq);
+
+       if (hca_ptr->ib_trans.ib_cq_empty) {
+               struct ibv_comp_channel *channel;
+               channel = hca_ptr->ib_trans.ib_cq_empty->channel;
+               ibv_destroy_cq(hca_ptr->ib_trans.ib_cq_empty);
+               ibv_destroy_comp_channel(channel);
+       }
 
        if (hca_ptr->ib_hca_handle != IB_INVALID_HANDLE) {
                if (ibv_close_device(hca_ptr->ib_hca_handle))
index 0036950680573e4810d6ff0a21c550320a71b23c..f1eb23b8842e3a43b8c637f187df6a3b75c82310 100644 (file)
@@ -17,7 +17,7 @@ if not "!F!" == "off" (
 rem set DAT_OVERRIDE=D:\dapl2\dat.conf\r
 rem favor DAT 2.0 (dapl2test.exe) over DAT 1.1 (dapltest.exe)\r
 \r
-set PF="%ProgramFiles%\OFED"\r
+set PF="%ProgramFiles%\WinOF"\r
 \r
 if NOT EXIST %PF%\dapl2test.exe (\r
     echo Missing file %PF%\dapl2test.exe ?\r
index 9c1888294ef44e910cea1b315e694b09ad7d36cf..abd17fb00f48e0b113a55f6aac22b1da4c30839c 100644 (file)
@@ -6,7 +6,7 @@ SETLOCAL
 \r
 rem set DAT_OVERRIDE=C:\DAT\dat.conf\r
 \r
-set PF="%ProgramFiles%\OFED"\r
+set PF="%ProgramFiles%\WinOF"\r
 \r
 if NOT EXIST %PF%\dapl2test.exe (\r
     echo Missing file %PF%\dapl2test.exe ?\r