Lines Matching +full:min +full:- +full:residency
1 // SPDX-License-Identifier: GPL-2.0
40 * struct cdev_debugfs - per cooling device statistics structure
65 * struct cdev_record - Common structure for cooling device entry
74 * @residency: a ktime_t representing a state residency duration
81 ktime_t residency; member
87 * struct trip_stats - Thermal trip statistics
96 * @min: minimum recorded temperature above the trip point
104 int min; member
109 * struct tz_episode - A mitigation episode information
131 * struct tz_debugfs - Store all mitigation episodes for a thermal zone
152 * struct thermal_debugfs - High level structure for a thermal object in debugfs
194 mutex_init(&thermal_dbg->lock); in thermal_debugfs_add_id()
198 thermal_dbg->d_top = debugfs_create_dir(ids, d); in thermal_debugfs_add_id()
199 if (!thermal_dbg->d_top) { in thermal_debugfs_add_id()
212 debugfs_remove(thermal_dbg->d_top); in thermal_debugfs_remove_id()
227 cdev_record->id = id; in thermal_debugfs_cdev_record_alloc()
228 INIT_LIST_HEAD(&cdev_record->node); in thermal_debugfs_cdev_record_alloc()
229 list_add_tail(&cdev_record->node, in thermal_debugfs_cdev_record_alloc()
230 &lists[cdev_record->id % CDEVSTATS_HASH_SIZE]); in thermal_debugfs_cdev_record_alloc()
242 if (entry->id == id) in thermal_debugfs_cdev_record_find()
269 &cdev_dbg->transitions[i], node) { in thermal_debugfs_cdev_clear()
270 list_del(&entry->node); in thermal_debugfs_cdev_clear()
275 &cdev_dbg->durations[i], node) { in thermal_debugfs_cdev_clear()
276 list_del(&entry->node); in thermal_debugfs_cdev_clear()
281 cdev_dbg->total = 0; in thermal_debugfs_cdev_clear()
286 struct thermal_debugfs *thermal_dbg = s->private; in cdev_seq_start()
288 mutex_lock(&thermal_dbg->lock); in cdev_seq_start()
302 struct thermal_debugfs *thermal_dbg = s->private; in cdev_seq_stop()
304 mutex_unlock(&thermal_dbg->lock); in cdev_seq_stop()
309 struct thermal_debugfs *thermal_dbg = s->private; in cdev_tt_seq_show()
310 struct cdev_debugfs *cdev_dbg = &thermal_dbg->cdev_dbg; in cdev_tt_seq_show()
311 struct list_head *transitions = cdev_dbg->transitions; in cdev_tt_seq_show()
321 * string for a transition would be "1024->1024\0" in cdev_tt_seq_show()
325 snprintf(buffer, ARRAY_SIZE(buffer), "%d->%d", in cdev_tt_seq_show()
326 entry->id >> 16, entry->id & 0xFFFF); in cdev_tt_seq_show()
328 seq_printf(s, "%-10s\t%-10llu\n", buffer, entry->count); in cdev_tt_seq_show()
345 struct thermal_debugfs *thermal_dbg = s->private; in cdev_dt_seq_show()
346 struct cdev_debugfs *cdev_dbg = &thermal_dbg->cdev_dbg; in cdev_dt_seq_show()
347 struct list_head *durations = cdev_dbg->durations; in cdev_dt_seq_show()
355 s64 duration = ktime_to_ms(entry->residency); in cdev_dt_seq_show()
357 if (entry->id == cdev_dbg->current_state) in cdev_dt_seq_show()
359 cdev_dbg->timestamp); in cdev_dt_seq_show()
361 seq_printf(s, "%-5d\t%-10llu\n", entry->id, duration); in cdev_dt_seq_show()
381 return -EINVAL; in cdev_clear_set()
383 mutex_lock(&thermal_dbg->lock); in cdev_clear_set()
385 thermal_debugfs_cdev_clear(&thermal_dbg->cdev_dbg); in cdev_clear_set()
387 mutex_unlock(&thermal_dbg->lock); in cdev_clear_set()
395 * thermal_debug_cdev_state_update - Update a cooling device state change
397 * Computes a transition and the duration of the previous state residency.
405 struct thermal_debugfs *thermal_dbg = cdev->debugfs; in thermal_debug_cdev_state_update()
410 if (!thermal_dbg || (thermal_dbg->cdev_dbg.current_state == new_state)) in thermal_debug_cdev_state_update()
413 mutex_lock(&thermal_dbg->lock); in thermal_debug_cdev_state_update()
415 cdev_dbg = &thermal_dbg->cdev_dbg; in thermal_debug_cdev_state_update()
417 old_state = cdev_dbg->current_state; in thermal_debug_cdev_state_update()
426 cdev_dbg->durations, in thermal_debug_cdev_state_update()
430 ktime_t delta = ktime_sub(now, cdev_dbg->timestamp); in thermal_debug_cdev_state_update()
431 cdev_record->residency = ktime_add(cdev_record->residency, delta); in thermal_debug_cdev_state_update()
432 cdev_dbg->timestamp = now; in thermal_debug_cdev_state_update()
435 cdev_dbg->current_state = new_state; in thermal_debug_cdev_state_update()
445 cdev_dbg->transitions, in thermal_debug_cdev_state_update()
448 cdev_record->count++; in thermal_debug_cdev_state_update()
450 cdev_dbg->total++; in thermal_debug_cdev_state_update()
452 mutex_unlock(&thermal_dbg->lock); in thermal_debug_cdev_state_update()
456 * thermal_debug_cdev_add - Add a cooling device debugfs entry
468 thermal_dbg = thermal_debugfs_add_id(d_cdev, cdev->id); in thermal_debug_cdev_add()
472 cdev_dbg = &thermal_dbg->cdev_dbg; in thermal_debug_cdev_add()
475 INIT_LIST_HEAD(&cdev_dbg->transitions[i]); in thermal_debug_cdev_add()
476 INIT_LIST_HEAD(&cdev_dbg->durations[i]); in thermal_debug_cdev_add()
479 cdev_dbg->current_state = 0; in thermal_debug_cdev_add()
480 cdev_dbg->timestamp = ktime_get(); in thermal_debug_cdev_add()
482 debugfs_create_file("trans_table", 0400, thermal_dbg->d_top, in thermal_debug_cdev_add()
485 debugfs_create_file("time_in_state_ms", 0400, thermal_dbg->d_top, in thermal_debug_cdev_add()
488 debugfs_create_file("clear", 0200, thermal_dbg->d_top, in thermal_debug_cdev_add()
491 debugfs_create_u32("total_trans", 0400, thermal_dbg->d_top, in thermal_debug_cdev_add()
492 &cdev_dbg->total); in thermal_debug_cdev_add()
494 cdev->debugfs = thermal_dbg; in thermal_debug_cdev_add()
498 * thermal_debug_cdev_remove - Remove a cooling device debugfs entry
506 struct thermal_debugfs *thermal_dbg = cdev->debugfs; in thermal_debug_cdev_remove()
511 mutex_lock(&thermal_dbg->lock); in thermal_debug_cdev_remove()
513 thermal_debugfs_cdev_clear(&thermal_dbg->cdev_dbg); in thermal_debug_cdev_remove()
514 cdev->debugfs = NULL; in thermal_debug_cdev_remove()
516 mutex_unlock(&thermal_dbg->lock); in thermal_debug_cdev_remove()
527 tze = kzalloc(struct_size(tze, trip_stats, tz->num_trips), GFP_KERNEL); in thermal_debugfs_tz_event_alloc()
531 INIT_LIST_HEAD(&tze->node); in thermal_debugfs_tz_event_alloc()
532 tze->timestamp = now; in thermal_debugfs_tz_event_alloc()
534 for (i = 0; i < tz->num_trips; i++) { in thermal_debugfs_tz_event_alloc()
535 tze->trip_stats[i].min = INT_MAX; in thermal_debugfs_tz_event_alloc()
536 tze->trip_stats[i].max = INT_MIN; in thermal_debugfs_tz_event_alloc()
547 struct thermal_debugfs *thermal_dbg = tz->debugfs; in thermal_debug_tz_trip_up()
548 int temperature = tz->temperature; in thermal_debug_tz_trip_up()
555 mutex_lock(&thermal_dbg->lock); in thermal_debug_tz_trip_up()
557 tz_dbg = &thermal_dbg->tz_dbg; in thermal_debug_tz_trip_up()
573 * | -------- in thermal_debug_tz_trip_up()
574 * trip 2 / \ ------ in thermal_debug_tz_trip_up()
576 * trip 1 / | | `---- | | \ in thermal_debug_tz_trip_up()
580 * | / | | | | | | | | `-- in thermal_debug_tz_trip_up()
582 * |----- | | | | | | | | in thermal_debug_tz_trip_up()
584 * --------|-|-|--------|--------|------|-|-|------------------> time in thermal_debug_tz_trip_up()
585 * | | |<--t2-->| |<-t2'>| | | in thermal_debug_tz_trip_up()
587 * | |<------------t1------------>| | in thermal_debug_tz_trip_up()
589 * |<-------------t0--------------->| in thermal_debug_tz_trip_up()
592 if (!tz_dbg->nr_trips) { in thermal_debug_tz_trip_up()
597 list_add(&tze->node, &tz_dbg->tz_episodes); in thermal_debug_tz_trip_up()
613 tz_dbg->trips_crossed[tz_dbg->nr_trips++] = trip_id; in thermal_debug_tz_trip_up()
615 tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node); in thermal_debug_tz_trip_up()
616 tze->trip_stats[trip_id].timestamp = now; in thermal_debug_tz_trip_up()
617 tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature); in thermal_debug_tz_trip_up()
618 tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature); in thermal_debug_tz_trip_up()
619 tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg + in thermal_debug_tz_trip_up()
620 (temperature - tze->trip_stats[trip_id].avg) / in thermal_debug_tz_trip_up()
621 tze->trip_stats[trip_id].count; in thermal_debug_tz_trip_up()
624 mutex_unlock(&thermal_dbg->lock); in thermal_debug_tz_trip_up()
630 struct thermal_debugfs *thermal_dbg = tz->debugfs; in thermal_debug_tz_trip_down()
640 mutex_lock(&thermal_dbg->lock); in thermal_debug_tz_trip_down()
642 tz_dbg = &thermal_dbg->tz_dbg; in thermal_debug_tz_trip_down()
651 if (!tz_dbg->nr_trips) in thermal_debug_tz_trip_down()
654 for (i = tz_dbg->nr_trips - 1; i >= 0; i--) { in thermal_debug_tz_trip_down()
655 if (tz_dbg->trips_crossed[i] == trip_id) in thermal_debug_tz_trip_down()
662 tz_dbg->nr_trips--; in thermal_debug_tz_trip_down()
664 if (i < tz_dbg->nr_trips) in thermal_debug_tz_trip_down()
665 tz_dbg->trips_crossed[i] = tz_dbg->trips_crossed[tz_dbg->nr_trips]; in thermal_debug_tz_trip_down()
667 tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node); in thermal_debug_tz_trip_down()
669 delta = ktime_sub(now, tze->trip_stats[trip_id].timestamp); in thermal_debug_tz_trip_down()
671 tze->trip_stats[trip_id].duration = in thermal_debug_tz_trip_down()
672 ktime_add(delta, tze->trip_stats[trip_id].duration); in thermal_debug_tz_trip_down()
678 if (!tz_dbg->nr_trips) in thermal_debug_tz_trip_down()
679 tze->duration = ktime_sub(now, tze->timestamp); in thermal_debug_tz_trip_down()
682 mutex_unlock(&thermal_dbg->lock); in thermal_debug_tz_trip_down()
687 struct thermal_debugfs *thermal_dbg = tz->debugfs; in thermal_debug_update_temp()
695 mutex_lock(&thermal_dbg->lock); in thermal_debug_update_temp()
697 tz_dbg = &thermal_dbg->tz_dbg; in thermal_debug_update_temp()
699 if (!tz_dbg->nr_trips) in thermal_debug_update_temp()
702 for (i = 0; i < tz_dbg->nr_trips; i++) { in thermal_debug_update_temp()
703 trip_id = tz_dbg->trips_crossed[i]; in thermal_debug_update_temp()
704 tze = list_first_entry(&tz_dbg->tz_episodes, struct tz_episode, node); in thermal_debug_update_temp()
705 tze->trip_stats[trip_id].count++; in thermal_debug_update_temp()
706 tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, tz->temperature); in thermal_debug_update_temp()
707 tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, tz->temperature); in thermal_debug_update_temp()
708 tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg + in thermal_debug_update_temp()
709 (tz->temperature - tze->trip_stats[trip_id].avg) / in thermal_debug_update_temp()
710 tze->trip_stats[trip_id].count; in thermal_debug_update_temp()
713 mutex_unlock(&thermal_dbg->lock); in thermal_debug_update_temp()
718 struct thermal_zone_device *tz = s->private; in tze_seq_start()
719 struct thermal_debugfs *thermal_dbg = tz->debugfs; in tze_seq_start()
720 struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg; in tze_seq_start()
722 mutex_lock(&thermal_dbg->lock); in tze_seq_start()
724 return seq_list_start(&tz_dbg->tz_episodes, *pos); in tze_seq_start()
729 struct thermal_zone_device *tz = s->private; in tze_seq_next()
730 struct thermal_debugfs *thermal_dbg = tz->debugfs; in tze_seq_next()
731 struct tz_debugfs *tz_dbg = &thermal_dbg->tz_dbg; in tze_seq_next()
733 return seq_list_next(v, &tz_dbg->tz_episodes, pos); in tze_seq_next()
738 struct thermal_zone_device *tz = s->private; in tze_seq_stop()
739 struct thermal_debugfs *thermal_dbg = tz->debugfs; in tze_seq_stop()
741 mutex_unlock(&thermal_dbg->lock); in tze_seq_stop()
746 struct thermal_zone_device *tz = s->private; in tze_seq_show()
754 seq_printf(s, ",-Mitigation at %lluus, duration=%llums\n", in tze_seq_show()
755 ktime_to_us(tze->timestamp), in tze_seq_show()
756 ktime_to_ms(tze->duration)); in tze_seq_show()
758 …seq_printf(s, "| trip | type | temp(°mC) | hyst(°mC) | duration | avg(°mC) | min(°mC) | m… in tze_seq_show()
766 if (trip->type == THERMAL_TRIP_CRITICAL) in tze_seq_show()
769 if (trip->type == THERMAL_TRIP_PASSIVE) in tze_seq_show()
771 else if (trip->type == THERMAL_TRIP_ACTIVE) in tze_seq_show()
781 9, trip->temperature, in tze_seq_show()
782 9, trip->hysteresis, in tze_seq_show()
783 10, ktime_to_ms(tze->trip_stats[trip_id].duration), in tze_seq_show()
784 9, tze->trip_stats[trip_id].avg, in tze_seq_show()
785 9, tze->trip_stats[trip_id].min, in tze_seq_show()
786 9, tze->trip_stats[trip_id].max); in tze_seq_show()
806 thermal_dbg = thermal_debugfs_add_id(d_tz, tz->id); in thermal_debug_tz_add()
810 tz_dbg = &thermal_dbg->tz_dbg; in thermal_debug_tz_add()
812 tz_dbg->trips_crossed = kzalloc(sizeof(int) * tz->num_trips, GFP_KERNEL); in thermal_debug_tz_add()
813 if (!tz_dbg->trips_crossed) { in thermal_debug_tz_add()
818 INIT_LIST_HEAD(&tz_dbg->tz_episodes); in thermal_debug_tz_add()
820 debugfs_create_file("mitigations", 0400, thermal_dbg->d_top, tz, &tze_fops); in thermal_debug_tz_add()
822 tz->debugfs = thermal_dbg; in thermal_debug_tz_add()
827 struct thermal_debugfs *thermal_dbg = tz->debugfs; in thermal_debug_tz_remove()
832 mutex_lock(&thermal_dbg->lock); in thermal_debug_tz_remove()
834 tz->debugfs = NULL; in thermal_debug_tz_remove()
836 mutex_unlock(&thermal_dbg->lock); in thermal_debug_tz_remove()