summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Smart <jsmart2021@gmail.com>2019-08-14 19:57:10 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2019-08-19 22:41:12 -0400
commit0d8af096430ed810aacade5f564e5b98347137d4 (patch)
tree67867467394d4e4d794ace20ba7d822f9d61f8f9
parentd79c9e9d4b3d9330ee38f392a7c98e0fc494f7f8 (diff)
scsi: lpfc: Add NVMe sequence level error recovery support
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>
-rw-r--r--drivers/scsi/lpfc/lpfc.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_disc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c4
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h8
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c8
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c13
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c3
7 files changed, 38 insertions, 1 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index b738639fdf3f..c21d61ea82d9 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -797,6 +797,7 @@ struct lpfc_hba {
797 uint8_t mds_diags_support; 797 uint8_t mds_diags_support;
798 uint8_t bbcredit_support; 798 uint8_t bbcredit_support;
799 uint8_t enab_exp_wqcq_pages; 799 uint8_t enab_exp_wqcq_pages;
800 u8 nsler; /* Firmware supports FC-NVMe-2 SLER */
800 801
801 /* HBA Config Parameters */ 802 /* HBA Config Parameters */
802 uint32_t cfg_ack0; 803 uint32_t cfg_ack0;
diff --git a/drivers/scsi/lpfc/lpfc_disc.h b/drivers/scsi/lpfc/lpfc_disc.h
index 49bb0b180b19..482e4a888dae 100644
--- a/drivers/scsi/lpfc/lpfc_disc.h
+++ b/drivers/scsi/lpfc/lpfc_disc.h
@@ -112,6 +112,8 @@ struct lpfc_nodelist {
112 uint8_t nlp_retry; /* used for ELS retries */ 112 uint8_t nlp_retry; /* used for ELS retries */
113 uint8_t nlp_fcp_info; /* class info, bits 0-3 */ 113 uint8_t nlp_fcp_info; /* class info, bits 0-3 */
114#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */ 114#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */
115 u8 nlp_nvme_info; /* NVME NSLER Support */
116#define NLP_NVME_NSLER 0x1 /* NVME NSLER device */
115 117
116 uint16_t nlp_usg_map; /* ndlp management usage bitmap */ 118 uint16_t nlp_usg_map; /* ndlp management usage bitmap */
117#define NLP_USG_NODE_ACT_BIT 0x1 /* Indicate ndlp is actively used */ 119#define NLP_USG_NODE_ACT_BIT 0x1 /* Indicate ndlp is actively used */
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 30bbfa3f6086..d5303994bfd6 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -2435,6 +2435,10 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
2435 npr_nvme = (struct lpfc_nvme_prli *)pcmd; 2435 npr_nvme = (struct lpfc_nvme_prli *)pcmd;
2436 bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE); 2436 bf_set(prli_type_code, npr_nvme, PRLI_NVME_TYPE);
2437 bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */ 2437 bf_set(prli_estabImagePair, npr_nvme, 0); /* Should be 0 */
2438 if (phba->nsler) {
2439 bf_set(prli_nsler, npr_nvme, 1);
2440 bf_set(prli_conf, npr_nvme, 1);
2441 }
2438 2442
2439 /* Only initiators request first burst. */ 2443 /* Only initiators request first burst. */
2440 if ((phba->cfg_nvme_enable_fb) && 2444 if ((phba->cfg_nvme_enable_fb) &&
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index e198de8eda32..bd533475c86a 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -3480,6 +3480,10 @@ struct lpfc_sli4_parameters {
3480#define cfg_bv1s_MASK 0x00000001 3480#define cfg_bv1s_MASK 0x00000001
3481#define cfg_bv1s_WORD word19 3481#define cfg_bv1s_WORD word19
3482 3482
3483#define cfg_nsler_SHIFT 12
3484#define cfg_nsler_MASK 0x00000001
3485#define cfg_nsler_WORD word19
3486
3483 uint32_t word20; 3487 uint32_t word20;
3484#define cfg_max_tow_xri_SHIFT 0 3488#define cfg_max_tow_xri_SHIFT 0
3485#define cfg_max_tow_xri_MASK 0x0000ffff 3489#define cfg_max_tow_xri_MASK 0x0000ffff
@@ -4621,6 +4625,7 @@ struct lpfc_nvme_prli {
4621#define prli_type_code_WORD word1 4625#define prli_type_code_WORD word1
4622 uint32_t word_rsvd2; 4626 uint32_t word_rsvd2;
4623 uint32_t word_rsvd3; 4627 uint32_t word_rsvd3;
4628
4624 uint32_t word4; 4629 uint32_t word4;
4625#define prli_fba_SHIFT 0 4630#define prli_fba_SHIFT 0
4626#define prli_fba_MASK 0x00000001 4631#define prli_fba_MASK 0x00000001
@@ -4637,6 +4642,9 @@ struct lpfc_nvme_prli {
4637#define prli_conf_SHIFT 7 4642#define prli_conf_SHIFT 7
4638#define prli_conf_MASK 0x00000001 4643#define prli_conf_MASK 0x00000001
4639#define prli_conf_WORD word4 4644#define prli_conf_WORD word4
4645#define prli_nsler_SHIFT 8
4646#define prli_nsler_MASK 0x00000001
4647#define prli_nsler_WORD word4
4640 uint32_t word5; 4648 uint32_t word5;
4641#define prli_fb_sz_SHIFT 0 4649#define prli_fb_sz_SHIFT 0
4642#define prli_fb_sz_MASK 0x0000ffff 4650#define prli_fb_sz_MASK 0x0000ffff
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index fa3741f12089..d71f1b066e30 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -11846,6 +11846,14 @@ fcponly:
11846 else 11846 else
11847 phba->mds_diags_support = 0; 11847 phba->mds_diags_support = 0;
11848 11848
11849 /*
11850 * Check if the SLI port supports NSLER
11851 */
11852 if (bf_get(cfg_nsler, mbx_sli4_parameters))
11853 phba->nsler = 1;
11854 else
11855 phba->nsler = 0;
11856
11849 return 0; 11857 return 0;
11850} 11858}
11851 11859
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 41ac07b99739..f4b879d25fe9 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -799,9 +799,15 @@ lpfc_rcv_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
799 if (npr->writeXferRdyDis) 799 if (npr->writeXferRdyDis)
800 ndlp->nlp_flag |= NLP_FIRSTBURST; 800 ndlp->nlp_flag |= NLP_FIRSTBURST;
801 } 801 }
802 if (npr->Retry) 802 if (npr->Retry && ndlp->nlp_type &
803 (NLP_FCP_INITIATOR | NLP_FCP_TARGET))
803 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE; 804 ndlp->nlp_fcp_info |= NLP_FCP_2_DEVICE;
804 805
806 if (npr->Retry && phba->nsler &&
807 ndlp->nlp_type & (NLP_NVME_INITIATOR | NLP_NVME_TARGET))
808 ndlp->nlp_nvme_info |= NLP_NVME_NSLER;
809
810
805 /* If this driver is in nvme target mode, set the ndlp's fc4 811 /* If this driver is in nvme target mode, set the ndlp's fc4
806 * type to NVME provided the PRLI response claims NVME FC4 812 * type to NVME provided the PRLI response claims NVME FC4
807 * type. Target mode does not issue gft_id so doesn't get 813 * 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,
2024 if (bf_get_be32(prli_init, nvpr)) 2030 if (bf_get_be32(prli_init, nvpr))
2025 ndlp->nlp_type |= NLP_NVME_INITIATOR; 2031 ndlp->nlp_type |= NLP_NVME_INITIATOR;
2026 2032
2033 if (phba->nsler && bf_get_be32(prli_nsler, nvpr))
2034 ndlp->nlp_nvme_info |= NLP_NVME_NSLER;
2035 else
2036 ndlp->nlp_nvme_info &= ~NLP_NVME_NSLER;
2037
2027 /* Target driver cannot solicit NVME FB. */ 2038 /* Target driver cannot solicit NVME FB. */
2028 if (bf_get_be32(prli_tgt, nvpr)) { 2039 if (bf_get_be32(prli_tgt, nvpr)) {
2029 /* Complete the nvme target roles. The transport 2040 /* Complete the nvme target roles. The transport
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 5e48318eb7a9..f66859d928ac 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1255,6 +1255,9 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
1255 sizeof(uint32_t) * 8); 1255 sizeof(uint32_t) * 8);
1256 cstat->control_requests++; 1256 cstat->control_requests++;
1257 } 1257 }
1258
1259 if (pnode->nlp_nvme_info & NLP_NVME_NSLER)
1260 bf_set(wqe_erp, &wqe->generic.wqe_com, 1);
1258 /* 1261 /*
1259 * Finish initializing those WQE fields that are independent 1262 * Finish initializing those WQE fields that are independent
1260 * of the nvme_cmnd request_buffer 1263 * of the nvme_cmnd request_buffer