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

Commit 53a14d0c authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "PM / devfreq: memlat: Look for min stall% in addition to ratio criteria"

parents 0ff38683 eccbcb11
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@ Optional properties:
				Defaults to 0x17 if not specified.
- qcom,inst-ev:			The instruction count event that this monitor is supposed to measure.
				Defaults to 0x08 if not specified.
- qcom,stall-cycle-ev:		The stall cycle count that this monitor is supposed to measure.
				Assumes 100% stall if not specified.



Example:
@@ -24,6 +27,7 @@ Example:
		qcom,target-dev = <&memlat0>;
		qcom,cachemiss-ev = <0x2A>;
		qcom,inst-ev = <0x08>;
		qcom,stall-cycle-ev = <0xE7>;
		qcom,core-dev-table =
			<  300000 1525>,
			<  499200 3143>,
+2 −2
Original line number Diff line number Diff line
@@ -9,12 +9,12 @@ Required properties:
- compatible:		Must be "devfreq-simple-dev"
- clock-names:		Must be "devfreq_clk"
- clocks:		Must refer to the clock that's fed to the device.
- freq-tbl-khz:		A list of usable frequencies (in KHz) for the device
			clock.
Optional properties:
- polling-ms:	Polling interval for the device in milliseconds. Default: 50
- governor:	Initial governor to user for the device. Default: "performance"
- qcom,prepare-clk:	Prepare the device clock during initialization.
- freq-tbl-khz:		A list of usable frequencies (in kHz) for the device
			clock.

Example:

+27 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ enum ev_index {
	INST_IDX,
	CM_IDX,
	CYC_IDX,
	STALL_CYC_IDX,
	NUM_EVENTS
};
#define INST_EV		0x08
@@ -92,12 +93,19 @@ static void read_perf_counters(int cpu, struct cpu_grp_info *cpu_grp)
{
	struct cpu_pmu_stats *cpustats = to_cpustats(cpu_grp, cpu);
	struct dev_stats *devstats = to_devstats(cpu_grp, cpu);
	unsigned long cyc_cnt;
	unsigned long cyc_cnt, stall_cnt;

	devstats->inst_count = read_event(&cpustats->events[INST_IDX]);
	devstats->mem_count = read_event(&cpustats->events[CM_IDX]);
	cyc_cnt = read_event(&cpustats->events[CYC_IDX]);
	devstats->freq = compute_freq(cpustats, cyc_cnt);
	if (cpustats->events[STALL_CYC_IDX].pevent) {
		stall_cnt = read_event(&cpustats->events[STALL_CYC_IDX]);
		stall_cnt = min(stall_cnt, cyc_cnt);
		devstats->stall_pct = mult_frac(100, stall_cnt, cyc_cnt);
	} else {
		devstats->stall_pct = 100;
	}
}

static unsigned long get_cnt(struct memlat_hwmon *hw)
@@ -117,7 +125,10 @@ static void delete_events(struct cpu_pmu_stats *cpustats)

	for (i = 0; i < ARRAY_SIZE(cpustats->events); i++) {
		cpustats->events[i].prev_count = 0;
		if (cpustats->events[i].pevent) {
			perf_event_release_kernel(cpustats->events[i].pevent);
			cpustats->events[i].pevent = NULL;
		}
	}
}

@@ -135,6 +146,7 @@ static void stop_hwmon(struct memlat_hwmon *hw)
		devstats->inst_count = 0;
		devstats->mem_count = 0;
		devstats->freq = 0;
		devstats->stall_pct = 0;
	}
}

@@ -159,6 +171,7 @@ static int set_events(struct cpu_grp_info *cpu_grp, int cpu)
	struct perf_event *pevent;
	struct perf_event_attr *attr;
	int err, i;
	unsigned int event_id;
	struct cpu_pmu_stats *cpustats = to_cpustats(cpu_grp, cpu);

	/* Allocate an attribute for event initialization */
@@ -167,7 +180,11 @@ static int set_events(struct cpu_grp_info *cpu_grp, int cpu)
		return -ENOMEM;

	for (i = 0; i < ARRAY_SIZE(cpustats->events); i++) {
		attr->config = cpu_grp->event_ids[i];
		event_id = cpu_grp->event_ids[i];
		if (!event_id)
			continue;

		attr->config = event_id;
		pevent = perf_event_create_kernel_counter(attr, cpu, NULL,
							  NULL, NULL);
		if (IS_ERR(pevent))
@@ -282,6 +299,13 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
	}
	cpu_grp->event_ids[INST_IDX] = event_id;

	ret = of_property_read_u32(dev->of_node, "qcom,stall-cycle-ev",
				   &event_id);
	if (ret)
		dev_dbg(dev, "Stall cycle event not specified. Event ignored.\n");
	else
		cpu_grp->event_ids[STALL_CYC_IDX] = event_id;

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

