ttm_bo.c 42.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/**************************************************************************
 *
 * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sub license, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 **************************************************************************/
/*
 * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
 */

J
Joe Perches 已提交
31 32
#define pr_fmt(fmt) "[TTM] " fmt

33 34 35
#include <drm/ttm/ttm_module.h>
#include <drm/ttm/ttm_bo_driver.h>
#include <drm/ttm/ttm_placement.h>
36 37 38 39 40 41
#include <linux/jiffies.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/module.h>
A
Arun Sharma 已提交
42
#include <linux/atomic.h>
43 44 45 46 47 48

#define TTM_ASSERT_LOCKED(param)
#define TTM_DEBUG(fmt, arg...)
#define TTM_BO_HASH_ORDER 13

static int ttm_bo_swapout(struct ttm_mem_shrink *shrink);
49 50 51 52 53 54 55
static void ttm_bo_global_kobj_release(struct kobject *kobj);

static struct attribute ttm_bo_count = {
	.name = "bo_count",
	.mode = S_IRUGO
};

56 57 58 59 60 61 62 63 64 65 66 67
static inline int ttm_mem_type_from_flags(uint32_t flags, uint32_t *mem_type)
{
	int i;

	for (i = 0; i <= TTM_PL_PRIV5; i++)
		if (flags & (1 << i)) {
			*mem_type = i;
			return 0;
		}
	return -EINVAL;
}

68
static void ttm_mem_type_debug(struct ttm_bo_device *bdev, int mem_type)
69
{
70 71
	struct ttm_mem_type_manager *man = &bdev->man[mem_type];

J
Joe Perches 已提交
72 73 74 75 76 77 78
	pr_err("    has_type: %d\n", man->has_type);
	pr_err("    use_type: %d\n", man->use_type);
	pr_err("    flags: 0x%08X\n", man->flags);
	pr_err("    gpu_offset: 0x%08lX\n", man->gpu_offset);
	pr_err("    size: %llu\n", man->size);
	pr_err("    available_caching: 0x%08X\n", man->available_caching);
	pr_err("    default_caching: 0x%08X\n", man->default_caching);
79 80
	if (mem_type != TTM_PL_SYSTEM)
		(*man->func->debug)(man, TTM_PFX);
81 82 83 84 85 86 87
}

static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo,
					struct ttm_placement *placement)
{
	int i, ret, mem_type;

J
Joe Perches 已提交
88 89 90
	pr_err("No space for %p (%lu pages, %luK, %luM)\n",
	       bo, bo->mem.num_pages, bo->mem.size >> 10,
	       bo->mem.size >> 20);
91 92 93 94 95
	for (i = 0; i < placement->num_placement; i++) {
		ret = ttm_mem_type_from_flags(placement->placement[i],
						&mem_type);
		if (ret)
			return;
J
Joe Perches 已提交
96 97
		pr_err("  placement[%d]=0x%08X (%d)\n",
		       i, placement->placement[i], mem_type);
98
		ttm_mem_type_debug(bo->bdev, mem_type);
99 100 101
	}
}

102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
static ssize_t ttm_bo_global_show(struct kobject *kobj,
				  struct attribute *attr,
				  char *buffer)
{
	struct ttm_bo_global *glob =
		container_of(kobj, struct ttm_bo_global, kobj);

	return snprintf(buffer, PAGE_SIZE, "%lu\n",
			(unsigned long) atomic_read(&glob->bo_count));
}

static struct attribute *ttm_bo_global_attrs[] = {
	&ttm_bo_count,
	NULL
};

118
static const struct sysfs_ops ttm_bo_global_ops = {
119 120 121 122 123 124 125 126 127
	.show = &ttm_bo_global_show
};

static struct kobj_type ttm_bo_glob_kobj_type  = {
	.release = &ttm_bo_global_kobj_release,
	.sysfs_ops = &ttm_bo_global_ops,
	.default_attrs = ttm_bo_global_attrs
};

128 129 130 131 132 133 134 135 136 137 138

static inline uint32_t ttm_bo_type_flags(unsigned type)
{
	return 1 << (type);
}

static void ttm_bo_release_list(struct kref *list_kref)
{
	struct ttm_buffer_object *bo =
	    container_of(list_kref, struct ttm_buffer_object, list_kref);
	struct ttm_bo_device *bdev = bo->bdev;
139
	size_t acc_size = bo->acc_size;
140 141 142 143 144 145 146 147 148 149 150

	BUG_ON(atomic_read(&bo->list_kref.refcount));
	BUG_ON(atomic_read(&bo->kref.refcount));
	BUG_ON(atomic_read(&bo->cpu_writers));
	BUG_ON(bo->sync_obj != NULL);
	BUG_ON(bo->mem.mm_node != NULL);
	BUG_ON(!list_empty(&bo->lru));
	BUG_ON(!list_empty(&bo->ddestroy));

	if (bo->ttm)
		ttm_tt_destroy(bo->ttm);
151
	atomic_dec(&bo->glob->bo_count);
152 153
	if (bo->resv == &bo->ttm_resv)
		reservation_object_fini(&bo->ttm_resv);
154
	mutex_destroy(&bo->wu_mutex);
155 156 157 158 159
	if (bo->destroy)
		bo->destroy(bo);
	else {
		kfree(bo);
	}
160
	ttm_mem_global_free(bdev->glob->mem_glob, acc_size);
161 162
}

163
void ttm_bo_add_to_lru(struct ttm_buffer_object *bo)
164 165 166 167
{
	struct ttm_bo_device *bdev = bo->bdev;
	struct ttm_mem_type_manager *man;

168
	lockdep_assert_held(&bo->resv->lock.base);
169 170 171 172 173 174 175 176 177 178

	if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) {

		BUG_ON(!list_empty(&bo->lru));

		man = &bdev->man[bo->mem.mem_type];
		list_add_tail(&bo->lru, &man->lru);
		kref_get(&bo->list_kref);

		if (bo->ttm != NULL) {
179
			list_add_tail(&bo->swap, &bo->glob->swap_lru);
180 181 182 183
			kref_get(&bo->list_kref);
		}
	}
}
184
EXPORT_SYMBOL(ttm_bo_add_to_lru);
185

186
int ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
{
	int put_count = 0;

	if (!list_empty(&bo->swap)) {
		list_del_init(&bo->swap);
		++put_count;
	}
	if (!list_empty(&bo->lru)) {
		list_del_init(&bo->lru);
		++put_count;
	}

	/*
	 * TODO: Add a driver hook to delete from
	 * driver-specific LRU's here.
	 */

	return put_count;
}

static void ttm_bo_ref_bug(struct kref *list_kref)
{
	BUG();
}

212 213 214
void ttm_bo_list_ref_sub(struct ttm_buffer_object *bo, int count,
			 bool never_free)
{
215 216
	kref_sub(&bo->list_kref, count,
		 (never_free) ? ttm_bo_ref_bug : ttm_bo_release_list);
217 218
}

219
void ttm_bo_del_sub_from_lru(struct ttm_buffer_object *bo)
220
{
221
	int put_count;
222

223 224 225 226
	spin_lock(&bo->glob->lru_lock);
	put_count = ttm_bo_del_from_lru(bo);
	spin_unlock(&bo->glob->lru_lock);
	ttm_bo_list_ref_sub(bo, put_count, true);
227
}
228
EXPORT_SYMBOL(ttm_bo_del_sub_from_lru);
229

230 231 232 233 234 235
/*
 * Call bo->mutex locked.
 */
