diff options
author | Jon Medhurst | 2013-06-17 07:29:43 -0500 |
---|---|---|
committer | Jon Medhurst | 2013-06-17 07:29:43 -0500 |
commit | 567aa4e79aa4450eb32528b6acda62f18ae76596 (patch) | |
tree | 747c381b968e6d044cdaefa4a64c5295566e2764 /driver/gator_main.c | |
parent | 4187fbf69e3cd436cfd3c93948492296e99e918c (diff) | |
parent | f15a1807ecf7af6dd0cac9e175ff00bf06d7c304 (diff) | |
download | arm-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.c | 126 |
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 |
11 | static unsigned long gator_protocol_version = 13; | 11 | static 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); | |||
162 | static int buffer_bytes_available(int cpu, int buftype); | 162 | static int buffer_bytes_available(int cpu, int buftype); |
163 | static bool buffer_check_space(int cpu, int buftype, int bytes); | 163 | static bool buffer_check_space(int cpu, int buftype, int bytes); |
164 | static int contiguous_space_available(int cpu, int bufytpe); | 164 | static int contiguous_space_available(int cpu, int bufytpe); |
165 | static void gator_buffer_write_packed_int(int cpu, int buftype, unsigned int x); | 165 | static void gator_buffer_write_packed_int(int cpu, int buftype, int x); |
166 | static void gator_buffer_write_packed_int64(int cpu, int buftype, unsigned long long x); | 166 | static void gator_buffer_write_packed_int64(int cpu, int buftype, long long x); |
167 | static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len); | 167 | static void gator_buffer_write_bytes(int cpu, int buftype, const char *x, int len); |
168 | static void gator_buffer_write_string(int cpu, int buftype, const char *x); | 168 | static void gator_buffer_write_string(int cpu, int buftype, const char *x); |
169 | static void gator_add_trace(int cpu, unsigned long address); | 169 | static 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 | ||
1230 | static ssize_t userspace_buffer_read(struct file *file, char __user *buf, | 1233 | static 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 | ||
1304 | out: | ||
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 | ||
1309 | const struct file_operations gator_event_buffer_fops = { | 1310 | const 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 | } |