Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH 2/5] cpufreq:boost: Add support for software based CPU frequency boost

61 views
Skip to first unread message

Lukasz Majewski

unread,
Jun 6, 2013, 3:10:01 AM6/6/13
to
This commit adds support for software based frequency boosting.
Exynos4 SoCs (e.g. 4x12) allow setting of frequency above its normal
condition limits. This can be done for some short time.

Overclocking (boost) support came from cpufreq driver (which is platform
dependent). Hence the data structure describing it is defined at its file.

To allow support for either SW and HW (Intel) based boosting, the cpufreq
core code has been extended to support both solutions.

The main boost switch has been put at /sys/devices/system/cpu/cpufreq/boost.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
---
drivers/cpufreq/cpufreq.c | 156 ++++++++++++++++++++++++++++++++++++++++++
drivers/cpufreq/freq_table.c | 87 ++++++++++++++++++++++-
include/linux/cpufreq.h | 35 +++++++++-
3 files changed, 275 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index ca74e27..8cf9a92 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -133,6 +133,11 @@ bool have_governor_per_policy(void)
return cpufreq_driver->have_governor_per_policy;
}

+/**
+ * Global definition of cpufreq_boost structure
+ */
+struct cpufreq_boost *cpufreq_boost;
+
static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
{
struct cpufreq_policy *data;
@@ -315,6 +320,45 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/*********************************************************************
* SYSFS INTERFACE *
*********************************************************************/
+ssize_t show_boost_status(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct cpufreq_boost *boost = cpufreq_boost;
+
+ if (!boost)
+ return -ENODEV;
+
+ return sprintf(buf, "%d\n", boost->status);
+}
+
+static ssize_t store_boost_status(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ struct cpufreq_boost *boost = cpufreq_boost;
+ struct cpufreq_policy *p;
+ int ret, enable;
+
+ if (!boost)
+ return -ENODEV;
+
+ ret = sscanf(buf, "%d", &enable);
+ if (ret != 1 || enable < 0 || enable > 1)
+ return -EINVAL;
+
+ /* Adjust all policies to support boost */
+ list_for_each_entry(p, &boost->policies, boost_list)
+ if (cpufreq_boost_trigger_state(p, enable)) {
+ pr_err("Cannot %sable boost (policy 0x%p)!\n",
+ enable ? "en" : "dis", p);
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static struct global_attr global_boost = __ATTR(boost, 0644,
+ show_boost_status,
+ store_boost_status);

static struct cpufreq_governor *__find_governor(const char *str_governor)
{
@@ -761,6 +805,18 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
if (cpufreq_set_drv_attr_files(policy, cpufreq_driver->attr))
goto err_out_kobj_put;

+ if (cpufreq_driver->boost) {
+ if (sysfs_create_file(cpufreq_global_kobject,
+ &(global_boost.attr)))
+ pr_warn("could not register global boost sysfs file\n");
+ else
+ pr_debug("registered global boost sysfs file\n");
+
+ if (cpufreq_set_drv_attr_files(policy,
+ cpufreq_driver->boost->attr))
+ goto err_out_kobj_put;
+ }
+
if (cpufreq_driver->get) {
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
if (ret)
@@ -923,6 +979,8 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
init_completion(&policy->kobj_unregister);
INIT_WORK(&policy->update, handle_update);

+ cpufreq_boost_init(policy);
+
/* call driver. From then on the cpufreq must be able
* to accept all calls to ->verify and ->setpolicy for this CPU
*/
@@ -1860,6 +1918,100 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
};

/*********************************************************************
+ * BOOST *
+ *********************************************************************/
+int cpufreq_boost_trigger_state(struct cpufreq_policy *policy, int state)
+{
+ struct cpufreq_boost *boost;
+ unsigned long flags;
+ int ret = 0;
+
+ if (!policy || !policy->boost || !policy->boost->low_level_boost)
+ return -ENODEV;
+
+ boost = policy->boost;
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
+
+ if (boost->status != state) {
+ policy->boost->status = state;
+ ret = boost->low_level_boost(policy, state);
+ if (ret) {
+ pr_err("BOOST cannot %sable low level code (%d)\n",
+ state ? "en" : "dis", ret);
+ return ret;
+ }
+ }
+
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+ pr_debug("cpufreq BOOST %sabled\n", state ? "en" : "dis");
+
+ return 0;
+}
+
+/**
+ * cpufreq_boost_notifier - notifier callback for cpufreq policy change.
+ * <at> nb: struct notifier_block * with callback info.
+ * <at> event: value showing cpufreq event for which this function invoked.
+ * <at> data: callback-specific data
+ */
+static int cpufreq_boost_notifier(struct notifier_block *nb,
+ unsigned long event, void *data)
+{
+ struct cpufreq_policy *policy = data;
+
+ if (event == CPUFREQ_INCOMPATIBLE) {
+ if (!policy || !policy->boost)
+ return -ENODEV;
+
+ if (policy->boost->status == CPUFREQ_BOOST_EN) {
+ pr_info("NOTIFIER BOOST: MAX: %d e:%lu cpu: %d\n",
+ policy->max, event, policy->cpu);
+ cpufreq_boost_trigger_state(policy, 0);
+ }
+ }
+
+ return 0;
+}
+
+/* Notifier for cpufreq policy change */
+static struct notifier_block cpufreq_boost_notifier_block = {
+ .notifier_call = cpufreq_boost_notifier,
+};
+
+int cpufreq_boost_init(struct cpufreq_policy *policy)
+{
+ int ret = 0;
+
+ if (!policy)
+ return -EINVAL;
+
+ if (!cpufreq_driver->boost) {
+ pr_err("Boost mode not supported on this device\n");
+ return -ENODEV;
+ }
+
+ policy->boost = cpufreq_boost = cpufreq_driver->boost;
+
+ /* disable boost for newly created policy - as we e.g. change
+ governor */
+ policy->boost->status = CPUFREQ_BOOST_DIS;
+
+ /* register policy notifier */
+ ret = cpufreq_register_notifier(&cpufreq_boost_notifier_block,
+ CPUFREQ_POLICY_NOTIFIER);
+ if (ret) {
+ pr_err("CPUFREQ BOOST notifier not registered.\n");
+ return ret;
+ }
+ /* add policy to policies list headed at struct cpufreq_boost */
+ list_add_tail(&policy->boost_list, &cpufreq_boost->policies);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(cpufreq_boost_init);
+
+/*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER *
*********************************************************************/

@@ -1954,6 +2106,10 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
pr_debug("unregistering driver %s\n", driver->name);

subsys_interface_unregister(&cpufreq_interface);
+
+ if (cpufreq_driver->boost)
+ sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));
+
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);

write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index d7a7966..0e95524 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -3,6 +3,8 @@
*
* Copyright (C) 2002 - 2003 Dominik Brodowski
*
+ * Copyright (C) 2013 Lukasz Majewski <l.maj...@samsung.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -20,6 +22,36 @@
* FREQUENCY TABLE HELPERS *
*********************************************************************/

+/*********************************************************************
+ * BOOST FREQ HELPERS *
+ *********************************************************************/
+static int cpufreq_frequency_table_skip_boost(struct cpufreq_policy *policy,
+ unsigned int index)
+{
+ if (index == CPUFREQ_BOOST)
+ if (!policy->boost ||
+ policy->boost->status == CPUFREQ_BOOST_DIS)
+ return 1;
+
+ return 0;
+}
+
+unsigned int
+cpufreq_frequency_table_boost_max(struct cpufreq_frequency_table *freq_table)
+{
+ int index, boost_freq_max;
+
+ for (index = 0, boost_freq_max = 0;
+ freq_table[index].frequency != CPUFREQ_TABLE_END; index++)
+ if (freq_table[index].index == CPUFREQ_BOOST) {
+ if (freq_table[index].frequency > boost_freq_max)
+ boost_freq_max = freq_table[index].frequency;
+ }
+
+ return boost_freq_max;
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_boost_max);
+
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
@@ -34,6 +66,10 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,

continue;
}
+ if (cpufreq_frequency_table_skip_boost(policy,
+ table[i].index))
+ continue;
+
pr_debug("table entry %u: %u kHz, %u index\n",
i, freq, table[i].index);
if (freq < min_freq)
@@ -70,6 +106,9 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
+ if (cpufreq_frequency_table_skip_boost(policy,
+ table[i].index))
+ continue;
if ((freq >= policy->min) && (freq <= policy->max))
count++;
else if ((next_larger > freq) && (freq > policy->max))
@@ -122,6 +161,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID)
continue;
+ if (cpufreq_frequency_table_skip_boost(policy,
+ table[i].index))
+ continue;
if ((freq < policy->min) || (freq > policy->max))
continue;
switch (relation) {
@@ -167,11 +209,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);

+#define CPUFREQ_SHOW_NORMAL 0
+#define CPUFREQ_SHOW_BOOST 1
+
static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/**
* show_available_freqs - show available frequencies for the specified CPU
*/
-static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
+ int show_boost)
{
unsigned int i = 0;
unsigned int cpu = policy->cpu;
@@ -186,22 +232,59 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue;
+
+ if (show_boost) {
+ if (table[i].index != CPUFREQ_BOOST)
+ continue;
+ } else {
+ if (cpufreq_frequency_table_skip_boost(policy,
+ table[i].index))
+ continue;
+ }
+
count += sprintf(&buf[count], "%d ", table[i].frequency);
}
count += sprintf(&buf[count], "\n");

return count;
+}

+/**
+ * show_available_normal_freqs - show normal boost frequencies for
+ * the specified CPU
+ */
+static ssize_t show_available_normal_freqs(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, CPUFREQ_SHOW_NORMAL);
}

struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
.attr = { .name = "scaling_available_frequencies",
.mode = 0444,
},
- .show = show_available_freqs,
+ .show = show_available_normal_freqs,
};
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);

+/**
+ * show_available_boost_freqs - show available boost frequencies for
+ * the specified CPU
+ */
+static ssize_t show_available_boost_freqs(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, CPUFREQ_SHOW_BOOST);
+}
+
+struct freq_attr cpufreq_freq_attr_boost_available_freqs = {
+ .attr = { .name = "scaling_boost_frequencies",
+ .mode = 0444,
+ },
+ .show = show_available_boost_freqs,
+};
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_boost_available_freqs);
+
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 037d36a..1294c8c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -88,6 +88,25 @@ struct cpufreq_real_policy {
struct cpufreq_governor *governor; /* see below */
};

+#define CPUFREQ_BOOST_DIS (0)
+#define CPUFREQ_BOOST_EN (1)
+
+struct cpufreq_policy;
+struct cpufreq_boost {
+ unsigned int max_boost_freq; /* maximum value of
+ * boosted freq */
+ unsigned int max_normal_freq; /* non boost max freq */
+ int status; /* status of boost */
+
+ /* boost sysfs attributies */
+ struct freq_attr **attr;
+
+ /* low-level trigger for boost */
+ int (*low_level_boost) (struct cpufreq_policy *policy, int state);
+
+ struct list_head policies;
+};
+
struct cpufreq_policy {
/* CPUs sharing clock, require sw coordination */
cpumask_var_t cpus; /* Online CPUs only */
@@ -113,6 +132,9 @@ struct cpufreq_policy {

struct cpufreq_real_policy user_policy;

+ struct cpufreq_boost *boost;
+ struct list_head boost_list;
+
struct kobject kobj;
struct completion kobj_unregister;
};
@@ -262,6 +284,9 @@ struct cpufreq_driver {
int (*suspend) (struct cpufreq_policy *policy);
int (*resume) (struct cpufreq_policy *policy);
struct freq_attr **attr;
+
+ /* platform specific boost support code */
+ struct cpufreq_boost *boost;
};

/* flags */
@@ -277,7 +302,6 @@ struct cpufreq_driver {
int cpufreq_register_driver(struct cpufreq_driver *driver_data);
int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);

-
void cpufreq_notify_transition(struct cpufreq_policy *policy,
struct cpufreq_freqs *freqs, unsigned int state);

@@ -403,6 +427,9 @@ extern struct cpufreq_governor cpufreq_gov_conservative;
#define CPUFREQ_ENTRY_INVALID ~0
#define CPUFREQ_TABLE_END ~1

+/* Define index for boost frequency */
+#define CPUFREQ_BOOST ~2
+
struct cpufreq_frequency_table {
unsigned int index; /* any */
unsigned int frequency; /* kHz - doesn't need to be in ascending
@@ -421,11 +448,17 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int relation,
unsigned int *index);

+unsigned int
+cpufreq_frequency_table_boost_max(struct cpufreq_frequency_table *freq_table);
+int cpufreq_boost_init(struct cpufreq_policy *policy);
+
/* the following 3 funtions are for cpufreq core use only */
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);
+int cpufreq_boost_trigger_state(struct cpufreq_policy *policy, int state);

/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+extern struct freq_attr cpufreq_freq_attr_boost_available_freqs;

void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);
--
1.7.10.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Lukasz Majewski

unread,
Jun 6, 2013, 3:10:01 AM6/6/13
to
This patch series introduces support for CPU overclocking technique
called Boost.

It is a follow up of a LAB governor proposal. Boost is a LAB component:
http://thread.gmane.org/gmane.linux.kernel/1484746/match=cpufreq

Boost unifies hardware based solution (e.g. Intel Nehalem) with
software oriented one (like the one done at Exynos).
For this reason cpufreq/freq_table code has been reorganized to exclude
common code.

Important design decisions:

- Boost related code is compiled-in unconditionally. I wanted to avoid
situation when a lot of #ifdef CONFIG_CPU_FREQ_BOOST are scattered at
cpufreq code (especially cpufreq.c large file)

- Only one cpufreq_boost instance is created at cpufreq driver file.

- Boost can manage overclocking when many policies are istalled in
the system (this is a preparation for b.L)

- Boost sysfs attributies are seen only when cpufreq driver supports them.
They will not show up until either CONFIG_CPU_FREQ_BOOST or device tree
cpufreq "boost_mode" attribute is defined.

- No special spin_lock for Boost was created. The one from cpufreq was
reused.

- Low level boost trigger function (*low_level_boost function callback) is
necessary to "glue" together acpi-cpufreq boost with software based one.



Tested at: HW: Exynos 4412 3.10 linux
Compile tested x86_64 defconfig (acpi) - help with HW test
needed

Lukasz Majewski (5):
cpufreq: Define cpufreq_set_drv_attr_files() to add per CPU sysfs
attributes
cpufreq:boost: Add support for software based CPU frequency boost
cpufreq:acpi:x86: Adjust the acpi-cpufreq.c code to work with common
boost solution
cpufreq:exynos:Extend exynos cpufreq driver to support boost
cpufreq:boost:Kconfig: Enable boost support at Kconfig

drivers/cpufreq/Kconfig | 7 ++
drivers/cpufreq/acpi-cpufreq.c | 64 ++++++--------
drivers/cpufreq/cpufreq.c | 175 ++++++++++++++++++++++++++++++++++++--
drivers/cpufreq/exynos-cpufreq.c | 48 +++++++++++
drivers/cpufreq/freq_table.c | 87 ++++++++++++++++++-
include/linux/cpufreq.h | 35 +++++++-
6 files changed, 369 insertions(+), 47 deletions(-)

Lukasz Majewski

unread,
Jun 6, 2013, 3:10:02 AM6/6/13
to
The cpufreq_set_drv_attr_files() function creates sysfs file entry for
each available CPU. With it in place it is possible to add different
set of attributes without code duplication.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
---
drivers/cpufreq/cpufreq.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1b8a48e..ca74e27 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -730,12 +730,23 @@ static int cpufreq_add_dev_symlink(unsigned int cpu,
return ret;
}

+static int cpufreq_set_drv_attr_files(struct cpufreq_policy *policy,
+ struct freq_attr **drv_attr)
+{
+ while ((drv_attr) && (*drv_attr)) {
+ if (sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)))
+ return 1;
+ drv_attr++;
+ }
+
+ return 0;
+}
+
static int cpufreq_add_dev_interface(unsigned int cpu,
struct cpufreq_policy *policy,
struct device *dev)
{
struct cpufreq_policy new_policy;
- struct freq_attr **drv_attr;
unsigned long flags;
int ret = 0;
unsigned int j;
@@ -747,13 +758,9 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
return ret;

/* set up files for this cpu device */
- drv_attr = cpufreq_driver->attr;
- while ((drv_attr) && (*drv_attr)) {
- ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr));
- if (ret)
- goto err_out_kobj_put;
- drv_attr++;
- }
+ if (cpufreq_set_drv_attr_files(policy, cpufreq_driver->attr))
+ goto err_out_kobj_put;
+
if (cpufreq_driver->get) {
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
if (ret)

Lukasz Majewski

unread,
Jun 6, 2013, 3:10:02 AM6/6/13
to
Enable/disable support for BOOST. New flag - CPU_FREQ_BOOST has been
defined for that.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
---
drivers/cpufreq/Kconfig | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
index a1488f5..1007c5e 100644
--- a/drivers/cpufreq/Kconfig
+++ b/drivers/cpufreq/Kconfig
@@ -23,6 +23,13 @@ config CPU_FREQ_TABLE
config CPU_FREQ_GOV_COMMON
bool

+config CPU_FREQ_BOOST
+ bool "CPU frequency boost support"
+ help
+ Switch to enable support for frequency boost
+
+ If in doubt, say N.
+
config CPU_FREQ_STAT
tristate "CPU frequency translation statistics"
select CPU_FREQ_TABLE

Lukasz Majewski

unread,
Jun 6, 2013, 3:20:02 AM6/6/13
to
New structure - exynos_boost has been created to embrace the information
related to boost support.

The CONFIG_CPU_FREQ_BOOST flag is responsible for attaching the boost structure
to the cpufreq driver.
Setting exynos cpufreq driver .boost field to NULL, indicates that boost is
not supported.
Moreover device tree attribute "boost_mode" defines if exynos platform
support frequency overclocking (boost).

Moreover new attribute structure describing extra CPU features supported when boost
is enabled is also provided.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
---
drivers/cpufreq/exynos-cpufreq.c | 48 ++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)

diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 3197d88..0b6fdf6 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -267,6 +267,38 @@ static struct freq_attr *exynos_cpufreq_attr[] = {
NULL,
};

+/* per CPU boost attributes to be exported to sysfs */
+static struct freq_attr *exynos_cpufreq_boost_attr[] = {
+ &cpufreq_freq_attr_boost_available_freqs,
+ NULL,
+};
+
+/* low level code to enable/disable boost */
+static int
+exynos_cpufreq_boost_trigger(struct cpufreq_policy *policy, int state)
+{
+
+ if (!policy || !policy->boost)
+ return -ENODEV;
+
+ if (state) {
+ policy->boost->max_normal_freq = policy->max;
+ policy->max = policy->boost->max_boost_freq;
+ policy->cpuinfo.max_freq = policy->max;
+ } else {
+ policy->max = policy->boost->max_normal_freq;
+ policy->cpuinfo.max_freq = policy->max;
+ }
+
+ return 0;
+}
+
+static struct cpufreq_boost exynos_boost = {
+ .attr = exynos_cpufreq_boost_attr,
+ .low_level_boost = exynos_cpufreq_boost_trigger,
+ .policies = LIST_HEAD_INIT(exynos_boost.policies),
+};
+
static struct cpufreq_driver exynos_driver = {
.flags = CPUFREQ_STICKY,
.verify = exynos_verify_speed,
@@ -276,6 +308,9 @@ static struct cpufreq_driver exynos_driver = {
.exit = exynos_cpufreq_cpu_exit,
.name = "exynos_cpufreq",
.attr = exynos_cpufreq_attr,
+#ifdef CONFIG_CPU_FREQ_BOOST
+ .boost = &exynos_boost,
+#endif
#ifdef CONFIG_PM
.suspend = exynos_cpufreq_suspend,
.resume = exynos_cpufreq_resume,
@@ -359,6 +394,8 @@ static struct of_device_id exynos_cpufreq_of_match[] __initconst = {

static int __init exynos_cpufreq_probe(struct platform_device *pdev)
{
+ struct device_node *node = pdev->dev.of_node;
+
int ret = -EINVAL;

exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
@@ -390,6 +427,17 @@ static int __init exynos_cpufreq_probe(struct platform_device *pdev)
goto err_vdd_arm;
}

+ /* If boost_mode property not available - then NULL out the boost
+ pointer to indicate thst boost is not supported*/
+ if (exynos_driver.boost) {
+ if (of_property_read_bool(node, "boost_mode"))
+ exynos_boost.max_boost_freq =
+ cpufreq_frequency_table_boost_max(
+ exynos_info->freq_table);
+ else
+ exynos_driver.boost = NULL;
+ }
+
locking_frequency = exynos_getspeed(0);

register_pm_notifier(&exynos_cpufreq_nb);

Lukasz Majewski

unread,
Jun 6, 2013, 3:20:02 AM6/6/13
to
The Intel's HW based boost solution needs to cooperate with common cpufreq
boost.

For this reason the sysfs handling code (/sys/devices/system/cpu/cpufreq/boost)
has been moved to a core cpufreq.c code.

The _store_boost() function has been redesigned to be used as low_level_boost
callback.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
---
drivers/cpufreq/acpi-cpufreq.c | 64 ++++++++++++++++------------------------
1 file changed, 26 insertions(+), 38 deletions(-)

diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 11b8b4b..2c95540 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -133,20 +133,10 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
wrmsr_on_cpus(cpumask, msr_addr, msrs);
}

-static ssize_t _store_boost(const char *buf, size_t count)
+static int _store_boost(struct cpufreq_policy *policy, int val)
{
- int ret;
- unsigned long val = 0;
-
- if (!boost_supported)
- return -EINVAL;
-
- ret = kstrtoul(buf, 10, &val);
- if (ret || (val > 1))
- return -EINVAL;
-
if ((val && boost_enabled) || (!val && !boost_enabled))
- return count;
+ return 0;

get_online_cpus();

@@ -157,30 +147,31 @@ static ssize_t _store_boost(const char *buf, size_t count)
boost_enabled = val;
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");

- return count;
+ return 0;
}

-static ssize_t store_global_boost(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
+static ssize_t store_boost(const char *buf, size_t count)
{
- return _store_boost(buf, count);
-}
+ int ret;
+ unsigned long val = 0;

-static ssize_t show_global_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%u\n", boost_enabled);
-}
+ if (!boost_supported)
+ return -EINVAL;

-static struct global_attr global_boost = __ATTR(boost, 0644,
- show_global_boost,
- store_global_boost);
+ ret = kstrtoul(buf, 10, &val);
+ if (ret || (val > 1))
+ return -EINVAL;
+
+ _store_boost(NULL, (int) val);
+
+ return count;
+}

#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
size_t count)
{
- return _store_boost(buf, count);
+ return store_boost(buf, count);
}

static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
@@ -910,6 +901,11 @@ static struct freq_attr *acpi_cpufreq_attr[] = {
NULL,
};

+static struct cpufreq_boost acpi_boost = {
+ .low_level_boost = _store_boost,
+ .policies = LIST_HEAD_INIT(acpi_boost.policies),
+};
+
static struct cpufreq_driver acpi_cpufreq_driver = {
.verify = acpi_cpufreq_verify,
.target = acpi_cpufreq_target,
@@ -920,6 +916,9 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.name = "acpi-cpufreq",
.owner = THIS_MODULE,
.attr = acpi_cpufreq_attr,
+#ifdef CONFIG_CPU_FREQ_BOOST
+ .boost = &acpi_boost,
+#endif
};

static void __init acpi_cpufreq_boost_init(void)
@@ -941,22 +940,11 @@ static void __init acpi_cpufreq_boost_init(void)
register_cpu_notifier(&boost_nb);

put_online_cpus();
- } else
- global_boost.attr.mode = 0444;
-
- /* We create the boost file in any case, though for systems without
- * hardware support it will be read-only and hardwired to return 0.
- */
- if (sysfs_create_file(cpufreq_global_kobject, &(global_boost.attr)))
- pr_warn(PFX "could not register global boost sysfs file\n");
- else
- pr_debug("registered global boost sysfs file\n");
+ }
}

static void __exit acpi_cpufreq_boost_exit(void)
{
- sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));
-
if (msrs) {
unregister_cpu_notifier(&boost_nb);

Viresh Kumar

unread,
Jun 6, 2013, 4:30:01 AM6/6/13
to
On 6 June 2013 12:37, Lukasz Majewski <l.maj...@samsung.com> wrote:

> Subject: cpufreq: Define cpufreq_set_drv_attr_files() to add per CPU sysfs attributes

Its not per-cpu. We just add it for policy->cpu and other routines
actually create links.

> The cpufreq_set_drv_attr_files() function creates sysfs file entry for
> each available CPU. With it in place it is possible to add different
> set of attributes without code duplication.

Not for each available cpu but are linked to a policy->kobj and so
shows up on each policy->cpus.

> Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
> ---
> drivers/cpufreq/cpufreq.c | 23 +++++++++++++++--------
> 1 file changed, 15 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 1b8a48e..ca74e27 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -730,12 +730,23 @@ static int cpufreq_add_dev_symlink(unsigned int cpu,
> return ret;
> }
>
> +static int cpufreq_set_drv_attr_files(struct cpufreq_policy *policy,
> + struct freq_attr **drv_attr)
> +{
> + while ((drv_attr) && (*drv_attr)) {
> + if (sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)))
> + return 1;

You are changing the semantics here. We used to return error
value from sysfs_create_file() and you are returning 1.

> + drv_attr++;

If drv_attr was valid initially, then drv_attr++ can't make it NULL.
So, we don't need to check validity of drv_attr for every loop.

Lukasz Majewski

unread,
Jun 6, 2013, 5:00:01 AM6/6/13
to
Hi Viresh,

> On 6 June 2013 12:37, Lukasz Majewski <l.maj...@samsung.com> wrote:
>
> > Subject: cpufreq: Define cpufreq_set_drv_attr_files() to add per
> > CPU sysfs attributes
>
> Its not per-cpu. We just add it for policy->cpu and other routines
> actually create links.
>
> > The cpufreq_set_drv_attr_files() function creates sysfs file entry
> > for each available CPU. With it in place it is possible to add
> > different set of attributes without code duplication.
>
> Not for each available cpu but are linked to a policy->kobj and so
> shows up on each policy->cpus.

Yes, you are right here. Thanks for detailed explanation. Being
"per-cpu" comes from kobj embedded at policy, which has information
about cpus affected.

>
> > Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> > Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
> > ---
> > drivers/cpufreq/cpufreq.c | 23 +++++++++++++++--------
> > 1 file changed, 15 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> > index 1b8a48e..ca74e27 100644
> > --- a/drivers/cpufreq/cpufreq.c
> > +++ b/drivers/cpufreq/cpufreq.c
> > @@ -730,12 +730,23 @@ static int cpufreq_add_dev_symlink(unsigned
> > int cpu, return ret;
> > }
> >
> > +static int cpufreq_set_drv_attr_files(struct cpufreq_policy
> > *policy,
> > + struct freq_attr **drv_attr)
> > +{
> > + while ((drv_attr) && (*drv_attr)) {
> > + if (sysfs_create_file(&policy->kobj,
> > &((*drv_attr)->attr)))
> > + return 1;
>
> You are changing the semantics here. We used to return error
> value from sysfs_create_file() and you are returning 1.

Yes, correct. The ret from sysfs_create_file shall be returned.
Returning 1 causes information lost.

>
> > + drv_attr++;
>
> If drv_attr was valid initially, then drv_attr++ can't make it NULL.
> So, we don't need to check validity of drv_attr for every loop.

I'm confused here.

So you want to check dev_attr for NULL just after:
drv_attr = cpufreq_driver->attr;
if (!drv_attr)
goto error;

and skip the check at the while loop:
while ((drv_attr) && (*drv_attr))

to

while ((*drv_attr))

Am I correct?


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 6, 2013, 5:10:01 AM6/6/13
to
On 6 June 2013 14:28, Lukasz Majewski <l.maj...@samsung.com> wrote:
> I'm confused here.
>
> So you want to check dev_attr for NULL just after:
> drv_attr = cpufreq_driver->attr;
> if (!drv_attr)
> goto error;
>
> and skip the check at the while loop:
> while ((drv_attr) && (*drv_attr))
>
> to
>
> while ((*drv_attr))
>
> Am I correct?

Bingo!!

Lukasz Majewski

unread,
Jun 6, 2013, 5:20:02 AM6/6/13
to
Hi Viresh,

> On 6 June 2013 14:28, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > I'm confused here.
> >
> > So you want to check dev_attr for NULL just after:
> > drv_attr = cpufreq_driver->attr;
> > if (!drv_attr)
> > goto error;
> >
> > and skip the check at the while loop:
> > while ((drv_attr) && (*drv_attr))
> >
> > to
> >
> > while ((*drv_attr))
> >
> > Am I correct?
>
> Bingo!!

Ok, no problem :-)

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 6, 2013, 7:00:01 AM6/6/13
to
Hi,

On 6 June 2013 12:37, Lukasz Majewski <l.maj...@samsung.com> wrote:
> This commit adds support for software based frequency boosting.
> Exynos4 SoCs (e.g. 4x12) allow setting of frequency above its normal
> condition limits. This can be done for some short time.
>
> Overclocking (boost) support came from cpufreq driver (which is platform
> dependent). Hence the data structure describing it is defined at its file.
>
> To allow support for either SW and HW (Intel) based boosting, the cpufreq
> core code has been extended to support both solutions.
>
> The main boost switch has been put at /sys/devices/system/cpu/cpufreq/boost.

Log requires some better paragraphs but I am not concerned about it for now.

> Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
> ---
> drivers/cpufreq/cpufreq.c | 156 ++++++++++++++++++++++++++++++++++++++++++
> drivers/cpufreq/freq_table.c | 87 ++++++++++++++++++++++-
> include/linux/cpufreq.h | 35 +++++++++-
> 3 files changed, 275 insertions(+), 3 deletions(-)

My initial view on this patch is: "It is overly engineered and needs
to get simplified"

> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index ca74e27..8cf9a92 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -133,6 +133,11 @@ bool have_governor_per_policy(void)
> return cpufreq_driver->have_governor_per_policy;
> }
>
> +/**
> + * Global definition of cpufreq_boost structure
> + */
> +struct cpufreq_boost *cpufreq_boost;

Probably just a 'static bool' here cpufreq_boost_enabled. Which takes
care of selection from sysfs.

> static struct cpufreq_governor *__find_governor(const char *str_governor)
> {
> @@ -761,6 +805,18 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
> if (cpufreq_set_drv_attr_files(policy, cpufreq_driver->attr))
> goto err_out_kobj_put;
>
> + if (cpufreq_driver->boost) {
> + if (sysfs_create_file(cpufreq_global_kobject,
> + &(global_boost.attr)))

This will report error for systems where we have two policy structures.
As we are creating something already present.

> + pr_warn("could not register global boost sysfs file\n");
> + else
> + pr_debug("registered global boost sysfs file\n");

Please make all your prints to print function name too:

pr_debug("%s: foo\n", __func__, foo);

> + if (cpufreq_set_drv_attr_files(policy,
> + cpufreq_driver->boost->attr))

Why is this required? Why do we want platforms to add some files
in sysfs?
Heh, policy can't be NULL here.

> + if (!cpufreq_driver->boost) {
> + pr_err("Boost mode not supported on this device\n");

Wow!! You want to screw everybody else's logs with this message.
Its not a crime if you don't have boost mode supported :)

Actually this routine must be called only if cpufreq_driver->boost
is valid.

> + return -ENODEV;
> + }
> +
> + policy->boost = cpufreq_boost = cpufreq_driver->boost;

Why are we copying same pointer to policy->boost? Driver is
passing pointer to a single memory location, just save it globally.

> + /* disable boost for newly created policy - as we e.g. change
> + governor */
> + policy->boost->status = CPUFREQ_BOOST_DIS;

Drivers supporting boost may want boost to be enabled by default,
maybe without any sysfs calls.

> + /* register policy notifier */
> + ret = cpufreq_register_notifier(&cpufreq_boost_notifier_block,
> + CPUFREQ_POLICY_NOTIFIER);
> + if (ret) {
> + pr_err("CPUFREQ BOOST notifier not registered.\n");
> + return ret;
> + }
> + /* add policy to policies list headed at struct cpufreq_boost */
> + list_add_tail(&policy->boost_list, &cpufreq_boost->policies);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL_GPL(cpufreq_boost_init);

Why do we need to maintain a list of boost here? notifiers? complex :(

> +/*********************************************************************
> * REGISTER / UNREGISTER CPUFREQ DRIVER *
> *********************************************************************/
>
> @@ -1954,6 +2106,10 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
> pr_debug("unregistering driver %s\n", driver->name);
>
> subsys_interface_unregister(&cpufreq_interface);
> +
> + if (cpufreq_driver->boost)
> + sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));

You haven't removed this from policy. Memory leak.

> unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
>
> write_lock_irqsave(&cpufreq_driver_lock, flags);
> diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
> index d7a7966..0e95524 100644
> --- a/drivers/cpufreq/freq_table.c
> +++ b/drivers/cpufreq/freq_table.c
> @@ -3,6 +3,8 @@
> *
> * Copyright (C) 2002 - 2003 Dominik Brodowski
> *
> + * Copyright (C) 2013 Lukasz Majewski <l.maj...@samsung.com>
> + *

You shouldn't add it unless you did some major work on this file. You aren't
maintaining this file in 2013.

> +static int cpufreq_frequency_table_skip_boost(struct cpufreq_policy *policy,
> + unsigned int index)
> +{
> + if (index == CPUFREQ_BOOST)
> + if (!policy->boost ||

This shouldn't be true. If index has got CPUFREQ_BOOST, then driver
has to support boost.

> + policy->boost->status == CPUFREQ_BOOST_DIS)
> + return 1;
> +
> + return 0;
> +}
> +
> +unsigned int
> +cpufreq_frequency_table_boost_max(struct cpufreq_frequency_table *freq_table)
> +{
> + int index, boost_freq_max;
> +
> + for (index = 0, boost_freq_max = 0;
> + freq_table[index].frequency != CPUFREQ_TABLE_END; index++)
> + if (freq_table[index].index == CPUFREQ_BOOST) {
> + if (freq_table[index].frequency > boost_freq_max)
> + boost_freq_max = freq_table[index].frequency;
> + }
> +
> + return boost_freq_max;
> +}
> +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_boost_max);

why do we need this?

> /*
> * if you use these, you must assure that the frequency table is valid
> * all the time between get_attr and put_attr!
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index 037d36a..1294c8c 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -88,6 +88,25 @@ struct cpufreq_real_policy {
> struct cpufreq_governor *governor; /* see below */
> };
>
> +#define CPUFREQ_BOOST_DIS (0)
> +#define CPUFREQ_BOOST_EN (1)

