Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp131310pxb; Fri, 15 Jan 2021 09:08:40 -0800 (PST) X-Google-Smtp-Source: ABdhPJyMaHLHMMDVfkzJni1jykDzRdffFujyjH4kLS2li5n0z25thJ4/mUyGtnB3xKTmAaiovGCo X-Received: by 2002:a05:6402:1d18:: with SMTP id dg24mr10253284edb.221.1610730520461; Fri, 15 Jan 2021 09:08:40 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1610730520; cv=none; d=google.com; s=arc-20160816; b=XMnC9jS9pE759qIaYTs20x6Ot+wdyJR3akxurvPOUyoozQ81iy5ZCWQOQy8rogDi2Y H/DyAZnc2UoObgNZC6u0+e9oXdL4sLgi3zaHpCnfCqvqrZ+rY3B9ZDrQQOg1uXWJU3Se Mtnb+fJDo4kJd9kR5BZYlSwg7vF9trnaHwxoXaR+WJF61wSvF6ZkkdYj7fS4mcfBwcc3 rp1W9FLzwa3rcWo3fXsHoarInS1mko+ra+I6pPBDNGCuyOu7ABbOzxyh94UGtLDl5hqR a97lIalh+/vXiCurPk6ZygykhQYH9D1a4ex7ymh+PU9qbiUzx2YjZnNuYYOoYEfiDiVh JLgw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=jMrpF4EozV2DG6NBrXRfzNNau1M1t8aHvXbf018l/lQ=; b=qeAesb5ds4zQRo7Z90v+y79v5ni6IkcqOcWX0kPYm+72G2oh7HJTWXjBPmlXV95P80 z7cmee32q+rgjcgnMGHpEp2qClZD/Ks3X1WA8D88p/ef1npcgG0i0gaCu2V0i3O2bjRU 8tcGUuWu167xgE0SCwD4RiWlr8qjzNUoPKQhjGQT1Pt6RRCxbPDD8XfYahb2LpFGAEep IBEeuJqVLGsVA/KfA0sONFN+sBBHjL6QnWyxJh0jML4vlCPaFcuXYMjjn/d+HaMzVil4 bOsE+Xt16nxYJBHg/JDj5sBGrshX/EYFzcGt1BKkFbQNmQcPU/tI3P15ypJ28/d77MV7 4iUA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id gb26si3575379ejc.384.2021.01.15.09.08.16; Fri, 15 Jan 2021 09:08:40 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728975AbhAORGZ (ORCPT + 99 others); Fri, 15 Jan 2021 12:06:25 -0500 Received: from foss.arm.com ([217.140.110.172]:45946 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728943AbhAORGY (ORCPT ); Fri, 15 Jan 2021 12:06:24 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id D1C78D6E; Fri, 15 Jan 2021 09:05:38 -0800 (PST) Received: from e123648.arm.com (unknown [10.57.3.129]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 0612A3F719; Fri, 15 Jan 2021 09:05:36 -0800 (PST) From: Lukasz Luba To: linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org, cw00.choi@samsung.com Cc: lukasz.luba@arm.com, myungjoo.ham@samsung.com, kyungmin.park@samsung.com Subject: [PATCH] PM / devfreq: Add sysfs attributes to simple_ondemand governor Date: Fri, 15 Jan 2021 17:05:30 +0000 Message-Id: <20210115170530.22603-1-lukasz.luba@arm.com> X-Mailer: git-send-email 2.17.1 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The simple_ondemand devfreq governor is used by quite a few devices, like GPUs, DSPs, memory controllers, etc. It implements algorithm which tries to predict the device frequency based on past statistics. There are two tunables for the algorithm: 'upthreshold' and 'downdifferential'. These tunables change the behavior of the decision, e.g. how fast to increase the frequency or how rapidly limit the frequency. These values might be different based on the application which is currently running, e.g. different behavior is needed for a game than for web browsing or clean desktop. The patch exports these two tunables so they can be adjusted based on current need. There is also a check with the allowed ranges to make sure the values are correct and safe. Signed-off-by: Lukasz Luba --- drivers/devfreq/governor_simpleondemand.c | 135 ++++++++++++++++++++++ 1 file changed, 135 insertions(+) diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c index d57b82a2b570..4b3c182e0a49 100644 --- a/drivers/devfreq/governor_simpleondemand.c +++ b/drivers/devfreq/governor_simpleondemand.c @@ -15,6 +15,7 @@ /* Default constants for DevFreq-Simple-Ondemand (DFSO) */ #define DFSO_UPTHRESHOLD (90) #define DFSO_DOWNDIFFERENCTIAL (5) +#define DFSO_MAX_VALUE (100) static int devfreq_simple_ondemand_func(struct devfreq *df, unsigned long *freq) { @@ -84,15 +85,149 @@ static int devfreq_simple_ondemand_func(struct devfreq *df, return 0; } +static ssize_t upthreshold_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct devfreq_simple_ondemand_data *data; + struct devfreq *df = to_devfreq(dev); + + if (!df->data) + return -EINVAL; + + data = df->data; + + return sprintf(buf, "%d\n", data->upthreshold); +} + +static ssize_t upthreshold_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct devfreq_simple_ondemand_data *data; + struct devfreq *df = to_devfreq(dev); + unsigned int value; + int ret; + + if (!df->data) + return -EINVAL; + + data = df->data; + + ret = kstrtouint(buf, 10, &value); + if (ret < 0) + return -EINVAL; + + mutex_lock(&df->lock); + + if (value > DFSO_MAX_VALUE || value <= data->downdifferential) { + mutex_unlock(&df->lock); + return -EINVAL; + } + + data->upthreshold = value; + mutex_unlock(&df->lock); + + return count; +} +static DEVICE_ATTR_RW(upthreshold); + +static ssize_t downdifferential_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct devfreq_simple_ondemand_data *data; + struct devfreq *df = to_devfreq(dev); + + if (!df->data) + return -EINVAL; + + data = df->data; + + return sprintf(buf, "%d\n", data->downdifferential); +} + +static ssize_t downdifferential_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct devfreq_simple_ondemand_data *data; + struct devfreq *df = to_devfreq(dev); + unsigned int value; + int ret; + + if (!df->data) + return -EINVAL; + + data = df->data; + + ret = kstrtouint(buf, 10, &value); + if (ret < 0) + return -EINVAL; + + mutex_lock(&df->lock); + + if (value > DFSO_MAX_VALUE || value >= data->upthreshold) { + mutex_unlock(&df->lock); + return -EINVAL; + } + + data->downdifferential = value; + mutex_unlock(&df->lock); + + return count; +} +static DEVICE_ATTR_RW(downdifferential); + +static void devfreq_simple_ondemand_sysfs_setup(struct devfreq *df) +{ + struct devfreq_simple_ondemand_data *data; + int ret; + + if (!df->data) { + /* The memory will be freed automatically */ + df->data = devm_kzalloc(&df->dev, + sizeof(struct devfreq_simple_ondemand_data), + GFP_KERNEL); + if (!df->data) { + dev_warn(&df->dev, "Unable to allocate memory"); + return; + } + } + + data = df->data; + + /* After new allocation setup default values, since they are used */ + if (!data->upthreshold) + data->upthreshold = DFSO_UPTHRESHOLD; + + if (!data->downdifferential) + data->downdifferential = DFSO_DOWNDIFFERENCTIAL; + + ret = sysfs_create_file(&df->dev.kobj, &dev_attr_upthreshold.attr); + if (ret < 0) + dev_warn(&df->dev, "Unable to create 'upthreshold' attr\n"); + + ret = sysfs_create_file(&df->dev.kobj, &dev_attr_downdifferential.attr); + if (ret < 0) + dev_warn(&df->dev, "Unable to create 'downdifferential' attr\n"); +} + +static void devfreq_simple_ondemand_sysfs_remove(struct devfreq *df) +{ + sysfs_remove_file(&df->dev.kobj, &dev_attr_upthreshold.attr); + sysfs_remove_file(&df->dev.kobj, &dev_attr_downdifferential.attr); +} + static int devfreq_simple_ondemand_handler(struct devfreq *devfreq, unsigned int event, void *data) { switch (event) { case DEVFREQ_GOV_START: devfreq_monitor_start(devfreq); + devfreq_simple_ondemand_sysfs_setup(devfreq); break; case DEVFREQ_GOV_STOP: + devfreq_simple_ondemand_sysfs_remove(devfreq); devfreq_monitor_stop(devfreq); break; -- 2.17.1