diff options
author | James Smart <james.smart@emulex.com> | 2013-10-10 12:21:30 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-10-25 04:58:17 -0400 |
commit | e8d3c3b14b9aba6adfd5a86d2ea88d4a7b185f24 (patch) | |
tree | 79d703a1d211b9d3ccff2069b4e1af6b933bf78c /drivers/scsi/lpfc | |
parent | 4902b381c6c99e5edaca1e2549f0a5149d90feec (diff) |
[SCSI] lpfc 8.3.43: Fixed invalid mailbox timeouts
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/lpfc')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 5efe12e87a15..b48c5504f573 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -71,6 +71,8 @@ static int lpfc_sli4_post_els_sgl_list(struct lpfc_hba *, struct list_head *, | |||
71 | int); | 71 | int); |
72 | static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, | 72 | static void lpfc_sli4_hba_handle_eqe(struct lpfc_hba *, struct lpfc_eqe *, |
73 | uint32_t); | 73 | uint32_t); |
74 | static bool lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba); | ||
75 | static bool lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba); | ||
74 | 76 | ||
75 | static IOCB_t * | 77 | static IOCB_t * |
76 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) | 78 | lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq) |
@@ -6566,6 +6568,108 @@ lpfc_mbox_timeout(unsigned long ptr) | |||
6566 | return; | 6568 | return; |
6567 | } | 6569 | } |
6568 | 6570 | ||
6571 | /** | ||
6572 | * lpfc_sli4_mbox_completions_pending - check to see if any mailbox completions | ||
6573 | * are pending | ||
6574 | * @phba: Pointer to HBA context object. | ||
6575 | * | ||
6576 | * This function checks if any mailbox completions are present on the mailbox | ||
6577 | * completion queue. | ||
6578 | **/ | ||
6579 | bool | ||
6580 | lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba) | ||
6581 | { | ||
6582 | |||
6583 | uint32_t idx; | ||
6584 | struct lpfc_queue *mcq; | ||
6585 | struct lpfc_mcqe *mcqe; | ||
6586 | bool pending_completions = false; | ||
6587 | |||
6588 | if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) | ||
6589 | return false; | ||
6590 | |||
6591 | /* Check for completions on mailbox completion queue */ | ||
6592 | |||
6593 | mcq = phba->sli4_hba.mbx_cq; | ||
6594 | idx = mcq->hba_index; | ||
6595 | while (bf_get_le32(lpfc_cqe_valid, mcq->qe[idx].cqe)) { | ||
6596 | mcqe = (struct lpfc_mcqe *)mcq->qe[idx].cqe; | ||
6597 | if (bf_get_le32(lpfc_trailer_completed, mcqe) && | ||
6598 | (!bf_get_le32(lpfc_trailer_async, mcqe))) { | ||
6599 | pending_completions = true; | ||
6600 | break; | ||
6601 | } | ||
6602 | idx = (idx + 1) % mcq->entry_count; | ||
6603 | if (mcq->hba_index == idx) | ||
6604 | break; | ||
6605 | } | ||
6606 | return pending_completions; | ||
6607 | |||
6608 | } | ||
6609 | |||
6610 | /** | ||
6611 | * lpfc_sli4_process_missed_mbox_completions - process mbox completions | ||
6612 | * that were missed. | ||
6613 | * @phba: Pointer to HBA context object. | ||
6614 | * | ||
6615 | * For sli4, it is possible to miss an interrupt. As such mbox completions | ||
6616 | * maybe missed causing erroneous mailbox timeouts to occur. This function | ||
6617 | * checks to see if mbox completions are on the mailbox completion queue | ||
6618 | * and will process all the completions associated with the eq for the | ||
6619 | * mailbox completion queue. | ||
6620 | **/ | ||
6621 | bool | ||
6622 | lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba) | ||
6623 | { | ||
6624 | |||
6625 | uint32_t eqidx; | ||
6626 | struct lpfc_queue *fpeq = NULL; | ||
6627 | struct lpfc_eqe *eqe; | ||
6628 | bool mbox_pending; | ||
6629 | |||
6630 | if (unlikely(!phba) || (phba->sli_rev != LPFC_SLI_REV4)) | ||
6631 | return false; | ||
6632 | |||
6633 | /* Find the eq associated with the mcq */ | ||
6634 | |||
6635 | if (phba->sli4_hba.hba_eq) | ||
6636 | for (eqidx = 0; eqidx < phba->cfg_fcp_io_channel; eqidx++) | ||
6637 | if (phba->sli4_hba.hba_eq[eqidx]->queue_id == | ||
6638 | phba->sli4_hba.mbx_cq->assoc_qid) { | ||
6639 | fpeq = phba->sli4_hba.hba_eq[eqidx]; | ||
6640 | break; | ||
6641 | } | ||
6642 | if (!fpeq) | ||
6643 | return false; | ||
6644 | |||
6645 | /* Turn off interrupts from this EQ */ | ||
6646 | |||
6647 | lpfc_sli4_eq_clr_intr(fpeq); | ||
6648 | |||
6649 | /* Check to see if a mbox completion is pending */ | ||
6650 | |||
6651 | mbox_pending = lpfc_sli4_mbox_completions_pending(phba); | ||
6652 | |||
6653 | /* | ||
6654 | * If a mbox completion is pending, process all the events on EQ | ||
6655 | * associated with the mbox completion queue (this could include | ||
6656 | * mailbox commands, async events, els commands, receive queue data | ||
6657 | * and fcp commands) | ||
6658 | */ | ||
6659 | |||
6660 | if (mbox_pending) | ||
6661 | while ((eqe = lpfc_sli4_eq_get(fpeq))) { | ||
6662 | lpfc_sli4_hba_handle_eqe(phba, eqe, eqidx); | ||
6663 | fpeq->EQ_processed++; | ||
6664 | } | ||
6665 | |||
6666 | /* Always clear and re-arm the EQ */ | ||
6667 | |||
6668 | lpfc_sli4_eq_release(fpeq, LPFC_QUEUE_REARM); | ||
6669 | |||
6670 | return mbox_pending; | ||
6671 | |||
6672 | } | ||
6569 | 6673 | ||
6570 | /** | 6674 | /** |
6571 | * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout | 6675 | * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout |
@@ -6583,6 +6687,10 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba) | |||
6583 | struct lpfc_sli *psli = &phba->sli; | 6687 | struct lpfc_sli *psli = &phba->sli; |
6584 | struct lpfc_sli_ring *pring; | 6688 | struct lpfc_sli_ring *pring; |
6585 | 6689 | ||
6690 | /* If the mailbox completed, process the completion and return */ | ||
6691 | if (lpfc_sli4_process_missed_mbox_completions(phba)) | ||
6692 | return; | ||
6693 | |||
6586 | /* Check the pmbox pointer first. There is a race condition | 6694 | /* Check the pmbox pointer first. There is a race condition |
6587 | * between the mbox timeout handler getting executed in the | 6695 | * between the mbox timeout handler getting executed in the |
6588 | * worklist and the mailbox actually completing. When this | 6696 | * worklist and the mailbox actually completing. When this |
@@ -7077,6 +7185,10 @@ lpfc_sli4_async_mbox_block(struct lpfc_hba *phba) | |||
7077 | 1000) + jiffies; | 7185 | 1000) + jiffies; |
7078 | spin_unlock_irq(&phba->hbalock); | 7186 | spin_unlock_irq(&phba->hbalock); |
7079 | 7187 | ||
7188 | /* Make sure the mailbox is really active */ | ||
7189 | if (timeout) | ||
7190 | lpfc_sli4_process_missed_mbox_completions(phba); | ||
7191 | |||
7080 | /* Wait for the outstnading mailbox command to complete */ | 7192 | /* Wait for the outstnading mailbox command to complete */ |
7081 | while (phba->sli.mbox_active) { | 7193 | while (phba->sli.mbox_active) { |
7082 | /* Check active mailbox complete status every 2ms */ | 7194 | /* Check active mailbox complete status every 2ms */ |