All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/7] qla2xxx driver enhancements
@ 2021-01-05 10:38 Nilesh Javali
  2021-01-05 10:38 ` [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port Nilesh Javali
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

Martin,

Please apply the qla2xxx driver enhancements to the scsi tree at your
earliest convenience.

v3:
Add complete fix for the warning reported by kernel test robot.

v2:
Fix warning reported by kernel test robot.


Bikash Hazarika (1):
  qla2xxx: Wait for ABTS response on I/O timeouts for NVMe

Nilesh Javali (1):
  qla2xxx: Update version to 10.02.00.105-k

Quinn Tran (1):
  qla2xxx: Fix mailbox Ch erroneous error

Saurav Kashyap (4):
  qla2xxx: Implementation to get and manage host, target stats and
    initiator port
  qla2xxx: Add error counters to debugfs node
  qla2xxx: Move some messages from debug to normal log level
  qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER

 drivers/scsi/qla2xxx/qla_attr.c    |   9 +
 drivers/scsi/qla2xxx/qla_bsg.c     | 342 +++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_bsg.h     |   5 +
 drivers/scsi/qla2xxx/qla_dbg.c     |   1 +
 drivers/scsi/qla2xxx/qla_def.h     |  83 +++++++
 drivers/scsi/qla2xxx/qla_dfs.c     |  28 +++
 drivers/scsi/qla2xxx/qla_fw.h      |  27 ++-
 drivers/scsi/qla2xxx/qla_gbl.h     |  29 +++
 drivers/scsi/qla2xxx/qla_gs.c      |   1 +
 drivers/scsi/qla2xxx/qla_init.c    | 230 ++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_iocb.c    |   8 +
 drivers/scsi/qla2xxx/qla_isr.c     |  82 ++++---
 drivers/scsi/qla2xxx/qla_mbx.c     |  18 +-
 drivers/scsi/qla2xxx/qla_nvme.c    |  90 +++++++-
 drivers/scsi/qla2xxx/qla_os.c      |  25 +++
 drivers/scsi/qla2xxx/qla_version.h |   4 +-
 16 files changed, 942 insertions(+), 40 deletions(-)


base-commit: be1b500212541a70006887bae558ff834d7365d0
-- 
2.19.0.rc0


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:05   ` Himanshu Madhani
  2021-01-05 10:38 ` [PATCH v3 2/7] qla2xxx: Add error counters to debugfs node Nilesh Javali
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Saurav Kashyap <skashyap@marvell.com>

This statistics will help in debugging process and checking specific
error counts.

Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Reported-by: kernel test robot <lkp@intel.com>
---
 drivers/scsi/qla2xxx/qla_attr.c |   9 +
 drivers/scsi/qla2xxx/qla_bsg.c  | 342 ++++++++++++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_bsg.h  |   5 +
 drivers/scsi/qla2xxx/qla_def.h  |  71 +++++++
 drivers/scsi/qla2xxx/qla_gbl.h  |  23 +++
 drivers/scsi/qla2xxx/qla_gs.c   |   1 +
 drivers/scsi/qla2xxx/qla_init.c | 216 ++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_isr.c  |  22 ++
 drivers/scsi/qla2xxx/qla_mbx.c  |   9 +
 drivers/scsi/qla2xxx/qla_os.c   |  20 ++
 10 files changed, 718 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index ab45ac1e5a72..63391c9be05d 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -710,6 +710,12 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
 		ql_log(ql_log_info, vha, 0x706e,
 		    "Issuing ISP reset.\n");
 
+		if (vha->hw->flags.port_isolated) {
+			ql_log(ql_log_info, vha, 0x706e,
+			       "Port is isolated, returning.\n");
+			return -EINVAL;
+		}
+
 		scsi_block_requests(vha->host);
 		if (IS_QLA82XX(ha)) {
 			ha->flags.isp82xx_no_md_cap = 1;
@@ -2717,6 +2723,9 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
 	if (IS_QLAFX00(vha->hw))
 		return 0;
 
+	if (vha->hw->flags.port_isolated)
+		return 0;
+
 	qla2x00_loop_reset(vha);
 	return 0;
 }
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 23b604832a54..ae3bc6ec8722 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -4,6 +4,7 @@
  * Copyright (c)  2003-2014 QLogic Corporation
  */
 #include "qla_def.h"
+#include "qla_gbl.h"
 
 #include <linux/kthread.h>
 #include <linux/vmalloc.h>
@@ -2444,6 +2445,323 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
 	return 0;
 }
 
+static int
+qla2x00_manage_host_stats(struct bsg_job *bsg_job)
+{
+	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct ql_vnd_mng_host_stats_param *req_data;
+	struct ql_vnd_mng_host_stats_resp rsp_data;
+	u32 req_data_len;
+	int ret = 0;
+
+	if (!vha->flags.online) {
+		ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
+		return -EIO;
+	}
+
+	req_data_len = bsg_job->request_payload.payload_len;
+
+	if (req_data_len != sizeof(struct ql_vnd_mng_host_stats_param)) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
+		return -EIO;
+	}
+
+	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+	if (!req_data) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
+		return -ENOMEM;
+	}
+
+	/* Copy the request buffer in req_data */
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+			  bsg_job->request_payload.sg_cnt, req_data,
+			  req_data_len);
+
+	switch (req_data->action) {
+	case 0:
+		ret = qla2xxx_stop_stats(vha->host, req_data->stat_type);
+		break;
+	case 1:
+		ret = qla2xxx_start_stats(vha->host, req_data->stat_type);
+		break;
+	case 2:
+		ret = qla2xxx_reset_stats(vha->host, req_data->stat_type);
+		break;
+	default:
+		ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
+		ret = -EIO;
+		break;
+	}
+
+	kfree(req_data);
+
+	/* Prepare response */
+	rsp_data.status = ret;
+	bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
+
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+	bsg_reply->reply_payload_rcv_len =
+		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+				    bsg_job->reply_payload.sg_cnt,
+				    &rsp_data,
+				    sizeof(struct ql_vnd_mng_host_stats_resp));
+
+	bsg_reply->result = DID_OK;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+	return ret;
+}
+
+static int
+qla2x00_get_host_stats(struct bsg_job *bsg_job)
+{
+	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct ql_vnd_stats_param *req_data;
+	struct ql_vnd_host_stats_resp rsp_data;
+	u32 req_data_len;
+	int ret = 0;
+	u64 ini_entry_count = 0;
+	u64 entry_count = 0;
+	u64 tgt_num = 0;
+	u64 tmp_stat_type = 0;
+	u64 response_len = 0;
+	void *data;
+
+	req_data_len = bsg_job->request_payload.payload_len;
+
+	if (req_data_len != sizeof(struct ql_vnd_stats_param)) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
+		return -EIO;
+	}
+
+	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+	if (!req_data) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
+		return -ENOMEM;
+	}
+
+	/* Copy the request buffer in req_data */
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+			  bsg_job->request_payload.sg_cnt, req_data, req_data_len);
+
+	/* Copy stat type to work on it */
+	tmp_stat_type = req_data->stat_type;
+
+	if (tmp_stat_type & QLA2XX_TGT_SHT_LNK_DOWN) {
+		/* Num of tgts connected to this host */
+		tgt_num = qla2x00_get_num_tgts(vha);
+		/* unset BIT_17 */
+		tmp_stat_type &= ~(1 << 17);
+	}
+
+	/* Total ini stats */
+	ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
+
+	/* Total number of entries */
+	entry_count = ini_entry_count + tgt_num;
+
+	response_len = sizeof(struct ql_vnd_host_stats_resp) +
+		(sizeof(struct ql_vnd_stat_entry) * entry_count);
+
+	if (response_len > bsg_job->reply_payload.payload_len) {
+		rsp_data.status = EXT_STATUS_BUFFER_TOO_SMALL;
+		bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
+		bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
+
+		bsg_reply->reply_payload_rcv_len =
+			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+					    bsg_job->reply_payload.sg_cnt, &rsp_data,
+					    sizeof(struct ql_vnd_mng_host_stats_resp));
+
+		bsg_reply->result = DID_OK;
+		bsg_job_done(bsg_job, bsg_reply->result,
+			     bsg_reply->reply_payload_rcv_len);
+		goto host_stat_out;
+	}
+
+	data = kzalloc(response_len, GFP_KERNEL);
+
+	ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
+				    data, response_len);
+
+	rsp_data.status = EXT_STATUS_OK;
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+
+	bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+							       bsg_job->reply_payload.sg_cnt,
+							       data, response_len);
+	bsg_reply->result = DID_OK;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+	kfree(data);
+host_stat_out:
+	kfree(req_data);
+	return ret;
+}
+
+static struct fc_rport *
+qla2xxx_find_rport(scsi_qla_host_t *vha, uint32_t tgt_num)
+{
+	fc_port_t *fcport = NULL;
+
+	list_for_each_entry(fcport, &vha->vp_fcports, list) {
+		if (fcport->rport->number == tgt_num)
+			return fcport->rport;
+	}
+	return NULL;
+}
+
+static int
+qla2x00_get_tgt_stats(struct bsg_job *bsg_job)
+{
+	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct ql_vnd_tgt_stats_param *req_data;
+	u32 req_data_len;
+	int ret = 0;
+	u64 response_len = 0;
+	struct ql_vnd_tgt_stats_resp *data = NULL;
+	struct fc_rport *rport = NULL;
+
+	if (!vha->flags.online) {
+		ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
+		return -EIO;
+	}
+
+	req_data_len = bsg_job->request_payload.payload_len;
+
+	if (req_data_len != sizeof(struct ql_vnd_stat_entry)) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
+		return -EIO;
+	}
+
+	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+	if (!req_data) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
+		return -ENOMEM;
+	}
+
+	/* Copy the request buffer in req_data */
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+			  bsg_job->request_payload.sg_cnt,
+			  req_data, req_data_len);
+
+	response_len = sizeof(struct ql_vnd_tgt_stats_resp) +
+		sizeof(struct ql_vnd_stat_entry);
+
+	/* structure + size for one entry */
+	data = kzalloc(response_len, GFP_KERNEL);
+	if (!data) {
+		kfree(req_data);
+		return -ENOMEM;
+	}
+
+	if (response_len > bsg_job->reply_payload.payload_len) {
+		data->status = EXT_STATUS_BUFFER_TOO_SMALL;
+		bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
+		bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
+
+		bsg_reply->reply_payload_rcv_len =
+			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+					    bsg_job->reply_payload.sg_cnt, &data,
+					    sizeof(struct ql_vnd_tgt_stats_resp));
+
+		bsg_reply->result = DID_OK;
+		bsg_job_done(bsg_job, bsg_reply->result,
+			     bsg_reply->reply_payload_rcv_len);
+		goto tgt_stat_out;
+	}
+
+	rport = qla2xxx_find_rport(vha, req_data->tgt_id);
+	if (!rport) {
+		ql_log(ql_log_warn, vha, 0x0000, "target %d not found.\n", req_data->tgt_id);
+		ret = EXT_STATUS_INVALID_PARAM;
+		data->status = EXT_STATUS_INVALID_PARAM;
+		goto reply;
+	}
+
+	ret = qla2xxx_get_tgt_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
+				    rport, (void *)data, response_len);
+
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+reply:
+	bsg_reply->reply_payload_rcv_len =
+		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+				    bsg_job->reply_payload.sg_cnt, data,
+				    response_len);
+	bsg_reply->result = DID_OK;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+tgt_stat_out:
+	kfree(data);
+	kfree(req_data);
+
+	return ret;
+}
+
+static int
+qla2x00_manage_host_port(struct bsg_job *bsg_job)
+{
+	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
+	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+	struct ql_vnd_mng_host_port_param *req_data;
+	struct ql_vnd_mng_host_port_resp rsp_data;
+	u32 req_data_len;
+	int ret = 0;
+
+	req_data_len = bsg_job->request_payload.payload_len;
+
+	if (req_data_len != sizeof(struct ql_vnd_mng_host_port_param)) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
+		return -EIO;
+	}
+
+	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
+	if (!req_data) {
+		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
+		return -ENOMEM;
+	}
+
+	/* Copy the request buffer in req_data */
+	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
+			  bsg_job->request_payload.sg_cnt, req_data, req_data_len);
+
+	switch (req_data->action) {
+	case 0:
+		ret = qla2xxx_enable_port(vha->host);
+		break;
+	case 1:
+		ret = qla2xxx_disable_port(vha->host);
+		break;
+	default:
+		ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
+		ret = -EIO;
+		break;
+	}
+
+	kfree(req_data);
+
+	/* Prepare response */
+	rsp_data.status = ret;
+	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
+	bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_port_resp);
+
+	bsg_reply->reply_payload_rcv_len =
+		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
+				    bsg_job->reply_payload.sg_cnt, &rsp_data,
+				    sizeof(struct ql_vnd_mng_host_port_resp));
+	bsg_reply->result = DID_OK;
+	bsg_job_done(bsg_job, bsg_reply->result,
+		     bsg_reply->reply_payload_rcv_len);
+
+	return ret;
+}
+
 static int
 qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
 {
@@ -2520,6 +2838,18 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
 	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
 		return qla2x00_get_flash_image_status(bsg_job);
 
+	case QL_VND_MANAGE_HOST_STATS:
+		return qla2x00_manage_host_stats(bsg_job);
+
+	case QL_VND_GET_HOST_STATS:
+		return qla2x00_get_host_stats(bsg_job);
+
+	case QL_VND_GET_TGT_STATS:
+		return qla2x00_get_tgt_stats(bsg_job);
+
+	case QL_VND_MANAGE_HOST_PORT:
+		return qla2x00_manage_host_port(bsg_job);
+
 	default:
 		return -ENOSYS;
 	}
@@ -2547,6 +2877,17 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
 		vha = shost_priv(host);
 	}
 
+	/* Disable port will bring down the chip, allow enable command */
+	if (bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_MANAGE_HOST_PORT ||
+	    bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_GET_HOST_STATS)
+		goto skip_chip_chk;
+
+	if (vha->hw->flags.port_isolated) {
+		bsg_reply->result = DID_ERROR;
+		/* operation not permitted */
+		return -EPERM;
+	}
+
 	if (qla2x00_chip_is_down(vha)) {
 		ql_dbg(ql_dbg_user, vha, 0x709f,
 		    "BSG: ISP abort active/needed -- cmd=%d.\n",
@@ -2554,6 +2895,7 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
 		return -EBUSY;
 	}
 
+skip_chip_chk:
 	ql_dbg(ql_dbg_user, vha, 0x7000,
 	    "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode);
 
diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
index 1a09b5512267..0274e99e4a12 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.h
+++ b/drivers/scsi/qla2xxx/qla_bsg.h
@@ -31,6 +31,10 @@
 #define QL_VND_DPORT_DIAGNOSTICS	0x19
 #define QL_VND_GET_PRIV_STATS_EX	0x1A
 #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E
+#define QL_VND_MANAGE_HOST_STATS	0x23
+#define QL_VND_GET_HOST_STATS		0x24
+#define QL_VND_GET_TGT_STATS		0x25
+#define QL_VND_MANAGE_HOST_PORT		0x26
 
 /* BSG Vendor specific subcode returns */
 #define EXT_STATUS_OK			0
@@ -40,6 +44,7 @@
 #define EXT_STATUS_DATA_OVERRUN		7
 #define EXT_STATUS_DATA_UNDERRUN	8
 #define EXT_STATUS_MAILBOX		11
+#define EXT_STATUS_BUFFER_TOO_SMALL	16
 #define EXT_STATUS_NO_MEMORY		17
 #define EXT_STATUS_DEVICE_OFFLINE	22
 
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 30c7e5e63851..f2f1b0231033 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2557,6 +2557,10 @@ typedef struct fc_port {
 	u16 n2n_chip_reset;
 
 	struct dentry *dfs_rport_dir;
+
+	u64 tgt_short_link_down_cnt;
+	u64 tgt_link_down_time;
+	u64 dev_loss_tmo;
 } fc_port_t;
 
 enum {
@@ -3922,6 +3926,7 @@ struct qla_hw_data {
 		uint32_t	scm_enabled:1;
 		uint32_t	max_req_queue_warned:1;
 		uint32_t	plogi_template_valid:1;
+		uint32_t	port_isolated:1;
 	} flags;
 
 	uint16_t max_exchg;
@@ -4851,6 +4856,13 @@ typedef struct scsi_qla_host {
 	uint8_t	scm_fabric_connection_flags;
 
 	unsigned int irq_offset;
+
+	u64 hw_err_cnt;
+	u64 interface_err_cnt;
+	u64 cmd_timeout_cnt;
+	u64 reset_cmd_err_cnt;
+	u64 link_down_time;
+	u64 short_link_down_cnt;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
@@ -5174,6 +5186,65 @@ struct sff_8247_a0 {
 #define PRLI_PHASE(_cls) \
 	((_cls == DSC_LS_PRLI_PEND) || (_cls == DSC_LS_PRLI_COMP))
 
+enum ql_vnd_host_stat_action {
+	stop = 0,
+	start,
+	clear,
+};
+
+struct ql_vnd_mng_host_stats_param {
+	u32 stat_type;
+	enum ql_vnd_host_stat_action action;
+} __packed;
+
+struct ql_vnd_mng_host_stats_resp {
+	u32 status;
+} __packed;
+
+struct ql_vnd_stats_param {
+	u32 stat_type;
+} __packed;
+
+struct ql_vnd_tgt_stats_param {
+	s32 tgt_id;
+	u32 stat_type;
+} __packed;
+
+enum ql_vnd_host_port_action {
+	enable = 0,
+	disable,
+};
+
+struct ql_vnd_mng_host_port_param {
+	enum ql_vnd_host_port_action action;
+} __packed;
+
+struct ql_vnd_mng_host_port_resp {
+	u32 status;
+} __packed;
+
+struct ql_vnd_stat_entry {
+	u32 stat_type;	/* Failure type */
+	u32 tgt_num;	/* Target Num */
+	u64 cnt;	/* Counter value */
+} __packed;
+
+struct ql_vnd_stats {
+	u64 entry_count; /* Num of entries */
+	u64 rservd;
+	struct ql_vnd_stat_entry entry[0]; /* Place holder of entries */
+} __packed;
+
+struct ql_vnd_host_stats_resp {
+	u32 status;
+	struct ql_vnd_stats stats;
+} __packed;
+
+struct ql_vnd_tgt_stats_resp {
+	u32 status;
+	struct ql_vnd_stats stats;
+} __packed;
+
 #include "qla_target.h"
 #include "qla_gbl.h"
 #include "qla_dbg.h"
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index e39b4f2da73a..708f82311b83 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -945,4 +945,27 @@ extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
 /* nvme.c */
 void qla_nvme_unregister_remote_port(struct fc_port *fcport);
 void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
+
+#define QLA2XX_HW_ERROR			BIT_0
+#define QLA2XX_SHT_LNK_DWN		BIT_1
+#define QLA2XX_INT_ERR			BIT_2
+#define QLA2XX_CMD_TIMEOUT		BIT_3
+#define QLA2XX_RESET_CMD_ERR		BIT_4
+#define QLA2XX_TGT_SHT_LNK_DOWN		BIT_17
+
+#define QLA2XX_MAX_LINK_DOWN_TIME	100
+
+int qla2xxx_start_stats(struct Scsi_Host *shost, u32 flags);
+int qla2xxx_stop_stats(struct Scsi_Host *shost, u32 flags);
+int qla2xxx_reset_stats(struct Scsi_Host *shost, u32 flags);
+
+int qla2xxx_get_ini_stats(struct Scsi_Host *shost, u32 flags, void *data, u64 size);
+int qla2xxx_get_tgt_stats(struct Scsi_Host *shost, u32 flags,
+			  struct fc_rport *rport, void *data, u64 size);
+int qla2xxx_disable_port(struct Scsi_Host *shost);
+int qla2xxx_enable_port(struct Scsi_Host *shost);
+
+uint64_t qla2x00_get_num_tgts(scsi_qla_host_t *vha);
+uint64_t qla2x00_count_set_bits(u32 num);
+
 #endif /* _QLA_GBL_H */
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 391ac75e3de3..517d358b0031 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3563,6 +3563,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
 					       __func__, __LINE__,
 					       fcport->port_name);
 
+					fcport->tgt_link_down_time = 0;
 					qlt_schedule_sess_for_deletion(fcport);
 					continue;
 				}
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index dcc0f0d823db..410ff5534a59 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -4993,6 +4993,9 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
 	fcport->login_retry = vha->hw->login_retry_count;
 	fcport->chip_reset = vha->hw->base_qpair->chip_reset;
 	fcport->logout_on_delete = 1;
+	fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
+	fcport->tgt_short_link_down_cnt = 0;
+	fcport->dev_loss_tmo = 0;
 
 	if (!fcport->ct_desc.ct_sns) {
 		ql_log(ql_log_warn, vha, 0xd049,
@@ -5490,6 +5493,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
 	spin_lock_irqsave(fcport->vha->host->host_lock, flags);
 	*((fc_port_t **)rport->dd_data) = fcport;
 	spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
+	fcport->dev_loss_tmo = rport->dev_loss_tmo;
 
 	rport->supported_classes = fcport->supported_classes;
 
@@ -5548,6 +5552,11 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
 		fcport->logout_on_delete = 1;
 	fcport->n2n_chip_reset = fcport->n2n_link_reset_cnt = 0;
 
+	if (fcport->tgt_link_down_time < fcport->dev_loss_tmo) {
+		fcport->tgt_short_link_down_cnt++;
+		fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
+	}
+
 	switch (vha->hw->current_topology) {
 	case ISP_CFG_N:
 	case ISP_CFG_NL:
@@ -6908,6 +6917,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
 	if (vha->flags.online) {
 		qla2x00_abort_isp_cleanup(vha);
 
+		if (vha->hw->flags.port_isolated)
+			return status;
+
 		if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags)) {
 			ha->flags.chip_reset_done = 1;
 			vha->flags.online = 1;
@@ -7029,6 +7041,11 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
 
 	}
 
+	if (vha->hw->flags.port_isolated) {
+		qla2x00_abort_isp_cleanup(vha);
+		return status;
+	}
+
 	if (!status) {
 		ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
 		qla2x00_configure_hba(vha);
@@ -9171,3 +9188,202 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
 fail:
 	return ret;
 }
+
+uint64_t
+qla2x00_count_set_bits(uint32_t num)
+{
+	/* Brian Kernighan's Alogorithm */
+	u64 count = 0;
+
+	while (num) {
+		num &= (num - 1);
+		count++;
+	}
+	return count;
+}
+
+uint64_t
+qla2x00_get_num_tgts(scsi_qla_host_t *vha)
+{
+	fc_port_t *f, *tf;
+	u64 count = 0;
+
+	f = NULL;
+	tf = NULL;
+
+	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
+		if (f->port_type != FCT_TARGET)
+			continue;
+		count++;
+	}
+	return count;
+}
+
+int qla2xxx_reset_stats(struct Scsi_Host *host, u32 flags)
+{
+	scsi_qla_host_t *vha = shost_priv(host);
+	fc_port_t *fcport = NULL;
+	unsigned long int_flags;
+
+	if (flags & QLA2XX_HW_ERROR)
+		vha->hw_err_cnt = 0;
+	if (flags & QLA2XX_SHT_LNK_DWN)
+		vha->short_link_down_cnt = 0;
+	if (flags & QLA2XX_INT_ERR)
+		vha->interface_err_cnt = 0;
+	if (flags & QLA2XX_CMD_TIMEOUT)
+		vha->cmd_timeout_cnt = 0;
+	if (flags & QLA2XX_RESET_CMD_ERR)
+		vha->reset_cmd_err_cnt = 0;
+	if (flags & QLA2XX_TGT_SHT_LNK_DOWN) {
+		spin_lock_irqsave(&vha->hw->tgt.sess_lock, int_flags);
+		list_for_each_entry(fcport, &vha->vp_fcports, list) {
+			fcport->tgt_short_link_down_cnt = 0;
+			fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
+		}
+		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, int_flags);
+	}
+	vha->link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
+	return 0;
+}
+
+int qla2xxx_start_stats(struct Scsi_Host *host, u32 flags)
+{
+	return qla2xxx_reset_stats(host, flags);
+}
+
+int qla2xxx_stop_stats(struct Scsi_Host *host, u32 flags)
+{
+	return qla2xxx_reset_stats(host, flags);
+}
+
+int qla2xxx_get_ini_stats(struct Scsi_Host *host, u32 flags,
+			  void *data, u64 size)
+{
+	scsi_qla_host_t *vha = shost_priv(host);
+	struct ql_vnd_host_stats_resp *resp = (struct ql_vnd_host_stats_resp *)data;
+	struct ql_vnd_stats *rsp_data = &resp->stats;
+	u64 ini_entry_count = 0;
+	u64 i = 0;
+	u64 entry_count = 0;
+	u64 num_tgt = 0;
+	u32 tmp_stat_type = 0;
+	fc_port_t *fcport = NULL;
+	unsigned long int_flags;
+
+	/* Copy stat type to work on it */
+	tmp_stat_type = flags;
+
+	if (tmp_stat_type & BIT_17) {
+		num_tgt = qla2x00_get_num_tgts(vha);
+		/* unset BIT_17 */
+		tmp_stat_type &= ~(1 << 17);
+	}
+	ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
+
+	entry_count = ini_entry_count + num_tgt;
+
+	rsp_data->entry_count = entry_count;
+
+	i = 0;
+	if (flags & QLA2XX_HW_ERROR) {
+		rsp_data->entry[i].stat_type = QLA2XX_HW_ERROR;
+		rsp_data->entry[i].tgt_num = 0x0;
+		rsp_data->entry[i].cnt = vha->hw_err_cnt;
+		i++;
+	}
+
+	if (flags & QLA2XX_SHT_LNK_DWN) {
+		rsp_data->entry[i].stat_type = QLA2XX_SHT_LNK_DWN;
+		rsp_data->entry[i].tgt_num = 0x0;
+		rsp_data->entry[i].cnt = vha->short_link_down_cnt;
+		i++;
+	}
+
+	if (flags & QLA2XX_INT_ERR) {
+		rsp_data->entry[i].stat_type = QLA2XX_INT_ERR;
+		rsp_data->entry[i].tgt_num = 0x0;
+		rsp_data->entry[i].cnt = vha->interface_err_cnt;
+		i++;
+	}
+
+	if (flags & QLA2XX_CMD_TIMEOUT) {
+		rsp_data->entry[i].stat_type = QLA2XX_CMD_TIMEOUT;
+		rsp_data->entry[i].tgt_num = 0x0;
+		rsp_data->entry[i].cnt = vha->cmd_timeout_cnt;
+		i++;
+	}
+
+	if (flags & QLA2XX_RESET_CMD_ERR) {
+		rsp_data->entry[i].stat_type = QLA2XX_RESET_CMD_ERR;
+		rsp_data->entry[i].tgt_num = 0x0;
+		rsp_data->entry[i].cnt = vha->reset_cmd_err_cnt;
+		i++;
+	}
+
+	/* i will continue from previous loop, as target
+	 * entries are after initiator
+	 */
+	if (flags & QLA2XX_TGT_SHT_LNK_DOWN) {
+		spin_lock_irqsave(&vha->hw->tgt.sess_lock, int_flags);
+		list_for_each_entry(fcport, &vha->vp_fcports, list) {
+			if (fcport->port_type != FCT_TARGET)
+				continue;
+			if (!fcport->rport)
+				continue;
+			rsp_data->entry[i].stat_type = QLA2XX_TGT_SHT_LNK_DOWN;
+			rsp_data->entry[i].tgt_num = fcport->rport->number;
+			rsp_data->entry[i].cnt = fcport->tgt_short_link_down_cnt;
+			i++;
+		}
+		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, int_flags);
+	}
+	resp->status = EXT_STATUS_OK;
+
+	return 0;
+}
+
+int qla2xxx_get_tgt_stats(struct Scsi_Host *host, u32 flags,
+			  struct fc_rport *rport, void *data, u64 size)
+{
+	struct ql_vnd_tgt_stats_resp *tgt_data = data;
+	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
+
+	tgt_data->status = 0;
+	tgt_data->stats.entry_count = 1;
+	tgt_data->stats.entry[0].stat_type = flags;
+	tgt_data->stats.entry[0].tgt_num = rport->number;
+	tgt_data->stats.entry[0].cnt = fcport->tgt_short_link_down_cnt;
+
+	return 0;
+}
+
+int qla2xxx_disable_port(struct Scsi_Host *host)
+{
+	scsi_qla_host_t *vha = shost_priv(host);
+
+	vha->hw->flags.port_isolated = 1;
+
+	if (qla2x00_chip_is_down(vha))
+		return 0;
+
+	if (vha->flags.online) {
+		qla2x00_abort_isp_cleanup(vha);
+		qla2x00_wait_for_sess_deletion(vha);
+	}
+
+	return 0;
+}
+
+int qla2xxx_enable_port(struct Scsi_Host *host)
+{
+	scsi_qla_host_t *vha = shost_priv(host);
+
+	vha->hw->flags.port_isolated = 0;
+	/* Set the flag to 1, so that isp_abort can proceed */
+	vha->flags.online = 1;
+	set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+	qla2xxx_wake_dpc(vha);
+
+	return 0;
+}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index f9142dbec112..9cf8326ab9fc 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1059,6 +1059,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 
 	case MBA_SYSTEM_ERR:		/* System Error */
 		mbx = 0;
+
+		vha->hw_err_cnt++;
+
 		if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
 		    IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
 			u16 m[4];
@@ -1112,6 +1115,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		ql_log(ql_log_warn, vha, 0x5006,
 		    "ISP Request Transfer Error (%x).\n",  mb[1]);
 
+		vha->hw_err_cnt++;
+
 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 		break;
 
@@ -1119,6 +1124,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		ql_log(ql_log_warn, vha, 0x5007,
 		    "ISP Response Transfer Error (%x).\n", mb[1]);
 
+		vha->hw_err_cnt++;
+
 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 		break;
 
@@ -1176,12 +1183,18 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		vha->flags.management_server_logged_in = 0;
 		qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
 
+		if (vha->link_down_time < vha->hw->port_down_retry_count) {
+			vha->short_link_down_cnt++;
+			vha->link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
+		}
+
 		break;
 
 	case MBA_LOOP_DOWN:		/* Loop Down Event */
 		SAVE_TOPO(ha);
 		ha->flags.lip_ae = 0;
 		ha->current_topology = 0;
+		vha->link_down_time = 0;
 
 		mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
 			? rd_reg_word(&reg24->mailbox4) : 0;
@@ -1503,6 +1516,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		ql_dbg(ql_dbg_async, vha, 0x5016,
 		    "Discard RND Frame -- %04x %04x %04x.\n",
 		    mb[1], mb[2], mb[3]);
+		vha->interface_err_cnt++;
 		break;
 
 	case MBA_TRACE_NOTIFICATION:
@@ -1592,6 +1606,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 
 	case MBA_IDC_AEN:
 		if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+			vha->hw_err_cnt++;
 			qla27xx_handle_8200_aen(vha, mb);
 		} else if (IS_QLA83XX(ha)) {
 			mb[4] = rd_reg_word(&reg24->mailbox4);
@@ -3101,6 +3116,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 				    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
 				    resid, scsi_bufflen(cp));
 
+				vha->interface_err_cnt++;
+
 				res = DID_ERROR << 16 | lscsi_status;
 				goto check_scsi_status;
 			}
@@ -3126,6 +3143,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 			    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
 			    resid, scsi_bufflen(cp));
 
+			vha->interface_err_cnt++;
+
 			res = DID_ERROR << 16 | lscsi_status;
 			goto check_scsi_status;
 		} else {
@@ -3208,6 +3227,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 
 	case CS_TRANSPORT:
 		res = DID_ERROR << 16;
+		vha->hw_err_cnt++;
 
 		if (!IS_PI_SPLIT_DET_CAPABLE(ha))
 			break;
@@ -3228,6 +3248,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee,
 		    pkt, sizeof(*sts24));
 		res = DID_ERROR << 16;
+		vha->hw_err_cnt++;
 		break;
 	default:
 		res = DID_ERROR << 16;
@@ -3839,6 +3860,7 @@ qla24xx_msix_default(int irq, void *dev_id)
 			    hccr);
 
 			qla2xxx_check_risc_status(vha);
+			vha->hw_err_cnt++;
 
 			ha->isp_ops->fw_dump(vha);
 			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index d7d4ab65009c..f438cdedca23 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -180,6 +180,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 		ql_log(ql_log_warn, vha, 0xd035,
 		    "Cmd access timeout, cmd=0x%x, Exiting.\n",
 		    mcp->mb[0]);
+		vha->hw_err_cnt++;
 		atomic_dec(&ha->num_pend_mbx_stage1);
 		return QLA_FUNCTION_TIMEOUT;
 	}
@@ -307,6 +308,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 				atomic_dec(&ha->num_pend_mbx_stage2);
 				ql_dbg(ql_dbg_mbx, vha, 0x1012,
 				    "Pending mailbox timeout, exiting.\n");
+				vha->hw_err_cnt++;
 				rval = QLA_FUNCTION_TIMEOUT;
 				goto premature_exit;
 			}
@@ -418,6 +420,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 			    "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n",
 			    command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
 			    mb[7], host_status, hccr);
+			vha->hw_err_cnt++;
 
 		} else {
 			mb[0] = RD_MAILBOX_REG(ha, &reg->isp, 0);
@@ -425,6 +428,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 			ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
 			    "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
 			    "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
+			vha->hw_err_cnt++;
 		}
 		ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
 
@@ -497,6 +501,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 				    "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP "
 				    "abort.\n", command, mcp->mb[0],
 				    ha->flags.eeh_busy);
+				vha->hw_err_cnt++;
 				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 				qla2xxx_wake_dpc(vha);
 			}
@@ -521,6 +526,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
 				    "Mailbox cmd timeout occurred, cmd=0x%x, "
 				    "mb[0]=0x%x. Scheduling ISP abort ",
 				    command, mcp->mb[0]);
+				vha->hw_err_cnt++;
 				set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
 				clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 				/* Allow next mbx cmd to come in. */
@@ -625,6 +631,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
 		ql_dbg(ql_dbg_mbx, vha, 0x1023,
 		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
 		    rval, mcp->mb[0], mcp->mb[1]);
+		vha->hw_err_cnt++;
 	} else {
 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024,
 		    "Done %s.\n", __func__);
@@ -736,6 +743,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
 
 		ql_dbg(ql_dbg_mbx, vha, 0x1026,
 		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
+		vha->hw_err_cnt++;
 		return rval;
 	}
 
@@ -1313,6 +1321,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
 	if (rval != QLA_SUCCESS) {
 		/*EMPTY*/
 		ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
+		vha->hw_err_cnt++;
 	} else {
 		/*EMPTY*/
 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034,
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index f80abe28f35a..a760cb38e487 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1274,6 +1274,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 	sp = scsi_cmd_priv(cmd);
 	qpair = sp->qpair;
 
+	vha->cmd_timeout_cnt++;
+
 	if ((sp->fcport && sp->fcport->deleted) || !qpair)
 		return SUCCESS;
 
@@ -1442,6 +1444,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
 	    "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name,
 	    reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun,
 	    cmd);
+	vha->reset_cmd_err_cnt++;
 	return FAILED;
 }
 
@@ -3141,6 +3144,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 	ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED;
 	ha->mr.fcport.scan_state = 1;
 
+	qla2xxx_reset_stats(host, QLA2XX_HW_ERROR | QLA2XX_SHT_LNK_DWN |
+			    QLA2XX_INT_ERR | QLA2XX_CMD_TIMEOUT |
+			    QLA2XX_RESET_CMD_ERR | QLA2XX_TGT_SHT_LNK_DOWN);
+
 	/* Set the SG table size based on ISP type */
 	if (!IS_FWI2_CAPABLE(ha)) {
 		if (IS_QLA2100(ha))
@@ -5090,6 +5097,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
 			fcport->d_id = e->u.new_sess.id;
 			fcport->flags |= FCF_FABRIC_DEVICE;
 			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
+			fcport->tgt_short_link_down_cnt = 0;
 
 			memcpy(fcport->port_name, e->u.new_sess.port_name,
 			    WWN_SIZE);
@@ -7061,6 +7069,8 @@ qla2x00_timer(struct timer_list *t)
 	uint16_t        w;
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req;
+	unsigned long flags;
+	fc_port_t *fcport = NULL;
 
 	if (ha->flags.eeh_busy) {
 		ql_dbg(ql_dbg_timer, vha, 0x6000,
@@ -7092,6 +7102,16 @@ qla2x00_timer(struct timer_list *t)
 	if (!vha->vp_idx && IS_QLAFX00(ha))
 		qlafx00_timer_routine(vha);
 
+	if (vha->link_down_time < QLA2XX_MAX_LINK_DOWN_TIME)
+		vha->link_down_time++;
+
+	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
+	list_for_each_entry(fcport, &vha->vp_fcports, list) {
+		if (fcport->tgt_link_down_time < QLA2XX_MAX_LINK_DOWN_TIME)
+			fcport->tgt_link_down_time++;
+	}
+	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
+
 	/* Loop down handler. */
 	if (atomic_read(&vha->loop_down_timer) > 0 &&
 	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 2/7] qla2xxx: Add error counters to debugfs node
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
  2021-01-05 10:38 ` [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:06   ` Himanshu Madhani
  2021-01-05 10:38 ` [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level Nilesh Javali
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Saurav Kashyap <skashyap@marvell.com>

Display error counters via debugfs node.

Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_dfs.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index d5ebcf7d70ff..ccce0eab844e 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -286,6 +286,10 @@ qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
 		core_qla_snd_status, qla_core_ret_sta_ctio, core_qla_free_cmd,
 		num_q_full_sent, num_alloc_iocb_failed, num_term_xchg_sent;
 	u16 i;
+	fc_port_t *fcport = NULL;
+
+	if (qla2x00_chip_is_down(vha))
+		return 0;
 
 	qla_core_sbt_cmd = qpair->tgt_counters.qla_core_sbt_cmd;
 	core_qla_que_buf = qpair->tgt_counters.core_qla_que_buf;
@@ -349,6 +353,30 @@ qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
 		vha->qla_stats.qla_dif_stats.dif_ref_tag_err);
 	seq_printf(s, "DIF App tag err = %d\n",
 		vha->qla_stats.qla_dif_stats.dif_app_tag_err);
+
+	seq_puts(s, "\n");
+	seq_puts(s, "Initiator Error Counters\n");
+	seq_printf(s, "HW Error Count =		%14lld\n",
+		   vha->hw_err_cnt);
+	seq_printf(s, "Link Down Count =	%14lld\n",
+		   vha->short_link_down_cnt);
+	seq_printf(s, "Interface Err Count =	%14lld\n",
+		   vha->interface_err_cnt);
+	seq_printf(s, "Cmd Timeout Count =	%14lld\n",
+		   vha->cmd_timeout_cnt);
+	seq_printf(s, "Reset Count =		%14lld\n",
+		   vha->reset_cmd_err_cnt);
+	seq_puts(s, "\n");
+
+	list_for_each_entry(fcport, &vha->vp_fcports, list) {
+		if (!fcport || !fcport->rport)
+			continue;
+
+		seq_printf(s, "Target Num = %7d Link Down Count = %14lld\n",
+			   fcport->rport->number, fcport->tgt_short_link_down_cnt);
+	}
+	seq_puts(s, "\n");
+
 	return 0;
 }
 
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
  2021-01-05 10:38 ` [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port Nilesh Javali
  2021-01-05 10:38 ` [PATCH v3 2/7] qla2xxx: Add error counters to debugfs node Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:06   ` Himanshu Madhani
  2021-01-05 10:38 ` [PATCH v3 4/7] qla2xxx: Wait for ABTS response on I/O timeouts for NVMe Nilesh Javali
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Saurav Kashyap <skashyap@marvell.com>

