aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
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);