mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 06:12:08 +00:00
iw_cxgb4: don't block in destroy_qp awaiting the last deref
Blocking in c4iw_destroy_qp() causes a deadlock when apps destroy a qp or disconnect a cm_id from their cm event handler function. There is no need to block here anyway, so just replace the refcnt atomic with a kref object and free the memory on the last put. Signed-off-by: Steve Wise <swise@opengridcomputing.com> Reviewed-by: Sagi Grimberg <sagi@grimberg.me> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
parent
1b1a889dbb
commit
ad61a4c7a9
@ -475,7 +475,7 @@ struct c4iw_qp {
|
||||
struct t4_wq wq;
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
atomic_t refcnt;
|
||||
struct kref kref;
|
||||
wait_queue_head_t wait;
|
||||
struct timer_list timer;
|
||||
int sq_sig_all;
|
||||
|
@ -683,17 +683,25 @@ static int build_inv_stag(union t4_wr *wqe, struct ib_send_wr *wr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _free_qp(struct kref *kref)
|
||||
{
|
||||
struct c4iw_qp *qhp;
|
||||
|
||||
qhp = container_of(kref, struct c4iw_qp, kref);
|
||||
PDBG("%s qhp %p\n", __func__, qhp);
|
||||
kfree(qhp);
|
||||
}
|
||||
|
||||
void c4iw_qp_add_ref(struct ib_qp *qp)
|
||||
{
|
||||
PDBG("%s ib_qp %p\n", __func__, qp);
|
||||
atomic_inc(&(to_c4iw_qp(qp)->refcnt));
|
||||
kref_get(&to_c4iw_qp(qp)->kref);
|
||||
}
|
||||
|
||||
void c4iw_qp_rem_ref(struct ib_qp *qp)
|
||||
{
|
||||
PDBG("%s ib_qp %p\n", __func__, qp);
|
||||
if (atomic_dec_and_test(&(to_c4iw_qp(qp)->refcnt)))
|
||||
wake_up(&(to_c4iw_qp(qp)->wait));
|
||||
kref_put(&to_c4iw_qp(qp)->kref, _free_qp);
|
||||
}
|
||||
|
||||
static void add_to_fc_list(struct list_head *head, struct list_head *entry)
|
||||
@ -1594,8 +1602,6 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
|
||||
wait_event(qhp->wait, !qhp->ep);
|
||||
|
||||
remove_handle(rhp, &rhp->qpidr, qhp->wq.sq.qid);
|
||||
atomic_dec(&qhp->refcnt);
|
||||
wait_event(qhp->wait, !atomic_read(&qhp->refcnt));
|
||||
|
||||
spin_lock_irq(&rhp->lock);
|
||||
if (!list_empty(&qhp->db_fc_entry))
|
||||
@ -1608,8 +1614,9 @@ int c4iw_destroy_qp(struct ib_qp *ib_qp)
|
||||
destroy_qp(&rhp->rdev, &qhp->wq,
|
||||
ucontext ? &ucontext->uctx : &rhp->rdev.uctx);
|
||||
|
||||
c4iw_qp_rem_ref(ib_qp);
|
||||
|
||||
PDBG("%s ib_qp %p qpid 0x%0x\n", __func__, ib_qp, qhp->wq.sq.qid);
|
||||
kfree(qhp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1706,7 +1713,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
|
||||
init_completion(&qhp->rq_drained);
|
||||
mutex_init(&qhp->mutex);
|
||||
init_waitqueue_head(&qhp->wait);
|
||||
atomic_set(&qhp->refcnt, 1);
|
||||
kref_init(&qhp->kref);
|
||||
|
||||
ret = insert_handle(rhp, &rhp->qpidr, qhp, qhp->wq.sq.qid);
|
||||
if (ret)
|
||||
|
Loading…
Reference in New Issue
Block a user