mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Karan Tilak Kumar <kartilak@cisco.com>
To: sebaddel@cisco.com
Cc: arulponn@cisco.com, djhawar@cisco.com, gcboffa@cisco.com,
	mkai2@cisco.com, satishkh@cisco.com, aeasi@cisco.com,
	jejb@linux.ibm.com, martin.petersen@oracle.com,
	linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org,
	jmeneghi@redhat.com, revers@redhat.com, adakopou@redhat.com,
	lduncan@suse.com, Karan Tilak Kumar <kartilak@cisco.com>,
	kernel test robot <lkp@intel.com>,
	Hannes Reinecke <hare@kernel.org>
Subject: [PATCH v5 11/13] scsi: fnic: Track NVMe transport statistics
Date: Tue, 23 Jun 2026 21:43:32 -0700	[thread overview]
Message-ID: <20260624044334.3079-12-kartilak@cisco.com> (raw)
In-Reply-To: <20260624044334.3079-1-kartilak@cisco.com>

Add counters for NVMe requests, responses, LS handling, aborts, and
wait-queue activity.

Update NVMe I/O, completion, LS response, LS abort, and abort paths to
maintain the new counters.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202605280619.pmobiDWp-lkp@intel.com/
Closes: https://lore.kernel.org/oe-kbuild-all/202605280519.Jd4fmgAZ-lkp@intel.com/
Reviewed-by: Sesidhar Baddela <sebaddel@cisco.com>
Reviewed-by: Arulprabhu Ponnusamy <arulponn@cisco.com>
Reviewed-by: Gian Carlo Boffa <gcboffa@cisco.com>
Reviewed-by: Arun Easi <aeasi@cisco.com>
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Reviewed-by: Lee Duncan <lduncan@suse.com>
Signed-off-by: Karan Tilak Kumar <kartilak@cisco.com>
Co-developed-by: Hannes Reinecke <hare@kernel.org>

---
Incorporate review comments from Lee Duncan:
        Convert the NVMe opcode stats helper to a switch statement.
        Share NVMe completion stats accounting and compute duration
        once.

Changes between v2 and v3:
Fix issues reported by kernel bot.

Changes between v3 and v4:
Incorporate review comments from Sashiko:
	Decrement NVMe completion wait queue counter when draining completions
	Preserve jiffies wrap when computing NVMe abort stats
---
 drivers/scsi/fnic/fnic_nvme.c  | 188 ++++++++++++++++++++++++++++++++-
 drivers/scsi/fnic/fnic_stats.h |  21 ++++
 2 files changed, 207 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/fnic/fnic_nvme.c b/drivers/scsi/fnic/fnic_nvme.c
index c4de6606c0b2..e322dd4dcb78 100644
--- a/drivers/scsi/fnic/fnic_nvme.c
+++ b/drivers/scsi/fnic/fnic_nvme.c
@@ -71,6 +71,61 @@ static void nvfnic_update_io_bytes(struct fnic *fnic,
 		fnic->fcp_output_bytes += io_req->fcp_req->transferred_length;
 }
 
