Commit 9064aeb2 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: Add EDC ELS support

When congestion management is enabled, issue EDC ELS to register congestion
signaling capabilities with the fabric. The response handling will process
the fabric parameters and set the reporting parameters.

Similarly, add support for receiving an EDC request from the fabric
generating a corresponding response.

Implement handlers for congestion signals from the fabric and maintain
statistics for them.

Link: https://lore.kernel.org/r/20210816162901.121235-6-jsmart2021@gmail.comCo-developed-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 428569e6
......@@ -403,6 +403,11 @@ struct lpfc_trunk_link {
link3;
};
struct lpfc_cgn_acqe_stat {
atomic64_t alarm;
atomic64_t warn;
};
struct lpfc_vport {
struct lpfc_hba *phba;
struct list_head listentry;
......@@ -1343,6 +1348,36 @@ struct lpfc_hba {
uint64_t ktime_seg10_min;
uint64_t ktime_seg10_max;
#endif
/* CMF objects */
u32 cmf_active_mode;
#define LPFC_CFG_OFF 0
/* Signal / FPIN handling for Congestion Mgmt */
u8 cgn_reg_fpin; /* Negotiated value from RDF */
u8 cgn_init_reg_fpin; /* Initial value from READ_CONFIG */
#define LPFC_CGN_FPIN_NONE 0x0
#define LPFC_CGN_FPIN_WARN 0x1
#define LPFC_CGN_FPIN_ALARM 0x2
#define LPFC_CGN_FPIN_BOTH (LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM)
u8 cgn_reg_signal; /* Negotiated value from EDC */
u8 cgn_init_reg_signal; /* Initial value from READ_CONFIG */
/* cgn_reg_signal and cgn_init_reg_signal use
* enum fc_edc_cg_signal_cap_types
*/
u16 cgn_fpin_frequency;
#define LPFC_FPIN_INIT_FREQ 0xffff
u32 cgn_sig_freq;
u32 cgn_acqe_cnt;
/* Statistics counter for ACQE cgn alarms and warnings */
struct lpfc_cgn_acqe_stat cgn_acqe_stat;
/* Congestion buffer information */
atomic_t cgn_fabric_warn_cnt; /* Total warning cgn events for info */
atomic_t cgn_fabric_alarm_cnt; /* Total alarm cgn events for info */
atomic_t cgn_sync_warn_cnt; /* Total warning events for SYNC wqe */
atomic_t cgn_sync_alarm_cnt; /* Total alarm events for SYNC wqe */
struct hlist_node cpuhp; /* used for cpuhp per hba callback */
struct timer_list cpuhp_poll_timer;
......
......@@ -6150,6 +6150,19 @@ LPFC_ATTR_RW(ras_fwlog_func, 0, 0, 7, "Firmware Logging Enabled on Function");
*/
LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
/* Signaling module parameters */
int lpfc_fabric_cgn_frequency = 100; /* 100 ms default */
module_param(lpfc_fabric_cgn_frequency, int, 0444);
MODULE_PARM_DESC(lpfc_fabric_cgn_frequency, "Congestion signaling fabric freq");
int lpfc_acqe_cgn_frequency = 10; /* 10 sec default */
module_param(lpfc_acqe_cgn_frequency, int, 0444);
MODULE_PARM_DESC(lpfc_acqe_cgn_frequency, "Congestion signaling ACQE freq");
int lpfc_use_cgn_signal = 1; /* 0 - only use FPINs, 1 - Use signals if avail */
module_param(lpfc_use_cgn_signal, int, 0444);
MODULE_PARM_DESC(lpfc_use_cgn_signal, "Use Congestion signaling if available");
/*
* lpfc_enable_dpp: Enable DPP on G7
* 0 = DPP on G7 disabled
......@@ -6915,6 +6928,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
hs->invalid_crc_count = pmb->un.varRdLnk.crcCnt;
hs->error_frames = pmb->un.varRdLnk.crcCnt;
hs->cn_sig_warn = atomic64_read(&phba->cgn_acqe_stat.warn);
hs->cn_sig_alarm = atomic64_read(&phba->cgn_acqe_stat.alarm);
hs->link_failure_count -= lso->link_failure_count;
hs->loss_of_sync_count -= lso->loss_of_sync_count;
hs->loss_of_signal_count -= lso->loss_of_signal_count;
......@@ -7026,6 +7042,12 @@ lpfc_reset_stats(struct Scsi_Host *shost)
else
lso->link_events = (phba->fc_eventTag >> 1);
atomic64_set(&phba->cgn_acqe_stat.warn, 0);
atomic64_set(&phba->cgn_acqe_stat.alarm, 0);
memset(&shost_to_fc_host(shost)->fpin_stats, 0,
sizeof(shost_to_fc_host(shost)->fpin_stats));
psli->stats_start = ktime_get_seconds();
mempool_free(pmboxq, phba->mbox_mem_pool);
......@@ -7459,6 +7481,11 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
lpfc_enable_mi_init(phba, lpfc_enable_mi);
phba->cmf_active_mode = LPFC_CFG_OFF;
if (lpfc_fabric_cgn_frequency > EDC_CG_SIGFREQ_CNT_MAX ||
lpfc_fabric_cgn_frequency < EDC_CG_SIGFREQ_CNT_MIN)
lpfc_fabric_cgn_frequency = 100; /* 100 ms default */
if (phba->sli_rev != LPFC_SLI_REV4) {
/* NVME only supported on SLI4 */
phba->nvmet_support = 0;
......
......@@ -74,6 +74,7 @@ int lpfc_init_iocb_list(struct lpfc_hba *phba, int cnt);
void lpfc_free_iocb_list(struct lpfc_hba *phba);
int lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
struct lpfc_queue *drq, int count, int idx);
int lpfc_config_cgn_signal(struct lpfc_hba *phba);
void lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *, LPFC_MBOXQ_t *);
void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
......@@ -143,6 +144,7 @@ int lpfc_issue_els_scr(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_els_rscn(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_fabric_reglogin(struct lpfc_vport *);
int lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry);
int lpfc_issue_els_edc(struct lpfc_vport *vport, uint8_t retry);
int lpfc_els_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_ct_free_iocb(struct lpfc_hba *, struct lpfc_iocbq *);
int lpfc_els_rsp_acc(struct lpfc_vport *, uint32_t, struct lpfc_iocbq *,
......@@ -607,6 +609,10 @@ extern int lpfc_enable_nvmet_cnt;
extern unsigned long long lpfc_enable_nvmet[];
extern int lpfc_no_hba_reset_cnt;
extern unsigned long lpfc_no_hba_reset[];
extern int lpfc_acqe_cgn_frequency;
extern int lpfc_fabric_cgn_frequency;
extern int lpfc_use_cgn_signal;
extern union lpfc_wqe128 lpfc_iread_cmd_template;
extern union lpfc_wqe128 lpfc_iwrite_cmd_template;
extern union lpfc_wqe128 lpfc_icmnd_cmd_template;
......
......@@ -2288,6 +2288,8 @@ lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* No retry on Vendor, RPA only done on physical port */
if (phba->link_flag & LS_CT_VEN_RPA) {
phba->link_flag &= ~LS_CT_VEN_RPA;
if (phba->cmf_active_mode == LPFC_CFG_OFF)
return;
lpfc_printf_log(phba, KERN_ERR,
LOG_DISCOVERY | LOG_ELS,
"6460 VEN FDMI RPA failure\n");
......
This diff is collapsed.
......@@ -4209,6 +4209,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *)(pmb->ctx_buf);
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *)pmb->ctx_ndlp;
struct lpfc_vport *vport = pmb->vport;
int rc;
pmb->ctx_buf = NULL;
pmb->ctx_ndlp = NULL;
......@@ -4284,9 +4285,23 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
/* Issue SCR just before NameServer GID_FT Query */
lpfc_issue_els_scr(vport, 0);
if (!phba->cfg_enable_mi ||
phba->sli4_hba.pc_sli4_params.mi_ver < LPFC_MIB3_SUPPORT)
/* Link was bounced or a Fabric LOGO occurred. Start EDC
* with initial FW values provided the congestion mode is
* not off. Note that signals may or may not be supported
* by the adapter but FPIN is provided by default for 1
* or both missing signals support.
*/
if (phba->cmf_active_mode != LPFC_CFG_OFF) {
phba->cgn_reg_fpin = phba->cgn_init_reg_fpin;
phba->cgn_reg_signal = phba->cgn_init_reg_signal;
rc = lpfc_issue_els_edc(vport, 0);
lpfc_printf_log(phba, KERN_INFO,
LOG_INIT | LOG_ELS | LOG_DISCOVERY,
"4220 EDC issue error x%x, Data: x%x\n",
rc, phba->cgn_init_reg_signal);
} else {
lpfc_issue_els_rdf(vport, 0);
}
}
vport->fc_ns_retry = 0;
......
......@@ -608,6 +608,7 @@ struct fc_vft_header {
#define ELS_CMD_LIRR 0x7A000000
#define ELS_CMD_LCB 0x81000000
#define ELS_CMD_FPIN 0x16000000
#define ELS_CMD_EDC 0x17000000
#define ELS_CMD_QFPA 0xB0000000
#define ELS_CMD_UVEM 0xB1000000
#else /* __LITTLE_ENDIAN_BITFIELD */
......@@ -652,6 +653,7 @@ struct fc_vft_header {
#define ELS_CMD_LIRR 0x7A
#define ELS_CMD_LCB 0x81
#define ELS_CMD_FPIN ELS_FPIN
#define ELS_CMD_EDC ELS_EDC
#define ELS_CMD_QFPA 0xB0
#define ELS_CMD_UVEM 0xB1
#endif
......
......@@ -2813,6 +2813,12 @@ struct lpfc_mbx_read_config {
#define lpfc_mbx_rd_conf_extnts_inuse_SHIFT 31
#define lpfc_mbx_rd_conf_extnts_inuse_MASK 0x00000001
#define lpfc_mbx_rd_conf_extnts_inuse_WORD word1
#define lpfc_mbx_rd_conf_wcs_SHIFT 28 /* warning signaling */
#define lpfc_mbx_rd_conf_wcs_MASK 0x00000001
#define lpfc_mbx_rd_conf_wcs_WORD word1
#define lpfc_mbx_rd_conf_acs_SHIFT 27 /* alarm signaling */
#define lpfc_mbx_rd_conf_acs_MASK 0x00000001
#define lpfc_mbx_rd_conf_acs_WORD word1
uint32_t word2;
#define lpfc_mbx_rd_conf_lnk_numb_SHIFT 0
#define lpfc_mbx_rd_conf_lnk_numb_MASK 0x0000003F
......@@ -3393,6 +3399,7 @@ struct lpfc_sli4_parameters {
#define LPFC_SET_UE_RECOVERY 0x10
#define LPFC_SET_MDS_DIAGS 0x12
#define LPFC_SET_CGN_SIGNAL 0x1f
#define LPFC_SET_DUAL_DUMP 0x1e
#define LPFC_SET_ENABLE_MI 0x21
struct lpfc_mbx_set_feature {
......@@ -3409,6 +3416,9 @@ struct lpfc_mbx_set_feature {
#define lpfc_mbx_set_feature_mds_deep_loopbk_SHIFT 1
#define lpfc_mbx_set_feature_mds_deep_loopbk_MASK 0x00000001
#define lpfc_mbx_set_feature_mds_deep_loopbk_WORD word6
#define lpfc_mbx_set_feature_CGN_warn_freq_SHIFT 0
#define lpfc_mbx_set_feature_CGN_warn_freq_MASK 0x0000ffff
#define lpfc_mbx_set_feature_CGN_warn_freq_WORD word6
#define lpfc_mbx_set_feature_dd_SHIFT 0
#define lpfc_mbx_set_feature_dd_MASK 0x00000001
#define lpfc_mbx_set_feature_dd_WORD word6
......@@ -3431,6 +3441,13 @@ struct lpfc_mbx_set_feature {
#define lpfc_mbx_set_feature_UESR_SHIFT 16
#define lpfc_mbx_set_feature_UESR_MASK 0x0000ffff
#define lpfc_mbx_set_feature_UESR_WORD word7
#define lpfc_mbx_set_feature_CGN_alarm_freq_SHIFT 0
#define lpfc_mbx_set_feature_CGN_alarm_freq_MASK 0x0000ffff
#define lpfc_mbx_set_feature_CGN_alarm_freq_WORD word7
u32 word8;
#define lpfc_mbx_set_feature_CGN_acqe_freq_SHIFT 0
#define lpfc_mbx_set_feature_CGN_acqe_freq_MASK 0x000000ff
#define lpfc_mbx_set_feature_CGN_acqe_freq_WORD word8
};
......@@ -4173,6 +4190,19 @@ struct lpfc_acqe_misconfigured_event {
#define LPFC_SLI_EVENT_STATUS_UNCERTIFIED 0x05
};
struct lpfc_acqe_cgn_signal {
u32 word0;
#define lpfc_warn_acqe_SHIFT 0
#define lpfc_warn_acqe_MASK 0x7FFFFFFF
#define lpfc_warn_acqe_WORD word0
#define lpfc_imm_acqe_SHIFT 31
#define lpfc_imm_acqe_MASK 0x1
#define lpfc_imm_acqe_WORD word0
u32 alarm_cnt;
u32 word2;
u32 trailer;
};
struct lpfc_acqe_sli {
uint32_t event_data1;
uint32_t event_data2;
......@@ -4187,6 +4217,7 @@ struct lpfc_acqe_sli {
#define LPFC_SLI_EVENT_TYPE_REMOTE_DPORT 0xA
#define LPFC_SLI_EVENT_TYPE_MISCONF_FAWWN 0xF
#define LPFC_SLI_EVENT_TYPE_EEPROM_FAILURE 0x10
#define LPFC_SLI_EVENT_TYPE_CGN_SIGNAL 0x11
};
/*
......@@ -4815,6 +4846,17 @@ struct lpfc_grp_hdr {
#define LPFC_FW_RESET 2
#define LPFC_DV_RESET 3
/* On some kernels, enum fc_ls_tlv_dtag does not have
* these 2 enums defined, on other kernels it does.
* To get aound this we need to add these 2 defines here.
*/
#ifndef ELS_DTAG_LNK_FAULT_CAP
#define ELS_DTAG_LNK_FAULT_CAP 0x0001000D
#endif
#ifndef ELS_DTAG_CG_SIGNAL_CAP
#define ELS_DTAG_CG_SIGNAL_CAP 0x0001000F
#endif
/*
* Initializer useful for decoding FPIN string table.
*/
......@@ -4823,6 +4865,22 @@ struct lpfc_grp_hdr {
{ FPIN_CONGN_SEVERITY_ERROR, "Alarm" }, \
}
/* EDC supports two descriptors. When allocated, it is the
* size of this structure plus each supported descriptor.
*/
struct lpfc_els_edc_req {
struct fc_els_edc edc; /* hdr up to descriptors */
struct fc_diag_cg_sig_desc cgn_desc; /* 1st descriptor */
};
/* Minimum structure defines for the EDC response.
* Balance is in buffer.
*/
struct lpfc_els_edc_rsp {
struct fc_els_edc_resp edc_rsp; /* hdr up to descriptors */
struct fc_diag_cg_sig_desc cgn_desc; /* 1st descriptor */
};
/* Used for logging FPIN messages */
#define LPFC_FPIN_WWPN_LINE_SZ 128
#define LPFC_FPIN_WWPN_LINE_CNT 6
......
......@@ -1243,7 +1243,8 @@ lpfc_idle_stat_delay_work(struct work_struct *work)
return;
if (phba->link_state == LPFC_HBA_ERROR ||
phba->pport->fc_flag & FC_OFFLINE_MODE)
phba->pport->fc_flag & FC_OFFLINE_MODE ||
phba->cmf_active_mode != LPFC_CFG_OFF)
goto requeue;
for_each_present_cpu(i) {
......@@ -5528,9 +5529,10 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
uint8_t operational = 0;
struct temp_event temp_event_data;
struct lpfc_acqe_misconfigured_event *misconfigured;
struct lpfc_acqe_cgn_signal *cgn_signal;
struct Scsi_Host *shost;
struct lpfc_vport **vports;
int rc, i;
int rc, i, cnt;
evt_type = bf_get(lpfc_trailer_type, acqe_sli);
......@@ -5703,6 +5705,40 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
"Event Data1: x%08x Event Data2: x%08x\n",
acqe_sli->event_data1, acqe_sli->event_data2);
break;
case LPFC_SLI_EVENT_TYPE_CGN_SIGNAL:
if (phba->cmf_active_mode == LPFC_CFG_OFF)
break;
cgn_signal = (struct lpfc_acqe_cgn_signal *)
&acqe_sli->event_data1;
phba->cgn_acqe_cnt++;
cnt = bf_get(lpfc_warn_acqe, cgn_signal);
atomic64_add(cnt, &phba->cgn_acqe_stat.warn);
atomic64_add(cgn_signal->alarm_cnt, &phba->cgn_acqe_stat.alarm);
/* no threshold for CMF, even 1 signal will trigger an event */
/* Alarm overrides warning, so check that first */
if (cgn_signal->alarm_cnt) {
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
/* Keep track of alarm cnt for cgn_info */
atomic_add(cgn_signal->alarm_cnt,
&phba->cgn_fabric_alarm_cnt);
/* Keep track of alarm cnt for CMF_SYNC_WQE */
atomic_add(cgn_signal->alarm_cnt,
&phba->cgn_sync_alarm_cnt);
}
} else if (cnt) {
/* signal action needs to be taken */
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY ||
phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
/* Keep track of warning cnt for cgn_info */
atomic_add(cnt, &phba->cgn_fabric_warn_cnt);
/* Keep track of warning cnt for CMF_SYNC_WQE */
atomic_add(cnt, &phba->cgn_sync_warn_cnt);
}
}
break;
default:
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"3193 Unrecognized SLI event, type: 0x%x",
......@@ -8702,6 +8738,52 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
phba->max_vpi = (phba->sli4_hba.max_cfg_param.max_vpi > 0) ?
(phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
phba->max_vports = phba->max_vpi;
/* Next decide on FPIN or Signal E2E CGN support
* For congestion alarms and warnings valid combination are:
* 1. FPIN alarms / FPIN warnings
* 2. Signal alarms / Signal warnings
* 3. FPIN alarms / Signal warnings
* 4. Signal alarms / FPIN warnings
*
* Initialize the adapter frequency to 100 mSecs
*/
phba->cgn_reg_fpin = LPFC_CGN_FPIN_BOTH;
phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
phba->cgn_sig_freq = lpfc_fabric_cgn_frequency;
if (lpfc_use_cgn_signal) {
if (bf_get(lpfc_mbx_rd_conf_wcs, rd_config)) {
phba->cgn_reg_signal = EDC_CG_SIG_WARN_ONLY;
phba->cgn_reg_fpin &= ~LPFC_CGN_FPIN_WARN;
}
if (bf_get(lpfc_mbx_rd_conf_acs, rd_config)) {
/* MUST support both alarm and warning
* because EDC does not support alarm alone.
*/
if (phba->cgn_reg_signal !=
EDC_CG_SIG_WARN_ONLY) {
/* Must support both or none */
phba->cgn_reg_fpin = LPFC_CGN_FPIN_BOTH;
phba->cgn_reg_signal =
EDC_CG_SIG_NOTSUPPORTED;
} else {
phba->cgn_reg_signal =
EDC_CG_SIG_WARN_ALARM;
phba->cgn_reg_fpin =
LPFC_CGN_FPIN_NONE;
}
}
}
/* Set the congestion initial signal and fpin values. */
phba->cgn_init_reg_fpin = phba->cgn_reg_fpin;
phba->cgn_init_reg_signal = phba->cgn_reg_signal;
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
"6446 READ_CONFIG reg_sig x%x reg_fpin:x%x\n",
phba->cgn_reg_signal, phba->cgn_reg_fpin);
lpfc_map_topology(phba, rd_config);
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
"2003 cfg params Extents? %d "
......
......@@ -6417,6 +6417,7 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
uint32_t feature)
{
uint32_t len;
u32 sig_freq = 0;
len = sizeof(struct lpfc_mbx_set_feature) -
sizeof(struct lpfc_sli4_cfg_mhdr);
......@@ -6439,6 +6440,35 @@ lpfc_set_features(struct lpfc_hba *phba, LPFC_MBOXQ_t *mbox,
mbox->u.mqe.un.set_feature.feature = LPFC_SET_MDS_DIAGS;
mbox->u.mqe.un.set_feature.param_len = 8;
break;
case LPFC_SET_CGN_SIGNAL:
if (phba->cmf_active_mode == LPFC_CFG_OFF)
sig_freq = 0;
else
sig_freq = phba->cgn_sig_freq;
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
bf_set(lpfc_mbx_set_feature_CGN_alarm_freq,
&mbox->u.mqe.un.set_feature, sig_freq);
bf_set(lpfc_mbx_set_feature_CGN_warn_freq,
&mbox->u.mqe.un.set_feature, sig_freq);
}
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY)
bf_set(lpfc_mbx_set_feature_CGN_warn_freq,
&mbox->u.mqe.un.set_feature, sig_freq);
if (phba->cmf_active_mode == LPFC_CFG_OFF ||
phba->cgn_reg_signal == EDC_CG_SIG_NOTSUPPORTED)
sig_freq = 0;
else
sig_freq = lpfc_acqe_cgn_frequency;
bf_set(lpfc_mbx_set_feature_CGN_acqe_freq,
&mbox->u.mqe.un.set_feature, sig_freq);
mbox->u.mqe.un.set_feature.feature = LPFC_SET_CGN_SIGNAL;
mbox->u.mqe.un.set_feature.param_len = 12;
break;
case LPFC_SET_DUAL_DUMP:
bf_set(lpfc_mbx_set_feature_dd,
&mbox->u.mqe.un.set_feature, LPFC_ENABLE_DUAL_DUMP);
......@@ -7445,6 +7475,91 @@ lpfc_post_rq_buffer(struct lpfc_hba *phba, struct lpfc_queue *hrq,
return 1;
}
static void
lpfc_mbx_cmpl_cgn_set_ftrs(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{
struct lpfc_vport *vport = pmb->vport;
union lpfc_sli4_cfg_shdr *shdr;
u32 shdr_status, shdr_add_status;
u32 sig, acqe;
/* Two outcomes. (1) Set featurs was successul and EDC negotiation
* is done. (2) Mailbox failed and send FPIN support only.
*/
shdr = (union lpfc_sli4_cfg_shdr *)
&pmb->u.mqe.un.sli4_config.header.cfg_shdr;
shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
if (shdr_status || shdr_add_status || pmb->u.mb.mbxStatus) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT | LOG_CGN_MGMT,
"2516 CGN SET_FEATURE mbox failed with "
"status x%x add_status x%x, mbx status x%x "
"Reset Congestion to FPINs only\n",
shdr_status, shdr_add_status,
pmb->u.mb.mbxStatus);
/* If there is a mbox error, move on to RDF */
phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
phba->cgn_reg_fpin = LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM;
goto out;
}
/* Zero out Congestion Signal ACQE counter */
phba->cgn_acqe_cnt = 0;
atomic64_set(&phba->cgn_acqe_stat.warn, 0);
atomic64_set(&phba->cgn_acqe_stat.alarm, 0);
acqe = bf_get(lpfc_mbx_set_feature_CGN_acqe_freq,
&pmb->u.mqe.un.set_feature);
sig = bf_get(lpfc_mbx_set_feature_CGN_warn_freq,
&pmb->u.mqe.un.set_feature);
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
"4620 SET_FEATURES Success: Freq: %ds %dms "
" Reg: x%x x%x\n", acqe, sig,
phba->cgn_reg_signal, phba->cgn_reg_fpin);
out:
mempool_free(pmb, phba->mbox_mem_pool);
/* Register for FPIN events from the fabric now that the
* EDC common_set_features has completed.
*/
lpfc_issue_els_rdf(vport, 0);
}
int
lpfc_config_cgn_signal(struct lpfc_hba *phba)
{
LPFC_MBOXQ_t *mboxq;
u32 rc;
mboxq = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mboxq)
goto out_rdf;
lpfc_set_features(phba, mboxq, LPFC_SET_CGN_SIGNAL);
mboxq->vport = phba->pport;
mboxq->mbox_cmpl = lpfc_mbx_cmpl_cgn_set_ftrs;
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
"4621 SET_FEATURES: FREQ sig x%x acqe x%x: "
"Reg: x%x x%x\n",
phba->cgn_sig_freq, lpfc_acqe_cgn_frequency,
phba->cgn_reg_signal, phba->cgn_reg_fpin);
rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED)
goto out;
return 0;
out:
mempool_free(mboxq, phba->mbox_mem_pool);
out_rdf:
/* If there is a mbox error, move on to RDF */
phba->cgn_reg_fpin = LPFC_CGN_FPIN_WARN | LPFC_CGN_FPIN_ALARM;
phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
lpfc_issue_els_rdf(phba->pport, 0);
return -EIO;
}
/**
* lpfc_init_idle_stat_hb - Initialize idle_stat tracking
* @phba: pointer to lpfc hba data structure.
......@@ -7476,7 +7591,8 @@ static void lpfc_init_idle_stat_hb(struct lpfc_hba *phba)
idle_stat->prev_idle = get_cpu_idle_time(i, &wall, 1);
idle_stat->prev_wall = wall;
if (phba->nvmet_support)
if (phba->nvmet_support ||
phba->cmf_active_mode != LPFC_CFG_OFF)
cq->poll_mode = LPFC_QUEUE_WORK;
else
cq->poll_mode = LPFC_IRQ_POLL;
......@@ -9947,6 +10063,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
if (pcmd && (*pcmd == ELS_CMD_FLOGI ||
*pcmd == ELS_CMD_SCR ||
*pcmd == ELS_CMD_RDF ||
*pcmd == ELS_CMD_EDC ||
*pcmd == ELS_CMD_RSCN_XMT ||
*pcmd == ELS_CMD_FDISC ||
*pcmd == ELS_CMD_LOGO ||
......@@ -14814,8 +14931,12 @@ static void lpfc_sli4_sched_cq_work(struct lpfc_hba *phba,
switch (cq->poll_mode) {
case LPFC_IRQ_POLL:
irq_poll_sched(&cq->iop);
break;
/* CGN mgmt is mutually exclusive from softirq processing */
if (phba->cmf_active_mode == LPFC_CFG_OFF) {
irq_poll_sched(&cq->iop);
break;
}
fallthrough;
case LPFC_QUEUE_WORK:
default:
if (is_kdump_kernel())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment