diff options
| author | Andrew Lunn <andrew@lunn.ch> | 2013-01-16 08:13:56 -0500 |
|---|---|---|
| committer | Jason Cooper <jason@lakedaemon.net> | 2013-01-22 20:08:01 -0500 |
| commit | f42abc72da2e77efefd547562a92ddd18926b48b (patch) | |
| tree | 6051f78be5db68b749bccd7fbb09ce2604e0f712 /drivers | |
| parent | d6f620a457aa4c5c2e8d1a079a1236216c445aba (diff) | |
mmc: mvsdio: use devm_ API to simplify/correct error paths.
There are a number of bugs in the error paths of this driver. Make
use of devm_ functions to simplify the cleanup on error.
Based on a patch by Russell King.
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Jason Cooper <jason@lakedaemon.net>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/mmc/host/mvsdio.c | 92 |
1 files changed, 30 insertions, 62 deletions
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index de4c20b3936c..f8dd36102949 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
| @@ -50,8 +50,6 @@ struct mvsd_host { | |||
| 50 | struct timer_list timer; | 50 | struct timer_list timer; |
| 51 | struct mmc_host *mmc; | 51 | struct mmc_host *mmc; |
| 52 | struct device *dev; | 52 | struct device *dev; |
| 53 | struct resource *res; | ||
| 54 | int irq; | ||
| 55 | struct clk *clk; | 53 | struct clk *clk; |
| 56 | int gpio_card_detect; | 54 | int gpio_card_detect; |
| 57 | int gpio_write_protect; | 55 | int gpio_write_protect; |
| @@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 718 | if (!r || irq < 0 || !mvsd_data) | 716 | if (!r || irq < 0 || !mvsd_data) |
| 719 | return -ENXIO; | 717 | return -ENXIO; |
| 720 | 718 | ||
| 721 | r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); | ||
| 722 | if (!r) | ||
| 723 | return -EBUSY; | ||
| 724 | |||
| 725 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); | 719 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); |
| 726 | if (!mmc) { | 720 | if (!mmc) { |
| 727 | ret = -ENOMEM; | 721 | ret = -ENOMEM; |
| @@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 731 | host = mmc_priv(mmc); | 725 | host = mmc_priv(mmc); |
| 732 | host->mmc = mmc; | 726 | host->mmc = mmc; |
| 733 | host->dev = &pdev->dev; | 727 | host->dev = &pdev->dev; |
| 734 | host->res = r; | ||
| 735 | host->base_clock = mvsd_data->clock / 2; | 728 | host->base_clock = mvsd_data->clock / 2; |
| 729 | host->clk = ERR_PTR(-EINVAL); | ||
| 736 | 730 | ||
| 737 | mmc->ops = &mvsd_ops; | 731 | mmc->ops = &mvsd_ops; |
| 738 | 732 | ||
| @@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 752 | 746 | ||
| 753 | spin_lock_init(&host->lock); | 747 | spin_lock_init(&host->lock); |
| 754 | 748 | ||
| 755 | host->base = ioremap(r->start, SZ_4K); | 749 | host->base = devm_request_and_ioremap(&pdev->dev, r); |
| 756 | if (!host->base) { | 750 | if (!host->base) { |
| 757 | ret = -ENOMEM; | 751 | ret = -ENOMEM; |
| 758 | goto out; | 752 | goto out; |
| @@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 765 | 759 | ||
| 766 | mvsd_power_down(host); | 760 | mvsd_power_down(host); |
| 767 | 761 | ||
| 768 | ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); | 762 | ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); |
| 769 | if (ret) { | 763 | if (ret) { |
| 770 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); | 764 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); |
| 771 | goto out; | 765 | goto out; |
| 772 | } else | 766 | } |
| 773 | host->irq = irq; | ||
| 774 | 767 | ||
| 775 | /* Not all platforms can gate the clock, so it is not | 768 | /* Not all platforms can gate the clock, so it is not |
| 776 | an error if the clock does not exists. */ | 769 | an error if the clock does not exists. */ |
| 777 | host->clk = clk_get(&pdev->dev, NULL); | 770 | host->clk = devm_clk_get(&pdev->dev, NULL); |
| 778 | if (!IS_ERR(host->clk)) { | 771 | if (!IS_ERR(host->clk)) |
| 779 | clk_prepare_enable(host->clk); | 772 | clk_prepare_enable(host->clk); |
| 780 | } | ||
| 781 | 773 | ||
| 782 | if (mvsd_data->gpio_card_detect) { | 774 | if (mvsd_data->gpio_card_detect) { |
| 783 | ret = gpio_request(mvsd_data->gpio_card_detect, | 775 | ret = devm_gpio_request_one(&pdev->dev, |
| 784 | DRIVER_NAME " cd"); | 776 | mvsd_data->gpio_card_detect, |
| 777 | GPIOF_IN, DRIVER_NAME " cd"); | ||
| 785 | if (ret == 0) { | 778 | if (ret == 0) { |
| 786 | gpio_direction_input(mvsd_data->gpio_card_detect); | ||
| 787 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); | 779 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); |
| 788 | ret = request_irq(irq, mvsd_card_detect_irq, | 780 | ret = devm_request_irq(&pdev->dev, irq, |
| 789 | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, | 781 | mvsd_card_detect_irq, |
| 790 | DRIVER_NAME " cd", host); | 782 | IRQ_TYPE_EDGE_RISING | |
| 783 | IRQ_TYPE_EDGE_FALLING, | ||
| 784 | DRIVER_NAME " cd", host); | ||
| 791 | if (ret == 0) | 785 | if (ret == 0) |
| 792 | host->gpio_card_detect = | 786 | host->gpio_card_detect = |
| 793 | mvsd_data->gpio_card_detect; | 787 | mvsd_data->gpio_card_detect; |
| 794 | else | 788 | else |
| 795 | gpio_free(mvsd_data->gpio_card_detect); | 789 | devm_gpio_free(&pdev->dev, |
| 790 | mvsd_data->gpio_card_detect); | ||
| 796 | } | 791 | } |
| 797 | } | 792 | } |
| 798 | if (!host->gpio_card_detect) | 793 | if (!host->gpio_card_detect) |
| 799 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 794 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
| 800 | 795 | ||
| 801 | if (mvsd_data->gpio_write_protect) { | 796 | if (mvsd_data->gpio_write_protect) { |
| 802 | ret = gpio_request(mvsd_data->gpio_write_protect, | 797 | ret = devm_gpio_request_one(&pdev->dev, |
| 803 | DRIVER_NAME " wp"); | 798 | mvsd_data->gpio_write_protect, |
| 799 | GPIOF_IN, DRIVER_NAME " wp"); | ||
| 804 | if (ret == 0) { | 800 | if (ret == 0) { |
| 805 | gpio_direction_input(mvsd_data->gpio_write_protect); | ||
| 806 | host->gpio_write_protect = | 801 | host->gpio_write_protect = |
| 807 | mvsd_data->gpio_write_protect; | 802 | mvsd_data->gpio_write_protect; |
| 808 | } | 803 | } |
| @@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
| 824 | return 0; | 819 | return 0; |
| 825 | 820 | ||
| 826 | out: | 821 | out: |
| 827 | if (host) { | 822 | if (mmc) { |
| 828 | if (host->irq) | 823 | if (!IS_ERR(host->clk)) |
| 829 | free_irq(host->irq, host); | ||
| 830 | if (host->gpio_card_detect) { | ||
| 831 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | ||
| 832 | gpio_free(host->gpio_card_detect); | ||
| 833 | } | ||
| 834 | if (host->gpio_write_protect) | ||
| 835 | gpio_free(host->gpio_write_protect); | ||
| 836 | if (host->base) | ||
| 837 | iounmap(host->base); | ||
| 838 | } | ||
| 839 | if (r) | ||
| 840 | release_resource(r); | ||
| 841 | if (mmc) | ||
| 842 | if (!IS_ERR_OR_NULL(host->clk)) { | ||
| 843 | clk_disable_unprepare(host->clk); | 824 | clk_disable_unprepare(host->clk); |
| 844 | clk_put(host->clk); | ||
| 845 | } | ||
| 846 | mmc_free_host(mmc); | 825 | mmc_free_host(mmc); |
| 826 | } | ||
| 847 | 827 | ||
| 848 | return ret; | 828 | return ret; |
| 849 | } | 829 | } |
| @@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev) | |||
| 852 | { | 832 | { |
| 853 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 833 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
| 854 | 834 | ||
| 855 | if (mmc) { | 835 | struct mvsd_host *host = mmc_priv(mmc); |
| 856 | struct mvsd_host *host = mmc_priv(mmc); | ||
| 857 | 836 | ||
| 858 | if (host->gpio_card_detect) { | 837 | mmc_remove_host(mmc); |
| 859 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | 838 | del_timer_sync(&host->timer); |
| 860 | gpio_free(host->gpio_card_detect); | 839 | mvsd_power_down(host); |
| 861 | } | 840 | |
| 862 | mmc_remove_host(mmc); | 841 | if (!IS_ERR(host->clk)) |
| 863 | free_irq(host->irq, host); | 842 | clk_disable_unprepare(host->clk); |
| 864 | if (host->gpio_write_protect) | 843 | mmc_free_host(mmc); |
| 865 | gpio_free(host->gpio_write_protect); | ||
| 866 | del_timer_sync(&host->timer); | ||
| 867 | mvsd_power_down(host); | ||
| 868 | iounmap(host->base); | ||
| 869 | release_resource(host->res); | ||
| 870 | 844 | ||
| 871 | if (!IS_ERR(host->clk)) { | ||
| 872 | clk_disable_unprepare(host->clk); | ||
| 873 | clk_put(host->clk); | ||
| 874 | } | ||
| 875 | mmc_free_host(mmc); | ||
| 876 | } | ||
| 877 | platform_set_drvdata(pdev, NULL); | 845 | platform_set_drvdata(pdev, NULL); |
| 878 | return 0; | 846 | return 0; |
| 879 | } | 847 | } |
