|
@@ -2039,14 +2039,24 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
|
|
lba_count = get_unaligned_be32(&buffer[20]);
|
|
lba_count = get_unaligned_be32(&buffer[20]);
|
|
desc_count = get_unaligned_be32(&buffer[24]);
|
|
desc_count = get_unaligned_be32(&buffer[24]);
|
|
|
|
|
|
- if (lba_count) {
|
|
|
|
- q->limits.max_discard_sectors =
|
|
|
|
- lba_count * sector_sz >> 9;
|
|
|
|
-
|
|
|
|
- if (desc_count)
|
|
|
|
|
|
+ if (lba_count && desc_count) {
|
|
|
|
+ if (sdkp->tpvpd && !sdkp->tpu)
|
|
|
|
+ sdkp->unmap = 0;
|
|
|
|
+ else
|
|
sdkp->unmap = 1;
|
|
sdkp->unmap = 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (sdkp->tpvpd && !sdkp->tpu && !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;
|
|
|
|
+
|
|
granularity = get_unaligned_be32(&buffer[28]);
|
|
granularity = get_unaligned_be32(&buffer[28]);
|
|
|
|
|
|
if (granularity)
|
|
if (granularity)
|
|
@@ -2087,6 +2097,31 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
|
|
kfree(buffer);
|
|
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->tpvpd = 1;
|
|
|
|
+ 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)
|
|
static int sd_try_extended_inquiry(struct scsi_device *sdp)
|
|
{
|
|
{
|
|
/*
|
|
/*
|
|
@@ -2138,6 +2173,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
|
|
sd_read_capacity(sdkp, buffer);
|
|
sd_read_capacity(sdkp, buffer);
|
|
|
|
|
|
if (sd_try_extended_inquiry(sdp)) {
|
|
if (sd_try_extended_inquiry(sdp)) {
|
|
|
|
+ sd_read_thin_provisioning(sdkp);
|
|
sd_read_block_limits(sdkp);
|
|
sd_read_block_limits(sdkp);
|
|
sd_read_block_characteristics(sdkp);
|
|
sd_read_block_characteristics(sdkp);
|
|
}
|
|
}
|