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

Commit 153f05de authored by Prakash Kamliya's avatar Prakash Kamliya
Browse files

msm: kgsl: Avoid L2PC on masked CPUs



If any of the Graphics rendering threads are running
on masked CPUs, avoid L2PC for some duration on that
CPU. This reduces latency on CPU (latency mainly
because of L2 cache flush) and helps on performance.
This change uses pm_qos_update_request_timeout() API.

Add l2pc-cpu-mask property in device tree to enable
this.

CRs-Fixed: 962598
Change-Id: If90090cd2c68ea7c07e269723931fef7201ef136
Signed-off-by: default avatarPrakash Kamliya <pkamliya@codeaurora.org>
parent 0132c779
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -110,6 +110,11 @@ Optional Properties:
				Signal the GPU to set Set TWOPASSUSEWFI bit in
				A5XX_PC_DBG_ECO_CNTL (5XX only)

- qcom,l2pc-cpu-mask:
				Disables L2PC on masked CPUs when any of Graphics
				rendering thread is running on masked CPUs.
				Bit 0 is for CPU-0, bit 1 is for CPU-1...

The following properties are optional as collecting data via coresight might
not be supported for every chipset. The documentation for coresight
properties can be found in:
+2 −0
Original line number Diff line number Diff line
@@ -1178,6 +1178,8 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev,

	spin_unlock(&drawctxt->lock);

	kgsl_pwrctrl_update_l2pc(&adreno_dev->dev);

	/* Add the context to the dispatcher pending list */
	dispatcher_queue_context(adreno_dev, drawctxt);

+19 −0
Original line number Diff line number Diff line
@@ -3786,6 +3786,7 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
{
	int status = -EINVAL;
	struct resource *res;
	int cpu;

	status = _register_device(device);
	if (status)
@@ -3924,6 +3925,22 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
				PM_QOS_CPU_DMA_LATENCY,
				PM_QOS_DEFAULT_VALUE);

	if (device->pwrctrl.l2pc_cpus_mask) {

		device->pwrctrl.l2pc_cpus_qos.type =
				PM_QOS_REQ_AFFINE_CORES;
		cpumask_empty(&device->pwrctrl.l2pc_cpus_qos.cpus_affine);
		for_each_possible_cpu(cpu) {
			if ((1 << cpu) & device->pwrctrl.l2pc_cpus_mask)
				cpumask_set_cpu(cpu, &device->pwrctrl.
						l2pc_cpus_qos.cpus_affine);
		}

		pm_qos_add_request(&device->pwrctrl.l2pc_cpus_qos,
				PM_QOS_CPU_DMA_LATENCY,
				PM_QOS_DEFAULT_VALUE);
	}


	device->events_wq = create_workqueue("kgsl-events");

@@ -3954,6 +3971,8 @@ void kgsl_device_platform_remove(struct kgsl_device *device)
	kgsl_pwrctrl_uninit_sysfs(device);

	pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma);
	if (device->pwrctrl.l2pc_cpus_mask)
		pm_qos_remove_request(&device->pwrctrl.l2pc_cpus_qos);

	idr_destroy(&device->context_idr);

+46 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2016, 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
@@ -54,6 +54,13 @@
#define DEFAULT_BUS_P 25
#define DEFAULT_BUS_DIV (100 / DEFAULT_BUS_P)

/*
 * The effective duration of qos request in usecs. After
 * timeout, qos request is cancelled automatically.
 * Kept 80ms default, inline with default GPU idle time.
 */
#define KGSL_L2PC_CPU_TIMEOUT	(80 * 1000)

