nouveau_bo.c 42.4 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
/*
 * Copyright 2007 Dave Airlied
 * 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, sublicense,
 * 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 NONINFRINGEMENT.  IN NO EVENT SHALL
 * VA LINUX SYSTEMS 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: Dave Airlied <airlied@linux.ie>
 *	    Ben Skeggs   <darktama@iinet.net.au>
 *	    Jeremy Kolb  <jkolb@brandeis.edu>
 */

30
#include <linux/dma-mapping.h>
31
#include <linux/swiotlb.h>
32

33
#include "nouveau_drv.h"
34
#include "nouveau_dma.h"
35
#include "nouveau_fence.h"
36

37 38 39
#include "nouveau_bo.h"
#include "nouveau_ttm.h"
#include "nouveau_gem.h"
40
#include "nouveau_mem.h"
41
#include "nouveau_vmm.h"
42

43 44 45 46
#include <nvif/class.h>
#include <nvif/if500b.h>
#include <nvif/if900b.h>

47 48 49 50 51
/*
 * NV10-NV40 tiling helpers
 */

static void
52 53
nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg,
			   u32 addr, u32 size, u32 pitch, u32 flags)
54
{
55
	struct nouveau_drm *drm = nouveau_drm(dev);
56
	int i = reg - drm->tile.reg;
57
	struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
B
Ben Skeggs 已提交
58
	struct nvkm_fb_tile *tile = &fb->tile.region[i];
59

60
	nouveau_fence_unref(&reg->fence);
61 62

	if (tile->pitch)
63
		nvkm_fb_tile_fini(fb, i, tile);
64 65

	if (pitch)
66
		nvkm_fb_tile_init(fb, i, addr, size, pitch, flags, tile);
67

68
	nvkm_fb_tile_prog(fb, i, tile);
69 70
}

71
static struct nouveau_drm_tile *
72 73
nv10_bo_get_tile_region(struct drm_device *dev, int i)
{
74
	struct nouveau_drm *drm = nouveau_drm(dev);
75
	struct nouveau_drm_tile *tile = &drm->tile.reg[i];
76

77
	spin_lock(&drm->tile.lock);
78 79 80 81 82 83 84

	if (!tile->used &&
	    (!tile->fence || nouveau_fence_done(tile->fence)))
		tile->used = true;
	else
		tile = NULL;

85
	spin_unlock(&drm->tile.lock);
86 87 88 89
	return tile;
}

static void
90
nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,
91
			struct dma_fence *fence)
92
{
93
	struct nouveau_drm *drm = nouveau_drm(dev);
94 95

	if (tile) {
96
		spin_lock(&drm->tile.lock);
97
		tile->fence = (struct nouveau_fence *)dma_fence_get(fence);
98
		tile->used = false;
99
		spin_unlock(&drm->tile.lock);
100 101 102
	}
}

103 104
static struct nouveau_drm_tile *
nv10_bo_set_tiling(struct drm_device *dev, u32 addr,
105
		   u32 size, u32 pitch, u32 zeta)
106
{
107
	struct nouveau_drm *drm = nouveau_drm(dev);
108
	struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
109
	struct nouveau_drm_tile *tile, *found = NULL;
110 111
	int i;

B
Ben Skeggs 已提交
112
	for (i = 0; i < fb->tile.regions; i++) {
113 114 115 116 117 118
		tile = nv10_bo_get_tile_region(dev, i);

		if (pitch && !found) {
			found = tile;
			continue;

B
Ben Skeggs 已提交
119
		} else if (tile && fb->tile.region[i].pitch) {
120 121 122 123 124 125 126 127
			/* Kill an unused tile region. */
			nv10_bo_update_tile_region(dev, tile, 0, 0, 0, 0);
		}

		nv10_bo_put_tile_region(dev, tile, NULL);
	}

	if (found)
128
		nv10_bo_update_tile_region(dev, found, addr, size, pitch, zeta);
129 130 131
	return found;
}

132 133 134
static void
nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
{
135 136
	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
	struct drm_device *dev = drm->dev;
137 138
	struct nouveau_bo *nvbo = nouveau_bo(bo);

139
	if (unlikely(nvbo->gem.filp))
140
		DRM_ERROR("bo %p still attached to GEM object\n", bo);
141
	WARN_ON(nvbo->pin_refcnt > 0);
142
	nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
143 144 145
	kfree(nvbo);
}

B
Ben Skeggs 已提交
146 147 148 149 150 151 152 153
static inline u64
roundup_64(u64 x, u32 y)
{
	x += y - 1;
	do_div(x, y);
	return x * y;
}

154
static void
155
nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
B
Ben Skeggs 已提交
156
		       int *align, u64 *size)
157
{
158
	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
159
	struct nvif_device *device = &drm->client.device;
160

161
	if (device->info.family < NV_DEVICE_INFO_V0_TESLA) {
162
		if (nvbo->mode) {
163
			if (device->info.chipset >= 0x40) {
164
				*align = 65536;
165
				*size = roundup_64(*size, 64 * nvbo->mode);
166

167
			} else if (device->info.chipset >= 0x30) {
168
				*align = 32768;
169
				*size = roundup_64(*size, 64 * nvbo->mode);
170

171
			} else if (device->info.chipset >= 0x20) {
172
				*align = 16384;
173
				*size = roundup_64(*size, 64 * nvbo->mode);
174

175
			} else if (device->info.chipset >= 0x10) {
176
				*align = 16384;
177
				*size = roundup_64(*size, 32 * nvbo->mode);
178 179
			}
		}
180
	} else {
181 182
		*size = roundup_64(*size, (1 << nvbo->page));
		*align = max((1 <<  nvbo->page), *align);
183 184
	}

B
Ben Skeggs 已提交
185
	*size = roundup_64(*size, PAGE_SIZE);
186 187
}

188
int
B
Ben Skeggs 已提交
189
nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
190
	       uint32_t flags, uint32_t tile_mode, uint32_t tile_flags,
191
	       struct sg_table *sg, struct reservation_object *robj,
192
	       struct nouveau_bo **pnvbo)
193
{
194
	struct nouveau_drm *drm = cli->drm;
195
	struct nouveau_bo *nvbo;
196
	struct nvif_mmu *mmu = &cli->mmu;
197
	struct nvif_vmm *vmm = &cli->vmm.vmm;
198
	size_t acc_size;
D
Dave Airlie 已提交
199
	int type = ttm_bo_type_device;
200
	int ret, i, pi = -1;
201

B
Ben Skeggs 已提交
202 203
	if (!size) {
		NV_WARN(drm, "skipped size %016llx\n", size);
204 205
		return -EINVAL;
	}
D
Dave Airlie 已提交
206 207 208

	if (sg)
		type = ttm_bo_type_sg;
209 210 211 212 213 214

	nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
	if (!nvbo)
		return -ENOMEM;
	INIT_LIST_HEAD(&nvbo->head);
	INIT_LIST_HEAD(&nvbo->entry);
215
	INIT_LIST_HEAD(&nvbo->vma_list);
216
	nvbo->bo.bdev = &drm->ttm.bdev;
217
	nvbo->cli = cli;
218

219 220 221 222 223 224 225 226 227 228 229
	/* This is confusing, and doesn't actually mean we want an uncached
	 * mapping, but is what NOUVEAU_GEM_DOMAIN_COHERENT gets translated
	 * into in nouveau_gem_new().
	 */
	if (flags & TTM_PL_FLAG_UNCACHED) {
		/* Determine if we can get a cache-coherent map, forcing
		 * uncached mapping if we can't.
		 */
		if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED)
			nvbo->force_coherent = true;
	}
