drm_memory.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:12k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
  2.  * Created: Thu Feb  4 14:00:34 1999 by faith@valinux.com
  3.  *
  4.  * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
  5.  * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
  6.  * All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice (including the next
  16.  * paragraph) shall be included in all copies or substantial portions of the
  17.  * Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  23.  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  24.  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  25.  * OTHER DEALINGS IN THE SOFTWARE.
  26.  *
  27.  * Authors:
  28.  *    Rickard E. (Rik) Faith <faith@valinux.com>
  29.  *    Gareth Hughes <gareth@valinux.com>
  30.  */
  31. #include <linux/config.h>
  32. #include "drmP.h"
  33. #include <linux/wrapper.h>
  34. typedef struct drm_mem_stats {
  35. const char   *name;
  36. int   succeed_count;
  37. int   free_count;
  38. int   fail_count;
  39. unsigned long   bytes_allocated;
  40. unsigned long   bytes_freed;
  41. } drm_mem_stats_t;
  42. static spinlock_t   DRM(mem_lock)      = SPIN_LOCK_UNLOCKED;
  43. static unsigned long   DRM(ram_available) = 0; /* In pages */
  44. static unsigned long   DRM(ram_used)      = 0;
  45. static drm_mem_stats_t   DRM(mem_stats)[]   = {
  46. [DRM_MEM_DMA]     = { "dmabufs"  },
  47. [DRM_MEM_SAREA]     = { "sareas"   },
  48. [DRM_MEM_DRIVER]    = { "driver"   },
  49. [DRM_MEM_MAGIC]     = { "magic"    },
  50. [DRM_MEM_IOCTLS]    = { "ioctltab" },
  51. [DRM_MEM_MAPS]     = { "maplist"  },
  52. [DRM_MEM_VMAS]     = { "vmalist"  },
  53. [DRM_MEM_BUFS]     = { "buflist"  },
  54. [DRM_MEM_SEGS]     = { "seglist"  },
  55. [DRM_MEM_PAGES]     = { "pagelist" },
  56. [DRM_MEM_FILES]     = { "files"    },
  57. [DRM_MEM_QUEUES]    = { "queues"   },
  58. [DRM_MEM_CMDS]     = { "commands" },
  59. [DRM_MEM_MAPPINGS]  = { "mappings" },
  60. [DRM_MEM_BUFLISTS]  = { "buflists" },
  61. [DRM_MEM_AGPLISTS]  = { "agplist"  },
  62. [DRM_MEM_SGLISTS]   = { "sglist"   },
  63. [DRM_MEM_TOTALAGP]  = { "totalagp" },
  64. [DRM_MEM_BOUNDAGP]  = { "boundagp" },
  65. [DRM_MEM_CTXBITMAP] = { "ctxbitmap"},
  66. [DRM_MEM_STUB]      = { "stub"     },
  67. { NULL, 0, } /* Last entry must be null */
  68. };
  69. void DRM(mem_init)(void)
  70. {
  71. drm_mem_stats_t *mem;
  72. struct sysinfo si;
  73. for (mem = DRM(mem_stats); mem->name; ++mem) {
  74. mem->succeed_count   = 0;
  75. mem->free_count      = 0;
  76. mem->fail_count      = 0;
  77. mem->bytes_allocated = 0;
  78. mem->bytes_freed     = 0;
  79. }
  80. si_meminfo(&si);
  81. DRM(ram_available) = si.totalram;
  82. DRM(ram_used)    = 0;
  83. }
  84. /* drm_mem_info is called whenever a process reads /dev/drm/mem. */
  85. static int DRM(_mem_info)(char *buf, char **start, off_t offset,
  86.   int request, int *eof, void *data)
  87. {
  88. drm_mem_stats_t *pt;
  89. int             len = 0;
  90. if (offset > DRM_PROC_LIMIT) {
  91. *eof = 1;
  92. return 0;
  93. }
  94. *eof   = 0;
  95. *start = &buf[offset];
  96. DRM_PROC_PRINT("   total counts "
  97.        " |    outstanding  n");
  98. DRM_PROC_PRINT("type    alloc freed fail bytes    freed"
  99.        " | allocs      bytesnn");
  100. DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |n",
  101.        "system", 0, 0, 0,
  102.        DRM(ram_available) << (PAGE_SHIFT - 10));
  103. DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB         |n",
  104.        "locked", 0, 0, 0, DRM(ram_used) >> 10);
  105. DRM_PROC_PRINT("n");
  106. for (pt = DRM(mem_stats); pt->name; pt++) {
  107. DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ldn",
  108.        pt->name,
  109.        pt->succeed_count,
  110.        pt->free_count,
  111.        pt->fail_count,
  112.        pt->bytes_allocated,
  113.        pt->bytes_freed,
  114.        pt->succeed_count - pt->free_count,
  115.        (long)pt->bytes_allocated
  116.        - (long)pt->bytes_freed);
  117. }
  118. if (len > request + offset) return request;
  119. *eof = 1;
  120. return len - offset;
  121. }
  122. int DRM(mem_info)(char *buf, char **start, off_t offset,
  123.   int len, int *eof, void *data)
  124. {
  125. int ret;
  126. spin_lock(&DRM(mem_lock));
  127. ret = DRM(_mem_info)(buf, start, offset, len, eof, data);
  128. spin_unlock(&DRM(mem_lock));
  129. return ret;
  130. }
  131. void *DRM(alloc)(size_t size, int area)
  132. {
  133. void *pt;
  134. if (!size) {
  135. DRM_MEM_ERROR(area, "Allocating 0 bytesn");
  136. return NULL;
  137. }
  138. if (!(pt = kmalloc(size, GFP_KERNEL))) {
  139. spin_lock(&DRM(mem_lock));
  140. ++DRM(mem_stats)[area].fail_count;
  141. spin_unlock(&DRM(mem_lock));
  142. return NULL;
  143. }
  144. spin_lock(&DRM(mem_lock));
  145. ++DRM(mem_stats)[area].succeed_count;
  146. DRM(mem_stats)[area].bytes_allocated += size;
  147. spin_unlock(&DRM(mem_lock));
  148. return pt;
  149. }
  150. void *DRM(realloc)(void *oldpt, size_t oldsize, size_t size, int area)
  151. {
  152. void *pt;
  153. if (!(pt = DRM(alloc)(size, area))) return NULL;
  154. if (oldpt && oldsize) {
  155. memcpy(pt, oldpt, oldsize);
  156. DRM(free)(oldpt, oldsize, area);
  157. }
  158. return pt;
  159. }
  160. char *DRM(strdup)(const char *s, int area)
  161. {
  162. char *pt;
  163. int  length = s ? strlen(s) : 0;
  164. if (!(pt = DRM(alloc)(length+1, area))) return NULL;
  165. strcpy(pt, s);
  166. return pt;
  167. }
  168. void DRM(strfree)(const char *s, int area)
  169. {
  170. unsigned int size;
  171. if (!s) return;
  172. size = 1 + (s ? strlen(s) : 0);
  173. DRM(free)((void *)s, size, area);
  174. }
  175. void DRM(free)(void *pt, size_t size, int area)
  176. {
  177. int alloc_count;
  178. int free_count;
  179. if (!pt) DRM_MEM_ERROR(area, "Attempt to free NULL pointern");
  180. else  kfree(pt);
  181. spin_lock(&DRM(mem_lock));
  182. DRM(mem_stats)[area].bytes_freed += size;
  183. free_count  = ++DRM(mem_stats)[area].free_count;
  184. alloc_count = DRM(mem_stats)[area].succeed_count;
  185. spin_unlock(&DRM(mem_lock));
  186. if (free_count > alloc_count) {
  187. DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocsn",
  188.       free_count, alloc_count);
  189. }
  190. }
  191. unsigned long DRM(alloc_pages)(int order, int area)
  192. {
  193. unsigned long address;
  194. unsigned long bytes   = PAGE_SIZE << order;
  195. unsigned long addr;
  196. unsigned int  sz;
  197. spin_lock(&DRM(mem_lock));
  198. if ((DRM(ram_used) >> PAGE_SHIFT)
  199.     > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) {
  200. spin_unlock(&DRM(mem_lock));
  201. return 0;
  202. }
  203. spin_unlock(&DRM(mem_lock));
  204. address = __get_free_pages(GFP_KERNEL, order);
  205. if (!address) {
  206. spin_lock(&DRM(mem_lock));
  207. ++DRM(mem_stats)[area].fail_count;
  208. spin_unlock(&DRM(mem_lock));
  209. return 0;
  210. }
  211. spin_lock(&DRM(mem_lock));
  212. ++DRM(mem_stats)[area].succeed_count;
  213. DRM(mem_stats)[area].bytes_allocated += bytes;
  214. DRM(ram_used)              += bytes;
  215. spin_unlock(&DRM(mem_lock));
  216. /* Zero outside the lock */
  217. memset((void *)address, 0, bytes);
  218. /* Reserve */
  219. for (addr = address, sz = bytes;
  220.      sz > 0;
  221.      addr += PAGE_SIZE, sz -= PAGE_SIZE) {
  222. mem_map_reserve(virt_to_page(addr));
  223. }
  224. return address;
  225. }
  226. void DRM(free_pages)(unsigned long address, int order, int area)
  227. {
  228. unsigned long bytes = PAGE_SIZE << order;
  229. int   alloc_count;
  230. int   free_count;
  231. unsigned long addr;
  232. unsigned int  sz;
  233. if (!address) {
  234. DRM_MEM_ERROR(area, "Attempt to free address 0n");
  235. } else {
  236. /* Unreserve */
  237. for (addr = address, sz = bytes;
  238.      sz > 0;
  239.      addr += PAGE_SIZE, sz -= PAGE_SIZE) {
  240. mem_map_unreserve(virt_to_page(addr));
  241. }
  242. free_pages(address, order);
  243. }
  244. spin_lock(&DRM(mem_lock));
  245. free_count  = ++DRM(mem_stats)[area].free_count;
  246. alloc_count = DRM(mem_stats)[area].succeed_count;
  247. DRM(mem_stats)[area].bytes_freed += bytes;
  248. DRM(ram_used)  -= bytes;
  249. spin_unlock(&DRM(mem_lock));
  250. if (free_count > alloc_count) {
  251. DRM_MEM_ERROR(area,
  252.       "Excess frees: %d frees, %d allocsn",
  253.       free_count, alloc_count);
  254. }
  255. }
  256. void *DRM(ioremap)(unsigned long offset, unsigned long size)
  257. {
  258. void *pt;
  259. if (!size) {
  260. DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
  261.       "Mapping 0 bytes at 0x%08lxn", offset);
  262. return NULL;
  263. }
  264. if (!(pt = ioremap(offset, size))) {
  265. spin_lock(&DRM(mem_lock));
  266. ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count;
  267. spin_unlock(&DRM(mem_lock));
  268. return NULL;
  269. }
  270. spin_lock(&DRM(mem_lock));
  271. ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
  272. DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size;
  273. spin_unlock(&DRM(mem_lock));
  274. return pt;
  275. }
  276. void DRM(ioremapfree)(void *pt, unsigned long size)
  277. {
  278. int alloc_count;
  279. int free_count;
  280. if (!pt)
  281. DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
  282.       "Attempt to free NULL pointern");
  283. else
  284. iounmap(pt);
  285. spin_lock(&DRM(mem_lock));
  286. DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size;
  287. free_count  = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count;
  288. alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count;
  289. spin_unlock(&DRM(mem_lock));
  290. if (free_count > alloc_count) {
  291. DRM_MEM_ERROR(DRM_MEM_MAPPINGS,
  292.       "Excess frees: %d frees, %d allocsn",
  293.       free_count, alloc_count);
  294. }
  295. }
  296. #if __REALLY_HAVE_AGP
  297. agp_memory *DRM(alloc_agp)(int pages, u32 type)
  298. {
  299. agp_memory *handle;
  300. if (!pages) {
  301. DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pagesn");
  302. return NULL;
  303. }
  304. if ((handle = DRM(agp_allocate_memory)(pages, type))) {
  305. spin_lock(&DRM(mem_lock));
  306. ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
  307. DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated
  308. += pages << PAGE_SHIFT;
  309. spin_unlock(&DRM(mem_lock));
  310. return handle;
  311. }
  312. spin_lock(&DRM(mem_lock));
  313. ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count;
  314. spin_unlock(&DRM(mem_lock));
  315. return NULL;
  316. }
  317. int DRM(free_agp)(agp_memory *handle, int pages)
  318. {
  319. int           alloc_count;
  320. int           free_count;
  321. int           retval = -EINVAL;
  322. if (!handle) {
  323. DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
  324.       "Attempt to free NULL AGP handlen");
  325. return retval;;
  326. }
  327. if (DRM(agp_free_memory)(handle)) {
  328. spin_lock(&DRM(mem_lock));
  329. free_count  = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count;
  330. alloc_count =   DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count;
  331. DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed
  332. += pages << PAGE_SHIFT;
  333. spin_unlock(&DRM(mem_lock));
  334. if (free_count > alloc_count) {
  335. DRM_MEM_ERROR(DRM_MEM_TOTALAGP,
  336.       "Excess frees: %d frees, %d allocsn",
  337.       free_count, alloc_count);
  338. }
  339. return 0;
  340. }
  341. return retval;
  342. }
  343. int DRM(bind_agp)(agp_memory *handle, unsigned int start)
  344. {
  345. int retcode = -EINVAL;
  346. if (!handle) {
  347. DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
  348.       "Attempt to bind NULL AGP handlen");
  349. return retcode;
  350. }
  351. if (!(retcode = DRM(agp_bind_memory)(handle, start))) {
  352. spin_lock(&DRM(mem_lock));
  353. ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
  354. DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated
  355. += handle->page_count << PAGE_SHIFT;
  356. spin_unlock(&DRM(mem_lock));
  357. return retcode;
  358. }
  359. spin_lock(&DRM(mem_lock));
  360. ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count;
  361. spin_unlock(&DRM(mem_lock));
  362. return retcode;
  363. }
  364. int DRM(unbind_agp)(agp_memory *handle)
  365. {
  366. int alloc_count;
  367. int free_count;
  368. int retcode = -EINVAL;
  369. if (!handle) {
  370. DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
  371.       "Attempt to unbind NULL AGP handlen");
  372. return retcode;
  373. }
  374. if ((retcode = DRM(agp_unbind_memory)(handle))) return retcode;
  375. spin_lock(&DRM(mem_lock));
  376. free_count  = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count;
  377. alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count;
  378. DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed
  379. += handle->page_count << PAGE_SHIFT;
  380. spin_unlock(&DRM(mem_lock));
  381. if (free_count > alloc_count) {
  382. DRM_MEM_ERROR(DRM_MEM_BOUNDAGP,
  383.       "Excess frees: %d frees, %d allocsn",
  384.       free_count, alloc_count);
  385. }
  386. return retcode;
  387. }
  388. #endif