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

Commit 0f9ebd55 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Finish up probe cleanups



Do the last bits needed to make the probes defer capable. Fix a few more
device_node reference counts and fix up the probe failure unwind paths.

Change-Id: Ic0dedbadd6f4c9b46a02e9b6ea0b145c81b50520
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent fb77ada1
Loading
Loading
Loading
Loading
+51 −39
Original line number Diff line number Diff line
@@ -908,11 +908,9 @@ static int adreno_of_parse_pwrlevels(struct adreno_device *adreno_dev,
	return ret;
}

static void adreno_of_get_initial_pwrlevel(struct adreno_device *adreno_dev,
static void adreno_of_get_initial_pwrlevel(struct kgsl_pwrctrl *pwr,
		struct device_node *node)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	int init_level = 1;

	of_property_read_u32(node, "qcom,initial-pwrlevel", &init_level);
@@ -959,14 +957,14 @@ static int adreno_of_get_legacy_pwrlevels(struct adreno_device *adreno_dev,
	}

	ret = adreno_of_parse_pwrlevels(adreno_dev, node);
	if (ret)
		return ret;

	adreno_of_get_initial_pwrlevel(adreno_dev, parent);

	if (!ret) {
		adreno_of_get_initial_pwrlevel(&device->pwrctrl, parent);
		adreno_of_get_limits(adreno_dev, parent);
	}

	return 0;
	of_node_put(node);
	return ret;
}

