aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/sd.c46
-rw-r--r--drivers/scsi/sd.h3
2 files changed, 44 insertions, 5 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8c9b275f71a7..0c4f89cfb7dc 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2039,14 +2039,24 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
2039 lba_count = get_unaligned_be32(&buffer[20]); 2039 lba_count = get_unaligned_be32(&buffer[20]);
2040 desc_count = get_unaligned_be32(&buffer[24]); 2040 desc_count = get_unaligned_be32(&buffer[24]);
2041 2041
2042 if (lba_count) { 2042 if (lba_count && desc_count) {
2043 q->limits.max_discard_sectors = 2043 if (sdkp->tpvpd && !sdkp->tpu)
2044 lba_count * sector_sz >> 9; 2044 sdkp->unmap = 0;
2045 2045 else
2046 if (desc_count)
2047 sdkp->unmap = 1; 2046 sdkp->unmap = 1;
2048 } 2047 }
2049 2048
2049 if (sdkp->tpvpd && !sdkp->tpu && !sdkp->tpws) {
2050 sd_printk(KERN_ERR, sdkp, "Thin provisioning is " \
2051 "enabled but neither TPU, nor TPWS are " \
2052 "set. Disabling discard!\n");
2053 goto out;
2054 }
2055
2056 if (lba_count)
2057 q->limits.max_discard_sectors =
2058 lba_count * sector_sz >> 9;
2059
2050 granularity = get_unaligned_be32(&buffer[28]); 2060 granularity = get_unaligned_be32(&buffer[28]);
2051 2061
2052 if (granularity) 2062 if (granularity)
@@ -2087,6 +2097,31 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
2087 kfree(buffer); 2097 kfree(buffer);
2088} 2098}
2089 2099
2100/**
2101 * sd_read_thin_provisioning - Query thin provisioning VPD page
2102 * @disk: disk to query
2103 */
2104static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
2105{
2106 unsigned char *buffer;
2107 const int vpd_len = 8;
2108
2109 if (sdkp->thin_provisioning == 0)
2110 return;
2111
2112 buffer = kmalloc(vpd_len, GFP_KERNEL);
2113
2114 if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len))
2115 goto out;
2116
2117 sdkp->tpvpd = 1;
2118 sdkp->tpu = (buffer[5] >> 7) & 1; /* UNMAP */
2119 sdkp->tpws = (buffer[5] >> 6) & 1; /* WRITE SAME(16) with UNMAP */
2120
2121 out:
2122 kfree(buffer);
2123}
2124
2090static int sd_try_extended_inquiry(struct scsi_device *sdp) 2125static int sd_try_extended_inquiry(struct scsi_device *sdp)
2091{ 2126{
2092 /* 2127 /*
@@ -2138,6 +2173,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
2138 sd_read_capacity(sdkp, buffer); 2173 sd_read_capacity(sdkp, buffer);
2139 2174
2140 if (sd_try_extended_inquiry(sdp)) { 2175 if (sd_try_extended_inquiry(sdp)) {
2176 sd_read_thin_provisioning(sdkp);
2141 sd_read_block_limits(sdkp); 2177 sd_read_block_limits(sdkp);
2142 sd_read_block_characteristics(sdkp); 2178 sd_read_block_characteristics(sdkp);
2143 } 2179 }
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 315ce9d96b1f..a40730ee465c 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -63,6 +63,9 @@ struct scsi_disk {
63 unsigned first_scan : 1; 63 unsigned first_scan : 1;
64 unsigned thin_provisioning : 1; 64 unsigned thin_provisioning : 1;
65 unsigned unmap : 1; 65 unsigned unmap : 1;
66 unsigned tpws : 1;
67 unsigned tpu : 1;
68 unsigned tpvpd : 1;
66}; 69};
67#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev) 70#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
68 71