blob: f335457638aeccfad23a25a0e9e68cee8b02cbaa [file] [log] [blame]
Jon Medhurst15ce78d2014-04-10 09:02:02 +01001/**
Jon Medhurstb1d07442015-05-08 12:04:18 +01002 * Copyright (C) ARM Limited 2010-2015. All rights reserved.
Jon Medhurst15ce78d2014-04-10 09:02:02 +01003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 */
9
10static void marshal_frame(int cpu, int buftype)
11{
12 int frame;
Jon Medhurst96b56152014-10-30 18:01:15 +000013 bool write_cpu;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010014
Jon Medhurst96b56152014-10-30 18:01:15 +000015 if (!per_cpu(gator_buffer, cpu)[buftype])
Jon Medhurst15ce78d2014-04-10 09:02:02 +010016 return;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010017
18 switch (buftype) {
19 case SUMMARY_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000020 write_cpu = false;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010021 frame = FRAME_SUMMARY;
22 break;
23 case BACKTRACE_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000024 write_cpu = true;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010025 frame = FRAME_BACKTRACE;
26 break;
27 case NAME_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000028 write_cpu = true;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010029 frame = FRAME_NAME;
30 break;
31 case COUNTER_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000032 write_cpu = false;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010033 frame = FRAME_COUNTER;
34 break;
35 case BLOCK_COUNTER_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000036 write_cpu = true;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010037 frame = FRAME_BLOCK_COUNTER;
38 break;
39 case ANNOTATE_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000040 write_cpu = false;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010041 frame = FRAME_ANNOTATE;
42 break;
43 case SCHED_TRACE_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000044 write_cpu = true;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010045 frame = FRAME_SCHED_TRACE;
46 break;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010047 case IDLE_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000048 write_cpu = false;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010049 frame = FRAME_IDLE;
50 break;
Jon Medhurste31266f2014-08-04 15:47:44 +010051 case ACTIVITY_BUF:
Jon Medhurst96b56152014-10-30 18:01:15 +000052 write_cpu = false;
Jon Medhurste31266f2014-08-04 15:47:44 +010053 frame = FRAME_ACTIVITY;
54 break;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010055 default:
Jon Medhurst96b56152014-10-30 18:01:15 +000056 write_cpu = false;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010057 frame = -1;
58 break;
59 }
60
Jon Medhurst96b56152014-10-30 18:01:15 +000061 /* add response type */
62 if (gator_response_type > 0)
Jon Medhurst15ce78d2014-04-10 09:02:02 +010063 gator_buffer_write_packed_int(cpu, buftype, gator_response_type);
Jon Medhurst15ce78d2014-04-10 09:02:02 +010064
Jon Medhurst96b56152014-10-30 18:01:15 +000065 /* leave space for 4-byte unpacked length */
Jon Medhurst15ce78d2014-04-10 09:02:02 +010066 per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype];
67
Jon Medhurst96b56152014-10-30 18:01:15 +000068 /* add frame type and core number */
Jon Medhurst15ce78d2014-04-10 09:02:02 +010069 gator_buffer_write_packed_int(cpu, buftype, frame);
Jon Medhurst96b56152014-10-30 18:01:15 +000070 if (write_cpu)
71 gator_buffer_write_packed_int(cpu, buftype, cpu);
Jon Medhurst15ce78d2014-04-10 09:02:02 +010072}
73
74static int buffer_bytes_available(int cpu, int buftype)
75{
76 int remaining, filled;
77
78 filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype];
Jon Medhurst96b56152014-10-30 18:01:15 +000079 if (filled < 0)
Jon Medhurst15ce78d2014-04-10 09:02:02 +010080 filled += gator_buffer_size[buftype];
Jon Medhurst15ce78d2014-04-10 09:02:02 +010081
82 remaining = gator_buffer_size[buftype] - filled;
83
Jon Medhurst96b56152014-10-30 18:01:15 +000084 if (per_cpu(buffer_space_available, cpu)[buftype])
85 /* Give some extra room; also allows space to insert the overflow error packet */
Jon Medhurst15ce78d2014-04-10 09:02:02 +010086 remaining -= 200;
Jon Medhurst96b56152014-10-30 18:01:15 +000087 else
88 /* Hysteresis, prevents multiple overflow messages */
Jon Medhurst15ce78d2014-04-10 09:02:02 +010089 remaining -= 2000;
Jon Medhurst15ce78d2014-04-10 09:02:02 +010090
91 return remaining;
92}
93
94static bool buffer_check_space(int cpu, int buftype, int bytes)
95{
96 int remaining = buffer_bytes_available(cpu, buftype);
97
Jon Medhurst96b56152014-10-30 18:01:15 +000098 if (remaining < bytes)
Jon Medhurst15ce78d2014-04-10 09:02:02 +010099 per_cpu(buffer_space_available, cpu)[buftype] = false;
Jon Medhurst96b56152014-10-30 18:01:15 +0000100 else
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100101 per_cpu(buffer_space_available, cpu)[buftype] = true;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100102
103 return per_cpu(buffer_space_available, cpu)[buftype];
104}
105
106static int contiguous_space_available(int cpu, int buftype)
107{
108 int remaining = buffer_bytes_available(cpu, buftype);
109 int contiguous = gator_buffer_size[buftype] - per_cpu(gator_buffer_write, cpu)[buftype];
Jon Medhurst96b56152014-10-30 18:01:15 +0000110
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100111 if (remaining < contiguous)
112 return remaining;
Jon Medhurst96b56152014-10-30 18:01:15 +0000113 return contiguous;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100114}
115
116static void gator_commit_buffer(int cpu, int buftype, u64 time)
117{
118 int type_length, commit, length, byte;
119 unsigned long flags;
120
121 if (!per_cpu(gator_buffer, cpu)[buftype])
122 return;
123
Jon Medhurst96b56152014-10-30 18:01:15 +0000124 /* post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload */
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100125 local_irq_save(flags);
126 type_length = gator_response_type ? 1 : 0;
127 commit = per_cpu(gator_buffer_commit, cpu)[buftype];
128 length = per_cpu(gator_buffer_write, cpu)[buftype] - commit;
Jon Medhurst96b56152014-10-30 18:01:15 +0000129 if (length < 0)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100130 length += gator_buffer_size[buftype];
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100131 length = length - type_length - sizeof(s32);
132
133 if (length <= FRAME_HEADER_SIZE) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000134 /* Nothing to write, only the frame header is present */
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100135 local_irq_restore(flags);
136 return;
137 }
138
Jon Medhurst96b56152014-10-30 18:01:15 +0000139 for (byte = 0; byte < sizeof(s32); byte++)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100140 per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100141
142 per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
143
144 if (gator_live_rate > 0) {
Jon Medhurst96b56152014-10-30 18:01:15 +0000145 while (time > per_cpu(gator_buffer_commit_time, cpu))
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100146 per_cpu(gator_buffer_commit_time, cpu) += gator_live_rate;
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100147 }
148
149 marshal_frame(cpu, buftype);
150 local_irq_restore(flags);
151
Jon Medhurst96b56152014-10-30 18:01:15 +0000152 /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100153 if (per_cpu(in_scheduler_context, cpu)) {
154#ifndef CONFIG_PREEMPT_RT_FULL
Jon Medhurst96b56152014-10-30 18:01:15 +0000155 /* mod_timer can not be used in interrupt context in RT-Preempt full */
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100156 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
157#endif
158 } else {
159 up(&gator_buffer_wake_sem);
160 }
161}
162
163static void buffer_check(int cpu, int buftype, u64 time)
164{
165 int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype];
Jon Medhurst96b56152014-10-30 18:01:15 +0000166
167 if (filled < 0)
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100168 filled += gator_buffer_size[buftype];
Jon Medhurst96b56152014-10-30 18:01:15 +0000169 if (filled >= ((gator_buffer_size[buftype] * 3) / 4))
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100170 gator_commit_buffer(cpu, buftype, time);
Jon Medhurst15ce78d2014-04-10 09:02:02 +0100171}