+ * sd_read_block_limits - Query disk device for preferred I/O sizes.
+ * @disk: disk to query
+ */
+static void sd_read_block_limits(struct scsi_disk *sdkp)
+{
+ struct request_queue *q = sdkp->disk->queue;
+ unsigned int sector_sz = sdkp->device->sector_size;
+ const int vpd_len = 64;
+ unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
+
+ if (!buffer ||
+ /* Block Limits VPD */
+ scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len))
+ goto out;
+
+ blk_queue_io_min(sdkp->disk->queue,
+ get_unaligned_be16(&buffer[6]) * sector_sz);
+ blk_queue_io_opt(sdkp->disk->queue,
+ get_unaligned_be32(&buffer[12]) * sector_sz);
+
+ /* Thin provisioning enabled and page length indicates TP support */
+ if (sdkp->thin_provisioning && buffer[3] == 0x3c) {
+ unsigned int lba_count, desc_count, granularity;
+
+ lba_count = get_unaligned_be32(&buffer[20]);
+ desc_count = get_unaligned_be32(&buffer[24]);
+
+ 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)
+ q->limits.discard_granularity = granularity * sector_sz;
+
+ if (buffer[32] & 0x80)
+ q->limits.discard_alignment =
+ get_unaligned_be32(&buffer[32]) & ~(1 << 31);
+ }
+
+ out:
+ kfree(buffer);
+}
+
+/**
+ * sd_read_block_characteristics - Query block dev. characteristics
+ * @disk: disk to query
+ */
+static void sd_read_block_characteristics(struct scsi_disk *sdkp)
+{
+ unsigned char *buffer;
+ u16 rot;
+ const int vpd_len = 64;
+
+ buffer = kmalloc(vpd_len, GFP_KERNEL);
+
+ if (!buffer ||
+ /* Block Device Characteristics VPD */
+ scsi_get_vpd_page(sdkp->device, 0xb1, buffer, vpd_len))
+ goto out;
+
+ rot = get_unaligned_be16(&buffer[4]);
+
+ if (rot == 1)
+ queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue);
+
+ out:
+ kfree(buffer);
+}
+
+static int sd_try_extended_inquiry(struct scsi_device *sdp)
+{
+ /*
+ * Although VPD inquiries can go to SCSI-2 type devices,
+ * some USB ones crash on receiving them, and the pages
+ * we currently ask for are for SPC-3 and beyond
+ */
+ if (sdp->scsi_level > SCSI_SPC_2)
+ return 1;
+ return 0;
+}
+
+/**