| From 4e492ba2614b449b022f31ed57295fb9477d6e2a Mon Sep 17 00:00:00 2001 |
| From: Tejun Heo <tj@kernel.org> |
| Date: Thu, 9 Dec 2010 15:59:32 +0100 |
| Subject: [PATCH] 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> |
| |
| diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c |
| index 5405b36..6e4b795 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; |
| } |
| |
| -- |
| 1.7.4.4 |
| |