static void loop(struct vi_state* vi_state) { ef_event evs[EF_VI_EVENT_POLL_MIN_EVS]; ef_vi* vi = &vi_state->vi; int i; pthread_mutex_lock(&ready_mutex); ++ready_cnt; pthread_cond_signal(&ready_cond); pthread_mutex_unlock(&ready_mutex); while( 1 ) { int n_ev = ef_eventq_poll(vi, evs, sizeof(evs) / sizeof(evs[0])); for( i = 0; i < n_ev; ++i ) switch( EF_EVENT_TYPE(evs[i]) ) { case EF_EVENT_TYPE_RX: /* This code does not handle jumbos. */ assert(EF_EVENT_RX_SOP(evs[i]) != 0); assert(EF_EVENT_RX_CONT(evs[i]) == 0); handle_rx(vi_state, EF_EVENT_RX_RQ_ID(evs[i]), EF_EVENT_RX_BYTES(evs[i]) - ef_vi_receive_prefix_len(vi)); break; case EF_EVENT_TYPE_RX_DISCARD: handle_rx_discard(vi_state, EF_EVENT_RX_DISCARD_RQ_ID(evs[i]), EF_EVENT_RX_DISCARD_TYPE(evs[i])); break; default: LOGE("ERROR: unexpected event %d\n", (int) EF_EVENT_TYPE(evs[i])); break; } vi_refill_rx_ring(vi_state); } }
/* The main loop. Poll each VI handling various types of events and * then try to refill them. */ static void main_loop(void) { int i, j, k; while( 1 ) { for( i = 0; i < 2; ++i ) { ef_vi* vi = &vis[i].vi; ef_event evs[EF_VI_EVENT_POLL_MIN_EVS]; int n_ev = ef_eventq_poll(vi, evs, sizeof(evs) / sizeof(evs[0])); for( j = 0; j < n_ev; ++j ) { switch( EF_EVENT_TYPE(evs[j]) ) { case EF_EVENT_TYPE_RX: /* This code does not handle jumbos. */ assert(EF_EVENT_RX_SOP(evs[j]) != 0); assert(EF_EVENT_RX_CONT(evs[j]) == 0); handle_rx(i, EF_EVENT_RX_RQ_ID(evs[j]), EF_EVENT_RX_BYTES(evs[j]) - ef_vi_receive_prefix_len(vi)); break; case EF_EVENT_TYPE_TX: { ef_request_id ids[EF_VI_TRANSMIT_BATCH]; int ntx = ef_vi_transmit_unbundle(vi, &evs[j], ids); for( k = 0; k < ntx; ++k ) complete_tx(i, ids[k]); break; } case EF_EVENT_TYPE_RX_DISCARD: handle_rx_discard(EF_EVENT_RX_DISCARD_RQ_ID(evs[j]), EF_EVENT_RX_DISCARD_TYPE(evs[j])); break; default: LOGE("ERROR: unexpected event %d\n", (int) EF_EVENT_TYPE(evs[j])); break; } } vi_refill_rx_ring(i); } } }
static void rx_wait(void) { ef_request_id ids[EF_VI_TRANSMIT_BATCH]; ef_event evs[EF_VI_EVENT_POLL_MIN_EVS]; int n_ev, i; while( 1 ) { n_ev = ef_eventq_poll(&vi, evs, sizeof(evs) / sizeof(evs[0])); if( n_ev > 0 ) for( i = 0; i < n_ev; ++i ) switch( EF_EVENT_TYPE(evs[i]) ) { case EF_EVENT_TYPE_RX: TEST(EF_EVENT_RX_SOP(evs[i]) == 1); TEST(EF_EVENT_RX_CONT(evs[i]) == 0); TEST((int) (rx_posted - rx_completed) > 0); ++rx_completed; return; case EF_EVENT_TYPE_TX: ef_vi_transmit_unbundle(&vi, &evs[i], ids); break; case EF_EVENT_TYPE_RX_DISCARD: fprintf(stderr, "ERROR: RX_DISCARD type=%d\n", EF_EVENT_RX_DISCARD_TYPE(evs[i])); break; case EF_EVENT_TYPE_TX_ERROR: fprintf(stderr, "ERROR: TX_ERROR type=%d\n", EF_EVENT_TX_ERROR_TYPE(evs[i])); break; default: fprintf(stderr, "ERROR: unexpected event "EF_EVENT_FMT"\n", EF_EVENT_PRI_ARG(evs[i])); break; } else if( cfg_wait ) TRY(ef_eventq_wait(&vi, driver_handle, ef_eventq_current(&vi), 0)); } }
static void rx_wait(void) { ef_request_id ids[EF_VI_TRANSMIT_BATCH]; ef_event evs[EF_VI_EVENT_POLL_MIN_EVS]; int n_ev, i; while( 1 ) { n_ev = ef_eventq_poll(&vi, evs, sizeof(evs) / sizeof(evs[0])); if( n_ev > 0 ) { for( i = 0; i < n_ev; ++i ) switch( EF_EVENT_TYPE(evs[i]) ) { case EF_EVENT_TYPE_RX: TEST(EF_EVENT_RX_SOP(evs[i]) == 1); TEST(EF_EVENT_RX_CONT(evs[i]) == 0); TEST((int) (rx_posted - rx_completed) > 0); ++rx_completed; return; case EF_EVENT_TYPE_TX: ef_vi_transmit_unbundle(&vi, &evs[i], ids); break; case EF_EVENT_TYPE_RX_DISCARD: fprintf(stderr, "ERROR: RX_DISCARD type=%d\n", EF_EVENT_RX_DISCARD_TYPE(evs[i])); break; case EF_EVENT_TYPE_TX_ERROR: fprintf(stderr, "ERROR: TX_ERROR type=%d\n", EF_EVENT_TX_ERROR_TYPE(evs[i])); break; default: fprintf(stderr, "ERROR: unexpected event "EF_EVENT_FMT"\n", EF_EVENT_PRI_ARG(evs[i])); break; } } else if( cfg_eventq_wait ) { TRY(ef_eventq_wait(&vi, driver_handle, ef_eventq_current(&vi), 0)); } else if( cfg_fd_wait ) { TRY(ef_vi_prime(&vi, driver_handle, ef_eventq_current(&vi))); struct pollfd pollfd = { .fd = driver_handle, .events = POLLIN, .revents = 0, }; TRY(poll(&pollfd, 1, -1)); } } } static void tx_send(void) { struct pkt_buf* pb = pkt_bufs[FIRST_TX_BUF]; ef_vi_transmit(&vi, pb->dma_buf_addr, tx_frame_len, 0); } /**********************************************************************/ static void pong_test(void) { int i; rx_post_8(); for( i = 0; i < cfg_iter; ++i ) { rx_wait(); tx_send(); if( i % 8 == 0 ) rx_post_8(); } }