static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc)
{
	struct ttm_bo_device *bdev = bo->bdev;
236
	struct ttm_bo_global *glob = bo->glob;
237 238 239 240 241 242
	int ret = 0;
	uint32_t page_flags = 0;

	TTM_ASSERT_LOCKED(&bo->mutex);
	bo->ttm = NULL;

D
Dave Airlie 已提交
243 244 245
	if (bdev->need_dma32)
		page_flags |= TTM_PAGE_FLAG_DMA32;

246 247 248 249 250
	switch (bo->type) {
	case ttm_bo_type_device:
		if (zero_alloc)
			page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC;
	case ttm_bo_type_kernel:
251 252
		bo->ttm = bdev->driver->ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
						      page_flags, glob->dummy_read_page);
253 254 255
		if (unlikely(bo->ttm == NULL))
			ret = -ENOMEM;
		break;
256 257 258 259 260 261 262 263 264 265
	case ttm_bo_type_sg:
		bo->ttm = bdev->driver->ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT,
						      page_flags | TTM_PAGE_FLAG_SG,
						      glob->dummy_read_page);
		if (unlikely(bo->ttm == NULL)) {
			ret = -ENOMEM;
			break;
		}
		bo->ttm->sg = bo->sg;
		break;
266
	default:
J
Joe Perches 已提交
267
		pr_err("Illegal buffer object type\n");
268 269 270 271 272 273 274 275 276
		ret = -EINVAL;
		break;
	}

	return ret;
}

static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
				  struct ttm_mem_reg *mem,
277
				  bool evict, bool interruptible,
278
				  bool no_wait_gpu)
279 280 281 282 283 284 285 286 287
{
	struct ttm_bo_device *bdev = bo->bdev;
	bool old_is_pci = ttm_mem_reg_is_pci(bdev, &bo->mem);
	bool new_is_pci = ttm_mem_reg_is_pci(bdev, mem);
	struct ttm_mem_type_manager *old_man = &bdev->man[bo->mem.mem_type];
	struct ttm_mem_type_manager *new_man = &bdev->man[mem->mem_type];
	int ret = 0;

	if (old_is_pci || new_is_pci ||
288 289 290 291 292 293 294
	    ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) {
		ret = ttm_mem_io_lock(old_man, true);
		if (unlikely(ret != 0))
			goto out_err;
		ttm_bo_unmap_virtual_locked(bo);
		ttm_mem_io_unlock(old_man);
	}
295 296 297 298 299

	/*
	 * Create and bind a ttm if required.
	 */

300 301
	if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
		if (bo->ttm == NULL) {
302 303
			bool zero = !(old_man->flags & TTM_MEMTYPE_FLAG_FIXED);
			ret = ttm_bo_add_ttm(bo, zero);
304 305 306
			if (ret)
				goto out_err;
		}
307 308 309

		ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
		if (ret)
310
			goto out_err;
311 312 313 314 315 316 317 318

		if (mem->mem_type != TTM_PL_SYSTEM) {
			ret = ttm_tt_bind(bo->ttm, mem);
			if (ret)
				goto out_err;
		}

		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
319 320
			if (bdev->driver->move_notify)
				bdev->driver->move_notify(bo, mem);
321
			bo->mem = *mem;
322 323 324 325 326
			mem->mm_node = NULL;
			goto moved;
		}
	}

327 328 329
	if (bdev->driver->move_notify)
		bdev->driver->move_notify(bo, mem);

330 331
	if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
	    !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED))
332
		ret = ttm_bo_move_ttm(bo, evict, no_wait_gpu, mem);
333 334
	else if (bdev->driver->move)
		ret = bdev->driver->move(bo, evict, interruptible,
335
					 no_wait_gpu, mem);
336
	else
337
		ret = ttm_bo_move_memcpy(bo, evict, no_wait_gpu, mem);
338

339 340 341 342 343 344 345
	if (ret) {
		if (bdev->driver->move_notify) {
			struct ttm_mem_reg tmp_mem = *mem;
			*mem = bo->mem;
			bo->mem = tmp_mem;
			bdev->driver->move_notify(bo, mem);
			bo->mem = *mem;
346
			*mem = tmp_mem;
347
		}
348

349 350
		goto out_err;
	}
351

352 353 354 355
moved:
	if (bo->evicted) {
		ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement);
		if (ret)
J
Joe Perches 已提交
356
			pr_err("Can not flush read caches\n");
357 358 359 360
		bo->evicted = false;
	}

	if (bo->mem.mm_node) {
361
		bo->offset = (bo->mem.start << PAGE_SHIFT) +
362 363
		    bdev->man[bo->mem.mem_type].gpu_offset;
		bo->cur_placement = bo->mem.placement;
364 365
	} else
		bo->offset = 0;
366 367 368 369 370 371 372 373 374 375 376 377 378 379

	return 0;

out_err:
	new_man = &bdev->man[bo->mem.mem_type];
	if ((new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm) {
		ttm_tt_unbind(bo->ttm);
		ttm_tt_destroy(bo->ttm);
		bo->ttm = NULL;
	}

	return ret;
}

380
/**
381
 * Call bo::reserved.
382
 * Will release GPU memory type usage on destruction.
383 384 385
 * This is the place to put in driver specific hooks to release
 * driver private resources.
 * Will release the bo::reserved lock.
386 387 388 389
 */

static void ttm_bo_cleanup_memtype_use(struct ttm_buffer_object *bo)
{
390 391 392
	if (bo->bdev->driver->move_notify)
		bo->bdev->driver->move_notify(bo, NULL);

393 394 395 396 397
	if (bo->ttm) {
		ttm_tt_unbind(bo->ttm);
		ttm_tt_destroy(bo->ttm);
		bo->ttm = NULL;
	}
398
	ttm_bo_mem_put(bo, &bo->mem);
399

400
	ww_mutex_unlock (&bo->resv->lock);
401 402
}

403
static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo)
404 405
{
	struct ttm_bo_device *bdev = bo->bdev;
406
	struct ttm_bo_global *glob = bo->glob;
407
	struct ttm_bo_driver *driver = bdev->driver;
408
	void *sync_obj = NULL;
409
	int put_count;
410 411
	int ret;

412
	spin_lock(&glob->lru_lock);
413
	ret = ttm_bo_reserve_nolru(bo, false, true, false, 0);
414

415
	spin_lock(&bdev->fence_lock);
416
	(void) ttm_bo_wait(bo, false, false, true);
417
	if (!ret && !bo->sync_obj) {
418
		spin_unlock(&bdev->fence_lock);
419
		put_count = ttm_bo_del_from_lru(bo);
420

421
		spin_unlock(&glob->lru_lock);
422
		ttm_bo_cleanup_memtype_use(bo);
423

424
		ttm_bo_list_ref_sub(bo, put_count, true);
425

426
		return;
427
	}
428 429
	if (bo->sync_obj)
		sync_obj = driver->sync_obj_ref(bo->sync_obj);
430 431
	spin_unlock(&bdev->fence_lock);

432 433 434 435 436 437 438 439 440 441 442 443
	if (!ret) {

		/*
		 * Make NO_EVICT bos immediately available to
		 * shrinkers, now that they are queued for
		 * destruction.
		 */
		if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) {
			bo->mem.placement &= ~TTM_PL_FLAG_NO_EVICT;
			ttm_bo_add_to_lru(bo);
		}

444
		ww_mutex_unlock(&bo->resv->lock);
445
	}
446 447 448 449 450

	kref_get(&bo->list_kref);
	list_add_tail(&bo->ddestroy, &bdev->ddestroy);
	spin_unlock(&glob->lru_lock);

451
	if (sync_obj) {
452
		driver->sync_obj_flush(sync_obj);
453 454
		driver->sync_obj_unref(&sync_obj);
	}
455 456 457 458 459
	schedule_delayed_work(&bdev->wq,
			      ((HZ / 100) < 1) ? 1 : HZ / 100);
}

