Commit f2d28566 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents be553754 103cf0e5
...@@ -198,6 +198,31 @@ Description: ...@@ -198,6 +198,31 @@ Description:
time (in microseconds) this cpu should spend in this idle state time (in microseconds) this cpu should spend in this idle state
to make the transition worth the effort. to make the transition worth the effort.
What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/
Date: March 2018
KernelVersion: v4.17
Contact: Linux power management list <linux-pm@vger.kernel.org>
Description:
Idle state usage statistics related to suspend-to-idle.
This attribute group is only present for states that can be
used in suspend-to-idle with suspended timekeeping.
What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/time
Date: March 2018
KernelVersion: v4.17
Contact: Linux power management list <linux-pm@vger.kernel.org>
Description:
Total time spent by the CPU in suspend-to-idle (with scheduler
tick suspended) after requesting this state.
What: /sys/devices/system/cpu/cpuX/cpuidle/stateN/s2idle/usage
Date: March 2018
KernelVersion: v4.17
Contact: Linux power management list <linux-pm@vger.kernel.org>
Description:
Total number of times this state has been requested by the CPU
while entering suspend-to-idle.
What: /sys/devices/system/cpu/cpu#/cpufreq/* What: /sys/devices/system/cpu/cpu#/cpufreq/*
Date: pre-git history Date: pre-git history
......
...@@ -287,3 +287,17 @@ Description: ...@@ -287,3 +287,17 @@ Description:
Writing a "1" to this file enables the debug messages and Writing a "1" to this file enables the debug messages and
writing a "0" (default) to it disables them. Reads from writing a "0" (default) to it disables them. Reads from
this file return the current value. this file return the current value.
What: /sys/power/resume_offset
Date: April 2018
Contact: Mario Limonciello <mario.limonciello@dell.com>
Description:
This file is used for telling the kernel an offset into a disk
to use when hibernating the system such as with a swap file.
Reads from this file will display the current offset
the kernel will be using on the next hibernation
attempt.
Using this sysfs file will override any values that were
set using the kernel command line for disk offset.
\ No newline at end of file
...@@ -18,8 +18,6 @@ Optional properties: ...@@ -18,8 +18,6 @@ Optional properties:
in unit of nanoseconds. in unit of nanoseconds.
- voltage-tolerance: Specify the CPU voltage tolerance in percentage. - voltage-tolerance: Specify the CPU voltage tolerance in percentage.
- #cooling-cells: - #cooling-cells:
- cooling-min-level:
- cooling-max-level:
Please refer to Documentation/devicetree/bindings/thermal/thermal.txt. Please refer to Documentation/devicetree/bindings/thermal/thermal.txt.
Examples: Examples:
...@@ -40,8 +38,6 @@ cpus { ...@@ -40,8 +38,6 @@ cpus {
>; >;
clock-latency = <61036>; /* two CLK32 periods */ clock-latency = <61036>; /* two CLK32 periods */
#cooling-cells = <2>; #cooling-cells = <2>;
cooling-min-level = <0>;
cooling-max-level = <2>;
}; };
cpu@1 { cpu@1 {
......
...@@ -21,8 +21,6 @@ Optional properties: ...@@ -21,8 +21,6 @@ Optional properties:
flow is handled by hardware, hence no software "voltage tracking" is flow is handled by hardware, hence no software "voltage tracking" is
needed. needed.
- #cooling-cells: - #cooling-cells:
- cooling-min-level:
- cooling-max-level:
Please refer to Documentation/devicetree/bindings/thermal/thermal.txt Please refer to Documentation/devicetree/bindings/thermal/thermal.txt
for detail. for detail.
...@@ -67,8 +65,6 @@ Example 1 (MT7623 SoC): ...@@ -67,8 +65,6 @@ Example 1 (MT7623 SoC):
clock-names = "cpu", "intermediate"; clock-names = "cpu", "intermediate";
operating-points-v2 = <&cpu_opp_table>; operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>; #cooling-cells = <2>;
cooling-min-level = <0>;
cooling-max-level = <7>;
}; };
cpu@1 { cpu@1 {
device_type = "cpu"; device_type = "cpu";
......
...@@ -24,8 +24,16 @@ Some warnings, first. ...@@ -24,8 +24,16 @@ Some warnings, first.
* see the FAQ below for details. (This is not true for more traditional * see the FAQ below for details. (This is not true for more traditional
* power states like "standby", which normally don't turn USB off.) * power states like "standby", which normally don't turn USB off.)
Swap partition:
You need to append resume=/dev/your_swap_partition to kernel command You need to append resume=/dev/your_swap_partition to kernel command
line. Then you suspend by line or specify it using /sys/power/resume.
Swap file:
If using a swapfile you can also specify a resume offset using
resume_offset=<number> on the kernel command line or specify it
in /sys/power/resume_offset.
After preparing then you suspend by
echo shutdown > /sys/power/disk; echo disk > /sys/power/state echo shutdown > /sys/power/disk; echo disk > /sys/power/state
......
...@@ -87,8 +87,6 @@ cpu0: cpu@0 { ...@@ -87,8 +87,6 @@ cpu0: cpu@0 {
clock-names = "cpu", "intermediate"; clock-names = "cpu", "intermediate";
operating-points-v2 = <&cpu_opp_table>; operating-points-v2 = <&cpu_opp_table>;
#cooling-cells = <2>; #cooling-cells = <2>;
cooling-min-level = <0>;
cooling-max-level = <7>;
clock-frequency = <1300000000>; clock-frequency = <1300000000>;
}; };
......
...@@ -543,6 +543,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, ...@@ -543,6 +543,7 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
unsigned long long ret; unsigned long long ret;
int d_min, d_max; int d_min, d_max;
bool wakeup = false; bool wakeup = false;
bool has_sxd = false;
acpi_status status; acpi_status status;
/* /*
...@@ -581,6 +582,10 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, ...@@ -581,6 +582,10 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
else else
return -ENODATA; return -ENODATA;
} }
if (status == AE_OK)
has_sxd = true;
d_min = ret; d_min = ret;
wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid wakeup = device_may_wakeup(dev) && adev->wakeup.flags.valid
&& adev->wakeup.sleep_state >= target_state; && adev->wakeup.sleep_state >= target_state;
...@@ -599,7 +604,11 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev, ...@@ -599,7 +604,11 @@ static int acpi_dev_pm_get_state(struct device *dev, struct acpi_device *adev,
method[3] = 'W'; method[3] = 'W';
status = acpi_evaluate_integer(handle, method, NULL, &ret); status = acpi_evaluate_integer(handle, method, NULL, &ret);
if (status == AE_NOT_FOUND) { 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; d_max = d_min;
} else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) { } else if (ACPI_SUCCESS(status) && ret <= ACPI_STATE_D3_COLD) {
/* Fall back to D3cold if ret is not a valid state. */ /* Fall back to D3cold if ret is not a valid state. */
......
...@@ -849,23 +849,25 @@ static void lpi_check_constraints(void) ...@@ -849,23 +849,25 @@ static void lpi_check_constraints(void)
int i; int i;
for (i = 0; i < lpi_constraints_table_size; ++i) { for (i = 0; i < lpi_constraints_table_size; ++i) {
acpi_handle handle = lpi_constraints_table[i].handle;
struct acpi_device *adev; struct acpi_device *adev;
if (acpi_bus_get_device(lpi_constraints_table[i].handle, &adev)) if (!handle || acpi_bus_get_device(handle, &adev))
continue; continue;
acpi_handle_debug(adev->handle, acpi_handle_debug(handle,
"LPI: required min power state:%s current power state:%s\n", "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(lpi_constraints_table[i].min_dstate),
acpi_power_state_string(adev->power.state)); acpi_power_state_string(adev->power.state));
if (!adev->flags.power_manageable) { 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; continue;
} }
if (adev->power.state < lpi_constraints_table[i].min_dstate) 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", "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(lpi_constraints_table[i].min_dstate),
acpi_power_state_string(adev->power.state)); acpi_power_state_string(adev->power.state));
...@@ -951,15 +953,8 @@ static int acpi_s2idle_prepare(void) ...@@ -951,15 +953,8 @@ static int acpi_s2idle_prepare(void)
if (lps0_device_handle) { if (lps0_device_handle) {
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF); acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF);
acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY); 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()) if (acpi_sci_irq_valid())
enable_irq_wake(acpi_sci_irq); enable_irq_wake(acpi_sci_irq);
...@@ -992,8 +987,9 @@ static void acpi_s2idle_sync(void) ...@@ -992,8 +987,9 @@ static void acpi_s2idle_sync(void)
* The EC driver uses the system workqueue and an additional special * The EC driver uses the system workqueue and an additional special
* one, so those need to be flushed too. * one, so those need to be flushed too.
*/ */
acpi_os_wait_events_complete(); /* synchronize SCI IRQ handling */
acpi_ec_flush_work(); acpi_ec_flush_work();
acpi_os_wait_events_complete(); acpi_os_wait_events_complete(); /* synchronize Notify handling */
s2idle_wakeup = false; s2idle_wakeup = false;
} }
...@@ -1005,8 +1001,6 @@ static void acpi_s2idle_restore(void) ...@@ -1005,8 +1001,6 @@ static void acpi_s2idle_restore(void)
if (lps0_device_handle) { if (lps0_device_handle) {
acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT); acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT);
acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON); acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON);
} else {
acpi_enable_all_runtime_gpes();
} }
} }
......
...@@ -196,8 +196,10 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -196,8 +196,10 @@ struct device_link *device_link_add(struct device *consumer,
} }
list_for_each_entry(link, &supplier->links.consumers, s_node) list_for_each_entry(link, &supplier->links.consumers, s_node)
if (link->consumer == consumer) if (link->consumer == consumer) {
kref_get(&link->kref);
goto out; goto out;
}
link = kzalloc(sizeof(*link), GFP_KERNEL); link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link) if (!link)
...@@ -222,6 +224,7 @@ struct device_link *device_link_add(struct device *consumer, ...@@ -222,6 +224,7 @@ struct device_link *device_link_add(struct device *consumer,
link->consumer = consumer; link->consumer = consumer;
INIT_LIST_HEAD(&link->c_node); INIT_LIST_HEAD(&link->c_node);
link->flags = flags; link->flags = flags;
kref_init(&link->kref);
/* Determine the initial link state. */ /* Determine the initial link state. */
if (flags & DL_FLAG_STATELESS) { if (flags & DL_FLAG_STATELESS) {
...@@ -292,8 +295,10 @@ static void __device_link_free_srcu(struct rcu_head *rhead) ...@@ -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)); 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_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier)); dev_name(link->supplier));
...@@ -305,8 +310,10 @@ static void __device_link_del(struct device_link *link) ...@@ -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); call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
} }
#else /* !CONFIG_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_info(link->consumer, "Dropping the link to %s\n",
dev_name(link->supplier)); dev_name(link->supplier));
...@@ -324,13 +331,15 @@ static void __device_link_del(struct device_link *link) ...@@ -324,13 +331,15 @@ static void __device_link_del(struct device_link *link)
* @link: Device link to delete. * @link: Device link to delete.
* *
* The caller must ensure proper synchronization of this function with runtime * 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) void device_link_del(struct device_link *link)
{ {
device_links_write_lock(); device_links_write_lock();
device_pm_lock(); device_pm_lock();
__device_link_del(link); kref_put(&link->kref, __device_link_del);
device_pm_unlock(); device_pm_unlock();
device_links_write_unlock(); device_links_write_unlock();
} }
...@@ -444,7 +453,7 @@ static void __device_links_no_driver(struct device *dev) ...@@ -444,7 +453,7 @@ static void __device_links_no_driver(struct device *dev)
continue; continue;
if (link->flags & DL_FLAG_AUTOREMOVE) 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) else if (link->status != DL_STATE_SUPPLIER_UNBIND)
WRITE_ONCE(link->status, DL_STATE_AVAILABLE); WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
} }
...@@ -597,13 +606,13 @@ static void device_links_purge(struct device *dev) ...@@ -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) { list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
WARN_ON(link->status == DL_STATE_ACTIVE); 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) { list_for_each_entry_safe_reverse(link, ln, &dev->links.consumers, s_node) {
WARN_ON(link->status != DL_STATE_DORMANT && WARN_ON(link->status != DL_STATE_DORMANT &&
link->status != DL_STATE_NONE); link->status != DL_STATE_NONE);
__device_link_del(link); __device_link_del(&link->kref);
} }
device_links_write_unlock(); device_links_write_unlock();
......
...@@ -31,6 +31,7 @@ struct wake_irq { ...@@ -31,6 +31,7 @@ struct wake_irq {
struct device *dev; struct device *dev;
unsigned int status; unsigned int status;
int irq; int irq;
const char *name;
}; };
extern void dev_pm_arm_wake_irq(struct wake_irq *wirq); extern void dev_pm_arm_wake_irq(struct wake_irq *wirq);
......
...@@ -112,6 +112,7 @@ void dev_pm_clear_wake_irq(struct device *dev) ...@@ -112,6 +112,7 @@ void dev_pm_clear_wake_irq(struct device *dev)
free_irq(wirq->irq, wirq); free_irq(wirq->irq, wirq);
wirq->status &= ~WAKE_IRQ_DEDICATED_MASK; wirq->status &= ~WAKE_IRQ_DEDICATED_MASK;
} }
kfree(wirq->name);
kfree(wirq); kfree(wirq);
} }
EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq); EXPORT_SYMBOL_GPL(dev_pm_clear_wake_irq);
...@@ -184,6 +185,12 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) ...@@ -184,6 +185,12 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
if (!wirq) if (!wirq)
return -ENOMEM; return -ENOMEM;
wirq->name = kasprintf(GFP_KERNEL, "%s:wakeup", dev_name(dev));
if (!wirq->name) {
err = -ENOMEM;
goto err_free;
}
wirq->dev = dev; wirq->dev = dev;
wirq->irq = irq; wirq->irq = irq;
irq_set_status_flags(irq, IRQ_NOAUTOEN); irq_set_status_flags(irq, IRQ_NOAUTOEN);
...@@ -196,9 +203,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) ...@@ -196,9 +203,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
* so we use a threaded irq. * so we use a threaded irq.
*/ */
err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq, err = request_threaded_irq(irq, NULL, handle_threaded_wake_irq,
IRQF_ONESHOT, dev_name(dev), wirq); IRQF_ONESHOT, wirq->name, wirq);
if (err) if (err)
goto err_free; goto err_free_name;
err = dev_pm_attach_wake_irq(dev, irq, wirq); err = dev_pm_attach_wake_irq(dev, irq, wirq);
if (err) if (err)
...@@ -210,6 +217,8 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) ...@@ -210,6 +217,8 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
err_free_irq: err_free_irq:
free_irq(irq, wirq); free_irq(irq, wirq);
err_free_name:
kfree(wirq->name);
err_free: err_free:
kfree(wirq); kfree(wirq);
......
...@@ -45,6 +45,7 @@ config ARM_DT_BL_CPUFREQ ...@@ -45,6 +45,7 @@ config ARM_DT_BL_CPUFREQ
config ARM_SCPI_CPUFREQ config ARM_SCPI_CPUFREQ
tristate "SCPI based CPUfreq driver" tristate "SCPI based CPUfreq driver"
depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI
depends on !CPU_THERMAL || THERMAL
help help
This adds the CPUfreq driver support for ARM platforms using SCPI This adds the CPUfreq driver support for ARM platforms using SCPI
protocol for CPU power management. protocol for CPU power management.
......
...@@ -794,15 +794,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -794,15 +794,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
valid_states++; valid_states++;
} }
freq_table[valid_states].frequency = CPUFREQ_TABLE_END; freq_table[valid_states].frequency = CPUFREQ_TABLE_END;
policy->freq_table = freq_table;
perf->state = 0; 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) { switch (perf->control_register.space_id) {
case ACPI_ADR_SPACE_SYSTEM_IO: case ACPI_ADR_SPACE_SYSTEM_IO:
/* /*
...@@ -842,8 +836,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -842,8 +836,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
return result; return result;
err_freqfree:
kfree(freq_table);
err_unreg: err_unreg:
acpi_processor_unregister_performance(cpu); acpi_processor_unregister_performance(cpu);
err_free_mask: err_free_mask:
...@@ -871,6 +863,15 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -871,6 +863,15 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
return 0; 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) static int acpi_cpufreq_resume(struct cpufreq_policy *policy)
{ {
struct acpi_cpufreq_data *data = policy->driver_data; struct acpi_cpufreq_data *data = policy->driver_data;
...@@ -898,6 +899,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = { ...@@ -898,6 +899,7 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.bios_limit = acpi_processor_get_bios_limit, .bios_limit = acpi_processor_get_bios_limit,
.init = acpi_cpufreq_cpu_init, .init = acpi_cpufreq_cpu_init,
.exit = acpi_cpufreq_cpu_exit, .exit = acpi_cpufreq_cpu_exit,
.ready = acpi_cpufreq_cpu_ready,
.resume = acpi_cpufreq_resume, .resume = acpi_cpufreq_resume,
.name = "acpi-cpufreq", .name = "acpi-cpufreq",
.attr = acpi_cpufreq_attr, .attr = acpi_cpufreq_attr,
......
...@@ -483,14 +483,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) ...@@ -483,14 +483,7 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
if (ret) if (ret)
return ret; return ret;
ret = cpufreq_table_validate_and_show(policy, freq_table[cur_cluster]); policy->freq_table = 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->cpuinfo.transition_latency = policy->cpuinfo.transition_latency =
arm_bL_ops->get_transition_latency(cpu_dev); arm_bL_ops->get_transition_latency(cpu_dev);
......
...@@ -902,11 +902,7 @@ static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy) ...@@ -902,11 +902,7 @@ static int brcm_avs_cpufreq_init(struct cpufreq_policy *policy)
return ret; return ret;
} }
ret = cpufreq_table_validate_and_show(policy, freq_table); policy->freq_table = freq_table;
if (ret) {
dev_err(dev, "invalid frequency table: %d\n", ret);
return ret;
}
/* All cores share the same clock and thus the same policy. */ /* All cores share the same clock and thus the same policy. */
cpumask_setall(policy->cpus); cpumask_setall(policy->cpus);
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/time.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -162,6 +163,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -162,6 +163,8 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.max_freq = cppc_dmi_max_khz; policy->cpuinfo.max_freq = cppc_dmi_max_khz;
policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); 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; policy->shared_type = cpu->shared_type;
if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY)
...@@ -230,8 +233,13 @@ static int __init cppc_cpufreq_init(void) ...@@ -230,8 +233,13 @@ static int __init cppc_cpufreq_init(void)
return ret; return ret;
out: out:
for_each_possible_cpu(i) for_each_possible_cpu(i) {
kfree(all_cpu_data[i]); cpu = all_cpu_data[i];
if (!cpu)
break;
free_cpumask_var(cpu->shared_cpu_map);
kfree(cpu);
}
kfree(all_cpu_data); kfree(all_cpu_data);
return -ENODEV; return -ENODEV;
......
...@@ -258,16 +258,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) ...@@ -258,16 +258,10 @@ static int cpufreq_init(struct cpufreq_policy *policy)
priv->cpu_dev = cpu_dev; priv->cpu_dev = cpu_dev;
policy->driver_data = priv; policy->driver_data = priv;
policy->clk = cpu_clk; policy->clk = cpu_clk;
policy->freq_table = freq_table;
policy->suspend_freq = dev_pm_opp_get_suspend_opp_freq(cpu_dev) / 1000; 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 */ /* Support turbo/boost mode */
if (policy_has_boost_freq(policy)) { if (policy_has_boost_freq(policy)) {
/* This gets disabled by core on driver unregister */ /* This gets disabled by core on driver unregister */
......
...@@ -178,14 +178,7 @@ int cpufreq_generic_init(struct cpufreq_policy *policy, ...@@ -178,14 +178,7 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table, struct cpufreq_frequency_table *table,
unsigned int transition_latency) unsigned int transition_latency)
{ {
int ret; policy->freq_table = table;
ret = cpufreq_table_validate_and_show(policy, table);
if (ret) {
pr_err("%s: invalid frequency table: %d\n", __func__, ret);
return ret;
}
policy->cpuinfo.transition_latency = transition_latency; policy->cpuinfo.transition_latency = transition_latency;
/* /*
...@@ -1219,6 +1212,10 @@ static int cpufreq_online(unsigned int cpu) ...@@ -1219,6 +1212,10 @@ static int cpufreq_online(unsigned int cpu)
goto out_free_policy; goto out_free_policy;
} }
ret = cpufreq_table_validate_and_sort(policy);
if (ret)
goto out_exit_policy;
down_write(&policy->rwsem); down_write(&policy->rwsem);
if (new_policy) { if (new_policy) {
...@@ -1249,7 +1246,7 @@ static int cpufreq_online(unsigned int cpu) ...@@ -1249,7 +1246,7 @@ static int cpufreq_online(unsigned int cpu)
policy->cur = cpufreq_driver->get(policy->cpu); policy->cur = cpufreq_driver->get(policy->cpu);
if (!policy->cur) { if (!policy->cur) {
pr_err("%s: ->get() failed\n", __func__); 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) ...@@ -1296,7 +1293,7 @@ static int cpufreq_online(unsigned int cpu)
if (new_policy) { if (new_policy) {
ret = cpufreq_add_dev_interface(policy); ret = cpufreq_add_dev_interface(policy);
if (ret) if (ret)
goto out_exit_policy; goto out_destroy_policy;
cpufreq_stats_create_table(policy); cpufreq_stats_create_table(policy);
...@@ -1311,7 +1308,7 @@ static int cpufreq_online(unsigned int cpu) ...@@ -1311,7 +1308,7 @@ static int cpufreq_online(unsigned int cpu)
__func__, cpu, ret); __func__, cpu, ret);
/* cpufreq_policy_free() will notify based on this */ /* cpufreq_policy_free() will notify based on this */
new_policy = false; new_policy = false;
goto out_exit_policy; goto out_destroy_policy;
} }
up_write(&policy->rwsem); up_write(&policy->rwsem);
...@@ -1326,15 +1323,16 @@ static int cpufreq_online(unsigned int cpu) ...@@ -1326,15 +1323,16 @@ static int cpufreq_online(unsigned int cpu)
return 0; 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); up_write(&policy->rwsem);
out_exit_policy:
if (cpufreq_driver->exit) if (cpufreq_driver->exit)
cpufreq_driver->exit(policy); cpufreq_driver->exit(policy);
for_each_cpu(j, policy->real_cpus)
remove_cpu_dev_symlink(policy, get_cpu_device(j));
out_free_policy: out_free_policy:
cpufreq_policy_free(policy); cpufreq_policy_free(policy);
return ret; return ret;
......
...@@ -184,7 +184,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy) ...@@ -184,7 +184,6 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
struct cpuinfo_x86 *c = &cpu_data(0); struct cpuinfo_x86 *c = &cpu_data(0);
struct cpufreq_frequency_table *f_table; struct cpufreq_frequency_table *f_table;
int k, step, voltage; int k, step, voltage;
int ret;
int states; int states;
#if IS_ENABLED(CONFIG_ACPI_PROCESSOR) #if IS_ENABLED(CONFIG_ACPI_PROCESSOR)
unsigned int limit; unsigned int limit;
...@@ -359,12 +358,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) ...@@ -359,12 +358,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
} }
policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */ policy->cpuinfo.transition_latency = 140000; /* 844mV -> 700mV in ns */
policy->freq_table = &centaur->freq_table[0];
ret = cpufreq_table_validate_and_show(policy, &centaur->freq_table[0]);
if (ret) {
kfree(centaur);
return ret;
}
return 0; return 0;
} }
......
...@@ -165,7 +165,8 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy) ...@@ -165,7 +165,8 @@ static int elanfreq_cpu_init(struct cpufreq_policy *policy)
if (pos->frequency > max_freq) if (pos->frequency > max_freq)
pos->frequency = CPUFREQ_ENTRY_INVALID; pos->frequency = CPUFREQ_ENTRY_INVALID;
return cpufreq_table_validate_and_show(policy, elanfreq_table); policy->freq_table = elanfreq_table;
return 0;
} }
......
...@@ -362,10 +362,24 @@ int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, ...@@ -362,10 +362,24 @@ int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
return ret; return ret;
policy->freq_table = table; policy->freq_table = table;
return set_freq_table_sorted(policy); return 0;
} }
EXPORT_SYMBOL_GPL(cpufreq_table_validate_and_show); 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_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("CPUfreq frequency table helpers"); MODULE_DESCRIPTION("CPUfreq frequency table helpers");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -270,10 +270,7 @@ acpi_cpufreq_cpu_init ( ...@@ -270,10 +270,7 @@ acpi_cpufreq_cpu_init (
} }
} }
result = cpufreq_table_validate_and_show(policy, freq_table); policy->freq_table = freq_table;
if (result) {
goto err_freqfree;
}
/* notify BIOS that we exist */ /* notify BIOS that we exist */
acpi_processor_notify_smm(THIS_MODULE); acpi_processor_notify_smm(THIS_MODULE);
...@@ -296,8 +293,6 @@ acpi_cpufreq_cpu_init ( ...@@ -296,8 +293,6 @@ acpi_cpufreq_cpu_init (
return (result); return (result);
err_freqfree:
kfree(freq_table);
err_unreg: err_unreg:
acpi_processor_unregister_performance(cpu); acpi_processor_unregister_performance(cpu);
err_free: err_free:
......
...@@ -52,6 +52,7 @@ static struct clk_bulk_data clks[] = { ...@@ -52,6 +52,7 @@ static struct clk_bulk_data clks[] = {
static struct device *cpu_dev; static struct device *cpu_dev;
static bool free_opp; static bool free_opp;
static struct cpufreq_frequency_table *freq_table; static struct cpufreq_frequency_table *freq_table;
static unsigned int max_freq;
static unsigned int transition_latency; static unsigned int transition_latency;
static u32 *imx6_soc_volt; static u32 *imx6_soc_volt;
...@@ -196,7 +197,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) ...@@ -196,7 +197,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
policy->clk = clks[ARM].clk; policy->clk = clks[ARM].clk;
ret = cpufreq_generic_init(policy, freq_table, transition_latency); ret = cpufreq_generic_init(policy, freq_table, transition_latency);
policy->suspend_freq = policy->max; policy->suspend_freq = max_freq;
return ret; return ret;
} }
...@@ -437,12 +438,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) ...@@ -437,12 +438,12 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
* freq_table initialised from OPP is therefore sorted in the * freq_table initialised from OPP is therefore sorted in the
* same order. * same order.
*/ */
max_freq = freq_table[--num].frequency;
opp = dev_pm_opp_find_freq_exact(cpu_dev, opp = dev_pm_opp_find_freq_exact(cpu_dev,
freq_table[0].frequency * 1000, true); freq_table[0].frequency * 1000, true);
min_volt = dev_pm_opp_get_voltage(opp); min_volt = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp); dev_pm_opp_put(opp);
opp = dev_pm_opp_find_freq_exact(cpu_dev, opp = dev_pm_opp_find_freq_exact(cpu_dev, max_freq * 1000, true);
freq_table[--num].frequency * 1000, true);
max_volt = dev_pm_opp_get_voltage(opp); max_volt = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp); dev_pm_opp_put(opp);
......
...@@ -895,8 +895,9 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) ...@@ -895,8 +895,9 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy)
longhaul_setup_voltagescaling(); longhaul_setup_voltagescaling();
policy->transition_delay_us = 200000; /* usec */ 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 = { static struct cpufreq_driver longhaul_driver = {
......
...@@ -460,21 +460,12 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) ...@@ -460,21 +460,12 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
return ret; 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); cpumask_copy(policy->cpus, &info->cpus);
policy->freq_table = freq_table;
policy->driver_data = info; policy->driver_data = info;
policy->clk = info->cpu_clk; policy->clk = info->cpu_clk;
return 0; 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) static int mtk_cpufreq_exit(struct cpufreq_policy *policy)
...@@ -578,7 +569,7 @@ static int __init mtk_cpufreq_driver_init(void) ...@@ -578,7 +569,7 @@ static int __init mtk_cpufreq_driver_init(void)
match = of_match_node(mtk_cpufreq_machines, np); match = of_match_node(mtk_cpufreq_machines, np);
of_node_put(np); of_node_put(np);
if (!match) { if (!match) {
pr_warn("Machine is not compatible with mtk-cpufreq\n"); pr_debug("Machine is not compatible with mtk-cpufreq\n");
return -ENODEV; return -ENODEV;
} }
......
...@@ -202,8 +202,9 @@ static int cpufreq_p4_cpu_init(struct cpufreq_policy *policy) ...@@ -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 /* the transition latency is set to be 1 higher than the maximum
* transition latency of the ondemand governor */ * transition latency of the ondemand governor */
policy->cpuinfo.transition_latency = 10000001; policy->cpuinfo.transition_latency = 10000001;
policy->freq_table = &p4clockmod_table[0];
return cpufreq_table_validate_and_show(policy, &p4clockmod_table[0]); return 0;
} }
......
...@@ -214,8 +214,9 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy) ...@@ -214,8 +214,9 @@ static int powernow_k6_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */ /* cpuinfo and default policy values */
policy->cpuinfo.transition_latency = 500000; policy->cpuinfo.transition_latency = 500000;
policy->freq_table = clock_ratio;
return cpufreq_table_validate_and_show(policy, clock_ratio); return 0;
} }
......
...@@ -639,8 +639,9 @@ static int powernow_cpu_init(struct cpufreq_policy *policy) ...@@ -639,8 +639,9 @@ static int powernow_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = policy->cpuinfo.transition_latency =
cpufreq_scale(2000000UL, fsb, 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) static int powernow_cpu_exit(struct cpufreq_policy *policy)
......
...@@ -122,14 +122,12 @@ static int query_current_values_with_pending_wait(struct powernow_k8_data *data) ...@@ -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) static void count_off_irt(struct powernow_k8_data *data)
{ {
udelay((1 << data->irt) * 10); udelay((1 << data->irt) * 10);
return;
} }
/* the voltage stabilization time */ /* the voltage stabilization time */
static void count_off_vst(struct powernow_k8_data *data) static void count_off_vst(struct powernow_k8_data *data)
{ {
udelay(data->vstable * VST_UNITS_20US); udelay(data->vstable * VST_UNITS_20US);
return;
} }
/* need to init the control msr to a safe value (for each cpu) */ /* 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, ...@@ -591,10 +589,8 @@ static int fill_powernow_table(struct powernow_k8_data *data,
powernow_table = kzalloc((sizeof(*powernow_table) powernow_table = kzalloc((sizeof(*powernow_table)
* (data->numps + 1)), GFP_KERNEL); * (data->numps + 1)), GFP_KERNEL);
if (!powernow_table) { if (!powernow_table)
pr_err("powernow_table memory alloc failure\n");
return -ENOMEM; return -ENOMEM;
}
for (j = 0; j < data->numps; j++) { for (j = 0; j < data->numps; j++) {
int freq; int freq;
...@@ -760,10 +756,8 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) ...@@ -760,10 +756,8 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data)
/* fill in data->powernow_table */ /* fill in data->powernow_table */
powernow_table = kzalloc((sizeof(*powernow_table) powernow_table = kzalloc((sizeof(*powernow_table)
* (data->acpi_data.state_count + 1)), GFP_KERNEL); * (data->acpi_data.state_count + 1)), GFP_KERNEL);
if (!powernow_table) { if (!powernow_table)
pr_debug("powernow_table memory alloc failure\n");
goto err_out; goto err_out;
}
/* fill in data */ /* fill in data */
data->numps = data->acpi_data.state_count; data->numps = data->acpi_data.state_count;
...@@ -1042,10 +1036,8 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) ...@@ -1042,10 +1036,8 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
return -ENODEV; return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL); data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) { if (!data)
pr_err("unable to alloc powernow_k8_data\n");
return -ENOMEM; return -ENOMEM;
}
data->cpu = pol->cpu; data->cpu = pol->cpu;
...@@ -1084,15 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) ...@@ -1084,15 +1076,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol)
cpumask_copy(pol->cpus, topology_core_cpumask(pol->cpu)); cpumask_copy(pol->cpus, topology_core_cpumask(pol->cpu));
data->available_cores = pol->cpus; data->available_cores = pol->cpus;
pol->freq_table = data->powernow_table;
/* 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;
}
pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n", pr_debug("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid); data->currfid, data->currvid);
......
...@@ -812,7 +812,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy, ...@@ -812,7 +812,7 @@ static int powernv_cpufreq_target_index(struct cpufreq_policy *policy,
static int powernv_cpufreq_cpu_init(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 kernfs_node *kn;
struct global_pstate_info *gpstates; struct global_pstate_info *gpstates;
...@@ -848,15 +848,10 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -848,15 +848,10 @@ static int powernv_cpufreq_cpu_init(struct cpufreq_policy *policy)
gpstates->timer.expires = jiffies + gpstates->timer.expires = jiffies +
msecs_to_jiffies(GPSTATE_TIMER_INTERVAL); msecs_to_jiffies(GPSTATE_TIMER_INTERVAL);
spin_lock_init(&gpstates->gpstate_lock); 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; policy->fast_switch_possible = true;
return ret; return 0;
} }
static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy) static int powernv_cpufreq_cpu_exit(struct cpufreq_policy *policy)
......
...@@ -121,9 +121,8 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -121,9 +121,8 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy)
cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu)); cpumask_copy(policy->cpus, cpu_sibling_mask(policy->cpu));
#endif #endif
/* this ensures that policy->cpuinfo_min policy->freq_table = cbe_freqs;
* and policy->cpuinfo_max are set correctly */ return 0;
return cpufreq_table_validate_and_show(policy, cbe_freqs);
} }
static int cbe_cpufreq_target(struct cpufreq_policy *policy, static int cbe_cpufreq_target(struct cpufreq_policy *policy,
......
...@@ -292,10 +292,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) ...@@ -292,10 +292,10 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy)
pr_info("using %s frequency table\n", pr_info("using %s frequency table\n",
pxa255_turbo_table ? "turbo" : "run"); 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()) { 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"); pr_info("frequency change support initialized\n");
......
...@@ -108,7 +108,9 @@ static int setup_freqs_table(struct cpufreq_policy *policy, ...@@ -108,7 +108,9 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
pxa3xx_freqs_num = num; pxa3xx_freqs_num = num;
pxa3xx_freqs_table = table; 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) static void __update_core_freq(struct pxa3xx_freq_info *info)
......
...@@ -165,7 +165,7 @@ static void freq_table_sort(struct cpufreq_frequency_table *freq_table, ...@@ -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) static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
{ {
struct device_node *np; struct device_node *np;
int i, count, ret; int i, count;
u32 freq; u32 freq;
struct clk *clk; struct clk *clk;
const struct clk_hw *hwclk; const struct clk_hw *hwclk;
...@@ -192,16 +192,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -192,16 +192,12 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
count = clk_hw_get_num_parents(hwclk); count = clk_hw_get_num_parents(hwclk);
data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL); data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
if (!data->pclk) { if (!data->pclk)
pr_err("%s: no memory\n", __func__);
goto err_nomem2; goto err_nomem2;
}
table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL); table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
if (!table) { if (!table)
pr_err("%s: no memory\n", __func__);
goto err_pclk; goto err_pclk;
}
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
clk = clk_hw_get_parent_by_index(hwclk, i)->clk; clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
...@@ -213,14 +209,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -213,14 +209,7 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
freq_table_redup(table, count); freq_table_redup(table, count);
freq_table_sort(table, count); freq_table_sort(table, count);
table[i].frequency = CPUFREQ_TABLE_END; table[i].frequency = CPUFREQ_TABLE_END;
policy->freq_table = table;
/* 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;
}
data->table = table; data->table = table;
/* update ->cpus if we have cluster, no harm if not */ /* update ->cpus if we have cluster, no harm if not */
...@@ -236,8 +225,6 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -236,8 +225,6 @@ static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
return 0; return 0;
err_nomem1:
kfree(table);
err_pclk: err_pclk:
kfree(data->pclk); kfree(data->pclk);
err_nomem2: err_nomem2:
......
...@@ -351,11 +351,8 @@ struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name) ...@@ -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) static int s3c_cpufreq_init(struct cpufreq_policy *policy)
{ {
policy->clk = clk_arm; policy->clk = clk_arm;
policy->cpuinfo.transition_latency = cpu_cur.info->latency; policy->cpuinfo.transition_latency = cpu_cur.info->latency;
policy->freq_table = ftab;
if (ftab)
return cpufreq_table_validate_and_show(policy, ftab);
return 0; return 0;
} }
...@@ -479,10 +476,8 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) ...@@ -479,10 +476,8 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
* initdata. */ * initdata. */
ours = kzalloc(sizeof(*ours), GFP_KERNEL); ours = kzalloc(sizeof(*ours), GFP_KERNEL);
if (ours == NULL) { if (!ours)
pr_err("%s: no memory\n", __func__);
return -ENOMEM; return -ENOMEM;
}
*ours = *board; *ours = *board;
cpu_cur.board = ours; cpu_cur.board = ours;
...@@ -568,10 +563,8 @@ static int s3c_cpufreq_build_freq(void) ...@@ -568,10 +563,8 @@ static int s3c_cpufreq_build_freq(void)
size++; size++;
ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL); ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL);
if (!ftab) { if (!ftab)
pr_err("%s: no memory for tables\n", __func__);
return -ENOMEM; return -ENOMEM;
}
ftab_size = size; ftab_size = size;
......
...@@ -83,8 +83,9 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -83,8 +83,9 @@ static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
/* cpuinfo and default policy values */ /* cpuinfo and default policy values */
policy->cpuinfo.transition_latency = 1000000; /* 1ms */ policy->cpuinfo.transition_latency = 1000000; /* 1ms */
policy->freq_table = sc520_freq_table;
return cpufreq_table_validate_and_show(policy, sc520_freq_table); return 0;
} }
......
...@@ -158,13 +158,7 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy) ...@@ -158,13 +158,7 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
} }
policy->driver_data = priv; policy->driver_data = priv;
policy->freq_table = freq_table;
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;
}
/* scpi allows DVFS request for any domain from any CPU */ /* scpi allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true; policy->dvfs_possible_from_any_cpu = true;
...@@ -178,8 +172,6 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy) ...@@ -178,8 +172,6 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
policy->fast_switch_possible = false; policy->fast_switch_possible = false;
return 0; return 0;
out_put_clk:
clk_put(priv->clk);
out_free_cpufreq_table: out_free_cpufreq_table:
dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
out_free_priv: out_free_priv:
......
...@@ -72,8 +72,9 @@ static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -72,8 +72,9 @@ static int sfi_cpufreq_cpu_init(struct cpufreq_policy *policy)
{ {
policy->shared_type = CPUFREQ_SHARED_TYPE_HW; policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
policy->cpuinfo.transition_latency = 100000; /* 100us */ 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 = { static struct cpufreq_driver sfi_cpufreq_driver = {
......
...@@ -122,11 +122,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -122,11 +122,7 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL;
if (freq_table) { if (freq_table) {
int result; policy->freq_table = freq_table;
result = cpufreq_table_validate_and_show(policy, freq_table);
if (result)
return result;
} else { } else {
dev_notice(dev, "no frequency table found, falling back " dev_notice(dev, "no frequency table found, falling back "
"to rate rounding.\n"); "to rate rounding.\n");
...@@ -137,11 +133,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy) ...@@ -137,11 +133,6 @@ static int sh_cpufreq_cpu_init(struct cpufreq_policy *policy)
(clk_round_rate(cpuclk, ~0UL) + 500) / 1000; (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; return 0;
} }
...@@ -155,6 +146,16 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy) ...@@ -155,6 +146,16 @@ static int sh_cpufreq_cpu_exit(struct cpufreq_policy *policy)
return 0; 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 = { static struct cpufreq_driver sh_cpufreq_driver = {
.name = "sh", .name = "sh",
.flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING, .flags = CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING,
...@@ -163,6 +164,7 @@ static struct cpufreq_driver sh_cpufreq_driver = { ...@@ -163,6 +164,7 @@ static struct cpufreq_driver sh_cpufreq_driver = {
.verify = sh_cpufreq_verify, .verify = sh_cpufreq_verify,
.init = sh_cpufreq_cpu_init, .init = sh_cpufreq_cpu_init,
.exit = sh_cpufreq_cpu_exit, .exit = sh_cpufreq_cpu_exit,
.ready = sh_cpufreq_cpu_ready,
.attr = cpufreq_generic_attr, .attr = cpufreq_generic_attr,
}; };
......
...@@ -292,8 +292,9 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -292,8 +292,9 @@ static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 0; policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick; 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) static int us2e_freq_cpu_exit(struct cpufreq_policy *policy)
......
...@@ -136,8 +136,9 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy) ...@@ -136,8 +136,9 @@ static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 0; policy->cpuinfo.transition_latency = 0;
policy->cur = clock_tick; 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) static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
......
...@@ -394,9 +394,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy) ...@@ -394,9 +394,9 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
policy->cpuinfo.transition_latency = 10000; policy->cpuinfo.transition_latency = 10000;
/* 10uS transition latency */ /* 10uS transition latency */
policy->freq_table = per_cpu(centrino_model, policy->cpu)->op_points;
return cpufreq_table_validate_and_show(policy, return 0;
per_cpu(centrino_model, policy->cpu)->op_points);
} }
static int centrino_cpu_exit(struct cpufreq_policy *policy) static int centrino_cpu_exit(struct cpufreq_policy *policy)
......
...@@ -304,7 +304,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -304,7 +304,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
if (gf.ret) if (gf.ret)
return gf.ret; return gf.ret;
return cpufreq_table_validate_and_show(policy, speedstep_freqs); policy->freq_table = speedstep_freqs;
return 0;
} }
......
...@@ -266,7 +266,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) ...@@ -266,7 +266,9 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy)
pr_debug("workaround worked.\n"); 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) static unsigned int speedstep_get(unsigned int cpu)
......
...@@ -78,7 +78,8 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy) ...@@ -78,7 +78,8 @@ static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
policy->driver_data = policy->driver_data =
data->regs + info->offset + EDVD_CORE_VOLT_FREQ(core); 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; policy->cpuinfo.transition_latency = 300 * 1000;
......
...@@ -129,7 +129,6 @@ static int __init arm_idle_init_cpu(int cpu) ...@@ -129,7 +129,6 @@ static int __init arm_idle_init_cpu(int cpu)
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) { if (!dev) {
pr_err("Failed to allocate cpuidle device\n");
ret = -ENOMEM; ret = -ENOMEM;
goto out_unregister_drv; goto out_unregister_drv;
} }
......
...@@ -117,7 +117,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev) ...@@ -117,7 +117,8 @@ static int exynos_cpuidle_probe(struct platform_device *pdev)
int ret; int ret;
if (IS_ENABLED(CONFIG_SMP) && 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; exynos_cpuidle_pdata = pdev->dev.platform_data;
ret = cpuidle_register(&exynos_coupled_idle_driver, ret = cpuidle_register(&exynos_coupled_idle_driver,
......
...@@ -131,6 +131,10 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv, ...@@ -131,6 +131,10 @@ int cpuidle_find_deepest_state(struct cpuidle_driver *drv,
static void enter_s2idle_proper(struct cpuidle_driver *drv, static void enter_s2idle_proper(struct cpuidle_driver *drv,
struct cpuidle_device *dev, int index) 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 * trace_suspend_resume() called by tick_freeze() for the last CPU
* executing it contains RCU usage regarded as invalid in the idle * executing it contains RCU usage regarded as invalid in the idle
...@@ -152,6 +156,11 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv, ...@@ -152,6 +156,11 @@ static void enter_s2idle_proper(struct cpuidle_driver *drv,
*/ */
RCU_NONIDLE(tick_unfreeze()); RCU_NONIDLE(tick_unfreeze());
start_critical_timings(); 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++;
} }
/** /**
......
...@@ -6,15 +6,30 @@ ...@@ -6,15 +6,30 @@
#include <linux/cpuidle.h> #include <linux/cpuidle.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/sched/idle.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, static int __cpuidle poll_idle(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index) struct cpuidle_driver *drv, int index)
{ {
u64 time_start = local_clock();
local_irq_enable(); local_irq_enable();
if (!current_set_polling_and_test()) { if (!current_set_polling_and_test()) {
while (!need_resched()) unsigned int loop_count = 0;
while (!need_resched()) {
cpu_relax(); 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(); current_clr_polling();
......
...@@ -330,6 +330,58 @@ struct cpuidle_state_kobj { ...@@ -330,6 +330,58 @@ struct cpuidle_state_kobj {
struct kobject 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_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(k) (kobj_to_state_obj(k)->state)
#define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage) #define kobj_to_state_usage(k) (kobj_to_state_obj(k)->state_usage)
...@@ -383,6 +435,7 @@ static struct kobj_type ktype_state_cpuidle = { ...@@ -383,6 +435,7 @@ static struct kobj_type ktype_state_cpuidle = {
static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i) 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); kobject_put(&device->kobjs[i]->kobj);
wait_for_completion(&device->kobjs[i]->kobj_unregister); wait_for_completion(&device->kobjs[i]->kobj_unregister);
kfree(device->kobjs[i]); kfree(device->kobjs[i]);
...@@ -417,6 +470,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) ...@@ -417,6 +470,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device)
kfree(kobj); kfree(kobj);
goto error_state; goto error_state;
} }
cpuidle_add_s2idle_attr_group(kobj);
kobject_uevent(&kobj->kobj, KOBJ_ADD); kobject_uevent(&kobj->kobj, KOBJ_ADD);
device->kobjs[i] = kobj; device->kobjs[i] = kobj;
} }
......
...@@ -452,17 +452,20 @@ static int socket_insert(struct pcmcia_socket *skt) ...@@ -452,17 +452,20 @@ static int socket_insert(struct pcmcia_socket *skt)
static int socket_suspend(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; return -EBUSY;
mutex_lock(&skt->ops_mutex); 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->socket = dead_socket;
skt->ops->set_socket(skt, &skt->socket); skt->ops->set_socket(skt, &skt->socket);
if (skt->ops->suspend) if (skt->ops->suspend)
skt->ops->suspend(skt); skt->ops->suspend(skt);
skt->state |= SOCKET_SUSPEND; skt->state |= SOCKET_SUSPEND;
skt->state &= ~SOCKET_IN_RESUME;
mutex_unlock(&skt->ops_mutex); mutex_unlock(&skt->ops_mutex);
return 0; return 0;
} }
...@@ -475,6 +478,7 @@ static int socket_early_resume(struct pcmcia_socket *skt) ...@@ -475,6 +478,7 @@ static int socket_early_resume(struct pcmcia_socket *skt)
skt->ops->set_socket(skt, &skt->socket); skt->ops->set_socket(skt, &skt->socket);
if (skt->state & SOCKET_PRESENT) if (skt->state & SOCKET_PRESENT)
skt->resume_status = socket_setup(skt, resume_delay); skt->resume_status = socket_setup(skt, resume_delay);
skt->state |= SOCKET_IN_RESUME;
mutex_unlock(&skt->ops_mutex); mutex_unlock(&skt->ops_mutex);
return 0; return 0;
} }
...@@ -484,7 +488,7 @@ static int socket_late_resume(struct pcmcia_socket *skt) ...@@ -484,7 +488,7 @@ static int socket_late_resume(struct pcmcia_socket *skt)
int ret = 0; int ret = 0;
mutex_lock(&skt->ops_mutex); mutex_lock(&skt->ops_mutex);
skt->state &= ~SOCKET_SUSPEND; skt->state &= ~(SOCKET_SUSPEND | SOCKET_IN_RESUME);
mutex_unlock(&skt->ops_mutex); mutex_unlock(&skt->ops_mutex);
if (!(skt->state & SOCKET_PRESENT)) { if (!(skt->state & SOCKET_PRESENT)) {
......
...@@ -70,6 +70,7 @@ struct pccard_resource_ops { ...@@ -70,6 +70,7 @@ struct pccard_resource_ops {
/* Flags in socket state */ /* Flags in socket state */
#define SOCKET_PRESENT 0x0008 #define SOCKET_PRESENT 0x0008
#define SOCKET_INUSE 0x0010 #define SOCKET_INUSE 0x0010
#define SOCKET_IN_RESUME 0x0040
#define SOCKET_SUSPEND 0x0080 #define SOCKET_SUSPEND 0x0080
#define SOCKET_WIN_REQ(i) (0x0100<<(i)) #define SOCKET_WIN_REQ(i) (0x0100<<(i))
#define SOCKET_CARDBUS 0x8000 #define SOCKET_CARDBUS 0x8000
......
...@@ -1162,6 +1162,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = { ...@@ -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_SKYLAKE_X, rapl_defaults_hsw_server),
RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE, rapl_defaults_core), RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE, rapl_defaults_core),
RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP, 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_SILVERMONT1, rapl_defaults_byt),
RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht), RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT, rapl_defaults_cht),
......
...@@ -962,6 +962,7 @@ extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs; ...@@ -962,6 +962,7 @@ extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs;
extern struct freq_attr *cpufreq_generic_attr[]; extern struct freq_attr *cpufreq_generic_attr[];
int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, int cpufreq_table_validate_and_show(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table); struct cpufreq_frequency_table *table);
int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy);
unsigned int cpufreq_generic_get(unsigned int cpu); unsigned int cpufreq_generic_get(unsigned int cpu);
int cpufreq_generic_init(struct cpufreq_policy *policy, int cpufreq_generic_init(struct cpufreq_policy *policy,
......
...@@ -33,6 +33,10 @@ struct cpuidle_state_usage { ...@@ -33,6 +33,10 @@ struct cpuidle_state_usage {
unsigned long long disable; unsigned long long disable;
unsigned long long usage; unsigned long long usage;
unsigned long long time; /* in US */ unsigned long long time; /* in US */
#ifdef CONFIG_SUSPEND
unsigned long long s2idle_usage;
unsigned long long s2idle_time; /* in US */
#endif
}; };
struct cpuidle_state { struct cpuidle_state {
......
...@@ -769,6 +769,7 @@ enum device_link_state { ...@@ -769,6 +769,7 @@ enum device_link_state {
* @status: The state of the link (with respect to the presence of drivers). * @status: The state of the link (with respect to the presence of drivers).
* @flags: Link flags. * @flags: Link flags.
* @rpm_active: Whether or not the consumer device is runtime-PM-active. * @rpm_active: Whether or not the consumer device is runtime-PM-active.
* @kref: Count repeated addition of the same link.
* @rcu_head: An RCU head to use for deferred execution of SRCU callbacks. * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
*/ */
struct device_link { struct device_link {
...@@ -779,6 +780,7 @@ struct device_link { ...@@ -779,6 +780,7 @@ struct device_link {
enum device_link_state status; enum device_link_state status;
u32 flags; u32 flags;
bool rpm_active; bool rpm_active;
struct kref kref;
#ifdef CONFIG_SRCU #ifdef CONFIG_SRCU
struct rcu_head rcu_head; struct rcu_head rcu_head;
#endif #endif
......
...@@ -1053,7 +1053,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, ...@@ -1053,7 +1053,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
lock_system_sleep(); lock_system_sleep();
swsusp_resume_device = res; swsusp_resume_device = res;
unlock_system_sleep(); unlock_system_sleep();
pr_info("Starting manual resume from disk\n"); pm_pr_dbg("Configured resume from disk to %u\n", swsusp_resume_device);
noresume = 0; noresume = 0;
software_resume(); software_resume();
return n; return n;
...@@ -1061,6 +1061,29 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr, ...@@ -1061,6 +1061,29 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
power_attr(resume); power_attr(resume);
static ssize_t resume_offset_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
return sprintf(buf, "%llu\n", (unsigned long long)swsusp_resume_block);
}
static ssize_t resume_offset_store(struct kobject *kobj,
struct kobj_attribute *attr, const char *buf,
size_t n)
{
unsigned long long offset;
int rc;
rc = kstrtoull(buf, 0, &offset);
if (rc)
return rc;
swsusp_resume_block = offset;
return n;
}
power_attr(resume_offset);
static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t image_size_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf) char *buf)
{ {
...@@ -1106,6 +1129,7 @@ power_attr(reserved_size); ...@@ -1106,6 +1129,7 @@ power_attr(reserved_size);
static struct attribute * g[] = { static struct attribute * g[] = {
&disk_attr.attr, &disk_attr.attr,
&resume_offset_attr.attr,
&resume_attr.attr, &resume_attr.attr,
&image_size_attr.attr, &image_size_attr.attr,
&reserved_size_attr.attr, &reserved_size_attr.attr,
......
...@@ -7,11 +7,24 @@ all: ...@@ -7,11 +7,24 @@ all:
install : uninstall install : uninstall
install -d $(DESTDIR)$(PREFIX)/lib/pm-graph install -d $(DESTDIR)$(PREFIX)/lib/pm-graph
install analyze_suspend.py $(DESTDIR)$(PREFIX)/lib/pm-graph install sleepgraph.py $(DESTDIR)$(PREFIX)/lib/pm-graph
install analyze_boot.py $(DESTDIR)$(PREFIX)/lib/pm-graph install bootgraph.py $(DESTDIR)$(PREFIX)/lib/pm-graph
install -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/cgskip.txt $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/freeze-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/freeze.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/freeze-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/standby-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/standby.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/standby-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/suspend-callgraph.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/suspend.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/suspend-dev.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
install -m 644 config/suspend-x2-proc.cfg $(DESTDIR)$(PREFIX)/lib/pm-graph/config
ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py $(DESTDIR)$(PREFIX)/bin/bootgraph install -d $(DESTDIR)$(PREFIX)/bin
ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py $(DESTDIR)$(PREFIX)/bin/sleepgraph ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/bootgraph.py $(DESTDIR)$(PREFIX)/bin/bootgraph
ln -s $(DESTDIR)$(PREFIX)/lib/pm-graph/sleepgraph.py $(DESTDIR)$(PREFIX)/bin/sleepgraph
install -d $(DESTDIR)$(PREFIX)/share/man/man8 install -d $(DESTDIR)$(PREFIX)/share/man/man8
install bootgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8 install bootgraph.8 $(DESTDIR)$(PREFIX)/share/man/man8
...@@ -24,9 +37,11 @@ uninstall : ...@@ -24,9 +37,11 @@ uninstall :
rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph rm -f $(DESTDIR)$(PREFIX)/bin/bootgraph
rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph rm -f $(DESTDIR)$(PREFIX)/bin/sleepgraph
rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_boot.py rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/config/*
rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/analyze_suspend.py if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph/config ] ; then \
rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*.pyc rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph/config; \
fi;
rm -f $(DESTDIR)$(PREFIX)/lib/pm-graph/*
if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \ if [ -d $(DESTDIR)$(PREFIX)/lib/pm-graph ] ; then \
rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \ rmdir $(DESTDIR)$(PREFIX)/lib/pm-graph; \
fi; fi;
...@@ -37,6 +37,9 @@ Print the current tool version ...@@ -37,6 +37,9 @@ Print the current tool version
Add the dmesg log to the html output. It will be viewable by Add the dmesg log to the html output. It will be viewable by
clicking a button in the timeline. clicking a button in the timeline.
.TP .TP
\fB-result \fIfile\fR
Export a results table to a text file for parsing.
.TP
\fB-o \fIname\fR \fB-o \fIname\fR
Overrides the output subdirectory name when running a new test. Overrides the output subdirectory name when running a new test.
Use {date}, {time}, {hostname} for current values. Use {date}, {time}, {hostname} for current values.
...@@ -44,14 +47,14 @@ Use {date}, {time}, {hostname} for current values. ...@@ -44,14 +47,14 @@ Use {date}, {time}, {hostname} for current values.
e.g. boot-{hostname}-{date}-{time} e.g. boot-{hostname}-{date}-{time}
.SS "advanced" .SS "advanced"
.TP .TP
\fB-f\fR \fB-f or -callgraph\fR
Use ftrace to add function detail (default: disabled)
.TP
\fB-callgraph\fR
Use ftrace to create initcall callgraphs (default: disabled). If -func Use ftrace to create initcall callgraphs (default: disabled). If -func
is not used there will be one callgraph per initcall. This can produce is not used there will be one callgraph per initcall. This can produce
very large outputs, i.e. 10MB - 100MB. very large outputs, i.e. 10MB - 100MB.
.TP .TP
\fB-fstat\fR
Use ftrace to add function detail (default: disabled)
.TP
\fB-maxdepth \fIlevel\fR \fB-maxdepth \fIlevel\fR
limit the callgraph trace depth to \fIlevel\fR (default: 2). This is limit the callgraph trace depth to \fIlevel\fR (default: 2). This is
the best way to limit the output size when using -callgraph. the best way to limit the output size when using -callgraph.
...@@ -67,6 +70,13 @@ Reduce callgraph output in the timeline by limiting it to a list of calls. The ...@@ -67,6 +70,13 @@ Reduce callgraph output in the timeline by limiting it to a list of calls. The
argument can be a single function name or a comma delimited list. argument can be a single function name or a comma delimited list.
(default: none) (default: none)
.TP .TP
\fB-cgskip \fIfile\fR
Reduce callgraph output in the timeline by skipping over uninteresting
functions in the trace, e.g. printk or console_unlock. The functions listed
in this file will show up as empty leaves in the callgraph with only the start/end
times displayed.
(default: none)
.TP
\fB-timeprec \fIn\fR \fB-timeprec \fIn\fR
Number of significant digits in timestamps (0:S, 3:ms, [6:us]) Number of significant digits in timestamps (0:S, 3:ms, [6:us])
.TP .TP
......
# -----------------------------------------------
# CallGraph function skip list
#
# This file contains a list of functions which are
# meant to be skipped in the callgraph trace. It reduces
# the callgraph html file size by treating these functions
# as leaves with no child calls. It can be editted by
# adding or removing function symbol names.
#
# The sleepgraph tool automatically pulls this file in when
# it is found in the config folder. It can be ignored if
# the tool is called with "-cgskip off".
# -----------------------------------------------
# low level scheduling and timing
up
down_timeout
mutex_lock
down_read
complete_all
schedule_timeout
wake_up_process
msleep
__udelay
ktime_get
# console calls
printk
dev_printk
console_unlock
# memory handling
__kmalloc
__kmalloc_track_caller
kmem_cache_alloc
kmem_cache_alloc_trace
kmem_cache_free
kstrdup
kstrdup_const
kmalloc_slab
new_slab
__slab_alloc
__slab_free
raw_pci_read
pci_read
alloc_pages_current
# debugfs and sysfs setup
debugfs_remove_recursive
debugfs_create_dir
debugfs_create_files
debugfs_create_dir
debugfs_get_inode
sysfs_add_file_mode_ns
sysfs_add_file
sysfs_create_dir_ns
sysfs_create_link
sysfs_create_group
sysfs_create_groups
sysfs_create_bin_file
dpm_sysfs_add
sysfs_create_file_ns
sysfs_merge_group
sysfs_add_link_to_group
sysfs_create_link_sd
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config thisfile.txt
#
[Settings]
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: mem
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: true
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: suspend-{hostname}-{date}-{time}-custom
# Override default timeline entries
# Do not use the internal default functions for timeline entries (default: false)
# Set this to true if you intend to only use the ones defined in this config
override-timeline-functions: true
# Override default dev timeline entries
# Do not use the internal default functions for dev timeline entries (default: false)
# Set this to true if you intend to only use the ones defined in this config
override-dev-timeline-functions: true
[timeline_functions_x86_64]
#
# Function calls to display in the timeline alongside device callbacks.
# The tool has an internal set of these functions which should cover the
# whole of kernel execution, but you can append or override here.
#
# This is a list of kprobes which use both symbol data and function arg data.
# The function calls are displayed on the timeline alongside the device blocks.
# The args are pulled directly from the stack using this architecture's registers
# and stack formatting. Three pieces of info are required. The function name,
# a format string, and an argument list
#
# Entry format:
#
# function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
#
# Required Arguments:
#
# function: The symbol name for the function you want probed, this is the
# minimum required for an entry, it will show up as the function
# name with no arguments.
#
# example: _cpu_up:
#
# Optional Arguments:
#
# format: The format to display the data on the timeline in. Use braces to
# enclose the arg names.
#
# example: CPU_ON[{cpu}]
#
# color: The color of the entry block in the timeline. The default color is
# transparent, so the entry shares the phase color. The color is an
# html color string, either a word, or an RGB.
#
# example: [color=#CC00CC]
#
# arglist: A list of arguments from registers/stack addresses. See URL:
# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
#
# example: cpu=%di:s32
#
# Example: Display cpu resume in the timeline
#
# _cpu_up: CPU_ON[{cpu}] cpu=%di:s32 [color=orange]
#
_cpu_down: CPU_OFF[{cpu}] cpu=%di:s32
_cpu_up: CPU_ON[{cpu}] cpu=%di:s32
sys_sync:
pm_prepare_console:
pm_notifier_call_chain:
freeze_processes:
freeze_kernel_threads:
pm_restrict_gfp_mask:
acpi_suspend_begin:
suspend_console:
acpi_pm_prepare:
syscore_suspend:
arch_enable_nonboot_cpus_end:
syscore_resume:
acpi_pm_finish:
resume_console:
acpi_pm_end:
pm_restore_gfp_mask:
thaw_processes:
pm_restore_console:
[dev_timeline_functions_x86_64]
#
# Dev mode function calls to display inside timeline entries
#
# This is a list of kprobes which use both symbol data and function arg data.
# The function calls are displayed on the timeline alongside the device blocks.
# The args are pulled directly from the stack using this architecture's registers
# and stack formatting. Three pieces of info are required. The function name,
# a format string, and an argument list
#
# Entry format:
#
# function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple]
#
# Required Arguments:
#
# function: The symbol name for the function you want probed, this is the
# minimum required for an entry, it will show up as the function
# name with no arguments.
#
# example: ata_eh_recover:
#
# Optional Arguments:
#
# format: The format to display the data on the timeline in. Use braces to
# enclose the arg names.
#
# example: ata{port}_port_reset
#
# color: The color of the entry block in the timeline. The default color is
# transparent, so the entry shares the phase color. The color is an
# html color string, either a word, or an RGB.
#
# example: [color=#CC00CC]
#
# arglist: A list of arguments from registers/stack addresses. See URL:
# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
#
# example: port=+36(%di):s32
#
# Example: Display ATA port reset as ataN_port_reset in the timeline
#
# ata_eh_recover: ata{port}_port_reset port=+36(%di):s32
#
msleep: msleep time=%di:s32
schedule_timeout_uninterruptible: schedule_timeout_uninterruptible timeout=%di:s32
schedule_timeout: schedule_timeout timeout=%di:s32
usleep_range: usleep_range min=%di:s32 max=%si:s32
__const_udelay: udelay loops=%di:s32
__mutex_lock_slowpath: mutex_lock_slowpath
ata_eh_recover: ata_eh_recover port=+36(%di):s32
acpi_os_stall:
acpi_resume_power_resources:
acpi_ps_parse_aml:
ext4_sync_fs:
i915_gem_resume:
i915_restore_state:
intel_opregion_setup:
g4x_pre_enable_dp:
vlv_pre_enable_dp:
chv_pre_enable_dp:
g4x_enable_dp:
vlv_enable_dp:
intel_hpd_init:
intel_opregion_register:
intel_dp_detect:
intel_hdmi_detect:
intel_opregion_init:
intel_fbdev_set_suspend:
#
# Generic S3 (Suspend to Mem) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/example.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: mem
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: suspend-{hostname}-{date}-{time}
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: true
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# Skip HTML generation
# Only capture the logs, don't generate the html timeline (default: false)
skiphtml: false
# Sync filesystem before suspend
# run sync before the test, minimizes sys_sync call time (default: false)
sync: true
# Runtime suspend enable/disable
# Enable/disable runtime suspend for all devices, restore all after test (default: no-action)
# rs: disable
# Turn display on/off for test
# Switch the display on/off for the test using xset (default: no-action)
# display: on
# Print results to text file
# Print the status of the test run in the given file (default: no-action)
result: result.txt
# Gzip the log files to save space
# Gzip the generated log files, and read gzipped log files (default: false)
gzip: true
# ---- Advanced Options ----
# Command to execute in lieu of suspend (default: "")
# command: echo mem > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Multiple test runs
# Run N tests D seconds apart, generates separate outputs with a summary (default: false)
# multi: 3 5
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back and display in the same timeline (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 0.001
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Callgraph phase filter
# Only enable callgraphs for one phase, i.e. resume_noirq (default: all)
cgphase: suspend
# Callgraph x2 test filter
# Only enable callgraphs test 0 or 1 when using -x2 (default: 1)
cgtest: 0
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 6
# Device Filter
# show only devices whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
# Add kprobe functions to the timeline
# Add functions to the timeline from a text file (default: no-action)
# fadd: file.txt
#
# Full Callgraph for S2 (Freeze) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/freeze-callgraph.cfg
#
# NOTE: the output of this test is very large (> 30MB)
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: freeze
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: freeze-{hostname}-{date}-{time}-cg
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of freeze (default: "")
# command: echo freeze > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: true
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 6
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Dev S2 (Freeze) test - includes src calls / kernel threads
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/freeze-dev.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: freeze
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: freeze-{hostname}-{date}-{time}-dev
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of freeze (default: "")
# command: echo freeze > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: true
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Generic S2 (Freeze) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/freeze.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: freeze
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: freeze-{hostname}-{date}-{time}
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of freeze (default: "")
# command: echo freeze > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 0.001
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Full Callgraph for S1 (Standby) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/standby-callgraph.cfg
#
# NOTE: the output of this test is very large (> 30MB)
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: standby
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: standby-{hostname}-{date}-{time}-cg
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of standby (default: "")
# command: echo standby > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: true
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 6
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Dev S1 (Standby) test - includes src calls / kernel threads
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/standby-dev.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: standby
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: standby-{hostname}-{date}-{time}-dev
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of standby (default: "")
# command: echo standby > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: true
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Generic S1 (Standby) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/standby.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: standby
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: standby-{hostname}-{date}-{time}
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of standby (default: "")
# command: echo standby > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 0.001
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Full Callgraph for S3 (Suspend to Mem) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/suspend.cfg
#
# NOTE: the output of this test is very large (> 30MB)
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: mem
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: suspend-{hostname}-{date}-{time}-cg
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of suspend (default: "")
# command: echo mem > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 0.001
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: true
# Max graph depth
# limit the callgraph trace to this depth (default: 0 = all)
maxdepth: 5
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 6
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Dev S3 (Suspend to Mem) test - includes src calls / kernel threads
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/suspend-dev.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: mem
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: suspend-{hostname}-{date}-{time}-dev
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of suspend (default: "")
# command: echo mem > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: true
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Proc S3 (Suspend to Mem) x2 test - includes user processes
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/suspend-proc.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: mem
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: suspend-{hostname}-{date}-{time}-x2-proc
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of suspend (default: "")
# command: echo mem > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: true
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: true
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 1000
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 1000
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 1000
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 1
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
#
# Generic S3 (Suspend to Mem) test
#
# This is the configuration file for sleepgraph. It contains
# all the tool arguments so that they don't have to be given on the
# command line. It also includes advanced settings for functions
# and kprobes. It is run like this
#
# sudo ./sleepgraph.py -config config/suspend.cfg
#
[Settings]
# ---- General Options ----
# Verbosity
# print verbose messages (default: false)
verbose: false
# Suspend Mode
# e.g. standby, mem, freeze, disk (default: mem)
mode: mem
# Output Directory Format
# output folder for html, ftrace, and dmesg. Use {date} and {time} for current values
output-dir: suspend-{hostname}-{date}-{time}
# Automatic Wakeup
# Use rtcwake to autoresume after X seconds, or off to disable (default: 15)
rtcwake: 15
# Add Logs
# add the dmesg and ftrace log to the html output (default: false)
addlogs: false
# Suspend/Resume Gap
# insert a small visible gap between suspend and resume on the timeline (default: false)
srgap: false
# ---- Advanced Options ----
# Command to execute in lieu of suspend (default: "")
# command: echo mem > /sys/power/state
# Display user processes
# graph user processes and cpu usage in the timeline (default: false)
proc: false
# Display function calls
# graph source functions in the timeline (default: false)
dev: false
# Back to Back Suspend/Resume
# Run two suspend/resumes back to back (default: false)
x2: false
# Back to Back Suspend Delay
# Time delay between the two test runs in ms (default: 0 ms)
x2delay: 0
# Pre Suspend Delay
# Include an N ms delay before (1st) suspend (default: 0 ms)
predelay: 0
# Post Resume Delay
# Include an N ms delay after (last) resume (default: 0 ms)
postdelay: 0
# Minimum Device Length
# graph only devices longer than min in the timeline (default: 0.001 ms)
mindev: 0.001
# ---- Debug Options ----
# Callgraph
# gather detailed ftrace callgraph data on all timeline events (default: false)
callgraph: false
# Expand Callgraph
# pre-expand the callgraph data in the html output (default: disabled)
expandcg: false
# Minimum Callgraph Length
# provide callgraph data for blocks longer than min (default: 0.001 ms)
mincg: 1
# Timestamp Precision
# Number of significant digits in timestamps (0:S, [3:ms], 6:us)
timeprec: 3
# Device Filter
# show only devs whose name/driver includes one of these strings
# devicefilter: _cpu_up,_cpu_down,i915,usb
...@@ -52,9 +52,32 @@ disable rtcwake and require a user keypress to resume. ...@@ -52,9 +52,32 @@ disable rtcwake and require a user keypress to resume.
\fB-addlogs\fR \fB-addlogs\fR
Add the dmesg and ftrace logs to the html output. They will be viewable by Add the dmesg and ftrace logs to the html output. They will be viewable by
clicking buttons in the timeline. clicking buttons in the timeline.
.TP
\fB-result \fIfile\fR
Export a results table to a text file for parsing.
.TP
\fB-sync\fR
Sync the filesystems before starting the test. This reduces the size of
the sys_sync call which happens in the suspend_prepare phase.
.TP
\fB-rs \fIenable/disable\fR
During test, enable/disable runtime suspend for all devices. The test is delayed
by 5 seconds to allow runtime suspend changes to occur. The settings are restored
after the test is complete.
.TP
\fB-display \fIon/off\fR
Turn the display on or off for the test using the xset command. This helps
maintain the consistecy of test data for better comparison.
.TP
\fB-skiphtml\fR
Run the test and capture the trace logs, but skip the timeline generation.
.SS "advanced" .SS "advanced"
.TP .TP
\fB-gzip\fR
Gzip the trace and dmesg logs to save space. The tool can also read in gzipped
logs for processing.
.TP
\fB-cmd \fIstr\fR \fB-cmd \fIstr\fR
Run the timeline over a custom suspend command, e.g. pm-suspend. By default Run the timeline over a custom suspend command, e.g. pm-suspend. By default
the tool forces suspend via /sys/power/state so this allows testing over the tool forces suspend via /sys/power/state so this allows testing over
...@@ -114,6 +137,18 @@ This reduces the html file size as there can be many tiny callgraphs ...@@ -114,6 +137,18 @@ This reduces the html file size as there can be many tiny callgraphs
which are barely visible in the timeline. which are barely visible in the timeline.
The value is a float: e.g. 0.001 represents 1 us. The value is a float: e.g. 0.001 represents 1 us.
.TP .TP
\fB-cgfilter \fI"func1,func2,..."\fR
Reduce callgraph output in the timeline by limiting it to a list of calls. The
argument can be a single function name or a comma delimited list.
(default: none)
.TP
\fB-cgskip \fIfile\fR
Reduce callgraph timeline size by skipping over uninteresting functions
in the trace, e.g. printk or console_unlock. The functions listed
in this file will show up as empty leaves in the callgraph with only the start/end
times displayed. cgskip.txt is used automatically if found in the path, so
use "off" to disable completely (default: cgskip.txt)
.TP
\fB-cgphase \fIp\fR \fB-cgphase \fIp\fR
Only show callgraph data for phase \fIp\fR (e.g. suspend_late). Only show callgraph data for phase \fIp\fR (e.g. suspend_late).
.TP .TP
...@@ -122,6 +157,9 @@ In an x2 run, only show callgraph data for test \fIn\fR (e.g. 0 or 1). ...@@ -122,6 +157,9 @@ In an x2 run, only show callgraph data for test \fIn\fR (e.g. 0 or 1).
.TP .TP
\fB-timeprec \fIn\fR \fB-timeprec \fIn\fR
Number of significant digits in timestamps (0:S, [3:ms], 6:us). Number of significant digits in timestamps (0:S, [3:ms], 6:us).
.TP
\fB-bufsize \fIN\fR
Set trace buffer size to N kilo-bytes (default: all of free memory up to 3GB)
.SH COMMANDS .SH COMMANDS
.TP .TP
...@@ -144,11 +182,8 @@ Print out the contents of the ACPI Firmware Performance Data Table. ...@@ -144,11 +182,8 @@ Print out the contents of the ACPI Firmware Performance Data Table.
\fB-sysinfo\fR \fB-sysinfo\fR
Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode. Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode.
.TP .TP
\fB-usbtopo\fR \fB-devinfo\fR
Print out the current USB topology with power info. Print out the pm settings of all devices which support runtime suspend.
.TP
\fB-usbauto\fR
Enable autosuspend for all connected USB devices.
.TP .TP
\fB-flist\fR \fB-flist\fR
Print the list of ftrace functions currently being captured. Functions Print the list of ftrace functions currently being captured. Functions
...@@ -198,7 +233,7 @@ Execute a mem suspend with a 15 second wakeup. Include the logs in the html. ...@@ -198,7 +233,7 @@ Execute a mem suspend with a 15 second wakeup. Include the logs in the html.
.PP .PP
Execute a standby with a 15 second wakeup. Change the output folder name. Execute a standby with a 15 second wakeup. Change the output folder name.
.IP .IP
\f(CW$ sudo sleepgraph -m standby -rtcwake 15 -o "standby-{hostname}-{date}-{time}"\fR \f(CW$ sudo sleepgraph -m standby -rtcwake 15 -o "standby-{host}-{date}-{time}"\fR
.PP .PP
Execute a freeze with no wakeup (require keypress). Change output folder name. Execute a freeze with no wakeup (require keypress). Change output folder name.
.IP .IP
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment