diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-31 21:01:18 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-31 21:01:18 -0400 |
| commit | 9fdadb2cbaf4b482dfd6086e8bd3d2db071a1702 (patch) | |
| tree | 4a6e11e3379ee93c1992cfd595872dded1fd2fac | |
| parent | 76f901eb4659779ecacd0e4eba49f55442daef53 (diff) | |
| parent | 63bc620b45af8c743ac291c8725933278c712692 (diff) | |
Merge branch 'drm-prime-vmap' of git://people.freedesktop.org/~airlied/linux
Pull drm prime mmap/vmap code from Dave Airlie:
"As mentioned previously these are the extra bits of drm that relied on
the dma-buf pull to work, the first three just stub out the mmap
interface, and the next set provide vmap export to i915/radeon/nouveau
and vmap import to udl."
* 'drm-prime-vmap' of git://people.freedesktop.org/~airlied/linux:
radeon: add radeon prime vmap support.
nouveau: add vmap support to nouveau prime support
udl: support vmapping imported dma-bufs
i915: add dma-buf vmap support for exporting vmapped buffer
radeon: add stub dma-buf mmap functionality
nouveau: add stub dma-buf mmap functionality.
i915: add stub dma-buf mmap callback.
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_dmabuf.c | 61 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_prime.c | 45 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_prime.c | 44 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_fb.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/udl/udl_gem.c | 25 |
8 files changed, 192 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 377c21f531e4..c9cfc67c2cf5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -942,6 +942,9 @@ struct drm_i915_gem_object { | |||
| 942 | 942 | ||
| 943 | /* prime dma-buf support */ | 943 | /* prime dma-buf support */ |
| 944 | struct sg_table *sg_table; | 944 | struct sg_table *sg_table; |
| 945 | void *dma_buf_vmapping; | ||
| 946 | int vmapping_count; | ||
| 947 | |||
| 945 | /** | 948 | /** |
| 946 | * Used for performing relocations during execbuffer insertion. | 949 | * Used for performing relocations during execbuffer insertion. |
| 947 | */ | 950 | */ |
diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 8e269178d6a5..aa308e1337db 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c | |||
| @@ -74,6 +74,59 @@ static void i915_gem_dmabuf_release(struct dma_buf *dma_buf) | |||
| 74 | } | 74 | } |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf) | ||
| 78 | { | ||
| 79 | struct drm_i915_gem_object *obj = dma_buf->priv; | ||
| 80 | struct drm_device *dev = obj->base.dev; | ||
| 81 | int ret; | ||
| 82 | |||
| 83 | ret = i915_mutex_lock_interruptible(dev); | ||
| 84 | if (ret) | ||
| 85 | return ERR_PTR(ret); | ||
| 86 | |||
| 87 | if (obj->dma_buf_vmapping) { | ||
| 88 | obj->vmapping_count++; | ||
| 89 | goto out_unlock; | ||
| 90 | } | ||
| 91 | |||
| 92 | if (!obj->pages) { | ||
| 93 | ret = i915_gem_object_get_pages_gtt(obj, __GFP_NORETRY | __GFP_NOWARN); | ||
| 94 | if (ret) { | ||
| 95 | mutex_unlock(&dev->struct_mutex); | ||
| 96 | return ERR_PTR(ret); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | |||
| 100 | obj->dma_buf_vmapping = vmap(obj->pages, obj->base.size / PAGE_SIZE, 0, PAGE_KERNEL); | ||
| 101 | if (!obj->dma_buf_vmapping) { | ||
| 102 | DRM_ERROR("failed to vmap object\n"); | ||
| 103 | goto out_unlock; | ||
| 104 | } | ||
| 105 | |||
| 106 | obj->vmapping_count = 1; | ||
| 107 | out_unlock: | ||
| 108 | mutex_unlock(&dev->struct_mutex); | ||
| 109 | return obj->dma_buf_vmapping; | ||
| 110 | } | ||
| 111 | |||
| 112 | static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) | ||
| 113 | { | ||
| 114 | struct drm_i915_gem_object *obj = dma_buf->priv; | ||
| 115 | struct drm_device *dev = obj->base.dev; | ||
| 116 | int ret; | ||
| 117 | |||
| 118 | ret = i915_mutex_lock_interruptible(dev); | ||
| 119 | if (ret) | ||
| 120 | return; | ||
| 121 | |||
| 122 | --obj->vmapping_count; | ||
| 123 | if (obj->vmapping_count == 0) { | ||
| 124 | vunmap(obj->dma_buf_vmapping); | ||
| 125 | obj->dma_buf_vmapping = NULL; | ||
| 126 | } | ||
| 127 | mutex_unlock(&dev->struct_mutex); | ||
| 128 | } | ||
| 129 | |||
| 77 | static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) | 130 | static void *i915_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, unsigned long page_num) |
| 78 | { | 131 | { |
| 79 | return NULL; | 132 | return NULL; |
| @@ -93,6 +146,11 @@ static void i915_gem_dmabuf_kunmap(struct dma_buf *dma_buf, unsigned long page_n | |||
| 93 | 146 | ||
| 94 | } | 147 | } |
| 95 | 148 | ||
| 149 | static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) | ||
| 150 | { | ||
| 151 | return -EINVAL; | ||
| 152 | } | ||
| 153 | |||
| 96 | static const struct dma_buf_ops i915_dmabuf_ops = { | 154 | static const struct dma_buf_ops i915_dmabuf_ops = { |
| 97 | .map_dma_buf = i915_gem_map_dma_buf, | 155 | .map_dma_buf = i915_gem_map_dma_buf, |
| 98 | .unmap_dma_buf = i915_gem_unmap_dma_buf, | 156 | .unmap_dma_buf = i915_gem_unmap_dma_buf, |
| @@ -101,6 +159,9 @@ static const struct dma_buf_ops i915_dmabuf_ops = { | |||
| 101 | .kmap_atomic = i915_gem_dmabuf_kmap_atomic, | 159 | .kmap_atomic = i915_gem_dmabuf_kmap_atomic, |
| 102 | .kunmap = i915_gem_dmabuf_kunmap, | 160 | .kunmap = i915_gem_dmabuf_kunmap, |
| 103 | .kunmap_atomic = i915_gem_dmabuf_kunmap_atomic, | 161 | .kunmap_atomic = i915_gem_dmabuf_kunmap_atomic, |
| 162 | .mmap = i915_gem_dmabuf_mmap, | ||
| 163 | .vmap = i915_gem_dmabuf_vmap, | ||
| 164 | .vunmap = i915_gem_dmabuf_vunmap, | ||
| 104 | }; | 165 | }; |
| 105 | 166 | ||
| 106 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, | 167 | struct dma_buf *i915_gem_prime_export(struct drm_device *dev, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 634d222c93de..8613cb23808c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
| @@ -123,6 +123,9 @@ struct nouveau_bo { | |||
| 123 | 123 | ||
| 124 | struct drm_gem_object *gem; | 124 | struct drm_gem_object *gem; |
| 125 | int pin_refcnt; | 125 | int pin_refcnt; |
| 126 | |||
| 127 | struct ttm_bo_kmap_obj dma_buf_vmap; | ||
| 128 | int vmapping_count; | ||
| 126 | }; | 129 | }; |
| 127 | 130 | ||
| 128 | #define nouveau_bo_tile_layout(nvbo) \ | 131 | #define nouveau_bo_tile_layout(nvbo) \ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index c58aab7370c5..a89240e5fb29 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c | |||
| @@ -61,6 +61,48 @@ static void nouveau_gem_kunmap(struct dma_buf *dma_buf, unsigned long page_num, | |||
| 61 | 61 | ||
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static int nouveau_gem_prime_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) | ||
| 65 | { | ||
| 66 | return -EINVAL; | ||
| 67 | } | ||
| 68 | |||
| 69 | static void *nouveau_gem_prime_vmap(struct dma_buf *dma_buf) | ||
| 70 | { | ||
| 71 | struct nouveau_bo *nvbo = dma_buf->priv; | ||
| 72 | struct drm_device *dev = nvbo->gem->dev; | ||
| 73 | int ret; | ||
| 74 | |||
| 75 | mutex_lock(&dev->struct_mutex); | ||
| 76 | if (nvbo->vmapping_count) { | ||
| 77 | nvbo->vmapping_count++; | ||
| 78 | goto out_unlock; | ||
| 79 | } | ||
| 80 | |||
| 81 | ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.num_pages, | ||
| 82 | &nvbo->dma_buf_vmap); | ||
| 83 | if (ret) { | ||
| 84 | mutex_unlock(&dev->struct_mutex); | ||
| 85 | return ERR_PTR(ret); | ||
| 86 | } | ||
| 87 | nvbo->vmapping_count = 1; | ||
| 88 | out_unlock: | ||
| 89 | mutex_unlock(&dev->struct_mutex); | ||
| 90 | return nvbo->dma_buf_vmap.virtual; | ||
| 91 | } | ||
| 92 | |||
| 93 | static void nouveau_gem_prime_vunmap(struct dma_buf *dma_buf, void *vaddr) | ||
| 94 | { | ||
| 95 | struct nouveau_bo *nvbo = dma_buf->priv; | ||
| 96 | struct drm_device *dev = nvbo->gem->dev; | ||
| 97 | |||
| 98 | mutex_lock(&dev->struct_mutex); | ||
| 99 | nvbo->vmapping_count--; | ||
| 100 | if (nvbo->vmapping_count == 0) { | ||
| 101 | ttm_bo_kunmap(&nvbo->dma_buf_vmap); | ||
| 102 | } | ||
| 103 | mutex_unlock(&dev->struct_mutex); | ||
| 104 | } | ||
| 105 | |||
| 64 | static const struct dma_buf_ops nouveau_dmabuf_ops = { | 106 | static const struct dma_buf_ops nouveau_dmabuf_ops = { |
| 65 | .map_dma_buf = nouveau_gem_map_dma_buf, | 107 | .map_dma_buf = nouveau_gem_map_dma_buf, |
| 66 | .unmap_dma_buf = nouveau_gem_unmap_dma_buf, | 108 | .unmap_dma_buf = nouveau_gem_unmap_dma_buf, |
| @@ -69,6 +111,9 @@ static const struct dma_buf_ops nouveau_dmabuf_ops = { | |||
| 69 | .kmap_atomic = | ||
