From: Hyeonseong Gil Date: Fri, 1 Apr 2016 00:39:23 +0000 (+0900) Subject: [COMMON] thermal: gpu_cooling: introduce power_allocator API X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=e38c1e3b614f73da1d7405e00b272c6c29ef0493;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] thermal: gpu_cooling: introduce power_allocator API Resolved migration conflicts from kernel 4.9 to 4.14. - rename gpufreq_device -> gpufreq_cdev - but keep up idr, power_table and build_dyn_power_table Change-Id: I9e18fb576053a2d2371a79c11757be0364982fb6 Signed-off-by: Hyeonseong Gil --- diff --git a/drivers/thermal/gpu_cooling.c b/drivers/thermal/gpu_cooling.c index 852c4ab01d40..8df12c8d1d00 100644 --- a/drivers/thermal/gpu_cooling.c +++ b/drivers/thermal/gpu_cooling.c @@ -28,6 +28,20 @@ #include #include #include +#include + +/** + * struct power_table - frequency to power conversion + * @frequency: frequency in KHz + * @power: power in mW + * + * This structure is built when the cooling device registers and helps + * in translating frequency to power and viceversa. + */ +struct power_table { + u32 frequency; + u32 power; +}; /** * struct gpufreq_cooling_device - data for cooling device with gpufreq @@ -39,7 +53,6 @@ * cooling devices. * @gpufreq_val: integer value representing the absolute value of the clipped * frequency. - * @allowed_gpus: all the gpus involved for this gpufreq_cooling_device. * * This structure is required for keeping information of each * gpufreq_cooling_device registered. In order to prevent corruption of this a @@ -50,12 +63,17 @@ struct gpufreq_cooling_device { struct thermal_cooling_device *cool_dev; unsigned int gpufreq_state; unsigned int gpufreq_val; + u32 last_load; + struct power_table *dyn_power_table; + int dyn_power_table_entries; + get_static_t plat_get_static_power; }; + static DEFINE_IDR(gpufreq_idr); static DEFINE_MUTEX(cooling_gpu_lock); static BLOCKING_NOTIFIER_HEAD(gpu_notifier); -static unsigned int gpufreq_dev_count; +static unsigned int gpufreq_cdev_count; extern struct cpufreq_frequency_table gpu_freq_table[]; @@ -215,9 +233,151 @@ unsigned long gpufreq_cooling_get_level(unsigned int gpu, unsigned int freq) } EXPORT_SYMBOL_GPL(gpufreq_cooling_get_level); +/** + * build_dyn_power_table() - create a dynamic power to frequency table + * @gpufreq_cdev: the gpufreq cooling device in which to store the table + * @capacitance: dynamic power coefficient for these gpus + * + * Build a dynamic power to frequency table for this gpu and store it + * in @gpufreq_cdev. This table will be used in gpu_power_to_freq() and + * gpu_freq_to_power() to convert between power and frequency + * efficiently. Power is stored in mW, frequency in KHz. The + * resulting table is in ascending order. + * + * Return: 0 on success, -EINVAL if there are no OPPs for any CPUs, + * -ENOMEM if we run out of memory or -EAGAIN if an OPP was + * added/enabled while the function was executing. + */ +static int build_dyn_power_table(struct gpufreq_cooling_device *gpufreq_cdev, + u32 capacitance) +{ + struct power_table *power_table; + int num_opps = 0, i, cnt = 0; + unsigned long freq; + + num_opps = gpu_dvfs_get_step(); + + if (num_opps == 0) + return -EINVAL; + + power_table = kcalloc(num_opps, sizeof(*power_table), GFP_KERNEL); + if (!power_table) + return -ENOMEM; + + for (freq = 0, i = 0; i < num_opps; i++) { + u32 voltage_mv; + u64 power; + + freq = gpu_dvfs_get_clock(num_opps - i - 1); + + if (freq > gpu_dvfs_get_max_freq()) + continue; + + voltage_mv = gpu_dvfs_get_voltage(freq) / 1000; + + /* + * Do the multiplication with MHz and millivolt so as + * to not overflow. + */ + power = (u64)capacitance * freq * voltage_mv * voltage_mv; + do_div(power, 1000000000); + + power_table[i].frequency = freq; + + /* power is stored in mW */ + power_table[i].power = power; + cnt++; + } + + gpufreq_cdev->dyn_power_table = power_table; + gpufreq_cdev->dyn_power_table_entries = cnt; + + return 0; +} + +static u32 gpu_freq_to_power(struct gpufreq_cooling_device *gpufreq_cdev, + u32 freq) +{ + int i; + struct power_table *pt = gpufreq_cdev->dyn_power_table; + + for (i = 1; i < gpufreq_cdev->dyn_power_table_entries; i++) + if (freq < pt[i].frequency) + break; + + return pt[i - 1].power; +} + +static u32 gpu_power_to_freq(struct gpufreq_cooling_device *gpufreq_cdev, + u32 power) +{ + int i; + struct power_table *pt = gpufreq_cdev->dyn_power_table; + + for (i = 1; i < gpufreq_cdev->dyn_power_table_entries; i++) + if (power < pt[i].power) + break; + + return pt[i - 1].frequency; +} + +/** + * get_static_power() - calculate the static power consumed by the gpus + * @gpufreq_cdev: struct &gpufreq_cooling_device for this gpu cdev + * @tz: thermal zone device in which we're operating + * @freq: frequency in KHz + * @power: pointer in which to store the calculated static power + * + * Calculate the static power consumed by the gpus described by + * @gpu_actor running at frequency @freq. This function relies on a + * platform specific function that should have been provided when the + * actor was registered. If it wasn't, the static power is assumed to + * be negligible. The calculated static power is stored in @power. + * + * Return: 0 on success, -E* on failure. + */ +static int get_static_power(struct gpufreq_cooling_device *gpufreq_cdev, + struct thermal_zone_device *tz, unsigned long freq, + u32 *power) +{ + unsigned long voltage; + + if (!gpufreq_cdev->plat_get_static_power || freq == 0) { + *power = 0; + return 0; + } + + voltage = gpu_dvfs_get_voltage(freq); + + if (voltage == 0) { + pr_warn("Failed to get voltage for frequency %lu\n", freq); + return -EINVAL; + } + + return gpufreq_cdev->plat_get_static_power(NULL, tz->passive_delay, + voltage, power); +} + +/** + * get_dynamic_power() - calculate the dynamic power + * @gpufreq_cdev: &gpufreq_cooling_device for this cdev + * @freq: current frequency + * + * Return: the dynamic power consumed by the gpus described by + * @gpufreq_cdev. + */ +static u32 get_dynamic_power(struct gpufreq_cooling_device *gpufreq_cdev, + unsigned long freq) +{ + u32 raw_gpu_power; + + raw_gpu_power = gpu_freq_to_power(gpufreq_cdev, freq); + return (raw_gpu_power * gpufreq_cdev->last_load) / 100; +} + /** * gpufreq_apply_cooling - function to apply frequency clipping. - * @gpufreq_device: gpufreq_cooling_device pointer containing frequency + * @gpufreq_cdev: gpufreq_cooling_device pointer containing frequency * clipping data. * @cooling_state: value of the cooling state. * @@ -227,14 +387,14 @@ EXPORT_SYMBOL_GPL(gpufreq_cooling_get_level); * Return: 0 on success, an error code otherwise (-EINVAL in case wrong * cooling state). */ -static int gpufreq_apply_cooling(struct gpufreq_cooling_device *gpufreq_device, +static int gpufreq_apply_cooling(struct gpufreq_cooling_device *gpufreq_cdev, unsigned long cooling_state) { /* Check if the old cooling action is same as new cooling action */ - if (gpufreq_device->gpufreq_state == cooling_state) + if (gpufreq_cdev->gpufreq_state == cooling_state) return 0; - gpufreq_device->gpufreq_state = cooling_state; + gpufreq_cdev->gpufreq_state = cooling_state; blocking_notifier_call_chain(&gpu_notifier, GPU_THROTTLING, &cooling_state); @@ -280,9 +440,9 @@ static int gpufreq_get_max_state(struct thermal_cooling_device *cdev, static int gpufreq_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { - struct gpufreq_cooling_device *gpufreq_device = cdev->devdata; + struct gpufreq_cooling_device *gpufreq_cdev = cdev->devdata; - *state = gpufreq_device->gpufreq_state; + *state = gpufreq_cdev->gpufreq_state; return 0; } @@ -300,9 +460,9 @@ static int gpufreq_get_cur_state(struct thermal_cooling_device *cdev, static int gpufreq_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { - struct gpufreq_cooling_device *gpufreq_device = cdev->devdata; + struct gpufreq_cooling_device *gpufreq_cdev = cdev->devdata; - return gpufreq_apply_cooling(gpufreq_device, state); + return gpufreq_apply_cooling(gpufreq_cdev, state); } static enum tmu_noti_state_t gpu_tstate = GPU_COLD; @@ -327,8 +487,151 @@ static int gpufreq_set_cur_temp(struct thermal_cooling_device *cdev, return 0; } +/** + * gpufreq_get_requested_power() - get the current power + * @cdev: &thermal_cooling_device pointer + * @tz: a valid thermal zone device pointer + * @power: pointer in which to store the resulting power + * + * Calculate the current power consumption of the gpus in milliwatts + * and store it in @power. This function should actually calculate + * the requested power, but it's hard to get the frequency that + * gpufreq would have assigned if there were no thermal limits. + * Instead, we calculate the current power on the assumption that the + * immediate future will look like the immediate past. + * + * We use the current frequency and the average load since this + * function was last called. In reality, there could have been + * multiple opps since this function was last called and that affects + * the load calculation. While it's not perfectly accurate, this + * simplification is good enough and works. REVISIT this, as more + * complex code may be needed if experiments show that it's not + * accurate enough. + * + * Return: 0 on success, -E* if getting the static power failed. + */ +static int gpufreq_get_requested_power(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, + u32 *power) +{ + unsigned long freq; + int ret = 0; + u32 static_power, dynamic_power; + struct gpufreq_cooling_device *gpufreq_cdev = cdev->devdata; + u32 load_gpu = 0; + + freq = gpu_dvfs_get_cur_clock(); + + load_gpu = gpu_dvfs_get_utilization();; + + gpufreq_cdev->last_load = load_gpu; + + dynamic_power = get_dynamic_power(gpufreq_cdev, freq); + ret = get_static_power(gpufreq_cdev, tz, freq, &static_power); + + if (ret) + return ret; + + if (trace_thermal_power_gpu_get_power_enabled()) { + trace_thermal_power_gpu_get_power( + freq, load_gpu, dynamic_power, static_power); + } + + *power = static_power + dynamic_power; + return 0; +} + +/** + * gpufreq_state2power() - convert a gpu cdev state to power consumed + * @cdev: &thermal_cooling_device pointer + * @tz: a valid thermal zone device pointer + * @state: cooling device state to be converted + * @power: pointer in which to store the resulting power + * + * Convert cooling device state @state into power consumption in + * milliwatts assuming 100% load. Store the calculated power in + * @power. + * + * Return: 0 on success, -EINVAL if the cooling device state could not + * be converted into a frequency or other -E* if there was an error + * when calculating the static power. + */ +static int gpufreq_state2power(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, + unsigned long state, u32 *power) +{ + unsigned int freq; + u32 static_power, dynamic_power; + int ret; + struct gpufreq_cooling_device *gpufreq_cdev = cdev->devdata; + + freq = gpu_freq_table[state].frequency / 1000; + if (!freq) + return -EINVAL; + + dynamic_power = gpu_freq_to_power(gpufreq_cdev, freq); + ret = get_static_power(gpufreq_cdev, tz, freq, &static_power); + if (ret) + return ret; + + *power = static_power + dynamic_power; + return 0; +} + +/** + * gpufreq_power2state() - convert power to a cooling device state + * @cdev: &thermal_cooling_device pointer + * @tz: a valid thermal zone device pointer + * @power: power in milliwatts to be converted + * @state: pointer in which to store the resulting state + * + * Calculate a cooling device state for the gpus described by @cdev + * that would allow them to consume at most @power mW and store it in + * @state. Note that this calculation depends on external factors + * such as the gpu load or the current static power. Calling this + * function with the same power as input can yield different cooling + * device states depending on those external factors. + * + * Return: 0 on success, -ENODEV if no gpus are online or -EINVAL if + * the calculated frequency could not be converted to a valid state. + * The latter should not happen unless the frequencies available to + * gpufreq have changed since the initialization of the gpu cooling + * device. + */ +static int gpufreq_power2state(struct thermal_cooling_device *cdev, + struct thermal_zone_device *tz, u32 power, + unsigned long *state) +{ + unsigned int cur_freq, target_freq; + int ret; + s32 dyn_power; + u32 last_load, normalised_power, static_power; + struct gpufreq_cooling_device *gpufreq_cdev = cdev->devdata; + + cur_freq = gpu_dvfs_get_cur_clock(); + ret = get_static_power(gpufreq_cdev, tz, cur_freq, &static_power); + if (ret) + return ret; + + dyn_power = power - static_power; + dyn_power = dyn_power > 0 ? dyn_power : 0; + last_load = gpufreq_cdev->last_load ?: 1; + normalised_power = (dyn_power * 100) / last_load; + target_freq = gpu_power_to_freq(gpufreq_cdev, normalised_power); + + *state = gpufreq_cooling_get_level(0, target_freq * 1000); + if (*state == THERMAL_CSTATE_INVALID) { + pr_warn("Failed to convert %dKHz for gpu into a cdev state\n", + target_freq); + return -EINVAL; + } + + trace_thermal_power_gpu_limit(target_freq, *state, power); + return 0; +} + /* Bind gpufreq callbacks to thermal cooling device ops */ -static struct thermal_cooling_device_ops const gpufreq_cooling_ops = { +static struct thermal_cooling_device_ops gpufreq_cooling_ops = { .get_max_state = gpufreq_get_max_state, .get_cur_state = gpufreq_get_cur_state, .set_cur_state = gpufreq_set_cur_state, @@ -345,6 +648,9 @@ int exynos_gpu_add_notifier(struct notifier_block *n) * __gpufreq_cooling_register - helper function to create gpufreq cooling device * @np: a valid struct device_node to the cooling device device tree node * @clip_gpus: gpumask of gpus where the frequency constraints will happen. + * @capacitance: dynamic power coefficient for these gpus + * @plat_static_func: function to calculate the static power consumed by these + * gpus (optional) * * This interface function registers the gpufreq cooling device with the name * "thermal-gpufreq-%x". This api can support multiple instances of gpufreq @@ -356,39 +662,53 @@ int exynos_gpu_add_notifier(struct notifier_block *n) */ static struct thermal_cooling_device * __gpufreq_cooling_register(struct device_node *np, - const struct cpumask *clip_gpus) + const struct cpumask *clip_gpus, u32 capacitance, + get_static_t plat_static_func) { struct thermal_cooling_device *cool_dev; - struct gpufreq_cooling_device *gpufreq_dev = NULL; + struct gpufreq_cooling_device *gpufreq_cdev = NULL; char dev_name[THERMAL_NAME_LENGTH]; int ret = 0; - gpufreq_dev = kzalloc(sizeof(struct gpufreq_cooling_device), + gpufreq_cdev = kzalloc(sizeof(struct gpufreq_cooling_device), GFP_KERNEL); - if (!gpufreq_dev) + if (!gpufreq_cdev) return ERR_PTR(-ENOMEM); - ret = get_idr(&gpufreq_idr, &gpufreq_dev->id); + ret = get_idr(&gpufreq_idr, &gpufreq_cdev->id); if (ret) { - kfree(gpufreq_dev); + kfree(gpufreq_cdev); return ERR_PTR(-EINVAL); } + if (capacitance) { + gpufreq_cooling_ops.get_requested_power = + gpufreq_get_requested_power; + gpufreq_cooling_ops.state2power = gpufreq_state2power; + gpufreq_cooling_ops.power2state = gpufreq_power2state; + gpufreq_cdev->plat_get_static_power = plat_static_func; + + ret = build_dyn_power_table(gpufreq_cdev, capacitance); + + if (ret) + return ERR_PTR(ret); + } + snprintf(dev_name, sizeof(dev_name), "thermal-gpufreq-%d", - gpufreq_dev->id); + gpufreq_cdev->id); - cool_dev = thermal_of_cooling_device_register(np, dev_name, gpufreq_dev, + cool_dev = thermal_of_cooling_device_register(np, dev_name, gpufreq_cdev, &gpufreq_cooling_ops); if (IS_ERR(cool_dev)) { - release_idr(&gpufreq_idr, gpufreq_dev->id); - kfree(gpufreq_dev); + release_idr(&gpufreq_idr, gpufreq_cdev->id); + kfree(gpufreq_cdev); return cool_dev; } - gpufreq_dev->cool_dev = cool_dev; - gpufreq_dev->gpufreq_state = 0; + gpufreq_cdev->cool_dev = cool_dev; + gpufreq_cdev->gpufreq_state = 0; mutex_lock(&cooling_gpu_lock); - gpufreq_dev_count++; + gpufreq_cdev_count++; mutex_unlock(&cooling_gpu_lock); @@ -409,7 +729,7 @@ __gpufreq_cooling_register(struct device_node *np, struct thermal_cooling_device * gpufreq_cooling_register(const struct cpumask *clip_gpus) { - return __gpufreq_cooling_register(NULL, clip_gpus); + return __gpufreq_cooling_register(NULL, clip_gpus, 0, NULL); } EXPORT_SYMBOL_GPL(gpufreq_cooling_register); @@ -433,10 +753,78 @@ of_gpufreq_cooling_register(struct device_node *np, if (!np) return ERR_PTR(-EINVAL); - return __gpufreq_cooling_register(np, clip_gpus); + return __gpufreq_cooling_register(np, clip_gpus, 0, NULL); } EXPORT_SYMBOL_GPL(of_gpufreq_cooling_register); +/** + * gpufreq_power_cooling_register() - create gpufreq cooling device with power extensions + * @clip_gpus: gpumask of gpus where the frequency constraints will happen + * @capacitance: dynamic power coefficient for these gpus + * @plat_static_func: function to calculate the static power consumed by these + * gpus (optional) + * + * This interface function registers the gpufreq cooling device with + * the name "thermal-gpufreq-%x". This api can support multiple + * instances of gpufreq cooling devices. Using this function, the + * cooling device will implement the power extensions by using a + * simple gpu power model. The gpus must have registered their OPPs + * using the OPP library. + * + * An optional @plat_static_func may be provided to calculate the + * static power consumed by these gpus. If the platform's static + * power consumption is unknown or negligible, make it NULL. + * + * Return: a valid struct thermal_cooling_device pointer on success, + * on failure, it returns a corresponding ERR_PTR(). + */ +struct thermal_cooling_device * +gpufreq_power_cooling_register(const struct cpumask *clip_gpus, u32 capacitance, + get_static_t plat_static_func) +{ + return __gpufreq_cooling_register(NULL, clip_gpus, capacitance, + plat_static_func); +} +EXPORT_SYMBOL(gpufreq_power_cooling_register); + +/** + * of_gpufreq_power_cooling_register() - create gpufreq cooling device with power extensions + * @np: a valid struct device_node to the cooling device device tree node + * @clip_gpus: gpumask of gpus where the frequency constraints will happen + * @capacitance: dynamic power coefficient for these gpus + * @plat_static_func: function to calculate the static power consumed by these + * gpus (optional) + * + * This interface function registers the gpufreq cooling device with + * the name "thermal-gpufreq-%x". This api can support multiple + * instances of gpufreq cooling devices. Using this API, the gpufreq + * cooling device will be linked to the device tree node provided. + * Using this function, the cooling device will implement the power + * extensions by using a simple gpu power model. The gpus must have + * registered their OPPs using the OPP library. + * + * An optional @plat_static_func may be provided to calculate the + * static power consumed by these gpus. If the platform's static + * power consumption is unknown or negligible, make it NULL. + * + * Return: a valid struct thermal_cooling_device pointer on success, + * on failure, it returns a corresponding ERR_PTR(). + */ +struct thermal_cooling_device * +of_gpufreq_power_cooling_register(struct device_node *np, + const struct cpumask *clip_gpus, + u32 capacitance, + get_static_t plat_static_func) +{ + if (!np) + return ERR_PTR(-EINVAL); + + return __gpufreq_cooling_register(np, clip_gpus, capacitance, + plat_static_func); +} +EXPORT_SYMBOL(of_gpufreq_power_cooling_register); + + /** * gpufreq_cooling_unregister - function to remove gpufreq cooling device. * @cdev: thermal cooling device pointer. @@ -445,18 +833,18 @@ EXPORT_SYMBOL_GPL(of_gpufreq_cooling_register); */ void gpufreq_cooling_unregister(struct thermal_cooling_device *cdev) { - struct gpufreq_cooling_device *gpufreq_dev; + struct gpufreq_cooling_device *gpufreq_cdev; if (!cdev) return; - gpufreq_dev = cdev->devdata; + gpufreq_cdev = cdev->devdata; mutex_lock(&cooling_gpu_lock); - gpufreq_dev_count--; + gpufreq_cdev_count--; mutex_unlock(&cooling_gpu_lock); - thermal_cooling_device_unregister(gpufreq_dev->cool_dev); - release_idr(&gpufreq_idr, gpufreq_dev->id); - kfree(gpufreq_dev); + thermal_cooling_device_unregister(gpufreq_cdev->cool_dev); + release_idr(&gpufreq_idr, gpufreq_cdev->id); + kfree(gpufreq_cdev); } EXPORT_SYMBOL_GPL(gpufreq_cooling_unregister); diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index f89ac734d69f..e2a53cf9d274 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -1222,6 +1222,8 @@ static int exynos_gpufreq_cooling_register(struct exynos_tmu_data *data) struct device_node *cool_np; struct of_phandle_args cooling_spec; int ret; + const char *governor_name; + u32 power_coefficient = 0; np = of_find_node_by_name(NULL, "thermal-zones"); if (!np) @@ -1244,7 +1246,13 @@ static int exynos_gpufreq_cooling_register(struct exynos_tmu_data *data) cool_np = cooling_spec.np; - data->cool_dev = of_gpufreq_cooling_register(cool_np, NULL); + if (!of_property_read_string(child, "governor", &governor_name)) { + if (!strncasecmp(governor_name, "power_allocator", THERMAL_NAME_LENGTH)) { + of_property_read_u32(cool_np, "dynamic-power-coefficient", &power_coefficient); + } + } + + data->cool_dev = of_gpufreq_power_cooling_register(cool_np, NULL, power_coefficient, NULL); return ret; } diff --git a/include/linux/gpu_cooling.h b/include/linux/gpu_cooling.h index 1a2435d9b34e..ff29dde41f7b 100755 --- a/include/linux/gpu_cooling.h +++ b/include/linux/gpu_cooling.h @@ -28,8 +28,10 @@ #include #include -#ifdef CONFIG_GPU_THERMAL +typedef int (*get_static_t)(cpumask_t *cpumask, int interval, + unsigned long voltage, u32 *power); +#ifdef CONFIG_GPU_THERMAL /** * gpufreq_cooling_register - function to create gpufreq cooling device. * @clip_gpus: cpumask of gpus where the frequency constraints will happen @@ -37,6 +39,10 @@ struct thermal_cooling_device * gpufreq_cooling_register(const struct cpumask *clip_gpus); +struct thermal_cooling_device * +gpufreq_power_cooling_register(const struct cpumask *clip_gpus, + u32 capacitance, get_static_t plat_static_func); + /** * of_gpufreq_cooling_register - create gpufreq cooling device based on DT. * @np: a valid struct device_node to the cooling device device tree node. @@ -46,6 +52,12 @@ gpufreq_cooling_register(const struct cpumask *clip_gpus); struct thermal_cooling_device * of_gpufreq_cooling_register(struct device_node *np, const struct cpumask *clip_gpus); + +struct thermal_cooling_device * +of_gpufreq_power_cooling_register(struct device_node *np, + const struct cpumask *clip_gpus, + u32 capacitance, + get_static_t plat_static_func); #else static inline struct thermal_cooling_device * of_gpufreq_cooling_register(struct device_node *np, @@ -53,6 +65,15 @@ of_gpufreq_cooling_register(struct device_node *np, { return NULL; } + +static inline struct thermal_cooling_device * +of_gpufreq_power_cooling_register(struct device_node *np, + const struct cpumask *clip_gpus, + u32 capacitance, + get_static_t plat_static_func) +{ + return NULL; +} #endif /** @@ -68,12 +89,30 @@ gpufreq_cooling_register(const struct cpumask *clip_gpus) { return NULL; } + +static inline struct thermal_cooling_device * +gpufreq_power_cooling_register(const struct cpumask *clip_gpus, + u32 capacitance, get_static_t plat_static_func) +{ + return NULL; +} + static inline struct thermal_cooling_device * of_gpufreq_cooling_register(struct device_node *np, const struct cpumask *clip_gpus) { return NULL; } + +static inline struct thermal_cooling_device * +of_gpufreq_power_cooling_register(struct device_node *np, + const struct cpumask *clip_gpus, + u32 capacitance, + get_static_t plat_static_func) +{ + return NULL; +} + static inline void gpufreq_cooling_unregister(struct thermal_cooling_device *cdev) { @@ -85,5 +124,19 @@ unsigned long gpufreq_cooling_get_level(unsigned int gpu, unsigned int freq) return THERMAL_CSTATE_INVALID; } #endif /* CONFIG_GPU_THERMAL */ - +#ifdef CONFIG_MALI_DVFS +extern int gpu_dvfs_get_clock(int level); +extern int gpu_dvfs_get_voltage(int clock); +extern int gpu_dvfs_get_step(void); +extern int gpu_dvfs_get_cur_clock(void); +extern int gpu_dvfs_get_utilization(void); +extern int gpu_dvfs_get_max_freq(void); +#else +static inline int gpu_dvfs_get_clock(int level) { return 0; } +static inline int gpu_dvfs_get_voltage(int clock) { return 0; } +static inline int gpu_dvfs_get_step(void) { return 0; } +static inline int gpu_dvfs_get_cur_clock(void) { return 0; } +static inline int gpu_dvfs_get_utilization(void) { return 0; } +static inline int gpu_dvfs_get_max_freq(void) { return 0; } +#endif #endif /* __GPU_COOLING_H__ */ diff --git a/include/trace/events/thermal.h b/include/trace/events/thermal.h index 466c09d882ad..8e1102d43cdc 100644 --- a/include/trace/events/thermal.h +++ b/include/trace/events/thermal.h @@ -204,6 +204,52 @@ TRACE_EVENT(thermal_power_devfreq_limit, __get_str(type), __entry->freq, __entry->cdev_state, __entry->power) ); + +TRACE_EVENT(thermal_power_gpu_get_power, + TP_PROTO(unsigned long freq, u32 load, u32 dynamic_power, u32 static_power), + + TP_ARGS(freq, load, dynamic_power, static_power), + + TP_STRUCT__entry( + __field(unsigned long, freq ) + __field(u32, load ) + __field(u32, dynamic_power ) + __field(u32, static_power ) + ), + + TP_fast_assign( + __entry->freq = freq; + __entry->load = load; + __entry->dynamic_power = dynamic_power; + __entry->static_power = static_power; + ), + + TP_printk("freq=%lu load=%d dynamic_power=%d static_power=%d", + __entry->freq, __entry->load, __entry->dynamic_power, __entry->static_power) +); + +TRACE_EVENT(thermal_power_gpu_limit, + TP_PROTO(unsigned int freq, unsigned long cdev_state, u32 power), + + TP_ARGS(freq, cdev_state, power), + + TP_STRUCT__entry( + __field(unsigned int, freq ) + __field(unsigned long, cdev_state) + __field(u32, power ) + ), + + TP_fast_assign( + __entry->freq = freq; + __entry->cdev_state = cdev_state; + __entry->power = power; + ), + + TP_printk("freq=%u cdev_state=%lu power=%u", + __entry->freq, __entry->cdev_state, + __entry->power) +); + #endif /* _TRACE_THERMAL_H */ /* This part must be outside protection */