blob: ca5492ac2da53bb792425f4d0ae9c0758d0cde96 [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 <subdev/fb.h>
5
6#include "nouveau_drm.h"
7#include "nouveau_ttm.h"
Ben Skeggs6ee73862009-12-11 19:24:15 +10008
9struct nouveau_sgdma_be {
Jerome Glisse8e7e7052011-11-09 17:15:26 -050010 /* this has to be the first field so populate/unpopulated in
11 * nouve_bo.c works properly, otherwise have to move them here
12 */
13 struct ttm_dma_tt ttm;
Ben Skeggs6ee73862009-12-11 19:24:15 +100014 struct drm_device *dev;
Ben Skeggs3863c9b2012-07-14 19:09:17 +100015 struct nouveau_mem *node;
Ben Skeggs6ee73862009-12-11 19:24:15 +100016};
17
Ben Skeggsefa58db2011-01-10 16:24:00 +100018static void
Jerome Glisse649bf3c2011-11-01 20:46:13 -040019nouveau_sgdma_destroy(struct ttm_tt *ttm)
Ben Skeggsefa58db2011-01-10 16:24:00 +100020{
Jerome Glisse649bf3c2011-11-01 20:46:13 -040021 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggsefa58db2011-01-10 16:24:00 +100022
Jerome Glisse649bf3c2011-11-01 20:46:13 -040023 if (ttm) {
Jerome Glisse8e7e7052011-11-09 17:15:26 -050024 ttm_dma_tt_fini(&nvbe->ttm);
Jerome Glisse649bf3c2011-11-01 20:46:13 -040025 kfree(nvbe);
Ben Skeggsefa58db2011-01-10 16:24:00 +100026 }
27}
28
Ben Skeggs6ee73862009-12-11 19:24:15 +100029static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040030nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
Ben Skeggs6ee73862009-12-11 19:24:15 +100031{
Jerome Glisse649bf3c2011-11-01 20:46:13 -040032 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggs3863c9b2012-07-14 19:09:17 +100033 struct nouveau_mem *node = mem->mm_node;
34 u64 size = mem->num_pages << 12;
Ben Skeggs6ee73862009-12-11 19:24:15 +100035
Ben Skeggs3863c9b2012-07-14 19:09:17 +100036 if (ttm->sg) {
37 node->sg = ttm->sg;
38 nouveau_vm_map_sg_table(&node->vma[0], 0, size, node);
39 } else {
40 node->pages = nvbe->ttm.dma_address;
41 nouveau_vm_map_sg(&node->vma[0], 0, size, node);
Ben Skeggs6ee73862009-12-11 19:24:15 +100042 }
Ben Skeggs6ee73862009-12-11 19:24:15 +100043
Ben Skeggs3863c9b2012-07-14 19:09:17 +100044 nvbe->node = node;
Ben Skeggs6ee73862009-12-11 19:24:15 +100045 return 0;
46}
47
48static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040049nv04_sgdma_unbind(struct ttm_tt *ttm)
Ben Skeggs6ee73862009-12-11 19:24:15 +100050{
Jerome Glisse649bf3c2011-11-01 20:46:13 -040051 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggs3863c9b2012-07-14 19:09:17 +100052 nouveau_vm_unmap(&nvbe->node->vma[0]);
Ben Skeggs6ee73862009-12-11 19:24:15 +100053 return 0;
54}
55
Ben Skeggsefa58db2011-01-10 16:24:00 +100056static struct ttm_backend_func nv04_sgdma_backend = {
Ben Skeggsefa58db2011-01-10 16:24:00 +100057 .bind = nv04_sgdma_bind,
58 .unbind = nv04_sgdma_unbind,
59 .destroy = nouveau_sgdma_destroy
60};
Ben Skeggs6ee73862009-12-11 19:24:15 +100061
Ben Skeggsb571fe22010-11-16 10:13:05 +100062static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040063nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
Ben Skeggsb571fe22010-11-16 10:13:05 +100064{
Jerome Glisse8e7e7052011-11-09 17:15:26 -050065 struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm;
Ben Skeggs26c0c9e2011-02-10 12:59:51 +100066 struct nouveau_mem *node = mem->mm_node;
Jerome Glisse649bf3c2011-11-01 20:46:13 -040067
Ben Skeggs26c0c9e2011-02-10 12:59:51 +100068 /* noop: bound in move_notify() */
Dave Airlie22b33e82012-04-02 11:53:06 +010069 if (ttm->sg) {
70 node->sg = ttm->sg;
71 } else
72 node->pages = nvbe->ttm.dma_address;
Ben Skeggsb571fe22010-11-16 10:13:05 +100073 return 0;
74}
75
76static int
Jerome Glisse649bf3c2011-11-01 20:46:13 -040077nv50_sgdma_unbind(struct ttm_tt *ttm)
Ben Skeggsb571fe22010-11-16 10:13:05 +100078{
Ben Skeggs26c0c9e2011-02-10 12:59:51 +100079 /* noop: unbound in move_notify() */
Ben Skeggsb571fe22010-11-16 10:13:05 +100080 return 0;
81}
82
Ben Skeggsb571fe22010-11-16 10:13:05 +100083static struct ttm_backend_func nv50_sgdma_backend = {
Ben Skeggsb571fe22010-11-16 10:13:05 +100084 .bind = nv50_sgdma_bind,
85 .unbind = nv50_sgdma_unbind,
86 .destroy = nouveau_sgdma_destroy
87};
88
Jerome Glisse649bf3c2011-11-01 20:46:13 -040089struct ttm_tt *
90nouveau_sgdma_create_ttm(struct ttm_bo_device *bdev,
91 unsigned long size, uint32_t page_flags,
92 struct page *dummy_read_page)
Ben Skeggs6ee73862009-12-11 19:24:15 +100093{
Ben Skeggsebb945a2012-07-20 08:17:34 +100094 struct nouveau_drm *drm = nouveau_bdev(bdev);
Ben Skeggs6ee73862009-12-11 19:24:15 +100095 struct nouveau_sgdma_be *nvbe;
96
Ben Skeggs6ee73862009-12-11 19:24:15 +100097 nvbe = kzalloc(sizeof(*nvbe), GFP_KERNEL);
98 if (!nvbe)
99 return NULL;
100
Ben Skeggsebb945a2012-07-20 08:17:34 +1000101 nvbe->dev = drm->dev;
102 if (nv_device(drm->device)->card_type < NV_50)
103 nvbe->ttm.ttm.func = &nv04_sgdma_backend;
104 else
105 nvbe->ttm.ttm.func = &nv50_sgdma_backend;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000106
Jerome Glisse8e7e7052011-11-09 17:15:26 -0500107 if (ttm_dma_tt_init(&nvbe->ttm, bdev, size, page_flags, dummy_read_page)) {
108 kfree(nvbe);
Jerome Glisse649bf3c2011-11-01 20:46:13 -0400109 return NULL;
110 }
Jerome Glisse8e7e7052011-11-09 17:15:26 -0500111 return &nvbe->ttm.ttm;
Ben Skeggs6ee73862009-12-11 19:24:15 +1000112}