Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: runtime: add tracepoint for runtime_status changes

Existing runtime PM ftrace events (`rpm_suspend`, `rpm_resume`,
`rpm_return_int`) offer limited visibility into the exact timing of device
runtime power state transitions, particularly when asynchronous operations
are involved. When the `rpm_suspend` or `rpm_resume` functions are invoked
with the `RPM_ASYNC` flag, a return value of 0 i.e., success merely
indicates that the device power state request has been queued, not that
the device has yet transitioned.

A new ftrace event, `rpm_status`, is introduced. This event directly logs
the `power.runtime_status` value of a device whenever it changes providing
granular tracking of runtime power state transitions regardless of
synchronous or asynchronous `rpm_suspend` / `rpm_resume` usage.

Signed-off-by: Vilas Bhat <vilasbhat@google.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Vilas Bhat and committed by
Rafael J. Wysocki
015abee4 b7d46644

+43
+1
drivers/base/power/runtime.c
··· 94 94 static void __update_runtime_status(struct device *dev, enum rpm_status status) 95 95 { 96 96 update_pm_runtime_accounting(dev); 97 + trace_rpm_status(dev, status); 97 98 dev->power.runtime_status = status; 98 99 } 99 100
+42
include/trace/events/rpm.h
··· 101 101 __entry->ret) 102 102 ); 103 103 104 + #define RPM_STATUS_STRINGS \ 105 + EM(RPM_INVALID, "RPM_INVALID") \ 106 + EM(RPM_ACTIVE, "RPM_ACTIVE") \ 107 + EM(RPM_RESUMING, "RPM_RESUMING") \ 108 + EM(RPM_SUSPENDED, "RPM_SUSPENDED") \ 109 + EMe(RPM_SUSPENDING, "RPM_SUSPENDING") 110 + 111 + /* Enums require being exported to userspace, for user tool parsing. */ 112 + #undef EM 113 + #undef EMe 114 + #define EM(a, b) TRACE_DEFINE_ENUM(a); 115 + #define EMe(a, b) TRACE_DEFINE_ENUM(a); 116 + 117 + RPM_STATUS_STRINGS 118 + 119 + /* 120 + * Now redefine the EM() and EMe() macros to map the enums to the strings that 121 + * will be printed in the output. 122 + */ 123 + #undef EM 124 + #undef EMe 125 + #define EM(a, b) { a, b }, 126 + #define EMe(a, b) { a, b } 127 + 128 + TRACE_EVENT(rpm_status, 129 + TP_PROTO(struct device *dev, enum rpm_status status), 130 + TP_ARGS(dev, status), 131 + 132 + TP_STRUCT__entry( 133 + __string(name, dev_name(dev)) 134 + __field(int, status) 135 + ), 136 + 137 + TP_fast_assign( 138 + __assign_str(name, dev_name(dev)); 139 + __entry->status = status; 140 + ), 141 + 142 + TP_printk("%s status=%s", __get_str(name), 143 + __print_symbolic(__entry->status, RPM_STATUS_STRINGS)) 144 + ); 145 + 104 146 #endif /* _TRACE_RUNTIME_POWER_H */ 105 147 106 148 /* This part must be outside protection */