aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/block/ub.c197
1 files changed, 4 insertions, 193 deletions
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index 26aa96eba439..21d0e075c928 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -180,6 +180,7 @@ struct ub_dev;
180#define UB_DIR_ILLEGAL2 2 180#define UB_DIR_ILLEGAL2 2
181#define UB_DIR_WRITE 3 181#define UB_DIR_WRITE 3
182 182
183/* P3 */
183#define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \ 184#define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \
184 (((c)==UB_DIR_READ)? 'r': 'n')) 185 (((c)==UB_DIR_READ)? 'r': 'n'))
185 186
@@ -195,24 +196,11 @@ enum ub_scsi_cmd_state {
195 UB_CMDST_DONE /* Final state */ 196 UB_CMDST_DONE /* Final state */
196}; 197};
197 198
198static char *ub_scsi_cmd_stname[] = {
199 ". ",
200 "Cmd",
201 "dat",
202 "c2s",
203 "sts",
204 "clr",
205 "crs",
206 "Sen",
207 "fin"
208};
209
210struct ub_scsi_cmd { 199struct ub_scsi_cmd {
211 unsigned char cdb[UB_MAX_CDB_SIZE]; 200 unsigned char cdb[UB_MAX_CDB_SIZE];
212 unsigned char cdb_len; 201 unsigned char cdb_len;
213 202
214 unsigned char dir; /* 0 - none, 1 - read, 3 - write. */ 203 unsigned char dir; /* 0 - none, 1 - read, 3 - write. */
215 unsigned char trace_index;
216 enum ub_scsi_cmd_state state; 204 enum ub_scsi_cmd_state state;
217 unsigned int tag; 205 unsigned int tag;
218 struct ub_scsi_cmd *next; 206 struct ub_scsi_cmd *next;
@@ -249,28 +237,6 @@ struct ub_capacity {
249}; 237};
250 238
251/* 239/*
252 * The SCSI command tracing structure.
253 */
254
255#define SCMD_ST_HIST_SZ 8
256#define SCMD_TRACE_SZ 63 /* Less than 4KB of 61-byte lines */
257
258struct ub_scsi_cmd_trace {
259 int hcur;
260 unsigned int tag;
261 unsigned int req_size, act_size;
262 unsigned char op;
263 unsigned char dir;
264 unsigned char key, asc, ascq;
265 char st_hst[SCMD_ST_HIST_SZ];
266};
267
268struct ub_scsi_trace {
269 int cur;
270 struct ub_scsi_cmd_trace vec[SCMD_TRACE_SZ];
271};
272
273/*
274 * This is a direct take-off from linux/include/completion.h 240 * This is a direct take-off from linux/include/completion.h
275 * The difference is that I do not wait on this thing, just poll. 241 * The difference is that I do not wait on this thing, just poll.
276 * When I want to wait (ub_probe), I just use the stock completion. 242 * When I want to wait (ub_probe), I just use the stock completion.
@@ -388,7 +354,6 @@ struct ub_dev {
388 wait_queue_head_t reset_wait; 354 wait_queue_head_t reset_wait;
389 355
390 int sg_stat[6]; 356 int sg_stat[6];
391 struct ub_scsi_trace tr;
392}; 357};
393 358
394/* 359/*
@@ -458,137 +423,6 @@ static int ub_qlock_next = 0;
458static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */ 423static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */
459 424
460/* 425/*
461 * The SCSI command tracing procedures.
462 */
463
464static void ub_cmdtr_new(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
465{
466 int n;
467 struct ub_scsi_cmd_trace *t;
468
469 if ((n = sc->tr.cur + 1) == SCMD_TRACE_SZ) n = 0;
470 t = &sc->tr.vec[n];
471
472 memset(t, 0, sizeof(struct ub_scsi_cmd_trace));
473 t->tag = cmd->tag;
474 t->op = cmd->cdb[0];
475 t->dir = cmd->dir;
476 t->req_size = cmd->len;
477 t->st_hst[0] = cmd->state;
478
479 sc->tr.cur = n;
480 cmd->trace_index = n;
481}
482
483static void ub_cmdtr_state(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
484{
485 int n;
486 struct ub_scsi_cmd_trace *t;
487
488 t = &sc->tr.vec[cmd->trace_index];
489 if (t->tag == cmd->tag) {
490 if ((n = t->hcur + 1) == SCMD_ST_HIST_SZ) n = 0;
491 t->st_hst[n] = cmd->state;
492 t->hcur = n;
493 }
494}
495
496static void ub_cmdtr_act_len(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
497{
498 struct ub_scsi_cmd_trace *t;
499
500 t = &sc->tr.vec[cmd->trace_index];
501 if (t->tag == cmd->tag)
502 t->act_size = cmd->act_len;
503}
504
505static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
506 unsigned char *sense)
507{
508 struct ub_scsi_cmd_trace *t;
509
510 t = &sc->tr.vec[cmd->trace_index];
511 if (t->tag == cmd->tag) {
512 t->key = sense[2] & 0x0F;
513 t->asc = sense[12];
514 t->ascq = sense[13];
515 }
516}
517
518static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr,
519 char *page)
520{
521 struct usb_interface *intf;
522 struct ub_dev *sc;
523 struct list_head *p;
524 struct ub_lun *lun;
525 int cnt;
526 unsigned long flags;
527 int nc, nh;
528 int i, j;
529 struct ub_scsi_cmd_trace *t;
530
531 intf = to_usb_interface(dev);
532 sc = usb_get_intfdata(intf);
533 if (sc == NULL)
534 return 0;
535
536 cnt = 0;
537 spin_lock_irqsave(sc->lock, flags);
538
539 cnt += sprintf(page + cnt,
540 "poison %d reset %d\n",
541 atomic_read(&sc->poison), sc->reset);
542 cnt += sprintf(page + cnt,
543 "qlen %d qmax %d\n",
544 sc->cmd_queue.qlen, sc->cmd_queue.qmax);
545 cnt += sprintf(page + cnt,
546 "sg %d %d %d %d %d .. %d\n",
547 sc->sg_stat[0],
548 sc->sg_stat[1],
549 sc->sg_stat[2],
550 sc->sg_stat[3],
551 sc->sg_stat[4],
552 sc->sg_stat[5]);
553
554 list_for_each (p, &sc->luns) {
555 lun = list_entry(p, struct ub_lun, link);
556 cnt += sprintf(page + cnt,
557 "lun %u changed %d removable %d readonly %d\n",
558 lun->num, lun->changed, lun->removable, lun->readonly);
559 }
560
561 if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
562 for (j = 0; j < SCMD_TRACE_SZ; j++) {
563 t = &sc->tr.vec[nc];
564
565 cnt += sprintf(page + cnt, "%08x %02x", t->tag, t->op);
566 if (t->op == REQUEST_SENSE) {
567 cnt += sprintf(page + cnt, " [sense %x %02x %02x]",
568 t->key, t->asc, t->ascq);
569 } else {
570 cnt += sprintf(page + cnt, " %c", UB_DIR_CHAR(t->dir));
571 cnt += sprintf(page + cnt, " [%5d %5d]",
572 t->req_size, t->act_size);
573 }
574 if ((nh = t->hcur + 1) == SCMD_ST_HIST_SZ) nh = 0;
575 for (i = 0; i < SCMD_ST_HIST_SZ; i++) {
576 cnt += sprintf(page + cnt, " %s",
577 ub_scsi_cmd_stname[(int)t->st_hst[nh]]);
578 if (++nh == SCMD_ST_HIST_SZ) nh = 0;
579 }
580 cnt += sprintf(page + cnt, "\n");
581
582 if (++nc == SCMD_TRACE_SZ) nc = 0;
583 }
584
585 spin_unlock_irqrestore(sc->lock, flags);
586 return cnt;
587}
588
589static DEVICE_ATTR(diag, S_IRUGO, ub_diag_show, NULL); /* N.B. World readable */
590
591/*
592 * The id allocator. 426 * The id allocator.
593 * 427 *
594 * This also stores the host for indexing by minor, which is somewhat dirty. 428 * This also stores the host for indexing by minor, which is somewhat dirty.
@@ -1090,7 +924,6 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1090 add_timer(&sc->work_timer); 924 add_timer(&sc->work_timer);
1091 925
1092 cmd->state = UB_CMDST_CMD; 926 cmd->state = UB_CMDST_CMD;
1093 ub_cmdtr_state(sc, cmd);
1094 return 0; 927 return 0;
1095} 928}
1096 929
@@ -1143,12 +976,10 @@ static void ub_scsi_dispatch(struct ub_dev *sc)
1143 ub_cmdq_pop(sc); 976 ub_cmdq_pop(sc);
1144 (*cmd->done)(sc, cmd); 977 (*cmd->done)(sc, cmd);
1145 } else if (cmd->state == UB_CMDST_INIT) { 978 } else if (cmd->state == UB_CMDST_INIT) {
1146 ub_cmdtr_new(sc, cmd);
1147 if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0) 979 if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0)
1148 break; 980 break;
1149 cmd->error = rc; 981 cmd->error = rc;
1150 cmd->state = UB_CMDST_DONE; 982 cmd->state = UB_CMDST_DONE;
1151 ub_cmdtr_state(sc, cmd);
1152 } else { 983 } else {
1153 if (!ub_is_completed(&sc->work_done)) 984 if (!ub_is_completed(&sc->work_done))
1154 break; 985 break;
@@ -1245,7 +1076,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1245 return; 1076 return;
1246 } 1077 }
1247 cmd->state = UB_CMDST_CLEAR; 1078 cmd->state = UB_CMDST_CLEAR;
1248 ub_cmdtr_state(sc, cmd);
1249 return; 1079 return;
1250 case -ESHUTDOWN: /* unplug */ 1080 case -ESHUTDOWN: /* unplug */
1251 case -EILSEQ: /* unplug timeout on uhci */ 1081 case -EILSEQ: /* unplug timeout on uhci */
@@ -1277,7 +1107,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1277 return; 1107 return;
1278 } 1108 }
1279 cmd->state = UB_CMDST_CLR2STS; 1109 cmd->state = UB_CMDST_CLR2STS;
1280 ub_cmdtr_state(sc, cmd);
1281 return; 1110 return;
1282 } 1111 }
1283 if (urb->status == -EOVERFLOW) { 1112 if (urb->status == -EOVERFLOW) {
@@ -1302,7 +1131,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1302 if (urb->status != 0 || 1131 if (urb->status != 0 ||
1303 len != cmd->sgv[cmd->current_sg].length) { 1132 len != cmd->sgv[cmd->current_sg].length) {
1304 cmd->act_len += len; 1133 cmd->act_len += len;
1305 ub_cmdtr_act_len(sc, cmd);
1306 1134
1307 cmd->error = -EIO; 1135 cmd->error = -EIO;
1308 ub_state_stat(sc, cmd); 1136 ub_state_stat(sc, cmd);
@@ -1329,7 +1157,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1329 } 1157 }
1330 1158
1331 cmd->act_len += urb->actual_length; 1159 cmd->act_len += urb->actual_length;
1332 ub_cmdtr_act_len(sc, cmd);
1333 1160
1334 if (++cmd->current_sg < cmd->nsg) { 1161 if (++cmd->current_sg < cmd->nsg) {
1335 ub_data_start(sc, cmd); 1162 ub_data_start(sc, cmd);
@@ -1355,7 +1182,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1355 cmd->error = -EIO; /* A cheap trick... */ 1182 cmd->error = -EIO; /* A cheap trick... */
1356 1183
1357 cmd->state = UB_CMDST_CLRRS; 1184 cmd->state = UB_CMDST_CLRRS;
1358 ub_cmdtr_state(sc, cmd);
1359 return; 1185 return;
1360 } 1186 }
1361 1187
@@ -1439,7 +1265,6 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1439 return; 1265 return;
1440 } 1266 }
1441 cmd->state = UB_CMDST_DONE; 1267 cmd->state = UB_CMDST_DONE;
1442 ub_cmdtr_state(sc, cmd);
1443 ub_cmdq_pop(sc); 1268 ub_cmdq_pop(sc);
1444 (*cmd->done)(sc, cmd); 1269 (*cmd->done)(sc, cmd);
1445 1270
@@ -1494,7 +1319,6 @@ static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1494 add_timer(&sc->work_timer); 1319 add_timer(&sc->work_timer);
1495 1320
1496 cmd->state = UB_CMDST_DATA; 1321 cmd->state = UB_CMDST_DATA;
1497 ub_cmdtr_state(sc, cmd);
1498} 1322}
1499 1323
1500/* 1324/*
@@ -1506,7 +1330,6 @@ static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc)
1506 1330
1507 cmd->error = rc; 1331 cmd->error = rc;
1508 cmd->state = UB_CMDST_DONE; 1332 cmd->state = UB_CMDST_DONE;
1509 ub_cmdtr_state(sc, cmd);
1510 ub_cmdq_pop(sc); 1333 ub_cmdq_pop(sc);
1511 (*cmd->done)(sc, cmd); 1334 (*cmd->done)(sc, cmd);
1512} 1335}
@@ -1552,7 +1375,6 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1552 1375
1553 cmd->stat_count = 0; 1376 cmd->stat_count = 0;
1554 cmd->state = UB_CMDST_STAT; 1377 cmd->state = UB_CMDST_STAT;
1555 ub_cmdtr_state(sc, cmd);
1556} 1378}
1557 1379
1558/* 1380/*
@@ -1571,7 +1393,6 @@ static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1571 return; 1393 return;
1572 1394
1573 cmd->state = UB_CMDST_STAT; 1395 cmd->state = UB_CMDST_STAT;
1574 ub_cmdtr_state(sc, cmd);
1575} 1396}
1576 1397
1577/* 1398/*
@@ -1609,7 +1430,6 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
1609 scmd->tag = sc->tagcnt++; 1430 scmd->tag = sc->tagcnt++;
1610 1431
1611 cmd->state = UB_CMDST_SENSE; 1432 cmd->state = UB_CMDST_SENSE;
1612 ub_cmdtr_state(sc, cmd);
1613 1433
1614 ub_cmdq_insert(sc, scmd); 1434 ub_cmdq_insert(sc, scmd);
1615 return; 1435 return;
@@ -1666,11 +1486,6 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
1666 struct ub_scsi_cmd *cmd; 1486 struct ub_scsi_cmd *cmd;
1667 1487
1668 /* 1488 /*
1669 * Ignoring scmd->act_len, because the buffer was pre-zeroed.
1670 */
1671 ub_cmdtr_sense(sc, scmd, sense);
1672
1673 /*
1674 * Find the command which triggered the unit attention or a check, 1489 * Find the command which triggered the unit attention or a check,
1675 * save the sense into it, and advance its state machine. 1490 * save the sense into it, and advance its state machine.
1676 */ 1491 */
@@ -1691,6 +1506,9 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
1691 return; 1506 return;
1692 } 1507 }
1693 1508
1509 /*
1510 * Ignoring scmd->act_len, because the buffer was pre-zeroed.
1511 */
1694 cmd->key = sense[2] & 0x0F; 1512 cmd->key = sense[2] & 0x0F;
1695 cmd->asc = sense[12]; 1513 cmd->asc = sense[12];
1696 cmd->ascq = sense[13]; 1514 cmd->ascq = sense[13];
@@ -2413,9 +2231,6 @@ static int ub_probe(struct usb_interface *intf,
2413 if (ub_get_pipes(sc, sc->dev, intf) != 0) 2231 if (ub_get_pipes(sc, sc->dev, intf) != 0)
2414 goto err_dev_desc; 2232 goto err_dev_desc;
2415 2233
2416 if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0)
2417 goto err_diag;
2418
2419 /* 2234 /*
2420 * At this point, all USB initialization is done, do upper layer. 2235 * At this point, all USB initialization is done, do upper layer.
2421 * We really hate halfway initialized structures, so from the 2236 * We really hate halfway initialized structures, so from the
@@ -2480,8 +2295,6 @@ static int ub_probe(struct usb_interface *intf,
2480 } 2295 }
2481 return 0; 2296 return 0;
2482 2297
2483 /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
2484err_diag:
2485err_dev_desc: 2298err_dev_desc:
2486 usb_set_intfdata(intf, NULL); 2299 usb_set_intfdata(intf, NULL);
2487 // usb_put_intf(sc->intf); 2300 // usb_put_intf(sc->intf);
@@ -2609,7 +2422,6 @@ static void ub_disconnect(struct usb_interface *intf)
2609 while ((cmd = ub_cmdq_peek(sc)) != NULL) { 2422 while ((cmd = ub_cmdq_peek(sc)) != NULL) {
2610 cmd->error = -ENOTCONN; 2423 cmd->error = -ENOTCONN;
2611 cmd->state = UB_CMDST_DONE; 2424 cmd->state = UB_CMDST_DONE;
2612 ub_cmdtr_state(sc, cmd);
2613 ub_cmdq_pop(sc); 2425 ub_cmdq_pop(sc);
2614 (*cmd->done)(sc, cmd); 2426 (*cmd->done)(sc, cmd);
2615 cnt++; 2427 cnt++;
@@ -2660,7 +2472,6 @@ static void ub_disconnect(struct usb_interface *intf)
2660 * and no URBs left in transit. 2472 * and no URBs left in transit.
2661 */ 2473 */
2662 2474
2663 device_remove_file(&sc->intf->dev, &dev_attr_diag);
2664 usb_set_intfdata(intf, NULL); 2475 usb_set_intfdata(intf, NULL);
2665 // usb_put_intf(sc->intf); 2476 // usb_put_intf(sc->intf);
2666 sc->intf = NULL; 2477 sc->intf = NULL;