@@ -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.
*
@@ -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 *);
@@ -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
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(-)