/**
460
 * function ttm_bo_cleanup_refs_and_unlock
461 462 463
 * If bo idle, remove from delayed- and lru lists, and unref.
 * If not idle, do nothing.
 *
464 465 466
 * Must be called with lru_lock and reservation held, this function
 * will drop both before returning.
 *
467 468 469 470
 * @interruptible         Any sleeps should occur interruptibly.
 * @no_wait_gpu           Never wait for gpu. Return -EBUSY instead.
 */

471 472 473
static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo,
					  bool interruptible,
					  bool no_wait_gpu)
474
{
475
	struct ttm_bo_device *bdev = bo->bdev;
476
	struct ttm_bo_driver *driver = bdev->driver;
477 478
	struct ttm_bo_global *glob = bo->glob;
	int put_count;
479
	int ret;
480

481
	spin_lock(&bdev->fence_lock);
482
	ret = ttm_bo_wait(bo, false, false, true);
483

484 485
	if (ret && !no_wait_gpu) {
		void *sync_obj;
486

487 488 489 490 491
		/*
		 * Take a reference to the fence and unreserve,
		 * at this point the buffer should be dead, so
		 * no new sync objects can be attached.
		 */
492
		sync_obj = driver->sync_obj_ref(bo->sync_obj);
493
		spin_unlock(&bdev->fence_lock);
494

495
		ww_mutex_unlock(&bo->resv->lock);
496 497
		spin_unlock(&glob->lru_lock);

498 499 500
		ret = driver->sync_obj_wait(sync_obj, false, interruptible);
		driver->sync_obj_unref(&sync_obj);
		if (ret)
501 502
			return ret;

503 504 505 506 507 508 509 510 511 512
		/*
		 * remove sync_obj with ttm_bo_wait, the wait should be
		 * finished, and no new wait object should have been added.
		 */
		spin_lock(&bdev->fence_lock);
		ret = ttm_bo_wait(bo, false, false, true);
		WARN_ON(ret);
		spin_unlock(&bdev->fence_lock);
		if (ret)
			return ret;
513

514
		spin_lock(&glob->lru_lock);
515
		ret = ttm_bo_reserve_nolru(bo, false, true, false, 0);
516

517 518 519 520 521 522 523 524 525 526 527 528 529 530
		/*
		 * We raced, and lost, someone else holds the reservation now,
		 * and is probably busy in ttm_bo_cleanup_memtype_use.
		 *
		 * Even if it's not the case, because we finished waiting any
		 * delayed destruction would succeed, so just return success
		 * here.
		 */
		if (ret) {
			spin_unlock(&glob->lru_lock);
			return 0;
		}
	} else
		spin_unlock(&bdev->fence_lock);
531

532
	if (ret || unlikely(list_empty(&bo->ddestroy))) {
533
		ww_mutex_unlock(&bo->resv->lock);
534
		spin_unlock(&glob->lru_lock);
535
		return ret;
536 537
	}

538 539 540 541 542 543 544
	put_count = ttm_bo_del_from_lru(bo);
	list_del_init(&bo->ddestroy);
	++put_count;

	spin_unlock(&glob->lru_lock);
	ttm_bo_cleanup_memtype_use(bo);

545
	ttm_bo_list_ref_sub(bo, put_count, true);
546 547

	return 0;
548 549 550 551 552 553 554 555 556
}

/**
 * Traverse the delayed list, and call ttm_bo_cleanup_refs on all
 * encountered buffers.
 */

static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all)
{
557
	struct ttm_bo_global *glob = bdev->glob;
558 559
	struct ttm_buffer_object *entry = NULL;
	int ret = 0;
560

561
	spin_lock(&glob->lru_lock);
562 563 564 565 566 567 568 569 570 571 572 573 574
	if (list_empty(&bdev->ddestroy))
		goto out_unlock;

	entry = list_first_entry(&bdev->ddestroy,
		struct ttm_buffer_object, ddestroy);
	kref_get(&entry->list_kref);

	for (;;) {
		struct ttm_buffer_object *nentry = NULL;

		if (entry->ddestroy.next != &bdev->ddestroy) {
			nentry = list_first_entry(&entry->ddestroy,
				struct ttm_buffer_object, ddestroy);
575 576 577
			kref_get(&nentry->list_kref);
		}

578 579 580 581 582 583 584 585
		ret = ttm_bo_reserve_nolru(entry, false, true, false, 0);
		if (remove_all && ret) {
			spin_unlock(&glob->lru_lock);
			ret = ttm_bo_reserve_nolru(entry, false, false,
						   false, 0);
			spin_lock(&glob->lru_lock);
		}

586 587 588 589 590 591
		if (!ret)
			ret = ttm_bo_cleanup_refs_and_unlock(entry, false,
							     !remove_all);
		else
			spin_unlock(&glob->lru_lock);

592
		kref_put(&entry->list_kref, ttm_bo_release_list);
593 594 595 596
		entry = nentry;

		if (ret || !entry)
			goto out;
597

598
		spin_lock(&glob->lru_lock);
599
		if (list_empty(&entry->ddestroy))
600 601 602
			break;
	}

603 604 605 606 607
out_unlock:
	spin_unlock(&glob->lru_lock);
out:
	if (entry)
		kref_put(&entry->list_kref, ttm_bo_release_list);
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626
	return ret;
}

static void ttm_bo_delayed_workqueue(struct work_struct *work)
{
	struct ttm_bo_device *bdev =
	    container_of(work, struct ttm_bo_device, wq.work);

	if (ttm_bo_delayed_delete(bdev, false)) {
		schedule_delayed_work(&bdev->wq,
				      ((HZ / 100) < 1) ? 1 : HZ / 100);
	}
}

static void ttm_bo_release(struct kref *kref)
{
	struct ttm_buffer_object *bo =
	    container_of(kref, struct ttm_buffer_object, kref);
	struct ttm_bo_device *bdev = bo->bdev;
627
	struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];
628

629
	drm_vma_offset_remove(&bdev->vma_manager, &bo->vma_node);
630 631 632
	ttm_mem_io_lock(man, false);
	ttm_mem_io_free_vm(bo);
	ttm_mem_io_unlock(man);
633
	ttm_bo_cleanup_refs_or_queue(bo);
634 635 636 637 638 639 640 641 642 643 644 645
	kref_put(&bo->list_kref, ttm_bo_release_list);
}

void ttm_bo_unref(struct ttm_buffer_object **p_bo)
{
	struct ttm_buffer_object *bo = *p_bo;

	*p_bo = NULL;
	kref_put(&bo->kref, ttm_bo_release);
}
EXPORT_SYMBOL(ttm_bo_unref);

646 647 648 649 650 651 652 653 654 655 656 657 658 659
int ttm_bo_lock_delayed_workqueue(struct ttm_bo_device *bdev)
{
	return cancel_delayed_work_sync(&bdev->wq);
}
EXPORT_SYMBOL(ttm_bo_lock_delayed_workqueue);

void ttm_bo_unlock_delayed_workqueue(struct ttm_bo_device *bdev, int resched)
{
	if (resched)
		schedule_delayed_work(&bdev->wq,
				      ((HZ / 100) < 1) ? 1 : HZ / 100);
}
EXPORT_SYMBOL(ttm_bo_unlock_delayed_workqueue);

660
static int ttm_bo_evict(struct ttm_buffer_object *bo, bool interruptible,
661
			bool no_wait_gpu)
