Merge tag 'v3.10.86' into linux-linaro-lsk-v3.10
[firefly-linux-kernel-4.4.55.git] / drivers / gator / gator_annotate.c
1 /**
2  * Copyright (C) ARM Limited 2010-2015. All rights reserved.
3  *
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
10 #include <linux/slab.h>
11 #include <linux/fs.h>
12 #include <linux/mm.h>
13 #include <linux/sched.h>
14 #include <linux/uaccess.h>
15 #include <asm/current.h>
16 #include <linux/spinlock.h>
17
18 static DEFINE_SPINLOCK(annotate_lock);
19 static bool collect_annotations;
20
21 static int annotate_copy(struct file *file, char const __user *buf, size_t count)
22 {
23         int cpu = 0;
24         int write = per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF];
25
26         if (file == NULL) {
27                 /* copy from kernel */
28                 memcpy(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count);
29         } else {
30                 /* copy from user space */
31                 if (copy_from_user(&per_cpu(gator_buffer, cpu)[ANNOTATE_BUF][write], buf, count) != 0)
32                         return -1;
33         }
34         per_cpu(gator_buffer_write, cpu)[ANNOTATE_BUF] = (write + count) & gator_buffer_mask[ANNOTATE_BUF];
35
36         return 0;
37 }
38
39 static ssize_t annotate_write(struct file *file, char const __user *buf, size_t count_orig, loff_t *offset)
40 {
41         int pid, cpu, header_size, available, contiguous, length1, length2, size, count = count_orig & 0x7fffffff;
42         bool interrupt_context;
43
44         if (*offset)
45                 return -EINVAL;
46
47         interrupt_context = in_interrupt();
48         /* Annotations are not supported in interrupt context, but may work
49          * if you comment out the the next four lines of code. By doing so,
50          * annotations in interrupt context can result in deadlocks and lost
51          * data.
52          */
53         if (interrupt_context) {
54                 pr_warning("gator: Annotations are not supported in interrupt context. Edit gator_annotate.c in the gator driver to enable annotations in interrupt context.\n");
55                 return -EINVAL;
56         }
57
58  retry:
59         /* synchronize between cores and with collect_annotations */
60         spin_lock(&annotate_lock);
61
62         if (!collect_annotations) {
63                 /* Not collecting annotations, tell the caller everything was written */
64                 size = count_orig;
65                 goto annotate_write_out;
66         }
67
68         /* Annotation only uses a single per-cpu buffer as the data must be in order to the engine */
69         cpu = 0;
70
71         if (current == NULL)
72                 pid = 0;
73         else
74                 pid = current->pid;
75
76         /* determine total size of the payload */
77         header_size = MAXSIZE_PACK32 * 3 + MAXSIZE_PACK64;
78         available = buffer_bytes_available(cpu, ANNOTATE_BUF) - header_size;
79         size = count < available ? count : available;
80
81         if (size <= 0) {
82                 /* Buffer is full, wait until space is available */
83                 spin_unlock(&annotate_lock);
84
85                 /* Drop the annotation as blocking is not allowed in interrupt context */
86                 if (interrupt_context)
87                         return -EINVAL;
88
89                 wait_event_interruptible(gator_annotate_wait, buffer_bytes_available(cpu, ANNOTATE_BUF) > header_size || !collect_annotations);
90
91                 /* Check to see if a signal is pending */
92                 if (signal_pending(current))
93                         return -EINTR;
94
95                 goto retry;
96         }
97
98         /* synchronize shared variables annotateBuf and annotatePos */
99         if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF]) {
100                 u64 time = gator_get_time();
101
102                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu());
103                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
104                 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, time);
105                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, size);
106
107                 /* determine the sizes to capture, length1 + length2 will equal size */
108                 contiguous = contiguous_space_available(cpu, ANNOTATE_BUF);
109                 if (size < contiguous) {
110                         length1 = size;
111                         length2 = 0;
112                 } else {
113                         length1 = contiguous;
114                         length2 = size - contiguous;
115                 }
116
117                 if (annotate_copy(file, buf, length1) != 0) {
118                         size = -EINVAL;
119                         goto annotate_write_out;
120                 }
121
122                 if (length2 > 0 && annotate_copy(file, &buf[length1], length2) != 0) {
123                         size = -EINVAL;
124                         goto annotate_write_out;
125                 }
126
127                 /* Check and commit; commit is set to occur once buffer is 3/4 full */
128                 buffer_check(cpu, ANNOTATE_BUF, time);
129         }
130
131 annotate_write_out:
132         spin_unlock(&annotate_lock);
133
134         /* return the number of bytes written */
135         return size;
136 }
137
138 #include "gator_annotate_kernel.c"
139
140 static int annotate_release(struct inode *inode, struct file *file)
141 {
142         int cpu = 0;
143
144         /* synchronize between cores */
145         spin_lock(&annotate_lock);
146
147         if (per_cpu(gator_buffer, cpu)[ANNOTATE_BUF] && buffer_check_space(cpu, ANNOTATE_BUF, MAXSIZE_PACK64 + 3 * MAXSIZE_PACK32)) {
148                 uint32_t pid = current->pid;
149
150                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, get_physical_cpu());
151                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, pid);
152                 /* time */
153                 gator_buffer_write_packed_int64(cpu, ANNOTATE_BUF, 0);
154                 /* size */
155                 gator_buffer_write_packed_int(cpu, ANNOTATE_BUF, 0);
156         }
157
158         /* Check and commit; commit is set to occur once buffer is 3/4 full */
159         buffer_check(cpu, ANNOTATE_BUF, gator_get_time());
160
161         spin_unlock(&annotate_lock);
162
163         return 0;
164 }
165
166 static const struct file_operations annotate_fops = {
167         .write = annotate_write,
168         .release = annotate_release
169 };
170
171 static int gator_annotate_create_files(struct super_block *sb, struct dentry *root)
172 {
173         return gatorfs_create_file_perm(sb, root, "annotate", &annotate_fops, 0666);
174 }
175
176 static int gator_annotate_start(void)
177 {
178         collect_annotations = true;
179         return 0;
180 }
181
182 static void gator_annotate_stop(void)
183 {
184         /* the spinlock here will ensure that when this function exits, we are not in the middle of an annotation */
185         spin_lock(&annotate_lock);
186         collect_annotations = false;
187         wake_up(&gator_annotate_wait);
188         spin_unlock(&annotate_lock);
189 }