1 /* 2 * NVIDIA Tegra DRM GEM helper functions 3 * 4 * Copyright (C) 2012 Sascha Hauer, Pengutronix 5 * Copyright (C) 2013 NVIDIA CORPORATION, All rights reserved. 6 * 7 * Based on the GEM/CMA helpers 8 * 9 * Copyright (c) 2011 Samsung Electronics Co., Ltd. 10 * 11 * This program is free software; you can redistribute it and/or 12 * modify it under the terms of the GNU General Public License 13 * as published by the Free Software Foundation; either version 2 14 * of the License, or (at your option) any later version. 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 #include <linux/dma-buf.h> 22 #include <drm/tegra_drm.h> 23 24 #include "gem.h" 25 26 static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) 27 { 28 return container_of(bo, struct tegra_bo, base); 29 } 30 31 static void tegra_bo_put(struct host1x_bo *bo) 32 { 33 struct tegra_bo *obj = host1x_to_tegra_bo(bo); 34 struct drm_device *drm = obj->gem.dev; 35 36 mutex_lock(&drm->struct_mutex); 37 drm_gem_object_unreference(&obj->gem); 38 mutex_unlock(&drm->struct_mutex); 39 } 40 41 static dma_addr_t tegra_bo_pin(struct host1x_bo *bo, struct sg_table **sgt) 42 { 43 struct tegra_bo *obj = host1x_to_tegra_bo(bo); 44 45 return obj->paddr; 46 } 47 48 static void tegra_bo_unpin(struct host1x_bo *bo, struct sg_table *sgt) 49 { 50 } 51 52 static void *tegra_bo_mmap(struct host1x_bo *bo) 53 { 54 struct tegra_bo *obj = host1x_to_tegra_bo(bo); 55 56 return obj->vaddr; 57 } 58 59 static void tegra_bo_munmap(struct host1x_bo *bo, void *addr) 60 { 61 } 62 63 static void *tegra_bo_kmap(struct host1x_bo *bo, unsigned int page) 64 { 65 struct tegra_bo *obj = host1x_to_tegra_bo(bo); 66 67 return obj->vaddr + page * PAGE_SIZE; 68 } 69 70 static void tegra_bo_kunmap(struct host1x_bo *bo, unsigned int page, 71 void *addr) 72 { 73 } 74 75 static struct host1x_bo *tegra_bo_get(struct host1x_bo *bo) 76 { 77 struct tegra_bo *obj = host1x_to_tegra_bo(bo); 78 struct drm_device *drm = obj->gem.dev; 79 80 mutex_lock(&drm->struct_mutex); 81 drm_gem_object_reference(&obj->gem); 82 mutex_unlock(&drm->struct_mutex); 83 84 return bo; 85 } 86 87 static const struct host1x_bo_ops tegra_bo_ops = { 88 .get = tegra_bo_get, 89 .put = tegra_bo_put, 90 .pin = tegra_bo_pin, 91 .unpin = tegra_bo_unpin, 92 .mmap = tegra_bo_mmap, 93 .munmap = tegra_bo_munmap, 94 .kmap = tegra_bo_kmap, 95 .kunmap = tegra_bo_kunmap, 96 }; 97 98 static void tegra_bo_destroy(struct drm_device *drm, struct tegra_bo *bo) 99 { 100 dma_free_writecombine(drm->dev, bo->gem.size, bo->vaddr, bo->paddr); 101 } 102 103 struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, 104 unsigned long flags) 105 { 106 struct tegra_bo *bo; 107 int err; 108 109 bo = kzalloc(sizeof(*bo), GFP_KERNEL); 110 if (!bo) 111 return ERR_PTR(-ENOMEM); 112 113 host1x_bo_init(&bo->base, &tegra_bo_ops); 114 size = round_up(size, PAGE_SIZE); 115 116 bo->vaddr = dma_alloc_writecombine(drm->dev, size, &bo->paddr, 117 GFP_KERNEL | __GFP_NOWARN); 118 if (!bo->vaddr) { 119 dev_err(drm->dev, "failed to allocate buffer with size %u\n", 120 size); 121 err = -ENOMEM; 122 goto err_dma; 123 } 124 125 err = drm_gem_object_init(drm, &bo->gem, size); 126 if (err) 127 goto err_init; 128 129 err = drm_gem_create_mmap_offset(&bo->gem); 130 if (err) 131 goto err_mmap; 132 133 if (flags & DRM_TEGRA_GEM_CREATE_TILED) 134 bo->flags |= TEGRA_BO_TILED; 135 136 if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP) 137 bo->flags |= TEGRA_BO_BOTTOM_UP; 138 139 return bo; 140 141 err_mmap: 142 drm_gem_object_release(&bo->gem); 143 err_init: 144 tegra_bo_destroy(drm, bo); 145 err_dma: 146 kfree(bo); 147 148 return ERR_PTR(err); 149 } 150 151 struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, 152 struct drm_device *drm, 153 unsigned int size, 154 unsigned long flags, 155 unsigned int *handle) 156 { 157 struct tegra_bo *bo; 158 int ret; 159 160 bo = tegra_bo_create(drm, size, flags); 161 if (IS_ERR(bo)) 162 return bo; 163 164 ret = drm_gem_handle_create(file, &bo->gem, handle); 165 if (ret) 166 goto err; 167 168 drm_gem_object_unreference_unlocked(&bo->gem); 169 170 return bo; 171 172 err: 173 tegra_bo_free_object(&bo->gem); 174 return ERR_PTR(ret); 175 } 176 177 struct tegra_bo *tegra_bo_import(struct drm_device *drm, struct dma_buf *buf) 178 { 179 struct dma_buf_attachment *attach; 180 struct tegra_bo *bo; 181 ssize_t size; 182 int err; 183 184 bo = kzalloc(sizeof(*bo), GFP_KERNEL); 185 if (!bo) 186 return ERR_PTR(-ENOMEM); 187 188 host1x_bo_init(&bo->base, &tegra_bo_ops); 189 size = round_up(buf->size, PAGE_SIZE); 190 191 err = drm_gem_object_init(drm, &bo->gem, size); 192 if (err < 0) 193 goto free; 194 195 err = drm_gem_create_mmap_offset(&bo->gem); 196 if (err < 0) 197 goto release; 198 199 attach = dma_buf_attach(buf, drm->dev); 200 if (IS_ERR(attach)) { 201 err = PTR_ERR(attach); 202 goto free_mmap; 203 } 204 205 get_dma_buf(buf); 206 207 bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE); 208 if (!bo->sgt) { 209 err = -ENOMEM; 210 goto detach; 211 } 212 213 if (IS_ERR(bo->sgt)) { 214 err = PTR_ERR(bo->sgt); 215 goto detach; 216 } 217 218 if (bo->sgt->nents > 1) { 219 err = -EINVAL; 220 goto detach; 221 } 222 223 bo->paddr = sg_dma_address(bo->sgt->sgl); 224 bo->gem.import_attach = attach; 225 226 return bo; 227 228 detach: 229 if (!IS_ERR_OR_NULL(bo->sgt)) 230 dma_buf_unmap_attachment(attach, bo->sgt, DMA_TO_DEVICE); 231 232 dma_buf_detach(buf, attach); 233 dma_buf_put(buf); 234 free_mmap: 235 drm_gem_free_mmap_offset(&bo->gem); 236 release: 237 drm_gem_object_release(&bo->gem); 238 free: 239 kfree(bo); 240 241 return ERR_PTR(err); 242 } 243 244 void tegra_bo_free_object(struct drm_gem_object *gem) 245 { 246 struct tegra_bo *bo = to_tegra_bo(gem); 247 248 if (gem->import_attach) { 249 dma_buf_unmap_attachment(gem->import_attach, bo->sgt, 250 DMA_TO_DEVICE); 251 drm_prime_gem_destroy(gem, NULL); 252 } else { 253 tegra_bo_destroy(gem->dev, bo); 254 } 255 256 drm_gem_free_mmap_offset(gem); 257 drm_gem_object_release(gem); 258 259 kfree(bo); 260 } 261 262 int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, 263 struct drm_mode_create_dumb *args) 264 { 265 int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); 266 struct tegra_bo *bo; 267 268 if (args->pitch < min_pitch) 269 args->pitch = min_pitch; 270 271 if (args->size < args->pitch * args->height) 272 args->size = args->pitch * args->height; 273 274 bo = tegra_bo_create_with_handle(file, drm, args->size, 0, 275 &args->handle); 276 if (IS_ERR(bo)) 277 return PTR_ERR(bo); 278 279 return 0; 280 } 281 282 int tegra_bo_dumb_map_offset(struct drm_file *file, struct drm_device *drm, 283 uint32_t handle, uint64_t *offset) 284 { 285 struct drm_gem_object *gem; 286 struct tegra_bo *bo; 287 288 mutex_lock(&drm->struct_mutex); 289 290 gem = drm_gem_object_lookup(drm, file, handle); 291 if (!gem) { 292 dev_err(drm->dev, "failed to lookup GEM object\n"); 293 mutex_unlock(&drm->struct_mutex); 294 return -EINVAL; 295 } 296 297 bo = to_tegra_bo(gem); 298 299 *offset = drm_vma_node_offset_addr(&bo->gem.vma_node); 300 301 drm_gem_object_unreference(gem); 302 303 mutex_unlock(&drm->struct_mutex); 304 305 return 0; 306 } 307 308 const struct vm_operations_struct tegra_bo_vm_ops = { 309 .open = drm_gem_vm_open, 310 .close = drm_gem_vm_close, 311 }; 312 313 int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma) 314 { 315 struct drm_gem_object *gem; 316 struct tegra_bo *bo; 317 int ret; 318 319 ret = drm_gem_mmap(file, vma); 320 if (ret) 321 return ret; 322 323 gem = vma->vm_private_data; 324 bo = to_tegra_bo(gem); 325 326 ret = remap_pfn_range(vma, vma->vm_start, bo->paddr >> PAGE_SHIFT, 327 vma->vm_end - vma->vm_start, vma->vm_page_prot); 328 if (ret) 329 drm_gem_vm_close(vma); 330 331 return ret; 332 } 333 334 static struct sg_table * 335 tegra_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, 336 enum dma_data_direction dir) 337 { 338 struct drm_gem_object *gem = attach->dmabuf->priv; 339 struct tegra_bo *bo = to_tegra_bo(gem); 340 struct sg_table *sgt; 341 342 sgt = kmalloc(sizeof(*sgt), GFP_KERNEL); 343 if (!sgt) 344 return NULL; 345 346 if (sg_alloc_table(sgt, 1, GFP_KERNEL)) { 347 kfree(sgt); 348 return NULL; 349 } 350 351 sg_dma_address(sgt->sgl) = bo->paddr; 352 sg_dma_len(sgt->sgl) = gem->size; 353 354 return sgt; 355 } 356 357 static void tegra_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach, 358 struct sg_table *sgt, 359 enum dma_data_direction dir) 360 { 361 sg_free_table(sgt); 362 kfree(sgt); 363 } 364 365 static void tegra_gem_prime_release(struct dma_buf *buf) 366 { 367 drm_gem_dmabuf_release(buf); 368 } 369 370 static void *tegra_gem_prime_kmap_atomic(struct dma_buf *buf, 371 unsigned long page) 372 { 373 return NULL; 374 } 375 376 static void tegra_gem_prime_kunmap_atomic(struct dma_buf *buf, 377 unsigned long page, 378 void *addr) 379 { 380 } 381 382 static void *tegra_gem_prime_kmap(struct dma_buf *buf, unsigned long page) 383 { 384 return NULL; 385 } 386 387 static void tegra_gem_prime_kunmap(struct dma_buf *buf, unsigned long page, 388 void *addr) 389 { 390 } 391 392 static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma) 393 { 394 return -EINVAL; 395 } 396 397 static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = { 398 .map_dma_buf = tegra_gem_prime_map_dma_buf, 399 .unmap_dma_buf = tegra_gem_prime_unmap_dma_buf, 400 .release = tegra_gem_prime_release, 401 .kmap_atomic = tegra_gem_prime_kmap_atomic, 402 .kunmap_atomic = tegra_gem_prime_kunmap_atomic, 403 .kmap = tegra_gem_prime_kmap, 404 .kunmap = tegra_gem_prime_kunmap, 405 .mmap = tegra_gem_prime_mmap, 406 }; 407 408 struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, 409 struct drm_gem_object *gem, 410 int flags) 411 { 412 return dma_buf_export(gem, &tegra_gem_prime_dmabuf_ops, gem->size, 413 flags); 414 } 415 416 struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, 417 struct dma_buf *buf) 418 { 419 struct tegra_bo *bo; 420 421 if (buf->ops == &tegra_gem_prime_dmabuf_ops) { 422 struct drm_gem_object *gem = buf->priv; 423 424 if (gem->dev == drm) { 425 drm_gem_object_reference(gem); 426 return gem; 427 } 428 } 429 430 bo = tegra_bo_import(drm, buf); 431 if (IS_ERR(bo)) 432 return ERR_CAST(bo); 433 434 return &bo->gem; 435 } 436