Loading drivers/scsi/libata-scsi.c +21 −27 Original line number Original line Diff line number Diff line Loading @@ -985,9 +985,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc if (dev->flags & ATA_DFLAG_LBA) { if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA; if (dev->flags & ATA_DFLAG_LBA48) { if (lba_28_ok(block, n_block)) { if (n_block > (64 * 1024)) /* use LBA28 */ goto invalid_fld; tf->command = ATA_CMD_VERIFY; tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { if (!(dev->flags & ATA_DFLAG_LBA48)) goto out_of_range; /* use LBA48 */ /* use LBA48 */ tf->flags |= ATA_TFLAG_LBA48; tf->flags |= ATA_TFLAG_LBA48; Loading @@ -998,15 +1002,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { } else if (n_block > 256) /* request too large even for LBA48 */ goto invalid_fld; goto out_of_range; /* use LBA28 */ tf->command = ATA_CMD_VERIFY; tf->device |= (block >> 24) & 0xf; } tf->nsect = n_block & 0xff; tf->nsect = n_block & 0xff; Loading @@ -1019,8 +1017,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc /* CHS */ /* CHS */ u32 sect, head, cyl, track; u32 sect, head, cyl, track; if (n_block > 256) if (!lba_28_ok(block, n_block)) goto invalid_fld; goto out_of_range; /* Convert LBA to CHS */ /* Convert LBA to CHS */ track = (u32)block / dev->sectors; track = (u32)block / dev->sectors; Loading Loading @@ -1139,9 +1137,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm if (dev->flags & ATA_DFLAG_LBA) { if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA; if (dev->flags & ATA_DFLAG_LBA48) { if (lba_28_ok(block, n_block)) { /* The request -may- be too large for LBA48. */ /* use LBA28 */ if ((block >> 48) || (n_block > 65536)) tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { if (!(dev->flags & ATA_DFLAG_LBA48)) goto out_of_range; goto out_of_range; /* use LBA48 */ /* use LBA48 */ Loading @@ -1152,16 +1152,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { } else /* use LBA28 */ /* request too large even for LBA48 */ /* The request -may- be too large for LBA28. */ if ((block >> 28) || (n_block > 256)) goto out_of_range; goto out_of_range; tf->device |= (block >> 24) & 0xf; } if (unlikely(ata_rwcmd_protocol(qc) < 0)) if (unlikely(ata_rwcmd_protocol(qc) < 0)) goto invalid_fld; goto invalid_fld; Loading @@ -1178,7 +1172,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm u32 sect, head, cyl, track; u32 sect, head, cyl, track; /* The request -may- be too large for CHS addressing. */ /* The request -may- be too large for CHS addressing. */ if ((block >> 28) || (n_block > 256)) if (!lba_28_ok(block, n_block)) goto out_of_range; goto out_of_range; if (unlikely(ata_rwcmd_protocol(qc) < 0)) if (unlikely(ata_rwcmd_protocol(qc) < 0)) Loading include/linux/ata.h +12 −0 Original line number Original line Diff line number Diff line Loading @@ -302,4 +302,16 @@ static inline int ata_ok(u8 status) == ATA_DRDY); == ATA_DRDY); } } static inline int lba_28_ok(u64 block, u32 n_block) { /* check the ending block number */ return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); } static inline int lba_48_ok(u64 block, u32 n_block) { /* check the ending block number */ return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); } #endif /* __LINUX_ATA_H__ */ #endif /* __LINUX_ATA_H__ */ Loading
drivers/scsi/libata-scsi.c +21 −27 Original line number Original line Diff line number Diff line Loading @@ -985,9 +985,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc if (dev->flags & ATA_DFLAG_LBA) { if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA; if (dev->flags & ATA_DFLAG_LBA48) { if (lba_28_ok(block, n_block)) { if (n_block > (64 * 1024)) /* use LBA28 */ goto invalid_fld; tf->command = ATA_CMD_VERIFY; tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { if (!(dev->flags & ATA_DFLAG_LBA48)) goto out_of_range; /* use LBA48 */ /* use LBA48 */ tf->flags |= ATA_TFLAG_LBA48; tf->flags |= ATA_TFLAG_LBA48; Loading @@ -998,15 +1002,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { } else if (n_block > 256) /* request too large even for LBA48 */ goto invalid_fld; goto out_of_range; /* use LBA28 */ tf->command = ATA_CMD_VERIFY; tf->device |= (block >> 24) & 0xf; } tf->nsect = n_block & 0xff; tf->nsect = n_block & 0xff; Loading @@ -1019,8 +1017,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, const u8 *sc /* CHS */ /* CHS */ u32 sect, head, cyl, track; u32 sect, head, cyl, track; if (n_block > 256) if (!lba_28_ok(block, n_block)) goto invalid_fld; goto out_of_range; /* Convert LBA to CHS */ /* Convert LBA to CHS */ track = (u32)block / dev->sectors; track = (u32)block / dev->sectors; Loading Loading @@ -1139,9 +1137,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm if (dev->flags & ATA_DFLAG_LBA) { if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; tf->flags |= ATA_TFLAG_LBA; if (dev->flags & ATA_DFLAG_LBA48) { if (lba_28_ok(block, n_block)) { /* The request -may- be too large for LBA48. */ /* use LBA28 */ if ((block >> 48) || (n_block > 65536)) tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { if (!(dev->flags & ATA_DFLAG_LBA48)) goto out_of_range; goto out_of_range; /* use LBA48 */ /* use LBA48 */ Loading @@ -1152,16 +1152,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; } else { } else /* use LBA28 */ /* request too large even for LBA48 */ /* The request -may- be too large for LBA28. */ if ((block >> 28) || (n_block > 256)) goto out_of_range; goto out_of_range; tf->device |= (block >> 24) & 0xf; } if (unlikely(ata_rwcmd_protocol(qc) < 0)) if (unlikely(ata_rwcmd_protocol(qc) < 0)) goto invalid_fld; goto invalid_fld; Loading @@ -1178,7 +1172,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm u32 sect, head, cyl, track; u32 sect, head, cyl, track; /* The request -may- be too large for CHS addressing. */ /* The request -may- be too large for CHS addressing. */ if ((block >> 28) || (n_block > 256)) if (!lba_28_ok(block, n_block)) goto out_of_range; goto out_of_range; if (unlikely(ata_rwcmd_protocol(qc) < 0)) if (unlikely(ata_rwcmd_protocol(qc) < 0)) Loading
include/linux/ata.h +12 −0 Original line number Original line Diff line number Diff line Loading @@ -302,4 +302,16 @@ static inline int ata_ok(u8 status) == ATA_DRDY); == ATA_DRDY); } } static inline int lba_28_ok(u64 block, u32 n_block) { /* check the ending block number */ return ((block + n_block - 1) < ((u64)1 << 28)) && (n_block <= 256); } static inline int lba_48_ok(u64 block, u32 n_block) { /* check the ending block number */ return ((block + n_block - 1) < ((u64)1 << 48)) && (n_block <= 65536); } #endif /* __LINUX_ATA_H__ */ #endif /* __LINUX_ATA_H__ */