230

231 232
	if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) {
		nvbo->kind = (tile_flags & 0x0000ff00) >> 8;
233 234 235 236 237 238
		if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) {
			kfree(nvbo);
			return -EINVAL;
		}

		nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind;
239 240 241 242
	} else
	if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
		nvbo->kind = (tile_flags & 0x00007f00) >> 8;
		nvbo->comp = (tile_flags & 0x00030000) >> 16;
243 244 245 246
		if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) {
			kfree(nvbo);
			return -EINVAL;
		}
247 248 249 250 251 252
	} else {
		nvbo->zeta = (tile_flags & 0x00000007);
	}
	nvbo->mode = tile_mode;
	nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG);

253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
	/* Determine the desirable target GPU page size for the buffer. */
	for (i = 0; i < vmm->page_nr; i++) {
		/* Because we cannot currently allow VMM maps to fail
		 * during buffer migration, we need to determine page
		 * size for the buffer up-front, and pre-allocate its
		 * page tables.
		 *
		 * Skip page sizes that can't support needed domains.
		 */
		if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE &&
		    (flags & TTM_PL_FLAG_VRAM) && !vmm->page[i].vram)
			continue;
		if ((flags & TTM_PL_FLAG_TT  ) && !vmm->page[i].host)
			continue;

		/* Select this page size if it's the first that supports
		 * the potential memory domains, or when it's compatible
		 * with the requested compression settings.
		 */
		if (pi < 0 || !nvbo->comp || vmm->page[i].comp)
			pi = i;

		/* Stop once the buffer is larger than the current page size. */
		if (size >= 1ULL << vmm->page[i].shift)
			break;
	}

	if (WARN_ON(pi < 0))
		return -EINVAL;

	/* Disable compression if suitable settings couldn't be found. */
	if (nvbo->comp && !vmm->page[pi].comp) {
		if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100)
			nvbo->kind = mmu->kind[nvbo->kind];
		nvbo->comp = 0;
288
	}
289
	nvbo->page = vmm->page[pi].shift;
290 291

	nouveau_bo_fixup_align(nvbo, flags, &align, &size);
292 293
	nvbo->bo.mem.num_pages = size >> PAGE_SHIFT;
	nouveau_bo_placement_set(nvbo, flags, 0);
294

295
	acc_size = ttm_bo_dma_acc_size(&drm->ttm.bdev, size,
296 297
				       sizeof(struct nouveau_bo));

298
	ret = ttm_bo_init(&drm->ttm.bdev, &nvbo->bo, size,
D
Dave Airlie 已提交
299
			  type, &nvbo->placement,
300
			  align >> PAGE_SHIFT, false, NULL, acc_size, sg,
301
			  robj, nouveau_bo_del_ttm);
302 303 304 305 306 307 308 309 310
	if (ret) {
		/* ttm will call nouveau_bo_del_ttm if it fails.. */
		return ret;
	}

	*pnvbo = nvbo;
	return 0;
}

311
static void
312
set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t type, uint32_t flags)
313 314 315 316
{
	*n = 0;

	if (type & TTM_PL_FLAG_VRAM)
317
		pl[(*n)++].flags = TTM_PL_FLAG_VRAM | flags;
318
	if (type & TTM_PL_FLAG_TT)
319
		pl[(*n)++].flags = TTM_PL_FLAG_TT | flags;
320
	if (type & TTM_PL_FLAG_SYSTEM)
321
		pl[(*n)++].flags = TTM_PL_FLAG_SYSTEM | flags;
322 323
}

324 325 326
static void
set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
{
327
	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
328
	u32 vram_pages = drm->client.device.info.ram_size >> PAGE_SHIFT;
329
	unsigned i, fpfn, lpfn;
330

331
	if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
332
	    nvbo->mode && (type & TTM_PL_FLAG_VRAM) &&
333
	    nvbo->bo.mem.num_pages < vram_pages / 4) {
334 335 336 337 338 339
		/*
		 * Make sure that the color and depth buffers are handled
		 * by independent memory controller units. Up to a 9x
		 * speed up when alpha-blending and depth-test are enabled
		 * at the same time.
		 */
340
		if (nvbo->zeta) {
341 342
			fpfn = vram_pages / 2;
			lpfn = ~0;
343
		} else {
344 345 346 347 348 349 350 351 352 353
			fpfn = 0;
			lpfn = vram_pages / 2;
		}
		for (i = 0; i < nvbo->placement.num_placement; ++i) {
			nvbo->placements[i].fpfn = fpfn;
			nvbo->placements[i].lpfn = lpfn;
		}
		for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
			nvbo->busy_placements[i].fpfn = fpfn;
			nvbo->busy_placements[i].lpfn = lpfn;
354 355 356 357
		}
	}
}

358
void
359
nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy)
360
{
361
	struct ttm_placement *pl = &nvbo->placement;
362 363 364
	uint32_t flags = (nvbo->force_coherent ? TTM_PL_FLAG_UNCACHED :
						 TTM_PL_MASK_CACHING) |
			 (nvbo->pin_refcnt ? TTM_PL_FLAG_NO_EVICT : 0);
365 366 367 368 369 370 371 372

	pl->placement = nvbo->placements;
	set_placement_list(nvbo->placements, &pl->num_placement,
			   type, flags);

	pl->busy_placement = nvbo->busy_placements;
	set_placement_list(nvbo->busy_placements, &pl->num_busy_placement,
			   type | busy, flags);
373 374

	set_placement_range(nvbo, type);
375 376 377
}

int
378
nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig)
379
{
380
	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
381
	struct ttm_buffer_object *bo = &nvbo->bo;
382
	bool force = false, evict = false;
383
	int ret;
384

385
	ret = ttm_bo_reserve(bo, false, false, NULL);
386
	if (ret)
387
		return ret;
388

389
	if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
390
	    memtype == TTM_PL_FLAG_VRAM && contig) {
391 392
		if (!nvbo->contig) {
			nvbo->contig = true;
393
			force = true;
394
			evict = true;
395
		}
396 397
	}

398 399 400 401 402 403 404 405
	if (nvbo->pin_refcnt) {
		if (!(memtype & (1 << bo->mem.mem_type)) || evict) {
			NV_ERROR(drm, "bo %p pinned elsewhere: "
				      "0x%08x vs 0x%08x\n", bo,
				 1 << bo->mem.mem_type, memtype);
			ret = -EBUSY;
		}
		nvbo->pin_refcnt++;
406
		goto out;
407 408 409 410 411 412 413 414
	}

	if (evict) {
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT, 0);
		ret = nouveau_bo_validate(nvbo, false, false);
		if (ret)
			goto out;
	}
415

416
	nvbo->pin_refcnt++;
417
	nouveau_bo_placement_set(nvbo, memtype, 0);
418

419 420 421 422 423
	/* drop pin_refcnt temporarily, so we don't trip the assertion
	 * in nouveau_bo_move() that makes sure we're not trying to
	 * move a pinned buffer
	 */
	nvbo->pin_refcnt--;
424
	ret = nouveau_bo_validate(nvbo, false, false);
425 426
	if (ret)
		goto out;
427
	nvbo->pin_refcnt++;
428 429 430 431 432 433 434 435 436 437

	switch (bo->mem.mem_type) {
	case TTM_PL_VRAM:
		drm->gem.vram_available -= bo->mem.size;
		break;
	case TTM_PL_TT:
		drm->gem.gart_available -= bo->mem.size;
		break;
	default:
		break;
438
	}
