1151497Sru/* SPDX-License-Identifier: GPL-2.0-only */
2104862Sru/*
3151497Sru * Copyright (C) 2022 Advanced Micro Devices, Inc.
4104862Sru * Authors:
5151497Sru *	Christian K��nig <christian.koenig@amd.com>
6151497Sru */
7104862Sru
8104862Sru#ifndef __LINUX_DMA_FENCE_UNWRAP_H
9104862Sru#define __LINUX_DMA_FENCE_UNWRAP_H
10104862Sru
11104862Srustruct dma_fence;
12104862Sru
13104862Sru/**
14104862Sru * struct dma_fence_unwrap - cursor into the container structure
15104862Sru *
16104862Sru * Should be used with dma_fence_unwrap_for_each() iterator macro.
17104862Sru */
18104862Srustruct dma_fence_unwrap {
19151497Sru	/**
20114402Sru	 * @chain: potential dma_fence_chain, but can be other fence as well
21104862Sru	 */
22104862Sru	struct dma_fence *chain;
23104862Sru	/**
24104862Sru	 * @array: potential dma_fence_array, but can be other fence as well
25104862Sru	 */
26104862Sru	struct dma_fence *array;
27104862Sru	/**
28104862Sru	 * @index: last returned index if @array is really a dma_fence_array
29104862Sru	 */
30104862Sru	unsigned int index;
31151497Sru};
32104862Sru
33151497Srustruct dma_fence *dma_fence_unwrap_first(struct dma_fence *head,
34151497Sru					 struct dma_fence_unwrap *cursor);
35104862Srustruct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor);
36104862Sru
37104862Sru/**
38104862Sru * dma_fence_unwrap_for_each - iterate over all fences in containers
39104862Sru * @fence: current fence
40104862Sru * @cursor: current position inside the containers
41104862Sru * @head: starting point for the iterator
42104862Sru *
43104862Sru * Unwrap dma_fence_chain and dma_fence_array containers and deep dive into all
44104862Sru * potential fences in them. If @head is just a normal fence only that one is
45104862Sru * returned.
46104862Sru */
47151497Sru#define dma_fence_unwrap_for_each(fence, cursor, head)			\
48104862Sru	for (fence = dma_fence_unwrap_first(head, cursor); fence;	\
49104862Sru	     fence = dma_fence_unwrap_next(cursor))
50104862Sru
51104862Srustruct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
52104862Sru					   struct dma_fence **fences,
53104862Sru					   struct dma_fence_unwrap *cursors);
54104862Sru
55104862Sru/**
56104862Sru * dma_fence_unwrap_merge - unwrap and merge fences
57104862Sru *
58104862Sru * All fences given as parameters are unwrapped and merged back together as flat
59104862Sru * dma_fence_array. Useful if multiple containers need to be merged together.
60104862Sru *
61104862Sru * Implemented as a macro to allocate the necessary arrays on the stack and
62104862Sru * account the stack frame size to the caller.
63104862Sru *
64104862Sru * Returns NULL on memory allocation failure, a dma_fence object representing
65104862Sru * all the given fences otherwise.
66104862Sru */
67104862Sru#define dma_fence_unwrap_merge(...)					\
68104862Sru	({								\
69104862Sru		struct dma_fence *__f[] = { __VA_ARGS__ };		\
70104862Sru		struct dma_fence_unwrap __c[ARRAY_SIZE(__f)];		\
71104862Sru									\
72104862Sru		__dma_fence_unwrap_merge(ARRAY_SIZE(__f), __f, __c);	\
73104862Sru	})
74151497Sru
75151497Sru#endif
76104862Sru