+39 −21
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2014-2015, 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2015, 2017, 2019, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt) "devfreq-simple-dev: " fmt
@@ -26,6 +26,7 @@ struct dev_data {
	struct clk *clk;
	struct devfreq *df;
	struct devfreq_dev_profile profile;
	bool freq_in_khz;
};

static void find_freq(struct devfreq_dev_profile *p, unsigned long *freq,
@@ -57,7 +58,7 @@ static int dev_target(struct device *dev, unsigned long *freq, u32 flags)

	find_freq(&d->profile, freq, flags);

	rfreq = clk_round_rate(d->clk, *freq * 1000);
	rfreq = clk_round_rate(d->clk, d->freq_in_khz ? *freq * 1000 : *freq);
	if (IS_ERR_VALUE(rfreq)) {
		dev_err(dev, "devfreq: Cannot find matching frequency for %lu\n",
			*freq);
@@ -75,39 +76,30 @@ static int dev_get_cur_freq(struct device *dev, unsigned long *freq)
	f = clk_get_rate(d->clk);
	if (IS_ERR_VALUE(f))
		return f;
	*freq = f / 1000;
	*freq = d->freq_in_khz ? f / 1000 : f;
	return 0;
}

#define PROP_TBL "freq-tbl-khz"
static int devfreq_clock_probe(struct platform_device *pdev)
static int parse_freq_table(struct device *dev, struct dev_data *d)
{
	struct device *dev = &pdev->dev;
	struct dev_data *d;
	struct devfreq_dev_profile *p;
	u32 *data, poll;
	const char *gov_name;
	struct devfreq_dev_profile *p = &d->profile;
	int ret, len, i, j;
	u32 *data;
	unsigned long f;

	d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
	if (!d)
		return -ENOMEM;
	platform_set_drvdata(pdev, d);

	d->clk = devm_clk_get(dev, "devfreq_clk");
	if (IS_ERR(d->clk))
		return PTR_ERR(d->clk);

	if (!of_find_property(dev->of_node, PROP_TBL, &len))
		return -EINVAL;
	if (!of_find_property(dev->of_node, PROP_TBL, &len)) {
		if (dev_pm_opp_get_opp_count(dev) <= 0)
			return -EPROBE_DEFER;
		return 0;
	}

	d->freq_in_khz = true;
	len /= sizeof(*data);
	data = devm_kzalloc(dev, len * sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	p = &d->profile;
	p->freq_table = devm_kzalloc(dev, len * sizeof(*p->freq_table),
				     GFP_KERNEL);
	if (!p->freq_table)
@@ -134,6 +126,32 @@ static int devfreq_clock_probe(struct platform_device *pdev)
		return -EINVAL;
	}

	return 0;
}

static int devfreq_clock_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct dev_data *d;
	struct devfreq_dev_profile *p;
	u32 poll;
	const char *gov_name;
	int ret;

	d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
	if (!d)
		return -ENOMEM;
	platform_set_drvdata(pdev, d);

	d->clk = devm_clk_get(dev, "devfreq_clk");
	if (IS_ERR(d->clk))
		return PTR_ERR(d->clk);

	ret = parse_freq_table(dev, d);
	if (ret)
		return ret;

	p = &d->profile;
	p->target = dev_target;
	p->get_cur_freq = dev_get_cur_freq;
	ret = dev_get_cur_freq(dev, &p->initial_freq);
+6 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

struct memlat_node {
	unsigned int ratio_ceil;
	unsigned int stall_floor;
	bool mon_started;
	bool already_zero;
	struct list_head list;
@@ -239,9 +240,11 @@ static int devfreq_memlat_get_freq(struct devfreq *df,
					hw->core_stats[i].id,
					hw->core_stats[i].inst_count,
					hw->core_stats[i].mem_count,
					hw->core_stats[i].freq, ratio);
					hw->core_stats[i].freq,
					hw->core_stats[i].stall_pct, ratio);

		if (ratio <= node->ratio_ceil
		    && hw->core_stats[i].stall_pct >= node->stall_floor
		    && hw->core_stats[i].freq > max_freq) {
			lat_dev = i;
			max_freq = hw->core_stats[i].freq;
@@ -267,9 +270,11 @@ 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[] = {
	&dev_attr_ratio_ceil.attr,
	&dev_attr_stall_floor.attr,
	&dev_attr_freq_map.attr,
	NULL,
};
Loading