diff options
author | np <np@FreeBSD.org> | 2016-06-01 18:46:54 +0000 |
---|---|---|
committer | np <np@FreeBSD.org> | 2016-06-01 18:46:54 +0000 |
commit | ca40d6fbcb0eb738d074fb7f45127d0722832b12 (patch) | |
tree | 1c8f1f50dbfff55accf6c1d014e832401ea75d2e | |
parent | 25669dd1d9562b9b1717d5ef59b15e1716c81634 (diff) | |
download | FreeBSD-src-ca40d6fbcb0eb738d074fb7f45127d0722832b12.zip FreeBSD-src-ca40d6fbcb0eb738d074fb7f45127d0722832b12.tar.gz |
iw_cxgbe: Fix panic that occurs when c4iw_ev_handler tries to acquire
comp_handler_lock but c4iw_destroy_cq has already freed the CQ memory
(which is where the lock resides).
Submitted by: Krishnamraju Eraparaju @ Chelsio
Sponsored by: Chelsio Communications
-rw-r--r-- | sys/dev/cxgbe/iw_cxgbe/ev.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/dev/cxgbe/iw_cxgbe/ev.c b/sys/dev/cxgbe/iw_cxgbe/ev.c index b0a9e13..f4ea0c7 100644 --- a/sys/dev/cxgbe/iw_cxgbe/ev.c +++ b/sys/dev/cxgbe/iw_cxgbe/ev.c @@ -194,13 +194,22 @@ int c4iw_ev_handler(struct sge_iq *iq, const struct rsp_ctrl *rc) struct c4iw_cq *chp; unsigned long flag; + spin_lock_irqsave(&dev->lock, flag); chp = get_chp(dev, qid); if (chp) { + atomic_inc(&chp->refcnt); + spin_unlock_irqrestore(&dev->lock, flag); + spin_lock_irqsave(&chp->comp_handler_lock, flag); (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context); spin_unlock_irqrestore(&chp->comp_handler_lock, flag); - } else + if (atomic_dec_and_test(&chp->refcnt)) + wake_up(&chp->wait); + } else { CTR2(KTR_IW_CXGBE, "%s unknown cqid 0x%x", __func__, qid); + spin_unlock_irqrestore(&dev->lock, flag); + } + return 0; } #endif |