Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include <linux/export.h>
4#include <linux/iosys-map.h>
5#include <linux/module.h>
6
7#include <drm/drm_debugfs.h>
8#include <drm/drm_device.h>
9#include <drm/drm_drv.h>
10#include <drm/drm_file.h>
11#include <drm/drm_framebuffer.h>
12#include <drm/drm_gem_atomic_helper.h>
13#include <drm/drm_gem_framebuffer_helper.h>
14#include <drm/drm_gem_ttm_helper.h>
15#include <drm/drm_gem_vram_helper.h>
16#include <drm/drm_managed.h>
17#include <drm/drm_mode.h>
18#include <drm/drm_plane.h>
19#include <drm/drm_prime.h>
20#include <drm/drm_print.h>
21
22#include <drm/ttm/ttm_range_manager.h>
23#include <drm/ttm/ttm_tt.h>
24
25static const struct drm_gem_object_funcs drm_gem_vram_object_funcs;
26
27/**
28 * DOC: overview
29 *
30 * This library provides &struct drm_gem_vram_object (GEM VRAM), a GEM
31 * buffer object that is backed by video RAM (VRAM). It can be used for
32 * framebuffer devices with dedicated memory.
33 *
34 * The data structure &struct drm_vram_mm and its helpers implement a memory
35 * manager for simple framebuffer devices with dedicated video memory. GEM
36 * VRAM buffer objects are either placed in the video memory or remain evicted
37 * to system memory.
38 *
39 * With the GEM interface userspace applications create, manage and destroy
40 * graphics buffers, such as an on-screen framebuffer. GEM does not provide
41 * an implementation of these interfaces. It's up to the DRM driver to
42 * provide an implementation that suits the hardware. If the hardware device
43 * contains dedicated video memory, the DRM driver can use the VRAM helper
44 * library. Each active buffer object is stored in video RAM. Active
45 * buffer are used for drawing the current frame, typically something like
46 * the frame's scanout buffer or the cursor image. If there's no more space
47 * left in VRAM, inactive GEM objects can be moved to system memory.
48 *
49 * To initialize the VRAM helper library call drmm_vram_helper_init().
50 * The function allocates and initializes an instance of &struct drm_vram_mm
51 * in &struct drm_device.vram_mm . Use &DRM_GEM_VRAM_DRIVER to initialize
52 * &struct drm_driver and &DEFINE_DRM_GEM_FOPS to define
53 * &struct file_operations; as illustrated below.
54 *
55 * .. code-block:: c
56 *
57 * DEFINE_DRM_GEM_FOPS(fops);
58 * struct drm_driver drv = {
59 * .driver_feature = DRM_ ... ,
60 * .fops = &fops,
61 * DRM_GEM_VRAM_DRIVER
62 * };
63 *
64 * int init_drm_driver()
65 * {
66 * struct drm_device *dev;
67 * uint64_t vram_base;
68 * unsigned long vram_size;
69 * int ret;
70 *
71 * // setup device, vram base and size
72 * // ...
73 *
74 * ret = drmm_vram_helper_init(dev, vram_base, vram_size);
75 * if (ret)
76 * return ret;
77 * return 0;
78 * }
79 *
80 * This creates an instance of &struct drm_vram_mm, exports DRM userspace
81 * interfaces for GEM buffer management and initializes file operations to
82 * allow for accessing created GEM buffers. With this setup, the DRM driver
83 * manages an area of video RAM with VRAM MM and provides GEM VRAM objects
84 * to userspace.
85 *
86 * You don't have to clean up the instance of VRAM MM.
87 * drmm_vram_helper_init() is a managed interface that installs a
88 * clean-up handler to run during the DRM device's release.
89 *
90 * A buffer object that is pinned in video RAM has a fixed address within that
91 * memory region. Call drm_gem_vram_offset() to retrieve this value. Typically
92 * it's used to program the hardware's scanout engine for framebuffers, set
93 * the cursor overlay's image for a mouse cursor, or use it as input to the
94 * hardware's drawing engine.
95 *
96 * To access a buffer object's memory from the DRM driver, call
97 * drm_gem_vram_vmap(). It maps the buffer into kernel address
98 * space and returns the memory address. Use drm_gem_vram_vunmap() to
99 * release the mapping.
100 */
101
102/*
103 * Buffer-objects helpers
104 */
105
106static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo)
107{
108 /* We got here via ttm_bo_fini(), which means that the
109 * TTM buffer object in 'bo' has already been cleaned
110 * up; only release the GEM object.
111 */
112
113 WARN_ON(gbo->vmap_use_count);
114 WARN_ON(iosys_map_is_set(&gbo->map));
115
116 drm_gem_object_release(&gbo->bo.base);
117}
118
119static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo)
120{
121 drm_gem_vram_cleanup(gbo);
122 kfree(gbo);
123}
124
125static void ttm_buffer_object_destroy(struct ttm_buffer_object *bo)
126{
127 struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo);
128
129 drm_gem_vram_destroy(gbo);
130}
131
132static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo,
133 unsigned long pl_flag)
134{
135 u32 invariant_flags = 0;
136 unsigned int i;
137 unsigned int c = 0;
138
139 if (pl_flag & DRM_GEM_VRAM_PL_FLAG_TOPDOWN)
140 invariant_flags = TTM_PL_FLAG_TOPDOWN;
141
142 gbo->placement.placement = gbo->placements;
143
144 if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) {
145 gbo->placements[c].mem_type = TTM_PL_VRAM;
146 gbo->placements[c++].flags = invariant_flags;
147 }
148
149 if (pl_flag & DRM_GEM_VRAM_PL_FLAG_SYSTEM || !c) {
150 gbo->placements[c].mem_type = TTM_PL_SYSTEM;
151 gbo->placements[c++].flags = invariant_flags;
152 }
153
154 gbo->placement.num_placement = c;
155
156 for (i = 0; i < c; ++i) {
157 gbo->placements[i].fpfn = 0;
158 gbo->placements[i].lpfn = 0;
159 }
160}
161
162/**
163 * drm_gem_vram_create() - Creates a VRAM-backed GEM object
164 * @dev: the DRM device
165 * @size: the buffer size in bytes
166 * @pg_align: the buffer's alignment in multiples of the page size
167 *
168 * GEM objects are allocated by calling struct drm_driver.gem_create_object,
169 * if set. Otherwise kzalloc() will be used. Drivers can set their own GEM
170 * object functions in struct drm_driver.gem_create_object. If no functions
171 * are set, the new GEM object will use the default functions from GEM VRAM
172 * helpers.
173 *
174 * Returns:
175 * A new instance of &struct drm_gem_vram_object on success, or
176 * an ERR_PTR()-encoded error code otherwise.
177 */
178struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
179 size_t size,
180 unsigned long pg_align)
181{
182 struct drm_gem_vram_object *gbo;
183 struct drm_gem_object *gem;
184 struct drm_vram_mm *vmm = dev->vram_mm;
185 struct ttm_device *bdev;
186 int ret;
187
188 if (WARN_ONCE(!vmm, "VRAM MM not initialized"))
189 return ERR_PTR(-EINVAL);
190
191 if (dev->driver->gem_create_object) {
192 gem = dev->driver->gem_create_object(dev, size);
193 if (IS_ERR(gem))
194 return ERR_CAST(gem);
195 gbo = drm_gem_vram_of_gem(gem);
196 } else {
197 gbo = kzalloc_obj(*gbo);
198 if (!gbo)
199 return ERR_PTR(-ENOMEM);
200 gem = &gbo->bo.base;
201 }
202
203 if (!gem->funcs)
204 gem->funcs = &drm_gem_vram_object_funcs;
205
206 ret = drm_gem_object_init(dev, gem, size);
207 if (ret) {
208 kfree(gbo);
209 return ERR_PTR(ret);
210 }
211
212 bdev = &vmm->bdev;
213
214 gbo->bo.bdev = bdev;
215 drm_gem_vram_placement(gbo, DRM_GEM_VRAM_PL_FLAG_SYSTEM);
216
217 /*
218 * A failing ttm_bo_init will call ttm_buffer_object_destroy
219 * to release gbo->bo.base and kfree gbo.
220 */
221 ret = ttm_bo_init_validate(bdev, &gbo->bo, ttm_bo_type_device,
222 &gbo->placement, pg_align, false, NULL, NULL,
223 ttm_buffer_object_destroy);
224 if (ret)
225 return ERR_PTR(ret);
226
227 return gbo;
228}
229EXPORT_SYMBOL(drm_gem_vram_create);
230
231/**
232 * drm_gem_vram_put() - Releases a reference to a VRAM-backed GEM object
233 * @gbo: the GEM VRAM object
234 *
235 * See ttm_bo_fini() for more information.
236 */
237void drm_gem_vram_put(struct drm_gem_vram_object *gbo)
238{
239 ttm_bo_fini(&gbo->bo);
240}
241EXPORT_SYMBOL(drm_gem_vram_put);
242
243static u64 drm_gem_vram_pg_offset(struct drm_gem_vram_object *gbo)
244{
245 /* Keep TTM behavior for now, remove when drivers are audited */
246 if (WARN_ON_ONCE(!gbo->bo.resource ||
247 gbo->bo.resource->mem_type == TTM_PL_SYSTEM))
248 return 0;
249
250 return gbo->bo.resource->start;
251}
252
253/**
254 * drm_gem_vram_offset() - Returns a GEM VRAM object's offset in video memory
255 * @gbo: the GEM VRAM object
256 *
257 * This function returns the buffer object's offset in the device's video
258 * memory. The buffer object has to be pinned to %TTM_PL_VRAM.
259 *
260 * Returns:
261 * The buffer object's offset in video memory on success, or
262 * a negative errno code otherwise.
263 */
264s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo)
265{
266 if (WARN_ON_ONCE(!gbo->bo.pin_count))
267 return (s64)-ENODEV;
268 return drm_gem_vram_pg_offset(gbo) << PAGE_SHIFT;
269}
270EXPORT_SYMBOL(drm_gem_vram_offset);
271
272static int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo,
273 unsigned long pl_flag)
274{
275 struct ttm_operation_ctx ctx = { false, false };
276 int ret;
277
278 dma_resv_assert_held(gbo->bo.base.resv);
279
280 if (gbo->bo.pin_count)
281 goto out;
282
283 if (pl_flag)
284 drm_gem_vram_placement(gbo, pl_flag);
285
286 ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx);
287 if (ret < 0)
288 return ret;
289
290out:
291 ttm_bo_pin(&gbo->bo);
292
293 return 0;
294}
295
296static int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag)
297{
298 int ret;
299
300 ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
301 if (ret)
302 return ret;
303 ret = drm_gem_vram_pin_locked(gbo, pl_flag);
304 ttm_bo_unreserve(&gbo->bo);
305
306 return ret;
307}
308
309static void drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo)
310{
311 dma_resv_assert_held(gbo->bo.base.resv);
312
313 ttm_bo_unpin(&gbo->bo);
314}
315
316static int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo)
317{
318 int ret;
319
320 ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
321 if (ret)
322 return ret;
323
324 drm_gem_vram_unpin_locked(gbo);
325 ttm_bo_unreserve(&gbo->bo);
326
327 return 0;
328}
329
330/**
331 * drm_gem_vram_vmap() - Pins and maps a GEM VRAM object into kernel address
332 * space
333 * @gbo: The GEM VRAM object to map
334 * @map: Returns the kernel virtual address of the VRAM GEM object's backing
335 * store.
336 *
337 * The vmap function pins a GEM VRAM object to its current location, either
338 * system or video memory, and maps its buffer into kernel address space.
339 * As pinned object cannot be relocated, you should avoid pinning objects
340 * permanently. Call drm_gem_vram_vunmap() with the returned address to
341 * unmap and unpin the GEM VRAM object.
342 *
343 * Returns:
344 * 0 on success, or a negative error code otherwise.
345 */
346int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, struct iosys_map *map)
347{
348 int ret;
349
350 dma_resv_assert_held(gbo->bo.base.resv);
351
352 if (gbo->vmap_use_count > 0)
353 goto out;
354
355 /*
356 * VRAM helpers unmap the BO only on demand. So the previous
357 * page mapping might still be around. Only vmap if the there's
358 * no mapping present.
359 */
360 if (iosys_map_is_null(&gbo->map)) {
361 ret = ttm_bo_vmap(&gbo->bo, &gbo->map);
362 if (ret)
363 return ret;
364 }
365
366out:
367 ++gbo->vmap_use_count;
368 *map = gbo->map;
369
370 return 0;
371}
372EXPORT_SYMBOL(drm_gem_vram_vmap);
373
374/**
375 * drm_gem_vram_vunmap() - Unmaps and unpins a GEM VRAM object
376 * @gbo: The GEM VRAM object to unmap
377 * @map: Kernel virtual address where the VRAM GEM object was mapped
378 *
379 * A call to drm_gem_vram_vunmap() unmaps and unpins a GEM VRAM buffer. See
380 * the documentation for drm_gem_vram_vmap() for more information.
381 */
382void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo,
383 struct iosys_map *map)
384{
385 struct drm_device *dev = gbo->bo.base.dev;
386
387 dma_resv_assert_held(gbo->bo.base.resv);
388
389 if (drm_WARN_ON_ONCE(dev, !gbo->vmap_use_count))
390 return;
391
392 if (drm_WARN_ON_ONCE(dev, !iosys_map_is_equal(&gbo->map, map)))
393 return; /* BUG: map not mapped from this BO */
394
395 if (--gbo->vmap_use_count > 0)
396 return;
397
398 /*
399 * Permanently mapping and unmapping buffers adds overhead from
400 * updating the page tables and creates debugging output. Therefore,
401 * we delay the actual unmap operation until the BO gets evicted
402 * from memory. See drm_gem_vram_bo_driver_move_notify().
403 */
404}
405EXPORT_SYMBOL(drm_gem_vram_vunmap);
406
407/**
408 * drm_gem_vram_fill_create_dumb() - Helper for implementing
409 * &struct drm_driver.dumb_create
410 *
411 * @file: the DRM file
412 * @dev: the DRM device
413 * @pg_align: the buffer's alignment in multiples of the page size
414 * @pitch_align: the scanline's alignment in powers of 2
415 * @args: the arguments as provided to
416 * &struct drm_driver.dumb_create
417 *
418 * This helper function fills &struct drm_mode_create_dumb, which is used
419 * by &struct drm_driver.dumb_create. Implementations of this interface
420 * should forwards their arguments to this helper, plus the driver-specific
421 * parameters.
422 *
423 * Returns:
424 * 0 on success, or
425 * a negative error code otherwise.
426 */
427int drm_gem_vram_fill_create_dumb(struct drm_file *file,
428 struct drm_device *dev,
429 unsigned long pg_align,
430 unsigned long pitch_align,
431 struct drm_mode_create_dumb *args)
432{
433 size_t pitch, size;
434 struct drm_gem_vram_object *gbo;
435 int ret;
436 u32 handle;
437
438 pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
439 if (pitch_align) {
440 if (WARN_ON_ONCE(!is_power_of_2(pitch_align)))
441 return -EINVAL;
442 pitch = ALIGN(pitch, pitch_align);
443 }
444 size = pitch * args->height;
445
446 size = roundup(size, PAGE_SIZE);
447 if (!size)
448 return -EINVAL;
449
450 gbo = drm_gem_vram_create(dev, size, pg_align);
451 if (IS_ERR(gbo))
452 return PTR_ERR(gbo);
453
454 ret = drm_gem_handle_create(file, &gbo->bo.base, &handle);
455 if (ret)
456 goto err_drm_gem_object_put;
457
458 drm_gem_object_put(&gbo->bo.base);
459
460 args->pitch = pitch;
461 args->size = size;
462 args->handle = handle;
463
464 return 0;
465
466err_drm_gem_object_put:
467 drm_gem_object_put(&gbo->bo.base);
468 return ret;
469}
470EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb);
471
472/*
473 * Helpers for struct ttm_device_funcs
474 */
475
476static bool drm_is_gem_vram(struct ttm_buffer_object *bo)
477{
478 return (bo->destroy == ttm_buffer_object_destroy);
479}
480
481static void drm_gem_vram_bo_driver_evict_flags(struct drm_gem_vram_object *gbo,
482 struct ttm_placement *pl)
483{
484 drm_gem_vram_placement(gbo, DRM_GEM_VRAM_PL_FLAG_SYSTEM);
485 *pl = gbo->placement;
486}
487
488static void drm_gem_vram_bo_driver_move_notify(struct drm_gem_vram_object *gbo)
489{
490 struct ttm_buffer_object *bo = &gbo->bo;
491 struct drm_device *dev = bo->base.dev;
492
493 if (drm_WARN_ON_ONCE(dev, gbo->vmap_use_count))
494 return;
495
496 ttm_bo_vunmap(bo, &gbo->map);
497 iosys_map_clear(&gbo->map); /* explicitly clear mapping for next vmap call */
498}
499
500static int drm_gem_vram_bo_driver_move(struct drm_gem_vram_object *gbo,
501 bool evict,
502 struct ttm_operation_ctx *ctx,
503 struct ttm_resource *new_mem)
504{
505 drm_gem_vram_bo_driver_move_notify(gbo);
506 return ttm_bo_move_memcpy(&gbo->bo, ctx, new_mem);
507}
508
509/*
510 * Helpers for struct drm_gem_object_funcs
511 */
512
513/**
514 * drm_gem_vram_object_free() - Implements &struct drm_gem_object_funcs.free
515 * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem
516 */
517static void drm_gem_vram_object_free(struct drm_gem_object *gem)
518{
519 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
520
521 drm_gem_vram_put(gbo);
522}
523
524/*
525 * Helpers for dump buffers
526 */
527
528/**
529 * drm_gem_vram_driver_dumb_create() - Implements &struct drm_driver.dumb_create
530 * @file: the DRM file
531 * @dev: the DRM device
532 * @args: the arguments as provided to
533 * &struct drm_driver.dumb_create
534 *
535 * This function requires the driver to use @drm_device.vram_mm for its
536 * instance of VRAM MM.
537 *
538 * Returns:
539 * 0 on success, or
540 * a negative error code otherwise.
541 */
542int drm_gem_vram_driver_dumb_create(struct drm_file *file,
543 struct drm_device *dev,
544 struct drm_mode_create_dumb *args)
545{
546 if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
547 return -EINVAL;
548
549 return drm_gem_vram_fill_create_dumb(file, dev, 0, 0, args);
550}
551EXPORT_SYMBOL(drm_gem_vram_driver_dumb_create);
552
553/*
554 * Helpers for struct drm_plane_helper_funcs
555 */
556
557static void __drm_gem_vram_plane_helper_cleanup_fb(struct drm_plane *plane,
558 struct drm_plane_state *state,
559 unsigned int num_planes)
560{
561 struct drm_gem_object *obj;
562 struct drm_gem_vram_object *gbo;
563 struct drm_framebuffer *fb = state->fb;
564
565 while (num_planes) {
566 --num_planes;
567 obj = drm_gem_fb_get_obj(fb, num_planes);
568 if (!obj)
569 continue;
570 gbo = drm_gem_vram_of_gem(obj);
571 drm_gem_vram_unpin(gbo);
572 }
573}
574
575/**
576 * drm_gem_vram_plane_helper_prepare_fb() - Implements &struct
577 * drm_plane_helper_funcs.prepare_fb
578 * @plane: a DRM plane
579 * @new_state: the plane's new state
580 *
581 * During plane updates, this function sets the plane's fence and
582 * pins the GEM VRAM objects of the plane's new framebuffer to VRAM.
583 * Call drm_gem_vram_plane_helper_cleanup_fb() to unpin them.
584 *
585 * Returns:
586 * 0 on success, or
587 * a negative errno code otherwise.
588 */
589int
590drm_gem_vram_plane_helper_prepare_fb(struct drm_plane *plane,
591 struct drm_plane_state *new_state)
592{
593 struct drm_framebuffer *fb = new_state->fb;
594 struct drm_gem_vram_object *gbo;
595 struct drm_gem_object *obj;
596 unsigned int i;
597 int ret;
598
599 if (!fb)
600 return 0;
601
602 for (i = 0; i < fb->format->num_planes; ++i) {
603 obj = drm_gem_fb_get_obj(fb, i);
604 if (!obj) {
605 ret = -EINVAL;
606 goto err_drm_gem_vram_unpin;
607 }
608 gbo = drm_gem_vram_of_gem(obj);
609 ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM);
610 if (ret)
611 goto err_drm_gem_vram_unpin;
612 }
613
614 ret = drm_gem_plane_helper_prepare_fb(plane, new_state);
615 if (ret)
616 goto err_drm_gem_vram_unpin;
617
618 return 0;
619
620err_drm_gem_vram_unpin:
621 __drm_gem_vram_plane_helper_cleanup_fb(plane, new_state, i);
622 return ret;
623}
624EXPORT_SYMBOL(drm_gem_vram_plane_helper_prepare_fb);
625
626/**
627 * drm_gem_vram_plane_helper_cleanup_fb() - Implements &struct
628 * drm_plane_helper_funcs.cleanup_fb
629 * @plane: a DRM plane
630 * @old_state: the plane's old state
631 *
632 * During plane updates, this function unpins the GEM VRAM
633 * objects of the plane's old framebuffer from VRAM. Complements
634 * drm_gem_vram_plane_helper_prepare_fb().
635 */
636void
637drm_gem_vram_plane_helper_cleanup_fb(struct drm_plane *plane,
638 struct drm_plane_state *old_state)
639{
640 struct drm_framebuffer *fb = old_state->fb;
641
642 if (!fb)
643 return;
644
645 __drm_gem_vram_plane_helper_cleanup_fb(plane, old_state, fb->format->num_planes);
646}
647EXPORT_SYMBOL(drm_gem_vram_plane_helper_cleanup_fb);
648
649/*
650 * PRIME helpers
651 */
652
653/**
654 * drm_gem_vram_object_vmap() -
655 * Implements &struct drm_gem_object_funcs.vmap
656 * @gem: The GEM object to map
657 * @map: Returns the kernel virtual address of the VRAM GEM object's backing
658 * store.
659 *
660 * Returns:
661 * 0 on success, or a negative error code otherwise.
662 */
663static int drm_gem_vram_object_vmap(struct drm_gem_object *gem,
664 struct iosys_map *map)
665{
666 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
667
668 return drm_gem_vram_vmap(gbo, map);
669}
670
671/**
672 * drm_gem_vram_object_vunmap() -
673 * Implements &struct drm_gem_object_funcs.vunmap
674 * @gem: The GEM object to unmap
675 * @map: Kernel virtual address where the VRAM GEM object was mapped
676 */
677static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem,
678 struct iosys_map *map)
679{
680 struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem);
681
682 drm_gem_vram_vunmap(gbo, map);
683}
684
685/*
686 * GEM object funcs
687 */
688
689static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = {
690 .free = drm_gem_vram_object_free,
691 .vmap = drm_gem_vram_object_vmap,
692 .vunmap = drm_gem_vram_object_vunmap,
693 .mmap = drm_gem_ttm_mmap,
694 .print_info = drm_gem_ttm_print_info,
695};
696
697/*
698 * VRAM memory manager
699 */
700
701/*
702 * TTM TT
703 */
704
705static void bo_driver_ttm_tt_destroy(struct ttm_device *bdev, struct ttm_tt *tt)
706{
707 ttm_tt_fini(tt);
708 kfree(tt);
709}
710
711/*
712 * TTM BO device
713 */
714
715static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
716 uint32_t page_flags)
717{
718 struct ttm_tt *tt;
719 int ret;
720
721 tt = kzalloc_obj(*tt);
722 if (!tt)
723 return NULL;
724
725 ret = ttm_tt_init(tt, bo, page_flags, ttm_cached, 0);
726 if (ret < 0)
727 goto err_ttm_tt_init;
728
729 return tt;
730
731err_ttm_tt_init:
732 kfree(tt);
733 return NULL;
734}
735
736static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
737 struct ttm_placement *placement)
738{
739 struct drm_gem_vram_object *gbo;
740
741 /* TTM may pass BOs that are not GEM VRAM BOs. */
742 if (!drm_is_gem_vram(bo))
743 return;
744
745 gbo = drm_gem_vram_of_bo(bo);
746
747 drm_gem_vram_bo_driver_evict_flags(gbo, placement);
748}
749
750static void bo_driver_delete_mem_notify(struct ttm_buffer_object *bo)
751{
752 struct drm_gem_vram_object *gbo;
753
754 /* TTM may pass BOs that are not GEM VRAM BOs. */
755 if (!drm_is_gem_vram(bo))
756 return;
757
758 gbo = drm_gem_vram_of_bo(bo);
759
760 drm_gem_vram_bo_driver_move_notify(gbo);
761}
762
763static int bo_driver_move(struct ttm_buffer_object *bo,
764 bool evict,
765 struct ttm_operation_ctx *ctx,
766 struct ttm_resource *new_mem,
767 struct ttm_place *hop)
768{
769 struct drm_gem_vram_object *gbo;
770
771 if (!bo->resource) {
772 if (new_mem->mem_type != TTM_PL_SYSTEM) {
773 hop->mem_type = TTM_PL_SYSTEM;
774 hop->flags = TTM_PL_FLAG_TEMPORARY;
775 return -EMULTIHOP;
776 }
777
778 ttm_bo_move_null(bo, new_mem);
779 return 0;
780 }
781
782 gbo = drm_gem_vram_of_bo(bo);
783
784 return drm_gem_vram_bo_driver_move(gbo, evict, ctx, new_mem);
785}
786
787static int bo_driver_io_mem_reserve(struct ttm_device *bdev,
788 struct ttm_resource *mem)
789{
790 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
791
792 switch (mem->mem_type) {
793 case TTM_PL_SYSTEM: /* nothing to do */
794 break;
795 case TTM_PL_VRAM:
796 mem->bus.offset = (mem->start << PAGE_SHIFT) + vmm->vram_base;
797 mem->bus.is_iomem = true;
798 mem->bus.caching = ttm_write_combined;
799 break;
800 default:
801 return -EINVAL;
802 }
803
804 return 0;
805}
806
807static struct ttm_device_funcs bo_driver = {
808 .ttm_tt_create = bo_driver_ttm_tt_create,
809 .ttm_tt_destroy = bo_driver_ttm_tt_destroy,
810 .eviction_valuable = ttm_bo_eviction_valuable,
811 .evict_flags = bo_driver_evict_flags,
812 .move = bo_driver_move,
813 .delete_mem_notify = bo_driver_delete_mem_notify,
814 .io_mem_reserve = bo_driver_io_mem_reserve,
815};
816
817/*
818 * struct drm_vram_mm
819 */
820
821static int drm_vram_mm_debugfs(struct seq_file *m, void *data)
822{
823 struct drm_debugfs_entry *entry = m->private;
824 struct drm_vram_mm *vmm = entry->dev->vram_mm;
825 struct ttm_resource_manager *man = ttm_manager_type(&vmm->bdev, TTM_PL_VRAM);
826 struct drm_printer p = drm_seq_file_printer(m);
827
828 ttm_resource_manager_debug(man, &p);
829 return 0;
830}
831
832static const struct drm_debugfs_info drm_vram_mm_debugfs_list[] = {
833 { "vram-mm", drm_vram_mm_debugfs, 0, NULL },
834};
835
836/**
837 * drm_vram_mm_debugfs_init() - Register VRAM MM debugfs file.
838 *
839 * @minor: drm minor device.
840 *
841 */
842void drm_vram_mm_debugfs_init(struct drm_minor *minor)
843{
844 drm_debugfs_add_files(minor->dev, drm_vram_mm_debugfs_list,
845 ARRAY_SIZE(drm_vram_mm_debugfs_list));
846}
847EXPORT_SYMBOL(drm_vram_mm_debugfs_init);
848
849static int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
850 uint64_t vram_base, size_t vram_size)
851{
852 int ret;
853
854 vmm->vram_base = vram_base;
855 vmm->vram_size = vram_size;
856
857 ret = ttm_device_init(&vmm->bdev, &bo_driver, dev->dev,
858 dev->anon_inode->i_mapping,
859 dev->vma_offset_manager,
860 TTM_ALLOCATION_POOL_USE_DMA32);
861 if (ret)
862 return ret;
863
864 ret = ttm_range_man_init(&vmm->bdev, TTM_PL_VRAM,
865 false, vram_size >> PAGE_SHIFT);
866 if (ret)
867 return ret;
868
869 return 0;
870}
871
872static void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
873{
874 ttm_range_man_fini(&vmm->bdev, TTM_PL_VRAM);
875 ttm_device_fini(&vmm->bdev);
876}
877
878/*
879 * Helpers for integration with struct drm_device
880 */
881
882static struct drm_vram_mm *drm_vram_helper_alloc_mm(struct drm_device *dev, uint64_t vram_base,
883 size_t vram_size)
884{
885 int ret;
886
887 if (WARN_ON(dev->vram_mm))
888 return dev->vram_mm;
889
890 dev->vram_mm = kzalloc_obj(*dev->vram_mm);
891 if (!dev->vram_mm)
892 return ERR_PTR(-ENOMEM);
893
894 ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size);
895 if (ret)
896 goto err_kfree;
897
898 return dev->vram_mm;
899
900err_kfree:
901 kfree(dev->vram_mm);
902 dev->vram_mm = NULL;
903 return ERR_PTR(ret);
904}
905
906static void drm_vram_helper_release_mm(struct drm_device *dev)
907{
908 if (!dev->vram_mm)
909 return;
910
911 drm_vram_mm_cleanup(dev->vram_mm);
912 kfree(dev->vram_mm);
913 dev->vram_mm = NULL;
914}
915
916static void drm_vram_mm_release(struct drm_device *dev, void *ptr)
917{
918 drm_vram_helper_release_mm(dev);
919}
920
921/**
922 * drmm_vram_helper_init - Initializes a device's instance of
923 * &struct drm_vram_mm
924 * @dev: the DRM device
925 * @vram_base: the base address of the video memory
926 * @vram_size: the size of the video memory in bytes
927 *
928 * Creates a new instance of &struct drm_vram_mm and stores it in
929 * struct &drm_device.vram_mm. The instance is auto-managed and cleaned
930 * up as part of device cleanup. Calling this function multiple times
931 * will generate an error message.
932 *
933 * Returns:
934 * 0 on success, or a negative errno code otherwise.
935 */
936int drmm_vram_helper_init(struct drm_device *dev, uint64_t vram_base,
937 size_t vram_size)
938{
939 struct drm_vram_mm *vram_mm;
940
941 if (drm_WARN_ON_ONCE(dev, dev->vram_mm))
942 return 0;
943
944 vram_mm = drm_vram_helper_alloc_mm(dev, vram_base, vram_size);
945 if (IS_ERR(vram_mm))
946 return PTR_ERR(vram_mm);
947 return drmm_add_action_or_reset(dev, drm_vram_mm_release, NULL);
948}
949EXPORT_SYMBOL(drmm_vram_helper_init);
950
951/*
952 * Mode-config helpers
953 */
954
955static enum drm_mode_status
956drm_vram_helper_mode_valid_internal(struct drm_device *dev,
957 const struct drm_display_mode *mode,
958 unsigned long max_bpp)
959{
960 struct drm_vram_mm *vmm = dev->vram_mm;
961 unsigned long fbsize, fbpages, max_fbpages;
962
963 if (WARN_ON(!dev->vram_mm))
964 return MODE_BAD;
965
966 max_fbpages = (vmm->vram_size / 2) >> PAGE_SHIFT;
967
968 fbsize = (u32)mode->hdisplay * mode->vdisplay * max_bpp;
969 fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
970
971 if (fbpages > max_fbpages)
972 return MODE_MEM;
973
974 return MODE_OK;
975}
976
977/**
978 * drm_vram_helper_mode_valid - Tests if a display mode's
979 * framebuffer fits into the available video memory.
980 * @dev: the DRM device
981 * @mode: the mode to test
982 *
983 * This function tests if enough video memory is available for using the
984 * specified display mode. Atomic modesetting requires importing the
985 * designated framebuffer into video memory before evicting the active
986 * one. Hence, any framebuffer may consume at most half of the available
987 * VRAM. Display modes that require a larger framebuffer can not be used,
988 * even if the CRTC does support them. Each framebuffer is assumed to
989 * have 32-bit color depth.
990 *
991 * Note:
992 * The function can only test if the display mode is supported in
993 * general. If there are too many framebuffers pinned to video memory,
994 * a display mode may still not be usable in practice. The color depth of
995 * 32-bit fits all current use case. A more flexible test can be added
996 * when necessary.
997 *
998 * Returns:
999 * MODE_OK if the display mode is supported, or an error code of type
1000 * enum drm_mode_status otherwise.
1001 */
1002enum drm_mode_status
1003drm_vram_helper_mode_valid(struct drm_device *dev,
1004 const struct drm_display_mode *mode)
1005{
1006 static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
1007
1008 return drm_vram_helper_mode_valid_internal(dev, mode, max_bpp);
1009}
1010EXPORT_SYMBOL(drm_vram_helper_mode_valid);
1011
1012MODULE_DESCRIPTION("DRM VRAM memory-management helpers");
1013MODULE_LICENSE("GPL");