This change will aid in debugging issues where debug level is not set.

Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_init.c | 10 +++----
 drivers/scsi/qla2xxx/qla_isr.c  | 52 ++++++++++++++++-----------------
 2 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 410ff5534a59..221369cdf71f 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -347,11 +347,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
 	if (NVME_TARGET(vha->hw, fcport))
 		lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
 
-	ql_dbg(ql_dbg_disc, vha, 0x2072,
-	    "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
-		"retries=%d.\n", fcport->port_name, sp->handle, fcport->loop_id,
-	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
-	    fcport->login_retry);
+	ql_log(ql_log_warn, vha, 0x2072,
+	       "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x retries=%d.\n",
+	       fcport->port_name, sp->handle, fcport->loop_id,
+	       fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
+	       fcport->login_retry);
 
 	rval = qla2x00_start_sp(sp);
 	if (rval != QLA_SUCCESS) {
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 9cf8326ab9fc..bfc8bbaeea46 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -1455,9 +1455,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
 		if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
 			break;
 
-		ql_dbg(ql_dbg_async, vha, 0x5013,
-		    "RSCN database changed -- %04x %04x %04x.\n",
-		    mb[1], mb[2], mb[3]);
+		ql_log(ql_log_warn, vha, 0x5013,
+		       "RSCN database changed -- %04x %04x %04x.\n",
+		       mb[1], mb[2], mb[3]);
 
 		rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
 		host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
@@ -2221,12 +2221,12 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
 		break;
 	}
 
-	ql_dbg(ql_dbg_async, sp->vha, 0x5037,
-	    "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
-	    type, sp->handle, fcport->d_id.b24, fcport->port_name,
-	    le16_to_cpu(logio->comp_status),
-	    le32_to_cpu(logio->io_parameter[0]),
-	    le32_to_cpu(logio->io_parameter[1]));
+	ql_log(ql_log_warn, sp->vha, 0x5037,
+	       "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
+	       type, sp->handle, fcport->d_id.b24, fcport->port_name,
+	       le16_to_cpu(logio->comp_status),
+	       le32_to_cpu(logio->io_parameter[0]),
+	       le32_to_cpu(logio->io_parameter[1]));
 
 logio_done:
 	sp->done(sp, 0);
@@ -2389,9 +2389,9 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 
 		tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
 		if (fd->transferred_length != tgt_xfer_len) {
-			ql_dbg(ql_dbg_io, fcport->vha, 0x3079,
-				"Dropped frame(s) detected (sent/rcvd=%u/%u).\n",
-				tgt_xfer_len, fd->transferred_length);
+			ql_log(ql_log_warn, fcport->vha, 0x3079,
+			       "Dropped frame(s) detected (sent/rcvd=%u/%u).\n",
+			       tgt_xfer_len, fd->transferred_length);
 			logit = 1;
 		} else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
 			/*
@@ -3112,9 +3112,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 		scsi_set_resid(cp, resid);
 		if (scsi_status & SS_RESIDUAL_UNDER) {
 			if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
-				ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
-				    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
-				    resid, scsi_bufflen(cp));
+				ql_log(ql_log_warn, fcport->vha, 0x301d,
+				       "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
+				       resid, scsi_bufflen(cp));
 
 				vha->interface_err_cnt++;
 
@@ -3139,9 +3139,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 			 * task not completed.
 			 */
 
-			ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
-			    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
-			    resid, scsi_bufflen(cp));
+			ql_log(ql_log_warn, fcport->vha, 0x301f,
+			       "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
+			       resid, scsi_bufflen(cp));
 
 			vha->interface_err_cnt++;
 
@@ -3257,15 +3257,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
 
 out:
 	if (logit)
-		ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
-		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu "
-		    "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
-		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
-		    comp_status, scsi_status, res, vha->host_no,
-		    cp->device->id, cp->device->lun, fcport->d_id.b.domain,
-		    fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
-		    cp->cmnd, scsi_bufflen(cp), rsp_info_len,
-		    resid_len, fw_resid_len, sp, cp);
+		ql_log(ql_log_warn, fcport->vha, 0x3022,
+		       "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
+		       comp_status, scsi_status, res, vha->host_no,
+		       cp->device->id, cp->device->lun, fcport->d_id.b.domain,
+		       fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
+		       cp->cmnd, scsi_bufflen(cp), rsp_info_len,
+		       resid_len, fw_resid_len, sp, cp);
 
 	if (rsp->status_srb == NULL)
 		sp->done(sp, res);
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 4/7] qla2xxx: Wait for ABTS response on I/O timeouts for NVMe
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
                   ` (2 preceding siblings ...)
  2021-01-05 10:38 ` [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:36   ` Himanshu Madhani
  2021-01-05 10:38 ` [PATCH v3 5/7] qla2xxx: Fix mailbox Ch erroneous error Nilesh Javali
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Bikash Hazarika <bhazarika@marvell.com>

FW needs to wait for an ABTS response before completing the I/O

Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_def.h  | 12 +++++
 drivers/scsi/qla2xxx/qla_fw.h   | 27 ++++++++--
 drivers/scsi/qla2xxx/qla_gbl.h  |  6 +++
 drivers/scsi/qla2xxx/qla_init.c |  4 ++
 drivers/scsi/qla2xxx/qla_iocb.c |  6 +++
 drivers/scsi/qla2xxx/qla_isr.c  |  8 +++
 drivers/scsi/qla2xxx/qla_mbx.c  |  6 +++
 drivers/scsi/qla2xxx/qla_nvme.c | 90 ++++++++++++++++++++++++++++++++-
 drivers/scsi/qla2xxx/qla_os.c   |  5 ++
 9 files changed, 159 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index f2f1b0231033..17da6b436e74 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2101,6 +2101,7 @@ typedef struct {
 #define CS_COMPLETE_CHKCOND	0x30	/* Error? */
 #define CS_IOCB_ERROR		0x31	/* Generic error for IOCB request
 					   failure */
+#define CS_REJECT_RECEIVED	0x4E	/* Reject received */
 #define CS_BAD_PAYLOAD		0x80	/* Driver defined */
 #define CS_UNKNOWN		0x81	/* Driver defined */
 #define CS_RETRY		0x82	/* Driver defined */
@@ -4150,6 +4151,17 @@ struct qla_hw_data {
 /* Bit 21 of fw_attributes decides the MCTP capabilities */
 #define IS_MCTP_CAPABLE(ha)	(IS_QLA2031(ha) && \
 				((ha)->fw_attributes_ext[0] & BIT_0))
+#define QLA_ABTS_FW_ENABLED(_ha)       ((_ha)->fw_attributes_ext[0] & BIT_14)
+#define QLA_SRB_NVME_LS(_sp) ((_sp)->type == SRB_NVME_LS)
+#define QLA_SRB_NVME_CMD(_sp) ((_sp)->type == SRB_NVME_CMD)
+#define QLA_NVME_IOS(_sp) (QLA_SRB_NVME_CMD(_sp) || QLA_SRB_NVME_LS(_sp))
+#define QLA_LS_ABTS_WAIT_ENABLED(_sp) \
+	(QLA_SRB_NVME_LS(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
+#define QLA_CMD_ABTS_WAIT_ENABLED(_sp) \
+	(QLA_SRB_NVME_CMD(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
+#define QLA_ABTS_WAIT_ENABLED(_sp) \
+	(QLA_NVME_IOS(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
+
 #define IS_PI_UNINIT_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
 #define IS_PI_IPGUARD_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
 #define IS_PI_DIFB_DIX0_CAPABLE(ha)	(0)
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 12b689e32883..49df418030e4 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -982,11 +982,18 @@ struct abort_entry_24xx {
 
 	uint32_t handle;		/* System handle. */
 
-	__le16	nport_handle;		/* N_PORT handle. */
-					/* or Completion status. */
+	union {
+		__le16 nport_handle;            /* N_PORT handle. */
+		__le16 comp_status;             /* Completion status. */
+	};
 
 	__le16	options;		/* Options. */
 #define AOF_NO_ABTS		BIT_0	/* Do not send any ABTS. */
+#define AOF_NO_RRQ		BIT_1   /* Do not send RRQ. */
+#define AOF_ABTS_TIMEOUT	BIT_2   /* Disable logout on ABTS timeout. */
+#define AOF_ABTS_RTY_CNT	BIT_3   /* Use driver specified retry count. */
+#define AOF_RSP_TIMEOUT		BIT_4   /* Use specified response timeout. */
+
 
 	uint32_t handle_to_abort;	/* System handle to abort. */
 
@@ -995,8 +1002,20 @@ struct abort_entry_24xx {
 
 	uint8_t port_id[3];		/* PortID of destination port. */
 	uint8_t vp_index;
-
-	uint8_t reserved_2[12];
+	u8	reserved_2[4];
+	union {
+		struct {
+			__le16 abts_rty_cnt;
+			__le16 rsp_timeout;
+		} drv;
+		struct {
+			u8	ba_rjt_vendorUnique;
+			u8	ba_rjt_reasonCodeExpl;
+			u8	ba_rjt_reasonCode;
+			u8	reserved_3;
+		} fw;
+	};
+	u8	reserved_4[4];
 };
 
 #define ABTS_RCV_TYPE		0x54
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 708f82311b83..6486f97d649e 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -177,6 +177,7 @@ extern int ql2xexlogins;
 extern int ql2xdifbundlinginternalbuffers;
 extern int ql2xfulldump_on_mpifail;
 extern int ql2xenforce_iocb_limit;
+extern int ql2xabts_wait_nvme;
 
 extern int qla2x00_loop_reset(scsi_qla_host_t *);
 extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
@@ -941,6 +942,11 @@ int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
 extern void qla24xx_process_purex_list(struct purex_list *);
 extern void qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp);
 extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
+extern void qla_wait_nvme_release_cmd_kref(srb_t *sp);
+extern void qla_nvme_abort_set_option
+		(struct abort_entry_24xx *abt, srb_t *sp);
+extern void qla_nvme_abort_process_comp_status
+		(struct abort_entry_24xx *abt, srb_t *sp);
 
 /* nvme.c */
 void qla_nvme_unregister_remote_port(struct fc_port *fcport);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 221369cdf71f..a6ab2629b7cf 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -136,6 +136,10 @@ static void qla24xx_abort_iocb_timeout(void *data)
 static void qla24xx_abort_sp_done(srb_t *sp, int res)
 {
 	struct srb_iocb *abt = &sp->u.iocb_cmd;
+	srb_t *orig_sp = sp->cmd_sp;
+
+	if (orig_sp)
+		qla_wait_nvme_release_cmd_kref(orig_sp);
 
 	del_timer(&sp->u.iocb_cmd.timer);
 	if (sp->flags & SRB_WAKEUP_ON_COMP)
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index c532c74ca1ab..e27359b294d3 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -3571,6 +3571,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
 	struct srb_iocb *aio = &sp->u.iocb_cmd;
 	scsi_qla_host_t *vha = sp->vha;
 	struct req_que *req = sp->qpair->req;
+	srb_t *orig_sp = sp->cmd_sp;
 
 	memset(abt_iocb, 0, sizeof(struct abort_entry_24xx));
 	abt_iocb->entry_type = ABORT_IOCB_TYPE;
@@ -3587,6 +3588,11 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
 			    aio->u.abt.cmd_hndl);
 	abt_iocb->vp_index = vha->vp_idx;
 	abt_iocb->req_que_no = aio->u.abt.req_que_no;
+
+	/* need to pass original sp */
+	if (orig_sp)
+		qla_nvme_abort_set_option(abt_iocb, orig_sp);
+
 	/* Send the command to the firmware */
 	wmb();
 }
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index bfc8bbaeea46..a4a52a2d724e 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -5,6 +5,7 @@
  */
 #include "qla_def.h"
 #include "qla_target.h"
+#include "qla_gbl.h"
 
 #include <linux/delay.h>
 #include <linux/slab.h>
@@ -3431,6 +3432,7 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 {
 	const char func[] = "ABT_IOCB";
 	srb_t *sp;
+	srb_t *orig_sp = NULL;
 	struct srb_iocb *abt;
 
 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
@@ -3439,6 +3441,12 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
 
 	abt = &sp->u.iocb_cmd;
 	abt->u.abt.comp_status = pkt->nport_handle;
+	abt->u.abt.comp_status = le16_to_cpu(pkt->comp_status);
+	orig_sp = sp->cmd_sp;
+	/* Need to pass original sp */
+	if (orig_sp)
+		qla_nvme_abort_process_comp_status(pkt, orig_sp);
+
 	sp->done(sp, 0);
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f438cdedca23..629af6fe8c55 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3243,6 +3243,8 @@ qla24xx_abort_command(srb_t *sp)
 	abt->vp_index = fcport->vha->vp_idx;
 
 	abt->req_que_no = cpu_to_le16(req->id);
+	/* Need to pass original sp */
+	qla_nvme_abort_set_option(abt, sp);
 
 	rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
 	if (rval != QLA_SUCCESS) {
@@ -3265,6 +3267,10 @@ qla24xx_abort_command(srb_t *sp)
 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091,
 		    "Done %s.\n", __func__);
 	}
+	if (rval == QLA_SUCCESS)
+		qla_nvme_abort_process_comp_status(abt, sp);
+
+	qla_wait_nvme_release_cmd_kref(sp);
 
 	dma_pool_free(ha->s_dma_pool, abt, abt_dma);
 
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index eab559b3b257..1cdb7352d6db 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -245,6 +245,12 @@ static void qla_nvme_abort_work(struct work_struct *work)
 	    __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted",
 	    sp, sp->handle, fcport, rval);
 
+	/* Returned before decreasing kref so that I/O requests
+	 * are waited until ABTS complete. This kref is decreased
+	 * at qla24xx_abort_sp_done function.
+	 */
+	if (ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp))
+		return;
 out:
 	/* kref_get was done before work was schedule. */
 	kref_put(&sp->cmd_kref, sp->put_fn);
@@ -284,7 +290,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
 	struct qla_hw_data *ha;
 	srb_t           *sp;
 
-
 	if (!fcport || (fcport && fcport->deleted))
 		return rval;
 
@@ -591,6 +596,7 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
 	sp->put_fn = qla_nvme_release_fcp_cmd_kref;
 	sp->qpair = qpair;
 	sp->vha = vha;
+	sp->cmd_sp = sp;
 	nvme = &sp->u.iocb_cmd;
 	nvme->u.nvme.desc = fd;
 
@@ -744,3 +750,85 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha)
 
 	return ret;
 }
+
+void qla_nvme_abort_set_option(struct abort_entry_24xx *abt, srb_t *orig_sp)
+{
+	struct qla_hw_data *ha;
+
+	if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp)))
+		return;
+
+	ha = orig_sp->fcport->vha->hw;
+
+	WARN_ON_ONCE(abt->options & cpu_to_le16(BIT_0));
+	/* Use Driver Specified Retry Count */
+	abt->options |= cpu_to_le16(AOF_ABTS_RTY_CNT);
+	abt->drv.abts_rty_cnt = cpu_to_le16(2);
+	/* Use specified response timeout */
+	abt->options |= cpu_to_le16(AOF_RSP_TIMEOUT);
+	/* set it to 2 * r_a_tov in secs */
+	abt->drv.rsp_timeout = cpu_to_le16(2 * (ha->r_a_tov / 10));
+}
+
+void qla_nvme_abort_process_comp_status(struct abort_entry_24xx *abt, srb_t *orig_sp)
+{
+	u16	comp_status;
+	struct scsi_qla_host *vha;
+
+	if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp)))
+		return;
+
+	vha = orig_sp->fcport->vha;
+
+	comp_status = le16_to_cpu(abt->comp_status);
+	switch (comp_status) {
+	case CS_RESET:		/* reset event aborted */
+	case CS_ABORTED:	/* IOCB was cleaned */
+	/* N_Port handle is not currently logged in */
+	case CS_TIMEOUT:
+	/* N_Port handle was logged out while waiting for ABTS to complete */
+	case CS_PORT_UNAVAILABLE:
+	/* Firmware found that the port name changed */
+	case CS_PORT_LOGGED_OUT:
+	/* BA_RJT was received for the ABTS */
+	case CS_PORT_CONFIG_CHG:
+		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09d,
+		       "Abort I/O IOCB completed with error, comp_status=%x\n",
+		comp_status);
+		break;
+
+	/* BA_RJT was received for the ABTS */
+	case CS_REJECT_RECEIVED:
+		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e,
+		       "BA_RJT was received for the ABTS rjt_vendorUnique = %u",
+			abt->fw.ba_rjt_vendorUnique);
+		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e,
+		       "ba_rjt_reasonCodeExpl = %u, ba_rjt_reasonCode = %u\n",
+		       abt->fw.ba_rjt_reasonCodeExpl, abt->fw.ba_rjt_reasonCode);
+		break;
+
+	case CS_COMPLETE:
+		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09f,
+		       "IOCB request is completed successfully comp_status=%x\n",
+		comp_status);
+		break;
+
+	case CS_IOCB_ERROR:
+		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf0a0,
+		       "IOCB request is failed, comp_status=%x\n", comp_status);
+		break;
+
+	default:
+		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf0a1,
+		       "Invalid Abort IO IOCB Completion Status %x\n",
+		comp_status);
+		break;
+	}
+}
+
+inline void qla_wait_nvme_release_cmd_kref(srb_t *orig_sp)
+{
+	if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp)))
+		return;
+	kref_put(&orig_sp->cmd_kref, orig_sp->put_fn);
+}
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a760cb38e487..3cfd83fce9c5 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -327,6 +327,11 @@ MODULE_PARM_DESC(ql2xrdpenable,
 		"Enables RDP responses. "
 		"0 - no RDP responses (default). "
 		"1 - provide RDP responses.");
