* [PATCH]PM QOS refresh against next-20100430
@ 2010-04-30 21:17 mark gross
0 siblings, 0 replies; 14+ messages in thread
From: mark gross @ 2010-04-30 21:17 UTC (permalink / raw)
To: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel
Cc: linux-pm, lkml
The following is a refresh of the PM_QOS implementation, this patch
updates some documentation input I got from Randy.
This patch changes the string based list management to a handle base
implementation to help with the hot path use of pm-qos, it also renames
much of the API to use "request" as opposed to "requirement" that was
used in the initial implementation. I did this because request more
accurately represents what it actually does.
Also, I added a string based ABI for users wanting to use a string
interface. So if the user writes 0xDDDDDDDD formatted hex it will be
accepted by the interface. (someone asked me for it and I don't think
it hurts anything.)
I really would like to get this refresh taken care of. Its been taking
me too long to close this. please review or include it in next.
Thanks!
--mgross
>From c45d8d86f89ac55fbb9a499fbc754e35258bf818 Mon Sep 17 00:00:00 2001
From: mgross <mark.gross@gmail.com>
Date: Sat, 13 Mar 2010 08:18:36 -0800
Subject: [PATCH 1/2] PM_QOS to use handle based list implementation and exported function name changes to be more descriptive of what is actually happening.
---
Documentation/power/pm_qos_interface.txt | 48 ++++---
drivers/acpi/processor_idle.c | 2 +-
drivers/cpuidle/governors/ladder.c | 2 +-
| 2 +-
drivers/net/e1000e/netdev.c | 22 ++--
drivers/net/igbvf/netdev.c | 6 +-
drivers/net/wireless/ipw2x00/ipw2100.c | 11 +-
include/linux/netdevice.h | 4 +
include/linux/pm_qos_params.h | 14 +-
include/sound/pcm.h | 3 +-
kernel/pm_qos_params.c | 214 ++++++++++++++---------------
net/mac80211/mlme.c | 2 +-
net/mac80211/scan.c | 2 +-
sound/core/pcm.c | 3 -
sound/core/pcm_native.c | 14 +-
15 files changed, 177 insertions(+), 172 deletions(-)
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index c40866e..bfed898 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -18,44 +18,46 @@ and pm_qos_params.h. This is done because having the available parameters
being runtime configurable or changeable from a driver was seen as too easy to
abuse.
-For each parameter a list of performance requirements is maintained along with
+For each parameter a list of performance requests is maintained along with
an aggregated target value. The aggregated target value is updated with
-changes to the requirement list or elements of the list. Typically the
-aggregated target value is simply the max or min of the requirement values held
+changes to the request list or elements of the list. Typically the
+aggregated target value is simply the max or min of the request values held
in the parameter list elements.
From kernel mode the use of this interface is simple:
-pm_qos_add_requirement(param_id, name, target_value):
-Will insert a named element in the list for that identified PM_QOS parameter
-with the target value. Upon change to this list the new target is recomputed
-and any registered notifiers are called only if the target value is now
-different.
-pm_qos_update_requirement(param_id, name, new_target_value):
-Will search the list identified by the param_id for the named list element and
-then update its target value, calling the notification tree if the aggregated
-target is changed. with that name is already registered.
+handle = pm_qos_add_request(param_class, target_value):
+Will insert an element into the list for that identified PM_QOS class with the
+target value. Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of pm_qos need to save the returned handle.
-pm_qos_remove_requirement(param_id, name):
-Will search the identified list for the named element and remove it, after
-removal it will update the aggregate target and call the notification tree if
-the target was changed as a result of removing the named requirement.
+void pm_qos_update_request(handle, new_target_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification tree if the
+target is changed.
+
+void pm_qos_remove_request(handle):
+Will remove the element. After removal it will update the aggregate target and
+call the notification tree if the target was changed as a result of removing
+the request.
From user mode:
-Only processes can register a pm_qos requirement. To provide for automatic
-cleanup for process the interface requires the process to register its
-parameter requirements in the following way:
+Only processes can register a pm_qos request. To provide for automatic
+cleanup of a process, the interface requires the process to register its
+parameter requests in the following way:
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]
As long as the device node is held open that process has a registered
-requirement on the parameter. The name of the requirement is "process_<PID>"
-derived from the current->pid from within the open system call.
+request on the parameter.
-To change the requested target value the process needs to write a s32 value to
-the open device node. This translates to a pm_qos_update_requirement call.
+To change the requested target value the process needs to write an s32 value to
+the open device node. Alternatively the user mode program could write a hex
+string for the value using 10 char long format e.g. "0x12345678". This
+translates to a pm_qos_update_request call.
To remove the user mode request for a target value simply close the device
node.
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5939e7f..c3817e1 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
"max_cstate: C%d\n"
"maximum allowed latency: %d usec\n",
pr->power.state ? pr->power.state - pr->power.states : 0,
- max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
+ max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
seq_puts(seq, "states:\n");
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 1c1ceb4..12c9890 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
struct ladder_device_state *last_state;
int last_residency, last_idx = ldev->last_state_idx;
- int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
/* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0)) {
--git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1aea715..61ca939 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -183,7 +183,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
static int menu_select(struct cpuidle_device *dev)
{
struct menu_device *data = &__get_cpu_var(menu_devices);
- int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
int i;
int multiplier;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 904bd6b..7550879 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2882,12 +2882,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
* excessive C-state transition latencies result in
* dropped transactions.
*/
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name, 55);
+ pm_qos_update_request(
+ adapter->netdev->pm_qos_req, 55);
} else {
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name,
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(
+ adapter->netdev->pm_qos_req,
+ PM_QOS_DEFAULT_VALUE);
}
}
@@ -3181,8 +3181,8 @@ int e1000e_up(struct e1000_adapter *adapter)
/* DMA latency requirement to workaround early-receive/jumbo issue */
if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name,
+ adapter->netdev->pm_qos_req =
+ pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
/* hardware has been reset, we need to reload some things */
@@ -3244,9 +3244,11 @@ void e1000e_down(struct e1000_adapter *adapter)
e1000_clean_tx_ring(adapter);
e1000_clean_rx_ring(adapter);
- if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name);
+ if (adapter->flags & FLAG_HAS_ERT) {
+ pm_qos_remove_request(
+ adapter->netdev->pm_qos_req);
+ adapter->netdev->pm_qos_req = NULL;
+ }
/*
* TODO: for power management, we could drop the link and
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 7012e3d..5e2b2a8 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -48,6 +48,7 @@
#define DRV_VERSION "1.0.0-k0"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
+struct pm_qos_request_list *igbvf_driver_pm_qos_req;
static const char igbvf_driver_string[] =
"Intel(R) Virtual Function Network Driver";
static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@ -2901,7 +2902,7 @@ static int __init igbvf_init_module(void)
printk(KERN_INFO "%s\n", igbvf_copyright);
ret = pci_register_driver(&igbvf_driver);
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
+ igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
return ret;
@@ -2917,7 +2918,8 @@ module_init(igbvf_init_module);
static void __exit igbvf_exit_module(void)
{
pci_unregister_driver(&igbvf_driver);
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
+ pm_qos_remove_request(igbvf_driver_pm_qos_req);
+ igbvf_driver_pm_qos_req = NULL;
}
module_exit(igbvf_exit_module);
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 2088ac0..7040e3b 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -174,6 +174,8 @@ that only one external action is invoked at a time.
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
+struct pm_qos_request_list *ipw2100_pm_qos_req;
+
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
#define IPW2100_RX_DEBUG /* Reception debugging */
@@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
/* the ipw2100 hardware really doesn't want power management delays
* longer than 175usec
*/
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
+ pm_qos_update_request(ipw2100_pm_qos_req, 175);
/* If the interrupt is enabled, turn it off... */
spin_lock_irqsave(&priv->low_lock, flags);
@@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
ipw2100_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->low_lock, flags);
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
/* We have to signal any supplicant if we are disassociating */
if (associated)
@@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
if (ret)
goto out;
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
+ ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
#ifdef CONFIG_IPW2100_DEBUG
ipw2100_debug_level = debug;
@@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
&driver_attr_debug_level);
#endif
pci_unregister_driver(&ipw2100_pci_driver);
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
+ pm_qos_remove_request(ipw2100_pm_qos_req);
}
module_init(ipw2100_init);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 40d4c20..5dd6d8c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -31,6 +31,7 @@
#include <linux/if_link.h>
#ifdef __KERNEL__
+#include <linux/pm_qos_params.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/mm.h>
@@ -778,6 +779,9 @@ struct net_device {
* the interface.
*/
char name[IFNAMSIZ];
+
+ struct pm_qos_request_list *pm_qos_req;
+
/* device name hash chain */
struct hlist_node name_hlist;
/* snmp alias */
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index d74f75e..8ba440e 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -14,12 +14,14 @@
#define PM_QOS_NUM_CLASSES 4
#define PM_QOS_DEFAULT_VALUE -1
-int pm_qos_add_requirement(int qos, char *name, s32 value);
-int pm_qos_update_requirement(int qos, char *name, s32 new_value);
-void pm_qos_remove_requirement(int qos, char *name);
+struct pm_qos_request_list;
-int pm_qos_requirement(int qos);
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+ s32 new_value);
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
-int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
-int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
+int pm_qos_request(int pm_qos_class);
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
+int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8b611a5..dd76cde 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -29,6 +29,7 @@
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/bitops.h>
+#include <linux/pm_qos_params.h>
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
#define snd_pcm_chip(pcm) ((pcm)->private_data)
@@ -365,7 +366,7 @@ struct snd_pcm_substream {
int number;
char name[32]; /* substream name */
int stream; /* stream (direction) */
- char latency_id[20]; /* latency identifier */
+ struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
size_t buffer_bytes_max; /* limit ring buffer size */
struct snd_dma_buffer dma_buffer;
unsigned int dma_buf_id;
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 3db49b9..a1aea04 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -2,7 +2,7 @@
* This module exposes the interface to kernel space for specifying
* QoS dependencies. It provides infrastructure for registration of:
*
- * Dependents on a QoS value : register requirements
+ * Dependents on a QoS value : register requests
* Watchers of QoS value : get notified when target QoS value changes
*
* This QoS design is best effort based. Dependents register their QoS needs.
@@ -14,19 +14,21 @@
* timeout: usec <-- currently not used.
* throughput: kbs (kilo byte / sec)
*
- * There are lists of pm_qos_objects each one wrapping requirements, notifiers
+ * There are lists of pm_qos_objects each one wrapping requests, notifiers
*
- * User mode requirements on a QOS parameter register themselves to the
+ * User mode requests on a QOS parameter register themselves to the
* subsystem by opening the device node /dev/... and writing there request to
* the node. As long as the process holds a file handle open to the node the
* client continues to be accounted for. Upon file release the usermode
- * requirement is removed and a new qos target is computed. This way when the
- * requirement that the application has is cleaned up when closes the file
+ * request is removed and a new qos target is computed. This way when the
+ * request that the application has is cleaned up when closes the file
* pointer or exits the pm_qos_object will get an opportunity to clean up.
*
* Mark Gross <mgross@linux.intel.com>
*/
+/*#define DEBUG*/
+
#include <linux/pm_qos_params.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
@@ -42,25 +44,25 @@
#include <linux/uaccess.h>
/*
- * locking rule: all changes to requirements or notifiers lists
+ * locking rule: all changes to requests or notifiers lists
* or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
* held, taken with _irqsave. One lock to rule them all
*/
-struct requirement_list {
+struct pm_qos_request_list {
struct list_head list;
union {
s32 value;
s32 usec;
s32 kbps;
};
- char *name;
+ int pm_qos_class;
};
static s32 max_compare(s32 v1, s32 v2);
static s32 min_compare(s32 v1, s32 v2);
struct pm_qos_object {
- struct requirement_list requirements;
+ struct pm_qos_request_list requests;
struct blocking_notifier_head *notifiers;
struct miscdevice pm_qos_power_miscdev;
char *name;
@@ -72,7 +74,7 @@ struct pm_qos_object {
static struct pm_qos_object null_pm_qos;
static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
static struct pm_qos_object cpu_dma_pm_qos = {
- .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
.notifiers = &cpu_dma_lat_notifier,
.name = "cpu_dma_latency",
.default_value = 2000 * USEC_PER_SEC,
@@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
static struct pm_qos_object network_lat_pm_qos = {
- .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
.notifiers = &network_lat_notifier,
.name = "network_latency",
.default_value = 2000 * USEC_PER_SEC,
@@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
static struct pm_qos_object network_throughput_pm_qos = {
- .requirements =
- {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
.notifiers = &network_throughput_notifier,
.name = "network_throughput",
.default_value = 0,
@@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
}
-static void update_target(int target)
+static void update_target(int pm_qos_class)
{
s32 extreme_value;
- struct requirement_list *node;
+ struct pm_qos_request_list *node;
unsigned long flags;
int call_notifier = 0;
spin_lock_irqsave(&pm_qos_lock, flags);
- extreme_value = pm_qos_array[target]->default_value;
+ extreme_value = pm_qos_array[pm_qos_class]->default_value;
list_for_each_entry(node,
- &pm_qos_array[target]->requirements.list, list) {
- extreme_value = pm_qos_array[target]->comparitor(
+ &pm_qos_array[pm_qos_class]->requests.list, list) {
+ extreme_value = pm_qos_array[pm_qos_class]->comparitor(
extreme_value, node->value);
}
- if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
+ if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
+ extreme_value) {
call_notifier = 1;
- atomic_set(&pm_qos_array[target]->target_value, extreme_value);
- pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
- atomic_read(&pm_qos_array[target]->target_value));
+ atomic_set(&pm_qos_array[pm_qos_class]->target_value,
+ extreme_value);
+ pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
+ atomic_read(&pm_qos_array[pm_qos_class]->target_value));
}
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (call_notifier)
- blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
- (unsigned long) extreme_value, NULL);
+ blocking_notifier_call_chain(
+ pm_qos_array[pm_qos_class]->notifiers,
+ (unsigned long) extreme_value, NULL);
}
static int register_pm_qos_misc(struct pm_qos_object *qos)
@@ -185,125 +189,110 @@ static int find_pm_qos_object_by_minor(int minor)
}
/**
- * pm_qos_requirement - returns current system wide qos expectation
+ * pm_qos_request - returns current system wide qos expectation
* @pm_qos_class: identification of which qos value is requested
*
* This function returns the current target value in an atomic manner.
*/
-int pm_qos_requirement(int pm_qos_class)
+int pm_qos_request(int pm_qos_class)
{
return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
}
-EXPORT_SYMBOL_GPL(pm_qos_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_request);
/**
- * pm_qos_add_requirement - inserts new qos request into the list
+ * pm_qos_add_request - inserts new qos request into the list
* @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
* @value: defines the qos request
*
* This function inserts a new entry in the pm_qos_class list of requested qos
* performance characteristics. It recomputes the aggregate QoS expectations
- * for the pm_qos_class of parameters.
+ * for the pm_qos_class of parameters, and returns the pm_qos_request list
+ * element as a handle for use in updating and removal. Call needs to save
+ * this handle for later use.
*/
-int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
{
- struct requirement_list *dep;
+ struct pm_qos_request_list *dep;
unsigned long flags;
- dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
+ dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
if (dep) {
if (value == PM_QOS_DEFAULT_VALUE)
dep->value = pm_qos_array[pm_qos_class]->default_value;
else
dep->value = value;
- dep->name = kstrdup(name, GFP_KERNEL);
- if (!dep->name)
- goto cleanup;
+ dep->pm_qos_class = pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
list_add(&dep->list,
- &pm_qos_array[pm_qos_class]->requirements.list);
+ &pm_qos_array[pm_qos_class]->requests.list);
spin_unlock_irqrestore(&pm_qos_lock, flags);
update_target(pm_qos_class);
-
- return 0;
}
-cleanup:
- kfree(dep);
- return -ENOMEM;
+ return dep;
}
-EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_add_request);
/**
- * pm_qos_update_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_update_request - modifies an existing qos request
+ * @pm_qos_req : handle to list element holding a pm_qos request to use
* @value: defines the qos request
*
- * Updates an existing qos requirement for the pm_qos_class of parameters along
+ * Updates an existing qos request for the pm_qos_class of parameters along
* with updating the target pm_qos_class value.
*
- * If the named request isn't in the list then no change is made.
+ * Attempts are made to make this code callable on hot code paths.
*/
-int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+ s32 new_value)
{
unsigned long flags;
- struct requirement_list *node;
int pending_update = 0;
+ s32 temp;
spin_lock_irqsave(&pm_qos_lock, flags);
- list_for_each_entry(node,
- &pm_qos_array[pm_qos_class]->requirements.list, list) {
- if (strcmp(node->name, name) == 0) {
- if (new_value == PM_QOS_DEFAULT_VALUE)
- node->value =
- pm_qos_array[pm_qos_class]->default_value;
- else
- node->value = new_value;
- pending_update = 1;
- break;
- }
+ if (new_value == PM_QOS_DEFAULT_VALUE)
+ temp = pm_qos_array[pm_qos_req->pm_qos_class]->default_value;
+ else
+ temp = new_value;
+
+ if (temp != pm_qos_req->value) {
+ pending_update = 1;
+ pm_qos_req->value = temp;
}
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (pending_update)
- update_target(pm_qos_class);
-
- return 0;
+ update_target(pm_qos_req->pm_qos_class);
}
-EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_update_request);
/**
- * pm_qos_remove_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_remove_request - modifies an existing qos request
+ * @pm_qos_req: handle to request list element
*
- * Will remove named qos request from pm_qos_class list of parameters and
- * recompute the current target value for the pm_qos_class.
+ * Will remove pm qos request from the list of requests and
+ * recompute the current target value for the pm_qos_class. Call this
+ * on slow code paths.
*/
-void pm_qos_remove_requirement(int pm_qos_class, char *name)
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
{
unsigned long flags;
- struct requirement_list *node;
- int pending_update = 0;
+ int qos_class;
+
+ if (pm_qos_req == NULL)
+ return;
+ /* silent return to keep pcm code cleaner */
+ qos_class = pm_qos_req->pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
- list_for_each_entry(node,
- &pm_qos_array[pm_qos_class]->requirements.list, list) {
- if (strcmp(node->name, name) == 0) {
- kfree(node->name);
- list_del(&node->list);
- kfree(node);
- pending_update = 1;
- break;
- }
- }
+ list_del(&pm_qos_req->list);
+ kfree(pm_qos_req);
spin_unlock_irqrestore(&pm_qos_lock, flags);
- if (pending_update)
- update_target(pm_qos_class);
+ update_target(qos_class);
}
-EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_remove_request);
/**
* pm_qos_add_notifier - sets notification entry for changes to target value
@@ -313,7 +302,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
* will register the notifier into a notification chain that gets called
* upon changes to the pm_qos_class target value.
*/
- int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
{
int retval;
@@ -343,21 +332,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
}
EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
-#define PID_NAME_LEN 32
-
static int pm_qos_power_open(struct inode *inode, struct file *filp)
{
- int ret;
long pm_qos_class;
- char name[PID_NAME_LEN];
pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
if (pm_qos_class >= 0) {
- filp->private_data = (void *)pm_qos_class;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- ret = pm_qos_add_requirement(pm_qos_class, name,
- PM_QOS_DEFAULT_VALUE);
- if (ret >= 0)
+ filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
+ PM_QOS_DEFAULT_VALUE);
+
+ if (filp->private_data)
return 0;
}
return -EPERM;
@@ -365,32 +349,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
static int pm_qos_power_release(struct inode *inode, struct file *filp)
{
- int pm_qos_class;
- char name[PID_NAME_LEN];
+ struct pm_qos_request_list *req;
- pm_qos_class = (long)filp->private_data;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- pm_qos_remove_requirement(pm_qos_class, name);
+ req = (struct pm_qos_request_list *)filp->private_data;
+ pm_qos_remove_request(req);
return 0;
}
+
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
s32 value;
- int pm_qos_class;
- char name[PID_NAME_LEN];
-
- pm_qos_class = (long)filp->private_data;
- if (count != sizeof(s32))
+ int x;
+ char ascii_value[11];
+ struct pm_qos_request_list *pm_qos_req;
+
+ if (count == sizeof(s32)) {
+ if (copy_from_user(&value, buf, sizeof(s32)))
+ return -EFAULT;
+ } else if (count == 11) { /* len('0x12345678/0') */
+ if (copy_from_user(ascii_value, buf, 11))
+ return -EFAULT;
+ x = sscanf(ascii_value, "%x", &value);
+ if (x != 1)
+ return -EINVAL;
+ pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
+ } else
return -EINVAL;
- if (copy_from_user(&value, buf, sizeof(s32)))
- return -EFAULT;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- pm_qos_update_requirement(pm_qos_class, name, value);
- return sizeof(s32);
+ pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
+ pm_qos_update_request(pm_qos_req, value);
+
+ return count;
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 358226f..3deaac3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -507,7 +507,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
s32 beaconint_us;
if (latency < 0)
- latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
+ latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
beaconint_us = ieee80211_tu_to_usec(
found->vif.bss_conf.beacon_int);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 8bc961f..be52bb8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -510,7 +510,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
bad_latency = time_after(jiffies +
ieee80211_scan_get_channel_time(next_chan),
local->leave_oper_channel_time +
- usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY)));
+ usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
listen_int_exceeded = time_after(jiffies +
ieee80211_scan_get_channel_time(next_chan),
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 0d428d0..cbe815d 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
substream->number = idx;
substream->stream = stream;
sprintf(substream->name, "subdevice #%i", idx);
- snprintf(substream->latency_id, sizeof(substream->latency_id),
- "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
- (stream ? 'c' : 'p'), idx);
substream->buffer_bytes_max = UINT_MAX;
if (prev == NULL)
pstr->substream = substream;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index c22ebb0..1bb0e23 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -481,11 +481,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
snd_pcm_timer_resolution_change(substream);
runtime->status->state = SNDRV_PCM_STATE_SETUP;
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id);
+ if (substream->latency_pm_qos_req) {
+ pm_qos_remove_request(substream->latency_pm_qos_req);
+ substream->latency_pm_qos_req = NULL;
+ }
if ((usecs = period_to_usecs(runtime)) >= 0)
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id, usecs);
+ substream->latency_pm_qos_req = pm_qos_add_request(
+ PM_QOS_CPU_DMA_LATENCY, usecs);
return 0;
_error:
/* hardware might be unuseable from this time,
@@ -540,8 +542,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
if (substream->ops->hw_free)
result = substream->ops->hw_free(substream);
runtime->status->state = SNDRV_PCM_STATE_OPEN;
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id);
+ pm_qos_remove_request(substream->latency_pm_qos_req);
+ substream->latency_pm_qos_req = NULL;
return result;
}
--
1.6.3.3
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH]PM QOS refresh against next-20100430
@ 2010-04-30 21:20 mark gross
2010-04-30 22:13 ` Rafael J. Wysocki
2010-05-03 16:33 ` Jonathan Corbet
0 siblings, 2 replies; 14+ messages in thread
From: mark gross @ 2010-04-30 21:20 UTC (permalink / raw)
To: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel
Cc: linux-pm, lkml
The following is a refresh of the PM_QOS implementation, this patch
updates some documentation input I got from Randy.
This patch changes the string based list management to a handle base
implementation to help with the hot path use of pm-qos, it also renames
much of the API to use "request" as opposed to "requirement" that was
used in the initial implementation. I did this because request more
accurately represents what it actually does.
Also, I added a string based ABI for users wanting to use a string
interface. So if the user writes 0xDDDDDDDD formatted hex it will be
accepted by the interface. (someone asked me for it and I don't think
it hurts anything.)
I really would like to get this refresh taken care of. Its been taking
me too long to close this. please review or include it in next.
Thanks!
--mgross
Ooops! forgot the signed off by line!
Signed-off-by: mark gross <mgross@linux.intel.com>
>From c45d8d86f89ac55fbb9a499fbc754e35258bf818 Mon Sep 17 00:00:00 2001
From: mgross <mark.gross@gmail.com>
Date: Sat, 13 Mar 2010 08:18:36 -0800
Subject: [PATCH 1/2] PM_QOS to use handle based list implementation and exported function name changes to be more descriptive of what is actually happening.
---
Documentation/power/pm_qos_interface.txt | 48 ++++---
drivers/acpi/processor_idle.c | 2 +-
drivers/cpuidle/governors/ladder.c | 2 +-
| 2 +-
drivers/net/e1000e/netdev.c | 22 ++--
drivers/net/igbvf/netdev.c | 6 +-
drivers/net/wireless/ipw2x00/ipw2100.c | 11 +-
include/linux/netdevice.h | 4 +
include/linux/pm_qos_params.h | 14 +-
include/sound/pcm.h | 3 +-
kernel/pm_qos_params.c | 214 ++++++++++++++---------------
net/mac80211/mlme.c | 2 +-
net/mac80211/scan.c | 2 +-
sound/core/pcm.c | 3 -
sound/core/pcm_native.c | 14 +-
15 files changed, 177 insertions(+), 172 deletions(-)
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index c40866e..bfed898 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -18,44 +18,46 @@ and pm_qos_params.h. This is done because having the available parameters
being runtime configurable or changeable from a driver was seen as too easy to
abuse.
-For each parameter a list of performance requirements is maintained along with
+For each parameter a list of performance requests is maintained along with
an aggregated target value. The aggregated target value is updated with
-changes to the requirement list or elements of the list. Typically the
-aggregated target value is simply the max or min of the requirement values held
+changes to the request list or elements of the list. Typically the
+aggregated target value is simply the max or min of the request values held
in the parameter list elements.
From kernel mode the use of this interface is simple:
-pm_qos_add_requirement(param_id, name, target_value):
-Will insert a named element in the list for that identified PM_QOS parameter
-with the target value. Upon change to this list the new target is recomputed
-and any registered notifiers are called only if the target value is now
-different.
-pm_qos_update_requirement(param_id, name, new_target_value):
-Will search the list identified by the param_id for the named list element and
-then update its target value, calling the notification tree if the aggregated
-target is changed. with that name is already registered.
+handle = pm_qos_add_request(param_class, target_value):
+Will insert an element into the list for that identified PM_QOS class with the
+target value. Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of pm_qos need to save the returned handle.
-pm_qos_remove_requirement(param_id, name):
-Will search the identified list for the named element and remove it, after
-removal it will update the aggregate target and call the notification tree if
-the target was changed as a result of removing the named requirement.
+void pm_qos_update_request(handle, new_target_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification tree if the
+target is changed.
+
+void pm_qos_remove_request(handle):
+Will remove the element. After removal it will update the aggregate target and
+call the notification tree if the target was changed as a result of removing
+the request.
From user mode:
-Only processes can register a pm_qos requirement. To provide for automatic
-cleanup for process the interface requires the process to register its
-parameter requirements in the following way:
+Only processes can register a pm_qos request. To provide for automatic
+cleanup of a process, the interface requires the process to register its
+parameter requests in the following way:
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]
As long as the device node is held open that process has a registered
-requirement on the parameter. The name of the requirement is "process_<PID>"
-derived from the current->pid from within the open system call.
+request on the parameter.
-To change the requested target value the process needs to write a s32 value to
-the open device node. This translates to a pm_qos_update_requirement call.
+To change the requested target value the process needs to write an s32 value to
+the open device node. Alternatively the user mode program could write a hex
+string for the value using 10 char long format e.g. "0x12345678". This
+translates to a pm_qos_update_request call.
To remove the user mode request for a target value simply close the device
node.
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5939e7f..c3817e1 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
"max_cstate: C%d\n"
"maximum allowed latency: %d usec\n",
pr->power.state ? pr->power.state - pr->power.states : 0,
- max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
+ max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
seq_puts(seq, "states:\n");
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 1c1ceb4..12c9890 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
struct ladder_device_state *last_state;
int last_residency, last_idx = ldev->last_state_idx;
- int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
/* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0)) {
--git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1aea715..61ca939 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -183,7 +183,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
static int menu_select(struct cpuidle_device *dev)
{
struct menu_device *data = &__get_cpu_var(menu_devices);
- int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
int i;
int multiplier;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 904bd6b..7550879 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2882,12 +2882,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
* excessive C-state transition latencies result in
* dropped transactions.
*/
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name, 55);
+ pm_qos_update_request(
+ adapter->netdev->pm_qos_req, 55);
} else {
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name,
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(
+ adapter->netdev->pm_qos_req,
+ PM_QOS_DEFAULT_VALUE);
}
}
@@ -3181,8 +3181,8 @@ int e1000e_up(struct e1000_adapter *adapter)
/* DMA latency requirement to workaround early-receive/jumbo issue */
if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name,
+ adapter->netdev->pm_qos_req =
+ pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
/* hardware has been reset, we need to reload some things */
@@ -3244,9 +3244,11 @@ void e1000e_down(struct e1000_adapter *adapter)
e1000_clean_tx_ring(adapter);
e1000_clean_rx_ring(adapter);
- if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name);
+ if (adapter->flags & FLAG_HAS_ERT) {
+ pm_qos_remove_request(
+ adapter->netdev->pm_qos_req);
+ adapter->netdev->pm_qos_req = NULL;
+ }
/*
* TODO: for power management, we could drop the link and
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 7012e3d..5e2b2a8 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -48,6 +48,7 @@
#define DRV_VERSION "1.0.0-k0"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
+struct pm_qos_request_list *igbvf_driver_pm_qos_req;
static const char igbvf_driver_string[] =
"Intel(R) Virtual Function Network Driver";
static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@ -2901,7 +2902,7 @@ static int __init igbvf_init_module(void)
printk(KERN_INFO "%s\n", igbvf_copyright);
ret = pci_register_driver(&igbvf_driver);
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
+ igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
return ret;
@@ -2917,7 +2918,8 @@ module_init(igbvf_init_module);
static void __exit igbvf_exit_module(void)
{
pci_unregister_driver(&igbvf_driver);
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
+ pm_qos_remove_request(igbvf_driver_pm_qos_req);
+ igbvf_driver_pm_qos_req = NULL;
}
module_exit(igbvf_exit_module);
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 2088ac0..7040e3b 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -174,6 +174,8 @@ that only one external action is invoked at a time.
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
+struct pm_qos_request_list *ipw2100_pm_qos_req;
+
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
#define IPW2100_RX_DEBUG /* Reception debugging */
@@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
/* the ipw2100 hardware really doesn't want power management delays
* longer than 175usec
*/
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
+ pm_qos_update_request(ipw2100_pm_qos_req, 175);
/* If the interrupt is enabled, turn it off... */
spin_lock_irqsave(&priv->low_lock, flags);
@@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
ipw2100_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->low_lock, flags);
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
/* We have to signal any supplicant if we are disassociating */
if (associated)
@@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
if (ret)
goto out;
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
+ ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
#ifdef CONFIG_IPW2100_DEBUG
ipw2100_debug_level = debug;
@@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
&driver_attr_debug_level);
#endif
pci_unregister_driver(&ipw2100_pci_driver);
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
+ pm_qos_remove_request(ipw2100_pm_qos_req);
}
module_init(ipw2100_init);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 40d4c20..5dd6d8c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -31,6 +31,7 @@
#include <linux/if_link.h>
#ifdef __KERNEL__
+#include <linux/pm_qos_params.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/mm.h>
@@ -778,6 +779,9 @@ struct net_device {
* the interface.
*/
char name[IFNAMSIZ];
+
+ struct pm_qos_request_list *pm_qos_req;
+
/* device name hash chain */
struct hlist_node name_hlist;
/* snmp alias */
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index d74f75e..8ba440e 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -14,12 +14,14 @@
#define PM_QOS_NUM_CLASSES 4
#define PM_QOS_DEFAULT_VALUE -1
-int pm_qos_add_requirement(int qos, char *name, s32 value);
-int pm_qos_update_requirement(int qos, char *name, s32 new_value);
-void pm_qos_remove_requirement(int qos, char *name);
+struct pm_qos_request_list;
-int pm_qos_requirement(int qos);
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+ s32 new_value);
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
-int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
-int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
+int pm_qos_request(int pm_qos_class);
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
+int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8b611a5..dd76cde 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -29,6 +29,7 @@
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/bitops.h>
+#include <linux/pm_qos_params.h>
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
#define snd_pcm_chip(pcm) ((pcm)->private_data)
@@ -365,7 +366,7 @@ struct snd_pcm_substream {
int number;
char name[32]; /* substream name */
int stream; /* stream (direction) */
- char latency_id[20]; /* latency identifier */
+ struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
size_t buffer_bytes_max; /* limit ring buffer size */
struct snd_dma_buffer dma_buffer;
unsigned int dma_buf_id;
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 3db49b9..a1aea04 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -2,7 +2,7 @@
* This module exposes the interface to kernel space for specifying
* QoS dependencies. It provides infrastructure for registration of:
*
- * Dependents on a QoS value : register requirements
+ * Dependents on a QoS value : register requests
* Watchers of QoS value : get notified when target QoS value changes
*
* This QoS design is best effort based. Dependents register their QoS needs.
@@ -14,19 +14,21 @@
* timeout: usec <-- currently not used.
* throughput: kbs (kilo byte / sec)
*
- * There are lists of pm_qos_objects each one wrapping requirements, notifiers
+ * There are lists of pm_qos_objects each one wrapping requests, notifiers
*
- * User mode requirements on a QOS parameter register themselves to the
+ * User mode requests on a QOS parameter register themselves to the
* subsystem by opening the device node /dev/... and writing there request to
* the node. As long as the process holds a file handle open to the node the
* client continues to be accounted for. Upon file release the usermode
- * requirement is removed and a new qos target is computed. This way when the
- * requirement that the application has is cleaned up when closes the file
+ * request is removed and a new qos target is computed. This way when the
+ * request that the application has is cleaned up when closes the file
* pointer or exits the pm_qos_object will get an opportunity to clean up.
*
* Mark Gross <mgross@linux.intel.com>
*/
+/*#define DEBUG*/
+
#include <linux/pm_qos_params.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
@@ -42,25 +44,25 @@
#include <linux/uaccess.h>
/*
- * locking rule: all changes to requirements or notifiers lists
+ * locking rule: all changes to requests or notifiers lists
* or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
* held, taken with _irqsave. One lock to rule them all
*/
-struct requirement_list {
+struct pm_qos_request_list {
struct list_head list;
union {
s32 value;
s32 usec;
s32 kbps;
};
- char *name;
+ int pm_qos_class;
};
static s32 max_compare(s32 v1, s32 v2);
static s32 min_compare(s32 v1, s32 v2);
struct pm_qos_object {
- struct requirement_list requirements;
+ struct pm_qos_request_list requests;
struct blocking_notifier_head *notifiers;
struct miscdevice pm_qos_power_miscdev;
char *name;
@@ -72,7 +74,7 @@ struct pm_qos_object {
static struct pm_qos_object null_pm_qos;
static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
static struct pm_qos_object cpu_dma_pm_qos = {
- .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
.notifiers = &cpu_dma_lat_notifier,
.name = "cpu_dma_latency",
.default_value = 2000 * USEC_PER_SEC,
@@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
static struct pm_qos_object network_lat_pm_qos = {
- .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
.notifiers = &network_lat_notifier,
.name = "network_latency",
.default_value = 2000 * USEC_PER_SEC,
@@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
static struct pm_qos_object network_throughput_pm_qos = {
- .requirements =
- {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
.notifiers = &network_throughput_notifier,
.name = "network_throughput",
.default_value = 0,
@@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
}
-static void update_target(int target)
+static void update_target(int pm_qos_class)
{
s32 extreme_value;
- struct requirement_list *node;
+ struct pm_qos_request_list *node;
unsigned long flags;
int call_notifier = 0;
spin_lock_irqsave(&pm_qos_lock, flags);
- extreme_value = pm_qos_array[target]->default_value;
+ extreme_value = pm_qos_array[pm_qos_class]->default_value;
list_for_each_entry(node,
- &pm_qos_array[target]->requirements.list, list) {
- extreme_value = pm_qos_array[target]->comparitor(
+ &pm_qos_array[pm_qos_class]->requests.list, list) {
+ extreme_value = pm_qos_array[pm_qos_class]->comparitor(
extreme_value, node->value);
}
- if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
+ if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
+ extreme_value) {
call_notifier = 1;
- atomic_set(&pm_qos_array[target]->target_value, extreme_value);
- pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
- atomic_read(&pm_qos_array[target]->target_value));
+ atomic_set(&pm_qos_array[pm_qos_class]->target_value,
+ extreme_value);
+ pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
+ atomic_read(&pm_qos_array[pm_qos_class]->target_value));
}
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (call_notifier)
- blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
- (unsigned long) extreme_value, NULL);
+ blocking_notifier_call_chain(
+ pm_qos_array[pm_qos_class]->notifiers,
+ (unsigned long) extreme_value, NULL);
}
static int register_pm_qos_misc(struct pm_qos_object *qos)
@@ -185,125 +189,110 @@ static int find_pm_qos_object_by_minor(int minor)
}
/**
- * pm_qos_requirement - returns current system wide qos expectation
+ * pm_qos_request - returns current system wide qos expectation
* @pm_qos_class: identification of which qos value is requested
*
* This function returns the current target value in an atomic manner.
*/
-int pm_qos_requirement(int pm_qos_class)
+int pm_qos_request(int pm_qos_class)
{
return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
}
-EXPORT_SYMBOL_GPL(pm_qos_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_request);
/**
- * pm_qos_add_requirement - inserts new qos request into the list
+ * pm_qos_add_request - inserts new qos request into the list
* @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
* @value: defines the qos request
*
* This function inserts a new entry in the pm_qos_class list of requested qos
* performance characteristics. It recomputes the aggregate QoS expectations
- * for the pm_qos_class of parameters.
+ * for the pm_qos_class of parameters, and returns the pm_qos_request list
+ * element as a handle for use in updating and removal. Call needs to save
+ * this handle for later use.
*/
-int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
{
- struct requirement_list *dep;
+ struct pm_qos_request_list *dep;
unsigned long flags;
- dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
+ dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
if (dep) {
if (value == PM_QOS_DEFAULT_VALUE)
dep->value = pm_qos_array[pm_qos_class]->default_value;
else
dep->value = value;
- dep->name = kstrdup(name, GFP_KERNEL);
- if (!dep->name)
- goto cleanup;
+ dep->pm_qos_class = pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
list_add(&dep->list,
- &pm_qos_array[pm_qos_class]->requirements.list);
+ &pm_qos_array[pm_qos_class]->requests.list);
spin_unlock_irqrestore(&pm_qos_lock, flags);
update_target(pm_qos_class);
-
- return 0;
}
-cleanup:
- kfree(dep);
- return -ENOMEM;
+ return dep;
}
-EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_add_request);
/**
- * pm_qos_update_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_update_request - modifies an existing qos request
+ * @pm_qos_req : handle to list element holding a pm_qos request to use
* @value: defines the qos request
*
- * Updates an existing qos requirement for the pm_qos_class of parameters along
+ * Updates an existing qos request for the pm_qos_class of parameters along
* with updating the target pm_qos_class value.
*
- * If the named request isn't in the list then no change is made.
+ * Attempts are made to make this code callable on hot code paths.
*/
-int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+ s32 new_value)
{
unsigned long flags;
- struct requirement_list *node;
int pending_update = 0;
+ s32 temp;
spin_lock_irqsave(&pm_qos_lock, flags);
- list_for_each_entry(node,
- &pm_qos_array[pm_qos_class]->requirements.list, list) {
- if (strcmp(node->name, name) == 0) {
- if (new_value == PM_QOS_DEFAULT_VALUE)
- node->value =
- pm_qos_array[pm_qos_class]->default_value;
- else
- node->value = new_value;
- pending_update = 1;
- break;
- }
+ if (new_value == PM_QOS_DEFAULT_VALUE)
+ temp = pm_qos_array[pm_qos_req->pm_qos_class]->default_value;
+ else
+ temp = new_value;
+
+ if (temp != pm_qos_req->value) {
+ pending_update = 1;
+ pm_qos_req->value = temp;
}
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (pending_update)
- update_target(pm_qos_class);
-
- return 0;
+ update_target(pm_qos_req->pm_qos_class);
}
-EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_update_request);
/**
- * pm_qos_remove_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_remove_request - modifies an existing qos request
+ * @pm_qos_req: handle to request list element
*
- * Will remove named qos request from pm_qos_class list of parameters and
- * recompute the current target value for the pm_qos_class.
+ * Will remove pm qos request from the list of requests and
+ * recompute the current target value for the pm_qos_class. Call this
+ * on slow code paths.
*/
-void pm_qos_remove_requirement(int pm_qos_class, char *name)
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
{
unsigned long flags;
- struct requirement_list *node;
- int pending_update = 0;
+ int qos_class;
+
+ if (pm_qos_req == NULL)
+ return;
+ /* silent return to keep pcm code cleaner */
+ qos_class = pm_qos_req->pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
- list_for_each_entry(node,
- &pm_qos_array[pm_qos_class]->requirements.list, list) {
- if (strcmp(node->name, name) == 0) {
- kfree(node->name);
- list_del(&node->list);
- kfree(node);
- pending_update = 1;
- break;
- }
- }
+ list_del(&pm_qos_req->list);
+ kfree(pm_qos_req);
spin_unlock_irqrestore(&pm_qos_lock, flags);
- if (pending_update)
- update_target(pm_qos_class);
+ update_target(qos_class);
}
-EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_remove_request);
/**
* pm_qos_add_notifier - sets notification entry for changes to target value
@@ -313,7 +302,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
* will register the notifier into a notification chain that gets called
* upon changes to the pm_qos_class target value.
*/
- int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
{
int retval;
@@ -343,21 +332,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
}
EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
-#define PID_NAME_LEN 32
-
static int pm_qos_power_open(struct inode *inode, struct file *filp)
{
- int ret;
long pm_qos_class;
- char name[PID_NAME_LEN];
pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
if (pm_qos_class >= 0) {
- filp->private_data = (void *)pm_qos_class;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- ret = pm_qos_add_requirement(pm_qos_class, name,
- PM_QOS_DEFAULT_VALUE);
- if (ret >= 0)
+ filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
+ PM_QOS_DEFAULT_VALUE);
+
+ if (filp->private_data)
return 0;
}
return -EPERM;
@@ -365,32 +349,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
static int pm_qos_power_release(struct inode *inode, struct file *filp)
{
- int pm_qos_class;
- char name[PID_NAME_LEN];
+ struct pm_qos_request_list *req;
- pm_qos_class = (long)filp->private_data;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- pm_qos_remove_requirement(pm_qos_class, name);
+ req = (struct pm_qos_request_list *)filp->private_data;
+ pm_qos_remove_request(req);
return 0;
}
+
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
s32 value;
- int pm_qos_class;
- char name[PID_NAME_LEN];
-
- pm_qos_class = (long)filp->private_data;
- if (count != sizeof(s32))
+ int x;
+ char ascii_value[11];
+ struct pm_qos_request_list *pm_qos_req;
+
+ if (count == sizeof(s32)) {
+ if (copy_from_user(&value, buf, sizeof(s32)))
+ return -EFAULT;
+ } else if (count == 11) { /* len('0x12345678/0') */
+ if (copy_from_user(ascii_value, buf, 11))
+ return -EFAULT;
+ x = sscanf(ascii_value, "%x", &value);
+ if (x != 1)
+ return -EINVAL;
+ pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
+ } else
return -EINVAL;
- if (copy_from_user(&value, buf, sizeof(s32)))
- return -EFAULT;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- pm_qos_update_requirement(pm_qos_class, name, value);
- return sizeof(s32);
+ pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
+ pm_qos_update_request(pm_qos_req, value);
+
+ return count;
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 358226f..3deaac3 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -507,7 +507,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
s32 beaconint_us;
if (latency < 0)
- latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
+ latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
beaconint_us = ieee80211_tu_to_usec(
found->vif.bss_conf.beacon_int);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 8bc961f..be52bb8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -510,7 +510,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
bad_latency = time_after(jiffies +
ieee80211_scan_get_channel_time(next_chan),
local->leave_oper_channel_time +
- usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY)));
+ usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
listen_int_exceeded = time_after(jiffies +
ieee80211_scan_get_channel_time(next_chan),
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 0d428d0..cbe815d 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
substream->number = idx;
substream->stream = stream;
sprintf(substream->name, "subdevice #%i", idx);
- snprintf(substream->latency_id, sizeof(substream->latency_id),
- "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
- (stream ? 'c' : 'p'), idx);
substream->buffer_bytes_max = UINT_MAX;
if (prev == NULL)
pstr->substream = substream;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index c22ebb0..1bb0e23 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -481,11 +481,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
snd_pcm_timer_resolution_change(substream);
runtime->status->state = SNDRV_PCM_STATE_SETUP;
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id);
+ if (substream->latency_pm_qos_req) {
+ pm_qos_remove_request(substream->latency_pm_qos_req);
+ substream->latency_pm_qos_req = NULL;
+ }
if ((usecs = period_to_usecs(runtime)) >= 0)
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id, usecs);
+ substream->latency_pm_qos_req = pm_qos_add_request(
+ PM_QOS_CPU_DMA_LATENCY, usecs);
return 0;
_error:
/* hardware might be unuseable from this time,
@@ -540,8 +542,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
if (substream->ops->hw_free)
result = substream->ops->hw_free(substream);
runtime->status->state = SNDRV_PCM_STATE_OPEN;
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id);
+ pm_qos_remove_request(substream->latency_pm_qos_req);
+ substream->latency_pm_qos_req = NULL;
return result;
}
--
1.6.3.3
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-04-30 21:20 mark gross
@ 2010-04-30 22:13 ` Rafael J. Wysocki
2010-04-30 23:05 ` mark gross
2010-05-03 16:33 ` Jonathan Corbet
1 sibling, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki @ 2010-04-30 22:13 UTC (permalink / raw)
To: mgross
Cc: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml, NetDev, Johannes Berg,
ACPI Devel Maling List, Len Brown, John W. Linville
On Friday 30 April 2010, mark gross wrote:
> The following is a refresh of the PM_QOS implementation, this patch
> updates some documentation input I got from Randy.
>
> This patch changes the string based list management to a handle base
> implementation to help with the hot path use of pm-qos, it also renames
> much of the API to use "request" as opposed to "requirement" that was
> used in the initial implementation. I did this because request more
> accurately represents what it actually does.
>
> Also, I added a string based ABI for users wanting to use a string
> interface. So if the user writes 0xDDDDDDDD formatted hex it will be
> accepted by the interface. (someone asked me for it and I don't think
> it hurts anything.)
>
> I really would like to get this refresh taken care of. Its been taking
> me too long to close this. please review or include it in next.
>
> Thanks!
Well, I'd take it to suspend-2.6/linux-next, but first, it touches
subsystems whose maintainers were not in the Cc list, like the network
drivers, wireless and ACPI. The changes are trivial, so I hope they don't
mind.
Second, my tree is based on the Linus' tree rather than linux-next and
the change in net/mac80211/scan.c doesn't seem to match that. Please tell me
what I'm supposed to do about that.
Thanks,
Rafael
> Ooops! forgot the signed off by line!
>
> Signed-off-by: mark gross <mgross@linux.intel.com>
>
> From c45d8d86f89ac55fbb9a499fbc754e35258bf818 Mon Sep 17 00:00:00 2001
> From: mgross <mark.gross@gmail.com>
> Date: Sat, 13 Mar 2010 08:18:36 -0800
> Subject: [PATCH 1/2] PM_QOS to use handle based list implementation and exported function name changes to be more descriptive of what is actually happening.
>
> ---
> Documentation/power/pm_qos_interface.txt | 48 ++++---
> drivers/acpi/processor_idle.c | 2 +-
> drivers/cpuidle/governors/ladder.c | 2 +-
> drivers/cpuidle/governors/menu.c | 2 +-
> drivers/net/e1000e/netdev.c | 22 ++--
> drivers/net/igbvf/netdev.c | 6 +-
> drivers/net/wireless/ipw2x00/ipw2100.c | 11 +-
> include/linux/netdevice.h | 4 +
> include/linux/pm_qos_params.h | 14 +-
> include/sound/pcm.h | 3 +-
> kernel/pm_qos_params.c | 214 ++++++++++++++---------------
> net/mac80211/mlme.c | 2 +-
> net/mac80211/scan.c | 2 +-
> sound/core/pcm.c | 3 -
> sound/core/pcm_native.c | 14 +-
> 15 files changed, 177 insertions(+), 172 deletions(-)
>
> diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
> index c40866e..bfed898 100644
> --- a/Documentation/power/pm_qos_interface.txt
> +++ b/Documentation/power/pm_qos_interface.txt
> @@ -18,44 +18,46 @@ and pm_qos_params.h. This is done because having the available parameters
> being runtime configurable or changeable from a driver was seen as too easy to
> abuse.
>
> -For each parameter a list of performance requirements is maintained along with
> +For each parameter a list of performance requests is maintained along with
> an aggregated target value. The aggregated target value is updated with
> -changes to the requirement list or elements of the list. Typically the
> -aggregated target value is simply the max or min of the requirement values held
> +changes to the request list or elements of the list. Typically the
> +aggregated target value is simply the max or min of the request values held
> in the parameter list elements.
>
> From kernel mode the use of this interface is simple:
> -pm_qos_add_requirement(param_id, name, target_value):
> -Will insert a named element in the list for that identified PM_QOS parameter
> -with the target value. Upon change to this list the new target is recomputed
> -and any registered notifiers are called only if the target value is now
> -different.
>
> -pm_qos_update_requirement(param_id, name, new_target_value):
> -Will search the list identified by the param_id for the named list element and
> -then update its target value, calling the notification tree if the aggregated
> -target is changed. with that name is already registered.
> +handle = pm_qos_add_request(param_class, target_value):
> +Will insert an element into the list for that identified PM_QOS class with the
> +target value. Upon change to this list the new target is recomputed and any
> +registered notifiers are called only if the target value is now different.
> +Clients of pm_qos need to save the returned handle.
>
> -pm_qos_remove_requirement(param_id, name):
> -Will search the identified list for the named element and remove it, after
> -removal it will update the aggregate target and call the notification tree if
> -the target was changed as a result of removing the named requirement.
> +void pm_qos_update_request(handle, new_target_value):
> +Will update the list element pointed to by the handle with the new target value
> +and recompute the new aggregated target, calling the notification tree if the
> +target is changed.
> +
> +void pm_qos_remove_request(handle):
> +Will remove the element. After removal it will update the aggregate target and
> +call the notification tree if the target was changed as a result of removing
> +the request.
>
>
> From user mode:
> -Only processes can register a pm_qos requirement. To provide for automatic
> -cleanup for process the interface requires the process to register its
> -parameter requirements in the following way:
> +Only processes can register a pm_qos request. To provide for automatic
> +cleanup of a process, the interface requires the process to register its
> +parameter requests in the following way:
>
> 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]
>
> As long as the device node is held open that process has a registered
> -requirement on the parameter. The name of the requirement is "process_<PID>"
> -derived from the current->pid from within the open system call.
> +request on the parameter.
>
> -To change the requested target value the process needs to write a s32 value to
> -the open device node. This translates to a pm_qos_update_requirement call.
> +To change the requested target value the process needs to write an s32 value to
> +the open device node. Alternatively the user mode program could write a hex
> +string for the value using 10 char long format e.g. "0x12345678". This
> +translates to a pm_qos_update_request call.
>
> To remove the user mode request for a target value simply close the device
> node.
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index 5939e7f..c3817e1 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
> "max_cstate: C%d\n"
> "maximum allowed latency: %d usec\n",
> pr->power.state ? pr->power.state - pr->power.states : 0,
> - max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
> + max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
>
> seq_puts(seq, "states:\n");
>
> diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
> index 1c1ceb4..12c9890 100644
> --- a/drivers/cpuidle/governors/ladder.c
> +++ b/drivers/cpuidle/governors/ladder.c
> @@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
> struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
> struct ladder_device_state *last_state;
> int last_residency, last_idx = ldev->last_state_idx;
> - int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
> + int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
>
> /* Special case when user has set very strict latency requirement */
> if (unlikely(latency_req == 0)) {
> diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
> index 1aea715..61ca939 100644
> --- a/drivers/cpuidle/governors/menu.c
> +++ b/drivers/cpuidle/governors/menu.c
> @@ -183,7 +183,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
> static int menu_select(struct cpuidle_device *dev)
> {
> struct menu_device *data = &__get_cpu_var(menu_devices);
> - int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
> + int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
> int i;
> int multiplier;
>
> diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
> index 904bd6b..7550879 100644
> --- a/drivers/net/e1000e/netdev.c
> +++ b/drivers/net/e1000e/netdev.c
> @@ -2882,12 +2882,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
> * excessive C-state transition latencies result in
> * dropped transactions.
> */
> - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
> - adapter->netdev->name, 55);
> + pm_qos_update_request(
> + adapter->netdev->pm_qos_req, 55);
> } else {
> - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
> - adapter->netdev->name,
> - PM_QOS_DEFAULT_VALUE);
> + pm_qos_update_request(
> + adapter->netdev->pm_qos_req,
> + PM_QOS_DEFAULT_VALUE);
> }
> }
>
> @@ -3181,8 +3181,8 @@ int e1000e_up(struct e1000_adapter *adapter)
>
> /* DMA latency requirement to workaround early-receive/jumbo issue */
> if (adapter->flags & FLAG_HAS_ERT)
> - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
> - adapter->netdev->name,
> + adapter->netdev->pm_qos_req =
> + pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
> PM_QOS_DEFAULT_VALUE);
>
> /* hardware has been reset, we need to reload some things */
> @@ -3244,9 +3244,11 @@ void e1000e_down(struct e1000_adapter *adapter)
> e1000_clean_tx_ring(adapter);
> e1000_clean_rx_ring(adapter);
>
> - if (adapter->flags & FLAG_HAS_ERT)
> - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> - adapter->netdev->name);
> + if (adapter->flags & FLAG_HAS_ERT) {
> + pm_qos_remove_request(
> + adapter->netdev->pm_qos_req);
> + adapter->netdev->pm_qos_req = NULL;
> + }
>
> /*
> * TODO: for power management, we could drop the link and
> diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
> index 7012e3d..5e2b2a8 100644
> --- a/drivers/net/igbvf/netdev.c
> +++ b/drivers/net/igbvf/netdev.c
> @@ -48,6 +48,7 @@
> #define DRV_VERSION "1.0.0-k0"
> char igbvf_driver_name[] = "igbvf";
> const char igbvf_driver_version[] = DRV_VERSION;
> +struct pm_qos_request_list *igbvf_driver_pm_qos_req;
> static const char igbvf_driver_string[] =
> "Intel(R) Virtual Function Network Driver";
> static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
> @@ -2901,7 +2902,7 @@ static int __init igbvf_init_module(void)
> printk(KERN_INFO "%s\n", igbvf_copyright);
>
> ret = pci_register_driver(&igbvf_driver);
> - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
> + igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
> PM_QOS_DEFAULT_VALUE);
>
> return ret;
> @@ -2917,7 +2918,8 @@ module_init(igbvf_init_module);
> static void __exit igbvf_exit_module(void)
> {
> pci_unregister_driver(&igbvf_driver);
> - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
> + pm_qos_remove_request(igbvf_driver_pm_qos_req);
> + igbvf_driver_pm_qos_req = NULL;
> }
> module_exit(igbvf_exit_module);
>
> diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
> index 2088ac0..7040e3b 100644
> --- a/drivers/net/wireless/ipw2x00/ipw2100.c
> +++ b/drivers/net/wireless/ipw2x00/ipw2100.c
> @@ -174,6 +174,8 @@ that only one external action is invoked at a time.
> #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
> #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
>
> +struct pm_qos_request_list *ipw2100_pm_qos_req;
> +
> /* Debugging stuff */
> #ifdef CONFIG_IPW2100_DEBUG
> #define IPW2100_RX_DEBUG /* Reception debugging */
> @@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
> /* the ipw2100 hardware really doesn't want power management delays
> * longer than 175usec
> */
> - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
> + pm_qos_update_request(ipw2100_pm_qos_req, 175);
>
> /* If the interrupt is enabled, turn it off... */
> spin_lock_irqsave(&priv->low_lock, flags);
> @@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
> ipw2100_disable_interrupts(priv);
> spin_unlock_irqrestore(&priv->low_lock, flags);
>
> - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
> - PM_QOS_DEFAULT_VALUE);
> + pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
>
> /* We have to signal any supplicant if we are disassociating */
> if (associated)
> @@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
> if (ret)
> goto out;
>
> - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
> + ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
> PM_QOS_DEFAULT_VALUE);
> #ifdef CONFIG_IPW2100_DEBUG
> ipw2100_debug_level = debug;
> @@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
> &driver_attr_debug_level);
> #endif
> pci_unregister_driver(&ipw2100_pci_driver);
> - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
> + pm_qos_remove_request(ipw2100_pm_qos_req);
> }
>
> module_init(ipw2100_init);
> diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> index 40d4c20..5dd6d8c 100644
> --- a/include/linux/netdevice.h
> +++ b/include/linux/netdevice.h
> @@ -31,6 +31,7 @@
> #include <linux/if_link.h>
>
> #ifdef __KERNEL__
> +#include <linux/pm_qos_params.h>
> #include <linux/timer.h>
> #include <linux/delay.h>
> #include <linux/mm.h>
> @@ -778,6 +779,9 @@ struct net_device {
> * the interface.
> */
> char name[IFNAMSIZ];
> +
> + struct pm_qos_request_list *pm_qos_req;
> +
> /* device name hash chain */
> struct hlist_node name_hlist;
> /* snmp alias */
> diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
> index d74f75e..8ba440e 100644
> --- a/include/linux/pm_qos_params.h
> +++ b/include/linux/pm_qos_params.h
> @@ -14,12 +14,14 @@
> #define PM_QOS_NUM_CLASSES 4
> #define PM_QOS_DEFAULT_VALUE -1
>
> -int pm_qos_add_requirement(int qos, char *name, s32 value);
> -int pm_qos_update_requirement(int qos, char *name, s32 new_value);
> -void pm_qos_remove_requirement(int qos, char *name);
> +struct pm_qos_request_list;
>
> -int pm_qos_requirement(int qos);
> +struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
> +void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
> + s32 new_value);
> +void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
>
> -int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
> -int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
> +int pm_qos_request(int pm_qos_class);
> +int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
> +int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
>
> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index 8b611a5..dd76cde 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -29,6 +29,7 @@
> #include <linux/poll.h>
> #include <linux/mm.h>
> #include <linux/bitops.h>
> +#include <linux/pm_qos_params.h>
>
> #define snd_pcm_substream_chip(substream) ((substream)->private_data)
> #define snd_pcm_chip(pcm) ((pcm)->private_data)
> @@ -365,7 +366,7 @@ struct snd_pcm_substream {
> int number;
> char name[32]; /* substream name */
> int stream; /* stream (direction) */
> - char latency_id[20]; /* latency identifier */
> + struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
> size_t buffer_bytes_max; /* limit ring buffer size */
> struct snd_dma_buffer dma_buffer;
> unsigned int dma_buf_id;
> diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
> index 3db49b9..a1aea04 100644
> --- a/kernel/pm_qos_params.c
> +++ b/kernel/pm_qos_params.c
> @@ -2,7 +2,7 @@
> * This module exposes the interface to kernel space for specifying
> * QoS dependencies. It provides infrastructure for registration of:
> *
> - * Dependents on a QoS value : register requirements
> + * Dependents on a QoS value : register requests
> * Watchers of QoS value : get notified when target QoS value changes
> *
> * This QoS design is best effort based. Dependents register their QoS needs.
> @@ -14,19 +14,21 @@
> * timeout: usec <-- currently not used.
> * throughput: kbs (kilo byte / sec)
> *
> - * There are lists of pm_qos_objects each one wrapping requirements, notifiers
> + * There are lists of pm_qos_objects each one wrapping requests, notifiers
> *
> - * User mode requirements on a QOS parameter register themselves to the
> + * User mode requests on a QOS parameter register themselves to the
> * subsystem by opening the device node /dev/... and writing there request to
> * the node. As long as the process holds a file handle open to the node the
> * client continues to be accounted for. Upon file release the usermode
> - * requirement is removed and a new qos target is computed. This way when the
> - * requirement that the application has is cleaned up when closes the file
> + * request is removed and a new qos target is computed. This way when the
> + * request that the application has is cleaned up when closes the file
> * pointer or exits the pm_qos_object will get an opportunity to clean up.
> *
> * Mark Gross <mgross@linux.intel.com>
> */
>
> +/*#define DEBUG*/
> +
> #include <linux/pm_qos_params.h>
> #include <linux/sched.h>
> #include <linux/spinlock.h>
> @@ -42,25 +44,25 @@
> #include <linux/uaccess.h>
>
> /*
> - * locking rule: all changes to requirements or notifiers lists
> + * locking rule: all changes to requests or notifiers lists
> * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
> * held, taken with _irqsave. One lock to rule them all
> */
> -struct requirement_list {
> +struct pm_qos_request_list {
> struct list_head list;
> union {
> s32 value;
> s32 usec;
> s32 kbps;
> };
> - char *name;
> + int pm_qos_class;
> };
>
> static s32 max_compare(s32 v1, s32 v2);
> static s32 min_compare(s32 v1, s32 v2);
>
> struct pm_qos_object {
> - struct requirement_list requirements;
> + struct pm_qos_request_list requests;
> struct blocking_notifier_head *notifiers;
> struct miscdevice pm_qos_power_miscdev;
> char *name;
> @@ -72,7 +74,7 @@ struct pm_qos_object {
> static struct pm_qos_object null_pm_qos;
> static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
> static struct pm_qos_object cpu_dma_pm_qos = {
> - .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
> + .requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
> .notifiers = &cpu_dma_lat_notifier,
> .name = "cpu_dma_latency",
> .default_value = 2000 * USEC_PER_SEC,
> @@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
>
> static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
> static struct pm_qos_object network_lat_pm_qos = {
> - .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
> + .requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
> .notifiers = &network_lat_notifier,
> .name = "network_latency",
> .default_value = 2000 * USEC_PER_SEC,
> @@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
>
> static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
> static struct pm_qos_object network_throughput_pm_qos = {
> - .requirements =
> - {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
> + .requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
> .notifiers = &network_throughput_notifier,
> .name = "network_throughput",
> .default_value = 0,
> @@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
> }
>
>
> -static void update_target(int target)
> +static void update_target(int pm_qos_class)
> {
> s32 extreme_value;
> - struct requirement_list *node;
> + struct pm_qos_request_list *node;
> unsigned long flags;
> int call_notifier = 0;
>
> spin_lock_irqsave(&pm_qos_lock, flags);
> - extreme_value = pm_qos_array[target]->default_value;
> + extreme_value = pm_qos_array[pm_qos_class]->default_value;
> list_for_each_entry(node,
> - &pm_qos_array[target]->requirements.list, list) {
> - extreme_value = pm_qos_array[target]->comparitor(
> + &pm_qos_array[pm_qos_class]->requests.list, list) {
> + extreme_value = pm_qos_array[pm_qos_class]->comparitor(
> extreme_value, node->value);
> }
> - if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
> + if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
> + extreme_value) {
> call_notifier = 1;
> - atomic_set(&pm_qos_array[target]->target_value, extreme_value);
> - pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
> - atomic_read(&pm_qos_array[target]->target_value));
> + atomic_set(&pm_qos_array[pm_qos_class]->target_value,
> + extreme_value);
> + pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
> + atomic_read(&pm_qos_array[pm_qos_class]->target_value));
> }
> spin_unlock_irqrestore(&pm_qos_lock, flags);
>
> if (call_notifier)
> - blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
> - (unsigned long) extreme_value, NULL);
> + blocking_notifier_call_chain(
> + pm_qos_array[pm_qos_class]->notifiers,
> + (unsigned long) extreme_value, NULL);
> }
>
> static int register_pm_qos_misc(struct pm_qos_object *qos)
> @@ -185,125 +189,110 @@ static int find_pm_qos_object_by_minor(int minor)
> }
>
> /**
> - * pm_qos_requirement - returns current system wide qos expectation
> + * pm_qos_request - returns current system wide qos expectation
> * @pm_qos_class: identification of which qos value is requested
> *
> * This function returns the current target value in an atomic manner.
> */
> -int pm_qos_requirement(int pm_qos_class)
> +int pm_qos_request(int pm_qos_class)
> {
> return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
> }
> -EXPORT_SYMBOL_GPL(pm_qos_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_request);
>
> /**
> - * pm_qos_add_requirement - inserts new qos request into the list
> + * pm_qos_add_request - inserts new qos request into the list
> * @pm_qos_class: identifies which list of qos request to us
> - * @name: identifies the request
> * @value: defines the qos request
> *
> * This function inserts a new entry in the pm_qos_class list of requested qos
> * performance characteristics. It recomputes the aggregate QoS expectations
> - * for the pm_qos_class of parameters.
> + * for the pm_qos_class of parameters, and returns the pm_qos_request list
> + * element as a handle for use in updating and removal. Call needs to save
> + * this handle for later use.
> */
> -int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
> +struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
> {
> - struct requirement_list *dep;
> + struct pm_qos_request_list *dep;
> unsigned long flags;
>
> - dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
> + dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
> if (dep) {
> if (value == PM_QOS_DEFAULT_VALUE)
> dep->value = pm_qos_array[pm_qos_class]->default_value;
> else
> dep->value = value;
> - dep->name = kstrdup(name, GFP_KERNEL);
> - if (!dep->name)
> - goto cleanup;
> + dep->pm_qos_class = pm_qos_class;
>
> spin_lock_irqsave(&pm_qos_lock, flags);
> list_add(&dep->list,
> - &pm_qos_array[pm_qos_class]->requirements.list);
> + &pm_qos_array[pm_qos_class]->requests.list);
> spin_unlock_irqrestore(&pm_qos_lock, flags);
> update_target(pm_qos_class);
> -
> - return 0;
> }
>
> -cleanup:
> - kfree(dep);
> - return -ENOMEM;
> + return dep;
> }
> -EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_add_request);
>
> /**
> - * pm_qos_update_requirement - modifies an existing qos request
> - * @pm_qos_class: identifies which list of qos request to us
> - * @name: identifies the request
> + * pm_qos_update_request - modifies an existing qos request
> + * @pm_qos_req : handle to list element holding a pm_qos request to use
> * @value: defines the qos request
> *
> - * Updates an existing qos requirement for the pm_qos_class of parameters along
> + * Updates an existing qos request for the pm_qos_class of parameters along
> * with updating the target pm_qos_class value.
> *
> - * If the named request isn't in the list then no change is made.
> + * Attempts are made to make this code callable on hot code paths.
> */
> -int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
> +void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
> + s32 new_value)
> {
> unsigned long flags;
> - struct requirement_list *node;
> int pending_update = 0;
> + s32 temp;
>
> spin_lock_irqsave(&pm_qos_lock, flags);
> - list_for_each_entry(node,
> - &pm_qos_array[pm_qos_class]->requirements.list, list) {
> - if (strcmp(node->name, name) == 0) {
> - if (new_value == PM_QOS_DEFAULT_VALUE)
> - node->value =
> - pm_qos_array[pm_qos_class]->default_value;
> - else
> - node->value = new_value;
> - pending_update = 1;
> - break;
> - }
> + if (new_value == PM_QOS_DEFAULT_VALUE)
> + temp = pm_qos_array[pm_qos_req->pm_qos_class]->default_value;
> + else
> + temp = new_value;
> +
> + if (temp != pm_qos_req->value) {
> + pending_update = 1;
> + pm_qos_req->value = temp;
> }
> spin_unlock_irqrestore(&pm_qos_lock, flags);
> if (pending_update)
> - update_target(pm_qos_class);
> -
> - return 0;
> + update_target(pm_qos_req->pm_qos_class);
> }
> -EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_update_request);
>
> /**
> - * pm_qos_remove_requirement - modifies an existing qos request
> - * @pm_qos_class: identifies which list of qos request to us
> - * @name: identifies the request
> + * pm_qos_remove_request - modifies an existing qos request
> + * @pm_qos_req: handle to request list element
> *
> - * Will remove named qos request from pm_qos_class list of parameters and
> - * recompute the current target value for the pm_qos_class.
> + * Will remove pm qos request from the list of requests and
> + * recompute the current target value for the pm_qos_class. Call this
> + * on slow code paths.
> */
> -void pm_qos_remove_requirement(int pm_qos_class, char *name)
> +void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
> {
> unsigned long flags;
> - struct requirement_list *node;
> - int pending_update = 0;
> + int qos_class;
> +
> + if (pm_qos_req == NULL)
> + return;
> + /* silent return to keep pcm code cleaner */
>
> + qos_class = pm_qos_req->pm_qos_class;
> spin_lock_irqsave(&pm_qos_lock, flags);
> - list_for_each_entry(node,
> - &pm_qos_array[pm_qos_class]->requirements.list, list) {
> - if (strcmp(node->name, name) == 0) {
> - kfree(node->name);
> - list_del(&node->list);
> - kfree(node);
> - pending_update = 1;
> - break;
> - }
> - }
> + list_del(&pm_qos_req->list);
> + kfree(pm_qos_req);
> spin_unlock_irqrestore(&pm_qos_lock, flags);
> - if (pending_update)
> - update_target(pm_qos_class);
> + update_target(qos_class);
> }
> -EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
> +EXPORT_SYMBOL_GPL(pm_qos_remove_request);
>
> /**
> * pm_qos_add_notifier - sets notification entry for changes to target value
> @@ -313,7 +302,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
> * will register the notifier into a notification chain that gets called
> * upon changes to the pm_qos_class target value.
> */
> - int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
> +int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
> {
> int retval;
>
> @@ -343,21 +332,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
> }
> EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
>
> -#define PID_NAME_LEN 32
> -
> static int pm_qos_power_open(struct inode *inode, struct file *filp)
> {
> - int ret;
> long pm_qos_class;
> - char name[PID_NAME_LEN];
>
> pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
> if (pm_qos_class >= 0) {
> - filp->private_data = (void *)pm_qos_class;
> - snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> - ret = pm_qos_add_requirement(pm_qos_class, name,
> - PM_QOS_DEFAULT_VALUE);
> - if (ret >= 0)
> + filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
> + PM_QOS_DEFAULT_VALUE);
> +
> + if (filp->private_data)
> return 0;
> }
> return -EPERM;
> @@ -365,32 +349,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
>
> static int pm_qos_power_release(struct inode *inode, struct file *filp)
> {
> - int pm_qos_class;
> - char name[PID_NAME_LEN];
> + struct pm_qos_request_list *req;
>
> - pm_qos_class = (long)filp->private_data;
> - snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> - pm_qos_remove_requirement(pm_qos_class, name);
> + req = (struct pm_qos_request_list *)filp->private_data;
> + pm_qos_remove_request(req);
>
> return 0;
> }
>
> +
> static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
> size_t count, loff_t *f_pos)
> {
> s32 value;
> - int pm_qos_class;
> - char name[PID_NAME_LEN];
> -
> - pm_qos_class = (long)filp->private_data;
> - if (count != sizeof(s32))
> + int x;
> + char ascii_value[11];
> + struct pm_qos_request_list *pm_qos_req;
> +
> + if (count == sizeof(s32)) {
> + if (copy_from_user(&value, buf, sizeof(s32)))
> + return -EFAULT;
> + } else if (count == 11) { /* len('0x12345678/0') */
> + if (copy_from_user(ascii_value, buf, 11))
> + return -EFAULT;
> + x = sscanf(ascii_value, "%x", &value);
> + if (x != 1)
> + return -EINVAL;
> + pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
> + } else
> return -EINVAL;
> - if (copy_from_user(&value, buf, sizeof(s32)))
> - return -EFAULT;
> - snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> - pm_qos_update_requirement(pm_qos_class, name, value);
>
> - return sizeof(s32);
> + pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
> + pm_qos_update_request(pm_qos_req, value);
> +
> + return count;
> }
>
>
> diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> index 358226f..3deaac3 100644
> --- a/net/mac80211/mlme.c
> +++ b/net/mac80211/mlme.c
> @@ -507,7 +507,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
> s32 beaconint_us;
>
> if (latency < 0)
> - latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
> + latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
>
> beaconint_us = ieee80211_tu_to_usec(
> found->vif.bss_conf.beacon_int);
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index 8bc961f..be52bb8 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -510,7 +510,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
> bad_latency = time_after(jiffies +
> ieee80211_scan_get_channel_time(next_chan),
> local->leave_oper_channel_time +
> - usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY)));
> + usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
>
> listen_int_exceeded = time_after(jiffies +
> ieee80211_scan_get_channel_time(next_chan),
> diff --git a/sound/core/pcm.c b/sound/core/pcm.c
> index 0d428d0..cbe815d 100644
> --- a/sound/core/pcm.c
> +++ b/sound/core/pcm.c
> @@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
> substream->number = idx;
> substream->stream = stream;
> sprintf(substream->name, "subdevice #%i", idx);
> - snprintf(substream->latency_id, sizeof(substream->latency_id),
> - "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
> - (stream ? 'c' : 'p'), idx);
> substream->buffer_bytes_max = UINT_MAX;
> if (prev == NULL)
> pstr->substream = substream;
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index c22ebb0..1bb0e23 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -481,11 +481,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
> snd_pcm_timer_resolution_change(substream);
> runtime->status->state = SNDRV_PCM_STATE_SETUP;
>
> - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> - substream->latency_id);
> + if (substream->latency_pm_qos_req) {
> + pm_qos_remove_request(substream->latency_pm_qos_req);
> + substream->latency_pm_qos_req = NULL;
> + }
> if ((usecs = period_to_usecs(runtime)) >= 0)
> - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
> - substream->latency_id, usecs);
> + substream->latency_pm_qos_req = pm_qos_add_request(
> + PM_QOS_CPU_DMA_LATENCY, usecs);
> return 0;
> _error:
> /* hardware might be unuseable from this time,
> @@ -540,8 +542,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
> if (substream->ops->hw_free)
> result = substream->ops->hw_free(substream);
> runtime->status->state = SNDRV_PCM_STATE_OPEN;
> - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> - substream->latency_id);
> + pm_qos_remove_request(substream->latency_pm_qos_req);
> + substream->latency_pm_qos_req = NULL;
> return result;
> }
>
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-04-30 22:13 ` Rafael J. Wysocki
@ 2010-04-30 23:05 ` mark gross
2010-04-30 23:08 ` Rafael J. Wysocki
0 siblings, 1 reply; 14+ messages in thread
From: mark gross @ 2010-04-30 23:05 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml, NetDev, Johannes Berg,
ACPI Devel Maling List, Len Brown, John W. Linville
On Sat, May 01, 2010 at 12:13:16AM +0200, Rafael J. Wysocki wrote:
> On Friday 30 April 2010, mark gross wrote:
> > The following is a refresh of the PM_QOS implementation, this patch
> > updates some documentation input I got from Randy.
> >
> > This patch changes the string based list management to a handle base
> > implementation to help with the hot path use of pm-qos, it also renames
> > much of the API to use "request" as opposed to "requirement" that was
> > used in the initial implementation. I did this because request more
> > accurately represents what it actually does.
> >
> > Also, I added a string based ABI for users wanting to use a string
> > interface. So if the user writes 0xDDDDDDDD formatted hex it will be
> > accepted by the interface. (someone asked me for it and I don't think
> > it hurts anything.)
> >
> > I really would like to get this refresh taken care of. Its been taking
> > me too long to close this. please review or include it in next.
> >
> > Thanks!
>
> Well, I'd take it to suspend-2.6/linux-next, but first, it touches
> subsystems whose maintainers were not in the Cc list, like the network
> drivers, wireless and ACPI. The changes are trivial, so I hope they don't
> mind.
>
> Second, my tree is based on the Linus' tree rather than linux-next and
> the change in net/mac80211/scan.c doesn't seem to match that. Please tell me
> what I'm supposed to do about that.
You can waite for monday and I'll send a rebased version to linus' tree.
I thought linux-next was where folks wanted me to put it.
I'll email out a new one monday.
Thanks,
--mgross
> Thanks,
> Rafael
>
>
> > Ooops! forgot the signed off by line!
> >
> > Signed-off-by: mark gross <mgross@linux.intel.com>
> >
> > From c45d8d86f89ac55fbb9a499fbc754e35258bf818 Mon Sep 17 00:00:00 2001
> > From: mgross <mark.gross@gmail.com>
> > Date: Sat, 13 Mar 2010 08:18:36 -0800
> > Subject: [PATCH 1/2] PM_QOS to use handle based list implementation and exported function name changes to be more descriptive of what is actually happening.
> >
> > ---
> > Documentation/power/pm_qos_interface.txt | 48 ++++---
> > drivers/acpi/processor_idle.c | 2 +-
> > drivers/cpuidle/governors/ladder.c | 2 +-
> > drivers/cpuidle/governors/menu.c | 2 +-
> > drivers/net/e1000e/netdev.c | 22 ++--
> > drivers/net/igbvf/netdev.c | 6 +-
> > drivers/net/wireless/ipw2x00/ipw2100.c | 11 +-
> > include/linux/netdevice.h | 4 +
> > include/linux/pm_qos_params.h | 14 +-
> > include/sound/pcm.h | 3 +-
> > kernel/pm_qos_params.c | 214 ++++++++++++++---------------
> > net/mac80211/mlme.c | 2 +-
> > net/mac80211/scan.c | 2 +-
> > sound/core/pcm.c | 3 -
> > sound/core/pcm_native.c | 14 +-
> > 15 files changed, 177 insertions(+), 172 deletions(-)
> >
> > diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
> > index c40866e..bfed898 100644
> > --- a/Documentation/power/pm_qos_interface.txt
> > +++ b/Documentation/power/pm_qos_interface.txt
> > @@ -18,44 +18,46 @@ and pm_qos_params.h. This is done because having the available parameters
> > being runtime configurable or changeable from a driver was seen as too easy to
> > abuse.
> >
> > -For each parameter a list of performance requirements is maintained along with
> > +For each parameter a list of performance requests is maintained along with
> > an aggregated target value. The aggregated target value is updated with
> > -changes to the requirement list or elements of the list. Typically the
> > -aggregated target value is simply the max or min of the requirement values held
> > +changes to the request list or elements of the list. Typically the
> > +aggregated target value is simply the max or min of the request values held
> > in the parameter list elements.
> >
> > From kernel mode the use of this interface is simple:
> > -pm_qos_add_requirement(param_id, name, target_value):
> > -Will insert a named element in the list for that identified PM_QOS parameter
> > -with the target value. Upon change to this list the new target is recomputed
> > -and any registered notifiers are called only if the target value is now
> > -different.
> >
> > -pm_qos_update_requirement(param_id, name, new_target_value):
> > -Will search the list identified by the param_id for the named list element and
> > -then update its target value, calling the notification tree if the aggregated
> > -target is changed. with that name is already registered.
> > +handle = pm_qos_add_request(param_class, target_value):
> > +Will insert an element into the list for that identified PM_QOS class with the
> > +target value. Upon change to this list the new target is recomputed and any
> > +registered notifiers are called only if the target value is now different.
> > +Clients of pm_qos need to save the returned handle.
> >
> > -pm_qos_remove_requirement(param_id, name):
> > -Will search the identified list for the named element and remove it, after
> > -removal it will update the aggregate target and call the notification tree if
> > -the target was changed as a result of removing the named requirement.
> > +void pm_qos_update_request(handle, new_target_value):
> > +Will update the list element pointed to by the handle with the new target value
> > +and recompute the new aggregated target, calling the notification tree if the
> > +target is changed.
> > +
> > +void pm_qos_remove_request(handle):
> > +Will remove the element. After removal it will update the aggregate target and
> > +call the notification tree if the target was changed as a result of removing
> > +the request.
> >
> >
> > From user mode:
> > -Only processes can register a pm_qos requirement. To provide for automatic
> > -cleanup for process the interface requires the process to register its
> > -parameter requirements in the following way:
> > +Only processes can register a pm_qos request. To provide for automatic
> > +cleanup of a process, the interface requires the process to register its
> > +parameter requests in the following way:
> >
> > 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]
> >
> > As long as the device node is held open that process has a registered
> > -requirement on the parameter. The name of the requirement is "process_<PID>"
> > -derived from the current->pid from within the open system call.
> > +request on the parameter.
> >
> > -To change the requested target value the process needs to write a s32 value to
> > -the open device node. This translates to a pm_qos_update_requirement call.
> > +To change the requested target value the process needs to write an s32 value to
> > +the open device node. Alternatively the user mode program could write a hex
> > +string for the value using 10 char long format e.g. "0x12345678". This
> > +translates to a pm_qos_update_request call.
> >
> > To remove the user mode request for a target value simply close the device
> > node.
> > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> > index 5939e7f..c3817e1 100644
> > --- a/drivers/acpi/processor_idle.c
> > +++ b/drivers/acpi/processor_idle.c
> > @@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
> > "max_cstate: C%d\n"
> > "maximum allowed latency: %d usec\n",
> > pr->power.state ? pr->power.state - pr->power.states : 0,
> > - max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
> > + max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
> >
> > seq_puts(seq, "states:\n");
> >
> > diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
> > index 1c1ceb4..12c9890 100644
> > --- a/drivers/cpuidle/governors/ladder.c
> > +++ b/drivers/cpuidle/governors/ladder.c
> > @@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
> > struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
> > struct ladder_device_state *last_state;
> > int last_residency, last_idx = ldev->last_state_idx;
> > - int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
> > + int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
> >
> > /* Special case when user has set very strict latency requirement */
> > if (unlikely(latency_req == 0)) {
> > diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
> > index 1aea715..61ca939 100644
> > --- a/drivers/cpuidle/governors/menu.c
> > +++ b/drivers/cpuidle/governors/menu.c
> > @@ -183,7 +183,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
> > static int menu_select(struct cpuidle_device *dev)
> > {
> > struct menu_device *data = &__get_cpu_var(menu_devices);
> > - int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
> > + int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
> > int i;
> > int multiplier;
> >
> > diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
> > index 904bd6b..7550879 100644
> > --- a/drivers/net/e1000e/netdev.c
> > +++ b/drivers/net/e1000e/netdev.c
> > @@ -2882,12 +2882,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
> > * excessive C-state transition latencies result in
> > * dropped transactions.
> > */
> > - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - adapter->netdev->name, 55);
> > + pm_qos_update_request(
> > + adapter->netdev->pm_qos_req, 55);
> > } else {
> > - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - adapter->netdev->name,
> > - PM_QOS_DEFAULT_VALUE);
> > + pm_qos_update_request(
> > + adapter->netdev->pm_qos_req,
> > + PM_QOS_DEFAULT_VALUE);
> > }
> > }
> >
> > @@ -3181,8 +3181,8 @@ int e1000e_up(struct e1000_adapter *adapter)
> >
> > /* DMA latency requirement to workaround early-receive/jumbo issue */
> > if (adapter->flags & FLAG_HAS_ERT)
> > - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - adapter->netdev->name,
> > + adapter->netdev->pm_qos_req =
> > + pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
> > PM_QOS_DEFAULT_VALUE);
> >
> > /* hardware has been reset, we need to reload some things */
> > @@ -3244,9 +3244,11 @@ void e1000e_down(struct e1000_adapter *adapter)
> > e1000_clean_tx_ring(adapter);
> > e1000_clean_rx_ring(adapter);
> >
> > - if (adapter->flags & FLAG_HAS_ERT)
> > - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - adapter->netdev->name);
> > + if (adapter->flags & FLAG_HAS_ERT) {
> > + pm_qos_remove_request(
> > + adapter->netdev->pm_qos_req);
> > + adapter->netdev->pm_qos_req = NULL;
> > + }
> >
> > /*
> > * TODO: for power management, we could drop the link and
> > diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
> > index 7012e3d..5e2b2a8 100644
> > --- a/drivers/net/igbvf/netdev.c
> > +++ b/drivers/net/igbvf/netdev.c
> > @@ -48,6 +48,7 @@
> > #define DRV_VERSION "1.0.0-k0"
> > char igbvf_driver_name[] = "igbvf";
> > const char igbvf_driver_version[] = DRV_VERSION;
> > +struct pm_qos_request_list *igbvf_driver_pm_qos_req;
> > static const char igbvf_driver_string[] =
> > "Intel(R) Virtual Function Network Driver";
> > static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
> > @@ -2901,7 +2902,7 @@ static int __init igbvf_init_module(void)
> > printk(KERN_INFO "%s\n", igbvf_copyright);
> >
> > ret = pci_register_driver(&igbvf_driver);
> > - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
> > + igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
> > PM_QOS_DEFAULT_VALUE);
> >
> > return ret;
> > @@ -2917,7 +2918,8 @@ module_init(igbvf_init_module);
> > static void __exit igbvf_exit_module(void)
> > {
> > pci_unregister_driver(&igbvf_driver);
> > - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
> > + pm_qos_remove_request(igbvf_driver_pm_qos_req);
> > + igbvf_driver_pm_qos_req = NULL;
> > }
> > module_exit(igbvf_exit_module);
> >
> > diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
> > index 2088ac0..7040e3b 100644
> > --- a/drivers/net/wireless/ipw2x00/ipw2100.c
> > +++ b/drivers/net/wireless/ipw2x00/ipw2100.c
> > @@ -174,6 +174,8 @@ that only one external action is invoked at a time.
> > #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
> > #define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
> >
> > +struct pm_qos_request_list *ipw2100_pm_qos_req;
> > +
> > /* Debugging stuff */
> > #ifdef CONFIG_IPW2100_DEBUG
> > #define IPW2100_RX_DEBUG /* Reception debugging */
> > @@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
> > /* the ipw2100 hardware really doesn't want power management delays
> > * longer than 175usec
> > */
> > - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
> > + pm_qos_update_request(ipw2100_pm_qos_req, 175);
> >
> > /* If the interrupt is enabled, turn it off... */
> > spin_lock_irqsave(&priv->low_lock, flags);
> > @@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
> > ipw2100_disable_interrupts(priv);
> > spin_unlock_irqrestore(&priv->low_lock, flags);
> >
> > - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
> > - PM_QOS_DEFAULT_VALUE);
> > + pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
> >
> > /* We have to signal any supplicant if we are disassociating */
> > if (associated)
> > @@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
> > if (ret)
> > goto out;
> >
> > - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
> > + ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
> > PM_QOS_DEFAULT_VALUE);
> > #ifdef CONFIG_IPW2100_DEBUG
> > ipw2100_debug_level = debug;
> > @@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
> > &driver_attr_debug_level);
> > #endif
> > pci_unregister_driver(&ipw2100_pci_driver);
> > - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
> > + pm_qos_remove_request(ipw2100_pm_qos_req);
> > }
> >
> > module_init(ipw2100_init);
> > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
> > index 40d4c20..5dd6d8c 100644
> > --- a/include/linux/netdevice.h
> > +++ b/include/linux/netdevice.h
> > @@ -31,6 +31,7 @@
> > #include <linux/if_link.h>
> >
> > #ifdef __KERNEL__
> > +#include <linux/pm_qos_params.h>
> > #include <linux/timer.h>
> > #include <linux/delay.h>
> > #include <linux/mm.h>
> > @@ -778,6 +779,9 @@ struct net_device {
> > * the interface.
> > */
> > char name[IFNAMSIZ];
> > +
> > + struct pm_qos_request_list *pm_qos_req;
> > +
> > /* device name hash chain */
> > struct hlist_node name_hlist;
> > /* snmp alias */
> > diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
> > index d74f75e..8ba440e 100644
> > --- a/include/linux/pm_qos_params.h
> > +++ b/include/linux/pm_qos_params.h
> > @@ -14,12 +14,14 @@
> > #define PM_QOS_NUM_CLASSES 4
> > #define PM_QOS_DEFAULT_VALUE -1
> >
> > -int pm_qos_add_requirement(int qos, char *name, s32 value);
> > -int pm_qos_update_requirement(int qos, char *name, s32 new_value);
> > -void pm_qos_remove_requirement(int qos, char *name);
> > +struct pm_qos_request_list;
> >
> > -int pm_qos_requirement(int qos);
> > +struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
> > +void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
> > + s32 new_value);
> > +void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
> >
> > -int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
> > -int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
> > +int pm_qos_request(int pm_qos_class);
> > +int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
> > +int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
> >
> > diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> > index 8b611a5..dd76cde 100644
> > --- a/include/sound/pcm.h
> > +++ b/include/sound/pcm.h
> > @@ -29,6 +29,7 @@
> > #include <linux/poll.h>
> > #include <linux/mm.h>
> > #include <linux/bitops.h>
> > +#include <linux/pm_qos_params.h>
> >
> > #define snd_pcm_substream_chip(substream) ((substream)->private_data)
> > #define snd_pcm_chip(pcm) ((pcm)->private_data)
> > @@ -365,7 +366,7 @@ struct snd_pcm_substream {
> > int number;
> > char name[32]; /* substream name */
> > int stream; /* stream (direction) */
> > - char latency_id[20]; /* latency identifier */
> > + struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
> > size_t buffer_bytes_max; /* limit ring buffer size */
> > struct snd_dma_buffer dma_buffer;
> > unsigned int dma_buf_id;
> > diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
> > index 3db49b9..a1aea04 100644
> > --- a/kernel/pm_qos_params.c
> > +++ b/kernel/pm_qos_params.c
> > @@ -2,7 +2,7 @@
> > * This module exposes the interface to kernel space for specifying
> > * QoS dependencies. It provides infrastructure for registration of:
> > *
> > - * Dependents on a QoS value : register requirements
> > + * Dependents on a QoS value : register requests
> > * Watchers of QoS value : get notified when target QoS value changes
> > *
> > * This QoS design is best effort based. Dependents register their QoS needs.
> > @@ -14,19 +14,21 @@
> > * timeout: usec <-- currently not used.
> > * throughput: kbs (kilo byte / sec)
> > *
> > - * There are lists of pm_qos_objects each one wrapping requirements, notifiers
> > + * There are lists of pm_qos_objects each one wrapping requests, notifiers
> > *
> > - * User mode requirements on a QOS parameter register themselves to the
> > + * User mode requests on a QOS parameter register themselves to the
> > * subsystem by opening the device node /dev/... and writing there request to
> > * the node. As long as the process holds a file handle open to the node the
> > * client continues to be accounted for. Upon file release the usermode
> > - * requirement is removed and a new qos target is computed. This way when the
> > - * requirement that the application has is cleaned up when closes the file
> > + * request is removed and a new qos target is computed. This way when the
> > + * request that the application has is cleaned up when closes the file
> > * pointer or exits the pm_qos_object will get an opportunity to clean up.
> > *
> > * Mark Gross <mgross@linux.intel.com>
> > */
> >
> > +/*#define DEBUG*/
> > +
> > #include <linux/pm_qos_params.h>
> > #include <linux/sched.h>
> > #include <linux/spinlock.h>
> > @@ -42,25 +44,25 @@
> > #include <linux/uaccess.h>
> >
> > /*
> > - * locking rule: all changes to requirements or notifiers lists
> > + * locking rule: all changes to requests or notifiers lists
> > * or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
> > * held, taken with _irqsave. One lock to rule them all
> > */
> > -struct requirement_list {
> > +struct pm_qos_request_list {
> > struct list_head list;
> > union {
> > s32 value;
> > s32 usec;
> > s32 kbps;
> > };
> > - char *name;
> > + int pm_qos_class;
> > };
> >
> > static s32 max_compare(s32 v1, s32 v2);
> > static s32 min_compare(s32 v1, s32 v2);
> >
> > struct pm_qos_object {
> > - struct requirement_list requirements;
> > + struct pm_qos_request_list requests;
> > struct blocking_notifier_head *notifiers;
> > struct miscdevice pm_qos_power_miscdev;
> > char *name;
> > @@ -72,7 +74,7 @@ struct pm_qos_object {
> > static struct pm_qos_object null_pm_qos;
> > static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
> > static struct pm_qos_object cpu_dma_pm_qos = {
> > - .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
> > + .requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
> > .notifiers = &cpu_dma_lat_notifier,
> > .name = "cpu_dma_latency",
> > .default_value = 2000 * USEC_PER_SEC,
> > @@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
> >
> > static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
> > static struct pm_qos_object network_lat_pm_qos = {
> > - .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
> > + .requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
> > .notifiers = &network_lat_notifier,
> > .name = "network_latency",
> > .default_value = 2000 * USEC_PER_SEC,
> > @@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
> >
> > static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
> > static struct pm_qos_object network_throughput_pm_qos = {
> > - .requirements =
> > - {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
> > + .requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
> > .notifiers = &network_throughput_notifier,
> > .name = "network_throughput",
> > .default_value = 0,
> > @@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
> > }
> >
> >
> > -static void update_target(int target)
> > +static void update_target(int pm_qos_class)
> > {
> > s32 extreme_value;
> > - struct requirement_list *node;
> > + struct pm_qos_request_list *node;
> > unsigned long flags;
> > int call_notifier = 0;
> >
> > spin_lock_irqsave(&pm_qos_lock, flags);
> > - extreme_value = pm_qos_array[target]->default_value;
> > + extreme_value = pm_qos_array[pm_qos_class]->default_value;
> > list_for_each_entry(node,
> > - &pm_qos_array[target]->requirements.list, list) {
> > - extreme_value = pm_qos_array[target]->comparitor(
> > + &pm_qos_array[pm_qos_class]->requests.list, list) {
> > + extreme_value = pm_qos_array[pm_qos_class]->comparitor(
> > extreme_value, node->value);
> > }
> > - if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
> > + if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
> > + extreme_value) {
> > call_notifier = 1;
> > - atomic_set(&pm_qos_array[target]->target_value, extreme_value);
> > - pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
> > - atomic_read(&pm_qos_array[target]->target_value));
> > + atomic_set(&pm_qos_array[pm_qos_class]->target_value,
> > + extreme_value);
> > + pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
> > + atomic_read(&pm_qos_array[pm_qos_class]->target_value));
> > }
> > spin_unlock_irqrestore(&pm_qos_lock, flags);
> >
> > if (call_notifier)
> > - blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
> > - (unsigned long) extreme_value, NULL);
> > + blocking_notifier_call_chain(
> > + pm_qos_array[pm_qos_class]->notifiers,
> > + (unsigned long) extreme_value, NULL);
> > }
> >
> > static int register_pm_qos_misc(struct pm_qos_object *qos)
> > @@ -185,125 +189,110 @@ static int find_pm_qos_object_by_minor(int minor)
> > }
> >
> > /**
> > - * pm_qos_requirement - returns current system wide qos expectation
> > + * pm_qos_request - returns current system wide qos expectation
> > * @pm_qos_class: identification of which qos value is requested
> > *
> > * This function returns the current target value in an atomic manner.
> > */
> > -int pm_qos_requirement(int pm_qos_class)
> > +int pm_qos_request(int pm_qos_class)
> > {
> > return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
> > }
> > -EXPORT_SYMBOL_GPL(pm_qos_requirement);
> > +EXPORT_SYMBOL_GPL(pm_qos_request);
> >
> > /**
> > - * pm_qos_add_requirement - inserts new qos request into the list
> > + * pm_qos_add_request - inserts new qos request into the list
> > * @pm_qos_class: identifies which list of qos request to us
> > - * @name: identifies the request
> > * @value: defines the qos request
> > *
> > * This function inserts a new entry in the pm_qos_class list of requested qos
> > * performance characteristics. It recomputes the aggregate QoS expectations
> > - * for the pm_qos_class of parameters.
> > + * for the pm_qos_class of parameters, and returns the pm_qos_request list
> > + * element as a handle for use in updating and removal. Call needs to save
> > + * this handle for later use.
> > */
> > -int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
> > +struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
> > {
> > - struct requirement_list *dep;
> > + struct pm_qos_request_list *dep;
> > unsigned long flags;
> >
> > - dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
> > + dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
> > if (dep) {
> > if (value == PM_QOS_DEFAULT_VALUE)
> > dep->value = pm_qos_array[pm_qos_class]->default_value;
> > else
> > dep->value = value;
> > - dep->name = kstrdup(name, GFP_KERNEL);
> > - if (!dep->name)
> > - goto cleanup;
> > + dep->pm_qos_class = pm_qos_class;
> >
> > spin_lock_irqsave(&pm_qos_lock, flags);
> > list_add(&dep->list,
> > - &pm_qos_array[pm_qos_class]->requirements.list);
> > + &pm_qos_array[pm_qos_class]->requests.list);
> > spin_unlock_irqrestore(&pm_qos_lock, flags);
> > update_target(pm_qos_class);
> > -
> > - return 0;
> > }
> >
> > -cleanup:
> > - kfree(dep);
> > - return -ENOMEM;
> > + return dep;
> > }
> > -EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
> > +EXPORT_SYMBOL_GPL(pm_qos_add_request);
> >
> > /**
> > - * pm_qos_update_requirement - modifies an existing qos request
> > - * @pm_qos_class: identifies which list of qos request to us
> > - * @name: identifies the request
> > + * pm_qos_update_request - modifies an existing qos request
> > + * @pm_qos_req : handle to list element holding a pm_qos request to use
> > * @value: defines the qos request
> > *
> > - * Updates an existing qos requirement for the pm_qos_class of parameters along
> > + * Updates an existing qos request for the pm_qos_class of parameters along
> > * with updating the target pm_qos_class value.
> > *
> > - * If the named request isn't in the list then no change is made.
> > + * Attempts are made to make this code callable on hot code paths.
> > */
> > -int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
> > +void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
> > + s32 new_value)
> > {
> > unsigned long flags;
> > - struct requirement_list *node;
> > int pending_update = 0;
> > + s32 temp;
> >
> > spin_lock_irqsave(&pm_qos_lock, flags);
> > - list_for_each_entry(node,
> > - &pm_qos_array[pm_qos_class]->requirements.list, list) {
> > - if (strcmp(node->name, name) == 0) {
> > - if (new_value == PM_QOS_DEFAULT_VALUE)
> > - node->value =
> > - pm_qos_array[pm_qos_class]->default_value;
> > - else
> > - node->value = new_value;
> > - pending_update = 1;
> > - break;
> > - }
> > + if (new_value == PM_QOS_DEFAULT_VALUE)
> > + temp = pm_qos_array[pm_qos_req->pm_qos_class]->default_value;
> > + else
> > + temp = new_value;
> > +
> > + if (temp != pm_qos_req->value) {
> > + pending_update = 1;
> > + pm_qos_req->value = temp;
> > }
> > spin_unlock_irqrestore(&pm_qos_lock, flags);
> > if (pending_update)
> > - update_target(pm_qos_class);
> > -
> > - return 0;
> > + update_target(pm_qos_req->pm_qos_class);
> > }
> > -EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
> > +EXPORT_SYMBOL_GPL(pm_qos_update_request);
> >
> > /**
> > - * pm_qos_remove_requirement - modifies an existing qos request
> > - * @pm_qos_class: identifies which list of qos request to us
> > - * @name: identifies the request
> > + * pm_qos_remove_request - modifies an existing qos request
> > + * @pm_qos_req: handle to request list element
> > *
> > - * Will remove named qos request from pm_qos_class list of parameters and
> > - * recompute the current target value for the pm_qos_class.
> > + * Will remove pm qos request from the list of requests and
> > + * recompute the current target value for the pm_qos_class. Call this
> > + * on slow code paths.
> > */
> > -void pm_qos_remove_requirement(int pm_qos_class, char *name)
> > +void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
> > {
> > unsigned long flags;
> > - struct requirement_list *node;
> > - int pending_update = 0;
> > + int qos_class;
> > +
> > + if (pm_qos_req == NULL)
> > + return;
> > + /* silent return to keep pcm code cleaner */
> >
> > + qos_class = pm_qos_req->pm_qos_class;
> > spin_lock_irqsave(&pm_qos_lock, flags);
> > - list_for_each_entry(node,
> > - &pm_qos_array[pm_qos_class]->requirements.list, list) {
> > - if (strcmp(node->name, name) == 0) {
> > - kfree(node->name);
> > - list_del(&node->list);
> > - kfree(node);
> > - pending_update = 1;
> > - break;
> > - }
> > - }
> > + list_del(&pm_qos_req->list);
> > + kfree(pm_qos_req);
> > spin_unlock_irqrestore(&pm_qos_lock, flags);
> > - if (pending_update)
> > - update_target(pm_qos_class);
> > + update_target(qos_class);
> > }
> > -EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
> > +EXPORT_SYMBOL_GPL(pm_qos_remove_request);
> >
> > /**
> > * pm_qos_add_notifier - sets notification entry for changes to target value
> > @@ -313,7 +302,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
> > * will register the notifier into a notification chain that gets called
> > * upon changes to the pm_qos_class target value.
> > */
> > - int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
> > +int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
> > {
> > int retval;
> >
> > @@ -343,21 +332,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
> > }
> > EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
> >
> > -#define PID_NAME_LEN 32
> > -
> > static int pm_qos_power_open(struct inode *inode, struct file *filp)
> > {
> > - int ret;
> > long pm_qos_class;
> > - char name[PID_NAME_LEN];
> >
> > pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
> > if (pm_qos_class >= 0) {
> > - filp->private_data = (void *)pm_qos_class;
> > - snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> > - ret = pm_qos_add_requirement(pm_qos_class, name,
> > - PM_QOS_DEFAULT_VALUE);
> > - if (ret >= 0)
> > + filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
> > + PM_QOS_DEFAULT_VALUE);
> > +
> > + if (filp->private_data)
> > return 0;
> > }
> > return -EPERM;
> > @@ -365,32 +349,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
> >
> > static int pm_qos_power_release(struct inode *inode, struct file *filp)
> > {
> > - int pm_qos_class;
> > - char name[PID_NAME_LEN];
> > + struct pm_qos_request_list *req;
> >
> > - pm_qos_class = (long)filp->private_data;
> > - snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> > - pm_qos_remove_requirement(pm_qos_class, name);
> > + req = (struct pm_qos_request_list *)filp->private_data;
> > + pm_qos_remove_request(req);
> >
> > return 0;
> > }
> >
> > +
> > static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
> > size_t count, loff_t *f_pos)
> > {
> > s32 value;
> > - int pm_qos_class;
> > - char name[PID_NAME_LEN];
> > -
> > - pm_qos_class = (long)filp->private_data;
> > - if (count != sizeof(s32))
> > + int x;
> > + char ascii_value[11];
> > + struct pm_qos_request_list *pm_qos_req;
> > +
> > + if (count == sizeof(s32)) {
> > + if (copy_from_user(&value, buf, sizeof(s32)))
> > + return -EFAULT;
> > + } else if (count == 11) { /* len('0x12345678/0') */
> > + if (copy_from_user(ascii_value, buf, 11))
> > + return -EFAULT;
> > + x = sscanf(ascii_value, "%x", &value);
> > + if (x != 1)
> > + return -EINVAL;
> > + pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
> > + } else
> > return -EINVAL;
> > - if (copy_from_user(&value, buf, sizeof(s32)))
> > - return -EFAULT;
> > - snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
> > - pm_qos_update_requirement(pm_qos_class, name, value);
> >
> > - return sizeof(s32);
> > + pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
> > + pm_qos_update_request(pm_qos_req, value);
> > +
> > + return count;
> > }
> >
> >
> > diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
> > index 358226f..3deaac3 100644
> > --- a/net/mac80211/mlme.c
> > +++ b/net/mac80211/mlme.c
> > @@ -507,7 +507,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
> > s32 beaconint_us;
> >
> > if (latency < 0)
> > - latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
> > + latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
> >
> > beaconint_us = ieee80211_tu_to_usec(
> > found->vif.bss_conf.beacon_int);
> > diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> > index 8bc961f..be52bb8 100644
> > --- a/net/mac80211/scan.c
> > +++ b/net/mac80211/scan.c
> > @@ -510,7 +510,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
> > bad_latency = time_after(jiffies +
> > ieee80211_scan_get_channel_time(next_chan),
> > local->leave_oper_channel_time +
> > - usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY)));
> > + usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
> >
> > listen_int_exceeded = time_after(jiffies +
> > ieee80211_scan_get_channel_time(next_chan),
> > diff --git a/sound/core/pcm.c b/sound/core/pcm.c
> > index 0d428d0..cbe815d 100644
> > --- a/sound/core/pcm.c
> > +++ b/sound/core/pcm.c
> > @@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
> > substream->number = idx;
> > substream->stream = stream;
> > sprintf(substream->name, "subdevice #%i", idx);
> > - snprintf(substream->latency_id, sizeof(substream->latency_id),
> > - "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
> > - (stream ? 'c' : 'p'), idx);
> > substream->buffer_bytes_max = UINT_MAX;
> > if (prev == NULL)
> > pstr->substream = substream;
> > diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> > index c22ebb0..1bb0e23 100644
> > --- a/sound/core/pcm_native.c
> > +++ b/sound/core/pcm_native.c
> > @@ -481,11 +481,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
> > snd_pcm_timer_resolution_change(substream);
> > runtime->status->state = SNDRV_PCM_STATE_SETUP;
> >
> > - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - substream->latency_id);
> > + if (substream->latency_pm_qos_req) {
> > + pm_qos_remove_request(substream->latency_pm_qos_req);
> > + substream->latency_pm_qos_req = NULL;
> > + }
> > if ((usecs = period_to_usecs(runtime)) >= 0)
> > - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - substream->latency_id, usecs);
> > + substream->latency_pm_qos_req = pm_qos_add_request(
> > + PM_QOS_CPU_DMA_LATENCY, usecs);
> > return 0;
> > _error:
> > /* hardware might be unuseable from this time,
> > @@ -540,8 +542,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
> > if (substream->ops->hw_free)
> > result = substream->ops->hw_free(substream);
> > runtime->status->state = SNDRV_PCM_STATE_OPEN;
> > - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
> > - substream->latency_id);
> > + pm_qos_remove_request(substream->latency_pm_qos_req);
> > + substream->latency_pm_qos_req = NULL;
> > return result;
> > }
> >
> >
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-04-30 23:05 ` mark gross
@ 2010-04-30 23:08 ` Rafael J. Wysocki
2010-05-04 14:30 ` mark gross
0 siblings, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki @ 2010-04-30 23:08 UTC (permalink / raw)
To: mgross
Cc: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml, NetDev, Johannes Berg,
ACPI Devel Maling List, Len Brown, John W. Linville
On Saturday 01 May 2010, mark gross wrote:
> On Sat, May 01, 2010 at 12:13:16AM +0200, Rafael J. Wysocki wrote:
> > On Friday 30 April 2010, mark gross wrote:
> > > The following is a refresh of the PM_QOS implementation, this patch
> > > updates some documentation input I got from Randy.
> > >
> > > This patch changes the string based list management to a handle base
> > > implementation to help with the hot path use of pm-qos, it also renames
> > > much of the API to use "request" as opposed to "requirement" that was
> > > used in the initial implementation. I did this because request more
> > > accurately represents what it actually does.
> > >
> > > Also, I added a string based ABI for users wanting to use a string
> > > interface. So if the user writes 0xDDDDDDDD formatted hex it will be
> > > accepted by the interface. (someone asked me for it and I don't think
> > > it hurts anything.)
> > >
> > > I really would like to get this refresh taken care of. Its been taking
> > > me too long to close this. please review or include it in next.
> > >
> > > Thanks!
> >
> > Well, I'd take it to suspend-2.6/linux-next, but first, it touches
> > subsystems whose maintainers were not in the Cc list, like the network
> > drivers, wireless and ACPI. The changes are trivial, so I hope they don't
> > mind.
> >
> > Second, my tree is based on the Linus' tree rather than linux-next and
> > the change in net/mac80211/scan.c doesn't seem to match that. Please tell me
> > what I'm supposed to do about that.
>
> You can waite for monday and I'll send a rebased version to linus' tree.
>
> I thought linux-next was where folks wanted me to put it.
>
> I'll email out a new one monday.
Great, thanks!
Rafael
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-04-30 21:20 mark gross
2010-04-30 22:13 ` Rafael J. Wysocki
@ 2010-05-03 16:33 ` Jonathan Corbet
2010-05-03 16:40 ` Kevin Hilman
1 sibling, 1 reply; 14+ messages in thread
From: Jonathan Corbet @ 2010-05-03 16:33 UTC (permalink / raw)
To: mgross
Cc: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml
On Fri, 30 Apr 2010 14:20:43 -0700
mark gross <mgross@linux.intel.com> wrote:
> This patch changes the string based list management to a handle base
> implementation to help with the hot path use of pm-qos
Having taken a quick look, I think the API change makes a lot of
sense. Hot paths are one thing; avoidance of accidental conflicts
would be another.
One question, though... one clear use of this API is for drivers to
say "don't go into C3 or deeper because things go wrong"; I'm about to
add another one of those. It works, but the use of a
PM_QOS_CPU_DMA_LATENCY requirement with a hard-coded number that one
hopes is small enough seems a bit...indirect. I wonder if it would be
clearer and more robust to add a new requirement^Wrequest type saying
"the quality of service I need is shallow sleeps only"?
jon
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-03 16:33 ` Jonathan Corbet
@ 2010-05-03 16:40 ` Kevin Hilman
2010-05-03 16:42 ` Jonathan Corbet
0 siblings, 1 reply; 14+ messages in thread
From: Kevin Hilman @ 2010-05-03 16:40 UTC (permalink / raw)
To: Jonathan Corbet
Cc: mgross, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml
Jonathan Corbet <corbet@lwn.net> writes:
> On Fri, 30 Apr 2010 14:20:43 -0700
> mark gross <mgross@linux.intel.com> wrote:
>
>> This patch changes the string based list management to a handle base
>> implementation to help with the hot path use of pm-qos
>
> Having taken a quick look, I think the API change makes a lot of
> sense. Hot paths are one thing; avoidance of accidental conflicts
> would be another.
>
> One question, though... one clear use of this API is for drivers to
> say "don't go into C3 or deeper because things go wrong"; I'm about to
> add another one of those. It works, but the use of a
> PM_QOS_CPU_DMA_LATENCY requirement with a hard-coded number that one
> hopes is small enough seems a bit...indirect. I wonder if it would be
> clearer and more robust to add a new requirement^Wrequest type saying
> "the quality of service I need is shallow sleeps only"?
The problem with that is portability.
What does "shallow" mean?
Even between different SoCs in the same family, shallow might have
different meaning, but across architectures, this certainly would not
be portable.
Kevin
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-03 16:40 ` Kevin Hilman
@ 2010-05-03 16:42 ` Jonathan Corbet
2010-05-03 17:01 ` Kevin Hilman
2010-05-04 4:16 ` Pavel Machek
0 siblings, 2 replies; 14+ messages in thread
From: Jonathan Corbet @ 2010-05-03 16:42 UTC (permalink / raw)
To: Kevin Hilman
Cc: mgross, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml
On Mon, 03 May 2010 09:40:11 -0700
Kevin Hilman <khilman@deeprootsystems.com> wrote:
> > One question, though... one clear use of this API is for drivers to
> > say "don't go into C3 or deeper because things go wrong"; I'm about to
> > add another one of those. It works, but the use of a
> > PM_QOS_CPU_DMA_LATENCY requirement with a hard-coded number that one
> > hopes is small enough seems a bit...indirect. I wonder if it would be
> > clearer and more robust to add a new requirement^Wrequest type saying
> > "the quality of service I need is shallow sleeps only"?
>
> The problem with that is portability.
>
> What does "shallow" mean?
Well, shallow could mean that the state lacks the CPUIDLE_FLAG_DEEP
flag; that should be relatively portable. In any case, it seems more
so than "if I put in a 55us latency requirement, I'll stay out of C3".
Just a thought, anyway; it's not like I've really worked through a
plausible alternative API.
jon
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-03 16:42 ` Jonathan Corbet
@ 2010-05-03 17:01 ` Kevin Hilman
2010-05-03 17:10 ` Jonathan Corbet
2010-05-03 21:39 ` Matthew Garrett
2010-05-04 4:16 ` Pavel Machek
1 sibling, 2 replies; 14+ messages in thread
From: Kevin Hilman @ 2010-05-03 17:01 UTC (permalink / raw)
To: Jonathan Corbet
Cc: mgross, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml
Jonathan Corbet <corbet@lwn.net> writes:
> On Mon, 03 May 2010 09:40:11 -0700
> Kevin Hilman <khilman@deeprootsystems.com> wrote:
>
>> > One question, though... one clear use of this API is for drivers to
>> > say "don't go into C3 or deeper because things go wrong"; I'm about to
>> > add another one of those. It works, but the use of a
>> > PM_QOS_CPU_DMA_LATENCY requirement with a hard-coded number that one
>> > hopes is small enough seems a bit...indirect. I wonder if it would be
>> > clearer and more robust to add a new requirement^Wrequest type saying
>> > "the quality of service I need is shallow sleeps only"?
>>
>> The problem with that is portability.
>>
>> What does "shallow" mean?
>
> Well, shallow could mean that the state lacks the CPUIDLE_FLAG_DEEP
> flag; that should be relatively portable. In any case, it seems
> more so than "if I put in a 55us latency requirement, I'll stay out
> of C3".
I guess it depends on your goal. Do you just want to stay out of C3
on your current platform? or do you want to stay out of any low-power
state (on any platform) where you'll have a latency of > 55 usecs?
The former is not portable (as C-states don't have the same meanings
across arches/SoCs) where as using a real-world number in usecs will
have meaning on any platform.
> Just a thought, anyway; it's not like I've really worked through a
> plausible alternative API.
My main concern is that drivers not be written with latency
constraints that assume an Intel-centric set of power states. There
are other SoCs out there with different sets of states and
corresponding latencies, so keeping things in real-world numbers
(latency, throughput, etc.) seems to me to be the only portable way.
Kevin
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-03 17:01 ` Kevin Hilman
@ 2010-05-03 17:10 ` Jonathan Corbet
2010-05-03 21:39 ` Matthew Garrett
1 sibling, 0 replies; 14+ messages in thread
From: Jonathan Corbet @ 2010-05-03 17:10 UTC (permalink / raw)
To: Kevin Hilman
Cc: mgross, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml
On Mon, 03 May 2010 10:01:50 -0700
Kevin Hilman <khilman@deeprootsystems.com> wrote:
> > Well, shallow could mean that the state lacks the CPUIDLE_FLAG_DEEP
> > flag; that should be relatively portable. In any case, it seems
> > more so than "if I put in a 55us latency requirement, I'll stay out
> > of C3".
>
> I guess it depends on your goal. Do you just want to stay out of C3
> on your current platform? or do you want to stay out of any low-power
> state (on any platform) where you'll have a latency of > 55 usecs?
My case is a camera driver; as long as latencies are on the scale of
the frame rate, things won't go too wrong. 1ms latencies would not be
a huge problem. What happens is that the hardware corrupts the data if
it goes into C3 while video capture is happening.
Comments in drivers/net/e1000e/netdev.c suggest that they were dealing
with similar issues.
> The former is not portable (as C-states don't have the same meanings
> across arches/SoCs) where as using a real-world number in usecs will
> have meaning on any platform.
Understood. But the end result is that I've ended up specifying a
latency requirement that is far tighter than the situation really needs
in order to achieve the real goal.
> My main concern is that drivers not be written with latency
> constraints that assume an Intel-centric set of power states. There
> are other SoCs out there with different sets of states and
> corresponding latencies, so keeping things in real-world numbers
> (latency, throughput, etc.) seems to me to be the only portable way.
Understood. Perhaps the pm_qos interface isn't the best way to achieve
the real goal here, but it's all we have at the moment.
Thanks,
jon
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-03 17:01 ` Kevin Hilman
2010-05-03 17:10 ` Jonathan Corbet
@ 2010-05-03 21:39 ` Matthew Garrett
1 sibling, 0 replies; 14+ messages in thread
From: Matthew Garrett @ 2010-05-03 21:39 UTC (permalink / raw)
To: Kevin Hilman
Cc: Jonathan Corbet, mgross, aili, dwalker, tiwai, bruce.w.allan,
davidb, mcgrof, pavel, linux-pm, lkml
On Mon, May 03, 2010 at 10:01:50AM -0700, Kevin Hilman wrote:
> Jonathan Corbet <corbet@lwn.net> writes:
> > Well, shallow could mean that the state lacks the CPUIDLE_FLAG_DEEP
> > flag; that should be relatively portable. In any case, it seems
> > more so than "if I put in a 55us latency requirement, I'll stay out
> > of C3".
>
> I guess it depends on your goal. Do you just want to stay out of C3
> on your current platform? or do you want to stay out of any low-power
> state (on any platform) where you'll have a latency of > 55 usecs?
I'd say that one plausible requirement is "DMA works", with another
being "all interrupts work" as distinguished from "wakeup interrupts
work".
--
Matthew Garrett | mjg59@srcf.ucam.org
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-03 16:42 ` Jonathan Corbet
2010-05-03 17:01 ` Kevin Hilman
@ 2010-05-04 4:16 ` Pavel Machek
1 sibling, 0 replies; 14+ messages in thread
From: Pavel Machek @ 2010-05-04 4:16 UTC (permalink / raw)
To: Jonathan Corbet
Cc: Kevin Hilman, mgross, aili, dwalker, tiwai, bruce.w.allan, davidb,
mcgrof, linux-pm, lkml
On Mon 2010-05-03 10:42:50, Jonathan Corbet wrote:
> On Mon, 03 May 2010 09:40:11 -0700
> Kevin Hilman <khilman@deeprootsystems.com> wrote:
>
> > > One question, though... one clear use of this API is for drivers to
> > > say "don't go into C3 or deeper because things go wrong"; I'm about to
> > > add another one of those. It works, but the use of a
> > > PM_QOS_CPU_DMA_LATENCY requirement with a hard-coded number that one
> > > hopes is small enough seems a bit...indirect. I wonder if it would be
> > > clearer and more robust to add a new requirement^Wrequest type saying
> > > "the quality of service I need is shallow sleeps only"?
> >
> > The problem with that is portability.
> >
> > What does "shallow" mean?
>
> Well, shallow could mean that the state lacks the CPUIDLE_FLAG_DEEP
> flag; that should be relatively portable. In any case, it seems more
> so than "if I put in a 55us latency requirement, I'll stay out of C3".
While C3 has maximum allowed latency (101usec, iirc), I believe
there's no minimum, so someone could create platform with really quick
C3 with perhaps only 10usec to enter...
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-04-30 23:08 ` Rafael J. Wysocki
@ 2010-05-04 14:30 ` mark gross
2010-05-05 23:59 ` Rafael J. Wysocki
0 siblings, 1 reply; 14+ messages in thread
From: mark gross @ 2010-05-04 14:30 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml, NetDev, Johannes Berg,
ACPI Devel Maling List, Len Brown, John W. Linville
On Sat, May 01, 2010 at 01:08:28AM +0200, Rafael J. Wysocki wrote:
> On Saturday 01 May 2010, mark gross wrote:
> > On Sat, May 01, 2010 at 12:13:16AM +0200, Rafael J. Wysocki wrote:
> > > On Friday 30 April 2010, mark gross wrote:
> > > > The following is a refresh of the PM_QOS implementation, this patch
> > > > updates some documentation input I got from Randy.
> > > >
> > > > This patch changes the string based list management to a handle base
> > > > implementation to help with the hot path use of pm-qos, it also renames
> > > > much of the API to use "request" as opposed to "requirement" that was
> > > > used in the initial implementation. I did this because request more
> > > > accurately represents what it actually does.
> > > >
> > > > Also, I added a string based ABI for users wanting to use a string
> > > > interface. So if the user writes 0xDDDDDDDD formatted hex it will be
> > > > accepted by the interface. (someone asked me for it and I don't think
> > > > it hurts anything.)
> > > >
> > > > I really would like to get this refresh taken care of. Its been taking
> > > > me too long to close this. please review or include it in next.
> > > >
> > > > Thanks!
> > >
> > > Well, I'd take it to suspend-2.6/linux-next, but first, it touches
> > > subsystems whose maintainers were not in the Cc list, like the network
> > > drivers, wireless and ACPI. The changes are trivial, so I hope they don't
> > > mind.
> > >
> > > Second, my tree is based on the Linus' tree rather than linux-next and
> > > the change in net/mac80211/scan.c doesn't seem to match that. Please tell me
> > > what I'm supposed to do about that.
> >
> > You can waite for monday and I'll send a rebased version to linus' tree.
> >
> > I thought linux-next was where folks wanted me to put it.
> >
> > I'll email out a new one monday.
>
> Great, thanks!
>
> Rafael
Sorry I'm late,
Signed-off-by: markgross <mgross@linux.intel.com>
>From e6300f50eff52d585dd9d5e14364dba5aa542477 Mon Sep 17 00:00:00 2001
From: markgross <mark.gross@intel.com>
Date: Mon, 3 May 2010 12:46:42 -0700
Subject: [PATCH] PM_QOS to use handle based list implementation and exported function name changes to be more descriptive of what is actually happening.
---
Documentation/power/pm_qos_interface.txt | 48 ++++---
drivers/acpi/processor_idle.c | 2 +-
drivers/cpuidle/governors/ladder.c | 2 +-
| 2 +-
drivers/net/e1000e/netdev.c | 22 ++--
drivers/net/igbvf/netdev.c | 6 +-
drivers/net/wireless/ipw2x00/ipw2100.c | 11 +-
include/linux/netdevice.h | 4 +
include/linux/pm_qos_params.h | 14 +-
include/sound/pcm.h | 3 +-
kernel/pm_qos_params.c | 214 ++++++++++++++---------------
net/mac80211/mlme.c | 2 +-
sound/core/pcm.c | 3 -
sound/core/pcm_native.c | 14 +-
14 files changed, 176 insertions(+), 171 deletions(-)
diff --git a/Documentation/power/pm_qos_interface.txt b/Documentation/power/pm_qos_interface.txt
index c40866e..bfed898 100644
--- a/Documentation/power/pm_qos_interface.txt
+++ b/Documentation/power/pm_qos_interface.txt
@@ -18,44 +18,46 @@ and pm_qos_params.h. This is done because having the available parameters
being runtime configurable or changeable from a driver was seen as too easy to
abuse.
-For each parameter a list of performance requirements is maintained along with
+For each parameter a list of performance requests is maintained along with
an aggregated target value. The aggregated target value is updated with
-changes to the requirement list or elements of the list. Typically the
-aggregated target value is simply the max or min of the requirement values held
+changes to the request list or elements of the list. Typically the
+aggregated target value is simply the max or min of the request values held
in the parameter list elements.
From kernel mode the use of this interface is simple:
-pm_qos_add_requirement(param_id, name, target_value):
-Will insert a named element in the list for that identified PM_QOS parameter
-with the target value. Upon change to this list the new target is recomputed
-and any registered notifiers are called only if the target value is now
-different.
-pm_qos_update_requirement(param_id, name, new_target_value):
-Will search the list identified by the param_id for the named list element and
-then update its target value, calling the notification tree if the aggregated
-target is changed. with that name is already registered.
+handle = pm_qos_add_request(param_class, target_value):
+Will insert an element into the list for that identified PM_QOS class with the
+target value. Upon change to this list the new target is recomputed and any
+registered notifiers are called only if the target value is now different.
+Clients of pm_qos need to save the returned handle.
-pm_qos_remove_requirement(param_id, name):
-Will search the identified list for the named element and remove it, after
-removal it will update the aggregate target and call the notification tree if
-the target was changed as a result of removing the named requirement.
+void pm_qos_update_request(handle, new_target_value):
+Will update the list element pointed to by the handle with the new target value
+and recompute the new aggregated target, calling the notification tree if the
+target is changed.
+
+void pm_qos_remove_request(handle):
+Will remove the element. After removal it will update the aggregate target and
+call the notification tree if the target was changed as a result of removing
+the request.
From user mode:
-Only processes can register a pm_qos requirement. To provide for automatic
-cleanup for process the interface requires the process to register its
-parameter requirements in the following way:
+Only processes can register a pm_qos request. To provide for automatic
+cleanup of a process, the interface requires the process to register its
+parameter requests in the following way:
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]
As long as the device node is held open that process has a registered
-requirement on the parameter. The name of the requirement is "process_<PID>"
-derived from the current->pid from within the open system call.
+request on the parameter.
-To change the requested target value the process needs to write a s32 value to
-the open device node. This translates to a pm_qos_update_requirement call.
+To change the requested target value the process needs to write an s32 value to
+the open device node. Alternatively the user mode program could write a hex
+string for the value using 10 char long format e.g. "0x12345678". This
+translates to a pm_qos_update_request call.
To remove the user mode request for a target value simply close the device
node.
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5939e7f..c3817e1 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -698,7 +698,7 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset)
"max_cstate: C%d\n"
"maximum allowed latency: %d usec\n",
pr->power.state ? pr->power.state - pr->power.states : 0,
- max_cstate, pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY));
+ max_cstate, pm_qos_request(PM_QOS_CPU_DMA_LATENCY));
seq_puts(seq, "states:\n");
diff --git a/drivers/cpuidle/governors/ladder.c b/drivers/cpuidle/governors/ladder.c
index 1c1ceb4..12c9890 100644
--- a/drivers/cpuidle/governors/ladder.c
+++ b/drivers/cpuidle/governors/ladder.c
@@ -67,7 +67,7 @@ static int ladder_select_state(struct cpuidle_device *dev)
struct ladder_device *ldev = &__get_cpu_var(ladder_devices);
struct ladder_device_state *last_state;
int last_residency, last_idx = ldev->last_state_idx;
- int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
/* Special case when user has set very strict latency requirement */
if (unlikely(latency_req == 0)) {
--git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 1aea715..61ca939 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -183,7 +183,7 @@ static u64 div_round64(u64 dividend, u32 divisor)
static int menu_select(struct cpuidle_device *dev)
{
struct menu_device *data = &__get_cpu_var(menu_devices);
- int latency_req = pm_qos_requirement(PM_QOS_CPU_DMA_LATENCY);
+ int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
int i;
int multiplier;
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index fb8fc7d..021e1dd 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -2524,12 +2524,12 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
* excessive C-state transition latencies result in
* dropped transactions.
*/
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name, 55);
+ pm_qos_update_request(
+ adapter->netdev->pm_qos_req, 55);
} else {
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name,
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(
+ adapter->netdev->pm_qos_req,
+ PM_QOS_DEFAULT_VALUE);
}
}
@@ -2824,8 +2824,8 @@ int e1000e_up(struct e1000_adapter *adapter)
/* DMA latency requirement to workaround early-receive/jumbo issue */
if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name,
+ adapter->netdev->pm_qos_req =
+ pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
/* hardware has been reset, we need to reload some things */
@@ -2887,9 +2887,11 @@ void e1000e_down(struct e1000_adapter *adapter)
e1000_clean_tx_ring(adapter);
e1000_clean_rx_ring(adapter);
- if (adapter->flags & FLAG_HAS_ERT)
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- adapter->netdev->name);
+ if (adapter->flags & FLAG_HAS_ERT) {
+ pm_qos_remove_request(
+ adapter->netdev->pm_qos_req);
+ adapter->netdev->pm_qos_req = NULL;
+ }
/*
* TODO: for power management, we could drop the link and
diff --git a/drivers/net/igbvf/netdev.c b/drivers/net/igbvf/netdev.c
index 1b1edad..f16e981 100644
--- a/drivers/net/igbvf/netdev.c
+++ b/drivers/net/igbvf/netdev.c
@@ -48,6 +48,7 @@
#define DRV_VERSION "1.0.0-k0"
char igbvf_driver_name[] = "igbvf";
const char igbvf_driver_version[] = DRV_VERSION;
+struct pm_qos_request_list *igbvf_driver_pm_qos_req;
static const char igbvf_driver_string[] =
"Intel(R) Virtual Function Network Driver";
static const char igbvf_copyright[] = "Copyright (c) 2009 Intel Corporation.";
@@ -2899,7 +2900,7 @@ static int __init igbvf_init_module(void)
printk(KERN_INFO "%s\n", igbvf_copyright);
ret = pci_register_driver(&igbvf_driver);
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name,
+ igbvf_driver_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
return ret;
@@ -2915,7 +2916,8 @@ module_init(igbvf_init_module);
static void __exit igbvf_exit_module(void)
{
pci_unregister_driver(&igbvf_driver);
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, igbvf_driver_name);
+ pm_qos_remove_request(igbvf_driver_pm_qos_req);
+ igbvf_driver_pm_qos_req = NULL;
}
module_exit(igbvf_exit_module);
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 9b72c45..2b05fe5 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -174,6 +174,8 @@ that only one external action is invoked at a time.
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation"
+struct pm_qos_request_list *ipw2100_pm_qos_req;
+
/* Debugging stuff */
#ifdef CONFIG_IPW2100_DEBUG
#define IPW2100_RX_DEBUG /* Reception debugging */
@@ -1739,7 +1741,7 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
/* the ipw2100 hardware really doesn't want power management delays
* longer than 175usec
*/
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175);
+ pm_qos_update_request(ipw2100_pm_qos_req, 175);
/* If the interrupt is enabled, turn it off... */
spin_lock_irqsave(&priv->low_lock, flags);
@@ -1887,8 +1889,7 @@ static void ipw2100_down(struct ipw2100_priv *priv)
ipw2100_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->low_lock, flags);
- pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
- PM_QOS_DEFAULT_VALUE);
+ pm_qos_update_request(ipw2100_pm_qos_req, PM_QOS_DEFAULT_VALUE);
/* We have to signal any supplicant if we are disassociating */
if (associated)
@@ -6669,7 +6670,7 @@ static int __init ipw2100_init(void)
if (ret)
goto out;
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100",
+ ipw2100_pm_qos_req = pm_qos_add_request(PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
#ifdef CONFIG_IPW2100_DEBUG
ipw2100_debug_level = debug;
@@ -6692,7 +6693,7 @@ static void __exit ipw2100_exit(void)
&driver_attr_debug_level);
#endif
pci_unregister_driver(&ipw2100_pci_driver);
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100");
+ pm_qos_remove_request(ipw2100_pm_qos_req);
}
module_init(ipw2100_init);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index fa8b476..3857517 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -31,6 +31,7 @@
#include <linux/if_link.h>
#ifdef __KERNEL__
+#include <linux/pm_qos_params.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/mm.h>
@@ -711,6 +712,9 @@ struct net_device {
* the interface.
*/
char name[IFNAMSIZ];
+
+ struct pm_qos_request_list *pm_qos_req;
+
/* device name hash chain */
struct hlist_node name_hlist;
/* snmp alias */
diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index d74f75e..8ba440e 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -14,12 +14,14 @@
#define PM_QOS_NUM_CLASSES 4
#define PM_QOS_DEFAULT_VALUE -1
-int pm_qos_add_requirement(int qos, char *name, s32 value);
-int pm_qos_update_requirement(int qos, char *name, s32 new_value);
-void pm_qos_remove_requirement(int qos, char *name);
+struct pm_qos_request_list;
-int pm_qos_requirement(int qos);
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value);
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+ s32 new_value);
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
-int pm_qos_add_notifier(int qos, struct notifier_block *notifier);
-int pm_qos_remove_notifier(int qos, struct notifier_block *notifier);
+int pm_qos_request(int pm_qos_class);
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
+int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8b611a5..dd76cde 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -29,6 +29,7 @@
#include <linux/poll.h>
#include <linux/mm.h>
#include <linux/bitops.h>
+#include <linux/pm_qos_params.h>
#define snd_pcm_substream_chip(substream) ((substream)->private_data)
#define snd_pcm_chip(pcm) ((pcm)->private_data)
@@ -365,7 +366,7 @@ struct snd_pcm_substream {
int number;
char name[32]; /* substream name */
int stream; /* stream (direction) */
- char latency_id[20]; /* latency identifier */
+ struct pm_qos_request_list *latency_pm_qos_req; /* pm_qos request */
size_t buffer_bytes_max; /* limit ring buffer size */
struct snd_dma_buffer dma_buffer;
unsigned int dma_buf_id;
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 3db49b9..a1aea04 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -2,7 +2,7 @@
* This module exposes the interface to kernel space for specifying
* QoS dependencies. It provides infrastructure for registration of:
*
- * Dependents on a QoS value : register requirements
+ * Dependents on a QoS value : register requests
* Watchers of QoS value : get notified when target QoS value changes
*
* This QoS design is best effort based. Dependents register their QoS needs.
@@ -14,19 +14,21 @@
* timeout: usec <-- currently not used.
* throughput: kbs (kilo byte / sec)
*
- * There are lists of pm_qos_objects each one wrapping requirements, notifiers
+ * There are lists of pm_qos_objects each one wrapping requests, notifiers
*
- * User mode requirements on a QOS parameter register themselves to the
+ * User mode requests on a QOS parameter register themselves to the
* subsystem by opening the device node /dev/... and writing there request to
* the node. As long as the process holds a file handle open to the node the
* client continues to be accounted for. Upon file release the usermode
- * requirement is removed and a new qos target is computed. This way when the
- * requirement that the application has is cleaned up when closes the file
+ * request is removed and a new qos target is computed. This way when the
+ * request that the application has is cleaned up when closes the file
* pointer or exits the pm_qos_object will get an opportunity to clean up.
*
* Mark Gross <mgross@linux.intel.com>
*/
+/*#define DEBUG*/
+
#include <linux/pm_qos_params.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
@@ -42,25 +44,25 @@
#include <linux/uaccess.h>
/*
- * locking rule: all changes to requirements or notifiers lists
+ * locking rule: all changes to requests or notifiers lists
* or pm_qos_object list and pm_qos_objects need to happen with pm_qos_lock
* held, taken with _irqsave. One lock to rule them all
*/
-struct requirement_list {
+struct pm_qos_request_list {
struct list_head list;
union {
s32 value;
s32 usec;
s32 kbps;
};
- char *name;
+ int pm_qos_class;
};
static s32 max_compare(s32 v1, s32 v2);
static s32 min_compare(s32 v1, s32 v2);
struct pm_qos_object {
- struct requirement_list requirements;
+ struct pm_qos_request_list requests;
struct blocking_notifier_head *notifiers;
struct miscdevice pm_qos_power_miscdev;
char *name;
@@ -72,7 +74,7 @@ struct pm_qos_object {
static struct pm_qos_object null_pm_qos;
static BLOCKING_NOTIFIER_HEAD(cpu_dma_lat_notifier);
static struct pm_qos_object cpu_dma_pm_qos = {
- .requirements = {LIST_HEAD_INIT(cpu_dma_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(cpu_dma_pm_qos.requests.list)},
.notifiers = &cpu_dma_lat_notifier,
.name = "cpu_dma_latency",
.default_value = 2000 * USEC_PER_SEC,
@@ -82,7 +84,7 @@ static struct pm_qos_object cpu_dma_pm_qos = {
static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
static struct pm_qos_object network_lat_pm_qos = {
- .requirements = {LIST_HEAD_INIT(network_lat_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(network_lat_pm_qos.requests.list)},
.notifiers = &network_lat_notifier,
.name = "network_latency",
.default_value = 2000 * USEC_PER_SEC,
@@ -93,8 +95,7 @@ static struct pm_qos_object network_lat_pm_qos = {
static BLOCKING_NOTIFIER_HEAD(network_throughput_notifier);
static struct pm_qos_object network_throughput_pm_qos = {
- .requirements =
- {LIST_HEAD_INIT(network_throughput_pm_qos.requirements.list)},
+ .requests = {LIST_HEAD_INIT(network_throughput_pm_qos.requests.list)},
.notifiers = &network_throughput_notifier,
.name = "network_throughput",
.default_value = 0,
@@ -135,31 +136,34 @@ static s32 min_compare(s32 v1, s32 v2)
}
-static void update_target(int target)
+static void update_target(int pm_qos_class)
{
s32 extreme_value;
- struct requirement_list *node;
+ struct pm_qos_request_list *node;
unsigned long flags;
int call_notifier = 0;
spin_lock_irqsave(&pm_qos_lock, flags);
- extreme_value = pm_qos_array[target]->default_value;
+ extreme_value = pm_qos_array[pm_qos_class]->default_value;
list_for_each_entry(node,
- &pm_qos_array[target]->requirements.list, list) {
- extreme_value = pm_qos_array[target]->comparitor(
+ &pm_qos_array[pm_qos_class]->requests.list, list) {
+ extreme_value = pm_qos_array[pm_qos_class]->comparitor(
extreme_value, node->value);
}
- if (atomic_read(&pm_qos_array[target]->target_value) != extreme_value) {
+ if (atomic_read(&pm_qos_array[pm_qos_class]->target_value) !=
+ extreme_value) {
call_notifier = 1;
- atomic_set(&pm_qos_array[target]->target_value, extreme_value);
- pr_debug(KERN_ERR "new target for qos %d is %d\n", target,
- atomic_read(&pm_qos_array[target]->target_value));
+ atomic_set(&pm_qos_array[pm_qos_class]->target_value,
+ extreme_value);
+ pr_debug(KERN_ERR "new target for qos %d is %d\n", pm_qos_class,
+ atomic_read(&pm_qos_array[pm_qos_class]->target_value));
}
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (call_notifier)
- blocking_notifier_call_chain(pm_qos_array[target]->notifiers,
- (unsigned long) extreme_value, NULL);
+ blocking_notifier_call_chain(
+ pm_qos_array[pm_qos_class]->notifiers,
+ (unsigned long) extreme_value, NULL);
}
static int register_pm_qos_misc(struct pm_qos_object *qos)
@@ -185,125 +189,110 @@ static int find_pm_qos_object_by_minor(int minor)
}
/**
- * pm_qos_requirement - returns current system wide qos expectation
+ * pm_qos_request - returns current system wide qos expectation
* @pm_qos_class: identification of which qos value is requested
*
* This function returns the current target value in an atomic manner.
*/
-int pm_qos_requirement(int pm_qos_class)
+int pm_qos_request(int pm_qos_class)
{
return atomic_read(&pm_qos_array[pm_qos_class]->target_value);
}
-EXPORT_SYMBOL_GPL(pm_qos_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_request);
/**
- * pm_qos_add_requirement - inserts new qos request into the list
+ * pm_qos_add_request - inserts new qos request into the list
* @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
* @value: defines the qos request
*
* This function inserts a new entry in the pm_qos_class list of requested qos
* performance characteristics. It recomputes the aggregate QoS expectations
- * for the pm_qos_class of parameters.
+ * for the pm_qos_class of parameters, and returns the pm_qos_request list
+ * element as a handle for use in updating and removal. Call needs to save
+ * this handle for later use.
*/
-int pm_qos_add_requirement(int pm_qos_class, char *name, s32 value)
+struct pm_qos_request_list *pm_qos_add_request(int pm_qos_class, s32 value)
{
- struct requirement_list *dep;
+ struct pm_qos_request_list *dep;
unsigned long flags;
- dep = kzalloc(sizeof(struct requirement_list), GFP_KERNEL);
+ dep = kzalloc(sizeof(struct pm_qos_request_list), GFP_KERNEL);
if (dep) {
if (value == PM_QOS_DEFAULT_VALUE)
dep->value = pm_qos_array[pm_qos_class]->default_value;
else
dep->value = value;
- dep->name = kstrdup(name, GFP_KERNEL);
- if (!dep->name)
- goto cleanup;
+ dep->pm_qos_class = pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
list_add(&dep->list,
- &pm_qos_array[pm_qos_class]->requirements.list);
+ &pm_qos_array[pm_qos_class]->requests.list);
spin_unlock_irqrestore(&pm_qos_lock, flags);
update_target(pm_qos_class);
-
- return 0;
}
-cleanup:
- kfree(dep);
- return -ENOMEM;
+ return dep;
}
-EXPORT_SYMBOL_GPL(pm_qos_add_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_add_request);
/**
- * pm_qos_update_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_update_request - modifies an existing qos request
+ * @pm_qos_req : handle to list element holding a pm_qos request to use
* @value: defines the qos request
*
- * Updates an existing qos requirement for the pm_qos_class of parameters along
+ * Updates an existing qos request for the pm_qos_class of parameters along
* with updating the target pm_qos_class value.
*
- * If the named request isn't in the list then no change is made.
+ * Attempts are made to make this code callable on hot code paths.
*/
-int pm_qos_update_requirement(int pm_qos_class, char *name, s32 new_value)
+void pm_qos_update_request(struct pm_qos_request_list *pm_qos_req,
+ s32 new_value)
{
unsigned long flags;
- struct requirement_list *node;
int pending_update = 0;
+ s32 temp;
spin_lock_irqsave(&pm_qos_lock, flags);
- list_for_each_entry(node,
- &pm_qos_array[pm_qos_class]->requirements.list, list) {
- if (strcmp(node->name, name) == 0) {
- if (new_value == PM_QOS_DEFAULT_VALUE)
- node->value =
- pm_qos_array[pm_qos_class]->default_value;
- else
- node->value = new_value;
- pending_update = 1;
- break;
- }
+ if (new_value == PM_QOS_DEFAULT_VALUE)
+ temp = pm_qos_array[pm_qos_req->pm_qos_class]->default_value;
+ else
+ temp = new_value;
+
+ if (temp != pm_qos_req->value) {
+ pending_update = 1;
+ pm_qos_req->value = temp;
}
spin_unlock_irqrestore(&pm_qos_lock, flags);
if (pending_update)
- update_target(pm_qos_class);
-
- return 0;
+ update_target(pm_qos_req->pm_qos_class);
}
-EXPORT_SYMBOL_GPL(pm_qos_update_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_update_request);
/**
- * pm_qos_remove_requirement - modifies an existing qos request
- * @pm_qos_class: identifies which list of qos request to us
- * @name: identifies the request
+ * pm_qos_remove_request - modifies an existing qos request
+ * @pm_qos_req: handle to request list element
*
- * Will remove named qos request from pm_qos_class list of parameters and
- * recompute the current target value for the pm_qos_class.
+ * Will remove pm qos request from the list of requests and
+ * recompute the current target value for the pm_qos_class. Call this
+ * on slow code paths.
*/
-void pm_qos_remove_requirement(int pm_qos_class, char *name)
+void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req)
{
unsigned long flags;
- struct requirement_list *node;
- int pending_update = 0;
+ int qos_class;
+
+ if (pm_qos_req == NULL)
+ return;
+ /* silent return to keep pcm code cleaner */
+ qos_class = pm_qos_req->pm_qos_class;
spin_lock_irqsave(&pm_qos_lock, flags);
- list_for_each_entry(node,
- &pm_qos_array[pm_qos_class]->requirements.list, list) {
- if (strcmp(node->name, name) == 0) {
- kfree(node->name);
- list_del(&node->list);
- kfree(node);
- pending_update = 1;
- break;
- }
- }
+ list_del(&pm_qos_req->list);
+ kfree(pm_qos_req);
spin_unlock_irqrestore(&pm_qos_lock, flags);
- if (pending_update)
- update_target(pm_qos_class);
+ update_target(qos_class);
}
-EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
+EXPORT_SYMBOL_GPL(pm_qos_remove_request);
/**
* pm_qos_add_notifier - sets notification entry for changes to target value
@@ -313,7 +302,7 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_requirement);
* will register the notifier into a notification chain that gets called
* upon changes to the pm_qos_class target value.
*/
- int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
{
int retval;
@@ -343,21 +332,16 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
}
EXPORT_SYMBOL_GPL(pm_qos_remove_notifier);
-#define PID_NAME_LEN 32
-
static int pm_qos_power_open(struct inode *inode, struct file *filp)
{
- int ret;
long pm_qos_class;
- char name[PID_NAME_LEN];
pm_qos_class = find_pm_qos_object_by_minor(iminor(inode));
if (pm_qos_class >= 0) {
- filp->private_data = (void *)pm_qos_class;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- ret = pm_qos_add_requirement(pm_qos_class, name,
- PM_QOS_DEFAULT_VALUE);
- if (ret >= 0)
+ filp->private_data = (void *) pm_qos_add_request(pm_qos_class,
+ PM_QOS_DEFAULT_VALUE);
+
+ if (filp->private_data)
return 0;
}
return -EPERM;
@@ -365,32 +349,40 @@ static int pm_qos_power_open(struct inode *inode, struct file *filp)
static int pm_qos_power_release(struct inode *inode, struct file *filp)
{
- int pm_qos_class;
- char name[PID_NAME_LEN];
+ struct pm_qos_request_list *req;
- pm_qos_class = (long)filp->private_data;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- pm_qos_remove_requirement(pm_qos_class, name);
+ req = (struct pm_qos_request_list *)filp->private_data;
+ pm_qos_remove_request(req);
return 0;
}
+
static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf,
size_t count, loff_t *f_pos)
{
s32 value;
- int pm_qos_class;
- char name[PID_NAME_LEN];
-
- pm_qos_class = (long)filp->private_data;
- if (count != sizeof(s32))
+ int x;
+ char ascii_value[11];
+ struct pm_qos_request_list *pm_qos_req;
+
+ if (count == sizeof(s32)) {
+ if (copy_from_user(&value, buf, sizeof(s32)))
+ return -EFAULT;
+ } else if (count == 11) { /* len('0x12345678/0') */
+ if (copy_from_user(ascii_value, buf, 11))
+ return -EFAULT;
+ x = sscanf(ascii_value, "%x", &value);
+ if (x != 1)
+ return -EINVAL;
+ pr_debug(KERN_ERR "%s, %d, 0x%x\n", ascii_value, x, value);
+ } else
return -EINVAL;
- if (copy_from_user(&value, buf, sizeof(s32)))
- return -EFAULT;
- snprintf(name, PID_NAME_LEN, "process_%d", current->pid);
- pm_qos_update_requirement(pm_qos_class, name, value);
- return sizeof(s32);
+ pm_qos_req = (struct pm_qos_request_list *)filp->private_data;
+ pm_qos_update_request(pm_qos_req, value);
+
+ return count;
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 4aefa6d..29de196 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -495,7 +495,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
s32 beaconint_us;
if (latency < 0)
- latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);
+ latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
beaconint_us = ieee80211_tu_to_usec(
found->vif.bss_conf.beacon_int);
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 0d428d0..cbe815d 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -648,9 +648,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
substream->number = idx;
substream->stream = stream;
sprintf(substream->name, "subdevice #%i", idx);
- snprintf(substream->latency_id, sizeof(substream->latency_id),
- "ALSA-PCM%d-%d%c%d", pcm->card->number, pcm->device,
- (stream ? 'c' : 'p'), idx);
substream->buffer_bytes_max = UINT_MAX;
if (prev == NULL)
pstr->substream = substream;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 8728876..605c86d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -481,11 +481,13 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
snd_pcm_timer_resolution_change(substream);
runtime->status->state = SNDRV_PCM_STATE_SETUP;
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id);
+ if (substream->latency_pm_qos_req) {
+ pm_qos_remove_request(substream->latency_pm_qos_req);
+ substream->latency_pm_qos_req = NULL;
+ }
if ((usecs = period_to_usecs(runtime)) >= 0)
- pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id, usecs);
+ substream->latency_pm_qos_req = pm_qos_add_request(
+ PM_QOS_CPU_DMA_LATENCY, usecs);
return 0;
_error:
/* hardware might be unuseable from this time,
@@ -540,8 +542,8 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
if (substream->ops->hw_free)
result = substream->ops->hw_free(substream);
runtime->status->state = SNDRV_PCM_STATE_OPEN;
- pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
- substream->latency_id);
+ pm_qos_remove_request(substream->latency_pm_qos_req);
+ substream->latency_pm_qos_req = NULL;
return result;
}
--
1.6.3.3
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430
2010-05-04 14:30 ` mark gross
@ 2010-05-05 23:59 ` Rafael J. Wysocki
0 siblings, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2010-05-05 23:59 UTC (permalink / raw)
To: mgross
Cc: Kevin Hilman, aili, dwalker, tiwai, bruce.w.allan, davidb, mcgrof,
pavel, linux-pm, lkml, NetDev, Johannes Berg,
ACPI Devel Maling List, Len Brown, John W. Linville
On Tuesday 04 May 2010, mark gross wrote:
> On Sat, May 01, 2010 at 01:08:28AM +0200, Rafael J. Wysocki wrote:
> > On Saturday 01 May 2010, mark gross wrote:
> > > On Sat, May 01, 2010 at 12:13:16AM +0200, Rafael J. Wysocki wrote:
> > > > On Friday 30 April 2010, mark gross wrote:
> > > > > The following is a refresh of the PM_QOS implementation, this patch
> > > > > updates some documentation input I got from Randy.
> > > > >
> > > > > This patch changes the string based list management to a handle base
> > > > > implementation to help with the hot path use of pm-qos, it also renames
> > > > > much of the API to use "request" as opposed to "requirement" that was
> > > > > used in the initial implementation. I did this because request more
> > > > > accurately represents what it actually does.
> > > > >
> > > > > Also, I added a string based ABI for users wanting to use a string
> > > > > interface. So if the user writes 0xDDDDDDDD formatted hex it will be
> > > > > accepted by the interface. (someone asked me for it and I don't think
> > > > > it hurts anything.)
> > > > >
> > > > > I really would like to get this refresh taken care of. Its been taking
> > > > > me too long to close this. please review or include it in next.
> > > > >
> > > > > Thanks!
> > > >
> > > > Well, I'd take it to suspend-2.6/linux-next, but first, it touches
> > > > subsystems whose maintainers were not in the Cc list, like the network
> > > > drivers, wireless and ACPI. The changes are trivial, so I hope they don't
> > > > mind.
> > > >
> > > > Second, my tree is based on the Linus' tree rather than linux-next and
> > > > the change in net/mac80211/scan.c doesn't seem to match that. Please tell me
> > > > what I'm supposed to do about that.
> > >
> > > You can waite for monday and I'll send a rebased version to linus' tree.
> > >
> > > I thought linux-next was where folks wanted me to put it.
> > >
> > > I'll email out a new one monday.
> >
> > Great, thanks!
> >
> > Rafael
>
> Sorry I'm late,
>
>
> Signed-off-by: markgross <mgross@linux.intel.com>
Applied to suspend-2.6/linux-next. Please verify the changelog.
Rafael
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2010-05-05 23:58 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-30 21:17 [PATCH]PM QOS refresh against next-20100430 mark gross
-- strict thread matches above, loose matches on Subject: below --
2010-04-30 21:20 mark gross
2010-04-30 22:13 ` Rafael J. Wysocki
2010-04-30 23:05 ` mark gross
2010-04-30 23:08 ` Rafael J. Wysocki
2010-05-04 14:30 ` mark gross
2010-05-05 23:59 ` Rafael J. Wysocki
2010-05-03 16:33 ` Jonathan Corbet
2010-05-03 16:40 ` Kevin Hilman
2010-05-03 16:42 ` Jonathan Corbet
2010-05-03 17:01 ` Kevin Hilman
2010-05-03 17:10 ` Jonathan Corbet
2010-05-03 21:39 ` Matthew Garrett
2010-05-04 4:16 ` Pavel Machek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).