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 <atian@nvidia.com>
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 <mperttunen@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Aaron Tian
2019-09-18 17:13:19 +08:00
committed by Laxman Dewangan
parent 0a98957d78
commit 410b58af61

View File

@@ -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 * This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License, * 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 */ /* variable for keeping the average frequency request */
unsigned long long average_target_freq; unsigned long long average_target_freq;
/* devfreq notifier_block */
struct notifier_block nb;
}; };
static unsigned long freqlist_up(struct wmark_gov_info *wmarkinfo, 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 + (wmarkinfo->p_smooth * wmarkinfo->average_target_freq +
ideal_freq) / (wmarkinfo->p_smooth + 1); 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 */ /* do not scale too often */
if (dt < wmarkinfo->p_block_window) if (dt < wmarkinfo->p_block_window)
return 0; return 0;
@@ -276,11 +276,38 @@ static int devfreq_watermark_start(struct devfreq *df)
return 0; 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, static int devfreq_watermark_event_handler(struct devfreq *df,
unsigned int event, void *wmark_type) unsigned int event, void *wmark_type)
{ {
struct wmark_gov_info *wmarkinfo; struct wmark_gov_info *wmarkinfo;
int ret = 0; int ret = 0;
struct notifier_block *nb;
switch (event) { switch (event) {
case DEVFREQ_GOV_START: case DEVFREQ_GOV_START:
@@ -300,10 +327,20 @@ static int devfreq_watermark_event_handler(struct devfreq *df,
update_watermarks(df, dev_stat.current_frequency, update_watermarks(df, dev_stat.current_frequency,
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; break;
} }
case DEVFREQ_GOV_STOP: case DEVFREQ_GOV_STOP:
devfreq_watermark_debug_stop(df); devfreq_watermark_debug_stop(df);
wmarkinfo = df->data;
nb = &wmarkinfo->nb;
devm_devfreq_unregister_notifier(df->dev.parent,
df, nb, DEVFREQ_TRANSITION_NOTIFIER);
break; break;
case DEVFREQ_GOV_SUSPEND: case DEVFREQ_GOV_SUSPEND:
devfreq_monitor_suspend(df); devfreq_monitor_suspend(df);