-/*
- * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- * in the file LICENSE.txt in the root directory. The license is also
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is in the file
- * LICENSE2.txt in the root directory. The license is also available from
- * the Open Source Initiative, see
- * http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- * copy of which is in the file LICENSE3.txt in the root directory. The
- * license is also available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/**********************************************************************
- *
- * HEADER: dapl_adapter_util.h
- *
- * PURPOSE: Utility defs & routines for the adapter data structure
- *
- * $Id: dapl_adapter_util.h 1317 2005-04-25 17:29:42Z jlentini $
- *
- **********************************************************************/
-
-#ifndef _DAPL_ADAPTER_UTIL_H_
-#define _DAPL_ADAPTER_UTIL_H_
-
-
-typedef enum async_handler_type
-{
- DAPL_ASYNC_UNAFILIATED,
- DAPL_ASYNC_CQ_ERROR,
- DAPL_ASYNC_CQ_COMPLETION,
- DAPL_ASYNC_QP_ERROR
-} DAPL_ASYNC_HANDLER_TYPE;
-
-
-int dapls_ib_init (void);
-
-int dapls_ib_release (void);
-
-DAT_RETURN dapls_ib_enum_hcas (
- IN const char *vendor,
- OUT DAPL_HCA_NAME **hca_names,
- OUT DAT_COUNT *total_hca_count);
-
-DAT_RETURN dapls_ib_get_instance_data(
- IN DAPL_HCA_NAME hca_name,
- OUT char *instance);
-
-DAT_RETURN dapls_ib_open_hca (
- IN char *namestr,
- IN DAPL_HCA *hca_ptr);
-
-DAT_RETURN dapls_ib_close_hca (
- IN DAPL_HCA *hca_ptr);
-
-DAT_RETURN dapls_ib_qp_alloc (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EP *ep_ptr,
- IN DAPL_EP *ep_ctx_ptr);
-
-DAT_RETURN dapls_ib_qp_free (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EP *ep_ptr);
-
-DAT_RETURN dapls_ib_qp_modify (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EP *ep_ptr,
- IN DAT_EP_ATTR *ep_attr);
-
-DAT_RETURN dapls_ib_connect (
- IN DAT_EP_HANDLE ep_handle,
- IN DAT_IA_ADDRESS_PTR remote_ia_address,
- IN DAT_CONN_QUAL remote_conn_qual,
- IN DAT_COUNT private_data_size,
- IN DAT_PVOID private_data);
-
-DAT_RETURN dapls_ib_disconnect (
- IN DAPL_EP *ep_ptr,
- IN DAT_CLOSE_FLAGS close_flags);
-
-DAT_RETURN dapls_ib_setup_conn_listener (
- IN DAPL_IA *ia_ptr,
- IN DAT_UINT64 ServiceID,
- IN DAPL_SP *sp_ptr);
-
-DAT_RETURN dapls_ib_remove_conn_listener (
- IN DAPL_IA *ia_ptr,
- IN DAPL_SP *sp_ptr);
-
-DAT_RETURN dapls_ib_accept_connection (
- IN DAT_CR_HANDLE cr_handle,
- IN DAT_EP_HANDLE ep_handle,
- IN DAT_COUNT private_data_size,
- IN const DAT_PVOID private_data);
-
-DAT_RETURN dapls_ib_reject_connection (
- IN dp_ib_cm_handle_t cm_handle,
- IN int reject_reason,
- IN DAT_COUNT private_data_size,
- IN const DAT_PVOID private_data);
-
-DAT_RETURN dapls_ib_setup_async_callback (
- IN DAPL_IA *ia_ptr,
- IN DAPL_ASYNC_HANDLER_TYPE handler_type,
- IN DAPL_EVD *evd_ptr,
- IN ib_async_handler_t callback,
- IN void *context);
-
-DAT_RETURN dapls_ib_cq_alloc (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr,
- IN DAT_COUNT *cqlen);
-
-DAT_RETURN dapls_ib_cq_free (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr);
-
-DAT_RETURN dapls_set_cq_notify (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr);
-
-DAT_RETURN dapls_ib_cq_resize (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr,
- IN DAT_COUNT *cqlen);
-
-DAT_RETURN dapls_ib_pd_alloc (
- IN DAPL_IA *ia_ptr,
- IN DAPL_PZ *pz);
-
-DAT_RETURN dapls_ib_pd_free (
- IN DAPL_PZ *pz);
-
-DAT_RETURN dapls_ib_mr_register (
- IN DAPL_IA *ia_ptr,
- IN DAPL_LMR *lmr,
- IN DAT_PVOID virt_addr,
- IN DAT_VLEN length,
- IN DAT_MEM_PRIV_FLAGS privileges,
- IN DAT_VA_TYPE va_type);
-
-#if defined(__KDAPL__)
-DAT_RETURN dapls_ib_mr_register_physical (
- IN DAPL_IA *ia_ptr,
- INOUT DAPL_LMR *lmr,
- IN DAT_PADDR phys_addr,
- IN DAT_VLEN length,
- IN DAT_MEM_PRIV_FLAGS privileges);
-#endif /* __KDAPL__ */
-
-DAT_RETURN dapls_ib_mr_deregister (
- IN DAPL_LMR *lmr);
-
-DAT_RETURN dapls_ib_mr_register_shared (
- IN DAPL_IA *ia_ptr,
- IN DAPL_LMR *lmr,
- IN DAT_MEM_PRIV_FLAGS privileges,
- IN DAT_VA_TYPE va_type);
-
-DAT_RETURN dapls_ib_mw_alloc (
- IN DAPL_RMR *rmr);
-
-DAT_RETURN dapls_ib_mw_free (
- IN DAPL_RMR *rmr);
-
-DAT_RETURN dapls_ib_mw_bind (
- IN DAPL_RMR *rmr,
- IN DAPL_LMR *lmr,
- IN DAPL_EP *ep,
- IN DAPL_COOKIE *cookie,
- IN DAT_VADDR virtual_address,
- IN DAT_VLEN length,
- IN DAT_MEM_PRIV_FLAGS mem_priv,
- IN DAT_BOOLEAN is_signaled);
-
-DAT_RETURN dapls_ib_mw_unbind (
- IN DAPL_RMR *rmr,
- IN DAPL_EP *ep,
- IN DAPL_COOKIE *cookie,
- IN DAT_BOOLEAN is_signaled);
-
-DAT_RETURN dapls_ib_query_hca (
- IN DAPL_HCA *hca_ptr,
- OUT DAT_IA_ATTR *ia_attr,
- OUT DAT_EP_ATTR *ep_attr,
- OUT DAT_SOCK_ADDR6 *ip_addr);
-
-DAT_RETURN dapls_ib_completion_poll (
- IN DAPL_HCA *hca_ptr,
- IN DAPL_EVD *evd_ptr,
- IN ib_work_completion_t *cqe_ptr);
-
-DAT_RETURN dapls_ib_completion_notify (
- IN ib_hca_handle_t hca_handle,
- IN DAPL_EVD *evd_ptr,
- IN ib_notification_type_t type);
-
-DAT_DTO_COMPLETION_STATUS dapls_ib_get_dto_status (
- IN ib_work_completion_t *cqe_ptr);
-
-void dapls_ib_reinit_ep (
- IN DAPL_EP *ep_ptr);
-
-void dapls_ib_disconnect_clean (
- IN DAPL_EP *ep_ptr,
- IN DAT_BOOLEAN passive,
- IN const ib_cm_events_t ib_cm_event);
-
-DAT_RETURN dapls_ib_get_async_event (
- IN ib_error_record_t *cause_ptr,
- OUT DAT_EVENT_NUMBER *async_event);
-
-DAT_EVENT_NUMBER dapls_ib_get_dat_event (
- IN const ib_cm_events_t ib_cm_event,
- IN DAT_BOOLEAN active);
-
-ib_cm_events_t dapls_ib_get_cm_event (
- IN DAT_EVENT_NUMBER dat_event_num);
-
-DAT_RETURN dapls_ib_cm_remote_addr (
- IN DAT_HANDLE dat_handle,
- OUT DAT_SOCK_ADDR6 *remote_ia_address);
-
-int dapls_ib_private_data_size (
- IN DAPL_PRIVATE *prd_ptr,
- IN DAPL_PDATA_OP conn_op,
- IN DAPL_HCA *hca_ptr);
-
-void
-dapls_query_provider_specific_attr(
- IN DAPL_IA *ia_ptr,
- IN DAT_PROVIDER_ATTR *attr_ptr );
-
-#ifdef CQ_WAIT_OBJECT
-DAT_RETURN
-dapls_ib_wait_object_create (
- IN DAPL_EVD *evd_ptr,
- IN ib_wait_obj_handle_t *p_cq_wait_obj_handle);
-
-DAT_RETURN
-dapls_ib_wait_object_destroy (
- IN ib_wait_obj_handle_t cq_wait_obj_handle);
-
-DAT_RETURN
-dapls_ib_wait_object_wakeup (
- IN ib_wait_obj_handle_t cq_wait_obj_handle);
-
-DAT_RETURN
-dapls_ib_wait_object_wait (
- IN ib_wait_obj_handle_t cq_wait_obj_handle,
- IN uint32_t timeout);
-#endif
-
-#ifdef DAT_EXTENSIONS
-void
-dapls_cqe_to_event_extension(
- IN DAPL_EP *ep_ptr,
- IN DAPL_COOKIE *cookie,
- IN ib_work_completion_t *cqe_ptr,
- IN DAT_EVENT *event_ptr);
-#endif
-
-/*
- * Values for provider DAT_NAMED_ATTR
- */
-#define IB_QP_STATE 1 /* QP state change request */
-
-
-#ifdef IBAPI
-#include "dapl_ibapi_dto.h"
-#elif VAPI
-#include "dapl_vapi_dto.h"
-#elif __OPENIB__
-#include "dapl_openib_dto.h"
-#elif DUMMY
-#include "dapl_dummy_dto.h"
-#elif OPENIB
-#include "dapl_ib_dto.h"
-#else
-#include "dapl_ibal_dto.h"
-#endif
-
-
-#endif /* _DAPL_ADAPTER_UTIL_H_ */
+/*\r
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ * in the file LICENSE.txt in the root directory. The license is also\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is in the file\r
+ * LICENSE2.txt in the root directory. The license is also available from\r
+ * the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a \r
+ * copy of which is in the file LICENSE3.txt in the root directory. The \r
+ * license is also available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * HEADER: dapl_adapter_util.h\r
+ *\r
+ * PURPOSE: Utility defs & routines for the adapter data structure\r
+ *\r
+ * $Id: dapl_adapter_util.h 1317 2005-04-25 17:29:42Z jlentini $\r
+ *\r
+ **********************************************************************/\r
+\r
+#ifndef _DAPL_ADAPTER_UTIL_H_\r
+#define _DAPL_ADAPTER_UTIL_H_\r
+\r
+\r
+typedef enum async_handler_type\r
+{\r
+ DAPL_ASYNC_UNAFILIATED,\r
+ DAPL_ASYNC_CQ_ERROR,\r
+ DAPL_ASYNC_CQ_COMPLETION,\r
+ DAPL_ASYNC_QP_ERROR\r
+} DAPL_ASYNC_HANDLER_TYPE;\r
+\r
+\r
+int dapls_ib_init (void);\r
+\r
+int dapls_ib_release (void);\r
+\r
+DAT_RETURN dapls_ib_enum_hcas (\r
+ IN const char *vendor, \r
+ OUT DAPL_HCA_NAME **hca_names,\r
+ OUT DAT_COUNT *total_hca_count);\r
+\r
+DAT_RETURN dapls_ib_get_instance_data(\r
+ IN DAPL_HCA_NAME hca_name, \r
+ OUT char *instance);\r
+\r
+DAT_RETURN dapls_ib_open_hca (\r
+ IN char *namestr,\r
+ IN DAPL_HCA *hca_ptr);\r
+\r
+DAT_RETURN dapls_ib_close_hca (\r
+ IN DAPL_HCA *hca_ptr);\r
+\r
+DAT_RETURN dapls_ib_qp_alloc (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EP *ep_ptr,\r
+ IN DAPL_EP *ep_ctx_ptr);\r
+\r
+DAT_RETURN dapls_ib_qp_free (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EP *ep_ptr);\r
+\r
+DAT_RETURN dapls_ib_qp_modify (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EP *ep_ptr,\r
+ IN DAT_EP_ATTR *ep_attr);\r
+\r
+DAT_RETURN dapls_ib_connect (\r
+ IN DAT_EP_HANDLE ep_handle,\r
+ IN DAT_IA_ADDRESS_PTR remote_ia_address,\r
+ IN DAT_CONN_QUAL remote_conn_qual,\r
+ IN DAT_COUNT private_data_size,\r
+ IN DAT_PVOID private_data);\r
+\r
+DAT_RETURN dapls_ib_disconnect (\r
+ IN DAPL_EP *ep_ptr,\r
+ IN DAT_CLOSE_FLAGS close_flags);\r
+\r
+DAT_RETURN dapls_ib_setup_conn_listener (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAT_UINT64 ServiceID,\r
+ IN DAPL_SP *sp_ptr);\r
+\r
+DAT_RETURN dapls_ib_remove_conn_listener (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_SP *sp_ptr);\r
+\r
+DAT_RETURN dapls_ib_accept_connection (\r
+ IN DAT_CR_HANDLE cr_handle,\r
+ IN DAT_EP_HANDLE ep_handle,\r
+ IN DAT_COUNT private_data_size,\r
+ IN const DAT_PVOID private_data);\r
+\r
+DAT_RETURN dapls_ib_reject_connection (\r
+ IN dp_ib_cm_handle_t cm_handle,\r
+ IN int reject_reason,\r
+ IN DAT_COUNT private_data_size,\r
+ IN const DAT_PVOID private_data);\r
+\r
+DAT_RETURN dapls_ib_setup_async_callback (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_ASYNC_HANDLER_TYPE handler_type,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN ib_async_handler_t callback,\r
+ IN void *context);\r
+\r
+DAT_RETURN dapls_ib_cq_alloc (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN DAT_COUNT *cqlen);\r
+\r
+DAT_RETURN dapls_ib_cq_free (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr);\r
+\r
+DAT_RETURN dapls_set_cq_notify (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr);\r
+\r
+DAT_RETURN dapls_ib_cq_resize (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN DAT_COUNT *cqlen);\r
+\r
+DAT_RETURN dapls_ib_pd_alloc (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_PZ *pz);\r
+\r
+DAT_RETURN dapls_ib_pd_free (\r
+ IN DAPL_PZ *pz);\r
+\r
+DAT_RETURN dapls_ib_mr_register (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_LMR *lmr,\r
+ IN DAT_PVOID virt_addr,\r
+ IN DAT_VLEN length,\r
+ IN DAT_MEM_PRIV_FLAGS privileges,\r
+ IN DAT_VA_TYPE va_type);\r
+\r
+#if defined(__KDAPL__)\r
+DAT_RETURN dapls_ib_mr_register_physical (\r
+ IN DAPL_IA *ia_ptr,\r
+ INOUT DAPL_LMR *lmr,\r
+ IN DAT_PADDR phys_addr,\r
+ IN DAT_VLEN length,\r
+ IN DAT_MEM_PRIV_FLAGS privileges);\r
+#endif /* __KDAPL__ */\r
+\r
+DAT_RETURN dapls_ib_mr_deregister (\r
+ IN DAPL_LMR *lmr);\r
+\r
+DAT_RETURN dapls_ib_mr_register_shared (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_LMR *lmr,\r
+ IN DAT_MEM_PRIV_FLAGS privileges,\r
+ IN DAT_VA_TYPE va_type);\r
+\r
+DAT_RETURN dapls_ib_mw_alloc (\r
+ IN DAPL_RMR *rmr);\r
+\r
+DAT_RETURN dapls_ib_mw_free (\r
+ IN DAPL_RMR *rmr);\r
+\r
+DAT_RETURN dapls_ib_mw_bind (\r
+ IN DAPL_RMR *rmr,\r
+ IN DAPL_LMR *lmr,\r
+ IN DAPL_EP *ep,\r
+ IN DAPL_COOKIE *cookie,\r
+ IN DAT_VADDR virtual_address,\r
+ IN DAT_VLEN length,\r
+ IN DAT_MEM_PRIV_FLAGS mem_priv,\r
+ IN DAT_BOOLEAN is_signaled);\r
+\r
+DAT_RETURN dapls_ib_mw_unbind (\r
+ IN DAPL_RMR *rmr,\r
+ IN DAPL_EP *ep,\r
+ IN DAPL_COOKIE *cookie,\r
+ IN DAT_BOOLEAN is_signaled);\r
+\r
+DAT_RETURN dapls_ib_query_hca (\r
+ IN DAPL_HCA *hca_ptr,\r
+ OUT DAT_IA_ATTR *ia_attr,\r
+ OUT DAT_EP_ATTR *ep_attr,\r
+ OUT DAT_SOCK_ADDR6 *ip_addr);\r
+\r
+DAT_RETURN dapls_ib_completion_poll (\r
+ IN DAPL_HCA *hca_ptr,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN ib_work_completion_t *cqe_ptr);\r
+\r
+DAT_RETURN dapls_ib_completion_notify (\r
+ IN ib_hca_handle_t hca_handle,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN ib_notification_type_t type);\r
+\r
+DAT_DTO_COMPLETION_STATUS dapls_ib_get_dto_status (\r
+ IN ib_work_completion_t *cqe_ptr);\r
+\r
+void dapls_ib_reinit_ep (\r
+ IN DAPL_EP *ep_ptr);\r
+\r
+void dapls_ib_disconnect_clean (\r
+ IN DAPL_EP *ep_ptr,\r
+ IN DAT_BOOLEAN passive,\r
+ IN const ib_cm_events_t ib_cm_event);\r
+\r
+DAT_RETURN dapls_ib_get_async_event (\r
+ IN ib_error_record_t *cause_ptr,\r
+ OUT DAT_EVENT_NUMBER *async_event);\r
+\r
+DAT_EVENT_NUMBER dapls_ib_get_dat_event (\r
+ IN const ib_cm_events_t ib_cm_event,\r
+ IN DAT_BOOLEAN active);\r
+\r
+ib_cm_events_t dapls_ib_get_cm_event (\r
+ IN DAT_EVENT_NUMBER dat_event_num);\r
+\r
+DAT_RETURN dapls_ib_cm_remote_addr (\r
+ IN DAT_HANDLE dat_handle,\r
+ OUT DAT_SOCK_ADDR6 *remote_ia_address);\r
+\r
+int dapls_ib_private_data_size (\r
+ IN DAPL_PRIVATE *prd_ptr,\r
+ IN DAPL_PDATA_OP conn_op,\r
+ IN DAPL_HCA *hca_ptr);\r
+\r
+void \r
+dapls_query_provider_specific_attr(\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAT_PROVIDER_ATTR *attr_ptr );\r
+\r
+DAT_RETURN\r
+dapls_evd_dto_wakeup (\r
+ IN DAPL_EVD *evd_ptr);\r
+\r
+DAT_RETURN\r
+dapls_evd_dto_wait (\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN uint32_t timeout);\r
+\r
+#ifdef DAT_EXTENSIONS\r
+void\r
+dapls_cqe_to_event_extension(\r
+ IN DAPL_EP *ep_ptr,\r
+ IN DAPL_COOKIE *cookie,\r
+ IN ib_work_completion_t *cqe_ptr,\r
+ IN DAT_EVENT *event_ptr);\r
+#endif\r
+\r
+/*\r
+ * Values for provider DAT_NAMED_ATTR\r
+ */\r
+#define IB_QP_STATE 1 /* QP state change request */\r
+\r
+\r
+#ifdef IBAPI\r
+#include "dapl_ibapi_dto.h"\r
+#elif VAPI\r
+#include "dapl_vapi_dto.h"\r
+#elif __OPENIB__\r
+#include "dapl_openib_dto.h"\r
+#elif DUMMY\r
+#include "dapl_dummy_dto.h"\r
+#elif OPENIB\r
+#include "dapl_ib_dto.h"\r
+#else\r
+#include "dapl_ibal_dto.h"\r
+#endif\r
+\r
+\r
+#endif /* _DAPL_ADAPTER_UTIL_H_ */\r
-/*
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- * copy of which is available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/**********************************************************************
- *
- * MODULE: dapl_evd_dto_callback.c
- *
- * PURPOSE: implements DTO callbacks from verbs
- *
- * $Id:$
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_evd_util.h"
-#include "dapl_cno_util.h"
-#include "dapl_cookie.h"
-#include "dapl_adapter_util.h"
-
-/*********************************************************************
- * *
- * Function Prototypes *
- * *
- *********************************************************************/
-
-/*********************************************************************
- * *
- * Function Definitions *
- * *
- *********************************************************************/
-
-/*
- * dapl_evd_dto_callback
- *
- * Input:
- * hca_handle_in,
- * cq_handle_in,
- * user_context_cq_p
- *
- * Output:
- * none
- *
- * This is invoked for both DTO and MW bind completions. Strictly
- * speaking it is an event callback rather than just a DTO callback.
- *
- */
-
-void
-dapl_evd_dto_callback(IN ib_hca_handle_t hca_handle,
- IN ib_cq_handle_t cq_handle, IN void *user_context)
-{
- DAPL_EVD *evd_ptr;
- DAT_RETURN dat_status;
- DAPL_EVD_STATE state;
-
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "dapl_evd_dto_callback(%p, %p, %p)\n",
- hca_handle, cq_handle, user_context);
-
- evd_ptr = (DAPL_EVD *) user_context;
- DAPL_CNTR(evd_ptr, DCNT_EVD_DTO_CALLBACK);
-
- dapl_os_assert(hca_handle ==
- evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle);
- dapl_os_assert(evd_ptr->ib_cq_handle == cq_handle);
- dapl_os_assert(evd_ptr->header.magic == DAPL_MAGIC_EVD);
-
- /* Read once. */
- state = *(volatile DAPL_EVD_STATE *)&evd_ptr->evd_state;
-
- dapl_dbg_log(DAPL_DBG_TYPE_EVD,
- "-- dapl_evd_dto_callback: CQ %p, state %x\n",
- (void *)evd_ptr->ib_cq_handle, state);
-
- /*
- * This function does not dequeue from the CQ; only the consumer
- * can do that. Instead, it wakes up waiters if any exist.
- * It rearms the completion only if completions should always occur
- * (specifically if a CNO is associated with the EVD and the
- * EVD is enabled.
- */
-
- if (state == DAPL_EVD_STATE_WAITED) {
- /*
- * If we could, it would be best to avoid this wakeup
- * (and the context switch) unless the number of events/CQs
- * waiting for the waiter was its threshold. We don't
- * currently have the ability to determine that without
- * dequeueing the events, and we can't do that for
- * synchronization reasons (racing with the waiter waking
- * up and dequeuing, sparked by other callbacks).
- */
-
- /*
- * We don't need to worry about taking the lock for the
- * wakeup because wakeups are sticky.
- */
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle)
- dapls_ib_wait_object_wakeup(evd_ptr->
- cq_wait_obj_handle);
- else
-#endif
- dapl_os_wait_object_wakeup(&evd_ptr->wait_object);
-
- } else if (state == DAPL_EVD_STATE_OPEN) {
- DAPL_CNO *cno = evd_ptr->cno_ptr;
- if (evd_ptr->evd_enabled && (evd_ptr->cno_ptr != NULL)) {
- /*
- * Re-enable callback, *then* trigger.
- * This guarantees we won't miss any events.
- */
- dat_status = dapls_ib_completion_notify(hca_handle,
- evd_ptr,
- IB_NOTIFY_ON_NEXT_COMP);
-
- if (DAT_SUCCESS != dat_status) {
- (void)dapls_evd_post_async_error_event(evd_ptr->
- header.
- owner_ia->
- async_error_evd,
- DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR,
- (DAT_IA_HANDLE)
- evd_ptr->
- header.
- owner_ia);
- }
-
- dapl_internal_cno_trigger(cno, evd_ptr);
- }
- }
- dapl_dbg_log(DAPL_DBG_TYPE_RTN, "dapl_evd_dto_callback () returns\n");
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
+/*\r
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
+ * copy of which is available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_evd_dto_callback.c\r
+ *\r
+ * PURPOSE: implements DTO callbacks from verbs\r
+ *\r
+ * $Id:$\r
+ **********************************************************************/\r
+\r
+#include "dapl.h"\r
+#include "dapl_evd_util.h"\r
+#include "dapl_cno_util.h"\r
+#include "dapl_cookie.h"\r
+#include "dapl_adapter_util.h"\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Function Prototypes *\r
+ * *\r
+ *********************************************************************/\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Function Definitions *\r
+ * *\r
+ *********************************************************************/\r
+\r
+/*\r
+ * dapl_evd_dto_callback\r
+ *\r
+ * Input:\r
+ * hca_handle_in, \r
+ * cq_handle_in, \r
+ * user_context_cq_p\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * This is invoked for both DTO and MW bind completions. Strictly \r
+ * speaking it is an event callback rather than just a DTO callback. \r
+ *\r
+ */\r
+\r
+void\r
+dapl_evd_dto_callback(IN ib_hca_handle_t hca_handle,\r
+ IN ib_cq_handle_t cq_handle, IN void *user_context)\r
+{\r
+ DAPL_EVD *evd_ptr;\r
+ DAT_RETURN dat_status;\r
+ DAPL_EVD_STATE state;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "dapl_evd_dto_callback(%p, %p, %p)\n",\r
+ hca_handle, cq_handle, user_context);\r
+\r
+ evd_ptr = (DAPL_EVD *) user_context;\r
+ DAPL_CNTR(evd_ptr, DCNT_EVD_DTO_CALLBACK);\r
+\r
+ dapl_os_assert(hca_handle ==\r
+ evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle);\r
+ dapl_os_assert(evd_ptr->ib_cq_handle == cq_handle);\r
+ dapl_os_assert(evd_ptr->header.magic == DAPL_MAGIC_EVD);\r
+\r
+ /* Read once. */\r
+ state = *(volatile DAPL_EVD_STATE *)&evd_ptr->evd_state;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_EVD,\r
+ "-- dapl_evd_dto_callback: CQ %p, state %x\n",\r
+ (void *)evd_ptr->ib_cq_handle, state);\r
+\r
+ /*\r
+ * This function does not dequeue from the CQ; only the consumer\r
+ * can do that. Instead, it wakes up waiters if any exist.\r
+ * It rearms the completion only if completions should always occur\r
+ * (specifically if a CNO is associated with the EVD and the\r
+ * EVD is enabled.\r
+ */\r
+\r
+ if (state == DAPL_EVD_STATE_WAITED) {\r
+ /*\r
+ * If we could, it would be best to avoid this wakeup\r
+ * (and the context switch) unless the number of events/CQs\r
+ * waiting for the waiter was its threshold. We don't\r
+ * currently have the ability to determine that without\r
+ * dequeueing the events, and we can't do that for\r
+ * synchronization reasons (racing with the waiter waking\r
+ * up and dequeuing, sparked by other callbacks).\r
+ */\r
+\r
+ /*\r
+ * We don't need to worry about taking the lock for the\r
+ * wakeup because wakeups are sticky.\r
+ */\r
+ dapls_evd_dto_wakeup(evd_ptr);\r
+\r
+ } else if (state == DAPL_EVD_STATE_OPEN) {\r
+ DAPL_CNO *cno = evd_ptr->cno_ptr;\r
+ if (evd_ptr->evd_enabled && (evd_ptr->cno_ptr != NULL)) {\r
+ /*\r
+ * Re-enable callback, *then* trigger.\r
+ * This guarantees we won't miss any events.\r
+ */\r
+ dat_status = dapls_ib_completion_notify(hca_handle,\r
+ evd_ptr,\r
+ IB_NOTIFY_ON_NEXT_COMP);\r
+\r
+ if (DAT_SUCCESS != dat_status) {\r
+ (void)dapls_evd_post_async_error_event(evd_ptr->\r
+ header.\r
+ owner_ia->\r
+ async_error_evd,\r
+ DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR,\r
+ (DAT_IA_HANDLE)\r
+ evd_ptr->\r
+ header.\r
+ owner_ia);\r
+ }\r
+\r
+ dapl_internal_cno_trigger(cno, evd_ptr);\r
+ }\r
+ }\r
+ dapl_dbg_log(DAPL_DBG_TYPE_RTN, "dapl_evd_dto_callback () returns\n");\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-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_evd_util.c
- *
- * PURPOSE: Manage EVD Info structure
- *
- * $Id: dapl_evd_util.c 1410 2006-07-19 17:12:02Z ardavis $
- **********************************************************************/
-
-#include "dapl_evd_util.h"
-#include "dapl_ia_util.h"
-#include "dapl_cno_util.h"
-#include "dapl_ring_buffer_util.h"
-#include "dapl_adapter_util.h"
-#include "dapl_cookie.h"
-#include "dapl.h"
-#include "dapl_cr_util.h"
-#include "dapl_sp_util.h"
-#include "dapl_ep_util.h"
-
-STATIC _INLINE_ void dapli_evd_eh_print_cqe(IN ib_work_completion_t * cqe);
-
-DAT_RETURN dapli_evd_event_alloc(IN DAPL_EVD * evd_ptr, IN DAT_COUNT qlen);
-
-char *dapl_event_str(IN DAT_EVENT_NUMBER event_num)
-{
-#if defined(DAPL_DBG)
- struct dat_event_str {
- char *str;
- DAT_EVENT_NUMBER num;
- };
- static struct dat_event_str events[] = {
- {"DAT_DTO_COMPLETION_EVENT", DAT_DTO_COMPLETION_EVENT},
- {"DAT_RMR_BIND_COMPLETION_EVENT",
- DAT_RMR_BIND_COMPLETION_EVENT},
- {"DAT_CONNECTION_REQUEST_EVENT", DAT_CONNECTION_REQUEST_EVENT},
- {"DAT_CONNECTION_EVENT_ESTABLISHED",
- DAT_CONNECTION_EVENT_ESTABLISHED},
- {"DAT_CONNECTION_EVENT_PEER_REJECTED",
- DAT_CONNECTION_EVENT_PEER_REJECTED},
- {"DAT_CONNECTION_EVENT_NON_PEER_REJECTED",
- DAT_CONNECTION_EVENT_NON_PEER_REJECTED},
- {"DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR",
- DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR},
- {"DAT_CONNECTION_EVENT_DISCONNECTED",
- DAT_CONNECTION_EVENT_DISCONNECTED},
- {"DAT_CONNECTION_EVENT_BROKEN", DAT_CONNECTION_EVENT_BROKEN},
- {"DAT_CONNECTION_EVENT_TIMED_OUT",
- DAT_CONNECTION_EVENT_TIMED_OUT},
- {"DAT_CONNECTION_EVENT_UNREACHABLE",
- DAT_CONNECTION_EVENT_UNREACHABLE},
- {"DAT_ASYNC_ERROR_EVD_OVERFLOW", DAT_ASYNC_ERROR_EVD_OVERFLOW},
- {"DAT_ASYNC_ERROR_IA_CATASTROPHIC",
- DAT_ASYNC_ERROR_IA_CATASTROPHIC},
- {"DAT_ASYNC_ERROR_EP_BROKEN", DAT_ASYNC_ERROR_EP_BROKEN},
- {"DAT_ASYNC_ERROR_TIMED_OUT", DAT_ASYNC_ERROR_TIMED_OUT},
- {"DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR",
- DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR},
- {"DAT_HA_DOWN_TO_1", DAT_HA_DOWN_TO_1},
- {"DAT_HA_UP_TO_MULTI_PATH", DAT_HA_UP_TO_MULTI_PATH},
- {"DAT_SOFTWARE_EVENT", DAT_SOFTWARE_EVENT},
-#ifdef DAT_EXTENSIONS
- {"DAT_EXTENSION_EVENT", DAT_EXTENSION_EVENT},
- {"DAT_IB_EXTENSION_RANGE_BASE", DAT_IB_EXTENSION_RANGE_BASE},
- {"DAT_IB_UD_CONNECTION_REQUEST_EVENT",
- DAT_IB_EXTENSION_RANGE_BASE + 1},
- {"DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED",
- DAT_IB_EXTENSION_RANGE_BASE + 2},
- {"DAT_IW_EXTENSION_RANGE_BASE", DAT_IW_EXTENSION_RANGE_BASE},
-#endif /* DAT_EXTENSIONS */
- {NULL, 0},
- };
- int i;
-
- for (i = 0; events[i].str; i++) {
- if (events[i].num == event_num)
- return events[i].str;
- }
- return "Unknown DAT event?";
-#else
- static char str[16];
- sprintf(str, "%x", event_num);
- return str;
-#endif
-}
-
-/*
- * dapls_evd_internal_create
- *
- * actually create the evd. this is called after all parameter checking
- * has been performed in dapl_ep_create. it is also called from dapl_ia_open
- * to create the default async evd.
- *
- * Input:
- * ia_ptr
- * cno_ptr
- * qlen
- * evd_flags
- *
- * Output:
- * evd_ptr_ptr
- *
- * Returns:
- * none
- *
- */
-
-DAT_RETURN
-dapls_evd_internal_create(DAPL_IA * ia_ptr,
- DAPL_CNO * cno_ptr,
- DAT_COUNT min_qlen,
- DAT_EVD_FLAGS evd_flags, DAPL_EVD ** evd_ptr_ptr)
-{
- DAPL_EVD *evd_ptr;
- DAT_COUNT cq_len;
- DAT_RETURN dat_status;
-
- dat_status = DAT_SUCCESS;
- *evd_ptr_ptr = NULL;
- cq_len = min_qlen;
-
- evd_ptr = dapls_evd_alloc(ia_ptr, cno_ptr, evd_flags, min_qlen);
- if (!evd_ptr) {
- dat_status =
- DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
- goto bail;
- }
-
- /*
- * If we are dealing with event streams besides a CQ event stream,
- * be conservative and set producer side locking. Otherwise, no.
- */
- evd_ptr->evd_producer_locking_needed =
- ((evd_flags & ~(DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG)) != 0);
-
- /* Before we setup any callbacks, transition state to OPEN. */
- evd_ptr->evd_state = DAPL_EVD_STATE_OPEN;
-
- if (evd_flags & DAT_EVD_ASYNC_FLAG) {
- /*
- * There is no cq associate with async evd. Set it to invalid
- */
- evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;
-
- } else if (0 != (evd_flags & ~(DAT_EVD_SOFTWARE_FLAG
- | DAT_EVD_CONNECTION_FLAG
- | DAT_EVD_CR_FLAG))) {
-#if defined(_VENDOR_IBAL_)
- /*
- * The creation of CQ required a PD (PZ) associated with it and
- * we do not have a PD here; therefore, the work-around is that we
- * will postpone the creation of the cq till the creation of QP which
- * this cq will associate with.
- */
- evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;
-#else
- dat_status = dapls_ib_cq_alloc(ia_ptr, evd_ptr, &cq_len);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-
- /* Now reset the cq_len in the attributes, it may have changed */
- evd_ptr->qlen = cq_len;
-
- dat_status =
- dapls_ib_setup_async_callback(ia_ptr,
- DAPL_ASYNC_CQ_COMPLETION,
- evd_ptr,
- (ib_async_handler_t)
- dapl_evd_dto_callback,
- evd_ptr);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-
- dat_status = dapls_set_cq_notify(ia_ptr, evd_ptr);
-
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-#endif /* _VENDOR_IBAL_ */
- }
-
- /* We now have an accurate count of events, so allocate them into
- * the EVD
- */
- dat_status = dapli_evd_event_alloc(evd_ptr, cq_len);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-
- dapl_ia_link_evd(ia_ptr, evd_ptr);
- *evd_ptr_ptr = evd_ptr;
-
- bail:
- if (dat_status != DAT_SUCCESS) {
- if (evd_ptr) {
- dapls_evd_dealloc(evd_ptr);
- }
- }
-
- return dat_status;
-}
-
-/*
- * dapls_evd_alloc
- *
- * alloc and initialize an EVD struct
- *
- * Input:
- * ia
- *
- * Output:
- * evd_ptr
- *
- * Returns:
- * none
- *
- */
-DAPL_EVD *dapls_evd_alloc(IN DAPL_IA * ia_ptr,
- IN DAPL_CNO * cno_ptr,
- IN DAT_EVD_FLAGS evd_flags, IN DAT_COUNT qlen)
-{
- DAPL_EVD *evd_ptr;
-
- /* Allocate EVD */
- evd_ptr = (DAPL_EVD *) dapl_os_alloc(sizeof(DAPL_EVD));
- if (!evd_ptr) {
- goto bail;
- }
-
- /* zero the structure */
- dapl_os_memzero(evd_ptr, sizeof(DAPL_EVD));
-
-#ifdef DAPL_COUNTERS
- /* Allocate counters */
- evd_ptr->cntrs =
- dapl_os_alloc(sizeof(DAT_UINT64) * DCNT_EVD_ALL_COUNTERS);
- if (evd_ptr->cntrs == NULL) {
- dapl_os_free(evd_ptr, sizeof(DAPL_EVD));
- return (NULL);
- }
- dapl_os_memzero(evd_ptr->cntrs,
- sizeof(DAT_UINT64) * DCNT_EVD_ALL_COUNTERS);
-#endif /* DAPL_COUNTERS */
-
- /*
- * initialize the header
- */
- evd_ptr->header.provider = ia_ptr->header.provider;
- evd_ptr->header.magic = DAPL_MAGIC_EVD;
- evd_ptr->header.handle_type = DAT_HANDLE_TYPE_EVD;
- evd_ptr->header.owner_ia = ia_ptr;
- evd_ptr->header.user_context.as_64 = 0;
- evd_ptr->header.user_context.as_ptr = NULL;
- dapl_llist_init_entry(&evd_ptr->header.ia_list_entry);
- dapl_os_lock_init(&evd_ptr->header.lock);
-
- /*
- * Initialize the body
- */
- evd_ptr->evd_state = DAPL_EVD_STATE_INITIAL;
- evd_ptr->evd_flags = evd_flags;
- evd_ptr->evd_enabled = DAT_TRUE;
- evd_ptr->evd_waitable = DAT_TRUE;
- evd_ptr->evd_producer_locking_needed = 1; /* Conservative value. */
- evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;
- dapl_os_atomic_set(&evd_ptr->evd_ref_count, 0);
- evd_ptr->catastrophic_overflow = DAT_FALSE;
- evd_ptr->qlen = qlen;
- evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD; /* FIXME: should be DAPL_EVD_STATE_INIT */
- dapl_os_wait_object_init(&evd_ptr->wait_object);
-
-#ifdef CQ_WAIT_OBJECT
- /* Create CQ wait object; no CNO and data stream type */
- if ((cno_ptr == NULL) &&
- ((evd_flags & ~(DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG)) == 0)) {
- dapls_ib_wait_object_create(evd_ptr,
- &evd_ptr->cq_wait_obj_handle);
- if (evd_ptr->cq_wait_obj_handle == NULL) {
- dapl_os_free(evd_ptr, sizeof(DAPL_EVD));
- evd_ptr = NULL;
- goto bail;
- }
- }
-#endif
-
- evd_ptr->cno_active_count = 0;
- if (cno_ptr != NULL) {
- /* Take a reference count on the CNO */
- dapl_os_atomic_inc(&cno_ptr->cno_ref_count);
- }
- evd_ptr->cno_ptr = cno_ptr;
-
- bail:
- return evd_ptr;
-}
-
-/*
- * dapls_evd_event_alloc
- *
- * alloc events into an EVD.
- *
- * Input:
- * evd_ptr
- * qlen
- *
- * Output:
- * NONE
- *
- * Returns:
- * DAT_SUCCESS
- * ERROR
- *
- */
-DAT_RETURN dapli_evd_event_alloc(IN DAPL_EVD * evd_ptr, IN DAT_COUNT qlen)
-{
- DAT_EVENT *event_ptr;
- DAT_COUNT i;
- DAT_RETURN dat_status;
-
- dat_status = DAT_SUCCESS;
-
- /* Allocate EVENTs */
- event_ptr =
- (DAT_EVENT *) dapl_os_alloc(evd_ptr->qlen * sizeof(DAT_EVENT));
- if (event_ptr == NULL) {
- dat_status =
- DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
- goto bail;
- }
- evd_ptr->events = event_ptr;
-
- /* allocate free event queue */
- dat_status = dapls_rbuf_alloc(&evd_ptr->free_event_queue, qlen);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-
- /* allocate pending event queue */
- dat_status = dapls_rbuf_alloc(&evd_ptr->pending_event_queue, qlen);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
-
- /* add events to free event queue */
- for (i = 0; i < evd_ptr->qlen; i++) {
- dapls_rbuf_add(&evd_ptr->free_event_queue, (void *)event_ptr);
- event_ptr++;
- }
-
- evd_ptr->cq_notified = DAT_FALSE;
- evd_ptr->cq_notified_when = 0;
- evd_ptr->threshold = 0;
-
- bail:
- return dat_status;
-}
-
-/*
- * dapls_evd_event_realloc
- *
- * realloc events into an EVD.
- *
- * Input:
- * evd_ptr
- * qlen
- *
- * Output:
- * NONE
- *
- * Returns:
- * DAT_SUCCESS
- * ERROR
- *
- */
-DAT_RETURN dapls_evd_event_realloc(IN DAPL_EVD * evd_ptr, IN DAT_COUNT qlen)
-{
- DAT_EVENT *events;
- DAT_COUNT old_qlen;
- DAT_COUNT i;
- intptr_t diff;
- DAT_RETURN dat_status;
-
- /* Allocate EVENTs */
- events = (DAT_EVENT *) dapl_os_realloc(evd_ptr->events,
- qlen * sizeof(DAT_EVENT));
- if (NULL == events) {
- dat_status =
- DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);
- goto bail;
- }
-
- diff = events - evd_ptr->events;
- evd_ptr->events = events;
-
- old_qlen = evd_ptr->qlen;
- evd_ptr->qlen = qlen;
-
- /* reallocate free event queue */
- dat_status = dapls_rbuf_realloc(&evd_ptr->free_event_queue, qlen);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
- dapls_rbuf_adjust(&evd_ptr->free_event_queue, diff);
-
- /* reallocate pending event queue */
- dat_status = dapls_rbuf_realloc(&evd_ptr->pending_event_queue, qlen);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
- dapls_rbuf_adjust(&evd_ptr->pending_event_queue, diff);
-
- /*
- * add new events to free event queue.
- */
- for (i = old_qlen; i < qlen; i++) {
- dapls_rbuf_add(&evd_ptr->free_event_queue, (void *)&events[i]);
- }
-
- bail:
- return dat_status;
-}
-
-/*
- * dapls_evd_dealloc
- *
- * Free the passed in EVD structure. If an error occurs, this function
- * will clean up all of the internal data structures and report the
- * error.
- *
- * Input:
- * evd_ptr
- *
- * Output:
- * none
- *
- * Returns:
- * status
- *
- */
-DAT_RETURN dapls_evd_dealloc(IN DAPL_EVD * evd_ptr)
-{
- DAT_RETURN dat_status;
- DAPL_IA *ia_ptr;
-
- dat_status = DAT_SUCCESS;
-
- dapl_os_assert(evd_ptr->header.magic == DAPL_MAGIC_EVD);
- dapl_os_assert(dapl_os_atomic_read(&evd_ptr->evd_ref_count) == 0);
-
- /*
- * Destroy the CQ first, to keep any more callbacks from coming
- * up from it.
- */
- if (evd_ptr->ib_cq_handle != IB_INVALID_HANDLE) {
- ia_ptr = evd_ptr->header.owner_ia;
-
- dat_status = dapls_ib_cq_free(ia_ptr, evd_ptr);
- if (dat_status != DAT_SUCCESS) {
- goto bail;
- }
- }
-
- /*
- * We should now be safe to invalidate the EVD; reset the
- * magic to prevent reuse.
- */
- evd_ptr->header.magic = DAPL_MAGIC_INVALID;
-
- /* Release reference on the CNO if it exists */
- if (evd_ptr->cno_ptr != NULL) {
- dapl_os_atomic_dec(&evd_ptr->cno_ptr->cno_ref_count);
- evd_ptr->cno_ptr = NULL;
- }
-
- /* If the ring buffer allocation failed, then the dapls_rbuf_destroy */
- /* function will detect that the ring buffer's internal data (ex. base */
- /* pointer) are invalid and will handle the situation appropriately */
- dapls_rbuf_destroy(&evd_ptr->free_event_queue);
- dapls_rbuf_destroy(&evd_ptr->pending_event_queue);
-
- if (evd_ptr->events) {
- dapl_os_free(evd_ptr->events,
- evd_ptr->qlen * sizeof(DAT_EVENT));
- }
-
- dapl_os_wait_object_destroy(&evd_ptr->wait_object);
-
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle) {
- dapls_ib_wait_object_destroy(evd_ptr->cq_wait_obj_handle);
- }
-#endif
-
-#ifdef DAPL_COUNTERS
- dapl_os_free(evd_ptr->cntrs,
- sizeof(DAT_UINT64) * DCNT_EVD_ALL_COUNTERS);
-#endif /* DAPL_COUNTERS */
-
- dapl_os_free(evd_ptr, sizeof(DAPL_EVD));
-
- bail:
- return dat_status;
-}
-
-STATIC _INLINE_ char *DAPL_GET_DTO_OP_STR(int op)
-{
- static char *dto_ops[] = {
- "OP_SEND",
- "OP_RECEIVE",
- "OP_RDMA_WRITE",
- "OP_RDMA_READ"
- };
- return ((op < 0 || op > 3) ? "Invalid DTO OP?" : dto_ops[op]);
-}
-
-#if !defined(DAPL_GET_CQE_OP_STR)
-#define DAPL_GET_CQE_OP_STR(e) "Unknown CEQ OP String?"
-#endif
-#if !defined(DAPL_GET_CQE_VENDOR_ERR)
-#define DAPL_GET_CQE_VENDOR_ERR(e) 0
-#endif
-
-/*
- * dapli_evd_eh_print_cqe
- *
- * Input:
- * cqe_ptr
- *
- * Output:
- * none
- *
- * Prints out a CQE for debug purposes
- *
- */
-
-void dapli_evd_eh_print_cqe(IN ib_work_completion_t * cqe_ptr)
-{
-#ifdef DAPL_DBG
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t >>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<\n");
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t dapl_evd_dto_callback : CQE \n");
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t\t work_req_id %lli\n", DAPL_GET_CQE_WRID(cqe_ptr));
- if (DAPL_GET_CQE_STATUS(cqe_ptr) == 0) {
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t\t op_type: %s\n",
- DAPL_GET_CQE_OP_STR(cqe_ptr));
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t\t bytes_num %d\n",
- DAPL_GET_CQE_BYTESNUM(cqe_ptr));
- }
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t\t status %d vendor_err 0x%x\n",
- DAPL_GET_CQE_STATUS(cqe_ptr),
- DAPL_GET_CQE_VENDOR_ERR(cqe_ptr));
- dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
- "\t >>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<\n");
-#endif
- return;
-}
-
-/*
- * Event posting code follows.
- */
-
-/*
- * These next two functions (dapli_evd_get_event and dapli_evd_post_event)
- * are a pair. They are always called together, from one of the functions
- * at the end of this file (dapl_evd_post_*_event).
- *
- * Note that if producer side locking is enabled, the first one takes the
- * EVD lock and the second releases it.
- */
-
-/* dapli_evd_get_event
- *
- * Get an event struct from the evd. The caller should fill in the event
- * and call dapl_evd_post_event.
- *
- * If there are no events available, an overflow event is generated to the
- * async EVD handler.
- *
- * If this EVD required producer locking, a successful return implies
- * that the lock is held.
- *
- * Input:
- * evd_ptr
- *
- * Output:
- * event
- *
- */
-
-static DAT_EVENT *dapli_evd_get_event(DAPL_EVD * evd_ptr)
-{
- DAT_EVENT *event;
-
- if (evd_ptr->evd_producer_locking_needed) {
- dapl_os_lock(&evd_ptr->header.lock);
- }
-
- event = (DAT_EVENT *) dapls_rbuf_remove(&evd_ptr->free_event_queue);
-
- /* Release the lock if it was taken and the call failed. */
- if (!event && evd_ptr->evd_producer_locking_needed) {
- dapl_os_unlock(&evd_ptr->header.lock);
- }
-
- return event;
-}
-
-/* dapli_evd_post_event
- *
- * Post the <event> to the evd. If possible, invoke the evd's CNO.
- * Otherwise post the event on the pending queue.
- *
- * If producer side locking is required, the EVD lock must be held upon
- * entry to this function.
- *
- * Input:
- * evd_ptr
- * event
- *
- * Output:
- * none
- *
- */
-
-static void
-dapli_evd_post_event(IN DAPL_EVD * evd_ptr, IN const DAT_EVENT * event_ptr)
-{
- DAT_RETURN dat_status;
- DAPL_CNO *cno_to_trigger = NULL;
-
- dapl_dbg_log(DAPL_DBG_TYPE_EVD, "%s: Called with event %s\n",
- __FUNCTION__, dapl_event_str(event_ptr->event_number));
-
- dat_status = dapls_rbuf_add(&evd_ptr->pending_event_queue,
- (void *)event_ptr);
- dapl_os_assert(dat_status == DAT_SUCCESS);
-
- dapl_os_assert(evd_ptr->evd_state == DAPL_EVD_STATE_WAITED
- || evd_ptr->evd_state == DAPL_EVD_STATE_OPEN);
-
- if (evd_ptr->evd_state == DAPL_EVD_STATE_OPEN) {
- /* No waiter. Arrange to trigger a CNO if it exists. */
-
- if (evd_ptr->evd_enabled) {
- cno_to_trigger = evd_ptr->cno_ptr;
- }
- if (evd_ptr->evd_producer_locking_needed) {
- dapl_os_unlock(&evd_ptr->header.lock);
- }
- } else {
- /*
- * We're in DAPL_EVD_STATE_WAITED. Take the lock if
- * we don't have it, recheck, and signal.
- */
- if (!evd_ptr->evd_producer_locking_needed) {
- dapl_os_lock(&evd_ptr->header.lock);
- }
-
- if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED
- && (dapls_rbuf_count(&evd_ptr->pending_event_queue)
- >= evd_ptr->threshold)) {
- dapl_os_unlock(&evd_ptr->header.lock);
-
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle)
- dapls_ib_wait_object_wakeup(evd_ptr->
- cq_wait_obj_handle);
- else
-#endif
- dapl_os_wait_object_wakeup(&evd_ptr->
- wait_object);
- } else {
- dapl_os_unlock(&evd_ptr->header.lock);
- }
- }
-
- if (cno_to_trigger != NULL) {
- dapl_internal_cno_trigger(cno_to_trigger, evd_ptr);
- }
-}
-
-/* dapli_evd_post_event_nosignal
- *
- * Post the <event> to the evd. Do not do any wakeup processing.
- * This function should only be called if it is known that there are
- * no waiters that it is appropriate to wakeup on this EVD. An example
- * of such a situation is during internal dat_evd_wait() processing.
- *
- * If producer side locking is required, the EVD lock must be held upon
- * entry to this function.
- *
- * Input:
- * evd_ptr
- * event
- *
- * Output:
- * none
- *
- */
-
-static void
-dapli_evd_post_event_nosignal(IN DAPL_EVD * evd_ptr,
- IN const DAT_EVENT * event_ptr)
-{
- DAT_RETURN dat_status;
-
- dapl_dbg_log(DAPL_DBG_TYPE_EVD, "%s: Called with event %s\n",
- __FUNCTION__, dapl_event_str(event_ptr->event_number));
-
- dat_status = dapls_rbuf_add(&evd_ptr->pending_event_queue,
- (void *)event_ptr);
- dapl_os_assert(dat_status == DAT_SUCCESS);
-
- dapl_os_assert(evd_ptr->evd_state == DAPL_EVD_STATE_WAITED
- || evd_ptr->evd_state == DAPL_EVD_STATE_OPEN);
-
- if (evd_ptr->evd_producer_locking_needed) {
- dapl_os_unlock(&evd_ptr->header.lock);
- }
-}
-
-/* dapli_evd_format_overflow_event
- *
- * format an overflow event for posting
- *
- * Input:
- * evd_ptr
- * event_ptr
- *
- * Output:
- * none
- *
- */
-static void
-dapli_evd_format_overflow_event(IN DAPL_EVD * evd_ptr,
- OUT DAT_EVENT * event_ptr)
-{
- DAPL_IA *ia_ptr;
-
- ia_ptr = evd_ptr->header.owner_ia;
-
- event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;
- event_ptr->event_number = DAT_ASYNC_ERROR_EVD_OVERFLOW;
- event_ptr->event_data.asynch_error_event_data.dat_handle =
- (DAT_HANDLE) ia_ptr;
-}
-
-/* dapli_evd_post_overflow_event
- *
- * post an overflow event
- *
- * Input:
- * async_evd_ptr
- * evd_ptr
- *
- * Output:
- * none
- *
- */
-static void
-dapli_evd_post_overflow_event(IN DAPL_EVD * async_evd_ptr,
- IN DAPL_EVD * overflow_evd_ptr)
-{
- DAT_EVENT *overflow_event;
-
- /* The overflow_evd_ptr mght be the same as evd.
- * In that case we've got a catastrophic overflow.
- */
- dapl_log(DAPL_DBG_TYPE_WARN,
- " WARNING: overflow event on EVD %p/n", overflow_evd_ptr);
-
- if (async_evd_ptr == overflow_evd_ptr) {
- async_evd_ptr->catastrophic_overflow = DAT_TRUE;
- async_evd_ptr->evd_state = DAPL_EVD_STATE_DEAD;
- return;
- }
-
- overflow_event = dapli_evd_get_event(overflow_evd_ptr);
- if (!overflow_event) {
- /* this is not good */
- overflow_evd_ptr->catastrophic_overflow = DAT_TRUE;
- overflow_evd_ptr->evd_state = DAPL_EVD_STATE_DEAD;
- return;
- }
- dapli_evd_format_overflow_event(overflow_evd_ptr, overflow_event);
- dapli_evd_post_event(overflow_evd_ptr, overflow_event);
-
- return;
-}
-
-static DAT_EVENT *dapli_evd_get_and_init_event(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number)
-{
- DAT_EVENT *event_ptr;
-
- event_ptr = dapli_evd_get_event(evd_ptr);
- if (NULL == event_ptr) {
- dapli_evd_post_overflow_event(evd_ptr->header.owner_ia->
- async_error_evd, evd_ptr);
- } else {
- event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;
- event_ptr->event_number = event_number;
- }
-
- return event_ptr;
-}
-
-DAT_RETURN
-dapls_evd_post_cr_arrival_event(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN DAT_SP_HANDLE sp_handle,
- DAT_IA_ADDRESS_PTR ia_address_ptr,
- DAT_CONN_QUAL conn_qual,
- DAT_CR_HANDLE cr_handle)
-{
- DAT_EVENT *event_ptr;
- event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
-
- if (event_ptr == NULL) {
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
- }
-
- event_ptr->event_data.cr_arrival_event_data.sp_handle = sp_handle;
- event_ptr->event_data.cr_arrival_event_data.local_ia_address_ptr
- = ia_address_ptr;
- event_ptr->event_data.cr_arrival_event_data.conn_qual = conn_qual;
- event_ptr->event_data.cr_arrival_event_data.cr_handle = cr_handle;
-
- dapli_evd_post_event(evd_ptr, event_ptr);
-
- return DAT_SUCCESS;
-}
-
-DAT_RETURN
-dapls_evd_post_connection_event(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN DAT_EP_HANDLE ep_handle,
- IN DAT_COUNT private_data_size,
- IN DAT_PVOID private_data)
-{
- DAT_EVENT *event_ptr;
- event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
-
- if (event_ptr == NULL) {
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
- }
-
- event_ptr->event_data.connect_event_data.ep_handle = ep_handle;
- event_ptr->event_data.connect_event_data.private_data_size
- = private_data_size;
- event_ptr->event_data.connect_event_data.private_data = private_data;
-
- dapli_evd_post_event(evd_ptr, event_ptr);
-
- return DAT_SUCCESS;
-}
-
-DAT_RETURN
-dapls_evd_post_async_error_event(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN DAT_IA_HANDLE ia_handle)
-{
- DAT_EVENT *event_ptr;
- event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
- dapl_log(DAPL_DBG_TYPE_WARN,
- " WARNING: async event - %s evd=%p/n",
- dapl_event_str(event_number), evd_ptr);
-
- if (event_ptr == NULL) {
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
- }
-
- event_ptr->event_data.asynch_error_event_data.dat_handle =
- (DAT_HANDLE) ia_handle;
-
- dapli_evd_post_event(evd_ptr, event_ptr);
-
- return DAT_SUCCESS;
-}
-
-DAT_RETURN
-dapls_evd_post_software_event(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN DAT_PVOID pointer)
-{
- DAT_EVENT *event_ptr;
- event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
-
- if (event_ptr == NULL) {
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
- }
-
- event_ptr->event_data.software_event_data.pointer = pointer;
-
- dapli_evd_post_event(evd_ptr, event_ptr);
-
- return DAT_SUCCESS;
-}
-
-/*
- * dapls_evd_post_generic_event
- *
- * Post a generic event type. Not used by all providers
- *
- * Input:
- * evd_ptr
- * event_number
- * data
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- *
- */
-DAT_RETURN
-dapls_evd_post_generic_event(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN DAT_EVENT_DATA * data)
-{
- DAT_EVENT *event_ptr;
-
- event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
-
- if (event_ptr == NULL) {
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
- }
-
- event_ptr->event_data = *data;
-
- dapli_evd_post_event(evd_ptr, event_ptr);
-
- return DAT_SUCCESS;
-}
-
-#ifdef DAT_EXTENSIONS
-DAT_RETURN
-dapls_evd_post_cr_event_ext(IN DAPL_SP * sp_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN dp_ib_cm_handle_t ib_cm_handle,
- IN DAT_COUNT p_size,
- IN DAT_PVOID p_data, IN DAT_PVOID ext_data)
-{
- DAPL_CR *cr_ptr;
- DAPL_EP *ep_ptr;
- DAT_EVENT *event_ptr;
- DAT_SP_HANDLE sp_handle;
-
- dapl_os_lock(&sp_ptr->header.lock);
- if (sp_ptr->listening == DAT_FALSE) {
- dapl_os_unlock(&sp_ptr->header.lock);
- dapl_dbg_log(DAPL_DBG_TYPE_CM,
- "---> post_cr_event_ext: conn event on down SP\n");
- (void)dapls_ib_reject_connection(ib_cm_handle,
- DAT_CONNECTION_EVENT_UNREACHABLE,
- 0, NULL);
- return DAT_CONN_QUAL_UNAVAILABLE;
- }
-
- /*
- * RSP connections only allow a single connection. Close
- * it down NOW so we reject any further connections.
- */
- if (sp_ptr->header.handle_type == DAT_HANDLE_TYPE_RSP)
- sp_ptr->listening = DAT_FALSE;
-
- dapl_os_unlock(&sp_ptr->header.lock);
-
- /* allocate new connect request */
- cr_ptr = dapls_cr_alloc(sp_ptr->header.owner_ia);
- if (cr_ptr == NULL)
- return DAT_INSUFFICIENT_RESOURCES;
-
- /* Set up the CR */
- cr_ptr->sp_ptr = sp_ptr; /* maintain sp_ptr in case of reject */
- cr_ptr->param.remote_port_qual = 0;
- cr_ptr->ib_cm_handle = ib_cm_handle;
- cr_ptr->param.remote_ia_address_ptr =
- (DAT_IA_ADDRESS_PTR) & cr_ptr->remote_ia_address;
-
- /*
- * Copy the remote address and private data out of the private_data
- */
- cr_ptr->param.private_data = cr_ptr->private_data;
- cr_ptr->param.private_data_size = p_size;
- if (p_size)
- dapl_os_memcpy(cr_ptr->private_data, p_data, p_size);
-
- /* EP will be NULL unless RSP service point */
- ep_ptr = (DAPL_EP *) sp_ptr->ep_handle;
-
- if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {
- DAPL_IA *ia_ptr;
- /*
- * Never true for RSP connections
- *
- * Create an EP for the user. If we can't allocate an
- * EP we are out of resources and need to tell the
- * requestor that we cant help them.
- */
- ia_ptr = sp_ptr->header.owner_ia;
- ep_ptr = dapl_ep_alloc(ia_ptr, NULL);
- if (ep_ptr == NULL) {
- dapls_cr_free(cr_ptr);
- /* Invoking function will call dapls_ib_cm_reject() */
- return DAT_INSUFFICIENT_RESOURCES;
- }
- ep_ptr->param.ia_handle = ia_ptr;
- ep_ptr->param.local_ia_address_ptr =
- (DAT_IA_ADDRESS_PTR) & ia_ptr->hca_ptr->hca_address;
-
- /* Link the EP onto the IA */
- dapl_ia_link_ep(ia_ptr, ep_ptr);
- }
-
- cr_ptr->param.local_ep_handle = ep_ptr;
-
- if (ep_ptr != NULL) {
- /* Assign valid EP fields: RSP and PSP_PROVIDER_FLAG only */
- if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {
- ep_ptr->param.ep_state =
- DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING;
- } else {
- /* RSP */
- dapl_os_assert(sp_ptr->header.handle_type ==
- DAT_HANDLE_TYPE_RSP);
- ep_ptr->param.ep_state =
- DAT_EP_STATE_PASSIVE_CONNECTION_PENDING;
- }
- ep_ptr->cm_handle = ib_cm_handle;
- }
-
- /* link the CR onto the SP so we can pick it up later */
- dapl_sp_link_cr(sp_ptr, cr_ptr);
-
- /* assign sp_ptr to union to avoid typecast errors from some compilers */
- sp_handle.psp_handle = (DAT_PSP_HANDLE) sp_ptr;
-
- /* Post the event. */
-
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
- event_ptr = dapli_evd_get_and_init_event(sp_ptr->evd_handle,
- event_number);
- if (event_ptr == NULL)
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
-
- event_ptr->event_data.cr_arrival_event_data.sp_handle = sp_handle;
- event_ptr->event_data.cr_arrival_event_data.local_ia_address_ptr =
- (DAT_IA_ADDRESS_PTR) & sp_ptr->header.owner_ia->hca_ptr->
- hca_address;
- event_ptr->event_data.cr_arrival_event_data.conn_qual =
- sp_ptr->conn_qual;
- event_ptr->event_data.cr_arrival_event_data.cr_handle =
- (DAT_HANDLE) cr_ptr;
-
- dapl_os_memcpy(&event_ptr->event_extension_data[0], ext_data, 64);
-
- dapli_evd_post_event(sp_ptr->evd_handle, event_ptr);
-
- return DAT_SUCCESS;
-}
-
-DAT_RETURN
-dapls_evd_post_connection_event_ext(IN DAPL_EVD * evd_ptr,
- IN DAT_EVENT_NUMBER event_number,
- IN DAT_EP_HANDLE ep_handle,
- IN DAT_COUNT private_data_size,
- IN DAT_PVOID private_data,
- IN DAT_PVOID ext_data)
-{
- DAT_EVENT *event_ptr;
- event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
- /*
- * Note event lock may be held on successful return
- * to be released by dapli_evd_post_event(), if provider side locking
- * is needed.
- */
- if (event_ptr == NULL)
- return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
- DAT_RESOURCE_MEMORY);
-
- event_ptr->event_data.connect_event_data.ep_handle = ep_handle;
- event_ptr->event_data.connect_event_data.private_data_size
- = private_data_size;
- event_ptr->event_data.connect_event_data.private_data = private_data;
-
- dapl_os_memcpy(&event_ptr->event_extension_data[0], ext_data, 64);
-
- dapli_evd_post_event(evd_ptr, event_ptr);
-
- return DAT_SUCCESS;
-}
-#endif
-
-/*
- * dapli_evd_cqe_to_event
- *
- * Convert a CQE into an event structure.
- *
- * Input:
- * evd_ptr
- * cqe_ptr
- *
- * Output:
- * event_ptr
- *
- * Returns:
- * none
- *
- */
-static void
-dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,
- IN void *cqe_ptr, OUT DAT_EVENT * event_ptr)
-{
- DAPL_EP *ep_ptr;
- DAPL_COOKIE *cookie;
- DAT_DTO_COMPLETION_STATUS dto_status;
- DAPL_COOKIE_BUFFER *buffer;
-
- /*
- * All that can be relied on if the status is bad is the status
- * and WRID.
- */
- dto_status = dapls_ib_get_dto_status(cqe_ptr);
-
- cookie = (DAPL_COOKIE *) (uintptr_t) DAPL_GET_CQE_WRID(cqe_ptr);
- dapl_os_assert((NULL != cookie));
-
- ep_ptr = cookie->ep;
- dapl_os_assert((NULL != ep_ptr));
- if (ep_ptr->header.magic != DAPL_MAGIC_EP) {
- /* ep may have been freed, just return */
- return;
- }
-
- dapls_io_trc_update_completion(ep_ptr, cookie, dto_status);
-
- event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;
-
- switch (cookie->type) {
- case DAPL_COOKIE_TYPE_DTO:
- {
-#ifdef DAT_EXTENSIONS
- /* Extended via request post or message receive */
- if ((cookie->val.dto.type == DAPL_DTO_TYPE_EXTENSION) ||
- (cookie->val.dto.type == DAPL_DTO_TYPE_RECV &&
- DAPL_GET_CQE_OPTYPE(cqe_ptr) != OP_RECEIVE)) {
- dapls_cqe_to_event_extension(ep_ptr, cookie,
- cqe_ptr,
- event_ptr);
- if (cookie->val.dto.type == DAPL_DTO_TYPE_RECV)
- dapls_cookie_dealloc(&ep_ptr->
- recv_buffer,
- cookie);
- else
- dapls_cookie_dealloc(&ep_ptr->
- req_buffer,
- cookie);
- break;
- }
-#endif
-
- if (DAPL_DTO_TYPE_RECV == cookie->val.dto.type)
- buffer = &ep_ptr->recv_buffer;
- else
- buffer = &ep_ptr->req_buffer;
-
- event_ptr->event_number = DAT_DTO_COMPLETION_EVENT;
- event_ptr->event_data.dto_completion_event_data.
- ep_handle = cookie->ep;
- event_ptr->event_data.dto_completion_event_data.
- user_cookie = cookie->val.dto.cookie;
- event_ptr->event_data.dto_completion_event_data.status =
- dto_status;
-
- if (cookie->val.dto.type == DAPL_DTO_TYPE_SEND ||
- cookie->val.dto.type == DAPL_DTO_TYPE_RDMA_WRITE) {
- /* Get size from DTO; CQE value may be off. */
- event_ptr->event_data.dto_completion_event_data.
- transfered_length = cookie->val.dto.size;
- } else {
- event_ptr->event_data.dto_completion_event_data.
- transfered_length =
- DAPL_GET_CQE_BYTESNUM(cqe_ptr);
- }
-
- dapls_cookie_dealloc(buffer, cookie);
- break;
- }
-
- case DAPL_COOKIE_TYPE_RMR:
- {
- event_ptr->event_number = DAT_RMR_BIND_COMPLETION_EVENT;
-
- event_ptr->event_data.rmr_completion_event_data.
- rmr_handle = cookie->val.rmr.rmr;
- event_ptr->event_data.rmr_completion_event_data.
- user_cookie = cookie->val.rmr.cookie;
- if (dto_status == DAT_DTO_SUCCESS) {
- event_ptr->event_data.rmr_completion_event_data.
- status = DAT_RMR_BIND_SUCCESS;
- dapl_os_assert((DAPL_GET_CQE_OPTYPE(cqe_ptr)) ==
- OP_BIND_MW);
- } else {
- dapl_dbg_log(DAPL_DBG_TYPE_DTO_COMP_ERR,
- " MW bind completion ERROR: %d: op %#x ep: %p\n",
- dto_status,
- DAPL_GET_CQE_OPTYPE(cqe_ptr),
- ep_ptr);
- event_ptr->event_data.rmr_completion_event_data.
- status = DAT_RMR_OPERATION_FAILED;
- dapl_os_atomic_dec(&cookie->val.rmr.rmr->lmr->
- lmr_ref_count);
- }
-
- dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);
- break;
- }
- default:
- {
- dapl_os_assert(!"Invalid Operation type");
- break;
- }
- } /* end switch */
-
- /*
- * Most error DTO ops result in disconnecting the EP. See
- * IBTA Vol 1.1, Chapter 10,Table 68, for expected effect on
- * state.
- */
- if ((dto_status != DAT_DTO_SUCCESS) &&
- (dto_status != DAT_DTO_ERR_FLUSHED)) {
- DAPL_EVD *evd_ptr;
-
- /*
- * If we are connected, generate disconnect and generate an
- * event. We may be racing with other disconnect ops, so we
- * need to check. We may also be racing CM connection events,
- * requiring us to check for connection pending states too.
- */
- dapl_os_lock(&ep_ptr->header.lock);
- if (ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED ||
- ep_ptr->param.ep_state ==
- DAT_EP_STATE_ACTIVE_CONNECTION_PENDING
- || ep_ptr->param.ep_state ==
- DAT_EP_STATE_PASSIVE_CONNECTION_PENDING
- || ep_ptr->param.ep_state ==
- DAT_EP_STATE_COMPLETION_PENDING)
- {
- ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
- dapl_os_unlock(&ep_ptr->header.lock);
- dapls_io_trc_dump(ep_ptr, cqe_ptr, dto_status);
-
- /* Let the other side know we have disconnected */
- (void)dapls_ib_disconnect(ep_ptr,
- DAT_CLOSE_ABRUPT_FLAG);
-
- /* ... and clean up the local side */
- evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;
- if (evd_ptr != NULL) {
- dapls_evd_post_connection_event(evd_ptr,
- DAT_CONNECTION_EVENT_BROKEN,
- (DAT_HANDLE)
- ep_ptr, 0, 0);
- }
- } else {
- dapl_os_unlock(&ep_ptr->header.lock);
- }
-
- dapl_log(DAPL_DBG_TYPE_ERR,
- "DTO completion ERR: status %d, op %s, vendor_err 0x%x - %s\n",
- DAPL_GET_CQE_STATUS(cqe_ptr),
- DAPL_GET_DTO_OP_STR(cookie->val.dto.type),
- DAPL_GET_CQE_VENDOR_ERR(cqe_ptr),
- inet_ntoa(((struct sockaddr_in *)&ep_ptr->
- remote_ia_address)->sin_addr));
- }
-}
-
-/*
- * dapls_evd_copy_cq
- *
- * Copy all entries on a CQ associated with the EVD onto that EVD
- * Up to caller to handle races, if any. Note that no EVD waiters will
- * be awoken by this copy.
- *
- * Input:
- * evd_ptr
- *
- * Output:
- * None
- *
- * Returns:
- * none
- *
- */
-void dapls_evd_copy_cq(DAPL_EVD * evd_ptr)
-{
- ib_work_completion_t cur_cqe;
- DAT_RETURN dat_status;
- DAT_EVENT *event;
-
- if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE) {
- /* Nothing to do if no CQ. */
- return;
- }
-
- while (1) {
- dat_status =
- dapls_ib_completion_poll(evd_ptr->header.owner_ia->hca_ptr,
- evd_ptr, &cur_cqe);
-
- if (dat_status != DAT_SUCCESS) {
- break;
- }
-
- /* For debugging. */
- dapli_evd_eh_print_cqe(&cur_cqe);
-
- /*
- * Can use DAT_DTO_COMPLETION_EVENT because dapli_evd_cqe_to_event
- * will overwrite.
- */
-
- event =
- dapli_evd_get_and_init_event(evd_ptr,
- DAT_DTO_COMPLETION_EVENT);
- if (event == NULL) {
- /* We've already attempted the overflow post; return. */
- return;
- }
-
- dapli_evd_cqe_to_event(evd_ptr, &cur_cqe, event);
-
- dapli_evd_post_event_nosignal(evd_ptr, event);
- }
-
- if (DAT_GET_TYPE(dat_status) != DAT_QUEUE_EMPTY) {
- dapl_dbg_log(DAPL_DBG_TYPE_EVD,
- "dapls_evd_copy_cq: dapls_ib_completion_poll returned 0x%x\n",
- dat_status);
- dapl_os_assert(!"Bad return from dapls_ib_completion_poll");
- }
-}
-
-/*
- * dapls_evd_cq_poll_to_event
- *
- * Attempt to dequeue a single CQE from a CQ and turn it into
- * an event.
- *
- * Input:
- * evd_ptr
- *
- * Output:
- * event
- *
- * Returns:
- * Status of operation
- *
- */
-DAT_RETURN
-dapls_evd_cq_poll_to_event(IN DAPL_EVD * evd_ptr, OUT DAT_EVENT * event)
-{
- DAT_RETURN dat_status;
- ib_work_completion_t cur_cqe;
-
- dat_status = dapls_ib_completion_poll(evd_ptr->header.owner_ia->hca_ptr,
- evd_ptr, &cur_cqe);
- if (dat_status == DAT_SUCCESS) {
- /* For debugging. */
- dapli_evd_eh_print_cqe(&cur_cqe);
-
- dapli_evd_cqe_to_event(evd_ptr, &cur_cqe, event);
- }
-
- return dat_status;
-}
-
-#ifdef DAPL_DBG_IO_TRC
-/*
- * Update I/O completions in the I/O trace buffer. I/O is posted to
- * the buffer, then we find it here using the cookie and mark it
- * completed with the completion status
- */
-void
-dapls_io_trc_update_completion(DAPL_EP * ep_ptr,
- DAPL_COOKIE * cookie,
- DAT_DTO_COMPLETION_STATUS dto_status)
-{
- int i;
- static unsigned int c_cnt = 1;
-
- for (i = 0; i < DBG_IO_TRC_QLEN; i++) {
- if (ep_ptr->ibt_base[i].cookie == cookie) {
- ep_ptr->ibt_base[i].status = dto_status;
- ep_ptr->ibt_base[i].done = c_cnt++;
- }
- }
-}
-
-/*
- * Dump the I/O trace buffers
- */
-void
-dapls_io_trc_dump(DAPL_EP * ep_ptr,
- void *cqe_ptr, DAT_DTO_COMPLETION_STATUS dto_status)
-{
- struct io_buf_track *ibt;
- int i;
- int cnt;
-
- dapl_os_printf("DISCONNECTING: dto_status = %x\n", dto_status);
- dapl_os_printf(" OpType = %x\n",
- DAPL_GET_CQE_OPTYPE(cqe_ptr));
- dapl_os_printf(" Bytes = %x\n",
- DAPL_GET_CQE_BYTESNUM(cqe_ptr));
- dapl_os_printf(" WRID (cookie) = %llx\n",
- DAPL_GET_CQE_WRID(cqe_ptr));
-
- if (ep_ptr->ibt_dumped == 0) {
-
- dapl_os_printf("EP %p (qpn %d) I/O trace buffer\n",
- ep_ptr, ep_ptr->qpn);
-
- ep_ptr->ibt_dumped = 1;
- ibt =
- (struct io_buf_track *)dapls_rbuf_remove(&ep_ptr->
- ibt_queue);
- cnt = DBG_IO_TRC_QLEN;
- while (ibt != NULL && cnt > 0) {
- dapl_os_printf
- ("%2d. %3s (%2d, %d) OP: %x cookie %p wqe %p rmv_target_addr %llx rmv_rmr_context %x\n",
- cnt, ibt->done == 0 ? "WRK" : "DON", ibt->status,
- ibt->done, ibt->op_type, ibt->cookie, ibt->wqe,
- ibt->remote_iov.target_address,
- ibt->remote_iov.rmr_context);
- for (i = 0; i < 3; i++) {
- if (ibt->iov[i].segment_length != 0) {
- dapl_os_printf
- (" (%4llx, %8x, %8llx)\n",
- ibt->iov[i].segment_length,
- ibt->iov[i].lmr_context,
- ibt->iov[i].virtual_address);
- }
- }
- ibt =
- (struct io_buf_track *)dapls_rbuf_remove(&ep_ptr->
- ibt_queue);
- cnt--;
- }
- }
-}
-#endif /* DAPL_DBG_IO_TRC */
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
+/*\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_evd_util.c\r
+ *\r
+ * PURPOSE: Manage EVD Info structure\r
+ *\r
+ * $Id: dapl_evd_util.c 1410 2006-07-19 17:12:02Z ardavis $\r
+ **********************************************************************/\r
+\r
+#include "dapl_evd_util.h"\r
+#include "dapl_ia_util.h"\r
+#include "dapl_cno_util.h"\r
+#include "dapl_ring_buffer_util.h"\r
+#include "dapl_adapter_util.h"\r
+#include "dapl_cookie.h"\r
+#include "dapl.h"\r
+#include "dapl_cr_util.h"\r
+#include "dapl_sp_util.h"\r
+#include "dapl_ep_util.h"\r
+\r
+STATIC _INLINE_ void dapli_evd_eh_print_cqe(IN ib_work_completion_t * cqe);\r
+\r
+DAT_RETURN dapli_evd_event_alloc(IN DAPL_EVD * evd_ptr, IN DAT_COUNT qlen);\r
+\r
+char *dapl_event_str(IN DAT_EVENT_NUMBER event_num)\r
+{\r
+#if defined(DAPL_DBG)\r
+ struct dat_event_str {\r
+ char *str;\r
+ DAT_EVENT_NUMBER num;\r
+ };\r
+ static struct dat_event_str events[] = {\r
+ {"DAT_DTO_COMPLETION_EVENT", DAT_DTO_COMPLETION_EVENT},\r
+ {"DAT_RMR_BIND_COMPLETION_EVENT",\r
+ DAT_RMR_BIND_COMPLETION_EVENT},\r
+ {"DAT_CONNECTION_REQUEST_EVENT", DAT_CONNECTION_REQUEST_EVENT},\r
+ {"DAT_CONNECTION_EVENT_ESTABLISHED",\r
+ DAT_CONNECTION_EVENT_ESTABLISHED},\r
+ {"DAT_CONNECTION_EVENT_PEER_REJECTED",\r
+ DAT_CONNECTION_EVENT_PEER_REJECTED},\r
+ {"DAT_CONNECTION_EVENT_NON_PEER_REJECTED",\r
+ DAT_CONNECTION_EVENT_NON_PEER_REJECTED},\r
+ {"DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR",\r
+ DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR},\r
+ {"DAT_CONNECTION_EVENT_DISCONNECTED",\r
+ DAT_CONNECTION_EVENT_DISCONNECTED},\r
+ {"DAT_CONNECTION_EVENT_BROKEN", DAT_CONNECTION_EVENT_BROKEN},\r
+ {"DAT_CONNECTION_EVENT_TIMED_OUT",\r
+ DAT_CONNECTION_EVENT_TIMED_OUT},\r
+ {"DAT_CONNECTION_EVENT_UNREACHABLE",\r
+ DAT_CONNECTION_EVENT_UNREACHABLE},\r
+ {"DAT_ASYNC_ERROR_EVD_OVERFLOW", DAT_ASYNC_ERROR_EVD_OVERFLOW},\r
+ {"DAT_ASYNC_ERROR_IA_CATASTROPHIC",\r
+ DAT_ASYNC_ERROR_IA_CATASTROPHIC},\r
+ {"DAT_ASYNC_ERROR_EP_BROKEN", DAT_ASYNC_ERROR_EP_BROKEN},\r
+ {"DAT_ASYNC_ERROR_TIMED_OUT", DAT_ASYNC_ERROR_TIMED_OUT},\r
+ {"DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR",\r
+ DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR},\r
+ {"DAT_HA_DOWN_TO_1", DAT_HA_DOWN_TO_1},\r
+ {"DAT_HA_UP_TO_MULTI_PATH", DAT_HA_UP_TO_MULTI_PATH},\r
+ {"DAT_SOFTWARE_EVENT", DAT_SOFTWARE_EVENT},\r
+#ifdef DAT_EXTENSIONS\r
+ {"DAT_EXTENSION_EVENT", DAT_EXTENSION_EVENT},\r
+ {"DAT_IB_EXTENSION_RANGE_BASE", DAT_IB_EXTENSION_RANGE_BASE},\r
+ {"DAT_IB_UD_CONNECTION_REQUEST_EVENT",\r
+ DAT_IB_EXTENSION_RANGE_BASE + 1},\r
+ {"DAT_IB_UD_CONNECTION_EVENT_ESTABLISHED",\r
+ DAT_IB_EXTENSION_RANGE_BASE + 2},\r
+ {"DAT_IW_EXTENSION_RANGE_BASE", DAT_IW_EXTENSION_RANGE_BASE},\r
+#endif /* DAT_EXTENSIONS */\r
+ {NULL, 0},\r
+ };\r
+ int i;\r
+\r
+ for (i = 0; events[i].str; i++) {\r
+ if (events[i].num == event_num)\r
+ return events[i].str;\r
+ }\r
+ return "Unknown DAT event?";\r
+#else\r
+ static char str[16];\r
+ sprintf(str, "%x", event_num);\r
+ return str;\r
+#endif\r
+}\r
+\r
+/*\r
+ * dapls_evd_internal_create\r
+ *\r
+ * actually create the evd. this is called after all parameter checking\r
+ * has been performed in dapl_ep_create. it is also called from dapl_ia_open\r
+ * to create the default async evd.\r
+ *\r
+ * Input:\r
+ * ia_ptr\r
+ * cno_ptr\r
+ * qlen\r
+ * evd_flags\r
+ *\r
+ * Output:\r
+ * evd_ptr_ptr\r
+ *\r
+ * Returns:\r
+ * none\r
+ *\r
+ */\r
+\r
+DAT_RETURN\r
+dapls_evd_internal_create(DAPL_IA * ia_ptr,\r
+ DAPL_CNO * cno_ptr,\r
+ DAT_COUNT min_qlen,\r
+ DAT_EVD_FLAGS evd_flags, DAPL_EVD ** evd_ptr_ptr)\r
+{\r
+ DAPL_EVD *evd_ptr;\r
+ DAT_COUNT cq_len;\r
+ DAT_RETURN dat_status;\r
+\r
+ dat_status = DAT_SUCCESS;\r
+ *evd_ptr_ptr = NULL;\r
+ cq_len = min_qlen;\r
+\r
+ evd_ptr = dapls_evd_alloc(ia_ptr, cno_ptr, evd_flags, min_qlen);\r
+ if (!evd_ptr) {\r
+ dat_status =\r
+ DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);\r
+ goto bail;\r
+ }\r
+\r
+ /*\r
+ * If we are dealing with event streams besides a CQ event stream,\r
+ * be conservative and set producer side locking. Otherwise, no.\r
+ */\r
+ evd_ptr->evd_producer_locking_needed =\r
+ !(evd_flags & (DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG));\r
+\r
+ /* Before we setup any callbacks, transition state to OPEN. */\r
+ evd_ptr->evd_state = DAPL_EVD_STATE_OPEN;\r
+\r
+ if (evd_flags & DAT_EVD_ASYNC_FLAG) {\r
+ /*\r
+ * There is no cq associate with async evd. Set it to invalid\r
+ */\r
+ evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;\r
+\r
+ } else if (0 != (evd_flags & ~(DAT_EVD_SOFTWARE_FLAG\r
+ | DAT_EVD_CONNECTION_FLAG\r
+ | DAT_EVD_CR_FLAG))) {\r
+#if defined(_VENDOR_IBAL_)\r
+ /* \r
+ * The creation of CQ required a PD (PZ) associated with it and\r
+ * we do not have a PD here; therefore, the work-around is that we\r
+ * will postpone the creation of the cq till the creation of QP which\r
+ * this cq will associate with.\r
+ */\r
+ evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;\r
+#else\r
+ dat_status = dapls_ib_cq_alloc(ia_ptr, evd_ptr, &cq_len);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+\r
+ /* Now reset the cq_len in the attributes, it may have changed */\r
+ evd_ptr->qlen = cq_len;\r
+\r
+ dat_status =\r
+ dapls_ib_setup_async_callback(ia_ptr,\r
+ DAPL_ASYNC_CQ_COMPLETION,\r
+ evd_ptr,\r
+ (ib_async_handler_t)\r
+ dapl_evd_dto_callback,\r
+ evd_ptr);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+\r
+ dat_status = dapls_set_cq_notify(ia_ptr, evd_ptr);\r
+\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+#endif /* _VENDOR_IBAL_ */\r
+ }\r
+\r
+ /* We now have an accurate count of events, so allocate them into\r
+ * the EVD\r
+ */\r
+ dat_status = dapli_evd_event_alloc(evd_ptr, cq_len);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+\r
+ dapl_ia_link_evd(ia_ptr, evd_ptr);\r
+ *evd_ptr_ptr = evd_ptr;\r
+\r
+ bail:\r
+ if (dat_status != DAT_SUCCESS) {\r
+ if (evd_ptr) {\r
+ dapls_evd_dealloc(evd_ptr);\r
+ }\r
+ }\r
+\r
+ return dat_status;\r
+}\r
+\r
+/*\r
+ * dapls_evd_alloc\r
+ *\r
+ * alloc and initialize an EVD struct\r
+ *\r
+ * Input:\r
+ * ia\r
+ *\r
+ * Output:\r
+ * evd_ptr\r
+ *\r
+ * Returns:\r
+ * none\r
+ *\r
+ */\r
+DAPL_EVD *dapls_evd_alloc(IN DAPL_IA * ia_ptr,\r
+ IN DAPL_CNO * cno_ptr,\r
+ IN DAT_EVD_FLAGS evd_flags, IN DAT_COUNT qlen)\r
+{\r
+ DAPL_EVD *evd_ptr;\r
+\r
+ /* Allocate EVD */\r
+ evd_ptr = (DAPL_EVD *) dapl_os_alloc(sizeof(DAPL_EVD));\r
+ if (!evd_ptr) {\r
+ goto bail;\r
+ }\r
+\r
+ /* zero the structure */\r
+ dapl_os_memzero(evd_ptr, sizeof(DAPL_EVD));\r
+\r
+#ifdef DAPL_COUNTERS\r
+ /* Allocate counters */\r
+ evd_ptr->cntrs =\r
+ dapl_os_alloc(sizeof(DAT_UINT64) * DCNT_EVD_ALL_COUNTERS);\r
+ if (evd_ptr->cntrs == NULL) {\r
+ dapl_os_free(evd_ptr, sizeof(DAPL_EVD));\r
+ return (NULL);\r
+ }\r
+ dapl_os_memzero(evd_ptr->cntrs,\r
+ sizeof(DAT_UINT64) * DCNT_EVD_ALL_COUNTERS);\r
+#endif /* DAPL_COUNTERS */\r
+\r
+ /*\r
+ * initialize the header\r
+ */\r
+ evd_ptr->header.provider = ia_ptr->header.provider;\r
+ evd_ptr->header.magic = DAPL_MAGIC_EVD;\r
+ evd_ptr->header.handle_type = DAT_HANDLE_TYPE_EVD;\r
+ evd_ptr->header.owner_ia = ia_ptr;\r
+ evd_ptr->header.user_context.as_64 = 0;\r
+ evd_ptr->header.user_context.as_ptr = NULL;\r
+ dapl_llist_init_entry(&evd_ptr->header.ia_list_entry);\r
+ dapl_os_lock_init(&evd_ptr->header.lock);\r
+\r
+ /*\r
+ * Initialize the body\r
+ */\r
+ evd_ptr->evd_state = DAPL_EVD_STATE_INITIAL;\r
+ evd_ptr->evd_flags = evd_flags;\r
+ evd_ptr->evd_enabled = DAT_TRUE;\r
+ evd_ptr->evd_waitable = DAT_TRUE;\r
+ evd_ptr->evd_producer_locking_needed = 1; /* Conservative value. */\r
+ evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;\r
+ dapl_os_atomic_set(&evd_ptr->evd_ref_count, 0);\r
+ evd_ptr->catastrophic_overflow = DAT_FALSE;\r
+ evd_ptr->qlen = qlen;\r
+ evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD; /* FIXME: should be DAPL_EVD_STATE_INIT */\r
+ dapl_os_wait_object_init(&evd_ptr->wait_object);\r
+\r
+ evd_ptr->cno_active_count = 0;\r
+ if (cno_ptr != NULL) {\r
+ /* Take a reference count on the CNO */\r
+ dapl_os_atomic_inc(&cno_ptr->cno_ref_count);\r
+ }\r
+ evd_ptr->cno_ptr = cno_ptr;\r
+\r
+ bail:\r
+ return evd_ptr;\r
+}\r
+\r
+/*\r
+ * dapls_evd_event_alloc\r
+ *\r
+ * alloc events into an EVD.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * qlen\r
+ *\r
+ * Output:\r
+ * NONE\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * ERROR\r
+ *\r
+ */\r
+DAT_RETURN dapli_evd_event_alloc(IN DAPL_EVD * evd_ptr, IN DAT_COUNT qlen)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+ DAT_COUNT i;\r
+ DAT_RETURN dat_status;\r
+\r
+ dat_status = DAT_SUCCESS;\r
+\r
+ /* Allocate EVENTs */\r
+ event_ptr =\r
+ (DAT_EVENT *) dapl_os_alloc(evd_ptr->qlen * sizeof(DAT_EVENT));\r
+ if (event_ptr == NULL) {\r
+ dat_status =\r
+ DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);\r
+ goto bail;\r
+ }\r
+ evd_ptr->events = event_ptr;\r
+\r
+ /* allocate free event queue */\r
+ dat_status = dapls_rbuf_alloc(&evd_ptr->free_event_queue, qlen);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+\r
+ /* allocate pending event queue */\r
+ dat_status = dapls_rbuf_alloc(&evd_ptr->pending_event_queue, qlen);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+\r
+ /* add events to free event queue */\r
+ for (i = 0; i < evd_ptr->qlen; i++) {\r
+ dapls_rbuf_add(&evd_ptr->free_event_queue, (void *)event_ptr);\r
+ event_ptr++;\r
+ }\r
+\r
+ evd_ptr->cq_notified = DAT_FALSE;\r
+ evd_ptr->cq_notified_when = 0;\r
+ evd_ptr->threshold = 0;\r
+\r
+ bail:\r
+ return dat_status;\r
+}\r
+\r
+/*\r
+ * dapls_evd_event_realloc\r
+ *\r
+ * realloc events into an EVD.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * qlen\r
+ *\r
+ * Output:\r
+ * NONE\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * ERROR\r
+ *\r
+ */\r
+DAT_RETURN dapls_evd_event_realloc(IN DAPL_EVD * evd_ptr, IN DAT_COUNT qlen)\r
+{\r
+ DAT_EVENT *events;\r
+ DAT_COUNT old_qlen;\r
+ DAT_COUNT i;\r
+ intptr_t diff;\r
+ DAT_RETURN dat_status;\r
+\r
+ /* Allocate EVENTs */\r
+ events = (DAT_EVENT *) dapl_os_realloc(evd_ptr->events,\r
+ qlen * sizeof(DAT_EVENT));\r
+ if (NULL == events) {\r
+ dat_status =\r
+ DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY);\r
+ goto bail;\r
+ }\r
+\r
+ diff = events - evd_ptr->events;\r
+ evd_ptr->events = events;\r
+\r
+ old_qlen = evd_ptr->qlen;\r
+ evd_ptr->qlen = qlen;\r
+\r
+ /* reallocate free event queue */\r
+ dat_status = dapls_rbuf_realloc(&evd_ptr->free_event_queue, qlen);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+ dapls_rbuf_adjust(&evd_ptr->free_event_queue, diff);\r
+\r
+ /* reallocate pending event queue */\r
+ dat_status = dapls_rbuf_realloc(&evd_ptr->pending_event_queue, qlen);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+ dapls_rbuf_adjust(&evd_ptr->pending_event_queue, diff);\r
+\r
+ /*\r
+ * add new events to free event queue. \r
+ */\r
+ for (i = old_qlen; i < qlen; i++) {\r
+ dapls_rbuf_add(&evd_ptr->free_event_queue, (void *)&events[i]);\r
+ }\r
+\r
+ bail:\r
+ return dat_status;\r
+}\r
+\r
+/*\r
+ * dapls_evd_dealloc\r
+ *\r
+ * Free the passed in EVD structure. If an error occurs, this function\r
+ * will clean up all of the internal data structures and report the\r
+ * error.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * status\r
+ *\r
+ */\r
+DAT_RETURN dapls_evd_dealloc(IN DAPL_EVD * evd_ptr)\r
+{\r
+ DAT_RETURN dat_status;\r
+ DAPL_IA *ia_ptr;\r
+\r
+ dat_status = DAT_SUCCESS;\r
+\r
+ dapl_os_assert(evd_ptr->header.magic == DAPL_MAGIC_EVD);\r
+ dapl_os_assert(dapl_os_atomic_read(&evd_ptr->evd_ref_count) == 0);\r
+\r
+ /*\r
+ * Destroy the CQ first, to keep any more callbacks from coming\r
+ * up from it.\r
+ */\r
+ evd_ptr->evd_enabled = DAT_FALSE;\r
+ if (evd_ptr->ib_cq_handle != IB_INVALID_HANDLE) {\r
+ ia_ptr = evd_ptr->header.owner_ia;\r
+\r
+ dat_status = dapls_ib_cq_free(ia_ptr, evd_ptr);\r
+ if (dat_status != DAT_SUCCESS) {\r
+ goto bail;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * We should now be safe to invalidate the EVD; reset the\r
+ * magic to prevent reuse.\r
+ */\r
+ evd_ptr->header.magic = DAPL_MAGIC_INVALID;\r
+\r
+ /* Release reference on the CNO if it exists */\r
+ if (evd_ptr->cno_ptr != NULL) {\r
+ dapl_os_atomic_dec(&evd_ptr->cno_ptr->cno_ref_count);\r
+ evd_ptr->cno_ptr = NULL;\r
+ }\r
+\r
+ /* If the ring buffer allocation failed, then the dapls_rbuf_destroy */\r
+ /* function will detect that the ring buffer's internal data (ex. base */\r
+ /* pointer) are invalid and will handle the situation appropriately */\r
+ dapls_rbuf_destroy(&evd_ptr->free_event_queue);\r
+ dapls_rbuf_destroy(&evd_ptr->pending_event_queue);\r
+\r
+ if (evd_ptr->events) {\r
+ dapl_os_free(evd_ptr->events,\r
+ evd_ptr->qlen * sizeof(DAT_EVENT));\r
+ }\r
+\r
+ dapl_os_wait_object_destroy(&evd_ptr->wait_object);\r
+\r
+#ifdef DAPL_COUNTERS\r
+ dapl_os_free(evd_ptr->cntrs,\r
+ sizeof(DAT_UINT64) * DCNT_EVD_ALL_COUNTERS);\r
+#endif /* DAPL_COUNTERS */\r
+\r
+ dapl_os_free(evd_ptr, sizeof(DAPL_EVD));\r
+\r
+ bail:\r
+ return dat_status;\r
+}\r
+\r
+STATIC _INLINE_ char *DAPL_GET_DTO_OP_STR(int op)\r
+{\r
+ static char *dto_ops[] = {\r
+ "OP_SEND",\r
+ "OP_RECEIVE",\r
+ "OP_RDMA_WRITE",\r
+ "OP_RDMA_READ"\r
+ };\r
+ return ((op < 0 || op > 3) ? "Invalid DTO OP?" : dto_ops[op]);\r
+}\r
+\r
+#if !defined(DAPL_GET_CQE_OP_STR)\r
+#define DAPL_GET_CQE_OP_STR(e) "Unknown CEQ OP String?"\r
+#endif\r
+#if !defined(DAPL_GET_CQE_VENDOR_ERR)\r
+#define DAPL_GET_CQE_VENDOR_ERR(e) 0\r
+#endif\r
+\r
+/*\r
+ * dapli_evd_eh_print_cqe\r
+ *\r
+ * Input:\r
+ * cqe_ptr\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Prints out a CQE for debug purposes\r
+ *\r
+ */\r
+\r
+void dapli_evd_eh_print_cqe(IN ib_work_completion_t * cqe_ptr)\r
+{\r
+#ifdef DAPL_DBG\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t >>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<\n");\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t dapl_evd_dto_callback : CQE \n");\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t\t work_req_id %lli\n", DAPL_GET_CQE_WRID(cqe_ptr));\r
+ if (DAPL_GET_CQE_STATUS(cqe_ptr) == 0) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t\t op_type: %s\n",\r
+ DAPL_GET_CQE_OP_STR(cqe_ptr));\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t\t bytes_num %d\n",\r
+ DAPL_GET_CQE_BYTESNUM(cqe_ptr));\r
+ }\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t\t status %d vendor_err 0x%x\n",\r
+ DAPL_GET_CQE_STATUS(cqe_ptr),\r
+ DAPL_GET_CQE_VENDOR_ERR(cqe_ptr));\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,\r
+ "\t >>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<\n");\r
+#endif\r
+ return;\r
+}\r
+\r
+/*\r
+ * Event posting code follows.\r
+ */\r
+\r
+/*\r
+ * These next two functions (dapli_evd_get_event and dapli_evd_post_event)\r
+ * are a pair. They are always called together, from one of the functions\r
+ * at the end of this file (dapl_evd_post_*_event).\r
+ *\r
+ * Note that if producer side locking is enabled, the first one takes the\r
+ * EVD lock and the second releases it.\r
+ */\r
+\r
+/* dapli_evd_get_event\r
+ *\r
+ * Get an event struct from the evd. The caller should fill in the event\r
+ * and call dapl_evd_post_event.\r
+ *\r
+ * If there are no events available, an overflow event is generated to the\r
+ * async EVD handler.\r
+ *\r
+ * If this EVD required producer locking, a successful return implies\r
+ * that the lock is held.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ *\r
+ * Output:\r
+ * event\r
+ *\r
+ */\r
+\r
+static DAT_EVENT *dapli_evd_get_event(DAPL_EVD * evd_ptr)\r
+{\r
+ DAT_EVENT *event;\r
+\r
+ if (evd_ptr->evd_producer_locking_needed) {\r
+ dapl_os_lock(&evd_ptr->header.lock);\r
+ }\r
+\r
+ event = (DAT_EVENT *) dapls_rbuf_remove(&evd_ptr->free_event_queue);\r
+\r
+ /* Release the lock if it was taken and the call failed. */\r
+ if (!event && evd_ptr->evd_producer_locking_needed) {\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+ }\r
+\r
+ return event;\r
+}\r
+\r
+/* dapli_evd_post_event\r
+ *\r
+ * Post the <event> to the evd. If possible, invoke the evd's CNO.\r
+ * Otherwise post the event on the pending queue.\r
+ *\r
+ * If producer side locking is required, the EVD lock must be held upon\r
+ * entry to this function.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * event\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ */\r
+\r
+static void\r
+dapli_evd_post_event(IN DAPL_EVD * evd_ptr, IN const DAT_EVENT * event_ptr)\r
+{\r
+ DAT_RETURN dat_status;\r
+ DAPL_CNO *cno_to_trigger = NULL;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_EVD, "%s: Called with event %s\n",\r
+ __FUNCTION__, dapl_event_str(event_ptr->event_number));\r
+\r
+ dat_status = dapls_rbuf_add(&evd_ptr->pending_event_queue,\r
+ (void *)event_ptr);\r
+ dapl_os_assert(dat_status == DAT_SUCCESS);\r
+\r
+ dapl_os_assert(evd_ptr->evd_state == DAPL_EVD_STATE_WAITED\r
+ || evd_ptr->evd_state == DAPL_EVD_STATE_OPEN);\r
+\r
+ if (evd_ptr->evd_state == DAPL_EVD_STATE_OPEN) {\r
+ /* No waiter. Arrange to trigger a CNO if it exists. */\r
+\r
+ if (evd_ptr->evd_enabled) {\r
+ cno_to_trigger = evd_ptr->cno_ptr;\r
+ }\r
+ if (evd_ptr->evd_producer_locking_needed) {\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+ }\r
+ } else {\r
+ /*\r
+ * We're in DAPL_EVD_STATE_WAITED. Take the lock if\r
+ * we don't have it, recheck, and signal.\r
+ */\r
+ if (!evd_ptr->evd_producer_locking_needed) {\r
+ dapl_os_lock(&evd_ptr->header.lock);\r
+ }\r
+\r
+ if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED\r
+ && (dapls_rbuf_count(&evd_ptr->pending_event_queue)\r
+ >= evd_ptr->threshold)) {\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+\r
+ if (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG)) {\r
+ dapls_evd_dto_wakeup(evd_ptr);\r
+ } else {\r
+ dapl_os_wait_object_wakeup(&evd_ptr->wait_object);\r
+ }\r
+\r
+ } else {\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+ }\r
+ }\r
+\r
+ if (cno_to_trigger != NULL) {\r
+ dapl_internal_cno_trigger(cno_to_trigger, evd_ptr);\r
+ }\r
+}\r
+\r
+/* dapli_evd_post_event_nosignal\r
+ *\r
+ * Post the <event> to the evd. Do not do any wakeup processing.\r
+ * This function should only be called if it is known that there are\r
+ * no waiters that it is appropriate to wakeup on this EVD. An example\r
+ * of such a situation is during internal dat_evd_wait() processing.\r
+ *\r
+ * If producer side locking is required, the EVD lock must be held upon\r
+ * entry to this function.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * event\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ */\r
+\r
+static void\r
+dapli_evd_post_event_nosignal(IN DAPL_EVD * evd_ptr,\r
+ IN const DAT_EVENT * event_ptr)\r
+{\r
+ DAT_RETURN dat_status;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_EVD, "%s: Called with event %s\n",\r
+ __FUNCTION__, dapl_event_str(event_ptr->event_number));\r
+\r
+ dat_status = dapls_rbuf_add(&evd_ptr->pending_event_queue,\r
+ (void *)event_ptr);\r
+ dapl_os_assert(dat_status == DAT_SUCCESS);\r
+\r
+ dapl_os_assert(evd_ptr->evd_state == DAPL_EVD_STATE_WAITED\r
+ || evd_ptr->evd_state == DAPL_EVD_STATE_OPEN);\r
+\r
+ if (evd_ptr->evd_producer_locking_needed) {\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+ }\r
+}\r
+\r
+/* dapli_evd_format_overflow_event\r
+ *\r
+ * format an overflow event for posting\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * event_ptr\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ */\r
+static void\r
+dapli_evd_format_overflow_event(IN DAPL_EVD * evd_ptr,\r
+ OUT DAT_EVENT * event_ptr)\r
+{\r
+ DAPL_IA *ia_ptr;\r
+\r
+ ia_ptr = evd_ptr->header.owner_ia;\r
+\r
+ event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;\r
+ event_ptr->event_number = DAT_ASYNC_ERROR_EVD_OVERFLOW;\r
+ event_ptr->event_data.asynch_error_event_data.dat_handle =\r
+ (DAT_HANDLE) ia_ptr;\r
+}\r
+\r
+/* dapli_evd_post_overflow_event\r
+ *\r
+ * post an overflow event\r
+ *\r
+ * Input:\r
+ * async_evd_ptr\r
+ * evd_ptr\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ */\r
+static void\r
+dapli_evd_post_overflow_event(IN DAPL_EVD * async_evd_ptr,\r
+ IN DAPL_EVD * overflow_evd_ptr)\r
+{\r
+ DAT_EVENT *overflow_event;\r
+\r
+ /* The overflow_evd_ptr mght be the same as evd.\r
+ * In that case we've got a catastrophic overflow.\r
+ */\r
+ dapl_log(DAPL_DBG_TYPE_WARN,\r
+ " WARNING: overflow event on EVD %p/n", overflow_evd_ptr);\r
+\r
+ if (async_evd_ptr == overflow_evd_ptr) {\r
+ async_evd_ptr->catastrophic_overflow = DAT_TRUE;\r
+ async_evd_ptr->evd_state = DAPL_EVD_STATE_DEAD;\r
+ return;\r
+ }\r
+\r
+ overflow_event = dapli_evd_get_event(overflow_evd_ptr);\r
+ if (!overflow_event) {\r
+ /* this is not good */\r
+ overflow_evd_ptr->catastrophic_overflow = DAT_TRUE;\r
+ overflow_evd_ptr->evd_state = DAPL_EVD_STATE_DEAD;\r
+ return;\r
+ }\r
+ dapli_evd_format_overflow_event(overflow_evd_ptr, overflow_event);\r
+ dapli_evd_post_event(overflow_evd_ptr, overflow_event);\r
+\r
+ return;\r
+}\r
+\r
+static DAT_EVENT *dapli_evd_get_and_init_event(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+\r
+ event_ptr = dapli_evd_get_event(evd_ptr);\r
+ if (NULL == event_ptr) {\r
+ dapli_evd_post_overflow_event(evd_ptr->header.owner_ia->\r
+ async_error_evd, evd_ptr);\r
+ } else {\r
+ event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;\r
+ event_ptr->event_number = event_number;\r
+ }\r
+\r
+ return event_ptr;\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_post_cr_arrival_event(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN DAT_SP_HANDLE sp_handle,\r
+ DAT_IA_ADDRESS_PTR ia_address_ptr,\r
+ DAT_CONN_QUAL conn_qual,\r
+ DAT_CR_HANDLE cr_handle)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+ event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+\r
+ if (event_ptr == NULL) {\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+ }\r
+\r
+ event_ptr->event_data.cr_arrival_event_data.sp_handle = sp_handle;\r
+ event_ptr->event_data.cr_arrival_event_data.local_ia_address_ptr\r
+ = ia_address_ptr;\r
+ event_ptr->event_data.cr_arrival_event_data.conn_qual = conn_qual;\r
+ event_ptr->event_data.cr_arrival_event_data.cr_handle = cr_handle;\r
+\r
+ dapli_evd_post_event(evd_ptr, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_post_connection_event(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN DAT_EP_HANDLE ep_handle,\r
+ IN DAT_COUNT private_data_size,\r
+ IN DAT_PVOID private_data)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+ event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+\r
+ if (event_ptr == NULL) {\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+ }\r
+\r
+ event_ptr->event_data.connect_event_data.ep_handle = ep_handle;\r
+ event_ptr->event_data.connect_event_data.private_data_size\r
+ = private_data_size;\r
+ event_ptr->event_data.connect_event_data.private_data = private_data;\r
+\r
+ dapli_evd_post_event(evd_ptr, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_post_async_error_event(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN DAT_IA_HANDLE ia_handle)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+ event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+ dapl_log(DAPL_DBG_TYPE_WARN,\r
+ " WARNING: async event - %s evd=%p/n",\r
+ dapl_event_str(event_number), evd_ptr);\r
+\r
+ if (event_ptr == NULL) {\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+ }\r
+\r
+ event_ptr->event_data.asynch_error_event_data.dat_handle =\r
+ (DAT_HANDLE) ia_handle;\r
+\r
+ dapli_evd_post_event(evd_ptr, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_post_software_event(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN DAT_PVOID pointer)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+ event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+\r
+ if (event_ptr == NULL) {\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+ }\r
+\r
+ event_ptr->event_data.software_event_data.pointer = pointer;\r
+\r
+ dapli_evd_post_event(evd_ptr, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+/*\r
+ * dapls_evd_post_generic_event\r
+ *\r
+ * Post a generic event type. Not used by all providers\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * event_number\r
+ * data\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_evd_post_generic_event(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN DAT_EVENT_DATA * data)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+\r
+ event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+\r
+ if (event_ptr == NULL) {\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+ }\r
+\r
+ event_ptr->event_data = *data;\r
+\r
+ dapli_evd_post_event(evd_ptr, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+#ifdef DAT_EXTENSIONS\r
+DAT_RETURN\r
+dapls_evd_post_cr_event_ext(IN DAPL_SP * sp_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN dp_ib_cm_handle_t ib_cm_handle,\r
+ IN DAT_COUNT p_size,\r
+ IN DAT_PVOID p_data, IN DAT_PVOID ext_data)\r
+{\r
+ DAPL_CR *cr_ptr;\r
+ DAPL_EP *ep_ptr;\r
+ DAT_EVENT *event_ptr;\r
+ DAT_SP_HANDLE sp_handle;\r
+\r
+ dapl_os_lock(&sp_ptr->header.lock);\r
+ if (sp_ptr->listening == DAT_FALSE) {\r
+ dapl_os_unlock(&sp_ptr->header.lock);\r
+ dapl_dbg_log(DAPL_DBG_TYPE_CM,\r
+ "---> post_cr_event_ext: conn event on down SP\n");\r
+ (void)dapls_ib_reject_connection(ib_cm_handle,\r
+ DAT_CONNECTION_EVENT_UNREACHABLE,\r
+ 0, NULL);\r
+ return DAT_CONN_QUAL_UNAVAILABLE;\r
+ }\r
+\r
+ /*\r
+ * RSP connections only allow a single connection. Close\r
+ * it down NOW so we reject any further connections.\r
+ */\r
+ if (sp_ptr->header.handle_type == DAT_HANDLE_TYPE_RSP)\r
+ sp_ptr->listening = DAT_FALSE;\r
+\r
+ dapl_os_unlock(&sp_ptr->header.lock);\r
+\r
+ /* allocate new connect request */\r
+ cr_ptr = dapls_cr_alloc(sp_ptr->header.owner_ia);\r
+ if (cr_ptr == NULL)\r
+ return DAT_INSUFFICIENT_RESOURCES;\r
+\r
+ /* Set up the CR */\r
+ cr_ptr->sp_ptr = sp_ptr; /* maintain sp_ptr in case of reject */\r
+ cr_ptr->param.remote_port_qual = 0;\r
+ cr_ptr->ib_cm_handle = ib_cm_handle;\r
+ cr_ptr->param.remote_ia_address_ptr =\r
+ (DAT_IA_ADDRESS_PTR) & cr_ptr->remote_ia_address;\r
+\r
+ /*\r
+ * Copy the remote address and private data out of the private_data\r
+ */\r
+ cr_ptr->param.private_data = cr_ptr->private_data;\r
+ cr_ptr->param.private_data_size = p_size;\r
+ if (p_size)\r
+ dapl_os_memcpy(cr_ptr->private_data, p_data, p_size);\r
+\r
+ /* EP will be NULL unless RSP service point */\r
+ ep_ptr = (DAPL_EP *) sp_ptr->ep_handle;\r
+\r
+ if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {\r
+ DAPL_IA *ia_ptr;\r
+ /*\r
+ * Never true for RSP connections\r
+ *\r
+ * Create an EP for the user. If we can't allocate an\r
+ * EP we are out of resources and need to tell the\r
+ * requestor that we cant help them.\r
+ */\r
+ ia_ptr = sp_ptr->header.owner_ia;\r
+ ep_ptr = dapl_ep_alloc(ia_ptr, NULL);\r
+ if (ep_ptr == NULL) {\r
+ dapls_cr_free(cr_ptr);\r
+ /* Invoking function will call dapls_ib_cm_reject() */\r
+ return DAT_INSUFFICIENT_RESOURCES;\r
+ }\r
+ ep_ptr->param.ia_handle = ia_ptr;\r
+ ep_ptr->param.local_ia_address_ptr =\r
+ (DAT_IA_ADDRESS_PTR) & ia_ptr->hca_ptr->hca_address;\r
+\r
+ /* Link the EP onto the IA */\r
+ dapl_ia_link_ep(ia_ptr, ep_ptr);\r
+ }\r
+\r
+ cr_ptr->param.local_ep_handle = ep_ptr;\r
+\r
+ if (ep_ptr != NULL) {\r
+ /* Assign valid EP fields: RSP and PSP_PROVIDER_FLAG only */\r
+ if (sp_ptr->psp_flags == DAT_PSP_PROVIDER_FLAG) {\r
+ ep_ptr->param.ep_state =\r
+ DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING;\r
+ } else {\r
+ /* RSP */\r
+ dapl_os_assert(sp_ptr->header.handle_type ==\r
+ DAT_HANDLE_TYPE_RSP);\r
+ ep_ptr->param.ep_state =\r
+ DAT_EP_STATE_PASSIVE_CONNECTION_PENDING;\r
+ }\r
+ ep_ptr->cm_handle = ib_cm_handle;\r
+ }\r
+\r
+ /* link the CR onto the SP so we can pick it up later */\r
+ dapl_sp_link_cr(sp_ptr, cr_ptr);\r
+\r
+ /* assign sp_ptr to union to avoid typecast errors from some compilers */\r
+ sp_handle.psp_handle = (DAT_PSP_HANDLE) sp_ptr;\r
+\r
+ /* Post the event. */\r
+\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+ event_ptr = dapli_evd_get_and_init_event(sp_ptr->evd_handle,\r
+ event_number);\r
+ if (event_ptr == NULL)\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+\r
+ event_ptr->event_data.cr_arrival_event_data.sp_handle = sp_handle;\r
+ event_ptr->event_data.cr_arrival_event_data.local_ia_address_ptr =\r
+ (DAT_IA_ADDRESS_PTR) & sp_ptr->header.owner_ia->hca_ptr->\r
+ hca_address;\r
+ event_ptr->event_data.cr_arrival_event_data.conn_qual =\r
+ sp_ptr->conn_qual;\r
+ event_ptr->event_data.cr_arrival_event_data.cr_handle =\r
+ (DAT_HANDLE) cr_ptr;\r
+\r
+ dapl_os_memcpy(&event_ptr->event_extension_data[0], ext_data, 64);\r
+\r
+ dapli_evd_post_event(sp_ptr->evd_handle, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_post_connection_event_ext(IN DAPL_EVD * evd_ptr,\r
+ IN DAT_EVENT_NUMBER event_number,\r
+ IN DAT_EP_HANDLE ep_handle,\r
+ IN DAT_COUNT private_data_size,\r
+ IN DAT_PVOID private_data,\r
+ IN DAT_PVOID ext_data)\r
+{\r
+ DAT_EVENT *event_ptr;\r
+ event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);\r
+ /*\r
+ * Note event lock may be held on successful return\r
+ * to be released by dapli_evd_post_event(), if provider side locking\r
+ * is needed.\r
+ */\r
+ if (event_ptr == NULL)\r
+ return DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,\r
+ DAT_RESOURCE_MEMORY);\r
+\r
+ event_ptr->event_data.connect_event_data.ep_handle = ep_handle;\r
+ event_ptr->event_data.connect_event_data.private_data_size\r
+ = private_data_size;\r
+ event_ptr->event_data.connect_event_data.private_data = private_data;\r
+\r
+ dapl_os_memcpy(&event_ptr->event_extension_data[0], ext_data, 64);\r
+\r
+ dapli_evd_post_event(evd_ptr, event_ptr);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+#endif\r
+\r
+/*\r
+ * dapli_evd_cqe_to_event\r
+ *\r
+ * Convert a CQE into an event structure.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ * cqe_ptr\r
+ *\r
+ * Output:\r
+ * event_ptr\r
+ *\r
+ * Returns:\r
+ * none\r
+ *\r
+ */\r
+static void\r
+dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,\r
+ IN void *cqe_ptr, OUT DAT_EVENT * event_ptr)\r
+{\r
+ DAPL_EP *ep_ptr;\r
+ DAPL_COOKIE *cookie;\r
+ DAT_DTO_COMPLETION_STATUS dto_status;\r
+ DAPL_COOKIE_BUFFER *buffer;\r
+\r
+ /*\r
+ * All that can be relied on if the status is bad is the status\r
+ * and WRID.\r
+ */\r
+ dto_status = dapls_ib_get_dto_status(cqe_ptr);\r
+\r
+ cookie = (DAPL_COOKIE *) (uintptr_t) DAPL_GET_CQE_WRID(cqe_ptr);\r
+ dapl_os_assert((NULL != cookie));\r
+\r
+ ep_ptr = cookie->ep;\r
+ dapl_os_assert((NULL != ep_ptr));\r
+ if (ep_ptr->header.magic != DAPL_MAGIC_EP) {\r
+ /* ep may have been freed, just return */\r
+ return;\r
+ }\r
+\r
+ dapls_io_trc_update_completion(ep_ptr, cookie, dto_status);\r
+\r
+ event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;\r
+\r
+ switch (cookie->type) {\r
+ case DAPL_COOKIE_TYPE_DTO:\r
+ {\r
+#ifdef DAT_EXTENSIONS\r
+ /* Extended via request post or message receive */\r
+ if ((cookie->val.dto.type == DAPL_DTO_TYPE_EXTENSION) ||\r
+ (cookie->val.dto.type == DAPL_DTO_TYPE_RECV &&\r
+ DAPL_GET_CQE_OPTYPE(cqe_ptr) != OP_RECEIVE)) {\r
+ dapls_cqe_to_event_extension(ep_ptr, cookie,\r
+ cqe_ptr,\r
+ event_ptr);\r
+ if (cookie->val.dto.type == DAPL_DTO_TYPE_RECV)\r
+ dapls_cookie_dealloc(&ep_ptr->\r
+ recv_buffer,\r
+ cookie);\r
+ else\r
+ dapls_cookie_dealloc(&ep_ptr->\r
+ req_buffer,\r
+ cookie);\r
+ break;\r
+ }\r
+#endif\r
+\r
+ if (DAPL_DTO_TYPE_RECV == cookie->val.dto.type)\r
+ buffer = &ep_ptr->recv_buffer;\r
+ else\r
+ buffer = &ep_ptr->req_buffer;\r
+\r
+ event_ptr->event_number = DAT_DTO_COMPLETION_EVENT;\r
+ event_ptr->event_data.dto_completion_event_data.\r
+ ep_handle = cookie->ep;\r
+ event_ptr->event_data.dto_completion_event_data.\r
+ user_cookie = cookie->val.dto.cookie;\r
+ event_ptr->event_data.dto_completion_event_data.status =\r
+ dto_status;\r
+\r
+ if (cookie->val.dto.type == DAPL_DTO_TYPE_SEND ||\r
+ cookie->val.dto.type == DAPL_DTO_TYPE_RDMA_WRITE) {\r
+ /* Get size from DTO; CQE value may be off. */\r
+ event_ptr->event_data.dto_completion_event_data.\r
+ transfered_length = cookie->val.dto.size;\r
+ } else {\r
+ event_ptr->event_data.dto_completion_event_data.\r
+ transfered_length =\r
+ DAPL_GET_CQE_BYTESNUM(cqe_ptr);\r
+ }\r
+\r
+ dapls_cookie_dealloc(buffer, cookie);\r
+ break;\r
+ }\r
+\r
+ case DAPL_COOKIE_TYPE_RMR:\r
+ {\r
+ event_ptr->event_number = DAT_RMR_BIND_COMPLETION_EVENT;\r
+\r
+ event_ptr->event_data.rmr_completion_event_data.\r
+ rmr_handle = cookie->val.rmr.rmr;\r
+ event_ptr->event_data.rmr_completion_event_data.\r
+ user_cookie = cookie->val.rmr.cookie;\r
+ if (dto_status == DAT_DTO_SUCCESS) {\r
+ event_ptr->event_data.rmr_completion_event_data.\r
+ status = DAT_RMR_BIND_SUCCESS;\r
+ dapl_os_assert((DAPL_GET_CQE_OPTYPE(cqe_ptr)) ==\r
+ OP_BIND_MW);\r
+ } else {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_DTO_COMP_ERR,\r
+ " MW bind completion ERROR: %d: op %#x ep: %p\n",\r
+ dto_status,\r
+ DAPL_GET_CQE_OPTYPE(cqe_ptr),\r
+ ep_ptr);\r
+ event_ptr->event_data.rmr_completion_event_data.\r
+ status = DAT_RMR_OPERATION_FAILED;\r
+ dapl_os_atomic_dec(&cookie->val.rmr.rmr->lmr->\r
+ lmr_ref_count);\r
+ }\r
+\r
+ dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);\r
+ break;\r
+ }\r
+ default:\r
+ {\r
+ dapl_os_assert(!"Invalid Operation type");\r
+ break;\r
+ }\r
+ } /* end switch */\r
+\r
+ /*\r
+ * Most error DTO ops result in disconnecting the EP. See\r
+ * IBTA Vol 1.1, Chapter 10,Table 68, for expected effect on\r
+ * state.\r
+ */\r
+ if ((dto_status != DAT_DTO_SUCCESS) &&\r
+ (dto_status != DAT_DTO_ERR_FLUSHED)) {\r
+ DAPL_EVD *evd_ptr;\r
+\r
+ /*\r
+ * If we are connected, generate disconnect and generate an\r
+ * event. We may be racing with other disconnect ops, so we\r
+ * need to check. We may also be racing CM connection events,\r
+ * requiring us to check for connection pending states too.\r
+ */\r
+ dapl_os_lock(&ep_ptr->header.lock);\r
+ if (ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED ||\r
+ ep_ptr->param.ep_state ==\r
+ DAT_EP_STATE_ACTIVE_CONNECTION_PENDING\r
+ || ep_ptr->param.ep_state ==\r
+ DAT_EP_STATE_PASSIVE_CONNECTION_PENDING\r
+ || ep_ptr->param.ep_state ==\r
+ DAT_EP_STATE_COMPLETION_PENDING)\r
+ {\r
+ ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;\r
+ dapl_os_unlock(&ep_ptr->header.lock);\r
+ dapls_io_trc_dump(ep_ptr, cqe_ptr, dto_status);\r
+\r
+ /* Let the other side know we have disconnected */\r
+ (void)dapls_ib_disconnect(ep_ptr,\r
+ DAT_CLOSE_ABRUPT_FLAG);\r
+\r
+ /* ... and clean up the local side */\r
+ evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;\r
+ if (evd_ptr != NULL) {\r
+ dapls_evd_post_connection_event(evd_ptr,\r
+ DAT_CONNECTION_EVENT_BROKEN,\r
+ (DAT_HANDLE)\r
+ ep_ptr, 0, 0);\r
+ }\r
+ } else {\r
+ dapl_os_unlock(&ep_ptr->header.lock);\r
+ }\r
+\r
+ dapl_log(DAPL_DBG_TYPE_ERR,\r
+ "DTO completion ERR: status %d, op %s, vendor_err 0x%x - %s\n",\r
+ DAPL_GET_CQE_STATUS(cqe_ptr),\r
+ DAPL_GET_DTO_OP_STR(cookie->val.dto.type),\r
+ DAPL_GET_CQE_VENDOR_ERR(cqe_ptr),\r
+ inet_ntoa(((struct sockaddr_in *)&ep_ptr->\r
+ remote_ia_address)->sin_addr));\r
+ }\r
+}\r
+\r
+/*\r
+ * dapls_evd_copy_cq\r
+ *\r
+ * Copy all entries on a CQ associated with the EVD onto that EVD\r
+ * Up to caller to handle races, if any. Note that no EVD waiters will\r
+ * be awoken by this copy.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ *\r
+ * Output:\r
+ * None\r
+ *\r
+ * Returns:\r
+ * none\r
+ *\r
+ */\r
+void dapls_evd_copy_cq(DAPL_EVD * evd_ptr)\r
+{\r
+ ib_work_completion_t cur_cqe;\r
+ DAT_RETURN dat_status;\r
+ DAT_EVENT *event;\r
+\r
+ if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE) {\r
+ /* Nothing to do if no CQ. */\r
+ return;\r
+ }\r
+\r
+ while (1) {\r
+ dat_status =\r
+ dapls_ib_completion_poll(evd_ptr->header.owner_ia->hca_ptr,\r
+ evd_ptr, &cur_cqe);\r
+\r
+ if (dat_status != DAT_SUCCESS) {\r
+ break;\r
+ }\r
+\r
+ /* For debugging. */\r
+ dapli_evd_eh_print_cqe(&cur_cqe);\r
+\r
+ /*\r
+ * Can use DAT_DTO_COMPLETION_EVENT because dapli_evd_cqe_to_event\r
+ * will overwrite.\r
+ */\r
+\r
+ event =\r
+ dapli_evd_get_and_init_event(evd_ptr,\r
+ DAT_DTO_COMPLETION_EVENT);\r
+ if (event == NULL) {\r
+ /* We've already attempted the overflow post; return. */\r
+ return;\r
+ }\r
+\r
+ dapli_evd_cqe_to_event(evd_ptr, &cur_cqe, event);\r
+\r
+ dapli_evd_post_event_nosignal(evd_ptr, event);\r
+ }\r
+\r
+ if (DAT_GET_TYPE(dat_status) != DAT_QUEUE_EMPTY) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_EVD,\r
+ "dapls_evd_copy_cq: dapls_ib_completion_poll returned 0x%x\n",\r
+ dat_status);\r
+ dapl_os_assert(!"Bad return from dapls_ib_completion_poll");\r
+ }\r
+}\r
+\r
+/*\r
+ * dapls_evd_cq_poll_to_event\r
+ *\r
+ * Attempt to dequeue a single CQE from a CQ and turn it into\r
+ * an event.\r
+ *\r
+ * Input:\r
+ * evd_ptr\r
+ *\r
+ * Output:\r
+ * event\r
+ *\r
+ * Returns:\r
+ * Status of operation\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_evd_cq_poll_to_event(IN DAPL_EVD * evd_ptr, OUT DAT_EVENT * event)\r
+{\r
+ DAT_RETURN dat_status;\r
+ ib_work_completion_t cur_cqe;\r
+\r
+ dat_status = dapls_ib_completion_poll(evd_ptr->header.owner_ia->hca_ptr,\r
+ evd_ptr, &cur_cqe);\r
+ if (dat_status == DAT_SUCCESS) {\r
+ /* For debugging. */\r
+ dapli_evd_eh_print_cqe(&cur_cqe);\r
+\r
+ dapli_evd_cqe_to_event(evd_ptr, &cur_cqe, event);\r
+ }\r
+\r
+ return dat_status;\r
+}\r
+\r
+#ifdef DAPL_DBG_IO_TRC\r
+/*\r
+ * Update I/O completions in the I/O trace buffer. I/O is posted to\r
+ * the buffer, then we find it here using the cookie and mark it\r
+ * completed with the completion status\r
+ */\r
+void\r
+dapls_io_trc_update_completion(DAPL_EP * ep_ptr,\r
+ DAPL_COOKIE * cookie,\r
+ DAT_DTO_COMPLETION_STATUS dto_status)\r
+{\r
+ int i;\r
+ static unsigned int c_cnt = 1;\r
+\r
+ for (i = 0; i < DBG_IO_TRC_QLEN; i++) {\r
+ if (ep_ptr->ibt_base[i].cookie == cookie) {\r
+ ep_ptr->ibt_base[i].status = dto_status;\r
+ ep_ptr->ibt_base[i].done = c_cnt++;\r
+ }\r
+ }\r
+}\r
+\r
+/*\r
+ * Dump the I/O trace buffers\r
+ */\r
+void\r
+dapls_io_trc_dump(DAPL_EP * ep_ptr,\r
+ void *cqe_ptr, DAT_DTO_COMPLETION_STATUS dto_status)\r
+{\r
+ struct io_buf_track *ibt;\r
+ int i;\r
+ int cnt;\r
+\r
+ dapl_os_printf("DISCONNECTING: dto_status = %x\n", dto_status);\r
+ dapl_os_printf(" OpType = %x\n",\r
+ DAPL_GET_CQE_OPTYPE(cqe_ptr));\r
+ dapl_os_printf(" Bytes = %x\n",\r
+ DAPL_GET_CQE_BYTESNUM(cqe_ptr));\r
+ dapl_os_printf(" WRID (cookie) = %llx\n",\r
+ DAPL_GET_CQE_WRID(cqe_ptr));\r
+\r
+ if (ep_ptr->ibt_dumped == 0) {\r
+\r
+ dapl_os_printf("EP %p (qpn %d) I/O trace buffer\n",\r
+ ep_ptr, ep_ptr->qpn);\r
+\r
+ ep_ptr->ibt_dumped = 1;\r
+ ibt =\r
+ (struct io_buf_track *)dapls_rbuf_remove(&ep_ptr->\r
+ ibt_queue);\r
+ cnt = DBG_IO_TRC_QLEN;\r
+ while (ibt != NULL && cnt > 0) {\r
+ dapl_os_printf\r
+ ("%2d. %3s (%2d, %d) OP: %x cookie %p wqe %p rmv_target_addr %llx rmv_rmr_context %x\n",\r
+ cnt, ibt->done == 0 ? "WRK" : "DON", ibt->status,\r
+ ibt->done, ibt->op_type, ibt->cookie, ibt->wqe,\r
+ ibt->remote_iov.target_address,\r
+ ibt->remote_iov.rmr_context);\r
+ for (i = 0; i < 3; i++) {\r
+ if (ibt->iov[i].segment_length != 0) {\r
+ dapl_os_printf\r
+ (" (%4llx, %8x, %8llx)\n",\r
+ ibt->iov[i].segment_length,\r
+ ibt->iov[i].lmr_context,\r
+ ibt->iov[i].virtual_address);\r
+ }\r
+ }\r
+ ibt =\r
+ (struct io_buf_track *)dapls_rbuf_remove(&ep_ptr->\r
+ ibt_queue);\r
+ cnt--;\r
+ }\r
+ }\r
+}\r
+#endif /* DAPL_DBG_IO_TRC */\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) 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_cq.c
- *
- * PURPOSE: CQ (Completion Qeueu) access routine using IBAL APIs
- *
- * $Id$
- *
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_adapter_util.h"
-#include "dapl_evd_util.h"
-#include "dapl_cr_util.h"
-#include "dapl_lmr_util.h"
-#include "dapl_rmr_util.h"
-#include "dapl_cookie.h"
-#include "dapl_ring_buffer_util.h"
-
-#ifndef NO_NAME_SERVICE
-#include "dapl_name_service.h"
-#endif /* NO_NAME_SERVICE */
-
-
-static void
-dapli_ibal_cq_async_error_callback ( IN ib_async_event_rec_t *p_err_rec )
-{
- DAPL_EVD *evd_ptr = (DAPL_EVD*)((void *)p_err_rec->context);
- DAPL_EVD *async_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,
- "--> DiCqAEC: CQ error %d for EVD context %lx\n",
- p_err_rec->code, p_err_rec->context);
-
- if (DAPL_BAD_HANDLE (evd_ptr, DAPL_MAGIC_EVD))
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> DiCqAEC: invalid EVD %lx\n", evd_ptr);
- return;
- }
-
- ia_ptr = evd_ptr->header.owner_ia;
- async_evd_ptr = ia_ptr->async_error_evd;
- if (async_evd_ptr == NULL)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,"--> DiCqAEC: can't find async_error_evd on %s HCA\n",
- (ia_ptr->header.provider)->device_name );
- 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,"--> DiCqAEC: can't find %s HCA\n",
- (ia_ptr->header.provider)->device_name);
- return;
- }
-
- /* find CQ error callback using ia_ptr for context */
- evd_cb = dapli_find_evd_cb_by_context ( async_evd_ptr, p_ca );
- if ((evd_cb == NULL) || (evd_cb->pfn_async_cq_err_cb == NULL))
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> DiCqAEC: no ERROR cb on %lx found \n", p_ca);
- return;
- }
-
- /* maps to dapl_evd_cq_async_error_callback(), context is EVD */
- evd_cb->pfn_async_cq_err_cb( (ib_hca_handle_t)p_ca,
- evd_ptr->ib_cq_handle,
- (ib_error_record_t*)&p_err_rec->code,
- evd_ptr );
-
-}
-
-
-/*
- * dapli_ibal_cq_competion_callback
- *
- * Completion callback for a CQ
- *
- * Input:
- * cq_context User context
- *
- * Output:
- * none
- *
- * Returns:
- */
-static void
-dapli_ib_cq_completion_cb (
- IN const ib_cq_handle_t h_cq,
- IN void *cq_context )
-{
- DAPL_EVD *evd_ptr;
- dapl_ibal_ca_t *p_ca;
-
- evd_ptr = (DAPL_EVD *) cq_context;
-
- dapl_dbg_log (DAPL_DBG_TYPE_CALLBACK,
- "--> DiICCC: cq_completion_cb evd %lx CQ %lx\n",
- evd_ptr, evd_ptr->ib_cq_handle);
-
- dapl_os_assert (evd_ptr != DAT_HANDLE_NULL);
-
- p_ca = (dapl_ibal_ca_t *) evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle;
-
- dapl_os_assert( h_cq == evd_ptr->ib_cq_handle );
-
- dapl_evd_dto_callback ( (ib_hca_handle_t) p_ca, h_cq, cq_context);
-}
-
-
-/*
- * dapl_ib_cq_late_alloc
- *
- * Alloc a CQ
- *
- * Input:
- * ia_handle IA handle
- * evd_ptr pointer to EVD struct
- * cqlen minimum QLen
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_cq_late_alloc (
- IN ib_pd_handle_t pd_handle,
- IN DAPL_EVD *evd_ptr )
-{
- ib_cq_create_t cq_create;
- ib_api_status_t ib_status;
- DAT_RETURN dat_status;
- dapl_ibal_ca_t *ibal_ca;
-
- dat_status = DAT_SUCCESS;
- cq_create.size = evd_ptr->qlen;
-
- ibal_ca = (dapl_ibal_ca_t*)evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle;
-
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle)
- {
- cq_create.h_wait_obj = evd_ptr->cq_wait_obj_handle;
- cq_create.pfn_comp_cb = NULL;
- }
- else
-#endif
- {
- cq_create.h_wait_obj = NULL;
- cq_create.pfn_comp_cb = dapli_ib_cq_completion_cb;
- }
-
- ib_status = ib_create_cq (
- (ib_ca_handle_t)ibal_ca->h_ca,
- &cq_create,
- evd_ptr /* context */,
- dapli_ibal_cq_async_error_callback,
- &evd_ptr->ib_cq_handle);
-
- dat_status = dapl_ib_status_convert (ib_status);
-
- if ( dat_status != DAT_SUCCESS )
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DsICLA: failed to create CQ for EVD %lx\n",evd_ptr);
- goto bail;
- }
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsCQ_alloc: pd=%lx cq=%lx CQsz=%d EVD->Qln=%d\n",
- pd_handle, evd_ptr->ib_cq_handle,
- cq_create.size, evd_ptr->qlen);
-
- /*
- * As long as the CQ size is >= the evd size, then things are OK; sez Arlin.
- */
- if ( cq_create.size < (uint32_t)evd_ptr->qlen )
- {
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsCQ_alloc: created CQ size(%d) < evd->qlen(%d)?\n",
- cq_create.size, evd_ptr->qlen);
- dat_status = dapl_ib_status_convert (IB_INVALID_CQ_SIZE);
- }
-
-bail:
- return dat_status;
-}
-
-/*
- * dapl_ib_cq_alloc
- *
- * Alloc a CQ
- *
- * Input:
- * ia_handle IA handle
- * evd_ptr pointer to EVD struct
- * cqlen minimum QLen
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-
-#if 0
-
-/* windows delays CQ creation as a PD (Protection Domain) is required
- * and we do not have one at this juncture. The follow code is for future
- * reference only.
- */
-
-DAT_RETURN
-dapls_ib_cq_alloc (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr,
- IN DAT_COUNT *cqlen )
-{
- dapl_dbg_log ( DAPL_DBG_TYPE_UTIL,
- "dapls_ib_cq_alloc: evd %lx cqlen=%d \n", evd_ptr, *cqlen );
-
- struct ibv_comp_channel *channel = ia_ptr->hca_ptr->ib_trans.ib_cq;
-
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle)
- channel = evd_ptr->cq_wait_obj_handle;
-#endif
-
- /* Call IB verbs to create CQ */
- evd_ptr->ib_cq_handle = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle,
- *cqlen,
- evd_ptr,
- channel,
- 0);
-
- if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE)
- return DAT_INSUFFICIENT_RESOURCES;
-
- /* arm cq for events */
- dapls_set_cq_notify(ia_ptr, evd_ptr);
-
- /* update with returned cq entry size */
- *cqlen = evd_ptr->ib_cq_handle->cqe;
-
- dapl_dbg_log ( DAPL_DBG_TYPE_UTIL,
- "dapls_ib_cq_alloc: new_cq %lx cqlen=%d \n",
- evd_ptr->ib_cq_handle, *cqlen );
-
- return DAT_SUCCESS;
-}
-#endif
-
-
-/*
- * dapl_ib_cq_free
- *
- * Dealloc a CQ
- *
- * Input:
- * ia_handle IA handle
- * evd_ptr pointer to EVD struct
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_cq_free (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr)
-{
- ib_api_status_t ib_status;
-
- if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )
- {
- return DAT_INVALID_HANDLE;
- }
-
- ib_status = ib_destroy_cq (evd_ptr->ib_cq_handle,
- /* destroy_callback */ NULL);
-
- return dapl_ib_status_convert (ib_status);
-}
-
-/*
- * dapls_cq_resize
- *
- * Resize CQ completion notifications
- *
- * Input:
- * ia_handle IA handle
- * evd_ptr pointer to EVD struct
- * cqlen minimum QLen
- *
- * Output:
- * cqlen may round up for optimal memory boundaries
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-
-DAT_RETURN
-dapls_ib_cq_resize (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr,
- IN DAT_COUNT *cqlen )
-{
- ib_api_status_t ib_status = IB_SUCCESS;
-
- if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )
- {
- return DAT_INVALID_HANDLE;
- }
- /*
- * Resize CQ only if CQ handle is valid, may be delayed waiting
- * for PZ allocation with IBAL
- */
-#if defined(_VENDOR_IBAL_)
- if ( evd_ptr->ib_cq_handle != IB_INVALID_HANDLE )
-#endif /* _VENDOR_IBAL_ */
- {
- ib_status = ib_modify_cq ( evd_ptr->ib_cq_handle,
- (uint32_t *)cqlen );
- dapl_dbg_log (DAPL_DBG_TYPE_EVD,
- "ib_modify_cq ( new cqlen = %d, status=%d ) \n",
- *cqlen, ib_status );
- }
- return dapl_ib_status_convert (ib_status);
-}
-
-
-/*
- * dapl_set_cq_notify
- *
- * Set up CQ completion notifications
- *
- * Input:
- * ia_handle IA handle
- * evd_ptr pointer to EVD struct
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_set_cq_notify (
- IN DAPL_IA *ia_ptr,
- IN DAPL_EVD *evd_ptr )
-{
- ib_api_status_t ib_status;
- if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )
- {
- return DAT_INVALID_HANDLE;
- }
- ib_status = ib_rearm_cq (
- evd_ptr->ib_cq_handle,
- FALSE /* next event but not solicited event */ );
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-/*
- * dapls_ib_cqd_create
- *
- * Set up CQ notification event thread
- *
- * Input:
- * ia_handle HCA handle
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_cqd_create ( IN DAPL_HCA *p_hca )
-{
- /*
- * We do not have CQD concept
- */
- p_hca->ib_trans.ib_cqd_handle = IB_INVALID_HANDLE;
-
- return DAT_SUCCESS;
-}
-
-
-/*
- * dapl_cqd_destroy
- *
- * Destroy CQ notification event thread
- *
- * Input:
- * ia_handle IA handle
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_cqd_destroy ( IN DAPL_HCA *p_hca )
-{
- p_hca->ib_trans.ib_cqd_handle = IB_INVALID_HANDLE;
- return (DAT_SUCCESS);
-}
-
-
-
-DAT_RETURN
-dapls_ib_n_completions_notify (
- IN ib_hca_handle_t hca_handle,
- IN ib_cq_handle_t cq_handle,
- IN uint32_t n_cqes )
-{
- ib_api_status_t ib_status;
- UNREFERENCED_PARAMETER(hca_handle);
-
- ib_status = ib_rearm_n_cq (
- cq_handle,
- n_cqes );
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-DAT_RETURN
-dapls_ib_peek_cq (
- IN ib_cq_handle_t cq_handle,
- OUT uint32_t* p_n_cqes)
-{
- ib_api_status_t ib_status;
-
- ib_status = ib_peek_cq ( cq_handle, p_n_cqes );
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
-
+\r
+/*\r
+ * Copyright (c) 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_cq.c\r
+ *\r
+ * PURPOSE: CQ (Completion Qeueu) access routine using IBAL APIs\r
+ *\r
+ * $Id$\r
+ *\r
+ **********************************************************************/\r
+\r
+#include "dapl.h"\r
+#include "dapl_adapter_util.h"\r
+#include "dapl_evd_util.h"\r
+#include "dapl_cr_util.h"\r
+#include "dapl_lmr_util.h"\r
+#include "dapl_rmr_util.h"\r
+#include "dapl_cookie.h"\r
+#include "dapl_ring_buffer_util.h"\r
+\r
+#ifndef NO_NAME_SERVICE\r
+#include "dapl_name_service.h"\r
+#endif /* NO_NAME_SERVICE */\r
+\r
+\r
+static void\r
+dapli_ibal_cq_async_error_callback ( IN ib_async_event_rec_t *p_err_rec )\r
+{\r
+ DAPL_EVD *evd_ptr = (DAPL_EVD*)((void *)p_err_rec->context);\r
+ DAPL_EVD *async_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,\r
+ "--> DiCqAEC: CQ error %d for EVD context %lx\n", \r
+ p_err_rec->code, p_err_rec->context);\r
+\r
+ if (DAPL_BAD_HANDLE (evd_ptr, DAPL_MAGIC_EVD))\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ "--> DiCqAEC: invalid EVD %lx\n", evd_ptr);\r
+ return;\r
+ }\r
+ \r
+ ia_ptr = evd_ptr->header.owner_ia;\r
+ async_evd_ptr = ia_ptr->async_error_evd;\r
+ if (async_evd_ptr == NULL)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,"--> DiCqAEC: can't find async_error_evd on %s HCA\n", \r
+ (ia_ptr->header.provider)->device_name );\r
+ return;\r
+ }\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,"--> DiCqAEC: can't find %s HCA\n", \r
+ (ia_ptr->header.provider)->device_name);\r
+ return;\r
+ }\r
+\r
+ /* find CQ error callback using ia_ptr for context */\r
+ evd_cb = dapli_find_evd_cb_by_context ( async_evd_ptr, p_ca );\r
+ if ((evd_cb == NULL) || (evd_cb->pfn_async_cq_err_cb == NULL))\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ "--> DiCqAEC: no ERROR cb on %lx found \n", p_ca);\r
+ return;\r
+ }\r
+\r
+ /* maps to dapl_evd_cq_async_error_callback(), context is EVD */\r
+ evd_cb->pfn_async_cq_err_cb( (ib_hca_handle_t)p_ca, \r
+ evd_ptr->ib_cq_handle,\r
+ (ib_error_record_t*)&p_err_rec->code,\r
+ evd_ptr );\r
+\r
+}\r
+\r
+\r
+/*\r
+ * dapli_ibal_cq_competion_callback\r
+ *\r
+ * Completion callback for a CQ\r
+ *\r
+ * Input:\r
+ * cq_context User context\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ */\r
+static void\r
+dapli_ib_cq_completion_cb (\r
+ IN const ib_cq_handle_t h_cq,\r
+ IN void *cq_context )\r
+{\r
+ DAPL_EVD *evd_ptr;\r
+ dapl_ibal_ca_t *p_ca;\r
+\r
+ evd_ptr = (DAPL_EVD *) cq_context;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_CALLBACK, \r
+ "--> DiICCC: cq_completion_cb evd %lx CQ %lx\n", \r
+ evd_ptr, evd_ptr->ib_cq_handle);\r
+\r
+ dapl_os_assert (evd_ptr != DAT_HANDLE_NULL);\r
+\r
+ p_ca = (dapl_ibal_ca_t *) evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle;\r
+\r
+ dapl_os_assert( h_cq == evd_ptr->ib_cq_handle );\r
+\r
+ dapl_evd_dto_callback ( (ib_hca_handle_t) p_ca, h_cq, cq_context);\r
+}\r
+\r
+\r
+/*\r
+ * dapl_ib_cq_late_alloc\r
+ *\r
+ * Alloc a CQ\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * evd_ptr pointer to EVD struct\r
+ * cqlen minimum QLen\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_cq_late_alloc (\r
+ IN ib_pd_handle_t pd_handle,\r
+ IN DAPL_EVD *evd_ptr )\r
+{\r
+ ib_cq_create_t cq_create;\r
+ ib_api_status_t ib_status;\r
+ DAT_RETURN dat_status;\r
+ dapl_ibal_ca_t *ibal_ca;\r
+ \r
+ dat_status = DAT_SUCCESS;\r
+ cq_create.size = evd_ptr->qlen;\r
+ \r
+ ibal_ca = (dapl_ibal_ca_t*)evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle;\r
+ \r
+ cq_create.h_wait_obj = NULL;\r
+ cq_create.pfn_comp_cb = dapli_ib_cq_completion_cb;\r
+\r
+ ib_status = ib_create_cq (\r
+ (ib_ca_handle_t)ibal_ca->h_ca,\r
+ &cq_create,\r
+ evd_ptr /* context */,\r
+ dapli_ibal_cq_async_error_callback,\r
+ &evd_ptr->ib_cq_handle);\r
+\r
+ dat_status = dapl_ib_status_convert (ib_status);\r
+\r
+ if ( dat_status != DAT_SUCCESS )\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DsICLA: failed to create CQ for EVD %lx\n",evd_ptr);\r
+ goto bail;\r
+ }\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsCQ_alloc: pd=%lx cq=%lx CQsz=%d EVD->Qln=%d\n",\r
+ pd_handle, evd_ptr->ib_cq_handle,\r
+ cq_create.size, evd_ptr->qlen);\r
+\r
+ /*\r
+ * As long as the CQ size is >= the evd size, then things are OK; sez Arlin.\r
+ */\r
+ if ( cq_create.size < (uint32_t)evd_ptr->qlen )\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsCQ_alloc: created CQ size(%d) < evd->qlen(%d)?\n",\r
+ cq_create.size, evd_ptr->qlen);\r
+ dat_status = dapl_ib_status_convert (IB_INVALID_CQ_SIZE);\r
+ }\r
+ \r
+bail: \r
+ return dat_status;\r
+}\r
+\r
+/*\r
+ * dapl_ib_cq_alloc\r
+ *\r
+ * Alloc a CQ\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * evd_ptr pointer to EVD struct\r
+ * cqlen minimum QLen\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+\r
+\r
+/*\r
+ * dapl_ib_cq_free\r
+ *\r
+ * Dealloc a CQ\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * evd_ptr pointer to EVD struct\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_cq_free (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr)\r
+{\r
+ ib_api_status_t ib_status;\r
+ \r
+ if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+\r
+ ib_status = ib_destroy_cq (evd_ptr->ib_cq_handle, \r
+ /* destroy_callback */ NULL);\r
+ \r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+/*\r
+ * dapls_cq_resize\r
+ *\r
+ * Resize CQ completion notifications\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * evd_ptr pointer to EVD struct\r
+ * cqlen minimum QLen \r
+ *\r
+ * Output:\r
+ * cqlen may round up for optimal memory boundaries \r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+\r
+DAT_RETURN\r
+dapls_ib_cq_resize (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN DAT_COUNT *cqlen )\r
+{\r
+ ib_api_status_t ib_status = IB_SUCCESS;\r
+\r
+ if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+ /* \r
+ * Resize CQ only if CQ handle is valid, may be delayed waiting\r
+ * for PZ allocation with IBAL \r
+ */\r
+#if defined(_VENDOR_IBAL_)\r
+ if ( evd_ptr->ib_cq_handle != IB_INVALID_HANDLE ) \r
+#endif /* _VENDOR_IBAL_ */\r
+ {\r
+ ib_status = ib_modify_cq ( evd_ptr->ib_cq_handle, \r
+ (uint32_t *)cqlen );\r
+ dapl_dbg_log (DAPL_DBG_TYPE_EVD,\r
+ "ib_modify_cq ( new cqlen = %d, status=%d ) \n",\r
+ *cqlen, ib_status );\r
+ } \r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+\r
+/*\r
+ * dapl_set_cq_notify\r
+ *\r
+ * Set up CQ completion notifications\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * evd_ptr pointer to EVD struct\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_set_cq_notify (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_EVD *evd_ptr )\r
+{\r
+ ib_api_status_t ib_status;\r
+ if ( ia_ptr == NULL || ia_ptr->header.magic != DAPL_MAGIC_IA )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+ ib_status = ib_rearm_cq ( \r
+ evd_ptr->ib_cq_handle,\r
+ FALSE /* next event but not solicited event */ );\r
+\r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_cqd_create\r
+ *\r
+ * Set up CQ notification event thread\r
+ *\r
+ * Input:\r
+ * ia_handle HCA handle\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_cqd_create ( IN DAPL_HCA *p_hca )\r
+{\r
+ /*\r
+ * We do not have CQD concept\r
+ */\r
+ p_hca->ib_trans.ib_cqd_handle = IB_INVALID_HANDLE;\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * dapl_cqd_destroy\r
+ *\r
+ * Destroy CQ notification event thread\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_cqd_destroy ( IN DAPL_HCA *p_hca )\r
+{\r
+ p_hca->ib_trans.ib_cqd_handle = IB_INVALID_HANDLE;\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+\r
+DAT_RETURN\r
+dapls_ib_n_completions_notify (\r
+ IN ib_hca_handle_t hca_handle,\r
+ IN ib_cq_handle_t cq_handle,\r
+ IN uint32_t n_cqes )\r
+{\r
+ ib_api_status_t ib_status;\r
+ UNREFERENCED_PARAMETER(hca_handle);\r
+\r
+ ib_status = ib_rearm_n_cq ( \r
+ cq_handle,\r
+ n_cqes );\r
+\r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+\r
+DAT_RETURN\r
+dapls_ib_peek_cq (\r
+ IN ib_cq_handle_t cq_handle,\r
+ OUT uint32_t* p_n_cqes)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = ib_peek_cq ( cq_handle, p_n_cqes );\r
+\r
+ return dapl_ib_status_convert (ib_status);\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_util.c
- *
- * PURPOSE: Utility routines for access to IBAL APIs
- *
- * $Id: dapl_ibal_util.c 33 2005-07-11 19:51:17Z ftillier $
- *
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_adapter_util.h"
-#include "dapl_evd_util.h"
-#include "dapl_cr_util.h"
-#include "dapl_lmr_util.h"
-#include "dapl_rmr_util.h"
-#include "dapl_cookie.h"
-#include "dapl_ring_buffer_util.h"
-
-#ifdef DAT_EXTENSIONS
-#include <dat2\dat_ib_extensions.h>
-#endif
-
-#ifndef NO_NAME_SERVICE
-#include "dapl_name_service.h"
-#endif /* NO_NAME_SERVICE */
-
-#include "dapl_ibal_name_service.h"
-
-#define DAPL_IBAL_MAX_CA 4
-#define DAT_ADAPTER_NAME "InfiniHost (Tavor)"
-#define DAT_VENDOR_NAME "Mellanox Technolgy Inc."
-
-/*
- * Root data structure for DAPL_IIBA.
- */
-dapl_ibal_root_t dapl_ibal_root;
-DAPL_HCA_NAME dapl_ibal_hca_name_array [DAPL_IBAL_MAX_CA] =
- {"IbalHca0", "IbalHca1", "IbalHca2", "IbalHca3"};
-ib_net64_t *gp_ibal_ca_guid_tbl = NULL;
-
-/*
- * DAT spec does not tie max_mtu_size with IB MTU
- *
-static ib_net32_t dapl_ibal_mtu_table[6] = {0, 256, 512, 1024, 2048, 4096};
- */
-
-int g_loopback_connection = 0;
-
-
-static cl_status_t
-dapli_init_root_ca_list(
- IN dapl_ibal_root_t *root )
-{
- cl_status_t status;
-
- cl_qlist_init (&root->ca_head);
- status = cl_spinlock_init (&root->ca_lock);
-
- if (status == CL_SUCCESS)
- {
- /*
- * Get the time ready to go but don't start here
- */
- root->shutdown = FALSE;
- root->initialized = TRUE;
- }
- else
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DiIRCL: cl_spinlock_init returned %d\n", status );
- root->initialized = FALSE;
- }
-
- root->h_al = NULL;
-
- return (status);
-}
-
-
-static cl_status_t
-dapli_destroy_root_ca_list(
- IN dapl_ibal_root_t *root )
-{
-
- root->initialized = FALSE;
-
- /*
- * At this point the lock should not be necessary
- */
- if (!cl_is_qlist_empty (&root->ca_head) )
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> Destroying nonempty ca list (%s)\n", "DiDRCL");
- }
- cl_spinlock_destroy (&root->ca_lock);
-
- return CL_SUCCESS;
-}
-
-
-static void
-dapli_shutdown_port_access(
- IN dapl_ibal_ca_t *ca )
-{
- dapl_ibal_port_t *p_port;
-
- TAKE_LOCK( ca->port_lock );
- {
- while ( ! cl_is_qlist_empty( &ca->port_head ) )
- {
- p_port = (dapl_ibal_port_t *)cl_qlist_remove_head( &ca->port_head );
- RELEASE_LOCK( ca->port_lock );
- {
- REMOVE_REFERENCE( &p_port->refs );
- REMOVE_REFERENCE( &p_port->ca->refs );
-
- dapl_os_free (p_port, sizeof (dapl_ibal_port_t));
- }
- TAKE_LOCK( ca->port_lock );
- }
- }
- RELEASE_LOCK( ca->port_lock );
-}
-
-
-static void dapli_shutdown_ca_access (void)
-{
- dapl_ibal_ca_t *ca;
-
- if ( dapl_ibal_root.initialized == FALSE )
- {
- goto destroy_root;
- }
-
- TAKE_LOCK (dapl_ibal_root.ca_lock);
- {
- while ( ! cl_is_qlist_empty (&dapl_ibal_root.ca_head) )
- {
- ca = (dapl_ibal_ca_t *)
- cl_qlist_remove_head (&dapl_ibal_root.ca_head);
-
- if (ca->p_ca_attr)
- {
- dapl_os_free (ca->p_ca_attr, sizeof (ib_ca_attr_t));
- }
-
-
- RELEASE_LOCK (dapl_ibal_root.ca_lock);
- {
- dapli_shutdown_port_access (ca);
- REMOVE_REFERENCE (&ca->refs);
- }
- TAKE_LOCK (dapl_ibal_root.ca_lock);
- }
- }
- RELEASE_LOCK (dapl_ibal_root.ca_lock);
-
-destroy_root:
- /*
- * Destroy the root CA list and list lock
- */
- dapli_destroy_root_ca_list (&dapl_ibal_root);
-
- /*
- * Signal we're all done and wake any waiter
- */
- dapl_ibal_root.shutdown = FALSE;
-}
-
-
-dapl_ibal_evd_cb_t *
-dapli_find_evd_cb_by_context(
- IN void *context,
- IN dapl_ibal_ca_t *ca)
-{
- dapl_ibal_evd_cb_t *evd_cb = NULL;
-
- TAKE_LOCK( ca->evd_cb_lock );
-
- evd_cb = (dapl_ibal_evd_cb_t *) cl_qlist_head( &ca->evd_cb_head );
- while ( &evd_cb->next != cl_qlist_end( &ca->evd_cb_head ) )
- {
- if ( context == evd_cb->context)
- {
- goto found;
- }
-
- /*
- * Try again
- */
- evd_cb = (dapl_ibal_evd_cb_t *) cl_qlist_next( &evd_cb->next );
- }
- /*
- * No joy
- */
- evd_cb = NULL;
-
-found:
-
- RELEASE_LOCK( ca->evd_cb_lock );
-
- return ( evd_cb );
-}
-
-
-static cl_status_t
-dapli_init_ca_evd_cb_list(
- IN dapl_ibal_ca_t *ca )
-{
- cl_status_t status;
-
- cl_qlist_init( &ca->evd_cb_head );
- status = cl_spinlock_init( &ca->evd_cb_lock );
- if ( status != CL_SUCCESS )
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DiICECL: cl_spinlock_init returned %d\n", status);
- return ( status );
-}
-
-
-static cl_status_t
-dapli_init_ca_port_list(
- IN dapl_ibal_ca_t *ca )
-{
- cl_status_t status;
-
- cl_qlist_init( &ca->port_head );
- status = cl_spinlock_init( &ca->port_lock );
- if ( status != CL_SUCCESS )
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DiICPL: cl_spinlock_init returned %d\n", status );
- return ( status );
-}
-
-dapl_ibal_port_t *
-dapli_ibal_get_port (
- IN dapl_ibal_ca_t *p_ca,
- IN uint8_t port_num)
-{
- cl_list_item_t *p_active_port = NULL;
-
- TAKE_LOCK (p_ca->port_lock);
- for ( p_active_port = cl_qlist_head( &p_ca->port_head );
- p_active_port != cl_qlist_end ( &p_ca->port_head);
- p_active_port = cl_qlist_next ( p_active_port ) )
- {
- if (((dapl_ibal_port_t *)p_active_port)->p_attr->port_num == port_num)
- break;
- }
- RELEASE_LOCK (p_ca->port_lock);
-
- return (dapl_ibal_port_t *)p_active_port;
-}
-
-
-void
-dapli_ibal_ca_async_error_callback( IN ib_async_event_rec_t *p_err_rec )
-{
- dapl_ibal_ca_t *p_ca = (dapl_ibal_ca_t*)((void *)p_err_rec->context);
- dapl_ibal_evd_cb_t *evd_cb;
- DAPL_IA *ia_ptr;
-
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DiCaAEC: CA error %d for context %p\n",
- p_err_rec->code, p_err_rec->context);
-
- if (p_ca == NULL)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DiCaAEC: invalid p_ca"
- "(%p)in async event rec\n",p_ca);
- return;
- }
-
- ia_ptr = (DAPL_IA*)p_ca->ia_ptr;
- if (ia_ptr == NULL)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> DiCaAEC: invalid ia_ptr in %p ca \n", p_ca );
- return;
- }
-
- if (ia_ptr->async_error_evd == NULL)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> DiCqAEC: can't find async_error_evd on %s HCA\n",
- (ia_ptr->header.provider)->device_name );
- return;
- }
-
- /* find QP error callback using p_ca for context */
- evd_cb = dapli_find_evd_cb_by_context (ia_ptr->async_error_evd, p_ca);
- if ((evd_cb == NULL) || (evd_cb->pfn_async_err_cb == NULL))
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> DiCaAEC: no ERROR cb on %p found \n", p_ca);
- return;
- }
-
- /* maps to dapl_evd_un_async_error_callback(), context is async_evd */
- evd_cb->pfn_async_err_cb( (ib_hca_handle_t)p_ca,
- (ib_error_record_t*)&p_err_rec->code,
- ia_ptr->async_error_evd );
-
-}
-
-
-static dapl_ibal_port_t *
-dapli_alloc_port(
- IN dapl_ibal_ca_t *ca,
- IN ib_port_attr_t *ib_port )
-{
- dapl_ibal_port_t *p_port = NULL;
-
- if (ca->h_ca == NULL )
- {
- return NULL;
- }
-
- /*
- * Allocate the port structure memory. This will also deal with the
- * copying ib_port_attr_t including GID and P_Key tables
- */
- p_port = dapl_os_alloc ( sizeof(dapl_ibal_port_t ) );
-
- if ( p_port )
- {
- dapl_os_memzero (p_port, sizeof(dapl_ibal_port_t ) );
-
- /*
- * We're good to go after initializing reference.
- */
- INIT_REFERENCE( &p_port->refs, 1, p_port, NULL /* pfn_destructor */ );
-
- p_port->p_attr = ib_port;
- }
- return ( p_port );
-}
-
-static void
-dapli_add_active_port(
- IN dapl_ibal_ca_t *ca )
-{
- dapl_ibal_port_t *p_port;
- ib_port_attr_t *p_port_attr;
- ib_ca_attr_t *p_ca_attr;
- int i;
-
- p_ca_attr = ca->p_ca_attr;
-
- dapl_os_assert (p_ca_attr != NULL);
-
- for (i = 0; i < p_ca_attr->num_ports; i++)
- {
- p_port_attr = &p_ca_attr->p_port_attr[i];
-
- {
- p_port = dapli_alloc_port( ca, p_port_attr );
- if ( p_port )
- {
- TAKE_REFERENCE (&ca->refs);
-
- /*
- * Record / update attribues
- */
- p_port->p_attr = p_port_attr;
-
- /*
- * Remember the parant CA keeping the reference we took above
- */
- p_port->ca = ca;
-
- /*
- * We're good to go - Add the new port to the list on the CA
- */
- LOCK_INSERT_TAIL( ca->port_lock, ca->port_head, p_port->next );
- }
- else
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: Could not allocate dapl_ibal_port_t\n",
- "DiAAP");
- }
- }
- dapl_dbg_log( DAPL_DBG_TYPE_UTIL,
- "--> DiAAP: Port %d logical link %s lid = %#x\n",
- p_port_attr->port_num,
- ( p_port_attr->link_state != IB_LINK_ACTIVE
- ? "DOWN": "UP" ),
- CL_HTON16(p_port_attr->lid) );
-
- } /* for loop */
-}
-
-static dapl_ibal_ca_t *
-dapli_alloc_ca(
- IN ib_al_handle_t h_al,
- IN ib_net64_t ca_guid)
-{
- dapl_ibal_ca_t *p_ca;
- ib_api_status_t status;
- uint32_t attr_size;
-
- /*
- * Allocate the CA structure
- */
- p_ca = dapl_os_alloc( sizeof(dapl_ibal_ca_t) );
- dapl_os_memzero (p_ca, sizeof(dapl_ibal_ca_t) );
-
- if ( p_ca )
- {
- /*
- * Now we pass dapli_ibal_ca_async_error_callback as the
- * async error callback
- */
- status = ib_open_ca( h_al,
- ca_guid,
- dapli_ibal_ca_async_error_callback,
- p_ca,
- &p_ca->h_ca );
- if ( status != IB_SUCCESS )
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DiAC: ib_open_ca returned %s\n",
- ib_get_err_str(status));
- dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));
- return (NULL);
- }
-
- /*
- * Get port list lock and list head initialized
- */
- if (( dapli_init_ca_port_list( p_ca ) != CL_SUCCESS ) ||
- ( dapli_init_ca_evd_cb_list( p_ca ) != CL_SUCCESS ))
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: dapli_init_ca_port_list returned failed\n",
- "DiAC");
- goto close_and_free_ca;
- }
-
- attr_size = 0;
- status = ib_query_ca (p_ca->h_ca, NULL, &attr_size);
- if (status != IB_INSUFFICIENT_MEMORY)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DiAC: ib_query_ca returned failed status = %d\n",
- status);
- goto close_and_free_ca;
- }
-
- p_ca->p_ca_attr = dapl_os_alloc ((int)attr_size);
- if (p_ca->p_ca_attr == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: dapli_alloc_ca failed to alloc memory\n",
- "DiAC");
- goto close_and_free_ca;
- }
-
- status = ib_query_ca (
- p_ca->h_ca,
- p_ca->p_ca_attr,
- &attr_size);
- if (status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> ib_query_ca returned failed status = %d\n",
- status);
- dapl_os_free (p_ca->p_ca_attr, (int)attr_size);
- goto close_and_free_ca;
- }
-
- p_ca->ca_attr_size = attr_size;
-
- INIT_REFERENCE( &p_ca->refs, 1, p_ca, NULL /* pfn_destructor */ );
-
- dapli_add_active_port (p_ca);
-
- /*
- * We're good to go
- */
- return ( p_ca );
- }
- else
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: Error allocating CA structure\n","DiAC");
- return ( NULL );
- }
-
-close_and_free_ca:
- /*
- * Close the CA.
- */
- (void) ib_close_ca ( p_ca->h_ca, NULL /* callback */);
- dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));
-
- /*
- * If we get here, there was an initialization failure
- */
- return ( NULL );
-}
-
-
-static dapl_ibal_ca_t *
-dapli_add_ca (
- IN ib_al_handle_t h_al,
- IN ib_net64_t ca_guid )
-{
- dapl_ibal_ca_t *p_ca;
-
- /*
- * Allocate a CA structure
- */
- p_ca = dapli_alloc_ca( h_al, ca_guid );
- if ( p_ca )
- {
- /*
- * Add the new CA to the list
- */
- LOCK_INSERT_TAIL( dapl_ibal_root.ca_lock,
- dapl_ibal_root.ca_head, p_ca->next );
- }
- else
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: Could not allocate dapl_ibal_ca_t "
- " for CA guid " F64x "\n","DiAA",ca_guid);
- }
-
- return ( p_ca );
-}
-
-
-int32_t
-dapls_ib_init (void)
-{
- ib_api_status_t status;
-
- /*
- * Initialize the root structure
- */
- if ( dapli_init_root_ca_list (&dapl_ibal_root) == CL_SUCCESS )
- {
- /*
- * Register with the access layer
- */
- status = ib_open_al (&dapl_ibal_root.h_al);
-
- if (status == IB_SUCCESS)
- {
- intn_t guid_count;
-
- status = ib_get_ca_guids ( dapl_ibal_root.h_al,
- NULL,
- &(size_t)guid_count );
- if (status != IB_INSUFFICIENT_MEMORY)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: ib_get_ca_guids failed = %d\n",
- __FUNCTION__,status);
- return -1;
- }
-
- if (guid_count == 0)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: found NO HCA in the system\n",
- __FUNCTION__);
- return -1;
- }
-
- if (guid_count > DAPL_IBAL_MAX_CA)
- {
- guid_count = DAPL_IBAL_MAX_CA;
- }
-
- gp_ibal_ca_guid_tbl = (ib_net64_t*)
- dapl_os_alloc ( (int)(guid_count *
- sizeof (ib_net64_t)) );
-
- if (gp_ibal_ca_guid_tbl == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> %s() can not alloc "
- "gp_ibal_ca_guid_tbl\n", __FUNCTION__);
-
- return -1;
- }
-
- status = ib_get_ca_guids ( dapl_ibal_root.h_al,
- gp_ibal_ca_guid_tbl,
- &(size_t)guid_count );
-
-
- if ( status != IB_SUCCESS )
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: ib_get_ca_guids failed '%s'\n",
- __FUNCTION__, ib_get_err_str(status) );
- return -1;
- }
-
- dapl_dbg_log ( DAPL_DBG_TYPE_UTIL,
- "--> %s: Success open AL & found %d HCA avail,\n",
- __FUNCTION__, guid_count);
- return 0;
- }
- else
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: ib_open_al() failed '%s'\n",
- __FUNCTION__, ib_get_err_str(status) );
- /*
- * Undo CA list
- */
- dapli_destroy_root_ca_list (&dapl_ibal_root);
- }
- }
- return -1;
-}
-
-
-int32_t dapls_ib_release (void)
-{
- dapl_ibal_root.shutdown = TRUE;
-
- dapli_shutdown_ca_access();
-
- /*
- * If shutdown not complete, wait for it
- */
- if (dapl_ibal_root.shutdown)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIR: timeout waiting for completion\n");
- }
-
- if ( dapl_ibal_root.h_al != NULL )
- {
- (void) ib_close_al (dapl_ibal_root.h_al);
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIR: ib_close_al() returns\n");
- dapl_ibal_root.h_al = NULL;
- }
-#ifdef DBG
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> %s: Exit\n",__FUNCTION__);
-#endif
-
- return 0;
-}
-
-
-/*
- * dapls_ib_enum_hcas
- *
- * Enumerate all HCAs on the system
- *
- * Input:
- * none
- *
- * Output:
- * hca_names Array of hca names
- * total_hca_count
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_enum_hcas (
- IN const char *vendor,
- OUT DAPL_HCA_NAME **hca_names,
- OUT DAT_COUNT *total_hca_count )
-{
- intn_t guid_count;
- ib_api_status_t ib_status;
- UNREFERENCED_PARAMETER(vendor);
-
- ib_status = ib_get_ca_guids (dapl_ibal_root.h_al, NULL, &(size_t)guid_count);
- if (ib_status != IB_INSUFFICIENT_MEMORY)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DsIEH: ib_get_ca_guids failed '%s'\n",
- ib_get_err_str(ib_status) );
- return dapl_ib_status_convert (ib_status);
- }
-
- if (guid_count == 0)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: ib_get_ca_guids no HCA in the system\n",
- "DsIEH");
- return (DAT_PROVIDER_NOT_FOUND);
- }
-
- if (guid_count > DAPL_IBAL_MAX_CA)
- {
- guid_count = DAPL_IBAL_MAX_CA;
- }
-
- gp_ibal_ca_guid_tbl = (ib_net64_t *)dapl_os_alloc ((int)(guid_count * sizeof (ib_net64_t)) );
-
- if (gp_ibal_ca_guid_tbl == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: can not alloc resources @line%d\n", "DsIEH",
- __LINE__);
- return (DAT_INSUFFICIENT_RESOURCES);
- }
-
- ib_status = ib_get_ca_guids ( dapl_ibal_root.h_al,
- gp_ibal_ca_guid_tbl,
- &(size_t)guid_count);
-
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DsIEH: ib_get_ca_guids failed status = %s\n",
- ib_get_err_str(ib_status) );
- return dapl_ib_status_convert (ib_status);
- }
-
- *hca_names = (DAPL_HCA_NAME*)
- dapl_os_alloc ((int)(guid_count * sizeof (DAPL_HCA_NAME)));
-
- if (*hca_names == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: can not alloc resources @line%d\n",
- "DsIEH", __LINE__);
- return (DAT_INSUFFICIENT_RESOURCES);
- }
-
- dapl_os_memcpy (*hca_names,
- dapl_ibal_hca_name_array,
- (int)(guid_count * sizeof (DAPL_HCA_NAME)) );
-
- *total_hca_count = (DAT_COUNT)guid_count;
-
- {
- int i;
-
- for (i = 0; i < guid_count; i++)
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIEH: %d) hca_names = %s\n",
- i, dapl_ibal_hca_name_array[i]);
- }
-
- return (DAT_SUCCESS);
-}
-
-
-
-IB_HCA_NAME
-dapl_ib_convert_name(
- IN char *name)
-{
- int i;
-
- if (gp_ibal_ca_guid_tbl == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DICN: found no HCA with name %s\n", name );
- return 0;
- }
-
- for (i = 0; i < DAPL_IBAL_MAX_CA; i++)
- {
- if (strcmp (name, dapl_ibal_hca_name_array[i]) == 0)
- {
- break;
- }
- }
-
- if (i >= DAPL_IBAL_MAX_CA)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DICN: can't find any HCA with name %s\n", name);
- return 0;
- }
-
- return (gp_ibal_ca_guid_tbl[i]);
-}
-
-
-/*
- * dapls_ib_open_hca
- *
- * Open HCA
- *
- * Input:
- * *hca_name pointer to provider device name
- * *ib_hca_handle_p pointer to provide HCA handle
- *
- * Output:
- * none
- *
- * Return:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN dapls_ib_open_hca ( IN char *hca_name,
- IN DAPL_HCA *p_hca )
-{
- dapl_ibal_ca_t *p_ca;
- IB_HCA_NAME ca_guid;
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL," open_hca: %s - %p\n", hca_name, p_hca);
-
- if (gp_ibal_ca_guid_tbl == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIOH: found no HCA with ca_guid"
- F64x "\n", hca_name);
- return (DAT_PROVIDER_NOT_FOUND);
- }
-
- ca_guid = dapl_ib_convert_name(hca_name);
-
- p_ca = dapli_add_ca (dapl_ibal_root.h_al, ca_guid);
-
- if (p_ca == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DsIOH: can not create ca for '%s' guid " F64x "\n",
- hca_name, ca_guid);
- return (DAT_INSUFFICIENT_RESOURCES);
- }
-
- p_hca->ib_hca_handle = (ib_hca_handle_t) p_ca;
- p_hca->ib_trans.d_hca = p_hca; // back-link
-
- /* initialize hca wait object for uAT event */
- dapl_os_wait_object_init(&p_hca->ib_trans.wait_object);
-
-#if SOCK_CM
- {
- DAT_RETURN dat_status;
-
- dat_status = dapli_init_sock_cm(p_hca);
- if ( dat_status != DAT_SUCCESS )
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- " %s() failed to init sock_CM\n", __FUNCTION__);
- return DAT_INTERNAL_ERROR;
- }
-
- /* initialize cr_list lock */
- dat_status = dapl_os_lock_init(&p_hca->ib_trans.lock);
- if (dat_status != DAT_SUCCESS)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR, " %s() failed to init lock\n",
- __FUNCTION__);
- return DAT_INTERNAL_ERROR;
- }
-
- /* initialize CM list for listens on this HCA */
- dapl_llist_init_head((DAPL_LLIST_HEAD*)&p_hca->ib_trans.list);
- }
-#endif
-
- return (DAT_SUCCESS);
-}
-
-
-/*
- * dapls_ib_close_hca
- *
- * Open HCA
- *
- * Input:
- * ib_hca_handle provide HCA handle
- *
- * Output:
- * none
- *
- * Return:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN dapls_ib_close_hca ( IN DAPL_HCA *p_hca )
-{
- dapl_ibal_ca_t *p_ca;
-
- p_ca = (dapl_ibal_ca_t *) p_hca->ib_hca_handle;
-
-#if SOCK_CM
-#endif
- /*
- * Remove it from the list
- */
- TAKE_LOCK (dapl_ibal_root.ca_lock);
- {
- cl_qlist_remove_item (&dapl_ibal_root.ca_head, &p_ca->next);
- }
- RELEASE_LOCK (dapl_ibal_root.ca_lock);
-
- dapli_shutdown_port_access (p_ca);
-
- /*
- * Remove the constructor reference
- */
- REMOVE_REFERENCE (&p_ca->refs);
-
- cl_spinlock_destroy (&p_ca->port_lock);
- cl_spinlock_destroy (&p_ca->evd_cb_lock);
-
- if (p_ca->p_ca_attr)
- dapl_os_free (p_ca->p_ca_attr, sizeof (ib_ca_attr_t));
-
- (void) ib_close_ca (p_ca->h_ca, NULL /* close_callback */);
-
- p_hca->ib_hca_handle = IB_INVALID_HANDLE;
- dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));
-
- return (DAT_SUCCESS);
-}
-
-
-
-/*
- * dapl_ib_pd_alloc
- *
- * Alloc a PD
- *
- * Input:
- * ia_handle IA handle
- * PZ_ptr pointer to PZEVD struct
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_pd_alloc (
- IN DAPL_IA *ia,
- IN DAPL_PZ *pz)
-{
- ib_api_status_t ib_status;
- dapl_ibal_ca_t *p_ca;
-
- p_ca = (dapl_ibal_ca_t *) ia->hca_ptr->ib_hca_handle;
-
- ib_status = ib_alloc_pd (
- p_ca->h_ca,
- IB_PDT_NORMAL,
- ia,
- &pz->pd_handle );
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-/*
- * dapl_ib_pd_free
- *
- * Free a PD
- *
- * Input:
- * PZ_ptr pointer to PZ struct
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_pd_free (
- IN DAPL_PZ *pz)
-{
- ib_api_status_t ib_status;
-
- ib_status = ib_dealloc_pd (pz->pd_handle, /* destroy_callback */ NULL);
-
- pz->pd_handle = IB_INVALID_HANDLE;
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-/*
- * dapl_ib_mr_register
- *
- * Register a virtual memory region
- *
- * Input:
- * ia_handle IA handle
- * lmr pointer to dapl_lmr struct
- * virt_addr virtual address of beginning of mem region
- * length length of memory region
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mr_register (
- IN DAPL_IA *ia,
- IN DAPL_LMR *lmr,
- IN DAT_PVOID virt_addr,
- IN DAT_VLEN length,
- IN DAT_MEM_PRIV_FLAGS privileges,
- IN DAT_VA_TYPE va_type)
-{
- ib_api_status_t ib_status;
- ib_mr_handle_t mr_handle;
- ib_mr_create_t mr_create;
- uint32_t l_key, r_key;
-
- if ( ia == NULL || ia->header.magic != DAPL_MAGIC_IA )
- {
- return DAT_INVALID_HANDLE;
- }
-
- /* IBAL does not support */
- if (va_type == DAT_VA_TYPE_ZB) {
- dapl_dbg_log(DAPL_DBG_TYPE_ERR,
- "--> va_type == DAT_VA_TYPE_ZB: NOT SUPPORTED\n");
- return DAT_ERROR (DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
- }
-
- mr_create.vaddr = (void *) virt_addr;
- mr_create.length = (size_t)length;
- mr_create.access_ctrl = dapl_lmr_convert_privileges (privileges);
- mr_create.access_ctrl |= IB_AC_MW_BIND;
-
- if (lmr->param.mem_type == DAT_MEM_TYPE_SHARED_VIRTUAL)
- {
- ib_status = ib_reg_shmid (
- ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,
- (const uint8_t*)lmr->shmid,
- &mr_create,
- (uint64_t *)&virt_addr,
- &l_key,
- &r_key,
- &mr_handle);
- }
- else
- {
- ib_status = ib_reg_mem ( ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,
- &mr_create,
- &l_key,
- &r_key,
- &mr_handle );
- }
-
- if (ib_status != IB_SUCCESS)
- {
- return (dapl_ib_status_convert (ib_status));
- }
-
- /* DAT/DAPL expects context in host order */
- l_key = cl_ntoh32(l_key);
- r_key = cl_ntoh32(r_key);
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMR: lmr (%p) lkey = 0x%x "
- "r_key= %#x mr_handle %p vaddr 0x%LX len 0x%LX\n",
- lmr, l_key, r_key, mr_handle, virt_addr, length);
-
- lmr->param.lmr_context = l_key;
- lmr->param.rmr_context = r_key;
- lmr->param.registered_size = length;
- lmr->param.registered_address = (DAT_VADDR)virt_addr;
- lmr->mr_handle = mr_handle;
-
- return (DAT_SUCCESS);
-}
-
-
-/*
- * dapl_ib_mr_deregister
- *
- * Free a memory region
- *
- * Input:
- * lmr pointer to dapl_lmr struct
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mr_deregister (
- IN DAPL_LMR *lmr)
-{
- ib_api_status_t ib_status;
-
- ib_status = ib_dereg_mr (lmr->mr_handle);
-
- if (ib_status != IB_SUCCESS)
- {
- return dapl_ib_status_convert (ib_status);
- }
-
- lmr->param.lmr_context = 0;
- lmr->mr_handle = IB_INVALID_HANDLE;
-
- return (DAT_SUCCESS);
-}
-
-
-/*
- * dapl_ib_mr_register_shared
- *
- * Register a virtual memory region
- *
- * Input:
- * ia_handle IA handle
- * lmr pointer to dapl_lmr struct
- * virt_addr virtual address of beginning of mem region
- * length length of memory region
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mr_register_shared (
- IN DAPL_IA *ia,
- IN DAPL_LMR *lmr,
- IN DAT_MEM_PRIV_FLAGS privileges,
- IN DAT_VA_TYPE va_type )
-{
- DAT_VADDR virt_addr;
- ib_mr_handle_t mr_handle;
- ib_api_status_t ib_status;
- ib_mr_handle_t new_mr_handle;
- ib_access_t access_ctrl;
- uint32_t l_key, r_key;
- ib_mr_create_t mr_create;
- if ( ia == NULL || ia->header.magic != DAPL_MAGIC_IA )
- {
- return DAT_INVALID_HANDLE;
- }
-
- /* IBAL does not support?? */
- if (va_type == DAT_VA_TYPE_ZB) {
- dapl_dbg_log(DAPL_DBG_TYPE_ERR,
- " va_type == DAT_VA_TYPE_ZB: NOT SUPPORTED\n");
- return DAT_ERROR (DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE);
- }
-
- virt_addr = dapl_mr_get_address (lmr->param.region_desc,
- lmr->param.mem_type);
-
- access_ctrl = dapl_lmr_convert_privileges (privileges);
- access_ctrl |= IB_AC_MW_BIND;
-
- mr_create.vaddr = (void *) virt_addr;
- mr_create.access_ctrl = access_ctrl;
- mr_handle = (ib_mr_handle_t) lmr->mr_handle;
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIMRS: orig mr_handle %p vaddr %p\n",
- mr_handle, virt_addr);
-
- if (lmr->param.mem_type == DAT_MEM_TYPE_SHARED_VIRTUAL)
- {
- ib_status = ib_reg_shmid ( ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,
- (const uint8_t*)lmr->shmid,
- &mr_create,
- &virt_addr,
- &l_key,
- &r_key,
- &new_mr_handle );
- }
- else
- {
-
- ib_status = ib_reg_shared ( mr_handle,
- ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,
- access_ctrl,
- /* in/out */(DAT_UINT64 *)&virt_addr,
- &l_key,
- &r_key,
- &new_mr_handle );
- }
-
- if (ib_status != IB_SUCCESS)
- {
- return dapl_ib_status_convert (ib_status);
- }
- /*
- * FIXME - Vu
- * What if virt_addr as an OUTPUT having the actual virtual address
- * assigned to the register region
- */
-
- /* DAT/DAPL expects context to be in host order */
- l_key = cl_ntoh32(l_key);
- r_key = cl_ntoh32(r_key);
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMRS: lmr (%p) lkey = 0x%x "
- "new mr_handle %p vaddr %p\n",
- lmr, l_key, new_mr_handle, virt_addr);
-
- lmr->param.lmr_context = l_key;
- lmr->param.rmr_context = r_key;
- lmr->param.registered_address = (DAT_VADDR) (uintptr_t) virt_addr;
- lmr->mr_handle = new_mr_handle;
-
- return (DAT_SUCCESS);
-}
-
-
-/*
- * dapls_ib_mw_alloc
- *
- * Bind a protection domain to a memory window
- *
- * Input:
- * rmr Initialized rmr to hold binding handles
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mw_alloc ( IN DAPL_RMR *rmr )
-{
- ib_api_status_t ib_status;
- uint32_t r_key;
- ib_mw_handle_t mw_handle;
-
- ib_status = ib_create_mw (
- ((DAPL_PZ *)rmr->param.pz_handle)->pd_handle,
- &r_key,
- &mw_handle);
-
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DsIMA: create MW failed = %s\n",
- ib_get_err_str(ib_status) );
- return dapl_ib_status_convert (ib_status);
- }
-
- rmr->mw_handle = mw_handle;
- rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(r_key);
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIMA: mw_handle %p r_key = 0x%x\n",
- mw_handle, rmr->param.rmr_context);
-
- return (DAT_SUCCESS);
-}
-
-
-/*
- * dapls_ib_mw_free
- *
- * Release bindings of a protection domain to a memory window
- *
- * Input:
- * rmr Initialized rmr to hold binding handles
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mw_free (
- IN DAPL_RMR *rmr)
-{
- ib_api_status_t ib_status;
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIMF: mw_handle %p\n", rmr->mw_handle);
-
- ib_status = ib_destroy_mw (rmr->mw_handle);
-
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMF: Free MW failed = %s\n",
- ib_get_err_str(ib_status));
- return dapl_ib_status_convert (ib_status);
- }
-
- rmr->param.rmr_context = 0;
- rmr->mw_handle = IB_INVALID_HANDLE;
-
- return (DAT_SUCCESS);
-}
-
-/*
- * dapls_ib_mw_bind
- *
- * Bind a protection domain to a memory window
- *
- * Input:
- * rmr Initialized rmr to hold binding handles
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mw_bind (
- IN DAPL_RMR *rmr,
- IN DAPL_LMR *lmr,
- IN DAPL_EP *ep,
- IN DAPL_COOKIE *cookie,
- IN DAT_VADDR virtual_address,
- IN DAT_VLEN length,
- IN DAT_MEM_PRIV_FLAGS mem_priv,
- IN ib_bool_t is_signaled)
-{
- ib_api_status_t ib_status;
- ib_bind_wr_t bind_wr_prop;
- uint32_t new_rkey;
-
- bind_wr_prop.local_ds.vaddr = virtual_address;
- bind_wr_prop.local_ds.length = (uint32_t)length;
- bind_wr_prop.local_ds.lkey = cl_hton32(lmr->param.lmr_context);
- bind_wr_prop.current_rkey = cl_hton32(rmr->param.rmr_context);
- bind_wr_prop.access_ctrl = dapl_rmr_convert_privileges (mem_priv);
- bind_wr_prop.send_opt = (is_signaled == TRUE) ?
- IB_SEND_OPT_SIGNALED : 0;
- bind_wr_prop.wr_id = (uint64_t) ((uintptr_t) cookie);
- bind_wr_prop.h_mr = lmr->mr_handle;
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMB: mr_handle %p, mw_handle %p "
- "vaddr %#I64x length %#I64x\n",
- lmr->mr_handle, rmr->mw_handle, virtual_address, length);
-
- ib_status = ib_bind_mw (
- rmr->mw_handle,
- ep->qp_handle,
- &bind_wr_prop,
- &new_rkey);
-
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMB: Bind MW failed = %s\n",
- ib_get_err_str(ib_status));
- return (dapl_ib_status_convert (ib_status));
- }
-
- rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(new_rkey);
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIMB: new_rkey = 0x%x\n", rmr->param.rmr_context);
-
- return (DAT_SUCCESS);
-}
-
-/*
- * dapls_ib_mw_unbind
- *
- * Unbind a memory window
- *
- * Input:
- * rmr Initialized rmr to hold binding handles
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- *
- */
-DAT_RETURN
-dapls_ib_mw_unbind (
- IN DAPL_RMR *rmr,
- IN DAPL_EP *ep,
- IN DAPL_COOKIE *cookie,
- IN ib_bool_t is_signaled)
-{
- ib_api_status_t ib_status;
- ib_bind_wr_t bind_wr_prop;
- uint32_t new_rkey;
-
- bind_wr_prop.local_ds.vaddr = 0;
- bind_wr_prop.local_ds.length = 0;
- bind_wr_prop.local_ds.lkey = 0;
- bind_wr_prop.access_ctrl = 0;
- bind_wr_prop.send_opt = (is_signaled == TRUE) ?
- IB_SEND_OPT_SIGNALED : 0;
- bind_wr_prop.wr_id = (uint64_t) ((uintptr_t) cookie);
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIMU: mw_handle = %p\n", rmr->mw_handle);
-
- ib_status = ib_bind_mw (
- rmr->mw_handle,
- ep->qp_handle,
- &bind_wr_prop,
- &new_rkey);
-
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMU: Unbind MW failed = %s\n",
- ib_get_err_str(ib_status));
- return (dapl_ib_status_convert (ib_status));
- }
-
- rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(new_rkey);
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- "--> DsIMU: unbind new_rkey 0x%x\n", rmr->param.rmr_context);
-
- return (DAT_SUCCESS);
-}
-
-
-/*
- * dapls_ib_setup_async_callback
- *
- * Set up an asynchronous callbacks of various kinds
- *
- * Input:
- * ia_handle IA handle
- * handler_type type of handler to set up
- * callback_handle handle param for completion callbacks
- * callback callback routine pointer
- * context argument for callback routine
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INSUFFICIENT_RESOURCES
- * DAT_INVALID_PARAMETER
- *
- */
-DAT_RETURN
-dapls_ib_setup_async_callback (
- IN DAPL_IA *ia_ptr,
- IN DAPL_ASYNC_HANDLER_TYPE handler_type,
- IN DAPL_EVD *evd_ptr,
- IN ib_async_handler_t callback,
- IN void *context )
-{
- dapl_ibal_ca_t *p_ca;
- dapl_ibal_evd_cb_t *evd_cb;
-
- dapl_dbg_log (DAPL_DBG_TYPE_UTIL,
- " setup_async_cb: ia %p type %d hdl %p cb %p ctx %p\n",
- ia_ptr, handler_type, evd_ptr, callback, context);
-
- p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;
-
- if (p_ca == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsISAC: can't find %s HCA\n",
- (ia_ptr->header.provider)->device_name);
- return (DAT_INVALID_HANDLE);
- }
-
- if (handler_type != DAPL_ASYNC_CQ_COMPLETION)
- {
- evd_cb = dapli_find_evd_cb_by_context (context, p_ca);
-
- if (evd_cb == NULL)
- {
- /*
- * No record for this evd. We allocate one
- */
- evd_cb = dapl_os_alloc (sizeof (dapl_ibal_evd_cb_t));
- dapl_os_memzero (evd_cb, sizeof(dapl_ibal_evd_cb_t));
-
- if (evd_cb == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> %s: can't alloc res\n","DsISAC");
- return (DAT_INSUFFICIENT_RESOURCES);
- }
-
- evd_cb->context = context;
-
- /*
- * Add the new EVD CB to the list
- */
- LOCK_INSERT_TAIL( p_ca->evd_cb_lock,
- p_ca->evd_cb_head,
- evd_cb->next );
- }
-
- switch (handler_type)
- {
- case DAPL_ASYNC_UNAFILIATED:
- evd_cb->pfn_async_err_cb = callback;
- break;
- case DAPL_ASYNC_CQ_ERROR:
- evd_cb->pfn_async_cq_err_cb = callback;
- break;
- case DAPL_ASYNC_QP_ERROR:
- evd_cb->pfn_async_qp_err_cb = callback;
- break;
- default:
- break;
- }
-
- }
-
- return DAT_SUCCESS;
-}
-
-
-/*
- * dapls_ib_query_gid
- *
- * Query the hca for the gid of the 1st active port.
- *
- * Input:
- * hca_handl hca handle
- * ep_attr attribute of the ep
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- * DAT_INVALID_PARAMETER
- */
-
-DAT_RETURN
-dapls_ib_query_gid( IN DAPL_HCA *hca_ptr,
- IN GID *gid )
-{
- dapl_ibal_ca_t *p_ca;
- ib_ca_attr_t *p_hca_attr;
- ib_api_status_t ib_status;
- ib_hca_port_t port_num;
-
- p_ca = (dapl_ibal_ca_t *) hca_ptr->ib_hca_handle;
-
- if (p_ca == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "%s() invalid hca_ptr %p", __FUNCTION__, hca_ptr);
- return DAT_INVALID_HANDLE;
- }
-
- ib_status = ib_query_ca (
- p_ca->h_ca,
- p_ca->p_ca_attr,
- &p_ca->ca_attr_size);
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "%s() ib_query_ca returned failed status = %s\n",
- ib_get_err_str(ib_status));
- return dapl_ib_status_convert (ib_status);
- }
-
- p_hca_attr = p_ca->p_ca_attr;
- port_num = hca_ptr->port_num - 1;
-
- gid->gid_prefix = p_hca_attr->p_port_attr[port_num].p_gid_table->unicast.prefix;
- gid->guid = p_hca_attr->p_port_attr[port_num].p_gid_table->unicast.interface_id;
- return DAT_SUCCESS;
-}
-
-
-/*
- * dapls_ib_query_hca
- *
- * Query the hca attribute
- *
- * Input:
- * hca_handl hca handle
- * ep_attr attribute of the ep
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_PARAMETER
- */
-
-DAT_RETURN dapls_ib_query_hca (
- IN DAPL_HCA *hca_ptr,
- OUT DAT_IA_ATTR *ia_attr,
- OUT DAT_EP_ATTR *ep_attr,
- OUT DAT_SOCK_ADDR6 *ip_addr)
-{
- ib_ca_attr_t *p_hca_attr;
- dapl_ibal_ca_t *p_ca;
- ib_api_status_t ib_status;
- ib_hca_port_t port_num;
- GID gid;
- DAT_SOCK_ADDR6 *p_sock_addr;
- DAT_RETURN dat_status = DAT_SUCCESS;
- port_num = hca_ptr->port_num;
-
- p_ca = (dapl_ibal_ca_t *) hca_ptr->ib_hca_handle;
-
- if (p_ca == NULL)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> %s: invalid handle %p",
- "DsIQH", hca_ptr);
- return (DAT_INVALID_HANDLE);
- }
-
- ib_status = ib_query_ca (
- p_ca->h_ca,
- p_ca->p_ca_attr,
- &p_ca->ca_attr_size);
- if (ib_status != IB_SUCCESS)
- {
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- "--> DsIQH: ib_query_ca returned failed status = %s\n",
- ib_get_err_str(ib_status));
- return (dapl_ib_status_convert (ib_status));
- }
-
- p_hca_attr = p_ca->p_ca_attr;
-
- if (ip_addr != NULL)
- {
- p_sock_addr = dapl_os_alloc(sizeof(DAT_SOCK_ADDR6));
- if ( !p_sock_addr )
- {
- dat_status = DAT_INSUFFICIENT_RESOURCES;
- dapl_dbg_log ( DAPL_DBG_TYPE_ERR,
- " Query Hca alloc Err: status %d\n",
- dat_status);
- return dat_status;
- }
- dapl_os_memzero(p_sock_addr, sizeof(DAT_SOCK_ADDR6));
-
- gid.gid_prefix = p_hca_attr->p_port_attr[port_num-1].p_gid_table->unicast.prefix;
- gid.guid = p_hca_attr->p_port_attr[port_num-1].p_gid_table->unicast.interface_id;
-
- dat_status = dapls_ns_map_ipaddr( hca_ptr,
- gid,
- (DAT_IA_ADDRESS_PTR)p_sock_addr);
-
- if ( dat_status != DAT_SUCCESS )
- {
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- " SA Query for local IP failed= %d\n", dat_status );
- /* what to do next ? */
- }
- else
- {
- dapl_dbg_log (DAPL_DBG_TYPE_CM, "SA query GID for IP: ");
- dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%0d:%d:%d:%d\n",
- (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[2]&0xff,
- (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[3]&0xff,
- (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[4]&0xff,
- (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[5]&0xff);
- }
-
- hca_ptr->hca_address = *p_sock_addr;
-
- /* if structure address not from our hca_ptr */
- if ( ip_addr != &hca_ptr->hca_address )
- {
- *ip_addr = *p_sock_addr;
- }
-
- dapl_os_free (p_sock_addr, sizeof(DAT_SOCK_ADDR6));
-
- } /* ip_addr != NULL */
-
- if ( ia_attr != NULL )
- {
- dapl_os_memzero( ia_attr->adapter_name,
- (int)sizeof(ia_attr->adapter_name ));
- dapl_os_memcpy(ia_attr->adapter_name,
- DAT_ADAPTER_NAME,
- min ( (int)dapl_os_strlen(DAT_ADAPTER_NAME),
- (int)(DAT_NAME_MAX_LENGTH)-1 ) );
-
- dapl_os_memzero ( ia_attr->vendor_name,
- (int)sizeof(ia_attr->vendor_name) );
- dapl_os_memcpy ( ia_attr->vendor_name,
- DAT_VENDOR_NAME,
- min ( (int)dapl_os_strlen(DAT_VENDOR_NAME),
- (int)(DAT_NAME_MAX_LENGTH)-1 ) );
-
- /* FIXME : Vu
- * this value should be revisited
- * It can be set by DAT consumers
- */
- ia_attr->ia_address_ptr = (DAT_PVOID)&hca_ptr->hca_address;
- ia_attr->hardware_version_major = p_hca_attr->dev_id;
- ia_attr->hardware_version_minor = p_hca_attr->revision;
- ia_attr->max_eps = p_hca_attr->max_qps;
- ia_attr->max_dto_per_ep = p_hca_attr->max_wrs;
- ia_attr->max_rdma_read_per_ep = p_hca_attr->max_qp_resp_res;
- ia_attr->max_evds = p_hca_attr->max_cqs;
- ia_attr->max_evd_qlen = p_hca_attr->max_cqes;
- ia_attr->max_iov_segments_per_dto = p_hca_attr->max_sges;
- ia_attr->max_lmrs = p_hca_attr->init_regions;
- ia_attr->max_lmr_block_size = p_hca_attr->init_region_size;
- ia_attr->max_rmrs = p_hca_attr->init_windows;
- ia_attr->max_lmr_virtual_address = p_hca_attr->max_addr_handles;
- ia_attr->max_rmr_target_address = p_hca_attr->max_addr_handles;
- ia_attr->max_pzs = p_hca_attr->max_pds;
- /*
- * DAT spec does not tie max_mtu_size with IB MTU
- *
- ia_attr->max_mtu_size =
- dapl_ibal_mtu_table[p_hca_attr->p_port_attr->mtu];
- */
- ia_attr->max_mtu_size =
- p_hca_attr->p_port_attr->max_msg_size;
- ia_attr->max_rdma_size =
- p_hca_attr->p_port_attr->max_msg_size;
- ia_attr->num_transport_attr = 0;
- ia_attr->transport_attr = NULL;
- ia_attr->num_vendor_attr = 0;
- ia_attr->vendor_attr = NULL;
- ia_attr->max_iov_segments_per_rdma_read = p_hca_attr->max_sges;
-
-#ifdef DAT_EXTENSIONS
- ia_attr->extension_supported = DAT_EXTENSION_IB;
- ia_attr->extension_version = DAT_IB_EXTENSION_VERSION;
-#endif
-
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
- " --> DsIMU_qHCA: (ver=%x) ep %d ep_q %d evd %d evd_q %d\n",
- ia_attr->hardware_version_major,
- ia_attr->max_eps, ia_attr->max_dto_per_ep,
- ia_attr->max_evds, ia_attr->max_evd_qlen );
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
- " --> DsIMU_qHCA: mtu %llu rdma %llu iov %d lmr %d rmr %d"
- " rdma_io %d\n",
- ia_attr->max_mtu_size, ia_attr->max_rdma_size,
- ia_attr->max_iov_segments_per_dto, ia_attr->max_lmrs,
- ia_attr->max_rmrs, ia_attr->max_rdma_read_per_ep );
- }
-
- if ( ep_attr != NULL )
- {
- (void) dapl_os_memzero(ep_attr, sizeof(*ep_attr));
- /*
- * DAT spec does not tie max_mtu_size with IB MTU
- *
- ep_attr->max_mtu_size =
- dapl_ibal_mtu_table[p_hca_attr->p_port_attr->mtu];
- */
- ep_attr->max_mtu_size = p_hca_attr->p_port_attr->max_msg_size;
- ep_attr->max_rdma_size = p_hca_attr->p_port_attr->max_msg_size;
- ep_attr->max_recv_dtos = p_hca_attr->max_wrs;
- ep_attr->max_request_dtos = p_hca_attr->max_wrs;
- ep_attr->max_recv_iov = p_hca_attr->max_sges;
- ep_attr->max_request_iov = p_hca_attr->max_sges;
- ep_attr->max_rdma_read_in = p_hca_attr->max_qp_resp_res;
- ep_attr->max_rdma_read_out= p_hca_attr->max_qp_resp_res;
-
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,
- " --> DsIMU_qHCA: msg %llu dto %d iov %d rdma i%d,o%d\n",
- ep_attr->max_mtu_size,
- ep_attr->max_recv_dtos, ep_attr->max_recv_iov,
- ep_attr->max_rdma_read_in, ep_attr->max_rdma_read_out);
- }
- return DAT_SUCCESS;
-}
-
-
-DAT_RETURN
-dapls_ib_completion_poll ( IN DAPL_HCA *p_hca,
- IN DAPL_EVD *p_evd,
- IN ib_work_completion_t *cqe_ptr )
-{
- ib_api_status_t ib_status;
- ib_work_completion_t *cqe_filled;
-
- /*
- * FIXME - Vu
- * Now we only poll for one cqe. We can poll for more than
- * one completions later for better. However, this requires
- * to change the logic in dapl_evd_dto_callback function
- * to process more than one completion.
- */
- cqe_ptr->p_next = NULL;
- cqe_filled = NULL;
-
- if ( !p_hca->ib_hca_handle )
- {
- return DAT_INVALID_HANDLE;
- }
-
- ib_status = ib_poll_cq (p_evd->ib_cq_handle, &cqe_ptr, &cqe_filled);
-
- if ( ib_status == IB_INVALID_CQ_HANDLE )
- {
- ib_status = IB_NOT_FOUND;
- }
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-DAT_RETURN
-dapls_ib_completion_notify ( IN ib_hca_handle_t hca_handle,
- IN DAPL_EVD *p_evd,
- IN ib_notification_type_t type )
-{
- ib_api_status_t ib_status;
- DAT_BOOLEAN solic_notify;
-
- if ( !hca_handle )
- {
- return DAT_INVALID_HANDLE;
- }
- solic_notify = (type == IB_NOTIFY_ON_SOLIC_COMP) ? DAT_TRUE : DAT_FALSE;
- ib_status = ib_rearm_cq ( p_evd->ib_cq_handle, solic_notify );
-
- return dapl_ib_status_convert (ib_status);
-}
-
-
-
-DAT_RETURN
-dapls_ib_wait_object_create (
- IN cl_waitobj_handle_t* p_cq_wait_obj_handle)
-{
- cl_status_t cl_status;
-
- cl_status = cl_waitobj_create (FALSE /* auto_reset */, p_cq_wait_obj_handle);
-
- if (cl_status == CL_SUCCESS)
- return DAT_SUCCESS;
-
- return DAT_INTERNAL_ERROR;
-}
-
-
-DAT_RETURN
-dapls_ib_wait_object_destroy (
- IN cl_waitobj_handle_t cq_wait_obj_handle)
-{
- cl_status_t cl_status;
-
- cl_status = cl_waitobj_destroy (cq_wait_obj_handle);
-
- if (cl_status == CL_SUCCESS)
- return DAT_SUCCESS;
-
- return DAT_INTERNAL_ERROR;
-}
-
-
-DAT_RETURN
-dapls_ib_wait_object_wakeup (
- IN cl_waitobj_handle_t cq_wait_obj_handle)
-{
- cl_status_t cl_status;
-
- cl_status = cl_waitobj_signal (cq_wait_obj_handle);
-
- if (cl_status == CL_SUCCESS)
- return DAT_SUCCESS;
-
- return DAT_INTERNAL_ERROR;
-}
-
-
-DAT_RETURN
-dapls_ib_wait_object_wait (
- IN cl_waitobj_handle_t cq_wait_obj_handle,
- IN uint32_t timeout)
-{
- cl_status_t cl_status;
-
- cl_status = cl_waitobj_wait_on (cq_wait_obj_handle, timeout, TRUE );
-
- switch (cl_status)
- {
- case CL_SUCCESS:
- return DAT_SUCCESS;
-
- case CL_TIMEOUT:
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> wait_object_wait: cl_timeout: %d\n", timeout);
- return DAT_TIMEOUT_EXPIRED;
-
- case CL_NOT_DONE:
- return DAT_SUCCESS;
-
- default:
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,
- "--> wait_object_wait: cl_error: %d\n", cl_status);
- return DAT_INTERNAL_ERROR;
- }
-}
-
-
-/*
- * dapls_ib_get_async_event
- *
- * Translate an asynchronous event type to the DAT event.
- * Note that different providers have different sets of errors.
- *
- * Input:
- * cause_ptr provider event cause
- *
- * Output:
- * async_event DAT mapping of error
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_NOT_IMPLEMENTED Caller is not interested this event
- */
-
-DAT_RETURN dapls_ib_get_async_event(
- IN ib_async_event_rec_t *cause_ptr,
- OUT DAT_EVENT_NUMBER *async_event)
-{
- ib_async_event_t event_id;
- DAT_RETURN dat_status;
-
- dat_status = DAT_SUCCESS;
- event_id = cause_ptr->code;
-
- dapl_dbg_log (DAPL_DBG_TYPE_WARN, "--> DsAE: event_id = %d%d\n", event_id);
-
- switch (event_id )
- {
- case IB_AE_SQ_ERROR:
- case IB_AE_SQ_DRAINED:
- case IB_AE_RQ_ERROR:
- {
- *async_event = DAT_ASYNC_ERROR_EP_BROKEN;
- break;
- }
-
- /* INTERNAL errors */
- case IB_AE_QP_FATAL:
- case IB_AE_CQ_ERROR:
- case IB_AE_LOCAL_FATAL:
- case IB_AE_WQ_REQ_ERROR:
- case IB_AE_WQ_ACCESS_ERROR:
- {
- *async_event = DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR;
- break;
- }
-
- /* CATASTROPHIC errors */
- case IB_AE_FLOW_CTRL_ERROR:
- case IB_AE_BUF_OVERRUN:
- {
- *async_event = DAT_ASYNC_ERROR_IA_CATASTROPHIC;
- break;
- }
-
- default:
- {
- /*
- * Errors we are not interested in reporting:
- * IB_AE_QP_APM
- * IB_AE_PKEY_TRAP
- * IB_AE_QKEY_TRAP
- * IB_AE_MKEY_TRAP
- * IB_AE_PORT_TRAP
- * IB_AE_QP_APM_ERROR
- * IB_AE_PORT_ACTIVE
- * ...
- */
- dat_status = DAT_NOT_IMPLEMENTED;
- }
-
- }
-
- return dat_status;
-}
-
-/*
- * dapls_ib_get_dto_status
- *
- * Return the DAT status of a DTO operation
- *
- * Input:
- * cqe_ptr pointer to completion queue entry
- *
- * Output:
- * none
- *
- * Returns:
- * Value from ib_status_map table above
- */
-
-DAT_DTO_COMPLETION_STATUS
-dapls_ib_get_dto_status(
- IN ib_work_completion_t *cqe_ptr)
-{
- ib_uint32_t ib_status;
-
- ib_status = DAPL_GET_CQE_STATUS (cqe_ptr);
-
- switch (ib_status)
- {
- case IB_COMP_ST_SUCCESS :
- return DAT_DTO_SUCCESS;
-
- case IB_COMP_ST_LOCAL_LEN_ERR:
- return DAT_DTO_ERR_LOCAL_LENGTH;
-
- case IB_COMP_ST_LOCAL_OP_ERR:
- return DAT_DTO_ERR_LOCAL_EP;
-
- case IB_COMP_ST_LOCAL_PROTECT_ERR:
- return DAT_DTO_ERR_LOCAL_PROTECTION;
-
- case IB_COMP_ST_WR_FLUSHED_ERR:
- return DAT_DTO_ERR_FLUSHED;
-
- case IB_COMP_ST_MW_BIND_ERR:
- return DAT_RMR_OPERATION_FAILED;
-
- case IB_COMP_ST_REM_ACC_ERR:
- return DAT_DTO_ERR_REMOTE_ACCESS;
-
- case IB_COMP_ST_REM_OP_ERR:
- return DAT_DTO_ERR_REMOTE_RESPONDER;
-
- case IB_COMP_ST_RNR_COUNTER:
- return DAT_DTO_ERR_RECEIVER_NOT_READY;
-
- case IB_COMP_ST_TRANSP_COUNTER:
- return DAT_DTO_ERR_TRANSPORT;
-
- case IB_COMP_ST_REM_REQ_ERR:
- return DAT_DTO_ERR_REMOTE_RESPONDER;
-
- case IB_COMP_ST_BAD_RESPONSE_ERR:
- return DAT_DTO_ERR_BAD_RESPONSE;
-
- case IB_COMP_ST_EE_STATE_ERR:
- case IB_COMP_ST_EE_CTX_NO_ERR:
- return DAT_DTO_ERR_TRANSPORT;
-
- default:
-#ifdef DAPL_DBG
- dapl_dbg_log (DAPL_DBG_TYPE_ERR,"%s() unknown IB_COMP_ST %x(0x%x)\n",
- __FUNCTION__,ib_status,ib_status);
-#endif
- return DAT_DTO_FAILURE;
- }
-}
-
-
-/*
- * Map all IBAPI DTO completion codes to the DAT equivelent.
- *
- * dapls_ib_get_dat_event
- *
- * Return a DAT connection event given a provider CM event.
- *
- * N.B. Some architectures combine async and CM events into a
- * generic async event. In that case, dapls_ib_get_dat_event()
- * and dapls_ib_get_async_event() should be entry points that
- * call into a common routine.
- *
- * Input:
- * ib_cm_event event provided to the dapl callback routine
- * active switch indicating active or passive connection
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_EVENT_NUMBER of translated provider value
- */
-
-DAT_EVENT_NUMBER
-dapls_ib_get_dat_event (
- IN const ib_cm_events_t ib_cm_event,
- IN DAT_BOOLEAN active)
-{
- DAT_EVENT_NUMBER dat_event_num = 0;
- UNREFERENCED_PARAMETER (active);
-
- switch ( ib_cm_event)
- {
- case IB_CME_CONNECTED:
- dat_event_num = DAT_CONNECTION_EVENT_ESTABLISHED;
- break;
- case IB_CME_DISCONNECTED:
- dat_event_num = DAT_CONNECTION_EVENT_DISCONNECTED;
- break;
- case IB_CME_DISCONNECTED_ON_LINK_DOWN:
- dat_event_num = DAT_CONNECTION_EVENT_DISCONNECTED;
- break;
- case IB_CME_CONNECTION_REQUEST_PENDING:
- dat_event_num = DAT_CONNECTION_REQUEST_EVENT;
- break;
- case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:
- dat_event_num = DAT_CONNECTION_REQUEST_EVENT;
- break;
- case IB_CME_DESTINATION_REJECT:
- dat_event_num = DAT_CONNECTION_EVENT_NON_PEER_REJECTED;
- break;
- case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:
- dat_event_num = DAT_CONNECTION_EVENT_PEER_REJECTED;
- break;
- case IB_CME_DESTINATION_UNREACHABLE:
- dat_event_num = DAT_CONNECTION_EVENT_UNREACHABLE;
- break;
- case IB_CME_TOO_MANY_CONNECTION_REQUESTS:
- dat_event_num = DAT_CONNECTION_EVENT_NON_PEER_REJECTED;
- break;
- case IB_CME_LOCAL_FAILURE:
- dat_event_num = DAT_CONNECTION_EVENT_BROKEN;
- break;
- case IB_CME_REPLY_RECEIVED:
- case IB_CME_REPLY_RECEIVED_PRIVATE_DATA:
- default:
- break;
- }
-#if 0
- dapl_dbg_log (DAPL_DBG_TYPE_CM,
- " dapls_ib_get_dat_event: event translation: (%s) "
- "ib_event 0x%x dat_event 0x%x\n",
- active ? "active" : "passive",
- ib_cm_event,
- dat_event_num);
-#endif
- return dat_event_num;
-}
-
-
-/*
- * dapls_ib_get_dat_event
- *
- * Return a DAT connection event given a provider CM event.
- *
- * N.B. Some architectures combine async and CM events into a
- * generic async event. In that case, dapls_ib_get_cm_event()
- * and dapls_ib_get_async_event() should be entry points that
- * call into a common routine.
- *
- * WARNING: In this implementation, there are multiple CM
- * events that map to a single DAT event. Be very careful
- * with provider routines that depend on this reverse mapping,
- * they may have to accomodate more CM events than they
- * 'naturally' would.
- *
- * Input:
- * dat_event_num DAT event we need an equivelent CM event for
- *
- * Output:
- * none
- *
- * Returns:
- * ib_cm_event of translated DAPL value
- */
-ib_cm_events_t
-dapls_ib_get_cm_event (
- IN DAT_EVENT_NUMBER dat_event_num)
-{
- ib_cm_events_t ib_cm_event = 0;
-
- switch (dat_event_num)
- {
- case DAT_CONNECTION_EVENT_ESTABLISHED:
- ib_cm_event = IB_CME_CONNECTED;
- break;
- case DAT_CONNECTION_EVENT_DISCONNECTED:
- ib_cm_event = IB_CME_DISCONNECTED;
- break;
- case DAT_CONNECTION_REQUEST_EVENT:
- ib_cm_event = IB_CME_CONNECTION_REQUEST_PENDING;
- break;
- case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:
- ib_cm_event = IB_CME_DESTINATION_REJECT;
- break;
- case DAT_CONNECTION_EVENT_PEER_REJECTED:
- ib_cm_event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;
- break;
- case DAT_CONNECTION_EVENT_UNREACHABLE:
- ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;
- break;
- case DAT_CONNECTION_EVENT_BROKEN:
- ib_cm_event = IB_CME_LOCAL_FAILURE;
- break;
- default:
- break;
- }
-
- return ib_cm_event;
-}
-
-
-
-/*
- * dapls_set_provider_specific_attr
- *
- * Input:
- * attr_ptr Pointer provider specific attributes
- *
- * Output:
- * none
- *
- * Returns:
- * void
- */
-
-#ifdef DAT_EXTENSIONS
-static DAT_NAMED_ATTR ib_attrs[] = {
- {
- "DAT_EXTENSION_INTERFACE", "TRUE"
- },
- {
- DAT_IB_ATTR_FETCH_AND_ADD, "TRUE"
- },
- {
- DAT_IB_ATTR_CMP_AND_SWAP, "TRUE"
- },
- {
- DAT_IB_ATTR_IMMED_DATA, "TRUE"
- },
-};
-#define SPEC_ATTR_SIZE( x ) (sizeof( x ) / sizeof( DAT_NAMED_ATTR))
-#else
-static DAT_NAMED_ATTR *ib_attrs = NULL;
-#define SPEC_ATTR_SIZE( x ) 0
-#endif
-
-void dapls_query_provider_specific_attr(
- IN DAPL_IA *ia_ptr,
- IN DAT_PROVIDER_ATTR *attr_ptr )
-{
- attr_ptr->num_provider_specific_attr = SPEC_ATTR_SIZE(ib_attrs);
- attr_ptr->provider_specific_attr = ib_attrs;
-}
-
-
-DAT_RETURN dapls_ns_map_gid (
- IN DAPL_HCA *hca_ptr,
- IN DAT_IA_ADDRESS_PTR remote_ia_address,
- OUT GID *gid)
-{
- return (dapls_ib_ns_map_gid (hca_ptr, remote_ia_address, gid));
-}
-
-DAT_RETURN dapls_ns_map_ipaddr (
- IN DAPL_HCA *hca_ptr,
- IN GID gid,
- OUT DAT_IA_ADDRESS_PTR remote_ia_address)
-{
- return (dapls_ib_ns_map_ipaddr (hca_ptr, gid, remote_ia_address));
-}
-
-
-#ifdef NOT_USED
-/*
- * dapls_ib_post_recv - defered.until QP ! in init state.
- *
- * Provider specific Post RECV function
- */
-
-DAT_RETURN
-dapls_ib_post_recv_defered (
- IN DAPL_EP *ep_ptr,
- IN DAPL_COOKIE *cookie,
- IN DAT_COUNT num_segments,
- IN DAT_LMR_TRIPLET *local_iov)
-{
- ib_api_status_t ib_status;
- ib_recv_wr_t *recv_wr, *rwr;
- ib_local_ds_t *ds_array_p;
- DAT_COUNT i, total_len;
-
- if (ep_ptr->qp_state != IB_QPS_INIT)
- {
- dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsPR: BAD QP state(%s), not init? "
- "EP %p QP %p cookie %p, num_seg %d\n",
- ib_get_port_state_str(ep_ptr->qp_state), ep_ptr,
- ep_ptr->qp_handle, cookie, num_segments);
- return (DAT_INSUFFICIENT_RESOURCES);
- }
-
- recv_wr = dapl_os_alloc (sizeof(ib_recv_wr_t)
- + (num_segments*sizeof(ib_local_ds_t)));
- if (NULL == recv_wr)
- {
- return (DAT_INSUFFICIENT_RESOURCES);
- }
-
- dapl_os_memzero(recv_wr, sizeof(ib_recv_wr_t));
- recv_wr->wr_id = (DAT_UINT64) cookie;
- recv_wr->num_ds = num_segments;
-
- ds_array_p = (ib_local_ds_t*)(recv_wr+1);
-
- recv_wr->ds_array = ds_array_p;
-
- //total_len = 0;
-
- for (total_len = i = 0; i < num_segments; i++, ds_array_p++)
- {
- ds_array_p->length = (uint32_t)local_iov[i].segment_length;
- ds_array_p->lkey = cl_hton32(local_iov[i].lmr_context);
- ds_array_p->vaddr = local_iov[i].virtual_address;
- total_len += ds_array_p->length;
- }
-
- if (cookie != NULL)
- {
- cookie->val.dto.size = total_len;
-
- dapl_dbg_log (DAPL_DBG_TYPE_EP,
- "--> DsPR: EP = %p QP = %p cookie= %p, num_seg= %d\n",
- ep_ptr, ep_ptr->qp_handle, cookie, num_segments);
- }
-
- recv_wr->p_next = NULL;
-
- /* find last defered recv work request, link new on the end */
- rwr=ep_ptr->cm_post;
- if (rwr == NULL)
- {
- ep_ptr->cm_post = (void*)recv_wr;
- i = 1;
- }
- else
- {
- for(i=2; rwr->p_next; rwr=rwr->p_next) i++;
- rwr->p_next = recv_wr;
- }
-
- dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsPR: %s() EP %p QP %p cookie %p "
- "num_seg %d Tdefered %d\n",
- __FUNCTION__, ep_ptr, ep_ptr->qp_handle, cookie, num_segments,
- i);
-
- return DAT_SUCCESS;
-}
-#endif
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
-
+/*\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.c\r
+ *\r
+ * PURPOSE: Utility routines for access to IBAL APIs\r
+ *\r
+ * $Id: dapl_ibal_util.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_cr_util.h"\r
+#include "dapl_lmr_util.h"\r
+#include "dapl_rmr_util.h"\r
+#include "dapl_cookie.h"\r
+#include "dapl_ring_buffer_util.h"\r
+\r
+#ifdef DAT_EXTENSIONS\r
+#include <dat2\dat_ib_extensions.h>\r
+#endif\r
+\r
+#ifndef NO_NAME_SERVICE\r
+#include "dapl_name_service.h"\r
+#endif /* NO_NAME_SERVICE */\r
+\r
+#include "dapl_ibal_name_service.h"\r
+\r
+#define DAPL_IBAL_MAX_CA 4\r
+#define DAT_ADAPTER_NAME "InfiniHost (Tavor)"\r
+#define DAT_VENDOR_NAME "Mellanox Technolgy Inc."\r
+\r
+/*\r
+ * Root data structure for DAPL_IIBA.\r
+ */\r
+dapl_ibal_root_t dapl_ibal_root;\r
+DAPL_HCA_NAME dapl_ibal_hca_name_array [DAPL_IBAL_MAX_CA] = \r
+ {"IbalHca0", "IbalHca1", "IbalHca2", "IbalHca3"};\r
+ib_net64_t *gp_ibal_ca_guid_tbl = NULL;\r
+\r
+/*\r
+ * DAT spec does not tie max_mtu_size with IB MTU\r
+ *\r
+static ib_net32_t dapl_ibal_mtu_table[6] = {0, 256, 512, 1024, 2048, 4096};\r
+ */\r
+ \r
+int g_loopback_connection = 0;\r
+\r
+\r
+static cl_status_t\r
+dapli_init_root_ca_list(\r
+ IN dapl_ibal_root_t *root )\r
+{\r
+ cl_status_t status;\r
+\r
+ cl_qlist_init (&root->ca_head);\r
+ status = cl_spinlock_init (&root->ca_lock);\r
+\r
+ if (status == CL_SUCCESS)\r
+ {\r
+ /*\r
+ * Get the time ready to go but don't start here\r
+ */\r
+ root->shutdown = FALSE;\r
+ root->initialized = TRUE;\r
+ }\r
+ else\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DiIRCL: cl_spinlock_init returned %d\n", status );\r
+ root->initialized = FALSE;\r
+ }\r
+ \r
+ root->h_al = NULL;\r
+\r
+ return (status);\r
+}\r
+\r
+\r
+static cl_status_t\r
+dapli_destroy_root_ca_list(\r
+ IN dapl_ibal_root_t *root )\r
+{\r
+\r
+ root->initialized = FALSE;\r
+\r
+ /* \r
+ * At this point the lock should not be necessary\r
+ */\r
+ if (!cl_is_qlist_empty (&root->ca_head) )\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> Destroying nonempty ca list (%s)\n", "DiDRCL");\r
+ }\r
+ cl_spinlock_destroy (&root->ca_lock);\r
+\r
+ return CL_SUCCESS;\r
+}\r
+\r
+\r
+static void\r
+dapli_shutdown_port_access(\r
+ IN dapl_ibal_ca_t *ca )\r
+{\r
+ dapl_ibal_port_t *p_port;\r
+\r
+ TAKE_LOCK( ca->port_lock );\r
+ {\r
+ while ( ! cl_is_qlist_empty( &ca->port_head ) )\r
+ {\r
+ p_port = (dapl_ibal_port_t *)cl_qlist_remove_head( &ca->port_head );\r
+ RELEASE_LOCK( ca->port_lock );\r
+ {\r
+ REMOVE_REFERENCE( &p_port->refs );\r
+ REMOVE_REFERENCE( &p_port->ca->refs );\r
+\r
+ dapl_os_free (p_port, sizeof (dapl_ibal_port_t));\r
+ }\r
+ TAKE_LOCK( ca->port_lock );\r
+ }\r
+ }\r
+ RELEASE_LOCK( ca->port_lock );\r
+}\r
+\r
+\r
+static void dapli_shutdown_ca_access (void)\r
+{\r
+ dapl_ibal_ca_t *ca;\r
+\r
+ if ( dapl_ibal_root.initialized == FALSE )\r
+ {\r
+ goto destroy_root;\r
+ }\r
+\r
+ TAKE_LOCK (dapl_ibal_root.ca_lock);\r
+ {\r
+ while ( ! cl_is_qlist_empty (&dapl_ibal_root.ca_head) )\r
+ {\r
+ ca = (dapl_ibal_ca_t *)\r
+ cl_qlist_remove_head (&dapl_ibal_root.ca_head);\r
+\r
+ if (ca->p_ca_attr)\r
+ {\r
+ dapl_os_free (ca->p_ca_attr, sizeof (ib_ca_attr_t));\r
+ }\r
+\r
+\r
+ RELEASE_LOCK (dapl_ibal_root.ca_lock);\r
+ {\r
+ dapli_shutdown_port_access (ca);\r
+ REMOVE_REFERENCE (&ca->refs);\r
+ }\r
+ TAKE_LOCK (dapl_ibal_root.ca_lock);\r
+ }\r
+ }\r
+ RELEASE_LOCK (dapl_ibal_root.ca_lock);\r
+\r
+destroy_root:\r
+ /*\r
+ * Destroy the root CA list and list lock\r
+ */\r
+ dapli_destroy_root_ca_list (&dapl_ibal_root);\r
+\r
+ /*\r
+ * Signal we're all done and wake any waiter\r
+ */\r
+ dapl_ibal_root.shutdown = FALSE;\r
+}\r
+\r
+\r
+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
+ dapl_ibal_evd_cb_t *evd_cb = NULL;\r
+\r
+ TAKE_LOCK( ca->evd_cb_lock );\r
+\r
+ evd_cb = (dapl_ibal_evd_cb_t *) cl_qlist_head( &ca->evd_cb_head );\r
+ while ( &evd_cb->next != cl_qlist_end( &ca->evd_cb_head ) )\r
+ {\r
+ if ( context == evd_cb->context)\r
+ {\r
+ goto found;\r
+ }\r
+\r
+ /*\r
+ * Try again\r
+ */\r
+ evd_cb = (dapl_ibal_evd_cb_t *) cl_qlist_next( &evd_cb->next );\r
+ }\r
+ /*\r
+ * No joy\r
+ */\r
+ evd_cb = NULL;\r
+\r
+found:\r
+\r
+ RELEASE_LOCK( ca->evd_cb_lock );\r
+\r
+ return ( evd_cb );\r
+}\r
+\r
+\r
+static cl_status_t\r
+dapli_init_ca_evd_cb_list(\r
+ IN dapl_ibal_ca_t *ca )\r
+{\r
+ cl_status_t status;\r
+\r
+ cl_qlist_init( &ca->evd_cb_head );\r
+ status = cl_spinlock_init( &ca->evd_cb_lock );\r
+ if ( status != CL_SUCCESS )\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DiICECL: cl_spinlock_init returned %d\n", status);\r
+ return ( status );\r
+}\r
+\r
+\r
+static cl_status_t\r
+dapli_init_ca_port_list(\r
+ IN dapl_ibal_ca_t *ca )\r
+{\r
+ cl_status_t status;\r
+\r
+ cl_qlist_init( &ca->port_head );\r
+ status = cl_spinlock_init( &ca->port_lock );\r
+ if ( status != CL_SUCCESS )\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DiICPL: cl_spinlock_init returned %d\n", status );\r
+ return ( status );\r
+}\r
+\r
+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
+ cl_list_item_t *p_active_port = NULL;\r
+ \r
+ TAKE_LOCK (p_ca->port_lock);\r
+ for ( p_active_port = cl_qlist_head( &p_ca->port_head );\r
+ p_active_port != cl_qlist_end ( &p_ca->port_head);\r
+ p_active_port = cl_qlist_next ( p_active_port ) )\r
+ {\r
+ if (((dapl_ibal_port_t *)p_active_port)->p_attr->port_num == port_num)\r
+ break; \r
+ }\r
+ RELEASE_LOCK (p_ca->port_lock);\r
+\r
+ return (dapl_ibal_port_t *)p_active_port;\r
+}\r
+\r
+\r
+void\r
+dapli_ibal_ca_async_error_callback( IN ib_async_event_rec_t *p_err_rec )\r
+{\r
+ dapl_ibal_ca_t *p_ca = (dapl_ibal_ca_t*)((void *)p_err_rec->context);\r
+ dapl_ibal_evd_cb_t *evd_cb;\r
+ DAPL_IA *ia_ptr;\r
+ \r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DiCaAEC: CA error %d for context %p\n", \r
+ p_err_rec->code, p_err_rec->context);\r
+\r
+ if (p_ca == NULL)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR, "--> DiCaAEC: invalid p_ca"\r
+ "(%p)in async event rec\n",p_ca);\r
+ return;\r
+ }\r
+ \r
+ ia_ptr = (DAPL_IA*)p_ca->ia_ptr;\r
+ if (ia_ptr == NULL)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ "--> DiCaAEC: invalid ia_ptr in %p ca \n", p_ca );\r
+ return;\r
+ }\r
+\r
+ if (ia_ptr->async_error_evd == NULL)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ "--> DiCqAEC: can't find async_error_evd on %s HCA\n", \r
+ (ia_ptr->header.provider)->device_name );\r
+ return;\r
+ }\r
+\r
+ /* find QP error callback using p_ca for context */\r
+ evd_cb = dapli_find_evd_cb_by_context (ia_ptr->async_error_evd, p_ca);\r
+ if ((evd_cb == NULL) || (evd_cb->pfn_async_err_cb == NULL))\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ "--> DiCaAEC: no ERROR cb on %p found \n", p_ca);\r
+ return;\r
+ }\r
+\r
+ /* maps to dapl_evd_un_async_error_callback(), context is async_evd */\r
+ evd_cb->pfn_async_err_cb( (ib_hca_handle_t)p_ca, \r
+ (ib_error_record_t*)&p_err_rec->code, \r
+ ia_ptr->async_error_evd );\r
+\r
+}\r
+\r
+\r
+static dapl_ibal_port_t *\r
+dapli_alloc_port(\r
+ IN dapl_ibal_ca_t *ca,\r
+ IN ib_port_attr_t *ib_port )\r
+{\r
+ dapl_ibal_port_t *p_port = NULL;\r
+\r
+ if (ca->h_ca == NULL )\r
+ {\r
+ return NULL;\r
+ }\r
+\r
+ /*\r
+ * Allocate the port structure memory. This will also deal with the\r
+ * copying ib_port_attr_t including GID and P_Key tables\r
+ */\r
+ p_port = dapl_os_alloc ( sizeof(dapl_ibal_port_t ) );\r
+\r
+ if ( p_port )\r
+ {\r
+ dapl_os_memzero (p_port, sizeof(dapl_ibal_port_t ) );\r
+\r
+ /*\r
+ * We're good to go after initializing reference.\r
+ */\r
+ INIT_REFERENCE( &p_port->refs, 1, p_port, NULL /* pfn_destructor */ );\r
+ \r
+ p_port->p_attr = ib_port;\r
+ }\r
+ return ( p_port );\r
+}\r
+\r
+static void\r
+dapli_add_active_port(\r
+ IN dapl_ibal_ca_t *ca )\r
+{\r
+ dapl_ibal_port_t *p_port;\r
+ ib_port_attr_t *p_port_attr;\r
+ ib_ca_attr_t *p_ca_attr;\r
+ int i;\r
+\r
+ p_ca_attr = ca->p_ca_attr;\r
+\r
+ dapl_os_assert (p_ca_attr != NULL);\r
+\r
+ for (i = 0; i < p_ca_attr->num_ports; i++)\r
+ {\r
+ p_port_attr = &p_ca_attr->p_port_attr[i];\r
+\r
+ {\r
+ p_port = dapli_alloc_port( ca, p_port_attr );\r
+ if ( p_port )\r
+ {\r
+ TAKE_REFERENCE (&ca->refs);\r
+\r
+ /*\r
+ * Record / update attribues\r
+ */\r
+ p_port->p_attr = p_port_attr;\r
+\r
+ /*\r
+ * Remember the parant CA keeping the reference we took above\r
+ */\r
+ p_port->ca = ca;\r
+\r
+ /*\r
+ * We're good to go - Add the new port to the list on the CA\r
+ */\r
+ LOCK_INSERT_TAIL( ca->port_lock, ca->port_head, p_port->next );\r
+ }\r
+ else\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: Could not allocate dapl_ibal_port_t\n",\r
+ "DiAAP");\r
+ }\r
+ }\r
+ dapl_dbg_log( DAPL_DBG_TYPE_UTIL,\r
+ "--> DiAAP: Port %d logical link %s lid = %#x\n",\r
+ p_port_attr->port_num,\r
+ ( p_port_attr->link_state != IB_LINK_ACTIVE\r
+ ? "DOWN": "UP" ),\r
+ CL_HTON16(p_port_attr->lid) );\r
+\r
+ } /* for loop */\r
+}\r
+\r
+static dapl_ibal_ca_t *\r
+dapli_alloc_ca(\r
+ IN ib_al_handle_t h_al,\r
+ IN ib_net64_t ca_guid)\r
+{\r
+ dapl_ibal_ca_t *p_ca;\r
+ ib_api_status_t status;\r
+ uint32_t attr_size;\r
+\r
+ /*\r
+ * Allocate the CA structure\r
+ */\r
+ p_ca = dapl_os_alloc( sizeof(dapl_ibal_ca_t) );\r
+ dapl_os_memzero (p_ca, sizeof(dapl_ibal_ca_t) );\r
+\r
+ if ( p_ca )\r
+ {\r
+ /*\r
+ * Now we pass dapli_ibal_ca_async_error_callback as the \r
+ * async error callback\r
+ */\r
+ status = ib_open_ca( h_al,\r
+ ca_guid,\r
+ dapli_ibal_ca_async_error_callback,\r
+ p_ca,\r
+ &p_ca->h_ca );\r
+ if ( status != IB_SUCCESS )\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DiAC: ib_open_ca returned %s\n",\r
+ ib_get_err_str(status));\r
+ dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));\r
+ return (NULL);\r
+ }\r
+\r
+ /*\r
+ * Get port list lock and list head initialized\r
+ */\r
+ if (( dapli_init_ca_port_list( p_ca ) != CL_SUCCESS ) ||\r
+ ( dapli_init_ca_evd_cb_list( p_ca ) != CL_SUCCESS ))\r
+ { \r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: dapli_init_ca_port_list returned failed\n",\r
+ "DiAC");\r
+ goto close_and_free_ca;\r
+ }\r
+\r
+ attr_size = 0;\r
+ status = ib_query_ca (p_ca->h_ca, NULL, &attr_size);\r
+ if (status != IB_INSUFFICIENT_MEMORY)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DiAC: ib_query_ca returned failed status = %d\n",\r
+ status);\r
+ goto close_and_free_ca;\r
+ }\r
+\r
+ p_ca->p_ca_attr = dapl_os_alloc ((int)attr_size);\r
+ if (p_ca->p_ca_attr == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: dapli_alloc_ca failed to alloc memory\n",\r
+ "DiAC");\r
+ goto close_and_free_ca;\r
+ }\r
+\r
+ status = ib_query_ca (\r
+ p_ca->h_ca,\r
+ p_ca->p_ca_attr,\r
+ &attr_size);\r
+ if (status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> ib_query_ca returned failed status = %d\n",\r
+ status);\r
+ dapl_os_free (p_ca->p_ca_attr, (int)attr_size);\r
+ goto close_and_free_ca;\r
+ }\r
+ \r
+ p_ca->ca_attr_size = attr_size;\r
+\r
+ INIT_REFERENCE( &p_ca->refs, 1, p_ca, NULL /* pfn_destructor */ );\r
+\r
+ dapli_add_active_port (p_ca);\r
+\r
+ /*\r
+ * We're good to go\r
+ */\r
+ return ( p_ca );\r
+ }\r
+ else\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: Error allocating CA structure\n","DiAC");\r
+ return ( NULL );\r
+ }\r
+\r
+close_and_free_ca:\r
+ /*\r
+ * Close the CA.\r
+ */\r
+ (void) ib_close_ca ( p_ca->h_ca, NULL /* callback */);\r
+ dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));\r
+\r
+ /*\r
+ * If we get here, there was an initialization failure\r
+ */\r
+ return ( NULL );\r
+}\r
+\r
+\r
+static dapl_ibal_ca_t *\r
+dapli_add_ca (\r
+ IN ib_al_handle_t h_al,\r
+ IN ib_net64_t ca_guid )\r
+{\r
+ dapl_ibal_ca_t *p_ca;\r
+\r
+ /*\r
+ * Allocate a CA structure\r
+ */\r
+ p_ca = dapli_alloc_ca( h_al, ca_guid );\r
+ if ( p_ca )\r
+ {\r
+ /*\r
+ * Add the new CA to the list\r
+ */\r
+ LOCK_INSERT_TAIL( dapl_ibal_root.ca_lock, \r
+ dapl_ibal_root.ca_head, p_ca->next );\r
+ }\r
+ else\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: Could not allocate dapl_ibal_ca_t "\r
+ " for CA guid " F64x "\n","DiAA",ca_guid);\r
+ }\r
+\r
+ return ( p_ca );\r
+}\r
+\r
+\r
+int32_t\r
+dapls_ib_init (void)\r
+{\r
+ ib_api_status_t status;\r
+\r
+ /*\r
+ * Initialize the root structure\r
+ */\r
+ if ( dapli_init_root_ca_list (&dapl_ibal_root) == CL_SUCCESS )\r
+ {\r
+ /*\r
+ * Register with the access layer\r
+ */\r
+ status = ib_open_al (&dapl_ibal_root.h_al);\r
+\r
+ if (status == IB_SUCCESS)\r
+ {\r
+ intn_t guid_count;\r
+\r
+ status = ib_get_ca_guids ( dapl_ibal_root.h_al,\r
+ NULL,\r
+ &(size_t)guid_count );\r
+ if (status != IB_INSUFFICIENT_MEMORY)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: ib_get_ca_guids failed = %d\n",\r
+ __FUNCTION__,status);\r
+ return -1;\r
+ }\r
+\r
+ if (guid_count == 0)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: found NO HCA in the system\n",\r
+ __FUNCTION__);\r
+ return -1;\r
+ }\r
+\r
+ if (guid_count > DAPL_IBAL_MAX_CA)\r
+ {\r
+ guid_count = DAPL_IBAL_MAX_CA;\r
+ }\r
+\r
+ gp_ibal_ca_guid_tbl = (ib_net64_t*)\r
+ dapl_os_alloc ( (int)(guid_count * \r
+ sizeof (ib_net64_t)) );\r
+\r
+ if (gp_ibal_ca_guid_tbl == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> %s() can not alloc "\r
+ "gp_ibal_ca_guid_tbl\n", __FUNCTION__);\r
+ \r
+ return -1;\r
+ }\r
+\r
+ status = ib_get_ca_guids ( dapl_ibal_root.h_al, \r
+ gp_ibal_ca_guid_tbl, \r
+ &(size_t)guid_count );\r
+ \r
+\r
+ if ( status != IB_SUCCESS )\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: ib_get_ca_guids failed '%s'\n", \r
+ __FUNCTION__, ib_get_err_str(status) );\r
+ return -1;\r
+ }\r
+\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_UTIL, \r
+ "--> %s: Success open AL & found %d HCA avail,\n",\r
+ __FUNCTION__, guid_count);\r
+ return 0;\r
+ }\r
+ else\r
+ { \r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: ib_open_al() failed '%s'\n",\r
+ __FUNCTION__, ib_get_err_str(status) );\r
+ /*\r
+ * Undo CA list\r
+ */\r
+ dapli_destroy_root_ca_list (&dapl_ibal_root);\r
+ }\r
+ }\r
+ return -1;\r
+}\r
+\r
+\r
+int32_t dapls_ib_release (void)\r
+{\r
+ dapl_ibal_root.shutdown = TRUE;\r
+\r
+ dapli_shutdown_ca_access();\r
+\r
+ /*\r
+ * If shutdown not complete, wait for it\r
+ */\r
+ if (dapl_ibal_root.shutdown)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsIR: timeout waiting for completion\n");\r
+ }\r
+\r
+ if ( dapl_ibal_root.h_al != NULL )\r
+ {\r
+ (void) ib_close_al (dapl_ibal_root.h_al);\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIR: ib_close_al() returns\n");\r
+ dapl_ibal_root.h_al = NULL;\r
+ }\r
+#ifdef DBG\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> %s: Exit\n",__FUNCTION__);\r
+#endif\r
+\r
+ return 0;\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_enum_hcas\r
+ *\r
+ * Enumerate all HCAs on the system\r
+ *\r
+ * Input:\r
+ * none\r
+ *\r
+ * Output:\r
+ * hca_names Array of hca names\r
+ * total_hca_count \r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_enum_hcas (\r
+ IN const char *vendor,\r
+ OUT DAPL_HCA_NAME **hca_names,\r
+ OUT DAT_COUNT *total_hca_count )\r
+{\r
+ intn_t guid_count;\r
+ ib_api_status_t ib_status;\r
+ UNREFERENCED_PARAMETER(vendor);\r
+\r
+ ib_status = ib_get_ca_guids (dapl_ibal_root.h_al, NULL, &(size_t)guid_count);\r
+ if (ib_status != IB_INSUFFICIENT_MEMORY)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DsIEH: ib_get_ca_guids failed '%s'\n",\r
+ ib_get_err_str(ib_status) );\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+\r
+ if (guid_count == 0)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: ib_get_ca_guids no HCA in the system\n",\r
+ "DsIEH");\r
+ return (DAT_PROVIDER_NOT_FOUND);\r
+ }\r
+\r
+ if (guid_count > DAPL_IBAL_MAX_CA)\r
+ {\r
+ guid_count = DAPL_IBAL_MAX_CA;\r
+ }\r
+\r
+ gp_ibal_ca_guid_tbl = (ib_net64_t *)dapl_os_alloc ((int)(guid_count * sizeof (ib_net64_t)) );\r
+\r
+ if (gp_ibal_ca_guid_tbl == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: can not alloc resources @line%d\n", "DsIEH",\r
+ __LINE__);\r
+ return (DAT_INSUFFICIENT_RESOURCES);\r
+ }\r
+\r
+ ib_status = ib_get_ca_guids ( dapl_ibal_root.h_al,\r
+ gp_ibal_ca_guid_tbl,\r
+ &(size_t)guid_count);\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DsIEH: ib_get_ca_guids failed status = %s\n", \r
+ ib_get_err_str(ib_status) );\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+\r
+ *hca_names = (DAPL_HCA_NAME*)\r
+ dapl_os_alloc ((int)(guid_count * sizeof (DAPL_HCA_NAME)));\r
+\r
+ if (*hca_names == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: can not alloc resources @line%d\n",\r
+ "DsIEH", __LINE__);\r
+ return (DAT_INSUFFICIENT_RESOURCES);\r
+ }\r
+\r
+ dapl_os_memcpy (*hca_names, \r
+ dapl_ibal_hca_name_array, \r
+ (int)(guid_count * sizeof (DAPL_HCA_NAME)) );\r
+\r
+ *total_hca_count = (DAT_COUNT)guid_count;\r
+\r
+ {\r
+ int i;\r
+\r
+ for (i = 0; i < guid_count; i++)\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIEH: %d) hca_names = %s\n",\r
+ i, dapl_ibal_hca_name_array[i]);\r
+ }\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+\r
+IB_HCA_NAME\r
+dapl_ib_convert_name(\r
+ IN char *name)\r
+{\r
+ int i;\r
+\r
+ if (gp_ibal_ca_guid_tbl == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DICN: found no HCA with name %s\n", name );\r
+ return 0;\r
+ }\r
+\r
+ for (i = 0; i < DAPL_IBAL_MAX_CA; i++)\r
+ {\r
+ if (strcmp (name, dapl_ibal_hca_name_array[i]) == 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (i >= DAPL_IBAL_MAX_CA)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DICN: can't find any HCA with name %s\n", name);\r
+ return 0;\r
+ }\r
+ \r
+ return (gp_ibal_ca_guid_tbl[i]);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_open_hca\r
+ *\r
+ * Open HCA\r
+ *\r
+ * Input:\r
+ * *hca_name pointer to provider device name\r
+ * *ib_hca_handle_p pointer to provide HCA handle\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Return:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN dapls_ib_open_hca ( IN char *hca_name,\r
+ IN DAPL_HCA *p_hca )\r
+{\r
+ dapl_ibal_ca_t *p_ca;\r
+ IB_HCA_NAME ca_guid;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL," open_hca: %s - %p\n", hca_name, p_hca);\r
+\r
+ if (gp_ibal_ca_guid_tbl == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIOH: found no HCA with ca_guid"\r
+ F64x "\n", hca_name);\r
+ return (DAT_PROVIDER_NOT_FOUND);\r
+ }\r
+\r
+ ca_guid = dapl_ib_convert_name(hca_name);\r
+\r
+ p_ca = dapli_add_ca (dapl_ibal_root.h_al, ca_guid);\r
+\r
+ if (p_ca == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DsIOH: can not create ca for '%s' guid " F64x "\n",\r
+ hca_name, ca_guid);\r
+ return (DAT_INSUFFICIENT_RESOURCES);\r
+ }\r
+\r
+ p_hca->ib_hca_handle = (ib_hca_handle_t) p_ca;\r
+ p_hca->ib_trans.d_hca = p_hca; // back-link\r
+\r
+ /* initialize hca wait object for uAT event */\r
+ dapl_os_wait_object_init(&p_hca->ib_trans.wait_object);\r
+\r
+#if SOCK_CM\r
+ {\r
+ DAT_RETURN dat_status;\r
+\r
+ dat_status = dapli_init_sock_cm(p_hca);\r
+ if ( dat_status != DAT_SUCCESS )\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ " %s() failed to init sock_CM\n", __FUNCTION__);\r
+ return DAT_INTERNAL_ERROR;\r
+ }\r
+\r
+ /* initialize cr_list lock */\r
+ dat_status = dapl_os_lock_init(&p_hca->ib_trans.lock);\r
+ if (dat_status != DAT_SUCCESS)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR, " %s() failed to init lock\n",\r
+ __FUNCTION__);\r
+ return DAT_INTERNAL_ERROR;\r
+ }\r
+\r
+ /* initialize CM list for listens on this HCA */\r
+ dapl_llist_init_head((DAPL_LLIST_HEAD*)&p_hca->ib_trans.list);\r
+ }\r
+#endif\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_close_hca\r
+ *\r
+ * Open HCA\r
+ *\r
+ * Input:\r
+ * ib_hca_handle provide HCA handle\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Return:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN dapls_ib_close_hca ( IN DAPL_HCA *p_hca )\r
+{\r
+ dapl_ibal_ca_t *p_ca;\r
+ \r
+ p_ca = (dapl_ibal_ca_t *) p_hca->ib_hca_handle;\r
+ \r
+#if SOCK_CM\r
+#endif\r
+ /*\r
+ * Remove it from the list\r
+ */\r
+ TAKE_LOCK (dapl_ibal_root.ca_lock);\r
+ {\r
+ cl_qlist_remove_item (&dapl_ibal_root.ca_head, &p_ca->next);\r
+ }\r
+ RELEASE_LOCK (dapl_ibal_root.ca_lock);\r
+\r
+ dapli_shutdown_port_access (p_ca);\r
+ \r
+ /*\r
+ * Remove the constructor reference\r
+ */\r
+ REMOVE_REFERENCE (&p_ca->refs);\r
+\r
+ cl_spinlock_destroy (&p_ca->port_lock);\r
+ cl_spinlock_destroy (&p_ca->evd_cb_lock);\r
+\r
+ if (p_ca->p_ca_attr)\r
+ dapl_os_free (p_ca->p_ca_attr, sizeof (ib_ca_attr_t));\r
+\r
+ (void) ib_close_ca (p_ca->h_ca, NULL /* close_callback */);\r
+\r
+ p_hca->ib_hca_handle = IB_INVALID_HANDLE;\r
+ dapl_os_free (p_ca, sizeof (dapl_ibal_ca_t));\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+\r
+/*\r
+ * dapl_ib_pd_alloc\r
+ *\r
+ * Alloc a PD\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * PZ_ptr pointer to PZEVD struct\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_pd_alloc (\r
+ IN DAPL_IA *ia,\r
+ IN DAPL_PZ *pz)\r
+{\r
+ ib_api_status_t ib_status;\r
+ dapl_ibal_ca_t *p_ca;\r
+\r
+ p_ca = (dapl_ibal_ca_t *) ia->hca_ptr->ib_hca_handle;\r
+\r
+ ib_status = ib_alloc_pd (\r
+ p_ca->h_ca,\r
+ IB_PDT_NORMAL,\r
+ ia,\r
+ &pz->pd_handle );\r
+\r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+\r
+/*\r
+ * dapl_ib_pd_free\r
+ *\r
+ * Free a PD\r
+ *\r
+ * Input:\r
+ * PZ_ptr pointer to PZ struct\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_pd_free (\r
+ IN DAPL_PZ *pz)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = ib_dealloc_pd (pz->pd_handle, /* destroy_callback */ NULL);\r
+\r
+ pz->pd_handle = IB_INVALID_HANDLE;\r
+\r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+\r
+/*\r
+ * dapl_ib_mr_register\r
+ *\r
+ * Register a virtual memory region\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * lmr pointer to dapl_lmr struct\r
+ * virt_addr virtual address of beginning of mem region\r
+ * length length of memory region\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mr_register (\r
+ IN DAPL_IA *ia,\r
+ IN DAPL_LMR *lmr,\r
+ IN DAT_PVOID virt_addr,\r
+ IN DAT_VLEN length,\r
+ IN DAT_MEM_PRIV_FLAGS privileges,\r
+ IN DAT_VA_TYPE va_type)\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_mr_handle_t mr_handle;\r
+ ib_mr_create_t mr_create;\r
+ uint32_t l_key, r_key; \r
+\r
+ if ( ia == NULL || ia->header.magic != DAPL_MAGIC_IA )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+\r
+ /* IBAL does not support */\r
+ if (va_type == DAT_VA_TYPE_ZB) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
+ "--> va_type == DAT_VA_TYPE_ZB: NOT SUPPORTED\n"); \r
+ return DAT_ERROR (DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE); \r
+ }\r
+\r
+ mr_create.vaddr = (void *) virt_addr;\r
+ mr_create.length = (size_t)length;\r
+ mr_create.access_ctrl = dapl_lmr_convert_privileges (privileges);\r
+ mr_create.access_ctrl |= IB_AC_MW_BIND;\r
+ \r
+ if (lmr->param.mem_type == DAT_MEM_TYPE_SHARED_VIRTUAL)\r
+ {\r
+ ib_status = ib_reg_shmid (\r
+ ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
+ (const uint8_t*)lmr->shmid,\r
+ &mr_create,\r
+ (uint64_t *)&virt_addr,\r
+ &l_key,\r
+ &r_key,\r
+ &mr_handle);\r
+ }\r
+ else \r
+ {\r
+ ib_status = ib_reg_mem ( ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
+ &mr_create,\r
+ &l_key,\r
+ &r_key,\r
+ &mr_handle );\r
+ }\r
+ \r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ return (dapl_ib_status_convert (ib_status));\r
+ }\r
+ \r
+ /* DAT/DAPL expects context in host order */\r
+ l_key = cl_ntoh32(l_key);\r
+ r_key = cl_ntoh32(r_key);\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMR: lmr (%p) lkey = 0x%x "\r
+ "r_key= %#x mr_handle %p vaddr 0x%LX len 0x%LX\n", \r
+ lmr, l_key, r_key, mr_handle, virt_addr, length);\r
+\r
+ lmr->param.lmr_context = l_key;\r
+ lmr->param.rmr_context = r_key;\r
+ lmr->param.registered_size = length;\r
+ lmr->param.registered_address = (DAT_VADDR)virt_addr;\r
+ lmr->mr_handle = mr_handle;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapl_ib_mr_deregister\r
+ *\r
+ * Free a memory region\r
+ *\r
+ * Input:\r
+ * lmr pointer to dapl_lmr struct\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mr_deregister (\r
+ IN DAPL_LMR *lmr)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ ib_status = ib_dereg_mr (lmr->mr_handle);\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+\r
+ lmr->param.lmr_context = 0;\r
+ lmr->mr_handle = IB_INVALID_HANDLE;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapl_ib_mr_register_shared\r
+ *\r
+ * Register a virtual memory region\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * lmr pointer to dapl_lmr struct\r
+ * virt_addr virtual address of beginning of mem region\r
+ * length length of memory region\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mr_register_shared (\r
+ IN DAPL_IA *ia,\r
+ IN DAPL_LMR *lmr,\r
+ IN DAT_MEM_PRIV_FLAGS privileges,\r
+ IN DAT_VA_TYPE va_type )\r
+{\r
+ DAT_VADDR virt_addr;\r
+ ib_mr_handle_t mr_handle;\r
+ ib_api_status_t ib_status;\r
+ ib_mr_handle_t new_mr_handle;\r
+ ib_access_t access_ctrl;\r
+ uint32_t l_key, r_key; \r
+ ib_mr_create_t mr_create;\r
+ if ( ia == NULL || ia->header.magic != DAPL_MAGIC_IA )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+\r
+ /* IBAL does not support?? */\r
+ if (va_type == DAT_VA_TYPE_ZB) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_ERR,\r
+ " va_type == DAT_VA_TYPE_ZB: NOT SUPPORTED\n"); \r
+ return DAT_ERROR (DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE); \r
+ }\r
+\r
+ virt_addr = dapl_mr_get_address (lmr->param.region_desc,\r
+ lmr->param.mem_type);\r
+\r
+ access_ctrl = dapl_lmr_convert_privileges (privileges);\r
+ access_ctrl |= IB_AC_MW_BIND;\r
+\r
+ mr_create.vaddr = (void *) virt_addr;\r
+ mr_create.access_ctrl = access_ctrl;\r
+ mr_handle = (ib_mr_handle_t) lmr->mr_handle;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsIMRS: orig mr_handle %p vaddr %p\n", \r
+ mr_handle, virt_addr);\r
+\r
+ if (lmr->param.mem_type == DAT_MEM_TYPE_SHARED_VIRTUAL)\r
+ {\r
+ ib_status = ib_reg_shmid ( ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
+ (const uint8_t*)lmr->shmid,\r
+ &mr_create,\r
+ &virt_addr,\r
+ &l_key,\r
+ &r_key,\r
+ &new_mr_handle );\r
+ }\r
+ else\r
+ { \r
+\r
+ ib_status = ib_reg_shared ( mr_handle,\r
+ ((DAPL_PZ *)lmr->param.pz_handle)->pd_handle,\r
+ access_ctrl,\r
+ /* in/out */(DAT_UINT64 *)&virt_addr,\r
+ &l_key,\r
+ &r_key,\r
+ &new_mr_handle );\r
+ }\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+ /*\r
+ * FIXME - Vu\r
+ * What if virt_addr as an OUTPUT having the actual virtual address\r
+ * assigned to the register region\r
+ */\r
+\r
+ /* DAT/DAPL expects context to be in host order */\r
+ l_key = cl_ntoh32(l_key);\r
+ r_key = cl_ntoh32(r_key);\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMRS: lmr (%p) lkey = 0x%x "\r
+ "new mr_handle %p vaddr %p\n",\r
+ lmr, l_key, new_mr_handle, virt_addr);\r
+\r
+ lmr->param.lmr_context = l_key;\r
+ lmr->param.rmr_context = r_key;\r
+ lmr->param.registered_address = (DAT_VADDR) (uintptr_t) virt_addr;\r
+ lmr->mr_handle = new_mr_handle;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_mw_alloc\r
+ *\r
+ * Bind a protection domain to a memory window\r
+ *\r
+ * Input:\r
+ * rmr Initialized rmr to hold binding handles\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mw_alloc ( IN DAPL_RMR *rmr )\r
+{\r
+ ib_api_status_t ib_status;\r
+ uint32_t r_key;\r
+ ib_mw_handle_t mw_handle;\r
+\r
+ ib_status = ib_create_mw (\r
+ ((DAPL_PZ *)rmr->param.pz_handle)->pd_handle,\r
+ &r_key,\r
+ &mw_handle);\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DsIMA: create MW failed = %s\n",\r
+ ib_get_err_str(ib_status) );\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+\r
+ rmr->mw_handle = mw_handle;\r
+ rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(r_key);\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsIMA: mw_handle %p r_key = 0x%x\n", \r
+ mw_handle, rmr->param.rmr_context);\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_mw_free\r
+ *\r
+ * Release bindings of a protection domain to a memory window\r
+ *\r
+ * Input:\r
+ * rmr Initialized rmr to hold binding handles\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mw_free (\r
+ IN DAPL_RMR *rmr)\r
+{\r
+ ib_api_status_t ib_status;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsIMF: mw_handle %p\n", rmr->mw_handle);\r
+\r
+ ib_status = ib_destroy_mw (rmr->mw_handle);\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMF: Free MW failed = %s\n",\r
+ ib_get_err_str(ib_status));\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+\r
+ rmr->param.rmr_context = 0;\r
+ rmr->mw_handle = IB_INVALID_HANDLE;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+/*\r
+ * dapls_ib_mw_bind\r
+ *\r
+ * Bind a protection domain to a memory window\r
+ *\r
+ * Input:\r
+ * rmr Initialized rmr to hold binding handles\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mw_bind (\r
+ IN DAPL_RMR *rmr,\r
+ IN DAPL_LMR *lmr,\r
+ IN DAPL_EP *ep,\r
+ IN DAPL_COOKIE *cookie,\r
+ IN DAT_VADDR virtual_address,\r
+ IN DAT_VLEN length,\r
+ IN DAT_MEM_PRIV_FLAGS mem_priv,\r
+ IN ib_bool_t is_signaled)\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_bind_wr_t bind_wr_prop;\r
+ uint32_t new_rkey;\r
+ \r
+ bind_wr_prop.local_ds.vaddr = virtual_address;\r
+ bind_wr_prop.local_ds.length = (uint32_t)length;\r
+ bind_wr_prop.local_ds.lkey = cl_hton32(lmr->param.lmr_context);\r
+ bind_wr_prop.current_rkey = cl_hton32(rmr->param.rmr_context);\r
+ bind_wr_prop.access_ctrl = dapl_rmr_convert_privileges (mem_priv);\r
+ bind_wr_prop.send_opt = (is_signaled == TRUE) ? \r
+ IB_SEND_OPT_SIGNALED : 0;\r
+ bind_wr_prop.wr_id = (uint64_t) ((uintptr_t) cookie);\r
+ bind_wr_prop.h_mr = lmr->mr_handle;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, "--> DsIMB: mr_handle %p, mw_handle %p "\r
+ "vaddr %#I64x length %#I64x\n", \r
+ lmr->mr_handle, rmr->mw_handle, virtual_address, length);\r
+\r
+ ib_status = ib_bind_mw (\r
+ rmr->mw_handle,\r
+ ep->qp_handle,\r
+ &bind_wr_prop,\r
+ &new_rkey);\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMB: Bind MW failed = %s\n", \r
+ ib_get_err_str(ib_status));\r
+ return (dapl_ib_status_convert (ib_status));\r
+ }\r
+\r
+ rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(new_rkey);\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL,\r
+ "--> DsIMB: new_rkey = 0x%x\n", rmr->param.rmr_context);\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+/*\r
+ * dapls_ib_mw_unbind\r
+ *\r
+ * Unbind a memory window\r
+ *\r
+ * Input:\r
+ * rmr Initialized rmr to hold binding handles\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INSUFFICIENT_RESOURCES\r
+ *\r
+ */\r
+DAT_RETURN\r
+dapls_ib_mw_unbind (\r
+ IN DAPL_RMR *rmr,\r
+ IN DAPL_EP *ep,\r
+ IN DAPL_COOKIE *cookie,\r
+ IN ib_bool_t is_signaled)\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_bind_wr_t bind_wr_prop;\r
+ uint32_t new_rkey;\r
+ \r
+ bind_wr_prop.local_ds.vaddr = 0;\r
+ bind_wr_prop.local_ds.length = 0;\r
+ bind_wr_prop.local_ds.lkey = 0;\r
+ bind_wr_prop.access_ctrl = 0;\r
+ bind_wr_prop.send_opt = (is_signaled == TRUE) ? \r
+ IB_SEND_OPT_SIGNALED : 0;\r
+ bind_wr_prop.wr_id = (uint64_t) ((uintptr_t) cookie);\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsIMU: mw_handle = %p\n", rmr->mw_handle);\r
+\r
+ ib_status = ib_bind_mw (\r
+ rmr->mw_handle,\r
+ ep->qp_handle,\r
+ &bind_wr_prop,\r
+ &new_rkey);\r
+\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsIMU: Unbind MW failed = %s\n", \r
+ ib_get_err_str(ib_status));\r
+ return (dapl_ib_status_convert (ib_status));\r
+ }\r
+\r
+ rmr->param.rmr_context = (DAT_RMR_CONTEXT) cl_ntoh32(new_rkey);\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL, \r
+ "--> DsIMU: unbind new_rkey 0x%x\n", rmr->param.rmr_context);\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_setup_async_callback\r
+ *\r
+ * Set up an asynchronous callbacks of various kinds\r
+ *\r
+ * Input:\r
+ * ia_handle IA handle\r
+ * handler_type type of handler to set up\r
+ * callback_handle handle param for completion callbacks\r
+ * callback callback routine pointer\r
+ * context argument for callback routine\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_async_callback (\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAPL_ASYNC_HANDLER_TYPE handler_type,\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN ib_async_handler_t callback,\r
+ IN void *context )\r
+{\r
+ dapl_ibal_ca_t *p_ca;\r
+ dapl_ibal_evd_cb_t *evd_cb;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_UTIL,\r
+ " setup_async_cb: ia %p type %d hdl %p cb %p ctx %p\n",\r
+ ia_ptr, handler_type, evd_ptr, callback, context);\r
+\r
+ p_ca = (dapl_ibal_ca_t *) ia_ptr->hca_ptr->ib_hca_handle;\r
+\r
+ if (p_ca == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> DsISAC: can't find %s HCA\n", \r
+ (ia_ptr->header.provider)->device_name);\r
+ return (DAT_INVALID_HANDLE);\r
+ }\r
+ \r
+ if (handler_type != DAPL_ASYNC_CQ_COMPLETION)\r
+ {\r
+ evd_cb = dapli_find_evd_cb_by_context (context, p_ca);\r
+ \r
+ if (evd_cb == NULL)\r
+ {\r
+ /* \r
+ * No record for this evd. We allocate one\r
+ */\r
+ evd_cb = dapl_os_alloc (sizeof (dapl_ibal_evd_cb_t));\r
+ dapl_os_memzero (evd_cb, sizeof(dapl_ibal_evd_cb_t));\r
+\r
+ if (evd_cb == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> %s: can't alloc res\n","DsISAC"); \r
+ return (DAT_INSUFFICIENT_RESOURCES);\r
+ }\r
+ \r
+ evd_cb->context = context;\r
+ \r
+ /*\r
+ * Add the new EVD CB to the list\r
+ */\r
+ LOCK_INSERT_TAIL( p_ca->evd_cb_lock, \r
+ p_ca->evd_cb_head,\r
+ evd_cb->next );\r
+ }\r
+\r
+ switch (handler_type)\r
+ {\r
+ case DAPL_ASYNC_UNAFILIATED:\r
+ evd_cb->pfn_async_err_cb = callback;\r
+ break;\r
+ case DAPL_ASYNC_CQ_ERROR:\r
+ evd_cb->pfn_async_cq_err_cb = callback;\r
+ break;\r
+ case DAPL_ASYNC_QP_ERROR:\r
+ evd_cb->pfn_async_qp_err_cb = callback;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ }\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_query_gid\r
+ *\r
+ * Query the hca for the gid of the 1st active port.\r
+ *\r
+ * Input:\r
+ * hca_handl hca handle \r
+ * ep_attr attribute of the ep\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ * DAT_INVALID_PARAMETER\r
+ */\r
+\r
+DAT_RETURN\r
+dapls_ib_query_gid( IN DAPL_HCA *hca_ptr,\r
+ IN GID *gid )\r
+{\r
+ dapl_ibal_ca_t *p_ca;\r
+ ib_ca_attr_t *p_hca_attr;\r
+ ib_api_status_t ib_status;\r
+ ib_hca_port_t port_num;\r
+\r
+ p_ca = (dapl_ibal_ca_t *) hca_ptr->ib_hca_handle;\r
+\r
+ if (p_ca == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "%s() invalid hca_ptr %p", __FUNCTION__, hca_ptr);\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+\r
+ ib_status = ib_query_ca (\r
+ p_ca->h_ca,\r
+ p_ca->p_ca_attr,\r
+ &p_ca->ca_attr_size);\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "%s() ib_query_ca returned failed status = %s\n", \r
+ ib_get_err_str(ib_status));\r
+ return dapl_ib_status_convert (ib_status);\r
+ }\r
+\r
+ p_hca_attr = p_ca->p_ca_attr;\r
+ port_num = hca_ptr->port_num - 1;\r
+\r
+ gid->gid_prefix = p_hca_attr->p_port_attr[port_num].p_gid_table->unicast.prefix;\r
+ gid->guid = p_hca_attr->p_port_attr[port_num].p_gid_table->unicast.interface_id;\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_query_hca\r
+ *\r
+ * Query the hca attribute\r
+ *\r
+ * Input:\r
+ * hca_handl hca handle \r
+ * ep_attr attribute of the ep\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_PARAMETER\r
+ */\r
+\r
+DAT_RETURN dapls_ib_query_hca (\r
+ IN DAPL_HCA *hca_ptr,\r
+ OUT DAT_IA_ATTR *ia_attr,\r
+ OUT DAT_EP_ATTR *ep_attr,\r
+ OUT DAT_SOCK_ADDR6 *ip_addr)\r
+{\r
+ ib_ca_attr_t *p_hca_attr;\r
+ dapl_ibal_ca_t *p_ca;\r
+ ib_api_status_t ib_status;\r
+ ib_hca_port_t port_num;\r
+ GID gid;\r
+ DAT_SOCK_ADDR6 *p_sock_addr;\r
+ DAT_RETURN dat_status = DAT_SUCCESS;\r
+ port_num = hca_ptr->port_num;\r
+\r
+ p_ca = (dapl_ibal_ca_t *) hca_ptr->ib_hca_handle;\r
+\r
+ if (p_ca == NULL)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR, "--> %s: invalid handle %p",\r
+ "DsIQH", hca_ptr);\r
+ return (DAT_INVALID_HANDLE);\r
+ }\r
+\r
+ ib_status = ib_query_ca (\r
+ p_ca->h_ca,\r
+ p_ca->p_ca_attr,\r
+ &p_ca->ca_attr_size);\r
+ if (ib_status != IB_SUCCESS)\r
+ {\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ "--> DsIQH: ib_query_ca returned failed status = %s\n", \r
+ ib_get_err_str(ib_status));\r
+ return (dapl_ib_status_convert (ib_status));\r
+ }\r
+\r
+ p_hca_attr = p_ca->p_ca_attr;\r
+\r
+ if (ip_addr != NULL)\r
+ {\r
+ p_sock_addr = dapl_os_alloc(sizeof(DAT_SOCK_ADDR6));\r
+ if ( !p_sock_addr )\r
+ {\r
+ dat_status = DAT_INSUFFICIENT_RESOURCES;\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_ERR,\r
+ " Query Hca alloc Err: status %d\n",\r
+ dat_status);\r
+ return dat_status;\r
+ }\r
+ dapl_os_memzero(p_sock_addr, sizeof(DAT_SOCK_ADDR6));\r
+\r
+ gid.gid_prefix = p_hca_attr->p_port_attr[port_num-1].p_gid_table->unicast.prefix;\r
+ gid.guid = p_hca_attr->p_port_attr[port_num-1].p_gid_table->unicast.interface_id;\r
+ \r
+ dat_status = dapls_ns_map_ipaddr( hca_ptr,\r
+ gid,\r
+ (DAT_IA_ADDRESS_PTR)p_sock_addr);\r
+ \r
+ if ( dat_status != DAT_SUCCESS )\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,\r
+ " SA Query for local IP failed= %d\n", dat_status );\r
+ /* what to do next ? */\r
+ }\r
+ else\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_CM, "SA query GID for IP: ");\r
+ dapl_dbg_log ( DAPL_DBG_TYPE_CM, "%0d:%d:%d:%d\n", \r
+ (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[2]&0xff,\r
+ (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[3]&0xff,\r
+ (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[4]&0xff,\r
+ (uint8_t)((DAT_IA_ADDRESS_PTR )p_sock_addr)->sa_data[5]&0xff);\r
+ }\r
+\r
+ hca_ptr->hca_address = *p_sock_addr;\r
+\r
+ /* if structure address not from our hca_ptr */\r
+ if ( ip_addr != &hca_ptr->hca_address )\r
+ {\r
+ *ip_addr = *p_sock_addr;\r
+ }\r
+\r
+ dapl_os_free (p_sock_addr, sizeof(DAT_SOCK_ADDR6));\r
+\r
+ } /* ip_addr != NULL */\r
+\r
+ if ( ia_attr != NULL )\r
+ {\r
+ dapl_os_memzero( ia_attr->adapter_name,\r
+ (int)sizeof(ia_attr->adapter_name ));\r
+ dapl_os_memcpy(ia_attr->adapter_name,\r
+ DAT_ADAPTER_NAME, \r
+ min ( (int)dapl_os_strlen(DAT_ADAPTER_NAME),\r
+ (int)(DAT_NAME_MAX_LENGTH)-1 ) );\r
+\r
+ dapl_os_memzero ( ia_attr->vendor_name,\r
+ (int)sizeof(ia_attr->vendor_name) );\r
+ dapl_os_memcpy ( ia_attr->vendor_name, \r
+ DAT_VENDOR_NAME,\r
+ min ( (int)dapl_os_strlen(DAT_VENDOR_NAME),\r
+ (int)(DAT_NAME_MAX_LENGTH)-1 ) );\r
+ \r
+ /* FIXME : Vu\r
+ * this value should be revisited\r
+ * It can be set by DAT consumers\r
+ */\r
+ ia_attr->ia_address_ptr = (DAT_PVOID)&hca_ptr->hca_address;\r
+ ia_attr->hardware_version_major = p_hca_attr->dev_id;\r
+ ia_attr->hardware_version_minor = p_hca_attr->revision;\r
+ ia_attr->max_eps = p_hca_attr->max_qps;\r
+ ia_attr->max_dto_per_ep = p_hca_attr->max_wrs;\r
+ ia_attr->max_rdma_read_per_ep = p_hca_attr->max_qp_resp_res;\r
+ ia_attr->max_evds = p_hca_attr->max_cqs;\r
+ ia_attr->max_evd_qlen = p_hca_attr->max_cqes;\r
+ ia_attr->max_iov_segments_per_dto = p_hca_attr->max_sges;\r
+ ia_attr->max_lmrs = p_hca_attr->init_regions;\r
+ ia_attr->max_lmr_block_size = p_hca_attr->init_region_size;\r
+ ia_attr->max_rmrs = p_hca_attr->init_windows;\r
+ ia_attr->max_lmr_virtual_address = p_hca_attr->max_addr_handles;\r
+ ia_attr->max_rmr_target_address = p_hca_attr->max_addr_handles;\r
+ ia_attr->max_pzs = p_hca_attr->max_pds;\r
+ /*\r
+ * DAT spec does not tie max_mtu_size with IB MTU\r
+ *\r
+ ia_attr->max_mtu_size = \r
+ dapl_ibal_mtu_table[p_hca_attr->p_port_attr->mtu];\r
+ */\r
+ ia_attr->max_mtu_size = \r
+ p_hca_attr->p_port_attr->max_msg_size;\r
+ ia_attr->max_rdma_size = \r
+ p_hca_attr->p_port_attr->max_msg_size;\r
+ ia_attr->num_transport_attr = 0;\r
+ ia_attr->transport_attr = NULL;\r
+ ia_attr->num_vendor_attr = 0;\r
+ ia_attr->vendor_attr = NULL;\r
+ ia_attr->max_iov_segments_per_rdma_read = p_hca_attr->max_sges;\r
+\r
+#ifdef DAT_EXTENSIONS\r
+ ia_attr->extension_supported = DAT_EXTENSION_IB;\r
+ ia_attr->extension_version = DAT_IB_EXTENSION_VERSION;\r
+#endif\r
+ \r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL, \r
+ " --> DsIMU_qHCA: (ver=%x) ep %d ep_q %d evd %d evd_q %d\n", \r
+ ia_attr->hardware_version_major,\r
+ ia_attr->max_eps, ia_attr->max_dto_per_ep,\r
+ ia_attr->max_evds, ia_attr->max_evd_qlen );\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL, \r
+ " --> DsIMU_qHCA: mtu %llu rdma %llu iov %d lmr %d rmr %d"\r
+ " rdma_io %d\n", \r
+ ia_attr->max_mtu_size, ia_attr->max_rdma_size,\r
+ ia_attr->max_iov_segments_per_dto, ia_attr->max_lmrs, \r
+ ia_attr->max_rmrs, ia_attr->max_rdma_read_per_ep );\r
+ }\r
+\r
+ if ( ep_attr != NULL )\r
+ {\r
+ (void) dapl_os_memzero(ep_attr, sizeof(*ep_attr)); \r
+ /*\r
+ * DAT spec does not tie max_mtu_size with IB MTU\r
+ *\r
+ ep_attr->max_mtu_size = \r
+ dapl_ibal_mtu_table[p_hca_attr->p_port_attr->mtu];\r
+ */\r
+ ep_attr->max_mtu_size = p_hca_attr->p_port_attr->max_msg_size;\r
+ ep_attr->max_rdma_size = p_hca_attr->p_port_attr->max_msg_size;\r
+ ep_attr->max_recv_dtos = p_hca_attr->max_wrs;\r
+ ep_attr->max_request_dtos = p_hca_attr->max_wrs;\r
+ ep_attr->max_recv_iov = p_hca_attr->max_sges;\r
+ ep_attr->max_request_iov = p_hca_attr->max_sges;\r
+ ep_attr->max_rdma_read_in = p_hca_attr->max_qp_resp_res;\r
+ ep_attr->max_rdma_read_out= p_hca_attr->max_qp_resp_res;\r
+ \r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL, \r
+ " --> DsIMU_qHCA: msg %llu dto %d iov %d rdma i%d,o%d\n", \r
+ ep_attr->max_mtu_size,\r
+ ep_attr->max_recv_dtos, ep_attr->max_recv_iov,\r
+ ep_attr->max_rdma_read_in, ep_attr->max_rdma_read_out);\r
+ }\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+\r
+DAT_RETURN\r
+dapls_ib_completion_poll ( IN DAPL_HCA *p_hca,\r
+ IN DAPL_EVD *p_evd,\r
+ IN ib_work_completion_t *cqe_ptr )\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_work_completion_t *cqe_filled;\r
+\r
+ /*\r
+ * FIXME - Vu\r
+ * Now we only poll for one cqe. We can poll for more than\r
+ * one completions later for better. However, this requires\r
+ * to change the logic in dapl_evd_dto_callback function\r
+ * to process more than one completion.\r
+ */\r
+ cqe_ptr->p_next = NULL;\r
+ cqe_filled = NULL;\r
+\r
+ if ( !p_hca->ib_hca_handle )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+\r
+ ib_status = ib_poll_cq (p_evd->ib_cq_handle, &cqe_ptr, &cqe_filled);\r
+\r
+ if ( ib_status == IB_INVALID_CQ_HANDLE )\r
+ {\r
+ ib_status = IB_NOT_FOUND;\r
+ }\r
+\r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+\r
+DAT_RETURN\r
+dapls_ib_completion_notify ( IN ib_hca_handle_t hca_handle,\r
+ IN DAPL_EVD *p_evd,\r
+ IN ib_notification_type_t type )\r
+{\r
+ ib_api_status_t ib_status;\r
+ DAT_BOOLEAN solic_notify;\r
+\r
+ if ( !hca_handle )\r
+ {\r
+ return DAT_INVALID_HANDLE;\r
+ }\r
+ solic_notify = (type == IB_NOTIFY_ON_SOLIC_COMP) ? DAT_TRUE : DAT_FALSE; \r
+ ib_status = ib_rearm_cq ( p_evd->ib_cq_handle, solic_notify );\r
+\r
+ return dapl_ib_status_convert (ib_status);\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_dto_wakeup (\r
+ IN DAPL_EVD *evd_ptr)\r
+{\r
+ return dapl_os_wait_object_wakeup(&evd_ptr->wait_object);\r
+}\r
+\r
+DAT_RETURN\r
+dapls_evd_dto_wait (\r
+ IN DAPL_EVD *evd_ptr,\r
+ IN uint32_t timeout)\r
+{\r
+ return dapl_os_wait_object_wait(&evd_ptr->wait_object, timeout);\r
+}\r
+\r
+/*\r
+ * dapls_ib_get_async_event\r
+ *\r
+ * Translate an asynchronous event type to the DAT event.\r
+ * Note that different providers have different sets of errors.\r
+ *\r
+ * Input:\r
+ * cause_ptr provider event cause\r
+ *\r
+ * Output:\r
+ * async_event DAT mapping of error\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_NOT_IMPLEMENTED Caller is not interested this event\r
+ */\r
+\r
+DAT_RETURN dapls_ib_get_async_event(\r
+ IN ib_async_event_rec_t *cause_ptr,\r
+ OUT DAT_EVENT_NUMBER *async_event)\r
+{\r
+ ib_async_event_t event_id;\r
+ DAT_RETURN dat_status;\r
+\r
+ dat_status = DAT_SUCCESS;\r
+ event_id = cause_ptr->code;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_WARN, "--> DsAE: event_id = %d%d\n", event_id);\r
+\r
+ switch (event_id )\r
+ {\r
+ case IB_AE_SQ_ERROR:\r
+ case IB_AE_SQ_DRAINED:\r
+ case IB_AE_RQ_ERROR:\r
+ {\r
+ *async_event = DAT_ASYNC_ERROR_EP_BROKEN;\r
+ break;\r
+ }\r
+\r
+ /* INTERNAL errors */\r
+ case IB_AE_QP_FATAL:\r
+ case IB_AE_CQ_ERROR:\r
+ case IB_AE_LOCAL_FATAL:\r
+ case IB_AE_WQ_REQ_ERROR:\r
+ case IB_AE_WQ_ACCESS_ERROR:\r
+ {\r
+ *async_event = DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR;\r
+ break;\r
+ }\r
+\r
+ /* CATASTROPHIC errors */\r
+ case IB_AE_FLOW_CTRL_ERROR:\r
+ case IB_AE_BUF_OVERRUN:\r
+ {\r
+ *async_event = DAT_ASYNC_ERROR_IA_CATASTROPHIC;\r
+ break;\r
+ }\r
+\r
+ default:\r
+ {\r
+ /*\r
+ * Errors we are not interested in reporting:\r
+ * IB_AE_QP_APM\r
+ * IB_AE_PKEY_TRAP\r
+ * IB_AE_QKEY_TRAP\r
+ * IB_AE_MKEY_TRAP\r
+ * IB_AE_PORT_TRAP\r
+ * IB_AE_QP_APM_ERROR\r
+ * IB_AE_PORT_ACTIVE\r
+ * ...\r
+ */\r
+ dat_status = DAT_NOT_IMPLEMENTED;\r
+ }\r
+\r
+ }\r
+ \r
+ return dat_status;\r
+}\r
+\r
+/*\r
+ * dapls_ib_get_dto_status\r
+ *\r
+ * Return the DAT status of a DTO operation\r
+ *\r
+ * Input:\r
+ * cqe_ptr pointer to completion queue entry\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * Value from ib_status_map table above\r
+ */\r
+\r
+DAT_DTO_COMPLETION_STATUS\r
+dapls_ib_get_dto_status(\r
+ IN ib_work_completion_t *cqe_ptr)\r
+{\r
+ ib_uint32_t ib_status;\r
+\r
+ ib_status = DAPL_GET_CQE_STATUS (cqe_ptr);\r
+\r
+ switch (ib_status)\r
+ {\r
+ case IB_COMP_ST_SUCCESS :\r
+ return DAT_DTO_SUCCESS;\r
+\r
+ case IB_COMP_ST_LOCAL_LEN_ERR:\r
+ return DAT_DTO_ERR_LOCAL_LENGTH;\r
+\r
+ case IB_COMP_ST_LOCAL_OP_ERR:\r
+ return DAT_DTO_ERR_LOCAL_EP;\r
+\r
+ case IB_COMP_ST_LOCAL_PROTECT_ERR:\r
+ return DAT_DTO_ERR_LOCAL_PROTECTION;\r
+\r
+ case IB_COMP_ST_WR_FLUSHED_ERR: \r
+ return DAT_DTO_ERR_FLUSHED;\r
+\r
+ case IB_COMP_ST_MW_BIND_ERR:\r
+ return DAT_RMR_OPERATION_FAILED;\r
+\r
+ case IB_COMP_ST_REM_ACC_ERR:\r
+ return DAT_DTO_ERR_REMOTE_ACCESS;\r
+\r
+ case IB_COMP_ST_REM_OP_ERR:\r
+ return DAT_DTO_ERR_REMOTE_RESPONDER;\r
+\r
+ case IB_COMP_ST_RNR_COUNTER:\r
+ return DAT_DTO_ERR_RECEIVER_NOT_READY;\r
+\r
+ case IB_COMP_ST_TRANSP_COUNTER:\r
+ return DAT_DTO_ERR_TRANSPORT;\r
+\r
+ case IB_COMP_ST_REM_REQ_ERR:\r
+ return DAT_DTO_ERR_REMOTE_RESPONDER;\r
+\r
+ case IB_COMP_ST_BAD_RESPONSE_ERR:\r
+ return DAT_DTO_ERR_BAD_RESPONSE;\r
+\r
+ case IB_COMP_ST_EE_STATE_ERR:\r
+ case IB_COMP_ST_EE_CTX_NO_ERR:\r
+ return DAT_DTO_ERR_TRANSPORT;\r
+\r
+ default:\r
+#ifdef DAPL_DBG\r
+ dapl_dbg_log (DAPL_DBG_TYPE_ERR,"%s() unknown IB_COMP_ST %x(0x%x)\n",\r
+ __FUNCTION__,ib_status,ib_status);\r
+#endif\r
+ return DAT_DTO_FAILURE;\r
+ }\r
+}\r
+\r
+\r
+/*\r
+ * Map all IBAPI DTO completion codes to the DAT equivelent.\r
+ *\r
+ * dapls_ib_get_dat_event\r
+ *\r
+ * Return a DAT connection event given a provider CM event.\r
+ *\r
+ * N.B. Some architectures combine async and CM events into a\r
+ * generic async event. In that case, dapls_ib_get_dat_event()\r
+ * and dapls_ib_get_async_event() should be entry points that\r
+ * call into a common routine.\r
+ *\r
+ * Input:\r
+ * ib_cm_event event provided to the dapl callback routine\r
+ * active switch indicating active or passive connection\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_EVENT_NUMBER of translated provider value\r
+ */\r
+\r
+DAT_EVENT_NUMBER\r
+dapls_ib_get_dat_event (\r
+ IN const ib_cm_events_t ib_cm_event,\r
+ IN DAT_BOOLEAN active)\r
+{\r
+ DAT_EVENT_NUMBER dat_event_num = 0;\r
+ UNREFERENCED_PARAMETER (active);\r
+\r
+ switch ( ib_cm_event)\r
+ {\r
+ case IB_CME_CONNECTED:\r
+ dat_event_num = DAT_CONNECTION_EVENT_ESTABLISHED;\r
+ break;\r
+ case IB_CME_DISCONNECTED:\r
+ dat_event_num = DAT_CONNECTION_EVENT_DISCONNECTED;\r
+ break;\r
+ case IB_CME_DISCONNECTED_ON_LINK_DOWN:\r
+ dat_event_num = DAT_CONNECTION_EVENT_DISCONNECTED;\r
+ break;\r
+ case IB_CME_CONNECTION_REQUEST_PENDING:\r
+ dat_event_num = DAT_CONNECTION_REQUEST_EVENT;\r
+ break;\r
+ case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:\r
+ dat_event_num = DAT_CONNECTION_REQUEST_EVENT;\r
+ break;\r
+ case IB_CME_DESTINATION_REJECT:\r
+ dat_event_num = DAT_CONNECTION_EVENT_NON_PEER_REJECTED;\r
+ break;\r
+ case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:\r
+ dat_event_num = DAT_CONNECTION_EVENT_PEER_REJECTED;\r
+ break;\r
+ case IB_CME_DESTINATION_UNREACHABLE:\r
+ dat_event_num = DAT_CONNECTION_EVENT_UNREACHABLE;\r
+ break;\r
+ case IB_CME_TOO_MANY_CONNECTION_REQUESTS:\r
+ dat_event_num = DAT_CONNECTION_EVENT_NON_PEER_REJECTED;\r
+ break;\r
+ case IB_CME_LOCAL_FAILURE:\r
+ dat_event_num = DAT_CONNECTION_EVENT_BROKEN;\r
+ break;\r
+ case IB_CME_REPLY_RECEIVED:\r
+ case IB_CME_REPLY_RECEIVED_PRIVATE_DATA:\r
+ default:\r
+ break;\r
+ }\r
+#if 0\r
+ dapl_dbg_log (DAPL_DBG_TYPE_CM,\r
+ " dapls_ib_get_dat_event: event translation: (%s) "\r
+ "ib_event 0x%x dat_event 0x%x\n",\r
+ active ? "active" : "passive",\r
+ ib_cm_event,\r
+ dat_event_num);\r
+#endif\r
+ return dat_event_num;\r
+}\r
+\r
+\r
+/*\r
+ * dapls_ib_get_dat_event\r
+ *\r
+ * Return a DAT connection event given a provider CM event.\r
+ *\r
+ * N.B. Some architectures combine async and CM events into a\r
+ * generic async event. In that case, dapls_ib_get_cm_event()\r
+ * and dapls_ib_get_async_event() should be entry points that\r
+ * call into a common routine.\r
+ *\r
+ * WARNING: In this implementation, there are multiple CM\r
+ * events that map to a single DAT event. Be very careful\r
+ * with provider routines that depend on this reverse mapping,\r
+ * they may have to accomodate more CM events than they\r
+ * 'naturally' would.\r
+ *\r
+ * Input:\r
+ * dat_event_num DAT event we need an equivelent CM event for\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * ib_cm_event of translated DAPL value\r
+ */\r
+ib_cm_events_t\r
+dapls_ib_get_cm_event (\r
+ IN DAT_EVENT_NUMBER dat_event_num)\r
+{\r
+ ib_cm_events_t ib_cm_event = 0;\r
+\r
+ switch (dat_event_num)\r
+ {\r
+ case DAT_CONNECTION_EVENT_ESTABLISHED:\r
+ ib_cm_event = IB_CME_CONNECTED;\r
+ break;\r
+ case DAT_CONNECTION_EVENT_DISCONNECTED:\r
+ ib_cm_event = IB_CME_DISCONNECTED;\r
+ break;\r
+ case DAT_CONNECTION_REQUEST_EVENT:\r
+ ib_cm_event = IB_CME_CONNECTION_REQUEST_PENDING;\r
+ break;\r
+ case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:\r
+ ib_cm_event = IB_CME_DESTINATION_REJECT;\r
+ break;\r
+ case DAT_CONNECTION_EVENT_PEER_REJECTED:\r
+ ib_cm_event = IB_CME_DESTINATION_REJECT_PRIVATE_DATA;\r
+ break;\r
+ case DAT_CONNECTION_EVENT_UNREACHABLE:\r
+ ib_cm_event = IB_CME_DESTINATION_UNREACHABLE;\r
+ break;\r
+ case DAT_CONNECTION_EVENT_BROKEN:\r
+ ib_cm_event = IB_CME_LOCAL_FAILURE;\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return ib_cm_event;\r
+}\r
+\r
+\r
+\r
+/*\r
+ * dapls_set_provider_specific_attr\r
+ *\r
+ * Input:\r
+ * attr_ptr Pointer provider specific attributes\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * void\r
+ */\r
+\r
+#ifdef DAT_EXTENSIONS\r
+static DAT_NAMED_ATTR ib_attrs[] = {\r
+ {\r
+ "DAT_EXTENSION_INTERFACE", "TRUE"\r
+ },\r
+ {\r
+ DAT_IB_ATTR_FETCH_AND_ADD, "TRUE"\r
+ },\r
+ {\r
+ DAT_IB_ATTR_CMP_AND_SWAP, "TRUE"\r
+ },\r
+ {\r
+ DAT_IB_ATTR_IMMED_DATA, "TRUE"\r
+ },\r
+};\r
+#define SPEC_ATTR_SIZE( x ) (sizeof( x ) / sizeof( DAT_NAMED_ATTR))\r
+#else\r
+static DAT_NAMED_ATTR *ib_attrs = NULL;\r
+#define SPEC_ATTR_SIZE( x ) 0\r
+#endif\r
+\r
+void dapls_query_provider_specific_attr(\r
+ IN DAPL_IA *ia_ptr,\r
+ IN DAT_PROVIDER_ATTR *attr_ptr )\r
+{\r
+ attr_ptr->num_provider_specific_attr = SPEC_ATTR_SIZE(ib_attrs);\r
+ attr_ptr->provider_specific_attr = ib_attrs;\r
+}\r
+\r
+\r
+DAT_RETURN dapls_ns_map_gid (\r
+ IN DAPL_HCA *hca_ptr,\r
+ IN DAT_IA_ADDRESS_PTR remote_ia_address,\r
+ OUT GID *gid)\r
+{\r
+ return (dapls_ib_ns_map_gid (hca_ptr, remote_ia_address, gid));\r
+}\r
+\r
+DAT_RETURN dapls_ns_map_ipaddr (\r
+ IN DAPL_HCA *hca_ptr,\r
+ IN GID gid,\r
+ OUT DAT_IA_ADDRESS_PTR remote_ia_address)\r
+{\r
+ return (dapls_ib_ns_map_ipaddr (hca_ptr, gid, remote_ia_address));\r
+}\r
+\r
+\r
+#ifdef NOT_USED\r
+/*\r
+ * dapls_ib_post_recv - defered.until QP ! in init state.\r
+ *\r
+ * Provider specific Post RECV function\r
+ */\r
+\r
+DAT_RETURN \r
+dapls_ib_post_recv_defered (\r
+ IN DAPL_EP *ep_ptr,\r
+ IN DAPL_COOKIE *cookie,\r
+ IN DAT_COUNT num_segments,\r
+ IN DAT_LMR_TRIPLET *local_iov)\r
+{\r
+ ib_api_status_t ib_status;\r
+ ib_recv_wr_t *recv_wr, *rwr;\r
+ ib_local_ds_t *ds_array_p;\r
+ DAT_COUNT i, total_len;\r
+\r
+ if (ep_ptr->qp_state != IB_QPS_INIT)\r
+ {\r
+ dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsPR: BAD QP state(%s), not init? "\r
+ "EP %p QP %p cookie %p, num_seg %d\n", \r
+ ib_get_port_state_str(ep_ptr->qp_state), ep_ptr,\r
+ ep_ptr->qp_handle, cookie, num_segments);\r
+ return (DAT_INSUFFICIENT_RESOURCES);\r
+ }\r
+\r
+ recv_wr = dapl_os_alloc (sizeof(ib_recv_wr_t)\r
+ + (num_segments*sizeof(ib_local_ds_t)));\r
+ if (NULL == recv_wr)\r
+ {\r
+ return (DAT_INSUFFICIENT_RESOURCES);\r
+ }\r
+\r
+ dapl_os_memzero(recv_wr, sizeof(ib_recv_wr_t));\r
+ recv_wr->wr_id = (DAT_UINT64) cookie;\r
+ recv_wr->num_ds = num_segments;\r
+\r
+ ds_array_p = (ib_local_ds_t*)(recv_wr+1);\r
+\r
+ recv_wr->ds_array = ds_array_p;\r
+\r
+ //total_len = 0;\r
+\r
+ for (total_len = i = 0; i < num_segments; i++, ds_array_p++)\r
+ {\r
+ ds_array_p->length = (uint32_t)local_iov[i].segment_length;\r
+ ds_array_p->lkey = cl_hton32(local_iov[i].lmr_context);\r
+ ds_array_p->vaddr = local_iov[i].virtual_address;\r
+ total_len += ds_array_p->length;\r
+ }\r
+\r
+ if (cookie != NULL)\r
+ {\r
+ cookie->val.dto.size = total_len;\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_EP,\r
+ "--> DsPR: EP = %p QP = %p cookie= %p, num_seg= %d\n", \r
+ ep_ptr, ep_ptr->qp_handle, cookie, num_segments);\r
+ }\r
+\r
+ recv_wr->p_next = NULL;\r
+\r
+ /* find last defered recv work request, link new on the end */\r
+ rwr=ep_ptr->cm_post;\r
+ if (rwr == NULL)\r
+ {\r
+ ep_ptr->cm_post = (void*)recv_wr;\r
+ i = 1;\r
+ }\r
+ else\r
+ {\r
+ for(i=2; rwr->p_next; rwr=rwr->p_next) i++;\r
+ rwr->p_next = recv_wr;\r
+ }\r
+\r
+ dapl_dbg_log (DAPL_DBG_TYPE_EP, "--> DsPR: %s() EP %p QP %p cookie %p "\r
+ "num_seg %d Tdefered %d\n", \r
+ __FUNCTION__, ep_ptr, ep_ptr->qp_handle, cookie, num_segments,\r
+ i);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+#endif\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_util.h
- *
- * PURPOSE: Utility defs & routines for access to openib-windows IBAL APIs
- *
- * $Id: dapl_ibal_util.h 33 2005-07-11 19:51:17Z ftillier $
- *
- **********************************************************************/
-
-#ifndef _DAPL_IBAL_UTIL_H_
-#define _DAPL_IBAL_UTIL_H_
-
-#include <iba/ib_al.h>
-#include <complib/cl_spinlock.h>
-#include <complib/cl_qlist.h>
-#include <complib/cl_atomic.h>
-
-#ifdef DAT_EXTENSIONS
-#include <dat2\dat_ib_extensions.h>
-#endif
-
-/*
- * Typedefs to map IBAL types to more generic 'ib' types
- */
-#ifdef SOCK_CM
-typedef struct ib_cm_handle *dp_ib_cm_handle_t;
-typedef struct ib_cm_handle *ib_cm_srvc_handle_t;
-#else
-typedef ib_cm_handle_t *dp_ib_cm_handle_t;
-typedef ib_listen_handle_t ib_cm_srvc_handle_t;
-#endif
-
-typedef ib_net64_t IB_HCA_NAME;
-typedef ib_ca_handle_t ib_hca_handle_t;
-typedef DAT_PVOID ib_cqd_handle_t;
-typedef ib_async_event_rec_t ib_error_record_t;
-typedef ib_wr_type_t ib_send_op_type_t;
-typedef ib_wc_t ib_work_completion_t;
-typedef uint32_t ib_hca_port_t;
-typedef uint32_t ib_uint32_t;
-typedef uint32_t ib_comp_handle_t;
-typedef ib_local_ds_t ib_data_segment_t;
-
-typedef unsigned __int3264 cl_dev_handle_t;
-
-
-typedef void (*ib_async_handler_t)(
- IN ib_hca_handle_t ib_hca_handle,
- IN ib_error_record_t *err_code,
- IN void *context);
-
-typedef void (*ib_async_qp_handler_t)(
- IN ib_hca_handle_t ib_hca_handle,
- IN ib_qp_handle_t ib_qp_handle,
- IN ib_error_record_t *err_code,
- IN void *context);
-
-typedef void (*ib_async_cq_handler_t)(
- IN ib_hca_handle_t ib_hca_handle,
- IN ib_cq_handle_t ib_cq_handle,
- IN ib_error_record_t *err_code,
- IN void *context);
-
-typedef ib_net64_t ib_guid_t;
-typedef ib_net16_t ib_lid_t;
-typedef boolean_t ib_bool_t;
-
-typedef struct _GID
-{
- uint64_t gid_prefix;
- uint64_t guid;
-} GID;
-
-typedef enum
-{
- IB_CME_CONNECTED,
- IB_CME_DISCONNECTED,
- IB_CME_DISCONNECTED_ON_LINK_DOWN,
- IB_CME_CONNECTION_REQUEST_PENDING,
- IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA,
- IB_CME_DESTINATION_REJECT,
- IB_CME_DESTINATION_REJECT_PRIVATE_DATA,
- IB_CME_DESTINATION_UNREACHABLE,
- IB_CME_TOO_MANY_CONNECTION_REQUESTS,
- IB_CME_LOCAL_FAILURE,
- IB_CME_REPLY_RECEIVED,
- IB_CME_REPLY_RECEIVED_PRIVATE_DATA,
- IB_CM_LOCAL_FAILURE
-} ib_cm_events_t;
-
-
-typedef enum
-{
- IB_NOTIFY_ON_NEXT_COMP,
- IB_NOTIFY_ON_SOLIC_COMP
-} ib_notification_type_t;
-
-typedef struct _ib_hca_name
-{
- DAT_NAME_PTR hca_name[DAT_NAME_MAX_LENGTH];
-} ib_hca_name_t;
-
-
-#define IB_INVALID_HANDLE NULL
-#define true TRUE
-#define false FALSE
-
-#define IB_MAX_REQ_PDATA_SIZE 92
-#define IB_MAX_REP_PDATA_SIZE 196
-#define IB_MAX_REJ_PDATA_SIZE 148
-#define IB_MAX_DREQ_PDATA_SIZE 220
-#define IB_MAX_DREP_PDATA_SIZE 224
-
-
-/* Resource Not Ready
- 1-6 is an actual retry count which is decremented to zero before
- an error condition is set.
- 7 is 'magic' in that it implies Infinite retry, just keeps trying.
-*/
-#define IB_RNR_RETRY_CNT 7
-
-/*
-IB 1.2 spec, page 331, table 45, RNR NAK timeout encoding (5-bits)
-
-00000=655.36ms(milliseconds)
-00001=0.01ms
-00010=0.02ms
-00011=0.03ms
-00100=0.04ms
-00101=0.06ms
-00110=0.08ms
-00111=0.12ms
-
-11100=163.84ms 28d
-11101=245.76ms 29d
-11110=327.68ms 30d
-11111=491.52ms 31d
-*/
-#define IB_RNR_NAK_TIMEOUT 0
-
-
-typedef void
-(*dapl_ibal_pfn_destructor_t)(
- IN void* context );
-
-typedef struct _dapl_ibal_refs
-{
- atomic32_t count; // number of references
- void* context; // context for destructor
- dapl_ibal_pfn_destructor_t destructor; // called when reference goes to zero
-
-} dapl_ibal_refs_t;
-
-
-typedef struct _dapl_ibal_root
-{
- ib_al_handle_t h_al; // handle to Access Layer
- cl_spinlock_t ca_lock; // CA list lock
- cl_qlist_t ca_head; // list head of CAs
- boolean_t shutdown; // when true, driver is shutting down
- boolean_t initialized; // when true, lib is initialized
-
-} dapl_ibal_root_t;
-
-
-typedef struct _dapl_ibal_ca
-{
- cl_list_item_t next; // peer CA list
- ib_ca_handle_t h_ca; // handle to open CA
- ib_ca_attr_t *p_ca_attr; // CA attributes
- uint32_t ca_attr_size;// size of ca attribute
- dapl_ibal_refs_t refs; // reference counting
- cl_spinlock_t port_lock; // port list lock
- cl_qlist_t port_head; // port list head for this CA
- cl_spinlock_t evd_cb_lock; // EVD async error cb list lock
- cl_qlist_t evd_cb_head; // EVD async error cb list head for this CA
- cl_dev_handle_t mlnx_device;
- DAT_PVOID *ia_ptr; // hook for CA async callbacks
-} dapl_ibal_ca_t;
-
-
-typedef struct _dapl_ibal_port
-{
- cl_list_item_t next; // peer CA list
- dapl_ibal_ca_t *ca; // pointer to parent CA
- ib_port_attr_t *p_attr; // port attributes
- dapl_ibal_refs_t refs; // reference counting
-} dapl_ibal_port_t;
-
-typedef struct _dapl_ibal_evd_cb
-{
- cl_list_item_t next; // peer CA list
- ib_async_handler_t pfn_async_err_cb;
- ib_async_qp_handler_t pfn_async_qp_err_cb;
- ib_async_cq_handler_t pfn_async_cq_err_cb;
- void *context;
-} dapl_ibal_evd_cb_t;
-
-/*
- * Definitions to map DTO OPs to IBAL Work-Request ops.
- */
-#define OP_BAD_OPCODE 0
-#define OP_RDMA_READ WR_RDMA_READ
-#define OP_RDMA_WRITE WR_RDMA_WRITE
-#define OP_SEND WR_SEND
-#define OP_COMP_AND_SWAP WR_COMPARE_SWAP
-#define OP_FETCH_AND_ADD WR_FETCH_ADD
-
-#define OP_RECEIVE 8 /* (8) */
-#define OP_BIND_MW 9 /* no-equivalent */
-#define OP_RDMA_WRITE_IMM 10 /* RDMA_WRITE+Immediate data */
-#define OP_RECEIVE_IMM 11 /* no-equivalent */
-
-/*
- * Definitions to map QP state
- */
-#define IB_QP_STATE_RESET IB_QPS_RESET
-#define IB_QP_STATE_INIT IB_QPS_INIT
-#define IB_QP_STATE_RTR IB_QPS_RTR
-#define IB_QP_STATE_RTS IB_QPS_RTS
-#define IB_QP_STATE_SQE IB_QPS_SQERR
-#define IB_QP_STATE_SQD IB_QPS_SQD
-#define IB_QP_STATE_ERROR IB_QPS_ERROR
-
-/*
- * Definitions to map Memory OPs
- */
-#define IB_ACCESS_LOCAL_WRITE IB_AC_LOCAL_WRITE
-#define IB_ACCESS_REMOTE_READ IB_AC_RDMA_READ
-#define IB_ACCESS_REMOTE_WRITE IB_AC_RDMA_WRITE
-#define IB_ACCESS_REMOTE_ATOMIC IB_AC_ATOMIC
-#define IB_ACCESS_MEM_WINDOW_BIND IB_AC_MW_BIND
-
-/*
- * CQE status
- */
-enum _dapl_comp_status
-{
- IB_COMP_ST_SUCCESS = IB_WCS_SUCCESS,
- IB_COMP_ST_LOCAL_LEN_ERR = IB_WCS_LOCAL_LEN_ERR,
- IB_COMP_ST_LOCAL_OP_ERR = IB_WCS_LOCAL_OP_ERR,
- IB_COMP_ST_LOCAL_PROTECT_ERR = IB_WCS_LOCAL_PROTECTION_ERR,
- IB_COMP_ST_WR_FLUSHED_ERR = IB_WCS_WR_FLUSHED_ERR,
- IB_COMP_ST_MW_BIND_ERR = IB_WCS_MEM_WINDOW_BIND_ERR,
- IB_COMP_ST_REM_ACC_ERR = IB_WCS_REM_ACCESS_ERR,
- IB_COMP_ST_REM_OP_ERR = IB_WCS_REM_OP_ERR,
- IB_COMP_ST_RNR_COUNTER = IB_WCS_RNR_RETRY_ERR,
- IB_COMP_ST_TRANSP_COUNTER = IB_WCS_TIMEOUT_RETRY_ERR,
- IB_COMP_ST_REM_REQ_ERR = IB_WCS_REM_INVALID_REQ_ERR,
- IB_COMP_ST_BAD_RESPONSE_ERR = IB_WCS_UNMATCHED_RESPONSE,
- IB_COMP_ST_EE_STATE_ERR,
- IB_COMP_ST_EE_CTX_NO_ERR
-};
-
-
-/*
- * Macro to check the state of an EP/QP
- */
-#define DAPLIB_NEEDS_INIT(ep) ((ep)->qp_state == IB_QPS_ERROR)
-
-
-/*
- * Resolve IBAL return codes to their DAPL equivelent.
- * Do not return invalid Handles, the user is not able
- * to deal with them.
- */
-STATIC _INLINE_ DAT_RETURN
-dapl_ib_status_convert (
- IN int32_t ib_status)
-{
- switch ( ib_status )
- {
- case IB_SUCCESS:
- {
- return DAT_SUCCESS;
- }
- case IB_INSUFFICIENT_RESOURCES:
- case IB_INSUFFICIENT_MEMORY:
- case IB_RESOURCE_BUSY:
- {
- return DAT_INSUFFICIENT_RESOURCES;
- }
- case IB_INVALID_CA_HANDLE:
- case IB_INVALID_CQ_HANDLE:
- case IB_INVALID_QP_HANDLE:
- case IB_INVALID_PD_HANDLE:
- case IB_INVALID_MR_HANDLE:
- case IB_INVALID_MW_HANDLE:
- case IB_INVALID_AL_HANDLE:
- case IB_INVALID_AV_HANDLE:
- {
- return DAT_INVALID_HANDLE;
- }
- case IB_INVALID_PKEY:
- {
- return DAT_PROTECTION_VIOLATION;
- }
- case IB_INVALID_LKEY:
- case IB_INVALID_RKEY:
- case IB_INVALID_PERMISSION:
- {
- return DAT_PRIVILEGES_VIOLATION;
- }
- case IB_INVALID_MAX_WRS:
- case IB_INVALID_MAX_SGE:
- case IB_INVALID_CQ_SIZE:
- case IB_INVALID_SETTING:
- case IB_INVALID_SERVICE_TYPE:
- case IB_INVALID_GID:
- case IB_INVALID_LID:
- case IB_INVALID_GUID:
- case IB_INVALID_PARAMETER:
- {
- return DAT_INVALID_PARAMETER;
- }
- case IB_INVALID_QP_STATE:
- case IB_INVALID_APM_STATE:
- case IB_INVALID_PORT_STATE:
- case IB_INVALID_STATE:
- {
- return DAT_INVALID_STATE;
- }
- case IB_NOT_FOUND:
- {
- return DAT_QUEUE_EMPTY;
- }
- case IB_OVERFLOW:
- {
- return DAT_QUEUE_FULL;
- }
- case IB_UNSUPPORTED:
- {
- return DAT_NOT_IMPLEMENTED;
- }
- case IB_TIMEOUT:
- {
- return DAT_TIMEOUT_EXPIRED;
- }
- case IB_CANCELED:
- {
- return DAT_ABORT;
- }
- default:
- {
- return DAT_INTERNAL_ERROR;
- }
- }
-}
-
-#define TAKE_LOCK( lock ) \
- cl_spinlock_acquire( &(lock) )
-
-#define RELEASE_LOCK( lock ) \
- cl_spinlock_release( &(lock) )
-
-#define LOCK_INSERT_HEAD( lock, head, item ) \
-{ \
- TAKE_LOCK( lock ); \
- cl_qlist_insert_head( &head, (cl_list_item_t*)(&item) ); \
- RELEASE_LOCK( lock ); \
-}
-
-#define LOCK_INSERT_TAIL( lock, tail, item ) \
-{ \
- TAKE_LOCK( lock ); \
- cl_qlist_insert_tail( &tail, (cl_list_item_t*)(&item) ); \
- RELEASE_LOCK( lock ); \
-}
-
-#define INIT_REFERENCE( p_ref, n, con, destruct ) \
-{ \
- (p_ref)->count = n; \
- (p_ref)->context = con; \
- (p_ref)->destructor = destruct; \
-}
-
-#define TAKE_REFERENCE( p_ref ) \
- cl_atomic_inc( &(p_ref)->count )
-
-#define REMOVE_REFERENCE( p_ref ) \
-{ \
- if ( cl_atomic_dec( &(p_ref)->count ) == 0 ) \
- if ( (p_ref)->destructor ) \
- (p_ref)->destructor( (p_ref)->context ); \
-}
-
-/*
- * dapl_llist_entry in dapl.h but dapl.h depends on provider
- * typedef's in this file first. move dapl_llist_entry out of dapl.h
- */
-struct ib_llist_entry
-{
- struct dapl_llist_entry *flink;
- struct dapl_llist_entry *blink;
- void *data;
- struct dapl_llist_entry *list_head;
-};
-
-#ifdef SOCK_CM
-
-typedef enum
-{
- IB_THREAD_INIT,
- IB_THREAD_RUN,
- IB_THREAD_CANCEL,
- IB_THREAD_EXIT
-
-} ib_thread_state_t;
-
-typedef enum scm_state
-{
- SCM_INIT,
- SCM_LISTEN,
- SCM_CONN_PENDING,
- SCM_ACCEPTING,
- SCM_ACCEPTED,
- SCM_REJECTED,
- SCM_CONNECTED,
- SCM_DISCONNECTED,
- SCM_DESTROY
-
-} SCM_STATE;
-
-#endif /* SOCK_CM */
-
-typedef struct _ib_hca_transport
-{
-#ifdef SOCK_CM
- int max_inline_send;
- ib_thread_state_t cr_state; /* CR thread */
- DAPL_OS_THREAD thread; /* CR thread */
- DAPL_OS_LOCK lock; /* CR serialization */
- struct ib_llist_entry *list; /* Connection Requests */
-#endif
- struct dapl_hca *d_hca;
- DAPL_OS_WAIT_OBJECT wait_object;
- DAPL_ATOMIC handle_ref_count; /* # of ia_opens on handle */
- ib_cqd_handle_t ib_cqd_handle; /* cq domain handle */
-
- /* Name service support */
- void *name_service_handle;
-
-} ib_hca_transport_t;
-
-/* provider specfic fields for shared memory support */
-typedef uint32_t ib_shm_transport_t;
-
-#ifdef SOCK_CM
-
-/* inline send rdma threshold */
-#define INLINE_SEND_DEFAULT 128
-
-/* CM mappings use SOCKETS */
-
-/* destination info exchanged between dapl, define wire protocol version */
-#define DSCM_VER 2
-
-typedef struct _ib_qp_cm
-{
- ib_net16_t ver;
- ib_net16_t rej;
- ib_net16_t lid;
- ib_net16_t port;
- ib_net32_t qpn;
- ib_net32_t p_size;
- DAT_SOCK_ADDR6 ia_address;
- GID gid;
-
-} ib_qp_cm_t;
-
-struct ib_cm_handle
-{
- struct ib_llist_entry entry;
- DAPL_OS_LOCK lock;
- SCM_STATE state;
- int socket;
- int l_socket;
- struct dapl_hca *hca;
- DAT_HANDLE sp;
- DAT_HANDLE cr;
- struct dapl_ep *ep;
- ib_qp_cm_t dst;
- unsigned char p_data[256];
-};
-
-DAT_RETURN dapli_init_sock_cm ( IN DAPL_HCA *hca_ptr );
-
-#endif /* SOCK_CM */
-
-/*
- * Prototype
- */
-
-extern ib_api_status_t
-dapls_modify_qp_state_to_error (
- ib_qp_handle_t qp_handle );
-
-extern ib_api_status_t
-dapls_modify_qp_state_to_reset (
- ib_qp_handle_t);
-
-extern ib_api_status_t
-dapls_modify_qp_state_to_init (
- ib_qp_handle_t, DAT_EP_ATTR *, dapl_ibal_port_t *);
-
-extern ib_api_status_t
-dapls_modify_qp_state_to_rtr (
- ib_qp_handle_t, ib_net32_t, ib_lid_t, dapl_ibal_port_t *);
-
-extern ib_api_status_t
-dapls_modify_qp_state_to_rts (
- ib_qp_handle_t);
-
-extern void
-dapli_ibal_ca_async_error_callback(
- IN ib_async_event_rec_t* p_err_rec );
-
-extern dapl_ibal_port_t *
-dapli_ibal_get_port (
- IN dapl_ibal_ca_t *p_ca,
- IN uint8_t port_num);
-
-extern int32_t dapls_ib_init (void);
-extern int32_t dapls_ib_release (void);
-
-extern dapl_ibal_evd_cb_t *
-dapli_find_evd_cb_by_context(
- IN void *context,
- IN dapl_ibal_ca_t *ca);
-
-extern IB_HCA_NAME
-dapl_ib_convert_name(IN char *name);
-
-
-STATIC _INLINE_ int32_t
-dapli_ibal_convert_privileges (IN DAT_MEM_PRIV_FLAGS privileges )
-{
- int32_t value = DAT_MEM_PRIV_NONE_FLAG;
-
- /*
- * if (DAT_MEM_PRIV_LOCAL_READ_FLAG & privileges)
- * do nothing
- */
- if (DAT_MEM_PRIV_LOCAL_WRITE_FLAG & privileges)
- value |= IB_ACCESS_LOCAL_WRITE;
-
- if (DAT_MEM_PRIV_REMOTE_WRITE_FLAG & privileges)
- value |= IB_ACCESS_REMOTE_WRITE;
-
- if (DAT_MEM_PRIV_REMOTE_READ_FLAG & privileges)
- value |= IB_ACCESS_REMOTE_READ;
-
-#ifdef DAT_EXTENSIONS
- if (DAT_IB_MEM_PRIV_REMOTE_ATOMIC & privileges)
- value |= IB_ACCESS_REMOTE_ATOMIC;
-#endif
-
-#ifdef DAPL_DBG
- if (value == DAT_MEM_PRIV_NONE_FLAG)
- {
- dapl_dbg_log(DAPL_DBG_TYPE_ERR,"%s() Unknown DAT_MEM_PRIV_ 0x%x\n",
- __FUNCTION__,privileges);
- }
-#endif
- return value;
-}
-
-#define dapl_rmr_convert_privileges(p) dapli_ibal_convert_privileges(p)
-#define dapl_lmr_convert_privileges(p) dapli_ibal_convert_privileges(p)
-
-#endif /* _DAPL_IBAL_UTIL_H_ */
+\r
+/*\r
+ * Copyright (c) 2005-2007 Intel Corporation. All rights reserved.\r
+ * Copyright (c) 2002, Network Appliance, Inc. All rights reserved. \r
+ * \r
+ * This Software is licensed under the terms of the "Common Public\r
+ * License" a copy of which is in the file LICENSE.txt in the root\r
+ * directory. The license is also available from the Open Source\r
+ * Initiative, see http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_ibal_util.h\r
+ *\r
+ * PURPOSE: Utility defs & routines for access to openib-windows IBAL APIs\r
+ *\r
+ * $Id: dapl_ibal_util.h 33 2005-07-11 19:51:17Z ftillier $\r
+ *\r
+ **********************************************************************/\r
+\r
+#ifndef _DAPL_IBAL_UTIL_H_\r
+#define _DAPL_IBAL_UTIL_H_\r
+\r
+#include <iba/ib_al.h>\r
+#include <complib/cl_spinlock.h>\r
+#include <complib/cl_qlist.h>\r
+#include <complib/cl_atomic.h>\r
+\r
+#ifdef DAT_EXTENSIONS\r
+#include <dat2\dat_ib_extensions.h>\r
+#endif\r
+\r
+/*\r
+ * Typedefs to map IBAL types to more generic 'ib' types\r
+ */\r
+#ifdef SOCK_CM\r
+typedef struct ib_cm_handle *dp_ib_cm_handle_t;\r
+typedef struct ib_cm_handle *ib_cm_srvc_handle_t;\r
+#else\r
+typedef ib_cm_handle_t *dp_ib_cm_handle_t;\r
+typedef ib_listen_handle_t ib_cm_srvc_handle_t;\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
+\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) 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;
-
- /* Mellanox Specific completion handle for registration/de-registration */
- ib_comp_handle_t ib_comp_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;
-
-#ifdef CQ_WAIT_OBJECT
- /* Some providers support a direct CQ wait object */
- ib_wait_obj_handle_t cq_wait_obj_handle;
-#endif
-
- DAT_COUNT threshold;
- DAPL_EVD_COMPLETION completion_type;
-
-#ifdef DAPL_COUNTERS
- void *cntrs;
-#endif
-};
-
-/* DAPL_PRIVATE used to pass private data in a connection */
-struct dapl_private
-{
-#ifdef IBHOSTS_NAMING
- DAT_SOCK_ADDR6 hca_address; /* local address of HCA*/
-#endif /* IBHOSTS_NAMING */
- unsigned char private_data[DAPL_MAX_PRIVATE_DATA_SIZE];
-};
-
-/* uDAPL timer entry, used to queue timeouts */
-struct dapl_timer_entry
-{
- DAPL_LLIST_ENTRY list_entry; /* link entry on ia struct */
- DAPL_OS_TIMEVAL expires;
- void (*function) (uintptr_t);
- void *data;
-};
-
-#ifdef DAPL_DBG_IO_TRC
-
-#define DBG_IO_TRC_QLEN 32 /* length of trace buffer */
-#define DBG_IO_TRC_IOV 3 /* iov elements we keep track of */
-
-struct io_buf_track
-{
- Ib_send_op_type op_type;
- DAPL_COOKIE *cookie;
- DAT_LMR_TRIPLET iov[DBG_IO_TRC_IOV];
- DAT_RMR_TRIPLET remote_iov;
- unsigned int done; /* count to track completion ordering */
- int status;
- void *wqe;
-};
-
-#endif /* DAPL_DBG_IO_TRC */
-
-/* DAPL_EP maps to DAT_EP_HANDLE */
-struct dapl_ep
-{
- DAPL_HEADER header;
- /* What the DAT Consumer asked for */
- DAT_EP_PARAM param;
-
- /* The RC Queue Pair (IBM OS API) */
- ib_qp_handle_t qp_handle;
- unsigned int qpn; /* qp number */
- ib_qp_state_t qp_state;
-
- /* communications manager handle (IBM OS API) */
- dp_ib_cm_handle_t cm_handle;
-
- /* store the remote IA address here, reference from the param
- * struct which only has a pointer, no storage
- */
- DAT_SOCK_ADDR6 remote_ia_address;
-
- /* For passive connections we maintain a back pointer to the CR */
- void * cr_ptr;
-
- /* pointer to connection timer, if set */
- struct dapl_timer_entry *cxn_timer;
-
- /* private data container */
- DAPL_PRIVATE private;
-
- /* DTO data */
- DAPL_ATOMIC req_count;
- DAPL_ATOMIC recv_count;
-
- DAPL_COOKIE_BUFFER req_buffer;
- DAPL_COOKIE_BUFFER recv_buffer;
-
-#ifdef DAPL_DBG_IO_TRC
- int ibt_dumped;
- struct io_buf_track *ibt_base;
- DAPL_RING_BUFFER ibt_queue;
-#endif /* DAPL_DBG_IO_TRC */
-#if defined(_WIN32) || defined(_WIN64)
- DAT_BOOLEAN recv_discreq;
- DAT_BOOLEAN sent_discreq;
- dp_ib_cm_handle_t ibal_cm_handle;
-#endif
-#ifdef DAPL_COUNTERS
- void *cntrs;
-#endif
-};
-
-/* DAPL_SRQ maps to DAT_SRQ_HANDLE */
-struct dapl_srq
-{
- DAPL_HEADER header;
- DAT_SRQ_PARAM param;
- DAPL_ATOMIC srq_ref_count;
- DAPL_COOKIE_BUFFER recv_buffer;
- DAPL_ATOMIC recv_count;
-};
-
-/* DAPL_PZ maps to DAT_PZ_HANDLE */
-struct dapl_pz
-{
- DAPL_HEADER header;
- ib_pd_handle_t pd_handle;
- DAPL_ATOMIC pz_ref_count;
-};
-
-/* DAPL_LMR maps to DAT_LMR_HANDLE */
-struct dapl_lmr
-{
- DAPL_HEADER header;
- DAT_LMR_PARAM param;
- ib_mr_handle_t mr_handle;
- DAPL_ATOMIC lmr_ref_count;
-#if !defined(__KDAPL__)
- char shmid[DAT_LMR_COOKIE_SIZE]; /* shared memory ID */
- ib_shm_transport_t ib_trans; /* provider specific data */
-#endif /* !__KDAPL__ */
-};
-
-/* DAPL_RMR maps to DAT_RMR_HANDLE */
-struct dapl_rmr
-{
- DAPL_HEADER header;
- DAT_RMR_PARAM param;
- DAPL_EP *ep;
- DAPL_PZ *pz;
- DAPL_LMR *lmr;
- ib_mw_handle_t mw_handle;
-};
-
-/* SP types, indicating the state and queue */
-typedef enum dapl_sp_state
-{
- DAPL_SP_STATE_FREE,
- DAPL_SP_STATE_PSP_LISTENING,
- DAPL_SP_STATE_PSP_PENDING,
- DAPL_SP_STATE_RSP_LISTENING,
- DAPL_SP_STATE_RSP_PENDING
-} DAPL_SP_STATE;
-
-/* DAPL_SP maps to DAT_PSP_HANDLE and DAT_RSP_HANDLE */
-struct dapl_sp
-{
- DAPL_HEADER header;
- DAPL_SP_STATE state; /* type and queue of the SP */
-
- /* PSP/RSP PARAM fields */
- DAT_CONN_QUAL conn_qual;
- DAT_EVD_HANDLE evd_handle;
- DAT_PSP_FLAGS psp_flags;
- DAT_EP_HANDLE ep_handle;
-
- /* maintenence fields */
- DAT_BOOLEAN listening; /* PSP is registered & active */
- ib_cm_srvc_handle_t cm_srvc_handle; /* Used by Mellanox CM */
- DAPL_LLIST_HEAD cr_list_head; /* CR pending queue */
- DAT_COUNT cr_list_count; /* count of CRs on queue */
-#if defined(_VENDOR_IBAL_)
- DAPL_OS_WAIT_OBJECT wait_object; /* cancel & destroy. */
-#endif
-};
-
-/* DAPL_CR maps to DAT_CR_HANDLE */
-struct dapl_cr
-{
- DAPL_HEADER header;
-
- /* for convenience the data is kept as a DAT_CR_PARAM.
- * however, the "local_endpoint" field is always NULL
- * so this wastes a pointer. This is probably ok to
- * simplify code, espedially dat_cr_query.
- */
- DAT_CR_PARAM param;
- /* IB specific fields */
- dp_ib_cm_handle_t ib_cm_handle;
-
- DAT_SOCK_ADDR6 remote_ia_address;
- /* Assuming that the maximum private data size is small.
- * If it gets large, use of a pointer may be appropriate.
- */
- unsigned char private_data[DAPL_MAX_PRIVATE_DATA_SIZE];
- /*
- * Need to be able to associate the CR back to the PSP for
- * dapl_cr_reject.
- */
- DAPL_SP *sp_ptr;
-};
-
-typedef enum dapl_dto_type
-{
- DAPL_DTO_TYPE_SEND,
- DAPL_DTO_TYPE_RECV,
- DAPL_DTO_TYPE_RDMA_WRITE,
- DAPL_DTO_TYPE_RDMA_READ,
-#ifdef DAT_EXTENSIONS
- DAPL_DTO_TYPE_EXTENSION,
-#endif
-} DAPL_DTO_TYPE;
-
-typedef enum dapl_cookie_type
-{
- DAPL_COOKIE_TYPE_NULL,
- DAPL_COOKIE_TYPE_DTO,
- DAPL_COOKIE_TYPE_RMR,
-} DAPL_COOKIE_TYPE;
-
-/* DAPL_DTO_COOKIE used as context for DTO WQEs */
-struct dapl_dto_cookie
-{
- DAPL_DTO_TYPE type;
- DAT_DTO_COOKIE cookie;
- DAT_COUNT size; /* used for SEND and RDMA write */
-};
-
-/* DAPL_RMR_COOKIE used as context for bind WQEs */
-struct dapl_rmr_cookie
-{
- DAPL_RMR *rmr;
- DAT_RMR_COOKIE cookie;
-};
-
-/* DAPL_COOKIE used as context for WQEs */
-struct dapl_cookie
-{
- DAPL_COOKIE_TYPE type; /* Must be first, to define struct. */
- DAPL_EP *ep;
- DAT_COUNT index;
- union
- {
- DAPL_DTO_COOKIE dto;
- DAPL_RMR_COOKIE rmr;
- } val;
-};
-
-/*
- * Private Data operations. Used to obtain the size of the private
- * data from the provider layer.
- */
-typedef enum dapl_private_data_op
-{
- DAPL_PDATA_CONN_REQ = 0, /* connect request */
- DAPL_PDATA_CONN_REP = 1, /* connect reply */
- DAPL_PDATA_CONN_REJ = 2, /* connect reject */
- DAPL_PDATA_CONN_DREQ = 3, /* disconnect request */
- DAPL_PDATA_CONN_DREP = 4, /* disconnect reply */
-} DAPL_PDATA_OP;
-
-
-/*
- * Generic HCA name field
- */
-#define DAPL_HCA_NAME_MAX_LEN 260
-typedef char DAPL_HCA_NAME[DAPL_HCA_NAME_MAX_LEN+1];
-
-#ifdef IBHOSTS_NAMING
-
-/*
- * Simple mapping table to match IP addresses to GIDs. Loaded
- * by dapl_init.
- */
-typedef struct _dapl_gid_map_table
-{
- uint32_t ip_address;
- ib_gid_t gid;
-} DAPL_GID_MAP;
-
-#endif /* IBHOSTS_NAMING */
-
-/*
- * IBTA defined reason for reject message: See IBTA 1.1 specification,
- * 12.6.7.2 REJECTION REASON section.
- */
-#define IB_CM_REJ_REASON_CONSUMER_REJ 0x001C
-
-
-#if defined(DAPL_DBG_IO_TRC)
-/*********************************************************************
- * *
- * Debug I/O tracing support prototypes *
- * *
- *********************************************************************/
-/*
- * I/O tracing support
- */
-void dapls_io_trc_alloc (
- DAPL_EP *ep_ptr);
-
-void dapls_io_trc_update_completion (
- DAPL_EP *ep_ptr,
- DAPL_COOKIE *cookie,
- ib_uint32_t ib_status );
-
-void dapls_io_trc_dump (
- DAPL_EP *ep_ptr,
- ib_work_completion_t *cqe_ptr,
- ib_uint32_t ib_status);
-
-#else /* DAPL_DBG_IO_TRC */
-
-#define dapls_io_trc_alloc(a)
-#define dapls_io_trc_update_completion(a, b, c)
-#define dapls_io_trc_dump(a, b, c)
-
-#endif /* DAPL_DBG_IO_TRC */
-
-
-/*********************************************************************
- * *
- * Function Prototypes *
- * *
- *********************************************************************/
-
-typedef void (*DAPL_CONNECTION_STATE_HANDLER) (
- IN DAPL_EP *,
- IN ib_cm_events_t,
- IN const void *,
- OUT DAT_EVENT *);
-
-/*
- * DAT Mandated functions
- */
-
-extern DAT_RETURN DAT_API dapl_ia_open (
- IN const DAT_NAME_PTR, /* name */
- IN DAT_COUNT, /* asynch_evd_qlen */
- INOUT DAT_EVD_HANDLE *, /* asynch_evd_handle */
- OUT DAT_IA_HANDLE *); /* ia_handle */
-
-extern DAT_RETURN DAT_API dapl_ia_close (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_CLOSE_FLAGS ); /* ia_flags */
-
-
-extern DAT_RETURN DAT_API dapl_ia_query (
- IN DAT_IA_HANDLE, /* ia handle */
- OUT DAT_EVD_HANDLE *, /* async_evd_handle */
- IN DAT_IA_ATTR_MASK, /* ia_params_mask */
- OUT DAT_IA_ATTR *, /* ia_params */
- IN DAT_PROVIDER_ATTR_MASK, /* provider_params_mask */
- OUT DAT_PROVIDER_ATTR * ); /* provider_params */
-
-
-/* helper functions */
-
-extern DAT_RETURN DAT_API dapl_set_consumer_context (
- IN DAT_HANDLE, /* dat handle */
- IN DAT_CONTEXT); /* context */
-
-extern DAT_RETURN DAT_API dapl_get_consumer_context (
- IN DAT_HANDLE, /* dat handle */
- OUT DAT_CONTEXT * ); /* context */
-
-extern DAT_RETURN DAT_API dapl_get_handle_type (
- IN DAT_HANDLE,
- OUT DAT_HANDLE_TYPE * );
-
-/* CNO functions */
-
-#if !defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_cno_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_OS_WAIT_PROXY_AGENT, /* agent */
- OUT DAT_CNO_HANDLE *); /* cno_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_modify_agent (
- IN DAT_CNO_HANDLE, /* cno_handle */
- IN DAT_OS_WAIT_PROXY_AGENT); /* agent */
-
-extern DAT_RETURN DAT_API dapl_cno_query (
- IN DAT_CNO_HANDLE, /* cno_handle */
- IN DAT_CNO_PARAM_MASK, /* cno_param_mask */
- OUT DAT_CNO_PARAM * ); /* cno_param */
-
-extern DAT_RETURN DAT_API dapl_cno_free (
- IN DAT_CNO_HANDLE); /* cno_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_wait (
- IN DAT_CNO_HANDLE, /* cno_handle */
- IN DAT_TIMEOUT, /* timeout */
- OUT DAT_EVD_HANDLE *); /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_fd_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- OUT DAT_FD *, /* file_descriptor */
- OUT DAT_CNO_HANDLE *); /* cno_handle */
-
-extern DAT_RETURN DAT_API dapl_cno_trigger (
- IN DAT_CNO_HANDLE, /* cno_handle */
- OUT DAT_EVD_HANDLE *); /* evd_handle */
-
-#endif /* !defined(__KERNEL__) */
-
-/* CR Functions */
-
-extern DAT_RETURN DAT_API dapl_cr_query (
- IN DAT_CR_HANDLE, /* cr_handle */
- IN DAT_CR_PARAM_MASK, /* cr_args_mask */
- OUT DAT_CR_PARAM * ); /* cwr_args */
-
-extern DAT_RETURN DAT_API dapl_cr_accept (
- IN DAT_CR_HANDLE, /* cr_handle */
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* private_data_size */
- IN const DAT_PVOID ); /* private_data */
-
-extern DAT_RETURN DAT_API dapl_cr_reject (
- IN DAT_CR_HANDLE, /* cr_handle */
- IN DAT_COUNT, /* private_data_size */
- IN const DAT_PVOID ); /* private_data */
-
-extern DAT_RETURN DAT_API dapl_cr_handoff (
- IN DAT_CR_HANDLE, /* cr_handle */
- IN DAT_CONN_QUAL); /* handoff */
-
-/* EVD Functions */
-
-#if defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_ia_memtype_hint (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_MEM_TYPE, /* mem_type */
- IN DAT_VLEN, /* length */
- IN DAT_MEM_OPT, /* mem_optimization */
- OUT DAT_VLEN *, /* suggested_length */
- OUT DAT_VADDR *); /* suggested_alignment */
-
-extern DAT_RETURN DAT_API dapl_evd_kcreate (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_COUNT, /* evd_min_qlen */
- IN DAT_UPCALL_POLICY, /* upcall_policy */
- IN const DAT_UPCALL_OBJECT *, /* upcall */
- IN DAT_EVD_FLAGS, /* evd_flags */
- OUT DAT_EVD_HANDLE * ); /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_evd_kquery (
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_EVD_PARAM_MASK, /* evd_args_mask */
- OUT DAT_EVD_PARAM * ); /* evd_args */
-
-#else
-extern DAT_RETURN DAT_API dapl_evd_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_COUNT, /* evd_min_qlen */
- IN DAT_CNO_HANDLE, /* cno_handle */
- IN DAT_EVD_FLAGS, /* evd_flags */
- OUT DAT_EVD_HANDLE * ); /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_evd_query (
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_EVD_PARAM_MASK, /* evd_args_mask */
- OUT DAT_EVD_PARAM * ); /* evd_args */
-#endif /* defined(__KERNEL__) */
-
-#if defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_evd_modify_upcall (
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_UPCALL_POLICY, /* upcall_policy */
- IN const DAT_UPCALL_OBJECT * ); /* upcall */
-
-#else
-
-extern DAT_RETURN DAT_API dapl_evd_modify_cno (
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_CNO_HANDLE); /* cno_handle */
-#endif
-
-extern DAT_RETURN DAT_API dapl_evd_enable (
- IN DAT_EVD_HANDLE); /* evd_handle */
-
-extern DAT_RETURN DAT_API dapl_evd_disable (
- IN DAT_EVD_HANDLE); /* evd_handle */
-
-#if !defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_evd_wait (
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_TIMEOUT, /* timeout */
- IN DAT_COUNT, /* threshold */
- OUT DAT_EVENT *, /* event */
- OUT DAT_COUNT *); /* nmore */
-#endif /* !defined(__KERNEL__) */
-
-extern DAT_RETURN DAT_API dapl_evd_resize (
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_COUNT ); /* evd_qlen */
-
-extern DAT_RETURN DAT_API dapl_evd_post_se (
- DAT_EVD_HANDLE, /* evd_handle */
- const DAT_EVENT * ); /* event */
-
-extern DAT_RETURN DAT_API dapl_evd_dequeue (
- IN DAT_EVD_HANDLE, /* evd_handle */
- OUT DAT_EVENT * ); /* event */
-
-extern DAT_RETURN DAT_API dapl_evd_free (
- IN DAT_EVD_HANDLE );
-
-extern DAT_RETURN DAT_API
-dapl_evd_set_unwaitable (
- IN DAT_EVD_HANDLE evd_handle );
-
-extern DAT_RETURN DAT_API
-dapl_evd_clear_unwaitable (
- IN DAT_EVD_HANDLE evd_handle );
-
-/* EP functions */
-
-extern DAT_RETURN DAT_API dapl_ep_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_PZ_HANDLE, /* pz_handle */
- IN DAT_EVD_HANDLE, /* in_dto_completion_evd_handle */
- IN DAT_EVD_HANDLE, /* out_dto_completion_evd_handle */
- IN DAT_EVD_HANDLE, /* connect_evd_handle */
- IN const DAT_EP_ATTR *, /* ep_parameters */
- OUT DAT_EP_HANDLE * ); /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_query (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_EP_PARAM_MASK, /* ep_args_mask */
- OUT DAT_EP_PARAM * ); /* ep_args */
-
-extern DAT_RETURN DAT_API dapl_ep_modify (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_EP_PARAM_MASK, /* ep_args_mask */
- IN const DAT_EP_PARAM * ); /* ep_args */
-
-extern DAT_RETURN DAT_API dapl_ep_connect (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_IA_ADDRESS_PTR, /* remote_ia_address */
- IN DAT_CONN_QUAL, /* remote_conn_qual */
- IN DAT_TIMEOUT, /* timeout */
- IN DAT_COUNT, /* private_data_size */
- IN const DAT_PVOID, /* private_data */
- IN DAT_QOS, /* quality_of_service */
- IN DAT_CONNECT_FLAGS ); /* connect_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_common_connect (
- IN DAT_EP_HANDLE ep, /* ep_handle */
- IN DAT_IA_ADDRESS_PTR remote_addr, /* remote_ia_address */
- IN DAT_TIMEOUT timeout, /* timeout */
- IN DAT_COUNT pdata_size, /* private_data_size */
- IN const DAT_PVOID pdata ); /* private_data */
-
-extern DAT_RETURN DAT_API dapl_ep_dup_connect (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_EP_HANDLE, /* ep_dup_handle */
- IN DAT_TIMEOUT, /* timeout*/
- IN DAT_COUNT, /* private_data_size */
- IN const DAT_PVOID, /* private_data */
- IN DAT_QOS); /* quality_of_service */
-
-extern DAT_RETURN DAT_API dapl_ep_disconnect (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_CLOSE_FLAGS ); /* close_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_send (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* num_segments */
- IN DAT_LMR_TRIPLET *, /* local_iov */
- IN DAT_DTO_COOKIE, /* user_cookie */
- IN DAT_COMPLETION_FLAGS ); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_recv (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* num_segments */
- IN DAT_LMR_TRIPLET *, /* local_iov */
- IN DAT_DTO_COOKIE, /* user_cookie */
- IN DAT_COMPLETION_FLAGS ); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_rdma_read (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* num_segments */
- IN DAT_LMR_TRIPLET *, /* local_iov */
- IN DAT_DTO_COOKIE, /* user_cookie */
- IN const DAT_RMR_TRIPLET *, /* remote_iov */
- IN DAT_COMPLETION_FLAGS ); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_rdma_read_to_rmr (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN const DAT_RMR_TRIPLET *,/* local_iov */
- IN DAT_DTO_COOKIE, /* user_cookie */
- IN const DAT_RMR_TRIPLET *,/* remote_iov */
- IN DAT_COMPLETION_FLAGS); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_rdma_write (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* num_segments */
- IN DAT_LMR_TRIPLET *, /* local_iov */
- IN DAT_DTO_COOKIE, /* user_cookie */
- IN const DAT_RMR_TRIPLET *, /* remote_iov */
- IN DAT_COMPLETION_FLAGS ); /* completion_flags */
-
-extern DAT_RETURN DAT_API dapl_ep_post_send_with_invalidate (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* num_segments */
- IN DAT_LMR_TRIPLET *, /* local_iov */
- IN DAT_DTO_COOKIE, /* user_cookie */
- IN DAT_COMPLETION_FLAGS, /* completion_flags */
- IN DAT_BOOLEAN, /* invalidate_flag */
- IN DAT_RMR_CONTEXT); /* RMR context */
-
-extern DAT_RETURN DAT_API dapl_ep_get_status (
- IN DAT_EP_HANDLE, /* ep_handle */
- OUT DAT_EP_STATE *, /* ep_state */
- OUT DAT_BOOLEAN *, /* in_dto_idle */
- OUT DAT_BOOLEAN * ); /* out_dto_idle */
-
-extern DAT_RETURN DAT_API dapl_ep_free (
- IN DAT_EP_HANDLE); /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_reset (
- IN DAT_EP_HANDLE); /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_create_with_srq (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_PZ_HANDLE, /* pz_handle */
- IN DAT_EVD_HANDLE, /* recv_evd_handle */
- IN DAT_EVD_HANDLE, /* request_evd_handle */
- IN DAT_EVD_HANDLE, /* connect_evd_handle */
- IN DAT_SRQ_HANDLE, /* srq_handle */
- IN const DAT_EP_ATTR *, /* ep_attributes */
- OUT DAT_EP_HANDLE *); /* ep_handle */
-
-extern DAT_RETURN DAT_API dapl_ep_recv_query (
- IN DAT_EP_HANDLE, /* ep_handle */
- OUT DAT_COUNT *, /* nbufs_allocated */
- OUT DAT_COUNT *); /* bufs_alloc_span */
-
-extern DAT_RETURN DAT_API dapl_ep_set_watermark (
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_COUNT, /* soft_high_watermark */
- IN DAT_COUNT); /* hard_high_watermark */
-
-/* LMR functions */
-
-#if defined(__KERNEL__)
-extern DAT_RETURN DAT_API dapl_lmr_kcreate (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_MEM_TYPE, /* mem_type */
- IN DAT_REGION_DESCRIPTION, /* region_description */
- IN DAT_VLEN, /* length */
- IN DAT_PZ_HANDLE, /* pz_handle */
- IN DAT_MEM_PRIV_FLAGS, /* privileges */
- IN DAT_VA_TYPE, /* va_type */
- IN DAT_MEM_OPT, /* optimization */
- OUT DAT_LMR_HANDLE *, /* lmr_handle */
- OUT DAT_LMR_CONTEXT *, /* lmr_context */
- OUT DAT_RMR_CONTEXT *, /* rmr_context */
- OUT DAT_VLEN *, /* registered_length */
- OUT DAT_VADDR * ); /* registered_address */
-#else
-extern DAT_RETURN DAT_API dapl_lmr_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_MEM_TYPE, /* mem_type */
- IN DAT_REGION_DESCRIPTION, /* region_description */
- IN DAT_VLEN, /* length */
- IN DAT_PZ_HANDLE, /* pz_handle */
- IN DAT_MEM_PRIV_FLAGS, /* privileges */
- IN DAT_VA_TYPE, /* va_type */
- OUT DAT_LMR_HANDLE *, /* lmr_handle */
- OUT DAT_LMR_CONTEXT *, /* lmr_context */
- OUT DAT_RMR_CONTEXT *, /* rmr_context */
- OUT DAT_VLEN *, /* registered_length */
- OUT DAT_VADDR * ); /* registered_address */
-#endif /* defined(__KERNEL__) */
-
-extern DAT_RETURN DAT_API dapl_lmr_query (
- IN DAT_LMR_HANDLE,
- IN DAT_LMR_PARAM_MASK,
- OUT DAT_LMR_PARAM *);
-
-extern DAT_RETURN DAT_API dapl_lmr_free (
- IN DAT_LMR_HANDLE);
-
-extern DAT_RETURN DAT_API dapl_lmr_sync_rdma_read (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN const DAT_LMR_TRIPLET *, /* local_segments */
- IN DAT_VLEN); /* num_segments */
-
-extern DAT_RETURN DAT_API dapl_lmr_sync_rdma_write (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN const DAT_LMR_TRIPLET *, /* local_segments */
- IN DAT_VLEN); /* num_segments */
-
-/* RMR Functions */
-
-extern DAT_RETURN DAT_API dapl_rmr_create (
- IN DAT_PZ_HANDLE, /* pz_handle */
- OUT DAT_RMR_HANDLE *); /* rmr_handle */
-
-extern DAT_RETURN DAT_API dapl_rmr_create_for_ep (
- IN DAT_PZ_HANDLE pz_handle, /* pz_handle */
- OUT DAT_RMR_HANDLE *rmr_handle); /* rmr_handle */
-
-extern DAT_RETURN DAT_API dapl_rmr_query (
- IN DAT_RMR_HANDLE, /* rmr_handle */
- IN DAT_RMR_PARAM_MASK, /* rmr_args_mask */
- OUT DAT_RMR_PARAM *); /* rmr_args */
-
-extern DAT_RETURN DAT_API dapl_rmr_bind (
- IN DAT_RMR_HANDLE, /* rmr_handle */
- IN DAT_LMR_HANDLE, /* lmr_handle */
- IN const DAT_LMR_TRIPLET *, /* lmr_triplet */
- IN DAT_MEM_PRIV_FLAGS, /* mem_priv */
- IN DAT_VA_TYPE, /* va_type */
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_RMR_COOKIE, /* user_cookie */
- IN DAT_COMPLETION_FLAGS, /* completion_flags */
- INOUT DAT_RMR_CONTEXT * ); /* context */
-
-extern DAT_RETURN DAT_API dapl_rmr_free (
- IN DAT_RMR_HANDLE);
-
-/* PSP Functions */
-
-extern DAT_RETURN DAT_API dapl_psp_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_CONN_QUAL, /* conn_qual */
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_PSP_FLAGS, /* psp_flags */
- OUT DAT_PSP_HANDLE * ); /* psp_handle */
-
-extern DAT_RETURN DAT_API dapl_psp_create_any (
- IN DAT_IA_HANDLE, /* ia_handle */
- OUT DAT_CONN_QUAL *, /* conn_qual */
- IN DAT_EVD_HANDLE, /* evd_handle */
- IN DAT_PSP_FLAGS, /* psp_flags */
- OUT DAT_PSP_HANDLE *); /* psp_handle */
-
-extern DAT_RETURN DAT_API dapl_psp_query (
- IN DAT_PSP_HANDLE,
- IN DAT_PSP_PARAM_MASK,
- OUT DAT_PSP_PARAM * );
-
-extern DAT_RETURN DAT_API dapl_psp_free (
- IN DAT_PSP_HANDLE ); /* psp_handle */
-
-/* RSP Functions */
-
-extern DAT_RETURN DAT_API dapl_rsp_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_CONN_QUAL, /* conn_qual */
- IN DAT_EP_HANDLE, /* ep_handle */
- IN DAT_EVD_HANDLE, /* evd_handle */
- OUT DAT_RSP_HANDLE * ); /* rsp_handle */
-
-extern DAT_RETURN DAT_API dapl_rsp_query (
- IN DAT_RSP_HANDLE,
- IN DAT_RSP_PARAM_MASK,
- OUT DAT_RSP_PARAM * );
-
-extern DAT_RETURN DAT_API dapl_rsp_free (
- IN DAT_RSP_HANDLE ); /* rsp_handle */
-
-/* PZ Functions */
-
-extern DAT_RETURN DAT_API dapl_pz_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- OUT DAT_PZ_HANDLE * ); /* pz_handle */
-
-extern DAT_RETURN DAT_API dapl_pz_query (
- IN DAT_PZ_HANDLE, /* pz_handle */
- IN DAT_PZ_PARAM_MASK, /* pz_args_mask */
- OUT DAT_PZ_PARAM * ); /* pz_args */
-
-extern DAT_RETURN DAT_API dapl_pz_free (
- IN DAT_PZ_HANDLE ); /* pz_handle */
-
-/* SRQ functions */
-
-extern DAT_RETURN DAT_API dapl_srq_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_PZ_HANDLE, /* pz_handle */
- IN DAT_SRQ_ATTR *, /* srq_attr */
- OUT DAT_SRQ_HANDLE *); /* srq_handle */
-
-extern DAT_RETURN DAT_API dapl_srq_free (
- IN DAT_SRQ_HANDLE); /* srq_handle */
-
-extern DAT_RETURN DAT_API dapl_srq_post_recv (
- IN DAT_SRQ_HANDLE, /* srq_handle */
- IN DAT_COUNT, /* num_segments */
- IN DAT_LMR_TRIPLET *, /* local_iov */
- IN DAT_DTO_COOKIE); /* user_cookie */
-
-extern DAT_RETURN DAT_API dapl_srq_query (
- IN DAT_SRQ_HANDLE, /* srq_handle */
- IN DAT_SRQ_PARAM_MASK, /* srq_param_mask */
- OUT DAT_SRQ_PARAM *); /* srq_param */
-
-extern DAT_RETURN DAT_API dapl_srq_resize (
- IN DAT_SRQ_HANDLE, /* srq_handle */
- IN DAT_COUNT); /* srq_max_recv_dto */
-
-extern DAT_RETURN DAT_API dapl_srq_set_lw (
- IN DAT_SRQ_HANDLE, /* srq_handle */
- IN DAT_COUNT); /* low_watermark */
-
-/* CSP functions */
-extern DAT_RETURN DAT_API dapl_csp_create (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN DAT_COMM *, /* communicator */
- IN DAT_IA_ADDRESS_PTR, /* address */
- IN DAT_EVD_HANDLE, /* evd_handle */
- OUT DAT_CSP_HANDLE *); /* csp_handle */
-
-extern DAT_RETURN DAT_API dapl_csp_query (
- IN DAT_CSP_HANDLE, /* csp_handle */
- IN DAT_CSP_PARAM_MASK, /* csp_param_mask */
- OUT DAT_CSP_PARAM *); /* csp_param */
-
-extern DAT_RETURN DAT_API dapl_csp_free (
- IN DAT_CSP_HANDLE); /* csp_handle */
-
-/* HA functions */
-DAT_RETURN DAT_API dapl_ia_ha (
- IN DAT_IA_HANDLE, /* ia_handle */
- IN const DAT_NAME_PTR, /* provider */
- OUT DAT_BOOLEAN *); /* answer */
-
-#ifdef DAT_EXTENSIONS
-#include <stdarg.h>
-extern DAT_RETURN DAT_API dapl_extensions (
- IN DAT_HANDLE, /* handle */
- IN DAT_EXTENDED_OP, /* extended op */
- IN va_list); /* argument list */
-#endif
-
-/*
- * DAPL internal utility function prototpyes
- */
-
-extern void dapl_llist_init_head (
- DAPL_LLIST_HEAD * head);
-
-extern void dapl_llist_init_entry (
- DAPL_LLIST_ENTRY * entry);
-
-extern DAT_BOOLEAN dapl_llist_is_empty (
- DAPL_LLIST_HEAD * head);
-
-extern void dapl_llist_add_head (
- DAPL_LLIST_HEAD * head,
- DAPL_LLIST_ENTRY * entry,
- void * data);
-
-extern void dapl_llist_add_tail (
- DAPL_LLIST_HEAD * head,
- DAPL_LLIST_ENTRY * entry,
- void * data);
-
-extern void dapl_llist_add_entry (
- DAPL_LLIST_HEAD * head,
- DAPL_LLIST_ENTRY * entry,
- DAPL_LLIST_ENTRY * new_entry,
- void * data);
-
-extern void * dapl_llist_remove_head (
- DAPL_LLIST_HEAD * head);
-
-extern void * dapl_llist_remove_tail (
- DAPL_LLIST_HEAD * head);
-
-extern void * dapl_llist_remove_entry (
- DAPL_LLIST_HEAD * head,
- DAPL_LLIST_ENTRY * entry);
-
-extern void * dapl_llist_peek_head (
- DAPL_LLIST_HEAD * head);
-
-extern void * dapl_llist_next_entry (
- IN DAPL_LLIST_HEAD *head,
- IN DAPL_LLIST_ENTRY *cur_ent);
-
-extern void dapl_llist_debug_print_list (
- DAPL_LLIST_HEAD * head);
-
-
-#endif
+/*\r
+ * Copyright (c) 2002-2005, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ * in the file LICENSE.txt in the root directory. The license is also\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is in the file\r
+ * LICENSE2.txt in the root directory. The license is also available from\r
+ * the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a \r
+ * copy of which is in the file LICENSE3.txt in the root directory. The \r
+ * license is also available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ *\r
+ * MODULE: dapl.h\r
+ *\r
+ * PURPOSE: defines common data structures for the DAPL reference implemenation\r
+ *\r
+ * Description: This file describes the working data structures used within\r
+ * DAPL RI.\r
+ *\r
+ *\r
+ * $Id: dapl.h 1317 2005-04-25 17:29:42Z jlentini $\r
+ **********************************************************************/\r
+\r
+#ifndef _DAPL_H_\r
+#define _DAPL_H_\r
+\r
+#if defined(__KERNEL__)\r
+#include <dat2/kdat.h>\r
+#else\r
+#include <dat2/udat.h>\r
+#endif /* defined(__KERNEL__) */\r
+#include <dat2/dat_registry.h>\r
+#include "dapl_osd.h"\r
+#include "dapl_debug.h"\r
+\r
+\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Enumerations *\r
+ * *\r
+ *********************************************************************/\r
+\r
+typedef enum dapl_magic\r
+{\r
+ /* magic number values for verification & debug */\r
+ DAPL_MAGIC_IA = 0xCafeF00d,\r
+ DAPL_MAGIC_EVD = 0xFeedFace,\r
+ DAPL_MAGIC_EP = 0xDeadBabe,\r
+ DAPL_MAGIC_LMR = 0xBeefCafe,\r
+ DAPL_MAGIC_RMR = 0xABadCafe,\r
+ DAPL_MAGIC_PZ = 0xDeafBeef,\r
+ DAPL_MAGIC_PSP = 0xBeadeD0c,\r
+ DAPL_MAGIC_RSP = 0xFab4Feed,\r
+ DAPL_MAGIC_SRQ = 0xC001Babe,\r
+ DAPL_MAGIC_CR = 0xBe12Cee1,\r
+ DAPL_MAGIC_CR_DESTROYED = 0xB12bDead,\r
+ DAPL_MAGIC_CNO = 0xDeadF00d,\r
+ DAPL_MAGIC_INVALID = 0xFFFFFFFF\r
+} DAPL_MAGIC;\r
+\r
+typedef enum dapl_evd_state\r
+{\r
+ DAPL_EVD_STATE_TERMINAL,\r
+ DAPL_EVD_STATE_INITIAL,\r
+ DAPL_EVD_STATE_OPEN,\r
+ DAPL_EVD_STATE_WAITED,\r
+ DAPL_EVD_STATE_DEAD = 0xDEAD\r
+} DAPL_EVD_STATE;\r
+\r
+typedef enum dapl_evd_completion\r
+{\r
+ DAPL_EVD_STATE_INIT,\r
+ DAPL_EVD_STATE_SOLICITED_WAIT,\r
+ DAPL_EVD_STATE_THRESHOLD,\r
+ DAPL_EVD_STATE_UNSIGNALLED\r
+} DAPL_EVD_COMPLETION;\r
+\r
+typedef enum dapl_cno_state\r
+{\r
+ DAPL_CNO_STATE_UNTRIGGERED,\r
+ DAPL_CNO_STATE_TRIGGERED,\r
+ DAPL_CNO_STATE_DEAD = 0xDeadFeed,\r
+} DAPL_CNO_STATE;\r
+\r
+typedef enum dapl_qp_state\r
+{\r
+ DAPL_QP_STATE_UNCONNECTED,\r
+ DAPL_QP_STATE_RESERVED,\r
+ DAPL_QP_STATE_PASSIVE_CONNECTION_PENDING,\r
+ DAPL_QP_STATE_ACTIVE_CONNECTION_PENDING,\r
+ DAPL_QP_STATE_TENTATIVE_CONNECTION_PENDING,\r
+ DAPL_QP_STATE_CONNECTED,\r
+ DAPL_QP_STATE_DISCONNECT_PENDING,\r
+ DAPL_QP_STATE_ERROR,\r
+ DAPL_QP_STATE_NOT_REUSABLE,\r
+ DAPL_QP_STATE_FREE\r
+} DAPL_QP_STATE;\r
+\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Constants *\r
+ * *\r
+ *********************************************************************/\r
+\r
+/*\r
+ * number of HCAs allowed\r
+ */\r
+#define DAPL_MAX_HCA_COUNT 4\r
+\r
+/*\r
+ * Configures the RMR bind evd restriction\r
+ */\r
+\r
+#define DAPL_RMR_BIND_EVD_RESTRICTION DAT_RMR_EVD_SAME_AS_REQUEST_EVD\r
+\r
+/*\r
+ * special qp_state indicating the EP does not have a QP attached yet\r
+ */\r
+#define DAPL_QP_STATE_UNATTACHED 0xFFF0\r
+\r
+#define DAPL_MAX_PRIVATE_DATA_SIZE 256\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Macros *\r
+ * *\r
+ *********************************************************************/\r
+\r
+#if defined (sun) || defined(__sun) || defined(_sun_) || defined (__solaris__) \r
+#define DAPL_BAD_PTR(a) ((unsigned long)(a) & 3)\r
+#elif defined(__linux__)\r
+#define DAPL_BAD_PTR(a) ((unsigned long)(a) & 3)\r
+#elif defined(_WIN64)\r
+#define DAPL_BAD_PTR(a) ((unsigned long)((DAT_UINT64)(a)) & 3)\r
+#elif defined(_WIN32)\r
+#define DAPL_BAD_PTR(a) ((unsigned long)((DAT_UINT64)(a)) & 3)\r
+#endif\r
+\r
+/*\r
+ * Simple macro to verify a handle is bad. Conditions:\r
+ * - pointer is NULL\r
+ * - pointer is not word aligned\r
+ * - pointer's magic number is wrong\r
+ */\r
+\r
+#define DAPL_BAD_HANDLE(h, magicNum) ( \\r
+ ((h) == NULL) || \\r
+ DAPL_BAD_PTR(h) || \\r
+ (((DAPL_HEADER *)(h))->magic != (magicNum)))\r
+\r
+#define DAPL_MIN(a, b) ((a < b) ? (a) : (b))\r
+#define DAPL_MAX(a, b) ((a > b) ? (a) : (b))\r
+\r
+#if NDEBUG > 0\r
+#define DEBUG_IS_BAD_HANDLE(h, magicNum) (DAPL_BAD_HANDLE(h, magicNum))\r
+#else\r
+#define DEBUG_IS_BAD_HANDLE(h, magicNum) (0)\r
+#endif\r
+\r
+#define DAT_ERROR(Type, SubType) ((DAT_RETURN)(DAT_CLASS_ERROR | Type | SubType))\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Typedefs *\r
+ * *\r
+ *********************************************************************/\r
+\r
+typedef struct dapl_llist_entry DAPL_LLIST_ENTRY;\r
+typedef DAPL_LLIST_ENTRY * DAPL_LLIST_HEAD;\r
+typedef struct dapl_ring_buffer DAPL_RING_BUFFER;\r
+typedef struct dapl_cookie_buffer DAPL_COOKIE_BUFFER;\r
+\r
+typedef struct dapl_hash_table DAPL_HASH_TABLE;\r
+typedef struct dapl_hash_table * DAPL_HASH_TABLEP;\r
+typedef DAT_UINT64 DAPL_HASH_KEY;\r
+typedef void * DAPL_HASH_DATA;\r
+\r
+typedef struct dapl_hca DAPL_HCA;\r
+\r
+typedef struct dapl_header DAPL_HEADER;\r
+\r
+typedef struct dapl_ia DAPL_IA;\r
+typedef struct dapl_cno DAPL_CNO;\r
+typedef struct dapl_evd DAPL_EVD;\r
+typedef struct dapl_ep DAPL_EP;\r
+typedef struct dapl_srq DAPL_SRQ;\r
+typedef struct dapl_pz DAPL_PZ;\r
+typedef struct dapl_lmr DAPL_LMR;\r
+typedef struct dapl_rmr DAPL_RMR;\r
+typedef struct dapl_sp DAPL_SP;\r
+typedef struct dapl_cr DAPL_CR;\r
+\r
+typedef struct dapl_cookie DAPL_COOKIE;\r
+typedef struct dapl_dto_cookie DAPL_DTO_COOKIE;\r
+typedef struct dapl_rmr_cookie DAPL_RMR_COOKIE;\r
+\r
+typedef struct dapl_private DAPL_PRIVATE;\r
+\r
+\r
+\r
+/*********************************************************************\r
+ * *\r
+ * Structures *\r
+ * *\r
+ *********************************************************************/\r
+\r
+struct dapl_llist_entry\r
+{\r
+ struct dapl_llist_entry *flink;\r
+ struct dapl_llist_entry *blink;\r
+ void *data;\r
+ DAPL_LLIST_HEAD *list_head; /* for consistency checking */\r
+};\r
+\r
+struct dapl_ring_buffer\r
+{\r
+ void **base; /* base of element array */\r
+ DAT_COUNT lim; /* mask, number of entries - 1 */\r
+ DAPL_ATOMIC head; /* head pointer index */\r
+ DAPL_ATOMIC tail; /* tail pointer index */\r
+};\r
+\r
+struct dapl_cookie_buffer\r
+{\r
+ DAPL_COOKIE *pool;\r
+ DAT_COUNT pool_size;\r
+ DAPL_ATOMIC head;\r
+ DAPL_ATOMIC tail;\r
+};\r
+\r
+#ifdef IBAPI\r
+#include "dapl_ibapi_util.h"\r
+#elif VAPI\r
+#include "dapl_vapi_util.h"\r
+#elif __OPENIB__\r
+#include "dapl_openib_util.h"\r
+#include "dapl_openib_cm.h"\r
+#elif DUMMY\r
+#include "dapl_dummy_util.h"\r
+#elif OPENIB\r
+#include "dapl_ib_util.h"\r
+#else /* windows - IBAL and/or IBAL+Sock_CM */\r
+#include "dapl_ibal_util.h"\r
+#endif\r
+\r
+struct dapl_hca\r
+{\r
+ DAPL_OS_LOCK lock;\r
+ DAPL_LLIST_HEAD ia_list_head; /* list of all open IAs */\r
+ DAPL_ATOMIC handle_ref_count; /* count of ia_opens on handle */\r
+ DAPL_EVD *async_evd;\r
+ DAPL_EVD *async_error_evd;\r
+ DAT_SOCK_ADDR6 hca_address; /* local address of HCA*/\r
+ char *name; /* provider name */\r
+ ib_hca_handle_t ib_hca_handle;\r
+ unsigned long port_num; /* physical port number */\r
+ ib_hca_transport_t ib_trans; /* Values specific transport API */\r
+ /* Memory Subsystem Support */\r
+ DAPL_HASH_TABLE *lmr_hash_table;\r
+ /* Limits & useful HCA attributes */\r
+ DAT_IA_ATTR ia_attr;\r
+};\r
+\r
+/* DAPL Objects always have the following header */\r
+struct dapl_header\r
+{\r
+ DAT_PROVIDER *provider; /* required by DAT - must be first */\r
+ DAPL_MAGIC magic; /* magic number for verification */\r
+ DAT_HANDLE_TYPE handle_type; /* struct type */\r
+ DAPL_IA *owner_ia; /* ia which owns this stuct */\r
+ DAPL_LLIST_ENTRY ia_list_entry; /* link entry on ia struct */\r
+ DAT_CONTEXT user_context; /* user context - opaque to DAPL */\r
+ DAPL_OS_LOCK lock; /* lock - in header for easier macros */\r
+};\r
+\r
+/* DAPL_IA maps to DAT_IA_HANDLE */\r
+struct dapl_ia\r
+{\r
+ DAPL_HEADER header;\r
+ DAPL_HCA *hca_ptr;\r
+ DAPL_EVD *async_error_evd;\r
+ DAT_BOOLEAN cleanup_async_error_evd;\r
+\r
+ DAPL_LLIST_ENTRY hca_ia_list_entry; /* HCAs list of IAs */\r
+ DAPL_LLIST_HEAD ep_list_head; /* EP queue */\r
+ DAPL_LLIST_HEAD lmr_list_head; /* LMR queue */\r
+ DAPL_LLIST_HEAD rmr_list_head; /* RMR queue */\r
+ DAPL_LLIST_HEAD pz_list_head; /* PZ queue */\r
+ DAPL_LLIST_HEAD evd_list_head; /* EVD queue */\r
+ DAPL_LLIST_HEAD cno_list_head; /* CNO queue */\r
+ DAPL_LLIST_HEAD psp_list_head; /* PSP queue */\r
+ DAPL_LLIST_HEAD rsp_list_head; /* RSP queue */\r
+ DAPL_LLIST_HEAD srq_list_head; /* SRQ queue */\r
+#ifdef DAPL_COUNTERS\r
+ void *cntrs;\r
+#endif\r
+};\r
+\r
+/* DAPL_CNO maps to DAT_CNO_HANDLE */\r
+struct dapl_cno\r
+{\r
+ DAPL_HEADER header;\r
+\r
+ /* A CNO cannot be freed while it is referenced elsewhere. */\r
+ DAPL_ATOMIC cno_ref_count;\r
+ DAPL_CNO_STATE cno_state;\r
+\r
+ DAT_COUNT cno_waiters;\r
+ DAPL_EVD *cno_evd_triggered;\r
+#if defined(__KERNEL__)\r
+ DAT_UPCALL_OBJECT cno_upcall;\r
+ DAT_UPCALL_POLICY cno_upcall_policy;\r
+#else\r
+ DAT_OS_WAIT_PROXY_AGENT cno_wait_agent;\r
+#endif /* defined(__KERNEL__) */\r
+\r
+ DAPL_OS_WAIT_OBJECT cno_wait_object;\r
+};\r
+\r
+/* DAPL_EVD maps to DAT_EVD_HANDLE */\r
+struct dapl_evd\r
+{\r
+ DAPL_HEADER header;\r
+\r
+ DAPL_EVD_STATE evd_state;\r
+ DAT_EVD_FLAGS evd_flags;\r
+ DAT_BOOLEAN evd_enabled; /* For attached CNO. */\r
+ DAT_BOOLEAN evd_waitable; /* EVD state. */\r
+\r
+ /* Derived from evd_flags; see dapls_evd_internal_create. */\r
+ DAT_BOOLEAN evd_producer_locking_needed;\r
+\r
+ /* Every EVD has a CQ unless it is a SOFTWARE_EVENT only EVD */\r
+ ib_cq_handle_t ib_cq_handle;\r
+\r
+ /* An Event Dispatcher cannot be freed while\r
+ * it is referenced elsewhere.\r
+ */\r
+ DAPL_ATOMIC evd_ref_count;\r
+\r
+ /* Set if there has been a catastrophic overflow */\r
+ DAT_BOOLEAN catastrophic_overflow;\r
+\r
+ /* the actual events */\r
+ DAT_COUNT qlen;\r
+ DAT_EVENT *events;\r
+ DAPL_RING_BUFFER free_event_queue;\r
+ DAPL_RING_BUFFER pending_event_queue;\r
+\r
+ /* CQ Completions are not placed into 'deferred_events'\r
+ ** rather they are simply left on the Completion Queue\r
+ ** and the fact that there was a notification is flagged.\r
+ */\r
+ DAT_BOOLEAN cq_notified;\r
+ DAPL_OS_TICKS cq_notified_when;\r
+\r
+ DAT_COUNT cno_active_count;\r
+ DAPL_CNO *cno_ptr;\r
+\r
+ DAPL_OS_WAIT_OBJECT wait_object;\r
+\r
+ DAT_COUNT threshold;\r
+ DAPL_EVD_COMPLETION completion_type;\r
+\r
+#ifdef DAPL_COUNTERS\r
+ void *cntrs;\r
+#endif\r
+};\r
+\r
+/* DAPL_PRIVATE used to pass private data in a connection */\r
+struct dapl_private\r
+{\r
+#ifdef IBHOSTS_NAMING\r
+ DAT_SOCK_ADDR6 hca_address; /* local address of HCA*/\r
+#endif /* IBHOSTS_NAMING */\r
+ unsigned char private_data[DAPL_MAX_PRIVATE_DATA_SIZE];\r
+};\r
+\r
+/* uDAPL timer entry, used to queue timeouts */\r
+struct dapl_timer_entry\r
+{\r
+ DAPL_LLIST_ENTRY list_entry; /* link entry on ia struct */\r
+ DAPL_OS_TIMEVAL expires;\r
+ void (*function) (uintptr_t);\r
+ void *data;\r
+};\r
+\r
+#ifdef DAPL_DBG_IO_TRC\r
+\r
+#define DBG_IO_TRC_QLEN 32 /* length of trace buffer */\r
+#define DBG_IO_TRC_IOV 3 /* iov elements we keep track of */\r
+\r
+struct io_buf_track\r
+{\r
+ Ib_send_op_type op_type;\r
+ DAPL_COOKIE *cookie;\r
+ DAT_LMR_TRIPLET iov[DBG_IO_TRC_IOV];\r
+ DAT_RMR_TRIPLET remote_iov;\r
+ unsigned int done; /* count to track completion ordering */\r
+ int status;\r
+ void *wqe;\r
+};\r
+\r
+#endif /* DAPL_DBG_IO_TRC */\r
+\r
+/* DAPL_EP maps to DAT_EP_HANDLE */\r
+struct dapl_ep\r
+{\r
+ DAPL_HEADER header;\r
+ /* What the DAT Consumer asked for */\r
+ DAT_EP_PARAM param;\r
+\r
+ /* The RC Queue Pair (IBM OS API) */\r
+ ib_qp_handle_t qp_handle;\r
+ unsigned int qpn; /* qp number */\r
+ ib_qp_state_t qp_state;\r
+\r
+ /* communications manager handle (IBM OS API) */\r
+ dp_ib_cm_handle_t cm_handle;\r
+\r
+ /* 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
+ dp_ib_cm_handle_t ibal_cm_handle;\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) 2005-2009 Intel Corporation. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- * copy of which is available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-/*
- * Definitions specific to OpenIB CMA provider.
- * Connection manager - rdma_cma, provided in separate library.
- */
-#ifndef _DAPL_IB_UTIL_H_
-#define _DAPL_IB_UTIL_H_
-#define _OPENIB_CMA_
-
-#include <infiniband/verbs.h>
-#include <rdma/rdma_cma.h>
-#include "openib_osd.h"
-#include "dapl_ib_common.h"
-
-#define IB_RC_RETRY_COUNT 7
-#define IB_RNR_RETRY_COUNT 7
-#define IB_CM_RESPONSE_TIMEOUT 23 /* 16 sec */
-#define IB_CM_RETRIES 15 /* 240 sec total default */
-#define IB_ARP_TIMEOUT 4000 /* 4 sec */
-#define IB_ARP_RETRY_COUNT 15 /* 60 sec total */
-#define IB_ROUTE_TIMEOUT 4000 /* 4 sec */
-#define IB_ROUTE_RETRY_COUNT 15 /* 60 sec total */
-#define IB_MAX_AT_RETRY 3
-
-/* CMA private data areas */
-#define CMA_PDATA_HDR 36
-#define IB_MAX_REQ_PDATA_SIZE (92-CMA_PDATA_HDR)
-#define IB_MAX_REP_PDATA_SIZE (196-CMA_PDATA_HDR)
-#define IB_MAX_REJ_PDATA_SIZE (148-CMA_PDATA_HDR)
-#define IB_MAX_DREQ_PDATA_SIZE (220-CMA_PDATA_HDR)
-#define IB_MAX_DREP_PDATA_SIZE (224-CMA_PDATA_HDR)
-#define IWARP_MAX_PDATA_SIZE (512-CMA_PDATA_HDR)
-
-struct dapl_cm_id {
- DAPL_OS_LOCK lock;
- int destroy;
- int arp_retries;
- int arp_timeout;
- int route_retries;
- int route_timeout;
- int in_callback;
- struct rdma_cm_id *cm_id;
- struct dapl_hca *hca;
- struct dapl_sp *sp;
- struct dapl_ep *ep;
- struct rdma_conn_param params;
- DAT_SOCK_ADDR6 r_addr;
- int p_len;
- unsigned char p_data[256]; /* dapl max private data size */
- ib_qp_cm_t dst; /* dapls_modify_qp_state */
- struct ibv_ah *ah; /* dapls_modify_qp_state */
-};
-
-typedef struct dapl_cm_id *dp_ib_cm_handle_t;
-typedef struct dapl_cm_id *ib_cm_srvc_handle_t;
-
-/* ib_hca_transport_t, specific to this implementation */
-typedef struct _ib_hca_transport
-{
- struct dapl_llist_entry entry;
- int destroy;
- struct dapl_hca *d_hca;
- struct rdma_cm_id *cm_id;
- struct ibv_comp_channel *ib_cq;
- ib_cq_handle_t ib_cq_empty;
- int max_inline_send;
- ib_async_handler_t async_unafiliated;
- void *async_un_ctx;
- ib_async_cq_handler_t async_cq_error;
- ib_async_dto_handler_t async_cq;
- ib_async_qp_handler_t async_qp_error;
- uint8_t max_cm_timeout;
- uint8_t max_cm_retries;
- /* device attributes */
- int rd_atom_in;
- int rd_atom_out;
- struct ibv_device *ib_dev;
- /* dapls_modify_qp_state */
- uint16_t lid;
- uint8_t ack_timer;
- uint8_t ack_retry;
- uint8_t rnr_timer;
- uint8_t rnr_retry;
- uint8_t global;
- uint8_t hop_limit;
- uint8_t tclass;
- uint8_t mtu;
- DAT_NAMED_ATTR named_attr;
-
-} ib_hca_transport_t;
-
-/* prototypes */
-void dapli_thread(void *arg);
-DAT_RETURN dapli_ib_thread_init(void);
-void dapli_ib_thread_destroy(void);
-void dapli_cma_event_cb(void);
-void dapli_async_event_cb(struct _ib_hca_transport *hca);
-dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep);
-void dapls_ib_cm_free(dp_ib_cm_handle_t cm, DAPL_EP *ep);
-DAT_RETURN dapls_modify_qp_state(IN ib_qp_handle_t qp_handle,
- IN ib_qp_state_t qp_state,
- IN dp_ib_cm_handle_t cm);
-
-STATIC _INLINE_ void dapls_print_cm_list(IN DAPL_IA * ia_ptr)
-{
- return;
-}
-
-#endif /* _DAPL_IB_UTIL_H_ */
+/*\r
+ * Copyright (c) 2005-2009 Intel Corporation. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
+ * copy of which is available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+/* \r
+ * Definitions specific to OpenIB CMA provider.\r
+ * Connection manager - rdma_cma, provided in separate library.\r
+ */\r
+#ifndef _DAPL_IB_UTIL_H_\r
+#define _DAPL_IB_UTIL_H_\r
+#define _OPENIB_CMA_ \r
+\r
+#include <infiniband/verbs.h>\r
+#include <rdma/rdma_cma.h>\r
+#include "openib_osd.h"\r
+#include "dapl_ib_common.h"\r
+\r
+#define IB_RC_RETRY_COUNT 7\r
+#define IB_RNR_RETRY_COUNT 7\r
+#define IB_CM_RESPONSE_TIMEOUT 23 /* 16 sec */\r
+#define IB_CM_RETRIES 15 /* 240 sec total default */\r
+#define IB_ARP_TIMEOUT 4000 /* 4 sec */\r
+#define IB_ARP_RETRY_COUNT 15 /* 60 sec total */\r
+#define IB_ROUTE_TIMEOUT 4000 /* 4 sec */\r
+#define IB_ROUTE_RETRY_COUNT 15 /* 60 sec total */\r
+#define IB_MAX_AT_RETRY 3\r
+\r
+/* CMA private data areas */\r
+#define CMA_PDATA_HDR 36\r
+#define IB_MAX_REQ_PDATA_SIZE (92-CMA_PDATA_HDR)\r
+#define IB_MAX_REP_PDATA_SIZE (196-CMA_PDATA_HDR)\r
+#define IB_MAX_REJ_PDATA_SIZE (148-CMA_PDATA_HDR)\r
+#define IB_MAX_DREQ_PDATA_SIZE (220-CMA_PDATA_HDR)\r
+#define IB_MAX_DREP_PDATA_SIZE (224-CMA_PDATA_HDR)\r
+#define IWARP_MAX_PDATA_SIZE (512-CMA_PDATA_HDR)\r
+\r
+struct dapl_cm_id {\r
+ DAPL_OS_LOCK lock;\r
+ int destroy;\r
+ int arp_retries;\r
+ int arp_timeout;\r
+ int route_retries;\r
+ int route_timeout;\r
+ int in_callback;\r
+ struct rdma_cm_id *cm_id;\r
+ struct dapl_hca *hca;\r
+ struct dapl_sp *sp;\r
+ struct dapl_ep *ep;\r
+ struct rdma_conn_param params;\r
+ DAT_SOCK_ADDR6 r_addr;\r
+ int p_len;\r
+ unsigned char p_data[256]; /* dapl max private data size */\r
+ ib_qp_cm_t dst; /* dapls_modify_qp_state */\r
+ struct ibv_ah *ah; /* dapls_modify_qp_state */\r
+};\r
+\r
+typedef struct dapl_cm_id *dp_ib_cm_handle_t;\r
+typedef struct dapl_cm_id *ib_cm_srvc_handle_t;\r
+\r
+/* ib_hca_transport_t, specific to this implementation */\r
+typedef struct _ib_hca_transport\r
+{ \r
+ struct dapl_llist_entry entry;\r
+ int destroy;\r
+ struct rdma_cm_id *cm_id;\r
+ struct ibv_comp_channel *ib_cq;\r
+ ib_cq_handle_t ib_cq_empty;\r
+ int max_inline_send;\r
+ ib_async_handler_t async_unafiliated;\r
+ void *async_un_ctx;\r
+ ib_async_cq_handler_t async_cq_error;\r
+ ib_async_dto_handler_t async_cq;\r
+ ib_async_qp_handler_t async_qp_error;\r
+ uint8_t max_cm_timeout;\r
+ uint8_t max_cm_retries;\r
+ /* device attributes */\r
+ int rd_atom_in;\r
+ int rd_atom_out;\r
+ struct ibv_context *ib_ctx;\r
+ struct ibv_device *ib_dev;\r
+ /* dapls_modify_qp_state */\r
+ uint16_t lid;\r
+ uint8_t ack_timer;\r
+ uint8_t ack_retry;\r
+ uint8_t rnr_timer;\r
+ uint8_t rnr_retry;\r
+ uint8_t global;\r
+ uint8_t hop_limit;\r
+ uint8_t tclass;\r
+ uint8_t mtu;\r
+ DAT_NAMED_ATTR named_attr;\r
+\r
+} ib_hca_transport_t;\r
+\r
+/* prototypes */\r
+void dapli_thread(void *arg);\r
+DAT_RETURN dapli_ib_thread_init(void);\r
+void dapli_ib_thread_destroy(void);\r
+void dapli_cma_event_cb(void);\r
+void dapli_async_event_cb(struct _ib_hca_transport *tp);\r
+void dapli_cq_event_cb(struct _ib_hca_transport *tp);\r
+dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep);\r
+void dapls_ib_cm_free(dp_ib_cm_handle_t cm, DAPL_EP *ep);\r
+DAT_RETURN dapls_modify_qp_state(IN ib_qp_handle_t qp_handle,\r
+ IN ib_qp_state_t qp_state,\r
+ IN dp_ib_cm_handle_t cm);\r
+\r
+STATIC _INLINE_ void dapls_print_cm_list(IN DAPL_IA * ia_ptr)\r
+{\r
+ return;\r
+}\r
+\r
+#endif /* _DAPL_IB_UTIL_H_ */\r
return 0;\r
}\r
\r
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
+{\r
+ channel->comp_channel.Milliseconds = 0;\r
+ return 0;\r
+}\r
+\r
static int dapls_thread_signal(void)\r
{\r
CompManagerCancel(windata.comp_mgr);\r
return dapls_config_fd(verbs->async_fd);\r
}\r
\r
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
+{\r
+ return dapls_config_fd(channel->fd);\r
+}\r
+\r
static int dapls_thread_signal(void)\r
{\r
return write(g_ib_pipe[1], "w", sizeof "w");\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
" open_hca: RDMA channel created (%p)\n", g_cm_events);\r
\r
- dat_status = dapli_ib_thread_init();\r
- if (dat_status != DAT_SUCCESS)\r
- return dat_status;\r
-\r
/* HCA name will be hostname or IP address */\r
if (getipaddr((char *)hca_name,\r
(char *)&hca_ptr->hca_address, \r
dapl_log(DAPL_DBG_TYPE_ERR,\r
" open_hca: rdma_bind ERR %s."\r
" Is %s configured?\n", strerror(errno), hca_name);\r
+ rdma_destroy_id(cm_id);\r
return DAT_INVALID_ADDRESS;\r
}\r
\r
dapls_config_verbs(cm_id->verbs);\r
hca_ptr->port_num = cm_id->port_num;\r
hca_ptr->ib_trans.ib_dev = cm_id->verbs->device;\r
+ hca_ptr->ib_trans.ib_ctx = cm_id->verbs;\r
gid = &cm_id->route.addr.addr.ibaddr.sgid;\r
\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
(unsigned long long)ntohll(gid->global.subnet_prefix),\r
(unsigned long long)ntohll(gid->global.interface_id));\r
\r
+ /* support for EVD's with CNO's: one channel via thread */\r
+ hca_ptr->ib_trans.ib_cq =\r
+ ibv_create_comp_channel(hca_ptr->ib_hca_handle);\r
+ if (hca_ptr->ib_trans.ib_cq == NULL) {\r
+ dapl_log(DAPL_DBG_TYPE_ERR,\r
+ " open_hca: ibv_create_comp_channel ERR %s\n",\r
+ strerror(errno));\r
+ rdma_destroy_id(cm_id);\r
+ return DAT_INTERNAL_ERROR;\r
+ }\r
+ if (dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq)) {\r
+ rdma_destroy_id(cm_id);\r
+ return DAT_INTERNAL_ERROR;\r
+ }\r
+\r
/* set inline max with env or default, get local lid and gid 0 */\r
if (hca_ptr->ib_hca_handle->device->transport_type\r
== IBV_TRANSPORT_IWARP)\r
/* set default IB MTU */\r
hca_ptr->ib_trans.mtu = dapl_ib_mtu(2048);\r
\r
+ dat_status = dapli_ib_thread_init();\r
+ if (dat_status != DAT_SUCCESS)\r
+ return dat_status;\r
/* \r
* Put new hca_transport on list for async and CQ event processing \r
* Wakeup work thread to add to polling list\r
*/\r
- dapl_llist_init_entry((DAPL_LLIST_ENTRY *) & hca_ptr->ib_trans.entry);\r
+ dapl_llist_init_entry((DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry);\r
dapl_os_lock(&g_hca_lock);\r
dapl_llist_add_tail(&g_hca_list,\r
- (DAPL_LLIST_ENTRY *) & hca_ptr->ib_trans.entry,\r
+ (DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry,\r
&hca_ptr->ib_trans.entry);\r
if (dapls_thread_signal() == -1)\r
dapl_log(DAPL_DBG_TYPE_UTIL,\r
&hca_ptr->hca_address)->sin_addr.s_addr >> 24 & 0xff, \r
hca_ptr->ib_trans.max_inline_send);\r
\r
- hca_ptr->ib_trans.d_hca = hca_ptr;\r
return DAT_SUCCESS;\r
}\r
\r
" ib_thread_destroy(%d) exit\n", dapl_os_getpid());\r
}\r
\r
-void dapli_async_event_cb(struct _ib_hca_transport *hca)\r
-{\r
- struct ibv_async_event event;\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " async_event(%p)\n", hca);\r
-\r
- if (hca->destroy)\r
- return;\r
-\r
- if (!ibv_get_async_event(hca->cm_id->verbs, &event)) {\r
-\r
- switch (event.event_type) {\r
- case IBV_EVENT_CQ_ERR:\r
- {\r
- struct dapl_ep *evd_ptr =\r
- event.element.cq->cq_context;\r
-\r
- dapl_log(DAPL_DBG_TYPE_ERR,\r
- "dapl async_event CQ (%p) ERR %d\n",\r
- evd_ptr, event.event_type);\r
-\r
- /* report up if async callback still setup */\r
- if (hca->async_cq_error)\r
- hca->async_cq_error(hca->cm_id->verbs,\r
- event.element.cq,\r
- &event,\r
- (void *)evd_ptr);\r
- break;\r
- }\r
- case IBV_EVENT_COMM_EST:\r
- {\r
- /* Received msgs on connected QP before RTU */\r
- dapl_log(DAPL_DBG_TYPE_UTIL,\r
- " async_event COMM_EST(%p) rdata beat RTU\n",\r
- event.element.qp);\r
-\r
- break;\r
- }\r
- case IBV_EVENT_QP_FATAL:\r
- case IBV_EVENT_QP_REQ_ERR:\r
- case IBV_EVENT_QP_ACCESS_ERR:\r
- case IBV_EVENT_QP_LAST_WQE_REACHED:\r
- case IBV_EVENT_SRQ_ERR:\r
- case IBV_EVENT_SRQ_LIMIT_REACHED:\r
- case IBV_EVENT_SQ_DRAINED:\r
- {\r
- struct dapl_ep *ep_ptr =\r
- event.element.qp->qp_context;\r
-\r
- dapl_log(DAPL_DBG_TYPE_ERR,\r
- "dapl async_event QP (%p) ERR %d\n",\r
- ep_ptr, event.event_type);\r
-\r
- /* report up if async callback still setup */\r
- if (hca->async_qp_error)\r
- hca->async_qp_error(hca->cm_id->verbs,\r
- ep_ptr->qp_handle,\r
- &event,\r
- (void *)ep_ptr);\r
- break;\r
- }\r
- case IBV_EVENT_PATH_MIG:\r
- case IBV_EVENT_PATH_MIG_ERR:\r
- case IBV_EVENT_DEVICE_FATAL:\r
- case IBV_EVENT_PORT_ACTIVE:\r
- case IBV_EVENT_PORT_ERR:\r
- case IBV_EVENT_LID_CHANGE:\r
- case IBV_EVENT_PKEY_CHANGE:\r
- case IBV_EVENT_SM_CHANGE:\r
- {\r
- dapl_log(DAPL_DBG_TYPE_WARN,\r
- "dapl async_event: DEV ERR %d\n",\r
- event.event_type);\r
-\r
- /* report up if async callback still setup */\r
- if (hca->async_unafiliated)\r
- hca->async_unafiliated(hca->cm_id->\r
- verbs, &event,\r
- hca->\r
- async_un_ctx);\r
- break;\r
- }\r
- case IBV_EVENT_CLIENT_REREGISTER:\r
- /* no need to report this event this time */\r
- dapl_log(DAPL_DBG_TYPE_UTIL,\r
- " async_event: IBV_CLIENT_REREGISTER\n");\r
- break;\r
-\r
- default:\r
- dapl_log(DAPL_DBG_TYPE_WARN,\r
- "dapl async_event: %d UNKNOWN\n",\r
- event.event_type);\r
- break;\r
-\r
- }\r
- ibv_ack_async_event(&event);\r
- }\r
-}\r
-\r
#if defined(_WIN64) || defined(_WIN32)\r
/* work thread for uAT, uCM, CQ, and async events */\r
void dapli_thread(void *arg)\r
dapl_os_unlock(&g_hca_lock);\r
uhca[idx]->destroy = 2;\r
} else {\r
+ dapli_cq_event_cb(uhca[idx]);\r
dapli_async_event_cb(uhca[idx]);\r
}\r
}\r
dapl_os_unlock(&g_hca_lock);\r
}\r
#else // _WIN64 || WIN32\r
+\r
/* work thread for uAT, uCM, CQ, and async events */\r
void dapli_thread(void *arg)\r
{\r
while (hca) {\r
\r
/* uASYNC events */\r
- ufds[++idx].fd = hca->cm_id->verbs->async_fd;\r
+ ufds[++idx].fd = hca->ib_ctx->async_fd;\r
+ ufds[idx].events = POLLIN;\r
+ ufds[idx].revents = 0;\r
+ uhca[idx] = hca;\r
+\r
+ /* CQ events are non-direct with CNO's */\r
+ ufds[++idx].fd = hca->ib_cq->fd;\r
ufds[idx].events = POLLIN;\r
ufds[idx].revents = 0;\r
uhca[idx] = hca;\r
if (ufds[1].revents == POLLIN)\r
dapli_cma_event_cb();\r
\r
- /* check and process ASYNC events, per device */\r
+ /* check and process CQ and ASYNC events, per device */\r
for (idx = 2; idx < fds; idx++) {\r
if (ufds[idx].revents == POLLIN) {\r
+ dapli_cq_event_cb(uhca[idx]);\r
dapli_async_event_cb(uhca[idx]);\r
}\r
}\r
strerror(errno));\r
\r
/* cleanup any device on list marked for destroy */\r
- for (idx = 2; idx < fds; idx++) {\r
+ for (idx = 3; idx < fds; idx++) {\r
if (uhca[idx] && uhca[idx]->destroy == 1) {\r
dapl_os_lock(&g_hca_lock);\r
dapl_llist_remove_entry(\r
dapls_ib_cq_alloc(IN DAPL_IA * ia_ptr,\r
IN DAPL_EVD * evd_ptr, IN DAT_COUNT * cqlen)\r
{\r
- struct ibv_comp_channel *channel = evd_ptr->cq_wait_obj_handle;\r
+ struct ibv_comp_channel *channel;\r
+ DAT_RETURN ret;\r
\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
"dapls_ib_cq_alloc: evd %p cqlen=%d \n", evd_ptr, *cqlen);\r
\r
- /* Call IB verbs to create CQ */\r
+ if (!evd_ptr->cno_ptr)\r
+ channel = ibv_create_comp_channel(ia_ptr->hca_ptr->ib_hca_handle);\r
+ else\r
+ channel = ia_ptr->hca_ptr->ib_trans.ib_cq;\r
+\r
+ if (!channel)\r
+ return DAT_INSUFFICIENT_RESOURCES;\r
+\r
evd_ptr->ib_cq_handle = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle,\r
*cqlen, evd_ptr, channel, 0);\r
\r
- if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE)\r
- return DAT_INSUFFICIENT_RESOURCES;\r
+ if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE) {\r
+ ret = DAT_INSUFFICIENT_RESOURCES;\r
+ goto err;\r
+ }\r
\r
/* arm cq for events */\r
dapls_set_cq_notify(ia_ptr, evd_ptr);\r
evd_ptr->ib_cq_handle, *cqlen);\r
\r
return DAT_SUCCESS;\r
+\r
+err:\r
+ if (!evd_ptr->cno_ptr)\r
+ ibv_destroy_comp_channel(channel);\r
+ return ret;\r
}\r
\r
/*\r
- * dapl_ib_cq_resize\r
+ * dapls_ib_cq_free\r
*\r
- * Alloc a CQ\r
+ * destroy a CQ\r
*\r
* Input:\r
* ia_handle IA handle\r
* evd_ptr pointer to EVD struct\r
- * cqlen minimum QLen\r
*\r
* Output:\r
* none\r
* DAT_INVALID_PARAMETER\r
*\r
*/\r
+DAT_RETURN dapls_ib_cq_free(IN DAPL_IA * ia_ptr, IN DAPL_EVD * evd_ptr)\r
+{\r
+ DAT_EVENT event;\r
+ ib_work_completion_t wc;\r
+ struct ibv_comp_channel *channel;\r
+\r
+ if (evd_ptr->ib_cq_handle != IB_INVALID_HANDLE) {\r
+ /* pull off CQ and EVD entries and toss */\r
+ while (ibv_poll_cq(evd_ptr->ib_cq_handle, 1, &wc) == 1) ;\r
+ while (dapl_evd_dequeue(evd_ptr, &event) == DAT_SUCCESS) ;\r
+\r
+ channel = evd_ptr->ib_cq_handle->channel;\r
+ if (ibv_destroy_cq(evd_ptr->ib_cq_handle))\r
+ return (dapl_convert_errno(errno, "ibv_destroy_cq"));\r
+ if (!evd_ptr->cno_ptr)\r
+ ibv_destroy_comp_channel(channel);\r
+ evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;\r
+ }\r
+ return DAT_SUCCESS;\r
+}\r
+\r
DAT_RETURN\r
-dapls_ib_cq_resize(IN DAPL_IA * ia_ptr,\r
- IN DAPL_EVD * evd_ptr, IN DAT_COUNT * cqlen)\r
+dapls_evd_dto_wakeup(IN DAPL_EVD * evd_ptr)\r
{\r
- ib_cq_handle_t new_cq;\r
- struct ibv_comp_channel *channel = evd_ptr->cq_wait_obj_handle;\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " cq_object_wakeup: evd=%p\n", evd_ptr);\r
\r
- /* IB verbs DOES support resize. REDO THIS.\r
- * Try to re-create CQ\r
- * with new size. Can only be done if QP is not attached. \r
- * destroy EBUSY == QP still attached.\r
- */\r
+ /* no wake up mechanism */\r
+ return DAT_SUCCESS;\r
+}\r
\r
- /* Call IB verbs to create CQ */\r
- new_cq = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle, *cqlen,\r
- evd_ptr, channel, 0);\r
+#if defined(_WIN32)\r
+static int\r
+dapls_wait_comp_channel(IN struct ibv_comp_channel *channel, IN uint32_t timeout)\r
+{\r
+ channel->comp_channel.Milliseconds =\r
+ (timeout == DAT_TIMEOUT_INFINITE) ? INFINITE : timeout / 1000;\r
+ return 0;\r
+}\r
\r
- if (new_cq == IB_INVALID_HANDLE)\r
- return DAT_INSUFFICIENT_RESOURCES;\r
+#else // WIN32\r
+\r
+static int\r
+dapls_wait_comp_channel(IN struct ibv_comp_channel *channel, IN uint32_t timeout)\r
+{\r
+ int status, timeout_ms;\r
+ struct pollfd cq_fd = {\r
+ .fd = channel->fd,\r
+ .events = POLLIN,\r
+ .revents = 0\r
+ };\r
+\r
+ /* uDAPL timeout values in usecs */\r
+ timeout_ms = (timeout == DAT_TIMEOUT_INFINITE) ? -1 : timeout / 1000;\r
+ status = poll(&cq_fd, 1, timeout_ms);\r
+ if (status > 0)\r
+ return 0;\r
+ else if (status == 0)\r
+ return ETIMEDOUT;\r
+ else\r
+ return status;\r
+}\r
+#endif\r
\r
- /* destroy the original and replace if successful */\r
- if (ibv_destroy_cq(evd_ptr->ib_cq_handle)) {\r
- ibv_destroy_cq(new_cq);\r
- return (dapl_convert_errno(errno, "resize_cq"));\r
+DAT_RETURN\r
+dapls_evd_dto_wait(IN DAPL_EVD * evd_ptr, IN uint32_t timeout)\r
+{\r
+ struct ibv_comp_channel *channel = evd_ptr->ib_cq_handle->channel;\r
+ struct ibv_cq *ibv_cq = NULL;\r
+ void *context;\r
+ int status;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " cq_object_wait: EVD %p time %d\n",\r
+ evd_ptr, timeout);\r
+\r
+ status = dapls_wait_comp_channel(channel, timeout);\r
+ if (!status) {\r
+ if (!ibv_get_cq_event(channel, &ibv_cq, &context)) {\r
+ ibv_ack_cq_events(ibv_cq, 1);\r
+ }\r
}\r
\r
- /* update EVD with new cq handle and size */\r
- evd_ptr->ib_cq_handle = new_cq;\r
- *cqlen = new_cq->cqe;\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " cq_object_wait: RET evd %p ibv_cq %p %s\n",\r
+ evd_ptr, ibv_cq, strerror(errno));\r
\r
- /* arm cq for events */\r
- dapls_set_cq_notify(ia_ptr, evd_ptr);\r
+ return dapl_convert_errno(status, "cq_wait_object_wait");\r
+}\r
\r
- return DAT_SUCCESS;\r
+void dapli_cq_event_cb(struct _ib_hca_transport *tp)\r
+{\r
+ /* check all comp events on this device */\r
+ struct dapl_evd *evd = NULL;\r
+ struct ibv_cq *ibv_cq = NULL;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL," dapli_cq_event_cb(%p)\n", tp);\r
+\r
+ while (!ibv_get_cq_event(tp->ib_cq, &ibv_cq, (void*)&evd)) {\r
+\r
+ if (!DAPL_BAD_HANDLE(evd, DAPL_MAGIC_EVD)) {\r
+ /* Both EVD or EVD->CNO event via callback */\r
+ dapl_evd_dto_callback(tp->ib_ctx, \r
+ evd->ib_cq_handle, (void*)evd);\r
+ }\r
+\r
+ ibv_ack_cq_events(ibv_cq, 1);\r
+ } \r
}\r
\r
/*\r
- * dapls_ib_cq_free\r
+ * dapl_ib_cq_resize\r
*\r
- * destroy a CQ\r
+ * Alloc a CQ\r
*\r
* Input:\r
* ia_handle IA handle\r
* evd_ptr pointer to EVD struct\r
+ * cqlen minimum QLen\r
*\r
* Output:\r
* none\r
* DAT_INVALID_PARAMETER\r
*\r
*/\r
-DAT_RETURN dapls_ib_cq_free(IN DAPL_IA * ia_ptr, IN DAPL_EVD * evd_ptr)\r
+DAT_RETURN\r
+dapls_ib_cq_resize(IN DAPL_IA * ia_ptr,\r
+ IN DAPL_EVD * evd_ptr, IN DAT_COUNT * cqlen)\r
{\r
- DAT_EVENT event;\r
- ib_work_completion_t wc;\r
+ ib_cq_handle_t old_cq, new_cq;\r
+ DAT_RETURN ret;\r
\r
- if (evd_ptr->ib_cq_handle != IB_INVALID_HANDLE) {\r
- /* pull off CQ and EVD entries and toss */\r
- while (ibv_poll_cq(evd_ptr->ib_cq_handle, 1, &wc) == 1) ;\r
- while (dapl_evd_dequeue(evd_ptr, &event) == DAT_SUCCESS) ;\r
- if (ibv_destroy_cq(evd_ptr->ib_cq_handle))\r
- return (dapl_convert_errno(errno, "ibv_destroy_cq"));\r
- evd_ptr->ib_cq_handle = IB_INVALID_HANDLE;\r
- }\r
+ old_cq = evd_ptr->ib_cq_handle;\r
+ ret = dapls_ib_cq_alloc(ia_ptr, evd_ptr, cqlen);\r
+ if (ret)\r
+ goto err;\r
+\r
+ new_cq = evd_ptr->ib_cq_handle;\r
+ evd_ptr->ib_cq_handle = old_cq;\r
+ dapls_ib_cq_free(ia_ptr, evd_ptr);\r
+ evd_ptr->ib_cq_handle = new_cq;\r
return DAT_SUCCESS;\r
+\r
+err:\r
+ evd_ptr->ib_cq_handle = old_cq;\r
+ return ret;\r
}\r
\r
/*\r
return DAT_QUEUE_EMPTY;\r
}\r
\r
-/* NEW common wait objects for providers with direct CQ wait objects */\r
-DAT_RETURN\r
-dapls_ib_wait_object_create(IN DAPL_EVD * evd_ptr,\r
- IN ib_wait_obj_handle_t * p_cq_wait_obj_handle)\r
-{\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_create: (%p,%p)\n",\r
- evd_ptr, p_cq_wait_obj_handle);\r
-\r
- /* set cq_wait object to evd_ptr */\r
- *p_cq_wait_obj_handle =\r
- ibv_create_comp_channel(evd_ptr->header.owner_ia->hca_ptr->\r
- ib_hca_handle);\r
-\r
- return DAT_SUCCESS;\r
-}\r
-\r
-DAT_RETURN\r
-dapls_ib_wait_object_destroy(IN ib_wait_obj_handle_t p_cq_wait_obj_handle)\r
-{\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_destroy: wait_obj=%p\n", p_cq_wait_obj_handle);\r
-\r
- ibv_destroy_comp_channel(p_cq_wait_obj_handle);\r
-\r
- return DAT_SUCCESS;\r
-}\r
-\r
-DAT_RETURN\r
-dapls_ib_wait_object_wakeup(IN ib_wait_obj_handle_t p_cq_wait_obj_handle)\r
-{\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_wakeup: wait_obj=%p\n", p_cq_wait_obj_handle);\r
-\r
- /* no wake up mechanism */\r
- return DAT_SUCCESS;\r
-}\r
-\r
-#if defined(_WIN32) || defined(_WIN64)\r
-DAT_RETURN\r
-dapls_ib_wait_object_wait(IN ib_wait_obj_handle_t p_cq_wait_obj_handle,\r
- IN uint32_t timeout)\r
-{\r
- struct dapl_evd *evd_ptr;\r
- struct ibv_cq *ibv_cq = NULL;\r
- int status = 0;\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_wait: CQ channel %p time %d\n",\r
- p_cq_wait_obj_handle, timeout);\r
-\r
- /* uDAPL timeout values in usecs */\r
- p_cq_wait_obj_handle->comp_channel.Milliseconds = timeout / 1000;\r
-\r
- /* returned event */\r
- status = ibv_get_cq_event(p_cq_wait_obj_handle, &ibv_cq,\r
- (void *)&evd_ptr);\r
- if (status == 0) {\r
- ibv_ack_cq_events(ibv_cq, 1);\r
- }\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_wait: RET evd %p ibv_cq %p %s\n",\r
- evd_ptr, ibv_cq, strerror(errno));\r
-\r
- return (dapl_convert_errno(status, "cq_wait_object_wait"));\r
-}\r
-#else //_WIN32 || _WIN64\r
-DAT_RETURN\r
-dapls_ib_wait_object_wait(IN ib_wait_obj_handle_t p_cq_wait_obj_handle,\r
- IN uint32_t timeout)\r
-{\r
- struct dapl_evd *evd_ptr;\r
- struct ibv_cq *ibv_cq = NULL;\r
- int status = 0;\r
- int timeout_ms = -1;\r
- struct pollfd cq_fd = {\r
- .fd = p_cq_wait_obj_handle->fd,\r
- .events = POLLIN,\r
- .revents = 0\r
- };\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_wait: CQ channel %p time %d\n",\r
- p_cq_wait_obj_handle, timeout);\r
-\r
- /* uDAPL timeout values in usecs */\r
- if (timeout != DAT_TIMEOUT_INFINITE)\r
- timeout_ms = timeout / 1000;\r
-\r
- status = poll(&cq_fd, 1, timeout_ms);\r
-\r
- /* returned event */\r
- if (status > 0) {\r
- if (!ibv_get_cq_event(p_cq_wait_obj_handle,\r
- &ibv_cq, (void *)&evd_ptr)) {\r
- ibv_ack_cq_events(ibv_cq, 1);\r
- }\r
- status = 0;\r
-\r
- /* timeout */\r
- } else if (status == 0)\r
- status = ETIMEDOUT;\r
-\r
- dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
- " cq_object_wait: RET evd %p ibv_cq %p %s\n",\r
- evd_ptr, ibv_cq, strerror(errno));\r
-\r
- return (dapl_convert_errno(status, "cq_wait_object_wait"));\r
-\r
-}\r
-#endif //_WIN32 || _WIN64\r
-\r
/*\r
* Local variables:\r
* c-indent-level: 4\r
typedef union ibv_gid GID;\r
typedef char *IB_HCA_NAME;\r
typedef uint16_t ib_hca_port_t;\r
-typedef uint32_t ib_comp_handle_t;\r
-\r
-typedef struct ibv_comp_channel *ib_wait_obj_handle_t;\r
\r
/* Definitions */\r
#define IB_INVALID_HANDLE NULL\r
/* prototypes */\r
int32_t dapls_ib_init(void);\r
int32_t dapls_ib_release(void);\r
+\r
+/* util.c */\r
enum ibv_mtu dapl_ib_mtu(int mtu);\r
char *dapl_ib_mtu_str(enum ibv_mtu mtu);\r
DAT_RETURN getlocalipaddr(DAT_SOCK_ADDR *addr, int addr_len);\r
else if (!ia_ptr->hca_ptr->ib_trans.ib_cq_empty)\r
rcv_cq = ia_ptr->hca_ptr->ib_trans.ib_cq_empty;\r
else {\r
- struct ibv_comp_channel *channel = \r
- rcv_evd->cq_wait_obj_handle;\r
+ struct ibv_comp_channel *channel;\r
+\r
+ channel = ibv_create_comp_channel(ia_ptr->hca_ptr->ib_hca_handle);\r
+ if (!channel)\r
+ return (dapl_convert_errno(ENOMEM, "create_cq"));\r
\r
/* Call IB verbs to create CQ */\r
rcv_cq = ibv_create_cq(ia_ptr->hca_ptr->ib_hca_handle,\r
0, NULL, channel, 0);\r
\r
- if (rcv_cq == IB_INVALID_HANDLE)\r
+ if (rcv_cq == IB_INVALID_HANDLE) {\r
+ ibv_destroy_comp_channel(channel);\r
return (dapl_convert_errno(ENOMEM, "create_cq"));\r
+ }\r
\r
ia_ptr->hca_ptr->ib_trans.ib_cq_empty = rcv_cq;\r
}\r
return DAT_SUCCESS;\r
}\r
\r
+void dapli_async_event_cb(struct _ib_hca_transport *hca)\r
+{\r
+ struct ibv_async_event event;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " async_event(%p)\n", hca);\r
+\r
+ if (hca->destroy)\r
+ return;\r
+\r
+ if (!ibv_get_async_event(hca->ib_ctx, &event)) {\r
+\r
+ switch (event.event_type) {\r
+ case IBV_EVENT_CQ_ERR:\r
+ {\r
+ struct dapl_ep *evd_ptr =\r
+ event.element.cq->cq_context;\r
+\r
+ dapl_log(DAPL_DBG_TYPE_ERR,\r
+ "dapl async_event CQ (%p) ERR %d\n",\r
+ evd_ptr, event.event_type);\r
+\r
+ /* report up if async callback still setup */\r
+ if (hca->async_cq_error)\r
+ hca->async_cq_error(hca->ib_ctx,\r
+ event.element.cq,\r
+ &event,\r
+ (void *)evd_ptr);\r
+ break;\r
+ }\r
+ case IBV_EVENT_COMM_EST:\r
+ {\r
+ /* Received msgs on connected QP before RTU */\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " async_event COMM_EST(%p) rdata beat RTU\n",\r
+ event.element.qp);\r
+\r
+ break;\r
+ }\r
+ case IBV_EVENT_QP_FATAL:\r
+ case IBV_EVENT_QP_REQ_ERR:\r
+ case IBV_EVENT_QP_ACCESS_ERR:\r
+ case IBV_EVENT_QP_LAST_WQE_REACHED:\r
+ case IBV_EVENT_SRQ_ERR:\r
+ case IBV_EVENT_SRQ_LIMIT_REACHED:\r
+ case IBV_EVENT_SQ_DRAINED:\r
+ {\r
+ struct dapl_ep *ep_ptr =\r
+ event.element.qp->qp_context;\r
+\r
+ dapl_log(DAPL_DBG_TYPE_ERR,\r
+ "dapl async_event QP (%p) ERR %d\n",\r
+ ep_ptr, event.event_type);\r
+\r
+ /* report up if async callback still setup */\r
+ if (hca->async_qp_error)\r
+ hca->async_qp_error(hca->ib_ctx,\r
+ ep_ptr->qp_handle,\r
+ &event,\r
+ (void *)ep_ptr);\r
+ break;\r
+ }\r
+ case IBV_EVENT_PATH_MIG:\r
+ case IBV_EVENT_PATH_MIG_ERR:\r
+ case IBV_EVENT_DEVICE_FATAL:\r
+ case IBV_EVENT_PORT_ACTIVE:\r
+ case IBV_EVENT_PORT_ERR:\r
+ case IBV_EVENT_LID_CHANGE:\r
+ case IBV_EVENT_PKEY_CHANGE:\r
+ case IBV_EVENT_SM_CHANGE:\r
+ {\r
+ dapl_log(DAPL_DBG_TYPE_WARN,\r
+ "dapl async_event: DEV ERR %d\n",\r
+ event.event_type);\r
+\r
+ /* report up if async callback still setup */\r
+ if (hca->async_unafiliated)\r
+ hca->async_unafiliated(hca->ib_ctx, \r
+ &event, \r
+ hca->async_un_ctx);\r
+ break;\r
+ }\r
+ case IBV_EVENT_CLIENT_REREGISTER:\r
+ /* no need to report this event this time */\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " async_event: IBV_CLIENT_REREGISTER\n");\r
+ break;\r
+\r
+ default:\r
+ dapl_log(DAPL_DBG_TYPE_WARN,\r
+ "dapl async_event: %d UNKNOWN\n",\r
+ event.event_type);\r
+ break;\r
+\r
+ }\r
+ ibv_ack_async_event(&event);\r
+ }\r
+}\r
+\r
/*\r
* dapls_set_provider_specific_attr\r
*\r
/* ib_hca_transport_t, specific to this implementation */\r
typedef struct _ib_hca_transport\r
{ \r
+ struct dapl_llist_entry entry;\r
+ int destroy;\r
union ibv_gid gid;\r
struct ibv_device *ib_dev;\r
+ struct ibv_context *ib_ctx;\r
ib_cq_handle_t ib_cq_empty;\r
DAPL_OS_LOCK cq_lock; \r
int max_inline_send;\r
void cr_thread(void *arg);\r
int dapli_cq_thread_init(struct dapl_hca *hca_ptr);\r
void dapli_cq_thread_destroy(struct dapl_hca *hca_ptr);\r
+void dapli_async_event_cb(struct _ib_hca_transport *tp);\r
+void dapli_cq_event_cb(struct _ib_hca_transport *tp);\r
DAT_RETURN dapli_socket_disconnect(dp_ib_cm_handle_t cm_ptr);\r
void dapls_print_cm_list(IN DAPL_IA *ia_ptr);\r
dp_ib_cm_handle_t dapls_ib_cm_create(DAPL_EP *ep);\r
\r
#include <stdlib.h>\r
\r
+ib_thread_state_t g_ib_thread_state = 0;\r
+DAPL_OS_THREAD g_ib_thread;\r
+DAPL_OS_LOCK g_hca_lock;\r
+struct dapl_llist_entry *g_hca_list;\r
+\r
+void dapli_thread(void *arg);\r
+DAT_RETURN dapli_ib_thread_init(void);\r
+void dapli_ib_thread_destroy(void);\r
+\r
+#if defined(_WIN64) || defined(_WIN32)\r
+#include "..\..\..\..\..\etc\user\comp_channel.cpp"\r
+#include <rdma\winverbs.h>\r
+\r
+struct ibvw_windata windata;\r
+\r
+static int dapls_os_init(void)\r
+{\r
+ return ibvw_get_windata(&windata, IBVW_WINDATA_VERSION);\r
+}\r
+\r
+static void dapls_os_release(void)\r
+{\r
+ if (windata.comp_mgr)\r
+ ibvw_release_windata(&windata, IBVW_WINDATA_VERSION);\r
+ windata.comp_mgr = NULL;\r
+}\r
+\r
+static int dapls_config_verbs(struct ibv_context *verbs)\r
+{\r
+ verbs->channel.Milliseconds = 0;\r
+ return 0;\r
+}\r
+\r
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
+{\r
+ channel->comp_channel.Milliseconds = 0;\r
+ return 0;\r
+}\r
+\r
+static int dapls_thread_signal(void)\r
+{\r
+ CompManagerCancel(windata.comp_mgr);\r
+ return 0;\r
+}\r
+#else // _WIN64 || WIN32\r
+int g_ib_pipe[2];\r
+\r
+static int dapls_os_init(void)\r
+{\r
+ /* create pipe for waking up work thread */\r
+ return pipe(g_ib_pipe);\r
+}\r
+\r
+static void dapls_os_release(void)\r
+{\r
+ /* close pipe? */\r
+}\r
+\r
+static int dapls_config_fd(int fd)\r
+{\r
+ int opts;\r
+\r
+ opts = fcntl(fd, F_GETFL);\r
+ if (opts < 0 || fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0) {\r
+ dapl_log(DAPL_DBG_TYPE_ERR,\r
+ " dapls_config_fd: fcntl on fd %d ERR %d %s\n",\r
+ fd, opts, strerror(errno));\r
+ return errno;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+static int dapls_config_verbs(struct ibv_context *verbs)\r
+{\r
+ return dapls_config_fd(verbs->async_fd);\r
+}\r
+\r
+static int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
+{\r
+ return dapls_config_fd(channel->fd);\r
+}\r
+\r
+static int dapls_thread_signal(void)\r
+{\r
+ return write(g_ib_pipe[1], "w", sizeof "w");\r
+}\r
+#endif\r
+\r
+\r
static int32_t create_cr_pipe(IN DAPL_HCA * hca_ptr)\r
{\r
DAPL_SOCKET listen_socket;\r
*/\r
int32_t dapls_ib_init(void)\r
{\r
- return 0;\r
-}\r
+ /* initialize hca_list */\r
+ dapl_os_lock_init(&g_hca_lock);\r
+ dapl_llist_init_head(&g_hca_list);\r
\r
-int32_t dapls_ib_release(void)\r
-{\r
- return 0;\r
-}\r
+ if (dapls_os_init())\r
+ return 1;\r
\r
-#if defined(_WIN64) || defined(_WIN32)\r
-int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
-{\r
return 0;\r
}\r
-#else // _WIN64 || WIN32\r
-int dapls_config_comp_channel(struct ibv_comp_channel *channel)\r
-{\r
- int opts;\r
-\r
- opts = fcntl(channel->fd, F_GETFL); /* uCQ */\r
- if (opts < 0 || fcntl(channel->fd, F_SETFL, opts | O_NONBLOCK) < 0) {\r
- dapl_log(DAPL_DBG_TYPE_ERR,\r
- " dapls_create_comp_channel: fcntl on ib_cq->fd %d ERR %d %s\n",\r
- channel->fd, opts, strerror(errno));\r
- return errno;\r
- }\r
\r
+int32_t dapls_ib_release(void)\r
+{\r
+ dapli_ib_thread_destroy();\r
+ dapls_os_release();\r
return 0;\r
}\r
-#endif\r
\r
/*\r
* dapls_ib_open_hca\r
" open_hca: device %s not found\n", hca_name);\r
goto err;\r
\r
- found:\r
+found:\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " open_hca: Found dev %s %016llx\n",\r
ibv_get_device_name(hca_ptr->ib_trans.ib_dev),\r
(unsigned long long)\r
strerror(errno));\r
goto err;\r
}\r
+ hca_ptr->ib_trans.ib_ctx = hca_ptr->ib_hca_handle;\r
+ dapls_config_verbs(hca_ptr->ib_hca_handle);\r
\r
/* get lid for this hca-port, network order */\r
if (ibv_query_port(hca_ptr->ib_hca_handle,\r
hca_ptr->ib_trans.mtu =\r
dapl_ib_mtu(dapl_os_get_env_val("DAPL_IB_MTU", SCM_IB_MTU));\r
\r
-#ifndef CQ_WAIT_OBJECT\r
- /* initialize cq_lock */\r
- dat_status = dapl_os_lock_init(&hca_ptr->ib_trans.cq_lock);\r
- if (dat_status != DAT_SUCCESS) {\r
- dapl_log(DAPL_DBG_TYPE_ERR,\r
- " open_hca: failed to init cq_lock\n");\r
- goto bail;\r
- }\r
- /* EVD events without direct CQ channels, non-blocking */\r
+\r
+ /* EVD events without direct CQ channels, CNO support */\r
hca_ptr->ib_trans.ib_cq =\r
ibv_create_comp_channel(hca_ptr->ib_hca_handle);\r
if (hca_ptr->ib_trans.ib_cq == NULL) {\r
strerror(errno));\r
goto bail;\r
}\r
-\r
- if (dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq)) {\r
- goto bail;\r
- }\r
-\r
- if (dapli_cq_thread_init(hca_ptr)) {\r
+ dapls_config_comp_channel(hca_ptr->ib_trans.ib_cq);\r
+ \r
+ dat_status = dapli_ib_thread_init();\r
+ if (dat_status != DAT_SUCCESS) {\r
dapl_log(DAPL_DBG_TYPE_ERR,\r
- " open_hca: cq_thread_init failed for %s\n",\r
- ibv_get_device_name(hca_ptr->ib_trans.ib_dev));\r
+ " open_hca: failed to init cq thread lock\n");\r
goto bail;\r
}\r
-#endif /* CQ_WAIT_OBJECT */\r
+ /* \r
+ * Put new hca_transport on list for async and CQ event processing \r
+ * Wakeup work thread to add to polling list\r
+ */\r
+ dapl_llist_init_entry((DAPL_LLIST_ENTRY *)&hca_ptr->ib_trans.entry);\r
+ dapl_os_lock(&g_hca_lock);\r
+ dapl_llist_add_tail(&g_hca_list,\r
+ (DAPL_LLIST_ENTRY *) &hca_ptr->ib_trans.entry,\r
+ &hca_ptr->ib_trans.entry);\r
+ if (dapls_thread_signal() == -1)\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " open_hca: thread wakeup error = %s\n",\r
+ strerror(errno));\r
+ dapl_os_unlock(&g_hca_lock);\r
\r
/* initialize cr_list lock */\r
dat_status = dapl_os_lock_init(&hca_ptr->ib_trans.lock);\r
\r
/* wait for thread */\r
while (hca_ptr->ib_trans.cr_state != IB_THREAD_RUN) {\r
- dapl_os_sleep_usec(2000);\r
+ dapl_os_sleep_usec(1000);\r
}\r
\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
{\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " close_hca: %p\n", hca_ptr);\r
\r
-#ifndef CQ_WAIT_OBJECT\r
- dapli_cq_thread_destroy(hca_ptr);\r
- dapl_os_lock_destroy(&hca_ptr->ib_trans.cq_lock);\r
-#endif /* CQ_WAIT_OBJECT */\r
-\r
if (hca_ptr->ib_hca_handle != IB_INVALID_HANDLE) {\r
if (ibv_close_device(hca_ptr->ib_hca_handle))\r
return (dapl_convert_errno(errno, "ib_close_device"));\r
hca_ptr->ib_hca_handle = IB_INVALID_HANDLE;\r
}\r
\r
+ dapl_os_lock(&g_hca_lock);\r
+ if (g_ib_thread_state != IB_THREAD_RUN) {\r
+ dapl_os_unlock(&g_hca_lock);\r
+ return (DAT_SUCCESS);\r
+ }\r
+ dapl_os_unlock(&g_hca_lock);\r
+\r
/* destroy cr_thread and lock */\r
hca_ptr->ib_trans.cr_state = IB_THREAD_CANCEL;\r
- if (send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0) == -1)\r
- dapl_log(DAPL_DBG_TYPE_UTIL,\r
- " thread_destroy: thread wakeup err = %s\n",\r
- strerror(errno));\r
+ send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);\r
while (hca_ptr->ib_trans.cr_state != IB_THREAD_EXIT) {\r
dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
" close_hca: waiting for cr_thread\n");\r
- if (send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0) == -1)\r
- dapl_log(DAPL_DBG_TYPE_UTIL,\r
- " thread_destroy: thread wakeup err = %s\n",\r
- strerror(errno));\r
- dapl_os_sleep_usec(2000);\r
+ send(hca_ptr->ib_trans.scm[1], "w", sizeof "w", 0);\r
+ dapl_os_sleep_usec(1000);\r
}\r
dapl_os_lock_destroy(&hca_ptr->ib_trans.lock);\r
destroy_cr_pipe(hca_ptr); /* no longer need pipe */\r
+ \r
+ /* \r
+ * Remove hca from async event processing list\r
+ * Wakeup work thread to remove from polling list\r
+ */\r
+ hca_ptr->ib_trans.destroy = 1;\r
+ if (dapls_thread_signal() == -1)\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " destroy: thread wakeup error = %s\n",\r
+ strerror(errno));\r
+\r
+ /* wait for thread to remove HCA references */\r
+ while (hca_ptr->ib_trans.destroy != 2) {\r
+ if (dapls_thread_signal() == -1)\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " destroy: thread wakeup error = %s\n",\r
+ strerror(errno));\r
+ dapl_os_sleep_usec(1000);\r
+ }\r
+\r
return (DAT_SUCCESS);\r
}\r
+\r
+DAT_RETURN dapli_ib_thread_init(void)\r
+{\r
+ DAT_RETURN dat_status;\r
+\r
+ dapl_os_lock(&g_hca_lock);\r
+ if (g_ib_thread_state != IB_THREAD_INIT) {\r
+ dapl_os_unlock(&g_hca_lock);\r
+ return DAT_SUCCESS;\r
+ }\r
+\r
+ g_ib_thread_state = IB_THREAD_CREATE;\r
+ dapl_os_unlock(&g_hca_lock);\r
+\r
+ /* create thread to process inbound connect request */\r
+ dat_status = dapl_os_thread_create(dapli_thread, NULL, &g_ib_thread);\r
+ if (dat_status != DAT_SUCCESS)\r
+ return (dapl_convert_errno(errno,\r
+ "create_thread ERR:"\r
+ " check resource limits"));\r
+\r
+ /* wait for thread to start */\r
+ dapl_os_lock(&g_hca_lock);\r
+ while (g_ib_thread_state != IB_THREAD_RUN) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " ib_thread_init: waiting for ib_thread\n");\r
+ dapl_os_unlock(&g_hca_lock);\r
+ dapl_os_sleep_usec(1000);\r
+ dapl_os_lock(&g_hca_lock);\r
+ }\r
+ dapl_os_unlock(&g_hca_lock);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+void dapli_ib_thread_destroy(void)\r
+{\r
+ int retries = 10;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " ib_thread_destroy(%d)\n", dapl_os_getpid());\r
+ /* \r
+ * wait for async thread to terminate. \r
+ * pthread_join would be the correct method\r
+ * but some applications have some issues\r
+ */\r
+\r
+ /* destroy ib_thread, wait for termination, if not already */\r
+ dapl_os_lock(&g_hca_lock);\r
+ if (g_ib_thread_state != IB_THREAD_RUN)\r
+ goto bail;\r
+\r
+ g_ib_thread_state = IB_THREAD_CANCEL;\r
+ if (dapls_thread_signal() == -1)\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " destroy: thread wakeup error = %s\n",\r
+ strerror(errno));\r
+ while ((g_ib_thread_state != IB_THREAD_EXIT) && (retries--)) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " ib_thread_destroy: waiting for ib_thread\n");\r
+ if (dapls_thread_signal() == -1)\r
+ dapl_log(DAPL_DBG_TYPE_UTIL,\r
+ " destroy: thread wakeup error = %s\n",\r
+ strerror(errno));\r
+ dapl_os_unlock(&g_hca_lock);\r
+ dapl_os_sleep_usec(2000);\r
+ dapl_os_lock(&g_hca_lock);\r
+ }\r
+bail:\r
+ dapl_os_unlock(&g_hca_lock);\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " ib_thread_destroy(%d) exit\n", dapl_os_getpid());\r
+}\r
+\r
+\r
+#if defined(_WIN64) || defined(_WIN32)\r
+/* work thread for uAT, uCM, CQ, and async events */\r
+void dapli_thread(void *arg)\r
+{\r
+ struct _ib_hca_transport *hca;\r
+ struct _ib_hca_transport *uhca[8];\r
+ COMP_CHANNEL *channel;\r
+ int ret, idx, cnt;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d,0x%x): ENTER: \n",\r
+ dapl_os_getpid(), g_ib_thread);\r
+\r
+ dapl_os_lock(&g_hca_lock);\r
+ for (g_ib_thread_state = IB_THREAD_RUN;\r
+ g_ib_thread_state == IB_THREAD_RUN; \r
+ dapl_os_lock(&g_hca_lock)) {\r
+\r
+ idx = 0;\r
+ hca = dapl_llist_is_empty(&g_hca_list) ? NULL :\r
+ dapl_llist_peek_head(&g_hca_list);\r
+\r
+ while (hca) {\r
+ uhca[idx++] = hca;\r
+ hca = dapl_llist_next_entry(&g_hca_list,\r
+ (DAPL_LLIST_ENTRY *)\r
+ &hca->entry);\r
+ }\r
+ cnt = idx;\r
+\r
+ dapl_os_unlock(&g_hca_lock);\r
+ ret = CompManagerPoll(windata.comp_mgr, INFINITE, &channel);\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL,\r
+ " ib_thread(%d) poll_event 0x%x\n",\r
+ dapl_os_getpid(), ret);\r
+\r
+\r
+ /* check and process ASYNC events, per device */\r
+ for (idx = 0; idx < cnt; idx++) {\r
+ if (uhca[idx]->destroy == 1) {\r
+ dapl_os_lock(&g_hca_lock);\r
+ dapl_llist_remove_entry(&g_hca_list,\r
+ (DAPL_LLIST_ENTRY *)\r
+ &uhca[idx]->entry);\r
+ dapl_os_unlock(&g_hca_lock);\r
+ uhca[idx]->destroy = 2;\r
+ } else {\r
+ dapli_cq_event_cb(uhca[idx]);\r
+ dapli_async_event_cb(uhca[idx]);\r
+ }\r
+ }\r
+ }\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_UTIL, " ib_thread(%d) EXIT\n",\r
+ dapl_os_getpid());\r
+ g_ib_thread_state = IB_THREAD_EXIT;\r
+ dapl_os_unlock(&g_hca_lock);\r
+}\r
+#else // _WIN64 || WIN32\r
+\r
+/* work thread for uAT, uCM, CQ, and async events */\r
+void dapli_thread(void *arg)\r
+{\r
+ struct pollfd ufds[__FD_SETSIZE];\r
+ struct _ib_hca_transport *uhca[__FD_SETSIZE] = { NULL };\r
+ struct _ib_hca_transport *hca;\r
+ int ret, idx, fds;\r
+ char rbuf[2];\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
+ " ib_thread(%d,0x%x): ENTER: pipe %d \n",\r
+ dapl_os_getpid(), g_ib_thread, g_ib_pipe[0]);\r
+\r
+ /* Poll across pipe, CM, AT never changes */\r
+ dapl_os_lock(&g_hca_lock);\r
+ g_ib_thread_state = IB_THREAD_RUN;\r
+\r
+ ufds[0].fd = g_ib_pipe[0]; /* pipe */\r
+ ufds[0].events = POLLIN;\r
+\r
+ while (g_ib_thread_state == IB_THREAD_RUN) {\r
+\r
+ /* build ufds after pipe and uCMA events */\r
+ ufds[0].revents = 0;\r
+ idx = 0;\r
+\r
+ /* Walk HCA list and setup async and CQ events */\r
+ if (!dapl_llist_is_empty(&g_hca_list))\r
+ hca = dapl_llist_peek_head(&g_hca_list);\r
+ else\r
+ hca = NULL;\r
+\r
+ while (hca) {\r
+\r
+ /* uASYNC events */\r
+ ufds[++idx].fd = hca->ib_ctx->async_fd;\r
+ ufds[idx].events = POLLIN;\r
+ ufds[idx].revents = 0;\r
+ uhca[idx] = hca;\r
+\r
+ /* CQ events are non-direct with CNO's */\r
+ ufds[++idx].fd = hca->ib_cq->fd;\r
+ ufds[idx].events = POLLIN;\r
+ ufds[idx].revents = 0;\r
+ uhca[idx] = hca;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
+ " ib_thread(%d) poll_fd: hca[%d]=%p,"\r
+ " async=%d pipe=%d \n",\r
+ dapl_os_getpid(), hca, ufds[idx - 1].fd,\r
+ ufds[0].fd);\r
+\r
+ hca = dapl_llist_next_entry(&g_hca_list,\r
+ (DAPL_LLIST_ENTRY *)\r
+ &hca->entry);\r
+ }\r
+\r
+ /* unlock, and setup poll */\r
+ fds = idx + 1;\r
+ dapl_os_unlock(&g_hca_lock);\r
+ ret = poll(ufds, fds, -1);\r
+ if (ret <= 0) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
+ " ib_thread(%d): ERR %s poll\n",\r
+ dapl_os_getpid(), strerror(errno));\r
+ dapl_os_lock(&g_hca_lock);\r
+ continue;\r
+ }\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_THREAD,\r
+ " ib_thread(%d) poll_event: "\r
+ " async=0x%x pipe=0x%x \n",\r
+ dapl_os_getpid(), ufds[idx].revents,\r
+ ufds[0].revents);\r
+\r
+ /* check and process CQ and ASYNC events, per device */\r
+ for (idx = 1; idx < fds; idx++) {\r
+ if (ufds[idx].revents == POLLIN) {\r
+ dapli_cq_event_cb(uhca[idx]);\r
+ dapli_async_event_cb(uhca[idx]);\r
+ }\r
+ }\r
+\r
+ /* check and process user events, PIPE */\r
+ if (ufds[0].revents == POLLIN) {\r
+ if (read(g_ib_pipe[0], rbuf, 2) == -1)\r
+ dapl_log(DAPL_DBG_TYPE_THREAD,\r
+ " cr_thread: pipe rd err= %s\n",\r
+ strerror(errno));\r
+\r
+ /* cleanup any device on list marked for destroy */\r
+ for (idx = 1; idx < fds; idx++) {\r
+ if (uhca[idx] && uhca[idx]->destroy == 1) {\r
+ dapl_os_lock(&g_hca_lock);\r
+ dapl_llist_remove_entry(\r
+ &g_hca_list,\r
+ (DAPL_LLIST_ENTRY*)\r
+ &uhca[idx]->entry);\r
+ dapl_os_unlock(&g_hca_lock);\r
+ uhca[idx]->destroy = 2;\r
+ }\r
+ }\r
+ }\r
+ dapl_os_lock(&g_hca_lock);\r
+ }\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_THREAD, " ib_thread(%d) EXIT\n",\r
+ dapl_os_getpid());\r
+ g_ib_thread_state = IB_THREAD_EXIT;\r
+ dapl_os_unlock(&g_hca_lock);\r
+}\r
+#endif\r
-/*
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- * copy of which is available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/**********************************************************************
- *
- * MODULE: dapl_evd_set_unwaitable.c
- *
- * PURPOSE: EVENT management
- * Description: Interfaces in this file are completely described in
- * the DAPL 1.1 API, Chapter 6, section 3.4.7
- *
- * $Id:$
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_adapter_util.h"
-
-/*
- * dapl_evd_set_unwaitable
- *
- * DAPL Requirements Version 1.1, 6.3.4.7
- *
- * Transition the Event Dispatcher into an unwaitable state
- *
- * Input:
- * evd_handle
- *
- * Output:
- * none
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_HANDLE
- */
-DAT_RETURN DAT_API dapl_evd_set_unwaitable(IN DAT_EVD_HANDLE evd_handle)
-{
- DAPL_EVD *evd_ptr;
- DAT_RETURN dat_status;
-
- evd_ptr = (DAPL_EVD *) evd_handle;
- dat_status = DAT_SUCCESS;
-
- if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD))
- {
- dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0);
- goto bail;
- }
- dapl_os_lock(&evd_ptr->header.lock);
- evd_ptr->evd_waitable = DAT_FALSE;
- dapl_os_unlock(&evd_ptr->header.lock);
-
- /*
- * If this evd is waiting, wake it up. There is an obvious race
- * condition here where we may wakeup the waiter before it goes to
- * sleep; but the wait_object allows this and will do the right
- * thing.
- */
- if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED) {
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle)
- dapls_ib_wait_object_wakeup(evd_ptr->
- cq_wait_obj_handle);
- else
-#endif
- dapl_os_wait_object_wakeup(&evd_ptr->wait_object);
- }
- bail:
- return dat_status;
-}
-
-/*
- * Local variables:
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 8
- * End:
- */
+/*\r
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
+ * copy of which is available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_evd_set_unwaitable.c\r
+ *\r
+ * PURPOSE: EVENT management\r
+ * Description: Interfaces in this file are completely described in\r
+ * the DAPL 1.1 API, Chapter 6, section 3.4.7\r
+ *\r
+ * $Id:$\r
+ **********************************************************************/\r
+\r
+#include "dapl.h"\r
+#include "dapl_adapter_util.h"\r
+\r
+/*\r
+ * dapl_evd_set_unwaitable\r
+ *\r
+ * DAPL Requirements Version 1.1, 6.3.4.7\r
+ *\r
+ * Transition the Event Dispatcher into an unwaitable state\r
+ *\r
+ * Input:\r
+ * evd_handle\r
+ *\r
+ * Output:\r
+ * none\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_HANDLE\r
+ */\r
+DAT_RETURN DAT_API dapl_evd_set_unwaitable(IN DAT_EVD_HANDLE evd_handle)\r
+{\r
+ DAPL_EVD *evd_ptr;\r
+ DAT_RETURN dat_status;\r
+\r
+ evd_ptr = (DAPL_EVD *) evd_handle;\r
+ dat_status = DAT_SUCCESS;\r
+\r
+ if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD))\r
+ {\r
+ dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0);\r
+ goto bail;\r
+ }\r
+ dapl_os_lock(&evd_ptr->header.lock);\r
+ evd_ptr->evd_waitable = DAT_FALSE;\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+\r
+ /*\r
+ * If this evd is waiting, wake it up. There is an obvious race\r
+ * condition here where we may wakeup the waiter before it goes to\r
+ * sleep; but the wait_object allows this and will do the right\r
+ * thing.\r
+ */\r
+ if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED) {\r
+ if (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG))\r
+ dapls_evd_dto_wakeup(evd_ptr);\r
+ else\r
+ dapl_os_wait_object_wakeup(&evd_ptr->wait_object);\r
+ }\r
+ bail:\r
+ return dat_status;\r
+}\r
+\r
+/*\r
+ * Local variables:\r
+ * c-indent-level: 4\r
+ * c-basic-offset: 4\r
+ * tab-width: 8\r
+ * End:\r
+ */\r
-/*
- * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
- *
- * This Software is licensed under one of the following licenses:
- *
- * 1) under the terms of the "Common Public License 1.0" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/cpl.php.
- *
- * 2) under the terms of the "The BSD License" a copy of which is
- * available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/bsd-license.php.
- *
- * 3) under the terms of the "GNU General Public License (GPL) Version 2" a
- * copy of which is available from the Open Source Initiative, see
- * http://www.opensource.org/licenses/gpl-license.php.
- *
- * Licensee has the right to choose one of the above licenses.
- *
- * Redistributions of source code must retain the above copyright
- * notice and one of the license notices.
- *
- * Redistributions in binary form must reproduce both the above copyright
- * notice, one of the license notices in the documentation
- * and/or other materials provided with the distribution.
- */
-
-/**********************************************************************
- *
- * MODULE: dapl_evd_wait.c
- *
- * PURPOSE: EVENT management
- *
- * Description: Interfaces in this file are completely defined in
- * the uDAPL 1.1 API specification
- *
- * $Id:$
- **********************************************************************/
-
-#include "dapl.h"
-#include "dapl_evd_util.h"
-#include "dapl_ring_buffer_util.h"
-#include "dapl_adapter_util.h"
-
-/*
- * dapl_evd_wait
- *
- * UDAPL Requirements Version xxx,
- *
- * Wait, up to specified timeout, for notification event on EVD.
- * Then return first available event.
- *
- * Input:
- * evd_handle
- * timeout
- *
- * Output:
- * event
- *
- * Returns:
- * DAT_SUCCESS
- * DAT_INVALID_PARAMETER
- * DAT_INVALID_STATE
- */
-
-DAT_RETURN DAT_API dapl_evd_wait(IN DAT_EVD_HANDLE evd_handle,
- IN DAT_TIMEOUT time_out,
- IN DAT_COUNT threshold,
- OUT DAT_EVENT * event, OUT DAT_COUNT * nmore)
-{
- DAPL_EVD *evd_ptr;
- DAT_RETURN dat_status;
- DAT_EVENT *local_event;
- DAT_BOOLEAN notify_requested = DAT_FALSE;
- DAT_BOOLEAN waitable;
- DAPL_EVD_STATE evd_state;
-
- dapl_dbg_log(DAPL_DBG_TYPE_API,
- "dapl_evd_wait (%p, %d, %d, %p, %p)\n",
- evd_handle, time_out, threshold, event, nmore);
-
- evd_ptr = (DAPL_EVD *) evd_handle;
- dat_status = DAT_SUCCESS;
-
- if (DAPL_BAD_HANDLE(evd_ptr, DAPL_MAGIC_EVD)) {
- /*
- * We return directly rather than bailing because
- * bailing attempts to update the evd, and we don't have
- * one.
- */
- dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0);
- goto bail;
- }
- if (!event) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);
- goto bail;
- }
- if (!nmore) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5);
- goto bail;
- }
- if (threshold <= 0 ||
- (threshold > 1
- && evd_ptr->completion_type != DAPL_EVD_STATE_THRESHOLD)
- || threshold > evd_ptr->qlen) {
- dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);
- goto bail;
- }
- if (evd_ptr->catastrophic_overflow) {
- dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);
- goto bail;
- }
- DAPL_CNTR(evd_ptr, DCNT_EVD_WAIT);
-
- dapl_dbg_log(DAPL_DBG_TYPE_EVD,
- "dapl_evd_wait: EVD %p, CQ %p\n",
- evd_ptr, (void *)evd_ptr->ib_cq_handle);
-
- /*
- * Make sure there are no other waiters and the evd is active.
- * Currently this means only the OPEN state is allowed.
- * Do this atomically. We need to take a lock to synchronize
- * with dapl_evd_dequeue(), but the atomic transition allows
- * non-locking synchronization with dapl_evd_query() and
- * dapl_evd_{query,enable,disable,{set,clear}_unwaitable}.
- */
-
- dapl_os_lock(&evd_ptr->header.lock);
- waitable = evd_ptr->evd_waitable;
-
- dapl_os_assert(sizeof(DAT_COUNT) == sizeof(DAPL_EVD_STATE));
- evd_state = evd_ptr->evd_state;
- if (evd_ptr->evd_state == DAPL_EVD_STATE_OPEN)
- evd_ptr->evd_state = DAPL_EVD_STATE_WAITED;
-
- if (evd_state != DAPL_EVD_STATE_OPEN) {
- /* Bogus state, bail out */
- dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);
- goto bail;
- }
-
- if (!waitable) {
- /* This EVD is not waitable, reset the state and bail */
- if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED)
- evd_ptr->evd_state = evd_state;
-
- dat_status =
- DAT_ERROR(DAT_INVALID_STATE,
- DAT_INVALID_STATE_EVD_UNWAITABLE);
- goto bail;
- }
-
- /*
- * We now own the EVD, even though we don't have the lock anymore,
- * because we're in the WAITED state.
- */
-
- evd_ptr->threshold = threshold;
-
- for (;;) {
- /*
- * Ideally we'd just check the number of entries on the CQ, but
- * we don't have a way to do that. Because we have to set *nmore
- * at some point in this routine, we'll need to do this copy
- * sometime even if threshold == 1.
- *
- * For connection evd or async evd, the function checks and
- * return right away if the ib_cq_handle associate with these evd
- * equal to IB_INVALID_HANDLE
- */
- dapl_os_unlock(&evd_ptr->header.lock);
- dapls_evd_copy_cq(evd_ptr);
- dapl_os_lock(&evd_ptr->header.lock);
-
- if (dapls_rbuf_count(&evd_ptr->pending_event_queue) >=
- threshold) {
- break;
- }
-
- /*
- * Do not enable the completion notification if this evd is not
- * a DTO_EVD or RMR_BIND_EVD
- */
- if ((!notify_requested) &&
- ((evd_ptr->evd_flags & DAT_EVD_DTO_FLAG) ||
- (evd_ptr->evd_flags & DAT_EVD_RMR_BIND_FLAG))) {
- dat_status =
- dapls_ib_completion_notify(evd_ptr->header.
- owner_ia->hca_ptr->
- ib_hca_handle, evd_ptr,
- (evd_ptr->
- completion_type ==
- DAPL_EVD_STATE_SOLICITED_WAIT)
- ? IB_NOTIFY_ON_SOLIC_COMP
- :
- IB_NOTIFY_ON_NEXT_COMP);
-
- DAPL_CNTR(evd_ptr, DCNT_EVD_WAIT_NOTIFY);
- /* FIXME report error */
- dapl_os_assert(dat_status == DAT_SUCCESS);
-
- notify_requested = DAT_TRUE;
-
- /* Try again. */
- continue;
- }
-
- /*
- * Unused by poster; it has no way to tell how many
- * items are on the queue without copying them over to the
- * EVD queue, and we're the only ones allowed to dequeue
- * from the CQ for synchronization/locking reasons.
- */
- evd_ptr->threshold = threshold;
-
- DAPL_CNTR(evd_ptr, DCNT_EVD_WAIT_BLOCKED);
- dapl_os_unlock(&evd_ptr->header.lock);
-
-#ifdef CQ_WAIT_OBJECT
- if (evd_ptr->cq_wait_obj_handle)
- dat_status =
- dapls_ib_wait_object_wait(evd_ptr->
- cq_wait_obj_handle,
- time_out);
- else
-#endif
- dat_status =
- dapl_os_wait_object_wait(&evd_ptr->wait_object,
- time_out);
-
- dapl_os_lock(&evd_ptr->header.lock);
-
- /*
- * FIXME: if the thread loops around and waits again
- * the time_out value needs to be updated.
- */
-
- notify_requested = DAT_FALSE; /* We've used it up. */
-
- /* See if we were awakened by evd_set_unwaitable */
- if (!evd_ptr->evd_waitable) {
- dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);
- }
-
- if (dat_status != DAT_SUCCESS) {
- /*
- * If the status is DAT_TIMEOUT, we'll break out of the
- * loop, *not* dequeue an event (because dat_status
- * != DAT_SUCCESS), set *nmore (as we should for timeout)
- * and return DAT_TIMEOUT.
- */
- break;
- }
- }
-
- evd_ptr->evd_state = DAPL_EVD_STATE_OPEN;
-
- if (dat_status == DAT_SUCCESS) {
- local_event = dapls_rbuf_remove(&evd_ptr->pending_event_queue);
- *event = *local_event;
- dapls_rbuf_add(&evd_ptr->free_event_queue, local_event);
- }
-
- /*
- * Valid if dat_status == DAT_SUCCESS || dat_status == DAT_TIMEOUT
- * Undefined otherwise, so ok to set it.
- */
- *nmore = dapls_rbuf_count(&evd_ptr->pending_event_queue);
-
- bail:
- dapl_os_unlock(&evd_ptr->header.lock);
- if (dat_status) {
- dapl_dbg_log(DAPL_DBG_TYPE_RTN,
- "dapl_evd_wait () returns 0x%x\n", dat_status);
- }
- return dat_status;
-}
+/*\r
+ * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
+ *\r
+ * This Software is licensed under one of the following licenses:\r
+ *\r
+ * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/cpl.php.\r
+ *\r
+ * 2) under the terms of the "The BSD License" a copy of which is\r
+ * available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/bsd-license.php.\r
+ *\r
+ * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
+ * copy of which is available from the Open Source Initiative, see\r
+ * http://www.opensource.org/licenses/gpl-license.php.\r
+ *\r
+ * Licensee has the right to choose one of the above licenses.\r
+ *\r
+ * Redistributions of source code must retain the above copyright\r
+ * notice and one of the license notices.\r
+ *\r
+ * Redistributions in binary form must reproduce both the above copyright\r
+ * notice, one of the license notices in the documentation\r
+ * and/or other materials provided with the distribution.\r
+ */\r
+\r
+/**********************************************************************\r
+ * \r
+ * MODULE: dapl_evd_wait.c\r
+ *\r
+ * PURPOSE: EVENT management\r
+ *\r
+ * Description: Interfaces in this file are completely defined in \r
+ * the uDAPL 1.1 API specification\r
+ *\r
+ * $Id:$\r
+ **********************************************************************/\r
+\r
+#include "dapl.h"\r
+#include "dapl_evd_util.h"\r
+#include "dapl_ring_buffer_util.h"\r
+#include "dapl_adapter_util.h"\r
+\r
+/*\r
+ * dapl_evd_wait\r
+ *\r
+ * UDAPL Requirements Version xxx, \r
+ *\r
+ * Wait, up to specified timeout, for notification event on EVD.\r
+ * Then return first available event.\r
+ *\r
+ * Input:\r
+ * evd_handle\r
+ * timeout\r
+ *\r
+ * Output:\r
+ * event\r
+ *\r
+ * Returns:\r
+ * DAT_SUCCESS\r
+ * DAT_INVALID_PARAMETER\r
+ * DAT_INVALID_STATE\r
+ */\r
+\r
+DAT_RETURN DAT_API dapl_evd_wait(IN DAT_EVD_HANDLE evd_handle,\r
+ IN DAT_TIMEOUT time_out,\r
+ IN DAT_COUNT threshold,\r
+ OUT DAT_EVENT * event, OUT DAT_COUNT * nmore)\r
+{\r
+ DAPL_EVD *evd_ptr;\r
+ DAT_RETURN dat_status;\r
+ DAT_EVENT *local_event;\r
+ DAT_BOOLEAN notify_requested = DAT_FALSE;\r
+ DAT_BOOLEAN waitable;\r
+ DAPL_EVD_STATE evd_state;\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_API,\r
+ "dapl_evd_wait (%p, %d, %d, %p, %p)\n",\r
+ evd_handle, time_out, threshold, event, nmore);\r
+\r
+ evd_ptr = (DAPL_EVD *) evd_handle;\r
+ dat_status = DAT_SUCCESS;\r
+\r
+ if (DAPL_BAD_HANDLE(evd_ptr, DAPL_MAGIC_EVD)) {\r
+ /*\r
+ * We return directly rather than bailing because\r
+ * bailing attempts to update the evd, and we don't have\r
+ * one.\r
+ */\r
+ dat_status = DAT_ERROR(DAT_INVALID_HANDLE, 0);\r
+ goto bail;\r
+ }\r
+ if (!event) {\r
+ dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4);\r
+ goto bail;\r
+ }\r
+ if (!nmore) {\r
+ dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5);\r
+ goto bail;\r
+ }\r
+ if (threshold <= 0 ||\r
+ (threshold > 1\r
+ && evd_ptr->completion_type != DAPL_EVD_STATE_THRESHOLD)\r
+ || threshold > evd_ptr->qlen) {\r
+ dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3);\r
+ goto bail;\r
+ }\r
+ if (evd_ptr->catastrophic_overflow) {\r
+ dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);\r
+ goto bail;\r
+ }\r
+ DAPL_CNTR(evd_ptr, DCNT_EVD_WAIT);\r
+\r
+ dapl_dbg_log(DAPL_DBG_TYPE_EVD,\r
+ "dapl_evd_wait: EVD %p, CQ %p\n",\r
+ evd_ptr, (void *)evd_ptr->ib_cq_handle);\r
+\r
+ /*\r
+ * Make sure there are no other waiters and the evd is active.\r
+ * Currently this means only the OPEN state is allowed.\r
+ * Do this atomically. We need to take a lock to synchronize\r
+ * with dapl_evd_dequeue(), but the atomic transition allows\r
+ * non-locking synchronization with dapl_evd_query() and\r
+ * dapl_evd_{query,enable,disable,{set,clear}_unwaitable}.\r
+ */\r
+\r
+ dapl_os_lock(&evd_ptr->header.lock);\r
+ waitable = evd_ptr->evd_waitable;\r
+\r
+ dapl_os_assert(sizeof(DAT_COUNT) == sizeof(DAPL_EVD_STATE));\r
+ evd_state = evd_ptr->evd_state;\r
+ if (evd_ptr->evd_state == DAPL_EVD_STATE_OPEN)\r
+ evd_ptr->evd_state = DAPL_EVD_STATE_WAITED;\r
+\r
+ if (evd_state != DAPL_EVD_STATE_OPEN) {\r
+ /* Bogus state, bail out */\r
+ dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);\r
+ goto bail;\r
+ }\r
+\r
+ if (!waitable) {\r
+ /* This EVD is not waitable, reset the state and bail */\r
+ if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED)\r
+ evd_ptr->evd_state = evd_state;\r
+\r
+ dat_status =\r
+ DAT_ERROR(DAT_INVALID_STATE,\r
+ DAT_INVALID_STATE_EVD_UNWAITABLE);\r
+ goto bail;\r
+ }\r
+\r
+ /*\r
+ * We now own the EVD, even though we don't have the lock anymore,\r
+ * because we're in the WAITED state.\r
+ */\r
+\r
+ evd_ptr->threshold = threshold;\r
+\r
+ for (;;) {\r
+ /*\r
+ * Ideally we'd just check the number of entries on the CQ, but\r
+ * we don't have a way to do that. Because we have to set *nmore\r
+ * at some point in this routine, we'll need to do this copy\r
+ * sometime even if threshold == 1.\r
+ *\r
+ * For connection evd or async evd, the function checks and\r
+ * return right away if the ib_cq_handle associate with these evd\r
+ * equal to IB_INVALID_HANDLE\r
+ */\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+ dapls_evd_copy_cq(evd_ptr);\r
+ dapl_os_lock(&evd_ptr->header.lock);\r
+\r
+ if (dapls_rbuf_count(&evd_ptr->pending_event_queue) >=\r
+ threshold) {\r
+ break;\r
+ }\r
+\r
+ /*\r
+ * Do not enable the completion notification if this evd is not \r
+ * a DTO_EVD or RMR_BIND_EVD\r
+ */\r
+ if ((!notify_requested) &&\r
+ (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG))) {\r
+ dat_status =\r
+ dapls_ib_completion_notify(evd_ptr->header.\r
+ owner_ia->hca_ptr->\r
+ ib_hca_handle, evd_ptr,\r
+ (evd_ptr->\r
+ completion_type ==\r
+ DAPL_EVD_STATE_SOLICITED_WAIT)\r
+ ? IB_NOTIFY_ON_SOLIC_COMP\r
+ :\r
+ IB_NOTIFY_ON_NEXT_COMP);\r
+\r
+ DAPL_CNTR(evd_ptr, DCNT_EVD_WAIT_NOTIFY);\r
+ /* FIXME report error */\r
+ dapl_os_assert(dat_status == DAT_SUCCESS);\r
+\r
+ notify_requested = DAT_TRUE;\r
+\r
+ /* Try again. */\r
+ continue;\r
+ }\r
+\r
+ /*\r
+ * Unused by poster; it has no way to tell how many\r
+ * items are on the queue without copying them over to the\r
+ * EVD queue, and we're the only ones allowed to dequeue\r
+ * from the CQ for synchronization/locking reasons.\r
+ */\r
+ evd_ptr->threshold = threshold;\r
+\r
+ DAPL_CNTR(evd_ptr, DCNT_EVD_WAIT_BLOCKED);\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+\r
+ if (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG)) {\r
+ dat_status = dapls_evd_dto_wait(evd_ptr, time_out);\r
+ } else {\r
+ dat_status = dapl_os_wait_object_wait(&evd_ptr->wait_object, time_out);\r
+ }\r
+\r
+ dapl_os_lock(&evd_ptr->header.lock);\r
+\r
+ /*\r
+ * FIXME: if the thread loops around and waits again\r
+ * the time_out value needs to be updated.\r
+ */\r
+\r
+ notify_requested = DAT_FALSE; /* We've used it up. */\r
+\r
+ /* See if we were awakened by evd_set_unwaitable */\r
+ if (!evd_ptr->evd_waitable) {\r
+ dat_status = DAT_ERROR(DAT_INVALID_STATE, 0);\r
+ }\r
+\r
+ if (dat_status != DAT_SUCCESS) {\r
+ /*\r
+ * If the status is DAT_TIMEOUT, we'll break out of the\r
+ * loop, *not* dequeue an event (because dat_status\r
+ * != DAT_SUCCESS), set *nmore (as we should for timeout)\r
+ * and return DAT_TIMEOUT.\r
+ */\r
+ break;\r
+ }\r
+ }\r
+\r
+ evd_ptr->evd_state = DAPL_EVD_STATE_OPEN;\r
+\r
+ if (dat_status == DAT_SUCCESS) {\r
+ local_event = dapls_rbuf_remove(&evd_ptr->pending_event_queue);\r
+ *event = *local_event;\r
+ dapls_rbuf_add(&evd_ptr->free_event_queue, local_event);\r
+ }\r
+\r
+ /*\r
+ * Valid if dat_status == DAT_SUCCESS || dat_status == DAT_TIMEOUT\r
+ * Undefined otherwise, so ok to set it.\r
+ */\r
+ *nmore = dapls_rbuf_count(&evd_ptr->pending_event_queue);\r
+\r
+ bail:\r
+ dapl_os_unlock(&evd_ptr->header.lock);\r
+ if (dat_status) {\r
+ dapl_dbg_log(DAPL_DBG_TYPE_RTN,\r
+ "dapl_evd_wait () returns 0x%x\n", dat_status);\r
+ }\r
+ return dat_status;\r
+}\r
#elif defined(_MSC_VER) || defined(_WIN32) || defined(_WIN64)
/* NT. MSC compiler, Win32/64 platform */
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
typedef unsigned __int32 DAT_UINT32; /* Unsigned host order, 32 bits */
typedef unsigned __int64 DAT_UINT64; /* unsigned host order, 64 bits */
typedef unsigned long DAT_UVERYLONG; /* unsigned longest native to compiler */
-/*
- * Copyright (c) 2005-2008 Intel Corporation. All rights reserved.
- *
- * This software is available to you under a choice of one of two
- * licenses. You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef DAPL_PROVIDER
-#undef DAPL_PROVIDER
-#endif
-
-#if defined(_WIN32) || defined(_WIN64)
-
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <io.h>
-#include <process.h>
-#include <complib/cl_types.h>
-#include "..\..\..\..\etc\user\getopt.c"
-
-#define getpid() ((int)GetCurrentProcessId())
-#define F64x "%I64x"
-
-#ifdef DBG
-#define DAPL_PROVIDER "ibnic0v2d"
-#else
-#define DAPL_PROVIDER "ibnic0v2"
-#endif
-
-#define ntohll _byteswap_uint64
-#define htonll _byteswap_uint64
-
-#else // _WIN32 || _WIN64
-
-#include <endian.h>
-#include <byteswap.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <sys/mman.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <unistd.h>
-
-#define DAPL_PROVIDER "ofa-v2-ib0"
-
-#define F64x "%"PRIx64""
-
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define htonll(x) (x)
-#define ntohll(x) (x)
-#elif __BYTE_ORDER == __LITTLE_ENDIAN
-#define htonll(x) bswap_64(x)
-#define ntohll(x) bswap_64(x)
-#endif
-
-#endif // _WIN32 || _WIN64
-
-/* Debug: 1 == connect & close only, otherwise full-meal deal */
-#define CONNECT_ONLY 0
-
-#define MAX_POLLING_CNT 50000
-#define MAX_RDMA_RD 4
-#define MAX_PROCS 1000
-
-/* Header files needed for DAT/uDAPL */
-#include "dat2/udat.h"
-
-/* definitions */
-#define SERVER_CONN_QUAL 45248
-#define DTO_TIMEOUT (1000*1000*5)
-#define DTO_FLUSH_TIMEOUT (1000*1000*2)
-#define CONN_TIMEOUT (1000*1000*10)
-#define SERVER_TIMEOUT DAT_TIMEOUT_INFINITE
-#define RDMA_BUFFER_SIZE (64)
-
-/* Global DAT vars */
-static DAT_IA_HANDLE h_ia = DAT_HANDLE_NULL;
-static DAT_PZ_HANDLE h_pz = DAT_HANDLE_NULL;
-static DAT_EP_HANDLE h_ep = DAT_HANDLE_NULL;
-static DAT_PSP_HANDLE h_psp = DAT_HANDLE_NULL;
-static DAT_CR_HANDLE h_cr = DAT_HANDLE_NULL;
-
-static DAT_EVD_HANDLE h_async_evd = DAT_HANDLE_NULL;
-static DAT_EVD_HANDLE h_dto_req_evd = DAT_HANDLE_NULL;
-static DAT_EVD_HANDLE h_dto_rcv_evd = DAT_HANDLE_NULL;
-static DAT_EVD_HANDLE h_cr_evd = DAT_HANDLE_NULL;
-static DAT_EVD_HANDLE h_conn_evd = DAT_HANDLE_NULL;
-static DAT_CNO_HANDLE h_dto_cno = DAT_HANDLE_NULL;
-
-/* RDMA buffers */
-static DAT_LMR_HANDLE h_lmr_send = DAT_HANDLE_NULL;
-static DAT_LMR_HANDLE h_lmr_recv = DAT_HANDLE_NULL;
-static DAT_LMR_CONTEXT lmr_context_send;
-static DAT_LMR_CONTEXT lmr_context_recv;
-static DAT_RMR_CONTEXT rmr_context_send;
-static DAT_RMR_CONTEXT rmr_context_recv;
-static DAT_VLEN registered_size_send;
-static DAT_VLEN registered_size_recv;
-static DAT_VADDR registered_addr_send;
-static DAT_VADDR registered_addr_recv;
-
-/* Initial msg receive buf, RMR exchange, and Rdma-write notification */
-#define MSG_BUF_COUNT 3
-#define MSG_IOV_COUNT 2
-static DAT_RMR_TRIPLET rmr_recv_msg[MSG_BUF_COUNT];
-static DAT_LMR_HANDLE h_lmr_recv_msg = DAT_HANDLE_NULL;
-static DAT_LMR_CONTEXT lmr_context_recv_msg;
-static DAT_RMR_CONTEXT rmr_context_recv_msg;
-static DAT_VLEN registered_size_recv_msg;
-static DAT_VADDR registered_addr_recv_msg;
-
-/* message send buffer */
-static DAT_RMR_TRIPLET rmr_send_msg;
-static DAT_LMR_HANDLE h_lmr_send_msg = DAT_HANDLE_NULL;
-static DAT_LMR_CONTEXT lmr_context_send_msg;
-static DAT_RMR_CONTEXT rmr_context_send_msg;
-static DAT_VLEN registered_size_send_msg;
-static DAT_VADDR registered_addr_send_msg;
-static DAT_EP_ATTR ep_attr;
-char hostname[256] = { 0 };
-char provider[64] = DAPL_PROVIDER;
-char addr_str[INET_ADDRSTRLEN];
-
-/* rdma pointers */
-char *rbuf = NULL;
-char *sbuf = NULL;
-int status;
-
-/* timers */
-double start, stop, total_us, total_sec;
-
-struct dt_time {
- double total;
- double open;
- double reg;
- double unreg;
- double pzc;
- double pzf;
- double evdc;
- double evdf;
- double cnoc;
- double cnof;
- double epc;
- double epf;
- double rdma_wr;
- double rdma_rd[MAX_RDMA_RD];
- double rdma_rd_total;
- double rtt;
- double close;
- double conn;
-};
-
-struct dt_time time;
-
-/* defaults */
-static int failed = 0;
-static int performance_times = 0;
-static int connected = 0;
-static int burst = 10;
-static int server = 1;
-static int verbose = 0;
-static int polling = 0;
-static int poll_count = 0;
-static int rdma_wr_poll_count = 0;
-static int conn_poll_count = 0;
-static int rdma_rd_poll_count[MAX_RDMA_RD] = { 0 };
-static int delay = 0;
-static int buf_len = RDMA_BUFFER_SIZE;
-static int use_cno = 0;
-static int recv_msg_index = 0;
-static int burst_msg_posted = 0;
-static int burst_msg_index = 0;
-
-/* forward prototypes */
-const char *DT_RetToString(DAT_RETURN ret_value);
-const char *DT_EventToSTr(DAT_EVENT_NUMBER event_code);
-void print_usage(void);
-double get_time(void);
-void init_data(void);
-
-DAT_RETURN send_msg(void *data,
- DAT_COUNT size,
- DAT_LMR_CONTEXT context,
- DAT_DTO_COOKIE cookie, DAT_COMPLETION_FLAGS flags);
-
-DAT_RETURN connect_ep(char *hostname, DAT_CONN_QUAL conn_id);
-void disconnect_ep(void);
-DAT_RETURN register_rdma_memory(void);
-DAT_RETURN unregister_rdma_memory(void);
-DAT_RETURN create_events(void);
-DAT_RETURN destroy_events(void);
-DAT_RETURN do_rdma_write_with_msg(void);
-DAT_RETURN do_rdma_read_with_msg(void);
-DAT_RETURN do_ping_pong_msg(void);
-
-#define LOGPRINTF if (verbose) printf
-
-void flush_evds(void)
-{
- DAT_EVENT event;
-
- /* Flush async error queue */
- printf("%d ERR: Checking ASYNC EVD...\n", getpid());
- while (dat_evd_dequeue(h_async_evd, &event) == DAT_SUCCESS) {
- printf(" ASYNC EVD ENTRY: handle=%p reason=%d\n",
- event.event_data.asynch_error_event_data.dat_handle,
- event.event_data.asynch_error_event_data.reason);
- }
- /* Flush receive queue */
- printf("%d ERR: Checking RECEIVE EVD...\n", getpid());
- while (dat_evd_dequeue(h_dto_rcv_evd, &event) == DAT_SUCCESS) {
- printf(" RCV EVD ENTRY: op=%d stat=%d ln=%d ck="F64x"\n",
- event.event_data.dto_completion_event_data.operation,
- event.event_data.dto_completion_event_data.status,
- event.event_data.dto_completion_event_data.transfered_length,
- event.event_data.dto_completion_event_data.user_cookie.as_64);
- }
- /* Flush request queue */
- printf("%d ERR: Checking REQUEST EVD...\n", getpid());
- while (dat_evd_dequeue(h_dto_req_evd, &event) == DAT_SUCCESS) {
- printf(" REQ EVD ENTRY: op=%d stat=%d ln=%d ck="F64x"\n",
- event.event_data.dto_completion_event_data.operation,
- event.event_data.dto_completion_event_data.status,
- event.event_data.dto_completion_event_data.transfered_length,
- event.event_data.dto_completion_event_data.user_cookie.as_64);
- }
-}
-
-int main(int argc, char **argv)
-{
- int i, c;
- DAT_RETURN ret;
- DAT_EP_PARAM ep_param;
-
- /* parse arguments */
- while ((c = getopt(argc, argv, "tscvpb:d:B:h:P:")) != -1) {
- switch (c) {
- case 't':
- performance_times = 1;
- fflush(stdout);
- break;
- case 's':
- server = 1;
- fflush(stdout);
- break;
- case 'c':
- use_cno = 1;
- printf("%d Creating CNO for DTO EVD's\n", getpid());
- fflush(stdout);
- break;
- case 'v':
- verbose = 1;
- printf("%d Verbose\n", getpid());
- fflush(stdout);
- break;
- case 'p':
- polling = 1;
- printf("%d Polling\n", getpid());
- fflush(stdout);
- break;
- case 'B':
- burst = atoi(optarg);
- break;
- case 'd':
- delay = atoi(optarg);
- break;
- case 'b':
- buf_len = atoi(optarg);
- break;
- case 'h':
- server = 0;
- strcpy(hostname, optarg);
- break;
- case 'P':
- strcpy(provider, optarg);
- break;
- default:
- print_usage();
- exit(-12);
- }
- }
-
-#if defined(_WIN32) || defined(_WIN64)
- {
- WSADATA wsaData;
-
- i = WSAStartup(MAKEWORD(2, 2), &wsaData);
- if (i != 0) {
- printf("%s WSAStartup(2.2) failed? (0x%x)\n", argv[0],
- i);
- fflush(stdout);
- exit(1);
- }
- }
-#endif
-
- if (!server) {
- printf("%d Running as client - %s\n", getpid(), provider);
- } else {
- printf("%d Running as server - %s\n", getpid(), provider);
- }
- fflush(stdout);
-
- /* allocate send and receive buffers */
- if (((rbuf = malloc(buf_len * (burst+1))) == NULL) ||
- ((sbuf = malloc(buf_len * (burst+1))) == NULL)) {
- perror("malloc");
- exit(1);
- }
- memset(&time, 0, sizeof(struct dt_time));
- LOGPRINTF("%d Allocated RDMA buffers (r:%p,s:%p) len %d \n",
- getpid(), rbuf, sbuf, buf_len);
-
- /* dat_ia_open, dat_pz_create */
- h_async_evd = DAT_HANDLE_NULL;
- start = get_time();
- ret = dat_ia_open(provider, 8, &h_async_evd, &h_ia);
- stop = get_time();
- time.open += ((stop - start) * 1.0e6);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d: Error Adaptor open: %s\n",
- getpid(), DT_RetToString(ret));
- exit(1);
- } else
- LOGPRINTF("%d Opened Interface Adaptor\n", getpid());
-
- /* Create Protection Zone */
- start = get_time();
- LOGPRINTF("%d Create Protection Zone\n", getpid());
- ret = dat_pz_create(h_ia, &h_pz);
- stop = get_time();
- time.pzc += ((stop - start) * 1.0e6);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error creating Protection Zone: %s\n",
- getpid(), DT_RetToString(ret));
- exit(1);
- } else
- LOGPRINTF("%d Created Protection Zone\n", getpid());
-
- /* Register memory */
- LOGPRINTF("%d Register RDMA memory\n", getpid());
- ret = register_rdma_memory();
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error registering RDMA memory: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else
- LOGPRINTF("%d Register RDMA memory done\n", getpid());
-
- LOGPRINTF("%d Create events\n", getpid());
- ret = create_events();
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error creating events: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else {
- LOGPRINTF("%d Create events done\n", getpid());
- }
-
- /* create EP */
- memset(&ep_attr, 0, sizeof(ep_attr));
- ep_attr.service_type = DAT_SERVICE_TYPE_RC;
- ep_attr.max_rdma_size = 0x10000;
- ep_attr.qos = 0;
- ep_attr.recv_completion_flags = 0;
- ep_attr.max_recv_dtos = MSG_BUF_COUNT + (burst * 3);
- ep_attr.max_request_dtos = MSG_BUF_COUNT + (burst * 3) + MAX_RDMA_RD;
- ep_attr.max_recv_iov = MSG_IOV_COUNT;
- ep_attr.max_request_iov = MSG_IOV_COUNT;
- ep_attr.max_rdma_read_in = MAX_RDMA_RD;
- ep_attr.max_rdma_read_out = MAX_RDMA_RD;
- ep_attr.request_completion_flags = DAT_COMPLETION_DEFAULT_FLAG;
- ep_attr.ep_transport_specific_count = 0;
- ep_attr.ep_transport_specific = NULL;
- ep_attr.ep_provider_specific_count = 0;
- ep_attr.ep_provider_specific = NULL;
-
- start = get_time();
- ret = dat_ep_create(h_ia, h_pz, h_dto_rcv_evd,
- h_dto_req_evd, h_conn_evd, &ep_attr, &h_ep);
- stop = get_time();
- time.epc += ((stop - start) * 1.0e6);
- time.total += time.epc;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_ep_create: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else
- LOGPRINTF("%d EP created %p \n", getpid(), h_ep);
-
- /*
- * register message buffers, establish connection, and
- * exchange DMA RMR information info via messages
- */
- ret = connect_ep(hostname, SERVER_CONN_QUAL);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error connect_ep: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else
- LOGPRINTF("%d connect_ep complete\n", getpid());
-
- /* Query EP for local and remote address information, print */
- ret = dat_ep_query(h_ep, DAT_EP_FIELD_ALL, &ep_param);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_ep_query: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else
- LOGPRINTF("%d EP queried %p \n", getpid(), h_ep);
-#if defined(_WIN32)
- printf("\n%d Query EP: LOCAL addr %s port %lld\n", getpid(),
- inet_ntoa(((struct sockaddr_in *)
- ep_param.local_ia_address_ptr)->sin_addr),
- (ep_param.local_port_qual));
-#else
- inet_ntop(AF_INET,
- &((struct sockaddr_in *)ep_param.local_ia_address_ptr)->
- sin_addr, addr_str, sizeof(addr_str));
- printf("\n%d Query EP: LOCAL addr %s port " F64x "\n", getpid(),
- addr_str, (ep_param.local_port_qual));
-#endif
-#if defined(_WIN32)
- printf("%d Query EP: REMOTE addr %s port %lld\n", getpid(),
- inet_ntoa(((struct sockaddr_in *)
- ep_param.local_ia_address_ptr)->sin_addr),
- (ep_param.remote_port_qual));
-#else
- inet_ntop(AF_INET,
- &((struct sockaddr_in *)ep_param.remote_ia_address_ptr)->
- sin_addr, addr_str, sizeof(addr_str));
- printf("%d Query EP: REMOTE addr %s port " F64x "\n", getpid(),
- addr_str, (ep_param.remote_port_qual));
-#endif
- fflush(stdout);
-
-#if CONNECT_ONLY
-#if defined(_WIN32) || defined(_WIN64)
- Sleep(1 * 1000);
-#else
- sleep(1);
-#endif
- goto cleanup;
-#endif
-
- /*********** RDMA write data *************/
- ret = do_rdma_write_with_msg();
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error do_rdma_write_with_msg: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else
- LOGPRINTF("%d do_rdma_write_with_msg complete\n", getpid());
-
- /*********** RDMA read data *************/
- ret = do_rdma_read_with_msg();
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error do_rdma_read_with_msg: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else
- LOGPRINTF("%d do_rdma_read_with_msg complete\n", getpid());
-
- /*********** PING PING messages ************/
- ret = do_ping_pong_msg();
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error do_ping_pong_msg: %s\n",
- getpid(), DT_RetToString(ret));
- goto cleanup;
- } else {
- LOGPRINTF("%d do_ping_pong_msg complete\n", getpid());
- goto complete;
- }
-
-cleanup:
- flush_evds();
- failed++;
-complete:
-
- /* disconnect and free EP resources */
- if (h_ep != DAT_HANDLE_NULL) {
- /* unregister message buffers and tear down connection */
- LOGPRINTF("%d Disconnect and Free EP %p \n", getpid(), h_ep);
- disconnect_ep();
-
- /* free EP */
- LOGPRINTF("%d Free EP %p \n", getpid(), h_ep);
- start = get_time();
- ret = dat_ep_free(h_ep);
- stop = get_time();
- time.epf += ((stop - start) * 1.0e6);
- time.total += time.epf;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing EP: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d Freed EP\n", getpid());
- h_ep = DAT_HANDLE_NULL;
- }
- }
-
- /* free EVDs */
- LOGPRINTF("%d destroy events\n", getpid());
- ret = destroy_events();
- if (ret != DAT_SUCCESS)
- fprintf(stderr, "%d Error destroy_events: %s\n",
- getpid(), DT_RetToString(ret));
- else
- LOGPRINTF("%d destroy events done\n", getpid());
-
- ret = unregister_rdma_memory();
- LOGPRINTF("%d unregister_rdma_memory \n", getpid());
- if (ret != DAT_SUCCESS)
- fprintf(stderr, "%d Error unregister_rdma_memory: %s\n",
- getpid(), DT_RetToString(ret));
- else
- LOGPRINTF("%d unregister_rdma_memory done\n", getpid());
-
- /* Free protection domain */
- LOGPRINTF("%d Freeing pz\n", getpid());
- start = get_time();
- ret = dat_pz_free(h_pz);
- stop = get_time();
- time.pzf += ((stop - start) * 1.0e6);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing PZ: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d Freed pz\n", getpid());
- h_pz = NULL;
- }
-
- /* close the device */
- LOGPRINTF("%d Closing Interface Adaptor\n", getpid());
- start = get_time();
- ret = dat_ia_close(h_ia, DAT_CLOSE_ABRUPT_FLAG);
- stop = get_time();
- time.close += ((stop - start) * 1.0e6);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d: Error Adaptor close: %s\n",
- getpid(), DT_RetToString(ret));
- } else
- LOGPRINTF("%d Closed Interface Adaptor\n", getpid());
-
- /* free rdma buffers */
- free(rbuf);
- free(sbuf);
-
- printf("\n%d: DAPL Test Complete. %s\n\n",
- getpid(), failed ? "FAILED" : "PASSED");
-
- fflush(stderr);
- fflush(stdout);
-
- if (!performance_times)
- exit(0);
-
- printf("\n%d: DAPL Test Complete.\n\n", getpid());
- printf("%d: Message RTT: Total=%10.2lf usec, %d bursts, itime=%10.2lf"
- " usec, pc=%d\n",
- getpid(), time.rtt, burst, time.rtt / burst, poll_count);
- printf("%d: RDMA write: Total=%10.2lf usec, %d bursts, itime=%10.2lf"
- " usec, pc=%d\n",
- getpid(), time.rdma_wr, burst,
- time.rdma_wr / burst, rdma_wr_poll_count);
- for (i = 0; i < MAX_RDMA_RD; i++) {
- printf("%d: RDMA read: Total=%10.2lf usec, %d bursts, "
- "itime=%10.2lf usec, pc=%d\n",
- getpid(), time.rdma_rd_total, MAX_RDMA_RD,
- time.rdma_rd[i], rdma_rd_poll_count[i]);
- }
- printf("%d: open: %10.2lf usec\n", getpid(), time.open);
- printf("%d: close: %10.2lf usec\n", getpid(), time.close);
- printf("%d: PZ create: %10.2lf usec\n", getpid(), time.pzc);
- printf("%d: PZ free: %10.2lf usec\n", getpid(), time.pzf);
- printf("%d: LMR create:%10.2lf usec\n", getpid(), time.reg);
- printf("%d: LMR free: %10.2lf usec\n", getpid(), time.unreg);
- printf("%d: EVD create:%10.2lf usec\n", getpid(), time.evdc);
- printf("%d: EVD free: %10.2lf usec\n", getpid(), time.evdf);
- if (use_cno) {
- printf("%d: CNO create: %10.2lf usec\n", getpid(), time.cnoc);
- printf("%d: CNO free: %10.2lf usec\n", getpid(), time.cnof);
- }
- printf("%d: EP create: %10.2lf usec\n", getpid(), time.epc);
- printf("%d: EP free: %10.2lf usec\n", getpid(), time.epf);
- if (!server)
- printf("%d: connect: %10.2lf usec, poll_cnt=%d\n",
- getpid(), time.conn, conn_poll_count);
- printf("%d: TOTAL: %10.2lf usec\n", getpid(), time.total);
-
-#if defined(_WIN32) || defined(_WIN64)
- WSACleanup();
-#endif
- return (0);
-}
-
-double get_time(void)
-{
- struct timeval tp;
-
- gettimeofday(&tp, NULL);
- return ((double)tp.tv_sec + (double)tp.tv_usec * 1e-6);
-}
-
-void init_data(void)
-{
- memset(rbuf, 'a', buf_len);
- memset(sbuf, 'b', buf_len);
-}
-
-DAT_RETURN
-send_msg(void *data,
- DAT_COUNT size,
- DAT_LMR_CONTEXT context,
- DAT_DTO_COOKIE cookie, DAT_COMPLETION_FLAGS flags)
-{
- DAT_LMR_TRIPLET iov;
- DAT_EVENT event;
- DAT_COUNT nmore;
- DAT_RETURN ret;
-
- iov.lmr_context = context;
-#if defined(_WIN32)
- iov.virtual_address = (DAT_VADDR) data;
-#else
- iov.virtual_address = (DAT_VADDR) (unsigned long)data;
-#endif
- iov.segment_length = size;
-
- LOGPRINTF("%d calling post_send\n", getpid());
- cookie.as_64 = 0xaaaa;
- ret = dat_ep_post_send(h_ep, 1, &iov, cookie, flags);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d: ERROR: dat_ep_post_send() %s\n",
- getpid(), DT_RetToString(ret));
- return ret;
- }
-
- if (!(flags & DAT_COMPLETION_SUPPRESS_FLAG)) {
- if (polling) {
- printf("%d Polling post send completion...\n",
- getpid());
- while (dat_evd_dequeue(h_dto_req_evd, &event) ==
- DAT_QUEUE_EMPTY) ;
- } else {
- LOGPRINTF("%d waiting for post_send completion event\n",
- getpid());
- if (use_cno) {
- DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;
- ret =
- dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);
- LOGPRINTF("%d cno wait return evd_handle=%p\n",
- getpid(), evd);
- if (evd != h_dto_req_evd) {
- fprintf(stderr,
- "%d Error waiting on h_dto_cno: evd != h_dto_req_evd\n",
- getpid());
- return (DAT_ABORT);
- }
- }
- /* use wait to dequeue */
- ret =
- dat_evd_wait(h_dto_req_evd, DTO_TIMEOUT, 1, &event,
- &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d: ERROR: DTO dat_evd_wait() %s\n",
- getpid(), DT_RetToString(ret));
- return ret;
- }
- }
-
- /* validate event number, len, cookie, and status */
- if (event.event_number != DAT_DTO_COMPLETION_EVENT) {
- fprintf(stderr, "%d: ERROR: DTO event number %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
-
- if ((event.event_data.dto_completion_event_data.
- transfered_length != size)
- || (event.event_data.dto_completion_event_data.user_cookie.
- as_64 != 0xaaaa)) {
- fprintf(stderr,
- "%d: ERROR: DTO len %d or cookie " F64x " \n",
- getpid(),
- event.event_data.dto_completion_event_data.
- transfered_length,
- event.event_data.dto_completion_event_data.
- user_cookie.as_64);
- return (DAT_ABORT);
-
- }
- if (event.event_data.dto_completion_event_data.status !=
- DAT_SUCCESS) {
- fprintf(stderr, "%d: ERROR: DTO event status %s\n",
- getpid(), DT_RetToString(ret));
- return (DAT_ABORT);
- }
- }
-
- return DAT_SUCCESS;
-}
-
-DAT_RETURN connect_ep(char *hostname, DAT_CONN_QUAL conn_id)
-{
- DAT_SOCK_ADDR remote_addr;
- DAT_RETURN ret;
- DAT_REGION_DESCRIPTION region;
- DAT_EVENT event;
- DAT_COUNT nmore;
- DAT_LMR_TRIPLET l_iov;
- DAT_RMR_TRIPLET r_iov;
- DAT_DTO_COOKIE cookie;
- int i;
- unsigned char *buf;
- DAT_CR_PARAM cr_param = { 0 };
- unsigned char pdata[48] = { 0 };
-
- /* Register send message buffer */
- LOGPRINTF("%d Registering send Message Buffer %p, len %d\n",
- getpid(), &rmr_send_msg, (int)sizeof(DAT_RMR_TRIPLET));
- region.for_va = &rmr_send_msg;
- ret = dat_lmr_create(h_ia,
- DAT_MEM_TYPE_VIRTUAL,
- region,
- sizeof(DAT_RMR_TRIPLET),
- h_pz,
- DAT_MEM_PRIV_LOCAL_WRITE_FLAG,
- DAT_VA_TYPE_VA,
- &h_lmr_send_msg,
- &lmr_context_send_msg,
- &rmr_context_send_msg,
- ®istered_size_send_msg,
- ®istered_addr_send_msg);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error registering send msg buffer: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d Registered send Message Buffer %p \n",
- getpid(), region.for_va);
-
- /* Register Receive buffers */
- LOGPRINTF("%d Registering Receive Message Buffer %p\n",
- getpid(), rmr_recv_msg);
- region.for_va = rmr_recv_msg;
- ret = dat_lmr_create(h_ia,
- DAT_MEM_TYPE_VIRTUAL,
- region,
- sizeof(DAT_RMR_TRIPLET) * MSG_BUF_COUNT,
- h_pz,
- DAT_MEM_PRIV_LOCAL_WRITE_FLAG,
- DAT_VA_TYPE_VA,
- &h_lmr_recv_msg,
- &lmr_context_recv_msg,
- &rmr_context_recv_msg,
- ®istered_size_recv_msg,
- ®istered_addr_recv_msg);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error registering recv msg buffer: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d Registered Receive Message Buffer %p\n",
- getpid(), region.for_va);
-
- for (i = 0; i < MSG_BUF_COUNT; i++) {
- cookie.as_64 = i;
- l_iov.lmr_context = lmr_context_recv_msg;
-#if defined(_WIN32)
- l_iov.virtual_address = (DAT_VADDR) & rmr_recv_msg[i];
-#else
- l_iov.virtual_address =
- (DAT_VADDR) (unsigned long)&rmr_recv_msg[i];
-#endif
- l_iov.segment_length = sizeof(DAT_RMR_TRIPLET);
-
- LOGPRINTF("%d Posting Receive Message Buffer %p\n",
- getpid(), &rmr_recv_msg[i]);
- ret = dat_ep_post_recv(h_ep,
- 1,
- &l_iov,
- cookie, DAT_COMPLETION_DEFAULT_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error registering recv msg buffer: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d Registered Receive Message Buffer %p\n",
- getpid(), region.for_va);
-
- }
-
- /* setup receive rdma buffer to initial string to be overwritten */
- strcpy((char *)rbuf, "blah, blah, blah\n");
-
- /* clear event structure */
- memset(&event, 0, sizeof(DAT_EVENT));
-
- if (server) { /* SERVER */
-
- /* create the service point for server listen */
- LOGPRINTF("%d Creating service point for listen\n", getpid());
- ret = dat_psp_create(h_ia,
- conn_id,
- h_cr_evd, DAT_PSP_CONSUMER_FLAG, &h_psp);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_psp_create: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d dat_psp_created for server listen\n",
- getpid());
-
- printf("%d Server waiting for connect request on port " F64x
- "\n", getpid(), conn_id);
-
- ret = dat_evd_wait(h_cr_evd, SERVER_TIMEOUT, 1, &event, &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_wait: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d dat_evd_wait for cr_evd completed\n",
- getpid());
-
- if (event.event_number != DAT_CONNECTION_REQUEST_EVENT) {
- fprintf(stderr, "%d Error unexpected cr event : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
- if ((event.event_data.cr_arrival_event_data.conn_qual !=
- SERVER_CONN_QUAL)
- || (event.event_data.cr_arrival_event_data.sp_handle.
- psp_handle != h_psp)) {
- fprintf(stderr, "%d Error wrong cr event data : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
-
- /* use to test rdma_cma timeout logic */
-#if defined(_WIN32) || defined(_WIN64)
- if (delay)
- Sleep(delay * 1000);
-#else
- if (delay)
- sleep(delay);
-#endif
-
- /* accept connect request from client */
- h_cr = event.event_data.cr_arrival_event_data.cr_handle;
- LOGPRINTF("%d Accepting connect request from client\n",
- getpid());
-
- /* private data - check and send it back */
- dat_cr_query(h_cr, DAT_CSP_FIELD_ALL, &cr_param);
-
- buf = (unsigned char *)cr_param.private_data;
- LOGPRINTF("%d CONN REQUEST Private Data %p[0]=%d [47]=%d\n",
- getpid(), buf, buf[0], buf[47]);
- for (i = 0; i < 48; i++) {
- if (buf[i] != i + 1) {
- fprintf(stderr, "%d Error with CONNECT REQUEST"
- " private data: %p[%d]=%d s/be %d\n",
- getpid(), buf, i, buf[i], i + 1);
- dat_cr_reject(h_cr, 0, NULL);
- return (DAT_ABORT);
- }
- buf[i]++; /* change for trip back */
- }
-
-#ifdef TEST_REJECT_WITH_PRIVATE_DATA
- printf("%d REJECT request with 48 bytes of private data\n",
- getpid());
- ret = dat_cr_reject(h_cr, 48, cr_param.private_data);
- printf("\n%d: DAPL Test Complete. %s\n\n",
- getpid(), ret ? "FAILED" : "PASSED");
- exit(0);
-#endif
-
- ret = dat_cr_accept(h_cr, h_ep, 48, cr_param.private_data);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_cr_accept: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d dat_cr_accept completed\n", getpid());
- } else { /* CLIENT */
- struct addrinfo *target;
- int rval;
-
-#if defined(_WIN32) || defined(_WIN64)
- if ((rval = getaddrinfo(hostname, "ftp", NULL, &target)) != 0) {
- printf("\n remote name resolution failed! %s\n",
- gai_strerror(rval));
- exit(1);
- }
- rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;
-#else
- if (getaddrinfo(hostname, NULL, NULL, &target) != 0) {
- perror("\n remote name resolution failed!");
- exit(1);
- }
- rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;
-#endif
- printf("%d Server Name: %s \n", getpid(), hostname);
- printf("%d Server Net Address: %d.%d.%d.%d port " F64x "\n",
- getpid(), (rval >> 0) & 0xff, (rval >> 8) & 0xff,
- (rval >> 16) & 0xff, (rval >> 24) & 0xff, conn_id);
-
- remote_addr = *((DAT_IA_ADDRESS_PTR) target->ai_addr);
- freeaddrinfo(target);
-
- for (i = 0; i < 48; i++) /* simple pattern in private data */
- pdata[i] = i + 1;
-
- LOGPRINTF("%d Connecting to server\n", getpid());
- start = get_time();
- ret = dat_ep_connect(h_ep,
- &remote_addr,
- conn_id,
- CONN_TIMEOUT,
- 48,
- (DAT_PVOID) pdata,
- 0, DAT_CONNECT_DEFAULT_FLAG);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_ep_connect: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d dat_ep_connect completed\n", getpid());
- }
-
- printf("%d Waiting for connect response\n", getpid());
-
- if (polling)
- while (DAT_GET_TYPE(dat_evd_dequeue(h_conn_evd, &event)) ==
- DAT_QUEUE_EMPTY)
- conn_poll_count++;
- else
- ret = dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE,
- 1, &event, &nmore);
-
- if (!server) {
- stop = get_time();
- time.conn += ((stop - start) * 1.0e6);
- }
-
-#ifdef TEST_REJECT_WITH_PRIVATE_DATA
- if (event.event_number != DAT_CONNECTION_EVENT_PEER_REJECTED) {
- fprintf(stderr, "%d expected conn reject event : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
- /* get the reject private data and validate */
- buf = (unsigned char *)event.event_data.connect_event_data.private_data;
- printf("%d Received REJECT with private data %p[0]=%d [47]=%d\n",
- getpid(), buf, buf[0], buf[47]);
- for (i = 0; i < 48; i++) {
- if (buf[i] != i + 2) {
- fprintf(stderr, "%d client: Error with REJECT event"
- " private data: %p[%d]=%d s/be %d\n",
- getpid(), buf, i, buf[i], i + 2);
- dat_ep_disconnect(h_ep, DAT_CLOSE_ABRUPT_FLAG);
- return (DAT_ABORT);
- }
- }
- printf("\n%d: DAPL Test Complete. PASSED\n\n", getpid());
- exit(0);
-#endif
-
- if (event.event_number != DAT_CONNECTION_EVENT_ESTABLISHED) {
- fprintf(stderr, "%d Error unexpected conn event : 0x%x %s\n",
- getpid(), event.event_number,
- DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
-
- /* check private data back from server */
- if (!server) {
- buf =
- (unsigned char *)event.event_data.connect_event_data.
- private_data;
- LOGPRINTF("%d CONN Private Data %p[0]=%d [47]=%d\n", getpid(),
- buf, buf[0], buf[47]);
- for (i = 0; i < 48; i++) {
- if (buf[i] != i + 2) {
- fprintf(stderr, "%d Error with CONNECT event"
- " private data: %p[%d]=%d s/be %d\n",
- getpid(), buf, i, buf[i], i + 2);
- dat_ep_disconnect(h_ep, DAT_CLOSE_ABRUPT_FLAG);
- LOGPRINTF
- ("%d waiting for disconnect event...\n",
- getpid());
- dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE,
- 1, &event, &nmore);
- return (DAT_ABORT);
- }
- }
- }
-
- printf("\n%d CONNECTED!\n\n", getpid());
- connected = 1;
-
-#if CONNECT_ONLY
- return 0;
-#endif
-
- /*
- * Setup our remote memory and tell the other side about it
- */
- rmr_send_msg.virtual_address = htonll((DAT_VADDR) (uintptr_t) rbuf);
- rmr_send_msg.segment_length = htonl(RDMA_BUFFER_SIZE);
- rmr_send_msg.rmr_context = htonl(rmr_context_recv);
-
- printf("%d Send RMR msg to remote: r_key_ctx=0x%x,va=%p,len=0x%x\n",
- getpid(), rmr_context_recv, rbuf, RDMA_BUFFER_SIZE);
-
- ret = send_msg(&rmr_send_msg,
- sizeof(DAT_RMR_TRIPLET),
- lmr_context_send_msg,
- cookie, DAT_COMPLETION_SUPPRESS_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error send_msg: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else
- LOGPRINTF("%d send_msg completed\n", getpid());
-
- /*
- * Wait for remote RMR information for RDMA
- */
- if (polling) {
- printf("%d Polling for remote to send RMR data\n", getpid());
- while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==
- DAT_QUEUE_EMPTY) ;
- } else {
- printf("%d Waiting for remote to send RMR data\n", getpid());
- if (use_cno) {
- DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;
- ret = dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);
- LOGPRINTF("%d cno wait return evd_handle=%p\n",
- getpid(), evd);
- if (evd != h_dto_rcv_evd) {
- fprintf(stderr,
- "%d Error waiting on h_dto_cno: evd != h_dto_rcv_evd\n",
- getpid());
- return (DAT_ABORT);
- }
- }
- /* use wait to dequeue */
- ret =
- dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event, &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error waiting on h_dto_rcv_evd: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d dat_evd_wait h_dto_rcv_evd completed\n",
- getpid());
- }
- }
-
- printf("%d remote RMR data arrived!\n", getpid());
-
- if (event.event_number != DAT_DTO_COMPLETION_EVENT) {
- fprintf(stderr, "%d Error unexpected DTO event : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
- if ((event.event_data.dto_completion_event_data.transfered_length !=
- sizeof(DAT_RMR_TRIPLET)) ||
- (event.event_data.dto_completion_event_data.user_cookie.as_64 !=
- recv_msg_index)) {
- fprintf(stderr,
- "ERR recv event: len=%d cookie=" F64x
- " expected %d/%d\n",
- (int)event.event_data.dto_completion_event_data.
- transfered_length,
- event.event_data.dto_completion_event_data.user_cookie.
- as_64, (int)sizeof(DAT_RMR_TRIPLET), recv_msg_index);
- return (DAT_ABORT);
- }
-
- /* swap received RMR msg: network order to host order */
- r_iov = rmr_recv_msg[recv_msg_index];
- rmr_recv_msg[recv_msg_index].rmr_context = ntohl(r_iov.rmr_context);
- rmr_recv_msg[recv_msg_index].virtual_address =
- ntohll(r_iov.virtual_address);
- rmr_recv_msg[recv_msg_index].segment_length =
- ntohl(r_iov.segment_length);
-
- printf("%d Received RMR from remote: "
- "r_iov: r_key_ctx=%x,va=" F64x ",len=0x%x\n",
- getpid(), rmr_recv_msg[recv_msg_index].rmr_context,
- rmr_recv_msg[recv_msg_index].virtual_address,
- rmr_recv_msg[recv_msg_index].segment_length);
-
- recv_msg_index++;
-
- return (DAT_SUCCESS);
-}
-
-void disconnect_ep(void)
-{
- DAT_RETURN ret;
- DAT_EVENT event;
- DAT_COUNT nmore;
-
- if (connected) {
-
- /*
- * Only the client needs to call disconnect. The server _should_ be able
- * to just wait on the EVD associated with connection events for a
- * disconnect request and then exit.
- */
- if (!server) {
- LOGPRINTF("%d dat_ep_disconnect\n", getpid());
- ret = dat_ep_disconnect(h_ep, DAT_CLOSE_DEFAULT);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error dat_ep_disconnect: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d dat_ep_disconnect completed\n",
- getpid());
- }
- } else {
- LOGPRINTF("%d Server waiting for disconnect...\n",
- getpid());
- }
-
- ret =
- dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE, 1, &event,
- &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_wait: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d dat_evd_wait for h_conn_evd completed\n",
- getpid());
- }
- }
-
- /* destroy service point */
- if ((server) && (h_psp != DAT_HANDLE_NULL)) {
- ret = dat_psp_free(h_psp);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_psp_free: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d dat_psp_free completed\n", getpid());
- }
- }
-
- /* Unregister Send message Buffer */
- if (h_lmr_send_msg != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Unregister send message h_lmr %p \n", getpid(),
- h_lmr_send_msg);
- ret = dat_lmr_free(h_lmr_send_msg);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error deregistering send msg mr: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d Unregistered send message Buffer\n",
- getpid());
- h_lmr_send_msg = NULL;
- }
- }
-
- /* Unregister recv message Buffer */
- if (h_lmr_recv_msg != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Unregister recv message h_lmr %p \n", getpid(),
- h_lmr_recv_msg);
- ret = dat_lmr_free(h_lmr_recv_msg);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error deregistering recv msg mr: %s\n",
- getpid(), DT_RetToString(ret));
- } else {
- LOGPRINTF("%d Unregistered recv message Buffer\n",
- getpid());
- h_lmr_recv_msg = NULL;
- }
- }
- return;
-}
-
-DAT_RETURN do_rdma_write_with_msg(void)
-{
- DAT_EVENT event;
- DAT_COUNT nmore;
- DAT_LMR_TRIPLET l_iov[MSG_IOV_COUNT];
- DAT_RMR_TRIPLET r_iov;
- DAT_DTO_COOKIE cookie;
- DAT_RETURN ret;
- int i;
-
- printf("\n %d RDMA WRITE DATA with SEND MSG\n\n", getpid());
-
- cookie.as_64 = 0x5555;
-
- if (recv_msg_index >= MSG_BUF_COUNT)
- return (DAT_ABORT);
-
- /* get RMR information from previously received message */
- r_iov = rmr_recv_msg[recv_msg_index - 1];
-
- if (server)
- strcpy((char *)sbuf, "server RDMA write data...");
- else
- strcpy((char *)sbuf, "client RDMA write data...");
-
- for (i = 0; i < MSG_IOV_COUNT; i++) {
- l_iov[i].lmr_context = lmr_context_send;
- l_iov[i].segment_length = buf_len / MSG_IOV_COUNT;
- l_iov[i].virtual_address = (DAT_VADDR) (uintptr_t)
- (&sbuf[l_iov[i].segment_length * i]);
-
- LOGPRINTF("%d rdma_write iov[%d] buf=%p,len=%d\n",
- getpid(), i, &sbuf[l_iov[i].segment_length * i],
- l_iov[i].segment_length);
- }
-
- start = get_time();
- for (i = 0; i < burst; i++) {
- cookie.as_64 = 0x9999;
- ret = dat_ep_post_rdma_write(h_ep, // ep_handle
- MSG_IOV_COUNT, // num_segments
- l_iov, // LMR
- cookie, // user_cookie
- &r_iov, // RMR
- DAT_COMPLETION_SUPPRESS_FLAG);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d: ERROR: dat_ep_post_rdma_write() %s\n",
- getpid(), DT_RetToString(ret));
- return (DAT_ABORT);
- }
- LOGPRINTF("%d rdma_write # %d completed\n", getpid(), i + 1);
- }
-
- /*
- * Send RMR information a 2nd time to indicate completion
- * NOTE: already swapped to network order in connect_ep
- */
- printf("%d Sending RDMA WRITE completion message\n", getpid());
-
- ret = send_msg(&rmr_send_msg,
- sizeof(DAT_RMR_TRIPLET),
- lmr_context_send_msg,
- cookie, DAT_COMPLETION_SUPPRESS_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error send_msg: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d send_msg completed\n", getpid());
- }
-
- /*
- * Collect first event, write completion or the inbound recv
- */
- if (polling) {
- while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==
- DAT_QUEUE_EMPTY)
- rdma_wr_poll_count++;
- } else {
- LOGPRINTF("%d waiting for message receive event\n", getpid());
- if (use_cno) {
- DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;
- ret = dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);
- LOGPRINTF("%d cno wait return evd_handle=%p\n",
- getpid(), evd);
- if (evd != h_dto_rcv_evd) {
- fprintf(stderr,
- "%d Error waiting on h_dto_cno: "
- "evd != h_dto_rcv_evd\n", getpid());
- return (ret);
- }
- }
- /* use wait to dequeue */
- ret =
- dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event, &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d: ERROR: DTO dat_evd_wait() %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- }
- }
- stop = get_time();
- time.rdma_wr = ((stop - start) * 1.0e6);
-
- /* validate event number and status */
- printf("%d inbound rdma_write; send message arrived!\n", getpid());
- if (event.event_number != DAT_DTO_COMPLETION_EVENT) {
- fprintf(stderr, "%d Error unexpected DTO event : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
-
- if ((event.event_data.dto_completion_event_data.transfered_length !=
- sizeof(DAT_RMR_TRIPLET))
- || (event.event_data.dto_completion_event_data.user_cookie.as_64 !=
- recv_msg_index)) {
- fprintf(stderr,
- "unexpected event data for receive: len=%d cookie=" F64x
- " exp %d/%d\n",
- (int)event.event_data.dto_completion_event_data.
- transfered_length,
- event.event_data.dto_completion_event_data.user_cookie.
- as_64, (int)sizeof(DAT_RMR_TRIPLET), recv_msg_index);
-
- return (DAT_ABORT);
- }
-
- /* swap received RMR msg: network order to host order */
- r_iov = rmr_recv_msg[recv_msg_index];
- rmr_recv_msg[recv_msg_index].virtual_address =
- ntohll(rmr_recv_msg[recv_msg_index].virtual_address);
- rmr_recv_msg[recv_msg_index].segment_length =
- ntohl(rmr_recv_msg[recv_msg_index].segment_length);
- rmr_recv_msg[recv_msg_index].rmr_context =
- ntohl(rmr_recv_msg[recv_msg_index].rmr_context);
-
- printf("%d Received RMR from remote: "
- "r_iov: r_key_ctx=%x,va=" F64x ",len=0x%x\n",
- getpid(), rmr_recv_msg[recv_msg_index].rmr_context,
- rmr_recv_msg[recv_msg_index].virtual_address,
- rmr_recv_msg[recv_msg_index].segment_length);
-
- LOGPRINTF("%d inbound rdma_write; send msg event SUCCESS!!\n",
- getpid());
-
- printf("%d %s RDMA write buffer contains: %s\n",
- getpid(), server ? "SERVER:" : "CLIENT:", rbuf);
-
- recv_msg_index++;
-
- return (DAT_SUCCESS);
-}
-
-DAT_RETURN do_rdma_read_with_msg(void)
-{
- DAT_EVENT event;
- DAT_COUNT nmore;
- DAT_LMR_TRIPLET l_iov;
- DAT_RMR_TRIPLET r_iov;
- DAT_DTO_COOKIE cookie;
- DAT_RETURN ret;
- int i;
-
- printf("\n %d RDMA READ DATA with SEND MSG\n\n", getpid());
-
- if (recv_msg_index >= MSG_BUF_COUNT)
- return (DAT_ABORT);
-
- /* get RMR information from previously received message */
- r_iov = rmr_recv_msg[recv_msg_index - 1];
-
- /* setup rdma read buffer to initial string to be overwritten */
- strcpy((char *)sbuf, "blah, blah, blah\n");
-
- if (server)
- strcpy((char *)rbuf, "server RDMA read data...");
- else
- strcpy((char *)rbuf, "client RDMA read data...");
-
- l_iov.lmr_context = lmr_context_send;
- l_iov.virtual_address = (DAT_VADDR) (uintptr_t) sbuf;
- l_iov.segment_length = buf_len;
-
- for (i = 0; i < MAX_RDMA_RD; i++) {
- cookie.as_64 = 0x9999;
- start = get_time();
- ret = dat_ep_post_rdma_read(h_ep, // ep_handle
- 1, // num_segments
- &l_iov, // LMR
- cookie, // user_cookie
- &r_iov, // RMR
- DAT_COMPLETION_DEFAULT_FLAG);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d: ERROR: dat_ep_post_rdma_read() %s\n",
- getpid(), DT_RetToString(ret));
- return (DAT_ABORT);
- }
-
- if (polling) {
- while (dat_evd_dequeue(h_dto_req_evd, &event) ==
- DAT_QUEUE_EMPTY)
- rdma_rd_poll_count[i]++;
- } else {
- LOGPRINTF("%d waiting for rdma_read completion event\n",
- getpid());
- if (use_cno) {
- DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;
- ret =
- dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);
- LOGPRINTF("%d cno wait return evd_handle=%p\n",
- getpid(), evd);
- if (evd != h_dto_req_evd) {
- fprintf(stderr,
- "%d Error waiting on h_dto_cno: evd != h_dto_req_evd\n",
- getpid());
- return (DAT_ABORT);
- }
- }
- /* use wait to dequeue */
- ret =
- dat_evd_wait(h_dto_req_evd, DTO_TIMEOUT, 1, &event,
- &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d: ERROR: DTO dat_evd_wait() %s\n",
- getpid(), DT_RetToString(ret));
- return ret;
- }
- }
- /* validate event number, len, cookie, and status */
- if (event.event_number != DAT_DTO_COMPLETION_EVENT) {
- fprintf(stderr, "%d: ERROR: DTO event number %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
- if ((event.event_data.dto_completion_event_data.
- transfered_length != buf_len)
- || (event.event_data.dto_completion_event_data.user_cookie.
- as_64 != 0x9999)) {
- fprintf(stderr,
- "%d: ERROR: DTO len %d or cookie " F64x "\n",
- getpid(),
- event.event_data.dto_completion_event_data.
- transfered_length,
- event.event_data.dto_completion_event_data.
- user_cookie.as_64);
- return (DAT_ABORT);
- }
- if (event.event_data.dto_completion_event_data.status !=
- DAT_SUCCESS) {
- fprintf(stderr, "%d: ERROR: DTO event status %s\n",
- getpid(), DT_RetToString(ret));
- return (DAT_ABORT);
- }
- stop = get_time();
- time.rdma_rd[i] = ((stop - start) * 1.0e6);
- time.rdma_rd_total += time.rdma_rd[i];
-
- LOGPRINTF("%d rdma_read # %d completed\n", getpid(), i + 1);
- }
-
- /*
- * Send RMR information a 3rd time to indicate completion
- * NOTE: already swapped to network order in connect_ep
- */
- printf("%d Sending RDMA read completion message\n", getpid());
-
- ret = send_msg(&rmr_send_msg,
- sizeof(DAT_RMR_TRIPLET),
- lmr_context_send_msg,
- cookie, DAT_COMPLETION_SUPPRESS_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error send_msg: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d send_msg completed\n", getpid());
- }
-
- /*
- * Collect first event, write completion or the inbound recv with immed
- */
- printf("%d Waiting for inbound message....\n", getpid());
- if (polling) {
- while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==
- DAT_QUEUE_EMPTY) ;
- } else {
- LOGPRINTF("%d waiting for message receive event\n", getpid());
- if (use_cno) {
- DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;
- ret = dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);
- LOGPRINTF("%d cno wait return evd_handle=%p\n",
- getpid(), evd);
- if (evd != h_dto_rcv_evd) {
- fprintf(stderr,
- "%d Error waiting on h_dto_cno: evd != h_dto_rcv_evd\n",
- getpid());
- return (ret);
- }
- }
- /* use wait to dequeue */
- ret =
- dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event, &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d: ERROR: DTO dat_evd_wait() %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- }
- }
-
- /* validate event number and status */
- printf("%d inbound rdma_read; send message arrived!\n", getpid());
- if (event.event_number != DAT_DTO_COMPLETION_EVENT) {
- fprintf(stderr, "%d Error unexpected DTO event : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
-
- if ((event.event_data.dto_completion_event_data.transfered_length !=
- sizeof(DAT_RMR_TRIPLET))
- || (event.event_data.dto_completion_event_data.user_cookie.as_64 !=
- recv_msg_index)) {
-
- fprintf(stderr,
- "unexpected event data for receive: len=%d cookie=" F64x
- " exp %d/%d\n",
- (int)event.event_data.dto_completion_event_data.
- transfered_length,
- event.event_data.dto_completion_event_data.user_cookie.
- as_64, (int)sizeof(DAT_RMR_TRIPLET), recv_msg_index);
-
- return (DAT_ABORT);
- }
-
- /* swap received RMR msg: network order to host order */
- r_iov = rmr_recv_msg[recv_msg_index];
- rmr_recv_msg[recv_msg_index].virtual_address =
- ntohll(rmr_recv_msg[recv_msg_index].virtual_address);
- rmr_recv_msg[recv_msg_index].segment_length =
- ntohl(rmr_recv_msg[recv_msg_index].segment_length);
- rmr_recv_msg[recv_msg_index].rmr_context =
- ntohl(rmr_recv_msg[recv_msg_index].rmr_context);
-
- printf("%d Received RMR from remote: "
- "r_iov: r_key_ctx=%x,va=" F64x ",len=0x%x\n",
- getpid(), rmr_recv_msg[recv_msg_index].rmr_context,
- rmr_recv_msg[recv_msg_index].virtual_address,
- rmr_recv_msg[recv_msg_index].segment_length);
-
- LOGPRINTF("%d inbound rdma_write; send msg event SUCCESS!!\n",
- getpid());
-
- printf("%d %s RCV RDMA read buffer contains: %s\n",
- getpid(), server ? "SERVER:" : "CLIENT:", sbuf);
-
- recv_msg_index++;
-
- return (DAT_SUCCESS);
-}
-
-DAT_RETURN do_ping_pong_msg()
-{
- DAT_EVENT event;
- DAT_COUNT nmore;
- DAT_DTO_COOKIE cookie;
- DAT_LMR_TRIPLET l_iov;
- DAT_RETURN ret;
- int i;
- char *snd_buf;
- char *rcv_buf;
-
- printf("\n %d PING DATA with SEND MSG\n\n", getpid());
-
- snd_buf = sbuf;
- rcv_buf = rbuf;
-
- /* pre-post all buffers */
- for (i = 0; i < burst; i++) {
- burst_msg_posted++;
- cookie.as_64 = i;
- l_iov.lmr_context = lmr_context_recv;
- l_iov.virtual_address = (DAT_VADDR) (uintptr_t) rcv_buf;
- l_iov.segment_length = buf_len;
-
- LOGPRINTF("%d Pre-posting Receive Message Buffers %p\n",
- getpid(), rcv_buf);
-
- ret = dat_ep_post_recv(h_ep,
- 1,
- &l_iov,
- cookie, DAT_COMPLETION_DEFAULT_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error posting recv msg buffer: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Posted Receive Message Buffer %p\n",
- getpid(), rcv_buf);
- }
-
- /* next buffer */
- rcv_buf += buf_len;
- }
-#if defined(_WIN32) || defined(_WIN64)
- Sleep(1000);
-#else
- sleep(1);
-#endif
-
- /* Initialize recv_buf and index to beginning */
- rcv_buf = rbuf;
- burst_msg_index = 0;
-
- /* client ping 0x55, server pong 0xAA in first byte */
- start = get_time();
- for (i = 0; i < burst; i++) {
- /* walk the send and recv buffers */
- if (!server) {
- *snd_buf = 0x55;
-
- LOGPRINTF("%d %s SND buffer %p contains: 0x%x len=%d\n",
- getpid(), server ? "SERVER:" : "CLIENT:",
- snd_buf, *snd_buf, buf_len);
-
- ret = send_msg(snd_buf,
- buf_len,
- lmr_context_send,
- cookie, DAT_COMPLETION_SUPPRESS_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error send_msg: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d send_msg completed\n", getpid());
- }
- }
-
- /* Wait for recv message */
- if (polling) {
- poll_count = 0;
- LOGPRINTF("%d Polling for message receive event\n",
- getpid());
- while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==
- DAT_QUEUE_EMPTY)
- poll_count++;
- } else {
- LOGPRINTF("%d waiting for message receive event\n",
- getpid());
- if (use_cno) {
- DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;
- ret =
- dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);
- LOGPRINTF("%d cno wait return evd_handle=%p\n",
- getpid(), evd);
- if (evd != h_dto_rcv_evd) {
- fprintf(stderr,
- "%d Error waiting on h_dto_cno: evd != h_dto_rcv_evd\n",
- getpid());
- return (ret);
- }
- }
- /* use wait to dequeue */
- ret =
- dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event,
- &nmore);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d: ERROR: DTO dat_evd_wait() %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- }
- }
- /* start timer after first message arrives on server */
- if (i == 0) {
- start = get_time();
- }
- /* validate event number and status */
- LOGPRINTF("%d inbound message; message arrived!\n", getpid());
- if (event.event_number != DAT_DTO_COMPLETION_EVENT) {
- fprintf(stderr, "%d Error unexpected DTO event : %s\n",
- getpid(), DT_EventToSTr(event.event_number));
- return (DAT_ABORT);
- }
- if ((event.event_data.dto_completion_event_data.
- transfered_length != buf_len)
- || (event.event_data.dto_completion_event_data.user_cookie.
- as_64 != burst_msg_index)) {
- fprintf(stderr,
- "ERR: recv event: len=%d cookie=" F64x
- " exp %d/%d\n",
- (int)event.event_data.dto_completion_event_data.
- transfered_length,
- event.event_data.dto_completion_event_data.
- user_cookie.as_64, (int)buf_len,
- (int)burst_msg_index);
-
- return (DAT_ABORT);
- }
-
- LOGPRINTF("%d %s RCV buffer %p contains: 0x%x len=%d\n",
- getpid(), server ? "SERVER:" : "CLIENT:",
- rcv_buf, *rcv_buf, buf_len);
-
- burst_msg_index++;
-
- /* If server, change data and send it back to client */
- if (server) {
- *snd_buf = 0xaa;
-
- LOGPRINTF("%d %s SND buffer %p contains: 0x%x len=%d\n",
- getpid(), server ? "SERVER:" : "CLIENT:",
- snd_buf, *snd_buf, buf_len);
-
- ret = send_msg(snd_buf,
- buf_len,
- lmr_context_send,
- cookie, DAT_COMPLETION_SUPPRESS_FLAG);
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error send_msg: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d send_msg completed\n", getpid());
- }
- }
-
- /* next buffers */
- rcv_buf += buf_len;
- snd_buf += buf_len;
- }
- stop = get_time();
- time.rtt = ((stop - start) * 1.0e6);
-
- return (DAT_SUCCESS);
-}
-
-/* Register RDMA Receive buffer */
-DAT_RETURN register_rdma_memory(void)
-{
- DAT_RETURN ret;
- DAT_REGION_DESCRIPTION region;
-
- region.for_va = rbuf;
- start = get_time();
- ret = dat_lmr_create(h_ia,
- DAT_MEM_TYPE_VIRTUAL,
- region,
- buf_len * (burst+1),
- h_pz,
- DAT_MEM_PRIV_ALL_FLAG,
- DAT_VA_TYPE_VA,
- &h_lmr_recv,
- &lmr_context_recv,
- &rmr_context_recv,
- ®istered_size_recv, ®istered_addr_recv);
- stop = get_time();
- time.reg += ((stop - start) * 1.0e6);
- time.total += time.reg;
-
- if (ret != DAT_SUCCESS) {
- fprintf(stderr,
- "%d Error registering Receive RDMA buffer: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Registered Receive RDMA Buffer %p\n",
- getpid(), region.for_va);
- }
-
- /* Register RDMA Send buffer */
- region.for_va = sbuf;
- ret = dat_lmr_create(h_ia,
- DAT_MEM_TYPE_VIRTUAL,
- region,
- buf_len * (burst + 1),
- h_pz,
- DAT_MEM_PRIV_ALL_FLAG,
- DAT_VA_TYPE_VA,
- &h_lmr_send,
- &lmr_context_send,
- &rmr_context_send,
- ®istered_size_send, ®istered_addr_send);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error registering send RDMA buffer: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Registered Send RDMA Buffer %p\n",
- getpid(), region.for_va);
- }
-
- return DAT_SUCCESS;
-}
-
-/*
- * Unregister RDMA memory
- */
-DAT_RETURN unregister_rdma_memory(void)
-{
- DAT_RETURN ret;
-
- /* Unregister Recv Buffer */
- if (h_lmr_recv != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Unregister h_lmr %p \n", getpid(), h_lmr_recv);
- start = get_time();
- ret = dat_lmr_free(h_lmr_recv);
- stop = get_time();
- time.unreg += ((stop - start) * 1.0e6);
- time.total += time.unreg;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error deregistering recv mr: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Unregistered Recv Buffer\n", getpid());
- h_lmr_recv = NULL;
- }
- }
-
- /* Unregister Send Buffer */
- if (h_lmr_send != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Unregister h_lmr %p \n", getpid(), h_lmr_send);
- ret = dat_lmr_free(h_lmr_send);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error deregistering send mr: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Unregistered send Buffer\n", getpid());
- h_lmr_send = NULL;
- }
- }
- return DAT_SUCCESS;
-}
-
- /*
- * Create CNO, CR, CONN, and DTO events
- */
-DAT_RETURN create_events(void)
-{
- DAT_RETURN ret;
- DAT_EVD_PARAM param;
-
- /* create CNO */
- if (use_cno) {
- start = get_time();
-#if defined(_WIN32) || defined(_WIN64)
- {
- DAT_OS_WAIT_PROXY_AGENT pa = { NULL, NULL };
- ret = dat_cno_create(h_ia, pa, &h_dto_cno);
- }
-#else
- ret =
- dat_cno_create(h_ia, DAT_OS_WAIT_PROXY_AGENT_NULL,
- &h_dto_cno);
-#endif
- stop = get_time();
- time.cnoc += ((stop - start) * 1.0e6);
- time.total += time.cnoc;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_cno_create: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d cr_evd created, %p\n", getpid(),
- h_dto_cno);
- }
- }
-
- /* create cr EVD */
- start = get_time();
- ret =
- dat_evd_create(h_ia, 10, DAT_HANDLE_NULL, DAT_EVD_CR_FLAG,
- &h_cr_evd);
- stop = get_time();
- time.evdc += ((stop - start) * 1.0e6);
- time.total += time.evdc;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_create: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d cr_evd created %p\n", getpid(), h_cr_evd);
- }
-
- /* create conn EVD */
- ret = dat_evd_create(h_ia,
- 10,
- DAT_HANDLE_NULL,
- DAT_EVD_CONNECTION_FLAG, &h_conn_evd);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_create: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d con_evd created %p\n", getpid(), h_conn_evd);
- }
-
- /* create dto SND EVD, with CNO if use_cno was set */
- ret = dat_evd_create(h_ia,
- (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2,
- h_dto_cno, DAT_EVD_DTO_FLAG, &h_dto_req_evd);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_create REQ: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d dto_req_evd created %p\n", getpid(),
- h_dto_req_evd);
- }
-
- /* create dto RCV EVD, with CNO if use_cno was set */
- ret = dat_evd_create(h_ia,
- MSG_BUF_COUNT + burst,
- h_dto_cno, DAT_EVD_DTO_FLAG, &h_dto_rcv_evd);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_create RCV: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d dto_rcv_evd created %p\n", getpid(),
- h_dto_rcv_evd);
- }
-
- /* query DTO req EVD and check size */
- ret = dat_evd_query(h_dto_req_evd, DAT_EVD_FIELD_EVD_QLEN, ¶m);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error dat_evd_query request evd: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else if (param.evd_qlen < (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2) {
- fprintf(stderr, "%d Error dat_evd qsize too small: %d < %d\n",
- getpid(), param.evd_qlen,
- (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2);
- return (ret);
- }
-
- LOGPRINTF("%d dto_req_evd QLEN - requested %d and actual %d\n",
- getpid(), (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2,
- param.evd_qlen);
-
- return DAT_SUCCESS;
-}
-
-/*
- * Destroy CR, CONN, CNO, and DTO events
- */
-
-DAT_RETURN destroy_events(void)
-{
- DAT_RETURN ret;
-
- /* free cr EVD */
- if (h_cr_evd != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Free cr EVD %p \n", getpid(), h_cr_evd);
- ret = dat_evd_free(h_cr_evd);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing cr EVD: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Freed cr EVD\n", getpid());
- h_cr_evd = DAT_HANDLE_NULL;
- }
- }
-
- /* free conn EVD */
- if (h_conn_evd != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Free conn EVD %p \n", getpid(), h_conn_evd);
- ret = dat_evd_free(h_conn_evd);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing conn EVD: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Freed conn EVD\n", getpid());
- h_conn_evd = DAT_HANDLE_NULL;
- }
- }
-
- /* free RCV dto EVD */
- if (h_dto_rcv_evd != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Free RCV dto EVD %p \n", getpid(), h_dto_rcv_evd);
- start = get_time();
- ret = dat_evd_free(h_dto_rcv_evd);
- stop = get_time();
- time.evdf += ((stop - start) * 1.0e6);
- time.total += time.evdf;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing dto EVD: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Freed dto EVD\n", getpid());
- h_dto_rcv_evd = DAT_HANDLE_NULL;
- }
- }
-
- /* free REQ dto EVD */
- if (h_dto_req_evd != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Free REQ dto EVD %p \n", getpid(), h_dto_req_evd);
- ret = dat_evd_free(h_dto_req_evd);
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing dto EVD: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Freed dto EVD\n", getpid());
- h_dto_req_evd = DAT_HANDLE_NULL;
- }
- }
-
- /* free CNO */
- if (h_dto_cno != DAT_HANDLE_NULL) {
- LOGPRINTF("%d Free dto CNO %p \n", getpid(), h_dto_cno);
- start = get_time();
- ret = dat_cno_free(h_dto_cno);
- stop = get_time();
- time.cnof += ((stop - start) * 1.0e6);
- time.total += time.cnof;
- if (ret != DAT_SUCCESS) {
- fprintf(stderr, "%d Error freeing dto CNO: %s\n",
- getpid(), DT_RetToString(ret));
- return (ret);
- } else {
- LOGPRINTF("%d Freed dto CNO\n", getpid());
- h_dto_cno = DAT_HANDLE_NULL;
- }
- }
- return DAT_SUCCESS;
-}
-
-/*
- * Map DAT_RETURN values to readable strings,
- * but don't assume the values are zero-based or contiguous.
- */
-char errmsg[512] = { 0 };
-const char *DT_RetToString(DAT_RETURN ret_value)
-{
- const char *major_msg, *minor_msg;
-
- dat_strerror(ret_value, &major_msg, &minor_msg);
-
- strcpy(errmsg, major_msg);
- strcat(errmsg, " ");
- strcat(errmsg, minor_msg);
-
- return errmsg;
-}
-
-/*
- * Map DAT_EVENT_CODE values to readable strings
- */
-const char *DT_EventToSTr(DAT_EVENT_NUMBER event_code)
-{
- unsigned int i;
- static struct {
- const char *name;
- DAT_RETURN value;
- } dat_events[] = {
-# define DATxx(x) { # x, x }
- DATxx(DAT_DTO_COMPLETION_EVENT),
- DATxx(DAT_RMR_BIND_COMPLETION_EVENT),
- DATxx(DAT_CONNECTION_REQUEST_EVENT),
- DATxx(DAT_CONNECTION_EVENT_ESTABLISHED),
- DATxx(DAT_CONNECTION_EVENT_PEER_REJECTED),
- DATxx(DAT_CONNECTION_EVENT_NON_PEER_REJECTED),
- DATxx(DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR),
- DATxx(DAT_CONNECTION_EVENT_DISCONNECTED),
- DATxx(DAT_CONNECTION_EVENT_BROKEN),
- DATxx(DAT_CONNECTION_EVENT_TIMED_OUT),
- DATxx(DAT_CONNECTION_EVENT_UNREACHABLE),
- DATxx(DAT_ASYNC_ERROR_EVD_OVERFLOW),
- DATxx(DAT_ASYNC_ERROR_IA_CATASTROPHIC),
- DATxx(DAT_ASYNC_ERROR_EP_BROKEN),
- DATxx(DAT_ASYNC_ERROR_TIMED_OUT),
- DATxx(DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR),
- DATxx(DAT_SOFTWARE_EVENT)
-# undef DATxx
- };
-# define NUM_EVENTS (sizeof(dat_events)/sizeof(dat_events[0]))
-
- for (i = 0; i < NUM_EVENTS; i++) {
- if (dat_events[i].value == event_code) {
- return (dat_events[i].name);
- }
- }
-
- return ("Invalid_DAT_EVENT_NUMBER");
-}
-
-void print_usage(void)
-{
- printf("\n DAPL USAGE \n\n");
- printf("s: server\n");
- printf("t: performance times\n");
- printf("c: use cno\n");
- printf("v: verbose\n");
- printf("p: polling\n");
- printf("d: delay before accept\n");
- printf("b: buf length to allocate\n");
- printf("B: burst count, rdma and msgs \n");
- printf("h: hostname/address of server, specified on client\n");
- printf("P: provider name (default = OpenIB-cma)\n");
- printf("\n");
-}
-
+/*\r
+ * Copyright (c) 2005-2008 Intel Corporation. All rights reserved.\r
+ *\r
+ * This software is available to you under a choice of one of two\r
+ * licenses. You may choose to be licensed under the terms of the GNU\r
+ * General Public License (GPL) Version 2, available from the file\r
+ * COPYING in the main directory of this source tree, or the\r
+ * OpenIB.org BSD license 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
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#ifdef DAPL_PROVIDER\r
+#undef DAPL_PROVIDER\r
+#endif\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+\r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h>\r
+#include <io.h>\r
+#include <process.h>\r
+#include <complib/cl_types.h>\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+\r
+#define getpid() ((int)GetCurrentProcessId())\r
+#define F64x "%I64x"\r
+\r
+#ifdef DBG\r
+#define DAPL_PROVIDER "ibnic0v2d"\r
+#else\r
+#define DAPL_PROVIDER "ibnic0v2"\r
+#endif\r
+\r
+#define ntohll _byteswap_uint64\r
+#define htonll _byteswap_uint64\r
+\r
+#else // _WIN32 || _WIN64\r
+\r
+#include <endian.h>\r
+#include <byteswap.h>\r
+#include <netdb.h>\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <sys/time.h>\r
+#include <netinet/in.h>\r
+#include <netinet/tcp.h>\r
+#include <arpa/inet.h>\r
+#include <sys/mman.h>\r
+#include <getopt.h>\r
+#include <inttypes.h>\r
+#include <unistd.h>\r
+\r
+#define DAPL_PROVIDER "ofa-v2-ib0"\r
+\r
+#define F64x "%"PRIx64""\r
+\r
+#if __BYTE_ORDER == __BIG_ENDIAN\r
+#define htonll(x) (x)\r
+#define ntohll(x) (x)\r
+#elif __BYTE_ORDER == __LITTLE_ENDIAN\r
+#define htonll(x) bswap_64(x)\r
+#define ntohll(x) bswap_64(x)\r
+#endif\r
+\r
+#endif // _WIN32 || _WIN64\r
+\r
+/* Debug: 1 == connect & close only, otherwise full-meal deal */\r
+#define CONNECT_ONLY 0\r
+\r
+#define MAX_POLLING_CNT 50000\r
+#define MAX_RDMA_RD 4\r
+#define MAX_PROCS 1000\r
+\r
+/* Header files needed for DAT/uDAPL */\r
+#include "dat2/udat.h"\r
+\r
+/* definitions */\r
+#define SERVER_CONN_QUAL 45248\r
+#define DTO_TIMEOUT (1000*1000*5)\r
+#define DTO_FLUSH_TIMEOUT (1000*1000*2)\r
+#define CONN_TIMEOUT (1000*1000*10)\r
+#define SERVER_TIMEOUT DAT_TIMEOUT_INFINITE\r
+#define RDMA_BUFFER_SIZE (64)\r
+\r
+/* Global DAT vars */\r
+static DAT_IA_HANDLE h_ia = DAT_HANDLE_NULL;\r
+static DAT_PZ_HANDLE h_pz = DAT_HANDLE_NULL;\r
+static DAT_EP_HANDLE h_ep = DAT_HANDLE_NULL;\r
+static DAT_PSP_HANDLE h_psp = DAT_HANDLE_NULL;\r
+static DAT_CR_HANDLE h_cr = DAT_HANDLE_NULL;\r
+\r
+static DAT_EVD_HANDLE h_async_evd = DAT_HANDLE_NULL;\r
+static DAT_EVD_HANDLE h_dto_req_evd = DAT_HANDLE_NULL;\r
+static DAT_EVD_HANDLE h_dto_rcv_evd = DAT_HANDLE_NULL;\r
+static DAT_EVD_HANDLE h_cr_evd = DAT_HANDLE_NULL;\r
+static DAT_EVD_HANDLE h_conn_evd = DAT_HANDLE_NULL;\r
+static DAT_CNO_HANDLE h_dto_cno = DAT_HANDLE_NULL;\r
+\r
+/* RDMA buffers */\r
+static DAT_LMR_HANDLE h_lmr_send = DAT_HANDLE_NULL;\r
+static DAT_LMR_HANDLE h_lmr_recv = DAT_HANDLE_NULL;\r
+static DAT_LMR_CONTEXT lmr_context_send;\r
+static DAT_LMR_CONTEXT lmr_context_recv;\r
+static DAT_RMR_CONTEXT rmr_context_send;\r
+static DAT_RMR_CONTEXT rmr_context_recv;\r
+static DAT_VLEN registered_size_send;\r
+static DAT_VLEN registered_size_recv;\r
+static DAT_VADDR registered_addr_send;\r
+static DAT_VADDR registered_addr_recv;\r
+\r
+/* Initial msg receive buf, RMR exchange, and Rdma-write notification */\r
+#define MSG_BUF_COUNT 3\r
+#define MSG_IOV_COUNT 2\r
+static DAT_RMR_TRIPLET rmr_recv_msg[MSG_BUF_COUNT];\r
+static DAT_LMR_HANDLE h_lmr_recv_msg = DAT_HANDLE_NULL;\r
+static DAT_LMR_CONTEXT lmr_context_recv_msg;\r
+static DAT_RMR_CONTEXT rmr_context_recv_msg;\r
+static DAT_VLEN registered_size_recv_msg;\r
+static DAT_VADDR registered_addr_recv_msg;\r
+\r
+/* message send buffer */\r
+static DAT_RMR_TRIPLET rmr_send_msg;\r
+static DAT_LMR_HANDLE h_lmr_send_msg = DAT_HANDLE_NULL;\r
+static DAT_LMR_CONTEXT lmr_context_send_msg;\r
+static DAT_RMR_CONTEXT rmr_context_send_msg;\r
+static DAT_VLEN registered_size_send_msg;\r
+static DAT_VADDR registered_addr_send_msg;\r
+static DAT_EP_ATTR ep_attr;\r
+char hostname[256] = { 0 };\r
+char provider[64] = DAPL_PROVIDER;\r
+char addr_str[INET_ADDRSTRLEN];\r
+\r
+/* rdma pointers */\r
+char *rbuf = NULL;\r
+char *sbuf = NULL;\r
+int status;\r
+\r
+/* timers */\r
+double start, stop, total_us, total_sec;\r
+\r
+struct dt_time {\r
+ double total;\r
+ double open;\r
+ double reg;\r
+ double unreg;\r
+ double pzc;\r
+ double pzf;\r
+ double evdc;\r
+ double evdf;\r
+ double cnoc;\r
+ double cnof;\r
+ double epc;\r
+ double epf;\r
+ double rdma_wr;\r
+ double rdma_rd[MAX_RDMA_RD];\r
+ double rdma_rd_total;\r
+ double rtt;\r
+ double close;\r
+ double conn;\r
+};\r
+\r
+struct dt_time time;\r
+\r
+/* defaults */\r
+static int failed = 0;\r
+static int performance_times = 0;\r
+static int connected = 0;\r
+static int burst = 10;\r
+static int server = 1;\r
+static int verbose = 0;\r
+static int polling = 0;\r
+static int poll_count = 0;\r
+static int rdma_wr_poll_count = 0;\r
+static int conn_poll_count = 0;\r
+static int rdma_rd_poll_count[MAX_RDMA_RD] = { 0 };\r
+static int delay = 0;\r
+static int buf_len = RDMA_BUFFER_SIZE;\r
+static int use_cno = 0;\r
+static int recv_msg_index = 0;\r
+static int burst_msg_posted = 0;\r
+static int burst_msg_index = 0;\r
+\r
+/* forward prototypes */\r
+const char *DT_RetToString(DAT_RETURN ret_value);\r
+const char *DT_EventToSTr(DAT_EVENT_NUMBER event_code);\r
+void print_usage(void);\r
+double get_time(void);\r
+void init_data(void);\r
+\r
+DAT_RETURN send_msg(void *data,\r
+ DAT_COUNT size,\r
+ DAT_LMR_CONTEXT context,\r
+ DAT_DTO_COOKIE cookie, DAT_COMPLETION_FLAGS flags);\r
+\r
+DAT_RETURN connect_ep(char *hostname, DAT_CONN_QUAL conn_id);\r
+void disconnect_ep(void);\r
+DAT_RETURN register_rdma_memory(void);\r
+DAT_RETURN unregister_rdma_memory(void);\r
+DAT_RETURN create_events(void);\r
+DAT_RETURN destroy_events(void);\r
+DAT_RETURN do_rdma_write_with_msg(void);\r
+DAT_RETURN do_rdma_read_with_msg(void);\r
+DAT_RETURN do_ping_pong_msg(void);\r
+\r
+#define LOGPRINTF if (verbose) printf\r
+\r
+void flush_evds(void)\r
+{\r
+ DAT_EVENT event;\r
+\r
+ /* Flush async error queue */\r
+ printf("%d ERR: Checking ASYNC EVD...\n", getpid());\r
+ while (dat_evd_dequeue(h_async_evd, &event) == DAT_SUCCESS) {\r
+ printf(" ASYNC EVD ENTRY: handle=%p reason=%d\n",\r
+ event.event_data.asynch_error_event_data.dat_handle,\r
+ event.event_data.asynch_error_event_data.reason);\r
+ }\r
+ /* Flush receive queue */\r
+ printf("%d ERR: Checking RECEIVE EVD...\n", getpid());\r
+ while (dat_evd_dequeue(h_dto_rcv_evd, &event) == DAT_SUCCESS) {\r
+ printf(" RCV EVD ENTRY: op=%d stat=%d ln=%d ck="F64x"\n",\r
+ event.event_data.dto_completion_event_data.operation,\r
+ event.event_data.dto_completion_event_data.status,\r
+ event.event_data.dto_completion_event_data.transfered_length,\r
+ event.event_data.dto_completion_event_data.user_cookie.as_64);\r
+ }\r
+ /* Flush request queue */\r
+ printf("%d ERR: Checking REQUEST EVD...\n", getpid());\r
+ while (dat_evd_dequeue(h_dto_req_evd, &event) == DAT_SUCCESS) {\r
+ printf(" REQ EVD ENTRY: op=%d stat=%d ln=%d ck="F64x"\n",\r
+ event.event_data.dto_completion_event_data.operation,\r
+ event.event_data.dto_completion_event_data.status,\r
+ event.event_data.dto_completion_event_data.transfered_length,\r
+ event.event_data.dto_completion_event_data.user_cookie.as_64);\r
+ }\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+ int i, c;\r
+ DAT_RETURN ret;\r
+ DAT_EP_PARAM ep_param;\r
+\r
+ /* parse arguments */\r
+ while ((c = getopt(argc, argv, "tscvpb:d:B:h:P:")) != -1) {\r
+ switch (c) {\r
+ case 't':\r
+ performance_times = 1;\r
+ fflush(stdout);\r
+ break;\r
+ case 's':\r
+ server = 1;\r
+ fflush(stdout);\r
+ break;\r
+ case 'c':\r
+ use_cno = 1;\r
+ printf("%d Creating CNO for DTO EVD's\n", getpid());\r
+ fflush(stdout);\r
+ break;\r
+ case 'v':\r
+ verbose = 1;\r
+ printf("%d Verbose\n", getpid());\r
+ fflush(stdout);\r
+ break;\r
+ case 'p':\r
+ polling = 1;\r
+ printf("%d Polling\n", getpid());\r
+ fflush(stdout);\r
+ break;\r
+ case 'B':\r
+ burst = atoi(optarg);\r
+ break;\r
+ case 'd':\r
+ delay = atoi(optarg);\r
+ break;\r
+ case 'b':\r
+ buf_len = atoi(optarg);\r
+ break;\r
+ case 'h':\r
+ server = 0;\r
+ strcpy(hostname, optarg);\r
+ break;\r
+ case 'P':\r
+ strcpy(provider, optarg);\r
+ break;\r
+ default:\r
+ print_usage();\r
+ exit(-12);\r
+ }\r
+ }\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ {\r
+ WSADATA wsaData;\r
+\r
+ i = WSAStartup(MAKEWORD(2, 2), &wsaData);\r
+ if (i != 0) {\r
+ printf("%s WSAStartup(2.2) failed? (0x%x)\n", argv[0],\r
+ i);\r
+ fflush(stdout);\r
+ exit(1);\r
+ }\r
+ }\r
+#endif\r
+\r
+ if (!server) {\r
+ printf("%d Running as client - %s\n", getpid(), provider);\r
+ } else {\r
+ printf("%d Running as server - %s\n", getpid(), provider);\r
+ }\r
+ fflush(stdout);\r
+\r
+ /* allocate send and receive buffers */\r
+ if (((rbuf = malloc(buf_len * (burst+1))) == NULL) ||\r
+ ((sbuf = malloc(buf_len * (burst+1))) == NULL)) {\r
+ perror("malloc");\r
+ exit(1);\r
+ }\r
+ memset(&time, 0, sizeof(struct dt_time));\r
+ LOGPRINTF("%d Allocated RDMA buffers (r:%p,s:%p) len %d \n",\r
+ getpid(), rbuf, sbuf, buf_len);\r
+\r
+ /* dat_ia_open, dat_pz_create */\r
+ h_async_evd = DAT_HANDLE_NULL;\r
+ start = get_time();\r
+ ret = dat_ia_open(provider, 8, &h_async_evd, &h_ia);\r
+ stop = get_time();\r
+ time.open += ((stop - start) * 1.0e6);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: Error Adaptor open: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ exit(1);\r
+ } else\r
+ LOGPRINTF("%d Opened Interface Adaptor\n", getpid());\r
+\r
+ /* Create Protection Zone */\r
+ start = get_time();\r
+ LOGPRINTF("%d Create Protection Zone\n", getpid());\r
+ ret = dat_pz_create(h_ia, &h_pz);\r
+ stop = get_time();\r
+ time.pzc += ((stop - start) * 1.0e6);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error creating Protection Zone: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ exit(1);\r
+ } else\r
+ LOGPRINTF("%d Created Protection Zone\n", getpid());\r
+\r
+ /* Register memory */\r
+ LOGPRINTF("%d Register RDMA memory\n", getpid());\r
+ ret = register_rdma_memory();\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error registering RDMA memory: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else\r
+ LOGPRINTF("%d Register RDMA memory done\n", getpid());\r
+\r
+ LOGPRINTF("%d Create events\n", getpid());\r
+ ret = create_events();\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error creating events: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else {\r
+ LOGPRINTF("%d Create events done\n", getpid());\r
+ }\r
+\r
+ /* create EP */\r
+ memset(&ep_attr, 0, sizeof(ep_attr));\r
+ ep_attr.service_type = DAT_SERVICE_TYPE_RC;\r
+ ep_attr.max_rdma_size = 0x10000;\r
+ ep_attr.qos = 0;\r
+ ep_attr.recv_completion_flags = 0;\r
+ ep_attr.max_recv_dtos = MSG_BUF_COUNT + (burst * 3);\r
+ ep_attr.max_request_dtos = MSG_BUF_COUNT + (burst * 3) + MAX_RDMA_RD;\r
+ ep_attr.max_recv_iov = MSG_IOV_COUNT;\r
+ ep_attr.max_request_iov = MSG_IOV_COUNT;\r
+ ep_attr.max_rdma_read_in = MAX_RDMA_RD;\r
+ ep_attr.max_rdma_read_out = MAX_RDMA_RD;\r
+ ep_attr.request_completion_flags = DAT_COMPLETION_DEFAULT_FLAG;\r
+ ep_attr.ep_transport_specific_count = 0;\r
+ ep_attr.ep_transport_specific = NULL;\r
+ ep_attr.ep_provider_specific_count = 0;\r
+ ep_attr.ep_provider_specific = NULL;\r
+\r
+ start = get_time();\r
+ ret = dat_ep_create(h_ia, h_pz, h_dto_rcv_evd,\r
+ h_dto_req_evd, h_conn_evd, &ep_attr, &h_ep);\r
+ stop = get_time();\r
+ time.epc += ((stop - start) * 1.0e6);\r
+ time.total += time.epc;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_ep_create: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else\r
+ LOGPRINTF("%d EP created %p \n", getpid(), h_ep);\r
+\r
+ /*\r
+ * register message buffers, establish connection, and\r
+ * exchange DMA RMR information info via messages\r
+ */\r
+ ret = connect_ep(hostname, SERVER_CONN_QUAL);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error connect_ep: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else\r
+ LOGPRINTF("%d connect_ep complete\n", getpid());\r
+\r
+ /* Query EP for local and remote address information, print */\r
+ ret = dat_ep_query(h_ep, DAT_EP_FIELD_ALL, &ep_param);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_ep_query: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else\r
+ LOGPRINTF("%d EP queried %p \n", getpid(), h_ep);\r
+#if defined(_WIN32)\r
+ printf("\n%d Query EP: LOCAL addr %s port %lld\n", getpid(),\r
+ inet_ntoa(((struct sockaddr_in *)\r
+ ep_param.local_ia_address_ptr)->sin_addr),\r
+ (ep_param.local_port_qual));\r
+#else\r
+ inet_ntop(AF_INET,\r
+ &((struct sockaddr_in *)ep_param.local_ia_address_ptr)->\r
+ sin_addr, addr_str, sizeof(addr_str));\r
+ printf("\n%d Query EP: LOCAL addr %s port " F64x "\n", getpid(),\r
+ addr_str, (ep_param.local_port_qual));\r
+#endif\r
+#if defined(_WIN32)\r
+ printf("%d Query EP: REMOTE addr %s port %lld\n", getpid(),\r
+ inet_ntoa(((struct sockaddr_in *)\r
+ ep_param.local_ia_address_ptr)->sin_addr),\r
+ (ep_param.remote_port_qual));\r
+#else\r
+ inet_ntop(AF_INET,\r
+ &((struct sockaddr_in *)ep_param.remote_ia_address_ptr)->\r
+ sin_addr, addr_str, sizeof(addr_str));\r
+ printf("%d Query EP: REMOTE addr %s port " F64x "\n", getpid(),\r
+ addr_str, (ep_param.remote_port_qual));\r
+#endif\r
+ fflush(stdout);\r
+\r
+#if CONNECT_ONLY\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ Sleep(1 * 1000);\r
+#else\r
+ sleep(1);\r
+#endif\r
+ goto cleanup;\r
+#endif\r
+\r
+ /*********** RDMA write data *************/\r
+ ret = do_rdma_write_with_msg();\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error do_rdma_write_with_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else\r
+ LOGPRINTF("%d do_rdma_write_with_msg complete\n", getpid());\r
+\r
+ /*********** RDMA read data *************/\r
+ ret = do_rdma_read_with_msg();\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error do_rdma_read_with_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else\r
+ LOGPRINTF("%d do_rdma_read_with_msg complete\n", getpid());\r
+\r
+ /*********** PING PING messages ************/\r
+ ret = do_ping_pong_msg();\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error do_ping_pong_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ goto cleanup;\r
+ } else {\r
+ LOGPRINTF("%d do_ping_pong_msg complete\n", getpid());\r
+ goto complete;\r
+ }\r
+\r
+cleanup:\r
+ flush_evds();\r
+ failed++;\r
+complete:\r
+\r
+ /* disconnect and free EP resources */\r
+ if (h_ep != DAT_HANDLE_NULL) {\r
+ /* unregister message buffers and tear down connection */\r
+ LOGPRINTF("%d Disconnect and Free EP %p \n", getpid(), h_ep);\r
+ disconnect_ep();\r
+\r
+ /* free EP */\r
+ LOGPRINTF("%d Free EP %p \n", getpid(), h_ep);\r
+ start = get_time();\r
+ ret = dat_ep_free(h_ep);\r
+ stop = get_time();\r
+ time.epf += ((stop - start) * 1.0e6);\r
+ time.total += time.epf;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing EP: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d Freed EP\n", getpid());\r
+ h_ep = DAT_HANDLE_NULL;\r
+ }\r
+ }\r
+\r
+ /* free EVDs */\r
+ LOGPRINTF("%d destroy events\n", getpid());\r
+ ret = destroy_events();\r
+ if (ret != DAT_SUCCESS)\r
+ fprintf(stderr, "%d Error destroy_events: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ else\r
+ LOGPRINTF("%d destroy events done\n", getpid());\r
+\r
+ ret = unregister_rdma_memory();\r
+ LOGPRINTF("%d unregister_rdma_memory \n", getpid());\r
+ if (ret != DAT_SUCCESS)\r
+ fprintf(stderr, "%d Error unregister_rdma_memory: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ else\r
+ LOGPRINTF("%d unregister_rdma_memory done\n", getpid());\r
+\r
+ /* Free protection domain */\r
+ LOGPRINTF("%d Freeing pz\n", getpid());\r
+ start = get_time();\r
+ ret = dat_pz_free(h_pz);\r
+ stop = get_time();\r
+ time.pzf += ((stop - start) * 1.0e6);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing PZ: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d Freed pz\n", getpid());\r
+ h_pz = NULL;\r
+ }\r
+\r
+ /* close the device */\r
+ LOGPRINTF("%d Closing Interface Adaptor\n", getpid());\r
+ start = get_time();\r
+ ret = dat_ia_close(h_ia, DAT_CLOSE_ABRUPT_FLAG);\r
+ stop = get_time();\r
+ time.close += ((stop - start) * 1.0e6);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: Error Adaptor close: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else\r
+ LOGPRINTF("%d Closed Interface Adaptor\n", getpid());\r
+\r
+ /* free rdma buffers */\r
+ free(rbuf);\r
+ free(sbuf);\r
+\r
+ printf("\n%d: DAPL Test Complete. %s\n\n",\r
+ getpid(), failed ? "FAILED" : "PASSED");\r
+\r
+ fflush(stderr);\r
+ fflush(stdout);\r
+\r
+ if (!performance_times)\r
+ exit(0);\r
+\r
+ printf("\n%d: DAPL Test Complete.\n\n", getpid());\r
+ printf("%d: Message RTT: Total=%10.2lf usec, %d bursts, itime=%10.2lf"\r
+ " usec, pc=%d\n",\r
+ getpid(), time.rtt, burst, time.rtt / burst, poll_count);\r
+ printf("%d: RDMA write: Total=%10.2lf usec, %d bursts, itime=%10.2lf"\r
+ " usec, pc=%d\n",\r
+ getpid(), time.rdma_wr, burst,\r
+ time.rdma_wr / burst, rdma_wr_poll_count);\r
+ for (i = 0; i < MAX_RDMA_RD; i++) {\r
+ printf("%d: RDMA read: Total=%10.2lf usec, %d bursts, "\r
+ "itime=%10.2lf usec, pc=%d\n",\r
+ getpid(), time.rdma_rd_total, MAX_RDMA_RD,\r
+ time.rdma_rd[i], rdma_rd_poll_count[i]);\r
+ }\r
+ printf("%d: open: %10.2lf usec\n", getpid(), time.open);\r
+ printf("%d: close: %10.2lf usec\n", getpid(), time.close);\r
+ printf("%d: PZ create: %10.2lf usec\n", getpid(), time.pzc);\r
+ printf("%d: PZ free: %10.2lf usec\n", getpid(), time.pzf);\r
+ printf("%d: LMR create:%10.2lf usec\n", getpid(), time.reg);\r
+ printf("%d: LMR free: %10.2lf usec\n", getpid(), time.unreg);\r
+ printf("%d: EVD create:%10.2lf usec\n", getpid(), time.evdc);\r
+ printf("%d: EVD free: %10.2lf usec\n", getpid(), time.evdf);\r
+ if (use_cno) {\r
+ printf("%d: CNO create: %10.2lf usec\n", getpid(), time.cnoc);\r
+ printf("%d: CNO free: %10.2lf usec\n", getpid(), time.cnof);\r
+ }\r
+ printf("%d: EP create: %10.2lf usec\n", getpid(), time.epc);\r
+ printf("%d: EP free: %10.2lf usec\n", getpid(), time.epf);\r
+ if (!server)\r
+ printf("%d: connect: %10.2lf usec, poll_cnt=%d\n", \r
+ getpid(), time.conn, conn_poll_count);\r
+ printf("%d: TOTAL: %10.2lf usec\n", getpid(), time.total);\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ WSACleanup();\r
+#endif\r
+ return (0);\r
+}\r
+\r
+double get_time(void)\r
+{\r
+ struct timeval tp;\r
+\r
+ gettimeofday(&tp, NULL);\r
+ return ((double)tp.tv_sec + (double)tp.tv_usec * 1e-6);\r
+}\r
+\r
+void init_data(void)\r
+{\r
+ memset(rbuf, 'a', buf_len);\r
+ memset(sbuf, 'b', buf_len);\r
+}\r
+\r
+DAT_RETURN\r
+send_msg(void *data,\r
+ DAT_COUNT size,\r
+ DAT_LMR_CONTEXT context,\r
+ DAT_DTO_COOKIE cookie, DAT_COMPLETION_FLAGS flags)\r
+{\r
+ DAT_LMR_TRIPLET iov;\r
+ DAT_EVENT event;\r
+ DAT_COUNT nmore;\r
+ DAT_RETURN ret;\r
+\r
+ iov.lmr_context = context;\r
+#if defined(_WIN32)\r
+ iov.virtual_address = (DAT_VADDR) data;\r
+#else\r
+ iov.virtual_address = (DAT_VADDR) (unsigned long)data;\r
+#endif\r
+ iov.segment_length = size;\r
+\r
+ LOGPRINTF("%d calling post_send\n", getpid());\r
+ cookie.as_64 = 0xaaaa;\r
+ ret = dat_ep_post_send(h_ep, 1, &iov, cookie, flags);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: ERROR: dat_ep_post_send() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return ret;\r
+ }\r
+\r
+ if (!(flags & DAT_COMPLETION_SUPPRESS_FLAG)) {\r
+ if (polling) {\r
+ printf("%d Polling post send completion...\n",\r
+ getpid());\r
+ while (dat_evd_dequeue(h_dto_req_evd, &event) ==\r
+ DAT_QUEUE_EMPTY) ;\r
+ } else {\r
+ LOGPRINTF("%d waiting for post_send completion event\n",\r
+ getpid());\r
+ if (use_cno) {\r
+ DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;\r
+ ret =\r
+ dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);\r
+ LOGPRINTF("%d cno wait return evd_handle=%p\n",\r
+ getpid(), evd);\r
+ if (evd != h_dto_req_evd) {\r
+ /* CNO timeout, already on EVD */\r
+ if (evd != NULL)\r
+ return (ret);\r
+ }\r
+ }\r
+ /* use wait to dequeue */\r
+ ret =\r
+ dat_evd_wait(h_dto_req_evd, DTO_TIMEOUT, 1, &event,\r
+ &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: DTO dat_evd_wait() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return ret;\r
+ }\r
+ }\r
+\r
+ /* validate event number, len, cookie, and status */\r
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+ fprintf(stderr, "%d: ERROR: DTO event number %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ if ((event.event_data.dto_completion_event_data.\r
+ transfered_length != size)\r
+ || (event.event_data.dto_completion_event_data.user_cookie.\r
+ as_64 != 0xaaaa)) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: DTO len %d or cookie " F64x " \n",\r
+ getpid(),\r
+ event.event_data.dto_completion_event_data.\r
+ transfered_length,\r
+ event.event_data.dto_completion_event_data.\r
+ user_cookie.as_64);\r
+ return (DAT_ABORT);\r
+\r
+ }\r
+ if (event.event_data.dto_completion_event_data.status !=\r
+ DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: ERROR: DTO event status %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (DAT_ABORT);\r
+ }\r
+ }\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+DAT_RETURN connect_ep(char *hostname, DAT_CONN_QUAL conn_id)\r
+{\r
+ DAT_SOCK_ADDR remote_addr;\r
+ DAT_RETURN ret;\r
+ DAT_REGION_DESCRIPTION region;\r
+ DAT_EVENT event;\r
+ DAT_COUNT nmore;\r
+ DAT_LMR_TRIPLET l_iov;\r
+ DAT_RMR_TRIPLET r_iov;\r
+ DAT_DTO_COOKIE cookie;\r
+ int i;\r
+ unsigned char *buf;\r
+ DAT_CR_PARAM cr_param = { 0 };\r
+ unsigned char pdata[48] = { 0 };\r
+\r
+ /* Register send message buffer */\r
+ LOGPRINTF("%d Registering send Message Buffer %p, len %d\n",\r
+ getpid(), &rmr_send_msg, (int)sizeof(DAT_RMR_TRIPLET));\r
+ region.for_va = &rmr_send_msg;\r
+ ret = dat_lmr_create(h_ia,\r
+ DAT_MEM_TYPE_VIRTUAL,\r
+ region,\r
+ sizeof(DAT_RMR_TRIPLET),\r
+ h_pz,\r
+ DAT_MEM_PRIV_LOCAL_WRITE_FLAG,\r
+ DAT_VA_TYPE_VA,\r
+ &h_lmr_send_msg,\r
+ &lmr_context_send_msg,\r
+ &rmr_context_send_msg,\r
+ ®istered_size_send_msg,\r
+ ®istered_addr_send_msg);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error registering send msg buffer: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d Registered send Message Buffer %p \n",\r
+ getpid(), region.for_va);\r
+\r
+ /* Register Receive buffers */\r
+ LOGPRINTF("%d Registering Receive Message Buffer %p\n",\r
+ getpid(), rmr_recv_msg);\r
+ region.for_va = rmr_recv_msg;\r
+ ret = dat_lmr_create(h_ia,\r
+ DAT_MEM_TYPE_VIRTUAL,\r
+ region,\r
+ sizeof(DAT_RMR_TRIPLET) * MSG_BUF_COUNT,\r
+ h_pz,\r
+ DAT_MEM_PRIV_LOCAL_WRITE_FLAG,\r
+ DAT_VA_TYPE_VA,\r
+ &h_lmr_recv_msg,\r
+ &lmr_context_recv_msg,\r
+ &rmr_context_recv_msg,\r
+ ®istered_size_recv_msg,\r
+ ®istered_addr_recv_msg);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error registering recv msg buffer: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d Registered Receive Message Buffer %p\n",\r
+ getpid(), region.for_va);\r
+\r
+ for (i = 0; i < MSG_BUF_COUNT; i++) {\r
+ cookie.as_64 = i;\r
+ l_iov.lmr_context = lmr_context_recv_msg;\r
+#if defined(_WIN32)\r
+ l_iov.virtual_address = (DAT_VADDR) & rmr_recv_msg[i];\r
+#else\r
+ l_iov.virtual_address =\r
+ (DAT_VADDR) (unsigned long)&rmr_recv_msg[i];\r
+#endif\r
+ l_iov.segment_length = sizeof(DAT_RMR_TRIPLET);\r
+\r
+ LOGPRINTF("%d Posting Receive Message Buffer %p\n",\r
+ getpid(), &rmr_recv_msg[i]);\r
+ ret = dat_ep_post_recv(h_ep,\r
+ 1,\r
+ &l_iov,\r
+ cookie, DAT_COMPLETION_DEFAULT_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error registering recv msg buffer: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d Registered Receive Message Buffer %p\n",\r
+ getpid(), region.for_va);\r
+\r
+ }\r
+\r
+ /* setup receive rdma buffer to initial string to be overwritten */\r
+ strcpy((char *)rbuf, "blah, blah, blah\n");\r
+\r
+ /* clear event structure */\r
+ memset(&event, 0, sizeof(DAT_EVENT));\r
+\r
+ if (server) { /* SERVER */\r
+\r
+ /* create the service point for server listen */\r
+ LOGPRINTF("%d Creating service point for listen\n", getpid());\r
+ ret = dat_psp_create(h_ia,\r
+ conn_id,\r
+ h_cr_evd, DAT_PSP_CONSUMER_FLAG, &h_psp);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_psp_create: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d dat_psp_created for server listen\n",\r
+ getpid());\r
+\r
+ printf("%d Server waiting for connect request on port " F64x\r
+ "\n", getpid(), conn_id);\r
+\r
+ ret = dat_evd_wait(h_cr_evd, SERVER_TIMEOUT, 1, &event, &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_wait: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d dat_evd_wait for cr_evd completed\n",\r
+ getpid());\r
+\r
+ if (event.event_number != DAT_CONNECTION_REQUEST_EVENT) {\r
+ fprintf(stderr, "%d Error unexpected cr event : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+ if ((event.event_data.cr_arrival_event_data.conn_qual !=\r
+ SERVER_CONN_QUAL)\r
+ || (event.event_data.cr_arrival_event_data.sp_handle.\r
+ psp_handle != h_psp)) {\r
+ fprintf(stderr, "%d Error wrong cr event data : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ /* use to test rdma_cma timeout logic */\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ if (delay)\r
+ Sleep(delay * 1000);\r
+#else\r
+ if (delay)\r
+ sleep(delay);\r
+#endif\r
+\r
+ /* accept connect request from client */\r
+ h_cr = event.event_data.cr_arrival_event_data.cr_handle;\r
+ LOGPRINTF("%d Accepting connect request from client\n",\r
+ getpid());\r
+\r
+ /* private data - check and send it back */\r
+ dat_cr_query(h_cr, DAT_CSP_FIELD_ALL, &cr_param);\r
+\r
+ buf = (unsigned char *)cr_param.private_data;\r
+ LOGPRINTF("%d CONN REQUEST Private Data %p[0]=%d [47]=%d\n",\r
+ getpid(), buf, buf[0], buf[47]);\r
+ for (i = 0; i < 48; i++) {\r
+ if (buf[i] != i + 1) {\r
+ fprintf(stderr, "%d Error with CONNECT REQUEST"\r
+ " private data: %p[%d]=%d s/be %d\n",\r
+ getpid(), buf, i, buf[i], i + 1);\r
+ dat_cr_reject(h_cr, 0, NULL);\r
+ return (DAT_ABORT);\r
+ }\r
+ buf[i]++; /* change for trip back */\r
+ }\r
+\r
+#ifdef TEST_REJECT_WITH_PRIVATE_DATA\r
+ printf("%d REJECT request with 48 bytes of private data\n",\r
+ getpid());\r
+ ret = dat_cr_reject(h_cr, 48, cr_param.private_data);\r
+ printf("\n%d: DAPL Test Complete. %s\n\n",\r
+ getpid(), ret ? "FAILED" : "PASSED");\r
+ exit(0);\r
+#endif\r
+\r
+ ret = dat_cr_accept(h_cr, h_ep, 48, cr_param.private_data);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_cr_accept: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d dat_cr_accept completed\n", getpid());\r
+ } else { /* CLIENT */\r
+ struct addrinfo *target;\r
+ int rval;\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ if ((rval = getaddrinfo(hostname, "ftp", NULL, &target)) != 0) {\r
+ printf("\n remote name resolution failed! %s\n",\r
+ gai_strerror(rval));\r
+ exit(1);\r
+ }\r
+ rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;\r
+#else\r
+ if (getaddrinfo(hostname, NULL, NULL, &target) != 0) {\r
+ perror("\n remote name resolution failed!");\r
+ exit(1);\r
+ }\r
+ rval = ((struct sockaddr_in *)target->ai_addr)->sin_addr.s_addr;\r
+#endif\r
+ printf("%d Server Name: %s \n", getpid(), hostname);\r
+ printf("%d Server Net Address: %d.%d.%d.%d port " F64x "\n",\r
+ getpid(), (rval >> 0) & 0xff, (rval >> 8) & 0xff,\r
+ (rval >> 16) & 0xff, (rval >> 24) & 0xff, conn_id);\r
+\r
+ remote_addr = *((DAT_IA_ADDRESS_PTR) target->ai_addr);\r
+ freeaddrinfo(target);\r
+\r
+ for (i = 0; i < 48; i++) /* simple pattern in private data */\r
+ pdata[i] = i + 1;\r
+\r
+ LOGPRINTF("%d Connecting to server\n", getpid());\r
+ start = get_time();\r
+ ret = dat_ep_connect(h_ep,\r
+ &remote_addr,\r
+ conn_id,\r
+ CONN_TIMEOUT,\r
+ 48,\r
+ (DAT_PVOID) pdata,\r
+ 0, DAT_CONNECT_DEFAULT_FLAG);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_ep_connect: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d dat_ep_connect completed\n", getpid());\r
+ }\r
+\r
+ printf("%d Waiting for connect response\n", getpid());\r
+\r
+ if (polling) \r
+ while (DAT_GET_TYPE(dat_evd_dequeue(h_conn_evd, &event)) == \r
+ DAT_QUEUE_EMPTY)\r
+ conn_poll_count++;\r
+ else \r
+ ret = dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE, \r
+ 1, &event, &nmore);\r
+\r
+ if (!server) {\r
+ stop = get_time();\r
+ time.conn += ((stop - start) * 1.0e6);\r
+ }\r
+\r
+#ifdef TEST_REJECT_WITH_PRIVATE_DATA\r
+ if (event.event_number != DAT_CONNECTION_EVENT_PEER_REJECTED) {\r
+ fprintf(stderr, "%d expected conn reject event : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+ /* get the reject private data and validate */\r
+ buf = (unsigned char *)event.event_data.connect_event_data.private_data;\r
+ printf("%d Received REJECT with private data %p[0]=%d [47]=%d\n",\r
+ getpid(), buf, buf[0], buf[47]);\r
+ for (i = 0; i < 48; i++) {\r
+ if (buf[i] != i + 2) {\r
+ fprintf(stderr, "%d client: Error with REJECT event"\r
+ " private data: %p[%d]=%d s/be %d\n",\r
+ getpid(), buf, i, buf[i], i + 2);\r
+ dat_ep_disconnect(h_ep, DAT_CLOSE_ABRUPT_FLAG);\r
+ return (DAT_ABORT);\r
+ }\r
+ }\r
+ printf("\n%d: DAPL Test Complete. PASSED\n\n", getpid());\r
+ exit(0);\r
+#endif\r
+\r
+ if (event.event_number != DAT_CONNECTION_EVENT_ESTABLISHED) {\r
+ fprintf(stderr, "%d Error unexpected conn event : 0x%x %s\n",\r
+ getpid(), event.event_number,\r
+ DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ /* check private data back from server */\r
+ if (!server) {\r
+ buf =\r
+ (unsigned char *)event.event_data.connect_event_data.\r
+ private_data;\r
+ LOGPRINTF("%d CONN Private Data %p[0]=%d [47]=%d\n", getpid(),\r
+ buf, buf[0], buf[47]);\r
+ for (i = 0; i < 48; i++) {\r
+ if (buf[i] != i + 2) {\r
+ fprintf(stderr, "%d Error with CONNECT event"\r
+ " private data: %p[%d]=%d s/be %d\n",\r
+ getpid(), buf, i, buf[i], i + 2);\r
+ dat_ep_disconnect(h_ep, DAT_CLOSE_ABRUPT_FLAG);\r
+ LOGPRINTF\r
+ ("%d waiting for disconnect event...\n",\r
+ getpid());\r
+ dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE,\r
+ 1, &event, &nmore);\r
+ return (DAT_ABORT);\r
+ }\r
+ }\r
+ }\r
+\r
+ printf("\n%d CONNECTED!\n\n", getpid());\r
+ connected = 1;\r
+\r
+#if CONNECT_ONLY\r
+ return 0;\r
+#endif\r
+\r
+ /*\r
+ * Setup our remote memory and tell the other side about it\r
+ */\r
+ rmr_send_msg.virtual_address = htonll((DAT_VADDR) (uintptr_t) rbuf);\r
+ rmr_send_msg.segment_length = htonl(RDMA_BUFFER_SIZE);\r
+ rmr_send_msg.rmr_context = htonl(rmr_context_recv);\r
+\r
+ printf("%d Send RMR msg to remote: r_key_ctx=0x%x,va=%p,len=0x%x\n",\r
+ getpid(), rmr_context_recv, rbuf, RDMA_BUFFER_SIZE);\r
+\r
+ ret = send_msg(&rmr_send_msg,\r
+ sizeof(DAT_RMR_TRIPLET),\r
+ lmr_context_send_msg,\r
+ cookie, DAT_COMPLETION_SUPPRESS_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error send_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else\r
+ LOGPRINTF("%d send_msg completed\n", getpid());\r
+\r
+ /*\r
+ * Wait for remote RMR information for RDMA\r
+ */\r
+ if (polling) {\r
+ printf("%d Polling for remote to send RMR data\n", getpid());\r
+ while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==\r
+ DAT_QUEUE_EMPTY) ;\r
+ } else {\r
+ printf("%d Waiting for remote to send RMR data\n", getpid());\r
+ if (use_cno) {\r
+ DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;\r
+ ret = dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);\r
+ LOGPRINTF("%d cno wait return evd_handle=%p\n",\r
+ getpid(), evd);\r
+ if (evd != h_dto_rcv_evd) {\r
+ /* CNO timeout, already on EVD */\r
+ if (evd != NULL)\r
+ return (ret);\r
+ }\r
+ }\r
+ /* use wait to dequeue */\r
+ ret =\r
+ dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error waiting on h_dto_rcv_evd: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d dat_evd_wait h_dto_rcv_evd completed\n",\r
+ getpid());\r
+ }\r
+ }\r
+\r
+ printf("%d remote RMR data arrived!\n", getpid());\r
+\r
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+ fprintf(stderr, "%d Error unexpected DTO event : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+ if ((event.event_data.dto_completion_event_data.transfered_length !=\r
+ sizeof(DAT_RMR_TRIPLET)) ||\r
+ (event.event_data.dto_completion_event_data.user_cookie.as_64 !=\r
+ recv_msg_index)) {\r
+ fprintf(stderr,\r
+ "ERR recv event: len=%d cookie=" F64x\r
+ " expected %d/%d\n",\r
+ (int)event.event_data.dto_completion_event_data.\r
+ transfered_length,\r
+ event.event_data.dto_completion_event_data.user_cookie.\r
+ as_64, (int)sizeof(DAT_RMR_TRIPLET), recv_msg_index);\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ /* swap received RMR msg: network order to host order */\r
+ r_iov = rmr_recv_msg[recv_msg_index];\r
+ rmr_recv_msg[recv_msg_index].rmr_context = ntohl(r_iov.rmr_context);\r
+ rmr_recv_msg[recv_msg_index].virtual_address =\r
+ ntohll(r_iov.virtual_address);\r
+ rmr_recv_msg[recv_msg_index].segment_length =\r
+ ntohl(r_iov.segment_length);\r
+\r
+ printf("%d Received RMR from remote: "\r
+ "r_iov: r_key_ctx=%x,va=" F64x ",len=0x%x\n",\r
+ getpid(), rmr_recv_msg[recv_msg_index].rmr_context,\r
+ rmr_recv_msg[recv_msg_index].virtual_address,\r
+ rmr_recv_msg[recv_msg_index].segment_length);\r
+\r
+ recv_msg_index++;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+void disconnect_ep(void)\r
+{\r
+ DAT_RETURN ret;\r
+ DAT_EVENT event;\r
+ DAT_COUNT nmore;\r
+\r
+ if (connected) {\r
+\r
+ /* \r
+ * Only the client needs to call disconnect. The server _should_ be able\r
+ * to just wait on the EVD associated with connection events for a\r
+ * disconnect request and then exit.\r
+ */\r
+ if (!server) {\r
+ LOGPRINTF("%d dat_ep_disconnect\n", getpid());\r
+ ret = dat_ep_disconnect(h_ep, DAT_CLOSE_DEFAULT);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error dat_ep_disconnect: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d dat_ep_disconnect completed\n",\r
+ getpid());\r
+ }\r
+ } else {\r
+ LOGPRINTF("%d Server waiting for disconnect...\n",\r
+ getpid());\r
+ }\r
+\r
+ ret =\r
+ dat_evd_wait(h_conn_evd, DAT_TIMEOUT_INFINITE, 1, &event,\r
+ &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_wait: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d dat_evd_wait for h_conn_evd completed\n",\r
+ getpid());\r
+ }\r
+ }\r
+\r
+ /* destroy service point */\r
+ if ((server) && (h_psp != DAT_HANDLE_NULL)) {\r
+ ret = dat_psp_free(h_psp);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_psp_free: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d dat_psp_free completed\n", getpid());\r
+ }\r
+ }\r
+\r
+ /* Unregister Send message Buffer */\r
+ if (h_lmr_send_msg != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Unregister send message h_lmr %p \n", getpid(),\r
+ h_lmr_send_msg);\r
+ ret = dat_lmr_free(h_lmr_send_msg);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error deregistering send msg mr: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d Unregistered send message Buffer\n",\r
+ getpid());\r
+ h_lmr_send_msg = NULL;\r
+ }\r
+ }\r
+\r
+ /* Unregister recv message Buffer */\r
+ if (h_lmr_recv_msg != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Unregister recv message h_lmr %p \n", getpid(),\r
+ h_lmr_recv_msg);\r
+ ret = dat_lmr_free(h_lmr_recv_msg);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error deregistering recv msg mr: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ } else {\r
+ LOGPRINTF("%d Unregistered recv message Buffer\n",\r
+ getpid());\r
+ h_lmr_recv_msg = NULL;\r
+ }\r
+ }\r
+ return;\r
+}\r
+\r
+DAT_RETURN do_rdma_write_with_msg(void)\r
+{\r
+ DAT_EVENT event;\r
+ DAT_COUNT nmore;\r
+ DAT_LMR_TRIPLET l_iov[MSG_IOV_COUNT];\r
+ DAT_RMR_TRIPLET r_iov;\r
+ DAT_DTO_COOKIE cookie;\r
+ DAT_RETURN ret;\r
+ int i;\r
+\r
+ printf("\n %d RDMA WRITE DATA with SEND MSG\n\n", getpid());\r
+\r
+ cookie.as_64 = 0x5555;\r
+\r
+ if (recv_msg_index >= MSG_BUF_COUNT)\r
+ return (DAT_ABORT);\r
+\r
+ /* get RMR information from previously received message */\r
+ r_iov = rmr_recv_msg[recv_msg_index - 1];\r
+\r
+ if (server)\r
+ strcpy((char *)sbuf, "server RDMA write data...");\r
+ else\r
+ strcpy((char *)sbuf, "client RDMA write data...");\r
+\r
+ for (i = 0; i < MSG_IOV_COUNT; i++) {\r
+ l_iov[i].lmr_context = lmr_context_send;\r
+ l_iov[i].segment_length = buf_len / MSG_IOV_COUNT;\r
+ l_iov[i].virtual_address = (DAT_VADDR) (uintptr_t)\r
+ (&sbuf[l_iov[i].segment_length * i]);\r
+\r
+ LOGPRINTF("%d rdma_write iov[%d] buf=%p,len=%d\n",\r
+ getpid(), i, &sbuf[l_iov[i].segment_length * i],\r
+ l_iov[i].segment_length);\r
+ }\r
+\r
+ start = get_time();\r
+ for (i = 0; i < burst; i++) {\r
+ cookie.as_64 = 0x9999;\r
+ ret = dat_ep_post_rdma_write(h_ep, // ep_handle\r
+ MSG_IOV_COUNT, // num_segments\r
+ l_iov, // LMR\r
+ cookie, // user_cookie\r
+ &r_iov, // RMR\r
+ DAT_COMPLETION_SUPPRESS_FLAG);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: dat_ep_post_rdma_write() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (DAT_ABORT);\r
+ }\r
+ LOGPRINTF("%d rdma_write # %d completed\n", getpid(), i + 1);\r
+ }\r
+\r
+ /*\r
+ * Send RMR information a 2nd time to indicate completion\r
+ * NOTE: already swapped to network order in connect_ep\r
+ */\r
+ printf("%d Sending RDMA WRITE completion message\n", getpid());\r
+\r
+ ret = send_msg(&rmr_send_msg,\r
+ sizeof(DAT_RMR_TRIPLET),\r
+ lmr_context_send_msg,\r
+ cookie, DAT_COMPLETION_SUPPRESS_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error send_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d send_msg completed\n", getpid());\r
+ }\r
+\r
+ /*\r
+ * Collect first event, write completion or the inbound recv \r
+ */\r
+ if (polling) {\r
+ while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==\r
+ DAT_QUEUE_EMPTY)\r
+ rdma_wr_poll_count++;\r
+ } else {\r
+ LOGPRINTF("%d waiting for message receive event\n", getpid());\r
+ if (use_cno) {\r
+ DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;\r
+ ret = dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);\r
+ LOGPRINTF("%d cno wait return evd_handle=%p\n",\r
+ getpid(), evd);\r
+ if (evd != h_dto_rcv_evd) {\r
+ /* CNO timeout, already on EVD */\r
+ if (evd != NULL)\r
+ return (ret);\r
+ }\r
+ }\r
+ /* use wait to dequeue */\r
+ ret =\r
+ dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: ERROR: DTO dat_evd_wait() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ }\r
+ }\r
+ stop = get_time();\r
+ time.rdma_wr = ((stop - start) * 1.0e6);\r
+\r
+ /* validate event number and status */\r
+ printf("%d inbound rdma_write; send message arrived!\n", getpid());\r
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+ fprintf(stderr, "%d Error unexpected DTO event : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ if ((event.event_data.dto_completion_event_data.transfered_length !=\r
+ sizeof(DAT_RMR_TRIPLET))\r
+ || (event.event_data.dto_completion_event_data.user_cookie.as_64 !=\r
+ recv_msg_index)) {\r
+ fprintf(stderr,\r
+ "unexpected event data for receive: len=%d cookie=" F64x\r
+ " exp %d/%d\n",\r
+ (int)event.event_data.dto_completion_event_data.\r
+ transfered_length,\r
+ event.event_data.dto_completion_event_data.user_cookie.\r
+ as_64, (int)sizeof(DAT_RMR_TRIPLET), recv_msg_index);\r
+\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ /* swap received RMR msg: network order to host order */\r
+ r_iov = rmr_recv_msg[recv_msg_index];\r
+ rmr_recv_msg[recv_msg_index].virtual_address =\r
+ ntohll(rmr_recv_msg[recv_msg_index].virtual_address);\r
+ rmr_recv_msg[recv_msg_index].segment_length =\r
+ ntohl(rmr_recv_msg[recv_msg_index].segment_length);\r
+ rmr_recv_msg[recv_msg_index].rmr_context =\r
+ ntohl(rmr_recv_msg[recv_msg_index].rmr_context);\r
+\r
+ printf("%d Received RMR from remote: "\r
+ "r_iov: r_key_ctx=%x,va=" F64x ",len=0x%x\n",\r
+ getpid(), rmr_recv_msg[recv_msg_index].rmr_context,\r
+ rmr_recv_msg[recv_msg_index].virtual_address,\r
+ rmr_recv_msg[recv_msg_index].segment_length);\r
+\r
+ LOGPRINTF("%d inbound rdma_write; send msg event SUCCESS!!\n",\r
+ getpid());\r
+\r
+ printf("%d %s RDMA write buffer contains: %s\n",\r
+ getpid(), server ? "SERVER:" : "CLIENT:", rbuf);\r
+\r
+ recv_msg_index++;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+DAT_RETURN do_rdma_read_with_msg(void)\r
+{\r
+ DAT_EVENT event;\r
+ DAT_COUNT nmore;\r
+ DAT_LMR_TRIPLET l_iov;\r
+ DAT_RMR_TRIPLET r_iov;\r
+ DAT_DTO_COOKIE cookie;\r
+ DAT_RETURN ret;\r
+ int i;\r
+\r
+ printf("\n %d RDMA READ DATA with SEND MSG\n\n", getpid());\r
+\r
+ if (recv_msg_index >= MSG_BUF_COUNT)\r
+ return (DAT_ABORT);\r
+\r
+ /* get RMR information from previously received message */\r
+ r_iov = rmr_recv_msg[recv_msg_index - 1];\r
+\r
+ /* setup rdma read buffer to initial string to be overwritten */\r
+ strcpy((char *)sbuf, "blah, blah, blah\n");\r
+\r
+ if (server)\r
+ strcpy((char *)rbuf, "server RDMA read data...");\r
+ else\r
+ strcpy((char *)rbuf, "client RDMA read data...");\r
+\r
+ l_iov.lmr_context = lmr_context_send;\r
+ l_iov.virtual_address = (DAT_VADDR) (uintptr_t) sbuf;\r
+ l_iov.segment_length = buf_len;\r
+\r
+ for (i = 0; i < MAX_RDMA_RD; i++) {\r
+ cookie.as_64 = 0x9999;\r
+ start = get_time();\r
+ ret = dat_ep_post_rdma_read(h_ep, // ep_handle\r
+ 1, // num_segments\r
+ &l_iov, // LMR\r
+ cookie, // user_cookie\r
+ &r_iov, // RMR\r
+ DAT_COMPLETION_DEFAULT_FLAG);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: dat_ep_post_rdma_read() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ if (polling) {\r
+ while (dat_evd_dequeue(h_dto_req_evd, &event) ==\r
+ DAT_QUEUE_EMPTY)\r
+ rdma_rd_poll_count[i]++;\r
+ } else {\r
+ LOGPRINTF("%d waiting for rdma_read completion event\n",\r
+ getpid());\r
+ if (use_cno) {\r
+ DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;\r
+ ret =\r
+ dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);\r
+ LOGPRINTF("%d cno wait return evd_handle=%p\n",\r
+ getpid(), evd);\r
+ if (evd != h_dto_req_evd) {\r
+ /* CNO timeout, already on EVD */\r
+ if (evd != NULL)\r
+ return (ret);\r
+ }\r
+ }\r
+ /* use wait to dequeue */\r
+ ret =\r
+ dat_evd_wait(h_dto_req_evd, DTO_TIMEOUT, 1, &event,\r
+ &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: DTO dat_evd_wait() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return ret;\r
+ }\r
+ }\r
+ /* validate event number, len, cookie, and status */\r
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+ fprintf(stderr, "%d: ERROR: DTO event number %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+ if ((event.event_data.dto_completion_event_data.\r
+ transfered_length != buf_len)\r
+ || (event.event_data.dto_completion_event_data.user_cookie.\r
+ as_64 != 0x9999)) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: DTO len %d or cookie " F64x "\n",\r
+ getpid(),\r
+ event.event_data.dto_completion_event_data.\r
+ transfered_length,\r
+ event.event_data.dto_completion_event_data.\r
+ user_cookie.as_64);\r
+ return (DAT_ABORT);\r
+ }\r
+ if (event.event_data.dto_completion_event_data.status !=\r
+ DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: ERROR: DTO event status %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (DAT_ABORT);\r
+ }\r
+ stop = get_time();\r
+ time.rdma_rd[i] = ((stop - start) * 1.0e6);\r
+ time.rdma_rd_total += time.rdma_rd[i];\r
+\r
+ LOGPRINTF("%d rdma_read # %d completed\n", getpid(), i + 1);\r
+ }\r
+\r
+ /*\r
+ * Send RMR information a 3rd time to indicate completion\r
+ * NOTE: already swapped to network order in connect_ep\r
+ */\r
+ printf("%d Sending RDMA read completion message\n", getpid());\r
+\r
+ /* give remote chance to process read completes */\r
+ if (use_cno) {\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ Sleep(1000);\r
+#else\r
+ sleep(1);\r
+#endif\r
+ }\r
+\r
+ ret = send_msg(&rmr_send_msg,\r
+ sizeof(DAT_RMR_TRIPLET),\r
+ lmr_context_send_msg,\r
+ cookie, DAT_COMPLETION_SUPPRESS_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error send_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d send_msg completed\n", getpid());\r
+ }\r
+\r
+ /*\r
+ * Collect first event, write completion or the inbound recv with immed\r
+ */\r
+ printf("%d Waiting for inbound message....\n", getpid());\r
+ if (polling) {\r
+ while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==\r
+ DAT_QUEUE_EMPTY) ;\r
+ } else {\r
+ LOGPRINTF("%d waiting for message receive event\n", getpid());\r
+ if (use_cno) {\r
+ DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;\r
+ \r
+ ret = dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);\r
+ LOGPRINTF("%d cno wait return evd_handle=%p\n",\r
+ getpid(), evd);\r
+ if (evd != h_dto_rcv_evd) {\r
+ /* CNO timeout, already on EVD */\r
+ if (evd != NULL)\r
+ return (ret);\r
+ }\r
+ }\r
+ /* use wait to dequeue */\r
+ ret =\r
+ dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event, &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d: ERROR: DTO dat_evd_wait() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ }\r
+ }\r
+\r
+ /* validate event number and status */\r
+ printf("%d inbound rdma_read; send message arrived!\n", getpid());\r
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+ fprintf(stderr, "%d Error unexpected DTO event : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ if ((event.event_data.dto_completion_event_data.transfered_length !=\r
+ sizeof(DAT_RMR_TRIPLET))\r
+ || (event.event_data.dto_completion_event_data.user_cookie.as_64 !=\r
+ recv_msg_index)) {\r
+\r
+ fprintf(stderr,\r
+ "unexpected event data for receive: len=%d cookie=" F64x\r
+ " exp %d/%d\n",\r
+ (int)event.event_data.dto_completion_event_data.\r
+ transfered_length,\r
+ event.event_data.dto_completion_event_data.user_cookie.\r
+ as_64, (int)sizeof(DAT_RMR_TRIPLET), recv_msg_index);\r
+\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ /* swap received RMR msg: network order to host order */\r
+ r_iov = rmr_recv_msg[recv_msg_index];\r
+ rmr_recv_msg[recv_msg_index].virtual_address =\r
+ ntohll(rmr_recv_msg[recv_msg_index].virtual_address);\r
+ rmr_recv_msg[recv_msg_index].segment_length =\r
+ ntohl(rmr_recv_msg[recv_msg_index].segment_length);\r
+ rmr_recv_msg[recv_msg_index].rmr_context =\r
+ ntohl(rmr_recv_msg[recv_msg_index].rmr_context);\r
+\r
+ printf("%d Received RMR from remote: "\r
+ "r_iov: r_key_ctx=%x,va=" F64x ",len=0x%x\n",\r
+ getpid(), rmr_recv_msg[recv_msg_index].rmr_context,\r
+ rmr_recv_msg[recv_msg_index].virtual_address,\r
+ rmr_recv_msg[recv_msg_index].segment_length);\r
+\r
+ LOGPRINTF("%d inbound rdma_write; send msg event SUCCESS!!\n",\r
+ getpid());\r
+\r
+ printf("%d %s RCV RDMA read buffer contains: %s\n",\r
+ getpid(), server ? "SERVER:" : "CLIENT:", sbuf);\r
+\r
+ recv_msg_index++;\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+DAT_RETURN do_ping_pong_msg()\r
+{\r
+ DAT_EVENT event;\r
+ DAT_COUNT nmore;\r
+ DAT_DTO_COOKIE cookie;\r
+ DAT_LMR_TRIPLET l_iov;\r
+ DAT_RETURN ret;\r
+ int i;\r
+ char *snd_buf;\r
+ char *rcv_buf;\r
+\r
+ printf("\n %d PING DATA with SEND MSG\n\n", getpid());\r
+\r
+ snd_buf = sbuf;\r
+ rcv_buf = rbuf;\r
+\r
+ /* pre-post all buffers */\r
+ for (i = 0; i < burst; i++) {\r
+ burst_msg_posted++;\r
+ cookie.as_64 = i;\r
+ l_iov.lmr_context = lmr_context_recv;\r
+ l_iov.virtual_address = (DAT_VADDR) (uintptr_t) rcv_buf;\r
+ l_iov.segment_length = buf_len;\r
+\r
+ LOGPRINTF("%d Pre-posting Receive Message Buffers %p\n",\r
+ getpid(), rcv_buf);\r
+\r
+ ret = dat_ep_post_recv(h_ep,\r
+ 1,\r
+ &l_iov,\r
+ cookie, DAT_COMPLETION_DEFAULT_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error posting recv msg buffer: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Posted Receive Message Buffer %p\n",\r
+ getpid(), rcv_buf);\r
+ }\r
+\r
+ /* next buffer */\r
+ rcv_buf += buf_len;\r
+ }\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ Sleep(1000);\r
+#else\r
+ sleep(1);\r
+#endif\r
+\r
+ /* Initialize recv_buf and index to beginning */\r
+ rcv_buf = rbuf;\r
+ burst_msg_index = 0;\r
+\r
+ /* client ping 0x55, server pong 0xAA in first byte */\r
+ start = get_time();\r
+ for (i = 0; i < burst; i++) {\r
+ /* walk the send and recv buffers */\r
+ if (!server) {\r
+ *snd_buf = 0x55;\r
+\r
+ LOGPRINTF("%d %s SND buffer %p contains: 0x%x len=%d\n",\r
+ getpid(), server ? "SERVER:" : "CLIENT:",\r
+ snd_buf, *snd_buf, buf_len);\r
+\r
+ ret = send_msg(snd_buf,\r
+ buf_len,\r
+ lmr_context_send,\r
+ cookie, DAT_COMPLETION_SUPPRESS_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error send_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d send_msg completed\n", getpid());\r
+ }\r
+ }\r
+\r
+ /* Wait for recv message */\r
+ if (polling) {\r
+ poll_count = 0;\r
+ LOGPRINTF("%d Polling for message receive event\n",\r
+ getpid());\r
+ while (dat_evd_dequeue(h_dto_rcv_evd, &event) ==\r
+ DAT_QUEUE_EMPTY)\r
+ poll_count++;\r
+ } else {\r
+ LOGPRINTF("%d waiting for message receive event\n",\r
+ getpid());\r
+ if (use_cno) {\r
+ DAT_EVD_HANDLE evd = DAT_HANDLE_NULL;\r
+ ret =\r
+ dat_cno_wait(h_dto_cno, DTO_TIMEOUT, &evd);\r
+ LOGPRINTF("%d cno wait return evd_handle=%p\n",\r
+ getpid(), evd);\r
+ if (evd != h_dto_rcv_evd) {\r
+ /* CNO timeout, already on EVD */\r
+ if (evd != NULL)\r
+ return (ret);\r
+ }\r
+ }\r
+ /* use wait to dequeue */\r
+ ret =\r
+ dat_evd_wait(h_dto_rcv_evd, DTO_TIMEOUT, 1, &event,\r
+ &nmore);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d: ERROR: DTO dat_evd_wait() %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ }\r
+ }\r
+ /* start timer after first message arrives on server */\r
+ if (i == 0) {\r
+ start = get_time();\r
+ }\r
+ /* validate event number and status */\r
+ LOGPRINTF("%d inbound message; message arrived!\n", getpid());\r
+ if (event.event_number != DAT_DTO_COMPLETION_EVENT) {\r
+ fprintf(stderr, "%d Error unexpected DTO event : %s\n",\r
+ getpid(), DT_EventToSTr(event.event_number));\r
+ return (DAT_ABORT);\r
+ }\r
+ if ((event.event_data.dto_completion_event_data.\r
+ transfered_length != buf_len)\r
+ || (event.event_data.dto_completion_event_data.user_cookie.\r
+ as_64 != burst_msg_index)) {\r
+ fprintf(stderr,\r
+ "ERR: recv event: len=%d cookie=" F64x\r
+ " exp %d/%d\n",\r
+ (int)event.event_data.dto_completion_event_data.\r
+ transfered_length,\r
+ event.event_data.dto_completion_event_data.\r
+ user_cookie.as_64, (int)buf_len,\r
+ (int)burst_msg_index);\r
+\r
+ return (DAT_ABORT);\r
+ }\r
+\r
+ LOGPRINTF("%d %s RCV buffer %p contains: 0x%x len=%d\n",\r
+ getpid(), server ? "SERVER:" : "CLIENT:",\r
+ rcv_buf, *rcv_buf, buf_len);\r
+\r
+ burst_msg_index++;\r
+\r
+ /* If server, change data and send it back to client */\r
+ if (server) {\r
+ *snd_buf = 0xaa;\r
+\r
+ LOGPRINTF("%d %s SND buffer %p contains: 0x%x len=%d\n",\r
+ getpid(), server ? "SERVER:" : "CLIENT:",\r
+ snd_buf, *snd_buf, buf_len);\r
+\r
+ ret = send_msg(snd_buf,\r
+ buf_len,\r
+ lmr_context_send,\r
+ cookie, DAT_COMPLETION_SUPPRESS_FLAG);\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error send_msg: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d send_msg completed\n", getpid());\r
+ }\r
+ }\r
+\r
+ /* next buffers */\r
+ rcv_buf += buf_len;\r
+ snd_buf += buf_len;\r
+ }\r
+ stop = get_time();\r
+ time.rtt = ((stop - start) * 1.0e6);\r
+\r
+ return (DAT_SUCCESS);\r
+}\r
+\r
+/* Register RDMA Receive buffer */\r
+DAT_RETURN register_rdma_memory(void)\r
+{\r
+ DAT_RETURN ret;\r
+ DAT_REGION_DESCRIPTION region;\r
+\r
+ region.for_va = rbuf;\r
+ start = get_time();\r
+ ret = dat_lmr_create(h_ia,\r
+ DAT_MEM_TYPE_VIRTUAL,\r
+ region,\r
+ buf_len * (burst+1),\r
+ h_pz,\r
+ DAT_MEM_PRIV_ALL_FLAG,\r
+ DAT_VA_TYPE_VA,\r
+ &h_lmr_recv,\r
+ &lmr_context_recv,\r
+ &rmr_context_recv,\r
+ ®istered_size_recv, ®istered_addr_recv);\r
+ stop = get_time();\r
+ time.reg += ((stop - start) * 1.0e6);\r
+ time.total += time.reg;\r
+\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr,\r
+ "%d Error registering Receive RDMA buffer: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Registered Receive RDMA Buffer %p\n",\r
+ getpid(), region.for_va);\r
+ }\r
+\r
+ /* Register RDMA Send buffer */\r
+ region.for_va = sbuf;\r
+ ret = dat_lmr_create(h_ia,\r
+ DAT_MEM_TYPE_VIRTUAL,\r
+ region,\r
+ buf_len * (burst + 1),\r
+ h_pz,\r
+ DAT_MEM_PRIV_ALL_FLAG,\r
+ DAT_VA_TYPE_VA,\r
+ &h_lmr_send,\r
+ &lmr_context_send,\r
+ &rmr_context_send,\r
+ ®istered_size_send, ®istered_addr_send);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error registering send RDMA buffer: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Registered Send RDMA Buffer %p\n",\r
+ getpid(), region.for_va);\r
+ }\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+/*\r
+ * Unregister RDMA memory\r
+ */\r
+DAT_RETURN unregister_rdma_memory(void)\r
+{\r
+ DAT_RETURN ret;\r
+\r
+ /* Unregister Recv Buffer */\r
+ if (h_lmr_recv != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Unregister h_lmr %p \n", getpid(), h_lmr_recv);\r
+ start = get_time();\r
+ ret = dat_lmr_free(h_lmr_recv);\r
+ stop = get_time();\r
+ time.unreg += ((stop - start) * 1.0e6);\r
+ time.total += time.unreg;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error deregistering recv mr: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Unregistered Recv Buffer\n", getpid());\r
+ h_lmr_recv = NULL;\r
+ }\r
+ }\r
+\r
+ /* Unregister Send Buffer */\r
+ if (h_lmr_send != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Unregister h_lmr %p \n", getpid(), h_lmr_send);\r
+ ret = dat_lmr_free(h_lmr_send);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error deregistering send mr: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Unregistered send Buffer\n", getpid());\r
+ h_lmr_send = NULL;\r
+ }\r
+ }\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+ /*\r
+ * Create CNO, CR, CONN, and DTO events\r
+ */\r
+DAT_RETURN create_events(void)\r
+{\r
+ DAT_RETURN ret;\r
+ DAT_EVD_PARAM param;\r
+\r
+ /* create CNO */\r
+ if (use_cno) {\r
+ start = get_time();\r
+#if defined(_WIN32) || defined(_WIN64)\r
+ {\r
+ DAT_OS_WAIT_PROXY_AGENT pa = { NULL, NULL };\r
+ ret = dat_cno_create(h_ia, pa, &h_dto_cno);\r
+ }\r
+#else\r
+ ret =\r
+ dat_cno_create(h_ia, DAT_OS_WAIT_PROXY_AGENT_NULL,\r
+ &h_dto_cno);\r
+#endif\r
+ stop = get_time();\r
+ time.cnoc += ((stop - start) * 1.0e6);\r
+ time.total += time.cnoc;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_cno_create: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d cr_evd created, %p\n", getpid(),\r
+ h_dto_cno);\r
+ }\r
+ }\r
+\r
+ /* create cr EVD */\r
+ start = get_time();\r
+ ret =\r
+ dat_evd_create(h_ia, 10, DAT_HANDLE_NULL, DAT_EVD_CR_FLAG,\r
+ &h_cr_evd);\r
+ stop = get_time();\r
+ time.evdc += ((stop - start) * 1.0e6);\r
+ time.total += time.evdc;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_create: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d cr_evd created %p\n", getpid(), h_cr_evd);\r
+ }\r
+\r
+ /* create conn EVD */\r
+ ret = dat_evd_create(h_ia,\r
+ 10,\r
+ DAT_HANDLE_NULL,\r
+ DAT_EVD_CONNECTION_FLAG, &h_conn_evd);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_create: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d con_evd created %p\n", getpid(), h_conn_evd);\r
+ }\r
+\r
+ /* create dto SND EVD, with CNO if use_cno was set */\r
+ ret = dat_evd_create(h_ia,\r
+ (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2,\r
+ h_dto_cno, DAT_EVD_DTO_FLAG, &h_dto_req_evd);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_create REQ: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d dto_req_evd created %p\n", getpid(),\r
+ h_dto_req_evd);\r
+ }\r
+\r
+ /* create dto RCV EVD, with CNO if use_cno was set */\r
+ ret = dat_evd_create(h_ia,\r
+ MSG_BUF_COUNT + burst,\r
+ h_dto_cno, DAT_EVD_DTO_FLAG, &h_dto_rcv_evd);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_create RCV: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d dto_rcv_evd created %p\n", getpid(),\r
+ h_dto_rcv_evd);\r
+ }\r
+\r
+ /* query DTO req EVD and check size */\r
+ ret = dat_evd_query(h_dto_req_evd, DAT_EVD_FIELD_EVD_QLEN, ¶m);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error dat_evd_query request evd: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else if (param.evd_qlen < (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2) {\r
+ fprintf(stderr, "%d Error dat_evd qsize too small: %d < %d\n",\r
+ getpid(), param.evd_qlen,\r
+ (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2);\r
+ return (ret);\r
+ }\r
+\r
+ LOGPRINTF("%d dto_req_evd QLEN - requested %d and actual %d\n",\r
+ getpid(), (MSG_BUF_COUNT + MAX_RDMA_RD + burst) * 2,\r
+ param.evd_qlen);\r
+\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+/*\r
+ * Destroy CR, CONN, CNO, and DTO events\r
+ */\r
+\r
+DAT_RETURN destroy_events(void)\r
+{\r
+ DAT_RETURN ret;\r
+\r
+ /* free cr EVD */\r
+ if (h_cr_evd != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Free cr EVD %p \n", getpid(), h_cr_evd);\r
+ ret = dat_evd_free(h_cr_evd);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing cr EVD: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Freed cr EVD\n", getpid());\r
+ h_cr_evd = DAT_HANDLE_NULL;\r
+ }\r
+ }\r
+\r
+ /* free conn EVD */\r
+ if (h_conn_evd != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Free conn EVD %p \n", getpid(), h_conn_evd);\r
+ ret = dat_evd_free(h_conn_evd);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing conn EVD: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Freed conn EVD\n", getpid());\r
+ h_conn_evd = DAT_HANDLE_NULL;\r
+ }\r
+ }\r
+\r
+ /* free RCV dto EVD */\r
+ if (h_dto_rcv_evd != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Free RCV dto EVD %p \n", getpid(), h_dto_rcv_evd);\r
+ start = get_time();\r
+ ret = dat_evd_free(h_dto_rcv_evd);\r
+ stop = get_time();\r
+ time.evdf += ((stop - start) * 1.0e6);\r
+ time.total += time.evdf;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing dto EVD: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Freed dto EVD\n", getpid());\r
+ h_dto_rcv_evd = DAT_HANDLE_NULL;\r
+ }\r
+ }\r
+\r
+ /* free REQ dto EVD */\r
+ if (h_dto_req_evd != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Free REQ dto EVD %p \n", getpid(), h_dto_req_evd);\r
+ ret = dat_evd_free(h_dto_req_evd);\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing dto EVD: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Freed dto EVD\n", getpid());\r
+ h_dto_req_evd = DAT_HANDLE_NULL;\r
+ }\r
+ }\r
+\r
+ /* free CNO */\r
+ if (h_dto_cno != DAT_HANDLE_NULL) {\r
+ LOGPRINTF("%d Free dto CNO %p \n", getpid(), h_dto_cno);\r
+ start = get_time();\r
+ ret = dat_cno_free(h_dto_cno);\r
+ stop = get_time();\r
+ time.cnof += ((stop - start) * 1.0e6);\r
+ time.total += time.cnof;\r
+ if (ret != DAT_SUCCESS) {\r
+ fprintf(stderr, "%d Error freeing dto CNO: %s\n",\r
+ getpid(), DT_RetToString(ret));\r
+ return (ret);\r
+ } else {\r
+ LOGPRINTF("%d Freed dto CNO\n", getpid());\r
+ h_dto_cno = DAT_HANDLE_NULL;\r
+ }\r
+ }\r
+ return DAT_SUCCESS;\r
+}\r
+\r
+/*\r
+ * Map DAT_RETURN values to readable strings,\r
+ * but don't assume the values are zero-based or contiguous.\r
+ */\r
+char errmsg[512] = { 0 };\r
+const char *DT_RetToString(DAT_RETURN ret_value)\r
+{\r
+ const char *major_msg, *minor_msg;\r
+\r
+ dat_strerror(ret_value, &major_msg, &minor_msg);\r
+\r
+ strcpy(errmsg, major_msg);\r
+ strcat(errmsg, " ");\r
+ strcat(errmsg, minor_msg);\r
+\r
+ return errmsg;\r
+}\r
+\r
+/*\r
+ * Map DAT_EVENT_CODE values to readable strings\r
+ */\r
+const char *DT_EventToSTr(DAT_EVENT_NUMBER event_code)\r
+{\r
+ unsigned int i;\r
+ static struct {\r
+ const char *name;\r
+ DAT_RETURN value;\r
+ } dat_events[] = {\r
+# define DATxx(x) { # x, x }\r
+ DATxx(DAT_DTO_COMPLETION_EVENT),\r
+ DATxx(DAT_RMR_BIND_COMPLETION_EVENT),\r
+ DATxx(DAT_CONNECTION_REQUEST_EVENT),\r
+ DATxx(DAT_CONNECTION_EVENT_ESTABLISHED),\r
+ DATxx(DAT_CONNECTION_EVENT_PEER_REJECTED),\r
+ DATxx(DAT_CONNECTION_EVENT_NON_PEER_REJECTED),\r
+ DATxx(DAT_CONNECTION_EVENT_ACCEPT_COMPLETION_ERROR),\r
+ DATxx(DAT_CONNECTION_EVENT_DISCONNECTED),\r
+ DATxx(DAT_CONNECTION_EVENT_BROKEN),\r
+ DATxx(DAT_CONNECTION_EVENT_TIMED_OUT),\r
+ DATxx(DAT_CONNECTION_EVENT_UNREACHABLE),\r
+ DATxx(DAT_ASYNC_ERROR_EVD_OVERFLOW),\r
+ DATxx(DAT_ASYNC_ERROR_IA_CATASTROPHIC),\r
+ DATxx(DAT_ASYNC_ERROR_EP_BROKEN),\r
+ DATxx(DAT_ASYNC_ERROR_TIMED_OUT),\r
+ DATxx(DAT_ASYNC_ERROR_PROVIDER_INTERNAL_ERROR),\r
+ DATxx(DAT_SOFTWARE_EVENT)\r
+# undef DATxx\r
+ };\r
+# define NUM_EVENTS (sizeof(dat_events)/sizeof(dat_events[0]))\r
+\r
+ for (i = 0; i < NUM_EVENTS; i++) {\r
+ if (dat_events[i].value == event_code) {\r
+ return (dat_events[i].name);\r
+ }\r
+ }\r
+\r
+ return ("Invalid_DAT_EVENT_NUMBER");\r
+}\r
+\r
+void print_usage(void)\r
+{\r
+ printf("\n DAPL USAGE \n\n");\r
+ printf("s: server\n");\r
+ printf("t: performance times\n");\r
+ printf("c: use cno\n");\r
+ printf("v: verbose\n");\r
+ printf("p: polling\n");\r
+ printf("d: delay before accept\n");\r
+ printf("b: buf length to allocate\n");\r
+ printf("B: burst count, rdma and msgs \n");\r
+ printf("h: hostname/address of server, specified on client\n");\r
+ printf("P: provider name (default = OpenIB-cma)\n");\r
+ printf("\n");\r
+}\r
+\r