From patchwork Thu Aug 19 15:49:01 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Martin K. Petersen" X-Patchwork-Id: 62184 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 68FD1B70E8 for ; Fri, 20 Aug 2010 01:51:49 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751800Ab0HSPv1 (ORCPT ); Thu, 19 Aug 2010 11:51:27 -0400 Received: from rcsinet10.oracle.com ([148.87.113.121]:35412 "EHLO rcsinet10.oracle.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751777Ab0HSPv0 (ORCPT ); Thu, 19 Aug 2010 11:51:26 -0400 Received: from acsinet15.oracle.com (acsinet15.oracle.com [141.146.126.227]) by rcsinet10.oracle.com (Switch-3.4.2/Switch-3.4.2) with ESMTP id o7JFpHkr021494 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 19 Aug 2010 15:51:19 GMT Received: from acsmt353.oracle.com (acsmt353.oracle.com [141.146.40.153]) by acsinet15.oracle.com (Switch-3.4.2/Switch-3.4.1) with ESMTP id o7JDkpgx014638; Thu, 19 Aug 2010 15:51:15 GMT Received: from abhmt012.oracle.com by acsmt354.oracle.com with ESMTP id 512368091282232975; Thu, 19 Aug 2010 08:49:35 -0700 Received: from groovelator.mkp.net (/209.217.122.111) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 19 Aug 2010 08:49:33 -0700 From: "Martin K. Petersen" To: linux-ide@vger.kernel.org, linux-scsi@vger.kernel.org, hch@lst.de Cc: "Martin K. Petersen" Subject: [PATCH 6/6] sd: Update thin provisioning support Date: Thu, 19 Aug 2010 11:49:01 -0400 Message-Id: <1282232941-9910-7-git-send-email-martin.petersen@oracle.com> X-Mailer: git-send-email 1.7.2.1 In-Reply-To: <1282232941-9910-1-git-send-email-martin.petersen@oracle.com> References: <1282232941-9910-1-git-send-email-martin.petersen@oracle.com> Sender: linux-ide-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ide@vger.kernel.org Add support for the Thin Provisioning VPD page and use the TPU and TPWS bits to switch between UNMAP and WRITE SAME(16) for discards. Signed-off-by: Martin K. Petersen --- drivers/scsi/sd.c | 40 +++++++++++++++++++++++++++++++++++----- drivers/scsi/sd.h | 2 ++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8802e48..7d6a61c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1991,14 +1991,19 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) lba_count = get_unaligned_be32(&buffer[20]); desc_count = get_unaligned_be32(&buffer[24]); - if (lba_count) { + if (sdkp->tpu && desc_count && lba_count) + sdkp->unmap = 1; + else if (!sdkp->tpws) { + sd_printk(KERN_ERR, sdkp, "Thin provisioning is " \ + "enabled but neither TPU, nor TPWS are " \ + "set. Disabling discard!\n"); + goto out; + } + + if (lba_count) q->limits.max_discard_sectors = lba_count * sector_sz >> 9; - if (desc_count) - sdkp->unmap = 1; - } - granularity = get_unaligned_be32(&buffer[28]); if (granularity) @@ -2039,6 +2044,30 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp) kfree(buffer); } +/** + * sd_read_thin_provisioning - Query thin provisioning VPD page + * @disk: disk to query + */ +static void sd_read_thin_provisioning(struct scsi_disk *sdkp) +{ + unsigned char *buffer; + const int vpd_len = 8; + + if (sdkp->thin_provisioning == 0) + return; + + buffer = kmalloc(vpd_len, GFP_KERNEL); + + if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len)) + goto out; + + sdkp->tpu = (buffer[5] >> 7) & 1; /* UNMAP */ + sdkp->tpws = (buffer[5] >> 6) & 1; /* WRITE SAME(16) with UNMAP */ + + out: + kfree(buffer); +} + static int sd_try_extended_inquiry(struct scsi_device *sdp) { /* @@ -2090,6 +2119,7 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_capacity(sdkp, buffer); if (sd_try_extended_inquiry(sdp)) { + sd_read_thin_provisioning(sdkp); sd_read_block_limits(sdkp); sd_read_block_characteristics(sdkp); } diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 43d3caf..9646062 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -62,6 +62,8 @@ struct scsi_disk { unsigned first_scan : 1; unsigned thin_provisioning : 1; unsigned unmap : 1; + unsigned tpws : 1; + unsigned tpu : 1; }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)