[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