ged_log.c 31 KB

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