]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - drivers/gpu/drm/nouveau/nouveau_sgdma.c
Merge remote-tracking branches 'asoc/topic/ac97', 'asoc/topic/ac97-mfd', 'asoc/topic...
[mirror_ubuntu-focal-kernel.git] / drivers / gpu / drm / nouveau / nouveau_sgdma.c
CommitLineData
b2441318 1// SPDX-License-Identifier: GPL-2.0
6ee73861 2#include <linux/pagemap.h>
5a0e3ad6 3#include <linux/slab.h>
6ee73861 4
4dc28134 5#include "nouveau_drv.h"
ebb945a9 6#include "nouveau_ttm.h"
6ee73861
BS
7
8struct nouveau_sgdma_be {
8e7e7052
JG
9 /* this has to be the first field so populate/unpopulated in
10 * nouve_bo.c works properly, otherwise have to move them here
11 */
12 struct ttm_dma_tt ttm;
be83cd4e 13 struct nvkm_mem *node;
6ee73861
BS
14};
15
efa58db3 16static void
649bf3ca 17nouveau_sgdma_destroy(struct ttm_tt *ttm)
efa58db3 18{
649bf3ca 19 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
efa58db3 20
649bf3ca 21 if (ttm) {
8e7e7052 22 ttm_dma_tt_fini(&nvbe->ttm);
649bf3ca 23 kfree(nvbe);
efa58db3
BS
24 }
25}
26
6ee73861 27static int
605f9ccd 28nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg)
6ee73861 29{
649bf3ca 30 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
605f9ccd 31 struct nvkm_mem *node = reg->mm_node;
6ee73861 32
3863c9bc 33 if (ttm->sg) {
2e2cfbe6
BS
34 node->sg = ttm->sg;
35 node->pages = NULL;
3863c9bc 36 } else {
2e2cfbe6 37 node->sg = NULL;
3863c9bc 38 node->pages = nvbe->ttm.dma_address;
6ee73861 39 }
605f9ccd 40 node->size = (reg->num_pages << PAGE_SHIFT) >> 12;
6ee73861 41
be83cd4e 42 nvkm_vm_map(&node->vma[0], node);
3863c9bc 43 nvbe->node = node;
6ee73861
BS
44 return 0;
45}
46
47static int
649bf3ca 48nv04_sgdma_unbind(struct ttm_tt *ttm)
6ee73861 49{
649bf3ca 50 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
be83cd4e 51 nvkm_vm_unmap(&nvbe->node->vma[0]);
6ee73861
BS
52 return 0;
53}
54
efa58db3 55static struct ttm_backend_func nv04_sgdma_backend = {
efa58db3
BS
56 .bind = nv04_sgdma_bind,
57 .unbind = nv04_sgdma_unbind,
58 .destroy = nouveau_sgdma_destroy
59};
6ee73861 60
b571fe21 61static int
605f9ccd 62nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg)
b571fe21 63{
8e7e7052 64 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
605f9ccd 65 struct nvkm_mem *node = reg->mm_node;
649bf3ca 66
26c0c9e3 67 /* noop: bound in move_notify() */
22b33e8e 68 if (ttm->sg) {
2e2cfbe6
BS
69 node->sg = ttm->sg;
70 node->pages = NULL;
71 } else {
72 node->sg = NULL;
22b33e8e 73 node->pages = nvbe->ttm.dma_address;
2e2cfbe6 74 }
605f9ccd 75 node->size = (reg->num_pages << PAGE_SHIFT) >> 12;
b571fe21
BS
76 return 0;
77}
78
79static int
649bf3ca 80nv50_sgdma_unbind(struct ttm_tt *ttm)
b571fe21 81{
26c0c9e3 82 /* noop: unbound in move_notify() */
b571fe21
BS
83 return 0;
84}
85
b571fe21 86static struct ttm_backend_func nv50_sgdma_backend = {
b571fe21
BS
87 .bind = nv50_sgdma_bind,
88 .unbind = nv50_sgdma_unbind,
89 .destroy = nouveau_sgdma_destroy
90};
91
649bf3ca
JG
92struct ttm_tt *
93nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
94 unsigned long size, uint32_t page_flags,
95 struct page *dummy_read_page)
6ee73861 96{
ebb945a9 97 struct nouveau_drm *drm = nouveau_bdev(bdev);
6ee73861
BS
98 struct nouveau_sgdma_be *nvbe;
99
6ee73861
BS
100 nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
101 if (!nvbe)
102 return NULL;
103
1167c6bc 104 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA)
ebb945a9
BS
105 nvbe->ttm.ttm.func = &nv04_sgdma_backend;
106 else
107 nvbe->ttm.ttm.func = &nv50_sgdma_backend;
6ee73861 108
7a59cc34 109 if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page))
495b2176
AC
110 /*
111 * A failing ttm_dma_tt_init() will call ttm_tt_destroy()
112 * and thus our nouveau_sgdma_destroy() hook, so we don't need
113 * to free nvbe here.
114 */
649bf3ca 115 return NULL;
8e7e7052 116 return &nvbe->ttm.ttm;
6ee73861 117}