From 410b58af6126265d0b7369dbf0d10dd5ed654511 Mon Sep 17 00:00:00 2001 From: Aaron Tian Date: Wed, 18 Sep 2019 17:13:19 +0800 Subject: [PATCH] video: tegra: host: update T186 VIC actmon driver Modify T186/T210 VIC actmon driver and wmark_active governor to address the following issues: 1. To let VIC actmon reports accurate VIC active cycle counts, set static WEIGHT_COUNT in both VIC actmon and VIC IP block. It ensures VIC actmon can capture all activity signal toggle event from VIC. The value of WEIGHT_COUNT are equal to: 4 * (max VIC freq / VIC_actmon freq) = 4 * (1024 / 19.2) ~= 213 2. Since VIC actmon reports active "VIC clock cycle" instead of "VIC actmon clock cycle", "relative loading translation" should consider current VIC clock freq. E.g., - sample_period = 80 us, VIC freq = 115.2 Mhz - 9216 cycles represents 100% loading (115.2 * 80) 3. Update upper/lower wmark settings after VIC clock scaled completed, to ensure wmark settings are equil to 0 ~ 100% loading of current freq. - Register 'get_dev_status' instance in devfreq_dev_profile, to let wmark active governor can query current device freq. - Register devfreq transition notifier in wmark_active governor. It will query current device freq. and update corresponding wmark value after VIC freq. changed. Bug 200501949 Change-Id: Ic159eb93fddc37d55b0c9649a3afcb50ed82cac2 Signed-off-by: Aaron Tian Reviewed-on: https://git-master.nvidia.com/r/2200520 (cherry picked from commit d6c7740ea2ddd9d5087d938e9ee3b3bc2c9b6d0a) Reviewed-on: https://git-master.nvidia.com/r/2263225 GVS: Gerrit_Virtual_Submit Reviewed-by: Mikko Perttunen Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/devfreq/governor_wmark_active.c | 45 ++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/devfreq/governor_wmark_active.c b/drivers/devfreq/governor_wmark_active.c index 4f6d41c7..9dca71ac 100644 --- a/drivers/devfreq/governor_wmark_active.c +++ b/drivers/devfreq/governor_wmark_active.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2014-2020, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -46,6 +46,9 @@ struct wmark_gov_info { /* variable for keeping the average frequency request */ unsigned long long average_target_freq; + + /* devfreq notifier_block */ + struct notifier_block nb; }; static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo, @@ -185,9 +188,6 @@ static int devfreq_watermark_target_freq(struct devfreq *df, (wmarkinfo->p_smooth * wmarkinfo->average_target_freq + ideal_freq) / (wmarkinfo->p_smooth + 1); - /* update watermarks to match the ideal frequency */ - update_watermarks(df, dev_stat.current_frequency, ideal_freq); - /* do not scale too often */ if (dt < wmarkinfo->p_block_window) return 0; @@ -276,11 +276,38 @@ static int devfreq_watermark_start(struct devfreq *df) return 0; } +static int devfreq_watermark_notifier_call(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct wmark_gov_info *data + = container_of(nb, struct wmark_gov_info, nb); + struct devfreq *df = (struct devfreq *)data->df; + unsigned long freq = 0; + + switch (event) { + case DEVFREQ_PRECHANGE: + break; + case DEVFREQ_POSTCHANGE: + /* get device freq. */ + df->profile->get_cur_freq(df->dev.parent, &freq); + + /* update watermarks by current device freq. */ + if (freq) + update_watermarks(df, freq, freq); + break; + default: + break; + } + + return NOTIFY_DONE; +} + static int devfreq_watermark_event_handler(struct devfreq *df, unsigned int event, void *wmark_type) { struct wmark_gov_info *wmarkinfo; int ret = 0; + struct notifier_block *nb; switch (event) { case DEVFREQ_GOV_START: @@ -300,10 +327,20 @@ static int devfreq_watermark_event_handler(struct devfreq *df, update_watermarks(df, dev_stat.current_frequency, dev_stat.current_frequency); + + nb = &wmarkinfo->nb; + nb->notifier_call = devfreq_watermark_notifier_call; + ret = devm_devfreq_register_notifier(df->dev.parent, + df, nb, DEVFREQ_TRANSITION_NOTIFIER); break; } case DEVFREQ_GOV_STOP: devfreq_watermark_debug_stop(df); + + wmarkinfo = df->data; + nb = &wmarkinfo->nb; + devm_devfreq_unregister_notifier(df->dev.parent, + df, nb, DEVFREQ_TRANSITION_NOTIFIER); break; case DEVFREQ_GOV_SUSPEND: devfreq_monitor_suspend(df);