[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>
This commit is contained in:
Родитель
59a10b172f
Коммит
c6a33e2464
|
@ -636,9 +636,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
||||||
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;
|
||||||
|
@ -649,15 +653,9 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
||||||
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;
|
||||||
|
|
||||||
|
@ -670,8 +668,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
||||||
/* 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;
|
||||||
|
@ -784,9 +782,11 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
||||||
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 */
|
||||||
|
@ -797,16 +797,10 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ata_rwcmd_protocol(qc);
|
ata_rwcmd_protocol(qc);
|
||||||
|
|
||||||
qc->nsect = n_block;
|
qc->nsect = n_block;
|
||||||
|
@ -822,7 +816,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
|
||||||
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;
|
||||||
|
|
||||||
ata_rwcmd_protocol(qc);
|
ata_rwcmd_protocol(qc);
|
||||||
|
|
|
@ -291,4 +291,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__ */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче