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

Commit 892d410d authored by Archana Sathyakumar's avatar Archana Sathyakumar Committed by Gerrit - the friendly Code Review server
Browse files

soc: qcom: msm-core: Remove the energy-aware driver



Future targets do not use userspace power any more. Remove
the driver altogether.

Change-Id: Ifb4f6913372e945e484d4c03d37d213c6950375c
Signed-off-by: default avatarArchana Sathyakumar <asathyak@codeaurora.org>
parent 0620a466
Loading
Loading
Loading
Loading
+0 −71
Original line number Diff line number Diff line
MSM Core Energy Aware driver

The Energy Aware driver provides per core power and temperature
information to the scheduler for it to make more power efficient
scheduling decision.

The required properties for the Energy-aware driver are:

- compatible:    "qcom,apss-core-ea"
- reg:           Physical address mapped to this device

Required nodes:
- ea@X: Parent node that has the sensor mapping for each cpu.
                 This node's phandle is provided within cpu node
                 to invoke/probe energy-aware only for available cpus.
                 There should be one such node present for each cpu.

Optional properties:
- qcom,low-hyst-temp: Degrees C below which the power numbers
                 need to be recomputed for the cores and reset
                 the threshold. If this is not present, the default
                 value is 10C.
- qcom,high-hyst-temp: Degrees C above which the power numbers
                 need to be recomputed for the cores and reset
                 the threshold. If this property is not present,
                 the default value is 5C.
- qcom,polling-interval: Interval for which the power numbers
                 need to be recomputed for the cores if there
                 is no change in threshold. If this property is not
                 present, the power is recalculated only on
                 temperature threshold notifications.
-qcom,throttling-temp: Temperature threshold for cpu frequency mitigation.
                 The value should be set same as the threshold temperature
                 in thermal module - 5 C, such that there is a bandwidth to
                 control the cores before frequency mitigation happens.

[Second level nodes]
Require properties to define per core characteristics:
- sensor:  Sensor phandle to map a particular sensor to the core.
                If this property is not present, then the core is assumed
                to be at 40C for all the power estimations. No sensor
                threshold is set. This phandle's compatible property is
                "qcom,sensor-information". This driver relies on the
                sensor-type and scaling-factor information provided in this
                phandle.

Example

qcom,msm-core@0xfc4b0000 {
	compatible = "qcom,apss-core-ea";
	reg = <0xfc4b0000 0x1000>;
	qcom,low-hyst-temp = <10>;
	qcom,high-hyst-temp = <5>;
	qcom,polling-interval = <50>;

	ea0: ea0 {
		sensor = <&sensor_information0>;
	};

	ea1: ea1 {
		sensor = <&sensor_information1>;
	};

};

CPU0: cpu@0 {
	device_type = "cpu";
	compatible = "arm,cortex-a53";
	reg = <0x0>;
	qcom,ea = <&ea0>;
};

drivers/soc/qcom/debug_core.c

deleted100644 → 0
+0 −330
Original line number Diff line number Diff line
/* 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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/debugfs.h>
#include <linux/ctype.h>
#include <linux/cpu.h>
#include "soc/qcom/msm-core.h"

#define MAX_PSTATES 50
#define NUM_OF_PENTRY 3 /* number of variables for ptable node */
#define NUM_OF_EENTRY 2 /* number of variables for enable node */

enum arg_offset {
	CPU_OFFSET,
	FREQ_OFFSET,
	POWER_OFFSET,
};

struct core_debug {
	int cpu;
	struct cpu_pstate_pwr *head;
	int enabled;
	int len;
	struct cpu_pwr_stats *ptr;
	struct cpu_pstate_pwr *driver_data;
	int driver_len;
};

static DEFINE_PER_CPU(struct core_debug, c_dgfs);
static struct cpu_pwr_stats *msm_core_data;
static struct debugfs_blob_wrapper help_msg = {
	.data =
"MSM CORE Debug-FS Support\n"
"\n"
"Hierarchy schema\n"
"/sys/kernel/debug/msm_core\n"
"  /help        - Static help text\n"
"  /ptable      - write to p-state table\n"
"  /enable      - enable the written p-state table\n"
"  /ptable_dump - Dump the debug ptable\n"
"\n"
"Usage\n"
" Input test frequency and power information in ptable:\n"
" echo \"0 300000 120\" > ptable\n"
" format: <cpu> <frequency in khz> <power>\n"
"\n"
" Enable the ptable for the cpu:\n"
" echo \"0 1\" > enable\n"
" format: <cpu> <1 to enable, 0 to disable>\n"
" Note: Writing 0 to disable will reset/clear the ptable\n"
"\n"
" Dump the entire ptable:\n"
" cat ptable\n"
" -----  CPU0 - Enabled ---------\n"
"     Freq       Power\n"
"     700000       120\n"
"-----  CPU0 - Live numbers -----\n"
"   Freq       Power\n"
"   300000      218\n"
" -----  CPU1 - Written ---------\n"
"     Freq       Power\n"
"     700000       120\n"
" Ptable dump will dump the status of the table as well\n"
" It shows:\n"
" Enabled -> for a cpu that debug ptable enabled\n"
" Written -> for a cpu that has debug ptable values written\n"
"            but not enabled\n"
"\n",

};