+static void nvfnic_update_io_stats(struct fnic *fnic, u8 opcode)
+{
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+
+	switch (opcode) {
+	case nvme_cmd_read:
+		atomic64_inc(&fnic_stats->nvme_stats.nvme_input_requests);
+		break;
+	case nvme_cmd_write:
+		atomic64_inc(&fnic_stats->nvme_stats.nvme_output_requests);
+		break;
+	default:
+		atomic64_inc(&fnic_stats->nvme_stats.nvme_control_requests);
+		break;
+	}
+}
+
+static void nvfnic_update_cmpl_stats(struct fnic *fnic,
+				     struct fnic_io_req *io_req)
+{
+	struct io_path_stats *io_stats = &fnic->fnic_stats.io_stats;
+	atomic64_t *duration_stat;
+	unsigned long io_duration_time;
+
+	atomic64_dec(&io_stats->active_ios);
+	if (atomic64_read(&fnic->io_cmpl_skip))
+		atomic64_dec(&fnic->io_cmpl_skip);
+	else
+		atomic64_inc(&io_stats->io_completions);
+
+	io_duration_time = jiffies_to_msecs(jiffies - io_req->start_time);
+
+	if (io_duration_time <= 10)
+		duration_stat = &io_stats->io_btw_0_to_10_msec;
+	else if (io_duration_time <= 100)
+		duration_stat = &io_stats->io_btw_10_to_100_msec;
+	else if (io_duration_time <= 500)
+		duration_stat = &io_stats->io_btw_100_to_500_msec;
+	else if (io_duration_time <= 5000)
+		duration_stat = &io_stats->io_btw_500_to_5000_msec;
+	else if (io_duration_time <= 10000)
+		duration_stat = &io_stats->io_btw_5000_to_10000_msec;
+	else if (io_duration_time <= 30000)
+		duration_stat = &io_stats->io_btw_10000_to_30000_msec;
+	else {
+		duration_stat = &io_stats->io_greater_than_30000_msec;
+		if (io_duration_time >
+		    atomic64_read(&io_stats->current_max_io_time))
+			atomic64_set(&io_stats->current_max_io_time,
+				     io_duration_time);
+	}
+
+	atomic64_inc(duration_stat);
+}
+
 int
 nvfnic_alloc_fcpio_tag(struct fnic_iport_s *iport, struct fnic_io_req *io_req)
 {
@@ -141,6 +196,7 @@ inline int nvfnic_queue_wq_nvme_copy_desc(struct fnic *fnic,
 	struct scatterlist *sg;
 	struct fnic_tport_s *tport = io_req->tport;
 	struct host_sg_desc *desc;
+	struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
 	unsigned int i;
 	unsigned long intr_flags;
 	int flags;
@@ -177,6 +233,7 @@ inline int nvfnic_queue_wq_nvme_copy_desc(struct fnic *fnic,
 		spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], intr_flags);
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 			    "Enqueue failure: No descriptors\n");
+		atomic64_inc(&misc_stats->io_cpwq_alloc_failures);
 		return -EBUSY;
 	}
 
@@ -198,6 +255,11 @@ inline int nvfnic_queue_wq_nvme_copy_desc(struct fnic *fnic,
 					tport->max_payload_size, tport->r_a_tov,
 					tport->e_d_tov);
 
+	atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs);
+	if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) >
+	    atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs))
+		atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs,
+		     atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs));
 
 	spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], intr_flags);
 	return 0;
@@ -207,20 +269,24 @@ bool
 nvfnic_transport_ready(struct fnic_iport_s *iport, struct fnic_tport_s *tport)
 {
 	struct fnic *fnic = iport->fnic;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 
 	if (tport == NULL)
 		return false;
 
 	if (fdls_get_state(&iport->fabric) == FDLS_STATE_LINKDOWN ||
 	    iport->state != FNIC_IPORT_STATE_READY) {
+		atomic64_inc(&fnic_stats->misc_stats.iport_not_ready);
 		return false;
 	}
 
 	if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
 		return false;
 
-	if (fdls_tport_is_offline(tport))
+	if (fdls_tport_is_offline(tport)) {
+		atomic64_inc(&fnic_stats->misc_stats.tport_not_ready);
 		return false;
+	}
 
 	return true;
 }
@@ -230,11 +296,14 @@ int nvfnic_queuecommand(struct fnic_io_req *io_req)
 	struct fnic_iport_s *iport = io_req->iport;
 	struct fnic *fnic = iport->fnic;
 	struct fnic_tport_s *tport = io_req->tport;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+	struct vnic_wq_copy *wq = io_req->wq;
 	int ret = 0;
 	int sg_count = 0;
 	unsigned long ptr;
 	unsigned char *lba;
 	u64 cmd_trace;
+	int idx;
 	struct nvme_fc_cmd_iu *cmdiu = io_req->fcp_req->cmdaddr;
 
 	io_req->cmd_state = FNIC_IOREQ_NOT_INITED;
@@ -261,6 +330,7 @@ int nvfnic_queuecommand(struct fnic_io_req *io_req)
 		    mempool_alloc(fnic->io_sgl_pool[io_req->sgl_type],
 				  GFP_ATOMIC);
 		if (!io_req->sgl_list) {
+			atomic64_inc(&fnic_stats->io_stats.alloc_failures);
 			FNIC_NVME_DBG(KERN_INFO, fnic,
 				      "Unable to alloc SGLs\n");
 			ret = -ENOMEM;
@@ -283,6 +353,8 @@ int nvfnic_queuecommand(struct fnic_io_req *io_req)
 	io_req->cmd_flags = FNIC_IO_INITIALIZED;
 
 	/* create copy wq desc and enqueue it */
+	idx = wq - &fnic->hw_copy_wq[0];
+	atomic64_inc(&fnic_stats->io_stats.ios[idx]);
 	ret = nvfnic_queue_wq_nvme_copy_desc(fnic, io_req->wq, io_req, sg_count);
 	if (ret) {
 		FNIC_NVME_DBG(KERN_ERR, fnic, "Unable to queue frame\n");
@@ -296,6 +368,13 @@ int nvfnic_queuecommand(struct fnic_io_req *io_req)
 			   (((u64)io_req->cmd_flags << 32) | io_req->cmd_state));
 		return ret;
 	}
