Skip to content

Commit

Permalink
lpfc: Add support for the CM framework
Browse files Browse the repository at this point in the history
This patch completes the enablement of the cm framework feature in the
adapter.

The patch performs the following:
- Detects the presence of the congestion management framework feature

When the cm framework is present:
- Issues the SET_FEATURE command to enable the feature
- Registers the cm statistics buffer with the adapter
- Reads the cm enablement buffer to determine the cm framework state
  for cm management.

When cm management is enabled:
- Monitors all FPIN and congestion signalling events, incrementing
  counters.
- Regularly syncs with the adapter to communicate congestion events and
  to receive an rx request limit.
- Monitors requests for rx data and ensures that no more than the
  adapter prescribed limit is issued on the link. If the limit is
  exceeded, scsi and/or nvme traffic is temporarily suspended.
- Maintains the minute, hourly, daily statistics buffer.
- Monitors for congestion enablement change events, causing a reread of
  the enablement buffer and acting on any change in enablement.

And
- Adds teardown logic, including buffer deregistration, on adapter
  detachment or reset.

Co-developed-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
  • Loading branch information
jsmart-gh authored and intel-lab-lkp committed Aug 13, 2021
1 parent d1a0dd2 commit 1a8e9dd
Show file tree
Hide file tree
Showing 12 changed files with 910 additions and 34 deletions.
33 changes: 30 additions & 3 deletions drivers/scsi/lpfc/lpfc.h
Expand Up @@ -550,6 +550,14 @@ struct lpfc_cgn_info {
#define LPFC_CGN_INFO_SZ (sizeof(struct lpfc_cgn_info) - \
sizeof(uint32_t))

struct lpfc_cgn_stat {
atomic64_t total_bytes;
atomic64_t rcv_bytes;
atomic64_t rx_latency;
#define LPFC_CGN_NOT_SENT 0xFFFFFFFFFFFFFFFFLL
atomic_t rx_io_cnt;
};

