diff options
author | Eric Anholt <eric@anholt.net> | 2019-04-01 18:26:33 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2019-04-16 18:32:20 -0400 |
commit | 5d5a179d3e90a8385b115e4bd19826ea0bcc6d11 (patch) | |
tree | 498a12878d4de2308f1cc88f23ffeb4a509f8a51 | |
parent | c8f005684c98f4d9942baec13ad98054dbf312a0 (diff) |
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)
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 93 | ||||
-rw-r--r-- | include/drm/drm_gem.h | 5 |
2 files changed, 98 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index e93043b64c2d..fae4676707b6 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -1367,3 +1367,96 @@ drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, | |||
1367 | ww_acquire_fini(acquire_ctx); | 1367 | ww_acquire_fini(acquire_ctx); |
1368 | } | 1368 | } |
1369 | EXPORT_SYMBOL(drm_gem_unlock_reservations); | 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); | ||
diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index 5ee85c9eaa9d..5047c7ee25f5 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h | |||
@@ -390,6 +390,11 @@ int drm_gem_lock_reservations(struct drm_gem_object **objs, int count, | |||
390 | struct ww_acquire_ctx *acquire_ctx); | 390 | struct ww_acquire_ctx *acquire_ctx); |
391 | void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, | 391 | void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, |
392 | struct ww_acquire_ctx *acquire_ctx); | 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 | int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, | 398 | int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, |
394 | u32 handle, u64 *offset); | 399 | u32 handle, u64 *offset); |
395 | int drm_gem_dumb_destroy(struct drm_file *file, | 400 | int drm_gem_dumb_destroy(struct drm_file *file, |