439

440
out:
441
	if (force && ret)
442
		nvbo->contig = false;
443
	ttm_bo_unreserve(bo);
444 445 446 447 448 449
	return ret;
}

int
nouveau_bo_unpin(struct nouveau_bo *nvbo)
{
450
	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
451
	struct ttm_buffer_object *bo = &nvbo->bo;
452
	int ret, ref;
453

454
	ret = ttm_bo_reserve(bo, false, false, NULL);
455 456 457
	if (ret)
		return ret;

458 459 460
	ref = --nvbo->pin_refcnt;
	WARN_ON_ONCE(ref < 0);
	if (ref)
461 462
		goto out;

463
	nouveau_bo_placement_set(nvbo, bo->mem.placement, 0);
464

465
	ret = nouveau_bo_validate(nvbo, false, false);
466 467 468
	if (ret == 0) {
		switch (bo->mem.mem_type) {
		case TTM_PL_VRAM:
469
			drm->gem.vram_available += bo->mem.size;
470 471
			break;
		case TTM_PL_TT:
472
			drm->gem.gart_available += bo->mem.size;
473 474 475 476 477 478
			break;
		default:
			break;
		}
	}

479
out:
480 481 482 483 484 485 486 487 488
	ttm_bo_unreserve(bo);
	return ret;
}

int
nouveau_bo_map(struct nouveau_bo *nvbo)
{
	int ret;

489
	ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
490 491 492
	if (ret)
		return ret;

493
	ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, &nvbo->kmap);
494

495 496 497 498 499 500 501
	ttm_bo_unreserve(&nvbo->bo);
	return ret;
}

void
nouveau_bo_unmap(struct nouveau_bo *nvbo)
{
502 503 504
	if (!nvbo)
		return;

505
	ttm_bo_kunmap(&nvbo->kmap);
506 507
}

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
void
nouveau_bo_sync_for_device(struct nouveau_bo *nvbo)
{
	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
	struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm;
	int i;

	if (!ttm_dma)
		return;

	/* Don't waste time looping if the object is coherent */
	if (nvbo->force_coherent)
		return;

	for (i = 0; i < ttm_dma->ttm.num_pages; i++)
523 524
		dma_sync_single_for_device(drm->dev->dev,
					   ttm_dma->dma_address[i],
525
					   PAGE_SIZE, DMA_TO_DEVICE);
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
}

void
nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
{
	struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
	struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm;
	int i;

	if (!ttm_dma)
		return;

	/* Don't waste time looping if the object is coherent */
	if (nvbo->force_coherent)
		return;

	for (i = 0; i < ttm_dma->ttm.num_pages; i++)
543
		dma_sync_single_for_cpu(drm->dev->dev, ttm_dma->dma_address[i],
544
					PAGE_SIZE, DMA_FROM_DEVICE);
545 546
}

547 548
int
nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
549
		    bool no_wait_gpu)
550
{
551
	struct ttm_operation_ctx ctx = { interruptible, no_wait_gpu };
552 553
	int ret;

554
	ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, &ctx);
555 556 557
	if (ret)
		return ret;

558 559
	nouveau_bo_sync_for_device(nvbo);

560 561 562
	return 0;
}

563 564 565 566 567
void
nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val)
{
	bool is_iomem;
	u16 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
568

569
	mem += index;
570

571 572 573 574 575 576 577 578 579 580 581
	if (is_iomem)
		iowrite16_native(val, (void __force __iomem *)mem);
	else
		*mem = val;
}

u32
nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index)
{
	bool is_iomem;
	u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
582

583
	mem += index;
584

585 586 587 588 589 590 591 592 593 594 595
	if (is_iomem)
		return ioread32_native((void __force __iomem *)mem);
	else
		return *mem;
}

void
nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val)
{
	bool is_iomem;
	u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
596

597
	mem += index;
598

599 600 601 602 603 604
	if (is_iomem)
		iowrite32_native(val, (void __force __iomem *)mem);
	else
		*mem = val;
}

605
static struct ttm_tt *
606 607
nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
		      uint32_t page_flags, struct page *dummy_read)
608
{
D
Daniel Vetter 已提交
609
#if IS_ENABLED(CONFIG_AGP)
610
	struct nouveau_drm *drm = nouveau_bdev(bdev);
611

612 613
	if (drm->agp.bridge) {
		return ttm_agp_tt_create(bdev, drm->agp.bridge, size,
614
					 page_flags, dummy_read);
615
	}
616
#endif
617

618
	return nouveau_sgdma_create_ttm(bdev, size, page_flags, dummy_read);
619 620 621 622 623 624 625 626 627 628 629 630 631
}

static int
nouveau_bo_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags)
{
	/* We'll do this from user space. */
	return 0;
}

static int
nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
			 struct ttm_mem_type_manager *man)
{
632
	struct nouveau_drm *drm = nouveau_bdev(bdev);
633
	struct nvif_mmu *mmu = &drm->client.mmu;
634 635 636 637 638 639 640 641

	switch (type) {
	case TTM_PL_SYSTEM:
		man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
		man->available_caching = TTM_PL_MASK_CACHING;
		man->default_caching = TTM_PL_FLAG_CACHED;
		break;
	case TTM_PL_VRAM:
642 643 644 645 646 647
		man->flags = TTM_MEMTYPE_FLAG_FIXED |
			     TTM_MEMTYPE_FLAG_MAPPABLE;
		man->available_caching = TTM_PL_FLAG_UNCACHED |
					 TTM_PL_FLAG_WC;
		man->default_caching = TTM_PL_FLAG_WC;

648
		if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
649
			/* Some BARs do not support being ioremapped WC */
650 651
			const u8 type = mmu->type[drm->ttm.type_vram].type;
			if (type & NVIF_MEM_UNCACHED) {
652 653 654 655
				man->available_caching = TTM_PL_FLAG_UNCACHED;
				man->default_caching = TTM_PL_FLAG_UNCACHED;
			}

B
Ben Skeggs 已提交
656
			man->func = &nouveau_vram_manager;
657 658 659
			man->io_reserve_fastpath = false;
			man->use_io_reserve_lru = true;
		} else {
B
Ben Skeggs 已提交
660
			man->func = &ttm_bo_manager_func;
661
		}
662 663
		break;
	case TTM_PL_TT:
664
		if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA)
665
			man->func = &nouveau_gart_manager;
666
		else
667
		if (!drm->agp.bridge)
668
			man->func = &nv04_gart_manager;
669 670
		else
			man->func = &ttm_bo_manager_func;
671

672
		if (drm->agp.bridge) {
673
			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
674 675 676
			man->available_caching = TTM_PL_FLAG_UNCACHED |
				TTM_PL_FLAG_WC;
			man->default_caching = TTM_PL_FLAG_WC;
677
		} else {
678 679 680 681 682
			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
				     TTM_MEMTYPE_FLAG_CMA;
			man->available_caching = TTM_PL_MASK_CACHING;
			man->default_caching = TTM_PL_FLAG_CACHED;
		}
683

684 685 686 687 688 689 690 691 692 693 694 695 696
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

static void
nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
{
	struct nouveau_bo *nvbo = nouveau_bo(bo);

	switch (bo->mem.mem_type) {
697
	case TTM_PL_VRAM:
698 699
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT,
					 TTM_PL_FLAG_SYSTEM);
700
		break;
701
	default:
702
		nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM, 0);
703 704
		break;
	}
705 706

	*pl = nvbo->placement;
707 708 709
}


