drm: Add drm_gem_vram_fill_create_dumb() to create dumb buffers
[linux-2.6-block.git] / drivers / gpu / drm / drm_gem_vram_helper.c
CommitLineData
85438a8d
TZ
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <drm/drm_gem_vram_helper.h>
fed1eec0 4#include <drm/drm_mode.h>
85438a8d
TZ
5#include <drm/ttm/ttm_page_alloc.h>
6
7/**
8 * DOC: overview
9 *
10 * This library provides a GEM buffer object that is backed by video RAM
11 * (VRAM). It can be used for framebuffer devices with dedicated memory.
12 */
13
14/*
15 * Buffer-objects helpers
16 */
17
18static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo)
19{
20 /* We got here via ttm_bo_put(), which means that the
21 * TTM buffer object in 'bo' has already been cleaned
22 * up; only release the GEM object.
23 */
24 drm_gem_object_release(&gbo->gem);
25}
26
27static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo)
28{
29 drm_gem_vram_cleanup(gbo);
30 kfree(gbo);
31}
32
33static void ttm_buffer_object_destroy(struct ttm_buffer_object *bo)
34{
35 struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
36
37 drm_gem_vram_destroy(gbo);
38}
39
40static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
41 unsigned long pl_flag)
42{
43 unsigned int i;
44 unsigned int c = 0;
45
46 gbo->placement.placement = gbo->placements;
47 gbo->placement.busy_placement = gbo->placements;
48
49 if (pl_flag & TTM_PL_FLAG_VRAM)
50 gbo->placements[c++].flags = TTM_PL_FLAG_WC |
51 TTM_PL_FLAG_UNCACHED |
52 TTM_PL_FLAG_VRAM;
53
54 if (pl_flag & TTM_PL_FLAG_SYSTEM)
55 gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
56 TTM_PL_FLAG_SYSTEM;
57
58 if (!c)
59 gbo->placements[c++].flags = TTM_PL_MASK_CACHING |
60 TTM_PL_FLAG_SYSTEM;
61
62 gbo->placement.num_placement = c;
63 gbo->placement.num_busy_placement = c;
64
65 for (i = 0; i < c; ++i) {
66 gbo->placements[i].fpfn = 0;
67 gbo->placements[i].lpfn = 0;
68 }
69}
70
71static int drm_gem_vram_init(struct drm_device *dev,
72 struct ttm_bo_device *bdev,
73 struct drm_gem_vram_object *gbo,
74 size_t size, unsigned long pg_align,
75 bool interruptible)
76{
77 int ret;
78 size_t acc_size;
79
80 ret = drm_gem_object_init(dev, &gbo->gem, size);
81 if (ret)
82 return ret;
83
84 acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo));
85
86 gbo->bo.bdev = bdev;
87 drm_gem_vram_placement(gbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
88
89 ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device,
90 &gbo->placement, pg_align, interruptible, acc_size,
91 NULL, NULL, ttm_buffer_object_destroy);
92 if (ret)
93 goto err_drm_gem_object_release;
94
95 return 0;
96
97err_drm_gem_object_release:
98 drm_gem_object_release(&gbo->gem);
99 return ret;
100}
101
102/**
103 * drm_gem_vram_create() - Creates a VRAM-backed GEM object
104 * @dev: the DRM device
105 * @bdev: the TTM BO device backing the object
106 * @size: the buffer size in bytes
107 * @pg_align: the buffer's alignment in multiples of the page size
108 * @interruptible: sleep interruptible if waiting for memory
109 *
110 * Returns:
111 * A new instance of &struct drm_gem_vram_object on success, or
112 * an ERR_PTR()-encoded error code otherwise.
113 */
114struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
115 struct ttm_bo_device *bdev,
116 size_t size,
117 unsigned long pg_align,
118 bool interruptible)
119{
120 struct drm_gem_vram_object *gbo;
121 int ret;
122
123 gbo = kzalloc(sizeof(*gbo), GFP_KERNEL);
124 if (!gbo)
125 return ERR_PTR(-ENOMEM);
126
127 ret = drm_gem_vram_init(dev, bdev, gbo, size, pg_align, interruptible);
128 if (ret < 0)
129 goto err_kfree;
130
131 return gbo;
132
133err_kfree:
134 kfree(gbo);
135 return ERR_PTR(ret);
136}
137EXPORT_SYMBOL(drm_gem_vram_create);
138
139/**
140 * drm_gem_vram_put() - Releases a reference to a VRAM-backed GEM object
141 * @gbo: the GEM VRAM object
142 *
143 * See ttm_bo_put() for more information.
144 */
145void drm_gem_vram_put(struct drm_gem_vram_object *gbo)
146{
147 ttm_bo_put(&gbo->bo);
148}
149EXPORT_SYMBOL(drm_gem_vram_put);
150
151/**
152 * drm_gem_vram_reserve() - Reserves a VRAM-backed GEM object
153 * @gbo: the GEM VRAM object
154 * @no_wait: don't wait for buffer object to become available
155 *
156 * See ttm_bo_reserve() for more information.
157 *
158 * Returns:
159 * 0 on success, or
160 * a negative error code otherwise
161 */
162int drm_gem_vram_reserve(struct drm_gem_vram_object *gbo, bool no_wait)
163{
164 return ttm_bo_reserve(&gbo->bo, true, no_wait, NULL);
165}
166EXPORT_SYMBOL(drm_gem_vram_reserve);
167
168/**
169 * drm_gem_vram_unreserve() - \
170 Release a reservation acquired by drm_gem_vram_reserve()
171 * @gbo: the GEM VRAM object
172 *
173 * See ttm_bo_unreserve() for more information.
174 */
175void drm_gem_vram_unreserve(struct drm_gem_vram_object *gbo)
176{
177 ttm_bo_unreserve(&gbo->bo);
178}
179EXPORT_SYMBOL(drm_gem_vram_unreserve);
180
181/**
182 * drm_gem_vram_mmap_offset() - Returns a GEM VRAM object's mmap offset
183 * @gbo: the GEM VRAM object
184 *
185 * See drm_vma_node_offset_addr() for more information.
186 *
187 * Returns:
188 * The buffer object's offset for userspace mappings on success, or
189 * 0 if no offset is allocated.
190 */
191u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo)
192{
193 return drm_vma_node_offset_addr(&gbo->bo.vma_node);
194}
195EXPORT_SYMBOL(drm_gem_vram_mmap_offset);
196
197/**
198 * drm_gem_vram_offset() - \
199 Returns a GEM VRAM object's offset in video memory
200 * @gbo: the GEM VRAM object
201 *
202 * This function returns the buffer object's offset in the device's video
203 * memory. The buffer object has to be pinned to %TTM_PL_VRAM.
204 *
205 * Returns:
206 * The buffer object's offset in video memory on success, or
207 * a negative errno code otherwise.
208 */
209s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo)
210{
211 if (WARN_ON_ONCE(!gbo->pin_count))
212 return (s64)-ENODEV;
213 return gbo->bo.offset;
214}
215EXPORT_SYMBOL(drm_gem_vram_offset);
216
217/**
218 * drm_gem_vram_pin() - Pins a GEM VRAM object in a region.
219 * @gbo: the GEM VRAM object
220 * @pl_flag: a bitmask of possible memory regions
221 *
222 * Pinning a buffer object ensures that it is not evicted from
223 * a memory region. A pinned buffer object has to be unpinned before
224 * it can be pinned to another region.
225 *
226 * Returns:
227 * 0 on success, or
228 * a negative error code otherwise.
229 */
230int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag)
231{
232 int i, ret;
233 struct ttm_operation_ctx ctx = { false, false };
234
235 if (gbo->pin_count) {
236 ++gbo->pin_count;
237 return 0;
238 }
239
240 drm_gem_vram_placement(gbo, pl_flag);
241 for (i = 0; i < gbo->placement.num_placement; ++i)
242 gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
243
244 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
245 if (ret < 0)
246 return ret;
247
248 gbo->pin_count = 1;
249
250 return 0;
251}
252EXPORT_SYMBOL(drm_gem_vram_pin);
253
254/**
255 * drm_gem_vram_unpin() - Unpins a GEM VRAM object
256 * @gbo: the GEM VRAM object
257 *
258 * Returns:
259 * 0 on success, or
260 * a negative error code otherwise.
261 */
262int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)
263{
264 int i, ret;
265 struct ttm_operation_ctx ctx = { false, false };
266
267 if (WARN_ON_ONCE(!gbo->pin_count))
268 return 0;
269
270 --gbo->pin_count;
271 if (gbo->pin_count)
272 return 0;
273
274 for (i = 0; i < gbo->placement.num_placement ; ++i)
275 gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
276
277 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
278 if (ret < 0)
279 return ret;
280
281 return 0;
282}
283EXPORT_SYMBOL(drm_gem_vram_unpin);
284
285/**
286 * drm_gem_vram_push_to_system() - \
287 Unpins a GEM VRAM object and moves it to system memory
288 * @gbo: the GEM VRAM object
289 *
290 * This operation only works if the caller holds the final pin on the
291 * buffer object.
292 *
293 * Returns:
294 * 0 on success, or
295 * a negative error code otherwise.
296 */
297int drm_gem_vram_push_to_system(struct drm_gem_vram_object *gbo)
298{
299 int i, ret;
300 struct ttm_operation_ctx ctx = { false, false };
301
302 if (WARN_ON_ONCE(!gbo->pin_count))
303 return 0;
304
305 --gbo->pin_count;
306 if (gbo->pin_count)
307 return 0;
308
309 if (gbo->kmap.virtual)
310 ttm_bo_kunmap(&gbo->kmap);
311
312 drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM);
313 for (i = 0; i < gbo->placement.num_placement ; ++i)
314 gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
315
316 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
317 if (ret)
318 return ret;
319
320 return 0;
321}
322EXPORT_SYMBOL(drm_gem_vram_push_to_system);
323
324/**
325 * drm_gem_vram_kmap_at() - Maps a GEM VRAM object into kernel address space
326 * @gbo: the GEM VRAM object
327 * @map: establish a mapping if necessary
328 * @is_iomem: returns true if the mapped memory is I/O memory, or false \
329 otherwise; can be NULL
330 * @kmap: the mapping's kmap object
331 *
332 * This function maps the buffer object into the kernel's address space
333 * or returns the current mapping. If the parameter map is false, the
334 * function only queries the current mapping, but does not establish a
335 * new one.
336 *
337 * Returns:
338 * The buffers virtual address if mapped, or
339 * NULL if not mapped, or
340 * an ERR_PTR()-encoded error code otherwise.
341 */
342void *drm_gem_vram_kmap_at(struct drm_gem_vram_object *gbo, bool map,
343 bool *is_iomem, struct ttm_bo_kmap_obj *kmap)
344{
345 int ret;
346
347 if (kmap->virtual || !map)
348 goto out;
349
350 ret = ttm_bo_kmap(&gbo->bo, 0, gbo->bo.num_pages, kmap);
351 if (ret)
352 return ERR_PTR(ret);
353
354out:
355 if (!is_iomem)
356 return kmap->virtual;
357 if (!kmap->virtual) {
358 *is_iomem = false;
359 return NULL;
360 }
361 return ttm_kmap_obj_virtual(kmap, is_iomem);
362}
363EXPORT_SYMBOL(drm_gem_vram_kmap_at);
364
365/**
366 * drm_gem_vram_kmap() - Maps a GEM VRAM object into kernel address space
367 * @gbo: the GEM VRAM object
368 * @map: establish a mapping if necessary
369 * @is_iomem: returns true if the mapped memory is I/O memory, or false \
370 otherwise; can be NULL
371 *
372 * This function maps the buffer object into the kernel's address space
373 * or returns the current mapping. If the parameter map is false, the
374 * function only queries the current mapping, but does not establish a
375 * new one.
376 *
377 * Returns:
378 * The buffers virtual address if mapped, or
379 * NULL if not mapped, or
380 * an ERR_PTR()-encoded error code otherwise.
381 */
382void *drm_gem_vram_kmap(struct drm_gem_vram_object *gbo, bool map,
383 bool *is_iomem)
384{
385 return drm_gem_vram_kmap_at(gbo, map, is_iomem, &gbo->kmap);
386}
387EXPORT_SYMBOL(drm_gem_vram_kmap);
388
389/**
390 * drm_gem_vram_kunmap_at() - Unmaps a GEM VRAM object
391 * @gbo: the GEM VRAM object
392 * @kmap: the mapping's kmap object
393 */
394void drm_gem_vram_kunmap_at(struct drm_gem_vram_object *gbo,
395 struct ttm_bo_kmap_obj *kmap)
396{
397 if (!kmap->virtual)
398 return;
399
400 ttm_bo_kunmap(kmap);
401 kmap->virtual = NULL;
402}
403EXPORT_SYMBOL(drm_gem_vram_kunmap_at);
404
405/**
406 * drm_gem_vram_kunmap() - Unmaps a GEM VRAM object
407 * @gbo: the GEM VRAM object
408 */
409void drm_gem_vram_kunmap(struct drm_gem_vram_object *gbo)
410{
411 drm_gem_vram_kunmap_at(gbo, &gbo->kmap);
412}
413EXPORT_SYMBOL(drm_gem_vram_kunmap);
6c812bc5 414
fed1eec0
TZ
415/**
416 * drm_gem_vram_fill_create_dumb() - \
417 Helper for implementing &struct drm_driver.dumb_create
418 * @file: the DRM file
419 * @dev: the DRM device
420 * @bdev: the TTM BO device managing the buffer object
421 * @pg_align: the buffer's alignment in multiples of the page size
422 * @interruptible: sleep interruptible if waiting for memory
423 * @args: the arguments as provided to \
424 &struct drm_driver.dumb_create
425 *
426 * This helper function fills &struct drm_mode_create_dumb, which is used
427 * by &struct drm_driver.dumb_create. Implementations of this interface
428 * should forwards their arguments to this helper, plus the driver-specific
429 * parameters.
430 *
431 * Returns:
432 * 0 on success, or
433 * a negative error code otherwise.
434 */
435int drm_gem_vram_fill_create_dumb(struct drm_file *file,
436 struct drm_device *dev,
437 struct ttm_bo_device *bdev,
438 unsigned long pg_align,
439 bool interruptible,
440 struct drm_mode_create_dumb *args)
441{
442 size_t pitch, size;
443 struct drm_gem_vram_object *gbo;
444 int ret;
445 u32 handle;
446
447 pitch = args->width * ((args->bpp + 7) / 8);
448 size = pitch * args->height;
449
450 size = roundup(size, PAGE_SIZE);
451 if (!size)
452 return -EINVAL;
453
454 gbo = drm_gem_vram_create(dev, bdev, size, pg_align, interruptible);
455 if (IS_ERR(gbo))
456 return PTR_ERR(gbo);
457
458 ret = drm_gem_handle_create(file, &gbo->gem, &handle);
459 if (ret)
460 goto err_drm_gem_object_put_unlocked;
461
462 drm_gem_object_put_unlocked(&gbo->gem);
463
464 args->pitch = pitch;
465 args->size = size;
466 args->handle = handle;
467
468 return 0;
469
470err_drm_gem_object_put_unlocked:
471 drm_gem_object_put_unlocked(&gbo->gem);
472 return ret;
473}
474EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
475
6c812bc5
TZ
476/*
477 * Helpers for struct ttm_bo_driver
478 */
479
480static bool drm_is_gem_vram(struct ttm_buffer_object *bo)
481{
482 return (bo->destroy == ttm_buffer_object_destroy);
483}
484
485/**
486 * drm_gem_vram_bo_driver_evict_flags() - \
487 Implements &struct ttm_bo_driver.evict_flags
488 * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo
489 * @pl: TTM placement information.
490 */
491void drm_gem_vram_bo_driver_evict_flags(struct ttm_buffer_object *bo,
492 struct ttm_placement *pl)
493{
494 struct drm_gem_vram_object *gbo;
495
496 /* TTM may pass BOs that are not GEM VRAM BOs. */
497 if (!drm_is_gem_vram(bo))
498 return;
499
500 gbo = drm_gem_vram_of_bo(bo);
501 drm_gem_vram_placement(gbo, TTM_PL_FLAG_SYSTEM);
502 *pl = gbo->placement;
503}
504EXPORT_SYMBOL(drm_gem_vram_bo_driver_evict_flags);
505
506/**
507 * drm_gem_vram_bo_driver_verify_access() - \
508 Implements &struct ttm_bo_driver.verify_access
509 * @bo: TTM buffer object. Refers to &struct drm_gem_vram_object.bo
510 * @filp: File pointer.
511 *
512 * Returns:
513 * 0 on success, or
514 * a negative errno code otherwise.
515 */
516int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo,
517 struct file *filp)
518{
519 struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
520
521 return drm_vma_node_verify_access(&gbo->gem.vma_node,
522 filp->private_data);
523}
524EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access);
737000fd
TZ
525
526/*
527 * Helpers for struct drm_driver
528 */
529
530/**
531 * drm_gem_vram_driver_gem_free_object_unlocked() - \
532 Implements &struct drm_driver.gem_free_object_unlocked
533 * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem
534 */
535void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem)
536{
537 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
538
539 drm_gem_vram_put(gbo);
540}
541EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked);
542
543/**
544 * drm_gem_vram_driver_dumb_mmap_offset() - \
545 Implements &struct drm_driver.dumb_mmap_offset
546 * @file: DRM file pointer.
547 * @dev: DRM device.
548 * @handle: GEM handle
549 * @offset: Returns the mapping's memory offset on success
550 *
551 * Returns:
552 * 0 on success, or
553 * a negative errno code otherwise.
554 */
555int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file,
556 struct drm_device *dev,
557 uint32_t handle, uint64_t *offset)
558{
559 struct drm_gem_object *gem;
560 struct drm_gem_vram_object *gbo;
561
562 gem = drm_gem_object_lookup(file, handle);
563 if (!gem)
564 return -ENOENT;
565
566 gbo = drm_gem_vram_of_gem(gem);
567 *offset = drm_gem_vram_mmap_offset(gbo);
568
569 drm_gem_object_put_unlocked(gem);
570
571 return 0;
572}
573EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset);