Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /** |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 2 | * \file drm_memory.h |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 3 | * Memory management wrappers for DRM. |
| 4 | * |
| 5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
| 6 | * \author Gareth Hughes <gareth@valinux.com> |
| 7 | */ |
| 8 | |
| 9 | /* |
| 10 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
| 11 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
| 12 | * All Rights Reserved. |
| 13 | * |
| 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: |
| 20 | * |
| 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 |
| 23 | * Software. |
| 24 | * |
| 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. |
| 32 | */ |
| 33 | |
| 34 | #include <linux/config.h> |
| 35 | #include "drmP.h" |
| 36 | |
| 37 | typedef struct drm_mem_stats { |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 38 | const char *name; |
| 39 | int succeed_count; |
| 40 | int free_count; |
| 41 | int fail_count; |
| 42 | unsigned long bytes_allocated; |
| 43 | unsigned long bytes_freed; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 44 | } drm_mem_stats_t; |
| 45 | |
| 46 | static DEFINE_SPINLOCK(DRM(mem_lock)); |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 47 | static unsigned long DRM(ram_available) = 0; /* In pages */ |
| 48 | static unsigned long DRM(ram_used) = 0; |
| 49 | static drm_mem_stats_t DRM(mem_stats)[] = |
| 50 | { |
| 51 | [DRM_MEM_DMA] = { |
| 52 | "dmabufs"},[DRM_MEM_SAREA] = { |
| 53 | "sareas"},[DRM_MEM_DRIVER] = { |
| 54 | "driver"},[DRM_MEM_MAGIC] = { |
| 55 | "magic"},[DRM_MEM_IOCTLS] = { |
| 56 | "ioctltab"},[DRM_MEM_MAPS] = { |
| 57 | "maplist"},[DRM_MEM_VMAS] = { |
| 58 | "vmalist"},[DRM_MEM_BUFS] = { |
| 59 | "buflist"},[DRM_MEM_SEGS] = { |
| 60 | "seglist"},[DRM_MEM_PAGES] = { |
| 61 | "pagelist"},[DRM_MEM_FILES] = { |
| 62 | "files"},[DRM_MEM_QUEUES] = { |
| 63 | "queues"},[DRM_MEM_CMDS] = { |
| 64 | "commands"},[DRM_MEM_MAPPINGS] = { |
| 65 | "mappings"},[DRM_MEM_BUFLISTS] = { |
| 66 | "buflists"},[DRM_MEM_AGPLISTS] = { |
| 67 | "agplist"},[DRM_MEM_SGLISTS] = { |
| 68 | "sglist"},[DRM_MEM_TOTALAGP] = { |
| 69 | "totalagp"},[DRM_MEM_BOUNDAGP] = { |
| 70 | "boundagp"},[DRM_MEM_CTXBITMAP] = { |
| 71 | "ctxbitmap"},[DRM_MEM_CTXLIST] = { |
| 72 | "ctxlist"},[DRM_MEM_STUB] = { |
| 73 | "stub"}, { |
| 74 | NULL, 0,} /* Last entry must be null */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 75 | }; |
| 76 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 77 | void DRM(mem_init) (void) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 78 | drm_mem_stats_t *mem; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 79 | struct sysinfo si; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 80 | |
| 81 | for (mem = DRM(mem_stats); mem->name; ++mem) { |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 82 | mem->succeed_count = 0; |
| 83 | mem->free_count = 0; |
| 84 | mem->fail_count = 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 85 | mem->bytes_allocated = 0; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 86 | mem->bytes_freed = 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | si_meminfo(&si); |
| 90 | DRM(ram_available) = si.totalram; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 91 | DRM(ram_used) = 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 92 | } |
| 93 | |
| 94 | /* drm_mem_info is called whenever a process reads /dev/drm/mem. */ |
| 95 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 96 | static int DRM(_mem_info) (char *buf, char **start, off_t offset, |
| 97 | int request, int *eof, void *data) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 | drm_mem_stats_t *pt; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 99 | int len = 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 100 | |
| 101 | if (offset > DRM_PROC_LIMIT) { |
| 102 | *eof = 1; |
| 103 | return 0; |
| 104 | } |
| 105 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 106 | *eof = 0; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 107 | *start = &buf[offset]; |
| 108 | |
| 109 | DRM_PROC_PRINT(" total counts " |
| 110 | " | outstanding \n"); |
| 111 | DRM_PROC_PRINT("type alloc freed fail bytes freed" |
| 112 | " | allocs bytes\n\n"); |
| 113 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n", |
| 114 | "system", 0, 0, 0, |
| 115 | DRM(ram_available) << (PAGE_SHIFT - 10)); |
| 116 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n", |
| 117 | "locked", 0, 0, 0, DRM(ram_used) >> 10); |
| 118 | DRM_PROC_PRINT("\n"); |
| 119 | for (pt = DRM(mem_stats); pt->name; pt++) { |
| 120 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n", |
| 121 | pt->name, |
| 122 | pt->succeed_count, |
| 123 | pt->free_count, |
| 124 | pt->fail_count, |
| 125 | pt->bytes_allocated, |
| 126 | pt->bytes_freed, |
| 127 | pt->succeed_count - pt->free_count, |
| 128 | (long)pt->bytes_allocated |
| 129 | - (long)pt->bytes_freed); |
| 130 | } |
| 131 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 132 | if (len > request + offset) |
| 133 | return request; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 134 | *eof = 1; |
| 135 | return len - offset; |
| 136 | } |
| 137 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 138 | int DRM(mem_info) (char *buf, char **start, off_t offset, |
| 139 | int len, int *eof, void *data) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 140 | int ret; |
| 141 | |
| 142 | spin_lock(&DRM(mem_lock)); |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 143 | ret = DRM(_mem_info) (buf, start, offset, len, eof, data); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 144 | spin_unlock(&DRM(mem_lock)); |
| 145 | return ret; |
| 146 | } |
| 147 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 148 | void *DRM(alloc) (size_t size, int area) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 149 | void *pt; |
| 150 | |
| 151 | if (!size) { |
| 152 | DRM_MEM_ERROR(area, "Allocating 0 bytes\n"); |
| 153 | return NULL; |
| 154 | } |
| 155 | |
| 156 | if (!(pt = kmalloc(size, GFP_KERNEL))) { |
| 157 | spin_lock(&DRM(mem_lock)); |
| 158 | ++DRM(mem_stats)[area].fail_count; |
| 159 | spin_unlock(&DRM(mem_lock)); |
| 160 | return NULL; |
| 161 | } |
| 162 | spin_lock(&DRM(mem_lock)); |
| 163 | ++DRM(mem_stats)[area].succeed_count; |
| 164 | DRM(mem_stats)[area].bytes_allocated += size; |
| 165 | spin_unlock(&DRM(mem_lock)); |
| 166 | return pt; |
| 167 | } |
| 168 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 169 | void *DRM(calloc) (size_t nmemb, size_t size, int area) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 170 | void *addr; |
| 171 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 172 | addr = DRM(alloc) (nmemb * size, area); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 173 | if (addr != NULL) |
| 174 | memset((void *)addr, 0, size * nmemb); |
| 175 | |
| 176 | return addr; |
| 177 | } |
| 178 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 179 | void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 180 | void *pt; |
| 181 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 182 | if (!(pt = DRM(alloc) (size, area))) |
| 183 | return NULL; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 184 | if (oldpt && oldsize) { |
| 185 | memcpy(pt, oldpt, oldsize); |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 186 | DRM(free) (oldpt, oldsize, area); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 187 | } |
| 188 | return pt; |
| 189 | } |
| 190 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 191 | void DRM(free) (void *pt, size_t size, int area) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 192 | int alloc_count; |
| 193 | int free_count; |
| 194 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 195 | if (!pt) |
| 196 | DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n"); |
| 197 | else |
| 198 | kfree(pt); |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 199 | spin_lock(&DRM(mem_lock)); |
| 200 | DRM(mem_stats)[area].bytes_freed += size; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 201 | free_count = ++DRM(mem_stats)[area].free_count; |
| 202 | alloc_count = DRM(mem_stats)[area].succeed_count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 203 | spin_unlock(&DRM(mem_lock)); |
| 204 | if (free_count > alloc_count) { |
| 205 | DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n", |
| 206 | free_count, alloc_count); |
| 207 | } |
| 208 | } |
| 209 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 210 | unsigned long DRM(alloc_pages) (int order, int area) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 211 | unsigned long address; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 212 | unsigned long bytes = PAGE_SIZE << order; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 213 | unsigned long addr; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 214 | unsigned int sz; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 215 | |
| 216 | spin_lock(&DRM(mem_lock)); |
| 217 | if ((DRM(ram_used) >> PAGE_SHIFT) |
| 218 | > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) { |
| 219 | spin_unlock(&DRM(mem_lock)); |
| 220 | return 0; |
| 221 | } |
| 222 | spin_unlock(&DRM(mem_lock)); |
| 223 | |
| 224 | address = __get_free_pages(GFP_KERNEL, order); |
| 225 | if (!address) { |
| 226 | spin_lock(&DRM(mem_lock)); |
| 227 | ++DRM(mem_stats)[area].fail_count; |
| 228 | spin_unlock(&DRM(mem_lock)); |
| 229 | return 0; |
| 230 | } |
| 231 | spin_lock(&DRM(mem_lock)); |
| 232 | ++DRM(mem_stats)[area].succeed_count; |
| 233 | DRM(mem_stats)[area].bytes_allocated += bytes; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 234 | DRM(ram_used) += bytes; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 235 | spin_unlock(&DRM(mem_lock)); |
| 236 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 237 | /* Zero outside the lock */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 238 | memset((void *)address, 0, bytes); |
| 239 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 240 | /* Reserve */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 241 | for (addr = address, sz = bytes; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 242 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 243 | SetPageReserved(virt_to_page(addr)); |
| 244 | } |
| 245 | |
| 246 | return address; |
| 247 | } |
| 248 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 249 | void DRM(free_pages) (unsigned long address, int order, int area) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 250 | unsigned long bytes = PAGE_SIZE << order; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 251 | int alloc_count; |
| 252 | int free_count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 253 | unsigned long addr; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 254 | unsigned int sz; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 255 | |
| 256 | if (!address) { |
| 257 | DRM_MEM_ERROR(area, "Attempt to free address 0\n"); |
| 258 | } else { |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 259 | /* Unreserve */ |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 260 | for (addr = address, sz = bytes; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 261 | sz > 0; addr += PAGE_SIZE, sz -= PAGE_SIZE) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 262 | ClearPageReserved(virt_to_page(addr)); |
| 263 | } |
| 264 | free_pages(address, order); |
| 265 | } |
| 266 | |
| 267 | spin_lock(&DRM(mem_lock)); |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 268 | free_count = ++DRM(mem_stats)[area].free_count; |
| 269 | alloc_count = DRM(mem_stats)[area].succeed_count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 270 | DRM(mem_stats)[area].bytes_freed += bytes; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 271 | DRM(ram_used) -= bytes; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 272 | spin_unlock(&DRM(mem_lock)); |
| 273 | if (free_count > alloc_count) { |
| 274 | DRM_MEM_ERROR(area, |
| 275 | "Excess frees: %d frees, %d allocs\n", |
| 276 | free_count, alloc_count); |
| 277 | } |
| 278 | } |
| 279 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 280 | void *DRM(ioremap) (unsigned long offset, unsigned long size, |
| 281 | drm_device_t * dev) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 282 | void *pt; |
| 283 | |
| 284 | if (!size) { |
| 285 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, |
| 286 | "Mapping 0 bytes at 0x%08lx\n", offset); |
| 287 | return NULL; |
| 288 | } |
| 289 | |
| 290 | if (!(pt = drm_ioremap(offset, size, dev))) { |
| 291 | spin_lock(&DRM(mem_lock)); |
| 292 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; |
| 293 | spin_unlock(&DRM(mem_lock)); |
| 294 | return NULL; |
| 295 | } |
| 296 | spin_lock(&DRM(mem_lock)); |
| 297 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; |
| 298 | DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; |
| 299 | spin_unlock(&DRM(mem_lock)); |
| 300 | return pt; |
| 301 | } |
| 302 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 303 | void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size, |
| 304 | drm_device_t * dev) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 305 | void *pt; |
| 306 | |
| 307 | if (!size) { |
| 308 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, |
| 309 | "Mapping 0 bytes at 0x%08lx\n", offset); |
| 310 | return NULL; |
| 311 | } |
| 312 | |
| 313 | if (!(pt = drm_ioremap_nocache(offset, size, dev))) { |
| 314 | spin_lock(&DRM(mem_lock)); |
| 315 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; |
| 316 | spin_unlock(&DRM(mem_lock)); |
| 317 | return NULL; |
| 318 | } |
| 319 | spin_lock(&DRM(mem_lock)); |
| 320 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; |
| 321 | DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; |
| 322 | spin_unlock(&DRM(mem_lock)); |
| 323 | return pt; |
| 324 | } |
| 325 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 326 | void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 327 | int alloc_count; |
| 328 | int free_count; |
| 329 | |
| 330 | if (!pt) |
| 331 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, |
| 332 | "Attempt to free NULL pointer\n"); |
| 333 | else |
| 334 | drm_ioremapfree(pt, size, dev); |
| 335 | |
| 336 | spin_lock(&DRM(mem_lock)); |
| 337 | DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 338 | free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count; |
| 339 | alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 340 | spin_unlock(&DRM(mem_lock)); |
| 341 | if (free_count > alloc_count) { |
| 342 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, |
| 343 | "Excess frees: %d frees, %d allocs\n", |
| 344 | free_count, alloc_count); |
| 345 | } |
| 346 | } |
| 347 | |
| 348 | #if __OS_HAS_AGP |
| 349 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 350 | DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 351 | DRM_AGP_MEM *handle; |
| 352 | |
| 353 | if (!pages) { |
| 354 | DRM_MEM_ERROR(DRM_MEM_TOTALAGP, "Allocating 0 pages\n"); |
| 355 | return NULL; |
| 356 | } |
| 357 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 358 | if ((handle = DRM(agp_allocate_memory) (pages, type))) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 359 | spin_lock(&DRM(mem_lock)); |
| 360 | ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; |
| 361 | DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 362 | += pages << PAGE_SHIFT; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 363 | spin_unlock(&DRM(mem_lock)); |
| 364 | return handle; |
| 365 | } |
| 366 | spin_lock(&DRM(mem_lock)); |
| 367 | ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count; |
| 368 | spin_unlock(&DRM(mem_lock)); |
| 369 | return NULL; |
| 370 | } |
| 371 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 372 | int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) { |
| 373 | int alloc_count; |
| 374 | int free_count; |
| 375 | int retval = -EINVAL; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 376 | |
| 377 | if (!handle) { |
| 378 | DRM_MEM_ERROR(DRM_MEM_TOTALAGP, |
| 379 | "Attempt to free NULL AGP handle\n"); |
| 380 | return retval; |
| 381 | } |
| 382 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 383 | if (DRM(agp_free_memory) (handle)) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 384 | spin_lock(&DRM(mem_lock)); |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 385 | free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count; |
| 386 | alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 387 | DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 388 | += pages << PAGE_SHIFT; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 389 | spin_unlock(&DRM(mem_lock)); |
| 390 | if (free_count > alloc_count) { |
| 391 | DRM_MEM_ERROR(DRM_MEM_TOTALAGP, |
| 392 | "Excess frees: %d frees, %d allocs\n", |
| 393 | free_count, alloc_count); |
| 394 | } |
| 395 | return 0; |
| 396 | } |
| 397 | return retval; |
| 398 | } |
| 399 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 400 | int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 401 | int retcode = -EINVAL; |
| 402 | |
| 403 | if (!handle) { |
| 404 | DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, |
| 405 | "Attempt to bind NULL AGP handle\n"); |
| 406 | return retcode; |
| 407 | } |
| 408 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 409 | if (!(retcode = DRM(agp_bind_memory) (handle, start))) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 410 | spin_lock(&DRM(mem_lock)); |
| 411 | ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; |
| 412 | DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 413 | += handle->page_count << PAGE_SHIFT; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 414 | spin_unlock(&DRM(mem_lock)); |
| 415 | return retcode; |
| 416 | } |
| 417 | spin_lock(&DRM(mem_lock)); |
| 418 | ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count; |
| 419 | spin_unlock(&DRM(mem_lock)); |
| 420 | return retcode; |
| 421 | } |
| 422 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 423 | int DRM(unbind_agp) (DRM_AGP_MEM * handle) { |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 424 | int alloc_count; |
| 425 | int free_count; |
| 426 | int retcode = -EINVAL; |
| 427 | |
| 428 | if (!handle) { |
| 429 | DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, |
| 430 | "Attempt to unbind NULL AGP handle\n"); |
| 431 | return retcode; |
| 432 | } |
| 433 | |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 434 | if ((retcode = DRM(agp_unbind_memory) (handle))) |
| 435 | return retcode; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 436 | spin_lock(&DRM(mem_lock)); |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 437 | free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 438 | alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; |
| 439 | DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed |
Dave Airlie | b5e89ed | 2005-09-25 14:28:13 +1000 | [diff] [blame] | 440 | += handle->page_count << PAGE_SHIFT; |
Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 441 | spin_unlock(&DRM(mem_lock)); |
| 442 | if (free_count > alloc_count) { |
| 443 | DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, |
| 444 | "Excess frees: %d frees, %d allocs\n", |
| 445 | free_count, alloc_count); |
| 446 | } |
| 447 | return retcode; |
| 448 | } |
| 449 | #endif |