lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon,  9 Dec 2019 15:44:23 +0100
From:   Kamil Konieczny <k.konieczny@...sung.com>
To:     k.konieczny@...sung.com
Cc:     Bartlomiej Zolnierkiewicz <b.zolnierkie@...sung.com>,
        Chanwoo Choi <cw00.choi@...sung.com>,
        Krzysztof Kozlowski <krzk@...nel.org>,
        Kyungmin Park <kyungmin.park@...sung.com>,
        linux-kernel@...r.kernel.org, linux-pm@...r.kernel.org,
        Marek Szyprowski <m.szyprowski@...sung.com>,
        MyungJoo Ham <myungjoo.ham@...sung.com>
Subject: [PATCH 2/4] PM / devfreq: add possibility for delayed work

Current devfreq workqueue uses deferred timer. Introduce sysfs
file delayed_timer and use it for change from deferred to
delayed work. The default is to use old deferred one, which
saves power, but can miss increased demand for higher bus
frequency if timer was assigned to idle cpu.

Signed-off-by: Kamil Konieczny <k.konieczny@...sung.com>
---
 Documentation/ABI/testing/sysfs-class-devfreq | 10 ++++
 drivers/devfreq/devfreq.c                     | 46 ++++++++++++++++++-
 include/linux/devfreq.h                       |  2 +
 3 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/Documentation/ABI/testing/sysfs-class-devfreq b/Documentation/ABI/testing/sysfs-class-devfreq
index 9758eb85ade3..07bfd0df6a4a 100644
--- a/Documentation/ABI/testing/sysfs-class-devfreq
+++ b/Documentation/ABI/testing/sysfs-class-devfreq
@@ -30,6 +30,16 @@ Description:
 		target_freq when get_cur_freq() is not implemented by
 		devfreq driver.
 
+What:		/sys/class/devfreq/.../delayed_timer
+Date:		December 2019
+Contact:	Kamil Konieczny <k.konieczny@...sung.com>
+Description:
+		This ABI shows or clears timer type used by devfreq
+		workqueue. When 0, it uses default deferred timer.
+		When set to 1 devfreq will use delayed timer. Example
+		useage:
+			echo 1 > /sys/class/devfreq/.../delayed_timer
+
 What:		/sys/class/devfreq/.../target_freq
 Date:		September 2012
 Contact:	Rajagopal Venkat <rajagopal.venkat@...aro.org>
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 955949c6fc1f..c277d1770fef 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -445,7 +445,11 @@ void devfreq_monitor_start(struct devfreq *devfreq)
 	if (devfreq->governor->interrupt_driven)
 		return;
 
-	INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
+	if (devfreq->delayed_timer)
+		INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor);
+	else
+		INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
+
 	if (devfreq->profile->polling_ms)
 		queue_delayed_work(devfreq_wq, &devfreq->work,
 			msecs_to_jiffies(devfreq->profile->polling_ms));
@@ -698,6 +702,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
 	devfreq->last_status.current_frequency = profile->initial_freq;
 	devfreq->data = data;
 	devfreq->nb.notifier_call = devfreq_notifier_call;
+	devfreq->delayed_timer = false;
 
 	if (!devfreq->profile->max_state && !devfreq->profile->freq_table) {
 		mutex_unlock(&devfreq->lock);
@@ -1288,6 +1293,44 @@ static ssize_t available_governors_show(struct device *d,
 }
 static DEVICE_ATTR_RO(available_governors);
 
+static ssize_t delayed_timer_show(struct device *dev,
+				  struct device_attribute *attr, char *buf)
+{
+	int i;
+
+	i = to_devfreq(dev)->delayed_timer ? 1 : 0;
+	return sprintf(buf, "%d\n", i);
+}
+
+static ssize_t delayed_timer_store(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct devfreq *df = to_devfreq(dev);
+	bool old_timer;
+	int value, ret;
+
+	if (!df->governor)
+		return -EINVAL;
+
+	ret = kstrtoint(buf, 10, &value);
+	if (ret || (value != 1 && value != 0))
+		return -EINVAL;
+
+	mutex_lock(&df->lock);
+	old_timer = df->delayed_timer;
+	df->delayed_timer = value == 0 ? false : true;
+	mutex_unlock(&df->lock);
+
+	if (old_timer != df->delayed_timer) {
+		devfreq_monitor_stop(df);
+		devfreq_monitor_start(df);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(delayed_timer);
+
 static ssize_t cur_freq_show(struct device *dev, struct device_attribute *attr,
 			     char *buf)
 {
@@ -1513,6 +1556,7 @@ static struct attribute *devfreq_attrs[] = {
 	&dev_attr_name.attr,
 	&dev_attr_governor.attr,
 	&dev_attr_available_governors.attr,
+	&dev_attr_delayed_timer.attr,
 	&dev_attr_cur_freq.attr,
 	&dev_attr_available_frequencies.attr,
 	&dev_attr_target_freq.attr,
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index de2fdc56aa5b..761aa0a09db7 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -134,6 +134,7 @@ struct devfreq_stats {
  *		reevaluate operable frequencies. Devfreq users may use
  *		devfreq.nb to the corresponding register notifier call chain.
  * @work:	delayed work for load monitoring.
+ * @delayed_timer:	use delayed or deferred timer for workqueue.
  * @previous_freq:	previously configured frequency value.
  * @data:	Private data of the governor. The devfreq framework does not
  *		touch this.
@@ -166,6 +167,7 @@ struct devfreq {
 	char governor_name[DEVFREQ_NAME_LEN];
 	struct notifier_block nb;
 	struct delayed_work work;
+	bool delayed_timer;
 
 	unsigned long previous_freq;
 	struct devfreq_dev_status last_status;
-- 
2.24.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