]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
scsi: lpfc: Add NVMe sequence level error recovery support
authorJames Smart <jsmart2021@gmail.com>
Wed, 14 Aug 2019 23:57:10 +0000 (16:57 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 20 Aug 2019 02:41:12 +0000 (22:41 -0400)
FC-NVMe-2 added support for sequence level error recovery in the FC-NVME
protocol. This allows for the detection of errors and lost frames and
immediate retransmission of data to avoid exchange termination, which
escalates into NVMeoFC connection and association failures. A significant
RAS improvement.

The driver is modified to indicate support for SLER in the NVMe PRLI is
issues and to check for support in the PRLI response.  When both sides
support it, the driver will set a bit in the WQE to enable the recovery
behavior on the exchange. The adapter will take care of all detection and
retransmission.

Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_disc.h
drivers/scsi/lpfc/lpfc_els.c
drivers/scsi/lpfc/lpfc_hw4.h
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nportdisc.c
drivers/scsi/lpfc/lpfc_nvme.c

index b738639fdf3f78a16ecadcdd78c899cda1dfada1..c21d61ea82d959060290b16f519683674ebee242 100644 (file)
@@ -797,6 +797,7 @@ struct lpfc_hba {
        uint8_t  mds_diags_support;
        uint8_t  bbcredit_support;
        uint8_t  enab_exp_wqcq_pages;
+       u8       nsler; /* Firmware supports FC-NVMe-2 SLER */
 
        /* HBA Config Parameters */
        uint32_t cfg_ack0;
index 49bb0b180b19017ac27193eb254d0fc17db229d0..482e4a888daeca09ef3c4f7f3bd9f5537d546890 100644 (file)
@@ -112,6 +112,8 @@ struct lpfc_nodelist {
        uint8_t         nlp_retry;              /* used for ELS retries */
        uint8_t         nlp_fcp_info;           /* class info, bits 0-3 */
 #define NLP_FCP_2_DEVICE   0x10                        /* FCP-2 device */
+       u8              nlp_nvme_info;          /* NVME NSLER Support */
+#define NLP_NVME_NSLER     0x1                 /* NVME NSLER device */
 
        uint16_t        nlp_usg_map;    /* ndlp management usage bitmap */
 #define NLP_USG_NODE_ACT_BIT   0x1     /* Indicate ndlp is actively used */
index 30bbfa3f6086de4bf70f5658a26d9f6ff2fa7503..d5303994bfd62e5c7e22496e3bb11c0c1fea4361 100644 (file)
@@ -2435,6 +2435,10 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                npr_nvme = (struct lpfc_nvme_prli *)pcmd;
                bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE);
                bf_set(prli_estabImagePair, npr_nvme, 0);  /* Should be 0 */
+               if (phba->nsler) {
+                       bf_set(prli_nsler, npr_nvme, 1);
+                       bf_set(prli_conf, npr_nvme, 1);
+               }
 
                /* Only initiators request first burst. */
                if ((phba->cfg_nvme_enable_fb) &&
index e198de8eda32fd58b6c3f47e305c25ca3c2d046d..bd533475c86a4aae92f7de67d84ad3f83a86e804 100644 (file)
@@ -3480,6 +3480,10 @@ struct lpfc_sli4_parameters {
 #define cfg_bv1s_MASK                           0x00000001
 #define cfg_bv1s_WORD                           word19
 
+#define cfg_nsler_SHIFT                         12
+#define cfg_nsler_MASK                          0x00000001
+#define cfg_nsler_WORD                          word19
+
        uint32_t word20;
 #define cfg_max_tow_xri_SHIFT                  0
 #define cfg_max_tow_xri_MASK                   0x0000ffff
@@ -4621,6 +4625,7 @@ struct lpfc_nvme_prli {
 #define prli_type_code_WORD             word1
        uint32_t word_rsvd2;
        uint32_t word_rsvd3;
+
        uint32_t word4;
 #define prli_fba_SHIFT                  0
 #define prli_fba_MASK                   0x00000001
@@ -4637,6 +4642,9 @@ struct lpfc_nvme_prli {
 #define prli_conf_SHIFT                 7
 #define prli_conf_MASK                  0x00000001
 #define prli_conf_WORD                  word4
+#define prli_nsler_SHIFT               8
+#define prli_nsler_MASK                        0x00000001
+#define prli_nsler_WORD                        word4
        uint32_t word5;
 #define prli_fb_sz_SHIFT                0
 #define prli_fb_sz_MASK                 0x0000ffff
index fa3741f12089894e169d9b33eff6292abfeaf91f..d71f1b066e30bf70dae58d7d93d3e0c3d1f76c80 100644 (file)
@@ -11846,6 +11846,14 @@ fcponly:
        else
                phba->mds_diags_support = 0;
 
+       /*
+        * Check if the SLI port supports NSLER
+        */
+       if (bf_get(cfg_nsler, mbx_sli4_parameters))
+               phba->nsler = 1;
+       else
+               phba->nsler = 0;
+
        return 0;
 }
 
index 41ac07b99739ae147e1c1d9790602e8e85ceb5b7..f4b879d25fe9d33229d40a5ab5675577b539c45a 100644 (file)
@@ -799,9 +799,15 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                        if (npr->writeXferRdyDis)
                                ndlp->nlp_flag |= NLP_FIRSTBURST;
                }
-               if (npr->Retry)
+               if (npr->Retry && ndlp->nlp_type &
+                                       (NLP_FCP_INITIATOR | NLP_FCP_TARGET))
                        ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
 
+               if (npr->Retry && phba->nsler &&
+                   ndlp->nlp_type & (NLP_NVME_INITIATOR | NLP_NVME_TARGET))
+                       ndlp->nlp_nvme_info |= NLP_NVME_NSLER;
+
+
                /* If this driver is in nvme target mode, set the ndlp's fc4
                 * type to NVME provided the PRLI response claims NVME FC4
                 * type.  Target mode does not issue gft_id so doesn't get
@@ -2024,6 +2030,11 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                if (bf_get_be32(prli_init, nvpr))
                        ndlp->nlp_type |= NLP_NVME_INITIATOR;
 
+               if (phba->nsler && bf_get_be32(prli_nsler, nvpr))
+                       ndlp->nlp_nvme_info |= NLP_NVME_NSLER;
+               else
+                       ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;
+
                /* Target driver cannot solicit NVME FB. */
                if (bf_get_be32(prli_tgt, nvpr)) {
                        /* Complete the nvme target roles.  The transport
index 5e48318eb7a9649f337899a7da3ac28777ce2274..f66859d928ac578193b7571a0d76f3263308f660 100644 (file)
@@ -1255,6 +1255,9 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
                       sizeof(uint32_t) * 8);
                cstat->control_requests++;
        }
+
+       if (pnode->nlp_nvme_info & NLP_NVME_NSLER)
+               bf_set(wqe_erp, &wqe->generic.wqe_com, 1);
        /*
         * Finish initializing those WQE fields that are independent
         * of the nvme_cmnd request_buffer