radeon_object.c 13.9 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 31 32
/*
 * Copyright 2009 Jerome Glisse.
 * 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 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.
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial portions
 * of the Software.
 *
 */
/*
 * Authors:
 *    Jerome Glisse <glisse@freedesktop.org>
 *    Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
 *    Dave Airlie
 */
#include <linux/list.h>
33
#include <linux/slab.h>
34 35 36
#include <drm/drmP.h>
#include "radeon_drm.h"
#include "radeon.h"
37
#include "radeon_trace.h"
38 39 40 41


int radeon_ttm_init(struct radeon_device *rdev);
void radeon_ttm_fini(struct radeon_device *rdev);
42
static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
43 44 45 46 47 48

/*
 * To exclude mutual BO access we rely on bo_reserve exclusion, as all
 * function are calling it.
 */

49
static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
50
{
51
	struct radeon_bo *bo;
52

53 54 55 56 57
	bo = container_of(tbo, struct radeon_bo, tbo);
	mutex_lock(&bo->rdev->gem.mutex);
	list_del_init(&bo->list);
	mutex_unlock(&bo->rdev->gem.mutex);
	radeon_bo_clear_surface_reg(bo);
58
	drm_gem_object_release(&bo->gem_base);
59
	kfree(bo);
60 61
}

62 63 64 65 66 67 68
bool radeon_ttm_bo_is_radeon_bo(struct ttm_buffer_object *bo)
{
	if (bo->destroy == &radeon_ttm_bo_destroy)
		return true;
	return false;
}

69 70 71 72 73
void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
{
	u32 c = 0;

	rbo->placement.fpfn = 0;
74
	rbo->placement.lpfn = 0;
75 76 77 78 79 80 81 82 83
	rbo->placement.placement = rbo->placements;
	rbo->placement.busy_placement = rbo->placements;
	if (domain & RADEON_GEM_DOMAIN_VRAM)
		rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
					TTM_PL_FLAG_VRAM;
	if (domain & RADEON_GEM_DOMAIN_GTT)
		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_TT;
	if (domain & RADEON_GEM_DOMAIN_CPU)
		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
84 85
	if (!c)
		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
86 87 88 89
	rbo->placement.num_placement = c;
	rbo->placement.num_busy_placement = c;
}

90
int radeon_bo_create(struct radeon_device *rdev,
91 92
		     unsigned long size, int byte_align, bool kernel, u32 domain,
		     struct radeon_bo **bo_ptr)
93
{
94
	struct radeon_bo *bo;
95
	enum ttm_bo_type type;
96 97
	unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
	unsigned long max_size = 0;
98 99
	int r;

100 101
	size = ALIGN(size, PAGE_SIZE);

102 103 104 105 106 107 108 109
	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
		rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
	}
	if (kernel) {
		type = ttm_bo_type_kernel;
	} else {
		type = ttm_bo_type_device;
	}
110
	*bo_ptr = NULL;
111

112 113 114 115 116 117 118 119
	/* maximun bo size is the minimun btw visible vram and gtt size */
	max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
	if ((page_align << PAGE_SHIFT) >= max_size) {
		printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
			__func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
		return -ENOMEM;
	}

120
retry:
121 122
	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
	if (bo == NULL)
123
		return -ENOMEM;
124 125 126 127 128
	r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size);
	if (unlikely(r)) {
		kfree(bo);
		return r;
	}
129
	bo->rdev = rdev;
130
	bo->gem_base.driver_private = NULL;
131 132
	bo->surface_reg = -1;
	INIT_LIST_HEAD(&bo->list);
133
	radeon_ttm_placement_from_domain(bo, domain);
134
	/* Kernel allocation are uninterruptible */
135
	mutex_lock(&rdev->vram_mutex);
136
	r = ttm_bo_init(&rdev->mman.bdev, &bo->tbo, size, type,
137
			&bo->placement, page_align, 0, !kernel, NULL, size,
138
			&radeon_ttm_bo_destroy);
139
	mutex_unlock(&rdev->vram_mutex);
140
	if (unlikely(r != 0)) {
141 142 143 144 145
		if (r != -ERESTARTSYS) {
			if (domain == RADEON_GEM_DOMAIN_VRAM) {
				domain |= RADEON_GEM_DOMAIN_GTT;
				goto retry;
			}
146
			dev_err(rdev->dev,
147 148
				"object_init failed for (%lu, 0x%08X)\n",
				size, domain);
149
		}
150 151
		return r;
	}
