diff options
| -rw-r--r-- | drivers/scsi/sd.c | 63 |
1 files changed, 16 insertions, 47 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7ff61d76b4c5..b61ebec6bca7 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -2027,14 +2027,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2027 | int old_rcd = sdkp->RCD; | 2027 | int old_rcd = sdkp->RCD; |
| 2028 | int old_dpofua = sdkp->DPOFUA; | 2028 | int old_dpofua = sdkp->DPOFUA; |
| 2029 | 2029 | ||
| 2030 | if (sdp->skip_ms_page_8) { | 2030 | if (sdp->skip_ms_page_8) |
| 2031 | if (sdp->type == TYPE_RBC) | 2031 | goto defaults; |
| 2032 | goto defaults; | 2032 | |
| 2033 | else { | 2033 | if (sdp->type == TYPE_RBC) { |
| 2034 | modepage = 0x3F; | ||
| 2035 | dbd = 0; | ||
| 2036 | } | ||
| 2037 | } else if (sdp->type == TYPE_RBC) { | ||
| 2038 | modepage = 6; | 2034 | modepage = 6; |
| 2039 | dbd = 8; | 2035 | dbd = 8; |
| 2040 | } else { | 2036 | } else { |
| @@ -2062,11 +2058,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2062 | */ | 2058 | */ |
| 2063 | if (len < 3) | 2059 | if (len < 3) |
| 2064 | goto bad_sense; | 2060 | goto bad_sense; |
| 2065 | else if (len > SD_BUF_SIZE) { | 2061 | if (len > 20) |
| 2066 | sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " | 2062 | len = 20; |
| 2067 | "data from %d to %d bytes\n", len, SD_BUF_SIZE); | 2063 | |
| 2068 | len = SD_BUF_SIZE; | 2064 | /* Take headers and block descriptors into account */ |
| 2069 | } | 2065 | len += data.header_length + data.block_descriptor_length; |
| 2066 | if (len > SD_BUF_SIZE) | ||
| 2067 | goto bad_sense; | ||
| 2070 | 2068 | ||
| 2071 | /* Get the data */ | 2069 | /* Get the data */ |
| 2072 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); | 2070 | res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); |
| @@ -2074,45 +2072,16 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
| 2074 | if (scsi_status_is_good(res)) { | 2072 | if (scsi_status_is_good(res)) { |
| 2075 | int offset = data.header_length + data.block_descriptor_length; | 2073 | int offset = data.header_length + data.block_descriptor_length; |
| 2076 | 2074 | ||
| 2077 | while (offset < len) { | 2075 | if (offset >= SD_BUF_SIZE - 2) { |
| 2078 | u8 page_code = buffer[offset] & 0x3F; | 2076 | sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); |
| 2079 | u8 spf = buffer[offset] & 0x40; | 2077 | goto defaults; |
| 2080 | |||
| 2081 | if (page_code == 8 || page_code == 6) { | ||
| 2082 | /* We're interested only in the first 3 bytes. | ||
| 2083 | */ | ||
| 2084 | if (len - offset <= 2) { | ||
| 2085 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
| 2086 | "mode parameter data\n"); | ||
| 2087 | goto defaults; | ||
| 2088 | } else { | ||
| 2089 | modepage = page_code; | ||
| 2090 | goto Page_found; | ||
| 2091 | } | ||
| 2092 | } else { | ||
| 2093 | /* Go to the next page */ | ||
| 2094 | if (spf && len - offset > 3) | ||
| 2095 | offset += 4 + (buffer[offset+2] << 8) + | ||
| 2096 | buffer[offset+3]; | ||
| 2097 | else if (!spf && len - offset > 1) | ||
| 2098 | offset += 2 + buffer[offset+1]; | ||
| 2099 | else { | ||
| 2100 | sd_printk(KERN_ERR, sdkp, "Incomplete " | ||
| 2101 | "mode parameter data\n"); | ||
| 2102 | goto defaults; | ||
| 2103 | } | ||
| 2104 | } | ||
| 2105 | } | 2078 | } |
| 2106 | 2079 | ||
| 2107 | if (modepage == 0x3F) { | 2080 | if ((buffer[offset] & 0x3f) != modepage) { |
| 2108 | sd_printk(KERN_ERR, sdkp, "No Caching mode page " | ||
| 2109 | "present\n"); | ||
| 2110 | goto defaults; | ||
| 2111 | } else if ((buffer[offset] & 0x3f) != modepage) { | ||
| 2112 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); | 2081 | sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); |
| 2113 | goto defaults; | 2082 | goto defaults; |
| 2114 | } | 2083 | } |
| 2115 | Page_found: | 2084 | |
| 2116 | if (modepage == 8) { | 2085 | if (modepage == 8) { |
| 2117 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); | 2086 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); |
| 2118 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); | 2087 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); |
