git: ab4b83874a4e - main - ctl: Update some core data paths to be protocol agnostic

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Fri, 03 May 2024 00:15:58 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=ab4b83874a4e696733c0ae6c05820891cc09c546

commit ab4b83874a4e696733c0ae6c05820891cc09c546
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2024-05-02 23:31:44 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-05-02 23:31:44 +0000

    ctl: Update some core data paths to be protocol agnostic
    
    - Add wrapper routines for invoking the be_move_done and io_continue
      callbacks in SCSI and NVMe I/O requests.
    
    - Use wrapper routines for access to shared fields between SCSI and
      NVMe I/O requests.
    
    - ctl_config_write_done is not fully updated since it resubmits SCSI
      commands via ctl_scsiio.  This will be completed in a subsequent
      commit when ctl_nvmeio is added.
    
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D44846
---
 sys/cam/ctl/ctl.c | 225 ++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 169 insertions(+), 56 deletions(-)

diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 0a9bb526109a..61c80d7cc1b3 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -528,6 +528,38 @@ static moduledata_t ctl_moduledata = {
 DECLARE_MODULE(ctl, ctl_moduledata, SI_SUB_CONFIGURE, SI_ORDER_THIRD);
 MODULE_VERSION(ctl, 1);
 
+static void
+ctl_be_move_done(union ctl_io *io, bool samethr)
+{
+	switch (io->io_hdr.io_type) {
+	case CTL_IO_SCSI:
+		io->scsiio.be_move_done(io, samethr);
+		break;
+	case CTL_IO_NVME:
+	case CTL_IO_NVME_ADMIN:
+		io->nvmeio.be_move_done(io, samethr);
+		break;
+	default:
+		__assert_unreachable();
+	}
+}
+
+static void
+ctl_continue_io(union ctl_io *io)
+{
+	switch (io->io_hdr.io_type) {
+	case CTL_IO_SCSI:
+		io->scsiio.io_cont(io);
+		break;
+	case CTL_IO_NVME:
+	case CTL_IO_NVME_ADMIN:
+		io->nvmeio.io_cont(io);
+		break;
+	default:
+		__assert_unreachable();
+	}
+}
+
 static struct ctl_frontend ha_frontend =
 {
 	.name = "ha",
@@ -601,32 +633,32 @@ ctl_ha_datamove(union ctl_io *io)
 	 * us to get more than CTL_HA_MAX_SG_ENTRIES S/G entries,
 	 * then we need to break this up into multiple transfers.
 	 */
-	if (io->scsiio.kern_sg_entries == 0) {
+	if (ctl_kern_sg_entries(io) == 0) {
 		msg.dt.kern_sg_entries = 1;
 #if 0
 		if (io->io_hdr.flags & CTL_FLAG_BUS_ADDR) {
-			msg.dt.sg_list[0].addr = io->scsiio.kern_data_ptr;
+			msg.dt.sg_list[0].addr = ctl_kern_data_ptr(io);
 		} else {
 			/* XXX KDM use busdma here! */
 			msg.dt.sg_list[0].addr =
-			    (void *)vtophys(io->scsiio.kern_data_ptr);
+			    (void *)vtophys(ctl_kern_data_ptr(io));
 		}
 #else
 		KASSERT((io->io_hdr.flags & CTL_FLAG_BUS_ADDR) == 0,
 		    ("HA does not support BUS_ADDR"));
-		msg.dt.sg_list[0].addr = io->scsiio.kern_data_ptr;
+		msg.dt.sg_list[0].addr = ctl_kern_data_ptr(io);
 #endif
-		msg.dt.sg_list[0].len = io->scsiio.kern_data_len;
+		msg.dt.sg_list[0].len = ctl_kern_data_len(io);
 		do_sg_copy = 0;
 	} else {
-		msg.dt.kern_sg_entries = io->scsiio.kern_sg_entries;
+		msg.dt.kern_sg_entries = ctl_kern_sg_entries(io);
 		do_sg_copy = 1;
 	}
 
-	msg.dt.kern_data_len = io->scsiio.kern_data_len;
-	msg.dt.kern_total_len = io->scsiio.kern_total_len;
-	msg.dt.kern_data_resid = io->scsiio.kern_data_resid;
-	msg.dt.kern_rel_offset = io->scsiio.kern_rel_offset;
+	msg.dt.kern_data_len = ctl_kern_data_len(io);
+	msg.dt.kern_total_len = ctl_kern_total_len(io);
+	msg.dt.kern_data_resid = ctl_kern_data_resid(io);
+	msg.dt.kern_rel_offset = ctl_kern_rel_offset(io);
 	msg.dt.sg_sequence = 0;
 
 	/*
@@ -640,7 +672,7 @@ ctl_ha_datamove(union ctl_io *io)
 		    sizeof(msg.dt.sg_list[0])),
 		    msg.dt.kern_sg_entries - sg_entries_sent);
 		if (do_sg_copy != 0) {
-			sgl = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr;
+			sgl = (struct ctl_sg_entry *)ctl_kern_data_ptr(io);
 			for (i = sg_entries_sent, j = 0;
 			     i < msg.dt.cur_sg_entries; i++, j++) {
 #if 0
@@ -4937,7 +4969,7 @@ ctl_config_move_done(union ctl_io *io, bool samethr)
 		 * we'll need to know how to clean them up here as well.
 		 */
 		if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
-			free(io->scsiio.kern_data_ptr, M_CTL);
+			free(ctl_kern_data_ptr(io), M_CTL);
 		ctl_done(io);
 		retval = CTL_RETVAL_COMPLETE;
 	} else {
@@ -4982,7 +5014,7 @@ ctl_data_submit_done(union ctl_io *io)
 	    (io->io_hdr.flags & CTL_FLAG_ABORT) == 0 &&
 	    ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
 	     (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
-		io->scsiio.io_cont(io);
+		ctl_continue_io(io);
 		return;
 	}
 	ctl_done(io);
@@ -5009,7 +5041,7 @@ ctl_config_write_done(union ctl_io *io)
 	    (io->io_hdr.flags & CTL_FLAG_ABORT) == 0 &&
 	    ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
 	     (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
-		io->scsiio.io_cont(io);
+		ctl_continue_io(io);
 		return;
 	}
 	/*
@@ -5018,7 +5050,7 @@ ctl_config_write_done(union ctl_io *io)
 	 * no data, like start/stop unit, we need to check here.
 	 */
 	if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
-		buf = io->scsiio.kern_data_ptr;
+		buf = ctl_kern_data_ptr(io);
 	else
 		buf = NULL;
 	ctl_done(io);
@@ -5038,7 +5070,7 @@ ctl_config_read_done(union ctl_io *io)
 	    ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE &&
 	     (io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS)) {
 		if (io->io_hdr.flags & CTL_FLAG_ALLOCATED)
-			buf = io->scsiio.kern_data_ptr;
+			buf = ctl_kern_data_ptr(io);
 		else
 			buf = NULL;
 		ctl_done(io);
@@ -5053,7 +5085,7 @@ ctl_config_read_done(union ctl_io *io)
 	 * the I/O just yet.
 	 */
 	if (io->io_hdr.flags & CTL_FLAG_IO_CONT) {
-		io->scsiio.io_cont(io);
+		ctl_continue_io(io);
 		return;
 	}
 
@@ -12318,11 +12350,7 @@ ctl_datamove_done_process(union ctl_io *io)
 {
 #ifdef CTL_TIME_IO
 	struct bintime cur_bt;
-#endif
-
-	CTL_IO_ASSERT(io, SCSI);
 
-#ifdef CTL_TIME_IO
 	getbinuptime(&cur_bt);
 	bintime_sub(&cur_bt, &io->io_hdr.dma_start_bt);
 	bintime_add(&io->io_hdr.dma_bt, &cur_bt);
@@ -12332,13 +12360,36 @@ ctl_datamove_done_process(union ctl_io *io)
 	if ((io->io_hdr.port_status != 0) &&
 	    ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
 	     (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
-		ctl_set_internal_failure(&io->scsiio, /*sks_valid*/ 1,
-		    /*retry_count*/ io->io_hdr.port_status);
-	} else if (io->scsiio.kern_data_resid != 0 &&
+		switch (io->io_hdr.io_type) {
+		case CTL_IO_SCSI:
+			ctl_set_internal_failure(&io->scsiio, /*sks_valid*/ 1,
+			    /*retry_count*/ io->io_hdr.port_status);
+			break;
+		case CTL_IO_NVME:
+		case CTL_IO_NVME_ADMIN:
+			if (io->io_hdr.flags & CTL_FLAG_ABORT)
+				ctl_nvme_set_command_aborted(&io->nvmeio);
+			else
+				ctl_nvme_set_data_transfer_error(&io->nvmeio);
+			break;
+		default:
+			__assert_unreachable();
+		}
+	} else if (ctl_kern_data_resid(io) != 0 &&
 	    (io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_OUT &&
 	    ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_STATUS_NONE ||
 	     (io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS)) {
-		ctl_set_invalid_field_ciu(&io->scsiio);
+		switch (io->io_hdr.io_type) {
+		case CTL_IO_SCSI:
+			ctl_set_invalid_field_ciu(&io->scsiio);
+			break;
+		case CTL_IO_NVME:
+		case CTL_IO_NVME_ADMIN:
+			ctl_nvme_set_data_transfer_error(&io->nvmeio);
+			break;
+		default:
+			__assert_unreachable();
+		}
 	} else if (ctl_debug & CTL_DEBUG_CDB_DATA)
 		ctl_data_print(io);
 }
@@ -12348,7 +12399,7 @@ ctl_datamove_done(union ctl_io *io, bool samethr)
 {
 
 	ctl_datamove_done_process(io);
-	io->scsiio.be_move_done(io, samethr);
+	ctl_be_move_done(io, samethr);
 }
 
 void
@@ -12361,7 +12412,7 @@ ctl_datamove(union ctl_io *io)
 	CTL_DEBUG_PRINT(("ctl_datamove\n"));
 
 	/* No data transferred yet.  Frontend must update this when done. */
-	io->scsiio.kern_data_resid = io->scsiio.kern_data_len;
+	ctl_set_kern_data_resid(io, ctl_kern_data_len(io));
 
 #ifdef CTL_TIME_IO
 	getbinuptime(&io->io_hdr.dma_start_bt);
@@ -12394,20 +12445,33 @@ ctl_datamove(union ctl_io *io)
 	 * the data move.
 	 */
 	if (io->io_hdr.flags & CTL_FLAG_ABORT) {
-		printf("ctl_datamove: tag 0x%jx on (%u:%u:%u) aborted\n",
-		       io->scsiio.tag_num, io->io_hdr.nexus.initid,
-		       io->io_hdr.nexus.targ_port,
-		       io->io_hdr.nexus.targ_lun);
+		switch (io->io_hdr.io_type) {
+		case CTL_IO_SCSI:
+			printf("ctl_datamove: tag 0x%jx on (%u:%u:%u) aborted\n",
+			    io->scsiio.tag_num, io->io_hdr.nexus.initid,
+			    io->io_hdr.nexus.targ_port,
+			    io->io_hdr.nexus.targ_lun);
+			break;
+		case CTL_IO_NVME:
+		case CTL_IO_NVME_ADMIN:
+			printf("ctl_datamove: CID 0x%x on (%u:%u:%u) aborted\n",
+			    le16toh(io->nvmeio.cmd.cid),
+			    io->io_hdr.nexus.initid, io->io_hdr.nexus.targ_port,
+			    io->io_hdr.nexus.targ_lun);
+			break;
+		default:
+			__assert_unreachable();
+		}
 		io->io_hdr.port_status = 31337;
 		ctl_datamove_done_process(io);
-		io->scsiio.be_move_done(io, true);
+		ctl_be_move_done(io, true);
 		return;
 	}
 
 	/* Don't confuse frontend with zero length data move. */
-	if (io->scsiio.kern_data_len == 0) {
+	if (ctl_kern_data_len(io) == 0) {
 		ctl_datamove_done_process(io);
-		io->scsiio.be_move_done(io, true);
+		ctl_be_move_done(io, true);
 		return;
 	}
 
@@ -12763,7 +12827,7 @@ ctl_datamove_remote_read(union ctl_io *io)
 		 * datamove done message, or call the callback with an
 		 * error if there is a problem.
 		 */
-		for (i = 0; i < io->scsiio.kern_sg_entries; i++)
+		for (i = 0; i < ctl_kern_sg_entries(io); i++)
 			free(CTL_LSGLT(io)[i].addr, M_CTL);
 		free(CTL_RSGL(io), M_CTL);
 		CTL_RSGL(io) = NULL;
@@ -12847,6 +12911,8 @@ ctl_process_done(union ctl_io *io)
 
 	switch (io->io_hdr.io_type) {
 	case CTL_IO_SCSI:
+	case CTL_IO_NVME:
+	case CTL_IO_NVME_ADMIN:
 		break;
 	case CTL_IO_TASK:
 		if (ctl_debug & CTL_DEBUG_INFO)
@@ -12877,6 +12943,8 @@ ctl_process_done(union ctl_io *io)
 		uint8_t mrie = lun->MODE_IE.mrie;
 		uint8_t per = ((lun->MODE_RWER.byte3 & SMS_RWER_PER) ||
 		    (lun->MODE_VER.byte3 & SMS_VER_PER));
+
+		CTL_IO_ASSERT(io, SCSI);
 		if (((mrie == SIEP_MRIE_REC_COND && per) ||
 		     mrie == SIEP_MRIE_REC_UNCOND ||
 		     mrie == SIEP_MRIE_NO_SENSE) &&
@@ -12910,7 +12978,9 @@ ctl_process_done(union ctl_io *io)
 	 * XXX KDM should we also track I/O latency?
 	 */
 	if ((io->io_hdr.status & CTL_STATUS_MASK) == CTL_SUCCESS &&
-	    io->io_hdr.io_type == CTL_IO_SCSI) {
+	    (io->io_hdr.io_type == CTL_IO_SCSI ||
+	    io->io_hdr.io_type == CTL_IO_NVME ||
+	    io->io_hdr.io_type == CTL_IO_NVME_ADMIN)) {
 		int type;
 #ifdef CTL_TIME_IO
 		struct bintime bt;
@@ -12927,7 +12997,7 @@ ctl_process_done(union ctl_io *io)
 		else
 			type = CTL_STATS_NO_IO;
 
-		lun->stats.bytes[type] += io->scsiio.kern_total_len;
+		lun->stats.bytes[type] += ctl_kern_total_len(io);
 		lun->stats.operations[type] ++;
 		lun->stats.dmas[type] += io->io_hdr.num_dmas;
 #ifdef CTL_TIME_IO
@@ -12936,7 +13006,7 @@ ctl_process_done(union ctl_io *io)
 #endif
 
 		mtx_lock(&port->port_lock);
-		port->stats.bytes[type] += io->scsiio.kern_total_len;
+		port->stats.bytes[type] += ctl_kern_total_len(io);
 		port->stats.operations[type] ++;
 		port->stats.dmas[type] += io->io_hdr.num_dmas;
 #ifdef CTL_TIME_IO
@@ -12980,8 +13050,19 @@ bailout:
 	 * properly.  The FETD is responsible for freeing the I/O and doing
 	 * whatever it needs to do to clean up its state.
 	 */
-	if (io->io_hdr.flags & CTL_FLAG_ABORT)
-		ctl_set_task_aborted(&io->scsiio);
+	if (io->io_hdr.flags & CTL_FLAG_ABORT) {
+		switch (io->io_hdr.io_type) {
+		case CTL_IO_SCSI:
+			ctl_set_task_aborted(&io->scsiio);
+			break;
+		case CTL_IO_NVME:
+		case CTL_IO_NVME_ADMIN:
+			ctl_nvme_set_command_aborted(&io->nvmeio);
+			break;
+		default:
+			__assert_unreachable();
+		}
+	}
 
 	/*
 	 * If enabled, print command error status.
@@ -13166,22 +13247,54 @@ ctl_done(union ctl_io *io)
 	 */
 #if 0
 	if (io->io_hdr.flags & CTL_FLAG_ALREADY_DONE) {
-		printf("%s: type %d msg %d cdb %x iptl: "
-		       "%u:%u:%u tag 0x%04x "
-		       "flag %#x status %x\n",
-			__func__,
-			io->io_hdr.io_type,
-			io->io_hdr.msg_type,
-			io->scsiio.cdb[0],
-			io->io_hdr.nexus.initid,
-			io->io_hdr.nexus.targ_port,
-			io->io_hdr.nexus.targ_lun,
-			(io->io_hdr.io_type ==
-			CTL_IO_TASK) ?
-			io->taskio.tag_num :
-			io->scsiio.tag_num,
-		        io->io_hdr.flags,
-			io->io_hdr.status);
+		switch (io->io_hdr.io_type) {
+		case CTL_IO_SCSI:
+		case CTL_IO_TASK:
+			printf("%s: type %d msg %d cdb %x iptl: "
+			    "%u:%u:%u tag 0x%04lx "
+			    "flag %#x status %x\n",
+			    __func__,
+			    io->io_hdr.io_type,
+			    io->io_hdr.msg_type,
+			    io->scsiio.cdb[0],
+			    io->io_hdr.nexus.initid,
+			    io->io_hdr.nexus.targ_port,
+			    io->io_hdr.nexus.targ_lun,
+			    (io->io_hdr.io_type == CTL_IO_TASK) ?
+			    io->taskio.tag_num :
+			    io->scsiio.tag_num,
+			    io->io_hdr.flags,
+			    io->io_hdr.status);
+			break;
+		case CTL_IO_NVME:
+		case CTL_IO_NVME_ADMIN:
+			printf("%s: type %d msg %d opc %x iptl: "
+			    "%u:%u:%u cid 0x%04x "
+			    "flag %#x status %x\n",
+			    __func__,
+			    io->io_hdr.io_type,
+			    io->io_hdr.msg_type,
+			    io->nvmeio.cmd.opc,
+			    io->io_hdr.nexus.initid,
+			    io->io_hdr.nexus.targ_port,
+			    io->io_hdr.nexus.targ_lun,
+			    io->nvmeio.cmd.cid,
+			    io->io_hdr.flags,
+			    io->io_hdr.status);
+			break;
+		default:
+			printf("%s: type %d msg %d iptl: "
+			    "%u:%u:%u flag %#x status %x\n",
+			    __func__,
+			    io->io_hdr.io_type,
+			    io->io_hdr.msg_type,
+			    io->io_hdr.nexus.initid,
+			    io->io_hdr.nexus.targ_port,
+			    io->io_hdr.nexus.targ_lun,
+			    io->io_hdr.flags,
+			    io->io_hdr.status);
+			break;
+		}
 	} else
 		io->io_hdr.flags |= CTL_FLAG_ALREADY_DONE;
 #endif