You don't need these.. Just create variable as bool and 0 & 1 would
be fine.

> +struct cpufreq_policy;
> +struct cpufreq_boost {
> + unsigned int max_boost_freq; /* maximum value of
> + * boosted freq */
> + unsigned int max_normal_freq; /* non boost max freq */
> + int status; /* status of boost */
> +
> + /* boost sysfs attributies */
> + struct freq_attr **attr;
> +
> + /* low-level trigger for boost */
> + int (*low_level_boost) (struct cpufreq_policy *policy, int state);
> +
> + struct list_head policies;
> +};

We don't need it. Just add two more fields to cpufreq_driver:
- have_boost_freqs and low_level_boost (maybe a better name.
What's its use?)

> struct cpufreq_policy {
> /* CPUs sharing clock, require sw coordination */
> cpumask_var_t cpus; /* Online CPUs only */
> @@ -113,6 +132,9 @@ struct cpufreq_policy {
>
> struct cpufreq_real_policy user_policy;
>
> + struct cpufreq_boost *boost;
> + struct list_head boost_list;

We don't need both of these.

> struct kobject kobj;
> struct completion kobj_unregister;
> };

> @@ -277,7 +302,6 @@ struct cpufreq_driver {
> int cpufreq_register_driver(struct cpufreq_driver *driver_data);
> int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
>
> -

??

> void cpufreq_notify_transition(struct cpufreq_policy *policy,
> struct cpufreq_freqs *freqs, unsigned int state);
>
> @@ -403,6 +427,9 @@ extern struct cpufreq_governor cpufreq_gov_conservative;
> #define CPUFREQ_ENTRY_INVALID ~0
> #define CPUFREQ_TABLE_END ~1
>
> +/* Define index for boost frequency */
> +#define CPUFREQ_BOOST ~2

s/CPUFREQ_BOOST/CPUFREQ_BOOST_FREQ

Lukasz Majewski

unread,
Jun 6, 2013, 7:50:03 AM6/6/13
to
Hi Viresh,
The pointer to struct cpufreq_boost is needed for further reference
(as it is now done with struct cpufreq_driver pointer - *cpufreq_driver
- defined at cpufreq.c file).


>
> > static struct cpufreq_governor *__find_governor(const char
> > *str_governor) {
> > @@ -761,6 +805,18 @@ static int cpufreq_add_dev_interface(unsigned
> > int cpu, if (cpufreq_set_drv_attr_files(policy,
> > cpufreq_driver->attr)) goto err_out_kobj_put;
> >
> > + if (cpufreq_driver->boost) {
> > + if (sysfs_create_file(cpufreq_global_kobject,
> > + &(global_boost.attr)))
>
> This will report error for systems where we have two policy
> structures. As we are creating something already present.
Good point, thanks.

>
> > + pr_warn("could not register global boost
> > sysfs file\n");
> > + else
> > + pr_debug("registered global boost sysfs
> > file\n");
>
> Please make all your prints to print function name too:
>
> pr_debug("%s: foo\n", __func__, foo);

OK.

>
> > + if (cpufreq_set_drv_attr_files(policy,
> > +
> > cpufreq_driver->boost->attr))
>
> Why is this required? Why do we want platforms to add some files
> in sysfs?

There are two kinds of attributes, which are exported by boost:

1. global boost (/sys/devices/system/cpu/cpufreq/boost)

2. attributes describing cpufreq abilities when boost is available
(/sys/devices/syste/cpu/cpu0/cpufreq/):
- scaling_boost_frequencies - which will show over clocked
frequencies
- the scaling_available_frequencies will also display boosted
frequency (when boost enabled)

Information from 2. is cpufreq_driver dependent. And that information
shouldn't been displayed when boost is not available
Extra precautions :-). I will remove it.

>
> > + if (!cpufreq_driver->boost) {
> > + pr_err("Boost mode not supported on this device\n");
>
> Wow!! You want to screw everybody else's logs with this message.
> Its not a crime if you don't have boost mode supported :)

Hmm, I've exaggerated a bit here.... :)

>
> Actually this routine must be called only if cpufreq_driver->boost
> is valid.
>
> > + return -ENODEV;
> > + }
> > +
> > + policy->boost = cpufreq_boost = cpufreq_driver->boost;
>
> Why are we copying same pointer to policy->boost? Driver is
> passing pointer to a single memory location, just save it globally.

This needs some explanation.

The sysfs entry presented at [1] doesn't bring any useful information
to reuse (like *policy). For this reason the global cpufreq_boost
pointer is needed.

However to efficiently manage the boost, it is necessary to keep per
policy pointer to the only struct cpufreq_boost instance (defined at
cpufreq_driver code).

>
> > + /* disable boost for newly created policy - as we e.g.
> > change
> > + governor */
> > + policy->boost->status = CPUFREQ_BOOST_DIS;
>
> Drivers supporting boost may want boost to be enabled by default,
> maybe without any sysfs calls.

This can be done by setting the struct cpufreq_boost status field to
CPUFREQ_BOOST_EN at cpufreq driver code (when boost structure is
defined)

>
> > + /* register policy notifier */
> > + ret =
> > cpufreq_register_notifier(&cpufreq_boost_notifier_block,
> > + CPUFREQ_POLICY_NOTIFIER);
> > + if (ret) {
> > + pr_err("CPUFREQ BOOST notifier not registered.\n");
> > + return ret;
> > + }
> > + /* add policy to policies list headed at struct
> > cpufreq_boost */
> > + list_add_tail(&policy->boost_list,
> > &cpufreq_boost->policies); +
> > + return 0;
> > +}
> > +EXPORT_SYMBOL_GPL(cpufreq_boost_init);
>
> Why do we need to maintain a list of boost here? notifiers? complex :(

Notifier is needed to disable boost when policy is changed (for
example when we change from ondemand/lab to performance governor).

I wanted to avoid the situation when boost stays enabled across
different governors.

The list of in system available policies is defined to allow boost
enable/disable for all policies available (by changing for example
policy->max field).

If we decide, that we will support only one policy (as it is now at
e.g. Exynos), the list is unnecessary here.

>
> > +/*********************************************************************
> > * REGISTER / UNREGISTER CPUFREQ
> > DRIVER *
> > *********************************************************************/
> >
> > @@ -1954,6 +2106,10 @@ int cpufreq_unregister_driver(struct
> > cpufreq_driver *driver) pr_debug("unregistering driver %s\n",
> > driver->name);
> >
> > subsys_interface_unregister(&cpufreq_interface);
> > +
> > + if (cpufreq_driver->boost)
> > + sysfs_remove_file(cpufreq_global_kobject,
> > &(global_boost.attr));
>
> You haven't removed this from policy. Memory leak.

Yes, you are right.

>
> > unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
> >
> > write_lock_irqsave(&cpufreq_driver_lock, flags);
> > diff --git a/drivers/cpufreq/freq_table.c
> > b/drivers/cpufreq/freq_table.c index d7a7966..0e95524 100644
> > --- a/drivers/cpufreq/freq_table.c
> > +++ b/drivers/cpufreq/freq_table.c
> > @@ -3,6 +3,8 @@
> > *
> > * Copyright (C) 2002 - 2003 Dominik Brodowski
> > *
> > + * Copyright (C) 2013 Lukasz Majewski <l.maj...@samsung.com>
> > + *
>
> You shouldn't add it unless you did some major work on this file. You
> aren't maintaining this file in 2013.

OK, I will remove the entry.

>
> > +static int cpufreq_frequency_table_skip_boost(struct
> > cpufreq_policy *policy,
> > + unsigned int index)
> > +{
> > + if (index == CPUFREQ_BOOST)
> > + if (!policy->boost ||
>
> This shouldn't be true. If index has got CPUFREQ_BOOST, then driver
> has to support boost.

Correct me if I'm wrong here, but in my understanding the boost shall be
only supported when both CPUFREQ_BOOST index is defined in a freq_table
and boost.state = CPUFREQ_BOOST_EN is set.

Setting of CPUFREQ_BOOST shouldn't by default allow to use over
clocking frequency.
To evaluate the maximal boost frequency from the frequency table. It is
then used as a delimiter (when LAB cooperates with thermal framework).

>
> > /*
> > * if you use these, you must assure that the frequency table is
> > valid
> > * all the time between get_attr and put_attr!
> > diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> > index 037d36a..1294c8c 100644
> > --- a/include/linux/cpufreq.h
> > +++ b/include/linux/cpufreq.h
> > @@ -88,6 +88,25 @@ struct cpufreq_real_policy {
> > struct cpufreq_governor *governor; /* see below */
> > };
> >
> > +#define CPUFREQ_BOOST_DIS (0)
> > +#define CPUFREQ_BOOST_EN (1)
>
> You don't need these.. Just create variable as bool and 0 & 1 would
> be fine.

Yes, this seems to be a clearer solution.

>
> > +struct cpufreq_policy;
> > +struct cpufreq_boost {
> > + unsigned int max_boost_freq; /* maximum value of
> > + * boosted freq */
> > + unsigned int max_normal_freq; /* non boost max
> > freq */
> > + int status; /* status of boost */
> > +
> > + /* boost sysfs attributies */
> > + struct freq_attr **attr;
> > +
> > + /* low-level trigger for boost */
> > + int (*low_level_boost) (struct cpufreq_policy *policy, int
> > state); +
> > + struct list_head policies;
> > +};
>
> We don't need it. Just add two more fields to cpufreq_driver:
> - have_boost_freqs and low_level_boost (maybe a better name.
> What's its use?)

The separate struct cpufreq_boost was created to explicitly separate
boost fields from cpufreq_driver structure.

If in your opinion this structure is redundant, I can remove it and
extend cpufreq_driver structure.

>
> > struct cpufreq_policy {
> > /* CPUs sharing clock, require sw coordination */
> > cpumask_var_t cpus; /* Online CPUs only */
> > @@ -113,6 +132,9 @@ struct cpufreq_policy {
> >
> > struct cpufreq_real_policy user_policy;
> >
> > + struct cpufreq_boost *boost;
> > + struct list_head boost_list;
>
> We don't need both of these.

*boost pointer is necessary when one wants to enable/disable boost from
e.g governor code (which operates mostly on struct cpufreq_policy
*policy pointers).

The boost_list is necessary to connect policies in a list.

>
> > struct kobject kobj;
> > struct completion kobj_unregister;
> > };
>
> > @@ -277,7 +302,6 @@ struct cpufreq_driver {
> > int cpufreq_register_driver(struct cpufreq_driver *driver_data);
> > int cpufreq_unregister_driver(struct cpufreq_driver *driver_data);
> >
> > -
>
> ??
>
> > void cpufreq_notify_transition(struct cpufreq_policy *policy,
> > struct cpufreq_freqs *freqs, unsigned int state);
> >
> > @@ -403,6 +427,9 @@ extern struct cpufreq_governor
> > cpufreq_gov_conservative; #define CPUFREQ_ENTRY_INVALID ~0
> > #define CPUFREQ_TABLE_END ~1
> >
> > +/* Define index for boost frequency */
> > +#define CPUFREQ_BOOST ~2
>
> s/CPUFREQ_BOOST/CPUFREQ_BOOST_FREQ

Ok, will be changed to something more descriptive.

Thanks for thorough review :-)

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Dave Jones

unread,
Jun 6, 2013, 10:50:01 AM6/6/13
to
On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:

> +config CPU_FREQ_BOOST
> + bool "CPU frequency boost support"
> + help
> + Switch to enable support for frequency boost
> +
> + If in doubt, say N.
> +

This help text is devoid of any useful information.

On what platforms ? What's the upside/downside ? Why is it an option ?

Dave

Lukasz Majewski

unread,
Jun 6, 2013, 11:20:02 AM6/6/13
to
Hi Dave,

> On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:
>
> > +config CPU_FREQ_BOOST
> > + bool "CPU frequency boost support"
> > + help
> > + Switch to enable support for frequency boost
> > +
> > + If in doubt, say N.
> > +
>
> This help text is devoid of any useful information.
>
> On what platforms ? What's the upside/downside ? Why is it an option ?

I shall be more verbose here.

The boost option is supposed to provide one solution to control
software based (like is is done with Samsung Exynos4 SoC) and hardware
based (like Intel's Turbo Boost feature) boost.

Support for Intel's boost is already in mainline. Therefore I aimed to
extend cpufreq to also manage software based solutions (e.g. Exynos).


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Dave Jones

unread,
Jun 6, 2013, 11:30:02 AM6/6/13
to
On Thu, Jun 06, 2013 at 05:14:31PM +0200, Lukasz Majewski wrote:
> Hi Dave,
>
> > On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:
> >
> > > +config CPU_FREQ_BOOST
> > > + bool "CPU frequency boost support"
> > > + help
> > > + Switch to enable support for frequency boost
> > > +
> > > + If in doubt, say N.
> > > +
> >
> > This help text is devoid of any useful information.
> >
> > On what platforms ? What's the upside/downside ? Why is it an option ?
>
> I shall be more verbose here.
>
> The boost option is supposed to provide one solution to control
> software based (like is is done with Samsung Exynos4 SoC) and hardware
> based (like Intel's Turbo Boost feature) boost.
>
> Support for Intel's boost is already in mainline. Therefore I aimed to
> extend cpufreq to also manage software based solutions (e.g. Exynos).

Given CPUFREQ is available on more platforms than X86/ARM, this option
could also use a depends.

Dave

Viresh Kumar

unread,
Jun 6, 2013, 11:50:01 AM6/6/13
to
On 6 June 2013 17:19, Lukasz Majewski <l.maj...@samsung.com> wrote:
>> On 6 June 2013 12:37, Lukasz Majewski <l.maj...@samsung.com> wrote:

>> > cpufreq_driver->boost->attr))
>>
>> Why is this required? Why do we want platforms to add some files
>> in sysfs?
>
> There are two kinds of attributes, which are exported by boost:
>
> 1. global boost (/sys/devices/system/cpu/cpufreq/boost)
>
> 2. attributes describing cpufreq abilities when boost is available
> (/sys/devices/syste/cpu/cpu0/cpufreq/):
> - scaling_boost_frequencies - which will show over clocked
> frequencies
> - the scaling_available_frequencies will also display boosted
> frequency (when boost enabled)
>
> Information from 2. is cpufreq_driver dependent. And that information
> shouldn't been displayed when boost is not available

This is not how I wanted this to be coded. Lets keep things simple:
- Implement it in the way cpufreq_freq_attr_scaling_available_freqs
is implemented. And then drivers which need to see boost freqs
can add it in their attr.

>> > + policy->boost = cpufreq_boost = cpufreq_driver->boost;
>>
>> Why are we copying same pointer to policy->boost? Driver is
>> passing pointer to a single memory location, just save it globally.
>
> This needs some explanation.
>
> The sysfs entry presented at [1] doesn't bring any useful information
> to reuse (like *policy). For this reason the global cpufreq_boost
> pointer is needed.
>
> However to efficiently manage the boost, it is necessary to keep per
> policy pointer to the only struct cpufreq_boost instance (defined at
> cpufreq_driver code).

No we don't need to screw struct cpufreq_policy with it.
Just need two variables here:
- cpufreq_driver->boost: If driver supports boost or not.
- If above is true then a global bool variable that will say boost is
enabled from sysfs or not.

>> > + /* disable boost for newly created policy - as we e.g.
>> > change
>> > + governor */
>> > + policy->boost->status = CPUFREQ_BOOST_DIS;
>>
>> Drivers supporting boost may want boost to be enabled by default,
>> maybe without any sysfs calls.
>
> This can be done by setting the struct cpufreq_boost status field to
> CPUFREQ_BOOST_EN at cpufreq driver code (when boost structure is
> defined)

This really isn't driver dependent.. But user dependent. Maybe lets
keep it disabled and people can enable it from sysfs.

>> Why do we need to maintain a list of boost here? notifiers? complex :(
>
> Notifier is needed to disable boost when policy is changed (for
> example when we change from ondemand/lab to performance governor).
>
> I wanted to avoid the situation when boost stays enabled across
> different governors.
>
> The list of in system available policies is defined to allow boost
> enable/disable for all policies available (by changing for example
> policy->max field).
>
> If we decide, that we will support only one policy (as it is now at
> e.g. Exynos), the list is unnecessary here.

What we discussed last in your earlier patchset was:
- Keep boost feature separate from governors.
- If it is enabled, then any governor can use it (if they want).
- Lets not disable it if governor is changed. user must do it explicitly.

>> > +static int cpufreq_frequency_table_skip_boost(struct
>> > cpufreq_policy *policy,
>> > + unsigned int index)
>> > +{
>> > + if (index == CPUFREQ_BOOST)
>> > + if (!policy->boost ||
>>
>> This shouldn't be true. If index has got CPUFREQ_BOOST, then driver
>> has to support boost.
>
> Correct me if I'm wrong here, but in my understanding the boost shall be
> only supported when both CPUFREQ_BOOST index is defined in a freq_table
> and boost.state = CPUFREQ_BOOST_EN is set.
>
> Setting of CPUFREQ_BOOST shouldn't by default allow to use over
> clocking frequency.

For cpufreq core boost is enabled as soon as cpufreq_driver->boost is
true. We can have additional checks to see if there is atleast one
boost frequency but can skip this too.

>> why do we need this?
>
> To evaluate the maximal boost frequency from the frequency table. It is
> then used as a delimiter (when LAB cooperates with thermal framework).

Introduce this with LAB then.. Lets keep it as simple as possible for now.
One step at a time.

>> > +struct cpufreq_boost {
>> > + unsigned int max_boost_freq; /* maximum value of
>> > + * boosted freq */
>> > + unsigned int max_normal_freq; /* non boost max
>> > freq */
>> > + int status; /* status of boost */
>> > +
>> > + /* boost sysfs attributies */
>> > + struct freq_attr **attr;
>> > +
>> > + /* low-level trigger for boost */
>> > + int (*low_level_boost) (struct cpufreq_policy *policy, int
>> > state); +
>> > + struct list_head policies;
>> > +};
>>
>> We don't need it. Just add two more fields to cpufreq_driver:
>> - have_boost_freqs and low_level_boost (maybe a better name.
>> What's its use?)
>
> The separate struct cpufreq_boost was created to explicitly separate
> boost fields from cpufreq_driver structure.
>
> If in your opinion this structure is redundant, I can remove it and
> extend cpufreq_driver structure.

I am not against a structure (as putting related stuff in a struct is always
better), but against so many fields in it to make things complicated.

I will only keep have_boost_freqs and low_level_boost. Remove
everything else.

> *boost pointer is necessary when one wants to enable/disable boost from
> e.g governor code (which operates mostly on struct cpufreq_policy
> *policy pointers).

We don't need to do this. boost can only be disabled from userspace by
user. No intervention from governor.

Viresh Kumar

unread,
Jun 6, 2013, 11:50:02 AM6/6/13
to
On 6 June 2013 20:51, Dave Jones <da...@redhat.com> wrote:
> Given CPUFREQ is available on more platforms than X86/ARM, this option
> could also use a depends.

It should be disabled by default, so please add default n.
But we don't need a depends here as everybody is open to use
it. Its a core feature.

Borislav Petkov

unread,
Jun 6, 2013, 12:00:02 PM6/6/13
to
On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:
> Enable/disable support for BOOST. New flag - CPU_FREQ_BOOST has been
> defined for that.

What's the reason for this? Why would you want to not compile-in the
boosting code?

Also, at least on x86, even with this feature disabled, the CPU will
boost by default unless you fiddle with it through the MSRs as root.

--
Regards/Gruss,
Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

Lukasz Majewski

unread,
Jun 7, 2013, 9:30:02 AM6/7/13
to
Hi Viresh,
I would prefer to have following fields in the cpufreq_boost structure:
struct cpufreq_boost {
unsigned int max_boost_freq; /*boost max freq*/
unsigned int max_normal_freq; /*max normal freq
int (*low_level_boost) (int state);
bool boost_en; /* indicate if boost is enabled */
}

The max_{boost|normal}_freq fields will be filed at
ret = cpufreq_driver->init(policy);

Thanks to them I will avoid calling many times routine, which extracts
from freq_table maximal boost and normal frequencies.

I could define those variables in the exynos-cpufreq.c driver, but I
think, that they are more suitable to be embedded at cpufreq_boost
structure.


>
> > *boost pointer is necessary when one wants to enable/disable boost
> > from e.g governor code (which operates mostly on struct
> > cpufreq_policy *policy pointers).
>
> We don't need to do this. boost can only be disabled from userspace by
> user. No intervention from governor.



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 7, 2013, 10:20:02 AM6/7/13
to
Hi Lukasz,

On 7 June 2013 18:57, Lukasz Majewski <l.maj...@samsung.com> wrote:

I hope you agreed to all the other comments I gave as I don't see an
explicit reply below each of these. I have seen people missing these
in past, so what would be better to do is:
- either reply below each one of them and say yes or no..
- Or write once below many comments and say: All above comments
are accepted.

So, that Reviewer is assured that you haven't missed anything.

> I would prefer to have following fields in the cpufreq_boost structure:
> struct cpufreq_boost {
> unsigned int max_boost_freq; /*boost max freq*/
> unsigned int max_normal_freq; /*max normal freq
> int (*low_level_boost) (int state);
> bool boost_en; /* indicate if boost is enabled */
> }
>
> The max_{boost|normal}_freq fields will be filed at
> ret = cpufreq_driver->init(policy);
>
> Thanks to them I will avoid calling many times routine, which extracts
> from freq_table maximal boost and normal frequencies.
>
> I could define those variables in the exynos-cpufreq.c driver, but I
> think, that they are more suitable to be embedded at cpufreq_boost
> structure.

I understand that you need these variables (I will still look how you are
using them in next version). But they are per policy and driver isn't
responsible for maintaining them. If they are required then cpufreq
core must find them out and keep in struct cpufreq_policy (as they
are policy dependent)..

So, remove this structure from cpufreq_driver and embed variables
directly.

Lukasz Majewski

unread,
Jun 7, 2013, 10:40:02 AM6/7/13
to
Hi Viresh,

> Hi Lukasz,
>
> On 7 June 2013 18:57, Lukasz Majewski <l.maj...@samsung.com> wrote:
>
> I hope you agreed to all the other comments I gave as I don't see an
> explicit reply below each of these. I have seen people missing these
> in past, so what would be better to do is:
> - either reply below each one of them and say yes or no..
> - Or write once below many comments and say: All above comments
> are accepted.
>
> So, that Reviewer is assured that you haven't missed anything.
>

Thanks for reminding :-).

I've read through all the comments. I'm redesigning now the driver to
remove redundant code.


> > I would prefer to have following fields in the cpufreq_boost
> > structure: struct cpufreq_boost {
> > unsigned int max_boost_freq; /*boost max freq*/
> > unsigned int max_normal_freq; /*max normal freq
> > int (*low_level_boost) (int state);
> > bool boost_en; /* indicate if boost is enabled */
> > }
> >
> > The max_{boost|normal}_freq fields will be filed at
> > ret = cpufreq_driver->init(policy);
> >
> > Thanks to them I will avoid calling many times routine, which
> > extracts from freq_table maximal boost and normal frequencies.
> >
> > I could define those variables in the exynos-cpufreq.c driver, but I
> > think, that they are more suitable to be embedded at cpufreq_boost
> > structure.
>
> I understand that you need these variables (I will still look how you
> are using them in next version). But they are per policy and driver
> isn't responsible for maintaining them. If they are required then
> cpufreq core must find them out and keep in struct cpufreq_policy (as
> they are policy dependent)..
>
> So, remove this structure from cpufreq_driver and embed variables
> directly.

After refactoring the code. I admit, that we shall embed the struct
cpu_boost fields directly to the coufreq_driver. There is no point to
create structure with 2 fields.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 7, 2013, 10:50:02 AM6/7/13
to
Hi Viresh,

> On 6 June 2013 17:19, Lukasz Majewski <l.maj...@samsung.com> wrote:
> >> On 6 June 2013 12:37, Lukasz Majewski <l.maj...@samsung.com>
> >> wrote:
>
> >> > cpufreq_driver->boost->attr))
> >>
> >> Why is this required? Why do we want platforms to add some files
> >> in sysfs?
> >
> > There are two kinds of attributes, which are exported by boost:
> >
> > 1. global boost (/sys/devices/system/cpu/cpufreq/boost)
> >
> > 2. attributes describing cpufreq abilities when boost is available
> > (/sys/devices/syste/cpu/cpu0/cpufreq/):
> > - scaling_boost_frequencies - which will show over clocked
> > frequencies
> > - the scaling_available_frequencies will also display
> > boosted frequency (when boost enabled)
> >
> > Information from 2. is cpufreq_driver dependent. And that
> > information shouldn't been displayed when boost is not available
>
> This is not how I wanted this to be coded. Lets keep things simple:
> - Implement it in the way cpufreq_freq_attr_scaling_available_freqs
> is implemented. And then drivers which need to see boost freqs
> can add it in their attr.

I've added scaling_boost_frequencies to cpufreq_driver attr.

However, I would keep the boost attributes definition in the freq_table
file (as I've proposed in my patch).

>
> >> > + policy->boost = cpufreq_boost = cpufreq_driver->boost;
> >>
> >> Why are we copying same pointer to policy->boost? Driver is
> >> passing pointer to a single memory location, just save it globally.
> >
> > This needs some explanation.
> >
> > The sysfs entry presented at [1] doesn't bring any useful
> > information to reuse (like *policy). For this reason the global
> > cpufreq_boost pointer is needed.
> >
> > However to efficiently manage the boost, it is necessary to keep per
> > policy pointer to the only struct cpufreq_boost instance (defined at
> > cpufreq_driver code).
>
> No we don't need to screw struct cpufreq_policy with it.
> Just need two variables here:
> - cpufreq_driver->boost: If driver supports boost or not.

This will be done as above.

> - If above is true then a global bool variable that will say boost is
> enabled from sysfs or not.

One global flag will be defined at cpufreq.c to indicate if global
boost sysfs attr has been created.



>
> >> > + /* disable boost for newly created policy - as we e.g.
> >> > change
> >> > + governor */
> >> > + policy->boost->status = CPUFREQ_BOOST_DIS;
> >>
> >> Drivers supporting boost may want boost to be enabled by default,
> >> maybe without any sysfs calls.
> >
> > This can be done by setting the struct cpufreq_boost status field to
> > CPUFREQ_BOOST_EN at cpufreq driver code (when boost structure is
> > defined)
>
> This really isn't driver dependent.. But user dependent. Maybe lets
> keep it disabled and people can enable it from sysfs.

The cpufreq_driver struct will have boost_en field. This will allow
keep boost state (it is similar to global boost_enable at
acpi-cpufreq.c).

>
> >> Why do we need to maintain a list of boost here? notifiers?
> >> complex :(
> >
> > Notifier is needed to disable boost when policy is changed (for
> > example when we change from ondemand/lab to performance governor).
> >
> > I wanted to avoid the situation when boost stays enabled across
> > different governors.
> >
> > The list of in system available policies is defined to allow boost
> > enable/disable for all policies available (by changing for example
> > policy->max field).
> >
> > If we decide, that we will support only one policy (as it is now at
> > e.g. Exynos), the list is unnecessary here.
>
> What we discussed last in your earlier patchset was:
> - Keep boost feature separate from governors.
Ok.

> - If it is enabled, then any governor can use it (if they want).

Ok, lets do it in this way

> - Lets not disable it if governor is changed. user must do it
> explicitly.

Ok, agree (notifier removed).

>
> >> > +static int cpufreq_frequency_table_skip_boost(struct
> >> > cpufreq_policy *policy,
> >> > + unsigned int index)
> >> > +{
> >> > + if (index == CPUFREQ_BOOST)
> >> > + if (!policy->boost ||
> >>
> >> This shouldn't be true. If index has got CPUFREQ_BOOST, then driver
> >> has to support boost.
> >
> > Correct me if I'm wrong here, but in my understanding the boost
> > shall be only supported when both CPUFREQ_BOOST index is defined in
> > a freq_table and boost.state = CPUFREQ_BOOST_EN is set.
> >
> > Setting of CPUFREQ_BOOST shouldn't by default allow to use over
> > clocking frequency.
>
> For cpufreq core boost is enabled as soon as cpufreq_driver->boost is
> true. We can have additional checks to see if there is atleast one
> boost frequency but can skip this too.

Checks are needed to read max_normal frequency and max boost frequency
from frequency table.

In exynos cpufreq_driver->init() I will disable boost.

>
> >> why do we need this?
> >
> > To evaluate the maximal boost frequency from the frequency table.
> > It is then used as a delimiter (when LAB cooperates with thermal
> > framework).
>
> Introduce this with LAB then.. Lets keep it as simple as possible for
> now. One step at a time.

Sorry, I have LAB in back of my head. For now I'm forgetting about
it :-) [*]
As I've written at other mail. This struct will have only two fields,
so I will embed those fields at cpufreq_driver.

>
> > *boost pointer is necessary when one wants to enable/disable boost
> > from e.g governor code (which operates mostly on struct
> > cpufreq_policy *policy pointers).
>
> We don't need to do this. boost can only be disabled from userspace by
> user. No intervention from governor.

Let's got for that option (as I've promissed at [*] :-) ).

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 7, 2013, 10:50:02 AM6/7/13
to
On 7 June 2013 20:04, Lukasz Majewski <l.maj...@samsung.com> wrote:
> After refactoring the code. I admit, that we shall embed the struct
> cpu_boost fields directly to the coufreq_driver. There is no point to
> create structure with 2 fields.

Great!! I will wait for your next version.

Lukasz Majewski

unread,
Jun 10, 2013, 9:30:02 AM6/10/13
to
Hi,

> On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:
> > Enable/disable support for BOOST. New flag - CPU_FREQ_BOOST has been
> > defined for that.
>
> What's the reason for this? Why would you want to not compile-in the
> boosting code?

I think that this flag could be removed and the "boost" could be
compiled-in permanently.

Viresh, what is your opinion?

>
> Also, at least on x86, even with this feature disabled, the CPU will
> boost by default unless you fiddle with it through the MSRs as root.
>

So this is a good argument for removing this flag from Kconfig.


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 10, 2013, 9:30:02 AM6/10/13
to
On 10 June 2013 18:50, Lukasz Majewski <l.maj...@samsung.com> wrote:
> Hi,
>
>> On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:
>> > Enable/disable support for BOOST. New flag - CPU_FREQ_BOOST has been
>> > defined for that.
>>
>> What's the reason for this? Why would you want to not compile-in the
>> boosting code?
>
> I think that this flag could be removed and the "boost" could be
> compiled-in permanently.
>
> Viresh, what is your opinion?

Yes, Borislav is correct. I haven't actually reviewed these last patches as
I saw lots of issues with first one :)

Lukasz Majewski

unread,
Jun 10, 2013, 9:50:02 AM6/10/13
to
Hi Viresh,

> On 10 June 2013 18:50, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > Hi,
> >
> >> On Thu, Jun 06, 2013 at 09:07:52AM +0200, Lukasz Majewski wrote:
> >> > Enable/disable support for BOOST. New flag - CPU_FREQ_BOOST has
> >> > been defined for that.
> >>
> >> What's the reason for this? Why would you want to not compile-in
> >> the boosting code?
> >
> > I think that this flag could be removed and the "boost" could be
> > compiled-in permanently.
> >
> > Viresh, what is your opinion?
>
> Yes, Borislav is correct. I haven't actually reviewed these last
> patches as I saw lots of issues with first one :)

Ok, thanks :-)

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 11, 2013, 5:10:02 AM6/11/13
to
This commit adds support for software based frequency boosting.
Some SoC (like Exynos4 - e.g. 4x12) allow setting frequency above
its normal condition limits. Such a change shall be only done for a short
time.

Overclocking (boost) support is essentially provided by platform
dependent cpufreq driver.

This commit unifies support for SW and HW (Intel) over clocking solutions
in the core cpufreq driver. Previously the "boost" sysfs attribute was
defined at acpi driver code.
By default boost is disabled. One global attribute is available at:
/sys/devices/system/cpu/cpufreq/boost.
It only shows up when cpufreq driver supports overclocking.
Under the hood frequencies dedicated for boosting are marked with a
special flag (CPUFREQ_BOOST_FREQ) at driver's frequency table.
It is the user's concern to enable/disable overclocking with proper call to
sysfs.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

---
Changes for v2:
- Removal of cpufreq_boost structure and move its fields to cpufreq_driver
structure
- Flag to indicate if global boost attribute is already defined
- Extent the pr_{err|debbug} functions to show current function names
---
drivers/cpufreq/cpufreq.c | 69 ++++++++++++++++++++++++++++++++++++++++++
drivers/cpufreq/freq_table.c | 57 ++++++++++++++++++++++++++++++++--
include/linux/cpufreq.h | 12 ++++++++
3 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1b8a48e..98ba5f1 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -40,6 +40,7 @@
* also protects the cpufreq_cpu_data array.
*/
static struct cpufreq_driver *cpufreq_driver;
+static bool cpufreq_boost_sysfs_defined;
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */
@@ -315,6 +316,33 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/*********************************************************************
* SYSFS INTERFACE *
*********************************************************************/
+ssize_t show_boost_status(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", cpufreq_driver->boost_en);
+}
+
+static ssize_t store_boost_status(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, enable;
+
+ ret = sscanf(buf, "%d", &enable);
+ if (ret != 1 || enable < 0 || enable > 1)
+ return -EINVAL;
+
+ if (cpufreq_boost_trigger_state(enable)) {
+ pr_err("%s: Cannot %sable boost!\n", __func__,
+ enable ? "en" : "dis");
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static struct global_attr global_boost = __ATTR(boost, 0644,
+ show_boost_status,
+ store_boost_status);

static struct cpufreq_governor *__find_governor(const char *str_governor)
{
@@ -754,6 +782,17 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
goto err_out_kobj_put;
drv_attr++;
}
+ if (cpufreq_driver->low_level_boost && !cpufreq_boost_sysfs_defined) {
+ ret = sysfs_create_file(cpufreq_global_kobject,
+ &(global_boost.attr));
+ if (ret) {
+ pr_err("%s: cannot register global boost sysfs file\n",
+ __func__);
+ goto err_out_kobj_put;
+ }
+ cpufreq_boost_sysfs_defined = 1;
+ }
+
if (cpufreq_driver->get) {
ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
if (ret)
@@ -1853,6 +1892,30 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
};

/*********************************************************************
+ * BOOST *
+ *********************************************************************/
+int cpufreq_boost_trigger_state(int state)
+{
+ int ret = 0;
+
+ if (!cpufreq_driver->low_level_boost)
+ return -ENODEV;
+
+ if (cpufreq_driver->boost_en != state) {
+ ret = cpufreq_driver->low_level_boost(state);
+ if (ret) {
+ pr_err("%s: BOOST cannot %sable low level code (%d)\n",
+ __func__, state ? "en" : "dis", ret);
+ return ret;
+ }
+ }
+
+ pr_debug("%s: cpufreq BOOST %sabled\n", __func__, state ? "en" : "dis");
+
+ return 0;
+}
+
+/*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER *
*********************************************************************/

@@ -1947,6 +2010,12 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
pr_debug("unregistering driver %s\n", driver->name);

subsys_interface_unregister(&cpufreq_interface);
+
+ if (cpufreq_driver->low_level_boost && cpufreq_boost_sysfs_defined) {
+ sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));
+ cpufreq_boost_sysfs_defined = 0;
+ }
+
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);

write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index d7a7966..4e4f692 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -20,6 +20,27 @@
* FREQUENCY TABLE HELPERS *
*********************************************************************/

+unsigned int
+cpufreq_frequency_table_max(struct cpufreq_frequency_table *freq_table,
+ int boost)
+{
+ int i = 0, boost_freq_max = 0, freq_max = 0;
+
+ for (; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ if (freq_table[i].index == CPUFREQ_BOOST_FREQ) {
+ if (freq_table[i].frequency > boost_freq_max)
+ boost_freq_max = freq_table[i].frequency;
+ } else {
+ if (freq_table[i].frequency > freq_max)
+ freq_max = freq_table[i].frequency;
+ }
+ }
+
+ return boost ? boost_freq_max : freq_max;
+
+}
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_max);
+
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table)
{
@@ -171,7 +192,8 @@ static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/**
* show_available_freqs - show available frequencies for the specified CPU
*/
-static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
+ int show_boost)
{
unsigned int i = 0;
unsigned int cpu = policy->cpu;
@@ -186,22 +208,53 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue;
+ if (show_boost)
+ if (table[i].index != CPUFREQ_BOOST_FREQ)
+ continue;
+
count += sprintf(&buf[count], "%d ", table[i].frequency);
}
count += sprintf(&buf[count], "\n");

return count;
+}

+/**
+ * show_available_normal_freqs - show normal boost frequencies for
+ * the specified CPU
+ */
+static ssize_t show_available_normal_freqs(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, 0);
}

struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
.attr = { .name = "scaling_available_frequencies",
.mode = 0444,
},
- .show = show_available_freqs,
+ .show = show_available_normal_freqs,
};
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);

+/**
+ * show_available_boost_freqs - show available boost frequencies for
+ * the specified CPU
+ */
+static ssize_t show_available_boost_freqs(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, 1);
+}
+
+struct freq_attr cpufreq_freq_attr_boost_available_freqs = {
+ .attr = { .name = "scaling_boost_frequencies",
+ .mode = 0444,
+ },
+ .show = show_available_boost_freqs,
+};
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_boost_available_freqs);
+
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 037d36a..d045da2 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -262,6 +262,10 @@ struct cpufreq_driver {
int (*suspend) (struct cpufreq_policy *policy);
int (*resume) (struct cpufreq_policy *policy);
struct freq_attr **attr;
+
+ /* platform specific boost support code */
+ bool boost_en;
+ int (*low_level_boost) (int state);
};

