1 /*        $NetBSD: dma-resv.h,v 1.10 2021/12/19 12:21:30 riastradh Exp $        */
2 
3 /*-
4  * Copyright (c) 2018 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Taylor R. Campbell.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef   _LINUX_DMA_RESV_H_
33 #define   _LINUX_DMA_RESV_H_
34 
35 #include <linux/dma-fence.h>
36 #include <linux/rcupdate.h>
37 #include <linux/seqlock.h>
38 #include <linux/ww_mutex.h>
39 
40 struct dma_resv {
41           struct ww_mutex                                   lock;
42           struct seqcount                                   seq;
43           struct dma_fence __rcu                            *fence_excl;
44           struct dma_resv_list __rcu              *fence;
45 
46           struct dma_resv_list __rcu              *robj_prealloc;
47 };
48 
49 struct dma_resv_list {
50           struct rcu_head               rol_rcu;
51 
52           uint32_t            shared_count;
53           uint32_t            shared_max;
54           struct dma_fence __rcu        *shared[];
55 };
56 
57 /* NetBSD addition */
58 struct dma_resv_poll {
59           kmutex_t            rp_lock;
60           struct selinfo                rp_selq;
61           struct dma_fence_cb           rp_fcb;
62           bool                          rp_claimed;
63 };
64 
65 #define   dma_resv_add_excl_fence                 linux_dma_resv_add_excl_fence
66 #define   dma_resv_add_shared_fence     linux_dma_resv_add_shared_fence
67 #define   dma_resv_assert_held                    linux_dma_resv_assert_held
68 #define   dma_resv_copy_fences                    linux_dma_resv_copy_fences
69 #define   dma_resv_do_poll              linux_dma_resv_do_poll
70 #define   dma_resv_fini                           linux_dma_resv_fini
71 #define   dma_resv_get_excl             linux_dma_resv_get_excl
72 #define   dma_resv_get_excl_rcu                   linux_dma_resv_get_excl_rcu
73 #define   dma_resv_get_fences_rcu                 linux_dma_resv_get_fences_rcu
74 #define   dma_resv_get_list             linux_dma_resv_get_list
75 #define   dma_resv_held                           linux_dma_resv_held
76 #define   dma_resv_init                           linux_dma_resv_init
77 #define   dma_resv_is_locked            linux_dma_resv_is_locked
78 #define   dma_resv_kqfilter             linux_dma_resv_kqfilter
79 #define   dma_resv_lock                           linux_dma_resv_lock
80 #define   dma_resv_lock_interruptible   linux_dma_resv_lock_interruptible
81 #define   dma_resv_lock_slow            linux_dma_resv_lock_slow
82 #define   dma_resv_lock_slow_interruptible linux_dma_resv_lock_slow_interruptible
83 #define   dma_resv_locking_ctx                    linux_dma_resv_locking_ctx
84 #define   dma_resv_reserve_shared                 linux_dma_resv_reserve_shared
85 #define   dma_resv_test_signaled_rcu    linux_dma_resv_test_signaled_rcu
86 #define   dma_resv_trylock              linux_dma_resv_trylock
87 #define   dma_resv_unlock                         linux_dma_resv_unlock
88 #define   dma_resv_wait_timeout_rcu     linux_dma_resv_wait_timeout_rcu
89 #define   dma_resv_poll_fini            linux_dma_resv_poll_fini
90 #define   dma_resv_poll_init            linux_dma_resv_poll_init
91 #define   reservation_ww_class                    linux_reservation_ww_class
92 
93 extern struct ww_class        reservation_ww_class;
94 
95 void      dma_resv_init(struct dma_resv *);
96 void      dma_resv_fini(struct dma_resv *);
97 int       dma_resv_lock(struct dma_resv *,
98               struct ww_acquire_ctx *);
99 void      dma_resv_lock_slow(struct dma_resv *,
100               struct ww_acquire_ctx *);
101 int       dma_resv_lock_interruptible(struct dma_resv *,
102               struct ww_acquire_ctx *);
103 int       dma_resv_lock_slow_interruptible(struct dma_resv *,
104               struct ww_acquire_ctx *);
105 bool      dma_resv_trylock(struct dma_resv *) __must_check;
106 struct ww_acquire_ctx *
107           dma_resv_locking_ctx(struct dma_resv *);
108 void      dma_resv_unlock(struct dma_resv *);
109 bool      dma_resv_is_locked(struct dma_resv *);
110 bool      dma_resv_held(struct dma_resv *);
111 void      dma_resv_assert_held(struct dma_resv *);
112 struct dma_fence *
113           dma_resv_get_excl(struct dma_resv *);
114 struct dma_resv_list *
115           dma_resv_get_list(struct dma_resv *);
116 int       dma_resv_reserve_shared(struct dma_resv *, unsigned int);
117 void      dma_resv_add_excl_fence(struct dma_resv *,
118               struct dma_fence *);
119 void      dma_resv_add_shared_fence(struct dma_resv *,
120               struct dma_fence *);
121 
122 struct dma_fence *
123           dma_resv_get_excl_rcu(const struct dma_resv *);
124 int       dma_resv_get_fences_rcu(const struct dma_resv *,
125               struct dma_fence **, unsigned *, struct dma_fence ***);
126 
127 int       dma_resv_copy_fences(struct dma_resv *,
128               const struct dma_resv *);
129 
130 bool      dma_resv_test_signaled_rcu(const struct dma_resv *,
131               bool);
132 long      dma_resv_wait_timeout_rcu(const struct dma_resv *,
133               bool, bool, unsigned long);
134 
135 /* NetBSD additions */
136 void      dma_resv_poll_init(struct dma_resv_poll *);
137 void      dma_resv_poll_fini(struct dma_resv_poll *);
138 int       dma_resv_do_poll(const struct dma_resv *, int,
139               struct dma_resv_poll *);
140 int       dma_resv_kqfilter(const struct dma_resv *,
141               struct knote *, struct dma_resv_poll *);
142 
143 static inline bool
dma_resv_has_excl_fence(const struct dma_resv * robj)144 dma_resv_has_excl_fence(const struct dma_resv *robj)
145 {
146           return robj->fence_excl != NULL;
147 }
148 
149 #endif    /* _LINUX_DMA_RESV_H_ */
150