[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>
This commit is contained in:
James Smart 2013-03-01 16:35:12 -05:00 committed by James Bottomley
parent d4a2618fa7
commit 0e9bb8d79c
8 changed files with 70 additions and 43 deletions

View File

@ -692,7 +692,7 @@ lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
*/ */
for (i = 0; i < psli->num_rings; i++) { for (i = 0; i < psli->num_rings; i++) {
pring = &psli->ring[i]; pring = &psli->ring[i];
while (pring->txcmplq_cnt) { while (!list_empty(&pring->txcmplq)) {
msleep(10); msleep(10);
if (cnt++ > 500) { /* 5 secs */ if (cnt++ > 500) { /* 5 secs */
lpfc_printf_log(phba, lpfc_printf_log(phba,

View File

@ -1559,7 +1559,7 @@ lpfc_bsg_diag_mode_enter(struct lpfc_hba *phba)
scsi_block_requests(shost); scsi_block_requests(shost);
} }
while (pring->txcmplq_cnt) { while (!list_empty(&pring->txcmplq)) {
if (i++ > 500) /* wait up to 5 seconds */ if (i++ > 500) /* wait up to 5 seconds */
break; break;
msleep(10); msleep(10);

View File

@ -6225,7 +6225,7 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
spin_unlock_irq(&phba->hbalock); 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); mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
} }
@ -6279,7 +6279,6 @@ lpfc_els_flush_cmd(struct lpfc_vport *vport)
continue; continue;
list_move_tail(&piocb->list, &completions); list_move_tail(&piocb->list, &completions);
pring->txq_cnt--;
} }
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { 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) cmd->ulpCommand == CMD_ABORT_XRI_CN)
continue; continue;
list_move_tail(&piocb->list, &completions); list_move_tail(&piocb->list, &completions);
pring->txq_cnt--;
} }
list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) { list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
if (piocb->iocb_flag & LPFC_IO_LIBDFC) if (piocb->iocb_flag & LPFC_IO_LIBDFC)
@ -8065,7 +8063,7 @@ lpfc_sli4_els_xri_aborted(struct lpfc_hba *phba,
rxid, 1); rxid, 1);
/* Check if TXQ queue needs to be serviced */ /* Check if TXQ queue needs to be serviced */
if (pring->txq_cnt) if (!(list_empty(&pring->txq)))
lpfc_worker_wake_up(phba); lpfc_worker_wake_up(phba);
return; return;
} }

View File

@ -696,7 +696,8 @@ lpfc_work_done(struct lpfc_hba *phba)
(status & (status &
HA_RXMASK)); 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); lpfc_drain_txq(phba);
/* /*
* Turn on Ring interrupts * Turn on Ring interrupts
@ -4354,7 +4355,6 @@ lpfc_no_rpi(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
with an error */ with an error */
list_move_tail(&iocb->list, list_move_tail(&iocb->list,
&completions); &completions);
pring->txq_cnt--;
} }
} }
spin_unlock_irq(&phba->hbalock); 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)) { (icmd->ulpCommand == CMD_XMIT_ELS_RSP64_CX)) {
list_move_tail(&iocb->list, &completions); list_move_tail(&iocb->list, &completions);
pring->txq_cnt--;
} }
} }

View File

@ -839,7 +839,6 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba)
* way, nothing should be on txcmplq as it will NEVER complete. * way, nothing should be on txcmplq as it will NEVER complete.
*/ */
list_splice_init(&pring->txcmplq, &completions); list_splice_init(&pring->txcmplq, &completions);
pring->txcmplq_cnt = 0;
spin_unlock_irq(&phba->hbalock); spin_unlock_irq(&phba->hbalock);
/* Cancel all the IOCBs from the completions list */ /* Cancel all the IOCBs from the completions list */

View File

@ -226,7 +226,6 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) { if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
/* It matches, so deque and call compl with anp error */ /* It matches, so deque and call compl with anp error */
list_move_tail(&iocb->list, &completions); list_move_tail(&iocb->list, &completions);
pring->txq_cnt--;
} }
} }

View File

@ -732,7 +732,7 @@ lpfc_sli4_fcp_xri_aborted(struct lpfc_hba *phba,
psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq); psb = container_of(iocbq, struct lpfc_scsi_buf, cur_iocbq);
psb->exch_busy = 0; psb->exch_busy = 0;
spin_unlock_irqrestore(&phba->hbalock, iflag); spin_unlock_irqrestore(&phba->hbalock, iflag);
if (pring->txq_cnt) if (!list_empty(&pring->txq))
lpfc_worker_wake_up(phba); lpfc_worker_wake_up(phba);
return; return;
@ -4246,7 +4246,7 @@ static __inline__ void lpfc_poll_rearm_timer(struct lpfc_hba * phba)
unsigned long poll_tmo_expires = unsigned long poll_tmo_expires =
(jiffies + msecs_to_jiffies(phba->cfg_poll_tmo)); (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, mod_timer(&phba->fcp_poll_timer,
poll_tmo_expires); poll_tmo_expires);
} }

