summaryrefslogtreecommitdiff
path: root/drivers/scsi/bnx2fc/bnx2fc_tgt.c
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2011-08-04 17:38:46 -0700
committerJames Bottomley <JBottomley@Parallels.com>2011-08-27 08:35:42 -0600
commitb338c785c5c945383046ff39092e3021ea5b1d95 (patch)
tree548bd66957226efdd21e32eefefc222fdc593a69 /drivers/scsi/bnx2fc/bnx2fc_tgt.c
parent81214013130cd24142f6465f7f5a256fed530c17 (diff)
[SCSI] bnx2fc: Fix NULL pointer deref during arm_cq.
There exists a race condition between CQ doorbell unmap and IO completion path that arms the CQ which causes a NULL dereference. Protect the ctx_base with cq_lock to avoid this. Also, wait for the CQ doorbell to be successfully mapped before arming the CQ. Also, do not count uncolicited CQ completions for free_sqes. Signed-off-by: Bhanu Prakash Gollapudi <bprakash@broadcom.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/bnx2fc/bnx2fc_tgt.c')
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_tgt.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index 3d28fbe1d99e..2f7a7da5b27b 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -133,9 +133,9 @@ retry_ofld:
printk(KERN_ERR PFX "map doorbell failed - no mem\n");
/* upload will take care of cleaning up sess resc */
lport->tt.rport_logoff(rdata);
- }
- /* Arm CQ */
- bnx2fc_arm_cq(tgt);
+ } else
+ /* Arm CQ */
+ bnx2fc_arm_cq(tgt);
return;
ofld_err:
@@ -806,14 +806,14 @@ mem_alloc_failure:
static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
struct bnx2fc_rport *tgt)
{
- BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
+ void __iomem *ctx_base_ptr;
- if (tgt->ctx_base) {
- iounmap(tgt->ctx_base);
- tgt->ctx_base = NULL;
- }
+ BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
spin_lock_bh(&tgt->cq_lock);
+ ctx_base_ptr = tgt->ctx_base;
+ tgt->ctx_base = NULL;
+
/* Free LCQ */
if (tgt->lcq) {
dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
@@ -867,4 +867,7 @@ static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
tgt->sq = NULL;
}
spin_unlock_bh(&tgt->cq_lock);
+
+ if (ctx_base_ptr)
+ iounmap(ctx_base_ptr);
}