Merge tag 'pm-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management updates from Rafael Wysocki:
 "These update the cpuidle poll state definition to reduce excessive
  energy usage related to it, add new CPU ID to the RAPL power capping
  driver, update the ACPI system suspend code to handle some special
  cases better, extend the PM core's device links code slightly, add new
  sysfs attribute for better suspend-to-idle diagnostics and easier
  hibernation handling, update power management tools and clean up
  cpufreq quite a bit.

  Specifics:

   - Modify the cpuidle poll state implementation to prevent CPUs from
     staying in the loop in there for excessive times (Rafael Wysocki).

   - Add Intel Cannon Lake chips support to the RAPL power capping
     driver (Joe Konno).

   - Add reference counting to the device links handling code in the PM
     core (Lukas Wunner).

   - Avoid reconfiguring GPEs on suspend-to-idle in the ACPI system
     suspend code (Rafael Wysocki).

   - Allow devices to be put into deeper low-power states via ACPI if
     both _SxD and _SxW are missing (Daniel Drake).

   - Reorganize the core ACPI suspend-to-idle wakeup code to avoid a
     keyboard wakeup issue on Asus UX331UA (Chris Chiu).

   - Prevent the PCMCIA library code from aborting suspend-to-idle due
     to noirq suspend failures resulting from incorrect assumptions
     (Rafael Wysocki).

   - Add coupled cpuidle supprt to the Exynos3250 platform (Marek
     Szyprowski).

   - Add new sysfs file to make it easier to specify the image storage
     location during hibernation (Mario Limonciello).

   - Add sysfs files for collecting suspend-to-idle usage and time
     statistics for CPU idle states (Rafael Wysocki).

   - Update the pm-graph utilities (Todd Brandt).

   - Reduce the kernel log noise related to reporting Low-power Idle
     constraings by the ACPI system suspend code (Rafael Wysocki).

   - Make it easier to distinguish dedicated wakeup IRQs in the
     /proc/interrupts output (Tony Lindgren).

   - Add the frequency table validation in cpufreq to the core and drop
     it from a number of cpufreq drivers (Viresh Kumar).

   - Drop "cooling-{min|max}-level" for CPU nodes from a couple of DT
     bindings (Viresh Kumar).

   - Clean up the CPU online error code path in the cpufreq core (Viresh
     Kumar).

   - Fix assorted issues in the SCPI, CPPC, mediatek and tegra186
     cpufreq drivers (Arnd Bergmann, Chunyu Hu, George Cherian, Viresh
     Kumar).

   - Drop memory allocation error messages from a few places in cpufreq
     and cpuildle drivers (Markus Elfring)"

* tag 'pm-4.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (56 commits)
  ACPI / PM: Fix keyboard wakeup from suspend-to-idle on ASUS UX331UA
  cpufreq: CPPC: Use transition_delay_us depending transition_latency
  PM / hibernate: Change message when writing to /sys/power/resume
  PM / hibernate: Make passing hibernate offsets more friendly
  cpuidle: poll_state: Avoid invoking local_clock() too often
  PM: cpuidle/suspend: Add s2idle usage and time state attributes
  cpuidle: Enable coupled cpuidle support on Exynos3250 platform
  cpuidle: poll_state: Add time limit to poll_idle()
  cpufreq: tegra186: Don't validate the frequency table twice
  cpufreq: speedstep: Don't validate the frequency table twice
  cpufreq: sparc: Don't validate the frequency table twice
  cpufreq: sh: Don't validate the frequency table twice
  cpufreq: sfi: Don't validate the frequency table twice
  cpufreq: scpi: Don't validate the frequency table twice
  cpufreq: sc520: Don't validate the frequency table twice
  cpufreq: s3c24xx: Don't validate the frequency table twice
  cpufreq: qoirq: Don't validate the frequency table twice
  cpufreq: pxa: Don't validate the frequency table twice
  cpufreq: ppc_cbe: Don't validate the frequency table twice
  cpufreq: powernow: Don't validate the frequency table twice
  ...
This commit is contained in:
Linus Torvalds
2018-04-03 10:45:39 -07:00
75 changed files with 2917 additions and 916 deletions

View File

@@ -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. */

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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.

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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:
up_write(&policy->rwsem);
if (cpufreq_driver->exit)
cpufreq_driver->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);
out_free_policy:
cpufreq_policy_free(policy);
return ret;

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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");

View File

@@ -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:

View File

@@ -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 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
* 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);

View File

@@ -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 = {

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -214,8 +214,9 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
/* 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;
}

View File

@@ -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)

View File

@@ -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);

View File

@@ -812,7 +812,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
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)

View File

@@ -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,

View File

@@ -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");

View File

@@ -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)

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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:

View File

@@ -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 = {

View File

@@ -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,
};

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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++;
}
/**

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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),