PM Quality Of Service Interface
该接口为驱动程序、子系统和用户空间应用程序提供了一个内核和用户模式接口,用于在一个参数上注册性能期望。
有两个不同的PM QoS框架可用:
- CPU延迟QoS。
- 每个设备的PM QoS框架提供了管理每个设备延迟约束和PM QoS标志的API。
PM QoS框架中使用的延迟单位是微秒(usec)。
1. PM QoS框架
维护一个全局的CPU延迟QoS请求列表,以及一个聚合(有效)目标值。随着请求列表或列表元素的更改,聚合目标值将进行更新。对于CPU延迟QoS,聚合目标值只是列表元素中持有的请求值的最小值。
注意:聚合目标值被实现为原子变量,因此读取聚合值不需要任何锁定机制。
从内核空间使用此接口很简单:
void cpu_latency_qos_add_request(handle, target_value):
将带有目标值的元素插入到CPU延迟QoS列表中。在更改此列表时,只有当目标值发生变化时,才会重新计算新的目标值并调用任何注册的通知器。PM QoS的客户端需要保存返回的句柄,以便将来在其他PM QoS API函数中使用。
void cpu_latency_qos_update_request(handle, new_target_value):
使用新的目标值更新由句柄指向的列表元素,并重新计算新的聚合目标,如果目标发生变化,则调用通知树。
void cpu_latency_qos_remove_request(handle):
删除元素。删除后,将更新聚合目标,并在由于删除请求而导致目标发生变化时调用通知树。
int cpu_latency_qos_limit():
返回CPU延迟QoS的聚合值。
int cpu_latency_qos_request_active(handle):
返回请求是否仍处于活动状态,即尚未从CPU延迟QoS列表中删除。
int cpu_latency_qos_add_notifier(notifier):
将通知回调函数添加到CPU延迟QoS中。当CPU延迟QoS的聚合值发生变化时,将调用此回调。
int cpu_latency_qos_remove_notifier(notifier):
从CPU延迟QoS中删除通知回调函数。
2. PM QoS每设备延迟和标志框架
对于每个设备,有三个PM QoS请求列表。其中两个与恢复延迟和活动状态延迟容忍度(以微秒为单位)的聚合目标一起维护,第三个用于PM QoS标志。在请求列表发生更改时,值将进行更新。
恢复延迟和活动状态延迟容忍度的目标值只是参数列表元素中持有的请求值的最小值。PM QoS标志的聚合值是所有列表元素值的按位或(gather)。目前定义了一个设备PM QoS标志:PM_QOS_FLAG_NO_POWER_OFF。
注意:聚合目标值的实现方式使得读取聚合值不需要任何锁定机制。
从内核模式使用此接口的方式如下:
int dev_pm_qos_add_request(device, handle, type, value):
将带有目标值的元素插入到标识设备的列表中。在更改此列表时,只有当目标值发生变化时,才会重新计算新的目标值并调用任何注册的通知器。dev_pm_qos的客户端需要保存句柄,以便将来在其他dev_pm_qos API函数中使用。
int dev_pm_qos_update_request(handle, new_value):
使用新的目标值更新由句柄指向的列表元素,并重新计算新的聚合目标,如果目标发生变化,则调用通知树。
int dev_pm_qos_remove_request(handle):
删除元素。删除后,将更新聚合目标,并在由于删除请求而导致目标发生变化时调用通知树。
s32 dev_pm_qos_read_value(device, type):
返回给定设备约束列表的聚合值。
enum pm_qos_flags_status dev_pm_qos_flags(device, mask)
检查给定设备的PM QoS标志与给定标志掩码的匹配情况。返回值的含义如下:
- PM_QOS_FLAGS_ALL:掩码中的所有标志都已设置。
- PM_QOS_FLAGS_SOME:掩码中的一些标志已设置。
- PM_QOS_FLAGS_NONE:掩码中的没有标志被设置。
- PM_QOS_FLAGS_UNDEFINED:设备的PM QoS结构尚未初始化或请求列表为空。
int dev_pm_qos_add_ancestor_request(dev, handle, type, value)
为给定设备的第一个直接祖先添加PM QoS请求,该设备的power.ignore_children标志未设置(对于DEV_PM_QOS_RESUME_LATENCY请求)或其power.set_latency_tolerance回调指针不为NULL(对于DEV_PM_QOS_LATENCY_TOLERANCE请求)。
int dev_pm_qos_expose_latency_limit(device, value)
将请求添加到设备的恢复延迟约束的PM QoS列表中,并在设备的power目录下创建sysfs属性pm_qos_resume_latency_us,允许用户空间操作该请求。
void dev_pm_qos_hide_latency_limit(device)
从设备的恢复延迟约束的PM QoS列表中删除由dev_pm_qos_expose_latency_limit()添加的请求,并从设备的power目录中删除sysfs属性pm_qos_resume_latency_us。
int dev_pm_qos_expose_flags(device, value)
将请求添加到设备的PM QoS标志列表中,并在设备的power目录下创建sysfs属性pm_qos_no_power_off,允许用户空间更改PM_QOS_FLAG_NO_POWER_OFF标志的值。
void dev_pm_qos_hide_flags(device)
从设备的PM QoS标志列表中删除由dev_pm_qos_expose_flags()添加的请求,并从设备的power目录中删除sysfs属性pm_qos_no_power_off。
通知机制
每个设备的PM QoS框架具有一个每设备的通知树。
int dev_pm_qos_add_notifier(device, notifier, type):
为设备添加特定请求类型的通知回调函数。
当设备约束列表的聚合值发生变化时,将调用此回调。
int dev_pm_qos_remove_notifier(device, notifier, type):
删除设备的通知回调函数。
活动状态延迟容忍度
活动状态延迟容忍度
该设备PM QoS类型用于支持在运行时切换到节能操作模式的系统。在这些系统中,如果硬件选择的操作模式过于激进地节能,可能会导致软件看到过多的延迟,从而导致软件无法满足某些协议要求、目标帧率或采样率等。
如果对于给定设备,软件可以控制延迟容忍度的机制,则应填充该设备的dev_pm_info结构中的.set_latency_tolerance回调。该回调指向的例程应实现将有效的要求值传递给硬件所需的任何操作。
每当设备的有效延迟容忍度发生变化时,将执行其.set_latency_tolerance()回调,并将有效值传递给它。如果该值为负数,表示设备的延迟容忍度要求列表为空,则期望回调将在可用的情况下将底层硬件延迟容忍度控制机制切换到自主模式。如果该值为PM_QOS_LATENCY_ANY,并且硬件支持特殊的“无要求”设置,则期望回调将使用它。这允许软件阻止硬件根据其电源状态的变化(例如从D3cold到D0的过渡)自动更新设备的延迟容忍度,通常可以在自主延迟容忍度控制模式下完成。
如果设备存在.set_latency_tolerance()回调,则在设备的power目录中将存在sysfs属性pm_qos_latency_tolerance_us。然后,用户空间可以使用该属性为设备指定其延迟容忍度要求(如果有)。将"any"写入该属性表示"没有要求,但不要让硬件控制延迟容忍度",将"auto"写入该属性允许硬件在设备的列表中没有其他内核要求的情况下切换到自主模式。
内核代码可以使用上述描述的函数以及DEV_PM_QOS_LATENCY_TOLERANCE设备PM QoS类型来为设备添加、删除和更新延迟容忍度要求。