1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include <drm/drm_device.h>
4 #include <drm/drm_file.h>
5 #include <drm/drm_vram_mm_helper.h>
7 #include <drm/ttm/ttm_page_alloc.h>
12 * The data structure &struct drm_vram_mm and its helpers implement a memory
13 * manager for simple framebuffer devices with dedicated video memory. Buffer
14 * objects are either placed in video RAM or evicted to system memory. These
15 * helper functions work well with &struct drm_gem_vram_object.
22 static void backend_func_destroy(struct ttm_tt *tt)
28 static struct ttm_backend_func backend_func = {
29 .destroy = backend_func_destroy
36 static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo,
42 tt = kzalloc(sizeof(*tt), GFP_KERNEL);
46 tt->func = &backend_func;
48 ret = ttm_tt_init(tt, bo, page_flags);
59 static int bo_driver_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
60 struct ttm_mem_type_manager *man)
64 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
65 man->available_caching = TTM_PL_MASK_CACHING;
66 man->default_caching = TTM_PL_FLAG_CACHED;
69 man->func = &ttm_bo_manager_func;
70 man->flags = TTM_MEMTYPE_FLAG_FIXED |
71 TTM_MEMTYPE_FLAG_MAPPABLE;
72 man->available_caching = TTM_PL_FLAG_UNCACHED |
74 man->default_caching = TTM_PL_FLAG_WC;
82 static void bo_driver_evict_flags(struct ttm_buffer_object *bo,
83 struct ttm_placement *placement)
85 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
87 if (vmm->funcs && vmm->funcs->evict_flags)
88 vmm->funcs->evict_flags(bo, placement);
91 static int bo_driver_verify_access(struct ttm_buffer_object *bo,
94 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bo->bdev);
96 if (!vmm->funcs || !vmm->funcs->verify_access)
98 return vmm->funcs->verify_access(bo, filp);
101 static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev,
102 struct ttm_mem_reg *mem)
104 struct ttm_mem_type_manager *man = bdev->man + mem->mem_type;
105 struct drm_vram_mm *vmm = drm_vram_mm_of_bdev(bdev);
107 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
110 mem->bus.addr = NULL;
111 mem->bus.size = mem->num_pages << PAGE_SHIFT;
113 switch (mem->mem_type) {
114 case TTM_PL_SYSTEM: /* nothing to do */
117 mem->bus.is_iomem = false;
120 mem->bus.offset = mem->start << PAGE_SHIFT;
121 mem->bus.base = vmm->vram_base;
122 mem->bus.is_iomem = true;
131 static void bo_driver_io_mem_free(struct ttm_bo_device *bdev,
132 struct ttm_mem_reg *mem)
135 static struct ttm_bo_driver bo_driver = {
136 .ttm_tt_create = bo_driver_ttm_tt_create,
137 .ttm_tt_populate = ttm_pool_populate,
138 .ttm_tt_unpopulate = ttm_pool_unpopulate,
139 .init_mem_type = bo_driver_init_mem_type,
140 .eviction_valuable = ttm_bo_eviction_valuable,
141 .evict_flags = bo_driver_evict_flags,
142 .verify_access = bo_driver_verify_access,
143 .io_mem_reserve = bo_driver_io_mem_reserve,
144 .io_mem_free = bo_driver_io_mem_free,
152 * drm_vram_mm_init() - Initialize an instance of VRAM MM.
153 * @vmm: the VRAM MM instance to initialize
154 * @dev: the DRM device
155 * @vram_base: the base address of the video memory
156 * @vram_size: the size of the video memory in bytes
157 * @funcs: callback functions for buffer objects
161 * a negative error code otherwise.
163 int drm_vram_mm_init(struct drm_vram_mm *vmm, struct drm_device *dev,
164 uint64_t vram_base, size_t vram_size,
165 const struct drm_vram_mm_funcs *funcs)
169 vmm->vram_base = vram_base;
170 vmm->vram_size = vram_size;
173 ret = ttm_bo_device_init(&vmm->bdev, &bo_driver,
174 dev->anon_inode->i_mapping,
179 ret = ttm_bo_init_mm(&vmm->bdev, TTM_PL_VRAM, vram_size >> PAGE_SHIFT);
185 EXPORT_SYMBOL(drm_vram_mm_init);
188 * drm_vram_mm_cleanup() - Cleans up an initialized instance of VRAM MM.
189 * @vmm: the VRAM MM instance to clean up
191 void drm_vram_mm_cleanup(struct drm_vram_mm *vmm)
193 ttm_bo_device_release(&vmm->bdev);
195 EXPORT_SYMBOL(drm_vram_mm_cleanup);
198 * drm_vram_mm_mmap() - Helper for implementing &struct file_operations.mmap()
199 * @filp: the mapping's file structure
200 * @vma: the mapping's memory area
201 * @vmm: the VRAM MM instance
205 * a negative error code otherwise.
207 int drm_vram_mm_mmap(struct file *filp, struct vm_area_struct *vma,
208 struct drm_vram_mm *vmm)
210 return ttm_bo_mmap(filp, vma, &vmm->bdev);
212 EXPORT_SYMBOL(drm_vram_mm_mmap);
215 * Helpers for integration with struct drm_device
219 * drm_vram_helper_alloc_mm - Allocates a device's instance of \
221 * @dev: the DRM device
222 * @vram_base: the base address of the video memory
223 * @vram_size: the size of the video memory in bytes
224 * @funcs: callback functions for buffer objects
227 * The new instance of &struct drm_vram_mm on success, or
228 * an ERR_PTR()-encoded errno code otherwise.
230 struct drm_vram_mm *drm_vram_helper_alloc_mm(
231 struct drm_device *dev, uint64_t vram_base, size_t vram_size,
232 const struct drm_vram_mm_funcs *funcs)
236 if (WARN_ON(dev->vram_mm))
239 dev->vram_mm = kzalloc(sizeof(*dev->vram_mm), GFP_KERNEL);
241 return ERR_PTR(-ENOMEM);
243 ret = drm_vram_mm_init(dev->vram_mm, dev, vram_base, vram_size, funcs);
254 EXPORT_SYMBOL(drm_vram_helper_alloc_mm);
257 * drm_vram_helper_release_mm - Releases a device's instance of \
259 * @dev: the DRM device
261 void drm_vram_helper_release_mm(struct drm_device *dev)
266 drm_vram_mm_cleanup(dev->vram_mm);
270 EXPORT_SYMBOL(drm_vram_helper_release_mm);
273 * Helpers for &struct file_operations
277 * drm_vram_mm_file_operations_mmap() - \
278 Implements &struct file_operations.mmap()
279 * @filp: the mapping's file structure
280 * @vma: the mapping's memory area
284 * a negative error code otherwise.
286 int drm_vram_mm_file_operations_mmap(
287 struct file *filp, struct vm_area_struct *vma)
289 struct drm_file *file_priv = filp->private_data;
290 struct drm_device *dev = file_priv->minor->dev;
292 if (WARN_ONCE(!dev->vram_mm, "VRAM MM not initialized"))
295 return drm_vram_mm_mmap(filp, vma, dev->vram_mm);
297 EXPORT_SYMBOL(drm_vram_mm_file_operations_mmap);