Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 252446
b: refs/heads/master
c: 0bcaa11
h: refs/heads/master
v: v3
  • Loading branch information
Luben Tuikov authored and James Bottomley committed May 24, 2011
1 parent 5eeada1 commit f911169
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 19 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 9ae58e144df1a4ecc91dcd9eea5a3f4a6d13b5fc
refs/heads/master: 0bcaa11154f07502e68375617e5650173eea8e50
79 changes: 61 additions & 18 deletions trunk/drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -2022,16 +2022,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)

int dbd;
int modepage;
int first_len;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
int old_wce = sdkp->WCE;
int old_rcd = sdkp->RCD;
int old_dpofua = sdkp->DPOFUA;

if (sdp->skip_ms_page_8)
goto defaults;

if (sdp->type == TYPE_RBC) {
first_len = 4;
if (sdp->skip_ms_page_8) {
if (sdp->type == TYPE_RBC)
goto defaults;
else {
if (sdp->skip_ms_page_3f)
goto defaults;
modepage = 0x3F;
if (sdp->use_192_bytes_for_3f)
first_len = 192;
dbd = 0;
}
} else if (sdp->type == TYPE_RBC) {
modepage = 6;
dbd = 8;
} else {
Expand All @@ -2040,13 +2050,15 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
}

/* cautiously ask */
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr);
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, first_len,
&data, &sshdr);

if (!scsi_status_is_good(res))
goto bad_sense;

if (!data.header_length) {
modepage = 6;
first_len = 0;
sd_printk(KERN_ERR, sdkp, "Missing header in MODE_SENSE response\n");
}

Expand All @@ -2059,30 +2071,61 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
*/
if (len < 3)
goto bad_sense;
if (len > 20)
len = 20;

/* Take headers and block descriptors into account */
len += data.header_length + data.block_descriptor_length;
if (len > SD_BUF_SIZE)
goto bad_sense;
else if (len > SD_BUF_SIZE) {
sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
"data from %d to %d bytes\n", len, SD_BUF_SIZE);
len = SD_BUF_SIZE;
}
if (modepage == 0x3F && sdp->use_192_bytes_for_3f)
len = 192;

/* Get the data */
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
if (len > first_len)
res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len,
&data, &sshdr);

if (scsi_status_is_good(res)) {
int offset = data.header_length + data.block_descriptor_length;

if (offset >= SD_BUF_SIZE - 2) {
sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
goto defaults;
while (offset < len) {
u8 page_code = buffer[offset] & 0x3F;
u8 spf = buffer[offset] & 0x40;

if (page_code == 8 || page_code == 6) {
/* We're interested only in the first 3 bytes.
*/
if (len - offset <= 2) {
sd_printk(KERN_ERR, sdkp, "Incomplete "
"mode parameter data\n");
goto defaults;
} else {
modepage = page_code;
goto Page_found;
}
} else {
/* Go to the next page */
if (spf && len - offset > 3)
offset += 4 + (buffer[offset+2] << 8) +
buffer[offset+3];
else if (!spf && len - offset > 1)
offset += 2 + buffer[offset+1];
else {
sd_printk(KERN_ERR, sdkp, "Incomplete "
"mode parameter data\n");
goto defaults;
}
}
}

if ((buffer[offset] & 0x3f) != modepage) {
if (modepage == 0x3F) {
sd_printk(KERN_ERR, sdkp, "No Caching mode page "
"present\n");
goto defaults;
} else if ((buffer[offset] & 0x3f) != modepage) {
sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
goto defaults;
}

Page_found:
if (modepage == 8) {
sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
Expand Down

0 comments on commit f911169

Please sign in to comment.