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 2aef41112c43..e2f298b2ade6 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -969,9 +969,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc | |||
969 | if (dev->flags & ATA_DFLAG_LBA) { | 969 | if (dev->flags & ATA_DFLAG_LBA) { |
970 | tf->flags |= ATA_TFLAG_LBA; | 970 | tf->flags |= ATA_TFLAG_LBA; |
971 | 971 | ||
972 | if (dev->flags & ATA_DFLAG_LBA48) { | 972 | if (lba_28_ok(block, n_block)) { |
973 | if (n_block > (64 * 1024)) | 973 | /* use LBA28 */ |
974 | goto invalid_fld; | 974 | tf->command = ATA_CMD_VERIFY; |
975 | tf->device |= (block >> 24) & 0xf; | ||
976 | } else if (lba_48_ok(block, n_block)) { | ||
977 | if (!(dev->flags & ATA_DFLAG_LBA48)) | ||
978 | goto out_of_range; | ||
975 | 979 | ||
976 | /* use LBA48 */ | 980 | /* use LBA48 */ |
977 | tf->flags |= ATA_TFLAG_LBA48; | 981 | tf->flags |= ATA_TFLAG_LBA48; |
@@ -982,15 +986,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc | |||
982 | tf->hob_lbah = (block >> 40) & 0xff; | 986 | tf->hob_lbah = (block >> 40) & 0xff; |
983 | tf->hob_lbam = (block >> 32) & 0xff; | 987 | tf->hob_lbam = (block >> 32) & 0xff; |
984 | tf->hob_lbal = (block >> 24) & 0xff; | 988 | tf->hob_lbal = (block >> 24) & 0xff; |
985 | } else { | 989 | } else |
986 | if (n_block > 256) | 990 | /* request too large even for LBA48 */ |
987 | goto invalid_fld; | 991 | goto out_of_range; |
988 | |||
989 | /* use LBA28 */ | ||
990 | tf->command = ATA_CMD_VERIFY; | ||
991 | |||
992 | tf->device |= (block >> 24) & 0xf; | ||
993 | } | ||
994 | 992 | ||
995 | tf->nsect = n_block & 0xff; | 993 | tf->nsect = n_block & 0xff; |
996 | 994 | ||
@@ -1003,8 +1001,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc | |||
1003 | /* CHS */ | 1001 | /* CHS */ |
1004 | u32 sect, head, cyl, track; | 1002 | u32 sect, head, cyl, track; |
1005 | 1003 | ||
1006 | if (n_block > 256) | 1004 | if (!lba_28_ok(block, n_block)) |
1007 | goto invalid_fld; | 1005 | goto out_of_range; |
1008 | 1006 | ||
1009 | /* Convert LBA to CHS */ | 1007 | /* Convert LBA to CHS */ |
1010 | track = (u32)block / dev->sectors; | 1008 | track = (u32)block / dev->sectors; |
@@ -1119,9 +1117,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1119 | if (dev->flags & ATA_DFLAG_LBA) { | 1117 | if (dev->flags & ATA_DFLAG_LBA) { |
1120 | tf->flags |= ATA_TFLAG_LBA; | 1118 | tf->flags |= ATA_TFLAG_LBA; |
1121 | 1119 | ||
1122 | if (dev->flags & ATA_DFLAG_LBA48) { | 1120 | if (lba_28_ok(block, n_block)) { |
1123 | /* The request -may- be too large for LBA48. */ | 1121 | /* use LBA28 */ |
1124 | if ((block >> 48) || (n_block > 65536)) | 1122 | tf->device |= (block >> 24) & 0xf; |
1123 | } else if (lba_48_ok(block, n_block)) { | ||
1124 | if (!(dev->flags & ATA_DFLAG_LBA48)) | ||
1125 | goto out_of_range; | 1125 | goto out_of_range; |
1126 | 1126 | ||
1127 | /* use LBA48 */ | 1127 | /* use LBA48 */ |
@@ -1132,15 +1132,9 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1132 | tf->hob_lbah = (block >> 40) & 0xff; | 1132 | tf->hob_lbah = (block >> 40) & 0xff; |
1133 | tf->hob_lbam = (block >> 32) & 0xff; | 1133 | tf->hob_lbam = (block >> 32) & 0xff; |
1134 | tf->hob_lbal = (block >> 24) & 0xff; | 1134 | tf->hob_lbal = (block >> 24) & 0xff; |
1135 | } else { | 1135 | } else |
1136 | /* use LBA28 */ | 1136 | /* request too large even for LBA48 */ |
1137 | 1137 | goto out_of_range; | |
1138 | /* The request -may- be too large for LBA28. */ | ||
1139 | if ((block >> 28) || (n_block > 256)) | ||
1140 | goto out_of_range; | ||
1141 | |||
1142 | tf->device |= (block >> 24) & 0xf; | ||
1143 | } | ||
1144 | 1138 | ||
1145 | ata_rwcmd_protocol(qc); | 1139 | ata_rwcmd_protocol(qc); |
1146 | 1140 | ||
@@ -1157,7 +1151,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1157 | u32 sect, head, cyl, track; | 1151 | u32 sect, head, cyl, track; |
1158 | 1152 | ||
1159 | /* The request -may- be too large for CHS addressing. */ | 1153 | /* The request -may- be too large for CHS addressing. */ |
1160 | if ((block >> 28) || (n_block > 256)) | 1154 | if (!lba_28_ok(block, n_block)) |
1161 | goto out_of_range; | 1155 | goto out_of_range; |
1162 | 1156 | ||
1163 | ata_rwcmd_protocol(qc); | 1157 | ata_rwcmd_protocol(qc); |
diff --git a/include/linux/ata.h b/include/linux/ata.h index d2873b732bb1..9245b97845aa 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -296,4 +296,16 @@ static inline int ata_ok(u8 status) | |||
296 | == ATA_DRDY); | 296 | == ATA_DRDY); |
297 | } | 297 | } |
298 | 298 | ||
299 | static inline int lba_28_ok(u64 block, u32 n_block) | ||
300 | { | ||
301 | /* check the ending block number */ | ||
302 | return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); | ||
303 | } | ||
304 | |||
305 | static inline int lba_48_ok(u64 block, u32 n_block) | ||
306 | { | ||
307 | /* check the ending block number */ | ||
308 | return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); | ||
309 | } | ||
310 | |||
299 | #endif /* __LINUX_ATA_H__ */ | 311 | #endif /* __LINUX_ATA_H__ */ |