diff options
| author | Suman Anna <s-anna@ti.com> | 2015-03-16 21:14:02 -0400 |
|---|---|---|
| committer | Tony Lindgren <tony@atomide.com> | 2015-03-17 13:44:58 -0400 |
| commit | a76fc9dda87b51010e4bc60b5e0065a70180b465 (patch) | |
| tree | aa4fb16367ba9ebf251145f72a1558f871e46b56 | |
| parent | e5ed5b60272871786b1c5434079925bc60d771b7 (diff) | |
ARM: OMAP: dmtimer: check for pm_runtime_get_sync() failure
The current OMAP dmtimer probe does not check for the return
status of pm_runtime_get_sync() before initializing the timer
registers. Any timer with missing hwmod data would return a
failure here, and the access of registers without enabling the
clocks for the timer would trigger a l3_noc interrupt and a
kernel boot hang. Add proper checking so that the probe would
return a failure graciously without hanging the kernel boot.
Signed-off-by: Suman Anna <s-anna@ti.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
| -rw-r--r-- | arch/arm/plat-omap/dmtimer.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index db10169a08de..f32c74c0e1de 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c | |||
| @@ -799,6 +799,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
| 799 | struct device *dev = &pdev->dev; | 799 | struct device *dev = &pdev->dev; |
| 800 | const struct of_device_id *match; | 800 | const struct of_device_id *match; |
| 801 | const struct dmtimer_platform_data *pdata; | 801 | const struct dmtimer_platform_data *pdata; |
| 802 | int ret; | ||
| 802 | 803 | ||
| 803 | match = of_match_device(of_match_ptr(omap_timer_match), dev); | 804 | match = of_match_device(of_match_ptr(omap_timer_match), dev); |
| 804 | pdata = match ? match->data : dev->platform_data; | 805 | pdata = match ? match->data : dev->platform_data; |
| @@ -860,7 +861,12 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
| 860 | } | 861 | } |
| 861 | 862 | ||
| 862 | if (!timer->reserved) { | 863 | if (!timer->reserved) { |
| 863 | pm_runtime_get_sync(dev); | 864 | ret = pm_runtime_get_sync(dev); |
| 865 | if (ret < 0) { | ||
| 866 | dev_err(dev, "%s: pm_runtime_get_sync failed!\n", | ||
| 867 | __func__); | ||
| 868 | goto err_get_sync; | ||
| 869 | } | ||
| 864 | __omap_dm_timer_init_regs(timer); | 870 | __omap_dm_timer_init_regs(timer); |
| 865 | pm_runtime_put(dev); | 871 | pm_runtime_put(dev); |
| 866 | } | 872 | } |
| @@ -873,6 +879,11 @@ static int omap_dm_timer_probe(struct platform_device *pdev) | |||
| 873 | dev_dbg(dev, "Device Probed.\n"); | 879 | dev_dbg(dev, "Device Probed.\n"); |
| 874 | 880 | ||
| 875 | return 0; | 881 | return 0; |
| 882 | |||
| 883 | err_get_sync: | ||
| 884 | pm_runtime_put_noidle(dev); | ||
| 885 | pm_runtime_disable(dev); | ||
| 886 | return ret; | ||
| 876 | } | 887 | } |
| 877 | 888 | ||
| 878 | /** | 889 | /** |