/* flags */
@@ -403,6 +407,9 @@ extern struct cpufreq_governor cpufreq_gov_conservative;
#define CPUFREQ_ENTRY_INVALID ~0
#define CPUFREQ_TABLE_END ~1

+/* Define index for boost frequency */
+#define CPUFREQ_BOOST_FREQ ~2
+
struct cpufreq_frequency_table {
unsigned int index; /* any */
unsigned int frequency; /* kHz - doesn't need to be in ascending
@@ -421,11 +428,16 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int relation,
unsigned int *index);

+unsigned int
+cpufreq_frequency_table_max(struct cpufreq_frequency_table *freq_table, int);
+int cpufreq_boost_trigger_state(int state);
+
/* the following 3 funtions are for cpufreq core use only */
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);

/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+extern struct freq_attr cpufreq_freq_attr_boost_available_freqs;

void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);

Lukasz Majewski

unread,
Jun 11, 2013, 5:10:03 AM6/11/13
to
This patch series introduces support for CPU overclocking technique
called Boost.

It is a follow up of a LAB governor proposal. Boost is a LAB component:
http://thread.gmane.org/gmane.linux.kernel/1484746/match=cpufreq

Boost unifies hardware based solution (e.g. Intel Nehalem) with
software oriented one (like the one done at Exynos).
For this reason cpufreq/freq_table code has been reorganized to include
common code.

Important design decisions:

- Boost related code is compiled-in unconditionally and disabled by default
The cpufreq_driver is responsibile for providing low_level_boost callback

- struct cpufreq_driver has been extended with boost related fields

- Boost sysfs attributies are seen only when cpufreq driver supports them.
They will not show up until either cpufreq_driver defines low_level_boost
callback or device tree's cpufreq "boost_mode" attribute is defined.

- No special spin_lock for Boost was created. The one from cpufreq_driver
was reused.

- Low level boost trigger function (*low_level_boost function callback) is
necessary to "glue" together acpi-cpufreq boost with software based one.



Tested at: HW:
Exynos 4412 3.10 linux
Exynos 4210 3.10 linux
Compile tested x86_64 defconfig (acpi) - help with HW (Intel Nehalem) test
needed


Two patches were abandoned (comparing to v1):
[PATCH 1/5] cpufreq: Define cpufreq_set_drv_attr_files() to add per CPU sysfs attributes
[PATCH 5/5] cpufreq:boost:Kconfig: Enable boost support at Kconfig

For detailed changelog please look into relevant patches

Lukasz Majewski (3):
cpufreq:boost: CPU frequency boost code unification for software and
hardware solutions
cpufreq:acpi:x86: Adjust the acpi-cpufreq.c code to work with common
boost solution
cpufreq:exynos:Extend Exynos cpufreq driver to support boost
framework

drivers/cpufreq/acpi-cpufreq.c | 72 ++++++++++++++------------------------
drivers/cpufreq/cpufreq.c | 69 ++++++++++++++++++++++++++++++++++++
drivers/cpufreq/exynos-cpufreq.c | 49 ++++++++++++++++++++++++--
drivers/cpufreq/freq_table.c | 57 ++++++++++++++++++++++++++++--
include/linux/cpufreq.h | 12 +++++++
5 files changed, 209 insertions(+), 50 deletions(-)

Lukasz Majewski

unread,
Jun 11, 2013, 5:10:03 AM6/11/13
to
The Intel's hardware based boost solution driver has been changed to cooperate with
common cpufreq boost framework.

The global sysfs boost attribute entry code (/sys/devices/system/cpu/cpufreq/boost)
has been moved to a core cpufreq code. This attribute is now only visible,
when cpufreq driver supports it.
Global flags (boost_enabled and boost_supported) were replaced with boost_en
flag and low_level_boost pointer presence at cpufreq driver structure.

The _store_boost() function has been redesigned to be used as low_level_boost
callback.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

---
Changes for v2:
- Replace boost_enabled and boost_supported global flags with proper entries
at struct cpufreq_driver.
- Removal of struct cpufreq_boost
---
drivers/cpufreq/acpi-cpufreq.c | 72 +++++++++++++++-------------------------
1 file changed, 26 insertions(+), 46 deletions(-)

diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 11b8b4b..a15c999 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -80,7 +80,6 @@ static struct acpi_processor_performance __percpu *acpi_perf_data;
static struct cpufreq_driver acpi_cpufreq_driver;

static unsigned int acpi_pstate_strict;
-static bool boost_enabled, boost_supported;
static struct msr __percpu *msrs;

static bool boost_state(unsigned int cpu)
@@ -133,20 +132,11 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
wrmsr_on_cpus(cpumask, msr_addr, msrs);
}

-static ssize_t _store_boost(const char *buf, size_t count)
+static int _store_boost(int val)
{
- int ret;
- unsigned long val = 0;
-
- if (!boost_supported)
- return -EINVAL;
-
- ret = kstrtoul(buf, 10, &val);
- if (ret || (val > 1))
- return -EINVAL;
-
- if ((val && boost_enabled) || (!val && !boost_enabled))
- return count;
+ if ((val && acpi_cpufreq_driver.boost_en) ||
+ (!val && !acpi_cpufreq_driver.boost_en))
+ return 0;

get_online_cpus();

@@ -154,38 +144,39 @@ static ssize_t _store_boost(const char *buf, size_t count)

put_online_cpus();

- boost_enabled = val;
+ acpi_cpufreq_driver.boost_en = val;
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");

- return count;
+ return 0;
}

-static ssize_t store_global_boost(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
+static ssize_t store_boost(const char *buf, size_t count)
{
- return _store_boost(buf, count);
-}
+ int ret;
+ unsigned long val = 0;

-static ssize_t show_global_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%u\n", boost_enabled);
-}
+ if (!acpi_cpufreq_driver.low_level_boost)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret || (val > 1))
+ return -EINVAL;

-static struct global_attr global_boost = __ATTR(boost, 0644,
- show_global_boost,
- store_global_boost);
+ _store_boost((int) val);
+
+ return count;
+}

#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
size_t count)
{
- return _store_boost(buf, count);
+ return store_boost(buf, count);
}

static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
{
- return sprintf(buf, "%u\n", boost_enabled);
+ return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_en);
}

static struct freq_attr cpb = __ATTR(cpb, 0644, show_cpb, store_cpb);
@@ -571,7 +562,7 @@ static int boost_notify(struct notifier_block *nb, unsigned long action,
switch (action) {
case CPU_UP_PREPARE:
case CPU_UP_PREPARE_FROZEN:
- boost_set_msrs(boost_enabled, cpumask);
+ boost_set_msrs(acpi_cpufreq_driver.boost_en, cpumask);
break;

case CPU_DOWN_PREPARE:
@@ -930,33 +921,22 @@ static void __init acpi_cpufreq_boost_init(void)
if (!msrs)
return;

- boost_supported = true;
- boost_enabled = boost_state(0);
+ acpi_cpufreq_driver.low_level_boost = &_store_boost;
+ acpi_cpufreq_driver.boost_en = boost_state(0);

get_online_cpus();

/* Force all MSRs to the same value */
- boost_set_msrs(boost_enabled, cpu_online_mask);
+ boost_set_msrs(acpi_cpufreq_driver.boost_en, cpu_online_mask);

register_cpu_notifier(&boost_nb);

put_online_cpus();
- } else
- global_boost.attr.mode = 0444;
-
- /* We create the boost file in any case, though for systems without
- * hardware support it will be read-only and hardwired to return 0.
- */
- if (sysfs_create_file(cpufreq_global_kobject, &(global_boost.attr)))
- pr_warn(PFX "could not register global boost sysfs file\n");
- else
- pr_debug("registered global boost sysfs file\n");
+ }
}

static void __exit acpi_cpufreq_boost_exit(void)
{
- sysfs_remove_file(cpufreq_global_kobject, &(global_boost.attr));
-
if (msrs) {
unregister_cpu_notifier(&boost_nb);

Lukasz Majewski

unread,
Jun 11, 2013, 5:10:03 AM6/11/13
to
The struct cpufreq_driver has been extended to embrace the information
related to boost support.

When "boost_mode" device tree attribute is defined for a platform, the
low_level_boost pointer is filled with proper address. The
.low_level_boost field filled to NULL, indicates that boost is not
supported.

Operations of exynos_cpufreq_boost_trigger() function are protected with
"local" mutex.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

---
Changes for v2:
- Removal of struct cpufreq_boost
- Removal of the CONFIG_CPU_FREQ_BOOST flag
- low_level_boost with valid address when boost is supported
---
drivers/cpufreq/exynos-cpufreq.c | 49 ++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 3197d88..8cf5636 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -33,6 +33,7 @@ static struct cpufreq_freqs freqs;
static unsigned int locking_frequency;
static bool frequency_locked;
static DEFINE_MUTEX(cpufreq_lock);
+static struct cpufreq_cpuinfo *cpufreq_cpu_info;

static int exynos_verify_speed(struct cpufreq_policy *policy)
{
@@ -154,6 +155,7 @@ out:
return ret;
}

+static struct cpufreq_driver exynos_driver;
static int exynos_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
@@ -244,6 +246,9 @@ static struct notifier_block exynos_cpufreq_nb = {

static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
+ unsigned int max_freq;
+ int ret;
+
policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);

cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
@@ -253,7 +258,19 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)

cpumask_setall(policy->cpus);

- return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ if (ret)
+ return ret;
+
+ if (exynos_driver.low_level_boost) {
+ /* disable boost by default */
+ max_freq = cpufreq_frequency_table_max(exynos_info->freq_table,
+ 0);
+ policy->cpuinfo.max_freq = policy->max = max_freq;
+ cpufreq_cpu_info = &policy->cpuinfo;
+ }
+
+ return 0;
}

static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
@@ -264,9 +281,32 @@ static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)

static struct freq_attr *exynos_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
+ &cpufreq_freq_attr_boost_available_freqs,
NULL,
};