static void add_to_ptable(unsigned int *arg)
{
	struct core_debug *node;
	int i, cpu = arg[CPU_OFFSET];
	uint32_t freq = arg[FREQ_OFFSET];
	uint32_t power = arg[POWER_OFFSET];

	if (!cpu_possible(cpu))
		return;

	if ((freq == 0) || (power == 0)) {
		pr_warn("Incorrect power data\n");
		return;
	}

	node = &per_cpu(c_dgfs, cpu);

	if (node->len >= MAX_PSTATES) {
		pr_warn("Dropped ptable update - no space left.\n");
		return;
	}

	if (!node->head) {
		node->head = kzalloc(sizeof(struct cpu_pstate_pwr) *
				     (MAX_PSTATES + 1),
					GFP_KERNEL);
		if (!node->head)
			return;
	}

	for (i = 0; i < node->len; i++) {
		if (node->head[i].freq == freq) {
			node->head[i].power = power;
			return;
		}
	}

	/*
	 * Insert a new frequency (may need to move things around to
	 * keep in ascending order).
	 */
	for (i = MAX_PSTATES - 1; i > 0; i--) {
		if (node->head[i-1].freq > freq) {
			node->head[i].freq = node->head[i-1].freq;
			node->head[i].power = node->head[i-1].power;
		} else if (node->head[i-1].freq != 0) {
			break;
		}
	}

	if (node->len < MAX_PSTATES) {
		node->head[i].freq = freq;
		node->head[i].power = power;
		node->len++;
	}

	if (node->ptr)
		node->ptr->len = node->len;
}

static int split_ptable_args(char *line, unsigned int *arg, uint32_t n)
{
	char *args;
	int i;
	int ret = 0;

	for (i = 0; i < n; i++) {
		if (!line)
			break;
		args = strsep(&line, " ");
		ret = kstrtouint(args, 10, &arg[i]);
		if (ret)
			return ret;
	}
	return ret;
}

static ssize_t msm_core_ptable_write(struct file *file,
		const char __user *ubuf, size_t len, loff_t *offp)
{
	char *kbuf;
	int ret;
	unsigned int arg[3];

	if (len == 0)
		return 0;

	kbuf = kzalloc(len + 1, GFP_KERNEL);
	if (!kbuf)
		return -ENOMEM;

	if (copy_from_user(kbuf, ubuf, len)) {
		ret = -EFAULT;
		goto done;
	}
	kbuf[len] = '\0';
	ret = split_ptable_args(kbuf, arg, NUM_OF_PENTRY);
	if (!ret) {
		add_to_ptable(arg);
		ret = len;
	}
done:
	kfree(kbuf);
	return ret;
}

static void print_table(struct seq_file *m, struct cpu_pstate_pwr *c_n,
		int len)
{
	int i;

	seq_puts(m, "   Freq       Power\n");
	for (i = 0; i < len; i++)
		seq_printf(m, "  %d       %u\n", c_n[i].freq,
				c_n[i].power);

}

static int msm_core_ptable_read(struct seq_file *m, void *data)
{
	int cpu;
	struct core_debug *node;

	for_each_possible_cpu(cpu) {
		node = &per_cpu(c_dgfs, cpu);
		if (node->head) {
			seq_printf(m, "-----  CPU%d - %s - Debug -------\n",
			cpu, node->enabled == 1 ? "Enabled" : "Written");
			print_table(m, node->head, node->len);
		}
		if (msm_core_data[cpu].ptable) {
			seq_printf(m, "--- CPU%d - Live numbers at %ldC---\n",
			cpu, node->ptr->temp);
			print_table(m, msm_core_data[cpu].ptable,
					node->driver_len);
		}
	}
	return 0;
}

