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

drm: Add helpers for setting up an array of dma_fence dependencies.

I needed to add implicit dependency support for v3d, and Rob Herring
has been working on it for panfrost, and I had recently looked at the
lima implementation so I think this will be a good intersection of
what we all want and simplify our scheduler implementations.

v2: Rebase on xa_limit_32b API change, and tiny checkpatch cleanups on
the way in (unsigned int vs unsigned, extra return before
EXPORT_SYMBOL_GPL)

Signed-off-by: Eric Anholt <eric@anholt.net>
Link: https://patchwork.freedesktop.org/patch/msgid/20190401222635.25013-6-eric@anholt.net
Reviewed-and-tested-by: Qiang Yu <yuq825@gmail.com> (v1)

+98
+93
drivers/gpu/drm/drm_gem.c
··· 1367 1367 ww_acquire_fini(acquire_ctx); 1368 1368 } 1369 1369 EXPORT_SYMBOL(drm_gem_unlock_reservations); 1370 + 1371 + /** 1372 + * drm_gem_fence_array_add - Adds the fence to an array of fences to be 1373 + * waited on, deduplicating fences from the same context. 1374 + * 1375 + * @fence_array array of dma_fence * for the job to block on. 1376 + * @fence the dma_fence to add to the list of dependencies. 1377 + * 1378 + * Returns: 1379 + * 0 on success, or an error on failing to expand the array. 1380 + */ 1381 + int drm_gem_fence_array_add(struct xarray *fence_array, 1382 + struct dma_fence *fence) 1383 + { 1384 + struct dma_fence *entry; 1385 + unsigned long index; 1386 + u32 id = 0; 1387 + int ret; 1388 + 1389 + if (!fence) 1390 + return 0; 1391 + 1392 + /* Deduplicate if we already depend on a fence from the same context. 1393 + * This lets the size of the array of deps scale with the number of 1394 + * engines involved, rather than the number of BOs. 1395 + */ 1396 + xa_for_each(fence_array, index, entry) { 1397 + if (entry->context != fence->context) 1398 + continue; 1399 + 1400 + if (dma_fence_is_later(fence, entry)) { 1401 + dma_fence_put(entry); 1402 + xa_store(fence_array, index, fence, GFP_KERNEL); 1403 + } else { 1404 + dma_fence_put(fence); 1405 + } 1406 + return 0; 1407 + } 1408 + 1409 + ret = xa_alloc(fence_array, &id, fence, xa_limit_32b, GFP_KERNEL); 1410 + if (ret != 0) 1411 + dma_fence_put(fence); 1412 + 1413 + return ret; 1414 + } 1415 + EXPORT_SYMBOL(drm_gem_fence_array_add); 1416 + 1417 + /** 1418 + * drm_gem_fence_array_add_implicit - Adds the implicit dependencies tracked 1419 + * in the GEM object's reservation object to an array of dma_fences for use in 1420 + * scheduling a rendering job. 1421 + * 1422 + * This should be called after drm_gem_lock_reservations() on your array of 1423 + * GEM objects used in the job but before updating the reservations with your 1424 + * own fences. 1425 + * 1426 + * @fence_array array of dma_fence * for the job to block on. 1427 + * @obj the gem object to add new dependencies from. 1428 + * @write whether the job might write the object (so we need to depend on 1429 + * shared fences in the reservation object). 1430 + */ 1431 + int drm_gem_fence_array_add_implicit(struct xarray *fence_array, 1432 + struct drm_gem_object *obj, 1433 + bool write) 1434 + { 1435 + int ret; 1436 + struct dma_fence **fences; 1437 + unsigned int i, fence_count; 1438 + 1439 + if (!write) { 1440 + struct dma_fence *fence = 1441 + reservation_object_get_excl_rcu(obj->resv); 1442 + 1443 + return drm_gem_fence_array_add(fence_array, fence); 1444 + } 1445 + 1446 + ret = reservation_object_get_fences_rcu(obj->resv, NULL, 1447 + &fence_count, &fences); 1448 + if (ret || !fence_count) 1449 + return ret; 1450 + 1451 + for (i = 0; i < fence_count; i++) { 1452 + ret = drm_gem_fence_array_add(fence_array, fences[i]); 1453 + if (ret) 1454 + break; 1455 + } 1456 + 1457 + for (; i < fence_count; i++) 1458 + dma_fence_put(fences[i]); 1459 + kfree(fences); 1460 + return ret; 1461 + } 1462 + EXPORT_SYMBOL(drm_gem_fence_array_add_implicit);
+5
include/drm/drm_gem.h
··· 390 390 struct ww_acquire_ctx *acquire_ctx); 391 391 void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, 392 392 struct ww_acquire_ctx *acquire_ctx); 393 + int drm_gem_fence_array_add(struct xarray *fence_array, 394 + struct dma_fence *fence); 395 + int drm_gem_fence_array_add_implicit(struct xarray *fence_array, 396 + struct drm_gem_object *obj, 397 + bool write); 393 398 int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, 394 399 u32 handle, u64 *offset); 395 400 int drm_gem_dumb_destroy(struct drm_file *file,