aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/device_pm.c11
-rw-r--r--drivers/acpi/sleep.c24
-rw-r--r--drivers/base/core.c25
-rw-r--r--drivers/base/power/power.h1
-rw-r--r--drivers/base/power/wakeirq.c13
-rw-r--r--drivers/cpufreq/Kconfig.arm1
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c20
-rw-r--r--drivers/cpufreq/arm_big_little.c9
-rw-r--r--drivers/cpufreq/brcmstb-avs-cpufreq.c6
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c12
-rw-r--r--drivers/cpufreq/cpufreq-dt.c8
-rw-r--r--drivers/cpufreq/cpufreq.c28
-rw-r--r--drivers/cpufreq/e_powersaver.c8
-rw-r--r--drivers/cpufreq/elanfreq.c3
-rw-r--r--drivers/cpufreq/freq_table.c16
-rw-r--r--drivers/cpufreq/ia64-acpi-cpufreq.c7
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c7
-rw-r--r--drivers/cpufreq/longhaul.c3
-rw-r--r--drivers/cpufreq/mediatek-cpufreq.c13
-rw-r--r--drivers/cpufreq/p4-clockmod.c3
-rw-r--r--drivers/cpufreq/powernow-k6.c3
-rw-r--r--drivers/cpufreq/powernow-k7.c3
-rw-r--r--drivers/cpufreq/powernow-k8.c24
-rw-r--r--drivers/cpufreq/powernv-cpufreq.c11
-rw-r--r--drivers/cpufreq/ppc_cbe_cpufreq.c5
-rw-r--r--drivers/cpufreq/pxa2xx-cpufreq.c4
-rw-r--r--drivers/cpufreq/pxa3xx-cpufreq.c4
-rw-r--r--drivers/cpufreq/qoriq-cpufreq.c21
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c13
-rw-r--r--drivers/cpufreq/sc520_freq.c3
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c10
-rw-r--r--drivers/cpufreq/sfi-cpufreq.c3
-rw-r--r--drivers/cpufreq/sh-cpufreq.c22
-rw-r--r--drivers/cpufreq/sparc-us2e-cpufreq.c3
-rw-r--r--drivers/cpufreq/sparc-us3-cpufreq.c3
-rw-r--r--drivers/cpufreq/speedstep-centrino.c4
-rw-r--r--drivers/cpufreq/speedstep-ich.c4
-rw-r--r--drivers/cpufreq/speedstep-smi.c4
-rw-r--r--drivers/cpufreq/tegra186-cpufreq.c3
-rw-r--r--drivers/cpuidle/cpuidle-arm.c1
-rw-r--r--drivers/cpuidle/cpuidle-exynos.c3
-rw-r--r--drivers/cpuidle/cpuidle.c9
-rw-r--r--drivers/cpuidle/poll_state.c17
-rw-r--r--drivers/cpuidle/sysfs.c54
-rw-r--r--drivers/pcmcia/cs.c10
-rw-r--r--drivers/pcmcia/cs_internal.h1
-rw-r--r--drivers/powercap/intel_rapl.c1
47 files changed, 261 insertions, 200 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index c4d0a1c912f0..3d96e4da2d98 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -543,6 +543,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
unsigned long long ret;
int d_min, d_max;
bool wakeup = false;
+ bool has_sxd = false;
acpi_status status;
/*
@@ -581,6 +582,10 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
else
return -ENODATA;
}
+
+ if (status == AE_OK)
+ has_sxd = true;
+
d_min = ret;
wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
&& adev->wakeup.sleep_state >= target_state;
@@ -599,7 +604,11 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
method[3] = 'W';
status = acpi_evaluate_integer(handle, method, NULL, &ret);
if (status == AE_NOT_FOUND) {
- if (target_state > ACPI_STATE_S0)
+ /* No _SxW. In this case, the ACPI spec says that we
+ * must not go into any power state deeper than the
+ * value returned from _SxD.
+ */
+ if (has_sxd && target_state > ACPI_STATE_S0)
d_max = d_min;
} else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) {
/* Fall back to D3cold if ret is not a valid state. */
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index b35923e3a926..99a1a650326d 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -849,23 +849,25 @@ static void lpi_check_constraints(void)
int i;
for (i = 0; i < lpi_constraints_table_size; ++i) {
+ acpi_handle handle = lpi_constraints_table[i].handle;
struct acpi_device *adev;
- if (acpi_bus_get_device(lpi_constraints_table[i].handle, &adev))
+ if (!handle || acpi_bus_get_device(handle, &adev))
continue;
- acpi_handle_debug(adev->handle,
+ acpi_handle_debug(handle,
"LPI: required min power state:%s current power state:%s\n",
acpi_power_state_string(lpi_constraints_table[i].min_dstate),
acpi_power_state_string(adev->power.state));
if (!adev->flags.power_manageable) {
- acpi_handle_info(adev->handle, "LPI: Device not power manageble\n");
+ acpi_handle_info(handle, "LPI: Device not power manageable\n");
+ lpi_constraints_table[i].handle = NULL;
continue;
}
if (adev->power.state < lpi_constraints_table[i].min_dstate)
- acpi_handle_info(adev->handle,
+ acpi_handle_info(handle,
"LPI: Constraint not met; min power state:%s current power state:%s\n",
acpi_power_state_string(lpi_constraints_table[i].min_dstate),
acpi_power_state_string(adev->power.state));
@@ -951,15 +953,8 @@ static int acpi_s2idle_prepare(void)
if (lps0_device_handle) {
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY);
- } else {
- /*
- * The configuration of GPEs is changed here to avoid spurious
- * wakeups, but that should not be necessary if this is a
- * "low-power S0" platform and the low-power S0 _DSM is present.
- */
- acpi_enable_all_wakeup_gpes();
- acpi_os_wait_events_complete();
}
+
if (acpi_sci_irq_valid())
enable_irq_wake(acpi_sci_irq);
@@ -992,8 +987,9 @@ static void acpi_s2idle_sync(void)
* The EC driver uses the system workqueue and an additional special
* one, so those need to be flushed too.
*/
+ acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */
acpi_ec_flush_work();
- acpi_os_wait_events_complete();
+ acpi_os_wait_events_complete(); /* synchronize Notify handling */
s2idle_wakeup = false;
}
@@ -1005,8 +1001,6 @@ static void acpi_s2idle_restore(void)
if (lps0_device_handle) {
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
- } else {
- acpi_enable_all_runtime_gpes();
}
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 5847364f25d9..b610816eb887 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -196,8 +196,10 @@ struct device_link *device_link_add(struct device *consumer,
}
list_for_each_entry(link, &supplier->links.consumers, s_node)
- if (link->consumer == consumer)
+ if (link->consumer == consumer) {
+ kref_get(&link->kref);
goto out;
+ }
link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link)
@@ -222,6 +224,7 @@ struct device_link *device_link_add(struct device *consumer,
link->consumer = consumer;
INIT_LIST_HEAD(&link->c_node);
link->flags = flags;
+ kref_init(&link->kref);
/* Determine the initial link state. */
if (flags & DL_FLAG_STATELESS) {
@@ -292,8 +295,10 @@ static void __device_link_free_srcu(struct rcu_head *rhead)
device_link_free(container_of(rhead, struct device_link, rcu_head));
}
-static void __device_link_del(struct device_link *link)
+static void __device_link_del(struct kref *kref)
{
+ struct device_link *link = container_of(kref, struct device_link, kref);
+
dev_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier));
@@ -305,8 +310,10 @@ static void __device_link_del(struct device_link *link)
call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
}
#else /* !CONFIG_SRCU */
-static void __device_link_del(struct device_link *link)
+static void __device_link_del(struct kref *kref)
{
+ struct device_link *link = container_of(kref, struct device_link, kref);
+
dev_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier));
@@ -324,13 +331,15 @@ static void __device_link_del(struct device_link *link)
* @link: Device link to delete.
*
* The caller must ensure proper synchronization of this function with runtime
- * PM.
+ * PM. If the link was added multiple times, it needs to be deleted as often.
+ * Care is required for hotplugged devices: Their links are purged on removal
+ * and calling device_link_del() is then no longer allowed.
*/
void device_link_del(struct device_link *link)
{
device_links_write_lock();
device_pm_lock();
- __device_link_del(link);
+ kref_put(&link->kref, __device_link_del);
device_pm_unlock();
device_links_write_unlock();
}
@@ -444,7 +453,7 @@ static void __device_links_no_driver(struct device *dev)
continue;
if (link->flags & DL_FLAG_AUTOREMOVE)
- __device_link_del(link);
+ kref_put(&link->kref, __device_link_del);
else if (link->status != DL_STATE_SUPPLIER_UNBIND)
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
}
@@ -597,13 +606,13 @@ static void device_links_purge(struct device *dev)
list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
WARN_ON(link->status == DL_STATE_ACTIVE);
- __device_link_del(link);
+ __device_link_del(&link->kref);
}
list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
WARN_ON(link->status != DL_STATE_DORMANT &&
link->status != DL_STATE_NONE);
- __device_link_del(link);
+ __device_link_del(&link->kref);
}
device_links_write_unlock();
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 21244c53e377..86e67e70b509 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -31,6 +31,7 @@ struct wake_irq {
struct device *dev;
unsigned int status;
int irq;
+ const char *name;
};
extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c
index 6637fc319269..b8fa5c0f2d13 100644
--- a/drivers/base/power/wakeirq.c
+++ b/drivers/base/power/wakeirq.c
@@ -112,6 +112,7 @@ void dev_pm_clear_wake_irq(struct device *dev)
free_irq(wirq->irq, wirq);
wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
}
+ kfree(wirq->name);
kfree(wirq);
}
EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
@@ -184,6 +185,12 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
if (!wirq)
return -ENOMEM;
+ wirq->name = kasprintf(GFP_KERNEL, "%s:wakeup", dev_name(dev));
+ if (!wirq->name) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
wirq->dev = dev;
wirq->irq = irq;
irq_set_status_flags(irq, IRQ_NOAUTOEN);
@@ -196,9 +203,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
* so we use a threaded irq.
*/
err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,
- IRQF_ONESHOT, dev_name(dev), wirq);
+ IRQF_ONESHOT, wirq->name, wirq);
if (err)
- goto err_free;
+ goto err_free_name;
err = dev_pm_attach_wake_irq(dev, irq, wirq);
if (err)
@@ -210,6 +217,8 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
err_free_irq:
free_irq(irq, wirq);
+err_free_name:
+ kfree(wirq->name);
err_free:
kfree(wirq);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index fb586e09682d..833b5f41f596 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -45,6 +45,7 @@ config ARM_DT_BL_CPUFREQ
config ARM_SCPI_CPUFREQ
tristate "SCPI based CPUfreq driver"
depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
+ depends on !CPU_THERMAL || THERMAL
help
This adds the CPUfreq driver support for ARM platforms using SCPI
protocol for CPU power management.
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index d0c34df0529c..9449657d72f0 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -794,15 +794,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
valid_states++;
}
freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
+ policy->freq_table = freq_table;
perf->state = 0;
- result = cpufreq_table_validate_and_show(policy, freq_table);
- if (result)
- goto err_freqfree;
-
- if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq)
- pr_warn(FW_WARN "P-state 0 is not max freq\n");
-
switch (perf->control_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO:
/*
@@ -842,8 +836,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
return result;
-err_freqfree:
- kfree(freq_table);
err_unreg:
acpi_processor_unregister_performance(cpu);
err_free_mask:
@@ -871,6 +863,15 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
+static void acpi_cpufreq_cpu_ready(struct cpufreq_policy *policy)
+{
+ struct acpi_processor_performance *perf = per_cpu_ptr(acpi_perf_data,
+ policy->cpu);
+
+ if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq)
+ pr_warn(FW_WARN "P-state 0 is not max freq\n");
+}
+
static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
{
struct acpi_cpufreq_data *data = policy->driver_data;
@@ -898,6 +899,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.bios_limit = acpi_processor_get_bios_limit,
.init = acpi_cpufreq_cpu_init,
.exit = acpi_cpufreq_cpu_exit,
+ .ready = acpi_cpufreq_cpu_ready,
.resume = acpi_cpufreq_resume,
.name = "acpi-cpufreq",
.attr = acpi_cpufreq_attr,
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index c56b57dcfda5..1d7ef5fc1977 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -483,14 +483,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
if (ret)
return ret;
- ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]);
- if (ret) {
- dev_err(cpu_dev, "CPU %d, cluster: %d invalid freq table\n",
- policy->cpu, cur_cluster);
- put_cluster_clk_and_freq_table(cpu_dev, policy->cpus);
- return ret;
- }
-
+ policy->freq_table = freq_table[cur_cluster];
policy->cpuinfo.transition_latency =
arm_bL_ops->get_transition_latency(cpu_dev);
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
index 7281a2c19c36..6cdac1aaf23c 100644
--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c
+++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
@@ -902,11 +902,7 @@ static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
return ret;
}
- ret = cpufreq_table_validate_and_show(policy, freq_table);
- if (ret) {
- dev_err(dev, "invalid frequency table: %d\n", ret);
- return ret;
- }
+ policy->freq_table = freq_table;
/* All cores share the same clock and thus the same policy. */
cpumask_setall(policy->cpus);
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index a1c3025f9df7..8300a9fcb80c 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -20,6 +20,7 @@
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/dmi.h>
+#include <linux/time.h>
#include <linux/vmalloc.h>
#include <asm/unaligned.h>
@@ -162,6 +163,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq = cppc_dmi_max_khz;
policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num);
+ policy->transition_delay_us = cppc_get_transition_latency(cpu_num) /
+ NSEC_PER_USEC;
policy->shared_type = cpu->shared_type;
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
@@ -230,8 +233,13 @@ static int __init cppc_cpufreq_init(void)
return ret;
out:
- for_each_possible_cpu(i)
- kfree(all_cpu_data[i]);
+ for_each_possible_cpu(i) {
+ cpu = all_cpu_data[i];
+ if (!cpu)
+ break;
+ free_cpumask_var(cpu->shared_cpu_map);
+ kfree(cpu);
+ }
kfree(all_cpu_data);
return -ENODEV;
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index de3d104c25d7..190ea0dccb79 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -258,16 +258,10 @@ static int cpufreq_init(struct cpufreq_policy *policy)
priv->cpu_dev = cpu_dev;
policy->driver_data = priv;
policy->clk = cpu_clk;
+ policy->freq_table = freq_table;
policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000;
- ret = cpufreq_table_validate_and_show(policy, freq_table);
- if (ret) {
- dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
- ret);
- goto out_free_cpufreq_table;
- }
-
/* Support turbo/boost mode */
if (policy_has_boost_freq(policy)) {
/* This gets disabled by core on driver unregister */
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index de33ebf008ad..075d18f6ba7a 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -178,14 +178,7 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table,
unsigned int transition_latency)
{
- int ret;
-
- ret = cpufreq_table_validate_and_show(policy, table);
- if (ret) {
- pr_err("%s: invalid frequency table: %d\n", __func__, ret);
- return ret;
- }
-
+ policy->freq_table = table;
policy->cpuinfo.transition_latency = transition_latency;
/*
@@ -1219,6 +1212,10 @@ static int cpufreq_online(unsigned int cpu)
goto out_free_policy;
}
+ ret = cpufreq_table_validate_and_sort(policy);
+ if (ret)
+ goto out_exit_policy;
+
down_write(&policy->rwsem);
if (new_policy) {
@@ -1249,7 +1246,7 @@ static int cpufreq_online(unsigned int cpu)
policy->cur = cpufreq_driver->get(policy->cpu);
if (!policy->cur) {
pr_err("%s: ->get() failed\n", __func__);
- goto out_exit_policy;
+ goto out_destroy_policy;
}
}
@@ -1296,7 +1293,7 @@ static int cpufreq_online(unsigned int cpu)
if (new_policy) {
ret = cpufreq_add_dev_interface(policy);
if (ret)
- goto out_exit_policy;
+ goto out_destroy_policy;
cpufreq_stats_create_table(policy);
@@ -1311,7 +1308,7 @@ static int cpufreq_online(unsigned int cpu)
__func__, cpu, ret);
/* cpufreq_policy_free() will notify based on this */
new_policy = false;
- goto out_exit_policy;
+ goto out_destroy_policy;
}
up_write(&policy->rwsem);
@@ -1326,15 +1323,16 @@ static int cpufreq_online(unsigned int cpu)
return 0;
-out_exit_policy:
+out_destroy_policy:
+ for_each_cpu(j, policy->real_cpus)
+ remove_cpu_dev_symlink(policy, get_cpu_device(j));
+
up_write(&policy->rwsem);
+out_exit_policy:
if (cpufreq_driver->exit)
cpufreq_driver->exit(policy);
- for_each_cpu(j, policy->real_cpus)
- remove_cpu_dev_symlink(policy, get_cpu_device(j));
-
out_free_policy:
cpufreq_policy_free(policy);
return ret;
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c
index cdf097b29862..60bea302abbe 100644
--- a/drivers/cpufreq/e_powersaver.c
+++ b/drivers/cpufreq/e_powersaver.c
@@ -184,7 +184,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
struct cpuinfo_x86 *c = &cpu_data(0);
struct cpufreq_frequency_table *f_table;
int k, step, voltage;
- int ret;
int states;
#if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
unsigned int limit;
@@ -359,12 +358,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
}
policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
-
- ret = cpufreq_table_validate_and_show(policy, &centaur->freq_table[0]);
- if (ret) {
- kfree(centaur);
- return ret;
- }
+ policy->freq_table = &centaur->freq_table[0];
return 0;
}
diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c
index 45e2ca62515e..03419f064752 100644
--- a/drivers/cpufreq/elanfreq.c
+++ b/drivers/cpufreq/elanfreq.c
@@ -165,7 +165,8 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
if (pos->frequency > max_freq)
pos->frequency = CPUFREQ_ENTRY_INVALID;
- return cpufreq_table_validate_and_show(policy, elanfreq_table);
+ policy->freq_table = elanfreq_table;
+ return 0;
}
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
index 6d007f824ca7..10e119ae66dd 100644
--- a/drivers/cpufreq/freq_table.c
+++ b/drivers/cpufreq/freq_table.c
@@ -362,10 +362,24 @@ int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
return ret;
policy->freq_table = table;
- return set_freq_table_sorted(policy);
+ return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show);
+int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy)
+{
+ int ret;
+
+ if (!policy->freq_table)
+ return 0;
+
+ ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table);
+ if (ret)
+ return ret;
+
+ return set_freq_table_sorted(policy);
+}
+
MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("CPUfreq frequency table helpers");
MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index a757c0a1e7b5..7974a2fdb760 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -270,10 +270,7 @@ acpi_cpufreq_cpu_init (
}
}
- result = cpufreq_table_validate_and_show(policy, freq_table);
- if (result) {
- goto err_freqfree;
- }
+ policy->freq_table = freq_table;
/* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE);
@@ -296,8 +293,6 @@ acpi_cpufreq_cpu_init (
return (result);
- err_freqfree:
- kfree(freq_table);
err_unreg:
acpi_processor_unregister_performance(cpu);
err_free:
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index ff67859948b3..83cf631fc9bc 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -52,6 +52,7 @@ static struct clk_bulk_data clks[] = {
static struct device *cpu_dev;
static bool free_opp;
static struct cpufreq_frequency_table *freq_table;
+static unsigned int max_freq;
static unsigned int transition_latency;
static u32 *imx6_soc_volt;
@@ -196,7 +197,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
policy->clk = clks[ARM].clk;
ret = cpufreq_generic_init(policy, freq_table, transition_latency);
- policy->suspend_freq = policy->max;
+ policy->suspend_freq = max_freq;
return ret;
}
@@ -437,12 +438,12 @@ soc_opp_out:
* freq_table initialised from OPP is therefore sorted in the
* same order.
*/
+ max_freq = freq_table[--num].frequency;
opp = dev_pm_opp_find_freq_exact(cpu_dev,
freq_table[0].frequency * 1000, true);
min_volt = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp);
- opp = dev_pm_opp_find_freq_exact(cpu_dev,
- freq_table[--num].frequency * 1000, true);
+ opp = dev_pm_opp_find_freq_exact(cpu_dev, max_freq * 1000, true);
max_volt = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp);
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index f730b6528c18..61a4c5b08219 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -895,8 +895,9 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
longhaul_setup_voltagescaling();
policy->transition_delay_us = 200000; /* usec */
+ policy->freq_table = longhaul_table;
- return cpufreq_table_validate_and_show(policy, longhaul_table);
+ return 0;
}
static struct cpufreq_driver longhaul_driver = {
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 8c04dddd3c28..eb8920d39818 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -460,21 +460,12 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
return ret;
}
- ret = cpufreq_table_validate_and_show(policy, freq_table);
- if (ret) {
- pr_err("%s: invalid frequency table: %d\n", __func__, ret);
- goto out_free_cpufreq_table;
- }
-
cpumask_copy(policy->cpus, &info->cpus);
+ policy->freq_table = freq_table;
policy->driver_data = info;
policy->clk = info->cpu_clk;
return 0;
-
-out_free_cpufreq_table:
- dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
- return ret;
}
static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
@@ -578,7 +569,7 @@ static int __init mtk_cpufreq_driver_init(void)
match = of_match_node(mtk_cpufreq_machines, np);
of_node_put(np);
if (!match) {
- pr_warn("Machine is not compatible with mtk-cpufreq\n");
+ pr_debug("Machine is not compatible with mtk-cpufreq\n");
return -ENODEV;
}
diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c
index a25741b1281b..911206243050 100644
--- a/drivers/cpufreq/p4-clockmod.c
+++ b/drivers/cpufreq/p4-clockmod.c
@@ -202,8 +202,9 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy)
/* the transition latency is set to be 1 higher than the maximum
* transition latency of the ondemand governor */
policy->cpuinfo.transition_latency = 10000001;
+ policy->freq_table = &p4clockmod_table[0];
- return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]);
+ return 0;
}
diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c
index dedd2568e852..8a8ea68611a8 100644
--- a/drivers/cpufreq/powernow-k6.c
+++ b/drivers/cpufreq/powernow-k6.c
@@ -214,8 +214,9 @@ have_busfreq:
/* cpuinfo and default policy values */
policy->cpuinfo.transition_latency = 500000;
+ policy->freq_table = clock_ratio;
- return cpufreq_table_validate_and_show(policy, clock_ratio);
+ return 0;
}
diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c
index 302e9ce793a0..d6cb052b0a75 100644
--- a/drivers/cpufreq/powernow-k7.c
+++ b/drivers/cpufreq/powernow-k7.c
@@ -639,8 +639,9 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency =
cpufreq_scale(2000000UL, fsb, latency);
+ policy->freq_table = powernow_table;
- return cpufreq_table_validate_and_show(policy, powernow_table);
+ return 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 b01e31db5f83..fb77b39a4ce3 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -122,14 +122,12 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data)
static void count_off_irt(struct powernow_k8_data *data)
{
udelay((1 << data->irt) * 10);
- return;
}
/* the voltage stabilization time */
static void count_off_vst(struct powernow_k8_data *data)
{
udelay(data->vstable * VST_UNITS_20US);
- return;
}
/* need to init the control msr to a safe value (for each cpu) */
@@ -591,10 +589,8 @@ static int fill_powernow_table(struct powernow_k8_data *data,
powernow_table = kzalloc((sizeof(*powernow_table)
* (data->numps + 1)), GFP_KERNEL);
- if (!powernow_table) {
- pr_err("powernow_table memory alloc failure\n");
+ if (!powernow_table)
return -ENOMEM;
- }
for (j = 0; j < data->numps; j++) {
int freq;
@@ -760,10 +756,8 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* fill in data->powernow_table */
powernow_table = kzalloc((sizeof(*powernow_table)
* (data->acpi_data.state_count + 1)), GFP_KERNEL);
- if (!powernow_table) {
- pr_debug("powernow_table memory alloc failure\n");
+ if (!powernow_table)
goto err_out;
- }
/* fill in data */
data->numps = data->acpi_data.state_count;
@@ -1042,10 +1036,8 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- pr_err("unable to alloc powernow_k8_data\n");
+ if (!data)
return -ENOMEM;
- }
data->cpu = pol->cpu;
@@ -1084,15 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
cpumask_copy(pol->cpus, topology_core_cpumask(pol->cpu));
data->available_cores = pol->cpus;
-
- /* min/max the cpu is capable of */
- if (cpufreq_table_validate_and_show(pol, data->powernow_table)) {
- pr_err(FW_BUG "invalid powernow_table\n");
- powernow_k8_cpu_exit_acpi(data);
- kfree(data->powernow_table);
- kfree(data);
- return -EINVAL;
- }
+ pol->freq_table = data->powernow_table;
pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c
index 29cdec198657..0591874856d3 100644
--- a/drivers/cpufreq/powernv-cpufreq.c
+++ b/drivers/cpufreq/powernv-cpufreq.c
@@ -812,7 +812,7 @@ gpstates_done:
static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
- int base, i, ret;
+ int base, i;
struct kernfs_node *kn;
struct global_pstate_info *gpstates;
@@ -848,15 +848,10 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
gpstates->timer.expires = jiffies +
msecs_to_jiffies(GPSTATE_TIMER_INTERVAL);
spin_lock_init(&gpstates->gpstate_lock);
- ret = cpufreq_table_validate_and_show(policy, powernv_freqs);
-
- if (ret < 0) {
- kfree(policy->driver_data);
- return ret;
- }
+ policy->freq_table = powernv_freqs;
policy->fast_switch_possible = true;
- return ret;
+ return 0;
}
static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c
index 5a4c5a639f61..41a0f0be3f9f 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq.c
@@ -121,9 +121,8 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
#endif
- /* this ensures that policy->cpuinfo_min
- * and policy->cpuinfo_max are set correctly */
- return cpufreq_table_validate_and_show(policy, cbe_freqs);
+ policy->freq_table = cbe_freqs;
+ return 0;
}
static int cbe_cpufreq_target(struct cpufreq_policy *policy,
diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c
index 06b024a3e474..46254e583982 100644
--- a/drivers/cpufreq/pxa2xx-cpufreq.c
+++ b/drivers/cpufreq/pxa2xx-cpufreq.c
@@ -292,10 +292,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
pr_info("using %s frequency table\n",
pxa255_turbo_table ? "turbo" : "run");
- cpufreq_table_validate_and_show(policy, pxa255_freq_table);
+ policy->freq_table = pxa255_freq_table;
}
else if (cpu_is_pxa27x()) {
- cpufreq_table_validate_and_show(policy, pxa27x_freq_table);
+ policy->freq_table = pxa27x_freq_table;
}
pr_info("frequency change support initialized\n");
diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c
index a01275900389..7acc7fa4536d 100644
--- a/drivers/cpufreq/pxa3xx-cpufreq.c
+++ b/drivers/cpufreq/pxa3xx-cpufreq.c
@@ -108,7 +108,9 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
pxa3xx_freqs_num = num;
pxa3xx_freqs_table = table;
- return cpufreq_table_validate_and_show(policy, table);
+ policy->freq_table = table;
+
+ return 0;
}
static void __update_core_freq(struct pxa3xx_freq_info *info)
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c
index 0562761a3dec..3d773f64b4df 100644
--- a/drivers/cpufreq/qoriq-cpufreq.c
+++ b/drivers/cpufreq/qoriq-cpufreq.c
@@ -165,7 +165,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table,
static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
struct device_node *np;
- int i, count, ret;
+ int i, count;
u32 freq;
struct clk *clk;
const struct clk_hw *hwclk;
@@ -192,16 +192,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
count = clk_hw_get_num_parents(hwclk);
data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
- if (!data->pclk) {
- pr_err("%s: no memory\n", __func__);
+ if (!data->pclk)
goto err_nomem2;
- }
table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
- if (!table) {
- pr_err("%s: no memory\n", __func__);
+ if (!table)
goto err_pclk;
- }
for (i = 0; i < count; i++) {
clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
@@ -213,14 +209,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
freq_table_redup(table, count);
freq_table_sort(table, count);
table[i].frequency = CPUFREQ_TABLE_END;
-
- /* set the min and max frequency properly */
- ret = cpufreq_table_validate_and_show(policy, table);
- if (ret) {
- pr_err("invalid frequency table: %d\n", ret);
- goto err_nomem1;
- }
-
+ policy->freq_table = table;
data->table = table;
/* update ->cpus if we have cluster, no harm if not */
@@ -236,8 +225,6 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
return 0;
-err_nomem1:
- kfree(table);
err_pclk:
kfree(data->pclk);
err_nomem2:
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 6bebc1f9f55a..909bd6e27639 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -351,11 +351,8 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
static int s3c_cpufreq_init(struct cpufreq_policy *policy)
{
policy->clk = clk_arm;
-
policy->cpuinfo.transition_latency = cpu_cur.info->latency;
-
- if (ftab)
- return cpufreq_table_validate_and_show(policy, ftab);
+ policy->freq_table = ftab;
return 0;
}
@@ -479,10 +476,8 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
* initdata. */
ours = kzalloc(sizeof(*ours), GFP_KERNEL);
- if (ours == NULL) {
- pr_err("%s: no memory\n", __func__);
+ if (!ours)
return -ENOMEM;
- }
*ours = *board;
cpu_cur.board = ours;
@@ -568,10 +563,8 @@ static int s3c_cpufreq_build_freq(void)
size++;
ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL);
- if (!ftab) {
- pr_err("%s: no memory for tables\n", __func__);
+ if (!ftab)
return -ENOMEM;
- }
ftab_size = size;
diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c
index 4225501a4b78..abaa75e86148 100644
--- a/drivers/cpufreq/sc520_freq.c
+++ b/drivers/cpufreq/sc520_freq.c
@@ -83,8 +83,9 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */
policy->cpuinfo.transition_latency = 1000000; /* 1ms */
+ policy->freq_table = sc520_freq_table;
- return cpufreq_table_validate_and_show(policy, sc520_freq_table);
+ return 0;
}
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index d300a163945f..87a98ec77773 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -158,13 +158,7 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
}
policy->driver_data = priv;
-
- ret = cpufreq_table_validate_and_show(policy, freq_table);
- if (ret) {
- dev_err(cpu_dev, "%s: invalid frequency table: %d\n", __func__,
- ret);
- goto out_put_clk;
- }
+ policy->freq_table = freq_table;
/* scpi allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true;
@@ -178,8 +172,6 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
policy->fast_switch_possible = false;
return 0;
-out_put_clk:
- clk_put(priv->clk);
out_free_cpufreq_table:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_priv:
diff --git a/drivers/cpufreq/sfi-cpufreq.c b/drivers/cpufreq/sfi-cpufreq.c
index 3779742f86e3..9767afe05da2 100644
--- a/drivers/cpufreq/sfi-cpufreq.c
+++ b/drivers/cpufreq/sfi-cpufreq.c
@@ -72,8 +72,9 @@ static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy)
{
policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
policy->cpuinfo.transition_latency = 100000; /* 100us */
+ policy->freq_table = freq_table;
- return cpufreq_table_validate_and_show(policy, freq_table);
+ return 0;
}
static struct cpufreq_driver sfi_cpufreq_driver = {
diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c
index 28893d435cf5..5096c0ab781b 100644
--- a/drivers/cpufreq/sh-cpufreq.c
+++ b/drivers/cpufreq/sh-cpufreq.c
@@ -122,11 +122,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL;
if (freq_table) {
- int result;
-
- result = cpufreq_table_validate_and_show(policy, freq_table);
- if (result)
- return result;
+ policy->freq_table = freq_table;
} else {
dev_notice(dev, "no frequency table found, falling back "
"to rate rounding.\n");
@@ -137,11 +133,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
(clk_round_rate(cpuclk, ~0UL) + 500) / 1000;
}
- dev_info(dev, "CPU Frequencies - Minimum %u.%03u MHz, "
- "Maximum %u.%03u MHz.\n",
- policy->min / 1000, policy->min % 1000,
- policy->max / 1000, policy->max % 1000);
-
return 0;
}
@@ -155,6 +146,16 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
return 0;
}
+static void sh_cpufreq_cpu_ready(struct cpufreq_policy *policy)
+{
+ struct device *dev = get_cpu_device(policy->cpu);
+
+ dev_info(dev, "CPU Frequencies - Minimum %u.%03u MHz, "
+ "Maximum %u.%03u MHz.\n",
+ policy->min / 1000, policy->min % 1000,
+ policy->max / 1000, policy->max % 1000);
+}
+
static struct cpufreq_driver sh_cpufreq_driver = {
.name = "sh",
.flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING,
@@ -163,6 +164,7 @@ static struct cpufreq_driver sh_cpufreq_driver = {
.verify = sh_cpufreq_verify,
.init = sh_cpufreq_cpu_init,
.exit = sh_cpufreq_cpu_exit,
+ .ready = sh_cpufreq_cpu_ready,
.attr = cpufreq_generic_attr,
};
diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c
index 90f33efee5fc..bbd1d1e166b8 100644
--- a/drivers/cpufreq/sparc-us2e-cpufreq.c
+++ b/drivers/cpufreq/sparc-us2e-cpufreq.c
@@ -292,8 +292,9 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick;
+ policy->freq_table = table;
- return cpufreq_table_validate_and_show(policy, table);
+ return 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 30645b0118f9..51e3c6018e74 100644
--- a/drivers/cpufreq/sparc-us3-cpufreq.c
+++ b/drivers/cpufreq/sparc-us3-cpufreq.c
@@ -136,8 +136,9 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick;
+ policy->freq_table = table;
- return cpufreq_table_validate_and_show(policy, table);
+ return 0;
}
static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c
index 4fa5adf16c70..a1fb735685db 100644
--- a/drivers/cpufreq/speedstep-centrino.c
+++ b/drivers/cpufreq/speedstep-centrino.c
@@ -394,9 +394,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 10000;
/* 10uS transition latency */
+ policy->freq_table = per_cpu(centrino_model, policy->cpu)->op_points;
- return cpufreq_table_validate_and_show(policy,
- per_cpu(centrino_model, policy->cpu)->op_points);
+ return 0;
}
static int centrino_cpu_exit(struct cpufreq_policy *policy)
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c
index 0412a246a785..fbbcb88db061 100644
--- a/drivers/cpufreq/speedstep-ich.c
+++ b/drivers/cpufreq/speedstep-ich.c
@@ -304,7 +304,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
if (gf.ret)
return gf.ret;
- return cpufreq_table_validate_and_show(policy, speedstep_freqs);
+ policy->freq_table = speedstep_freqs;
+
+ return 0;
}
diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c
index d23f24ccff38..01fe70dae20b 100644
--- a/drivers/cpufreq/speedstep-smi.c
+++ b/drivers/cpufreq/speedstep-smi.c
@@ -266,7 +266,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
pr_debug("workaround worked.\n");
}
- return cpufreq_table_validate_and_show(policy, speedstep_freqs);
+ policy->freq_table = speedstep_freqs;
+
+ return 0;
}
static unsigned int speedstep_get(unsigned int cpu)
diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c
index fe7875311d62..1f59966573aa 100644
--- a/drivers/cpufreq/tegra186-cpufreq.c
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -78,7 +78,8 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
policy->driver_data =
data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core);
- cpufreq_table_validate_and_show(policy, cluster->table);
+ policy->freq_table = cluster->table;
+ break;
}
policy->cpuinfo.transition_latency = 300 * 1000;
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index ddee1b601b89..e07bc7ace774 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -129,7 +129,6 @@ static int __init arm_idle_init_cpu(int cpu)
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- pr_err("Failed to allocate cpuidle device\n");
ret = -ENOMEM;
goto out_unregister_drv;
}
diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c
index 00cd129b10a4..0171a6e190d7 100644
--- a/drivers/cpuidle/cpuidle-exynos.c
+++ b/drivers/cpuidle/cpuidle-exynos.c
@@ -117,7 +117,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev)
int ret;
if (IS_ENABLED(CONFIG_SMP) &&
- of_machine_is_compatible("samsung,exynos4210")) {
+ (of_machine_is_compatible("samsung,exynos4210") ||
+ of_machine_is_compatible("samsung,exynos3250"))) {
exynos_cpuidle_pdata = pdev->dev.platform_data;
ret = cpuidle_register(&exynos_coupled_idle_driver,
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 68a16827f45f..0003e9a02637 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -131,6 +131,10 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
static void enter_s2idle_proper(struct cpuidle_driver *drv,
struct cpuidle_device *dev, int index)
{
+ ktime_t time_start, time_end;
+
+ time_start = ns_to_ktime(local_clock());
+
/*
* trace_suspend_resume() called by tick_freeze() for the last CPU
* executing it contains RCU usage regarded as invalid in the idle
@@ -152,6 +156,11 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv,
*/
RCU_NONIDLE(tick_unfreeze());
start_critical_timings();
+
+ time_end = ns_to_ktime(local_clock());
+
+ dev->states_usage[index].s2idle_time += ktime_us_delta(time_end, time_start);
+ dev->states_usage[index].s2idle_usage++;
}
/**
diff --git a/drivers/cpuidle/poll_state.c b/drivers/cpuidle/poll_state.c
index 7416b16287de..3f86d23c592e 100644
--- a/drivers/cpuidle/poll_state.c
+++ b/drivers/cpuidle/poll_state.c
@@ -6,15 +6,30 @@
#include <linux/cpuidle.h>
#include <linux/sched.h>
+#include <linux/sched/clock.h>
#include <linux/sched/idle.h>
+#define POLL_IDLE_TIME_LIMIT (TICK_NSEC / 16)
+#define POLL_IDLE_RELAX_COUNT 200
+
static int __cpuidle poll_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
+ u64 time_start = local_clock();
+
local_irq_enable();
if (!current_set_polling_and_test()) {
- while (!need_resched())
+ unsigned int loop_count = 0;
+
+ while (!need_resched()) {
cpu_relax();
+ if (loop_count++ < POLL_IDLE_RELAX_COUNT)
+ continue;
+
+ loop_count = 0;
+ if (local_clock() - time_start > POLL_IDLE_TIME_LIMIT)
+ break;
+ }
}
current_clr_polling();
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index ae948b1da93a..e754c7aae7f7 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -330,6 +330,58 @@ struct cpuidle_state_kobj {
struct kobject kobj;
};
+#ifdef CONFIG_SUSPEND
+#define define_show_state_s2idle_ull_function(_name) \
+static ssize_t show_state_s2idle_##_name(struct cpuidle_state *state, \
+ struct cpuidle_state_usage *state_usage, \
+ char *buf) \
+{ \
+ return sprintf(buf, "%llu\n", state_usage->s2idle_##_name);\
+}
+
+define_show_state_s2idle_ull_function(usage);
+define_show_state_s2idle_ull_function(time);
+
+#define define_one_state_s2idle_ro(_name, show) \
+static struct cpuidle_state_attr attr_s2idle_##_name = \
+ __ATTR(_name, 0444, show, NULL)
+
+define_one_state_s2idle_ro(usage, show_state_s2idle_usage);
+define_one_state_s2idle_ro(time, show_state_s2idle_time);
+
+static struct attribute *cpuidle_state_s2idle_attrs[] = {
+ &attr_s2idle_usage.attr,
+ &attr_s2idle_time.attr,
+ NULL
+};
+
+static const struct attribute_group cpuidle_state_s2idle_group = {
+ .name = "s2idle",
+ .attrs = cpuidle_state_s2idle_attrs,
+};
+
+static void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj)
+{
+ int ret;
+
+ if (!kobj->state->enter_s2idle)
+ return;
+
+ ret = sysfs_create_group(&kobj->kobj, &cpuidle_state_s2idle_group);
+ if (ret)
+ pr_debug("%s: sysfs attribute group not created\n", __func__);
+}
+
+static void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj)
+{
+ if (kobj->state->enter_s2idle)
+ sysfs_remove_group(&kobj->kobj, &cpuidle_state_s2idle_group);
+}
+#else
+static inline void cpuidle_add_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { }
+static inline void cpuidle_remove_s2idle_attr_group(struct cpuidle_state_kobj *kobj) { }
+#endif /* CONFIG_SUSPEND */
+
#define kobj_to_state_obj(k) container_of(k, struct cpuidle_state_kobj, kobj)
#define kobj_to_state(k) (kobj_to_state_obj(k)->state)
#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
@@ -383,6 +435,7 @@ static struct kobj_type ktype_state_cpuidle = {
static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
{
+ cpuidle_remove_s2idle_attr_group(device->kobjs[i]);
kobject_put(&device->kobjs[i]->kobj);
wait_for_completion(&device->kobjs[i]->kobj_unregister);
kfree(device->kobjs[i]);
@@ -417,6 +470,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
kfree(kobj);
goto error_state;
}
+ cpuidle_add_s2idle_attr_group(kobj);
kobject_uevent(&kobj->kobj, KOBJ_ADD);
device->kobjs[i] = kobj;
}
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index c3b615c94b4b..8c8caec3a72c 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -452,17 +452,20 @@ static int socket_insert(struct pcmcia_socket *skt)
static int socket_suspend(struct pcmcia_socket *skt)
{
- if (skt->state & SOCKET_SUSPEND)
+ if ((skt->state & SOCKET_SUSPEND) && !(skt->state & SOCKET_IN_RESUME))
return -EBUSY;
mutex_lock(&skt->ops_mutex);
- skt->suspended_state = skt->state;
+ /* store state on first suspend, but not after spurious wakeups */
+ if (!(skt->state & SOCKET_IN_RESUME))
+ skt->suspended_state = skt->state;
skt->socket = dead_socket;
skt->ops->set_socket(skt, &skt->socket);
if (skt->ops->suspend)
skt->ops->suspend(skt);
skt->state |= SOCKET_SUSPEND;
+ skt->state &= ~SOCKET_IN_RESUME;
mutex_unlock(&skt->ops_mutex);
return 0;
}
@@ -475,6 +478,7 @@ static int socket_early_resume(struct pcmcia_socket *skt)
skt->ops->set_socket(skt, &skt->socket);
if (skt->state & SOCKET_PRESENT)
skt->resume_status = socket_setup(skt, resume_delay);
+ skt->state |= SOCKET_IN_RESUME;
mutex_unlock(&skt->ops_mutex);
return 0;
}
@@ -484,7 +488,7 @@ static int socket_late_resume(struct pcmcia_socket *skt)
int ret = 0;
mutex_lock(&skt->ops_mutex);
- skt->state &= ~SOCKET_SUSPEND;
+ skt->state &= ~(SOCKET_SUSPEND | SOCKET_IN_RESUME);
mutex_unlock(&skt->ops_mutex);
if (!(skt->state & SOCKET_PRESENT)) {
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 6765beadea95..03ec43802909 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -70,6 +70,7 @@ struct pccard_resource_ops {
/* Flags in socket state */
#define SOCKET_PRESENT 0x0008
#define SOCKET_INUSE 0x0010
+#define SOCKET_IN_RESUME 0x0040
#define SOCKET_SUSPEND 0x0080
#define SOCKET_WIN_REQ(i) (0x0100<<(i))
#define SOCKET_CARDBUS 0x8000
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 35636e1d8a3d..295d8dcba48c 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -1162,6 +1162,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
RAPL_CPU(INTEL_FAM6_SKYLAKE_X, rapl_defaults_hsw_server),
RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, rapl_defaults_core),
+ RAPL_CPU(INTEL_FAM6_CANNONLAKE_MOBILE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1, rapl_defaults_byt),
RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht),