Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

drm/vmwgfx: Remove the dedicated memory accounting

vmwgfx shared very elaborate memory accounting with ttm. It was moved
from ttm to vmwgfx in change
f07069da6b4c ("drm/ttm: move memory accounting into vmwgfx v4")
but because of complexity it was hard to maintain. Some parts of the code
weren't freeing memory correctly and some were missing accounting all
together. While those would be fairly easy to fix the fundamental reason
for memory accounting in the driver was the ability to invoke shrinker
which is part of TTM code as well (with support for unified memory
hopefully coming soon).

That meant that vmwgfx had a lot of code that was either unused or
duplicating code from TTM. Removing this code also prevents excessive
calls to global swapout which were common during memory pressure
because both vmwgfx and TTM would invoke the shrinker when memory
usage reached half of RAM.

Fixes: f07069da6b4c ("drm/ttm: move memory accounting into vmwgfx v4")
Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Martin Krastev <krastevm@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211206172620.3139754-2-zack@kde.org

+38 -1316
+1 -1
drivers/gpu/drm/vmwgfx/Makefile
··· 9 9 vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \ 10 10 vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \ 11 11 vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \ 12 - vmwgfx_devcaps.o ttm_object.o ttm_memory.o vmwgfx_system_manager.o 12 + vmwgfx_devcaps.o ttm_object.o vmwgfx_system_manager.o 13 13 14 14 vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o 15 15 vmwgfx-$(CONFIG_TRANSPARENT_HUGEPAGE) += vmwgfx_thp.o
-586
drivers/gpu/drm/vmwgfx/ttm_memory.c
··· 1 - /* SPDX-License-Identifier: GPL-2.0 OR MIT */ 2 - /************************************************************************** 3 - * 4 - * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA 5 - * All Rights Reserved. 6 - * 7 - * Permission is hereby granted, free of charge, to any person obtaining a 8 - * copy of this software and associated documentation files (the 9 - * "Software"), to deal in the Software without restriction, including 10 - * without limitation the rights to use, copy, modify, merge, publish, 11 - * distribute, sub license, and/or sell copies of the Software, and to 12 - * permit persons to whom the Software is furnished to do so, subject to 13 - * the following conditions: 14 - * 15 - * The above copyright notice and this permission notice (including the 16 - * next paragraph) shall be included in all copies or substantial portions 17 - * of the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 22 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 23 - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 25 - * USE OR OTHER DEALINGS IN THE SOFTWARE. 26 - * 27 - **************************************************************************/ 28 - 29 - #define pr_fmt(fmt) "[TTM] " fmt 30 - 31 - #include <linux/spinlock.h> 32 - #include <linux/sched.h> 33 - #include <linux/wait.h> 34 - #include <linux/mm.h> 35 - #include <linux/module.h> 36 - #include <linux/slab.h> 37 - 38 - #include <drm/drm_device.h> 39 - #include <drm/drm_file.h> 40 - #include <drm/ttm/ttm_device.h> 41 - 42 - #include "ttm_memory.h" 43 - 44 - #define TTM_MEMORY_ALLOC_RETRIES 4 45 - 46 - struct ttm_mem_global ttm_mem_glob; 47 - EXPORT_SYMBOL(ttm_mem_glob); 48 - 49 - struct ttm_mem_zone { 50 - struct kobject kobj; 51 - struct ttm_mem_global *glob; 52 - const char *name; 53 - uint64_t zone_mem; 54 - uint64_t emer_mem; 55 - uint64_t max_mem; 56 - uint64_t swap_limit; 57 - uint64_t used_mem; 58 - }; 59 - 60 - static struct attribute ttm_mem_sys = { 61 - .name = "zone_memory", 62 - .mode = S_IRUGO 63 - }; 64 - static struct attribute ttm_mem_emer = { 65 - .name = "emergency_memory", 66 - .mode = S_IRUGO | S_IWUSR 67 - }; 68 - static struct attribute ttm_mem_max = { 69 - .name = "available_memory", 70 - .mode = S_IRUGO | S_IWUSR 71 - }; 72 - static struct attribute ttm_mem_swap = { 73 - .name = "swap_limit", 74 - .mode = S_IRUGO | S_IWUSR 75 - }; 76 - static struct attribute ttm_mem_used = { 77 - .name = "used_memory", 78 - .mode = S_IRUGO 79 - }; 80 - 81 - static void ttm_mem_zone_kobj_release(struct kobject *kobj) 82 - { 83 - struct ttm_mem_zone *zone = 84 - container_of(kobj, struct ttm_mem_zone, kobj); 85 - 86 - pr_info("Zone %7s: Used memory at exit: %llu KiB\n", 87 - zone->name, (unsigned long long)zone->used_mem >> 10); 88 - kfree(zone); 89 - } 90 - 91 - static ssize_t ttm_mem_zone_show(struct kobject *kobj, 92 - struct attribute *attr, 93 - char *buffer) 94 - { 95 - struct ttm_mem_zone *zone = 96 - container_of(kobj, struct ttm_mem_zone, kobj); 97 - uint64_t val = 0; 98 - 99 - spin_lock(&zone->glob->lock); 100 - if (attr == &ttm_mem_sys) 101 - val = zone->zone_mem; 102 - else if (attr == &ttm_mem_emer) 103 - val = zone->emer_mem; 104 - else if (attr == &ttm_mem_max) 105 - val = zone->max_mem; 106 - else if (attr == &ttm_mem_swap) 107 - val = zone->swap_limit; 108 - else if (attr == &ttm_mem_used) 109 - val = zone->used_mem; 110 - spin_unlock(&zone->glob->lock); 111 - 112 - return snprintf(buffer, PAGE_SIZE, "%llu\n", 113 - (unsigned long long) val >> 10); 114 - } 115 - 116 - static void ttm_check_swapping(struct ttm_mem_global *glob); 117 - 118 - static ssize_t ttm_mem_zone_store(struct kobject *kobj, 119 - struct attribute *attr, 120 - const char *buffer, 121 - size_t size) 122 - { 123 - struct ttm_mem_zone *zone = 124 - container_of(kobj, struct ttm_mem_zone, kobj); 125 - int chars; 126 - unsigned long val; 127 - uint64_t val64; 128 - 129 - chars = sscanf(buffer, "%lu", &val); 130 - if (chars == 0) 131 - return size; 132 - 133 - val64 = val; 134 - val64 <<= 10; 135 - 136 - spin_lock(&zone->glob->lock); 137 - if (val64 > zone->zone_mem) 138 - val64 = zone->zone_mem; 139 - if (attr == &ttm_mem_emer) { 140 - zone->emer_mem = val64; 141 - if (zone->max_mem > val64) 142 - zone->max_mem = val64; 143 - } else if (attr == &ttm_mem_max) { 144 - zone->max_mem = val64; 145 - if (zone->emer_mem < val64) 146 - zone->emer_mem = val64; 147 - } else if (attr == &ttm_mem_swap) 148 - zone->swap_limit = val64; 149 - spin_unlock(&zone->glob->lock); 150 - 151 - ttm_check_swapping(zone->glob); 152 - 153 - return size; 154 - } 155 - 156 - static struct attribute *ttm_mem_zone_attrs[] = { 157 - &ttm_mem_sys, 158 - &ttm_mem_emer, 159 - &ttm_mem_max, 160 - &ttm_mem_swap, 161 - &ttm_mem_used, 162 - NULL 163 - }; 164 - 165 - static const struct sysfs_ops ttm_mem_zone_ops = { 166 - .show = &ttm_mem_zone_show, 167 - .store = &ttm_mem_zone_store 168 - }; 169 - 170 - static struct kobj_type ttm_mem_zone_kobj_type = { 171 - .release = &ttm_mem_zone_kobj_release, 172 - .sysfs_ops = &ttm_mem_zone_ops, 173 - .default_attrs = ttm_mem_zone_attrs, 174 - }; 175 - static struct kobj_type ttm_mem_glob_kobj_type = {0}; 176 - 177 - static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob, 178 - bool from_wq, uint64_t extra) 179 - { 180 - unsigned int i; 181 - struct ttm_mem_zone *zone; 182 - uint64_t target; 183 - 184 - for (i = 0; i < glob->num_zones; ++i) { 185 - zone = glob->zones[i]; 186 - 187 - if (from_wq) 188 - target = zone->swap_limit; 189 - else if (capable(CAP_SYS_ADMIN)) 190 - target = zone->emer_mem; 191 - else 192 - target = zone->max_mem; 193 - 194 - target = (extra > target) ? 0ULL : target; 195 - 196 - if (zone->used_mem > target) 197 - return true; 198 - } 199 - return false; 200 - } 201 - 202 - /* 203 - * At this point we only support a single shrink callback. 204 - * Extend this if needed, perhaps using a linked list of callbacks. 205 - * Note that this function is reentrant: 206 - * many threads may try to swap out at any given time. 207 - */ 208 - 209 - static void ttm_shrink(struct ttm_mem_global *glob, bool from_wq, 210 - uint64_t extra, struct ttm_operation_ctx *ctx) 211 - { 212 - int ret; 213 - 214 - spin_lock(&glob->lock); 215 - 216 - while (ttm_zones_above_swap_target(glob, from_wq, extra)) { 217 - spin_unlock(&glob->lock); 218 - ret = ttm_global_swapout(ctx, GFP_KERNEL); 219 - spin_lock(&glob->lock); 220 - if (unlikely(ret <= 0)) 221 - break; 222 - } 223 - 224 - spin_unlock(&glob->lock); 225 - } 226 - 227 - static void ttm_shrink_work(struct work_struct *work) 228 - { 229 - struct ttm_operation_ctx ctx = { 230 - .interruptible = false, 231 - .no_wait_gpu = false 232 - }; 233 - struct ttm_mem_global *glob = 234 - container_of(work, struct ttm_mem_global, work); 235 - 236 - ttm_shrink(glob, true, 0ULL, &ctx); 237 - } 238 - 239 - static int ttm_mem_init_kernel_zone(struct ttm_mem_global *glob, 240 - const struct sysinfo *si) 241 - { 242 - struct ttm_mem_zone *zone = kzalloc(sizeof(*zone), GFP_KERNEL); 243 - uint64_t mem; 244 - int ret; 245 - 246 - if (unlikely(!zone)) 247 - return -ENOMEM; 248 - 249 - mem = si->totalram - si->totalhigh; 250 - mem *= si->mem_unit; 251 - 252 - zone->name = "kernel"; 253 - zone->zone_mem = mem; 254 - zone->max_mem = mem >> 1; 255 - zone->emer_mem = (mem >> 1) + (mem >> 2); 256 - zone->swap_limit = zone->max_mem - (mem >> 3); 257 - zone->used_mem = 0; 258 - zone->glob = glob; 259 - glob->zone_kernel = zone; 260 - ret = kobject_init_and_add( 261 - &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name); 262 - if (unlikely(ret != 0)) { 263 - kobject_put(&zone->kobj); 264 - return ret; 265 - } 266 - glob->zones[glob->num_zones++] = zone; 267 - return 0; 268 - } 269 - 270 - #ifdef CONFIG_HIGHMEM 271 - static int ttm_mem_init_highmem_zone(struct ttm_mem_global *glob, 272 - const struct sysinfo *si) 273 - { 274 - struct ttm_mem_zone *zone; 275 - uint64_t mem; 276 - int ret; 277 - 278 - if (si->totalhigh == 0) 279 - return 0; 280 - 281 - zone = kzalloc(sizeof(*zone), GFP_KERNEL); 282 - if (unlikely(!zone)) 283 - return -ENOMEM; 284 - 285 - mem = si->totalram; 286 - mem *= si->mem_unit; 287 - 288 - zone->name = "highmem"; 289 - zone->zone_mem = mem; 290 - zone->max_mem = mem >> 1; 291 - zone->emer_mem = (mem >> 1) + (mem >> 2); 292 - zone->swap_limit = zone->max_mem - (mem >> 3); 293 - zone->used_mem = 0; 294 - zone->glob = glob; 295 - glob->zone_highmem = zone; 296 - ret = kobject_init_and_add( 297 - &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, "%s", 298 - zone->name); 299 - if (unlikely(ret != 0)) { 300 - kobject_put(&zone->kobj); 301 - return ret; 302 - } 303 - glob->zones[glob->num_zones++] = zone; 304 - return 0; 305 - } 306 - #else 307 - static int ttm_mem_init_dma32_zone(struct ttm_mem_global *glob, 308 - const struct sysinfo *si) 309 - { 310 - struct ttm_mem_zone *zone = kzalloc(sizeof(*zone), GFP_KERNEL); 311 - uint64_t mem; 312 - int ret; 313 - 314 - if (unlikely(!zone)) 315 - return -ENOMEM; 316 - 317 - mem = si->totalram; 318 - mem *= si->mem_unit; 319 - 320 - /** 321 - * No special dma32 zone needed. 322 - */ 323 - 324 - if (mem <= ((uint64_t) 1ULL << 32)) { 325 - kfree(zone); 326 - return 0; 327 - } 328 - 329 - /* 330 - * Limit max dma32 memory to 4GB for now 331 - * until we can figure out how big this 332 - * zone really is. 333 - */ 334 - 335 - mem = ((uint64_t) 1ULL << 32); 336 - zone->name = "dma32"; 337 - zone->zone_mem = mem; 338 - zone->max_mem = mem >> 1; 339 - zone->emer_mem = (mem >> 1) + (mem >> 2); 340 - zone->swap_limit = zone->max_mem - (mem >> 3); 341 - zone->used_mem = 0; 342 - zone->glob = glob; 343 - glob->zone_dma32 = zone; 344 - ret = kobject_init_and_add( 345 - &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name); 346 - if (unlikely(ret != 0)) { 347 - kobject_put(&zone->kobj); 348 - return ret; 349 - } 350 - glob->zones[glob->num_zones++] = zone; 351 - return 0; 352 - } 353 - #endif 354 - 355 - int ttm_mem_global_init(struct ttm_mem_global *glob, struct device *dev) 356 - { 357 - struct sysinfo si; 358 - int ret; 359 - int i; 360 - struct ttm_mem_zone *zone; 361 - 362 - spin_lock_init(&glob->lock); 363 - glob->swap_queue = create_singlethread_workqueue("ttm_swap"); 364 - INIT_WORK(&glob->work, ttm_shrink_work); 365 - 366 - ret = kobject_init_and_add(&glob->kobj, &ttm_mem_glob_kobj_type, 367 - &dev->kobj, "memory_accounting"); 368 - if (unlikely(ret != 0)) { 369 - kobject_put(&glob->kobj); 370 - return ret; 371 - } 372 - 373 - si_meminfo(&si); 374 - 375 - ret = ttm_mem_init_kernel_zone(glob, &si); 376 - if (unlikely(ret != 0)) 377 - goto out_no_zone; 378 - #ifdef CONFIG_HIGHMEM 379 - ret = ttm_mem_init_highmem_zone(glob, &si); 380 - if (unlikely(ret != 0)) 381 - goto out_no_zone; 382 - #else 383 - ret = ttm_mem_init_dma32_zone(glob, &si); 384 - if (unlikely(ret != 0)) 385 - goto out_no_zone; 386 - #endif 387 - for (i = 0; i < glob->num_zones; ++i) { 388 - zone = glob->zones[i]; 389 - pr_info("Zone %7s: Available graphics memory: %llu KiB\n", 390 - zone->name, (unsigned long long)zone->max_mem >> 10); 391 - } 392 - return 0; 393 - out_no_zone: 394 - ttm_mem_global_release(glob); 395 - return ret; 396 - } 397 - 398 - void ttm_mem_global_release(struct ttm_mem_global *glob) 399 - { 400 - struct ttm_mem_zone *zone; 401 - unsigned int i; 402 - 403 - destroy_workqueue(glob->swap_queue); 404 - glob->swap_queue = NULL; 405 - for (i = 0; i < glob->num_zones; ++i) { 406 - zone = glob->zones[i]; 407 - kobject_del(&zone->kobj); 408 - kobject_put(&zone->kobj); 409 - } 410 - kobject_del(&glob->kobj); 411 - kobject_put(&glob->kobj); 412 - memset(glob, 0, sizeof(*glob)); 413 - } 414 - 415 - static void ttm_check_swapping(struct ttm_mem_global *glob) 416 - { 417 - bool needs_swapping = false; 418 - unsigned int i; 419 - struct ttm_mem_zone *zone; 420 - 421 - spin_lock(&glob->lock); 422 - for (i = 0; i < glob->num_zones; ++i) { 423 - zone = glob->zones[i]; 424 - if (zone->used_mem > zone->swap_limit) { 425 - needs_swapping = true; 426 - break; 427 - } 428 - } 429 - 430 - spin_unlock(&glob->lock); 431 - 432 - if (unlikely(needs_swapping)) 433 - (void)queue_work(glob->swap_queue, &glob->work); 434 - 435 - } 436 - 437 - static void ttm_mem_global_free_zone(struct ttm_mem_global *glob, 438 - struct ttm_mem_zone *single_zone, 439 - uint64_t amount) 440 - { 441 - unsigned int i; 442 - struct ttm_mem_zone *zone; 443 - 444 - spin_lock(&glob->lock); 445 - for (i = 0; i < glob->num_zones; ++i) { 446 - zone = glob->zones[i]; 447 - if (single_zone && zone != single_zone) 448 - continue; 449 - zone->used_mem -= amount; 450 - } 451 - spin_unlock(&glob->lock); 452 - } 453 - 454 - void ttm_mem_global_free(struct ttm_mem_global *glob, 455 - uint64_t amount) 456 - { 457 - return ttm_mem_global_free_zone(glob, glob->zone_kernel, amount); 458 - } 459 - EXPORT_SYMBOL(ttm_mem_global_free); 460 - 461 - static int ttm_mem_global_reserve(struct ttm_mem_global *glob, 462 - struct ttm_mem_zone *single_zone, 463 - uint64_t amount, bool reserve) 464 - { 465 - uint64_t limit; 466 - int ret = -ENOMEM; 467 - unsigned int i; 468 - struct ttm_mem_zone *zone; 469 - 470 - spin_lock(&glob->lock); 471 - for (i = 0; i < glob->num_zones; ++i) { 472 - zone = glob->zones[i]; 473 - if (single_zone && zone != single_zone) 474 - continue; 475 - 476 - limit = (capable(CAP_SYS_ADMIN)) ? 477 - zone->emer_mem : zone->max_mem; 478 - 479 - if (zone->used_mem > limit) 480 - goto out_unlock; 481 - } 482 - 483 - if (reserve) { 484 - for (i = 0; i < glob->num_zones; ++i) { 485 - zone = glob->zones[i]; 486 - if (single_zone && zone != single_zone) 487 - continue; 488 - zone->used_mem += amount; 489 - } 490 - } 491 - 492 - ret = 0; 493 - out_unlock: 494 - spin_unlock(&glob->lock); 495 - ttm_check_swapping(glob); 496 - 497 - return ret; 498 - } 499 - 500 - 501 - static int ttm_mem_global_alloc_zone(struct ttm_mem_global *glob, 502 - struct ttm_mem_zone *single_zone, 503 - uint64_t memory, 504 - struct ttm_operation_ctx *ctx) 505 - { 506 - int count = TTM_MEMORY_ALLOC_RETRIES; 507 - 508 - while (unlikely(ttm_mem_global_reserve(glob, 509 - single_zone, 510 - memory, true) 511 - != 0)) { 512 - if (ctx->no_wait_gpu) 513 - return -ENOMEM; 514 - if (unlikely(count-- == 0)) 515 - return -ENOMEM; 516 - ttm_shrink(glob, false, memory + (memory >> 2) + 16, ctx); 517 - } 518 - 519 - return 0; 520 - } 521 - 522 - int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, 523 - struct ttm_operation_ctx *ctx) 524 - { 525 - /** 526 - * Normal allocations of kernel memory are registered in 527 - * the kernel zone. 528 - */ 529 - 530 - return ttm_mem_global_alloc_zone(glob, glob->zone_kernel, memory, ctx); 531 - } 532 - EXPORT_SYMBOL(ttm_mem_global_alloc); 533 - 534 - int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, 535 - struct page *page, uint64_t size, 536 - struct ttm_operation_ctx *ctx) 537 - { 538 - struct ttm_mem_zone *zone = NULL; 539 - 540 - /** 541 - * Page allocations may be registed in a single zone 542 - * only if highmem or !dma32. 543 - */ 544 - 545 - #ifdef CONFIG_HIGHMEM 546 - if (PageHighMem(page) && glob->zone_highmem != NULL) 547 - zone = glob->zone_highmem; 548 - #else 549 - if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL) 550 - zone = glob->zone_kernel; 551 - #endif 552 - return ttm_mem_global_alloc_zone(glob, zone, size, ctx); 553 - } 554 - 555 - void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page, 556 - uint64_t size) 557 - { 558 - struct ttm_mem_zone *zone = NULL; 559 - 560 - #ifdef CONFIG_HIGHMEM 561 - if (PageHighMem(page) && glob->zone_highmem != NULL) 562 - zone = glob->zone_highmem; 563 - #else 564 - if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL) 565 - zone = glob->zone_kernel; 566 - #endif 567 - ttm_mem_global_free_zone(glob, zone, size); 568 - } 569 - 570 - size_t ttm_round_pot(size_t size) 571 - { 572 - if ((size & (size - 1)) == 0) 573 - return size; 574 - else if (size > PAGE_SIZE) 575 - return PAGE_ALIGN(size); 576 - else { 577 - size_t tmp_size = 4; 578 - 579 - while (tmp_size < size) 580 - tmp_size <<= 1; 581 - 582 - return tmp_size; 583 - } 584 - return 0; 585 - } 586 - EXPORT_SYMBOL(ttm_round_pot);
-92
drivers/gpu/drm/vmwgfx/ttm_memory.h
··· 1 - /************************************************************************** 2 - * 3 - * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA 4 - * All Rights Reserved. 5 - * 6 - * Permission is hereby granted, free of charge, to any person obtaining a 7 - * copy of this software and associated documentation files (the 8 - * "Software"), to deal in the Software without restriction, including 9 - * without limitation the rights to use, copy, modify, merge, publish, 10 - * distribute, sub license, and/or sell copies of the Software, and to 11 - * permit persons to whom the Software is furnished to do so, subject to 12 - * the following conditions: 13 - * 14 - * The above copyright notice and this permission notice (including the 15 - * next paragraph) shall be included in all copies or substantial portions 16 - * of the Software. 17 - * 18 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 - * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 - * 26 - **************************************************************************/ 27 - 28 - #ifndef TTM_MEMORY_H 29 - #define TTM_MEMORY_H 30 - 31 - #include <linux/workqueue.h> 32 - #include <linux/spinlock.h> 33 - #include <linux/bug.h> 34 - #include <linux/wait.h> 35 - #include <linux/errno.h> 36 - #include <linux/kobject.h> 37 - #include <linux/mm.h> 38 - 39 - #include <drm/ttm/ttm_bo_api.h> 40 - 41 - /** 42 - * struct ttm_mem_global - Global memory accounting structure. 43 - * 44 - * @shrink: A single callback to shrink TTM memory usage. Extend this 45 - * to a linked list to be able to handle multiple callbacks when needed. 46 - * @swap_queue: A workqueue to handle shrinking in low memory situations. We 47 - * need a separate workqueue since it will spend a lot of time waiting 48 - * for the GPU, and this will otherwise block other workqueue tasks(?) 49 - * At this point we use only a single-threaded workqueue. 50 - * @work: The workqueue callback for the shrink queue. 51 - * @lock: Lock to protect the @shrink - and the memory accounting members, 52 - * that is, essentially the whole structure with some exceptions. 53 - * @zones: Array of pointers to accounting zones. 54 - * @num_zones: Number of populated entries in the @zones array. 55 - * @zone_kernel: Pointer to the kernel zone. 56 - * @zone_highmem: Pointer to the highmem zone if there is one. 57 - * @zone_dma32: Pointer to the dma32 zone if there is one. 58 - * 59 - * Note that this structure is not per device. It should be global for all 60 - * graphics devices. 61 - */ 62 - 63 - #define TTM_MEM_MAX_ZONES 2 64 - struct ttm_mem_zone; 65 - extern struct ttm_mem_global { 66 - struct kobject kobj; 67 - struct workqueue_struct *swap_queue; 68 - struct work_struct work; 69 - spinlock_t lock; 70 - struct ttm_mem_zone *zones[TTM_MEM_MAX_ZONES]; 71 - unsigned int num_zones; 72 - struct ttm_mem_zone *zone_kernel; 73 - #ifdef CONFIG_HIGHMEM 74 - struct ttm_mem_zone *zone_highmem; 75 - #else 76 - struct ttm_mem_zone *zone_dma32; 77 - #endif 78 - } ttm_mem_glob; 79 - 80 - int ttm_mem_global_init(struct ttm_mem_global *glob, struct device *dev); 81 - void ttm_mem_global_release(struct ttm_mem_global *glob); 82 - int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, 83 - struct ttm_operation_ctx *ctx); 84 - void ttm_mem_global_free(struct ttm_mem_global *glob, uint64_t amount); 85 - int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, 86 - struct page *page, uint64_t size, 87 - struct ttm_operation_ctx *ctx); 88 - void ttm_mem_global_free_page(struct ttm_mem_global *glob, 89 - struct page *page, uint64_t size); 90 - size_t ttm_round_pot(size_t size); 91 - 92 - #endif
+2 -34
drivers/gpu/drm/vmwgfx/ttm_object.c
··· 93 93 spinlock_t object_lock; 94 94 struct vmwgfx_open_hash object_hash; 95 95 atomic_t object_count; 96 - struct ttm_mem_global *mem_glob; 97 96 struct dma_buf_ops ops; 98 97 void (*dmabuf_release)(struct dma_buf *dma_buf); 99 - size_t dma_buf_size; 100 98 struct idr idr; 101 99 }; 102 100 ··· 350 352 struct vmwgfx_open_hash *ht = &tfile->ref_hash[ref_type]; 351 353 struct ttm_ref_object *ref; 352 354 struct vmwgfx_hash_item *hash; 353 - struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 354 - struct ttm_operation_ctx ctx = { 355 - .interruptible = false, 356 - .no_wait_gpu = false 357 - }; 358 355 int ret = -EINVAL; 359 356 360 357 if (base->tfile != tfile && !base->shareable) ··· 374 381 if (require_existed) 375 382 return -EPERM; 376 383 377 - ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), 378 - &ctx); 379 - if (unlikely(ret != 0)) 380 - return ret; 381 384 ref = kmalloc(sizeof(*ref), GFP_KERNEL); 382 385 if (unlikely(ref == NULL)) { 383 - ttm_mem_global_free(mem_glob, sizeof(*ref)); 384 386 return -ENOMEM; 385 387 } 386 388 ··· 400 412 spin_unlock(&tfile->lock); 401 413 BUG_ON(ret != -EINVAL); 402 414 403 - ttm_mem_global_free(mem_glob, sizeof(*ref)); 404 415 kfree(ref); 405 416 } 406 417 ··· 414 427 struct ttm_base_object *base = ref->obj; 415 428 struct ttm_object_file *tfile = ref->tfile; 416 429 struct vmwgfx_open_hash *ht; 417 - struct ttm_mem_global *mem_glob = tfile->tdev->mem_glob; 418 430 419 431 ht = &tfile->ref_hash[ref->ref_type]; 420 432 (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash); ··· 424 438 base->ref_obj_release(base, ref->ref_type); 425 439 426 440 ttm_base_object_unref(&ref->obj); 427 - ttm_mem_global_free(mem_glob, sizeof(*ref)); 428 441 kfree_rcu(ref, rcu_head); 429 442 spin_lock(&tfile->lock); 430 443 } ··· 511 526 } 512 527 513 528 struct ttm_object_device * 514 - ttm_object_device_init(struct ttm_mem_global *mem_glob, 515 - unsigned int hash_order, 529 + ttm_object_device_init(unsigned int hash_order, 516 530 const struct dma_buf_ops *ops) 517 531 { 518 532 struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL); ··· 520 536 if (unlikely(tdev == NULL)) 521 537 return NULL; 522 538 523 - tdev->mem_glob = mem_glob; 524 539 spin_lock_init(&tdev->object_lock); 525 540 atomic_set(&tdev->object_count, 0); 526 541 ret = vmwgfx_ht_create(&tdev->object_hash, hash_order); ··· 530 547 tdev->ops = *ops; 531 548 tdev->dmabuf_release = tdev->ops.release; 532 549 tdev->ops.release = ttm_prime_dmabuf_release; 533 - tdev->dma_buf_size = ttm_round_pot(sizeof(struct dma_buf)) + 534 - ttm_round_pot(sizeof(struct file)); 535 550 return tdev; 536 551 537 552 out_no_object_hash: ··· 614 633 if (prime->dma_buf == dma_buf) 615 634 prime->dma_buf = NULL; 616 635 mutex_unlock(&prime->mutex); 617 - ttm_mem_global_free(tdev->mem_glob, tdev->dma_buf_size); 618 636 ttm_base_object_unref(&base); 619 637 } 620 638 ··· 695 715 dma_buf = prime->dma_buf; 696 716 if (!dma_buf || !get_dma_buf_unless_doomed(dma_buf)) { 697 717 DEFINE_DMA_BUF_EXPORT_INFO(exp_info); 698 - struct ttm_operation_ctx ctx = { 699 - .interruptible = true, 700 - .no_wait_gpu = false 701 - }; 702 718 exp_info.ops = &tdev->ops; 703 719 exp_info.size = prime->size; 704 720 exp_info.flags = flags; 705 721 exp_info.priv = prime; 706 722 707 723 /* 708 - * Need to create a new dma_buf, with memory accounting. 724 + * Need to create a new dma_buf 709 725 */ 710 - ret = ttm_mem_global_alloc(tdev->mem_glob, tdev->dma_buf_size, 711 - &ctx); 712 - if (unlikely(ret != 0)) { 713 - mutex_unlock(&prime->mutex); 714 - goto out_unref; 715 - } 716 726 717 727 dma_buf = dma_buf_export(&exp_info); 718 728 if (IS_ERR(dma_buf)) { 719 729 ret = PTR_ERR(dma_buf); 720 - ttm_mem_global_free(tdev->mem_glob, 721 - tdev->dma_buf_size); 722 730 mutex_unlock(&prime->mutex); 723 731 goto out_unref; 724 732 }
+1 -11
drivers/gpu/drm/vmwgfx/ttm_object.h
··· 42 42 #include <linux/list.h> 43 43 #include <linux/rcupdate.h> 44 44 45 - #include "ttm_memory.h" 46 45 #include "vmwgfx_hashtab.h" 47 46 48 47 /** ··· 295 296 /** 296 297 * ttm_object device init - initialize a struct ttm_object_device 297 298 * 298 - * @mem_glob: struct ttm_mem_global for memory accounting. 299 299 * @hash_order: Order of hash table used to hash the base objects. 300 300 * @ops: DMA buf ops for prime objects of this device. 301 301 * ··· 303 305 */ 304 306 305 307 extern struct ttm_object_device * 306 - ttm_object_device_init(struct ttm_mem_global *mem_glob, 307 - unsigned int hash_order, 308 + ttm_object_device_init(unsigned int hash_order, 308 309 const struct dma_buf_ops *ops); 309 310 310 311 /** ··· 348 351 349 352 #define ttm_prime_object_kfree(__obj, __prime) \ 350 353 kfree_rcu(__obj, __prime.base.rhead) 351 - 352 - /* 353 - * Extra memory required by the base object's idr storage, which is allocated 354 - * separately from the base object itself. We estimate an on-average 128 bytes 355 - * per idr. 356 - */ 357 - #define TTM_OBJ_EXTRA_SIZE 128 358 354 359 355 struct ttm_base_object * 360 356 ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key);
+2 -18
drivers/gpu/drm/vmwgfx/vmwgfx_binding.c
··· 1327 1327 } 1328 1328 1329 1329 /** 1330 - * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state with 1331 - * memory accounting. 1330 + * vmw_binding_state_alloc - Allocate a struct vmw_ctx_binding_state. 1332 1331 * 1333 1332 * @dev_priv: Pointer to a device private structure. 1334 1333 * ··· 1337 1338 vmw_binding_state_alloc(struct vmw_private *dev_priv) 1338 1339 { 1339 1340 struct vmw_ctx_binding_state *cbs; 1340 - struct ttm_operation_ctx ctx = { 1341 - .interruptible = false, 1342 - .no_wait_gpu = false 1343 - }; 1344 - int ret; 1345 - 1346 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), sizeof(*cbs), 1347 - &ctx); 1348 - if (ret) 1349 - return ERR_PTR(ret); 1350 1341 1351 1342 cbs = vzalloc(sizeof(*cbs)); 1352 1343 if (!cbs) { 1353 - ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1354 1344 return ERR_PTR(-ENOMEM); 1355 1345 } 1356 1346 ··· 1350 1362 } 1351 1363 1352 1364 /** 1353 - * vmw_binding_state_free - Free a struct vmw_ctx_binding_state and its 1354 - * memory accounting info. 1365 + * vmw_binding_state_free - Free a struct vmw_ctx_binding_state. 1355 1366 * 1356 1367 * @cbs: Pointer to the struct vmw_ctx_binding_state to be freed. 1357 1368 */ 1358 1369 void vmw_binding_state_free(struct vmw_ctx_binding_state *cbs) 1359 1370 { 1360 - struct vmw_private *dev_priv = cbs->dev_priv; 1361 - 1362 1371 vfree(cbs); 1363 - ttm_mem_global_free(vmw_mem_glob(dev_priv), sizeof(*cbs)); 1364 1372 } 1365 1373 1366 1374 /**
+9 -56
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
··· 392 392 393 393 394 394 /** 395 - * vmw_bo_acc_size - Calculate the pinned memory usage of buffers 396 - * 397 - * @dev_priv: Pointer to a struct vmw_private identifying the device. 398 - * @size: The requested buffer size. 399 - * @user: Whether this is an ordinary dma buffer or a user dma buffer. 400 - */ 401 - static size_t vmw_bo_acc_size(struct vmw_private *dev_priv, size_t size, 402 - bool user) 403 - { 404 - static size_t struct_size, user_struct_size; 405 - size_t num_pages = PFN_UP(size); 406 - size_t page_array_size = ttm_round_pot(num_pages * sizeof(void *)); 407 - 408 - if (unlikely(struct_size == 0)) { 409 - size_t backend_size = ttm_round_pot(vmw_tt_size); 410 - 411 - struct_size = backend_size + 412 - ttm_round_pot(sizeof(struct vmw_buffer_object)); 413 - user_struct_size = backend_size + 414 - ttm_round_pot(sizeof(struct vmw_user_buffer_object)) + 415 - TTM_OBJ_EXTRA_SIZE; 416 - } 417 - 418 - if (dev_priv->map_mode == vmw_dma_alloc_coherent) 419 - page_array_size += 420 - ttm_round_pot(num_pages * sizeof(dma_addr_t)); 421 - 422 - return ((user) ? user_struct_size : struct_size) + 423 - page_array_size; 424 - } 425 - 426 - 427 - /** 428 395 * vmw_bo_bo_free - vmw buffer object destructor 429 396 * 430 397 * @bo: Pointer to the embedded struct ttm_buffer_object ··· 438 471 struct ttm_placement *placement, 439 472 struct ttm_buffer_object **p_bo) 440 473 { 441 - struct ttm_operation_ctx ctx = { false, false }; 474 + struct ttm_operation_ctx ctx = { 475 + .interruptible = false, 476 + .no_wait_gpu = false 477 + }; 442 478 struct ttm_buffer_object *bo; 443 - size_t acc_size; 444 479 int ret; 445 480 446 481 bo = kzalloc(sizeof(*bo), GFP_KERNEL); 447 482 if (unlikely(!bo)) 448 483 return -ENOMEM; 449 - 450 - acc_size = ttm_round_pot(sizeof(*bo)); 451 - acc_size += ttm_round_pot(PFN_UP(size) * sizeof(void *)); 452 - acc_size += ttm_round_pot(sizeof(struct ttm_tt)); 453 - 454 - ret = ttm_mem_global_alloc(&ttm_mem_glob, acc_size, &ctx); 455 - if (unlikely(ret)) 456 - goto error_free; 457 - 458 484 459 485 bo->base.size = size; 460 486 dma_resv_init(&bo->base._resv); ··· 457 497 ttm_bo_type_kernel, placement, 0, 458 498 &ctx, NULL, NULL, NULL); 459 499 if (unlikely(ret)) 460 - goto error_account; 500 + goto error_free; 461 501 462 502 ttm_bo_pin(bo); 463 503 ttm_bo_unreserve(bo); 464 504 *p_bo = bo; 465 505 466 506 return 0; 467 - 468 - error_account: 469 - ttm_mem_global_free(&ttm_mem_glob, acc_size); 470 507 471 508 error_free: 472 509 kfree(bo); ··· 490 533 bool interruptible, bool pin, 491 534 void (*bo_free)(struct ttm_buffer_object *bo)) 492 535 { 493 - struct ttm_operation_ctx ctx = { interruptible, false }; 536 + struct ttm_operation_ctx ctx = { 537 + .interruptible = interruptible, 538 + .no_wait_gpu = false 539 + }; 494 540 struct ttm_device *bdev = &dev_priv->bdev; 495 - size_t acc_size; 496 541 int ret; 497 542 bool user = (bo_free == &vmw_user_bo_destroy); 498 543 499 544 WARN_ON_ONCE(!bo_free && (!user && (bo_free != vmw_bo_bo_free))); 500 - 501 - acc_size = vmw_bo_acc_size(dev_priv, size, user); 502 545 memset(vmw_bo, 0, sizeof(*vmw_bo)); 503 546 BUILD_BUG_ON(TTM_MAX_BO_PRIORITY <= 3); 504 547 vmw_bo->base.priority = 3; 505 548 vmw_bo->res_tree = RB_ROOT; 506 549 507 - ret = ttm_mem_global_alloc(&ttm_mem_glob, acc_size, &ctx); 508 - if (unlikely(ret)) 509 - return ret; 510 550 511 551 vmw_bo->base.base.size = size; 512 552 dma_resv_init(&vmw_bo->base.base._resv); ··· 513 559 ttm_bo_type_device, placement, 514 560 0, &ctx, NULL, NULL, bo_free); 515 561 if (unlikely(ret)) { 516 - ttm_mem_global_free(&ttm_mem_glob, acc_size); 517 562 return ret; 518 563 } 519 564
-19
drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
··· 324 324 kfree(man); 325 325 } 326 326 327 - /** 328 - * vmw_cmdbuf_res_man_size - Return the size of a command buffer managed 329 - * resource manager 330 - * 331 - * Returns the approximate allocation size of a command buffer managed 332 - * resource manager. 333 - */ 334 - size_t vmw_cmdbuf_res_man_size(void) 335 - { 336 - static size_t res_man_size; 337 - 338 - if (unlikely(res_man_size == 0)) 339 - res_man_size = 340 - ttm_round_pot(sizeof(struct vmw_cmdbuf_res_manager)) + 341 - ttm_round_pot(sizeof(struct hlist_head) << 342 - VMW_CMDBUF_RES_MAN_HT_ORDER); 343 - 344 - return res_man_size; 345 - }
-26
drivers/gpu/drm/vmwgfx/vmwgfx_context.c
··· 60 60 struct ttm_validate_buffer *val_buf); 61 61 static int vmw_dx_context_destroy(struct vmw_resource *res); 62 62 63 - static uint64_t vmw_user_context_size; 64 - 65 63 static const struct vmw_user_resource_conv user_context_conv = { 66 64 .object_type = VMW_RES_CONTEXT, 67 65 .base_obj_to_res = vmw_user_context_base_to_res, ··· 684 686 { 685 687 struct vmw_user_context *ctx = 686 688 container_of(res, struct vmw_user_context, res); 687 - struct vmw_private *dev_priv = res->dev_priv; 688 689 689 690 if (ctx->cbs) 690 691 vmw_binding_state_free(ctx->cbs); ··· 691 694 (void) vmw_context_bind_dx_query(res, NULL); 692 695 693 696 ttm_base_object_kfree(ctx, base); 694 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 695 - vmw_user_context_size); 696 697 } 697 698 698 699 /* ··· 727 732 struct vmw_resource *tmp; 728 733 struct drm_vmw_context_arg *arg = (struct drm_vmw_context_arg *)data; 729 734 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 730 - struct ttm_operation_ctx ttm_opt_ctx = { 731 - .interruptible = true, 732 - .no_wait_gpu = false 733 - }; 734 735 int ret; 735 736 736 737 if (!has_sm4_context(dev_priv) && dx) { ··· 734 743 return -EINVAL; 735 744 } 736 745 737 - if (unlikely(vmw_user_context_size == 0)) 738 - vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 739 - ((dev_priv->has_mob) ? vmw_cmdbuf_res_man_size() : 0) + 740 - + VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE; 741 - 742 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 743 - vmw_user_context_size, 744 - &ttm_opt_ctx); 745 - if (unlikely(ret != 0)) { 746 - if (ret != -ERESTARTSYS) 747 - DRM_ERROR("Out of graphics memory for context" 748 - " creation.\n"); 749 - goto out_ret; 750 - } 751 - 752 746 ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); 753 747 if (unlikely(!ctx)) { 754 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 755 - vmw_user_context_size); 756 748 ret = -ENOMEM; 757 749 goto out_ret; 758 750 }
-18
drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
··· 546 546 (void) vmw_cotable_destroy(res); 547 547 } 548 548 549 - static size_t cotable_acc_size; 550 - 551 549 /** 552 550 * vmw_cotable_free - Cotable resource destructor 553 551 * ··· 553 555 */ 554 556 static void vmw_cotable_free(struct vmw_resource *res) 555 557 { 556 - struct vmw_private *dev_priv = res->dev_priv; 557 - 558 558 kfree(res); 559 - ttm_mem_global_free(vmw_mem_glob(dev_priv), cotable_acc_size); 560 559 } 561 560 562 561 /** ··· 569 574 u32 type) 570 575 { 571 576 struct vmw_cotable *vcotbl; 572 - struct ttm_operation_ctx ttm_opt_ctx = { 573 - .interruptible = true, 574 - .no_wait_gpu = false 575 - }; 576 577 int ret; 577 578 u32 num_entries; 578 - 579 - if (unlikely(cotable_acc_size == 0)) 580 - cotable_acc_size = ttm_round_pot(sizeof(struct vmw_cotable)); 581 - 582 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 583 - cotable_acc_size, &ttm_opt_ctx); 584 - if (unlikely(ret)) 585 - return ERR_PTR(ret); 586 579 587 580 vcotbl = kzalloc(sizeof(*vcotbl), GFP_KERNEL); 588 581 if (unlikely(!vcotbl)) { ··· 605 622 out_no_init: 606 623 kfree(vcotbl); 607 624 out_no_alloc: 608 - ttm_mem_global_free(vmw_mem_glob(dev_priv), cotable_acc_size); 609 625 return ERR_PTR(ret); 610 626 } 611 627
+2 -15
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
··· 50 50 #define VMW_MIN_INITIAL_WIDTH 800 51 51 #define VMW_MIN_INITIAL_HEIGHT 600 52 52 53 - #define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) 54 - 55 - 56 53 /* 57 54 * Fully encoded drm commands. Might move to vmw_drm.h 58 55 */ ··· 983 986 goto out_err0; 984 987 } 985 988 986 - dev_priv->tdev = ttm_object_device_init(&ttm_mem_glob, 12, 987 - &vmw_prime_dmabuf_ops); 989 + dev_priv->tdev = ttm_object_device_init(12, &vmw_prime_dmabuf_ops); 988 990 989 991 if (unlikely(dev_priv->tdev == NULL)) { 990 992 drm_err(&dev_priv->drm, ··· 1078 1082 if (vmw_devcap_get(dev_priv, SVGA3D_DEVCAP_DXCONTEXT)) 1079 1083 dev_priv->sm_type = VMW_SM_4; 1080 1084 } 1081 - 1082 - vmw_validation_mem_init_ttm(dev_priv, VMWGFX_VALIDATION_MEM_GRAN); 1083 1085 1084 1086 /* SVGA_CAP2_DX2 (DefineGBSurface_v3) is needed for SM4_1 support */ 1085 1087 if (has_sm4_context(dev_priv) && ··· 1391 1397 { 1392 1398 struct drm_device *dev = pci_get_drvdata(pdev); 1393 1399 1394 - ttm_mem_global_release(&ttm_mem_glob); 1395 1400 drm_dev_unregister(dev); 1396 1401 vmw_driver_unload(dev); 1397 1402 } ··· 1634 1641 1635 1642 pci_set_drvdata(pdev, &vmw->drm); 1636 1643 1637 - ret = ttm_mem_global_init(&ttm_mem_glob, &pdev->dev); 1638 - if (ret) 1639 - goto out_error; 1640 - 1641 1644 ret = vmw_driver_load(vmw, ent->device); 1642 1645 if (ret) 1643 - goto out_release; 1646 + goto out_error; 1644 1647 1645 1648 ret = drm_dev_register(&vmw->drm, 0); 1646 1649 if (ret) ··· 1645 1656 return 0; 1646 1657 out_unload: 1647 1658 vmw_driver_unload(&vmw->drm); 1648 - out_release: 1649 - ttm_mem_global_release(&ttm_mem_glob); 1650 1659 out_error: 1651 1660 return ret; 1652 1661 }
-25
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
··· 628 628 struct vmw_cmdbuf_man *cman; 629 629 DECLARE_BITMAP(irqthread_pending, VMW_IRQTHREAD_MAX); 630 630 631 - /* Validation memory reservation */ 632 - struct vmw_validation_mem vvm; 633 - 634 631 uint32 *devcaps; 635 632 636 633 /* ··· 1025 1028 1026 1029 extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); 1027 1030 1028 - extern void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv, 1029 - size_t gran); 1030 - 1031 1031 /** 1032 1032 * TTM buffer object driver - vmwgfx_ttm_buffer.c 1033 1033 */ ··· 1322 1328 struct drm_file *file_priv); 1323 1329 extern int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, 1324 1330 struct drm_file *file_priv); 1325 - int vmw_surface_gb_priv_define(struct drm_device *dev, 1326 - uint32_t user_accounting_size, 1327 - SVGA3dSurfaceAllFlags svga3d_flags, 1328 - SVGA3dSurfaceFormat format, 1329 - bool for_scanout, 1330 - uint32_t num_mip_levels, 1331 - uint32_t multisample_count, 1332 - uint32_t array_size, 1333 - struct drm_vmw_size size, 1334 - SVGA3dMSPattern multisample_pattern, 1335 - SVGA3dMSQualityLevel quality_level, 1336 - struct vmw_surface **srf_out); 1337 1331 extern int vmw_gb_surface_define_ext_ioctl(struct drm_device *dev, 1338 1332 void *data, 1339 1333 struct drm_file *file_priv); ··· 1330 1348 struct drm_file *file_priv); 1331 1349 1332 1350 int vmw_gb_surface_define(struct vmw_private *dev_priv, 1333 - uint32_t user_accounting_size, 1334 1351 const struct vmw_surface_metadata *req, 1335 1352 struct vmw_surface **srf_out); 1336 1353 ··· 1390 1409 extern struct vmw_cmdbuf_res_manager * 1391 1410 vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv); 1392 1411 extern void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man); 1393 - extern size_t vmw_cmdbuf_res_man_size(void); 1394 1412 extern struct vmw_resource * 1395 1413 vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man, 1396 1414 enum vmw_cmdbuf_res_type res_type, ··· 1584 1604 { 1585 1605 ttm_bo_get(&buf->base); 1586 1606 return buf; 1587 - } 1588 - 1589 - static inline struct ttm_mem_global *vmw_mem_glob(struct vmw_private *dev_priv) 1590 - { 1591 - return &ttm_mem_glob; 1592 1607 } 1593 1608 1594 1609 static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv)
-2
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
··· 4054 4054 struct sync_file *sync_file = NULL; 4055 4055 DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1); 4056 4056 4057 - vmw_validation_set_val_mem(&val_ctx, &dev_priv->vvm); 4058 - 4059 4057 if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { 4060 4058 out_fence_fd = get_unused_fd_flags(O_CLOEXEC); 4061 4059 if (out_fence_fd < 0) {
-30
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
··· 37 37 spinlock_t lock; 38 38 struct list_head fence_list; 39 39 struct work_struct work; 40 - u32 user_fence_size; 41 - u32 fence_size; 42 - u32 event_fence_action_size; 43 40 bool fifo_down; 44 41 struct list_head cleanup_list; 45 42 uint32_t pending_actions[VMW_ACTION_MAX]; ··· 301 304 INIT_LIST_HEAD(&fman->cleanup_list); 302 305 INIT_WORK(&fman->work, &vmw_fence_work_func); 303 306 fman->fifo_down = true; 304 - fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)) + 305 - TTM_OBJ_EXTRA_SIZE; 306 - fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj)); 307 - fman->event_fence_action_size = 308 - ttm_round_pot(sizeof(struct vmw_event_fence_action)); 309 307 mutex_init(&fman->goal_irq_mutex); 310 308 fman->ctx = dma_fence_context_alloc(1); 311 309 ··· 552 560 { 553 561 struct vmw_user_fence *ufence = 554 562 container_of(fence, struct vmw_user_fence, fence); 555 - struct vmw_fence_manager *fman = fman_from_fence(fence); 556 563 557 564 ttm_base_object_kfree(ufence, base); 558 - /* 559 - * Free kernel space accounting. 560 - */ 561 - ttm_mem_global_free(vmw_mem_glob(fman->dev_priv), 562 - fman->user_fence_size); 563 565 } 564 566 565 567 static void vmw_user_fence_base_release(struct ttm_base_object **p_base) ··· 576 590 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 577 591 struct vmw_user_fence *ufence; 578 592 struct vmw_fence_obj *tmp; 579 - struct ttm_mem_global *mem_glob = vmw_mem_glob(fman->dev_priv); 580 - struct ttm_operation_ctx ctx = { 581 - .interruptible = false, 582 - .no_wait_gpu = false 583 - }; 584 593 int ret; 585 - 586 - /* 587 - * Kernel memory space accounting, since this object may 588 - * be created by a user-space request. 589 - */ 590 - 591 - ret = ttm_mem_global_alloc(mem_glob, fman->user_fence_size, 592 - &ctx); 593 - if (unlikely(ret != 0)) 594 - return ret; 595 594 596 595 ufence = kzalloc(sizeof(*ufence), GFP_KERNEL); 597 596 if (unlikely(!ufence)) { ··· 617 646 tmp = &ufence->fence; 618 647 vmw_fence_obj_unreference(&tmp); 619 648 out_no_object: 620 - ttm_mem_global_free(mem_glob, fman->user_fence_size); 621 649 return ret; 622 650 } 623 651
+1 -1
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 1188 1188 metadata.base_size.depth = 1; 1189 1189 metadata.scanout = true; 1190 1190 1191 - ret = vmw_gb_surface_define(vmw_priv(dev), 0, &metadata, srf_out); 1191 + ret = vmw_gb_surface_define(vmw_priv(dev), &metadata, srf_out); 1192 1192 if (ret) { 1193 1193 DRM_ERROR("Failed to allocate proxy content buffer\n"); 1194 1194 return ret;
+3 -4
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
··· 413 413 * @mob: Pointer to the mob the pagetable of which we want to 414 414 * populate. 415 415 * 416 - * This function allocates memory to be used for the pagetable, and 417 - * adjusts TTM memory accounting accordingly. Returns ENOMEM if 418 - * memory resources aren't sufficient and may cause TTM buffer objects 419 - * to be swapped out by using the TTM memory accounting function. 416 + * This function allocates memory to be used for the pagetable. 417 + * Returns ENOMEM if memory resources aren't sufficient and may 418 + * cause TTM buffer objects to be swapped out. 420 419 */ 421 420 static int vmw_mob_pt_populate(struct vmw_private *dev_priv, 422 421 struct vmw_mob *mob)
+1 -19
drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
··· 57 57 * @ref_count: Reference count for this structure 58 58 * @bitmap_size: The size of the bitmap in bits. Typically equal to the 59 59 * nuber of pages in the bo. 60 - * @size: The accounting size for this struct. 61 60 * @bitmap: A bitmap where each bit represents a page. A set bit means a 62 61 * dirty page. 63 62 */ ··· 67 68 unsigned int change_count; 68 69 unsigned int ref_count; 69 70 unsigned long bitmap_size; 70 - size_t size; 71 71 unsigned long bitmap[]; 72 72 }; 73 73 ··· 231 233 { 232 234 struct vmw_bo_dirty *dirty = vbo->dirty; 233 235 pgoff_t num_pages = vbo->base.resource->num_pages; 234 - size_t size, acc_size; 236 + size_t size; 235 237 int ret; 236 - static struct ttm_operation_ctx ctx = { 237 - .interruptible = false, 238 - .no_wait_gpu = false 239 - }; 240 238 241 239 if (dirty) { 242 240 dirty->ref_count++; ··· 240 246 } 241 247 242 248 size = sizeof(*dirty) + BITS_TO_LONGS(num_pages) * sizeof(long); 243 - acc_size = ttm_round_pot(size); 244 - ret = ttm_mem_global_alloc(&ttm_mem_glob, acc_size, &ctx); 245 - if (ret) { 246 - VMW_DEBUG_USER("Out of graphics memory for buffer object " 247 - "dirty tracker.\n"); 248 - return ret; 249 - } 250 249 dirty = kvzalloc(size, GFP_KERNEL); 251 250 if (!dirty) { 252 251 ret = -ENOMEM; 253 252 goto out_no_dirty; 254 253 } 255 254 256 - dirty->size = acc_size; 257 255 dirty->bitmap_size = num_pages; 258 256 dirty->start = dirty->bitmap_size; 259 257 dirty->end = 0; ··· 271 285 return 0; 272 286 273 287 out_no_dirty: 274 - ttm_mem_global_free(&ttm_mem_glob, acc_size); 275 288 return ret; 276 289 } 277 290 ··· 289 304 struct vmw_bo_dirty *dirty = vbo->dirty; 290 305 291 306 if (dirty && --dirty->ref_count == 0) { 292 - size_t acc_size = dirty->size; 293 - 294 307 kvfree(dirty); 295 - ttm_mem_global_free(&ttm_mem_glob, acc_size); 296 308 vbo->dirty = NULL; 297 309 } 298 310 }
+1 -73
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
··· 53 53 struct list_head cotable_head; 54 54 }; 55 55 56 - static uint64_t vmw_user_shader_size; 57 - static uint64_t vmw_shader_size; 58 - static size_t vmw_shader_dx_size; 59 - 60 56 static void vmw_user_shader_free(struct vmw_resource *res); 61 57 static struct vmw_resource * 62 58 vmw_user_shader_base_to_res(struct ttm_base_object *base); ··· 75 79 enum vmw_cmdbuf_res_state state); 76 80 static bool vmw_shader_id_ok(u32 user_key, SVGA3dShaderType shader_type); 77 81 static u32 vmw_shader_key(u32 user_key, SVGA3dShaderType shader_type); 78 - static uint64_t vmw_user_shader_size; 79 82 80 83 static const struct vmw_user_resource_conv user_shader_conv = { 81 84 .object_type = VMW_RES_SHADER, ··· 558 563 * 559 564 * @res: The shader resource 560 565 * 561 - * Frees the DX shader resource and updates memory accounting. 566 + * Frees the DX shader resource. 562 567 */ 563 568 static void vmw_dx_shader_res_free(struct vmw_resource *res) 564 569 { 565 - struct vmw_private *dev_priv = res->dev_priv; 566 570 struct vmw_dx_shader *shader = vmw_res_to_dx_shader(res); 567 571 568 572 vmw_resource_unreference(&shader->cotable); 569 573 kfree(shader); 570 - ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size); 571 574 } 572 575 573 576 /** ··· 587 594 struct vmw_dx_shader *shader; 588 595 struct vmw_resource *res; 589 596 struct vmw_private *dev_priv = ctx->dev_priv; 590 - struct ttm_operation_ctx ttm_opt_ctx = { 591 - .interruptible = true, 592 - .no_wait_gpu = false 593 - }; 594 597 int ret; 595 - 596 - if (!vmw_shader_dx_size) 597 - vmw_shader_dx_size = ttm_round_pot(sizeof(*shader)); 598 598 599 599 if (!vmw_shader_id_ok(user_key, shader_type)) 600 600 return -EINVAL; 601 601 602 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), vmw_shader_dx_size, 603 - &ttm_opt_ctx); 604 - if (ret) { 605 - if (ret != -ERESTARTSYS) 606 - DRM_ERROR("Out of graphics memory for shader " 607 - "creation.\n"); 608 - return ret; 609 - } 610 - 611 602 shader = kmalloc(sizeof(*shader), GFP_KERNEL); 612 603 if (!shader) { 613 - ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_shader_dx_size); 614 604 return -ENOMEM; 615 605 } 616 606 ··· 645 669 { 646 670 struct vmw_user_shader *ushader = 647 671 container_of(res, struct vmw_user_shader, shader.res); 648 - struct vmw_private *dev_priv = res->dev_priv; 649 672 650 673 ttm_base_object_kfree(ushader, base); 651 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 652 - vmw_user_shader_size); 653 674 } 654 675 655 676 static void vmw_shader_free(struct vmw_resource *res) 656 677 { 657 678 struct vmw_shader *shader = vmw_res_to_shader(res); 658 - struct vmw_private *dev_priv = res->dev_priv; 659 679 660 680 kfree(shader); 661 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 662 - vmw_shader_size); 663 681 } 664 682 665 683 /* ··· 692 722 { 693 723 struct vmw_user_shader *ushader; 694 724 struct vmw_resource *res, *tmp; 695 - struct ttm_operation_ctx ctx = { 696 - .interruptible = true, 697 - .no_wait_gpu = false 698 - }; 699 725 int ret; 700 - 701 - if (unlikely(vmw_user_shader_size == 0)) 702 - vmw_user_shader_size = 703 - ttm_round_pot(sizeof(struct vmw_user_shader)) + 704 - VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE; 705 - 706 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 707 - vmw_user_shader_size, 708 - &ctx); 709 - if (unlikely(ret != 0)) { 710 - if (ret != -ERESTARTSYS) 711 - DRM_ERROR("Out of graphics memory for shader " 712 - "creation.\n"); 713 - goto out; 714 - } 715 726 716 727 ushader = kzalloc(sizeof(*ushader), GFP_KERNEL); 717 728 if (unlikely(!ushader)) { 718 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 719 - vmw_user_shader_size); 720 729 ret = -ENOMEM; 721 730 goto out; 722 731 } ··· 742 793 { 743 794 struct vmw_shader *shader; 744 795 struct vmw_resource *res; 745 - struct ttm_operation_ctx ctx = { 746 - .interruptible = true, 747 - .no_wait_gpu = false 748 - }; 749 796 int ret; 750 - 751 - if (unlikely(vmw_shader_size == 0)) 752 - vmw_shader_size = 753 - ttm_round_pot(sizeof(struct vmw_shader)) + 754 - VMW_IDA_ACC_SIZE; 755 - 756 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 757 - vmw_shader_size, 758 - &ctx); 759 - if (unlikely(ret != 0)) { 760 - if (ret != -ERESTARTSYS) 761 - DRM_ERROR("Out of graphics memory for shader " 762 - "creation.\n"); 763 - goto out_err; 764 - } 765 797 766 798 shader = kzalloc(sizeof(*shader), GFP_KERNEL); 767 799 if (unlikely(!shader)) { 768 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 769 - vmw_shader_size); 770 800 ret = -ENOMEM; 771 801 goto out_err; 772 802 }
+1 -26
drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c
··· 32 32 * struct vmw_user_simple_resource - User-space simple resource struct 33 33 * 34 34 * @base: The TTM base object implementing user-space visibility. 35 - * @account_size: How much memory was accounted for this object. 36 35 * @simple: The embedded struct vmw_simple_resource. 37 36 */ 38 37 struct vmw_user_simple_resource { 39 38 struct ttm_base_object base; 40 - size_t account_size; 41 39 struct vmw_simple_resource simple; 42 40 /* 43 41 * Nothing to be placed after @simple, since size of @simple is ··· 89 91 * 90 92 * @res: The struct vmw_resource member of the simple resource object. 91 93 * 92 - * Frees memory and memory accounting for the object. 94 + * Frees memory for the object. 93 95 */ 94 96 static void vmw_simple_resource_free(struct vmw_resource *res) 95 97 { 96 98 struct vmw_user_simple_resource *usimple = 97 99 container_of(res, struct vmw_user_simple_resource, 98 100 simple.res); 99 - struct vmw_private *dev_priv = res->dev_priv; 100 - size_t size = usimple->account_size; 101 101 102 102 ttm_base_object_kfree(usimple, base); 103 - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 104 103 } 105 104 106 105 /** ··· 144 149 struct vmw_resource *res; 145 150 struct vmw_resource *tmp; 146 151 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 147 - struct ttm_operation_ctx ctx = { 148 - .interruptible = true, 149 - .no_wait_gpu = false 150 - }; 151 152 size_t alloc_size; 152 - size_t account_size; 153 153 int ret; 154 154 155 155 alloc_size = offsetof(struct vmw_user_simple_resource, simple) + 156 156 func->size; 157 - account_size = ttm_round_pot(alloc_size) + VMW_IDA_ACC_SIZE + 158 - TTM_OBJ_EXTRA_SIZE; 159 - 160 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), account_size, 161 - &ctx); 162 - if (ret) { 163 - if (ret != -ERESTARTSYS) 164 - DRM_ERROR("Out of graphics memory for %s" 165 - " creation.\n", func->res_func.type_name); 166 - 167 - goto out_ret; 168 - } 169 157 170 158 usimple = kzalloc(alloc_size, GFP_KERNEL); 171 159 if (!usimple) { 172 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 173 - account_size); 174 160 ret = -ENOMEM; 175 161 goto out_ret; 176 162 } 177 163 178 164 usimple->simple.func = func; 179 - usimple->account_size = account_size; 180 165 res = &usimple->simple.res; 181 166 usimple->base.shareable = false; 182 167 usimple->base.tfile = NULL;
+1 -16
drivers/gpu/drm/vmwgfx/vmwgfx_so.c
··· 279 279 * 280 280 * @res: Pointer to a struct vmw_resource 281 281 * 282 - * Frees memory and memory accounting held by a struct vmw_view. 282 + * Frees memory held by the struct vmw_view. 283 283 */ 284 284 static void vmw_view_res_free(struct vmw_resource *res) 285 285 { 286 286 struct vmw_view *view = vmw_view(res); 287 - size_t size = offsetof(struct vmw_view, cmd) + view->cmd_size; 288 - struct vmw_private *dev_priv = res->dev_priv; 289 287 290 288 vmw_resource_unreference(&view->cotable); 291 289 vmw_resource_unreference(&view->srf); 292 290 kfree_rcu(view, rcu); 293 - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 294 291 } 295 292 296 293 /** ··· 324 327 struct vmw_private *dev_priv = ctx->dev_priv; 325 328 struct vmw_resource *res; 326 329 struct vmw_view *view; 327 - struct ttm_operation_ctx ttm_opt_ctx = { 328 - .interruptible = true, 329 - .no_wait_gpu = false 330 - }; 331 330 size_t size; 332 331 int ret; 333 332 ··· 340 347 341 348 size = offsetof(struct vmw_view, cmd) + cmd_size; 342 349 343 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ttm_opt_ctx); 344 - if (ret) { 345 - if (ret != -ERESTARTSYS) 346 - DRM_ERROR("Out of graphics memory for view creation\n"); 347 - return ret; 348 - } 349 - 350 350 view = kmalloc(size, GFP_KERNEL); 351 351 if (!view) { 352 - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 353 352 return -ENOMEM; 354 353 } 355 354
+1 -1
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
··· 1123 1123 } 1124 1124 1125 1125 if (!vps->surf) { 1126 - ret = vmw_gb_surface_define(dev_priv, 0, &metadata, 1126 + ret = vmw_gb_surface_define(dev_priv, &metadata, 1127 1127 &vps->surf); 1128 1128 if (ret != 0) { 1129 1129 DRM_ERROR("Couldn't allocate STDU surface.\n");
-21
drivers/gpu/drm/vmwgfx/vmwgfx_streamoutput.c
··· 60 60 static void vmw_dx_streamoutput_commit_notify(struct vmw_resource *res, 61 61 enum vmw_cmdbuf_res_state state); 62 62 63 - static size_t vmw_streamoutput_size; 64 - 65 63 static const struct vmw_res_func vmw_dx_streamoutput_func = { 66 64 .res_type = vmw_res_streamoutput, 67 65 .needs_backup = true, ··· 252 254 253 255 static void vmw_dx_streamoutput_res_free(struct vmw_resource *res) 254 256 { 255 - struct vmw_private *dev_priv = res->dev_priv; 256 257 struct vmw_dx_streamoutput *so = vmw_res_to_dx_streamoutput(res); 257 258 258 259 vmw_resource_unreference(&so->cotable); 259 260 kfree(so); 260 - ttm_mem_global_free(vmw_mem_glob(dev_priv), vmw_streamoutput_size); 261 261 } 262 262 263 263 static void vmw_dx_streamoutput_hw_destroy(struct vmw_resource *res) ··· 280 284 struct vmw_dx_streamoutput *so; 281 285 struct vmw_resource *res; 282 286 struct vmw_private *dev_priv = ctx->dev_priv; 283 - struct ttm_operation_ctx ttm_opt_ctx = { 284 - .interruptible = true, 285 - .no_wait_gpu = false 286 - }; 287 287 int ret; 288 - 289 - if (!vmw_streamoutput_size) 290 - vmw_streamoutput_size = ttm_round_pot(sizeof(*so)); 291 - 292 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 293 - vmw_streamoutput_size, &ttm_opt_ctx); 294 - if (ret) { 295 - if (ret != -ERESTARTSYS) 296 - DRM_ERROR("Out of graphics memory for streamout.\n"); 297 - return ret; 298 - } 299 288 300 289 so = kmalloc(sizeof(*so), GFP_KERNEL); 301 290 if (!so) { 302 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 303 - vmw_streamoutput_size); 304 291 return -ENOMEM; 305 292 } 306 293
+7 -83
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
··· 45 45 * @prime: The TTM prime object. 46 46 * @base: The TTM base object handling user-space visibility. 47 47 * @srf: The surface metadata. 48 - * @size: TTM accounting size for the surface. 49 48 * @master: Master of the creating client. Used for security check. 50 49 * @backup_base: The TTM base object of the backup buffer. 51 50 */ 52 51 struct vmw_user_surface { 53 52 struct ttm_prime_object prime; 54 53 struct vmw_surface srf; 55 - uint32_t size; 56 54 struct drm_master *master; 57 55 struct ttm_base_object *backup_base; 58 56 }; ··· 72 74 /** 73 75 * struct vmw_surface_dirty - Surface dirty-tracker 74 76 * @cache: Cached layout information of the surface. 75 - * @size: Accounting size for the struct vmw_surface_dirty. 76 77 * @num_subres: Number of subresources. 77 78 * @boxes: Array of SVGA3dBoxes indicating dirty regions. One per subresource. 78 79 */ 79 80 struct vmw_surface_dirty { 80 81 struct vmw_surface_cache cache; 81 - size_t size; 82 82 u32 num_subres; 83 83 SVGA3dBox boxes[]; 84 84 }; ··· 124 128 125 129 const struct vmw_user_resource_conv *user_surface_converter = 126 130 &user_surface_conv; 127 - 128 - 129 - static uint64_t vmw_user_surface_size; 130 131 131 132 static const struct vmw_res_func vmw_legacy_surface_func = { 132 133 .res_type = vmw_res_surface, ··· 352 359 * vmw_surface. 353 360 * 354 361 * Destroys a the device surface associated with a struct vmw_surface if 355 - * any, and adjusts accounting and resource count accordingly. 362 + * any, and adjusts resource count accordingly. 356 363 */ 357 364 static void vmw_hw_surface_destroy(struct vmw_resource *res) 358 365 { ··· 659 666 struct vmw_surface *srf = vmw_res_to_srf(res); 660 667 struct vmw_user_surface *user_srf = 661 668 container_of(srf, struct vmw_user_surface, srf); 662 - struct vmw_private *dev_priv = srf->res.dev_priv; 663 - uint32_t size = user_srf->size; 664 669 665 670 WARN_ON_ONCE(res->dirty); 666 671 if (user_srf->master) ··· 667 676 kfree(srf->metadata.sizes); 668 677 kfree(srf->snooper.image); 669 678 ttm_prime_object_kfree(user_srf, prime); 670 - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 671 679 } 672 680 673 681 /** ··· 730 740 struct drm_vmw_surface_create_req *req = &arg->req; 731 741 struct drm_vmw_surface_arg *rep = &arg->rep; 732 742 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 733 - struct ttm_operation_ctx ctx = { 734 - .interruptible = true, 735 - .no_wait_gpu = false 736 - }; 737 743 int ret; 738 744 int i, j; 739 745 uint32_t cur_bo_offset; 740 746 struct drm_vmw_size *cur_size; 741 747 struct vmw_surface_offset *cur_offset; 742 748 uint32_t num_sizes; 743 - uint32_t size; 744 749 const SVGA3dSurfaceDesc *desc; 745 - 746 - if (unlikely(vmw_user_surface_size == 0)) 747 - vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + 748 - VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE; 749 750 750 751 num_sizes = 0; 751 752 for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) { ··· 749 768 num_sizes == 0) 750 769 return -EINVAL; 751 770 752 - size = vmw_user_surface_size + 753 - ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) + 754 - ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset)); 755 - 756 771 desc = vmw_surface_get_desc(req->format); 757 772 if (unlikely(desc->blockDesc == SVGA3DBLOCKDESC_NONE)) { 758 773 VMW_DEBUG_USER("Invalid format %d for surface creation.\n", ··· 756 779 return -EINVAL; 757 780 } 758 781 759 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 760 - size, &ctx); 761 - if (unlikely(ret != 0)) { 762 - if (ret != -ERESTARTSYS) 763 - DRM_ERROR("Out of graphics memory for surface.\n"); 764 - goto out_unlock; 765 - } 766 - 767 782 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); 768 783 if (unlikely(!user_srf)) { 769 784 ret = -ENOMEM; 770 - goto out_no_user_srf; 785 + goto out_unlock; 771 786 } 772 787 773 788 srf = &user_srf->srf; ··· 774 805 memcpy(metadata->mip_levels, req->mip_levels, 775 806 sizeof(metadata->mip_levels)); 776 807 metadata->num_sizes = num_sizes; 777 - user_srf->size = size; 778 808 metadata->sizes = 779 809 memdup_user((struct drm_vmw_size __user *)(unsigned long) 780 810 req->size_addr, ··· 884 916 kfree(metadata->sizes); 885 917 out_no_sizes: 886 918 ttm_prime_object_kfree(user_srf, prime); 887 - out_no_user_srf: 888 - ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 889 919 out_unlock: 890 920 return ret; 891 921 } ··· 1425 1459 struct vmw_resource *res; 1426 1460 struct vmw_resource *tmp; 1427 1461 int ret = 0; 1428 - uint32_t size; 1429 1462 uint32_t backup_handle = 0; 1430 1463 SVGA3dSurfaceAllFlags svga3d_flags_64 = 1431 1464 SVGA3D_FLAGS_64(req->svga3d_flags_upper_32_bits, ··· 1471 1506 return -EINVAL; 1472 1507 } 1473 1508 1474 - if (unlikely(vmw_user_surface_size == 0)) 1475 - vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) + 1476 - VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE; 1477 - 1478 - size = vmw_user_surface_size; 1479 - 1480 1509 metadata.flags = svga3d_flags_64; 1481 1510 metadata.format = req->base.format; 1482 1511 metadata.mip_levels[0] = req->base.mip_levels; ··· 1485 1526 drm_vmw_surface_flag_scanout; 1486 1527 1487 1528 /* Define a surface based on the parameters. */ 1488 - ret = vmw_gb_surface_define(dev_priv, size, &metadata, &srf); 1529 + ret = vmw_gb_surface_define(dev_priv, &metadata, &srf); 1489 1530 if (ret != 0) { 1490 1531 VMW_DEBUG_USER("Failed to define surface.\n"); 1491 1532 return ret; ··· 1914 1955 u32 num_mip; 1915 1956 u32 num_subres; 1916 1957 u32 num_samples; 1917 - size_t dirty_size, acc_size; 1918 - static struct ttm_operation_ctx ctx = { 1919 - .interruptible = false, 1920 - .no_wait_gpu = false 1921 - }; 1958 + size_t dirty_size; 1922 1959 int ret; 1923 1960 1924 1961 if (metadata->array_size) ··· 1928 1973 1929 1974 num_subres = num_layers * num_mip; 1930 1975 dirty_size = struct_size(dirty, boxes, num_subres); 1931 - acc_size = ttm_round_pot(dirty_size); 1932 - ret = ttm_mem_global_alloc(vmw_mem_glob(res->dev_priv), 1933 - acc_size, &ctx); 1934 - if (ret) { 1935 - VMW_DEBUG_USER("Out of graphics memory for surface " 1936 - "dirty tracker.\n"); 1937 - return ret; 1938 - } 1939 1976 1940 1977 dirty = kvzalloc(dirty_size, GFP_KERNEL); 1941 1978 if (!dirty) { ··· 1937 1990 1938 1991 num_samples = max_t(u32, 1, metadata->multisample_count); 1939 1992 ret = vmw_surface_setup_cache(&metadata->base_size, metadata->format, 1940 - num_mip, num_layers, num_samples, 1941 - &dirty->cache); 1993 + num_mip, num_layers, num_samples, 1994 + &dirty->cache); 1942 1995 if (ret) 1943 1996 goto out_no_cache; 1944 1997 1945 1998 dirty->num_subres = num_subres; 1946 - dirty->size = acc_size; 1947 1999 res->dirty = (struct vmw_resource_dirty *) dirty; 1948 2000 1949 2001 return 0; ··· 1950 2004 out_no_cache: 1951 2005 kvfree(dirty); 1952 2006 out_no_dirty: 1953 - ttm_mem_global_free(vmw_mem_glob(res->dev_priv), acc_size); 1954 2007 return ret; 1955 2008 } 1956 2009 ··· 1960 2015 { 1961 2016 struct vmw_surface_dirty *dirty = 1962 2017 (struct vmw_surface_dirty *) res->dirty; 1963 - size_t acc_size = dirty->size; 1964 2018 1965 2019 kvfree(dirty); 1966 - ttm_mem_global_free(vmw_mem_glob(res->dev_priv), acc_size); 1967 2020 res->dirty = NULL; 1968 2021 } 1969 2022 ··· 1994 2051 * vmw_gb_surface_define - Define a private GB surface 1995 2052 * 1996 2053 * @dev_priv: Pointer to a device private. 1997 - * @user_accounting_size: Used to track user-space memory usage, set 1998 - * to 0 for kernel mode only memory 1999 2054 * @metadata: Metadata representing the surface to create. 2000 2055 * @user_srf_out: allocated user_srf. Set to NULL on failure. 2001 2056 * ··· 2003 2062 * it available to user mode drivers. 2004 2063 */ 2005 2064 int vmw_gb_surface_define(struct vmw_private *dev_priv, 2006 - uint32_t user_accounting_size, 2007 2065 const struct vmw_surface_metadata *req, 2008 2066 struct vmw_surface **srf_out) 2009 2067 { 2010 2068 struct vmw_surface_metadata *metadata; 2011 2069 struct vmw_user_surface *user_srf; 2012 2070 struct vmw_surface *srf; 2013 - struct ttm_operation_ctx ctx = { 2014 - .interruptible = true, 2015 - .no_wait_gpu = false 2016 - }; 2017 2071 u32 sample_count = 1; 2018 2072 u32 num_layers = 1; 2019 2073 int ret; ··· 2049 2113 if (req->sizes != NULL) 2050 2114 return -EINVAL; 2051 2115 2052 - ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv), 2053 - user_accounting_size, &ctx); 2054 - if (ret != 0) { 2055 - if (ret != -ERESTARTSYS) 2056 - DRM_ERROR("Out of graphics memory for surface.\n"); 2057 - goto out_unlock; 2058 - } 2059 - 2060 2116 user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); 2061 2117 if (unlikely(!user_srf)) { 2062 2118 ret = -ENOMEM; 2063 - goto out_no_user_srf; 2119 + goto out_unlock; 2064 2120 } 2065 2121 2066 2122 *srf_out = &user_srf->srf; 2067 - user_srf->size = user_accounting_size; 2068 2123 user_srf->prime.base.shareable = false; 2069 2124 user_srf->prime.base.tfile = NULL; 2070 2125 ··· 2105 2178 ret = vmw_surface_init(dev_priv, srf, vmw_user_surface_free); 2106 2179 2107 2180 return ret; 2108 - 2109 - out_no_user_srf: 2110 - ttm_mem_global_free(vmw_mem_glob(dev_priv), user_accounting_size); 2111 2181 2112 2182 out_unlock: 2113 2183 return ret;
-50
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
··· 175 175 int mem_type; 176 176 struct sg_table sgt; 177 177 struct vmw_sg_table vsgt; 178 - uint64_t sg_alloc_size; 179 178 bool mapped; 180 179 bool bound; 181 180 }; ··· 299 300 static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) 300 301 { 301 302 struct vmw_private *dev_priv = vmw_tt->dev_priv; 302 - struct ttm_mem_global *glob = vmw_mem_glob(dev_priv); 303 303 struct vmw_sg_table *vsgt = &vmw_tt->vsgt; 304 - struct ttm_operation_ctx ctx = { 305 - .interruptible = true, 306 - .no_wait_gpu = false 307 - }; 308 304 struct vmw_piter iter; 309 305 dma_addr_t old; 310 306 int ret = 0; 311 - static size_t sgl_size; 312 - static size_t sgt_size; 313 307 314 308 if (vmw_tt->mapped) 315 309 return 0; ··· 316 324 switch (dev_priv->map_mode) { 317 325 case vmw_dma_map_bind: 318 326 case vmw_dma_map_populate: 319 - if (unlikely(!sgl_size)) { 320 - sgl_size = ttm_round_pot(sizeof(struct scatterlist)); 321 - sgt_size = ttm_round_pot(sizeof(struct sg_table)); 322 - } 323 - vmw_tt->sg_alloc_size = sgt_size + sgl_size * vsgt->num_pages; 324 - ret = ttm_mem_global_alloc(glob, vmw_tt->sg_alloc_size, &ctx); 325 - if (unlikely(ret != 0)) 326 - return ret; 327 - 328 327 ret = sg_alloc_table_from_pages_segment( 329 328 &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0, 330 329 (unsigned long)vsgt->num_pages << PAGE_SHIFT, 331 330 dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL); 332 331 if (ret) 333 332 goto out_sg_alloc_fail; 334 - 335 - if (vsgt->num_pages > vmw_tt->sgt.orig_nents) { 336 - uint64_t over_alloc = 337 - sgl_size * (vsgt->num_pages - 338 - vmw_tt->sgt.orig_nents); 339 - 340 - ttm_mem_global_free(glob, over_alloc); 341 - vmw_tt->sg_alloc_size -= over_alloc; 342 - } 343 333 344 334 ret = vmw_ttm_map_for_dma(vmw_tt); 345 335 if (unlikely(ret != 0)) ··· 349 375 sg_free_table(vmw_tt->vsgt.sgt); 350 376 vmw_tt->vsgt.sgt = NULL; 351 377 out_sg_alloc_fail: 352 - ttm_mem_global_free(glob, vmw_tt->sg_alloc_size); 353 378 return ret; 354 379 } 355 380 ··· 374 401 vmw_ttm_unmap_from_dma(vmw_tt); 375 402 sg_free_table(vmw_tt->vsgt.sgt); 376 403 vmw_tt->vsgt.sgt = NULL; 377 - ttm_mem_global_free(vmw_mem_glob(dev_priv), 378 - vmw_tt->sg_alloc_size); 379 404 break; 380 405 default: 381 406 break; ··· 493 522 static int vmw_ttm_populate(struct ttm_device *bdev, 494 523 struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) 495 524 { 496 - unsigned int i; 497 525 int ret; 498 526 499 527 /* TODO: maybe completely drop this ? */ ··· 500 530 return 0; 501 531 502 532 ret = ttm_pool_alloc(&bdev->pool, ttm, ctx); 503 - if (ret) 504 - return ret; 505 533 506 - for (i = 0; i < ttm->num_pages; ++i) { 507 - ret = ttm_mem_global_alloc_page(&ttm_mem_glob, ttm->pages[i], 508 - PAGE_SIZE, ctx); 509 - if (ret) 510 - goto error; 511 - } 512 - return 0; 513 - 514 - error: 515 - while (i--) 516 - ttm_mem_global_free_page(&ttm_mem_glob, ttm->pages[i], 517 - PAGE_SIZE); 518 - ttm_pool_free(&bdev->pool, ttm); 519 534 return ret; 520 535 } 521 536 ··· 509 554 { 510 555 struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, 511 556 dma_ttm); 512 - unsigned int i; 513 557 514 558 vmw_ttm_unbind(bdev, ttm); 515 559 ··· 518 564 } 519 565 520 566 vmw_ttm_unmap_dma(vmw_tt); 521 - 522 - for (i = 0; i < ttm->num_pages; ++i) 523 - ttm_mem_global_free_page(&ttm_mem_glob, ttm->pages[i], 524 - PAGE_SIZE); 525 567 526 568 ttm_pool_free(&bdev->pool, ttm); 527 569 }
-35
drivers/gpu/drm/vmwgfx/vmwgfx_ttm_glue.c
··· 99 99 return ret; 100 100 } 101 101 102 - /* struct vmw_validation_mem callback */ 103 - static int vmw_vmt_reserve(struct vmw_validation_mem *m, size_t size) 104 - { 105 - static struct ttm_operation_ctx ctx = {.interruptible = false, 106 - .no_wait_gpu = false}; 107 - struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm); 108 - 109 - return ttm_mem_global_alloc(vmw_mem_glob(dev_priv), size, &ctx); 110 - } 111 - 112 - /* struct vmw_validation_mem callback */ 113 - static void vmw_vmt_unreserve(struct vmw_validation_mem *m, size_t size) 114 - { 115 - struct vmw_private *dev_priv = container_of(m, struct vmw_private, vvm); 116 - 117 - return ttm_mem_global_free(vmw_mem_glob(dev_priv), size); 118 - } 119 - 120 - /** 121 - * vmw_validation_mem_init_ttm - Interface the validation memory tracker 122 - * to ttm. 123 - * @dev_priv: Pointer to struct vmw_private. The reason we choose a vmw private 124 - * rather than a struct vmw_validation_mem is to make sure assumption in the 125 - * callbacks that struct vmw_private derives from struct vmw_validation_mem 126 - * holds true. 127 - * @gran: The recommended allocation granularity 128 - */ 129 - void vmw_validation_mem_init_ttm(struct vmw_private *dev_priv, size_t gran) 130 - { 131 - struct vmw_validation_mem *vvm = &dev_priv->vvm; 132 - 133 - vvm->reserve_mem = vmw_vmt_reserve; 134 - vvm->unreserve_mem = vmw_vmt_unreserve; 135 - vvm->gran = gran; 136 - }
+5 -8
drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
··· 29 29 #include "vmwgfx_validation.h" 30 30 #include "vmwgfx_drv.h" 31 31 32 + 33 + #define VMWGFX_VALIDATION_MEM_GRAN (16*PAGE_SIZE) 34 + 32 35 /** 33 36 * struct vmw_validation_bo_node - Buffer object validation metadata. 34 37 * @base: Metadata used for TTM reservation- and validation. ··· 116 113 struct page *page; 117 114 118 115 if (ctx->vm && ctx->vm_size_left < PAGE_SIZE) { 119 - int ret = ctx->vm->reserve_mem(ctx->vm, ctx->vm->gran); 120 - 121 - if (ret) 122 - return NULL; 123 - 124 - ctx->vm_size_left += ctx->vm->gran; 125 - ctx->total_mem += ctx->vm->gran; 116 + ctx->vm_size_left += VMWGFX_VALIDATION_MEM_GRAN; 117 + ctx->total_mem += VMWGFX_VALIDATION_MEM_GRAN; 126 118 } 127 119 128 120 page = alloc_page(GFP_KERNEL | __GFP_ZERO); ··· 157 159 158 160 ctx->mem_size_left = 0; 159 161 if (ctx->vm && ctx->total_mem) { 160 - ctx->vm->unreserve_mem(ctx->vm, ctx->total_mem); 161 162 ctx->total_mem = 0; 162 163 ctx->vm_size_left = 0; 163 164 }
-46
drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
··· 40 40 #define VMW_RES_DIRTY_CLEAR BIT(1) 41 41 42 42 /** 43 - * struct vmw_validation_mem - Custom interface to provide memory reservations 44 - * for the validation code. 45 - * @reserve_mem: Callback to reserve memory 46 - * @unreserve_mem: Callback to unreserve memory 47 - * @gran: Reservation granularity. Contains a hint how much memory should 48 - * be reserved in each call to @reserve_mem(). A slow implementation may want 49 - * reservation to be done in large batches. 50 - */ 51 - struct vmw_validation_mem { 52 - int (*reserve_mem)(struct vmw_validation_mem *m, size_t size); 53 - void (*unreserve_mem)(struct vmw_validation_mem *m, size_t size); 54 - size_t gran; 55 - }; 56 - 57 - /** 58 43 * struct vmw_validation_context - Per command submission validation context 59 44 * @ht: Hash table used to find resource- or buffer object duplicates 60 45 * @resource_list: List head for resource validation metadata ··· 115 130 } 116 131 117 132 /** 118 - * vmw_validation_set_val_mem - Register a validation mem object for 119 - * validation memory reservation 120 - * @ctx: The validation context 121 - * @vm: Pointer to a struct vmw_validation_mem 122 - * 123 - * Must be set before the first attempt to allocate validation memory. 124 - */ 125 - static inline void 126 - vmw_validation_set_val_mem(struct vmw_validation_context *ctx, 127 - struct vmw_validation_mem *vm) 128 - { 129 - ctx->vm = vm; 130 - } 131 - 132 - /** 133 133 * vmw_validation_set_ht - Register a hash table for duplicate finding 134 134 * @ctx: The validation context 135 135 * @ht: Pointer to a hash table to use for duplicate finding ··· 158 188 { 159 189 ttm_eu_fence_buffer_objects(&ctx->ticket, &ctx->bo_list, 160 190 (void *) fence); 161 - } 162 - 163 - /** 164 - * vmw_validation_context_init - Initialize a validation context 165 - * @ctx: Pointer to the validation context to initialize 166 - * 167 - * This function initializes a validation context with @merge_dups set 168 - * to false 169 - */ 170 - static inline void 171 - vmw_validation_context_init(struct vmw_validation_context *ctx) 172 - { 173 - memset(ctx, 0, sizeof(*ctx)); 174 - INIT_LIST_HEAD(&ctx->resource_list); 175 - INIT_LIST_HEAD(&ctx->resource_ctx_list); 176 - INIT_LIST_HEAD(&ctx->bo_list); 177 191 } 178 192 179 193 /**