[kernel] r15547 - in dists/sid/linux-2.6/debian: . patches/features/all patches/series

Maximilian Attems maks at alioth.debian.org
Sat Apr 24 00:06:37 UTC 2010


Author: maks
Date: Sat Apr 24 00:06:11 2010
New Revision: 15547

Log:
add libata TRIM support

landed in 2.6.33, all patches also sent to stable.

Added:
   dists/sid/linux-2.6/debian/patches/features/all/SCSI-Correctly-handle-thin-provisioning-write-error.patch
   dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi-Add-missing-command-definitions.patch
   dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi_debug-Thin-provisioning-support.patch
   dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi_debug-fix-Thin-provisioning-support.patch
   dists/sid/linux-2.6/debian/patches/features/all/libata-Clarify-ata_set_lba_range_entries-function.patch
   dists/sid/linux-2.6/debian/patches/features/all/libata-Report-zeroed-read-after-TRIM-and-max-discard.patch
   dists/sid/linux-2.6/debian/patches/features/all/libata-add-translation-for-SCSI-WRITE-SAME-aka-TRIM-.patch
   dists/sid/linux-2.6/debian/patches/features/all/libata-use-the-WRITE_SAME_16-define.patch
Modified:
   dists/sid/linux-2.6/debian/changelog
   dists/sid/linux-2.6/debian/patches/series/12

Modified: dists/sid/linux-2.6/debian/changelog
==============================================================================
--- dists/sid/linux-2.6/debian/changelog	Fri Apr 23 17:39:32 2010	(r15546)
+++ dists/sid/linux-2.6/debian/changelog	Sat Apr 24 00:06:11 2010	(r15547)
@@ -42,6 +42,7 @@
   * Add EC path for Thinkpad X100.
   * Bump ABI to 5, apply:
     - hrtimer: Tune hrtimer_interrupt hang logic
+  * Add libata TRIM support.
 
   [ dann frazier ]
   * Add DRBD backport

