Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ae4c4037 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Clean up power-related members if probe fails"

parents b24a83ae 6c68a94c
Loading
Loading
Loading
Loading
+75 −32
Original line number Diff line number Diff line
/* 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);
}

/**