cxgbe(4): Fix a couple of problems in the sge_wrq data path.
- start_wrq_wr must not drain the wr_list if there are incomplete_wrs pending. This can happen when a t4_wrq_tx runs between two start_wrq_wr. - commit_wrq_wr must examine the cookie's pidx and ndesc with the queue's lock held. Otherwise there is a bad race when incomplete WRs are being completed and commit_wrq_wr for the WR that is ahead in the queue updates the next incomplete WR's cookie's pidx/ndesc but the commit_wrq_wr for the second one is using stale values that it read without the lock. MFC after: 1 week Sponsored by: Chelsio Communications
This commit is contained in:
parent
9467c0e4be
commit
5f42964041
@ -2354,7 +2354,7 @@ start_wrq_wr(struct sge_wrq *wrq, int len16, struct wrq_cookie *cookie)
|
||||
|
||||
EQ_LOCK(eq);
|
||||
|
||||
if (!STAILQ_EMPTY(&wrq->wr_list))
|
||||
if (TAILQ_EMPTY(&wrq->incomplete_wrs) && !STAILQ_EMPTY(&wrq->wr_list))
|
||||
drain_wrq_wr_list(sc, wrq);
|
||||
|
||||
if (!STAILQ_EMPTY(&wrq->wr_list)) {
|
||||
@ -2408,9 +2408,6 @@ commit_wrq_wr(struct sge_wrq *wrq, void *w, struct wrq_cookie *cookie)
|
||||
return;
|
||||
}
|
||||
|
||||
ndesc = cookie->ndesc; /* Can be more than SGE_MAX_WR_NDESC here. */
|
||||
pidx = cookie->pidx;
|
||||
MPASS(pidx >= 0 && pidx < eq->sidx);
|
||||
if (__predict_false(w == &wrq->ss[0])) {
|
||||
int n = (eq->sidx - wrq->ss_pidx) * EQ_ESIZE;
|
||||
|
||||
@ -2422,6 +2419,9 @@ commit_wrq_wr(struct sge_wrq *wrq, void *w, struct wrq_cookie *cookie)
|
||||
wrq->tx_wrs_direct++;
|
||||
|
||||
EQ_LOCK(eq);
|
||||
ndesc = cookie->ndesc; /* Can be more than SGE_MAX_WR_NDESC here. */
|
||||
pidx = cookie->pidx;
|
||||
MPASS(pidx >= 0 && pidx < eq->sidx);
|
||||
prev = TAILQ_PREV(cookie, wrq_incomplete_wrs, link);
|
||||
next = TAILQ_NEXT(cookie, link);
|
||||
if (prev == NULL) {
|
||||
|
Loading…
Reference in New Issue
Block a user