aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2019-04-01 18:26:33 -0400
committerEric Anholt <eric@anholt.net>2019-04-16 18:32:20 -0400
commit5d5a179d3e90a8385b115e4bd19826ea0bcc6d11 (patch)
tree498a12878d4de2308f1cc88f23ffeb4a509f8a51
parentc8f005684c98f4d9942baec13ad98054dbf312a0 (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.c93
-rw-r--r--include/drm/drm_gem.h5
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}
1369EXPORT_SYMBOL(drm_gem_unlock_reservations); 1369EXPORT_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 */
1381int 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}
1415EXPORT_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 */
1431int 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}
1462EXPORT_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);
391void drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, 391void 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);
393int drm_gem_fence_array_add(struct xarray *fence_array,
394 struct dma_fence *fence);
395int drm_gem_fence_array_add_implicit(struct xarray *fence_array,
396 struct drm_gem_object *obj,
397 bool write);
393int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev, 398int drm_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
394 u32 handle, u64 *offset); 399 u32 handle, u64 *offset);
395int drm_gem_dumb_destroy(struct drm_file *file, 400int drm_gem_dumb_destroy(struct drm_file *file,