PM QOS refresh against next-20100430
Subsystems (9)
PATCH 1/1 PM QOS refresh against next-20100430
The following is a refresh of the PM_QOS implementation, this patch updates some documentation input I got from Randy.
This patch changes the string based list management to a handle base implementation to help with the hot path use of pm-qos, it also renames much of the API to use "request" as opposed to "requirement" that was used in the initial implementation. I did this because request more accurately represents what it actually does.
Also, I added a string based ABI for users wanting to use a string interface. So if the user writes 0xDDDDDDDD formatted hex it will be accepted by the interface. (someone asked me for it and I don't think it hurts anything.)
I really would like to get this refresh taken care of. Its been taking me too long to close this. please review or include it in next.
Thanks!
--mgross
Quoted 1 line
From
c45d8d86f89ac55fbb9a499fbc754e35258bf818Mon Sep 17 00:00:00 2001
From: mgross <[email protected]>
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(-)
Documentation/power/pm_qos_interface.txt +25 -23
@@ -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.
drivers/acpi/processor_idle.c +1 -1
@@ -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" );
drivers/cpuidle/governors/ladder.c +1 -1
@@ -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 )) {
drivers/cpuidle/governors/menu.c +1 -1
@@ -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;
drivers/net/e1000e/netdev.c +12 -10
@@ -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
drivers/net/igbvf/netdev.c +4 -2
@@ -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);
drivers/net/wireless/ipw2x00/ipw2100.c +6 -5
@@ -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);
include/linux/netdevice.h +4 -0
@@ -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 */
include/linux/pm_qos_params.h +8 -6
@@ -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);
include/sound/pcm.h +2 -1
@@ -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;
kernel/pm_qos_params.c +103 -111
392 lines not on this page · raw message
net/mac80211/mlme.c +1 -1
@@ -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);
net/mac80211/scan.c +1 -1
@@ -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),
sound/core/pcm.c +0 -3
@@ -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;
sound/core/pcm_native.c +8 -6
@@ -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; }
Signature · 1 line
1.6.3.3