]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
libata: fix internal command failure handling
authorTejun Heo <tj@kernel.org>
Fri, 16 Oct 2009 04:00:51 +0000 (13:00 +0900)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 10 Nov 2009 00:21:47 +0000 (16:21 -0800)
commit f4b31db92d163df8a639f5a8c8633bdeb6e8432d upstream.

When an internal command fails, it should be failed directly without
invoking EH.  In the original implemetation, this was accomplished by
letting internal command bypass failure handling in ata_qc_complete().
However, later changes added post-successful-completion handling to
that code path and the success path is no longer adequate as internal
command failure path.  One of the visible problems is that internal
command failure due to timeout or other freeze conditions would
spuriously trigger WARN_ON_ONCE() in the success path.

This patch updates failure path such that internal command failure
handling is contained there.

Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/ata/libata-core.c

index e71149b19860fb9f0273fb4e49c0d1c929f74a3b..41439435ff2e1348dfd0f2513f50060a875ac02f 100644 (file)
@@ -5008,12 +5008,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                        qc->flags |= ATA_QCFLAG_FAILED;
 
                if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
-                       if (!ata_tag_internal(qc->tag)) {
-                               /* always fill result TF for failed qc */
-                               fill_result_tf(qc);
+                       /* always fill result TF for failed qc */
+                       fill_result_tf(qc);
+
+                       if (!ata_tag_internal(qc->tag))
                                ata_qc_schedule_eh(qc);
-                               return;
-                       }
+                       else
+                               __ata_qc_complete(qc);
+                       return;
                }
 
                /* read result TF if requested */