+static int exynos_cpufreq_boost_trigger(int state)
+{
+ struct cpufreq_policy *policy = container_of(cpufreq_cpu_info,
+ struct cpufreq_policy,
+ cpuinfo);
+ unsigned int max_freq;
+
+ mutex_lock(&cpufreq_lock);
+ exynos_driver.boost_en = state;
+
+ /* Recalculate maximal frequency */
+ max_freq = cpufreq_frequency_table_max(exynos_info->freq_table,
+ exynos_driver.boost_en);
+
+ if (policy->max != max_freq)
+ policy->cpuinfo.max_freq = policy->max = max_freq;
+
+ mutex_unlock(&cpufreq_lock);
+
+ return 0;
+}
+
static struct cpufreq_driver exynos_driver = {
.flags = CPUFREQ_STICKY,
.verify = exynos_verify_speed,
@@ -275,7 +315,7 @@ static struct cpufreq_driver exynos_driver = {
.init = exynos_cpufreq_cpu_init,
.exit = exynos_cpufreq_cpu_exit,
.name = "exynos_cpufreq",
- .attr = exynos_cpufreq_attr,
+ .attr = exynos_cpufreq_attr,
#ifdef CONFIG_PM
.suspend = exynos_cpufreq_suspend,
.resume = exynos_cpufreq_resume,
@@ -359,6 +399,8 @@ static struct of_device_id exynos_cpufreq_of_match[] __initconst = {

static int __init exynos_cpufreq_probe(struct platform_device *pdev)
{
+ struct device_node *node = pdev->dev.of_node;
+
int ret = -EINVAL;

exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
@@ -391,6 +433,9 @@ static int __init exynos_cpufreq_probe(struct platform_device *pdev)
}

locking_frequency = exynos_getspeed(0);
+ if (of_property_read_bool(node, "boost_mode"))
+ exynos_driver.low_level_boost =
+ &exynos_cpufreq_boost_trigger;

register_pm_notifier(&exynos_cpufreq_nb);

Viresh Kumar

unread,
Jun 12, 2013, 1:20:03 AM6/12/13
to
On 11 June 2013 14:33, Lukasz Majewski <l.maj...@samsung.com> wrote:
> This patch series introduces support for CPU overclocking technique
> called Boost.
>
> It is a follow up of a LAB governor proposal. Boost is a LAB component:
> http://thread.gmane.org/gmane.linux.kernel/1484746/match=cpufreq
>
> Boost unifies hardware based solution (e.g. Intel Nehalem) with
> software oriented one (like the one done at Exynos).
> For this reason cpufreq/freq_table code has been reorganized to include
> common code.

To be honest, I haven't given a review to patches 2/3 and 3/3 as I am
concerned more about 1/3.

Maybe you can just send v3 of 1/3. 2/3 and 3/3 can be sent when we have
finalized 2/3 and 3/3 's version.

Viresh Kumar

unread,
Jun 12, 2013, 1:20:03 AM6/12/13
to
Hi,

Change subject to: "cpufreq: Add boost frequency support in core"

On 11 June 2013 14:33, Lukasz Majewski <l.maj...@samsung.com> wrote:
> This commit adds support for software based frequency boosting.

No. It adds support for both software and hardware boosting. So just
write: This commit adds boost frequency support in cpufreq core (Hardware
& Software).

> Some SoC (like Exynos4 - e.g. 4x12) allow setting frequency above
> its normal condition limits. Such a change shall be only done for a short

s/condition/operation
s/change/mode
s/done/used

> time.
>
> Overclocking (boost) support is essentially provided by platform
> dependent cpufreq driver.
>
> This commit unifies support for SW and HW (Intel) over clocking solutions
> in the core cpufreq driver. Previously the "boost" sysfs attribute was
> defined at acpi driver code.
> By default boost is disabled. One global attribute is available at:
> /sys/devices/system/cpu/cpufreq/boost.

Enter a blank line here.

> It only shows up when cpufreq driver supports overclocking.
> Under the hood frequencies dedicated for boosting are marked with a
> special flag (CPUFREQ_BOOST_FREQ) at driver's frequency table.
> It is the user's concern to enable/disable overclocking with proper call to
> sysfs.

Good.

> Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
>
> ---
> Changes for v2:
> - Removal of cpufreq_boost structure and move its fields to cpufreq_driver
> structure
> - Flag to indicate if global boost attribute is already defined
> - Extent the pr_{err|debbug} functions to show current function names
> ---

You don't have to manually add "---" here. Just keep a blank line instead.

> drivers/cpufreq/cpufreq.c | 69 ++++++++++++++++++++++++++++++++++++++++++
> drivers/cpufreq/freq_table.c | 57 ++++++++++++++++++++++++++++++++--
> include/linux/cpufreq.h | 12 ++++++++
> 3 files changed, 136 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 1b8a48e..98ba5f1 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -40,6 +40,7 @@
> * also protects the cpufreq_cpu_data array.
> */
> static struct cpufreq_driver *cpufreq_driver;
> +static bool cpufreq_boost_sysfs_defined;
> static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
> #ifdef CONFIG_HOTPLUG_CPU
> /* This one keeps track of the previously set governor of a removed CPU */
> @@ -315,6 +316,33 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
> /*********************************************************************
> * SYSFS INTERFACE *
> *********************************************************************/
> +ssize_t show_boost_status(struct kobject *kobj,
> + struct attribute *attr, char *buf)
> +{
> + return sprintf(buf, "%d\n", cpufreq_driver->boost_en);

This isn't correct. It shows if cpufreq driver supports boost or
not and it should show if boost is enabled from sysfs when
cpufreq driver supports boost.

> +}
> +
> +static ssize_t store_boost_status(struct kobject *kobj, struct attribute *attr,
> + const char *buf, size_t count)
> +{
> + int ret, enable;
> +
> + ret = sscanf(buf, "%d", &enable);
> + if (ret != 1 || enable < 0 || enable > 1)
> + return -EINVAL;
> +
> + if (cpufreq_boost_trigger_state(enable)) {
> + pr_err("%s: Cannot %sable boost!\n", __func__,
> + enable ? "en" : "dis");

%sable doesn't look very much readable. Use complete strings:
"enable" and "disable".

> + return -EINVAL;
> + }
> +
> + return count;
> +}
> +
> +static struct global_attr global_boost = __ATTR(boost, 0644,
> + show_boost_status,
> + store_boost_status);

User define_one_global_rw.

> static struct cpufreq_governor *__find_governor(const char *str_governor)
> {
> @@ -754,6 +782,17 @@ static int cpufreq_add_dev_interface(unsigned int cpu,

Why not do this in cpufreq_register_driver()?

> goto err_out_kobj_put;
> drv_attr++;
> }
> + if (cpufreq_driver->low_level_boost && !cpufreq_boost_sysfs_defined) {

I thought low_level_boost() is a function which will only be supported
for drivers
using hardware boost feature, like intel. And so we must have used boost_en
here.

> + ret = sysfs_create_file(cpufreq_global_kobject,
> + &(global_boost.attr));

cpufreq_sysfs_create_file(), check 2361be23666232dbb4851a527f466c4cbf5340fc
for details.

> + if (ret) {
> + pr_err("%s: cannot register global boost sysfs file\n",
> + __func__);
> + goto err_out_kobj_put;
> + }
> + cpufreq_boost_sysfs_defined = 1;
> + }
> +
> if (cpufreq_driver->get) {
> ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr);
> if (ret)
> @@ -1853,6 +1892,30 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
> };
>
> /*********************************************************************
> + * BOOST *
> + *********************************************************************/
> +int cpufreq_boost_trigger_state(int state)
> +{
> + int ret = 0;
> +
> + if (!cpufreq_driver->low_level_boost)
> + return -ENODEV;

I am certainly not aligned with your design. What's the
use of this field? And please update documentation too for these
new entries in cpufreq_driver structure.

> + if (cpufreq_driver->boost_en != state) {

So, you are using boost_en to see if boost is enabled from sysfs?
Then you have put it at wrong place.

I thought there would be three variables:
- cpufreq_driver->boost_supported: boost is enabled for driver
- cpufreq_driver->low_level_boost(): to set desired boost state
(Only for hardware boosting)
- boost_enabled: global variable in cpufreq.c file, used only if
cpufreq_driver->boost_supported is true.


> diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
> index d7a7966..4e4f692 100644
> --- a/drivers/cpufreq/freq_table.c
> +++ b/drivers/cpufreq/freq_table.c
> @@ -20,6 +20,27 @@
> * FREQUENCY TABLE HELPERS *
> *********************************************************************/
>
> +unsigned int
> +cpufreq_frequency_table_max(struct cpufreq_frequency_table *freq_table,
> + int boost)
> +{
> + int i = 0, boost_freq_max = 0, freq_max = 0;
> +
> + for (; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
> + if (freq_table[i].index == CPUFREQ_BOOST_FREQ) {
> + if (freq_table[i].frequency > boost_freq_max)
> + boost_freq_max = freq_table[i].frequency;

Do above only when boost==true and below when boost==false.
Looks wrong. You will show boost freqs when show_boost is false.
Code redundancy can be reduced by creating a macro for declaring
**_availabe_freqs, its attributes and export symbol.

> /*
> * if you use these, you must assure that the frequency table is valid
> * all the time between get_attr and put_attr!

With this patch alone, we would be using boost frequencies even in
normal cases where we haven't enabled boost.

Viresh Kumar

unread,
Jun 12, 2013, 2:10:02 AM6/12/13
to
On 12 June 2013 11:30, Lukasz Majewski <l.maj...@samsung.com> wrote:
> As you pointed out in the other mail 1/3 has its own issues, but I
> think that patches 2/3 and 3/3 are an integral part of the boost
> support and bring better overall overview to the design.

Yes they are. Undoubtedly.

>> Maybe you can just send v3 of 1/3. 2/3 and 3/3 can be sent when we
>> have finalized 2/3 and 3/3 's version.
>
> I'd opt for sending the whole patchset (it shouldn't be so difficult to
> adjust those patches), since it is easier for me to test.

Okay.

Lukasz Majewski

unread,
Jun 12, 2013, 2:10:02 AM6/12/13
to
Hi Viresh,

> On 11 June 2013 14:33, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > This patch series introduces support for CPU overclocking technique
> > called Boost.
> >
> > It is a follow up of a LAB governor proposal. Boost is a LAB
> > component:
> > http://thread.gmane.org/gmane.linux.kernel/1484746/match=cpufreq
> >
> > Boost unifies hardware based solution (e.g. Intel Nehalem) with
> > software oriented one (like the one done at Exynos).
> > For this reason cpufreq/freq_table code has been reorganized to
> > include common code.
>
> To be honest, I haven't given a review to patches 2/3 and 3/3 as I am
> concerned more about 1/3.

As you pointed out in the other mail 1/3 has its own issues, but I
think that patches 2/3 and 3/3 are an integral part of the boost
support and bring better overall overview to the design.

>
> Maybe you can just send v3 of 1/3. 2/3 and 3/3 can be sent when we
> have finalized 2/3 and 3/3 's version.

I'd opt for sending the whole patchset (it shouldn't be so difficult to
adjust those patches), since it is easier for me to test.



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 12, 2013, 3:50:02 AM6/12/13
to
Hi Viresh,

> Hi,
>
> Change subject to: "cpufreq: Add boost frequency support in core"

Ok.

>
> On 11 June 2013 14:33, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > This commit adds support for software based frequency boosting.
>
> No. It adds support for both software and hardware boosting. So just
> write: This commit adds boost frequency support in cpufreq core
> (Hardware & Software).

Ok.
>
> > Some SoC (like Exynos4 - e.g. 4x12) allow setting frequency above
> > its normal condition limits. Such a change shall be only done for a
> > short
>
> s/condition/operation
> s/change/mode
> s/done/used
>

Ok.

> > time.
> >
> > Overclocking (boost) support is essentially provided by platform
> > dependent cpufreq driver.
> >
> > This commit unifies support for SW and HW (Intel) over clocking
> > solutions in the core cpufreq driver. Previously the "boost" sysfs
> > attribute was defined at acpi driver code.
> > By default boost is disabled. One global attribute is available at:
> > /sys/devices/system/cpu/cpufreq/boost.
>
> Enter a blank line here.

Ok

>
> > It only shows up when cpufreq driver supports overclocking.
> > Under the hood frequencies dedicated for boosting are marked with a
> > special flag (CPUFREQ_BOOST_FREQ) at driver's frequency table.
> > It is the user's concern to enable/disable overclocking with proper
> > call to sysfs.
>
> Good.
>
> > Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> > Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
> >
> > ---
^^^^
[*] this --- was added manually by me.

> > Changes for v2:
> > - Removal of cpufreq_boost structure and move its fields to
> > cpufreq_driver structure
> > - Flag to indicate if global boost attribute is already defined
> > - Extent the pr_{err|debbug} functions to show current function
> > names ---
>
> You don't have to manually add "---" here. Just keep a blank line
> instead.

One "---" is added by git automatically. The [*] was added to distinct
the changelog from rest of the commit. At least older versions of GIT
required this to not include changelog to commit messages.
The cpufreq_driver->low_level_boost() is only valid when cpufreq driver
supports boost. Otherwise it is NULL. Thereof you will not see those
attributes exported to /sysfs until cpufreq driver supports boost.

When "boost" attribute is exported - then it returns state of boosting
(if it is enabled or not).

>
> > +}
> > +
> > +static ssize_t store_boost_status(struct kobject *kobj, struct
> > attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > + int ret, enable;
> > +
> > + ret = sscanf(buf, "%d", &enable);
> > + if (ret != 1 || enable < 0 || enable > 1)
> > + return -EINVAL;
> > +
> > + if (cpufreq_boost_trigger_state(enable)) {
> > + pr_err("%s: Cannot %sable boost!\n", __func__,
> > + enable ? "en" : "dis");
>
> %sable doesn't look very much readable. Use complete strings:
> "enable" and "disable".

Ok.

>
> > + return -EINVAL;
> > + }
> > +
> > + return count;
> > +}
> > +
> > +static struct global_attr global_boost = __ATTR(boost, 0644,
> > + show_boost_status,
> > + store_boost_status);
>
> User define_one_global_rw.

Ok, will reuse available macros (this code was taken directly from
acpi-cpufreq.c file).

>
> > static struct cpufreq_governor *__find_governor(const char
> > *str_governor) {
> > @@ -754,6 +782,17 @@ static int cpufreq_add_dev_interface(unsigned
> > int cpu,
>
> Why not do this in cpufreq_register_driver()?

Good point. I will move this code to cpufreq_register_driver.

>
> > goto err_out_kobj_put;
> > drv_attr++;
> > }
> > + if (cpufreq_driver->low_level_boost
> > && !cpufreq_boost_sysfs_defined) {
>
> I thought low_level_boost() is a function which will only be supported
> for drivers
> using hardware boost feature, like intel.

I think that we shall give users some flexibility and don't assume that
low_level_boost is only used for one solution/vendor.

It is also needed with software controlled boost. Please refer to patch
3/3.

> And so we must have used
> boost_en here.

boost_en has two meanings:
0 - either boost disabled or not supported (when low_level_boost=NULL).
1 - boost is enabled.

>
> > + ret = sysfs_create_file(cpufreq_global_kobject,
> > + &(global_boost.attr));
>
> cpufreq_sysfs_create_file(), check
> 2361be23666232dbb4851a527f466c4cbf5340fc for details.

Ok, I will rebase those changes to newest
kernel/git/rafael/linux-pm.git ,branch
kernel_pm/pm-cpufreq
I had to rewrite a bit :-) patches since we decided to drop struct
cpufreq_boost.

I've added two fields to cpufreq_driver:
- low_level_boost:
* When boost is not supported (default) it is set to NULL. This
field has two purposes: Indicates if boost is available on
the system and provides address of low level callback
* When cpufreq driver assigns pointer to this field,
it means that it is supported

- boost_en:
* It shows if boost is enabled or disabled/not supported to the
rest of the system.

> And please update documentation too for these
> new entries in cpufreq_driver structure.

Ok I will extend it.

>
> > + if (cpufreq_driver->boost_en != state) {
>
> So, you are using boost_en to see if boost is enabled from sysfs?
> Then you have put it at wrong place.

I check if boost is already enabled.

>
> I thought there would be three variables:
> - cpufreq_driver->boost_supported: boost is enabled for driver

For this purpose I check the low_level_boost pointer if it's NULL or
not.

> - cpufreq_driver->low_level_boost(): to set desired boost state
> (Only for hardware boosting)

It has two purposes (as described above) and can be used (defined) by
software and hardware boost solutions.

> - boost_enabled: global variable in cpufreq.c file, used only if
> cpufreq_driver->boost_supported is true.

I think that boost enabled flag shall be defined at cpufreq driver
(please look into acpi_cpufreq.c - which used another set of global
flags).
It will then provide one flag for cpufreq.c (core) and drivers.

However I've added one global flag: cpufreq_boost_sysfs_defined
which indicates if /sys/devices/system/cpu/cpufreq/boost attribute has
been already defined (to prevent multiple definitions attempts).

>
>
> > diff --git a/drivers/cpufreq/freq_table.c
> > b/drivers/cpufreq/freq_table.c index d7a7966..4e4f692 100644
> > --- a/drivers/cpufreq/freq_table.c
> > +++ b/drivers/cpufreq/freq_table.c
> > @@ -20,6 +20,27 @@
> > * FREQUENCY TABLE
> > HELPERS *
> > *********************************************************************/
> >
> > +unsigned int
> > +cpufreq_frequency_table_max(struct cpufreq_frequency_table
> > *freq_table,
> > + int boost)
> > +{
> > + int i = 0, boost_freq_max = 0, freq_max = 0;
> > +
> > + for (; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
> > + if (freq_table[i].index == CPUFREQ_BOOST_FREQ) {
> > + if (freq_table[i].frequency >
> > boost_freq_max)
> > + boost_freq_max =
> > freq_table[i].frequency;
>
> Do above only when boost==true and below when boost==false.

Ok.
My purpose here is to display frequencies only tagged with
CPUFREQ_BOOST_FREQ and when show_boost is true.

When show_boost is false, the operation of the function is unchanged.
Yes, you are right here. Those two structures only differ with
different names.

>
> > /*
> > * if you use these, you must assure that the frequency table is
> > valid
> > * all the time between get_attr and put_attr!
>
> With this patch alone, we would be using boost frequencies even in
> normal cases where we haven't enabled boost.

Correct me if I'm wrong here, but the
cpufreq_freq_attr_boost_available_freqs will be added to cpufreq
driver's freq_attr table (i.e. *exynos_cpufreq_attr[]).
It is cpufreq driver's responsibility to add this attribute. By default
all other drivers add only cpufreq_freq_attr_boost_available_freqs.


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 12, 2013, 4:10:02 AM6/12/13
to
On 12 June 2013 13:09, Lukasz Majewski <l.maj...@samsung.com> wrote:
> Hi Viresh,

Hi Lukasz,

>> Hi,

Please don't remove the line which says, who wrote last mail at what time.
These >, >>, >>>, >>>>, ... have a meaning. They help us understand who
wrote what in bottom posting. And as you removed my line, nobody can see
who wrote above "Hi" to you :)

>> You don't have to manually add "---" here. Just keep a blank line
>> instead.
>
> One "---" is added by git automatically. The [*] was added to distinct
> the changelog from rest of the commit. At least older versions of GIT
> required this to not include changelog to commit messages.

You don't have to add an extra "---" line. Just write your changelog
after "---" added by git and give a blank line between your last
changelog line and below ones (probably just to make it more
readable and not a must, but i am not sure).

>> > drivers/cpufreq/cpufreq.c | 69
>> > ++++++++++++++++++++++++++++++++++++++++++
>> > drivers/cpufreq/freq_table.c | 57
>> > ++++++++++++++++++++++++++++++++-- include/linux/cpufreq.h |
>> > 12 ++++++++ 3 files changed, 136 insertions(+), 2 deletions(-)

> I think that we shall give users some flexibility and don't assume that
> low_level_boost is only used for one solution/vendor.
>
> It is also needed with software controlled boost. Please refer to patch
> 3/3.

You didn't get me. I am not asking to keep it only for Intel. But keep
this variable as is (s/low_level_boost/set_boost_freq), and make it
optional. So, few drivers can implement it but not everybody is required
to.

So, Add another variable: boost_supported, which will tell cpufreq core
that boost is supported by governor or not.

And a global variable in cpufreq.c boost_enabled to track status of
what user has requested.

> However I've added one global flag: cpufreq_boost_sysfs_defined
> which indicates if /sys/devices/system/cpu/cpufreq/boost attribute has
> been already defined (to prevent multiple definitions attempts).

You don't need this variable anymore as sysfs create file is now
moved to cpufreq_register_driver(), so this can't be called twice.

>> > char *buf) +static ssize_t show_available_freqs(struct
>> > cpufreq_policy *policy, char *buf,
>> > + int show_boost)
>> > {
>> > unsigned int i = 0;
>> > unsigned int cpu = policy->cpu;
>> > @@ -186,22 +208,53 @@ static ssize_t show_available_freqs(struct
>> > cpufreq_policy *policy, char *buf) for (i = 0;
>> > (table[i].frequency != CPUFREQ_TABLE_END); i++) { if
>> > (table[i].frequency == CPUFREQ_ENTRY_INVALID) continue;
>> > + if (show_boost)
>> > + if (table[i].index != CPUFREQ_BOOST_FREQ)
>> > + continue;
>> > +
>>
>> Looks wrong. You will show boost freqs when show_boost is false.
>
> My purpose here is to display frequencies only tagged with
> CPUFREQ_BOOST_FREQ and when show_boost is true.
>
> When show_boost is false, the operation of the function is unchanged.

Which is wrong. When show_boost is false, it means that user don't
want to see boost frequencies and so you should skip them.

>> With this patch alone, we would be using boost frequencies even in
>> normal cases where we haven't enabled boost.
>
> Correct me if I'm wrong here, but the
> cpufreq_freq_attr_boost_available_freqs will be added to cpufreq
> driver's freq_attr table (i.e. *exynos_cpufreq_attr[]).
> It is cpufreq driver's responsibility to add this attribute. By default
> all other drivers add only cpufreq_freq_attr_boost_available_freqs.

You are just talking about showing boost freqs in sysfs. I am talking
about the frequencies that governors will select when boost is
disabled from sysfs. Because we don't skip boost frequencies in
target() routines, we will set them as and when governor requests
them.

Lukasz Majewski

unread,
Jun 12, 2013, 5:20:02 AM6/12/13
to
On Wed, 12 Jun 2013 13:39:18 +0530, Viresh Kumar wrote:

Hi Viresh,

> On 12 June 2013 13:09, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > Hi Viresh,
>
> Hi Lukasz,
>
> >> Hi,
>
> Please don't remove the line which says, who wrote last mail at what
> time. These >, >>, >>>, >>>>, ... have a meaning. They help us
> understand who wrote what in bottom posting. And as you removed my
> line, nobody can see who wrote above "Hi" to you :)

Ok, mailer adjusted.

>
> >> You don't have to manually add "---" here. Just keep a blank line
> >> instead.
> >
> > One "---" is added by git automatically. The [*] was added to
> > distinct the changelog from rest of the commit. At least older
> > versions of GIT required this to not include changelog to commit
> > messages.
>
> You don't have to add an extra "---" line. Just write your changelog
> after "---" added by git and give a blank line between your last
> changelog line and below ones (probably just to make it more
> readable and not a must, but i am not sure).

I got your point. If you prefer, I will stick to it. No problem.

As a side note:

In the other open source project (u-boot) we use the pattern which I've
used previously. It has one big advantage - I can edit change log at
git gui (just below sign-of-by). It is simply more convenient for
me :-). Those changes between "---" are simply skipped by git am
afterwards.

>
> >> > drivers/cpufreq/cpufreq.c | 69
> >> > ++++++++++++++++++++++++++++++++++++++++++
> >> > drivers/cpufreq/freq_table.c | 57
> >> > ++++++++++++++++++++++++++++++++-- include/linux/cpufreq.h |
> >> > 12 ++++++++ 3 files changed, 136 insertions(+), 2 deletions(-)
>
> > I think that we shall give users some flexibility and don't assume
> > that low_level_boost is only used for one solution/vendor.
> >
> > It is also needed with software controlled boost. Please refer to
> > patch 3/3.
>
> You didn't get me. I am not asking to keep it only for Intel. But keep
> this variable as is (s/low_level_boost/set_boost_freq), and make it
> optional. So, few drivers can implement it but not everybody is
> required to.

The low_level_boost (set_boost_freq)[*] is optional. However it seems to
me, that the burden of changing available set of frequencies (when
boost is enabled) must be put to cpufreq driver anyway.

Without this function [*] defined, we cannot enable frequency boosting.

>
> So, Add another variable: boost_supported, which will tell cpufreq
> core that boost is supported by governor or not.
^^^^^^^shouldn't it be cpufreq driver?

Ok, boost_supported seems needed. In my opinion it shall be defined at
cpufreq_driver structure (since it provides boosting infrastructure
anyway).

>
> And a global variable in cpufreq.c boost_enabled to track status of
> what user has requested.

I think, that boost_enable shall be also defined at cpufreq driver (as
proposed in the patch). We keep pointer to cpufreq driver at cpufreq.c
anyway. Moreover, boost_enable flag is already defined at
acpi-cpufreq.c (as static). We will have two flags for the same
purpose.

>
> > However I've added one global flag: cpufreq_boost_sysfs_defined
> > which indicates if /sys/devices/system/cpu/cpufreq/boost attribute
> > has been already defined (to prevent multiple definitions attempts).
>
> You don't need this variable anymore as sysfs create file is now
> moved to cpufreq_register_driver(), so this can't be called twice.

Yes, in this situation the cpufreq_boost_sysfs_defined flag is
redundant.

>
> >> > char *buf) +static ssize_t show_available_freqs(struct
> >> > cpufreq_policy *policy, char *buf,
> >> > + int show_boost)
> >> > {
> >> > unsigned int i = 0;
> >> > unsigned int cpu = policy->cpu;
> >> > @@ -186,22 +208,53 @@ static ssize_t show_available_freqs(struct
> >> > cpufreq_policy *policy, char *buf) for (i = 0;
> >> > (table[i].frequency != CPUFREQ_TABLE_END); i++) { if
> >> > (table[i].frequency == CPUFREQ_ENTRY_INVALID) continue;
> >> > + if (show_boost)
> >> > + if (table[i].index != CPUFREQ_BOOST_FREQ)
> >> > + continue;
> >> > +
> >>
> >> Looks wrong. You will show boost freqs when show_boost is false.
> >
> > My purpose here is to display frequencies only tagged with
> > CPUFREQ_BOOST_FREQ and when show_boost is true.
> >
> > When show_boost is false, the operation of the function is
> > unchanged.
>
> Which is wrong. When show_boost is false, it means that user don't
> want to see boost frequencies and so you should skip them.

So we want as follows:
show_boost = 1 ---> show only frequencies tagged as CPUFREQ_BOOST_FREQ
show_boost = 0 ---> show only "normal" (non boost) frequencies

>
> >> With this patch alone, we would be using boost frequencies even in
> >> normal cases where we haven't enabled boost.
> >
> > Correct me if I'm wrong here, but the
> > cpufreq_freq_attr_boost_available_freqs will be added to cpufreq
> > driver's freq_attr table (i.e. *exynos_cpufreq_attr[]).
> > It is cpufreq driver's responsibility to add this attribute. By
> > default all other drivers add only
> > cpufreq_freq_attr_boost_available_freqs.
>
> You are just talking about showing boost freqs in sysfs. I am talking
> about the frequencies that governors will select when boost is
> disabled from sysfs. Because we don't skip boost frequencies in
> target() routines, we will set them as and when governor requests
> them.

I think, that it is the main issue here and it shall be cleared out:

Frequencies marked as: CPUFREQ_BOOST_FREQ are added permanently to the
freq_table.
That is the distinction to the original overclocking patch posted with
LAB, where freq_boost structure was modified and boost frequencies were
either valid or invalid.

Then we can in SW control boost in two ways:
1. change policy->max value (to the maximal boost frequency) - as it is
done now (v3) at Exynos. This is the simple solution (patch 3/3)

2. Modify all freq_table helper functions to be aware of boost and
skip boost frequencies when boost_enable = 0. (as it was done at v2).
This requires code modification at freq_table.c and reevaluation of
policy.

Maybe you have any other idea?


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 12, 2013, 5:30:02 AM6/12/13
to
On 12 June 2013 14:39, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Wed, 12 Jun 2013 13:39:18 +0530, Viresh Kumar wrote:
>> On 12 June 2013 13:09, Lukasz Majewski <l.maj...@samsung.com> wrote:

>> You don't have to add an extra "---" line. Just write your changelog
>> after "---" added by git and give a blank line between your last
>> changelog line and below ones (probably just to make it more
>> readable and not a must, but i am not sure).
>
> I got your point. If you prefer, I will stick to it. No problem.

Its not how I prefer it, but how everybody does it :)

> As a side note:
>
> In the other open source project (u-boot) we use the pattern which I've
> used previously. It has one big advantage - I can edit change log at
> git gui (just below sign-of-by). It is simply more convenient for
> me :-). Those changes between "---" are simply skipped by git am
> afterwards.

Yes, I am still asking you to follow the same steps:

git send-email --annotate ***patches***

and then write whatever you don't want to be logged by git am after
the "---" already present in the patch.

>> >> > drivers/cpufreq/cpufreq.c | 69
>> >> > ++++++++++++++++++++++++++++++++++++++++++
>> >> > drivers/cpufreq/freq_table.c | 57
>> >> > ++++++++++++++++++++++++++++++++-- include/linux/cpufreq.h |
>> >> > 12 ++++++++ 3 files changed, 136 insertions(+), 2 deletions(-)
>>
>> > I think that we shall give users some flexibility and don't assume
>> > that low_level_boost is only used for one solution/vendor.
>> >
>> > It is also needed with software controlled boost. Please refer to
>> > patch 3/3.
>>
>> You didn't get me. I am not asking to keep it only for Intel. But keep
>> this variable as is (s/low_level_boost/set_boost_freq), and make it
>> optional. So, few drivers can implement it but not everybody is
>> required to.
>
> The low_level_boost (set_boost_freq)[*] is optional. However it seems to
> me, that the burden of changing available set of frequencies (when
> boost is enabled) must be put to cpufreq driver anyway.

Driver shouldn't play with boost freqs at runtime. This has to be handled
by cpufreq core. The only thing cpufreq driver must be doing in
low_level_boost or set_boost_freq (as what I suggested it to be), is
to set the boost frequency requested by core. And so this routine would
only be defined by drivers that have a special way of setting boost
frequencies. For others ->target() routine should be able to set all
freqs, boost or non boost.

> Without this function [*] defined, we cannot enable frequency boosting.

why?

>> So, Add another variable: boost_supported, which will tell cpufreq
>> core that boost is supported by governor or not.
> ^^^^^^^shouldn't it be cpufreq driver?

Yeah, sorry :(

> Ok, boost_supported seems needed. In my opinion it shall be defined at
> cpufreq_driver structure (since it provides boosting infrastructure
> anyway).

that's what I asked.

>> And a global variable in cpufreq.c boost_enabled to track status of
>> what user has requested.
>
> I think, that boost_enable shall be also defined at cpufreq driver (as
> proposed in the patch).

Not really. Driver should only care about if it supports boost or not.
If it is enabled/disabled by sysfs or not should be kept inside core
in a global variable.

Moreover, if we have 5-6 cpufreq drivers compiled in (for multi-arch
compiled kernels), we will save memory wasted by this variable if
it is present in cpufreq_driver.

> Moreover, boost_enable flag is already defined at
> acpi-cpufreq.c (as static). We will have two flags for the same
> purpose.

No, we don't have to. Just expose another API from cpufreq core
to get status of boost.

> So we want as follows:
> show_boost = 1 ---> show only frequencies tagged as CPUFREQ_BOOST_FREQ
> show_boost = 0 ---> show only "normal" (non boost) frequencies

Yes.

>> You are just talking about showing boost freqs in sysfs. I am talking
>> about the frequencies that governors will select when boost is
>> disabled from sysfs. Because we don't skip boost frequencies in
>> target() routines, we will set them as and when governor requests
>> them.
>
> I think, that it is the main issue here and it shall be cleared out:
>
> Frequencies marked as: CPUFREQ_BOOST_FREQ are added permanently to the
> freq_table.
> That is the distinction to the original overclocking patch posted with
>> LAB, where freq_boost structure was modified and boost frequencies were
> either valid or invalid.

Yes.

> Then we can in SW control boost in two ways:
> 1. change policy->max value (to the maximal boost frequency) - as it is
> done now (v3) at Exynos. This is the simple solution (patch 3/3)

Drivers aren't supposed to set policy->max. It should be taken care
of by core or freq_table.c file.

> 2. Modify all freq_table helper functions to be aware of boost and
> skip boost frequencies when boost_enable = 0. (as it was done at v2).
> This requires code modification at freq_table.c and reevaluation of
> policy.

Yes, the core must be aware of it and must take the right decision
here. So, we need to take care of boost freq in freq_table.c

Rafael J. Wysocki

unread,
Jun 12, 2013, 7:20:02 AM6/12/13
to
Which doesn't matter anyway. None of them will show up in git log, so don't
worry. :-)

[...]

>
> > And so we must have used
> > boost_en here.
>
> boost_en has two meanings:
> 0 - either boost disabled or not supported (when low_level_boost=NULL).
> 1 - boost is enabled.

Gosh, please don't do that. Use *two* flags, one meaning "supported" and the
second meaning "enabled".

Thanks,
Rafael


--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

Lukasz Majewski

unread,
Jun 12, 2013, 7:50:02 AM6/12/13
to
On Wed, 12 Jun 2013 13:23:20 +0200, Rafael J. Wysocki wrote:

Hi Rafael,
That was already pointed out by Viresh. I will stick to his
guidelines :-).

>
> Thanks,
> Rafael
>
>



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 12, 2013, 8:40:03 AM6/12/13
to
On Wed, 12 Jun 2013 14:55:45 +0530, Viresh Kumar wrote:
> On 12 June 2013 14:39, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > On Wed, 12 Jun 2013 13:39:18 +0530, Viresh Kumar wrote:
> >> On 12 June 2013 13:09, Lukasz Majewski <l.maj...@samsung.com>
> >> wrote:
>
> >> You don't have to add an extra "---" line. Just write your
> >> changelog after "---" added by git and give a blank line between
> >> your last changelog line and below ones (probably just to make it
> >> more readable and not a must, but i am not sure).
> >
> > I got your point. If you prefer, I will stick to it. No problem.
>
> Its not how I prefer it, but how everybody does it :)

Ok, :-)

>
> > As a side note:
> >
> > In the other open source project (u-boot) we use the pattern which
> > I've used previously. It has one big advantage - I can edit change
> > log at git gui (just below sign-of-by). It is simply more
> > convenient for me :-). Those changes between "---" are simply
> > skipped by git am afterwards.
>
> Yes, I am still asking you to follow the same steps:
>
> git send-email --annotate ***patches***
>
> and then write whatever you don't want to be logged by git am after
> the "---" already present in the patch.

Ok,

>
> >> >> > drivers/cpufreq/cpufreq.c | 69
> >> >> > ++++++++++++++++++++++++++++++++++++++++++
> >> >> > drivers/cpufreq/freq_table.c | 57
> >> >> > ++++++++++++++++++++++++++++++++--
> >> >> > include/linux/cpufreq.h | 12 ++++++++ 3 files changed,
> >> >> > 136 insertions(+), 2 deletions(-)
> >>
> >> > I think that we shall give users some flexibility and don't
> >> > assume that low_level_boost is only used for one solution/vendor.
> >> >
> >> > It is also needed with software controlled boost. Please refer to
> >> > patch 3/3.
> >>
> >> You didn't get me. I am not asking to keep it only for Intel. But
> >> keep this variable as is (s/low_level_boost/set_boost_freq), and
> >> make it optional. So, few drivers can implement it but not
> >> everybody is required to.
> >
> > The low_level_boost (set_boost_freq)[*] is optional. However it
> > seems to me, that the burden of changing available set of
> > frequencies (when boost is enabled) must be put to cpufreq driver
> > anyway.
>
> Driver shouldn't play with boost freqs at runtime. This has to be
> handled by cpufreq core. The only thing cpufreq driver must be doing
> in low_level_boost or set_boost_freq (as what I suggested it to be),

So you want the set_boost_freq to not be used with software based
boosting. Ok.

> is to set the boost frequency requested by core. And so this routine
> would only be defined by drivers that have a special way of setting
> boost frequencies. For others ->target() routine should be able to
> set all freqs, boost or non boost.
>
> > Without this function [*] defined, we cannot enable frequency
> > boosting.
>
> why?

Hmm, please read my further comment.

>
> >> So, Add another variable: boost_supported, which will tell cpufreq
> >> core that boost is supported by governor or not.
> > ^^^^^^^shouldn't it be cpufreq
> > driver?
>
> Yeah, sorry :(

Ok.

>
> > Ok, boost_supported seems needed. In my opinion it shall be defined
> > at cpufreq_driver structure (since it provides boosting
> > infrastructure anyway).
>
> that's what I asked.

Ok :-) .

>
> >> And a global variable in cpufreq.c boost_enabled to track status of
> >> what user has requested.
> >
> > I think, that boost_enable shall be also defined at cpufreq driver
> > (as proposed in the patch).
>
> Not really. Driver should only care about if it supports boost or not.
> If it is enabled/disabled by sysfs or not should be kept inside core
> in a global variable.

Ok,

>
> Moreover, if we have 5-6 cpufreq drivers compiled in (for multi-arch
> compiled kernels), we will save memory wasted by this variable if
> it is present in cpufreq_driver.

Ok. I didn't thought about this use case. Agree.

>
> > Moreover, boost_enable flag is already defined at
> > acpi-cpufreq.c (as static). We will have two flags for the same
> > purpose.
>
> No, we don't have to. Just expose another API from cpufreq core
> to get status of boost.

Ok.

>
> > So we want as follows:
> > show_boost = 1 ---> show only frequencies tagged as
> > CPUFREQ_BOOST_FREQ show_boost = 0 ---> show only "normal" (non
> > boost) frequencies
>
> Yes.

Ok,

>
> >> You are just talking about showing boost freqs in sysfs. I am
> >> talking about the frequencies that governors will select when
> >> boost is disabled from sysfs. Because we don't skip boost
> >> frequencies in target() routines, we will set them as and when
> >> governor requests them.
> >
> > I think, that it is the main issue here and it shall be cleared out:
> >
> > Frequencies marked as: CPUFREQ_BOOST_FREQ are added permanently to
> > the freq_table.
> > That is the distinction to the original overclocking patch posted
> > with
> >> LAB, where freq_boost structure was modified and boost frequencies
> >> were
> > either valid or invalid.
>
> Yes.
>
> > Then we can in SW control boost in two ways:
> > 1. change policy->max value (to the maximal boost frequency) - as
> > it is done now (v3) at Exynos. This is the simple solution (patch
> > 3/3)
>
> Drivers aren't supposed to set policy->max. It should be taken care
> of by core or freq_table.c file.

This seems the right thing, but it would require some functions defined
at freq_table.c to be extended to accept bool "boost" parameter (which
would not consider freqs tagged as CPUFREQ_BOOST_FREQ).
Then each per cpu policy, shall be read and its max freq shall be
updated when someone enables boost from sysfs (at
cpufreq_boost_trigger_state).

This is my idea to manage boost mode from core code. Am I right?



>
> > 2. Modify all freq_table helper functions to be aware of boost and
> > skip boost frequencies when boost_enable = 0. (as it was done at
> > v2). This requires code modification at freq_table.c and
> > reevaluation of policy.
>
> Yes, the core must be aware of it and must take the right decision
> here. So, we need to take care of boost freq in freq_table.c

Ok. Then we agreed :-).

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 14, 2013, 3:40:02 AM6/14/13
to
The struct cpufreq_driver has been extended to embrace the information
related to boost support.

When "boost_mode" device tree attribute is defined for a platform, the
boost_supported flag is set. Moreover boost related attributes were
exported.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v2:
- Removal of struct cpufreq_boost
- Removal of the CONFIG_CPU_FREQ_BOOST flag
- low_level_boost with valid address when boost is supported

Changes for v3:
- Remove low level boost code
- Move boost management code to cpufreq core code
- Use boost_supported flag to indicate if driver supports over clocking

---
drivers/cpufreq/exynos-cpufreq.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 32ec2f6..0420d47 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -265,6 +265,7 @@ static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)

static struct freq_attr *exynos_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
+ &cpufreq_freq_attr_scaling_boost_freqs,
NULL,
};

@@ -360,6 +361,7 @@ static struct of_device_id exynos_cpufreq_of_match[] __initconst = {

static int __init exynos_cpufreq_probe(struct platform_device *pdev)
{
+ struct device_node *node = pdev->dev.of_node;
int ret = -EINVAL;

exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
@@ -392,6 +394,8 @@ static int __init exynos_cpufreq_probe(struct platform_device *pdev)
}

locking_frequency = exynos_getspeed(0);
+ if (of_property_read_bool(node, "boost_mode"))
+ exynos_driver.boost_supported = 1;

register_pm_notifier(&exynos_cpufreq_nb);

--
1.7.10.4

Lukasz Majewski

unread,
Jun 14, 2013, 3:40:02 AM6/14/13
to
This patch series introduces support for CPU overclocking technique
called Boost.

It is a follow up of a LAB governor proposal. Boost is a LAB component:
http://thread.gmane.org/gmane.linux.kernel/1484746/match=cpufreq

Boost unifies hardware based solution (e.g. Intel Nehalem) with
software oriented one (like the one done at Exynos).
For this reason cpufreq/freq_table code has been reorganized to include
common code.

Important design decisions:

- Boost related code is compiled-in unconditionally and disabled by default
The cpufreq_driver is responsibile for providing set_boost_freq callback
(if needed)

- struct cpufreq_driver has been extended with boost related fields:
-- boost_supported - when driver supports boosting
-- set_boost_freq - callback to function, which is necessary to
enable boost at the processor (like it is done at Intel)

- Boost sysfs attributies are seen only when cpufreq driver supports them.
They will not show up until either cpufreq_driver defines boost_supported
flag or device tree's cpufreq "boost_mode" attribute.

- No special spin_lock for Boost was created. The one from cpufreq_driver
was reused.

- The Boost code doesn't rely on any policy. When boost state is changed,
then policies attached to each CPU are updated.


Tested at: HW:
Exynos 4412 3.10 linux
Exynos 4210 3.10 linux
Compile tested x86_64 defconfig (acpi) - help with HW (Intel Nehalem) test
needed


Lukasz Majewski (3):
cpufreq: Add boost frequency support in core
cpufreq:acpi:x86: Adjust the acpi-cpufreq.c code to work with common
boost solution
cpufreq:exynos:Extend Exynos cpufreq driver to support boost
framework

arch/arm/mach-s3c24xx/cpufreq.c | 2 +-
arch/powerpc/platforms/pasemi/cpufreq.c | 2 +-
arch/powerpc/platforms/powermac/cpufreq_32.c | 2 +-
arch/powerpc/platforms/powermac/cpufreq_64.c | 2 +-
drivers/cpufreq/acpi-cpufreq.c | 62 +++++++-----------
drivers/cpufreq/arm_big_little.c | 3 +-
drivers/cpufreq/blackfin-cpufreq.c | 2 +-
drivers/cpufreq/cpufreq-cpu0.c | 2 +-
drivers/cpufreq/cpufreq.c | 87 ++++++++++++++++++++++++++
drivers/cpufreq/cris-artpec3-cpufreq.c | 2 +-
drivers/cpufreq/cris-etraxfs-cpufreq.c | 2 +-
drivers/cpufreq/davinci-cpufreq.c | 2 +-
drivers/cpufreq/dbx500-cpufreq.c | 2 +-
drivers/cpufreq/e_powersaver.c | 3 +-
drivers/cpufreq/elanfreq.c | 2 +-
drivers/cpufreq/exynos-cpufreq.c | 7 ++-
drivers/cpufreq/exynos5440-cpufreq.c | 2 +-
drivers/cpufreq/freq_table.c | 44 ++++++++++---
drivers/cpufreq/ia64-acpi-cpufreq.c | 2 +-
drivers/cpufreq/imx6q-cpufreq.c | 2 +-
drivers/cpufreq/kirkwood-cpufreq.c | 3 +-
drivers/cpufreq/longhaul.c | 2 +-
drivers/cpufreq/loongson2_cpufreq.c | 2 +-
drivers/cpufreq/maple-cpufreq.c | 2 +-
drivers/cpufreq/omap-cpufreq.c | 2 +-
drivers/cpufreq/p4-clockmod.c | 2 +-
drivers/cpufreq/powernow-k6.c | 2 +-
drivers/cpufreq/powernow-k7.c | 2 +-
drivers/cpufreq/powernow-k8.c | 2 +-
drivers/cpufreq/ppc_cbe_cpufreq.c | 2 +-
drivers/cpufreq/pxa2xx-cpufreq.c | 4 +-
drivers/cpufreq/pxa3xx-cpufreq.c | 2 +-
drivers/cpufreq/s3c2416-cpufreq.c | 2 +-
drivers/cpufreq/s3c64xx-cpufreq.c | 2 +-
drivers/cpufreq/s5pv210-cpufreq.c | 2 +-
drivers/cpufreq/sc520_freq.c | 2 +-
drivers/cpufreq/sh-cpufreq.c | 2 +-
drivers/cpufreq/sparc-us2e-cpufreq.c | 2 +-
drivers/cpufreq/sparc-us3-cpufreq.c | 2 +-
drivers/cpufreq/spear-cpufreq.c | 3 +-
drivers/cpufreq/speedstep-centrino.c | 2 +-
drivers/cpufreq/speedstep-ich.c | 2 +-
drivers/cpufreq/speedstep-smi.c | 2 +-
drivers/cpufreq/tegra-cpufreq.c | 4 +-
include/linux/cpufreq.h | 18 +++++-
45 files changed, 211 insertions(+), 95 deletions(-)

Lukasz Majewski

unread,
Jun 14, 2013, 3:40:02 AM6/14/13
to
The Intel's hardware based boost solution driver has been changed to cooperate with
common cpufreq boost framework.

The global sysfs boost attribute entry code (/sys/devices/system/cpu/cpufreq/boost)
has been moved to a core cpufreq code. This attribute is now only visible,
when cpufreq driver supports it.
The boost supported global flag was replaced with the one defined at acpi's
cpufreq driver.

The _store_boost() function has been redesigned to be used as set_boost_freq
callback.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v2:
- Replace boost_enabled and boost_supported global flags with proper entries
at struct cpufreq_driver.
- Removal of struct cpufreq_boost

Changes for v3:
- Bring back boost_enabled as a global flag
- Move boost_supported to cpufreq_driver structure

---
drivers/cpufreq/acpi-cpufreq.c | 60 ++++++++++++++--------------------------
1 file changed, 20 insertions(+), 40 deletions(-)

diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index abca529..9cd528e 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -80,7 +80,7 @@ static struct acpi_processor_performance __percpu *acpi_perf_data;
static struct cpufreq_driver acpi_cpufreq_driver;

static unsigned int acpi_pstate_strict;
-static bool boost_enabled, boost_supported;
+static bool boost_enabled;
static struct msr __percpu *msrs;

static bool boost_state(unsigned int cpu)
@@ -133,20 +133,10 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask)
wrmsr_on_cpus(cpumask, msr_addr, msrs);
}

-static ssize_t _store_boost(const char *buf, size_t count)
+static int _store_boost(int val)
{
- int ret;
- unsigned long val = 0;
-
- if (!boost_supported)
- return -EINVAL;
-
- ret = kstrtoul(buf, 10, &val);
- if (ret || (val > 1))
- return -EINVAL;
-
if ((val && boost_enabled) || (!val && !boost_enabled))
- return count;
+ return 0;

get_online_cpus();

@@ -157,30 +147,31 @@ static ssize_t _store_boost(const char *buf, size_t count)
boost_enabled = val;
pr_debug("Core Boosting %sabled.\n", val ? "en" : "dis");

- return count;
+ return 0;
}

-static ssize_t store_global_boost(struct kobject *kobj, struct attribute *attr,
- const char *buf, size_t count)
+static ssize_t store_boost(const char *buf, size_t count)
{
- return _store_boost(buf, count);
-}
+ int ret;
+ unsigned long val = 0;

-static ssize_t show_global_boost(struct kobject *kobj,
- struct attribute *attr, char *buf)
-{
- return sprintf(buf, "%u\n", boost_enabled);
-}
+ if (!acpi_cpufreq_driver.boost_supported)
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret || (val > 1))
+ return -EINVAL;

-static struct global_attr global_boost = __ATTR(boost, 0644,
- show_global_boost,
- store_global_boost);
+ _store_boost((int) val);
+
+ return count;
+}

#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
size_t count)
{
- return _store_boost(buf, count);
+ return store_boost(buf, count);
}

static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
@@ -930,8 +921,8 @@ static void __init acpi_cpufreq_boost_init(void)
if (!msrs)
return;

- boost_supported = true;
boost_enabled = boost_state(0);
+ acpi_cpufreq_driver.boost_supported = true;

get_online_cpus();

@@ -941,22 +932,11 @@ static void __init acpi_cpufreq_boost_init(void)
register_cpu_notifier(&boost_nb);

put_online_cpus();
- } else
- global_boost.attr.mode = 0444;
-
- /* We create the boost file in any case, though for systems without
- * hardware support it will be read-only and hardwired to return 0.
- */
- if (cpufreq_sysfs_create_file(&(global_boost.attr)))
- pr_warn(PFX "could not register global boost sysfs file\n");
- else
- pr_debug("registered global boost sysfs file\n");
+ }
}

static void __exit acpi_cpufreq_boost_exit(void)
{
- cpufreq_sysfs_remove_file(&(global_boost.attr));
-
if (msrs) {
unregister_cpu_notifier(&boost_nb);

Lukasz Majewski

unread,
Jun 14, 2013, 3:40:03 AM6/14/13
to
This commit adds boost frequency support in cpufreq core (Hardware &
Software).
Some SoC (like Exynos4 - e.g. 4x12) allow setting frequency above
its normal operation limits. Such a mode shall be only used for a short
time.

Overclocking (boost) support is essentially provided by platform
dependent cpufreq driver.

This commit unifies support for SW and HW (Intel) over clocking solutions
in the core cpufreq driver. Previously the "boost" sysfs attribute was
defined at acpi driver code.
By default boost is disabled. One global attribute is available at:
/sys/devices/system/cpu/cpufreq/boost.

It only shows up when cpufreq driver supports overclocking.
Under the hood frequencies dedicated for boosting are marked with a
special flag (CPUFREQ_BOOST_FREQ) at driver's frequency table.
It is the user's concern to enable/disable overclocking with proper call to
sysfs.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v2:
- Removal of cpufreq_boost structure and move its fields to cpufreq_driver
structure
- Flag to indicate if global boost attribute is already defined
- Extent the pr_{err|debbug} functions to show current function names

Changes for v3:
- Method for reading boost status
- Removal of cpufreq_frequency_table_max()
- Extent cpufreq_frequency_table_cpuinfo() to support boost parameter
- boost_supported flag added to cpufreq_driver struct
- "boost" sysfs attribute control flag removed
- One global flag describing state of the boost defined at cpufreq core
- Rename cpufreq_driver's low_level_boost field to set_boost_freq()
- Usage of cpufreq_sysfs_{remove|add}_file() routines

---
arch/arm/mach-s3c24xx/cpufreq.c | 2 +-
arch/powerpc/platforms/pasemi/cpufreq.c | 2 +-
arch/powerpc/platforms/powermac/cpufreq_32.c | 2 +-
arch/powerpc/platforms/powermac/cpufreq_64.c | 2 +-
drivers/cpufreq/acpi-cpufreq.c | 2 +-
drivers/cpufreq/arm_big_little.c | 3 +-
drivers/cpufreq/blackfin-cpufreq.c | 2 +-
drivers/cpufreq/cpufreq-cpu0.c | 2 +-
drivers/cpufreq/cpufreq.c | 87 ++++++++++++++++++++++++++
drivers/cpufreq/cris-artpec3-cpufreq.c | 2 +-
drivers/cpufreq/cris-etraxfs-cpufreq.c | 2 +-
drivers/cpufreq/davinci-cpufreq.c | 2 +-
drivers/cpufreq/dbx500-cpufreq.c | 2 +-
drivers/cpufreq/e_powersaver.c | 3 +-
drivers/cpufreq/elanfreq.c | 2 +-
drivers/cpufreq/exynos-cpufreq.c | 3 +-
45 files changed, 187 insertions(+), 55 deletions(-)

diff --git a/arch/arm/mach-s3c24xx/cpufreq.c b/arch/arm/mach-s3c24xx/cpufreq.c
index 3c0e78e..882fcb5 100644
--- a/arch/arm/mach-s3c24xx/cpufreq.c
+++ b/arch/arm/mach-s3c24xx/cpufreq.c
@@ -387,7 +387,7 @@ static int s3c_cpufreq_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = cpu_cur.info->latency;

if (ftab)
- cpufreq_frequency_table_cpuinfo(policy, ftab);
+ cpufreq_frequency_table_cpuinfo(policy, ftab, 0);

return 0;
}
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index be1e795..3d2fcc7 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -223,7 +223,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
/* this ensures that policy->cpuinfo_min and policy->cpuinfo_max
* are set correctly
*/
- return cpufreq_frequency_table_cpuinfo(policy, pas_freqs);
+ return cpufreq_frequency_table_cpuinfo(policy, pas_freqs, 0);

out_unmap_sdcpwr:
iounmap(sdcpwr_mapbase);
diff --git a/arch/powerpc/platforms/powermac/cpufreq_32.c b/arch/powerpc/platforms/powermac/cpufreq_32.c
index 3104fad..f9805c6 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_32.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_32.c
@@ -408,7 +408,7 @@ static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cur = cur_freq;

cpufreq_frequency_table_get_attr(pmac_cpu_freqs, policy->cpu);
- return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs);
+ return cpufreq_frequency_table_cpuinfo(policy, pmac_cpu_freqs, 0);
}

static u32 read_gpio(struct device_node *np)
diff --git a/arch/powerpc/platforms/powermac/cpufreq_64.c b/arch/powerpc/platforms/powermac/cpufreq_64.c
index 7ba4234..cb7869b 100644
--- a/arch/powerpc/platforms/powermac/cpufreq_64.c
+++ b/arch/powerpc/platforms/powermac/cpufreq_64.c
@@ -365,7 +365,7 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpufreq_frequency_table_get_attr(g5_cpu_freqs, policy->cpu);

return cpufreq_frequency_table_cpuinfo(policy,
- g5_cpu_freqs);
+ g5_cpu_freqs, 0);
}


diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 2845566..abca529 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -819,7 +819,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
perf->state = 0;

- result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table, 0);
if (result)
goto err_freqfree;

diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 5d7f53f..f06567e 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -167,7 +167,8 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
if (ret)
return ret;

- ret = cpufreq_frequency_table_cpuinfo(policy, freq_table[cur_cluster]);
+ ret = cpufreq_frequency_table_cpuinfo(policy, freq_table[cur_cluster],
+ 0);
if (ret) {
dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
policy->cpu, cur_cluster);
diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c
index 995511e80..65fc627 100644
--- a/drivers/cpufreq/blackfin-cpufreq.c
+++ b/drivers/cpufreq/blackfin-cpufreq.c
@@ -211,7 +211,7 @@ static int __bfin_cpu_init(struct cpufreq_policy *policy)

policy->cur = cclk;
cpufreq_frequency_table_get_attr(bfin_freq_table, policy->cpu);
- return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table);
+ return cpufreq_frequency_table_cpuinfo(policy, bfin_freq_table, 0);
}

static struct freq_attr *bfin_freq_attr[] = {
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index ad1fde2..fd2f5f3 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -128,7 +128,7 @@ static int cpu0_cpufreq_init(struct cpufreq_policy *policy)
{
int ret;

- ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
if (ret) {
pr_err("invalid frequency table: %d\n", ret);
return ret;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 2ce86ed..02e57db 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -40,6 +40,7 @@
* also protects the cpufreq_cpu_data array.
*/
static struct cpufreq_driver *cpufreq_driver;
+static bool cpufreq_boost_enabled;
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */
@@ -315,6 +316,30 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/*********************************************************************
* SYSFS INTERFACE *
*********************************************************************/
+ssize_t show_boost(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", cpufreq_boost_enabled);
+}
+
+static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, enable;
+
+ ret = sscanf(buf, "%d", &enable);
+ if (ret != 1 || enable < 0 || enable > 1)
+ return -EINVAL;
+
+ if (cpufreq_boost_trigger_state(enable)) {
+ pr_err("%s: Cannot %sable boost!\n", __func__,
+ enable ? "en" : "dis");
+ return -EINVAL;
+ }
+
+ return count;
+}
+define_one_global_rw(boost);

static struct cpufreq_governor *__find_governor(const char *str_governor)
{
@@ -1896,6 +1921,55 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
};

/*********************************************************************
+ * BOOST *
+ *********************************************************************/
+int cpufreq_boost_trigger_state(int state)
+{
+ struct cpufreq_frequency_table *freq_table;
+ struct cpufreq_policy *policy;
+ unsigned long flags;
+ int ret = 0, cpu;
+
+ if (!cpufreq_driver->boost_supported)
+ return -ENODEV;
+
+ if (cpufreq_boost_enabled != state) {
+ if (cpufreq_driver->set_boost_freq) {
+ ret = cpufreq_driver->set_boost_freq(state);
+ if (ret) {
+ pr_err("%s: BOOST cannot enable (%d)\n",
+ __func__, ret);
+ return ret;
+ }
+ }
+
+ for_each_possible_cpu(cpu) {
+ policy = cpufreq_cpu_get(cpu);
+ freq_table = cpufreq_frequency_get_table(cpu);
+ if (policy && freq_table) {
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
+ cpufreq_frequency_table_cpuinfo(policy,
+ freq_table,
+ state);
+ cpufreq_boost_enabled = state;
+ write_unlock_irqrestore(&cpufreq_driver_lock,
+ flags);
+ }
+ }
+ }
+
+ pr_debug("%s: cpufreq BOOST %s\n", __func__,
+ state ? "enabled" : "disabled");
+
+ return 0;
+}
+
+int cpufreq_boost_state(void)
+{
+ return cpufreq_boost_enabled;
+}
+
+/*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER *
*********************************************************************/

@@ -1934,6 +2008,15 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
cpufreq_driver = driver_data;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);

+ if (cpufreq_driver->boost_supported) {
+ ret = cpufreq_sysfs_create_file(&(boost.attr));
+ if (ret) {
+ pr_err("%s: cannot register global boost sysfs file\n",
+ __func__);
+ goto err_null_driver;
+ }
+ }
+
ret = subsys_interface_register(&cpufreq_interface);
if (ret)
goto err_null_driver;
@@ -1990,6 +2073,10 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
pr_debug("unregistering driver %s\n", driver->name);

subsys_interface_unregister(&cpufreq_interface);
+
+ if (cpufreq_driver->boost_supported)
+ cpufreq_sysfs_remove_file(&(boost.attr));
+
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);

write_lock_irqsave(&cpufreq_driver_lock, flags);
diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c
index ee142c4..a50b6f5 100644
--- a/drivers/cpufreq/cris-artpec3-cpufreq.c
+++ b/drivers/cpufreq/cris-artpec3-cpufreq.c
@@ -82,7 +82,7 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 1000000; /* 1ms */
policy->cur = cris_freq_get_cpu_frequency(0);

- result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table, 0);
if (result)
return (result);

diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c
index 1295223..3e09693 100644
--- a/drivers/cpufreq/cris-etraxfs-cpufreq.c
+++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c
@@ -81,7 +81,7 @@ static int cris_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 1000000; /* 1ms */
policy->cur = cris_freq_get_cpu_frequency(0);

- result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table, 0);
if (result)
return (result);

diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c
index c33c76c..e1ec64f 100644
--- a/drivers/cpufreq/davinci-cpufreq.c
+++ b/drivers/cpufreq/davinci-cpufreq.c
@@ -137,7 +137,7 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)