Added: dists/sid/linux-2.6/debian/patches/features/all/SCSI-Correctly-handle-thin-provisioning-write-error.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/SCSI-Correctly-handle-thin-provisioning-write-error.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,31 @@
+From d8705f11d89cfabf4a9f0ea234d4809b22abb33e Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen at oracle.com>
+Date: Thu, 26 Nov 2009 12:00:41 -0500
+Subject: [PATCH] [SCSI] Correctly handle thin provisioning write error
+
+A thin provisioned device may temporarily be out of sufficient
+allocation units to fulfill a write request.  In that case it will
+return a space allocation in progress error.  Wait a bit and retry the
+write.
+
+Signed-off-by: Martin K. Petersen <martin.petersen at oracle.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+---
+ drivers/scsi/scsi_lib.c |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+index e495d38..d892768 100644
+--- a/drivers/scsi/scsi_lib.c
++++ b/drivers/scsi/scsi_lib.c
+@@ -859,6 +859,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
+ 				case 0x07: /* operation in progress */
+ 				case 0x08: /* Long write in progress */
+ 				case 0x09: /* self test in progress */
++				case 0x14: /* space allocation in progress */
+ 					action = ACTION_DELAYED_RETRY;
+ 					break;
+ 				default:
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi-Add-missing-command-definitions.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi-Add-missing-command-definitions.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,62 @@
+From f57e4502cea471c69782d4790c71d8414ab49a9d Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen at oracle.com>
+Date: Thu, 15 Oct 2009 14:43:23 -0400
+Subject: [PATCH] [SCSI] scsi: Add missing command definitions
+
+Add definitions for UNMAP, WRITE SAME{16,32} and GET LBA STATUS
+commands.
+
+Signed-off-by: Martin K. Petersen <martin.petersen at oracle.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+---
+ drivers/scsi/constants.c |    1 +
+ include/scsi/scsi.h      |    4 ++++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
+index 63abb06..9129bcf 100644
+--- a/drivers/scsi/constants.c
++++ b/drivers/scsi/constants.c
+@@ -141,6 +141,7 @@ static const struct value_name_pair serv_out12_arr[] = {
+ static const struct value_name_pair serv_in16_arr[] = {
+ 	{0x10, "Read capacity(16)"},
+ 	{0x11, "Read long(16)"},
++	{0x12, "Get LBA status"},
+ };
+ #define SERV_IN16_SZ ARRAY_SIZE(serv_in16_arr)
+ 
+diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
+index 34c46ab..8b4deca 100644
+--- a/include/scsi/scsi.h
++++ b/include/scsi/scsi.h
+@@ -94,6 +94,7 @@ struct scsi_cmnd;
+ #define WRITE_LONG            0x3f
+ #define CHANGE_DEFINITION     0x40
+ #define WRITE_SAME            0x41
++#define UNMAP		      0x42
+ #define READ_TOC              0x43
+ #define LOG_SELECT            0x4c
+ #define LOG_SENSE             0x4d
+@@ -122,9 +123,11 @@ struct scsi_cmnd;
+ #define READ_16               0x88
+ #define WRITE_16              0x8a
+ #define VERIFY_16	      0x8f
++#define WRITE_SAME_16	      0x93
+ #define SERVICE_ACTION_IN     0x9e
+ /* values for service action in */
+ #define	SAI_READ_CAPACITY_16  0x10
++#define SAI_GET_LBA_STATUS    0x12
+ /* values for maintenance in */
+ #define MI_REPORT_TARGET_PGS  0x0a
+ /* values for maintenance out */
+@@ -132,6 +135,7 @@ struct scsi_cmnd;
+ /* values for variable length command */
+ #define READ_32		      0x09
+ #define WRITE_32	      0x0b
++#define WRITE_SAME_32	      0x0d
+ 
+ /* Values for T10/04-262r7 */
+ #define	ATA_16		      0x85	/* 16-byte pass-thru */
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi_debug-Thin-provisioning-support.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi_debug-Thin-provisioning-support.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,553 @@
+From 44d9269481bb43df445adf464b06ff031e67d7ea Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen at oracle.com>
+Date: Thu, 15 Oct 2009 14:45:27 -0400
+Subject: [PATCH] [SCSI] scsi_debug: Thin provisioning support
+
+This version fixes 64-bit modulo on 32-bit as well as inadvertent map
+updates when TP was disabled.
+
+Implement support for thin provisioning in scsi_debug.  No actual memory
+de-allocation is taking place.  The intent is to emulate a thinly
+provisioned storage device, not to be one.
+
+There are four new module options:
+
+ - unmap_granularity specifies the granularity at which to track mapped
+   blocks (specified in number of logical blocks).  2048 (1 MB) is a
+   realistic value for disk arrays although some may have a finer
+   granularity.
+
+ - unmap_alignment specifies the first LBA which is naturally aligned on
+   an unmap_granularity boundary.
+
+ - unmap_max_desc specifies the maximum number of ranges that can be
+   unmapped using one UNMAP command.  If this is 0, only WRITE SAME is
+   supported and UNMAP will cause a check condition.
+
+ - unmap_max_blocks specifies the maximum number of blocks that can be
+   unmapped using a single UNMAP command.  Default is 0xffffffff.
+
+These parameters are reported in the new and extended block limits VPD.
+
+If unmap_granularity is specified the device is tagged as thin
+provisioning capable in READ CAPACITY(16).  A bitmap is allocated to
+track whether blocks are mapped or not.  A WRITE request will cause a
+block to be mapped.  So will WRITE SAME unless the UNMAP bit is set.
+
+Blocks can be unmapped using either WRITE SAME or UNMAP.  No accounting
+is done to track partial blocks.  This means that only whole blocks will
+be marked free.  This is how the array people tell me their firmwares
+work.
+
+GET LBA STATUS is also supported.  This command reports whether a block
+is mapped or not, and how long the adjoining mapped/unmapped extent is.
+
+The block allocation bitmap can also be viewed from user space via:
+
+	/sys/bus/pseudo/drivers/scsi_debug/map
+
+Signed-off-by: Martin K. Petersen <martin.petersen at oracle.com>
+Acked-by: Douglas Gilbert <dgilbert at interlog.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+---
+ drivers/scsi/scsi_debug.c |  338 ++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 335 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index c4103be..cb4bf16 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -44,6 +44,8 @@
+ 
+ #include <net/checksum.h>
+ 
++#include <asm/unaligned.h>
++
+ #include <scsi/scsi.h>
+ #include <scsi/scsi_cmnd.h>
+ #include <scsi/scsi_device.h>
+@@ -105,6 +107,10 @@ static const char * scsi_debug_version_date = "20070104";
+ #define DEF_ATO 1
+ #define DEF_PHYSBLK_EXP 0
+ #define DEF_LOWEST_ALIGNED 0
++#define DEF_UNMAP_MAX_BLOCKS 0
++#define DEF_UNMAP_MAX_DESC 0
++#define DEF_UNMAP_GRANULARITY 0
++#define DEF_UNMAP_ALIGNMENT 0
+ 
+ /* bit mask values for scsi_debug_opts */
+ #define SCSI_DEBUG_OPT_NOISE   1
+@@ -162,6 +168,10 @@ static int scsi_debug_guard = DEF_GUARD;
+ static int scsi_debug_ato = DEF_ATO;
+ static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
+ static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
++static int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
++static int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
++static int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
++static int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
+ 
+ static int scsi_debug_cmnd_count = 0;
+ 
+@@ -223,7 +233,9 @@ static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
+ 
+ static unsigned char * fake_storep;	/* ramdisk storage */
+ static unsigned char *dif_storep;	/* protection info */
++static void *map_storep;		/* provisioning map */
+ 
++static unsigned long map_size;
+ static int num_aborts = 0;
+ static int num_dev_resets = 0;
+ static int num_bus_resets = 0;
+@@ -317,6 +329,7 @@ static void get_data_transfer_info(unsigned char *cmd,
+ 			(u32)cmd[28] << 24;
+ 		break;
+ 
++	case WRITE_SAME_16:
+ 	case WRITE_16:
+ 	case READ_16:
+ 		*lba = (u64)cmd[9] | (u64)cmd[8] << 8 |
+@@ -335,6 +348,7 @@ static void get_data_transfer_info(unsigned char *cmd,
+ 		*num = (u32)cmd[9] | (u32)cmd[8] << 8 | (u32)cmd[7] << 16 |
+ 			(u32)cmd[6] << 24;
+ 		break;
++	case WRITE_SAME:
+ 	case WRITE_10:
+ 	case READ_10:
+ 	case XDWRITEREAD_10:
+@@ -691,6 +705,29 @@ static int inquiry_evpd_b0(unsigned char * arr)
+ 		arr[6] = (sdebug_store_sectors >> 8) & 0xff;
+ 		arr[7] = sdebug_store_sectors & 0xff;
+ 	}
++
++	if (scsi_debug_unmap_max_desc) {
++		unsigned int blocks;
++
++		if (scsi_debug_unmap_max_blocks)
++			blocks = scsi_debug_unmap_max_blocks;
++		else
++			blocks = 0xffffffff;
++
++		put_unaligned_be32(blocks, &arr[16]);
++		put_unaligned_be32(scsi_debug_unmap_max_desc, &arr[20]);
++	}
++
++	if (scsi_debug_unmap_alignment) {
++		put_unaligned_be32(scsi_debug_unmap_alignment, &arr[28]);
++		arr[28] |= 0x80; /* UGAVALID */
++	}
++
++	if (scsi_debug_unmap_granularity) {
++		put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
++		return 0x3c; /* Mandatory page length for thin provisioning */
++	}
++
+ 	return sizeof(vpdb0_data);
+ }
+ 
+@@ -974,6 +1011,10 @@ static int resp_readcap16(struct scsi_cmnd * scp,
+ 	arr[11] = scsi_debug_sector_size & 0xff;
+ 	arr[13] = scsi_debug_physblk_exp & 0xf;
+ 	arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
++
++	if (scsi_debug_unmap_granularity)
++		arr[14] |= 0x80; /* TPE */
++
+ 	arr[15] = scsi_debug_lowest_aligned & 0xff;
+ 
+ 	if (scsi_debug_dif) {
+@@ -1887,6 +1928,70 @@ out:
+ 	return ret;
+ }
+ 
++static unsigned int map_state(sector_t lba, unsigned int *num)
++{
++	unsigned int granularity, alignment, mapped;
++	sector_t block, next, end;
++
++	granularity = scsi_debug_unmap_granularity;
++	alignment = granularity - scsi_debug_unmap_alignment;
++	block = lba + alignment;
++	do_div(block, granularity);
++
++	mapped = test_bit(block, map_storep);
++
++	if (mapped)
++		next = find_next_zero_bit(map_storep, map_size, block);
++	else
++		next = find_next_bit(map_storep, map_size, block);
++
++	end = next * granularity - scsi_debug_unmap_alignment;
++	*num = end - lba;
++
++	return mapped;
++}
++
++static void map_region(sector_t lba, unsigned int len)
++{
++	unsigned int granularity, alignment;
++	sector_t end = lba + len;
++
++	granularity = scsi_debug_unmap_granularity;
++	alignment = granularity - scsi_debug_unmap_alignment;
++
++	while (lba < end) {
++		sector_t block, rem;
++
++		block = lba + alignment;
++		rem = do_div(block, granularity);
++
++		set_bit(block, map_storep);
++
++		lba += granularity - rem;
++	}
++}
++
++static void unmap_region(sector_t lba, unsigned int len)
++{
++	unsigned int granularity, alignment;
++	sector_t end = lba + len;
++
++	granularity = scsi_debug_unmap_granularity;
++	alignment = granularity - scsi_debug_unmap_alignment;
++
++	while (lba < end) {
++		sector_t block, rem;
++
++		block = lba + alignment;
++		rem = do_div(block, granularity);
++
++		if (rem == 0 && lba + granularity <= end)
++			clear_bit(block, map_storep);
++
++		lba += granularity - rem;
++	}
++}
++
+ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
+ 		      unsigned int num, struct sdebug_dev_info *devip,
+ 		      u32 ei_lba)
+@@ -1910,6 +2015,8 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
+ 
+ 	write_lock_irqsave(&atomic_rw, iflags);
+ 	ret = do_device_access(SCpnt, devip, lba, num, 1);
++	if (scsi_debug_unmap_granularity)
++		map_region(lba, num);
+ 	write_unlock_irqrestore(&atomic_rw, iflags);
+ 	if (-1 == ret)
+ 		return (DID_ERROR << 16);
+@@ -1917,9 +2024,143 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
+ 		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+ 		printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, "
+ 		       " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
++
++	return 0;
++}
++
++static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba,
++		      unsigned int num, struct sdebug_dev_info *devip,
++			   u32 ei_lba, unsigned int unmap)
++{
++	unsigned long iflags;
++	unsigned long long i;
++	int ret;
++
++	ret = check_device_access_params(devip, lba, num);
++	if (ret)
++		return ret;
++
++	write_lock_irqsave(&atomic_rw, iflags);
++
++	if (unmap && scsi_debug_unmap_granularity) {
++		unmap_region(lba, num);
++		goto out;
++	}
++
++	/* Else fetch one logical block */
++	ret = fetch_to_dev_buffer(scmd,
++				  fake_storep + (lba * scsi_debug_sector_size),
++				  scsi_debug_sector_size);
++
++	if (-1 == ret) {
++		write_unlock_irqrestore(&atomic_rw, iflags);
++		return (DID_ERROR << 16);
++	} else if ((ret < (num * scsi_debug_sector_size)) &&
++		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
++		printk(KERN_INFO "scsi_debug: write same: cdb indicated=%u, "
++		       " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret);
++
++	/* Copy first sector to remaining blocks */
++	for (i = 1 ; i < num ; i++)
++		memcpy(fake_storep + ((lba + i) * scsi_debug_sector_size),
++		       fake_storep + (lba * scsi_debug_sector_size),
++		       scsi_debug_sector_size);
++
++	if (scsi_debug_unmap_granularity)
++		map_region(lba, num);
++out:
++	write_unlock_irqrestore(&atomic_rw, iflags);
++
+ 	return 0;
+ }
+ 
++struct unmap_block_desc {
++	__be64	lba;
++	__be32	blocks;
++	__be32	__reserved;
++};
++
++static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip)
++{
++	unsigned char *buf;
++	struct unmap_block_desc *desc;
++	unsigned int i, payload_len, descriptors;
++	int ret;
++
++	ret = check_readiness(scmd, 1, devip);
++	if (ret)
++		return ret;
++
++	payload_len = get_unaligned_be16(&scmd->cmnd[7]);
++	BUG_ON(scsi_bufflen(scmd) != payload_len);
++
++	descriptors = (payload_len - 8) / 16;
++
++	buf = kmalloc(scsi_bufflen(scmd), GFP_ATOMIC);
++	if (!buf)
++		return check_condition_result;
++
++	scsi_sg_copy_to_buffer(scmd, buf, scsi_bufflen(scmd));
++
++	BUG_ON(get_unaligned_be16(&buf[0]) != payload_len - 2);
++	BUG_ON(get_unaligned_be16(&buf[2]) != descriptors * 16);
++
++	desc = (void *)&buf[8];
++
++	for (i = 0 ; i < descriptors ; i++) {
++		unsigned long long lba = get_unaligned_be64(&desc[i].lba);
++		unsigned int num = get_unaligned_be32(&desc[i].blocks);
++
++		ret = check_device_access_params(devip, lba, num);
++		if (ret)
++			goto out;
++
++		unmap_region(lba, num);
++	}
++
++	ret = 0;
++
++out:
++	kfree(buf);
++
++	return ret;
++}
++
++#define SDEBUG_GET_LBA_STATUS_LEN 32
++
++static int resp_get_lba_status(struct scsi_cmnd * scmd,
++			       struct sdebug_dev_info * devip)
++{
++	unsigned long long lba;
++	unsigned int alloc_len, mapped, num;
++	unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN];
++	int ret;
++
++	ret = check_readiness(scmd, 1, devip);
++	if (ret)
++		return ret;
++
++	lba = get_unaligned_be64(&scmd->cmnd[2]);
++	alloc_len = get_unaligned_be32(&scmd->cmnd[10]);
++
++	if (alloc_len < 24)
++		return 0;
++
++	ret = check_device_access_params(devip, lba, 1);
++	if (ret)
++		return ret;
++
++	mapped = map_state(lba, &num);
++
++	memset(arr, 0, SDEBUG_GET_LBA_STATUS_LEN);
++	put_unaligned_be32(16, &arr[0]);	/* Parameter Data Length */
++	put_unaligned_be64(lba, &arr[8]);	/* LBA */
++	put_unaligned_be32(num, &arr[16]);	/* Number of blocks */
++	arr[20] = !mapped;			/* mapped = 0, unmapped = 1 */
++
++	return fill_from_dev_buffer(scmd, arr, SDEBUG_GET_LBA_STATUS_LEN);
++}
++
+ #define SDEBUG_RLUN_ARR_SZ 256
+ 
+ static int resp_report_luns(struct scsi_cmnd * scp,
+@@ -2430,6 +2671,10 @@ module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
+ module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
+ module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
+ module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
++module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
++module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
++module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
++module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
+ 
+ MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
+ MODULE_DESCRIPTION("SCSI debug adapter driver");
+@@ -2458,6 +2703,10 @@ MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
+ MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
+ MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
+ MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
++MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0)");
++MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=0)");
++MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=0)");
++MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
+ 
+ static char sdebug_info[256];
+ 
+@@ -2816,6 +3065,23 @@ static ssize_t sdebug_ato_show(struct device_driver *ddp, char *buf)
+ }
+ DRIVER_ATTR(ato, S_IRUGO, sdebug_ato_show, NULL);
+ 
++static ssize_t sdebug_map_show(struct device_driver *ddp, char *buf)
++{
++	ssize_t count;
++
++	if (scsi_debug_unmap_granularity == 0)
++		return scnprintf(buf, PAGE_SIZE, "0-%u\n",
++				 sdebug_store_sectors);
++
++	count = bitmap_scnlistprintf(buf, PAGE_SIZE, map_storep, map_size);
++
++	buf[count++] = '\n';
++	buf[count++] = 0;
++
++	return count;
++}
++DRIVER_ATTR(map, S_IRUGO, sdebug_map_show, NULL);
++
+ 
+ /* Note: The following function creates attribute files in the
+    /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
+@@ -2847,11 +3113,13 @@ static int do_create_driverfs_files(void)
+ 	ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dif);
+ 	ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_guard);
+ 	ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ato);
++	ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_map);
+ 	return ret;
+ }
+ 
+ static void do_remove_driverfs_files(void)
+ {
++	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_map);
+ 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ato);
+ 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_guard);
+ 	driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dif);
+@@ -2989,6 +3257,36 @@ static int __init scsi_debug_init(void)
+ 		memset(dif_storep, 0xff, dif_size);
+ 	}
+ 
++	if (scsi_debug_unmap_granularity) {
++		unsigned int map_bytes;
++
++		if (scsi_debug_unmap_granularity < scsi_debug_unmap_alignment) {
++			printk(KERN_ERR
++			       "%s: ERR: unmap_granularity < unmap_alignment\n",
++			       __func__);
++			return -EINVAL;
++		}
++
++		map_size = (sdebug_store_sectors / scsi_debug_unmap_granularity);
++		map_bytes = map_size >> 3;
++		map_storep = vmalloc(map_bytes);
++
++		printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n",
++		       map_size);
++
++		if (map_storep == NULL) {
++			printk(KERN_ERR "scsi_debug_init: out of mem. (MAP)\n");
++			ret = -ENOMEM;
++			goto free_vm;
++		}
++
++		memset(map_storep, 0x0, map_bytes);
++
++		/* Map first 1KB for partition table */
++		if (scsi_debug_num_parts)
++			map_region(0, 2);
++	}
++
+ 	ret = device_register(&pseudo_primary);
+ 	if (ret < 0) {
+ 		printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
+@@ -3041,6 +3339,8 @@ bus_unreg:
+ dev_unreg:
+ 	device_unregister(&pseudo_primary);
+ free_vm:
++	if (map_storep)
++		vfree(map_storep);
+ 	if (dif_storep)
+ 		vfree(dif_storep);
+ 	vfree(fake_storep);
+@@ -3167,6 +3467,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
+ 	int inj_dif = 0;
+ 	int inj_dix = 0;
+ 	int delay_override = 0;
++	int unmap = 0;
+ 
+ 	scsi_set_resid(SCpnt, 0);
+ 	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
+@@ -3272,13 +3573,21 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
+ 		errsts = resp_readcap(SCpnt, devip);
+ 		break;
+ 	case SERVICE_ACTION_IN:
+-		if (SAI_READ_CAPACITY_16 != cmd[1]) {
++		if (cmd[1] == SAI_READ_CAPACITY_16)
++			errsts = resp_readcap16(SCpnt, devip);
++		else if (cmd[1] == SAI_GET_LBA_STATUS) {
++
++			if (scsi_debug_unmap_max_desc == 0) {
++				mk_sense_buffer(devip, ILLEGAL_REQUEST,
++						INVALID_COMMAND_OPCODE, 0);
++				errsts = check_condition_result;
++			} else
++				errsts = resp_get_lba_status(SCpnt, devip);
++		} else {
+ 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
+ 					INVALID_OPCODE, 0);
+ 			errsts = check_condition_result;
+-			break;
+ 		}
+-		errsts = resp_readcap16(SCpnt, devip);
+ 		break;
+ 	case MAINTENANCE_IN:
+ 		if (MI_REPORT_TARGET_PGS != cmd[1]) {
+@@ -3378,6 +3687,29 @@ write:
+ 			errsts = illegal_condition_result;
+ 		}
+ 		break;
++	case WRITE_SAME_16:
++		if (cmd[1] & 0x8)
++			unmap = 1;
++		/* fall through */
++	case WRITE_SAME:
++		errsts = check_readiness(SCpnt, 0, devip);
++		if (errsts)
++			break;
++		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
++		errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap);
++		break;
++	case UNMAP:
++		errsts = check_readiness(SCpnt, 0, devip);
++		if (errsts)
++			break;
++
++		if (scsi_debug_unmap_max_desc == 0) {
++			mk_sense_buffer(devip, ILLEGAL_REQUEST,
++					INVALID_COMMAND_OPCODE, 0);
++			errsts = check_condition_result;
++		} else
++			errsts = resp_unmap(SCpnt, devip);
++		break;
+ 	case MODE_SENSE:
+ 	case MODE_SENSE_10:
+ 		errsts = resp_mode_sense(SCpnt, target, devip);
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi_debug-fix-Thin-provisioning-support.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/SCSI-scsi_debug-fix-Thin-provisioning-support.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,57 @@
+From 1e49f78505b2c4df193614d774bf46d067cda7d8 Mon Sep 17 00:00:00 2001
+From: Douglas Gilbert <dgilbert at interlog.com>
+Date: Thu, 29 Oct 2009 01:48:31 -0400
+Subject: [PATCH] [SCSI] scsi_debug: fix Thin provisioning support
+
+While testing scsi_debug with these patches I found a
+problem with the Block Limits VPD page function. The
+length returned by the inquiry_evpd_b0() function was
+too short. A patch to fix that and a cosmetic change
+(that the form factor of scsi_debug is less than 1.8
+inches) is attached.
+
+Signed-off-by: Douglas Gilbert <dgilbert at interlog.com>
+Signed-off-by: James Bottomley <James.Bottomley at suse.de>
+---
+ drivers/scsi/scsi_debug.c |   13 +++++++++----
+ 1 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
+index cb4bf16..0b575c8 100644
+--- a/drivers/scsi/scsi_debug.c
++++ b/drivers/scsi/scsi_debug.c
+@@ -685,10 +685,12 @@ static int inquiry_evpd_89(unsigned char * arr)
+ }
+ 
+ 
++/* Block limits VPD page (SBC-3) */
+ static unsigned char vpdb0_data[] = {
+-	/* from 4th byte */ 0,0,0,4,
+-	0,0,0x4,0,
+-	0,0,0,64,
++	/* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64,
++	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
++	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
++	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ };
+ 
+ static int inquiry_evpd_b0(unsigned char * arr)
+@@ -731,11 +733,14 @@ static int inquiry_evpd_b0(unsigned char * arr)
+ 	return sizeof(vpdb0_data);
+ }
+ 
++/* Block device characteristics VPD page (SBC-3) */
+ static int inquiry_evpd_b1(unsigned char *arr)
+ {
+ 	memset(arr, 0, 0x3c);
+ 	arr[0] = 0;
+-	arr[1] = 1;
++	arr[1] = 1;	/* non rotating medium (e.g. solid state) */
++	arr[2] = 0;
++	arr[3] = 5;	/* less than 1.8" */
+ 
+ 	return 0x3c;
+ }
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/libata-Clarify-ata_set_lba_range_entries-function.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/libata-Clarify-ata_set_lba_range_entries-function.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,74 @@
+From d0634c4aea0b80447cbdc4c0db285004b860c455 Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen at oracle.com>
+Date: Thu, 26 Nov 2009 12:00:43 -0500
+Subject: [PATCH] libata: Clarify ata_set_lba_range_entries function
+
+ata_set_lba_range_entries used the variable max for two different things
+which was confusing.  Make the function take a buffer size in bytes as
+argument and return the used buffer size upon completion.
+
+Signed-off-by: Martin K. Petersen <martin.petersen at oracle.com>
+Signed-off-by: Jeff Garzik <jgarzik at redhat.com>
+---
+ drivers/ata/libata-scsi.c |    2 +-
+ include/linux/ata.h       |   20 ++++++++++----------
+ 2 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index e1e186b..62e6b9e 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -2972,7 +2972,7 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
+ 		goto invalid_fld;
+ 
+ 	buf = page_address(sg_page(scsi_sglist(scmd)));
+-	size = ata_set_lba_range_entries(buf, 512 / 8, block, n_block);
++	size = ata_set_lba_range_entries(buf, 512, block, n_block);
+ 
+ 	tf->protocol = ATA_PROT_DMA;
+ 	tf->hob_feature = 0;
+diff --git a/include/linux/ata.h b/include/linux/ata.h
+index dfa2298..38a6948 100644
+--- a/include/linux/ata.h
++++ b/include/linux/ata.h
+@@ -982,17 +982,17 @@ static inline void ata_id_to_hd_driveid(u16 *id)
+ }
+ 
+ /*
+- * Write up to 'max' LBA Range Entries to the buffer that will cover the
+- * extent from sector to sector + count.  This is used for TRIM and for
+- * ADD LBA(S) TO NV CACHE PINNED SET.
++ * Write LBA Range Entries to the buffer that will cover the extent from
++ * sector to sector + count.  This is used for TRIM and for ADD LBA(S)
++ * TO NV CACHE PINNED SET.
+  */
+-static inline unsigned ata_set_lba_range_entries(void *_buffer, unsigned max,
+-						u64 sector, unsigned long count)
++static inline unsigned ata_set_lba_range_entries(void *_buffer,
++		unsigned buf_size, u64 sector, unsigned long count)
+ {
+ 	__le64 *buffer = _buffer;
+-	unsigned i = 0;
++	unsigned i = 0, used_bytes;
+ 
+-	while (i < max) {
++	while (i < buf_size / 8 ) { /* 6-byte LBA + 2-byte range per entry */
+ 		u64 entry = sector |
+ 			((u64)(count > 0xffff ? 0xffff : count) << 48);
+ 		buffer[i++] = __cpu_to_le64(entry);
+@@ -1002,9 +1002,9 @@ static inline unsigned ata_set_lba_range_entries(void *_buffer, unsigned max,
+ 		sector += 0xffff;
+ 	}
+ 
+-	max = ALIGN(i * 8, 512);
+-	memset(buffer + i, 0, max - i * 8);
+-	return max;
++	used_bytes = ALIGN(i * 8, 512);
++	memset(buffer + i, 0, used_bytes - i * 8);
++	return used_bytes;
+ }
+ 
+ static inline int is_multi_taskfile(struct ata_taskfile *tf)
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/libata-Report-zeroed-read-after-TRIM-and-max-discard.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/libata-Report-zeroed-read-after-TRIM-and-max-discard.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,82 @@
+From e78db4dfb1355a895f7ea50133b702b55b8ed184 Mon Sep 17 00:00:00 2001
+From: Martin K. Petersen <martin.petersen at oracle.com>
+Date: Thu, 26 Nov 2009 22:46:03 -0500
+Subject: [PATCH] libata: Report zeroed read after TRIM and max discard size
+
+Our current TRIM payload is a single sector that can accommodate 64 *
+65535 blocks being unmapped.  Report this value in the Block Limits
+Maximum Unmap LBA count field.
+
+If a storage device supports TRIM and the DRAT and RZAT bits are set,
+report TPRZ=1 in Read Capacity(16).
+
+Signed-off-by: Martin K. Petersen <martin.petersen at oracle.com>
+Signed-off-by: Jeff Garzik <jgarzik at redhat.com>
+---
+ drivers/ata/libata-scsi.c |   12 +++++++++---
+ include/linux/ata.h       |   11 +++++++++++
+ 2 files changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 340a616..e1e186b 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -2115,8 +2115,10 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
+ 	 * that we support some form of unmap - in thise case via WRITE SAME
+ 	 * with the unmap bit set.
+ 	 */
+-	if (ata_id_has_trim(args->id))
++	if (ata_id_has_trim(args->id)) {
++		put_unaligned_be32(65535 * 512 / 8, &rbuf[20]);
+ 		put_unaligned_be32(1, &rbuf[28]);
++	}
+ 
+ 	return 0;
+ }
+@@ -2411,8 +2413,12 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
+ 		rbuf[14] = (lowest_aligned >> 8) & 0x3f;
+ 		rbuf[15] = lowest_aligned;
+ 
+-		if (ata_id_has_trim(args->id))
+-			rbuf[14] |= 0x80;
++		if (ata_id_has_trim(args->id)) {
++			rbuf[14] |= 0x80; /* TPE */
++
++			if (ata_id_has_zero_after_trim(args->id))
++				rbuf[14] |= 0x40; /* TPRZ */
++		}
+ 	}
+ 
+ 	return 0;
+diff --git a/include/linux/ata.h b/include/linux/ata.h
+index e2595e8..dfa2298 100644
+--- a/include/linux/ata.h
++++ b/include/linux/ata.h
+@@ -75,6 +75,7 @@ enum {
+ 	ATA_ID_EIDE_DMA_TIME	= 66,
+ 	ATA_ID_EIDE_PIO		= 67,
+ 	ATA_ID_EIDE_PIO_IORDY	= 68,
++	ATA_ID_ADDITIONAL_SUPP	= 69,
+ 	ATA_ID_QUEUE_DEPTH	= 75,
+ 	ATA_ID_MAJOR_VER	= 80,
+ 	ATA_ID_COMMAND_SET_1	= 82,
+@@ -816,6 +817,16 @@ static inline int ata_id_has_trim(const u16 *id)
+ 	return 0;
+ }
+ 
++static inline int ata_id_has_zero_after_trim(const u16 *id)
++{
++	/* DSM supported, deterministic read, and read zero after trim set */
++	if (ata_id_has_trim(id) &&
++	    (id[ATA_ID_ADDITIONAL_SUPP] & 0x4020) == 0x4020)
++		return 1;
++
++	return 0;
++}
++
+ static inline int ata_id_current_chs_valid(const u16 *id)
+ {
+ 	/* For ATA-1 devices, if the INITIALIZE DEVICE PARAMETERS command
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/libata-add-translation-for-SCSI-WRITE-SAME-aka-TRIM-.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/libata-add-translation-for-SCSI-WRITE-SAME-aka-TRIM-.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,206 @@
+From 18f0f97850059303ed73b1f02084f55ca330a80c Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch at infradead.org>
+Date: Tue, 17 Nov 2009 10:00:47 -0500
+Subject: [PATCH] libata: add translation for SCSI WRITE SAME (aka TRIM support)
+
+Add support for the ATA TRIM command in libata.  We translate a WRITE SAME 16
+command with the unmap bit set into an ATA TRIM command and export enough
+information in READ CAPACITY 16 and the block limits EVPD page so that the new
+SCSI layer discard support will driver this for us.
+
+Note that I hardcode the WRITE_SAME_16 opcode for now as the patch to introduce
+the symbolic is not in 2.6.32 yet but only in the SCSI tree - as soon as it is
+merged we can fix it up to properly use the symbolic name.
+
+Signed-off-by: Christoph Hellwig <hch at lst.de>
+Signed-off-by: Jeff Garzik <jgarzik at redhat.com>
+---
+ drivers/ata/libata-scsi.c |   98 +++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/ata.h       |   13 ++++++
+ 2 files changed, 111 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 512a3ee..340a616 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -47,6 +47,7 @@
+ #include <linux/hdreg.h>
+ #include <linux/uaccess.h>
+ #include <linux/suspend.h>
++#include <asm/unaligned.h>
+ 
+ #include "libata.h"
+ 
+@@ -1963,6 +1964,7 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
+ 		0x80,	/* page 0x80, unit serial no page */
+ 		0x83,	/* page 0x83, device ident page */
+ 		0x89,	/* page 0x89, ata info page */
++		0xb0,	/* page 0xb0, block limits page */
+ 		0xb1,	/* page 0xb1, block device characteristics page */
+ 	};
+ 
+@@ -2084,6 +2086,41 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
+ 	return 0;
+ }
+ 
++static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
++{
++	u32 min_io_sectors;
++
++	rbuf[1] = 0xb0;
++	rbuf[3] = 0x3c;		/* required VPD size with unmap support */
++
++	/*
++	 * Optimal transfer length granularity.
++	 *
++	 * This is always one physical block, but for disks with a smaller
++	 * logical than physical sector size we need to figure out what the
++	 * latter is.
++	 */
++	if (ata_id_has_large_logical_sectors(args->id))
++		min_io_sectors = ata_id_logical_per_physical_sectors(args->id);
++	else
++		min_io_sectors = 1;
++	put_unaligned_be16(min_io_sectors, &rbuf[6]);
++
++	/*
++	 * Optimal unmap granularity.
++	 *
++	 * The ATA spec doesn't even know about a granularity or alignment
++	 * for the TRIM command.  We can leave away most of the unmap related
++	 * VPD page entries, but we have specifify a granularity to signal
++	 * that we support some form of unmap - in thise case via WRITE SAME
++	 * with the unmap bit set.
++	 */
++	if (ata_id_has_trim(args->id))
++		put_unaligned_be32(1, &rbuf[28]);
++
++	return 0;
++}
++
+ static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
+ {
+ 	int form_factor = ata_id_form_factor(args->id);
+@@ -2373,6 +2410,9 @@ static unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf)
+ 		rbuf[13] = log_per_phys;
+ 		rbuf[14] = (lowest_aligned >> 8) & 0x3f;
+ 		rbuf[15] = lowest_aligned;
++
++		if (ata_id_has_trim(args->id))
++			rbuf[14] |= 0x80;
+ 	}
+ 
+ 	return 0;
+@@ -2895,6 +2935,58 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
+ 	return 1;
+ }
+ 
++static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
++{
++	struct ata_taskfile *tf = &qc->tf;
++	struct scsi_cmnd *scmd = qc->scsicmd;
++	struct ata_device *dev = qc->dev;
++	const u8 *cdb = scmd->cmnd;
++	u64 block;
++	u32 n_block;
++	u32 size;
++	void *buf;
++
++	/* we may not issue DMA commands if no DMA mode is set */
++	if (unlikely(!dev->dma_mode))
++		goto invalid_fld;
++
++	if (unlikely(scmd->cmd_len < 16))
++		goto invalid_fld;
++	scsi_16_lba_len(cdb, &block, &n_block);
++
++	/* for now we only support WRITE SAME with the unmap bit set */
++	if (unlikely(!(cdb[1] & 0x8)))
++		goto invalid_fld;
++
++	/*
++	 * WRITE SAME always has a sector sized buffer as payload, this
++	 * should never be a multiple entry S/G list.
++	 */
++	if (!scsi_sg_count(scmd))
++		goto invalid_fld;
++
++	buf = page_address(sg_page(scsi_sglist(scmd)));
++	size = ata_set_lba_range_entries(buf, 512 / 8, block, n_block);
++
++	tf->protocol = ATA_PROT_DMA;
++	tf->hob_feature = 0;
++	tf->feature = ATA_DSM_TRIM;
++	tf->hob_nsect = (size / 512) >> 8;
++	tf->nsect = size / 512;
++	tf->command = ATA_CMD_DSM;
++	tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 |
++		     ATA_TFLAG_WRITE;
++
++	ata_qc_set_pc_nbytes(qc);
++
++	return 0;
++
++ invalid_fld:
++	ata_scsi_set_sense(scmd, ILLEGAL_REQUEST, 0x24, 0x00);
++	/* "Invalid field in cdb" */
++	return 1;
++}
++
+ /**
+  *	ata_get_xlat_func - check if SCSI to ATA translation is possible
+  *	@dev: ATA device
+@@ -2919,6 +3011,9 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
+ 	case WRITE_16:
+ 		return ata_scsi_rw_xlat;
+ 
++	case 0x93 /*WRITE_SAME_16*/:
++		return ata_scsi_write_same_xlat;
++
+ 	case SYNCHRONIZE_CACHE:
+ 		if (ata_try_flush_cache(dev))
+ 			return ata_scsi_flush_xlat;
+@@ -3108,6 +3203,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
+ 		case 0x89:
+ 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
+ 			break;
++		case 0xb0:
++			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b0);
++			break;
+ 		case 0xb1:
+ 			ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
+ 			break;
+diff --git a/include/linux/ata.h b/include/linux/ata.h
+index 4fb3573..e2595e8 100644
+--- a/include/linux/ata.h
++++ b/include/linux/ata.h
+@@ -87,6 +87,7 @@ enum {
+ 	ATA_ID_HW_CONFIG	= 93,
+ 	ATA_ID_SPG		= 98,
+ 	ATA_ID_LBA_CAPACITY_2	= 100,
++	ATA_ID_SECTOR_SIZE	= 106,
+ 	ATA_ID_LAST_LUN		= 126,
+ 	ATA_ID_DLF		= 128,
+ 	ATA_ID_CSFO		= 129,
+@@ -638,6 +639,18 @@ static inline int ata_id_flush_ext_enabled(const u16 *id)
+ 	return (id[ATA_ID_CFS_ENABLE_2] & 0x2400) == 0x2400;
+ }
+ 
++static inline int ata_id_has_large_logical_sectors(const u16 *id)
++{
++	if ((id[ATA_ID_SECTOR_SIZE] & 0xc000) != 0x4000)
++		return 0;
++	return id[ATA_ID_SECTOR_SIZE] & (1 << 13);
++}
++
++static inline u8 ata_id_logical_per_physical_sectors(const u16 *id)
++{
++	return id[ATA_ID_SECTOR_SIZE] & 0xf;
++}
++
+ static inline int ata_id_has_lba48(const u16 *id)
+ {
+ 	if ((id[ATA_ID_COMMAND_SET_2] & 0xC000) != 0x4000)
+-- 
+1.6.5
+

Added: dists/sid/linux-2.6/debian/patches/features/all/libata-use-the-WRITE_SAME_16-define.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux-2.6/debian/patches/features/all/libata-use-the-WRITE_SAME_16-define.patch	Sat Apr 24 00:06:11 2010	(r15547)
@@ -0,0 +1,30 @@
+From 0cdd6eb7e08fc39e9c906cc46b6ee9095c3077a9 Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch at lst.de>
+Date: Thu, 10 Dec 2009 10:36:01 +0100
+Subject: [PATCH] libata: use the WRITE_SAME_16 define
+
+Now that the scsi tree has hit mainline we can use the newly added WRITE_SAME_16
+define.
+
+Signed-off-by: Christoph Hellwig <hch at lst.de>
+Signed-off-by: Jeff Garzik <jgarzik at redhat.com>
+---
+ drivers/ata/libata-scsi.c |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 1683ebd..f4ea5a8 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -3022,7 +3022,7 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd)
+ 	case WRITE_16:
+ 		return ata_scsi_rw_xlat;
+ 
+-	case 0x93 /*WRITE_SAME_16*/:
++	case WRITE_SAME_16:
+ 		return ata_scsi_write_same_xlat;
+ 
+ 	case SYNCHRONIZE_CACHE:
+-- 
+1.6.5
+

