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:
parent
e51c3cc83f
commit
6c68a94c53
1 changed files with 75 additions and 32 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue