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

rtc: Add tracepoints for RTC system

It will be more helpful to add some tracepoints to track RTC actions when
debugging RTC driver. Below sample is that we set/read the RTC time, then
set 2 alarms, so we can see the trace logs:

set/read RTC time:
kworker/0:1-67 [000] 21.814245: rtc_set_time: UTC (1510301580) (0)
kworker/0:1-67 [000] 21.814312: rtc_read_time: UTC (1510301580) (0)

set the first alarm timer:
kworker/0:1-67 [000] 21.829238: rtc_timer_enqueue: RTC timer:(ffffffc15eb49bc8) expires:1510301700000000000 period:0
kworker/0:1-67 [000] 22.018279: rtc_set_alarm: UTC (1510301700) (0)

set the second alarm timer:
kworker/0:1-67 [000] 22.230284: rtc_timer_enqueue: RTC timer:(ffffff80088e6430) expires:1510301820000000000 period:0

the first alarm timer was expired:
kworker/0:1-67 [000] 145.155584: rtc_timer_dequeue: RTC timer:(ffffffc15eb49bc8) expires:1510301700000000000 period:0
kworker/0:1-67 [000] 145.155593: rtc_timer_fired: RTC timer:(ffffffc15eb49bc8) expires:1510301700000000000 period:0
kworker/0:1-67 [000] 145.172504: rtc_set_alarm: UTC (1510301820) (0)

the second alarm timer was expired:
kworker/0:1-67 [000] 269.102353: rtc_timer_dequeue: RTC timer:(ffffff80088e6430) expires:1510301820000000000 period:0
kworker/0:1-67 [000] 269.102360: rtc_timer_fired: RTC timer:(ffffff80088e6430) expires:1510301820000000000 period:0

disable alarm irq:
kworker/0:1-67 [000] 269.102469: rtc_alarm_irq_enable: disable RTC alarm IRQ (0)

Signed-off-by: Baolin Wang <baolin.wang@linaro.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

authored by

Baolin Wang and committed by
Alexandre Belloni
29a1f599 7928b2cb

