diff options
author | Albert Lee <albertcc@tw.ibm.com> | 2005-10-12 03:12:26 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-18 17:18:16 -0400 |
commit | c6a33e2464edd87f8c12cc2d11369a5b44c65b77 (patch) | |
tree | f15eb374fa98fb1f76bf3a7cffd9cb8ef7173091 /drivers/scsi/libata-scsi.c | |
parent | 59a10b172fccaea793352c00fd9065f0a5b4ef70 (diff) |
[PATCH] libata CHS: LBA28/LBA48 optimization (revise #6)
- add lba_28_ok() and lba_48_ok() to ata.h.
- check ending block number instead of staring block number.
- use lba_28_ok() for CHS range check
- LBA28/LBA48 optimization
Suggested by Mark Lord and Alan Cox.
Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
=====
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 48 |
1 files changed, 21 insertions, 27 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 90bf22204668..efbe6fe65442 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -636,9 +636,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
636 | if (dev->flags & ATA_DFLAG_LBA) { | 636 | if (dev->flags & ATA_DFLAG_LBA) { |
637 | tf->flags |= ATA_TFLAG_LBA; | 637 | tf->flags |= ATA_TFLAG_LBA; |
638 | 638 | ||
639 | if (dev->flags & ATA_DFLAG_LBA48) { | 639 | if (lba_28_ok(block, n_block)) { |
640 | if (n_block > (64 * 1024)) | 640 | /* use LBA28 */ |
641 | goto invalid_fld; | 641 | tf->command = ATA_CMD_VERIFY; |
642 | tf->device |= (block >> 24) & 0xf; | ||
643 | } else if (lba_48_ok(block, n_block)) { | ||
644 | if (!(dev->flags & ATA_DFLAG_LBA48)) | ||
645 | goto out_of_range; | ||
642 | 646 | ||
643 | /* use LBA48 */ | 647 | /* use LBA48 */ |
644 | tf->flags |= ATA_TFLAG_LBA48; | 648 | tf->flags |= ATA_TFLAG_LBA48; |
@@ -649,15 +653,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
649 | tf->hob_lbah = (block >> 40) & 0xff; | 653 | tf->hob_lbah = (block >> 40) & 0xff; |
650 | tf->hob_lbam = (block >> 32) & 0xff; | 654 | tf->hob_lbam = (block >> 32) & 0xff; |
651 | tf->hob_lbal = (block >> 24) & 0xff; | 655 | tf->hob_lbal = (block >> 24) & 0xff; |
652 | } else { | 656 | } else |
653 | if (n_block > 256) | 657 | /* request too large even for LBA48 */ |
654 | goto invalid_fld; | 658 | goto out_of_range; |
655 | |||
656 | /* use LBA28 */ | ||
657 | tf->command = ATA_CMD_VERIFY; | ||
658 | |||
659 | tf->device |= (block >> 24) & 0xf; | ||
660 | } | ||
661 | 659 | ||
662 | tf->nsect = n_block & 0xff; | 660 | tf->nsect = n_block & 0xff; |
663 | 661 | ||
@@ -670,8 +668,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
670 | /* CHS */ | 668 | /* CHS */ |
671 | u32 sect, head, cyl, track; | 669 | u32 sect, head, cyl, track; |
672 | 670 | ||
673 | if (n_block > 256) | 671 | if (!lba_28_ok(block, n_block)) |
674 | goto invalid_fld; | 672 | goto out_of_range; |
675 | 673 | ||
676 | /* Convert LBA to CHS */ | 674 | /* Convert LBA to CHS */ |
677 | track = (u32)block / dev->sectors; | 675 | track = (u32)block / dev->sectors; |
@@ -784,9 +782,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
784 | if (dev->flags & ATA_DFLAG_LBA) { | 782 | if (dev->flags & ATA_DFLAG_LBA) { |
785 | tf->flags |= ATA_TFLAG_LBA; | 783 | tf->flags |= ATA_TFLAG_LBA; |
786 | 784 | ||
787 | if (dev->flags & ATA_DFLAG_LBA48) { | 785 | if (lba_28_ok(block, n_block)) { |
788 | /* The request -may- be too large for LBA48. */ | 786 | /* use LBA28 */ |
789 | if ((block >> 48) || (n_block > 65536)) | 787 | tf->device |= (block >> 24) & 0xf; |
788 | } else if (lba_48_ok(block, n_block)) { | ||
789 | if (!(dev->flags & ATA_DFLAG_LBA48)) | ||
790 | goto out_of_range; | 790 | goto out_of_range; |
791 | 791 | ||
792 | /* use LBA48 */ | 792 | /* use LBA48 */ |
@@ -797,15 +797,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
797 | tf->hob_lbah = (block >> 40) & 0xff; | 797 | tf->hob_lbah = (block >> 40) & 0xff; |
798 | tf->hob_lbam = (block >> 32) & 0xff; | 798 | tf->hob_lbam = (block >> 32) & 0xff; |
799 | tf->hob_lbal = (block >> 24) & 0xff; | 799 | tf->hob_lbal = (block >> 24) & 0xff; |
800 | } else { | 800 | } else |
801 | /* use LBA28 */ | 801 | /* request too large even for LBA48 */ |
802 | 802 | goto out_of_range; | |
803 | /* The request -may- be too large for LBA28. */ | ||
804 | if ((block >> 28) || (n_block > 256)) | ||
805 | goto out_of_range; | ||
806 | |||
807 | tf->device |= (block >> 24) & 0xf; | ||
808 | } | ||
809 | 803 | ||
810 | ata_rwcmd_protocol(qc); | 804 | ata_rwcmd_protocol(qc); |
811 | 805 | ||
@@ -822,7 +816,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd) | |||
822 | u32 sect, head, cyl, track; | 816 | u32 sect, head, cyl, track; |
823 | 817 | ||
824 | /* The request -may- be too large for CHS addressing. */ | 818 | /* The request -may- be too large for CHS addressing. */ |
825 | if ((block >> 28) || (n_block > 256)) | 819 | if (!lba_28_ok(block, n_block)) |
826 | goto out_of_range; | 820 | goto out_of_range; |
827 | 821 | ||
828 | ata_rwcmd_protocol(qc); | 822 | ata_rwcmd_protocol(qc); |