Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c6a33e24 authored by Albert Lee's avatar Albert Lee Committed by Jeff Garzik
Browse files

[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: default avatarAlbert Lee <albertcc@tw.ibm.com>

=====
Signed-off-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 59a10b17
Loading
Loading
Loading
Loading
+21 −27
Original line number Diff line number Diff line
@@ -636,9 +636,13 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
	if (dev->flags & ATA_DFLAG_LBA) {
		tf->flags |= ATA_TFLAG_LBA;

		if (dev->flags & ATA_DFLAG_LBA48) {
			if (n_block > (64 * 1024))
				goto invalid_fld;
		if (lba_28_ok(block, n_block)) {
			/* use LBA28 */
			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 */
			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_lbam = (block >> 32) & 0xff;
			tf->hob_lbal = (block >> 24) & 0xff;
		} else {
			if (n_block > 256)
				goto invalid_fld;

			/* use LBA28 */
			tf->command = ATA_CMD_VERIFY;

			tf->device |= (block >> 24) & 0xf;
		}
		} else
			/* request too large even for LBA48 */
			goto out_of_range;

		tf->nsect = n_block & 0xff;

@@ -670,8 +668,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
		/* CHS */
		u32 sect, head, cyl, track;

		if (n_block > 256)
			goto invalid_fld;
		if (!lba_28_ok(block, n_block))
			goto out_of_range;

		/* Convert LBA to CHS */
		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) {
		tf->flags |= ATA_TFLAG_LBA;

		if (dev->flags & ATA_DFLAG_LBA48) {
			/* The request -may- be too large for LBA48. */
			if ((block >> 48) || (n_block > 65536))
		if (lba_28_ok(block, n_block)) {
			/* use LBA28 */
			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 */
@@ -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_lbam = (block >> 32) & 0xff;
			tf->hob_lbal = (block >> 24) & 0xff;
		} else { 
			/* use LBA28 */

			/* The request -may- be too large for LBA28. */
			if ((block >> 28) || (n_block > 256))
		} else
			/* request too large even for LBA48 */
			goto out_of_range;

			tf->device |= (block >> 24) & 0xf;
		}

		ata_rwcmd_protocol(qc);

		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;

		/* 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;

		ata_rwcmd_protocol(qc);
+12 −0
Original line number Diff line number Diff line
@@ -291,4 +291,16 @@ static inline int ata_ok(u8 status)
			== 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__ */