Commit fc6763a2 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-opp', 'pm-qos', 'acpi-pm', 'pm-domains' and 'pm-tools'

* pm-opp:
  PM / OPP: Correct Documentation about library location
  opp: of: Support multiple suspend OPPs defined in DT
  dt-bindings: opp: Support multiple opp-suspend properties
  opp: core: add regulators enable and disable
  opp: Don't decrement uninitialized list_kref

* pm-qos:
  PM: QoS: Get rid of unused flags

* acpi-pm:
  ACPI: PM: Print debug messages on device power state changes

* pm-domains:
  PM / Domains: Verify PM domain type in dev_pm_genpd_set_performance_state()
  PM / Domains: Simplify genpd_lookup_dev()
  PM / Domains: Align in-parameter names for some genpd functions

* pm-tools:
  pm-graph: make setVal unbuffered again for python2 and python3
  cpupower: update German translation
  tools/power/cpupower: fix 64bit detection when cross-compiling
  cpupower: Add missing newline at end of file
  pm-graph v5.5
...@@ -140,8 +140,8 @@ Optional properties: ...@@ -140,8 +140,8 @@ Optional properties:
frequency for a short duration of time limited by the device's power, current frequency for a short duration of time limited by the device's power, current
and thermal limits. and thermal limits.
- opp-suspend: Marks the OPP to be used during device suspend. Only one OPP in - opp-suspend: Marks the OPP to be used during device suspend. If multiple OPPs
the table should have this. in the table have this, the OPP with highest opp-hz will be used.
- opp-supported-hw: This enables us to select only a subset of OPPs from the - opp-supported-hw: This enables us to select only a subset of OPPs from the
larger OPP table, based on what version of the hardware we are running on. We larger OPP table, based on what version of the hardware we are running on. We
......
...@@ -46,7 +46,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples: ...@@ -46,7 +46,7 @@ We can represent these as three OPPs as the following {Hz, uV} tuples:
---------------------------------------- ----------------------------------------
OPP library provides a set of helper functions to organize and query the OPP OPP library provides a set of helper functions to organize and query the OPP
information. The library is located in drivers/base/power/opp.c and the header information. The library is located in drivers/opp/ directory and the header
is located in include/linux/pm_opp.h. OPP library can be enabled by enabling is located in include/linux/pm_opp.h. OPP library can be enabled by enabling
CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on CONFIG_PM_OPP from power management menuconfig menu. OPP library depends on
CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to CONFIG_PM as certain SoCs such as Texas Instrument's OMAP framework allows to
......
...@@ -7,8 +7,7 @@ performance expectations by drivers, subsystems and user space applications on ...@@ -7,8 +7,7 @@ performance expectations by drivers, subsystems and user space applications on
one of the parameters. one of the parameters.
Two different PM QoS frameworks are available: Two different PM QoS frameworks are available:
1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput, 1. PM QoS classes for cpu_dma_latency
memory_bandwidth.
2. the per-device PM QoS framework provides the API to manage the per-device latency 2. the per-device PM QoS framework provides the API to manage the per-device latency
constraints and PM QoS flags. constraints and PM QoS flags.
...@@ -79,7 +78,7 @@ cleanup of a process, the interface requires the process to register its ...@@ -79,7 +78,7 @@ cleanup of a process, the interface requires the process to register its
parameter requests in the following way: parameter requests in the following way:
To register the default pm_qos target for the specific parameter, the process To register the default pm_qos target for the specific parameter, the process
must open one of /dev/[cpu_dma_latency, network_latency, network_throughput] must open /dev/cpu_dma_latency
As long as the device node is held open that process has a registered As long as the device node is held open that process has a registered
request on the parameter. request on the parameter.
......
...@@ -166,6 +166,10 @@ int acpi_device_set_power(struct acpi_device *device, int state) ...@@ -166,6 +166,10 @@ int acpi_device_set_power(struct acpi_device *device, int state)
|| (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD)) || (state < ACPI_STATE_D0) || (state > ACPI_STATE_D3_COLD))
return -EINVAL; return -EINVAL;
acpi_handle_debug(device->handle, "Power state change: %s -> %s\n",
acpi_power_state_string(device->power.state),
acpi_power_state_string(state));
/* Make sure this is a valid target state */ /* Make sure this is a valid target state */
/* There is a special case for D0 addressed below. */ /* There is a special case for D0 addressed below. */
......
...@@ -149,29 +149,24 @@ static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev, ...@@ -149,29 +149,24 @@ static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
return ret; return ret;
} }
static int genpd_runtime_suspend(struct device *dev);
/* /*
* Get the generic PM domain for a particular struct device. * Get the generic PM domain for a particular struct device.
* This validates the struct device pointer, the PM domain pointer, * This validates the struct device pointer, the PM domain pointer,
* and checks that the PM domain pointer is a real generic PM domain. * and checks that the PM domain pointer is a real generic PM domain.
* Any failure results in NULL being returned. * Any failure results in NULL being returned.
*/ */
static struct generic_pm_domain *genpd_lookup_dev(struct device *dev) static struct generic_pm_domain *dev_to_genpd_safe(struct device *dev)
{ {
struct generic_pm_domain *genpd = NULL, *gpd;
if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain)) if (IS_ERR_OR_NULL(dev) || IS_ERR_OR_NULL(dev->pm_domain))
return NULL; return NULL;
mutex_lock(&gpd_list_lock); /* A genpd's always have its ->runtime_suspend() callback assigned. */
list_for_each_entry(gpd, &gpd_list, gpd_list_node) { if (dev->pm_domain->ops.runtime_suspend == genpd_runtime_suspend)
if (&gpd->domain == dev->pm_domain) { return pd_to_genpd(dev->pm_domain);
genpd = gpd;
break;
}
}
mutex_unlock(&gpd_list_lock);
return genpd; return NULL;
} }
/* /*
...@@ -385,8 +380,8 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state) ...@@ -385,8 +380,8 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
unsigned int prev; unsigned int prev;
int ret; int ret;
genpd = dev_to_genpd(dev); genpd = dev_to_genpd_safe(dev);
if (IS_ERR(genpd)) if (!genpd)
return -ENODEV; return -ENODEV;
if (unlikely(!genpd->set_performance_state)) if (unlikely(!genpd->set_performance_state))
...@@ -1610,7 +1605,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd, ...@@ -1610,7 +1605,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
*/ */
int pm_genpd_remove_device(struct device *dev) int pm_genpd_remove_device(struct device *dev)
{ {
struct generic_pm_domain *genpd = genpd_lookup_dev(dev); struct generic_pm_domain *genpd = dev_to_genpd_safe(dev);
if (!genpd) if (!genpd)
return -EINVAL; return -EINVAL;
......
...@@ -988,6 +988,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index) ...@@ -988,6 +988,7 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head); BLOCKING_INIT_NOTIFIER_HEAD(&opp_table->head);
INIT_LIST_HEAD(&opp_table->opp_list); INIT_LIST_HEAD(&opp_table->opp_list);
kref_init(&opp_table->kref); kref_init(&opp_table->kref);
kref_init(&opp_table->list_kref);
/* Secure the device table modification */ /* Secure the device table modification */
list_add(&opp_table->node, &opp_tables); list_add(&opp_table->node, &opp_tables);
...@@ -1625,6 +1626,12 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, ...@@ -1625,6 +1626,12 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
goto free_regulators; goto free_regulators;
} }
ret = regulator_enable(reg);
if (ret < 0) {
regulator_put(reg);
goto free_regulators;
}
opp_table->regulators[i] = reg; opp_table->regulators[i] = reg;
} }
...@@ -1638,8 +1645,10 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev, ...@@ -1638,8 +1645,10 @@ struct opp_table *dev_pm_opp_set_regulators(struct device *dev,
return opp_table; return opp_table;
free_regulators: free_regulators:
while (i != 0) while (i--) {
regulator_put(opp_table->regulators[--i]); regulator_disable(opp_table->regulators[i]);
regulator_put(opp_table->regulators[i]);
}
kfree(opp_table->regulators); kfree(opp_table->regulators);
opp_table->regulators = NULL; opp_table->regulators = NULL;
...@@ -1665,8 +1674,10 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table) ...@@ -1665,8 +1674,10 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
/* Make sure there are no concurrent readers while updating opp_table */ /* Make sure there are no concurrent readers while updating opp_table */
WARN_ON(!list_empty(&opp_table->opp_list)); WARN_ON(!list_empty(&opp_table->opp_list));
for (i = opp_table->regulator_count - 1; i >= 0; i--) for (i = opp_table->regulator_count - 1; i >= 0; i--) {
regulator_disable(opp_table->regulators[i]);
regulator_put(opp_table->regulators[i]); regulator_put(opp_table->regulators[i]);
}
_free_set_opp_data(opp_table); _free_set_opp_data(opp_table);
......
...@@ -617,9 +617,12 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table, ...@@ -617,9 +617,12 @@ static struct dev_pm_opp *_opp_add_static_v2(struct opp_table *opp_table,
/* OPP to select on device suspend */ /* OPP to select on device suspend */
if (of_property_read_bool(np, "opp-suspend")) { if (of_property_read_bool(np, "opp-suspend")) {
if (opp_table->suspend_opp) { if (opp_table->suspend_opp) {
dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n", /* Pick the OPP with higher rate as suspend OPP */
__func__, opp_table->suspend_opp->rate, if (new_opp->rate > opp_table->suspend_opp->rate) {
new_opp->rate); opp_table->suspend_opp->suspend = false;
new_opp->suspend = true;
opp_table->suspend_opp = new_opp;
}
} else { } else {
new_opp->suspend = true; new_opp->suspend = true;
opp_table->suspend_opp = new_opp; opp_table->suspend_opp = new_opp;
...@@ -662,8 +665,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) ...@@ -662,8 +665,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
return 0; return 0;
} }
kref_init(&opp_table->list_kref);
/* We have opp-table node now, iterate over it and add OPPs */ /* We have opp-table node now, iterate over it and add OPPs */
for_each_available_child_of_node(opp_table->np, np) { for_each_available_child_of_node(opp_table->np, np) {
opp = _opp_add_static_v2(opp_table, dev, np); opp = _opp_add_static_v2(opp_table, dev, np);
...@@ -672,17 +673,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) ...@@ -672,17 +673,15 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
dev_err(dev, "%s: Failed to add OPP, %d\n", __func__, dev_err(dev, "%s: Failed to add OPP, %d\n", __func__,
ret); ret);
of_node_put(np); of_node_put(np);
goto put_list_kref; return ret;
} else if (opp) { } else if (opp) {
count++; count++;
} }
} }
/* There should be one of more OPP defined */ /* There should be one of more OPP defined */
if (WARN_ON(!count)) { if (WARN_ON(!count))
ret = -ENOENT; return -ENOENT;
goto put_list_kref;
}
list_for_each_entry(opp, &opp_table->opp_list, node) list_for_each_entry(opp, &opp_table->opp_list, node)
pstate_count += !!opp->pstate; pstate_count += !!opp->pstate;
...@@ -691,8 +690,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) ...@@ -691,8 +690,7 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
if (pstate_count && pstate_count != count) { if (pstate_count && pstate_count != count) {
dev_err(dev, "Not all nodes have performance state set (%d: %d)\n", dev_err(dev, "Not all nodes have performance state set (%d: %d)\n",
count, pstate_count); count, pstate_count);
ret = -ENOENT; return -ENOENT;
goto put_list_kref;
} }
if (pstate_count) if (pstate_count)
...@@ -701,11 +699,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table) ...@@ -701,11 +699,6 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
opp_table->parsed_static_opps = true; opp_table->parsed_static_opps = true;
return 0; return 0;
put_list_kref:
_put_opp_list_kref(opp_table);
return ret;
} }
/* Initializes OPP tables based on old-deprecated bindings */ /* Initializes OPP tables based on old-deprecated bindings */
...@@ -731,8 +724,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) ...@@ -731,8 +724,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
return -EINVAL; return -EINVAL;
} }
kref_init(&opp_table->list_kref);
val = prop->value; val = prop->value;
while (nr) { while (nr) {
unsigned long freq = be32_to_cpup(val++) * 1000; unsigned long freq = be32_to_cpup(val++) * 1000;
...@@ -742,7 +733,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table) ...@@ -742,7 +733,6 @@ static int _of_add_opp_table_v1(struct device *dev, struct opp_table *opp_table)
if (ret) { if (ret) {
dev_err(dev, "%s: Failed to add OPP %ld (%d)\n", dev_err(dev, "%s: Failed to add OPP %ld (%d)\n",
__func__, freq, ret); __func__, freq, ret);
_put_opp_list_kref(opp_table);
return ret; return ret;
} }
nr -= 2; nr -= 2;
......
...@@ -197,9 +197,9 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev) ...@@ -197,9 +197,9 @@ static inline struct generic_pm_domain_data *dev_gpd_data(struct device *dev)
int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev); int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev);
int pm_genpd_remove_device(struct device *dev); int pm_genpd_remove_device(struct device *dev);
int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_subdomain); struct generic_pm_domain *subdomain);
int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *target); struct generic_pm_domain *subdomain);
int pm_genpd_init(struct generic_pm_domain *genpd, int pm_genpd_init(struct generic_pm_domain *genpd,
struct dev_power_governor *gov, bool is_off); struct dev_power_governor *gov, bool is_off);
int pm_genpd_remove(struct generic_pm_domain *genpd); int pm_genpd_remove(struct generic_pm_domain *genpd);
...@@ -226,12 +226,12 @@ static inline int pm_genpd_remove_device(struct device *dev) ...@@ -226,12 +226,12 @@ static inline int pm_genpd_remove_device(struct device *dev)
return -ENOSYS; return -ENOSYS;
} }
static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *new_sd) struct generic_pm_domain *subdomain)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, static inline int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *target) struct generic_pm_domain *subdomain)
{ {
return -ENOSYS; return -ENOSYS;
} }
...@@ -282,8 +282,8 @@ int of_genpd_add_provider_onecell(struct device_node *np, ...@@ -282,8 +282,8 @@ int of_genpd_add_provider_onecell(struct device_node *np,
struct genpd_onecell_data *data); struct genpd_onecell_data *data);
void of_genpd_del_provider(struct device_node *np); void of_genpd_del_provider(struct device_node *np);
int of_genpd_add_device(struct of_phandle_args *args, struct device *dev); int of_genpd_add_device(struct of_phandle_args *args, struct device *dev);
int of_genpd_add_subdomain(struct of_phandle_args *parent, int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
struct of_phandle_args *new_subdomain); struct of_phandle_args *subdomain_spec);
struct generic_pm_domain *of_genpd_remove_last(struct device_node *np); struct generic_pm_domain *of_genpd_remove_last(struct device_node *np);
int of_genpd_parse_idle_states(struct device_node *dn, int of_genpd_parse_idle_states(struct device_node *dn,
struct genpd_power_state **states, int *n); struct genpd_power_state **states, int *n);
...@@ -316,8 +316,8 @@ static inline int of_genpd_add_device(struct of_phandle_args *args, ...@@ -316,8 +316,8 @@ static inline int of_genpd_add_device(struct of_phandle_args *args,
return -ENODEV; return -ENODEV;
} }
static inline int of_genpd_add_subdomain(struct of_phandle_args *parent, static inline int of_genpd_add_subdomain(struct of_phandle_args *parent_spec,
struct of_phandle_args *new_subdomain) struct of_phandle_args *subdomain_spec)
{ {
return -ENODEV; return -ENODEV;
} }
......
...@@ -13,9 +13,6 @@ ...@@ -13,9 +13,6 @@
enum { enum {
PM_QOS_RESERVED = 0, PM_QOS_RESERVED = 0,
PM_QOS_CPU_DMA_LATENCY, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_NETWORK_LATENCY,
PM_QOS_NETWORK_THROUGHPUT,
PM_QOS_MEMORY_BANDWIDTH,
/* insert new class ID */ /* insert new class ID */
PM_QOS_NUM_CLASSES, PM_QOS_NUM_CLASSES,
...@@ -33,9 +30,6 @@ enum pm_qos_flags_status { ...@@ -33,9 +30,6 @@ enum pm_qos_flags_status {
#define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC) #define PM_QOS_LATENCY_ANY_NS ((s64)PM_QOS_LATENCY_ANY * NSEC_PER_USEC)
#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC) #define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0
#define PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE 0
#define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_DEFAULT_VALUE PM_QOS_LATENCY_ANY
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS #define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
......
...@@ -379,9 +379,7 @@ DECLARE_EVENT_CLASS(pm_qos_request, ...@@ -379,9 +379,7 @@ DECLARE_EVENT_CLASS(pm_qos_request,
TP_printk("pm_qos_class=%s value=%d", TP_printk("pm_qos_class=%s value=%d",
__print_symbolic(__entry->pm_qos_class, __print_symbolic(__entry->pm_qos_class,
{ PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }),
{ PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" },
{ PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }),
__entry->value) __entry->value)
); );
...@@ -426,9 +424,7 @@ TRACE_EVENT(pm_qos_update_request_timeout, ...@@ -426,9 +424,7 @@ TRACE_EVENT(pm_qos_update_request_timeout,
TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld", TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld",
__print_symbolic(__entry->pm_qos_class, __print_symbolic(__entry->pm_qos_class,
{ PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }),
{ PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" },
{ PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }),
__entry->value, __entry->timeout_us) __entry->value, __entry->timeout_us)
); );
......
...@@ -78,57 +78,9 @@ static struct pm_qos_object cpu_dma_pm_qos = { ...@@ -78,57 +78,9 @@ static struct pm_qos_object cpu_dma_pm_qos = {
.name = "cpu_dma_latency", .name = "cpu_dma_latency",
}; };
static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
static struct pm_qos_constraints network_lat_constraints = {
.list = PLIST_HEAD_INIT(network_lat_constraints.list),
.target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
.default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
.no_constraint_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
.type = PM_QOS_MIN,
.notifiers = &network_lat_notifier,
};
static struct pm_qos_object network_lat_pm_qos = {
.constraints = &network_lat_constraints,
.name = "network_latency",
};
static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
static struct pm_qos_constraints network_tput_constraints = {
.list = PLIST_HEAD_INIT(network_tput_constraints.list),
.target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
.default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
.no_constraint_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
.type = PM_QOS_MAX,
.notifiers = &network_throughput_notifier,
};
static struct pm_qos_object network_throughput_pm_qos = {
.constraints = &network_tput_constraints,
.name = "network_throughput",
};
static BLOCKING_NOTIFIER_HEAD(memory_bandwidth_notifier);
static struct pm_qos_constraints memory_bw_constraints = {
.list = PLIST_HEAD_INIT(memory_bw_constraints.list),
.target_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE,
.default_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE,
.no_constraint_value = PM_QOS_MEMORY_BANDWIDTH_DEFAULT_VALUE,
.type = PM_QOS_SUM,
.notifiers = &memory_bandwidth_notifier,
};
static struct pm_qos_object memory_bandwidth_pm_qos = {
.constraints = &memory_bw_constraints,
.name = "memory_bandwidth",
};
static struct pm_qos_object *pm_qos_array[] = { static struct pm_qos_object *pm_qos_array[] = {
&null_pm_qos, &null_pm_qos,
&cpu_dma_pm_qos, &cpu_dma_pm_qos,
&network_lat_pm_qos,
&network_throughput_pm_qos,
&memory_bandwidth_pm_qos,
}; };
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
......
...@@ -18,7 +18,6 @@ OUTDIR := $(shell cd $(OUTPUT) && pwd) ...@@ -18,7 +18,6 @@ OUTDIR := $(shell cd $(OUTPUT) && pwd)
$(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist)) $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
endif endif
include ../../scripts/Makefile.arch
# --- CONFIGURATION BEGIN --- # --- CONFIGURATION BEGIN ---
...@@ -69,11 +68,6 @@ bindir ?= /usr/bin ...@@ -69,11 +68,6 @@ bindir ?= /usr/bin
sbindir ?= /usr/sbin sbindir ?= /usr/sbin
mandir ?= /usr/man mandir ?= /usr/man
includedir ?= /usr/include includedir ?= /usr/include
ifeq ($(IS_64_BIT), 1)
libdir ?= /usr/lib64
else
libdir ?= /usr/lib
endif
localedir ?= /usr/share/locale localedir ?= /usr/share/locale
docdir ?= /usr/share/doc/packages/cpupower docdir ?= /usr/share/doc/packages/cpupower
confdir ?= /etc/ confdir ?= /etc/
...@@ -100,6 +94,14 @@ RANLIB = $(CROSS)ranlib ...@@ -100,6 +94,14 @@ RANLIB = $(CROSS)ranlib
HOSTCC = gcc HOSTCC = gcc
MKDIR = mkdir MKDIR = mkdir
# 64bit library detection
include ../../scripts/Makefile.arch
ifeq ($(IS_64_BIT), 1)
libdir ?= /usr/lib64
else
libdir ?= /usr/lib
endif
# Now we set up the build system # Now we set up the build system
# #
......
...@@ -88,4 +88,4 @@ done ...@@ -88,4 +88,4 @@ done
echo >> $dir/plot_script.gpl echo >> $dir/plot_script.gpl
gnuplot $dir/plot_script.gpl gnuplot $dir/plot_script.gpl
rm -r $dir rm -r $dir
\ No newline at end of file
...@@ -85,4 +85,4 @@ function create_plots() ...@@ -85,4 +85,4 @@ function create_plots()
} }
measure measure
create_plots create_plots
\ No newline at end of file
This diff is collapsed.
p m - g r a p h p m - g r a p h
pm-graph: suspend/resume/boot timing analysis tools pm-graph: suspend/resume/boot timing analysis tools
Version: 5.4 Version: 5.5
Author: Todd Brandt <todd.e.brandt@intel.com> Author: Todd Brandt <todd.e.brandt@intel.com>
Home Page: https://01.org/pm-graph Home Page: https://01.org/pm-graph
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
- upstream version in git: - upstream version in git:
https://github.com/intel/pm-graph/ https://github.com/intel/pm-graph/
Requirements:
- runs with python2 or python3, choice is made by /usr/bin/python link
- python2 now requires python-configparser be installed
Table of Contents Table of Contents
- Overview - Overview
- Setup - Setup
......
#!/usr/bin/python2 #!/usr/bin/python
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
# #
# Tool for analyzing boot timing # Tool for analyzing boot timing
# Copyright (c) 2013, Intel Corporation. # Copyright (c) 2013, Intel Corporation.
# #
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# Authors: # Authors:
# Todd Brandt <todd.e.brandt@linux.intel.com> # Todd Brandt <todd.e.brandt@linux.intel.com>
# #
...@@ -81,7 +90,7 @@ class SystemValues(aslib.SystemValues): ...@@ -81,7 +90,7 @@ class SystemValues(aslib.SystemValues):
cmdline = 'initcall_debug log_buf_len=32M' cmdline = 'initcall_debug log_buf_len=32M'
if self.useftrace: if self.useftrace:
if self.cpucount > 0: if self.cpucount > 0:
bs = min(self.memtotal / 2, 2*1024*1024) / self.cpucount bs = min(self.memtotal // 2, 2*1024*1024) // self.cpucount
else: else:
bs = 131072 bs = 131072
cmdline += ' trace_buf_size=%dK trace_clock=global '\ cmdline += ' trace_buf_size=%dK trace_clock=global '\
...@@ -137,13 +146,13 @@ class SystemValues(aslib.SystemValues): ...@@ -137,13 +146,13 @@ class SystemValues(aslib.SystemValues):
if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']: if arg in ['-h', '-v', '-cronjob', '-reboot', '-verbose']:
continue continue
elif arg in ['-o', '-dmesg', '-ftrace', '-func']: elif arg in ['-o', '-dmesg', '-ftrace', '-func']:
args.next() next(args)
continue continue
elif arg == '-result': elif arg == '-result':
cmdline += ' %s "%s"' % (arg, os.path.abspath(args.next())) cmdline += ' %s "%s"' % (arg, os.path.abspath(next(args)))
continue continue
elif arg == '-cgskip': elif arg == '-cgskip':
file = self.configFile(args.next()) file = self.configFile(next(args))
cmdline += ' %s "%s"' % (arg, os.path.abspath(file)) cmdline += ' %s "%s"' % (arg, os.path.abspath(file))
continue continue
cmdline += ' '+arg cmdline += ' '+arg
...@@ -292,11 +301,11 @@ def parseKernelLog(): ...@@ -292,11 +301,11 @@ def parseKernelLog():
tp = aslib.TestProps() tp = aslib.TestProps()
devtemp = dict() devtemp = dict()
if(sysvals.dmesgfile): if(sysvals.dmesgfile):
lf = open(sysvals.dmesgfile, 'r') lf = open(sysvals.dmesgfile, 'rb')
else: else:
lf = Popen('dmesg', stdout=PIPE).stdout lf = Popen('dmesg', stdout=PIPE).stdout
for line in lf: for line in lf:
line = line.replace('\r\n', '') line = aslib.ascii(line).replace('\r\n', '')
# grab the stamp and sysinfo # grab the stamp and sysinfo
if re.match(tp.stampfmt, line): if re.match(tp.stampfmt, line):
tp.stamp = line tp.stamp = line
...@@ -649,7 +658,7 @@ def createBootGraph(data): ...@@ -649,7 +658,7 @@ def createBootGraph(data):
statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info']) statinfo += '\t"%s": [\n\t\t"%s",\n' % (n, devstats[n]['info'])
if 'fstat' in devstats[n]: if 'fstat' in devstats[n]:
funcs = devstats[n]['fstat'] funcs = devstats[n]['fstat']
for f in sorted(funcs, key=funcs.get, reverse=True): for f in sorted(funcs, key=lambda k:(funcs[k], k), reverse=True):
if funcs[f][0] < 0.01 and len(funcs) > 10: if funcs[f][0] < 0.01 and len(funcs) > 10:
break break
statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1]) statinfo += '\t\t"%f|%s|%d",\n' % (funcs[f][0], f, funcs[f][1])
...@@ -729,7 +738,7 @@ def updateCron(restore=False): ...@@ -729,7 +738,7 @@ def updateCron(restore=False):
op.write('@reboot python %s\n' % sysvals.cronjobCmdString()) op.write('@reboot python %s\n' % sysvals.cronjobCmdString())
op.close() op.close()
res = call([cmd, cronfile]) res = call([cmd, cronfile])
except Exception, e: except Exception as e:
pprint('Exception: %s' % str(e)) pprint('Exception: %s' % str(e))
shutil.move(backfile, cronfile) shutil.move(backfile, cronfile)
res = -1 res = -1
...@@ -745,7 +754,7 @@ def updateGrub(restore=False): ...@@ -745,7 +754,7 @@ def updateGrub(restore=False):
try: try:
call(sysvals.blexec, stderr=PIPE, stdout=PIPE, call(sysvals.blexec, stderr=PIPE, stdout=PIPE,
env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'}) env={'PATH': '.:/sbin:/usr/sbin:/usr/bin:/sbin:/bin'})
except Exception, e: except Exception as e:
pprint('Exception: %s\n' % str(e)) pprint('Exception: %s\n' % str(e))
return return
# extract the option and create a grub config without it # extract the option and create a grub config without it
...@@ -792,7 +801,7 @@ def updateGrub(restore=False): ...@@ -792,7 +801,7 @@ def updateGrub(restore=False):
op.close() op.close()
res = call(sysvals.blexec) res = call(sysvals.blexec)
os.remove(grubfile) os.remove(grubfile)
except Exception, e: except Exception as e:
pprint('Exception: %s' % str(e)) pprint('Exception: %s' % str(e))
res = -1 res = -1
# cleanup # cleanup
...@@ -866,6 +875,7 @@ def printHelp(): ...@@ -866,6 +875,7 @@ def printHelp():
'Other commands:\n'\ 'Other commands:\n'\
' -flistall Print all functions capable of being captured in ftrace\n'\ ' -flistall Print all functions capable of being captured in ftrace\n'\
' -sysinfo Print out system info extracted from BIOS\n'\ ' -sysinfo Print out system info extracted from BIOS\n'\
' -which exec Print an executable path, should function even without PATH\n'\
' [redo]\n'\ ' [redo]\n'\
' -dmesg file Create HTML output using dmesg input (used with -ftrace)\n'\ ' -dmesg file Create HTML output using dmesg input (used with -ftrace)\n'\
' -ftrace file Create HTML output using ftrace input (used with -dmesg)\n'\ ' -ftrace file Create HTML output using ftrace input (used with -dmesg)\n'\
...@@ -907,13 +917,13 @@ if __name__ == '__main__': ...@@ -907,13 +917,13 @@ if __name__ == '__main__':
sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0) sysvals.mincglen = aslib.getArgFloat('-mincg', args, 0.0, 10000.0)
elif(arg == '-cgfilter'): elif(arg == '-cgfilter'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No callgraph functions supplied', True) doError('No callgraph functions supplied', True)
sysvals.setCallgraphFilter(val) sysvals.setCallgraphFilter(val)
elif(arg == '-cgskip'): elif(arg == '-cgskip'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No file supplied', True) doError('No file supplied', True)
if val.lower() in switchoff: if val.lower() in switchoff:
...@@ -924,7 +934,7 @@ if __name__ == '__main__': ...@@ -924,7 +934,7 @@ if __name__ == '__main__':
doError('%s does not exist' % cgskip) doError('%s does not exist' % cgskip)
elif(arg == '-bl'): elif(arg == '-bl'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No boot loader name supplied', True) doError('No boot loader name supplied', True)
if val.lower() not in ['grub']: if val.lower() not in ['grub']:
...@@ -937,7 +947,7 @@ if __name__ == '__main__': ...@@ -937,7 +947,7 @@ if __name__ == '__main__':
sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000) sysvals.max_graph_depth = aslib.getArgInt('-maxdepth', args, 0, 1000)
elif(arg == '-func'): elif(arg == '-func'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No filter functions supplied', True) doError('No filter functions supplied', True)
sysvals.useftrace = True sysvals.useftrace = True
...@@ -946,7 +956,7 @@ if __name__ == '__main__': ...@@ -946,7 +956,7 @@ if __name__ == '__main__':
sysvals.setGraphFilter(val) sysvals.setGraphFilter(val)
elif(arg == '-ftrace'): elif(arg == '-ftrace'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No ftrace file supplied', True) doError('No ftrace file supplied', True)
if(os.path.exists(val) == False): if(os.path.exists(val) == False):
...@@ -959,7 +969,7 @@ if __name__ == '__main__': ...@@ -959,7 +969,7 @@ if __name__ == '__main__':
sysvals.cgexp = True sysvals.cgexp = True
elif(arg == '-dmesg'): elif(arg == '-dmesg'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No dmesg file supplied', True) doError('No dmesg file supplied', True)
if(os.path.exists(val) == False): if(os.path.exists(val) == False):
...@@ -968,13 +978,13 @@ if __name__ == '__main__': ...@@ -968,13 +978,13 @@ if __name__ == '__main__':
sysvals.dmesgfile = val sysvals.dmesgfile = val
elif(arg == '-o'): elif(arg == '-o'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No subdirectory name supplied', True) doError('No subdirectory name supplied', True)
sysvals.testdir = sysvals.setOutputFolder(val) sysvals.testdir = sysvals.setOutputFolder(val)
elif(arg == '-result'): elif(arg == '-result'):
try: try:
val = args.next() val = next(args)
except: except:
doError('No result file supplied', True) doError('No result file supplied', True)
sysvals.result = val sysvals.result = val
...@@ -986,6 +996,17 @@ if __name__ == '__main__': ...@@ -986,6 +996,17 @@ if __name__ == '__main__':
# remaining options are only for cron job use # remaining options are only for cron job use
elif(arg == '-cronjob'): elif(arg == '-cronjob'):
sysvals.iscronjob = True sysvals.iscronjob = True
elif(arg == '-which'):
try:
val = next(args)
except:
doError('No executable supplied', True)
out = sysvals.getExec(val)
if not out:
print('%s not found' % val)
sys.exit(1)
print(out)
sys.exit(0)
else: else:
doError('Invalid argument: '+arg, True) doError('Invalid argument: '+arg, True)
......
...@@ -53,10 +53,10 @@ disable rtcwake and require a user keypress to resume. ...@@ -53,10 +53,10 @@ disable rtcwake and require a user keypress to resume.
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 .TP
\fB-turbostat\fR \fB-noturbostat\fR
Use turbostat to execute the command in freeze mode (default: disabled). This By default, if turbostat is found and the requested mode is freeze, sleepgraph
will provide turbostat output in the log which will tell you which actual will execute the suspend via turbostat and collect data in the timeline log.
power modes were entered. This option disables the use of turbostat.
.TP .TP
\fB-result \fIfile\fR \fB-result \fIfile\fR
Export a results table to a text file for parsing. Export a results table to a text file for parsing.
......
This diff is collapsed.
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