import OT_8063_20170412 mali driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / gpu / ged / src / ged_log.c
1 #include <linux/version.h>
2 #include <asm/io.h>
3 #include <linux/mm.h>
4 #include <linux/pagemap.h>
5 #include <linux/genalloc.h>
6 #include <linux/sched.h>
7 #include <linux/mutex.h>
8 //#include <linux/xlog.h>
9 #include <linux/proc_fs.h>
10 #include <linux/seq_file.h>
11 #include <linux/rtc.h>
12
13 #include "ged_base.h"
14 #include "ged_log.h"
15 #include "ged_debugFS.h"
16 #include "ged_profile_dvfs.h"
17 #include "ged_hashtable.h"
18
19 enum
20 {
21 /* 0x00 - 0xff reserved for internal buffer type */
22
23 /* rewrite the oldest log when buffer is full */
24 GED_LOG_ATTR_RINGBUFFER = 0x1,
25 /* stop logging when buffer is full */
26 GED_LOG_ATTR_QUEUEBUFFER = 0x2,
27 /* increase buffersize when buffer is full */
28 GED_LOG_ATTR_AUTO_INCREASE = 0x4,
29 };
30
31 typedef struct GED_LOG_BUF_LINE_TAG
32 {
33 int offset;
34 int tattrs;
35 long long time;
36 long int time_usec;
37 int pid;
38 int tid;
39 } GED_LOG_BUF_LINE;
40
41 typedef struct GED_LOG_BUF_TAG
42 {
43 GED_LOG_BUF_TYPE eType;
44 int attrs;
45
46 void *pMemory;
47 int i32MemorySize;
48
49 GED_LOG_BUF_LINE *psLine;
50 char *pcBuffer;
51 int i32LineCount;
52 int i32BufferSize;
53 int i32LineCurrent;
54 int i32BufferCurrent;
55
56 spinlock_t sSpinLock;
57 unsigned long ui32IRQFlags;
58
59 char acName[GED_LOG_BUF_NAME_LENGTH];
60 char acNodeName[GED_LOG_BUF_NODE_NAME_LENGTH];
61
62 struct dentry* psEntry;
63
64 struct list_head sList;
65
66 unsigned int ui32HashNodeID;
67
68 } GED_LOG_BUF;
69
70 typedef struct GED_LOG_LISTEN_TAG
71 {
72 GED_LOG_BUF_HANDLE *pCBHnd;
73 char acName[GED_LOG_BUF_NAME_LENGTH];
74 struct list_head sList;
75 } GED_LOG_LISTEN;
76
77 typedef struct GED_LOG_BUF_LIST_TAG
78 {
79 rwlock_t sLock;
80 struct list_head sList_buf;
81 struct list_head sList_listen;
82 } GED_LOG_BUF_LIST;
83
84 static GED_LOG_BUF_LIST gsGEDLogBufList = {
85 .sLock = __RW_LOCK_UNLOCKED(gsGEDLogBufList.sLock),
86 .sList_buf = LIST_HEAD_INIT(gsGEDLogBufList.sList_buf),
87 .sList_listen = LIST_HEAD_INIT(gsGEDLogBufList.sList_listen),
88 };
89
90 static struct dentry* gpsGEDLogEntry = NULL;
91 static struct dentry* gpsGEDLogBufsDir = NULL;
92
93 static GED_HASHTABLE_HANDLE ghHashTable = NULL;
94
95 //-----------------------------------------------------------------------------
96 //
97 // GED Log Buf
98 //
99 //-----------------------------------------------------------------------------
100 static GED_LOG_BUF* ged_log_buf_from_handle(GED_LOG_BUF_HANDLE hLogBuf)
101 {
102 return ged_hashtable_find(ghHashTable, (unsigned int)hLogBuf);
103 }
104
105 static GED_ERROR __ged_log_buf_vprint(GED_LOG_BUF *psGEDLogBuf, const char *fmt, va_list args, int attrs)
106 {
107 int buf_n;
108 int len;
109
110 if (!psGEDLogBuf)
111 return GED_OK;
112
113 spin_lock_irqsave(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
114
115 /* if OOM */
116 if (psGEDLogBuf->i32LineCurrent >= psGEDLogBuf->i32LineCount ||
117 psGEDLogBuf->i32BufferCurrent + 256 > psGEDLogBuf->i32BufferSize)
118 {
119 if (attrs & GED_LOG_ATTR_RINGBUFFER)
120 {
121 /* for ring buffer, we start over. */
122 psGEDLogBuf->i32LineCurrent = 0;
123 psGEDLogBuf->i32BufferCurrent = 0;
124 }
125 else if (attrs & GED_LOG_ATTR_QUEUEBUFFER)
126 {
127 if (attrs & GED_LOG_ATTR_AUTO_INCREASE)
128 {
129 int newLineCount, newBufferSize;
130
131 /* incease min(25%, 1MB) */
132 if ((psGEDLogBuf->i32LineCount >> 2) <= 1024 * 1024)
133 {
134 newLineCount = psGEDLogBuf->i32LineCount + (psGEDLogBuf->i32LineCount >> 2);
135 newBufferSize = psGEDLogBuf->i32BufferSize + (psGEDLogBuf->i32BufferSize >> 2);
136 }
137 else
138 {
139 newLineCount = psGEDLogBuf->i32LineCount + 4096;
140 newBufferSize = psGEDLogBuf->i32BufferSize + 1024 * 1024;
141 }
142
143 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
144 if (ged_log_buf_resize(psGEDLogBuf->ui32HashNodeID, newLineCount, newBufferSize) != GED_OK)
145 {
146 return GED_ERROR_OOM;
147 }
148 spin_lock_irqsave(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
149 }
150 else
151 {
152 /* for queuebuffer only, we skip the log. */
153 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
154 return GED_ERROR_OOM;
155 }
156 }
157 }
158
159 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].offset = psGEDLogBuf->i32BufferCurrent;
160 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].tattrs = 0;
161 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].time = 0;
162
163 /* record the kernel time */
164 if (attrs & GED_LOG_ATTR_TIME)
165 {
166 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].tattrs = GED_LOG_ATTR_TIME;
167 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].time = ged_get_time();
168 }
169
170 /* record the user time */
171 if (attrs & GED_LOG_ATTR_TIME_TPT)
172 {
173 struct timeval time;
174 unsigned long local_time;
175
176 do_gettimeofday(&time);
177 local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
178
179 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].tattrs = GED_LOG_ATTR_TIME_TPT;
180 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].time = local_time;
181 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].time_usec = time.tv_usec;
182 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].pid = current->tgid;
183 psGEDLogBuf->psLine[psGEDLogBuf->i32LineCurrent].tid = current->pid;
184 }
185
186 buf_n = psGEDLogBuf->i32BufferSize - psGEDLogBuf->i32BufferCurrent;
187 len = vsnprintf(psGEDLogBuf->pcBuffer + psGEDLogBuf->i32BufferCurrent, buf_n, fmt, args);
188
189 if (len > buf_n) len = buf_n;
190
191 buf_n -= len;
192
193 if (attrs & GED_LOG_ATTR_RINGBUFFER)
194 {
195 int i;
196 int check = 10 + 1; /* we check the following 10 items. */
197 int a = psGEDLogBuf->i32BufferCurrent;
198 int b = psGEDLogBuf->i32BufferCurrent + len + 2;
199
200 for (i = psGEDLogBuf->i32LineCurrent+1; --check && i < psGEDLogBuf->i32LineCount; ++i)
201 {
202 int pos = psGEDLogBuf->psLine[i].offset;
203 if (pos >= a && pos < b)
204 psGEDLogBuf->psLine[i].offset = -1;
205 }
206
207 if (check && i == psGEDLogBuf->i32LineCount)
208 {
209 for (i = 0; --check && i < psGEDLogBuf->i32LineCurrent; ++i)
210 {
211 int pos = psGEDLogBuf->psLine[i].offset;
212
213 if (pos >= a && pos < b)
214 psGEDLogBuf->psLine[i].offset = -1;
215 }
216 }
217 }
218
219 /* update current */
220 psGEDLogBuf->i32BufferCurrent += len + 2;
221 psGEDLogBuf->i32LineCurrent += 1;
222
223 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
224
225 return GED_OK;
226 }
227
228 static GED_ERROR __ged_log_buf_print(GED_LOG_BUF *psGEDLogBuf, const char *fmt, ...)
229 {
230 va_list args;
231 GED_ERROR err;
232
233 va_start(args, fmt);
234 err = __ged_log_buf_vprint(psGEDLogBuf, fmt, args, psGEDLogBuf->attrs | GED_LOG_ATTR_TIME);
235 va_end(args);
236
237 return err;
238 }
239
240 static int __ged_log_buf_write(GED_LOG_BUF *psGEDLogBuf, const char __user *pszBuffer, int i32Count)
241 {
242 int cnt;
243 char buf[256];
244
245 if (!psGEDLogBuf)
246 {
247 return 0;
248 }
249
250 cnt = (i32Count >= 256) ? 255 : i32Count;
251
252 ged_copy_from_user(buf, pszBuffer, cnt);
253
254 buf[cnt] = 0;
255 if (buf[cnt-1] == '\n')
256 {
257 buf[cnt-1] = 0;
258 }
259
260 __ged_log_buf_print(psGEDLogBuf, buf);
261
262 return cnt;
263 }
264
265 static void __ged_log_buf_check_get_early_list(GED_LOG_BUF_HANDLE hLogBuf, const char *pszName)
266 {
267 struct list_head *psListEntry, *psListEntryTemp, *psList;
268 GED_LOG_LISTEN *psFound = NULL, *psLogListen;
269
270 read_lock_bh(&gsGEDLogBufList.sLock);
271
272 psList = &gsGEDLogBufList.sList_listen;
273 list_for_each_safe(psListEntry, psListEntryTemp, psList)
274 {
275 psLogListen = list_entry(psListEntry, GED_LOG_LISTEN, sList);
276 if (0 == strcmp(psLogListen->acName, pszName))
277 {
278 psFound = psLogListen;
279 break;
280 }
281 }
282
283 read_unlock_bh(&gsGEDLogBufList.sLock);
284
285 if (psFound)
286 {
287 write_lock_bh(&gsGEDLogBufList.sLock);
288 *psFound->pCBHnd = hLogBuf;
289 list_del(&psFound->sList);
290 write_unlock_bh(&gsGEDLogBufList.sLock);
291 }
292 }
293
294 static ssize_t ged_log_buf_write_entry(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData)
295 {
296 return (ssize_t)__ged_log_buf_write((GED_LOG_BUF *)pvData, pszBuffer, (int)uiCount);
297 }
298 //-----------------------------------------------------------------------------
299 static void* ged_log_buf_seq_start(struct seq_file *psSeqFile, loff_t *puiPosition)
300 {
301 GED_LOG_BUF *psGEDLogBuf = (GED_LOG_BUF *)psSeqFile->private;
302
303 if (0 == *puiPosition)
304 {
305 return psGEDLogBuf;
306 }
307 return NULL;
308 }
309 //-----------------------------------------------------------------------------
310 static void ged_log_buf_seq_stop(struct seq_file *psSeqFile, void *pvData)
311 {
312
313 }
314 //-----------------------------------------------------------------------------
315 static void* ged_log_buf_seq_next(struct seq_file *psSeqFile, void *pvData, loff_t *puiPosition)
316 {
317 (*puiPosition)++;
318
319 return NULL;
320 }
321 //-----------------------------------------------------------------------------
322 static int ged_log_buf_seq_show_print(struct seq_file *psSeqFile, GED_LOG_BUF *psGEDLogBuf, int i)
323 {
324 int err = 0;
325 GED_LOG_BUF_LINE *line;
326
327 line = &psGEDLogBuf->psLine[i];
328
329 if (line->offset >= 0)
330 {
331 if (line->tattrs & GED_LOG_ATTR_TIME)
332 {
333 unsigned long long t;
334 unsigned long nanosec_rem;
335
336 t = line->time;
337 nanosec_rem = do_div(t, 1000000000);
338
339 seq_printf(psSeqFile,"[%5llu.%06lu] ", t, nanosec_rem / 1000);
340 }
341
342 if (line->tattrs & GED_LOG_ATTR_TIME_TPT)
343 {
344 unsigned long local_time;
345 struct rtc_time tm;
346
347 local_time = line->time;
348 rtc_time_to_tm(local_time, &tm);
349
350 seq_printf(psSeqFile,"%02d-%02d %02d:%02d:%02d.%06lu %5d %5d ",
351 /*tm.tm_year + 1900,*/ tm.tm_mon + 1, tm.tm_mday,
352 tm.tm_hour, tm.tm_min, tm.tm_sec,
353 line->time_usec, line->pid, line->tid);
354 }
355
356 err = seq_printf(psSeqFile, "%s\n", psGEDLogBuf->pcBuffer + line->offset);
357 }
358
359 return err;
360 }
361
362 static int ged_log_buf_seq_show(struct seq_file *psSeqFile, void *pvData)
363 {
364 GED_LOG_BUF *psGEDLogBuf = (GED_LOG_BUF *)pvData;
365
366 if (psGEDLogBuf != NULL)
367 {
368 int i;
369
370 spin_lock_irqsave(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
371
372 if (psGEDLogBuf->acName[0] != '\0')
373 {
374 seq_printf(psSeqFile, "---------- %s (%d/%d) ----------\n",
375 psGEDLogBuf->acName, psGEDLogBuf->i32BufferCurrent, psGEDLogBuf->i32BufferSize);
376 }
377
378 if (psGEDLogBuf->attrs & GED_LOG_ATTR_RINGBUFFER)
379 {
380 for (i = psGEDLogBuf->i32LineCurrent; i < psGEDLogBuf->i32LineCount; ++i)
381 {
382 if (0 != ged_log_buf_seq_show_print(psSeqFile, psGEDLogBuf, i))
383 break;
384 }
385
386 //seq_printf(psSeqFile, " > ---------- start over ----------\n");
387
388 for (i = 0; i < psGEDLogBuf->i32LineCurrent; ++i)
389 {
390 if (0 != ged_log_buf_seq_show_print(psSeqFile, psGEDLogBuf, i))
391 break;
392 }
393 }
394 else if (psGEDLogBuf->attrs & GED_LOG_ATTR_QUEUEBUFFER)
395 {
396 for (i = 0; i < psGEDLogBuf->i32LineCount; ++i)
397 {
398 if (0 != ged_log_buf_seq_show_print(psSeqFile, psGEDLogBuf, i))
399 break;
400 }
401 }
402
403 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
404 }
405
406 return 0;
407 }
408 //-----------------------------------------------------------------------------
409 static struct seq_operations gsGEDLogBufReadOps =
410 {
411 .start = ged_log_buf_seq_start,
412 .stop = ged_log_buf_seq_stop,
413 .next = ged_log_buf_seq_next,
414 .show = ged_log_buf_seq_show,
415 };
416 //-----------------------------------------------------------------------------
417 GED_LOG_BUF_HANDLE ged_log_buf_alloc(
418 int i32MaxLineCount,
419 int i32MaxBufferSizeByte,
420 GED_LOG_BUF_TYPE eType,
421 const char* pszName,
422 const char* pszNodeName)
423 {
424 GED_LOG_BUF *psGEDLogBuf;
425 GED_ERROR error;
426
427 if (((!pszName) && (!pszNodeName)) || (i32MaxLineCount <= 0) || (i32MaxBufferSizeByte <= 0))
428 {
429 return (GED_LOG_BUF_HANDLE)0;
430 }
431
432 psGEDLogBuf = (GED_LOG_BUF*)ged_alloc(sizeof(GED_LOG_BUF));
433 if (NULL == psGEDLogBuf)
434 {
435 GED_LOGE("ged: failed to allocate log buf!\n");
436 return (GED_LOG_BUF_HANDLE)0;
437 }
438
439 psGEDLogBuf->eType = eType;
440
441 switch (eType)
442 {
443 case GED_LOG_BUF_TYPE_RINGBUFFER:
444 psGEDLogBuf->attrs = GED_LOG_ATTR_RINGBUFFER;
445 break;
446 case GED_LOG_BUF_TYPE_QUEUEBUFFER:
447 psGEDLogBuf->attrs = GED_LOG_ATTR_QUEUEBUFFER;
448 break;
449 case GED_LOG_BUF_TYPE_QUEUEBUFFER_AUTO_INCREASE:
450 psGEDLogBuf->attrs = GED_LOG_ATTR_QUEUEBUFFER | GED_LOG_ATTR_AUTO_INCREASE;
451 break;
452 }
453
454 psGEDLogBuf->i32MemorySize = i32MaxBufferSizeByte + sizeof(GED_LOG_BUF_LINE) * i32MaxLineCount;
455 psGEDLogBuf->pMemory = ged_alloc(psGEDLogBuf->i32MemorySize);
456 if (NULL == psGEDLogBuf->pMemory)
457 {
458 ged_free(psGEDLogBuf, sizeof(GED_LOG_BUF));
459 GED_LOGE("ged: failed to allocate log buf!\n");
460 return (GED_LOG_BUF_HANDLE)0;
461 }
462
463 psGEDLogBuf->psLine = (GED_LOG_BUF_LINE *)psGEDLogBuf->pMemory;
464 psGEDLogBuf->pcBuffer = (char *)&psGEDLogBuf->psLine[i32MaxLineCount];
465 psGEDLogBuf->i32LineCount = i32MaxLineCount;
466 psGEDLogBuf->i32BufferSize = i32MaxBufferSizeByte;
467 psGEDLogBuf->i32LineCurrent = 0;
468 psGEDLogBuf->i32BufferCurrent = 0;
469
470 psGEDLogBuf->psEntry = NULL;
471 spin_lock_init(&psGEDLogBuf->sSpinLock);
472 psGEDLogBuf->acName[0] = '\0';
473 psGEDLogBuf->acNodeName[0] = '\0';
474
475 /* Init Line */
476 {
477 int i = 0;
478 for (i = 0; i < psGEDLogBuf->i32LineCount; ++i)
479 psGEDLogBuf->psLine[i].offset = -1;
480 }
481
482 if (pszName)
483 {
484 snprintf(psGEDLogBuf->acName, GED_LOG_BUF_NAME_LENGTH, "%s", pszName);
485 }
486
487 // Add into the global list
488 INIT_LIST_HEAD(&psGEDLogBuf->sList);
489 write_lock_bh(&gsGEDLogBufList.sLock);
490 list_add(&psGEDLogBuf->sList, &gsGEDLogBufList.sList_buf);
491 write_unlock_bh(&gsGEDLogBufList.sLock);
492
493 if (pszNodeName)
494 {
495 int err;
496 snprintf(psGEDLogBuf->acNodeName, GED_LOG_BUF_NODE_NAME_LENGTH, "%s", pszNodeName);
497 err = ged_debugFS_create_entry(
498 psGEDLogBuf->acNodeName,
499 gpsGEDLogBufsDir,
500 &gsGEDLogBufReadOps,
501 ged_log_buf_write_entry,
502 psGEDLogBuf,
503 &psGEDLogBuf->psEntry);
504
505 if (unlikely(err))
506 {
507 GED_LOGE("ged: failed to create %s entry, err(%d)!\n", pszNodeName, err);
508 ged_log_buf_free(psGEDLogBuf->ui32HashNodeID);
509 return (GED_LOG_BUF_HANDLE)0;
510 }
511 }
512
513 error = ged_hashtable_insert(ghHashTable, psGEDLogBuf, &psGEDLogBuf->ui32HashNodeID);
514 if (GED_OK != error)
515 {
516 GED_LOGE("ged: failed to insert into a hash table, err(%d)!\n", error);
517 ged_log_buf_free(psGEDLogBuf->ui32HashNodeID);
518 return (GED_LOG_BUF_HANDLE)0;
519 }
520
521 GED_LOGI("ged_log_buf_alloc OK\n");
522
523 __ged_log_buf_check_get_early_list(psGEDLogBuf->ui32HashNodeID, pszName);
524
525 return (GED_LOG_BUF_HANDLE)psGEDLogBuf->ui32HashNodeID;
526 }
527
528 GED_ERROR ged_log_buf_resize(
529 GED_LOG_BUF_HANDLE hLogBuf,
530 int i32NewMaxLineCount,
531 int i32NewMaxBufferSizeByte)
532 {
533 int i;
534 GED_LOG_BUF *psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
535 int i32NewMemorySize, i32OldMemorySize;
536 void *pNewMemory, *pOldMemory;
537 GED_LOG_BUF_LINE *pi32NewLine;
538 char *pcNewBuffer;
539
540 if ((NULL == psGEDLogBuf) || (i32NewMaxLineCount <= 0) || (i32NewMaxBufferSizeByte <= 0))
541 {
542 return GED_ERROR_INVALID_PARAMS;
543 }
544
545 i32NewMemorySize = i32NewMaxBufferSizeByte + sizeof(GED_LOG_BUF_LINE) * i32NewMaxLineCount;
546 pNewMemory = ged_alloc(i32NewMemorySize);
547 if (NULL == pNewMemory)
548 {
549 return GED_ERROR_OOM;
550 }
551
552 spin_lock_irqsave(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
553
554 pi32NewLine = (GED_LOG_BUF_LINE *)pNewMemory;
555 pcNewBuffer = (char *)&pi32NewLine[i32NewMaxLineCount];
556
557 memcpy(pi32NewLine, psGEDLogBuf->psLine, sizeof(GED_LOG_BUF_LINE) * min(i32NewMaxLineCount, psGEDLogBuf->i32LineCount));
558 memcpy(pcNewBuffer, psGEDLogBuf->pcBuffer, min(i32NewMaxBufferSizeByte, psGEDLogBuf->i32BufferSize));
559
560 for (i = psGEDLogBuf->i32LineCount; i < i32NewMaxLineCount; ++i)
561 pi32NewLine[i].offset = -1;
562
563 i32OldMemorySize = psGEDLogBuf->i32MemorySize;
564 pOldMemory = psGEDLogBuf->pMemory;
565
566 psGEDLogBuf->i32MemorySize = i32NewMemorySize;
567 psGEDLogBuf->pMemory = pNewMemory;
568 psGEDLogBuf->psLine = pi32NewLine;
569 psGEDLogBuf->pcBuffer = pcNewBuffer;
570 psGEDLogBuf->i32LineCount = i32NewMaxLineCount;
571 psGEDLogBuf->i32BufferSize = i32NewMaxBufferSizeByte;
572
573 if (psGEDLogBuf->i32BufferCurrent >= i32NewMaxBufferSizeByte)
574 psGEDLogBuf->i32BufferCurrent = i32NewMaxBufferSizeByte - 1;
575 pcNewBuffer[psGEDLogBuf->i32BufferCurrent] = 0;
576
577 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
578 ged_free(pOldMemory, i32OldMemorySize);
579
580 return GED_OK;
581 }
582
583 GED_ERROR ged_log_buf_ignore_lines(GED_LOG_BUF_HANDLE hLogBuf, int n)
584 {
585 GED_LOG_BUF *psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
586
587 if (psGEDLogBuf && n > 0)
588 {
589 if (psGEDLogBuf->attrs & GED_LOG_ATTR_QUEUEBUFFER)
590 {
591 if (n >= psGEDLogBuf->i32LineCurrent)
592 {
593 /* reset all buffer */
594 ged_log_buf_reset(hLogBuf);
595 }
596 else
597 {
598 int i;
599 int buf_offset;
600 int buf_size;
601
602 spin_lock_irqsave(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
603
604 buf_offset = psGEDLogBuf->psLine[n].offset;
605 buf_size = psGEDLogBuf->i32BufferCurrent - buf_offset;
606
607 /* Move lines, update offset and update current */
608 for (i = 0; n + i < psGEDLogBuf->i32LineCount; ++i)
609 {
610 psGEDLogBuf->psLine[i] = psGEDLogBuf->psLine[n + i];
611 psGEDLogBuf->psLine[i].offset -= buf_offset;
612 }
613 psGEDLogBuf->i32LineCurrent -= n;
614
615 /* Move buffers and update current */
616 for (i = 0; i < buf_size; ++i)
617 psGEDLogBuf->pcBuffer[i] = psGEDLogBuf->pcBuffer[buf_offset + i];
618 psGEDLogBuf->i32BufferCurrent = buf_size;
619
620 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
621 }
622 }
623 }
624
625 return GED_OK;
626 }
627
628 GED_LOG_BUF_HANDLE ged_log_buf_get(const char* pszName)
629 {
630 struct list_head *psListEntry, *psListEntryTemp, *psList;
631 GED_LOG_BUF *psFound = NULL, *psLogBuf;
632
633 if (!pszName)
634 {
635 return (GED_LOG_BUF_HANDLE)0;
636 }
637
638 read_lock_bh(&gsGEDLogBufList.sLock);
639
640 psList = &gsGEDLogBufList.sList_buf;
641 list_for_each_safe(psListEntry, psListEntryTemp, psList)
642 {
643 psLogBuf = list_entry(psListEntry, GED_LOG_BUF, sList);
644 if (0 == strcmp(psLogBuf->acName, pszName))
645 {
646 psFound = psLogBuf;
647 break;
648 }
649 }
650
651 read_unlock_bh(&gsGEDLogBufList.sLock);
652
653 if (!psFound)
654 {
655 return (GED_LOG_BUF_HANDLE)0;
656 }
657
658 return (GED_LOG_BUF_HANDLE)psFound->ui32HashNodeID;
659 }
660
661 int ged_log_buf_get_early(const char* pszName, GED_LOG_BUF_HANDLE *callback_set_handle)
662 {
663 int err = 0;
664
665 if (NULL == pszName)
666 {
667 return GED_ERROR_INVALID_PARAMS;
668 }
669
670 *callback_set_handle = ged_log_buf_get(pszName);
671
672 if (0 == *callback_set_handle)
673 {
674 GED_LOG_LISTEN *psGEDLogListen;
675
676 write_lock_bh(&gsGEDLogBufList.sLock);
677
678 /* search again */
679 {
680 struct list_head *psListEntry, *psListEntryTemp, *psList;
681 GED_LOG_BUF *psFound = NULL, *psLogBuf;
682
683 psList = &gsGEDLogBufList.sList_buf;
684 list_for_each_safe(psListEntry, psListEntryTemp, psList)
685 {
686 psLogBuf = list_entry(psListEntry, GED_LOG_BUF, sList);
687 if (0 == strcmp(psLogBuf->acName, pszName))
688 {
689 psFound = psLogBuf;
690 break;
691 }
692 }
693
694 if (psFound)
695 {
696 *callback_set_handle = (GED_LOG_BUF_HANDLE)psFound->ui32HashNodeID;
697 goto exit_unlock;
698 }
699 }
700
701 /* add to listen list */
702 psGEDLogListen = (GED_LOG_LISTEN*)ged_alloc(sizeof(GED_LOG_LISTEN));
703 if (NULL == psGEDLogListen)
704 {
705 err = GED_ERROR_OOM;
706 goto exit_unlock;
707 }
708 psGEDLogListen->pCBHnd = callback_set_handle;
709 snprintf(psGEDLogListen->acName, GED_LOG_BUF_NAME_LENGTH, "%s", pszName);
710 INIT_LIST_HEAD(&psGEDLogListen->sList);
711 list_add(&psGEDLogListen->sList, &gsGEDLogBufList.sList_listen);
712
713 exit_unlock:
714 write_unlock_bh(&gsGEDLogBufList.sLock);
715 }
716
717 return err;
718 }
719
720 //-----------------------------------------------------------------------------
721 void ged_log_buf_free(GED_LOG_BUF_HANDLE hLogBuf)
722 {
723 GED_LOG_BUF *psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
724 if (psGEDLogBuf)
725 {
726 ged_hashtable_remove(ghHashTable, psGEDLogBuf->ui32HashNodeID);
727
728 write_lock_bh(&gsGEDLogBufList.sLock);
729 list_del(&psGEDLogBuf->sList);
730 write_unlock_bh(&gsGEDLogBufList.sLock);
731
732 if (psGEDLogBuf->psEntry)
733 {
734 ged_debugFS_remove_entry(psGEDLogBuf->psEntry);
735 }
736
737 ged_free(psGEDLogBuf->pMemory, psGEDLogBuf->i32MemorySize);
738 ged_free(psGEDLogBuf, sizeof(GED_LOG_BUF));
739
740 GED_LOGI("ged_log_buf_free OK\n");
741 }
742 }
743 //-----------------------------------------------------------------------------
744 GED_ERROR ged_log_buf_print(GED_LOG_BUF_HANDLE hLogBuf, const char *fmt, ...)
745 {
746 va_list args;
747 GED_ERROR err;
748 GED_LOG_BUF *psGEDLogBuf;
749
750 if (hLogBuf)
751 {
752 psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
753
754 va_start(args, fmt);
755 err = __ged_log_buf_vprint(psGEDLogBuf, fmt, args, psGEDLogBuf->attrs);
756 va_end(args);
757 }
758
759 return GED_OK;
760 }
761 GED_ERROR ged_log_buf_print2(GED_LOG_BUF_HANDLE hLogBuf, int i32LogAttrs, const char *fmt, ...)
762 {
763 va_list args;
764 GED_ERROR err;
765 GED_LOG_BUF *psGEDLogBuf;
766
767 if (hLogBuf)
768 {
769 psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
770
771 /* clear reserved attrs */
772 i32LogAttrs &= ~0xff;
773
774 va_start(args, fmt);
775 err = __ged_log_buf_vprint(psGEDLogBuf, fmt, args, psGEDLogBuf->attrs | i32LogAttrs);
776 va_end(args);
777 }
778
779 return GED_OK;
780 }
781 //-----------------------------------------------------------------------------
782 GED_ERROR ged_log_buf_reset(GED_LOG_BUF_HANDLE hLogBuf)
783 {
784 GED_LOG_BUF *psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
785 if (psGEDLogBuf)
786 {
787 int i;
788 spin_lock_irqsave(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
789
790 psGEDLogBuf->i32LineCurrent = 0;
791 psGEDLogBuf->i32BufferCurrent = 0;
792 for (i = 0; i < psGEDLogBuf->i32LineCount; ++i)
793 {
794 psGEDLogBuf->psLine[i].offset = -1;
795 }
796
797 spin_unlock_irqrestore(&psGEDLogBuf->sSpinLock, psGEDLogBuf->ui32IRQFlags);
798 }
799
800 return GED_OK;
801 }
802
803 //-----------------------------------------------------------------------------
804 //
805 // GED Log System
806 //
807 //-----------------------------------------------------------------------------
808 static ssize_t ged_log_write_entry(const char __user *pszBuffer, size_t uiCount, loff_t uiPosition, void *pvData)
809 {
810 #define GED_LOG_CMD_SIZE 64
811 char acBuffer[GED_LOG_CMD_SIZE];
812
813 int i32Value;
814
815 if ((0 < uiCount) && (uiCount < GED_LOG_CMD_SIZE))
816 {
817 if (0 == ged_copy_from_user(acBuffer, pszBuffer, uiCount))
818 {
819 acBuffer[uiCount - 1] = '\0';
820 if (strcmp(acBuffer, "reset") == 0)
821 {
822 struct list_head *psListEntry, *psListEntryTemp, *psList;
823 write_lock_bh(&gsGEDLogBufList.sLock);
824 psList = &gsGEDLogBufList.sList_buf;
825 list_for_each_safe(psListEntry, psListEntryTemp, psList)
826 {
827 GED_LOG_BUF* psGEDLogBuf = (GED_LOG_BUF*)list_entry(psListEntry, GED_LOG_BUF, sList);
828 ged_log_buf_reset(psGEDLogBuf->ui32HashNodeID);
829 }
830 write_unlock_bh(&gsGEDLogBufList.sLock);
831 }
832 else if (strcmp(acBuffer, "profile_dvfs_enable") == 0)
833 {
834 ged_profile_dvfs_enable();
835 }
836 else if (strcmp(acBuffer, "profile_dvfs_disable") == 0)
837 {
838 ged_profile_dvfs_disable();
839 }
840 else if (strcmp(acBuffer, "profile_dvfs_start") == 0)
841 {
842 ged_profile_dvfs_start();
843 }
844 else if (strcmp(acBuffer, "profile_dvfs_stop") == 0)
845 {
846 ged_profile_dvfs_stop();
847 }
848 else if (sscanf(acBuffer, "profile_dvfs_ignore_lines %d", &i32Value) == 1)
849 {
850 ged_profile_dvfs_ignore_lines(i32Value);
851 }
852 //else if (...) //for other commands
853 //{
854 //}
855 }
856 }
857
858 return uiCount;
859 }
860 //-----------------------------------------------------------------------------
861 static void* ged_log_seq_start(struct seq_file *psSeqFile, loff_t *puiPosition)
862 {
863 struct list_head *psListEntry, *psListEntryTemp, *psList;
864 loff_t uiCurrentPosition = 0;
865
866 read_lock_bh(&gsGEDLogBufList.sLock);
867
868 psList = &gsGEDLogBufList.sList_buf;
869 list_for_each_safe(psListEntry, psListEntryTemp, psList)
870 {
871 GED_LOG_BUF* psGEDLogBuf = (GED_LOG_BUF*)list_entry(psListEntry, GED_LOG_BUF, sList);
872 if (psGEDLogBuf->acName[0] != '\0')
873 {
874 if (uiCurrentPosition == *puiPosition)
875 {
876 return psGEDLogBuf;
877 }
878 uiCurrentPosition ++;
879 }
880 }
881
882 return NULL;
883 }
884 //-----------------------------------------------------------------------------
885 static void ged_log_seq_stop(struct seq_file *psSeqFile, void *pvData)
886 {
887 read_unlock_bh(&gsGEDLogBufList.sLock);
888 }
889 //-----------------------------------------------------------------------------
890 static void* ged_log_seq_next(struct seq_file *psSeqFile, void *pvData, loff_t *puiPosition)
891 {
892 struct list_head *psListEntry, *psListEntryTemp, *psList;
893 loff_t uiCurrentPosition = 0;
894
895 (*puiPosition)++;
896
897 psList = &gsGEDLogBufList.sList_buf;
898 list_for_each_safe(psListEntry, psListEntryTemp, psList)
899 {
900 GED_LOG_BUF* psGEDLogBuf = (GED_LOG_BUF*)list_entry(psListEntry, GED_LOG_BUF, sList);
901 if (psGEDLogBuf->acName[0] != '\0')
902 {
903 if (uiCurrentPosition == *puiPosition)
904 {
905 return psGEDLogBuf;
906 }
907 uiCurrentPosition ++;
908 }
909 }
910
911 return NULL;
912 }
913 //-----------------------------------------------------------------------------
914 static struct seq_operations gsGEDLogReadOps =
915 {
916 .start = ged_log_seq_start,
917 .stop = ged_log_seq_stop,
918 .next = ged_log_seq_next,
919 .show = ged_log_buf_seq_show,
920 };
921 //-----------------------------------------------------------------------------
922 GED_ERROR ged_log_system_init(void)
923 {
924 GED_ERROR err = GED_OK;
925
926 err = ged_debugFS_create_entry(
927 "gedlog",
928 NULL,
929 &gsGEDLogReadOps,
930 ged_log_write_entry,
931 NULL,
932 &gpsGEDLogEntry);
933
934 if (unlikely(err != GED_OK))
935 {
936 GED_LOGE("ged: failed to create gedlog entry!\n");
937 goto ERROR;
938 }
939
940 err = ged_debugFS_create_entry_dir(
941 "logbufs",
942 NULL,
943 &gpsGEDLogBufsDir);
944
945 if (unlikely(err != GED_OK))
946 {
947 err = GED_ERROR_FAIL;
948 GED_LOGE("ged: failed to create logbufs dir!\n");
949 goto ERROR;
950 }
951
952 ghHashTable = ged_hashtable_create(5);
953 if (!ghHashTable)
954 {
955 err = GED_ERROR_OOM;
956 GED_LOGE("ged: failed to create a hash table!\n");
957 goto ERROR;
958 }
959
960 return err;
961
962 ERROR:
963
964 ged_log_system_exit();
965
966 return err;
967 }
968 //-----------------------------------------------------------------------------
969 void ged_log_system_exit(void)
970 {
971 ged_hashtable_destroy(ghHashTable);
972
973 ged_debugFS_remove_entry(gpsGEDLogEntry);
974 }
975 //-----------------------------------------------------------------------------
976 int ged_log_buf_write(GED_LOG_BUF_HANDLE hLogBuf, const char __user *pszBuffer, int i32Count)
977 {
978 GED_LOG_BUF *psGEDLogBuf = ged_log_buf_from_handle(hLogBuf);
979 return __ged_log_buf_write(psGEDLogBuf, pszBuffer, i32Count);
980 }
981
982 EXPORT_SYMBOL(ged_log_buf_alloc);
983 EXPORT_SYMBOL(ged_log_buf_reset);
984 EXPORT_SYMBOL(ged_log_buf_get);
985 EXPORT_SYMBOL(ged_log_buf_get_early);
986 EXPORT_SYMBOL(ged_log_buf_free);
987 EXPORT_SYMBOL(ged_log_buf_print);
988 EXPORT_SYMBOL(ged_log_buf_print2);