662 663 664
{
	struct ttm_bo_device *bdev = bo->bdev;
	struct ttm_mem_reg evict_mem;
665 666
	struct ttm_placement placement;
	int ret = 0;
667

668
	spin_lock(&bdev->fence_lock);
669
	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
670
	spin_unlock(&bdev->fence_lock);
671

672
	if (unlikely(ret != 0)) {
673
		if (ret != -ERESTARTSYS) {
J
Joe Perches 已提交
674
			pr_err("Failed to expire sync object before buffer eviction\n");
675
		}
676 677 678
		goto out;
	}

679
	lockdep_assert_held(&bo->resv->lock.base);
680 681 682

	evict_mem = bo->mem;
	evict_mem.mm_node = NULL;
683 684
	evict_mem.bus.io_reserved_vm = false;
	evict_mem.bus.io_reserved_count = 0;
685

686 687 688 689
	placement.fpfn = 0;
	placement.lpfn = 0;
	placement.num_placement = 0;
	placement.num_busy_placement = 0;
690 691
	bdev->driver->evict_flags(bo, &placement);
	ret = ttm_bo_mem_space(bo, &placement, &evict_mem, interruptible,
692
				no_wait_gpu);
693
	if (ret) {
694
		if (ret != -ERESTARTSYS) {
J
Joe Perches 已提交
695 696
			pr_err("Failed to find memory space for buffer 0x%p eviction\n",
			       bo);
697 698
			ttm_bo_mem_space_debug(bo, &placement);
		}
699 700 701 702
		goto out;
	}

	ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible,
703
				     no_wait_gpu);
704
	if (ret) {
705
		if (ret != -ERESTARTSYS)
J
Joe Perches 已提交
706
			pr_err("Buffer eviction failed\n");
707
		ttm_bo_mem_put(bo, &evict_mem);
708 709
		goto out;
	}
710 711 712 713 714 715 716
	bo->evicted = true;
out:
	return ret;
}

static int ttm_mem_evict_first(struct ttm_bo_device *bdev,
				uint32_t mem_type,
717
				bool interruptible,
718
				bool no_wait_gpu)
719 720 721 722
{
	struct ttm_bo_global *glob = bdev->glob;
	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
	struct ttm_buffer_object *bo;
723
	int ret = -EBUSY, put_count;
724

725
	spin_lock(&glob->lru_lock);
726
	list_for_each_entry(bo, &man->lru, lru) {
727
		ret = ttm_bo_reserve_nolru(bo, false, true, false, 0);
728 729 730 731 732
		if (!ret)
			break;
	}

	if (ret) {
733
		spin_unlock(&glob->lru_lock);
734
		return ret;
735 736
	}

737
	kref_get(&bo->list_kref);
738

739
	if (!list_empty(&bo->ddestroy)) {
740 741
		ret = ttm_bo_cleanup_refs_and_unlock(bo, interruptible,
						     no_wait_gpu);
742
		kref_put(&bo->list_kref, ttm_bo_release_list);
743
		return ret;
744 745
	}

746
	put_count = ttm_bo_del_from_lru(bo);
747
	spin_unlock(&glob->lru_lock);
748 749 750

	BUG_ON(ret != 0);

751
	ttm_bo_list_ref_sub(bo, put_count, true);
752

753
	ret = ttm_bo_evict(bo, interruptible, no_wait_gpu);
754
	ttm_bo_unreserve(bo);
755

756
	kref_put(&bo->list_kref, ttm_bo_release_list);
757 758 759
	return ret;
}

760 761
void ttm_bo_mem_put(struct ttm_buffer_object *bo, struct ttm_mem_reg *mem)
{
762
	struct ttm_mem_type_manager *man = &bo->bdev->man[mem->mem_type];
763

764 765
	if (mem->mm_node)
		(*man->func->put_node)(man, mem);
766 767 768
}
EXPORT_SYMBOL(ttm_bo_mem_put);

769 770 771 772
/**
 * Repeatedly evict memory from the LRU for @mem_type until we create enough
 * space, or we've evicted everything and there isn't enough space.
 */
773 774 775 776
static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo,
					uint32_t mem_type,
					struct ttm_placement *placement,
					struct ttm_mem_reg *mem,
777 778
					bool interruptible,
					bool no_wait_gpu)
779
{
780
	struct ttm_bo_device *bdev = bo->bdev;
781 782 783 784
	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
	int ret;

	do {
785
		ret = (*man->func->get_node)(man, bo, placement, mem);
786 787
		if (unlikely(ret != 0))
			return ret;
788
		if (mem->mm_node)
789
			break;
790 791
		ret = ttm_mem_evict_first(bdev, mem_type,
					  interruptible, no_wait_gpu);
792 793 794
		if (unlikely(ret != 0))
			return ret;
	} while (1);
795
	if (mem->mm_node == NULL)
796 797 798 799 800
		return -ENOMEM;
	mem->mem_type = mem_type;
	return 0;
}

801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
static uint32_t ttm_bo_select_caching(struct ttm_mem_type_manager *man,
				      uint32_t cur_placement,
				      uint32_t proposed_placement)
{
	uint32_t caching = proposed_placement & TTM_PL_MASK_CACHING;
	uint32_t result = proposed_placement & ~TTM_PL_MASK_CACHING;

	/**
	 * Keep current caching if possible.
	 */

	if ((cur_placement & caching) != 0)
		result |= (cur_placement & caching);
	else if ((man->default_caching & caching) != 0)
		result |= man->default_caching;
	else if ((TTM_PL_FLAG_CACHED & caching) != 0)
		result |= TTM_PL_FLAG_CACHED;
	else if ((TTM_PL_FLAG_WC & caching) != 0)
		result |= TTM_PL_FLAG_WC;
	else if ((TTM_PL_FLAG_UNCACHED & caching) != 0)
		result |= TTM_PL_FLAG_UNCACHED;

	return result;
}

826 827
static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man,
				 uint32_t mem_type,
828 829
				 uint32_t proposed_placement,
				 uint32_t *masked_placement)
830 831 832
{
	uint32_t cur_flags = ttm_bo_type_flags(mem_type);

833
	if ((cur_flags & proposed_placement & TTM_PL_MASK_MEM) == 0)
834 835
		return false;

836
	if ((proposed_placement & man->available_caching) == 0)
837 838
		return false;

839 840 841
	cur_flags |= (proposed_placement & man->available_caching);

	*masked_placement = cur_flags;
842 843 844 845 846 847 848 849 850 851 852 853
	return true;
}

/**
 * Creates space for memory region @mem according to its type.
 *
 * This function first searches for free space in compatible memory types in
 * the priority order defined by the driver.  If free space isn't found, then
 * ttm_bo_mem_force_space is attempted in priority order to evict and find
 * space.
 */
int ttm_bo_mem_space(struct ttm_buffer_object *bo,
854 855
			struct ttm_placement *placement,
			struct ttm_mem_reg *mem,
856
			bool interruptible,
857
			bool no_wait_gpu)
858 859 860 861 862 863 864
{
	struct ttm_bo_device *bdev = bo->bdev;
	struct ttm_mem_type_manager *man;
	uint32_t mem_type = TTM_PL_SYSTEM;
	uint32_t cur_flags = 0;
	bool type_found = false;
	bool type_ok = false;
865
	bool has_erestartsys = false;
866
	int i, ret;
867 868

	mem->mm_node = NULL;
869
	for (i = 0; i < placement->num_placement; ++i) {
870 871 872 873
		ret = ttm_mem_type_from_flags(placement->placement[i],
						&mem_type);
		if (ret)
			return ret;
874 875 876
		man = &bdev->man[mem_type];

		type_ok = ttm_bo_mt_compatible(man,
877 878 879
						mem_type,
						placement->placement[i],
						&cur_flags);
880 881 882 883

		if (!type_ok)
			continue;

884 885
		cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
						  cur_flags);
886 887 888 889 890 891
		/*
		 * Use the access and other non-mapping-related flag bits from
		 * the memory placement flags to the current flags
		 */
		ttm_flag_masked(&cur_flags, placement->placement[i],
				~TTM_PL_MASK_MEMTYPE);
892

893 894 895 896 897
		if (mem_type == TTM_PL_SYSTEM)
			break;

		if (man->has_type && man->use_type) {
			type_found = true;
898
			ret = (*man->func->get_node)(man, bo, placement, mem);
899 900
			if (unlikely(ret))
				return ret;
901
		}
902
		if (mem->mm_node)
903 904 905
			break;
	}