Modified: dists/sid/linux-2.6/debian/patches/series/12
==============================================================================
--- dists/sid/linux-2.6/debian/patches/series/12	Fri Apr 23 17:39:32 2010	(r15546)
+++ dists/sid/linux-2.6/debian/patches/series/12	Sat Apr 24 00:06:11 2010	(r15547)
@@ -28,3 +28,11 @@
 + bugfix/all/libata-fix-accesses-at-LBA28-boundary.patch
 + bugfix/all/thinkpad-acpi-add-x100e.patch
 + bugfix/all/hrtimer-tune-hrtimer_interrupt-hang-logic.patch
++ features/all/libata-add-translation-for-SCSI-WRITE-SAME-aka-TRIM-.patch
++ features/all/SCSI-scsi-Add-missing-command-definitions.patch
++ features/all/SCSI-scsi_debug-Thin-provisioning-support.patch
++ features/all/libata-use-the-WRITE_SAME_16-define.patch
++ features/all/SCSI-scsi_debug-fix-Thin-provisioning-support.patch
++ features/all/SCSI-Correctly-handle-thin-provisioning-write-error.patch
++ features/all/libata-Report-zeroed-read-after-TRIM-and-max-discard.patch
++ features/all/libata-Clarify-ata_set_lba_range_entries-function.patch



More information about the Kernel-svn-changes mailing list