diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 00ae40fd4977..2831803a1817 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2021, The Linux Foundation. All rights reserved. */ #include @@ -297,7 +297,8 @@ static void kgsl_pwrctrl_set_thermal_pwrlevel(struct kgsl_device *device, if (level >= pwr->num_pwrlevels) level = pwr->num_pwrlevels - 1; - pwr->thermal_pwrlevel = level; + pwr->sysfs_thermal_pwrlevel = level; + pwr->thermal_pwrlevel = max(pwr->cooling_thermal_pwrlevel, pwr->sysfs_thermal_pwrlevel); /* Update the current level using the new limit */ kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel); @@ -921,7 +922,7 @@ static ssize_t _max_clock_mhz_show(struct kgsl_device *device, char *buf) struct kgsl_pwrctrl *pwr = &device->pwrctrl; return scnprintf(buf, PAGE_SIZE, "%d\n", - pwr->pwrlevels[pwr->max_pwrlevel].gpu_freq / 1000000); + pwr->pwrlevels[pwr->thermal_pwrlevel].gpu_freq / 1000000); } static ssize_t max_clock_mhz_show(struct device *dev, @@ -937,7 +938,6 @@ static ssize_t _max_clock_mhz_store(struct kgsl_device *device, { u32 freq; int ret, level; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; ret = kstrtou32(buf, 0, &freq); if (ret) @@ -947,11 +947,12 @@ static ssize_t _max_clock_mhz_store(struct kgsl_device *device, if (level < 0) return level; - mutex_lock(&device->mutex); - pwr->max_pwrlevel = min_t(unsigned int, level, pwr->min_pwrlevel); - kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel); - mutex_unlock(&device->mutex); - + /* + * You would think this would set max_pwrlevel but the legacy behavior + * is that it set thermal_pwrlevel instead so we don't want to mess with + * that. + */ + kgsl_pwrctrl_set_thermal_pwrlevel(device, level); return count; } @@ -1552,6 +1553,8 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->max_pwrlevel = 0; pwr->min_pwrlevel = pwr->num_pwrlevels - 1; pwr->thermal_pwrlevel = 0; + pwr->sysfs_thermal_pwrlevel = 0; + pwr->cooling_thermal_pwrlevel = 0; pwr->thermal_pwrlevel_floor = pwr->min_pwrlevel; pwr->wakeup_maxpwrlevel = 0; diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index ad97e33ffea9..9b040126c57b 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2021, The Linux Foundation. All rights reserved. */ #ifndef __KGSL_PWRCTRL_H #define __KGSL_PWRCTRL_H @@ -89,7 +89,9 @@ struct kgsl_pwrlevel { * @nb - Notifier block to receive GPU OPP change event * @active_pwrlevel - The currently active power level * @previous_pwrlevel - The power level before transition - * @thermal_pwrlevel - maximum powerlevel constraint from thermal + * @thermal_pwrlevel - consolidated maximum thermal powerlevel constraint + * @sysfs_thermal_pwrlevel - maximum powerlevel constraint from sysfs + * @cooling_thermal_pwrlevel - maximum pwrlevel constraint from devfreq cooling fw * @thermal_pwrlevel_floor - minimum powerlevel constraint from thermal * @default_pwrlevel - device wake up power level * @max_pwrlevel - maximum allowable powerlevel per the user @@ -133,6 +135,8 @@ struct kgsl_pwrctrl { unsigned int active_pwrlevel; unsigned int previous_pwrlevel; unsigned int thermal_pwrlevel; + unsigned int sysfs_thermal_pwrlevel; + unsigned int cooling_thermal_pwrlevel; unsigned int thermal_pwrlevel_floor; unsigned int default_pwrlevel; unsigned int wakeup_maxpwrlevel; diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 995aa28143c2..d6ae94a3cb42 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2010-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2010-2021, The Linux Foundation. All rights reserved. */ #include @@ -654,7 +654,8 @@ static int opp_notify(struct notifier_block *nb, min_level = level; } - pwr->thermal_pwrlevel = max_level; + pwr->cooling_thermal_pwrlevel = max_level; + pwr->thermal_pwrlevel = max(pwr->cooling_thermal_pwrlevel, pwr->sysfs_thermal_pwrlevel); pwr->thermal_pwrlevel_floor = min_level; /* Update the current level using the new limit */