710 711 712 713 714 715
static int
nve0_bo_move_init(struct nouveau_channel *chan, u32 handle)
{
	int ret = RING_SPACE(chan, 2);
	if (ret == 0) {
		BEGIN_NVC0(chan, NvSubCopy, 0x0000, 1);
716
		OUT_RING  (chan, handle & 0x0000ffff);
717 718 719 720 721
		FIRE_RING (chan);
	}
	return ret;
}

722 723
static int
nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
724
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
725
{
726
	struct nouveau_mem *mem = nouveau_mem(old_reg);
727 728
	int ret = RING_SPACE(chan, 10);
	if (ret == 0) {
729
		BEGIN_NVC0(chan, NvSubCopy, 0x0400, 8);
730 731 732 733
		OUT_RING  (chan, upper_32_bits(mem->vma[0].addr));
		OUT_RING  (chan, lower_32_bits(mem->vma[0].addr));
		OUT_RING  (chan, upper_32_bits(mem->vma[1].addr));
		OUT_RING  (chan, lower_32_bits(mem->vma[1].addr));
734 735 736
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, PAGE_SIZE);
737
		OUT_RING  (chan, new_reg->num_pages);
738
		BEGIN_IMC0(chan, NvSubCopy, 0x0300, 0x0386);
739 740 741 742
	}
	return ret;
}

743 744 745 746 747 748 749 750 751 752 753
static int
nvc0_bo_move_init(struct nouveau_channel *chan, u32 handle)
{
	int ret = RING_SPACE(chan, 2);
	if (ret == 0) {
		BEGIN_NVC0(chan, NvSubCopy, 0x0000, 1);
		OUT_RING  (chan, handle);
	}
	return ret;
}

754 755
static int
nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
756
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
757
{
758 759 760
	struct nouveau_mem *mem = nouveau_mem(old_reg);
	u64 src_offset = mem->vma[0].addr;
	u64 dst_offset = mem->vma[1].addr;
761
	u32 page_count = new_reg->num_pages;
762 763
	int ret;

764
	page_count = new_reg->num_pages;
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
	while (page_count) {
		int line_count = (page_count > 8191) ? 8191 : page_count;

		ret = RING_SPACE(chan, 11);
		if (ret)
			return ret;

		BEGIN_NVC0(chan, NvSubCopy, 0x030c, 8);
		OUT_RING  (chan, upper_32_bits(src_offset));
		OUT_RING  (chan, lower_32_bits(src_offset));
		OUT_RING  (chan, upper_32_bits(dst_offset));
		OUT_RING  (chan, lower_32_bits(dst_offset));
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, line_count);
		BEGIN_NVC0(chan, NvSubCopy, 0x0300, 1);
		OUT_RING  (chan, 0x00000110);

		page_count -= line_count;
		src_offset += (PAGE_SIZE * line_count);
		dst_offset += (PAGE_SIZE * line_count);
	}

	return 0;
}

B
Ben Skeggs 已提交
792 793
static int
nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
794
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
B
Ben Skeggs 已提交
795
{
796 797 798
	struct nouveau_mem *mem = nouveau_mem(old_reg);
	u64 src_offset = mem->vma[0].addr;
	u64 dst_offset = mem->vma[1].addr;
799
	u32 page_count = new_reg->num_pages;
B
Ben Skeggs 已提交
800 801
	int ret;

802
	page_count = new_reg->num_pages;
B
Ben Skeggs 已提交
803 804 805 806 807 808 809
	while (page_count) {
		int line_count = (page_count > 2047) ? 2047 : page_count;

		ret = RING_SPACE(chan, 12);
		if (ret)
			return ret;

810
		BEGIN_NVC0(chan, NvSubCopy, 0x0238, 2);
B
Ben Skeggs 已提交
811 812
		OUT_RING  (chan, upper_32_bits(dst_offset));
		OUT_RING  (chan, lower_32_bits(dst_offset));
813
		BEGIN_NVC0(chan, NvSubCopy, 0x030c, 6);
B
Ben Skeggs 已提交
814 815 816 817 818 819
		OUT_RING  (chan, upper_32_bits(src_offset));
		OUT_RING  (chan, lower_32_bits(src_offset));
		OUT_RING  (chan, PAGE_SIZE); /* src_pitch */
		OUT_RING  (chan, PAGE_SIZE); /* dst_pitch */
		OUT_RING  (chan, PAGE_SIZE); /* line_length */
		OUT_RING  (chan, line_count);
820
		BEGIN_NVC0(chan, NvSubCopy, 0x0300, 1);
B
Ben Skeggs 已提交
821 822 823 824 825 826 827 828 829 830
		OUT_RING  (chan, 0x00100110);

		page_count -= line_count;
		src_offset += (PAGE_SIZE * line_count);
		dst_offset += (PAGE_SIZE * line_count);
	}

	return 0;
}

831 832
static int
nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
833
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
834
{
835 836 837
	struct nouveau_mem *mem = nouveau_mem(old_reg);
	u64 src_offset = mem->vma[0].addr;
	u64 dst_offset = mem->vma[1].addr;
838
	u32 page_count = new_reg->num_pages;
839 840
	int ret;

841
	page_count = new_reg->num_pages;
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
	while (page_count) {
		int line_count = (page_count > 8191) ? 8191 : page_count;

		ret = RING_SPACE(chan, 11);
		if (ret)
			return ret;

		BEGIN_NV04(chan, NvSubCopy, 0x030c, 8);
		OUT_RING  (chan, upper_32_bits(src_offset));
		OUT_RING  (chan, lower_32_bits(src_offset));
		OUT_RING  (chan, upper_32_bits(dst_offset));
		OUT_RING  (chan, lower_32_bits(dst_offset));
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, PAGE_SIZE);
		OUT_RING  (chan, line_count);
		BEGIN_NV04(chan, NvSubCopy, 0x0300, 1);
		OUT_RING  (chan, 0x00000110);

		page_count -= line_count;
		src_offset += (PAGE_SIZE * line_count);
		dst_offset += (PAGE_SIZE * line_count);
	}

	return 0;
}

869 870
static int
nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
871
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
872
{
873
	struct nouveau_mem *mem = nouveau_mem(old_reg);
874 875 876
	int ret = RING_SPACE(chan, 7);
	if (ret == 0) {
		BEGIN_NV04(chan, NvSubCopy, 0x0320, 6);
877 878 879 880
		OUT_RING  (chan, upper_32_bits(mem->vma[0].addr));
		OUT_RING  (chan, lower_32_bits(mem->vma[0].addr));
		OUT_RING  (chan, upper_32_bits(mem->vma[1].addr));
		OUT_RING  (chan, lower_32_bits(mem->vma[1].addr));
881
		OUT_RING  (chan, 0x00000000 /* COPY */);
882
		OUT_RING  (chan, new_reg->num_pages << PAGE_SHIFT);
883 884 885 886
	}
	return ret;
}

887 888
static int
nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
889
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
890
{
891
	struct nouveau_mem *mem = nouveau_mem(old_reg);
892 893 894
	int ret = RING_SPACE(chan, 7);
	if (ret == 0) {
		BEGIN_NV04(chan, NvSubCopy, 0x0304, 6);
895
		OUT_RING  (chan, new_reg->num_pages << PAGE_SHIFT);
896 897 898 899
		OUT_RING  (chan, upper_32_bits(mem->vma[0].addr));
		OUT_RING  (chan, lower_32_bits(mem->vma[0].addr));
		OUT_RING  (chan, upper_32_bits(mem->vma[1].addr));
		OUT_RING  (chan, lower_32_bits(mem->vma[1].addr));
900 901 902 903 904
		OUT_RING  (chan, 0x00000000 /* MODE_COPY, QUERY_NONE */);
	}
	return ret;
}