struct lpfc_cgn_acqe_stat {
atomic64_t alarm;
atomic64_t warn;
Expand Down Expand Up @@ -1021,7 +1029,10 @@ struct lpfc_hba {
* capability
*/
#define HBA_FLOGI_ISSUED 0x100000 /* FLOGI was issued */
#define HBA_CGN_RSVD1 0x200000 /* Reserved CGN flag */
#define HBA_CGN_DAY_WRAP 0x400000 /* HBA Congestion info day wraps */
#define HBA_DEFER_FLOGI 0x800000 /* Defer FLOGI till read_sparm cmpl */
#define HBA_SETUP 0x1000000 /* Signifies HBA setup is completed */
#define HBA_NEEDS_CFG_PORT 0x2000000 /* SLI3 - needs a CONFIG_PORT mbox */
#define HBA_HBEAT_INP 0x4000000 /* mbox HBEAT is in progress */
#define HBA_HBEAT_TMO 0x8000000 /* HBEAT initiated after timeout */
Expand Down Expand Up @@ -1272,6 +1283,7 @@ struct lpfc_hba {
uint32_t total_iocbq_bufs;
struct list_head active_rrq_list;
spinlock_t hbalock;
struct work_struct unblock_request_work; /* SCSI layer unblock IOs */

/* dma_mem_pools */
struct dma_pool *lpfc_sg_dma_buf_pool;
Expand Down Expand Up @@ -1496,12 +1508,25 @@ struct lpfc_hba {
uint64_t ktime_seg10_max;
#endif
/* CMF objects */
u32 cmf_active_mode;
#define LPFC_CFG_OFF 0

struct lpfc_cgn_stat __percpu *cmf_stat;
uint32_t cmf_interval_rate; /* timer interval limit in ms */
uint32_t cmf_timer_cnt;
#define LPFC_CMF_INTERVAL 90
uint64_t cmf_link_byte_count;
uint64_t cmf_max_line_rate;
uint64_t cmf_max_bytes_per_interval;
uint64_t cmf_last_sync_bw;
#define LPFC_CMF_BLK_SIZE 512
struct hrtimer cmf_timer;
atomic_t cmf_bw_wait;
atomic_t cmf_busy;
atomic_t cmf_stop_io; /* To block request and stop IO's */
uint32_t cmf_active_mode;
uint32_t cmf_info_per_interval;
#define LPFC_MAX_CMF_INFO 32
struct timespec64 cmf_latency; /* Interval congestion timestamp */
uint32_t cmf_last_ts; /* Interval congestion time (ms) */
uint32_t cmf_active_info;

/* Signal / FPIN handling for Congestion Mgmt */
u8 cgn_reg_fpin; /* Negotiated value from RDF */
Expand All @@ -1521,6 +1546,8 @@ struct lpfc_hba {
u32 cgn_sig_freq;
u32 cgn_acqe_cnt;

uint64_t rx_block_cnt;

/* Congestion parameters from flash */
struct lpfc_cgn_param cgn_p;

Expand Down
1 change: 1 addition & 0 deletions drivers/scsi/lpfc/lpfc_attr.c
Expand Up @@ -7476,6 +7476,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
lpfc_enable_mi_init(phba, lpfc_enable_mi);

phba->cgn_p.cgn_param_mode = LPFC_CFG_OFF;
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)
Expand Down
10 changes: 10 additions & 0 deletions drivers/scsi/lpfc/lpfc_crtn.h
Expand Up @@ -59,6 +59,7 @@ int lpfc_sli4_mbox_rsrc_extent(struct lpfc_hba *, struct lpfcMboxq *,
uint16_t, uint16_t, bool);
int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
int lpfc_reg_congestion_buf(struct lpfc_hba *phba);
int lpfc_unreg_congestion_buf(struct lpfc_hba *phba);
struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
Expand All @@ -75,11 +76,17 @@ 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);
uint32_t lpfc_calc_cmf_latency(struct lpfc_hba *phba);
void lpfc_cmf_signal_init(struct lpfc_hba *phba);
void lpfc_cmf_start(struct lpfc_hba *phba);
void lpfc_cmf_stop(struct lpfc_hba *phba);
void lpfc_init_congestion_stat(struct lpfc_hba *phba);
void lpfc_init_congestion_buf(struct lpfc_hba *phba);
int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
int lpfc_config_cgn_signal(struct lpfc_hba *phba);
int lpfc_issue_cmf_sync_wqe(struct lpfc_hba *phba, u32 ms, u64 total);
void lpfc_unblock_requests(struct lpfc_hba *phba);
void lpfc_block_requests(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 *);
Expand Down Expand Up @@ -471,6 +478,9 @@ void lpfc_free_fast_evt(struct lpfc_hba *, struct lpfc_fast_path_event *);
void lpfc_create_static_vport(struct lpfc_hba *);
void lpfc_stop_hba_timers(struct lpfc_hba *);
void lpfc_stop_port(struct lpfc_hba *);
int lpfc_update_cmf_cmd(struct lpfc_hba *phba, uint32_t sz);
int lpfc_update_cmf_cmpl(struct lpfc_hba *phba, uint64_t val, uint32_t sz,
struct Scsi_Host *shost);
void __lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *);
void lpfc_sli4_stop_fcf_redisc_wait_timer(struct lpfc_hba *);
void lpfc_parse_fcoe_conf(struct lpfc_hba *, uint8_t *, uint32_t);
Expand Down
73 changes: 69 additions & 4 deletions drivers/scsi/lpfc/lpfc_els.c
Expand Up @@ -3333,9 +3333,11 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
lpfc_printf_vlog(vport, KERN_INFO,
LOG_ELS | LOG_CGN_MGMT,
"4677 Fabric RDF Notification Grant "
"Data: 0x%08x\n",
"Data: 0x%08x Reg: %x %x\n",
be32_to_cpu(
prdf->reg_d1.desc_tags[i]));
prdf->reg_d1.desc_tags[i]),
phba->cgn_reg_signal,
phba->cgn_reg_fpin);
}

out:
Expand Down Expand Up @@ -3702,9 +3704,11 @@ lpfc_issue_els_rdf(struct lpfc_vport *vport, uint8_t retry)
prdf->reg_d1.desc_tags[3] = cpu_to_be32(ELS_DTAG_CONGESTION);

lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS | LOG_CGN_MGMT,
"6444 Xmit RDF to remote NPORT x%x\n",
ndlp->nlp_DID);
"6444 Xmit RDF to remote NPORT x%x Reg: %x %x\n",
ndlp->nlp_DID, phba->cgn_reg_signal,
phba->cgn_reg_fpin);

