diff options
author | Al Viro <viro@parcelfarce.linux.theplanet.co.uk> | 2005-05-15 20:59:55 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-05-26 09:41:15 -0400 |
commit | 631e8a1398ce4cfef8b30678d51daf0c64313a09 (patch) | |
tree | 14d3b601b4a7160568c58d53a94a0a4711094588 /drivers/scsi/sd.c | |
parent | 53222b906903fd861dc24ebccfa07ee125941313 (diff) |
[SCSI] TYPE_RBC cache fixes (sbp2.c affected)
a) TYPE_SDAD renamed to TYPE_RBC and taken to scsi.h
b) in sbp2.c remapping of TYPE_RPB to TYPE_DISK turned off
c) relevant places in midlayer and sd.c taught to accept TYPE_RBC
d) sd.c::sd_read_cache_type() looks into page 6 when dealing with
TYPE_RBC - these guys have writeback cache flag there and are not guaranteed
to have page 8 at all.
e) sd_read_cache_type() got an extra sanity check - it checks that
it got the page it asked for before using its contents. And screams if
mismatch had happened. Rationale: there are broken devices out there that
are "helpful" enough to go for "I don't have a page you've asked for, here,
have another one". For example, PL3507 had been caught doing just that...
f) sbp2 sets sdev->use_10_for_rw and sdev->use_10_for_ms instead
of bothering to remap READ6/WRITE6/MOD_SENSE, so most of the conversions
in there are gone now.
Incidentally, I wonder if USB storage devices that have no
mode page 8 are simply RBC ones. I haven't touched that, but it might
be interesting to check...
Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 36 |
1 files changed, 27 insertions, 9 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 19afb25e44d3..bb8235598787 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -1368,17 +1368,26 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, | |||
1368 | */ | 1368 | */ |
1369 | static void | 1369 | static void |
1370 | sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | 1370 | sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, |
1371 | struct scsi_request *SRpnt, unsigned char *buffer) { | 1371 | struct scsi_request *SRpnt, unsigned char *buffer) |
1372 | { | ||
1372 | int len = 0, res; | 1373 | int len = 0, res; |
1373 | 1374 | ||
1374 | const int dbd = 0; /* DBD */ | 1375 | int dbd; |
1375 | const int modepage = 0x08; /* current values, cache page */ | 1376 | int modepage; |
1376 | struct scsi_mode_data data; | 1377 | struct scsi_mode_data data; |
1377 | struct scsi_sense_hdr sshdr; | 1378 | struct scsi_sense_hdr sshdr; |
1378 | 1379 | ||
1379 | if (sdkp->device->skip_ms_page_8) | 1380 | if (sdkp->device->skip_ms_page_8) |
1380 | goto defaults; | 1381 | goto defaults; |
1381 | 1382 | ||
1383 | if (sdkp->device->type == TYPE_RBC) { | ||
1384 | modepage = 6; | ||
1385 | dbd = 8; | ||
1386 | } else { | ||
1387 | modepage = 8; | ||
1388 | dbd = 0; | ||
1389 | } | ||
1390 | |||
1382 | /* cautiously ask */ | 1391 | /* cautiously ask */ |
1383 | res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data); | 1392 | res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data); |
1384 | 1393 | ||
@@ -1409,11 +1418,20 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, | |||
1409 | "write back, no read (daft)" | 1418 | "write back, no read (daft)" |
1410 | }; | 1419 | }; |
1411 | int ct = 0; | 1420 | int ct = 0; |
1412 | int offset = data.header_length + | 1421 | int offset = data.header_length + data.block_descriptor_length; |
1413 | data.block_descriptor_length + 2; | ||
1414 | 1422 | ||
1415 | sdkp->WCE = ((buffer[offset] & 0x04) != 0); | 1423 | if ((buffer[offset] & 0x3f) != modepage) { |
1416 | sdkp->RCD = ((buffer[offset] & 0x01) != 0); | 1424 | printk(KERN_ERR "%s: got wrong page\n", diskname); |
1425 | goto defaults; | ||
1426 | } | ||
1427 | |||
1428 | if (modepage == 8) { | ||
1429 | sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); | ||
1430 | sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); | ||
1431 | } else { | ||
1432 | sdkp->WCE = ((buffer[offset + 2] & 0x01) == 0); | ||
1433 | sdkp->RCD = 0; | ||
1434 | } | ||
1417 | 1435 | ||
1418 | ct = sdkp->RCD + 2*sdkp->WCE; | 1436 | ct = sdkp->RCD + 2*sdkp->WCE; |
1419 | 1437 | ||
@@ -1533,7 +1551,7 @@ static int sd_probe(struct device *dev) | |||
1533 | int error; | 1551 | int error; |
1534 | 1552 | ||
1535 | error = -ENODEV; | 1553 | error = -ENODEV; |
1536 | if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)) | 1554 | if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC) |
1537 | goto out; | 1555 | goto out; |
1538 | 1556 | ||
1539 | SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", | 1557 | SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", |
@@ -1570,7 +1588,7 @@ static int sd_probe(struct device *dev) | |||
1570 | sdkp->openers = 0; | 1588 | sdkp->openers = 0; |
1571 | 1589 | ||
1572 | if (!sdp->timeout) { | 1590 | if (!sdp->timeout) { |
1573 | if (sdp->type == TYPE_DISK) | 1591 | if (sdp->type != TYPE_MOD) |
1574 | sdp->timeout = SD_TIMEOUT; | 1592 | sdp->timeout = SD_TIMEOUT; |
1575 | else | 1593 | else |
1576 | sdp->timeout = SD_MOD_TIMEOUT; | 1594 | sdp->timeout = SD_MOD_TIMEOUT; |