Commit | Line | Data |
---|---|---|
02af6beb | 1 | |
6fa3eb70 S |
2 | #include <linux/sched.h> |
3 | #include <linux/string.h> | |
4 | #include <linux/vmalloc.h> | |
5 | #include <linux/proc_fs.h> | |
6 | #include <linux/seq_file.h> | |
7 | ||
8 | #include "mtk_pp.h" | |
9 | ||
10 | #if defined(MTK_DEBUG) && defined(MTK_DEBUG_PROC_PRINT) | |
11 | ||
12 | static struct proc_dir_entry *g_MTKPP_proc; | |
13 | static MTK_PROC_PRINT_DATA *g_MTKPPdata[MTKPP_ID_SIZE]; | |
14 | ||
15 | static void MTKPP_InitLock(MTK_PROC_PRINT_DATA *data) | |
16 | { | |
17 | spin_lock_init(&data->lock); | |
18 | } | |
19 | ||
20 | static void MTKPP_Lock(MTK_PROC_PRINT_DATA *data) | |
21 | { | |
22 | spin_lock_irqsave(&data->lock, data->irqflags); | |
23 | } | |
24 | static void MTKPP_UnLock(MTK_PROC_PRINT_DATA *data) | |
25 | { | |
26 | spin_unlock_irqrestore(&data->lock, data->irqflags); | |
27 | } | |
28 | ||
29 | static void MTKPP_PrintQueueBuffer(MTK_PROC_PRINT_DATA *data, const char *fmt, ...) MTK_PP_FORMAT_PRINTF(2,3); | |
30 | ||
02af6beb | 31 | //static void MTKPP_PrintQueueBuffer2(MTK_PROC_PRINT_DATA *data, const char *fmt, ...) MTK_PP_FORMAT_PRINTF(2,3); |
6fa3eb70 S |
32 | |
33 | static void MTKPP_PrintRingBuffer(MTK_PROC_PRINT_DATA *data, const char *fmt, ...) MTK_PP_FORMAT_PRINTF(2,3); | |
34 | ||
35 | static int MTKPP_PrintTime(char *buf, int n) | |
36 | { | |
37 | /* copy & modify from ./kernel/printk.c */ | |
38 | unsigned long long t; | |
39 | unsigned long nanosec_rem; | |
40 | ||
41 | t = cpu_clock(smp_processor_id()); | |
42 | nanosec_rem = do_div(t, 1000000000); | |
43 | ||
44 | return snprintf(buf, n, "[%5lu.%06lu] ", (unsigned long) t, nanosec_rem / 1000); | |
45 | } | |
46 | ||
47 | static void MTKPP_PrintQueueBuffer(MTK_PROC_PRINT_DATA *data, const char *fmt, ...) | |
48 | { | |
49 | va_list args; | |
50 | char *buf; | |
51 | int len; | |
52 | ||
53 | MTKPP_Lock(data); | |
54 | ||
55 | if ((data->current_line >= data->line_array_size) | |
56 | || (data->current_data >= (data->data_array_size - 128))) | |
57 | { | |
58 | // out of buffer, ignore input | |
59 | MTKPP_UnLock(data); | |
60 | return; | |
61 | } | |
62 | ||
63 | /* Move to next line */ | |
64 | buf = data->line[data->current_line++] = data->data + data->current_data; | |
65 | ||
66 | /* Print string */ | |
67 | va_start(args, fmt); | |
68 | len = vsnprintf(buf, (data->data_array_size - data->current_data), fmt, args); | |
69 | va_end(args); | |
70 | ||
71 | data->current_data += len + 1; | |
72 | ||
73 | MTKPP_UnLock(data); | |
74 | } | |
75 | ||
02af6beb | 76 | #if 0 |
6fa3eb70 S |
77 | static void MTKPP_PrintQueueBuffer2(MTK_PROC_PRINT_DATA *data, const char *fmt, ...) |
78 | { | |
79 | va_list args; | |
80 | char *buf; | |
81 | int len; | |
82 | ||
83 | MTKPP_Lock(data); | |
84 | ||
85 | if ((data->current_line >= data->line_array_size) | |
86 | || (data->current_data >= (data->data_array_size - 128))) | |
87 | { | |
88 | // out of buffer, ignore input | |
89 | MTKPP_UnLock(data); | |
90 | return; | |
91 | } | |
92 | ||
93 | /* Move to next line */ | |
94 | buf = data->line[data->current_line++] = data->data + data->current_data; | |
95 | ||
96 | /* Add the current time stamp */ | |
97 | len = MTKPP_PrintTime(buf, (data->data_array_size - data->current_data)); | |
98 | buf += len; | |
99 | data->current_data += len; | |
100 | ||
101 | /* Print string */ | |
102 | va_start(args, fmt); | |
103 | len = vsnprintf(buf, (data->data_array_size - data->current_data), fmt, args); | |
104 | va_end(args); | |
105 | ||
106 | data->current_data += len + 1 ; | |
107 | ||
108 | MTKPP_UnLock(data); | |
109 | } | |
02af6beb | 110 | #endif |
6fa3eb70 S |
111 | |
112 | static void MTKPP_PrintRingBuffer(MTK_PROC_PRINT_DATA *data, const char *fmt, ...) | |
113 | { | |
114 | va_list args; | |
115 | char *buf; | |
116 | int len, s; | |
117 | ||
118 | MTKPP_Lock(data); | |
119 | ||
120 | if ((data->current_line >= data->line_array_size) | |
121 | || (data->current_data >= (data->data_array_size - 128))) | |
122 | { | |
123 | data->current_line = 0; | |
124 | data->current_data = 0; | |
125 | } | |
126 | ||
127 | /* Move to next line */ | |
128 | buf = data->line[data->current_line++] = data->data + data->current_data; | |
129 | ||
130 | /* Add the current time stamp */ | |
131 | len = MTKPP_PrintTime(buf, (data->data_array_size - data->current_data)); | |
132 | buf += len; | |
133 | data->current_data += len; | |
134 | ||
135 | /* Print string */ | |
136 | va_start(args, fmt); | |
137 | len = vsnprintf(buf, (data->data_array_size - data->current_data), fmt, args); | |
138 | va_end(args); | |
139 | ||
140 | data->current_data += len + 1 ; | |
141 | ||
142 | /* Clear overflow data */ | |
143 | buf += len; s = data->current_line; | |
144 | while (s < data->line_array_size | |
145 | && data->line[s] != NULL | |
146 | && data->line[s] <= buf) | |
147 | { | |
148 | data->line[s++] = NULL; | |
149 | } | |
150 | ||
151 | MTKPP_UnLock(data); | |
152 | } | |
153 | ||
154 | static MTK_PROC_PRINT_DATA *MTKPP_AllocStruct(int type) | |
155 | { | |
156 | MTK_PROC_PRINT_DATA *data; | |
157 | ||
158 | data = vmalloc(sizeof(MTK_PROC_PRINT_DATA)); | |
159 | if (data == NULL) | |
160 | { | |
161 | _MTKPP_DEBUG_LOG("%s: vmalloc fail", __func__); | |
162 | goto err_out; | |
163 | } | |
164 | ||
165 | MTKPP_InitLock(data); | |
166 | ||
167 | switch (type) | |
168 | { | |
169 | case MTKPP_BUFFERTYPE_QUEUEBUFFER: | |
170 | data->pfn_print = MTKPP_PrintQueueBuffer; | |
171 | break; | |
172 | case MTKPP_BUFFERTYPE_RINGBUFFER: | |
173 | data->pfn_print = MTKPP_PrintRingBuffer; | |
174 | break; | |
175 | default: | |
176 | // something wrong | |
177 | _MTKPP_DEBUG_LOG("%s: unknow flags: %d", __func__, type); | |
178 | goto err_out2; | |
179 | break; | |
180 | } | |
181 | ||
182 | data->data = NULL; | |
183 | data->line = NULL; | |
184 | data->data_array_size = 0; | |
185 | data->line_array_size = 0; | |
186 | data->current_data = 0; | |
187 | data->current_line = 0; | |
188 | data->type = type; | |
189 | ||
190 | return data; | |
191 | ||
192 | err_out2: | |
193 | vfree(data); | |
194 | err_out: | |
195 | return NULL; | |
196 | ||
197 | } | |
198 | ||
199 | static void MTKPP_FreeStruct(MTK_PROC_PRINT_DATA **data) | |
200 | { | |
201 | vfree(*data); | |
202 | *data = NULL; | |
203 | } | |
204 | ||
205 | static void MTKPP_AllocData(MTK_PROC_PRINT_DATA *data, int data_size, int max_line) | |
206 | { | |
207 | MTKPP_Lock(data); | |
208 | ||
209 | data->data = (char *)kmalloc(sizeof(char)*data_size, GFP_ATOMIC); | |
210 | if (data->data == NULL) | |
211 | { | |
212 | _MTKPP_DEBUG_LOG("%s, kmalloc data fail, size = %d", __func__, data_size); | |
213 | goto err_alloc_struct; | |
214 | } | |
215 | data->line = (char **)kmalloc(sizeof(char*)*max_line, GFP_ATOMIC); | |
216 | if (data->line == NULL) | |
217 | { | |
218 | _MTKPP_DEBUG_LOG("%s, kmalloc line fail, size = %d", __func__, data_size); | |
219 | goto err_alloc_data; | |
220 | } | |
221 | ||
222 | data->data_array_size = data_size; | |
223 | data->line_array_size = max_line; | |
224 | ||
225 | MTKPP_UnLock(data); | |
226 | ||
227 | return; | |
228 | ||
229 | err_alloc_data: | |
230 | kfree(data->data); | |
231 | err_alloc_struct: | |
232 | MTKPP_UnLock(data); | |
233 | return; | |
234 | ||
235 | } | |
236 | ||
237 | static void MTKPP_FreeData(MTK_PROC_PRINT_DATA *data) | |
238 | { | |
239 | MTKPP_Lock(data); | |
240 | ||
241 | kfree(data->line); | |
242 | kfree(data->data); | |
243 | ||
244 | data->line = NULL; | |
245 | data->data = NULL; | |
246 | data->data_array_size = 0; | |
247 | data->line_array_size = 0; | |
248 | data->current_data = 0; | |
249 | data->current_line = 0; | |
250 | ||
251 | MTKPP_UnLock(data); | |
252 | } | |
253 | ||
254 | static void MTKPP_CleanData(MTK_PROC_PRINT_DATA *data) | |
255 | { | |
256 | MTKPP_Lock(data); | |
257 | ||
258 | memset(data->line, 0, sizeof(char*)*data->line_array_size); | |
259 | data->current_data = 0; | |
260 | data->current_line = 0; | |
261 | ||
262 | MTKPP_UnLock(data); | |
263 | } | |
264 | ||
265 | static void* MTKPP_SeqStart(struct seq_file *s, loff_t *pos) | |
266 | { | |
267 | loff_t *spos; | |
268 | ||
269 | spos = kmalloc(sizeof(loff_t), GFP_KERNEL); | |
270 | ||
271 | if (*pos >= MTKPP_ID_SIZE) | |
272 | { | |
273 | // MTK: lono@2013/1/7 | |
274 | return NULL; | |
275 | } | |
276 | ||
277 | if (spos == NULL) | |
278 | { | |
279 | return NULL; | |
280 | } | |
281 | ||
282 | *spos = *pos; | |
283 | return spos; | |
284 | } | |
285 | ||
286 | static void* MTKPP_SeqNext(struct seq_file *s, void *v, loff_t *pos) | |
287 | { | |
288 | loff_t *spos = (loff_t *) v; | |
289 | *pos = ++(*spos); | |
290 | ||
291 | return (*pos < MTKPP_ID_SIZE) ? spos : NULL; | |
292 | } | |
293 | ||
294 | static void MTKPP_SeqStop(struct seq_file *s, void *v) | |
295 | { | |
296 | kfree(v); | |
297 | } | |
298 | ||
299 | static int MTKPP_SeqShow(struct seq_file *sfile, void *v) | |
300 | { | |
301 | MTK_PROC_PRINT_DATA *data; | |
302 | int off, i; | |
303 | loff_t *spos = (loff_t *) v; | |
304 | ||
305 | off = *spos; | |
306 | data = g_MTKPPdata[off]; | |
307 | ||
308 | seq_printf(sfile, "\n" "===== buffer_id = %d =====\n", off); | |
309 | ||
310 | MTKPP_Lock(data); | |
311 | ||
312 | switch (data->type) | |
313 | { | |
314 | case MTKPP_BUFFERTYPE_QUEUEBUFFER: | |
315 | seq_printf(sfile, "data_size = %d/%d\n", data->current_data, data->data_array_size); | |
316 | seq_printf(sfile, "data_line = %d/%d\n", data->current_line, data->line_array_size); | |
317 | for (i = 0; i < data->current_line; ++i) | |
318 | { | |
319 | seq_printf(sfile, "%s\n", data->line[i]); | |
320 | } | |
321 | break; | |
322 | case MTKPP_BUFFERTYPE_RINGBUFFER: | |
323 | seq_printf(sfile, "data_size = %d\n", data->data_array_size); | |
324 | seq_printf(sfile, "data_line = %d\n", data->line_array_size); | |
325 | for (i = data->current_line; i < data->line_array_size; ++i) | |
326 | { | |
327 | if (data->line[i] != NULL) | |
328 | { | |
329 | seq_printf(sfile, "%s\n", data->line[i]); | |
330 | } | |
331 | } | |
332 | for (i = 0; i < data->current_line; ++i) | |
333 | { | |
334 | if (data->line[i] != NULL) | |
335 | { | |
336 | seq_printf(sfile, "%s\n", data->line[i]); | |
337 | } | |
338 | } | |
339 | break; | |
340 | default: | |
341 | // FIXME: assert here | |
342 | break; | |
343 | } | |
344 | ||
345 | MTKPP_UnLock(data); | |
346 | ||
347 | return 0; | |
348 | } | |
349 | ||
350 | static struct seq_operations g_MTKPP_seq_ops = { | |
351 | .start = MTKPP_SeqStart, | |
352 | .next = MTKPP_SeqNext, | |
353 | .stop = MTKPP_SeqStop, | |
354 | .show = MTKPP_SeqShow | |
355 | }; | |
356 | ||
357 | static int MTKPP_ProcOpen(struct inode *inode, struct file *file) | |
358 | { | |
359 | return seq_open(file, &g_MTKPP_seq_ops); | |
360 | } | |
361 | ||
362 | static struct file_operations g_MTKPP_proc_ops = { | |
363 | .open = MTKPP_ProcOpen, | |
364 | .read = seq_read, // system | |
365 | .llseek = seq_lseek, // system | |
366 | .release = seq_release // system | |
367 | }; | |
368 | ||
369 | void MTKPP_Init(void) | |
370 | { | |
371 | int i; | |
372 | struct { | |
373 | MTKPP_ID uid; | |
374 | MTKPP_BUFFERTYPE type; | |
375 | int data_size; | |
376 | int max_line; | |
377 | } mtk_pp_register_tabls[] = | |
378 | { | |
379 | {MTKPP_ID_SYNC, MTKPP_BUFFERTYPE_RINGBUFFER, 1024 * 1024 * 2, 1024}, | |
380 | }; | |
381 | ||
382 | for (i = 0; i < MTKPP_ID_SIZE; ++i) | |
383 | { | |
384 | if (i != mtk_pp_register_tabls[i].uid) | |
385 | { | |
386 | _MTKPP_DEBUG_LOG("%s: index(%d) != tabel_uid(%d)", __func__, i, mtk_pp_register_tabls[i].uid); | |
387 | goto err_out; | |
388 | } | |
389 | ||
390 | g_MTKPPdata[i] = MTKPP_AllocStruct(mtk_pp_register_tabls[i].type); | |
391 | ||
392 | if (g_MTKPPdata[i] == NULL) | |
393 | { | |
394 | _MTKPP_DEBUG_LOG("%s: alloc struct fail: flags = %d", __func__, mtk_pp_register_tabls[i].type); | |
395 | goto err_out; | |
396 | } | |
397 | ||
398 | if (mtk_pp_register_tabls[i].data_size > 0) | |
399 | { | |
400 | MTKPP_AllocData( | |
401 | g_MTKPPdata[i], | |
402 | mtk_pp_register_tabls[i].data_size, | |
403 | mtk_pp_register_tabls[i].max_line | |
404 | ); | |
405 | ||
406 | MTKPP_CleanData(g_MTKPPdata[i]); | |
407 | } | |
408 | } | |
409 | ||
02af6beb | 410 | g_MTKPP_proc = proc_create("gpulog", 0, NULL, &g_MTKPP_proc_ops); |
6fa3eb70 S |
411 | |
412 | return; | |
413 | ||
414 | err_out: | |
415 | return; | |
416 | } | |
417 | ||
418 | void MTKPP_Deinit(void) | |
419 | { | |
420 | int i; | |
421 | ||
422 | remove_proc_entry("gpulog", NULL); | |
423 | ||
424 | for (i = (MTKPP_ID_SIZE - 1); i >= 0; --i) | |
425 | { | |
426 | MTKPP_FreeData(g_MTKPPdata[i]); | |
427 | MTKPP_FreeStruct(&g_MTKPPdata[i]); | |
428 | } | |
429 | } | |
430 | ||
431 | MTK_PROC_PRINT_DATA *MTKPP_GetData(MTKPP_ID id) | |
432 | { | |
433 | return (id >= 0 && id < MTKPP_ID_SIZE) ? | |
434 | g_MTKPPdata[id] : NULL; | |
435 | } | |
436 | ||
437 | #endif |