policy->cur = davinci_getspeed(0);

- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
if (result) {
pr_err("%s: cpufreq_frequency_table_cpuinfo() failed",
__func__);
diff --git a/drivers/cpufreq/dbx500-cpufreq.c b/drivers/cpufreq/dbx500-cpufreq.c
index 6ec6539..30b89eb 100644
--- a/drivers/cpufreq/dbx500-cpufreq.c
+++ b/drivers/cpufreq/dbx500-cpufreq.c
@@ -87,7 +87,7 @@ static int __cpuinit dbx500_cpufreq_init(struct cpufreq_policy *policy)
int res;

/* get policy fields based on the table */
- res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ res = cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
if (!res)
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
else {
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index 37380fb..1eea205 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -400,7 +400,8 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
policy->cur = fsb * current_multiplier;

- ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0]);
+ ret = cpufreq_frequency_table_cpuinfo(policy, &centaur->freq_table[0],
+ 0);
if (ret) {
kfree(centaur);
return ret;
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
index 658d860..6700524 100644
--- a/drivers/cpufreq/elanfreq.c
+++ b/drivers/cpufreq/elanfreq.c
@@ -223,7 +223,7 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = elanfreq_get_cpu_frequency(0);

- result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, elanfreq_table, 0);
if (result)
return result;

diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 3197d88..32ec2f6 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -253,7 +253,8 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)

cpumask_setall(policy->cpus);

- return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+ return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table,
+ 0);
}

static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
index 0c74018..936e239 100644
--- a/drivers/cpufreq/exynos5440-cpufreq.c
+++ b/drivers/cpufreq/exynos5440-cpufreq.c
@@ -323,7 +323,7 @@ static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
int ret;

- ret = cpufreq_frequency_table_cpuinfo(policy, dvfs_info->freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, dvfs_info->freq_table, 0);
if (ret) {
dev_err(dvfs_info->dev, "Invalid frequency table: %d\n", ret);
return ret;
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index d7a7966..f1a4d785 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -21,7 +21,8 @@
*********************************************************************/

int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
- struct cpufreq_frequency_table *table)
+ struct cpufreq_frequency_table *table,
+ int boost)
{
unsigned int min_freq = ~0;
unsigned int max_freq = 0;
@@ -31,9 +32,11 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
unsigned int freq = table[i].frequency;
if (freq == CPUFREQ_ENTRY_INVALID) {
pr_debug("table entry %u is invalid, skipping\n", i);
-
continue;
}
+ if (!boost && table[i].index == CPUFREQ_BOOST_FREQ)
+ continue;
+
pr_debug("table entry %u: %u kHz, %u index\n",
i, freq, table[i].index);
if (freq < min_freq)
@@ -171,7 +174,8 @@ static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/**
* show_available_freqs - show available frequencies for the specified CPU
*/
-static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
+ int show_boost)
{
unsigned int i = 0;
unsigned int cpu = policy->cpu;
@@ -186,22 +190,42 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue;
+ if (show_boost && table[i].index != CPUFREQ_BOOST_FREQ)
+ continue;
+ if (!show_boost && table[i].index == CPUFREQ_BOOST_FREQ)
+ continue;
+
count += sprintf(&buf[count], "%d ", table[i].frequency);
}
count += sprintf(&buf[count], "\n");

return count;
-
}

-struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
- .attr = { .name = "scaling_available_frequencies",
- .mode = 0444,
- },
- .show = show_available_freqs,
-};
+/**
+ * show_scaling_available_frequencies - show normal boost frequencies for
+ * the specified CPU
+ */
+static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, 0);
+}
+cpufreq_attr_available_freq(scaling_available);
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);

+/**
+ * show_available_boost_freqs - show available boost frequencies for
+ * the specified CPU
+ */
+static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, 1);
+}
+cpufreq_attr_available_freq(scaling_boost);
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs);
+
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index c0075db..7a29a92 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -335,7 +335,7 @@ acpi_cpufreq_cpu_init (
}
}

- result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table, 0);
if (result) {
goto err_freqfree;
}
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index b78bc35..9d09c29 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -172,7 +172,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
{
int ret;

- ret = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
if (ret) {
dev_err(cpu_dev, "invalid frequency table: %d\n", ret);
return ret;
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index b2644af..03b95bd 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -131,7 +131,8 @@ static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 5000; /* 5uS */
policy->cur = kirkwood_cpufreq_get_cpu_frequency(0);

- result = cpufreq_frequency_table_cpuinfo(policy, kirkwood_freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, kirkwood_freq_table,
+ 0);
if (result)
return result;

diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index b448638..ef2cea3 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -921,7 +921,7 @@ static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 200000; /* nsec */
policy->cur = calc_speed(longhaul_get_cpu_mult());

- ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, longhaul_table, 0);
if (ret)
return ret;

diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index d539127..fc8bcbb 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -136,7 +136,7 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpu);

return cpufreq_frequency_table_cpuinfo(policy,
- &loongson2_clockmod_table[0]);
+ &loongson2_clockmod_table[0], 0);
}

static int loongson2_cpufreq_verify(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c
index cdd6291..1b35285 100644
--- a/drivers/cpufreq/maple-cpufreq.c
+++ b/drivers/cpufreq/maple-cpufreq.c
@@ -184,7 +184,7 @@ static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpufreq_frequency_table_get_attr(maple_cpu_freqs, policy->cpu);

return cpufreq_frequency_table_cpuinfo(policy,
- maple_cpu_freqs);
+ maple_cpu_freqs, 0);
}


diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 0279d18..30473ae 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -191,7 +191,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)

atomic_inc_return(&freq_table_users);

- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
if (result)
goto fail_table;

diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index 421ef37..8f36e69 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -239,7 +239,7 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 10000001;
policy->cur = stock_freq;

- return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0]);
+ return cpufreq_frequency_table_cpuinfo(policy, &p4clockmod_table[0], 0);
}


diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index ea0222a..4ffe7d5 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -167,7 +167,7 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 200000;
policy->cur = busfreq * max_multiplier;

- result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio);
+ result = cpufreq_frequency_table_cpuinfo(policy, clock_ratio, 0);
if (result)
return result;

diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index 53888da..73c8345 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -683,7 +683,7 @@ static int __cpuinit powernow_cpu_init(struct cpufreq_policy *policy)

cpufreq_frequency_table_get_attr(powernow_table, policy->cpu);

- return cpufreq_frequency_table_cpuinfo(policy, powernow_table);
+ return cpufreq_frequency_table_cpuinfo(policy, powernow_table, 0);
}

static int powernow_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index b828efe..67d3283 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1156,7 +1156,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
pr_debug("policy current frequency %d kHz\n", pol->cur);

/* min/max the cpu is capable of */
- if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table)) {
+ if (cpufreq_frequency_table_cpuinfo(pol, data->powernow_table), 0) {
printk(KERN_ERR FW_BUG PFX "invalid powernow_table\n");
powernow_k8_cpu_exit_acpi(data);
kfree(data->powernow_table);
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c
index e577a1d..b50d9f1 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq.c
@@ -127,7 +127,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)

/* this ensures that policy->cpuinfo_min
* and policy->cpuinfo_max are set correctly */
- return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs);
+ return cpufreq_frequency_table_cpuinfo(policy, cbe_freqs, 0);
}

static int cbe_cpufreq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c
index 9e5bc8e..cd5d74a 100644
--- a/drivers/cpufreq/pxa2xx-cpufreq.c
+++ b/drivers/cpufreq/pxa2xx-cpufreq.c
@@ -453,10 +453,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
find_freq_tables(&pxa255_freq_table, &pxa255_freqs);
pr_info("PXA255 cpufreq using %s frequency table\n",
pxa255_turbo_table ? "turbo" : "run");
- cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table);
+ cpufreq_frequency_table_cpuinfo(policy, pxa255_freq_table, 0);
}
else if (cpu_is_pxa27x())
- cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table);
+ cpufreq_frequency_table_cpuinfo(policy, pxa27x_freq_table, 0);

printk(KERN_INFO "PXA CPU frequency change support initialized\n");

diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c
index 15d60f8..c16d3f8 100644
--- a/drivers/cpufreq/pxa3xx-cpufreq.c
+++ b/drivers/cpufreq/pxa3xx-cpufreq.c
@@ -108,7 +108,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
pxa3xx_freqs_num = num;
pxa3xx_freqs_table = table;

- return cpufreq_frequency_table_cpuinfo(policy, table);
+ return cpufreq_frequency_table_cpuinfo(policy, table, 0);
}

static void __update_core_freq(struct pxa3xx_freq_info *info)
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
index 4f1881e..ea2b626 100644
--- a/drivers/cpufreq/s3c2416-cpufreq.c
+++ b/drivers/cpufreq/s3c2416-cpufreq.c
@@ -494,7 +494,7 @@ static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = (500 * 1000) +
s3c_freq->regulator_latency;

- ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, s3c_freq->freq_table, 0);
if (ret)
goto err_freq_table;

diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 27cacb5..137d29b 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -247,7 +247,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
*/
policy->cpuinfo.transition_latency = (500 * 1000) + regulator_latency;

- ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
+ ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table, 0);
if (ret != 0) {
pr_err("Failed to configure frequency table: %d\n",
ret);
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 5c77570..8b7c790 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -557,7 +557,7 @@ static int __init s5pv210_cpu_init(struct cpufreq_policy *policy)

policy->cpuinfo.transition_latency = 40000;

- return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table);
+ return cpufreq_frequency_table_cpuinfo(policy, s5pv210_freq_table, 0);

out_dmc1:
clk_put(dmc0_clk);
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
index f740b13..d809fd0 100644
--- a/drivers/cpufreq/sc520_freq.c
+++ b/drivers/cpufreq/sc520_freq.c
@@ -117,7 +117,7 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 1000000; /* 1ms */
policy->cur = sc520_freq_get_cpu_frequency(0);

- result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, sc520_freq_table, 0);
if (result)
return result;

diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c
index 73adb64..c064d7c 100644
--- a/drivers/cpufreq/sh-cpufreq.c
+++ b/drivers/cpufreq/sh-cpufreq.c
@@ -120,7 +120,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (freq_table) {
int result;

- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
if (!result)
cpufreq_frequency_table_get_attr(freq_table, cpu);
} else {
diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c
index 306ae46..c0345c4 100644
--- a/drivers/cpufreq/sparc-us2e-cpufreq.c
+++ b/drivers/cpufreq/sparc-us2e-cpufreq.c
@@ -324,7 +324,7 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick;

- return cpufreq_frequency_table_cpuinfo(policy, table);
+ return cpufreq_frequency_table_cpuinfo(policy, table, 0);
}

static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c
index c71ee14..27a03b6 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -181,7 +181,7 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick;

- return cpufreq_frequency_table_cpuinfo(policy, table);
+ return cpufreq_frequency_table_cpuinfo(policy, table, 0);
}

static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index 156829f..517e19c 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -178,7 +178,8 @@ static int spear_cpufreq_init(struct cpufreq_policy *policy)
{
int ret;

- ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl);
+ ret = cpufreq_frequency_table_cpuinfo(policy, spear_cpufreq.freq_tbl,
+ 0);
if (ret) {
pr_err("cpufreq_frequency_table_cpuinfo() failed");
return ret;
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index 618e6f4..85b981b 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -403,7 +403,7 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
pr_debug("centrino_cpu_init: cur=%dkHz\n", policy->cur);

ret = cpufreq_frequency_table_cpuinfo(policy,
- per_cpu(centrino_model, policy->cpu)->op_points);
+ per_cpu(centrino_model, policy->cpu)->op_points, 0);
if (ret)
return (ret);

diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index e2e5aa9..711c973 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -349,7 +349,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */
policy->cur = speed;

- result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
+ result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs, 0);
if (result)
return result;

diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index f5a6b70..569e75e 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -329,7 +329,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
policy->cur = speed;

- result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs);
+ result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs, 0);
if (result)
return result;

diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra-cpufreq.c
index c74c0e1..8bf95e0 100644
--- a/drivers/cpufreq/tegra-cpufreq.c
+++ b/drivers/cpufreq/tegra-cpufreq.c
@@ -216,7 +216,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
clk_prepare_enable(emc_clk);
clk_prepare_enable(cpu_clk);

- cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
policy->cur = tegra_getspeed(policy->cpu);
target_cpu_speed[policy->cpu] = policy->cur;
@@ -234,7 +234,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)

static int tegra_cpu_exit(struct cpufreq_policy *policy)
{
- cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ cpufreq_frequency_table_cpuinfo(policy, freq_table, 0);
clk_disable_unprepare(emc_clk);
return 0;
}
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index ab1932c..027442d 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -266,6 +266,10 @@ struct cpufreq_driver {
int (*suspend) (struct cpufreq_policy *policy);
int (*resume) (struct cpufreq_policy *policy);
struct freq_attr **attr;
+
+ /* platform specific boost support code */
+ bool boost_supported;
+ int (*set_boost_freq) (int state);
};

/* flags */
@@ -318,6 +322,10 @@ __ATTR(_name, _perm, show_##_name, NULL)
static struct freq_attr _name = \
__ATTR(_name, 0644, show_##_name, store_##_name)

+#define cpufreq_attr_available_freq(_name) \
+struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
+__ATTR_RO(_name##_frequencies)
+
struct global_attr {
struct attribute attr;
ssize_t (*show)(struct kobject *kobj,
@@ -407,6 +415,9 @@ extern struct cpufreq_governor cpufreq_gov_conservative;
#define CPUFREQ_ENTRY_INVALID ~0
#define CPUFREQ_TABLE_END ~1

+/* Define index for boost frequency */
+#define CPUFREQ_BOOST_FREQ ~2
+
struct cpufreq_frequency_table {
unsigned int index; /* any */
unsigned int frequency; /* kHz - doesn't need to be in ascending
@@ -414,7 +425,8 @@ struct cpufreq_frequency_table {
};

int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
- struct cpufreq_frequency_table *table);
+ struct cpufreq_frequency_table *table,
+ int boost);

int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table);
@@ -425,11 +437,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int relation,
unsigned int *index);

+int cpufreq_boost_trigger_state(int state);
+int cpufreq_boost_state(void);
+
/* the following 3 funtions are for cpufreq core use only */
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);

/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs;

void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);

Viresh Kumar

unread,
Jun 16, 2013, 11:30:02 PM6/16/13
to
Wow!! I am shocked to see these many files getting updated :)

Viresh Kumar

unread,
Jun 17, 2013, 1:50:02 AM6/17/13
to
On 14 June 2013 13:08, Lukasz Majewski <l.maj...@samsung.com> wrote:
> Changes for v2:
> - Removal of cpufreq_boost structure and move its fields to cpufreq_driver
> structure
> - Flag to indicate if global boost attribute is already defined
> - Extent the pr_{err|debbug} functions to show current function names
>
> Changes for v3:
> - Method for reading boost status
> - Removal of cpufreq_frequency_table_max()
> - Extent cpufreq_frequency_table_cpuinfo() to support boost parameter
> - boost_supported flag added to cpufreq_driver struct
> - "boost" sysfs attribute control flag removed
> - One global flag describing state of the boost defined at cpufreq core
> - Rename cpufreq_driver's low_level_boost field to set_boost_freq()
> - Usage of cpufreq_sysfs_{remove|add}_file() routines

Latest change log first please.
Please don't use %sable as discussed earlier.

> + return -EINVAL;
> + }
> +
> + return count;
> +}
> +define_one_global_rw(boost);
>
> static struct cpufreq_governor *__find_governor(const char *str_governor)
> {
> @@ -1896,6 +1921,55 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
> };
>
> /*********************************************************************
> + * BOOST *
> + *********************************************************************/
> +int cpufreq_boost_trigger_state(int state)
> +{
> + struct cpufreq_frequency_table *freq_table;
> + struct cpufreq_policy *policy;
> + unsigned long flags;
> + int ret = 0, cpu;
> +
> + if (!cpufreq_driver->boost_supported)
> + return -ENODEV;

This can't happen. sysfs directory is present only when we
have boost supported.

> + if (cpufreq_boost_enabled != state) {
> + if (cpufreq_driver->set_boost_freq) {
> + ret = cpufreq_driver->set_boost_freq(state);

I thought this routine was for setting boost frequency and not
for enabling boost feature. If boost has to be enabled separately
then this routine must take care of it while setting freq.

So, in other words, this must not be called here.

> + if (ret) {
> + pr_err("%s: BOOST cannot enable (%d)\n",
> + __func__, ret);
> + return ret;
> + }
> + }
> +
> + for_each_possible_cpu(cpu) {
> + policy = cpufreq_cpu_get(cpu);

In case this code is required, it would make more sense to keep list
of all available policies, which we can iterate through.

> + freq_table = cpufreq_frequency_get_table(cpu);
> + if (policy && freq_table) {
> + write_lock_irqsave(&cpufreq_driver_lock, flags);
> + cpufreq_frequency_table_cpuinfo(policy,
> + freq_table,
> + state);

We obviously don't need the last param to this routine and so bunch
of changes you did in this patch.

cpufreq_frequency_table_cpuinfo() can itself check if boost is enabled
or not.

> + cpufreq_boost_enabled = state;
> + write_unlock_irqrestore(&cpufreq_driver_lock,
> + flags);
> + }
> + }

I am not sure if this is required at all. Or what complications can be
there when we update max/min on the fly here.

> + }
> +
> + pr_debug("%s: cpufreq BOOST %s\n", __func__,
> + state ? "enabled" : "disabled");
> +
> + return 0;
> +}
> +
> +int cpufreq_boost_state(void)

s/cpufreq_boost_state/cpufreq_boost_enabled

> +{
> + return cpufreq_boost_enabled;

s/cpufreq_boost_enabled/boost_enabled
This part looked good :)
Maybe, this instead of above two if statements:

if (show_boost ^ (table[i].index == CPUFREQ_BOOST_FREQ))
continue

> count += sprintf(&buf[count], "%d ", table[i].frequency);
> }
> count += sprintf(&buf[count], "\n");
>
> return count;
> -
> }
>
> -struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
> - .attr = { .name = "scaling_available_frequencies",
> - .mode = 0444,
> - },
> - .show = show_available_freqs,
> -};
> +/**
> + * show_scaling_available_frequencies - show normal boost frequencies for

s/boost /

> + * the specified CPU
> + */
> +static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy,
> + char *buf)
> +{
> + return show_available_freqs(policy, buf, 0);
> +}
> +cpufreq_attr_available_freq(scaling_available);
> EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);
>
> +/**
> + * show_available_boost_freqs - show available boost frequencies for
> + * the specified CPU
> + */
> +static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy,
> + char *buf)
> +{
> + return show_available_freqs(policy, buf, 1);
> +}
> +cpufreq_attr_available_freq(scaling_boost);
> +EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs);
> +
> /*
> * if you use these, you must assure that the frequency table is valid
> * all the time between get_attr and put_attr!

> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index ab1932c..027442d 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -266,6 +266,10 @@ struct cpufreq_driver {
> int (*suspend) (struct cpufreq_policy *policy);
> int (*resume) (struct cpufreq_policy *policy);
> struct freq_attr **attr;
> +
> + /* platform specific boost support code */
> + bool boost_supported;
> + int (*set_boost_freq) (int state);
> };
>
> /* flags */
> @@ -318,6 +322,10 @@ __ATTR(_name, _perm, show_##_name, NULL)
> static struct freq_attr _name = \
> __ATTR(_name, 0644, show_##_name, store_##_name)
>
> +#define cpufreq_attr_available_freq(_name) \
> +struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
> +__ATTR_RO(_name##_frequencies)

What is this doing in cpufreq.h? It will only be used by freq_table.c file.


Again, I couldn't see how boost freqs are getting used? You have
probably made them part of normal freq range here and so they
might be used during normal operations. But we wanted it to be
used only when we have few cpus on... etc.. Where is that logic?

Lukasz Majewski

unread,
Jun 17, 2013, 1:50:03 AM6/17/13
to
Hmm, CPUFREQ framework is quite popular :-).

Changing this one particular function, seemed to be the best solution.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 17, 2013, 3:20:02 AM6/17/13
to
On Mon, 17 Jun 2013 11:13:18 +0530, Viresh Kumar wrote:
> On 14 June 2013 13:08, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > Changes for v2:
> > - Removal of cpufreq_boost structure and move its fields to
> > cpufreq_driver structure
> > - Flag to indicate if global boost attribute is already defined
> > - Extent the pr_{err|debbug} functions to show current function
> > names
> >
> > Changes for v3:
> > - Method for reading boost status
> > - Removal of cpufreq_frequency_table_max()
> > - Extent cpufreq_frequency_table_cpuinfo() to support boost
> > parameter
> > - boost_supported flag added to cpufreq_driver struct
> > - "boost" sysfs attribute control flag removed
> > - One global flag describing state of the boost defined at cpufreq
> > core
> > - Rename cpufreq_driver's low_level_boost field to set_boost_freq()
> > - Usage of cpufreq_sysfs_{remove|add}_file() routines
>
> Latest change log first please.

Ok.
My bad. I've overlooked this one.
I know, that we shall not look into the future. But this method will be
used when somebody would like to enable boost from kernel. Let's say
new governor or such :-).

I can remove this and add it later, but I think, that it is safer to
add it straightaway.

>
> > + if (cpufreq_boost_enabled != state) {
> > + if (cpufreq_driver->set_boost_freq) {
> > + ret = cpufreq_driver->set_boost_freq(state);
>
> I thought this routine was for setting boost frequency and not
> for enabling boost feature. If boost has to be enabled separately
> then this routine must take care of it while setting freq.
>
> So, in other words, this must not be called here.

This function explicitly follows current logic of acpi-cpufreq.c.

I would like to avoid modifying legacy/working code as much as
possible (especially when I hadn't yet received any feedback about
acpi-cpufreq.c file changes).


>
> > + if (ret) {
> > + pr_err("%s: BOOST cannot enable
> > (%d)\n",
> > + __func__, ret);
> > + return ret;
> > + }
> > + }
> > +
> > + for_each_possible_cpu(cpu) {
> > + policy = cpufreq_cpu_get(cpu);
>
> In case this code is required, it would make more sense to keep list
> of all available policies, which we can iterate through.

Maybe I don't get the big picture, but why we cannot iterate
through possible CPUs? At least one shall have valid policy and
freq_table combination.

I've already proposed list of all policies (at v1), but we decided to
abandon this idea.

In which way list is better than iteration through all possible per-cpu
variables, which store policies?


>
> > + freq_table =
> > cpufreq_frequency_get_table(cpu);
> > + if (policy && freq_table) {
> > +
> > write_lock_irqsave(&cpufreq_driver_lock, flags);
> > +
> > cpufreq_frequency_table_cpuinfo(policy,
> > +
> > freq_table,
> > +
> > state);
>
> We obviously don't need the last param to this routine and so bunch
> of changes you did in this patch.
>
> cpufreq_frequency_table_cpuinfo() can itself check if boost is enabled
> or not.

Yes, you are right. We can check if boost is supported and enabled
inside this function.

>
> > + cpufreq_boost_enabled = state;
> > +
> > write_unlock_irqrestore(&cpufreq_driver_lock,
> > + flags);
> > + }
> > + }
>
> I am not sure if this is required at all. Or what complications can be
> there when we update max/min on the fly here.

Correct me if I'm wrong, but I'm using scripts for tests which run
simultaneously and enables/disables boost feature. I don't recall if
there is a lock at sysfs, which would prevent from simultaneous write
to the "boost" sysfs attribute.

I will doubble check that.

>
> > + }
> > +
> > + pr_debug("%s: cpufreq BOOST %s\n", __func__,
> > + state ? "enabled" : "disabled");
> > +
> > + return 0;
> > +}
> > +
> > +int cpufreq_boost_state(void)
>
> s/cpufreq_boost_state/cpufreq_boost_enabled

OK.
Yes. Good point.