View File

@ -1008,6 +1008,18 @@ __lpfc_sli_release_iocbq_s4(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
else else
sglq = __lpfc_clear_active_sglq(phba, iocbq->sli4_lxritag); 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 (sglq) {
if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) && if ((iocbq->iocb_flag & LPFC_EXCHANGE_BUSY) &&
(sglq->state != SGL_XRI_ABORTED)) { (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); &phba->sli4_hba.lpfc_sgl_list);
/* Check if TXQ queue needs to be serviced */ /* Check if TXQ queue needs to be serviced */
if (pring->txq_cnt) if (!list_empty(&pring->txq))
lpfc_worker_wake_up(phba); lpfc_worker_wake_up(phba);
} }
} }
@ -1055,6 +1067,14 @@ __lpfc_sli_release_iocbq_s3(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
{ {
size_t start_clean = offsetof(struct lpfc_iocbq, iocb); 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. * Clean all volatile data fields, preserve iotag and node struct.
*/ */
@ -1121,7 +1141,6 @@ lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist,
while (!list_empty(iocblist)) { while (!list_empty(iocblist)) {
list_remove_head(iocblist, piocb, struct lpfc_iocbq, list); list_remove_head(iocblist, piocb, struct lpfc_iocbq, list);
if (!piocb->iocb_cmpl) if (!piocb->iocb_cmpl)
lpfc_sli_release_iocbq(phba, piocb); lpfc_sli_release_iocbq(phba, piocb);
else { 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); list_add_tail(&piocb->list, &pring->txcmplq);
piocb->iocb_flag |= LPFC_IO_ON_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)) && if ((unlikely(pring->ringno == LPFC_ELS_RING)) &&
(piocb->iocb.ulpCommand != CMD_ABORT_XRI_CN) && (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; struct lpfc_iocbq *cmd_iocb;
list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list); list_remove_head((&pring->txq), cmd_iocb, struct lpfc_iocbq, list);
if (cmd_iocb != NULL)
pring->txq_cnt--;
return cmd_iocb; 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) * (c) link attention events can be processed (fcp ring only)
* (d) IOCB processing is not blocked by the outstanding mbox command. * (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 || (pring->ringno != phba->sli.fcp_ring ||
phba->sli.sli_flag & LPFC_PROCESS_LA)) { 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]; cmd_iocb = phba->sli.iocbq_lookup[iotag];
list_del_init(&cmd_iocb->list); list_del_init(&cmd_iocb->list);
if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) { if (cmd_iocb->iocb_flag & LPFC_IO_ON_TXCMPLQ) {
pring->txcmplq_cnt--;
cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
} }
return cmd_iocb; return cmd_iocb;
@ -2649,7 +2663,6 @@ lpfc_sli_iocbq_lookup_by_tag(struct lpfc_hba *phba,
/* remove from txcmpl queue list */ /* remove from txcmpl queue list */
list_del_init(&cmd_iocb->list); list_del_init(&cmd_iocb->list);
cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ; cmd_iocb->iocb_flag &= ~LPFC_IO_ON_TXCMPLQ;
pring->txcmplq_cnt--;
return cmd_iocb; 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); spin_lock_irq(&phba->hbalock);
list_splice_init(&pring->txq, &completions); list_splice_init(&pring->txq, &completions);
pring->txq_cnt = 0;
/* Next issue ABTS for everything on the txcmplq */ /* Next issue ABTS for everything on the txcmplq */
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) 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); spin_lock_irq(&phba->hbalock);
/* Retrieve everything on txq */ /* Retrieve everything on txq */
list_splice_init(&pring->txq, &txq); list_splice_init(&pring->txq, &txq);
pring->txq_cnt = 0;
/* Retrieve everything on the txcmplq */ /* Retrieve everything on the txcmplq */
list_splice_init(&pring->txcmplq, &txcmplq); list_splice_init(&pring->txcmplq, &txcmplq);
pring->txcmplq_cnt = 0;
/* Indicate the I/O queues are flushed */ /* Indicate the I/O queues are flushed */
phba->hba_flag |= HBA_FCP_IOQ_FLUSH; 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. */ /* Insert the caller's iocb in the txq tail for later processing. */
list_add_tail(&piocb->list, &pring->txq); 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) piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
sglq = NULL; sglq = NULL;
else { else {
if (pring->txq_cnt) { if (!list_empty(&pring->txq)) {
if (!(flag & SLI_IOCB_RET_IOCB)) { if (!(flag & SLI_IOCB_RET_IOCB)) {
__lpfc_sli_ringtx_put(phba, __lpfc_sli_ringtx_put(phba,
pring, piocb); pring, piocb);
@ -9054,7 +9063,6 @@ lpfc_sli_host_down(struct lpfc_vport *vport)
if (iocb->vport != vport) if (iocb->vport != vport)
continue; continue;
list_move_tail(&iocb->list, &completions); list_move_tail(&iocb->list, &completions);
pring->txq_cnt--;
} }
/* Next issue ABTS for everything on the txcmplq */ /* 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. * given to the FW yet.
*/ */
list_splice_init(&pring->txq, &completions); list_splice_init(&pring->txq, &completions);
pring->txq_cnt = 0;
} }
spin_unlock_irqrestore(&phba->hbalock, flags); spin_unlock_irqrestore(&phba->hbalock, flags);
@ -9965,6 +9971,9 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba *phba,
long timeleft, timeout_req = 0; long timeleft, timeout_req = 0;
int retval = IOCB_SUCCESS; int retval = IOCB_SUCCESS;
uint32_t creg_val; 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]; struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
/* /*
* If the caller has provided a response iocbq buffer, then context2 * 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; retval = IOCB_TIMEDOUT;
} }
} else if (retval == IOCB_BUSY) { } else if (retval == IOCB_BUSY) {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI, if (phba->cfg_log_verbose & LOG_SLI) {
"2818 Max IOCBs %d txq cnt %d txcmplq cnt %d\n", list_for_each_entry(iocb, &pring->txq, list) {
phba->iocb_cnt, pring->txq_cnt, pring->txcmplq_cnt); 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; return retval;
} else { } else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI, 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; struct lpfc_iocbq *irspiocbq;
unsigned long iflags; unsigned long iflags;
struct lpfc_sli_ring *pring = cq->pring; 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 */ /* Get an irspiocbq for later ELS response processing use */
irspiocbq = lpfc_sli_get_iocbq(phba); irspiocbq = lpfc_sli_get_iocbq(phba);
if (!irspiocbq) { 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, lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d " "0387 NO IOCBQ data: txq_cnt=%d iocb_cnt=%d "
"fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n", "fcp_txcmplq_cnt=%d, els_txcmplq_cnt=%d\n",
pring->txq_cnt, phba->iocb_cnt, txq_cnt, phba->iocb_cnt,
phba->sli.ring[LPFC_FCP_RING].txcmplq_cnt, fcp_txcmplq_cnt,
phba->sli.ring[LPFC_ELS_RING].txcmplq_cnt); txcmplq_cnt);
return false; return false;
} }
@ -16244,14 +16270,19 @@ lpfc_drain_txq(struct lpfc_hba *phba)
char *fail_msg = NULL; char *fail_msg = NULL;
struct lpfc_sglq *sglq; struct lpfc_sglq *sglq;
union lpfc_wqe wqe; union lpfc_wqe wqe;
int txq_cnt = 0;
spin_lock_irqsave(&phba->hbalock, iflags); spin_lock_irqsave(&phba->hbalock, iflags);
if (pring->txq_cnt > pring->txq_max) list_for_each_entry(piocbq, &pring->txq, list) {
pring->txq_max = pring->txq_cnt; txq_cnt++;
}
if (txq_cnt > pring->txq_max)
pring->txq_max = txq_cnt;
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
while (pring->txq_cnt) { while (!list_empty(&pring->txq)) {
spin_lock_irqsave(&phba->hbalock, iflags); spin_lock_irqsave(&phba->hbalock, iflags);
piocbq = lpfc_sli_ringtx_get(phba, pring); piocbq = lpfc_sli_ringtx_get(phba, pring);
@ -16259,7 +16290,7 @@ lpfc_drain_txq(struct lpfc_hba *phba)
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
lpfc_printf_log(phba, KERN_ERR, LOG_SLI, lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
"2823 txq empty and txq_cnt is %d\n ", "2823 txq empty and txq_cnt is %d\n ",
pring->txq_cnt); txq_cnt);
break; break;
} }
sglq = __lpfc_sli_get_sglq(phba, piocbq); sglq = __lpfc_sli_get_sglq(phba, piocbq);
@ -16268,6 +16299,7 @@ lpfc_drain_txq(struct lpfc_hba *phba)
spin_unlock_irqrestore(&phba->hbalock, iflags); spin_unlock_irqrestore(&phba->hbalock, iflags);
break; break;
} }
txq_cnt--;
/* The xri and iocb resources secured, /* The xri and iocb resources secured,
* attempt to issue request * attempt to issue request
@ -16299,5 +16331,5 @@ lpfc_drain_txq(struct lpfc_hba *phba)
lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT, lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
IOERR_SLI_ABORTED); IOERR_SLI_ABORTED);
return pring->txq_cnt; return txq_cnt;
} }