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.c82
1 files changed, 63 insertions, 19 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index bd0806e64e85..953773cb26d9 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -490,7 +490,8 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
490 unsigned int max_blocks = 0; 490 unsigned int max_blocks = 0;
491 491
492 q->limits.discard_zeroes_data = sdkp->lbprz; 492 q->limits.discard_zeroes_data = sdkp->lbprz;
493 q->limits.discard_alignment = sdkp->unmap_alignment; 493 q->limits.discard_alignment = sdkp->unmap_alignment *
494 logical_block_size;
494 q->limits.discard_granularity = 495 q->limits.discard_granularity =
495 max(sdkp->physical_block_size, 496 max(sdkp->physical_block_size,
496 sdkp->unmap_granularity * logical_block_size); 497 sdkp->unmap_granularity * logical_block_size);
@@ -2021,16 +2022,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
2021 2022
2022 int dbd; 2023 int dbd;
2023 int modepage; 2024 int modepage;
2025 int first_len;
2024 struct scsi_mode_data data; 2026 struct scsi_mode_data data;
2025 struct scsi_sense_hdr sshdr; 2027 struct scsi_sense_hdr sshdr;
2026 int old_wce = sdkp->WCE; 2028 int old_wce = sdkp->WCE;
2027 int old_rcd = sdkp->RCD; 2029 int old_rcd = sdkp->RCD;
2028 int old_dpofua = sdkp->DPOFUA; 2030 int old_dpofua = sdkp->DPOFUA;
2029 2031
2030 if (sdp->skip_ms_page_8) 2032 first_len = 4;
2031 goto defaults; 2033 if (sdp->skip_ms_page_8) {
2032 2034 if (sdp->type == TYPE_RBC)
2033 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) {
2034 modepage = 6; 2045 modepage = 6;
2035 dbd = 8; 2046 dbd = 8;
2036 } else { 2047 } else {
@@ -2039,13 +2050,15 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
2039 } 2050 }
2040 2051
2041 /* cautiously ask */ 2052 /* cautiously ask */
2042 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);
2043 2055
2044 if (!scsi_status_is_good(res)) 2056 if (!scsi_status_is_good(res))
2045 goto bad_sense; 2057 goto bad_sense;
2046 2058
2047 if (!data.header_length) { 2059 if (!data.header_length) {
2048 modepage = 6; 2060 modepage = 6;
2061 first_len = 0;
2049 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");
2050 } 2063 }
2051 2064
@@ -2058,30 +2071,61 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
2058 */ 2071 */
2059 if (len < 3) 2072 if (len < 3)
2060 goto bad_sense; 2073 goto bad_sense;
2061 if (len > 20) 2074 else if (len > SD_BUF_SIZE) {
2062 len = 20; 2075 sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
2063 2076 "data from %d to %d bytes\n", len, SD_BUF_SIZE);
2064 /* Take headers and block descriptors into account */ 2077 len = SD_BUF_SIZE;
2065 len += data.header_length + data.block_descriptor_length; 2078 }
2066 if (len > SD_BUF_SIZE) 2079 if (modepage == 0x3F && sdp->use_192_bytes_for_3f)
2067 goto bad_sense; 2080 len = 192;
2068 2081
2069 /* Get the data */ 2082 /* Get the data */
2070 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);
2071 2086
2072 if (scsi_status_is_good(res)) { 2087 if (scsi_status_is_good(res)) {
2073 int offset = data.header_length + data.block_descriptor_length; 2088 int offset = data.header_length + data.block_descriptor_length;
2074 2089
2075 if (offset >= SD_BUF_SIZE - 2) { 2090 while (offset < len) {
2076 sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); 2091 u8 page_code = buffer[offset] & 0x3F;
2077 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 }
2078 } 2118 }
2079 2119
2080 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) {
2081 sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); 2125 sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
2082 goto defaults; 2126 goto defaults;
2083 } 2127 }
2084 2128 Page_found:
2085 if (modepage == 8) { 2129 if (modepage == 8) {
2086 sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); 2130 sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
2087 sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); 2131 sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);