diff options
author | Bhanu Prakash Gollapudi <bprakash@broadcom.com> | 2011-08-04 20:38:46 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2011-08-27 10:35:42 -0400 |
commit | b338c785c5c945383046ff39092e3021ea5b1d95 (patch) | |
tree | 548bd66957226efdd21e32eefefc222fdc593a69 /drivers/scsi/bnx2fc/bnx2fc_hwi.c | |
parent | 81214013130cd24142f6465f7f5a256fed530c17 (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_hwi.c')
-rw-r--r-- | drivers/scsi/bnx2fc/bnx2fc_hwi.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 72cfb14acd3a..b241f3d33362 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c | |||
@@ -1009,6 +1009,7 @@ int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt) | |||
1009 | u32 cq_cons; | 1009 | u32 cq_cons; |
1010 | struct fcoe_cqe *cqe; | 1010 | struct fcoe_cqe *cqe; |
1011 | u32 num_free_sqes = 0; | 1011 | u32 num_free_sqes = 0; |
1012 | u32 num_cqes = 0; | ||
1012 | u16 wqe; | 1013 | u16 wqe; |
1013 | 1014 | ||
1014 | /* | 1015 | /* |
@@ -1058,10 +1059,11 @@ unlock: | |||
1058 | wake_up_process(fps->iothread); | 1059 | wake_up_process(fps->iothread); |
1059 | else | 1060 | else |
1060 | bnx2fc_process_cq_compl(tgt, wqe); | 1061 | bnx2fc_process_cq_compl(tgt, wqe); |
1062 | num_free_sqes++; | ||
1061 | } | 1063 | } |
1062 | cqe++; | 1064 | cqe++; |
1063 | tgt->cq_cons_idx++; | 1065 | tgt->cq_cons_idx++; |
1064 | num_free_sqes++; | 1066 | num_cqes++; |
1065 | 1067 | ||
1066 | if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) { | 1068 | if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) { |
1067 | tgt->cq_cons_idx = 0; | 1069 | tgt->cq_cons_idx = 0; |
@@ -1070,8 +1072,10 @@ unlock: | |||
1070 | 1 - tgt->cq_curr_toggle_bit; | 1072 | 1 - tgt->cq_curr_toggle_bit; |
1071 | } | 1073 | } |
1072 | } | 1074 | } |
1073 | if (num_free_sqes) { | 1075 | if (num_cqes) { |
1074 | bnx2fc_arm_cq(tgt); | 1076 | /* Arm CQ only if doorbell is mapped */ |
1077 | if (tgt->ctx_base) | ||
1078 | bnx2fc_arm_cq(tgt); | ||
1075 | atomic_add(num_free_sqes, &tgt->free_sqes); | 1079 | atomic_add(num_free_sqes, &tgt->free_sqes); |
1076 | } | 1080 | } |
1077 | spin_unlock_bh(&tgt->cq_lock); | 1081 | spin_unlock_bh(&tgt->cq_lock); |