Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thermal: add trace events to the power allocator governor

Add trace events for the power allocator governor and the power actor
interface of the cpu cooling device.

Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Javi Merino <javi.merino@arm.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>

authored by

Javi Merino and committed by
Eduardo Valentin
6828a471 6b775e87

+194 -4
+29 -2
drivers/thermal/cpu_cooling.c
··· 31 31 #include <linux/cpu.h> 32 32 #include <linux/cpu_cooling.h> 33 33 34 + #include <trace/events/thermal.h> 35 + 34 36 /* 35 37 * Cooling state <-> CPUFreq frequency 36 38 * ··· 590 588 u32 *power) 591 589 { 592 590 unsigned long freq; 593 - int cpu, ret; 591 + int i = 0, cpu, ret; 594 592 u32 static_power, dynamic_power, total_load = 0; 595 593 struct cpufreq_cooling_device *cpufreq_device = cdev->devdata; 594 + u32 *load_cpu = NULL; 596 595 597 596 freq = cpufreq_quick_get(cpumask_any(&cpufreq_device->allowed_cpus)); 597 + 598 + if (trace_thermal_power_cpu_get_power_enabled()) { 599 + u32 ncpus = cpumask_weight(&cpufreq_device->allowed_cpus); 600 + 601 + load_cpu = devm_kcalloc(&cdev->device, ncpus, sizeof(*load_cpu), 602 + GFP_KERNEL); 603 + } 598 604 599 605 for_each_cpu(cpu, &cpufreq_device->allowed_cpus) { 600 606 u32 load; ··· 613 603 load = 0; 614 604 615 605 total_load += load; 606 + if (trace_thermal_power_cpu_limit_enabled() && load_cpu) 607 + load_cpu[i] = load; 608 + 609 + i++; 616 610 } 617 611 618 612 cpufreq_device->last_load = total_load; 619 613 620 614 dynamic_power = get_dynamic_power(cpufreq_device, freq); 621 615 ret = get_static_power(cpufreq_device, tz, freq, &static_power); 622 - if (ret) 616 + if (ret) { 617 + if (load_cpu) 618 + devm_kfree(&cdev->device, load_cpu); 623 619 return ret; 620 + } 621 + 622 + if (load_cpu) { 623 + trace_thermal_power_cpu_get_power( 624 + &cpufreq_device->allowed_cpus, 625 + freq, load_cpu, i, dynamic_power, static_power); 626 + 627 + devm_kfree(&cdev->device, load_cpu); 628 + } 624 629 625 630 *power = static_power + dynamic_power; 626 631 return 0; ··· 743 718 return -EINVAL; 744 719 } 745 720 721 + trace_thermal_power_cpu_limit(&cpufreq_device->allowed_cpus, 722 + target_freq, *state, power); 746 723 return 0; 747 724 } 748 725
+20 -2
drivers/thermal/power_allocator.c
··· 19 19 #include <linux/slab.h> 20 20 #include <linux/thermal.h> 21 21 22 + #define CREATE_TRACE_POINTS 23 + #include <trace/events/thermal_power_allocator.h> 24 + 22 25 #include "thermal_core.h" 23 26 24 27 #define FRAC_BITS 10 ··· 141 138 /* feed-forward the known sustainable dissipatable power */ 142 139 power_range = tz->tzp->sustainable_power + frac_to_int(power_range); 143 140 144 - return clamp(power_range, (s64)0, (s64)max_allocatable_power); 141 + power_range = clamp(power_range, (s64)0, (s64)max_allocatable_power); 142 + 143 + trace_thermal_power_allocator_pid(tz, frac_to_int(err), 144 + frac_to_int(params->err_integral), 145 + frac_to_int(p), frac_to_int(i), 146 + frac_to_int(d), power_range); 147 + 148 + return power_range; 145 149 } 146 150 147 151 /** ··· 229 219 struct power_allocator_params *params = tz->governor_data; 230 220 u32 *req_power, *max_power, *granted_power, *extra_actor_power; 231 221 u32 total_req_power, max_allocatable_power; 232 - u32 power_range; 222 + u32 total_granted_power, power_range; 233 223 int i, num_actors, total_weight, ret = 0; 234 224 int trip_max_desired_temperature = params->trip_max_desired_temperature; 235 225 ··· 305 295 divvy_up_power(req_power, max_power, num_actors, total_req_power, 306 296 power_range, granted_power, extra_actor_power); 307 297 298 + total_granted_power = 0; 308 299 i = 0; 309 300 list_for_each_entry(instance, &tz->thermal_instances, tz_node) { 310 301 if (instance->trip != trip_max_desired_temperature) ··· 316 305 317 306 power_actor_set_power(instance->cdev, instance, 318 307 granted_power[i]); 308 + total_granted_power += granted_power[i]; 319 309 320 310 i++; 321 311 } 312 + 313 + trace_thermal_power_allocator(tz, req_power, total_req_power, 314 + granted_power, total_granted_power, 315 + num_actors, power_range, 316 + max_allocatable_power, current_temp, 317 + (s32)control_temp - (s32)current_temp); 322 318 323 319 devm_kfree(&tz->device, req_power); 324 320 unlock:
+58
include/trace/events/thermal.h
··· 77 77 __entry->trip_type) 78 78 ); 79 79 80 + TRACE_EVENT(thermal_power_cpu_get_power, 81 + TP_PROTO(const struct cpumask *cpus, unsigned long freq, u32 *load, 82 + size_t load_len, u32 dynamic_power, u32 static_power), 83 + 84 + TP_ARGS(cpus, freq, load, load_len, dynamic_power, static_power), 85 + 86 + TP_STRUCT__entry( 87 + __bitmask(cpumask, num_possible_cpus()) 88 + __field(unsigned long, freq ) 89 + __dynamic_array(u32, load, load_len) 90 + __field(size_t, load_len ) 91 + __field(u32, dynamic_power ) 92 + __field(u32, static_power ) 93 + ), 94 + 95 + TP_fast_assign( 96 + __assign_bitmask(cpumask, cpumask_bits(cpus), 97 + num_possible_cpus()); 98 + __entry->freq = freq; 99 + memcpy(__get_dynamic_array(load), load, 100 + load_len * sizeof(*load)); 101 + __entry->load_len = load_len; 102 + __entry->dynamic_power = dynamic_power; 103 + __entry->static_power = static_power; 104 + ), 105 + 106 + TP_printk("cpus=%s freq=%lu load={%s} dynamic_power=%d static_power=%d", 107 + __get_bitmask(cpumask), __entry->freq, 108 + __print_array(__get_dynamic_array(load), __entry->load_len, 4), 109 + __entry->dynamic_power, __entry->static_power) 110 + ); 111 + 112 + TRACE_EVENT(thermal_power_cpu_limit, 113 + TP_PROTO(const struct cpumask *cpus, unsigned int freq, 114 + unsigned long cdev_state, u32 power), 115 + 116 + TP_ARGS(cpus, freq, cdev_state, power), 117 + 118 + TP_STRUCT__entry( 119 + __bitmask(cpumask, num_possible_cpus()) 120 + __field(unsigned int, freq ) 121 + __field(unsigned long, cdev_state) 122 + __field(u32, power ) 123 + ), 124 + 125 + TP_fast_assign( 126 + __assign_bitmask(cpumask, cpumask_bits(cpus), 127 + num_possible_cpus()); 128 + __entry->freq = freq; 129 + __entry->cdev_state = cdev_state; 130 + __entry->power = power; 131 + ), 132 + 133 + TP_printk("cpus=%s freq=%u cdev_state=%lu power=%u", 134 + __get_bitmask(cpumask), __entry->freq, __entry->cdev_state, 135 + __entry->power) 136 + ); 137 + 80 138 #endif /* _TRACE_THERMAL_H */ 81 139 82 140 /* This part must be outside protection */
+87
include/trace/events/thermal_power_allocator.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM thermal_power_allocator 3 + 4 + #if !defined(_TRACE_THERMAL_POWER_ALLOCATOR_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_THERMAL_POWER_ALLOCATOR_H 6 + 7 + #include <linux/tracepoint.h> 8 + 9 + TRACE_EVENT(thermal_power_allocator, 10 + TP_PROTO(struct thermal_zone_device *tz, u32 *req_power, 11 + u32 total_req_power, u32 *granted_power, 12 + u32 total_granted_power, size_t num_actors, 13 + u32 power_range, u32 max_allocatable_power, 14 + unsigned long current_temp, s32 delta_temp), 15 + TP_ARGS(tz, req_power, total_req_power, granted_power, 16 + total_granted_power, num_actors, power_range, 17 + max_allocatable_power, current_temp, delta_temp), 18 + TP_STRUCT__entry( 19 + __field(int, tz_id ) 20 + __dynamic_array(u32, req_power, num_actors ) 21 + __field(u32, total_req_power ) 22 + __dynamic_array(u32, granted_power, num_actors) 23 + __field(u32, total_granted_power ) 24 + __field(size_t, num_actors ) 25 + __field(u32, power_range ) 26 + __field(u32, max_allocatable_power ) 27 + __field(unsigned long, current_temp ) 28 + __field(s32, delta_temp ) 29 + ), 30 + TP_fast_assign( 31 + __entry->tz_id = tz->id; 32 + memcpy(__get_dynamic_array(req_power), req_power, 33 + num_actors * sizeof(*req_power)); 34 + __entry->total_req_power = total_req_power; 35 + memcpy(__get_dynamic_array(granted_power), granted_power, 36 + num_actors * sizeof(*granted_power)); 37 + __entry->total_granted_power = total_granted_power; 38 + __entry->num_actors = num_actors; 39 + __entry->power_range = power_range; 40 + __entry->max_allocatable_power = max_allocatable_power; 41 + __entry->current_temp = current_temp; 42 + __entry->delta_temp = delta_temp; 43 + ), 44 + 45 + TP_printk("thermal_zone_id=%d req_power={%s} total_req_power=%u granted_power={%s} total_granted_power=%u power_range=%u max_allocatable_power=%u current_temperature=%lu delta_temperature=%d", 46 + __entry->tz_id, 47 + __print_array(__get_dynamic_array(req_power), 48 + __entry->num_actors, 4), 49 + __entry->total_req_power, 50 + __print_array(__get_dynamic_array(granted_power), 51 + __entry->num_actors, 4), 52 + __entry->total_granted_power, __entry->power_range, 53 + __entry->max_allocatable_power, __entry->current_temp, 54 + __entry->delta_temp) 55 + ); 56 + 57 + TRACE_EVENT(thermal_power_allocator_pid, 58 + TP_PROTO(struct thermal_zone_device *tz, s32 err, s32 err_integral, 59 + s64 p, s64 i, s64 d, s32 output), 60 + TP_ARGS(tz, err, err_integral, p, i, d, output), 61 + TP_STRUCT__entry( 62 + __field(int, tz_id ) 63 + __field(s32, err ) 64 + __field(s32, err_integral) 65 + __field(s64, p ) 66 + __field(s64, i ) 67 + __field(s64, d ) 68 + __field(s32, output ) 69 + ), 70 + TP_fast_assign( 71 + __entry->tz_id = tz->id; 72 + __entry->err = err; 73 + __entry->err_integral = err_integral; 74 + __entry->p = p; 75 + __entry->i = i; 76 + __entry->d = d; 77 + __entry->output = output; 78 + ), 79 + 80 + TP_printk("thermal_zone_id=%d err=%d err_integral=%d p=%lld i=%lld d=%lld output=%d", 81 + __entry->tz_id, __entry->err, __entry->err_integral, 82 + __entry->p, __entry->i, __entry->d, __entry->output) 83 + ); 84 + #endif /* _TRACE_THERMAL_POWER_ALLOCATOR_H */ 85 + 86 + /* This part must be outside protection */ 87 + #include <trace/define_trace.h>