aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h14
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c28
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c65
6 files changed, 103 insertions, 25 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 64d6e3399a68..69da16d63a01 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -695,7 +695,8 @@ struct lpfc_hba {
695 uint8_t wwnn[8]; 695 uint8_t wwnn[8];
696 uint8_t wwpn[8]; 696 uint8_t wwpn[8];
697 uint32_t RandomData[7]; 697 uint32_t RandomData[7];
698 uint32_t fcp_embed_io; 698 uint8_t fcp_embed_io;
699 uint8_t mds_diags_support;
699 700
700 /* HBA Config Parameters */ 701 /* HBA Config Parameters */
701 uint32_t cfg_ack0; 702 uint32_t cfg_ack0;
@@ -760,6 +761,7 @@ struct lpfc_hba {
760#define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */ 761#define LPFC_FDMI_NO_SUPPORT 0 /* FDMI not supported */
761#define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */ 762#define LPFC_FDMI_SUPPORT 1 /* FDMI supported? */
762 uint32_t cfg_enable_SmartSAN; 763 uint32_t cfg_enable_SmartSAN;
764 uint32_t cfg_enable_mds_diags;
763 lpfc_vpd_t vpd; /* vital product data */ 765 lpfc_vpd_t vpd; /* vital product data */
764 766
765 struct pci_dev *pcidev; 767 struct pci_dev *pcidev;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index cfec2eca4dd3..cde7da6af2ea 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -4780,6 +4780,14 @@ LPFC_ATTR_R(prot_sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT,
4780 LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT, 4780 LPFC_DEFAULT_SG_SEG_CNT, LPFC_MAX_SG_SEG_CNT,
4781 "Max Protection Scatter Gather Segment Count"); 4781 "Max Protection Scatter Gather Segment Count");
4782 4782
4783/*
4784 * lpfc_enable_mds_diags: Enable MDS Diagnostics
4785 * 0 = MDS Diagnostics disabled (default)
4786 * 1 = MDS Diagnostics enabled
4787 * Value range is [0,1]. Default value is 0.
4788 */
4789LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
4790
4783struct device_attribute *lpfc_hba_attrs[] = { 4791struct device_attribute *lpfc_hba_attrs[] = {
4784 &dev_attr_bg_info, 4792 &dev_attr_bg_info,
4785 &dev_attr_bg_guard_err, 4793 &dev_attr_bg_guard_err,
@@ -4876,6 +4884,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
4876 &dev_attr_lpfc_sriov_hw_max_virtfn, 4884 &dev_attr_lpfc_sriov_hw_max_virtfn,
4877 &dev_attr_protocol, 4885 &dev_attr_protocol,
4878 &dev_attr_lpfc_xlane_supported, 4886 &dev_attr_lpfc_xlane_supported,
4887 &dev_attr_lpfc_enable_mds_diags,
4879 NULL, 4888 NULL,
4880}; 4889};
4881 4890
@@ -5867,6 +5876,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
5867 lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up); 5876 lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
5868 lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt); 5877 lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
5869 phba->cfg_enable_dss = 1; 5878 phba->cfg_enable_dss = 1;
5879 lpfc_enable_mds_diags_init(phba, lpfc_enable_mds_diags);
5870 return; 5880 return;
5871} 5881}
5872 5882
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 861270edd84a..5afbf4d06d53 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3299,6 +3299,12 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
3299 FC_VPORT_FABRIC_REJ_WWN); 3299 FC_VPORT_FABRIC_REJ_WWN);
3300 } 3300 }
3301 break; 3301 break;
3302 case LSRJT_VENDOR_UNIQUE:
3303 if ((stat.un.b.vendorUnique == 0x45) &&
3304 (cmd == ELS_CMD_FLOGI)) {
3305 goto out_retry;
3306 }
3307 break;
3302 } 3308 }
3303 break; 3309 break;
3304 3310
@@ -3344,6 +3350,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
3344 if ((vport->load_flag & FC_UNLOADING) != 0) 3350 if ((vport->load_flag & FC_UNLOADING) != 0)
3345 retry = 0; 3351 retry = 0;
3346 3352
3353out_retry:
3347 if (retry) { 3354 if (retry) {
3348 if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) { 3355 if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_FDISC)) {
3349 /* Stop retrying PLOGI and FDISC if in FCF discovery */ 3356 /* Stop retrying PLOGI and FDISC if in FCF discovery */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 8738b3dc87f1..ee8022737591 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -2888,9 +2888,13 @@ struct lpfc_sli4_parameters {
2888#define cfg_ext_embed_cb_SHIFT 0 2888#define cfg_ext_embed_cb_SHIFT 0
2889#define cfg_ext_embed_cb_MASK 0x00000001 2889#define cfg_ext_embed_cb_MASK 0x00000001
2890#define cfg_ext_embed_cb_WORD word19 2890#define cfg_ext_embed_cb_WORD word19
2891#define cfg_mds_diags_SHIFT 1
2892#define cfg_mds_diags_MASK 0x00000001
2893#define cfg_mds_diags_WORD word19
2891}; 2894};
2892 2895
2893#define LPFC_SET_UE_RECOVERY 0x10 2896#define LPFC_SET_UE_RECOVERY 0x10
2897#define LPFC_SET_MDS_DIAGS 0x11
2894struct lpfc_mbx_set_feature { 2898struct lpfc_mbx_set_feature {
2895 struct mbox_header header; 2899 struct mbox_header header;
2896 uint32_t feature; 2900 uint32_t feature;
@@ -2899,6 +2903,12 @@ struct lpfc_mbx_set_feature {
2899#define lpfc_mbx_set_feature_UER_SHIFT 0 2903#define lpfc_mbx_set_feature_UER_SHIFT 0
2900#define lpfc_mbx_set_feature_UER_MASK 0x00000001 2904#define lpfc_mbx_set_feature_UER_MASK 0x00000001
2901#define lpfc_mbx_set_feature_UER_WORD word6 2905#define lpfc_mbx_set_feature_UER_WORD word6
2906#define lpfc_mbx_set_feature_mds_SHIFT 0
2907#define lpfc_mbx_set_feature_mds_MASK 0x00000001
2908#define lpfc_mbx_set_feature_mds_WORD word6
2909#define lpfc_mbx_set_feature_mds_deep_loopbk_SHIFT 1
2910#define lpfc_mbx_set_feature_mds_deep_loopbk_MASK 0x00000001
2911#define lpfc_mbx_set_feature_mds_deep_loopbk_WORD word6
2902 uint32_t word7; 2912 uint32_t word7;
2903#define lpfc_mbx_set_feature_UERP_SHIFT 0 2913#define lpfc_mbx_set_feature_UERP_SHIFT 0
2904#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff 2914#define lpfc_mbx_set_feature_UERP_MASK 0x0000ffff
@@ -3464,6 +3474,8 @@ struct lpfc_acqe_fc_la {
3464#define LPFC_FC_LA_TYPE_LINK_UP 0x1 3474#define LPFC_FC_LA_TYPE_LINK_UP 0x1
3465#define LPFC_FC_LA_TYPE_LINK_DOWN 0x2 3475#define LPFC_FC_LA_TYPE_LINK_DOWN 0x2
3466#define LPFC_FC_LA_TYPE_NO_HARD_ALPA 0x3 3476#define LPFC_FC_LA_TYPE_NO_HARD_ALPA 0x3
3477#define LPFC_FC_LA_TYPE_MDS_LINK_DOWN 0x4
3478#define LPFC_FC_LA_TYPE_MDS_LOOPBACK 0x5
3467#define lpfc_acqe_fc_la_port_type_SHIFT 6 3479#define lpfc_acqe_fc_la_port_type_SHIFT 6
3468#define lpfc_acqe_fc_la_port_type_MASK 0x00000003 3480#define lpfc_acqe_fc_la_port_type_MASK 0x00000003
3469#define lpfc_acqe_fc_la_port_type_WORD word0 3481#define lpfc_acqe_fc_la_port_type_WORD word0
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index f11e33ee4132..bb514d2262cf 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -4040,6 +4040,8 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
4040{ 4040{
4041 struct lpfc_dmabuf *mp; 4041 struct lpfc_dmabuf *mp;
4042 LPFC_MBOXQ_t *pmb; 4042 LPFC_MBOXQ_t *pmb;
4043 MAILBOX_t *mb;
4044 struct lpfc_mbx_read_top *la;
4043 int rc; 4045 int rc;
4044 4046
4045 if (bf_get(lpfc_trailer_type, acqe_fc) != 4047 if (bf_get(lpfc_trailer_type, acqe_fc) !=
@@ -4110,6 +4112,24 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
4110 pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology; 4112 pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
4111 pmb->vport = phba->pport; 4113 pmb->vport = phba->pport;
4112 4114
4115 if (phba->sli4_hba.link_state.status != LPFC_FC_LA_TYPE_LINK_UP) {
4116 /* Parse and translate status field */
4117 mb = &pmb->u.mb;
4118 mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
4119 (void *)acqe_fc);
4120
4121 /* Parse and translate link attention fields */
4122 la = (struct lpfc_mbx_read_top *)&pmb->u.mb.un.varReadTop;
4123 la->eventTag = acqe_fc->event_tag;
4124 bf_set(lpfc_mbx_read_top_att_type, la,
4125 LPFC_FC_LA_TYPE_LINK_DOWN);
4126
4127 /* Invoke the mailbox command callback function */
4128 lpfc_mbx_cmpl_read_topology(phba, pmb);
4129
4130 return;
4131 }
4132
4113 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); 4133 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
4114 if (rc == MBX_NOT_FINISHED) 4134 if (rc == MBX_NOT_FINISHED)
4115 goto out_free_dmabuf; 4135 goto out_free_dmabuf;
@@ -9585,6 +9605,14 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
9585 phba->fcp_embed_io = 1; 9605 phba->fcp_embed_io = 1;
9586 else 9606 else
9587 phba->fcp_embed_io = 0; 9607 phba->fcp_embed_io = 0;
9608
9609 /*
9610 * Check if the SLI port supports MDS Diagnostics
9611 */
9612 if (bf_get(cfg_mds_diags, mbx_sli4_parameters))
9613 phba->mds_diags_support = 1;
9614 else
9615 phba->mds_diags_support = 0;
9588 return 0; 9616 return 0;
9589} 9617}
9590 9618
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index b3a781d38fa8..6eef9720e5c9 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5691,37 +5691,35 @@ lpfc_sli4_dealloc_extent(struct lpfc_hba *phba, uint16_t type)
5691} 5691}
5692 5692
5693void 5693void
5694lpfc_set_features(struct lpfc_hba *phba) 5694lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
5695 uint32_t feature)
5695{ 5696{
5696 LPFC_MBOXQ_t *mbox = NULL;
5697 uint32_t len; 5697 uint32_t len;
5698 int rc;
5699 5698
5700 mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
5701 if (!mbox)
5702 return;
5703 len = sizeof(struct lpfc_mbx_set_feature) - 5699 len = sizeof(struct lpfc_mbx_set_feature) -
5704 sizeof(struct lpfc_sli4_cfg_mhdr); 5700 sizeof(struct lpfc_sli4_cfg_mhdr);
5705 lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON, 5701 lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_COMMON,
5706 LPFC_MBOX_OPCODE_SET_FEATURES, len, 5702 LPFC_MBOX_OPCODE_SET_FEATURES, len,
5707 LPFC_SLI4_MBX_EMBED); 5703 LPFC_SLI4_MBX_EMBED);
5708 bf_set(lpfc_mbx_set_feature_UER,
5709 &mbox->u.mqe.un.set_feature, 1);
5710 mbox->u.mqe.un.set_feature.feature = LPFC_SET_UE_RECOVERY;
5711 mbox->u.mqe.un.set_feature.param_len = 8;
5712 rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
5713 5704
5714 if (rc != MBX_SUCCESS) { 5705 switch (feature) {
5715 mempool_free(mbox, phba->mbox_mem_pool); 5706 case LPFC_SET_UE_RECOVERY:
5716 return; 5707 bf_set(lpfc_mbx_set_feature_UER,
5708 &mbox->u.mqe.un.set_feature, 1);
5709 mbox->u.mqe.un.set_feature.feature = LPFC_SET_UE_RECOVERY;
5710 mbox->u.mqe.un.set_feature.param_len = 8;
5711 break;
5712 case LPFC_SET_MDS_DIAGS:
5713 bf_set(lpfc_mbx_set_feature_mds,
5714 &mbox->u.mqe.un.set_feature, 1);
5715 bf_set(lpfc_mbx_set_feature_mds_deep_loopbk,
5716 &mbox->u.mqe.un.set_feature, 0);
5717 mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
5718 mbox->u.mqe.un.set_feature.param_len = 8;
5719 break;
5717 } 5720 }
5718 phba->hba_flag |= HBA_RECOVERABLE_UE; 5721
5719 phba->eratt_poll_interval = 1; /* Set 1Sec interval to detect UE */ 5722 return;
5720 phba->sli4_hba.ue_to_sr = bf_get(lpfc_mbx_set_feature_UESR,
5721 &mbox->u.mqe.un.set_feature);
5722 phba->sli4_hba.ue_to_rp = bf_get(lpfc_mbx_set_feature_UERP,
5723 &mbox->u.mqe.un.set_feature);
5724 mempool_free(mbox, phba->mbox_mem_pool);
5725} 5723}
5726 5724
5727/** 5725/**
@@ -6449,8 +6447,29 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
6449 } 6447 }
6450 6448
6451 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) == 6449 if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
6452 LPFC_SLI_INTF_IF_TYPE_0) 6450 LPFC_SLI_INTF_IF_TYPE_0) {
6453 lpfc_set_features(phba); 6451 lpfc_set_features(phba, mboxq, LPFC_SET_UE_RECOVERY);
6452 rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
6453 if (rc == MBX_SUCCESS) {
6454 phba->hba_flag |= HBA_RECOVERABLE_UE;
6455 /* Set 1Sec interval to detect UE */
6456 phba->eratt_poll_interval = 1;
6457 phba->sli4_hba.ue_to_sr = bf_get(
6458 lpfc_mbx_set_feature_UESR,
6459 &mboxq->u.mqe.un.set_feature);
6460 phba->sli4_hba.ue_to_rp = bf_get(
6461 lpfc_mbx_set_feature_UERP,
6462 &mboxq->u.mqe.un.set_feature);
6463 }
6464 }
6465
6466 if (phba->cfg_enable_mds_diags && phba->mds_diags_support) {
6467 /* Enable MDS Diagnostics only if the SLI Port supports it */
6468 lpfc_set_features(phba, mboxq, LPFC_SET_MDS_DIAGS);
6469 rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
6470 if (rc != MBX_SUCCESS)
6471 phba->mds_diags_support = 0;
6472 }
6454 6473
6455 /* 6474 /*
6456 * Discover the port's supported feature set and match it against the 6475 * Discover the port's supported feature set and match it against the