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

Commit 860aa3c7 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Add a path for dynamic AB bus votes"

parents 1a94270f 4fa91be7
Loading
Loading
Loading
Loading
+24 −8
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#include "governor.h"

unsigned long (*extern_get_bw)(void) = NULL;
unsigned long *dev_ab;
static unsigned long dev_ib;

DEFINE_MUTEX(df_lock);
static struct devfreq *df;
@@ -29,12 +31,15 @@ static int devfreq_vbif_get_freq(struct devfreq *df,
				unsigned long *freq,
				u32 *flag)
{
	if (extern_get_bw) {
		*freq = extern_get_bw();
		return 0;
	} else {
		return -ENODEV;
	/* If the IB isn't set yet, check if it should be non-zero. */
	if (!dev_ib && extern_get_bw) {
		dev_ib = extern_get_bw();
		if (dev_ab)
			*dev_ab = dev_ib / 4;
	}

	*freq = dev_ib;
	return 0;
}

/*
@@ -47,14 +52,15 @@ void devfreq_vbif_register_callback(void *p)
	extern_get_bw = p;
}


int devfreq_vbif_update_bw(void)
int devfreq_vbif_update_bw(unsigned long ib, unsigned long ab)
{
	int ret = 0;

	mutex_lock(&df_lock);
	if (df) {
		mutex_lock(&df->lock);
		dev_ib = ib;
		*dev_ab = ab;
		ret = update_devfreq(df);
		mutex_unlock(&df->lock);
	}
@@ -66,14 +72,24 @@ static int devfreq_vbif_ev_handler(struct devfreq *devfreq,
					unsigned int event, void *data)
{
	int ret;
	struct devfreq_dev_status stat;

	switch (event) {
	case DEVFREQ_GOV_START:
		mutex_lock(&df_lock);
		df = devfreq;
		if (df->profile->get_dev_status)
			ret = df->profile->get_dev_status(df->dev.parent,
					&stat);
		else
			ret = 0;
		if (ret || !stat.private_data)
			pr_warn("Device doesn't take AB votes!\n");
		else
			dev_ab = stat.private_data;
		mutex_unlock(&df_lock);

		ret = devfreq_vbif_update_bw();
		ret = devfreq_vbif_update_bw(0, 0);
		if (ret) {
			pr_err("Unable to update BW! Gov start failed!\n");
			return ret;
+3 −2
Original line number Diff line number Diff line
@@ -63,14 +63,14 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
	priv->bus.total_time += stats.total_time;
	priv->bus.gpu_time += stats.busy_time;
	priv->bus.ram_time += b.ram_time;
	priv->bus.ram_time += b.ram_wait;
	priv->bus.ram_wait += b.ram_wait;

	level = devfreq_get_freq_level(df, stats.current_frequency);

	if (priv->bus.total_time < LONG_FLOOR)
		return result;

	norm_cycles = (unsigned int)priv->bus.ram_time /
	norm_cycles = (unsigned int)(priv->bus.ram_time + priv->bus.ram_wait) /
			(unsigned int) priv->bus.total_time;
	gpu_percent = (100 * (unsigned int)priv->bus.gpu_time) /
			(unsigned int) priv->bus.total_time;
@@ -100,6 +100,7 @@ static int devfreq_gpubw_get_target(struct devfreq *df,
	priv->bus.total_time = 0;
	priv->bus.gpu_time = 0;
	priv->bus.ram_time = 0;
	priv->bus.ram_wait = 0;

	return result;
}
+37 −2
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@

#define KGSL_MAX_BUSLEVELS	20

#define DEFAULT_BUS_P 25
#define DEFAULT_BUS_DIV (100 / DEFAULT_BUS_P)

struct clk_pair {
	const char *name;
	uint map;
@@ -96,6 +99,7 @@ static struct clk_pair clks[KGSL_MAX_CLKS] = {

static unsigned int ib_votes[KGSL_MAX_BUSLEVELS];
static int last_vote_buslevel;
static int max_vote_buslevel;

static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
					int requested_state);
@@ -114,6 +118,29 @@ static unsigned int kgsl_get_bw(void)
	return ib_votes[last_vote_buslevel];
}

/**
 * _ab_buslevel_update() - Return latest msm bus AB vote
 * @pwr: Pointer to the kgsl_pwrctrl struct
 * @ab: Pointer to be updated with the calculated AB vote
 */
static void _ab_buslevel_update(struct kgsl_pwrctrl *pwr,
				unsigned long *ab)
{
	unsigned int ib = ib_votes[last_vote_buslevel];
	unsigned int max_bw = ib_votes[max_vote_buslevel];
	if (!ab)
		return;
	if (ib == 0)
		*ab = 0;
	else if (!pwr->bus_percent_ab)
		*ab = DEFAULT_BUS_P * ib / 100;
	else
		*ab = (pwr->bus_percent_ab * max_bw) / 100;

	if (*ab > ib)
		*ab = ib;
}

/**
 * _adjust_pwrlevel() - Given a requested power level do bounds checking on the
 * constraints and return the nearest possible level
@@ -167,6 +194,7 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device,
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	int cur = pwr->pwrlevels[pwr->active_pwrlevel].bus_freq;
	int buslevel = 0;
	unsigned long ab;
	if (!pwr->pcl)
		return;
	/* the bus should be ON to update the active frequency */
@@ -186,10 +214,12 @@ void kgsl_pwrctrl_buslevel_update(struct kgsl_device *device,
	}
	trace_kgsl_buslevel(device, pwr->active_pwrlevel, buslevel);
	last_vote_buslevel = buslevel;
	/* buslevel is the IB vote, update the AB */
	_ab_buslevel_update(pwr, &ab);
	/* vote for ocmem */
	msm_bus_scale_client_update_request(pwr->pcl, buslevel);
	/* ask a governor to vote on behalf of us */
	devfreq_vbif_update_bw();
	devfreq_vbif_update_bw(ib_votes[last_vote_buslevel], ab);
}
EXPORT_SYMBOL(kgsl_pwrctrl_buslevel_update);

