summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2010-12-09 15:59:32 +0100
committerPaul Gortmaker <paul.gortmaker@windriver.com>2011-06-26 12:47:00 -0400
commit1934efbaa9c48febf9770b7c8ea3522403c55d15 (patch)
treef1a66415308642f22ce8dfca79c592540a691fe3 /drivers
parentab16f3c757a8aeac8b0ee935e6de99ea68388fc1 (diff)
libata: no special completion processing for EH commands
commit f08dc1ac6b15c681f4643d8da1700e06c3855608 upstream. ata_qc_complete() contains special handling for certain commands. For example, it schedules EH for device revalidation after certain configurations are changed. These shouldn't be applied to EH commands but they were. In most cases, it doesn't cause an actual problem because EH doesn't issue any command which would trigger special handling; however, ACPI can issue such commands via _GTF which can cause weird interactions. Restructure ata_qc_complete() such that EH commands are always passed on to __ata_qc_complete(). stable: Please apply to -stable only after 2.6.38 is released. Signed-off-by: Tejun Heo <tj@kernel.org> Reported-by: Kyle McMartin <kyle@mcmartin.ca> Signed-off-by: Jeff Garzik <jgarzik@redhat.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-core.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 5405b3636afd..6e4b795d79e0 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5038,9 +5038,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
{
struct ata_device *dev = qc->dev;
- if (ata_tag_internal(qc->tag))
- return;
-
if (ata_is_nodata(qc->tf.protocol))
return;
@@ -5084,14 +5081,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
if (unlikely(qc->err_mask))
qc->flags |= ATA_QCFLAG_FAILED;
- if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
- /* always fill result TF for failed qc */
+ /*
+ * Finish internal commands without any further processing
+ * and always with the result TF filled.
+ */
+ if (unlikely(ata_tag_internal(qc->tag))) {
fill_result_tf(qc);
+ __ata_qc_complete(qc);
+ return;
+ }
- if (!ata_tag_internal(qc->tag))
- ata_qc_schedule_eh(qc);
- else
- __ata_qc_complete(qc);
+ /*
+ * Non-internal qc has failed. Fill the result TF and
+ * summon EH.
+ */
+ if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
+ fill_result_tf(qc);
+ ata_qc_schedule_eh(qc);
return;
}