IB/ipath: Fix a race where s_last is updated without lock held
There is a small window where a send work queue entry could be overwritten by ib_post_send() because s_last is updated before the entry is read. This patch closes the window by acquiring the lock and updating the last send work queue entry index after reading the wr_id. Signed-off-by: Ralph Campbell <ralph.campbell@qlogic.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
committed by
Roland Dreier
parent
96db0e0335
commit
fffbfeaa68
@@ -630,11 +630,8 @@ bail:;
|
|||||||
void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe,
|
void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe,
|
||||||
enum ib_wc_status status)
|
enum ib_wc_status status)
|
||||||
{
|
{
|
||||||
u32 last = qp->s_last;
|
unsigned long flags;
|
||||||
|
u32 last;
|
||||||
if (++last == qp->s_size)
|
|
||||||
last = 0;
|
|
||||||
qp->s_last = last;
|
|
||||||
|
|
||||||
/* See ch. 11.2.4.1 and 10.7.3.1 */
|
/* See ch. 11.2.4.1 and 10.7.3.1 */
|
||||||
if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) ||
|
if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) ||
|
||||||
@@ -658,4 +655,11 @@ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe,
|
|||||||
wc.port_num = 0;
|
wc.port_num = 0;
|
||||||
ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
|
ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spin_lock_irqsave(&qp->s_lock, flags);
|
||||||
|
last = qp->s_last;
|
||||||
|
if (++last >= qp->s_size)
|
||||||
|
last = 0;
|
||||||
|
qp->s_last = last;
|
||||||
|
spin_unlock_irqrestore(&qp->s_lock, flags);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user