905 906 907
static int
nv50_bo_move_init(struct nouveau_channel *chan, u32 handle)
{
908
	int ret = RING_SPACE(chan, 6);
909
	if (ret == 0) {
910 911 912
		BEGIN_NV04(chan, NvSubCopy, 0x0000, 1);
		OUT_RING  (chan, handle);
		BEGIN_NV04(chan, NvSubCopy, 0x0180, 3);
913 914 915
		OUT_RING  (chan, chan->drm->ntfy.handle);
		OUT_RING  (chan, chan->vram.handle);
		OUT_RING  (chan, chan->vram.handle);
916 917 918 919 920
	}

	return ret;
}

921
static int
922
nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
923
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
924
{
925
	struct nouveau_mem *mem = nouveau_mem(old_reg);
926
	u64 length = (new_reg->num_pages << PAGE_SHIFT);
927 928 929 930
	u64 src_offset = mem->vma[0].addr;
	u64 dst_offset = mem->vma[1].addr;
	int src_tiled = !!mem->kind;
	int dst_tiled = !!nouveau_mem(new_reg)->kind;
931 932
	int ret;

933 934 935
	while (length) {
		u32 amount, stride, height;

936 937 938 939
		ret = RING_SPACE(chan, 18 + 6 * (src_tiled + dst_tiled));
		if (ret)
			return ret;

940 941
		amount  = min(length, (u64)(4 * 1024 * 1024));
		stride  = 16 * 4;
942 943
		height  = amount / stride;

944
		if (src_tiled) {
945
			BEGIN_NV04(chan, NvSubCopy, 0x0200, 7);
946
			OUT_RING  (chan, 0);
947
			OUT_RING  (chan, 0);
948 949 950 951 952 953
			OUT_RING  (chan, stride);
			OUT_RING  (chan, height);
			OUT_RING  (chan, 1);
			OUT_RING  (chan, 0);
			OUT_RING  (chan, 0);
		} else {
954
			BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
955 956
			OUT_RING  (chan, 1);
		}
957
		if (dst_tiled) {
958
			BEGIN_NV04(chan, NvSubCopy, 0x021c, 7);
959
			OUT_RING  (chan, 0);
960
			OUT_RING  (chan, 0);
961 962 963 964 965 966
			OUT_RING  (chan, stride);
			OUT_RING  (chan, height);
			OUT_RING  (chan, 1);
			OUT_RING  (chan, 0);
			OUT_RING  (chan, 0);
		} else {
967
			BEGIN_NV04(chan, NvSubCopy, 0x021c, 1);
968 969 970
			OUT_RING  (chan, 1);
		}

971
		BEGIN_NV04(chan, NvSubCopy, 0x0238, 2);
972 973
		OUT_RING  (chan, upper_32_bits(src_offset));
		OUT_RING  (chan, upper_32_bits(dst_offset));
974
		BEGIN_NV04(chan, NvSubCopy, 0x030c, 8);
975 976 977 978 979 980 981 982
		OUT_RING  (chan, lower_32_bits(src_offset));
		OUT_RING  (chan, lower_32_bits(dst_offset));
		OUT_RING  (chan, stride);
		OUT_RING  (chan, stride);
		OUT_RING  (chan, stride);
		OUT_RING  (chan, height);
		OUT_RING  (chan, 0x00000101);
		OUT_RING  (chan, 0x00000000);
983
		BEGIN_NV04(chan, NvSubCopy, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
984 985 986 987 988
		OUT_RING  (chan, 0);

		length -= amount;
		src_offset += amount;
		dst_offset += amount;
989 990
	}

991 992 993
	return 0;
}

994 995 996
static int
nv04_bo_move_init(struct nouveau_channel *chan, u32 handle)
{
997
	int ret = RING_SPACE(chan, 4);
998
	if (ret == 0) {
999 1000 1001
		BEGIN_NV04(chan, NvSubCopy, 0x0000, 1);
		OUT_RING  (chan, handle);
		BEGIN_NV04(chan, NvSubCopy, 0x0180, 1);
1002
		OUT_RING  (chan, chan->drm->ntfy.handle);
1003 1004 1005 1006 1007
	}

	return ret;
}

1008 1009
static inline uint32_t
nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
1010
		      struct nouveau_channel *chan, struct ttm_mem_reg *reg)
1011
{
1012
	if (reg->mem_type == TTM_PL_TT)
1013
		return NvDmaTT;
1014
	return chan->vram.handle;
1015 1016
}

1017 1018
static int
nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
1019
		  struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg)
1020
{
1021 1022 1023
	u32 src_offset = old_reg->start << PAGE_SHIFT;
	u32 dst_offset = new_reg->start << PAGE_SHIFT;
	u32 page_count = new_reg->num_pages;
1024 1025 1026 1027 1028 1029
	int ret;

	ret = RING_SPACE(chan, 3);
	if (ret)
		return ret;

1030
	BEGIN_NV04(chan, NvSubCopy, NV_MEMORY_TO_MEMORY_FORMAT_DMA_SOURCE, 2);
1031 1032
	OUT_RING  (chan, nouveau_bo_mem_ctxdma(bo, chan, old_reg));
	OUT_RING  (chan, nouveau_bo_mem_ctxdma(bo, chan, new_reg));
1033

1034
	page_count = new_reg->num_pages;
1035 1036 1037 1038 1039 1040
	while (page_count) {
		int line_count = (page_count > 2047) ? 2047 : page_count;

		ret = RING_SPACE(chan, 11);
		if (ret)
			return ret;
1041

1042
		BEGIN_NV04(chan, NvSubCopy,
1043
				 NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
1044 1045 1046 1047 1048 1049 1050 1051
		OUT_RING  (chan, src_offset);
		OUT_RING  (chan, dst_offset);
		OUT_RING  (chan, PAGE_SIZE); /* src_pitch */
		OUT_RING  (chan, PAGE_SIZE); /* dst_pitch */
		OUT_RING  (chan, PAGE_SIZE); /* line_length */
		OUT_RING  (chan, line_count);
		OUT_RING  (chan, 0x00000101);
		OUT_RING  (chan, 0x00000000);
1052
		BEGIN_NV04(chan, NvSubCopy, NV_MEMORY_TO_MEMORY_FORMAT_NOP, 1);
1053
		OUT_RING  (chan, 0);
1054 1055 1056 1057 1058 1059

		page_count -= line_count;
		src_offset += (PAGE_SIZE * line_count);
		dst_offset += (PAGE_SIZE * line_count);
	}

1060 1061 1062
	return 0;
}

1063
static int
1064
nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
1065
		     struct ttm_mem_reg *reg)
1066
{
1067 1068
	struct nouveau_mem *old_mem = nouveau_mem(&bo->mem);
	struct nouveau_mem *new_mem = nouveau_mem(reg);
1069
	struct nvif_vmm *vmm = &drm->client.vmm.vmm;
1070 1071
	int ret;

1072 1073
	ret = nvif_vmm_get(vmm, LAZY, false, old_mem->mem.page, 0,
			   old_mem->mem.size, &old_mem->vma[0]);
1074 1075 1076
	if (ret)
		return ret;

1077 1078 1079 1080
	ret = nvif_vmm_get(vmm, LAZY, false, new_mem->mem.page, 0,
			   new_mem->mem.size, &old_mem->vma[1]);
	if (ret)
		goto done;
1081

1082 1083 1084 1085 1086 1087 1088
	ret = nouveau_mem_map(old_mem, vmm, &old_mem->vma[0]);
	if (ret)
		goto done;

	ret = nouveau_mem_map(new_mem, vmm, &old_mem->vma[1]);
done:
	if (ret) {
1089 1090
		nvif_vmm_put(vmm, &old_mem->vma[1]);
		nvif_vmm_put(vmm, &old_mem->vma[0]);
1091
	}
1092 1093 1094
	return 0;
}

