static VAPI_ret_t psib_check_cq(hca_info_t *hca_info) { VAPI_wc_desc_t comp_desc; VAPI_ret_t rc; rc = VAPI_poll_cq(hca_info->hca_hndl, hca_info->cq_hndl, &comp_desc); if (rc == VAPI_OK) { if (comp_desc.opcode == VAPI_CQE_RQ_SEND_DATA) { /* receive something */ con_info_t *con = (con_info_t *)(unsigned long)comp_desc.id; // printf("Recv done... recv: %d tosend: %d send: %d\n", // con->n_recv_toks, con->n_tosend_toks, con->n_send_toks); if (comp_desc.status == VAPI_SUCCESS) { psib_msg_t *msg; msg = ((psib_msg_t *)con->recv_bufs.ptr) + ((con->recv_pos + con->n_recv_toks) % SIZE_SR_QUEUE); /* Fresh tokens ? */ con->n_send_toks += msg->header.token; // /* ToDo: Maybe disable the next 4 lines ? */ // if ((con->n_recv_toks == 0) && (msg->header.payload == 0)) { // /* no payload. skip packet. */ // psib_recvdone(con); // } con->n_recv_toks++; } else { if (psib_debug > 0) { printf("Failed receive request (status %d). Connection broken!\n", comp_desc.status); } con->con_broken = 1; } } else if (comp_desc.opcode == VAPI_CQE_SQ_SEND_DATA) { /* Send done */ con_info_t *con = (con_info_t *)(unsigned long)comp_desc.id; if (comp_desc.status == VAPI_SUCCESS) { // printf("Send done... recv: %d tosend: %d send: %d\n", // con->n_recv_toks, con->n_tosend_toks, con->n_send_toks); } else { if (psib_debug > 0) { printf("Failed send request (status %d). Connection broken!\n", comp_desc.status); } con->con_broken = 1; } } else { printf("Unknown Opcode: %d\n", comp_desc.opcode); } } return rc; }
VAPI_ret_t osmt_mtl_mad_poll4cqe(VAPI_hca_hndl_t hca, VAPI_cq_hndl_t cq, VAPI_wc_desc_t * wc_desc_p, u_int32_t max_poll, u_int32_t poll_sleep, VAPI_ud_av_hndl_t * avh_p) { VAPI_ret_t ret = VAPI_CQ_EMPTY; u_int32_t poll_cnt = 0; /* wait for something to arrive */ while ((ret == VAPI_CQ_EMPTY) && (poll_cnt < max_poll)) { ret = VAPI_poll_cq(hca, cq, wc_desc_p); /* don't sleep if we already succeeded) */ if (ret != VAPI_CQ_EMPTY) { break; } usleep(poll_sleep); poll_cnt++; } /* if passed an AVH to destory - do it */ if (avh_p != NULL) { VAPI_destroy_addr_hndl(hca, *avh_p); } if ((poll_cnt == max_poll) && (ret == VAPI_CQ_EMPTY)) { MTL_DEBUG1(__FUNCTION__ ": Failed to get completion on wq after %d polls.\n", max_poll); return VAPI_CQ_EMPTY; } if (ret != VAPI_OK) { MTL_DEBUG1(__FUNCTION__ ": VAPI_poll_cq failed with ret=%s on sq_cq\n", mtl_strerror_sym(ret)); return ret; } if (wc_desc_p->status != VAPI_SUCCESS) { MTL_DEBUG1(__FUNCTION__ ": completion error (%d) detected\n", wc_desc_p->status); } return VAPI_OK; }
void event_handler(VAPI_hca_hndl_t hca, VAPI_cq_hndl_t cq, void* data) { VAPI_ret_t ret; while(1) { ret = VAPI_poll_cq(hca, cq, &wc); if(ret == VAPI_CQ_EMPTY) { LOGPRINTF("Empty completion queue, requesting next notification\n"); VAPI_req_comp_notif(hca_hndl, r_cq_hndl, VAPI_NEXT_COMP); return; } else if(ret != VAPI_OK) { fprintf(stderr, "Error in event_handler, polling cq: %s\n", VAPI_strerror(ret)); exit(-1); } else if(wc.status != VAPI_SUCCESS) { fprintf(stderr, "Error in event_handler, on returned work completion " "status: %s\n", VAPI_wc_status_sym(wc.status)); exit(-1); } LOGPRINTF("Retrieved work completion\n"); /* For ping-pong mode at least, this check shouldn't be needed for * normal operation, but it will help catch any bugs with multiple * sends coming through when we're only expecting one. */ if(receive_complete == 1) { while(receive_complete != 0) sched_yield(); } receive_complete = 1; } }
/* Reset is used after a trial to empty the work request queues so we have enough room for the next trial to run */ void Reset(ArgStruct *p) { VAPI_ret_t ret; /* Return code */ VAPI_sr_desc_t sr; /* Send request */ VAPI_rr_desc_t rr; /* Recv request */ /* If comptype is event, then we'll use event handler to detect receive, * so initialize receive_complete flag */ if(p->prot.comptype == NP_COMP_EVENT) receive_complete = 0; /* Prepost receive */ rr.opcode = VAPI_RECEIVE; rr.comp_type = VAPI_SIGNALED; rr.sg_lst_len = 0; LOGPRINTF("Posting recv request in Reset\n"); ret = VAPI_post_rr(hca_hndl, qp_hndl, &rr); if(ret != VAPI_OK) { fprintf(stderr, " Error posting recv request: %s\n", VAPI_strerror(ret)); CleanUp(p); exit(-1); } /* Make sure both nodes have preposted receives */ Sync(p); /* Post Send */ sr.opcode = VAPI_SEND; sr.comp_type = VAPI_SIGNALED; sr.set_se = FALSE; /* This needed due to a bug in Mellanox HW rel a-0 */ sr.sg_lst_len = 0; LOGPRINTF("Posting send request \n"); ret = VAPI_post_sr(hca_hndl, qp_hndl, &sr); if(ret != VAPI_OK) { fprintf(stderr, " Error posting send request in Reset: %s\n", VAPI_strerror(ret)); exit(-1); } if(wc.status != VAPI_SUCCESS) { fprintf(stderr, " Error in completion status: %s\n", VAPI_wc_status_sym(wc.status)); exit(-1); } LOGPRINTF("Polling for completion of send request\n"); ret = VAPI_CQ_EMPTY; while(ret == VAPI_CQ_EMPTY) ret = VAPI_poll_cq(hca_hndl, s_cq_hndl, &wc); if(ret != VAPI_OK) { fprintf(stderr, "Error polling CQ for send in Reset: %s\n", VAPI_strerror(ret)); exit(-1); } if(wc.status != VAPI_SUCCESS) { fprintf(stderr, " Error in completion status: %s\n", VAPI_wc_status_sym(wc.status)); exit(-1); } LOGPRINTF("Status of send completion: %s\n", VAPI_wc_status_sym(wc.status)); if(p->prot.comptype == NP_COMP_EVENT) { /* If using event completion, the event handler will set receive_complete * when it gets the completion event. */ LOGPRINTF("Waiting for receive_complete flag\n"); while(receive_complete == 0) { /* BUSY WAIT */ } } else { LOGPRINTF("Polling for completion of recv request\n"); ret = VAPI_CQ_EMPTY; while(ret == VAPI_CQ_EMPTY) ret = VAPI_poll_cq(hca_hndl, r_cq_hndl, &wc); if(ret != VAPI_OK) { fprintf(stderr, "Error polling CQ for recv in Reset: %s\n", VAPI_strerror(ret)); exit(-1); } if(wc.status != VAPI_SUCCESS) { fprintf(stderr, " Error in completion status: %s\n", VAPI_wc_status_sym(wc.status)); exit(-1); } LOGPRINTF("Status of recv completion: %s\n", VAPI_wc_status_sym(wc.status)); } LOGPRINTF("Done with reset\n"); }
void RecvData(ArgStruct *p) { VAPI_ret_t ret; /* Busy wait for incoming data */ LOGPRINTF("Receiving at buffer address %p\n", p->r_ptr); if( p->prot.comptype == NP_COMP_LOCALPOLL ) { /* Poll for receive completion locally on the receive data */ LOGPRINTF("Waiting for last byte of data to arrive\n"); while(p->r_ptr[p->bufflen-1] != 'a' + (p->cache ? 1 - p->tr : 1) ) { /* BUSY WAIT -- this should be fine since we * declared r_ptr with volatile qualifier */ } /* Reset last byte */ p->r_ptr[p->bufflen-1] = 'a' + (p->cache ? p->tr : 0); LOGPRINTF("Received all of data\n"); } else if( p->prot.comptype == NP_COMP_VAPIPOLL ) { /* Poll for receive completion using VAPI poll function */ LOGPRINTF("Polling completion queue for VAPI work completion\n"); ret = VAPI_CQ_EMPTY; while(ret == VAPI_CQ_EMPTY) ret = VAPI_poll_cq(hca_hndl, r_cq_hndl, &wc); if(ret != VAPI_OK) { fprintf(stderr, "Error in RecvData, polling for completion: %s\n", VAPI_strerror(ret)); exit(-1); } if(wc.status != VAPI_SUCCESS) { fprintf(stderr, "Error in status of returned completion: %s\n", VAPI_wc_status_sym(wc.status)); exit(-1); } LOGPRINTF("Retrieved successful completion\n"); } else if( p->prot.comptype == NP_COMP_EVENT ) { /* Instead of polling directly on data or VAPI completion queue, * let the VAPI event completion handler set a flag when the receive * completes, and poll on that instead. Could try using semaphore here * as well to eliminate busy polling */ LOGPRINTF("Polling receive flag\n"); while( receive_complete == 0 ) { /* BUSY WAIT */ } /* If in prepost-burst mode, we won't be calling PrepareToReceive * between ping-pongs, so we need to reset the receive_complete * flag here. */ if( p->preburst ) receive_complete = 0; LOGPRINTF("Receive completed\n"); } }