summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst2013-06-17 07:29:43 -0500
committerJon Medhurst2013-06-17 07:29:43 -0500
commit567aa4e79aa4450eb32528b6acda62f18ae76596 (patch)
tree747c381b968e6d044cdaefa4a64c5295566e2764 /driver/gator_main.c
parent4187fbf69e3cd436cfd3c93948492296e99e918c (diff)
parentf15a1807ecf7af6dd0cac9e175ff00bf06d7c304 (diff)
downloadarm-ds5-gator-567aa4e79aa4450eb32528b6acda62f18ae76596.tar.gz
arm-ds5-gator-567aa4e79aa4450eb32528b6acda62f18ae76596.tar.xz
arm-ds5-gator-567aa4e79aa4450eb32528b6acda62f18ae76596.zip
Merge branch 'master' into android
Diffstat (limited to 'driver/gator_main.c')
-rw-r--r--driver/gator_main.c126
1 files changed, 65 insertions, 61 deletions
diff --git a/driver/gator_main.c b/driver/gator_main.c
index 88650f6..5eab034 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10// This version must match the gator daemon version 10// This version must match the gator daemon version
11static unsigned long gator_protocol_version = 13; 11static unsigned long gator_protocol_version = 14;
12 12
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <linux/cpu.h> 14#include <linux/cpu.h>
@@ -162,8 +162,8 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time);
162static int buffer_bytes_available(int cpu, int buftype); 162static int buffer_bytes_available(int cpu, int buftype);
163static bool buffer_check_space(int cpu, int buftype, int bytes); 163static bool buffer_check_space(int cpu, int buftype, int bytes);
164static int contiguous_space_available(int cpu, int bufytpe); 164static int contiguous_space_available(int cpu, int bufytpe);
165static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x); 165static void gator_buffer_write_packed_int(int cpu, int buftype, int x);
166static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x); 166static void gator_buffer_write_packed_int64(int cpu, int buftype, long long x);
167static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len); 167static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len);
168static void gator_buffer_write_string(int cpu, int buftype, const char *x); 168static void gator_buffer_write_string(int cpu, int buftype, const char *x);
169static void gator_add_trace(int cpu, unsigned long address); 169static void gator_add_trace(int cpu, unsigned long address);
@@ -389,6 +389,8 @@ static bool buffer_commit_ready(int *cpu, int *buftype)
389 return true; 389 return true;
390 } 390 }
391 } 391 }
392 *cpu = -1;
393 *buftype = -1;
392 return false; 394 return false;
393} 395}
394 396
@@ -476,14 +478,14 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
476 if (length < 0) { 478 if (length < 0) {
477 length += gator_buffer_size[buftype]; 479 length += gator_buffer_size[buftype];
478 } 480 }
479 length = length - type_length - sizeof(int); 481 length = length - type_length - sizeof(s32);
480 482
481 if (length <= FRAME_HEADER_SIZE) { 483 if (length <= FRAME_HEADER_SIZE) {
482 // Nothing to write, only the frame header is present 484 // Nothing to write, only the frame header is present
483 return; 485 return;
484 } 486 }
485 487
486 for (byte = 0; byte < sizeof(int); byte++) { 488 for (byte = 0; byte < sizeof(s32); byte++) {
487 per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF; 489 per_cpu(gator_buffer, cpu)[buftype][(commit + type_length + byte) & gator_buffer_mask[buftype]] = (length >> byte * 8) & 0xFF;
488 } 490 }
489 491
@@ -595,7 +597,7 @@ static void gator_timer_offline(void *migrate)
595 597
596 // Offline any events and output counters 598 // Offline any events and output counters
597 time = gator_get_time(); 599 time = gator_get_time();
598 if (marshal_event_header()) { 600 if (marshal_event_header(time)) {
599 list_for_each_entry(gi, &gator_events, list) { 601 list_for_each_entry(gi, &gator_events, list) {
600 if (gi->offline) { 602 if (gi->offline) {
601 len = gi->offline(&buffer, migrate); 603 len = gi->offline(&buffer, migrate);
@@ -644,11 +646,13 @@ static void gator_timer_online(void *migrate)
644 struct gator_interface *gi; 646 struct gator_interface *gi;
645 int len, cpu = get_physical_cpu(); 647 int len, cpu = get_physical_cpu();
646 int *buffer; 648 int *buffer;
649 u64 time;
647 650
648 gator_trace_power_online(); 651 gator_trace_power_online();
649 652
650 // online any events and output counters 653 // online any events and output counters
651 if (marshal_event_header()) { 654 time = gator_get_time();
655 if (marshal_event_header(time)) {
652 list_for_each_entry(gi, &gator_events, list) { 656 list_for_each_entry(gi, &gator_events, list) {
653 if (gi->online) { 657 if (gi->online) {
654 len = gi->online(&buffer, migrate); 658 len = gi->online(&buffer, migrate);
@@ -656,7 +660,7 @@ static void gator_timer_online(void *migrate)
656 } 660 }
657 } 661 }
658 // Only check after writing all counters so that time and corresponding counters appear in the same frame 662 // Only check after writing all counters so that time and corresponding counters appear in the same frame
659 buffer_check(cpu, BLOCK_COUNTER_BUF, gator_get_time()); 663 buffer_check(cpu, BLOCK_COUNTER_BUF, time);
660 } 664 }
661 665
662 if (!migrate) { 666 if (!migrate) {
@@ -745,8 +749,6 @@ static u64 gator_get_time(void)
745 if (!printed_monotonic_warning && delta > 500000) { 749 if (!printed_monotonic_warning && delta > 500000) {
746 printk(KERN_ERR "%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __FUNCTION__, cpu, delta); 750 printk(KERN_ERR "%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\nSkew in Streamline data may be present at the fine zoom levels\n", __FUNCTION__, cpu, delta);
747 printed_monotonic_warning = true; 751 printed_monotonic_warning = true;
748 } else {
749 pr_debug("%s: getrawmonotonic is not monotonic cpu: %i delta: %lli\n", __FUNCTION__, cpu, delta);
750 } 752 }
751 timestamp = prev_timestamp; 753 timestamp = prev_timestamp;
752 } 754 }
@@ -894,6 +896,7 @@ static int gator_init(void)
894 if (gator_events_list[i]) 896 if (gator_events_list[i])
895 gator_events_list[i](); 897 gator_events_list[i]();
896 898
899 gator_trace_sched_init();
897 gator_trace_power_init(); 900 gator_trace_power_init();
898 901
899 return 0; 902 return 0;
@@ -1227,83 +1230,81 @@ static int userspace_buffer_release(struct inode *inode, struct file *file)
1227 return 0; 1230 return 0;
1228} 1231}
1229 1232
1230static ssize_t userspace_buffer_read(struct file *file, char __user *buf, 1233static ssize_t userspace_buffer_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
1231 size_t count, loff_t *offset)
1232{ 1234{
1233 int retval = -EINVAL; 1235 int commit, length1, length2, read;
1234 int commit = 0, length1, length2, read;
1235 char *buffer1; 1236 char *buffer1;
1236 char *buffer2 = NULL; 1237 char *buffer2;
1237 int cpu, buftype; 1238 int cpu, buftype;
1239 int written = 0;
1238 1240
1239 /* do not handle partial reads */ 1241 // ensure there is enough space for a whole frame
1240 if (count != userspace_buffer_size || *offset) 1242 if (count < userspace_buffer_size || *offset) {
1241 return -EINVAL; 1243 return -EINVAL;
1244 }
1242 1245
1243 // sleep until the condition is true or a signal is received 1246 // sleep until the condition is true or a signal is received
1244 // the condition is checked each time gator_buffer_wait is woken up 1247 // the condition is checked each time gator_buffer_wait is woken up
1245 buftype = cpu = -1;
1246 wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(&cpu, &buftype) || !gator_started); 1248 wait_event_interruptible(gator_buffer_wait, buffer_commit_ready(&cpu, &buftype) || !gator_started);
1247 1249
1248 if (signal_pending(current)) 1250 if (signal_pending(current)) {
1249 return -EINTR; 1251 return -EINTR;
1250 1252 }
1251 length2 = 0;
1252 retval = -EFAULT;
1253
1254 mutex_lock(&gator_buffer_mutex);
1255 1253
1256 if (buftype == -1 || cpu == -1) { 1254 if (buftype == -1 || cpu == -1) {
1257 retval = 0; 1255 return 0;
1258 goto out;
1259 } 1256 }
1260 1257
1261 read = per_cpu(gator_buffer_read, cpu)[buftype]; 1258 mutex_lock(&gator_buffer_mutex);
1262 commit = per_cpu(gator_buffer_commit, cpu)[buftype];
1263 1259
1264 /* May happen if the buffer is freed during pending reads. */ 1260 do {
1265 if (!per_cpu(gator_buffer, cpu)[buftype]) { 1261 read = per_cpu(gator_buffer_read, cpu)[buftype];
1266 retval = -EFAULT; 1262 commit = per_cpu(gator_buffer_commit, cpu)[buftype];
1267 goto out;
1268 }
1269 1263
1270 /* determine the size of two halves */ 1264 // May happen if the buffer is freed during pending reads.
1271 length1 = commit - read; 1265 if (!per_cpu(gator_buffer, cpu)[buftype]) {
1272 buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]); 1266 break;
1273 buffer2 = &(per_cpu(gator_buffer, cpu)[buftype][0]); 1267 }
1274 if (length1 < 0) {
1275 length1 = gator_buffer_size[buftype] - read;
1276 length2 = commit;
1277 }
1278 1268
1279 /* start, middle or end */ 1269 // determine the size of two halves
1280 if (length1 > 0) { 1270 length1 = commit - read;
1281 if (copy_to_user(&buf[0], buffer1, length1)) { 1271 length2 = 0;
1282 goto out; 1272 buffer1 = &(per_cpu(gator_buffer, cpu)[buftype][read]);
1273 buffer2 = &(per_cpu(gator_buffer, cpu)[buftype][0]);
1274 if (length1 < 0) {
1275 length1 = gator_buffer_size[buftype] - read;
1276 length2 = commit;
1283 } 1277 }
1284 }
1285 1278
1286 /* possible wrap around */ 1279 if (length1 + length2 > count - written) {
1287 if (length2 > 0) { 1280 break;
1288 if (copy_to_user(&buf[length1], buffer2, length2)) {
1289 goto out;
1290 } 1281 }
1291 }
1292 1282
1293 per_cpu(gator_buffer_read, cpu)[buftype] = commit; 1283 // start, middle or end
1294 retval = length1 + length2; 1284 if (length1 > 0 && copy_to_user(&buf[written], buffer1, length1)) {
1285 break;
1286 }
1295 1287
1296 /* kick just in case we've lost an SMP event */ 1288 // possible wrap around
1297 wake_up(&gator_buffer_wait); 1289 if (length2 > 0 && copy_to_user(&buf[written + length1], buffer2, length2)) {
1290 break;
1291 }
1298 1292
1299 // Wake up annotate_write if more space is available 1293 per_cpu(gator_buffer_read, cpu)[buftype] = commit;
1300 if (buftype == ANNOTATE_BUF) { 1294 written += length1 + length2;
1301 wake_up(&gator_annotate_wait); 1295
1302 } 1296 // Wake up annotate_write if more space is available
1297 if (buftype == ANNOTATE_BUF) {
1298 wake_up(&gator_annotate_wait);
1299 }
1300 } while (buffer_commit_ready(&cpu, &buftype));
1303 1301
1304out:
1305 mutex_unlock(&gator_buffer_mutex); 1302 mutex_unlock(&gator_buffer_mutex);
1306 return retval; 1303
1304 // kick just in case we've lost an SMP event
1305 wake_up(&gator_buffer_wait);
1306
1307 return written > 0 ? written : -EFAULT;
1307} 1308}
1308 1309
1309const struct file_operations gator_event_buffer_fops = { 1310const struct file_operations gator_event_buffer_fops = {
@@ -1376,6 +1377,9 @@ void gator_op_create_files(struct super_block *sb, struct dentry *root)
1376 if (gi->create_files) 1377 if (gi->create_files)
1377 gi->create_files(sb, dir); 1378 gi->create_files(sb, dir);
1378 1379
1380 // Sched Events
1381 sched_trace_create_files(sb, dir);
1382
1379 // Power interface 1383 // Power interface
1380 gator_trace_power_create_files(sb, dir); 1384 gator_trace_power_create_files(sb, dir);
1381} 1385}