diff options
author | Borislav Petkov <petkovbb@googlemail.com> | 2008-04-26 11:36:37 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-04-26 11:36:37 -0400 |
commit | 968c49641338f4fb71d35352d49b1d25a68c5e93 (patch) | |
tree | fbff834006b20bfac4af6dbc70b951a31bc2f3af /drivers/ide/ide-cd.c | |
parent | 9841654949f0a3f1289b6b95b2ab56cd99fb5360 (diff) |
ide-cd: remove the internal 64k buffer
This removes the internal ide-cd buffer and falls back to read-ahead block layer
capabilities. Thorough testing (cd burning, dvd read, raw read) gives with the
bufferless mode marginally better performance in addition to simplified code.
bufferless:
dd: reading `/dev/hdc': Input/output error
6238+0 records in
6238+0 records out
204406784 bytes (204 MB) copied, 259.891 s, 787 kB/s
real 4m21.598s
user 0m0.014s
sys 0m0.744s
with the old buffer (2.6.25-rc1):
dd: reading `/dev/hdc': Input/output error
6238+0 records in
6238+0 records out
204406784 bytes (204 MB) copied, 262.893 s, 778 kB/s
real 4m22.938s
user 0m0.009s
sys 0m0.771s
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r-- | drivers/ide/ide-cd.c | 123 |
1 files changed, 4 insertions, 119 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index fe5aefbf8339..5163f6069f8a 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -89,7 +89,6 @@ static void cdrom_saw_media_change (ide_drive_t *drive) | |||
89 | 89 | ||
90 | cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED; | 90 | cd->cd_flags |= IDE_CD_FLAG_MEDIA_CHANGED; |
91 | cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID; | 91 | cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID; |
92 | cd->nsectors_buffered = 0; | ||
93 | } | 92 | } |
94 | 93 | ||
95 | static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, | 94 | static int cdrom_log_sense(ide_drive_t *drive, struct request *rq, |
@@ -626,47 +625,6 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects) | |||
626 | } | 625 | } |
627 | 626 | ||
628 | /* | 627 | /* |
629 | * Buffer up to SECTORS_TO_TRANSFER sectors from the drive in our sector | ||
630 | * buffer. Once the first sector is added, any subsequent sectors are | ||
631 | * assumed to be continuous (until the buffer is cleared). For the first | ||
632 | * sector added, SECTOR is its sector number. (SECTOR is then ignored until | ||
633 | * the buffer is cleared.) | ||
634 | */ | ||
635 | static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, | ||
636 | int sectors_to_transfer) | ||
637 | { | ||
638 | struct cdrom_info *info = drive->driver_data; | ||
639 | |||
640 | /* Number of sectors to read into the buffer. */ | ||
641 | int sectors_to_buffer = min_t(int, sectors_to_transfer, | ||
642 | (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - | ||
643 | info->nsectors_buffered); | ||
644 | |||
645 | char *dest; | ||
646 | |||
647 | /* If we couldn't get a buffer, don't try to buffer anything... */ | ||
648 | if (info->buffer == NULL) | ||
649 | sectors_to_buffer = 0; | ||
650 | |||
651 | /* If this is the first sector in the buffer, remember its number. */ | ||
652 | if (info->nsectors_buffered == 0) | ||
653 | info->sector_buffered = sector; | ||
654 | |||
655 | /* Read the data into the buffer. */ | ||
656 | dest = info->buffer + info->nsectors_buffered * SECTOR_SIZE; | ||
657 | while (sectors_to_buffer > 0) { | ||
658 | HWIF(drive)->atapi_input_bytes(drive, dest, SECTOR_SIZE); | ||
659 | --sectors_to_buffer; | ||
660 | --sectors_to_transfer; | ||
661 | ++info->nsectors_buffered; | ||
662 | dest += SECTOR_SIZE; | ||
663 | } | ||
664 | |||
665 | /* Throw away any remaining data. */ | ||
666 | ide_cd_drain_data(drive, sectors_to_transfer); | ||
667 | } | ||
668 | |||
669 | /* | ||
670 | * Check the contents of the interrupt reason register from the cdrom | 628 | * Check the contents of the interrupt reason register from the cdrom |
671 | * and attempt to recover if there are problems. Returns 0 if everything's | 629 | * and attempt to recover if there are problems. Returns 0 if everything's |
672 | * ok; nonzero if the request has been terminated. | 630 | * ok; nonzero if the request has been terminated. |
@@ -734,65 +692,6 @@ static int ide_cd_check_transfer_size(ide_drive_t *drive, int len) | |||
734 | return 1; | 692 | return 1; |
735 | } | 693 | } |
736 | 694 | ||
737 | /* | ||
738 | * Try to satisfy some of the current read request from our cached data. | ||
739 | * Returns nonzero if the request has been completed, zero otherwise. | ||
740 | */ | ||
741 | static int cdrom_read_from_buffer (ide_drive_t *drive) | ||
742 | { | ||
743 | struct cdrom_info *info = drive->driver_data; | ||
744 | struct request *rq = HWGROUP(drive)->rq; | ||
745 | unsigned short sectors_per_frame; | ||
746 | |||
747 | sectors_per_frame = queue_hardsect_size(drive->queue) >> SECTOR_BITS; | ||
748 | |||
749 | /* Can't do anything if there's no buffer. */ | ||
750 | if (info->buffer == NULL) return 0; | ||
751 | |||
752 | /* Loop while this request needs data and the next block is present | ||
753 | in our cache. */ | ||
754 | while (rq->nr_sectors > 0 && | ||
755 | rq->sector >= info->sector_buffered && | ||
756 | rq->sector < info->sector_buffered + info->nsectors_buffered) { | ||
757 | if (rq->current_nr_sectors == 0) | ||
758 | cdrom_end_request(drive, 1); | ||
759 | |||
760 | memcpy (rq->buffer, | ||
761 | info->buffer + | ||
762 | (rq->sector - info->sector_buffered) * SECTOR_SIZE, | ||
763 | SECTOR_SIZE); | ||
764 | rq->buffer += SECTOR_SIZE; | ||
765 | --rq->current_nr_sectors; | ||
766 | --rq->nr_sectors; | ||
767 | ++rq->sector; | ||
768 | } | ||
769 | |||
770 | /* If we've satisfied the current request, | ||
771 | terminate it successfully. */ | ||
772 | if (rq->nr_sectors == 0) { | ||
773 | cdrom_end_request(drive, 1); | ||
774 | return -1; | ||
775 | } | ||
776 | |||
777 | /* Move on to the next buffer if needed. */ | ||
778 | if (rq->current_nr_sectors == 0) | ||
779 | cdrom_end_request(drive, 1); | ||
780 | |||
781 | /* If this condition does not hold, then the kluge i use to | ||
782 | represent the number of sectors to skip at the start of a transfer | ||
783 | will fail. I think that this will never happen, but let's be | ||
784 | paranoid and check. */ | ||
785 | if (rq->current_nr_sectors < bio_cur_sectors(rq->bio) && | ||
786 | (rq->sector & (sectors_per_frame - 1))) { | ||
787 | printk(KERN_ERR "%s: cdrom_read_from_buffer: buffer botch (%ld)\n", | ||
788 | drive->name, (long)rq->sector); | ||
789 | cdrom_end_request(drive, 0); | ||
790 | return -1; | ||
791 | } | ||
792 | |||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); | 695 | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *); |
797 | 696 | ||
798 | /* | 697 | /* |
@@ -1134,11 +1033,9 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1134 | if (!ptr) { | 1033 | if (!ptr) { |
1135 | if (blk_fs_request(rq) && !write) | 1034 | if (blk_fs_request(rq) && !write) |
1136 | /* | 1035 | /* |
1137 | * If the buffers are full, cache the rest | 1036 | * If the buffers are full, pipe the rest into |
1138 | * of the data in our internal buffer. | 1037 | * oblivion. */ |
1139 | */ | 1038 | ide_cd_drain_data(drive, thislen >> 9); |
1140 | cdrom_buffer_sectors(drive, rq->sector, | ||
1141 | thislen >> 9); | ||
1142 | else { | 1039 | else { |
1143 | printk(KERN_ERR "%s: confused, missing data\n", | 1040 | printk(KERN_ERR "%s: confused, missing data\n", |
1144 | drive->name); | 1041 | drive->name); |
@@ -1243,10 +1140,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | |||
1243 | * weirdness which might be present in the request packet. | 1140 | * weirdness which might be present in the request packet. |
1244 | */ | 1141 | */ |
1245 | restore_request(rq); | 1142 | restore_request(rq); |
1246 | |||
1247 | /* Satisfy whatever we can of this request from our cache. */ | ||
1248 | if (cdrom_read_from_buffer(drive)) | ||
1249 | return ide_stopped; | ||
1250 | } | 1143 | } |
1251 | 1144 | ||
1252 | /* | 1145 | /* |
@@ -1262,9 +1155,6 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | |||
1262 | } else | 1155 | } else |
1263 | cd->dma = drive->using_dma; | 1156 | cd->dma = drive->using_dma; |
1264 | 1157 | ||
1265 | /* Clear the local sector buffer. */ | ||
1266 | cd->nsectors_buffered = 0; | ||
1267 | |||
1268 | if (write) | 1158 | if (write) |
1269 | cd->devinfo.media_written = 1; | 1159 | cd->devinfo.media_written = 1; |
1270 | 1160 | ||
@@ -2030,7 +1920,6 @@ static void ide_cd_release(struct kref *kref) | |||
2030 | ide_drive_t *drive = info->drive; | 1920 | ide_drive_t *drive = info->drive; |
2031 | struct gendisk *g = info->disk; | 1921 | struct gendisk *g = info->disk; |
2032 | 1922 | ||
2033 | kfree(info->buffer); | ||
2034 | kfree(info->toc); | 1923 | kfree(info->toc); |
2035 | if (devinfo->handle == drive) | 1924 | if (devinfo->handle == drive) |
2036 | unregister_cdrom(devinfo); | 1925 | unregister_cdrom(devinfo); |
@@ -2090,11 +1979,7 @@ static int idecd_open(struct inode * inode, struct file * file) | |||
2090 | if (!(info = ide_cd_get(disk))) | 1979 | if (!(info = ide_cd_get(disk))) |
2091 | return -ENXIO; | 1980 | return -ENXIO; |
2092 | 1981 | ||
2093 | if (!info->buffer) | 1982 | rc = cdrom_open(&info->devinfo, inode, file); |
2094 | info->buffer = kmalloc(SECTOR_BUFFER_SIZE, GFP_KERNEL|__GFP_REPEAT); | ||
2095 | |||
2096 | if (info->buffer) | ||
2097 | rc = cdrom_open(&info->devinfo, inode, file); | ||
2098 | 1983 | ||
2099 | if (rc < 0) | 1984 | if (rc < 0) |
2100 | ide_cd_put(info); | 1985 | ide_cd_put(info); |