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

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
...@@ -466,7 +466,7 @@ int ata_acpi_cbl_80wire(struct ata_port *ap) ...@@ -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); ...@@ -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, ...@@ -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) ...@@ -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)
*/ (*nr_executed)++;
tmp = taskfile_load_raw(dev, gtf++);
if (!rc)
rc = tmp;
(*nr_executed)++;
} }
ata_acpi_clear_gtf(dev); ata_acpi_clear_gtf(dev);
return rc; if (rc < 0)
return rc;
return 0;
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment