Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include <linux/uaccess.h> |
2 | #include <linux/module.h> | |
3 | #include <linux/types.h> | |
4 | #include <linux/device.h> | |
5 | #include <linux/fs.h> | |
6 | #include <linux/platform_device.h> | |
7 | #include <linux/cdev.h> | |
8 | //#include <asm/io.h> | |
9 | #include <linux/proc_fs.h> //proc file use | |
10 | #include <linux/slab.h> //kmalloc/kfree in kernel 3.10 | |
11 | #include <linux/spinlock.h> | |
12 | #include <linux/mm.h> | |
13 | #include <linux/sched.h> | |
14 | #include <linux/delay.h> | |
15 | #include <linux/ioctl.h> | |
16 | #include <linux/xlog.h> | |
17 | #include <mach/mt_reg_base.h> | |
18 | #include <mach/mt_clkmgr.h> | |
19 | #include <mach/sync_write.h> | |
20 | #include <mach/camera_sysram.h> | |
21 | #include <mach/mt_reg_base.h> | |
22 | #include <mach/camera_sysram_imp.h> | |
23 | ||
24 | #define ISP_VALID_REG_RANGE 0x10000 | |
25 | #define IMGSYS_BASE_ADDR 0x15000000 | |
26 | ||
27 | //----------------------------------------------------------------------------- | |
28 | static SYSRAM_STRUCT Sysram; | |
29 | //------------------------------------------------------------------------------ | |
30 | static void SYSRAM_GetTime(MUINT64* pUS64, MUINT32* pSec, MUINT32* pUSec) | |
31 | { | |
32 | ktime_t Time; | |
33 | MUINT64 TimeSec; | |
34 | // | |
35 | Time = ktime_get();//ns | |
36 | TimeSec = Time.tv64; | |
37 | do_div( TimeSec, 1000 ); | |
38 | // | |
39 | *pUS64 = TimeSec; | |
40 | *pUSec = do_div( TimeSec, 1000000); | |
41 | *pSec = (MUINT64)TimeSec; | |
42 | } | |
43 | //------------------------------------------------------------------------------ | |
44 | static void SYSRAM_CheckClock(void) | |
45 | { | |
46 | //LOG_MSG("AllocatedTbl(0x%08X),EnableClk(%d)",Sysram.AllocatedTbl,Sysram.EnableClk); | |
47 | if(Sysram.AllocatedTbl) | |
48 | { | |
49 | if(!(Sysram.EnableClk)) | |
50 | { | |
51 | Sysram.EnableClk = true; | |
52 | /* | |
53 | LOG_MSG("AllocatedTbl(0x%08lX),EnableClk(%d)", | |
54 | Sysram.AllocatedTbl, | |
55 | Sysram.EnableClk); | |
56 | */ | |
57 | } | |
58 | } | |
59 | else | |
60 | { | |
61 | if(Sysram.EnableClk) | |
62 | { | |
63 | Sysram.EnableClk = false; | |
64 | /* | |
65 | LOG_MSG("AllocatedTbl(0x%08lX),EnableClk(%d)", | |
66 | Sysram.AllocatedTbl, | |
67 | Sysram.EnableClk); | |
68 | */ | |
69 | } | |
70 | } | |
71 | } | |
72 | //------------------------------------------------------------------------------ | |
73 | static void SYSRAM_DumpResMgr(void) | |
74 | { | |
75 | unsigned int u4Idx = 0; | |
76 | LOG_MSG("TotalUserCount(%ld),AllocatedTbl(0x%lX)", | |
77 | Sysram.TotalUserCount, | |
78 | Sysram.AllocatedTbl); | |
79 | // | |
80 | for (u4Idx = 0; u4Idx < SYSRAM_USER_AMOUNT; u4Idx++) | |
81 | { | |
82 | if ( 0 < Sysram.AllocatedSize[u4Idx] ) | |
83 | { | |
84 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[u4Idx]; | |
85 | LOG_MSG("[id:%u][%s][size:0x%lX][pid:%d][tgid:%d][%s][%5lu.%06lu]", | |
86 | u4Idx, | |
87 | SysramUserName[u4Idx], | |
88 | Sysram.AllocatedSize[u4Idx], | |
89 | pUserInfo->pid, | |
90 | pUserInfo->tgid, | |
91 | pUserInfo->ProcName, | |
92 | pUserInfo->TimeS, | |
93 | pUserInfo->TimeUS); | |
94 | } | |
95 | } | |
96 | LOG_MSG("End"); | |
97 | } | |
98 | //------------------------------------------------------------------------------ | |
99 | static inline MBOOL SYSRAM_IsBadOwner(SYSRAM_USER_ENUM const User) | |
100 | { | |
101 | if(SYSRAM_USER_AMOUNT <= User || User < 0) | |
102 | { | |
103 | return MTRUE; | |
104 | } | |
105 | else | |
106 | { | |
107 | return MFALSE; | |
108 | } | |
109 | } | |
110 | //------------------------------------------------------------------------------ | |
111 | static void SYSRAM_SetUserTaskInfo(SYSRAM_USER_ENUM const User) | |
112 | { | |
113 | if(!SYSRAM_IsBadOwner(User)) | |
114 | { | |
115 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[User]; | |
116 | // | |
117 | pUserInfo->pid = current->pid; | |
118 | pUserInfo->tgid = current->tgid; | |
119 | memcpy(pUserInfo->ProcName, current->comm, sizeof(pUserInfo->ProcName)); | |
120 | // | |
121 | SYSRAM_GetTime(&(pUserInfo->Time64), &(pUserInfo->TimeS), &(pUserInfo->TimeUS)); | |
122 | } | |
123 | } | |
124 | //------------------------------------------------------------------------------ | |
125 | static void SYSRAM_ResetUserTaskInfo(SYSRAM_USER_ENUM const User) | |
126 | { | |
127 | if(!SYSRAM_IsBadOwner(User)) | |
128 | { | |
129 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[User]; | |
130 | memset(pUserInfo, 0, sizeof(*pUserInfo)); | |
131 | } | |
132 | } | |
133 | //------------------------------------------------------------------------------ | |
134 | static inline void SYSRAM_SpinLock(void) | |
135 | { | |
136 | spin_lock(&Sysram.SpinLock); | |
137 | } | |
138 | //------------------------------------------------------------------------------ | |
139 | static inline void SYSRAM_SpinUnlock(void) | |
140 | { | |
141 | spin_unlock(&Sysram.SpinLock); | |
142 | } | |
143 | //------------------------------------------------------------------------------ | |
144 | static inline MBOOL SYSRAM_UserIsLocked(SYSRAM_USER_ENUM const User) | |
145 | { | |
146 | if((1 << User) & Sysram.AllocatedTbl) | |
147 | { | |
148 | return MTRUE; | |
149 | } | |
150 | else | |
151 | { | |
152 | return MFALSE; | |
153 | } | |
154 | } | |
155 | //------------------------------------------------------------------------------ | |
156 | static inline MBOOL SYSRAM_UserIsUnlocked(SYSRAM_USER_ENUM const User) | |
157 | { | |
158 | if(SYSRAM_UserIsLocked(User) == 0) | |
159 | { | |
160 | return MTRUE; | |
161 | } | |
162 | else | |
163 | { | |
164 | return MFALSE; | |
165 | } | |
166 | } | |
167 | //------------------------------------------------------------------------------ | |
168 | static void SYSRAM_LockUser(SYSRAM_USER_ENUM const User, MUINT32 const Size) | |
169 | { | |
170 | if(SYSRAM_UserIsLocked(User)) | |
171 | { | |
172 | return; | |
173 | } | |
174 | // | |
175 | Sysram.TotalUserCount++; | |
176 | Sysram.AllocatedTbl |= (1 << User); | |
177 | Sysram.AllocatedSize[User] = Size; | |
178 | SYSRAM_SetUserTaskInfo(User); | |
179 | //Debug Log. | |
180 | if((1<<User) & SysramLogUserMask) | |
181 | { | |
182 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[User]; | |
183 | LOG_MSG("[%s][%lu bytes]OK,Time(%lu.%06lu)", | |
184 | SysramUserName[User], | |
185 | Sysram.AllocatedSize[User], | |
186 | pUserInfo->TimeS, | |
187 | pUserInfo->TimeUS); | |
188 | } | |
189 | } | |
190 | //------------------------------------------------------------------------------ | |
191 | static void SYSRAM_UnlockUser(SYSRAM_USER_ENUM const User) | |
192 | { if(SYSRAM_UserIsUnlocked(User)) | |
193 | { | |
194 | return; | |
195 | } | |
196 | // Debug Log. | |
197 | if((1<<User) & SysramLogUserMask) | |
198 | { | |
199 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[User]; | |
200 | MUINT32 Sec, USec; | |
201 | MUINT64 Time64 = 0; | |
202 | SYSRAM_GetTime(&Time64,&Sec,&USec); | |
203 | // | |
204 | LOG_MSG("[%s][%lu bytes]Time(%lu.%06lu - %lu.%06lu)(%lu.%06lu)", | |
205 | SysramUserName[User], | |
206 | Sysram.AllocatedSize[User], | |
207 | pUserInfo->TimeS, | |
208 | pUserInfo->TimeUS, | |
209 | Sec, | |
210 | USec, | |
211 | ((MUINT32)(Time64-pUserInfo->Time64))/1000, | |
212 | ((MUINT32)(Time64-pUserInfo->Time64))%1000); | |
213 | } | |
214 | // | |
215 | if(Sysram.TotalUserCount > 0) | |
216 | { | |
217 | Sysram.TotalUserCount--; | |
218 | } | |
219 | Sysram.AllocatedTbl &= (~(1 << User)); | |
220 | Sysram.AllocatedSize[User] = 0; | |
221 | SYSRAM_ResetUserTaskInfo(User); | |
222 | } | |
223 | //------------------------------------------------------------------------------ | |
224 | static void SYSRAM_DumpLayout(void) | |
225 | { | |
226 | MUINT32 Index = 0; | |
227 | SYSRAM_MEM_NODE_STRUCT* pCurrNode = NULL; | |
228 | // | |
229 | LOG_DMP("[SYSRAM_DumpLayout]\n"); | |
230 | LOG_DMP("AllocatedTbl = 0x%08lX\n",Sysram.AllocatedTbl); | |
231 | LOG_DMP("=========================================\n"); | |
232 | for (Index = 0; Index < SYSRAM_MEM_BANK_AMOUNT; Index++) | |
233 | { | |
234 | LOG_DMP("\n [Mem Pool %ld] (IndexTbl, UserCount)=(%lX, %ld)\n", | |
235 | Index, | |
236 | SysramMemPoolInfo[Index].IndexTbl, | |
237 | SysramMemPoolInfo[Index].UserCount); | |
238 | LOG_DMP("[Locked Time] [Owner Offset Size Index pCurrent pPrevious pNext] [pid tgid] [Proc Name / Owner Name]\n"); | |
239 | pCurrNode = &SysramMemPoolInfo[Index].pMemNode[0]; | |
240 | while(NULL != pCurrNode) | |
241 | { | |
242 | SYSRAM_USER_ENUM const User = pCurrNode->User; | |
243 | if(SYSRAM_IsBadOwner(User)) | |
244 | { | |
245 | LOG_DMP( | |
246 | "------------ --------" | |
247 | " %2d\t0x%05lX 0x%05lX %ld %p %p\t%p\n", | |
248 | pCurrNode->User, | |
249 | pCurrNode->Offset, | |
250 | pCurrNode->Length, | |
251 | pCurrNode->Index, | |
252 | pCurrNode, | |
253 | pCurrNode->pPrev, | |
254 | pCurrNode->pNext); | |
255 | } | |
256 | else | |
257 | { | |
258 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[User]; | |
259 | LOG_DMP("%5lu.%06lu" | |
260 | " %2d\t0x%05lX 0x%05lX %ld %p %p\t%p" | |
261 | " %-4d %-4d \"%s\" / \"%s\"\n", | |
262 | pUserInfo->TimeS, | |
263 | pUserInfo->TimeUS, | |
264 | User, | |
265 | pCurrNode->Offset, | |
266 | pCurrNode->Length, | |
267 | pCurrNode->Index, | |
268 | pCurrNode, | |
269 | pCurrNode->pPrev, | |
270 | pCurrNode->pNext, | |
271 | pUserInfo->pid, | |
272 | pUserInfo->tgid, | |
273 | pUserInfo->ProcName, | |
274 | SysramUserName[User]); | |
275 | } | |
276 | pCurrNode = pCurrNode->pNext; | |
277 | }; | |
278 | } | |
279 | LOG_DMP("\n"); | |
280 | SYSRAM_DumpResMgr(); | |
281 | } | |
282 | //------------------------------------------------------------------------------ | |
283 | static SYSRAM_MEM_NODE_STRUCT* SYSRAM_AllocNode(SYSRAM_MEM_POOL_STRUCT*const pMemPoolInfo) | |
284 | { | |
285 | SYSRAM_MEM_NODE_STRUCT* pNode = NULL; | |
286 | MUINT32 Index = 0; | |
287 | // | |
288 | for(Index = 0; Index < pMemPoolInfo->UserAmount; Index+=1) | |
289 | { | |
290 | if((pMemPoolInfo->IndexTbl) & (1 << Index)) | |
291 | { | |
292 | pMemPoolInfo->IndexTbl &= (~(1 << Index)); | |
293 | // A free node is found. | |
294 | pNode = &pMemPoolInfo->pMemNode[Index]; | |
295 | pNode->User = SYSRAM_USER_NONE; | |
296 | pNode->Offset = 0; | |
297 | pNode->Length = 0; | |
298 | pNode->pPrev = NULL; | |
299 | pNode->pNext = NULL; | |
300 | pNode->Index = Index; | |
301 | break; | |
302 | } | |
303 | } | |
304 | // Shouldn't happen. | |
305 | if( ! pNode ) | |
306 | { | |
307 | LOG_ERR("returns NULL - pMemPoolInfo->IndexTbl(%lX)",pMemPoolInfo->IndexTbl); | |
308 | } | |
309 | return pNode; | |
310 | } | |
311 | //------------------------------------------------------------------------------ | |
312 | static void SYSRAM_FreeNode( | |
313 | SYSRAM_MEM_POOL_STRUCT*const pMemPoolInfo, | |
314 | SYSRAM_MEM_NODE_STRUCT*const pNode) | |
315 | { | |
316 | pMemPoolInfo->IndexTbl |= (1<<pNode->Index); | |
317 | pNode->User = SYSRAM_USER_NONE; | |
318 | pNode->Offset = 0; | |
319 | pNode->Length = 0; | |
320 | pNode->pPrev = NULL; | |
321 | pNode->pNext = NULL; | |
322 | pNode->Index = 0; | |
323 | } | |
324 | //------------------------------------------------------------------------------ | |
325 | static MBOOL SYSRAM_IsLegalSizeToAlloc( | |
326 | SYSRAM_MEM_BANK_ENUM const MemBankNo, | |
327 | SYSRAM_USER_ENUM const User, | |
328 | MUINT32 const Size) | |
329 | { | |
330 | MUINT32 MaxSize = 0; | |
331 | // (1) Check the memory pool. | |
332 | switch(MemBankNo) | |
333 | { | |
334 | case SYSRAM_MEM_BANK_BAD: | |
335 | case SYSRAM_MEM_BANK_AMOUNT: | |
336 | { | |
337 | // Illegal Memory Pool: return "illegal" | |
338 | // Shouldn't happen. | |
339 | goto EXIT; | |
340 | } | |
341 | default: | |
342 | { | |
343 | break; | |
344 | } | |
345 | } | |
346 | // (2) | |
347 | // Here we use the dynamic memory pools. | |
348 | MaxSize = SysramUserSize[User]; | |
349 | // | |
350 | EXIT: | |
351 | if(MaxSize < Size) | |
352 | { | |
353 | LOG_ERR("[User:%s]requested size(0x%lX) > max size(0x%lX)", | |
354 | SysramUserName[User], | |
355 | Size, | |
356 | MaxSize); | |
357 | SYSRAM_DumpLayout(); | |
358 | return MFALSE; | |
359 | } | |
360 | return MTRUE; | |
361 | } | |
362 | //------------------------------------------------------------------------------ | |
363 | /* | |
364 | Alignment should be 2^N, 4/8/2048 bytes alignment only | |
365 | First fit algorithm | |
366 | */ | |
367 | static MUINT32 SYSRAM_AllocUserPhy( | |
368 | SYSRAM_USER_ENUM const User, | |
369 | MUINT32 const Size, | |
370 | MUINT32 const Alignment, | |
371 | SYSRAM_MEM_BANK_ENUM const MemBankNo | |
372 | ) | |
373 | { | |
374 | SYSRAM_MEM_NODE_STRUCT* pSplitNode = NULL; | |
375 | SYSRAM_MEM_NODE_STRUCT* pCurrNode = NULL; | |
376 | MUINT32 AlingnedAddr = 0; | |
377 | MUINT32 ActualSize = 0; | |
378 | // | |
379 | SYSRAM_MEM_POOL_STRUCT*const pMemPoolInfo = SYSRAM_GetMemPoolInfo(MemBankNo); | |
380 | if(!pMemPoolInfo) | |
381 | { | |
382 | return 0; | |
383 | } | |
384 | // | |
385 | pCurrNode = &pMemPoolInfo->pMemNode[0]; | |
386 | for (; pCurrNode && pCurrNode->Offset < pMemPoolInfo->Size; pCurrNode = pCurrNode->pNext) | |
387 | { | |
388 | if(SYSRAM_USER_NONE == pCurrNode->User) | |
389 | { | |
390 | //Free space | |
391 | AlingnedAddr = (pCurrNode->Offset + Alignment - 1)&(~(Alignment - 1)); | |
392 | ActualSize = Size + AlingnedAddr - pCurrNode->Offset; | |
393 | if (ActualSize <= pCurrNode->Length) | |
394 | { | |
395 | // Hit!! Split into 2 | |
396 | // pSplitNode pointers to the next available (free) node. | |
397 | pSplitNode = SYSRAM_AllocNode(pMemPoolInfo); | |
398 | pSplitNode->Offset = pCurrNode->Offset + ActualSize; | |
399 | pSplitNode->Length = pCurrNode->Length - ActualSize; | |
400 | pSplitNode->pPrev = pCurrNode; | |
401 | pSplitNode->pNext = pCurrNode->pNext; | |
402 | // | |
403 | pCurrNode->User = User; | |
404 | pCurrNode->Length = ActualSize; | |
405 | pCurrNode->pNext = pSplitNode; | |
406 | // | |
407 | if(NULL != pSplitNode->pNext) | |
408 | { | |
409 | pSplitNode->pNext->pPrev = pSplitNode; | |
410 | } | |
411 | // | |
412 | pMemPoolInfo->UserCount++; | |
413 | break; | |
414 | } | |
415 | //Not hit | |
416 | ActualSize = 0; | |
417 | } | |
418 | }; | |
419 | // | |
420 | return ActualSize ? (AlingnedAddr + pMemPoolInfo->Addr) : 0; | |
421 | } | |
422 | //------------------------------------------------------------------------------ | |
423 | static MBOOL SYSRAM_FreeUserPhy( | |
424 | SYSRAM_USER_ENUM const User, | |
425 | SYSRAM_MEM_BANK_ENUM const MemBankNo) | |
426 | { | |
427 | MBOOL Ret = MFALSE; | |
428 | SYSRAM_MEM_NODE_STRUCT* pPrevOrNextNode = NULL; | |
429 | SYSRAM_MEM_NODE_STRUCT* pCurrNode = NULL; | |
430 | SYSRAM_MEM_NODE_STRUCT* pTempNode = NULL; | |
431 | SYSRAM_MEM_POOL_STRUCT*const pMemPoolInfo = SYSRAM_GetMemPoolInfo(MemBankNo); | |
432 | // | |
433 | if(!pMemPoolInfo) | |
434 | { | |
435 | LOG_ERR("pMemPoolInfo==NULL,User(%d),MemBankNo(%d)",User,MemBankNo); | |
436 | return MFALSE; | |
437 | } | |
438 | // | |
439 | pCurrNode = &pMemPoolInfo->pMemNode[0]; | |
440 | for(; pCurrNode; pCurrNode = pCurrNode->pNext) | |
441 | { | |
442 | if(User == pCurrNode->User) | |
443 | { | |
444 | Ret = MTRUE; // user is found. | |
445 | if ( pMemPoolInfo->UserCount > 0 ) | |
446 | pMemPoolInfo->UserCount--; | |
447 | ||
448 | pCurrNode->User = SYSRAM_USER_NONE; | |
449 | if(NULL != pCurrNode->pPrev) | |
450 | { | |
451 | pPrevOrNextNode = pCurrNode->pPrev; | |
452 | // | |
453 | if(SYSRAM_USER_NONE == pPrevOrNextNode->User) | |
454 | { | |
455 | //Merge previous: prev(o) + curr(x) | |
456 | pTempNode = pCurrNode; | |
457 | pCurrNode = pPrevOrNextNode; | |
458 | pCurrNode->Length += pTempNode->Length; | |
459 | pCurrNode->pNext = pTempNode->pNext; | |
460 | if(NULL != pTempNode->pNext) | |
461 | { | |
462 | pTempNode->pNext->pPrev = pCurrNode; | |
463 | } | |
464 | SYSRAM_FreeNode(pMemPoolInfo, pTempNode); | |
465 | } | |
466 | } | |
467 | ||
468 | if(NULL != pCurrNode->pNext) | |
469 | { | |
470 | pPrevOrNextNode = pCurrNode->pNext; | |
471 | // | |
472 | if(SYSRAM_USER_NONE == pPrevOrNextNode->User) | |
473 | { | |
474 | //Merge next: curr(o) + next(x) | |
475 | pTempNode = pPrevOrNextNode; | |
476 | pCurrNode->Length += pTempNode->Length; | |
477 | pCurrNode->pNext = pTempNode->pNext; | |
478 | if(NULL != pCurrNode->pNext) | |
479 | { | |
480 | pCurrNode->pNext->pPrev = pCurrNode; | |
481 | } | |
482 | SYSRAM_FreeNode(pMemPoolInfo, pTempNode); | |
483 | } | |
484 | } | |
485 | break; | |
486 | } | |
487 | } | |
488 | // | |
489 | return Ret; | |
490 | } | |
491 | //------------------------------------------------------------------------------ | |
492 | static MUINT32 SYSRAM_AllocUser( | |
493 | SYSRAM_USER_ENUM const User, | |
494 | MUINT32 Size, | |
495 | MUINT32 const Alignment) | |
496 | { | |
497 | MUINT32 Addr = 0; | |
498 | SYSRAM_MEM_BANK_ENUM const MemBankNo = SYSRAM_GetMemBankNo(User); | |
499 | // | |
500 | if(SYSRAM_IsBadOwner(User)) | |
501 | { | |
502 | LOG_ERR("User(%d) out of range(%d)",User,SYSRAM_USER_AMOUNT); | |
503 | return 0; | |
504 | } | |
505 | // | |
506 | if(!SYSRAM_IsLegalSizeToAlloc(MemBankNo, User, Size)) | |
507 | { | |
508 | return 0; | |
509 | } | |
510 | // | |
511 | switch (MemBankNo) | |
512 | { | |
513 | case SYSRAM_MEM_BANK_BAD: | |
514 | case SYSRAM_MEM_BANK_AMOUNT: | |
515 | { | |
516 | // Do nothing. | |
517 | break; | |
518 | } | |
519 | default: | |
520 | { | |
521 | Addr = SYSRAM_AllocUserPhy( | |
522 | User, | |
523 | Size, | |
524 | Alignment, | |
525 | MemBankNo); | |
526 | break; | |
527 | } | |
528 | } | |
529 | // | |
530 | if(0 < Addr) | |
531 | { | |
532 | SYSRAM_LockUser(User,Size); | |
533 | } | |
534 | // | |
535 | return Addr; | |
536 | } | |
537 | //------------------------------------------------------------------------------ | |
538 | static void SYSRAM_FreeUser(SYSRAM_USER_ENUM const User) | |
539 | { | |
540 | SYSRAM_MEM_BANK_ENUM const MemBankNo = SYSRAM_GetMemBankNo(User); | |
541 | // | |
542 | switch(MemBankNo) | |
543 | { | |
544 | case SYSRAM_MEM_BANK_BAD: | |
545 | case SYSRAM_MEM_BANK_AMOUNT: | |
546 | { | |
547 | // Do nothing. | |
548 | break; | |
549 | } | |
550 | default: | |
551 | { | |
552 | if(SYSRAM_FreeUserPhy(User, MemBankNo)) | |
553 | { | |
554 | SYSRAM_UnlockUser(User); | |
555 | } | |
556 | else | |
557 | { | |
558 | LOG_ERR("Cannot free User(%d)",User); | |
559 | SYSRAM_DumpLayout(); | |
560 | } | |
561 | break; | |
562 | } | |
563 | } | |
564 | } | |
565 | //------------------------------------------------------------------------------ | |
566 | static MUINT32 SYSRAM_MsToJiffies(MUINT32 TimeMs) | |
567 | { | |
568 | return ((TimeMs*HZ + 512) >> 10); | |
569 | } | |
570 | //------------------------------------------------------------------------------ | |
571 | static MUINT32 SYSRAM_TryAllocUser( | |
572 | SYSRAM_USER_ENUM const User, | |
573 | MUINT32 const Size, | |
574 | MUINT32 const Alignment) | |
575 | { | |
576 | MUINT32 Addr = 0; | |
577 | // | |
578 | SYSRAM_SpinLock(); | |
579 | // | |
580 | if(SYSRAM_UserIsLocked(User)) | |
581 | { | |
582 | SYSRAM_SpinUnlock(); | |
583 | LOG_ERR("[User:%s]has been already allocated!",SysramUserName[User]); | |
584 | return 0; | |
585 | } | |
586 | // | |
587 | Addr = SYSRAM_AllocUser(User, Size, Alignment); | |
588 | if(Addr != 0) | |
589 | { | |
590 | SYSRAM_CheckClock(); | |
591 | } | |
592 | SYSRAM_SpinUnlock(); | |
593 | // | |
594 | return Addr; | |
595 | } | |
596 | //------------------------------------------------------------------------------ | |
597 | static MUINT32 SYSRAM_IOC_Alloc( | |
598 | SYSRAM_USER_ENUM const User, | |
599 | MUINT32 const Size, | |
600 | MUINT32 Alignment, | |
601 | MUINT32 const TimeoutMS) | |
602 | { | |
603 | MUINT32 Addr = 0; | |
604 | INT32 TimeOut = 0; | |
605 | // | |
606 | if(SYSRAM_IsBadOwner(User)) | |
607 | { | |
608 | LOG_ERR("User(%d) out of range(%d)",User,SYSRAM_USER_AMOUNT); | |
609 | return 0; | |
610 | } | |
611 | // | |
612 | if(0 == Size) | |
613 | { | |
614 | LOG_ERR("[User:%s]allocates 0 size!",SysramUserName[User]); | |
615 | return 0; | |
616 | } | |
617 | // | |
618 | Addr = SYSRAM_TryAllocUser(User, Size, Alignment); | |
619 | if ( | |
620 | 0 != Addr //success | |
621 | || 0 == TimeoutMS //failure without a timeout specified | |
622 | ) | |
623 | { | |
624 | goto EXIT; | |
625 | } | |
626 | // | |
627 | TimeOut = wait_event_interruptible_timeout( | |
628 | Sysram.WaitQueueHead, | |
629 | 0 != ( Addr = SYSRAM_TryAllocUser(User, Size, Alignment) ), | |
630 | SYSRAM_MsToJiffies(TimeoutMS)); | |
631 | // | |
632 | if(0 == TimeOut && 0 == Addr ) | |
633 | { | |
634 | LOG_ERR("[User:%s]allocate timeout",SysramUserName[User]); | |
635 | } | |
636 | // | |
637 | EXIT: | |
638 | if (0 == Addr) | |
639 | { // Failure | |
640 | LOG_ERR("[User:%s]fails to allocate.Size(%lu),Alignment(%lu),TimeoutMS(%lu)", | |
641 | SysramUserName[User], | |
642 | Size, | |
643 | Alignment, | |
644 | TimeoutMS); | |
645 | SYSRAM_DumpLayout(); | |
646 | } | |
647 | else | |
648 | { // Success | |
649 | if ( (1<<User) & SysramLogUserMask ) | |
650 | { | |
651 | LOG_MSG("[User:%s]%lu bytes OK", | |
652 | SysramUserName[User], | |
653 | Size); | |
654 | } | |
655 | } | |
656 | // | |
657 | return Addr; | |
658 | } | |
659 | //------------------------------------------------------------------------------ | |
660 | static void SYSRAM_IOC_Free(SYSRAM_USER_ENUM User) | |
661 | { | |
662 | if(SYSRAM_IsBadOwner(User)) | |
663 | { | |
664 | LOG_ERR("User(%d) out of range(%d)",User,SYSRAM_USER_AMOUNT); | |
665 | return; | |
666 | } | |
667 | // | |
668 | SYSRAM_SpinLock(); | |
669 | SYSRAM_FreeUser(User); | |
670 | wake_up_interruptible(&Sysram.WaitQueueHead); | |
671 | SYSRAM_CheckClock(); | |
672 | SYSRAM_SpinUnlock(); | |
673 | // | |
674 | if((1<<User) & SysramLogUserMask) | |
675 | { | |
676 | LOG_MSG("[User:%s]Done",SysramUserName[User]); | |
677 | } | |
678 | } | |
679 | //------------------------------------------------------------------------------ | |
680 | static int SYSRAM_Open( | |
681 | struct inode* pInode, | |
682 | struct file* pFile) | |
683 | { | |
684 | int Ret = 0; | |
685 | MUINT32 Sec = 0,USec = 0; | |
686 | MUINT64 Time64 = 0; | |
687 | SYSRAM_PROC_STRUCT* pProc; | |
688 | // | |
689 | SYSRAM_GetTime(&Time64, &Sec, &USec); | |
690 | // | |
691 | LOG_MSG("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
692 | current->comm, | |
693 | current->pid, | |
694 | current->tgid, | |
695 | Sec, | |
696 | USec); | |
697 | // | |
698 | SYSRAM_SpinLock(); | |
699 | // | |
700 | pFile->private_data = kmalloc(sizeof(SYSRAM_PROC_STRUCT) , GFP_ATOMIC); | |
701 | if(pFile->private_data == NULL) | |
702 | { | |
703 | Ret = -ENOMEM; | |
704 | } | |
705 | else | |
706 | { | |
707 | pProc = (SYSRAM_PROC_STRUCT*)(pFile->private_data); | |
708 | pProc->Pid = 0; | |
709 | pProc->Tgid = 0; | |
710 | strcpy(pProc->ProcName,SYSRAM_PROC_NAME); | |
711 | pProc->Table = 0; | |
712 | pProc->Time64 = Time64; | |
713 | pProc->TimeS = Sec; | |
714 | pProc->TimeUS = USec; | |
715 | } | |
716 | // | |
717 | SYSRAM_SpinUnlock(); | |
718 | // | |
719 | if(Ret == (-ENOMEM)) | |
720 | { | |
721 | LOG_ERR("No enough memory"); | |
722 | /* | |
723 | LOG_ERR("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
724 | current->comm, | |
725 | current->pid, | |
726 | current->tgid, | |
727 | Sec, | |
728 | USec); | |
729 | */ | |
730 | } | |
731 | // | |
732 | return Ret; | |
733 | } | |
734 | //------------------------------------------------------------------------------ | |
735 | static int SYSRAM_Release( | |
736 | struct inode* pInode, | |
737 | struct file* pFile) | |
738 | { | |
739 | MUINT32 Index = 0; | |
740 | MUINT32 Sec = 0,USec = 0; | |
741 | MUINT64 Time64 = 0; | |
742 | SYSRAM_PROC_STRUCT* pProc; | |
743 | // | |
744 | SYSRAM_GetTime(&Time64, &Sec, &USec); | |
745 | // | |
746 | LOG_MSG("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
747 | current->comm, | |
748 | current->pid, | |
749 | current->tgid, | |
750 | Sec, | |
751 | USec); | |
752 | // | |
753 | if(pFile->private_data != NULL) | |
754 | { | |
755 | pProc = (SYSRAM_PROC_STRUCT*)(pFile->private_data); | |
756 | // | |
757 | if( pProc->Pid != 0 || | |
758 | pProc->Tgid != 0 || | |
759 | pProc->Table != 0) | |
760 | { | |
761 | // | |
762 | LOG_WRN("Proc:Name(%s),pid(%d),tgid(%d),Table(0x%08lX),Time(%ld.%06ld)", | |
763 | pProc->ProcName, | |
764 | pProc->Pid, | |
765 | pProc->Tgid, | |
766 | pProc->Table, | |
767 | pProc->TimeS, | |
768 | pProc->TimeUS); | |
769 | // | |
770 | if(pProc->Table) | |
771 | { | |
772 | LOG_WRN("Force to release"); | |
773 | /* | |
774 | LOG_WRN("Proc:Name(%s),pid(%d),tgid(%d),Table(0x%08lX),Time(%ld.%06ld)", | |
775 | pProc->ProcName, | |
776 | pProc->Pid, | |
777 | pProc->Tgid, | |
778 | pProc->Table, | |
779 | pProc->TimeS, | |
780 | pProc->TimeUS); | |
781 | */ | |
782 | SYSRAM_DumpLayout(); | |
783 | // | |
784 | for(Index = 0 ; Index < SYSRAM_USER_AMOUNT; Index++) | |
785 | { | |
786 | if(pProc->Table & (1 << Index)) | |
787 | { | |
788 | SYSRAM_IOC_Free((SYSRAM_USER_ENUM)Index); | |
789 | } | |
790 | } | |
791 | } | |
792 | } | |
793 | // | |
794 | kfree(pFile->private_data); | |
795 | pFile->private_data = NULL; | |
796 | } | |
797 | else | |
798 | { | |
799 | LOG_WRN("private_data is NULL"); | |
800 | /* | |
801 | LOG_WRN("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
802 | current->comm, | |
803 | current->pid, | |
804 | current->tgid, | |
805 | Sec, | |
806 | USec); | |
807 | */ | |
808 | } | |
809 | // | |
810 | return 0; | |
811 | } | |
812 | //------------------------------------------------------------------------------ | |
813 | static int SYSRAM_Flush( | |
814 | struct file* pFile, | |
815 | fl_owner_t Id) | |
816 | { | |
817 | MUINT32 Index = 0; | |
818 | MUINT32 Sec = 0,USec = 0; | |
819 | MUINT64 Time64 = 0; | |
820 | SYSRAM_PROC_STRUCT* pProc; | |
821 | // | |
822 | SYSRAM_GetTime(&Time64, &Sec, &USec); | |
823 | // | |
824 | LOG_MSG("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
825 | current->comm, | |
826 | current->pid, | |
827 | current->tgid, | |
828 | Sec, | |
829 | USec); | |
830 | // | |
831 | if(pFile->private_data != NULL) | |
832 | { | |
833 | pProc = (SYSRAM_PROC_STRUCT *)pFile->private_data; | |
834 | // | |
835 | if( pProc->Pid != 0 || | |
836 | pProc->Tgid != 0 || | |
837 | pProc->Table != 0) | |
838 | { | |
839 | // | |
840 | LOG_WRN("Proc:Name(%s),pid(%d),tgid(%d),Table(0x%08lX),Time(%ld.%06ld)", | |
841 | pProc->ProcName, | |
842 | pProc->Pid, | |
843 | pProc->Tgid, | |
844 | pProc->Table, | |
845 | pProc->TimeS, | |
846 | pProc->TimeUS); | |
847 | // | |
848 | if( pProc->Tgid == 0 && | |
849 | pProc->Table != 0) | |
850 | { | |
851 | LOG_ERR("No Tgid info"); | |
852 | /* | |
853 | LOG_ERR("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
854 | current->comm, | |
855 | current->pid, | |
856 | current->tgid, | |
857 | Sec, | |
858 | USec); | |
859 | LOG_ERR("Proc:Name(%s),pid(%d),tgid(%d),Table(0x%08lX),Time(%ld.%06ld)", | |
860 | pProc->ProcName, | |
861 | pProc->Pid, | |
862 | pProc->Tgid, | |
863 | pProc->Table, | |
864 | pProc->TimeS, | |
865 | pProc->TimeUS); | |
866 | */ | |
867 | } | |
868 | else | |
869 | if( (pProc->Tgid == current->tgid) || | |
870 | ((pProc->Tgid != current->tgid) && (strcmp(current->comm, "binder") == 0))) | |
871 | { | |
872 | if(pProc->Table) | |
873 | { | |
874 | LOG_WRN("Force to release"); | |
875 | /* | |
876 | LOG_WRN("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
877 | current->comm, | |
878 | current->pid, | |
879 | current->tgid, | |
880 | Sec, | |
881 | USec); | |
882 | */ | |
883 | SYSRAM_DumpLayout(); | |
884 | // | |
885 | for(Index = 0 ; Index < SYSRAM_USER_AMOUNT; Index++) | |
886 | { | |
887 | if(pProc->Table & (1 << Index)) | |
888 | { | |
889 | SYSRAM_IOC_Free((SYSRAM_USER_ENUM)Index); | |
890 | } | |
891 | } | |
892 | // | |
893 | pProc->Table= 0; | |
894 | } | |
895 | } | |
896 | ||
897 | } | |
898 | } | |
899 | else | |
900 | { | |
901 | LOG_WRN("private_data is NULL"); | |
902 | /* | |
903 | LOG_WRN("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
904 | current->comm, | |
905 | current->pid, | |
906 | current->tgid, | |
907 | Sec, | |
908 | USec); | |
909 | */ | |
910 | } | |
911 | // | |
912 | return 0; | |
913 | } | |
914 | //------------------------------------------------------------------------------ | |
915 | static int SYSRAM_mmap( | |
916 | struct file* pFile, | |
917 | struct vm_area_struct* pVma) | |
918 | { | |
919 | //LOG_MSG(""); | |
920 | long length = 0; | |
921 | MUINT32 pfn=0x0; | |
922 | pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot); | |
923 | length=(long)(pVma->vm_end - pVma->vm_start); | |
924 | pfn=pVma->vm_pgoff<<PAGE_SHIFT;//page from number, physical address of kernel memory | |
925 | LOG_WRN("pVma->vm_pgoff(0x%x),phy(0x%x),pVmapVma->vm_start(0x%x),pVma->vm_end(0x%x),length(0x%x)",\ | |
926 | pVma->vm_pgoff,pVma->vm_pgoff<<PAGE_SHIFT,pVma->vm_start,pVma->vm_end,length); | |
927 | if((length>ISP_VALID_REG_RANGE) || (pfn<IMGSYS_BASE_ADDR) || (pfn>(IMGSYS_BASE_ADDR+ISP_VALID_REG_RANGE))) | |
928 | { | |
929 | LOG_ERR("mmap range error : vm_start(0x%x),vm_end(0x%x),length(0x%x),pfn(0x%x)!",pVma->vm_start,pVma->vm_end,length,pfn); | |
930 | return -EAGAIN; | |
931 | } | |
932 | if(remap_pfn_range( | |
933 | pVma, | |
934 | pVma->vm_start, | |
935 | pVma->vm_pgoff, | |
936 | pVma->vm_end - pVma->vm_start, | |
937 | pVma->vm_page_prot)) | |
938 | { | |
939 | LOG_ERR("fail"); | |
940 | return -EAGAIN; | |
941 | } | |
942 | return 0; | |
943 | } | |
944 | //------------------------------------------------------------------------------ | |
945 | static long SYSRAM_Ioctl( | |
946 | struct file* pFile, | |
947 | unsigned int Cmd, | |
948 | unsigned long Param) | |
949 | { | |
950 | MINT32 Ret = 0; | |
951 | MUINT32 Sec = 0,USec = 0; | |
952 | MUINT64 Time64 = 0; | |
953 | SYSRAM_PROC_STRUCT* pProc = (SYSRAM_PROC_STRUCT*)pFile->private_data; | |
954 | SYSRAM_ALLOC_STRUCT Alloc; | |
955 | SYSRAM_USER_ENUM User; | |
956 | // | |
957 | SYSRAM_GetTime(&Time64, &Sec, &USec); | |
958 | /* | |
959 | LOG_MSG("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
960 | current->comm, | |
961 | current->pid, | |
962 | current->tgid, | |
963 | Sec, | |
964 | USec); | |
965 | */ | |
966 | if(pFile->private_data == NULL) | |
967 | { | |
968 | LOG_WRN("private_data is NULL."); | |
969 | Ret = -EFAULT; | |
970 | goto EXIT; | |
971 | } | |
972 | // | |
973 | switch(Cmd) | |
974 | { | |
975 | case SYSRAM_ALLOC: | |
976 | { | |
977 | if(copy_from_user(&Alloc, (void*)Param, sizeof(SYSRAM_ALLOC_STRUCT)) == 0) | |
978 | { | |
979 | if(SYSRAM_IsBadOwner(Alloc.User)) | |
980 | { | |
981 | LOG_ERR("User(%d) out of range(%d)",Alloc.User,SYSRAM_USER_AMOUNT); | |
982 | Ret = -EFAULT; | |
983 | goto EXIT; | |
984 | } | |
985 | // | |
986 | Alloc.Addr = SYSRAM_IOC_Alloc( | |
987 | Alloc.User, | |
988 | Alloc.Size, | |
989 | Alloc.Alignment, | |
990 | Alloc.TimeoutMS); | |
991 | if(Alloc.Addr != 0) | |
992 | { | |
993 | SYSRAM_SpinLock(); | |
994 | pProc->Table |= (1 << Alloc.User); | |
995 | if(pProc->Tgid == 0) | |
996 | { | |
997 | pProc->Pid = current->pid; | |
998 | pProc->Tgid = current->tgid; | |
999 | strcpy(pProc->ProcName,current->comm); | |
1000 | SYSRAM_SpinUnlock(); | |
1001 | } | |
1002 | else | |
1003 | { | |
1004 | SYSRAM_SpinUnlock(); | |
1005 | if(pProc->Tgid != current->tgid) | |
1006 | { | |
1007 | LOG_ERR("Tgid is inconsistent"); | |
1008 | Ret = -EFAULT; | |
1009 | } | |
1010 | } | |
1011 | } | |
1012 | else | |
1013 | { | |
1014 | Ret = -EFAULT; | |
1015 | } | |
1016 | // | |
1017 | if(copy_to_user((void*)Param, &Alloc, sizeof(SYSRAM_ALLOC_STRUCT)) ) | |
1018 | { | |
1019 | LOG_ERR("copy to user failed"); | |
1020 | Ret = -EFAULT; | |
1021 | } | |
1022 | } | |
1023 | else | |
1024 | { | |
1025 | LOG_ERR("copy_from_user fail"); | |
1026 | Ret = -EFAULT; | |
1027 | } | |
1028 | break; | |
1029 | } | |
1030 | // | |
1031 | case SYSRAM_FREE: | |
1032 | { | |
1033 | if(copy_from_user(&User, (void*)Param, sizeof(SYSRAM_USER_ENUM)) == 0) | |
1034 | { | |
1035 | if(SYSRAM_IsBadOwner(User)) | |
1036 | { | |
1037 | LOG_ERR("User(%d) out of range(%d)",User,SYSRAM_USER_AMOUNT); | |
1038 | Ret = -EFAULT; | |
1039 | goto EXIT; | |
1040 | } | |
1041 | // | |
1042 | SYSRAM_SpinLock(); | |
1043 | if((pProc->Table) & (1 << User)) | |
1044 | { | |
1045 | SYSRAM_SpinUnlock(); | |
1046 | SYSRAM_IOC_Free(User); | |
1047 | SYSRAM_SpinLock(); | |
1048 | // | |
1049 | pProc->Table &= (~(1 << User)); | |
1050 | if(pProc->Table == 0) | |
1051 | { | |
1052 | pProc->Pid = 0; | |
1053 | pProc->Tgid = 0; | |
1054 | strcpy(pProc->ProcName,SYSRAM_PROC_NAME); | |
1055 | } | |
1056 | SYSRAM_SpinUnlock(); | |
1057 | } | |
1058 | else | |
1059 | { | |
1060 | SYSRAM_SpinUnlock(); | |
1061 | LOG_WRN("Freeing unallocated buffer user(%d)",User); | |
1062 | Ret = -EFAULT; | |
1063 | } | |
1064 | } | |
1065 | else | |
1066 | { | |
1067 | LOG_ERR("copy_from_user fail"); | |
1068 | Ret = -EFAULT; | |
1069 | } | |
1070 | break; | |
1071 | } | |
1072 | case SYSRAM_DUMP: | |
1073 | { | |
1074 | SYSRAM_DumpLayout(); | |
1075 | break; | |
1076 | } | |
1077 | default: | |
1078 | { | |
1079 | LOG_WRN("No such command"); | |
1080 | Ret = -EINVAL; | |
1081 | break; | |
1082 | } | |
1083 | } | |
1084 | // | |
1085 | EXIT: | |
1086 | if(Ret != 0) | |
1087 | { | |
1088 | LOG_ERR("Fail"); | |
1089 | LOG_ERR("Cur:Name(%s),pid(%d),tgid(%d),Time(%ld.%06ld)", | |
1090 | current->comm, | |
1091 | current->pid, | |
1092 | current->tgid, | |
1093 | Sec, | |
1094 | USec); | |
1095 | if(pFile->private_data != NULL) | |
1096 | { | |
1097 | LOG_ERR("Proc:Name(%s),pid(%d),tgid(%d),Table(0x%08lX),Time(%ld.%06ld)", | |
1098 | pProc->ProcName, | |
1099 | pProc->Pid, | |
1100 | pProc->Tgid, | |
1101 | pProc->Table, | |
1102 | Sec, | |
1103 | USec); | |
1104 | } | |
1105 | } | |
1106 | // | |
1107 | return Ret; | |
1108 | } | |
1109 | //------------------------------------------------------------------------------ | |
1110 | static const struct file_operations SysramFileOper = | |
1111 | { | |
1112 | .owner = THIS_MODULE, | |
1113 | .open = SYSRAM_Open, | |
1114 | .release = SYSRAM_Release, | |
1115 | .flush = SYSRAM_Flush, | |
1116 | .unlocked_ioctl = SYSRAM_Ioctl, | |
1117 | .mmap = SYSRAM_mmap, | |
1118 | }; | |
1119 | //------------------------------------------------------------------------------ | |
1120 | static inline int SYSRAM_RegCharDrv(void) | |
1121 | { | |
1122 | LOG_MSG("E"); | |
1123 | if(alloc_chrdev_region(&Sysram.DevNo, 0, 1,SYSRAM_DEV_NAME) ) | |
1124 | { | |
1125 | LOG_ERR("allocate device no failed"); | |
1126 | return -EAGAIN; | |
1127 | } | |
1128 | //allocate driver | |
1129 | Sysram.pCharDrv = cdev_alloc(); | |
1130 | if(Sysram.pCharDrv == NULL) | |
1131 | { | |
1132 | unregister_chrdev_region(Sysram.DevNo, 1); | |
1133 | LOG_ERR("allocate mem for kobject failed"); | |
1134 | return -ENOMEM; | |
1135 | } | |
1136 | //Attatch file operation. | |
1137 | cdev_init(Sysram.pCharDrv, &SysramFileOper); | |
1138 | Sysram.pCharDrv->owner = THIS_MODULE; | |
1139 | //Add to system | |
1140 | if(cdev_add(Sysram.pCharDrv, Sysram.DevNo, 1)) | |
1141 | { | |
1142 | LOG_ERR("Attatch file operation failed"); | |
1143 | unregister_chrdev_region(Sysram.DevNo, 1); | |
1144 | return -EAGAIN; | |
1145 | } | |
1146 | LOG_MSG("X"); | |
1147 | return 0; | |
1148 | } | |
1149 | //------------------------------------------------------------------------------ | |
1150 | static inline void SYSRAM_UnregCharDrv(void) | |
1151 | { | |
1152 | LOG_MSG("E"); | |
1153 | //Release char driver | |
1154 | cdev_del(Sysram.pCharDrv); | |
1155 | unregister_chrdev_region(Sysram.DevNo, 1); | |
1156 | LOG_MSG("X"); | |
1157 | } | |
1158 | //------------------------------------------------------------------------------ | |
1159 | static int SYSRAM_Probe(struct platform_device *pDev) | |
1160 | { | |
1161 | MINT32 Ret = 0; | |
1162 | MUINT32 Index = 0; | |
1163 | struct device* sysram_device = NULL; | |
1164 | // | |
1165 | LOG_MSG("E"); | |
1166 | //register char driver | |
1167 | //allocate major no | |
1168 | if(SYSRAM_RegCharDrv()) | |
1169 | { | |
1170 | LOG_ERR("register char failed"); | |
1171 | return -EAGAIN; | |
1172 | } | |
1173 | ||
1174 | Sysram.pClass = class_create(THIS_MODULE, "SysramDrv"); | |
1175 | if(IS_ERR(Sysram.pClass)) | |
1176 | { | |
1177 | Ret = PTR_ERR(Sysram.pClass); | |
1178 | LOG_ERR("Unable to create class, err(%ld)", Ret); | |
1179 | return Ret; | |
1180 | } | |
1181 | sysram_device = device_create( | |
1182 | Sysram.pClass, | |
1183 | NULL, | |
1184 | Sysram.DevNo, | |
1185 | NULL, | |
1186 | SYSRAM_DEV_NAME); | |
1187 | //Initialize variables | |
1188 | spin_lock_init(&Sysram.SpinLock); | |
1189 | Sysram.TotalUserCount = 0; | |
1190 | Sysram.AllocatedTbl = 0; | |
1191 | memset(Sysram.AllocatedSize, 0, sizeof(Sysram.AllocatedSize)); | |
1192 | memset(Sysram.UserInfo, 0, sizeof(Sysram.UserInfo)); | |
1193 | init_waitqueue_head(&Sysram.WaitQueueHead); | |
1194 | Sysram.EnableClk = MFALSE; | |
1195 | // | |
1196 | for(Index = 0; Index < SYSRAM_MEM_BANK_AMOUNT; Index++) | |
1197 | { | |
1198 | SysramMemPoolInfo[Index].pMemNode[0].User = SYSRAM_USER_NONE; | |
1199 | SysramMemPoolInfo[Index].pMemNode[0].Offset = 0; | |
1200 | SysramMemPoolInfo[Index].pMemNode[0].Length = SysramMemPoolInfo[Index].Size; | |
1201 | SysramMemPoolInfo[Index].pMemNode[0].Index = 0; | |
1202 | SysramMemPoolInfo[Index].pMemNode[0].pNext = NULL; | |
1203 | SysramMemPoolInfo[Index].pMemNode[0].pPrev = NULL; | |
1204 | SysramMemPoolInfo[Index].IndexTbl = (~0x1); | |
1205 | SysramMemPoolInfo[Index].UserCount= 0; | |
1206 | } | |
1207 | // | |
1208 | for(Index = 0; Index < SYSRAM_USER_AMOUNT; Index++) | |
1209 | { | |
1210 | Sysram.AllocatedSize[Index] = 0; | |
1211 | } | |
1212 | Sysram.DebugFlag = SYSRAM_DEBUG_DEFAULT; | |
1213 | // | |
1214 | LOG_MSG("X"); | |
1215 | return Ret; | |
1216 | } | |
1217 | //------------------------------------------------------------------------------ | |
1218 | static int SYSRAM_Remove(struct platform_device *pDev) | |
1219 | { | |
1220 | LOG_MSG("E"); | |
1221 | //unregister char driver. | |
1222 | SYSRAM_UnregCharDrv(); | |
1223 | // | |
1224 | device_destroy(Sysram.pClass, Sysram.DevNo); | |
1225 | class_destroy(Sysram.pClass); | |
1226 | // | |
1227 | LOG_MSG("X"); | |
1228 | // | |
1229 | return 0; | |
1230 | } | |
1231 | //------------------------------------------------------------------------------ | |
1232 | static int SYSRAM_Suspend( | |
1233 | struct platform_device* pDev, | |
1234 | pm_message_t Mesg) | |
1235 | { | |
1236 | LOG_MSG(""); | |
1237 | return 0; | |
1238 | } | |
1239 | //------------------------------------------------------------------------------ | |
1240 | static int SYSRAM_Resume(struct platform_device *pDev) | |
1241 | { | |
1242 | LOG_MSG(""); | |
1243 | return 0; | |
1244 | } | |
1245 | //------------------------------------------------------------------------------ | |
1246 | static struct platform_driver SysramPlatformDriver = | |
1247 | { | |
1248 | .probe = SYSRAM_Probe, | |
1249 | .remove = SYSRAM_Remove, | |
1250 | .suspend = SYSRAM_Suspend, | |
1251 | .resume = SYSRAM_Resume, | |
1252 | .driver = | |
1253 | { | |
1254 | .name = SYSRAM_DEV_NAME, | |
1255 | .owner = THIS_MODULE, | |
1256 | } | |
1257 | }; | |
1258 | //------------------------------------------------------------------------------ | |
1259 | static int SYSRAM_DumpLayoutToProc( | |
1260 | char* pPage, | |
1261 | char** ppStart, | |
1262 | off_t Off, | |
1263 | int Count, | |
1264 | int* pEof, | |
1265 | void* pData) | |
1266 | { | |
1267 | char *p = pPage; | |
1268 | MUINT32 len = 0; | |
1269 | MUINT32 Index = 0; | |
1270 | SYSRAM_MEM_NODE_STRUCT* pCurrNode = NULL; | |
1271 | // | |
1272 | p += sprintf(p, "\n[SYSRAM_DumpLayoutToProc]\n"); | |
1273 | p += sprintf(p, "AllocatedTbl = 0x%08lX\n",Sysram.AllocatedTbl); | |
1274 | p += sprintf(p, "=========================================\n" ); | |
1275 | for (Index = 0; Index < SYSRAM_MEM_BANK_AMOUNT; Index++) | |
1276 | { | |
1277 | p += sprintf(p, "\n [Mem Pool %ld] (IndexTbl, UserCount)=(%lX, %ld)\n", | |
1278 | Index, | |
1279 | SysramMemPoolInfo[Index].IndexTbl, | |
1280 | SysramMemPoolInfo[Index].UserCount); | |
1281 | p += sprintf(p, "[Locked Time] [Owner Offset Size Index pCurrent pPrevious pNext] [pid tgid] [Proc Name / Owner Name]\n"); | |
1282 | pCurrNode = &SysramMemPoolInfo[Index].pMemNode[0]; | |
1283 | while ( NULL != pCurrNode ) | |
1284 | { | |
1285 | SYSRAM_USER_ENUM const User = pCurrNode->User; | |
1286 | if ( SYSRAM_IsBadOwner(User) ) | |
1287 | { | |
1288 | p += sprintf(p, | |
1289 | "------------ --------" | |
1290 | " %2d\t0x%05lX 0x%05lX %ld %p %p\t%p\n", | |
1291 | pCurrNode->User, | |
1292 | pCurrNode->Offset, | |
1293 | pCurrNode->Length, | |
1294 | pCurrNode->Index, | |
1295 | pCurrNode, | |
1296 | pCurrNode->pPrev, | |
1297 | pCurrNode->pNext | |
1298 | ); | |
1299 | } | |
1300 | else | |
1301 | { | |
1302 | SYSRAM_USER_STRUCT*const pUserInfo = &Sysram.UserInfo[User]; | |
1303 | p += sprintf(p, | |
1304 | "%5lu.%06lu" | |
1305 | " %2d\t0x%05lX 0x%05lX %ld %p %p\t%p" | |
1306 | " %-4d %-4d \"%s\" / \"%s\"\n", | |
1307 | pUserInfo->TimeS, | |
1308 | pUserInfo->TimeUS, | |
1309 | User, | |
1310 | pCurrNode->Offset, | |
1311 | pCurrNode->Length, | |
1312 | pCurrNode->Index, | |
1313 | pCurrNode, | |
1314 | pCurrNode->pPrev, | |
1315 | pCurrNode->pNext, | |
1316 | pUserInfo->pid, | |
1317 | pUserInfo->tgid, | |
1318 | pUserInfo->ProcName, | |
1319 | SysramUserName[User]); | |
1320 | } | |
1321 | pCurrNode = pCurrNode->pNext; | |
1322 | }; | |
1323 | } | |
1324 | // | |
1325 | *ppStart = pPage + Off; | |
1326 | len = p - pPage; | |
1327 | if(len > Off) | |
1328 | { | |
1329 | len -= Off; | |
1330 | } | |
1331 | else | |
1332 | { | |
1333 | len = 0; | |
1334 | } | |
1335 | // | |
1336 | return len < Count ? len : Count; | |
1337 | } | |
1338 | //------------------------------------------------------------------------------ | |
1339 | static int SYSRAM_ReadFlag( | |
1340 | char* pPage, | |
1341 | char** ppStart, | |
1342 | off_t Off, | |
1343 | int Count, | |
1344 | int* pEof, | |
1345 | void* pData) | |
1346 | { | |
1347 | char *p = pPage; | |
1348 | MUINT32 len = 0; | |
1349 | // | |
1350 | p += sprintf(p, "\r\n[SYSRAM_ReadFlag]\r\n"); | |
1351 | p += sprintf(p, "=========================================\r\n" ); | |
1352 | p += sprintf(p, "Sysram.DebugFlag = 0x%08lX\r\n",Sysram.DebugFlag); | |
1353 | ||
1354 | *ppStart = pPage + Off; | |
1355 | ||
1356 | len = p - pPage; | |
1357 | if(len > Off) | |
1358 | { | |
1359 | len -= Off; | |
1360 | } | |
1361 | else | |
1362 | { | |
1363 | len = 0; | |
1364 | } | |
1365 | // | |
1366 | return len < Count ? len : Count; | |
1367 | } | |
1368 | //------------------------------------------------------------------------------ | |
1369 | static int SYSRAM_WriteFlag( | |
1370 | struct file* pFile, | |
1371 | const char* pBuffer, | |
1372 | unsigned long Count, | |
1373 | void* pData) | |
1374 | { | |
1375 | char acBuf[32]; | |
1376 | MUINT32 u4CopySize = 0; | |
1377 | MUINT32 u4SysramDbgFlag = 0; | |
1378 | // | |
1379 | u4CopySize = (Count < (sizeof(acBuf) - 1)) ? Count : (sizeof(acBuf) - 1); | |
1380 | if(copy_from_user(acBuf, pBuffer, u4CopySize)) | |
1381 | { | |
1382 | return 0; | |
1383 | } | |
1384 | acBuf[u4CopySize] = '\0'; | |
1385 | if(3 == sscanf(acBuf, "%lx", &u4SysramDbgFlag)) | |
1386 | { | |
1387 | Sysram.DebugFlag = u4SysramDbgFlag; | |
1388 | } | |
1389 | return Count; | |
1390 | } | |
1391 | ||
1392 | /******************************************************************************* | |
1393 | * | |
1394 | ********************************************************************************/ | |
1395 | static const struct file_operations fsysram_proc_fops = { | |
1396 | .read = SYSRAM_DumpLayoutToProc, | |
1397 | .write = NULL, | |
1398 | }; | |
1399 | static const struct file_operations fsysram_flag_proc_fops = { | |
1400 | .read = SYSRAM_ReadFlag, | |
1401 | .write = SYSRAM_WriteFlag, | |
1402 | }; | |
1403 | ||
1404 | //----------------------------------------------------------------------------- | |
1405 | static int __init SYSRAM_Init(void) | |
1406 | { | |
1407 | struct proc_dir_entry *pEntry; | |
1408 | // | |
1409 | LOG_MSG("E"); | |
1410 | // | |
1411 | if(platform_driver_register(&SysramPlatformDriver)) | |
1412 | { | |
1413 | LOG_ERR("failed to register sysram driver"); | |
1414 | return -ENODEV; | |
1415 | } | |
1416 | // | |
1417 | //linux-3.10 procfs API changed | |
1418 | #if 1 | |
1419 | proc_create("sysram",0,NULL,&fsysram_proc_fops); | |
1420 | proc_create("sysram_flag",0,NULL,&fsysram_flag_proc_fops); | |
1421 | #else | |
1422 | pEntry = create_proc_entry("sysram", 0, NULL); | |
1423 | if(pEntry) | |
1424 | { | |
1425 | pEntry->read_proc = SYSRAM_DumpLayoutToProc; | |
1426 | pEntry->write_proc = NULL; | |
1427 | } | |
1428 | else | |
1429 | { | |
1430 | LOG_ERR("add /proc/sysram entry fail."); | |
1431 | } | |
1432 | // | |
1433 | pEntry = create_proc_entry("sysram_flag", 0, NULL); | |
1434 | if(pEntry) | |
1435 | { | |
1436 | pEntry->read_proc = SYSRAM_ReadFlag; | |
1437 | pEntry->write_proc = SYSRAM_WriteFlag; | |
1438 | } | |
1439 | else | |
1440 | { | |
1441 | LOG_ERR("add /proc/sysram_flag entry fail"); | |
1442 | } | |
1443 | #endif | |
1444 | LOG_MSG("X"); | |
1445 | // | |
1446 | return 0; | |
1447 | } | |
1448 | //------------------------------------------------------------------------------ | |
1449 | static void __exit SYSRAM_Exit(void) | |
1450 | { | |
1451 | LOG_MSG("E"); | |
1452 | platform_driver_unregister(&SysramPlatformDriver); | |
1453 | LOG_MSG("X"); | |
1454 | } | |
1455 | //------------------------------------------------------------------------------ | |
1456 | module_init(SYSRAM_Init); | |
1457 | module_exit(SYSRAM_Exit); | |
1458 | MODULE_DESCRIPTION("Camera sysram driver"); | |
1459 | MODULE_AUTHOR("Marx <marx.chiu@mediatek.com>"); | |
1460 | MODULE_LICENSE("GPL"); | |
1461 | //------------------------------------------------------------------------------ | |
1462 |