+
+	atomic64_inc(&fnic_stats->io_stats.active_ios);
+	atomic64_inc(&fnic_stats->io_stats.num_ios);
+	if (atomic64_read(&fnic_stats->io_stats.active_ios) >
+	    atomic64_read(&fnic_stats->io_stats.max_active_ios))
+		atomic64_set(&fnic_stats->io_stats.max_active_ios,
+		     atomic64_read(&fnic_stats->io_stats.active_ios));
 	io_req->cmd_flags |= FNIC_IO_ISSUED;
  out:
 	lba = (char *)&cmdiu->sqe.rw.slba;
@@ -322,11 +401,14 @@ int nvfnic_fcpio_send(struct nvme_fc_local_port *lport,
 	struct fnic *fnic = iport->fnic;
 	unsigned long flags = 0;
 	struct fnic_tport_s *tport;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 
 	spin_lock_irqsave(&fnic->fnic_lock, flags);
 
 	tport = (struct fnic_tport_s *)rport->private;
+	atomic64_inc(&fnic_stats->io_stats.nvme_io_reqs_rcvd);
 	if (!nvfnic_transport_ready(iport, tport)) {
+		atomic64_inc(&fnic_stats->io_stats.nvme_io_rsps_sent);
 		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 		if (tport != NULL)
 			FNIC_NVME_DBG(KERN_INFO, fnic,
@@ -353,7 +435,9 @@ int nvfnic_fcpio_send(struct nvme_fc_local_port *lport,
 	if (io_req->tag == FNIC_NVME_NO_FREE_TAG) {
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 			    "No free tag available. Failing IO\n");
+		atomic64_inc(&fnic_stats->io_stats.alloc_failures);
 		atomic_dec(&fnic->in_flight);
+		atomic64_inc(&fnic_stats->io_stats.nvme_io_rsps_sent);
 		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 		return -EBUSY;
 	}
@@ -379,6 +463,7 @@ void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic,
 	struct fcpio_tag ftag;
 	u32 id;
 	struct fnic_io_req *io_req;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 	unsigned long start_time;
 	u64 cmd_trace;
 	char *lba;
@@ -403,6 +488,7 @@ void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic,
 
 	WARN_ON_ONCE(!io_req);
 	if (!io_req) {
+		atomic64_inc(&fnic_stats->io_stats.ioreq_null);
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 			      "IO req null hdr: %s tag: 0x%x desc: 0x%p\n",
 			      fnic_fcpio_status_to_str(hdr_status), id, desc);
@@ -471,6 +557,7 @@ void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic,
 	}
 
 	if (hdr_status != FCPIO_SUCCESS) {
+		atomic64_inc(&fnic_stats->io_stats.io_failures);
 		FNIC_NVME_DBG(KERN_INFO, fnic, "hdr status: %s\n",
 			    fnic_fcpio_status_to_str(hdr_status));
 	}
@@ -491,7 +578,9 @@ void nvfnic_fcpio_nvme_fast_cmpl_handler(struct fnic *fnic,
 		   (((u64) io_req->cmd_flags << 32) |
 		    io_req->cmd_state));
 
+	nvfnic_update_io_stats(fnic, cmdiu->sqe.rw.opcode);
 	nvfnic_update_io_bytes(fnic, io_req, cmdiu->sqe.rw.opcode);
+	nvfnic_update_cmpl_stats(fnic, io_req);
 
 	nvfnic_release_nvme_ioreq_buf(iport, io_req);
 	if (io_req->done)
@@ -509,6 +598,7 @@ void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
 	u32 id;
 	struct fcpio_nvme_cmpl *nvme_cmpl;
 	struct fnic_io_req *io_req;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 	unsigned long start_time;
 	uint32_t rsplen;
 	struct nvme_fc_ersp_iu *ersp;
@@ -539,6 +629,7 @@ void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
 
 	io_req = nvfnic_find_io_req_by_tag(fnic, tag);
 	if (!io_req) {
+		atomic64_inc(&fnic_stats->io_stats.ioreq_null);
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 			    "IOREQ is null hdr status: %s tag: 0x%x desc: %p\n",
 			    fnic_fcpio_status_to_str(hdr_status), tag, desc);
@@ -631,6 +722,7 @@ void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
 			}
 			memcpy(io_req->fcp_req->rspaddr, ersp, rsplen);
 		}
+		atomic64_inc(&fnic_stats->nvme_stats.nvme_ersps);
 		io_req->fcp_req->rcv_rsplen = rsplen;
 		break;
 
@@ -642,6 +734,7 @@ void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
 	}
 
 	if (hdr_status != FCPIO_SUCCESS) {
+		atomic64_inc(&fnic_stats->io_stats.io_failures);
 		FNIC_NVME_DBG(KERN_ERR, fnic, "hdr status: %s tag: 0x%x\n",
 			    fnic_fcpio_status_to_str(hdr_status), tag);
 	}
@@ -664,7 +757,9 @@ void nvfnic_fcpio_ersp_cmpl_handler(struct fnic *fnic,
 		   (((u64) io_req->cmd_flags << 32) |
 		    io_req->cmd_state));
 
+	nvfnic_update_io_stats(fnic, cmdiu->sqe.rw.opcode);
 	nvfnic_update_io_bytes(fnic, io_req, cmdiu->sqe.rw.opcode);
+	nvfnic_update_cmpl_stats(fnic, io_req);
 
 	nvfnic_release_nvme_ioreq_buf(iport, io_req);
 
@@ -685,6 +780,10 @@ void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
 	unsigned int tag;
 	struct fnic_io_req *io_req;
 	struct nvme_fc_cmd_iu *cmd_iu;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+	struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats;
+	struct terminate_stats *term_stats = &fnic->fnic_stats.term_stats;
+	struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
 	struct fnic_iport_s *iport;
 
 	fcpio_header_dec(&desc->hdr, &type, &hdr_status, &ftag);
@@ -702,6 +801,7 @@ void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
 	io_req = nvfnic_find_io_req_by_tag(fnic, tag);
 	WARN_ON_ONCE(!io_req);
 	if (!io_req) {
+		atomic64_inc(&fnic_stats->io_stats.ioreq_null);
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 			      "IOREQ null hdr:%s tag:0x%x desc:%p\n",
 			      fnic_fcpio_status_to_str(hdr_status), tag, desc);
@@ -730,6 +830,10 @@ void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 				"Abort timeout received tag: 0x%x id: 0x%x\n",
 			      tag, id);
+		if (io_req->cmd_flags & FNIC_IO_ABTS_ISSUED)
+			atomic64_inc(&abts_stats->abort_fw_timeouts);
+		else
+			atomic64_inc(&term_stats->terminate_fw_timeouts);
 		break;
 	case FCPIO_ITMF_REJECTED:
 		FNIC_NVME_DBG(KERN_ERR, fnic,
@@ -741,11 +845,19 @@ void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 			      "Abort IO not found tag:0x%x id:0x%x\n",
 			      tag, id);
+		if (io_req->cmd_flags & FNIC_IO_ABTS_ISSUED)
+			atomic64_inc(&abts_stats->abort_io_not_found);
+		else
+			atomic64_inc(&term_stats->terminate_io_not_found);
 		break;
 	default:
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 				"Abort unknown received tag: 0x%x id: 0x%x\n",
 			    tag, id);
+		if (io_req->cmd_flags & FNIC_IO_ABTS_ISSUED)
+			atomic64_inc(&abts_stats->abort_failures);
+		else
+			atomic64_inc(&term_stats->terminate_failures);
 		break;
 	}
 
@@ -771,6 +883,8 @@ void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
 
 	io_req->cmd_flags |= FNIC_IO_ABT_TERM_DONE;
 
+	if (!(io_req->cmd_flags & (FNIC_IO_ABORTED | FNIC_IO_DONE)))
+		atomic64_inc(&misc_stats->no_icmnd_itmf_cmpls);
 
 	io_req->fcp_req->transferred_length = 0;
 	io_req->fcp_req->rcv_rsplen = 0;
