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

Commit 6c3dd985 authored by Rama Aparna Mallavarapu's avatar Rama Aparna Mallavarapu
Browse files

PM / devfreq: memlat: Add support for compute-bound logic



Currently, an entirely separate governor is used to handle compute-bound
cases.  Roll this functionality into the existing memlat governor and
allow devices to choose which logic to target by specifying different
drivers in the 'compatible' field.

Change-Id: I8dc41bf0474309c3564dec8e6c813511b8a7fc02
Signed-off-by: default avatarJonathan Avila <avilaj@codeaurora.org>
Signed-off-by: default avatarRama Aparna Mallavarapu <aparnam@codeaurora.org>
parent b0ac6a95
Loading
Loading
Loading
Loading
+34 −12
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@
#include "governor.h"
#include "governor_memlat.h"
#include <linux/perf_event.h>
#include <linux/of_device.h>

enum ev_index {
	INST_IDX,
@@ -52,6 +53,10 @@ struct cpu_grp_info {
	struct memlat_hwmon hw;
};

struct memlat_mon_spec {
	bool is_compute;
};

#define to_cpustats(cpu_grp, cpu) \
	(&cpu_grp->cpustats[cpu - cpumask_first(&cpu_grp->cpus)])
#define to_devstats(cpu_grp, cpu) \
@@ -83,6 +88,9 @@ static inline unsigned long read_event(struct event_data *event)
	unsigned long ev_count;
	u64 total, enabled, running;

	if (!event->pevent)
		return 0;

	total = perf_event_read_value(event->pevent, &enabled, &running);
	ev_count = total - event->prev_count;
	event->prev_count = total;
@@ -249,6 +257,7 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct memlat_hwmon *hw;
	struct cpu_grp_info *cpu_grp;
	const struct memlat_mon_spec *spec;
	int cpu, ret;
	u32 event_id;

@@ -282,6 +291,22 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)

	cpu_grp->event_ids[CYC_IDX] = CYC_EV;

	for_each_cpu(cpu, &cpu_grp->cpus)
		to_devstats(cpu_grp, cpu)->id = cpu;

	hw->start_hwmon = &start_hwmon;
	hw->stop_hwmon = &stop_hwmon;
	hw->get_cnt = &get_cnt;

	spec = of_device_get_match_data(dev);
	if (spec && spec->is_compute) {
		ret = register_compute(dev, hw);
		if (ret)
			pr_err("Compute Gov registration failed\n");

		return ret;
	}

	ret = of_property_read_u32(dev->of_node, "qcom,cachemiss-ev",
				   &event_id);
	if (ret) {
@@ -306,24 +331,21 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
	else
		cpu_grp->event_ids[STALL_CYC_IDX] = event_id;

	for_each_cpu(cpu, &cpu_grp->cpus)
		to_devstats(cpu_grp, cpu)->id = cpu;

	hw->start_hwmon = &start_hwmon;
	hw->stop_hwmon = &stop_hwmon;
	hw->get_cnt = &get_cnt;

	ret = register_memlat(dev, hw);
	if (ret) {
	if (ret)
		pr_err("Mem Latency Gov registration failed\n");

	return ret;
}

	return 0;
}
static const struct memlat_mon_spec spec[] = {
	[0] = { false },
	[1] = { true },
};

static const struct of_device_id memlat_match_table[] = {
	{ .compatible = "qcom,arm-memlat-mon" },
	{ .compatible = "qcom,arm-memlat-mon", .data = &spec[0] },
	{ .compatible = "qcom,arm-cpu-mon", .data = &spec[1] },
	{}
};

