Re: [DO NOT APPLY] sd take advantage of rotation speed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>>>>> "Matthew" == Matthew Wilcox <matthew@xxxxxx> writes:

Matthew> A question of policy ... should we interrogate page 0 to find
Matthew> out if page 0x83 exists?  You don't currently, but ses.c is
Matthew> limited to devices with an enclosure ... which is presumably
Matthew> only newer devices.  Do we have any idea if devices blow up
Matthew> on being asked for random VPD that they might not have?

We should check.

I actually changed my VPD code a bit on Friday.  There's a function to
do the heavy lifting and sanity checking, and a helper that can be
called without worrying about the details.  I moved the page list
checking from the caller to the helper function.

-- 
Martin K. Petersen	Oracle Linux Engineering

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1534,6 +1538,109 @@ defaults:
 	sdkp->DPOFUA = 0;
 }
 
+static int sd_vpd_inquiry(struct scsi_disk *sdkp, unsigned char *buffer, u8 page, u8 len)
+{
+	int result;
+	unsigned char cmd[16];
+	struct scsi_sense_hdr sshdr;
+
+	memset(cmd, 0, 16);
+	cmd[0] = INQUIRY;
+	cmd[1] = 1;		/* EVPD */
+	cmd[2] = page;		/* VPD page */
+	cmd[3] = len;
+	
+	result = scsi_execute_req(sdkp->device, cmd, DMA_FROM_DEVICE, buffer,
+				  len, &sshdr, SD_TIMEOUT, SD_MAX_RETRIES);
+
+	if (media_not_present(sdkp, &sshdr))
+		return -EIO;
+
+	if (result) {
+		sd_printk(KERN_ERR, sdkp, "EVPD Inquiry failed\n");
+		return -EIO;
+	}
+
+	if (buffer[1] != page) {
+		sd_printk(KERN_ERR, sdkp, "Page code not %2x (%2x)\n", page,
+			  buffer[1]);
+		return -EIO;
+	}
+
+	return buffer[3];
+}
+
+static int sd_get_vpd_page(struct scsi_disk *sdkp, unsigned char *buffer, u8 page, u8 len)
+{
+	int i, result;
+
+	/* Get Supported Pages list */
+	if (sd_vpd_inquiry(sdkp, buffer, 0x0, 255) < 0)
+		return -1;
+
+	for (i = 0 ; i < buffer[3] ; i++)
+		if (buffer[4+i] == page)
+			goto found;
+
+	return -1;
+
+found:
+	result = sd_vpd_inquiry(sdkp, buffer, page, len);
+
+	if (result < 0)
+		return -1;
+
+	if (buffer[3] != len)
+		sd_printk(KERN_ERR, sdkp, "VPD pg %x, req. %u bytes, got %u\n",
+			  page, len, buffer[3]);
+
+	return result;
+}
+
+/**
+ * sd_block_limits - Query disk device for preferred I/O sizes.
+ * @disk: disk to query
+ * @buffer: temporary buffer to store inquiry response in
+ */
+static void sd_block_limits(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+	struct io_topology *iot = sdkp->disk->topology;
+
+	/* Block Limits VPD */
+	if (sd_get_vpd_page(sdkp, buffer, 0xb0, 16) < 0)
+		return;
+
+	iot->phys_off = 0;
+	iot->opt_block = be16_to_cpup((__be16 *)&buffer[6])
+		* sdkp->device->sector_size;
+	iot->max_length = be32_to_cpup((__be32 *)&buffer[8])
+		* sdkp->device->sector_size;
+	iot->opt_length = be32_to_cpup((__be32 *)&buffer[12])
+		* sdkp->device->sector_size;
+}
+
+/**
+ * sd_block_characteristics - Query block dev. characteristics
+ * @disk: disk to query
+ * @buffer: temporary buffer to store inquiry response in
+ */
+static void sd_block_characteristics(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+	struct io_topology *iot = sdkp->disk->topology;
+	unsigned int rotation;
+
+	/* Block Device Characteristics VPD */
+	if (sd_get_vpd_page(sdkp, buffer, 0xb1, 64) < 0)
+		return;
+
+	rotation = be16_to_cpup((__be16 *)&buffer[4]);
+
+	if (rotation == 1)
+		iot->dev_type = IO_TYPE_SSD;
+	else if (rotation > 0x400)
+		iot->dev_type = IO_TYPE_DISK;
+}
+
 /**
  *	sd_revalidate_disk - called the first time a new disk is seen,
  *	performs disk spin up, read_capacity, etc.
@@ -1579,6 +1686,8 @@ static int sd_revalidate_disk(struct gen
 	 */
 	if (sdkp->media_present) {
 		sd_read_capacity(sdkp, buffer);
+		sd_block_limits(sdkp, buffer);
+		sd_block_characteristics(sdkp, buffer);
 		sd_read_write_protect_flag(sdkp, buffer);
 		sd_read_cache_type(sdkp, buffer);
 	}
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux