diff options
author | Pete Zaitcev <zaitcev@redhat.com> | 2005-07-27 14:43:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-07-27 19:25:52 -0400 |
commit | 1872bcebbcd6ad7ddd99e92fb1e4f3d19e73919c (patch) | |
tree | dc1fe75f915fb58edb36b0bab877b2787e663b92 /drivers/block | |
parent | 90c5029e471636f21221bf66b9a46ada2ab79a22 (diff) |
[PATCH] ub: fix for blank CDs
This patch fixes a microcode lockup in my CD-ROM adapters when a blank CD
is inserted. However, do not try to burn CDs yet! I'm pretty sure that
trying it will end in coasters.
- Fix a few cases where we were unable to resynchronize with replies
for previous commands. The main thing is to keep reading replies
in case of a stall. This is done with the new state CLRRS.
- Since I am forgetting the basic state machine already, document it.
- Move counter increments in the looping path in its own function.
- Fix a harmless buglet in case CSW read fails to submit: do not
override state.
- Implement the Alan Stern's idea for adaptive signature checking.
Signed-off-by: Pete Zaitcev <zaitcev@yahoo.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/ub.c | 211 |
1 files changed, 170 insertions, 41 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 685f061e69b2..a026567f5d18 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
@@ -23,6 +23,7 @@ | |||
23 | * -- Exterminate P3 printks | 23 | * -- Exterminate P3 printks |
24 | * -- Resove XXX's | 24 | * -- Resove XXX's |
25 | * -- Redo "benh's retries", perhaps have spin-up code to handle them. V:D=? | 25 | * -- Redo "benh's retries", perhaps have spin-up code to handle them. V:D=? |
26 | * -- CLEAR, CLR2STS, CLRRS seem to be ripe for refactoring. | ||
26 | */ | 27 | */ |
27 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
@@ -38,6 +39,73 @@ | |||
38 | #define UB_MAJOR 180 | 39 | #define UB_MAJOR 180 |
39 | 40 | ||
40 | /* | 41 | /* |
42 | * The command state machine is the key model for understanding of this driver. | ||
43 | * | ||
44 | * The general rule is that all transitions are done towards the bottom | ||
45 | * of the diagram, thus preventing any loops. | ||
46 | * | ||
47 | * An exception to that is how the STAT state is handled. A counter allows it | ||
48 | * to be re-entered along the path marked with [C]. | ||
49 | * | ||
50 | * +--------+ | ||
51 | * ! INIT ! | ||
52 | * +--------+ | ||
53 | * ! | ||
54 | * ub_scsi_cmd_start fails ->--------------------------------------\ | ||
55 | * ! ! | ||
56 | * V ! | ||
57 | * +--------+ ! | ||
58 | * ! CMD ! ! | ||
59 | * +--------+ ! | ||
60 | * ! +--------+ ! | ||
61 | * was -EPIPE -->-------------------------------->! CLEAR ! ! | ||
62 | * ! +--------+ ! | ||
63 | * ! ! ! | ||
64 | * was error -->------------------------------------- ! --------->\ | ||
65 | * ! ! ! | ||
66 | * /--<-- cmd->dir == NONE ? ! ! | ||
67 | * ! ! ! ! | ||
68 | * ! V ! ! | ||
69 | * ! +--------+ ! ! | ||
70 | * ! ! DATA ! ! ! | ||
71 | * ! +--------+ ! ! | ||
72 | * ! ! +---------+ ! ! | ||
73 | * ! was -EPIPE -->--------------->! CLR2STS ! ! ! | ||
74 | * ! ! +---------+ ! ! | ||
75 | * ! ! ! ! ! | ||
76 | * ! ! was error -->---- ! --------->\ | ||
77 | * ! was error -->--------------------- ! ------------- ! --------->\ | ||
78 | * ! ! ! ! ! | ||
79 | * ! V ! ! ! | ||
80 | * \--->+--------+ ! ! ! | ||
81 | * ! STAT !<--------------------------/ ! ! | ||
82 | * /--->+--------+ ! ! | ||
83 | * ! ! ! ! | ||
84 | * [C] was -EPIPE -->-----------\ ! ! | ||
85 | * ! ! ! ! ! | ||
86 | * +<---- len == 0 ! ! ! | ||
87 | * ! ! ! ! ! | ||
88 | * ! was error -->--------------------------------------!---------->\ | ||
89 | * ! ! ! ! ! | ||
90 | * +<---- bad CSW ! ! ! | ||
91 | * +<---- bad tag ! ! ! | ||
92 | * ! ! V ! ! | ||
93 | * ! ! +--------+ ! ! | ||
94 | * ! ! ! CLRRS ! ! ! | ||
95 | * ! ! +--------+ ! ! | ||
96 | * ! ! ! ! ! | ||
97 | * \------- ! --------------------[C]--------\ ! ! | ||
98 | * ! ! ! ! | ||
99 | * cmd->error---\ +--------+ ! ! | ||
100 | * ! +--------------->! SENSE !<----------/ ! | ||
101 | * STAT_FAIL----/ +--------+ ! | ||
102 | * ! ! V | ||
103 | * ! V +--------+ | ||
104 | * \--------------------------------\--------------------->! DONE ! | ||
105 | * +--------+ | ||
106 | */ | ||
107 | |||
108 | /* | ||
41 | * Definitions which have to be scattered once we understand the layout better. | 109 | * Definitions which have to be scattered once we understand the layout better. |
42 | */ | 110 | */ |
43 | 111 | ||
@@ -91,8 +159,6 @@ struct bulk_cs_wrap { | |||
91 | 159 | ||
92 | #define US_BULK_CS_WRAP_LEN 13 | 160 | #define US_BULK_CS_WRAP_LEN 13 |
93 | #define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ | 161 | #define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ |
94 | /* This is for Olympus Camedia digital cameras */ | ||
95 | #define US_BULK_CS_OLYMPUS_SIGN 0x55425355 /* spells out 'USBU' */ | ||
96 | #define US_BULK_STAT_OK 0 | 162 | #define US_BULK_STAT_OK 0 |
97 | #define US_BULK_STAT_FAIL 1 | 163 | #define US_BULK_STAT_FAIL 1 |
98 | #define US_BULK_STAT_PHASE 2 | 164 | #define US_BULK_STAT_PHASE 2 |
@@ -135,6 +201,7 @@ enum ub_scsi_cmd_state { | |||
135 | UB_CMDST_CLR2STS, /* Clearing before requesting status */ | 201 | UB_CMDST_CLR2STS, /* Clearing before requesting status */ |
136 | UB_CMDST_STAT, /* Status phase */ | 202 | UB_CMDST_STAT, /* Status phase */ |
137 | UB_CMDST_CLEAR, /* Clearing a stall (halt, actually) */ | 203 | UB_CMDST_CLEAR, /* Clearing a stall (halt, actually) */ |
204 | UB_CMDST_CLRRS, /* Clearing before retrying status */ | ||
138 | UB_CMDST_SENSE, /* Sending Request Sense */ | 205 | UB_CMDST_SENSE, /* Sending Request Sense */ |
139 | UB_CMDST_DONE /* Final state */ | 206 | UB_CMDST_DONE /* Final state */ |
140 | }; | 207 | }; |
@@ -146,6 +213,7 @@ static char *ub_scsi_cmd_stname[] = { | |||
146 | "c2s", | 213 | "c2s", |
147 | "sts", | 214 | "sts", |
148 | "clr", | 215 | "clr", |
216 | "crs", | ||
149 | "Sen", | 217 | "Sen", |
150 | "fin" | 218 | "fin" |
151 | }; | 219 | }; |
@@ -316,6 +384,7 @@ struct ub_dev { | |||
316 | struct urb work_urb; | 384 | struct urb work_urb; |
317 | struct timer_list work_timer; | 385 | struct timer_list work_timer; |
318 | int last_pipe; /* What might need clearing */ | 386 | int last_pipe; /* What might need clearing */ |
387 | __le32 signature; /* Learned signature */ | ||
319 | struct bulk_cb_wrap work_bcb; | 388 | struct bulk_cb_wrap work_bcb; |
320 | struct bulk_cs_wrap work_bcs; | 389 | struct bulk_cs_wrap work_bcs; |
321 | struct usb_ctrlrequest work_cr; | 390 | struct usb_ctrlrequest work_cr; |
@@ -339,8 +408,9 @@ static void ub_scsi_action(unsigned long _dev); | |||
339 | static void ub_scsi_dispatch(struct ub_dev *sc); | 408 | static void ub_scsi_dispatch(struct ub_dev *sc); |
340 | static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 409 | static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
341 | static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc); | 410 | static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc); |
342 | static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 411 | static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
343 | static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 412 | static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
413 | static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | ||
344 | static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 414 | static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
345 | static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, | 415 | static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, |
346 | int stalled_pipe); | 416 | int stalled_pipe); |
@@ -1085,6 +1155,28 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1085 | 1155 | ||
1086 | ub_state_stat(sc, cmd); | 1156 | ub_state_stat(sc, cmd); |
1087 | 1157 | ||
1158 | } else if (cmd->state == UB_CMDST_CLRRS) { | ||
1159 | if (urb->status == -EPIPE) { | ||
1160 | /* | ||
1161 | * STALL while clearning STALL. | ||
1162 | * The control pipe clears itself - nothing to do. | ||
1163 | * XXX Might try to reset the device here and retry. | ||
1164 | */ | ||
1165 | printk(KERN_NOTICE "%s: stall on control pipe\n", | ||
1166 | sc->name); | ||
1167 | goto Bad_End; | ||
1168 | } | ||
1169 | |||
1170 | /* | ||
1171 | * We ignore the result for the halt clear. | ||
1172 | */ | ||
1173 | |||
1174 | /* reset the endpoint toggle */ | ||
1175 | usb_settoggle(sc->dev, usb_pipeendpoint(sc->last_pipe), | ||
1176 | usb_pipeout(sc->last_pipe), 0); | ||
1177 | |||
1178 | ub_state_stat_counted(sc, cmd); | ||
1179 | |||
1088 | } else if (cmd->state == UB_CMDST_CMD) { | 1180 | } else if (cmd->state == UB_CMDST_CMD) { |
1089 | if (urb->status == -EPIPE) { | 1181 | if (urb->status == -EPIPE) { |
1090 | rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); | 1182 | rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); |
@@ -1190,52 +1282,57 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1190 | */ | 1282 | */ |
1191 | goto Bad_End; | 1283 | goto Bad_End; |
1192 | } | 1284 | } |
1193 | cmd->state = UB_CMDST_CLEAR; | 1285 | |
1286 | /* | ||
1287 | * Having a stall when getting CSW is an error, so | ||
1288 | * make sure uppper levels are not oblivious to it. | ||
1289 | */ | ||
1290 | cmd->error = -EIO; /* A cheap trick... */ | ||
1291 | |||
1292 | cmd->state = UB_CMDST_CLRRS; | ||
1194 | ub_cmdtr_state(sc, cmd); | 1293 | ub_cmdtr_state(sc, cmd); |
1195 | return; | 1294 | return; |
1196 | } | 1295 | } |
1296 | if (urb->status == -EOVERFLOW) { | ||
1297 | /* | ||
1298 | * XXX We are screwed here. Retrying is pointless, | ||
1299 | * because the pipelined data will not get in until | ||
1300 | * we read with a big enough buffer. We must reset XXX. | ||
1301 | */ | ||
1302 | goto Bad_End; | ||
1303 | } | ||
1197 | if (urb->status != 0) | 1304 | if (urb->status != 0) |
1198 | goto Bad_End; | 1305 | goto Bad_End; |
1199 | 1306 | ||
1200 | if (urb->actual_length == 0) { | 1307 | if (urb->actual_length == 0) { |
1201 | /* | 1308 | ub_state_stat_counted(sc, cmd); |
1202 | * Some broken devices add unnecessary zero-length | ||
1203 | * packets to the end of their data transfers. | ||
1204 | * Such packets show up as 0-length CSWs. If we | ||
1205 | * encounter such a thing, try to read the CSW again. | ||
1206 | */ | ||
1207 | if (++cmd->stat_count >= 4) { | ||
1208 | printk(KERN_NOTICE "%s: unable to get CSW\n", | ||
1209 | sc->name); | ||
1210 | goto Bad_End; | ||
1211 | } | ||
1212 | __ub_state_stat(sc, cmd); | ||
1213 | return; | 1309 | return; |
1214 | } | 1310 | } |
1215 | 1311 | ||
1216 | /* | 1312 | /* |
1217 | * Check the returned Bulk protocol status. | 1313 | * Check the returned Bulk protocol status. |
1314 | * The status block has to be validated first. | ||
1218 | */ | 1315 | */ |
1219 | 1316 | ||
1220 | bcs = &sc->work_bcs; | 1317 | bcs = &sc->work_bcs; |
1221 | rc = le32_to_cpu(bcs->Residue); | 1318 | |
1222 | if (rc != cmd->len - cmd->act_len) { | 1319 | if (sc->signature == cpu_to_le32(0)) { |
1223 | /* | 1320 | /* |
1224 | * It is all right to transfer less, the caller has | 1321 | * This is the first reply, so do not perform the check. |
1225 | * to check. But it's not all right if the device | 1322 | * Instead, remember the signature the device uses |
1226 | * counts disagree with our counts. | 1323 | * for future checks. But do not allow a nul. |
1227 | */ | 1324 | */ |
1228 | /* P3 */ printk("%s: resid %d len %d act %d\n", | 1325 | sc->signature = bcs->Signature; |
1229 | sc->name, rc, cmd->len, cmd->act_len); | 1326 | if (sc->signature == cpu_to_le32(0)) { |
1230 | goto Bad_End; | 1327 | ub_state_stat_counted(sc, cmd); |
1231 | } | 1328 | return; |
1232 | 1329 | } | |
1233 | #if 0 | 1330 | } else { |
1234 | if (bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) && | 1331 | if (bcs->Signature != sc->signature) { |
1235 | bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) { | 1332 | ub_state_stat_counted(sc, cmd); |
1236 | /* Windows ignores signatures, so do we. */ | 1333 | return; |
1334 | } | ||
1237 | } | 1335 | } |
1238 | #endif | ||
1239 | 1336 | ||
1240 | if (bcs->Tag != cmd->tag) { | 1337 | if (bcs->Tag != cmd->tag) { |
1241 | /* | 1338 | /* |
@@ -1245,16 +1342,22 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1245 | * commands and reply at commands we timed out before. | 1342 | * commands and reply at commands we timed out before. |
1246 | * Without flushing these replies we loop forever. | 1343 | * Without flushing these replies we loop forever. |
1247 | */ | 1344 | */ |
1248 | if (++cmd->stat_count >= 4) { | 1345 | ub_state_stat_counted(sc, cmd); |
1249 | printk(KERN_NOTICE "%s: " | ||
1250 | "tag mismatch orig 0x%x reply 0x%x\n", | ||
1251 | sc->name, cmd->tag, bcs->Tag); | ||
1252 | goto Bad_End; | ||
1253 | } | ||
1254 | __ub_state_stat(sc, cmd); | ||
1255 | return; | 1346 | return; |
1256 | } | 1347 | } |
1257 | 1348 | ||
1349 | rc = le32_to_cpu(bcs->Residue); | ||
1350 | if (rc != cmd->len - cmd->act_len) { | ||
1351 | /* | ||
1352 | * It is all right to transfer less, the caller has | ||
1353 | * to check. But it's not all right if the device | ||
1354 | * counts disagree with our counts. | ||
1355 | */ | ||
1356 | /* P3 */ printk("%s: resid %d len %d act %d\n", | ||
1357 | sc->name, rc, cmd->len, cmd->act_len); | ||
1358 | goto Bad_End; | ||
1359 | } | ||
1360 | |||
1258 | switch (bcs->Status) { | 1361 | switch (bcs->Status) { |
1259 | case US_BULK_STAT_OK: | 1362 | case US_BULK_STAT_OK: |
1260 | break; | 1363 | break; |
@@ -1272,6 +1375,10 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1272 | } | 1375 | } |
1273 | 1376 | ||
1274 | /* Not zeroing error to preserve a babble indicator */ | 1377 | /* Not zeroing error to preserve a babble indicator */ |
1378 | if (cmd->error != 0) { | ||
1379 | ub_state_sense(sc, cmd); | ||
1380 | return; | ||
1381 | } | ||
1275 | cmd->state = UB_CMDST_DONE; | 1382 | cmd->state = UB_CMDST_DONE; |
1276 | ub_cmdtr_state(sc, cmd); | 1383 | ub_cmdtr_state(sc, cmd); |
1277 | ub_cmdq_pop(sc); | 1384 | ub_cmdq_pop(sc); |
@@ -1310,7 +1417,7 @@ static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc) | |||
1310 | * Factorization helper for the command state machine: | 1417 | * Factorization helper for the command state machine: |
1311 | * Submit a CSW read. | 1418 | * Submit a CSW read. |
1312 | */ | 1419 | */ |
1313 | static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | 1420 | static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) |
1314 | { | 1421 | { |
1315 | int rc; | 1422 | int rc; |
1316 | 1423 | ||
@@ -1328,11 +1435,12 @@ static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1328 | /* XXX Clear stalls */ | 1435 | /* XXX Clear stalls */ |
1329 | ub_complete(&sc->work_done); | 1436 | ub_complete(&sc->work_done); |
1330 | ub_state_done(sc, cmd, rc); | 1437 | ub_state_done(sc, cmd, rc); |
1331 | return; | 1438 | return -1; |
1332 | } | 1439 | } |
1333 | 1440 | ||
1334 | sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT; | 1441 | sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT; |
1335 | add_timer(&sc->work_timer); | 1442 | add_timer(&sc->work_timer); |
1443 | return 0; | ||
1336 | } | 1444 | } |
1337 | 1445 | ||
1338 | /* | 1446 | /* |
@@ -1341,7 +1449,9 @@ static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1341 | */ | 1449 | */ |
1342 | static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | 1450 | static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) |
1343 | { | 1451 | { |
1344 | __ub_state_stat(sc, cmd); | 1452 | |
1453 | if (__ub_state_stat(sc, cmd) != 0) | ||
1454 | return; | ||
1345 | 1455 | ||
1346 | cmd->stat_count = 0; | 1456 | cmd->stat_count = 0; |
1347 | cmd->state = UB_CMDST_STAT; | 1457 | cmd->state = UB_CMDST_STAT; |
@@ -1350,6 +1460,25 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
1350 | 1460 | ||
1351 | /* | 1461 | /* |
1352 | * Factorization helper for the command state machine: | 1462 | * Factorization helper for the command state machine: |
1463 | * Submit a CSW read and go to STAT state with counter (along [C] path). | ||
1464 | */ | ||
1465 | static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | ||
1466 | { | ||
1467 | |||
1468 | if (++cmd->stat_count >= 4) { | ||
1469 | ub_state_sense(sc, cmd); | ||
1470 | return; | ||
1471 | } | ||
1472 | |||
1473 | if (__ub_state_stat(sc, cmd) != 0) | ||
1474 | return; | ||
1475 | |||
1476 | cmd->state = UB_CMDST_STAT; | ||
1477 | ub_cmdtr_state(sc, cmd); | ||
1478 | } | ||
1479 | |||
1480 | /* | ||
1481 | * Factorization helper for the command state machine: | ||
1353 | * Submit a REQUEST SENSE and go to SENSE state. | 1482 | * Submit a REQUEST SENSE and go to SENSE state. |
1354 | */ | 1483 | */ |
1355 | static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | 1484 | static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) |