blob: 8c3053a177d6c4c36a0b5acd405fc72c340eea2c [file] [log] [blame]
Ben Skeggs6ee73862009-12-11 19:24:15 +10001#include <linux/pagemap.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09002#include <linux/slab.h>
Ben Skeggs6ee73862009-12-11 19:24:15 +10003
Ben Skeggsebb945a2012-07-20 08:17:34 +10004#include "nouveau_drm.h"
5#include "nouveau_ttm.h"
Ben Skeggs6ee73862009-12-11 19:24:15 +10006
7struct nouveau_sgdma_be {
Jerome Glisse8e7e7052011-11-09 17:15:26 -05008 /* this has to be the first field so populate/unpopulated in
9 * nouve_bo.c works properly, otherwise have to move them here
10 */
11 struct ttm_dma_tt ttm;
Ben Skeggsbe83cd42015-01-14 15:36:34 +100012 struct nvkm_mem *node;
Ben Skeggs6ee73862009-12-11 19:24:15 +100013};
14
Ben Skeggsefa58db2011-01-10 16:24:00 +100015static void
Jerome Glisse649bf3c2011-11-01 20:46:13 -040016nouveau_sgdma_destroy(struct ttm_tt *ttm)
Ben Skeggsefa58db2011-01-10 16:24:00 +100017{
Jerome Glisse649bf3c2011-11-01 20:46:13 -040018 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggsefa58db2011-01-10 16:24:00 +100019
Jerome Glisse649bf3c2011-11-01 20:46:13 -040020 if (ttm) {
Jerome Glisse8e7e7052011-11-09 17:15:26 -050021 ttm_dma_tt_fini(&nvbe->ttm);
Jerome Glisse649bf3c2011-11-01 20:46:13 -040022 kfree(nvbe);
Ben Skeggsefa58db2011-01-10 16:24:00 +100023 }
24}
25
Ben Skeggs6ee73862009-12-11 19:24:15 +100026static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040027nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
Ben Skeggs6ee73862009-12-11 19:24:15 +100028{
Jerome Glisse649bf3c2011-11-01 20:46:13 -040029 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggsbe83cd42015-01-14 15:36:34 +100030 struct nvkm_mem *node = mem->mm_node;
Ben Skeggs6ee73862009-12-11 19:24:15 +100031
Ben Skeggs3863c9b2012-07-14 19:09:17 +100032 if (ttm->sg) {
Ben Skeggs2e2cfbe2013-11-15 11:56:49 +100033 node->sg = ttm->sg;
34 node->pages = NULL;
Ben Skeggs3863c9b2012-07-14 19:09:17 +100035 } else {
Ben Skeggs2e2cfbe2013-11-15 11:56:49 +100036 node->sg = NULL;
Ben Skeggs3863c9b2012-07-14 19:09:17 +100037 node->pages = nvbe->ttm.dma_address;
Ben Skeggs6ee73862009-12-11 19:24:15 +100038 }
Ben Skeggs2e2cfbe2013-11-15 11:56:49 +100039 node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
Ben Skeggs6ee73862009-12-11 19:24:15 +100040
Ben Skeggsbe83cd42015-01-14 15:36:34 +100041 nvkm_vm_map(&node->vma[0], node);
Ben Skeggs3863c9b2012-07-14 19:09:17 +100042 nvbe->node = node;
Ben Skeggs6ee73862009-12-11 19:24:15 +100043 return 0;
44}
45
46static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040047nv04_sgdma_unbind(struct ttm_tt *ttm)
Ben Skeggs6ee73862009-12-11 19:24:15 +100048{
Jerome Glisse649bf3c2011-11-01 20:46:13 -040049 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggsbe83cd42015-01-14 15:36:34 +100050 nvkm_vm_unmap(&nvbe->node->vma[0]);
Ben Skeggs6ee73862009-12-11 19:24:15 +100051 return 0;
52}
53
Ben Skeggsefa58db2011-01-10 16:24:00 +100054static struct ttm_backend_func nv04_sgdma_backend = {
Ben Skeggsefa58db2011-01-10 16:24:00 +100055 .bind = nv04_sgdma_bind,
56 .unbind = nv04_sgdma_unbind,
57 .destroy = nouveau_sgdma_destroy
58};
Ben Skeggs6ee73862009-12-11 19:24:15 +100059
Ben Skeggsb571fe22010-11-16 10:13:05 +100060static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040061nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
Ben Skeggsb571fe22010-11-16 10:13:05 +100062{
Jerome Glisse8e7e7052011-11-09 17:15:26 -050063 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggsbe83cd42015-01-14 15:36:34 +100064 struct nvkm_mem *node = mem->mm_node;
Jerome Glisse649bf3c2011-11-01 20:46:13 -040065
Ben Skeggs26c0c9e2011-02-10 12:59:51 +100066 /* noop: bound in move_notify() */
Dave Airlie22b33e82012-04-02 11:53:06 +010067 if (ttm->sg) {
Ben Skeggs2e2cfbe2013-11-15 11:56:49 +100068 node->sg = ttm->sg;
69 node->pages = NULL;
70 } else {
71 node->sg = NULL;
Dave Airlie22b33e82012-04-02 11:53:06 +010072 node->pages = nvbe->ttm.dma_address;
Ben Skeggs2e2cfbe2013-11-15 11:56:49 +100073 }
74 node->size = (mem->num_pages << PAGE_SHIFT) >> 12;
Ben Skeggsb571fe22010-11-16 10:13:05 +100075 return 0;
76}
77
78static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040079nv50_sgdma_unbind(struct ttm_tt *ttm)
Ben Skeggsb571fe22010-11-16 10:13:05 +100080{
Ben Skeggs26c0c9e2011-02-10 12:59:51 +100081 /* noop: unbound in move_notify() */
Ben Skeggsb571fe22010-11-16 10:13:05 +100082 return 0;
83}
84
Ben Skeggsb571fe22010-11-16 10:13:05 +100085static struct ttm_backend_func nv50_sgdma_backend = {
Ben Skeggsb571fe22010-11-16 10:13:05 +100086 .bind = nv50_sgdma_bind,
87 .unbind = nv50_sgdma_unbind,
88 .destroy = nouveau_sgdma_destroy
89};
90
Jerome Glisse649bf3c2011-11-01 20:46:13 -040091struct ttm_tt *
92nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
93 unsigned long size, uint32_t page_flags,
94 struct page *dummy_read_page)
Ben Skeggs6ee73862009-12-11 19:24:15 +100095{
Ben Skeggsebb945a2012-07-20 08:17:34 +100096 struct nouveau_drm *drm = nouveau_bdev(bdev);
Ben Skeggs6ee73862009-12-11 19:24:15 +100097 struct nouveau_sgdma_be *nvbe;
98
Ben Skeggs6ee73862009-12-11 19:24:15 +100099 nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
100 if (!nvbe)
101 return NULL;
102
Ben Skeggs967e7bd2014-08-10 04:10:22 +1000103 if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA)
Ben Skeggsebb945a2012-07-20 08:17:34 +1000104 nvbe->ttm.ttm.func = &nv04_sgdma_backend;
105 else
106 nvbe->ttm.ttm.func = &nv50_sgdma_backend;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000107
Ben Skeggs7a59cc32013-09-17 14:13:32 +1000108 if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page))
Alexandre Courbot495b2172014-12-11 04:07:20 +0900109 /*
110 * A failing ttm_dma_tt_init() will call ttm_tt_destroy()
111 * and thus our nouveau_sgdma_destroy() hook, so we don't need
112 * to free nvbe here.
113 */
Jerome Glisse649bf3c2011-11-01 20:46:13 -0400114 return NULL;
Jerome Glisse8e7e7052011-11-09 17:15:26 -0500115 return &nvbe->ttm.ttm;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000116}