1095 1096
static int
nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, bool intr,
1097
		     bool no_wait_gpu, struct ttm_mem_reg *new_reg)
1098
{
1099
	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1100
	struct nouveau_channel *chan = drm->ttm.chan;
1101
	struct nouveau_cli *cli = (void *)chan->user.client;
1102
	struct nouveau_fence *fence;
1103 1104
	int ret;

1105
	/* create temporary vmas for the transfer and attach them to the
1106
	 * old nvkm_mem node, these will get cleaned up after ttm has
1107
	 * destroyed the ttm_mem_reg
1108
	 */
1109
	if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
1110
		ret = nouveau_bo_move_prep(drm, bo, new_reg);
1111
		if (ret)
1112
			return ret;
1113 1114
	}

1115
	mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
1116
	ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, intr);
1117
	if (ret == 0) {
1118
		ret = drm->ttm.move(chan, bo, &bo->mem, new_reg);
1119 1120 1121
		if (ret == 0) {
			ret = nouveau_fence_new(chan, false, &fence);
			if (ret == 0) {
1122 1123
				ret = ttm_bo_move_accel_cleanup(bo,
								&fence->base,
1124
								evict,
1125
								new_reg);
1126 1127 1128
				nouveau_fence_unref(&fence);
			}
		}
1129
	}
1130
	mutex_unlock(&cli->mutex);
1131
	return ret;
1132 1133
}

1134
void
1135
nouveau_bo_move_init(struct nouveau_drm *drm)
1136 1137 1138
{
	static const struct {
		const char *name;
1139
		int engine;
1140
		s32 oclass;
1141 1142 1143 1144 1145
		int (*exec)(struct nouveau_channel *,
			    struct ttm_buffer_object *,
			    struct ttm_mem_reg *, struct ttm_mem_reg *);
		int (*init)(struct nouveau_channel *, u32 handle);
	} _methods[] = {
1146 1147
		{  "COPY", 4, 0xc1b5, nve0_bo_move_copy, nve0_bo_move_init },
		{  "GRCE", 0, 0xc1b5, nve0_bo_move_copy, nvc0_bo_move_init },
1148 1149
		{  "COPY", 4, 0xc0b5, nve0_bo_move_copy, nve0_bo_move_init },
		{  "GRCE", 0, 0xc0b5, nve0_bo_move_copy, nvc0_bo_move_init },
1150 1151
		{  "COPY", 4, 0xb0b5, nve0_bo_move_copy, nve0_bo_move_init },
		{  "GRCE", 0, 0xb0b5, nve0_bo_move_copy, nvc0_bo_move_init },
1152
		{  "COPY", 4, 0xa0b5, nve0_bo_move_copy, nve0_bo_move_init },
1153
		{  "GRCE", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init },
1154 1155 1156 1157 1158 1159 1160
		{ "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init },
		{ "COPY0", 4, 0x90b5, nvc0_bo_move_copy, nvc0_bo_move_init },
		{  "COPY", 0, 0x85b5, nva3_bo_move_copy, nv50_bo_move_init },
		{ "CRYPT", 0, 0x74c1, nv84_bo_move_exec, nv50_bo_move_init },
		{  "M2MF", 0, 0x9039, nvc0_bo_move_m2mf, nvc0_bo_move_init },
		{  "M2MF", 0, 0x5039, nv50_bo_move_m2mf, nv50_bo_move_init },
		{  "M2MF", 0, 0x0039, nv04_bo_move_m2mf, nv04_bo_move_init },
1161
		{},
1162
		{ "CRYPT", 0, 0x88b4, nv98_bo_move_exec, nv50_bo_move_init },
1163 1164 1165 1166 1167
	}, *mthd = _methods;
	const char *name = "CPU";
	int ret;

	do {
1168
		struct nouveau_channel *chan;
1169

1170
		if (mthd->engine)
1171 1172 1173 1174 1175 1176
			chan = drm->cechan;
		else
			chan = drm->channel;
		if (chan == NULL)
			continue;

1177
		ret = nvif_object_init(&chan->user,
1178 1179 1180
				       mthd->oclass | (mthd->engine << 16),
				       mthd->oclass, NULL, 0,
				       &drm->ttm.copy);
1181
		if (ret == 0) {
1182
			ret = mthd->init(chan, drm->ttm.copy.handle);
1183
			if (ret) {
1184
				nvif_object_fini(&drm->ttm.copy);
1185
				continue;
1186
			}
1187 1188

			drm->ttm.move = mthd->exec;
1189
			drm->ttm.chan = chan;
1190 1191
			name = mthd->name;
			break;
1192 1193 1194
		}
	} while ((++mthd)->exec);

1195
	NV_INFO(drm, "MM: using %s for buffer copies\n", name);
1196 1197
}

1198 1199
static int
nouveau_bo_move_flipd(struct ttm_buffer_object *bo, bool evict, bool intr,
1200
		      bool no_wait_gpu, struct ttm_mem_reg *new_reg)
1201
{
1202
	struct ttm_operation_ctx ctx = { intr, no_wait_gpu };
1203 1204 1205 1206 1207
	struct ttm_place placement_memtype = {
		.fpfn = 0,
		.lpfn = 0,
		.flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING
	};
1208
	struct ttm_placement placement;
1209
	struct ttm_mem_reg tmp_reg;
1210 1211 1212
	int ret;

	placement.num_placement = placement.num_busy_placement = 1;
1213
	placement.placement = placement.busy_placement = &placement_memtype;
1214

1215 1216
	tmp_reg = *new_reg;
	tmp_reg.mm_node = NULL;
1217
	ret = ttm_bo_mem_space(bo, &placement, &tmp_reg, &ctx);
1218 1219 1220
	if (ret)
		return ret;

1221
	ret = ttm_tt_bind(bo->ttm, &tmp_reg);
1222 1223 1224
	if (ret)
		goto out;

1225
	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, &tmp_reg);
1226 1227 1228
	if (ret)
		goto out;

1229
	ret = ttm_bo_move_ttm(bo, intr, no_wait_gpu, new_reg);
1230
out:
1231
	ttm_bo_mem_put(bo, &tmp_reg);
1232 1233 1234 1235 1236
	return ret;
}

static int
nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr,
1237
		      bool no_wait_gpu, struct ttm_mem_reg *new_reg)
1238
{
1239
	struct ttm_operation_ctx ctx = { intr, no_wait_gpu };
1240 1241 1242 1243 1244
	struct ttm_place placement_memtype = {
		.fpfn = 0,
		.lpfn = 0,
		.flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING
	};
1245
	struct ttm_placement placement;
1246
	struct ttm_mem_reg tmp_reg;
1247 1248 1249
	int ret;

	placement.num_placement = placement.num_busy_placement = 1;
1250
	placement.placement = placement.busy_placement = &placement_memtype;
1251

1252 1253
	tmp_reg = *new_reg;
	tmp_reg.mm_node = NULL;
1254
	ret = ttm_bo_mem_space(bo, &placement, &tmp_reg, &ctx);
1255 1256 1257
	if (ret)
		return ret;

1258
	ret = ttm_bo_move_ttm(bo, intr, no_wait_gpu, &tmp_reg);
1259 1260 1261
	if (ret)
		goto out;

1262
	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_gpu, new_reg);
