aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorLuben Tuikov <ltuikov@yahoo.com>2011-05-19 03:00:58 -0400
committerJames Bottomley <jbottomley@parallels.com>2011-05-24 12:43:52 -0400
commit0bcaa11154f07502e68375617e5650173eea8e50 (patch)
tree53529da81b2352faeb90e2cbfead1e4bea335afa /drivers/scsi/sd.c
parent9ae58e144df1a4ecc91dcd9eea5a3f4a6d13b5fc (diff)
[SCSI] Retrieve the Caching mode page (version 2)
Some kernel transport drivers unconditionally disable retrieval of the Caching mode page. One such for example is the BBB/CBI transport over USB. Such a restraint is too harsh as some devices do support the Caching mode page. Unconditionally enabling the retrieval of this mode page over those transports at their transport code level may result in some devices failing and becoming unusable. This patch implements a method of retrieving the Caching mode page without unconditionally enabling it in the transports which unconditionally disable it. The idea is to ask for all supported pages, page code 0x3F, and then search for the Caching mode page in the mode parameter data returned. The sd driver already asks for all the mode pages supported by the attached device by setting the page code to 0x3F in order to find out if the media is write protected by reading the WP bit in the Device Specific Parameter field. It then attempts to retrieve only the Caching mode page by setting the page code to 8 and actually attempting to retrieve it if and only if the transport allows it. The method implemented here is that if the transport doesn't allow retrieval of the Caching mode page and the device is not RBC, then we ask for all pages supported by setting the page code to 0x3F (similarly to how the WP bit is retrieved above), and then we search for the Caching mode page in the mode parameter data returned. With this patch, devices over SATA, report this (no change): Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] 976773168 512-byte logical blocks: (500 GB/465 GiB) Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: Attached scsi generic sg0 type 0 Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Write Protect is off Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Mode Sense: 00 3a 00 00 Oct 22 18:45:58 localhost kernel: sd 0:0:0:0: [sda] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA Smart devices report their Caching mode page. This is a change where we'd previously see the kernel making assumption about the device's cache being write-through: Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: Attached scsi generic sg2 type 0 Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] 610472646 4096-byte logical blocks: (2.50 TB/2.27 TiB) Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Write Protect is off Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Mode Sense: 47 00 10 08 Oct 22 18:45:58 localhost kernel: sd 6:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and FUA And "dumb" devices over BBB, are correctly shown not to support reporting the Caching mode page: Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] 15663104 512-byte logical blocks: (8.01 GB/7.46 GiB) Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Write Protect is off Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Mode Sense: 23 00 00 00 Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] No Caching mode page present Oct 22 18:49:06 localhost kernel: sd 7:0:0:0: [sdc] Assuming drive cache: write through Version 2 adds this: Some devices don't support page code 0x3F, and others require a fixed transfer length of 192 bytes. This single commit includes a patch by Alan Stern which fixes this. Reported-and-tested-by: Richard Senior <richard@r-senior.demon.co.uk> Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Luben Tuikov <ltuikov@yahoo.com> Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c79
1 files changed, 61 insertions, 18 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 1c69c14be0cd..953773cb26d9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2022,16 +2022,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
2022 2022
2023 int dbd; 2023 int dbd;
2024 int modepage; 2024 int modepage;
2025 int first_len;
2025 struct scsi_mode_data data; 2026 struct scsi_mode_data data;
2026 struct scsi_sense_hdr sshdr; 2027 struct scsi_sense_hdr sshdr;
2027 int old_wce = sdkp->WCE; 2028 int old_wce = sdkp->WCE;
2028 int old_rcd = sdkp->RCD; 2029 int old_rcd = sdkp->RCD;
2029 int old_dpofua = sdkp->DPOFUA; 2030 int old_dpofua = sdkp->DPOFUA;
2030 2031
2031 if (sdp->skip_ms_page_8) 2032 first_len = 4;
2032 goto defaults; 2033 if (sdp->skip_ms_page_8) {
2033 2034 if (sdp->type == TYPE_RBC)
2034 if (sdp->type == TYPE_RBC) { 2035 goto defaults;
2036 else {
2037 if (sdp->skip_ms_page_3f)
2038 goto defaults;
2039 modepage = 0x3F;
2040 if (sdp->use_192_bytes_for_3f)
2041 first_len = 192;
2042 dbd = 0;
2043 }
2044 } else if (sdp->type == TYPE_RBC) {
2035 modepage = 6; 2045 modepage = 6;
2036 dbd = 8; 2046 dbd = 8;
2037 } else { 2047 } else {
@@ -2040,13 +2050,15 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
2040 } 2050 }
2041 2051
2042 /* cautiously ask */ 2052 /* cautiously ask */
2043 res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); 2053 res = sd_do_mode_sense(sdp, dbd, modepage, buffer, first_len,
2054 &data, &sshdr);
2044 2055
2045 if (!scsi_status_is_good(res)) 2056 if (!scsi_status_is_good(res))
2046 goto bad_sense; 2057 goto bad_sense;
2047 2058
2048 if (!data.header_length) { 2059 if (!data.header_length) {
2049 modepage = 6; 2060 modepage = 6;
2061 first_len = 0;
2050 sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n"); 2062 sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n");
2051 } 2063 }
2052 2064
@@ -2059,30 +2071,61 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
2059 */ 2071 */
2060 if (len < 3) 2072 if (len < 3)
2061 goto bad_sense; 2073 goto bad_sense;
2062 if (len > 20) 2074 else if (len > SD_BUF_SIZE) {
2063 len = 20; 2075 sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
2064 2076 "data from %d to %d bytes\n", len, SD_BUF_SIZE);
2065 /* Take headers and block descriptors into account */ 2077 len = SD_BUF_SIZE;
2066 len += data.header_length + data.block_descriptor_length; 2078 }
2067 if (len > SD_BUF_SIZE) 2079 if (modepage == 0x3F && sdp->use_192_bytes_for_3f)
2068 goto bad_sense; 2080 len = 192;
2069 2081
2070 /* Get the data */ 2082 /* Get the data */
2071 res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); 2083 if (len > first_len)
2084 res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len,
2085 &data, &sshdr);
2072 2086
2073 if (scsi_status_is_good(res)) { 2087 if (scsi_status_is_good(res)) {
2074 int offset = data.header_length + data.block_descriptor_length; 2088 int offset = data.header_length + data.block_descriptor_length;
2075 2089
2076 if (offset >= SD_BUF_SIZE - 2) { 2090 while (offset < len) {
2077 sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); 2091 u8 page_code = buffer[offset] & 0x3F;
2078 goto defaults; 2092 u8 spf = buffer[offset] & 0x40;
2093
2094 if (page_code == 8 || page_code == 6) {
2095 /* We're interested only in the first 3 bytes.
2096 */
2097 if (len - offset <= 2) {
2098 sd_printk(KERN_ERR, sdkp, "Incomplete "
2099 "mode parameter data\n");
2100 goto defaults;
2101 } else {
2102 modepage = page_code;
2103 goto Page_found;
2104 }
2105 } else {
2106 /* Go to the next page */
2107 if (spf && len - offset > 3)
2108 offset += 4 + (buffer[offset+2] << 8) +
2109 buffer[offset+3];
2110 else if (!spf && len - offset > 1)
2111 offset += 2 + buffer[offset+1];
2112 else {
2113 sd_printk(KERN_ERR, sdkp, "Incomplete "
2114 "mode parameter data\n");
2115 goto defaults;
2116 }
2117 }
2079 } 2118 }
2080 2119
2081 if ((buffer[offset] & 0x3f) != modepage) { 2120 if (modepage == 0x3F) {
2121 sd_printk(KERN_ERR, sdkp, "No Caching mode page "
2122 "present\n");
2123 goto defaults;
2124 } else if ((buffer[offset] & 0x3f) != modepage) {
2082 sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); 2125 sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
2083 goto defaults; 2126 goto defaults;
2084 } 2127 }
2085 2128 Page_found:
2086 if (modepage == 8) { 2129 if (modepage == 8) {
2087 sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); 2130 sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
2088 sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); 2131 sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);