/* Order deeply matters here because reasons. New entries go on the end */
static const char * const clocks[] = {
	"src_clk",
@@ -433,6 +440,33 @@ void kgsl_pwrctrl_set_constraint(struct kgsl_device *device,
}
EXPORT_SYMBOL(kgsl_pwrctrl_set_constraint);

/**
 * kgsl_pwrctrl_update_l2pc() - Update existing qos request
 * @device: Pointer to the kgsl_device struct
 *
 * Updates an existing qos request to avoid L2PC on the
 * CPUs (which are selected through dtsi) on which GPU
 * thread is running. This would help for performance.
 */
void kgsl_pwrctrl_update_l2pc(struct kgsl_device *device)
{
	int cpu;

	if (device->pwrctrl.l2pc_cpus_mask == 0)
		return;

	cpu = get_cpu();
	put_cpu();

	if ((1 << cpu) & device->pwrctrl.l2pc_cpus_mask) {
		pm_qos_update_request_timeout(
				&device->pwrctrl.l2pc_cpus_qos,
				device->pwrctrl.pm_qos_active_latency,
				KGSL_L2PC_CPU_TIMEOUT);
	}
}
EXPORT_SYMBOL(kgsl_pwrctrl_update_l2pc);

static ssize_t kgsl_pwrctrl_thermal_pwrlevel_store(struct device *dev,
					 struct device_attribute *attr,
					 const char *buf, size_t count)
@@ -1670,6 +1704,9 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
		&pwr->pm_qos_wakeup_latency))
		pwr->pm_qos_wakeup_latency = 101;

	kgsl_property_read_u32(device, "qcom,l2pc-cpu-mask",
			&pwr->l2pc_cpus_mask);

	pm_runtime_enable(&pdev->dev);

	ocmem_bus_node = of_find_node_by_name(
@@ -2158,6 +2195,10 @@ _sleep(struct kgsl_device *device)
		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP);
		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
					PM_QOS_DEFAULT_VALUE);
		if (device->pwrctrl.l2pc_cpus_mask)
			pm_qos_update_request(
					&device->pwrctrl.l2pc_cpus_qos,
					PM_QOS_DEFAULT_VALUE);
		break;
	case KGSL_STATE_SLUMBER:
		break;
@@ -2205,6 +2246,10 @@ _slumber(struct kgsl_device *device)
		kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER);
		pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma,
						PM_QOS_DEFAULT_VALUE);
		if (device->pwrctrl.l2pc_cpus_mask)
			pm_qos_update_request(
					&device->pwrctrl.l2pc_cpus_qos,
					PM_QOS_DEFAULT_VALUE);
		break;
	case KGSL_STATE_SUSPEND:
		complete_all(&device->hwaccess_gate);
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2010-2016, 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
@@ -128,6 +128,8 @@ struct kgsl_regulator {
 * @ocmem - ocmem bus scale identifier
 * @irq_name - resource name for the IRQ
 * @clk_stats - structure of clock statistics
 * @l2pc_cpus_mask - mask to avoid L2PC on masked CPUs
 * @l2pc_cpus_qos - qos structure to avoid L2PC on CPUs
 * @pm_qos_req_dma - the power management quality of service structure
 * @pm_qos_active_latency - allowed CPU latency in microseconds when active
 * @pm_qos_wakeup_latency - allowed CPU latency in microseconds during wakeup
@@ -176,6 +178,8 @@ struct kgsl_pwrctrl {
	uint32_t ocmem_pcl;
	const char *irq_name;
	struct kgsl_clk_stats clk_stats;
	unsigned int l2pc_cpus_mask;
	struct pm_qos_request l2pc_cpus_qos;
	struct pm_qos_request pm_qos_req_dma;
	unsigned int pm_qos_active_latency;
	unsigned int pm_qos_wakeup_latency;
@@ -238,4 +242,5 @@ int kgsl_active_count_wait(struct kgsl_device *device, int count);
void kgsl_pwrctrl_busy_time(struct kgsl_device *device, u64 time, u64 busy);
void kgsl_pwrctrl_set_constraint(struct kgsl_device *device,
			struct kgsl_pwr_constraint *pwrc, uint32_t id);
void kgsl_pwrctrl_update_l2pc(struct kgsl_device *device);
#endif /* __KGSL_PWRCTRL_H */