* Re: [PATCH]PM QOS refresh against next-20100430 [not found] <20100430212043.GA30315@linux.intel.com> @ 2010-04-30 22:13 ` Rafael J. Wysocki 2010-04-30 23:05 ` mark gross 0 siblings, 1 reply; 5+ 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] 5+ messages in thread
* Re: [PATCH]PM QOS refresh against next-20100430 2010-04-30 22:13 ` [PATCH]PM QOS refresh against next-20100430 Rafael J. Wysocki @ 2010-04-30 23:05 ` mark gross 2010-04-30 23:08 ` Rafael J. Wysocki 0 siblings, 1 reply; 5+ 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] 5+ 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; 5+ 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] 5+ 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; 5+ 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 +- 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 +- 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)) { 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 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] 5+ 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; 5+ 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] 5+ messages in thread
end of thread, other threads:[~2010-05-05 23:59 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20100430212043.GA30315@linux.intel.com>
2010-04-30 22:13 ` [PATCH]PM QOS refresh against next-20100430 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
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).