From 6c68a94c5317133280ff5df443c75eea95c23202 Mon Sep 17 00:00:00 2001 From: Lynus Vaz Date: Wed, 4 Jan 2017 15:28:07 +0530 Subject: msm: kgsl: Clean up power-related members if probe fails If power-related initialization fails during device probe, clean up the kgsl structure members. This is useful if the device probe is retried later. Change-Id: I75aeb199da685bb5055ba5a8a0bb552656951674 Signed-off-by: Lynus Vaz --- drivers/gpu/msm/kgsl_pwrctrl.c | 107 +++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index cd9a82a9bf4a..fe6aa45901d0 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1994,6 +1994,42 @@ static int _isense_clk_set_rate(struct kgsl_pwrctrl *pwr, int level) return clk_set_rate(pwr->grp_clks[pwr->isense_clk_indx], rate); } +static inline void _close_pcl(struct kgsl_pwrctrl *pwr) +{ + if (pwr->pcl) + msm_bus_scale_unregister_client(pwr->pcl); + + pwr->pcl = 0; +} + +static inline void _close_ocmem_pcl(struct kgsl_pwrctrl *pwr) +{ + if (pwr->ocmem_pcl) + msm_bus_scale_unregister_client(pwr->ocmem_pcl); + + pwr->ocmem_pcl = 0; +} + +static inline void _close_regulators(struct kgsl_pwrctrl *pwr) +{ + int i; + + for (i = 0; i < KGSL_MAX_REGULATORS; i++) + pwr->regulators[i].reg = NULL; +} + +static inline void _close_clks(struct kgsl_device *device) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + int i; + + for (i = 0; i < KGSL_MAX_CLKS; i++) + pwr->grp_clks[i] = NULL; + + if (pwr->gpu_bimc_int_clk) + devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk); +} + int kgsl_pwrctrl_init(struct kgsl_device *device) { int i, k, m, n = 0, result; @@ -2011,7 +2047,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) result = _get_clocks(device); if (result) - return result; + goto error_cleanup_clks; /* Make sure we have a source clk for freq setting */ if (pwr->grp_clks[0] == NULL) @@ -2029,7 +2065,8 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) if (pwr->num_pwrlevels == 0) { KGSL_PWR_ERR(device, "No power levels are defined\n"); - return -EINVAL; + result = -EINVAL; + goto error_cleanup_clks; } /* Initialize the user and thermal clock constraints */ @@ -2059,7 +2096,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) result = get_regulators(device); if (result) - return result; + goto error_cleanup_regulators; pwr->power_flags = 0; @@ -2079,8 +2116,10 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->ocmem_pcl = msm_bus_scale_register_client (ocmem_scale_table); - if (!pwr->ocmem_pcl) - return -EINVAL; + if (!pwr->ocmem_pcl) { + result = -EINVAL; + goto error_disable_pm; + } } /* Bus width in bytes, set it to zero if not found */ @@ -2110,14 +2149,18 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) * from the driver. */ pwr->pcl = msm_bus_scale_register_client(bus_scale_table); - if (pwr->pcl == 0) - return -EINVAL; + if (pwr->pcl == 0) { + result = -EINVAL; + goto error_cleanup_ocmem_pcl; + } } pwr->bus_ib = kzalloc(bus_scale_table->num_usecases * sizeof(*pwr->bus_ib), GFP_KERNEL); - if (pwr->bus_ib == NULL) - return -ENOMEM; + if (pwr->bus_ib == NULL) { + result = -ENOMEM; + goto error_cleanup_pcl; + } /* * Pull the BW vote out of the bus table. They will be used to @@ -2175,36 +2218,26 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) &pwr->tsens_name); return result; + +error_cleanup_pcl: + _close_pcl(pwr); +error_cleanup_ocmem_pcl: + _close_ocmem_pcl(pwr); +error_disable_pm: + pm_runtime_disable(&pdev->dev); +error_cleanup_regulators: + _close_regulators(pwr); +error_cleanup_clks: + _close_clks(device); + return result; } void kgsl_pwrctrl_close(struct kgsl_device *device) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; - int i; KGSL_PWR_INFO(device, "close device %d\n", device->id); - pm_runtime_disable(&device->pdev->dev); - - if (pwr->pcl) - msm_bus_scale_unregister_client(pwr->pcl); - - pwr->pcl = 0; - - if (pwr->ocmem_pcl) - msm_bus_scale_unregister_client(pwr->ocmem_pcl); - - pwr->ocmem_pcl = 0; - - for (i = 0; i < KGSL_MAX_REGULATORS; i++) - pwr->regulators[i].reg = NULL; - - for (i = 0; i < KGSL_MAX_REGULATORS; i++) - pwr->grp_clks[i] = NULL; - - if (pwr->gpu_bimc_int_clk) - devm_clk_put(&device->pdev->dev, pwr->gpu_bimc_int_clk); - pwr->power_flags = 0; if (!IS_ERR_OR_NULL(pwr->sysfs_pwr_limit)) { @@ -2213,6 +2246,16 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) pwr->sysfs_pwr_limit = NULL; } kfree(pwr->bus_ib); + + _close_pcl(pwr); + + _close_ocmem_pcl(pwr); + + pm_runtime_disable(&device->pdev->dev); + + _close_regulators(pwr); + + _close_clks(device); } /** -- cgit v1.2.3