Commit f90f0828 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

libata: stop being overjealous about non-IO commands

libata EH always revalidated device and retried failed command after
error except for ATAPI CCs.  This is unnecessary and hinders with
users issuing direct commands.  This patch makes the following
changes.

* Make sata_sil24 not request ATA_EH_REVALIDATE on device errors.
  sil24 is the only driver which does this.  All others let libata EH
  core code decide.

* Don't request revalidation after device error of non-IO command.
  Revalidation doesn't really help anybody.  As ATA_EH_REVALIDATE
  isn't set by default, there's no reason to clear it after sense data
  is read.  Kill ATA_EH_REVALIDATE clearing code while at it.

* Don't retry non-IO command after device error.  Device has rejected
  the command.  There's no point in retrying.
Signed-off-by: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent b666da35
...@@ -1800,10 +1800,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) ...@@ -1800,10 +1800,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
qc->err_mask &= ~AC_ERR_OTHER; qc->err_mask &= ~AC_ERR_OTHER;
/* SENSE_VALID trumps dev/unknown error and revalidation */ /* SENSE_VALID trumps dev/unknown error and revalidation */
if (qc->flags & ATA_QCFLAG_SENSE_VALID) { if (qc->flags & ATA_QCFLAG_SENSE_VALID)
qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
ehc->i.action &= ~ATA_EH_REVALIDATE;
}
/* accumulate error info */ /* accumulate error info */
ehc->i.dev = qc->dev; ehc->i.dev = qc->dev;
...@@ -1816,7 +1814,8 @@ static void ata_eh_link_autopsy(struct ata_link *link) ...@@ -1816,7 +1814,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
if (ap->pflags & ATA_PFLAG_FROZEN || if (ap->pflags & ATA_PFLAG_FROZEN ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT)) all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
ehc->i.action |= ATA_EH_SOFTRESET; ehc->i.action |= ATA_EH_SOFTRESET;
else if (all_err_mask) else if ((is_io && all_err_mask) ||
(!is_io && (all_err_mask & ~AC_ERR_DEV)))
ehc->i.action |= ATA_EH_REVALIDATE; ehc->i.action |= ATA_EH_REVALIDATE;
/* if we have offending qcs and the associated failed device */ /* if we have offending qcs and the associated failed device */
...@@ -2697,8 +2696,15 @@ void ata_eh_finish(struct ata_port *ap) ...@@ -2697,8 +2696,15 @@ void ata_eh_finish(struct ata_port *ap)
/* FIXME: Once EH migration is complete, /* FIXME: Once EH migration is complete,
* generate sense data in this function, * generate sense data in this function,
* considering both err_mask and tf. * considering both err_mask and tf.
*
* There's no point in retrying invalid
* (detected by libata) and non-IO device
* errors (rejected by device). Finish them
* immediately.
*/ */
if (qc->err_mask & AC_ERR_INVALID) if ((qc->err_mask & AC_ERR_INVALID) ||
(!(qc->flags & ATA_QCFLAG_IO) &&
qc->err_mask == AC_ERR_DEV))
ata_eh_qc_complete(qc); ata_eh_qc_complete(qc);
else else
ata_eh_qc_retry(qc); ata_eh_qc_retry(qc);
......
...@@ -265,11 +265,11 @@ static struct sil24_cerr_info { ...@@ -265,11 +265,11 @@ static struct sil24_cerr_info {
unsigned int err_mask, action; unsigned int err_mask, action;
const char *desc; const char *desc;
} sil24_cerr_db[] = { } sil24_cerr_db[] = {
[0] = { AC_ERR_DEV, ATA_EH_REVALIDATE, [0] = { AC_ERR_DEV, 0,
"device error" }, "device error" },
[PORT_CERR_DEV] = { AC_ERR_DEV, ATA_EH_REVALIDATE, [PORT_CERR_DEV] = { AC_ERR_DEV, 0,
"device error via D2H FIS" }, "device error via D2H FIS" },
[PORT_CERR_SDB] = { AC_ERR_DEV, ATA_EH_REVALIDATE, [PORT_CERR_SDB] = { AC_ERR_DEV, 0,
"device error via SDB FIS" }, "device error via SDB FIS" },
[PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET,
"error in data FIS" }, "error in data FIS" },
......
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