Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f7e4bb44 authored by Mihir Patel's avatar Mihir Patel Committed by Matt Wagantall
Browse files

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: default avatarMihir Patel <mihirp@codeaurora.org>
parent 2f6ae135
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -83,6 +83,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.
+12 −2
Original line number Diff line number Diff line
@@ -24,6 +24,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)
@@ -60,6 +62,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;

@@ -104,8 +107,15 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
			bus_profile->flag = DEVFREQ_FLAG_SLOW_HINT;
	}

	/* 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 */
	if (bus_profile->flag) {
		norm_ab =  (unsigned int)priv->bus.ram_time /
			(unsigned int) priv->bus.total_time;
		if (norm_ab > norm_ab_max)
+9 −1
Original line number Diff line number Diff line
@@ -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;
@@ -1548,6 +1552,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,
+4 −0
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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;

Loading