On Thu, Jan 10, 2013 at 09:29:15PM +0100, Andrew Lunn wrote:
> A NULL is a valid clk cookie, so we should not be tested with
> IS_ERR_NULL(). Replace it with IS_ERR().
> 
> Signed-off-by: Andrew Lunn <and...@lunn.ch>
> ---
>  drivers/mmc/host/mvsdio.c |    2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
> index de4c20b..d0050fa 100644
> --- a/drivers/mmc/host/mvsdio.c
> +++ b/drivers/mmc/host/mvsdio.c
> @@ -839,7 +839,7 @@ out:
>       if (r)
>               release_resource(r);
>       if (mmc)
> -             if (!IS_ERR_OR_NULL(host->clk)) {
> +             if (!IS_ERR(host->clk)) {
>                       clk_disable_unprepare(host->clk);
>                       clk_put(host->clk);
>               }

Actually, no.

1. I've already recently pointed out that C is not python, and this code
   is broken.  (Look at the lack of missing braces around the code you've
   modified.)
2. host->clk _can_ be NULL here.

Here's the (untested) bare minimum needed to fix this driver:

 drivers/mmc/host/mvsdio.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index de4c20b..4190fb4 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -733,6 +733,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
        host->dev = &pdev->dev;
        host->res = r;
        host->base_clock = mvsd_data->clock / 2;
+       host->clk = ERR_PTR(-EINVAL);
 
        mmc->ops = &mvsd_ops;
 
@@ -837,13 +838,14 @@ static int __init mvsd_probe(struct platform_device *pdev)
                        iounmap(host->base);
        }
        if (r)
-               release_resource(r);
-       if (mmc)
-               if (!IS_ERR_OR_NULL(host->clk)) {
+               release_mem_resource(r->start, resource_size(r));
+       if (mmc) {
+               if (!IS_ERR(host->clk)) {
                        clk_disable_unprepare(host->clk);
                        clk_put(host->clk);
                }
                mmc_free_host(mmc);
+       }
 
        return ret;
 }
@@ -866,7 +868,7 @@ static int __exit mvsd_remove(struct platform_device *pdev)
                del_timer_sync(&host->timer);
                mvsd_power_down(host);
                iounmap(host->base);
