19e39c5baSBill Taylor /*
29e39c5baSBill Taylor  * CDDL HEADER START
39e39c5baSBill Taylor  *
49e39c5baSBill Taylor  * The contents of this file are subject to the terms of the
59e39c5baSBill Taylor  * Common Development and Distribution License (the "License").
69e39c5baSBill Taylor  * You may not use this file except in compliance with the License.
79e39c5baSBill Taylor  *
89e39c5baSBill Taylor  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
99e39c5baSBill Taylor  * or http://www.opensolaris.org/os/licensing.
109e39c5baSBill Taylor  * See the License for the specific language governing permissions
119e39c5baSBill Taylor  * and limitations under the License.
129e39c5baSBill Taylor  *
139e39c5baSBill Taylor  * When distributing Covered Code, include this CDDL HEADER in each
149e39c5baSBill Taylor  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
159e39c5baSBill Taylor  * If applicable, add the following below this CDDL HEADER, with the
169e39c5baSBill Taylor  * fields enclosed by brackets "[]" replaced with your own identifying
179e39c5baSBill Taylor  * information: Portions Copyright [yyyy] [name of copyright owner]
189e39c5baSBill Taylor  *
199e39c5baSBill Taylor  * CDDL HEADER END
209e39c5baSBill Taylor  */
219e39c5baSBill Taylor 
229e39c5baSBill Taylor /*
239e39c5baSBill Taylor  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
249e39c5baSBill Taylor  */
259e39c5baSBill Taylor 
269e39c5baSBill Taylor /*
279e39c5baSBill Taylor  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
289e39c5baSBill Taylor  * Use is subject to license terms.
299e39c5baSBill Taylor  */
309e39c5baSBill Taylor 
319e39c5baSBill Taylor /*
329e39c5baSBill Taylor  *
339e39c5baSBill Taylor  * MODULE: dapl_evd_util.c
349e39c5baSBill Taylor  *
359e39c5baSBill Taylor  * PURPOSE: Manage EVD Info structure
369e39c5baSBill Taylor  *
379e39c5baSBill Taylor  * $Id: dapl_evd_util.c,v 1.41 2003/08/20 13:18:36 sjs2 Exp $
389e39c5baSBill Taylor  */
399e39c5baSBill Taylor 
409e39c5baSBill Taylor #include <sys/time.h>
419e39c5baSBill Taylor #include <strings.h>
429e39c5baSBill Taylor #include "dapl_evd_util.h"
439e39c5baSBill Taylor #include "dapl_ia_util.h"
449e39c5baSBill Taylor #include "dapl_cno_util.h"
459e39c5baSBill Taylor #include "dapl_ring_buffer_util.h"
469e39c5baSBill Taylor #include "dapl_adapter_util.h"
479e39c5baSBill Taylor #include "dapl_tavor_ibtf_impl.h"
489e39c5baSBill Taylor #include "dapl_cookie.h"
499e39c5baSBill Taylor #include "dapl.h"
509e39c5baSBill Taylor 
519e39c5baSBill Taylor 
529e39c5baSBill Taylor #ifdef	DAPL_DBG	/* For debugging.  */
539e39c5baSBill Taylor static void
549e39c5baSBill Taylor dapli_evd_eh_print_cqe(
559e39c5baSBill Taylor 	IN  ib_work_completion_t	cqe);
569e39c5baSBill Taylor #endif
579e39c5baSBill Taylor 
589e39c5baSBill Taylor static DAT_BOOLEAN
599e39c5baSBill Taylor dapli_evd_cqe_to_event(
609e39c5baSBill Taylor     IN DAPL_EVD			*evd_ptr,
619e39c5baSBill Taylor     IN ib_work_completion_t	*cqe_ptr,
629e39c5baSBill Taylor     IN DAT_BOOLEAN		process_premature_events,
639e39c5baSBill Taylor     OUT DAT_EVENT		*event_ptr);
649e39c5baSBill Taylor 
659e39c5baSBill Taylor static DAT_RETURN
669e39c5baSBill Taylor dapli_evd_event_alloc(
679e39c5baSBill Taylor 	IN  DAPL_EVD		*evd_ptr,
689e39c5baSBill Taylor 	IN  DAPL_CNO		*cno_ptr,
699e39c5baSBill Taylor 	IN  DAT_COUNT		qlen);
709e39c5baSBill Taylor 
719e39c5baSBill Taylor 
729e39c5baSBill Taylor /*
739e39c5baSBill Taylor  * dapls_evd_internal_create
749e39c5baSBill Taylor  *
759e39c5baSBill Taylor  * actually create the evd.  this is called after all parameter checking
769e39c5baSBill Taylor  * has been performed in dapl_ep_create.  it is also called from dapl_ia_open
779e39c5baSBill Taylor  * to create the default async evd.
789e39c5baSBill Taylor  *
799e39c5baSBill Taylor  * Input:
80*93fec3daSToomas Soome  *	ia_ptr
819e39c5baSBill Taylor  *	cno_ptr
829e39c5baSBill Taylor  *	qlen
839e39c5baSBill Taylor  *	evd_flags
849e39c5baSBill Taylor  *
859e39c5baSBill Taylor  * Output:
86*93fec3daSToomas Soome  *	evd_ptr_ptr
879e39c5baSBill Taylor  *
889e39c5baSBill Taylor  * Returns:
89*93fec3daSToomas Soome  *	none
909e39c5baSBill Taylor  *
919e39c5baSBill Taylor  */
929e39c5baSBill Taylor 
939e39c5baSBill Taylor 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)949e39c5baSBill Taylor dapls_evd_internal_create(
959e39c5baSBill Taylor     DAPL_IA		*ia_ptr,
969e39c5baSBill Taylor     DAPL_CNO		*cno_ptr,
979e39c5baSBill Taylor     DAT_COUNT		min_qlen,
989e39c5baSBill Taylor     DAT_EVD_FLAGS	evd_flags,
999e39c5baSBill Taylor     DAPL_EVD		**evd_ptr_ptr)
1009e39c5baSBill Taylor {
1019e39c5baSBill Taylor 	DAPL_EVD	*evd_ptr;
1029e39c5baSBill Taylor 	DAT_COUNT	cq_len;
1039e39c5baSBill Taylor 	DAT_RETURN	dat_status;
1049e39c5baSBill Taylor 
1059e39c5baSBill Taylor 	dat_status	= DAT_SUCCESS;
1069e39c5baSBill Taylor 	*evd_ptr_ptr	= NULL;
1079e39c5baSBill Taylor 	cq_len		= min_qlen;
1089e39c5baSBill Taylor 
1099e39c5baSBill Taylor 	evd_ptr = dapls_evd_alloc(ia_ptr,
1109e39c5baSBill Taylor 	    cno_ptr,
1119e39c5baSBill Taylor 	    evd_flags,
1129e39c5baSBill Taylor 	    min_qlen);
1139e39c5baSBill Taylor 	if (!evd_ptr) {
1149e39c5baSBill Taylor 		dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
1159e39c5baSBill Taylor 		    DAT_RESOURCE_MEMORY);
1169e39c5baSBill Taylor 		goto bail;
1179e39c5baSBill Taylor 	}
1189e39c5baSBill Taylor 
1199e39c5baSBill Taylor 	/*
1209e39c5baSBill Taylor 	 * If we are dealing with event streams besides a CQ event stream,
1219e39c5baSBill Taylor 	 * be conservative and set producer side locking.  Otherwise, no.
1229e39c5baSBill Taylor 	 */
1239e39c5baSBill Taylor 	evd_ptr->evd_producer_locking_needed =
1249e39c5baSBill Taylor 	    ((evd_flags & ~ (DAT_EVD_DTO_FLAG|DAT_EVD_RMR_BIND_FLAG)) != 0);
1259e39c5baSBill Taylor 
1269e39c5baSBill Taylor 	/* Before we setup any callbacks, transition state to OPEN.  */
1279e39c5baSBill Taylor 	evd_ptr->evd_state = DAPL_EVD_STATE_OPEN;
1289e39c5baSBill Taylor 
1299e39c5baSBill Taylor 	/*
1309e39c5baSBill Taylor 	 * we need to call cq_alloc even for connection/cr/async evds
1319e39c5baSBill Taylor 	 * since all the allocation happens there.
1329e39c5baSBill Taylor 	 */
1339e39c5baSBill Taylor 	dat_status = dapls_ib_cq_alloc(ia_ptr,
1349e39c5baSBill Taylor 	    evd_ptr, cno_ptr, &cq_len);
1359e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
1369e39c5baSBill Taylor 		goto bail;
1379e39c5baSBill Taylor 	}
1389e39c5baSBill Taylor 
139*93fec3daSToomas Soome #if 0
140*93fec3daSToomas Soome 	/*
141*93fec3daSToomas Soome 	 * Current implementation of dapls_ib_setup_async_callback() does
142*93fec3daSToomas Soome 	 * nothing and returns DAT_SUCCESS. However, it is declared to expect
143*93fec3daSToomas Soome 	 * function pointers with different signatures. We do leave the code
144*93fec3daSToomas Soome 	 * block out till dapls_ib_setup_async_callback() is implemented.
145*93fec3daSToomas Soome 	 */
1469e39c5baSBill Taylor 	dat_status = dapls_ib_setup_async_callback(
1479e39c5baSBill Taylor 	    ia_ptr,
1489e39c5baSBill Taylor 	    DAPL_ASYNC_CQ_COMPLETION,
1499e39c5baSBill Taylor 	    (unsigned int *) evd_ptr->ib_cq_handle,
1509e39c5baSBill Taylor 	    (ib_async_handler_t)dapl_evd_dto_callback,
1519e39c5baSBill Taylor 	    evd_ptr);
1529e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
1539e39c5baSBill Taylor 		goto bail;
1549e39c5baSBill Taylor 	}
155*93fec3daSToomas Soome #endif
1569e39c5baSBill Taylor 	/*
1579e39c5baSBill Taylor 	 * cq_notify is not required since when evd_wait is called
1589e39c5baSBill Taylor 	 * time we go and poll cq anyways.
1599e39c5baSBill Taylor 	 * dat_status = dapls_set_cq_notify(ia_ptr, evd_ptr);
1609e39c5baSBill Taylor 	 */
1619e39c5baSBill Taylor 
1629e39c5baSBill Taylor 	/*
1639e39c5baSBill Taylor 	 * We now have an accurate count of events, so allocate them into
1649e39c5baSBill Taylor 	 * the EVD
1659e39c5baSBill Taylor 	 */
1669e39c5baSBill Taylor 	dat_status = dapli_evd_event_alloc(evd_ptr, cno_ptr, cq_len);
1679e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
1689e39c5baSBill Taylor 		goto bail;
1699e39c5baSBill Taylor 	}
1709e39c5baSBill Taylor 
1719e39c5baSBill Taylor 	/* We're assuming success in the following.   */
1729e39c5baSBill Taylor 	dapl_os_assert(dat_status == DAT_SUCCESS);
1739e39c5baSBill Taylor 	dapl_ia_link_evd(ia_ptr, evd_ptr);
1749e39c5baSBill Taylor 	*evd_ptr_ptr = evd_ptr;
1759e39c5baSBill Taylor 
1769e39c5baSBill Taylor bail:
1779e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
1789e39c5baSBill Taylor 		if (evd_ptr) {
1799e39c5baSBill Taylor 			(void) dapls_evd_dealloc(evd_ptr);
1809e39c5baSBill Taylor 		}
1819e39c5baSBill Taylor 	}
1829e39c5baSBill Taylor 
1839e39c5baSBill Taylor 	return (dat_status);
1849e39c5baSBill Taylor }
1859e39c5baSBill Taylor 
1869e39c5baSBill Taylor /*
1879e39c5baSBill Taylor  * dapls_evd_alloc
1889e39c5baSBill Taylor  *
1899e39c5baSBill Taylor  * alloc and initialize an EVD struct
1909e39c5baSBill Taylor  *
1919e39c5baSBill Taylor  * Input:
192*93fec3daSToomas Soome  *	ia
1939e39c5baSBill Taylor  *
1949e39c5baSBill Taylor  * Output:
195*93fec3daSToomas Soome  *	evd_ptr
1969e39c5baSBill Taylor  *
1979e39c5baSBill Taylor  * Returns:
198*93fec3daSToomas Soome  *	none
1999e39c5baSBill Taylor  *
2009e39c5baSBill Taylor  */
2019e39c5baSBill Taylor 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)2029e39c5baSBill Taylor dapls_evd_alloc(
2039e39c5baSBill Taylor     IN DAPL_IA		*ia_ptr,
2049e39c5baSBill Taylor     IN DAPL_CNO		*cno_ptr,
2059e39c5baSBill Taylor     IN DAT_EVD_FLAGS	evd_flags,
2069e39c5baSBill Taylor     IN DAT_COUNT	qlen) /* ARGSUSED */
2079e39c5baSBill Taylor {
2089e39c5baSBill Taylor 	DAPL_EVD	*evd_ptr;
2099e39c5baSBill Taylor 
2109e39c5baSBill Taylor 	evd_ptr    = NULL;
2119e39c5baSBill Taylor 
2129e39c5baSBill Taylor 	/* Allocate EVD */
2139e39c5baSBill Taylor 	evd_ptr = (DAPL_EVD *)dapl_os_alloc(sizeof (DAPL_EVD));
2149e39c5baSBill Taylor 	if (!evd_ptr) {
2159e39c5baSBill Taylor 		goto bail;
2169e39c5baSBill Taylor 	}
2179e39c5baSBill Taylor 
2189e39c5baSBill Taylor 	/* zero the structure */
2199e39c5baSBill Taylor 	(void) dapl_os_memzero(evd_ptr, sizeof (DAPL_EVD));
2209e39c5baSBill Taylor 
2219e39c5baSBill Taylor 	/*
2229e39c5baSBill Taylor 	 * initialize the header
2239e39c5baSBill Taylor 	 */
2249e39c5baSBill Taylor 	evd_ptr->header.provider		= ia_ptr->header.provider;
2259e39c5baSBill Taylor 	evd_ptr->header.magic			= DAPL_MAGIC_EVD;
2269e39c5baSBill Taylor 	evd_ptr->header.handle_type		= DAT_HANDLE_TYPE_EVD;
2279e39c5baSBill Taylor 	evd_ptr->header.owner_ia		= ia_ptr;
2289e39c5baSBill Taylor 	evd_ptr->header.user_context.as_64	= 0;
2299e39c5baSBill Taylor 	evd_ptr->header.user_context.as_ptr	= NULL;
2309e39c5baSBill Taylor 	dapl_llist_init_entry(&evd_ptr->header.ia_list_entry);
2319e39c5baSBill Taylor 	dapl_os_lock_init(&evd_ptr->header.lock);
2329e39c5baSBill Taylor 
2339e39c5baSBill Taylor 	/*
2349e39c5baSBill Taylor 	 * Initialize the body
2359e39c5baSBill Taylor 	 */
2369e39c5baSBill Taylor 	evd_ptr->evd_state	= DAPL_EVD_STATE_INITIAL;
2379e39c5baSBill Taylor 	evd_ptr->evd_flags	= evd_flags;
2389e39c5baSBill Taylor 	evd_ptr->evd_enabled	= DAT_TRUE;
2399e39c5baSBill Taylor 	evd_ptr->evd_waitable	= DAT_TRUE;
2409e39c5baSBill Taylor 	evd_ptr->evd_producer_locking_needed = 1; /* Conservative value.  */
2419e39c5baSBill Taylor 	evd_ptr->ib_cq_handle	= IB_INVALID_HANDLE;
2429e39c5baSBill Taylor 	evd_ptr->evd_ref_count	= 0;
2439e39c5baSBill Taylor 	evd_ptr->catastrophic_overflow = DAT_FALSE;
2449e39c5baSBill Taylor 	evd_ptr->qlen		= qlen;
2459e39c5baSBill Taylor 
2469e39c5baSBill Taylor 	dapl_llist_init_entry(&evd_ptr->cno_list_entry);
2479e39c5baSBill Taylor 	evd_ptr->completion_type = DAPL_EVD_STATE_THRESHOLD;
2489e39c5baSBill Taylor 	(void) dapl_os_wait_object_init(&evd_ptr->wait_object);
2499e39c5baSBill Taylor 
2509e39c5baSBill Taylor bail:
2519e39c5baSBill Taylor 	return (evd_ptr);
2529e39c5baSBill Taylor }
2539e39c5baSBill Taylor 
2549e39c5baSBill Taylor 
2559e39c5baSBill Taylor /*
2569e39c5baSBill Taylor  * dapls_evd_event_alloc
2579e39c5baSBill Taylor  *
2589e39c5baSBill Taylor  * alloc events into an EVD.
2599e39c5baSBill Taylor  *
2609e39c5baSBill Taylor  * Input:
261*93fec3daSToomas Soome  *	evd_ptr
2629e39c5baSBill Taylor  *	qlen
2639e39c5baSBill Taylor  *
2649e39c5baSBill Taylor  * Output:
265*93fec3daSToomas Soome  *	NONE
2669e39c5baSBill Taylor  *
2679e39c5baSBill Taylor  * Returns:
268*93fec3daSToomas Soome  *	DAT_SUCCESS
2699e39c5baSBill Taylor  *	ERROR
2709e39c5baSBill Taylor  *
2719e39c5baSBill Taylor  */
2729e39c5baSBill Taylor DAT_RETURN
dapli_evd_event_alloc(IN DAPL_EVD * evd_ptr,IN DAPL_CNO * cno_ptr,IN DAT_COUNT qlen)2739e39c5baSBill Taylor dapli_evd_event_alloc(
2749e39c5baSBill Taylor     IN DAPL_EVD		*evd_ptr,
2759e39c5baSBill Taylor     IN  DAPL_CNO	*cno_ptr,
2769e39c5baSBill Taylor     IN DAT_COUNT	qlen)
2779e39c5baSBill Taylor {
2789e39c5baSBill Taylor 	DAT_EVENT	*event_ptr;
2799e39c5baSBill Taylor 	DAT_COUNT	i;
2809e39c5baSBill Taylor 	DAT_RETURN	dat_status;
2819e39c5baSBill Taylor 
2829e39c5baSBill Taylor 	dat_status = DAT_SUCCESS;
2839e39c5baSBill Taylor 	event_ptr  = NULL;
2849e39c5baSBill Taylor 
2859e39c5baSBill Taylor 	/* Allocate EVENTs */
2869e39c5baSBill Taylor 	event_ptr = (DAT_EVENT *) dapl_os_alloc(qlen * sizeof (DAT_EVENT));
2879e39c5baSBill Taylor 	if (!event_ptr) {
2889e39c5baSBill Taylor 		goto bail;
2899e39c5baSBill Taylor 	}
2909e39c5baSBill Taylor 	evd_ptr->events = event_ptr;
2919e39c5baSBill Taylor 	evd_ptr->qlen = qlen;
2929e39c5baSBill Taylor 
2939e39c5baSBill Taylor 	/* allocate free event queue */
2949e39c5baSBill Taylor 	dat_status = dapls_rbuf_alloc(&evd_ptr->free_event_queue, qlen);
2959e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
2969e39c5baSBill Taylor 		goto bail;
2979e39c5baSBill Taylor 	}
2989e39c5baSBill Taylor 
2999e39c5baSBill Taylor 	/* allocate pending event queue */
3009e39c5baSBill Taylor 	dat_status = dapls_rbuf_alloc(&evd_ptr->pending_event_queue, qlen);
3019e39c5baSBill Taylor 	if (dat_status != DAT_SUCCESS) {
3029e39c5baSBill Taylor 		goto bail;
3039e39c5baSBill Taylor 	}
3049e39c5baSBill Taylor 
3059e39c5baSBill Taylor 	/* add events to free event queue */
3069e39c5baSBill Taylor 	for (i = 0; i < qlen; i++) {
3079e39c5baSBill Taylor 		dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue,
3089e39c5baSBill Taylor 		    (void *)event_ptr);
3099e39c5baSBill Taylor 		dapl_os_assert(dat_status == DAT_SUCCESS);
3109e39c5baSBill Taylor 		event_ptr++;
3119e39c5baSBill Taylor 	}
3129e39c5baSBill Taylor 	evd_ptr->cq_notified = DAT_FALSE;
3139e39c5baSBill Taylor 	evd_ptr->cq_notified_when = 0;
3149e39c5baSBill Taylor 	evd_ptr->cno_active_count = 0;
3159e39c5baSBill Taylor 	if (cno_ptr != NULL) {
3169e39c5baSBill Taylor 		dapl_os_lock(&cno_ptr->header.lock);
3179e39c5baSBill Taylor 		dapl_llist_add_head(&cno_ptr->evd_list_head,
3189e39c5baSBill Taylor 		    &evd_ptr->cno_list_entry, evd_ptr);
3199e39c5baSBill Taylor 		/* Take a reference count on the CNO */
3209e39c5baSBill Taylor 		dapl_os_atomic_inc(&cno_ptr->cno_ref_count);
3219e39c5baSBill Taylor 		dapl_os_unlock(&cno_ptr->header.lock);
3229e39c5baSBill Taylor 	}
3239e39c5baSBill Taylor 	evd_ptr->cno_ptr = cno_ptr;
3249e39c5baSBill Taylor 	evd_ptr->threshold = 0;
3259e39c5baSBill Taylor 
3269e39c5baSBill Taylor bail:
3279e39c5baSBill Taylor 	return (dat_status);
3289e39c5baSBill Taylor }
3299e39c5baSBill Taylor 
3309e39c5baSBill Taylor 
3319e39c5baSBill Taylor /*
3329e39c5baSBill Taylor  * dapls_evd_dealloc
3339e39c5baSBill Taylor  *
3349e39c5baSBill Taylor  * Free the passed in EVD structure. If an error occurs, this function
3359e39c5baSBill Taylor  * will clean up all of the internal data structures and report the
3369e39c5baSBill Taylor  * error.
3379e39c5baSBill Taylor  *
3389e39c5baSBill Taylor  * Input:
339*93fec3daSToomas Soome  *	evd_ptr
3409e39c5baSBill Taylor  *
3419e39c5baSBill Taylor  * Output:
342*93fec3daSToomas Soome  *	none
3439e39c5baSBill Taylor  *
3449e39c5baSBill Taylor  * Returns:
345*93fec3daSToomas Soome  *	status
3469e39c5baSBill Taylor  *
3479e39c5baSBill Taylor  */
3489e39c5baSBill Taylor DAT_RETURN
dapls_evd_dealloc(IN DAPL_EVD * evd_ptr)3499e39c5baSBill Taylor dapls_evd_dealloc(
3509e39c5baSBill Taylor     IN DAPL_EVD		*evd_ptr)
3519e39c5baSBill Taylor {
3529e39c5baSBill Taylor 	DAT_RETURN	dat_status;
3539e39c5baSBill Taylor 	DAPL_IA	*ia_ptr;
3549e39c5baSBill Taylor 
3559e39c5baSBill Taylor 	dat_status = DAT_SUCCESS;
3569e39c5baSBill Taylor 
3579e39c5baSBill Taylor 	dapl_os_assert(evd_ptr->header.magic == DAPL_MAGIC_EVD);
3589e39c5baSBill Taylor 	dapl_os_assert(evd_ptr->evd_ref_count == 0);
3599e39c5baSBill Taylor 
3609e39c5baSBill Taylor 	/*
3619e39c5baSBill Taylor 	 * Destroy the CQ first, to keep any more callbacks from coming
3629e39c5baSBill Taylor 	 * up from it.
3639e39c5baSBill Taylor 	 */
3649e39c5baSBill Taylor 	if (evd_ptr->ib_cq_handle != IB_INVALID_HANDLE) {
3659e39c5baSBill Taylor 		ia_ptr = evd_ptr->header.owner_ia;
3669e39c5baSBill Taylor 
3679e39c5baSBill Taylor 		dat_status = dapls_ib_cq_free(ia_ptr, evd_ptr);
3689e39c5baSBill Taylor 		if (dat_status != DAT_SUCCESS) {
3699e39c5baSBill Taylor 			goto bail;
3709e39c5baSBill Taylor 		}
3719e39c5baSBill Taylor 	}
3729e39c5baSBill Taylor 
3739e39c5baSBill Taylor 	/*
3749e39c5baSBill Taylor 	 * We should now be safe to invalidate the EVD; reset the
3759e39c5baSBill Taylor 	 * magic to prevent reuse.
3769e39c5baSBill Taylor 	 */
3779e39c5baSBill Taylor 	evd_ptr->header.magic = DAPL_MAGIC_INVALID;
3789e39c5baSBill Taylor 
3799e39c5baSBill Taylor 	/* Release reference on the CNO if it exists */
3809e39c5baSBill Taylor 	if (evd_ptr->cno_ptr != NULL) {
3819e39c5baSBill Taylor 		dapl_os_lock(&evd_ptr->cno_ptr->header.lock);
3829e39c5baSBill Taylor 		(void) dapl_llist_remove_entry(&evd_ptr->cno_ptr->evd_list_head,
3839e39c5baSBill Taylor 		    &evd_ptr->cno_list_entry);
3849e39c5baSBill Taylor 		dapl_os_atomic_dec(&evd_ptr->cno_ptr->cno_ref_count);
3859e39c5baSBill Taylor 		dapl_os_unlock(&evd_ptr->cno_ptr->header.lock);
3869e39c5baSBill Taylor 	}
3879e39c5baSBill Taylor 
3889e39c5baSBill Taylor 	/*
3899e39c5baSBill Taylor 	 * If the ring buffer allocation failed, then the dapls_rbuf_destroy
3909e39c5baSBill Taylor 	 * function will detect that the ring buffer's internal data (ex. base
3919e39c5baSBill Taylor 	 * pointer) are invalid and will handle the situation appropriately
3929e39c5baSBill Taylor 	 */
3939e39c5baSBill Taylor 	dapls_rbuf_destroy(&evd_ptr->free_event_queue);
3949e39c5baSBill Taylor 	dapls_rbuf_destroy(&evd_ptr->pending_event_queue);
3959e39c5baSBill Taylor 
3969e39c5baSBill Taylor 	if (evd_ptr->events) {
3979e39c5baSBill Taylor 		dapl_os_free(evd_ptr->events,
3989e39c5baSBill Taylor 		    evd_ptr->qlen * sizeof (DAT_EVENT));
3999e39c5baSBill Taylor 	}
4009e39c5baSBill Taylor 
4019e39c5baSBill Taylor 	(void) dapl_os_wait_object_destroy(&evd_ptr->wait_object);
4029e39c5baSBill Taylor 	dapl_os_free(evd_ptr, sizeof (DAPL_EVD));
4039e39c5baSBill Taylor 
4049e39c5baSBill Taylor bail:
4059e39c5baSBill Taylor 	return (dat_status);
4069e39c5baSBill Taylor }
4079e39c5baSBill Taylor 
4089e39c5baSBill Taylor 
4099e39c5baSBill Taylor /*
4109e39c5baSBill Taylor  * dapli_evd_eh_print_cqe
4119e39c5baSBill Taylor  *
4129e39c5baSBill Taylor  * Input:
4139e39c5baSBill Taylor  *	cqe
4149e39c5baSBill Taylor  *
4159e39c5baSBill Taylor  * Output:
4169e39c5baSBill Taylor  *	none
4179e39c5baSBill Taylor  *
4189e39c5baSBill Taylor  * Prints out a CQE for debug purposes
4199e39c5baSBill Taylor  *
4209e39c5baSBill Taylor  */
4219e39c5baSBill Taylor 
4229e39c5baSBill Taylor #ifdef	DAPL_DBG	/* For debugging.  */
4239e39c5baSBill Taylor void
dapli_evd_eh_print_cqe(IN ib_work_completion_t cqe)424*93fec3daSToomas Soome dapli_evd_eh_print_cqe(IN ib_work_completion_t cqe)
4259e39c5baSBill Taylor {
4269e39c5baSBill Taylor 	static char *optable[] = {
4279e39c5baSBill Taylor 		"",
4289e39c5baSBill Taylor 		"OP_SEND",
4299e39c5baSBill Taylor 		"OP_RDMA_READ",
4309e39c5baSBill Taylor 		"OP_RDMA_WRITE",
4319e39c5baSBill Taylor 		"OP_COMP_AND_SWAP",
4329e39c5baSBill Taylor 		"OP_FETCH_AND_ADD",
4339e39c5baSBill Taylor 		"OP_BIND_MW",
4349e39c5baSBill Taylor 		"OP_RECEIVE",
4359e39c5baSBill Taylor 		"OP_RECEIVE_RDMAWI",
4369e39c5baSBill Taylor 		0
4379e39c5baSBill Taylor 	};
4389e39c5baSBill Taylor 	DAPL_COOKIE		*dto_cookie;
4399e39c5baSBill Taylor 
4409e39c5baSBill Taylor 	dto_cookie = (DAPL_COOKIE *) (uintptr_t)DAPL_GET_CQE_WRID(&cqe);
4419e39c5baSBill Taylor 
4429e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4439e39c5baSBill Taylor 	    "\t >>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<\n");
4449e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4459e39c5baSBill Taylor 	    "\t dapl_evd_dto_callback : CQE \n");
4469e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4479e39c5baSBill Taylor 	    "\t\t work_req_id 0x%llx\n", DAPL_GET_CQE_WRID(&cqe));
4489e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4499e39c5baSBill Taylor 	    "\t\t op_type: %s\n", optable[DAPL_GET_CQE_OPTYPE(&cqe)]);
4509e39c5baSBill Taylor 	if ((DAPL_GET_CQE_OPTYPE(&cqe) == OP_SEND) ||
4519e39c5baSBill Taylor 	    (DAPL_GET_CQE_OPTYPE(&cqe) == OP_RDMA_WRITE)) {
4529e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4539e39c5baSBill Taylor 		    "\t\t bytes_num %d\n", dto_cookie->val.dto.size);
4549e39c5baSBill Taylor 	} else {
4559e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4569e39c5baSBill Taylor 		    "\t\t bytes_num %d\n", DAPL_GET_CQE_BYTESNUM(&cqe));
4579e39c5baSBill Taylor 	}
4589e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4599e39c5baSBill Taylor 	    "\t\t status %d\n", DAPL_GET_CQE_STATUS(&cqe));
4609e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_CALLBACK,
4619e39c5baSBill Taylor 	    "\t >>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<\n");
4629e39c5baSBill Taylor }
4639e39c5baSBill Taylor #endif
4649e39c5baSBill Taylor 
4659e39c5baSBill Taylor /*
4669e39c5baSBill Taylor  * Event posting code follows.
4679e39c5baSBill Taylor  */
4689e39c5baSBill Taylor 
4699e39c5baSBill Taylor /*
4709e39c5baSBill Taylor  * These next two functions (dapli_evd_get_event and dapli_evd_post_event)
4719e39c5baSBill Taylor  * are a pair.  They are always called together, from one of the functions
4729e39c5baSBill Taylor  * at the end of this file (dapl_evd_post_*_event).
4739e39c5baSBill Taylor  *
4749e39c5baSBill Taylor  * Note that if producer side locking is enabled, the first one takes the
4759e39c5baSBill Taylor  * EVD lock and the second releases it.
4769e39c5baSBill Taylor  */
4779e39c5baSBill Taylor 
4789e39c5baSBill Taylor /*
4799e39c5baSBill Taylor  * dapli_evd_get_event
4809e39c5baSBill Taylor  *
4819e39c5baSBill Taylor  * Get an event struct from the evd.  The caller should fill in the event
4829e39c5baSBill Taylor  * and call dapl_evd_post_event.
4839e39c5baSBill Taylor  *
4849e39c5baSBill Taylor  * If there are no events available, an overflow event is generated to the
4859e39c5baSBill Taylor  * async EVD handler.
4869e39c5baSBill Taylor  *
4879e39c5baSBill Taylor  * If this EVD required producer locking, a successful return implies
4889e39c5baSBill Taylor  * that the lock is held.
4899e39c5baSBill Taylor  *
4909e39c5baSBill Taylor  * Input:
491*93fec3daSToomas Soome  *	evd_ptr
4929e39c5baSBill Taylor  *
4939e39c5baSBill Taylor  * Output:
4949e39c5baSBill Taylor  *	event
4959e39c5baSBill Taylor  *
4969e39c5baSBill Taylor  */
4979e39c5baSBill Taylor 
4989e39c5baSBill Taylor static DAT_EVENT *
dapli_evd_get_event(DAPL_EVD * evd_ptr)4999e39c5baSBill Taylor dapli_evd_get_event(
5009e39c5baSBill Taylor     DAPL_EVD *evd_ptr)
5019e39c5baSBill Taylor {
5029e39c5baSBill Taylor 	DAT_EVENT	*event;
5039e39c5baSBill Taylor 
5049e39c5baSBill Taylor 	if (evd_ptr->evd_producer_locking_needed) {
5059e39c5baSBill Taylor 		dapl_os_lock(&evd_ptr->header.lock);
5069e39c5baSBill Taylor 	}
5079e39c5baSBill Taylor 
5089e39c5baSBill Taylor 	event = (DAT_EVENT *)dapls_rbuf_remove(&evd_ptr->free_event_queue);
5099e39c5baSBill Taylor 
5109e39c5baSBill Taylor 	/* Release the lock if it was taken and the call failed.  */
5119e39c5baSBill Taylor 	if (!event && evd_ptr->evd_producer_locking_needed) {
5129e39c5baSBill Taylor 		dapl_os_unlock(&evd_ptr->header.lock);
5139e39c5baSBill Taylor 	}
5149e39c5baSBill Taylor 
5159e39c5baSBill Taylor 	return (event);
5169e39c5baSBill Taylor }
5179e39c5baSBill Taylor 
5189e39c5baSBill Taylor /*
5199e39c5baSBill Taylor  * dapli_evd_post_event
5209e39c5baSBill Taylor  *
5219e39c5baSBill Taylor  * Post the <event> to the evd.  If possible, invoke the evd's CNO.
5229e39c5baSBill Taylor  * Otherwise post the event on the pending queue.
5239e39c5baSBill Taylor  *
5249e39c5baSBill Taylor  * If producer side locking is required, the EVD lock must be held upon
5259e39c5baSBill Taylor  * entry to this function.
5269e39c5baSBill Taylor  *
5279e39c5baSBill Taylor  * Input:
528*93fec3daSToomas Soome  *	evd_ptr
529*93fec3daSToomas Soome  *	event
5309e39c5baSBill Taylor  *
5319e39c5baSBill Taylor  * Output:
5329e39c5baSBill Taylor  *	none
5339e39c5baSBill Taylor  *
5349e39c5baSBill Taylor  */
5359e39c5baSBill Taylor 
5369e39c5baSBill Taylor static void
dapli_evd_post_event(IN DAPL_EVD * evd_ptr,IN const DAT_EVENT * event_ptr)5379e39c5baSBill Taylor dapli_evd_post_event(
5389e39c5baSBill Taylor     IN	DAPL_EVD	*evd_ptr,
5399e39c5baSBill Taylor     IN	const DAT_EVENT	*event_ptr)
5409e39c5baSBill Taylor {
5419e39c5baSBill Taylor 	DAT_RETURN	dat_status;
542*93fec3daSToomas Soome 	DAPL_CNO	*cno_to_trigger = NULL;
5439e39c5baSBill Taylor 
5449e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_EVD,
5459e39c5baSBill Taylor 	    "dapli_evd_post_event: Called with event # %x\n",
5469e39c5baSBill Taylor 	    event_ptr->event_number);
5479e39c5baSBill Taylor 
5489e39c5baSBill Taylor 	dat_status = dapls_rbuf_add(&evd_ptr->pending_event_queue,
5499e39c5baSBill Taylor 	    (void *)event_ptr);
5509e39c5baSBill Taylor 	dapl_os_assert(dat_status == DAT_SUCCESS);
5519e39c5baSBill Taylor 
5529e39c5baSBill Taylor 	dapl_os_assert(evd_ptr->evd_state == DAPL_EVD_STATE_WAITED ||
5539e39c5baSBill Taylor 	    evd_ptr->evd_state == DAPL_EVD_STATE_OPEN);
5549e39c5baSBill Taylor 
5559e39c5baSBill Taylor 	if (evd_ptr->evd_state == DAPL_EVD_STATE_OPEN) {
5569e39c5baSBill Taylor 		/* No waiter.  Arrange to trigger a CNO if it exists.  */
5579e39c5baSBill Taylor 
5589e39c5baSBill Taylor 		if (evd_ptr->evd_enabled) {
5599e39c5baSBill Taylor 			cno_to_trigger = evd_ptr->cno_ptr;
5609e39c5baSBill Taylor 		}
5619e39c5baSBill Taylor 		if (evd_ptr->evd_producer_locking_needed) {
5629e39c5baSBill Taylor 			dapl_os_unlock(&evd_ptr->header.lock);
5639e39c5baSBill Taylor 		}
5649e39c5baSBill Taylor 	} else {
5659e39c5baSBill Taylor 		/*
5669e39c5baSBill Taylor 		 * This routine gets called
5679e39c5baSBill Taylor 		 *  - In the context of the waiting thread when CQ, CM or ASYNC
5689e39c5baSBill Taylor 		 *    events need to be put on to the EVD ring buffer.
5699e39c5baSBill Taylor 		 *  - Due to a post of a software event.
5709e39c5baSBill Taylor 		 *
5719e39c5baSBill Taylor 		 * In the first case the waiting thread is pulling the events
5729e39c5baSBill Taylor 		 * from various streams into the evd so there is no need to
5739e39c5baSBill Taylor 		 * wake any thread. In the second case if the evd is in waited
5749e39c5baSBill Taylor 		 * state then we need to wakeup the waiting thread.
5759e39c5baSBill Taylor 		 */
5769e39c5baSBill Taylor 		if (event_ptr->event_number == DAT_SOFTWARE_EVENT) {
5779e39c5baSBill Taylor 			/*
5789e39c5baSBill Taylor 			 * We're in DAPL_EVD_STATE_WAITED.  Take the lock if
5799e39c5baSBill Taylor 			 * we don't have it, recheck, and signal.
5809e39c5baSBill Taylor 			 */
5819e39c5baSBill Taylor 
5829e39c5baSBill Taylor 			if (!evd_ptr->evd_producer_locking_needed) {
5839e39c5baSBill Taylor 				dapl_os_lock(&evd_ptr->header.lock);
5849e39c5baSBill Taylor 			}
5859e39c5baSBill Taylor 
5869e39c5baSBill Taylor 			if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED) {
5879e39c5baSBill Taylor 				dapl_os_unlock(&evd_ptr->header.lock);
5889e39c5baSBill Taylor 				(void) dapls_ib_event_wakeup(evd_ptr);
5899e39c5baSBill Taylor 			} else {
5909e39c5baSBill Taylor 				dapl_os_unlock(&evd_ptr->header.lock);
5919e39c5baSBill Taylor 			}
5929e39c5baSBill Taylor 		} else {
5939e39c5baSBill Taylor 			if (evd_ptr->evd_producer_locking_needed) {
5949e39c5baSBill Taylor 				dapl_os_unlock(&evd_ptr->header.lock);
5959e39c5baSBill Taylor 			}
5969e39c5baSBill Taylor 		}
5979e39c5baSBill Taylor 	}
5989e39c5baSBill Taylor 
5999e39c5baSBill Taylor 	if (cno_to_trigger != NULL) {
6009e39c5baSBill Taylor 		dapl_cno_trigger(cno_to_trigger, evd_ptr);
6019e39c5baSBill Taylor 	}
6029e39c5baSBill Taylor }
6039e39c5baSBill Taylor 
6049e39c5baSBill Taylor /*
6059e39c5baSBill Taylor  * dapli_evd_post_event_nosignal
6069e39c5baSBill Taylor  *
6079e39c5baSBill Taylor  * Post the <event> to the evd.  Do not do any wakeup processing.
6089e39c5baSBill Taylor  * This function should only be called if it is known that there are
6099e39c5baSBill Taylor  * no waiters that it is appropriate to wakeup on this EVD.  An example
6109e39c5baSBill Taylor  * of such a situation is during internal dat_evd_wait() processing.
6119e39c5baSBill Taylor  *
6129e39c5baSBill Taylor  * If producer side locking is required, the EVD lock must be held upon
6139e39c5baSBill Taylor  * entry to this function.
6149e39c5baSBill Taylor  *
6159e39c5baSBill Taylor  * Input:
616*93fec3daSToomas Soome  *	evd_ptr
617*93fec3daSToomas Soome  *	event
6189e39c5baSBill Taylor  *
6199e39c5baSBill Taylor  * Output:
6209e39c5baSBill Taylor  *	none
6219e39c5baSBill Taylor  *
6229e39c5baSBill Taylor  */
6239e39c5baSBill Taylor 
6249e39c5baSBill Taylor static void
dapli_evd_post_event_nosignal(IN DAPL_EVD * evd_ptr,IN const DAT_EVENT * event_ptr)6259e39c5baSBill Taylor dapli_evd_post_event_nosignal(
6269e39c5baSBill Taylor     IN	DAPL_EVD	*evd_ptr,
6279e39c5baSBill Taylor     IN	const DAT_EVENT	*event_ptr)
6289e39c5baSBill Taylor {
6299e39c5baSBill Taylor 	DAT_RETURN	dat_status;
6309e39c5baSBill Taylor 
6319e39c5baSBill Taylor 	dapl_dbg_log(DAPL_DBG_TYPE_EVD,
6329e39c5baSBill Taylor 	    "dapli_evd_post_event: Called with event # %x\n",
6339e39c5baSBill Taylor 	    event_ptr->event_number);
6349e39c5baSBill Taylor 
6359e39c5baSBill Taylor 	dat_status = dapls_rbuf_add(&evd_ptr->pending_event_queue,
6369e39c5baSBill Taylor 	    (void *)event_ptr);
6379e39c5baSBill Taylor 	dapl_os_assert(dat_status == DAT_SUCCESS);
6389e39c5baSBill Taylor 
6399e39c5baSBill Taylor 	dapl_os_assert(evd_ptr->evd_state == DAPL_EVD_STATE_WAITED ||
6409e39c5baSBill Taylor 	    evd_ptr->evd_state == DAPL_EVD_STATE_OPEN);
6419e39c5baSBill Taylor 
6429e39c5baSBill Taylor 	if (evd_ptr->evd_producer_locking_needed) {
6439e39c5baSBill Taylor 		dapl_os_unlock(&evd_ptr->header.lock);
6449e39c5baSBill Taylor 	}
6459e39c5baSBill Taylor }
6469e39c5baSBill Taylor 
6479e39c5baSBill Taylor /*
6489e39c5baSBill Taylor  * dapli_evd_format_overflow_event
6499e39c5baSBill Taylor  *
6509e39c5baSBill Taylor  * format an overflow event for posting
6519e39c5baSBill Taylor  *
6529e39c5baSBill Taylor  * Input:
653*93fec3daSToomas Soome  *	evd_ptr
654*93fec3daSToomas Soome  *	event_ptr
6559e39c5baSBill Taylor  *
6569e39c5baSBill Taylor  * Output:
6579e39c5baSBill Taylor  *	none
6589e39c5baSBill Taylor  *
6599e39c5baSBill Taylor  */
6609e39c5baSBill Taylor static void
dapli_evd_format_overflow_event(IN DAPL_EVD * evd_ptr,OUT DAT_EVENT * event_ptr)6619e39c5baSBill Taylor dapli_evd_format_overflow_event(
6629e39c5baSBill Taylor 	IN  DAPL_EVD  *evd_ptr,
6639e39c5baSBill Taylor 	OUT DAT_EVENT *event_ptr)
6649e39c5baSBill Taylor {
6659e39c5baSBill Taylor 	DAPL_IA *ia_ptr;
6669e39c5baSBill Taylor 
6679e39c5baSBill Taylor 	ia_ptr = evd_ptr->header.owner_ia;
6689e39c5baSBill Taylor 
6699e39c5baSBill Taylor 	event_ptr->evd_handle   = (DAT_EVD_HANDLE)evd_ptr;
6709e39c5baSBill Taylor 	event_ptr->event_number = DAT_ASYNC_ERROR_EVD_OVERFLOW;
6719e39c5baSBill Taylor 	event_ptr->event_data.asynch_error_event_data.dat_handle =
6729e39c5baSBill Taylor 	    (DAT_HANDLE)ia_ptr;
6739e39c5baSBill Taylor }
6749e39c5baSBill Taylor 
6759e39c5baSBill Taylor /*
6769e39c5baSBill Taylor  * dapli_evd_post_overflow_event
6779e39c5baSBill Taylor  *
6789e39c5baSBill Taylor  * post an overflow event
6799e39c5baSBill Taylor  *
6809e39c5baSBill Taylor  * Input:
681*93fec3daSToomas Soome  *	async_evd_ptr
682*93fec3daSToomas Soome  *	evd_ptr
6839e39c5baSBill Taylor  *
6849e39c5baSBill Taylor  * Output:
6859e39c5baSBill Taylor  *	none
6869e39c5baSBill Taylor  *
6879e39c5baSBill Taylor  */
6889e39c5baSBill Taylor static void
dapli_evd_post_overflow_event(IN DAPL_EVD * async_evd_ptr,IN DAPL_EVD * overflow_evd_ptr)6899e39c5baSBill Taylor dapli_evd_post_overflow_event(
6909e39c5baSBill Taylor     IN  DAPL_EVD  *async_evd_ptr,
6919e39c5baSBill Taylor     IN  DAPL_EVD  *overflow_evd_ptr)
6929e39c5baSBill Taylor {
6939e39c5baSBill Taylor 	DAT_EVENT *overflow_event;
6949e39c5baSBill Taylor 
6959e39c5baSBill Taylor 	/*
6969e39c5baSBill Taylor 	 * The overflow_evd_ptr mght be the same as evd.
6979e39c5baSBill Taylor 	 * In that case we've got a catastrophic overflow.
6989e39c5baSBill Taylor 	 */
6999e39c5baSBill Taylor 	if (async_evd_ptr == overflow_evd_ptr) {
7009e39c5baSBill Taylor 		async_evd_ptr->catastrophic_overflow = DAT_TRUE;
7019e39c5baSBill Taylor 		async_evd_ptr->evd_state = DAPL_EVD_STATE_DEAD;
7029e39c5baSBill Taylor 		return;
7039e39c5baSBill Taylor 	}
7049e39c5baSBill Taylor 
7059e39c5baSBill Taylor 	overflow_event = dapli_evd_get_event(overflow_evd_ptr);
7069e39c5baSBill Taylor 	if (!overflow_event) {
7079e39c5baSBill Taylor 		/* this is not good */
7089e39c5baSBill Taylor 		overflow_evd_ptr->catastrophic_overflow = DAT_TRUE;
7099e39c5baSBill Taylor 		overflow_evd_ptr->evd_state = DAPL_EVD_STATE_DEAD;
7109e39c5baSBill Taylor 		return;
7119e39c5baSBill Taylor 	}
7129e39c5baSBill Taylor 	dapli_evd_format_overflow_event(overflow_evd_ptr, overflow_event);
7139e39c5baSBill Taylor 	dapli_evd_post_event(overflow_evd_ptr, overflow_event);
7149e39c5baSBill Taylor }
7159e39c5baSBill Taylor 
7169e39c5baSBill Taylor static DAT_EVENT *
dapli_evd_get_and_init_event(IN DAPL_EVD * evd_ptr,IN DAT_EVENT_NUMBER event_number)7179e39c5baSBill Taylor dapli_evd_get_and_init_event(
7189e39c5baSBill Taylor     IN DAPL_EVD				*evd_ptr,
7199e39c5baSBill Taylor     IN DAT_EVENT_NUMBER			event_number)
7209e39c5baSBill Taylor {
721*93fec3daSToomas Soome 	DAT_EVENT		*event_ptr;
7229e39c5baSBill Taylor 
7239e39c5baSBill Taylor 	event_ptr = dapli_evd_get_event(evd_ptr);
7249e39c5baSBill Taylor 	if (NULL == event_ptr) {
7259e39c5baSBill Taylor 		dapli_evd_post_overflow_event(
7269e39c5baSBill Taylor 		    evd_ptr->header.owner_ia->async_error_evd, evd_ptr);
7279e39c5baSBill Taylor 	} else {
7289e39c5baSBill Taylor 		event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;
7299e39c5baSBill Taylor 		event_ptr->event_number = event_number;
7309e39c5baSBill Taylor 	}
7319e39c5baSBill Taylor 
7329e39c5baSBill Taylor 	return (event_ptr);
7339e39c5baSBill Taylor }
7349e39c5baSBill Taylor 
7359e39c5baSBill Taylor 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)7369e39c5baSBill Taylor dapls_evd_post_cr_arrival_event(
7379e39c5baSBill Taylor     IN DAPL_EVD				*evd_ptr,
7389e39c5baSBill Taylor     IN DAT_EVENT_NUMBER			event_number,
7399e39c5baSBill Taylor     IN DAT_SP_HANDLE			sp_handle,
7409e39c5baSBill Taylor     DAT_IA_ADDRESS_PTR			ia_address_ptr,
7419e39c5baSBill Taylor     DAT_CONN_QUAL			conn_qual,
7429e39c5baSBill Taylor     DAT_CR_HANDLE			cr_handle)
7439e39c5baSBill Taylor {
744*93fec3daSToomas Soome 	DAT_EVENT		*event_ptr;
7459e39c5baSBill Taylor 	event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
7469e39c5baSBill Taylor 	/*
7479e39c5baSBill Taylor 	 * Note event lock may be held on successful return
7489e39c5baSBill Taylor 	 * to be released by dapli_evd_post_event(), if provider side locking
7499e39c5baSBill Taylor 	 * is needed.
7509e39c5baSBill Taylor 	 */
7519e39c5baSBill Taylor 
7529e39c5baSBill Taylor 	if (!event_ptr) {
7539e39c5baSBill Taylor 		return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
7549e39c5baSBill Taylor 	}
7559e39c5baSBill Taylor 
7569e39c5baSBill Taylor 	event_ptr->event_data.cr_arrival_event_data.sp_handle = sp_handle;
7579e39c5baSBill Taylor 	event_ptr->event_data.cr_arrival_event_data.local_ia_address_ptr
7589e39c5baSBill Taylor 	    = ia_address_ptr;
7599e39c5baSBill Taylor 	event_ptr->event_data.cr_arrival_event_data.conn_qual = conn_qual;
7609e39c5baSBill Taylor 	event_ptr->event_data.cr_arrival_event_data.cr_handle = cr_handle;
7619e39c5baSBill Taylor 
7629e39c5baSBill Taylor 	dapli_evd_post_event(evd_ptr, event_ptr);
7639e39c5baSBill Taylor 	return (DAT_SUCCESS);
7649e39c5baSBill Taylor }
7659e39c5baSBill Taylor 
7669e39c5baSBill Taylor 
7679e39c5baSBill Taylor 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)7689e39c5baSBill Taylor dapls_evd_post_connection_event(
7699e39c5baSBill Taylor     IN DAPL_EVD				*evd_ptr,
7709e39c5baSBill Taylor     IN DAT_EVENT_NUMBER			event_number,
7719e39c5baSBill Taylor     IN DAT_EP_HANDLE			ep_handle,
7729e39c5baSBill Taylor     IN DAT_COUNT			private_data_size,
7739e39c5baSBill Taylor     IN DAT_PVOID			private_data)
7749e39c5baSBill Taylor {
775*93fec3daSToomas Soome 	DAT_EVENT		*event_ptr;
7769e39c5baSBill Taylor 	event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
7779e39c5baSBill Taylor 	/*
7789e39c5baSBill Taylor 	 * Note event lock may be held on successful return
7799e39c5baSBill Taylor 	 * to be released by dapli_evd_post_event(), if provider side locking
7809e39c5baSBill Taylor 	 * is needed.
7819e39c5baSBill Taylor 	 */
7829e39c5baSBill Taylor 
7839e39c5baSBill Taylor 	if (!event_ptr) {
7849e39c5baSBill Taylor 		return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
7859e39c5baSBill Taylor 	}
7869e39c5baSBill Taylor 
7879e39c5baSBill Taylor 	event_ptr->event_data.connect_event_data.ep_handle = ep_handle;
7889e39c5baSBill Taylor 	event_ptr->event_data.connect_event_data.private_data_size
7899e39c5baSBill Taylor 	    = private_data_size;
7909e39c5baSBill Taylor 	event_ptr->event_data.connect_event_data.private_data = private_data;
7919e39c5baSBill Taylor 
7929e39c5baSBill Taylor 	dapli_evd_post_event(evd_ptr, event_ptr);
7939e39c5baSBill Taylor 	return (DAT_SUCCESS);
7949e39c5baSBill Taylor }
7959e39c5baSBill Taylor 
7969e39c5baSBill Taylor 
7979e39c5baSBill Taylor 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)7989e39c5baSBill Taylor dapls_evd_post_async_error_event(
7999e39c5baSBill Taylor     IN DAPL_EVD				*evd_ptr,
8009e39c5baSBill Taylor     IN DAT_EVENT_NUMBER			event_number,
8019e39c5baSBill Taylor     IN DAT_IA_HANDLE			ia_handle)
8029e39c5baSBill Taylor {
803*93fec3daSToomas Soome 	DAT_EVENT		*event_ptr;
8049e39c5baSBill Taylor 	event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
8059e39c5baSBill Taylor 	/*
8069e39c5baSBill Taylor 	 * Note event lock may be held on successful return
8079e39c5baSBill Taylor 	 * to be released by dapli_evd_post_event(), if provider side locking
8089e39c5baSBill Taylor 	 * is needed.
8099e39c5baSBill Taylor 	 */
8109e39c5baSBill Taylor 
8119e39c5baSBill Taylor 	if (!event_ptr) {
8129e39c5baSBill Taylor 		return (DAT_INSUFFICIENT_RESOURCES | DAT_RESOURCE_MEMORY);
8139e39c5baSBill Taylor 	}
8149e39c5baSBill Taylor 
8159e39c5baSBill Taylor 	event_ptr->event_data.asynch_error_event_data.dat_handle = ia_handle;
8169e39c5baSBill Taylor 
8179e39c5baSBill Taylor 	dapli_evd_post_event(evd_ptr, event_ptr);
8189e39c5baSBill Taylor 	return (DAT_SUCCESS);
8199e39c5baSBill Taylor }
8209e39c5baSBill Taylor 
8219e39c5baSBill Taylor 
8229e39c5baSBill Taylor DAT_RETURN
dapls_evd_post_software_event(IN DAPL_EVD * evd_ptr,IN DAT_EVENT_NUMBER event_number,IN DAT_PVOID pointer)8239e39c5baSBill Taylor dapls_evd_post_software_event(
8249e39c5baSBill Taylor     IN DAPL_EVD				*evd_ptr,
8259e39c5baSBill Taylor     IN DAT_EVENT_NUMBER			event_number,
8269e39c5baSBill Taylor     IN DAT_PVOID			pointer)
8279e39c5baSBill Taylor {
828*93fec3daSToomas Soome 	DAT_EVENT		*event_ptr;
8299e39c5baSBill Taylor 	event_ptr = dapli_evd_get_and_init_event(evd_ptr, event_number);
8309e39c5baSBill Taylor 	/*
8319e39c5baSBill Taylor 	 * Note event lock may be held on successful return
8329e39c5baSBill Taylor 	 * to be released by dapli_evd_post_event(), if provider side locking
8339e39c5baSBill Taylor 	 * is needed.
8349e39c5baSBill Taylor 	 */
8359e39c5baSBill Taylor 
8369e39c5baSBill Taylor 	if (!event_ptr) {
8379e39c5baSBill Taylor 		return (DAT_QUEUE_FULL);
8389e39c5baSBill Taylor 	}
8399e39c5baSBill Taylor 
8409e39c5baSBill Taylor 	event_ptr->event_data.software_event_data.pointer = pointer;
8419e39c5baSBill Taylor 
8429e39c5baSBill Taylor 	dapli_evd_post_event(evd_ptr, event_ptr);
8439e39c5baSBill Taylor 	return (DAT_SUCCESS);
8449e39c5baSBill Taylor }
8459e39c5baSBill Taylor 
8469e39c5baSBill Taylor void
dapls_evd_post_premature_events(IN DAPL_EP * ep_ptr)8479e39c5baSBill Taylor dapls_evd_post_premature_events(IN DAPL_EP *ep_ptr)
8489e39c5baSBill Taylor {
8499e39c5baSBill Taylor 	DAPL_EVD		*evd_ptr;
8509e39c5baSBill Taylor 	DAT_EVENT		*event;
8519e39c5baSBill Taylor 	ib_work_completion_t	*cqe;
8529e39c5baSBill Taylor 	uint32_t		qpn;
8539e39c5baSBill Taylor 	int			prm_idx;
8549e39c5baSBill Taylor 	int			nevents;
8559e39c5baSBill Taylor 	int			i;
8569e39c5baSBill Taylor 
8579e39c5baSBill Taylor 	dapls_ib_poll_premature_events(ep_ptr, &cqe, &nevents);
8589e39c5baSBill Taylor 	/* premature events are always recv events */
8599e39c5baSBill Taylor 	evd_ptr = ep_ptr->param.recv_evd_handle;
8609e39c5baSBill Taylor 	qpn = ep_ptr->qpn;
8619e39c5baSBill Taylor 
8629e39c5baSBill Taylor 	i = 0;
8639e39c5baSBill Taylor 	prm_idx = 0;
8649e39c5baSBill Taylor 	while (i < nevents) {
8659e39c5baSBill Taylor 		/*
8669e39c5baSBill Taylor 		 * If srq_attached, premature events cannot exceed max_recv_dtos
8679e39c5baSBill Taylor 		 */
8689e39c5baSBill Taylor 		dapl_os_assert(!ep_ptr->srq_attached ||
8699e39c5baSBill Taylor 		    (prm_idx <= ((DAPL_SRQ *)ep_ptr->param.srq_handle)->
8709e39c5baSBill Taylor 		    param.max_recv_dtos));
8719e39c5baSBill Taylor 
8729e39c5baSBill Taylor 		/*
8739e39c5baSBill Taylor 		 * The SRQ premature event list could potentially have
8749e39c5baSBill Taylor 		 * holes (ie. free entries in the middle) or premature
8759e39c5baSBill Taylor 		 * events for other QPs. These need to be skipped.
8769e39c5baSBill Taylor 		 */
8779e39c5baSBill Taylor 		if (ep_ptr->srq_attached &&
8789e39c5baSBill Taylor 		    (!DAPL_CQE_IS_VALID(&cqe[prm_idx]) ||
8799e39c5baSBill Taylor 		    (DAPL_GET_CQE_QPN(&cqe[prm_idx]) != qpn))) {
8809e39c5baSBill Taylor 			prm_idx++;
8819e39c5baSBill Taylor 			continue;
8829e39c5baSBill Taylor 		}
8839e39c5baSBill Taylor 
8849e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_DTO_COMP_ERR,
8859e39c5baSBill Taylor 		    " Premature DTO processing\n");
8869e39c5baSBill Taylor 
8879e39c5baSBill Taylor #ifdef	DAPL_DBG	/* For debugging.  */
8889e39c5baSBill Taylor 		dapli_evd_eh_print_cqe(cqe[i]);
8899e39c5baSBill Taylor #endif
8909e39c5baSBill Taylor 		/*
8919e39c5baSBill Taylor 		 * Can use DAT_DTO_COMPLETION_EVENT because
8929e39c5baSBill Taylor 		 * dapli_evd_cqe_to_event will overwrite.
8939e39c5baSBill Taylor 		 */
8949e39c5baSBill Taylor 		event = dapli_evd_get_and_init_event(evd_ptr,
8959e39c5baSBill Taylor 		    DAT_DTO_COMPLETION_EVENT);
8969e39c5baSBill Taylor 		if (event == NULL) {
8979e39c5baSBill Taylor 			/* We've already attempted the overflow post, return */
8989e39c5baSBill Taylor 			return;
8999e39c5baSBill Taylor 		}
9009e39c5baSBill Taylor 		(void) dapli_evd_cqe_to_event(evd_ptr, &cqe[i], DAT_TRUE,
9019e39c5baSBill Taylor 		    event);
9029e39c5baSBill Taylor 		dapli_evd_post_event_nosignal(evd_ptr, event);
9039e39c5baSBill Taylor 		/*
9049e39c5baSBill Taylor 		 * For SRQ attached QPs recycle the premature event
9059e39c5baSBill Taylor 		 */
9069e39c5baSBill Taylor 		if (ep_ptr->srq_attached) {
9079e39c5baSBill Taylor 			dapls_ib_free_premature_events(ep_ptr, prm_idx);
9089e39c5baSBill Taylor 			prm_idx++;
9099e39c5baSBill Taylor 		}
9109e39c5baSBill Taylor 		i++;
9119e39c5baSBill Taylor 	}
9129e39c5baSBill Taylor }
9139e39c5baSBill Taylor 
9149e39c5baSBill Taylor /*
9159e39c5baSBill Taylor  * dapli_evd_cqe_to_event
9169e39c5baSBill Taylor  *
9179e39c5baSBill Taylor  * Convert a CQE into an event structure.
9189e39c5baSBill Taylor  *
9199e39c5baSBill Taylor  * Input:
9209e39c5baSBill Taylor  *	evd_ptr
921*93fec3daSToomas Soome  *	cqe_ptr
9229e39c5baSBill Taylor  *
9239e39c5baSBill Taylor  * Output:
924*93fec3daSToomas Soome  *	event_ptr
9259e39c5baSBill Taylor  *
9269e39c5baSBill Taylor  * Returns:
927*93fec3daSToomas Soome  *	none
9289e39c5baSBill Taylor  *
9299e39c5baSBill Taylor  */
9309e39c5baSBill Taylor static DAT_BOOLEAN
dapli_evd_cqe_to_event(IN DAPL_EVD * evd_ptr,IN ib_work_completion_t * cqe_ptr,IN DAT_BOOLEAN process_premature_events,OUT DAT_EVENT * event_ptr)9319e39c5baSBill Taylor dapli_evd_cqe_to_event(
9329e39c5baSBill Taylor     IN DAPL_EVD			*evd_ptr,
9339e39c5baSBill Taylor     IN ib_work_completion_t	*cqe_ptr,
9349e39c5baSBill Taylor     IN DAT_BOOLEAN		process_premature_events,
9359e39c5baSBill Taylor     OUT DAT_EVENT		*event_ptr)
9369e39c5baSBill Taylor {
9379e39c5baSBill Taylor 	DAPL_EP			*ep_ptr;
9389e39c5baSBill Taylor 	DAPL_SRQ		*srq_ptr;
9399e39c5baSBill Taylor 	DAPL_COOKIE		*cookie;
9409e39c5baSBill Taylor 	DAT_EP_STATE		ep_state;
9419e39c5baSBill Taylor 	ib_qp_handle_t		qp;
9429e39c5baSBill Taylor 	ib_uint32_t		ib_status;
9439e39c5baSBill Taylor 	ib_uint32_t		ibtype;
9449e39c5baSBill Taylor 	int			srq_enabled;
9459e39c5baSBill Taylor 	int			dto_error = 0;
9469e39c5baSBill Taylor 
9479e39c5baSBill Taylor 
9489e39c5baSBill Taylor 	/*
9499e39c5baSBill Taylor 	 * All that can be relied on if the status is bad is the status
9509e39c5baSBill Taylor 	 * and WRID.
9519e39c5baSBill Taylor 	 */
9529e39c5baSBill Taylor 	ib_status = DAPL_GET_CQE_STATUS(cqe_ptr);
9539e39c5baSBill Taylor 
9549e39c5baSBill Taylor 	cookie = (DAPL_COOKIE *)((uintptr_t)DAPL_GET_CQE_WRID(cqe_ptr));
9559e39c5baSBill Taylor 	dapl_os_assert((NULL != cookie));
9569e39c5baSBill Taylor 
9579e39c5baSBill Taylor 	if (cookie->queue_type == DAPL_COOKIE_QUEUE_EP) {
9589e39c5baSBill Taylor 		srq_enabled = 0;
9599e39c5baSBill Taylor 		ep_ptr = cookie->queue.ep;
9609e39c5baSBill Taylor 	} else {
9619e39c5baSBill Taylor 		srq_enabled = 1;
9629e39c5baSBill Taylor 		srq_ptr = cookie->queue.srq;
9639e39c5baSBill Taylor 		dapl_os_assert(NULL != srq_ptr);
9649e39c5baSBill Taylor 		dapl_os_assert(srq_ptr->header.magic == DAPL_MAGIC_SRQ);
9659e39c5baSBill Taylor 		ib_status = DAPL_GET_CQE_STATUS(cqe_ptr);
9669e39c5baSBill Taylor 		ep_ptr = dapls_ib_srq_lookup_ep(srq_ptr, cqe_ptr);
9679e39c5baSBill Taylor 	}
9689e39c5baSBill Taylor 
9699e39c5baSBill Taylor 	dapl_os_assert((NULL != ep_ptr));
9709e39c5baSBill Taylor 	dapl_os_assert((ep_ptr->header.magic == DAPL_MAGIC_EP) ||
9719e39c5baSBill Taylor 	    (ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT));
9729e39c5baSBill Taylor 
9739e39c5baSBill Taylor 	event_ptr->evd_handle = (DAT_EVD_HANDLE) evd_ptr;
9749e39c5baSBill Taylor 
9759e39c5baSBill Taylor 	/*
9769e39c5baSBill Taylor 	 * Check if the DTO completion arrived before CONNECTION_ESTABLISHED
9779e39c5baSBill Taylor 	 * event -
9789e39c5baSBill Taylor 	 *
9799e39c5baSBill Taylor 	 * Send DTOs can occur only if ep state is CONNECTED/DISCONNECTED
9809e39c5baSBill Taylor 	 * therefore it cannot occur before connection established event.
9819e39c5baSBill Taylor 	 * Receive DTO can potentially complete before connection established
9829e39c5baSBill Taylor 	 * event has been delivered to the client. In this case if the
9839e39c5baSBill Taylor 	 * ep state is ACTIVE_CONNECTION_PENDING (active side) or
9849e39c5baSBill Taylor 	 * COMPLETION_PENDING (passive side) the event is put in a special
9859e39c5baSBill Taylor 	 * event queue in the qp_handle.
9869e39c5baSBill Taylor 	 *
9879e39c5baSBill Taylor 	 */
9889e39c5baSBill Taylor 	if (!process_premature_events &&
9899e39c5baSBill Taylor 	    (cookie->type == DAPL_COOKIE_TYPE_DTO) &&
9909e39c5baSBill Taylor 	    (ib_status == IB_COMP_ST_SUCCESS)) {
9919e39c5baSBill Taylor 		ep_state = ep_ptr->param.ep_state;
9929e39c5baSBill Taylor 		qp = ep_ptr->qp_handle;
9939e39c5baSBill Taylor 		if ((ep_state == DAT_EP_STATE_ACTIVE_CONNECTION_PENDING) ||
9949e39c5baSBill Taylor 		    (ep_state == DAT_EP_STATE_COMPLETION_PENDING) ||
9959e39c5baSBill Taylor 		    (qp->qp_num_premature_events > 0)) {
9969e39c5baSBill Taylor 			/*
9979e39c5baSBill Taylor 			 * not yet ready to put the event in the evd ring
9989e39c5baSBill Taylor 			 * buffer
9999e39c5baSBill Taylor 			 */
10009e39c5baSBill Taylor 			dapls_ib_store_premature_events(qp, cqe_ptr);
10019e39c5baSBill Taylor 			return (DAT_FALSE);
10029e39c5baSBill Taylor 		}
10039e39c5baSBill Taylor 	}
10049e39c5baSBill Taylor 
10059e39c5baSBill Taylor 	switch (cookie->type) {
10069e39c5baSBill Taylor 	case DAPL_COOKIE_TYPE_DTO:
10079e39c5baSBill Taylor 	{
10089e39c5baSBill Taylor 		DAPL_COOKIE_BUFFER	*buffer;
10099e39c5baSBill Taylor 
10109e39c5baSBill Taylor 		if (DAPL_DTO_TYPE_RECV == cookie->val.dto.type) {
10119e39c5baSBill Taylor 			if (srq_enabled) {
10129e39c5baSBill Taylor 				dapl_os_atomic_dec(&srq_ptr->recv_count);
10139e39c5baSBill Taylor 				buffer = &srq_ptr->recv_buffer;
10149e39c5baSBill Taylor 			} else {
10159e39c5baSBill Taylor 				dapl_os_atomic_dec(&ep_ptr->recv_count);
10169e39c5baSBill Taylor 				buffer = &ep_ptr->recv_buffer;
10179e39c5baSBill Taylor 			}
10189e39c5baSBill Taylor 		} else {
10199e39c5baSBill Taylor 			dapl_os_atomic_dec(&ep_ptr->req_count);
10209e39c5baSBill Taylor 			buffer = &ep_ptr->req_buffer;
10219e39c5baSBill Taylor 		}
10229e39c5baSBill Taylor 
10239e39c5baSBill Taylor 		event_ptr->event_number = DAT_DTO_COMPLETION_EVENT;
10249e39c5baSBill Taylor 		event_ptr->event_data.dto_completion_event_data.ep_handle =
10259e39c5baSBill Taylor 		    ep_ptr;
10269e39c5baSBill Taylor 		event_ptr->event_data.dto_completion_event_data.user_cookie =
10279e39c5baSBill Taylor 		    cookie->val.dto.cookie;
10289e39c5baSBill Taylor 
10299e39c5baSBill Taylor 		switch (ib_status) {
10309e39c5baSBill Taylor 		case IB_COMP_ST_SUCCESS:
10319e39c5baSBill Taylor 		{
10329e39c5baSBill Taylor 			ibtype = DAPL_GET_CQE_OPTYPE(cqe_ptr);
10339e39c5baSBill Taylor 
10349e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10359e39c5baSBill Taylor 			    DAT_DTO_SUCCESS;
10369e39c5baSBill Taylor 			dapl_os_assert((ibtype == OP_SEND &&
10379e39c5baSBill Taylor 			    cookie->val.dto.type == DAPL_DTO_TYPE_SEND) ||
10389e39c5baSBill Taylor 			    (ibtype == OP_RECEIVE &&
10399e39c5baSBill Taylor 			    cookie->val.dto.type == DAPL_DTO_TYPE_RECV) ||
10409e39c5baSBill Taylor 			    (ibtype == OP_RDMA_WRITE &&
10419e39c5baSBill Taylor 			    cookie->val.dto.type ==
10429e39c5baSBill Taylor 			    DAPL_DTO_TYPE_RDMA_WRITE) ||
10439e39c5baSBill Taylor 			    (ibtype == OP_RDMA_READ &&
10449e39c5baSBill Taylor 			    cookie->val.dto.type ==
10459e39c5baSBill Taylor 			    DAPL_DTO_TYPE_RDMA_READ));
10469e39c5baSBill Taylor 			break;
10479e39c5baSBill Taylor 		}
10489e39c5baSBill Taylor 		case IB_COMP_ST_LOCAL_LEN_ERR:
10499e39c5baSBill Taylor 		{
10509e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10519e39c5baSBill Taylor 			    DAT_DTO_ERR_LOCAL_LENGTH;
10529e39c5baSBill Taylor 			break;
10539e39c5baSBill Taylor 		}
10549e39c5baSBill Taylor 		case IB_COMP_ST_LOCAL_PROTECT_ERR:
10559e39c5baSBill Taylor 		{
10569e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10579e39c5baSBill Taylor 			    DAT_DTO_ERR_LOCAL_PROTECTION;
10589e39c5baSBill Taylor 			break;
10599e39c5baSBill Taylor 		}
10609e39c5baSBill Taylor 		case IB_COMP_ST_WR_FLUSHED_ERR:
10619e39c5baSBill Taylor 		{
10629e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10639e39c5baSBill Taylor 			    DAT_DTO_ERR_FLUSHED;
10649e39c5baSBill Taylor 			break;
10659e39c5baSBill Taylor 		}
10669e39c5baSBill Taylor 		case IB_COMP_ST_BAD_RESPONSE_ERR:
10679e39c5baSBill Taylor 		{
10689e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10699e39c5baSBill Taylor 			    DAT_DTO_ERR_BAD_RESPONSE;
10709e39c5baSBill Taylor 			break;
10719e39c5baSBill Taylor 		}
10729e39c5baSBill Taylor 		case IB_COMP_ST_REM_REQ_ERR:
10739e39c5baSBill Taylor 		case IB_COMP_ST_REM_OP_ERR:
10749e39c5baSBill Taylor 		{
10759e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10769e39c5baSBill Taylor 			    DAT_DTO_ERR_REMOTE_RESPONDER;
10779e39c5baSBill Taylor 			break;
10789e39c5baSBill Taylor 		}
10799e39c5baSBill Taylor 		case IB_COMP_ST_REM_ACC_ERR:
10809e39c5baSBill Taylor 		{
10819e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10829e39c5baSBill Taylor 			    DAT_DTO_ERR_REMOTE_ACCESS;
10839e39c5baSBill Taylor 			break;
10849e39c5baSBill Taylor 		}
10859e39c5baSBill Taylor 		/*
10869e39c5baSBill Taylor 		 * Unsupported RD errors
10879e39c5baSBill Taylor 		 * case IB_COMP_ST_EE_STATE_ERR:
10889e39c5baSBill Taylor 		 * case IB_COMP_ST_EE_CTX_NO_ERR:
10899e39c5baSBill Taylor 		 */
10909e39c5baSBill Taylor 		case IB_COMP_ST_TRANSP_COUNTER:
10919e39c5baSBill Taylor 		{
10929e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10939e39c5baSBill Taylor 			    DAT_DTO_ERR_TRANSPORT;
10949e39c5baSBill Taylor 			break;
10959e39c5baSBill Taylor 		}
10969e39c5baSBill Taylor 		case IB_COMP_ST_RNR_COUNTER:
10979e39c5baSBill Taylor 		{
10989e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
10999e39c5baSBill Taylor 			    DAT_DTO_ERR_RECEIVER_NOT_READY;
11009e39c5baSBill Taylor 			break;
11019e39c5baSBill Taylor 		}
11029e39c5baSBill Taylor 		case IB_COMP_ST_MW_BIND_ERR:
11039e39c5baSBill Taylor 		{
11049e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
11059e39c5baSBill Taylor 			    DAT_RMR_OPERATION_FAILED;
11069e39c5baSBill Taylor 			break;
11079e39c5baSBill Taylor 		}
11089e39c5baSBill Taylor 		case IB_COMP_ST_LOCAL_OP_ERR:
11099e39c5baSBill Taylor 		{
11109e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
11119e39c5baSBill Taylor 			    DAT_DTO_ERR_LOCAL_EP;
11129e39c5baSBill Taylor 			break;
11139e39c5baSBill Taylor 		}
11149e39c5baSBill Taylor 		default:
11159e39c5baSBill Taylor 		{
11169e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_DTO_COMP_ERR,
11179e39c5baSBill Taylor 			    " DTO completion ERROR: %d: op %#x\n",
11189e39c5baSBill Taylor 			    DAPL_GET_CQE_STATUS(cqe_ptr),
11199e39c5baSBill Taylor 			    DAPL_GET_CQE_OPTYPE(cqe_ptr));
11209e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.status =
11219e39c5baSBill Taylor 			    DAT_DTO_FAILURE;
11229e39c5baSBill Taylor 			break;
11239e39c5baSBill Taylor 		}
11249e39c5baSBill Taylor 		}
11259e39c5baSBill Taylor 
11269e39c5baSBill Taylor 		/* Most error DTO ops result in disconnecting the EP */
11279e39c5baSBill Taylor 		if ((event_ptr->event_data.dto_completion_event_data.status !=
11289e39c5baSBill Taylor 		    DAT_DTO_SUCCESS) &&
11299e39c5baSBill Taylor 		    (event_ptr->event_data.dto_completion_event_data.status !=
11309e39c5baSBill Taylor 		    DAT_RMR_OPERATION_FAILED)) {
11319e39c5baSBill Taylor 			dto_error = 1;
11329e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_DTO_COMP_ERR,
11339e39c5baSBill Taylor 			    " DTO completion ERROR: %d: op %#x\n",
11349e39c5baSBill Taylor 			    DAPL_GET_CQE_STATUS(cqe_ptr),
11359e39c5baSBill Taylor 			    DAPL_GET_CQE_OPTYPE(cqe_ptr));
11369e39c5baSBill Taylor 		}
11379e39c5baSBill Taylor 
11389e39c5baSBill Taylor 		if (cookie->val.dto.type == DAPL_DTO_TYPE_SEND ||
11399e39c5baSBill Taylor 		    cookie->val.dto.type == DAPL_DTO_TYPE_RDMA_WRITE) {
11409e39c5baSBill Taylor 			/* Get size from DTO; CQE value may be off.  */
11419e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.
11429e39c5baSBill Taylor 			    transfered_length = cookie->val.dto.size;
11439e39c5baSBill Taylor 		} else {
11449e39c5baSBill Taylor 			event_ptr->event_data.dto_completion_event_data.
11459e39c5baSBill Taylor 			    transfered_length = DAPL_GET_CQE_BYTESNUM(cqe_ptr);
11469e39c5baSBill Taylor 		}
11479e39c5baSBill Taylor 
11489e39c5baSBill Taylor 		dapls_cookie_dealloc(buffer, cookie);
11499e39c5baSBill Taylor 		break;
11509e39c5baSBill Taylor 	}
11519e39c5baSBill Taylor 
11529e39c5baSBill Taylor 	case DAPL_COOKIE_TYPE_RMR:
11539e39c5baSBill Taylor 	{
11549e39c5baSBill Taylor 		dapl_os_atomic_dec(&ep_ptr->req_count);
11559e39c5baSBill Taylor 
11569e39c5baSBill Taylor 		event_ptr->event_number = DAT_RMR_BIND_COMPLETION_EVENT;
11579e39c5baSBill Taylor 
11589e39c5baSBill Taylor 		event_ptr->event_data.rmr_completion_event_data.rmr_handle =
11599e39c5baSBill Taylor 		    cookie->val.rmr.rmr;
11609e39c5baSBill Taylor 		event_ptr->event_data.rmr_completion_event_data.user_cookie =
11619e39c5baSBill Taylor 		    cookie->val.rmr.cookie;
11629e39c5baSBill Taylor 		if (ib_status == IB_COMP_ST_SUCCESS) {
11639e39c5baSBill Taylor 			ibtype = DAPL_GET_CQE_OPTYPE(cqe_ptr);
11649e39c5baSBill Taylor 
11659e39c5baSBill Taylor 			event_ptr->event_data.rmr_completion_event_data.status =
11669e39c5baSBill Taylor 			    DAT_RMR_BIND_SUCCESS;
11679e39c5baSBill Taylor 			dapl_os_assert(ibtype == OP_BIND_MW);
11689e39c5baSBill Taylor 		} else {
11699e39c5baSBill Taylor 			event_ptr->event_data.rmr_completion_event_data.status =
11709e39c5baSBill Taylor 			    DAT_RMR_BIND_FAILURE;
11719e39c5baSBill Taylor 			dto_error = 1;
11729e39c5baSBill Taylor 		}
11739e39c5baSBill Taylor 
11749e39c5baSBill Taylor 		dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie);
11759e39c5baSBill Taylor 		break;
11769e39c5baSBill Taylor 	}
11779e39c5baSBill Taylor 	default:
11789e39c5baSBill Taylor 	{
11799e39c5baSBill Taylor 		dapl_os_assert(!"Invalid Operation type");
11809e39c5baSBill Taylor 		break;
11819e39c5baSBill Taylor 	}
11829e39c5baSBill Taylor 	}
11839e39c5baSBill Taylor 
11849e39c5baSBill Taylor 	/*
11859e39c5baSBill Taylor 	 * A DTO failed this will cause the connection to be broken
11869e39c5baSBill Taylor 	 */
11879e39c5baSBill Taylor 	if ((dto_error) && (ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED)) {
11889e39c5baSBill Taylor 		ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
11899e39c5baSBill Taylor 		/*
11909e39c5baSBill Taylor 		 * Disconnect at the IB level.
11919e39c5baSBill Taylor 		 */
11929e39c5baSBill Taylor 		dapls_ib_disconnect_clean(ep_ptr, DAT_TRUE, IB_CME_CONNECTED);
11939e39c5baSBill Taylor 	}
11949e39c5baSBill Taylor 	/* convert premature rec to error flush on disconnect */
11959e39c5baSBill Taylor 	if (process_premature_events && (ep_ptr->param.ep_state ==
11969e39c5baSBill Taylor 	    DAT_EP_STATE_DISCONNECTED) && (ib_status == IB_COMP_ST_SUCCESS)) {
11979e39c5baSBill Taylor 		dapl_os_assert(ibtype == OP_RECEIVE &&
11989e39c5baSBill Taylor 		    cookie->val.dto.type == DAPL_DTO_TYPE_RECV);
11999e39c5baSBill Taylor 		event_ptr->event_data.dto_completion_event_data.status =
12009e39c5baSBill Taylor 		    DAT_DTO_ERR_FLUSHED;
12019e39c5baSBill Taylor 	}
12029e39c5baSBill Taylor 	return (DAT_TRUE);
12039e39c5baSBill Taylor }
12049e39c5baSBill Taylor 
12059e39c5baSBill Taylor /*
12069e39c5baSBill Taylor  * dapls_evd_copy_cq
12079e39c5baSBill Taylor  *
12089e39c5baSBill Taylor  * Copy all entries on a CQ associated with the EVD onto that EVD
12099e39c5baSBill Taylor  * Up to caller to handle races, if any.  Note that no EVD waiters will
12109e39c5baSBill Taylor  * be awoken by this copy.
12119e39c5baSBill Taylor  *
12129e39c5baSBill Taylor  * Input:
12139e39c5baSBill Taylor  *	evd_ptr
12149e39c5baSBill Taylor  *
12159e39c5baSBill Taylor  * Output:
1216*93fec3daSToomas Soome  *	nevents
12179e39c5baSBill Taylor  *
12189e39c5baSBill Taylor  * Returns:
1219*93fec3daSToomas Soome  *	none
12209e39c5baSBill Taylor  *
12219e39c5baSBill Taylor  */
12229e39c5baSBill Taylor void
dapls_evd_copy_cq(DAPL_EVD * evd_ptr,int * nevents)12239e39c5baSBill Taylor dapls_evd_copy_cq(
12249e39c5baSBill Taylor 	DAPL_EVD	*evd_ptr,
12259e39c5baSBill Taylor 	int		*nevents)
12269e39c5baSBill Taylor {
12279e39c5baSBill Taylor 	ib_work_completion_t	cqe[MAX_CQES_PER_POLL];
12289e39c5baSBill Taylor 	DAT_RETURN		dat_status;
12299e39c5baSBill Taylor 	ib_cq_handle_t		cq_handle;
12309e39c5baSBill Taylor 	DAT_EVENT		*event;
12319e39c5baSBill Taylor 	uint_t			num_cqes_polled = 0;
12329e39c5baSBill Taylor 	int			cqe_events;
12339e39c5baSBill Taylor 	int			i;
12349e39c5baSBill Taylor 
12359e39c5baSBill Taylor 	cq_handle = evd_ptr->ib_cq_handle;
12369e39c5baSBill Taylor 
12379e39c5baSBill Taylor 	*nevents = 0;
12389e39c5baSBill Taylor 
12399e39c5baSBill Taylor 	if (cq_handle == IB_INVALID_HANDLE) {
12409e39c5baSBill Taylor 		/* Nothing to do if no CQ.  */
12419e39c5baSBill Taylor 		return;
12429e39c5baSBill Taylor 	}
12439e39c5baSBill Taylor 	dat_status = DAPL_POLL(evd_ptr)(cq_handle,
12449e39c5baSBill Taylor 	    cqe, MAX_CQES_PER_POLL, &num_cqes_polled);
12459e39c5baSBill Taylor 
12469e39c5baSBill Taylor 	if (dat_status == DAT_SUCCESS) {
12479e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_EVD, "dapls_evd_copy_cq: %u\n",
12489e39c5baSBill Taylor 		    num_cqes_polled);
12499e39c5baSBill Taylor 		cqe_events = 0;
12509e39c5baSBill Taylor 		for (i = 0; i < num_cqes_polled; i++) {
12519e39c5baSBill Taylor #ifdef	DAPL_DBG	/* For debugging.  */
12529e39c5baSBill Taylor 			dapli_evd_eh_print_cqe(cqe[i]);
12539e39c5baSBill Taylor #endif
12549e39c5baSBill Taylor 
12559e39c5baSBill Taylor 			/*
12569e39c5baSBill Taylor 			 * Can use DAT_DTO_COMPLETION_EVENT because
12579e39c5baSBill Taylor 			 * dapli_evd_cqe_to_event will overwrite.
12589e39c5baSBill Taylor 			 */
12599e39c5baSBill Taylor 
12609e39c5baSBill Taylor 			event = dapli_evd_get_and_init_event(
12619e39c5baSBill Taylor 			    evd_ptr, DAT_DTO_COMPLETION_EVENT);
12629e39c5baSBill Taylor 			if (event == NULL) {
12639e39c5baSBill Taylor 			/*
12649e39c5baSBill Taylor 			 * We've already attempted the overflow post; return.
12659e39c5baSBill Taylor 			 */
12669e39c5baSBill Taylor 				return;
12679e39c5baSBill Taylor 			}
12689e39c5baSBill Taylor 			if (dapli_evd_cqe_to_event(evd_ptr, &cqe[i], DAT_FALSE,
12699e39c5baSBill Taylor 			    event)) {
12709e39c5baSBill Taylor 				dapli_evd_post_event_nosignal(evd_ptr, event);
12719e39c5baSBill Taylor 				cqe_events++;
12729e39c5baSBill Taylor 			} else {
12739e39c5baSBill Taylor 				dapl_dbg_log(DAPL_DBG_TYPE_EVD,
12749e39c5baSBill Taylor 				    "dapls_evd_copy_cq: premature event\n");
12759e39c5baSBill Taylor 				/*
12769e39c5baSBill Taylor 				 * We've deferred processing the CQE, so add
12779e39c5baSBill Taylor 				 * the event_ptr back to free queue
12789e39c5baSBill Taylor 				 */
12799e39c5baSBill Taylor 				dat_status = dapls_rbuf_add(&evd_ptr->
12809e39c5baSBill Taylor 				    free_event_queue, (void *)event);
12819e39c5baSBill Taylor 				dapl_os_assert(dat_status == DAT_SUCCESS);
12829e39c5baSBill Taylor 				if (evd_ptr->evd_producer_locking_needed) {
12839e39c5baSBill Taylor 					dapl_os_unlock(&evd_ptr->header.lock);
12849e39c5baSBill Taylor 				}
12859e39c5baSBill Taylor 			}
12869e39c5baSBill Taylor 		}
12879e39c5baSBill Taylor 		*nevents = cqe_events;
12889e39c5baSBill Taylor 	} else if (DAT_GET_TYPE(dat_status) != DAT_QUEUE_EMPTY) {
12899e39c5baSBill Taylor 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
12909e39c5baSBill Taylor 		    "dapls_evd_copy_cq: dapls_ib_completion_poll "
12919e39c5baSBill Taylor 		    "returned 0x%x\n", dat_status);
12929e39c5baSBill Taylor 		dapl_os_assert(!"Bad return from dapls_ib_completion_poll");
12939e39c5baSBill Taylor 	}
12949e39c5baSBill Taylor }
12959e39c5baSBill Taylor 
12969e39c5baSBill Taylor /*
12979e39c5baSBill Taylor  * dapls_evd_copy_events
12989e39c5baSBill Taylor  *
12999e39c5baSBill Taylor  * Copy all events associated with the EVD onto that EVD
13009e39c5baSBill Taylor  *
13019e39c5baSBill Taylor  * Input:
13029e39c5baSBill Taylor  *	evd_ptr
13039e39c5baSBill Taylor  *	timeout
13049e39c5baSBill Taylor  *
13059e39c5baSBill Taylor  * Output:
1306*93fec3daSToomas Soome  *	return status
13079e39c5baSBill Taylor  *
13089e39c5baSBill Taylor  * Returns:
1309*93fec3daSToomas Soome  *	none
13109e39c5baSBill Taylor  *
13119e39c5baSBill Taylor  */
13129e39c5baSBill Taylor DAT_RETURN
dapls_evd_copy_events(DAPL_EVD * evd_ptr,DAT_TIMEOUT timeout)1313*93fec3daSToomas Soome dapls_evd_copy_events(DAPL_EVD *evd_ptr, DAT_TIMEOUT timeout)
13149e39c5baSBill Taylor {
13159e39c5baSBill Taylor 	dapl_ib_event_t	evp_arr[NUM_EVENTS_PER_POLL];
13169e39c5baSBill Taylor 	dapl_ib_event_t	*evpp_start;
13179e39c5baSBill Taylor 	dapl_ib_event_t	*evpp;
13189e39c5baSBill Taylor 	DAPL_IA		*ia_ptr;
13199e39c5baSBill Taylor 	DAT_RETURN	dat_status;
13209e39c5baSBill Taylor 	int		waited;
13219e39c5baSBill Taylor 	uint64_t	curr_time;
13229e39c5baSBill Taylor 	uint64_t	final_time;
13239e39c5baSBill Taylor 	uint64_t	time_left;
13249e39c5baSBill Taylor 	int		events_needed = 0;
13259e39c5baSBill Taylor 	int		nevents = 0;
13269e39c5baSBill Taylor 	int		num_cqe = 0;
13279e39c5baSBill Taylor 	int		num_ke = 0; /* kernel events - CM or ASYNC events */
13289e39c5baSBill Taylor 	int		i;
13299e39c5baSBill Taylor 
13309e39c5baSBill Taylor 	/* rbuf count is zero on entry */
13319e39c5baSBill Taylor 
13329e39c5baSBill Taylor 	if (evd_ptr->evd_flags & (DAT_EVD_CONNECTION_FLAG |
13339e39c5baSBill Taylor 	    DAT_EVD_CR_FLAG | DAT_EVD_ASYNC_FLAG)) {
13349e39c5baSBill Taylor 		if (evd_ptr->threshold <= NUM_EVENTS_PER_POLL) {
13359e39c5baSBill Taylor 			evpp = evp_arr;
13369e39c5baSBill Taylor 		} else {
13379e39c5baSBill Taylor 			/* need to allocate on the heap */
13389e39c5baSBill Taylor 			evpp = (dapl_ib_event_t *)dapl_os_alloc(
13399e39c5baSBill Taylor 			    evd_ptr->threshold * sizeof (dapl_ib_event_t));
13409e39c5baSBill Taylor 			if (evpp == NULL) {
13419e39c5baSBill Taylor 				return (DAT_INSUFFICIENT_RESOURCES);
13429e39c5baSBill Taylor 			}
13439e39c5baSBill Taylor 		}
13449e39c5baSBill Taylor 		evpp_start = evpp;
13459e39c5baSBill Taylor 		/* for evd_dequeue, check for ke before returning Q_EMPTY */
13469e39c5baSBill Taylor 		if (evd_ptr->threshold == 0 && timeout == 0)
13479e39c5baSBill Taylor 			evd_ptr->threshold = 1;
13489e39c5baSBill Taylor 	} else {
13499e39c5baSBill Taylor 		evpp = NULL;
13509e39c5baSBill Taylor 		evpp_start = NULL;
13519e39c5baSBill Taylor 	}
13529e39c5baSBill Taylor 	ia_ptr = evd_ptr->header.owner_ia;
13539e39c5baSBill Taylor 	waited = 0;
13549e39c5baSBill Taylor 	dat_status = DAT_SUCCESS;
13559e39c5baSBill Taylor 
13569e39c5baSBill Taylor 	/* calculate various time wait elements */
13579e39c5baSBill Taylor 	if (timeout == 0) {
13589e39c5baSBill Taylor 		final_time = 0;
13599e39c5baSBill Taylor 		time_left = 0;
13609e39c5baSBill Taylor 	} else if (timeout == DAT_TIMEOUT_INFINITE) {
13619e39c5baSBill Taylor 		/*
13629e39c5baSBill Taylor 		 * The real value of DAT_TIMEOUT_INFINITE is fairly small
13639e39c5baSBill Taylor 		 * ~71 mins, to prevent premature timeouts map it to
13649e39c5baSBill Taylor 		 * 1 year.  NOTE: 64-bit integers are needed here
13659e39c5baSBill Taylor 		 * because 32 bits is not enough.  Other types,
13669e39c5baSBill Taylor 		 * such as clock_t are not 64-bit, so are not
13679e39c5baSBill Taylor 		 * sufficient for this.  Similarly, hrtime_t is
13689e39c5baSBill Taylor 		 * defined as a "nanosecond counter", which does not
13699e39c5baSBill Taylor 		 * match our need for time in microseconds, so we
13709e39c5baSBill Taylor 		 * just use the more general uint64_t here.
13719e39c5baSBill Taylor 		 */
13729e39c5baSBill Taylor #define	DAPL_ONE_YEAR_IN_USEC	((365 * 24 * 3600) * 1000000LL)
13739e39c5baSBill Taylor 		curr_time = gethrtime();
13749e39c5baSBill Taylor 		time_left = DAPL_ONE_YEAR_IN_USEC;
13759e39c5baSBill Taylor 		final_time = curr_time + DAPL_ONE_YEAR_IN_USEC * 1000;
13769e39c5baSBill Taylor 	} else {
13779e39c5baSBill Taylor 		/*
13789e39c5baSBill Taylor 		 * maximum time by which the routine needs to return
13799e39c5baSBill Taylor 		 * DAT_TIMEOUT_INFINITE is defined as ~0 but its of type int
13809e39c5baSBill Taylor 		 * so mask the MSB to avoid overflow
13819e39c5baSBill Taylor 		 */
13829e39c5baSBill Taylor 		curr_time = gethrtime();
13839e39c5baSBill Taylor 		final_time = curr_time + (uint64_t)(timeout&0x7fffffff)*1000;
13849e39c5baSBill Taylor 		time_left = (final_time - curr_time)/1000;
13859e39c5baSBill Taylor 	}
13869e39c5baSBill Taylor 
13879e39c5baSBill Taylor 	do {
13889e39c5baSBill Taylor 		/*
13899e39c5baSBill Taylor 		 * If this evd has a CQ event stream check the CQs first
13909e39c5baSBill Taylor 		 */
13919e39c5baSBill Taylor 		if (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG |
13929e39c5baSBill Taylor 		    DAT_EVD_RMR_BIND_FLAG)) {
13939e39c5baSBill Taylor 			/*
13949e39c5baSBill Taylor 			 * Poll CQ for events, update the total number of CQEs
13959e39c5baSBill Taylor 			 * so far
13969e39c5baSBill Taylor 			 */
13979e39c5baSBill Taylor 			nevents = 0;
13989e39c5baSBill Taylor 			dapls_evd_copy_cq(evd_ptr, &nevents);
13999e39c5baSBill Taylor 			num_cqe += nevents;
14009e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
14019e39c5baSBill Taylor 			    "dapls_evd_copy_event: copy_cq num_cqe(%d)\n",
14029e39c5baSBill Taylor 			    num_cqe);
14039e39c5baSBill Taylor 		}
14049e39c5baSBill Taylor 
14059e39c5baSBill Taylor 		/*
14069e39c5baSBill Taylor 		 * We use the dapls_rbuf_count since it includes
14079e39c5baSBill Taylor 		 *  - CQ events pulled by dapls_evd_copy_cq
14089e39c5baSBill Taylor 		 *  - events added by dat_evd_post_se()
14099e39c5baSBill Taylor 		 */
14109e39c5baSBill Taylor 		events_needed = evd_ptr->threshold - num_ke -
14119e39c5baSBill Taylor 		    dapls_rbuf_count(&evd_ptr->pending_event_queue);
14129e39c5baSBill Taylor 
14139e39c5baSBill Taylor 		/*
14149e39c5baSBill Taylor 		 * check for pending events
14159e39c5baSBill Taylor 		 * note: threshold=0 implies dapl_evd_dequeue
14169e39c5baSBill Taylor 		 */
14179e39c5baSBill Taylor 		if (events_needed < 0) {
14189e39c5baSBill Taylor 			/* There are more than sufficient events */
14199e39c5baSBill Taylor 			break;
14209e39c5baSBill Taylor 		} else if (events_needed == 0) {
14219e39c5baSBill Taylor 			/* report queue empty on dat_evd_dequeue */
14229e39c5baSBill Taylor 			/* non CQ events are expected to be polled */
14239e39c5baSBill Taylor 			/* by dat_evd_wait */
14249e39c5baSBill Taylor 			if (evd_ptr->threshold == 0)
14259e39c5baSBill Taylor 				dat_status =  DAT_ERROR(DAT_QUEUE_EMPTY, 0);
14269e39c5baSBill Taylor 			/*
14279e39c5baSBill Taylor 			 * when threshold > 0, we have sufficient events
14289e39c5baSBill Taylor 			 */
14299e39c5baSBill Taylor 			break;
14309e39c5baSBill Taylor 		} else {
14319e39c5baSBill Taylor 			/*
14329e39c5baSBill Taylor 			 * when we reach here, this implies dat_evd_wait
14339e39c5baSBill Taylor 			 * return on any dto completion as
14349e39c5baSBill Taylor 			 * threshold > 1 will be taken as hint only
14359e39c5baSBill Taylor 			 */
14369e39c5baSBill Taylor 			if (num_cqe)
14379e39c5baSBill Taylor 				break;
14389e39c5baSBill Taylor 		}
14399e39c5baSBill Taylor 
14409e39c5baSBill Taylor 		/* check we've already waited */
14419e39c5baSBill Taylor 		if (waited > 0) {
14429e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
14439e39c5baSBill Taylor 			    "dapls_evd_copy_event: waited[%d]\n", waited);
14449e39c5baSBill Taylor 			if (dat_status != DAT_SUCCESS)
14459e39c5baSBill Taylor 				break;
14469e39c5baSBill Taylor 			curr_time = gethrtime();
14479e39c5baSBill Taylor 			/* exit on time expired */
14489e39c5baSBill Taylor 			if (curr_time >= final_time)
14499e39c5baSBill Taylor 				break;
14509e39c5baSBill Taylor 			time_left = (final_time - curr_time)/1000;
14519e39c5baSBill Taylor 		}
14529e39c5baSBill Taylor 
14539e39c5baSBill Taylor 		/* check for DTO type evd's */
14549e39c5baSBill Taylor 		if (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG |
14559e39c5baSBill Taylor 		    DAT_EVD_RMR_BIND_FLAG)) {
14569e39c5baSBill Taylor 			if (events_needed == 1) {
14579e39c5baSBill Taylor 				/*
14589e39c5baSBill Taylor 				 * Need only one event so enable cq
14599e39c5baSBill Taylor 				 * notification
14609e39c5baSBill Taylor 				 */
14619e39c5baSBill Taylor 				/*
14629e39c5baSBill Taylor 				 * XXX: Things need to be modified here to
14639e39c5baSBill Taylor 				 * implement the NOTIFICATION suppression
14649e39c5baSBill Taylor 				 * correctly - relies on THRESHOLD flag
14659e39c5baSBill Taylor 				 * and UNSIGNALLED flag to be stored
14669e39c5baSBill Taylor 				 * in the evd.
14679e39c5baSBill Taylor 				 */
14689e39c5baSBill Taylor 				dat_status = dapls_set_cq_notify(ia_ptr,
14699e39c5baSBill Taylor 				    evd_ptr);
14709e39c5baSBill Taylor 				if (dat_status != DAT_SUCCESS) {
14719e39c5baSBill Taylor 					dapl_dbg_log(DAPL_DBG_TYPE_EVD,
14729e39c5baSBill Taylor 					    "dapls_evd_copy_event:"
14739e39c5baSBill Taylor 					    " set_cq_notify(%d)\n", dat_status);
14749e39c5baSBill Taylor 					return (dat_status);
14759e39c5baSBill Taylor 				}
14769e39c5baSBill Taylor 			} else if (events_needed > 1) {
14779e39c5baSBill Taylor 				/*
14789e39c5baSBill Taylor 				 * We need multiple events so lets enable CQ for
14799e39c5baSBill Taylor 				 * notification on N events.
14809e39c5baSBill Taylor 				 * dat_status = dapls_set_cqN_notify(ia_ptr,
14819e39c5baSBill Taylor 				 * evd_ptr, (uint32_t)events_needed);
14829e39c5baSBill Taylor 				 */
14839e39c5baSBill Taylor 				dat_status = dapls_set_cq_notify(ia_ptr,
14849e39c5baSBill Taylor 				    evd_ptr);
14859e39c5baSBill Taylor 				if (dat_status != DAT_SUCCESS) {
14869e39c5baSBill Taylor 					dapl_dbg_log(DAPL_DBG_TYPE_EVD,
14879e39c5baSBill Taylor 					    "dapls_evd_copy_event:"
14889e39c5baSBill Taylor 					    " set_cqN_notify:%d\n", dat_status);
14899e39c5baSBill Taylor 					return (dat_status);
14909e39c5baSBill Taylor 				}
14919e39c5baSBill Taylor 			}
14929e39c5baSBill Taylor 
14939e39c5baSBill Taylor 			/*
14949e39c5baSBill Taylor 			 * Per Tavor PRM if completions occur after polling
14959e39c5baSBill Taylor 			 * the CQ and before arming it, upon arming the CQ
14969e39c5baSBill Taylor 			 * handler will be immediately fired. Hence it
14979e39c5baSBill Taylor 			 * recommends that a re-poll of the CQ can be skipped
14989e39c5baSBill Taylor 			 * as an optimization.
14999e39c5baSBill Taylor 			 */
15009e39c5baSBill Taylor 		}
15019e39c5baSBill Taylor 
15029e39c5baSBill Taylor 		nevents = 0;
15039e39c5baSBill Taylor 
15049e39c5baSBill Taylor 		/*
15059e39c5baSBill Taylor 		 * non-NULL evpp_start denotes either
15069e39c5baSBill Taylor 		 * DAT_EVD_CONNECTION_FLAG, DAT_EVD_CR_FLAG, DAT_EVD_ASYNC_FLAG
15079e39c5baSBill Taylor 		 * is set and thus needs to check events from kernel
15089e39c5baSBill Taylor 		 */
15099e39c5baSBill Taylor 		if (evpp_start) {
15109e39c5baSBill Taylor 			/*
15119e39c5baSBill Taylor 			 * Even if dat_status is not DAT_SUCCESS, num_events
15129e39c5baSBill Taylor 			 * could be non-zero.
15139e39c5baSBill Taylor 			 */
15149e39c5baSBill Taylor 			dat_status = dapls_ib_event_poll(evd_ptr, time_left,
15159e39c5baSBill Taylor 			    (evd_ptr->threshold - (num_cqe + num_ke)), evpp,
15169e39c5baSBill Taylor 			    &nevents);
15179e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
15189e39c5baSBill Taylor 			    "dapls_evd_copy_event: poll returned 0x%x(%d)\n",
15199e39c5baSBill Taylor 			    dat_status, nevents);
15209e39c5baSBill Taylor 
15219e39c5baSBill Taylor 			num_ke += nevents;
15229e39c5baSBill Taylor 			evpp += nevents;
15239e39c5baSBill Taylor 		} else {
15249e39c5baSBill Taylor 			/* perform a timewait */
15259e39c5baSBill Taylor 			dat_status = dapls_ib_event_poll(evd_ptr, time_left,
15269e39c5baSBill Taylor 			    0, NULL, &nevents);
15279e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
15289e39c5baSBill Taylor 			    "dapls_evd_copy_event: poll(cq_notification) "
15299e39c5baSBill Taylor 			    "returned 0x%x\n", dat_status);
15309e39c5baSBill Taylor 			if (DAT_GET_TYPE(dat_status) == DAT_INTERRUPTED_CALL)
15319e39c5baSBill Taylor 				return (dat_status);
15329e39c5baSBill Taylor 		}
15339e39c5baSBill Taylor 
15349e39c5baSBill Taylor 		waited++;
15359e39c5baSBill Taylor 	} while (dapls_rbuf_count(&evd_ptr->pending_event_queue) + num_ke <
15369e39c5baSBill Taylor 	    evd_ptr->threshold);
15379e39c5baSBill Taylor 
15389e39c5baSBill Taylor 	/* process the cm events now */
15399e39c5baSBill Taylor 	for (i = 0; i < num_ke; i++) {
15409e39c5baSBill Taylor 		switch (evpp_start[i].ibe_ev_family) {
15419e39c5baSBill Taylor 		case DAPL_CR_EVENTS: /* PASSIVE side events */
15429e39c5baSBill Taylor 		case DAPL_PASSIVE_CONNECTION_EVENTS:
15439e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
15449e39c5baSBill Taylor 			    "dapls_evd_copy_event: Passive side Event %d\n",
15459e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_event);
15469e39c5baSBill Taylor 			dapls_cr_callback((ib_cm_handle_t)
15479e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_psep_cookie,
15489e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_event,
15499e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_priv_data_ptr, (void *)
15509e39c5baSBill Taylor 			    (uintptr_t)evpp_start[i].ibe_ce.ibce_cookie);
15519e39c5baSBill Taylor 			break;
15529e39c5baSBill Taylor 		case DAPL_ACTIVE_CONNECTION_EVENTS: /* ACTIVE side events */
15539e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
15549e39c5baSBill Taylor 			    "dapls_evd_copy_event: Active Conn Event %d\n",
15559e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_event);
15569e39c5baSBill Taylor 			dapl_evd_connection_callback((ib_cm_handle_t)
15579e39c5baSBill Taylor 			    IB_INVALID_HANDLE,
15589e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_event,
15599e39c5baSBill Taylor 			    evpp_start[i].ibe_ce.ibce_priv_data_ptr, (void *)
15609e39c5baSBill Taylor 			    (uintptr_t)evpp_start[i].ibe_ce.ibce_cookie);
15619e39c5baSBill Taylor 			break;
15629e39c5baSBill Taylor 		case DAPL_ASYNC_EVENTS:
15639e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_EVD,
15649e39c5baSBill Taylor 			    "dapls_evd_copy_event: Async Event %d\n",
15659e39c5baSBill Taylor 			    evpp_start[i].ibe_async.ibae_type);
15669e39c5baSBill Taylor 			dapls_ib_async_callback(evd_ptr,
15679e39c5baSBill Taylor 			    ia_ptr->hca_ptr->ib_hca_handle,
15689e39c5baSBill Taylor 			    &(evpp_start[i].ibe_async), ia_ptr);
15699e39c5baSBill Taylor 			break;
15709e39c5baSBill Taylor 		default:
15719e39c5baSBill Taylor 			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
15729e39c5baSBill Taylor 			    "dapls_evd_copy_event: dapls_ib_event_poll %d "
15739e39c5baSBill Taylor 			    "returned 0x%x\n", i, evpp_start[i].ibe_ev_family);
15749e39c5baSBill Taylor 			dapl_os_assert(!"Bad return from dapls_ib_event_poll");
15759e39c5baSBill Taylor 			break;
15769e39c5baSBill Taylor 		}
15779e39c5baSBill Taylor 	}
15789e39c5baSBill Taylor 
15799e39c5baSBill Taylor 	return (dat_status);
15809e39c5baSBill Taylor }
15819e39c5baSBill Taylor 
15829e39c5baSBill Taylor /*
15839e39c5baSBill Taylor  * dapls_evd_cq_poll_to_event
15849e39c5baSBill Taylor  *
15859e39c5baSBill Taylor  * Attempt to dequeue a single CQE from a CQ and turn it into
15869e39c5baSBill Taylor  * an event.
15879e39c5baSBill Taylor  *
15889e39c5baSBill Taylor  * Input:
15899e39c5baSBill Taylor  *	evd_ptr
15909e39c5baSBill Taylor  *
15919e39c5baSBill Taylor  * Output:
1592*93fec3daSToomas Soome  *	event
15939e39c5baSBill Taylor  *
15949e39c5baSBill Taylor  * Returns:
1595*93fec3daSToomas Soome  *	Status of operation
15969e39c5baSBill Taylor  *
15979e39c5baSBill Taylor  */
15989e39c5baSBill Taylor DAT_RETURN
dapls_evd_cq_poll_to_event(IN DAPL_EVD * evd_ptr,OUT DAT_EVENT * event)1599*93fec3daSToomas Soome dapls_evd_cq_poll_to_event(IN DAPL_EVD *evd_ptr, OUT DAT_EVENT *event)
16009e39c5baSBill Taylor {
16019e39c5baSBill Taylor 	DAT_RETURN		dat_status;
16029e39c5baSBill Taylor 	ib_work_completion_t	cur_cqe;
16039e39c5baSBill Taylor 
16049e39c5baSBill Taylor 	/* skip one layer of do-nothing function */
16059e39c5baSBill Taylor 	dat_status = DAPL_POLL1(evd_ptr)(evd_ptr->ib_cq_handle, &cur_cqe);
16069e39c5baSBill Taylor 
16079e39c5baSBill Taylor 	if (dat_status == DAT_SUCCESS) {
16089e39c5baSBill Taylor #ifdef	DAPL_DBG	/* For debugging.  */
16099e39c5baSBill Taylor 		dapli_evd_eh_print_cqe(cur_cqe);
16109e39c5baSBill Taylor #endif
16119e39c5baSBill Taylor 		(void) dapli_evd_cqe_to_event(evd_ptr, &cur_cqe, DAT_FALSE,
16129e39c5baSBill Taylor 		    event);
16139e39c5baSBill Taylor 	}
16149e39c5baSBill Taylor 
16159e39c5baSBill Taylor 	return (dat_status);
16169e39c5baSBill Taylor }
16179e39c5baSBill Taylor 
16189e39c5baSBill Taylor /*
16199e39c5baSBill Taylor  * Local variables:
16209e39c5baSBill Taylor  *  c-indent-level: 4
16219e39c5baSBill Taylor  *  c-basic-offset: 4
16229e39c5baSBill Taylor  *  tab-width: 8
16239e39c5baSBill Taylor  * End:
16249e39c5baSBill Taylor  */
1625