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

regulator: Add basic trace facilities

Provide some basic trace facilities to the regulator API. We generate
events on regulator enable, disable and voltage setting over the actual
hardware operations (which are assumed to be the expensive ones which
require interaction with the actual device). This is intended to facilitate
debug of the performance and behaviour with consumers allowing unified
traces to be generated including the regulator operations within the
context of the other components of the system.

For enable we log the explicit delay for the voltage ramp separately to
the interaction with the hardware to highlight the time consumed in I/O.
We should add a similar delay for voltage changes, though there the
relatively small magnitude of the changes in the context of the I/O
costs makes it much less critical for most regulators.

Only hardware interactions are currently traced as the primary focus is
on the performance and synchronisation of actual hardware interactions.
Additional tracepoints for debugging of the logical operations can be
added later if required.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>

authored by

Mark Brown and committed by
Liam Girdwood
02fa3ec0 3a93f2a9

+158
+17
drivers/regulator/core.c
··· 25 25 #include <linux/regulator/driver.h> 26 26 #include <linux/regulator/machine.h> 27 27 28 + #define CREATE_TRACE_POINTS 29 + #include <trace/events/regulator.h> 30 + 28 31 #include "dummy.h" 29 32 30 33 #define REGULATOR_VERSION "0.5" ··· 1313 1310 delay = 0; 1314 1311 } 1315 1312 1313 + trace_regulator_enable(rdev_get_name(rdev)); 1314 + 1316 1315 /* Allow the regulator to ramp; it would be useful 1317 1316 * to extend this for bulk operations so that the 1318 1317 * regulators can ramp together. */ ··· 1322 1317 if (ret < 0) 1323 1318 return ret; 1324 1319 1320 + trace_regulator_enable_delay(rdev_get_name(rdev)); 1321 + 1325 1322 if (delay >= 1000) { 1326 1323 mdelay(delay / 1000); 1327 1324 udelay(delay % 1000); 1328 1325 } else if (delay) { 1329 1326 udelay(delay); 1330 1327 } 1328 + 1329 + trace_regulator_enable_complete(rdev_get_name(rdev)); 1331 1330 1332 1331 } else if (ret < 0) { 1333 1332 printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", ··· 1388 1379 /* we are last user */ 1389 1380 if (_regulator_can_change_status(rdev) && 1390 1381 rdev->desc->ops->disable) { 1382 + trace_regulator_disable(rdev_get_name(rdev)); 1383 + 1391 1384 ret = rdev->desc->ops->disable(rdev); 1392 1385 if (ret < 0) { 1393 1386 printk(KERN_ERR "%s: failed to disable %s\n", 1394 1387 __func__, rdev_get_name(rdev)); 1395 1388 return ret; 1396 1389 } 1390 + 1391 + trace_regulator_disable_complete(rdev_get_name(rdev)); 1397 1392 1398 1393 _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 1399 1394 NULL); ··· 1658 1645 regulator->min_uV = min_uV; 1659 1646 regulator->max_uV = max_uV; 1660 1647 1648 + trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 1649 + 1661 1650 ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, &selector); 1662 1651 1663 1652 if (rdev->desc->ops->list_voltage) 1664 1653 selector = rdev->desc->ops->list_voltage(rdev, selector); 1665 1654 else 1666 1655 selector = -1; 1656 + 1657 + trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector); 1667 1658 1668 1659 out: 1669 1660 _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, NULL);
+141
include/trace/events/regulator.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM regulator 3 + 4 + #if !defined(_TRACE_REGULATOR_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_REGULATOR_H 6 + 7 + #include <linux/ktime.h> 8 + #include <linux/tracepoint.h> 9 + 10 + /* 11 + * Events which just log themselves and the regulator name for enable/disable 12 + * type tracking. 13 + */ 14 + DECLARE_EVENT_CLASS(regulator_basic, 15 + 16 + TP_PROTO(const char *name), 17 + 18 + TP_ARGS(name), 19 + 20 + TP_STRUCT__entry( 21 + __string( name, name ) 22 + ), 23 + 24 + TP_fast_assign( 25 + __assign_str(name, name); 26 + ), 27 + 28 + TP_printk("name=%s", __get_str(name)) 29 + 30 + ); 31 + 32 + DEFINE_EVENT(regulator_basic, regulator_enable, 33 + 34 + TP_PROTO(const char *name), 35 + 36 + TP_ARGS(name) 37 + 38 + ); 39 + 40 + DEFINE_EVENT(regulator_basic, regulator_enable_delay, 41 + 42 + TP_PROTO(const char *name), 43 + 44 + TP_ARGS(name) 45 + 46 + ); 47 + 48 + DEFINE_EVENT(regulator_basic, regulator_enable_complete, 49 + 50 + TP_PROTO(const char *name), 51 + 52 + TP_ARGS(name) 53 + 54 + ); 55 + 56 + DEFINE_EVENT(regulator_basic, regulator_disable, 57 + 58 + TP_PROTO(const char *name), 59 + 60 + TP_ARGS(name) 61 + 62 + ); 63 + 64 + DEFINE_EVENT(regulator_basic, regulator_disable_complete, 65 + 66 + TP_PROTO(const char *name), 67 + 68 + TP_ARGS(name) 69 + 70 + ); 71 + 72 + /* 73 + * Events that take a range of numerical values, mostly for voltages 74 + * and so on. 75 + */ 76 + DECLARE_EVENT_CLASS(regulator_range, 77 + 78 + TP_PROTO(const char *name, int min, int max), 79 + 80 + TP_ARGS(name, min, max), 81 + 82 + TP_STRUCT__entry( 83 + __string( name, name ) 84 + __field( int, min ) 85 + __field( int, max ) 86 + ), 87 + 88 + TP_fast_assign( 89 + __assign_str(name, name); 90 + __entry->min = min; 91 + __entry->max = max; 92 + ), 93 + 94 + TP_printk("name=%s (%d-%d)", __get_str(name), 95 + (int)__entry->min, (int)__entry->max) 96 + ); 97 + 98 + DEFINE_EVENT(regulator_range, regulator_set_voltage, 99 + 100 + TP_PROTO(const char *name, int min, int max), 101 + 102 + TP_ARGS(name, min, max) 103 + 104 + ); 105 + 106 + 107 + /* 108 + * Events that take a single value, mostly for readback and refcounts. 109 + */ 110 + DECLARE_EVENT_CLASS(regulator_value, 111 + 112 + TP_PROTO(const char *name, unsigned int val), 113 + 114 + TP_ARGS(name, val), 115 + 116 + TP_STRUCT__entry( 117 + __string( name, name ) 118 + __field( unsigned int, val ) 119 + ), 120 + 121 + TP_fast_assign( 122 + __assign_str(name, name); 123 + __entry->val = val; 124 + ), 125 + 126 + TP_printk("name=%s, val=%u", __get_str(name), 127 + (int)__entry->val) 128 + ); 129 + 130 + DEFINE_EVENT(regulator_value, regulator_set_voltage_complete, 131 + 132 + TP_PROTO(const char *name, unsigned int value), 133 + 134 + TP_ARGS(name, value) 135 + 136 + ); 137 + 138 + #endif /* _TRACE_POWER_H */ 139 + 140 + /* This part must be outside protection */ 141 + #include <trace/define_trace.h>