152
	*bo_ptr = bo;
153

154
	trace_radeon_bo_create(bo);
155

156 157 158
	return 0;
}

159
int radeon_bo_kmap(struct radeon_bo *bo, void **ptr)
160
{
161
	bool is_iomem;
162 163
	int r;

164
	if (bo->kptr) {
165
		if (ptr) {
166
			*ptr = bo->kptr;
167 168 169
		}
		return 0;
	}
170
	r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
171 172 173
	if (r) {
		return r;
	}
174
	bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
175
	if (ptr) {
176
		*ptr = bo->kptr;
177
	}
178
	radeon_bo_check_tiling(bo, 0, 0);
179 180 181
	return 0;
}

182
void radeon_bo_kunmap(struct radeon_bo *bo)
183
{
184
	if (bo->kptr == NULL)
185
		return;
186 187 188
	bo->kptr = NULL;
	radeon_bo_check_tiling(bo, 0, 0);
	ttm_bo_kunmap(&bo->kmap);
189 190
}

191
void radeon_bo_unref(struct radeon_bo **bo)
192
{
193
	struct ttm_buffer_object *tbo;
194
	struct radeon_device *rdev;
195

196
	if ((*bo) == NULL)
197
		return;
198
	rdev = (*bo)->rdev;
199
	tbo = &((*bo)->tbo);
200
	mutex_lock(&rdev->vram_mutex);
201
	ttm_bo_unref(&tbo);
202
	mutex_unlock(&rdev->vram_mutex);
203 204
	if (tbo == NULL)
		*bo = NULL;
205 206
}

207
int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
208
{
209
	int r, i;
210

211 212 213 214
	if (bo->pin_count) {
		bo->pin_count++;
		if (gpu_addr)
			*gpu_addr = radeon_bo_gpu_offset(bo);
215 216
		return 0;
	}
217
	radeon_ttm_placement_from_domain(bo, domain);
218 219 220 221
	if (domain == RADEON_GEM_DOMAIN_VRAM) {
		/* force to pin into visible video ram */
		bo->placement.lpfn = bo->rdev->mc.visible_vram_size >> PAGE_SHIFT;
	}
222 223
	for (i = 0; i < bo->placement.num_placement; i++)
		bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
224
	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
225 226 227 228
	if (likely(r == 0)) {
		bo->pin_count = 1;
		if (gpu_addr != NULL)
			*gpu_addr = radeon_bo_gpu_offset(bo);
229
	}
230
	if (unlikely(r != 0))
231
		dev_err(bo->rdev->dev, "%p pin failed\n", bo);
232 233 234
	return r;
}

235
int radeon_bo_unpin(struct radeon_bo *bo)
236
{
237
	int r, i;
238

239 240 241
	if (!bo->pin_count) {
		dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo);
		return 0;
242
	}
243 244 245
	bo->pin_count--;
	if (bo->pin_count)
		return 0;
246 247
	for (i = 0; i < bo->placement.num_placement; i++)
		bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
248
	r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false, false);
249
	if (unlikely(r != 0))
250
		dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
251
	return r;
252 253
}

254
int radeon_bo_evict_vram(struct radeon_device *rdev)
255
{
256 257
	/* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */
	if (0 && (rdev->flags & RADEON_IS_IGP)) {
258 259 260
		if (rdev->mc.igp_sideport_enabled == false)
			/* Useless to evict on IGP chips */
			return 0;
261 262 263 264
	}
	return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM);
}

265
void radeon_bo_force_delete(struct radeon_device *rdev)
266
{
267
	struct radeon_bo *bo, *n;
268 269 270 271

	if (list_empty(&rdev->gem.objects)) {
		return;
	}
272 273
	dev_err(rdev->dev, "Userspace still has active objects !\n");
	list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
274
		mutex_lock(&rdev->ddev->struct_mutex);
275
		dev_err(rdev->dev, "%p %p %lu %lu force free\n",
276 277
			&bo->gem_base, bo, (unsigned long)bo->gem_base.size,
			*((unsigned long *)&bo->gem_base.refcount));
278 279 280
		mutex_lock(&bo->rdev->gem.mutex);
		list_del_init(&bo->list);
		mutex_unlock(&bo->rdev->gem.mutex);
281
		/* this should unref the ttm bo */
282
		drm_gem_object_unreference(&bo->gem_base);
283 284 285 286
		mutex_unlock(&rdev->ddev->struct_mutex);
	}
}

287
int radeon_bo_init(struct radeon_device *rdev)
288
{
289 290 291 292 293 294 295 296
	/* Add an MTRR for the VRAM */
	rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
			MTRR_TYPE_WRCOMB, 1);
	DRM_INFO("Detected VRAM RAM=%lluM, BAR=%lluM\n",
		rdev->mc.mc_vram_size >> 20,
		(unsigned long long)rdev->mc.aper_size >> 20);
	DRM_INFO("RAM width %dbits %cDR\n",
			rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
297 298 299
	return radeon_ttm_init(rdev);
}

300
void radeon_bo_fini(struct radeon_device *rdev)
301 302 303 304
{
	radeon_ttm_fini(rdev);
}

305 306
void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
				struct list_head *head)
307 308
{
	if (lobj->wdomain) {
309
		list_add(&lobj->tv.head, head);
310
	} else {
311
		list_add_tail(&lobj->tv.head, head);
312 313 314
	}
}

315
int radeon_bo_list_validate(struct list_head *head)
316
{
317 318
	struct radeon_bo_list *lobj;
	struct radeon_bo *bo;
319
	u32 domain;
320 321
	int r;

322
	r = ttm_eu_reserve_buffers(head);
323 324 325
	if (unlikely(r != 0)) {
		return r;
	}
326
	list_for_each_entry(lobj, head, tv.head) {
327 328
		bo = lobj->bo;
		if (!bo->pin_count) {
329 330 331 332
			domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
			
		retry:
			radeon_ttm_placement_from_domain(bo, domain);
333
			r = ttm_bo_validate(&bo->tbo, &bo->placement,
334
						true, false, false);
335 336 337 338 339
			if (unlikely(r)) {
				if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
					domain |= RADEON_GEM_DOMAIN_GTT;
					goto retry;
				}
340
				return r;
341
			}
342
		}
343 344
		lobj->gpu_offset = radeon_bo_gpu_offset(bo);
		lobj->tiling_flags = bo->tiling_flags;
345 346 347 348
	}
	return 0;
}

349
int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
350 351
			     struct vm_area_struct *vma)
{
352
	return ttm_fbdev_mmap(vma, &bo->tbo);
353 354
}

355
int radeon_bo_get_surface_reg(struct radeon_bo *bo)
356
{
357
	struct radeon_device *rdev = bo->rdev;
358
	struct radeon_surface_reg *reg;
359
	struct radeon_bo *old_object;
360 361 362
	int steal;
	int i;

363 364 365
	BUG_ON(!atomic_read(&bo->tbo.reserved));

	if (!bo->tiling_flags)
366 367
		return 0;

368 369 370
	if (bo->surface_reg >= 0) {
		reg = &rdev->surface_regs[bo->surface_reg];
		i = bo->surface_reg;
371 372 373 374 375 376 377
		goto out;
	}

	steal = -1;
	for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {

		reg = &rdev->surface_regs[i];
378
		if (!reg->bo)
379 380
			break;

381
		old_object = reg->bo;
382 383 384 385 386 387 388 389 390 391
		if (old_object->pin_count == 0)
			steal = i;
	}

	/* if we are all out */
	if (i == RADEON_GEM_MAX_SURFACES) {
		if (steal == -1)
			return -ENOMEM;
		/* find someone with a surface reg and nuke their BO */
		reg = &rdev->surface_regs[steal];
392
		old_object = reg->bo;
393 394
		/* blow away the mapping */
		DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
395
		ttm_bo_unmap_virtual(&old_object->tbo);
396 397 398 399
		old_object->surface_reg = -1;
		i = steal;
	}

400 401
	bo->surface_reg = i;
	reg->bo = bo;
402 403

out:
404
	radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch,
405
			       bo->tbo.mem.start << PAGE_SHIFT,
406
			       bo->tbo.num_pages << PAGE_SHIFT);
407 408 409
	return 0;
}

410
static void radeon_bo_clear_surface_reg(struct radeon_bo *bo)
411
{
412
	struct radeon_device *rdev = bo->rdev;
413 414
	struct radeon_surface_reg *reg;

415
	if (bo->surface_reg == -1)
416 417
		return;

418 419
	reg = &rdev->surface_regs[bo->surface_reg];
	radeon_clear_surface_reg(rdev, bo->surface_reg);
420

421 422
	reg->bo = NULL;
	bo->surface_reg = -1;
423 424
}

