aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/bnx2fc/bnx2fc_tgt.c
diff options
context:
space:
mode:
authorBhanu Prakash Gollapudi <bprakash@broadcom.com>2012-12-21 22:40:31 -0500
committerJames Bottomley <JBottomley@Parallels.com>2013-01-29 18:48:48 -0500
commite7f4fed5fa96d3da12c3e1c8ed9f536235eec3b5 (patch)
treea13ac74c4e452af823c18f06e3b9891d1f497ff7 /drivers/scsi/bnx2fc/bnx2fc_tgt.c
parent26bf62a3dd0752f29609b2dea85a4f0b806da315 (diff)
[SCSI] bnx2fc: Map the doorbell register between offload and enable requests
We used to map doorbell register after FW enable request is complete. This causes a race condition when unsolicited event is received, and FW sends a CQE for it. Since the doorbell is not mapped, driver does not arm CQ, which means FW will not notify the driver for further CQ completions. To resolve this, map the doorbell between offload and enable, so that driver is ready to receive the unsolicited packets and arm the CQ as soon as FW enable is performed. 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.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
index 236d8894bd82..c57a3bb8a9fb 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c
@@ -33,6 +33,7 @@ static void bnx2fc_upld_timer(unsigned long data)
33 BNX2FC_TGT_DBG(tgt, "upld_timer - Upload compl not received!!\n"); 33 BNX2FC_TGT_DBG(tgt, "upld_timer - Upload compl not received!!\n");
34 /* fake upload completion */ 34 /* fake upload completion */
35 clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags); 35 clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
36 clear_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
36 set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags); 37 set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
37 wake_up_interruptible(&tgt->upld_wait); 38 wake_up_interruptible(&tgt->upld_wait);
38} 39}
@@ -55,6 +56,7 @@ static void bnx2fc_ofld_timer(unsigned long data)
55 * resources are freed up in bnx2fc_offload_session 56 * resources are freed up in bnx2fc_offload_session
56 */ 57 */
57 clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags); 58 clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
59 clear_bit(BNX2FC_FLAG_ENABLED, &tgt->flags);
58 set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags); 60 set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
59 wake_up_interruptible(&tgt->ofld_wait); 61 wake_up_interruptible(&tgt->ofld_wait);
60} 62}
@@ -135,14 +137,23 @@ retry_ofld:
135 } 137 }
136 if (bnx2fc_map_doorbell(tgt)) { 138 if (bnx2fc_map_doorbell(tgt)) {
137 printk(KERN_ERR PFX "map doorbell failed - no mem\n"); 139 printk(KERN_ERR PFX "map doorbell failed - no mem\n");
138 /* upload will take care of cleaning up sess resc */ 140 goto ofld_err;
139 lport->tt.rport_logoff(rdata); 141 }
142 clear_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
143 rval = bnx2fc_send_session_enable_req(port, tgt);
144 if (rval) {
145 pr_err(PFX "enable session failed\n");
146 goto ofld_err;
140 } 147 }
148 bnx2fc_ofld_wait(tgt);
149 if (!(test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)))
150 goto ofld_err;
141 return; 151 return;
142 152
143ofld_err: 153ofld_err:
144 /* couldn't offload the session. log off from this rport */ 154 /* couldn't offload the session. log off from this rport */
145 BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n"); 155 BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n");
156 clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
146 /* Free session resources */ 157 /* Free session resources */
147 bnx2fc_free_session_resc(hba, tgt); 158 bnx2fc_free_session_resc(hba, tgt);
148tgt_init_err: 159tgt_init_err:
@@ -476,7 +487,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
476 tgt = (struct bnx2fc_rport *)&rp[1]; 487 tgt = (struct bnx2fc_rport *)&rp[1];
477 488
478 /* This can happen when ADISC finds the same target */ 489 /* This can happen when ADISC finds the same target */
479 if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) { 490 if (test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)) {
480 BNX2FC_TGT_DBG(tgt, "already offloaded\n"); 491 BNX2FC_TGT_DBG(tgt, "already offloaded\n");
481 mutex_unlock(&hba->hba_mutex); 492 mutex_unlock(&hba->hba_mutex);
482 return; 493 return;
@@ -491,11 +502,8 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
491 BNX2FC_TGT_DBG(tgt, "OFFLOAD num_ofld_sess = %d\n", 502 BNX2FC_TGT_DBG(tgt, "OFFLOAD num_ofld_sess = %d\n",
492 hba->num_ofld_sess); 503 hba->num_ofld_sess);
493 504
494 if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) { 505 if (test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags)) {
495 /* 506 /* Session is offloaded and enabled. */
496 * Session is offloaded and enabled. Map
497 * doorbell register for this target
498 */
499 BNX2FC_TGT_DBG(tgt, "sess offloaded\n"); 507 BNX2FC_TGT_DBG(tgt, "sess offloaded\n");
500 /* This counter is protected with hba mutex */ 508 /* This counter is protected with hba mutex */
501 hba->num_ofld_sess++; 509 hba->num_ofld_sess++;
@@ -532,7 +540,7 @@ void bnx2fc_rport_event_handler(struct fc_lport *lport,
532 */ 540 */
533 tgt = (struct bnx2fc_rport *)&rp[1]; 541 tgt = (struct bnx2fc_rport *)&rp[1];
534 542
535 if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) { 543 if (!(test_bit(BNX2FC_FLAG_ENABLED, &tgt->flags))) {
536 mutex_unlock(&hba->hba_mutex); 544 mutex_unlock(&hba->hba_mutex);
537 break; 545 break;
538 } 546 }