diff options
author | Dave Airlie <airlied@redhat.com> | 2012-04-02 06:53:06 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-05-23 05:46:55 -0400 |
commit | 22b33e8ed0e38b8ddcf082e35580f2e67a3a0262 (patch) | |
tree | d6e51cc2c960d8ee5f0b2fa598971d985031532e /drivers/gpu/drm/nouveau | |
parent | 129b78bfca591e736e56a294f0e357d73d938f7e (diff) |
nouveau: add PRIME support
This adds prime->fd and fd->prime support to nouveau,
it passes the SG object to TTM, and then populates the
GART entries using it.
v2: add stubbed kmap + use new function to fill out pages array
for faulting + add reimport test.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
-rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 42 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_channel.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mem.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_prime.c | 163 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_sgdma.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_vm.c | 57 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_vm.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_crtc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_crtc.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_evo.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvd0_display.c | 6 |
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 | ||
42 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o | 42 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o |
43 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o | 43 | nouveau-$(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, | |||
89 | int | 89 | int |
90 | nouveau_bo_new(struct drm_device *dev, int size, int align, | 90 | nouveau_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 | ||
91 | struct nouveau_tile_reg { | 92 | struct nouveau_tile_reg { |
@@ -1416,7 +1417,9 @@ extern int nv04_crtc_create(struct drm_device *, int index); | |||
1416 | extern struct ttm_bo_driver nouveau_bo_driver; | 1417 | extern struct ttm_bo_driver nouveau_bo_driver; |
1417 | extern int nouveau_bo_new(struct drm_device *, int size, int align, | 1418 | extern 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 **); | ||
1420 | extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); | 1423 | extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags); |
1421 | extern int nouveau_bo_unpin(struct nouveau_bo *); | 1424 | extern int nouveau_bo_unpin(struct nouveau_bo *); |
1422 | extern int nouveau_bo_map(struct nouveau_bo *); | 1425 | extern int nouveau_bo_map(struct nouveau_bo *); |
@@ -1501,6 +1504,11 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *, | |||
1501 | extern int nouveau_gem_ioctl_info(struct drm_device *, void *, | 1504 | extern int nouveau_gem_ioctl_info(struct drm_device *, void *, |
1502 | struct drm_file *); | 1505 | struct drm_file *); |
1503 | 1506 | ||
1507 | extern struct dma_buf *nouveau_gem_prime_export(struct drm_device *dev, | ||
1508 | struct drm_gem_object *obj, int flags); | ||
1509 | extern 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 */ |
1505 | int nouveau_display_create(struct drm_device *dev); | 1513 | int nouveau_display_create(struct drm_device *dev); |
1506 | void nouveau_display_destroy(struct drm_device *dev); | 1514 | void 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 | |||
11 | static 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 | |||
27 | static 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 | |||
35 | static 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 | |||
45 | static void *nouveau_gem_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) | ||
46 | { | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | static void nouveau_gem_kunmap_atomic(struct dma_buf *dma_buf, unsigned long page_num, void *addr) | ||
51 | { | ||
52 | |||
53 | } | ||
54 | static void *nouveau_gem_kmap(struct dma_buf *dma_buf, unsigned long page_num) | ||
55 | { | ||
56 | return NULL; | ||
57 | } | ||
58 | |||
59 | static void nouveau_gem_kunmap(struct dma_buf *dma_buf, unsigned long page_num, void *addr) | ||
60 | { | ||
61 | |||
62 | } | ||
63 | |||
64 | struct 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 | |||
74 | static int | ||
75 | nouveau_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 | |||
107 | struct 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 | |||
121 | struct 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 | |||
157 | fail_unmap: | ||
158 | dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL); | ||
159 | fail_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 | ||
79 | void | 79 | void |
80 | nouveau_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 | } | ||
132 | finish: | ||
133 | vm->flush(vm); | ||
134 | } | ||
135 | |||
136 | void | ||
80 | nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, | 137 | nouveau_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 *); | |||
90 | void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); | 93 | void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); |
91 | void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, | 94 | void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, |
92 | struct nouveau_mem *); | 95 | struct nouveau_mem *); |
93 | 96 | void 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 */ |
95 | void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, | 99 | void 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) |