906
	if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || mem->mm_node) {
907 908 909 910 911 912 913 914
		mem->mem_type = mem_type;
		mem->placement = cur_flags;
		return 0;
	}

	if (!type_found)
		return -EINVAL;

915 916
	for (i = 0; i < placement->num_busy_placement; ++i) {
		ret = ttm_mem_type_from_flags(placement->busy_placement[i],
917 918 919
						&mem_type);
		if (ret)
			return ret;
920 921 922 923
		man = &bdev->man[mem_type];
		if (!man->has_type)
			continue;
		if (!ttm_bo_mt_compatible(man,
924
						mem_type,
925
						placement->busy_placement[i],
926
						&cur_flags))
927 928
			continue;

929 930
		cur_flags = ttm_bo_select_caching(man, bo->mem.placement,
						  cur_flags);
931 932 933 934
		/*
		 * Use the access and other non-mapping-related flag bits from
		 * the memory placement flags to the current flags
		 */
935
		ttm_flag_masked(&cur_flags, placement->busy_placement[i],
936
				~TTM_PL_MASK_MEMTYPE);
937

938 939 940 941 942 943 944 945

		if (mem_type == TTM_PL_SYSTEM) {
			mem->mem_type = mem_type;
			mem->placement = cur_flags;
			mem->mm_node = NULL;
			return 0;
		}

946
		ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem,
947
						interruptible, no_wait_gpu);
948 949 950 951
		if (ret == 0 && mem->mm_node) {
			mem->placement = cur_flags;
			return 0;
		}
952 953
		if (ret == -ERESTARTSYS)
			has_erestartsys = true;
954
	}
955
	ret = (has_erestartsys) ? -ERESTARTSYS : -ENOMEM;
956 957 958 959
	return ret;
}
EXPORT_SYMBOL(ttm_bo_mem_space);

960
static int ttm_bo_move_buffer(struct ttm_buffer_object *bo,
961
			struct ttm_placement *placement,
962
			bool interruptible,
963
			bool no_wait_gpu)
964 965 966
{
	int ret = 0;
	struct ttm_mem_reg mem;
967
	struct ttm_bo_device *bdev = bo->bdev;
968

969
	lockdep_assert_held(&bo->resv->lock.base);
970 971 972 973 974 975

	/*
	 * FIXME: It's possible to pipeline buffer moves.
	 * Have the driver move function wait for idle when necessary,
	 * instead of doing it here.
	 */
976
	spin_lock(&bdev->fence_lock);
977
	ret = ttm_bo_wait(bo, false, interruptible, no_wait_gpu);
978
	spin_unlock(&bdev->fence_lock);
979 980 981 982 983
	if (ret)
		return ret;
	mem.num_pages = bo->num_pages;
	mem.size = mem.num_pages << PAGE_SHIFT;
	mem.page_alignment = bo->mem.page_alignment;
984 985
	mem.bus.io_reserved_vm = false;
	mem.bus.io_reserved_count = 0;
986 987 988
	/*
	 * Determine where to move the buffer.
	 */
989 990
	ret = ttm_bo_mem_space(bo, placement, &mem,
			       interruptible, no_wait_gpu);
991 992
	if (ret)
		goto out_unlock;
993 994
	ret = ttm_bo_handle_move_mem(bo, &mem, false,
				     interruptible, no_wait_gpu);
995
out_unlock:
996 997
	if (ret && mem.mm_node)
		ttm_bo_mem_put(bo, &mem);
998 999 1000
	return ret;
}

1001 1002 1003
static bool ttm_bo_mem_compat(struct ttm_placement *placement,
			      struct ttm_mem_reg *mem,
			      uint32_t *new_flags)
1004
{
1005
	int i;
1006

1007 1008 1009
	if (mem->mm_node && placement->lpfn != 0 &&
	    (mem->start < placement->fpfn ||
	     mem->start + mem->num_pages > placement->lpfn))
1010
		return false;
1011 1012

	for (i = 0; i < placement->num_placement; i++) {
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
		*new_flags = placement->placement[i];
		if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
		    (*new_flags & mem->placement & TTM_PL_MASK_MEM))
			return true;
	}

	for (i = 0; i < placement->num_busy_placement; i++) {
		*new_flags = placement->busy_placement[i];
		if ((*new_flags & mem->placement & TTM_PL_MASK_CACHING) &&
		    (*new_flags & mem->placement & TTM_PL_MASK_MEM))
			return true;
1024
	}
1025 1026

	return false;
1027 1028
}

1029 1030
int ttm_bo_validate(struct ttm_buffer_object *bo,
			struct ttm_placement *placement,
1031
			bool interruptible,
1032
			bool no_wait_gpu)
1033 1034
{
	int ret;
1035
	uint32_t new_flags;
1036

1037
	lockdep_assert_held(&bo->resv->lock.base);
1038 1039 1040 1041 1042
	/* Check that range is valid */
	if (placement->lpfn || placement->fpfn)
		if (placement->fpfn > placement->lpfn ||
			(placement->lpfn - placement->fpfn) < bo->num_pages)
			return -EINVAL;
1043 1044 1045
	/*
	 * Check whether we need to move buffer.
	 */
1046
	if (!ttm_bo_mem_compat(placement, &bo->mem, &new_flags)) {
1047 1048
		ret = ttm_bo_move_buffer(bo, placement, interruptible,
					 no_wait_gpu);
1049
		if (ret)
1050
			return ret;
1051 1052 1053 1054 1055
	} else {
		/*
		 * Use the access and other non-mapping-related flag bits from
		 * the compatible memory placement flags to the active flags
		 */
1056
		ttm_flag_masked(&bo->mem.placement, new_flags,
1057
				~TTM_PL_MASK_MEMTYPE);
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
	}
	/*
	 * We might need to add a TTM.
	 */
	if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
		ret = ttm_bo_add_ttm(bo, true);
		if (ret)
			return ret;
	}
	return 0;
}
1069
EXPORT_SYMBOL(ttm_bo_validate);
1070

1071 1072
int ttm_bo_check_placement(struct ttm_buffer_object *bo,
				struct ttm_placement *placement)
1073
{
1074 1075
	BUG_ON((placement->fpfn || placement->lpfn) &&
	       (bo->mem.num_pages > (placement->lpfn - placement->fpfn)));
1076 1077 1078 1079

	return 0;
}

1080 1081 1082 1083 1084 1085 1086
int ttm_bo_init(struct ttm_bo_device *bdev,
		struct ttm_buffer_object *bo,
		unsigned long size,
		enum ttm_bo_type type,
		struct ttm_placement *placement,
		uint32_t page_alignment,
		bool interruptible,
J
Jan Engelhardt 已提交
1087
		struct file *persistent_swap_storage,
1088
		size_t acc_size,
1089
		struct sg_table *sg,
1090
		void (*destroy) (struct ttm_buffer_object *))
