+commit 6c6a482b8ad33d134f0631019b249bd0fea71007
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Thu Jun 17 12:40:21 2010 -0700
+
+ scm, ucm: add pkey, pkey_index, sl override for QP's
+
+ On a per open basis, add environment variables
+ DAPL_IB_SL and DAPL_IB_PKEY and use on
+ connection setup (QP modify) to override default
+ values of 0 for SL and PKEY index. If pkey is
+ provided then find the pkey index with
+ ibv_query_pkey for dev_attr.max_pkeys.
+ Will be used for RC and UD type QP's.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 876942781e9bf72302184f3534a2ddc4068550ac
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Thu Jun 10 11:40:45 2010 -0700
+
+ cma: remove dependency on rdma_cma_abi.h
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit b34ea37650b5eefeedfc463345775ff568df259e
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Jun 2 14:13:05 2010 -0700
+
+ configure: need a false conditional for verbs attr.link_layer member check
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 977f11871d3d4e98f602f890ade1c31cf4169c9c
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Jun 2 10:05:03 2010 -0700
+
+ ucm: incorrectly freeing port on passive side after reject
+
+ cm_release was incorrectly freeing a client port
+ assuming it was the server listening port. Move
+ the listening port cleanup to remove_conn_listner
+ and only cleanup client ports in cm_release.
+
+ Error Messages indicating problem:
+
+ CM_REQ retry 1 [lid, port, qpn]: 9 ff9a 340085 -> 9 6fa 34004e Time(ms) 1999 > 1600
+ DUPLICATE: op REQ st CM_CONNECTED [lid, port, qpn]: 9 6fa 0x0 <- 0x9 ff9a 0x340085
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 7aedfb1e9dcb9e2841ebe3496bb9aae33c1f6a5b
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Jun 2 09:45:42 2010 -0700
+
+ ucm: modify debug CM output for consistency, all ports, qpn in hex
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 8e776ff0621cee1824be224b7a32f79e89b0ebc2
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 24 16:44:25 2010 -0700
+
+ Release 2.0.28
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 8fdbd949ef464aa57b13743ab087ea72f035fbc3
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 24 16:28:05 2010 -0700
+
+ config: add conditional check for new verbs port_attr.link_layer
+
+ Check for link_layer type ETHERNET and set global for GID
+ configuration on modify QP.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 1ce0875fb2ac6120cfee006b48a20a4ec38f599b
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 24 10:30:28 2010 -0700
+
+ dat.conf: update manpage with latest provider information, add examples
+
+ Add information regarding OpenFabrics provider choices
+ and explain cma, scm, and ucm providers.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 9c42d5872feb07f25f003e01263a3062ebc3bdbb
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed May 19 16:38:53 2010 -0700
+
+ cma, scm: new provider entries for Mellanox RDMA over Ethernet device
+
+ Add options for netdev eth2 and eth3 for cma and for device mlx4_0 port 1 and 2 for scm.
+
+ ofa-v2-cma-roe-eth2 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 "eth2 0" ""
+ ofa-v2-cma-roe-eth3 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 "eth3 0" ""
+ ofa-v2-scm-roe-mlx4_0-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "mlx4_0 1" ""
+ ofa-v2-scm-roe-mlx4_0-2 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "mlx4_0 2" ""
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit d947e05317fe7fef19c90f772ec8f458ff52b196
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed May 19 15:17:58 2010 -0700
+
+ dapltest: server info devicename is not large enough for dapl_name storage
+
+ Server info device name is a 80 char array but the dapl device name
+ that is copied is 256 bytes. Increase started_server.devicename definition.
+ Chalk one up for windows SDK OACR (auto code review).
+
+ Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+commit c7a7a886af194cf735ee1eb62d9e14967d51249a
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed May 19 14:48:49 2010 -0700
+
+ windows: comp_channel.cpp is included by util.c in the openib_common.
+
+ Remove it from device.c in individual providers to avoid
+ duplicate definitions.
+
+ Line endings were corrected to linux format from windows as part of
+ the change.
+
+ Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+commit bcaa400778d14a977d5cd224056baa0cff06126d
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed May 19 14:45:55 2010 -0700
+
+ windows: need to include linux directory to pick up _errno.h
+
+ Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+commit c616a8549db461e39feed71f0f10228313d17b90
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 17 16:22:30 2010 -0700
+
+ scm: check for hca object before signaling thread
+
+ There may not be an hca object attached to cm object
+ when freeing during cleanup.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 1dbba72741da267f71903a9f2ec03628f3e8a47a
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 17 16:15:21 2010 -0700
+
+ scm, cma: fini code can be called multiple times and hang via fork
+
+ The providers should protect against forked child exits and
+ not cleanup until the parent init actually exits. Otherwise,
+ the child will hang trying to cleanup dapl thread. Modify to
+ check process id for proper init to fini cleanup and limit
+ cleanup to parent only.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit b35cb1b16a9dda349dbb19bce9f9bd4afb7240a4
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Fri May 14 16:20:52 2010 -0700
+
+ scm: add option to use other network devices with environment variable DAPL_SCM_NETDEV
+
+ New environment variable can be used to set the netdev
+ for sockets to use instead of the default network device
+ returned using gethostname.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit cfdf8bb8951b1c19b8e42d58e4ec26070fdc078e
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Fri May 14 10:27:50 2010 -0700
+
+ scm: cr_thread occasionally segv's when disconnecting all-to-all MPI static connections
+
+ Note: no valid calltrace for segv on cr_thread because
+ of state changing in switch statement from another
+ thread, jumped unknown location.
+
+ Program received signal SIGSEGV, Segmentation fault.
+ [Switching to Thread 0x41a65940 (LWP 1328)]
+ 0x00002b2e7d9d5134 in ?? ()
+
+ Add cm object locking on all state change/checking. When
+ freeing CM object wakeup cr_thread to process
+ state change to CM_FREE.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 4b04afc32940ac42fb2a9bc789a537b527d149fe
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Thu May 13 10:31:17 2010 -0700
+
+ scm: SOCKOPT ERR Connection timed out on large clusters
+
+ Large scale all to all connections on +1000 cores
+ the listen backlog is reached and SYN's are dropped
+ which causes the connect to timeout. Retry connect
+ on timeout errors.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 625369f991982f020c04156f312ecf2ecafd77b3
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 10 12:46:17 2010 -0700
+
+ ucm: UD mode, active side cm object released to soon, the RTU could be lost.
+
+ Will see following message with DAPL_DBG_TYPE set for Errors & Warnings (0x3):
+ ucm_recv: NO MATCH op REP 0x120 65487 i0x60005e c0x60005e < 0xd2 19824 0x60006a
+
+ The cm object was released on the active side after the connection
+ was established, RTU sent. This is a problem if the RTU is lost
+ and the remote side retries the REPLY. The RTU is never resent.
+ Keep the cm object until the EP is destroyed.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 83eec7f19a7442fe568dea685cee7b02fef2f4d1
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon May 10 12:35:51 2010 -0700
+
+ cma, ucm: cleanup issues with dat_ep_free on a connected EP without disconnecting.
+
+ During EP free, disconnecting with ABRUPT close flag, the disconnect should wait
+ for the DISC event to fire to allow the CM to be properly destroyed upon return.
+
+ The cma must also release the lock when calling the blocking rdma_destroy_id given
+ the callback thread could attempt to acquire the lock for reference counting.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit da83172db68d05f54b2c1c77b84ecf86dea0c693
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Apr 28 15:37:27 2010 -0700
+
+ ucm: increase default UCM retry count for connect reply to 15
+
+ On very large clusters UCM is timing out with retries at 10.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 5c710a197bb60268e99e8d1cd7fa26f89b366172
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Apr 27 11:20:08 2010 -0700
+
+ scm: remove modify QP to ERR state during disconnect on UD type QP
+
+ The disconnect on a UD type QP should not modify QP to error
+ since this is a shared QP. The disconnect should be treated
+ as a NOP on the UD type QP and only be transitioned during
+ the QP destroy (dat_ep_free).
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 64c8009f7ba48c22a6829862447ab5f67c66ba55
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Thu Apr 8 16:32:02 2010 -0700
+
+ windows: remove static paths from dapltest scripts
+
+ signed-off-by: stan smith <stan.smith@intel.com>
+
+commit 84b78b0b586ee25c7ab78e2c5f7f19a3ce3f21ee
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Thu Apr 8 09:38:57 2010 -0700
+
+ common: EP links to EVD, PZ incorrectly released before provider CM objects freed.
+
+ unlink/clear references after ALL CM objects linked to EP are freed.
+ Otherwise, event processing via CM objects could reference the handles
+ still linked to EP. After CM objects are freed (blocking) these handles
+ linked to EP are guaranteed not to refereence from underlying provider.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 297e149e7af631663ecc60472a3ee093a7f72059
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Apr 7 11:12:21 2010 -0700
+
+ common: remove unnecessary lmr lkey hashing and duplicate lkey checking
+
+ lmr lkey hashing is too restrictive given the returned lkey could be
+ the same value for different regions on some rdma devices. Actually,
+ this checking is really unecesssary and requires considerable overhead
+ for hashing so just remove hashing of lmr lkey's. Let verbs device
+ level do the checking and validation.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 96fba2ee7a0a1766f200c9486e62aad46d18bb09
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon Mar 29 12:20:34 2010 -0800
+
+ ibal: output completion code in deciaml & hex as intended
+
+ sign-off-by: stan smith <stan.smith@intel.com>
+
+commit 753f7d35c814367f431deeb307e6decd933a8b5a
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 15:02:44 2010 -0800
+
+ ucm: set timer during RTU_PENDING state change.
+
+ The timer thread may pick up an unitialized timer
+ value and timeout before the reply was sent.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 9fc851021d91b282054cf28b4f83f7e5d376f228
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 14:47:58 2010 -0800
+
+ ucm: fix issues with new EP to CM linking changes
+
+ Add EP locking around QP modify
+ Remove release during disconnect event processing
+ Add check in cm_free to check state and schedule thread if necessary.
+ Add some additional debugging
+ Add processing in disconnect_clean for conn_req timeout
+ Remove extra CR's
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit a5da5e4dac52366a9fe9efeb9a128bd4511481e2
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 14:18:06 2010 -0800
+
+ scm: add EP locking and cm checking to socket cm disconnect
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 7f733cd1a9acd4b9b270a807673290362050053d
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 09:44:44 2010 -0800
+
+ scm: new cm_ep linking broke UD mode over socket cm
+
+ Add EP locking around modify_qp for EP state.
+ Add new dapli_ep_check for debugging EP
+ Cleanup extra CR's
+ Change socket errno to dapl_socket_errno() abstraction
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit a528267020972e0c449f240ba72a0cc80a5d372e
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 09:17:01 2010 -0800
+
+ openib common: add some debug prints to help isolate QP type issues
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit fdfdc439d091c878c74d23b9ac46a3320379199d
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 09:15:12 2010 -0800
+
+ common: dapl_event_str function missing 2 IB extended events
+
+ Add all IB extended events in event string print function
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 2bf3eb939e9a584ae0fe2de70f16cdcca8acf014
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Mar 16 09:12:11 2010 -0800
+
+ common: dat_ep_connect should not set timer UD endpoints
+
+ connect for UD type is simply AH resolution and doesn't
+ need timed. The common code is not designed to handle
+ multiple timed events on connect requests so just ignore
+ timing UD AH requests.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 73ca06debe4735dfc11f44076a13dde079657b2e
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon Mar 15 10:23:47 2010 -0800
+
+ ucm: fix error path during accept_usr reply failure
+
+ if accept_usr fails when sending reply the EP was
+ being linked to CM instead of properly unlinked.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 944ef4445faceeb90bb61d4e377274ad0fd6711f
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon Mar 8 13:56:28 2010 -0800
+
+ ibal: add missing windows makefile
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 1d53e8eb90e6f74b41e7767e1c71851ff4ec73fd
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Mon Mar 8 12:53:45 2010 -0800
+
+ ibal: changes for EP to CM linking and synchronization.
+
+ Windows IBAL changes to allocate and manage CM objects
+ and to link them to the EP. This will insure the CM
+ IBAL objects and cm_id's are not destroy before EP.
+ Remove windows only ibal_cm_handle in EP structure.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 4b939076aa32bb52957fcc6791e187c9433d4c24
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Feb 24 12:00:07 2010 -0800
+
+ scm: add support for canceling conn request that times out.
+
+ print warning message during timeout.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit f38fc04d517ee6c0560b271298293c56cc619522
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Feb 24 11:28:04 2010 -0800
+
+ scm, cma, ucm: consolidate dat event/provider event translation
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 41739dab38a4be8076ecd9e61b5e175cf91ab322
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Feb 24 11:26:25 2010 -0800
+
+ common: missed linking changes from atomic to acquire/release
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit 7ff4f840bf1150fa2c2f541c93d810622ea9733b
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Wed Feb 24 10:03:57 2010 -0800
+
+ common: add CM-EP linking to support mutiple CM's and proper protection during destruction
+
+ Add linking for CM to EP, including reference counting, to insure syncronization
+ during creation and destruction. A cm_list_head has been added to the EP object to
+ support multiple CM objects (UD) per EP. If the CM object is linked to an EP it
+ cannot be destroyed.
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
+commit c9fbd6e7a8131d4077039d5da716b618727d4009
+Author: Arlin Davis <arlin.r.davis@intel.com>
+Date: Tue Feb 23 16:26:41 2010 -0800
+
+ Release 2.0.27-1
+
+ Signed-off-by: Arlin Davis <arlin.r.davis@intel.com>
+
commit 454c27b1f357c7c3070e459b25d12929f86304ca
Author: Arlin Davis <arlin.r.davis@intel.com>
Date: Mon Feb 22 09:42:17 2010 -0800
XPROGRAMS =
endif
+if DEFINE_ATTR_LINK_LAYER
+XFLAGS += -DDEFINE_ATTR_LINK_LAYER
+endif
+
if DEBUG
AM_CFLAGS = -g -Wall -D_GNU_SOURCE -DDAPL_DBG -DDAT_CONF="\"$(sysconfdir)/dat.conf\""
else
echo ofa-v2-mlx4_0-1u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mlx4_0 1" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
echo ofa-v2-mlx4_0-2u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mlx4_0 2" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
echo ofa-v2-mthca0-1u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mthca0 1" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
- echo ofa-v2-mthca0-2u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mthca0 2" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf;
+ echo ofa-v2-mthca0-2u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mthca0 2" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
+ echo ofa-v2-cma-roe-eth2 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 '"eth2 0" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
+ echo ofa-v2-cma-roe-eth3 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 '"eth3 0" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
+ echo ofa-v2-scm-roe-mlx4_0-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 '"mlx4_0 1" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf; \
+ echo ofa-v2-scm-roe-mlx4_0-2 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 '"mlx4_0 2" ""' >> $(DESTDIR)$(sysconfdir)/dat.conf;
uninstall-hook:
if test -e $(DESTDIR)$(sysconfdir)/dat.conf; then \
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
-AC_INIT(dapl, 2.0.27, linux-rdma@vger.kernel.org)
+AC_INIT(dapl, 2.0.29, 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.27)
+AM_INIT_AUTOMAKE(dapl, 2.0.29)
AM_PROG_LIBTOOL
then
AC_CHECK_LIB(ibverbs, ibv_get_device_list, [],
AC_MSG_ERROR([ibv_get_device_list() not found. libdapl requires libibverbs.]))
-fi
-dnl Checks for header files.
-if test "$disable_libcheck" != "yes"
-then
AC_CHECK_HEADER(infiniband/verbs.h, [],
AC_MSG_ERROR([<infiniband/verbs.h> not found. Is libibverbs installed?]))
+
+AC_CHECK_MEMBER(struct ibv_port_attr.link_layer,
+ AM_CONDITIONAL(DEFINE_ATTR_LINK_LAYER, test "yes" = "yes"),
+ AM_CONDITIONAL(DEFINE_ATTR_LINK_LAYER, test "yes" = "no"),
+ [#include <infiniband/verbs.h>])
+else
+ AM_CONDITIONAL(DEFINE_ATTR_LINK_LAYER, test "yes" = "no")
fi
AC_CACHE_CHECK(whether ld accepts --version-script, ac_cv_version_script,
echo ofa-v2-mlx4_0-2u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mlx4_0 2" ""' >> %{_sysconfdir}/dat.conf
echo ofa-v2-mthca0-1u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mthca0 1" ""' >> %{_sysconfdir}/dat.conf
echo ofa-v2-mthca0-2u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 '"mthca0 2" ""' >> %{_sysconfdir}/dat.conf
+echo ofa-v2-cma-roe-eth2 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 '"eth2 0" ""' >> %{_sysconfdir}/dat.conf
+echo ofa-v2-cma-roe-eth3 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 '"eth3 0" ""' >> %{_sysconfdir}/dat.conf
+echo ofa-v2-scm-roe-mlx4_0-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 '"mlx4_0 1" ""' >> %{_sysconfdir}/dat.conf
+echo ofa-v2-scm-roe-mlx4_0-2 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 '"mlx4_0 2" ""' >> %{_sysconfdir}/dat.conf
%postun
/sbin/ldconfig
%{_mandir}/man5/*.5*
%changelog
+* Thu Jun 17 2010 Arlin Davis <ardavis@ichips.intel.com> - 2.0.29
+- DAT/DAPL Version 2.0.29 Release 1, OFED 1.5.2 RC2
+
+* Mon May 24 2010 Arlin Davis <ardavis@ichips.intel.com> - 2.0.28
+- DAT/DAPL Version 2.0.28 Release 1, OFED 1.5.2 RC1
+
* 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
-/*\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
+/*
+ * 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 CR 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));
+}
dapl_os_lock(&ep_ptr->header.lock);
if (ep_ptr->param.ep_state ==
DAT_EP_STATE_ACTIVE_CONNECTION_PENDING
- && timeout != DAT_TIMEOUT_INFINITE) {
+ && timeout != DAT_TIMEOUT_INFINITE &&
+ ep_ptr->param.ep_attr.service_type == DAT_SERVICE_TYPE_RC) {
ep_ptr->cxn_timer =
(DAPL_OS_TIMER *)
dapl_os_alloc(sizeof(DAPL_OS_TIMER));
*/
(void)dapl_ep_disconnect(ep_ptr, DAT_CLOSE_ABRUPT_FLAG);
+ /* 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;
+ }
+
/*
* Do verification of parameters and the state change atomically.
*/
}
}
- /* 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);
-/*\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_util.c\r
- *\r
- * PURPOSE: Manage EP Info structure\r
- *\r
- * $Id:$\r
- **********************************************************************/\r
-\r
-#include "dapl_ep_util.h"\r
-#include "dapl_ring_buffer_util.h"\r
-#include "dapl_cookie.h"\r
-#include "dapl_adapter_util.h"\r
-#include "dapl_evd_util.h"\r
-#include "dapl_cr_util.h" /* for callback routine */\r
-\r
-/*\r
- * Local definitions\r
- */\r
-/*\r
- * Default number of I/O operations on an end point\r
- */\r
-#define IB_IO_DEFAULT 16\r
-/*\r
- * Default number of scatter/gather entries available to a single\r
- * post send/recv\r
- */\r
-#define IB_IOV_DEFAULT 4\r
-\r
-/*\r
- * Default number of RDMA operations in progress at a time\r
- */\r
-#define IB_RDMA_DEFAULT 4\r
-\r
-extern void dapli_ep_default_attrs(IN DAPL_EP * ep_ptr);\r
-\r
-char *dapl_get_ep_state_str(DAT_EP_STATE state)\r
-{\r
-#ifdef DAPL_DBG\r
- static char *state_str[DAT_EP_STATE_CONNECTED_MULTI_PATH + 1] = {\r
- "DAT_EP_STATE_UNCONNECTED", /* quiescent state */\r
- "DAT_EP_STATE_UNCONFIGURED_UNCONNECTED",\r
- "DAT_EP_STATE_RESERVED",\r
- "DAT_EP_STATE_UNCONFIGURED_RESERVED",\r
- "DAT_EP_STATE_PASSIVE_CONNECTION_PENDING",\r
- "DAT_EP_STATE_UNCONFIGURED_PASSIVE",\r
- "DAT_EP_STATE_ACTIVE_CONNECTION_PENDING",\r
- "DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING",\r
- "DAT_EP_STATE_UNCONFIGURED_TENTATIVE",\r
- "DAT_EP_STATE_CONNECTED",\r
- "DAT_EP_STATE_DISCONNECT_PENDING",\r
- "DAT_EP_STATE_DISCONNECTED",\r
- "DAT_EP_STATE_COMPLETION_PENDING",\r
- "DAT_EP_STATE_CONNECTED_SINGLE_PATH",\r
- "DAT_EP_STATE_CONNECTED_MULTI_PATH"\r
- };\r
- return state_str[state];\r
-#else\r
- static char buf[12];\r
- sprintf(buf, "%d", state);\r
- return buf;\r
-#endif\r
-}\r
-\r
-/*\r
- * dapl_ep_alloc\r
- *\r
- * alloc and initialize an EP INFO struct\r
- *\r
- * Input:\r
- * IA INFO struct ptr\r
- *\r
- * Output:\r
- * ep_ptr\r
- *\r
- * Returns:\r
- * none\r
- *\r
- */\r
-DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr)\r
-{\r
- DAPL_EP *ep_ptr;\r
-\r
- /* Allocate EP */\r
- ep_ptr =\r
- (DAPL_EP *) dapl_os_alloc(sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));\r
- if (ep_ptr == NULL) {\r
- goto bail;\r
- }\r
-\r
- /* zero the structure */\r
- dapl_os_memzero(ep_ptr, sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));\r
-\r
-#ifdef DAPL_COUNTERS\r
- /* Allocate counters */\r
- ep_ptr->cntrs =\r
- dapl_os_alloc(sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);\r
- if (ep_ptr->cntrs == NULL) {\r
- dapl_os_free(ep_ptr, sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));\r
- return (NULL);\r
- }\r
- dapl_os_memzero(ep_ptr->cntrs,\r
- sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);\r
-#endif /* DAPL_COUNTERS */\r
-\r
- /*\r
- * initialize the header\r
- */\r
- ep_ptr->header.provider = ia_ptr->header.provider;\r
- ep_ptr->header.magic = DAPL_MAGIC_EP;\r
- ep_ptr->header.handle_type = DAT_HANDLE_TYPE_EP;\r
- ep_ptr->header.owner_ia = ia_ptr;\r
- ep_ptr->header.user_context.as_64 = 0;\r
- 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
- * Initialize the body\r
- */\r
- /*\r
- * Set up default parameters if the user passed in a NULL\r
- */\r
- if (ep_attr == NULL) {\r
- dapli_ep_default_attrs(ep_ptr);\r
- } else {\r
- ep_ptr->param.ep_attr = *ep_attr;\r
- }\r
-\r
- /*\r
- * IBM OS API specific fields\r
- */\r
- ep_ptr->qp_handle = IB_INVALID_HANDLE;\r
- ep_ptr->qpn = 0;\r
- ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;\r
-\r
- if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->req_buffer,\r
- ep_ptr,\r
- ep_ptr->param.ep_attr.\r
- max_request_dtos)) {\r
- dapl_ep_dealloc(ep_ptr);\r
- ep_ptr = NULL;\r
- goto bail;\r
- }\r
-\r
- if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->recv_buffer,\r
- ep_ptr,\r
- ep_ptr->param.ep_attr.max_recv_dtos))\r
- {\r
- dapl_ep_dealloc(ep_ptr);\r
- ep_ptr = NULL;\r
- goto bail;\r
- }\r
-\r
- dapls_io_trc_alloc(ep_ptr);\r
-\r
- bail:\r
- return ep_ptr;\r
-}\r
-\r
-/*\r
- * dapl_ep_dealloc\r
- *\r
- * Free the passed in EP structure.\r
- *\r
- * Input:\r
- * entry point pointer\r
- *\r
- * Output:\r
- * none\r
- *\r
- * Returns:\r
- * none\r
- *\r
- */\r
-void dapl_ep_dealloc(IN DAPL_EP * ep_ptr)\r
-{\r
- dapl_os_assert(ep_ptr->header.magic == DAPL_MAGIC_EP);\r
-\r
- ep_ptr->header.magic = DAPL_MAGIC_INVALID; /* reset magic to prevent reuse */\r
-\r
- dapls_cb_free(&ep_ptr->req_buffer);\r
- dapls_cb_free(&ep_ptr->recv_buffer);\r
-\r
- if (NULL != ep_ptr->cxn_timer) {\r
- dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));\r
- }\r
-\r
-#ifdef DAPL_COUNTERS\r
- dapl_os_free(ep_ptr->cntrs, sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);\r
-#endif /* DAPL_COUNTERS */\r
-\r
- dapl_os_free(ep_ptr, sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));\r
-}\r
-\r
-/*\r
- * dapl_ep_default_attrs\r
- *\r
- * Set default values in the parameter fields\r
- *\r
- * Input:\r
- * entry point pointer\r
- *\r
- * Output:\r
- * none\r
- *\r
- * Returns:\r
- * none\r
- *\r
- */\r
-void dapli_ep_default_attrs(IN DAPL_EP * ep_ptr)\r
-{\r
- DAT_EP_ATTR ep_attr_limit;\r
- DAT_EP_ATTR *ep_attr;\r
- DAT_RETURN dat_status;\r
-\r
- ep_attr = &ep_ptr->param.ep_attr;\r
- /* Set up defaults */\r
- dapl_os_memzero(ep_attr, sizeof(DAT_EP_ATTR));\r
-\r
- /* mtu and rdma sizes fixed in IB as per IBTA 1.1, 9.4.3, 9.4.4, 9.7.7. */\r
- ep_attr->max_mtu_size = 0x80000000;\r
- ep_attr->max_rdma_size = 0x80000000;\r
-\r
- ep_attr->qos = DAT_QOS_BEST_EFFORT;\r
- ep_attr->service_type = DAT_SERVICE_TYPE_RC;\r
- ep_attr->max_recv_dtos = IB_IO_DEFAULT;\r
- ep_attr->max_request_dtos = IB_IO_DEFAULT;\r
- ep_attr->max_recv_iov = IB_IOV_DEFAULT;\r
- ep_attr->max_request_iov = IB_IOV_DEFAULT;\r
- ep_attr->max_rdma_read_in = IB_RDMA_DEFAULT;\r
- ep_attr->max_rdma_read_out = IB_RDMA_DEFAULT;\r
-\r
- /*\r
- * Configure the EP as a standard completion type, which will be\r
- * used by the EVDs. A threshold of 1 is the default state of an\r
- * EVD.\r
- */\r
- ep_attr->request_completion_flags = DAT_COMPLETION_EVD_THRESHOLD_FLAG;\r
- ep_attr->recv_completion_flags = DAT_COMPLETION_EVD_THRESHOLD_FLAG;\r
- /*\r
- * Unspecified defaults:\r
- * - ep_privileges: No RDMA capabilities\r
- * - num_transport_specific_params: none\r
- * - transport_specific_params: none\r
- * - num_provider_specific_params: 0\r
- * - provider_specific_params: 0\r
- */\r
-\r
- dat_status = dapls_ib_query_hca(ep_ptr->header.owner_ia->hca_ptr,\r
- NULL, &ep_attr_limit, NULL);\r
- /* check against HCA maximums */\r
- if (dat_status == DAT_SUCCESS) {\r
- ep_ptr->param.ep_attr.max_mtu_size =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_mtu_size,\r
- ep_attr_limit.max_mtu_size);\r
- ep_ptr->param.ep_attr.max_rdma_size =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_rdma_size,\r
- ep_attr_limit.max_rdma_size);\r
- ep_ptr->param.ep_attr.max_recv_dtos =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_recv_dtos,\r
- ep_attr_limit.max_recv_dtos);\r
- ep_ptr->param.ep_attr.max_request_dtos =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_request_dtos,\r
- ep_attr_limit.max_request_dtos);\r
- ep_ptr->param.ep_attr.max_recv_iov =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_recv_iov,\r
- ep_attr_limit.max_recv_iov);\r
- ep_ptr->param.ep_attr.max_request_iov =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_request_iov,\r
- ep_attr_limit.max_request_iov);\r
- ep_ptr->param.ep_attr.max_rdma_read_in =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_rdma_read_in,\r
- ep_attr_limit.max_rdma_read_in);\r
- ep_ptr->param.ep_attr.max_rdma_read_out =\r
- DAPL_MIN(ep_ptr->param.ep_attr.max_rdma_read_out,\r
- ep_attr_limit.max_rdma_read_out);\r
- }\r
-}\r
-\r
-DAT_RETURN dapl_ep_check_recv_completion_flags(DAT_COMPLETION_FLAGS flags)\r
-{\r
-\r
- /*\r
- * InfiniBand will not allow signal suppression for RECV completions,\r
- * see the 1.0.1 spec section 10.7.3.1, 10.8.6.\r
- * N.B. SIGNALLED has a different meaning in dapl than it does\r
- * in IB; IB SIGNALLED is the same as DAPL SUPPRESS. DAPL\r
- * SIGNALLED simply means the user will not get awakened when\r
- * an EVD completes, even though the dapl handler is invoked.\r
- */\r
-\r
- if (flags & DAT_COMPLETION_SUPPRESS_FLAG) {\r
- return DAT_INVALID_PARAMETER;\r
- }\r
-\r
- return DAT_SUCCESS;\r
-}\r
-\r
-DAT_RETURN dapl_ep_check_request_completion_flags(DAT_COMPLETION_FLAGS flags)\r
-{\r
- return DAT_SUCCESS;\r
-}\r
-\r
-DAT_RETURN\r
-dapl_ep_post_send_req(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
- IN DAPL_DTO_TYPE dto_type, IN int op_type)\r
-{\r
- DAPL_EP *ep_ptr;\r
- DAPL_COOKIE *cookie;\r
- DAT_RETURN dat_status;\r
-\r
- if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) {\r
- dat_status =\r
- DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);\r
- goto bail;\r
- }\r
-\r
- ep_ptr = (DAPL_EP *) ep_handle;\r
-\r
- /*\r
- * Synchronization ok since this buffer is only used for send\r
- * requests, which aren't allowed to race with each other.\r
- */\r
- dat_status = dapls_dto_cookie_alloc(&ep_ptr->req_buffer,\r
- dto_type, user_cookie, &cookie);\r
- if (dat_status != DAT_SUCCESS) {\r
- dapl_log(DAPL_DBG_TYPE_ERR,\r
- " dapl_post_req resource ERR:"\r
- " dtos pending = %d, max_dtos %d, max_cb %d hd %d tl %d\n",\r
- dapls_cb_pending(&ep_ptr->req_buffer),\r
- ep_ptr->param.ep_attr.max_request_dtos,\r
- ep_ptr->req_buffer.pool_size,\r
- ep_ptr->req_buffer.head, ep_ptr->req_buffer.tail);\r
-\r
- goto bail;\r
- }\r
-\r
- /*\r
- * Invoke provider specific routine to post DTO\r
- */\r
- dat_status = dapls_ib_post_send(ep_ptr,\r
- op_type,\r
- cookie,\r
- num_segments,\r
- local_iov,\r
- remote_iov, completion_flags);\r
-\r
- if (dat_status != DAT_SUCCESS) {\r
- dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);\r
- }\r
-\r
- bail:\r
- return dat_status;\r
-}\r
-\r
-/*\r
- * dapli_ep_timeout\r
- *\r
- * If this routine is invoked before a connection occurs, generate an\r
- * event\r
- */\r
-void dapls_ep_timeout(uintptr_t arg)\r
-{\r
- DAPL_EP *ep_ptr;\r
- ib_cm_events_t ib_cm_event;\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapls_ep_timeout! ep %lx\n", arg);\r
-\r
- ep_ptr = (DAPL_EP *) arg;\r
-\r
- /* reset the EP state */\r
- ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
-\r
- /* Clean up the EP and put the underlying QP into the ERROR state.\r
- * 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_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
- connect_evd_handle,\r
- DAT_CONNECTION_EVENT_TIMED_OUT,\r
- (DAT_HANDLE) ep_ptr, 0, 0);\r
-}\r
-\r
-/*\r
- * dapls_ep_state_subtype\r
- *\r
- * Return the INVALID_STATE connection subtype associated with an\r
- * INVALID_STATE on an EP. Strictly for error reporting.\r
- */\r
-DAT_RETURN_SUBTYPE dapls_ep_state_subtype(IN DAPL_EP * ep_ptr)\r
-{\r
- DAT_RETURN_SUBTYPE dat_status;\r
-\r
- switch (ep_ptr->param.ep_state) {\r
- case DAT_EP_STATE_UNCONNECTED:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_UNCONNECTED;\r
- break;\r
- }\r
- case DAT_EP_STATE_RESERVED:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_RESERVED;\r
- break;\r
- }\r
- case DAT_EP_STATE_PASSIVE_CONNECTION_PENDING:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_PASSCONNPENDING;\r
- break;\r
- }\r
- case DAT_EP_STATE_ACTIVE_CONNECTION_PENDING:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_ACTCONNPENDING;\r
- break;\r
- }\r
- case DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_TENTCONNPENDING;\r
- break;\r
- }\r
- case DAT_EP_STATE_CONNECTED:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_CONNECTED;\r
- break;\r
- }\r
- case DAT_EP_STATE_DISCONNECT_PENDING:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_DISCPENDING;\r
- break;\r
- }\r
- case DAT_EP_STATE_DISCONNECTED:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_DISCONNECTED;\r
- break;\r
- }\r
- case DAT_EP_STATE_COMPLETION_PENDING:\r
- {\r
- dat_status = DAT_INVALID_STATE_EP_COMPLPENDING;\r
- break;\r
- }\r
-\r
- default:\r
- {\r
- dat_status = 0;\r
- break;\r
- }\r
- }\r
-\r
- return dat_status;\r
-}\r
-\r
-#ifdef DAPL_DBG_IO_TRC\r
-/* allocate trace buffer */\r
-void dapls_io_trc_alloc(DAPL_EP * ep_ptr)\r
-{\r
- DAT_RETURN dat_status;\r
- int i;\r
- struct io_buf_track *ibt;\r
-\r
- ep_ptr->ibt_dumped = 0; /* bool to control how often we print */\r
- dat_status = dapls_rbuf_alloc(&ep_ptr->ibt_queue, DBG_IO_TRC_QLEN);\r
- if (dat_status != DAT_SUCCESS) {\r
- goto bail;\r
- }\r
- ibt =\r
- (struct io_buf_track *)dapl_os_alloc(sizeof(struct io_buf_track) *\r
- DBG_IO_TRC_QLEN);\r
-\r
- if (dat_status != DAT_SUCCESS) {\r
- dapls_rbuf_destroy(&ep_ptr->ibt_queue);\r
- goto bail;\r
- }\r
- ep_ptr->ibt_base = ibt;\r
- dapl_os_memzero(ibt, sizeof(struct io_buf_track) * DBG_IO_TRC_QLEN);\r
-\r
- /* add events to free event queue */\r
- for (i = 0; i < DBG_IO_TRC_QLEN; i++) {\r
- dapls_rbuf_add(&ep_ptr->ibt_queue, ibt++);\r
- }\r
- bail:\r
- return;\r
-}\r
-#endif /* DAPL_DBG_IO_TRC */\r
-\r
-/*\r
- * Generate a disconnect event on abruct close for older verbs providers \r
- * that do not do it automatically.\r
- */\r
-\r
-void\r
-dapl_ep_legacy_post_disconnect(DAPL_EP * ep_ptr,\r
- DAT_CLOSE_FLAGS disconnect_flags)\r
-{\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
- * that cleaned up.\r
- */\r
- dapl_os_lock(&ep_ptr->header.lock);\r
- if (disconnect_flags == DAT_CLOSE_ABRUPT_FLAG &&\r
- ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) {\r
- /*\r
- * If this is an ABRUPT close, the provider will not generate\r
- * a disconnect message so we do it manually here. Just invoke\r
- * the CM callback as it will clean up the appropriate\r
- * data structures, reset the state, and generate the event\r
- * on the way out. Obtain the provider dependent cm_event to \r
- * pass into the callback for a disconnect.\r
- */\r
- ib_cm_event =\r
- 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
- dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,\r
- " dapl_ep_disconnect force callback on EP %p CM handle %x\n",\r
- ep_ptr, cr_ptr->ib_cm_handle);\r
-\r
- 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(cm_ptr,\r
- ib_cm_event,\r
- NULL, 0, (void *)ep_ptr);\r
- }\r
- } else {\r
- dapl_os_unlock(&ep_ptr->header.lock);\r
- }\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
- * 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_util.c
+ *
+ * PURPOSE: Manage EP Info structure
+ *
+ * $Id:$
+ **********************************************************************/
+
+#include "dapl_ep_util.h"
+#include "dapl_ring_buffer_util.h"
+#include "dapl_cookie.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_cr_util.h" /* for callback routine */
+
+/*
+ * Local definitions
+ */
+/*
+ * Default number of I/O operations on an end point
+ */
+#define IB_IO_DEFAULT 16
+/*
+ * Default number of scatter/gather entries available to a single
+ * post send/recv
+ */
+#define IB_IOV_DEFAULT 4
+
+/*
+ * Default number of RDMA operations in progress at a time
+ */
+#define IB_RDMA_DEFAULT 4
+
+extern void dapli_ep_default_attrs(IN DAPL_EP * ep_ptr);
+
+char *dapl_get_ep_state_str(DAT_EP_STATE state)
+{
+#ifdef DAPL_DBG
+ static char *state_str[DAT_EP_STATE_CONNECTED_MULTI_PATH + 1] = {
+ "DAT_EP_STATE_UNCONNECTED", /* quiescent state */
+ "DAT_EP_STATE_UNCONFIGURED_UNCONNECTED",
+ "DAT_EP_STATE_RESERVED",
+ "DAT_EP_STATE_UNCONFIGURED_RESERVED",
+ "DAT_EP_STATE_PASSIVE_CONNECTION_PENDING",
+ "DAT_EP_STATE_UNCONFIGURED_PASSIVE",
+ "DAT_EP_STATE_ACTIVE_CONNECTION_PENDING",
+ "DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING",
+ "DAT_EP_STATE_UNCONFIGURED_TENTATIVE",
+ "DAT_EP_STATE_CONNECTED",
+ "DAT_EP_STATE_DISCONNECT_PENDING",
+ "DAT_EP_STATE_DISCONNECTED",
+ "DAT_EP_STATE_COMPLETION_PENDING",
+ "DAT_EP_STATE_CONNECTED_SINGLE_PATH",
+ "DAT_EP_STATE_CONNECTED_MULTI_PATH"
+ };
+ return state_str[state];
+#else
+ static char buf[12];
+ sprintf(buf, "%d", state);
+ return buf;
+#endif
+}
+
+/*
+ * dapl_ep_alloc
+ *
+ * alloc and initialize an EP INFO struct
+ *
+ * Input:
+ * IA INFO struct ptr
+ *
+ * Output:
+ * ep_ptr
+ *
+ * Returns:
+ * none
+ *
+ */
+DAPL_EP *dapl_ep_alloc(IN DAPL_IA * ia_ptr, IN const DAT_EP_ATTR * ep_attr)
+{
+ DAPL_EP *ep_ptr;
+
+ /* Allocate EP */
+ ep_ptr =
+ (DAPL_EP *) dapl_os_alloc(sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));
+ if (ep_ptr == NULL) {
+ goto bail;
+ }
+
+ /* zero the structure */
+ dapl_os_memzero(ep_ptr, sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));
+
+#ifdef DAPL_COUNTERS
+ /* Allocate counters */
+ ep_ptr->cntrs =
+ dapl_os_alloc(sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);
+ if (ep_ptr->cntrs == NULL) {
+ dapl_os_free(ep_ptr, sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));
+ return (NULL);
+ }
+ dapl_os_memzero(ep_ptr->cntrs,
+ sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);
+#endif /* DAPL_COUNTERS */
+
+ /*
+ * initialize the header
+ */
+ ep_ptr->header.provider = ia_ptr->header.provider;
+ ep_ptr->header.magic = DAPL_MAGIC_EP;
+ ep_ptr->header.handle_type = DAT_HANDLE_TYPE_EP;
+ ep_ptr->header.owner_ia = ia_ptr;
+ ep_ptr->header.user_context.as_64 = 0;
+ ep_ptr->header.user_context.as_ptr = NULL;
+
+ dapl_llist_init_entry(&ep_ptr->header.ia_list_entry);
+ dapl_llist_init_head(&ep_ptr->cm_list_head);
+ dapl_os_lock_init(&ep_ptr->header.lock);
+
+ /*
+ * Initialize the body
+ */
+ /*
+ * Set up default parameters if the user passed in a NULL
+ */
+ if (ep_attr == NULL) {
+ dapli_ep_default_attrs(ep_ptr);
+ } else {
+ ep_ptr->param.ep_attr = *ep_attr;
+ }
+
+ /*
+ * IBM OS API specific fields
+ */
+ ep_ptr->qp_handle = IB_INVALID_HANDLE;
+ ep_ptr->qpn = 0;
+ ep_ptr->qp_state = DAPL_QP_STATE_UNATTACHED;
+
+ if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->req_buffer,
+ ep_ptr,
+ ep_ptr->param.ep_attr.
+ max_request_dtos)) {
+ dapl_ep_dealloc(ep_ptr);
+ ep_ptr = NULL;
+ goto bail;
+ }
+
+ if (DAT_SUCCESS != dapls_cb_create(&ep_ptr->recv_buffer,
+ ep_ptr,
+ ep_ptr->param.ep_attr.max_recv_dtos))
+ {
+ dapl_ep_dealloc(ep_ptr);
+ ep_ptr = NULL;
+ goto bail;
+ }
+
+ dapls_io_trc_alloc(ep_ptr);
+
+ bail:
+ return ep_ptr;
+}
+
+/*
+ * dapl_ep_dealloc
+ *
+ * Free the passed in EP structure.
+ *
+ * Input:
+ * entry point pointer
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * none
+ *
+ */
+void dapl_ep_dealloc(IN DAPL_EP * ep_ptr)
+{
+ dapl_os_assert(ep_ptr->header.magic == DAPL_MAGIC_EP);
+
+ ep_ptr->header.magic = DAPL_MAGIC_INVALID; /* reset magic to prevent reuse */
+
+ dapls_cb_free(&ep_ptr->req_buffer);
+ dapls_cb_free(&ep_ptr->recv_buffer);
+
+ if (NULL != ep_ptr->cxn_timer) {
+ dapl_os_free(ep_ptr->cxn_timer, sizeof(DAPL_OS_TIMER));
+ }
+
+#ifdef DAPL_COUNTERS
+ dapl_os_free(ep_ptr->cntrs, sizeof(DAT_UINT64) * DCNT_EP_ALL_COUNTERS);
+#endif /* DAPL_COUNTERS */
+
+ dapl_os_free(ep_ptr, sizeof(DAPL_EP) + sizeof(DAT_SOCK_ADDR));
+}
+
+/*
+ * dapl_ep_default_attrs
+ *
+ * Set default values in the parameter fields
+ *
+ * Input:
+ * entry point pointer
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * none
+ *
+ */
+void dapli_ep_default_attrs(IN DAPL_EP * ep_ptr)
+{
+ DAT_EP_ATTR ep_attr_limit;
+ DAT_EP_ATTR *ep_attr;
+ DAT_RETURN dat_status;
+
+ ep_attr = &ep_ptr->param.ep_attr;
+ /* Set up defaults */
+ dapl_os_memzero(ep_attr, sizeof(DAT_EP_ATTR));
+
+ /* mtu and rdma sizes fixed in IB as per IBTA 1.1, 9.4.3, 9.4.4, 9.7.7. */
+ ep_attr->max_mtu_size = 0x80000000;
+ ep_attr->max_rdma_size = 0x80000000;
+
+ ep_attr->qos = DAT_QOS_BEST_EFFORT;
+ ep_attr->service_type = DAT_SERVICE_TYPE_RC;
+ ep_attr->max_recv_dtos = IB_IO_DEFAULT;
+ ep_attr->max_request_dtos = IB_IO_DEFAULT;
+ ep_attr->max_recv_iov = IB_IOV_DEFAULT;
+ ep_attr->max_request_iov = IB_IOV_DEFAULT;
+ ep_attr->max_rdma_read_in = IB_RDMA_DEFAULT;
+ ep_attr->max_rdma_read_out = IB_RDMA_DEFAULT;
+
+ /*
+ * Configure the EP as a standard completion type, which will be
+ * used by the EVDs. A threshold of 1 is the default state of an
+ * EVD.
+ */
+ ep_attr->request_completion_flags = DAT_COMPLETION_EVD_THRESHOLD_FLAG;
+ ep_attr->recv_completion_flags = DAT_COMPLETION_EVD_THRESHOLD_FLAG;
+ /*
+ * Unspecified defaults:
+ * - ep_privileges: No RDMA capabilities
+ * - num_transport_specific_params: none
+ * - transport_specific_params: none
+ * - num_provider_specific_params: 0
+ * - provider_specific_params: 0
+ */
+
+ dat_status = dapls_ib_query_hca(ep_ptr->header.owner_ia->hca_ptr,
+ NULL, &ep_attr_limit, NULL);
+ /* check against HCA maximums */
+ if (dat_status == DAT_SUCCESS) {
+ ep_ptr->param.ep_attr.max_mtu_size =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_mtu_size,
+ ep_attr_limit.max_mtu_size);
+ ep_ptr->param.ep_attr.max_rdma_size =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_rdma_size,
+ ep_attr_limit.max_rdma_size);
+ ep_ptr->param.ep_attr.max_recv_dtos =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_recv_dtos,
+ ep_attr_limit.max_recv_dtos);
+ ep_ptr->param.ep_attr.max_request_dtos =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_request_dtos,
+ ep_attr_limit.max_request_dtos);
+ ep_ptr->param.ep_attr.max_recv_iov =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_recv_iov,
+ ep_attr_limit.max_recv_iov);
+ ep_ptr->param.ep_attr.max_request_iov =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_request_iov,
+ ep_attr_limit.max_request_iov);
+ ep_ptr->param.ep_attr.max_rdma_read_in =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_rdma_read_in,
+ ep_attr_limit.max_rdma_read_in);
+ ep_ptr->param.ep_attr.max_rdma_read_out =
+ DAPL_MIN(ep_ptr->param.ep_attr.max_rdma_read_out,
+ ep_attr_limit.max_rdma_read_out);
+ }
+}
+
+DAT_RETURN dapl_ep_check_recv_completion_flags(DAT_COMPLETION_FLAGS flags)
+{
+
+ /*
+ * InfiniBand will not allow signal suppression for RECV completions,
+ * see the 1.0.1 spec section 10.7.3.1, 10.8.6.
+ * N.B. SIGNALLED has a different meaning in dapl than it does
+ * in IB; IB SIGNALLED is the same as DAPL SUPPRESS. DAPL
+ * SIGNALLED simply means the user will not get awakened when
+ * an EVD completes, even though the dapl handler is invoked.
+ */
+
+ if (flags & DAT_COMPLETION_SUPPRESS_FLAG) {
+ return DAT_INVALID_PARAMETER;
+ }
+
+ return DAT_SUCCESS;
+}
+
+DAT_RETURN dapl_ep_check_request_completion_flags(DAT_COMPLETION_FLAGS flags)
+{
+ return DAT_SUCCESS;
+}
+
+DAT_RETURN
+dapl_ep_post_send_req(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,
+ IN DAPL_DTO_TYPE dto_type, IN int op_type)
+{
+ DAPL_EP *ep_ptr;
+ DAPL_COOKIE *cookie;
+ DAT_RETURN dat_status;
+
+ if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) {
+ dat_status =
+ DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP);
+ goto bail;
+ }
+
+ ep_ptr = (DAPL_EP *) ep_handle;
+
+ /*
+ * Synchronization ok since this buffer is only used for send
+ * requests, which aren't allowed to race with each other.
+ */
+ dat_status = dapls_dto_cookie_alloc(&ep_ptr->req_buffer,
+ dto_type, user_cookie, &cookie);
+ if (dat_status != DAT_SUCCESS) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " dapl_post_req resource ERR:"
+ " dtos pending = %d, max_dtos %d, max_cb %d hd %d tl %d\n",
+ dapls_cb_pending(&ep_ptr->req_buffer),
+ ep_ptr->param.ep_attr.max_request_dtos,
+ ep_ptr->req_buffer.pool_size,
+ ep_ptr->req_buffer.head, ep_ptr->req_buffer.tail);
+
+ goto bail;
+ }
+
+ /*
+ * Invoke provider specific routine to post DTO
+ */
+ dat_status = dapls_ib_post_send(ep_ptr,
+ op_type,
+ cookie,
+ num_segments,
+ local_iov,
+ remote_iov, completion_flags);
+
+ if (dat_status != DAT_SUCCESS) {
+ dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);
+ }
+
+ bail:
+ return dat_status;
+}
+
+/*
+ * dapli_ep_timeout
+ *
+ * If this routine is invoked before a connection occurs, generate an
+ * event
+ */
+void dapls_ep_timeout(uintptr_t arg)
+{
+ DAPL_EP *ep_ptr;
+ ib_cm_events_t ib_cm_event;
+
+ dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapls_ep_timeout! ep %lx\n", arg);
+
+ ep_ptr = (DAPL_EP *) arg;
+
+ /* reset the EP state */
+ ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
+
+ /* Clean up the EP and put the underlying QP into the ERROR state.
+ * The disconnect_clean interface requires the provided dependent
+ *cm event number.
+ */
+ ib_cm_event = dapls_ib_get_cm_event(DAT_CONNECTION_EVENT_TIMED_OUT);
+ dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, ib_cm_event);
+
+ (void)dapls_evd_post_connection_event((DAPL_EVD *) ep_ptr->param.
+ connect_evd_handle,
+ DAT_CONNECTION_EVENT_TIMED_OUT,
+ (DAT_HANDLE) ep_ptr, 0, 0);
+}
+
+/*
+ * dapls_ep_state_subtype
+ *
+ * Return the INVALID_STATE connection subtype associated with an
+ * INVALID_STATE on an EP. Strictly for error reporting.
+ */
+DAT_RETURN_SUBTYPE dapls_ep_state_subtype(IN DAPL_EP * ep_ptr)
+{
+ DAT_RETURN_SUBTYPE dat_status;
+
+ switch (ep_ptr->param.ep_state) {
+ case DAT_EP_STATE_UNCONNECTED:
+ {
+ dat_status = DAT_INVALID_STATE_EP_UNCONNECTED;
+ break;
+ }
+ case DAT_EP_STATE_RESERVED:
+ {
+ dat_status = DAT_INVALID_STATE_EP_RESERVED;
+ break;
+ }
+ case DAT_EP_STATE_PASSIVE_CONNECTION_PENDING:
+ {
+ dat_status = DAT_INVALID_STATE_EP_PASSCONNPENDING;
+ break;
+ }
+ case DAT_EP_STATE_ACTIVE_CONNECTION_PENDING:
+ {
+ dat_status = DAT_INVALID_STATE_EP_ACTCONNPENDING;
+ break;
+ }
+ case DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING:
+ {
+ dat_status = DAT_INVALID_STATE_EP_TENTCONNPENDING;
+ break;
+ }
+ case DAT_EP_STATE_CONNECTED:
+ {
+ dat_status = DAT_INVALID_STATE_EP_CONNECTED;
+ break;
+ }
+ case DAT_EP_STATE_DISCONNECT_PENDING:
+ {
+ dat_status = DAT_INVALID_STATE_EP_DISCPENDING;
+ break;
+ }
+ case DAT_EP_STATE_DISCONNECTED:
+ {
+ dat_status = DAT_INVALID_STATE_EP_DISCONNECTED;
+ break;
+ }
+ case DAT_EP_STATE_COMPLETION_PENDING:
+ {
+ dat_status = DAT_INVALID_STATE_EP_COMPLPENDING;
+ break;
+ }
+
+ default:
+ {
+ dat_status = 0;
+ break;
+ }
+ }
+
+ return dat_status;
+}
+
+#ifdef DAPL_DBG_IO_TRC
+/* allocate trace buffer */
+void dapls_io_trc_alloc(DAPL_EP * ep_ptr)
+{
+ DAT_RETURN dat_status;
+ int i;
+ struct io_buf_track *ibt;
+
+ ep_ptr->ibt_dumped = 0; /* bool to control how often we print */
+ dat_status = dapls_rbuf_alloc(&ep_ptr->ibt_queue, DBG_IO_TRC_QLEN);
+ if (dat_status != DAT_SUCCESS) {
+ goto bail;
+ }
+ ibt =
+ (struct io_buf_track *)dapl_os_alloc(sizeof(struct io_buf_track) *
+ DBG_IO_TRC_QLEN);
+
+ if (dat_status != DAT_SUCCESS) {
+ dapls_rbuf_destroy(&ep_ptr->ibt_queue);
+ goto bail;
+ }
+ ep_ptr->ibt_base = ibt;
+ dapl_os_memzero(ibt, sizeof(struct io_buf_track) * DBG_IO_TRC_QLEN);
+
+ /* add events to free event queue */
+ for (i = 0; i < DBG_IO_TRC_QLEN; i++) {
+ dapls_rbuf_add(&ep_ptr->ibt_queue, ibt++);
+ }
+ bail:
+ return;
+}
+#endif /* DAPL_DBG_IO_TRC */
+
+/*
+ * Generate a disconnect event on abruct close for older verbs providers
+ * that do not do it automatically.
+ */
+
+void
+dapl_ep_legacy_post_disconnect(DAPL_EP * ep_ptr,
+ DAT_CLOSE_FLAGS disconnect_flags)
+{
+ ib_cm_events_t ib_cm_event;
+ DAPL_CR *cr_ptr;
+ dp_ib_cm_handle_t cm_ptr;
+
+ /*
+ * Acquire the lock and make sure we didn't get a callback
+ * that cleaned up.
+ */
+ dapl_os_lock(&ep_ptr->header.lock);
+ if (disconnect_flags == DAT_CLOSE_ABRUPT_FLAG &&
+ ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) {
+ /*
+ * If this is an ABRUPT close, the provider will not generate
+ * a disconnect message so we do it manually here. Just invoke
+ * the CM callback as it will clean up the appropriate
+ * data structures, reset the state, and generate the event
+ * on the way out. Obtain the provider dependent cm_event to
+ * pass into the callback for a disconnect.
+ */
+ ib_cm_event =
+ dapls_ib_get_cm_event(DAT_CONNECTION_EVENT_DISCONNECTED);
+
+ cr_ptr = ep_ptr->cr_ptr;
+ 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);
+
+ if (cr_ptr != NULL) {
+ dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,
+ " dapl_ep_disconnect force callback on EP %p CM handle %x\n",
+ ep_ptr, cr_ptr->ib_cm_handle);
+
+ dapls_cr_callback(cr_ptr->ib_cm_handle,
+ ib_cm_event, NULL, 0, cr_ptr->sp_ptr);
+ } else {
+ dapl_evd_connection_callback(cm_ptr,
+ ib_cm_event,
+ NULL, 0, (void *)ep_ptr);
+ }
+ } else {
+ dapl_os_unlock(&ep_ptr->header.lock);
+ }
+}
+
+/*
+ * dapl_ep_link_cm
+ *
+ * Add linking of provider's CM object to a EP structure
+ * This enables multiple CM's per EP, and syncronization
+ *
+ * Input:
+ * DAPL_EP *ep_ptr
+ * dp_ib_cm_handle_t *cm_ptr defined in provider's dapl_util.h
+ *
+ * CM objects linked with EP using ->list_entry
+ * Output:
+ * none
+ *
+ * Returns:
+ * none
+ *
+ */
+void dapl_ep_link_cm(IN DAPL_EP *ep_ptr, IN dp_ib_cm_handle_t cm_ptr)
+{
+ dapl_os_lock(&ep_ptr->header.lock);
+ dapls_cm_acquire(cm_ptr);
+ dapl_llist_add_tail(&ep_ptr->cm_list_head, &cm_ptr->list_entry, cm_ptr);
+ dapl_os_unlock(&ep_ptr->header.lock);
+}
+
+void dapl_ep_unlink_cm(IN DAPL_EP *ep_ptr, IN dp_ib_cm_handle_t cm_ptr)
+{
+ dapl_os_lock(&ep_ptr->header.lock);
+ dapl_llist_remove_entry(&ep_ptr->cm_list_head, &cm_ptr->list_entry);
+ dapls_cm_release(cm_ptr);
+ dapl_os_unlock(&ep_ptr->header.lock);
+}
+
+/*
+ * Local variables:
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 8
+ * End:
+ */
DAT_IB_EXTENSION_RANGE_BASE + 1},
{"DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED",
DAT_IB_EXTENSION_RANGE_BASE + 2},
+ {"DAT_IB_UD_CONNECTION_REJECT_EVENT",
+ DAT_IB_EXTENSION_RANGE_BASE + 3},
+ {"DAT_IB_UD_CONNECTION_ERROR_EVENT",
+ DAT_IB_EXTENSION_RANGE_BASE + 4},
{"DAT_IW_EXTENSION_RANGE_BASE", DAT_IW_EXTENSION_RANGE_BASE},
#endif /* DAT_EXTENSIONS */
{NULL, 0},
#include "dapl_adapter_util.h"
#include "dapl_provider.h"
#include "dapl_hca_util.h"
-#include "dapl_hash.h"
/*
* dapl_hca_alloc
}
dapl_os_memzero(hca_ptr, sizeof(DAPL_HCA));
-
- if (DAT_SUCCESS !=
- dapls_hash_create(DAPL_HASH_TABLE_DEFAULT_CAPACITY,
- &hca_ptr->lmr_hash_table)) {
- goto bail;
- }
-
dapl_os_lock_init(&hca_ptr->lock);
dapl_llist_init_head(&hca_ptr->ia_list_head);
return (hca_ptr);
bail:
- if (NULL != hca_ptr) {
- if (NULL != hca_ptr->lmr_hash_table) {
- dapls_hash_free(hca_ptr->lmr_hash_table);
- }
-
+ if (NULL != hca_ptr)
dapl_os_free(hca_ptr, sizeof(DAPL_HCA));
- }
return NULL;
}
*/
void dapl_hca_free(DAPL_HCA * hca_ptr)
{
- (void)dapls_hash_free(hca_ptr->lmr_hash_table);
dapl_os_free(hca_ptr->name, dapl_os_strlen(hca_ptr->name) + 1);
dapl_os_free(hca_ptr, sizeof(DAPL_HCA));
}
return DAT_INVALID_STATE;
}
- dat_status =
- dapls_hash_remove(lmr->header.owner_ia->hca_ptr->
- lmr_hash_table,
- lmr->param.lmr_context, NULL);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-
dat_status = dapls_ib_mr_deregister(lmr);
if (dat_status == DAT_SUCCESS) {
dapl_os_atomic_dec(&pz->pz_ref_count);
dapl_lmr_dealloc(lmr);
- } else {
- /*
- * Deregister failed; put it back in the
- * hash table.
- */
- dapls_hash_insert(lmr->header.owner_ia->
- hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, lmr);
- }
-
+ }
break;
}
#if defined(__KDAPL__)
STATIC _INLINE_ DAT_RETURN
dapli_rmr_bind_fuse(IN DAPL_RMR * rmr,
- IN const DAT_LMR_TRIPLET * lmr_triplet,
+ IN DAT_LMR_HANDLE lmr_handle,
+ IN const DAT_LMR_TRIPLET * lmr_triplet,
IN DAT_MEM_PRIV_FLAGS mem_priv,
IN DAPL_EP * ep_ptr,
IN DAT_RMR_COOKIE user_cookie,
DAT_RETURN
dapli_rmr_bind_fuse(IN DAPL_RMR * rmr,
+ IN DAT_LMR_HANDLE lmr_handle,
IN const DAT_LMR_TRIPLET * lmr_triplet,
IN DAT_MEM_PRIV_FLAGS mem_priv,
IN DAPL_EP * ep_ptr,
DAPL_COOKIE *cookie;
DAT_RETURN dat_status;
DAT_BOOLEAN is_signaled;
- DAPL_HASH_DATA hash_lmr;
- dat_status =
- dapls_hash_search(rmr->header.owner_ia->hca_ptr->lmr_hash_table,
- lmr_triplet->lmr_context, &hash_lmr);
- if (DAT_SUCCESS != dat_status) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
- goto bail;
- }
- lmr = (DAPL_LMR *) hash_lmr;
+ lmr = (DAPL_LMR *) lmr_handle;
/* if the ep in unconnected return an error. IB requires that the */
/* QP be connected to change a memory window binding since: */
/* if the rmr should be bound */
if (0 != lmr_triplet->segment_length) {
return dapli_rmr_bind_fuse(rmr,
+ lmr_handle,
lmr_triplet,
mem_priv,
ep_ptr,
-\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_cm.c\r
- *\r
- * PURPOSE: IB Connection routines for access to IBAL APIs\r
- *\r
- * $Id: dapl_ibal_cm.c 584 2007-02-07 13:12:18Z sleybo $\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_sp_util.h"\r
-#include "dapl_ep_util.h"\r
-#include "dapl_ia_util.h"\r
-#include "dapl_ibal_util.h"\r
-#include "dapl_name_service.h"\r
-#include "dapl_ibal_name_service.h"\r
-#include "dapl_cookie.h"\r
-\r
-#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF\r
-#define DAPL_ATS_SERVICE_ID ATS_SERVICE_ID //0x10000CE100415453\r
-#define DAPL_ATS_NAME ATS_NAME\r
-#define HCA_IPV6_ADDRESS_LENGTH 16\r
-\r
-/* until dapl_ibal_util.h define of IB_INVALID_HANDLE which overlaps the\r
- * Windows ib_types.h typedef enu ib_api_status_t IB_INVALID_HANDLE is fixed.\r
- */\r
-#undef IB_INVALID_HANDLE\r
-#define DAPL_IB_INVALID_HANDLE NULL\r
-\r
-int g_dapl_loopback_connection = 0;\r
-extern dapl_ibal_root_t dapl_ibal_root;\r
-\r
-/*\r
- * Prototypes\r
- */\r
-\r
-char *\r
-dapli_ib_cm_event_str(ib_cm_events_t e)\r
-{\r
-#ifdef DBG\r
- char *cp;\r
- static char *event_str[13] = {\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
- };\r
-\r
- if (e > IB_CM_LOCAL_FAILURE || e < IB_CME_CONNECTED)\r
- cp = "BAD EVENT";\r
- else\r
- cp = event_str[e];\r
-\r
- return cp;\r
-#else\r
- static char num[8];\r
- sprintf(num,"%d",e);\r
- return num;\r
-#endif\r
-}\r
-\r
-\r
-#if defined(DAPL_DBG)\r
-\r
-void dapli_print_private_data( char *prefix, const uint8_t *pd, int len )\r
-{\r
- int i;\r
- \r
- if ( !pd || len <= 0 )\r
- return;\r
-\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
- dapl_log ( DAPL_DBG_TYPE_ERR,\r
- " Private data size(%d) > Max(%d), ignored.\n ",\r
- len,DAPL_MAX_PRIVATE_DATA_SIZE);\r
- len = IB_MAX_REP_PDATA_SIZE;\r
- }\r
-\r
- for ( i = 0 ; i < len; i++ )\r
- {\r
- dapl_log ( DAPL_DBG_TYPE_CM, "%2x ", pd[i]);\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
- IN ib_cm_apr_rec_t *p_cm_apr_rec )\r
-{\r
- UNUSED_PARAM( p_cm_apr_rec );\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCAcb: CM callback APR (Alternate Path Request)\n");\r
-}\r
-\r
-static void \r
-dapli_ib_cm_lap_cb (\r
- IN ib_cm_lap_rec_t *p_cm_lap_rec )\r
-{\r
- UNUSED_PARAM( p_cm_lap_rec );\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCLcb: CM callback LAP (Load Alternate Path)\n");\r
-}\r
-\r
-/*\r
- * Connection Disconnect Request callback\r
- * We received a DREQ, return a DREP (disconnect reply).\r
- */\r
-\r
-static void \r
-dapli_ib_cm_dreq_cb (\r
- IN ib_cm_dreq_rec_t *p_cm_dreq_rec )\r
-{\r
- 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
- ep_ptr = (DAPL_EP * __ptr64) p_cm_dreq_rec->qp_context;\r
- if ( DAPL_BAD_PTR(ep_ptr) )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, \r
- "--> %s: BAD_PTR EP %lx\n", __FUNCTION__, ep_ptr);\r
- return;\r
- }\r
- if ( ep_ptr->header.magic != DAPL_MAGIC_EP )\r
- {\r
- if ( ep_ptr->header.magic == DAPL_MAGIC_INVALID )\r
- return;\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
- "--> %s: EP %p BAD_EP_MAGIC %x != wanted %x\n",\r
- __FUNCTION__, ep_ptr, ep_ptr->header.magic,\r
- 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
- __FUNCTION__,ep_ptr,\r
- dapl_get_ep_state_str(ep_ptr->param.ep_state),\r
- (ep_ptr->sent_discreq == DAT_TRUE ? "TRUE":"FALSE"));\r
-\r
- dapl_os_lock (&ep_ptr->header.lock);\r
- if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED\r
- /*|| ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING\r
- && ep_ptr->sent_discreq == DAT_TRUE)*/ )\r
- {\r
- dapl_os_unlock (&ep_ptr->header.lock);\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCDcb: EP %lx QP %lx already Disconnected\n",\r
- ep_ptr, ep_ptr->qp_handle);\r
- return;\r
- }\r
-\r
- ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING;\r
- ep_ptr->recv_discreq = DAT_TRUE;\r
- dapl_os_unlock (&ep_ptr->header.lock);\r
-\r
- dapl_os_memzero (&cm_drep, sizeof(ib_cm_drep_t));\r
-\r
- /* Could fail if we received reply from other side, no need to retry */\r
- /* Wait for any send ops in process holding reference */\r
- while (dapls_cb_pending(&ep_ptr->req_buffer) && bail-- > 0 )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCDcb: WAIT for EP=%lx req_count(%d) != 0\n", \r
- ep_ptr, dapls_cb_pending(&ep_ptr->req_buffer));\r
- dapl_os_sleep_usec (100);\r
- }\r
-\r
- ib_cm_drep (p_cm_dreq_rec->h_cm_dreq, &cm_drep);\r
-\r
- /* CM puts QP in reset state */\r
- ep_ptr->qp_state = IB_QPS_RESET;\r
- \r
- if (ep_ptr->cr_ptr)\r
- {\r
- /* passive side */\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
- (void *) (((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr) );\r
- }\r
- else\r
- {\r
- /* active side */\r
- dapl_evd_connection_callback (\r
- cm_ptr,\r
- IB_CME_DISCONNECTED,\r
- (void * __ptr64)\r
- p_cm_dreq_rec->p_dreq_pdata,\r
- IB_DREQ_PDATA_SIZE,\r
- p_cm_dreq_rec->qp_context );\r
- }\r
-}\r
-\r
-/*\r
- * Connection Disconnect Reply callback\r
- * We sent a DREQ and received a DREP.\r
- */\r
-\r
-static void \r
-dapli_ib_cm_drep_cb (\r
- 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
- ep_ptr = (DAPL_EP * __ptr64) p_cm_drep_rec->qp_context;\r
-\r
- if (p_cm_drep_rec->cm_status)\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "--> %s: DREP cm_status(%s) EP=%p\n", __FUNCTION__,\r
- ib_get_err_str(p_cm_drep_rec->cm_status), ep_ptr); \r
- }\r
-\r
- if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
- "--> %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
- cm_ptr);\r
-\r
- if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, \r
- "--> DiCDpcb: EP %lx QP %lx already Disconnected\n",\r
- ep_ptr, ep_ptr->qp_handle);\r
- return;\r
- }\r
-\r
- if (ep_ptr->cr_ptr)\r
- {\r
- /* passive connection side */\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
- (void *) (((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr) );\r
- }\r
- else\r
- {\r
- /* active connection side */\r
- dapl_evd_connection_callback (\r
- cm_ptr,\r
- IB_CME_DISCONNECTED,\r
- (void * __ptr64) p_cm_drep_rec->p_drep_pdata,\r
- IB_DREP_PDATA_SIZE,\r
- p_cm_drep_rec->qp_context );\r
- }\r
-}\r
-\r
-/*\r
- * CM reply callback\r
- */\r
-\r
-static void \r
-dapli_ib_cm_rep_cb (\r
- IN ib_cm_rep_rec_t *p_cm_rep_rec )\r
-{\r
- ib_api_status_t ib_status; \r
- ib_cm_rtu_t cm_rtu;\r
- uint8_t cm_cb_op;\r
- 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
- ep_ptr = (DAPL_EP * __ptr64) p_cm_rep_rec->qp_context;\r
-\r
- if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: EP %lx invalid or FREED\n",\r
- __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
- ep_ptr, p_cm_rep_rec->resp_res);\r
-\r
- p_ca = (dapl_ibal_ca_t *) \r
- ep_ptr->header.owner_ia->hca_ptr->ib_hca_handle;\r
-\r
- dapl_os_memzero (&cm_rtu, sizeof ( ib_cm_rtu_t ));\r
- cm_rtu.pfn_cm_apr_cb = dapli_ib_cm_apr_cb;\r
- cm_rtu.pfn_cm_dreq_cb = dapli_ib_cm_dreq_cb;\r
- cm_rtu.p_rtu_pdata = NULL;\r
- cm_rtu.access_ctrl = \r
- IB_AC_LOCAL_WRITE|IB_AC_RDMA_WRITE|IB_AC_MW_BIND|IB_AC_ATOMIC;\r
- if ((ep_ptr->param.ep_attr.max_rdma_read_in > 0) || \r
- (ep_ptr->param.ep_attr.max_rdma_read_out > 0))\r
- {\r
- cm_rtu.access_ctrl |= IB_AC_RDMA_READ;\r
- }\r
- \r
- cm_rtu.rq_depth = 0;\r
- cm_rtu.sq_depth = 0;\r
- \r
- ib_status = ib_cm_rtu (p_cm_rep_rec->h_cm_rep, &cm_rtu);\r
-\r
- if (ib_status == IB_SUCCESS)\r
- {\r
- cm_cb_op = IB_CME_CONNECTED;\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCRpcb: EP %lx Connected req_count %d\n", \r
- ep_ptr, dapls_cb_pending(&ep_ptr->req_buffer));\r
- }\r
- else\r
- {\r
- cm_cb_op = IB_CME_LOCAL_FAILURE;\r
- }\r
-\r
- prd_ptr = (DAPL_PRIVATE * __ptr64) p_cm_rep_rec->p_rep_pdata;\r
-\r
-#if defined(DAPL_DBG) && 0\r
- dapli_print_private_data( "DiCRpcb",\r
- prd_ptr->private_data,\r
- IB_MAX_REP_PDATA_SIZE);\r
-#endif\r
-\r
- dapl_evd_connection_callback ( \r
- cm_ptr,\r
- cm_cb_op,\r
- (void *) prd_ptr,\r
- IB_REP_PDATA_SIZE,\r
- (void * __ptr64) p_cm_rep_rec->qp_context);\r
-}\r
-\r
-\r
-static void \r
-dapli_ib_cm_rej_cb (\r
- IN ib_cm_rej_rec_t *p_cm_rej_rec )\r
-{\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
- ep_ptr = (DAPL_EP * __ptr64) p_cm_rej_rec->qp_context;\r
-\r
- if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: EP %lx invalid or FREED\n",\r
- __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
- ep_ptr,ep_ptr->qp_handle,CL_NTOH16(p_cm_rej_rec->rej_status));\r
-\r
- switch (p_cm_rej_rec->rej_status)\r
- {\r
- case IB_REJ_INSUF_RESOURCES:\r
- case IB_REJ_INSUF_QP:\r
- case IB_REJ_INVALID_COMM_ID:\r
- case IB_REJ_INVALID_COMM_INSTANCE:\r
- case IB_REJ_INVALID_PKT_RATE:\r
- case IB_REJ_INVALID_ALT_GID:\r
- case IB_REJ_INVALID_ALT_LID:\r
- case IB_REJ_INVALID_ALT_SL:\r
- case IB_REJ_INVALID_ALT_TRAFFIC_CLASS:\r
- case IB_REJ_INVALID_ALT_PKT_RATE:\r
- case IB_REJ_INVALID_ALT_HOP_LIMIT:\r
- case IB_REJ_INVALID_ALT_FLOW_LBL:\r
- case IB_REJ_INVALID_GID:\r
- case IB_REJ_INVALID_LID:\r
- case IB_REJ_INVALID_SID:\r
- case IB_REJ_INVALID_SL:\r
- case IB_REJ_INVALID_TRAFFIC_CLASS:\r
- case IB_REJ_PORT_REDIRECT:\r
- case IB_REJ_INVALID_MTU:\r
- case IB_REJ_INSUFFICIENT_RESP_RES:\r
- case IB_REJ_INVALID_CLASS_VER:\r
- case IB_REJ_INVALID_FLOW_LBL:\r
- cm_event = IB_CME_DESTINATION_REJECT;\r
- break;\r
-\r
- case IB_REJ_TIMEOUT:\r
- cm_event = IB_CME_DESTINATION_UNREACHABLE;\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, "--> DiCRjcb: CR TIMEOUT\n");\r
- break;\r
-\r
- case IB_REJ_USER_DEFINED:\r
- cm_event = IB_CME_DESTINATION_REJECT;\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCRjcb: user defined rej reason %s\n",\r
- p_cm_rej_rec->p_ari);\r
- break;\r
-\r
- default:\r
- cm_event = IB_CME_LOCAL_FAILURE;\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DiCRjcb: with unknown status %x\n", \r
- p_cm_rej_rec->rej_status);\r
- break;\r
- }\r
-\r
- /* FIXME - Vu\r
- * We do not take care off the user defined rej reason with additional \r
- * rejection information (p_ari)\r
- */\r
-\r
- if (ep_ptr->cr_ptr)\r
- {\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
- (void *) ((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr);\r
- }\r
- else\r
- {\r
- dapl_evd_connection_callback (\r
- cm_ptr,\r
- cm_event,\r
- (void * __ptr64) p_cm_rej_rec->p_rej_pdata,\r
- IB_REJ_PDATA_SIZE,\r
- (void * __ptr64) p_cm_rej_rec->qp_context );\r
- }\r
-\r
-}\r
-\r
-\r
-\r
-static void \r
-dapli_ib_cm_req_cb ( IN ib_cm_req_rec_t *p_cm_req_rec )\r
-{\r
- DAPL_SP *sp_ptr;\r
- DAT_SOCK_ADDR6 dest_ia_addr;\r
- dp_ib_cm_handle_t cm_ptr;\r
-\r
- dapl_os_assert (p_cm_req_rec);\r
-\r
- sp_ptr = (DAPL_SP * __ptr64) p_cm_req_rec->context;\r
-\r
- dapl_os_assert (sp_ptr);\r
-\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
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "%s: BAD-Magic in SP %lx, racing CM callback?\n",\r
- __FUNCTION__, sp_ptr );\r
- return;\r
- }\r
-\r
- dapl_os_assert ( sp_ptr->header.magic == DAPL_MAGIC_PSP || \r
- sp_ptr->header.magic == DAPL_MAGIC_RSP );\r
-\r
- /* preserve ibal's connection handle storage so we have a consistent\r
- * pointer value. The reasons this is done dynamically instead of a static\r
- * allocation in an end_point is the pointer value is set in the SP list\r
- * of CR's here and searched for from disconnect callbacks. If the pointer\r
- * value changes, you never find the CR on the sp list...\r
- * EP struct deallocation is where this memory is released or prior in the\r
- * error case.\r
- */\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
- __FUNCTION__);\r
- return;\r
- }\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
- */\r
- if (sp_ptr->cm_srvc_handle != p_cm_req_rec->h_cm_listen)\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK, \r
- "--> DiCRqcb: cm_service_handle is changed\n"); \r
- sp_ptr->cm_srvc_handle = p_cm_req_rec->h_cm_listen;\r
- }\r
-\r
- dapl_os_memzero (&dest_ia_addr, sizeof (dest_ia_addr));\r
-\r
-#ifdef NO_NAME_SERVICE\r
-\r
- {\r
- DAPL_PRIVATE *prd_ptr;\r
- \r
- prd_ptr = (DAPL_PRIVATE *)p_cm_req_rec->p_req_pdata;\r
-\r
- dapl_os_memcpy ((void *)&dest_ia_addr,\r
- (void *)&prd_ptr->hca_address,\r
- sizeof (DAT_SOCK_ADDR6)); \r
- }\r
- \r
-#else\r
-\r
- {\r
- GID dest_gid;\r
-\r
- dapl_os_memzero (&dest_gid, sizeof (dest_gid));\r
-\r
- dest_gid.guid = p_cm_req_rec->primary_path.dgid.unicast.interface_id;\r
- dest_gid.gid_prefix = p_cm_req_rec->primary_path.dgid.unicast.prefix;\r
-\r
- if (DAT_SUCCESS != dapls_ns_map_ipaddr (\r
- sp_ptr->header.owner_ia->hca_ptr,\r
- dest_gid,\r
- (DAT_IA_ADDRESS_PTR)&dest_ia_addr))\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "cm_req_cb: SP = %lx failed mapping GID-IPaddr\n",\r
- sp_ptr);\r
- }\r
- }\r
-\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
- \r
- //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 (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
- /* 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
- * We should cache some fields in path record in the Name Service DB\r
- * such as: dgid, dlid\r
- * Also we do not save resp_res (ie. max_oustanding_rdma_read/atomic)\r
- * rnr_retry_cnt and flow_ctrl fields\r
- */\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "%s: SP %lx max_rdma_read %d PrivateData %lx\n",\r
- __FUNCTION__, sp_ptr, p_cm_req_rec->resp_res,\r
- p_cm_req_rec->p_req_pdata);\r
-\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
- (void * __ptr64) sp_ptr );\r
-}\r
-\r
-\r
-static void \r
-dapli_ib_cm_mra_cb (\r
- 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
- "--> DiCMcb: CM callback MRA\n");\r
-}\r
-\r
-static void \r
-dapli_ib_cm_rtu_cb (\r
- IN ib_cm_rtu_rec_t *p_cm_rtu_rec )\r
-{\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
- ep_ptr = (DAPL_EP * __ptr64) p_cm_rtu_rec->qp_context;\r
-\r
- if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: EP %lx invalid or FREED\n",\r
- __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 CR %lx\n",\r
- ep_ptr, ep_ptr->qp_handle, ep_ptr->cr_ptr); \r
-\r
- if (ep_ptr->cr_ptr)\r
- {\r
- DAPL_SP *sp_ptr;\r
-\r
- sp_ptr = ((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr;\r
-\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
- (void *) sp_ptr);\r
- \r
- }\r
- else\r
- {\r
- dapl_evd_connection_callback ( \r
- cm_ptr,\r
- IB_CME_CONNECTED,\r
- (void * __ptr64) p_cm_rtu_rec->p_rtu_pdata,\r
- IB_RTU_PDATA_SIZE,\r
- (void *) ep_ptr);\r
- }\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 (\r
- IN DAT_HANDLE dat_handle,\r
- OUT DAT_SOCK_ADDR6 *remote_address )\r
-{\r
-\r
- DAPL_HEADER *header;\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
- cm = dapl_get_cm_from_ep((DAPL_EP *)dat_handle);\r
- rtype = "EP";\r
- }\r
- else if (header->magic == DAPL_MAGIC_CR) \r
- {\r
- cm = ((DAPL_CR *) dat_handle)->ib_cm_handle;\r
- rtype = "CR";\r
- }\r
- else \r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM,\r
- "%s: hdr->magic %x, dat_handle(%lx)\n",\r
- __FUNCTION__, header->magic, dat_handle );\r
- return DAT_INVALID_HANDLE;\r
- }\r
-\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 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
-}\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 (\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
- DAPL_EP *ep_ptr;\r
- DAPL_IA *ia_ptr;\r
- ib_api_status_t ib_status;\r
- dapl_ibal_port_t *p_active_port;\r
- dapl_ibal_ca_t *p_ca;\r
- ib_cm_req_t cm_req;\r
- ib_path_rec_t path_rec;\r
- GID dest_GID;\r
- ib_query_req_t query_req;\r
- ib_gid_pair_t gid_pair;\r
- ib_service_record_t service_rec;\r
- int retry_cnt;\r
- DAT_RETURN dat_status;\r
-\r
- ep_ptr = (DAPL_EP *) ep_handle;\r
- ia_ptr = ep_ptr->header.owner_ia;\r
- ep_ptr->cr_ptr = NULL;\r
- retry_cnt = 0;\r
- dat_status = DAT_SUCCESS;\r
-\r
- p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
-\r
- /*\r
- * We are using the first active port in the list for\r
- * communication. We have to get back here when we decide to support\r
- * fail-over and high-availability.\r
- */\r
- p_active_port = dapli_ibal_get_port ( p_ca,\r
- (uint8_t)ia_ptr->hca_ptr->port_num );\r
-\r
- if (NULL == p_active_port)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"--> DsC: Port %d not available %d\n",\r
- ia_ptr->hca_ptr->port_num, __LINE__ );\r
- return (DAT_INVALID_STATE);\r
- }\r
-\r
- dapl_os_memzero (&dest_GID, sizeof (GID));\r
- dapl_os_memzero (&cm_req, sizeof (ib_cm_req_t));\r
- dapl_os_memzero (&path_rec, sizeof (ib_path_rec_t));\r
- dapl_os_memzero (&service_rec, sizeof (ib_service_record_t));\r
- dapl_os_memzero (&query_req, sizeof (ib_query_req_t));\r
- dapl_os_memzero (&gid_pair, sizeof (ib_gid_pair_t));\r
- dapl_os_memzero (&ep_ptr->remote_ia_address, sizeof (DAT_SOCK_ADDR6));\r
-\r
- dapl_os_memcpy (&ep_ptr->remote_ia_address, \r
- remote_ia_address, \r
- sizeof (ep_ptr->remote_ia_address));\r
-\r
-\r
-#ifdef NO_NAME_SERVICE\r
-\r
- if (DAT_SUCCESS !=\r
- (dat_status = dapls_ns_lookup_address (\r
- ia_ptr,\r
- remote_ia_address,\r
- &dest_GID )))\r
- {\r
- /*\r
- * Remote address not in the table, this is a\r
- * strange return code!\r
- */\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"--> DsC: exits status = %x\n", dat_status);\r
- return dat_status;\r
- }\r
-\r
- dest_GID.guid = CL_HTON64 (dest_GID.guid);\r
- dest_GID.gid_prefix = CL_HTON64 (dest_GID.gid_prefix);\r
-\r
-#else\r
-\r
- /*\r
- * We query the SA to get the dest_gid with the \r
- * {uDAPL_svc_id, IP-address} as the key to get GID.\r
- */\r
- if (DAT_SUCCESS !=\r
- (dat_status = dapls_ns_map_gid (ia_ptr->hca_ptr, \r
- remote_ia_address,\r
- &dest_GID)))\r
- \r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsC: fail to map remote_ia_addr "\r
- "(sa_family %d) to gid\n",\r
- remote_ia_address->sa_family); \r
- return dat_status;\r
- }\r
-#endif /* NO_NAME_SERVICE */\r
-\r
- gid_pair.dest_gid.unicast.interface_id = dest_GID.guid;\r
- gid_pair.dest_gid.unicast.prefix = dest_GID.gid_prefix;\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "dapls_ib_connect: EP %lx QP %lx SERVER GID{0x" F64x\r
- ", 0x" F64x "}\n", \r
- ep_ptr, ep_ptr->qp_handle,\r
- cl_hton64 (gid_pair.dest_gid.unicast.prefix),\r
- cl_hton64 (gid_pair.dest_gid.unicast.interface_id));\r
-\r
- gid_pair.src_gid = p_active_port->p_attr->p_gid_table[0];\r
-/*\r
- if ((gid_pair.src_gid.unicast.interface_id == \r
- gid_pair.dest_gid.unicast.interface_id ) &&\r
- (gid_pair.src_gid.unicast.prefix == \r
- gid_pair.dest_gid.unicast.prefix ))\r
- {\r
- path_rec.dgid = gid_pair.dest_gid;\r
- path_rec.sgid = gid_pair.src_gid;\r
- path_rec.slid = path_rec.dlid = p_active_port->p_attr->lid;\r
- path_rec.pkey = p_active_port->p_attr->p_pkey_table[0];\r
- path_rec.mtu = p_active_port->p_attr->mtu;\r
- path_rec.pkt_life = 18; // 1 sec\r
- path_rec.rate = IB_PATH_RECORD_RATE_10_GBS;\r
- \r
- }\r
- else\r
- {\r
- */\r
- /*\r
- * Query SA to get the path record from pair of GIDs\r
- */\r
- dapl_os_memzero (&query_req, sizeof (ib_query_req_t));\r
- query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS;\r
- query_req.p_query_input = (void *) &gid_pair;\r
- query_req.flags = IB_FLAGS_SYNC; \r
- query_req.timeout_ms = 1 * 1000; /* 1 second */\r
- query_req.retry_cnt = 3;\r
- /* query SA using this port */\r
- query_req.port_guid = p_active_port->p_attr->port_guid;\r
- query_req.query_context = (void *) &path_rec;\r
- query_req.pfn_query_cb = dapli_ib_sa_query_cb;\r
- \r
- ib_status = ib_query (dapl_ibal_root.h_al, &query_req, NULL);\r
-\r
- if ((ib_status != IB_SUCCESS) || (!path_rec.dlid))\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"--> DsC: EP %lx QP %lx query "\r
- "pair_gids status = %s\n", \r
- ep_ptr, ep_ptr->qp_handle,ib_get_err_str(ib_status));\r
- return DAT_INVALID_PARAMETER;\r
- }\r
-\r
- //}\r
-\r
- /*\r
- * Tavor has a HW bug that causes bandwidth with 2K MTU to be less than\r
- * with 1K MTU. Cap the MTU based on device ID to compensate for this.\r
- */\r
- if( (p_ca->p_ca_attr->dev_id == 0x5A44) &&\r
- (ib_path_rec_mtu( &path_rec ) > IB_MTU_LEN_1024) )\r
- {\r
- /* Local endpoint is Tavor - cap MTU to 1K for extra bandwidth. */\r
- path_rec.mtu &= IB_PATH_REC_SELECTOR_MASK;\r
- path_rec.mtu |= IB_MTU_LEN_1024;\r
- }\r
-\r
- /* \r
- * prepare the Service ID from conn_qual \r
- */\r
- cm_req.svc_id = remote_conn_qual;\r
- cm_req.p_primary_path = &path_rec;\r
- cm_req.p_alt_path = NULL;\r
- cm_req.h_qp = ep_ptr->qp_handle;\r
- cm_req.qp_type = IB_QPT_RELIABLE_CONN;\r
- cm_req.p_req_pdata = (uint8_t *) private_data;\r
- cm_req.req_length = (uint8_t)\r
- min(private_data_size,IB_MAX_REQ_PDATA_SIZE);\r
- /* cm retry to send this request messages, IB max of 4 bits */\r
- cm_req.max_cm_retries = 15; /* timer outside of call, s/be infinite */\r
- /* qp retry to send any wr */\r
- cm_req.retry_cnt = 5;\r
- /* max num of oustanding RDMA read/atomic support */\r
- cm_req.resp_res = (uint8_t)ep_ptr->param.ep_attr.max_rdma_read_in;\r
- /* max num of oustanding RDMA read/atomic will use */\r
- cm_req.init_depth = (uint8_t)ep_ptr->param.ep_attr.max_rdma_read_out;\r
-\r
- /* time wait before retrying a pkt after receiving a RNR NAK */\r
- cm_req.rnr_nak_timeout = IB_RNR_NAK_TIMEOUT;\r
- \r
- /* \r
- * number of time local QP should retry after receiving RNR NACK before\r
- * reporting an error\r
- */\r
- cm_req.rnr_retry_cnt = IB_RNR_RETRY_CNT;\r
-\r
- cm_req.remote_resp_timeout = 16; /* 250ms */\r
- cm_req.local_resp_timeout = 16; /* 250ms */\r
- \r
- cm_req.flow_ctrl = TRUE;\r
- cm_req.flags = 0;\r
- /*\r
- * We do not use specific data buffer to check for specific connection\r
- */\r
- cm_req.p_compare_buffer = NULL;\r
- cm_req.compare_offset = 0;\r
- cm_req.compare_length = 0;\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, "--> DsConn: EP=%lx QP=%lx rio=%d,%d pl=%d "\r
- "mtu=%d slid=%#x dlid=%#x\n", \r
- ep_ptr, ep_ptr->qp_handle, cm_req.resp_res, \r
- cm_req.init_depth, ib_path_rec_pkt_life(&path_rec),\r
- ib_path_rec_mtu(&path_rec),\r
- cm_req.p_primary_path->slid,\r
- cm_req.p_primary_path->dlid);\r
-\r
- /*\r
- * We do not support peer_to_peer; therefore, we set pfn_cm_req_cb = NULL\r
- */\r
- cm_req.pfn_cm_req_cb = NULL;\r
- cm_req.pfn_cm_rep_cb = dapli_ib_cm_rep_cb;\r
- cm_req.pfn_cm_rej_cb = dapli_ib_cm_rej_cb;\r
- /* callback when a message received acknowledgement is received */\r
- cm_req.pfn_cm_mra_cb = dapli_ib_cm_mra_cb;\r
-\r
- ib_status = ib_cm_req (&cm_req);\r
- \r
- if ( ib_status != IB_SUCCESS )\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "--> DsC: EP %lx QP %lx conn_request failed = %s\n", \r
- ep_ptr, ep_ptr->qp_handle, ib_get_err_str(ib_status));\r
-\r
- return (dapl_ib_status_convert (ib_status));\r
- }\r
-\r
- return DAT_SUCCESS;\r
-}\r
-\r
-\r
-/*\r
- * dapls_ib_disconnect\r
- *\r
- * Disconnect an EP\r
- *\r
- * Input:\r
- * ep_handle,\r
- * disconnect_flags\r
- * DAT_CLOSE_ABRUPT_FLAG - no callback\r
- * DAT_CLOSE_GRACEFUL_FLAG - callback desired.\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_disconnect ( IN DAPL_EP *ep_ptr,\r
- IN DAT_CLOSE_FLAGS disconnect_flags )\r
-{\r
- ib_api_status_t ib_status = IB_SUCCESS;\r
- ib_cm_dreq_t cm_dreq;\r
- dp_ib_cm_handle_t cm_ptr;\r
-\r
- dapl_os_assert(ep_ptr);\r
-\r
- if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "--> %s: BAD EP Magic EP=%lx\n", __FUNCTION__,ep_ptr); \r
- return DAT_SUCCESS;\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 DAT_SUCCESS;\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
- ep_ptr->recv_discreq, ep_ptr->sent_discreq,\r
- (disconnect_flags == DAT_CLOSE_ABRUPT_FLAG ? "Abrupt":"Graceful"));\r
-\r
- if ( disconnect_flags == DAT_CLOSE_ABRUPT_FLAG )\r
- {\r
- if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED )\r
- return DAT_SUCCESS;\r
-\r
- if ( ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECT_PENDING )\r
- {\r
- dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
- "%s() calling legacy_post_disconnect()\n",__FUNCTION__);\r
- dapl_ep_legacy_post_disconnect(ep_ptr, disconnect_flags);\r
- return DAT_SUCCESS;\r
- }\r
- }\r
-\r
- dapl_os_memzero(&cm_dreq, sizeof(ib_cm_dreq_t));\r
-\r
- cm_dreq.qp_type = IB_QPT_RELIABLE_CONN;\r
- cm_dreq.h_qp = ep_ptr->qp_handle;\r
- cm_dreq.pfn_cm_drep_cb = dapli_ib_cm_drep_cb;\r
- \r
- /* \r
- * Currently we do not send any disconnect private data to\r
- * the other endpoint because DAT 2.0 does not support it. \r
- */\r
- cm_dreq.p_dreq_pdata = NULL;\r
- cm_dreq.flags = IB_FLAGS_SYNC;\r
-\r
- /*\r
- * still need to send DREQ (disconnect request)?\r
- */\r
- if ( (ep_ptr->recv_discreq == DAT_FALSE)\r
- && (ep_ptr->sent_discreq == DAT_FALSE)\r
- && (ep_ptr->qp_state != IB_QPS_RESET) )\r
- {\r
- ep_ptr->sent_discreq = DAT_TRUE;\r
- ib_status = ib_cm_dreq ( &cm_dreq );\r
-\r
- if ( ib_status == IB_SUCCESS )\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "--> DsD: EP %p DREQ SENT\n", ep_ptr);\r
-\r
- /* tolerate INVALID_STATE error as the other side can race ahead and\r
- * generate a DREQ before we do.\r
- */\r
- if ( ib_status == IB_INVALID_STATE || ib_status == IB_INVALID_HANDLE )\r
- {\r
- ib_status = IB_SUCCESS;\r
- }\r
- else if (ib_status)\r
- {\r
- dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
- "%s() EP %p ib_cm_dreq() status %s\n",\r
- __FUNCTION__,ep_ptr,ib_get_err_str(ib_status));\r
- }\r
- }\r
- return ib_status;\r
-}\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_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_setup_conn_listener (\r
- IN DAPL_IA *ia_ptr,\r
- IN DAT_UINT64 ServiceID,\r
- IN DAPL_SP *sp_ptr )\r
-{\r
- ib_api_status_t ib_status;\r
- ib_cm_listen_t cm_listen;\r
- dapl_ibal_ca_t *p_ca;\r
- dapl_ibal_port_t *p_active_port;\r
-\r
- p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
-\r
- /*\r
- * We are using the first active port in the list for\r
- * communication. We have to get back here when we decide to support\r
- * fail-over and high-availability.\r
- */\r
- p_active_port = dapli_ibal_get_port( p_ca,\r
- (uint8_t)ia_ptr->hca_ptr->port_num );\r
-\r
- if (NULL == p_active_port)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"%s: SP %lx port %d not available\n",\r
- __FUNCTION__, sp_ptr, ia_ptr->hca_ptr->port_num );\r
- return (DAT_INVALID_STATE);\r
- }\r
-\r
- if (p_active_port->p_attr->lid == 0)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "--> DsSCL: SP %lx SID 0x" F64x " port %d\n", \r
- sp_ptr, cl_hton64(ServiceID),\r
- p_active_port->p_attr->port_num);\r
- return (DAT_INVALID_STATE);\r
- }\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "%s: SP %lx port %d GID{0x" F64x ", 0x" F64x "} and SID 0x" F64x "\n", \r
- __FUNCTION__,\r
- sp_ptr, p_active_port->p_attr->port_num,\r
- cl_hton64 (p_active_port->p_attr->p_gid_table[0].unicast.prefix),\r
- cl_hton64 (p_active_port->p_attr->p_gid_table[0].unicast.interface_id),\r
- cl_hton64 (ServiceID));\r
- \r
- dapl_os_memzero (&cm_listen, sizeof (ib_cm_listen_t));\r
-\r
- /*\r
- * Listen for all request on this specific CA\r
- */\r
- cm_listen.ca_guid = (p_ca->p_ca_attr->ca_guid);\r
- cm_listen.svc_id = ServiceID;\r
- cm_listen.qp_type = IB_QPT_RELIABLE_CONN; \r
-\r
- /*\r
- * We do not use specific data buffer to check for specific connection\r
- */\r
- cm_listen.p_compare_buffer = NULL;//(uint8_t*)&sp_ptr->conn_qual;\r
- cm_listen.compare_offset = 0;//IB_MAX_REQ_PDATA_SIZE - sizeof(DAT_CONN_QUAL);\r
- cm_listen.compare_length = 0;//sizeof(DAT_CONN_QUAL);\r
-\r
- /*\r
- * We can pick a port here for communication and the others are reserved\r
- * for fail-over / high-availability - TBD\r
- */\r
- cm_listen.port_guid = p_active_port->p_attr->port_guid;\r
- cm_listen.lid = p_active_port->p_attr->lid;\r
- cm_listen.pkey = p_active_port->p_attr->p_pkey_table[0];\r
-\r
- /*\r
- * Register request or mra callback functions\r
- */\r
- cm_listen.pfn_cm_req_cb = dapli_ib_cm_req_cb;\r
-\r
- ib_status = ib_cm_listen ( dapl_ibal_root.h_al,\r
- &cm_listen,\r
- (void *) sp_ptr,\r
- &sp_ptr->cm_srvc_handle );\r
-\r
- if (ib_status != IB_SUCCESS)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "%s: SP %lx SID 0x" F64x " listen failed %s\n", \r
- __FUNCTION__, sp_ptr, cl_hton64 (ServiceID),\r
- ib_get_err_str(ib_status));\r
- }\r
-\r
- return dapl_ib_status_convert (ib_status);\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_PARAMETER\r
- *\r
- */\r
-DAT_RETURN\r
-dapls_ib_remove_conn_listener (\r
- IN DAPL_IA *ia_ptr,\r
- IN DAPL_SP *sp_ptr )\r
-{\r
- ib_api_status_t ib_status;\r
- DAT_RETURN dat_status = DAT_SUCCESS;\r
- \r
- UNUSED_PARAM( ia_ptr );\r
-\r
- dapl_os_assert ( sp_ptr );\r
-\r
- dapl_os_assert ( sp_ptr->header.magic == DAPL_MAGIC_PSP ||\r
- sp_ptr->header.magic == DAPL_MAGIC_RSP );\r
-\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s() cm_srvc_handle %lx\n",\r
- __FUNCTION__, sp_ptr->cm_srvc_handle );\r
-\r
- if (sp_ptr->cm_srvc_handle)\r
- {\r
- ib_status = ib_cm_cancel ( sp_ptr->cm_srvc_handle, \r
- NULL );\r
- \r
- if (ib_status != IB_SUCCESS)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "--> DsRCL: SP %lx ib_cm_cancel failed(0x%x) %s\n", \r
- sp_ptr, sp_ptr->cm_srvc_handle,\r
- ib_get_err_str(ib_status));\r
- sp_ptr->cm_srvc_handle = NULL;\r
- return (DAT_INVALID_PARAMETER);\r
- }\r
-\r
- sp_ptr->cm_srvc_handle = NULL;\r
- }\r
-\r
- return dat_status;\r
-}\r
-\r
-/*\r
- * dapls_ib_reject_connection\r
- *\r
- * Perform necessary steps to reject a connection\r
- *\r
- * Input:\r
- * cr_handle\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_reject_connection ( IN dp_ib_cm_handle_t ib_cm_handle,\r
- IN int reject_reason,\r
- IN DAT_COUNT private_data_size,\r
- IN const DAT_PVOID private_data)\r
-{\r
- ib_api_status_t ib_status;\r
- ib_cm_rej_t cm_rej;\r
- static char *rej_table[] =\r
- {\r
- "INVALID_REJ_REASON",\r
- "INVALID_REJ_REASON",\r
- "INVALID_REJ_REASON",\r
- "INVALID_REJ_REASON",\r
- "INVALID_REJ_REASON",\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_CM_LOCAL_FAILURE"\r
- };\r
-\r
-#define REJ_TABLE_SIZE IB_CM_LOCAL_FAILURE\r
-\r
- reject_reason = __min( reject_reason & 0xff, REJ_TABLE_SIZE);\r
-\r
- cm_rej.rej_status = IB_REJ_USER_DEFINED;\r
- cm_rej.p_ari = (ib_ari_t *)&rej_table[reject_reason]; \r
- cm_rej.ari_length = (uint8_t)strlen (rej_table[reject_reason]);\r
-\r
- cm_rej.p_rej_pdata = private_data;\r
- cm_rej.rej_length = private_data_size;\r
-\r
-#if defined(DAPL_DBG) && 0\r
- dapli_print_private_data("DsRjC",private_data,private_data_size);\r
-#endif\r
-\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 %p reject failed %s\n", \r
- ib_cm_handle, ib_get_err_str(ib_status) );\r
- }\r
-\r
- return ( dapl_ib_status_convert ( ib_status ) );\r
-}\r
-\r
-\r
-\r
-#if 0\r
-static void\r
-dapli_query_qp( ib_qp_handle_t qp_handle, ib_qp_attr_t *qpa )\r
-{\r
- ib_api_status_t ib_status;\r
- \r
- ib_status = ib_query_qp ( qp_handle, qpa );\r
- if (ib_status != IB_SUCCESS)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"ib_query_qp(%lx) '%s'\n",\r
- qp_handle, ib_get_err_str(ib_status) );\r
- }\r
- else\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM, "--> QP(%lx) state %s "\r
- "type %d init %d acc %x\n",\r
- qp_handle,\r
- ib_get_port_state_str(qpa->state),\r
- qpa->qp_type,\r
- qpa->init_depth,\r
- qpa->access_ctrl );\r
- }\r
-}\r
-#endif\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_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN\r
-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
- DAPL_CR *cr_ptr;\r
- DAPL_EP *ep_ptr;\r
- DAPL_IA *ia_ptr;\r
- DAT_RETURN dat_status;\r
- ib_api_status_t ib_status;\r
- dapl_ibal_ca_t *p_ca;\r
- 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
- ia_ptr = ep_ptr->header.owner_ia;\r
-\r
- if ( ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED )\r
- {\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, ep_ptr );\r
-\r
- if ( dat_status != DAT_SUCCESS)\r
- {\r
- /* This is not a great error code, but all the spec allows */\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "--> DsIBAC: CR %lx EP %lx alloc QP failed 0x%x\n",\r
- cr_ptr, ep_ptr, dat_status );\r
- return (dat_status);\r
- }\r
- }\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
- "--> DsIBAC: CR %lx EP %lx port %d is not available\n",\r
- cr_ptr, ep_ptr, ia_ptr->hca_ptr->port_num);\r
- return (DAT_INVALID_STATE);\r
- }\r
-\r
- cr_ptr->param.local_ep_handle = ep_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
- \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*)&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)\r
- {\r
- char ipa[20];\r
-\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM|DAPL_DBG_TYPE_CALLBACK, \r
- "%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
- }\r
-#endif\r
-\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
-\r
- cm_rep.h_qp = ep_ptr->qp_handle;\r
- cm_rep.qp_type = IB_QPT_RELIABLE_CONN;\r
-\r
- if (private_data_size > IB_MAX_REP_PDATA_SIZE) {\r
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
- "--> DsIBAC: private_data_size(%d) > Max(%d)\n",\r
- private_data_size, IB_MAX_REP_PDATA_SIZE);\r
- return DAT_ERROR(DAT_LENGTH_ERROR, DAT_NO_SUBTYPE);\r
- \r
- }\r
- cm_rep.p_rep_pdata = (const uint8_t *)private_data;\r
- cm_rep.rep_length = private_data_size;\r
- \r
-#if defined(DAPL_DBG) && 0\r
- dapli_print_private_data( "DsIBAC",\r
- (const uint8_t*)private_data,\r
- private_data_size );\r
-#endif\r
-\r
- cm_rep.pfn_cm_rej_cb = dapli_ib_cm_rej_cb;\r
- cm_rep.pfn_cm_mra_cb = dapli_ib_cm_mra_cb;\r
- cm_rep.pfn_cm_rtu_cb = dapli_ib_cm_rtu_cb;\r
- cm_rep.pfn_cm_lap_cb = dapli_ib_cm_lap_cb;\r
- cm_rep.pfn_cm_dreq_cb = dapli_ib_cm_dreq_cb;\r
-\r
- /*\r
- * FIXME - Vu\r
- * Pay attention to the attributes. \r
- * Some of them are desirably set by DAT consumers\r
- */\r
- /*\r
- * We enable the qp associate with this connection ep all the access right\r
- * We enable the flow_ctrl, retry till success\r
- * We will limit the access right and flow_ctrl upon DAT consumers \r
- * requirements\r
- */\r
- cm_rep.access_ctrl =\r
- IB_AC_LOCAL_WRITE|IB_AC_RDMA_WRITE|IB_AC_MW_BIND|IB_AC_ATOMIC;\r
-\r
- if ((ep_ptr->param.ep_attr.max_rdma_read_in > 0) \r
- || (ep_ptr->param.ep_attr.max_rdma_read_out > 0))\r
- {\r
- cm_rep.access_ctrl |= IB_AC_RDMA_READ;\r
- }\r
-\r
- cm_rep.sq_depth = 0;\r
- cm_rep.rq_depth = 0;\r
- cm_rep.init_depth = (uint8_t)ep_ptr->param.ep_attr.max_rdma_read_out;\r
- cm_rep.flow_ctrl = TRUE;\r
- cm_rep.flags = 0;\r
- cm_rep.failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
- cm_rep.target_ack_delay = 14;\r
- cm_rep.rnr_nak_timeout = IB_RNR_NAK_TIMEOUT;\r
- cm_rep.rnr_retry_cnt = IB_RNR_RETRY_CNT;\r
- cm_rep.pp_recv_failure = NULL;\r
- cm_rep.p_recv_wr = NULL;\r
- \r
- dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
- "--> DsIBAC: cm_rep: acc %x init %d qp_type %x req_count %d\n",\r
- 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 ( 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
- \r
- return ( dapl_ib_status_convert ( ib_status ) );\r
-}\r
-\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
- *\r
- * Output:\r
- * none\r
- *\r
- * Returns:\r
- * void\r
- *\r
- */\r
-void\r
-dapls_ib_disconnect_clean (\r
- IN DAPL_EP *ep_ptr,\r
- IN DAT_BOOLEAN active,\r
- IN const ib_cm_events_t ib_cm_event )\r
-{\r
- DAPL_IA *ia_ptr;\r
- ib_qp_attr_t qp_attr;\r
- ib_api_status_t ib_status;\r
-\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s(%s): cm_event: %s \n", __FUNCTION__,\r
- (active?"A":"P"), dapli_ib_cm_event_str(ib_cm_event));\r
-\r
- ia_ptr = ep_ptr->header.owner_ia;\r
- \r
- if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM,\r
- ">>>DSCONN_CLEAN(%s): cm_event: %s Invalid IA_ptr\n",\r
- (active?"Act":"Pas"),dapli_ib_cm_event_str(ib_cm_event));\r
- return;\r
- }\r
- dapl_os_assert ( ep_ptr->header.magic == DAPL_MAGIC_EP );\r
- \r
- ep_ptr->sent_discreq = DAT_FALSE;\r
- ep_ptr->recv_discreq = DAT_FALSE;\r
-\r
- /* \r
- * Query the QP to get the current state */\r
- ib_status = ib_query_qp ( ep_ptr->qp_handle, &qp_attr );\r
- \r
- if ( ib_status != IB_SUCCESS )\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- ">>>DSCONN_CLEAN(%s): Query QP failed = %s\n",\r
- (active?"Act":"Pas"),ib_get_err_str(ib_status) );\r
- return;\r
- }\r
- \r
- ep_ptr->qp_state = qp_attr.state;\r
-\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM, ">>>DSCONN_CLEAN(%s): cm_event: %d "\r
- "ep_ptr %lx ep_state %s qp_state %#x\n", \r
- (active?"A":"P"), ib_cm_event, ep_ptr,\r
- dapl_get_ep_state_str(ep_ptr->param.ep_state),\r
- ep_ptr->qp_state );\r
-\r
- if ( ep_ptr->qp_state != IB_QPS_ERROR &&\r
- ep_ptr->qp_state != IB_QPS_RESET &&\r
- ep_ptr->qp_state != IB_QPS_INIT )\r
- {\r
- ep_ptr->qp_state = IB_QPS_ERROR;\r
- dapls_modify_qp_state_to_error (ep_ptr->qp_handle);\r
- }\r
-}\r
-\r
-\r
-#ifdef NOT_USED\r
-/*\r
- * dapls_ib_cr_handoff\r
- *\r
- * Hand off the connection request to another service point \r
- *\r
- * Input:\r
- * cr_handle DAT_CR_HANDLE\r
- * handoff_serv_id DAT_CONN_QUAL\r
- *\r
- * Output:\r
- * none\r
- *\r
- * Returns:\r
- * DAT_SUCCESS\r
- * DAT_INVALID_PARAMETER\r
- *\r
- */\r
-DAT_RETURN \r
-dapls_ib_cr_handoff (\r
- IN DAT_CR_HANDLE cr_handle,\r
- IN DAT_CONN_QUAL handoff_serv_id )\r
-{\r
- DAPL_CR *cr_ptr;\r
- ib_api_status_t ib_status;\r
- \r
- cr_ptr = (DAPL_CR *) cr_handle;\r
-\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
- return DAT_INVALID_PARAMETER;\r
- }\r
-\r
- if (cr_ptr->sp_ptr == DAPL_IB_INVALID_HANDLE)\r
- {\r
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "--> DsCH: CR = %lx invalid psp handle\n", cr_ptr);\r
- return DAT_INVALID_PARAMETER;\r
- }\r
-\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
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
- "--> DsCH: CR = %lx handoff failed = %s\n", \r
- cr_ptr, ib_get_err_str(ib_status) );\r
-\r
- return dapl_ib_status_convert (ib_status);\r
- }\r
-\r
- dapl_dbg_log ( DAPL_DBG_TYPE_CM,\r
- "--> %s(): remove CR %lx from SP %lx Queue\n",\r
- __FUNCTION__, cr_ptr, cr_ptr->sp_ptr);\r
- /* Remove the CR from the queue */\r
- dapl_sp_remove_cr (cr_ptr->sp_ptr, cr_ptr);\r
-\r
- /*\r
- * If this SP has been removed from service, free it\r
- * up after the last CR is removed\r
- */\r
- dapl_os_lock (&cr_ptr->sp_ptr->header.lock);\r
- if ( cr_ptr->sp_ptr->listening != DAT_TRUE && \r
- cr_ptr->sp_ptr->cr_list_count == 0 &&\r
- cr_ptr->sp_ptr->state != DAPL_SP_STATE_FREE )\r
- {\r
- dapl_dbg_log (DAPL_DBG_TYPE_CM, \r
- "--> DsCH: CR = %lx disconnect dump SP = %lx \n", \r
- cr_ptr, cr_ptr->sp_ptr);\r
- /* Decrement the ref count on the EVD */\r
- if (cr_ptr->sp_ptr->evd_handle)\r
- {\r
- dapl_os_atomic_dec (& ((DAPL_EVD *)cr_ptr->sp_ptr->evd_handle)->evd_ref_count);\r
- cr_ptr->sp_ptr->evd_handle = NULL;\r
- }\r
- cr_ptr->sp_ptr->state = DAPL_SP_STATE_FREE;\r
- dapl_os_unlock (&cr_ptr->sp_ptr->header.lock);\r
- (void)dapls_ib_remove_conn_listener ( cr_ptr->sp_ptr->header.owner_ia,\r
- cr_ptr->sp_ptr );\r
- dapls_ia_unlink_sp ( (DAPL_IA *)cr_ptr->sp_ptr->header.owner_ia,\r
- cr_ptr->sp_ptr );\r
- dapls_sp_free_sp ( cr_ptr->sp_ptr );\r
- }\r
- else\r
- {\r
- dapl_os_unlock (&cr_ptr->sp_ptr->header.lock);\r
- }\r
-\r
- /*\r
- * Clean up and dispose of the resource\r
- */\r
- dapls_cr_free (cr_ptr);\r
-\r
- return (DAT_SUCCESS);\r
-}\r
-#endif\r
-\r
-int\r
-dapls_ib_private_data_size (\r
- IN DAPL_HCA *hca_ptr)\r
-{\r
- return IB_MAX_REQ_PDATA_SIZE;\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
+
+/*
+ * 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_cm.c
+ *
+ * PURPOSE: IB Connection routines for access to IBAL APIs
+ *
+ * $Id: dapl_ibal_cm.c 584 2007-02-07 13:12:18Z sleybo $
+ *
+ **********************************************************************/
+
+#include "dapl.h"
+#include "dapl_adapter_util.h"
+#include "dapl_evd_util.h"
+#include "dapl_cr_util.h"
+#include "dapl_sp_util.h"
+#include "dapl_ep_util.h"
+#include "dapl_ia_util.h"
+#include "dapl_ibal_util.h"
+#include "dapl_name_service.h"
+#include "dapl_ibal_name_service.h"
+#include "dapl_cookie.h"
+
+#define IB_INFINITE_SERVICE_LEASE 0xFFFFFFFF
+#define DAPL_ATS_SERVICE_ID ATS_SERVICE_ID //0x10000CE100415453
+#define DAPL_ATS_NAME ATS_NAME
+#define HCA_IPV6_ADDRESS_LENGTH 16
+
+/* until dapl_ibal_util.h define of IB_INVALID_HANDLE which overlaps the
+ * Windows ib_types.h typedef enu ib_api_status_t IB_INVALID_HANDLE is fixed.
+ */
+#undef IB_INVALID_HANDLE
+#define DAPL_IB_INVALID_HANDLE NULL
+
+int g_dapl_loopback_connection = 0;
+extern dapl_ibal_root_t dapl_ibal_root;
+
+/*
+ * Prototypes
+ */
+
+char *
+dapli_ib_cm_event_str(ib_cm_events_t e)
+{
+#ifdef DBG
+ char *cp;
+ static char *event_str[13] = {
+ "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"
+ };
+
+ if (e > IB_CM_LOCAL_FAILURE || e < IB_CME_CONNECTED)
+ cp = "BAD EVENT";
+ else
+ cp = event_str[e];
+
+ return cp;
+#else
+ static char num[8];
+ sprintf(num,"%d",e);
+ return num;
+#endif
+}
+
+
+#if defined(DAPL_DBG)
+
+void dapli_print_private_data( char *prefix, const uint8_t *pd, int len )
+{
+ int i;
+
+ if ( !pd || len <= 0 )
+ return;
+
+ dapl_log ( DAPL_DBG_TYPE_CM, "--> %s: private_data(len %d)\n ",prefix,len);
+
+ if (len > IB_MAX_REP_PDATA_SIZE)
+ {
+ dapl_log ( DAPL_DBG_TYPE_ERR,
+ " Private data size(%d) > Max(%d), ignored.\n ",
+ len,DAPL_MAX_PRIVATE_DATA_SIZE);
+ len = IB_MAX_REP_PDATA_SIZE;
+ }
+
+ for ( i = 0 ; i < len; i++ )
+ {
+ dapl_log ( DAPL_DBG_TYPE_CM, "%2x ", pd[i]);
+ if ( ((i+1) % 5) == 0 )
+ dapl_log ( DAPL_DBG_TYPE_CM, "\n ");
+ }
+ dapl_log ( DAPL_DBG_TYPE_CM, "\n");
+}
+#endif
+
+/* EP-CM linking support */
+dp_ib_cm_handle_t ibal_cm_alloc(void)
+{
+ 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));
+ cm_ptr->ref_count = 1;
+
+ if (dapl_os_lock_init(&cm_ptr->lock)) {
+ dapl_os_free(cm_ptr, sizeof(*cm_ptr));
+ return NULL;
+ }
+
+ dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm_ptr->list_entry);
+
+ return cm_ptr;
+}
+
+/* free CM object resources */
+static void ibal_cm_dealloc(dp_ib_cm_handle_t cm_ptr)
+{
+ dapl_os_assert(!cm_ptr->ref_count);
+ dapl_os_lock_destroy(&cm_ptr->lock);
+ 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--;
+ if (cm_ptr->ref_count) {
+ dapl_os_unlock(&cm_ptr->lock);
+ return;
+ }
+ dapl_os_unlock(&cm_ptr->lock);
+ ibal_cm_dealloc(cm_ptr);
+}
+
+/* blocking: called from user thread dapl_ep_free() only */
+void dapls_cm_free(dp_ib_cm_handle_t cm_ptr)
+{
+ dapl_ep_unlink_cm(cm_ptr->ep, cm_ptr);
+
+ /* final reference, alloc */
+ dapls_cm_release(cm_ptr);
+}
+
+static void
+dapli_ib_cm_apr_cb (
+ IN ib_cm_apr_rec_t *p_cm_apr_rec )
+{
+ UNUSED_PARAM( p_cm_apr_rec );
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCAcb: CM callback APR (Alternate Path Request)\n");
+}
+
+static void
+dapli_ib_cm_lap_cb (
+ IN ib_cm_lap_rec_t *p_cm_lap_rec )
+{
+ UNUSED_PARAM( p_cm_lap_rec );
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCLcb: CM callback LAP (Load Alternate Path)\n");
+}
+
+/*
+ * Connection Disconnect Request callback
+ * We received a DREQ, return a DREP (disconnect reply).
+ */
+
+static void
+dapli_ib_cm_dreq_cb (
+ IN ib_cm_dreq_rec_t *p_cm_dreq_rec )
+{
+ ib_cm_drep_t cm_drep;
+ DAPL_EP *ep_ptr;
+ int bail=10;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert (p_cm_dreq_rec);
+
+ ep_ptr = (DAPL_EP * __ptr64) p_cm_dreq_rec->qp_context;
+ if ( DAPL_BAD_PTR(ep_ptr) )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: BAD_PTR EP %lx\n", __FUNCTION__, ep_ptr);
+ return;
+ }
+ if ( ep_ptr->header.magic != DAPL_MAGIC_EP )
+ {
+ if ( ep_ptr->header.magic == DAPL_MAGIC_INVALID )
+ return;
+
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: EP %p BAD_EP_MAGIC %x != wanted %x\n",
+ __FUNCTION__, ep_ptr, ep_ptr->header.magic,
+ DAPL_MAGIC_EP );
+ return;
+ }
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);
+ return;
+ }
+ dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_dreq_rec->h_cm_dreq.h_qp);
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> %s() EP %p, %s sent_discreq %s\n",
+ __FUNCTION__,ep_ptr,
+ dapl_get_ep_state_str(ep_ptr->param.ep_state),
+ (ep_ptr->sent_discreq == DAT_TRUE ? "TRUE":"FALSE"));
+
+ dapl_os_lock (&ep_ptr->header.lock);
+ if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED
+ /*|| ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING
+ && ep_ptr->sent_discreq == DAT_TRUE)*/ )
+ {
+ dapl_os_unlock (&ep_ptr->header.lock);
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCDcb: EP %lx QP %lx already Disconnected\n",
+ ep_ptr, ep_ptr->qp_handle);
+ return;
+ }
+
+ ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING;
+ ep_ptr->recv_discreq = DAT_TRUE;
+ dapl_os_unlock (&ep_ptr->header.lock);
+
+ dapl_os_memzero (&cm_drep, sizeof(ib_cm_drep_t));
+
+ /* Could fail if we received reply from other side, no need to retry */
+ /* Wait for any send ops in process holding reference */
+ while (dapls_cb_pending(&ep_ptr->req_buffer) && bail-- > 0 )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCDcb: WAIT for EP=%lx req_count(%d) != 0\n",
+ ep_ptr, dapls_cb_pending(&ep_ptr->req_buffer));
+ dapl_os_sleep_usec (100);
+ }
+
+ ib_cm_drep (p_cm_dreq_rec->h_cm_dreq, &cm_drep);
+
+ /* CM puts QP in reset state */
+ ep_ptr->qp_state = IB_QPS_RESET;
+
+ if (ep_ptr->cr_ptr)
+ {
+ /* passive side */
+ dapls_cr_callback ( cm_ptr,
+ IB_CME_DISCONNECTED,
+ (void * __ptr64) p_cm_dreq_rec->p_dreq_pdata,
+ IB_DREQ_PDATA_SIZE,
+ (void *) (((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr) );
+ }
+ else
+ {
+ /* active side */
+ dapl_evd_connection_callback (
+ cm_ptr,
+ IB_CME_DISCONNECTED,
+ (void * __ptr64)
+ p_cm_dreq_rec->p_dreq_pdata,
+ IB_DREQ_PDATA_SIZE,
+ p_cm_dreq_rec->qp_context );
+ }
+}
+
+/*
+ * Connection Disconnect Reply callback
+ * We sent a DREQ and received a DREP.
+ */
+
+static void
+dapli_ib_cm_drep_cb (
+ IN ib_cm_drep_rec_t *p_cm_drep_rec )
+{
+ DAPL_EP *ep_ptr;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert (p_cm_drep_rec != NULL);
+
+ ep_ptr = (DAPL_EP * __ptr64) p_cm_drep_rec->qp_context;
+
+ if (p_cm_drep_rec->cm_status)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> %s: DREP cm_status(%s) EP=%p\n", __FUNCTION__,
+ ib_get_err_str(p_cm_drep_rec->cm_status), ep_ptr);
+ }
+
+ if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: BAD EP Handle EP=%lx\n", __FUNCTION__,ep_ptr);
+ return;
+ }
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);
+ return;
+ }
+ dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_drep_rec->h_qp);
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCDpcb: EP %p state %s cm_hdl %p\n",ep_ptr,
+ dapl_get_ep_state_str(ep_ptr->param.ep_state),
+ cm_ptr);
+
+ if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> DiCDpcb: EP %lx QP %lx already Disconnected\n",
+ ep_ptr, ep_ptr->qp_handle);
+ return;
+ }
+
+ if (ep_ptr->cr_ptr)
+ {
+ /* passive connection side */
+ dapls_cr_callback ( cm_ptr,
+ IB_CME_DISCONNECTED,
+ (void * __ptr64) p_cm_drep_rec->p_drep_pdata,
+ IB_DREP_PDATA_SIZE,
+ (void *) (((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr) );
+ }
+ else
+ {
+ /* active connection side */
+ dapl_evd_connection_callback (
+ cm_ptr,
+ IB_CME_DISCONNECTED,
+ (void * __ptr64) p_cm_drep_rec->p_drep_pdata,
+ IB_DREP_PDATA_SIZE,
+ p_cm_drep_rec->qp_context );
+ }
+}
+
+/*
+ * CM reply callback
+ */
+
+static void
+dapli_ib_cm_rep_cb (
+ IN ib_cm_rep_rec_t *p_cm_rep_rec )
+{
+ ib_api_status_t ib_status;
+ ib_cm_rtu_t cm_rtu;
+ uint8_t cm_cb_op;
+ DAPL_PRIVATE *prd_ptr;
+ DAPL_EP *ep_ptr;
+ dapl_ibal_ca_t *p_ca;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert (p_cm_rep_rec != NULL);
+
+ ep_ptr = (DAPL_EP * __ptr64) p_cm_rep_rec->qp_context;
+
+ if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: EP %lx invalid or FREED\n",
+ __FUNCTION__, ep_ptr);
+ return;
+ }
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);
+ return;
+ }
+ dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_rep_rec->h_cm_rep.h_qp);
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCRpcb: EP %lx local_max_rdma_read_in %d\n",
+ ep_ptr, p_cm_rep_rec->resp_res);
+
+ p_ca = (dapl_ibal_ca_t *)
+ ep_ptr->header.owner_ia->hca_ptr->ib_hca_handle;
+
+ dapl_os_memzero (&cm_rtu, sizeof ( ib_cm_rtu_t ));
+ cm_rtu.pfn_cm_apr_cb = dapli_ib_cm_apr_cb;
+ cm_rtu.pfn_cm_dreq_cb = dapli_ib_cm_dreq_cb;
+ cm_rtu.p_rtu_pdata = NULL;
+ cm_rtu.access_ctrl =
+ IB_AC_LOCAL_WRITE|IB_AC_RDMA_WRITE|IB_AC_MW_BIND|IB_AC_ATOMIC;
+ if ((ep_ptr->param.ep_attr.max_rdma_read_in > 0) ||
+ (ep_ptr->param.ep_attr.max_rdma_read_out > 0))
+ {
+ cm_rtu.access_ctrl |= IB_AC_RDMA_READ;
+ }
+
+ cm_rtu.rq_depth = 0;
+ cm_rtu.sq_depth = 0;
+
+ ib_status = ib_cm_rtu (p_cm_rep_rec->h_cm_rep, &cm_rtu);
+
+ if (ib_status == IB_SUCCESS)
+ {
+ cm_cb_op = IB_CME_CONNECTED;
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCRpcb: EP %lx Connected req_count %d\n",
+ ep_ptr, dapls_cb_pending(&ep_ptr->req_buffer));
+ }
+ else
+ {
+ cm_cb_op = IB_CME_LOCAL_FAILURE;
+ }
+
+ prd_ptr = (DAPL_PRIVATE * __ptr64) p_cm_rep_rec->p_rep_pdata;
+
+#if defined(DAPL_DBG) && 0
+ dapli_print_private_data( "DiCRpcb",
+ prd_ptr->private_data,
+ IB_MAX_REP_PDATA_SIZE);
+#endif
+
+ dapl_evd_connection_callback (
+ cm_ptr,
+ cm_cb_op,
+ (void *) prd_ptr,
+ IB_REP_PDATA_SIZE,
+ (void * __ptr64) p_cm_rep_rec->qp_context);
+}
+
+
+static void
+dapli_ib_cm_rej_cb (
+ IN ib_cm_rej_rec_t *p_cm_rej_rec )
+{
+ DAPL_EP *ep_ptr;
+ ib_cm_events_t cm_event;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert (p_cm_rej_rec);
+
+ ep_ptr = (DAPL_EP * __ptr64) p_cm_rej_rec->qp_context;
+
+ if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: EP %lx invalid or FREED\n",
+ __FUNCTION__, ep_ptr);
+ return;
+ }
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);
+ return;
+ }
+ dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_rej_rec->h_qp);
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCRjcb: EP = %lx QP = %lx rej reason = 0x%x\n",
+ ep_ptr,ep_ptr->qp_handle,CL_NTOH16(p_cm_rej_rec->rej_status));
+
+ switch (p_cm_rej_rec->rej_status)
+ {
+ case IB_REJ_INSUF_RESOURCES:
+ case IB_REJ_INSUF_QP:
+ case IB_REJ_INVALID_COMM_ID:
+ case IB_REJ_INVALID_COMM_INSTANCE:
+ case IB_REJ_INVALID_PKT_RATE:
+ case IB_REJ_INVALID_ALT_GID:
+ case IB_REJ_INVALID_ALT_LID:
+ case IB_REJ_INVALID_ALT_SL:
+ case IB_REJ_INVALID_ALT_TRAFFIC_CLASS:
+ case IB_REJ_INVALID_ALT_PKT_RATE:
+ case IB_REJ_INVALID_ALT_HOP_LIMIT:
+ case IB_REJ_INVALID_ALT_FLOW_LBL:
+ case IB_REJ_INVALID_GID:
+ case IB_REJ_INVALID_LID:
+ case IB_REJ_INVALID_SID:
+ case IB_REJ_INVALID_SL:
+ case IB_REJ_INVALID_TRAFFIC_CLASS:
+ case IB_REJ_PORT_REDIRECT:
+ case IB_REJ_INVALID_MTU:
+ case IB_REJ_INSUFFICIENT_RESP_RES:
+ case IB_REJ_INVALID_CLASS_VER:
+ case IB_REJ_INVALID_FLOW_LBL:
+ cm_event = IB_CME_DESTINATION_REJECT;
+ break;
+
+ case IB_REJ_TIMEOUT:
+ cm_event = IB_CME_DESTINATION_UNREACHABLE;
+ dapl_dbg_log (DAPL_DBG_TYPE_CM, "--> DiCRjcb: CR TIMEOUT\n");
+ break;
+
+ case IB_REJ_USER_DEFINED:
+ cm_event = IB_CME_DESTINATION_REJECT;
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCRjcb: user defined rej reason %s\n",
+ p_cm_rej_rec->p_ari);
+ break;
+
+ default:
+ cm_event = IB_CME_LOCAL_FAILURE;
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DiCRjcb: with unknown status %x\n",
+ p_cm_rej_rec->rej_status);
+ break;
+ }
+
+ /* FIXME - Vu
+ * We do not take care off the user defined rej reason with additional
+ * rejection information (p_ari)
+ */
+
+ if (ep_ptr->cr_ptr)
+ {
+ dapls_cr_callback ( cm_ptr,
+ cm_event,
+ (void * __ptr64) p_cm_rej_rec->p_rej_pdata,
+ IB_REJ_PDATA_SIZE,
+ (void *) ((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr);
+ }
+ else
+ {
+ dapl_evd_connection_callback (
+ cm_ptr,
+ cm_event,
+ (void * __ptr64) p_cm_rej_rec->p_rej_pdata,
+ IB_REJ_PDATA_SIZE,
+ (void * __ptr64) p_cm_rej_rec->qp_context );
+ }
+
+}
+
+
+
+static void
+dapli_ib_cm_req_cb ( IN ib_cm_req_rec_t *p_cm_req_rec )
+{
+ DAPL_SP *sp_ptr;
+ DAT_SOCK_ADDR6 dest_ia_addr;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert (p_cm_req_rec);
+
+ sp_ptr = (DAPL_SP * __ptr64) p_cm_req_rec->context;
+
+ dapl_os_assert (sp_ptr);
+
+ /*
+ * 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)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "%s: BAD-Magic in SP %lx, racing CM callback?\n",
+ __FUNCTION__, sp_ptr );
+ return;
+ }
+
+ dapl_os_assert ( sp_ptr->header.magic == DAPL_MAGIC_PSP ||
+ sp_ptr->header.magic == DAPL_MAGIC_RSP );
+
+ /* preserve ibal's connection handle storage so we have a consistent
+ * pointer value. The reasons this is done dynamically instead of a static
+ * allocation in an end_point is the pointer value is set in the SP list
+ * of CR's here and searched for from disconnect callbacks. If the pointer
+ * value changes, you never find the CR on the sp list...
+ * EP struct deallocation is where this memory is released or prior in the
+ * error case.
+ */
+ cm_ptr = ibal_cm_alloc();
+ if (!cm_ptr)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "%s: FAILED to alloc IB CM handle storage?\n",
+ __FUNCTION__);
+ return;
+ }
+
+ /*
+ * Save the cm_srvc_handle to avoid the race condition between
+ * the return of the ib_cm_listen and the notification of a conn req
+ */
+ if (sp_ptr->cm_srvc_handle != p_cm_req_rec->h_cm_listen)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+ "--> DiCRqcb: cm_service_handle is changed\n");
+ sp_ptr->cm_srvc_handle = p_cm_req_rec->h_cm_listen;
+ }
+
+ dapl_os_memzero (&dest_ia_addr, sizeof (dest_ia_addr));
+
+#ifdef NO_NAME_SERVICE
+
+ {
+ DAPL_PRIVATE *prd_ptr;
+
+ prd_ptr = (DAPL_PRIVATE *)p_cm_req_rec->p_req_pdata;
+
+ dapl_os_memcpy ((void *)&dest_ia_addr,
+ (void *)&prd_ptr->hca_address,
+ sizeof (DAT_SOCK_ADDR6));
+ }
+
+#else
+
+ {
+ GID dest_gid;
+
+ dapl_os_memzero (&dest_gid, sizeof (dest_gid));
+
+ dest_gid.guid = p_cm_req_rec->primary_path.dgid.unicast.interface_id;
+ dest_gid.gid_prefix = p_cm_req_rec->primary_path.dgid.unicast.prefix;
+
+ if (DAT_SUCCESS != dapls_ns_map_ipaddr (
+ sp_ptr->header.owner_ia->hca_ptr,
+ dest_gid,
+ (DAT_IA_ADDRESS_PTR)&dest_ia_addr))
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "cm_req_cb: SP = %lx failed mapping GID-IPaddr\n",
+ sp_ptr);
+ }
+ }
+
+#endif /* NO_NAME_SERVICE */
+
+ /* preserve CR cm handle data */
+ dapl_os_memcpy( (void*)&cm_ptr->ib_cm,
+ (void*)&p_cm_req_rec->h_cm_req,
+ sizeof(ib_cm_handle_t));
+
+ /* preserve remote IP address */
+ dapl_os_memcpy( (void*)&cm_ptr->dst_ip_addr,
+ (void*)&dest_ia_addr,
+ sizeof(dest_ia_addr));
+
+#if defined(DAPL_DBG)
+ {
+ char ipa[20];
+
+ //rval = ((struct sockaddr_in *) (&dest_ia_addr))->sin_addr.s_addr;
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM|DAPL_DBG_TYPE_CALLBACK,
+ "%s: query SA (CM %lx)->dst_ip_addr: %s\n",
+ __FUNCTION__,cm_ptr,
+ dapli_get_ip_addr_str(
+ (DAT_SOCK_ADDR6*) &cm_ptr->dst_ip_addr, ipa) );
+ }
+#endif
+
+ /* FIXME - Vu
+ * We have NOT used/saved the primary and alternative path record
+ * ie. p_cm_req_rec->p_primary_path and p_cm_req_rec->p_alt_path
+ * We should cache some fields in path record in the Name Service DB
+ * such as: dgid, dlid
+ * Also we do not save resp_res (ie. max_oustanding_rdma_read/atomic)
+ * rnr_retry_cnt and flow_ctrl fields
+ */
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "%s: SP %lx max_rdma_read %d PrivateData %lx\n",
+ __FUNCTION__, sp_ptr, p_cm_req_rec->resp_res,
+ p_cm_req_rec->p_req_pdata);
+
+ dapls_cr_callback ( cm_ptr,
+ IB_CME_CONNECTION_REQUEST_PENDING,
+ (void * __ptr64) p_cm_req_rec->p_req_pdata,
+ IB_REQ_PDATA_SIZE,
+ (void * __ptr64) sp_ptr );
+}
+
+
+static void
+dapli_ib_cm_mra_cb (
+ IN ib_cm_mra_rec_t *p_cm_mra_rec )
+{
+ UNUSED_PARAM( p_cm_mra_rec );
+ dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+ "--> DiCMcb: CM callback MRA\n");
+}
+
+static void
+dapli_ib_cm_rtu_cb (
+ IN ib_cm_rtu_rec_t *p_cm_rtu_rec )
+{
+ DAPL_EP *ep_ptr;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert (p_cm_rtu_rec != NULL);
+
+ ep_ptr = (DAPL_EP * __ptr64) p_cm_rtu_rec->qp_context;
+
+ if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> %s: EP %lx invalid or FREED\n",
+ __FUNCTION__, ep_ptr);
+ return;
+ }
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);
+ return;
+ }
+ dapl_os_assert(cm_ptr->ib_cm.h_qp == p_cm_rtu_rec->h_qp);
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,
+ "--> DiCRucb: EP %lx QP %lx CR %lx\n",
+ ep_ptr, ep_ptr->qp_handle, ep_ptr->cr_ptr);
+
+ if (ep_ptr->cr_ptr)
+ {
+ DAPL_SP *sp_ptr;
+
+ sp_ptr = ((DAPL_CR *) ep_ptr->cr_ptr)->sp_ptr;
+
+ /* passive connection side */
+ dapls_cr_callback ( cm_ptr,
+ IB_CME_CONNECTED,
+ (void * __ptr64) p_cm_rtu_rec->p_rtu_pdata,
+ IB_RTU_PDATA_SIZE,
+ (void *) sp_ptr);
+
+ }
+ else
+ {
+ dapl_evd_connection_callback (
+ cm_ptr,
+ IB_CME_CONNECTED,
+ (void * __ptr64) p_cm_rtu_rec->p_rtu_pdata,
+ IB_RTU_PDATA_SIZE,
+ (void *) ep_ptr);
+ }
+}
+
+/*
+ * 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_address )
+{
+
+ DAPL_HEADER *header;
+ dp_ib_cm_handle_t cm;
+ char ipa[20];
+ char *rtype;
+
+ header = (DAPL_HEADER *)dat_handle;
+
+ if (header->magic == DAPL_MAGIC_EP)
+ {
+ cm = dapl_get_cm_from_ep((DAPL_EP *)dat_handle);
+ rtype = "EP";
+ }
+ else if (header->magic == DAPL_MAGIC_CR)
+ {
+ cm = ((DAPL_CR *) dat_handle)->ib_cm_handle;
+ rtype = "CR";
+ }
+ else
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM,
+ "%s: hdr->magic %x, dat_handle(%lx)\n",
+ __FUNCTION__, header->magic, dat_handle );
+ return DAT_INVALID_HANDLE;
+ }
+
+ dapl_os_memcpy( remote_address, &cm->dst_ip_addr, sizeof(DAT_SOCK_ADDR6) );
+
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s: returns %s remote Addrs %s\n",
+ __FUNCTION__, rtype,
+ dapli_get_ip_addr_str((DAT_SOCK_ADDR6*)remote_address,ipa) );
+
+ return DAT_SUCCESS;
+}
+
+
+/*
+ * 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 DAT_PVOID private_data )
+{
+ DAPL_EP *ep_ptr;
+ DAPL_IA *ia_ptr;
+ ib_api_status_t ib_status;
+ dapl_ibal_port_t *p_active_port;
+ dapl_ibal_ca_t *p_ca;
+ ib_cm_req_t cm_req;
+ ib_path_rec_t path_rec;
+ GID dest_GID;
+ ib_query_req_t query_req;
+ ib_gid_pair_t gid_pair;
+ ib_service_record_t service_rec;
+ int retry_cnt;
+ DAT_RETURN dat_status;
+
+ ep_ptr = (DAPL_EP *) ep_handle;
+ ia_ptr = ep_ptr->header.owner_ia;
+ ep_ptr->cr_ptr = NULL;
+ retry_cnt = 0;
+ dat_status = DAT_SUCCESS;
+
+ p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;
+
+ /*
+ * We are using the first active port in the list for
+ * communication. We have to get back here when we decide to support
+ * fail-over and high-availability.
+ */
+ 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,"--> DsC: Port %d not available %d\n",
+ ia_ptr->hca_ptr->port_num, __LINE__ );
+ return (DAT_INVALID_STATE);
+ }
+
+ dapl_os_memzero (&dest_GID, sizeof (GID));
+ dapl_os_memzero (&cm_req, sizeof (ib_cm_req_t));
+ dapl_os_memzero (&path_rec, sizeof (ib_path_rec_t));
+ dapl_os_memzero (&service_rec, sizeof (ib_service_record_t));
+ dapl_os_memzero (&query_req, sizeof (ib_query_req_t));
+ dapl_os_memzero (&gid_pair, sizeof (ib_gid_pair_t));
+ dapl_os_memzero (&ep_ptr->remote_ia_address, sizeof (DAT_SOCK_ADDR6));
+
+ dapl_os_memcpy (&ep_ptr->remote_ia_address,
+ remote_ia_address,
+ sizeof (ep_ptr->remote_ia_address));
+
+
+#ifdef NO_NAME_SERVICE
+
+ if (DAT_SUCCESS !=
+ (dat_status = dapls_ns_lookup_address (
+ ia_ptr,
+ remote_ia_address,
+ &dest_GID )))
+ {
+ /*
+ * Remote address not in the table, this is a
+ * strange return code!
+ */
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"--> DsC: exits status = %x\n", dat_status);
+ return dat_status;
+ }
+
+ dest_GID.guid = CL_HTON64 (dest_GID.guid);
+ dest_GID.gid_prefix = CL_HTON64 (dest_GID.gid_prefix);
+
+#else
+
+ /*
+ * We query the SA to get the dest_gid with the
+ * {uDAPL_svc_id, IP-address} as the key to get GID.
+ */
+ if (DAT_SUCCESS !=
+ (dat_status = dapls_ns_map_gid (ia_ptr->hca_ptr,
+ remote_ia_address,
+ &dest_GID)))
+
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsC: fail to map remote_ia_addr "
+ "(sa_family %d) to gid\n",
+ remote_ia_address->sa_family);
+ return dat_status;
+ }
+#endif /* NO_NAME_SERVICE */
+
+ gid_pair.dest_gid.unicast.interface_id = dest_GID.guid;
+ gid_pair.dest_gid.unicast.prefix = dest_GID.gid_prefix;
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "dapls_ib_connect: EP %lx QP %lx SERVER GID{0x" F64x
+ ", 0x" F64x "}\n",
+ ep_ptr, ep_ptr->qp_handle,
+ cl_hton64 (gid_pair.dest_gid.unicast.prefix),
+ cl_hton64 (gid_pair.dest_gid.unicast.interface_id));
+
+ gid_pair.src_gid = p_active_port->p_attr->p_gid_table[0];
+/*
+ if ((gid_pair.src_gid.unicast.interface_id ==
+ gid_pair.dest_gid.unicast.interface_id ) &&
+ (gid_pair.src_gid.unicast.prefix ==
+ gid_pair.dest_gid.unicast.prefix ))
+ {
+ path_rec.dgid = gid_pair.dest_gid;
+ path_rec.sgid = gid_pair.src_gid;
+ path_rec.slid = path_rec.dlid = p_active_port->p_attr->lid;
+ path_rec.pkey = p_active_port->p_attr->p_pkey_table[0];
+ path_rec.mtu = p_active_port->p_attr->mtu;
+ path_rec.pkt_life = 18; // 1 sec
+ path_rec.rate = IB_PATH_RECORD_RATE_10_GBS;
+
+ }
+ else
+ {
+ */
+ /*
+ * Query SA to get the path record from pair of GIDs
+ */
+ dapl_os_memzero (&query_req, sizeof (ib_query_req_t));
+ query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS;
+ query_req.p_query_input = (void *) &gid_pair;
+ query_req.flags = IB_FLAGS_SYNC;
+ query_req.timeout_ms = 1 * 1000; /* 1 second */
+ query_req.retry_cnt = 3;
+ /* query SA using this port */
+ query_req.port_guid = p_active_port->p_attr->port_guid;
+ query_req.query_context = (void *) &path_rec;
+ query_req.pfn_query_cb = dapli_ib_sa_query_cb;
+
+ ib_status = ib_query (dapl_ibal_root.h_al, &query_req, NULL);
+
+ if ((ib_status != IB_SUCCESS) || (!path_rec.dlid))
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"--> DsC: EP %lx QP %lx query "
+ "pair_gids status = %s\n",
+ ep_ptr, ep_ptr->qp_handle,ib_get_err_str(ib_status));
+ return DAT_INVALID_PARAMETER;
+ }
+
+ //}
+
+ /*
+ * Tavor has a HW bug that causes bandwidth with 2K MTU to be less than
+ * with 1K MTU. Cap the MTU based on device ID to compensate for this.
+ */
+ if( (p_ca->p_ca_attr->dev_id == 0x5A44) &&
+ (ib_path_rec_mtu( &path_rec ) > IB_MTU_LEN_1024) )
+ {
+ /* Local endpoint is Tavor - cap MTU to 1K for extra bandwidth. */
+ path_rec.mtu &= IB_PATH_REC_SELECTOR_MASK;
+ path_rec.mtu |= IB_MTU_LEN_1024;
+ }
+
+ /*
+ * prepare the Service ID from conn_qual
+ */
+ cm_req.svc_id = remote_conn_qual;
+ cm_req.p_primary_path = &path_rec;
+ cm_req.p_alt_path = NULL;
+ cm_req.h_qp = ep_ptr->qp_handle;
+ cm_req.qp_type = IB_QPT_RELIABLE_CONN;
+ cm_req.p_req_pdata = (uint8_t *) private_data;
+ cm_req.req_length = (uint8_t)
+ min(private_data_size,IB_MAX_REQ_PDATA_SIZE);
+ /* cm retry to send this request messages, IB max of 4 bits */
+ cm_req.max_cm_retries = 15; /* timer outside of call, s/be infinite */
+ /* qp retry to send any wr */
+ cm_req.retry_cnt = 5;
+ /* max num of oustanding RDMA read/atomic support */
+ cm_req.resp_res = (uint8_t)ep_ptr->param.ep_attr.max_rdma_read_in;
+ /* max num of oustanding RDMA read/atomic will use */
+ cm_req.init_depth = (uint8_t)ep_ptr->param.ep_attr.max_rdma_read_out;
+
+ /* time wait before retrying a pkt after receiving a RNR NAK */
+ cm_req.rnr_nak_timeout = IB_RNR_NAK_TIMEOUT;
+
+ /*
+ * number of time local QP should retry after receiving RNR NACK before
+ * reporting an error
+ */
+ cm_req.rnr_retry_cnt = IB_RNR_RETRY_CNT;
+
+ cm_req.remote_resp_timeout = 16; /* 250ms */
+ cm_req.local_resp_timeout = 16; /* 250ms */
+
+ cm_req.flow_ctrl = TRUE;
+ cm_req.flags = 0;
+ /*
+ * We do not use specific data buffer to check for specific connection
+ */
+ cm_req.p_compare_buffer = NULL;
+ cm_req.compare_offset = 0;
+ cm_req.compare_length = 0;
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM, "--> DsConn: EP=%lx QP=%lx rio=%d,%d pl=%d "
+ "mtu=%d slid=%#x dlid=%#x\n",
+ ep_ptr, ep_ptr->qp_handle, cm_req.resp_res,
+ cm_req.init_depth, ib_path_rec_pkt_life(&path_rec),
+ ib_path_rec_mtu(&path_rec),
+ cm_req.p_primary_path->slid,
+ cm_req.p_primary_path->dlid);
+
+ /*
+ * We do not support peer_to_peer; therefore, we set pfn_cm_req_cb = NULL
+ */
+ cm_req.pfn_cm_req_cb = NULL;
+ cm_req.pfn_cm_rep_cb = dapli_ib_cm_rep_cb;
+ cm_req.pfn_cm_rej_cb = dapli_ib_cm_rej_cb;
+ /* callback when a message received acknowledgement is received */
+ cm_req.pfn_cm_mra_cb = dapli_ib_cm_mra_cb;
+
+ ib_status = ib_cm_req (&cm_req);
+
+ if ( ib_status != IB_SUCCESS )
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsC: EP %lx QP %lx conn_request failed = %s\n",
+ ep_ptr, ep_ptr->qp_handle, ib_get_err_str(ib_status));
+
+ return (dapl_ib_status_convert (ib_status));
+ }
+
+ return DAT_SUCCESS;
+}
+
+
+/*
+ * dapls_ib_disconnect
+ *
+ * Disconnect an EP
+ *
+ * Input:
+ * ep_handle,
+ * disconnect_flags
+ * DAT_CLOSE_ABRUPT_FLAG - no callback
+ * DAT_CLOSE_GRACEFUL_FLAG - callback desired.
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * DAT_SUCCESS
+ * DAT_INSUFFICIENT_RESOURCES
+ * DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_disconnect ( IN DAPL_EP *ep_ptr,
+ IN DAT_CLOSE_FLAGS disconnect_flags )
+{
+ ib_api_status_t ib_status = IB_SUCCESS;
+ ib_cm_dreq_t cm_dreq;
+ dp_ib_cm_handle_t cm_ptr;
+
+ dapl_os_assert(ep_ptr);
+
+ if ( DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> %s: BAD EP Magic EP=%lx\n", __FUNCTION__,ep_ptr);
+ return DAT_SUCCESS;
+ }
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> %s: !CM_PTR on EP %p\n", __FUNCTION__, ep_ptr);
+ return DAT_SUCCESS;
+ }
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> %s() EP %p %s rx_drq %d tx_drq %d Close %s\n", __FUNCTION__,
+ ep_ptr, dapl_get_ep_state_str(ep_ptr->param.ep_state),
+ ep_ptr->recv_discreq, ep_ptr->sent_discreq,
+ (disconnect_flags == DAT_CLOSE_ABRUPT_FLAG ? "Abrupt":"Graceful"));
+
+ if ( disconnect_flags == DAT_CLOSE_ABRUPT_FLAG )
+ {
+ if ( ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED )
+ return DAT_SUCCESS;
+
+ if ( ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECT_PENDING )
+ {
+ dapl_dbg_log(DAPL_DBG_TYPE_CM,
+ "%s() calling legacy_post_disconnect()\n",__FUNCTION__);
+ dapl_ep_legacy_post_disconnect(ep_ptr, disconnect_flags);
+ return DAT_SUCCESS;
+ }
+ }
+
+ dapl_os_memzero(&cm_dreq, sizeof(ib_cm_dreq_t));
+
+ cm_dreq.qp_type = IB_QPT_RELIABLE_CONN;
+ cm_dreq.h_qp = ep_ptr->qp_handle;
+ cm_dreq.pfn_cm_drep_cb = dapli_ib_cm_drep_cb;
+
+ /*
+ * Currently we do not send any disconnect private data to
+ * the other endpoint because DAT 2.0 does not support it.
+ */
+ cm_dreq.p_dreq_pdata = NULL;
+ cm_dreq.flags = IB_FLAGS_SYNC;
+
+ /*
+ * still need to send DREQ (disconnect request)?
+ */
+ if ( (ep_ptr->recv_discreq == DAT_FALSE)
+ && (ep_ptr->sent_discreq == DAT_FALSE)
+ && (ep_ptr->qp_state != IB_QPS_RESET) )
+ {
+ ep_ptr->sent_discreq = DAT_TRUE;
+ ib_status = ib_cm_dreq ( &cm_dreq );
+
+ if ( ib_status == IB_SUCCESS )
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DsD: EP %p DREQ SENT\n", ep_ptr);
+
+ /* tolerate INVALID_STATE error as the other side can race ahead and
+ * generate a DREQ before we do.
+ */
+ if ( ib_status == IB_INVALID_STATE || ib_status == IB_INVALID_HANDLE )
+ {
+ ib_status = IB_SUCCESS;
+ }
+ else if (ib_status)
+ {
+ dapl_dbg_log(DAPL_DBG_TYPE_ERR,
+ "%s() EP %p ib_cm_dreq() status %s\n",
+ __FUNCTION__,ep_ptr,ib_get_err_str(ib_status));
+ }
+ }
+ return ib_status;
+}
+
+
+/*
+ * 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_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_setup_conn_listener (
+ IN DAPL_IA *ia_ptr,
+ IN DAT_UINT64 ServiceID,
+ IN DAPL_SP *sp_ptr )
+{
+ ib_api_status_t ib_status;
+ ib_cm_listen_t cm_listen;
+ dapl_ibal_ca_t *p_ca;
+ dapl_ibal_port_t *p_active_port;
+
+ p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;
+
+ /*
+ * We are using the first active port in the list for
+ * communication. We have to get back here when we decide to support
+ * fail-over and high-availability.
+ */
+ 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,"%s: SP %lx port %d not available\n",
+ __FUNCTION__, sp_ptr, ia_ptr->hca_ptr->port_num );
+ return (DAT_INVALID_STATE);
+ }
+
+ if (p_active_port->p_attr->lid == 0)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsSCL: SP %lx SID 0x" F64x " port %d\n",
+ sp_ptr, cl_hton64(ServiceID),
+ p_active_port->p_attr->port_num);
+ return (DAT_INVALID_STATE);
+ }
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "%s: SP %lx port %d GID{0x" F64x ", 0x" F64x "} and SID 0x" F64x "\n",
+ __FUNCTION__,
+ sp_ptr, p_active_port->p_attr->port_num,
+ cl_hton64 (p_active_port->p_attr->p_gid_table[0].unicast.prefix),
+ cl_hton64 (p_active_port->p_attr->p_gid_table[0].unicast.interface_id),
+ cl_hton64 (ServiceID));
+
+ dapl_os_memzero (&cm_listen, sizeof (ib_cm_listen_t));
+
+ /*
+ * Listen for all request on this specific CA
+ */
+ cm_listen.ca_guid = (p_ca->p_ca_attr->ca_guid);
+ cm_listen.svc_id = ServiceID;
+ cm_listen.qp_type = IB_QPT_RELIABLE_CONN;
+
+ /*
+ * We do not use specific data buffer to check for specific connection
+ */
+ cm_listen.p_compare_buffer = NULL;//(uint8_t*)&sp_ptr->conn_qual;
+ cm_listen.compare_offset = 0;//IB_MAX_REQ_PDATA_SIZE - sizeof(DAT_CONN_QUAL);
+ cm_listen.compare_length = 0;//sizeof(DAT_CONN_QUAL);
+
+ /*
+ * We can pick a port here for communication and the others are reserved
+ * for fail-over / high-availability - TBD
+ */
+ cm_listen.port_guid = p_active_port->p_attr->port_guid;
+ cm_listen.lid = p_active_port->p_attr->lid;
+ cm_listen.pkey = p_active_port->p_attr->p_pkey_table[0];
+
+ /*
+ * Register request or mra callback functions
+ */
+ cm_listen.pfn_cm_req_cb = dapli_ib_cm_req_cb;
+
+ ib_status = ib_cm_listen ( dapl_ibal_root.h_al,
+ &cm_listen,
+ (void *) sp_ptr,
+ &sp_ptr->cm_srvc_handle );
+
+ if (ib_status != IB_SUCCESS)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "%s: SP %lx SID 0x" F64x " listen failed %s\n",
+ __FUNCTION__, sp_ptr, cl_hton64 (ServiceID),
+ ib_get_err_str(ib_status));
+ }
+
+ return dapl_ib_status_convert (ib_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_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_remove_conn_listener (
+ IN DAPL_IA *ia_ptr,
+ IN DAPL_SP *sp_ptr )
+{
+ ib_api_status_t ib_status;
+ DAT_RETURN dat_status = DAT_SUCCESS;
+
+ UNUSED_PARAM( ia_ptr );
+
+ dapl_os_assert ( sp_ptr );
+
+ dapl_os_assert ( sp_ptr->header.magic == DAPL_MAGIC_PSP ||
+ sp_ptr->header.magic == DAPL_MAGIC_RSP );
+
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s() cm_srvc_handle %lx\n",
+ __FUNCTION__, sp_ptr->cm_srvc_handle );
+
+ if (sp_ptr->cm_srvc_handle)
+ {
+ ib_status = ib_cm_cancel ( sp_ptr->cm_srvc_handle,
+ NULL );
+
+ if (ib_status != IB_SUCCESS)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsRCL: SP %lx ib_cm_cancel failed(0x%x) %s\n",
+ sp_ptr, sp_ptr->cm_srvc_handle,
+ ib_get_err_str(ib_status));
+ sp_ptr->cm_srvc_handle = NULL;
+ return (DAT_INVALID_PARAMETER);
+ }
+
+ sp_ptr->cm_srvc_handle = NULL;
+ }
+
+ return dat_status;
+}
+
+/*
+ * dapls_ib_reject_connection
+ *
+ * Perform necessary steps to reject a connection
+ *
+ * Input:
+ * cr_handle
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * DAT_SUCCESS
+ * DAT_INSUFFICIENT_RESOURCES
+ * DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_reject_connection ( IN dp_ib_cm_handle_t ib_cm_handle,
+ IN int reject_reason,
+ IN DAT_COUNT private_data_size,
+ IN const DAT_PVOID private_data)
+{
+ ib_api_status_t ib_status;
+ ib_cm_rej_t cm_rej;
+ static char *rej_table[] =
+ {
+ "INVALID_REJ_REASON",
+ "INVALID_REJ_REASON",
+ "INVALID_REJ_REASON",
+ "INVALID_REJ_REASON",
+ "INVALID_REJ_REASON",
+ "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_CM_LOCAL_FAILURE"
+ };
+
+#define REJ_TABLE_SIZE IB_CM_LOCAL_FAILURE
+
+ reject_reason = __min( reject_reason & 0xff, REJ_TABLE_SIZE);
+
+ cm_rej.rej_status = IB_REJ_USER_DEFINED;
+ cm_rej.p_ari = (ib_ari_t *)&rej_table[reject_reason];
+ cm_rej.ari_length = (uint8_t)strlen (rej_table[reject_reason]);
+
+ cm_rej.p_rej_pdata = private_data;
+ cm_rej.rej_length = private_data_size;
+
+#if defined(DAPL_DBG) && 0
+ dapli_print_private_data("DsRjC",private_data,private_data_size);
+#endif
+
+ ib_status = ib_cm_rej(ib_cm_handle->ib_cm, &cm_rej);
+
+ if (ib_status != IB_SUCCESS)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsRjC: cm_handle %p reject failed %s\n",
+ ib_cm_handle, ib_get_err_str(ib_status) );
+ }
+
+ return ( dapl_ib_status_convert ( ib_status ) );
+}
+
+
+
+#if 0
+static void
+dapli_query_qp( ib_qp_handle_t qp_handle, ib_qp_attr_t *qpa )
+{
+ ib_api_status_t ib_status;
+
+ ib_status = ib_query_qp ( qp_handle, qpa );
+ if (ib_status != IB_SUCCESS)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,"ib_query_qp(%lx) '%s'\n",
+ qp_handle, ib_get_err_str(ib_status) );
+ }
+ else
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM, "--> QP(%lx) state %s "
+ "type %d init %d acc %x\n",
+ qp_handle,
+ ib_get_port_state_str(qpa->state),
+ qpa->qp_type,
+ qpa->init_depth,
+ qpa->access_ctrl );
+ }
+}
+#endif
+
+
+/*
+ * 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_INVALID_PARAMETER
+ *
+ */
+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 )
+{
+ DAPL_CR *cr_ptr;
+ DAPL_EP *ep_ptr;
+ DAPL_IA *ia_ptr;
+ DAT_RETURN dat_status;
+ ib_api_status_t ib_status;
+ dapl_ibal_ca_t *p_ca;
+ dapl_ibal_port_t *p_active_port;
+ ib_cm_rep_t cm_rep;
+ ib_qp_attr_t qpa;
+ dp_ib_cm_handle_t cm_ptr;
+
+ cr_ptr = (DAPL_CR *) cr_handle;
+ ep_ptr = (DAPL_EP *) ep_handle;
+ ia_ptr = ep_ptr->header.owner_ia;
+
+ 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, ep_ptr );
+
+ if ( dat_status != DAT_SUCCESS)
+ {
+ /* This is not a great error code, but all the spec allows */
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsIBAC: CR %lx EP %lx alloc QP failed 0x%x\n",
+ cr_ptr, ep_ptr, dat_status );
+ return (dat_status);
+ }
+ }
+
+ 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,
+ "--> DsIBAC: CR %lx EP %lx port %d is not available\n",
+ cr_ptr, ep_ptr, ia_ptr->hca_ptr->port_num);
+ return (DAT_INVALID_STATE);
+ }
+
+ cr_ptr->param.local_ep_handle = ep_handle;
+
+ /*
+ * assume ownership, in that once the EP is released the dynamic
+ * memory containing the IBAL CM handle (ib_cm_handle_t) struct will
+ * be released; see dapl_ep_dealloc().
+ */
+
+ /* EP-CM, save/release CR CM object, use EP CM object already linked */
+ cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ if (!cm_ptr) {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsIBAC: CM linking to EP %p not available\n",
+ ep_ptr);
+ return (DAT_INVALID_STATE);
+ }
+
+ /* set remote IP addr fields. IP addr data is deduced from Connection
+ * Request record (gid/lib) and stashed away for use here. DAPL 1.1
+ * had an interface for passing the IP info down, interface went away
+ * in 2.0?
+ */
+ dapl_os_memcpy( (void*)&ep_ptr->remote_ia_address,
+ (void*)&cr_ptr->ib_cm_handle->dst_ip_addr,
+ sizeof(DAT_SOCK_ADDR6) );
+
+ dapl_os_memcpy( (void*)&cr_ptr->remote_ia_address,
+ (void*)&ep_ptr->remote_ia_address,
+ sizeof(DAT_SOCK_ADDR6) );
+
+#if defined(DAPL_DBG)
+ {
+ char ipa[20];
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM|DAPL_DBG_TYPE_CALLBACK,
+ "%s: EP(%lx) RemoteAddr: %s\n",
+ __FUNCTION__, ep_ptr,
+ dapli_get_ip_addr_str(
+ (DAT_SOCK_ADDR6*)&ep_ptr->remote_ia_address, ipa) );
+ }
+#endif
+
+ dapl_os_memcpy( (void*)&cm_ptr->dst_ip_addr,
+ (void*)&cr_ptr->ib_cm_handle->dst_ip_addr,
+ sizeof(DAT_SOCK_ADDR6) );
+
+ /* get h_al and connection ID from CR CM object, h_qp already set */
+ cm_ptr->ib_cm.cid = cr_ptr->ib_cm_handle->ib_cm.cid;
+ cm_ptr->ib_cm.h_al = cr_ptr->ib_cm_handle->ib_cm.h_al;
+ dapls_cm_release(cr_ptr->ib_cm_handle);
+
+ cr_ptr->ib_cm_handle = cm_ptr; /* for dapli_get_sp_ep() upcall */
+
+ ep_ptr->cr_ptr = cr_ptr;
+
+ dapl_os_memzero ( (void*)&cm_rep, sizeof (ib_cm_rep_t) );
+
+ cm_rep.h_qp = ep_ptr->qp_handle;
+ cm_rep.qp_type = IB_QPT_RELIABLE_CONN;
+
+ if (private_data_size > IB_MAX_REP_PDATA_SIZE) {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,
+ "--> DsIBAC: private_data_size(%d) > Max(%d)\n",
+ private_data_size, IB_MAX_REP_PDATA_SIZE);
+ return DAT_ERROR(DAT_LENGTH_ERROR, DAT_NO_SUBTYPE);
+
+ }
+ cm_rep.p_rep_pdata = (const uint8_t *)private_data;
+ cm_rep.rep_length = private_data_size;
+
+#if defined(DAPL_DBG) && 0
+ dapli_print_private_data( "DsIBAC",
+ (const uint8_t*)private_data,
+ private_data_size );
+#endif
+
+ cm_rep.pfn_cm_rej_cb = dapli_ib_cm_rej_cb;
+ cm_rep.pfn_cm_mra_cb = dapli_ib_cm_mra_cb;
+ cm_rep.pfn_cm_rtu_cb = dapli_ib_cm_rtu_cb;
+ cm_rep.pfn_cm_lap_cb = dapli_ib_cm_lap_cb;
+ cm_rep.pfn_cm_dreq_cb = dapli_ib_cm_dreq_cb;
+
+ /*
+ * FIXME - Vu
+ * Pay attention to the attributes.
+ * Some of them are desirably set by DAT consumers
+ */
+ /*
+ * We enable the qp associate with this connection ep all the access right
+ * We enable the flow_ctrl, retry till success
+ * We will limit the access right and flow_ctrl upon DAT consumers
+ * requirements
+ */
+ cm_rep.access_ctrl =
+ IB_AC_LOCAL_WRITE|IB_AC_RDMA_WRITE|IB_AC_MW_BIND|IB_AC_ATOMIC;
+
+ if ((ep_ptr->param.ep_attr.max_rdma_read_in > 0)
+ || (ep_ptr->param.ep_attr.max_rdma_read_out > 0))
+ {
+ cm_rep.access_ctrl |= IB_AC_RDMA_READ;
+ }
+
+ cm_rep.sq_depth = 0;
+ cm_rep.rq_depth = 0;
+ cm_rep.init_depth = (uint8_t)ep_ptr->param.ep_attr.max_rdma_read_out;
+ cm_rep.flow_ctrl = TRUE;
+ cm_rep.flags = 0;
+ cm_rep.failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;
+ cm_rep.target_ack_delay = 14;
+ cm_rep.rnr_nak_timeout = IB_RNR_NAK_TIMEOUT;
+ cm_rep.rnr_retry_cnt = IB_RNR_RETRY_CNT;
+ cm_rep.pp_recv_failure = NULL;
+ cm_rep.p_recv_wr = NULL;
+
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DsIBAC: cm_rep: acc %x init %d qp_type %x req_count %d\n",
+ cm_rep.access_ctrl, cm_rep.init_depth,cm_rep.qp_type,
+ dapls_cb_pending(&ep_ptr->req_buffer));
+
+ ib_status = ib_cm_rep ( cm_ptr->ib_cm, &cm_rep );
+
+ if (ib_status != IB_SUCCESS)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsIBAC: EP %lx QP %lx CR reply failed '%s'\n",
+ ep_ptr, ep_ptr->qp_handle, ib_get_err_str(ib_status) );
+ }
+
+ return ( dapl_ib_status_convert ( ib_status ) );
+}
+
+
+
+/*
+ * 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
+ *
+ * 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 )
+{
+ DAPL_IA *ia_ptr;
+ ib_qp_attr_t qp_attr;
+ ib_api_status_t ib_status;
+
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%s(%s): cm_event: %s \n", __FUNCTION__,
+ (active?"A":"P"), dapli_ib_cm_event_str(ib_cm_event));
+
+ ia_ptr = ep_ptr->header.owner_ia;
+
+ if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM,
+ ">>>DSCONN_CLEAN(%s): cm_event: %s Invalid IA_ptr\n",
+ (active?"Act":"Pas"),dapli_ib_cm_event_str(ib_cm_event));
+ return;
+ }
+ dapl_os_assert ( ep_ptr->header.magic == DAPL_MAGIC_EP );
+
+ ep_ptr->sent_discreq = DAT_FALSE;
+ ep_ptr->recv_discreq = DAT_FALSE;
+
+ /*
+ * Query the QP to get the current state */
+ ib_status = ib_query_qp ( ep_ptr->qp_handle, &qp_attr );
+
+ if ( ib_status != IB_SUCCESS )
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ ">>>DSCONN_CLEAN(%s): Query QP failed = %s\n",
+ (active?"Act":"Pas"),ib_get_err_str(ib_status) );
+ return;
+ }
+
+ ep_ptr->qp_state = qp_attr.state;
+
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM, ">>>DSCONN_CLEAN(%s): cm_event: %d "
+ "ep_ptr %lx ep_state %s qp_state %#x\n",
+ (active?"A":"P"), ib_cm_event, ep_ptr,
+ dapl_get_ep_state_str(ep_ptr->param.ep_state),
+ ep_ptr->qp_state );
+
+ if ( ep_ptr->qp_state != IB_QPS_ERROR &&
+ ep_ptr->qp_state != IB_QPS_RESET &&
+ ep_ptr->qp_state != IB_QPS_INIT )
+ {
+ ep_ptr->qp_state = IB_QPS_ERROR;
+ dapls_modify_qp_state_to_error (ep_ptr->qp_handle);
+ }
+}
+
+
+#ifdef NOT_USED
+/*
+ * dapls_ib_cr_handoff
+ *
+ * Hand off the connection request to another service point
+ *
+ * Input:
+ * cr_handle DAT_CR_HANDLE
+ * handoff_serv_id DAT_CONN_QUAL
+ *
+ * Output:
+ * none
+ *
+ * Returns:
+ * DAT_SUCCESS
+ * DAT_INVALID_PARAMETER
+ *
+ */
+DAT_RETURN
+dapls_ib_cr_handoff (
+ IN DAT_CR_HANDLE cr_handle,
+ IN DAT_CONN_QUAL handoff_serv_id )
+{
+ DAPL_CR *cr_ptr;
+ ib_api_status_t ib_status;
+
+ cr_ptr = (DAPL_CR *) cr_handle;
+
+ if (cr_ptr->ib_cm_handle->ib_cm.cid == 0xFFFFFFFF)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsCH: CR = %lx invalid cm handle\n", cr_ptr);
+ return DAT_INVALID_PARAMETER;
+ }
+
+ if (cr_ptr->sp_ptr == DAPL_IB_INVALID_HANDLE)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsCH: CR = %lx invalid psp handle\n", cr_ptr);
+ return DAT_INVALID_PARAMETER;
+ }
+
+ ib_status = ib_cm_handoff (cr_ptr->ib_cm_handle->ib_cm, handoff_serv_id);
+
+ if (ib_status != IB_SUCCESS)
+ {
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
+ "--> DsCH: CR = %lx handoff failed = %s\n",
+ cr_ptr, ib_get_err_str(ib_status) );
+
+ return dapl_ib_status_convert (ib_status);
+ }
+
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM,
+ "--> %s(): remove CR %lx from SP %lx Queue\n",
+ __FUNCTION__, cr_ptr, cr_ptr->sp_ptr);
+ /* Remove the CR from the queue */
+ dapl_sp_remove_cr (cr_ptr->sp_ptr, cr_ptr);
+
+ /*
+ * If this SP has been removed from service, free it
+ * up after the last CR is removed
+ */
+ dapl_os_lock (&cr_ptr->sp_ptr->header.lock);
+ if ( cr_ptr->sp_ptr->listening != DAT_TRUE &&
+ cr_ptr->sp_ptr->cr_list_count == 0 &&
+ cr_ptr->sp_ptr->state != DAPL_SP_STATE_FREE )
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,
+ "--> DsCH: CR = %lx disconnect dump SP = %lx \n",
+ cr_ptr, cr_ptr->sp_ptr);
+ /* Decrement the ref count on the EVD */
+ if (cr_ptr->sp_ptr->evd_handle)
+ {
+ dapl_os_atomic_dec (& ((DAPL_EVD *)cr_ptr->sp_ptr->evd_handle)->evd_ref_count);
+ cr_ptr->sp_ptr->evd_handle = NULL;
+ }
+ cr_ptr->sp_ptr->state = DAPL_SP_STATE_FREE;
+ dapl_os_unlock (&cr_ptr->sp_ptr->header.lock);
+ (void)dapls_ib_remove_conn_listener ( cr_ptr->sp_ptr->header.owner_ia,
+ cr_ptr->sp_ptr );
+ dapls_ia_unlink_sp ( (DAPL_IA *)cr_ptr->sp_ptr->header.owner_ia,
+ cr_ptr->sp_ptr );
+ dapls_sp_free_sp ( cr_ptr->sp_ptr );
+ }
+ else
+ {
+ dapl_os_unlock (&cr_ptr->sp_ptr->header.lock);
+ }
+
+ /*
+ * Clean up and dispose of the resource
+ */
+ dapls_cr_free (cr_ptr);
+
+ return (DAT_SUCCESS);
+}
+#endif
+
+int
+dapls_ib_private_data_size (
+ IN DAPL_HCA *hca_ptr)
+{
+ return IB_MAX_REQ_PDATA_SIZE;
+}
+
+
+/*
+ * 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
+
+/*
+ * 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"
+#include "dapl_ep_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;
+ dp_ib_cm_handle_t cm_ptr;
+
+ 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);
+ }
+ /* EP-CM linking */
+ cm_ptr = ibal_cm_alloc();
+ if (!cm_ptr)
+ {
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DsQA: Create CM failed\n");
+ return (DAT_INSUFFICIENT_RESOURCES);
+ }
+ cm_ptr->ib_cm.h_qp = ep_ptr->qp_handle;
+ cm_ptr->ep = ep_ptr;
+ dapl_ep_link_cm(ep_ptr, cm_ptr);
+
+ 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_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
+
+/*
+ * 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
+
+/* EP-CM linking requires list_entry, protected ref counting */
+typedef struct dapl_ibal_cm
+{
+ struct dapl_llist_entry list_entry;
+ DAPL_OS_LOCK lock;
+ int ref_count;
+ DAT_SOCK_ADDR6 dst_ip_addr;
+ ib_cm_handle_t ib_cm; /* h_al, h_qp, cid */
+ DAPL_EP *ep;
+
+} dapl_ibal_cm_t;
+
+typedef dapl_ibal_cm_t *dp_ib_cm_handle_t;
+typedef ib_listen_handle_t ib_cm_srvc_handle_t;
+
+/* EP-CM linking prototypes */
+extern void dapls_cm_acquire(dp_ib_cm_handle_t cm_ptr);
+extern void dapls_cm_release(dp_ib_cm_handle_t cm_ptr);
+extern void dapls_cm_free(dp_ib_cm_handle_t cm_ptr);
+extern dp_ib_cm_handle_t ibal_cm_alloc(void);
+
+#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_ */
-#
-# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
-# file to this component. This file merely indirects to the real make file
-# that is shared by all the driver components of the OpenIB Windows project.
-#
-
-!INCLUDE ..\..\..\..\inc\openib.def
+#\r
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
+# file to this component. This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\..\inc\openib.def\r
-/*\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
+/*
+ * 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) 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
+/*
+ * 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;
+
+ /* Add support for multiple CM object ownership */
+ DAPL_LLIST_HEAD cm_list_head;
+
+ /* 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;
+#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
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
- if (conn->cm_id) {
- if (conn->cm_id->qp)
- rdma_destroy_qp(conn->cm_id);
- rdma_destroy_id(conn->cm_id);
- }\r
- dapl_os_unlock(&conn->lock);\r
- dapli_cm_dealloc(conn);\r
+ conn->ref_count--;
+ if (conn->ref_count) {
+ dapl_os_unlock(&conn->lock);
+ return;
+ }
+ dapl_os_unlock(&conn->lock);
+ dapli_cm_dealloc(conn);
}
/* BLOCKING: called from dapl_ep_free, EP link will be last 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);
+ struct rdma_cm_id *cm_id = conn->cm_id;
+
+ if (cm_id->qp)
+ rdma_destroy_qp(cm_id);
conn->cm_id = NULL;
+ dapl_os_unlock(&conn->lock);
+ rdma_destroy_id(cm_id); /* blocking, event processing */
+ dapl_os_lock(&conn->lock);
}
/* EP linking is last reference */
/* no graceful half-pipe disconnect option */
rdma_disconnect(conn->cm_id);
+ /* ABRUPT close, wait for callback and DISCONNECTED state */
+ if (close_flags == DAT_CLOSE_ABRUPT_FLAG) {
+ dapl_os_lock(&ep_ptr->header.lock);
+ while (ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECTED) {
+ dapl_os_unlock(&ep_ptr->header.lock);
+ dapl_os_sleep_usec(10000);
+ dapl_os_lock(&ep_ptr->header.lock);
+ }
+ dapl_os_unlock(&ep_ptr->header.lock);
+ }
+
/*
* DAT event notification occurs from the callback
* Note: will fire even if DREQ goes unanswered on timeout
return DAT_SUCCESS;
bail:
+ rdma_destroy_id(conn->cm_id);
dapls_cm_release(conn);
return dat_status;
}
if (conn != IB_INVALID_HANDLE) {
sp_ptr->cm_srvc_handle = NULL;
+ if (conn->cm_id) {
+ rdma_destroy_id(conn->cm_id);
+ conn->cm_id = NULL;
+ }
dapls_cm_release(conn);
}
+
return DAT_SUCCESS;
}
dapl_ep_unlink_cm(ep_ptr, ep_conn);
ep_conn->cm_id->qp = NULL;
ep_conn->ep = NULL;
+ rdma_destroy_id(ep_conn->cm_id);
dapls_cm_release(ep_conn);
/* add new CM to EP linking, qp_handle unchanged */
rdma_reject(cr_conn->cm_id, NULL, 0);
/* no EP linking, ok to destroy */
+ rdma_destroy_id(cr_conn->cm_id);
dapls_cm_release(cr_conn);
return dat_status;
}
cm_handle->p_data, offset + private_data_size);
/* no EP linking, ok to destroy */
+ rdma_destroy_id(cm_handle->cm_id);
dapls_cm_release(cm_handle);
return dapl_convert_errno(ret, "reject");
}
dapls_cm_acquire(conn);
+ /* destroying cm_id, consumer thread blocking waiting for ACK */
+ if (conn->cm_id == NULL) {
+ dapls_cm_release(conn);
+ rdma_ack_cm_event(event);
+ return;
+ }
+
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);
#define IB_MAX_AT_RETRY 3
/* CMA private data areas, use CMA max with known transport definitions */
+#ifndef RDMA_MAX_PRIVATE_DATA
+#if defined(_WIN64) || defined(_WIN32)
+#define RDMA_MAX_PRIVATE_DATA 64
+#else
+#define RDMA_MAX_PRIVATE_DATA 256
+#endif
+#endif
+
#define CMA_PDATA_HDR 36
#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)
uint8_t tclass;
uint8_t mtu;
DAT_NAMED_ATTR named_attr;
-
+ uint8_t sl;
+ uint16_t pkey;
+ int pkey_idx;
} ib_hca_transport_t;
/* prototypes */
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);
return 0;
}
#else // _WIN64 || WIN32
+
int g_ib_pipe[2];
static int dapls_os_init(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)
{
/* 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;
+ 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;
}
/*
* 0 success, -1 error
*
*/
+DAT_UINT32 g_parent = 0;
int32_t dapls_ib_init(void)
{
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " dapl_ib_init: \n");
+ g_parent = dapl_os_getpid();
/* initialize hca_list lock */
dapl_os_lock_init(&g_hca_lock);
int32_t dapls_ib_release(void)
{
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " dapl_ib_release: \n");
+ /* only parent will cleanup */
+ if (dapl_os_getpid() != g_parent)
+ return 0;
+
dapli_ib_thread_destroy();
if (g_cm_events != NULL)
rdma_destroy_event_channel(g_cm_events);
#define OPENIB_OSD_H
#include <rdma/rdma_cma.h>
-#include <rdma/rdma_cma_abi.h>
#include <byteswap.h>
#include <sys/poll.h>
#define DCM_TCLASS 0
/* DAPL uCM timers, default queue sizes */
-#define DCM_RETRY_CNT 10
+#define DCM_RETRY_CNT 15
#define DCM_REP_TIME 800 /* reply timeout in m_secs */
#define DCM_RTU_TIME 400 /* rtu timeout in m_secs */
#define DCM_QP_SIZE 500 /* uCM tx, rx qp size */
/* util.c */
enum ibv_mtu dapl_ib_mtu(int mtu);
char *dapl_ib_mtu_str(enum ibv_mtu mtu);
-DAT_RETURN getlocalipaddr(DAT_SOCK_ADDR *addr, int addr_len);
+int getipaddr_netdev(char *name, char *addr, int addr_len);
+DAT_RETURN getlocalipaddr(char *addr, int addr_len);
/* qp.c */
DAT_RETURN dapls_modify_qp_ud(IN DAPL_HCA *hca, IN ib_qp_handle_t qp);
}
#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_alloc: qpn %p type %d sq %d,%d rq %d,%d\n",
+ ep_ptr->qp_handle->qp_num, ep_ptr->qp_handle->qp_type,
qp_create.cap.max_send_wr, qp_create.cap.max_send_sge,
qp_create.cap.max_recv_wr, qp_create.cap.max_recv_sge);
qp_attr.ah_attr.grh.traffic_class =
ia_ptr->hca_ptr->ib_trans.tclass;
}
- qp_attr.ah_attr.sl = 0;
+ qp_attr.ah_attr.sl = ia_ptr->hca_ptr->ib_trans.sl;
qp_attr.ah_attr.src_path_bits = 0;
qp_attr.ah_attr.port_num = ia_ptr->hca_ptr->port_num;
qp_attr.qkey = DAT_UD_QKEY;
}
- qp_attr.pkey_index = 0;
+ qp_attr.pkey_index = ia_ptr->hca_ptr->ib_trans.pkey_idx;
qp_attr.port_num = ia_ptr->hca_ptr->port_num;
dapl_dbg_log(DAPL_DBG_TYPE_EP,
/* 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.pkey_index = hca->ib_trans.pkey_idx;
qp_attr.port_num = hca->port_num;
qp_attr.qkey = DAT_UD_QKEY;
if (ibv_modify_qp(qp, &qp_attr,
struct ibv_qp_attr qp_attr;
ib_ah_handle_t ah;
- if (qp->qp_type != IBV_QPT_UD)
+ if (qp->qp_type != IBV_QPT_UD) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " create_ah ERR: QP_type != UD\n");
return NULL;
+ }
dapl_os_memzero((void *)&qp_attr, sizeof(qp_attr));
qp_attr.qp_state = IBV_QP_STATE;
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.sl = hca->ib_trans.sl;
qp_attr.ah_attr.src_path_bits = 0;
qp_attr.ah_attr.port_num = hca->port_num;
int g_dapl_loopback_connection = 0;
+#if defined(_WIN64) || defined(_WIN32)
+#include "..\..\..\..\..\etc\user\comp_channel.cpp"
+#include <rdma\winverbs.h>
+
+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;
+}
+
+#else // _WIN64 || WIN32
+
+/* Get IP address using network device name */
+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;
+}
+#endif
+
enum ibv_mtu dapl_ib_mtu(int mtu)
{
switch (mtu) {
}
}
-DAT_RETURN getlocalipaddr(DAT_SOCK_ADDR * addr, int addr_len)
+DAT_RETURN getlocalipaddr(char *addr, int addr_len)
{
struct sockaddr_in *sin;
struct addrinfo *res, hint, *ai;
int ret;
char hostname[256];
+ char *netdev = getenv("DAPL_SCM_NETDEV");
+
+ /* use provided netdev instead of default hostname */
+ if (netdev != NULL) {
+ ret = getipaddr_netdev(netdev, addr, addr_len);
+ if (ret) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " getlocalipaddr: DAPL_SCM_NETDEV provided %s"
+ " but not configured on system? ERR = %s\n",
+ netdev, strerror(ret));
+ return dapl_convert_errno(ret, "getlocalipaddr");
+ } else
+ return DAT_SUCCESS;
+ }
if (addr_len < sizeof(*sin)) {
return DAT_INTERNAL_ERROR;
hca_ptr->ib_trans.named_attr.value =
dapl_ib_mtu_str(hca_ptr->ib_trans.mtu);
+ if (hca_ptr->ib_hca_handle->device->transport_type != IBV_TRANSPORT_IB)
+ goto skip_ib;
+
+ /* set SL, PKEY values, defaults = 0 */
+ hca_ptr->ib_trans.pkey_idx = 0;
+ hca_ptr->ib_trans.pkey = dapl_os_get_env_val("DAPL_IB_PKEY", 0);
+ hca_ptr->ib_trans.sl = dapl_os_get_env_val("DAPL_IB_SL", 0);
+
+ /* index provided, get pkey; pkey provided, get index */
+ if (hca_ptr->ib_trans.pkey) {
+ int i; uint16_t pkey = 0;
+ for (i=0; i < dev_attr.max_pkeys; i++) {
+ if (ibv_query_pkey(hca_ptr->ib_hca_handle,
+ hca_ptr->port_num,
+ i, &pkey)) {
+ i = dev_attr.max_pkeys;
+ break;
+ }
+ if (pkey == hca_ptr->ib_trans.pkey) {
+ hca_ptr->ib_trans.pkey_idx = i;
+ break;
+ }
+ }
+ if (i == dev_attr.max_pkeys) {
+ dapl_log(DAPL_DBG_TYPE_WARN,
+ " Warning: new pkey(%d), query (%s)"
+ " err or key !found, using defaults\n",
+ hca_ptr->ib_trans.pkey, strerror(errno));
+ }
+ }
+skip_ib:
+
+#ifdef DEFINE_ATTR_LINK_LAYER
+#ifndef _OPENIB_CMA_
+ if (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET)
+ hca_ptr->ib_trans.global = 1;
+
+ dapl_log(DAPL_DBG_TYPE_UTIL,
+ " query_hca: port.link_layer = 0x%x\n",
+ port_attr.link_layer);
+#endif
+#endif
dapl_log(DAPL_DBG_TYPE_UTIL,
" query_hca: (%x.%x) eps %d, sz %d evds %d,"
- " sz %d mtu %d\n",
+ " sz %d mtu %d - pkey %d p_idx %d sl %d\n",
ia_attr->hardware_version_major,
ia_attr->hardware_version_minor,
ia_attr->max_eps, ia_attr->max_dto_per_ep,
ia_attr->max_evds, ia_attr->max_evd_qlen,
- 128 << hca_ptr->ib_trans.mtu);
+ 128 << hca_ptr->ib_trans.mtu,
+ hca_ptr->ib_trans.pkey,
+ hca_ptr->ib_trans.pkey_idx,
+ hca_ptr->ib_trans.sl);
dapl_log(DAPL_DBG_TYPE_UTIL,
" query_hca: msg %llu rdma %llu iov %d lmr %d rmr %d"
$(SDK_LIB_PATH)\ws2_32.lib \\r
!if $(FREEBUILD)\r
$(TARGETPATH)\*\dat2.lib \\r
+ $(TARGETPATH)\*\winverbs.lib \\r
$(TARGETPATH)\*\libibverbs.lib\r
!else\r
$(TARGETPATH)\*\dat2d.lib \\r
+ $(TARGETPATH)\*\winverbs.lib \\r
$(TARGETPATH)\*\libibverbsd.lib\r
!endif\r
\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: 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_ep_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 = 1;\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_THREAD,\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_THREAD, " 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_THREAD, " dapl_select: sleep, fds=%d\n", set->index);\r
- ret = poll(set->set, set->index, -1);\r
- dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " dapl_select: wakeup, ret=0x%x\n", ret);\r
- return ret;\r
-}\r
-\r
-#define dapl_socket_errno() errno\r
-#endif\r
-\r
-static void dapli_cm_thread_signal(dp_ib_cm_handle_t cm_ptr) \r
-{\r
- send(cm_ptr->hca->ib_trans.scm[1], "w", sizeof "w", 0);\r
-}\r
-\r
-static void dapli_cm_free(dp_ib_cm_handle_t cm_ptr) \r
-{\r
- dapl_os_lock(&cm_ptr->lock);\r
- cm_ptr->state = DCM_FREE;\r
- dapl_os_unlock(&cm_ptr->lock);\r
- dapli_cm_thread_signal(cm_ptr);\r
-}\r
-\r
-static void dapli_cm_dealloc(dp_ib_cm_handle_t cm_ptr) \r
-{\r
- dapl_os_assert(!cm_ptr->ref_count);\r
- \r
- if (cm_ptr->socket != DAPL_INVALID_SOCKET) {\r
- shutdown(cm_ptr->socket, SHUT_RDWR);\r
- closesocket(cm_ptr->socket);\r
- }\r
- if (cm_ptr->ah) \r
- ibv_destroy_ah(cm_ptr->ah);\r
- \r
- dapl_os_lock_destroy(&cm_ptr->lock);\r
- dapl_os_wait_object_destroy(&cm_ptr->event);\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
- dapli_cm_dealloc(cm_ptr);\r
-}\r
-\r
-static dp_ib_cm_handle_t dapli_cm_alloc(DAPL_EP *ep_ptr)\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
- if (dapl_os_wait_object_init(&cm_ptr->event)) {\r
- dapl_os_lock_destroy(&cm_ptr->lock);\r
- goto bail;\r
- }\r
- dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm_ptr->list_entry);\r
- dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&cm_ptr->local_entry);\r
-\r
- cm_ptr->msg.ver = htons(DCM_VER);\r
- cm_ptr->socket = DAPL_INVALID_SOCKET;\r
- dapls_cm_acquire(cm_ptr);\r
- \r
- /* Link EP and CM */\r
- if (ep_ptr != NULL) {\r
- dapl_ep_link_cm(ep_ptr, cm_ptr); /* ref++ */\r
- cm_ptr->ep = ep_ptr;\r
- cm_ptr->hca = ((DAPL_IA *)ep_ptr->param.ia_handle)->hca_ptr;\r
- }\r
- return cm_ptr;\r
-bail:\r
- dapl_os_free(cm_ptr, sizeof(*cm_ptr));\r
- return NULL;\r
-}\r
-\r
-/* queue socket for processing CM work */\r
-static void dapli_cm_queue(dp_ib_cm_handle_t cm_ptr)\r
-{\r
- /* add to work queue for cr thread processing */\r
- dapl_os_lock(&cm_ptr->hca->ib_trans.lock);\r
- dapls_cm_acquire(cm_ptr);\r
- dapl_llist_add_tail(&cm_ptr->hca->ib_trans.list,\r
- (DAPL_LLIST_ENTRY *)&cm_ptr->local_entry, cm_ptr);\r
- dapl_os_unlock(&cm_ptr->hca->ib_trans.lock);\r
- dapli_cm_thread_signal(cm_ptr);\r
-}\r
-\r
-/* called with local LIST lock */\r
-static void dapli_cm_dequeue(dp_ib_cm_handle_t cm_ptr)\r
-{\r
- /* Remove from work queue, cr thread processing */\r
- dapl_llist_remove_entry(&cm_ptr->hca->ib_trans.list,\r
- (DAPL_LLIST_ENTRY *)&cm_ptr->local_entry);\r
- dapls_cm_release(cm_ptr);\r
-}\r
-\r
-/* BLOCKING: called from dapl_ep_free, EP link will be last ref */\r
-void dapls_cm_free(dp_ib_cm_handle_t cm_ptr)\r
-{\r
- dapl_log(DAPL_DBG_TYPE_CM,\r
- " cm_free: cm %p %s ep %p refs=%d\n", \r
- cm_ptr, dapl_cm_state_str(cm_ptr->state),\r
- cm_ptr->ep, cm_ptr->ref_count);\r
- \r
- /* free from internal workq, wait until EP is last ref */\r
- dapl_os_lock(&cm_ptr->lock);\r
- cm_ptr->state = DCM_FREE;\r
- while (cm_ptr->ref_count != 1) {\r
- dapl_os_unlock(&cm_ptr->lock);\r
- dapl_os_sleep_usec(10000);\r
- dapl_os_lock(&cm_ptr->lock);\r
- }\r
- dapl_os_unlock(&cm_ptr->lock);\r
-\r
- /* unlink, dequeue from EP. Final ref so release will destroy */\r
- dapl_ep_unlink_cm(cm_ptr->ep, cm_ptr);\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
- DAT_UINT32 disc_data = htonl(0xdead);\r
-\r
- dapl_os_lock(&cm_ptr->lock);\r
- if (cm_ptr->state != DCM_CONNECTED || \r
- cm_ptr->state == DCM_DISCONNECTED) {\r
- dapl_os_unlock(&cm_ptr->lock);\r
- return DAT_SUCCESS;\r
- }\r
- cm_ptr->state = DCM_DISCONNECTED;\r
- dapl_os_unlock(&cm_ptr->lock);\r
- \r
- /* send disc date, close socket, schedule destroy */\r
- dapls_modify_qp_state(cm_ptr->ep->qp_handle, IBV_QPS_ERR, 0,0,0);\r
- send(cm_ptr->socket, (char *)&disc_data, sizeof(disc_data), 0);\r
-\r
- /* disconnect events for RC's only */\r
- if (cm_ptr->ep->param.ep_attr.service_type == DAT_SERVICE_TYPE_RC) {\r
- if (cm_ptr->ep->cr_ptr) {\r
- dapls_cr_callback(cm_ptr,\r
- IB_CME_DISCONNECTED,\r
- NULL, 0, cm_ptr->sp);\r
- } else {\r
- dapl_evd_connection_callback(cm_ptr,\r
- IB_CME_DISCONNECTED,\r
- NULL, 0, cm_ptr->ep);\r
- }\r
- }\r
- \r
- /* release from workq */\r
- dapli_cm_free(cm_ptr);\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
- /* mark CM object for cleanup */\r
- dapli_cm_free(cm_ptr);\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
-static 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 = dapli_cm_alloc(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->hca = ia_ptr->hca_ptr;\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
- /* 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
- /* queue up on work thread */\r
- dapli_cm_queue(cm_ptr);\r
- return DAT_SUCCESS;\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
- /* Never queued, destroy */\r
- dapls_cm_release(cm_ptr);\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
- dapl_ep_unlink_cm(cm_ptr->ep, cm_ptr);\r
- dapli_cm_free(cm_ptr);\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
- 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
- (ib_gid_handle_t)cm_ptr->msg.saddr.ib.gid) != 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
- 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
- goto bail;\r
- }\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
- /* cleanup and release from local list */\r
- dapli_cm_free(cm_ptr);\r
- \r
- } else\r
-#endif\r
- {\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
- cm_ptr->state = DCM_REJECTED;\r
- dapl_evd_connection_callback(NULL, event, cm_ptr->msg.p_data,\r
- DCM_MAX_PDATA_SIZE, ep_ptr);\r
- dapli_cm_free(cm_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
- int opt = 1;\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
- " setup listen(ia_ptr %p ServiceID %d sp_ptr %p)\n",\r
- ia_ptr, serviceID, sp_ptr);\r
-\r
- cm_ptr = dapli_cm_alloc(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
- setsockopt(cm_ptr->socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));\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_log(DAPL_DBG_TYPE_CM,\r
- " listen: ERROR %s on port %d\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
- " setup listen: port %d cr %p s_fd %d\n",\r
- serviceID + 1000, cm_ptr, cm_ptr->socket);\r
-\r
- return dat_status;\r
-bail:\r
- /* Never queued, destroy here */\r
- dapls_cm_release(cm_ptr);\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 = dapli_cm_alloc(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_cm_release(acm_ptr);\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
- /* mark for destroy, active will see socket close as rej */\r
- dapli_cm_free(acm_ptr);\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
- 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
- (ib_gid_handle_t)cm_ptr->msg.saddr.ib.gid) != 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
- 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
- goto bail;\r
- }\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
- cm_ptr->hca = ia_ptr->hca_ptr;\r
- cm_ptr->state = DCM_ACCEPTED;\r
-\r
- /* Link CM to EP, already queued on work thread */\r
- dapl_ep_link_cm(ep_ptr, cm_ptr);\r
- cm_ptr->ep = ep_ptr;\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
- dapl_ep_unlink_cm(ep_ptr, cm_ptr);\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
-\r
- return DAT_SUCCESS;\r
-bail:\r
- /* schedule cleanup from workq */\r
- dapli_cm_free(cm_ptr);\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
- /* cleanup and release from local list, still on EP list */\r
- dapli_cm_free(cm_ptr);\r
- \r
- } else \r
-#endif\r
- {\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
- cm_ptr->state = DCM_REJECTED;\r
- dapls_cr_callback(cm_ptr, event, NULL, 0, cm_ptr->sp);\r
- dapli_cm_free(cm_ptr);\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 = (DAPL_EP *) ep_handle;\r
- \r
- dapl_dbg_log(DAPL_DBG_TYPE_EP,\r
- " connect(ep_handle %p ....)\n", ep_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
- dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
-\r
- if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED ||\r
- ep_ptr->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC) {\r
- return DAT_SUCCESS;\r
- } \r
- \r
- /* RC. Transition to error state to flush queue */\r
- dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0, 0, 0);\r
-\r
- return (dapli_socket_disconnect(cm_ptr));\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
- if (ib_cm_event == IB_CME_TIMEOUT) {\r
- dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);\r
-\r
- dapl_log(DAPL_DBG_TYPE_WARN,\r
- "dapls_ib_disc_clean: CONN_TIMEOUT ep %p cm %p %s\n",\r
- ep_ptr, cm_ptr, dapl_cm_state_str(cm_ptr->state));\r
- \r
- /* schedule release of socket and local resources */\r
- dapli_cm_free(cm_ptr);\r
- }\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
- /* free cm_srvc_handle, release will cleanup */\r
- if (cm_ptr != NULL) {\r
- /* cr_thread will free */\r
- sp_ptr->cm_srvc_handle = NULL;\r
- dapli_cm_free(cm_ptr);\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
- /* 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
- /* release and cleanup CM object */\r
- dapli_cm_free(cm_ptr);\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 conn;\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
- conn = dapl_get_cm_from_ep((DAPL_EP *) dat_handle);\r
- else if (header->magic == DAPL_MAGIC_CR)\r
- conn = ((DAPL_CR *) dat_handle)->ib_cm_handle;\r
- else\r
- return DAT_INVALID_HANDLE;\r
-\r
- dapl_os_memcpy(remote_ia_address,\r
- &conn->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
-/* 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->local_entry);\r
- dapls_cm_acquire(cr); /* hold thread ref */\r
- dapl_os_lock(&cr->lock);\r
- if (cr->state == DCM_FREE || \r
- hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) {\r
- dapl_log(DAPL_DBG_TYPE_CM, \r
- " CM FREE: %p ep=%p st=%s sck=%d refs=%d\n", \r
- cr, cr->ep, dapl_cm_state_str(cr->state), \r
- cr->socket, cr->ref_count);\r
-\r
- if (cr->socket != DAPL_INVALID_SOCKET) {\r
- shutdown(cr->socket, SHUT_RDWR);\r
- closesocket(cr->socket);\r
- cr->socket = DAPL_INVALID_SOCKET;\r
- }\r
- dapl_os_unlock(&cr->lock);\r
- dapls_cm_release(cr); /* release alloc ref */\r
- dapli_cm_dequeue(cr); /* release workq ref */\r
- dapls_cm_release(cr); /* release thread ref */\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: fd_set ERR 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
- dapls_cm_release(cr); /* release ref */\r
- continue;\r
- }\r
- dapl_os_unlock(&cr->lock);\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_THREAD,\r
- " poll ret=0x%x %s sck=%d\n",\r
- ret, dapl_cm_state_str(cr->state), \r
- 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 && 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
-\r
- dapls_cm_release(cr); /* release ref */\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_THREAD,\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_THREAD, " 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->local_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
+/*
+ * 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"
+
+/* forward declarations */
+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);
+
+#ifdef DAPL_DBG
+/* Check for EP linking to IA and proper connect state */
+void dapli_ep_check(DAPL_EP *ep)
+{
+ DAPL_IA *ia_ptr = ep->header.owner_ia;
+ DAPL_EP *ep_ptr, *next_ep_ptr;
+ int found = 0;
+
+ dapl_os_lock(&ia_ptr->header.lock);
+ ep_ptr = (dapl_llist_is_empty (&ia_ptr->ep_list_head)
+ ? NULL : dapl_llist_peek_head (&ia_ptr->ep_list_head));
+
+ while (ep_ptr != NULL) {
+ next_ep_ptr =
+ dapl_llist_next_entry(&ia_ptr->ep_list_head,
+ &ep_ptr->header.ia_list_entry);
+ if (ep == ep_ptr) {
+ found++;
+ if ((ep->cr_ptr && ep->param.ep_state
+ != DAT_EP_STATE_COMPLETION_PENDING) ||
+ (!ep->cr_ptr && ep->param.ep_state
+ != DAT_EP_STATE_ACTIVE_CONNECTION_PENDING))
+ goto err;
+ else
+ goto match;
+ }
+ ep_ptr = next_ep_ptr;
+ }
+err:
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " dapli_ep_check ERR: %s %s ep=%p state=%d magic=0x%x\n",
+ ep->cr_ptr ? "PASSIVE":"ACTIVE",
+ found ? "WRONG_STATE":"NOT_FOUND" ,
+ ep, ep->param.ep_state, ep->header.magic);
+match:
+ dapl_os_unlock(&ia_ptr->header.lock);
+ return;
+}
+#else
+#define dapli_ep_check(ep)
+#endif
+
+#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)
+{
+ if (cm_ptr->hca)
+ 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--;
+ if (cm_ptr->ref_count) {
+ dapl_os_unlock(&cm_ptr->lock);
+ return;
+ }
+ dapl_os_unlock(&cm_ptr->lock);
+ dapli_cm_dealloc(cm_ptr);
+}
+
+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) {
+ dapli_cm_thread_signal(cm_ptr);
+ 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 */
+ 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) {
+ dapl_os_lock(&cm_ptr->ep->header.lock);
+ dapls_modify_qp_state(cm_ptr->ep->qp_handle, IBV_QPS_ERR, 0,0,0);
+ dapl_os_unlock(&cm_ptr->ep->header.lock);
+ 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 - %s\n",
+ err == -1 ? "POLL" : "SOCKOPT",
+ err == -1 ? strerror(dapl_socket_errno()) : strerror(err),
+ inet_ntoa(((struct sockaddr_in *)
+ &cm_ptr->addr)->sin_addr),
+ ntohs(((struct sockaddr_in *)
+ &cm_ptr->addr)->sin_port),
+ err == ETIMEDOUT ? "RETRYING...":"ABORTING");
+
+ /* retry a timeout */
+ if (err == ETIMEDOUT) {
+ 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;
+ }
+
+ dapl_os_lock(&cm_ptr->lock);
+ cm_ptr->state = DCM_REP_PENDING;
+ dapl_os_unlock(&cm_ptr->lock);
+
+ /* 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))) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " CONN_PENDING len ERR 0x%x %s, wcnt=%d(%d) -> %s\n",
+ err, strerror(err), 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " connect: socket create ERR 0x%x %s\n",
+ err, strerror(err));
+ goto bail;
+ }
+
+ ret = dapl_config_socket(cm_ptr->socket);
+ if (ret < 0) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " connect: config socket %d RET %d ERR 0x%x %s\n",
+ cm_ptr->socket, ret,
+ dapl_socket_errno(), 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) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " connect: dapl_connect_socket RET %d ERR 0x%x %s\n",
+ ret, dapl_socket_errno(),
+ strerror(dapl_socket_errno()));
+ 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)) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " connect getsockname ERROR: 0x%x %s -> %s r_qual %d\n",
+ err, strerror(err),
+ 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 r_qual %d\n",
+ 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_WARN,
+ " CONN_RTU read: sk %d ERR 0x%x, rcnt=%d, v=%d -> %s PORT L-%x R-%x PID L-%x R-%x\n",
+ cm_ptr->socket, err, 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 (err == 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " CONN_RTU read pdata: ERR 0x%x %s, rcnt=%d -> %s\n",
+ err, strerror(err), 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 */
+ dapl_os_lock(&ep_ptr->header.lock);
+ 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));
+ dapl_os_unlock(&ep_ptr->header.lock);
+ 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));
+ dapl_os_unlock(&ep_ptr->header.lock);
+ goto bail;
+ }
+ dapl_os_unlock(&ep_ptr->header.lock);
+ dapl_dbg_log(DAPL_DBG_TYPE_EP, " connect_rtu: send RTU\n");
+
+ /* complete handshake after final QP state change, Just ver+op */
+ dapl_os_lock(&cm_ptr->lock);
+ cm_ptr->state = DCM_CONNECTED;
+ dapl_os_unlock(&cm_ptr->lock);
+
+ cm_ptr->msg.op = ntohs(DCM_RTU);
+ if (send(cm_ptr->socket, (char *)&cm_ptr->msg, 4, 0) == -1) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " CONN_RTU: write ERR = 0x%x %s\n",
+ err, strerror(err));
+ 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
+ {
+ dapli_ep_check(cm_ptr->ep);
+ 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 */
+ dapl_os_lock(&cm_ptr->lock);
+ cm_ptr->state = DCM_REJECTED;
+ dapl_os_unlock(&cm_ptr->lock);
+
+ 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;
+
+ 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " listen: socket create: ERR 0x%x %s\n",
+ err, strerror(err));
+ dat_status = DAT_INSUFFICIENT_RESOURCES;
+ goto bail;
+ }
+
+ setsockopt(cm_ptr->socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));
+ 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)) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_CM,
+ " listen: ERROR 0x%x %s on port %d\n",
+ err, strerror(err), serviceID + 1000);
+ if (err == 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " ACCEPT: ERR 0x%x %s on FD %d l_cr %p\n",
+ err, strerror(err), 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " ACCEPT: NODELAY setsockopt:"
+ " RET %d ERR 0x%x %s\n",
+ ret, err, strerror(err));
+ }
+
+ /* 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " ACCEPT read: ERR 0x%x %s, rcnt=%d, ver=%d\n",
+ err, strerror(err), 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) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " accept read pdata: ERR 0x%x %s, rcnt=%d\n",
+ err, strerror(err), len);
+ goto bail;
+ }
+ p_data = acm_ptr->msg.p_data;
+ }
+ dapl_os_lock(&acm_ptr->lock);
+ acm_ptr->state = DCM_ACCEPTING_DATA;
+ dapl_os_unlock(&acm_ptr->lock);
+
+ 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 */
+ dapl_os_lock(&ep_ptr->header.lock);
+ 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));
+ dapl_os_unlock(&ep_ptr->header.lock);
+ 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));
+ dapl_os_unlock(&ep_ptr->header.lock);
+ goto bail;
+ }
+ dapl_os_unlock(&ep_ptr->header.lock);
+
+ /* 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;
+ dapl_os_lock(&cm_ptr->lock);
+ cm_ptr->state = DCM_ACCEPTED;
+ dapl_os_unlock(&cm_ptr->lock);
+
+ /* Link CM to EP, already queued on work thread */
+ dapl_ep_link_cm(ep_ptr, cm_ptr);
+ cm_ptr->ep = ep_ptr;
+
+ 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)) {
+ int err = dapl_socket_errno();
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " ACCEPT_USR: ERR 0x%x %s, wcnt=%d -> %s\n",
+ err, strerror(err), len,
+ inet_ntoa(((struct sockaddr_in *)
+ &cm_ptr->msg.daddr.so)->sin_addr));
+ dapl_ep_unlink_cm(ep_ptr, cm_ptr);
+ cm_ptr->ep = NULL;
+ 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");
+
+ 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 */
+ dapl_os_lock(&cm_ptr->lock);
+ cm_ptr->state = DCM_CONNECTED;
+ dapl_os_unlock(&cm_ptr->lock);
+
+ /* 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
+ {
+ dapli_ep_check(cm_ptr->ep);
+ 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
+ dapl_os_lock(&cm_ptr->lock);
+ cm_ptr->state = DCM_REJECTED;
+ dapl_os_unlock(&cm_ptr->lock);
+
+ 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);
+
+ dapl_os_lock(&ep_ptr->header.lock);
+ if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED ||
+ ep_ptr->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC ||
+ cm_ptr == NULL) {
+ dapl_os_unlock(&ep_ptr->header.lock);
+ return DAT_SUCCESS;
+ }
+ dapl_os_unlock(&ep_ptr->header.lock);
+ 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;
+
+ if ((cm_ptr = dapl_get_cm_from_ep(ep_ptr)) == NULL)
+ return;
+
+ 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 */
+ dapl_os_lock(&cr->lock);
+ 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:
+ dapl_os_unlock(&cr->lock);
+ dapli_socket_accept(cr);
+ break;
+ case DCM_ACCEPTING:
+ dapl_os_unlock(&cr->lock);
+ dapli_socket_accept_data(cr);
+ break;
+ case DCM_ACCEPTED:
+ dapl_os_unlock(&cr->lock);
+ dapli_socket_accept_rtu(cr);
+ break;
+ case DCM_REP_PENDING:
+ dapl_os_unlock(&cr->lock);
+ dapli_socket_connect_rtu(cr);
+ break;
+ case DCM_CONNECTED:
+ dapl_os_unlock(&cr->lock);
+ dapli_socket_disconnect(cr);
+ break;
+ default:
+ dapl_os_unlock(&cr->lock);
+ break;
+ }
+ } else
+ dapl_os_unlock(&cr->lock);
+
+ /* ASYNC connections, writable, readable, error; check status */
+ } else if (ret == DAPL_FD_WRITE ||
+ (cr->state == DCM_CONN_PENDING &&
+ ret == DAPL_FD_ERROR)) {
+
+ opt = 0;
+ opt_len = sizeof(opt);
+ ret = getsockopt(cr->socket, SOL_SOCKET,
+ SO_ERROR, (char *)&opt,
+ &opt_len);
+ dapl_os_unlock(&cr->lock);
+ if (!ret && !opt)
+ dapli_socket_connected(cr, opt);
+ else
+ dapli_socket_connected(cr, opt ? opt : dapl_socket_errno());
+ } else
+ dapl_os_unlock(&cr->lock);
+
+ 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
uint8_t mtu;
DAT_NAMED_ATTR named_attr;
DAPL_SOCKET scm[2];
+ uint8_t sl;
+ uint16_t pkey;
+ int pkey_idx;
+
} ib_hca_transport_t;
/* prototypes */
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;
* 0 success, -1 error
*
*/
+DAT_UINT32 g_parent = 0;
int32_t dapls_ib_init(void)
{
+ g_parent = dapl_os_getpid();
+
/* initialize hca_list */
dapl_os_lock_init(&g_hca_lock);
dapl_llist_init_head(&g_hca_list);
int32_t dapls_ib_release(void)
{
+ /* only parent init will cleanup */
+ if (dapl_os_getpid() != g_parent)
+ return 0;
+
dapli_ib_thread_destroy();
dapls_os_release();
return 0;
" 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,
+ dat_status = getlocalipaddr((char *)&hca_ptr->hca_address,
sizeof(DAT_SOCK_ADDR6));
if (dat_status != DAT_SUCCESS)
return dat_status;
$(SDK_LIB_PATH)\ws2_32.lib \\r
!if $(FREEBUILD)\r
$(TARGETPATH)\*\dat2.lib \\r
+ $(TARGETPATH)\*\winverbs.lib \\r
$(TARGETPATH)\*\libibverbs.lib\r
!else\r
$(TARGETPATH)\*\dat2d.lib \\r
+ $(TARGETPATH)\*\winverbsd.lib \\r
$(TARGETPATH)\*\libibverbsd.lib\r
!endif\r
\r
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]:"
+ " CM_REQ retry %d %p [lid, port, qpn]:"
" %x %x %x -> %x %x %x Time(ms) %llu > %llu\n",
- cm->retries, ntohs(cm->msg.saddr.ib.lid),
+ cm, 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.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",
+ " %x %x %x -> %x %x %x r_pid %x (%x) Time(ms) %llu > %llu\n",
cm->retries,
ntohs(cm->msg.saddr.ib.lid),
ntohs(cm->msg.sport),
(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",
+ " %x %x %x -> %x %x %x r_pid %x (%x) Time(ms) %llu > %llu\n",
cm->retries,
ntohs(cm->msg.saddr.ib.lid),
ntohs(cm->msg.sport),
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",
+ " CM reject -> LID %x, QPN %x PORT %x\n",
ntohs(smsg.daddr.ib.lid),
ntohl(smsg.dqpn), ntohs(smsg.dport));
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",
+ " %x %x %x -> %x %x %x\n",
dapl_cm_op_str(ntohs(msg->op)),
dapl_cm_state_str(cm->state),
ntohs(msg->saddr.ib.lid),
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",
+ " %x %x %x -> %x %x %x\n",
dapl_cm_op_str(ntohs(msg->op)),
dapl_cm_state_str(cm->state),
ntohs(msg->saddr.ib.lid),
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) {
+ } else if (ntohs(msg->op) != DCM_DREP){
+ /* DREP ok to ignore, any other print warning */
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),
+ " ucm_recv: UNEXPECTED MSG on cm %p"
+ " <- op %s, st %s spsp %x sqpn %x\n",
+ cm, dapl_cm_op_str(ntohs(msg->op)),
+ dapl_cm_state_str(cm->state),
ntohs(msg->sport), ntohl(msg->sqpn));
}
dapl_os_unlock(&cm->lock);
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),
+ " <- op %s, %s spsp %x sqpn %x\n",
+ dapl_cm_op_str(ntohs(msg->op)),
+ dapl_cm_state_str(cm->state),
ntohs(msg->sport), ntohl(msg->sqpn));
dapl_os_unlock(&cm->lock);
break;
/* 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",
+ " DUPLICATE: cm %p op %s st %s [lid, port, qpn]:"
+ " %x %x %x <- %x %x %x\n", cm,
dapl_cm_op_str(ntohs(msg->op)),
dapl_cm_state_str(cm->state),
ntohs(msg->daddr.ib.lid),
ntohs(msg->saddr.ib.lid),
ntohs(msg->sport),
ntohl(msg->saddr.ib.qpn));
+
return NULL;
}
}
}
/* not match on listenq for valid request, send reject */
- if (ntohs(msg->op) == DCM_REQ && !found)
+ if (ntohs(msg->op) == DCM_REQ && !found) {
+ dapl_log(DAPL_DBG_TYPE_WARN,
+ " ucm_recv: NO LISTENER for %s %x %x i%x c%x"
+ " < %x %x %x, sending reject\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));
+
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",
+ " ucm_recv: NO MATCH op %s %x %x i%x c%x"
+ " < %x %x %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),
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),
+ " ucm_send: op %s ln %d lid %x c_qpn %x rport %s\n",
+ dapl_cm_op_str(ntohs(smsg->op)),
+ sge.length, htons(smsg->daddr.ib.lid),
htonl(smsg->dqpn), htons(smsg->dport));
/* empty slot, then create AH */
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
+ cm->ref_count--;
+ if (cm->ref_count) {
+ dapl_os_unlock(&cm->lock);
+ return;
+ }
/* 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
- dapli_cm_dealloc(cm);\r
+ }
+ dapl_os_unlock(&cm->lock);
+ dapli_cm_dealloc(cm);
}
dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep)
/* schedule destruction of CM object */
void dapli_cm_free(dp_ib_cm_handle_t cm)
{
+ dapl_log(DAPL_DBG_TYPE_CM,
+ " dapli_cm_free: cm %p %s ep %p refs=%d\n",
+ cm, dapl_cm_state_str(cm->state),
+ cm->ep, cm->ref_count);
+
dapl_os_lock(&cm->lock);
cm->state = DCM_FREE;
dapls_thread_signal(&cm->hca->ib_trans.signal);
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",
+ " dapl_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;
+ if (cm->state != DCM_FREE)
+ cm->state = DCM_FREE;
+
while (cm->ref_count != 1) {
dapl_os_unlock(&cm->lock);
+ dapls_thread_signal(&cm->hca->ib_trans.signal);
dapl_os_sleep_usec(10000);
dapl_os_lock(&cm->lock);
}
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);
}
/*
DAT_RETURN dapli_cm_disconnect(dp_ib_cm_handle_t cm)
{
int finalize = 1;
+ int wakeup = 0;
dapl_os_lock(&cm->lock);
switch (cm->state) {
/* 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);
+ finalize = 0; /* wait for DREP, wakeup timer after DREQ sent */
+ wakeup = 1;
break;
case DCM_DISC_PENDING:
/* DREQ timeout, resend until retries exhausted */
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",
+ " %x %x %x -> %x %x %x\n",
htons(cm->msg.saddr.ib.lid),
htonl(cm->msg.saddr.ib.qpn),
htons(cm->msg.sport),
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 */
+ /* DREQ received, send DREP and schedule event, finalize */
cm->msg.op = htons(DCM_DREP);
break;
+ case DCM_DISCONNECTED:
+ dapl_os_unlock(&cm->lock);
+ return DAT_SUCCESS;
default:
+ dapl_log(DAPL_DBG_TYPE_WARN,
+ " disconnect UNKNOWN state: ep %p cm %p %s %s"
+ " %x %x %x %s %x %x %x r_pid %x (%x)\n",
+ 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));
+
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 (wakeup)
+ dapls_thread_signal(&cm->hca->ib_trans.signal);
if (finalize)
ucm_disconnect_final(cm);
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",
+ " connect: lid %x i_qpn %x lport %x p_sz=%d -> "
+ " lid %x c_qpn %x rport %x\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),
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",
+ " 0x%x %x 0x%x -> 0x%x %x 0x%x\n",
htons(cm->msg.saddr.ib.lid),
htonl(cm->msg.saddr.ib.qpn),
htons(cm->msg.sport),
bail:
dapl_log(DAPL_DBG_TYPE_WARN,
- " connect: ERR %s -> cm_lid %d cm_qpn %d r_psp %d p_sz=%d\n",
+ " connect: ERR %s -> cm_lid %x cm_qpn %x r_psp %x 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));
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),
+ " op %s, st %s <- lid %x sqpn %x sport %x\n",
+ dapl_cm_op_str(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);
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",
+ " st %s <- lid %x sqpn %x spsp %x\n",
ntohs(msg->p_size),
dapl_cm_state_str(cm->state),
ntohs(msg->saddr.ib.lid),
dapl_dbg_log(DAPL_DBG_TYPE_CM,
" CONN_RTU: DST lid=%x,"
- " iqp=%x, qp_type=%d, port=%d psize=%d\n",
+ " iqp=%x, qp_type=%d, port=%x 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));
event = IB_CME_DESTINATION_REJECT;
if (event != IB_CME_CONNECTED) {
+ dapl_log(DAPL_DBG_TYPE_CM,
+ " ACTIVE: CM_REQ REJECTED:"
+ " cm %p op %s, st %s dlid %x iqp %x port %x <-"
+ " slid %x iqp %x port %x\n", cm,
+ dapl_cm_op_str(ntohs(msg->op)),
+ dapl_cm_state_str(cm->state),
+ ntohs(msg->daddr.ib.lid), ntohl(msg->daddr.ib.qpn),
+ ntohs(msg->dport), ntohs(msg->saddr.ib.lid),
+ ntohl(msg->saddr.ib.qpn), ntohs(msg->sport));
+
cm->state = DCM_REJECTED;
dapl_os_unlock(&cm->lock);
&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",
+ " ACTIVE: UD xevent ah %p qpn %x lid %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"
(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
{
/* dest CM info from CR msg, source CM info from listen */
acm->sp = cm->sp;
acm->hca = cm->hca;
+ acm->msg.op = msg->op;
acm->msg.dport = msg->sport;
acm->msg.dqpn = msg->sqpn;
acm->msg.sport = cm->msg.sport;
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",
+ " accept: DST port=%x 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));
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),
+ " op %s, st %s <- lid %x iqp %x sport %x\n",
+ dapl_cm_op_str(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);
&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",
+ " PASSIVE: UD xevent ah %p qpn %x lid %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"
(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);
{
dapl_os_lock(&cm->lock);
if (cm->state != DCM_RTU_PENDING) {
+ dapl_log(DAPL_DBG_TYPE_ERR,
+ " CM_REPLY: wrong state %s",
+ dapl_cm_state_str(cm->state));
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",
+ " CM_REPLY: RETRIES EXHAUSTED (lid port qpn)"
+ " %x %x %x -> %x %x %x\n",
htons(cm->msg.saddr.ib.lid),
htons(cm->msg.sport),
htonl(cm->msg.saddr.ib.qpn),
dapl_os_unlock(&cm->lock);
return DAT_INVALID_STATE;
}
+ dapl_os_unlock(&cm->lock);
dapl_dbg_log(DAPL_DBG_TYPE_CM,
" ACCEPT_USR: remote lid=%x"
#endif
/* modify QP to RTR and then to RTS with remote info already read */
+ dapl_os_lock(&ep->header.lock);
if (dapls_modify_qp_state(ep->qp_handle,
IBV_QPS_RTR,
cm->msg.daddr.ib.qpn,
" 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);
+ dapl_os_unlock(&ep->header.lock);
goto bail;
}
if (dapls_modify_qp_state(ep->qp_handle,
" 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);
+ dapl_os_unlock(&ep->header.lock);
goto bail;
}
+ dapl_os_unlock(&ep->header.lock);
/* save remote address information */
dapl_os_memcpy(&ep->remote_ia_address,
dapl_ep_link_cm(ep, cm);
cm->ep = ep;
cm->hca = ia->hca_ptr;
- cm->state = DCM_RTU_PENDING;
+
+ dapl_os_lock(&cm->lock);
dapl_os_get_time(&cm->timer); /* RTU expected */
+ cm->state = DCM_RTU_PENDING;
dapl_os_unlock(&cm->lock);
if (ucm_reply(cm)) {
- dapl_ep_link_cm(ep, cm);
+ dapl_ep_unlink_cm(ep, cm);
goto bail;
}
dapl_dbg_log(DAPL_DBG_TYPE_CM, " PASSIVE: accepted!\n");
{
dp_ib_cm_handle_t cm_ptr = dapl_get_cm_from_ep(ep_ptr);
+ dapl_os_lock(&ep_ptr->header.lock);
if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED ||
- ep_ptr->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC) {
+ ep_ptr->param.ep_attr.service_type != DAT_SERVICE_TYPE_RC ||
+ cm_ptr == NULL) {
+ dapl_os_unlock(&ep_ptr->header.lock);
return DAT_SUCCESS;
}
+ dapl_os_unlock(&ep_ptr->header.lock);
- /* RC. Transition to error state to flush queue */
- dapls_modify_qp_state(ep_ptr->qp_handle, IBV_QPS_ERR, 0, 0, 0);
+ dapli_cm_disconnect(cm_ptr);
+
+ /* ABRUPT close, wait for callback and DISCONNECTED state */
+ if (close_flags == DAT_CLOSE_ABRUPT_FLAG) {
+ dapl_os_lock(&ep_ptr->header.lock);
+ while (ep_ptr->param.ep_state != DAT_EP_STATE_DISCONNECTED) {
+ dapl_os_unlock(&ep_ptr->header.lock);
+ dapl_os_sleep_usec(10000);
+ dapl_os_lock(&ep_ptr->header.lock);
+ }
+ dapl_os_unlock(&ep_ptr->header.lock);
+ }
- return (dapli_cm_disconnect(cm_ptr));
+ return DAT_SUCCESS;
}
/*
IN DAT_BOOLEAN active,
IN const ib_cm_events_t ib_cm_event)
{
- /* nothing to cleanup */
+ if (ib_cm_event == IB_CME_TIMEOUT) {
+ dp_ib_cm_handle_t cm_ptr;
+
+ if ((cm_ptr = dapl_get_cm_from_ep(ep)) == NULL)
+ return;
+
+ dapl_log(DAPL_DBG_TYPE_WARN,
+ "dapls_ib_disc_clean: CONN_TIMEOUT ep %p cm %p %s\n",
+ ep, cm_ptr, dapl_cm_state_str(cm_ptr->state));
+
+ /* schedule release of socket and local resources */
+ dapli_cm_free(cm_ptr);
+ }
}
/*
ib_cm_srvc_handle_t cm = NULL;
dapl_dbg_log(DAPL_DBG_TYPE_EP,
- " listen(ia %p ServiceID %d sp %p)\n",
+ " listen(ia %p ServiceID %x 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",
+ " listen: ERROR %s on conn_qual %x\n",
strerror(errno), sid);
return DAT_CONN_QUAL_IN_USE;
}
/* 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",
+ " remove_listener(ia %p sp %p cm %p psp=%x)\n",
ia, sp, cm, ntohs(cm->msg.dport));
sp->cm_srvc_handle = NULL;
dapli_dequeue_listen(cm);
+ ucm_free_port(&cm->hca->ib_trans, ntohs(cm->msg.sport));
dapls_cm_release(cm); /* last ref, dealloc */
}
return DAT_SUCCESS;
/* cr_thread will destroy CR, update saddr lid, gid, qp_type info */
dapl_os_lock(&cm->lock);
+ dapl_log(DAPL_DBG_TYPE_CM,
+ " PASSIVE: REJECTING CM_REQ:"
+ " cm %p op %s, st %s slid %x iqp %x port %x ->"
+ " dlid %x iqp %x port %x\n", cm,
+ dapl_cm_op_str(ntohs(cm->msg.op)),
+ dapl_cm_state_str(cm->state),
+ ntohs(cm->hca->ib_trans.addr.ib.lid),
+ ntohl(cm->msg.saddr.ib.qpn),
+ ntohs(cm->msg.sport), ntohs(cm->msg.daddr.ib.lid),
+ ntohl(cm->msg.daddr.ib.qpn), ntohs(cm->msg.dport));
+
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;
#endif
#ifdef DAPL_COUNTERS
+static char _ctr_host_[128];
/* Debug aid: List all Connections in process and state */
void dapls_print_cm_list(IN DAPL_IA *ia_ptr)
{
else
next_cm = NULL;
- printf("\n DAPL IA LISTEN/CONNECTIONS IN PROCESS:\n");
+ gethostname(_ctr_host_, sizeof(_ctr_host_));
+ printf("\n [%s:%x] DAPL IA LISTEN/CONNECTIONS IN PROCESS:\n",
+ _ctr_host_ , dapl_os_getpid());
+
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",
+ printf( " LISTEN[%d]: sp %p %s uCM_QP: %x %x %x l_pid %x (%x)\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),
(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",
+ " %x %x %x %s %x %x %x r_pid %x (%x)\n",
i, cm->ep, cm,
cm->msg.saddr.ib.qp_type == IBV_QPT_RC ? "RC" : "UD",
dapl_cm_state_str(cm->state),
struct ibv_ah **ah;
DAPL_OS_LOCK plock;
uint8_t *sid; /* Sevice IDs, port space, bitarray? */
+ uint8_t sl;
+ uint16_t pkey;
+ int pkey_idx;
} ib_hca_transport_t;
static int ucm_service_create(IN DAPL_HCA *hca);
#if defined (_WIN32)
-#include "..\..\..\..\..\etc\user\comp_channel.cpp"
#include <rdma\winverbs.h>
static int32_t create_os_signal(IN DAPL_HCA * hca_ptr)
{
- return CompSetInit(&hca_ptr->ib_trans.signal.set);\r
+ return CompSetInit(&hca_ptr->ib_trans.signal.set);
}
static void destroy_os_signal(IN DAPL_HCA * hca_ptr)
{
- CompSetCleanup(&hca_ptr->ib_trans.signal.set);\r
+ CompSetCleanup(&hca_ptr->ib_trans.signal.set);
}
static int dapls_config_verbs(struct ibv_context *verbs)
goto bail;
}
- /* if the LMR context is already in the hash table */
- dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, NULL);
- if (dat_status == DAT_SUCCESS) {
- (void)dapls_ib_mr_deregister(lmr);
- dapl_lmr_dealloc(lmr);
-
- dat_status =
- DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_LMR_IN_USE);
- goto bail;
- }
-
- dat_status = dapls_hash_insert(ia->hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, lmr);
- if (dat_status != DAT_SUCCESS) {
- (void)dapls_ib_mr_deregister(lmr);
- dapl_lmr_dealloc(lmr);
-
- /* The value returned by dapls_hash_insert(.) is not */
- /* returned to the consumer because the spec. requires */
- /* that dat_lmr_create(.) return only certain values. */
- dat_status =
- DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
- goto bail;
- }
-
dapl_os_atomic_inc(&pz->pz_ref_count);
*lmr_handle = (DAT_LMR_HANDLE) lmr;
DAPL_LMR *lmr;
DAT_REGION_DESCRIPTION reg_desc;
DAT_RETURN dat_status;
- DAPL_HASH_DATA hash_lmr;
dapl_dbg_log(DAPL_DBG_TYPE_API,
"dapl_lmr_create_lmr (%p, %p, %p, %x, %x, %p, %p, %p, %p)\n",
lmr_handle,
lmr_context, registered_length, registered_address);
- dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table,
- original_lmr->param.lmr_context,
- &hash_lmr);
- if (dat_status != DAT_SUCCESS) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2);
- goto bail;
- }
- lmr = (DAPL_LMR *) hash_lmr;
reg_desc.for_lmr_handle = (DAT_LMR_HANDLE) original_lmr;
lmr = dapl_lmr_alloc(ia,
goto bail;
}
- /* if the LMR context is already in the hash table */
- dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, NULL);
- if (dat_status == DAT_SUCCESS) {
- dapls_ib_mr_deregister(lmr);
- dapl_lmr_dealloc(lmr);
-
- dat_status =
- DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_LMR_IN_USE);
- goto bail;
- }
-
- dat_status = dapls_hash_insert(ia->hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, lmr);
- if (dat_status != DAT_SUCCESS) {
- dapls_ib_mr_deregister(lmr);
- dapl_lmr_dealloc(lmr);
-
- /* The value returned by dapls_hash_insert(.) is not */
- /* returned to the consumer because the spec. requires */
- /* that dat_lmr_create(.) return only certain values. */
- dat_status =
- DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
- goto bail;
- }
-
dapl_os_atomic_inc(&pz->pz_ref_count);
*lmr_handle = (DAT_LMR_HANDLE) lmr;
goto bail;
}
- /* if the LMR context is already in the hash table */
- dat_status = dapls_hash_search(ia->hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, NULL);
- if (DAT_SUCCESS == dat_status) {
- (void)dapls_ib_mr_deregister(lmr);
- dapl_lmr_dealloc(lmr);
-
- dat_status =
- DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_LMR_IN_USE);
- goto bail;
- }
-
- dat_status = dapls_hash_insert(ia->hca_ptr->lmr_hash_table,
- lmr->param.lmr_context, lmr);
- if (dat_status != DAT_SUCCESS) {
- (void)dapls_ib_mr_deregister(lmr);
- dapl_lmr_dealloc(lmr);
-
- /* The value returned by dapls_hash_insert(.) is not */
- /* returned to the consumer because the spec. requires */
- /* that dat_lmr_create(.) return only certain values. */
- dat_status =
- DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
- goto bail;
- }
-
dapl_os_atomic_inc(&pz->pz_ref_count);
*lmr_handle = (DAT_LMR_HANDLE) lmr;
- ia params, IA specific parameters - device name and port
- platform params, (not used)
.PP
-.SH Example netdev entries for OpenFabrics rdma_cm providers, both v1.2 and v2.0
+.SH OpenFabrics RDMA providers:
\br
+ Provider options for both 1.2 and 2.0, each using different CM services
+
+ 1. cma - OpenFabrics rdma_cm - uses rdma_cm services for connections
+ - requires IPoIB and SA/SM services for IB
+ - netdev used for device name, without port designation (ia_params)
+ - Supports any transport rdma_cm supports including IB, iWARP, RoCEE
+ - libdaplcma.so (1.2), libdaplofa (2.0)
+
+ 2. scm - uDAPL socket based CM - exchanges CM information over sockets
+ - eliminates the need for rdma_cm, IPoIB, and SA for IB
+ - verbs device used for device name with port designation (ia_param)
+ - Supports IB, RoCEE. Doesn't support iWARP
+ - libdaplscm.so (1.2), libdaploscm (2.0)
+
+ 3. ucm - uDAPL unreliable IB CM - exchanges CM information via IB UD QP's
+ - eliminates the need for sockets or rdma_cm
+ - verbs device used for device name with port designation (ia_param)
+ - Supports IB only, no name service.
+ - libdaplucm.so (1.2), libdaploucm (2.0)
+.PP
+.SH Example entries for each OpenFabrics provider
+\br
+
+ 1. cma - OpenFarbrics rdma_cm (v1.2 and v2.0 examples)
+
OpenIB-cma u1.2 nonthreadsafe default libdaplcma.so.1 dapl.1.2 "ib0 0" ""
ofa-v2-ib0 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 "ib0 0" ""
+ ofa-v2-iwarp u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 "eth2 0" ""
+ ofa-v2-cma-roe-eth2 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 "eth2 0" ""
+ ofa-v2-cma-roe-eth3 u2.0 nonthreadsafe default libdaplofa.so.2 dapl.2.0 "eth3 0" ""
- NOTE: The OpenFabrics providers use <ia_params> to specify the device with one of the following:
+ NOTE: The OpenFabrics CMA providers use <ia_params> to specify the device with one of the following:
network address, network hostname, or netdev name; along with port number.
- The OpenIB- and ofa-v2- IA names are unique mappings. Reserved for OpenFabrics providers.
+ 2. scm - uDAPL socket based CM (v1.2 and v2.0 examples)
+
+ OpenIB-mlx4_0-1 u1.2 nonthreadsafe default libdaplscm.so.1 dapl.1.2 "mlx4_0 1" ""
+ OpenIB-ipath0-1 u1.2 nonthreadsafe default libdaplscm.so.1 dapl.1.2 "ipath0 1" ""
+ ofa-v2-mlx4_0-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "mlx4_0 1" ""
+ ofa-v2-mlx4_0-2 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "mlx4_0 2" ""
+ ofa-v2-mlx4_1-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "mlx4_1 1" ""
+ ofa-v2-ehca0-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "ehca0 1" ""
+ ofa-v2-scm-roe-mlx4_0-1 u2.0 nonthreadsafe default libdaploscm.so.2 dapl.2.0 "mlx4_0 1" ""
+
+ 3. ucm - uDAPL unreliable IB CM (not supported in 1.2, v2.0 examples)
+
+ ofa-v2-mlx4_0-1u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 "mlx4_0 1" ""
+ ofa-v2-mlx4_0-2u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 "mlx4_0 2" ""
+ ofa-v2-ipath0-1u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 "ipath0 1" ""
+ ofa-v2-ehca0-1u u2.0 nonthreadsafe default libdaploucm.so.2 dapl.2.0 "ehca0 1" ""
+
+ Note: OpenIB- and ofa-v2- IA names are unique mappings, reserved for OpenFabrics providers.
+.PP
+The default location for this configuration file is /etc/dat.conf.
.PP
-The default location for this configuration file is /etc/dat.conf.
The file location may be overridden with the environment variable DAT_OVERRIDE=/your_own_directory/your_dat.conf.
.PP
-.SH "SEE ALSO"
+.SH "SEE ALSO" rdma_cm verbs socket
.PP
struct started_server
{
- char devicename[80];
+ char devicename[256];
struct started_server *next;
};