Am 10.06.21 um 23:09 schrieb Jason Ekstrand:
Add a helper function to get a single fence representing all fences in a dma_resv object.
This fence is either the only one in the object or all not signaled fences of the object in a flatted out dma_fence_array.
v2 (Jason Ekstrand):
- Take reference of fences both for creating the dma_fence_array and in the case where we return one fence.
- Handle the case where dma_resv_get_list() returns NULL
v3 (Jason Ekstrand):
- Add an _rcu suffix because it is read-only
- Rewrite to use dma_resv_get_fences_rcu so it's RCU-safe
- Add an EXPORT_SYMBOL_GPL declaration
- Re-author the patch to Jason since very little is left of Christian König's original patch
- Remove the extra fence argument
v4 (Jason Ekstrand):
- Restore the extra fence argument
v5 (Daniel Vetter):
- Rename from _rcu to _unlocked since it doesn't leak RCU details to the caller
- Fix docs
- Use ERR_PTR for error handling rather than an output dma_fence**
v5 (Jason Ekstrand):
- Drop the extra fence param and leave that to a separate patch
v6 (Jason Ekstrand):
- Rename to dma_resv_get_singleton to match the new naming convention for dma_resv helpers which work without taking a lock.
Signed-off-by: Jason Ekstrand jason@jlekstrand.net Reviewed-by: Daniel Vetter daniel.vetter@ffwll.ch
Reviewed-by: Christian König christian.koenig@amd.com
Cc: Christian König christian.koenig@amd.com Cc: Maarten Lankhorst maarten.lankhorst@linux.intel.com
drivers/dma-buf/dma-resv.c | 91 ++++++++++++++++++++++++++++++++++++++ include/linux/dma-resv.h | 1 + 2 files changed, 92 insertions(+)
diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index f26c71747d43a..1b26aa7e5d81c 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -34,6 +34,8 @@ */
#include <linux/dma-resv.h> +#include <linux/dma-fence-chain.h> +#include <linux/dma-fence-array.h> #include <linux/export.h> #include <linux/mm.h> #include <linux/sched/mm.h> @@ -50,6 +52,10 @@
- write-side updates.
*/
+#define dma_fence_deep_dive_for_each(fence, chain, index, head) \
- dma_fence_chain_for_each(chain, head) \
dma_fence_array_for_each(fence, index, chain)
- DEFINE_WD_CLASS(reservation_ww_class); EXPORT_SYMBOL(reservation_ww_class);
@@ -495,6 +501,91 @@ int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **pfence_excl, } EXPORT_SYMBOL_GPL(dma_resv_get_fences);
+/**
- dma_resv_get_singleton - get a single fence for the dma_resv object
- @obj: the reservation object
- Get a single fence representing all unsignaled fences in the dma_resv object
- plus the given extra fence. If we got only one fence return a new
- reference to that, otherwise return a dma_fence_array object.
- RETURNS
- The singleton dma_fence on success or an ERR_PTR on failure
- */
+struct dma_fence *dma_resv_get_singleton(struct dma_resv *obj) +{
- struct dma_fence *result, **resv_fences, *fence, *chain, **fences;
- struct dma_fence_array *array;
- unsigned int num_resv_fences, num_fences;
- unsigned int err, i, j;
- err = dma_resv_get_fences(obj, NULL, &num_resv_fences, &resv_fences);
- if (err)
return ERR_PTR(err);
- if (num_resv_fences == 0)
return NULL;
- num_fences = 0;
- result = NULL;
- for (i = 0; i < num_resv_fences; ++i) {
dma_fence_deep_dive_for_each(fence, chain, j, resv_fences[i]) {
if (dma_fence_is_signaled(fence))
continue;
result = fence;
++num_fences;
}
- }
- if (num_fences <= 1) {
result = dma_fence_get(result);
goto put_resv_fences;
- }
- fences = kmalloc_array(num_fences, sizeof(struct dma_fence *),
GFP_KERNEL);
- if (!fences) {
result = ERR_PTR(-ENOMEM);
goto put_resv_fences;
- }
- num_fences = 0;
- for (i = 0; i < num_resv_fences; ++i) {
dma_fence_deep_dive_for_each(fence, chain, j, resv_fences[i]) {
if (!dma_fence_is_signaled(fence))
fences[num_fences++] = dma_fence_get(fence);
}
- }
- if (num_fences <= 1) {
result = num_fences ? fences[0] : NULL;
kfree(fences);
goto put_resv_fences;
- }
- array = dma_fence_array_create(num_fences, fences,
dma_fence_context_alloc(1),
1, false);
- if (array) {
result = &array->base;
- } else {
result = ERR_PTR(-ENOMEM);
while (num_fences--)
dma_fence_put(fences[num_fences]);
kfree(fences);
- }
+put_resv_fences:
- while (num_resv_fences--)
dma_fence_put(resv_fences[num_resv_fences]);
- kfree(resv_fences);
- return result;
+} +EXPORT_SYMBOL_GPL(dma_resv_get_singleton);
- /**
- dma_resv_wait_timeout - Wait on reservation's objects
- shared and/or exclusive fences.
diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 562b885cf9c3d..d60982975a786 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -275,6 +275,7 @@ void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence); int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **pfence_excl, unsigned *pshared_count, struct dma_fence ***pshared); int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src); +struct dma_fence *dma_resv_get_singleton(struct dma_resv *obj); long dma_resv_wait_timeout(struct dma_resv *obj, bool wait_all, bool intr, unsigned long timeout); bool dma_resv_test_signaled(struct dma_resv *obj, bool test_all);