Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc65edcf authored by Ralph Campbell's avatar Ralph Campbell Committed by Roland Dreier
Browse files

IB/ipath: Fix RNR NAK handling



This patch fixes a couple of minor problems with RNR NAK handling:
 - The insertion sort was causing extra delay when inserting ahead
   vs. behind an existing entry on the list.
 - A resend of a first packet of a message which is still not ready,
   needs another RNR NAK (i.e., it was suppressed when it shouldn't).
 - Also, the resend tasklet doesn't need to be woken up unless the
   ACK/NAK actually indicates progress has been made.

Signed-off-by: default avatarRalph Campbell <ralph.campbell@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent e57d62a1
Loading
Loading
Loading
Loading
+7 −11
Original line number Diff line number Diff line
@@ -647,6 +647,7 @@ static void send_rc_ack(struct ipath_qp *qp)

queue_ack:
	spin_lock_irqsave(&qp->s_lock, flags);
	dev->n_rc_qacks++;
	qp->s_flags |= IPATH_S_ACK_PENDING;
	qp->s_nak_state = qp->r_nak_state;
	qp->s_ack_psn = qp->r_ack_psn;
@@ -798,11 +799,13 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc)

static inline void update_last_psn(struct ipath_qp *qp, u32 psn)
{
	if (qp->s_last_psn != psn) {
		qp->s_last_psn = psn;
		if (qp->s_wait_credit) {
			qp->s_wait_credit = 0;
			tasklet_hi_schedule(&qp->s_task);
		}
	qp->s_last_psn = psn;
	}
}

/**
@@ -1653,13 +1656,6 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
	case OP(SEND_FIRST):
		if (!ipath_get_rwqe(qp, 0)) {
		rnr_nak:
			/*
			 * A RNR NAK will ACK earlier sends and RDMA writes.
			 * Don't queue the NAK if a RDMA read or atomic
			 * is pending though.
			 */
			if (qp->r_nak_state)
				goto done;
			qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer;
			qp->r_ack_psn = qp->r_psn;
			goto send_ack;
+5 −1
Original line number Diff line number Diff line
@@ -98,11 +98,15 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp)
		while (qp->s_rnr_timeout >= nqp->s_rnr_timeout) {
			qp->s_rnr_timeout -= nqp->s_rnr_timeout;
			l = l->next;
			if (l->next == &dev->rnrwait)
			if (l->next == &dev->rnrwait) {
				nqp = NULL;
				break;
			}
			nqp = list_entry(l->next, struct ipath_qp,
					 timerwait);
		}
		if (nqp)
			nqp->s_rnr_timeout -= qp->s_rnr_timeout;
		list_add(&qp->timerwait, l);
	}
	spin_unlock_irqrestore(&dev->pending_lock, flags);