2 * Copyright (C) ARM Limited 2010-2015. All rights reserved.
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.
10 static void marshal_frame(int cpu, int buftype)
15 if (!per_cpu(gator_buffer, cpu)[buftype])
21 frame = FRAME_SUMMARY;
25 frame = FRAME_BACKTRACE;
33 frame = FRAME_COUNTER;
35 case BLOCK_COUNTER_BUF:
37 frame = FRAME_BLOCK_COUNTER;
41 frame = FRAME_ANNOTATE;
45 frame = FRAME_SCHED_TRACE;
53 frame = FRAME_ACTIVITY;
61 /* add response type */
62 if (gator_response_type > 0)
63 gator_buffer_write_packed_int(cpu, buftype, gator_response_type);
65 /* leave space for 4-byte unpacked length */
66 per_cpu(gator_buffer_write, cpu)[buftype] = (per_cpu(gator_buffer_write, cpu)[buftype] + sizeof(s32)) & gator_buffer_mask[buftype];
68 /* add frame type and core number */
69 gator_buffer_write_packed_int(cpu, buftype, frame);
71 gator_buffer_write_packed_int(cpu, buftype, cpu);
74 static int buffer_bytes_available(int cpu, int buftype)
76 int remaining, filled;
78 filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_read, cpu)[buftype];
80 filled += gator_buffer_size[buftype];
82 remaining = gator_buffer_size[buftype] - filled;
84 if (per_cpu(buffer_space_available, cpu)[buftype])
85 /* Give some extra room; also allows space to insert the overflow error packet */
88 /* Hysteresis, prevents multiple overflow messages */
94 static bool buffer_check_space(int cpu, int buftype, int bytes)
96 int remaining = buffer_bytes_available(cpu, buftype);
98 if (remaining < bytes)
99 per_cpu(buffer_space_available, cpu)[buftype] = false;
101 per_cpu(buffer_space_available, cpu)[buftype] = true;
103 return per_cpu(buffer_space_available, cpu)[buftype];
106 static int contiguous_space_available(int cpu, int buftype)
108 int remaining = buffer_bytes_available(cpu, buftype);
109 int contiguous = gator_buffer_size[buftype] - per_cpu(gator_buffer_write, cpu)[buftype];
111 if (remaining < contiguous)
116 static void gator_commit_buffer(int cpu, int buftype, u64 time)
118 int type_length, commit, length, byte;
121 if (!per_cpu(gator_buffer, cpu)[buftype])
124 /* post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload */
125 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;
130 length += gator_buffer_size[buftype];
131 length = length - type_length - sizeof(s32);
133 if (length <= FRAME_HEADER_SIZE) {
134 /* Nothing to write, only the frame header is present */
135 local_irq_restore(flags);
139 for (byte = 0; byte < sizeof(s32); byte++)
140 per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
142 per_cpu(gator_buffer_commit, cpu)[buftype] = per_cpu(gator_buffer_write, cpu)[buftype];
144 if (gator_live_rate > 0) {
145 while (time > per_cpu(gator_buffer_commit_time, cpu))
146 per_cpu(gator_buffer_commit_time, cpu) += gator_live_rate;
149 marshal_frame(cpu, buftype);
150 local_irq_restore(flags);
152 /* had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater */
153 if (per_cpu(in_scheduler_context, cpu)) {
154 #ifndef CONFIG_PREEMPT_RT_FULL
155 /* mod_timer can not be used in interrupt context in RT-Preempt full */
156 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
159 up(&gator_buffer_wake_sem);
163 static void buffer_check(int cpu, int buftype, u64 time)
165 int filled = per_cpu(gator_buffer_write, cpu)[buftype] - per_cpu(gator_buffer_commit, cpu)[buftype];
168 filled += gator_buffer_size[buftype];
169 if (filled >= ((gator_buffer_size[buftype] * 3) / 4))
170 gator_commit_buffer(cpu, buftype, time);