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 | |
| 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>
| -rw-r--r-- | drivers/ieee1394/sbp2.c | 130 | ||||
| -rw-r--r-- | drivers/ieee1394/sbp2.h | 4 | ||||
| -rw-r--r-- | drivers/scsi/scsi_scan.c | 1 | ||||
| -rw-r--r-- | drivers/scsi/sd.c | 36 | ||||
| -rw-r--r-- | include/scsi/scsi.h | 1 |
5 files changed, 32 insertions, 140 deletions
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 00c7b958361a..094e646ed4de 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c | |||
| @@ -1070,7 +1070,7 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_ | |||
| 1070 | static __inline__ int sbp2_command_conversion_device_type(u8 device_type) | 1070 | static __inline__ int sbp2_command_conversion_device_type(u8 device_type) |
| 1071 | { | 1071 | { |
| 1072 | return (((device_type == TYPE_DISK) || | 1072 | return (((device_type == TYPE_DISK) || |
| 1073 | (device_type == TYPE_SDAD) || | 1073 | (device_type == TYPE_RBC) || |
| 1074 | (device_type == TYPE_ROM)) ? 1:0); | 1074 | (device_type == TYPE_ROM)) ? 1:0); |
| 1075 | } | 1075 | } |
| 1076 | 1076 | ||
| @@ -2111,102 +2111,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, | |||
| 2111 | */ | 2111 | */ |
| 2112 | static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd) | 2112 | static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd) |
| 2113 | { | 2113 | { |
| 2114 | unchar new_cmd[16]; | ||
| 2115 | u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun); | ||
| 2116 | |||
| 2117 | SBP2_DEBUG("sbp2_check_sbp2_command"); | ||
| 2118 | |||
| 2119 | switch (*cmd) { | ||
| 2120 | |||
| 2121 | case READ_6: | ||
| 2122 | |||
| 2123 | if (sbp2_command_conversion_device_type(device_type)) { | ||
| 2124 | |||
| 2125 | SBP2_DEBUG("Convert READ_6 to READ_10"); | ||
| 2126 | |||
| 2127 | /* | ||
| 2128 | * Need to turn read_6 into read_10 | ||
| 2129 | */ | ||
| 2130 | new_cmd[0] = 0x28; | ||
| 2131 | new_cmd[1] = (cmd[1] & 0xe0); | ||
| 2132 | new_cmd[2] = 0x0; | ||
| 2133 | new_cmd[3] = (cmd[1] & 0x1f); | ||
| 2134 | new_cmd[4] = cmd[2]; | ||
| 2135 | new_cmd[5] = cmd[3]; | ||
| 2136 | new_cmd[6] = 0x0; | ||
| 2137 | new_cmd[7] = 0x0; | ||
| 2138 | new_cmd[8] = cmd[4]; | ||
| 2139 | new_cmd[9] = cmd[5]; | ||
| 2140 | |||
| 2141 | memcpy(cmd, new_cmd, 10); | ||
| 2142 | |||
| 2143 | } | ||
| 2144 | |||
| 2145 | break; | ||
| 2146 | |||
| 2147 | case WRITE_6: | ||
| 2148 | |||
| 2149 | if (sbp2_command_conversion_device_type(device_type)) { | ||
| 2150 | |||
| 2151 | SBP2_DEBUG("Convert WRITE_6 to WRITE_10"); | ||
| 2152 | |||
| 2153 | /* | ||
| 2154 | * Need to turn write_6 into write_10 | ||
| 2155 | */ | ||
| 2156 | new_cmd[0] = 0x2a; | ||
| 2157 | new_cmd[1] = (cmd[1] & 0xe0); | ||
| 2158 | new_cmd[2] = 0x0; | ||
| 2159 | new_cmd[3] = (cmd[1] & 0x1f); | ||
| 2160 | new_cmd[4] = cmd[2]; | ||
| 2161 | new_cmd[5] = cmd[3]; | ||
| 2162 | new_cmd[6] = 0x0; | ||
| 2163 | new_cmd[7] = 0x0; | ||
| 2164 | new_cmd[8] = cmd[4]; | ||
| 2165 | new_cmd[9] = cmd[5]; | ||
| 2166 | |||
| 2167 | memcpy(cmd, new_cmd, 10); | ||
| 2168 | |||
| 2169 | } | ||
| 2170 | |||
| 2171 | break; | ||
| 2172 | |||
| 2173 | case MODE_SENSE: | ||
| 2174 | |||
| 2175 | if (sbp2_command_conversion_device_type(device_type)) { | ||
| 2176 | |||
| 2177 | SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10"); | ||
| 2178 | |||
| 2179 | /* | ||
| 2180 | * Need to turn mode_sense_6 into mode_sense_10 | ||
| 2181 | */ | ||
| 2182 | new_cmd[0] = 0x5a; | ||
| 2183 | new_cmd[1] = cmd[1]; | ||
| 2184 | new_cmd[2] = cmd[2]; | ||
| 2185 | new_cmd[3] = 0x0; | ||
| 2186 | new_cmd[4] = 0x0; | ||
| 2187 | new_cmd[5] = 0x0; | ||
| 2188 | new_cmd[6] = 0x0; | ||
| 2189 | new_cmd[7] = 0x0; | ||
| 2190 | new_cmd[8] = cmd[4]; | ||
| 2191 | new_cmd[9] = cmd[5]; | ||
| 2192 | |||
| 2193 | memcpy(cmd, new_cmd, 10); | ||
| 2194 | |||
| 2195 | } | ||
| 2196 | |||
| 2197 | break; | ||
| 2198 | |||
| 2199 | case MODE_SELECT: | ||
| 2200 | |||
| 2201 | /* | ||
| 2202 | * TODO. Probably need to change mode select to 10 byte version | ||
| 2203 | */ | ||
| 2204 | |||
| 2205 | default: | ||
| 2206 | break; | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | return; | ||
| 2210 | } | 2114 | } |
| 2211 | 2115 | ||
| 2212 | /* | 2116 | /* |
| @@ -2272,14 +2176,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, | |||
| 2272 | } | 2176 | } |
| 2273 | 2177 | ||
| 2274 | /* | 2178 | /* |
| 2275 | * Check for Simple Direct Access Device and change it to TYPE_DISK | ||
| 2276 | */ | ||
| 2277 | if ((scsi_buf[0] & 0x1f) == TYPE_SDAD) { | ||
| 2278 | SBP2_DEBUG("Changing TYPE_SDAD to TYPE_DISK"); | ||
| 2279 | scsi_buf[0] &= 0xe0; | ||
| 2280 | } | ||
| 2281 | |||
| 2282 | /* | ||
| 2283 | * Fix ansi revision and response data format | 2179 | * Fix ansi revision and response data format |
| 2284 | */ | 2180 | */ |
| 2285 | scsi_buf[2] |= 2; | 2181 | scsi_buf[2] |= 2; |
| @@ -2287,27 +2183,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, | |||
| 2287 | 2183 | ||
| 2288 | break; | 2184 | break; |
| 2289 | 2185 | ||
| 2290 | case MODE_SENSE: | ||
| 2291 | |||
| 2292 | if (sbp2_command_conversion_device_type(device_type)) { | ||
| 2293 | |||
| 2294 | SBP2_DEBUG("Modify mode sense response (10 byte version)"); | ||
| 2295 | |||
| 2296 | scsi_buf[0] = scsi_buf[1]; /* Mode data length */ | ||
| 2297 | scsi_buf[1] = scsi_buf[2]; /* Medium type */ | ||
| 2298 | scsi_buf[2] = scsi_buf[3]; /* Device specific parameter */ | ||
| 2299 | scsi_buf[3] = scsi_buf[7]; /* Block descriptor length */ | ||
| 2300 | memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]); | ||
| 2301 | } | ||
| 2302 | |||
| 2303 | break; | ||
| 2304 | |||
| 2305 | case MODE_SELECT: | ||
| 2306 | |||
| 2307 | /* | ||
| 2308 | * TODO. Probably need to change mode select to 10 byte version | ||
| 2309 | */ | ||
| 2310 | |||
| 2311 | default: | 2186 | default: |
| 2312 | break; | 2187 | break; |
| 2313 | } | 2188 | } |
| @@ -2690,7 +2565,8 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, | |||
| 2690 | static int sbp2scsi_slave_configure (struct scsi_device *sdev) | 2565 | static int sbp2scsi_slave_configure (struct scsi_device *sdev) |
| 2691 | { | 2566 | { |
| 2692 | blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); | 2567 | blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); |
| 2693 | 2568 | sdev->use_10_for_rw = 1; | |
| 2569 | sdev->use_10_for_ms = 1; | ||
| 2694 | return 0; | 2570 | return 0; |
| 2695 | } | 2571 | } |
| 2696 | 2572 | ||
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h index a84b039a05b9..cd425be74841 100644 --- a/drivers/ieee1394/sbp2.h +++ b/drivers/ieee1394/sbp2.h | |||
| @@ -266,10 +266,6 @@ struct sbp2_status_block { | |||
| 266 | #define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */ | 266 | #define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */ |
| 267 | #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ | 267 | #define SBP2_MAX_SECTORS 255 /* Max sectors supported */ |
| 268 | 268 | ||
| 269 | #ifndef TYPE_SDAD | ||
| 270 | #define TYPE_SDAD 0x0e /* simplified direct access device */ | ||
| 271 | #endif | ||
| 272 | |||
| 273 | /* | 269 | /* |
| 274 | * SCSI direction table... | 270 | * SCSI direction table... |
| 275 | * (now used as a back-up in case the direction passed down from above is "unknown") | 271 | * (now used as a back-up in case the direction passed down from above is "unknown") |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index cca772624ae7..588611568d14 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
| @@ -625,6 +625,7 @@ static int scsi_add_lun(struct scsi_device *sdev, char *inq_result, int *bflags) | |||
| 625 | case TYPE_MEDIUM_CHANGER: | 625 | case TYPE_MEDIUM_CHANGER: |
| 626 | case TYPE_ENCLOSURE: | 626 | case TYPE_ENCLOSURE: |
| 627 | case TYPE_COMM: | 627 | case TYPE_COMM: |
| 628 | case TYPE_RBC: | ||
| 628 | sdev->writeable = 1; | 629 | sdev->writeable = 1; |
| 629 | break; | 630 | break; |
| 630 | case TYPE_WORM: | 631 | case TYPE_WORM: |
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; |
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index ca1e3b4a3183..1fb233741513 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h | |||
| @@ -213,6 +213,7 @@ static inline int scsi_status_is_good(int status) | |||
| 213 | #define TYPE_COMM 0x09 /* Communications device */ | 213 | #define TYPE_COMM 0x09 /* Communications device */ |
| 214 | #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ | 214 | #define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ |
| 215 | #define TYPE_RAID 0x0c | 215 | #define TYPE_RAID 0x0c |
| 216 | #define TYPE_RBC 0x0e | ||
| 216 | #define TYPE_NO_LUN 0x7f | 217 | #define TYPE_NO_LUN 0x7f |
| 217 | 218 | ||
| 218 | /* | 219 | /* |
