diff options
-rw-r--r-- | drivers/scsi/libata-scsi.c | 48 | ||||
-rw-r--r-- | include/linux/ata.h | 12 |
2 files changed, 33 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); |
diff --git a/include/linux/ata.h b/include/linux/ata.h index 630908c9378b..b7e7e1cb2633 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -291,4 +291,16 @@ static inline int ata_ok(u8 status) | |||
291 | == ATA_DRDY); | 291 | == ATA_DRDY); |
292 | } | 292 | } |
293 | 293 | ||
294 | static inline int lba_28_ok(u64 block, u32 n_block) | ||
295 | { | ||
296 | /* check the ending block number */ | ||
297 | return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); | ||
298 | } | ||
299 | |||
300 | static inline int lba_48_ok(u64 block, u32 n_block) | ||
301 | { | ||
302 | /* check the ending block number */ | ||
303 | return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); | ||
304 | } | ||
305 | |||
294 | #endif /* __LINUX_ATA_H__ */ | 306 | #endif /* __LINUX_ATA_H__ */ |