projects/linux·blob master · refs

319 lines · 9.4 KiB

1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef __DRM_GEM_SHMEM_HELPER_H__
4#define __DRM_GEM_SHMEM_HELPER_H__
5
6#include <linux/fs.h>
7#include <linux/mm.h>
8#include <linux/mutex.h>
9
10#include <drm/drm_file.h>
11#include <drm/drm_gem.h>
12#include <drm/drm_ioctl.h>
13#include <drm/drm_prime.h>
14
15struct dma_buf_attachment;
16struct drm_mode_create_dumb;
17struct drm_printer;
18struct sg_table;
19
20/**
21 * struct drm_gem_shmem_object - GEM object backed by shmem
22 */
23struct drm_gem_shmem_object {
24 /**
25 * @base: Base GEM object
26 */
27 struct drm_gem_object base;
28
29 /**
30 * @pages: Page table
31 */
32 struct page **pages;
33
34 /**
35 * @pages_use_count:
36 *
37 * Reference count on the pages table.
38 * The pages are put when the count reaches zero.
39 */
40 refcount_t pages_use_count;
41
42 /**
43 * @pages_pin_count:
44 *
45 * Reference count on the pinned pages table.
46 *
47 * Pages are hard-pinned and reside in memory if count
48 * greater than zero. Otherwise, when count is zero, the pages are
49 * allowed to be evicted and purged by memory shrinker.
50 */
51 refcount_t pages_pin_count;
52
53 /**
54 * @madv: State for madvise
55 *
56 * 0 is active/inuse.
57 * A negative value is the object is purged.
58 * Positive values are driver specific and not used by the helpers.
59 */
60 int madv;
61
62 /**
63 * @madv_list: List entry for madvise tracking
64 *
65 * Typically used by drivers to track purgeable objects
66 */
67 struct list_head madv_list;
68
69 /**
70 * @sgt: Scatter/gather table for imported PRIME buffers
71 */
72 struct sg_table *sgt;
73
74 /**
75 * @vaddr: Kernel virtual address of the backing memory
76 */
77 void *vaddr;
78
79 /**
80 * @vmap_use_count:
81 *
82 * Reference count on the virtual address.
83 * The address are un-mapped when the count reaches zero.
84 */
85 refcount_t vmap_use_count;
86
87 /**
88 * @pages_mark_dirty_on_put:
89 *
90 * Mark pages as dirty when they are put.
91 */
92 bool pages_mark_dirty_on_put : 1;
93
94 /**
95 * @pages_mark_accessed_on_put:
96 *
97 * Mark pages as accessed when they are put.
98 */
99 bool pages_mark_accessed_on_put : 1;
100
101 /**
102 * @map_wc: map object write-combined (instead of using shmem defaults).
103 */
104 bool map_wc : 1;
105};
106
107#define to_drm_gem_shmem_obj(obj) \
108 container_of(obj, struct drm_gem_shmem_object, base)
109
110int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size);
111struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
112void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);
113void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
114void __drm_gem_shmem_free_sgt_locked(struct drm_gem_shmem_object *shmem);
115
116void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem);
117int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem);
118void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem);
119int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem,
120 struct iosys_map *map);
121void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
122 struct iosys_map *map);
123int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct *vma);
124
125int drm_gem_shmem_pin_locked(struct drm_gem_shmem_object *shmem);
126void drm_gem_shmem_unpin_locked(struct drm_gem_shmem_object *shmem);
127
128int drm_gem_shmem_madvise_locked(struct drm_gem_shmem_object *shmem, int madv);
129
130static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem)
131{
132 return (shmem->madv > 0) &&
133 !refcount_read(&shmem->pages_pin_count) && shmem->sgt &&
134 !shmem->base.dma_buf && !drm_gem_is_imported(&shmem->base);
135}
136
137void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem);
138
139struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem);
140struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem);
141
142void drm_gem_shmem_print_info(const struct drm_gem_shmem_object *shmem,
143 struct drm_printer *p, unsigned int indent);
144
145int drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
146 struct drm_device *dev, size_t size,
147 uint32_t *handle);
148
149extern const struct vm_operations_struct drm_gem_shmem_vm_ops;
150
151/*
152 * GEM object functions
153 */
154
155/**
156 * drm_gem_shmem_object_free - GEM object function for drm_gem_shmem_free()
157 * @obj: GEM object to free
158 *
159 * This function wraps drm_gem_shmem_free(). Drivers that employ the shmem helpers
160 * should use it as their &drm_gem_object_funcs.free handler.
161 */
162static inline void drm_gem_shmem_object_free(struct drm_gem_object *obj)
163{
164 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
165
166 drm_gem_shmem_free(shmem);
167}
168
169/**
170 * drm_gem_shmem_object_print_info() - Print &drm_gem_shmem_object info for debugfs
171 * @p: DRM printer
172 * @indent: Tab indentation level
173 * @obj: GEM object
174 *
175 * This function wraps drm_gem_shmem_print_info(). Drivers that employ the shmem helpers should
176 * use this function as their &drm_gem_object_funcs.print_info handler.
177 */
178static inline void drm_gem_shmem_object_print_info(struct drm_printer *p, unsigned int indent,
179 const struct drm_gem_object *obj)
180{
181 const struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
182
183 drm_gem_shmem_print_info(shmem, p, indent);
184}
185
186/**
187 * drm_gem_shmem_object_pin - GEM object function for drm_gem_shmem_pin()
188 * @obj: GEM object
189 *
190 * This function wraps drm_gem_shmem_pin(). Drivers that employ the shmem helpers should
191 * use it as their &drm_gem_object_funcs.pin handler.
192 */
193static inline int drm_gem_shmem_object_pin(struct drm_gem_object *obj)
194{
195 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
196
197 return drm_gem_shmem_pin_locked(shmem);
198}
199
200/**
201 * drm_gem_shmem_object_unpin - GEM object function for drm_gem_shmem_unpin()
202 * @obj: GEM object
203 *
204 * This function wraps drm_gem_shmem_unpin(). Drivers that employ the shmem helpers should
205 * use it as their &drm_gem_object_funcs.unpin handler.
206 */
207static inline void drm_gem_shmem_object_unpin(struct drm_gem_object *obj)
208{
209 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
210
211 drm_gem_shmem_unpin_locked(shmem);
212}
213
214/**
215 * drm_gem_shmem_object_get_sg_table - GEM object function for drm_gem_shmem_get_sg_table()
216 * @obj: GEM object
217 *
218 * This function wraps drm_gem_shmem_get_sg_table(). Drivers that employ the shmem helpers should
219 * use it as their &drm_gem_object_funcs.get_sg_table handler.
220 *
221 * Returns:
222 * A pointer to the scatter/gather table of pinned pages or error pointer on failure.
223 */
224static inline struct sg_table *drm_gem_shmem_object_get_sg_table(struct drm_gem_object *obj)
225{
226 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
227
228 return drm_gem_shmem_get_sg_table(shmem);
229}
230
231/*
232 * drm_gem_shmem_object_vmap - GEM object function for drm_gem_shmem_vmap_locked()
233 * @obj: GEM object
234 * @map: Returns the kernel virtual address of the SHMEM GEM object's backing store.
235 *
236 * This function wraps drm_gem_shmem_vmap_locked(). Drivers that employ the shmem
237 * helpers should use it as their &drm_gem_object_funcs.vmap handler.
238 *
239 * Returns:
240 * 0 on success or a negative error code on failure.
241 */
242static inline int drm_gem_shmem_object_vmap(struct drm_gem_object *obj,
243 struct iosys_map *map)
244{
245 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
246
247 return drm_gem_shmem_vmap_locked(shmem, map);
248}
249
250/*
251 * drm_gem_shmem_object_vunmap - GEM object function for drm_gem_shmem_vunmap()
252 * @obj: GEM object
253 * @map: Kernel virtual address where the SHMEM GEM object was mapped
254 *
255 * This function wraps drm_gem_shmem_vunmap_locked(). Drivers that employ the shmem
256 * helpers should use it as their &drm_gem_object_funcs.vunmap handler.
257 */
258static inline void drm_gem_shmem_object_vunmap(struct drm_gem_object *obj,
259 struct iosys_map *map)
260{
261 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
262
263 drm_gem_shmem_vunmap_locked(shmem, map);
264}
265
266/**
267 * drm_gem_shmem_object_mmap - GEM object function for drm_gem_shmem_mmap()
268 * @obj: GEM object
269 * @vma: VMA for the area to be mapped
270 *
271 * This function wraps drm_gem_shmem_mmap(). Drivers that employ the shmem helpers should
272 * use it as their &drm_gem_object_funcs.mmap handler.
273 *
274 * Returns:
275 * 0 on success or a negative error code on failure.
276 */
277static inline int drm_gem_shmem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
278{
279 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
280
281 return drm_gem_shmem_mmap(shmem, vma);
282}
283
284/*
285 * Driver ops
286 */
287
288struct drm_gem_object *
289drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
290 struct dma_buf_attachment *attach,
291 struct sg_table *sgt);
292int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev,
293 struct drm_mode_create_dumb *args);
294struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev,
295 struct dma_buf *buf);
296
297/**
298 * DRM_GEM_SHMEM_DRIVER_OPS - Default shmem GEM operations
299 *
300 * This macro provides a shortcut for setting the shmem GEM operations
301 * in the &drm_driver structure. Drivers that do not require an s/g table
302 * for imported buffers should use this.
303 */
304#define DRM_GEM_SHMEM_DRIVER_OPS \
305 .gem_prime_import = drm_gem_shmem_prime_import_no_map, \
306 .dumb_create = drm_gem_shmem_dumb_create
307
308/*
309 * Kunit helpers
310 */
311
312#if IS_ENABLED(CONFIG_KUNIT)
313int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem, struct iosys_map *map);
314void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem, struct iosys_map *map);
315int drm_gem_shmem_madvise(struct drm_gem_shmem_object *shmem, int madv);
316int drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem);
317#endif
318
319#endif /* __DRM_GEM_SHMEM_HELPER_H__ */