diff options
| author | Prakash Kamliya <pkamliya@codeaurora.org> | 2016-01-22 10:59:20 +0530 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:19:35 -0700 |
| commit | f087bb3d9ae69ccd2396929e397e9b7989eaeb6e (patch) | |
| tree | dd45087629c85fc9b2b880fc70ea978bbec967fe /drivers/gpu | |
| parent | 9b63383c0ab6d0eb1b90921d3ac4060b644c4a73 (diff) | |
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: Prakash Kamliya <pkamliya@codeaurora.org>
Diffstat (limited to 'drivers/gpu')
| -rw-r--r-- | drivers/gpu/msm/adreno_dispatch.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl.c | 19 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_pwrctrl.c | 47 | ||||
| -rw-r--r-- | drivers/gpu/msm/kgsl_pwrctrl.h | 7 |
4 files changed, 73 insertions, 2 deletions
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index d8a345cf8f5b..a2215a4af4ab 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -1177,6 +1177,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); diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index e42ade36e83f..6246147cec80 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -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); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 671639be249a..b884acf067a6 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1,4 +1,4 @@ -/* 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 @@ -53,6 +53,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", @@ -446,6 +453,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) @@ -1716,6 +1750,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( @@ -2205,6 +2242,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; @@ -2252,6 +2293,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); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 5335dbfa6a58..aa6462183ec3 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -1,4 +1,4 @@ -/* 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 */ |
