Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc5 295 lines 7.5 kB view raw
1/* exynos_drm_dmabuf.c 2 * 3 * Copyright (c) 2012 Samsung Electronics Co., Ltd. 4 * Author: Inki Dae <inki.dae@samsung.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the next 14 * paragraph) shall be included in all copies or substantial portions of the 15 * Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26#include <drm/drmP.h> 27#include <drm/exynos_drm.h> 28#include "exynos_drm_drv.h" 29#include "exynos_drm_gem.h" 30 31#include <linux/dma-buf.h> 32 33static struct sg_table *exynos_pages_to_sg(struct page **pages, int nr_pages, 34 unsigned int page_size) 35{ 36 struct sg_table *sgt = NULL; 37 struct scatterlist *sgl; 38 int i, ret; 39 40 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); 41 if (!sgt) 42 goto out; 43 44 ret = sg_alloc_table(sgt, nr_pages, GFP_KERNEL); 45 if (ret) 46 goto err_free_sgt; 47 48 if (page_size < PAGE_SIZE) 49 page_size = PAGE_SIZE; 50 51 for_each_sg(sgt->sgl, sgl, nr_pages, i) 52 sg_set_page(sgl, pages[i], page_size, 0); 53 54 return sgt; 55 56err_free_sgt: 57 kfree(sgt); 58 sgt = NULL; 59out: 60 return NULL; 61} 62 63static struct sg_table * 64 exynos_gem_map_dma_buf(struct dma_buf_attachment *attach, 65 enum dma_data_direction dir) 66{ 67 struct exynos_drm_gem_obj *gem_obj = attach->dmabuf->priv; 68 struct drm_device *dev = gem_obj->base.dev; 69 struct exynos_drm_gem_buf *buf; 70 struct sg_table *sgt = NULL; 71 unsigned int npages; 72 int nents; 73 74 DRM_DEBUG_PRIME("%s\n", __FILE__); 75 76 mutex_lock(&dev->struct_mutex); 77 78 buf = gem_obj->buffer; 79 80 /* there should always be pages allocated. */ 81 if (!buf->pages) { 82 DRM_ERROR("pages is null.\n"); 83 goto err_unlock; 84 } 85 86 npages = buf->size / buf->page_size; 87 88 sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size); 89 if (!sgt) { 90 DRM_DEBUG_PRIME("exynos_pages_to_sg returned NULL!\n"); 91 goto err_unlock; 92 } 93 nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir); 94 95 DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n", 96 npages, buf->size, buf->page_size); 97 98err_unlock: 99 mutex_unlock(&dev->struct_mutex); 100 return sgt; 101} 102 103static void exynos_gem_unmap_dma_buf(struct dma_buf_attachment *attach, 104 struct sg_table *sgt, 105 enum dma_data_direction dir) 106{ 107 dma_unmap_sg(attach->dev, sgt->sgl, sgt->nents, dir); 108 sg_free_table(sgt); 109 kfree(sgt); 110 sgt = NULL; 111} 112 113static void exynos_dmabuf_release(struct dma_buf *dmabuf) 114{ 115 struct exynos_drm_gem_obj *exynos_gem_obj = dmabuf->priv; 116 117 DRM_DEBUG_PRIME("%s\n", __FILE__); 118 119 /* 120 * exynos_dmabuf_release() call means that file object's 121 * f_count is 0 and it calls drm_gem_object_handle_unreference() 122 * to drop the references that these values had been increased 123 * at drm_prime_handle_to_fd() 124 */ 125 if (exynos_gem_obj->base.export_dma_buf == dmabuf) { 126 exynos_gem_obj->base.export_dma_buf = NULL; 127 128 /* 129 * drop this gem object refcount to release allocated buffer 130 * and resources. 131 */ 132 drm_gem_object_unreference_unlocked(&exynos_gem_obj->base); 133 } 134} 135 136static void *exynos_gem_dmabuf_kmap_atomic(struct dma_buf *dma_buf, 137 unsigned long page_num) 138{ 139 /* TODO */ 140 141 return NULL; 142} 143 144static void exynos_gem_dmabuf_kunmap_atomic(struct dma_buf *dma_buf, 145 unsigned long page_num, 146 void *addr) 147{ 148 /* TODO */ 149} 150 151static void *exynos_gem_dmabuf_kmap(struct dma_buf *dma_buf, 152 unsigned long page_num) 153{ 154 /* TODO */ 155 156 return NULL; 157} 158 159static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf, 160 unsigned long page_num, void *addr) 161{ 162 /* TODO */ 163} 164 165static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf, 166 struct vm_area_struct *vma) 167{ 168 return -ENOTTY; 169} 170 171static struct dma_buf_ops exynos_dmabuf_ops = { 172 .map_dma_buf = exynos_gem_map_dma_buf, 173 .unmap_dma_buf = exynos_gem_unmap_dma_buf, 174 .kmap = exynos_gem_dmabuf_kmap, 175 .kmap_atomic = exynos_gem_dmabuf_kmap_atomic, 176 .kunmap = exynos_gem_dmabuf_kunmap, 177 .kunmap_atomic = exynos_gem_dmabuf_kunmap_atomic, 178 .mmap = exynos_gem_dmabuf_mmap, 179 .release = exynos_dmabuf_release, 180}; 181 182struct dma_buf *exynos_dmabuf_prime_export(struct drm_device *drm_dev, 183 struct drm_gem_object *obj, int flags) 184{ 185 struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj); 186 187 return dma_buf_export(exynos_gem_obj, &exynos_dmabuf_ops, 188 exynos_gem_obj->base.size, 0600); 189} 190 191struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev, 192 struct dma_buf *dma_buf) 193{ 194 struct dma_buf_attachment *attach; 195 struct sg_table *sgt; 196 struct scatterlist *sgl; 197 struct exynos_drm_gem_obj *exynos_gem_obj; 198 struct exynos_drm_gem_buf *buffer; 199 struct page *page; 200 int ret; 201 202 DRM_DEBUG_PRIME("%s\n", __FILE__); 203 204 /* is this one of own objects? */ 205 if (dma_buf->ops == &exynos_dmabuf_ops) { 206 struct drm_gem_object *obj; 207 208 exynos_gem_obj = dma_buf->priv; 209 obj = &exynos_gem_obj->base; 210 211 /* is it from our device? */ 212 if (obj->dev == drm_dev) { 213 drm_gem_object_reference(obj); 214 return obj; 215 } 216 } 217 218 attach = dma_buf_attach(dma_buf, drm_dev->dev); 219 if (IS_ERR(attach)) 220 return ERR_PTR(-EINVAL); 221 222 223 sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); 224 if (IS_ERR_OR_NULL(sgt)) { 225 ret = PTR_ERR(sgt); 226 goto err_buf_detach; 227 } 228 229 buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); 230 if (!buffer) { 231 DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n"); 232 ret = -ENOMEM; 233 goto err_unmap_attach; 234 } 235 236 buffer->pages = kzalloc(sizeof(*page) * sgt->nents, GFP_KERNEL); 237 if (!buffer->pages) { 238 DRM_ERROR("failed to allocate pages.\n"); 239 ret = -ENOMEM; 240 goto err_free_buffer; 241 } 242 243 exynos_gem_obj = exynos_drm_gem_init(drm_dev, dma_buf->size); 244 if (!exynos_gem_obj) { 245 ret = -ENOMEM; 246 goto err_free_pages; 247 } 248 249 sgl = sgt->sgl; 250 251 if (sgt->nents == 1) { 252 buffer->dma_addr = sg_dma_address(sgt->sgl); 253 buffer->size = sg_dma_len(sgt->sgl); 254 255 /* always physically continuous memory if sgt->nents is 1. */ 256 exynos_gem_obj->flags |= EXYNOS_BO_CONTIG; 257 } else { 258 unsigned int i = 0; 259 260 buffer->dma_addr = sg_dma_address(sgl); 261 while (i < sgt->nents) { 262 buffer->pages[i] = sg_page(sgl); 263 buffer->size += sg_dma_len(sgl); 264 sgl = sg_next(sgl); 265 i++; 266 } 267 268 exynos_gem_obj->flags |= EXYNOS_BO_NONCONTIG; 269 } 270 271 exynos_gem_obj->buffer = buffer; 272 buffer->sgt = sgt; 273 exynos_gem_obj->base.import_attach = attach; 274 275 DRM_DEBUG_PRIME("dma_addr = 0x%x, size = 0x%lx\n", buffer->dma_addr, 276 buffer->size); 277 278 return &exynos_gem_obj->base; 279 280err_free_pages: 281 kfree(buffer->pages); 282 buffer->pages = NULL; 283err_free_buffer: 284 kfree(buffer); 285 buffer = NULL; 286err_unmap_attach: 287 dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL); 288err_buf_detach: 289 dma_buf_detach(dma_buf, attach); 290 return ERR_PTR(ret); 291} 292 293MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>"); 294MODULE_DESCRIPTION("Samsung SoC DRM DMABUF Module"); 295MODULE_LICENSE("GPL");