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 <lvaz@codeaurora.org>
This commit is contained in:
Lynus Vaz 2017-01-04 15:28:07 +05:30
parent e51c3cc83f
commit 6c68a94c53

View file

@ -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);
}
/**