scsi: lpfc: Add new RCQE status for handling DMA failures
authorJustin Tee <justin.tee@broadcom.com>
Mon, 17 Apr 2023 19:15:56 +0000 (12:15 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 8 May 2023 11:16:05 +0000 (07:16 -0400)
A new RCQE status value indicating DMA failure when transferring
asynchronously received data to an RQE is introduced.  Such errors are
unexpected and handlers are updated to log KERN_ERR and dump lpfc's debug
trace buffer to kmsg.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20230417191558.83100-6-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_sli.c

index a428116..082f8a1 100644 (file)
@@ -536,9 +536,9 @@ struct sli4_wcqe_xri_aborted {
 /* completion queue entry structure for rqe completion */
 struct lpfc_rcqe {
        uint32_t word0;
-#define lpfc_rcqe_bindex_SHIFT         16
-#define lpfc_rcqe_bindex_MASK          0x0000FFF
-#define lpfc_rcqe_bindex_WORD          word0
+#define lpfc_rcqe_iv_SHIFT             31
+#define lpfc_rcqe_iv_MASK              0x00000001
+#define lpfc_rcqe_iv_WORD              word0
 #define lpfc_rcqe_status_SHIFT         8
 #define lpfc_rcqe_status_MASK          0x000000FF
 #define lpfc_rcqe_status_WORD          word0
@@ -546,6 +546,7 @@ struct lpfc_rcqe {
 #define FC_STATUS_RQ_BUF_LEN_EXCEEDED  0x11 /* payload truncated */
 #define FC_STATUS_INSUFF_BUF_NEED_BUF  0x12 /* Insufficient buffers */
 #define FC_STATUS_INSUFF_BUF_FRM_DISC  0x13 /* Frame Discard */
+#define FC_STATUS_RQ_DMA_FAILURE       0x14 /* DMA failure */
        uint32_t word1;
 #define lpfc_rcqe_fcf_id_v1_SHIFT      0
 #define lpfc_rcqe_fcf_id_v1_MASK       0x0000003F
index 35b1d5d..5f979da 100644 (file)
@@ -14682,6 +14682,38 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
                spin_unlock_irqrestore(&phba->hbalock, iflags);
                workposted = true;
                break;
+       case FC_STATUS_RQ_DMA_FAILURE:
+               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+                               "2564 RQE DMA Error x%x, x%08x x%08x x%08x "
+                               "x%08x\n",
+                               status, rcqe->word0, rcqe->word1,
+                               rcqe->word2, rcqe->word3);
+
+               /* If IV set, no further recovery */
+               if (bf_get(lpfc_rcqe_iv, rcqe))
+                       break;
+
+               /* recycle consumed resource */
+               spin_lock_irqsave(&phba->hbalock, iflags);
+               lpfc_sli4_rq_release(hrq, drq);
+               dma_buf = lpfc_sli_hbqbuf_get(&phba->hbqs[0].hbq_buffer_list);
+               if (!dma_buf) {
+                       hrq->RQ_no_buf_found++;
+                       spin_unlock_irqrestore(&phba->hbalock, iflags);
+                       break;
+               }
+               hrq->RQ_rcv_buf++;
+               hrq->RQ_buf_posted--;
+               spin_unlock_irqrestore(&phba->hbalock, iflags);
+               lpfc_in_buf_free(phba, &dma_buf->dbuf);
+               break;
+       default:
+               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+                               "2565 Unexpected RQE Status x%x, w0-3 x%08x "
+                               "x%08x x%08x x%08x\n",
+                               status, rcqe->word0, rcqe->word1,
+                               rcqe->word2, rcqe->word3);
+               break;
        }
 out:
        return workposted;
@@ -15203,6 +15235,38 @@ drop:
                hrq->RQ_no_posted_buf++;
                /* Post more buffers if possible */
                break;
+       case FC_STATUS_RQ_DMA_FAILURE:
+               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+                               "2575 RQE DMA Error x%x, x%08x x%08x x%08x "
+                               "x%08x\n",
+                               status, rcqe->word0, rcqe->word1,
+                               rcqe->word2, rcqe->word3);
+
+               /* If IV set, no further recovery */
+               if (bf_get(lpfc_rcqe_iv, rcqe))
+                       break;
+
+               /* recycle consumed resource */
+               spin_lock_irqsave(&phba->hbalock, iflags);
+               lpfc_sli4_rq_release(hrq, drq);
+               dma_buf = lpfc_sli_rqbuf_get(phba, hrq);
+               if (!dma_buf) {
+                       hrq->RQ_no_buf_found++;
+                       spin_unlock_irqrestore(&phba->hbalock, iflags);
+                       break;
+               }
+               hrq->RQ_rcv_buf++;
+               hrq->RQ_buf_posted--;
+               spin_unlock_irqrestore(&phba->hbalock, iflags);
+               lpfc_rq_buf_free(phba, &dma_buf->hbuf);
+               break;
+       default:
+               lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+                               "2576 Unexpected RQE Status x%x, w0-3 x%08x "
+                               "x%08x x%08x x%08x\n",
+                               status, rcqe->word0, rcqe->word1,
+                               rcqe->word2, rcqe->word3);
+               break;
        }
 out:
        return workposted;