Пример #1
0
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);
	}
}
Пример #2
0
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);
	}
}
Пример #3
0
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);
	}
}