1091
{
1092
	int ret = 0;
1093
	unsigned long num_pages;
1094
	struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
1095
	bool locked;
1096 1097 1098

	ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
	if (ret) {
J
Joe Perches 已提交
1099
		pr_err("Out of kernel memory\n");
1100 1101 1102 1103 1104 1105
		if (destroy)
			(*destroy)(bo);
		else
			kfree(bo);
		return -ENOMEM;
	}
1106 1107 1108

	num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
	if (num_pages == 0) {
J
Joe Perches 已提交
1109
		pr_err("Illegal buffer object size\n");
1110 1111 1112 1113
		if (destroy)
			(*destroy)(bo);
		else
			kfree(bo);
1114
		ttm_mem_global_free(mem_glob, acc_size);
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124
		return -EINVAL;
	}
	bo->destroy = destroy;

	kref_init(&bo->kref);
	kref_init(&bo->list_kref);
	atomic_set(&bo->cpu_writers, 0);
	INIT_LIST_HEAD(&bo->lru);
	INIT_LIST_HEAD(&bo->ddestroy);
	INIT_LIST_HEAD(&bo->swap);
1125
	INIT_LIST_HEAD(&bo->io_reserve_lru);
1126
	mutex_init(&bo->wu_mutex);
1127
	bo->bdev = bdev;
1128
	bo->glob = bdev->glob;
1129 1130
	bo->type = type;
	bo->num_pages = num_pages;
1131
	bo->mem.size = num_pages << PAGE_SHIFT;
1132 1133 1134 1135
	bo->mem.mem_type = TTM_PL_SYSTEM;
	bo->mem.num_pages = bo->num_pages;
	bo->mem.mm_node = NULL;
	bo->mem.page_alignment = page_alignment;
1136 1137
	bo->mem.bus.io_reserved_vm = false;
	bo->mem.bus.io_reserved_count = 0;
1138 1139
	bo->priv_flags = 0;
	bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED);
J
Jan Engelhardt 已提交
1140
	bo->persistent_swap_storage = persistent_swap_storage;
1141
	bo->acc_size = acc_size;
1142
	bo->sg = sg;
1143 1144
	bo->resv = &bo->ttm_resv;
	reservation_object_init(bo->resv);
1145
	atomic_inc(&bo->glob->bo_count);
1146
	drm_vma_node_reset(&bo->vma_node);
1147

1148
	ret = ttm_bo_check_placement(bo, placement);
1149 1150 1151 1152 1153

	/*
	 * For ttm_bo_type_device buffers, allocate
	 * address space from the device.
	 */
1154 1155 1156
	if (likely(!ret) &&
	    (bo->type == ttm_bo_type_device ||
	     bo->type == ttm_bo_type_sg))
1157 1158
		ret = drm_vma_offset_add(&bdev->vma_manager, &bo->vma_node,
					 bo->mem.num_pages);
1159

1160 1161
	locked = ww_mutex_trylock(&bo->resv->lock);
	WARN_ON(!locked);
1162

1163 1164
	if (likely(!ret))
		ret = ttm_bo_validate(bo, placement, interruptible, false);
1165 1166

	ttm_bo_unreserve(bo);
1167 1168 1169

	if (unlikely(ret))
		ttm_bo_unref(&bo);
1170 1171 1172

	return ret;
}
1173
EXPORT_SYMBOL(ttm_bo_init);
1174

1175 1176 1177
size_t ttm_bo_acc_size(struct ttm_bo_device *bdev,
		       unsigned long bo_size,
		       unsigned struct_size)
1178
{
1179 1180
	unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT;
	size_t size = 0;
1181

1182 1183 1184 1185
	size += ttm_round_pot(struct_size);
	size += PAGE_ALIGN(npages * sizeof(void *));
	size += ttm_round_pot(sizeof(struct ttm_tt));
	return size;
1186
}
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202
EXPORT_SYMBOL(ttm_bo_acc_size);

size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev,
			   unsigned long bo_size,
			   unsigned struct_size)
{
	unsigned npages = (PAGE_ALIGN(bo_size)) >> PAGE_SHIFT;
	size_t size = 0;

	size += ttm_round_pot(struct_size);
	size += PAGE_ALIGN(npages * sizeof(void *));
	size += PAGE_ALIGN(npages * sizeof(dma_addr_t));
	size += ttm_round_pot(sizeof(struct ttm_dma_tt));
	return size;
}
EXPORT_SYMBOL(ttm_bo_dma_acc_size);
1203

1204 1205 1206 1207 1208 1209
int ttm_bo_create(struct ttm_bo_device *bdev,
			unsigned long size,
			enum ttm_bo_type type,
			struct ttm_placement *placement,
			uint32_t page_alignment,
			bool interruptible,
J
Jan Engelhardt 已提交
1210
			struct file *persistent_swap_storage,
1211
			struct ttm_buffer_object **p_bo)
1212 1213
{
	struct ttm_buffer_object *bo;
1214
	size_t acc_size;
1215
	int ret;
1216 1217

	bo = kzalloc(sizeof(*bo), GFP_KERNEL);
1218
	if (unlikely(bo == NULL))
1219 1220
		return -ENOMEM;

1221
	acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object));
1222
	ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
1223 1224
			  interruptible, persistent_swap_storage, acc_size,
			  NULL, NULL);
1225 1226 1227 1228 1229
	if (likely(ret == 0))
		*p_bo = bo;

	return ret;
}
T
Thomas Hellstrom 已提交
1230
EXPORT_SYMBOL(ttm_bo_create);
1231 1232

static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev,
1233
					unsigned mem_type, bool allow_errors)
1234
{
1235
	struct ttm_mem_type_manager *man = &bdev->man[mem_type];
1236
	struct ttm_bo_global *glob = bdev->glob;
1237 1238 1239 1240 1241 1242
	int ret;

	/*
	 * Can't use standard list traversal since we're unlocking.
	 */

1243
	spin_lock(&glob->lru_lock);
1244
	while (!list_empty(&man->lru)) {
1245
		spin_unlock(&glob->lru_lock);
1246
		ret = ttm_mem_evict_first(bdev, mem_type, false, false);
1247 1248 1249 1250
		if (ret) {
			if (allow_errors) {
				return ret;
			} else {
J
Joe Perches 已提交
1251
				pr_err("Cleanup eviction failed\n");
1252 1253
			}
		}
1254
		spin_lock(&glob->lru_lock);
1255
	}
1256
	spin_unlock(&glob->lru_lock);
1257 1258 1259 1260 1261
	return 0;
}

int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type)
{
R
Roel Kluin 已提交
1262
	struct ttm_mem_type_manager *man;
1263 1264 1265
	int ret = -EINVAL;

	if (mem_type >= TTM_NUM_MEM_TYPES) {
J
Joe Perches 已提交
1266
		pr_err("Illegal memory type %d\n", mem_type);
1267 1268
		return ret;
	}
R
Roel Kluin 已提交
1269
	man = &bdev->man[mem_type];
1270 1271

	if (!man->has_type) {
J
Joe Perches 已提交
1272 1273
		pr_err("Trying to take down uninitialized memory manager type %u\n",
		       mem_type);
1274 1275 1276 1277 1278 1279 1280 1281
		return ret;
	}

	man->use_type = false;
	man->has_type = false;

	ret = 0;
	if (mem_type > 0) {
1282
		ttm_bo_force_list_clean(bdev, mem_type, false);
1283

1284
		ret = (*man->func->takedown)(man);
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
	}

	return ret;
}
EXPORT_SYMBOL(ttm_bo_clean_mm);

int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type)
{
	struct ttm_mem_type_manager *man = &bdev->man[mem_type];

	if (mem_type == 0 || mem_type >= TTM_NUM_MEM_TYPES) {
J
Joe Perches 已提交
1296
		pr_err("Illegal memory manager memory type %u\n", mem_type);
1297 1298 1299 1300
		return -EINVAL;
	}

	if (!man->has_type) {
J
Joe Perches 已提交
1301
		pr_err("Memory type %u has not been initialized\n", mem_type);
1302 1303 1304
		return 0;
	}

1305
	return ttm_bo_force_list_clean(bdev, mem_type, true);
1306 1307 1308 1309
}
EXPORT_SYMBOL(ttm_bo_evict_mm);

int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
1310
			unsigned long p_size)
