From patchwork Mon Apr 4 05:06:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Shaun Tancheff X-Patchwork-Id: 8737421 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 0D841C0553 for ; Mon, 4 Apr 2016 05:06:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0646F201EF for ; Mon, 4 Apr 2016 05:06:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D76CD201F5 for ; Mon, 4 Apr 2016 05:06:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752161AbcDDFGw (ORCPT ); Mon, 4 Apr 2016 01:06:52 -0400 Received: from mail-pf0-f193.google.com ([209.85.192.193]:33289 "EHLO mail-pf0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752092AbcDDFGu (ORCPT ); Mon, 4 Apr 2016 01:06:50 -0400 Received: by mail-pf0-f193.google.com with SMTP id e190so3835440pfe.0; Sun, 03 Apr 2016 22:06:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=m1xBspIJ1vLZ7zBCE1qfGaCioOlx5nBBQFLefjnvhj0=; b=pkgYLXz/oybpXBU+e9y8jyGkfgzrxT6N0yBbv+BAjqHp8PqixzLTKsGx8OqLyKY/5e o1dhEJ/6Fo9Vx45erg9HrigMQ1Kk0GFWtbuTPhsMB+deggzfs+FbCC/EMOB7+qEFkT+l Y63qJ/8StlSRj1JMS4b5M0pDyjRf303Y8budKAnfArCpx0jkEdtjR8euOkXVGse2OIGt jB+0kN+UWDY3pfPBlL6ii2ZO2vj8pqp3rkutMg7SV69d/UkxGIG4NMfGQ/uK3x+05uQH h9a8k3v457LQc+eSGS4sZdbLyIh274cvQp9UttPK+yF2OLuObltzgTXI/mSrhLzH7CFw z2Rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=m1xBspIJ1vLZ7zBCE1qfGaCioOlx5nBBQFLefjnvhj0=; b=ikWF8gKXYee96uQy7tFA3ILV6yVSsmfHSyi9oJwqfHb2L9UeNgwNQ+CI5P1vchYCuw V33ewdDLlYWbRqNcR7LVNsIFf118QpIggIT7WMrSF9Da6TKN62E9gSrZW41ex9JZ59aV /8PT8v/QT0Fv71qbN24gB2QvOR4cx/PcXFUCL2hidxsrbTkIsFRR80GjuQGykP+3Kqxn 7VPbElK4OeJ3G4tCcyzaFFEm32phbMVF49jDKanANIIiMFk7h+2dnKcDz6h2pa0TLp1R 1kTUS00Cz9sb7wu5Y9NeYdONxTCqH7EyVpc00c05min1E8iDyEO45iI85sVMgP2HvWfq XQRg== X-Gm-Message-State: AD7BkJKXWkTkNJ2OUMD6wtIfYX2Cq6c6FdO2tfRu/qsMTDRZ1Iuxt6tmJTiHguNcCuBfRQ== X-Received: by 10.98.73.221 with SMTP id r90mr17766396pfi.70.1459746408878; Sun, 03 Apr 2016 22:06:48 -0700 (PDT) Received: from localhost.localdomain ([103.47.135.1]) by smtp.gmail.com with ESMTPSA id k65sm35804188pfb.30.2016.04.03.22.06.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 03 Apr 2016 22:06:48 -0700 (PDT) From: Shaun Tancheff To: linux-ide@vger.kernel.org, dm-devel@redhat.com, linux-block@vger.kernel.org, linux-scsi@vger.kernel.org Cc: Jens Axboe , Shaun Tancheff , Shaun Tancheff Subject: [PATCH 06/12] Add ata pass-through path for ZAC commands. Date: Mon, 4 Apr 2016 12:06:10 +0700 Message-Id: <1459746376-27983-7-git-send-email-shaun@tancheff.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1459746376-27983-1-git-send-email-shaun@tancheff.com> References: <1459746376-27983-1-git-send-email-shaun@tancheff.com> Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-7.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current generation of HBA SAS adapters support connecting SATA drives and perform SCSI<->ATA translations in hardware. Unfortunately the ZBC commands are not being translate (yet). Currently users of SAS controllers can only send ZAC commands via ata pass-through. This method overloads the meaning of REQ_META to direct ZBC commands to construct ZAC equivalent ATA pass through commands. Note also that this approach expects the initiator to deal with the little endian result due to bypassing the normal translation layers. Signed-off-by: Shaun Tancheff --- block/ioctl.c | 29 +++++++++++++++++++ drivers/scsi/sd.c | 84 +++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 99 insertions(+), 14 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index 825848f..aa11450 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -285,6 +285,35 @@ static int blk_zoned_action_ioctl(struct block_device *bdev, fmode_t mode, return -EFAULT; } + /* + * When the low bit is set force ATA passthrough try to work around + * older SAS HBA controllers that don't support ZBC to ZAC translation. + * + * When the low bit is clear follow the normal path but also correct + * for ~0ul LBA means 'for all lbas'. + * + * NB: We should do extra checking here to see if the user specified + * the entire block device as opposed to a partition of the + * device.... + */ + if (arg & 1) { + bi_rw |= REQ_META; + if (arg != ~0ul) + arg &= ~1ul; /* ~1 :: 0xFF...FE */ + } else { + if (arg == ~1ul) + arg = ~0ul; + } + + /* + * When acting on zones we explicitly disallow using a partition. + */ + if (bdev != bdev->bd_contains) { + pr_err("%s: All zone operations disallowed on this device\n", + __func__); + return -EFAULT; + } + switch (cmd) { case BLKOPENZONE: bi_rw |= REQ_OPEN_ZONE; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 379edf6..3cb0200 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -100,6 +101,16 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); #define SD_MINORS 0 #endif +static inline void _lba_to_cmd_ata(u8 *cmd, u64 _lba) +{ + cmd[1] = _lba & 0xff; + cmd[3] = (_lba >> 8) & 0xff; + cmd[5] = (_lba >> 16) & 0xff; + cmd[0] = (_lba >> 24) & 0xff; + cmd[2] = (_lba >> 32) & 0xff; + cmd[4] = (_lba >> 40) & 0xff; +} + static void sd_config_discard(struct scsi_disk *, unsigned int); static void sd_config_write_same(struct scsi_disk *); static int sd_revalidate_disk(struct gendisk *); @@ -1181,11 +1192,26 @@ static int sd_setup_zoned_cmnd(struct scsi_cmnd *cmd) cmd->cmd_len = 16; memset(cmd->cmnd, 0, cmd->cmd_len); - cmd->cmnd[0] = ZBC_REPORT_ZONES; - cmd->cmnd[1] = ZBC_REPORT_OPT; - put_unaligned_be64(sector, &cmd->cmnd[2]); - put_unaligned_be32(nr_bytes, &cmd->cmnd[10]); - cmd->cmnd[14] = bio_get_streamid(bio); + if (rq->cmd_flags & REQ_META) { + cmd->cmnd[0] = ATA_16; + cmd->cmnd[1] = (0x6 << 1) | 1; + cmd->cmnd[2] = 0x0e; + cmd->cmnd[3] = bio_get_streamid(bio); + cmd->cmnd[4] = ATA_SUBCMD_REP_ZONES; + cmd->cmnd[5] = ((nr_bytes / 512) >> 8) & 0xff; + cmd->cmnd[6] = (nr_bytes / 512) & 0xff; + + _lba_to_cmd_ata(&cmd->cmnd[7], sector); + + cmd->cmnd[13] = 1 << 6; + cmd->cmnd[14] = ATA_CMD_ZONE_MAN_IN; + } else { + cmd->cmnd[0] = ZBC_REPORT_ZONES; + cmd->cmnd[1] = ZBC_REPORT_OPT; + put_unaligned_be64(sector, &cmd->cmnd[2]); + put_unaligned_be32(nr_bytes, &cmd->cmnd[10]); + cmd->cmnd[14] = bio_get_streamid(bio); + } cmd->sc_data_direction = DMA_FROM_DEVICE; cmd->sdb.length = nr_bytes; cmd->transfersize = sdp->sector_size; @@ -1207,14 +1233,28 @@ static int sd_setup_zoned_cmnd(struct scsi_cmnd *cmd) memset(cmd->cmnd, 0, cmd->cmd_len); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); - cmd->cmnd[0] = ZBC_ACTION; - cmd->cmnd[1] = ZBC_SA_ZONE_OPEN; - if (rq->cmd_flags & REQ_CLOSE_ZONE) - cmd->cmnd[1] = ZBC_SA_ZONE_CLOSE; - if (rq->cmd_flags & REQ_RESET_ZONE) - cmd->cmnd[1] = ZBC_SA_RESET_WP; - cmd->cmnd[14] = allbit; - put_unaligned_be64(sector, &cmd->cmnd[2]); + if (rq->cmd_flags & REQ_META) { + cmd->cmnd[0] = ATA_16; + cmd->cmnd[1] = (3 << 1) | 1; + cmd->cmnd[3] = allbit; + cmd->cmnd[4] = ATA_SUBCMD_OPEN_ZONES; + if (rq->cmd_flags & REQ_CLOSE_ZONE) + cmd->cmnd[4] = ATA_SUBCMD_CLOSE_ZONES; + if (rq->cmd_flags & REQ_RESET_ZONE) + cmd->cmnd[4] = ATA_SUBCMD_RESET_WP; + _lba_to_cmd_ata(&cmd->cmnd[7], sector); + cmd->cmnd[13] = 1 << 6; + cmd->cmnd[14] = ATA_CMD_ZONE_MAN_OUT; + } else { + cmd->cmnd[0] = ZBC_ACTION; + cmd->cmnd[1] = ZBC_SA_ZONE_OPEN; + if (rq->cmd_flags & REQ_CLOSE_ZONE) + cmd->cmnd[1] = ZBC_SA_ZONE_CLOSE; + if (rq->cmd_flags & REQ_RESET_ZONE) + cmd->cmnd[1] = ZBC_SA_RESET_WP; + cmd->cmnd[14] = allbit; + put_unaligned_be64(sector, &cmd->cmnd[2]); + } cmd->transfersize = 0; cmd->underflow = 0; cmd->allowed = SD_MAX_RETRIES; @@ -2812,7 +2852,7 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) { unsigned char *buffer; u16 rot; - const int vpd_len = 64; + const int vpd_len = 512; buffer = kmalloc(vpd_len, GFP_KERNEL); @@ -2839,6 +2879,22 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) * Any subsequent reads will be zero'd. */ sdkp->device->zabc = 1; + } else { + unsigned char cmd[16] = { 0 }; + + cmd[0] = ATA_16; + cmd[1] = (4 << 1) | 1; + cmd[2] = 0xe; + cmd[6] = 0x1; + cmd[8] = 0x1; + cmd[14] = ATA_CMD_ID_ATA; + + if (scsi_execute_req(sdkp->device, cmd, DMA_FROM_DEVICE, buffer, + vpd_len, NULL, 30 * HZ, 3, NULL)) + goto out; + + if (ata_drive_zac_ha((u16 *)buffer)) + sdkp->device->zabc = 1; } out: