|  | PM Quality Of Service Interface. | 
|  |  | 
|  | This interface provides a kernel and user mode interface for registering | 
|  | performance expectations by drivers, subsystems and user space applications on | 
|  | one of the parameters. | 
|  |  | 
|  | Two different PM QoS frameworks are available: | 
|  | 1. PM QoS classes for cpu_dma_latency, network_latency, network_throughput. | 
|  | 2. the per-device PM QoS framework provides the API to manage the per-device latency | 
|  | constraints. | 
|  |  | 
|  | Each parameters have defined units: | 
|  | * latency: usec | 
|  | * timeout: usec | 
|  | * throughput: kbs (kilo bit / sec) | 
|  |  | 
|  |  | 
|  | 1. PM QoS framework | 
|  |  | 
|  | The infrastructure exposes multiple misc device nodes one per implemented | 
|  | parameter.  The set of parameters implement is defined by pm_qos_power_init() | 
|  | 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 requests is maintained along with | 
|  | an aggregated target value.  The aggregated target value is updated with | 
|  | 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. | 
|  | Note: the aggregated target value is implemented as an atomic variable so that | 
|  | reading the aggregated value does not require any locking mechanism. | 
|  |  | 
|  |  | 
|  | From kernel mode the use of this interface is simple: | 
|  |  | 
|  | void pm_qos_add_request(handle, 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 for future use in other | 
|  | pm_qos API functions. | 
|  |  | 
|  | 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. | 
|  |  | 
|  | int pm_qos_request(param_class): | 
|  | Returns the aggregated value for a given PM QoS class. | 
|  |  | 
|  | int pm_qos_request_active(handle): | 
|  | Returns if the request is still active, i.e. it has not been removed from a | 
|  | PM QoS class constraints list. | 
|  |  | 
|  | int pm_qos_add_notifier(param_class, notifier): | 
|  | Adds a notification callback function to the PM QoS class. The callback is | 
|  | called when the aggregated value for the PM QoS class is changed. | 
|  |  | 
|  | int pm_qos_remove_notifier(int param_class, notifier): | 
|  | Removes the notification callback function for the PM QoS class. | 
|  |  | 
|  |  | 
|  | From user mode: | 
|  | 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 | 
|  | request on the parameter. | 
|  |  | 
|  | 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. | 
|  |  | 
|  |  | 
|  | 2. PM QoS per-device latency framework | 
|  |  | 
|  | For each device a list of performance requests is maintained along with | 
|  | an aggregated target value.  The aggregated target value is updated with | 
|  | 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. | 
|  | Note: the aggregated target value is implemented as an atomic variable so that | 
|  | reading the aggregated value does not require any locking mechanism. | 
|  |  | 
|  |  | 
|  | From kernel mode the use of this interface is the following: | 
|  |  | 
|  | int dev_pm_qos_add_request(device, handle, value): | 
|  | Will insert an element into the list for that identified device 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 dev_pm_qos need to save the handle for future use in other | 
|  | dev_pm_qos API functions. | 
|  |  | 
|  | int dev_pm_qos_update_request(handle, new_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 trees if the | 
|  | target is changed. | 
|  |  | 
|  | int dev_pm_qos_remove_request(handle): | 
|  | Will remove the element.  After removal it will update the aggregate target and | 
|  | call the notification trees if the target was changed as a result of removing | 
|  | the request. | 
|  |  | 
|  | s32 dev_pm_qos_read_value(device): | 
|  | Returns the aggregated value for a given device's constraints list. | 
|  |  | 
|  |  | 
|  | Notification mechanisms: | 
|  | The per-device PM QoS framework has 2 different and distinct notification trees: | 
|  | a per-device notification tree and a global notification tree. | 
|  |  | 
|  | int dev_pm_qos_add_notifier(device, notifier): | 
|  | Adds a notification callback function for the device. | 
|  | The callback is called when the aggregated value of the device constraints list | 
|  | is changed. | 
|  |  | 
|  | int dev_pm_qos_remove_notifier(device, notifier): | 
|  | Removes the notification callback function for the device. | 
|  |  | 
|  | int dev_pm_qos_add_global_notifier(notifier): | 
|  | Adds a notification callback function in the global notification tree of the | 
|  | framework. | 
|  | The callback is called when the aggregated value for any device is changed. | 
|  |  | 
|  | int dev_pm_qos_remove_global_notifier(notifier): | 
|  | Removes the notification callback function from the global notification tree | 
|  | of the framework. | 
|  |  | 
|  |  | 
|  | From user mode: | 
|  | No API for user space access to the per-device latency constraints is provided | 
|  | yet - still under discussion. | 
|  |  |