1263 1264 1265 1266
	if (ret)
		goto out;

out:
1267
	ttm_bo_mem_put(bo, &tmp_reg);
1268 1269 1270
	return ret;
}

1271
static void
1272
nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict,
1273
		     struct ttm_mem_reg *new_reg)
1274
{
1275
	struct nouveau_mem *mem = new_reg ? nouveau_mem(new_reg) : NULL;
1276
	struct nouveau_bo *nvbo = nouveau_bo(bo);
1277
	struct nouveau_vma *vma;
1278

1279 1280 1281 1282
	/* ttm can now (stupidly) pass the driver bos it didn't create... */
	if (bo->destroy != nouveau_bo_del_ttm)
		return;

1283
	if (mem && new_reg->mem_type != TTM_PL_SYSTEM &&
1284
	    mem->mem.page == nvbo->page) {
1285
		list_for_each_entry(vma, &nvbo->vma_list, head) {
1286
			nouveau_vma_map(vma, mem);
1287 1288 1289
		}
	} else {
		list_for_each_entry(vma, &nvbo->vma_list, head) {
1290
			WARN_ON(ttm_bo_wait(bo, false, false));
1291
			nouveau_vma_unmap(vma);
1292
		}
1293 1294 1295
	}
}

1296
static int
1297
nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_reg,
1298
		   struct nouveau_drm_tile **new_tile)
1299
{
1300 1301
	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
	struct drm_device *dev = drm->dev;
1302
	struct nouveau_bo *nvbo = nouveau_bo(bo);
1303
	u64 offset = new_reg->start << PAGE_SHIFT;
1304

1305
	*new_tile = NULL;
1306
	if (new_reg->mem_type != TTM_PL_VRAM)
1307 1308
		return 0;

1309
	if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
1310
		*new_tile = nv10_bo_set_tiling(dev, offset, new_reg->size,
1311
					       nvbo->mode, nvbo->zeta);
1312 1313
	}

1314 1315 1316 1317 1318
	return 0;
}

static void
nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
1319 1320
		      struct nouveau_drm_tile *new_tile,
		      struct nouveau_drm_tile **old_tile)
1321
{
1322 1323
	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
	struct drm_device *dev = drm->dev;
1324
	struct dma_fence *fence = reservation_object_get_excl(bo->resv);
1325

1326
	nv10_bo_put_tile_region(dev, *old_tile, fence);
1327
	*old_tile = new_tile;
1328 1329 1330
}

static int
1331 1332 1333
nouveau_bo_move(struct ttm_buffer_object *bo, bool evict,
		struct ttm_operation_ctx *ctx,
		struct ttm_mem_reg *new_reg)
1334
{
1335
	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1336
	struct nouveau_bo *nvbo = nouveau_bo(bo);
1337
	struct ttm_mem_reg *old_reg = &bo->mem;
1338
	struct nouveau_drm_tile *new_tile = NULL;
1339 1340
	int ret = 0;

1341
	ret = ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu);
1342 1343 1344
	if (ret)
		return ret;

1345 1346 1347
	if (nvbo->pin_refcnt)
		NV_WARN(drm, "Moving pinned object %p!\n", nvbo);

1348
	if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
1349
		ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile);
1350 1351 1352
		if (ret)
			return ret;
	}
1353 1354

	/* Fake bo copy. */
1355
	if (old_reg->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
1356
		BUG_ON(bo->mem.mm_node != NULL);
1357 1358
		bo->mem = *new_reg;
		new_reg->mm_node = NULL;
1359
		goto out;
1360 1361
	}

1362
	/* Hardware assisted copy. */
1363
	if (drm->ttm.move) {
1364
		if (new_reg->mem_type == TTM_PL_SYSTEM)
1365 1366 1367
			ret = nouveau_bo_move_flipd(bo, evict,
						    ctx->interruptible,
						    ctx->no_wait_gpu, new_reg);
1368
		else if (old_reg->mem_type == TTM_PL_SYSTEM)
1369 1370 1371
			ret = nouveau_bo_move_flips(bo, evict,
						    ctx->interruptible,
						    ctx->no_wait_gpu, new_reg);
1372
		else
1373 1374 1375
			ret = nouveau_bo_move_m2mf(bo, evict,
						   ctx->interruptible,
						   ctx->no_wait_gpu, new_reg);
1376 1377 1378
		if (!ret)
			goto out;
	}
1379 1380

	/* Fallback to software copy. */
1381
	ret = ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu);
1382
	if (ret == 0)
1383 1384
		ret = ttm_bo_move_memcpy(bo, ctx->interruptible,
					 ctx->no_wait_gpu, new_reg);
1385 1386

out:
1387
	if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
1388 1389 1390 1391 1392
		if (ret)
			nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
		else
			nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
	}
1393 1394

	return ret;
1395 1396 1397 1398 1399
}

static int
nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
{
1400 1401
	struct nouveau_bo *nvbo = nouveau_bo(bo);

D
David Herrmann 已提交
1402 1403
	return drm_vma_node_verify_access(&nvbo->gem.vma_node,
					  filp->private_data);
1404 1405
}

1406
static int
1407
nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1408
{
1409
	struct ttm_mem_type_manager *man = &bdev->man[reg->mem_type];
1410
	struct nouveau_drm *drm = nouveau_bdev(bdev);
1411
	struct nvkm_device *device = nvxx_device(&drm->client.device);
1412
	struct nouveau_mem *mem = nouveau_mem(reg);
1413

1414 1415 1416 1417 1418
	reg->bus.addr = NULL;
	reg->bus.offset = 0;
	reg->bus.size = reg->num_pages << PAGE_SHIFT;
	reg->bus.base = 0;
	reg->bus.is_iomem = false;
1419 1420
	if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
		return -EINVAL;
1421
	switch (reg->mem_type) {
1422 1423 1424 1425
	case TTM_PL_SYSTEM:
		/* System memory */
		return 0;
	case TTM_PL_TT:
D
Daniel Vetter 已提交
1426
#if IS_ENABLED(CONFIG_AGP)
1427
		if (drm->agp.bridge) {
1428 1429 1430
			reg->bus.offset = reg->start << PAGE_SHIFT;
			reg->bus.base = drm->agp.base;
			reg->bus.is_iomem = !drm->agp.cma;
1431 1432
		}
#endif
1433
		if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 || !mem->kind)
1434 1435 1436
			/* untiled */
			break;
		/* fallthrough, tiled memory */
1437
	case TTM_PL_VRAM:
1438 1439 1440
		reg->bus.offset = reg->start << PAGE_SHIFT;
		reg->bus.base = device->func->resource_addr(device, 1);
		reg->bus.is_iomem = true;
1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
		if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
			union {
				struct nv50_mem_map_v0 nv50;
				struct gf100_mem_map_v0 gf100;
			} args;
			u64 handle, length;
			u32 argc = 0;
			int ret;

			switch (mem->mem.object.oclass) {
			case NVIF_CLASS_MEM_NV50:
				args.nv50.version = 0;
				args.nv50.ro = 0;
				args.nv50.kind = mem->kind;
				args.nv50.comp = mem->comp;
				break;
			case NVIF_CLASS_MEM_GF100:
				args.gf100.version = 0;
				args.gf100.ro = 0;
				args.gf100.kind = mem->kind;
				break;
			default:
				WARN_ON(1);
				break;
			}

			ret = nvif_object_map_handle(&mem->mem.object,
						     &argc, argc,
						     &handle, &length);
			if (ret != 1)
				return ret ? ret : -EINVAL;

			reg->bus.base = 0;
			reg->bus.offset = handle;
1475
		}