425 426
int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
				uint32_t tiling_flags, uint32_t pitch)
427
{
428 429 430 431 432 433 434 435 436
	int r;

	r = radeon_bo_reserve(bo, false);
	if (unlikely(r != 0))
		return r;
	bo->tiling_flags = tiling_flags;
	bo->pitch = pitch;
	radeon_bo_unreserve(bo);
	return 0;
437 438
}

439 440 441
void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
				uint32_t *tiling_flags,
				uint32_t *pitch)
442
{
443
	BUG_ON(!atomic_read(&bo->tbo.reserved));
444
	if (tiling_flags)
445
		*tiling_flags = bo->tiling_flags;
446
	if (pitch)
447
		*pitch = bo->pitch;
448 449
}

450 451
int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
				bool force_drop)
452
{
453 454 455
	BUG_ON(!atomic_read(&bo->tbo.reserved));

	if (!(bo->tiling_flags & RADEON_TILING_SURFACE))
456 457 458
		return 0;

	if (force_drop) {
459
		radeon_bo_clear_surface_reg(bo);
460 461 462
		return 0;
	}

463
	if (bo->tbo.mem.mem_type != TTM_PL_VRAM) {
464 465 466
		if (!has_moved)
			return 0;

467 468
		if (bo->surface_reg >= 0)
			radeon_bo_clear_surface_reg(bo);
469 470 471
		return 0;
	}

472
	if ((bo->surface_reg >= 0) && !has_moved)
473 474
		return 0;

475
	return radeon_bo_get_surface_reg(bo);
476 477 478
}

void radeon_bo_move_notify(struct ttm_buffer_object *bo,
479
			   struct ttm_mem_reg *mem)
480
{
481 482 483 484
	struct radeon_bo *rbo;
	if (!radeon_ttm_bo_is_radeon_bo(bo))
		return;
	rbo = container_of(bo, struct radeon_bo, tbo);
485
	radeon_bo_check_tiling(rbo, 0, 1);
486 487
}

488
int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
489
{
490
	struct radeon_device *rdev;
491
	struct radeon_bo *rbo;
492 493 494
	unsigned long offset, size;
	int r;

495
	if (!radeon_ttm_bo_is_radeon_bo(bo))
496
		return 0;
497
	rbo = container_of(bo, struct radeon_bo, tbo);
498
	radeon_bo_check_tiling(rbo, 0, 0);
499 500 501
	rdev = rbo->rdev;
	if (bo->mem.mem_type == TTM_PL_VRAM) {
		size = bo->mem.num_pages << PAGE_SHIFT;
502
		offset = bo->mem.start << PAGE_SHIFT;
503 504 505 506 507 508 509
		if ((offset + size) > rdev->mc.visible_vram_size) {
			/* hurrah the memory is not visible ! */
			radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM);
			rbo->placement.lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT;
			r = ttm_bo_validate(bo, &rbo->placement, false, true, false);
			if (unlikely(r != 0))
				return r;
510
			offset = bo->mem.start << PAGE_SHIFT;
511 512 513 514 515 516
			/* this should not happen */
			if ((offset + size) > rdev->mc.visible_vram_size)
				return -EINVAL;
		}
	}
	return 0;
517
}
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559

int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait,
		   enum ttm_buffer_usage usage)
{
	int r;

	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
	if (unlikely(r != 0))
		return r;
	spin_lock(&bo->tbo.bdev->fence_lock);
	if (mem_type)
		*mem_type = bo->tbo.mem.mem_type;
	if (bo->tbo.sync_obj)
		r = ttm_bo_wait(&bo->tbo, true, true, no_wait, usage);
	spin_unlock(&bo->tbo.bdev->fence_lock);
	ttm_bo_unreserve(&bo->tbo);
	return r;
}


/**
 * radeon_bo_reserve - reserve bo
 * @bo:		bo structure
 * @no_wait:		don't sleep while trying to reserve (return -EBUSY)
 *
 * Returns:
 * -EBUSY: buffer is busy and @no_wait is true
 * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by
 * a signal. Release all buffer reservations and return to user-space.
 */
int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
{
	int r;

	r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
	if (unlikely(r != 0)) {
		if (r != -ERESTARTSYS)
			dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
		return r;
	}
	return 0;
}