scsi: lpfc: Fix MDS diagnostics failure (Rx < Tx)
authorJames Smart <jsmart2021@gmail.com>
Fri, 25 May 2018 04:08:57 +0000 (21:08 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 29 May 2018 02:40:32 +0000 (22:40 -0400)
MDS diagnostics fail because of frame count mismatch.

Unavailability of SGL is the trigger for this issue. If ELS SGL is not
available to process MDS frame, IOCB is put in FCP txq but not attempted to
post afterwards. So, driver stops processing incoming frames as it runs out
of IOCB.  lpfc_drain_txq attempts to submit IOCBS that are queued in ELS
txq but MDS frames are posted to FCP WQ.

Attempt to submit IOCBs that are present in FCP txq when MDS loopback is
running.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <james.smart@broadcom.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/lpfc/lpfc_sli.c

index cf2cbaa241b9e442f180a65d0f5c03d0567ef1ff..2fef54fab86d4450ecaa08a38577487899b7f46b 100644 (file)
@@ -708,8 +708,7 @@ lpfc_work_done(struct lpfc_hba *phba)
                                                                HA_RXMASK));
                        }
                }
-               if ((phba->sli_rev == LPFC_SLI_REV4) &&
-                                (!list_empty(&pring->txq)))
+               if (phba->sli_rev == LPFC_SLI_REV4)
                        lpfc_drain_txq(phba);
                /*
                 * Turn on Ring interrupts
index 6b709cd4140bac4ae9353b4ef2451728370c2bff..4b70d53acb7204d542a45108ef99bc237726ef53 100644 (file)
@@ -19069,9 +19069,22 @@ lpfc_drain_txq(struct lpfc_hba *phba)
        struct lpfc_sglq *sglq;
        union lpfc_wqe128 wqe;
        uint32_t txq_cnt = 0;
+       struct lpfc_queue *wq;
 
-       pring = lpfc_phba_elsring(phba);
-       if (unlikely(!pring))
+       if (phba->link_flag & LS_MDS_LOOPBACK) {
+               /* MDS WQE are posted only to first WQ*/
+               wq = phba->sli4_hba.fcp_wq[0];
+               if (unlikely(!wq))
+                       return 0;
+               pring = wq->pring;
+       } else {
+               wq = phba->sli4_hba.els_wq;
+               if (unlikely(!wq))
+                       return 0;
+               pring = lpfc_phba_elsring(phba);
+       }
+
+       if (unlikely(!pring) || list_empty(&pring->txq))
                return 0;
 
        spin_lock_irqsave(&pring->ring_lock, iflags);
@@ -19112,7 +19125,7 @@ lpfc_drain_txq(struct lpfc_hba *phba)
                        fail_msg = "to convert bpl to sgl";
                else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe))
                        fail_msg = "to convert iocb to wqe";
-               else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe))
+               else if (lpfc_sli4_wq_put(wq, &wqe))
                        fail_msg = " - Wq is full";
                else
                        lpfc_sli_ringtxcmpl_put(phba, pring, piocbq);