aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-03-31 14:15:13 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-03-31 14:15:13 -0400
commita08915ba594da66145f33a972db578a58b9135f1 (patch)
treed27379ab4ff2b101a74ffe594e2dfa2939131ee0
parent5ed57ad705d6b58386ac43d2ca1c8fc66aee1101 (diff)
ide-cd: use scatterlists for PIO transfers (fs requests)
* Export ide_pio_bytes(). * Add ->last_xfer_len field to struct ide_cmd. * Add ide_cd_error_cmd() helper to ide-cd. * Convert ide-cd to use scatterlists also for PIO transfers (fs requests only for now) and get rid of partial completions (except when the error happens -- which is still subject to change later because looking at ATAPI spec it seems that the device is free to error the whole transfer with setting the Error bit only on the last transfer chunk). * Update ide_cd_{prepare_rw,restore_request,do_request}() accordingly. * Inline ide_cd_restore_request() into cdrom_start_rw(). Cc: Borislav Petkov <petkovbb@gmail.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
-rw-r--r--drivers/ide/ide-cd.c146
-rw-r--r--drivers/ide/ide-taskfile.c5
-rw-r--r--include/linux/ide.h4
3 files changed, 50 insertions, 105 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 30113e69c8bb..5f15859c2c73 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -539,64 +539,12 @@ static ide_startstop_t ide_cd_prepare_rw_request(ide_drive_t *drive,
539{ 539{
540 ide_debug_log(IDE_DBG_RQ, "rq->cmd_flags: 0x%x", rq->cmd_flags); 540 ide_debug_log(IDE_DBG_RQ, "rq->cmd_flags: 0x%x", rq->cmd_flags);
541 541
542 if (rq_data_dir(rq) == READ) {
543 unsigned short sectors_per_frame =
544 queue_hardsect_size(drive->queue) >> SECTOR_BITS;
545 int nskip = rq->sector & (sectors_per_frame - 1);
546
547 /*
548 * If the requested sector doesn't start on a frame boundary,
549 * we must adjust the start of the transfer so that it does,
550 * and remember to skip the first few sectors.
551 *
552 * If the rq->current_nr_sectors field is larger than the size
553 * of the buffer, it will mean that we're to skip a number of
554 * sectors equal to the amount by which rq->current_nr_sectors
555 * is larger than the buffer size.
556 */
557 if (nskip > 0) {
558 /* sanity check... */
559 if (rq->current_nr_sectors !=
560 bio_cur_sectors(rq->bio)) {
561 printk(KERN_ERR PFX "%s: %s: buffer botch (%u)\n",
562 drive->name, __func__,
563 rq->current_nr_sectors);
564 return ide_stopped;
565 }
566 rq->current_nr_sectors += nskip;
567 }
568 }
569
570 /* set up the command */ 542 /* set up the command */
571 rq->timeout = ATAPI_WAIT_PC; 543 rq->timeout = ATAPI_WAIT_PC;
572 544
573 return ide_started; 545 return ide_started;
574} 546}
575 547
576/*
577 * Fix up a possibly partially-processed request so that we can start it over
578 * entirely, or even put it back on the request queue.
579 */
580static void ide_cd_restore_request(ide_drive_t *drive, struct request *rq)
581{
582
583 ide_debug_log(IDE_DBG_FUNC, "enter");
584
585 if (rq->buffer != bio_data(rq->bio)) {
586 sector_t n =
587 (rq->buffer - (char *)bio_data(rq->bio)) / SECTOR_SIZE;
588
589 rq->buffer = bio_data(rq->bio);
590 rq->nr_sectors += n;
591 rq->sector -= n;
592 }
593 rq->current_nr_sectors = bio_cur_sectors(rq->bio);
594 rq->hard_cur_sectors = rq->current_nr_sectors;
595 rq->hard_nr_sectors = rq->nr_sectors;
596 rq->hard_sector = rq->sector;
597 rq->q->prep_rq_fn(rq->q, rq);
598}
599
600static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq) 548static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct request *rq)
601{ 549{
602 ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]); 550 ide_debug_log(IDE_DBG_FUNC, "rq->cmd[0]: 0x%x", rq->cmd[0]);
@@ -690,6 +638,17 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd,
690 return (flags & REQ_FAILED) ? -EIO : 0; 638 return (flags & REQ_FAILED) ? -EIO : 0;
691} 639}
692 640
641static void ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd)
642{
643 unsigned int nr_bytes = cmd->nbytes - cmd->nleft;
644
645 if (cmd->tf_flags & IDE_TFLAG_WRITE)
646 nr_bytes -= cmd->last_xfer_len;
647
648 if (nr_bytes > 0)
649 ide_complete_rq(drive, 0, nr_bytes);
650}
651
693/* 652/*
694 * Called from blk_end_request_callback() after the data of the request is 653 * Called from blk_end_request_callback() after the data of the request is
695 * completed and before the request itself is completed. By returning value '1', 654 * completed and before the request itself is completed. By returning value '1',
@@ -703,6 +662,7 @@ static int cdrom_newpc_intr_dummy_cb(struct request *rq)
703static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) 662static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
704{ 663{
705 ide_hwif_t *hwif = drive->hwif; 664 ide_hwif_t *hwif = drive->hwif;
665 struct ide_cmd *cmd = &hwif->cmd;
706 struct request *rq = hwif->rq; 666 struct request *rq = hwif->rq;
707 xfer_func_t *xferfunc; 667 xfer_func_t *xferfunc;
708 ide_expiry_t *expiry = NULL; 668 ide_expiry_t *expiry = NULL;
@@ -769,11 +729,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
769 * Otherwise, complete the command normally. 729 * Otherwise, complete the command normally.
770 */ 730 */
771 uptodate = 1; 731 uptodate = 1;
772 if (rq->current_nr_sectors > 0) { 732 if (cmd->nleft > 0) {
773 printk(KERN_ERR PFX "%s: %s: data underrun " 733 printk(KERN_ERR PFX "%s: %s: data underrun "
774 "(%d blocks)\n", 734 "(%u bytes)\n", drive->name, __func__,
775 drive->name, __func__, 735 cmd->nleft);
776 rq->current_nr_sectors);
777 if (!write) 736 if (!write)
778 rq->cmd_flags |= REQ_FAILED; 737 rq->cmd_flags |= REQ_FAILED;
779 uptodate = 0; 738 uptodate = 0;
@@ -795,24 +754,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
795 754
796 if (blk_fs_request(rq)) { 755 if (blk_fs_request(rq)) {
797 if (write == 0) { 756 if (write == 0) {
798 int nskip;
799
800 if (ide_cd_check_transfer_size(drive, len)) 757 if (ide_cd_check_transfer_size(drive, len))
801 goto out_end; 758 goto out_end;
802
803 /*
804 * First, figure out if we need to bit-bucket
805 * any of the leading sectors.
806 */
807 nskip = min_t(int, rq->current_nr_sectors
808 - bio_cur_sectors(rq->bio),
809 thislen >> 9);
810 if (nskip > 0) {
811 ide_pad_transfer(drive, write, nskip << 9);
812 rq->current_nr_sectors -= nskip;
813 thislen -= (nskip << 9);
814 }
815 } 759 }
760 cmd->last_xfer_len = 0;
816 } 761 }
817 762
818 if (ireason == 0) { 763 if (ireason == 0) {
@@ -835,15 +780,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
835 /* bio backed? */ 780 /* bio backed? */
836 if (rq->bio) { 781 if (rq->bio) {
837 if (blk_fs_request(rq)) { 782 if (blk_fs_request(rq)) {
838 ptr = rq->buffer; 783 blen = min_t(int, thislen, cmd->nleft);
839 blen = rq->current_nr_sectors << 9;
840 } else { 784 } else {
841 ptr = bio_data(rq->bio); 785 ptr = bio_data(rq->bio);
842 blen = bio_iovec(rq->bio)->bv_len; 786 blen = bio_iovec(rq->bio)->bv_len;
843 } 787 }
844 } 788 }
845 789
846 if (!ptr) { 790 if ((blk_fs_request(rq) && cmd->nleft == 0) ||
791 (blk_fs_request(rq) == 0 && ptr == NULL)) {
847 if (blk_fs_request(rq) && !write) 792 if (blk_fs_request(rq) && !write)
848 /* 793 /*
849 * If the buffers are full, pipe the rest into 794 * If the buffers are full, pipe the rest into
@@ -863,26 +808,16 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
863 if (blen > thislen) 808 if (blen > thislen)
864 blen = thislen; 809 blen = thislen;
865 810
866 xferfunc(drive, NULL, ptr, blen); 811 if (blk_fs_request(rq)) {
812 ide_pio_bytes(drive, cmd, write, blen);
813 cmd->last_xfer_len += blen;
814 } else
815 xferfunc(drive, NULL, ptr, blen);
867 816
868 thislen -= blen; 817 thislen -= blen;
869 len -= blen; 818 len -= blen;
870 819
871 if (blk_fs_request(rq)) { 820 if (blk_fs_request(rq) == 0) {
872 rq->buffer += blen;
873 rq->nr_sectors -= (blen >> 9);
874 rq->current_nr_sectors -= (blen >> 9);
875 rq->sector += (blen >> 9);
876
877 if (rq->current_nr_sectors == 0 && rq->nr_sectors) {
878 nsectors = rq->hard_cur_sectors;
879
880 if (nsectors == 0)
881 nsectors = 1;
882
883 ide_complete_rq(drive, 0, nsectors << 9);
884 }
885 } else {
886 rq->data_len -= blen; 821 rq->data_len -= blen;
887 822
888 /* 823 /*
@@ -933,8 +868,10 @@ out_end:
933 ide_cd_complete_failed_rq(drive, rq); 868 ide_cd_complete_failed_rq(drive, rq);
934 869
935 if (blk_fs_request(rq)) { 870 if (blk_fs_request(rq)) {
936 if (rq->current_nr_sectors == 0) 871 if (cmd->nleft == 0)
937 uptodate = 1; 872 uptodate = 1;
873 if (uptodate == 0)
874 ide_cd_error_cmd(drive, cmd);
938 } else { 875 } else {
939 if (uptodate <= 0 && rq->errors == 0) 876 if (uptodate <= 0 && rq->errors == 0)
940 rq->errors = -EIO; 877 rq->errors = -EIO;
@@ -944,7 +881,7 @@ out_end:
944 if (blk_pc_request(rq)) 881 if (blk_pc_request(rq))
945 nsectors = (rq->data_len + 511) >> 9; 882 nsectors = (rq->data_len + 511) >> 9;
946 else 883 else
947 nsectors = rq->hard_cur_sectors; 884 nsectors = rq->hard_nr_sectors;
948 885
949 if (nsectors == 0) 886 if (nsectors == 0)
950 nsectors = 1; 887 nsectors = 1;
@@ -960,9 +897,10 @@ out_end:
960static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) 897static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
961{ 898{
962 struct cdrom_info *cd = drive->driver_data; 899 struct cdrom_info *cd = drive->driver_data;
900 struct request_queue *q = drive->queue;
963 int write = rq_data_dir(rq) == WRITE; 901 int write = rq_data_dir(rq) == WRITE;
964 unsigned short sectors_per_frame = 902 unsigned short sectors_per_frame =
965 queue_hardsect_size(drive->queue) >> SECTOR_BITS; 903 queue_hardsect_size(q) >> SECTOR_BITS;
966 904
967 ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, write: 0x%x, " 905 ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, write: 0x%x, "
968 "secs_per_frame: %u", 906 "secs_per_frame: %u",
@@ -977,17 +915,16 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq)
977 * We may be retrying this request after an error. Fix up any 915 * We may be retrying this request after an error. Fix up any
978 * weirdness which might be present in the request packet. 916 * weirdness which might be present in the request packet.
979 */ 917 */
980 ide_cd_restore_request(drive, rq); 918 q->prep_rq_fn(q, rq);
981 } 919 }
982 920
983 /* use DMA, if possible / writes *must* be hardware frame aligned */ 921 /* fs requests *must* be hardware frame aligned */
984 if ((rq->nr_sectors & (sectors_per_frame - 1)) || 922 if ((rq->nr_sectors & (sectors_per_frame - 1)) ||
985 (rq->sector & (sectors_per_frame - 1))) { 923 (rq->sector & (sectors_per_frame - 1)))
986 if (write) 924 return ide_stopped;
987 return ide_stopped; 925
988 drive->dma = 0; 926 /* use DMA, if possible */
989 } else 927 drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
990 drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA);
991 928
992 if (write) 929 if (write)
993 cd->devinfo.media_written = 1; 930 cd->devinfo.media_written = 1;
@@ -1050,8 +987,6 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
1050 if (blk_fs_request(rq)) { 987 if (blk_fs_request(rq)) {
1051 if (cdrom_start_rw(drive, rq) == ide_stopped || 988 if (cdrom_start_rw(drive, rq) == ide_stopped ||
1052 ide_cd_prepare_rw_request(drive, rq) == ide_stopped) { 989 ide_cd_prepare_rw_request(drive, rq) == ide_stopped) {
1053 if (rq->current_nr_sectors == 0)
1054 uptodate = 1;
1055 goto out_end; 990 goto out_end;
1056 } 991 }
1057 } else if (blk_sense_request(rq) || blk_pc_request(rq) || 992 } else if (blk_sense_request(rq) || blk_pc_request(rq) ||
@@ -1078,6 +1013,11 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq,
1078 1013
1079 cmd.rq = rq; 1014 cmd.rq = rq;
1080 1015
1016 if (blk_fs_request(rq)) {
1017 ide_init_sg_cmd(&cmd, rq->nr_sectors << 9);
1018 ide_map_sg(drive, &cmd);
1019 }
1020
1081 return ide_issue_pc(drive, &cmd); 1021 return ide_issue_pc(drive, &cmd);
1082out_end: 1022out_end:
1083 nsectors = rq->hard_nr_sectors; 1023 nsectors = rq->hard_nr_sectors;
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
index 0e333ecf2ad6..a3b7a50562b2 100644
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -188,8 +188,8 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
188 return stat; 188 return stat;
189} 189}
190 190
191static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd, 191void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
192 unsigned int write, unsigned int len) 192 unsigned int write, unsigned int len)
193{ 193{
194 ide_hwif_t *hwif = drive->hwif; 194 ide_hwif_t *hwif = drive->hwif;
195 struct scatterlist *sg = hwif->sg_table; 195 struct scatterlist *sg = hwif->sg_table;
@@ -243,6 +243,7 @@ static void ide_pio_bytes(ide_drive_t *drive, struct ide_cmd *cmd,
243 len -= nr_bytes; 243 len -= nr_bytes;
244 } 244 }
245} 245}
246EXPORT_SYMBOL_GPL(ide_pio_bytes);
246 247
247static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd, 248static void ide_pio_datablock(ide_drive_t *drive, struct ide_cmd *cmd,
248 unsigned int write) 249 unsigned int write)
diff --git a/include/linux/ide.h b/include/linux/ide.h
index d5d832271f44..c2841c0c36c8 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -352,6 +352,8 @@ struct ide_cmd {
352 352
353 unsigned int nbytes; 353 unsigned int nbytes;
354 unsigned int nleft; 354 unsigned int nleft;
355 unsigned int last_xfer_len;
356
355 struct scatterlist *cursg; 357 struct scatterlist *cursg;
356 unsigned int cursg_ofs; 358 unsigned int cursg_ofs;
357 359
@@ -1226,6 +1228,8 @@ ide_startstop_t ide_issue_pc(ide_drive_t *, struct ide_cmd *);
1226 1228
1227ide_startstop_t do_rw_taskfile(ide_drive_t *, struct ide_cmd *); 1229ide_startstop_t do_rw_taskfile(ide_drive_t *, struct ide_cmd *);
1228 1230
1231void ide_pio_bytes(ide_drive_t *, struct ide_cmd *, unsigned int, unsigned int);
1232
1229void ide_finish_cmd(ide_drive_t *, struct ide_cmd *, u8); 1233void ide_finish_cmd(ide_drive_t *, struct ide_cmd *, u8);
1230 1234
1231int ide_raw_taskfile(ide_drive_t *, struct ide_cmd *, u8 *, u16); 1235int ide_raw_taskfile(ide_drive_t *, struct ide_cmd *, u8 *, u16);