diff options
author | James Smart <james.smart@emulex.com> | 2013-03-02 01:35:12 +0400 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2013-04-10 01:21:58 +0400 |
commit | 0e9bb8d79c52ca115f3fc4a692ca0dd6931e2eeb (patch) | |
tree | ca868fc67d44fbcff55e449f00ee4a4142098740 /drivers/scsi/lpfc | |
parent | d4a2618fa77b5e58ec15342972bd3505a1c3f551 (diff) | |
download | linux-0e9bb8d79c52ca115f3fc4a692ca0dd6931e2eeb.tar.xz |
[SCSI] lpfc 8.3.38: Fixed NMI watch dog panic's when resetting the hba.
Fixed NMI watch dog panic's when resetting the hba.
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_attr.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_bsg.c | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_hbadisc.c | 5 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_nportdisc.c | 1 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_scsi.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 92 |
8 files changed, 70 insertions, 43 deletions
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index a364cae9e984..97921dcd8626 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -692,7 +692,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type) */ for (i = 0; i < psli->num_rings; i++) { pring = &psli->ring[i]; - while (pring->txcmplq_cnt) { + while (!list_empty(&pring->txcmplq)) { msleep(10); if (cnt++ > 500) { /* 5 secs */ lpfc_printf_log(phba, diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index 32d5683e6181..18d3b69963ab 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c @@ -1559,7 +1559,7 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba) scsi_block_requests(shost); } - while (pring->txcmplq_cnt) { + while (!list_empty(&pring->txcmplq)) { if (i++ > 500) /* wait up to 5 seconds */ break; msleep(10); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 08d156a9094f..b7a61ff43ca8 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6225,7 +6225,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport) spin_unlock_irq(&phba->hbalock); } - if (phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt) + if (!list_empty(&phba->sli.ring[LPFC_ELS_RING].txcmplq)) mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout); } @@ -6279,7 +6279,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport) continue; list_move_tail(&piocb->list, &completions); - pring->txq_cnt--; } list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { @@ -6339,7 +6338,6 @@ lpfc_els_flush_all_cmd(struct lpfc_hba *phba) cmd->ulpCommand == CMD_ABORT_XRI_CN) continue; list_move_tail(&piocb->list, &completions); - pring->txq_cnt--; } list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { if (piocb->iocb_flag & LPFC_IO_LIBDFC) @@ -8065,7 +8063,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba, rxid, 1); /* Check if TXQ queue needs to be serviced */ - if (pring->txq_cnt) + if (!(list_empty(&pring->txq))) lpfc_worker_wake_up(phba); return; } diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index d7096ad94d3f..915e1aa6c681 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -696,7 +696,8 @@ lpfc_work_done(struct lpfc_hba *phba) (status & HA_RXMASK)); } - if ((phba->sli_rev == LPFC_SLI_REV4) && pring->txq_cnt) + if ((phba->sli_rev == LPFC_SLI_REV4) & + (!list_empty(&pring->txq))) lpfc_drain_txq(phba); /* * Turn on Ring interrupts @@ -4354,7 +4355,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) with an error */ list_move_tail(&iocb->list, &completions); - pring->txq_cnt--; } } spin_unlock_irq(&phba->hbalock); @@ -5055,7 +5055,6 @@ lpfc_free_tx(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) { list_move_tail(&iocb->list, &completions); - pring->txq_cnt--; } } diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 314b4f61b9e3..b28f4e7c3bc6 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -839,7 +839,6 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba) * way, nothing should be on txcmplq as it will NEVER complete. */ list_splice_init(&pring->txcmplq, &completions); - pring->txcmplq_cnt = 0; spin_unlock_irq(&phba->hbalock); /* Cancel all the IOCBs from the completions list */ diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 46128c679202..82f4d3542289 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -226,7 +226,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp) if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { /* It matches, so deque and call compl with anp error */ list_move_tail(&iocb->list, &completions); - pring->txq_cnt--; } } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 98af07c6e300..e75210d67970 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -732,7 +732,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba, psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); psb->exch_busy = 0; spin_unlock_irqrestore(&phba->hbalock, iflag); - if (pring->txq_cnt) + if (!list_empty(&pring->txq)) lpfc_worker_wake_up(phba); return; @@ -4246,7 +4246,7 @@ static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba) unsigned long poll_tmo_expires = (jiffies + msecs_to_jiffies(phba->cfg_poll_tmo)); - if (phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt) + if (!list_empty(&phba->sli.ring[LPFC_FCP_RING].txcmplq)) mod_timer(&phba->fcp_poll_timer, poll_tmo_expires); } diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 74b67d98e952..a0ef439058f0 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -1008,6 +1008,18 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) else sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_lxritag); + /* + ** This should have been removed from the txcmplq before calling + ** iocbq_release. The normal completion + ** path should have already done the list_del_init. + */ + if (unlikely(!list_empty(&iocbq->list))) { + if (iocbq->iocb_flag & LPFC_IO_ON_TXCMPLQ) + iocbq->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; + list_del_init(&iocbq->list); + } + + if (sglq) { if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && (sglq->state != SGL_XRI_ABORTED)) { @@ -1024,7 +1036,7 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) &phba->sli4_hba.lpfc_sgl_list); /* Check if TXQ queue needs to be serviced */ - if (pring->txq_cnt) + if (!list_empty(&pring->txq)) lpfc_worker_wake_up(phba); } } @@ -1056,6 +1068,14 @@ __lpfc_sli_release_iocbq_s3(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq) size_t start_clean = offsetof(struct lpfc_iocbq, iocb); /* + ** This should have been removed from the txcmplq before calling + ** iocbq_release. The normal completion + ** path should have already done the list_del_init. + */ + if (unlikely(!list_empty(&iocbq->list))) + list_del_init(&iocbq->list); + + /* * Clean all volatile data fields, preserve iotag and node struct. */ memset((char*)iocbq + start_clean, 0, sizeof(*iocbq) - start_clean); @@ -1121,7 +1141,6 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist, while (!list_empty(iocblist)) { list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); - if (!piocb->iocb_cmpl) lpfc_sli_release_iocbq(phba, piocb); else { @@ -1309,9 +1328,6 @@ lpfc_sli_ringtxcmpl_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, { list_add_tail(&piocb->list, &pring->txcmplq); piocb->iocb_flag |= LPFC_IO_ON_TXCMPLQ; - pring->txcmplq_cnt++; - if (pring->txcmplq_cnt > pring->txcmplq_max) - pring->txcmplq_max = pring->txcmplq_cnt; if ((unlikely(pring->ringno == LPFC_ELS_RING)) && (piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && @@ -1343,8 +1359,6 @@ lpfc_sli_ringtx_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) struct lpfc_iocbq *cmd_iocb; list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list); - if (cmd_iocb != NULL) - pring->txq_cnt--; return cmd_iocb; } @@ -1613,8 +1627,9 @@ lpfc_sli_resume_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) * (c) link attention events can be processed (fcp ring only) * (d) IOCB processing is not blocked by the outstanding mbox command. */ - if (pring->txq_cnt && - lpfc_is_link_up(phba) && + + if (lpfc_is_link_up(phba) && + (!list_empty(&pring->txq)) && (pring->ringno != phba->sli.fcp_ring || phba->sli.sli_flag & LPFC_PROCESS_LA)) { @@ -2611,7 +2626,6 @@ lpfc_sli_iocbq_lookup(struct lpfc_hba *phba, cmd_iocb = phba->sli.iocbq_lookup[iotag]; list_del_init(&cmd_iocb->list); if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { - pring->txcmplq_cnt--; cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; } return cmd_iocb; @@ -2649,7 +2663,6 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba, /* remove from txcmpl queue list */ list_del_init(&cmd_iocb->list); cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; - pring->txcmplq_cnt--; return cmd_iocb; } } @@ -3498,7 +3511,6 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring) */ spin_lock_irq(&phba->hbalock); list_splice_init(&pring->txq, &completions); - pring->txq_cnt = 0; /* Next issue ABTS for everything on the txcmplq */ list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) @@ -3535,11 +3547,9 @@ lpfc_sli_flush_fcp_rings(struct lpfc_hba *phba) spin_lock_irq(&phba->hbalock); /* Retrieve everything on txq */ list_splice_init(&pring->txq, &txq); - pring->txq_cnt = 0; /* Retrieve everything on the txcmplq */ list_splice_init(&pring->txcmplq, &txcmplq); - pring->txcmplq_cnt = 0; /* Indicate the I/O queues are flushed */ phba->hba_flag |= HBA_FCP_IOQ_FLUSH; @@ -7614,7 +7624,6 @@ __lpfc_sli_ringtx_put(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, { /* Insert the caller's iocb in the txq tail for later processing. */ list_add_tail(&piocb->list, &pring->txq); - pring->txq_cnt++; } /** @@ -8386,7 +8395,7 @@ __lpfc_sli_issue_iocb_s4(struct lpfc_hba *phba, uint32_t ring_number, piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN) sglq = NULL; else { - if (pring->txq_cnt) { + if (!list_empty(&pring->txq)) { if (!(flag & SLI_IOCB_RET_IOCB)) { __lpfc_sli_ringtx_put(phba, pring, piocb); @@ -9054,7 +9063,6 @@ lpfc_sli_host_down(struct lpfc_vport *vport) if (iocb->vport != vport) continue; list_move_tail(&iocb->list, &completions); - pring->txq_cnt--; } /* Next issue ABTS for everything on the txcmplq */ @@ -9123,8 +9131,6 @@ lpfc_sli_hba_down(struct lpfc_hba *phba) * given to the FW yet. */ list_splice_init(&pring->txq, &completions); - pring->txq_cnt = 0; - } spin_unlock_irqrestore(&phba->hbalock, flags); @@ -9965,6 +9971,9 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, long timeleft, timeout_req = 0; int retval = IOCB_SUCCESS; uint32_t creg_val; + struct lpfc_iocbq *iocb; + int txq_cnt = 0; + int txcmplq_cnt = 0; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING]; /* * If the caller has provided a response iocbq buffer, then context2 @@ -10012,9 +10021,17 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba, retval = IOCB_TIMEDOUT; } } else if (retval == IOCB_BUSY) { - lpfc_printf_log(phba, KERN_INFO, LOG_SLI, - "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n", - phba->iocb_cnt, pring->txq_cnt, pring->txcmplq_cnt); + if (phba->cfg_log_verbose & LOG_SLI) { + list_for_each_entry(iocb, &pring->txq, list) { + txq_cnt++; + } + list_for_each_entry(iocb, &pring->txcmplq, list) { + txcmplq_cnt++; + } + lpfc_printf_log(phba, KERN_INFO, LOG_SLI, + "2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n", + phba->iocb_cnt, txq_cnt, txcmplq_cnt); + } return retval; } else { lpfc_printf_log(phba, KERN_INFO, LOG_SLI, @@ -11297,16 +11314,25 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, struct lpfc_iocbq *irspiocbq; unsigned long iflags; struct lpfc_sli_ring *pring = cq->pring; + int txq_cnt = 0; + int txcmplq_cnt = 0; + int fcp_txcmplq_cnt = 0; /* Get an irspiocbq for later ELS response processing use */ irspiocbq = lpfc_sli_get_iocbq(phba); if (!irspiocbq) { + if (!list_empty(&pring->txq)) + txq_cnt++; + if (!list_empty(&pring->txcmplq)) + txcmplq_cnt++; + if (!list_empty(&phba->sli.ring[LPFC_FCP_RING].txcmplq)) + fcp_txcmplq_cnt++; lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d " "fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n", - pring->txq_cnt, phba->iocb_cnt, - phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt, - phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt); + txq_cnt, phba->iocb_cnt, + fcp_txcmplq_cnt, + txcmplq_cnt); return false; } @@ -16244,14 +16270,19 @@ lpfc_drain_txq(struct lpfc_hba *phba) char *fail_msg = NULL; struct lpfc_sglq *sglq; union lpfc_wqe wqe; + int txq_cnt = 0; spin_lock_irqsave(&phba->hbalock, iflags); - if (pring->txq_cnt > pring->txq_max) - pring->txq_max = pring->txq_cnt; + list_for_each_entry(piocbq, &pring->txq, list) { + txq_cnt++; + } + + if (txq_cnt > pring->txq_max) + pring->txq_max = txq_cnt; spin_unlock_irqrestore(&phba->hbalock, iflags); - while (pring->txq_cnt) { + while (!list_empty(&pring->txq)) { spin_lock_irqsave(&phba->hbalock, iflags); piocbq = lpfc_sli_ringtx_get(phba, pring); @@ -16259,7 +16290,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) spin_unlock_irqrestore(&phba->hbalock, iflags); lpfc_printf_log(phba, KERN_ERR, LOG_SLI, "2823 txq empty and txq_cnt is %d\n ", - pring->txq_cnt); + txq_cnt); break; } sglq = __lpfc_sli_get_sglq(phba, piocbq); @@ -16268,6 +16299,7 @@ lpfc_drain_txq(struct lpfc_hba *phba) spin_unlock_irqrestore(&phba->hbalock, iflags); break; } + txq_cnt--; /* The xri and iocb resources secured, * attempt to issue request @@ -16299,5 +16331,5 @@ lpfc_drain_txq(struct lpfc_hba *phba) lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, IOERR_SLI_ABORTED); - return pring->txq_cnt; + return txq_cnt; } |