From patchwork Sat Jun 17 11:00:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Minwoo Im X-Patchwork-Id: 9794055 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id A1D0A6038E for ; Sat, 17 Jun 2017 11:00:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 88049284D2 for ; Sat, 17 Jun 2017 11:00:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7950F284DC; Sat, 17 Jun 2017 11:00:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D9AD3284D2 for ; Sat, 17 Jun 2017 11:00:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752727AbdFQLA5 (ORCPT ); Sat, 17 Jun 2017 07:00:57 -0400 Received: from mail-pf0-f196.google.com ([209.85.192.196]:36650 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752190AbdFQLAz (ORCPT ); Sat, 17 Jun 2017 07:00:55 -0400 Received: by mail-pf0-f196.google.com with SMTP id y7so10144894pfd.3; Sat, 17 Jun 2017 04:00:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=oogY9i590d4A87kEQSsy9rBghqrjnPFtLlO4wJKZWDc=; b=jYoVvbW/NlxwqcYLZNZJu7S8d3GyzB+rCY00pF0wNISu5AxtZK5cPu6B5bQqDBTjx6 pLtNap8bsI8DkyhE7G6zc717R4OjWybfbPpbXYKWnI/Wv+Ae7G2CwaTStBA4HFJJvEDk 4/41phcVyfNIZIcoVU5OKlcAJG4VryBP5zXI36esvNnP1qqLvXJa+RjCdFztOTB5gDAh QyJeSdtEe+QT43/1TmdhsO/Xxr2exobtobnp7t5qyN7NkRETEY19qXhfxxhIsY5/l18r kQL2k/9e5LxV4NSwHBN+TDt7T1lh1rJCn2MmrwKFrEWLhoprY/t8Xvrpb/xqlxa8FyAr Nd9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=oogY9i590d4A87kEQSsy9rBghqrjnPFtLlO4wJKZWDc=; b=FFszj4aDGQQE0TssVkaMUPeFCsvkl4iPcx0Ss/9zGveUtcrJWdfYp/Q1Yg0V4y6L3a J8sJxmIcsH6HglClRHTfJFgsxgpz9ZbID81rI4wbsFFK6EzSIVz4bV5ayo0K1GcgLmBJ nHiQb0EKsyOZCtgWQmKwqRXh6rJ0li611I3UhFGl+47NY9ueYL21pQDb2UcwzKBcTrml Ul+PNKxeO+BMxjYcfv4Rc6BCJbiYnkUaUTHgNPQbBqHbMwCGsV+s2CGvc42PlqR/si+f xjK2DLhZUGQg4fsEsDGZjzCBA5DnTH8K9ntKbiuD3Vlz9owSRMBgxuLKaz65aaDqo9m4 jaqQ== X-Gm-Message-State: AKS2vOw8wyH2eL8kIXpbUdwANtYYqYQ2BcrO5yh5Jl/eWCmEnF9zG/8e qbjZ/C1WPqxkyg== X-Received: by 10.84.216.92 with SMTP id f28mr11393769plj.199.1497697254496; Sat, 17 Jun 2017 04:00:54 -0700 (PDT) Received: from Lim-localhost.skbroadband ([61.98.86.79]) by smtp.gmail.com with ESMTPSA id k70sm9755136pfg.72.2017.06.17.04.00.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 17 Jun 2017 04:00:53 -0700 (PDT) From: Minwoo Im To: Tejun Heo , "James E.J. Bottomley" , "Martin K. Petersen" , Bart Van Assche Cc: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org, Minwoo Im Subject: [PATCH] scsi/libata: Support variable-length cdb of ata pass-thru(32). Date: Sat, 17 Jun 2017 20:00:43 +0900 Message-Id: <1497697243-3724-1-git-send-email-dn3108@gmail.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Proposal Background: SAT-4 supports ATA PASS-THROUGH(32) SCSI command to translate SCSI commands to further ATA command format(e.g. auxiliary field). To support any command translation from SCSI command to ATA, This patch would be great for it. Patch Description: ATA PASS-THROUGH(32) command defines 7Fh as a opcode which means a variable length command. It could be in any size from 12 to 260. However, first to support ATA PASS-THROUGH(32), ATA Device max CDB length has been modified to 32(It used to be 16). Additionally, SCSI command max length has been modified to 260 to support variable-length cdbs in kernel. ata_get_xlat_func() adds a condition for variable length command. ata_scsi_var_len_cdb_xlat() checks the ATA PASS-THROUGH(32) service action. After checking, it will call ata_scsi_pass_thru() just like ATA PASS-THROUGH(12) and (16). ata_scsi_pass_thru() adds some code lines to support (32) pass-thru. pass-thru(32) has a different CDB contents from 12, or 16. Please refer below patch and fill free to give any opinions. Thanks, Minwoo. Signed-off-by: Minwoo Im --- drivers/ata/libata-core.c | 2 +- drivers/ata/libata-scsi.c | 95 ++++++++++++++++++++++++++++++++++++++++++--- include/scsi/scsi_proto.h | 1 + 3 files changed, 91 insertions(+), 7 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index e157a0e..f1d3ba4 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2587,7 +2587,7 @@ int ata_dev_configure(struct ata_device *dev) } ata_dev_config_sense_reporting(dev); ata_dev_config_zac(dev); - dev->cdb_len = 16; + dev->cdb_len = 32; } /* ATAPI-specific feature tests */ diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 49ba983..b6e32d9 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -3127,7 +3127,7 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, * ata_scsi_pass_thru - convert ATA pass-thru CDB to taskfile * @qc: command structure to be initialized * - * Handles either 12 or 16-byte versions of the CDB. + * Handles either 12, 16, or 32-byte versions of the CDB. * * RETURNS: * Zero on success, non-zero on failure. @@ -3140,13 +3140,36 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) const u8 *cdb = scmd->cmnd; u16 fp; - if ((tf->protocol = ata_scsi_map_proto(cdb[1])) == ATA_PROT_UNKNOWN) { + /* + * if SCSI operation code in cdb[0] is ATA_12 or ATA_16, + * then cdb[1] will contain protocol of ATA PASS-THROUGH. + * otherwise, Its operation code shall be ATA_32(7Fh). + * in this case, cdb[10] will contain protocol of it. + * we call this command as a variable-length cdb. + */ + if (cdb[0] == ATA_12 || cdb[0] == ATA_16) + tf->protocol = ata_scsi_map_proto(cdb[1]); + else + tf->protocol = ata_scsi_map_proto(cdb[10]); + + if (tf->protocol == ATA_PROT_UNKNOWN) { fp = 1; goto invalid_fld; } - if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0) - tf->protocol = ATA_PROT_NCQ_NODATA; + /* + * if protocol has a NCQ property and transfer length is 0, + * then the protocol will be marked as a NCQ_NODATA. + * in case of ATA_12 and ATA_16, cdb[2] has a t_length field. + * otherwise, cdb[11] will have a t_length field. + */ + if (cdb[0] == ATA_12 || cdb[0] == ATA_16) { + if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0) + tf->protocol = ATA_PROT_NCQ_NODATA; + } else { + if (ata_is_ncq(tf->protocol) && (cdb[11] & 0x3) == 0) + tf->protocol = ATA_PROT_NCQ_NODATA; + } /* enable LBA */ tf->flags |= ATA_TFLAG_LBA; @@ -3181,7 +3204,7 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->lbah = cdb[12]; tf->device = cdb[13]; tf->command = cdb[14]; - } else { + } else if (cdb[0] == ATA_12) { /* * 12-byte CDB - incapable of extended commands. */ @@ -3194,6 +3217,31 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) tf->lbah = cdb[7]; tf->device = cdb[8]; tf->command = cdb[9]; + } else { + /* + * 32-byte CDB - may contain extended command fields. + * + * If that is the case, copy the upper byte register values. + */ + if (cdb[10] & 0x01) { + tf->hob_feature = cdb[20]; + tf->hob_nsect = cdb[22]; + tf->hob_lbal = cdb[16]; + tf->hob_lbam = cdb[15]; + tf->hob_lbah = cdb[14]; + tf->flags |= ATA_TFLAG_LBA48; + } else + tf->flags &= ~ATA_TFLAG_LBA48; + + tf->feature = cdb[21]; + tf->nsect = cdb[23]; + tf->lbal = cdb[19]; + tf->lbam = cdb[18]; + tf->lbah = cdb[17]; + tf->device = cdb[24]; + tf->command = cdb[25]; + tf->auxiliary = (cdb[28] << 24) | (cdb[29] << 16) + | (cdb[30] << 8) | cdb[31]; } /* For NCQ commands copy the tag value */ @@ -4068,6 +4116,33 @@ static unsigned int ata_scsi_mode_select_xlat(struct ata_queued_cmd *qc) } /** + * ata_scsi_var_len_cdb_xlat - SATL Variable Length CDB to Handler + * @qc: Command to be translated + * + * Translate a SCSI variable length CDB to specified commands. + * It checks a service action value in CDB to call corresponding handler. + * + * RETURNS: + * Zero on success, non-zero on failure + */ + +static unsigned int ata_scsi_var_len_cdb_xlat(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + const u8 *cdb = scmd->cmnd; + const u16 sa = (cdb[8] >> 8) | cdb[9]; /* service action */ + + // if service action represents a ata pass-thru(32) command, + // then pass it to ata_scsi_pass_thru handler. + if (sa == ATA_32) + return ata_scsi_pass_thru(qc); + +unspprt_sa: + /* unsupported service action */ + return 1; +} + +/** * ata_get_xlat_func - check if SCSI to ATA translation is possible * @dev: ATA device * @cmd: SCSI command opcode to consider @@ -4107,6 +4182,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) case ATA_16: return ata_scsi_pass_thru; + case VARIABLE_LENGTH_CMD: + return ata_scsi_var_len_cdb_xlat; + case MODE_SELECT: case MODE_SELECT_10: return ata_scsi_mode_select_xlat; @@ -4385,7 +4463,12 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) shost->max_id = 16; shost->max_lun = 1; shost->max_channel = 1; - shost->max_cmd_len = 16; + /* + * SPC-3, SPC-4: Definition of CDB + * A CDB may have a fixed length of up to 16 bytes or + * variable length of between 12 and 260 bytes. + */ + shost->max_cmd_len = 260; /* Schedule policy is determined by ->qc_defer() * callback and it needs to see every deferred qc. diff --git a/include/scsi/scsi_proto.h b/include/scsi/scsi_proto.h index ce78ec8..8545e34 100644 --- a/include/scsi/scsi_proto.h +++ b/include/scsi/scsi_proto.h @@ -164,6 +164,7 @@ #define WRITE_SAME_32 0x0d /* Values for T10/04-262r7 */ +#define ATA_32 0x1ff0 /* 32-byte pass-thru, service action */ #define ATA_16 0x85 /* 16-byte pass-thru */ #define ATA_12 0xa1 /* 12-byte pass-thru */