+int ql2xabts_wait_nvme = 1;
+module_param(ql2xabts_wait_nvme, int, 0444);
+MODULE_PARM_DESC(ql2xabts_wait_nvme,
+		 "To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
+
 
 static void qla2x00_clear_drv_active(struct qla_hw_data *);
 static void qla2x00_free_device(scsi_qla_host_t *);
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 5/7] qla2xxx: Fix mailbox Ch erroneous error
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
                   ` (3 preceding siblings ...)
  2021-01-05 10:38 ` [PATCH v3 4/7] qla2xxx: Wait for ABTS response on I/O timeouts for NVMe Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:37   ` Himanshu Madhani
  2021-01-05 10:38 ` [PATCH v3 6/7] qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER Nilesh Javali
  2021-01-05 10:38 ` [PATCH v3 7/7] qla2xxx: Update version to 10.02.00.105-k Nilesh Javali
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Quinn Tran <qutran@marvell.com>

Mailbox Ch/dump ram extend expects mb register 10 to be
set. If not set/clear, firmware can pick up garbage from previous
invocation of this mailbox. Example: mctp dump can set mb10.
On subsequent flash read which use mailbox cmd Ch, mb10 can
retain previous value.

Cc: stable@vger.kernel.org
Signed-off-by: Quinn Tran <qutran@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_dbg.c | 1 +
 drivers/scsi/qla2xxx/qla_mbx.c | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index bb7431912d41..144a893e7335 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -202,6 +202,7 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, __be32 *ram,
 		wrt_reg_word(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
 		wrt_reg_word(&reg->mailbox1, LSW(addr));
 		wrt_reg_word(&reg->mailbox8, MSW(addr));
+		wrt_reg_word(&reg->mailbox10, 0);
 
 		wrt_reg_word(&reg->mailbox2, MSW(LSD(dump_dma)));
 		wrt_reg_word(&reg->mailbox3, LSW(LSD(dump_dma)));
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 629af6fe8c55..06c99963b2c9 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -4291,7 +4291,8 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
 	if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
 		mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
 		mcp->mb[8] = MSW(addr);
-		mcp->out_mb = MBX_8|MBX_0;
+		mcp->mb[10] = 0;
+		mcp->out_mb = MBX_10|MBX_8|MBX_0;
 	} else {
 		mcp->mb[0] = MBC_DUMP_RISC_RAM;
 		mcp->out_mb = MBX_0;
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 6/7] qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
                   ` (4 preceding siblings ...)
  2021-01-05 10:38 ` [PATCH v3 5/7] qla2xxx: Fix mailbox Ch erroneous error Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:37   ` Himanshu Madhani
  2021-01-05 10:38 ` [PATCH v3 7/7] qla2xxx: Update version to 10.02.00.105-k Nilesh Javali
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

From: Saurav Kashyap <skashyap@marvell.com>

Enable NVME confirmation bit in PRLI.

Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_iocb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index e27359b294d3..8b41cbaf8535 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -2378,6 +2378,8 @@ qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 			logio->io_parameter[0] =
 				cpu_to_le32(NVME_PRLI_SP_FIRST_BURST);
 		if (sp->vha->flags.nvme2_enabled) {
+			/* Set service parameter BIT_7 for NVME CONF support */
+			logio->io_parameter[0] |= NVME_PRLI_SP_CONF;
 			/* Set service parameter BIT_8 for SLER support */
 			logio->io_parameter[0] |=
 				cpu_to_le32(NVME_PRLI_SP_SLER);
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH v3 7/7] qla2xxx: Update version to 10.02.00.105-k
  2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
                   ` (5 preceding siblings ...)
  2021-01-05 10:38 ` [PATCH v3 6/7] qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER Nilesh Javali
@ 2021-01-05 10:38 ` Nilesh Javali
  2021-01-06 15:38   ` Himanshu Madhani
  6 siblings, 1 reply; 21+ messages in thread
From: Nilesh Javali @ 2021-01-05 10:38 UTC (permalink / raw)
  To: martin.petersen; +Cc: linux-scsi, GR-QLogic-Storage-Upstream

Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_version.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index ccec858875dd..72c648442e8d 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -6,9 +6,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "10.02.00.104-k"
+#define QLA2XXX_VERSION      "10.02.00.105-k"
 
 #define QLA_DRIVER_MAJOR_VER	10
 #define QLA_DRIVER_MINOR_VER	2
 #define QLA_DRIVER_PATCH_VER	0
-#define QLA_DRIVER_BETA_VER	104
+#define QLA_DRIVER_BETA_VER	105
-- 
2.19.0.rc0


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port
  2021-01-05 10:38 ` [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port Nilesh Javali
@ 2021-01-06 15:05   ` Himanshu Madhani
  2021-01-07  5:34     ` [EXT] " Saurav Kashyap
  0 siblings, 1 reply; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:05 UTC (permalink / raw)
  To: Nilesh Javali, Saurav Kashyap
  Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

Hi Saurav, 

> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Saurav Kashyap <skashyap@marvell.com>
> 
> This statistics will help in debugging process and checking specific
> error counts.
> 

An example of sample statistics output would be nice (not must)

> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> Reported-by: kernel test robot <lkp@intel.com>
> ---
> drivers/scsi/qla2xxx/qla_attr.c |   9 +
> drivers/scsi/qla2xxx/qla_bsg.c  | 342 ++++++++++++++++++++++++++++++++
> drivers/scsi/qla2xxx/qla_bsg.h  |   5 +
> drivers/scsi/qla2xxx/qla_def.h  |  71 +++++++
> drivers/scsi/qla2xxx/qla_gbl.h  |  23 +++
> drivers/scsi/qla2xxx/qla_gs.c   |   1 +
> drivers/scsi/qla2xxx/qla_init.c | 216 ++++++++++++++++++++
> drivers/scsi/qla2xxx/qla_isr.c  |  22 ++
> drivers/scsi/qla2xxx/qla_mbx.c  |   9 +
> drivers/scsi/qla2xxx/qla_os.c   |  20 ++
> 10 files changed, 718 insertions(+)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
> index ab45ac1e5a72..63391c9be05d 100644
> --- a/drivers/scsi/qla2xxx/qla_attr.c
> +++ b/drivers/scsi/qla2xxx/qla_attr.c
> @@ -710,6 +710,12 @@ qla2x00_sysfs_write_reset(struct file *filp, struct kobject *kobj,
> 		ql_log(ql_log_info, vha, 0x706e,
> 		    "Issuing ISP reset.\n");
> 
> +		if (vha->hw->flags.port_isolated) {
> +			ql_log(ql_log_info, vha, 0x706e,
> +			       "Port is isolated, returning.\n");
> +			return -EINVAL;
> +		}
> +
> 		scsi_block_requests(vha->host);
> 		if (IS_QLA82XX(ha)) {
> 			ha->flags.isp82xx_no_md_cap = 1;
> @@ -2717,6 +2723,9 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
> 	if (IS_QLAFX00(vha->hw))
> 		return 0;
> 
> +	if (vha->hw->flags.port_isolated)
> +		return 0;
> +
> 	qla2x00_loop_reset(vha);
> 	return 0;
> }
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> index 23b604832a54..ae3bc6ec8722 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.c
> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> @@ -4,6 +4,7 @@
>  * Copyright (c)  2003-2014 QLogic Corporation
>  */
> #include "qla_def.h"
> +#include "qla_gbl.h"
> 
> #include <linux/kthread.h>
> #include <linux/vmalloc.h>
> @@ -2444,6 +2445,323 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
> 	return 0;
> }
> 
> +static int
> +qla2x00_manage_host_stats(struct bsg_job *bsg_job)
> +{
> +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +	struct ql_vnd_mng_host_stats_param *req_data;
> +	struct ql_vnd_mng_host_stats_resp rsp_data;
> +	u32 req_data_len;
> +	int ret = 0;
> +
> +	if (!vha->flags.online) {
> +		ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
> +		return -EIO;
> +	}
> +
> +	req_data_len = bsg_job->request_payload.payload_len;
> +
> +	if (req_data_len != sizeof(struct ql_vnd_mng_host_stats_param)) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> +		return -EIO;
> +	}
> +
> +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> +	if (!req_data) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Copy the request buffer in req_data */
> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> +			  bsg_job->request_payload.sg_cnt, req_data,
> +			  req_data_len);
> +
> +	switch (req_data->action) {
> +	case 0:
> +		ret = qla2xxx_stop_stats(vha->host, req_data->stat_type);
> +		break;
> +	case 1:
> +		ret = qla2xxx_start_stats(vha->host, req_data->stat_type);
> +		break;
> +	case 2:
> +		ret = qla2xxx_reset_stats(vha->host, req_data->stat_type);
> +		break;
> +	default:
> +		ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
> +		ret = -EIO;
> +		break;
> +	}
> +

I don’t like using case 0/1/2 for the above action switch statements. Why not define it as QL_STATS_ACTION_START/STOP/RESET. 

> +	kfree(req_data);
> +
> +	/* Prepare response */
> +	rsp_data.status = ret;
> +	bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
> +
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +	bsg_reply->reply_payload_rcv_len =
> +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +				    bsg_job->reply_payload.sg_cnt,
> +				    &rsp_data,
> +				    sizeof(struct ql_vnd_mng_host_stats_resp));
> +
> +	bsg_reply->result = DID_OK;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +	return ret;
> +}
> +
> +static int
> +qla2x00_get_host_stats(struct bsg_job *bsg_job)
> +{
> +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +	struct ql_vnd_stats_param *req_data;
> +	struct ql_vnd_host_stats_resp rsp_data;
> +	u32 req_data_len;
> +	int ret = 0;
> +	u64 ini_entry_count = 0;
> +	u64 entry_count = 0;
> +	u64 tgt_num = 0;
> +	u64 tmp_stat_type = 0;
> +	u64 response_len = 0;
> +	void *data;
> +
> +	req_data_len = bsg_job->request_payload.payload_len;
> +
> +	if (req_data_len != sizeof(struct ql_vnd_stats_param)) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> +		return -EIO;
> +	}
> +
> +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> +	if (!req_data) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Copy the request buffer in req_data */
> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> +			  bsg_job->request_payload.sg_cnt, req_data, req_data_len);
> +
> +	/* Copy stat type to work on it */
> +	tmp_stat_type = req_data->stat_type;
> +
> +	if (tmp_stat_type & QLA2XX_TGT_SHT_LNK_DOWN) {
> +		/* Num of tgts connected to this host */
> +		tgt_num = qla2x00_get_num_tgts(vha);
> +		/* unset BIT_17 */
> +		tmp_stat_type &= ~(1 << 17);
> +	}
> +
> +	/* Total ini stats */
> +	ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
> +
> +	/* Total number of entries */
> +	entry_count = ini_entry_count + tgt_num;
> +
> +	response_len = sizeof(struct ql_vnd_host_stats_resp) +
> +		(sizeof(struct ql_vnd_stat_entry) * entry_count);
> +
> +	if (response_len > bsg_job->reply_payload.payload_len) {
> +		rsp_data.status = EXT_STATUS_BUFFER_TOO_SMALL;
> +		bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
> +		bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
> +
> +		bsg_reply->reply_payload_rcv_len =
> +			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +					    bsg_job->reply_payload.sg_cnt, &rsp_data,
> +					    sizeof(struct ql_vnd_mng_host_stats_resp));
> +
> +		bsg_reply->result = DID_OK;
> +		bsg_job_done(bsg_job, bsg_reply->result,
> +			     bsg_reply->reply_payload_rcv_len);
> +		goto host_stat_out;
> +	}
> +
> +	data = kzalloc(response_len, GFP_KERNEL);
> +
> +	ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
> +				    data, response_len);
> +
> +	rsp_data.status = EXT_STATUS_OK;
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +
> +	bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +							       bsg_job->reply_payload.sg_cnt,
> +							       data, response_len);
> +	bsg_reply->result = DID_OK;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +	kfree(data);
> +host_stat_out:
> +	kfree(req_data);
> +	return ret;
> +}
> +
> +static struct fc_rport *
> +qla2xxx_find_rport(scsi_qla_host_t *vha, uint32_t tgt_num)
> +{
> +	fc_port_t *fcport = NULL;
> +
> +	list_for_each_entry(fcport, &vha->vp_fcports, list) {
> +		if (fcport->rport->number == tgt_num)
> +			return fcport->rport;
> +	}
> +	return NULL;
> +}
> +
> +static int
> +qla2x00_get_tgt_stats(struct bsg_job *bsg_job)
> +{
> +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +	struct ql_vnd_tgt_stats_param *req_data;
> +	u32 req_data_len;
> +	int ret = 0;
> +	u64 response_len = 0;
> +	struct ql_vnd_tgt_stats_resp *data = NULL;
> +	struct fc_rport *rport = NULL;
> +
> +	if (!vha->flags.online) {
> +		ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
> +		return -EIO;
> +	}
> +
> +	req_data_len = bsg_job->request_payload.payload_len;
> +
> +	if (req_data_len != sizeof(struct ql_vnd_stat_entry)) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> +		return -EIO;
> +	}
> +
> +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> +	if (!req_data) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Copy the request buffer in req_data */
> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> +			  bsg_job->request_payload.sg_cnt,
> +			  req_data, req_data_len);
> +
> +	response_len = sizeof(struct ql_vnd_tgt_stats_resp) +
> +		sizeof(struct ql_vnd_stat_entry);
> +
> +	/* structure + size for one entry */
> +	data = kzalloc(response_len, GFP_KERNEL);
> +	if (!data) {
> +		kfree(req_data);
> +		return -ENOMEM;
> +	}
> +
> +	if (response_len > bsg_job->reply_payload.payload_len) {
> +		data->status = EXT_STATUS_BUFFER_TOO_SMALL;
> +		bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_BUFFER_TOO_SMALL;
> +		bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_stats_resp);
> +
> +		bsg_reply->reply_payload_rcv_len =
> +			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +					    bsg_job->reply_payload.sg_cnt, &data,
> +					    sizeof(struct ql_vnd_tgt_stats_resp));
> +
> +		bsg_reply->result = DID_OK;
> +		bsg_job_done(bsg_job, bsg_reply->result,
> +			     bsg_reply->reply_payload_rcv_len);
> +		goto tgt_stat_out;
> +	}
> +
> +	rport = qla2xxx_find_rport(vha, req_data->tgt_id);
> +	if (!rport) {
> +		ql_log(ql_log_warn, vha, 0x0000, "target %d not found.\n", req_data->tgt_id);
> +		ret = EXT_STATUS_INVALID_PARAM;
> +		data->status = EXT_STATUS_INVALID_PARAM;
> +		goto reply;
> +	}
> +
> +	ret = qla2xxx_get_tgt_stats(fc_bsg_to_shost(bsg_job), req_data->stat_type,
> +				    rport, (void *)data, response_len);
> +
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +reply:
> +	bsg_reply->reply_payload_rcv_len =
> +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +				    bsg_job->reply_payload.sg_cnt, data,
> +				    response_len);
> +	bsg_reply->result = DID_OK;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +tgt_stat_out:
> +	kfree(data);
> +	kfree(req_data);
> +
> +	return ret;
> +}
> +
> +static int
> +qla2x00_manage_host_port(struct bsg_job *bsg_job)
> +{
> +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> +	struct ql_vnd_mng_host_port_param *req_data;
> +	struct ql_vnd_mng_host_port_resp rsp_data;
> +	u32 req_data_len;
> +	int ret = 0;
> +
> +	req_data_len = bsg_job->request_payload.payload_len;
> +
> +	if (req_data_len != sizeof(struct ql_vnd_mng_host_port_param)) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> +		return -EIO;
> +	}
> +
> +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> +	if (!req_data) {
> +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation failure.\n");
> +		return -ENOMEM;
> +	}
> +
> +	/* Copy the request buffer in req_data */
> +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> +			  bsg_job->request_payload.sg_cnt, req_data, req_data_len);
> +
> +	switch (req_data->action) {
> +	case 0:
> +		ret = qla2xxx_enable_port(vha->host);
> +		break;
> +	case 1:
> +		ret = qla2xxx_disable_port(vha->host);
> +		break;
> +	default:
> +		ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
> +		ret = -EIO;
> +		break;
> +	}
> +

Same comment as above… why not use more descriptive name so that user does not have to go to header file to understand what is case 0 and case 1.. Just use QL_HOST_ACTION_ENABLE/DISABLE

