]> nv-tegra.nvidia Code Review - linux-2.6.git/commitdiff
[PATCH] libata: fix ata_qc_issue() error handling
authorTejun Heo <htejun@gmail.com>
Mon, 23 Jan 2006 04:09:36 +0000 (13:09 +0900)
committerJeff Garzik <jgarzik@pobox.com>
Fri, 27 Jan 2006 03:33:50 +0000 (22:33 -0500)
When ata_qc_issue() fails, the qc might have been dma mapped or not.
So, performing only ata_qc_free() results in dma map leak.  This patch
makes ata_qc_issue() mark dma map flags correctly on failure and calls
ata_qc_complete() after ata_qc_issue() fails.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c

index 15df633521d006d164192e1c38a729d58ebe73de..43a23286d6fe4e9cb730be834e8b9a02ca3237cf 100644 (file)
@@ -1125,8 +1125,10 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
        qc->private_data = &wait;
        qc->complete_fn = ata_qc_complete_internal;
 
-       if (ata_qc_issue(qc))
-               goto issue_fail;
+       if (ata_qc_issue(qc)) {
+               qc->err_mask = AC_ERR_OTHER;
+               ata_qc_complete(qc);
+       }
 
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
@@ -1155,11 +1157,6 @@ ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
        ata_qc_free(qc);
 
        return err_mask;
-
- issue_fail:
-       ata_qc_free(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-       return AC_ERR_OTHER;
 }
 
 /**
@@ -3687,10 +3684,10 @@ int ata_qc_issue(struct ata_queued_cmd *qc)
        if (ata_should_dma_map(qc)) {
                if (qc->flags & ATA_QCFLAG_SG) {
                        if (ata_sg_setup(qc))
-                               goto err_out;
+                               goto sg_err;
                } else if (qc->flags & ATA_QCFLAG_SINGLE) {
                        if (ata_sg_setup_one(qc))
-                               goto err_out;
+                               goto sg_err;
                }
        } else {
                qc->flags &= ~ATA_QCFLAG_DMAMAP;
@@ -3703,7 +3700,8 @@ int ata_qc_issue(struct ata_queued_cmd *qc)
 
        return ap->ops->qc_issue(qc);
 
-err_out:
+sg_err:
+       qc->flags &= ~ATA_QCFLAG_DMAMAP;
        return -1;
 }
 
index ce3fe928a386767745dc1e1aec923be1be769898..c496309f691a045855cbf65c1898c2755702c604 100644 (file)
@@ -1322,8 +1322,10 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
                goto early_finish;
 
        /* select device, send command to hardware */
-       if (ata_qc_issue(qc))
-               goto err_did;
+       if (ata_qc_issue(qc)) {
+               qc->err_mask |= AC_ERR_OTHER;
+               ata_qc_complete(qc);
+       }
 
        VPRINTK("EXIT\n");
        return;