@@ -307,6 +337,7 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device,
	 * frequency increases.
	 */
	pwr->bus_mod = 0;
	pwr->bus_percent_ab = 0;
	kgsl_pwrctrl_buslevel_update(device, true);

	pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel];
@@ -1427,11 +1458,15 @@ int kgsl_pwrctrl_init(struct kgsl_device *device)
		struct msm_bus_vectors *vector = &usecase->vectors[0];
		if (vector->dst == MSM_BUS_SLAVE_EBI_CH0 &&
				vector->ib != 0) {
			if (i < KGSL_MAX_BUSLEVELS)

			if (i < KGSL_MAX_BUSLEVELS) {
				/* Convert bytes to Mbytes. */
				ib_votes[i] =
					DIV_ROUND_UP_ULL(vector->ib, 1048576)
					- 1;
				if (ib_votes[i] > ib_votes[max_vote_buslevel])
					max_vote_buslevel = i;
			}

			for (k = 0; k < n; k++)
				if (vector->ib == pwr->bus_ib[k]) {
+2 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ struct kgsl_pwr_constraint {
 * @pm_qos_wakeup_latency - allowed CPU latency in microseconds during wakeup
 * @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_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
@@ -145,6 +146,7 @@ struct kgsl_pwrctrl {
	unsigned int pm_qos_wakeup_latency;
	bool bus_control;
	int bus_mod;
	unsigned int bus_percent_ab;
	struct device *devbw;
	unsigned int bus_index[KGSL_MAX_PWRLEVELS];
	uint64_t bus_ib[KGSL_MAX_PWRLEVELS];
+11 −8
Original line number Diff line number Diff line
@@ -26,6 +26,13 @@ static void do_devfreq_suspend(struct work_struct *work);
static void do_devfreq_resume(struct work_struct *work);
static void do_devfreq_notify(struct work_struct *work);

/*
 * These variables are used to keep the latest data
 * returned by kgsl_devfreq_get_dev_status
 */
static struct xstats last_xstats;
static struct devfreq_dev_status last_status = { .private_data = &last_xstats };

/*
 * kgsl_pwrscale_sleep - notify governor that device is going off
 * @device: The device
@@ -61,6 +68,7 @@ void kgsl_pwrscale_wake(struct kgsl_device *device)
	/* clear old stats before waking */
	memset(&device->pwrscale.accum_stats, 0,
		sizeof(device->pwrscale.accum_stats));
	memset(&last_xstats, 0, sizeof(last_xstats));

	/* and any hw activity from waking up*/
	device->ftbl->power_stats(device, &stats);
@@ -264,13 +272,6 @@ int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags)
}
EXPORT_SYMBOL(kgsl_devfreq_target);

/*
 * These variables are used to keep the latest data
 * returned by kgsl_devfreq_get_dev_status
 */
struct xstats last_xstats;
struct devfreq_dev_status last_status = { .private_data = &last_xstats };

/*
 * kgsl_devfreq_get_dev_status - devfreq_dev_profile.get_dev_status callback
 * @dev: see devfreq.h
@@ -488,8 +489,10 @@ int kgsl_busmon_target(struct device *dev, unsigned long *freq, u32 flags)
		((pwr_level->bus_freq + pwr->bus_mod) > pwr_level->bus_min))
			pwr->bus_mod--;

	if (pwr->bus_mod != b)
	if (pwr->bus_mod != b) {
		pwr->bus_percent_ab = device->pwrscale.bus_profile.percent_ab;
		kgsl_pwrctrl_buslevel_update(device, true);
	}

	mutex_unlock(&device->mutex);
	return 0;
Loading