> +	kfree(req_data);
> +
> +	/* Prepare response */
> +	rsp_data.status = ret;
> +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> +	bsg_job->reply_payload.payload_len = sizeof(struct ql_vnd_mng_host_port_resp);
> +
> +	bsg_reply->reply_payload_rcv_len =
> +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> +				    bsg_job->reply_payload.sg_cnt, &rsp_data,
> +				    sizeof(struct ql_vnd_mng_host_port_resp));
> +	bsg_reply->result = DID_OK;
> +	bsg_job_done(bsg_job, bsg_reply->result,
> +		     bsg_reply->reply_payload_rcv_len);
> +
> +	return ret;
> +}
> +
> static int
> qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
> {
> @@ -2520,6 +2838,18 @@ qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
> 	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
> 		return qla2x00_get_flash_image_status(bsg_job);
> 
> +	case QL_VND_MANAGE_HOST_STATS:
> +		return qla2x00_manage_host_stats(bsg_job);
> +
> +	case QL_VND_GET_HOST_STATS:
> +		return qla2x00_get_host_stats(bsg_job);
> +
> +	case QL_VND_GET_TGT_STATS:
> +		return qla2x00_get_tgt_stats(bsg_job);
> +
> +	case QL_VND_MANAGE_HOST_PORT:
> +		return qla2x00_manage_host_port(bsg_job);
> +
> 	default:
> 		return -ENOSYS;
> 	}
> @@ -2547,6 +2877,17 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
> 		vha = shost_priv(host);
> 	}
> 
> +	/* Disable port will bring down the chip, allow enable command */
> +	if (bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_MANAGE_HOST_PORT ||
> +	    bsg_request->rqst_data.h_vendor.vendor_cmd[0] == QL_VND_GET_HOST_STATS)
> +		goto skip_chip_chk;
> +
> +	if (vha->hw->flags.port_isolated) {
> +		bsg_reply->result = DID_ERROR;
> +		/* operation not permitted */
> +		return -EPERM;
> +	}
> +
> 	if (qla2x00_chip_is_down(vha)) {
> 		ql_dbg(ql_dbg_user, vha, 0x709f,
> 		    "BSG: ISP abort active/needed -- cmd=%d.\n",
> @@ -2554,6 +2895,7 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
> 		return -EBUSY;
> 	}
> 
> +skip_chip_chk:
> 	ql_dbg(ql_dbg_user, vha, 0x7000,
> 	    "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode);
> 
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> index 1a09b5512267..0274e99e4a12 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.h
> +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> @@ -31,6 +31,10 @@
> #define QL_VND_DPORT_DIAGNOSTICS	0x19
> #define QL_VND_GET_PRIV_STATS_EX	0x1A
> #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E
> +#define QL_VND_MANAGE_HOST_STATS	0x23
> +#define QL_VND_GET_HOST_STATS		0x24
> +#define QL_VND_GET_TGT_STATS		0x25
> +#define QL_VND_MANAGE_HOST_PORT		0x26
> 
> /* BSG Vendor specific subcode returns */
> #define EXT_STATUS_OK			0
> @@ -40,6 +44,7 @@
> #define EXT_STATUS_DATA_OVERRUN		7
> #define EXT_STATUS_DATA_UNDERRUN	8
> #define EXT_STATUS_MAILBOX		11
> +#define EXT_STATUS_BUFFER_TOO_SMALL	16
> #define EXT_STATUS_NO_MEMORY		17
> #define EXT_STATUS_DEVICE_OFFLINE	22
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index 30c7e5e63851..f2f1b0231033 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -2557,6 +2557,10 @@ typedef struct fc_port {
> 	u16 n2n_chip_reset;
> 
> 	struct dentry *dfs_rport_dir;
> +
> +	u64 tgt_short_link_down_cnt;
> +	u64 tgt_link_down_time;
> +	u64 dev_loss_tmo;
> } fc_port_t;
> 
> enum {
> @@ -3922,6 +3926,7 @@ struct qla_hw_data {
> 		uint32_t	scm_enabled:1;
> 		uint32_t	max_req_queue_warned:1;
> 		uint32_t	plogi_template_valid:1;
> +		uint32_t	port_isolated:1;

Just for my understanding, in regards to stats display, What does port_isolated indicates?

> 	} flags;
> 
> 	uint16_t max_exchg;
> @@ -4851,6 +4856,13 @@ typedef struct scsi_qla_host {
> 	uint8_t	scm_fabric_connection_flags;
> 
> 	unsigned int irq_offset;
> +
> +	u64 hw_err_cnt;
> +	u64 interface_err_cnt;
> +	u64 cmd_timeout_cnt;
> +	u64 reset_cmd_err_cnt;
> +	u64 link_down_time;
> +	u64 short_link_down_cnt;
> } scsi_qla_host_t;
> 
> struct qla27xx_image_status {
> @@ -5174,6 +5186,65 @@ struct sff_8247_a0 {
> #define PRLI_PHASE(_cls) \
> 	((_cls == DSC_LS_PRLI_PEND) || (_cls == DSC_LS_PRLI_COMP))
> 
> +enum ql_vnd_host_stat_action {
> +	stop = 0,
> +	start,
> +	clear,
> +};
> +
> +struct ql_vnd_mng_host_stats_param {
> +	u32 stat_type;
> +	enum ql_vnd_host_stat_action action;
> +} __packed;
> +
> +struct ql_vnd_mng_host_stats_resp {
> +	u32 status;
> +} __packed;
> +
> +struct ql_vnd_stats_param {
> +	u32 stat_type;
> +} __packed;
> +
> +struct ql_vnd_tgt_stats_param {
> +	s32 tgt_id;
> +	u32 stat_type;
> +} __packed;
> +
> +enum ql_vnd_host_port_action {
> +	enable = 0,
> +	disable,
> +};
> +
> +struct ql_vnd_mng_host_port_param {
> +	enum ql_vnd_host_port_action action;
> +} __packed;
> +
> +struct ql_vnd_mng_host_port_resp {
> +	u32 status;
> +} __packed;
> +
> +struct ql_vnd_stat_entry {
> +	u32 stat_type;	/* Failure type */
> +	u32 tgt_num;	/* Target Num */
> +	u64 cnt;	/* Counter value */
> +} __packed;
> +
> +struct ql_vnd_stats {
> +	u64 entry_count; /* Num of entries */
> +	u64 rservd;
> +	struct ql_vnd_stat_entry entry[0]; /* Place holder of entries */
> +} __packed;
> +
> +struct ql_vnd_host_stats_resp {
> +	u32 status;
> +	struct ql_vnd_stats stats;
> +} __packed;
> +
> +struct ql_vnd_tgt_stats_resp {
> +	u32 status;
> +	struct ql_vnd_stats stats;
> +} __packed;
> +
> #include "qla_target.h"
> #include "qla_gbl.h"
> #include "qla_dbg.h"
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index e39b4f2da73a..708f82311b83 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -945,4 +945,27 @@ extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
> /* nvme.c */
> void qla_nvme_unregister_remote_port(struct fc_port *fcport);
> void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
> +
> +#define QLA2XX_HW_ERROR			BIT_0
> +#define QLA2XX_SHT_LNK_DWN		BIT_1
> +#define QLA2XX_INT_ERR			BIT_2
> +#define QLA2XX_CMD_TIMEOUT		BIT_3
> +#define QLA2XX_RESET_CMD_ERR		BIT_4
> +#define QLA2XX_TGT_SHT_LNK_DOWN		BIT_17
> +
> +#define QLA2XX_MAX_LINK_DOWN_TIME	100
> +
> +int qla2xxx_start_stats(struct Scsi_Host *shost, u32 flags);
> +int qla2xxx_stop_stats(struct Scsi_Host *shost, u32 flags);
> +int qla2xxx_reset_stats(struct Scsi_Host *shost, u32 flags);
> +
> +int qla2xxx_get_ini_stats(struct Scsi_Host *shost, u32 flags, void *data, u64 size);
> +int qla2xxx_get_tgt_stats(struct Scsi_Host *shost, u32 flags,
> +			  struct fc_rport *rport, void *data, u64 size);
> +int qla2xxx_disable_port(struct Scsi_Host *shost);
> +int qla2xxx_enable_port(struct Scsi_Host *shost);
> +
> +uint64_t qla2x00_get_num_tgts(scsi_qla_host_t *vha);
> +uint64_t qla2x00_count_set_bits(u32 num);
> +
> #endif /* _QLA_GBL_H */
> diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> index 391ac75e3de3..517d358b0031 100644
> --- a/drivers/scsi/qla2xxx/qla_gs.c
> +++ b/drivers/scsi/qla2xxx/qla_gs.c
> @@ -3563,6 +3563,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
> 					       __func__, __LINE__,
> 					       fcport->port_name);
> 
> +					fcport->tgt_link_down_time = 0;
> 					qlt_schedule_sess_for_deletion(fcport);
> 					continue;
> 				}
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index dcc0f0d823db..410ff5534a59 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -4993,6 +4993,9 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
> 	fcport->login_retry = vha->hw->login_retry_count;
> 	fcport->chip_reset = vha->hw->base_qpair->chip_reset;
> 	fcport->logout_on_delete = 1;
> +	fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> +	fcport->tgt_short_link_down_cnt = 0;
> +	fcport->dev_loss_tmo = 0;
> 
> 	if (!fcport->ct_desc.ct_sns) {
> 		ql_log(ql_log_warn, vha, 0xd049,
> @@ -5490,6 +5493,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
> 	spin_lock_irqsave(fcport->vha->host->host_lock, flags);
> 	*((fc_port_t **)rport->dd_data) = fcport;
> 	spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
> +	fcport->dev_loss_tmo = rport->dev_loss_tmo;
> 
> 	rport->supported_classes = fcport->supported_classes;
> 
> @@ -5548,6 +5552,11 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
> 		fcport->logout_on_delete = 1;
> 	fcport->n2n_chip_reset = fcport->n2n_link_reset_cnt = 0;
> 
> +	if (fcport->tgt_link_down_time < fcport->dev_loss_tmo) {
> +		fcport->tgt_short_link_down_cnt++;
> +		fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> +	}
> +
> 	switch (vha->hw->current_topology) {
> 	case ISP_CFG_N:
> 	case ISP_CFG_NL:
> @@ -6908,6 +6917,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
> 	if (vha->flags.online) {
> 		qla2x00_abort_isp_cleanup(vha);
> 
> +		if (vha->hw->flags.port_isolated)
> +			return status;
> +
> 		if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha->dpc_flags)) {
> 			ha->flags.chip_reset_done = 1;
> 			vha->flags.online = 1;
> @@ -7029,6 +7041,11 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
> 
> 	}
> 
> +	if (vha->hw->flags.port_isolated) {
> +		qla2x00_abort_isp_cleanup(vha);
> +		return status;
> +	}
> +
> 	if (!status) {
> 		ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n", __func__);
> 		qla2x00_configure_hba(vha);
> @@ -9171,3 +9188,202 @@ int qla2xxx_delete_qpair(struct scsi_qla_host *vha, struct qla_qpair *qpair)
> fail:
> 	return ret;
> }
> +
> +uint64_t
> +qla2x00_count_set_bits(uint32_t num)
> +{
> +	/* Brian Kernighan's Alogorithm */
> +	u64 count = 0;
> +
> +	while (num) {
> +		num &= (num - 1);
> +		count++;
> +	}
> +	return count;
> +}
> +
> +uint64_t
> +qla2x00_get_num_tgts(scsi_qla_host_t *vha)
> +{
> +	fc_port_t *f, *tf;
> +	u64 count = 0;
> +
> +	f = NULL;
> +	tf = NULL;
> +
> +	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
> +		if (f->port_type != FCT_TARGET)
> +			continue;
> +		count++;
> +	}
> +	return count;
> +}
> +
> +int qla2xxx_reset_stats(struct Scsi_Host *host, u32 flags)
> +{
> +	scsi_qla_host_t *vha = shost_priv(host);
> +	fc_port_t *fcport = NULL;
> +	unsigned long int_flags;
> +
> +	if (flags & QLA2XX_HW_ERROR)
> +		vha->hw_err_cnt = 0;
> +	if (flags & QLA2XX_SHT_LNK_DWN)
> +		vha->short_link_down_cnt = 0;
> +	if (flags & QLA2XX_INT_ERR)
> +		vha->interface_err_cnt = 0;
> +	if (flags & QLA2XX_CMD_TIMEOUT)
> +		vha->cmd_timeout_cnt = 0;
> +	if (flags & QLA2XX_RESET_CMD_ERR)
> +		vha->reset_cmd_err_cnt = 0;
> +	if (flags & QLA2XX_TGT_SHT_LNK_DOWN) {
> +		spin_lock_irqsave(&vha->hw->tgt.sess_lock, int_flags);
> +		list_for_each_entry(fcport, &vha->vp_fcports, list) {
> +			fcport->tgt_short_link_down_cnt = 0;
> +			fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> +		}
> +		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, int_flags);
> +	}
> +	vha->link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> +	return 0;
> +}
> +
> +int qla2xxx_start_stats(struct Scsi_Host *host, u32 flags)
> +{
> +	return qla2xxx_reset_stats(host, flags);
> +}
> +
> +int qla2xxx_stop_stats(struct Scsi_Host *host, u32 flags)
> +{
> +	return qla2xxx_reset_stats(host, flags);
> +}
> +
> +int qla2xxx_get_ini_stats(struct Scsi_Host *host, u32 flags,
> +			  void *data, u64 size)
> +{
> +	scsi_qla_host_t *vha = shost_priv(host);
> +	struct ql_vnd_host_stats_resp *resp = (struct ql_vnd_host_stats_resp *)data;
> +	struct ql_vnd_stats *rsp_data = &resp->stats;
> +	u64 ini_entry_count = 0;
> +	u64 i = 0;
> +	u64 entry_count = 0;
> +	u64 num_tgt = 0;
> +	u32 tmp_stat_type = 0;
> +	fc_port_t *fcport = NULL;
> +	unsigned long int_flags;
> +
> +	/* Copy stat type to work on it */
> +	tmp_stat_type = flags;
> +
> +	if (tmp_stat_type & BIT_17) {
> +		num_tgt = qla2x00_get_num_tgts(vha);
> +		/* unset BIT_17 */
> +		tmp_stat_type &= ~(1 << 17);
> +	}
> +	ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
> +
> +	entry_count = ini_entry_count + num_tgt;
> +
> +	rsp_data->entry_count = entry_count;
> +
> +	i = 0;
> +	if (flags & QLA2XX_HW_ERROR) {
> +		rsp_data->entry[i].stat_type = QLA2XX_HW_ERROR;
> +		rsp_data->entry[i].tgt_num = 0x0;
> +		rsp_data->entry[i].cnt = vha->hw_err_cnt;
> +		i++;
> +	}
> +
> +	if (flags & QLA2XX_SHT_LNK_DWN) {
> +		rsp_data->entry[i].stat_type = QLA2XX_SHT_LNK_DWN;
> +		rsp_data->entry[i].tgt_num = 0x0;
> +		rsp_data->entry[i].cnt = vha->short_link_down_cnt;
> +		i++;
> +	}
> +
> +	if (flags & QLA2XX_INT_ERR) {
> +		rsp_data->entry[i].stat_type = QLA2XX_INT_ERR;
> +		rsp_data->entry[i].tgt_num = 0x0;
> +		rsp_data->entry[i].cnt = vha->interface_err_cnt;
> +		i++;
> +	}
> +
> +	if (flags & QLA2XX_CMD_TIMEOUT) {
> +		rsp_data->entry[i].stat_type = QLA2XX_CMD_TIMEOUT;
> +		rsp_data->entry[i].tgt_num = 0x0;
> +		rsp_data->entry[i].cnt = vha->cmd_timeout_cnt;
> +		i++;
> +	}
> +
> +	if (flags & QLA2XX_RESET_CMD_ERR) {
> +		rsp_data->entry[i].stat_type = QLA2XX_RESET_CMD_ERR;
> +		rsp_data->entry[i].tgt_num = 0x0;
> +		rsp_data->entry[i].cnt = vha->reset_cmd_err_cnt;
> +		i++;
> +	}
> +
> +	/* i will continue from previous loop, as target
> +	 * entries are after initiator
> +	 */
> +	if (flags & QLA2XX_TGT_SHT_LNK_DOWN) {
> +		spin_lock_irqsave(&vha->hw->tgt.sess_lock, int_flags);
> +		list_for_each_entry(fcport, &vha->vp_fcports, list) {
> +			if (fcport->port_type != FCT_TARGET)
> +				continue;
> +			if (!fcport->rport)
> +				continue;
> +			rsp_data->entry[i].stat_type = QLA2XX_TGT_SHT_LNK_DOWN;
> +			rsp_data->entry[i].tgt_num = fcport->rport->number;
> +			rsp_data->entry[i].cnt = fcport->tgt_short_link_down_cnt;
> +			i++;
> +		}
> +		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, int_flags);
> +	}
> +	resp->status = EXT_STATUS_OK;
> +
> +	return 0;
> +}
> +
> +int qla2xxx_get_tgt_stats(struct Scsi_Host *host, u32 flags,
> +			  struct fc_rport *rport, void *data, u64 size)
> +{
> +	struct ql_vnd_tgt_stats_resp *tgt_data = data;
> +	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
> +
> +	tgt_data->status = 0;
> +	tgt_data->stats.entry_count = 1;
> +	tgt_data->stats.entry[0].stat_type = flags;
> +	tgt_data->stats.entry[0].tgt_num = rport->number;
> +	tgt_data->stats.entry[0].cnt = fcport->tgt_short_link_down_cnt;
> +
> +	return 0;
> +}
> +
> +int qla2xxx_disable_port(struct Scsi_Host *host)
> +{
> +	scsi_qla_host_t *vha = shost_priv(host);
> +
> +	vha->hw->flags.port_isolated = 1;
> +
> +	if (qla2x00_chip_is_down(vha))
> +		return 0;
> +
> +	if (vha->flags.online) {
> +		qla2x00_abort_isp_cleanup(vha);
> +		qla2x00_wait_for_sess_deletion(vha);
> +	}
> +
> +	return 0;
> +}
> +
> +int qla2xxx_enable_port(struct Scsi_Host *host)
> +{
> +	scsi_qla_host_t *vha = shost_priv(host);
> +
> +	vha->hw->flags.port_isolated = 0;
> +	/* Set the flag to 1, so that isp_abort can proceed */
> +	vha->flags.online = 1;
> +	set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> +	qla2xxx_wake_dpc(vha);
> +
> +	return 0;
> +}
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index f9142dbec112..9cf8326ab9fc 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -1059,6 +1059,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 
> 	case MBA_SYSTEM_ERR:		/* System Error */
> 		mbx = 0;
> +
> +		vha->hw_err_cnt++;
> +
> 		if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
> 		    IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
> 			u16 m[4];
> @@ -1112,6 +1115,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 		ql_log(ql_log_warn, vha, 0x5006,
> 		    "ISP Request Transfer Error (%x).\n",  mb[1]);
> 
> +		vha->hw_err_cnt++;
> +
> 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> 		break;
> 
> @@ -1119,6 +1124,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 		ql_log(ql_log_warn, vha, 0x5007,
> 		    "ISP Response Transfer Error (%x).\n", mb[1]);
> 
> +		vha->hw_err_cnt++;
> +
> 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> 		break;
> 
> @@ -1176,12 +1183,18 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 		vha->flags.management_server_logged_in = 0;
> 		qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha->link_data_rate);
> 
> +		if (vha->link_down_time < vha->hw->port_down_retry_count) {
> +			vha->short_link_down_cnt++;
> +			vha->link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> +		}
> +
> 		break;
> 
> 	case MBA_LOOP_DOWN:		/* Loop Down Event */
> 		SAVE_TOPO(ha);
> 		ha->flags.lip_ae = 0;
> 		ha->current_topology = 0;
> +		vha->link_down_time = 0;
> 
> 		mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
> 			? rd_reg_word(&reg24->mailbox4) : 0;
> @@ -1503,6 +1516,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 		ql_dbg(ql_dbg_async, vha, 0x5016,
> 		    "Discard RND Frame -- %04x %04x %04x.\n",
> 		    mb[1], mb[2], mb[3]);
> +		vha->interface_err_cnt++;
> 		break;
> 
> 	case MBA_TRACE_NOTIFICATION:
> @@ -1592,6 +1606,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 
> 	case MBA_IDC_AEN:
> 		if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
> +			vha->hw_err_cnt++;
> 			qla27xx_handle_8200_aen(vha, mb);
> 		} else if (IS_QLA83XX(ha)) {
> 			mb[4] = rd_reg_word(&reg24->mailbox4);
> @@ -3101,6 +3116,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 				    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
> 				    resid, scsi_bufflen(cp));
> 
> +				vha->interface_err_cnt++;
> +
> 				res = DID_ERROR << 16 | lscsi_status;
> 				goto check_scsi_status;
> 			}
> @@ -3126,6 +3143,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 			    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
> 			    resid, scsi_bufflen(cp));
> 
> +			vha->interface_err_cnt++;
> +
> 			res = DID_ERROR << 16 | lscsi_status;
> 			goto check_scsi_status;
> 		} else {
> @@ -3208,6 +3227,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 
> 	case CS_TRANSPORT:
> 		res = DID_ERROR << 16;
> +		vha->hw_err_cnt++;
> 
> 		if (!IS_PI_SPLIT_DET_CAPABLE(ha))
> 			break;
> @@ -3228,6 +3248,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 		ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee,
> 		    pkt, sizeof(*sts24));
> 		res = DID_ERROR << 16;
> +		vha->hw_err_cnt++;
> 		break;
> 	default:
> 		res = DID_ERROR << 16;
> @@ -3839,6 +3860,7 @@ qla24xx_msix_default(int irq, void *dev_id)
> 			    hccr);
> 
> 			qla2xxx_check_risc_status(vha);
> +			vha->hw_err_cnt++;
> 
> 			ha->isp_ops->fw_dump(vha);
> 			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index d7d4ab65009c..f438cdedca23 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -180,6 +180,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
> 		ql_log(ql_log_warn, vha, 0xd035,
> 		    "Cmd access timeout, cmd=0x%x, Exiting.\n",
> 		    mcp->mb[0]);
> +		vha->hw_err_cnt++;
> 		atomic_dec(&ha->num_pend_mbx_stage1);
> 		return QLA_FUNCTION_TIMEOUT;
> 	}
> @@ -307,6 +308,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
> 				atomic_dec(&ha->num_pend_mbx_stage2);
> 				ql_dbg(ql_dbg_mbx, vha, 0x1012,
> 				    "Pending mailbox timeout, exiting.\n");
> +				vha->hw_err_cnt++;
> 				rval = QLA_FUNCTION_TIMEOUT;
> 				goto premature_exit;
> 			}
> @@ -418,6 +420,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
> 			    "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x host_status 0x%x hccr 0x%x\n",
> 			    command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
> 			    mb[7], host_status, hccr);
> +			vha->hw_err_cnt++;
> 
> 		} else {
> 			mb[0] = RD_MAILBOX_REG(ha, &reg->isp, 0);
> @@ -425,6 +428,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
> 			ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
> 			    "MBX Command timeout for cmd %x, iocontrol=%x jiffies=%lx "
> 			    "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
> +			vha->hw_err_cnt++;
> 		}
> 		ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
> 
> @@ -497,6 +501,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
> 				    "mb[0]=0x%x, eeh_busy=0x%x. Scheduling ISP "
> 				    "abort.\n", command, mcp->mb[0],
> 				    ha->flags.eeh_busy);
> +				vha->hw_err_cnt++;
> 				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> 				qla2xxx_wake_dpc(vha);
> 			}
> @@ -521,6 +526,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
> 				    "Mailbox cmd timeout occurred, cmd=0x%x, "
> 				    "mb[0]=0x%x. Scheduling ISP abort ",
> 				    command, mcp->mb[0]);
> +				vha->hw_err_cnt++;
> 				set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
> 				clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> 				/* Allow next mbx cmd to come in. */
> @@ -625,6 +631,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t risc_addr,
> 		ql_dbg(ql_dbg_mbx, vha, 0x1023,
> 		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
> 		    rval, mcp->mb[0], mcp->mb[1]);
> +		vha->hw_err_cnt++;
> 	} else {
> 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024,
> 		    "Done %s.\n", __func__);
> @@ -736,6 +743,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
> 
> 		ql_dbg(ql_dbg_mbx, vha, 0x1026,
> 		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
> +		vha->hw_err_cnt++;
> 		return rval;
> 	}
> 
> @@ -1313,6 +1321,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
> 	if (rval != QLA_SUCCESS) {
> 		/*EMPTY*/
> 		ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
> +		vha->hw_err_cnt++;
> 	} else {
> 		/*EMPTY*/
> 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034,
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index f80abe28f35a..a760cb38e487 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -1274,6 +1274,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
> 	sp = scsi_cmd_priv(cmd);
> 	qpair = sp->qpair;
> 
> +	vha->cmd_timeout_cnt++;
> +
> 	if ((sp->fcport && sp->fcport->deleted) || !qpair)
> 		return SUCCESS;
> 
> @@ -1442,6 +1444,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type,
> 	    "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name,
> 	    reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun,
> 	    cmd);
> +	vha->reset_cmd_err_cnt++;
> 	return FAILED;
> }
> 
> @@ -3141,6 +3144,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
> 	ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED;
> 	ha->mr.fcport.scan_state = 1;
> 
> +	qla2xxx_reset_stats(host, QLA2XX_HW_ERROR | QLA2XX_SHT_LNK_DWN |
> +			    QLA2XX_INT_ERR | QLA2XX_CMD_TIMEOUT |
> +			    QLA2XX_RESET_CMD_ERR | QLA2XX_TGT_SHT_LNK_DOWN);
> +
> 	/* Set the SG table size based on ISP type */
> 	if (!IS_FWI2_CAPABLE(ha)) {
> 		if (IS_QLA2100(ha))
> @@ -5090,6 +5097,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, struct qla_work_evt *e)
> 			fcport->d_id = e->u.new_sess.id;
> 			fcport->flags |= FCF_FABRIC_DEVICE;
> 			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
> +			fcport->tgt_short_link_down_cnt = 0;
> 
> 			memcpy(fcport->port_name, e->u.new_sess.port_name,
> 			    WWN_SIZE);
> @@ -7061,6 +7069,8 @@ qla2x00_timer(struct timer_list *t)
> 	uint16_t        w;
> 	struct qla_hw_data *ha = vha->hw;
> 	struct req_que *req;
> +	unsigned long flags;
> +	fc_port_t *fcport = NULL;
> 
> 	if (ha->flags.eeh_busy) {
> 		ql_dbg(ql_dbg_timer, vha, 0x6000,
> @@ -7092,6 +7102,16 @@ qla2x00_timer(struct timer_list *t)
> 	if (!vha->vp_idx && IS_QLAFX00(ha))
> 		qlafx00_timer_routine(vha);
> 
> +	if (vha->link_down_time < QLA2XX_MAX_LINK_DOWN_TIME)
> +		vha->link_down_time++;
> +
> +	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
> +	list_for_each_entry(fcport, &vha->vp_fcports, list) {
> +		if (fcport->tgt_link_down_time < QLA2XX_MAX_LINK_DOWN_TIME)
> +			fcport->tgt_link_down_time++;
> +	}
> +	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> +
> 	/* Loop down handler. */
> 	if (atomic_read(&vha->loop_down_timer) > 0 &&
> 	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
> -- 
> 2.19.0.rc0
> 

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 2/7] qla2xxx: Add error counters to debugfs node
  2021-01-05 10:38 ` [PATCH v3 2/7] qla2xxx: Add error counters to debugfs node Nilesh Javali
@ 2021-01-06 15:06   ` Himanshu Madhani
  0 siblings, 0 replies; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:06 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream



> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Saurav Kashyap <skashyap@marvell.com>
> 
> Display error counters via debugfs node.
> 
> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_dfs.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
> index d5ebcf7d70ff..ccce0eab844e 100644
> --- a/drivers/scsi/qla2xxx/qla_dfs.c
> +++ b/drivers/scsi/qla2xxx/qla_dfs.c
> @@ -286,6 +286,10 @@ qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
> 		core_qla_snd_status, qla_core_ret_sta_ctio, core_qla_free_cmd,
> 		num_q_full_sent, num_alloc_iocb_failed, num_term_xchg_sent;
> 	u16 i;
> +	fc_port_t *fcport = NULL;
> +
> +	if (qla2x00_chip_is_down(vha))
> +		return 0;
> 
> 	qla_core_sbt_cmd = qpair->tgt_counters.qla_core_sbt_cmd;
> 	core_qla_que_buf = qpair->tgt_counters.core_qla_que_buf;
> @@ -349,6 +353,30 @@ qla_dfs_tgt_counters_show(struct seq_file *s, void *unused)
> 		vha->qla_stats.qla_dif_stats.dif_ref_tag_err);
> 	seq_printf(s, "DIF App tag err = %d\n",
> 		vha->qla_stats.qla_dif_stats.dif_app_tag_err);
> +
> +	seq_puts(s, "\n");
> +	seq_puts(s, "Initiator Error Counters\n");
> +	seq_printf(s, "HW Error Count =		%14lld\n",
> +		   vha->hw_err_cnt);
> +	seq_printf(s, "Link Down Count =	%14lld\n",
> +		   vha->short_link_down_cnt);
> +	seq_printf(s, "Interface Err Count =	%14lld\n",
> +		   vha->interface_err_cnt);
> +	seq_printf(s, "Cmd Timeout Count =	%14lld\n",
> +		   vha->cmd_timeout_cnt);
> +	seq_printf(s, "Reset Count =		%14lld\n",
> +		   vha->reset_cmd_err_cnt);
> +	seq_puts(s, "\n");
> +
> +	list_for_each_entry(fcport, &vha->vp_fcports, list) {
> +		if (!fcport || !fcport->rport)
> +			continue;
> +
> +		seq_printf(s, "Target Num = %7d Link Down Count = %14lld\n",
> +			   fcport->rport->number, fcport->tgt_short_link_down_cnt);
> +	}
> +	seq_puts(s, "\n");
> +
> 	return 0;
> }
> 
> -- 
> 2.19.0.rc0
> 

Looks Good. 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level
  2021-01-05 10:38 ` [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level Nilesh Javali
@ 2021-01-06 15:06   ` Himanshu Madhani
  2021-01-07  5:51     ` [EXT] " Saurav Kashyap
  0 siblings, 1 reply; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:06 UTC (permalink / raw)
  To: Nilesh Javali, Saurav Kashyap
  Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

Hi Saurav,

> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Saurav Kashyap <skashyap@marvell.com>
> 
> This change will aid in debugging issues where debug level is not set.
> 
> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_init.c | 10 +++----
> drivers/scsi/qla2xxx/qla_isr.c  | 52 ++++++++++++++++-----------------
> 2 files changed, 30 insertions(+), 32 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 410ff5534a59..221369cdf71f 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -347,11 +347,11 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t *fcport,
> 	if (NVME_TARGET(vha->hw, fcport))
> 		lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
> 
> -	ql_dbg(ql_dbg_disc, vha, 0x2072,
> -	    "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
> -		"retries=%d.\n", fcport->port_name, sp->handle, fcport->loop_id,
> -	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
> -	    fcport->login_retry);
> +	ql_log(ql_log_warn, vha, 0x2072,
> +	       "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x retries=%d.\n",
> +	       fcport->port_name, sp->handle, fcport->loop_id,
> +	       fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
> +	       fcport->login_retry);
> 
> 	rval = qla2x00_start_sp(sp);
> 	if (rval != QLA_SUCCESS) {
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index 9cf8326ab9fc..bfc8bbaeea46 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -1455,9 +1455,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
> 		if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
> 			break;
> 
> -		ql_dbg(ql_dbg_async, vha, 0x5013,
> -		    "RSCN database changed -- %04x %04x %04x.\n",
> -		    mb[1], mb[2], mb[3]);
> +		ql_log(ql_log_warn, vha, 0x5013,
> +		       "RSCN database changed -- %04x %04x %04x.\n",
> +		       mb[1], mb[2], mb[3]);
> 
> 		rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
> 		host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area << 8)
> @@ -2221,12 +2221,12 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req,
> 		break;
> 	}
> 
> -	ql_dbg(ql_dbg_async, sp->vha, 0x5037,
> -	    "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
> -	    type, sp->handle, fcport->d_id.b24, fcport->port_name,
> -	    le16_to_cpu(logio->comp_status),
> -	    le32_to_cpu(logio->io_parameter[0]),
> -	    le32_to_cpu(logio->io_parameter[1]));
> +	ql_log(ql_log_warn, sp->vha, 0x5037,
> +	       "Async-%s failed: handle=%x pid=%06x wwpn=%8phC comp_status=%x iop0=%x iop1=%x\n",
> +	       type, sp->handle, fcport->d_id.b24, fcport->port_name,
> +	       le16_to_cpu(logio->comp_status),
> +	       le32_to_cpu(logio->io_parameter[0]),
> +	       le32_to_cpu(logio->io_parameter[1]));
> 
> logio_done:
> 	sp->done(sp, 0);
> @@ -2389,9 +2389,9 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
> 
> 		tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
> 		if (fd->transferred_length != tgt_xfer_len) {
> -			ql_dbg(ql_dbg_io, fcport->vha, 0x3079,
> -				"Dropped frame(s) detected (sent/rcvd=%u/%u).\n",
> -				tgt_xfer_len, fd->transferred_length);
> +			ql_log(ql_log_warn, fcport->vha, 0x3079,
> +			       "Dropped frame(s) detected (sent/rcvd=%u/%u).\n",
> +			       tgt_xfer_len, fd->transferred_length);
> 			logit = 1;
> 		} else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
> 			/*
> @@ -3112,9 +3112,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 		scsi_set_resid(cp, resid);
> 		if (scsi_status & SS_RESIDUAL_UNDER) {
> 			if (IS_FWI2_CAPABLE(ha) && fw_resid_len != resid_len) {
> -				ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
> -				    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
> -				    resid, scsi_bufflen(cp));
> +				ql_log(ql_log_warn, fcport->vha, 0x301d,
> +				       "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
> +				       resid, scsi_bufflen(cp));
> 
> 				vha->interface_err_cnt++;
> 
> @@ -3139,9 +3139,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 			 * task not completed.
> 			 */
> 
> -			ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
> -			    "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
> -			    resid, scsi_bufflen(cp));
> +			ql_log(ql_log_warn, fcport->vha, 0x301f,
> +			       "Dropped frame(s) detected (0x%x of 0x%x bytes).\n",
> +			       resid, scsi_bufflen(cp));
> 
> 			vha->interface_err_cnt++;
> 
> @@ -3257,15 +3257,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
> 
> out:
> 	if (logit)
> -		ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
> -		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu "
> -		    "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
> -		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
> -		    comp_status, scsi_status, res, vha->host_no,
> -		    cp->device->id, cp->device->lun, fcport->d_id.b.domain,
> -		    fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
> -		    cp->cmnd, scsi_bufflen(cp), rsp_info_len,
> -		    resid_len, fw_resid_len, sp, cp);
> +		ql_log(ql_log_warn, fcport->vha, 0x3022,
> +		       "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
> +		       comp_status, scsi_status, res, vha->host_no,
> +		       cp->device->id, cp->device->lun, fcport->d_id.b.domain,
> +		       fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
> +		       cp->cmnd, scsi_bufflen(cp), rsp_info_len,
> +		       resid_len, fw_resid_len, sp, cp);
> 
> 	if (rsp->status_srb == NULL)
> 		sp->done(sp, res);
> -- 
> 2.19.0.rc0
> 

I like the direction of this patch. 

Can you consider removing "logit" variable. Since logit was designed to print messages only when a specific debug (IO bits in this case) was set.

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 4/7] qla2xxx: Wait for ABTS response on I/O timeouts for NVMe
  2021-01-05 10:38 ` [PATCH v3 4/7] qla2xxx: Wait for ABTS response on I/O timeouts for NVMe Nilesh Javali
@ 2021-01-06 15:36   ` Himanshu Madhani
  0 siblings, 0 replies; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:36 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream



> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Bikash Hazarika <bhazarika@marvell.com>
> 
> FW needs to wait for an ABTS response before completing the I/O
> 
> Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> Signed-off-by: Arun Easi <aeasi@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_def.h  | 12 +++++
> drivers/scsi/qla2xxx/qla_fw.h   | 27 ++++++++--
> drivers/scsi/qla2xxx/qla_gbl.h  |  6 +++
> drivers/scsi/qla2xxx/qla_init.c |  4 ++
> drivers/scsi/qla2xxx/qla_iocb.c |  6 +++
> drivers/scsi/qla2xxx/qla_isr.c  |  8 +++
> drivers/scsi/qla2xxx/qla_mbx.c  |  6 +++
> drivers/scsi/qla2xxx/qla_nvme.c | 90 ++++++++++++++++++++++++++++++++-
> drivers/scsi/qla2xxx/qla_os.c   |  5 ++
> 9 files changed, 159 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index f2f1b0231033..17da6b436e74 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -2101,6 +2101,7 @@ typedef struct {
> #define CS_COMPLETE_CHKCOND	0x30	/* Error? */
> #define CS_IOCB_ERROR		0x31	/* Generic error for IOCB request
> 					   failure */
> +#define CS_REJECT_RECEIVED	0x4E	/* Reject received */
> #define CS_BAD_PAYLOAD		0x80	/* Driver defined */
> #define CS_UNKNOWN		0x81	/* Driver defined */
> #define CS_RETRY		0x82	/* Driver defined */
> @@ -4150,6 +4151,17 @@ struct qla_hw_data {
> /* Bit 21 of fw_attributes decides the MCTP capabilities */
> #define IS_MCTP_CAPABLE(ha)	(IS_QLA2031(ha) && \
> 				((ha)->fw_attributes_ext[0] & BIT_0))
> +#define QLA_ABTS_FW_ENABLED(_ha)       ((_ha)->fw_attributes_ext[0] & BIT_14)
> +#define QLA_SRB_NVME_LS(_sp) ((_sp)->type == SRB_NVME_LS)
> +#define QLA_SRB_NVME_CMD(_sp) ((_sp)->type == SRB_NVME_CMD)
> +#define QLA_NVME_IOS(_sp) (QLA_SRB_NVME_CMD(_sp) || QLA_SRB_NVME_LS(_sp))
> +#define QLA_LS_ABTS_WAIT_ENABLED(_sp) \
> +	(QLA_SRB_NVME_LS(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
> +#define QLA_CMD_ABTS_WAIT_ENABLED(_sp) \
> +	(QLA_SRB_NVME_CMD(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
> +#define QLA_ABTS_WAIT_ENABLED(_sp) \
> +	(QLA_NVME_IOS(_sp) && QLA_ABTS_FW_ENABLED(_sp->fcport->vha->hw))
> +
> #define IS_PI_UNINIT_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
> #define IS_PI_IPGUARD_CAPABLE(ha)	(IS_QLA83XX(ha) || IS_QLA27XX(ha))
> #define IS_PI_DIFB_DIX0_CAPABLE(ha)	(0)
> diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
> index 12b689e32883..49df418030e4 100644
> --- a/drivers/scsi/qla2xxx/qla_fw.h
> +++ b/drivers/scsi/qla2xxx/qla_fw.h
> @@ -982,11 +982,18 @@ struct abort_entry_24xx {
> 
> 	uint32_t handle;		/* System handle. */
> 
> -	__le16	nport_handle;		/* N_PORT handle. */
> -					/* or Completion status. */
> +	union {
> +		__le16 nport_handle;            /* N_PORT handle. */
> +		__le16 comp_status;             /* Completion status. */
> +	};
> 
> 	__le16	options;		/* Options. */
> #define AOF_NO_ABTS		BIT_0	/* Do not send any ABTS. */
> +#define AOF_NO_RRQ		BIT_1   /* Do not send RRQ. */
> +#define AOF_ABTS_TIMEOUT	BIT_2   /* Disable logout on ABTS timeout. */
> +#define AOF_ABTS_RTY_CNT	BIT_3   /* Use driver specified retry count. */
> +#define AOF_RSP_TIMEOUT		BIT_4   /* Use specified response timeout. */
> +
> 
> 	uint32_t handle_to_abort;	/* System handle to abort. */
> 
> @@ -995,8 +1002,20 @@ struct abort_entry_24xx {
> 
> 	uint8_t port_id[3];		/* PortID of destination port. */
> 	uint8_t vp_index;
> -
> -	uint8_t reserved_2[12];
> +	u8	reserved_2[4];
> +	union {
> +		struct {
> +			__le16 abts_rty_cnt;
> +			__le16 rsp_timeout;
> +		} drv;
> +		struct {
> +			u8	ba_rjt_vendorUnique;
> +			u8	ba_rjt_reasonCodeExpl;
> +			u8	ba_rjt_reasonCode;
> +			u8	reserved_3;
> +		} fw;
> +	};
> +	u8	reserved_4[4];
> };
> 
> #define ABTS_RCV_TYPE		0x54
> diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> index 708f82311b83..6486f97d649e 100644
> --- a/drivers/scsi/qla2xxx/qla_gbl.h
> +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> @@ -177,6 +177,7 @@ extern int ql2xexlogins;
> extern int ql2xdifbundlinginternalbuffers;
> extern int ql2xfulldump_on_mpifail;
> extern int ql2xenforce_iocb_limit;
> +extern int ql2xabts_wait_nvme;
> 
> extern int qla2x00_loop_reset(scsi_qla_host_t *);
> extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
> @@ -941,6 +942,11 @@ int qla2x00_set_data_rate(scsi_qla_host_t *vha, uint16_t mode);
> extern void qla24xx_process_purex_list(struct purex_list *);
> extern void qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp);
> extern void qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
> +extern void qla_wait_nvme_release_cmd_kref(srb_t *sp);
> +extern void qla_nvme_abort_set_option
> +		(struct abort_entry_24xx *abt, srb_t *sp);
> +extern void qla_nvme_abort_process_comp_status
> +		(struct abort_entry_24xx *abt, srb_t *sp);
> 
> /* nvme.c */
> void qla_nvme_unregister_remote_port(struct fc_port *fcport);
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 221369cdf71f..a6ab2629b7cf 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -136,6 +136,10 @@ static void qla24xx_abort_iocb_timeout(void *data)
> static void qla24xx_abort_sp_done(srb_t *sp, int res)
> {
> 	struct srb_iocb *abt = &sp->u.iocb_cmd;
> +	srb_t *orig_sp = sp->cmd_sp;
> +
> +	if (orig_sp)
> +		qla_wait_nvme_release_cmd_kref(orig_sp);
> 
> 	del_timer(&sp->u.iocb_cmd.timer);
> 	if (sp->flags & SRB_WAKEUP_ON_COMP)
> diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> index c532c74ca1ab..e27359b294d3 100644
> --- a/drivers/scsi/qla2xxx/qla_iocb.c
> +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> @@ -3571,6 +3571,7 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
> 	struct srb_iocb *aio = &sp->u.iocb_cmd;
> 	scsi_qla_host_t *vha = sp->vha;
> 	struct req_que *req = sp->qpair->req;
> +	srb_t *orig_sp = sp->cmd_sp;
> 
> 	memset(abt_iocb, 0, sizeof(struct abort_entry_24xx));
> 	abt_iocb->entry_type = ABORT_IOCB_TYPE;
> @@ -3587,6 +3588,11 @@ qla24xx_abort_iocb(srb_t *sp, struct abort_entry_24xx *abt_iocb)
> 			    aio->u.abt.cmd_hndl);
> 	abt_iocb->vp_index = vha->vp_idx;
> 	abt_iocb->req_que_no = aio->u.abt.req_que_no;
> +
> +	/* need to pass original sp */
> +	if (orig_sp)
> +		qla_nvme_abort_set_option(abt_iocb, orig_sp);
> +
> 	/* Send the command to the firmware */
> 	wmb();
> }
> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> index bfc8bbaeea46..a4a52a2d724e 100644
> --- a/drivers/scsi/qla2xxx/qla_isr.c
> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> @@ -5,6 +5,7 @@
>  */
> #include "qla_def.h"
> #include "qla_target.h"
> +#include "qla_gbl.h"
> 
> #include <linux/delay.h>
> #include <linux/slab.h>
> @@ -3431,6 +3432,7 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
> {
> 	const char func[] = "ABT_IOCB";
> 	srb_t *sp;
> +	srb_t *orig_sp = NULL;
> 	struct srb_iocb *abt;
> 
> 	sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
> @@ -3439,6 +3441,12 @@ qla24xx_abort_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
> 
> 	abt = &sp->u.iocb_cmd;
> 	abt->u.abt.comp_status = pkt->nport_handle;
> +	abt->u.abt.comp_status = le16_to_cpu(pkt->comp_status);

Is this intentional?

abt->u.abt.comp_status has value assigned twice, once for nport_handle and then again with comp_status? 

> +	orig_sp = sp->cmd_sp;
> +	/* Need to pass original sp */
> +	if (orig_sp)
> +		qla_nvme_abort_process_comp_status(pkt, orig_sp);
> +
> 	sp->done(sp, 0);
> }
> 
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index f438cdedca23..629af6fe8c55 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -3243,6 +3243,8 @@ qla24xx_abort_command(srb_t *sp)
> 	abt->vp_index = fcport->vha->vp_idx;
> 
> 	abt->req_que_no = cpu_to_le16(req->id);
> +	/* Need to pass original sp */
> +	qla_nvme_abort_set_option(abt, sp);
> 
> 	rval = qla2x00_issue_iocb(vha, abt, abt_dma, 0);
> 	if (rval != QLA_SUCCESS) {
> @@ -3265,6 +3267,10 @@ qla24xx_abort_command(srb_t *sp)
> 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1091,
> 		    "Done %s.\n", __func__);
> 	}
> +	if (rval == QLA_SUCCESS)
> +		qla_nvme_abort_process_comp_status(abt, sp);
> +
> +	qla_wait_nvme_release_cmd_kref(sp);
> 
> 	dma_pool_free(ha->s_dma_pool, abt, abt_dma);
> 
> diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
> index eab559b3b257..1cdb7352d6db 100644
> --- a/drivers/scsi/qla2xxx/qla_nvme.c
> +++ b/drivers/scsi/qla2xxx/qla_nvme.c
> @@ -245,6 +245,12 @@ static void qla_nvme_abort_work(struct work_struct *work)
> 	    __func__, (rval != QLA_SUCCESS) ? "Failed to abort" : "Aborted",
> 	    sp, sp->handle, fcport, rval);
> 
> +	/* Returned before decreasing kref so that I/O requests
> +	 * are waited until ABTS complete. This kref is decreased
> +	 * at qla24xx_abort_sp_done function.
> +	 */

Small nit: Can you please use separate line for comment start 

> +	if (ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(sp))
> +		return;
> out:
> 	/* kref_get was done before work was schedule. */
> 	kref_put(&sp->cmd_kref, sp->put_fn);
> @@ -284,7 +290,6 @@ static int qla_nvme_ls_req(struct nvme_fc_local_port *lport,
> 	struct qla_hw_data *ha;
> 	srb_t           *sp;
> 
> -
> 	if (!fcport || (fcport && fcport->deleted))
> 		return rval;
> 
> @@ -591,6 +596,7 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
> 	sp->put_fn = qla_nvme_release_fcp_cmd_kref;
> 	sp->qpair = qpair;
> 	sp->vha = vha;
> +	sp->cmd_sp = sp;
> 	nvme = &sp->u.iocb_cmd;
> 	nvme->u.nvme.desc = fd;
> 
> @@ -744,3 +750,85 @@ int qla_nvme_register_hba(struct scsi_qla_host *vha)
> 
> 	return ret;
> }
> +
> +void qla_nvme_abort_set_option(struct abort_entry_24xx *abt, srb_t *orig_sp)
> +{
> +	struct qla_hw_data *ha;
> +
> +	if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp)))
> +		return;
> +
> +	ha = orig_sp->fcport->vha->hw;
> +
> +	WARN_ON_ONCE(abt->options & cpu_to_le16(BIT_0));
> +	/* Use Driver Specified Retry Count */
> +	abt->options |= cpu_to_le16(AOF_ABTS_RTY_CNT);
> +	abt->drv.abts_rty_cnt = cpu_to_le16(2);
> +	/* Use specified response timeout */
> +	abt->options |= cpu_to_le16(AOF_RSP_TIMEOUT);
> +	/* set it to 2 * r_a_tov in secs */
> +	abt->drv.rsp_timeout = cpu_to_le16(2 * (ha->r_a_tov / 10));
> +}
> +
> +void qla_nvme_abort_process_comp_status(struct abort_entry_24xx *abt, srb_t *orig_sp)
> +{
> +	u16	comp_status;
> +	struct scsi_qla_host *vha;
> +
> +	if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp)))
> +		return;
> +
> +	vha = orig_sp->fcport->vha;
> +
> +	comp_status = le16_to_cpu(abt->comp_status);
> +	switch (comp_status) {
> +	case CS_RESET:		/* reset event aborted */
> +	case CS_ABORTED:	/* IOCB was cleaned */
> +	/* N_Port handle is not currently logged in */
> +	case CS_TIMEOUT:
> +	/* N_Port handle was logged out while waiting for ABTS to complete */
> +	case CS_PORT_UNAVAILABLE:
> +	/* Firmware found that the port name changed */
> +	case CS_PORT_LOGGED_OUT:
> +	/* BA_RJT was received for the ABTS */
> +	case CS_PORT_CONFIG_CHG:
> +		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09d,
> +		       "Abort I/O IOCB completed with error, comp_status=%x\n",
> +		comp_status);
> +		break;
> +
> +	/* BA_RJT was received for the ABTS */
> +	case CS_REJECT_RECEIVED:
> +		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e,
> +		       "BA_RJT was received for the ABTS rjt_vendorUnique = %u",
> +			abt->fw.ba_rjt_vendorUnique);
> +		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09e,
> +		       "ba_rjt_reasonCodeExpl = %u, ba_rjt_reasonCode = %u\n",
> +		       abt->fw.ba_rjt_reasonCodeExpl, abt->fw.ba_rjt_reasonCode);
> +		break;
> +
> +	case CS_COMPLETE:
> +		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf09f,
> +		       "IOCB request is completed successfully comp_status=%x\n",
> +		comp_status);
> +		break;
> +
> +	case CS_IOCB_ERROR:
> +		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf0a0,
> +		       "IOCB request is failed, comp_status=%x\n", comp_status);
> +		break;
> +
> +	default:
> +		ql_dbg(ql_dbg_async + ql_dbg_mbx, vha, 0xf0a1,
> +		       "Invalid Abort IO IOCB Completion Status %x\n",
> +		comp_status);
> +		break;
> +	}
> +}
> +
> +inline void qla_wait_nvme_release_cmd_kref(srb_t *orig_sp)
> +{
> +	if (!(ql2xabts_wait_nvme && QLA_ABTS_WAIT_ENABLED(orig_sp)))
> +		return;
> +	kref_put(&orig_sp->cmd_kref, orig_sp->put_fn);
> +}
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index a760cb38e487..3cfd83fce9c5 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -327,6 +327,11 @@ MODULE_PARM_DESC(ql2xrdpenable,
> 		"Enables RDP responses. "
> 		"0 - no RDP responses (default). "
> 		"1 - provide RDP responses.");
> +int ql2xabts_wait_nvme = 1;
> +module_param(ql2xabts_wait_nvme, int, 0444);
> +MODULE_PARM_DESC(ql2xabts_wait_nvme,
> +		 "To wait for ABTS response on I/O timeouts for NVMe. (default: 1)");
> +
> 
> static void qla2x00_clear_drv_active(struct qla_hw_data *);
> static void qla2x00_free_device(scsi_qla_host_t *);
> -- 
> 2.19.0.rc0
> 

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 5/7] qla2xxx: Fix mailbox Ch erroneous error
  2021-01-05 10:38 ` [PATCH v3 5/7] qla2xxx: Fix mailbox Ch erroneous error Nilesh Javali
@ 2021-01-06 15:37   ` Himanshu Madhani
  0 siblings, 0 replies; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:37 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream



> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Quinn Tran <qutran@marvell.com>
> 
> Mailbox Ch/dump ram extend expects mb register 10 to be
> set. If not set/clear, firmware can pick up garbage from previous
> invocation of this mailbox. Example: mctp dump can set mb10.
> On subsequent flash read which use mailbox cmd Ch, mb10 can
> retain previous value.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Quinn Tran <qutran@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_dbg.c | 1 +
> drivers/scsi/qla2xxx/qla_mbx.c | 3 ++-
> 2 files changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
> index bb7431912d41..144a893e7335 100644
> --- a/drivers/scsi/qla2xxx/qla_dbg.c
> +++ b/drivers/scsi/qla2xxx/qla_dbg.c
> @@ -202,6 +202,7 @@ qla24xx_dump_ram(struct qla_hw_data *ha, uint32_t addr, __be32 *ram,
> 		wrt_reg_word(&reg->mailbox0, MBC_DUMP_RISC_RAM_EXTENDED);
> 		wrt_reg_word(&reg->mailbox1, LSW(addr));
> 		wrt_reg_word(&reg->mailbox8, MSW(addr));
> +		wrt_reg_word(&reg->mailbox10, 0);
> 
> 		wrt_reg_word(&reg->mailbox2, MSW(LSD(dump_dma)));
> 		wrt_reg_word(&reg->mailbox3, LSW(LSD(dump_dma)));
> diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> index 629af6fe8c55..06c99963b2c9 100644
> --- a/drivers/scsi/qla2xxx/qla_mbx.c
> +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> @@ -4291,7 +4291,8 @@ qla2x00_dump_ram(scsi_qla_host_t *vha, dma_addr_t req_dma, uint32_t addr,
> 	if (MSW(addr) || IS_FWI2_CAPABLE(vha->hw)) {
> 		mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED;
> 		mcp->mb[8] = MSW(addr);
> -		mcp->out_mb = MBX_8|MBX_0;
> +		mcp->mb[10] = 0;
> +		mcp->out_mb = MBX_10|MBX_8|MBX_0;
> 	} else {
> 		mcp->mb[0] = MBC_DUMP_RISC_RAM;
> 		mcp->out_mb = MBX_0;
> -- 
> 2.19.0.rc0
> 

Looks Good. 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 6/7] qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER
  2021-01-05 10:38 ` [PATCH v3 6/7] qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER Nilesh Javali
@ 2021-01-06 15:37   ` Himanshu Madhani
  0 siblings, 0 replies; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:37 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream



> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> From: Saurav Kashyap <skashyap@marvell.com>
> 
> Enable NVME confirmation bit in PRLI.
> 
> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_iocb.c | 2 ++
> 1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> index e27359b294d3..8b41cbaf8535 100644
> --- a/drivers/scsi/qla2xxx/qla_iocb.c
> +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> @@ -2378,6 +2378,8 @@ qla24xx_prli_iocb(srb_t *sp, struct logio_entry_24xx *logio)
> 			logio->io_parameter[0] =
> 				cpu_to_le32(NVME_PRLI_SP_FIRST_BURST);
> 		if (sp->vha->flags.nvme2_enabled) {
> +			/* Set service parameter BIT_7 for NVME CONF support */
> +			logio->io_parameter[0] |= NVME_PRLI_SP_CONF;
> 			/* Set service parameter BIT_8 for SLER support */
> 			logio->io_parameter[0] |=
> 				cpu_to_le32(NVME_PRLI_SP_SLER);
> -- 
> 2.19.0.rc0
> 

Looks Good. 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH v3 7/7] qla2xxx: Update version to 10.02.00.105-k
  2021-01-05 10:38 ` [PATCH v3 7/7] qla2xxx: Update version to 10.02.00.105-k Nilesh Javali
@ 2021-01-06 15:38   ` Himanshu Madhani
  0 siblings, 0 replies; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-06 15:38 UTC (permalink / raw)
  To: Nilesh Javali; +Cc: martin.petersen, linux-scsi, GR-QLogic-Storage-Upstream



> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> 
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
> drivers/scsi/qla2xxx/qla_version.h | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
> index ccec858875dd..72c648442e8d 100644
> --- a/drivers/scsi/qla2xxx/qla_version.h
> +++ b/drivers/scsi/qla2xxx/qla_version.h
> @@ -6,9 +6,9 @@
> /*
>  * Driver version
>  */
> -#define QLA2XXX_VERSION      "10.02.00.104-k"
> +#define QLA2XXX_VERSION      "10.02.00.105-k"
> 
> #define QLA_DRIVER_MAJOR_VER	10
> #define QLA_DRIVER_MINOR_VER	2
> #define QLA_DRIVER_PATCH_VER	0
> -#define QLA_DRIVER_BETA_VER	104
> +#define QLA_DRIVER_BETA_VER	105
> -- 
> 2.19.0.rc0
> 

Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [EXT] Re: [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port
  2021-01-06 15:05   ` Himanshu Madhani
@ 2021-01-07  5:34     ` Saurav Kashyap
  2021-01-07 17:57       ` [EXT] " Himanshu Madhani
  0 siblings, 1 reply; 21+ messages in thread
From: Saurav Kashyap @ 2021-01-07  5:34 UTC (permalink / raw)
  To: Himanshu Madhani, Nilesh Javali
  Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

Hi Himanshu,
Thanks for a review, comments inline