+77 −16
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ struct memlat_node {
static LIST_HEAD(memlat_list);
static DEFINE_MUTEX(list_lock);

static int use_cnt;
static int memlat_use_cnt;
static int compute_use_cnt;
static DEFINE_MUTEX(state_lock);

#define show_attr(name) \
@@ -232,8 +233,7 @@ static int devfreq_memlat_get_freq(struct devfreq *df,
		if (hw->core_stats[i].mem_count)
			ratio /= hw->core_stats[i].mem_count;

		if (!hw->core_stats[i].inst_count
		    || !hw->core_stats[i].freq)
		if (!hw->core_stats[i].freq)
			continue;

		trace_memlat_dev_meas(dev_name(df->dev.parent),
@@ -272,16 +272,26 @@ static int devfreq_memlat_get_freq(struct devfreq *df,
gov_attr(ratio_ceil, 1U, 10000U);
gov_attr(stall_floor, 0U, 100U);

static struct attribute *dev_attr[] = {
static struct attribute *memlat_dev_attr[] = {
	&dev_attr_ratio_ceil.attr,
	&dev_attr_stall_floor.attr,
	&dev_attr_freq_map.attr,
	NULL,
};

static struct attribute_group dev_attr_group = {
static struct attribute *compute_dev_attr[] = {
	&dev_attr_freq_map.attr,
	NULL,
};

static struct attribute_group memlat_dev_attr_group = {
	.name = "mem_latency",
	.attrs = dev_attr,
	.attrs = memlat_dev_attr,
};

static struct attribute_group compute_dev_attr_group = {
	.name = "compute",
	.attrs = compute_dev_attr,
};

#define MIN_MS	10U
@@ -330,6 +340,12 @@ static struct devfreq_governor devfreq_gov_memlat = {
	.event_handler = devfreq_memlat_ev_handler,
};

static struct devfreq_governor devfreq_gov_compute = {
	.name = "compute",
	.get_target_freq = devfreq_memlat_get_freq,
	.event_handler = devfreq_memlat_ev_handler,
};

#define NUM_COLS	2
static struct core_dev_map *init_core_dev_map(struct device *dev,
		char *prop_name)
@@ -372,20 +388,17 @@ static struct core_dev_map *init_core_dev_map(struct device *dev,
	return tbl;
}

int register_memlat(struct device *dev, struct memlat_hwmon *hw)
static struct memlat_node *register_common(struct device *dev,
					   struct memlat_hwmon *hw)
{
	int ret = 0;
	struct memlat_node *node;

	if (!hw->dev && !hw->of_node)
		return -EINVAL;
		return ERR_PTR(-EINVAL);

	node = devm_kzalloc(dev, sizeof(*node), GFP_KERNEL);
	if (!node)
		return -ENOMEM;

	node->gov = &devfreq_gov_memlat;
	node->attr_grp = &dev_attr_group;
		return ERR_PTR(-ENOMEM);

	node->ratio_ceil = 10;
	node->hw = hw;
@@ -393,20 +406,68 @@ int register_memlat(struct device *dev, struct memlat_hwmon *hw)
	hw->freq_map = init_core_dev_map(dev, "qcom,core-dev-table");
	if (!hw->freq_map) {
		dev_err(dev, "Couldn't find the core-dev freq table!\n");
		return -EINVAL;
		return ERR_PTR(-EINVAL);
	}

	mutex_lock(&list_lock);
	list_add_tail(&node->list, &memlat_list);
	mutex_unlock(&list_lock);

	return node;
}

int register_compute(struct device *dev, struct memlat_hwmon *hw)
{
	struct memlat_node *node;
	int ret = 0;

	node = register_common(dev, hw);
	if (IS_ERR(node)) {
		ret = PTR_ERR(node);
		goto out;
	}

	mutex_lock(&state_lock);
	if (!use_cnt)
	node->gov = &devfreq_gov_compute;
	node->attr_grp = &compute_dev_attr_group;

	if (!compute_use_cnt)
		ret = devfreq_add_governor(&devfreq_gov_compute);
	if (!ret)
		compute_use_cnt++;
	mutex_unlock(&state_lock);

out:
	if (!ret)
		dev_info(dev, "Compute governor registered.\n");
	else
		dev_err(dev, "Compute governor registration failed!\n");

	return ret;
}

int register_memlat(struct device *dev, struct memlat_hwmon *hw)
{
	struct memlat_node *node;
	int ret = 0;

	node = register_common(dev, hw);
	if (IS_ERR(node)) {
		ret = PTR_ERR(node);
		goto out;
	}

	mutex_lock(&state_lock);
	node->gov = &devfreq_gov_memlat;
	node->attr_grp = &memlat_dev_attr_group;

	if (!memlat_use_cnt)
		ret = devfreq_add_governor(&devfreq_gov_memlat);
	if (!ret)
		use_cnt++;
		memlat_use_cnt++;
	mutex_unlock(&state_lock);

out:
	if (!ret)
		dev_info(dev, "Memory Latency governor registered.\n");
	else
+7 −1
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ struct memlat_hwmon {

#ifdef CONFIG_DEVFREQ_GOV_MEMLAT
int register_memlat(struct device *dev, struct memlat_hwmon *hw);
int register_compute(struct device *dev, struct memlat_hwmon *hw);
int update_memlat(struct memlat_hwmon *hw);
#else
static inline int register_memlat(struct device *dev,
@@ -73,6 +74,11 @@ static inline int register_memlat(struct device *dev,
{
	return 0;
}
static inline int register_compute(struct device *dev,
				   struct memlat_hwmon *hw)
{
	return 0;
}
static inline int update_memlat(struct memlat_hwmon *hw)
{
	return 0;