>
> > count += sprintf(&buf[count], "%d ",
> > table[i].frequency); }
> > count += sprintf(&buf[count], "\n");
> >
> > return count;
> > -
> > }
> >
> > -struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
> > - .attr = { .name = "scaling_available_frequencies",
> > - .mode = 0444,
> > - },
> > - .show = show_available_freqs,
> > -};
> > +/**
> > + * show_scaling_available_frequencies - show normal boost
> > frequencies for
>
> s/boost /

Ok.
I wanted to add those #defines to the place where other similar ones
are placed.

I can put it to freq_table.c.

>
>
> Again, I couldn't see how boost freqs are getting used? You have
> probably made them part of normal freq range here and so they
> might be used during normal operations. But we wanted it to be
> used only when we have few cpus on... etc.. Where is that logic?

The logic is as follow:
- cpufreq_driver exports .attr field. When driver supports boost then
two attributes are exported (even when boost is not enabled, but
supported):
- scaling_available_frequencies (only normal frequencies - this
attribute is unchanged)
- scaling_boost_frequencies - list possible boost frequencies.

When boost is not supported - then only scaling_available_frequencies
is exported (as it is done now).

Please refer to patch 3/3.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 17, 2013, 3:50:01 AM6/17/13
to
On 17 June 2013 12:45, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Mon, 17 Jun 2013 11:13:18 +0530, Viresh Kumar wrote:
>> On 14 June 2013 13:08, Lukasz Majewski <l.maj...@samsung.com> wrote:

>> > +int cpufreq_boost_trigger_state(int state) +{

>> > + if (!cpufreq_driver->boost_supported)
>> > + return -ENODEV;
>>
>> This can't happen. sysfs directory is present only when we
>> have boost supported.
>
> I know, that we shall not look into the future. But this method will be
> used when somebody would like to enable boost from kernel. Let's say
> new governor or such :-).

We don't know if that would be acceptable or not as of now.

> I can remove this and add it later, but I think, that it is safer to
> add it straightaway.

Remove it for now.

>>
>> > + if (cpufreq_boost_enabled != state) {
>> > + if (cpufreq_driver->set_boost_freq) {
>> > + ret = cpufreq_driver->set_boost_freq(state);
>>
>> I thought this routine was for setting boost frequency and not
>> for enabling boost feature. If boost has to be enabled separately
>> then this routine must take care of it while setting freq.
>>
>> So, in other words, this must not be called here.
>
> This function explicitly follows current logic of acpi-cpufreq.c.
>
> I would like to avoid modifying legacy/working code as much as
> possible (especially when I hadn't yet received any feedback about
> acpi-cpufreq.c file changes).

Hmm.. I saw that code now. You are talking about: boost_set_msrs ??

So, this function has nothing to do with set_boost_freq() but
enable_boost(). Rename your function similarly and keep this code.

>> > + if (ret) {
>> > + pr_err("%s: BOOST cannot enable
>> > (%d)\n",
>> > + __func__, ret);
>> > + return ret;
>> > + }
>> > + }
>> > +
>> > + for_each_possible_cpu(cpu) {
>> > + policy = cpufreq_cpu_get(cpu);
>>
>> In case this code is required, it would make more sense to keep list
>> of all available policies, which we can iterate through.
>
> Maybe I don't get the big picture, but why we cannot iterate
> through possible CPUs? At least one shall have valid policy and
> freq_table combination.

Many cpus share same policy structure and so iterating over all of them
isn't a very good idea. Either keep a mask of cpus already iterated,
copy policy->cpus to it on each iteration. If a cpu is already done
skip loop for it.

OR keep a list of policies. I would prefer the later (do it in a separate
patch), as this can be used later too.

> I've already proposed list of all policies (at v1), but we decided to
> abandon this idea.

I don't remember why it was there but reason wasn't good enough to
keep it.

>> I am not sure if this is required at all. Or what complications can be
>> there when we update max/min on the fly here.
>
> Correct me if I'm wrong, but I'm using scripts for tests which run
> simultaneously and enables/disables boost feature. I don't recall if
> there is a lock at sysfs, which would prevent from simultaneous write
> to the "boost" sysfs attribute.
>
> I will doubble check that.

It isn't about a crash but how cpufreq subsystem works. I will think over
it later too, for now you can keep it.

>> > +{
>> > + return cpufreq_boost_enabled;
>>
>> s/cpufreq_boost_enabled/boost_enabled

??

>> > @@ -318,6 +322,10 @@ __ATTR(_name, _perm, show_##_name, NULL)
>> > static struct freq_attr _name = \
>> > __ATTR(_name, 0644, show_##_name, store_##_name)
>> >
>> > +#define cpufreq_attr_available_freq(_name) \
>> > +struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
>> > +__ATTR_RO(_name##_frequencies)
>>
>> What is this doing in cpufreq.h? It will only be used by freq_table.c
>> file.
>
> I wanted to add those #defines to the place where other similar ones
> are placed.

That's not how these or any other declaration should be placed. By adding
these to cpufreq.h, you are inviting other parts of kernel to use them.
Which we don't want.

> I can put it to freq_table.c.

Thanks.

>> Again, I couldn't see how boost freqs are getting used? You have
>> probably made them part of normal freq range here and so they
>> might be used during normal operations. But we wanted it to be
>> used only when we have few cpus on... etc.. Where is that logic?
>
> The logic is as follow:
> - cpufreq_driver exports .attr field. When driver supports boost then
> two attributes are exported (even when boost is not enabled, but
> supported):
> - scaling_available_frequencies (only normal frequencies - this
> attribute is unchanged)
> - scaling_boost_frequencies - list possible boost frequencies.
>
> When boost is not supported - then only scaling_available_frequencies
> is exported (as it is done now).

You are missing the whole point behind keeping this patchset. Its not
about how to expose boost freqs to sysfs (that's what you are talking
about) but to use these frequencies on the fly. Some part of kernel
code would be setting these frequencies in real hardware. Who will
set these frequencies? On what basis? How do we ensure we don't
burn your chip?

Lukasz Majewski

unread,
Jun 17, 2013, 5:10:02 AM6/17/13
to
On Mon, 17 Jun 2013 09:43:27 +0200, Viresh Kumar wrote:
> On 17 June 2013 12:45, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > On Mon, 17 Jun 2013 11:13:18 +0530, Viresh Kumar wrote:
> >> On 14 June 2013 13:08, Lukasz Majewski <l.maj...@samsung.com>
> >> wrote:
>
> >> > +int cpufreq_boost_trigger_state(int state) +{
>
> >> > + if (!cpufreq_driver->boost_supported)
> >> > + return -ENODEV;
> >>
> >> This can't happen. sysfs directory is present only when we
> >> have boost supported.
> >
> > I know, that we shall not look into the future. But this method
> > will be used when somebody would like to enable boost from kernel.
> > Let's say new governor or such :-).
>
> We don't know if that would be acceptable or not as of now.
>
> > I can remove this and add it later, but I think, that it is safer to
> > add it straightaway.
>
> Remove it for now.

Ok.

>
> >>
> >> > + if (cpufreq_boost_enabled != state) {
> >> > + if (cpufreq_driver->set_boost_freq) {
> >> > + ret =
> >> > cpufreq_driver->set_boost_freq(state);
> >>
> >> I thought this routine was for setting boost frequency and not
> >> for enabling boost feature. If boost has to be enabled separately
> >> then this routine must take care of it while setting freq.
> >>
> >> So, in other words, this must not be called here.
> >
> > This function explicitly follows current logic of acpi-cpufreq.c.
> >
> > I would like to avoid modifying legacy/working code as much as
> > possible (especially when I hadn't yet received any feedback about
> > acpi-cpufreq.c file changes).
>
> Hmm.. I saw that code now. You are talking about: boost_set_msrs ??
>
> So, this function has nothing to do with set_boost_freq() but
> enable_boost(). Rename your function similarly and keep this code.

Ok.

>
> >> > + if (ret) {
> >> > + pr_err("%s: BOOST cannot enable
> >> > (%d)\n",
> >> > + __func__, ret);
> >> > + return ret;
> >> > + }
> >> > + }
> >> > +
> >> > + for_each_possible_cpu(cpu) {
> >> > + policy = cpufreq_cpu_get(cpu);
> >>
> >> In case this code is required, it would make more sense to keep
> >> list of all available policies, which we can iterate through.
> >
> > Maybe I don't get the big picture, but why we cannot iterate
> > through possible CPUs? At least one shall have valid policy and
> > freq_table combination.
>
> Many cpus share same policy structure and so iterating over all of
> them isn't a very good idea. Either keep a mask of cpus already
> iterated, copy policy->cpus to it on each iteration. If a cpu is
> already done skip loop for it.

This is the situation, which I wanted to avoid. Policy has the
policy->cpus mask already implemented, but we don't know how/where to
hook to them (one solution would be to start from cpu0, but for some
reason I'm reluctant to do it in this way).

>
> OR keep a list of policies. I would prefer the later (do it in a
> separate patch), as this can be used later too.

I will declare a boost_policy list at cpufreq.c. Then I will add policy
to it, when cpufreq_add_dev() is called.

>
> > I've already proposed list of all policies (at v1), but we decided
> > to abandon this idea.
>
> I don't remember why it was there but reason wasn't good enough to
> keep it.

:-). Lets try with list.

>
> >> I am not sure if this is required at all. Or what complications
> >> can be there when we update max/min on the fly here.
> >
> > Correct me if I'm wrong, but I'm using scripts for tests which run
> > simultaneously and enables/disables boost feature. I don't recall if
> > there is a lock at sysfs, which would prevent from simultaneous
> > write to the "boost" sysfs attribute.
> >
> > I will doubble check that.
>
> It isn't about a crash but how cpufreq subsystem works. I will think
> over it later too, for now you can keep it.

OK.

>
> >> > +{
> >> > + return cpufreq_boost_enabled;
> >>
> >> s/cpufreq_boost_enabled/boost_enabled
>
> ??

I will change the name.

>
> >> > @@ -318,6 +322,10 @@ __ATTR(_name, _perm, show_##_name, NULL)
> >> > static struct freq_attr _name = \
> >> > __ATTR(_name, 0644, show_##_name, store_##_name)
> >> >
> >> > +#define cpufreq_attr_available_freq(_name) \
> >> > +struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
> >> > +__ATTR_RO(_name##_frequencies)
> >>
> >> What is this doing in cpufreq.h? It will only be used by
> >> freq_table.c file.
> >
> > I wanted to add those #defines to the place where other similar ones
> > are placed.
>
> That's not how these or any other declaration should be placed. By
> adding these to cpufreq.h, you are inviting other parts of kernel to
> use them. Which we don't want.
>
> > I can put it to freq_table.c.
>
> Thanks.

Ok. I will keep the code local.

>
> >> Again, I couldn't see how boost freqs are getting used? You have
> >> probably made them part of normal freq range here and so they
> >> might be used during normal operations. But we wanted it to be
> >> used only when we have few cpus on... etc.. Where is that logic?
> >
> > The logic is as follow:
> > - cpufreq_driver exports .attr field. When driver supports boost
> > then two attributes are exported (even when boost is not enabled,
> > but supported):
> > - scaling_available_frequencies (only normal frequencies -
> > this attribute is unchanged)
> > - scaling_boost_frequencies - list possible boost
> > frequencies.
> >
> > When boost is not supported - then only
> > scaling_available_frequencies is exported (as it is done now).
>
> You are missing the whole point behind keeping this patchset. Its not
> about how to expose boost freqs to sysfs (that's what you are talking
> about) but to use these frequencies on the fly.

Two separate things:

1. I think, that scaling_available_frequencies [*] attribute has to
stay unchanged (this is how userspace sees the API). Linus would
we very unhappy :-) if we had changed public API.

x86 guys, please correct me, but I think that [*] will be not
changed (expanded) when Intel's HW boost is enabled at acpi-cpufreq.c
code.

The scaling_boost_frequencies is only visible when driver (and
probably soc maintainer) is ready to handle boosting. It shows over
clocked frequencies.

2. How we would control boost?
- To enable this you must mark IDs for some freqs as
CPUFREQ_BOOST_FREQ.
- The cpufreq_boost.boost_supported flag needs to be true (set at
cpufreq driver code)
- One needs to enable boosting by sysfs or call
cpufreq_boost_trigger_state(1); The latter will not work when
cpufreq_driver->boost_supported is not set.

I assume that when somebody takes those three above steps, then he is
aware that boost is working on his machine.

How one can control the boost? I'm now (on my setup) using thermal
subsystem. I set proper trip points and when one of them is met, then
boost is disabled. Moreover the thermal governor (stepwise) also
reduces frequency.

It works stable with v3.10 (with 3.8 there were some bugs - now they
are fixed).


The core acpi-cpufreq.c code hadn't been changed by me, so I assume
that it will work as before.

> Some part of kernel
> code would be setting these frequencies in real hardware. Who will
> set these frequencies?

Those freqs are set by ->target() callback (when allowed)

> On what basis? How do we ensure we don't
> burn your chip?

Thermal subsystem is a good example here. Another may be a
governor, or even scheduler.


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 17, 2013, 5:20:02 AM6/17/13
to
On 17 June 2013 14:38, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Mon, 17 Jun 2013 09:43:27 +0200, Viresh Kumar wrote:

>> Many cpus share same policy structure and so iterating over all of
>> them isn't a very good idea. Either keep a mask of cpus already
>> iterated, copy policy->cpus to it on each iteration. If a cpu is
>> already done skip loop for it.
>
> This is the situation, which I wanted to avoid. Policy has the
> policy->cpus mask already implemented, but we don't know how/where to
> hook to them (one solution would be to start from cpu0, but for some
> reason I'm reluctant to do it in this way).

We could have started from any cpu. Result and performance would have
been same.

>> OR keep a list of policies. I would prefer the later (do it in a
>> separate patch), as this can be used later too.
>
> I will declare a boost_policy list at cpufreq.c. Then I will add policy
> to it, when cpufreq_add_dev() is called.

This list doesn't have anything to do with boost. Its just a list of
all policies.

>> >> Again, I couldn't see how boost freqs are getting used? You have
>> >> probably made them part of normal freq range here and so they
>> >> might be used during normal operations. But we wanted it to be
>> >> used only when we have few cpus on... etc.. Where is that logic?
>> >
>> > The logic is as follow:
>> > - cpufreq_driver exports .attr field. When driver supports boost
>> > then two attributes are exported (even when boost is not enabled,
>> > but supported):
>> > - scaling_available_frequencies (only normal frequencies -
>> > this attribute is unchanged)
>> > - scaling_boost_frequencies - list possible boost
>> > frequencies.
>> >
>> > When boost is not supported - then only
>> > scaling_available_frequencies is exported (as it is done now).
>>
>> You are missing the whole point behind keeping this patchset. Its not
>> about how to expose boost freqs to sysfs (that's what you are talking
>> about) but to use these frequencies on the fly.
>
> Two separate things:
>
> 1. I think, that scaling_available_frequencies [*] attribute has to
> stay unchanged (this is how userspace sees the API). Linus would
> we very unhappy :-) if we had changed public API.

I never asked to modify it. :)

> x86 guys, please correct me, but I think that [*] will be not
> changed (expanded) when Intel's HW boost is enabled at acpi-cpufreq.c
> code.
>
> The scaling_boost_frequencies is only visible when driver (and
> probably soc maintainer) is ready to handle boosting. It shows over
> clocked frequencies.

Correct.

> 2. How we would control boost?
> - To enable this you must mark IDs for some freqs as
> CPUFREQ_BOOST_FREQ.
> - The cpufreq_boost.boost_supported flag needs to be true (set at
> cpufreq driver code)
> - One needs to enable boosting by sysfs or call
> cpufreq_boost_trigger_state(1); The latter will not work when
> cpufreq_driver->boost_supported is not set.
>
> I assume that when somebody takes those three above steps, then he is
> aware that boost is working on his machine.

All good until now.

> How one can control the boost? I'm now (on my setup) using thermal
> subsystem. I set proper trip points and when one of them is met, then
> boost is disabled. Moreover the thermal governor (stepwise) also
> reduces frequency.
>
> It works stable with v3.10 (with 3.8 there were some bugs - now they
> are fixed).
>
>
> The core acpi-cpufreq.c code hadn't been changed by me, so I assume
> that it will work as before.

That should adapt your patch in your patchset.

>> Some part of kernel
>> code would be setting these frequencies in real hardware. Who will
>> set these frequencies?
>
> Those freqs are set by ->target() callback (when allowed)

From sysfs?? I thought we are going to have some automatic control
of this stuff from inside kernel. Userspace can't control when to run
on boost freqs.

>> On what basis? How do we ensure we don't
>> burn your chip?
>
> Thermal subsystem is a good example here. Another may be a
> governor, or even scheduler.

So, you are enabling boost from sysfs when your thermal framework
says, you can do it?

That's not going to work. There should be something inside kernel to
take care of this stuff. Otherwise a user may switch on boost accidentally
and may burn his chip.

Lukasz Majewski

unread,
Jun 17, 2013, 6:00:01 AM6/17/13
to
On Mon, 17 Jun 2013 14:48:51 +0530, Viresh Kumar wrote:
> On 17 June 2013 14:38, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > On Mon, 17 Jun 2013 09:43:27 +0200, Viresh Kumar wrote:
>
> >> Many cpus share same policy structure and so iterating over all of
> >> them isn't a very good idea. Either keep a mask of cpus already
> >> iterated, copy policy->cpus to it on each iteration. If a cpu is
> >> already done skip loop for it.
> >
> > This is the situation, which I wanted to avoid. Policy has the
> > policy->cpus mask already implemented, but we don't know how/where
> > to hook to them (one solution would be to start from cpu0, but for
> > some reason I'm reluctant to do it in this way).
>
> We could have started from any cpu. Result and performance would have
> been same.

Yes. But I don't want to hardcode anything. Especially starting CPU
number.

>
> >> OR keep a list of policies. I would prefer the later (do it in a
> >> separate patch), as this can be used later too.
> >
> > I will declare a boost_policy list at cpufreq.c. Then I will add
> > policy to it, when cpufreq_add_dev() is called.
>
> This list doesn't have anything to do with boost. Its just a list of
> all policies.

Ok, I see.
>
> >> >> Again, I couldn't see how boost freqs are getting used? You have
> >> >> probably made them part of normal freq range here and so they
> >> >> might be used during normal operations. But we wanted it to be
> >> >> used only when we have few cpus on... etc.. Where is that logic?
> >> >
> >> > The logic is as follow:
> >> > - cpufreq_driver exports .attr field. When driver supports boost
> >> > then two attributes are exported (even when boost is not enabled,
> >> > but supported):
> >> > - scaling_available_frequencies (only normal frequencies
> >> > - this attribute is unchanged)
> >> > - scaling_boost_frequencies - list possible boost
> >> > frequencies.
> >> >
> >> > When boost is not supported - then only
> >> > scaling_available_frequencies is exported (as it is done now).
> >>
> >> You are missing the whole point behind keeping this patchset. Its
> >> not about how to expose boost freqs to sysfs (that's what you are
> >> talking about) but to use these frequencies on the fly.
> >
> > Two separate things:
> >
> > 1. I think, that scaling_available_frequencies [*] attribute has to
> > stay unchanged (this is how userspace sees the API). Linus would
> > we very unhappy :-) if we had changed public API.
>
> I never asked to modify it. :)

:-)

>
> > x86 guys, please correct me, but I think that [*] will be not
> > changed (expanded) when Intel's HW boost is enabled at
> > acpi-cpufreq.c code.
> >
> > The scaling_boost_frequencies is only visible when driver (and
> > probably soc maintainer) is ready to handle boosting. It shows
> > over clocked frequencies.
>
> Correct.

Ok.

>
> > 2. How we would control boost?
> > - To enable this you must mark IDs for some freqs as
> > CPUFREQ_BOOST_FREQ.
> > - The cpufreq_boost.boost_supported flag needs to be true (set at
> > cpufreq driver code)
> > - One needs to enable boosting by sysfs or call
> > cpufreq_boost_trigger_state(1); The latter will not work when
> > cpufreq_driver->boost_supported is not set.
> >
> > I assume that when somebody takes those three above steps, then he
> > is aware that boost is working on his machine.
>
> All good until now.

Ok.

>
> > How one can control the boost? I'm now (on my setup) using thermal
> > subsystem. I set proper trip points and when one of them is met,
> > then boost is disabled. Moreover the thermal governor (stepwise)
> > also reduces frequency.
> >
> > It works stable with v3.10 (with 3.8 there were some bugs - now they
> > are fixed).
> >
> >
> > The core acpi-cpufreq.c code hadn't been changed by me, so I assume
> > that it will work as before.
>
> That should adapt your patch in your patchset.
>
> >> Some part of kernel
> >> code would be setting these frequencies in real hardware. Who will
> >> set these frequencies?
> >
> > Those freqs are set by ->target() callback (when allowed)

The ->target() [*] is called when governor calls it. I didn't change any
of this behaviour.

>
> From sysfs?? I thought we are going to have some automatic control
> of this stuff from inside kernel.

From sysfs I just enable the boost. I do not order from userpace the
cpufreq to run with a particular (boosted) frequency.

When I enable boost - I ask (politely) the cpufreq core to reevaluate
policies and when applicable increase policy->max.

Then governor can use this new frequencies for normal operation.

> Userspace can't control when to run
> on boost freqs.

The control, if boost frequency shall be used or not, is done by
governor when load is appropriate.

>
> >> On what basis? How do we ensure we don't
> >> burn your chip?
> >
> > Thermal subsystem is a good example here. Another may be a
> > governor, or even scheduler.
>
> So, you are enabling boost from sysfs when your thermal framework
> says, you can do it?

No. I'm enabling boost from sysfs (modify policies). This does not mean
that boost frequency is run.

If governor decides, that it shall use boost freq - then it will use
it.
When during heavy workload (and running boost freq), the trip point for
thermal is being passed, the boost shall be disabled.
Moreover stepwise will also reduce frequency with which SoC runs.

>
> That's not going to work. There should be something inside kernel to
> take care of this stuff. Otherwise a user may switch on boost
> accidentally and may burn his chip.

User can by mistake enable boost. But then she/he needs to load SoC to
the maximum (to enable policy->max). After heating up the SoC - the
thermal goes in and disables boost and reduces frequency to cool down
the device.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 17, 2013, 9:20:01 AM6/17/13
to
On 17 June 2013 15:28, Lukasz Majewski <l.maj...@samsung.com> wrote:
> Yes. But I don't want to hardcode anything. Especially starting CPU
> number.

There is nothing wrong with it. for_each_online_cpu() is good enough
on these cases.

>> > How one can control the boost? I'm now (on my setup) using thermal
>> > subsystem. I set proper trip points and when one of them is met,
>> > then boost is disabled. Moreover the thermal governor (stepwise)
>> > also reduces frequency.
>> >
>> > It works stable with v3.10 (with 3.8 there were some bugs - now they
>> > are fixed).
>> >
>> >
>> > The core acpi-cpufreq.c code hadn't been changed by me, so I assume
>> > that it will work as before.
>>
>> That should adapt your patch in your patchset.

??

>> From sysfs?? I thought we are going to have some automatic control
>> of this stuff from inside kernel.
>
> From sysfs I just enable the boost. I do not order from userpace the
> cpufreq to run with a particular (boosted) frequency.
>
> When I enable boost - I ask (politely) the cpufreq core to reevaluate
> policies and when applicable increase policy->max.
>
> Then governor can use this new frequencies for normal operation.

So, with your current patchset in, ondemand or conservative governors
will start using boost frequencies. Which might burn your chip.

Lukasz Majewski

unread,
Jun 17, 2013, 10:00:01 AM6/17/13
to
On Mon, 17 Jun 2013 18:40:50 +0530, Viresh Kumar wrote:
> On 17 June 2013 15:28, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > Yes. But I don't want to hardcode anything. Especially starting CPU
> > number.
>
> There is nothing wrong with it. for_each_online_cpu() is good enough
> on these cases.

I've already changed this code to use list of policies.

I will send this at v4.

>
> >> > How one can control the boost? I'm now (on my setup) using
> >> > thermal subsystem. I set proper trip points and when one of them
> >> > is met, then boost is disabled. Moreover the thermal governor
> >> > (stepwise) also reduces frequency.
> >> >
> >> > It works stable with v3.10 (with 3.8 there were some bugs - now
> >> > they are fixed).
> >> >
> >> >
> >> > The core acpi-cpufreq.c code hadn't been changed by me, so I
> >> > assume that it will work as before.
> >>
> >> That should adapt your patch in your patchset.

Could you explain what do you mean?


>
> ??
>
> >> From sysfs?? I thought we are going to have some automatic control
> >> of this stuff from inside kernel.
> >
> > From sysfs I just enable the boost. I do not order from userpace the
> > cpufreq to run with a particular (boosted) frequency.
> >
> > When I enable boost - I ask (politely) the cpufreq core to
> > reevaluate policies and when applicable increase policy->max.
> >
> > Then governor can use this new frequencies for normal operation.
>
> So, with your current patchset in, ondemand or conservative governors
> will start using boost frequencies. Which might burn your chip.

Two scenarios:
1. Thermal framework is compiled in and enabled (for exynos/other SoC)
-> trip point is reached -> boost is disabled -> frequency is reduced ->
SoC is cooled down.

I think, that thermal framework is a good "safe valve" here.


2. Thermal framework is disabled and user has enabled boost and used
ondemand / conservative governor.
Then execute gzip < /dev/urandom > /dev/null & (on all cores).

Then yes, chip will hang/burn due to crossing operating point (or burn).


What other means of control (despite of thermal) would you consider
applicable?

What comes to my mind is modifying governor logic to count how long the
CPU run with boost enabled and then disable it.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 18, 2013, 2:50:02 AM6/18/13
to
On 17 June 2013 19:21, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Mon, 17 Jun 2013 18:40:50 +0530, Viresh Kumar wrote:
>> >> > The core acpi-cpufreq.c code hadn't been changed by me, so I
>> >> > assume that it will work as before.
>> >>
>> >> That should adapt your patch in your patchset.
>
> Could you explain what do you mean?

Update acpi-cpufreq to use your infrastructure.

>> >> From sysfs?? I thought we are going to have some automatic control
>> >> of this stuff from inside kernel.
>> >
>> > From sysfs I just enable the boost. I do not order from userpace the
>> > cpufreq to run with a particular (boosted) frequency.
>> >
>> > When I enable boost - I ask (politely) the cpufreq core to
>> > reevaluate policies and when applicable increase policy->max.
>> >
>> > Then governor can use this new frequencies for normal operation.
>>
>> So, with your current patchset in, ondemand or conservative governors
>> will start using boost frequencies. Which might burn your chip.
>
> Two scenarios:
> 1. Thermal framework is compiled in and enabled (for exynos/other SoC)
> -> trip point is reached -> boost is disabled -> frequency is reduced ->
> SoC is cooled down.
>
> I think, that thermal framework is a good "safe valve" here.

Even in this case boost shouldn't have been enabled by default.
Its not only about burning the chip but more than that.

According to my understanding, boost was important for power
saving. In case a high load can be managed by a single cpu with
boost freqs, then its better to use boost freqs rather than bringing
another cpu up.

Normally boost freqs are not so useful if we talk about powersaving,
as their energy consumption is much higher with not so great impact
on performance.

That's why when this thread started we talked about boost only when
one cpu is operational. But with your patch all cores can use boost
freq and thermal will come into picture just to save the chip.

That's wrong. This isn't why we invented boost here. Otherwise you
just don't need boost feature at all for your SoC. Just make these
freqs as available freqs and let thermal control policy->max/min
to save your chip.

> 2. Thermal framework is disabled and user has enabled boost and used
> ondemand / conservative governor.
> Then execute gzip < /dev/urandom > /dev/null & (on all cores).
>
> Then yes, chip will hang/burn due to crossing operating point (or burn).
>
>
> What other means of control (despite of thermal) would you consider
> applicable?
>
> What comes to my mind is modifying governor logic to count how long the
> CPU run with boost enabled and then disable it.

Its not about how long.. One cpu type can work longer with boost freq
compared to other.

What we probably need is:
- Enabled boost from sysfs if required (now below steps will come into
picture)
- See how many cpus are running, if only one then start using boost freqs
- Now thermal should be come into picture to save chip in case a single
cpu running at boost can burn it out.

Lukasz Majewski

unread,
Jun 18, 2013, 4:30:03 AM6/18/13
to
On Tue, 18 Jun 2013 08:42:13 +0200, Viresh Kumar wrote:
> On 17 June 2013 19:21, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > On Mon, 17 Jun 2013 18:40:50 +0530, Viresh Kumar wrote:
> >> >> > The core acpi-cpufreq.c code hadn't been changed by me, so I
> >> >> > assume that it will work as before.
> >> >>
> >> >> That should adapt your patch in your patchset.
> >
> > Could you explain what do you mean?
>
> Update acpi-cpufreq to use your infrastructure.

Ach... It is already done, since I always post acpi related patch to
the boost series :-).
I agree here.

>
> That's wrong. This isn't why we invented boost here. Otherwise you
> just don't need boost feature at all for your SoC. Just make these
> freqs as available freqs and let thermal control policy->max/min
> to save your chip.

Also I agree.

>
> > 2. Thermal framework is disabled and user has enabled boost and used
> > ondemand / conservative governor.
> > Then execute gzip < /dev/urandom > /dev/null & (on all cores).
> >
> > Then yes, chip will hang/burn due to crossing operating point (or
> > burn).
> >
> >
> > What other means of control (despite of thermal) would you consider
> > applicable?
> >
> > What comes to my mind is modifying governor logic to count how long
> > the CPU run with boost enabled and then disable it.
>
> Its not about how long.. One cpu type can work longer with boost freq
> compared to other.
>
> What we probably need is:
> - Enabled boost from sysfs if required (now below steps will come into
> picture)
> - See how many cpus are running, if only one then start using boost
> freqs

You are right here.

I'd like to propose following solution:
1. For acpi (where boost_enable come into play) - do not consider
number of active cpus (this is done in HW anyway)

2. For SW solution evaluate how many CPUs are running. If only one is
running then allow enabling boost from sysfs.

But following situation is also possible: User enable boost when one
core is only running and then for some reason other core is woken up.
What shall be done then?
Shall we then disable boost immediately when cpufreq detects that
more than one core is running? Or leave this situation to be handled by
thermal subsystem?

As a side note:
Logic proposed at point 2, is already implemented at LAB
(enable LAB only when one core is running and disable it when more
than one come into play).


> - Now thermal should be come into picture to save chip in case a
> single cpu running at boost can burn it out.

I will extent v4 to embrace code which switches off boost at thermal.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 18, 2013, 4:50:01 AM6/18/13
to
On 18 June 2013 13:54, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Tue, 18 Jun 2013 08:42:13 +0200, Viresh Kumar wrote:

>> Its not about how long.. One cpu type can work longer with boost freq
>> compared to other.
>>
>> What we probably need is:
>> - Enabled boost from sysfs if required (now below steps will come into
>> picture)
>> - See how many cpus are running, if only one then start using boost
>> freqs
>
> You are right here.
>
> I'd like to propose following solution:
> 1. For acpi (where boost_enable come into play) - do not consider
> number of active cpus (this is done in HW anyway)
>
> 2. For SW solution evaluate how many CPUs are running. If only one is
> running then allow enabling boost from sysfs.

Looks fine.

> But following situation is also possible: User enable boost when one
> core is only running and then for some reason other core is woken up.
> What shall be done then?
> Shall we then disable boost immediately when cpufreq detects that
> more than one core is running? Or leave this situation to be handled by
> thermal subsystem?

Obviously disable boost ASAP. Every SoC might not have a thermal
framework glue to do it.

> As a side note:
> Logic proposed at point 2, is already implemented at LAB
> (enable LAB only when one core is running and disable it when more
> than one come into play).

Hmm.. So, eventually that will go away now :)

>> - Now thermal should be come into picture to save chip in case a
>> single cpu running at boost can burn it out.
>
> I will extent v4 to embrace code which switches off boost at thermal.

Gud.

Lukasz Majewski

unread,
Jun 18, 2013, 5:20:02 AM6/18/13
to
On Tue, 18 Jun 2013 14:10:28 +0530, Viresh Kumar wrote:
> On 18 June 2013 13:54, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > On Tue, 18 Jun 2013 08:42:13 +0200, Viresh Kumar wrote:
>
> >> Its not about how long.. One cpu type can work longer with boost
> >> freq compared to other.
> >>
> >> What we probably need is:
> >> - Enabled boost from sysfs if required (now below steps will come
> >> into picture)
> >> - See how many cpus are running, if only one then start using boost
> >> freqs
> >
> > You are right here.
> >
> > I'd like to propose following solution:
> > 1. For acpi (where boost_enable come into play) - do not consider
> > number of active cpus (this is done in HW anyway)
> >
> > 2. For SW solution evaluate how many CPUs are running. If only one
> > is running then allow enabling boost from sysfs.
>
> Looks fine.

Ok,

>
> > But following situation is also possible: User enable boost when one
> > core is only running and then for some reason other core is woken
> > up. What shall be done then?
> > Shall we then disable boost immediately when cpufreq detects that
> > more than one core is running? Or leave this situation to be
> > handled by thermal subsystem?
>
> Obviously disable boost ASAP. Every SoC might not have a thermal
> framework glue to do it.

Implementation of counting number of idle CPUs would impose extending
the cpufreq core itself. Do you have any hints how this can be done in
a neat way?

I suspect, that porting the LAB solution to the cpufreq core may be not
easy. I think that the best place for it would be governor core code.

>
> > As a side note:
> > Logic proposed at point 2, is already implemented at LAB
> > (enable LAB only when one core is running and disable it when more
> > than one come into play).
>
> Hmm.. So, eventually that will go away now :)

But this is not the only functionality, which LAB posses :-).

>
> >> - Now thermal should be come into picture to save chip in case a
> >> single cpu running at boost can burn it out.
> >
> > I will extent v4 to embrace code which switches off boost at
> > thermal.
>
> Gud.

Ok.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Rafael J. Wysocki

unread,
Jun 18, 2013, 9:20:02 AM6/18/13
to
Do you mean the 'boost' sysfs attribute or the 'turbo frequencies' concept?

> Normally boost freqs are not so useful if we talk about powersaving,
> as their energy consumption is much higher with not so great impact
> on performance.

Er, er, please be careful here. The impact on performance may be sufficient
for deep C-states to become relevant in some cases.

> That's why when this thread started we talked about boost only when
> one cpu is operational. But with your patch all cores can use boost
> freq and thermal will come into picture just to save the chip.

Well, that's why on x86 turbo is controlled by hardware that takes care of
keeping things within the chip's thermal limits.

> That's wrong. This isn't why we invented boost here. Otherwise you
> just don't need boost feature at all for your SoC. Just make these
> freqs as available freqs and let thermal control policy->max/min
> to save your chip.

The 'boost' attribute added by acpi-cpufreq means "let the hardware use turbo
frequencies".

I'd recommend you both to read Documentation/cpu-freq/boost.txt now. :-)

I think we can extend the meaning to "let turbo frequencies be used", but if
we need software to play the role of the hardware's thermal control, we need
to be very careful.

> > 2. Thermal framework is disabled and user has enabled boost and used
> > ondemand / conservative governor.
> > Then execute gzip < /dev/urandom > /dev/null & (on all cores).
> >
> > Then yes, chip will hang/burn due to crossing operating point (or burn).
> >
> >
> > What other means of control (despite of thermal) would you consider
> > applicable?
> >
> > What comes to my mind is modifying governor logic to count how long the
> > CPU run with boost enabled and then disable it.
>
> Its not about how long.. One cpu type can work longer with boost freq
> compared to other.
>
> What we probably need is:
> - Enabled boost from sysfs if required (now below steps will come into
> picture)

This has to be compatible with the existing stuff.

> - See how many cpus are running, if only one then start using boost freqs
> - Now thermal should be come into picture to save chip in case a single
> cpu running at boost can burn it out.

I'd say there needs to be a separate controller/monitor for that that will
know what the chip's thermal limit is and how that relates to how fast the
CPU core(s) may run and for how much time. I'm not sure it is sufficient
to "wait for thermal to kick in" here, because you may need to slow down
things in advance (i.e. before thermal sensors tell you there's too much heat,
because that may be too late already).

Thanks,
Rafael


--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

Lukasz Majewski

unread,
Jun 18, 2013, 9:50:01 AM6/18/13
to
And this is the reason why I don't want to overly change acpi-cpufreq.c
code. :-)

>
> > That's wrong. This isn't why we invented boost here. Otherwise you
> > just don't need boost feature at all for your SoC. Just make these
> > freqs as available freqs and let thermal control policy->max/min
> > to save your chip.
>
> The 'boost' attribute added by acpi-cpufreq means "let the hardware
> use turbo frequencies".

This is HW managed. We only enable the switch and then simply forget
about it.

>
> I'd recommend you both to read Documentation/cpu-freq/boost.txt
> now. :-)


According to the documentation:
"Reading the file is always supported, even if the processor does not
support boosting. In this case the file will be read-only and always
reads as "0""

Hmm, in the proposed patch set, the "boost" attribute is only exported
when cpufreq driver sets boost_supported flag.
I think that thermal subsystem shall be the second option to disable SW
boosting.

The main control shall be done inside the cpufreq core. The idea to
disable boost when more than one core is active is rational.

I'm going to implement this concept at v4.

>
> Thanks,
> Rafael
>
>



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 19, 2013, 3:20:02 AM6/19/13
to
On Tue, 18 Jun 2013 15:44:56 +0200, Lukasz Majewski wrote:

Dear Viesh, Rafael,

> >
> > I'd recommend you both to read Documentation/cpu-freq/boost.txt
> > now. :-)
>
>
> According to the documentation:
> "Reading the file is always supported, even if the processor does not
> support boosting. In this case the file will be read-only and always
> reads as "0""
>
> Hmm, in the proposed patch set, the "boost" attribute is only exported
> when cpufreq driver sets boost_supported flag.

I would like to clarify the above issue.

When I've discussed with Viresh previous version of this patch, we have
agreed, that "boost" sysfs attribute [*]:
/sys/devices/system/cpu/cpufreq/boost

would be only visible when boost_supported flag is set at cpufreq
driver.

When acpi-cpufreq driver doesn't support boost, the attribute [*]
won't be exported at all. This contradicts the documentation and legacy
acpi-cpufreq behaviour.

Since I'm affraid to break API (with all its consequences :-) ), I would
like to be sure that this is OK, and thereof I'm allowed to rewrite
documentation accordingly.

I simply need explicit permission from both maintainers :-).

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:02 PM6/19/13
to
Policies available in a cpufreq framework are now linked together. They are
accessible via cpufreq_policy_list defined at cpufreq core.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- New patch
---
drivers/cpufreq/cpufreq.c | 3 +++
include/linux/cpufreq.h | 1 +
2 files changed, 4 insertions(+)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 2ce86ed..665e641 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -46,6 +46,7 @@ static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
#endif
static DEFINE_RWLOCK(cpufreq_driver_lock);
+static LIST_HEAD(cpufreq_policy_list);

/*
* cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
@@ -989,6 +990,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
}
#endif

+ list_add(&policy->policy_list, &cpufreq_policy_list);
ret = cpufreq_add_dev_interface(cpu, policy, dev);
if (ret)
goto err_out_unregister;
@@ -1992,6 +1994,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
subsys_interface_unregister(&cpufreq_interface);
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);

+ list_del(&cpufreq_policy_list);
write_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_driver = NULL;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index ab1932c..5348981 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -117,6 +117,7 @@ struct cpufreq_policy {

struct cpufreq_real_policy user_policy;

+ struct list_head policy_list;
struct kobject kobj;
struct completion kobj_unregister;
};
--
1.7.10.4

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:03 PM6/19/13
to
This patch adds protection from accidental enable of boost at systems,
which supports software boosting.

Boost software mode can be only enabled when up to one busy (with heavy
load) core is available on the system. Such approach brings extra
protection from over heating.

Moreover the boost is automatically disabled, when cpufreq core detects
more busy cores.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- New patch
---
drivers/cpufreq/cpufreq.c | 9 +++++++--
drivers/cpufreq/cpufreq_governor.c | 3 +++
2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index f785273..59d2cac 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1932,12 +1932,17 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
/*********************************************************************
* BOOST *
*********************************************************************/
-static int cpufreq_boost_trigger_state_sw(void)
+static int cpufreq_boost_trigger_state_sw(int state)
{
struct cpufreq_frequency_table *freq_table;
struct cpufreq_policy *policy;
int ret = -EINVAL;

+ if (state && cpufreq_num_busy_cpu() > 1) {
+ boost_enabled = 0;
+ return 0;
+ }
+
list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
freq_table = cpufreq_frequency_get_table(policy->cpu);
if (freq_table)
@@ -1959,7 +1964,7 @@ int cpufreq_boost_trigger_state(int state)
if (cpufreq_driver->enable_boost)
ret = cpufreq_driver->enable_boost(state);
else
- ret = cpufreq_boost_trigger_state_sw();
+ ret = cpufreq_boost_trigger_state_sw(state);

if (ret) {
boost_enabled = 0;
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 3402533..9383ab9 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -162,6 +162,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
max_load = load;
}

+ if (cpufreq_boost_supported() && cpufreq_num_busy_cpu() > 1)
+ cpufreq_boost_trigger_state(0);
+
dbs_data->cdata->gov_check_cpu(cpu, max_load);
}
EXPORT_SYMBOL_GPL(dbs_check_cpu);

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:03 PM6/19/13
to
This patch series introduces support for CPU overclocking technique
called Boost.

