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.

drm/panfrost: Provide a custom dma_buf implementation

Before we introduce cached CPU mappings, we want a dma_buf
implementation satisfying synchronization requests around CPU
accesses coming from a dma_buf exported by our driver. Let's
provide our own implementation relying on the default
gem_shmem_prime helpers designed for that purpose.

v5:
- New patch

v6:
- Collect R-b

v7:
- Hand-roll our own dma_buf boilerplate

v8:
- No changes

Reviewed-by: Steven Price <steven.price@arm.com>
Link: https://patch.msgid.link/20251208100841.730527-9-boris.brezillon@collabora.com
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>

+127
+1
drivers/gpu/drm/panfrost/panfrost_drv.c
··· 852 852 .minor = 5, 853 853 854 854 .gem_create_object = panfrost_gem_create_object, 855 + .gem_prime_import = panfrost_gem_prime_import, 855 856 .gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table, 856 857 #ifdef CONFIG_DEBUG_FS 857 858 .debugfs_init = panfrost_debugfs_init,
+123
drivers/gpu/drm/panfrost/panfrost_gem.c
··· 277 277 return 0; 278 278 } 279 279 280 + static struct sg_table * 281 + panfrost_gem_prime_map_dma_buf(struct dma_buf_attachment *attach, 282 + enum dma_data_direction dir) 283 + { 284 + struct sg_table *sgt = drm_gem_map_dma_buf(attach, dir); 285 + 286 + if (!IS_ERR(sgt)) 287 + attach->priv = sgt; 288 + 289 + return sgt; 290 + } 291 + 292 + static void 293 + panfrost_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach, 294 + struct sg_table *sgt, 295 + enum dma_data_direction dir) 296 + { 297 + attach->priv = NULL; 298 + drm_gem_unmap_dma_buf(attach, sgt, dir); 299 + } 300 + 301 + static int 302 + panfrost_gem_prime_begin_cpu_access(struct dma_buf *dma_buf, 303 + enum dma_data_direction dir) 304 + { 305 + struct drm_gem_object *obj = dma_buf->priv; 306 + struct drm_device *dev = obj->dev; 307 + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); 308 + struct dma_buf_attachment *attach; 309 + 310 + dma_resv_lock(obj->resv, NULL); 311 + if (shmem->sgt) 312 + dma_sync_sgtable_for_cpu(dev->dev, shmem->sgt, dir); 313 + 314 + if (shmem->vaddr) 315 + invalidate_kernel_vmap_range(shmem->vaddr, shmem->base.size); 316 + 317 + list_for_each_entry(attach, &dma_buf->attachments, node) { 318 + struct sg_table *sgt = attach->priv; 319 + 320 + if (sgt) 321 + dma_sync_sgtable_for_cpu(attach->dev, sgt, dir); 322 + } 323 + dma_resv_unlock(obj->resv); 324 + 325 + return 0; 326 + } 327 + 328 + static int 329 + panfrost_gem_prime_end_cpu_access(struct dma_buf *dma_buf, 330 + enum dma_data_direction dir) 331 + { 332 + struct drm_gem_object *obj = dma_buf->priv; 333 + struct drm_device *dev = obj->dev; 334 + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); 335 + struct dma_buf_attachment *attach; 336 + 337 + dma_resv_lock(obj->resv, NULL); 338 + list_for_each_entry(attach, &dma_buf->attachments, node) { 339 + struct sg_table *sgt = attach->priv; 340 + 341 + if (sgt) 342 + dma_sync_sgtable_for_device(attach->dev, sgt, dir); 343 + } 344 + 345 + if (shmem->vaddr) 346 + flush_kernel_vmap_range(shmem->vaddr, shmem->base.size); 347 + 348 + if (shmem->sgt) 349 + dma_sync_sgtable_for_device(dev->dev, shmem->sgt, dir); 350 + 351 + dma_resv_unlock(obj->resv); 352 + return 0; 353 + } 354 + 355 + static const struct dma_buf_ops panfrost_dma_buf_ops = { 356 + .attach = drm_gem_map_attach, 357 + .detach = drm_gem_map_detach, 358 + .map_dma_buf = panfrost_gem_prime_map_dma_buf, 359 + .unmap_dma_buf = panfrost_gem_prime_unmap_dma_buf, 360 + .release = drm_gem_dmabuf_release, 361 + .mmap = drm_gem_dmabuf_mmap, 362 + .vmap = drm_gem_dmabuf_vmap, 363 + .vunmap = drm_gem_dmabuf_vunmap, 364 + .begin_cpu_access = panfrost_gem_prime_begin_cpu_access, 365 + .end_cpu_access = panfrost_gem_prime_end_cpu_access, 366 + }; 367 + 368 + static struct dma_buf * 369 + panfrost_gem_prime_export(struct drm_gem_object *obj, int flags) 370 + { 371 + struct drm_device *dev = obj->dev; 372 + struct dma_buf_export_info exp_info = { 373 + .exp_name = KBUILD_MODNAME, 374 + .owner = THIS_MODULE, 375 + .ops = &panfrost_dma_buf_ops, 376 + .size = obj->size, 377 + .flags = flags, 378 + .priv = obj, 379 + .resv = obj->resv, 380 + }; 381 + 382 + return drm_gem_dmabuf_export(dev, &exp_info); 383 + } 384 + 385 + struct drm_gem_object * 386 + panfrost_gem_prime_import(struct drm_device *dev, 387 + struct dma_buf *dma_buf) 388 + { 389 + struct drm_gem_object *obj = dma_buf->priv; 390 + 391 + if (dma_buf->ops == &panfrost_dma_buf_ops && obj->dev == dev) { 392 + /* Importing dmabuf exported from our own gem increases 393 + * refcount on gem itself instead of f_count of dmabuf. 394 + */ 395 + drm_gem_object_get(obj); 396 + return obj; 397 + } 398 + 399 + return drm_gem_prime_import(dev, dma_buf); 400 + } 401 + 280 402 static const struct drm_gem_object_funcs panfrost_gem_funcs = { 281 403 .free = panfrost_gem_free_object, 282 404 .open = panfrost_gem_open, ··· 407 285 .pin = panfrost_gem_pin, 408 286 .unpin = drm_gem_shmem_object_unpin, 409 287 .get_sg_table = drm_gem_shmem_object_get_sg_table, 288 + .export = panfrost_gem_prime_export, 410 289 .vmap = drm_gem_shmem_object_vmap, 411 290 .vunmap = drm_gem_shmem_object_vunmap, 412 291 .mmap = drm_gem_shmem_object_mmap,
+3
drivers/gpu/drm/panfrost/panfrost_gem.h
··· 132 132 panfrost_gem_prime_import_sg_table(struct drm_device *dev, 133 133 struct dma_buf_attachment *attach, 134 134 struct sg_table *sgt); 135 + struct drm_gem_object * 136 + panfrost_gem_prime_import(struct drm_device *dev, 137 + struct dma_buf *dma_buf); 135 138 136 139 struct panfrost_gem_object * 137 140 panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags);