diff mbox series

[v2,1/4] target: Handle MI_REPORT_SUPPORTED_OPERATION_CODES

Message ID 41806206e78812afe97101a11881f5a33092a93b.1658195608.git.Thinh.Nguyen@synopsys.com
State New
Headers show
Series [v2,1/4] target: Handle MI_REPORT_SUPPORTED_OPERATION_CODES | expand

Commit Message

Thinh Nguyen July 19, 2022, 2:07 a.m. UTC
Microsoft Windows checks for MI_REPORT_SUPPORTED_OPERATION_CODES. Let's
handle this MAINTENANCE_IN command and report supported commands.

Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
---
 Changes in v2:
 - Fix spec section number
 - Fix potential invalid "buf" access on error

 drivers/target/target_core_alua.c | 70 +++++++++++++++++++++++++++++++
 drivers/target/target_core_alua.h |  2 +
 drivers/target/target_core_spc.c  | 14 ++++++-
 3 files changed, 84 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index b56ef8af66e7..881e04ce8544 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -259,6 +259,76 @@  target_emulate_report_target_port_groups(struct se_cmd *cmd)
 	return 0;
 }
 
+/*
+ * REPORT_SUPPORTED_OPERATION_CODES
+ *
+ * See spc4r37 section 6.35
+ */
+sense_reason_t
+target_emulate_report_supported_opcodes(struct se_cmd *cmd)
+{
+	unsigned char *cdb = cmd->t_task_cdb;
+	unsigned char *buf;
+
+	/*
+	 * Only supports reporting option 1.
+	 * i.e. one command parameter with no service action.
+	 */
+	if ((cdb[2] & 0x7) != 1) {
+		pr_warn("Unsupported reporting op code %d\n", cdb[2]);
+		return TCM_UNSUPPORTED_SCSI_OPCODE;
+	}
+
+	buf = transport_kmap_data_sg(cmd);
+	if (!buf)
+		return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+	switch (cdb[3]) {
+	case INQUIRY:
+	case MODE_SENSE:
+	case MODE_SENSE_10:
+	case READ_CAPACITY:
+	case SERVICE_ACTION_IN_16:
+	case REPORT_LUNS:
+	case REQUEST_SENSE:
+	case SYNCHRONIZE_CACHE:
+	case REZERO_UNIT:
+	case SEEK_6:
+	case SEEK_10:
+	case TEST_UNIT_READY:
+	case SEND_DIAGNOSTIC:
+	case MAINTENANCE_IN:
+	case READ_6:
+	case READ_10:
+	case READ_16:
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_16:
+	case VERIFY_16:
+	case MODE_SELECT:
+	case MODE_SELECT_10:
+	case START_STOP:
+	case SECURITY_PROTOCOL_IN:
+	case SECURITY_PROTOCOL_OUT:
+		/* Supported */
+		buf[1] = 3;
+		break;
+	case ATA_12:
+	case ATA_16:
+	case VERIFY:
+	case ZBC_IN:
+	case ZBC_OUT:
+	default:
+		/* Not supported */
+		buf[1] = 1;
+		break;
+	}
+
+	transport_kunmap_data_sg(cmd);
+	target_complete_cmd(cmd, SAM_STAT_GOOD);
+	return 0;
+}
+
 /*
  * SET_TARGET_PORT_GROUPS for explicit ALUA operation.
  *
diff --git a/drivers/target/target_core_alua.h b/drivers/target/target_core_alua.h
index fc9637cce825..7941e4dd4f97 100644
--- a/drivers/target/target_core_alua.h
+++ b/drivers/target/target_core_alua.h
@@ -82,6 +82,8 @@  extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
 extern struct kmem_cache *t10_alua_lba_map_cache;
 extern struct kmem_cache *t10_alua_lba_map_mem_cache;
 
+extern sense_reason_t
+target_emulate_report_supported_opcodes(struct se_cmd *cmd);
 extern sense_reason_t target_emulate_report_target_port_groups(struct se_cmd *);
 extern sense_reason_t target_emulate_set_target_port_groups(struct se_cmd *);
 extern sense_reason_t target_emulate_report_referrals(struct se_cmd *);
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index c14441c89bed..dd799158609d 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -1425,15 +1425,25 @@  spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
 		break;
 	case MAINTENANCE_IN:
 		if (dev->transport->get_device_type(dev) != TYPE_ROM) {
+			u8 action = cdb[1] & 0x1f;
+
 			/*
 			 * MAINTENANCE_IN from SCC-2
 			 * Check for emulated MI_REPORT_TARGET_PGS
 			 */
-			if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS) {
+			if (action == MI_REPORT_TARGET_PGS) {
 				cmd->execute_cmd =
 					target_emulate_report_target_port_groups;
+
+				*size = get_unaligned_be32(&cdb[6]);
+			}
+
+			if (action == MI_REPORT_SUPPORTED_OPERATION_CODES) {
+				cmd->execute_cmd =
+					target_emulate_report_supported_opcodes;
+
+				*size = get_unaligned_be16(&cdb[2]);
 			}
-			*size = get_unaligned_be32(&cdb[6]);
 		} else {
 			/*
 			 * GPCMD_SEND_KEY from multi media commands