| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright (C) 2022 Advanced Micro Devices, Inc. | 
|---|
| 4 | * Authors: | 
|---|
| 5 | *	Christian König <christian.koenig@amd.com> | 
|---|
| 6 | */ | 
|---|
| 7 |  | 
|---|
| 8 | #ifndef __LINUX_DMA_FENCE_UNWRAP_H | 
|---|
| 9 | #define __LINUX_DMA_FENCE_UNWRAP_H | 
|---|
| 10 |  | 
|---|
| 11 | struct dma_fence; | 
|---|
| 12 |  | 
|---|
| 13 | /** | 
|---|
| 14 | * struct dma_fence_unwrap - cursor into the container structure | 
|---|
| 15 | * | 
|---|
| 16 | * Should be used with dma_fence_unwrap_for_each() iterator macro. | 
|---|
| 17 | */ | 
|---|
| 18 | struct dma_fence_unwrap { | 
|---|
| 19 | /** | 
|---|
| 20 | * @chain: potential dma_fence_chain, but can be other fence as well | 
|---|
| 21 | */ | 
|---|
| 22 | struct dma_fence *chain; | 
|---|
| 23 | /** | 
|---|
| 24 | * @array: potential dma_fence_array, but can be other fence as well | 
|---|
| 25 | */ | 
|---|
| 26 | struct dma_fence *array; | 
|---|
| 27 | /** | 
|---|
| 28 | * @index: last returned index if @array is really a dma_fence_array | 
|---|
| 29 | */ | 
|---|
| 30 | unsigned int index; | 
|---|
| 31 | }; | 
|---|
| 32 |  | 
|---|
| 33 | struct dma_fence *dma_fence_unwrap_first(struct dma_fence *head, | 
|---|
| 34 | struct dma_fence_unwrap *cursor); | 
|---|
| 35 | struct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor); | 
|---|
| 36 |  | 
|---|
| 37 | /** | 
|---|
| 38 | * dma_fence_unwrap_for_each - iterate over all fences in containers | 
|---|
| 39 | * @fence: current fence | 
|---|
| 40 | * @cursor: current position inside the containers | 
|---|
| 41 | * @head: starting point for the iterator | 
|---|
| 42 | * | 
|---|
| 43 | * Unwrap dma_fence_chain and dma_fence_array containers and deep dive into all | 
|---|
| 44 | * potential fences in them. If @head is just a normal fence only that one is | 
|---|
| 45 | * returned. | 
|---|
| 46 | */ | 
|---|
| 47 | #define dma_fence_unwrap_for_each(fence, cursor, head)			\ | 
|---|
| 48 | for (fence = dma_fence_unwrap_first(head, cursor); fence;	\ | 
|---|
| 49 | fence = dma_fence_unwrap_next(cursor)) | 
|---|
| 50 |  | 
|---|
| 51 | struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences, | 
|---|
| 52 | struct dma_fence **fences, | 
|---|
| 53 | struct dma_fence_unwrap *cursors); | 
|---|
| 54 |  | 
|---|
| 55 | int dma_fence_dedup_array(struct dma_fence **array, int num_fences); | 
|---|
| 56 |  | 
|---|
| 57 | /** | 
|---|
| 58 | * dma_fence_unwrap_merge - unwrap and merge fences | 
|---|
| 59 | * | 
|---|
| 60 | * All fences given as parameters are unwrapped and merged back together as flat | 
|---|
| 61 | * dma_fence_array. Useful if multiple containers need to be merged together. | 
|---|
| 62 | * | 
|---|
| 63 | * Implemented as a macro to allocate the necessary arrays on the stack and | 
|---|
| 64 | * account the stack frame size to the caller. | 
|---|
| 65 | * | 
|---|
| 66 | * Returns NULL on memory allocation failure, a dma_fence object representing | 
|---|
| 67 | * all the given fences otherwise. | 
|---|
| 68 | */ | 
|---|
| 69 | #define dma_fence_unwrap_merge(...)					\ | 
|---|
| 70 | ({								\ | 
|---|
| 71 | struct dma_fence *__f[] = { __VA_ARGS__ };		\ | 
|---|
| 72 | struct dma_fence_unwrap __c[ARRAY_SIZE(__f)];		\ | 
|---|
| 73 | \ | 
|---|
| 74 | __dma_fence_unwrap_merge(ARRAY_SIZE(__f), __f, __c);	\ | 
|---|
| 75 | }) | 
|---|
| 76 |  | 
|---|
| 77 | #endif | 
|---|
| 78 |  | 
|---|