aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorVasiliy Kulikov <segoon@openwall.com>2011-07-03 07:26:47 -0400
committerJeff Garzik <jgarzik@pobox.com>2011-07-23 18:03:54 -0400
commit04e506b5e7bd61c3a99af9964f7f1177c17f3424 (patch)
tree7448465bc6c2662ec3b7a7a3e5c3de2edc31663b /drivers/ata
parent3c4aa91f21f65b7b40bdfb015eacbcb8453ccae2 (diff)
sata_dwc_460ex: fix error path
Fixed hsdev memleak on sata_dwc_probe() error. As dma_dwc_exit() can be called multiple times without sata_dma_regs and irq_dma changes, it might lead to double free on sequential dma_dwc_exit() calls. So, zero these fields after free calls. Signed-off-by: Vasiliy Kulikov <segoon@openwall.com> Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/sata_dwc_460ex.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index dc88a39e7db8..b02c4ffa4db0 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -766,11 +766,15 @@ static int dma_dwc_xfer_setup(struct scatterlist *sg, int num_elems,
766static void dma_dwc_exit(struct sata_dwc_device *hsdev) 766static void dma_dwc_exit(struct sata_dwc_device *hsdev)
767{ 767{
768 dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__); 768 dev_dbg(host_pvt.dwc_dev, "%s:\n", __func__);
769 if (host_pvt.sata_dma_regs) 769 if (host_pvt.sata_dma_regs) {
770 iounmap(host_pvt.sata_dma_regs); 770 iounmap(host_pvt.sata_dma_regs);
771 host_pvt.sata_dma_regs = NULL;
772 }
771 773
772 if (hsdev->irq_dma) 774 if (hsdev->irq_dma) {
773 free_irq(hsdev->irq_dma, hsdev); 775 free_irq(hsdev->irq_dma, hsdev);
776 hsdev->irq_dma = 0;
777 }
774} 778}
775 779
776/* 780/*
@@ -1642,7 +1646,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
1642 if (hsdev == NULL) { 1646 if (hsdev == NULL) {
1643 dev_err(&ofdev->dev, "kmalloc failed for hsdev\n"); 1647 dev_err(&ofdev->dev, "kmalloc failed for hsdev\n");
1644 err = -ENOMEM; 1648 err = -ENOMEM;
1645 goto error_out; 1649 goto error;
1646 } 1650 }
1647 memset(hsdev, 0, sizeof(*hsdev)); 1651 memset(hsdev, 0, sizeof(*hsdev));
1648 1652
@@ -1652,7 +1656,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
1652 dev_err(&ofdev->dev, "ioremap failed for SATA register" 1656 dev_err(&ofdev->dev, "ioremap failed for SATA register"
1653 " address\n"); 1657 " address\n");
1654 err = -ENODEV; 1658 err = -ENODEV;
1655 goto error_out; 1659 goto error_kmalloc;
1656 } 1660 }
1657 hsdev->reg_base = base; 1661 hsdev->reg_base = base;
1658 dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); 1662 dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n");
@@ -1665,7 +1669,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
1665 if (!host) { 1669 if (!host) {
1666 dev_err(&ofdev->dev, "ata_host_alloc_pinfo failed\n"); 1670 dev_err(&ofdev->dev, "ata_host_alloc_pinfo failed\n");
1667 err = -ENOMEM; 1671 err = -ENOMEM;
1668 goto error_out; 1672 goto error_iomap;
1669 } 1673 }
1670 1674
1671 host->private_data = hsdev; 1675 host->private_data = hsdev;
@@ -1733,8 +1737,11 @@ error_out:
1733 /* Free SATA DMA resources */ 1737 /* Free SATA DMA resources */
1734 dma_dwc_exit(hsdev); 1738 dma_dwc_exit(hsdev);
1735 1739
1736 if (base) 1740error_iomap:
1737 iounmap(base); 1741 iounmap(base);
1742error_kmalloc:
1743 kfree(hsdev);
1744error:
1738 return err; 1745 return err;
1739} 1746}
1740 1747