-               release_resource(host->res);
+               release_mem_resource(host->res->start, resource_size(host->res);
 
                if (!IS_ERR(host->clk)) {
                        clk_disable_unprepare(host->clk);


But... we can do better than that.  We have the devm_* APIs which will
make this code simpler, and less prone to these kinds of silly errors.
I've left the request_irq()s alone because it isn't obvious to me that
there isn't a reason for releasing the IRQ at a particular point in the
cleanup, and there's no sign that IRQs may be asked on the device itself.

Note also that I found another bug in this driver - it requests a region
1K in size, but ioremaps 4K.  That's just wrong.  But anyway, the whole
issue goes away with devm_request_and_ioremap().

What remains?  The assumption that GPIO0 means "no GPIO" rather than
testing with gpio_valid() and the IRQ stuff.

 drivers/mmc/host/mvsdio.c |   61 +++++++++++++++-----------------------------
 1 files changed, 21 insertions(+), 40 deletions(-)

diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index de4c20b..4723310 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -50,7 +50,6 @@ struct mvsd_host {
        struct timer_list timer;
        struct mmc_host *mmc;
        struct device *dev;
-       struct resource *res;
        int irq;
        struct clk *clk;
        int gpio_card_detect;
@@ -718,10 +717,6 @@ static int __init mvsd_probe(struct platform_device *pdev)
        if (!r || irq < 0 || !mvsd_data)
                return -ENXIO;
 
-       r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
-       if (!r)
-               return -EBUSY;
-
        mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
@@ -731,8 +726,8 @@ static int __init mvsd_probe(struct platform_device *pdev)
        host = mmc_priv(mmc);
        host->mmc = mmc;
        host->dev = &pdev->dev;
-       host->res = r;
        host->base_clock = mvsd_data->clock / 2;
+       host->clk = ERR_PTR(-EINVAL);
 
        mmc->ops = &mvsd_ops;
 
@@ -752,7 +747,7 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
        spin_lock_init(&host->lock);
 
-       host->base = ioremap(r->start, SZ_4K);
+       host->base = devm_request_and_ioremap(&pdev->dev, r);
        if (!host->base) {
                ret = -ENOMEM;
                goto out;
@@ -774,16 +769,15 @@ static int __init mvsd_probe(struct platform_device *pdev)
 
        /* Not all platforms can gate the clock, so it is not
           an error if the clock does not exists. */
-       host->clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(host->clk)) {
+       host->clk = devm_clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(host->clk))
                clk_prepare_enable(host->clk);
-       }
 
        if (mvsd_data->gpio_card_detect) {
-               ret = gpio_request(mvsd_data->gpio_card_detect,
-                                  DRIVER_NAME " cd");
+               ret = devm_gpio_request_one(&pdev->dev,
+                                           mvsd_data->gpio_card_detect,
+                                           GPIOF_IN, DRIVER_NAME " cd");
                if (ret == 0) {
-                       gpio_direction_input(mvsd_data->gpio_card_detect);
                        irq = gpio_to_irq(mvsd_data->gpio_card_detect);
                        ret = request_irq(irq, mvsd_card_detect_irq,
                                          IRQ_TYPE_EDGE_RISING | 
IRQ_TYPE_EDGE_FALLING,
@@ -792,17 +786,18 @@ static int __init mvsd_probe(struct platform_device *pdev)
                                host->gpio_card_detect =
                                        mvsd_data->gpio_card_detect;
                        else
-                               gpio_free(mvsd_data->gpio_card_detect);
+                               devm_gpio_free(&pdev->dev,
+                                              mvsd_data->gpio_card_detect);
                }
        }
        if (!host->gpio_card_detect)
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        if (mvsd_data->gpio_write_protect) {
-               ret = gpio_request(mvsd_data->gpio_write_protect,
-                                  DRIVER_NAME " wp");
+               ret = devm_gpio_request_one(&pdev->dev,
+                                           mvsd_data->gpio_write_protect,
+                                           GPIOF_IN, DRIVER_NAME " wp");
                if (ret == 0) {
-                       gpio_direction_input(mvsd_data->gpio_write_protect);
                        host->gpio_write_protect =
                                mvsd_data->gpio_write_protect;
                }
@@ -827,23 +822,15 @@ static int __init mvsd_probe(struct platform_device *pdev)
        if (host) {
                if (host->irq)
                        free_irq(host->irq, host);
-               if (host->gpio_card_detect) {
+               if (host->gpio_card_detect)
                        free_irq(gpio_to_irq(host->gpio_card_detect), host);
-                       gpio_free(host->gpio_card_detect);
-               }
-               if (host->gpio_write_protect)
-                       gpio_free(host->gpio_write_protect);
-               if (host->base)
-                       iounmap(host->base);
        }
-       if (r)
-               release_resource(r);
-       if (mmc)
-               if (!IS_ERR_OR_NULL(host->clk)) {
+       if (mmc) {
+               if (!IS_ERR(host->clk))
                        clk_disable_unprepare(host->clk);
-                       clk_put(host->clk);
-               }
+
                mmc_free_host(mmc);
+       }
 
        return ret;
 }
@@ -855,23 +842,17 @@ static int __exit mvsd_remove(struct platform_device 
*pdev)
        if (mmc) {
                struct mvsd_host *host = mmc_priv(mmc);
 
-               if (host->gpio_card_detect) {
+               if (host->gpio_card_detect)
                        free_irq(gpio_to_irq(host->gpio_card_detect), host);
-                       gpio_free(host->gpio_card_detect);
-               }
+
                mmc_remove_host(mmc);
                free_irq(host->irq, host);
-               if (host->gpio_write_protect)
-                       gpio_free(host->gpio_write_protect);
                del_timer_sync(&host->timer);
                mvsd_power_down(host);
-               iounmap(host->base);
-               release_resource(host->res);
 
-               if (!IS_ERR(host->clk)) {
+               if (!IS_ERR(host->clk))
                        clk_disable_unprepare(host->clk);
-                       clk_put(host->clk);
-               }
+
                mmc_free_host(mmc);
        }
        platform_set_drvdata(pdev, NULL);

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to