> -----Original Message-----
> From: Himanshu Madhani <himanshu.madhani@oracle.com>
> Sent: Wednesday, January 6, 2021 8:35 PM
> To: Nilesh Javali <njavali@marvell.com>; Saurav Kashyap
> <skashyap@marvell.com>
> Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> Upstream@marvell.com>
> Subject: [EXT] Re: [PATCH v3 1/7] qla2xxx: Implementation to get and manage
> host, target stats and initiator port
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Saurav,
> 
> > On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> >
> > From: Saurav Kashyap <skashyap@marvell.com>
> >
> > This statistics will help in debugging process and checking specific
> > error counts.
> >
> 
> An example of sample statistics output would be nice (not must)
> 
> > Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> > Signed-off-by: Nilesh Javali <njavali@marvell.com>
> > Reported-by: kernel test robot <lkp@intel.com>
> > ---
> > drivers/scsi/qla2xxx/qla_attr.c |   9 +
> > drivers/scsi/qla2xxx/qla_bsg.c  | 342 ++++++++++++++++++++++++++++++++
> > drivers/scsi/qla2xxx/qla_bsg.h  |   5 +
> > drivers/scsi/qla2xxx/qla_def.h  |  71 +++++++
> > drivers/scsi/qla2xxx/qla_gbl.h  |  23 +++
> > drivers/scsi/qla2xxx/qla_gs.c   |   1 +
> > drivers/scsi/qla2xxx/qla_init.c | 216 ++++++++++++++++++++
> > drivers/scsi/qla2xxx/qla_isr.c  |  22 ++
> > drivers/scsi/qla2xxx/qla_mbx.c  |   9 +
> > drivers/scsi/qla2xxx/qla_os.c   |  20 ++
> > 10 files changed, 718 insertions(+)
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
> > index ab45ac1e5a72..63391c9be05d 100644
> > --- a/drivers/scsi/qla2xxx/qla_attr.c
> > +++ b/drivers/scsi/qla2xxx/qla_attr.c
> > @@ -710,6 +710,12 @@ qla2x00_sysfs_write_reset(struct file *filp, struct
> kobject *kobj,
> > 		ql_log(ql_log_info, vha, 0x706e,
> > 		    "Issuing ISP reset.\n");
> >
> > +		if (vha->hw->flags.port_isolated) {
> > +			ql_log(ql_log_info, vha, 0x706e,
> > +			       "Port is isolated, returning.\n");
> > +			return -EINVAL;
> > +		}
> > +
> > 		scsi_block_requests(vha->host);
> > 		if (IS_QLA82XX(ha)) {
> > 			ha->flags.isp82xx_no_md_cap = 1;
> > @@ -2717,6 +2723,9 @@ qla2x00_issue_lip(struct Scsi_Host *shost)
> > 	if (IS_QLAFX00(vha->hw))
> > 		return 0;
> >
> > +	if (vha->hw->flags.port_isolated)
> > +		return 0;
> > +
> > 	qla2x00_loop_reset(vha);
> > 	return 0;
> > }
> > diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> > index 23b604832a54..ae3bc6ec8722 100644
> > --- a/drivers/scsi/qla2xxx/qla_bsg.c
> > +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> > @@ -4,6 +4,7 @@
> >  * Copyright (c)  2003-2014 QLogic Corporation
> >  */
> > #include "qla_def.h"
> > +#include "qla_gbl.h"
> >
> > #include <linux/kthread.h>
> > #include <linux/vmalloc.h>
> > @@ -2444,6 +2445,323 @@ qla2x00_get_flash_image_status(struct bsg_job
> *bsg_job)
> > 	return 0;
> > }
> >
> > +static int
> > +qla2x00_manage_host_stats(struct bsg_job *bsg_job)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> > +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> > +	struct ql_vnd_mng_host_stats_param *req_data;
> > +	struct ql_vnd_mng_host_stats_resp rsp_data;
> > +	u32 req_data_len;
> > +	int ret = 0;
> > +
> > +	if (!vha->flags.online) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
> > +		return -EIO;
> > +	}
> > +
> > +	req_data_len = bsg_job->request_payload.payload_len;
> > +
> > +	if (req_data_len != sizeof(struct ql_vnd_mng_host_stats_param)) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> > +		return -EIO;
> > +	}
> > +
> > +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> > +	if (!req_data) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation
> failure.\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	/* Copy the request buffer in req_data */
> > +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> > +			  bsg_job->request_payload.sg_cnt, req_data,
> > +			  req_data_len);
> > +
> > +	switch (req_data->action) {
> > +	case 0:
> > +		ret = qla2xxx_stop_stats(vha->host, req_data->stat_type);
> > +		break;
> > +	case 1:
> > +		ret = qla2xxx_start_stats(vha->host, req_data->stat_type);
> > +		break;
> > +	case 2:
> > +		ret = qla2xxx_reset_stats(vha->host, req_data->stat_type);
> > +		break;
> > +	default:
> > +		ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
> > +		ret = -EIO;
> > +		break;
> > +	}
> > +
> 
> I don’t like using case 0/1/2 for the above action switch statements. Why not
> define it as QL_STATS_ACTION_START/STOP/RESET.
<SK> Make sense.
> 
> > +	kfree(req_data);
> > +
> > +	/* Prepare response */
> > +	rsp_data.status = ret;
> > +	bsg_job->reply_payload.payload_len = sizeof(struct
> ql_vnd_mng_host_stats_resp);
> > +
> > +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> > +	bsg_reply->reply_payload_rcv_len =
> > +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> > +				    bsg_job->reply_payload.sg_cnt,
> > +				    &rsp_data,
> > +				    sizeof(struct ql_vnd_mng_host_stats_resp));
> > +
> > +	bsg_reply->result = DID_OK;
> > +	bsg_job_done(bsg_job, bsg_reply->result,
> > +		     bsg_reply->reply_payload_rcv_len);
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> > +qla2x00_get_host_stats(struct bsg_job *bsg_job)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> > +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> > +	struct ql_vnd_stats_param *req_data;
> > +	struct ql_vnd_host_stats_resp rsp_data;
> > +	u32 req_data_len;
> > +	int ret = 0;
> > +	u64 ini_entry_count = 0;
> > +	u64 entry_count = 0;
> > +	u64 tgt_num = 0;
> > +	u64 tmp_stat_type = 0;
> > +	u64 response_len = 0;
> > +	void *data;
> > +
> > +	req_data_len = bsg_job->request_payload.payload_len;
> > +
> > +	if (req_data_len != sizeof(struct ql_vnd_stats_param)) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> > +		return -EIO;
> > +	}
> > +
> > +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> > +	if (!req_data) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation
> failure.\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	/* Copy the request buffer in req_data */
> > +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> > +			  bsg_job->request_payload.sg_cnt, req_data,
> req_data_len);
> > +
> > +	/* Copy stat type to work on it */
> > +	tmp_stat_type = req_data->stat_type;
> > +
> > +	if (tmp_stat_type & QLA2XX_TGT_SHT_LNK_DOWN) {
> > +		/* Num of tgts connected to this host */
> > +		tgt_num = qla2x00_get_num_tgts(vha);
> > +		/* unset BIT_17 */
> > +		tmp_stat_type &= ~(1 << 17);
> > +	}
> > +
> > +	/* Total ini stats */
> > +	ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
> > +
> > +	/* Total number of entries */
> > +	entry_count = ini_entry_count + tgt_num;
> > +
> > +	response_len = sizeof(struct ql_vnd_host_stats_resp) +
> > +		(sizeof(struct ql_vnd_stat_entry) * entry_count);
> > +
> > +	if (response_len > bsg_job->reply_payload.payload_len) {
> > +		rsp_data.status = EXT_STATUS_BUFFER_TOO_SMALL;
> > +		bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
> EXT_STATUS_BUFFER_TOO_SMALL;
> > +		bsg_job->reply_payload.payload_len = sizeof(struct
> ql_vnd_mng_host_stats_resp);
> > +
> > +		bsg_reply->reply_payload_rcv_len =
> > +			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> > +					    bsg_job->reply_payload.sg_cnt,
> &rsp_data,
> > +					    sizeof(struct
> ql_vnd_mng_host_stats_resp));
> > +
> > +		bsg_reply->result = DID_OK;
> > +		bsg_job_done(bsg_job, bsg_reply->result,
> > +			     bsg_reply->reply_payload_rcv_len);
> > +		goto host_stat_out;
> > +	}
> > +
> > +	data = kzalloc(response_len, GFP_KERNEL);
> > +
> > +	ret = qla2xxx_get_ini_stats(fc_bsg_to_shost(bsg_job), req_data-
> >stat_type,
> > +				    data, response_len);
> > +
> > +	rsp_data.status = EXT_STATUS_OK;
> > +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> > +
> > +	bsg_reply->reply_payload_rcv_len = sg_copy_from_buffer(bsg_job-
> >reply_payload.sg_list,
> > +							       bsg_job-
> >reply_payload.sg_cnt,
> > +							       data,
> response_len);
> > +	bsg_reply->result = DID_OK;
> > +	bsg_job_done(bsg_job, bsg_reply->result,
> > +		     bsg_reply->reply_payload_rcv_len);
> > +
> > +	kfree(data);
> > +host_stat_out:
> > +	kfree(req_data);
> > +	return ret;
> > +}
> > +
> > +static struct fc_rport *
> > +qla2xxx_find_rport(scsi_qla_host_t *vha, uint32_t tgt_num)
> > +{
> > +	fc_port_t *fcport = NULL;
> > +
> > +	list_for_each_entry(fcport, &vha->vp_fcports, list) {
> > +		if (fcport->rport->number == tgt_num)
> > +			return fcport->rport;
> > +	}
> > +	return NULL;
> > +}
> > +
> > +static int
> > +qla2x00_get_tgt_stats(struct bsg_job *bsg_job)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> > +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> > +	struct ql_vnd_tgt_stats_param *req_data;
> > +	u32 req_data_len;
> > +	int ret = 0;
> > +	u64 response_len = 0;
> > +	struct ql_vnd_tgt_stats_resp *data = NULL;
> > +	struct fc_rport *rport = NULL;
> > +
> > +	if (!vha->flags.online) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "Host is not online.\n");
> > +		return -EIO;
> > +	}
> > +
> > +	req_data_len = bsg_job->request_payload.payload_len;
> > +
> > +	if (req_data_len != sizeof(struct ql_vnd_stat_entry)) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> > +		return -EIO;
> > +	}
> > +
> > +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> > +	if (!req_data) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation
> failure.\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	/* Copy the request buffer in req_data */
> > +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> > +			  bsg_job->request_payload.sg_cnt,
> > +			  req_data, req_data_len);
> > +
> > +	response_len = sizeof(struct ql_vnd_tgt_stats_resp) +
> > +		sizeof(struct ql_vnd_stat_entry);
> > +
> > +	/* structure + size for one entry */
> > +	data = kzalloc(response_len, GFP_KERNEL);
> > +	if (!data) {
> > +		kfree(req_data);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	if (response_len > bsg_job->reply_payload.payload_len) {
> > +		data->status = EXT_STATUS_BUFFER_TOO_SMALL;
> > +		bsg_reply->reply_data.vendor_reply.vendor_rsp[0] =
> EXT_STATUS_BUFFER_TOO_SMALL;
> > +		bsg_job->reply_payload.payload_len = sizeof(struct
> ql_vnd_mng_host_stats_resp);
> > +
> > +		bsg_reply->reply_payload_rcv_len =
> > +			sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> > +					    bsg_job->reply_payload.sg_cnt,
> &data,
> > +					    sizeof(struct
> ql_vnd_tgt_stats_resp));
> > +
> > +		bsg_reply->result = DID_OK;
> > +		bsg_job_done(bsg_job, bsg_reply->result,
> > +			     bsg_reply->reply_payload_rcv_len);
> > +		goto tgt_stat_out;
> > +	}
> > +
> > +	rport = qla2xxx_find_rport(vha, req_data->tgt_id);
> > +	if (!rport) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "target %d not found.\n",
> req_data->tgt_id);
> > +		ret = EXT_STATUS_INVALID_PARAM;
> > +		data->status = EXT_STATUS_INVALID_PARAM;
> > +		goto reply;
> > +	}
> > +
> > +	ret = qla2xxx_get_tgt_stats(fc_bsg_to_shost(bsg_job), req_data-
> >stat_type,
> > +				    rport, (void *)data, response_len);
> > +
> > +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> > +reply:
> > +	bsg_reply->reply_payload_rcv_len =
> > +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> > +				    bsg_job->reply_payload.sg_cnt, data,
> > +				    response_len);
> > +	bsg_reply->result = DID_OK;
> > +	bsg_job_done(bsg_job, bsg_reply->result,
> > +		     bsg_reply->reply_payload_rcv_len);
> > +
> > +tgt_stat_out:
> > +	kfree(data);
> > +	kfree(req_data);
> > +
> > +	return ret;
> > +}
> > +
> > +static int
> > +qla2x00_manage_host_port(struct bsg_job *bsg_job)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
> > +	struct fc_bsg_reply *bsg_reply = bsg_job->reply;
> > +	struct ql_vnd_mng_host_port_param *req_data;
> > +	struct ql_vnd_mng_host_port_resp rsp_data;
> > +	u32 req_data_len;
> > +	int ret = 0;
> > +
> > +	req_data_len = bsg_job->request_payload.payload_len;
> > +
> > +	if (req_data_len != sizeof(struct ql_vnd_mng_host_port_param)) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data_len invalid.\n");
> > +		return -EIO;
> > +	}
> > +
> > +	req_data = kzalloc(sizeof(*req_data), GFP_KERNEL);
> > +	if (!req_data) {
> > +		ql_log(ql_log_warn, vha, 0x0000, "req_data memory allocation
> failure.\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	/* Copy the request buffer in req_data */
> > +	sg_copy_to_buffer(bsg_job->request_payload.sg_list,
> > +			  bsg_job->request_payload.sg_cnt, req_data,
> req_data_len);
> > +
> > +	switch (req_data->action) {
> > +	case 0:
> > +		ret = qla2xxx_enable_port(vha->host);
> > +		break;
> > +	case 1:
> > +		ret = qla2xxx_disable_port(vha->host);
> > +		break;
> > +	default:
> > +		ql_log(ql_log_warn, vha, 0x0000, "Invalid action.\n");
> > +		ret = -EIO;
> > +		break;
> > +	}
> > +
> 
> Same comment as above… why not use more descriptive name so that user
> does not have to go to header file to understand what is case 0 and case 1.. Just
> use QL_HOST_ACTION_ENABLE/DISABLE
<SK> Make sense.
> 
> > +	kfree(req_data);
> > +
> > +	/* Prepare response */
> > +	rsp_data.status = ret;
> > +	bsg_reply->reply_data.vendor_reply.vendor_rsp[0] = EXT_STATUS_OK;
> > +	bsg_job->reply_payload.payload_len = sizeof(struct
> ql_vnd_mng_host_port_resp);
> > +
> > +	bsg_reply->reply_payload_rcv_len =
> > +		sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
> > +				    bsg_job->reply_payload.sg_cnt, &rsp_data,
> > +				    sizeof(struct ql_vnd_mng_host_port_resp));
> > +	bsg_reply->result = DID_OK;
> > +	bsg_job_done(bsg_job, bsg_reply->result,
> > +		     bsg_reply->reply_payload_rcv_len);
> > +
> > +	return ret;
> > +}
> > +
> > static int
> > qla2x00_process_vendor_specific(struct bsg_job *bsg_job)
> > {
> > @@ -2520,6 +2838,18 @@ qla2x00_process_vendor_specific(struct bsg_job
> *bsg_job)
> > 	case QL_VND_SS_GET_FLASH_IMAGE_STATUS:
> > 		return qla2x00_get_flash_image_status(bsg_job);
> >
> > +	case QL_VND_MANAGE_HOST_STATS:
> > +		return qla2x00_manage_host_stats(bsg_job);
> > +
> > +	case QL_VND_GET_HOST_STATS:
> > +		return qla2x00_get_host_stats(bsg_job);
> > +
> > +	case QL_VND_GET_TGT_STATS:
> > +		return qla2x00_get_tgt_stats(bsg_job);
> > +
> > +	case QL_VND_MANAGE_HOST_PORT:
> > +		return qla2x00_manage_host_port(bsg_job);
> > +
> > 	default:
> > 		return -ENOSYS;
> > 	}
> > @@ -2547,6 +2877,17 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
> > 		vha = shost_priv(host);
> > 	}
> >
> > +	/* Disable port will bring down the chip, allow enable command */
> > +	if (bsg_request->rqst_data.h_vendor.vendor_cmd[0] ==
> QL_VND_MANAGE_HOST_PORT ||
> > +	    bsg_request->rqst_data.h_vendor.vendor_cmd[0] ==
> QL_VND_GET_HOST_STATS)
> > +		goto skip_chip_chk;
> > +
> > +	if (vha->hw->flags.port_isolated) {
> > +		bsg_reply->result = DID_ERROR;
> > +		/* operation not permitted */
> > +		return -EPERM;
> > +	}
> > +
> > 	if (qla2x00_chip_is_down(vha)) {
> > 		ql_dbg(ql_dbg_user, vha, 0x709f,
> > 		    "BSG: ISP abort active/needed -- cmd=%d.\n",
> > @@ -2554,6 +2895,7 @@ qla24xx_bsg_request(struct bsg_job *bsg_job)
> > 		return -EBUSY;
> > 	}
> >
> > +skip_chip_chk:
> > 	ql_dbg(ql_dbg_user, vha, 0x7000,
> > 	    "Entered %s msgcode=0x%x.\n", __func__, bsg_request->msgcode);
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_bsg.h b/drivers/scsi/qla2xxx/qla_bsg.h
> > index 1a09b5512267..0274e99e4a12 100644
> > --- a/drivers/scsi/qla2xxx/qla_bsg.h
> > +++ b/drivers/scsi/qla2xxx/qla_bsg.h
> > @@ -31,6 +31,10 @@
> > #define QL_VND_DPORT_DIAGNOSTICS	0x19
> > #define QL_VND_GET_PRIV_STATS_EX	0x1A
> > #define QL_VND_SS_GET_FLASH_IMAGE_STATUS	0x1E
> > +#define QL_VND_MANAGE_HOST_STATS	0x23
> > +#define QL_VND_GET_HOST_STATS		0x24
> > +#define QL_VND_GET_TGT_STATS		0x25
> > +#define QL_VND_MANAGE_HOST_PORT		0x26
> >
> > /* BSG Vendor specific subcode returns */
> > #define EXT_STATUS_OK			0
> > @@ -40,6 +44,7 @@
> > #define EXT_STATUS_DATA_OVERRUN		7
> > #define EXT_STATUS_DATA_UNDERRUN	8
> > #define EXT_STATUS_MAILBOX		11
> > +#define EXT_STATUS_BUFFER_TOO_SMALL	16
> > #define EXT_STATUS_NO_MEMORY		17
> > #define EXT_STATUS_DEVICE_OFFLINE	22
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> > index 30c7e5e63851..f2f1b0231033 100644
> > --- a/drivers/scsi/qla2xxx/qla_def.h
> > +++ b/drivers/scsi/qla2xxx/qla_def.h
> > @@ -2557,6 +2557,10 @@ typedef struct fc_port {
> > 	u16 n2n_chip_reset;
> >
> > 	struct dentry *dfs_rport_dir;
> > +
> > +	u64 tgt_short_link_down_cnt;
> > +	u64 tgt_link_down_time;
> > +	u64 dev_loss_tmo;
> > } fc_port_t;
> >
> > enum {
> > @@ -3922,6 +3926,7 @@ struct qla_hw_data {
> > 		uint32_t	scm_enabled:1;
> > 		uint32_t	max_req_queue_warned:1;
> > 		uint32_t	plogi_template_valid:1;
> > +		uint32_t	port_isolated:1;
> 
> Just for my understanding, in regards to stats display, What does port_isolated
> indicates?
<SK> It's a state of the port, it comes as part of managing the port. If the error count is more,
user can opt to change the state and port will go to offline state.

> 
> > 	} flags;
> >
> > 	uint16_t max_exchg;
> > @@ -4851,6 +4856,13 @@ typedef struct scsi_qla_host {
> > 	uint8_t	scm_fabric_connection_flags;
> >
> > 	unsigned int irq_offset;
> > +
> > +	u64 hw_err_cnt;
> > +	u64 interface_err_cnt;
> > +	u64 cmd_timeout_cnt;
> > +	u64 reset_cmd_err_cnt;
> > +	u64 link_down_time;
> > +	u64 short_link_down_cnt;
> > } scsi_qla_host_t;
> >
> > struct qla27xx_image_status {
> > @@ -5174,6 +5186,65 @@ struct sff_8247_a0 {
> > #define PRLI_PHASE(_cls) \
> > 	((_cls == DSC_LS_PRLI_PEND) || (_cls == DSC_LS_PRLI_COMP))
> >
> > +enum ql_vnd_host_stat_action {
> > +	stop = 0,
> > +	start,
> > +	clear,
> > +};
> > +
> > +struct ql_vnd_mng_host_stats_param {
> > +	u32 stat_type;
> > +	enum ql_vnd_host_stat_action action;
> > +} __packed;
> > +
> > +struct ql_vnd_mng_host_stats_resp {
> > +	u32 status;
> > +} __packed;
> > +
> > +struct ql_vnd_stats_param {
> > +	u32 stat_type;
> > +} __packed;
> > +
> > +struct ql_vnd_tgt_stats_param {
> > +	s32 tgt_id;
> > +	u32 stat_type;
> > +} __packed;
> > +
> > +enum ql_vnd_host_port_action {
> > +	enable = 0,
> > +	disable,
> > +};
> > +
> > +struct ql_vnd_mng_host_port_param {
> > +	enum ql_vnd_host_port_action action;
> > +} __packed;
> > +
> > +struct ql_vnd_mng_host_port_resp {
> > +	u32 status;
> > +} __packed;
> > +
> > +struct ql_vnd_stat_entry {
> > +	u32 stat_type;	/* Failure type */
> > +	u32 tgt_num;	/* Target Num */
> > +	u64 cnt;	/* Counter value */
> > +} __packed;
> > +
> > +struct ql_vnd_stats {
> > +	u64 entry_count; /* Num of entries */
> > +	u64 rservd;
> > +	struct ql_vnd_stat_entry entry[0]; /* Place holder of entries */
> > +} __packed;
> > +
> > +struct ql_vnd_host_stats_resp {
> > +	u32 status;
> > +	struct ql_vnd_stats stats;
> > +} __packed;
> > +
> > +struct ql_vnd_tgt_stats_resp {
> > +	u32 status;
> > +	struct ql_vnd_stats stats;
> > +} __packed;
> > +
> > #include "qla_target.h"
> > #include "qla_gbl.h"
> > #include "qla_dbg.h"
> > diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
> > index e39b4f2da73a..708f82311b83 100644
> > --- a/drivers/scsi/qla2xxx/qla_gbl.h
> > +++ b/drivers/scsi/qla2xxx/qla_gbl.h
> > @@ -945,4 +945,27 @@ extern void
> qla2x00_dfs_remove_rport(scsi_qla_host_t *vha, struct fc_port *fp);
> > /* nvme.c */
> > void qla_nvme_unregister_remote_port(struct fc_port *fcport);
> > void qla_handle_els_plogi_done(scsi_qla_host_t *vha, struct event_arg *ea);
> > +
> > +#define QLA2XX_HW_ERROR			BIT_0
> > +#define QLA2XX_SHT_LNK_DWN		BIT_1
> > +#define QLA2XX_INT_ERR			BIT_2
> > +#define QLA2XX_CMD_TIMEOUT		BIT_3
> > +#define QLA2XX_RESET_CMD_ERR		BIT_4
> > +#define QLA2XX_TGT_SHT_LNK_DOWN		BIT_17
> > +
> > +#define QLA2XX_MAX_LINK_DOWN_TIME	100
> > +
> > +int qla2xxx_start_stats(struct Scsi_Host *shost, u32 flags);
> > +int qla2xxx_stop_stats(struct Scsi_Host *shost, u32 flags);
> > +int qla2xxx_reset_stats(struct Scsi_Host *shost, u32 flags);
> > +
> > +int qla2xxx_get_ini_stats(struct Scsi_Host *shost, u32 flags, void *data, u64
> size);
> > +int qla2xxx_get_tgt_stats(struct Scsi_Host *shost, u32 flags,
> > +			  struct fc_rport *rport, void *data, u64 size);
> > +int qla2xxx_disable_port(struct Scsi_Host *shost);
> > +int qla2xxx_enable_port(struct Scsi_Host *shost);
> > +
> > +uint64_t qla2x00_get_num_tgts(scsi_qla_host_t *vha);
> > +uint64_t qla2x00_count_set_bits(u32 num);
> > +
> > #endif /* _QLA_GBL_H */
> > diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> > index 391ac75e3de3..517d358b0031 100644
> > --- a/drivers/scsi/qla2xxx/qla_gs.c
> > +++ b/drivers/scsi/qla2xxx/qla_gs.c
> > @@ -3563,6 +3563,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t
> *vha, srb_t *sp)
> > 					       __func__, __LINE__,
> > 					       fcport->port_name);
> >
> > +					fcport->tgt_link_down_time = 0;
> >
> 	qlt_schedule_sess_for_deletion(fcport);
> > 					continue;
> > 				}
> > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> > index dcc0f0d823db..410ff5534a59 100644
> > --- a/drivers/scsi/qla2xxx/qla_init.c
> > +++ b/drivers/scsi/qla2xxx/qla_init.c
> > @@ -4993,6 +4993,9 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t
> flags)
> > 	fcport->login_retry = vha->hw->login_retry_count;
> > 	fcport->chip_reset = vha->hw->base_qpair->chip_reset;
> > 	fcport->logout_on_delete = 1;
> > +	fcport->tgt_link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> > +	fcport->tgt_short_link_down_cnt = 0;
> > +	fcport->dev_loss_tmo = 0;
> >
> > 	if (!fcport->ct_desc.ct_sns) {
> > 		ql_log(ql_log_warn, vha, 0xd049,
> > @@ -5490,6 +5493,7 @@ qla2x00_reg_remote_port(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> > 	spin_lock_irqsave(fcport->vha->host->host_lock, flags);
> > 	*((fc_port_t **)rport->dd_data) = fcport;
> > 	spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
> > +	fcport->dev_loss_tmo = rport->dev_loss_tmo;
> >
> > 	rport->supported_classes = fcport->supported_classes;
> >
> > @@ -5548,6 +5552,11 @@ qla2x00_update_fcport(scsi_qla_host_t *vha,
> fc_port_t *fcport)
> > 		fcport->logout_on_delete = 1;
> > 	fcport->n2n_chip_reset = fcport->n2n_link_reset_cnt = 0;
> >
> > +	if (fcport->tgt_link_down_time < fcport->dev_loss_tmo) {
> > +		fcport->tgt_short_link_down_cnt++;
> > +		fcport->tgt_link_down_time =
> QLA2XX_MAX_LINK_DOWN_TIME;
> > +	}
> > +
> > 	switch (vha->hw->current_topology) {
> > 	case ISP_CFG_N:
> > 	case ISP_CFG_NL:
> > @@ -6908,6 +6917,9 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
> > 	if (vha->flags.online) {
> > 		qla2x00_abort_isp_cleanup(vha);
> >
> > +		if (vha->hw->flags.port_isolated)
> > +			return status;
> > +
> > 		if (test_and_clear_bit(ISP_ABORT_TO_ROM, &vha-
> >dpc_flags)) {
> > 			ha->flags.chip_reset_done = 1;
> > 			vha->flags.online = 1;
> > @@ -7029,6 +7041,11 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
> >
> > 	}
> >
> > +	if (vha->hw->flags.port_isolated) {
> > +		qla2x00_abort_isp_cleanup(vha);
> > +		return status;
> > +	}
> > +
> > 	if (!status) {
> > 		ql_dbg(ql_dbg_taskm, vha, 0x8022, "%s succeeded.\n",
> __func__);
> > 		qla2x00_configure_hba(vha);
> > @@ -9171,3 +9188,202 @@ int qla2xxx_delete_qpair(struct scsi_qla_host
> *vha, struct qla_qpair *qpair)
> > fail:
> > 	return ret;
> > }
> > +
> > +uint64_t
> > +qla2x00_count_set_bits(uint32_t num)
> > +{
> > +	/* Brian Kernighan's Alogorithm */
> > +	u64 count = 0;
> > +
> > +	while (num) {
> > +		num &= (num - 1);
> > +		count++;
> > +	}
> > +	return count;
> > +}
> > +
> > +uint64_t
> > +qla2x00_get_num_tgts(scsi_qla_host_t *vha)
> > +{
> > +	fc_port_t *f, *tf;
> > +	u64 count = 0;
> > +
> > +	f = NULL;
> > +	tf = NULL;
> > +
> > +	list_for_each_entry_safe(f, tf, &vha->vp_fcports, list) {
> > +		if (f->port_type != FCT_TARGET)
> > +			continue;
> > +		count++;
> > +	}
> > +	return count;
> > +}
> > +
> > +int qla2xxx_reset_stats(struct Scsi_Host *host, u32 flags)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(host);
> > +	fc_port_t *fcport = NULL;
> > +	unsigned long int_flags;
> > +
> > +	if (flags & QLA2XX_HW_ERROR)
> > +		vha->hw_err_cnt = 0;
> > +	if (flags & QLA2XX_SHT_LNK_DWN)
> > +		vha->short_link_down_cnt = 0;
> > +	if (flags & QLA2XX_INT_ERR)
> > +		vha->interface_err_cnt = 0;
> > +	if (flags & QLA2XX_CMD_TIMEOUT)
> > +		vha->cmd_timeout_cnt = 0;
> > +	if (flags & QLA2XX_RESET_CMD_ERR)
> > +		vha->reset_cmd_err_cnt = 0;
> > +	if (flags & QLA2XX_TGT_SHT_LNK_DOWN) {
> > +		spin_lock_irqsave(&vha->hw->tgt.sess_lock, int_flags);
> > +		list_for_each_entry(fcport, &vha->vp_fcports, list) {
> > +			fcport->tgt_short_link_down_cnt = 0;
> > +			fcport->tgt_link_down_time =
> QLA2XX_MAX_LINK_DOWN_TIME;
> > +		}
> > +		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, int_flags);
> > +	}
> > +	vha->link_down_time = QLA2XX_MAX_LINK_DOWN_TIME;
> > +	return 0;
> > +}
> > +
> > +int qla2xxx_start_stats(struct Scsi_Host *host, u32 flags)
> > +{
> > +	return qla2xxx_reset_stats(host, flags);
> > +}
> > +
> > +int qla2xxx_stop_stats(struct Scsi_Host *host, u32 flags)
> > +{
> > +	return qla2xxx_reset_stats(host, flags);
> > +}
> > +
> > +int qla2xxx_get_ini_stats(struct Scsi_Host *host, u32 flags,
> > +			  void *data, u64 size)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(host);
> > +	struct ql_vnd_host_stats_resp *resp = (struct ql_vnd_host_stats_resp
> *)data;
> > +	struct ql_vnd_stats *rsp_data = &resp->stats;
> > +	u64 ini_entry_count = 0;
> > +	u64 i = 0;
> > +	u64 entry_count = 0;
> > +	u64 num_tgt = 0;
> > +	u32 tmp_stat_type = 0;
> > +	fc_port_t *fcport = NULL;
> > +	unsigned long int_flags;
> > +
> > +	/* Copy stat type to work on it */
> > +	tmp_stat_type = flags;
> > +
> > +	if (tmp_stat_type & BIT_17) {
> > +		num_tgt = qla2x00_get_num_tgts(vha);
> > +		/* unset BIT_17 */
> > +		tmp_stat_type &= ~(1 << 17);
> > +	}
> > +	ini_entry_count = qla2x00_count_set_bits(tmp_stat_type);
> > +
> > +	entry_count = ini_entry_count + num_tgt;
> > +
> > +	rsp_data->entry_count = entry_count;
> > +
> > +	i = 0;
> > +	if (flags & QLA2XX_HW_ERROR) {
> > +		rsp_data->entry[i].stat_type = QLA2XX_HW_ERROR;
> > +		rsp_data->entry[i].tgt_num = 0x0;
> > +		rsp_data->entry[i].cnt = vha->hw_err_cnt;
> > +		i++;
> > +	}
> > +
> > +	if (flags & QLA2XX_SHT_LNK_DWN) {
> > +		rsp_data->entry[i].stat_type = QLA2XX_SHT_LNK_DWN;
> > +		rsp_data->entry[i].tgt_num = 0x0;
> > +		rsp_data->entry[i].cnt = vha->short_link_down_cnt;
> > +		i++;
> > +	}
> > +
> > +	if (flags & QLA2XX_INT_ERR) {
> > +		rsp_data->entry[i].stat_type = QLA2XX_INT_ERR;
> > +		rsp_data->entry[i].tgt_num = 0x0;
> > +		rsp_data->entry[i].cnt = vha->interface_err_cnt;
> > +		i++;
> > +	}
> > +
> > +	if (flags & QLA2XX_CMD_TIMEOUT) {
> > +		rsp_data->entry[i].stat_type = QLA2XX_CMD_TIMEOUT;
> > +		rsp_data->entry[i].tgt_num = 0x0;
> > +		rsp_data->entry[i].cnt = vha->cmd_timeout_cnt;
> > +		i++;
> > +	}
> > +
> > +	if (flags & QLA2XX_RESET_CMD_ERR) {
> > +		rsp_data->entry[i].stat_type = QLA2XX_RESET_CMD_ERR;
> > +		rsp_data->entry[i].tgt_num = 0x0;
> > +		rsp_data->entry[i].cnt = vha->reset_cmd_err_cnt;
> > +		i++;
> > +	}
> > +
> > +	/* i will continue from previous loop, as target
> > +	 * entries are after initiator
> > +	 */
> > +	if (flags & QLA2XX_TGT_SHT_LNK_DOWN) {
> > +		spin_lock_irqsave(&vha->hw->tgt.sess_lock, int_flags);
> > +		list_for_each_entry(fcport, &vha->vp_fcports, list) {
> > +			if (fcport->port_type != FCT_TARGET)
> > +				continue;
> > +			if (!fcport->rport)
> > +				continue;
> > +			rsp_data->entry[i].stat_type =
> QLA2XX_TGT_SHT_LNK_DOWN;
> > +			rsp_data->entry[i].tgt_num = fcport->rport->number;
> > +			rsp_data->entry[i].cnt = fcport-
> >tgt_short_link_down_cnt;
> > +			i++;
> > +		}
> > +		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, int_flags);
> > +	}
> > +	resp->status = EXT_STATUS_OK;
> > +
> > +	return 0;
> > +}
> > +
> > +int qla2xxx_get_tgt_stats(struct Scsi_Host *host, u32 flags,
> > +			  struct fc_rport *rport, void *data, u64 size)
> > +{
> > +	struct ql_vnd_tgt_stats_resp *tgt_data = data;
> > +	fc_port_t *fcport = *(fc_port_t **)rport->dd_data;
> > +
> > +	tgt_data->status = 0;
> > +	tgt_data->stats.entry_count = 1;
> > +	tgt_data->stats.entry[0].stat_type = flags;
> > +	tgt_data->stats.entry[0].tgt_num = rport->number;
> > +	tgt_data->stats.entry[0].cnt = fcport->tgt_short_link_down_cnt;
> > +
> > +	return 0;
> > +}
> > +
> > +int qla2xxx_disable_port(struct Scsi_Host *host)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(host);
> > +
> > +	vha->hw->flags.port_isolated = 1;
> > +
> > +	if (qla2x00_chip_is_down(vha))
> > +		return 0;
> > +
> > +	if (vha->flags.online) {
> > +		qla2x00_abort_isp_cleanup(vha);
> > +		qla2x00_wait_for_sess_deletion(vha);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +int qla2xxx_enable_port(struct Scsi_Host *host)
> > +{
> > +	scsi_qla_host_t *vha = shost_priv(host);
> > +
> > +	vha->hw->flags.port_isolated = 0;
> > +	/* Set the flag to 1, so that isp_abort can proceed */
> > +	vha->flags.online = 1;
> > +	set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> > +	qla2xxx_wake_dpc(vha);
> > +
> > +	return 0;
> > +}
> > diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> > index f9142dbec112..9cf8326ab9fc 100644
> > --- a/drivers/scsi/qla2xxx/qla_isr.c
> > +++ b/drivers/scsi/qla2xxx/qla_isr.c
> > @@ -1059,6 +1059,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
> rsp_que *rsp, uint16_t *mb)
> >
> > 	case MBA_SYSTEM_ERR:		/* System Error */
> > 		mbx = 0;
> > +
> > +		vha->hw_err_cnt++;
> > +
> > 		if (IS_QLA81XX(ha) || IS_QLA83XX(ha) ||
> > 		    IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
> > 			u16 m[4];
> > @@ -1112,6 +1115,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
> rsp_que *rsp, uint16_t *mb)
> > 		ql_log(ql_log_warn, vha, 0x5006,
> > 		    "ISP Request Transfer Error (%x).\n",  mb[1]);
> >
> > +		vha->hw_err_cnt++;
> > +
> > 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> > 		break;
> >
> > @@ -1119,6 +1124,8 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
> rsp_que *rsp, uint16_t *mb)
> > 		ql_log(ql_log_warn, vha, 0x5007,
> > 		    "ISP Response Transfer Error (%x).\n", mb[1]);
> >
> > +		vha->hw_err_cnt++;
> > +
> > 		set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> > 		break;
> >
> > @@ -1176,12 +1183,18 @@ qla2x00_async_event(scsi_qla_host_t *vha,
> struct rsp_que *rsp, uint16_t *mb)
> > 		vha->flags.management_server_logged_in = 0;
> > 		qla2x00_post_aen_work(vha, FCH_EVT_LINKUP, ha-
> >link_data_rate);
> >
> > +		if (vha->link_down_time < vha->hw->port_down_retry_count) {
> > +			vha->short_link_down_cnt++;
> > +			vha->link_down_time =
> QLA2XX_MAX_LINK_DOWN_TIME;
> > +		}
> > +
> > 		break;
> >
> > 	case MBA_LOOP_DOWN:		/* Loop Down Event */
> > 		SAVE_TOPO(ha);
> > 		ha->flags.lip_ae = 0;
> > 		ha->current_topology = 0;
> > +		vha->link_down_time = 0;
> >
> > 		mbx = (IS_QLA81XX(ha) || IS_QLA8031(ha))
> > 			? rd_reg_word(&reg24->mailbox4) : 0;
> > @@ -1503,6 +1516,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
> rsp_que *rsp, uint16_t *mb)
> > 		ql_dbg(ql_dbg_async, vha, 0x5016,
> > 		    "Discard RND Frame -- %04x %04x %04x.\n",
> > 		    mb[1], mb[2], mb[3]);
> > +		vha->interface_err_cnt++;
> > 		break;
> >
> > 	case MBA_TRACE_NOTIFICATION:
> > @@ -1592,6 +1606,7 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
> rsp_que *rsp, uint16_t *mb)
> >
> > 	case MBA_IDC_AEN:
> > 		if (IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
> > +			vha->hw_err_cnt++;
> > 			qla27xx_handle_8200_aen(vha, mb);
> > 		} else if (IS_QLA83XX(ha)) {
> > 			mb[4] = rd_reg_word(&reg24->mailbox4);
> > @@ -3101,6 +3116,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
> rsp_que *rsp, void *pkt)
> > 				    "Dropped frame(s) detected (0x%x of 0x%x
> bytes).\n",
> > 				    resid, scsi_bufflen(cp));
> >
> > +				vha->interface_err_cnt++;
> > +
> > 				res = DID_ERROR << 16 | lscsi_status;
> > 				goto check_scsi_status;
> > 			}
> > @@ -3126,6 +3143,8 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
> rsp_que *rsp, void *pkt)
> > 			    "Dropped frame(s) detected (0x%x of 0x%x
> bytes).\n",
> > 			    resid, scsi_bufflen(cp));
> >
> > +			vha->interface_err_cnt++;
> > +
> > 			res = DID_ERROR << 16 | lscsi_status;
> > 			goto check_scsi_status;
> > 		} else {
> > @@ -3208,6 +3227,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
> rsp_que *rsp, void *pkt)
> >
> > 	case CS_TRANSPORT:
> > 		res = DID_ERROR << 16;
> > +		vha->hw_err_cnt++;
> >
> > 		if (!IS_PI_SPLIT_DET_CAPABLE(ha))
> > 			break;
> > @@ -3228,6 +3248,7 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
> rsp_que *rsp, void *pkt)
> > 		ql_dump_buffer(ql_dbg_tgt + ql_dbg_verbose, vha, 0xe0ee,
> > 		    pkt, sizeof(*sts24));
> > 		res = DID_ERROR << 16;
> > +		vha->hw_err_cnt++;
> > 		break;
> > 	default:
> > 		res = DID_ERROR << 16;
> > @@ -3839,6 +3860,7 @@ qla24xx_msix_default(int irq, void *dev_id)
> > 			    hccr);
> >
> > 			qla2xxx_check_risc_status(vha);
> > +			vha->hw_err_cnt++;
> >
> > 			ha->isp_ops->fw_dump(vha);
> > 			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
> > diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
> > index d7d4ab65009c..f438cdedca23 100644
> > --- a/drivers/scsi/qla2xxx/qla_mbx.c
> > +++ b/drivers/scsi/qla2xxx/qla_mbx.c
> > @@ -180,6 +180,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha,
> mbx_cmd_t *mcp)
> > 		ql_log(ql_log_warn, vha, 0xd035,
> > 		    "Cmd access timeout, cmd=0x%x, Exiting.\n",
> > 		    mcp->mb[0]);
> > +		vha->hw_err_cnt++;
> > 		atomic_dec(&ha->num_pend_mbx_stage1);
> > 		return QLA_FUNCTION_TIMEOUT;
> > 	}
> > @@ -307,6 +308,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha,
> mbx_cmd_t *mcp)
> > 				atomic_dec(&ha->num_pend_mbx_stage2);
> > 				ql_dbg(ql_dbg_mbx, vha, 0x1012,
> > 				    "Pending mailbox timeout, exiting.\n");
> > +				vha->hw_err_cnt++;
> > 				rval = QLA_FUNCTION_TIMEOUT;
> > 				goto premature_exit;
> > 			}
> > @@ -418,6 +420,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha,
> mbx_cmd_t *mcp)
> > 			    "mb[0-3]=[0x%x 0x%x 0x%x 0x%x] mb7 0x%x
> host_status 0x%x hccr 0x%x\n",
> > 			    command, ictrl, jiffies, mb[0], mb[1], mb[2], mb[3],
> > 			    mb[7], host_status, hccr);
> > +			vha->hw_err_cnt++;
> >
> > 		} else {
> > 			mb[0] = RD_MAILBOX_REG(ha, &reg->isp, 0);
> > @@ -425,6 +428,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha,
> mbx_cmd_t *mcp)
> > 			ql_dbg(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1119,
> > 			    "MBX Command timeout for cmd %x, iocontrol=%x
> jiffies=%lx "
> > 			    "mb[0]=0x%x\n", command, ictrl, jiffies, mb[0]);
> > +			vha->hw_err_cnt++;
> > 		}
> > 		ql_dump_regs(ql_dbg_mbx + ql_dbg_buffer, vha, 0x1019);
> >
> > @@ -497,6 +501,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha,
> mbx_cmd_t *mcp)
> > 				    "mb[0]=0x%x, eeh_busy=0x%x. Scheduling
> ISP "
> > 				    "abort.\n", command, mcp->mb[0],
> > 				    ha->flags.eeh_busy);
> > +				vha->hw_err_cnt++;
> > 				set_bit(ISP_ABORT_NEEDED, &vha-
> >dpc_flags);
> > 				qla2xxx_wake_dpc(vha);
> > 			}
> > @@ -521,6 +526,7 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha,
> mbx_cmd_t *mcp)
> > 				    "Mailbox cmd timeout occurred, cmd=0x%x,
> "
> > 				    "mb[0]=0x%x. Scheduling ISP abort ",
> > 				    command, mcp->mb[0]);
> > +				vha->hw_err_cnt++;
> > 				set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
> > 				clear_bit(ISP_ABORT_NEEDED, &vha-
> >dpc_flags);
> > 				/* Allow next mbx cmd to come in. */
> > @@ -625,6 +631,7 @@ qla2x00_load_ram(scsi_qla_host_t *vha, dma_addr_t
> req_dma, uint32_t risc_addr,
> > 		ql_dbg(ql_dbg_mbx, vha, 0x1023,
> > 		    "Failed=%x mb[0]=%x mb[1]=%x.\n",
> > 		    rval, mcp->mb[0], mcp->mb[1]);
> > +		vha->hw_err_cnt++;
> > 	} else {
> > 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1024,
> > 		    "Done %s.\n", __func__);
> > @@ -736,6 +743,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t
> risc_addr)
> >
> > 		ql_dbg(ql_dbg_mbx, vha, 0x1026,
> > 		    "Failed=%x mb[0]=%x.\n", rval, mcp->mb[0]);
> > +		vha->hw_err_cnt++;
> > 		return rval;
> > 	}
> >
> > @@ -1313,6 +1321,7 @@ qla2x00_mbx_reg_test(scsi_qla_host_t *vha)
> > 	if (rval != QLA_SUCCESS) {
> > 		/*EMPTY*/
> > 		ql_dbg(ql_dbg_mbx, vha, 0x1033, "Failed=%x.\n", rval);
> > +		vha->hw_err_cnt++;
> > 	} else {
> > 		/*EMPTY*/
> > 		ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1034,
> > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> > index f80abe28f35a..a760cb38e487 100644
> > --- a/drivers/scsi/qla2xxx/qla_os.c
> > +++ b/drivers/scsi/qla2xxx/qla_os.c
> > @@ -1274,6 +1274,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
> > 	sp = scsi_cmd_priv(cmd);
> > 	qpair = sp->qpair;
> >
> > +	vha->cmd_timeout_cnt++;
> > +
> > 	if ((sp->fcport && sp->fcport->deleted) || !qpair)
> > 		return SUCCESS;
> >
> > @@ -1442,6 +1444,7 @@ __qla2xxx_eh_generic_reset(char *name, enum
> nexus_wait_type type,
> > 	    "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name,
> > 	    reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun,
> > 	    cmd);
> > +	vha->reset_cmd_err_cnt++;
> > 	return FAILED;
> > }
> >
> > @@ -3141,6 +3144,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const
> struct pci_device_id *id)
> > 	ha->mr.fcport.supported_classes = FC_COS_UNSPECIFIED;
> > 	ha->mr.fcport.scan_state = 1;
> >
> > +	qla2xxx_reset_stats(host, QLA2XX_HW_ERROR |
> QLA2XX_SHT_LNK_DWN |
> > +			    QLA2XX_INT_ERR | QLA2XX_CMD_TIMEOUT |
> > +			    QLA2XX_RESET_CMD_ERR |
> QLA2XX_TGT_SHT_LNK_DOWN);
> > +
> > 	/* Set the SG table size based on ISP type */
> > 	if (!IS_FWI2_CAPABLE(ha)) {
> > 		if (IS_QLA2100(ha))
> > @@ -5090,6 +5097,7 @@ void qla24xx_create_new_sess(struct scsi_qla_host
> *vha, struct qla_work_evt *e)
> > 			fcport->d_id = e->u.new_sess.id;
> > 			fcport->flags |= FCF_FABRIC_DEVICE;
> > 			fcport->fw_login_state = DSC_LS_PLOGI_PEND;
> > +			fcport->tgt_short_link_down_cnt = 0;
> >
> > 			memcpy(fcport->port_name, e-
> >u.new_sess.port_name,
> > 			    WWN_SIZE);
> > @@ -7061,6 +7069,8 @@ qla2x00_timer(struct timer_list *t)
> > 	uint16_t        w;
> > 	struct qla_hw_data *ha = vha->hw;
> > 	struct req_que *req;
> > +	unsigned long flags;
> > +	fc_port_t *fcport = NULL;
> >
> > 	if (ha->flags.eeh_busy) {
> > 		ql_dbg(ql_dbg_timer, vha, 0x6000,
> > @@ -7092,6 +7102,16 @@ qla2x00_timer(struct timer_list *t)
> > 	if (!vha->vp_idx && IS_QLAFX00(ha))
> > 		qlafx00_timer_routine(vha);
> >
> > +	if (vha->link_down_time < QLA2XX_MAX_LINK_DOWN_TIME)
> > +		vha->link_down_time++;
> > +
> > +	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
> > +	list_for_each_entry(fcport, &vha->vp_fcports, list) {
> > +		if (fcport->tgt_link_down_time <
> QLA2XX_MAX_LINK_DOWN_TIME)
> > +			fcport->tgt_link_down_time++;
> > +	}
> > +	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
> > +
> > 	/* Loop down handler. */
> > 	if (atomic_read(&vha->loop_down_timer) > 0 &&
> > 	    !(test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags)) &&
> > --
> > 2.19.0.rc0
> >
> 
> --
> Himanshu Madhani	 Oracle Linux Engineering

Thanks,
~Saurav


^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [EXT] Re: [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level
  2021-01-06 15:06   ` Himanshu Madhani
@ 2021-01-07  5:51     ` Saurav Kashyap
  2021-01-07 17:51       ` [EXT] " Himanshu Madhani
  0 siblings, 1 reply; 21+ messages in thread
From: Saurav Kashyap @ 2021-01-07  5:51 UTC (permalink / raw)
  To: Himanshu Madhani, Nilesh Javali
  Cc: Martin K. Petersen, linux-scsi, GR-QLogic-Storage-Upstream

Hi Himanshu,
Thanks for the review, comments inline..

> -----Original Message-----
> From: Himanshu Madhani <himanshu.madhani@oracle.com>
> Sent: Wednesday, January 6, 2021 8:37 PM
> To: Nilesh Javali <njavali@marvell.com>; Saurav Kashyap
> <skashyap@marvell.com>
> Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> Upstream@marvell.com>
> Subject: [EXT] Re: [PATCH v3 3/7] qla2xxx: Move some messages from debug to
> normal log level
> 
> External Email
> 
> ----------------------------------------------------------------------
> Hi Saurav,
> 
> > On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> >
> > From: Saurav Kashyap <skashyap@marvell.com>
> >
> > This change will aid in debugging issues where debug level is not set.
> >
> > Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> > Signed-off-by: Nilesh Javali <njavali@marvell.com>
> > ---
> > drivers/scsi/qla2xxx/qla_init.c | 10 +++----
> > drivers/scsi/qla2xxx/qla_isr.c  | 52 ++++++++++++++++-----------------
> > 2 files changed, 30 insertions(+), 32 deletions(-)
> >
> > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> > index 410ff5534a59..221369cdf71f 100644
> > --- a/drivers/scsi/qla2xxx/qla_init.c
> > +++ b/drivers/scsi/qla2xxx/qla_init.c
> > @@ -347,11 +347,11 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> fc_port_t *fcport,
> > 	if (NVME_TARGET(vha->hw, fcport))
> > 		lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
> >
> > -	ql_dbg(ql_dbg_disc, vha, 0x2072,
> > -	    "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
> > -		"retries=%d.\n", fcport->port_name, sp->handle, fcport-
> >loop_id,
> > -	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
> > -	    fcport->login_retry);
> > +	ql_log(ql_log_warn, vha, 0x2072,
> > +	       "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x
> retries=%d.\n",
> > +	       fcport->port_name, sp->handle, fcport->loop_id,
> > +	       fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
> > +	       fcport->login_retry);
> >
> > 	rval = qla2x00_start_sp(sp);
> > 	if (rval != QLA_SUCCESS) {
> > diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> > index 9cf8326ab9fc..bfc8bbaeea46 100644
> > --- a/drivers/scsi/qla2xxx/qla_isr.c
> > +++ b/drivers/scsi/qla2xxx/qla_isr.c
> > @@ -1455,9 +1455,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
> rsp_que *rsp, uint16_t *mb)
> > 		if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
> > 			break;
> >
> > -		ql_dbg(ql_dbg_async, vha, 0x5013,
> > -		    "RSCN database changed -- %04x %04x %04x.\n",
> > -		    mb[1], mb[2], mb[3]);
> > +		ql_log(ql_log_warn, vha, 0x5013,
> > +		       "RSCN database changed -- %04x %04x %04x.\n",
> > +		       mb[1], mb[2], mb[3]);
> >
> > 		rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
> > 		host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area <<
> 8)
> > @@ -2221,12 +2221,12 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct
> req_que *req,
> > 		break;
> > 	}
> >
> > -	ql_dbg(ql_dbg_async, sp->vha, 0x5037,
> > -	    "Async-%s failed: handle=%x pid=%06x wwpn=%8phC
> comp_status=%x iop0=%x iop1=%x\n",
> > -	    type, sp->handle, fcport->d_id.b24, fcport->port_name,
> > -	    le16_to_cpu(logio->comp_status),
> > -	    le32_to_cpu(logio->io_parameter[0]),
> > -	    le32_to_cpu(logio->io_parameter[1]));
> > +	ql_log(ql_log_warn, sp->vha, 0x5037,
> > +	       "Async-%s failed: handle=%x pid=%06x wwpn=%8phC
> comp_status=%x iop0=%x iop1=%x\n",
> > +	       type, sp->handle, fcport->d_id.b24, fcport->port_name,
> > +	       le16_to_cpu(logio->comp_status),
> > +	       le32_to_cpu(logio->io_parameter[0]),
> > +	       le32_to_cpu(logio->io_parameter[1]));
> >
> > logio_done:
> > 	sp->done(sp, 0);
> > @@ -2389,9 +2389,9 @@ static void
> qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
> >
> > 		tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
> > 		if (fd->transferred_length != tgt_xfer_len) {
> > -			ql_dbg(ql_dbg_io, fcport->vha, 0x3079,
> > -				"Dropped frame(s) detected
> (sent/rcvd=%u/%u).\n",
> > -				tgt_xfer_len, fd->transferred_length);
> > +			ql_log(ql_log_warn, fcport->vha, 0x3079,
> > +			       "Dropped frame(s) detected
> (sent/rcvd=%u/%u).\n",
> > +			       tgt_xfer_len, fd->transferred_length);
> > 			logit = 1;
> > 		} else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
> > 			/*
> > @@ -3112,9 +3112,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
> rsp_que *rsp, void *pkt)
> > 		scsi_set_resid(cp, resid);
> > 		if (scsi_status & SS_RESIDUAL_UNDER) {
> > 			if (IS_FWI2_CAPABLE(ha) && fw_resid_len !=
> resid_len) {
> > -				ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
> > -				    "Dropped frame(s) detected (0x%x of 0x%x
> bytes).\n",
> > -				    resid, scsi_bufflen(cp));
> > +				ql_log(ql_log_warn, fcport->vha, 0x301d,
> > +				       "Dropped frame(s) detected (0x%x of 0x%x
> bytes).\n",
> > +				       resid, scsi_bufflen(cp));
> >
> > 				vha->interface_err_cnt++;
> >
> > @@ -3139,9 +3139,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
> rsp_que *rsp, void *pkt)
> > 			 * task not completed.
> > 			 */
> >
> > -			ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
> > -			    "Dropped frame(s) detected (0x%x of 0x%x
> bytes).\n",
> > -			    resid, scsi_bufflen(cp));
> > +			ql_log(ql_log_warn, fcport->vha, 0x301f,
> > +			       "Dropped frame(s) detected (0x%x of 0x%x
> bytes).\n",
> > +			       resid, scsi_bufflen(cp));
> >
> > 			vha->interface_err_cnt++;
> >
> > @@ -3257,15 +3257,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha,
> struct rsp_que *rsp, void *pkt)
> >
> > out:
> > 	if (logit)
> > -		ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
> > -		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu
> "
> > -		    "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
> > -		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
> > -		    comp_status, scsi_status, res, vha->host_no,
> > -		    cp->device->id, cp->device->lun, fcport->d_id.b.domain,
> > -		    fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
> > -		    cp->cmnd, scsi_bufflen(cp), rsp_info_len,
> > -		    resid_len, fw_resid_len, sp, cp);
> > +		ql_log(ql_log_warn, fcport->vha, 0x3022,
> > +		       "FCP command status: 0x%x-0x%x (0x%x)
> nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x
> rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
> > +		       comp_status, scsi_status, res, vha->host_no,
> > +		       cp->device->id, cp->device->lun, fcport->d_id.b.domain,
> > +		       fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
> > +		       cp->cmnd, scsi_bufflen(cp), rsp_info_len,
> > +		       resid_len, fw_resid_len, sp, cp);
> >
> > 	if (rsp->status_srb == NULL)
> > 		sp->done(sp, res);
> > --
> > 2.19.0.rc0
> >
> 
> I like the direction of this patch.
> 
> Can you consider removing "logit" variable. Since logit was designed to print
> messages only when a specific debug (IO bits in this case) was set.
<SK> logit is set under certain IO error conditions not based on any debug. If logit is removed,
this print will be come for each and every IO. 

Thanks,
~Saurav
> 
> --
> Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [EXT] [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level
  2021-01-07  5:51     ` [EXT] " Saurav Kashyap
@ 2021-01-07 17:51       ` Himanshu Madhani
  2021-01-08  4:41         ` Saurav Kashyap
  0 siblings, 1 reply; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-07 17:51 UTC (permalink / raw)
  To: Saurav Kashyap
  Cc: Nilesh Javali, Martin K. Petersen, linux-scsi,
	GR-QLogic-Storage-Upstream



> On Jan 6, 2021, at 11:51 PM, Saurav Kashyap <skashyap@marvell.com> wrote:
> 
> Hi Himanshu,
> Thanks for the review, comments inline..
> 
>> -----Original Message-----
>> From: Himanshu Madhani <himanshu.madhani@oracle.com>
>> Sent: Wednesday, January 6, 2021 8:37 PM
>> To: Nilesh Javali <njavali@marvell.com>; Saurav Kashyap
>> <skashyap@marvell.com>
>> Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
>> scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
>> Upstream@marvell.com>
>> Subject: [EXT] Re: [PATCH v3 3/7] qla2xxx: Move some messages from debug to
>> normal log level
>> 
>> External Email
>> 
>> ----------------------------------------------------------------------
>> Hi Saurav,
>> 
>>> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
>>> 
>>> From: Saurav Kashyap <skashyap@marvell.com>
>>> 
>>> This change will aid in debugging issues where debug level is not set.
>>> 
>>> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
>>> Signed-off-by: Nilesh Javali <njavali@marvell.com>
>>> ---
>>> drivers/scsi/qla2xxx/qla_init.c | 10 +++----
>>> drivers/scsi/qla2xxx/qla_isr.c  | 52 ++++++++++++++++-----------------
>>> 2 files changed, 30 insertions(+), 32 deletions(-)
>>> 
>>> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
>>> index 410ff5534a59..221369cdf71f 100644
>>> --- a/drivers/scsi/qla2xxx/qla_init.c
>>> +++ b/drivers/scsi/qla2xxx/qla_init.c
>>> @@ -347,11 +347,11 @@ qla2x00_async_login(struct scsi_qla_host *vha,
>> fc_port_t *fcport,
>>> 	if (NVME_TARGET(vha->hw, fcport))
>>> 		lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
>>> 
>>> -	ql_dbg(ql_dbg_disc, vha, 0x2072,
>>> -	    "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
>>> -		"retries=%d.\n", fcport->port_name, sp->handle, fcport-
>>> loop_id,
>>> -	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
>>> -	    fcport->login_retry);
>>> +	ql_log(ql_log_warn, vha, 0x2072,
>>> +	       "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x
>> retries=%d.\n",
>>> +	       fcport->port_name, sp->handle, fcport->loop_id,
>>> +	       fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
>>> +	       fcport->login_retry);
>>> 
>>> 	rval = qla2x00_start_sp(sp);
>>> 	if (rval != QLA_SUCCESS) {
>>> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
>>> index 9cf8326ab9fc..bfc8bbaeea46 100644
>>> --- a/drivers/scsi/qla2xxx/qla_isr.c
>>> +++ b/drivers/scsi/qla2xxx/qla_isr.c
>>> @@ -1455,9 +1455,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct
>> rsp_que *rsp, uint16_t *mb)
>>> 		if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
>>> 			break;
>>> 
>>> -		ql_dbg(ql_dbg_async, vha, 0x5013,
>>> -		    "RSCN database changed -- %04x %04x %04x.\n",
>>> -		    mb[1], mb[2], mb[3]);
>>> +		ql_log(ql_log_warn, vha, 0x5013,
>>> +		       "RSCN database changed -- %04x %04x %04x.\n",
>>> +		       mb[1], mb[2], mb[3]);
>>> 
>>> 		rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
>>> 		host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area <<
>> 8)
>>> @@ -2221,12 +2221,12 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct
>> req_que *req,
>>> 		break;
>>> 	}
>>> 
>>> -	ql_dbg(ql_dbg_async, sp->vha, 0x5037,
>>> -	    "Async-%s failed: handle=%x pid=%06x wwpn=%8phC
>> comp_status=%x iop0=%x iop1=%x\n",
>>> -	    type, sp->handle, fcport->d_id.b24, fcport->port_name,
>>> -	    le16_to_cpu(logio->comp_status),
>>> -	    le32_to_cpu(logio->io_parameter[0]),
>>> -	    le32_to_cpu(logio->io_parameter[1]));
>>> +	ql_log(ql_log_warn, sp->vha, 0x5037,
>>> +	       "Async-%s failed: handle=%x pid=%06x wwpn=%8phC
>> comp_status=%x iop0=%x iop1=%x\n",
>>> +	       type, sp->handle, fcport->d_id.b24, fcport->port_name,
>>> +	       le16_to_cpu(logio->comp_status),
>>> +	       le32_to_cpu(logio->io_parameter[0]),
>>> +	       le32_to_cpu(logio->io_parameter[1]));
>>> 
>>> logio_done:
>>> 	sp->done(sp, 0);
>>> @@ -2389,9 +2389,9 @@ static void
>> qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
>>> 
>>> 		tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
>>> 		if (fd->transferred_length != tgt_xfer_len) {
>>> -			ql_dbg(ql_dbg_io, fcport->vha, 0x3079,
>>> -				"Dropped frame(s) detected
>> (sent/rcvd=%u/%u).\n",
>>> -				tgt_xfer_len, fd->transferred_length);
>>> +			ql_log(ql_log_warn, fcport->vha, 0x3079,
>>> +			       "Dropped frame(s) detected
>> (sent/rcvd=%u/%u).\n",
>>> +			       tgt_xfer_len, fd->transferred_length);
>>> 			logit = 1;
>>> 		} else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
>>> 			/*
>>> @@ -3112,9 +3112,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
>> rsp_que *rsp, void *pkt)
>>> 		scsi_set_resid(cp, resid);
>>> 		if (scsi_status & SS_RESIDUAL_UNDER) {
>>> 			if (IS_FWI2_CAPABLE(ha) && fw_resid_len !=
>> resid_len) {
>>> -				ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
>>> -				    "Dropped frame(s) detected (0x%x of 0x%x
>> bytes).\n",
>>> -				    resid, scsi_bufflen(cp));
>>> +				ql_log(ql_log_warn, fcport->vha, 0x301d,
>>> +				       "Dropped frame(s) detected (0x%x of 0x%x
>> bytes).\n",
>>> +				       resid, scsi_bufflen(cp));
>>> 
>>> 				vha->interface_err_cnt++;
>>> 
>>> @@ -3139,9 +3139,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct
>> rsp_que *rsp, void *pkt)
>>> 			 * task not completed.
>>> 			 */
>>> 
>>> -			ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
>>> -			    "Dropped frame(s) detected (0x%x of 0x%x
>> bytes).\n",
>>> -			    resid, scsi_bufflen(cp));
>>> +			ql_log(ql_log_warn, fcport->vha, 0x301f,
>>> +			       "Dropped frame(s) detected (0x%x of 0x%x
>> bytes).\n",
>>> +			       resid, scsi_bufflen(cp));
>>> 
>>> 			vha->interface_err_cnt++;
>>> 
>>> @@ -3257,15 +3257,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha,
>> struct rsp_que *rsp, void *pkt)
>>> 
>>> out:
>>> 	if (logit)
>>> -		ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
>>> -		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu
>> "
>>> -		    "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
>>> -		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
>>> -		    comp_status, scsi_status, res, vha->host_no,
>>> -		    cp->device->id, cp->device->lun, fcport->d_id.b.domain,
>>> -		    fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
>>> -		    cp->cmnd, scsi_bufflen(cp), rsp_info_len,
>>> -		    resid_len, fw_resid_len, sp, cp);
>>> +		ql_log(ql_log_warn, fcport->vha, 0x3022,
>>> +		       "FCP command status: 0x%x-0x%x (0x%x)
>> nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x
>> rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
>>> +		       comp_status, scsi_status, res, vha->host_no,
>>> +		       cp->device->id, cp->device->lun, fcport->d_id.b.domain,
>>> +		       fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
>>> +		       cp->cmnd, scsi_bufflen(cp), rsp_info_len,
>>> +		       resid_len, fw_resid_len, sp, cp);
>>> 
>>> 	if (rsp->status_srb == NULL)
>>> 		sp->done(sp, res);
>>> --
>>> 2.19.0.rc0
>>> 
>> 
>> I like the direction of this patch.
>> 
>> Can you consider removing "logit" variable. Since logit was designed to print
>> messages only when a specific debug (IO bits in this case) was set.
> <SK> logit is set under certain IO error conditions not based on any debug. If logit is removed,
> this print will be come for each and every IO. 
> 

