From eb5c20de351867120c8dfb6d523d5795a3125b02 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 12 Apr 2016 14:25:08 +0300 Subject: [PATCH] mmc: sdhci: Fix error paths in sdhci_add_host() Some error paths in sdhci_add_host() simply returned without cleaning up. Also the return value from mmc_add_host() was not being checked. Signed-off-by: Adrian Hunter Signed-off-by: Ulf Hansson --- drivers/mmc/host/sdhci.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 73edf44ad1ac..734f3773478e 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2965,7 +2965,8 @@ int sdhci_add_host(struct sdhci_host *host) if (!host->ops->get_max_clock) { pr_err("%s: Hardware doesn't specify base clock frequency.\n", mmc_hostname(mmc)); - return -ENODEV; + ret = -ENODEV; + goto undma; } host->max_clk = host->ops->get_max_clock(host); } @@ -3015,7 +3016,8 @@ int sdhci_add_host(struct sdhci_host *host) } else { pr_err("%s: Hardware doesn't specify timeout clock frequency.\n", mmc_hostname(mmc)); - return -ENODEV; + ret = -ENODEV; + goto undma; } } @@ -3069,8 +3071,9 @@ int sdhci_add_host(struct sdhci_host *host) mmc->caps |= MMC_CAP_NEEDS_POLL; /* If there are external regulators, get them */ - if (mmc_regulator_get_supply(mmc) == -EPROBE_DEFER) - return -EPROBE_DEFER; + ret = mmc_regulator_get_supply(mmc); + if (ret == -EPROBE_DEFER) + goto undma; /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ if (!IS_ERR(mmc->supply.vqmmc)) { @@ -3227,7 +3230,8 @@ int sdhci_add_host(struct sdhci_host *host) if (mmc->ocr_avail == 0) { pr_err("%s: Hardware doesn't report any support voltages.\n", mmc_hostname(mmc)); - return -ENODEV; + ret = -ENODEV; + goto unreg; } spin_lock_init(&host->lock); @@ -3323,13 +3327,15 @@ int sdhci_add_host(struct sdhci_host *host) if (ret) { pr_err("%s: Failed to register LED device: %d\n", mmc_hostname(mmc), ret); - goto reset; + goto unirq; } #endif mmiowb(); - mmc_add_host(mmc); + ret = mmc_add_host(mmc); + if (ret) + goto unled; pr_info("%s: SDHCI controller on %s [%s] using %s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), @@ -3341,15 +3347,27 @@ int sdhci_add_host(struct sdhci_host *host) return 0; +unled: #ifdef SDHCI_USE_LEDS_CLASS -reset: + led_classdev_unregister(&host->led); +unirq: +#endif sdhci_do_reset(host, SDHCI_RESET_ALL); sdhci_writel(host, 0, SDHCI_INT_ENABLE); sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); free_irq(host->irq, host); -#endif untasklet: tasklet_kill(&host->finish_tasklet); +unreg: + if (!IS_ERR(mmc->supply.vqmmc)) + regulator_disable(mmc->supply.vqmmc); +undma: + if (host->align_buffer) + dma_free_coherent(mmc_dev(mmc), host->align_buffer_sz + + host->adma_table_sz, host->align_buffer, + host->align_addr); + host->adma_table = NULL; + host->align_buffer = NULL; return ret; } -- 2.20.1