scsi: lpfc: Add Buffer to Buffer credit recovery support
Add Buffer to buffer credit recovery support to the driver. This is a negotiated feature with the peer that allows for both sides to detect dropped RRDY's and FC Frames and recover credit. Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <james.smart@broadcom.com> Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
d58734f05f
commit
44fd7fe3dd
|
@ -733,7 +733,6 @@ struct lpfc_hba {
|
|||
uint32_t fc_rttov; /* R_T_TOV timer value */
|
||||
uint32_t fc_altov; /* AL_TOV timer value */
|
||||
uint32_t fc_crtov; /* C_R_TOV timer value */
|
||||
uint32_t fc_citov; /* C_I_TOV timer value */
|
||||
|
||||
struct serv_parm fc_fabparam; /* fabric service parameters buffer */
|
||||
uint8_t alpa_map[128]; /* AL_PA map from READ_LA */
|
||||
|
@ -757,6 +756,7 @@ struct lpfc_hba {
|
|||
#define LPFC_NVMET_MAX_PORTS 32
|
||||
uint8_t mds_diags_support;
|
||||
uint32_t initial_imax;
|
||||
uint8_t bbcredit_support;
|
||||
|
||||
/* HBA Config Parameters */
|
||||
uint32_t cfg_ack0;
|
||||
|
@ -836,6 +836,7 @@ struct lpfc_hba {
|
|||
uint32_t cfg_enable_SmartSAN;
|
||||
uint32_t cfg_enable_mds_diags;
|
||||
uint32_t cfg_enable_fc4_type;
|
||||
uint32_t cfg_enable_bbcr; /*Enable BB Credit Recovery*/
|
||||
uint32_t cfg_xri_split;
|
||||
#define LPFC_ENABLE_FCP 1
|
||||
#define LPFC_ENABLE_NVME 2
|
||||
|
|
|
@ -1888,6 +1888,36 @@ static inline bool lpfc_rangecheck(uint val, uint min, uint max)
|
|||
return val >= min && val <= max;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_enable_bbcr_set: Sets an attribute value.
|
||||
* @phba: pointer the the adapter structure.
|
||||
* @val: integer attribute value.
|
||||
*
|
||||
* Description:
|
||||
* Validates the min and max values then sets the
|
||||
* adapter config field if in the valid range. prints error message
|
||||
* and does not set the parameter if invalid.
|
||||
*
|
||||
* Returns:
|
||||
* zero on success
|
||||
* -EINVAL if val is invalid
|
||||
*/
|
||||
static ssize_t
|
||||
lpfc_enable_bbcr_set(struct lpfc_hba *phba, uint val)
|
||||
{
|
||||
if (lpfc_rangecheck(val, 0, 1) && phba->sli_rev == LPFC_SLI_REV4) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"3068 %s_enable_bbcr changed from %d to %d\n",
|
||||
LPFC_DRIVER_NAME, phba->cfg_enable_bbcr, val);
|
||||
phba->cfg_enable_bbcr = val;
|
||||
return 0;
|
||||
}
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"0451 %s_enable_bbcr cannot set to %d, range is 0, 1\n",
|
||||
LPFC_DRIVER_NAME, val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_param_show - Return a cfg attribute value in decimal
|
||||
*
|
||||
|
@ -5111,6 +5141,14 @@ LPFC_ATTR_R(sg_seg_cnt, LPFC_DEFAULT_SG_SEG_CNT, LPFC_DEFAULT_SG_SEG_CNT,
|
|||
*/
|
||||
LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS Diagnostics");
|
||||
|
||||
/*
|
||||
* lpfc_enable_bbcr: Enable BB Credit Recovery
|
||||
* 0 = BB Credit Recovery disabled
|
||||
* 1 = BB Credit Recovery enabled (default)
|
||||
* Value range is [0,1]. Default value is 1.
|
||||
*/
|
||||
LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
|
||||
|
||||
struct device_attribute *lpfc_hba_attrs[] = {
|
||||
&dev_attr_nvme_info,
|
||||
&dev_attr_bg_info,
|
||||
|
@ -5218,6 +5256,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_protocol,
|
||||
&dev_attr_lpfc_xlane_supported,
|
||||
&dev_attr_lpfc_enable_mds_diags,
|
||||
&dev_attr_lpfc_enable_bbcr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -6229,11 +6268,13 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
lpfc_nvmet_fb_size_init(phba, lpfc_nvmet_fb_size);
|
||||
lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
|
||||
lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
|
||||
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
|
||||
|
||||
if (phba->sli_rev != LPFC_SLI_REV4) {
|
||||
/* NVME only supported on SLI4 */
|
||||
phba->nvmet_support = 0;
|
||||
phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
|
||||
phba->cfg_enable_bbcr = 0;
|
||||
} else {
|
||||
/* We MUST have FCP support */
|
||||
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_FCP))
|
||||
|
|
|
@ -46,6 +46,16 @@ lpfc_param_store(name)\
|
|||
static DEVICE_ATTR(lpfc_##name, S_IRUGO | S_IWUSR,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_BBCR_ATTR_RW(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, 0444);\
|
||||
MODULE_PARM_DESC(lpfc_##name, desc);\
|
||||
lpfc_param_show(name)\
|
||||
lpfc_param_init(name, defval, minval, maxval)\
|
||||
lpfc_param_store(name)\
|
||||
static DEVICE_ATTR(lpfc_##name, 0444 | 0644,\
|
||||
lpfc_##name##_show, lpfc_##name##_store)
|
||||
|
||||
#define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
|
||||
static uint lpfc_##name = defval;\
|
||||
module_param(lpfc_##name, uint, S_IRUGO);\
|
||||
|
|
|
@ -2033,6 +2033,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
|
|||
|
||||
sp->cmn.valid_vendor_ver_level = 0;
|
||||
memset(sp->un.vendorVersion, 0, sizeof(sp->un.vendorVersion));
|
||||
sp->cmn.bbRcvSizeMsb &= 0xF;
|
||||
|
||||
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
|
||||
"Issue PLOGI: did:x%x",
|
||||
|
@ -3456,8 +3457,18 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
|
|||
maxretry = 3;
|
||||
delay = 1000;
|
||||
retry = 1;
|
||||
break;
|
||||
} else if (cmd == ELS_CMD_FLOGI &&
|
||||
stat.un.b.lsRjtRsnCodeExp ==
|
||||
LSEXP_NOTHING_MORE) {
|
||||
vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf;
|
||||
retry = 1;
|
||||
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
|
||||
"0820 FLOGI Failed (x%x). "
|
||||
"BBCredit Not Supported\n",
|
||||
stat.un.lsRjtError);
|
||||
}
|
||||
break;
|
||||
|
||||
case LSRJT_PROTOCOL_ERR:
|
||||
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
|
||||
(cmd == ELS_CMD_FDISC) &&
|
||||
|
@ -4201,6 +4212,7 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
|
|||
sp->cmn.valid_vendor_ver_level = 0;
|
||||
memset(sp->un.vendorVersion, 0,
|
||||
sizeof(sp->un.vendorVersion));
|
||||
sp->cmn.bbRcvSizeMsb &= 0xF;
|
||||
|
||||
/* If our firmware supports this feature, convey that
|
||||
* info to the target using the vendor specific field.
|
||||
|
|
|
@ -1108,6 +1108,7 @@ void
|
|||
lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
||||
{
|
||||
struct lpfc_vport *vport = pmb->vport;
|
||||
uint8_t bbscn = 0;
|
||||
|
||||
if (pmb->u.mb.mbxStatus)
|
||||
goto out;
|
||||
|
@ -1134,10 +1135,17 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
|
|||
/* Start discovery by sending a FLOGI. port_state is identically
|
||||
* LPFC_FLOGI while waiting for FLOGI cmpl
|
||||
*/
|
||||
if (vport->port_state != LPFC_FLOGI)
|
||||
if (vport->port_state != LPFC_FLOGI) {
|
||||
if (phba->bbcredit_support && phba->cfg_enable_bbcr) {
|
||||
bbscn = bf_get(lpfc_bbscn_def,
|
||||
&phba->sli4_hba.bbscn_params);
|
||||
vport->fc_sparam.cmn.bbRcvSizeMsb &= 0xf;
|
||||
vport->fc_sparam.cmn.bbRcvSizeMsb |= (bbscn << 4);
|
||||
}
|
||||
lpfc_initial_flogi(vport);
|
||||
else if (vport->fc_flag & FC_PT2PT)
|
||||
} else if (vport->fc_flag & FC_PT2PT) {
|
||||
lpfc_disc_start(vport);
|
||||
}
|
||||
return;
|
||||
|
||||
out:
|
||||
|
|
|
@ -2293,15 +2293,27 @@ typedef struct {
|
|||
uint32_t rttov;
|
||||
uint32_t altov;
|
||||
uint32_t crtov;
|
||||
uint32_t citov;
|
||||
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t rsvd4:19;
|
||||
uint32_t cscn:1;
|
||||
uint32_t bbscn:4;
|
||||
uint32_t rsvd3:8;
|
||||
#else /* __LITTLE_ENDIAN_BITFIELD */
|
||||
uint32_t rsvd3:8;
|
||||
uint32_t bbscn:4;
|
||||
uint32_t cscn:1;
|
||||
uint32_t rsvd4:19;
|
||||
#endif
|
||||
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint32_t rrq_enable:1;
|
||||
uint32_t rrq_immed:1;
|
||||
uint32_t rsvd4:29;
|
||||
uint32_t rsvd5:29;
|
||||
uint32_t ack0_enable:1;
|
||||
#else /* __LITTLE_ENDIAN_BITFIELD */
|
||||
uint32_t ack0_enable:1;
|
||||
uint32_t rsvd4:29;
|
||||
uint32_t rsvd5:29;
|
||||
uint32_t rrq_immed:1;
|
||||
uint32_t rrq_enable:1;
|
||||
#endif
|
||||
|
|
|
@ -2217,9 +2217,15 @@ struct lpfc_mbx_reg_vfi {
|
|||
uint32_t e_d_tov;
|
||||
uint32_t r_a_tov;
|
||||
uint32_t word10;
|
||||
#define lpfc_reg_vfi_nport_id_SHIFT 0
|
||||
#define lpfc_reg_vfi_nport_id_MASK 0x00FFFFFF
|
||||
#define lpfc_reg_vfi_nport_id_WORD word10
|
||||
#define lpfc_reg_vfi_nport_id_SHIFT 0
|
||||
#define lpfc_reg_vfi_nport_id_MASK 0x00FFFFFF
|
||||
#define lpfc_reg_vfi_nport_id_WORD word10
|
||||
#define lpfc_reg_vfi_bbcr_SHIFT 27
|
||||
#define lpfc_reg_vfi_bbcr_MASK 0x00000001
|
||||
#define lpfc_reg_vfi_bbcr_WORD word10
|
||||
#define lpfc_reg_vfi_bbscn_SHIFT 28
|
||||
#define lpfc_reg_vfi_bbscn_MASK 0x0000000F
|
||||
#define lpfc_reg_vfi_bbscn_WORD word10
|
||||
};
|
||||
|
||||
struct lpfc_mbx_init_vpi {
|
||||
|
@ -2646,7 +2652,16 @@ struct lpfc_mbx_read_config {
|
|||
#define lpfc_mbx_rd_conf_link_speed_MASK 0x0000FFFF
|
||||
#define lpfc_mbx_rd_conf_link_speed_WORD word6
|
||||
uint32_t rsvd_7;
|
||||
uint32_t rsvd_8;
|
||||
uint32_t word8;
|
||||
#define lpfc_mbx_rd_conf_bbscn_min_SHIFT 0
|
||||
#define lpfc_mbx_rd_conf_bbscn_min_MASK 0x0000000F
|
||||
#define lpfc_mbx_rd_conf_bbscn_min_WORD word8
|
||||
#define lpfc_mbx_rd_conf_bbscn_max_SHIFT 4
|
||||
#define lpfc_mbx_rd_conf_bbscn_max_MASK 0x0000000F
|
||||
#define lpfc_mbx_rd_conf_bbscn_max_WORD word8
|
||||
#define lpfc_mbx_rd_conf_bbscn_def_SHIFT 8
|
||||
#define lpfc_mbx_rd_conf_bbscn_def_MASK 0x0000000F
|
||||
#define lpfc_mbx_rd_conf_bbscn_def_WORD word8
|
||||
uint32_t word9;
|
||||
#define lpfc_mbx_rd_conf_lmt_SHIFT 0
|
||||
#define lpfc_mbx_rd_conf_lmt_MASK 0x0000FFFF
|
||||
|
|
|
@ -7625,6 +7625,11 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
|
|||
lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
|
||||
"3082 Mailbox (x%x) returned ldv:x0\n",
|
||||
bf_get(lpfc_mqe_command, &pmb->u.mqe));
|
||||
if (bf_get(lpfc_mbx_rd_conf_bbscn_def, rd_config)) {
|
||||
phba->bbcredit_support = 1;
|
||||
phba->sli4_hba.bbscn_params.word0 = rd_config->word8;
|
||||
}
|
||||
|
||||
phba->sli4_hba.extents_in_use =
|
||||
bf_get(lpfc_mbx_rd_conf_extnts_inuse, rd_config);
|
||||
phba->sli4_hba.max_cfg_param.max_xri =
|
||||
|
|
|
@ -376,7 +376,12 @@ lpfc_config_link(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
|||
mb->un.varCfgLnk.rttov = phba->fc_rttov;
|
||||
mb->un.varCfgLnk.altov = phba->fc_altov;
|
||||
mb->un.varCfgLnk.crtov = phba->fc_crtov;
|
||||
mb->un.varCfgLnk.citov = phba->fc_citov;
|
||||
mb->un.varCfgLnk.cscn = 0;
|
||||
if (phba->bbcredit_support && phba->cfg_enable_bbcr) {
|
||||
mb->un.varCfgLnk.cscn = 1;
|
||||
mb->un.varCfgLnk.bbscn = bf_get(lpfc_bbscn_def,
|
||||
&phba->sli4_hba.bbscn_params);
|
||||
}
|
||||
|
||||
if (phba->cfg_ack0 && (phba->sli_rev < LPFC_SLI_REV4))
|
||||
mb->un.varCfgLnk.ack0_enable = 1;
|
||||
|
@ -2139,6 +2144,7 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
|
|||
{
|
||||
struct lpfc_mbx_reg_vfi *reg_vfi;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
uint8_t bbscn_fabric = 0, bbscn_max = 0, bbscn_def = 0;
|
||||
|
||||
memset(mbox, 0, sizeof(*mbox));
|
||||
reg_vfi = &mbox->u.mqe.un.reg_vfi;
|
||||
|
@ -2168,16 +2174,39 @@ lpfc_reg_vfi(struct lpfcMboxq *mbox, struct lpfc_vport *vport, dma_addr_t phys)
|
|||
bf_set(lpfc_reg_vfi_vp, reg_vfi, 0);
|
||||
bf_set(lpfc_reg_vfi_upd, reg_vfi, 1);
|
||||
}
|
||||
|
||||
bf_set(lpfc_reg_vfi_bbcr, reg_vfi, 0);
|
||||
bf_set(lpfc_reg_vfi_bbscn, reg_vfi, 0);
|
||||
bbscn_fabric = (phba->fc_fabparam.cmn.bbRcvSizeMsb >> 4) & 0xF;
|
||||
|
||||
if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
|
||||
bbscn_fabric != 0) {
|
||||
bbscn_max = bf_get(lpfc_bbscn_max,
|
||||
&phba->sli4_hba.bbscn_params);
|
||||
if (bbscn_fabric <= bbscn_max) {
|
||||
bbscn_def = bf_get(lpfc_bbscn_def,
|
||||
&phba->sli4_hba.bbscn_params);
|
||||
|
||||
if (bbscn_fabric > bbscn_def)
|
||||
bf_set(lpfc_reg_vfi_bbscn, reg_vfi,
|
||||
bbscn_fabric);
|
||||
else
|
||||
bf_set(lpfc_reg_vfi_bbscn, reg_vfi, bbscn_def);
|
||||
|
||||
bf_set(lpfc_reg_vfi_bbcr, reg_vfi, 1);
|
||||
}
|
||||
}
|
||||
lpfc_printf_vlog(vport, KERN_INFO, LOG_MBOX,
|
||||
"3134 Register VFI, mydid:x%x, fcfi:%d, "
|
||||
" vfi:%d, vpi:%d, fc_pname:%x%x fc_flag:x%x"
|
||||
" port_state:x%x topology chg:%d\n",
|
||||
" port_state:x%x topology chg:%d bbscn_fabric :%d\n",
|
||||
vport->fc_myDID,
|
||||
phba->fcf.fcfi,
|
||||
phba->sli4_hba.vfi_ids[vport->vfi],
|
||||
phba->vpi_ids[vport->vpi],
|
||||
reg_vfi->wwn[0], reg_vfi->wwn[1], vport->fc_flag,
|
||||
vport->port_state, phba->fc_topology_changed);
|
||||
vport->port_state, phba->fc_topology_changed,
|
||||
bbscn_fabric);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -420,6 +420,20 @@ struct lpfc_hba_eq_hdl {
|
|||
#define LPFC_MULTI_CPU_AFFINITY 0xffffffff
|
||||
};
|
||||
|
||||
/*BB Credit recovery value*/
|
||||
struct lpfc_bbscn_params {
|
||||
uint32_t word0;
|
||||
#define lpfc_bbscn_min_SHIFT 0
|
||||
#define lpfc_bbscn_min_MASK 0x0000000F
|
||||
#define lpfc_bbscn_min_WORD word0
|
||||
#define lpfc_bbscn_max_SHIFT 4
|
||||
#define lpfc_bbscn_max_MASK 0x0000000F
|
||||
#define lpfc_bbscn_max_WORD word0
|
||||
#define lpfc_bbscn_def_SHIFT 8
|
||||
#define lpfc_bbscn_def_MASK 0x0000000F
|
||||
#define lpfc_bbscn_def_WORD word0
|
||||
};
|
||||
|
||||
/* Port Capabilities for SLI4 Parameters */
|
||||
struct lpfc_pc_sli4_params {
|
||||
uint32_t supported;
|
||||
|
@ -551,6 +565,7 @@ struct lpfc_sli4_hba {
|
|||
uint32_t ue_to_rp;
|
||||
struct lpfc_register sli_intf;
|
||||
struct lpfc_pc_sli4_params pc_sli4_params;
|
||||
struct lpfc_bbscn_params bbscn_params;
|
||||
struct lpfc_hba_eq_hdl *hba_eq_hdl; /* HBA per-WQ handle */
|
||||
|
||||
/* Pointers to the constructed SLI4 queues */
|
||||
|
|
Loading…
Reference in New Issue