static int adreno_of_get_pwrlevels(struct adreno_device *adreno_dev,
@@ -989,10 +987,12 @@ static int adreno_of_get_pwrlevels(struct adreno_device *adreno_dev,
			int ret;

			ret = adreno_of_parse_pwrlevels(adreno_dev, child);
			if (ret)
			if (ret) {
				of_node_put(child);
				return ret;
			}

			adreno_of_get_initial_pwrlevel(adreno_dev, child);
			adreno_of_get_initial_pwrlevel(&device->pwrctrl, child);

			/*
			 * Check for global throttle-pwrlevel first and override
@@ -1001,6 +1001,7 @@ static int adreno_of_get_pwrlevels(struct adreno_device *adreno_dev,
			adreno_of_get_limits(adreno_dev, parent);
			adreno_of_get_limits(adreno_dev, child);

			of_node_put(child);
			return 0;
		}
	}
@@ -1032,26 +1033,23 @@ l3_pwrlevel_probe(struct kgsl_device *device, struct device_node *node)
		if (index >= device->num_l3_pwrlevels)
			device->num_l3_pwrlevels = index + 1;

		if (of_property_read_u32(child, "qcom,l3-freq",
				&device->l3_freq[index]))
			continue;
		of_property_read_u32(child, "qcom,l3-freq",
				&device->l3_freq[index]);
	}

	device->l3_clk = devm_clk_get(&device->pdev->dev, "l3_vote");

	if (IS_ERR_OR_NULL(device->l3_clk)) {
	if (IS_ERR_OR_NULL(device->l3_clk))
		dev_err(&device->pdev->dev,
			"Unable to get the l3_vote clock\n");
		device->l3_clk = NULL;
	}
}

static int adreno_of_get_power(struct adreno_device *adreno_dev,
		struct platform_device *pdev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct device_node *node = pdev->dev.of_node;
	struct resource *res;
	int ret;

	/* Get starting physical address of device registers */
	res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM,
@@ -1071,10 +1069,11 @@ static int adreno_of_get_power(struct adreno_device *adreno_dev,
	device->reg_phys = res->start;
	device->reg_len = resource_size(res);

	if (adreno_of_get_pwrlevels(adreno_dev, node))
		return -EINVAL;
	ret = adreno_of_get_pwrlevels(adreno_dev, pdev->dev.of_node);
	if (ret)
		return ret;

	l3_pwrlevel_probe(device, node);
	l3_pwrlevel_probe(device, pdev->dev.of_node);

	/* Default timeout is 80 ms across all targets */
	device->pwrctrl.interval_timeout = msecs_to_jiffies(80);
@@ -1082,7 +1081,8 @@ static int adreno_of_get_power(struct adreno_device *adreno_dev,
	/* Set default bus control to true on all targets */
	device->pwrctrl.bus_control = true;

	device->pwrctrl.input_disable = of_property_read_bool(node,
	device->pwrctrl.input_disable =
		of_property_read_bool(pdev->dev.of_node,
			"qcom,disable-wake-on-touch");

	return 0;
@@ -1267,7 +1267,7 @@ static int adreno_read_speed_bin(struct platform_device *pdev)
	return val;
}

static void adreno_probe_llcc(struct adreno_device *adreno_dev,
static int adreno_probe_llcc(struct adreno_device *adreno_dev,
		struct platform_device *pdev)
{
	int ret;
@@ -1275,16 +1275,32 @@ static void adreno_probe_llcc(struct adreno_device *adreno_dev,
	/* Get the system cache slice descriptor for GPU */
	adreno_dev->gpu_llc_slice = llcc_slice_getd(LLCC_GPU);
	ret = PTR_ERR_OR_ZERO(adreno_dev->gpu_llc_slice);
	if (ret && ret != -ENOENT)
		dev_warn(&pdev->dev, "Unable to get the GPU LLC slice: %d\n",
			ret);

	if (ret) {
		/* Propagate EPROBE_DEFER back to the probe function */
		if (ret == -EPROBE_DEFER)
			return ret;

		if (ret != -ENOENT)
			dev_warn(&pdev->dev,
				"Unable to get the GPU LLC slice: %d\n", ret);
	}

	/* Get the system cache slice descriptor for GPU pagetables */
	adreno_dev->gpuhtw_llc_slice = llcc_slice_getd(LLCC_GPUHTW);
	ret = PTR_ERR_OR_ZERO(adreno_dev->gpuhtw_llc_slice);
	if (ret && ret != -ENOENT)
		dev_warn(&pdev->dev, "Unable to get GPU HTW LLC slice: %d\n",
			ret);
	if (ret) {
		if (ret == -EPROBE_DEFER) {
			llcc_slice_putd(adreno_dev->gpu_llc_slice);
			return ret;
		}

		if (ret != -ENOENT)
			dev_warn(&pdev->dev,
				"Unable to get GPU HTW LLC slice: %d\n", ret);
	}

	return 0;
}

static const struct kgsl_functable adreno_functable;
@@ -1318,10 +1334,6 @@ static void adreno_setup_device(struct adreno_device *adreno_dev)
	INIT_LIST_HEAD(&adreno_dev->active_list);
	spin_lock_init(&adreno_dev->active_list_lock);

	/* Enable use of the LLC slices where applicable */
	adreno_dev->gpu_llc_slice_enable = true;
	adreno_dev->gpuhtw_llc_slice_enable = true;

	for (i = 0; i < ARRAY_SIZE(adreno_dev->ringbuffers); i++) {
		struct adreno_ringbuffer *rb = &adreno_dev->ringbuffers[i];

@@ -1375,10 +1387,8 @@ static int adreno_bind(struct device *dev)
		return -ENODEV;

	status = adreno_of_get_power(adreno_dev, pdev);
	if (status) {
		device->pdev = NULL;
	if (status)
		return status;
	}

	status = kgsl_bus_init(device, pdev);
	if (status)
@@ -1407,8 +1417,10 @@ static int adreno_bind(struct device *dev)
	device->mmu.secured = (IS_ENABLED(CONFIG_QCOM_SECURE_BUFFER) &&
		ADRENO_FEATURE(adreno_dev, ADRENO_CONTENT_PROTECTION));

	/* Probe the LLCC */
	adreno_probe_llcc(adreno_dev, pdev);
	/* Probe the LLCC - this could return -EPROBE_DEFER */
	status = adreno_probe_llcc(adreno_dev, pdev);
	if (status)
		goto err;

	/*
	 * IF the GPU HTW slice was successsful set the MMU feature so the
+3 −0
Original line number Diff line number Diff line
@@ -2286,6 +2286,9 @@ static void a6xx_platform_setup(struct adreno_device *adreno_dev)
	adreno_dev->preempt.skipsaverestore = true;
	adreno_dev->preempt.usesgmem = true;

	adreno_dev->gpu_llc_slice_enable = true;
	adreno_dev->gpuhtw_llc_slice_enable = true;

	if (adreno_has_gbif(adreno_dev)) {
		a6xx_perfcounter_groups[KGSL_PERFCOUNTER_GROUP_VBIF].regs =
				a6xx_perfcounters_gbif;
+19 −30
Original line number Diff line number Diff line
@@ -324,32 +324,6 @@ static void adreno_preemption_timer(struct timer_list *t)
	queue_work(system_unbound_wq, &adreno_dev->preempt.work);
}

static void adreno_preemption_init(struct adreno_device *adreno_dev)
{
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	struct adreno_preemption *preempt = &adreno_dev->preempt;
	int ret;

	if (!ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
		return;

	timer_setup(&preempt->timer, adreno_preemption_timer, 0);

	ret = gpudev->preemption_init(adreno_dev);

	WARN(ret, "adreno GPU preemption is disabled\n");
}

static void adreno_preemption_close(struct adreno_device *adreno_dev)
{
	struct adreno_preemption *preempt = &adreno_dev->preempt;

	if (!ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
		return;

	del_timer(&preempt->timer);
}

int adreno_ringbuffer_init(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
@@ -386,15 +360,30 @@ int adreno_ringbuffer_init(struct adreno_device *adreno_dev)
		}
	}

	adreno_preemption_init(adreno_dev);

	adreno_dev->cur_rb = &(adreno_dev->ringbuffers[0]);

	if (ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION)) {
		struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
		struct adreno_preemption *preempt = &adreno_dev->preempt;
		int ret;

		timer_setup(&preempt->timer, adreno_preemption_timer, 0);

		ret = gpudev->preemption_init(adreno_dev);
		WARN(ret, "adreno GPU preemption is disabled\n");
	}

	return 0;
}

void adreno_ringbuffer_close(struct adreno_device *adreno_dev)
{
	adreno_preemption_close(adreno_dev);
	struct adreno_preemption *preempt = &adreno_dev->preempt;

	if (!ADRENO_FEATURE(adreno_dev, ADRENO_PREEMPTION))
		return;

	del_timer(&preempt->timer);
}

/*
@@ -791,7 +780,7 @@ static void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
		((context->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
			(flags & KGSL_CONTEXT_PWR_CONSTRAINT))) {

		if (!device->l3_clk) {
		if (IS_ERR_OR_NULL(device->l3_clk)) {
			dev_err_once(device->dev,
				"l3_vote clk not available\n");
			return;
+4 −10
Original line number Diff line number Diff line
@@ -4835,8 +4835,7 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
	/* Disable the sparse ioctl invocation as they are not used */
	device->flags &= ~KGSL_FLAG_SPARSE;

	kgsl_device_debugfs_init(device);

	/* Can return -EPROBE_DEFER */
	status = kgsl_pwrctrl_init(device);
	if (status)
		goto error;
@@ -4873,10 +4872,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
	rwlock_init(&device->context_lock);
	spin_lock_init(&device->submit_lock);

	/* Check to see if our device can perform DMA correctly */
	status = dma_set_coherent_mask(&pdev->dev, KGSL_DMA_BIT_MASK);
	if (status)
		goto error_close_mmu;
	kgsl_device_debugfs_init(device);

	dma_set_coherent_mask(&pdev->dev, KGSL_DMA_BIT_MASK);

	/* Set up the GPU events for the device */
	kgsl_device_events_probe(device);
@@ -4889,13 +4887,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)

	return 0;

error_close_mmu:
	kgsl_mmu_close(device);
	kgsl_free_globals(device);
error_pwrctrl_close:
	kgsl_pwrctrl_close(device);
error:
	kgsl_device_debugfs_close(device);
	_unregister_device(device);
	return status;
}
+3 −11
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/of.h>
@@ -1107,8 +1107,8 @@ void kgsl_device_snapshot_probe(struct kgsl_device *device, u32 size)
{
	device->snapshot_memory.size = size;

	device->snapshot_memory.ptr = kzalloc(device->snapshot_memory.size,
		GFP_KERNEL);
	device->snapshot_memory.ptr = devm_kzalloc(&device->pdev->dev,
		device->snapshot_memory.size, GFP_KERNEL);

	if (!device->snapshot_memory.ptr)
		return;
@@ -1147,14 +1147,6 @@ void kgsl_device_snapshot_close(struct kgsl_device *device)
	sysfs_remove_files(&device->snapshot_kobj, snapshot_attrs);

	kobject_put(&device->snapshot_kobj);

	kfree(device->snapshot_memory.ptr);

	device->snapshot_memory.ptr = NULL;
	device->snapshot_memory.size = 0;
	device->snapshot_faultcount = 0;
	device->force_panic = false;
	device->snapshot_crashdumper = true;
}

/**