static inline int mca_btl_ugni_progress_rdma (mca_btl_ugni_module_t *ugni_module) { ompi_common_ugni_post_desc_t *desc; mca_btl_ugni_base_frag_t *frag; gni_cq_entry_t event_data = 0; uint32_t recoverable = 1; gni_return_t rc; rc = GNI_CqGetEvent (ugni_module->rdma_local_cq, &event_data); if (GNI_RC_NOT_DONE == rc) { return 0; } if (OPAL_UNLIKELY((GNI_RC_SUCCESS != rc && !event_data) || GNI_CQ_OVERRUN(event_data))) { /* TODO -- need to handle overrun -- how do we do this without an event? will the event eventually come back? Ask Cray */ BTL_ERROR(("unhandled post error! ugni rc = %d", rc)); assert (0); return ompi_common_rc_ugni_to_ompi (rc); } rc = GNI_GetCompleted (ugni_module->rdma_local_cq, event_data, (gni_post_descriptor_t **) &desc); if (OPAL_UNLIKELY(GNI_RC_SUCCESS != rc && GNI_RC_TRANSACTION_ERROR != rc)) { BTL_ERROR(("Error in GNI_GetComplete %s", gni_err_str[rc])); return ompi_common_rc_ugni_to_ompi (rc); } frag = MCA_BTL_UGNI_DESC_TO_FRAG(desc); if (OPAL_UNLIKELY(GNI_RC_SUCCESS != rc || !GNI_CQ_STATUS_OK(event_data))) { (void) GNI_CqErrorRecoverable (event_data, &recoverable); if (OPAL_UNLIKELY(++frag->post_desc.tries >= mca_btl_ugni_component.rdma_max_retries || !recoverable)) { /* give up */ BTL_ERROR(("giving up on frag %p", (void *) frag)); frag->cbfunc (frag, OMPI_ERROR); return OMPI_ERROR; } /* repost transaction */ mca_btl_ugni_repost (frag, OMPI_SUCCESS); return 0; } BTL_VERBOSE(("RDMA/FMA complete for frag %p", (void *) frag)); frag->cbfunc (frag, ompi_common_rc_ugni_to_ompi (rc)); return 1; }
static inline int mca_btl_ugni_directed_ep_post (mca_btl_base_endpoint_t *ep) { gni_return_t rc; rc = GNI_EpPostDataWId (ep->smsg_ep_handle, &ep->mailbox->smsg_attrib, sizeof (ep->mailbox->smsg_attrib), &ep->remote_smsg_attrib, sizeof (ep->remote_smsg_attrib), MCA_BTL_UGNI_CONNECT_DIRECTED_ID | ep->common->ep_rem_id); return ompi_common_rc_ugni_to_ompi (rc); }
static inline int mca_btl_ugni_progress_datagram (mca_btl_ugni_module_t *ugni_module) { uint32_t remote_addr, remote_id; mca_btl_base_endpoint_t *ep; gni_post_state_t post_state; gni_ep_handle_t handle; uint64_t datagram_id; gni_return_t grc; int count = 0; /* check for datagram completion */ grc = GNI_PostDataProbeById (ugni_module->device->dev_handle, &datagram_id); if (OPAL_LIKELY(GNI_RC_SUCCESS != grc)) { return 0; } if ((datagram_id & MCA_BTL_UGNI_DATAGRAM_MASK) == MCA_BTL_UGNI_CONNECT_WILDCARD_ID) { handle = ugni_module->wildcard_ep; } else { handle = ugni_module->endpoints[(uint32_t)(datagram_id & 0xffffffffull)]->smsg_ep_handle; } /* wait for the incoming datagram to complete (in case it isn't) */ grc = GNI_EpPostDataWaitById (handle, datagram_id, -1, &post_state, &remote_addr, &remote_id); if (GNI_RC_SUCCESS != grc) { BTL_ERROR(("GNI_EpPostDataWaitById failed with rc = %d", grc)); return ompi_common_rc_ugni_to_ompi (grc); } BTL_VERBOSE(("got a datagram completion: id = %" PRIx64 ", state = %d, " "peer = %d", datagram_id, post_state, remote_id)); ep = ugni_module->endpoints[remote_id]; /* NTH: TODO -- error handling */ (void) mca_btl_ugni_ep_connect_progress (ep); if (MCA_BTL_UGNI_EP_STATE_CONNECTED == ep->state) { /* process messages waiting in the endpoint's smsg mailbox */ count = mca_btl_ugni_smsg_process (ep); } /* repost the wildcard datagram */ if ((datagram_id & MCA_BTL_UGNI_DATAGRAM_MASK) == MCA_BTL_UGNI_CONNECT_WILDCARD_ID) { mca_btl_ugni_wildcard_ep_post (ugni_module); } return count; }
int mca_btl_ugni_smsg_init (mca_btl_ugni_module_t *ugni_module) { gni_return_t rc; rc = GNI_SmsgSetMaxRetrans (ugni_module->device->dev_handle, mca_btl_ugni_component.smsg_max_retries); if (GNI_RC_SUCCESS != rc) { BTL_ERROR(("error setting maximum SMSG retries")); return ompi_common_rc_ugni_to_ompi (rc); } return OMPI_SUCCESS; }
int mca_btl_ugni_module_init (mca_btl_ugni_module_t *ugni_module, ompi_common_ugni_device_t *dev) { int rc; BTL_VERBOSE(("binding module %p to device %p", (void *) ugni_module, (void *) dev)); /* copy module defaults (and function pointers) */ memmove (ugni_module, &mca_btl_ugni_module, sizeof (mca_btl_ugni_module)); ugni_module->initialized = false; ugni_module->nlocal_procs = 0; ugni_module->active_send_count = 0; OBJ_CONSTRUCT(&ugni_module->failed_frags, opal_list_t); OBJ_CONSTRUCT(&ugni_module->eager_frags_send, ompi_free_list_t); OBJ_CONSTRUCT(&ugni_module->eager_frags_recv, ompi_free_list_t); OBJ_CONSTRUCT(&ugni_module->smsg_frags, ompi_free_list_t); OBJ_CONSTRUCT(&ugni_module->rdma_frags, ompi_free_list_t); OBJ_CONSTRUCT(&ugni_module->rdma_int_frags, ompi_free_list_t); OBJ_CONSTRUCT(&ugni_module->pending_smsg_frags_bb, opal_pointer_array_t); OBJ_CONSTRUCT(&ugni_module->ep_wait_list, opal_list_t); OBJ_CONSTRUCT(&ugni_module->endpoints, opal_pointer_array_t); OBJ_CONSTRUCT(&ugni_module->id_to_endpoint, opal_hash_table_t); ugni_module->device = dev; dev->btl_ctx = (void *) ugni_module; /* create wildcard endpoint to listen for connections. * there is no need to bind this endpoint. */ rc = GNI_EpCreate (ugni_module->device->dev_handle, NULL, &ugni_module->wildcard_ep); if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) { BTL_ERROR(("error creating wildcard ugni endpoint")); return ompi_common_rc_ugni_to_ompi (rc); } /* post wildcard datagram */ rc = mca_btl_ugni_wildcard_ep_post (ugni_module); if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) { BTL_ERROR(("error posting wildcard datagram")); return rc; } return OMPI_SUCCESS; }
int mca_btl_ugni_progress_remote_smsg (mca_btl_ugni_module_t *btl) { mca_btl_base_endpoint_t *ep; gni_cq_entry_t event_data; gni_return_t grc; uint64_t inst_id; grc = GNI_CqGetEvent (btl->smsg_remote_cq, &event_data); if (GNI_RC_NOT_DONE == grc) { return 0; } if (OPAL_UNLIKELY(GNI_RC_SUCCESS != grc || !GNI_CQ_STATUS_OK(event_data) || GNI_CQ_OVERRUN(event_data))) { if (GNI_RC_ERROR_RESOURCE == grc || (GNI_RC_SUCCESS == grc && GNI_CQ_OVERRUN(event_data))) { /* recover from smsg cq overrun */ return mca_btl_ugni_handle_remote_smsg_overrun (btl); } BTL_ERROR(("unhandled error in GNI_CqGetEvent")); /* unhandled error: crash */ assert (0); return ompi_common_rc_ugni_to_ompi (grc); } BTL_VERBOSE(("REMOTE CQ: Got event 0x%" PRIx64 ". msg id = %" PRIu64 ". ok = %d, type = %" PRIu64 "\n", (uint64_t) event_data, GNI_CQ_GET_MSG_ID(event_data), GNI_CQ_STATUS_OK(event_data), GNI_CQ_GET_TYPE(event_data))); inst_id = GNI_CQ_GET_INST_ID(event_data); ep = btl->endpoints[inst_id & 0xffffffff]; if (OPAL_UNLIKELY(MCA_BTL_UGNI_EP_STATE_CONNECTED != ep->state)) { /* due to the nature of datagrams we may get a smsg completion before we get mailbox info from the peer */ BTL_VERBOSE(("event occurred on an unconnected endpoint! ep state = %d", ep->state)); return 0; } return mca_btl_ugni_smsg_process (ep); }
static int mca_btl_ugni_smsg_setup (void) { gni_smsg_attr_t tmp_smsg_attrib; unsigned int mbox_size; size_t nprocs; gni_return_t rc; (void) ompi_proc_world (&nprocs); if (0 == mca_btl_ugni_component.ugni_smsg_limit) { /* auto-set the smsg limit based on the number of ranks */ if (nprocs <= 512) { mca_btl_ugni_component.ugni_smsg_limit = 8192; } else if (nprocs <= 1024) { mca_btl_ugni_component.ugni_smsg_limit = 2048; } else if (nprocs <= 8192) { mca_btl_ugni_component.ugni_smsg_limit = 1024; } else if (nprocs <= 16384) { mca_btl_ugni_component.ugni_smsg_limit = 512; } else { mca_btl_ugni_component.ugni_smsg_limit = 256; } } mca_btl_ugni_component.smsg_max_data = mca_btl_ugni_component.ugni_smsg_limit - sizeof (mca_btl_ugni_send_frag_hdr_t); /* calculate mailbox size */ tmp_smsg_attrib.msg_type = GNI_SMSG_TYPE_MBOX_AUTO_RETRANSMIT; tmp_smsg_attrib.msg_maxsize = mca_btl_ugni_component.ugni_smsg_limit; tmp_smsg_attrib.mbox_maxcredit = mca_btl_ugni_component.smsg_max_credits; rc = GNI_SmsgBufferSizeNeeded (&tmp_smsg_attrib, &mbox_size); if (OPAL_UNLIKELY(GNI_RC_SUCCESS != rc)) { BTL_ERROR(("error in GNI_SmsgBufferSizeNeeded")); return ompi_common_rc_ugni_to_ompi (rc); } mca_btl_ugni_component.smsg_mbox_size = OPAL_ALIGN(mbox_size, 64, unsigned int); return OMPI_SUCCESS; }
static inline int mca_btl_ugni_ep_connect_finish (mca_btl_base_endpoint_t *ep) { gni_return_t grc; int rc; BTL_VERBOSE(("finishing connection. remote attributes: msg_type = %d, msg_buffer = %p, buff_size = %d, " "mem_hndl = {qword1 = %" PRIu64 ", qword2 = %" PRIu64 "}, mbox = %d, mbox_maxcredit = %d, " "msg_maxsize = %d", ep->remote_smsg_attrib.msg_type, ep->remote_smsg_attrib.msg_buffer, ep->remote_smsg_attrib.buff_size, ep->remote_smsg_attrib.mem_hndl.qword1, ep->remote_smsg_attrib.mem_hndl.qword2, ep->remote_smsg_attrib.mbox_offset, ep->remote_smsg_attrib.mbox_maxcredit, ep->remote_smsg_attrib.msg_maxsize)); BTL_VERBOSE(("finishing connection. local attributes: msg_type = %d, msg_buffer = %p, buff_size = %d, " "mem_hndl = {qword1 = %" PRIu64 ", qword2 = %" PRIu64 "}, mbox = %d, mbox_maxcredit = %d, " "msg_maxsize = %d", ep->mailbox->smsg_attrib.msg_type, ep->mailbox->smsg_attrib.msg_buffer, ep->mailbox->smsg_attrib.buff_size, ep->mailbox->smsg_attrib.mem_hndl.qword1, ep->mailbox->smsg_attrib.mem_hndl.qword2, ep->mailbox->smsg_attrib.mbox_offset, ep->mailbox->smsg_attrib.mbox_maxcredit, ep->mailbox->smsg_attrib.msg_maxsize)); grc = GNI_SmsgInit (ep->smsg_ep_handle, &ep->mailbox->smsg_attrib, &ep->remote_smsg_attrib); if (OPAL_UNLIKELY(GNI_RC_SUCCESS != grc)) { BTL_ERROR(("error initializing SMSG protocol. rc = %d", grc)); return ompi_common_rc_ugni_to_ompi (grc); } ep->state = MCA_BTL_UGNI_EP_STATE_CONNECTED; /* send all pending messages */ BTL_VERBOSE(("endpoint connected. posting %u sends", (unsigned int) opal_list_get_size (&ep->frag_wait_list))); rc = mca_btl_progress_send_wait_list (ep); if (OPAL_UNLIKELY(OMPI_SUCCESS != rc)) { ep->wait_listed = true; opal_list_append (&ep->btl->ep_wait_list, &ep->super); } return OMPI_SUCCESS; }
static inline int mca_btl_ugni_progress_datagram (mca_btl_ugni_module_t *ugni_module) { uint32_t remote_addr, remote_id; uint64_t datagram_id, data; mca_btl_base_endpoint_t *ep; gni_post_state_t post_state; gni_ep_handle_t handle; gni_return_t grc; int count = 0, rc; /* check for datagram completion */ grc = GNI_PostDataProbeById (ugni_module->device->dev_handle, &datagram_id); if (OPAL_LIKELY(GNI_RC_SUCCESS != grc)) { return 0; } data = datagram_id & ~(MCA_BTL_UGNI_DATAGRAM_MASK); BTL_VERBOSE(("datgram_id: %" PRIx64 ", mask: %" PRIx64, datagram_id, (uint64_t) (datagram_id & MCA_BTL_UGNI_DATAGRAM_MASK))); if ((datagram_id & MCA_BTL_UGNI_DATAGRAM_MASK) == MCA_BTL_UGNI_CONNECT_DIRECTED_ID) { ep = (mca_btl_base_endpoint_t *) opal_pointer_array_get_item (&ugni_module->endpoints, data); handle = ep->smsg_ep_handle; } else { handle = ugni_module->wildcard_ep; } /* wait for the incoming datagram to complete (in case it isn't) */ grc = GNI_EpPostDataWaitById (handle, datagram_id, -1, &post_state, &remote_addr, &remote_id); if (GNI_RC_SUCCESS != grc) { BTL_ERROR(("GNI_EpPostDataWaitById failed with rc = %d", grc)); return ompi_common_rc_ugni_to_ompi (grc); } /* if this is a wildcard endpoint lookup the remote peer by the proc id we received */ if (handle == ugni_module->wildcard_ep) { BTL_VERBOSE(("received connection attempt on wildcard endpoint from proc id: %" PRIx64, ugni_module->wc_remote_attr.proc_id)); rc = opal_hash_table_get_value_uint64 (&ugni_module->id_to_endpoint, ugni_module->wc_remote_attr.proc_id, (void *) &ep); /* check if the endpoint is known */ if (OPAL_UNLIKELY(OPAL_SUCCESS != rc || NULL == ep)) { BTL_ERROR(("received connection attempt from an unknown peer. rc: %d, ep: %p, id: 0x%" PRIx64, rc, ep, ugni_module->wc_remote_attr.proc_id)); return OMPI_ERR_NOT_FOUND; } } else { BTL_VERBOSE(("directed datagram complete for endpoint %p", ep)); } /* should not have gotten a NULL endpoint */ assert (NULL != ep); BTL_VERBOSE(("got a datagram completion: id = %" PRIx64 ", state = %d, " "data = 0x%" PRIx64 ", ep = %p, remote id: %d", datagram_id, post_state, data, ep, remote_id)); /* NTH: TODO -- error handling */ (void) mca_btl_ugni_ep_connect_progress (ep); if (MCA_BTL_UGNI_EP_STATE_CONNECTED == ep->state) { /* process messages waiting in the endpoint's smsg mailbox */ count = mca_btl_ugni_smsg_process (ep); } /* repost the wildcard datagram */ if (handle == ugni_module->wildcard_ep) { mca_btl_ugni_wildcard_ep_post (ugni_module); } return count; }