16ee73861SBen Skeggs /*
26ee73861SBen Skeggs * Copyright 2007 Dave Airlied
36ee73861SBen Skeggs * All Rights Reserved.
46ee73861SBen Skeggs *
56ee73861SBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
66ee73861SBen Skeggs * copy of this software and associated documentation files (the "Software"),
76ee73861SBen Skeggs * to deal in the Software without restriction, including without limitation
86ee73861SBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
96ee73861SBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the
106ee73861SBen Skeggs * Software is furnished to do so, subject to the following conditions:
116ee73861SBen Skeggs *
126ee73861SBen Skeggs * The above copyright notice and this permission notice (including the next
136ee73861SBen Skeggs * paragraph) shall be included in all copies or substantial portions of the
146ee73861SBen Skeggs * Software.
156ee73861SBen Skeggs *
166ee73861SBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
176ee73861SBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
186ee73861SBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
196ee73861SBen Skeggs * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
206ee73861SBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
216ee73861SBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
226ee73861SBen Skeggs * OTHER DEALINGS IN THE SOFTWARE.
236ee73861SBen Skeggs */
246ee73861SBen Skeggs /*
256ee73861SBen Skeggs * Authors: Dave Airlied <airlied@linux.ie>
266ee73861SBen Skeggs * Ben Skeggs <darktama@iinet.net.au>
276ee73861SBen Skeggs * Jeremy Kolb <jkolb@brandeis.edu>
286ee73861SBen Skeggs */
296ee73861SBen Skeggs
30fdb751efSBen Skeggs #include <linux/dma-mapping.h>
31a3185f91SChristian König #include <drm/ttm/ttm_tt.h>
326ee73861SBen Skeggs
334dc28134SBen Skeggs #include "nouveau_drv.h"
348b9d5d63SBen Skeggs #include "nouveau_chan.h"
35d375e7d5SBen Skeggs #include "nouveau_fence.h"
366ee73861SBen Skeggs
37ebb945a9SBen Skeggs #include "nouveau_bo.h"
38ebb945a9SBen Skeggs #include "nouveau_ttm.h"
39ebb945a9SBen Skeggs #include "nouveau_gem.h"
409ce523ccSBen Skeggs #include "nouveau_mem.h"
4124e8375bSBen Skeggs #include "nouveau_vmm.h"
42a510604dSMaarten Maathuis
43d7722134SBen Skeggs #include <nvif/class.h>
44d7722134SBen Skeggs #include <nvif/if500b.h>
45d7722134SBen Skeggs #include <nvif/if900b.h>
46d7722134SBen Skeggs
478af8a109SChristian König static int nouveau_ttm_tt_bind(struct ttm_device *bdev, struct ttm_tt *ttm,
48cae515f4SDave Airlie struct ttm_resource *reg);
498af8a109SChristian König static void nouveau_ttm_tt_unbind(struct ttm_device *bdev, struct ttm_tt *ttm);
50cae515f4SDave Airlie
51bc9e7b9aSBen Skeggs /*
52bc9e7b9aSBen Skeggs * NV10-NV40 tiling helpers
53bc9e7b9aSBen Skeggs */
54bc9e7b9aSBen Skeggs
55bc9e7b9aSBen Skeggs static void
nv10_bo_update_tile_region(struct drm_device * dev,struct nouveau_drm_tile * reg,u32 addr,u32 size,u32 pitch,u32 flags)56ebb945a9SBen Skeggs nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg,
57ebb945a9SBen Skeggs u32 addr, u32 size, u32 pitch, u32 flags)
58bc9e7b9aSBen Skeggs {
5977145f1cSBen Skeggs struct nouveau_drm *drm = nouveau_drm(dev);
60ebb945a9SBen Skeggs int i = reg - drm->tile.reg;
61359088d5SBen Skeggs struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
62b1e4553cSBen Skeggs struct nvkm_fb_tile *tile = &fb->tile.region[i];
63bc9e7b9aSBen Skeggs
64ebb945a9SBen Skeggs nouveau_fence_unref(®->fence);
65bc9e7b9aSBen Skeggs
66bc9e7b9aSBen Skeggs if (tile->pitch)
6703c8952fSBen Skeggs nvkm_fb_tile_fini(fb, i, tile);
68bc9e7b9aSBen Skeggs
69bc9e7b9aSBen Skeggs if (pitch)
7003c8952fSBen Skeggs nvkm_fb_tile_init(fb, i, addr, size, pitch, flags, tile);
71bc9e7b9aSBen Skeggs
7203c8952fSBen Skeggs nvkm_fb_tile_prog(fb, i, tile);
73bc9e7b9aSBen Skeggs }
74bc9e7b9aSBen Skeggs
75ebb945a9SBen Skeggs static struct nouveau_drm_tile *
nv10_bo_get_tile_region(struct drm_device * dev,int i)76bc9e7b9aSBen Skeggs nv10_bo_get_tile_region(struct drm_device *dev, int i)
77bc9e7b9aSBen Skeggs {
7877145f1cSBen Skeggs struct nouveau_drm *drm = nouveau_drm(dev);
79ebb945a9SBen Skeggs struct nouveau_drm_tile *tile = &drm->tile.reg[i];
80bc9e7b9aSBen Skeggs
81ebb945a9SBen Skeggs spin_lock(&drm->tile.lock);
82bc9e7b9aSBen Skeggs
83bc9e7b9aSBen Skeggs if (!tile->used &&
84bc9e7b9aSBen Skeggs (!tile->fence || nouveau_fence_done(tile->fence)))
85bc9e7b9aSBen Skeggs tile->used = true;
86bc9e7b9aSBen Skeggs else
87bc9e7b9aSBen Skeggs tile = NULL;
88bc9e7b9aSBen Skeggs
89ebb945a9SBen Skeggs spin_unlock(&drm->tile.lock);
90bc9e7b9aSBen Skeggs return tile;
91bc9e7b9aSBen Skeggs }
92bc9e7b9aSBen Skeggs
93bc9e7b9aSBen Skeggs static void
nv10_bo_put_tile_region(struct drm_device * dev,struct nouveau_drm_tile * tile,struct dma_fence * fence)94ebb945a9SBen Skeggs nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile,
95f54d1867SChris Wilson struct dma_fence *fence)
96bc9e7b9aSBen Skeggs {
9777145f1cSBen Skeggs struct nouveau_drm *drm = nouveau_drm(dev);
98bc9e7b9aSBen Skeggs
99bc9e7b9aSBen Skeggs if (tile) {
100ebb945a9SBen Skeggs spin_lock(&drm->tile.lock);
101f54d1867SChris Wilson tile->fence = (struct nouveau_fence *)dma_fence_get(fence);
102bc9e7b9aSBen Skeggs tile->used = false;
103ebb945a9SBen Skeggs spin_unlock(&drm->tile.lock);
104bc9e7b9aSBen Skeggs }
105bc9e7b9aSBen Skeggs }
106bc9e7b9aSBen Skeggs
107ebb945a9SBen Skeggs static struct nouveau_drm_tile *
nv10_bo_set_tiling(struct drm_device * dev,u32 addr,u32 size,u32 pitch,u32 zeta)108ebb945a9SBen Skeggs nv10_bo_set_tiling(struct drm_device *dev, u32 addr,
1097760a2e3SBen Skeggs u32 size, u32 pitch, u32 zeta)
110bc9e7b9aSBen Skeggs {
11177145f1cSBen Skeggs struct nouveau_drm *drm = nouveau_drm(dev);
1121167c6bcSBen Skeggs struct nvkm_fb *fb = nvxx_fb(&drm->client.device);
113ebb945a9SBen Skeggs struct nouveau_drm_tile *tile, *found = NULL;
114bc9e7b9aSBen Skeggs int i;
115bc9e7b9aSBen Skeggs
116b1e4553cSBen Skeggs for (i = 0; i < fb->tile.regions; i++) {
117bc9e7b9aSBen Skeggs tile = nv10_bo_get_tile_region(dev, i);
118bc9e7b9aSBen Skeggs
119bc9e7b9aSBen Skeggs if (pitch && !found) {
120bc9e7b9aSBen Skeggs found = tile;
121bc9e7b9aSBen Skeggs continue;
122bc9e7b9aSBen Skeggs
123b1e4553cSBen Skeggs } else if (tile && fb->tile.region[i].pitch) {
124bc9e7b9aSBen Skeggs /* Kill an unused tile region. */
125bc9e7b9aSBen Skeggs nv10_bo_update_tile_region(dev, tile, 0, 0, 0, 0);
126bc9e7b9aSBen Skeggs }
127bc9e7b9aSBen Skeggs
128bc9e7b9aSBen Skeggs nv10_bo_put_tile_region(dev, tile, NULL);
129bc9e7b9aSBen Skeggs }
130bc9e7b9aSBen Skeggs
131bc9e7b9aSBen Skeggs if (found)
1327760a2e3SBen Skeggs nv10_bo_update_tile_region(dev, found, addr, size, pitch, zeta);
133bc9e7b9aSBen Skeggs return found;
134bc9e7b9aSBen Skeggs }
135bc9e7b9aSBen Skeggs
1366ee73861SBen Skeggs static void
nouveau_bo_del_ttm(struct ttm_buffer_object * bo)1376ee73861SBen Skeggs nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
1386ee73861SBen Skeggs {
139ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
140ebb945a9SBen Skeggs struct drm_device *dev = drm->dev;
1416ee73861SBen Skeggs struct nouveau_bo *nvbo = nouveau_bo(bo);
1426ee73861SBen Skeggs
1436797cea1SChristian König WARN_ON(nvbo->bo.pin_count > 0);
144141b15e5SChristian König nouveau_bo_del_io_reserve_lru(bo);
145bc9e7b9aSBen Skeggs nv10_bo_put_tile_region(dev, nvbo->tile, NULL);
146641f53c0SThierry Reding
147641f53c0SThierry Reding /*
148641f53c0SThierry Reding * If nouveau_bo_new() allocated this buffer, the GEM object was never
149641f53c0SThierry Reding * initialized, so don't attempt to release it.
150641f53c0SThierry Reding */
151641f53c0SThierry Reding if (bo->base.dev)
152641f53c0SThierry Reding drm_gem_object_release(&bo->base);
153d098775eSChristian König else
154d098775eSChristian König dma_resv_fini(&bo->base._resv);
155641f53c0SThierry Reding
1566ee73861SBen Skeggs kfree(nvbo);
1576ee73861SBen Skeggs }
1586ee73861SBen Skeggs
1594d8b3d34SBen Skeggs static inline u64
roundup_64(u64 x,u32 y)1604d8b3d34SBen Skeggs roundup_64(u64 x, u32 y)
1614d8b3d34SBen Skeggs {
1624d8b3d34SBen Skeggs x += y - 1;
1634d8b3d34SBen Skeggs do_div(x, y);
1644d8b3d34SBen Skeggs return x * y;
1654d8b3d34SBen Skeggs }
1664d8b3d34SBen Skeggs
167a0af9addSFrancisco Jerez static void
nouveau_bo_fixup_align(struct nouveau_bo * nvbo,int * align,u64 * size)16881b61579SChristian König nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, u64 *size)
169a0af9addSFrancisco Jerez {
170ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
1711167c6bcSBen Skeggs struct nvif_device *device = &drm->client.device;
172a0af9addSFrancisco Jerez
173967e7bdeSBen Skeggs if (device->info.family < NV_DEVICE_INFO_V0_TESLA) {
1747760a2e3SBen Skeggs if (nvbo->mode) {
175967e7bdeSBen Skeggs if (device->info.chipset >= 0x40) {
176a0af9addSFrancisco Jerez *align = 65536;
1777760a2e3SBen Skeggs *size = roundup_64(*size, 64 * nvbo->mode);
178a0af9addSFrancisco Jerez
179967e7bdeSBen Skeggs } else if (device->info.chipset >= 0x30) {
180a0af9addSFrancisco Jerez *align = 32768;
1817760a2e3SBen Skeggs *size = roundup_64(*size, 64 * nvbo->mode);
182a0af9addSFrancisco Jerez
183967e7bdeSBen Skeggs } else if (device->info.chipset >= 0x20) {
184a0af9addSFrancisco Jerez *align = 16384;
1857760a2e3SBen Skeggs *size = roundup_64(*size, 64 * nvbo->mode);
186a0af9addSFrancisco Jerez
187967e7bdeSBen Skeggs } else if (device->info.chipset >= 0x10) {
188a0af9addSFrancisco Jerez *align = 16384;
1897760a2e3SBen Skeggs *size = roundup_64(*size, 32 * nvbo->mode);
190a0af9addSFrancisco Jerez }
191a0af9addSFrancisco Jerez }
192bfd83acaSBen Skeggs } else {
1937760a2e3SBen Skeggs *size = roundup_64(*size, (1 << nvbo->page));
1947760a2e3SBen Skeggs *align = max((1 << nvbo->page), *align);
195a0af9addSFrancisco Jerez }
196bfd83acaSBen Skeggs
1974d8b3d34SBen Skeggs *size = roundup_64(*size, PAGE_SIZE);
198a0af9addSFrancisco Jerez }
199a0af9addSFrancisco Jerez
200019cbd4aSThierry Reding struct nouveau_bo *
nouveau_bo_alloc(struct nouveau_cli * cli,u64 * size,int * align,u32 domain,u32 tile_mode,u32 tile_flags,bool internal)20181b61579SChristian König nouveau_bo_alloc(struct nouveau_cli *cli, u64 *size, int *align, u32 domain,
202b88baab8SDanilo Krummrich u32 tile_mode, u32 tile_flags, bool internal)
2036ee73861SBen Skeggs {
204e75c091bSBen Skeggs struct nouveau_drm *drm = cli->drm;
2056ee73861SBen Skeggs struct nouveau_bo *nvbo;
206a220dd73SBen Skeggs struct nvif_mmu *mmu = &cli->mmu;
2077b05a7c0SDanilo Krummrich struct nvif_vmm *vmm = &nouveau_cli_vmm(cli)->vmm;
208019cbd4aSThierry Reding int i, pi = -1;
20935095f75SMaarten Lankhorst
2109ca7f796SThierry Reding if (!*size) {
2119ca7f796SThierry Reding NV_WARN(drm, "skipped size %016llx\n", *size);
212019cbd4aSThierry Reding return ERR_PTR(-EINVAL);
2130108bc80SMaarten Lankhorst }
21422b33e8eSDave Airlie
2156ee73861SBen Skeggs nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
2166ee73861SBen Skeggs if (!nvbo)
217019cbd4aSThierry Reding return ERR_PTR(-ENOMEM);
218a7f7d13eSDanilo Krummrich
2196ee73861SBen Skeggs INIT_LIST_HEAD(&nvbo->head);
2206ee73861SBen Skeggs INIT_LIST_HEAD(&nvbo->entry);
221fd2871afSBen Skeggs INIT_LIST_HEAD(&nvbo->vma_list);
222ebb945a9SBen Skeggs nvbo->bo.bdev = &drm->ttm.bdev;
2236ee73861SBen Skeggs
224acb16cfaSBen Skeggs /* This is confusing, and doesn't actually mean we want an uncached
225acb16cfaSBen Skeggs * mapping, but is what NOUVEAU_GEM_DOMAIN_COHERENT gets translated
226acb16cfaSBen Skeggs * into in nouveau_gem_new().
227acb16cfaSBen Skeggs */
22881b61579SChristian König if (domain & NOUVEAU_GEM_DOMAIN_COHERENT) {
229acb16cfaSBen Skeggs /* Determine if we can get a cache-coherent map, forcing
230acb16cfaSBen Skeggs * uncached mapping if we can't.
231acb16cfaSBen Skeggs */
23274a39954SBen Skeggs if (!nouveau_drm_use_coherent_gpu_mapping(drm))
233acb16cfaSBen Skeggs nvbo->force_coherent = true;
234acb16cfaSBen Skeggs }
235c3a0c771SAlexandre Courbot
236b88baab8SDanilo Krummrich nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG);
2373652ac87SMohamed Ahmed
2387760a2e3SBen Skeggs if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) {
2397760a2e3SBen Skeggs nvbo->kind = (tile_flags & 0x0000ff00) >> 8;
240a220dd73SBen Skeggs if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) {
241a220dd73SBen Skeggs kfree(nvbo);
242019cbd4aSThierry Reding return ERR_PTR(-EINVAL);
243a220dd73SBen Skeggs }
244a220dd73SBen Skeggs
245a220dd73SBen Skeggs nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind;
246b88baab8SDanilo Krummrich } else if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
2477760a2e3SBen Skeggs nvbo->kind = (tile_flags & 0x00007f00) >> 8;
2487760a2e3SBen Skeggs nvbo->comp = (tile_flags & 0x00030000) >> 16;
249a220dd73SBen Skeggs if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) {
250a220dd73SBen Skeggs kfree(nvbo);
251019cbd4aSThierry Reding return ERR_PTR(-EINVAL);
252a220dd73SBen Skeggs }
2537760a2e3SBen Skeggs } else {
2547760a2e3SBen Skeggs nvbo->zeta = (tile_flags & 0x00000007);
2557760a2e3SBen Skeggs }
2567760a2e3SBen Skeggs nvbo->mode = tile_mode;
2577760a2e3SBen Skeggs
2583652ac87SMohamed Ahmed if (!nouveau_cli_uvmm(cli) || internal) {
2597dc6a446SBen Skeggs /* Determine the desirable target GPU page size for the buffer. */
2607dc6a446SBen Skeggs for (i = 0; i < vmm->page_nr; i++) {
2617dc6a446SBen Skeggs /* Because we cannot currently allow VMM maps to fail
2627dc6a446SBen Skeggs * during buffer migration, we need to determine page
2637dc6a446SBen Skeggs * size for the buffer up-front, and pre-allocate its
2647dc6a446SBen Skeggs * page tables.
2657dc6a446SBen Skeggs *
2667dc6a446SBen Skeggs * Skip page sizes that can't support needed domains.
2677dc6a446SBen Skeggs */
2687dc6a446SBen Skeggs if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE &&
26981b61579SChristian König (domain & NOUVEAU_GEM_DOMAIN_VRAM) && !vmm->page[i].vram)
2707dc6a446SBen Skeggs continue;
27181b61579SChristian König if ((domain & NOUVEAU_GEM_DOMAIN_GART) &&
272f29f18ebSBen Skeggs (!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT))
2737dc6a446SBen Skeggs continue;
2747dc6a446SBen Skeggs
2757dc6a446SBen Skeggs /* Select this page size if it's the first that supports
2767dc6a446SBen Skeggs * the potential memory domains, or when it's compatible
2777dc6a446SBen Skeggs * with the requested compression settings.
2787dc6a446SBen Skeggs */
2797dc6a446SBen Skeggs if (pi < 0 || !nvbo->comp || vmm->page[i].comp)
2807dc6a446SBen Skeggs pi = i;
2817dc6a446SBen Skeggs
2827dc6a446SBen Skeggs /* Stop once the buffer is larger than the current page size. */
2839ca7f796SThierry Reding if (*size >= 1ULL << vmm->page[i].shift)
2847dc6a446SBen Skeggs break;
2857dc6a446SBen Skeggs }
2867dc6a446SBen Skeggs
2876dc54874SJianglei Nie if (WARN_ON(pi < 0)) {
2886dc54874SJianglei Nie kfree(nvbo);
289019cbd4aSThierry Reding return ERR_PTR(-EINVAL);
2906dc54874SJianglei Nie }
2917dc6a446SBen Skeggs
2927dc6a446SBen Skeggs /* Disable compression if suitable settings couldn't be found. */
2937dc6a446SBen Skeggs if (nvbo->comp && !vmm->page[pi].comp) {
2947dc6a446SBen Skeggs if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100)
295a220dd73SBen Skeggs nvbo->kind = mmu->kind[nvbo->kind];
2967760a2e3SBen Skeggs nvbo->comp = 0;
2977760a2e3SBen Skeggs }
2987dc6a446SBen Skeggs nvbo->page = vmm->page[pi].shift;
299b88baab8SDanilo Krummrich } else {
300b88baab8SDanilo Krummrich /* Determine the desirable target GPU page size for the buffer. */
301b88baab8SDanilo Krummrich for (i = 0; i < vmm->page_nr; i++) {
302b88baab8SDanilo Krummrich /* Because we cannot currently allow VMM maps to fail
303b88baab8SDanilo Krummrich * during buffer migration, we need to determine page
304b88baab8SDanilo Krummrich * size for the buffer up-front, and pre-allocate its
305b88baab8SDanilo Krummrich * page tables.
306b88baab8SDanilo Krummrich *
307b88baab8SDanilo Krummrich * Skip page sizes that can't support needed domains.
308b88baab8SDanilo Krummrich */
309b88baab8SDanilo Krummrich if ((domain & NOUVEAU_GEM_DOMAIN_VRAM) && !vmm->page[i].vram)
310b88baab8SDanilo Krummrich continue;
311b88baab8SDanilo Krummrich if ((domain & NOUVEAU_GEM_DOMAIN_GART) &&
312b88baab8SDanilo Krummrich (!vmm->page[i].host || vmm->page[i].shift > PAGE_SHIFT))
313b88baab8SDanilo Krummrich continue;
314b88baab8SDanilo Krummrich
31559ae50ebSDave Airlie /* pick the last one as it will be smallest. */
316b88baab8SDanilo Krummrich pi = i;
31759ae50ebSDave Airlie
318b88baab8SDanilo Krummrich /* Stop once the buffer is larger than the current page size. */
319b88baab8SDanilo Krummrich if (*size >= 1ULL << vmm->page[i].shift)
320b88baab8SDanilo Krummrich break;
321b88baab8SDanilo Krummrich }
322b88baab8SDanilo Krummrich if (WARN_ON(pi < 0)) {
323b88baab8SDanilo Krummrich kfree(nvbo);
324b88baab8SDanilo Krummrich return ERR_PTR(-EINVAL);
325b88baab8SDanilo Krummrich }
326b88baab8SDanilo Krummrich nvbo->page = vmm->page[pi].shift;
327b88baab8SDanilo Krummrich }
328f91bac5bSBen Skeggs
32981b61579SChristian König nouveau_bo_fixup_align(nvbo, align, size);
3309ca7f796SThierry Reding
331019cbd4aSThierry Reding return nvbo;
332019cbd4aSThierry Reding }
333019cbd4aSThierry Reding
334019cbd4aSThierry Reding int
nouveau_bo_init(struct nouveau_bo * nvbo,u64 size,int align,u32 domain,struct sg_table * sg,struct dma_resv * robj)33581b61579SChristian König nouveau_bo_init(struct nouveau_bo *nvbo, u64 size, int align, u32 domain,
336019cbd4aSThierry Reding struct sg_table *sg, struct dma_resv *robj)
337019cbd4aSThierry Reding {
338019cbd4aSThierry Reding int type = sg ? ttm_bo_type_sg : ttm_bo_type_device;
339019cbd4aSThierry Reding int ret;
340b88baab8SDanilo Krummrich struct ttm_operation_ctx ctx = {
341b88baab8SDanilo Krummrich .interruptible = false,
342b88baab8SDanilo Krummrich .no_wait_gpu = false,
343b88baab8SDanilo Krummrich .resv = robj,
344b88baab8SDanilo Krummrich };
345019cbd4aSThierry Reding
34681b61579SChristian König nouveau_bo_placement_set(nvbo, domain, 0);
347141b15e5SChristian König INIT_LIST_HEAD(&nvbo->io_reserve_lru);
3486ee73861SBen Skeggs
349b88baab8SDanilo Krummrich ret = ttm_bo_init_reserved(nvbo->bo.bdev, &nvbo->bo, type,
350b88baab8SDanilo Krummrich &nvbo->placement, align >> PAGE_SHIFT, &ctx,
351347987a2SChristian König sg, robj, nouveau_bo_del_ttm);
3526ee73861SBen Skeggs if (ret) {
3536ee73861SBen Skeggs /* ttm will call nouveau_bo_del_ttm if it fails.. */
3546ee73861SBen Skeggs return ret;
3556ee73861SBen Skeggs }
3566ee73861SBen Skeggs
357b88baab8SDanilo Krummrich if (!robj)
358b88baab8SDanilo Krummrich ttm_bo_unreserve(&nvbo->bo);
359b88baab8SDanilo Krummrich
360019cbd4aSThierry Reding return 0;
361019cbd4aSThierry Reding }
362019cbd4aSThierry Reding
363019cbd4aSThierry Reding int
nouveau_bo_new(struct nouveau_cli * cli,u64 size,int align,uint32_t domain,uint32_t tile_mode,uint32_t tile_flags,struct sg_table * sg,struct dma_resv * robj,struct nouveau_bo ** pnvbo)364019cbd4aSThierry Reding nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align,
36581b61579SChristian König uint32_t domain, uint32_t tile_mode, uint32_t tile_flags,
366019cbd4aSThierry Reding struct sg_table *sg, struct dma_resv *robj,
367019cbd4aSThierry Reding struct nouveau_bo **pnvbo)
368019cbd4aSThierry Reding {
369019cbd4aSThierry Reding struct nouveau_bo *nvbo;
370019cbd4aSThierry Reding int ret;
371019cbd4aSThierry Reding
37281b61579SChristian König nvbo = nouveau_bo_alloc(cli, &size, &align, domain, tile_mode,
373b88baab8SDanilo Krummrich tile_flags, true);
374019cbd4aSThierry Reding if (IS_ERR(nvbo))
375019cbd4aSThierry Reding return PTR_ERR(nvbo);
376019cbd4aSThierry Reding
377d098775eSChristian König nvbo->bo.base.size = size;
378d098775eSChristian König dma_resv_init(&nvbo->bo.base._resv);
379d098775eSChristian König drm_vma_node_reset(&nvbo->bo.base.vma_node);
380d098775eSChristian König
381a7f7d13eSDanilo Krummrich /* This must be called before ttm_bo_init_reserved(). Subsequent
382a7f7d13eSDanilo Krummrich * bo_move() callbacks might already iterate the GEMs GPUVA list.
383a7f7d13eSDanilo Krummrich */
384a7f7d13eSDanilo Krummrich drm_gem_gpuva_init(&nvbo->bo.base);
385a7f7d13eSDanilo Krummrich
38681b61579SChristian König ret = nouveau_bo_init(nvbo, size, align, domain, sg, robj);
387019cbd4aSThierry Reding if (ret)
388019cbd4aSThierry Reding return ret;
389019cbd4aSThierry Reding
3906ee73861SBen Skeggs *pnvbo = nvbo;
3916ee73861SBen Skeggs return 0;
3926ee73861SBen Skeggs }
3936ee73861SBen Skeggs
39478ad0f7bSFrancisco Jerez static void
set_placement_list(struct ttm_place * pl,unsigned * n,uint32_t domain)395ce65b874SChristian König set_placement_list(struct ttm_place *pl, unsigned *n, uint32_t domain)
3966ee73861SBen Skeggs {
39778ad0f7bSFrancisco Jerez *n = 0;
3986ee73861SBen Skeggs
39948e07c23SChristian König if (domain & NOUVEAU_GEM_DOMAIN_VRAM) {
40048e07c23SChristian König pl[*n].mem_type = TTM_PL_VRAM;
401ce65b874SChristian König pl[*n].flags = 0;
4025839172fSChristian König (*n)++;
40348e07c23SChristian König }
40448e07c23SChristian König if (domain & NOUVEAU_GEM_DOMAIN_GART) {
40548e07c23SChristian König pl[*n].mem_type = TTM_PL_TT;
406ce65b874SChristian König pl[*n].flags = 0;
4075839172fSChristian König (*n)++;
40848e07c23SChristian König }
40948e07c23SChristian König if (domain & NOUVEAU_GEM_DOMAIN_CPU) {
41048e07c23SChristian König pl[*n].mem_type = TTM_PL_SYSTEM;
411ce65b874SChristian König pl[(*n)++].flags = 0;
41248e07c23SChristian König }
41337cb3e08SBen Skeggs }
41478ad0f7bSFrancisco Jerez
415699ddfd9SFrancisco Jerez static void
set_placement_range(struct nouveau_bo * nvbo,uint32_t domain)41681b61579SChristian König set_placement_range(struct nouveau_bo *nvbo, uint32_t domain)
417699ddfd9SFrancisco Jerez {
418ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
419aeaf45c5SChristian König u64 vram_size = drm->client.device.info.ram_size;
420f1217ed0SChristian König unsigned i, fpfn, lpfn;
421699ddfd9SFrancisco Jerez
4221167c6bcSBen Skeggs if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CELSIUS &&
42381b61579SChristian König nvbo->mode && (domain & NOUVEAU_GEM_DOMAIN_VRAM) &&
424aeaf45c5SChristian König nvbo->bo.base.size < vram_size / 4) {
425699ddfd9SFrancisco Jerez /*
426699ddfd9SFrancisco Jerez * Make sure that the color and depth buffers are handled
427699ddfd9SFrancisco Jerez * by independent memory controller units. Up to a 9x
428699ddfd9SFrancisco Jerez * speed up when alpha-blending and depth-test are enabled
429699ddfd9SFrancisco Jerez * at the same time.
430699ddfd9SFrancisco Jerez */
4317760a2e3SBen Skeggs if (nvbo->zeta) {
432aeaf45c5SChristian König fpfn = (vram_size / 2) >> PAGE_SHIFT;
433f1217ed0SChristian König lpfn = ~0;
434699ddfd9SFrancisco Jerez } else {
435f1217ed0SChristian König fpfn = 0;
436aeaf45c5SChristian König lpfn = (vram_size / 2) >> PAGE_SHIFT;
437f1217ed0SChristian König }
438f1217ed0SChristian König for (i = 0; i < nvbo->placement.num_placement; ++i) {
439f1217ed0SChristian König nvbo->placements[i].fpfn = fpfn;
440f1217ed0SChristian König nvbo->placements[i].lpfn = lpfn;
441f1217ed0SChristian König }
442f1217ed0SChristian König for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
443f1217ed0SChristian König nvbo->busy_placements[i].fpfn = fpfn;
444f1217ed0SChristian König nvbo->busy_placements[i].lpfn = lpfn;
445699ddfd9SFrancisco Jerez }
446699ddfd9SFrancisco Jerez }
447699ddfd9SFrancisco Jerez }
448699ddfd9SFrancisco Jerez
44978ad0f7bSFrancisco Jerez void
nouveau_bo_placement_set(struct nouveau_bo * nvbo,uint32_t domain,uint32_t busy)45081b61579SChristian König nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t domain,
45181b61579SChristian König uint32_t busy)
45278ad0f7bSFrancisco Jerez {
45378ad0f7bSFrancisco Jerez struct ttm_placement *pl = &nvbo->placement;
45478ad0f7bSFrancisco Jerez
45578ad0f7bSFrancisco Jerez pl->placement = nvbo->placements;
456ce65b874SChristian König set_placement_list(nvbo->placements, &pl->num_placement, domain);
45778ad0f7bSFrancisco Jerez
45878ad0f7bSFrancisco Jerez pl->busy_placement = nvbo->busy_placements;
459ce65b874SChristian König set_placement_list(nvbo->busy_placements, &pl->num_busy_placement,
460ce65b874SChristian König domain | busy);
461699ddfd9SFrancisco Jerez
46281b61579SChristian König set_placement_range(nvbo, domain);
4636ee73861SBen Skeggs }
4646ee73861SBen Skeggs
4656ee73861SBen Skeggs int
nouveau_bo_pin(struct nouveau_bo * nvbo,uint32_t domain,bool contig)46681b61579SChristian König nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t domain, bool contig)
4676ee73861SBen Skeggs {
468ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
4696ee73861SBen Skeggs struct ttm_buffer_object *bo = &nvbo->bo;
470ad76b3f7SBen Skeggs bool force = false, evict = false;
47178ad0f7bSFrancisco Jerez int ret;
4726ee73861SBen Skeggs
473dfd5e50eSChristian König ret = ttm_bo_reserve(bo, false, false, NULL);
4740ae6d7bcSDaniel Vetter if (ret)
47550ab2e52SBen Skeggs return ret;
4760ae6d7bcSDaniel Vetter
4771167c6bcSBen Skeggs if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
47881b61579SChristian König domain == NOUVEAU_GEM_DOMAIN_VRAM && contig) {
4797760a2e3SBen Skeggs if (!nvbo->contig) {
4807760a2e3SBen Skeggs nvbo->contig = true;
481ad76b3f7SBen Skeggs force = true;
4827760a2e3SBen Skeggs evict = true;
483ad76b3f7SBen Skeggs }
484ad76b3f7SBen Skeggs }
485ad76b3f7SBen Skeggs
4866797cea1SChristian König if (nvbo->bo.pin_count) {
48781b61579SChristian König bool error = evict;
48881b61579SChristian König
489d3116756SChristian König switch (bo->resource->mem_type) {
49081b61579SChristian König case TTM_PL_VRAM:
49181b61579SChristian König error |= !(domain & NOUVEAU_GEM_DOMAIN_VRAM);
49281b61579SChristian König break;
49381b61579SChristian König case TTM_PL_TT:
49481b61579SChristian König error |= !(domain & NOUVEAU_GEM_DOMAIN_GART);
495f49efb10SGustavo A. R. Silva break;
49681b61579SChristian König default:
49781b61579SChristian König break;
49881b61579SChristian König }
49981b61579SChristian König
50081b61579SChristian König if (error) {
501ad76b3f7SBen Skeggs NV_ERROR(drm, "bo %p pinned elsewhere: "
502ad76b3f7SBen Skeggs "0x%08x vs 0x%08x\n", bo,
503d3116756SChristian König bo->resource->mem_type, domain);
504ad76b3f7SBen Skeggs ret = -EBUSY;
505ad76b3f7SBen Skeggs }
5066797cea1SChristian König ttm_bo_pin(&nvbo->bo);
5070ae6d7bcSDaniel Vetter goto out;
5086ee73861SBen Skeggs }
5096ee73861SBen Skeggs
510ad76b3f7SBen Skeggs if (evict) {
51181b61579SChristian König nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, 0);
512ad76b3f7SBen Skeggs ret = nouveau_bo_validate(nvbo, false, false);
513ad76b3f7SBen Skeggs if (ret)
51450ab2e52SBen Skeggs goto out;
515ad76b3f7SBen Skeggs }
5166ee73861SBen Skeggs
51781b61579SChristian König nouveau_bo_placement_set(nvbo, domain, 0);
51897a875cbSMaarten Lankhorst ret = nouveau_bo_validate(nvbo, false, false);
5196aac6cedSBen Skeggs if (ret)
5206aac6cedSBen Skeggs goto out;
5216797cea1SChristian König
5226797cea1SChristian König ttm_bo_pin(&nvbo->bo);
5236aac6cedSBen Skeggs
524d3116756SChristian König switch (bo->resource->mem_type) {
5256ee73861SBen Skeggs case TTM_PL_VRAM:
526e11bfb99SChristian König drm->gem.vram_available -= bo->base.size;
5276ee73861SBen Skeggs break;
5286ee73861SBen Skeggs case TTM_PL_TT:
529e11bfb99SChristian König drm->gem.gart_available -= bo->base.size;
5306ee73861SBen Skeggs break;
5316ee73861SBen Skeggs default:
5326ee73861SBen Skeggs break;
5336ee73861SBen Skeggs }
5345be5a15aSAlexandre Courbot
5356ee73861SBen Skeggs out:
536ad76b3f7SBen Skeggs if (force && ret)
5377760a2e3SBen Skeggs nvbo->contig = false;
5380ae6d7bcSDaniel Vetter ttm_bo_unreserve(bo);
5396ee73861SBen Skeggs return ret;
5406ee73861SBen Skeggs }
5416ee73861SBen Skeggs
5426ee73861SBen Skeggs int
nouveau_bo_unpin(struct nouveau_bo * nvbo)5436ee73861SBen Skeggs nouveau_bo_unpin(struct nouveau_bo *nvbo)
5446ee73861SBen Skeggs {
545ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
5466ee73861SBen Skeggs struct ttm_buffer_object *bo = &nvbo->bo;
5476797cea1SChristian König int ret;
5486ee73861SBen Skeggs
549dfd5e50eSChristian König ret = ttm_bo_reserve(bo, false, false, NULL);
5506ee73861SBen Skeggs if (ret)
5516ee73861SBen Skeggs return ret;
5526ee73861SBen Skeggs
5536797cea1SChristian König ttm_bo_unpin(&nvbo->bo);
5546797cea1SChristian König if (!nvbo->bo.pin_count) {
555d3116756SChristian König switch (bo->resource->mem_type) {
5566ee73861SBen Skeggs case TTM_PL_VRAM:
557e11bfb99SChristian König drm->gem.vram_available += bo->base.size;
5586ee73861SBen Skeggs break;
5596ee73861SBen Skeggs case TTM_PL_TT:
560e11bfb99SChristian König drm->gem.gart_available += bo->base.size;
5616ee73861SBen Skeggs break;
5626ee73861SBen Skeggs default:
5636ee73861SBen Skeggs break;
5646ee73861SBen Skeggs }
5656ee73861SBen Skeggs }
5666ee73861SBen Skeggs
5676ee73861SBen Skeggs ttm_bo_unreserve(bo);
5686797cea1SChristian König return 0;
5696ee73861SBen Skeggs }
5706ee73861SBen Skeggs
5716ee73861SBen Skeggs int
nouveau_bo_map(struct nouveau_bo * nvbo)5726ee73861SBen Skeggs nouveau_bo_map(struct nouveau_bo *nvbo)
5736ee73861SBen Skeggs {
5746ee73861SBen Skeggs int ret;
5756ee73861SBen Skeggs
576dfd5e50eSChristian König ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL);
5776ee73861SBen Skeggs if (ret)
5786ee73861SBen Skeggs return ret;
5796ee73861SBen Skeggs
580e3c92eb4SSomalapuram Amaranath ret = ttm_bo_kmap(&nvbo->bo, 0, PFN_UP(nvbo->bo.base.size), &nvbo->kmap);
581c3a0c771SAlexandre Courbot
5826ee73861SBen Skeggs ttm_bo_unreserve(&nvbo->bo);
5836ee73861SBen Skeggs return ret;
5846ee73861SBen Skeggs }
5856ee73861SBen Skeggs
5866ee73861SBen Skeggs void
nouveau_bo_unmap(struct nouveau_bo * nvbo)5876ee73861SBen Skeggs nouveau_bo_unmap(struct nouveau_bo *nvbo)
5886ee73861SBen Skeggs {
589c3a0c771SAlexandre Courbot if (!nvbo)
590c3a0c771SAlexandre Courbot return;
591c3a0c771SAlexandre Courbot
5926ee73861SBen Skeggs ttm_bo_kunmap(&nvbo->kmap);
5936ee73861SBen Skeggs }
5946ee73861SBen Skeggs
595b22870baSAlexandre Courbot void
nouveau_bo_sync_for_device(struct nouveau_bo * nvbo)596b22870baSAlexandre Courbot nouveau_bo_sync_for_device(struct nouveau_bo *nvbo)
597b22870baSAlexandre Courbot {
598b22870baSAlexandre Courbot struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
599e34b8feeSChristian König struct ttm_tt *ttm_dma = (struct ttm_tt *)nvbo->bo.ttm;
600f295c8cfSDave Airlie int i, j;
601b22870baSAlexandre Courbot
602d3300991SChristian König if (!ttm_dma || !ttm_dma->dma_address)
603b22870baSAlexandre Courbot return;
604e94c55b8STobias Klausmann if (!ttm_dma->pages) {
605e94c55b8STobias Klausmann NV_DEBUG(drm, "ttm_dma 0x%p: pages NULL\n", ttm_dma);
606e94c55b8STobias Klausmann return;
607e94c55b8STobias Klausmann }
608b22870baSAlexandre Courbot
609b22870baSAlexandre Courbot /* Don't waste time looping if the object is coherent */
610b22870baSAlexandre Courbot if (nvbo->force_coherent)
611b22870baSAlexandre Courbot return;
612b22870baSAlexandre Courbot
6134042160cSDave Airlie i = 0;
6144042160cSDave Airlie while (i < ttm_dma->num_pages) {
615f295c8cfSDave Airlie struct page *p = ttm_dma->pages[i];
616f295c8cfSDave Airlie size_t num_pages = 1;
617f295c8cfSDave Airlie
618f295c8cfSDave Airlie for (j = i + 1; j < ttm_dma->num_pages; ++j) {
619f295c8cfSDave Airlie if (++p != ttm_dma->pages[j])
620f295c8cfSDave Airlie break;
621f295c8cfSDave Airlie
622f295c8cfSDave Airlie ++num_pages;
623f295c8cfSDave Airlie }
624359088d5SBen Skeggs dma_sync_single_for_device(drm->dev->dev,
625359088d5SBen Skeggs ttm_dma->dma_address[i],
626f295c8cfSDave Airlie num_pages * PAGE_SIZE, DMA_TO_DEVICE);
627f295c8cfSDave Airlie i += num_pages;
628f295c8cfSDave Airlie }
629b22870baSAlexandre Courbot }
630b22870baSAlexandre Courbot
631b22870baSAlexandre Courbot void
nouveau_bo_sync_for_cpu(struct nouveau_bo * nvbo)632b22870baSAlexandre Courbot nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo)
633b22870baSAlexandre Courbot {
634b22870baSAlexandre Courbot struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev);
635e34b8feeSChristian König struct ttm_tt *ttm_dma = (struct ttm_tt *)nvbo->bo.ttm;
636f295c8cfSDave Airlie int i, j;
637b22870baSAlexandre Courbot
638d3300991SChristian König if (!ttm_dma || !ttm_dma->dma_address)
639b22870baSAlexandre Courbot return;
640e94c55b8STobias Klausmann if (!ttm_dma->pages) {
641e94c55b8STobias Klausmann NV_DEBUG(drm, "ttm_dma 0x%p: pages NULL\n", ttm_dma);
642e94c55b8STobias Klausmann return;
643e94c55b8STobias Klausmann }
644b22870baSAlexandre Courbot
645b22870baSAlexandre Courbot /* Don't waste time looping if the object is coherent */
646b22870baSAlexandre Courbot if (nvbo->force_coherent)
647b22870baSAlexandre Courbot return;
648b22870baSAlexandre Courbot
6494042160cSDave Airlie i = 0;
6504042160cSDave Airlie while (i < ttm_dma->num_pages) {
651f295c8cfSDave Airlie struct page *p = ttm_dma->pages[i];
652f295c8cfSDave Airlie size_t num_pages = 1;
653f295c8cfSDave Airlie
654f295c8cfSDave Airlie for (j = i + 1; j < ttm_dma->num_pages; ++j) {
655f295c8cfSDave Airlie if (++p != ttm_dma->pages[j])
656f295c8cfSDave Airlie break;
657f295c8cfSDave Airlie
658f295c8cfSDave Airlie ++num_pages;
659f295c8cfSDave Airlie }
660f295c8cfSDave Airlie
661359088d5SBen Skeggs dma_sync_single_for_cpu(drm->dev->dev, ttm_dma->dma_address[i],
662f295c8cfSDave Airlie num_pages * PAGE_SIZE, DMA_FROM_DEVICE);
663f295c8cfSDave Airlie i += num_pages;
664f295c8cfSDave Airlie }
665b22870baSAlexandre Courbot }
666b22870baSAlexandre Courbot
nouveau_bo_add_io_reserve_lru(struct ttm_buffer_object * bo)667141b15e5SChristian König void nouveau_bo_add_io_reserve_lru(struct ttm_buffer_object *bo)
668141b15e5SChristian König {
669141b15e5SChristian König struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
670141b15e5SChristian König struct nouveau_bo *nvbo = nouveau_bo(bo);
671141b15e5SChristian König
672141b15e5SChristian König mutex_lock(&drm->ttm.io_reserve_mutex);
673141b15e5SChristian König list_move_tail(&nvbo->io_reserve_lru, &drm->ttm.io_reserve_lru);
674141b15e5SChristian König mutex_unlock(&drm->ttm.io_reserve_mutex);
675141b15e5SChristian König }
676141b15e5SChristian König
nouveau_bo_del_io_reserve_lru(struct ttm_buffer_object * bo)677141b15e5SChristian König void nouveau_bo_del_io_reserve_lru(struct ttm_buffer_object *bo)
678141b15e5SChristian König {
679141b15e5SChristian König struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
680141b15e5SChristian König struct nouveau_bo *nvbo = nouveau_bo(bo);
681141b15e5SChristian König
682141b15e5SChristian König mutex_lock(&drm->ttm.io_reserve_mutex);
683141b15e5SChristian König list_del_init(&nvbo->io_reserve_lru);
684141b15e5SChristian König mutex_unlock(&drm->ttm.io_reserve_mutex);
685141b15e5SChristian König }
686141b15e5SChristian König
6877a45d764SBen Skeggs int
nouveau_bo_validate(struct nouveau_bo * nvbo,bool interruptible,bool no_wait_gpu)6887a45d764SBen Skeggs nouveau_bo_validate(struct nouveau_bo *nvbo, bool interruptible,
68997a875cbSMaarten Lankhorst bool no_wait_gpu)
6907a45d764SBen Skeggs {
69119be5570SChristian König struct ttm_operation_ctx ctx = { interruptible, no_wait_gpu };
6927a45d764SBen Skeggs int ret;
6937a45d764SBen Skeggs
69419be5570SChristian König ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, &ctx);
6957a45d764SBen Skeggs if (ret)
6967a45d764SBen Skeggs return ret;
6977a45d764SBen Skeggs
698b22870baSAlexandre Courbot nouveau_bo_sync_for_device(nvbo);
699b22870baSAlexandre Courbot
7007a45d764SBen Skeggs return 0;
7017a45d764SBen Skeggs }
7027a45d764SBen Skeggs
7036ee73861SBen Skeggs void
nouveau_bo_wr16(struct nouveau_bo * nvbo,unsigned index,u16 val)7046ee73861SBen Skeggs nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val)
7056ee73861SBen Skeggs {
7066ee73861SBen Skeggs bool is_iomem;
7076ee73861SBen Skeggs u16 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
708c3a0c771SAlexandre Courbot
70936a471baSAlexandre Courbot mem += index;
710c3a0c771SAlexandre Courbot
7116ee73861SBen Skeggs if (is_iomem)
7126ee73861SBen Skeggs iowrite16_native(val, (void __force __iomem *)mem);
7136ee73861SBen Skeggs else
7146ee73861SBen Skeggs *mem = val;
7156ee73861SBen Skeggs }
7166ee73861SBen Skeggs
7176ee73861SBen Skeggs u32
nouveau_bo_rd32(struct nouveau_bo * nvbo,unsigned index)7186ee73861SBen Skeggs nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index)
7196ee73861SBen Skeggs {
7206ee73861SBen Skeggs bool is_iomem;
7216ee73861SBen Skeggs u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
722c3a0c771SAlexandre Courbot
72336a471baSAlexandre Courbot mem += index;
724c3a0c771SAlexandre Courbot
7256ee73861SBen Skeggs if (is_iomem)
7266ee73861SBen Skeggs return ioread32_native((void __force __iomem *)mem);
7276ee73861SBen Skeggs else
7286ee73861SBen Skeggs return *mem;
7296ee73861SBen Skeggs }
7306ee73861SBen Skeggs
7316ee73861SBen Skeggs void
nouveau_bo_wr32(struct nouveau_bo * nvbo,unsigned index,u32 val)7326ee73861SBen Skeggs nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val)
7336ee73861SBen Skeggs {
7346ee73861SBen Skeggs bool is_iomem;
7356ee73861SBen Skeggs u32 *mem = ttm_kmap_obj_virtual(&nvbo->kmap, &is_iomem);
736c3a0c771SAlexandre Courbot
73736a471baSAlexandre Courbot mem += index;
738c3a0c771SAlexandre Courbot
7396ee73861SBen Skeggs if (is_iomem)
7406ee73861SBen Skeggs iowrite32_native(val, (void __force __iomem *)mem);
7416ee73861SBen Skeggs else
7426ee73861SBen Skeggs *mem = val;
7436ee73861SBen Skeggs }
7446ee73861SBen Skeggs
745649bf3caSJerome Glisse static struct ttm_tt *
nouveau_ttm_tt_create(struct ttm_buffer_object * bo,uint32_t page_flags)746dde5da23SChristian König nouveau_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags)
7476ee73861SBen Skeggs {
748a7fb8a23SDaniel Vetter #if IS_ENABLED(CONFIG_AGP)
749dde5da23SChristian König struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
7506ee73861SBen Skeggs
751340b0e7cSBen Skeggs if (drm->agp.bridge) {
752dde5da23SChristian König return ttm_agp_tt_create(bo, drm->agp.bridge, page_flags);
7536ee73861SBen Skeggs }
754df1b4b91SMax Filippov #endif
7556ee73861SBen Skeggs
756dde5da23SChristian König return nouveau_sgdma_create_ttm(bo, page_flags);
7576ee73861SBen Skeggs }
7586ee73861SBen Skeggs
7598635784aSDave Airlie static int
nouveau_ttm_tt_bind(struct ttm_device * bdev,struct ttm_tt * ttm,struct ttm_resource * reg)7608af8a109SChristian König nouveau_ttm_tt_bind(struct ttm_device *bdev, struct ttm_tt *ttm,
7618635784aSDave Airlie struct ttm_resource *reg)
7628635784aSDave Airlie {
7638635784aSDave Airlie #if IS_ENABLED(CONFIG_AGP)
7648635784aSDave Airlie struct nouveau_drm *drm = nouveau_bdev(bdev);
7650b988ca1SDave Airlie #endif
7660b988ca1SDave Airlie if (!reg)
7670b988ca1SDave Airlie return -EINVAL;
7680b988ca1SDave Airlie #if IS_ENABLED(CONFIG_AGP)
7698635784aSDave Airlie if (drm->agp.bridge)
77048efa57eSDave Airlie return ttm_agp_bind(ttm, reg);
7718635784aSDave Airlie #endif
7728635784aSDave Airlie return nouveau_sgdma_bind(bdev, ttm, reg);
7738635784aSDave Airlie }
7748635784aSDave Airlie
7758635784aSDave Airlie static void
nouveau_ttm_tt_unbind(struct ttm_device * bdev,struct ttm_tt * ttm)7768af8a109SChristian König nouveau_ttm_tt_unbind(struct ttm_device *bdev, struct ttm_tt *ttm)
7778635784aSDave Airlie {
7788635784aSDave Airlie #if IS_ENABLED(CONFIG_AGP)
7798635784aSDave Airlie struct nouveau_drm *drm = nouveau_bdev(bdev);
7808635784aSDave Airlie
7818635784aSDave Airlie if (drm->agp.bridge) {
78248efa57eSDave Airlie ttm_agp_unbind(ttm);
7838635784aSDave Airlie return;
7848635784aSDave Airlie }
7858635784aSDave Airlie #endif
7868635784aSDave Airlie nouveau_sgdma_unbind(bdev, ttm);
7878635784aSDave Airlie }
7888635784aSDave Airlie
7896ee73861SBen Skeggs static void
nouveau_bo_evict_flags(struct ttm_buffer_object * bo,struct ttm_placement * pl)7906ee73861SBen Skeggs nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
7916ee73861SBen Skeggs {
7926ee73861SBen Skeggs struct nouveau_bo *nvbo = nouveau_bo(bo);
7936ee73861SBen Skeggs
794d3116756SChristian König switch (bo->resource->mem_type) {
79522fbd538SFrancisco Jerez case TTM_PL_VRAM:
79681b61579SChristian König nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART,
79781b61579SChristian König NOUVEAU_GEM_DOMAIN_CPU);
79822fbd538SFrancisco Jerez break;
7996ee73861SBen Skeggs default:
80081b61579SChristian König nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_CPU, 0);
8016ee73861SBen Skeggs break;
8026ee73861SBen Skeggs }
80322fbd538SFrancisco Jerez
80422fbd538SFrancisco Jerez *pl = nvbo->placement;
8056ee73861SBen Skeggs }
8066ee73861SBen Skeggs
807f1ab0cc9SBen Skeggs static int
nouveau_bo_move_prep(struct nouveau_drm * drm,struct ttm_buffer_object * bo,struct ttm_resource * reg)8083c57d85dSBen Skeggs nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo,
8092966141aSDave Airlie struct ttm_resource *reg)
810d2f96666SBen Skeggs {
811d3116756SChristian König struct nouveau_mem *old_mem = nouveau_mem(bo->resource);
8129ce523ccSBen Skeggs struct nouveau_mem *new_mem = nouveau_mem(reg);
813d7722134SBen Skeggs struct nvif_vmm *vmm = &drm->client.vmm.vmm;
814d2f96666SBen Skeggs int ret;
815d2f96666SBen Skeggs
816d7722134SBen Skeggs ret = nvif_vmm_get(vmm, LAZY, false, old_mem->mem.page, 0,
817d7722134SBen Skeggs old_mem->mem.size, &old_mem->vma[0]);
818d2f96666SBen Skeggs if (ret)
819d2f96666SBen Skeggs return ret;
820d2f96666SBen Skeggs
821d7722134SBen Skeggs ret = nvif_vmm_get(vmm, LAZY, false, new_mem->mem.page, 0,
822d7722134SBen Skeggs new_mem->mem.size, &old_mem->vma[1]);
823d7722134SBen Skeggs if (ret)
824d7722134SBen Skeggs goto done;
8253c57d85dSBen Skeggs
8269ce523ccSBen Skeggs ret = nouveau_mem_map(old_mem, vmm, &old_mem->vma[0]);
8279ce523ccSBen Skeggs if (ret)
8289ce523ccSBen Skeggs goto done;
8299ce523ccSBen Skeggs
8309ce523ccSBen Skeggs ret = nouveau_mem_map(new_mem, vmm, &old_mem->vma[1]);
8319ce523ccSBen Skeggs done:
8329ce523ccSBen Skeggs if (ret) {
833d7722134SBen Skeggs nvif_vmm_put(vmm, &old_mem->vma[1]);
834d7722134SBen Skeggs nvif_vmm_put(vmm, &old_mem->vma[0]);
8359ce523ccSBen Skeggs }
836d2f96666SBen Skeggs return 0;
837d2f96666SBen Skeggs }
838d2f96666SBen Skeggs
839d2f96666SBen Skeggs static int
nouveau_bo_move_m2mf(struct ttm_buffer_object * bo,int evict,struct ttm_operation_ctx * ctx,struct ttm_resource * new_reg)84054661867SDave Airlie nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
84154661867SDave Airlie struct ttm_operation_ctx *ctx,
84254661867SDave Airlie struct ttm_resource *new_reg)
843f1ab0cc9SBen Skeggs {
844ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
8451934a2adSDave Jones struct nouveau_channel *chan = drm->ttm.chan;
846*0aac3fb6SBen Skeggs struct nouveau_cli *cli = chan->cli;
84735b8141bSBen Skeggs struct nouveau_fence *fence;
848f1ab0cc9SBen Skeggs int ret;
849f1ab0cc9SBen Skeggs
850d2f96666SBen Skeggs /* create temporary vmas for the transfer and attach them to the
851be83cd4eSBen Skeggs * old nvkm_mem node, these will get cleaned up after ttm has
8522966141aSDave Airlie * destroyed the ttm_resource
8533425df48SBen Skeggs */
8541167c6bcSBen Skeggs if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
855605f9ccdSBen Skeggs ret = nouveau_bo_move_prep(drm, bo, new_reg);
8563425df48SBen Skeggs if (ret)
8573c57d85dSBen Skeggs return ret;
8583425df48SBen Skeggs }
8593425df48SBen Skeggs
860551620f2SDaniel Vetter if (drm_drv_uses_atomic_modeset(drm->dev))
861551620f2SDaniel Vetter mutex_lock(&cli->mutex);
862551620f2SDaniel Vetter else
8630ad72863SBen Skeggs mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
8647f2a0b50SDanilo Krummrich
86554661867SDave Airlie ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, ctx->interruptible);
8667f2a0b50SDanilo Krummrich if (ret)
8677f2a0b50SDanilo Krummrich goto out_unlock;
8687f2a0b50SDanilo Krummrich
869d3116756SChristian König ret = drm->ttm.move(chan, bo, bo->resource, new_reg);
8707f2a0b50SDanilo Krummrich if (ret)
8717f2a0b50SDanilo Krummrich goto out_unlock;
8727f2a0b50SDanilo Krummrich
873978474dcSDanilo Krummrich ret = nouveau_fence_new(&fence, chan);
8747f2a0b50SDanilo Krummrich if (ret)
8757f2a0b50SDanilo Krummrich goto out_unlock;
8767f2a0b50SDanilo Krummrich
8776b04ce96SKarol Herbst /* TODO: figure out a better solution here
8786b04ce96SKarol Herbst *
8796b04ce96SKarol Herbst * wait on the fence here explicitly as going through
8806b04ce96SKarol Herbst * ttm_bo_move_accel_cleanup somehow doesn't seem to do it.
8816b04ce96SKarol Herbst *
8826b04ce96SKarol Herbst * Without this the operation can timeout and we'll fallback to a
8836b04ce96SKarol Herbst * software copy, which might take several minutes to finish.
8846b04ce96SKarol Herbst */
8856b04ce96SKarol Herbst nouveau_fence_wait(fence, false, false);
8867f2a0b50SDanilo Krummrich ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false,
887605f9ccdSBen Skeggs new_reg);
88835b8141bSBen Skeggs nouveau_fence_unref(&fence);
8897f2a0b50SDanilo Krummrich
8907f2a0b50SDanilo Krummrich out_unlock:
8910ad72863SBen Skeggs mutex_unlock(&cli->mutex);
8926a6b73f2SBen Skeggs return ret;
8936ee73861SBen Skeggs }
8946ee73861SBen Skeggs
895d1b167e1SBen Skeggs void
nouveau_bo_move_init(struct nouveau_drm * drm)89649981046SBen Skeggs nouveau_bo_move_init(struct nouveau_drm *drm)
897d1b167e1SBen Skeggs {
89872ecb0a6SJames Jones static const struct _method_table {
899d1b167e1SBen Skeggs const char *name;
9001a46098eSBen Skeggs int engine;
901315a8b2eSBen Skeggs s32 oclass;
902d1b167e1SBen Skeggs int (*exec)(struct nouveau_channel *,
903d1b167e1SBen Skeggs struct ttm_buffer_object *,
9042966141aSDave Airlie struct ttm_resource *, struct ttm_resource *);
905d1b167e1SBen Skeggs int (*init)(struct nouveau_channel *, u32 handle);
906d1b167e1SBen Skeggs } _methods[] = {
90749b2dfc0SBen Skeggs { "COPY", 4, 0xc7b5, nve0_bo_move_copy, nve0_bo_move_init },
90805d271c3SBen Skeggs { "GRCE", 0, 0xc7b5, nve0_bo_move_copy, nvc0_bo_move_init },
90905d271c3SBen Skeggs { "COPY", 4, 0xc6b5, nve0_bo_move_copy, nve0_bo_move_init },
91005d271c3SBen Skeggs { "GRCE", 0, 0xc6b5, nve0_bo_move_copy, nvc0_bo_move_init },
911c36322d2SBen Skeggs { "COPY", 4, 0xc5b5, nve0_bo_move_copy, nve0_bo_move_init },
912c36322d2SBen Skeggs { "GRCE", 0, 0xc5b5, nve0_bo_move_copy, nvc0_bo_move_init },
9136e1f34e3SBen Skeggs { "COPY", 4, 0xc3b5, nve0_bo_move_copy, nve0_bo_move_init },
9146e1f34e3SBen Skeggs { "GRCE", 0, 0xc3b5, nve0_bo_move_copy, nvc0_bo_move_init },
915146cfe24SBen Skeggs { "COPY", 4, 0xc1b5, nve0_bo_move_copy, nve0_bo_move_init },
916146cfe24SBen Skeggs { "GRCE", 0, 0xc1b5, nve0_bo_move_copy, nvc0_bo_move_init },
9178e7e1586SBen Skeggs { "COPY", 4, 0xc0b5, nve0_bo_move_copy, nve0_bo_move_init },
9188e7e1586SBen Skeggs { "GRCE", 0, 0xc0b5, nve0_bo_move_copy, nvc0_bo_move_init },
919990b4547SBen Skeggs { "COPY", 4, 0xb0b5, nve0_bo_move_copy, nve0_bo_move_init },
920990b4547SBen Skeggs { "GRCE", 0, 0xb0b5, nve0_bo_move_copy, nvc0_bo_move_init },
92100fc6f6fSBen Skeggs { "COPY", 4, 0xa0b5, nve0_bo_move_copy, nve0_bo_move_init },
92249981046SBen Skeggs { "GRCE", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init },
9231a46098eSBen Skeggs { "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init },
9241a46098eSBen Skeggs { "COPY0", 4, 0x90b5, nvc0_bo_move_copy, nvc0_bo_move_init },
9251a46098eSBen Skeggs { "COPY", 0, 0x85b5, nva3_bo_move_copy, nv50_bo_move_init },
9261a46098eSBen Skeggs { "CRYPT", 0, 0x74c1, nv84_bo_move_exec, nv50_bo_move_init },
9271a46098eSBen Skeggs { "M2MF", 0, 0x9039, nvc0_bo_move_m2mf, nvc0_bo_move_init },
9281a46098eSBen Skeggs { "M2MF", 0, 0x5039, nv50_bo_move_m2mf, nv50_bo_move_init },
9291a46098eSBen Skeggs { "M2MF", 0, 0x0039, nv04_bo_move_m2mf, nv04_bo_move_init },
9305490e5dfSBen Skeggs {},
93172ecb0a6SJames Jones };
93272ecb0a6SJames Jones const struct _method_table *mthd = _methods;
933d1b167e1SBen Skeggs const char *name = "CPU";
934d1b167e1SBen Skeggs int ret;
935d1b167e1SBen Skeggs
936d1b167e1SBen Skeggs do {
93749981046SBen Skeggs struct nouveau_channel *chan;
938ebb945a9SBen Skeggs
93900fc6f6fSBen Skeggs if (mthd->engine)
94049981046SBen Skeggs chan = drm->cechan;
94149981046SBen Skeggs else
94249981046SBen Skeggs chan = drm->channel;
94349981046SBen Skeggs if (chan == NULL)
94449981046SBen Skeggs continue;
94549981046SBen Skeggs
9469ac596a4SBen Skeggs ret = nvif_object_ctor(&chan->user, "ttmBoMove",
9470ad72863SBen Skeggs mthd->oclass | (mthd->engine << 16),
9480ad72863SBen Skeggs mthd->oclass, NULL, 0,
9490ad72863SBen Skeggs &drm->ttm.copy);
950d1b167e1SBen Skeggs if (ret == 0) {
9510ad72863SBen Skeggs ret = mthd->init(chan, drm->ttm.copy.handle);
952ebb945a9SBen Skeggs if (ret) {
9539ac596a4SBen Skeggs nvif_object_dtor(&drm->ttm.copy);
954ebb945a9SBen Skeggs continue;
955ebb945a9SBen Skeggs }
956ebb945a9SBen Skeggs
957ebb945a9SBen Skeggs drm->ttm.move = mthd->exec;
9581bb3f6a2SBen Skeggs drm->ttm.chan = chan;
959d1b167e1SBen Skeggs name = mthd->name;
960d1b167e1SBen Skeggs break;
961d1b167e1SBen Skeggs }
962d1b167e1SBen Skeggs } while ((++mthd)->exec);
963d1b167e1SBen Skeggs
964ebb945a9SBen Skeggs NV_INFO(drm, "MM: using %s for buffer copies\n", name);
965d1b167e1SBen Skeggs }
966d1b167e1SBen Skeggs
nouveau_bo_move_ntfy(struct ttm_buffer_object * bo,struct ttm_resource * new_reg)9675ea143c3SChristian König static void nouveau_bo_move_ntfy(struct ttm_buffer_object *bo,
9682966141aSDave Airlie struct ttm_resource *new_reg)
969a4154bbfSBen Skeggs {
9709ce523ccSBen Skeggs struct nouveau_mem *mem = new_reg ? nouveau_mem(new_reg) : NULL;
971a4154bbfSBen Skeggs struct nouveau_bo *nvbo = nouveau_bo(bo);
97224e8375bSBen Skeggs struct nouveau_vma *vma;
97341d351f2SChristian König long ret;
974a4154bbfSBen Skeggs
9759f1feed2SBen Skeggs /* ttm can now (stupidly) pass the driver bos it didn't create... */
9769f1feed2SBen Skeggs if (bo->destroy != nouveau_bo_del_ttm)
9779f1feed2SBen Skeggs return;
9789f1feed2SBen Skeggs
979141b15e5SChristian König nouveau_bo_del_io_reserve_lru(bo);
980141b15e5SChristian König
981425b34f7SBen Skeggs if (mem && new_reg->mem_type != TTM_PL_SYSTEM &&
9829ce523ccSBen Skeggs mem->mem.page == nvbo->page) {
983a48296abSBen Skeggs list_for_each_entry(vma, &nvbo->vma_list, head) {
98424e8375bSBen Skeggs nouveau_vma_map(vma, mem);
985a48296abSBen Skeggs }
986b88baab8SDanilo Krummrich nouveau_uvmm_bo_map_all(nvbo, mem);
987d2f96666SBen Skeggs } else {
988a48296abSBen Skeggs list_for_each_entry(vma, &nvbo->vma_list, head) {
98941d351f2SChristian König ret = dma_resv_wait_timeout(bo->base.resv,
99041d351f2SChristian König DMA_RESV_USAGE_BOOKKEEP,
99141d351f2SChristian König false, 15 * HZ);
99241d351f2SChristian König WARN_ON(ret <= 0);
99324e8375bSBen Skeggs nouveau_vma_unmap(vma);
994fd2871afSBen Skeggs }
995b88baab8SDanilo Krummrich nouveau_uvmm_bo_unmap_all(nvbo);
996a4154bbfSBen Skeggs }
9970dc9b286SNirmoy Das
998cb1c8146SChristian König if (new_reg)
9990dc9b286SNirmoy Das nvbo->offset = (new_reg->start << PAGE_SHIFT);
10000dc9b286SNirmoy Das
1001a4154bbfSBen Skeggs }
1002a4154bbfSBen Skeggs
10036ee73861SBen Skeggs static int
nouveau_bo_vm_bind(struct ttm_buffer_object * bo,struct ttm_resource * new_reg,struct nouveau_drm_tile ** new_tile)10042966141aSDave Airlie nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_resource *new_reg,
1005ebb945a9SBen Skeggs struct nouveau_drm_tile **new_tile)
10066ee73861SBen Skeggs {
1007ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1008ebb945a9SBen Skeggs struct drm_device *dev = drm->dev;
1009a0af9addSFrancisco Jerez struct nouveau_bo *nvbo = nouveau_bo(bo);
1010605f9ccdSBen Skeggs u64 offset = new_reg->start << PAGE_SHIFT;
10116ee73861SBen Skeggs
1012a0af9addSFrancisco Jerez *new_tile = NULL;
1013605f9ccdSBen Skeggs if (new_reg->mem_type != TTM_PL_VRAM)
1014a0af9addSFrancisco Jerez return 0;
10156ee73861SBen Skeggs
10161167c6bcSBen Skeggs if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) {
1017e11bfb99SChristian König *new_tile = nv10_bo_set_tiling(dev, offset, bo->base.size,
10187760a2e3SBen Skeggs nvbo->mode, nvbo->zeta);
10196ee73861SBen Skeggs }
10206ee73861SBen Skeggs
1021a0af9addSFrancisco Jerez return 0;
1022a0af9addSFrancisco Jerez }
10236ee73861SBen Skeggs
1024a0af9addSFrancisco Jerez static void
nouveau_bo_vm_cleanup(struct ttm_buffer_object * bo,struct nouveau_drm_tile * new_tile,struct nouveau_drm_tile ** old_tile)1025a0af9addSFrancisco Jerez nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo,
1026ebb945a9SBen Skeggs struct nouveau_drm_tile *new_tile,
1027ebb945a9SBen Skeggs struct nouveau_drm_tile **old_tile)
1028a0af9addSFrancisco Jerez {
1029ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1030ebb945a9SBen Skeggs struct drm_device *dev = drm->dev;
1031756cc94dSChristian König struct dma_fence *fence;
1032756cc94dSChristian König int ret;
1033756cc94dSChristian König
10347bc80a54SChristian König ret = dma_resv_get_singleton(bo->base.resv, DMA_RESV_USAGE_WRITE,
10357bc80a54SChristian König &fence);
1036756cc94dSChristian König if (ret)
10377bc80a54SChristian König dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_WRITE,
10387bc80a54SChristian König false, MAX_SCHEDULE_TIMEOUT);
1039a0af9addSFrancisco Jerez
1040f2c24b83SMaarten Lankhorst nv10_bo_put_tile_region(dev, *old_tile, fence);
1041a0af9addSFrancisco Jerez *old_tile = new_tile;
1042a0af9addSFrancisco Jerez }
1043a0af9addSFrancisco Jerez
1044a0af9addSFrancisco Jerez static int
nouveau_bo_move(struct ttm_buffer_object * bo,bool evict,struct ttm_operation_ctx * ctx,struct ttm_resource * new_reg,struct ttm_place * hop)10452823f4f0SChristian König nouveau_bo_move(struct ttm_buffer_object *bo, bool evict,
10462823f4f0SChristian König struct ttm_operation_ctx *ctx,
1047ebdf5651SDave Airlie struct ttm_resource *new_reg,
1048ebdf5651SDave Airlie struct ttm_place *hop)
1049a0af9addSFrancisco Jerez {
1050ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1051a0af9addSFrancisco Jerez struct nouveau_bo *nvbo = nouveau_bo(bo);
1052d3116756SChristian König struct ttm_resource *old_reg = bo->resource;
1053ebb945a9SBen Skeggs struct nouveau_drm_tile *new_tile = NULL;
1054a0af9addSFrancisco Jerez int ret = 0;
1055a0af9addSFrancisco Jerez
10560c8c0659SDave Airlie
1057bfe5e585SDave Airlie if (new_reg->mem_type == TTM_PL_TT) {
1058bfe5e585SDave Airlie ret = nouveau_ttm_tt_bind(bo->bdev, bo->ttm, new_reg);
105988932a7bSChristian König if (ret)
106088932a7bSChristian König return ret;
1061bfe5e585SDave Airlie }
106288932a7bSChristian König
10635ea143c3SChristian König nouveau_bo_move_ntfy(bo, new_reg);
10640ef1ed81SDave Airlie ret = ttm_bo_wait_ctx(bo, ctx);
10655be5a15aSAlexandre Courbot if (ret)
10666d820003SDave Airlie goto out_ntfy;
1067967e7bdeSBen Skeggs
10681167c6bcSBen Skeggs if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
1069605f9ccdSBen Skeggs ret = nouveau_bo_vm_bind(bo, new_reg, &new_tile);
1070a0af9addSFrancisco Jerez if (ret)
10716d820003SDave Airlie goto out_ntfy;
1072a4154bbfSBen Skeggs }
1073a0af9addSFrancisco Jerez
1074a0af9addSFrancisco Jerez /* Fake bo copy. */
107564e257f1SChristian König if (!old_reg || (old_reg->mem_type == TTM_PL_SYSTEM &&
107664e257f1SChristian König !bo->ttm)) {
1077ecfe6953SDave Airlie ttm_bo_move_null(bo, new_reg);
1078a0af9addSFrancisco Jerez goto out;
10796ee73861SBen Skeggs }
10806ee73861SBen Skeggs
108112b68474SDave Airlie if (old_reg->mem_type == TTM_PL_SYSTEM &&
108212b68474SDave Airlie new_reg->mem_type == TTM_PL_TT) {
108312b68474SDave Airlie ttm_bo_move_null(bo, new_reg);
108412b68474SDave Airlie goto out;
108512b68474SDave Airlie }
108612b68474SDave Airlie
108712b68474SDave Airlie if (old_reg->mem_type == TTM_PL_TT &&
108812b68474SDave Airlie new_reg->mem_type == TTM_PL_SYSTEM) {
108929a1d482SDave Airlie nouveau_ttm_tt_unbind(bo->bdev, bo->ttm);
1090bfa3357eSChristian König ttm_resource_free(bo, &bo->resource);
1091c37d951cSDave Airlie ttm_bo_assign_mem(bo, new_reg);
109212b68474SDave Airlie goto out;
109312b68474SDave Airlie }
109412b68474SDave Airlie
1095a0af9addSFrancisco Jerez /* Hardware assisted copy. */
1096cef9e99eSBen Skeggs if (drm->ttm.move) {
1097660a5995SDave Airlie if ((old_reg->mem_type == TTM_PL_SYSTEM &&
1098660a5995SDave Airlie new_reg->mem_type == TTM_PL_VRAM) ||
1099660a5995SDave Airlie (old_reg->mem_type == TTM_PL_VRAM &&
1100660a5995SDave Airlie new_reg->mem_type == TTM_PL_SYSTEM)) {
1101660a5995SDave Airlie hop->fpfn = 0;
1102660a5995SDave Airlie hop->lpfn = 0;
1103660a5995SDave Airlie hop->mem_type = TTM_PL_TT;
1104660a5995SDave Airlie hop->flags = 0;
1105660a5995SDave Airlie return -EMULTIHOP;
1106660a5995SDave Airlie }
110754661867SDave Airlie ret = nouveau_bo_move_m2mf(bo, evict, ctx,
110854661867SDave Airlie new_reg);
1109660a5995SDave Airlie } else
1110660a5995SDave Airlie ret = -ENODEV;
1111a0af9addSFrancisco Jerez
1112660a5995SDave Airlie if (ret) {
1113a0af9addSFrancisco Jerez /* Fallback to software copy. */
11143e98d829SRoger He ret = ttm_bo_move_memcpy(bo, ctx, new_reg);
1115660a5995SDave Airlie }
1116a0af9addSFrancisco Jerez
1117a0af9addSFrancisco Jerez out:
11181167c6bcSBen Skeggs if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) {
1119a0af9addSFrancisco Jerez if (ret)
1120a0af9addSFrancisco Jerez nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
1121a0af9addSFrancisco Jerez else
1122a0af9addSFrancisco Jerez nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
1123a4154bbfSBen Skeggs }
11246d820003SDave Airlie out_ntfy:
11256d820003SDave Airlie if (ret) {
1126d3116756SChristian König nouveau_bo_move_ntfy(bo, bo->resource);
11276d820003SDave Airlie }
1128a0af9addSFrancisco Jerez return ret;
11296ee73861SBen Skeggs }
11306ee73861SBen Skeggs
1131141b15e5SChristian König static void
nouveau_ttm_io_mem_free_locked(struct nouveau_drm * drm,struct ttm_resource * reg)1132141b15e5SChristian König nouveau_ttm_io_mem_free_locked(struct nouveau_drm *drm,
1133141b15e5SChristian König struct ttm_resource *reg)
1134141b15e5SChristian König {
1135141b15e5SChristian König struct nouveau_mem *mem = nouveau_mem(reg);
1136141b15e5SChristian König
1137141b15e5SChristian König if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
1138141b15e5SChristian König switch (reg->mem_type) {
1139141b15e5SChristian König case TTM_PL_TT:
1140141b15e5SChristian König if (mem->kind)
1141141b15e5SChristian König nvif_object_unmap_handle(&mem->mem.object);
1142141b15e5SChristian König break;
1143141b15e5SChristian König case TTM_PL_VRAM:
1144141b15e5SChristian König nvif_object_unmap_handle(&mem->mem.object);
1145141b15e5SChristian König break;
1146141b15e5SChristian König default:
1147141b15e5SChristian König break;
1148141b15e5SChristian König }
1149141b15e5SChristian König }
1150141b15e5SChristian König }
1151141b15e5SChristian König
1152f32f02fdSJerome Glisse static int
nouveau_ttm_io_mem_reserve(struct ttm_device * bdev,struct ttm_resource * reg)11538af8a109SChristian König nouveau_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *reg)
1154f32f02fdSJerome Glisse {
1155ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bdev);
11561167c6bcSBen Skeggs struct nvkm_device *device = nvxx_device(&drm->client.device);
11579ce523ccSBen Skeggs struct nouveau_mem *mem = nouveau_mem(reg);
11581cf65c45SChristian König struct nvif_mmu *mmu = &drm->client.mmu;
1159141b15e5SChristian König int ret;
1160f32f02fdSJerome Glisse
1161141b15e5SChristian König mutex_lock(&drm->ttm.io_reserve_mutex);
1162141b15e5SChristian König retry:
1163605f9ccdSBen Skeggs switch (reg->mem_type) {
1164f32f02fdSJerome Glisse case TTM_PL_SYSTEM:
1165f32f02fdSJerome Glisse /* System memory */
1166141b15e5SChristian König ret = 0;
1167141b15e5SChristian König goto out;
1168f32f02fdSJerome Glisse case TTM_PL_TT:
1169a7fb8a23SDaniel Vetter #if IS_ENABLED(CONFIG_AGP)
1170340b0e7cSBen Skeggs if (drm->agp.bridge) {
117154d04ea8SChristian König reg->bus.offset = (reg->start << PAGE_SHIFT) +
117254d04ea8SChristian König drm->agp.base;
1173605f9ccdSBen Skeggs reg->bus.is_iomem = !drm->agp.cma;
11741cf65c45SChristian König reg->bus.caching = ttm_write_combined;
1175f32f02fdSJerome Glisse }
1176f32f02fdSJerome Glisse #endif
1177141b15e5SChristian König if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 ||
1178141b15e5SChristian König !mem->kind) {
1179a5540906SMaarten Lankhorst /* untiled */
1180141b15e5SChristian König ret = 0;
1181f32f02fdSJerome Glisse break;
1182141b15e5SChristian König }
1183f6e7393eSGustavo A. R. Silva fallthrough; /* tiled memory */
1184f32f02fdSJerome Glisse case TTM_PL_VRAM:
118554d04ea8SChristian König reg->bus.offset = (reg->start << PAGE_SHIFT) +
118654d04ea8SChristian König device->func->resource_addr(device, 1);
1187605f9ccdSBen Skeggs reg->bus.is_iomem = true;
11881cf65c45SChristian König
11891cf65c45SChristian König /* Some BARs do not support being ioremapped WC */
11901cf65c45SChristian König if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA &&
1191be323a4cSBen Skeggs mmu->type[drm->ttm.type_vram].type & NVIF_MEM_UNCACHED)
11921cf65c45SChristian König reg->bus.caching = ttm_uncached;
11931cf65c45SChristian König else
11941cf65c45SChristian König reg->bus.caching = ttm_write_combined;
11951cf65c45SChristian König
1196d7722134SBen Skeggs if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) {
1197d7722134SBen Skeggs union {
1198d7722134SBen Skeggs struct nv50_mem_map_v0 nv50;
1199d7722134SBen Skeggs struct gf100_mem_map_v0 gf100;
1200d7722134SBen Skeggs } args;
1201d7722134SBen Skeggs u64 handle, length;
1202d7722134SBen Skeggs u32 argc = 0;
1203f869ef88SBen Skeggs
1204d7722134SBen Skeggs switch (mem->mem.object.oclass) {
1205d7722134SBen Skeggs case NVIF_CLASS_MEM_NV50:
1206d7722134SBen Skeggs args.nv50.version = 0;
1207d7722134SBen Skeggs args.nv50.ro = 0;
1208d7722134SBen Skeggs args.nv50.kind = mem->kind;
1209d7722134SBen Skeggs args.nv50.comp = mem->comp;
1210b554b12aSThierry Reding argc = sizeof(args.nv50);
1211d7722134SBen Skeggs break;
1212d7722134SBen Skeggs case NVIF_CLASS_MEM_GF100:
1213d7722134SBen Skeggs args.gf100.version = 0;
1214d7722134SBen Skeggs args.gf100.ro = 0;
1215d7722134SBen Skeggs args.gf100.kind = mem->kind;
1216b554b12aSThierry Reding argc = sizeof(args.gf100);
1217d7722134SBen Skeggs break;
1218d7722134SBen Skeggs default:
1219d7722134SBen Skeggs WARN_ON(1);
1220d7722134SBen Skeggs break;
1221d7722134SBen Skeggs }
1222f869ef88SBen Skeggs
1223d7722134SBen Skeggs ret = nvif_object_map_handle(&mem->mem.object,
1224b554b12aSThierry Reding &args, argc,
1225d7722134SBen Skeggs &handle, &length);
12268a39db76SBen Skeggs if (ret != 1) {
12278a39db76SBen Skeggs if (WARN_ON(ret == 0))
1228141b15e5SChristian König ret = -EINVAL;
1229141b15e5SChristian König goto out;
12308a39db76SBen Skeggs }
1231d7722134SBen Skeggs
1232d7722134SBen Skeggs reg->bus.offset = handle;
1233f869ef88SBen Skeggs }
1234aea656b0SChristian König ret = 0;
1235f869ef88SBen Skeggs break;
1236f32f02fdSJerome Glisse default:
1237141b15e5SChristian König ret = -EINVAL;
1238f32f02fdSJerome Glisse }
1239141b15e5SChristian König
1240141b15e5SChristian König out:
1241141b15e5SChristian König if (ret == -ENOSPC) {
1242141b15e5SChristian König struct nouveau_bo *nvbo;
1243141b15e5SChristian König
1244141b15e5SChristian König nvbo = list_first_entry_or_null(&drm->ttm.io_reserve_lru,
1245141b15e5SChristian König typeof(*nvbo),
1246141b15e5SChristian König io_reserve_lru);
1247141b15e5SChristian König if (nvbo) {
1248141b15e5SChristian König list_del_init(&nvbo->io_reserve_lru);
1249141b15e5SChristian König drm_vma_node_unmap(&nvbo->bo.base.vma_node,
1250141b15e5SChristian König bdev->dev_mapping);
1251d3116756SChristian König nouveau_ttm_io_mem_free_locked(drm, nvbo->bo.resource);
1252123c3bccSDave Airlie nvbo->bo.resource->bus.offset = 0;
1253123c3bccSDave Airlie nvbo->bo.resource->bus.addr = NULL;
1254141b15e5SChristian König goto retry;
1255141b15e5SChristian König }
1256141b15e5SChristian König
1257141b15e5SChristian König }
1258141b15e5SChristian König mutex_unlock(&drm->ttm.io_reserve_mutex);
1259141b15e5SChristian König return ret;
1260f32f02fdSJerome Glisse }
1261f32f02fdSJerome Glisse
1262f32f02fdSJerome Glisse static void
nouveau_ttm_io_mem_free(struct ttm_device * bdev,struct ttm_resource * reg)12638af8a109SChristian König nouveau_ttm_io_mem_free(struct ttm_device *bdev, struct ttm_resource *reg)
1264f32f02fdSJerome Glisse {
1265d7722134SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bdev);
1266f869ef88SBen Skeggs
1267141b15e5SChristian König mutex_lock(&drm->ttm.io_reserve_mutex);
1268141b15e5SChristian König nouveau_ttm_io_mem_free_locked(drm, reg);
1269141b15e5SChristian König mutex_unlock(&drm->ttm.io_reserve_mutex);
1270f32f02fdSJerome Glisse }
1271f32f02fdSJerome Glisse
nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object * bo)127276fe313aSChristian König vm_fault_t nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
1273f32f02fdSJerome Glisse {
1274ebb945a9SBen Skeggs struct nouveau_drm *drm = nouveau_bdev(bo->bdev);
1275e1429b4cSBen Skeggs struct nouveau_bo *nvbo = nouveau_bo(bo);
12761167c6bcSBen Skeggs struct nvkm_device *device = nvxx_device(&drm->client.device);
12777e8820feSBen Skeggs u32 mappable = device->func->resource_size(device, 1) >> PAGE_SHIFT;
1278f1217ed0SChristian König int i, ret;
1279e1429b4cSBen Skeggs
1280e1429b4cSBen Skeggs /* as long as the bo isn't in vram, and isn't tiled, we've got
1281e1429b4cSBen Skeggs * nothing to do here.
1282e1429b4cSBen Skeggs */
1283d3116756SChristian König if (bo->resource->mem_type != TTM_PL_VRAM) {
12841167c6bcSBen Skeggs if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA ||
12857760a2e3SBen Skeggs !nvbo->kind)
1286f32f02fdSJerome Glisse return 0;
1287a5540906SMaarten Lankhorst
1288d3116756SChristian König if (bo->resource->mem_type != TTM_PL_SYSTEM)
1289a5540906SMaarten Lankhorst return 0;
1290f32f02fdSJerome Glisse
129176fe313aSChristian König nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_GART, 0);
129276fe313aSChristian König
129376fe313aSChristian König } else {
1294e1429b4cSBen Skeggs /* make sure bo is in mappable vram */
12951167c6bcSBen Skeggs if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA ||
1296e3c92eb4SSomalapuram Amaranath bo->resource->start + PFN_UP(bo->resource->size) < mappable)
1297e1429b4cSBen Skeggs return 0;
1298e1429b4cSBen Skeggs
1299f1217ed0SChristian König for (i = 0; i < nvbo->placement.num_placement; ++i) {
1300f1217ed0SChristian König nvbo->placements[i].fpfn = 0;
1301f1217ed0SChristian König nvbo->placements[i].lpfn = mappable;
1302f1217ed0SChristian König }
1303e1429b4cSBen Skeggs
1304f1217ed0SChristian König for (i = 0; i < nvbo->placement.num_busy_placement; ++i) {
1305f1217ed0SChristian König nvbo->busy_placements[i].fpfn = 0;
1306f1217ed0SChristian König nvbo->busy_placements[i].lpfn = mappable;
1307f1217ed0SChristian König }
1308f1217ed0SChristian König
130981b61579SChristian König nouveau_bo_placement_set(nvbo, NOUVEAU_GEM_DOMAIN_VRAM, 0);
131076fe313aSChristian König }
131176fe313aSChristian König
131276fe313aSChristian König ret = nouveau_bo_validate(nvbo, false, false);
131376fe313aSChristian König if (unlikely(ret == -EBUSY || ret == -ERESTARTSYS))
131476fe313aSChristian König return VM_FAULT_NOPAGE;
131576fe313aSChristian König else if (unlikely(ret))
131676fe313aSChristian König return VM_FAULT_SIGBUS;
131776fe313aSChristian König
131876fe313aSChristian König ttm_bo_move_to_lru_tail_unlocked(bo);
131976fe313aSChristian König return 0;
1320e1429b4cSBen Skeggs }
1321e1429b4cSBen Skeggs
13223230cfc3SKonrad Rzeszutek Wilk static int
nouveau_ttm_tt_populate(struct ttm_device * bdev,struct ttm_tt * ttm,struct ttm_operation_ctx * ctx)13238af8a109SChristian König nouveau_ttm_tt_populate(struct ttm_device *bdev,
13240a667b50SDave Airlie struct ttm_tt *ttm, struct ttm_operation_ctx *ctx)
13253230cfc3SKonrad Rzeszutek Wilk {
1326e34b8feeSChristian König struct ttm_tt *ttm_dma = (void *)ttm;
1327ebb945a9SBen Skeggs struct nouveau_drm *drm;
132843d46f0bSMatthew Auld bool slave = !!(ttm->page_flags & TTM_TT_FLAG_EXTERNAL);
13293230cfc3SKonrad Rzeszutek Wilk
13307eec9151SDave Airlie if (ttm_tt_is_populated(ttm))
13313230cfc3SKonrad Rzeszutek Wilk return 0;
13323230cfc3SKonrad Rzeszutek Wilk
133322b33e8eSDave Airlie if (slave && ttm->sg) {
1334c67e6279SChristian König drm_prime_sg_to_dma_addr_array(ttm->sg, ttm_dma->dma_address,
1335470cfe71SChristian König ttm->num_pages);
133622b33e8eSDave Airlie return 0;
133722b33e8eSDave Airlie }
133822b33e8eSDave Airlie
13390a667b50SDave Airlie drm = nouveau_bdev(bdev);
13403230cfc3SKonrad Rzeszutek Wilk
1341461619f5SChristian König return ttm_pool_alloc(&drm->ttm.bdev.pool, ttm, ctx);
13423230cfc3SKonrad Rzeszutek Wilk }
13433230cfc3SKonrad Rzeszutek Wilk
13443230cfc3SKonrad Rzeszutek Wilk static void
nouveau_ttm_tt_unpopulate(struct ttm_device * bdev,struct ttm_tt * ttm)13458af8a109SChristian König nouveau_ttm_tt_unpopulate(struct ttm_device *bdev,
13460a667b50SDave Airlie struct ttm_tt *ttm)
13473230cfc3SKonrad Rzeszutek Wilk {
1348ebb945a9SBen Skeggs struct nouveau_drm *drm;
134943d46f0bSMatthew Auld bool slave = !!(ttm->page_flags & TTM_TT_FLAG_EXTERNAL);
135022b33e8eSDave Airlie
135122b33e8eSDave Airlie if (slave)
135222b33e8eSDave Airlie return;
13533230cfc3SKonrad Rzeszutek Wilk
135461a8736fSChristian König nouveau_ttm_tt_unbind(bdev, ttm);
135561a8736fSChristian König
13560a667b50SDave Airlie drm = nouveau_bdev(bdev);
13573230cfc3SKonrad Rzeszutek Wilk
1358461619f5SChristian König return ttm_pool_free(&drm->ttm.bdev.pool, ttm);
13593230cfc3SKonrad Rzeszutek Wilk }
13603230cfc3SKonrad Rzeszutek Wilk
13618635784aSDave Airlie static void
nouveau_ttm_tt_destroy(struct ttm_device * bdev,struct ttm_tt * ttm)13628af8a109SChristian König nouveau_ttm_tt_destroy(struct ttm_device *bdev,
13638635784aSDave Airlie struct ttm_tt *ttm)
13648635784aSDave Airlie {
13658635784aSDave Airlie #if IS_ENABLED(CONFIG_AGP)
13668635784aSDave Airlie struct nouveau_drm *drm = nouveau_bdev(bdev);
13678635784aSDave Airlie if (drm->agp.bridge) {
136848efa57eSDave Airlie ttm_agp_destroy(ttm);
13698635784aSDave Airlie return;
13708635784aSDave Airlie }
13718635784aSDave Airlie #endif
13728635784aSDave Airlie nouveau_sgdma_destroy(bdev, ttm);
13738635784aSDave Airlie }
13748635784aSDave Airlie
1375dd7cfd64SMaarten Lankhorst void
nouveau_bo_fence(struct nouveau_bo * nvbo,struct nouveau_fence * fence,bool exclusive)1376809e9447SMaarten Lankhorst nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive)
1377dd7cfd64SMaarten Lankhorst {
137852791eeeSChristian König struct dma_resv *resv = nvbo->bo.base.resv;
1379dd7cfd64SMaarten Lankhorst
138073511edfSChristian König if (!fence)
138173511edfSChristian König return;
138273511edfSChristian König
138373511edfSChristian König dma_resv_add_fence(resv, &fence->base, exclusive ?
138473511edfSChristian König DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ);
1385dd7cfd64SMaarten Lankhorst }
1386dd7cfd64SMaarten Lankhorst
13876a6e5988SDave Airlie static void
nouveau_bo_delete_mem_notify(struct ttm_buffer_object * bo)13886a6e5988SDave Airlie nouveau_bo_delete_mem_notify(struct ttm_buffer_object *bo)
13896a6e5988SDave Airlie {
13905ea143c3SChristian König nouveau_bo_move_ntfy(bo, NULL);
13916a6e5988SDave Airlie }
13926a6e5988SDave Airlie
13938af8a109SChristian König struct ttm_device_funcs nouveau_bo_driver = {
1394649bf3caSJerome Glisse .ttm_tt_create = &nouveau_ttm_tt_create,
13953230cfc3SKonrad Rzeszutek Wilk .ttm_tt_populate = &nouveau_ttm_tt_populate,
13963230cfc3SKonrad Rzeszutek Wilk .ttm_tt_unpopulate = &nouveau_ttm_tt_unpopulate,
13978635784aSDave Airlie .ttm_tt_destroy = &nouveau_ttm_tt_destroy,
1398a2ab19feSChristian König .eviction_valuable = ttm_bo_eviction_valuable,
13996ee73861SBen Skeggs .evict_flags = nouveau_bo_evict_flags,
14006a6e5988SDave Airlie .delete_mem_notify = nouveau_bo_delete_mem_notify,
14016ee73861SBen Skeggs .move = nouveau_bo_move,
1402f32f02fdSJerome Glisse .io_mem_reserve = &nouveau_ttm_io_mem_reserve,
1403f32f02fdSJerome Glisse .io_mem_free = &nouveau_ttm_io_mem_free,
14046ee73861SBen Skeggs };
1405