[SCSI] lpfc 8.3.38: Fixed NMI watch dog panic's when resetting the hba.
authorJames Smart <james.smart@emulex.com>
Fri, 1 Mar 2013 21:35:12 +0000 (16:35 -0500)
committerJames Bottomley <JBottomley@Parallels.com>
Tue, 9 Apr 2013 21:21:58 +0000 (14:21 -0700)
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>
drivers/scsi/lpfc/lpfc_attr.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/lpfc/lpfc_sli.c

index a364cae..97921dc 100644 (file)
@@ -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,
index 32d5683..18d3b69 100644 (file)
@@ -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);
index 08d156a..b7a61ff 100644 (file)
@@ -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;
                }
index d7096ad..915e1aa 100644 (file)
@@ -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--;
                }
        }
 
index 314b4f6..b28f4e7 100644 (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.
                 */
                list_splice_init(&pring->txcmplq, &completions);
-               pring->txcmplq_cnt = 0;
                spin_unlock_irq(&phba->hbalock);
 
                /* Cancel all the IOCBs from the completions list */
index 46128c6..82f4d35 100644 (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)) {
                        /* It matches, so deque and call compl with anp error */
                        list_move_tail(&iocb->list, &completions);
-                       pring->txq_cnt--;
                }
        }
 
index 98af07c..e75210d 100644 (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->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);
 }
index 74b67d9..a0ef439 100644 (file)
@@ -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);
                }
        }
@@ -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);
 
+       /*
+       ** 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.
         */
@@ -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;
 }