It is a follow up of a LAB governor proposal. Boost is a LAB component:
http://thread.gmane.org/gmane.linux.kernel/1484746/match=cpufreq

Boost unifies hardware based solution (e.g. Intel Nehalem) with
software oriented one (like the one done at Exynos).
For this reason cpufreq/freq_table code has been reorganized to include
common code.

Important design decisions:

- Boost related code is compiled-in unconditionally and disabled by default
The cpufreq_driver is responsibile for setting boost_supported flag and
providing enable_boost callback(if HW support is needed)

- struct cpufreq_driver has been extended with boost related fields:
-- boost_supported - when driver supports boosting
-- enable_boost - callback to function, which is necessary to
enable boost in the processor (like it is done at Intel)

- Boost sysfs attribute (/sys/devices/system/cpu/cpufreq/boost) is always
provided.
It will be read only, until either cpufreq_driver defines boost_supported
flag or device tree's cpufreq "boost_mode" attribute is defined. It is
consistent with legacy acpi API.

- No special spin_lock for Boost was created. The one from cpufreq core
was reused.

- All available policies are now stored in a list.

- The Boost code doesn't rely on any policy. When boost state is changed,
then the policy list is iterated and proper adjustements are done.

- Number of busy cpus (with load > 90%) is calculated and exported as a
global sysfs attribute.

- The SW based boost can be only enabled when up to one core is regarded as
a "busy" one. For safety reasons boost is disabled when more cores comes
into play.

- To improve safety level, the thermal framework is also extended to disable
software boosting, when thermal trip point is reached.

New patches for v4:
cpufreq: Store cpufreq policies in a list
cpufreq: Calculate number of busy CPUs
cpufreq: Enable software boost only when up to one busy core is running
thermal:boost: Disable boost when trip point is reached

Tested at: HW:
Exynos 4412 3.10 linux
Exynos 4210 3.10 linux
Compile tested x86_64 defconfig (acpi) - help with HW (Intel Nehalem) test
needed


Lukasz Majewski (7):
cpufreq: Store cpufreq policies in a list
cpufreq: Add boost frequency support in core
cpufreq:acpi:x86: Adjust the acpi-cpufreq.c code to work with common
boost solution
cpufreq:exynos:Extend Exynos cpufreq driver to support boost
framework
cpufreq: Calculate number of busy CPUs
cpufreq: Enable software boost only when up to one busy core is
running
thermal:boost: Disable boost when trip point is reached

drivers/cpufreq/acpi-cpufreq.c | 61 ++++++-----------
drivers/cpufreq/cpufreq.c | 132 ++++++++++++++++++++++++++++++++++++
drivers/cpufreq/cpufreq_governor.c | 4 ++
drivers/cpufreq/exynos-cpufreq.c | 4 ++
drivers/cpufreq/freq_table.c | 43 ++++++++++--
drivers/thermal/cpu_cooling.c | 3 +
include/linux/cpufreq.h | 15 ++++
7 files changed, 215 insertions(+), 47 deletions(-)

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:03 PM6/19/13
to
In the core governor code, per cpu load value is calculated. This patch
uses it to mark processor as a "busy" one, when load value is higher than
90%.

New cpufreq sysfs attribute is created (busy_cpus). It is read only
and provides information about number of actually busy CPU.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- New patch
---
drivers/cpufreq/cpufreq.c | 31 ++++++++++++++++++++++++++++++-
drivers/cpufreq/cpufreq_governor.c | 1 +
include/linux/cpufreq.h | 3 +++
3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 9141d33..f785273 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -48,6 +48,7 @@ static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
#endif
static DEFINE_RWLOCK(cpufreq_driver_lock);
static LIST_HEAD(cpufreq_policy_list);
+static cpumask_t cpufreq_busy_cpus;

/*
* cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
@@ -317,6 +318,13 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/*********************************************************************
* SYSFS INTERFACE *
*********************************************************************/
+ssize_t show_busy_cpus(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", cpufreq_num_busy_cpu());
+}
+define_one_global_ro(busy_cpus);
+
ssize_t show_boost(struct kobject *kobj,
struct attribute *attr, char *buf)
{
@@ -1980,6 +1988,17 @@ int cpufreq_boost_enabled(void)
return boost_enabled;
}

+int cpufreq_num_busy_cpu(void)
+{
+ return cpumask_weight(&cpufreq_busy_cpus);
+}
+
+void cpufreq_set_busy_cpu(int cpu, int val)
+{
+ val ? cpumask_set_cpu(cpu, &cpufreq_busy_cpus) :
+ cpumask_clear_cpu(cpu, &cpufreq_busy_cpus);
+}
+
/*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER *
*********************************************************************/
@@ -2019,6 +2038,13 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
cpufreq_driver = driver_data;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);

+ ret = cpufreq_sysfs_create_file(&(busy_cpus.attr));
+ if (ret) {
+ pr_err("%s: cannot register global busy_cpus sysfs file\n",
+ __func__);
+ goto err_null_driver;
+ }
+
if (!cpufreq_driver->boost_supported)
boost.attr.mode = 0444;

@@ -2026,7 +2052,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
if (ret) {
pr_err("%s: cannot register global boost sysfs file\n",
__func__);
- goto err_null_driver;
+ goto err_busy_idle_unreg;
}

ret = subsys_interface_register(&cpufreq_interface);
@@ -2058,6 +2084,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
return 0;
err_if_unreg:
subsys_interface_unregister(&cpufreq_interface);
+err_busy_idle_unreg:
+ cpufreq_sysfs_remove_file(&(busy_cpus.attr));
err_null_driver:
write_lock_irqsave(&cpufreq_driver_lock, flags);
cpufreq_driver = NULL;
@@ -2086,6 +2114,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)

subsys_interface_unregister(&cpufreq_interface);

+ cpufreq_sysfs_remove_file(&(busy_cpus.attr));
cpufreq_sysfs_remove_file(&(boost.attr));
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);

diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 077cea7..3402533 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -148,6 +148,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu)
continue;

load = 100 * (wall_time - idle_time) / wall_time;
+ cpufreq_set_busy_cpu(j, load > 90 ? 1 : 0);

if (dbs_data->cdata->governor == GOV_ONDEMAND) {
int freq_avg = __cpufreq_driver_getavg(policy, j);
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 4783c4c..536abfc 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -436,6 +436,9 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
int cpufreq_boost_trigger_state(int state);
int cpufreq_boost_supported(void);
int cpufreq_boost_enabled(void);
+
+void cpufreq_set_busy_cpu(int cpu, int val);
+int cpufreq_num_busy_cpu(void);
/* the following 3 funtions are for cpufreq core use only */
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:04 PM6/19/13
to
This commit adds boost frequency support in cpufreq core (Hardware &
Software).
Some SoC (like Exynos4 - e.g. 4x12) allow setting frequency above
its normal operation limits. Such a mode shall be only used for a short
time.

Overclocking (boost) support is essentially provided by platform
dependent cpufreq driver.

This commit unifies support for SW and HW (Intel) over clocking solutions
in the core cpufreq driver. Previously the "boost" sysfs attribute was
defined at acpi driver code.
Boost sysfs attribute is always exported (to support legacy API). By
default boost is exported as read only. One global attribute is available at:
/sys/devices/system/cpu/cpufreq/boost.

Under the hood frequencies dedicated for boosting are marked with a
special flag (CPUFREQ_BOOST_FREQ) at driver's frequency table.
It is the user's concern to enable/disable overclocking with proper call to
sysfs.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- Remove boost parameter from cpufreq_frequency_table_cpuinfo() function
- Introduce cpufreq_boost_supported() method
- Use of cpufreq_boost_supported() and cpufreq_boost_enabled() to decide
if frequency shall be skipped
- Rename set_boost_freq() to enable_boost()
- cpufreq_attr_available_freq() moved to freq_table.c
- Use policy list to get access to cpufreq policies
- Rename global boost flag (cpufreq_boost_enabled -> boost_enabled)
- pr_err corrected ( %sable)
- Remove sanity check at cpufreq_boost_trigger_state() entrance [to test if
boost is supported]
- Use either HW (boost_enable) callback or SW managed boost
- Introduce new cpufreq_boost_trigger_state_sw() method to handle boost
at SW.
- Protect boost_enabled manipulation with lock
- Always export boost attribute (preserve legacy behaviour). When boost
is not supported this attribute is read only

Changes for v3:
- Method for reading boost status
- Removal of cpufreq_frequency_table_max()
- Extent cpufreq_frequency_table_cpuinfo() to support boost parameter
- boost_supported flag added to cpufreq_driver struct
- "boost" sysfs attribute control flag removed
- One global flag describing state of the boost defined at cpufreq core
- Rename cpufreq_driver's low_level_boost field to set_boost_freq()
- Usage of cpufreq_sysfs_{remove|add}_file() routines

Changes for v2:
- Removal of cpufreq_boost structure and move its fields to cpufreq_driver
structure
- Flag to indicate if global boost attribute is already defined
- Extent the pr_{err|debbug} functions to show current function names
---
drivers/cpufreq/cpufreq.c | 95 ++++++++++++++++++++++++++++++++++++++++++
drivers/cpufreq/freq_table.c | 43 +++++++++++++++----
include/linux/cpufreq.h | 11 +++++
3 files changed, 142 insertions(+), 7 deletions(-)

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 665e641..9141d33 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -40,6 +40,7 @@
* also protects the cpufreq_cpu_data array.
*/
static struct cpufreq_driver *cpufreq_driver;
+static bool boost_enabled;
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
#ifdef CONFIG_HOTPLUG_CPU
/* This one keeps track of the previously set governor of a removed CPU */
@@ -316,6 +317,29 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
/*********************************************************************
* SYSFS INTERFACE *
*********************************************************************/
+ssize_t show_boost(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", boost_enabled);
+}
+
+static ssize_t store_boost(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, enable;
+
+ ret = sscanf(buf, "%d", &enable);
+ if (ret != 1 || enable < 0 || enable > 1)
+ return -EINVAL;
+
+ if (cpufreq_boost_trigger_state(enable)) {
+ pr_err("%s: Cannot enable boost!\n", __func__);
+ return -EINVAL;
+ }
+
+ return count;
+}
+define_one_global_rw(boost);

static struct cpufreq_governor *__find_governor(const char *str_governor)
{
@@ -1898,6 +1922,65 @@ static struct notifier_block __refdata cpufreq_cpu_notifier = {
};

/*********************************************************************
+ * BOOST *
+ *********************************************************************/
+static int cpufreq_boost_trigger_state_sw(void)
+{
+ struct cpufreq_frequency_table *freq_table;
+ struct cpufreq_policy *policy;
+ int ret = -EINVAL;
+
+ list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
+ freq_table = cpufreq_frequency_get_table(policy->cpu);
+ if (freq_table)
+ ret = cpufreq_frequency_table_cpuinfo(policy,
+ freq_table);
+ }
+
+ return ret;
+
+}
+int cpufreq_boost_trigger_state(int state)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ if (boost_enabled != state) {
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
+ boost_enabled = state;
+ if (cpufreq_driver->enable_boost)
+ ret = cpufreq_driver->enable_boost(state);
+ else
+ ret = cpufreq_boost_trigger_state_sw();
+
+ if (ret) {
+ boost_enabled = 0;
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+ pr_err("%s: BOOST cannot enable (%d)\n",
+ __func__, ret);
+
+ return ret;
+ }
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+ pr_debug("%s: cpufreq BOOST %s\n", __func__,
+ state ? "enabled" : "disabled");
+ }
+
+ return 0;
+}
+
+int cpufreq_boost_supported(void)
+{
+ return cpufreq_driver->boost_supported;
+}
+
+int cpufreq_boost_enabled(void)
+{
+ return boost_enabled;
+}
+
+/*********************************************************************
* REGISTER / UNREGISTER CPUFREQ DRIVER *
*********************************************************************/

@@ -1936,6 +2019,16 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
cpufreq_driver = driver_data;
write_unlock_irqrestore(&cpufreq_driver_lock, flags);

+ if (!cpufreq_driver->boost_supported)
+ boost.attr.mode = 0444;
+
+ ret = cpufreq_sysfs_create_file(&(boost.attr));
+ if (ret) {
+ pr_err("%s: cannot register global boost sysfs file\n",
+ __func__);
+ goto err_null_driver;
+ }
+
ret = subsys_interface_register(&cpufreq_interface);
if (ret)
goto err_null_driver;
@@ -1992,6 +2085,8 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
pr_debug("unregistering driver %s\n", driver->name);

subsys_interface_unregister(&cpufreq_interface);
+
+ cpufreq_sysfs_remove_file(&(boost.attr));
unregister_hotcpu_notifier(&cpufreq_cpu_notifier);

list_del(&cpufreq_policy_list);
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index d7a7966..9c8e71e 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -34,6 +34,11 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,

continue;
}
+ if (cpufreq_boost_supported())
+ if (!cpufreq_boost_enabled()
+ && table[i].index == CPUFREQ_BOOST_FREQ)
+ continue;
+
pr_debug("table entry %u: %u kHz, %u index\n",
i, freq, table[i].index);
if (freq < min_freq)
@@ -171,7 +176,8 @@ static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/**
* show_available_freqs - show available frequencies for the specified CPU
*/
-static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
+static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
+ int show_boost)
{
unsigned int i = 0;
unsigned int cpu = policy->cpu;
@@ -186,6 +192,9 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
continue;
+ if (show_boost ^ (table[i].index == CPUFREQ_BOOST_FREQ))
+ continue;
+
count += sprintf(&buf[count], "%d ", table[i].frequency);
}
count += sprintf(&buf[count], "\n");
@@ -194,14 +203,34 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)

}

-struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
- .attr = { .name = "scaling_available_frequencies",
- .mode = 0444,
- },
- .show = show_available_freqs,
-};
+#define cpufreq_attr_available_freq(_name) \
+struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
+__ATTR_RO(_name##_frequencies)
+
+/**
+ * show_scaling_available_frequencies - show normal boost frequencies for
+ * the specified CPU
+ */
+static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, 0);
+}
+cpufreq_attr_available_freq(scaling_available);
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);

+/**
+ * show_available_boost_freqs - show available boost frequencies for
+ * the specified CPU
+ */
+static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy,
+ char *buf)
+{
+ return show_available_freqs(policy, buf, 1);
+}
+cpufreq_attr_available_freq(scaling_boost);
+EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_boost_freqs);
+
/*
* if you use these, you must assure that the frequency table is valid
* all the time between get_attr and put_attr!
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 5348981..4783c4c 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -267,6 +267,10 @@ struct cpufreq_driver {
int (*suspend) (struct cpufreq_policy *policy);
int (*resume) (struct cpufreq_policy *policy);
struct freq_attr **attr;
+
+ /* platform specific boost support code */
+ bool boost_supported;
+ int (*enable_boost) (int state);
};

/* flags */
@@ -408,6 +412,9 @@ extern struct cpufreq_governor cpufreq_gov_conservative;
#define CPUFREQ_ENTRY_INVALID ~0
#define CPUFREQ_TABLE_END ~1

+/* Define index for boost frequency */
+#define CPUFREQ_BOOST_FREQ ~2
+
struct cpufreq_frequency_table {
unsigned int index; /* any */
unsigned int frequency; /* kHz - doesn't need to be in ascending
@@ -426,11 +433,15 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
unsigned int relation,
unsigned int *index);

+int cpufreq_boost_trigger_state(int state);
+int cpufreq_boost_supported(void);
+int cpufreq_boost_enabled(void);
/* the following 3 funtions are for cpufreq core use only */
struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu);

/* the following are really really optional */
extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs;
+extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs;

void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
unsigned int cpu);

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:03 PM6/19/13
to
This patch provides support for disabling cpufreq's boost
feature when thermal trip point is reached.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- New patch
---
drivers/thermal/cpu_cooling.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index c94bf2e..3bdd870 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -323,6 +323,9 @@ static int cpufreq_thermal_notifier(struct notifier_block *nb,
if (cpumask_test_cpu(policy->cpu, &notify_device->allowed_cpus))
max_freq = notify_device->cpufreq_val;

+ if (cpufreq_boost_supported())
+ cpufreq_boost_trigger_state(0);
+
/* Never exceed user_policy.max */
if (max_freq > policy->user_policy.max)
max_freq = policy->user_policy.max;

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:04 PM6/19/13
to
The Intel's hardware based boost solution driver has been changed to cooperate with
common cpufreq boost framework.

The global sysfs boost attribute entry code (/sys/devices/system/cpu/cpufreq/boost)
has been moved to a core cpufreq code. This attribute is always visible.
When cpufreq driver doesn't support boost, it is read only.
The boost supported global flag was replaced with the one defined at acpi's
cpufreq driver.

The _store_boost() function has been redesigned to be used as set_boost_freq
callback.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- add _store_boost to acpi_cpufreq_driver structure

Changes for v3:
- Bring back boost_enabled as a global flag
- Move boost_supported to cpufreq_driver structure

Changes for v2:
- Replace boost_enabled and boost_supported global flags with proper entries
at struct cpufreq_driver.
- Removal of struct cpufreq_boost
---
drivers/cpufreq/acpi-cpufreq.c | 61 ++++++++++++++--------------------------
1 file changed, 21 insertions(+), 40 deletions(-)

diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 2845566..f33a3c9 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
+ return -EINVAL;
+
+ ret = kstrtoul(buf, 10, &val);
+ if (ret || (val > 1))
+ return -EINVAL;

-static struct global_attr global_boost = __ATTR(boost, 0644,
- show_global_boost,
- store_global_boost);
+ _store_boost((int) val);
+
+ return count;
+}

#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
size_t count)
{
- return _store_boost(buf, count);
+ return store_boost(buf, count);
}

static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
@@ -920,6 +911,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.name = "acpi-cpufreq",
.owner = THIS_MODULE,
.attr = acpi_cpufreq_attr,
+ .enable_boost = _store_boost,
};

static void __init acpi_cpufreq_boost_init(void)
@@ -930,8 +922,8 @@ static void __init acpi_cpufreq_boost_init(void)
if (!msrs)
return;

- boost_supported = true;
boost_enabled = boost_state(0);
+ acpi_cpufreq_driver.boost_supported = true;

get_online_cpus();

@@ -941,22 +933,11 @@ static void __init acpi_cpufreq_boost_init(void)
register_cpu_notifier(&boost_nb);

put_online_cpus();
- } else
- global_boost.attr.mode = 0444;
-
- /* We create the boost file in any case, though for systems without
- * hardware support it will be read-only and hardwired to return 0.
- */
- if (cpufreq_sysfs_create_file(&(global_boost.attr)))
- pr_warn(PFX "could not register global boost sysfs file\n");
- else
- pr_debug("registered global boost sysfs file\n");
+ }
}

static void __exit acpi_cpufreq_boost_exit(void)
{
- cpufreq_sysfs_remove_file(&(global_boost.attr));
-
if (msrs) {
unregister_cpu_notifier(&boost_nb);

Lukasz Majewski

unread,
Jun 19, 2013, 1:20:03 PM6/19/13
to
The struct cpufreq_driver has been extended to embrace the information
related to boost support.

When "boost_mode" device tree attribute is defined for a platform, the
boost_supported flag is set. Moreover boost related attributes were
exported.

Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
Signed-off-by: Myungjoo Ham <myungj...@samsung.com>

Changes for v4:
- None

Changes for v3:
- Remove low level boost code
- Move boost management code to cpufreq core code
- Use boost_supported flag to indicate if driver supports over clocking

Changes for v2:
- Removal of struct cpufreq_boost
- Removal of the CONFIG_CPU_FREQ_BOOST flag
- low_level_boost with valid address when boost is supported
---
drivers/cpufreq/exynos-cpufreq.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index 3197d88..b0e424e 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -264,6 +264,7 @@ static int exynos_cpufreq_cpu_exit(struct cpufreq_policy *policy)

static struct freq_attr *exynos_cpufreq_attr[] = {
&cpufreq_freq_attr_scaling_available_freqs,
+ &cpufreq_freq_attr_scaling_boost_freqs,
NULL,
};

@@ -359,6 +360,7 @@ static struct of_device_id exynos_cpufreq_of_match[] __initconst = {

static int __init exynos_cpufreq_probe(struct platform_device *pdev)
{
+ struct device_node *node = pdev->dev.of_node;
int ret = -EINVAL;

exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
@@ -391,6 +393,8 @@ static int __init exynos_cpufreq_probe(struct platform_device *pdev)
}

locking_frequency = exynos_getspeed(0);
+ if (of_property_read_bool(node, "boost_mode"))
+ exynos_driver.boost_supported = 1;

register_pm_notifier(&exynos_cpufreq_nb);

Dirk Brandewie

unread,
Jun 19, 2013, 1:50:02 PM6/19/13
to
On 06/19/2013 10:12 AM, Lukasz Majewski wrote:
> This commit adds boost frequency support in cpufreq core (Hardware &

> +/*********************************************************************
> * REGISTER / UNREGISTER CPUFREQ DRIVER *
> *********************************************************************/
>
> @@ -1936,6 +2019,16 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
> cpufreq_driver = driver_data;
> write_unlock_irqrestore(&cpufreq_driver_lock, flags);
>
> + if (!cpufreq_driver->boost_supported)
> + boost.attr.mode = 0444;
> +
> + ret = cpufreq_sysfs_create_file(&(boost.attr));
> + if (ret) {
> + pr_err("%s: cannot register global boost sysfs file\n",
> + __func__);
> + goto err_null_driver;
> + }
> +

I do not think the boost sysfs should be created at all if boost is not
supported.

For intel_pstate the read-only boost would be there for no reason and would
cause confusion on the part of the user IMHO

> ret = subsys_interface_register(&cpufreq_interface);
> if (ret)
> goto err_null_driver;
> @@ -1992,6 +2085,8 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
> pr_debug("unregistering driver %s\n", driver->name);
>
> subsys_interface_unregister(&cpufreq_interface);
> +
> + cpufreq_sysfs_remove_file(&(boost.attr));
> unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
>

Dirk Brandewie

unread,
Jun 19, 2013, 2:10:01 PM6/19/13
to
On 06/19/2013 10:12 AM, Lukasz Majewski wrote:
> In the core governor code, per cpu load value is calculated. This patch
> uses it to mark processor as a "busy" one, when load value is higher than
> 90%.
>
> New cpufreq sysfs attribute is created (busy_cpus). It is read only
> and provides information about number of actually busy CPU.
>

What is the intended use of this interface?

For drivers that have internal governors it will be misleading/wrong

--Dirk

Lukasz Majewski

unread,
Jun 19, 2013, 4:40:03 PM6/19/13
to
On Wed, 19 Jun 2013 10:48:53 -0700
Dirk Brandewie <dirk.br...@gmail.com> wrote:

> On 06/19/2013 10:12 AM, Lukasz Majewski wrote:
> > This commit adds boost frequency support in cpufreq core (Hardware &
>
> > +/*********************************************************************
> > * REGISTER / UNREGISTER CPUFREQ
> > DRIVER *
> > *********************************************************************/
> >
> > @@ -1936,6 +2019,16 @@ int cpufreq_register_driver(struct
> > cpufreq_driver *driver_data) cpufreq_driver = driver_data;
> > write_unlock_irqrestore(&cpufreq_driver_lock, flags);
> >
> > + if (!cpufreq_driver->boost_supported)
> > + boost.attr.mode = 0444;
> > +
> > + ret = cpufreq_sysfs_create_file(&(boost.attr));
> > + if (ret) {
> > + pr_err("%s: cannot register global boost sysfs
> > file\n",
> > + __func__);
> > + goto err_null_driver;
> > + }
> > +
>
> I do not think the boost sysfs should be created at all if boost is
> not supported.

This was my first thought. But unfortunately this "boost" attribute is
always exported at acpi-cpufreq.c and in my opinion is part of a
legacy API.

I totally agree with the idea of exporting boost only when supported,
but I would like to know the community opinion about this (especially
Viresh and Rafael shall speak up).

>
> For intel_pstate the read-only boost would be there for no reason and
> would cause confusion on the part of the user IMHO

You are probably right here. However I don't know what was the
original rationale behind exporting this attribute as read only.

>
> > ret = subsys_interface_register(&cpufreq_interface);
> > if (ret)
> > goto err_null_driver;
> > @@ -1992,6 +2085,8 @@ int cpufreq_unregister_driver(struct
> > cpufreq_driver *driver) pr_debug("unregistering driver %s\n",
> > driver->name);
> >
> > subsys_interface_unregister(&cpufreq_interface);
> > +
> > + cpufreq_sysfs_remove_file(&(boost.attr));
> > unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
> >
>

Best regards,

Lukasz Majewski

Lukasz Majewski

unread,
Jun 19, 2013, 5:00:03 PM6/19/13
to
On Wed, 19 Jun 2013 11:01:07 -0700
Dirk Brandewie <dirk.br...@gmail.com> wrote:

> On 06/19/2013 10:12 AM, Lukasz Majewski wrote:
> > In the core governor code, per cpu load value is calculated. This
> > patch uses it to mark processor as a "busy" one, when load value is
> > higher than 90%.
> >
> > New cpufreq sysfs attribute is created (busy_cpus). It is read only
> > and provides information about number of actually busy CPU.
> >
>
> What is the intended use of this interface?

The kernel API would be handy with boost managed by software (like it is
done with exynos) and with LAB governor.

The intention is to have two save valves for boost:

1. Enable SW controlled boost only when we have just one busy CPU.

2. Use the Thermal subsystem to switch off SW managed boost when it
detects that SoC is overheating.

The problem with 2 is that, the boost code is compiled in to the cpufreq
core (no CONFIG_BOOST flag). Thereof we cannot guarantee, that thermal
would be always enabled (the KConfig select option).
I think that thermal subsystem is a suitable place to disable SW boost
at emergency. However in my opinion this is not enough and precaution
defined at 1 is needed.

I can remove exporting the "busy_cpu" sysfs attribute if you think, that
it would confuse userspace. Its purpose is mainly informational.

>
> For drivers that have internal governors it will be misleading/wrong

Would you be so kind and give me an example of such an internal
governor?

Maybe I've overlooked some important information/usecase.
Best regards,

Lukasz Majewski

Rafael J. Wysocki

unread,
Jun 19, 2013, 6:20:02 PM6/19/13
to
Simple: Export it only when supported.

Thanks,
Rafael


--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

Rafael J. Wysocki

unread,
Jun 19, 2013, 6:20:02 PM6/19/13
to
Please look at intel_pstate.c.

Thanks,
Rafael


--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

Viresh Kumar

unread,
Jun 20, 2013, 1:10:02 AM6/20/13
to
On 18 June 2013 19:14, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Tue, 18 Jun 2013 15:26:16 +0200, Rafael J. Wysocki wrote:
>> On Tuesday, June 18, 2013 12:12:13 PM Viresh Kumar wrote:
>> > On 17 June 2013 19:21, Lukasz Majewski <l.maj...@samsung.com>

>> Well, that's why on x86 turbo is controlled by hardware that takes
>> care of keeping things within the chip's thermal limits.
>
> And this is the reason why I don't want to overly change acpi-cpufreq.c
> code. :-)

We need to keep both hardware/software boost features at the same place
in core, they may behave differently though. That's why I wanted you
to do that.

> I think that thermal subsystem shall be the second option to disable SW
> boosting.
>
> The main control shall be done inside the cpufreq core. The idea to
> disable boost when more than one core is active is rational.

But then, it might not be enough. A single core can make your SoC
very hot.

Viresh Kumar

unread,
Jun 20, 2013, 1:10:01 AM6/20/13
to
On 18 June 2013 18:56, Rafael J. Wysocki <r...@sisk.pl> wrote:
> On Tuesday, June 18, 2013 12:12:13 PM Viresh Kumar wrote:
>> On 17 June 2013 19:21, Lukasz Majewski <l.maj...@samsung.com> wrote:

>> According to my understanding, boost was important for power
>> saving. In case a high load can be managed by a single cpu with
>> boost freqs, then its better to use boost freqs rather than bringing
>> another cpu up.
>
> Do you mean the 'boost' sysfs attribute or the 'turbo frequencies' concept?

I thought they are the. Probably not, but I am not sure about the
difference.

>> Normally boost freqs are not so useful if we talk about powersaving,
>> as their energy consumption is much higher with not so great impact
>> on performance.
>
> Er, er, please be careful here. The impact on performance may be sufficient
> for deep C-states to become relevant in some cases.

Hmm.

>> That's why when this thread started we talked about boost only when
>> one cpu is operational. But with your patch all cores can use boost
>> freq and thermal will come into picture just to save the chip.
>
> Well, that's why on x86 turbo is controlled by hardware that takes care of
> keeping things within the chip's thermal limits.

Yeah.

>> That's wrong. This isn't why we invented boost here. Otherwise you
>> just don't need boost feature at all for your SoC. Just make these
>> freqs as available freqs and let thermal control policy->max/min
>> to save your chip.
>
> The 'boost' attribute added by acpi-cpufreq means "let the hardware use turbo
> frequencies".
>
> I'd recommend you both to read Documentation/cpu-freq/boost.txt now. :-)

I did it now :)

> I think we can extend the meaning to "let turbo frequencies be used", but if
> we need software to play the role of the hardware's thermal control, we need
> to be very careful.

Exactly. There are two variants now:
- Hardware boost: x86: Don't do any trick in software to prevent hardware
from boosting... Let the hardware take control as it is today
- Software boost: The initial idea from Lukasz was about using boost only
when one cpu is used. That's the impression I had in mind. And it looked
sensible too to some extent. BUT there is a great chance that any mistake
can burn chips, so we need to be extremely careful.

>> What we probably need is:
>> - Enabled boost from sysfs if required (now below steps will come into
>> picture)
>
> This has to be compatible with the existing stuff.

Sure.

>> - See how many cpus are running, if only one then start using boost freqs
>> - Now thermal should be come into picture to save chip in case a single
>> cpu running at boost can burn it out.
>
> I'd say there needs to be a separate controller/monitor for that that will
> know what the chip's thermal limit is and how that relates to how fast the
> CPU core(s) may run and for how much time. I'm not sure it is sufficient
> to "wait for thermal to kick in" here, because you may need to slow down
> things in advance (i.e. before thermal sensors tell you there's too much heat,
> because that may be too late already).

That's why I wasn't sure about software boosting initially. But at the same
time a thermal sensor might be good enough. They just have to be programmed
accordingly, so that they fire a bit in advance before things are out of
control. :)

Viresh Kumar

unread,
Jun 20, 2013, 1:20:02 AM6/20/13
to
On 19 June 2013 12:46, Lukasz Majewski <l.maj...@samsung.com> wrote:
> I would like to clarify the above issue.
>
> When I've discussed with Viresh previous version of this patch, we have
> agreed, that "boost" sysfs attribute [*]:
> /sys/devices/system/cpu/cpufreq/boost
>
> would be only visible when boost_supported flag is set at cpufreq
> driver.

Yes.

> When acpi-cpufreq driver doesn't support boost, the attribute [*]
> won't be exported at all. This contradicts the documentation and legacy
> acpi-cpufreq behaviour.

No they aren't contradictory. What the documentation meant was:
acpi-cpufreq driver is used by lots of different x86 processors. Now
all processors might not support boost inside x86 also. And for them
we will keep 'boost' file readonly. This is done by following statement

if (boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA)) {
boost_supported = true;
....
} else
global_boost.attr.mode = 0444;

Documentation file doesn't talk about any other cpufreq driver, for
them there is no concept like boost.

You need to preserve this functionality.

> Since I'm affraid to break API (with all its consequences :-) ), I would
> like to be sure that this is OK, and thereof I'm allowed to rewrite
> documentation accordingly.
>
> I simply need explicit permission from both maintainers :-).

