Loading Documentation/devicetree/bindings/gpu/adreno.txt +5 −0 Original line number Diff line number Diff line Loading @@ -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: Loading drivers/gpu/msm/adreno_dispatch.c +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading drivers/gpu/msm/kgsl.c +19 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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"); Loading Loading @@ -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); Loading drivers/gpu/msm/kgsl_pwrctrl.c +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 Loading Loading @@ -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", Loading Loading @@ -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) Loading Loading @@ -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( Loading Loading @@ -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; Loading Loading @@ -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); Loading drivers/gpu/msm/kgsl_pwrctrl.h +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 Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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 */ Loading
Documentation/devicetree/bindings/gpu/adreno.txt +5 −0 Original line number Diff line number Diff line Loading @@ -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: Loading
drivers/gpu/msm/adreno_dispatch.c +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
drivers/gpu/msm/kgsl.c +19 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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"); Loading Loading @@ -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); Loading
drivers/gpu/msm/kgsl_pwrctrl.c +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 Loading Loading @@ -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", Loading Loading @@ -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) Loading Loading @@ -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( Loading Loading @@ -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; Loading Loading @@ -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); Loading
drivers/gpu/msm/kgsl_pwrctrl.h +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 Loading Loading @@ -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 Loading Loading @@ -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; Loading Loading @@ -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 */