summaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo2007-10-25 11:22:44 +0200
committerJeff Garzik2007-10-29 11:15:25 +0100
commit4dbfa39b6c95eb9d0aedb5bd00bb552b91c31e3d (patch)
treeb3b92aa44fe651af464373d8a21a3da8897fa479 /drivers/ata/libata-core.c
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6 (diff)
downloadkernel-qcow2-linux-4dbfa39b6c95eb9d0aedb5bd00bb552b91c31e3d.tar.gz
kernel-qcow2-linux-4dbfa39b6c95eb9d0aedb5bd00bb552b91c31e3d.tar.xz
kernel-qcow2-linux-4dbfa39b6c95eb9d0aedb5bd00bb552b91c31e3d.zip
libata: relocate and fix post-command processing
Some commands need post-processing after successful completion. This was done in ata_scsi_qc_complete() till now but this has the following problems. * Post-command processing gets executed when qc is completed from EH. Some qc's are retried from EH with zero err_mask and thus triggers unnecessary/incorrect post-command processing. * Command post processing doesn't belong to SAT layer. * Link-wide revalidation was scheduled where device revalidation suffices. This patch moves post-command processing to success completion path of ata_qc_complete() which is travelled iff the command is going to be completed without passing through EH and updates post-command processing such that device-specific action is used. While at it, restructure code a bit for readability. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 081e3dfb64d4..5aedd1af06e6 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5594,6 +5594,9 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* taken care of.
*/
if (ap->ops->error_handler) {
+ struct ata_device *dev = qc->dev;
+ struct ata_eh_info *ehi = &dev->link->eh_info;
+
WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
if (unlikely(qc->err_mask))
@@ -5612,6 +5615,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
if (qc->flags & ATA_QCFLAG_RESULT_TF)
fill_result_tf(qc);
+ /* Some commands need post-processing after successful
+ * completion.
+ */
+ switch (qc->tf.command) {
+ case ATA_CMD_SET_FEATURES:
+ if (qc->tf.feature != SETFEATURES_WC_ON &&
+ qc->tf.feature != SETFEATURES_WC_OFF)
+ break;
+ /* fall through */
+ case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
+ case ATA_CMD_SET_MULTI: /* multi_count changed */
+ /* revalidate device */
+ ehi->dev_action[dev->devno] |= ATA_EH_REVALIDATE;
+ ata_port_schedule_eh(ap);
+ break;
+ }
+
__ata_qc_complete(qc);
} else {
if (qc->flags & ATA_QCFLAG_EH_SCHEDULED)