For me its okay to rewrite documentation.

Viresh Kumar

unread,
Jun 20, 2013, 1:20:02 AM6/20/13
to
On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:

> Boost sysfs attribute is always exported (to support legacy API). By
> default boost is exported as read only. One global attribute is available at:
> /sys/devices/system/cpu/cpufreq/boost.

You asked me and Rafael a question and posted your next version without
even waiting for our replies? That will waste your time and ours too
reviewing it.

Lukasz Majewski

unread,
Jun 20, 2013, 2:50:01 AM6/20/13
to
On Thu, 20 Jun 2013 10:41:41 +0530, Viresh Kumar wrote:
> On 19 June 2013 12:46, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > I would like to clarify the above issue.
> >
> > When I've discussed with Viresh previous version of this patch, we
> > have agreed, that "boost" sysfs attribute [*]:
> > /sys/devices/system/cpu/cpufreq/boost
> >
> > would be only visible when boost_supported flag is set at cpufreq
> > driver.
>
> Yes.
>
> > When acpi-cpufreq driver doesn't support boost, the attribute [*]
> > won't be exported at all. This contradicts the documentation and
> > legacy acpi-cpufreq behaviour.
>
> No they aren't contradictory. What the documentation meant was:
> acpi-cpufreq driver is used by lots of different x86 processors. Now
> all processors might not support boost inside x86 also. And for them
> we will keep 'boost' file readonly. This is done by following
> statement

Thanks for explanation.

>
> if (boot_cpu_has(X86_FEATURE_CPB) ||
> boot_cpu_has(X86_FEATURE_IDA)) { boost_supported = true;
> ....
> } else
> global_boost.attr.mode = 0444;

Grrr.... So simple and obvious solution [1].

>
> Documentation file doesn't talk about any other cpufreq driver, for
> them there is no concept like boost.
>
> You need to preserve this functionality.

Yes the idea [1], solves problem with legacy API.

>
> > Since I'm affraid to break API (with all its consequences :-) ), I
> > would like to be sure that this is OK, and thereof I'm allowed to
> > rewrite documentation accordingly.
> >
> > I simply need explicit permission from both maintainers :-).
>
> For me its okay to rewrite documentation.

I will extent documentation about the SW managed boost.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 20, 2013, 6:10:02 AM6/20/13
to
On Thu, 20 Jun 2013 10:31:30 +0530, Viresh Kumar wrote:
> > I'd say there needs to be a separate controller/monitor for that
> > that will know what the chip's thermal limit is and how that
> > relates to how fast the CPU core(s) may run and for how much time.
> > I'm not sure it is sufficient to "wait for thermal to kick in"
> > here, because you may need to slow down things in advance (i.e.
> > before thermal sensors tell you there's too much heat, because that
> > may be too late already).
>
> That's why I wasn't sure about software boosting initially. But at
> the same time a thermal sensor might be good enough. They just have
> to be programmed accordingly, so that they fire a bit in advance
> before things are out of control. :)

I think that thermal subsystem shall disable boost when SoC is heated
up.

The problem is to guarantee, that thermal will be always enabled and
correctly configured when software based boost is ready to run.


--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Rafael J. Wysocki

unread,
Jun 20, 2013, 4:00:03 PM6/20/13
to
On Thursday, June 20, 2013 10:43:08 AM Viresh Kumar wrote:
> On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
>
> > Boost sysfs attribute is always exported (to support legacy API). By
> > default boost is exported as read only. One global attribute is available at:
> > /sys/devices/system/cpu/cpufreq/boost.
>
> You asked me and Rafael a question and posted your next version without
> even waiting for our replies? That will waste your time and ours too
> reviewing it.

I believe I replied to that (in a different branch of the thread).

And the reply was: Do not expose if not supported.

Thanks,
Rafael


--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

Lukasz Majewski

unread,
Jun 21, 2013, 2:30:02 AM6/21/13
to
On Thu, 20 Jun 2013 22:03:45 +0200, Rafael J. Wysocki wrote:

Hi Rafael,

> On Thursday, June 20, 2013 10:43:08 AM Viresh Kumar wrote:
> > On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com>
> > wrote:
> >
> > > Boost sysfs attribute is always exported (to support legacy API).
> > > By default boost is exported as read only. One global attribute
> > > is available at: /sys/devices/system/cpu/cpufreq/boost.
> >
> > You asked me and Rafael a question and posted your next version
> > without even waiting for our replies? That will waste your time and
> > ours too reviewing it.
>
> I believe I replied to that (in a different branch of the thread).
>
> And the reply was: Do not expose if not supported.

Thanks for reply. Understood :-)

>
> Thanks,
> Rafael
>
>



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 26, 2013, 3:50:02 AM6/26/13
to
Hi Viresh,
If this is not a problem, I'd like to kindly ask You to review those
patches.

Rafael has expressed his opinion about "boost" attribute clearly at the
other mail (as a response to v4 patches):
"Simple: Export it only when supported."

Despite the change about the "boost" attribute visibility there were
many other changes, which deserve maintainer's look.



>
> Lukasz Majewski (7):
> cpufreq: Store cpufreq policies in a list
> cpufreq: Add boost frequency support in core
> cpufreq:acpi:x86: Adjust the acpi-cpufreq.c code to work with common
> boost solution
> cpufreq:exynos:Extend Exynos cpufreq driver to support boost
> framework
> cpufreq: Calculate number of busy CPUs
> cpufreq: Enable software boost only when up to one busy core is
> running
> thermal:boost: Disable boost when trip point is reached
>
> drivers/cpufreq/acpi-cpufreq.c | 61 ++++++-----------
> drivers/cpufreq/cpufreq.c | 132
> ++++++++++++++++++++++++++++++++++++
> drivers/cpufreq/cpufreq_governor.c | 4 ++
> drivers/cpufreq/exynos-cpufreq.c | 4 ++
> drivers/cpufreq/freq_table.c | 43 ++++++++++--
> drivers/thermal/cpu_cooling.c | 3 +
> include/linux/cpufreq.h | 15 ++++ 7 files changed, 215
> insertions(+), 47 deletions(-)
>



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 26, 2013, 4:00:02 AM6/26/13
to
On Wed, Jun 26, 2013 at 1:18 PM, Lukasz Majewski <l.maj...@samsung.com> wrote:
> If this is not a problem, I'd like to kindly ask You to review those
> patches.
>
> Rafael has expressed his opinion about "boost" attribute clearly at the
> other mail (as a response to v4 patches):
> "Simple: Export it only when supported."
>
> Despite the change about the "boost" attribute visibility there were
> many other changes, which deserve maintainer's look.

I haven't got time to review it until now.. I will try to do it this week.

Viresh Kumar

unread,
Jun 26, 2013, 6:40:02 AM6/26/13
to
On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
> Policies available in a cpufreq framework are now linked together. They are
> accessible via cpufreq_policy_list defined at cpufreq core.
>
> Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
>
> Changes for v4:
> - New patch

You need to write changelog after ---, so that it doesn't get commited.

> ---
> drivers/cpufreq/cpufreq.c | 3 +++
> include/linux/cpufreq.h | 1 +
> 2 files changed, 4 insertions(+)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 2ce86ed..665e641 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -46,6 +46,7 @@ static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
> static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor);
> #endif
> static DEFINE_RWLOCK(cpufreq_driver_lock);
> +static LIST_HEAD(cpufreq_policy_list);
>
> /*
> * cpu_policy_rwsem is a per CPU reader-writer semaphore designed to cure
> @@ -989,6 +990,7 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif)
> }
> #endif
>
> + list_add(&policy->policy_list, &cpufreq_policy_list);
> ret = cpufreq_add_dev_interface(cpu, policy, dev);
> if (ret)
> goto err_out_unregister;

what about handling error cases?

> @@ -1992,6 +1994,7 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
> subsys_interface_unregister(&cpufreq_interface);
> unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
>
> + list_del(&cpufreq_policy_list);
> write_lock_irqsave(&cpufreq_driver_lock, flags);
> cpufreq_driver = NULL;
> write_unlock_irqrestore(&cpufreq_driver_lock, flags);
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index ab1932c..5348981 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -117,6 +117,7 @@ struct cpufreq_policy {
>
> struct cpufreq_real_policy user_policy;
>
> + struct list_head policy_list;
> struct kobject kobj;
> struct completion kobj_unregister;

--
viresh

Viresh Kumar

unread,
Jun 26, 2013, 7:00:01 AM6/26/13
to
On 26 June 2013 16:24, Lukasz Majewski <l.maj...@samsung.com> wrote:
>> > ---
>
> So here <---> I will put change log for v5.

correct.

>> > ret = cpufreq_add_dev_interface(cpu, policy, dev);
>> > if (ret)
>
> I will add list_del(&cpufreq_policy_list);
> here.

May not be sufficient. You must do it once at the end of this routine.

Viresh Kumar

unread,
Jun 26, 2013, 7:00:02 AM6/26/13
to
On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
> Boost sysfs attribute is always exported (to support legacy API). By
> default boost is exported as read only. One global attribute is available at:
> /sys/devices/system/cpu/cpufreq/boost.

I assume you are going to fix this as discussed in other threads.

> Changes for v4:
> - Remove boost parameter from cpufreq_frequency_table_cpuinfo() function
> - Introduce cpufreq_boost_supported() method
> - Use of cpufreq_boost_supported() and cpufreq_boost_enabled() to decide
> if frequency shall be skipped
> - Rename set_boost_freq() to enable_boost()
> - cpufreq_attr_available_freq() moved to freq_table.c
> - Use policy list to get access to cpufreq policies
> - Rename global boost flag (cpufreq_boost_enabled -> boost_enabled)
> - pr_err corrected ( %sable)
> - Remove sanity check at cpufreq_boost_trigger_state() entrance [to test if
> boost is supported]
> - Use either HW (boost_enable) callback or SW managed boost
> - Introduce new cpufreq_boost_trigger_state_sw() method to handle boost
> at SW.
> - Protect boost_enabled manipulation with lock
> - Always export boost attribute (preserve legacy behaviour). When boost
> is not supported this attribute is read only

Very well written changelog. But write it after ---
Probably do boost_enabled = true here.

> + return count;
> +}
> +define_one_global_rw(boost);

> /*********************************************************************
> + * BOOST *
> + *********************************************************************/
> +static int cpufreq_boost_trigger_state_sw(void)
> +{
> + struct cpufreq_frequency_table *freq_table;
> + struct cpufreq_policy *policy;
> + int ret = -EINVAL;
> +
> + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) {
> + freq_table = cpufreq_frequency_get_table(policy->cpu);
> + if (freq_table)
> + ret = cpufreq_frequency_table_cpuinfo(policy,
> + freq_table);
> + }
> +
> + return ret;
> +
> +}

add blank line here.

> +int cpufreq_boost_trigger_state(int state)
> +{
> + unsigned long flags;
> + int ret = 0;
> +
> + if (boost_enabled != state) {
> + write_lock_irqsave(&cpufreq_driver_lock, flags);
> + boost_enabled = state;
> + if (cpufreq_driver->enable_boost)
> + ret = cpufreq_driver->enable_boost(state);
> + else
> + ret = cpufreq_boost_trigger_state_sw();
> +
> + if (ret) {
> + boost_enabled = 0;
> + write_unlock_irqrestore(&cpufreq_driver_lock, flags);
> + pr_err("%s: BOOST cannot enable (%d)\n",
> + __func__, ret);
> +
> + return ret;
> + }
> + write_unlock_irqrestore(&cpufreq_driver_lock, flags);

You can rewrite if (ret) and unlock() code to make it less redundant.
unlock and return ret at the end and write other stuff before it.

> + pr_debug("%s: cpufreq BOOST %s\n", __func__,
> + state ? "enabled" : "disabled");
> + }
> +
> + return 0;
> +}
> +
> +int cpufreq_boost_supported(void)
> +{
> + return cpufreq_driver->boost_supported;
> +}
> +
> +int cpufreq_boost_enabled(void)
> +{
> + return boost_enabled;
> +}

EXPORT_SYMBOL_GPL ??

> +/*********************************************************************
> * REGISTER / UNREGISTER CPUFREQ DRIVER *
> *********************************************************************/
>
> @@ -1936,6 +2019,16 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
> cpufreq_driver = driver_data;
> write_unlock_irqrestore(&cpufreq_driver_lock, flags);
>
> + if (!cpufreq_driver->boost_supported)
> + boost.attr.mode = 0444;
> +
> + ret = cpufreq_sysfs_create_file(&(boost.attr));
> + if (ret) {
> + pr_err("%s: cannot register global boost sysfs file\n",
> + __func__);
> + goto err_null_driver;
> + }

This would change.

> ret = subsys_interface_register(&cpufreq_interface);
> if (ret)
> goto err_null_driver;
> @@ -1992,6 +2085,8 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver)
> pr_debug("unregistering driver %s\n", driver->name);
>
> subsys_interface_unregister(&cpufreq_interface);
> +
> + cpufreq_sysfs_remove_file(&(boost.attr));
> unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
>
> list_del(&cpufreq_policy_list);
> diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
> index d7a7966..9c8e71e 100644
> --- a/drivers/cpufreq/freq_table.c
> +++ b/drivers/cpufreq/freq_table.c
> @@ -34,6 +34,11 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
>
> continue;
> }
> + if (cpufreq_boost_supported())

Probably remove this check. Assume somebody while testing exynos,
just sent boost_supported as false. Then you will not skip this frequency
and may burn your chip :)

> + if (!cpufreq_boost_enabled()
> + && table[i].index == CPUFREQ_BOOST_FREQ)
> + continue;

This should be enough.

> pr_debug("table entry %u: %u kHz, %u index\n",
> i, freq, table[i].index);
> if (freq < min_freq)
> @@ -171,7 +176,8 @@ static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
> /**
> * show_available_freqs - show available frequencies for the specified CPU
> */
> -static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
> +static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf,
> + int show_boost)
> {
> unsigned int i = 0;
> unsigned int cpu = policy->cpu;
> @@ -186,6 +192,9 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
> for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
> if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
> continue;

Add a comment here describing your complex logic.

> + if (show_boost ^ (table[i].index == CPUFREQ_BOOST_FREQ))
> + continue;
> +
> count += sprintf(&buf[count], "%d ", table[i].frequency);
> }
> count += sprintf(&buf[count], "\n");
> @@ -194,14 +203,34 @@ static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
>
> }
>
> -struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
> - .attr = { .name = "scaling_available_frequencies",
> - .mode = 0444,
> - },
> - .show = show_available_freqs,
> -};
> +#define cpufreq_attr_available_freq(_name) \
> +struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
> +__ATTR_RO(_name##_frequencies)
> +
> +/**
> + * show_scaling_available_frequencies - show normal boost frequencies for

You missed this comment earlier. boost??
Why is this present here?

Lukasz Majewski

unread,
Jun 26, 2013, 7:00:02 AM6/26/13
to
On 26 Jun 2013 16:05:12,Viresh Kumar <viresh...@linaro.org> wrote:
> On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > Policies available in a cpufreq framework are now linked together.
> > They are accessible via cpufreq_policy_list defined at cpufreq core.
> >
> > Signed-off-by: Lukasz Majewski <l.maj...@samsung.com>
> > Signed-off-by: Myungjoo Ham <myungj...@samsung.com>
> >
> > Changes for v4:
> > - New patch
>
> You need to write changelog after ---, so that it doesn't get
> commited.
>
> > ---

So here <---> I will put change log for v5.


> > drivers/cpufreq/cpufreq.c | 3 +++
> > include/linux/cpufreq.h | 1 +
> > 2 files changed, 4 insertions(+)
> >
> > diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> > index 2ce86ed..665e641 100644
> > --- a/drivers/cpufreq/cpufreq.c
> > +++ b/drivers/cpufreq/cpufreq.c
> > @@ -46,6 +46,7 @@ static DEFINE_PER_CPU(struct cpufreq_policy *,
> > cpufreq_cpu_data); static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN],
> > cpufreq_cpu_governor); #endif
> > static DEFINE_RWLOCK(cpufreq_driver_lock);
> > +static LIST_HEAD(cpufreq_policy_list);
> >
> > /*
> > * cpu_policy_rwsem is a per CPU reader-writer semaphore designed
> > to cure @@ -989,6 +990,7 @@ static int cpufreq_add_dev(struct
> > device *dev, struct subsys_interface *sif) }
> > #endif
> >
> > + list_add(&policy->policy_list, &cpufreq_policy_list);
> > ret = cpufreq_add_dev_interface(cpu, policy, dev);
> > if (ret)

I will add list_del(&cpufreq_policy_list);
here.

> > goto err_out_unregister;
>
> what about handling error cases?

Thanks for spotting.

>
> > @@ -1992,6 +1994,7 @@ int cpufreq_unregister_driver(struct
> > cpufreq_driver *driver)
> > subsys_interface_unregister(&cpufreq_interface);
> > unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
> >
> > + list_del(&cpufreq_policy_list);
> > write_lock_irqsave(&cpufreq_driver_lock, flags);
> > cpufreq_driver = NULL;
> > write_unlock_irqrestore(&cpufreq_driver_lock, flags);
> > diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> > index ab1932c..5348981 100644
> > --- a/include/linux/cpufreq.h
> > +++ b/include/linux/cpufreq.h
> > @@ -117,6 +117,7 @@ struct cpufreq_policy {
> >
> > struct cpufreq_real_policy user_policy;
> >
> > + struct list_head policy_list;
> > struct kobject kobj;
> > struct completion kobj_unregister;
>
> --
> viresh



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 26, 2013, 7:10:02 AM6/26/13
to
On Wed, 26 Jun 2013 16:26:30 +0530, Viresh Kumar wrote:
> On 26 June 2013 16:24, Lukasz Majewski <l.maj...@samsung.com> wrote:
> >> > ---
> >
> > So here <---> I will put change log for v5.
>
> correct.

OK.

>
> >> > ret = cpufreq_add_dev_interface(cpu, policy, dev);
> >> > if (ret)
> >
> > I will add list_del(&cpufreq_policy_list);
> > here.
>
> May not be sufficient. You must do it once at the end of this routine.

Then I will add this code below:

err_out_kobj_put:
list_del(&cpufreq_policy_list);
[rest of error path]

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Viresh Kumar

unread,
Jun 26, 2013, 7:10:02 AM6/26/13
to
On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
> diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c

> static unsigned int acpi_pstate_strict;
> -static bool boost_enabled, boost_supported;
> +static bool boost_enabled;

Instead of this variable use cpufreq_boost_enabled() directly.

And then this patch may change as well..

I couldn't find any more issues with this patch but some Intel guy must
review it.

Viresh Kumar

unread,
Jun 26, 2013, 7:10:02 AM6/26/13
to
On 11 June 2013 14:33, Lukasz Majewski <l.maj...@samsung.com> wrote:
> The struct cpufreq_driver has been extended to embrace the information
> related to boost support.
>
> When "boost_mode" device tree attribute is defined for a platform, the
> low_level_boost pointer is filled with proper address. The
> .low_level_boost field filled to NULL, indicates that boost is not
> supported.

This patch is still few generations back :)

Viresh Kumar

unread,
Jun 26, 2013, 7:10:03 AM6/26/13
to
On 26 June 2013 16:34, Lukasz Majewski <l.maj...@samsung.com> wrote:
> err_out_kobj_put:
> list_del(&cpufreq_policy_list);
> [rest of error path]

I couldn't find err_out_kobj_put in existing code :)

BTW, just add to the list only once everything passed.

Lukasz Majewski

unread,
Jun 26, 2013, 8:20:01 AM6/26/13
to
On Wed, 26 Jun 2013 16:33:30 +0530, Viresh Kumar wrote:
> On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > diff --git a/drivers/cpufreq/acpi-cpufreq.c
> > b/drivers/cpufreq/acpi-cpufreq.c
>
> > static unsigned int acpi_pstate_strict;
> > -static bool boost_enabled, boost_supported;
> > +static bool boost_enabled;
>
> Instead of this variable use cpufreq_boost_enabled() directly.

OK.

>
> And then this patch may change as well..
>
> I couldn't find any more issues with this patch but some Intel guy
> must review it.

Yes, indeed Intel review is welcome.
--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 26, 2013, 8:20:02 AM6/26/13
to
On Wed, 26 Jun 2013 16:38:15 +0530, Viresh Kumar wrote:

> On 26 June 2013 16:34, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > err_out_kobj_put:
> > list_del(&cpufreq_policy_list);
> > [rest of error path]
>
> I couldn't find err_out_kobj_put in existing code :)
>
> BTW, just add to the list only once everything passed.

Ok, we can do it like that :-)

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 26, 2013, 9:00:02 AM6/26/13
to
On Wed, 26 Jun 2013 16:24:32 +0530, Viresh Kumar wrote:
> On 19 June 2013 22:42, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > Boost sysfs attribute is always exported (to support legacy API). By
> > default boost is exported as read only. One global attribute is
> > available at: /sys/devices/system/cpu/cpufreq/boost.
>
> I assume you are going to fix this as discussed in other threads.
Yes. Boost attribute will be visible only when boost is supported.

>
> > Changes for v4:
> > - Remove boost parameter from cpufreq_frequency_table_cpuinfo()
> > function
> > - Introduce cpufreq_boost_supported() method
> > - Use of cpufreq_boost_supported() and cpufreq_boost_enabled() to
> > decide if frequency shall be skipped
> > - Rename set_boost_freq() to enable_boost()
> > - cpufreq_attr_available_freq() moved to freq_table.c
> > - Use policy list to get access to cpufreq policies
> > - Rename global boost flag (cpufreq_boost_enabled -> boost_enabled)
> > - pr_err corrected ( %sable)
> > - Remove sanity check at cpufreq_boost_trigger_state() entrance [to
> > test if boost is supported]
> > - Use either HW (boost_enable) callback or SW managed boost
> > - Introduce new cpufreq_boost_trigger_state_sw() method to handle
> > boost at SW.
> > - Protect boost_enabled manipulation with lock
> > - Always export boost attribute (preserve legacy behaviour). When
> > boost is not supported this attribute is read only
>
> Very well written changelog. But write it after ---

I will stick to the rule proposed at patch 1/4, ver 4.
I would prefer to set boot_enabled at
cpufreq_boost_trigger_state() method. It is closer to the
cpufreq_driver->enable_boost and cpufreq_boost_trigger_state_sw();
functions, which do change the freq.
OK.

>
> > +int cpufreq_boost_trigger_state(int state)
> > +{
> > + unsigned long flags;
> > + int ret = 0;
> > +
> > + if (boost_enabled != state) {
> > + write_lock_irqsave(&cpufreq_driver_lock, flags);
> > + boost_enabled = state;
> > + if (cpufreq_driver->enable_boost)
> > + ret = cpufreq_driver->enable_boost(state);
^^^^^^^^^^^^^
I would prefer to change this
name to enable_boost_hw
It is more informative, since it is tailored to hw based boost (Intel).

> > + else
> > + ret = cpufreq_boost_trigger_state_sw();
> > +
> > + if (ret) {
> > + boost_enabled = 0;
> > +
> > write_unlock_irqrestore(&cpufreq_driver_lock, flags);
> > + pr_err("%s: BOOST cannot enable (%d)\n",
> > + __func__, ret);
> > +
> > + return ret;
> > + }
> > + write_unlock_irqrestore(&cpufreq_driver_lock,
> > flags);
>
> You can rewrite if (ret) and unlock() code to make it less redundant.
> unlock and return ret at the end and write other stuff before it.

I will rewrite it as follow:

if (ret)
boost_enabled = 0;

write_unlock_irqrestore(&cpufreq_driver_lock, flags);
pr_debug("%s: cpufreq BOOST %s\n", __func__,
state ? "enabled" : "disabled");

return ret;

>
> > + pr_debug("%s: cpufreq BOOST %s\n", __func__,
> > + state ? "enabled" : "disabled");
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +int cpufreq_boost_supported(void)
> > +{
> > + return cpufreq_driver->boost_supported;
> > +}
> > +
> > +int cpufreq_boost_enabled(void)
> > +{
> > + return boost_enabled;
> > +}
>
> EXPORT_SYMBOL_GPL ??

I will export cpufreq_boost_enabled() and cpufreq_boost_supported()

>
> > +/*********************************************************************
> > * REGISTER / UNREGISTER CPUFREQ
> > DRIVER *
> > *********************************************************************/
> >
> > @@ -1936,6 +2019,16 @@ int cpufreq_register_driver(struct
> > cpufreq_driver *driver_data) cpufreq_driver = driver_data;
> > write_unlock_irqrestore(&cpufreq_driver_lock, flags);
> >
> > + if (!cpufreq_driver->boost_supported)
> > + boost.attr.mode = 0444;
Will be removed ^^^^^^^^^^^^^^^
> > +
> > + ret = cpufreq_sysfs_create_file(&(boost.attr));
> > + if (ret) {
> > + pr_err("%s: cannot register global boost sysfs
> > file\n",
> > + __func__);
> > + goto err_null_driver;
> > + }
>
> This would change.

This will be only exported when cpufreq_boost_supported() is true.

>
> > ret = subsys_interface_register(&cpufreq_interface);
> > if (ret)
> > goto err_null_driver;
> > @@ -1992,6 +2085,8 @@ int cpufreq_unregister_driver(struct
> > cpufreq_driver *driver) pr_debug("unregistering driver %s\n",
> > driver->name);
> >
> > subsys_interface_unregister(&cpufreq_interface);
> > +
> > + cpufreq_sysfs_remove_file(&(boost.attr));
> > unregister_hotcpu_notifier(&cpufreq_cpu_notifier);
> >
> > list_del(&cpufreq_policy_list);
> > diff --git a/drivers/cpufreq/freq_table.c
> > b/drivers/cpufreq/freq_table.c index d7a7966..9c8e71e 100644
> > --- a/drivers/cpufreq/freq_table.c
> > +++ b/drivers/cpufreq/freq_table.c
> > @@ -34,6 +34,11 @@ int cpufreq_frequency_table_cpuinfo(struct
> > cpufreq_policy *policy,
> >
> > continue;
> > }
> > + if (cpufreq_boost_supported())
>
> Probably remove this check. Assume somebody while testing exynos,
> just sent boost_supported as false. Then you will not skip this
> frequency and may burn your chip :)

OK.

>
> > + if (!cpufreq_boost_enabled()
> > + && table[i].index == CPUFREQ_BOOST_FREQ)
> > + continue;
>
> This should be enough.

Let's only rely on the cpufreq_boost_enabled() test here.

>
> > pr_debug("table entry %u: %u kHz, %u index\n",
> > i, freq, table[i].index);
> > if (freq < min_freq)
> > @@ -171,7 +176,8 @@ static DEFINE_PER_CPU(struct
> > cpufreq_frequency_table *, cpufreq_show_table); /**
> > * show_available_freqs - show available frequencies for the
> > specified CPU */
> > -static ssize_t show_available_freqs(struct cpufreq_policy *policy,
> > char *buf) +static ssize_t show_available_freqs(struct
> > cpufreq_policy *policy, char *buf,
> > + int show_boost)
> > {
> > unsigned int i = 0;
> > unsigned int cpu = policy->cpu;
> > @@ -186,6 +192,9 @@ static ssize_t show_available_freqs(struct
> > cpufreq_policy *policy, char *buf) for (i = 0;
> > (table[i].frequency != CPUFREQ_TABLE_END); i++) { if
> > (table[i].frequency == CPUFREQ_ENTRY_INVALID) continue;
>
> Add a comment here describing your complex logic.

OK.

>
> > + if (show_boost ^ (table[i].index ==
> > CPUFREQ_BOOST_FREQ))
> > + continue;
> > +
> > count += sprintf(&buf[count], "%d ",
> > table[i].frequency); }
> > count += sprintf(&buf[count], "\n");
> > @@ -194,14 +203,34 @@ static ssize_t show_available_freqs(struct
> > cpufreq_policy *policy, char *buf)
> >
> > }
> >
> > -struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
> > - .attr = { .name = "scaling_available_frequencies",
> > - .mode = 0444,
> > - },
> > - .show = show_available_freqs,
> > -};
> > +#define cpufreq_attr_available_freq(_name) \
> > +struct freq_attr cpufreq_freq_attr_##_name##_freqs = \
> > +__ATTR_RO(_name##_frequencies)
> > +
> > +/**
> > + * show_scaling_available_frequencies - show normal boost
> > frequencies for
>
> You missed this comment earlier. boost??

My mistake. This will be corrected.
We had agreed to talk only about cpufreq :-).

This declaration will be removed.

--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 26, 2013, 10:00:03 AM6/26/13
to
On Wed, 26 Jun 2013 16:35:32 +0530, Viresh Kumar wrote:
> On 11 June 2013 14:33, Lukasz Majewski <l.maj...@samsung.com> wrote:
> > The struct cpufreq_driver has been extended to embrace the
> > information related to boost support.
> >
> > When "boost_mode" device tree attribute is defined for a platform,
> > the low_level_boost pointer is filled with proper address. The
> > .low_level_boost field filled to NULL, indicates that boost is not
> > supported.
>
> This patch is still few generations back :)

But this is v2 version of boost patches.

Please also review:
[PATCH v4 4/7]
[PATCH v4 5/7]
[PATCH v4 6/7]
[PATCH v4 7/7] - disable boost at thermal framework



--
Best regards,

Lukasz Majewski

Samsung R&D Institute Poland (SRPOL) | Linux Platform Group

Lukasz Majewski

unread,
Jun 26, 2013, 10:10:02 AM6/26/13
to
On Wed, 26 Jun 2013 14:54:12 +0200, Lukasz Majewski wrote:
> > >
> > > +int cpufreq_boost_trigger_state(int state);
> >
> > Why is this present here?
>
> We had agreed to talk only about cpufreq :-).
>
> This declaration will be removed.

Correction:

This declaration is needed for allowing disabling cpufreq boost at
thermal subsystem (please refer to [PATCH v4 7/7]).

Viresh Kumar

unread,
Jun 27, 2013, 12:10:01 AM6/27/13
to
On 26 June 2013 19:28, Lukasz Majewski <l.maj...@samsung.com> wrote:
> On Wed, 26 Jun 2013 16:35:32 +0530, Viresh Kumar wrote:
>> This patch is still few generations back :)
>
> But this is v2 version of boost patches.

My mistake....

> Please also review:
> [PATCH v4 4/7]
> [PATCH v4 5/7]
> [PATCH v4 6/7]
> [PATCH v4 7/7] - disable boost at thermal framework

don't worry I will review everything. I went home after reviewing half
of the patches.
It is loading more messages.
0 new messages