Yeah. I see that and so it was more of a suggestion while you are optimizing debugging effort without having to enable extended logging. if you can optimize logit logic while at it would be nice. I’ll leave it upto you. No objection to patch itself.

However, when you submit v2 of this patchset, I do want more descriptive commit message. Usually small things like this can escape scrutiny under “debug level change” description. 

> Thanks,
> ~Saurav
>> 
>> --
>> Himanshu Madhani	 Oracle Linux Engineering

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [EXT] [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port
  2021-01-07  5:34     ` [EXT] " Saurav Kashyap
@ 2021-01-07 17:57       ` Himanshu Madhani
  2021-01-08  4:37         ` Saurav Kashyap
  0 siblings, 1 reply; 21+ messages in thread
From: Himanshu Madhani @ 2021-01-07 17:57 UTC (permalink / raw)
  To: Saurav Kashyap
  Cc: Nilesh Javali, Martin K. Petersen, linux-scsi,
	GR-QLogic-Storage-Upstream



> On Jan 6, 2021, at 11:34 PM, Saurav Kashyap <skashyap@marvell.com> wrote:
> 
> <SK> It's a state of the port, it comes as part of managing the port. If the error count is more,
> user can opt to change the state and port will go to offline state.

In that case, small description in a commit message would have been very helpful. Its not Clear from the patch about user’s capability of changing state of port 

--
Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [EXT] [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port
  2021-01-07 17:57       ` [EXT] " Himanshu Madhani
@ 2021-01-08  4:37         ` Saurav Kashyap
  0 siblings, 0 replies; 21+ messages in thread
From: Saurav Kashyap @ 2021-01-08  4:37 UTC (permalink / raw)
  To: Himanshu Madhani
  Cc: Nilesh Javali, Martin K. Petersen, linux-scsi,
	GR-QLogic-Storage-Upstream

Hi Himanshu,

> -----Original Message-----
> From: Himanshu Madhani <himanshu.madhani@oracle.com>
> Sent: Thursday, January 7, 2021 11:27 PM
> To: Saurav Kashyap <skashyap@marvell.com>
> Cc: Nilesh Javali <njavali@marvell.com>; Martin K. Petersen
> <martin.petersen@oracle.com>; linux-scsi@vger.kernel.org; GR-QLogic-
> Storage-Upstream <GR-QLogic-Storage-Upstream@marvell.com>
> Subject: Re: [EXT] [PATCH v3 1/7] qla2xxx: Implementation to get and manage
> host, target stats and initiator port
> 
> 
> 
> > On Jan 6, 2021, at 11:34 PM, Saurav Kashyap <skashyap@marvell.com>
> wrote:
> >
> > <SK> It's a state of the port, it comes as part of managing the port. If the
> error count is more,
> > user can opt to change the state and port will go to offline state.
> 
> In that case, small description in a commit message would have been very
> helpful. Its not Clear from the patch about user’s capability of changing state of
> port
> 
Sure.

Thanks,
~Saurav
> --
> Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

* RE: [EXT] [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level
  2021-01-07 17:51       ` [EXT] " Himanshu Madhani
@ 2021-01-08  4:41         ` Saurav Kashyap
  0 siblings, 0 replies; 21+ messages in thread
From: Saurav Kashyap @ 2021-01-08  4:41 UTC (permalink / raw)
  To: Himanshu Madhani
  Cc: Nilesh Javali, Martin K. Petersen, linux-scsi,
	GR-QLogic-Storage-Upstream

Hi Himanshu,

> -----Original Message-----
> From: Himanshu Madhani <himanshu.madhani@oracle.com>
> Sent: Thursday, January 7, 2021 11:22 PM
> To: Saurav Kashyap <skashyap@marvell.com>
> Cc: Nilesh Javali <njavali@marvell.com>; Martin K. Petersen
> <martin.petersen@oracle.com>; linux-scsi@vger.kernel.org; GR-QLogic-
> Storage-Upstream <GR-QLogic-Storage-Upstream@marvell.com>
> Subject: Re: [EXT] [PATCH v3 3/7] qla2xxx: Move some messages from debug to
> normal log level
> 
> 
> 
> > On Jan 6, 2021, at 11:51 PM, Saurav Kashyap <skashyap@marvell.com>
> wrote:
> >
> > Hi Himanshu,
> > Thanks for the review, comments inline..
> >
> >> -----Original Message-----
> >> From: Himanshu Madhani <himanshu.madhani@oracle.com>
> >> Sent: Wednesday, January 6, 2021 8:37 PM
> >> To: Nilesh Javali <njavali@marvell.com>; Saurav Kashyap
> >> <skashyap@marvell.com>
> >> Cc: Martin K. Petersen <martin.petersen@oracle.com>; linux-
> >> scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-Storage-
> >> Upstream@marvell.com>
> >> Subject: [EXT] Re: [PATCH v3 3/7] qla2xxx: Move some messages from
> debug to
> >> normal log level
> >>
> >> External Email
> >>
> >> ----------------------------------------------------------------------
> >> Hi Saurav,
> >>
> >>> On Jan 5, 2021, at 4:38 AM, Nilesh Javali <njavali@marvell.com> wrote:
> >>>
> >>> From: Saurav Kashyap <skashyap@marvell.com>
> >>>
> >>> This change will aid in debugging issues where debug level is not set.
> >>>
> >>> Signed-off-by: Saurav Kashyap <skashyap@marvell.com>
> >>> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> >>> ---
> >>> drivers/scsi/qla2xxx/qla_init.c | 10 +++----
> >>> drivers/scsi/qla2xxx/qla_isr.c  | 52 ++++++++++++++++-----------------
> >>> 2 files changed, 30 insertions(+), 32 deletions(-)
> >>>
> >>> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> >>> index 410ff5534a59..221369cdf71f 100644
> >>> --- a/drivers/scsi/qla2xxx/qla_init.c
> >>> +++ b/drivers/scsi/qla2xxx/qla_init.c
> >>> @@ -347,11 +347,11 @@ qla2x00_async_login(struct scsi_qla_host *vha,
> >> fc_port_t *fcport,
> >>> 	if (NVME_TARGET(vha->hw, fcport))
> >>> 		lio->u.logio.flags |= SRB_LOGIN_SKIP_PRLI;
> >>>
> >>> -	ql_dbg(ql_dbg_disc, vha, 0x2072,
> >>> -	    "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x "
> >>> -		"retries=%d.\n", fcport->port_name, sp->handle, fcport-
> >>> loop_id,
> >>> -	    fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
> >>> -	    fcport->login_retry);
> >>> +	ql_log(ql_log_warn, vha, 0x2072,
> >>> +	       "Async-login - %8phC hdl=%x, loopid=%x portid=%02x%02x%02x
> >> retries=%d.\n",
> >>> +	       fcport->port_name, sp->handle, fcport->loop_id,
> >>> +	       fcport->d_id.b.domain, fcport->d_id.b.area, fcport->d_id.b.al_pa,
> >>> +	       fcport->login_retry);
> >>>
> >>> 	rval = qla2x00_start_sp(sp);
> >>> 	if (rval != QLA_SUCCESS) {
> >>> diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
> >>> index 9cf8326ab9fc..bfc8bbaeea46 100644
> >>> --- a/drivers/scsi/qla2xxx/qla_isr.c
> >>> +++ b/drivers/scsi/qla2xxx/qla_isr.c
> >>> @@ -1455,9 +1455,9 @@ qla2x00_async_event(scsi_qla_host_t *vha,
> struct
> >> rsp_que *rsp, uint16_t *mb)
> >>> 		if (ha->flags.npiv_supported && vha->vp_idx != (mb[3] & 0xff))
> >>> 			break;
> >>>
> >>> -		ql_dbg(ql_dbg_async, vha, 0x5013,
> >>> -		    "RSCN database changed -- %04x %04x %04x.\n",
> >>> -		    mb[1], mb[2], mb[3]);
> >>> +		ql_log(ql_log_warn, vha, 0x5013,
> >>> +		       "RSCN database changed -- %04x %04x %04x.\n",
> >>> +		       mb[1], mb[2], mb[3]);
> >>>
> >>> 		rscn_entry = ((mb[1] & 0xff) << 16) | mb[2];
> >>> 		host_pid = (vha->d_id.b.domain << 16) | (vha->d_id.b.area <<
> >> 8)
> >>> @@ -2221,12 +2221,12 @@ qla24xx_logio_entry(scsi_qla_host_t *vha,
> struct
> >> req_que *req,
> >>> 		break;
> >>> 	}
> >>>
> >>> -	ql_dbg(ql_dbg_async, sp->vha, 0x5037,
> >>> -	    "Async-%s failed: handle=%x pid=%06x wwpn=%8phC
> >> comp_status=%x iop0=%x iop1=%x\n",
> >>> -	    type, sp->handle, fcport->d_id.b24, fcport->port_name,
> >>> -	    le16_to_cpu(logio->comp_status),
> >>> -	    le32_to_cpu(logio->io_parameter[0]),
> >>> -	    le32_to_cpu(logio->io_parameter[1]));
> >>> +	ql_log(ql_log_warn, sp->vha, 0x5037,
> >>> +	       "Async-%s failed: handle=%x pid=%06x wwpn=%8phC
> >> comp_status=%x iop0=%x iop1=%x\n",
> >>> +	       type, sp->handle, fcport->d_id.b24, fcport->port_name,
> >>> +	       le16_to_cpu(logio->comp_status),
> >>> +	       le32_to_cpu(logio->io_parameter[0]),
> >>> +	       le32_to_cpu(logio->io_parameter[1]));
> >>>
> >>> logio_done:
> >>> 	sp->done(sp, 0);
> >>> @@ -2389,9 +2389,9 @@ static void
> >> qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req,
> >>>
> >>> 		tgt_xfer_len = be32_to_cpu(rsp_iu->xfrd_len);
> >>> 		if (fd->transferred_length != tgt_xfer_len) {
> >>> -			ql_dbg(ql_dbg_io, fcport->vha, 0x3079,
> >>> -				"Dropped frame(s) detected
> >> (sent/rcvd=%u/%u).\n",
> >>> -				tgt_xfer_len, fd->transferred_length);
> >>> +			ql_log(ql_log_warn, fcport->vha, 0x3079,
> >>> +			       "Dropped frame(s) detected
> >> (sent/rcvd=%u/%u).\n",
> >>> +			       tgt_xfer_len, fd->transferred_length);
> >>> 			logit = 1;
> >>> 		} else if (le16_to_cpu(comp_status) == CS_DATA_UNDERRUN) {
> >>> 			/*
> >>> @@ -3112,9 +3112,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha,
> struct
> >> rsp_que *rsp, void *pkt)
> >>> 		scsi_set_resid(cp, resid);
> >>> 		if (scsi_status & SS_RESIDUAL_UNDER) {
> >>> 			if (IS_FWI2_CAPABLE(ha) && fw_resid_len !=
> >> resid_len) {
> >>> -				ql_dbg(ql_dbg_io, fcport->vha, 0x301d,
> >>> -				    "Dropped frame(s) detected (0x%x of 0x%x
> >> bytes).\n",
> >>> -				    resid, scsi_bufflen(cp));
> >>> +				ql_log(ql_log_warn, fcport->vha, 0x301d,
> >>> +				       "Dropped frame(s) detected (0x%x of 0x%x
> >> bytes).\n",
> >>> +				       resid, scsi_bufflen(cp));
> >>>
> >>> 				vha->interface_err_cnt++;
> >>>
> >>> @@ -3139,9 +3139,9 @@ qla2x00_status_entry(scsi_qla_host_t *vha,
> struct
> >> rsp_que *rsp, void *pkt)
> >>> 			 * task not completed.
> >>> 			 */
> >>>
> >>> -			ql_dbg(ql_dbg_io, fcport->vha, 0x301f,
> >>> -			    "Dropped frame(s) detected (0x%x of 0x%x
> >> bytes).\n",
> >>> -			    resid, scsi_bufflen(cp));
> >>> +			ql_log(ql_log_warn, fcport->vha, 0x301f,
> >>> +			       "Dropped frame(s) detected (0x%x of 0x%x
> >> bytes).\n",
> >>> +			       resid, scsi_bufflen(cp));
> >>>
> >>> 			vha->interface_err_cnt++;
> >>>
> >>> @@ -3257,15 +3257,13 @@ qla2x00_status_entry(scsi_qla_host_t *vha,
> >> struct rsp_que *rsp, void *pkt)
> >>>
> >>> out:
> >>> 	if (logit)
> >>> -		ql_dbg(ql_dbg_io, fcport->vha, 0x3022,
> >>> -		    "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu
> >> "
> >>> -		    "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x "
> >>> -		    "rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
> >>> -		    comp_status, scsi_status, res, vha->host_no,
> >>> -		    cp->device->id, cp->device->lun, fcport->d_id.b.domain,
> >>> -		    fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
> >>> -		    cp->cmnd, scsi_bufflen(cp), rsp_info_len,
> >>> -		    resid_len, fw_resid_len, sp, cp);
> >>> +		ql_log(ql_log_warn, fcport->vha, 0x3022,
> >>> +		       "FCP command status: 0x%x-0x%x (0x%x)
> >> nexus=%ld:%d:%llu portid=%02x%02x%02x oxid=0x%x cdb=%10phN
> len=0x%x
> >> rsp_info=0x%x resid=0x%x fw_resid=0x%x sp=%p cp=%p.\n",
> >>> +		       comp_status, scsi_status, res, vha->host_no,
> >>> +		       cp->device->id, cp->device->lun, fcport->d_id.b.domain,
> >>> +		       fcport->d_id.b.area, fcport->d_id.b.al_pa, ox_id,
> >>> +		       cp->cmnd, scsi_bufflen(cp), rsp_info_len,
> >>> +		       resid_len, fw_resid_len, sp, cp);
> >>>
> >>> 	if (rsp->status_srb == NULL)
> >>> 		sp->done(sp, res);
> >>> --
> >>> 2.19.0.rc0
> >>>
> >>
> >> I like the direction of this patch.
> >>
> >> Can you consider removing "logit" variable. Since logit was designed to print
> >> messages only when a specific debug (IO bits in this case) was set.
> > <SK> logit is set under certain IO error conditions not based on any debug. If
> logit is removed,
> > this print will be come for each and every IO.
> >
> 
> Yeah. I see that and so it was more of a suggestion while you are optimizing
> debugging effort without having to enable extended logging. if you can
> optimize logit logic while at it would be nice. I’ll leave it upto you. No objection
> to patch itself.
I will look into it, I am not going to changes this patch and series. 
If I end up in making changes then it will be new patch.

> 
> However, when you submit v2 of this patchset, I do want more descriptive
> commit message. Usually small things like this can escape scrutiny under
> “debug level change” description.
Sure.

Thanks,
~Saurav
> 
> > Thanks,
> > ~Saurav
> >>
> >> --
> >> Himanshu Madhani	 Oracle Linux Engineering
> 
> --
> Himanshu Madhani	 Oracle Linux Engineering


^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2021-01-08  4:41 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-05 10:38 [PATCH v3 0/7] qla2xxx driver enhancements Nilesh Javali
2021-01-05 10:38 ` [PATCH v3 1/7] qla2xxx: Implementation to get and manage host, target stats and initiator port Nilesh Javali
2021-01-06 15:05   ` Himanshu Madhani
2021-01-07  5:34     ` [EXT] " Saurav Kashyap
2021-01-07 17:57       ` [EXT] " Himanshu Madhani
2021-01-08  4:37         ` Saurav Kashyap
2021-01-05 10:38 ` [PATCH v3 2/7] qla2xxx: Add error counters to debugfs node Nilesh Javali
2021-01-06 15:06   ` Himanshu Madhani
2021-01-05 10:38 ` [PATCH v3 3/7] qla2xxx: Move some messages from debug to normal log level Nilesh Javali
2021-01-06 15:06   ` Himanshu Madhani
2021-01-07  5:51     ` [EXT] " Saurav Kashyap
2021-01-07 17:51       ` [EXT] " Himanshu Madhani
2021-01-08  4:41         ` Saurav Kashyap
2021-01-05 10:38 ` [PATCH v3 4/7] qla2xxx: Wait for ABTS response on I/O timeouts for NVMe Nilesh Javali
2021-01-06 15:36   ` Himanshu Madhani
2021-01-05 10:38 ` [PATCH v3 5/7] qla2xxx: Fix mailbox Ch erroneous error Nilesh Javali
2021-01-06 15:37   ` Himanshu Madhani
2021-01-05 10:38 ` [PATCH v3 6/7] qla2xxx: Enable NVME CONF (BIT_7) when enabling SLER Nilesh Javali
2021-01-06 15:37   ` Himanshu Madhani
2021-01-05 10:38 ` [PATCH v3 7/7] qla2xxx: Update version to 10.02.00.105-k Nilesh Javali
2021-01-06 15:38   ` Himanshu Madhani

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.