@@ -779,6 +893,12 @@ void nvfnic_fcpio_nvme_itmf_cmpl_handler(struct fnic *fnic,
 	else
 		io_req->fcp_req->status = NVME_SC_INTERNAL;
 
+	atomic64_dec(&fnic_stats->io_stats.active_ios);
+	if (atomic64_read(&fnic->io_cmpl_skip))
+		atomic64_dec(&fnic->io_cmpl_skip);
+	else
+		atomic64_inc(&fnic_stats->io_stats.io_completions);
+
 	nvfnic_release_nvme_ioreq_buf(iport, io_req);
 	if (io_req->done)
 		io_req->done(io_req);
@@ -951,9 +1071,14 @@ bool _terminate_tport_ios(struct sbitmap *map, unsigned int tag,
 void nvfnic_terminate_tport_ios(struct fnic *fnic,
 				     struct fnic_tport_s *tport)
 {
+	struct abort_stats *abts_stats = &fnic->fnic_stats.abts_stats;
 
 	sbitmap_for_each_set(&fnic->nvfnic_tag_map, _terminate_tport_ios, tport);
 
+	FNIC_NVME_DBG(KERN_INFO, fnic,
+		      "tport: 0x%x aborted %lld in_flight %d\n",
+		      tport->fcid, atomic64_read(&abts_stats->aborts),
+		      atomic_read(&fnic->in_flight));
 }
 
 bool _cleanup_all_nvme_io(struct sbitmap *map, unsigned int tag,
@@ -1083,12 +1208,15 @@ nvfnic_find_ls_req(struct fnic_tport_s *tport, uint16_t oxid)
 void nvfnic_fcpio_cmpl(struct fnic_io_req *io_req)
 {
 	struct fnic *fnic = io_req->iport->fnic;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 
 	nvfnic_free_fcpio_tag(io_req->iport, io_req);
+	atomic64_inc(&fnic_stats->io_stats.nvme_ios_queued_for_rsp);
 	io_req->waitq_start_time = jiffies;
 
 	llist_add(&io_req->nvfnic_io_cmpl, &fnic->nvme_io_event_llist);
 	atomic_inc(&fnic->nvme_io_event_queued);
+	atomic64_inc(&fnic_stats->io_stats.nvme_num_ios_in_waitq);
 
 	queue_work(fnic_cmpl_queue, &fnic->nvme_io_cmpl_work);
 }
@@ -1103,6 +1231,7 @@ void nvfnic_process_ls_abts_rsp(struct fnic_iport_s *iport,
 	uint8_t *fcid;
 	uint16_t oxid = FNIC_STD_GET_OX_ID(fchdr);
 	struct fnic *fnic = iport->fnic;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 
 	fcid = FNIC_STD_GET_S_ID(fchdr);
 	tport_fcid = ntoh24(fcid);
@@ -1130,8 +1259,12 @@ void nvfnic_process_ls_abts_rsp(struct fnic_iport_s *iport,
 		return;
 	}
 
+	atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_abort_responses);
 	nvfnic_ls_req->state = FNIC_LS_REQ_ABTS_COMPLETE;
 
+	FNIC_NVME_DBG(KERN_DEBUG, fnic, "nvme_ls_requests: %lld\n",
+		      (u64) atomic64_read(&fnic_stats->nvme_stats.nvme_ls_requests));
+
 	list_del(&nvfnic_ls_req->list);
 	fdls_free_oxid(iport, oxid, &nvfnic_ls_req->oxid);
 	lsreq->private = NULL;
@@ -1166,6 +1299,7 @@ void nvfnic_ls_rsp_recv(struct fnic_iport_s *iport,
 		      sizeof(fchdr->fh_s_id);
 	int status = 0;
 	struct fnic *fnic = iport->fnic;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 
 	if (len < (int)sizeof(*fchdr)) {
 		if (len >= sid_len) {
@@ -1231,6 +1365,7 @@ void nvfnic_ls_rsp_recv(struct fnic_iport_s *iport,
 	}
 
 	nvfnic_ls_req->state = FNIC_LS_REQ_CMD_COMPLETE;
+	atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_responses);
 
 	list_del_init(&nvfnic_ls_req->list);
 	lsreq->private = NULL;
@@ -1277,6 +1412,7 @@ void nvfnic_ls_req_timeout(struct timer_list *t)
 	struct nvmefc_ls_req *ls_req = nvfnic_ls_req->ls_req;
 	struct fnic_iport_s *iport = &fnic->iport;
 	struct fnic_tport_s *tport = (struct fnic_tport_s *) nvfnic_ls_req->tport;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 	uint16_t oxid = nvfnic_ls_req->oxid;
 	int timeout;
 
@@ -1311,6 +1447,7 @@ void nvfnic_ls_req_timeout(struct timer_list *t)
 			      "tport: 0x%x lsreq: 0x%x sending abort\n",
 			      tport->fcid, nvfnic_ls_req->oxid);
 		nvfnic_ls_req->state = FNIC_LS_REQ_CMD_ABTS_PENDING;
+		atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_aborts);
 		spin_unlock_irqrestore(&fnic->fnic_lock, fnic->lock_flags);
 
 		if (fdls_send_ls_req_abts(iport, tport, nvfnic_ls_req->oxid) == 0) {
@@ -1363,6 +1500,7 @@ int nvfnic_ls_req_send(struct nvme_fc_local_port *lport,
 	uint8_t *ls_req_payload;
 	struct fnic *fnic = iport->fnic;
 	struct fc_frame_header *fchdr;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 	struct nvfnic_ls_req *nvfnic_ls_req = ls_req->private;
 	uint16_t frame_size = FNIC_ETH_FCOE_HDRS_OFFSET +
 			sizeof(struct fc_frame_header) + ls_req->rqstlen;
@@ -1405,6 +1543,7 @@ int nvfnic_ls_req_send(struct nvme_fc_local_port *lport,
 		return -EAGAIN;
 	}
 
+	atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_requests);
 	timer_setup(&nvfnic_ls_req->ls_req_timer, nvfnic_ls_req_timeout,
 		     0UL);
 
@@ -1437,6 +1576,11 @@ int nvfnic_ls_req_send(struct nvme_fc_local_port *lport,
 		 iport->fcid, nvfnic_ls_req->oxid, *((uint8_t *) ls_req->rqstaddr),
 		 ls_req->rqstlen);
 
+	FNIC_NVME_DBG(KERN_INFO, fnic,
+		 "0x%x: ls_reqs count: %lld",
+		 iport->fcid,
+		 (u64) atomic64_read(&fnic_stats->nvme_stats.nvme_ls_requests));
+
 	list_add_tail(&nvfnic_ls_req->list, &tport->ls_req_list);
 	nvfnic_ls_req->state = FNIC_LS_REQ_CMD_PENDING;
 
@@ -1559,6 +1703,7 @@ void nvfnic_ls_req_abort(struct nvme_fc_local_port *lport,
 	struct fnic *fnic = iport->fnic;
 	struct fnic_tport_s *tport;
 	struct nvfnic_ls_req *nvfnic_ls_req;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
 	uint16_t oxid;
 	int timeout;
 	int ret;
@@ -1620,6 +1765,7 @@ void nvfnic_ls_req_abort(struct nvme_fc_local_port *lport,
 
 	/* Mark the state and flags */
 	nvfnic_ls_req->state = FNIC_LS_REQ_CMD_ABTS_PENDING;
+	atomic64_inc(&fnic_stats->nvme_stats.nvme_ls_aborts);
 	oxid = nvfnic_ls_req->oxid;
 
 	ret = fdls_send_ls_req_abts(iport, tport, oxid);
@@ -1645,6 +1791,7 @@ bool nvfnic_queue_abort_io_req(struct fnic *fnic, int tag,
 {
 	int idx;
 	unsigned long flags;
+	struct misc_stats *misc_stats = &fnic->fnic_stats.misc_stats;
 
 	idx = io_req->wq - &fnic->hw_copy_wq[0];
 
@@ -1660,12 +1807,18 @@ bool nvfnic_queue_abort_io_req(struct fnic *fnic, int tag,
 		atomic_dec(&fnic->in_flight);
 		FNIC_NVME_DBG(KERN_ERR, fnic,
 				"tag 0x%x failure: no descriptors\n", tag);
+		atomic64_inc(&misc_stats->abts_cpwq_alloc_failures);
 		return false;
 	}
 	fnic_queue_wq_copy_desc_itmf(io_req->wq, tag | FNIC_TAG_ABORT,
 				     0, task_req, tag, NULL, io_req->port_id,
 				     fnic->config.ra_tov, fnic->config.ed_tov);
 
+	atomic64_inc(&fnic->fnic_stats.fw_stats.active_fw_reqs);
+	if (atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs) >
+	    atomic64_read(&fnic->fnic_stats.fw_stats.max_fw_reqs))
+		atomic64_set(&fnic->fnic_stats.fw_stats.max_fw_reqs,
+			     atomic64_read(&fnic->fnic_stats.fw_stats.active_fw_reqs));
 
 	spin_unlock_irqrestore(&fnic->wq_copy_lock[idx], flags);
 	atomic_dec(&fnic->in_flight);
@@ -1682,9 +1835,13 @@ void nvfnic_fcpio_abort(struct nvme_fc_local_port *lport,
 	struct nvme_fc_cmd_iu *cmd_iu = fcp_req->cmdaddr;
 	struct fnic_io_req *io_req = (struct fnic_io_req *)fcp_req->private;
 	unsigned int tag = io_req->tag;
+	struct fnic_stats *fnic_stats = &fnic->fnic_stats;
+	struct abort_stats *abts_stats;
 	unsigned long flags = 0;
+	unsigned long abt_issued_time;
 	unsigned int task_req;
 	enum fnic_ioreq_state old_ioreq_state;
+	unsigned long num_ios_waitq, waitq_2sec, waitq_max_time;
 
 	spin_lock_irqsave(&fnic->fnic_lock, flags);
 
@@ -1700,6 +1857,15 @@ void nvfnic_fcpio_abort(struct nvme_fc_local_port *lport,
 		FNIC_NVME_DBG(KERN_INFO, fnic,
 			      "cmd tag freed or not issued:0x%x sn:0x%08x\n",
 			      io_req->tag, be32_to_cpu(cmd_iu->csn));
+		num_ios_waitq =
+		    atomic64_read(&fnic_stats->io_stats.nvme_num_ios_in_waitq);
+		waitq_2sec =
+		    atomic64_read(&fnic_stats->io_stats.nvme_ios_in_waitq_3000_msec);
+		waitq_max_time =
+		    atomic64_read(&fnic_stats->io_stats.nvme_ios_in_waitq_max_time);
+		FNIC_NVME_DBG(KERN_INFO, fnic,
+			      "waitq:%ld waitq_2sec:%ld max_wait:%ld\n",
+			      num_ios_waitq, waitq_2sec, waitq_max_time);
 		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
 		return;
 	}
@@ -1747,7 +1913,24 @@ void nvfnic_fcpio_abort(struct nvme_fc_local_port *lport,
 		task_req = FCPIO_ITMF_ABT_TASK;
 	}
 
-
+	abts_stats = &fnic->fnic_stats.abts_stats;
+	atomic64_inc(&abts_stats->aborts);
+
+	abt_issued_time = jiffies_to_msecs(jiffies - io_req->start_time);
+	if (abt_issued_time <= 6000)
+		atomic64_inc(&abts_stats->abort_issued_btw_0_to_6_sec);
+	else if (abt_issued_time > 6000 && abt_issued_time <= 20000)
+		atomic64_inc(&abts_stats->abort_issued_btw_6_to_20_sec);
+	else if (abt_issued_time > 20000 && abt_issued_time <= 30000)
+		atomic64_inc(&abts_stats->abort_issued_btw_20_to_30_sec);
+	else if (abt_issued_time > 30000 && abt_issued_time <= 40000)
+		atomic64_inc(&abts_stats->abort_issued_btw_30_to_40_sec);
+	else if (abt_issued_time > 40000 && abt_issued_time <= 50000)
+		atomic64_inc(&abts_stats->abort_issued_btw_40_to_50_sec);
+	else if (abt_issued_time > 50000 && abt_issued_time <= 60000)
+		atomic64_inc(&abts_stats->abort_issued_btw_50_to_60_sec);
+	else
+		atomic64_inc(&abts_stats->abort_issued_greater_than_60_sec);
 
 	old_ioreq_state = io_req->cmd_state;
 	io_req->cmd_state = FNIC_IOREQ_ABTS_PENDING;
@@ -1800,6 +1983,7 @@ void nvfnic_nvme_iodone_work(struct work_struct *work)
 	llnode = llist_del_all(&fnic->nvme_io_event_llist);
 	llist_for_each_entry_safe(io_req, tmp, llnode, nvfnic_io_cmpl) {
 		atomic_dec(&fnic->nvme_io_event_queued);
+		atomic64_dec(&fnic->fnic_stats.io_stats.nvme_num_ios_in_waitq);
 		io_req->fcp_req->done(io_req->fcp_req);
 	}
 }
diff --git a/drivers/scsi/fnic/fnic_stats.h b/drivers/scsi/fnic/fnic_stats.h
index 8ddd20401a59..fc81e4a7e29e 100644
--- a/drivers/scsi/fnic/fnic_stats.h
+++ b/drivers/scsi/fnic/fnic_stats.h
@@ -29,6 +29,15 @@ struct io_path_stats {
 	atomic64_t io_greater_than_30000_msec;
 	atomic64_t current_max_io_time;
 	atomic64_t ios[FNIC_MQ_MAX_QUEUES];
+
+	atomic64_t nvme_io_reqs_rcvd;
+	atomic64_t nvme_ios_queued_for_rsp;
+	atomic64_t nvme_io_rsps_unqueued;
+	atomic64_t nvme_io_rsps_sending;
+	atomic64_t nvme_io_rsps_sent;
+	atomic64_t nvme_num_ios_in_waitq;
+	atomic64_t nvme_ios_in_waitq_3000_msec;
+	atomic64_t nvme_ios_in_waitq_max_time;
 };
 
 struct abort_stats {
@@ -151,6 +160,17 @@ struct fnic_iport_stats {
 	atomic64_t unsupported_frames_dropped;
 };
 
+struct nvme_host_statistics {
+	atomic64_t nvme_input_requests;
+	atomic64_t nvme_output_requests;
+	atomic64_t nvme_control_requests;
+	atomic64_t nvme_ersps;
+	atomic64_t nvme_ls_requests;
+	atomic64_t nvme_ls_responses;
+	atomic64_t nvme_ls_aborts;
+	atomic64_t nvme_ls_abort_responses;
+};
+
 struct fnic_stats {
 	struct stats_timestamps stats_timestamps;
 	struct io_path_stats io_stats;
@@ -161,6 +181,7 @@ struct fnic_stats {
 	struct vlan_stats vlan_stats;
 	struct fc_host_statistics host_stats;
 	struct misc_stats misc_stats;
+	struct nvme_host_statistics nvme_stats;
 };
 
 struct stats_debug_info {
-- 
2.47.1


  parent reply	other threads:[~2026-06-24  4:50 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-24  4:43 [PATCH v5 00/13] Introduce functionality for NVMe initiator Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 01/13] scsi: fnic: Make debug logging protocol independent Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 02/13] scsi: fnic: Use fnic_num for non-SCSI identifiers Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 03/13] scsi: fnic: Decode firmware role configuration Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 04/13] scsi: fnic: Advertise NVMe initiator service parameters Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 05/13] scsi: fnic: Add FDLS role handling for NVMe initiators Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 06/13] scsi: fnic: Add the NVMe/FC transport path Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 07/13] scsi: fnic: Route completions and resets by initiator role Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 08/13] scsi: fnic: Handle NVMe LS frames in FDLS Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 09/13] scsi: fnic: Send NVMe LS requests through FDLS Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 10/13] scsi: fnic: Abort timed-out NVMe LS requests Karan Tilak Kumar
2026-06-24  4:43 ` Karan Tilak Kumar [this message]
2026-06-24  4:43 ` [PATCH v5 12/13] scsi: fnic: Expose NVMe transport state in debugfs Karan Tilak Kumar
2026-06-24  4:43 ` [PATCH v5 13/13] scsi: fnic: Bump up version number Karan Tilak Kumar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260624044334.3079-12-kartilak@cisco.com \
    --to=kartilak@cisco.com \
    --cc=adakopou@redhat.com \
    --cc=aeasi@cisco.com \
    --cc=arulponn@cisco.com \
    --cc=djhawar@cisco.com \
    --cc=gcboffa@cisco.com \
    --cc=hare@kernel.org \
    --cc=jejb@linux.ibm.com \
    --cc=jmeneghi@redhat.com \
    --cc=lduncan@suse.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=lkp@intel.com \
    --cc=martin.petersen@oracle.com \
    --cc=mkai2@cisco.com \
    --cc=revers@redhat.com \
    --cc=satishkh@cisco.com \
    --cc=sebaddel@cisco.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®