2 * \file drm_memory_debug.h
3 * Memory management wrappers for DRM.
5 * \author Rickard E. (Rik) Faith <faith@valinux.com>
6 * \author Gareth Hughes <gareth@valinux.com>
10 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
11 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
12 * All Rights Reserved.
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 * OTHER DEALINGS IN THE SOFTWARE.
36 typedef struct drm_mem_stats
{
41 unsigned long bytes_allocated
;
42 unsigned long bytes_freed
;
45 static DEFINE_SPINLOCK(drm_mem_lock
);
46 static unsigned long drm_ram_available
= 0; /* In pages */
47 static unsigned long drm_ram_used
= 0;
48 static drm_mem_stats_t drm_mem_stats
[] =
50 [DRM_MEM_DMA
] = {"dmabufs"},
51 [DRM_MEM_SAREA
] = {"sareas"},
52 [DRM_MEM_DRIVER
] = {"driver"},
53 [DRM_MEM_MAGIC
] = {"magic"},
54 [DRM_MEM_IOCTLS
] = {"ioctltab"},
55 [DRM_MEM_MAPS
] = {"maplist"},
56 [DRM_MEM_VMAS
] = {"vmalist"},
57 [DRM_MEM_BUFS
] = {"buflist"},
58 [DRM_MEM_SEGS
] = {"seglist"},
59 [DRM_MEM_PAGES
] = {"pagelist"},
60 [DRM_MEM_FILES
] = {"files"},
61 [DRM_MEM_QUEUES
] = {"queues"},
62 [DRM_MEM_CMDS
] = {"commands"},
63 [DRM_MEM_MAPPINGS
] = {"mappings"},
64 [DRM_MEM_BUFLISTS
] = {"buflists"},
65 [DRM_MEM_AGPLISTS
] = {"agplist"},
66 [DRM_MEM_SGLISTS
] = {"sglist"},
67 [DRM_MEM_TOTALAGP
] = {"totalagp"},
68 [DRM_MEM_BOUNDAGP
] = {"boundagp"},
69 [DRM_MEM_CTXBITMAP
] = {"ctxbitmap"},
70 [DRM_MEM_CTXLIST
] = {"ctxlist"},
71 [DRM_MEM_STUB
] = {"stub"},
72 {NULL
, 0,} /* Last entry must be null */
75 void drm_mem_init (void) {
79 for (mem
= drm_mem_stats
; mem
->name
; ++mem
) {
80 mem
->succeed_count
= 0;
83 mem
->bytes_allocated
= 0;
88 drm_ram_available
= si
.totalram
;
92 /* drm_mem_info is called whenever a process reads /dev/drm/mem. */
94 static int drm__mem_info (char *buf
, char **start
, off_t offset
,
95 int request
, int *eof
, void *data
) {
99 if (offset
> DRM_PROC_LIMIT
) {
105 *start
= &buf
[offset
];
107 DRM_PROC_PRINT(" total counts "
108 " | outstanding \n");
109 DRM_PROC_PRINT("type alloc freed fail bytes freed"
110 " | allocs bytes\n\n");
111 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
113 drm_ram_available
<< (PAGE_SHIFT
- 10));
114 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n",
115 "locked", 0, 0, 0, drm_ram_used
>> 10);
116 DRM_PROC_PRINT("\n");
117 for (pt
= drm_mem_stats
; pt
->name
; pt
++) {
118 DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
125 pt
->succeed_count
- pt
->free_count
,
126 (long)pt
->bytes_allocated
127 - (long)pt
->bytes_freed
);
130 if (len
> request
+ offset
)
136 int drm_mem_info (char *buf
, char **start
, off_t offset
,
137 int len
, int *eof
, void *data
) {
140 spin_lock(&drm_mem_lock
);
141 ret
= drm__mem_info (buf
, start
, offset
, len
, eof
, data
);
142 spin_unlock(&drm_mem_lock
);
146 void *drm_alloc (size_t size
, int area
) {
150 DRM_MEM_ERROR(area
, "Allocating 0 bytes\n");
154 if (!(pt
= kmalloc(size
, GFP_KERNEL
))) {
155 spin_lock(&drm_mem_lock
);
156 ++drm_mem_stats
[area
].fail_count
;
157 spin_unlock(&drm_mem_lock
);
160 spin_lock(&drm_mem_lock
);
161 ++drm_mem_stats
[area
].succeed_count
;
162 drm_mem_stats
[area
].bytes_allocated
+= size
;
163 spin_unlock(&drm_mem_lock
);
167 void *drm_calloc (size_t nmemb
, size_t size
, int area
) {
170 addr
= drm_alloc (nmemb
* size
, area
);
172 memset((void *)addr
, 0, size
* nmemb
);
177 void *drm_realloc (void *oldpt
, size_t oldsize
, size_t size
, int area
) {
180 if (!(pt
= drm_alloc (size
, area
)))
182 if (oldpt
&& oldsize
) {
183 memcpy(pt
, oldpt
, oldsize
);
184 drm_free (oldpt
, oldsize
, area
);
189 void drm_free (void *pt
, size_t size
, int area
) {
194 DRM_MEM_ERROR(area
, "Attempt to free NULL pointer\n");
197 spin_lock(&drm_mem_lock
);
198 drm_mem_stats
[area
].bytes_freed
+= size
;
199 free_count
= ++drm_mem_stats
[area
].free_count
;
200 alloc_count
= drm_mem_stats
[area
].succeed_count
;
201 spin_unlock(&drm_mem_lock
);
202 if (free_count
> alloc_count
) {
203 DRM_MEM_ERROR(area
, "Excess frees: %d frees, %d allocs\n",
204 free_count
, alloc_count
);
208 void *drm_ioremap (unsigned long offset
, unsigned long size
,
209 drm_device_t
* dev
) {
213 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
214 "Mapping 0 bytes at 0x%08lx\n", offset
);
218 if (!(pt
= drm_ioremap(offset
, size
, dev
))) {
219 spin_lock(&drm_mem_lock
);
220 ++drm_mem_stats
[DRM_MEM_MAPPINGS
].fail_count
;
221 spin_unlock(&drm_mem_lock
);
224 spin_lock(&drm_mem_lock
);
225 ++drm_mem_stats
[DRM_MEM_MAPPINGS
].succeed_count
;
226 drm_mem_stats
[DRM_MEM_MAPPINGS
].bytes_allocated
+= size
;
227 spin_unlock(&drm_mem_lock
);
232 void *drm_ioremap_nocache (unsigned long offset
, unsigned long size
,
233 drm_device_t
* dev
) {
237 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
238 "Mapping 0 bytes at 0x%08lx\n", offset
);
242 if (!(pt
= drm_ioremap_nocache(offset
, size
, dev
))) {
243 spin_lock(&drm_mem_lock
);
244 ++drm_mem_stats
[DRM_MEM_MAPPINGS
].fail_count
;
245 spin_unlock(&drm_mem_lock
);
248 spin_lock(&drm_mem_lock
);
249 ++drm_mem_stats
[DRM_MEM_MAPPINGS
].succeed_count
;
250 drm_mem_stats
[DRM_MEM_MAPPINGS
].bytes_allocated
+= size
;
251 spin_unlock(&drm_mem_lock
);
256 void drm_ioremapfree (void *pt
, unsigned long size
, drm_device_t
* dev
) {
261 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
262 "Attempt to free NULL pointer\n");
264 drm_ioremapfree(pt
, size
, dev
);
266 spin_lock(&drm_mem_lock
);
267 drm_mem_stats
[DRM_MEM_MAPPINGS
].bytes_freed
+= size
;
268 free_count
= ++drm_mem_stats
[DRM_MEM_MAPPINGS
].free_count
;
269 alloc_count
= drm_mem_stats
[DRM_MEM_MAPPINGS
].succeed_count
;
270 spin_unlock(&drm_mem_lock
);
271 if (free_count
> alloc_count
) {
272 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
273 "Excess frees: %d frees, %d allocs\n",
274 free_count
, alloc_count
);
280 DRM_AGP_MEM
*drm_alloc_agp (drm_device_t
*dev
, int pages
, u32 type
) {
284 DRM_MEM_ERROR(DRM_MEM_TOTALAGP
, "Allocating 0 pages\n");
288 if ((handle
= drm_agp_allocate_memory (pages
, type
))) {
289 spin_lock(&drm_mem_lock
);
290 ++drm_mem_stats
[DRM_MEM_TOTALAGP
].succeed_count
;
291 drm_mem_stats
[DRM_MEM_TOTALAGP
].bytes_allocated
292 += pages
<< PAGE_SHIFT
;
293 spin_unlock(&drm_mem_lock
);
296 spin_lock(&drm_mem_lock
);
297 ++drm_mem_stats
[DRM_MEM_TOTALAGP
].fail_count
;
298 spin_unlock(&drm_mem_lock
);
302 int drm_free_agp (DRM_AGP_MEM
* handle
, int pages
) {
305 int retval
= -EINVAL
;
308 DRM_MEM_ERROR(DRM_MEM_TOTALAGP
,
309 "Attempt to free NULL AGP handle\n");
313 if (drm_agp_free_memory (handle
)) {
314 spin_lock(&drm_mem_lock
);
315 free_count
= ++drm_mem_stats
[DRM_MEM_TOTALAGP
].free_count
;
316 alloc_count
= drm_mem_stats
[DRM_MEM_TOTALAGP
].succeed_count
;
317 drm_mem_stats
[DRM_MEM_TOTALAGP
].bytes_freed
318 += pages
<< PAGE_SHIFT
;
319 spin_unlock(&drm_mem_lock
);
320 if (free_count
> alloc_count
) {
321 DRM_MEM_ERROR(DRM_MEM_TOTALAGP
,
322 "Excess frees: %d frees, %d allocs\n",
323 free_count
, alloc_count
);
330 int drm_bind_agp (DRM_AGP_MEM
* handle
, unsigned int start
) {
331 int retcode
= -EINVAL
;
334 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP
,
335 "Attempt to bind NULL AGP handle\n");
339 if (!(retcode
= drm_agp_bind_memory (handle
, start
))) {
340 spin_lock(&drm_mem_lock
);
341 ++drm_mem_stats
[DRM_MEM_BOUNDAGP
].succeed_count
;
342 drm_mem_stats
[DRM_MEM_BOUNDAGP
].bytes_allocated
343 += handle
->page_count
<< PAGE_SHIFT
;
344 spin_unlock(&drm_mem_lock
);
347 spin_lock(&drm_mem_lock
);
348 ++drm_mem_stats
[DRM_MEM_BOUNDAGP
].fail_count
;
349 spin_unlock(&drm_mem_lock
);
353 int drm_unbind_agp (DRM_AGP_MEM
* handle
) {
356 int retcode
= -EINVAL
;
359 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP
,
360 "Attempt to unbind NULL AGP handle\n");
364 if ((retcode
= drm_agp_unbind_memory (handle
)))
366 spin_lock(&drm_mem_lock
);
367 free_count
= ++drm_mem_stats
[DRM_MEM_BOUNDAGP
].free_count
;
368 alloc_count
= drm_mem_stats
[DRM_MEM_BOUNDAGP
].succeed_count
;
369 drm_mem_stats
[DRM_MEM_BOUNDAGP
].bytes_freed
370 += handle
->page_count
<< PAGE_SHIFT
;
371 spin_unlock(&drm_mem_lock
);
372 if (free_count
> alloc_count
) {
373 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP
,
374 "Excess frees: %d frees, %d allocs\n",
375 free_count
, alloc_count
);