+236
+30
drivers/rtc/interface.c
··· 17 17 #include <linux/log2.h> 18 18 #include <linux/workqueue.h> 19 19 20 + #define CREATE_TRACE_POINTS 21 + #include <trace/events/rtc.h> 22 + 20 23 static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer); 21 24 static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer); 22 25 ··· 56 53 57 54 err = __rtc_read_time(rtc, tm); 58 55 mutex_unlock(&rtc->ops_lock); 56 + 57 + trace_rtc_read_time(rtc_tm_to_time64(tm), err); 59 58 return err; 60 59 } 61 60 EXPORT_SYMBOL_GPL(rtc_read_time); ··· 92 87 mutex_unlock(&rtc->ops_lock); 93 88 /* A timer might have just expired */ 94 89 schedule_work(&rtc->irqwork); 90 + 91 + trace_rtc_set_time(rtc_tm_to_time64(tm), err); 95 92 return err; 96 93 } 97 94 EXPORT_SYMBOL_GPL(rtc_set_time); ··· 126 119 } 127 120 128 121 mutex_unlock(&rtc->ops_lock); 122 + 123 + trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err); 129 124 return err; 130 125 } 131 126 ··· 325 316 } 326 317 mutex_unlock(&rtc->ops_lock); 327 318 319 + trace_rtc_read_alarm(rtc_tm_to_time64(&alarm->time), err); 328 320 return err; 329 321 } 330 322 EXPORT_SYMBOL_GPL(rtc_read_alarm); ··· 362 352 else 363 353 err = rtc->ops->set_alarm(rtc->dev.parent, alarm); 364 354 355 + trace_rtc_set_alarm(rtc_tm_to_time64(&alarm->time), err); 365 356 return err; 366 357 } 367 358 ··· 417 406 418 407 rtc->aie_timer.enabled = 1; 419 408 timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node); 409 + trace_rtc_timer_enqueue(&rtc->aie_timer); 420 410 } 421 411 mutex_unlock(&rtc->ops_lock); 422 412 return err; ··· 447 435 err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled); 448 436 449 437 mutex_unlock(&rtc->ops_lock); 438 + 439 + trace_rtc_alarm_irq_enable(enabled, err); 450 440 return err; 451 441 } 452 442 EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); ··· 723 709 rtc->pie_enabled = enabled; 724 710 } 725 711 spin_unlock_irqrestore(&rtc->irq_task_lock, flags); 712 + 713 + trace_rtc_irq_set_state(enabled, err); 726 714 return err; 727 715 } 728 716 EXPORT_SYMBOL_GPL(rtc_irq_set_state); ··· 761 745 } 762 746 } 763 747 spin_unlock_irqrestore(&rtc->irq_task_lock, flags); 748 + 749 + trace_rtc_irq_set_freq(freq, err); 764 750 return err; 765 751 } 766 752 EXPORT_SYMBOL_GPL(rtc_irq_set_freq); ··· 797 779 } 798 780 799 781 timerqueue_add(&rtc->timerqueue, &timer->node); 782 + trace_rtc_timer_enqueue(timer); 800 783 if (!next || ktime_before(timer->node.expires, next->expires)) { 801 784 struct rtc_wkalrm alarm; 802 785 int err; ··· 809 790 schedule_work(&rtc->irqwork); 810 791 } else if (err) { 811 792 timerqueue_del(&rtc->timerqueue, &timer->node); 793 + trace_rtc_timer_dequeue(timer); 812 794 timer->enabled = 0; 813 795 return err; 814 796 } ··· 823 803 return; 824 804 825 805 rtc->ops->alarm_irq_enable(rtc->dev.parent, false); 806 + trace_rtc_alarm_irq_enable(0, 0); 826 807 } 827 808 828 809 /** ··· 842 821 { 843 822 struct timerqueue_node *next = timerqueue_getnext(&rtc->timerqueue); 844 823 timerqueue_del(&rtc->timerqueue, &timer->node); 824 + trace_rtc_timer_dequeue(timer); 845 825 timer->enabled = 0; 846 826 if (next == &timer->node) { 847 827 struct rtc_wkalrm alarm; ··· 893 871 /* expire timer */ 894 872 timer = container_of(next, struct rtc_timer, node); 895 873 timerqueue_del(&rtc->timerqueue, &timer->node); 874 + trace_rtc_timer_dequeue(timer); 896 875 timer->enabled = 0; 897 876 if (timer->task.func) 898 877 timer->task.func(timer->task.private_data); 899 878 879 + trace_rtc_timer_fired(timer); 900 880 /* Re-add/fwd periodic timers */ 901 881 if (ktime_to_ns(timer->period)) { 902 882 timer->node.expires = ktime_add(timer->node.expires, 903 883 timer->period); 904 884 timer->enabled = 1; 905 885 timerqueue_add(&rtc->timerqueue, &timer->node); 886 + trace_rtc_timer_enqueue(timer); 906 887 } 907 888 } 908 889 ··· 927 902 928 903 timer = container_of(next, struct rtc_timer, node); 929 904 timerqueue_del(&rtc->timerqueue, &timer->node); 905 + trace_rtc_timer_dequeue(timer); 930 906 timer->enabled = 0; 931 907 dev_err(&rtc->dev, "__rtc_set_alarm: err=%d\n", err); 932 908 goto again; ··· 1018 992 mutex_lock(&rtc->ops_lock); 1019 993 ret = rtc->ops->read_offset(rtc->dev.parent, offset); 1020 994 mutex_unlock(&rtc->ops_lock); 995 + 996 + trace_rtc_read_offset(*offset, ret); 1021 997 return ret; 1022 998 } 1023 999 ··· 1053 1025 mutex_lock(&rtc->ops_lock); 1054 1026 ret = rtc->ops->set_offset(rtc->dev.parent, offset); 1055 1027 mutex_unlock(&rtc->ops_lock); 1028 + 1029 + trace_rtc_set_offset(offset, ret); 1056 1030 return ret; 1057 1031 }
+206
include/trace/events/rtc.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM rtc 3 + 4 + #if !defined(_TRACE_RTC_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_RTC_H 6 + 7 + #include <linux/rtc.h> 8 + #include <linux/tracepoint.h> 9 + 10 + DECLARE_EVENT_CLASS(rtc_time_alarm_class, 11 + 12 + TP_PROTO(time64_t secs, int err), 13 + 14 + TP_ARGS(secs, err), 15 + 16 + TP_STRUCT__entry( 17 + __field(time64_t, secs) 18 + __field(int, err) 19 + ), 20 + 21 + TP_fast_assign( 22 + __entry->secs = secs; 23 + __entry->err = err; 24 + ), 25 + 26 + TP_printk("UTC (%lld) (%d)", 27 + __entry->secs, __entry->err 28 + ) 29 + ); 30 + 31 + DEFINE_EVENT(rtc_time_alarm_class, rtc_set_time, 32 + 33 + TP_PROTO(time64_t secs, int err), 34 + 35 + TP_ARGS(secs, err) 36 + ); 37 + 38 + DEFINE_EVENT(rtc_time_alarm_class, rtc_read_time, 39 + 40 + TP_PROTO(time64_t secs, int err), 41 + 42 + TP_ARGS(secs, err) 43 + ); 44 + 45 + DEFINE_EVENT(rtc_time_alarm_class, rtc_set_alarm, 46 + 47 + TP_PROTO(time64_t secs, int err), 48 + 49 + TP_ARGS(secs, err) 50 + ); 51 + 52 + DEFINE_EVENT(rtc_time_alarm_class, rtc_read_alarm, 53 + 54 + TP_PROTO(time64_t secs, int err), 55 + 56 + TP_ARGS(secs, err) 57 + ); 58 + 59 + TRACE_EVENT(rtc_irq_set_freq, 60 + 61 + TP_PROTO(int freq, int err), 62 + 63 + TP_ARGS(freq, err), 64 + 65 + TP_STRUCT__entry( 66 + __field(int, freq) 67 + __field(int, err) 68 + ), 69 + 70 + TP_fast_assign( 71 + __entry->freq = freq; 72 + __entry->err = err; 73 + ), 74 + 75 + TP_printk("set RTC periodic IRQ frequency:%u (%d)", 76 + __entry->freq, __entry->err 77 + ) 78 + ); 79 + 80 + TRACE_EVENT(rtc_irq_set_state, 81 + 82 + TP_PROTO(int enabled, int err), 83 + 84 + TP_ARGS(enabled, err), 85 + 86 + TP_STRUCT__entry( 87 + __field(int, enabled) 88 + __field(int, err) 89 + ), 90 + 91 + TP_fast_assign( 92 + __entry->enabled = enabled; 93 + __entry->err = err; 94 + ), 95 + 96 + TP_printk("%s RTC 2^N Hz periodic IRQs (%d)", 97 + __entry->enabled ? "enable" : "disable", 98 + __entry->err 99 + ) 100 + ); 101 + 102 + TRACE_EVENT(rtc_alarm_irq_enable, 103 + 104 + TP_PROTO(unsigned int enabled, int err), 105 + 106 + TP_ARGS(enabled, err), 107 + 108 + TP_STRUCT__entry( 109 + __field(unsigned int, enabled) 110 + __field(int, err) 111 + ), 112 + 113 + TP_fast_assign( 114 + __entry->enabled = enabled; 115 + __entry->err = err; 116 + ), 117 + 118 + TP_printk("%s RTC alarm IRQ (%d)", 119 + __entry->enabled ? "enable" : "disable", 120 + __entry->err 121 + ) 122 + ); 123 + 124 + DECLARE_EVENT_CLASS(rtc_offset_class, 125 + 126 + TP_PROTO(long offset, int err), 127 + 128 + TP_ARGS(offset, err), 129 + 130 + TP_STRUCT__entry( 131 + __field(long, offset) 132 + __field(int, err) 133 + ), 134 + 135 + TP_fast_assign( 136 + __entry->offset = offset; 137 + __entry->err = err; 138 + ), 139 + 140 + TP_printk("RTC offset: %ld (%d)", 141 + __entry->offset, __entry->err 142 + ) 143 + ); 144 + 145 + DEFINE_EVENT(rtc_offset_class, rtc_set_offset, 146 + 147 + TP_PROTO(long offset, int err), 148 + 149 + TP_ARGS(offset, err) 150 + ); 151 + 152 + DEFINE_EVENT(rtc_offset_class, rtc_read_offset, 153 + 154 + TP_PROTO(long offset, int err), 155 + 156 + TP_ARGS(offset, err) 157 + ); 158 + 159 + DECLARE_EVENT_CLASS(rtc_timer_class, 160 + 161 + TP_PROTO(struct rtc_timer *timer), 162 + 163 + TP_ARGS(timer), 164 + 165 + TP_STRUCT__entry( 166 + __field(struct rtc_timer *, timer) 167 + __field(ktime_t, expires) 168 + __field(ktime_t, period) 169 + ), 170 + 171 + TP_fast_assign( 172 + __entry->timer = timer; 173 + __entry->expires = timer->node.expires; 174 + __entry->period = timer->period; 175 + ), 176 + 177 + TP_printk("RTC timer:(%p) expires:%lld period:%lld", 178 + __entry->timer, __entry->expires, __entry->period 179 + ) 180 + ); 181 + 182 + DEFINE_EVENT(rtc_timer_class, rtc_timer_enqueue, 183 + 184 + TP_PROTO(struct rtc_timer *timer), 185 + 186 + TP_ARGS(timer) 187 + ); 188 + 189 + DEFINE_EVENT(rtc_timer_class, rtc_timer_dequeue, 190 + 191 + TP_PROTO(struct rtc_timer *timer), 192 + 193 + TP_ARGS(timer) 194 + ); 195 + 196 + DEFINE_EVENT(rtc_timer_class, rtc_timer_fired, 197 + 198 + TP_PROTO(struct rtc_timer *timer), 199 + 200 + TP_ARGS(timer) 201 + ); 202 + 203 + #endif /* _TRACE_RTC_H */ 204 + 205 + /* This part must be outside protection */ 206 + #include <trace/define_trace.h>