mirror of
https://github.com/torvalds/linux.git
synced 2024-12-14 07:02:23 +00:00
IB/hfi1: Fix abba locking issue with sc_disable()
sc_disable() after having disabled the send context wakes up any waiters
by calling hfi1_qp_wakeup() while holding the waitlock for the sc.
This is contrary to the model for all other calls to hfi1_qp_wakeup()
where the waitlock is dropped and a local is used to drive calls to
hfi1_qp_wakeup().
Fix by moving the sc->piowait into a local list and driving the wakeup
calls from the list.
Fixes: 099a884ba4
("IB/hfi1: Handle wakeup of orphaned QPs for pio")
Link: https://lore.kernel.org/r/20211013141852.128104.2682.stgit@awfm-01.cornelisnetworks.com
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@cornelisnetworks.com>
Reported-by: TOTE Robot <oslab@tsinghua.edu.cn>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
parent
d39bf40e55
commit
13bac86195
@ -878,6 +878,7 @@ void sc_disable(struct send_context *sc)
|
|||||||
{
|
{
|
||||||
u64 reg;
|
u64 reg;
|
||||||
struct pio_buf *pbuf;
|
struct pio_buf *pbuf;
|
||||||
|
LIST_HEAD(wake_list);
|
||||||
|
|
||||||
if (!sc)
|
if (!sc)
|
||||||
return;
|
return;
|
||||||
@ -912,19 +913,21 @@ void sc_disable(struct send_context *sc)
|
|||||||
spin_unlock(&sc->release_lock);
|
spin_unlock(&sc->release_lock);
|
||||||
|
|
||||||
write_seqlock(&sc->waitlock);
|
write_seqlock(&sc->waitlock);
|
||||||
while (!list_empty(&sc->piowait)) {
|
if (!list_empty(&sc->piowait))
|
||||||
|
list_move(&sc->piowait, &wake_list);
|
||||||
|
write_sequnlock(&sc->waitlock);
|
||||||
|
while (!list_empty(&wake_list)) {
|
||||||
struct iowait *wait;
|
struct iowait *wait;
|
||||||
struct rvt_qp *qp;
|
struct rvt_qp *qp;
|
||||||
struct hfi1_qp_priv *priv;
|
struct hfi1_qp_priv *priv;
|
||||||
|
|
||||||
wait = list_first_entry(&sc->piowait, struct iowait, list);
|
wait = list_first_entry(&wake_list, struct iowait, list);
|
||||||
qp = iowait_to_qp(wait);
|
qp = iowait_to_qp(wait);
|
||||||
priv = qp->priv;
|
priv = qp->priv;
|
||||||
list_del_init(&priv->s_iowait.list);
|
list_del_init(&priv->s_iowait.list);
|
||||||
priv->s_iowait.lock = NULL;
|
priv->s_iowait.lock = NULL;
|
||||||
hfi1_qp_wakeup(qp, RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
|
hfi1_qp_wakeup(qp, RVT_S_WAIT_PIO | HFI1_S_WAIT_PIO_DRAIN);
|
||||||
}
|
}
|
||||||
write_sequnlock(&sc->waitlock);
|
|
||||||
|
|
||||||
spin_unlock_irq(&sc->alloc_lock);
|
spin_unlock_irq(&sc->alloc_lock);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user