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

Commit 3862a343 authored by Rohit Gupta's avatar Rohit Gupta
Browse files

PM / devfreq: memlat: Allow some events to be specified in DT



This patch introduces two new DT properties for the memlat monitor
for specifying PMU event ids for instruction and cache miss events.
This is done in order to minimize changes to driver code in case of
changes to those event ids across targets and maintain backward
compatibility. Additionally it makes it easier to specify multiple
drivers in the DT that can monitor events across multiple cache
levels using different cache miss event ids (provided they are
supported by hardware).

Change-Id: I0c464c80134e25db6304750ff7a98104ee2f0b9c
Signed-off-by: default avatarRohit Gupta <rohgup@codeaurora.org>
parent 64b7e65c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -10,11 +10,20 @@ Required properties:
- qcom,core-dev-table:		A mapping table of core frequency to a required bandwidth vote at the
				given core frequency.

Optional properties:
- qcom,cachemiss-ev:		The cache miss event that this monitor is supposed to measure.
				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.


Example:
	qcom,arm-memlat-mon {
		compatible = "qcom,arm-memlat-mon";
		qcom,cpulist = <&CPU0 &CPU1>;
		qcom,target-dev = <&memlat0>;
		qcom,cachemiss-ev = <0x2A>;
		qcom,inst-ev = <0x08>;
		qcom,core-dev-table =
			<  300000 1525>,
			<  499200 3143>,
+29 −8
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2017, 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
@@ -34,7 +34,7 @@

enum ev_index {
	INST_IDX,
	L2DM_IDX,
	CM_IDX,
	CYC_IDX,
	NUM_EVENTS
};
@@ -51,6 +51,8 @@ struct memlat_hwmon_data {
	struct event_data events[NUM_EVENTS];
	ktime_t prev_ts;
	bool init_pending;
	unsigned long cache_miss_event;
	unsigned long inst_event;
};
static DEFINE_PER_CPU(struct memlat_hwmon_data, pm_data);

@@ -111,7 +113,7 @@ static void read_perf_counters(int cpu, struct cpu_grp_info *cpu_grp)
			read_event(&hw_data->events[INST_IDX]);

	hw->core_stats[cpu_idx].mem_count =
			read_event(&hw_data->events[L2DM_IDX]);
			read_event(&hw_data->events[CM_IDX]);

	cyc_cnt = read_event(&hw_data->events[CYC_IDX]);
	hw->core_stats[cpu_idx].freq = compute_freq(hw_data, cyc_cnt);
@@ -192,19 +194,19 @@ static int set_events(struct memlat_hwmon_data *hw_data, int cpu)
	if (IS_ERR(attr))
		return PTR_ERR(attr);

	attr->config = INST_EV;
	attr->config = hw_data->inst_event;
	pevent = perf_event_create_kernel_counter(attr, cpu, NULL, NULL, NULL);
	if (IS_ERR(pevent))
		goto err_out;
	hw_data->events[INST_IDX].pevent = pevent;
	perf_event_enable(hw_data->events[INST_IDX].pevent);

	attr->config = L2DM_EV;
	attr->config = hw_data->cache_miss_event;
	pevent = perf_event_create_kernel_counter(attr, cpu, NULL, NULL, NULL);
	if (IS_ERR(pevent))
		goto err_out;
	hw_data->events[L2DM_IDX].pevent = pevent;
	perf_event_enable(hw_data->events[L2DM_IDX].pevent);
	hw_data->events[CM_IDX].pevent = pevent;
	perf_event_enable(hw_data->events[CM_IDX].pevent);

	attr->config = CYC_EV;
	pevent = perf_event_create_kernel_counter(attr, cpu, NULL, NULL, NULL);
@@ -300,6 +302,7 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
	struct memlat_hwmon *hw;
	struct cpu_grp_info *cpu_grp;
	int cpu, ret;
	u32 cachemiss_ev, inst_ev;

	cpu_grp = devm_kzalloc(dev, sizeof(*cpu_grp), GFP_KERNEL);
	if (!cpu_grp)
@@ -325,8 +328,26 @@ static int arm_memlat_mon_driver_probe(struct platform_device *pdev)
	if (!hw->core_stats)
		return -ENOMEM;

	for_each_cpu(cpu, &cpu_grp->cpus)
	ret = of_property_read_u32(dev->of_node, "qcom,cachemiss-ev",
			&cachemiss_ev);
	if (ret) {
		dev_dbg(dev, "Cache Miss event not specified. Using def:0x%x\n",
				L2DM_EV);
		cachemiss_ev = L2DM_EV;
	}

	ret = of_property_read_u32(dev->of_node, "qcom,inst-ev", &inst_ev);
	if (ret) {
		dev_dbg(dev, "Inst event not specified. Using def:0x%x\n",
				INST_EV);
		inst_ev = INST_EV;
	}

	for_each_cpu(cpu, &cpu_grp->cpus) {
		hw->core_stats[cpu - cpumask_first(&cpu_grp->cpus)].id = cpu;
		(&per_cpu(pm_data, cpu))->cache_miss_event = cachemiss_ev;
		(&per_cpu(pm_data, cpu))->inst_event = inst_ev;
	}

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