diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_sgdma.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_sgdma.c | 123 |
1 files changed, 49 insertions, 74 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b7ab268f7d6f..bd870028514b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -1,116 +1,91 @@ +// SPDX-License-Identifier: MIT #include <linux/pagemap.h> #include <linux/slab.h> +#include <drm/ttm/ttm_tt.h> #include "nouveau_drv.h" +#include "nouveau_mem.h" #include "nouveau_ttm.h" +#include "nouveau_bo.h" struct nouveau_sgdma_be { /* this has to be the first field so populate/unpopulated in * nouve_bo.c works properly, otherwise have to move them here */ - struct ttm_dma_tt ttm; - struct nvkm_mem *node; + struct ttm_tt ttm; + struct nouveau_mem *mem; }; -static void -nouveau_sgdma_destroy(struct ttm_tt *ttm) +void +nouveau_sgdma_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; if (ttm) { - ttm_dma_tt_fini(&nvbe->ttm); + ttm_tt_fini(&nvbe->ttm); kfree(nvbe); } } -static int -nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) +int +nouveau_sgdma_bind(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_resource *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct nvkm_mem *node = reg->mm_node; - - if (ttm->sg) { - node->sg = ttm->sg; - node->pages = NULL; - } else { - node->sg = NULL; - node->pages = nvbe->ttm.dma_address; + struct nouveau_drm *drm = nouveau_bdev(bdev); + struct nouveau_mem *mem = nouveau_mem(reg); + int ret; + + if (nvbe->mem) + return 0; + + ret = nouveau_mem_host(reg, &nvbe->ttm); + if (ret) + return ret; + + if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { + ret = nouveau_mem_map(mem, &drm->client.vmm.vmm, &mem->vma[0]); + if (ret) { + nouveau_mem_fini(mem); + return ret; + } } - node->size = (reg->num_pages << PAGE_SHIFT) >> 12; - - nvkm_vm_map(&node->vma[0], node); - nvbe->node = node; - return 0; -} -static int -nv04_sgdma_unbind(struct ttm_tt *ttm) -{ - struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - nvkm_vm_unmap(&nvbe->node->vma[0]); + nvbe->mem = mem; return 0; } -static struct ttm_backend_func nv04_sgdma_backend = { - .bind = nv04_sgdma_bind, - .unbind = nv04_sgdma_unbind, - .destroy = nouveau_sgdma_destroy -}; - -static int -nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) +void +nouveau_sgdma_unbind(struct ttm_device *bdev, struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct nvkm_mem *node = reg->mm_node; - - /* noop: bound in move_notify() */ - if (ttm->sg) { - node->sg = ttm->sg; - node->pages = NULL; - } else { - node->sg = NULL; - node->pages = nvbe->ttm.dma_address; + if (nvbe->mem) { + nouveau_mem_fini(nvbe->mem); + nvbe->mem = NULL; } - node->size = (reg->num_pages << PAGE_SHIFT) >> 12; - return 0; -} - -static int -nv50_sgdma_unbind(struct ttm_tt *ttm) -{ - /* noop: unbound in move_notify() */ - return 0; } -static struct ttm_backend_func nv50_sgdma_backend = { - .bind = nv50_sgdma_bind, - .unbind = nv50_sgdma_unbind, - .destroy = nouveau_sgdma_destroy -}; - struct ttm_tt * -nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev, - unsigned long size, uint32_t page_flags, - struct page *dummy_read_page) +nouveau_sgdma_create_ttm(struct ttm_buffer_object *bo, uint32_t page_flags) { - struct nouveau_drm *drm = nouveau_bdev(bdev); + struct nouveau_drm *drm = nouveau_bdev(bo->bdev); + struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_sgdma_be *nvbe; + enum ttm_caching caching; + + if (nvbo->force_coherent) + caching = ttm_uncached; + else if (drm->agp.bridge) + caching = ttm_write_combined; + else + caching = ttm_cached; nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL); if (!nvbe) return NULL; - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) - nvbe->ttm.ttm.func = &nv04_sgdma_backend; - else - nvbe->ttm.ttm.func = &nv50_sgdma_backend; - - if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) - /* - * A failing ttm_dma_tt_init() will call ttm_tt_destroy() - * and thus our nouveau_sgdma_destroy() hook, so we don't need - * to free nvbe here. - */ + if (ttm_sg_tt_init(&nvbe->ttm, bo, page_flags, caching)) { + kfree(nvbe); return NULL; - return &nvbe->ttm.ttm; + } + return &nvbe->ttm; } |