1311 1312 1313 1314
{
	int ret = -EINVAL;
	struct ttm_mem_type_manager *man;

1315
	BUG_ON(type >= TTM_NUM_MEM_TYPES);
1316
	man = &bdev->man[type];
1317
	BUG_ON(man->has_type);
1318 1319 1320 1321
	man->io_reserve_fastpath = true;
	man->use_io_reserve_lru = false;
	mutex_init(&man->io_reserve_mutex);
	INIT_LIST_HEAD(&man->io_reserve_lru);
1322 1323 1324 1325

	ret = bdev->driver->init_mem_type(bdev, type, man);
	if (ret)
		return ret;
1326
	man->bdev = bdev;
1327 1328 1329

	ret = 0;
	if (type != TTM_PL_SYSTEM) {
1330
		ret = (*man->func->init)(man, p_size);
1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
		if (ret)
			return ret;
	}
	man->has_type = true;
	man->use_type = true;
	man->size = p_size;

	INIT_LIST_HEAD(&man->lru);

	return 0;
}
EXPORT_SYMBOL(ttm_bo_init_mm);

1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
static void ttm_bo_global_kobj_release(struct kobject *kobj)
{
	struct ttm_bo_global *glob =
		container_of(kobj, struct ttm_bo_global, kobj);

	ttm_mem_unregister_shrink(glob->mem_glob, &glob->shrink);
	__free_page(glob->dummy_read_page);
	kfree(glob);
}

1354
void ttm_bo_global_release(struct drm_global_reference *ref)
1355 1356 1357 1358 1359 1360 1361 1362
{
	struct ttm_bo_global *glob = ref->object;

	kobject_del(&glob->kobj);
	kobject_put(&glob->kobj);
}
EXPORT_SYMBOL(ttm_bo_global_release);

1363
int ttm_bo_global_init(struct drm_global_reference *ref)
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385
{
	struct ttm_bo_global_ref *bo_ref =
		container_of(ref, struct ttm_bo_global_ref, ref);
	struct ttm_bo_global *glob = ref->object;
	int ret;

	mutex_init(&glob->device_list_mutex);
	spin_lock_init(&glob->lru_lock);
	glob->mem_glob = bo_ref->mem_glob;
	glob->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32);

	if (unlikely(glob->dummy_read_page == NULL)) {
		ret = -ENOMEM;
		goto out_no_drp;
	}

	INIT_LIST_HEAD(&glob->swap_lru);
	INIT_LIST_HEAD(&glob->device_list);

	ttm_mem_init_shrink(&glob->shrink, ttm_bo_swapout);
	ret = ttm_mem_register_shrink(glob->mem_glob, &glob->shrink);
	if (unlikely(ret != 0)) {
J
Joe Perches 已提交
1386
		pr_err("Could not register buffer object swapout\n");
1387 1388 1389 1390 1391
		goto out_no_shrink;
	}

	atomic_set(&glob->bo_count, 0);

1392 1393
	ret = kobject_init_and_add(
		&glob->kobj, &ttm_bo_glob_kobj_type, ttm_get_kobj(), "buffer_objects");
1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
	if (unlikely(ret != 0))
		kobject_put(&glob->kobj);
	return ret;
out_no_shrink:
	__free_page(glob->dummy_read_page);
out_no_drp:
	kfree(glob);
	return ret;
}
EXPORT_SYMBOL(ttm_bo_global_init);


1406 1407 1408 1409 1410
int ttm_bo_device_release(struct ttm_bo_device *bdev)
{
	int ret = 0;
	unsigned i = TTM_NUM_MEM_TYPES;
	struct ttm_mem_type_manager *man;
1411
	struct ttm_bo_global *glob = bdev->glob;
1412 1413 1414 1415 1416 1417 1418

	while (i--) {
		man = &bdev->man[i];
		if (man->has_type) {
			man->use_type = false;
			if ((i != TTM_PL_SYSTEM) && ttm_bo_clean_mm(bdev, i)) {
				ret = -EBUSY;
J
Joe Perches 已提交
1419 1420
				pr_err("DRM memory manager type %d is not clean\n",
				       i);
1421 1422 1423 1424 1425
			}
			man->has_type = false;
		}
	}

1426 1427 1428 1429
	mutex_lock(&glob->device_list_mutex);
	list_del(&bdev->device_list);
	mutex_unlock(&glob->device_list_mutex);

1430
	cancel_delayed_work_sync(&bdev->wq);
1431 1432 1433 1434

	while (ttm_bo_delayed_delete(bdev, true))
		;

1435
	spin_lock(&glob->lru_lock);
1436 1437 1438 1439 1440
	if (list_empty(&bdev->ddestroy))
		TTM_DEBUG("Delayed destroy list was clean\n");

	if (list_empty(&bdev->man[0].lru))
		TTM_DEBUG("Swap list was clean\n");
1441
	spin_unlock(&glob->lru_lock);
1442

1443
	drm_vma_offset_manager_destroy(&bdev->vma_manager);
1444 1445 1446 1447 1448 1449

	return ret;
}
EXPORT_SYMBOL(ttm_bo_device_release);

int ttm_bo_device_init(struct ttm_bo_device *bdev,
1450 1451
		       struct ttm_bo_global *glob,
		       struct ttm_bo_driver *driver,
1452
		       struct address_space *mapping,
D
Dave Airlie 已提交
1453
		       uint64_t file_page_offset,
D
Dave Airlie 已提交
1454
		       bool need_dma32)
1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465
{
	int ret = -EINVAL;

	bdev->driver = driver;

	memset(bdev->man, 0, sizeof(bdev->man));

	/*
	 * Initialize the system memory buffer type.
	 * Other types need to be driver / IOCTL initialized.
	 */
1466
	ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0);
1467
	if (unlikely(ret != 0))
1468
		goto out_no_sys;
1469

1470 1471
	drm_vma_offset_manager_init(&bdev->vma_manager, file_page_offset,
				    0x10000000);
1472 1473
	INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue);
	INIT_LIST_HEAD(&bdev->ddestroy);
1474
	bdev->dev_mapping = mapping;
1475
	bdev->glob = glob;
D
Dave Airlie 已提交
1476
	bdev->need_dma32 = need_dma32;
1477
	bdev->val_seq = 0;
1478
	spin_lock_init(&bdev->fence_lock);
1479 1480 1481
	mutex_lock(&glob->device_list_mutex);
	list_add_tail(&bdev->device_list, &glob->device_list);
	mutex_unlock(&glob->device_list_mutex);
1482 1483

	return 0;
1484
out_no_sys:
1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
	return ret;
}
EXPORT_SYMBOL(ttm_bo_device_init);

/*
 * buffer object vm functions.
 */

bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
{
	struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];

	if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
		if (mem->mem_type == TTM_PL_SYSTEM)
			return false;

		if (man->flags & TTM_MEMTYPE_FLAG_CMA)
			return false;

		if (mem->placement & TTM_PL_FLAG_CACHED)
			return false;
	}
	return true;
}

1510
void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo)
1511 1512 1513
{
	struct ttm_bo_device *bdev = bo->bdev;

1514
	drm_vma_node_unmap(&bo->vma_node, bdev->dev_mapping);
1515
	ttm_mem_io_free_vm(bo);
1516
}
1517 1518 1519 1520 1521 1522 1523 1524 1525

void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo)
{
	struct ttm_bo_device *bdev = bo->bdev;
	struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type];

	ttm_mem_io_lock(man, false);
	ttm_bo_unmap_virtual_locked(bo);
	ttm_mem_io_unlock(man);
1526
}
1527 1528


1529
EXPORT_SYMBOL(ttm_bo_unmap_virtual);
1530 1531 1532