static ssize_t msm_core_enable_write(struct file *file,
		const char __user *ubuf, size_t len, loff_t *offp)
{
	char *kbuf;
	int ret;
	unsigned int arg[3];
	int cpu;

	if (len == 0)
		return 0;

	kbuf = kzalloc(len + 1, GFP_KERNEL);
	if (!kbuf)
		return -ENOMEM;

	if (copy_from_user(kbuf, ubuf, len)) {
		ret = -EFAULT;
		goto done;
	}
	kbuf[len] = '\0';
	ret = split_ptable_args(kbuf, arg, NUM_OF_EENTRY);
	if (ret)
		goto done;
	cpu = arg[CPU_OFFSET];

	if (cpu_possible(cpu)) {
		struct core_debug *node = &per_cpu(c_dgfs, cpu);

		if (arg[FREQ_OFFSET]) {
			msm_core_data[cpu].ptable = node->head;
			msm_core_data[cpu].len = node->len;
		} else {
			msm_core_data[cpu].ptable = node->driver_data;
			msm_core_data[cpu].len = node->driver_len;
			node->len = 0;
		}
		node->enabled = arg[FREQ_OFFSET];
	}
	ret = len;
	blocking_notifier_call_chain(
			get_power_update_notifier(), cpu, NULL);

done:
	kfree(kbuf);
	return ret;
}

static const struct file_operations msm_core_enable_ops = {
	.write = msm_core_enable_write,
};

static int msm_core_dump_open(struct inode *inode, struct file *file)
{
	return single_open(file, msm_core_ptable_read, inode->i_private);
}

static const struct file_operations msm_core_ptable_ops = {
	.open = msm_core_dump_open,
	.read = seq_read,
	.write = msm_core_ptable_write,
	.llseek = seq_lseek,
	.release = single_release,
};

int msm_core_debug_init(void)
{
	struct dentry *dir = NULL;
	struct dentry *file = NULL;
	int i;

	msm_core_data = get_cpu_pwr_stats();
	if (!msm_core_data)
		goto fail;

	dir = debugfs_create_dir("msm_core", NULL);
	if (IS_ERR_OR_NULL(dir))
		return PTR_ERR(dir);

	file = debugfs_create_file("enable", 0660, dir, NULL,
			&msm_core_enable_ops);
	if (IS_ERR_OR_NULL(file))
		goto fail;

	file = debugfs_create_file("ptable", 0660, dir, NULL,
			&msm_core_ptable_ops);
	if (IS_ERR_OR_NULL(file))
		goto fail;

	help_msg.size = strlen(help_msg.data);
	file = debugfs_create_blob("help", 0444, dir, &help_msg);
	if (IS_ERR_OR_NULL(file))
		goto fail;

	for (i = 0; i < num_possible_cpus(); i++) {
		per_cpu(c_dgfs, i).ptr = &msm_core_data[i];
		per_cpu(c_dgfs, i).driver_data = msm_core_data[i].ptable;
		per_cpu(c_dgfs, i).driver_len = msm_core_data[i].len;
	}
	return 0;
fail:
	debugfs_remove(dir);
	return PTR_ERR(file);
}
late_initcall(msm_core_debug_init);

drivers/soc/qcom/msm-core.c

deleted100644 → 0
+0 −902

File deleted.

Preview size limit exceeded, changes collapsed.

+0 −15
Original line number Diff line number Diff line
@@ -28,21 +28,6 @@ struct cpu {
	struct device dev;
};

struct cpu_pstate_pwr {
	unsigned int freq;
	uint32_t power;
};

struct cpu_pwr_stats {
	int cpu;
	long temp;
	struct cpu_pstate_pwr *ptable;
	bool throttling;
	int len;
};

extern struct cpu_pwr_stats *get_cpu_pwr_stats(void);

extern void boot_cpu_init(void);
extern void boot_cpu_state_init(void);

include/soc/qcom/msm-core.h

deleted100644 → 0
+0 −27
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2015,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
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __ARCH_ARM_MACH_MSM_CORE_H
#define __ARCH_ARM_MACH_MSM_CORE_H
#ifdef CONFIG_APSS_CORE_EA
void set_cpu_throttled(struct cpumask *mask, bool throttling);
struct blocking_notifier_head *get_power_update_notifier(void);
void trigger_cpu_pwr_stats_calc(void);
struct cpu_pwr_stats *get_cpu_pwr_stats(void);
#else
static inline void set_cpu_throttled(struct cpumask *mask, bool throttling) {}
struct blocking_notifier_head *get_power_update_notifier(void) {return NULL; }
static inline void trigger_cpu_pwr_stats_calc(void) {}
struct cpu_pwr_stats *get_cpu_pwr_stats(void) {return NULL; }
#endif
#endif
Loading