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

Commit c728a914 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik
Browse files

libata: clean up read/set native_max address functions



Merge ata_read_native_max_addres_ext() into ata_read_native_max_address()
and combine ata_set_native_max_address_ext() and
ata_set_native_max_address() into ata_set_max_sectors().

* reduce duplicate code
* return 0 or -errno depending on error conditions
* report if command fails
* use ATA_LBA instead of 0x40

This is in preparation of ata_hpa_resize() update.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent db6f8759
Loading
Loading
Loading
Loading
+77 −97
Original line number Diff line number Diff line
@@ -863,129 +863,113 @@ static u64 ata_tf_to_lba(struct ata_taskfile *tf)
}

/**
 *	ata_read_native_max_address_ext	-	LBA48 native max query
 *	@dev: Device to query
 *	ata_read_native_max_address - Read native max address
 *	@dev: target device
 *	@max_sectors: out parameter for the result native max address
 *
 *	Perform an LBA48 or LBA28 native size query upon the device in
 *	question.
 *
 *	Perform an LBA48 size query upon the device in question. Return the
 *	actual LBA48 size or zero if the command fails.
 *	RETURNS:
 *	0 on success, -EACCES if command is aborted by the drive.
 *	-EIO on other errors.
 */

static u64 ata_read_native_max_address_ext(struct ata_device *dev)
static int ata_read_native_max_address(struct ata_device *dev, u64 *max_sectors)
{
	unsigned int err;
	unsigned int err_mask;
	struct ata_taskfile tf;
	int lba48 = ata_id_has_lba48(dev->id);

	ata_tf_init(dev, &tf);

	/* always clear all address registers */
	tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;

	if (lba48) {
		tf.command = ATA_CMD_READ_NATIVE_MAX_EXT;
	tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | ATA_TFLAG_ISADDR;
	tf.protocol |= ATA_PROT_NODATA;
	tf.device |= 0x40;
		tf.flags |= ATA_TFLAG_LBA48;
	} else
		tf.command = ATA_CMD_READ_NATIVE_MAX;

	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
	if (err)
		return 0;
	tf.protocol |= ATA_PROT_NODATA;
	tf.device |= ATA_LBA;

	return ata_tf_to_lba48(&tf);
	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
	if (err_mask) {
		ata_dev_printk(dev, KERN_WARNING, "failed to read native "
			       "max address (err_mask=0x%x)\n", err_mask);
		if (err_mask == AC_ERR_DEV && (tf.feature & ATA_ABORTED))
			return -EACCES;
		return -EIO;
	}

/**
 *	ata_read_native_max_address	-	LBA28 native max query
 *	@dev: Device to query
 *
 *	Performa an LBA28 size query upon the device in question. Return the
 *	actual LBA28 size or zero if the command fails.
 */

static u64 ata_read_native_max_address(struct ata_device *dev)
{
	unsigned int err;
	struct ata_taskfile tf;

	ata_tf_init(dev, &tf);

	tf.command = ATA_CMD_READ_NATIVE_MAX;
	tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;
	tf.protocol |= ATA_PROT_NODATA;
	tf.device |= 0x40;
	if (lba48)
		*max_sectors = ata_tf_to_lba48(&tf);
	else
		*max_sectors = ata_tf_to_lba(&tf);

	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
	if (err)
	return 0;

	return ata_tf_to_lba(&tf);
}

/**
 *	ata_set_native_max_address_ext	-	LBA48 native max set
 *	@dev: Device to query
 *	ata_set_max_sectors - Set max sectors
 *	@dev: target device
 *	@new_sectors: new max sectors value to set for the device
 *	@res_sectors: result max sectors
 *
 *	Perform an LBA48 size set max upon the device in question. Return the
 *	actual LBA48 size or zero if the command fails.
 *	Set max sectors of @dev to @new_sectors.
 *
 *	RETURNS:
 *	0 on success, -EACCES if command is aborted or denied (due to
 *	previous non-volatile SET_MAX) by the drive.  -EIO on other
 *	errors.
 */

static u64 ata_set_native_max_address_ext(struct ata_device *dev, u64 new_sectors)
static int ata_set_max_sectors(struct ata_device *dev, u64 new_sectors,
			       u64 *res_sectors)
{
	unsigned int err;
	unsigned int err_mask;
	struct ata_taskfile tf;
	int lba48 = ata_id_has_lba48(dev->id);

	new_sectors--;

	ata_tf_init(dev, &tf);

	tf.command = ATA_CMD_SET_MAX_EXT;
	tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_LBA48 | ATA_TFLAG_ISADDR;
	tf.protocol |= ATA_PROT_NODATA;
	tf.device |= 0x40;
	tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;

	tf.lbal = (new_sectors >> 0) & 0xff;
	tf.lbam = (new_sectors >> 8) & 0xff;
	tf.lbah = (new_sectors >> 16) & 0xff;
	if (lba48) {
		tf.command = ATA_CMD_SET_MAX_EXT;
		tf.flags |= ATA_TFLAG_LBA48;

		tf.hob_lbal = (new_sectors >> 24) & 0xff;
		tf.hob_lbam = (new_sectors >> 32) & 0xff;
		tf.hob_lbah = (new_sectors >> 40) & 0xff;

	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
	if (err)
		return 0;

	return ata_tf_to_lba48(&tf);
}

/**
 *	ata_set_native_max_address	-	LBA28 native max set
 *	@dev: Device to query
 *	@new_sectors: new max sectors value to set for the device
 *
 *	Perform an LBA28 size set max upon the device in question. Return the
 *	actual LBA28 size or zero if the command fails.
 */

static u64 ata_set_native_max_address(struct ata_device *dev, u64 new_sectors)
{
	unsigned int err;
	struct ata_taskfile tf;

	new_sectors--;

	ata_tf_init(dev, &tf);

	} else
		tf.command = ATA_CMD_SET_MAX;
	tf.flags |= ATA_TFLAG_DEVICE | ATA_TFLAG_ISADDR;

	tf.protocol |= ATA_PROT_NODATA;
	tf.device |= ATA_LBA;

	tf.lbal = (new_sectors >> 0) & 0xff;
	tf.lbam = (new_sectors >> 8) & 0xff;
	tf.lbah = (new_sectors >> 16) & 0xff;
	tf.device |= ((new_sectors >> 24) & 0x0f) | 0x40;

	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
	if (err)
		return 0;
	err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
	if (err_mask) {
		ata_dev_printk(dev, KERN_WARNING, "failed to set "
			       "max address (err_mask=0x%x)\n", err_mask);
		if (err_mask == AC_ERR_DEV &&
		    (tf.feature & (ATA_ABORTED | ATA_IDNF)))
			return -EACCES;
		return -EIO;
	}

	if (lba48)
		*res_sectors = ata_tf_to_lba48(&tf);
	else
		*res_sectors = ata_tf_to_lba(&tf);

	return ata_tf_to_lba(&tf);
	return 0;
}

/**
@@ -1001,11 +985,11 @@ static u64 ata_hpa_resize(struct ata_device *dev)
{
	u64 sectors = dev->n_sectors;
	u64 hpa_sectors;
	int rc;

	if (ata_id_has_lba48(dev->id))
		hpa_sectors = ata_read_native_max_address_ext(dev);
	else
		hpa_sectors = ata_read_native_max_address(dev);
	rc = ata_read_native_max_address(dev, &hpa_sectors);
	if (rc)
		return 0;

	if (hpa_sectors > sectors) {
		ata_dev_printk(dev, KERN_INFO,
@@ -1015,13 +999,9 @@ static u64 ata_hpa_resize(struct ata_device *dev)
			(long long)sectors, (long long)hpa_sectors);

		if (ata_ignore_hpa) {
			if (ata_id_has_lba48(dev->id))
				hpa_sectors = ata_set_native_max_address_ext(dev, hpa_sectors);
			else
				hpa_sectors = ata_set_native_max_address(dev,
								hpa_sectors);
			rc = ata_set_max_sectors(dev, hpa_sectors, &hpa_sectors);

			if (hpa_sectors) {
			if (rc == 0) {
				ata_dev_printk(dev, KERN_INFO, "native size "
					"increased to %lld sectors\n",
					(long long)hpa_sectors);