msm: kgsl: Dynamic AB voting based on actual bus transactions
Right now AB vote is calulated as a percentage of total possible BW which causes higher AB vote than actual GPU bus transactions in some use cases. We can calculate actual GPU bus BW if we know bus_width for the target. This change will derive AB vote based on bus_width defined in dtsi and VBIF counters. Define bus_width in number of bytes in target gpu dtsi file to use this new AB vote calculation. Change-Id: I75d19c18649d9a87d20e3dbf7b623b772265fb5b Signed-off-by: Mihir Patel <mihirp@codeaurora.org>
This commit is contained in:
parent
e5c5e18d13
commit
72c4388425
|
@ -82,6 +82,8 @@ Optional Properties:
|
|||
- qcom,initial-powerlevel: This value indicates which qcom,gpu-pwrlevel should be used at start time
|
||||
and when coming back out of resume
|
||||
- qcom,bus-control: Boolean. Enables an independent bus vote from the gpu frequency
|
||||
- qcom,bus-width: Bus width in number of bytes. This enables dynamic AB bus voting based on
|
||||
bus width and actual bus transactions.
|
||||
- qcom,gpubw-dev: a phandle to a device representing bus bandwidth requirements
|
||||
(see devdw.txt)
|
||||
- qcom,idle-timeout: This property represents the time in microseconds for idle timeout.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -23,6 +23,8 @@
|
|||
#define HIST 5
|
||||
#define TARGET 80
|
||||
#define CAP 75
|
||||
/* AB vote is in multiple of BW_STEP Mega bytes */
|
||||
#define BW_STEP 160
|
||||
|
||||
static void _update_cutoff(struct devfreq_msm_adreno_tz_data *priv,
|
||||
unsigned int norm_max)
|
||||
|
@ -59,6 +61,7 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
|
|||
*/
|
||||
static int norm_ab_max = 300;
|
||||
int norm_ab;
|
||||
unsigned long ab_mbytes = 0;
|
||||
|
||||
stats.private_data = &b;
|
||||
|
||||
|
@ -103,8 +106,15 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
|
|||
bus_profile->flag = DEVFREQ_FLAG_SLOW_HINT;
|
||||
}
|
||||
|
||||
/* Re-calculate the AB percentage for a new IB vote */
|
||||
if (bus_profile->flag) {
|
||||
/* Calculate the AB vote based on bus width if defined */
|
||||
if (priv->bus.width) {
|
||||
norm_ab = (unsigned int)priv->bus.ram_time /
|
||||
(unsigned int) priv->bus.total_time;
|
||||
/* Calculate AB in Mega Bytes and roundup in BW_STEP */
|
||||
ab_mbytes = (norm_ab * priv->bus.width * 1000000ULL) >> 20;
|
||||
bus_profile->ab_mbytes = roundup(ab_mbytes, BW_STEP);
|
||||
} else if (bus_profile->flag) {
|
||||
/* Re-calculate the AB percentage for a new IB vote */
|
||||
norm_ab = (unsigned int)priv->bus.ram_time /
|
||||
(unsigned int) priv->bus.total_time;
|
||||
if (norm_ab > norm_ab_max)
|
||||
|
|
|
@ -168,8 +168,10 @@ static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr,
|
|||
return;
|
||||
if (ib == 0)
|
||||
*ab = 0;
|
||||
else if (!pwr->bus_percent_ab)
|
||||
else if ((!pwr->bus_percent_ab) && (!pwr->bus_ab_mbytes))
|
||||
*ab = DEFAULT_BUS_P * ib / 100;
|
||||
else if (pwr->bus_width)
|
||||
*ab = pwr->bus_ab_mbytes;
|
||||
else
|
||||
*ab = (pwr->bus_percent_ab * max_bw) / 100;
|
||||
|
||||
|
@ -250,6 +252,8 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device,
|
|||
} else {
|
||||
/* If the bus is being turned off, reset to default level */
|
||||
pwr->bus_mod = 0;
|
||||
pwr->bus_percent_ab = 0;
|
||||
pwr->bus_ab_mbytes = 0;
|
||||
}
|
||||
trace_kgsl_buslevel(device, pwr->active_pwrlevel, buslevel);
|
||||
last_vote_buslevel = buslevel;
|
||||
|
@ -1553,6 +1557,10 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
|
|||
|
||||
/* Set if independent bus BW voting is supported */
|
||||
pwr->bus_control = pdata->bus_control;
|
||||
/* Bus width in bytes, set it to zero if not found */
|
||||
if (of_property_read_u32(pdev->dev.of_node, "qcom,bus-width",
|
||||
&pwr->bus_width))
|
||||
pwr->bus_width = 0;
|
||||
|
||||
/* Check if gpu bandwidth vote device is defined in dts */
|
||||
gpubw_dev_node = of_parse_phandle(pdev->dev.of_node,
|
||||
|
|
|
@ -108,6 +108,8 @@ struct kgsl_pwr_constraint {
|
|||
* @bus_control - true if the bus calculation is independent
|
||||
* @bus_mod - modifier from the current power level for the bus vote
|
||||
* @bus_percent_ab - current percent of total possible bus usage
|
||||
* @bus_width - target specific bus width in number of bytes
|
||||
* @bus_ab_mbytes - AB vote in Mbytes for current bus usage
|
||||
* @bus_index - default bus index into the bus_ib table
|
||||
* @bus_ib - the set of unique ib requests needed for the bus calculation
|
||||
* @constraint - currently active power constraint
|
||||
|
@ -152,6 +154,8 @@ struct kgsl_pwrctrl {
|
|||
bool bus_control;
|
||||
int bus_mod;
|
||||
unsigned int bus_percent_ab;
|
||||
unsigned int bus_width;
|
||||
unsigned long bus_ab_mbytes;
|
||||
struct device *devbw;
|
||||
unsigned int bus_index[KGSL_MAX_PWRLEVELS];
|
||||
uint64_t *bus_ib;
|
||||
|
|
|
@ -715,6 +715,7 @@ int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags)
|
|||
|
||||
if (pwr->bus_mod != b) {
|
||||
pwr->bus_percent_ab = device->pwrscale.bus_profile.percent_ab;
|
||||
pwr->bus_ab_mbytes = device->pwrscale.bus_profile.ab_mbytes;
|
||||
kgsl_pwrctrl_buslevel_update(device, true);
|
||||
}
|
||||
|
||||
|
@ -797,6 +798,7 @@ int kgsl_pwrscale_init(struct device *dev, const char *governor)
|
|||
data->bus.num = out;
|
||||
data->bus.ib = &pwr->bus_ib[0];
|
||||
data->bus.index = &pwr->bus_index[0];
|
||||
data->bus.width = pwr->bus_width;
|
||||
} else
|
||||
data->bus.num = 0;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ struct devfreq_msm_adreno_tz_data {
|
|||
u64 gpu_time;
|
||||
u32 num;
|
||||
u32 max;
|
||||
u32 width;
|
||||
u32 up[MSM_ADRENO_MAX_PWRLEVELS];
|
||||
u32 down[MSM_ADRENO_MAX_PWRLEVELS];
|
||||
u32 p_up[MSM_ADRENO_MAX_PWRLEVELS];
|
||||
|
@ -61,6 +62,7 @@ struct msm_adreno_extended_profile {
|
|||
struct msm_busmon_extended_profile {
|
||||
u32 flag;
|
||||
unsigned long percent_ab;
|
||||
unsigned long ab_mbytes;
|
||||
struct devfreq_msm_adreno_tz_data *private_data;
|
||||
struct devfreq_dev_profile profile;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue