DAT_RETURN dapl_cr_query( IN DAT_CR_HANDLE cr_handle, IN DAT_CR_PARAM_MASK cr_param_mask, OUT DAT_CR_PARAM *cr_param) { DAPL_CR *cr_ptr; DAT_RETURN dat_status; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_cr_query (%p, %x, %p)\n", cr_handle, cr_param_mask, cr_param); dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(cr_handle, DAPL_MAGIC_CR)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CR); goto bail; } if (NULL == cr_param) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } cr_ptr = (DAPL_CR *) cr_handle; /* since the arguments are easily accessible, ignore the mask */ (void) dapl_os_memcpy(cr_param, &cr_ptr->param, sizeof (DAT_CR_PARAM)); bail: return (dat_status); }
/* * dapl_ep_recv_query * * uDAPL Version 1.2, 6.6.11 * * Destroy an instance of the Endpoint * * Input: * ep_handle * * Output: * none * * Returns: * DAT_SUCCESS * DAT_INVALID_PARAMETER * DAT_INVALID_HANDLE * DAT_MODEL_NOT_SUPPORTED */ DAT_RETURN DAT_API dapl_ep_recv_query(IN DAT_EP_HANDLE ep_handle, OUT DAT_COUNT * nbufs_allocate, OUT DAT_COUNT * bufs_alloc_span) { DAPL_EP *ep_ptr; DAT_RETURN dat_status; dat_status = DAT_SUCCESS; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_ep_recv_query (%p, %p, %p)\n", ep_handle, nbufs_allocate, bufs_alloc_span); ep_ptr = (DAPL_EP *) ep_handle; /* * Verify parameter & state */ if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE); bail: return dat_status; }
/* * dapl_cno_query * * DAPL Requirements Version xxx, 6.3.2.5 * * Return the consumer parameters of the CNO * * Input: * cno_handle * cno_param_mask * cno_param * * Output: * cno_param * * Returns: * DAT_SUCCESS * DAT_INVALID_HANDLE * DAT_INVALID_PARAMETER */ DAT_RETURN dapl_cno_query( IN DAT_CNO_HANDLE cno_handle, /* cno_handle */ IN DAT_CNO_PARAM_MASK cno_param_mask, /* cno_param_mask */ OUT DAT_CNO_PARAM *cno_param) /* cno_param */ { DAPL_CNO *cno_ptr; DAT_RETURN dat_status; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(cno_handle, DAPL_MAGIC_CNO)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CNO); goto bail; } /* check for invalid cno param mask */ if (cno_param_mask & ~DAT_CNO_FIELD_ALL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } if (NULL == cno_param) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } cno_ptr = (DAPL_CNO *)cno_handle; cno_param->ia_handle = cno_ptr->header.owner_ia; cno_param->agent = cno_ptr->cno_wait_agent; bail: return (dat_status); }
/* * 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; /* * 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) { if (evd_ptr->evd_flags & (DAT_EVD_DTO_FLAG | DAT_EVD_RMR_BIND_FLAG)) dapls_evd_dto_wakeup(evd_ptr); else dapl_os_wait_object_wakeup(&evd_ptr->wait_object); } dapl_os_unlock(&evd_ptr->header.lock); bail: return dat_status; }
/* * dapl_ep_query * * DAPL Requirements Version xxx, 6.5.5 * * Provide the consumer parameters, including attributes and status of * the Endpoint. * * Input: * ep_handle * ep_param_mask * * Output: * ep_param * * Returns: * DAT_SUCCESS * DAT_INVALID_PARAMETER */ DAT_RETURN DAT_API dapl_ep_query(IN DAT_EP_HANDLE ep_handle, IN DAT_EP_PARAM_MASK ep_param_mask, OUT DAT_EP_PARAM * ep_param) { DAPL_EP *ep_ptr; DAT_RETURN dat_status; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_ep_query (%p, %x, %p)\n", ep_handle, ep_param_mask, ep_param); dat_status = DAT_SUCCESS; ep_ptr = (DAPL_EP *) ep_handle; /* * Verify parameter & state */ if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } if (ep_param == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } /* * Fill in according to user request * * N.B. Just slam all values into the user structure, there * is nothing to be gained by checking for each bit. */ if (ep_param_mask & DAT_EP_FIELD_ALL) { /* only attempt to get remote IA address if consumer requested it */ if (ep_param_mask & DAT_EP_FIELD_REMOTE_IA_ADDRESS_PTR) { if (ep_ptr->param.ep_state == DAT_EP_STATE_CONNECTED) { /* obtain the remote IP address */ dat_status = dapls_ib_cm_remote_addr((DAT_HANDLE) ep_handle, &ep_ptr-> remote_ia_address); } ep_ptr->param.remote_ia_address_ptr = (DAT_IA_ADDRESS_PTR) & ep_ptr->remote_ia_address; } *ep_param = ep_ptr->param; dats_get_ia_handle(ep_ptr->param.ia_handle, &ep_param->ia_handle); } bail: return dat_status; }
/* * dapl_rmr_bind * * DAPL Requirements Version xxx, 6.6.4.4 * * Bind the RMR to the specified memory region within the LMR and * provide a new rmr_context value. * * Input: * Output: */ DAT_RETURN dapl_rmr_bind( IN DAT_RMR_HANDLE rmr_handle, IN const DAT_LMR_TRIPLET *lmr_triplet, IN DAT_MEM_PRIV_FLAGS mem_priv, IN DAT_EP_HANDLE ep_handle, IN DAT_RMR_COOKIE user_cookie, IN DAT_COMPLETION_FLAGS completion_flags, OUT DAT_RMR_CONTEXT *rmr_context) { DAPL_RMR *rmr; DAPL_EP *ep_ptr; if (DAPL_BAD_HANDLE(rmr_handle, DAPL_MAGIC_RMR)) { return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_RMR)); } if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) { return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP)); } rmr = (DAPL_RMR *) rmr_handle; ep_ptr = (DAPL_EP *) ep_handle; /* if the rmr should be bound */ if (0 != lmr_triplet->segment_length) { return (dapli_rmr_bind_fuse(rmr, lmr_triplet, mem_priv, ep_ptr, user_cookie, completion_flags, rmr_context)); } else { /* the rmr should be unbound */ return (dapli_rmr_bind_unfuse(rmr, lmr_triplet, ep_ptr, user_cookie, completion_flags)); } }
DAT_RETURN 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 qos) { DAPL_EP *ep_dup_ptr; DAT_RETURN dat_status; DAT_IA_ADDRESS_PTR remote_ia_address_ptr; DAT_CONN_QUAL remote_conn_qual; ep_dup_ptr = (DAPL_EP *)ep_dup_handle; /* * Verify the dup handle, which must be connected. All other * parameters will be verified by dapl_ep_connect */ if (DAPL_BAD_HANDLE(ep_dup_handle, DAPL_MAGIC_EP)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } /* * Check both the EP state and the QP state: if we don't have a QP * there is a problem. Do this under a lock and pull out * the connection parameters for atomicity. */ dapl_os_lock(&ep_dup_ptr->header.lock); if (ep_dup_ptr->param.ep_state != DAT_EP_STATE_CONNECTED) { dapl_os_unlock(&ep_dup_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, dapls_ep_state_subtype(ep_dup_ptr)); goto bail; } remote_ia_address_ptr = ep_dup_ptr->param.remote_ia_address_ptr; remote_conn_qual = ep_dup_ptr->param.remote_port_qual; dapl_os_unlock(&ep_dup_ptr->header.lock); dat_status = dapl_ep_connect(ep_handle, remote_ia_address_ptr, remote_conn_qual, timeout, private_data_size, private_data, qos, DAT_CONNECT_DEFAULT_FLAG); bail: return (dat_status); }
/* * dapl_cno_create * * DAPL Requirements Version xxx, 6.3.4.1 * * Create a consumer notification object instance * * Input: * ia_handle * wait_agent * cno_handle * * Output: * cno_handle * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_HANDLE * DAT_INVALID_PARAMETER */ DAT_RETURN dapl_cno_create( IN DAT_IA_HANDLE ia_handle, /* ia_handle */ IN DAT_OS_WAIT_PROXY_AGENT wait_agent, /* agent */ OUT DAT_CNO_HANDLE *cno_handle) /* cno_handle */ { DAPL_IA *ia_ptr; DAPL_CNO *cno_ptr; DAT_RETURN dat_status; ia_ptr = (DAPL_IA *)ia_handle; cno_ptr = NULL; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(ia_handle, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } cno_ptr = dapl_cno_alloc(ia_ptr, wait_agent); if (!cno_ptr) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } cno_ptr->cno_state = DAPL_CNO_STATE_UNTRIGGERED; dat_status = dapls_ib_cno_alloc(ia_ptr, cno_ptr); if (dat_status != DAT_SUCCESS) { goto bail; } dapl_ia_link_cno(ia_ptr, cno_ptr); *cno_handle = cno_ptr; bail: if (dat_status != DAT_SUCCESS && cno_ptr != NULL) { dapl_cno_dealloc(cno_ptr); } return (dat_status); }
/* * dapl_cno_free * * DAPL Requirements Version xxx, 6.3.2.2 * * Destroy a consumer notification object instance * * Input: * cno_handle * * Output: * none * * Returns: * DAT_SUCCESS * DAT_INVALID_HANDLE * DAT_INVALID_STATE */ DAT_RETURN dapl_cno_free( IN DAT_CNO_HANDLE cno_handle) /* cno_handle */ { DAPL_CNO *cno_ptr; DAT_RETURN dat_status; dat_status = DAT_SUCCESS; cno_ptr = (DAPL_CNO *)cno_handle; if (DAPL_BAD_HANDLE(cno_handle, DAPL_MAGIC_CNO)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CNO); goto bail; } if (cno_ptr->cno_ref_count != 0 || cno_ptr->cno_waiters != 0) { dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_CNO_IN_USE); goto bail; } dapl_os_lock(&cno_ptr->header.lock); if (!dapl_llist_is_empty(&cno_ptr->evd_list_head)) { dapl_dbg_log(DAPL_DBG_TYPE_UTIL, "cno_free: evd list not empty!\n"); dapl_os_unlock(&cno_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_CNO_IN_USE); goto bail; } dapl_os_unlock(&cno_ptr->header.lock); dat_status = dapls_ib_cno_free(cno_ptr); if (dat_status != DAT_SUCCESS) { goto bail; } dapl_ia_unlink_cno(cno_ptr->header.owner_ia, cno_ptr); dapl_cno_dealloc(cno_ptr); bail: return (dat_status); }
DAT_RETURN DAT_API dapl_evd_disable(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; } evd_ptr->evd_enabled = DAT_FALSE; bail: return dat_status; }
DAT_RETURN dapl_cr_handoff( IN DAT_CR_HANDLE cr_handle, IN DAT_CONN_QUAL cr_handoff) /* handoff */ { DAPL_CR *cr_ptr; DAT_RETURN dat_status; if (DAPL_BAD_HANDLE(cr_handle, DAPL_MAGIC_CR)) { return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CR)); } cr_ptr = (DAPL_CR *)cr_handle; dat_status = dapls_ib_handoff_connection(cr_ptr, cr_handoff); /* Remove the CR from the queue, then free it */ dapl_sp_remove_cr(cr_ptr->sp_ptr, cr_ptr); dapls_cr_free(cr_ptr); return (dat_status); }
/* * dapl_pz_query * * DAPL Requirements Version xxx, 6.6.2.1 * * Return the ia associated with the protection zone pz * * Input: * pz_handle * pz_param_mask * * Output: * pz_param * * Returns: * DAT_SUCCESS * DAT_INVALID_HANDLE * DAT_INVALID_PARAMETER */ DAT_RETURN dapl_pz_query( IN DAT_PZ_HANDLE pz_handle, IN DAT_PZ_PARAM_MASK pz_param_mask, OUT DAT_PZ_PARAM *pz_param) { DAPL_PZ *pz; DAT_RETURN dat_status; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_pz_query (%p, %x, %p)\n", pz_handle, pz_param_mask, pz_param); dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_PZ); goto bail; } if (NULL == pz_param) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } if (pz_param_mask & ~DAT_PZ_FIELD_ALL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } pz = (DAPL_PZ *) pz_handle; /* Since the DAT_PZ_ARGS values are easily accessible, */ /* don't bother checking the DAT_PZ_ARGS_MASK value */ pz_param->ia_handle = (DAT_IA_HANDLE) pz->header.owner_ia; bail: return (dat_status); }
/* * dapl_rmr_free * * DAPL Requirements Version xxx, 6.6.4.2 * * Destroy an instance of the Remote Memory Region * * Input: * rmr_handle * * Output: * none * * Returns: * DAT_SUCCESS * DAT_INVALID_PARAMETER */ DAT_RETURN dapl_rmr_free(IN DAT_RMR_HANDLE rmr_handle) { DAPL_RMR *rmr; DAT_RETURN dat_status; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(rmr_handle, DAPL_MAGIC_RMR)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_RMR); goto bail; } rmr = (DAPL_RMR *)rmr_handle; /* * If the user did not perform an unbind op, release * counts here. */ if (rmr->param.lmr_triplet.virtual_address != 0) { (void) dapl_os_atomic_dec(&rmr->lmr->lmr_ref_count); rmr->param.lmr_triplet.virtual_address = 0; } dat_status = dapls_ib_mw_free(rmr); if (dat_status != DAT_SUCCESS) { goto bail; } dapl_os_atomic_dec(&rmr->pz->pz_ref_count); dapl_rmr_dealloc(rmr); bail: return (dat_status); }
/* * dapl_srq_query * * DAPL Requirements Version 1.2, 6.5.6 * * Return SRQ parameters to the consumer * * Input: * srq_handle * srq_param_mask * * Output: * srq_param * * Returns: * DAT_SUCCESS * DAT_INVALID_HANDLE * DAT_INVALID_PARAMETER */ 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) { DAPL_SRQ *srq_ptr; DAT_RETURN dat_status; dat_status = DAT_SUCCESS; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_srq_query (%p, %x, %p)\n", srq_handle, srq_param_mask, srq_param); if (DAPL_BAD_HANDLE(srq_handle, DAPL_MAGIC_SRQ)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_SRQ); goto bail; } if (srq_param == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } srq_ptr = (DAPL_SRQ *) srq_handle; /* * XXX Need to calculate available_dto_count and outstanding_dto_count */ srq_ptr->param.available_dto_count = DAT_VALUE_UNKNOWN; srq_ptr->param.outstanding_dto_count = DAT_VALUE_UNKNOWN; *srq_param = srq_ptr->param; dats_get_ia_handle(srq_ptr->header.owner_ia, &srq_param->ia_handle); bail: return dat_status; }
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) { DAPL_IA *ia_ptr; DAPL_EVD *evd_ptr; DAPL_CNO *cno_ptr; DAT_RETURN dat_status; DAT_PROVIDER_ATTR provider_attr; int i; int j; int flag_mask[6]; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_evd_create (%p, %d, %p, 0x%x, %p)\n", ia_handle, evd_min_qlen, cno_handle, evd_flags, evd_handle); ia_ptr = (DAPL_IA *) ia_handle; cno_ptr = (DAPL_CNO *) cno_handle; evd_ptr = NULL; *evd_handle = NULL; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(ia_handle, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } DAPL_CNTR(ia_ptr, DCNT_IA_EVD_CREATE); if (evd_min_qlen <= 0) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } if (evd_min_qlen > ia_ptr->hca_ptr->ia_attr.max_evd_qlen) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_TEVD); goto bail; } if (cno_handle != DAT_HANDLE_NULL && DAPL_BAD_HANDLE(cno_handle, DAPL_MAGIC_CNO)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CNO); goto bail; } /* * Check the merging attributes to ensure the combination of * flags requested is supported. */ dapl_ia_query(ia_handle, NULL, 0, NULL, DAT_PROVIDER_FIELD_ALL, &provider_attr); /* Set up an array of flags to compare against; the EVD bits are * a sparse array that need to be mapped to the merging flags */ flag_mask[0] = DAT_EVD_SOFTWARE_FLAG; flag_mask[1] = DAT_EVD_CR_FLAG; flag_mask[2] = DAT_EVD_DTO_FLAG; flag_mask[3] = DAT_EVD_CONNECTION_FLAG; flag_mask[4] = DAT_EVD_RMR_BIND_FLAG; flag_mask[5] = DAT_EVD_ASYNC_FLAG; for (i = 0; i < 6; i++) { if (flag_mask[i] & evd_flags) { for (j = 0; j < 6; j++) { if (flag_mask[j] & evd_flags) { if (provider_attr. evd_stream_merging_supported[i][j] == DAT_FALSE) { dat_status = DAT_ERROR (DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); goto bail; } } } /* end for j */ } } /* end for i */ dat_status = dapls_evd_internal_create(ia_ptr, cno_ptr, evd_min_qlen, evd_flags, &evd_ptr); if (dat_status != DAT_SUCCESS) { goto bail; } evd_ptr->evd_state = DAPL_EVD_STATE_OPEN; *evd_handle = (DAT_EVD_HANDLE) evd_ptr; bail: if (dat_status != DAT_SUCCESS) { if (evd_ptr) { dapl_evd_free(evd_ptr); } } dapl_dbg_log(DAPL_DBG_TYPE_RTN, "dapl_evd_create () returns 0x%x\n", dat_status); return dat_status; }
/* * dapl_ia_open * * DAPL Requirements Version xxx, 6.2.1.1 * * Open a provider and return a handle. The handle enables the user * to invoke operations on this provider. * * The dat_ia_open call is actually part of the DAT registration module. * That function maps the DAT_NAME parameter of dat_ia_open to a DAT_PROVIDER, * and calls this function. * * Input: * provider * async_evd_qlen * async_evd_handle_ptr * * Output: * async_evd_handle * ia_handle * * Return Values: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_PARAMETER * DAT_INVALID_HANDLE * DAT_PROVIDER_NOT_FOUND (returned by dat registry if necessary) */ DAT_RETURN DAT_API dapl_ia_open(IN const DAT_NAME_PTR name, IN DAT_COUNT async_evd_qlen, INOUT DAT_EVD_HANDLE * async_evd_handle_ptr, OUT DAT_IA_HANDLE * ia_handle_ptr) { DAT_RETURN dat_status; DAT_PROVIDER *provider; DAPL_HCA *hca_ptr; DAPL_IA *ia_ptr; DAPL_EVD *evd_ptr; dat_status = DAT_SUCCESS; hca_ptr = NULL; ia_ptr = NULL; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_ia_open (%s, %d, %p, %p)\n", name, async_evd_qlen, async_evd_handle_ptr, ia_handle_ptr); dat_status = dapl_provider_list_search(name, &provider); if (DAT_SUCCESS != dat_status) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG1); goto bail; } /* ia_handle_ptr and async_evd_handle_ptr cannot be NULL */ if (ia_handle_ptr == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); goto bail; } if (async_evd_handle_ptr == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } /* initialize the caller's OUT param */ *ia_handle_ptr = DAT_HANDLE_NULL; /* get the hca_ptr */ hca_ptr = (DAPL_HCA *) provider->extension; /* log levels could be reset and set between opens */ g_dapl_dbg_type = dapl_os_get_env_val("DAPL_DBG_TYPE", DAPL_DBG_TYPE_ERR | DAPL_DBG_TYPE_WARN); /* * Open the HCA if it has not been done before. */ dapl_os_lock(&hca_ptr->lock); if (hca_ptr->ib_hca_handle == IB_INVALID_HANDLE) { /* register with the HW */ dat_status = dapls_ib_open_hca(hca_ptr->name, hca_ptr, DAPL_OPEN_NORMAL); if (dat_status != DAT_SUCCESS) { dapl_dbg_log(DAPL_DBG_TYPE_ERR, "dapls_ib_open_hca failed %x\n", dat_status); dapl_os_unlock(&hca_ptr->lock); goto bail; } /* * Obtain the IP address associated with this name and HCA. */ #ifdef IBHOSTS_NAMING dapli_assign_hca_ip_address(hca_ptr, name); #endif /* IBHOSTS_NAMING */ /* * Obtain IA attributes from the HCA to limit certain * operations. * If using DAPL_ATS naming, ib_query_hca will also set the ip * address. */ dat_status = dapls_ib_query_hca(hca_ptr, &hca_ptr->ia_attr, NULL, &hca_ptr->hca_address); if (dat_status != DAT_SUCCESS) { dapli_hca_cleanup(hca_ptr, DAT_FALSE); dapl_os_unlock(&hca_ptr->lock); goto bail; } } /* Take a reference on the hca_handle */ dapl_os_atomic_inc(&hca_ptr->handle_ref_count); dapl_os_unlock(&hca_ptr->lock); /* Allocate and initialize ia structure */ ia_ptr = dapl_ia_alloc(provider, hca_ptr); if (!ia_ptr) { dapl_os_lock(&hca_ptr->lock); dapli_hca_cleanup(hca_ptr, DAT_TRUE); dapl_os_unlock(&hca_ptr->lock); dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } /* we need an async EVD for this IA * use the one passed in (if non-NULL) or create one */ evd_ptr = (DAPL_EVD *) * async_evd_handle_ptr; if (evd_ptr) { if (DAPL_BAD_HANDLE(evd_ptr, DAPL_MAGIC_EVD) || !(evd_ptr->evd_flags & DAT_EVD_ASYNC_FLAG)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_ASYNC); goto bail; } /* InfiniBand allows only 1 asychronous event handler per HCA */ /* (see InfiniBand Spec, release 1.1, vol I, section 11.5.2, */ /* page 559). */ /* */ /* We only need to make sure that this EVD's CQ belongs to */ /* the same HCA as is being opened. */ if (evd_ptr->header.owner_ia->hca_ptr->ib_hca_handle != hca_ptr->ib_hca_handle) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_ASYNC); goto bail; } ia_ptr->cleanup_async_error_evd = DAT_FALSE; ia_ptr->async_error_evd = evd_ptr; } else { /* Verify we have >0 length, and let the provider check the size */ if (async_evd_qlen <= 0) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } dat_status = dapls_evd_internal_create(ia_ptr, NULL, /* CNO ptr */ async_evd_qlen, DAT_EVD_ASYNC_FLAG, &evd_ptr); if (dat_status != DAT_SUCCESS) { goto bail; } dapl_os_atomic_inc(&evd_ptr->evd_ref_count); dapl_os_lock(&hca_ptr->lock); if (hca_ptr->async_evd != (DAPL_EVD *) 0) { dapl_os_unlock(&hca_ptr->lock); } else { hca_ptr->async_evd = evd_ptr; dapl_os_unlock(&hca_ptr->lock); /* Register the handlers associated with the async EVD. */ dat_status = dapls_ia_setup_callbacks(ia_ptr, evd_ptr); if (dat_status != DAT_SUCCESS) { /* Assign the EVD so it gets cleaned up */ ia_ptr->cleanup_async_error_evd = DAT_TRUE; ia_ptr->async_error_evd = evd_ptr; goto bail; } } ia_ptr->cleanup_async_error_evd = DAT_TRUE; ia_ptr->async_error_evd = evd_ptr; } dat_status = DAT_SUCCESS; *ia_handle_ptr = ia_ptr; *async_evd_handle_ptr = evd_ptr; #if DAPL_COUNTERS dapli_start_counters((DAT_HANDLE)ia_ptr); #endif bail: if (dat_status != DAT_SUCCESS) { if (ia_ptr) { /* This will release the async EVD if needed. */ dapl_ia_close(ia_ptr, DAT_CLOSE_ABRUPT_FLAG); } } dapl_dbg_log(DAPL_DBG_TYPE_RTN, "dapl_ia_open () returns 0x%x\n", dat_status); return dat_status; }
/* * dapl_psp_create * * uDAPL: User Direct Access Program Library Version 1.1, 6.4.1.1 * * Create a persistent Public Service Point that can recieve multiple * requests for connections and generate multiple connection request * instances that wil be delivered to the specified Event Dispatcher * in a notification event. * * Input: * ia_handle * conn_qual * evd_handle * psp_flags * * Output: * psp_handle * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_PARAMETER * DAT_CONN_QUAL_IN_USE * DAT_MODEL_NOT_SUPPORTED */ DAT_RETURN 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) { DAPL_IA *ia_ptr; DAPL_SP *sp_ptr; DAPL_EVD *evd_ptr; DAT_BOOLEAN sp_found; DAT_RETURN dat_status; ia_ptr = (DAPL_IA *)ia_handle; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } if (psp_handle == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5); goto bail; } /* check for invalid psp flags */ if ((psp_flags != DAT_PSP_CONSUMER_FLAG) && (psp_flags != DAT_PSP_PROVIDER_FLAG)) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); goto bail; } evd_ptr = (DAPL_EVD *)evd_handle; if (!(evd_ptr->evd_flags & DAT_EVD_CR_FLAG)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } /* * check for connection qualifier eq 0 * in IB this is called Null Service ID, use of it in CM is invalid. * in tcp/udp, port number 0 is reserved. */ if (!conn_qual) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } /* * See if we have a quiescent listener to use for this PSP, else * create one and set it listening */ sp_ptr = dapls_ia_sp_search(ia_ptr, conn_qual, DAT_TRUE); sp_found = DAT_TRUE; if (sp_ptr == NULL) { /* Allocate PSP */ sp_found = DAT_FALSE; sp_ptr = dapls_sp_alloc(ia_ptr, DAT_TRUE); if (sp_ptr == NULL) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } } else if (sp_ptr->listening == DAT_TRUE) { dat_status = DAT_ERROR(DAT_CONN_QUAL_IN_USE, 0); goto bail; } /* * Fill out the args for a PSP */ sp_ptr->ia_handle = ia_handle; sp_ptr->conn_qual = conn_qual; sp_ptr->evd_handle = evd_handle; sp_ptr->psp_flags = psp_flags; sp_ptr->ep_handle = NULL; /* * Take a reference on the EVD handle */ (void) dapl_os_atomic_inc(&((DAPL_EVD *)evd_handle)->evd_ref_count); /* * Set up a listener for a connection. Connections can arrive * even before this call returns! */ sp_ptr->state = DAPL_SP_STATE_PSP_LISTENING; sp_ptr->listening = DAT_TRUE; /* * If this is a new sp we need to add it to the IA queue, and set up * a conn_listener. */ if (sp_found == DAT_FALSE) { /* Link it onto the IA */ dapl_ia_link_psp(ia_ptr, sp_ptr); dat_status = dapls_ib_setup_conn_listener(ia_ptr, conn_qual, sp_ptr); if (dat_status != DAT_SUCCESS) { /* * Have a problem setting up the connection, something * wrong! The psp_free decrements the EVD refcount for * us; we don't * need to do that. * But we want to set the listener bits to false, * as we know that call failed. */ sp_ptr->state = DAPL_SP_STATE_FREE; sp_ptr->listening = DAT_FALSE; (void) dapl_psp_free((DAT_PSP_HANDLE) sp_ptr); dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapl_psp_create setup_conn_listener failed: " "%x\n", dat_status); goto bail; } } /* * Return handle to the user */ *psp_handle = (DAT_PSP_HANDLE)sp_ptr; bail: return (dat_status); }
/* * dapl_ep_connect * * DAPL Requirements Version xxx, 6.5.7 * * Request a connection be established between the local Endpoint * and a remote Endpoint. This operation is used by the active/client * side of a connection * * Input: * ep_handle * remote_ia_address * remote_conn_qual * timeout * private_data_size * privaet_data * qos * connect_flags * * Output: * None * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOUCRES * DAT_INVALID_PARAMETER * DAT_MODLE_NOT_SUPPORTED */ DAT_RETURN dapl_ep_connect( IN DAT_EP_HANDLE ep_handle, IN DAT_IA_ADDRESS_PTR remote_ia_address, IN DAT_CONN_QUAL remote_conn_qual, IN DAT_TIMEOUT timeout, IN DAT_COUNT private_data_size, IN const DAT_PVOID private_data, IN DAT_QOS qos, IN DAT_CONNECT_FLAGS connect_flags) { DAPL_EP *ep_ptr; DAPL_PRIVATE prd; DAPL_EP alloc_ep; DAT_RETURN dat_status; dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM, "dapl_ep_connect (%p, {%u.%u.%u.%u}, %X, %d, %d, %p, %x, %x)\n", ep_handle, remote_ia_address->sa_data[2], remote_ia_address->sa_data[3], remote_ia_address->sa_data[4], remote_ia_address->sa_data[5], remote_conn_qual, timeout, private_data_size, private_data, qos, connect_flags); dat_status = DAT_SUCCESS; ep_ptr = (DAPL_EP *) ep_handle; /* * Verify parameter & state. The connection handle must be good * at this point. */ if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } if (DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CONN); goto bail; } /* * If the endpoint needs a QP, associated the QP with it. * This needs to be done carefully, in order to: * * Avoid allocating under a lock. * * Not step on data structures being altered by * routines with which we are racing. * So we: * * Confirm that a new QP is needed and is not forbidden by the * current state. * * Allocate it into a separate EP. * * Take the EP lock. * * Reconfirm that the EP is in a state where it needs a QP. * * Assign the QP and release the lock. */ if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) { if (ep_ptr->param.pz_handle == NULL || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ)) { dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_EP_NOTREADY); goto bail; } alloc_ep = *ep_ptr; dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia, &alloc_ep, ep_ptr); if (dat_status != DAT_SUCCESS) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } dapl_os_lock(&ep_ptr->header.lock); /* * PZ shouldn't have changed since we're only racing with * dapl_cr_accept() */ if (ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED) { /* Bail, cleaning up. */ dapl_os_unlock(&ep_ptr->header.lock); dat_status = dapls_ib_qp_free(ep_ptr->header.owner_ia, &alloc_ep); if (dat_status != DAT_SUCCESS) { dapl_dbg_log(DAPL_DBG_TYPE_WARN, "ep_connect: ib_qp_free failed with %x\n", dat_status); } dat_status = DAT_ERROR(DAT_INVALID_STATE, dapls_ep_state_subtype(ep_ptr)); goto bail; } ep_ptr->qp_handle = alloc_ep.qp_handle; ep_ptr->qpn = alloc_ep.qpn; ep_ptr->qp_state = alloc_ep.qp_state; dapl_os_unlock(&ep_ptr->header.lock); } /* * We do state checks and transitions under lock. * The only code we're racing against is dapl_cr_accept. */ dapl_os_lock(&ep_ptr->header.lock); /* * Verify the attributes of the EP handle before we connect it. Test * all of the handles to make sure they are currently valid. * Specifically: * pz_handle required * recv_evd_handle optional, but must be valid * request_evd_handle optional, but must be valid * connect_evd_handle required */ if (ep_ptr->param.pz_handle == NULL || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) || ep_ptr->param.connect_evd_handle == NULL || DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD) || !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags & DAT_EVD_CONNECTION_FLAG) || (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL && (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD))) || (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL && (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle, DAPL_MAGIC_EVD)))) { dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_EP_NOTREADY); goto bail; } /* * Check both the EP state and the QP state: if we don't have a QP * we need to attach one now. */ if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) { dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia, ep_ptr, ep_ptr); if (dat_status != DAT_SUCCESS) { dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_TEP); goto bail; } } if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED) { dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, dapls_ep_state_subtype(ep_ptr)); goto bail; } if (qos != DAT_QOS_BEST_EFFORT || connect_flags != DAT_CONNECT_DEFAULT_FLAG) { /* * At this point we only support one QOS level */ dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_MODEL_NOT_SUPPORTED, 0); goto bail; } /* * Verify the private data size doesn't exceed the max */ if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) { dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5); goto bail; } /* * transition the state before requesting a connection to avoid * race conditions */ ep_ptr->param.ep_state = DAT_EP_STATE_ACTIVE_CONNECTION_PENDING; /* * At this point we're committed, and done with the endpoint * except for the connect, so we can drop the lock. */ dapl_os_unlock(&ep_ptr->header.lock); /* * fill in the private data */ (void) dapl_os_memzero(&prd, sizeof (DAPL_PRIVATE)); if (private_data_size > 0) (void) dapl_os_memcpy(prd.private_data, private_data, private_data_size); /* Copy the connection qualifiers */ (void) dapl_os_memcpy(ep_ptr->param.remote_ia_address_ptr, remote_ia_address, sizeof (DAT_SOCK_ADDR6)); ep_ptr->param.remote_port_qual = remote_conn_qual; dat_status = dapls_ib_connect(ep_handle, remote_ia_address, remote_conn_qual, private_data_size, &prd, timeout); if (dat_status != DAT_SUCCESS) { DAPL_EVD *evd_ptr; if (dat_status == DAT_ERROR(DAT_INVALID_ADDRESS, DAT_INVALID_ADDRESS_UNREACHABLE)) { /* Unreachable IP address */ evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle; if (evd_ptr != NULL) { (void) dapls_evd_post_connection_event(evd_ptr, DAT_CONNECTION_EVENT_UNREACHABLE, (DAT_HANDLE) ep_ptr, 0, 0); } ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED; dat_status = DAT_SUCCESS; } else if (dat_status == DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ADDRESS_UNREACHABLE)) { /* Non-existant connection qualifier */ evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle; if (evd_ptr != NULL) { (void) dapls_evd_post_connection_event(evd_ptr, DAT_CONNECTION_EVENT_NON_PEER_REJECTED, (DAT_HANDLE) ep_ptr, 0, 0); } ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED; dat_status = DAT_SUCCESS; } else { ep_ptr->param.ep_state = DAT_EP_STATE_UNCONNECTED; } } bail: dapl_dbg_log(DAPL_DBG_TYPE_RTN | DAPL_DBG_TYPE_CM, "dapl_ep_connect () returns 0x%x\n", dat_status); return (dat_status); }
/* * dapl_psp_create_any * * uDAPL: User Direct Access Program Library Version 1.1, 6.4.3.3 * * Create a persistent Public Service Point that can receive multiple * requests for connections and generate multiple connection request * instances that will be delivered to the specified Event Dispatcher * in a notification event. Differs from dapl_psp_create() in that * the conn_qual is selected by the implementation and returned to * the user. * * Input: * ia_handle * evd_handle * psp_flags * * Output: * conn_qual * psp_handle * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_HANDLE * DAT_INVALID_PARAMETER * DAT_CONN_QUAL_IN_USE * DAT_MODEL_NOT_SUPPORTED */ 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) { DAPL_IA *ia_ptr; DAPL_SP *sp_ptr; DAPL_EVD *evd_ptr; DAT_RETURN dat_status; static DAT_CONN_QUAL hint_conn_qual = 1024; /* seed value */ DAT_CONN_QUAL lcl_conn_qual; DAT_CONN_QUAL limit_conn_qual; ia_ptr = (DAPL_IA *) ia_handle; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } if (psp_handle == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5); goto bail; } if (conn_qual == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } evd_ptr = (DAPL_EVD *) evd_handle; if (!(evd_ptr->evd_flags & DAT_EVD_CR_FLAG)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } if (psp_flags != DAT_PSP_CONSUMER_FLAG && psp_flags != DAT_PSP_PROVIDER_FLAG) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); goto bail; } /* Allocate PSP */ sp_ptr = dapls_sp_alloc(ia_ptr, DAT_TRUE); if (sp_ptr == NULL) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } DAPL_CNTR(ia_ptr, DCNT_IA_PSP_CREATE_ANY); /* * Fill out the args for a PSP */ sp_ptr->evd_handle = evd_handle; sp_ptr->psp_flags = psp_flags; sp_ptr->ep_handle = NULL; /* * Take a reference on the EVD handle */ dapl_os_atomic_inc(&((DAPL_EVD *) evd_handle)->evd_ref_count); /* Link it onto the IA */ dapl_ia_link_psp(ia_ptr, sp_ptr); /* * Set up a listener for a connection. Connections can arrive * even before this call returns! */ sp_ptr->state = DAPL_SP_STATE_PSP_LISTENING; sp_ptr->listening = DAT_TRUE; limit_conn_qual = 0; lcl_conn_qual = hint_conn_qual; dat_status = ~DAT_SUCCESS; while (dat_status != DAT_SUCCESS) { dat_status = dapls_ib_setup_conn_listener(ia_ptr, lcl_conn_qual, sp_ptr); lcl_conn_qual++; if (dat_status == DAT_CONN_QUAL_IN_USE) { /* * If we have a big number of tries and we still haven't * found a service_ID we can use, bail out with an error, * something is wrong! */ if (limit_conn_qual++ > 100000) { dat_status = DAT_CONN_QUAL_UNAVAILABLE; break; } } } hint_conn_qual = lcl_conn_qual; if (dat_status != DAT_SUCCESS) { /* * Have a problem setting up the connection, something wrong! */ dapl_os_atomic_dec(&((DAPL_EVD *) evd_handle)->evd_ref_count); sp_ptr->evd_handle = NULL; dapls_ia_unlink_sp(ia_ptr, sp_ptr); dapls_sp_free_sp(sp_ptr); dapl_os_printf ("--> dapl_psp_create cannot set up conn listener: %x\n", dat_status); goto bail; } sp_ptr->conn_qual = lcl_conn_qual - 1; /* * Return handle to the user */ *conn_qual = sp_ptr->conn_qual; *psp_handle = (DAT_PSP_HANDLE) sp_ptr; bail: return dat_status; }
/* * dapli_get_sp_ep * * Passive side of a connection is now fully established. Clean * up resources and obtain the EP pointer associated with a CR in * the SP * * Input: * ib_cm_handle, * sp_ptr * connection_event * * Output: * none * * Returns * ep_ptr * */ DAPL_EP *dapli_get_sp_ep(IN dp_ib_cm_handle_t ib_cm_handle, IN DAPL_SP * sp_ptr, IN DAT_EVENT_NUMBER dat_event_num) { DAPL_CR *cr_ptr; DAPL_EP *ep_ptr; /* * acquire the lock, we may be racing with other threads here */ dapl_os_lock(&sp_ptr->header.lock); /* Verify under lock that the SP is still valid */ if (sp_ptr->header.magic == DAPL_MAGIC_INVALID) { dapl_os_unlock(&sp_ptr->header.lock); return NULL; } /* * There are potentially multiple connections in progress. Need to * go through the list and find the one we are interested * in. There is no guarantee of order. dapl_sp_search_cr * leaves the CR on the SP queue. */ cr_ptr = dapl_sp_search_cr(sp_ptr, ib_cm_handle); if (cr_ptr == NULL) { dapl_os_unlock(&sp_ptr->header.lock); return NULL; } ep_ptr = (DAPL_EP *) cr_ptr->param.local_ep_handle; /* Quick check to ensure our EP is still valid */ if ((DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP))) { ep_ptr = NULL; } /* The CR record is discarded in all except for the CONNECTED case, * as it will have no further relevance. */ if (dat_event_num != DAT_CONNECTION_EVENT_ESTABLISHED) { /* Remove the CR from the queue */ dapl_sp_remove_cr(sp_ptr, cr_ptr); if (ep_ptr != NULL) { ep_ptr->cr_ptr = NULL; } /* * If this SP has been removed from service, free it * up after the last CR is removed */ if (sp_ptr->listening != DAT_TRUE && sp_ptr->cr_list_count == 0 && sp_ptr->state != DAPL_SP_STATE_FREE && sp_ptr->state != DAPL_SP_STATE_RSP_LISTENING) { dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapli_get_sp_ep! disconnect dump sp: %p \n", sp_ptr); /* Decrement the ref count on the EVD */ if (sp_ptr->evd_handle) { dapl_os_atomic_dec(& ((DAPL_EVD *) sp_ptr-> evd_handle)->evd_ref_count); sp_ptr->evd_handle = NULL; } sp_ptr->state = DAPL_SP_STATE_FREE; dapl_os_unlock(&sp_ptr->header.lock); (void)dapls_ib_remove_conn_listener(sp_ptr->header. owner_ia, sp_ptr); dapls_ia_unlink_sp((DAPL_IA *) sp_ptr->header.owner_ia, sp_ptr); dapls_sp_free_sp(sp_ptr); dapls_cr_free(cr_ptr); goto skip_unlock; } dapl_os_unlock(&sp_ptr->header.lock); /* free memory outside of the lock */ dapls_cr_free(cr_ptr); } else { dapl_os_unlock(&sp_ptr->header.lock); } skip_unlock: return ep_ptr; }
DAT_RETURN dapl_evd_resize( IN DAT_EVD_HANDLE evd_handle, IN DAT_COUNT req_evd_qlen) { int i; DAPL_EVD *evd_ptr; DAT_EVENT *event_ptr; DAT_EVENT *eventp; DAT_EVENT *event; DAT_EVENT *new_event; DAPL_RING_BUFFER free_event_queue; DAPL_RING_BUFFER pending_event_queue; DAT_RETURN dat_status; DAT_COUNT max_evd_qlen; DAT_COUNT evd_qlen; evd_ptr = (DAPL_EVD *)evd_handle; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { return (DAT_ERROR(DAT_INVALID_HANDLE, 0)); } if (req_evd_qlen < evd_ptr->qlen) { return (DAT_ERROR(DAT_INVALID_STATE, 0)); } if (req_evd_qlen == evd_ptr->qlen) { return (DAT_SUCCESS); } max_evd_qlen = evd_ptr->header.owner_ia->hca_ptr->ia_attr.max_evd_qlen; if (req_evd_qlen > max_evd_qlen) { return (DAT_ERROR(DAT_INVALID_STATE, 0)); } evd_qlen = DAPL_MIN_RESZ_QLEN; while (req_evd_qlen > evd_qlen) { evd_qlen <<= 1; if (evd_qlen > max_evd_qlen) evd_qlen = max_evd_qlen; } /* Allocate EVENTs */ event_ptr = (DAT_EVENT *) dapl_os_alloc(evd_qlen * sizeof (DAT_EVENT)); if (!event_ptr) { return (DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY)); } /* allocate free event queue */ dat_status = dapls_rbuf_alloc(&free_event_queue, evd_qlen); if (dat_status != DAT_SUCCESS) { goto bail; } /* allocate pending event queue */ dat_status = dapls_rbuf_alloc(&pending_event_queue, evd_qlen); if (dat_status != DAT_SUCCESS) { goto bail; } /* need to resize the cq only for DTO/BIND evds */ if (0 != (evd_ptr->evd_flags & ~ (DAT_EVD_SOFTWARE_FLAG | DAT_EVD_CONNECTION_FLAG | DAT_EVD_CR_FLAG))) { dat_status = dapls_ib_cq_resize(evd_ptr, evd_qlen); if (dat_status != DAT_SUCCESS) goto bail; } /* add events to free event queue */ for (i = 0, eventp = event_ptr; i < evd_qlen; i++) { (void) dapls_rbuf_add(&free_event_queue, (void *)eventp); eventp++; } /* * copy pending events from evd to the new pending event queue */ while (event = (DAT_EVENT *) dapls_rbuf_remove(&evd_ptr->pending_event_queue)) { new_event = (DAT_EVENT *) dapls_rbuf_remove(&free_event_queue); dapl_os_assert(new_event); (void) dapl_os_memcpy(new_event, event, sizeof (DAT_EVENT)); dat_status = dapls_rbuf_add(&pending_event_queue, new_event); dapl_os_assert(dat_status == DAT_SUCCESS); dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue, event); dapl_os_assert(dat_status == DAT_SUCCESS); } 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)); } evd_ptr->events = event_ptr; evd_ptr->free_event_queue = free_event_queue; evd_ptr->pending_event_queue = pending_event_queue; evd_ptr->qlen = evd_qlen; return (DAT_SUCCESS); bail: /* * If we are here means event_ptr was allocd but something else * failed */ dapl_os_free(event_ptr, evd_qlen * sizeof (DAT_EVENT)); dapls_rbuf_destroy(&free_event_queue); dapls_rbuf_destroy(&pending_event_queue); return (dat_status); }
/* * dapl_psp_create * * uDAPL: User Direct Access Program Library Version 1.1, 6.4.1.1 * * Create a persistent Public Service Point that can receive multiple * requests for connections and generate multiple connection request * instances that will be delivered to the specified Event Dispatcher * in a notification event. * * Input: * ia_handle * conn_qual * evd_handle * psp_flags * * Output: * psp_handle * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_PARAMETER * DAT_CONN_QUAL_IN_USE * DAT_MODEL_NOT_SUPPORTED */ 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) { DAPL_IA *ia_ptr; DAPL_SP *sp_ptr; DAPL_EVD *evd_ptr; DAT_BOOLEAN sp_found; DAT_RETURN dat_status; ia_ptr = (DAPL_IA *) ia_handle; dat_status = DAT_SUCCESS; if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } if (psp_handle == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5); goto bail; } evd_ptr = (DAPL_EVD *) evd_handle; if (!(evd_ptr->evd_flags & DAT_EVD_CR_FLAG)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } if (psp_flags != DAT_PSP_CONSUMER_FLAG && psp_flags != DAT_PSP_PROVIDER_FLAG) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); goto bail; } DAPL_CNTR(ia_ptr, DCNT_IA_PSP_CREATE); /* * See if we have a quiescent listener to use for this PSP, else * create one and set it listening */ sp_ptr = dapls_ia_sp_search(ia_ptr, conn_qual, DAT_TRUE); sp_found = DAT_TRUE; if (sp_ptr == NULL) { /* Allocate PSP */ sp_found = DAT_FALSE; sp_ptr = dapls_sp_alloc(ia_ptr, DAT_TRUE); if (sp_ptr == NULL) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } } else if (sp_ptr->listening == DAT_TRUE) { dat_status = DAT_ERROR(DAT_CONN_QUAL_IN_USE, 0); goto bail; } /* * Fill out the args for a PSP */ sp_ptr->conn_qual = conn_qual; sp_ptr->evd_handle = evd_handle; sp_ptr->psp_flags = psp_flags; sp_ptr->ep_handle = NULL; /* * Take a reference on the EVD handle */ dapl_os_atomic_inc(&((DAPL_EVD *) evd_handle)->evd_ref_count); /* * Set up a listener for a connection. Connections can arrive * even before this call returns! */ sp_ptr->state = DAPL_SP_STATE_PSP_LISTENING; sp_ptr->listening = DAT_TRUE; /* * If this is a new sp we need to add it to the IA queue, and set up * a conn_listener. */ if (sp_found == DAT_FALSE) { /* Link it onto the IA before enabling it to receive conn * requests */ dapl_ia_link_psp(ia_ptr, sp_ptr); dat_status = dapls_ib_setup_conn_listener(ia_ptr, conn_qual, sp_ptr); if (dat_status != DAT_SUCCESS) { /* * Have a problem setting up the connection, something * wrong! Decrements the EVD refcount & release it. */ dapl_os_atomic_dec(&((DAPL_EVD *) evd_handle)-> evd_ref_count); sp_ptr->evd_handle = NULL; dapls_ia_unlink_sp(ia_ptr, sp_ptr); dapls_sp_free_sp(sp_ptr); dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapl_psp_create setup_conn_listener failed: %x\n", dat_status); goto bail; } } /* * Return handle to the user */ *psp_handle = (DAT_PSP_HANDLE) sp_ptr; bail: return dat_status; }
/* * dapl_cr_accept * * DAPL Requirements Version xxx, 6.4.2.1 * * Establish a connection between active remote side requesting Endpoint * and passic side local Endpoint. * * Input: * cr_handle * ep_handle * private_data_size * private_data * * Output: * none * * Returns: * DAT_SUCCESS * DAT_INVALID_PARAMETER * DAT_INVALID_ATTRIBUTE */ DAT_RETURN 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) { DAPL_EP *ep_ptr; DAT_RETURN dat_status; DAPL_PRIVATE prd; DAPL_CR *cr_ptr; DAT_EP_STATE entry_ep_state; DAT_EP_HANDLE entry_ep_handle; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_cr_accept(%p, %p, %d, %p)\n", cr_handle, ep_handle, private_data_size, private_data); if (DAPL_BAD_HANDLE(cr_handle, DAPL_MAGIC_CR)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_CR); goto bail; } cr_ptr = (DAPL_CR *) cr_handle; /* * Return an error if we have an ep_handle and the CR already has an * EP, indicating this is an RSP connection or PSP_PROVIDER_FLAG was * specified. */ if (ep_handle != NULL && (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP) || cr_ptr->param.local_ep_handle != NULL)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } if ((0 != private_data_size) && (NULL == private_data)) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG4); goto bail; } /* * Verify the private data size doesn't exceed the max */ if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG3); goto bail; } /* * ep_handle is NULL if the user specified DAT_PSP_PROVIDER_FLAG * OR this is an RSP connection; retrieve it from the cr. */ if (ep_handle == NULL) { ep_handle = cr_ptr->param.local_ep_handle; if ((((DAPL_EP *) ep_handle)->param.ep_state != DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING) && (((DAPL_EP *)ep_handle)->param.ep_state != DAT_EP_STATE_PASSIVE_CONNECTION_PENDING)) { return (DAT_INVALID_STATE); } } else { /* ensure this EP isn't connected or in use */ if (((DAPL_EP *)ep_handle)->param.ep_state != DAT_EP_STATE_UNCONNECTED) { return (DAT_INVALID_STATE); } } ep_ptr = (DAPL_EP *) ep_handle; /* * Verify the attributes of the EP handle before we connect it. Test * all of the handles to make sure they are currently valid. * Specifically: * pz_handle required * recv_evd_handle optional, but must be valid * request_evd_handle optional, but must be valid * connect_evd_handle required * We do all verification and state change under lock, at which * point the EP state should protect us from most races. */ dapl_os_lock(&ep_ptr->header.lock); if ((ep_ptr->param.pz_handle == NULL) || DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) || (ep_ptr->param.connect_evd_handle == NULL) || DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD) || !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags & DAT_EVD_CONNECTION_FLAG) || (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL && (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle, DAPL_MAGIC_EVD))) || (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL && (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle, DAPL_MAGIC_EVD)))) { dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) { /* * If we are lazy attaching the QP then we may need to * hook it up here. Typically, we run this code only for * DAT_PSP_PROVIDER_FLAG */ dat_status = dapls_ib_qp_alloc(cr_ptr->header.owner_ia, ep_ptr, ep_ptr); if (dat_status != DAT_SUCCESS) { /* This is not a great error code, but spec allows */ dapl_os_unlock(&ep_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } } entry_ep_state = ep_ptr->param.ep_state; entry_ep_handle = cr_ptr->param.local_ep_handle; ep_ptr->param.ep_state = DAT_EP_STATE_COMPLETION_PENDING; ep_ptr->cm_handle = cr_ptr->ib_cm_handle; ep_ptr->cr_ptr = cr_ptr; ep_ptr->param.remote_ia_address_ptr = cr_ptr->param. remote_ia_address_ptr; cr_ptr->param.local_ep_handle = ep_handle; /* * private data */ (void) dapl_os_memcpy(prd.private_data, private_data, private_data_size); (void) dapl_os_memzero(prd.private_data + private_data_size, sizeof (DAPL_PRIVATE) - private_data_size); dapl_os_unlock(&ep_ptr->header.lock); dat_status = dapls_ib_accept_connection(cr_handle, ep_handle, &prd); /* * If the provider failed, unwind the damage so we are back at * the initial state. */ if (dat_status != DAT_SUCCESS) { ep_ptr->param.ep_state = entry_ep_state; cr_ptr->param.local_ep_handle = entry_ep_handle; } else { /* * Make this CR invalid. We need to hang on to it until * the connection terminates, but it's destroyed from * the app point of view. */ cr_ptr->header.magic = DAPL_MAGIC_CR_DESTROYED; } bail: return (dat_status); }
DAT_RETURN dapl_evd_dequeue( IN DAT_EVD_HANDLE evd_handle, OUT DAT_EVENT *event) { DAPL_EVD *evd_ptr; DAT_EVENT *local_event; DAT_RETURN dat_status; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_evd_dequeue (%p, %p)\n", evd_handle, event); 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; } if (event == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } /* * We need to dequeue under lock, as the IB OS Access API * restricts us from having multiple threads in CQ poll, and the * DAPL 1.1 API allows multiple threads in dat_evd_dequeue() */ dapl_os_lock(&evd_ptr->header.lock); /* * Make sure there are no other waiters and the evd is active. * Currently this means only the OPEN state is allowed. */ if (evd_ptr->evd_state != DAPL_EVD_STATE_OPEN || evd_ptr->catastrophic_overflow) { dapl_os_unlock(&evd_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); goto bail; } /* * Try the EVD rbuf first; poll from the CQ only if that's empty. * This keeps events in order if dat_evd_wait() has copied events * from CQ to EVD. */ if (evd_ptr->pending_event_queue.head != evd_ptr->pending_event_queue.tail) { local_event = (DAT_EVENT *) dapls_rbuf_remove(&evd_ptr->pending_event_queue); if (local_event != NULL) { *event = *local_event; dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue, local_event); } else { /* should never happen */ dat_status = DAT_ERROR(DAT_INTERNAL_ERROR, 0); } } else if (evd_ptr->ib_cq_handle == IB_INVALID_HANDLE) { dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0); } else if ((evd_ptr->evd_flags & (DAT_EVD_CONNECTION_FLAG | DAT_EVD_CR_FLAG | DAT_EVD_ASYNC_FLAG)) == 0) { /* * No need to drop into kernel, just check the CQ. */ dat_status = dapls_evd_cq_poll_to_event(evd_ptr, event); } else { /* poll for events with threshold and timeout both 0 */ evd_ptr->threshold = 0; dapl_os_unlock(&evd_ptr->header.lock); dat_status = dapls_evd_copy_events(evd_ptr, 0); if (dat_status != DAT_SUCCESS) { dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0); goto bail; } dapl_os_lock(&evd_ptr->header.lock); local_event = (DAT_EVENT *)dapls_rbuf_remove( &evd_ptr->pending_event_queue); if (local_event != NULL) { *event = *local_event; dat_status = dapls_rbuf_add(&evd_ptr->free_event_queue, local_event); } else { /* still didn't find anything */ dat_status = DAT_ERROR(DAT_QUEUE_EMPTY, 0); } } dapl_os_unlock(&evd_ptr->header.lock); bail: dapl_dbg_log(DAPL_DBG_TYPE_RTN, "dapl_evd_dequeue () returns 0x%x\n", dat_status); return (dat_status); }
/* * dapl_rsp_create * * uDAPL: User Direct Access Program Library Version 1.1, 6.4.3.4.1 * * Create a Resereved Service Point with the specified Endpoint * that generates at most one Connection Request that is * delivered to the specified Event Dispatcher in a notification * event * * Input: * ia_handle * conn_qual * ep_handle * evd_handle * * Output: * rsp_handle * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_PARAMETER * DAT_INVALID_STATE * DAT_CONN_QUAL_IN_USE */ DAT_RETURN 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) { DAPL_IA *ia_ptr; DAPL_SP *sp_ptr; DAPL_EVD *evd_ptr; DAPL_EP *ep_ptr; DAT_BOOLEAN sp_found; DAT_RETURN dat_status; dat_status = DAT_SUCCESS; ia_ptr = (DAPL_IA *)ia_handle; dapl_dbg_log(DAPL_DBG_TYPE_CM, ">>> dapl_rsp_free conn_qual: %x EP: %p\n", conn_qual, ep_handle); if (DAPL_BAD_HANDLE(ia_ptr, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } if (rsp_handle == NULL) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5); goto bail; } ep_ptr = (DAPL_EP *) ep_handle; if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED) { dat_status = DAT_ERROR(DAT_INVALID_STATE, dapls_ep_state_subtype(ep_ptr)); goto bail; } evd_ptr = (DAPL_EVD *)evd_handle; if (!(evd_ptr->evd_flags & DAT_EVD_CR_FLAG)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EVD_CR); goto bail; } sp_ptr = dapls_ia_sp_search(ia_ptr, conn_qual, DAT_FALSE); sp_found = DAT_TRUE; if (sp_ptr == NULL) { sp_found = DAT_FALSE; /* Allocate RSP */ sp_ptr = dapls_sp_alloc(ia_ptr, DAT_FALSE); if (sp_ptr == NULL) { dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES, DAT_RESOURCE_MEMORY); goto bail; } } /* * Fill out the RSP args */ sp_ptr->ia_handle = ia_handle; sp_ptr->conn_qual = conn_qual; sp_ptr->evd_handle = evd_handle; sp_ptr->psp_flags = 0; sp_ptr->ep_handle = ep_handle; /* * Take a reference on the EVD handle */ (void) dapl_os_atomic_inc(&((DAPL_EVD *)evd_handle)->evd_ref_count); /* * Update the EP state indicating the provider now owns it */ ep_ptr->param.ep_state = DAT_EP_STATE_RESERVED; /* * Set up a listener for a connection. Connections can arrive * even before this call returns! */ sp_ptr->state = DAPL_SP_STATE_RSP_LISTENING; sp_ptr->listening = DAT_TRUE; if (sp_found == DAT_FALSE) { /* Link it onto the IA */ dapl_ia_link_rsp(ia_ptr, sp_ptr); dat_status = dapls_ib_setup_conn_listener(ia_ptr, conn_qual, sp_ptr); if (dat_status != DAT_SUCCESS) { /* * Have a problem setting up the connection, something * wrong! * rsp_free will decrement the EVD refcount. Set * listening to * false to avoid tearing down the * conn_listener which didn't * get set up. */ sp_ptr->listening = DAT_FALSE; (void) dapl_rsp_free((DAT_RSP_HANDLE) sp_ptr); dapl_dbg_log(DAPL_DBG_TYPE_CM, "--> dapl_rsp_create setup_conn_listener failed: " "%x\n", dat_status); goto bail; } } /* * Return handle to the user */ *rsp_handle = (DAT_RSP_HANDLE)sp_ptr; bail: return (dat_status); }
/* * dapl_ep_free * * DAPL Requirements Version xxx, 6.5.3 * * Destroy an instance of the Endpoint * * Input: * ep_handle * * Output: * none * * Returns: * DAT_SUCCESS * DAT_INVALID_PARAMETER * DAT_INVALID_STATE */ DAT_RETURN dapl_ep_free( IN DAT_EP_HANDLE ep_handle) { DAPL_EP *ep_ptr; DAPL_IA *ia_ptr; DAT_EP_PARAM *param; DAT_RETURN dat_status = DAT_SUCCESS; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_ep_free (%p)\n", ep_handle); ep_ptr = (DAPL_EP *) ep_handle; param = &ep_ptr->param; /* * Verify parameter & state */ if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP) && !(ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT && ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP); goto bail; } if (ep_ptr->param.ep_state == DAT_EP_STATE_RESERVED || ep_ptr->param.ep_state == DAT_EP_STATE_PASSIVE_CONNECTION_PENDING || ep_ptr->param.ep_state == DAT_EP_STATE_TENTATIVE_CONNECTION_PENDING) { dapl_dbg_log(DAPL_DBG_TYPE_WARN, "--> dapl_ep_free: invalid state: %x, ep %p\n", ep_ptr->param.ep_state, ep_ptr); dat_status = DAT_ERROR(DAT_INVALID_STATE, dapls_ep_state_subtype(ep_ptr)); goto bail; } ia_ptr = ep_ptr->header.owner_ia; /* * If we are connected, issue a disconnect. If we are in the * disconnect_pending state, disconnect with the ABRUPT flag * set. */ /* * Do verification of parameters and the state change atomically. */ 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_COMPLETION_PENDING || ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECT_PENDING) { /* * Issue the disconnect and return. The DISCONNECT callback * will invoke this routine and finish the job */ ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING; dapl_os_unlock(&ep_ptr->header.lock); dapl_dbg_log(DAPL_DBG_TYPE_EP, "--> dapl_ep_free: disconnecting EP: %x, ep %p\n", ep_ptr->param.ep_state, ep_ptr); dat_status = dapls_ib_disconnect(ep_ptr, DAT_CLOSE_ABRUPT_FLAG); ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECT_PENDING; ep_ptr->header.magic = DAPL_MAGIC_EP_EXIT; } else { dapl_os_unlock(&ep_ptr->header.lock); } /* * Release all reference counts and unlink this structure. If we * got here from a callback, don't repeat this step */ if (!(ep_ptr->header.magic == DAPL_MAGIC_EP_EXIT && ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED)) { /* Remove link from the IA */ dapl_ia_unlink_ep(ia_ptr, ep_ptr); } /* * If the EP is disconnected tear everything down. Otherwise, * disconnect the EP but leave the QP and basic EP structure * intact; the callback code will finish the job. */ dapl_os_lock(&ep_ptr->header.lock); if (ep_ptr->param.ep_state == DAT_EP_STATE_DISCONNECTED || ep_ptr->param.ep_state == DAT_EP_STATE_UNCONNECTED) { /* * Update ref counts. Note the user may have used ep_modify * to set handles to NULL. */ if (param->pz_handle != NULL) { dapl_os_atomic_dec(&((DAPL_PZ *) param->pz_handle)->pz_ref_count); param->pz_handle = NULL; } if (param->recv_evd_handle != NULL) { dapl_os_atomic_dec(&((DAPL_EVD *) param->recv_evd_handle)->evd_ref_count); param->recv_evd_handle = NULL; } if (param->request_evd_handle != NULL) { dapl_os_atomic_dec(&((DAPL_EVD *) param->request_evd_handle)->evd_ref_count); param->request_evd_handle = NULL; } if (param->connect_evd_handle != NULL) { dapl_os_atomic_dec(&((DAPL_EVD *) param->connect_evd_handle)->evd_ref_count); param->connect_evd_handle = NULL; } if (param->srq_handle != NULL) { dapl_os_atomic_dec(&((DAPL_SRQ *) param->srq_handle)->srq_ref_count); param->srq_handle = NULL; } dapl_dbg_log(DAPL_DBG_TYPE_EP, "--> dapl_ep_free: Free EP: %x, ep %p\n", ep_ptr->param.ep_state, ep_ptr); /* * Free the QP. If the EP has never been used, * the QP is invalid */ if (ep_ptr->qp_handle != IB_INVALID_HANDLE) { dat_status = dapls_ib_qp_free(ia_ptr, ep_ptr); /* * This should always succeed, but report to the user if * there is a problem */ if (dat_status != DAT_SUCCESS) { goto bail; } ep_ptr->qp_handle = IB_INVALID_HANDLE; } dapl_os_unlock(&ep_ptr->header.lock); /* Free the resource */ dapl_ep_dealloc(ep_ptr); } else { dapl_os_unlock(&ep_ptr->header.lock); } bail: return (dat_status); }
/* * dapl_lmr_create * * Register a memory region with an Interface Adaptor. * * Input: * ia_handle * mem_type * region_description * length * pz_handle * privileges * * Output: * lmr_handle * lmr_context * registered_length * registered_address * * Returns: * DAT_SUCCESS * DAT_INSUFFICIENT_RESOURCES * DAT_INVALID_PARAMETER * DAT_INVALID_HANDLE * DAT_INVALID_STATE * DAT_MODEL_NOT_SUPPORTED * */ 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) { DAPL_IA *ia; DAPL_PZ *pz; DAT_RETURN dat_status; if (DAPL_BAD_HANDLE(ia_handle, DAPL_MAGIC_IA)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_IA); goto bail; } if (DAPL_BAD_HANDLE(pz_handle, DAPL_MAGIC_PZ)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_PZ); goto bail; } if (NULL == lmr_handle) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG7); goto bail; } ia = (DAPL_IA *) ia_handle; pz = (DAPL_PZ *) pz_handle; DAPL_CNTR(ia, DCNT_IA_LMR_CREATE); switch (mem_type) { case DAT_MEM_TYPE_VIRTUAL: { dat_status = dapli_lmr_create_virtual(ia, region_description.for_va, length, pz, privileges, va_type, lmr_handle, lmr_context, rmr_context, registered_length, registered_address); break; } case DAT_MEM_TYPE_LMR: { DAPL_LMR *lmr; if (DAPL_BAD_HANDLE (region_description.for_lmr_handle, DAPL_MAGIC_LMR)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_LMR); goto bail; } lmr = (DAPL_LMR *) region_description.for_lmr_handle; dat_status = dapli_lmr_create_lmr(ia, lmr, pz, privileges, va_type, lmr_handle, lmr_context, rmr_context, registered_length, registered_address); break; } case DAT_MEM_TYPE_SHARED_VIRTUAL: { #if (VN_MEM_SHARED_VIRTUAL_SUPPORT > 0) dat_status = dapli_lmr_create_shared(ia, region_description, length, pz, privileges, va_type, lmr_handle, lmr_context, rmr_context, registered_length, registered_address); #else dat_status = DAT_ERROR(DAT_NOT_IMPLEMENTED, DAT_NO_SUBTYPE); #endif break; } default: { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); break; } } bail: return dat_status; }
/* * dapl_cno_wait * * DAPL Requirements Version xxx, 6.3.2.3 * * Wait for a consumer notification event * * Input: * cno_handle * timeout * evd_handle * * Output: * evd_handle * * Returns: * DAT_SUCCESS * DAT_INVALID_HANDLE * DAT_QUEUE_EMPTY * DAT_INVALID_PARAMETER */ DAT_RETURN DAT_API dapl_cno_wait(IN DAT_CNO_HANDLE cno_handle, /* cno_handle */ IN DAT_TIMEOUT timeout, /* agent */ OUT DAT_EVD_HANDLE * evd_handle) { /* ia_handle */ DAPL_CNO *cno_ptr; DAT_RETURN dat_status; if (DAPL_BAD_HANDLE(cno_handle, DAPL_MAGIC_CNO)) { dat_status = DAT_INVALID_HANDLE | DAT_INVALID_HANDLE_CNO; goto bail; } dat_status = DAT_SUCCESS; cno_ptr = (DAPL_CNO *) cno_handle; if (cno_ptr->cno_state == DAPL_CNO_STATE_DEAD) { dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_CNO_DEAD); goto bail; } dapl_os_lock(&cno_ptr->header.lock); if (cno_ptr->cno_state == DAPL_CNO_STATE_TRIGGERED) { cno_ptr->cno_state = DAPL_CNO_STATE_UNTRIGGERED; *evd_handle = cno_ptr->cno_evd_triggered; cno_ptr->cno_evd_triggered = NULL; dapl_os_unlock(&cno_ptr->header.lock); goto bail; } while (cno_ptr->cno_state == DAPL_CNO_STATE_UNTRIGGERED && DAT_GET_TYPE(dat_status) != DAT_TIMEOUT_EXPIRED) { cno_ptr->cno_waiters++; dapl_os_unlock(&cno_ptr->header.lock); dat_status = dapl_os_wait_object_wait(&cno_ptr->cno_wait_object, timeout); dapl_os_lock(&cno_ptr->header.lock); cno_ptr->cno_waiters--; } if (cno_ptr->cno_state == DAPL_CNO_STATE_DEAD) { dat_status = DAT_ERROR(DAT_INVALID_STATE, DAT_INVALID_STATE_CNO_DEAD); } else if (dat_status == DAT_SUCCESS) { /* * After the first triggering, this will be a valid handle. * If we're racing with wakeups of other CNO waiters, * that's ok. */ dapl_os_assert(cno_ptr->cno_state == DAPL_CNO_STATE_TRIGGERED); cno_ptr->cno_state = DAPL_CNO_STATE_UNTRIGGERED; *evd_handle = cno_ptr->cno_evd_triggered; cno_ptr->cno_evd_triggered = NULL; } else if (DAT_GET_TYPE(dat_status) == DAT_TIMEOUT_EXPIRED) { cno_ptr->cno_state = DAPL_CNO_STATE_UNTRIGGERED; *evd_handle = NULL; dat_status = DAT_QUEUE_EMPTY; } else { /* * The only other reason we could have made it out of * the loop is an interrupted system call. */ dapl_os_assert(DAT_GET_TYPE(dat_status) == DAT_INTERRUPTED_CALL); } dapl_os_unlock(&cno_ptr->header.lock); bail: return dat_status; }
DAT_RETURN dapli_post_ext(IN DAT_EP_HANDLE ep_handle, IN DAT_UINT64 cmp_add, IN DAT_UINT64 swap, IN DAT_UINT32 immed_data, IN DAT_COUNT segments, IN DAT_LMR_TRIPLET * local_iov, IN DAT_DTO_COOKIE user_cookie, IN const DAT_RMR_TRIPLET * remote_iov, IN int op_type, IN DAT_COMPLETION_FLAGS flags, IN DAT_IB_ADDR_HANDLE * ah) { DAPL_EP *ep_ptr; ib_qp_handle_t qp_ptr; DAPL_COOKIE *cookie = NULL; DAT_RETURN dat_status = DAT_SUCCESS; dapl_dbg_log(DAPL_DBG_TYPE_API, " post_ext_op: ep %p cmp_val %d " "swap_val %d cookie 0x%x, r_iov %p, flags 0x%x, ah %p\n", ep_handle, (unsigned)cmp_add, (unsigned)swap, (unsigned)user_cookie.as_64, remote_iov, flags, ah); if (DAPL_BAD_HANDLE(ep_handle, DAPL_MAGIC_EP)) return (DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE_EP)); ep_ptr = (DAPL_EP *) ep_handle; qp_ptr = ep_ptr->qp_handle; /* * Synchronization ok since this buffer is only used for send * requests, which aren't allowed to race with each other. */ dat_status = dapls_dto_cookie_alloc(&ep_ptr->req_buffer, DAPL_DTO_TYPE_EXTENSION, user_cookie, &cookie); if (dat_status != DAT_SUCCESS) goto bail; /* * Take reference before posting to avoid race conditions with * completions */ dapl_os_atomic_inc(&ep_ptr->req_count); /* * Invoke provider specific routine to post DTO */ dat_status = dapls_ib_post_ext_send(ep_ptr, op_type, cookie, segments, /* data segments */ local_iov, remote_iov, immed_data, /* immed data */ cmp_add, /* compare or add */ swap, /* swap */ flags, ah); if (dat_status != DAT_SUCCESS) { dapl_os_atomic_dec(&ep_ptr->req_count); dapls_cookie_dealloc(&ep_ptr->req_buffer, cookie); } bail: return dat_status; }
DAT_RETURN DAT_API dapl_evd_resize(IN DAT_EVD_HANDLE evd_handle, IN DAT_COUNT evd_qlen) { DAPL_IA *ia_ptr; DAPL_EVD *evd_ptr; DAT_COUNT pend_cnt; DAT_RETURN dat_status; dapl_dbg_log(DAPL_DBG_TYPE_API, "dapl_evd_resize (%p, %d)\n", evd_handle, evd_qlen); if (DAPL_BAD_HANDLE(evd_handle, DAPL_MAGIC_EVD)) { dat_status = DAT_ERROR(DAT_INVALID_HANDLE, DAT_INVALID_HANDLE1); goto bail; } evd_ptr = (DAPL_EVD *) evd_handle; ia_ptr = evd_ptr->header.owner_ia; if (evd_qlen == evd_ptr->qlen) { dat_status = DAT_SUCCESS; goto bail; } if (evd_qlen > ia_ptr->hca_ptr->ia_attr.max_evd_qlen) { dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG2); goto bail; } dapl_os_lock(&evd_ptr->header.lock); /* Don't try to resize if we are actively waiting */ if (evd_ptr->evd_state == DAPL_EVD_STATE_WAITED) { dapl_os_unlock(&evd_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); goto bail; } pend_cnt = dapls_rbuf_count(&evd_ptr->pending_event_queue); if (pend_cnt > evd_qlen) { dapl_os_unlock(&evd_ptr->header.lock); dat_status = DAT_ERROR(DAT_INVALID_STATE, 0); goto bail; } if (evd_ptr->ib_cq_handle) { dat_status = dapls_ib_cq_resize(evd_ptr->header.owner_ia, evd_ptr, &evd_qlen); if (dat_status != DAT_SUCCESS) { dapl_os_unlock(&evd_ptr->header.lock); goto bail; } } dat_status = dapls_evd_event_realloc(evd_ptr, evd_qlen); if (dat_status != DAT_SUCCESS) { dapl_os_unlock(&evd_ptr->header.lock); goto bail; } dapl_os_unlock(&evd_ptr->header.lock); bail: return dat_status; }