aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorJames Smart <james.smart@emulex.com>2013-09-06 12:19:45 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-09-10 20:22:28 -0400
commitb5a9b2dfe685117d20062e7cb7998df4d786fca7 (patch)
treedd0bdb7fc1d7f34e6c6531c7ccfe2849616a9bb1 /drivers/scsi
parent9a86ed48408af49207172e590554d82cdb21cdbd (diff)
[SCSI] lpfc 8.3.42: Fixed race condition between BSG I/O dispatch and timeout handling
Signed-off-by: James Smart <james.smart@emulex.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c86
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.h3
2 files changed, 72 insertions, 17 deletions
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index de5a1b08b036..aa2109765a86 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -317,6 +317,11 @@ lpfc_bsg_send_mgmt_cmd_cmp(struct lpfc_hba *phba,
317 } 317 }
318 spin_unlock_irqrestore(&phba->ct_ev_lock, flags); 318 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
319 319
320 /* Close the timeout handler abort window */
321 spin_lock_irqsave(&phba->hbalock, flags);
322 cmdiocbq->iocb_aux_flag &= ~LPFC_IO_CMD_OUTSTANDING;
323 spin_unlock_irqrestore(&phba->hbalock, flags);
324
320 iocb = &dd_data->context_un.iocb; 325 iocb = &dd_data->context_un.iocb;
321 ndlp = iocb->ndlp; 326 ndlp = iocb->ndlp;
322 rmp = iocb->rmp; 327 rmp = iocb->rmp;
@@ -387,6 +392,7 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
387 int request_nseg; 392 int request_nseg;
388 int reply_nseg; 393 int reply_nseg;
389 struct bsg_job_data *dd_data; 394 struct bsg_job_data *dd_data;
395 unsigned long flags;
390 uint32_t creg_val; 396 uint32_t creg_val;
391 int rc = 0; 397 int rc = 0;
392 int iocb_stat; 398 int iocb_stat;
@@ -501,14 +507,24 @@ lpfc_bsg_send_mgmt_cmd(struct fc_bsg_job *job)
501 } 507 }
502 508
503 iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); 509 iocb_stat = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
504 if (iocb_stat == IOCB_SUCCESS) 510
511 if (iocb_stat == IOCB_SUCCESS) {
512 spin_lock_irqsave(&phba->hbalock, flags);
513 /* make sure the I/O had not been completed yet */
514 if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) {
515 /* open up abort window to timeout handler */
516 cmdiocbq->iocb_aux_flag |= LPFC_IO_CMD_OUTSTANDING;
517 }
518 spin_unlock_irqrestore(&phba->hbalock, flags);
505 return 0; /* done for now */ 519 return 0; /* done for now */
506 else if (iocb_stat == IOCB_BUSY) 520 } else if (iocb_stat == IOCB_BUSY) {
507 rc = -EAGAIN; 521 rc = -EAGAIN;
508 else 522 } else {
509 rc = -EIO; 523 rc = -EIO;
524 }
510 525
511 /* iocb failed so cleanup */ 526 /* iocb failed so cleanup */
527 job->dd_data = NULL;
512 528
513free_rmp: 529free_rmp:
514 lpfc_free_bsg_buffers(phba, rmp); 530 lpfc_free_bsg_buffers(phba, rmp);
@@ -577,6 +593,11 @@ lpfc_bsg_rport_els_cmp(struct lpfc_hba *phba,
577 } 593 }
578 spin_unlock_irqrestore(&phba->ct_ev_lock, flags); 594 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
579 595
596 /* Close the timeout handler abort window */
597 spin_lock_irqsave(&phba->hbalock, flags);
598 cmdiocbq->iocb_aux_flag &= ~LPFC_IO_CMD_OUTSTANDING;
599 spin_unlock_irqrestore(&phba->hbalock, flags);
600
580 rsp = &rspiocbq->iocb; 601 rsp = &rspiocbq->iocb;
581 pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2; 602 pcmd = (struct lpfc_dmabuf *)cmdiocbq->context2;
582 prsp = (struct lpfc_dmabuf *)pcmd->list.next; 603 prsp = (struct lpfc_dmabuf *)pcmd->list.next;
@@ -639,6 +660,7 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
639 struct lpfc_iocbq *cmdiocbq; 660 struct lpfc_iocbq *cmdiocbq;
640 uint16_t rpi = 0; 661 uint16_t rpi = 0;
641 struct bsg_job_data *dd_data; 662 struct bsg_job_data *dd_data;
663 unsigned long flags;
642 uint32_t creg_val; 664 uint32_t creg_val;
643 int rc = 0; 665 int rc = 0;
644 666
@@ -721,15 +743,25 @@ lpfc_bsg_rport_els(struct fc_bsg_job *job)
721 743
722 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0); 744 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, cmdiocbq, 0);
723 745
724 if (rc == IOCB_SUCCESS) 746 if (rc == IOCB_SUCCESS) {
747 spin_lock_irqsave(&phba->hbalock, flags);
748 /* make sure the I/O had not been completed/released */
749 if (cmdiocbq->iocb_flag & LPFC_IO_LIBDFC) {
750 /* open up abort window to timeout handler */
751 cmdiocbq->iocb_aux_flag |= LPFC_IO_CMD_OUTSTANDING;
752 }
753 spin_unlock_irqrestore(&phba->hbalock, flags);
725 return 0; /* done for now */ 754 return 0; /* done for now */
726 else if (rc == IOCB_BUSY) 755 } else if (rc == IOCB_BUSY) {
727 rc = -EAGAIN; 756 rc = -EAGAIN;
728 else 757 } else {
729 rc = -EIO; 758 rc = -EIO;
759 }
730 760
731linkdown_err: 761 /* iocb failed so cleanup */
762 job->dd_data = NULL;
732 763
764linkdown_err:
733 cmdiocbq->context1 = ndlp; 765 cmdiocbq->context1 = ndlp;
734 lpfc_els_free_iocb(phba, cmdiocbq); 766 lpfc_els_free_iocb(phba, cmdiocbq);
735 767
@@ -1370,6 +1402,11 @@ lpfc_issue_ct_rsp_cmp(struct lpfc_hba *phba,
1370 } 1402 }
1371 spin_unlock_irqrestore(&phba->ct_ev_lock, flags); 1403 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
1372 1404
1405 /* Close the timeout handler abort window */
1406 spin_lock_irqsave(&phba->hbalock, flags);
1407 cmdiocbq->iocb_aux_flag &= ~LPFC_IO_CMD_OUTSTANDING;
1408 spin_unlock_irqrestore(&phba->hbalock, flags);
1409
1373 ndlp = dd_data->context_un.iocb.ndlp; 1410 ndlp = dd_data->context_un.iocb.ndlp;
1374 cmp = cmdiocbq->context2; 1411 cmp = cmdiocbq->context2;
1375 bmp = cmdiocbq->context3; 1412 bmp = cmdiocbq->context3;
@@ -1433,6 +1470,7 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
1433 int rc = 0; 1470 int rc = 0;
1434 struct lpfc_nodelist *ndlp = NULL; 1471 struct lpfc_nodelist *ndlp = NULL;
1435 struct bsg_job_data *dd_data; 1472 struct bsg_job_data *dd_data;
1473 unsigned long flags;
1436 uint32_t creg_val; 1474 uint32_t creg_val;
1437 1475
1438 /* allocate our bsg tracking structure */ 1476 /* allocate our bsg tracking structure */
@@ -1542,8 +1580,19 @@ lpfc_issue_ct_rsp(struct lpfc_hba *phba, struct fc_bsg_job *job, uint32_t tag,
1542 1580
1543 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0); 1581 rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
1544 1582
1545 if (rc == IOCB_SUCCESS) 1583 if (rc == IOCB_SUCCESS) {
1584 spin_lock_irqsave(&phba->hbalock, flags);
1585 /* make sure the I/O had not been completed/released */
1586 if (ctiocb->iocb_flag & LPFC_IO_LIBDFC) {
1587 /* open up abort window to timeout handler */
1588 ctiocb->iocb_aux_flag |= LPFC_IO_CMD_OUTSTANDING;
1589 }
1590 spin_unlock_irqrestore(&phba->hbalock, flags);
1546 return 0; /* done for now */ 1591 return 0; /* done for now */
1592 }
1593
1594 /* iocb failed so cleanup */
1595 job->dd_data = NULL;
1547 1596
1548issue_ct_rsp_exit: 1597issue_ct_rsp_exit:
1549 lpfc_sli_release_iocbq(phba, ctiocb); 1598 lpfc_sli_release_iocbq(phba, ctiocb);
@@ -5284,9 +5333,15 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
5284 * remove it from the txq queue and call cancel iocbs. 5333 * remove it from the txq queue and call cancel iocbs.
5285 * Otherwise, call abort iotag 5334 * Otherwise, call abort iotag
5286 */ 5335 */
5287
5288 cmdiocb = dd_data->context_un.iocb.cmdiocbq; 5336 cmdiocb = dd_data->context_un.iocb.cmdiocbq;
5289 spin_lock_irq(&phba->hbalock); 5337 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5338
5339 spin_lock_irqsave(&phba->hbalock, flags);
5340 /* make sure the I/O abort window is still open */
5341 if (!(cmdiocb->iocb_aux_flag & LPFC_IO_CMD_OUTSTANDING)) {
5342 spin_unlock_irqrestore(&phba->hbalock, flags);
5343 return -EAGAIN;
5344 }
5290 list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq, 5345 list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
5291 list) { 5346 list) {
5292 if (check_iocb == cmdiocb) { 5347 if (check_iocb == cmdiocb) {
@@ -5296,8 +5351,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
5296 } 5351 }
5297 if (list_empty(&completions)) 5352 if (list_empty(&completions))
5298 lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); 5353 lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
5299 spin_unlock_irq(&phba->hbalock); 5354 spin_unlock_irqrestore(&phba->hbalock, flags);
5300 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5301 if (!list_empty(&completions)) { 5355 if (!list_empty(&completions)) {
5302 lpfc_sli_cancel_iocbs(phba, &completions, 5356 lpfc_sli_cancel_iocbs(phba, &completions,
5303 IOSTAT_LOCAL_REJECT, 5357 IOSTAT_LOCAL_REJECT,
@@ -5321,9 +5375,10 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
5321 * remove it from the txq queue and call cancel iocbs. 5375 * remove it from the txq queue and call cancel iocbs.
5322 * Otherwise, call abort iotag. 5376 * Otherwise, call abort iotag.
5323 */ 5377 */
5324
5325 cmdiocb = dd_data->context_un.menlo.cmdiocbq; 5378 cmdiocb = dd_data->context_un.menlo.cmdiocbq;
5326 spin_lock_irq(&phba->hbalock); 5379 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5380
5381 spin_lock_irqsave(&phba->hbalock, flags);
5327 list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq, 5382 list_for_each_entry_safe(check_iocb, next_iocb, &pring->txq,
5328 list) { 5383 list) {
5329 if (check_iocb == cmdiocb) { 5384 if (check_iocb == cmdiocb) {
@@ -5333,8 +5388,7 @@ lpfc_bsg_timeout(struct fc_bsg_job *job)
5333 } 5388 }
5334 if (list_empty(&completions)) 5389 if (list_empty(&completions))
5335 lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb); 5390 lpfc_sli_issue_abort_iotag(phba, pring, cmdiocb);
5336 spin_unlock_irq(&phba->hbalock); 5391 spin_unlock_irqrestore(&phba->hbalock, flags);
5337 spin_unlock_irqrestore(&phba->ct_ev_lock, flags);
5338 if (!list_empty(&completions)) { 5392 if (!list_empty(&completions)) {
5339 lpfc_sli_cancel_iocbs(phba, &completions, 5393 lpfc_sli_cancel_iocbs(phba, &completions,
5340 IOSTAT_LOCAL_REJECT, 5394 IOSTAT_LOCAL_REJECT,
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h
index 97617996206d..4b8216df2afd 100644
--- a/drivers/scsi/lpfc/lpfc_sli.h
+++ b/drivers/scsi/lpfc/lpfc_sli.h
@@ -77,7 +77,8 @@ struct lpfc_iocbq {
77#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */ 77#define LPFC_FIP_ELS_ID_MASK 0xc000 /* ELS_ID range 0-3, non-shifted mask */
78#define LPFC_FIP_ELS_ID_SHIFT 14 78#define LPFC_FIP_ELS_ID_SHIFT 14
79 79
80 uint8_t rsvd2; 80 uint8_t iocb_aux_flag;
81#define LPFC_IO_CMD_OUTSTANDING 0x01 /* timeout handler abort window */
81 uint32_t drvrTimeout; /* driver timeout in seconds */ 82 uint32_t drvrTimeout; /* driver timeout in seconds */
82 uint32_t fcp_wqidx; /* index to FCP work queue */ 83 uint32_t fcp_wqidx; /* index to FCP work queue */
83 struct lpfc_vport *vport;/* virtual port pointer */ 84 struct lpfc_vport *vport;/* virtual port pointer */