mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
scsi: lpfc: Add cmf_info sysfs entry
Allow abbreviated cm framework status information to be obtained via sysfs. Link: https://lore.kernel.org/r/20210816162901.121235-14-jsmart2021@gmail.com 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> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
9f77870870
commit
74a7baa2a3
7 changed files with 235 additions and 10 deletions
|
@ -1600,6 +1600,7 @@ struct lpfc_hba {
|
|||
};
|
||||
|
||||
#define LPFC_MAX_RXMONITOR_ENTRY 800
|
||||
#define LPFC_MAX_RXMONITOR_DUMP 32
|
||||
struct rxtable_entry {
|
||||
uint64_t total_bytes; /* Total no of read bytes requested */
|
||||
uint64_t rcv_bytes; /* Total no of read bytes completed */
|
||||
|
|
|
@ -57,6 +57,8 @@
|
|||
#define LPFC_MIN_DEVLOSS_TMO 1
|
||||
#define LPFC_MAX_DEVLOSS_TMO 255
|
||||
|
||||
#define LPFC_MAX_INFO_TMP_LEN 100
|
||||
#define LPFC_INFO_MORE_STR "\nCould be more info...\n"
|
||||
/*
|
||||
* Write key size should be multiple of 4. If write key is changed
|
||||
* make sure that library write key is also changed.
|
||||
|
@ -112,6 +114,186 @@ lpfc_jedec_to_ascii(int incr, char hdw[])
|
|||
return;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
lpfc_cmf_info_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(dev);
|
||||
struct lpfc_vport *vport = (struct lpfc_vport *)shost->hostdata;
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
struct lpfc_cgn_info *cp = NULL;
|
||||
struct lpfc_cgn_stat *cgs;
|
||||
int len = 0;
|
||||
int cpu;
|
||||
u64 rcv, total;
|
||||
char tmp[LPFC_MAX_INFO_TMP_LEN] = {0};
|
||||
|
||||
if (phba->cgn_i)
|
||||
cp = (struct lpfc_cgn_info *)phba->cgn_i->virt;
|
||||
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"Congestion Mgmt Info: E2Eattr %d Ver %d "
|
||||
"CMF %d cnt %d\n",
|
||||
phba->sli4_hba.pc_sli4_params.mi_ver,
|
||||
cp ? cp->cgn_info_version : 0,
|
||||
phba->sli4_hba.pc_sli4_params.cmf, phba->cmf_timer_cnt);
|
||||
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
if (!phba->sli4_hba.pc_sli4_params.cmf)
|
||||
goto buffer_done;
|
||||
|
||||
switch (phba->cgn_init_reg_signal) {
|
||||
case EDC_CG_SIG_WARN_ONLY:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"Register: Init: Signal:WARN ");
|
||||
break;
|
||||
case EDC_CG_SIG_WARN_ALARM:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"Register: Init: Signal:WARN|ALARM ");
|
||||
break;
|
||||
default:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"Register: Init: Signal:NONE ");
|
||||
break;
|
||||
}
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
switch (phba->cgn_init_reg_fpin) {
|
||||
case LPFC_CGN_FPIN_WARN:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:WARN\n");
|
||||
break;
|
||||
case LPFC_CGN_FPIN_ALARM:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:ALARM\n");
|
||||
break;
|
||||
case LPFC_CGN_FPIN_BOTH:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:WARN|ALARM\n");
|
||||
break;
|
||||
default:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:NONE\n");
|
||||
break;
|
||||
}
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
switch (phba->cgn_reg_signal) {
|
||||
case EDC_CG_SIG_WARN_ONLY:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
" Current: Signal:WARN ");
|
||||
break;
|
||||
case EDC_CG_SIG_WARN_ALARM:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
" Current: Signal:WARN|ALARM ");
|
||||
break;
|
||||
default:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
" Current: Signal:NONE ");
|
||||
break;
|
||||
}
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
switch (phba->cgn_reg_fpin) {
|
||||
case LPFC_CGN_FPIN_WARN:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:WARN ACQEcnt:%d\n", phba->cgn_acqe_cnt);
|
||||
break;
|
||||
case LPFC_CGN_FPIN_ALARM:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt);
|
||||
break;
|
||||
case LPFC_CGN_FPIN_BOTH:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:WARN|ALARM ACQEcnt:%d\n", phba->cgn_acqe_cnt);
|
||||
break;
|
||||
default:
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"FPIN:NONE ACQEcnt:%d\n", phba->cgn_acqe_cnt);
|
||||
break;
|
||||
}
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
if (phba->cmf_active_mode != phba->cgn_p.cgn_param_mode) {
|
||||
switch (phba->cmf_active_mode) {
|
||||
case LPFC_CFG_OFF:
|
||||
scnprintf(tmp, sizeof(tmp), "Active: Mode:Off\n");
|
||||
break;
|
||||
case LPFC_CFG_MANAGED:
|
||||
scnprintf(tmp, sizeof(tmp), "Active: Mode:Managed\n");
|
||||
break;
|
||||
case LPFC_CFG_MONITOR:
|
||||
scnprintf(tmp, sizeof(tmp), "Active: Mode:Monitor\n");
|
||||
break;
|
||||
default:
|
||||
scnprintf(tmp, sizeof(tmp), "Active: Mode:Unknown\n");
|
||||
}
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
}
|
||||
|
||||
switch (phba->cgn_p.cgn_param_mode) {
|
||||
case LPFC_CFG_OFF:
|
||||
scnprintf(tmp, sizeof(tmp), "Config: Mode:Off ");
|
||||
break;
|
||||
case LPFC_CFG_MANAGED:
|
||||
scnprintf(tmp, sizeof(tmp), "Config: Mode:Managed ");
|
||||
break;
|
||||
case LPFC_CFG_MONITOR:
|
||||
scnprintf(tmp, sizeof(tmp), "Config: Mode:Monitor ");
|
||||
break;
|
||||
default:
|
||||
scnprintf(tmp, sizeof(tmp), "Config: Mode:Unknown ");
|
||||
}
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
total = 0;
|
||||
rcv = 0;
|
||||
for_each_present_cpu(cpu) {
|
||||
cgs = per_cpu_ptr(phba->cmf_stat, cpu);
|
||||
total += atomic64_read(&cgs->total_bytes);
|
||||
rcv += atomic64_read(&cgs->rcv_bytes);
|
||||
}
|
||||
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"IObusy:%d Info:%d Bytes: Rcv:x%llx Total:x%llx\n",
|
||||
atomic_read(&phba->cmf_busy),
|
||||
phba->cmf_active_info, rcv, total);
|
||||
if (strlcat(buf, tmp, PAGE_SIZE) >= PAGE_SIZE)
|
||||
goto buffer_done;
|
||||
|
||||
scnprintf(tmp, sizeof(tmp),
|
||||
"Port_speed:%d Link_byte_cnt:%ld "
|
||||
"Max_byte_per_interval:%ld\n",
|
||||
lpfc_sli_port_speed_get(phba),
|
||||
(unsigned long)phba->cmf_link_byte_count,
|
||||
(unsigned long)phba->cmf_max_bytes_per_interval);
|
||||
strlcat(buf, tmp, PAGE_SIZE);
|
||||
|
||||
buffer_done:
|
||||
len = strnlen(buf, PAGE_SIZE);
|
||||
|
||||
if (unlikely(len >= (PAGE_SIZE - 1))) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"6312 Catching potential buffer "
|
||||
"overflow > PAGE_SIZE = %lu bytes\n",
|
||||
PAGE_SIZE);
|
||||
strscpy(buf + PAGE_SIZE - 1 -
|
||||
strnlen(LPFC_INFO_MORE_STR, PAGE_SIZE - 1),
|
||||
LPFC_INFO_MORE_STR,
|
||||
strnlen(LPFC_INFO_MORE_STR, PAGE_SIZE - 1)
|
||||
+ 1);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_drvr_version_show - Return the Emulex driver string with version number
|
||||
* @dev: class unused variable.
|
||||
|
@ -168,7 +350,7 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
|
|||
char *statep;
|
||||
int i;
|
||||
int len = 0;
|
||||
char tmp[LPFC_MAX_NVME_INFO_TMP_LEN] = {0};
|
||||
char tmp[LPFC_MAX_INFO_TMP_LEN] = {0};
|
||||
|
||||
if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
|
||||
len = scnprintf(buf, PAGE_SIZE, "NVME Disabled\n");
|
||||
|
@ -512,9 +694,9 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
|
|||
"6314 Catching potential buffer "
|
||||
"overflow > PAGE_SIZE = %lu bytes\n",
|
||||
PAGE_SIZE);
|
||||
strlcpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_NVME_INFO_MORE_STR),
|
||||
LPFC_NVME_INFO_MORE_STR,
|
||||
sizeof(LPFC_NVME_INFO_MORE_STR) + 1);
|
||||
strscpy(buf + PAGE_SIZE - 1 - sizeof(LPFC_INFO_MORE_STR),
|
||||
LPFC_INFO_MORE_STR,
|
||||
sizeof(LPFC_INFO_MORE_STR) + 1);
|
||||
}
|
||||
|
||||
return len;
|
||||
|
@ -2636,6 +2818,7 @@ static DEVICE_ATTR_RO(lpfc_sriov_hw_max_virtfn);
|
|||
static DEVICE_ATTR(protocol, S_IRUGO, lpfc_sli4_protocol_show, NULL);
|
||||
static DEVICE_ATTR(lpfc_xlane_supported, S_IRUGO, lpfc_oas_supported_show,
|
||||
NULL);
|
||||
static DEVICE_ATTR(cmf_info, 0444, lpfc_cmf_info_show, NULL);
|
||||
|
||||
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
|
||||
#define WWN_SZ 8
|
||||
|
@ -6332,6 +6515,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
|
|||
&dev_attr_lpfc_enable_bbcr,
|
||||
&dev_attr_lpfc_enable_dpp,
|
||||
&dev_attr_lpfc_enable_mi,
|
||||
&dev_attr_cmf_info,
|
||||
&dev_attr_lpfc_max_vmid,
|
||||
&dev_attr_lpfc_vmid_inactivity_timeout,
|
||||
&dev_attr_lpfc_vmid_app_header,
|
||||
|
@ -6362,6 +6546,7 @@ struct device_attribute *lpfc_vport_attrs[] = {
|
|||
&dev_attr_lpfc_max_scsicmpl_time,
|
||||
&dev_attr_lpfc_stat_data_ctrl,
|
||||
&dev_attr_lpfc_static_vport,
|
||||
&dev_attr_cmf_info,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -86,6 +86,7 @@ int lpfc_sli4_cgn_params_read(struct lpfc_hba *phba);
|
|||
uint32_t lpfc_cgn_calc_crc32(void *bufp, uint32_t sz, uint32_t seed);
|
||||
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_cgn_dump_rxmonitor(struct lpfc_hba *phba);
|
||||
void lpfc_cgn_update_stat(struct lpfc_hba *phba, uint32_t dtag);
|
||||
void lpfc_unblock_requests(struct lpfc_hba *phba);
|
||||
void lpfc_block_requests(struct lpfc_hba *phba);
|
||||
|
@ -159,6 +160,7 @@ 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);
|
||||
void lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length);
|
||||
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 *,
|
||||
|
|
|
@ -9632,7 +9632,7 @@ lpfc_els_rcv_fpin_cgn(struct lpfc_hba *phba, struct fc_tlv_desc *tlv)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
|
||||
{
|
||||
struct lpfc_hba *phba = vport->phba;
|
||||
|
|
|
@ -1157,6 +1157,7 @@ struct lpfc_mbx_nembed_sge_virt {
|
|||
void *addr[LPFC_SLI4_MBX_SGE_MAX_PAGES];
|
||||
};
|
||||
|
||||
#define LPFC_MBX_OBJECT_NAME_LEN_DW 26
|
||||
struct lpfc_mbx_read_object { /* Version 0 */
|
||||
struct mbox_header header;
|
||||
union {
|
||||
|
@ -1166,7 +1167,7 @@ struct lpfc_mbx_read_object { /* Version 0 */
|
|||
#define lpfc_mbx_rd_object_rlen_MASK 0x00FFFFFF
|
||||
#define lpfc_mbx_rd_object_rlen_WORD word0
|
||||
uint32_t rd_object_offset;
|
||||
uint32_t rd_object_name[26];
|
||||
uint32_t rd_object_name[LPFC_MBX_OBJECT_NAME_LEN_DW];
|
||||
#define LPFC_OBJ_NAME_SZ 104 /* 26 x sizeof(uint32_t) is 104. */
|
||||
uint32_t rd_object_cnt;
|
||||
struct lpfc_mbx_host_buf rd_object_hbuf[4];
|
||||
|
@ -3871,6 +3872,7 @@ struct lpfc_mbx_get_port_name {
|
|||
#define MB_CEQ_STATUS_QUEUE_FLUSHING 0x4
|
||||
#define MB_CQE_STATUS_DMA_FAILED 0x5
|
||||
|
||||
|
||||
#define LPFC_MBX_WR_CONFIG_MAX_BDE 1
|
||||
struct lpfc_mbx_wr_object {
|
||||
struct mbox_header header;
|
||||
|
@ -3887,7 +3889,7 @@ struct lpfc_mbx_wr_object {
|
|||
#define lpfc_wr_object_write_length_MASK 0x00FFFFFF
|
||||
#define lpfc_wr_object_write_length_WORD word4
|
||||
uint32_t write_offset;
|
||||
uint32_t object_name[26];
|
||||
uint32_t object_name[LPFC_MBX_OBJECT_NAME_LEN_DW];
|
||||
uint32_t bde_count;
|
||||
struct ulp_bde64 bde[LPFC_MBX_WR_CONFIG_MAX_BDE];
|
||||
} request;
|
||||
|
|
|
@ -5404,6 +5404,44 @@ lpfc_async_link_speed_to_read_top(struct lpfc_hba *phba, uint8_t speed_code)
|
|||
return port_speed;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_cgn_dump_rxmonitor(struct lpfc_hba *phba)
|
||||
{
|
||||
struct rxtable_entry *entry;
|
||||
int cnt = 0, head, tail, last, start;
|
||||
|
||||
head = atomic_read(&phba->rxtable_idx_head);
|
||||
tail = atomic_read(&phba->rxtable_idx_tail);
|
||||
if (!phba->rxtable || head == tail) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_CGN_MGMT,
|
||||
"4411 Rxtable is empty\n");
|
||||
return;
|
||||
}
|
||||
last = tail;
|
||||
start = head;
|
||||
|
||||
/* Display the last LPFC_MAX_RXMONITOR_DUMP entries from the rxtable */
|
||||
while (start != last) {
|
||||
if (start)
|
||||
start--;
|
||||
else
|
||||
start = LPFC_MAX_RXMONITOR_ENTRY - 1;
|
||||
entry = &phba->rxtable[start];
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_CGN_MGMT,
|
||||
"4410 %02d: MBPI %lld Xmit %lld Cmpl %lld "
|
||||
"Lat %lld ASz %lld Info %02d BWUtil %d "
|
||||
"Int %d slot %d\n",
|
||||
cnt, entry->max_bytes_per_interval,
|
||||
entry->total_bytes, entry->rcv_bytes,
|
||||
entry->avg_io_latency, entry->avg_io_size,
|
||||
entry->cmf_info, entry->timer_utilization,
|
||||
entry->timer_interval, start);
|
||||
cnt++;
|
||||
if (cnt >= LPFC_MAX_RXMONITOR_DUMP)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lpfc_cgn_update_stat - Save data into congestion stats buffer
|
||||
* @phba: pointer to lpfc hba data structure.
|
||||
|
|
|
@ -34,9 +34,6 @@
|
|||
#define LPFC_NVME_FB_SHIFT 9
|
||||
#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */
|
||||
|
||||
#define LPFC_MAX_NVME_INFO_TMP_LEN 100
|
||||
#define LPFC_NVME_INFO_MORE_STR "\nCould be more info...\n"
|
||||
|
||||
#define lpfc_ndlp_get_nrport(ndlp) \
|
||||
((!ndlp->nrport || (ndlp->fc4_xpt_flags & NVME_XPT_UNREG_WAIT))\
|
||||
? NULL : ndlp->nrport)
|
||||
|
|
Loading…
Reference in a new issue