int ttm_bo_wait(struct ttm_buffer_object *bo,
1533
		bool lazy, bool interruptible, bool no_wait)
1534 1535
{
	struct ttm_bo_driver *driver = bo->bdev->driver;
1536
	struct ttm_bo_device *bdev = bo->bdev;
1537 1538 1539
	void *sync_obj;
	int ret = 0;

1540
	if (likely(bo->sync_obj == NULL))
1541 1542
		return 0;

1543
	while (bo->sync_obj) {
1544

1545
		if (driver->sync_obj_signaled(bo->sync_obj)) {
1546 1547 1548 1549 1550 1551
			void *tmp_obj = bo->sync_obj;
			bo->sync_obj = NULL;
			clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags);
			spin_unlock(&bdev->fence_lock);
			driver->sync_obj_unref(&tmp_obj);
			spin_lock(&bdev->fence_lock);
1552 1553 1554 1555 1556 1557
			continue;
		}

		if (no_wait)
			return -EBUSY;

1558
		sync_obj = driver->sync_obj_ref(bo->sync_obj);
1559
		spin_unlock(&bdev->fence_lock);
1560
		ret = driver->sync_obj_wait(sync_obj,
1561 1562 1563
					    lazy, interruptible);
		if (unlikely(ret != 0)) {
			driver->sync_obj_unref(&sync_obj);
1564
			spin_lock(&bdev->fence_lock);
1565 1566
			return ret;
		}
1567
		spin_lock(&bdev->fence_lock);
1568
		if (likely(bo->sync_obj == sync_obj)) {
1569 1570 1571 1572 1573 1574 1575 1576
			void *tmp_obj = bo->sync_obj;
			bo->sync_obj = NULL;
			clear_bit(TTM_BO_PRIV_FLAG_MOVING,
				  &bo->priv_flags);
			spin_unlock(&bdev->fence_lock);
			driver->sync_obj_unref(&sync_obj);
			driver->sync_obj_unref(&tmp_obj);
			spin_lock(&bdev->fence_lock);
1577
		} else {
1578
			spin_unlock(&bdev->fence_lock);
1579
			driver->sync_obj_unref(&sync_obj);
1580
			spin_lock(&bdev->fence_lock);
1581 1582 1583 1584 1585 1586 1587 1588
		}
	}
	return 0;
}
EXPORT_SYMBOL(ttm_bo_wait);

int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait)
{
1589
	struct ttm_bo_device *bdev = bo->bdev;
1590 1591 1592
	int ret = 0;

	/*
1593
	 * Using ttm_bo_reserve makes sure the lru lists are updated.
1594 1595 1596 1597 1598
	 */

	ret = ttm_bo_reserve(bo, true, no_wait, false, 0);
	if (unlikely(ret != 0))
		return ret;
1599
	spin_lock(&bdev->fence_lock);
1600
	ret = ttm_bo_wait(bo, false, true, no_wait);
1601
	spin_unlock(&bdev->fence_lock);
1602 1603 1604 1605 1606
	if (likely(ret == 0))
		atomic_inc(&bo->cpu_writers);
	ttm_bo_unreserve(bo);
	return ret;
}
1607
EXPORT_SYMBOL(ttm_bo_synccpu_write_grab);
1608 1609 1610

void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo)
{
1611
	atomic_dec(&bo->cpu_writers);
1612
}
1613
EXPORT_SYMBOL(ttm_bo_synccpu_write_release);
1614 1615 1616 1617 1618 1619 1620 1621

/**
 * A buffer object shrink method that tries to swap out the first
 * buffer object on the bo_global::swap_lru list.
 */

static int ttm_bo_swapout(struct ttm_mem_shrink *shrink)
{
1622 1623
	struct ttm_bo_global *glob =
	    container_of(shrink, struct ttm_bo_global, shrink);
1624 1625 1626 1627 1628
	struct ttm_buffer_object *bo;
	int ret = -EBUSY;
	int put_count;
	uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM);

1629
	spin_lock(&glob->lru_lock);
1630
	list_for_each_entry(bo, &glob->swap_lru, swap) {
1631
		ret = ttm_bo_reserve_nolru(bo, false, true, false, 0);
1632 1633 1634
		if (!ret)
			break;
	}
1635

1636 1637 1638 1639
	if (ret) {
		spin_unlock(&glob->lru_lock);
		return ret;
	}
1640

1641
	kref_get(&bo->list_kref);
1642

1643 1644 1645 1646
	if (!list_empty(&bo->ddestroy)) {
		ret = ttm_bo_cleanup_refs_and_unlock(bo, false, false);
		kref_put(&bo->list_kref, ttm_bo_release_list);
		return ret;
1647 1648 1649
	}

	put_count = ttm_bo_del_from_lru(bo);
1650
	spin_unlock(&glob->lru_lock);
1651

1652
	ttm_bo_list_ref_sub(bo, put_count, true);
1653 1654 1655 1656 1657

	/**
	 * Wait for GPU, then move to system cached.
	 */

1658
	spin_lock(&bo->bdev->fence_lock);
1659
	ret = ttm_bo_wait(bo, false, false, false);
1660
	spin_unlock(&bo->bdev->fence_lock);
1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673

	if (unlikely(ret != 0))
		goto out;

	if ((bo->mem.placement & swap_placement) != swap_placement) {
		struct ttm_mem_reg evict_mem;

		evict_mem = bo->mem;
		evict_mem.mm_node = NULL;
		evict_mem.placement = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED;
		evict_mem.mem_type = TTM_PL_SYSTEM;

		ret = ttm_bo_handle_move_mem(bo, &evict_mem, true,
1674
					     false, false);
1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685
		if (unlikely(ret != 0))
			goto out;
	}

	ttm_bo_unmap_virtual(bo);

	/**
	 * Swap out. Buffer will be swapped in again as soon as
	 * anyone tries to access a ttm page.
	 */

1686 1687 1688
	if (bo->bdev->driver->swap_notify)
		bo->bdev->driver->swap_notify(bo);

J
Jan Engelhardt 已提交
1689
	ret = ttm_tt_swapout(bo->ttm, bo->persistent_swap_storage);
1690 1691 1692 1693 1694 1695 1696 1697
out:

	/**
	 *
	 * Unreserve without putting on LRU to avoid swapping out an
	 * already swapped buffer.
	 */

1698
	ww_mutex_unlock(&bo->resv->lock);
1699 1700 1701 1702 1703 1704
	kref_put(&bo->list_kref, ttm_bo_release_list);
	return ret;
}

void ttm_bo_swapout_all(struct ttm_bo_device *bdev)
{
1705
	while (ttm_bo_swapout(&bdev->glob->shrink) == 0)
1706 1707
		;
}
1708
EXPORT_SYMBOL(ttm_bo_swapout_all);
1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740

/**
 * ttm_bo_wait_unreserved - interruptible wait for a buffer object to become
 * unreserved
 *
 * @bo: Pointer to buffer
 */
int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo)
{
	int ret;

	/*
	 * In the absense of a wait_unlocked API,
	 * Use the bo::wu_mutex to avoid triggering livelocks due to
	 * concurrent use of this function. Note that this use of
	 * bo::wu_mutex can go away if we change locking order to
	 * mmap_sem -> bo::reserve.
	 */
	ret = mutex_lock_interruptible(&bo->wu_mutex);
	if (unlikely(ret != 0))
		return -ERESTARTSYS;
	if (!ww_mutex_is_locked(&bo->resv->lock))
		goto out_unlock;
	ret = ttm_bo_reserve_nolru(bo, true, false, false, NULL);
	if (unlikely(ret != 0))
		goto out_unlock;
	ww_mutex_unlock(&bo->resv->lock);

out_unlock:
	mutex_unlock(&bo->wu_mutex);
	return ret;
}