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

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

libata-acpi: improve _GTF execution error handling and reporting



As _GTF commands can't transfer data, device error never signals
transfer error.  It indicates that the device vetoed the operation, so
it's meaningless to retry.

This patch makes libata-acpi to report and continue on device errors
when executing _GTF commands.  Also commands rejected by device don't
contribute to the number of _GTF commands executed.

While at it, update _GTF execution reporting such that all successful
commands are logged at KERN_DEBUG and rename taskfile_load_raw() to
ata_acpi_run_tf() for consistency.

Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 66fa7f21
Loading
Loading
Loading
Loading
+46 −31
Original line number Original line Diff line number Diff line
@@ -466,7 +466,7 @@ int ata_acpi_cbl_80wire(struct ata_port *ap)
EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);


/**
/**
 * taskfile_load_raw - send taskfile registers to host controller
 * ata_acpi_run_tf - send taskfile registers to host controller
 * @dev: target ATA device
 * @dev: target ATA device
 * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
 * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
 *
 *
@@ -485,14 +485,17 @@ EXPORT_SYMBOL_GPL(ata_acpi_cbl_80wire);
 * EH context.
 * EH context.
 *
 *
 * RETURNS:
 * RETURNS:
 * 0 on success, -errno on failure.
 * 1 if command is executed successfully.  0 if ignored or rejected,
 * -errno on other errors.
 */
 */
static int taskfile_load_raw(struct ata_device *dev,
static int ata_acpi_run_tf(struct ata_device *dev,
			   const struct ata_acpi_gtf *gtf)
			   const struct ata_acpi_gtf *gtf)
{
{
	struct ata_port *ap = dev->link->ap;
	struct ata_taskfile tf, rtf;
	struct ata_taskfile tf, rtf;
	unsigned int err_mask;
	unsigned int err_mask;
	const char *level;
	char msg[60];
	int rc;


	if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)
	if ((gtf->tf[0] == 0) && (gtf->tf[1] == 0) && (gtf->tf[2] == 0)
	    && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)
	    && (gtf->tf[3] == 0) && (gtf->tf[4] == 0) && (gtf->tf[5] == 0)
@@ -512,24 +515,39 @@ static int taskfile_load_raw(struct ata_device *dev,
	tf.device  = gtf->tf[5];	/* 0x1f6 */
	tf.device  = gtf->tf[5];	/* 0x1f6 */
	tf.command = gtf->tf[6];	/* 0x1f7 */
	tf.command = gtf->tf[6];	/* 0x1f7 */


	if (ata_msg_probe(ap))
		ata_dev_printk(dev, KERN_DEBUG, "executing ACPI cmd "
			       "%02x/%02x:%02x:%02x:%02x:%02x:%02x\n",
			       tf.command, tf.feature, tf.nsect,
			       tf.lbal, tf.lbam, tf.lbah, tf.device);

	rtf = tf;
	rtf = tf;
	err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0);
	err_mask = ata_exec_internal(dev, &rtf, NULL, DMA_NONE, NULL, 0, 0);
	if (err_mask) {

		ata_dev_printk(dev, KERN_ERR,
	switch (err_mask) {
			"ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x failed "
	case 0:
			"(Emask=0x%x Stat=0x%02x Err=0x%02x)\n",
		level = KERN_DEBUG;
			tf.command, tf.feature, tf.nsect, tf.lbal, tf.lbam,
		snprintf(msg, sizeof(msg), "succeeded");
			tf.lbah, tf.device, err_mask, rtf.command, rtf.feature);
		rc = 1;
		return -EIO;
		break;

	case AC_ERR_DEV:
		level = KERN_INFO;
		snprintf(msg, sizeof(msg),
			 "rejected by device (Stat=0x%02x Err=0x%02x)",
			 rtf.command, rtf.feature);
		rc = 0;
		break;

	default:
		level = KERN_ERR;
		snprintf(msg, sizeof(msg),
			 "failed (Emask=0x%x Stat=0x%02x Err=0x%02x)",
			 err_mask, rtf.command, rtf.feature);
		rc = -EIO;
		break;
	}
	}


	return 0;
	ata_dev_printk(dev, level,
		       "ACPI cmd %02x/%02x:%02x:%02x:%02x:%02x:%02x %s\n",
		       tf.command, tf.feature, tf.nsect, tf.lbal,
		       tf.lbam, tf.lbah, tf.device, msg);

	return rc;
}
}


/**
/**
@@ -558,22 +576,19 @@ static int ata_acpi_exec_tfs(struct ata_device *dev, int *nr_executed)
	gtf_count = rc;
	gtf_count = rc;


	/* execute them */
	/* execute them */
	for (i = 0, rc = 0; i < gtf_count; i++) {
	for (i = 0; i < gtf_count; i++) {
		int tmp;
		rc = ata_acpi_run_tf(dev, gtf++);

		if (rc < 0)
		/* ACPI errors are eventually ignored.  Run till the
			break;
		 * end even after errors.
		if (rc)
		 */
		tmp = taskfile_load_raw(dev, gtf++);
		if (!rc)
			rc = tmp;

			(*nr_executed)++;
			(*nr_executed)++;
	}
	}


	ata_acpi_clear_gtf(dev);
	ata_acpi_clear_gtf(dev);


	if (rc < 0)
		return rc;
		return rc;
	return 0;
}
}


/**
/**