Commit 74a7baa2 authored by James Smart's avatar James Smart Committed by Martin K. Petersen
Browse files

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: 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 9f778708
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+189 −4
Original line number Diff line number Diff line
@@ -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,
};

+2 −0
Original line number Diff line number Diff line
@@ -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 *,
+1 −1
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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;
Loading