diff options
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r-- | drivers/ide/ide-tape.c | 123 |
1 files changed, 46 insertions, 77 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 4e6181c7bbda..64dfa7458f8d 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -152,11 +152,6 @@ struct idetape_bh { | |||
152 | #define IDETAPE_LU_RETENSION_MASK 2 | 152 | #define IDETAPE_LU_RETENSION_MASK 2 |
153 | #define IDETAPE_LU_EOT_MASK 4 | 153 | #define IDETAPE_LU_EOT_MASK 4 |
154 | 154 | ||
155 | /* Error codes returned in rq->errors to the higher part of the driver. */ | ||
156 | #define IDETAPE_ERROR_GENERAL 101 | ||
157 | #define IDETAPE_ERROR_FILEMARK 102 | ||
158 | #define IDETAPE_ERROR_EOD 103 | ||
159 | |||
160 | /* Structures related to the SELECT SENSE / MODE SENSE packet commands. */ | 155 | /* Structures related to the SELECT SENSE / MODE SENSE packet commands. */ |
161 | #define IDETAPE_BLOCK_DESCRIPTOR 0 | 156 | #define IDETAPE_BLOCK_DESCRIPTOR 0 |
162 | #define IDETAPE_CAPABILITIES_PAGE 0x2a | 157 | #define IDETAPE_CAPABILITIES_PAGE 0x2a |
@@ -171,14 +166,6 @@ typedef struct ide_tape_obj { | |||
171 | struct gendisk *disk; | 166 | struct gendisk *disk; |
172 | struct device dev; | 167 | struct device dev; |
173 | 168 | ||
174 | /* | ||
175 | * failed_pc points to the last failed packet command, or contains | ||
176 | * NULL if we do not need to retry any packet command. This is | ||
177 | * required since an additional packet command is needed before the | ||
178 | * retry, to get detailed information on what went wrong. | ||
179 | */ | ||
180 | /* Last failed packet command */ | ||
181 | struct ide_atapi_pc *failed_pc; | ||
182 | /* used by REQ_IDETAPE_{READ,WRITE} requests */ | 169 | /* used by REQ_IDETAPE_{READ,WRITE} requests */ |
183 | struct ide_atapi_pc queued_pc; | 170 | struct ide_atapi_pc queued_pc; |
184 | 171 | ||
@@ -245,9 +232,6 @@ typedef struct ide_tape_obj { | |||
245 | /* Wasted space in each stage */ | 232 | /* Wasted space in each stage */ |
246 | int excess_bh_size; | 233 | int excess_bh_size; |
247 | 234 | ||
248 | /* protects the ide-tape queue */ | ||
249 | spinlock_t lock; | ||
250 | |||
251 | /* Measures average tape speed */ | 235 | /* Measures average tape speed */ |
252 | unsigned long avg_time; | 236 | unsigned long avg_time; |
253 | int avg_size; | 237 | int avg_size; |
@@ -400,7 +384,7 @@ static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) | |||
400 | static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | 384 | static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) |
401 | { | 385 | { |
402 | idetape_tape_t *tape = drive->driver_data; | 386 | idetape_tape_t *tape = drive->driver_data; |
403 | struct ide_atapi_pc *pc = tape->failed_pc; | 387 | struct ide_atapi_pc *pc = drive->failed_pc; |
404 | 388 | ||
405 | tape->sense_key = sense[2] & 0xF; | 389 | tape->sense_key = sense[2] & 0xF; |
406 | tape->asc = sense[12]; | 390 | tape->asc = sense[12]; |
@@ -433,19 +417,19 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | |||
433 | } | 417 | } |
434 | } | 418 | } |
435 | if (pc->c[0] == READ_6 && (sense[2] & 0x80)) { | 419 | if (pc->c[0] == READ_6 && (sense[2] & 0x80)) { |
436 | pc->error = IDETAPE_ERROR_FILEMARK; | 420 | pc->error = IDE_DRV_ERROR_FILEMARK; |
437 | pc->flags |= PC_FLAG_ABORT; | 421 | pc->flags |= PC_FLAG_ABORT; |
438 | } | 422 | } |
439 | if (pc->c[0] == WRITE_6) { | 423 | if (pc->c[0] == WRITE_6) { |
440 | if ((sense[2] & 0x40) || (tape->sense_key == 0xd | 424 | if ((sense[2] & 0x40) || (tape->sense_key == 0xd |
441 | && tape->asc == 0x0 && tape->ascq == 0x2)) { | 425 | && tape->asc == 0x0 && tape->ascq == 0x2)) { |
442 | pc->error = IDETAPE_ERROR_EOD; | 426 | pc->error = IDE_DRV_ERROR_EOD; |
443 | pc->flags |= PC_FLAG_ABORT; | 427 | pc->flags |= PC_FLAG_ABORT; |
444 | } | 428 | } |
445 | } | 429 | } |
446 | if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { | 430 | if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { |
447 | if (tape->sense_key == 8) { | 431 | if (tape->sense_key == 8) { |
448 | pc->error = IDETAPE_ERROR_EOD; | 432 | pc->error = IDE_DRV_ERROR_EOD; |
449 | pc->flags |= PC_FLAG_ABORT; | 433 | pc->flags |= PC_FLAG_ABORT; |
450 | } | 434 | } |
451 | if (!(pc->flags & PC_FLAG_ABORT) && | 435 | if (!(pc->flags & PC_FLAG_ABORT) && |
@@ -477,52 +461,23 @@ static void ide_tape_kfree_buffer(idetape_tape_t *tape) | |||
477 | } | 461 | } |
478 | } | 462 | } |
479 | 463 | ||
480 | static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) | ||
481 | { | ||
482 | struct request *rq = drive->hwif->rq; | ||
483 | idetape_tape_t *tape = drive->driver_data; | ||
484 | unsigned long flags; | ||
485 | int error; | ||
486 | |||
487 | debug_log(DBG_PROCS, "Enter %s\n", __func__); | ||
488 | |||
489 | switch (uptodate) { | ||
490 | case 0: error = IDETAPE_ERROR_GENERAL; break; | ||
491 | case 1: error = 0; break; | ||
492 | default: error = uptodate; | ||
493 | } | ||
494 | rq->errors = error; | ||
495 | if (error) | ||
496 | tape->failed_pc = NULL; | ||
497 | |||
498 | if (!blk_special_request(rq)) { | ||
499 | ide_end_request(drive, uptodate, nr_sects); | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | spin_lock_irqsave(&tape->lock, flags); | ||
504 | |||
505 | ide_end_drive_cmd(drive, 0, 0); | ||
506 | |||
507 | spin_unlock_irqrestore(&tape->lock, flags); | ||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static void ide_tape_handle_dsc(ide_drive_t *); | 464 | static void ide_tape_handle_dsc(ide_drive_t *); |
512 | 465 | ||
513 | static void ide_tape_callback(ide_drive_t *drive, int dsc) | 466 | static int ide_tape_callback(ide_drive_t *drive, int dsc) |
514 | { | 467 | { |
515 | idetape_tape_t *tape = drive->driver_data; | 468 | idetape_tape_t *tape = drive->driver_data; |
516 | struct ide_atapi_pc *pc = drive->pc; | 469 | struct ide_atapi_pc *pc = drive->pc; |
470 | struct request *rq = drive->hwif->rq; | ||
517 | int uptodate = pc->error ? 0 : 1; | 471 | int uptodate = pc->error ? 0 : 1; |
472 | int err = uptodate ? 0 : IDE_DRV_ERROR_GENERAL; | ||
518 | 473 | ||
519 | debug_log(DBG_PROCS, "Enter %s\n", __func__); | 474 | debug_log(DBG_PROCS, "Enter %s\n", __func__); |
520 | 475 | ||
521 | if (dsc) | 476 | if (dsc) |
522 | ide_tape_handle_dsc(drive); | 477 | ide_tape_handle_dsc(drive); |
523 | 478 | ||
524 | if (tape->failed_pc == pc) | 479 | if (drive->failed_pc == pc) |
525 | tape->failed_pc = NULL; | 480 | drive->failed_pc = NULL; |
526 | 481 | ||
527 | if (pc->c[0] == REQUEST_SENSE) { | 482 | if (pc->c[0] == REQUEST_SENSE) { |
528 | if (uptodate) | 483 | if (uptodate) |
@@ -531,7 +486,6 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc) | |||
531 | printk(KERN_ERR "ide-tape: Error in REQUEST SENSE " | 486 | printk(KERN_ERR "ide-tape: Error in REQUEST SENSE " |
532 | "itself - Aborting request!\n"); | 487 | "itself - Aborting request!\n"); |
533 | } else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { | 488 | } else if (pc->c[0] == READ_6 || pc->c[0] == WRITE_6) { |
534 | struct request *rq = drive->hwif->rq; | ||
535 | int blocks = pc->xferred / tape->blk_size; | 489 | int blocks = pc->xferred / tape->blk_size; |
536 | 490 | ||
537 | tape->avg_size += blocks * tape->blk_size; | 491 | tape->avg_size += blocks * tape->blk_size; |
@@ -546,8 +500,10 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc) | |||
546 | tape->first_frame += blocks; | 500 | tape->first_frame += blocks; |
547 | rq->current_nr_sectors -= blocks; | 501 | rq->current_nr_sectors -= blocks; |
548 | 502 | ||
549 | if (pc->error) | 503 | if (pc->error) { |
550 | uptodate = pc->error; | 504 | uptodate = 0; |
505 | err = pc->error; | ||
506 | } | ||
551 | } else if (pc->c[0] == READ_POSITION && uptodate) { | 507 | } else if (pc->c[0] == READ_POSITION && uptodate) { |
552 | u8 *readpos = pc->buf; | 508 | u8 *readpos = pc->buf; |
553 | 509 | ||
@@ -561,6 +517,7 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc) | |||
561 | "to the tape\n"); | 517 | "to the tape\n"); |
562 | clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags); | 518 | clear_bit(IDE_AFLAG_ADDRESS_VALID, &drive->atapi_flags); |
563 | uptodate = 0; | 519 | uptodate = 0; |
520 | err = IDE_DRV_ERROR_GENERAL; | ||
564 | } else { | 521 | } else { |
565 | debug_log(DBG_SENSE, "Block Location - %u\n", | 522 | debug_log(DBG_SENSE, "Block Location - %u\n", |
566 | be32_to_cpup((__be32 *)&readpos[4])); | 523 | be32_to_cpup((__be32 *)&readpos[4])); |
@@ -571,7 +528,9 @@ static void ide_tape_callback(ide_drive_t *drive, int dsc) | |||
571 | } | 528 | } |
572 | } | 529 | } |
573 | 530 | ||
574 | idetape_end_request(drive, uptodate, 0); | 531 | rq->errors = err; |
532 | |||
533 | return uptodate; | ||
575 | } | 534 | } |
576 | 535 | ||
577 | /* | 536 | /* |
@@ -621,7 +580,7 @@ static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
621 | * | 580 | * |
622 | * The handling will be done in three stages: | 581 | * The handling will be done in three stages: |
623 | * | 582 | * |
624 | * 1. idetape_issue_pc will send the packet command to the drive, and will set | 583 | * 1. ide_tape_issue_pc will send the packet command to the drive, and will set |
625 | * the interrupt handler to ide_pc_intr. | 584 | * the interrupt handler to ide_pc_intr. |
626 | * | 585 | * |
627 | * 2. On each interrupt, ide_pc_intr will be called. This step will be | 586 | * 2. On each interrupt, ide_pc_intr will be called. This step will be |
@@ -649,8 +608,9 @@ static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | |||
649 | * request. | 608 | * request. |
650 | */ | 609 | */ |
651 | 610 | ||
652 | static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, | 611 | static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, |
653 | struct ide_atapi_pc *pc) | 612 | struct ide_cmd *cmd, |
613 | struct ide_atapi_pc *pc) | ||
654 | { | 614 | { |
655 | idetape_tape_t *tape = drive->driver_data; | 615 | idetape_tape_t *tape = drive->driver_data; |
656 | 616 | ||
@@ -660,8 +620,8 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, | |||
660 | "Two request sense in serial were issued\n"); | 620 | "Two request sense in serial were issued\n"); |
661 | } | 621 | } |
662 | 622 | ||
663 | if (tape->failed_pc == NULL && pc->c[0] != REQUEST_SENSE) | 623 | if (drive->failed_pc == NULL && pc->c[0] != REQUEST_SENSE) |
664 | tape->failed_pc = pc; | 624 | drive->failed_pc = pc; |
665 | 625 | ||
666 | /* Set the current packet command */ | 626 | /* Set the current packet command */ |
667 | drive->pc = pc; | 627 | drive->pc = pc; |
@@ -685,9 +645,9 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, | |||
685 | tape->ascq); | 645 | tape->ascq); |
686 | } | 646 | } |
687 | /* Giving up */ | 647 | /* Giving up */ |
688 | pc->error = IDETAPE_ERROR_GENERAL; | 648 | pc->error = IDE_DRV_ERROR_GENERAL; |
689 | } | 649 | } |
690 | tape->failed_pc = NULL; | 650 | drive->failed_pc = NULL; |
691 | drive->pc_callback(drive, 0); | 651 | drive->pc_callback(drive, 0); |
692 | return ide_stopped; | 652 | return ide_stopped; |
693 | } | 653 | } |
@@ -695,7 +655,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive, | |||
695 | 655 | ||
696 | pc->retries++; | 656 | pc->retries++; |
697 | 657 | ||
698 | return ide_issue_pc(drive); | 658 | return ide_issue_pc(drive, cmd); |
699 | } | 659 | } |
700 | 660 | ||
701 | /* A mode sense command is used to "sense" tape parameters. */ | 661 | /* A mode sense command is used to "sense" tape parameters. */ |
@@ -746,8 +706,8 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) | |||
746 | } | 706 | } |
747 | pc->error = 0; | 707 | pc->error = 0; |
748 | } else { | 708 | } else { |
749 | pc->error = IDETAPE_ERROR_GENERAL; | 709 | pc->error = IDE_DRV_ERROR_GENERAL; |
750 | tape->failed_pc = NULL; | 710 | drive->failed_pc = NULL; |
751 | } | 711 | } |
752 | drive->pc_callback(drive, 0); | 712 | drive->pc_callback(drive, 0); |
753 | return ide_stopped; | 713 | return ide_stopped; |
@@ -790,6 +750,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
790 | idetape_tape_t *tape = drive->driver_data; | 750 | idetape_tape_t *tape = drive->driver_data; |
791 | struct ide_atapi_pc *pc = NULL; | 751 | struct ide_atapi_pc *pc = NULL; |
792 | struct request *postponed_rq = tape->postponed_rq; | 752 | struct request *postponed_rq = tape->postponed_rq; |
753 | struct ide_cmd cmd; | ||
793 | u8 stat; | 754 | u8 stat; |
794 | 755 | ||
795 | debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu," | 756 | debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu," |
@@ -801,13 +762,15 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
801 | /* We do not support buffer cache originated requests. */ | 762 | /* We do not support buffer cache originated requests. */ |
802 | printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " | 763 | printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " |
803 | "request queue (%d)\n", drive->name, rq->cmd_type); | 764 | "request queue (%d)\n", drive->name, rq->cmd_type); |
804 | ide_end_request(drive, 0, 0); | 765 | if (blk_fs_request(rq) == 0 && rq->errors == 0) |
766 | rq->errors = -EIO; | ||
767 | ide_complete_rq(drive, -EIO, ide_rq_bytes(rq)); | ||
805 | return ide_stopped; | 768 | return ide_stopped; |
806 | } | 769 | } |
807 | 770 | ||
808 | /* Retry a failed packet command */ | 771 | /* Retry a failed packet command */ |
809 | if (tape->failed_pc && drive->pc->c[0] == REQUEST_SENSE) { | 772 | if (drive->failed_pc && drive->pc->c[0] == REQUEST_SENSE) { |
810 | pc = tape->failed_pc; | 773 | pc = drive->failed_pc; |
811 | goto out; | 774 | goto out; |
812 | } | 775 | } |
813 | 776 | ||
@@ -815,7 +778,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
815 | if (rq != postponed_rq) { | 778 | if (rq != postponed_rq) { |
816 | printk(KERN_ERR "ide-tape: ide-tape.c bug - " | 779 | printk(KERN_ERR "ide-tape: ide-tape.c bug - " |
817 | "Two DSC requests were queued\n"); | 780 | "Two DSC requests were queued\n"); |
818 | idetape_end_request(drive, 0, 0); | 781 | drive->failed_pc = NULL; |
782 | rq->errors = 0; | ||
783 | ide_complete_rq(drive, 0, blk_rq_bytes(rq)); | ||
819 | return ide_stopped; | 784 | return ide_stopped; |
820 | } | 785 | } |
821 | 786 | ||
@@ -881,7 +846,14 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
881 | BUG(); | 846 | BUG(); |
882 | 847 | ||
883 | out: | 848 | out: |
884 | return idetape_issue_pc(drive, pc); | 849 | memset(&cmd, 0, sizeof(cmd)); |
850 | |||
851 | if (rq_data_dir(rq)) | ||
852 | cmd.tf_flags |= IDE_TFLAG_WRITE; | ||
853 | |||
854 | cmd.rq = rq; | ||
855 | |||
856 | return ide_tape_issue_pc(drive, &cmd, pc); | ||
885 | } | 857 | } |
886 | 858 | ||
887 | /* | 859 | /* |
@@ -1226,7 +1198,7 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, | |||
1226 | 1198 | ||
1227 | if (tape->merge_bh) | 1199 | if (tape->merge_bh) |
1228 | idetape_init_merge_buffer(tape); | 1200 | idetape_init_merge_buffer(tape); |
1229 | if (errors == IDETAPE_ERROR_GENERAL) | 1201 | if (errors == IDE_DRV_ERROR_GENERAL) |
1230 | return -EIO; | 1202 | return -EIO; |
1231 | return ret; | 1203 | return ret; |
1232 | } | 1204 | } |
@@ -2192,8 +2164,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) | |||
2192 | drive->pc_update_buffers = idetape_update_buffers; | 2164 | drive->pc_update_buffers = idetape_update_buffers; |
2193 | drive->pc_io_buffers = ide_tape_io_buffers; | 2165 | drive->pc_io_buffers = ide_tape_io_buffers; |
2194 | 2166 | ||
2195 | spin_lock_init(&tape->lock); | ||
2196 | |||
2197 | drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; | 2167 | drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; |
2198 | 2168 | ||
2199 | if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) { | 2169 | if (drive->hwif->host_flags & IDE_HFLAG_NO_DSC) { |
@@ -2325,7 +2295,6 @@ static struct ide_driver idetape_driver = { | |||
2325 | .remove = ide_tape_remove, | 2295 | .remove = ide_tape_remove, |
2326 | .version = IDETAPE_VERSION, | 2296 | .version = IDETAPE_VERSION, |
2327 | .do_request = idetape_do_request, | 2297 | .do_request = idetape_do_request, |
2328 | .end_request = idetape_end_request, | ||
2329 | #ifdef CONFIG_IDE_PROC_FS | 2298 | #ifdef CONFIG_IDE_PROC_FS |
2330 | .proc_entries = ide_tape_proc_entries, | 2299 | .proc_entries = ide_tape_proc_entries, |
2331 | .proc_devsets = ide_tape_proc_devsets, | 2300 | .proc_devsets = ide_tape_proc_devsets, |