1476 1477 1478 1479 1480 1481 1482 1483
		break;
	default:
		return -EINVAL;
	}
	return 0;
}

static void
1484
nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg)
1485
{
1486
	struct nouveau_drm *drm = nouveau_bdev(bdev);
1487
	struct nouveau_mem *mem = nouveau_mem(reg);
1488

1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501
	if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
		switch (reg->mem_type) {
		case TTM_PL_TT:
			if (mem->kind)
				nvif_object_unmap_handle(&mem->mem.object);
			break;
		case TTM_PL_VRAM:
			nvif_object_unmap_handle(&mem->mem.object);
			break;
		default:
			break;
		}
	}
1502 1503 1504 1505 1506
}

static int
nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
{
1507
	struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1508
	struct nouveau_bo *nvbo = nouveau_bo(bo);
1509
	struct nvkm_device *device = nvxx_device(&drm->client.device);
1510
	u32 mappable = device->func->resource_size(device, 1) >> PAGE_SHIFT;
1511
	int i, ret;
1512 1513 1514 1515 1516

	/* as long as the bo isn't in vram, and isn't tiled, we've got
	 * nothing to do here.
	 */
	if (bo->mem.mem_type != TTM_PL_VRAM) {
1517
		if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA ||
1518
		    !nvbo->kind)
1519
			return 0;
1520 1521 1522 1523 1524 1525 1526 1527 1528

		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
			nouveau_bo_placement_set(nvbo, TTM_PL_TT, 0);

			ret = nouveau_bo_validate(nvbo, false, false);
			if (ret)
				return ret;
		}
		return 0;
1529 1530 1531
	}

	/* make sure bo is in mappable vram */
1532
	if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA ||
1533
	    bo->mem.start + bo->mem.num_pages < mappable)
1534 1535
		return 0;

1536 1537 1538 1539 1540 1541 1542 1543 1544
	for (i = 0; i < nvbo->placement.num_placement; ++i) {
		nvbo->placements[i].fpfn = 0;
		nvbo->placements[i].lpfn = mappable;
	}

	for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
		nvbo->busy_placements[i].fpfn = 0;
		nvbo->busy_placements[i].lpfn = mappable;
	}
1545

1546
	nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_VRAM, 0);
1547
	return nouveau_bo_validate(nvbo, false, false);
1548 1549
}

1550 1551 1552
static int
nouveau_ttm_tt_populate(struct ttm_tt *ttm)
{
1553
	struct ttm_dma_tt *ttm_dma = (void *)ttm;
1554
	struct nouveau_drm *drm;
1555
	struct device *dev;
1556 1557
	unsigned i;
	int r;
D
Dave Airlie 已提交
1558
	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
1559 1560 1561 1562

	if (ttm->state != tt_unpopulated)
		return 0;

D
Dave Airlie 已提交
1563 1564 1565 1566 1567 1568 1569 1570
	if (slave && ttm->sg) {
		/* make userspace faulting work */
		drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
						 ttm_dma->dma_address, ttm->num_pages);
		ttm->state = tt_unbound;
		return 0;
	}

1571
	drm = nouveau_bdev(ttm->bdev);
1572
	dev = drm->dev->dev;
1573

D
Daniel Vetter 已提交
1574
#if IS_ENABLED(CONFIG_AGP)
1575
	if (drm->agp.bridge) {
J
Jerome Glisse 已提交
1576 1577 1578 1579
		return ttm_agp_tt_populate(ttm);
	}
#endif

1580
#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86)
1581
	if (swiotlb_nr_tbl()) {
1582
		return ttm_dma_populate((void *)ttm, dev);
1583 1584 1585 1586 1587 1588 1589 1590 1591
	}
#endif

	r = ttm_pool_populate(ttm);
	if (r) {
		return r;
	}

	for (i = 0; i < ttm->num_pages; i++) {
1592 1593
		dma_addr_t addr;

1594
		addr = dma_map_page(dev, ttm->pages[i], 0, PAGE_SIZE,
1595 1596
				    DMA_BIDIRECTIONAL);

1597
		if (dma_mapping_error(dev, addr)) {
1598
			while (i--) {
1599
				dma_unmap_page(dev, ttm_dma->dma_address[i],
1600
					       PAGE_SIZE, DMA_BIDIRECTIONAL);
1601
				ttm_dma->dma_address[i] = 0;
1602 1603 1604 1605
			}
			ttm_pool_unpopulate(ttm);
			return -EFAULT;
		}
1606 1607

		ttm_dma->dma_address[i] = addr;
1608 1609 1610 1611 1612 1613 1614
	}
	return 0;
}

static void
nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
{
1615
	struct ttm_dma_tt *ttm_dma = (void *)ttm;
1616
	struct nouveau_drm *drm;
1617
	struct device *dev;
1618
	unsigned i;
D
Dave Airlie 已提交
1619 1620 1621 1622
	bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);

	if (slave)
		return;
1623

1624
	drm = nouveau_bdev(ttm->bdev);
1625
	dev = drm->dev->dev;
1626

D
Daniel Vetter 已提交
1627
#if IS_ENABLED(CONFIG_AGP)
1628
	if (drm->agp.bridge) {
J
Jerome Glisse 已提交
1629 1630 1631 1632 1633
		ttm_agp_tt_unpopulate(ttm);
		return;
	}
#endif

1634
#if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86)
1635
	if (swiotlb_nr_tbl()) {
1636
		ttm_dma_unpopulate((void *)ttm, dev);
1637 1638 1639 1640 1641
		return;
	}
#endif

	for (i = 0; i < ttm->num_pages; i++) {
1642
		if (ttm_dma->dma_address[i]) {
1643
			dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE,
1644
				       DMA_BIDIRECTIONAL);
1645 1646 1647 1648 1649 1650
		}
	}

	ttm_pool_unpopulate(ttm);
}

1651
void
1652
nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive)
1653
{
1654
	struct reservation_object *resv = nvbo->bo.resv;
1655

1656 1657 1658 1659
	if (exclusive)
		reservation_object_add_excl_fence(resv, &fence->base);
	else if (fence)
		reservation_object_add_shared_fence(resv, &fence->base);
1660 1661
}

1662
struct ttm_bo_driver nouveau_bo_driver = {
1663
	.ttm_tt_create = &nouveau_ttm_tt_create,
1664 1665
	.ttm_tt_populate = &nouveau_ttm_tt_populate,
	.ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
1666 1667
	.invalidate_caches = nouveau_bo_invalidate_caches,
	.init_mem_type = nouveau_bo_init_mem_type,
1668
	.eviction_valuable = ttm_bo_eviction_valuable,
1669
	.evict_flags = nouveau_bo_evict_flags,
1670
	.move_notify = nouveau_bo_move_ntfy,
1671 1672
	.move = nouveau_bo_move,
	.verify_access = nouveau_bo_verify_access,
1673 1674 1675
	.fault_reserve_notify = &nouveau_ttm_fault_reserve_notify,
	.io_mem_reserve = &nouveau_ttm_io_mem_reserve,
	.io_mem_free = &nouveau_ttm_io_mem_free,
1676
	.io_mem_pfn = ttm_bo_default_io_mem_pfn,
1677
};