1 /* drm_memory.h -- Memory management wrappers for DRM -*- linux-c -*-
2 * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com
4 * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
5 * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
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:
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
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.
28 * Rickard E. (Rik) Faith <faith@valinux.com>
29 * Gareth Hughes <gareth@valinux.com>
31 * $FreeBSD: src/sys/dev/drm/drm_memory.h,v 1.8.2.1 2003/04/26 07:05:28 anholt Exp $
32 * $DragonFly: src/sys/dev/drm/drm_memory.h,v 1.5 2006/09/05 03:48:10 dillon Exp $
35 #include "dev/drm/drmP.h"
37 #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
38 #define malloctype DRM(M_DRM)
39 /* The macros conflicted in the MALLOC_DEFINE */
41 MALLOC_DEFINE(malloctype
, "drm", "DRM Data Structures");
46 typedef struct drm_mem_stats
{
51 unsigned long bytes_allocated
;
52 unsigned long bytes_freed
;
55 static DRM_SPINTYPE
DRM(mem_lock
);
56 static unsigned long DRM(ram_available
) = 0; /* In pages */
57 static unsigned long DRM(ram_used
) = 0;
58 static drm_mem_stats_t
DRM(mem_stats
)[] = {
59 [DRM_MEM_DMA
] = { "dmabufs" },
60 [DRM_MEM_SAREA
] = { "sareas" },
61 [DRM_MEM_DRIVER
] = { "driver" },
62 [DRM_MEM_MAGIC
] = { "magic" },
63 [DRM_MEM_IOCTLS
] = { "ioctltab" },
64 [DRM_MEM_MAPS
] = { "maplist" },
65 [DRM_MEM_BUFS
] = { "buflist" },
66 [DRM_MEM_SEGS
] = { "seglist" },
67 [DRM_MEM_PAGES
] = { "pagelist" },
68 [DRM_MEM_FILES
] = { "files" },
69 [DRM_MEM_QUEUES
] = { "queues" },
70 [DRM_MEM_CMDS
] = { "commands" },
71 [DRM_MEM_MAPPINGS
] = { "mappings" },
72 [DRM_MEM_BUFLISTS
] = { "buflists" },
73 [DRM_MEM_AGPLISTS
] = { "agplist" },
74 [DRM_MEM_SGLISTS
] = { "sglist" },
75 [DRM_MEM_TOTALAGP
] = { "totalagp" },
76 [DRM_MEM_BOUNDAGP
] = { "boundagp" },
77 [DRM_MEM_CTXBITMAP
] = { "ctxbitmap"},
78 [DRM_MEM_STUB
] = { "stub" },
79 { NULL
, 0, } /* Last entry must be null */
82 void DRM(mem_init
)(void)
87 malloc_type_attach(DRM(M_DRM
));
90 DRM_SPININIT(DRM(mem_lock
), "drm memory");
92 for (mem
= DRM(mem_stats
); mem
->name
; ++mem
) {
93 mem
->succeed_count
= 0;
96 mem
->bytes_allocated
= 0;
100 DRM(ram_available
) = 0; /* si.totalram */
104 void DRM(mem_uninit
)(void)
106 DRM_SPINUNINIT(DRM(mem_lock
));
109 #if defined(__DragonFly__) || defined(__FreeBSD__)
110 /* drm_mem_info is called whenever a process reads /dev/drm/mem. */
112 DRM(_mem_info
)(drm_mem_stats_t
*stats
, struct sysctl_oid
*oidp
, void *arg1
,
113 int arg2
, struct sysctl_req
*req
)
119 DRM_SYSCTL_PRINT(" total counts "
120 " | outstanding \n");
121 DRM_SYSCTL_PRINT("type alloc freed fail bytes freed"
122 " | allocs bytes\n\n");
123 DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
124 "system", 0, 0, 0, DRM(ram_available
));
125 DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu |\n",
126 "locked", 0, 0, 0, DRM(ram_used
));
127 DRM_SYSCTL_PRINT("\n");
128 for (pt
= stats
; pt
->name
; pt
++) {
129 DRM_SYSCTL_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n",
136 pt
->succeed_count
- pt
->free_count
,
137 (long)pt
->bytes_allocated
138 - (long)pt
->bytes_freed
);
140 SYSCTL_OUT(req
, "", 1);
145 int DRM(mem_info
) DRM_SYSCTL_HANDLER_ARGS
148 drm_mem_stats_t
*stats
;
150 stats
= kmalloc(sizeof(DRM(mem_stats
)), DRM(M_DRM
), M_WAITOK
);
152 DRM_SPINLOCK(&DRM(mem_lock
));
153 bcopy(DRM(mem_stats
), stats
, sizeof(DRM(mem_stats
)));
154 DRM_SPINUNLOCK(&DRM(mem_lock
));
156 ret
= DRM(_mem_info
)(stats
, oidp
, arg1
, arg2
, req
);
158 kfree(stats
, DRM(M_DRM
));
161 #endif /* __FreeBSD__ */
163 void *DRM(alloc
)(size_t size
, int area
)
168 DRM_MEM_ERROR(area
, "Allocating 0 bytes\n");
172 if (!(pt
= kmalloc(size
, DRM(M_DRM
), M_NOWAIT
))) {
173 DRM_SPINLOCK(&DRM(mem_lock
));
174 ++DRM(mem_stats
)[area
].fail_count
;
175 DRM_SPINUNLOCK(&DRM(mem_lock
));
178 DRM_SPINLOCK(&DRM(mem_lock
));
179 ++DRM(mem_stats
)[area
].succeed_count
;
180 DRM(mem_stats
)[area
].bytes_allocated
+= size
;
181 DRM_SPINUNLOCK(&DRM(mem_lock
));
185 void *DRM(realloc
)(void *oldpt
, size_t oldsize
, size_t size
, int area
)
189 if (!(pt
= DRM(alloc
)(size
, area
))) return NULL
;
190 if (oldpt
&& oldsize
) {
191 memcpy(pt
, oldpt
, oldsize
);
192 DRM(free
)(oldpt
, oldsize
, area
);
197 char *DRM(strdup
)(const char *s
, int area
)
200 int length
= s
? strlen(s
) : 0;
202 if (!(pt
= DRM(alloc
)(length
+1, area
))) return NULL
;
207 void DRM(strfree
)(char *s
, int area
)
213 size
= 1 + strlen(s
);
214 DRM(free
)((void *)s
, size
, area
);
217 void DRM(free
)(void *pt
, size_t size
, int area
)
223 DRM_MEM_ERROR(area
, "Attempt to free NULL pointer\n");
225 kfree(pt
, DRM(M_DRM
));
226 DRM_SPINLOCK(&DRM(mem_lock
));
227 DRM(mem_stats
)[area
].bytes_freed
+= size
;
228 free_count
= ++DRM(mem_stats
)[area
].free_count
;
229 alloc_count
= DRM(mem_stats
)[area
].succeed_count
;
230 DRM_SPINUNLOCK(&DRM(mem_lock
));
231 if (free_count
> alloc_count
) {
232 DRM_MEM_ERROR(area
, "Excess frees: %d frees, %d allocs\n",
233 free_count
, alloc_count
);
237 void *DRM(ioremap
)( drm_device_t
*dev
, drm_local_map_t
*map
)
242 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
243 "Mapping 0 bytes at 0x%08lx\n", map
->offset
);
247 map
->iot
= dev
->pa
.pa_memt
;
250 #if defined(__DragonFly__) || defined(__FreeBSD__)
251 if (!(pt
= pmap_mapdev(map
->offset
, map
->size
))) {
252 #elif defined(__NetBSD__)
253 if (bus_space_map(map
->iot
, map
->offset
, map
->size
,
254 BUS_SPACE_MAP_LINEAR
, &map
->ioh
)) {
256 DRM_SPINLOCK(&DRM(mem_lock
));
257 ++DRM(mem_stats
)[DRM_MEM_MAPPINGS
].fail_count
;
258 DRM_SPINUNLOCK(&DRM(mem_lock
));
262 pt
= bus_space_vaddr(map
->iot
, map
->ioh
);
264 DRM_SPINLOCK(&DRM(mem_lock
));
265 ++DRM(mem_stats
)[DRM_MEM_MAPPINGS
].succeed_count
;
266 DRM(mem_stats
)[DRM_MEM_MAPPINGS
].bytes_allocated
+= map
->size
;
267 DRM_SPINUNLOCK(&DRM(mem_lock
));
273 void *DRM(ioremap_nocache
)(unsigned long offset
, unsigned long size
)
278 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
279 "Mapping 0 bytes at 0x%08lx\n", offset
);
284 if (!(pt
= ioremap_nocache(offset
, size
))) {
285 DRM_SPINLOCK(&DRM(mem_lock
));
286 ++DRM(mem_stats
)[DRM_MEM_MAPPINGS
].fail_count
;
287 DRM_SPINUNLOCK(&DRM(mem_lock
));
290 DRM_SPINLOCK(&DRM(mem_lock
));
291 ++DRM(mem_stats
)[DRM_MEM_MAPPINGS
].succeed_count
;
292 DRM(mem_stats
)[DRM_MEM_MAPPINGS
].bytes_allocated
+= size
;
293 DRM_SPINUNLOCK(&DRM(mem_lock
));
298 void DRM(ioremapfree
)(drm_local_map_t
*map
)
303 if (map
->handle
== NULL
)
304 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
305 "Attempt to free NULL pointer\n");
307 #if defined(__DragonFly__) || defined(__FreeBSD__)
308 pmap_unmapdev((vm_offset_t
) map
->handle
, map
->size
);
309 #elif defined(__NetBSD__)
310 bus_space_unmap(map
->iot
, map
->ioh
, map
->size
);
313 DRM_SPINLOCK(&DRM(mem_lock
));
314 DRM(mem_stats
)[DRM_MEM_MAPPINGS
].bytes_freed
+= map
->size
;
315 free_count
= ++DRM(mem_stats
)[DRM_MEM_MAPPINGS
].free_count
;
316 alloc_count
= DRM(mem_stats
)[DRM_MEM_MAPPINGS
].succeed_count
;
317 DRM_SPINUNLOCK(&DRM(mem_lock
));
318 if (free_count
> alloc_count
) {
319 DRM_MEM_ERROR(DRM_MEM_MAPPINGS
,
320 "Excess frees: %d frees, %d allocs\n",
321 free_count
, alloc_count
);
325 #if __REALLY_HAVE_AGP
326 agp_memory
*DRM(alloc_agp
)(int pages
, u32 type
)
331 DRM_MEM_ERROR(DRM_MEM_TOTALAGP
, "Allocating 0 pages\n");
335 if ((handle
= DRM(agp_allocate_memory
)(pages
, type
))) {
336 DRM_SPINLOCK(&DRM(mem_lock
));
337 ++DRM(mem_stats
)[DRM_MEM_TOTALAGP
].succeed_count
;
338 DRM(mem_stats
)[DRM_MEM_TOTALAGP
].bytes_allocated
339 += pages
<< PAGE_SHIFT
;
340 DRM_SPINUNLOCK(&DRM(mem_lock
));
343 DRM_SPINLOCK(&DRM(mem_lock
));
344 ++DRM(mem_stats
)[DRM_MEM_TOTALAGP
].fail_count
;
345 DRM_SPINUNLOCK(&DRM(mem_lock
));
349 int DRM(free_agp
)(agp_memory
*handle
, int pages
)
355 DRM_MEM_ERROR(DRM_MEM_TOTALAGP
,
356 "Attempt to free NULL AGP handle\n");
357 return DRM_ERR(EINVAL
);
360 if (DRM(agp_free_memory
)(handle
)) {
361 DRM_SPINLOCK(&DRM(mem_lock
));
362 free_count
= ++DRM(mem_stats
)[DRM_MEM_TOTALAGP
].free_count
;
363 alloc_count
= DRM(mem_stats
)[DRM_MEM_TOTALAGP
].succeed_count
;
364 DRM(mem_stats
)[DRM_MEM_TOTALAGP
].bytes_freed
365 += pages
<< PAGE_SHIFT
;
366 DRM_SPINUNLOCK(&DRM(mem_lock
));
367 if (free_count
> alloc_count
) {
368 DRM_MEM_ERROR(DRM_MEM_TOTALAGP
,
369 "Excess frees: %d frees, %d allocs\n",
370 free_count
, alloc_count
);
374 return DRM_ERR(EINVAL
);
377 int DRM(bind_agp
)(agp_memory
*handle
, unsigned int start
)
380 device_t dev
= DRM_AGP_FIND_DEVICE();
381 struct agp_memory_info info
;
387 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP
,
388 "Attempt to bind NULL AGP handle\n");
389 return DRM_ERR(EINVAL
);
392 if (!(retcode
= DRM(agp_bind_memory
)(handle
, start
))) {
393 DRM_SPINLOCK(&DRM(mem_lock
));
394 ++DRM(mem_stats
)[DRM_MEM_BOUNDAGP
].succeed_count
;
395 agp_memory_info(dev
, handle
, &info
);
396 DRM(mem_stats
)[DRM_MEM_BOUNDAGP
].bytes_allocated
398 DRM_SPINUNLOCK(&DRM(mem_lock
));
401 DRM_SPINLOCK(&DRM(mem_lock
));
402 ++DRM(mem_stats
)[DRM_MEM_BOUNDAGP
].fail_count
;
403 DRM_SPINUNLOCK(&DRM(mem_lock
));
404 return DRM_ERR(retcode
);
407 int DRM(unbind_agp
)(agp_memory
*handle
)
411 int retcode
= EINVAL
;
412 device_t dev
= DRM_AGP_FIND_DEVICE();
413 struct agp_memory_info info
;
419 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP
,
420 "Attempt to unbind NULL AGP handle\n");
421 return DRM_ERR(retcode
);
424 agp_memory_info(dev
, handle
, &info
);
426 if ((retcode
= DRM(agp_unbind_memory
)(handle
)))
427 return DRM_ERR(retcode
);
429 DRM_SPINLOCK(&DRM(mem_lock
));
430 free_count
= ++DRM(mem_stats
)[DRM_MEM_BOUNDAGP
].free_count
;
431 alloc_count
= DRM(mem_stats
)[DRM_MEM_BOUNDAGP
].succeed_count
;
432 DRM(mem_stats
)[DRM_MEM_BOUNDAGP
].bytes_freed
434 DRM_SPINUNLOCK(&DRM(mem_lock
));
435 if (free_count
> alloc_count
) {
436 DRM_MEM_ERROR(DRM_MEM_BOUNDAGP
,
437 "Excess frees: %d frees, %d allocs\n",
438 free_count
, alloc_count
);
440 return DRM_ERR(retcode
);