aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/Makefile2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c42
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_channel.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_prime.c163
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_sgdma.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.c57
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vm.h6
-rw-r--r--drivers/gpu/drm/nouveau/nv04_crtc.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv50_crtc.c4
-rw-r--r--drivers/gpu/drm/nouveau/nv50_evo.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvd0_display.c6
16 files changed, 296 insertions, 25 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 1a2ad7eb173..01f13351a47 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -37,7 +37,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
37 nv50_calc.o \ 37 nv50_calc.o \
38 nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \ 38 nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o \
39 nv50_vram.o nvc0_vram.o \ 39 nv50_vram.o nvc0_vram.o \
40 nv50_vm.o nvc0_vm.o 40 nv50_vm.o nvc0_vm.o nouveau_prime.o
41 41
42nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o 42nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
43nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o 43nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 81599d6e636..4435e115b92 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -89,12 +89,17 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
89int 89int
90nouveau_bo_new(struct drm_device *dev, int size, int align, 90nouveau_bo_new(struct drm_device *dev, int size, int align,
91 uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, 91 uint32_t flags, uint32_t tile_mode, uint32_t tile_flags,
92 struct sg_table *sg,
92 struct nouveau_bo **pnvbo) 93 struct nouveau_bo **pnvbo)
93{ 94{
94 struct drm_nouveau_private *dev_priv = dev->dev_private; 95 struct drm_nouveau_private *dev_priv = dev->dev_private;
95 struct nouveau_bo *nvbo; 96 struct nouveau_bo *nvbo;
96 size_t acc_size; 97 size_t acc_size;
97 int ret; 98 int ret;
99 int type = ttm_bo_type_device;
100
101 if (sg)
102 type = ttm_bo_type_sg;
98 103
99 nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL); 104 nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
100 if (!nvbo) 105 if (!nvbo)
@@ -120,8 +125,8 @@ nouveau_bo_new(struct drm_device *dev, int size, int align,
120 sizeof(struct nouveau_bo)); 125 sizeof(struct nouveau_bo));
121 126
122 ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size, 127 ret = ttm_bo_init(&dev_priv->ttm.bdev, &nvbo->bo, size,
123 ttm_bo_type_device, &nvbo->placement, 128 type, &nvbo->placement,
124 align >> PAGE_SHIFT, 0, false, NULL, acc_size, NULL, 129 align >> PAGE_SHIFT, 0, false, NULL, acc_size, sg,
125 nouveau_bo_del_ttm); 130 nouveau_bo_del_ttm);
126 if (ret) { 131 if (ret) {
127 /* ttm will call nouveau_bo_del_ttm if it fails.. */ 132 /* ttm will call nouveau_bo_del_ttm if it fails.. */
@@ -817,9 +822,14 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
817 } else 822 } else
818 if (new_mem && new_mem->mem_type == TTM_PL_TT && 823 if (new_mem && new_mem->mem_type == TTM_PL_TT &&
819 nvbo->page_shift == vma->vm->spg_shift) { 824 nvbo->page_shift == vma->vm->spg_shift) {
820 nouveau_vm_map_sg(vma, 0, new_mem-> 825 if (((struct nouveau_mem *)new_mem->mm_node)->sg)
821 num_pages << PAGE_SHIFT, 826 nouveau_vm_map_sg_table(vma, 0, new_mem->
822 new_mem->mm_node); 827 num_pages << PAGE_SHIFT,
828 new_mem->mm_node);
829 else
830 nouveau_vm_map_sg(vma, 0, new_mem->
831 num_pages << PAGE_SHIFT,
832 new_mem->mm_node);
823 } else { 833 } else {
824 nouveau_vm_unmap(vma); 834 nouveau_vm_unmap(vma);
825 } 835 }
@@ -1058,10 +1068,19 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm)
1058 struct drm_device *dev; 1068 struct drm_device *dev;
1059 unsigned i; 1069 unsigned i;
1060 int r; 1070 int r;
1071 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
1061 1072
1062 if (ttm->state != tt_unpopulated) 1073 if (ttm->state != tt_unpopulated)
1063 return 0; 1074 return 0;
1064 1075
1076 if (slave && ttm->sg) {
1077 /* make userspace faulting work */
1078 drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages,
1079 ttm_dma->dma_address, ttm->num_pages);
1080 ttm->state = tt_unbound;
1081 return 0;
1082 }
1083
1065 dev_priv = nouveau_bdev(ttm->bdev); 1084 dev_priv = nouveau_bdev(ttm->bdev);
1066 dev = dev_priv->dev; 1085 dev = dev_priv->dev;
1067 1086
@@ -1106,6 +1125,10 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm)
1106 struct drm_nouveau_private *dev_priv; 1125 struct drm_nouveau_private *dev_priv;
1107 struct drm_device *dev; 1126 struct drm_device *dev;
1108 unsigned i; 1127 unsigned i;
1128 bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG);
1129
1130 if (slave)
1131 return;
1109 1132
1110 dev_priv = nouveau_bdev(ttm->bdev); 1133 dev_priv = nouveau_bdev(ttm->bdev);
1111 dev = dev_priv->dev; 1134 dev = dev_priv->dev;
@@ -1181,9 +1204,12 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm,
1181 1204
1182 if (nvbo->bo.mem.mem_type == TTM_PL_VRAM) 1205 if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
1183 nouveau_vm_map(vma, nvbo->bo.mem.mm_node); 1206 nouveau_vm_map(vma, nvbo->bo.mem.mm_node);
1184 else 1207 else if (nvbo->bo.mem.mem_type == TTM_PL_TT) {
1185 if (nvbo->bo.mem.mem_type == TTM_PL_TT) 1208 if (node->sg)
1186 nouveau_vm_map_sg(vma, 0, size, node); 1209 nouveau_vm_map_sg_table(vma, 0, size, node);
1210 else
1211 nouveau_vm_map_sg(vma, 0, size, node);
1212 }
1187 1213
1188 list_add_tail(&vma->head, &nvbo->vma_list); 1214 list_add_tail(&vma->head, &nvbo->vma_list);
1189 vma->refcount = 1; 1215 vma->refcount = 1;
diff --git a/drivers/gpu/drm/nouveau/nouveau_channel.c b/drivers/gpu/drm/nouveau/nouveau_channel.c
index 846afb0bfef..730bbb249b0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_channel.c
+++ b/drivers/gpu/drm/nouveau/nouveau_channel.c
@@ -38,7 +38,7 @@ nouveau_channel_pushbuf_init(struct nouveau_channel *chan)
38 int ret; 38 int ret;
39 39
40 /* allocate buffer object */ 40 /* allocate buffer object */
41 ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, &chan->pushbuf_bo); 41 ret = nouveau_bo_new(dev, 65536, 0, mem, 0, 0, NULL, &chan->pushbuf_bo);
42 if (ret) 42 if (ret)
43 goto out; 43 goto out;
44 44
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c
index 4f2030bd567..b394ecf787f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.c
@@ -408,7 +408,7 @@ static struct drm_driver driver = {
408 .driver_features = 408 .driver_features =
409 DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | 409 DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
410 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | 410 DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
411 DRIVER_MODESET, 411 DRIVER_MODESET | DRIVER_PRIME,
412 .load = nouveau_load, 412 .load = nouveau_load,
413 .firstopen = nouveau_firstopen, 413 .firstopen = nouveau_firstopen,
414 .lastclose = nouveau_lastclose, 414 .lastclose = nouveau_lastclose,
@@ -430,6 +430,12 @@ static struct drm_driver driver = {
430 .reclaim_buffers = drm_core_reclaim_buffers, 430 .reclaim_buffers = drm_core_reclaim_buffers,
431 .ioctls = nouveau_ioctls, 431 .ioctls = nouveau_ioctls,
432 .fops = &nouveau_driver_fops, 432 .fops = &nouveau_driver_fops,
433
434 .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
435 .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
436 .gem_prime_export = nouveau_gem_prime_export,
437 .gem_prime_import = nouveau_gem_prime_import,
438
433 .gem_init_object = nouveau_gem_object_new, 439 .gem_init_object = nouveau_gem_object_new,
434 .gem_free_object = nouveau_gem_object_del, 440 .gem_free_object = nouveau_gem_object_del,
435 .gem_open_object = nouveau_gem_object_open, 441 .gem_open_object = nouveau_gem_object_open,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 3aef353a926..92c9a8a648d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -86,6 +86,7 @@ struct nouveau_mem {
86 u32 memtype; 86 u32 memtype;
87 u64 offset; 87 u64 offset;
88 u64 size; 88 u64 size;
89 struct sg_table *sg;
89}; 90};
90 91
91struct nouveau_tile_reg { 92struct nouveau_tile_reg {
@@ -1416,7 +1417,9 @@ extern int nv04_crtc_create(struct drm_device *, int index);
1416extern struct ttm_bo_driver nouveau_bo_driver; 1417extern struct ttm_bo_driver nouveau_bo_driver;
1417extern int nouveau_bo_new(struct drm_device *, int size, int align, 1418extern int nouveau_bo_new(struct drm_device *, int size, int align,
1418 uint32_t flags, uint32_t tile_mode, 1419 uint32_t flags, uint32_t tile_mode,
1419 uint32_t tile_flags, struct nouveau_bo **); 1420 uint32_t tile_flags,
1421 struct sg_table *sg,
1422 struct nouveau_bo **);
1420extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); 1423extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
1421extern int nouveau_bo_unpin(struct nouveau_bo *); 1424extern int nouveau_bo_unpin(struct nouveau_bo *);
1422extern int nouveau_bo_map(struct nouveau_bo *); 1425extern int nouveau_bo_map(struct nouveau_bo *);
@@ -1501,6 +1504,11 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
1501extern int nouveau_gem_ioctl_info(struct drm_device *, void *, 1504extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
1502 struct drm_file *); 1505 struct drm_file *);
1503 1506
1507extern struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev,
1508 struct drm_gem_object *obj, int flags);
1509extern struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev,
1510 struct dma_buf *dma_buf);
1511
1504/* nouveau_display.c */ 1512/* nouveau_display.c */
1505int nouveau_display_create(struct drm_device *dev); 1513int nouveau_display_create(struct drm_device *dev);
1506void nouveau_display_destroy(struct drm_device *dev); 1514void nouveau_display_destroy(struct drm_device *dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index c1dc20f6cb8..965e3d2e8a7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -573,7 +573,7 @@ nouveau_fence_init(struct drm_device *dev)
573 /* Create a shared VRAM heap for cross-channel sync. */ 573 /* Create a shared VRAM heap for cross-channel sync. */
574 if (USE_SEMA(dev)) { 574 if (USE_SEMA(dev)) {
575 ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM, 575 ret = nouveau_bo_new(dev, size, 0, TTM_PL_FLAG_VRAM,
576 0, 0, &dev_priv->fence.bo); 576 0, 0, NULL, &dev_priv->fence.bo);
577 if (ret) 577 if (ret)
578 return ret; 578 return ret;
579 579
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index ed52a6f4161..666dad0717a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -23,6 +23,7 @@
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 * 24 *
25 */ 25 */
26#include <linux/dma-buf.h>
26#include "drmP.h" 27#include "drmP.h"
27#include "drm.h" 28#include "drm.h"
28 29
@@ -53,6 +54,9 @@ nouveau_gem_object_del(struct drm_gem_object *gem)
53 nouveau_bo_unpin(nvbo); 54 nouveau_bo_unpin(nvbo);
54 } 55 }
55 56
57 if (gem->import_attach)
58 drm_prime_gem_destroy(gem, nvbo->bo.sg);
59
56 ttm_bo_unref(&bo); 60 ttm_bo_unref(&bo);
57 61
58 drm_gem_object_release(gem); 62 drm_gem_object_release(gem);
@@ -139,7 +143,7 @@ nouveau_gem_new(struct drm_device *dev, int size, int align, uint32_t domain,
139 flags |= TTM_PL_FLAG_SYSTEM; 143 flags |= TTM_PL_FLAG_SYSTEM;
140 144
141 ret = nouveau_bo_new(dev, size, align, flags, tile_mode, 145 ret = nouveau_bo_new(dev, size, align, flags, tile_mode,
142 tile_flags, pnvbo); 146 tile_flags, NULL, pnvbo);
143 if (ret) 147 if (ret)
144 return ret; 148 return ret;
145 nvbo = *pnvbo; 149 nvbo = *pnvbo;
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index b08065f981d..bb2f0a43f59 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -416,7 +416,7 @@ nouveau_mem_vram_init(struct drm_device *dev)
416 416
417 if (dev_priv->card_type < NV_50) { 417 if (dev_priv->card_type < NV_50) {
418 ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM, 418 ret = nouveau_bo_new(dev, 256*1024, 0, TTM_PL_FLAG_VRAM,
419 0, 0, &dev_priv->vga_ram); 419 0, 0, NULL, &dev_priv->vga_ram);
420 if (ret == 0) 420 if (ret == 0)
421 ret = nouveau_bo_pin(dev_priv->vga_ram, 421 ret = nouveau_bo_pin(dev_priv->vga_ram,
422 TTM_PL_FLAG_VRAM); 422 TTM_PL_FLAG_VRAM);
diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c
new file mode 100644
index 00000000000..ed6b8465260
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_prime.c
@@ -0,0 +1,163 @@
1
2#include "drmP.h"
3#include "drm.h"
4
5#include "nouveau_drv.h"
6#include "nouveau_drm.h"
7#include "nouveau_dma.h"
8
9#include <linux/dma-buf.h>
10
11static struct sg_table *nouveau_gem_map_dma_buf(struct dma_buf_attachment *attachment,
12 enum dma_data_direction dir)
13{
14 struct nouveau_bo *nvbo = attachment->dmabuf->priv;
15 struct drm_device *dev = nvbo->gem->dev;
16 int npages = nvbo->bo.num_pages;
17 struct sg_table *sg;
18 int nents;
19
20 mutex_lock(&dev->struct_mutex);
21 sg = drm_prime_pages_to_sg(nvbo->bo.ttm->pages, npages);
22 nents = dma_map_sg(attachment->dev, sg->sgl, sg->nents, dir);
23 mutex_unlock(&dev->struct_mutex);
24 return sg;
25}
26
27static void nouveau_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
28 struct sg_table *sg, enum dma_data_direction dir)
29{
30 dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
31 sg_free_table(sg);
32 kfree(sg);
33}
34
35static void nouveau_gem_dmabuf_release(struct dma_buf *dma_buf)
36{
37 struct nouveau_bo *nvbo = dma_buf->priv;
38
39 if (nvbo->gem->export_dma_buf == dma_buf) {
40 nvbo->gem->export_dma_buf = NULL;
41 drm_gem_object_unreference_unlocked(nvbo->gem);
42 }
43}
44
45static void *nouveau_gem_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num)
46{
47 return NULL;
48}
49
50static void nouveau_gem_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
51{
52
53}
54static void *nouveau_gem_kmap(struct dma_buf *dma_buf, unsigned long page_num)
55{
56 return NULL;
57}
58
59static void nouveau_gem_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr)
60{
61
62}
63
64struct dma_buf_ops nouveau_dmabuf_ops = {
65 .map_dma_buf = nouveau_gem_map_dma_buf,
66 .unmap_dma_buf = nouveau_gem_unmap_dma_buf,
67 .release = nouveau_gem_dmabuf_release,
68 .kmap = nouveau_gem_kmap,
69 .kmap_atomic = nouveau_gem_kmap_atomic,
70 .kunmap = nouveau_gem_kunmap,
71 .kunmap_atomic = nouveau_gem_kunmap_atomic,
72};
73
74static int
75nouveau_prime_new(struct drm_device *dev,
76 size_t size,
77 struct sg_table *sg,
78 struct nouveau_bo **pnvbo)
79{
80 struct nouveau_bo *nvbo;
81 u32 flags = 0;
82 int ret;
83
84 flags = TTM_PL_FLAG_TT;
85
86 ret = nouveau_bo_new(dev, size, 0, flags, 0, 0,
87 sg, pnvbo);
88 if (ret)
89 return ret;
90 nvbo = *pnvbo;
91
92 /* we restrict allowed domains on nv50+ to only the types
93 * that were requested at creation time. not possibly on
94 * earlier chips without busting the ABI.
95 */
96 nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_GART;
97 nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size);
98 if (!nvbo->gem) {
99 nouveau_bo_ref(NULL, pnvbo);
100 return -ENOMEM;
101 }
102
103 nvbo->gem->driver_private = nvbo;
104 return 0;
105}
106
107struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev,
108 struct drm_gem_object *obj, int flags)
109{
110 struct nouveau_bo *nvbo = nouveau_gem_object(obj);
111 int ret = 0;
112
113 /* pin buffer into GTT */
114 ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_TT);
115 if (ret)
116 return ERR_PTR(-EINVAL);
117
118 return dma_buf_export(nvbo, &nouveau_dmabuf_ops, obj->size, flags);
119}
120
121struct drm_gem_object *nouveau_gem_prime_import(struct drm_device *dev,
122 struct dma_buf *dma_buf)
123{
124 struct dma_buf_attachment *attach;
125 struct sg_table *sg;
126 struct nouveau_bo *nvbo;
127 int ret;
128
129 if (dma_buf->ops == &nouveau_dmabuf_ops) {
130 nvbo = dma_buf->priv;
131 if (nvbo->gem) {
132 if (nvbo->gem->dev == dev) {
133 drm_gem_object_reference(nvbo->gem);
134 return nvbo->gem;
135 }
136 }
137 }
138 /* need to attach */
139 attach = dma_buf_attach(dma_buf, dev->dev);
140 if (IS_ERR(attach))
141 return ERR_PTR(PTR_ERR(attach));
142
143 sg = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
144 if (IS_ERR(sg)) {
145 ret = PTR_ERR(sg);
146 goto fail_detach;
147 }
148
149 ret = nouveau_prime_new(dev, dma_buf->size, sg, &nvbo);
150 if (ret)
151 goto fail_unmap;
152
153 nvbo->gem->import_attach = attach;
154
155 return nvbo->gem;
156
157fail_unmap:
158 dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
159fail_detach:
160 dma_buf_detach(dma_buf, attach);
161 return ERR_PTR(ret);
162}
163
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
index 47f245edf53..27aac9ada73 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c
@@ -290,7 +290,10 @@ nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *mem)
290 struct nouveau_mem *node = mem->mm_node; 290 struct nouveau_mem *node = mem->mm_node;
291 291
292 /* noop: bound in move_notify() */ 292 /* noop: bound in move_notify() */
293 node->pages = nvbe->ttm.dma_address; 293 if (ttm->sg) {
294 node->sg = ttm->sg;
295 } else
296 node->pages = nvbe->ttm.dma_address;
294 return 0; 297 return 0;
295} 298}
296 299
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.c b/drivers/gpu/drm/nouveau/nouveau_vm.c
index 2bf6c0350b4..11edd5e91a0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.c
@@ -77,6 +77,63 @@ nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
77} 77}
78 78
79void 79void
80nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
81 struct nouveau_mem *mem)
82{
83 struct nouveau_vm *vm = vma->vm;
84 int big = vma->node->type != vm->spg_shift;
85 u32 offset = vma->node->offset + (delta >> 12);
86 u32 bits = vma->node->type - 12;
87 u32 num = length >> vma->node->type;
88 u32 pde = (offset >> vm->pgt_bits) - vm->fpde;
89 u32 pte = (offset & ((1 << vm->pgt_bits) - 1)) >> bits;
90 u32 max = 1 << (vm->pgt_bits - bits);
91 unsigned m, sglen;
92 u32 end, len;
93 int i;
94 struct scatterlist *sg;
95
96 for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) {
97 struct nouveau_gpuobj *pgt = vm->pgt[pde].obj[big];
98 sglen = sg_dma_len(sg) >> PAGE_SHIFT;
99
100 end = pte + sglen;
101 if (unlikely(end >= max))
102 end = max;
103 len = end - pte;
104
105 for (m = 0; m < len; m++) {
106 dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
107
108 vm->map_sg(vma, pgt, mem, pte, 1, &addr);
109 num--;
110 pte++;
111
112 if (num == 0)
113 goto finish;
114 }
115 if (unlikely(end >= max)) {
116 pde++;
117 pte = 0;
118 }
119 if (m < sglen) {
120 for (; m < sglen; m++) {
121 dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT);
122
123 vm->map_sg(vma, pgt, mem, pte, 1, &addr);
124 num--;
125 pte++;
126 if (num == 0)
127 goto finish;
128 }
129 }
130
131 }
132finish:
133 vm->flush(vm);
134}
135
136void
80nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, 137nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
81 struct nouveau_mem *mem) 138 struct nouveau_mem *mem)
82{ 139{
diff --git a/drivers/gpu/drm/nouveau/nouveau_vm.h b/drivers/gpu/drm/nouveau/nouveau_vm.h
index 4fb6e728734..a8246e7e4a8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vm.h
+++ b/drivers/gpu/drm/nouveau/nouveau_vm.h
@@ -72,6 +72,9 @@ struct nouveau_vm {
72 u64 phys, u64 delta); 72 u64 phys, u64 delta);
73 void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *, 73 void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
74 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *); 74 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
75
76 void (*map_sg_table)(struct nouveau_vma *, struct nouveau_gpuobj *,
77 struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
75 void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt); 78 void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt);
76 void (*flush)(struct nouveau_vm *); 79 void (*flush)(struct nouveau_vm *);
77}; 80};
@@ -90,7 +93,8 @@ void nouveau_vm_unmap(struct nouveau_vma *);
90void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); 93void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
91void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, 94void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
92 struct nouveau_mem *); 95 struct nouveau_mem *);
93 96void nouveau_vm_map_sg_table(struct nouveau_vma *vma, u64 delta, u64 length,
97 struct nouveau_mem *mem);
94/* nv50_vm.c */ 98/* nv50_vm.c */
95void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, 99void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
96 struct nouveau_gpuobj *pgt[2]); 100 struct nouveau_gpuobj *pgt[2]);
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c
index 728d07584d3..4c31c63e552 100644
--- a/drivers/gpu/drm/nouveau/nv04_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv04_crtc.c
@@ -1047,7 +1047,7 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
1047 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); 1047 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
1048 1048
1049 ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, 1049 ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
1050 0, 0x0000, &nv_crtc->cursor.nvbo); 1050 0, 0x0000, NULL, &nv_crtc->cursor.nvbo);
1051 if (!ret) { 1051 if (!ret) {
1052 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); 1052 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
1053 if (!ret) 1053 if (!ret)
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c
index 701b927998b..cad2abd1175 100644
--- a/drivers/gpu/drm/nouveau/nv50_crtc.c
+++ b/drivers/gpu/drm/nouveau/nv50_crtc.c
@@ -769,7 +769,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
769 nv_crtc->lut.depth = 0; 769 nv_crtc->lut.depth = 0;
770 770
771 ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM, 771 ret = nouveau_bo_new(dev, 4096, 0x100, TTM_PL_FLAG_VRAM,
772 0, 0x0000, &nv_crtc->lut.nvbo); 772 0, 0x0000, NULL, &nv_crtc->lut.nvbo);
773 if (!ret) { 773 if (!ret) {
774 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); 774 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
775 if (!ret) 775 if (!ret)
@@ -795,7 +795,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
795 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256); 795 drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
796 796
797 ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM, 797 ret = nouveau_bo_new(dev, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
798 0, 0x0000, &nv_crtc->cursor.nvbo); 798 0, 0x0000, NULL, &nv_crtc->cursor.nvbo);
799 if (!ret) { 799 if (!ret) {
800 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); 800 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
801 if (!ret) 801 if (!ret)
diff --git a/drivers/gpu/drm/nouveau/nv50_evo.c b/drivers/gpu/drm/nouveau/nv50_evo.c
index 9b962e989d7..ddcd5559582 100644
--- a/drivers/gpu/drm/nouveau/nv50_evo.c
+++ b/drivers/gpu/drm/nouveau/nv50_evo.c
@@ -117,7 +117,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid,
117 evo->user_get = 4; 117 evo->user_get = 4;
118 evo->user_put = 0; 118 evo->user_put = 0;
119 119
120 ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, 120 ret = nouveau_bo_new(dev, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0, NULL,
121 &evo->pushbuf_bo); 121 &evo->pushbuf_bo);
122 if (ret == 0) 122 if (ret == 0)
123 ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM); 123 ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
@@ -333,7 +333,7 @@ nv50_evo_create(struct drm_device *dev)
333 goto err; 333 goto err;
334 334
335 ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 335 ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
336 0, 0x0000, &dispc->sem.bo); 336 0, 0x0000, NULL, &dispc->sem.bo);
337 if (!ret) { 337 if (!ret) {
338 ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM); 338 ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
339 if (!ret) 339 if (!ret)
diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c
index 0247250939e..1f3a9b1240e 100644
--- a/drivers/gpu/drm/nouveau/nvd0_display.c
+++ b/drivers/gpu/drm/nouveau/nvd0_display.c
@@ -882,7 +882,7 @@ nvd0_crtc_create(struct drm_device *dev, int index)
882 drm_mode_crtc_set_gamma_size(crtc, 256); 882 drm_mode_crtc_set_gamma_size(crtc, 256);
883 883
884 ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM, 884 ret = nouveau_bo_new(dev, 64 * 64 * 4, 0x100, TTM_PL_FLAG_VRAM,
885 0, 0x0000, &nv_crtc->cursor.nvbo); 885 0, 0x0000, NULL, &nv_crtc->cursor.nvbo);
886 if (!ret) { 886 if (!ret) {
887 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); 887 ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
888 if (!ret) 888 if (!ret)
@@ -895,7 +895,7 @@ nvd0_crtc_create(struct drm_device *dev, int index)
895 goto out; 895 goto out;
896 896
897 ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM, 897 ret = nouveau_bo_new(dev, 8192, 0x100, TTM_PL_FLAG_VRAM,
898 0, 0x0000, &nv_crtc->lut.nvbo); 898 0, 0x0000, NULL, &nv_crtc->lut.nvbo);
899 if (!ret) { 899 if (!ret) {
900 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM); 900 ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
901 if (!ret) 901 if (!ret)
@@ -2030,7 +2030,7 @@ nvd0_display_create(struct drm_device *dev)
2030 2030
2031 /* small shared memory area we use for notifiers and semaphores */ 2031 /* small shared memory area we use for notifiers and semaphores */
2032 ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 2032 ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM,
2033 0, 0x0000, &disp->sync); 2033 0, 0x0000, NULL, &disp->sync);
2034 if (!ret) { 2034 if (!ret) {
2035 ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM); 2035 ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM);
2036 if (!ret) 2036 if (!ret)