static inline void usdf_process_nak(struct usdf_ep *ep, uint16_t seq) { struct usdf_msg_qe *wqe; size_t rewind; /* Ignore NAKs of future packets */ if (RUDP_SEQ_GE(seq, ep->e.msg.ep_next_tx_seq)) { return; } /* * Move any WQEs that contain NAKed sequences back to the * posted list. We set ms_resid == 0 here because final set to zero * is optimized out of the fastpath */ while (!TAILQ_EMPTY(&ep->e.msg.ep_sent_wqe)) { wqe = TAILQ_LAST(&ep->e.msg.ep_sent_wqe, usdf_msg_qe_head); TAILQ_REMOVE(&ep->e.msg.ep_sent_wqe, wqe, ms_link); wqe->ms_resid = 0; TAILQ_INSERT_HEAD(&ep->e.msg.ep_posted_wqe, wqe, ms_link); } wqe = TAILQ_FIRST(&ep->e.msg.ep_posted_wqe); /* reset WQE to old sequence # */ if (wqe->ms_resid == 0) { rewind = RUDP_SEQ_DIFF(wqe->ms_last_seq, seq) + 1; } else { rewind = RUDP_SEQ_DIFF(ep->e.msg.ep_next_tx_seq, seq); } if (rewind > 0) { ep->e.msg.ep_seq_credits = USDF_RUDP_SEQ_CREDITS; ep->e.msg.ep_next_tx_seq = seq; usdf_msg_rewind_qe(wqe, rewind, ep->ep_domain->dom_fabric->fab_dev_attrs->uda_mtu - sizeof(struct rudp_pkt)); usdf_msg_ep_ready(ep); } }
static inline void usdf_msg_process_ack(struct usdf_ep *ep, uint16_t seq) { struct usdf_cq_hard *hcq; struct usdf_msg_qe *wqe; struct usdf_tx *tx; uint16_t max_ack; unsigned credits; tx = ep->ep_tx; /* don't try to ACK what we don't think we've sent */ max_ack = ep->e.msg.ep_next_tx_seq - 1; if (RUDP_SEQ_GT(seq, max_ack)) { seq = max_ack; } hcq = tx->t.msg.tx_hcq; while (!TAILQ_EMPTY(&ep->e.msg.ep_sent_wqe)) { wqe = TAILQ_FIRST(&ep->e.msg.ep_sent_wqe); if (RUDP_SEQ_LE(wqe->ms_last_seq, seq)) { TAILQ_REMOVE(&ep->e.msg.ep_sent_wqe, wqe, ms_link); USDF_DBG_SYS(EP_DATA, "send complete, signal_comp=%u\n", wqe->ms_signal_comp); if (wqe->ms_signal_comp) hcq->cqh_post(hcq, wqe->ms_context, wqe->ms_length, FI_SUCCESS, FI_MSG | FI_SEND); usdf_msg_put_tx_wqe(tx, wqe); } else { break; } } credits = RUDP_SEQ_DIFF(seq, ep->e.msg.ep_last_rx_ack); if (ep->e.msg.ep_seq_credits == 0 && credits > 0 && !TAILQ_EMPTY(&ep->e.msg.ep_posted_wqe)) { usdf_msg_ep_ready(ep); } ep->e.msg.ep_seq_credits += credits; ep->e.msg.ep_last_rx_ack = seq; /* If all ACKed, cancel timer, else reset it */ if (seq == max_ack) { usdf_timer_cancel(ep->ep_domain->dom_fabric, ep->e.msg.ep_ack_timer); } else { usdf_timer_reset(ep->ep_domain->dom_fabric, ep->e.msg.ep_ack_timer, USDF_RUDP_ACK_TIMEOUT); } }
static inline void usdf_msg_process_ack(struct usdf_ep *ep, uint16_t seq) { struct usdf_cq_hard *hcq; struct usdf_msg_qe *wqe; uint16_t max_ack; unsigned credits; /* don't try to ACK what we don't think we've sent */ max_ack = ep->e.msg.ep_next_tx_seq - 1; if (RUDP_SEQ_GT(seq, max_ack)) { seq = max_ack; } hcq = ep->ep_tx->t.msg.tx_hcq; while (!TAILQ_EMPTY(&ep->e.msg.ep_sent_wqe)) { wqe = TAILQ_FIRST(&ep->e.msg.ep_sent_wqe); if (RUDP_SEQ_LE(wqe->ms_last_seq, seq)) { TAILQ_REMOVE(&ep->e.msg.ep_sent_wqe, wqe, ms_link); hcq->cqh_post(hcq, wqe->ms_context, wqe->ms_length); TAILQ_INSERT_HEAD(&ep->ep_tx->t.msg.tx_free_wqe, wqe, ms_link); } else { break; } } credits = RUDP_SEQ_DIFF(seq, ep->e.msg.ep_last_rx_ack); if (ep->e.msg.ep_seq_credits == 0 && credits > 0 && !TAILQ_EMPTY(&ep->e.msg.ep_posted_wqe)) { usdf_msg_ep_ready(ep); } ep->e.msg.ep_seq_credits += credits; ep->e.msg.ep_last_rx_ack = seq; /* If all ACKed, cancel timer, else reset it */ if (seq == max_ack) { usdf_timer_cancel(ep->ep_domain->dom_fabric, ep->e.msg.ep_ack_timer); } else { usdf_timer_reset(ep->ep_domain->dom_fabric, ep->e.msg.ep_ack_timer, USDF_RUDP_ACK_TIMEOUT); } }