phba->cgn_fpin_frequency = LPFC_FPIN_INIT_FREQ;
elsiocb->iocb_cmpl = lpfc_cmpl_els_disc_cmd;
elsiocb->context1 = lpfc_nlp_get(ndlp);
if (!elsiocb->context1) {
Expand Down Expand Up @@ -3778,6 +3782,8 @@ lpfc_least_capable_settings(struct lpfc_hba *phba,
{
u32 rsp_sig_cap = 0, drv_sig_cap = 0;
u32 rsp_sig_freq_cyc = 0, rsp_sig_freq_scale = 0;
struct lpfc_cgn_info *cp;
u16 sig_freq;

/* Get rsp signal and frequency capabilities. */
rsp_sig_cap = be32_to_cpu(pcgd->xmt_signal_capability);
Expand Down Expand Up @@ -3832,6 +3838,24 @@ lpfc_least_capable_settings(struct lpfc_hba *phba,
phba->cgn_reg_fpin &= ~LPFC_CGN_FPIN_WARN;
}
}

if (!phba->cgn_i)
return;

/* Update signal frequency in congestion info buffer */
cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;

/* Frequency (in ms) Signal Warning/Signal Congestion Notifications
* are received by the HBA
*/
sig_freq = phba->cgn_sig_freq;

if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ONLY)
cp->cgn_warn_freq = cpu_to_le16(sig_freq);
if (phba->cgn_reg_signal == EDC_CG_SIG_WARN_ALARM) {
cp->cgn_alarm_freq = cpu_to_le16(sig_freq);
cp->cgn_warn_freq = cpu_to_le16(sig_freq);
}
return;

out_no_support:
Expand Down Expand Up @@ -9508,11 +9532,13 @@ lpfc_els_rcv_fpin_peer_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
static int
lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
{
struct lpfc_cgn_info *cp;
struct fc_fn_congn_desc *cgn = (struct fc_fn_congn_desc *)tlv;
const char *cgn_evt_str;
u32 cgn_evt;
const char *cgn_sev_str;
u32 cgn_sev;
uint16_t value;
bool nm_log = false;
int rc = 1;

Expand Down Expand Up @@ -9540,9 +9566,48 @@ lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
switch (cgn_sev) {
case FPIN_CONGN_SEVERITY_ERROR:
/* Take action here for an Alarm event */
if (phba->cmf_active_mode != LPFC_CFG_OFF) {
if (phba->cgn_reg_fpin & LPFC_CGN_FPIN_ALARM) {
/* Track of alarm cnt for cgn_info */
atomic_inc(&phba->cgn_fabric_alarm_cnt);
/* Track of alarm cnt for SYNC_WQE */
atomic_inc(&phba->cgn_sync_alarm_cnt);
}
goto cleanup;
}
break;
case FPIN_CONGN_SEVERITY_WARNING:
/* Take action here for a Warning event */
if (phba->cmf_active_mode != LPFC_CFG_OFF) {
if (phba->cgn_reg_fpin & LPFC_CGN_FPIN_WARN) {
/* Track of warning cnt for cgn_info */
atomic_inc(&phba->cgn_fabric_warn_cnt);
/* Track of warning cnt for SYNC_WQE */
atomic_inc(&phba->cgn_sync_warn_cnt);
}
cleanup:
/* Save frequency in ms */
phba->cgn_fpin_frequency =
be32_to_cpu(cgn->event_period);
value = phba->cgn_fpin_frequency;
if (phba->cgn_i) {
cp = (struct lpfc_cgn_info *)
phba->cgn_i->virt;
if (phba->cgn_reg_fpin &
LPFC_CGN_FPIN_ALARM)
cp->cgn_alarm_freq =
cpu_to_le16(value);
if (phba->cgn_reg_fpin &
LPFC_CGN_FPIN_WARN)
cp->cgn_warn_freq =
cpu_to_le16(value);
}

/* Don't deliver to upper layer since
* driver took action on this tlv.
*/
rc = 0;
}
break;
}
break;
Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/lpfc/lpfc_hbadisc.c
Expand Up @@ -3647,6 +3647,10 @@ lpfc_mbx_cmpl_read_topology(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
phba->wait_4_mlo_maint_flg);
}
lpfc_mbx_process_link_up(phba, la);

if (phba->cmf_active_mode != LPFC_CFG_OFF)
lpfc_cmf_signal_init(phba);

} else if (attn_type == LPFC_ATT_LINK_DOWN ||
attn_type == LPFC_ATT_UNEXP_WWPN) {
phba->fc_stat.LinkDown++;
Expand Down

0 comments on commit 1a8e9dd

Please sign in to comment.