2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
10 static void bochs_ttm_placement(struct bochs_bo *bo, int domain);
12 /* ---------------------------------------------------------------------- */
14 static inline struct bochs_device *bochs_bdev(struct ttm_bo_device *bd)
16 return container_of(bd, struct bochs_device, ttm.bdev);
19 static int bochs_ttm_global_init(struct bochs_device *bochs)
21 struct drm_global_reference *global_ref;
24 global_ref = &bochs->ttm.bo_global_ref.ref;
25 global_ref->global_type = DRM_GLOBAL_TTM_BO;
26 global_ref->size = sizeof(struct ttm_bo_global);
27 global_ref->init = &ttm_bo_global_ref_init;
28 global_ref->release = &ttm_bo_global_ref_release;
29 r = drm_global_item_ref(global_ref);
31 DRM_ERROR("Failed setting up TTM BO subsystem.\n");
38 static void bochs_ttm_global_release(struct bochs_device *bochs)
40 if (bochs->ttm.bo_global_ref.ref.release == NULL)
43 drm_global_item_unref(&bochs->ttm.bo_global_ref.ref);
44 bochs->ttm.bo_global_ref.ref.release = NULL;
48 static void bochs_bo_ttm_destroy(struct ttm_buffer_object *tbo)
52 bo = container_of(tbo, struct bochs_bo, bo);
53 drm_gem_object_release(&bo->gem);
57 static bool bochs_ttm_bo_is_bochs_bo(struct ttm_buffer_object *bo)
59 if (bo->destroy == &bochs_bo_ttm_destroy)
64 static int bochs_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
65 struct ttm_mem_type_manager *man)
69 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
70 man->available_caching = TTM_PL_MASK_CACHING;
71 man->default_caching = TTM_PL_FLAG_CACHED;
74 man->func = &ttm_bo_manager_func;
75 man->flags = TTM_MEMTYPE_FLAG_FIXED |
76 TTM_MEMTYPE_FLAG_MAPPABLE;
77 man->available_caching = TTM_PL_FLAG_UNCACHED |
79 man->default_caching = TTM_PL_FLAG_WC;
82 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
89 bochs_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
91 struct bochs_bo *bochsbo = bochs_bo(bo);
93 if (!bochs_ttm_bo_is_bochs_bo(bo))
96 bochs_ttm_placement(bochsbo, TTM_PL_FLAG_SYSTEM);
97 *pl = bochsbo->placement;
100 static int bochs_bo_verify_access(struct ttm_buffer_object *bo,
103 struct bochs_bo *bochsbo = bochs_bo(bo);
105 return drm_vma_node_verify_access(&bochsbo->gem.vma_node,
109 static int bochs_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
110 struct ttm_mem_reg *mem)
112 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
113 struct bochs_device *bochs = bochs_bdev(bdev);
115 mem->bus.addr = NULL;
117 mem->bus.size = mem->num_pages << PAGE_SHIFT;
119 mem->bus.is_iomem = false;
120 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
122 switch (mem->mem_type) {
127 mem->bus.offset = mem->start << PAGE_SHIFT;
128 mem->bus.base = bochs->fb_base;
129 mem->bus.is_iomem = true;
138 static void bochs_ttm_io_mem_free(struct ttm_bo_device *bdev,
139 struct ttm_mem_reg *mem)
143 static void bochs_ttm_backend_destroy(struct ttm_tt *tt)
149 static struct ttm_backend_func bochs_tt_backend_func = {
150 .destroy = &bochs_ttm_backend_destroy,
153 static struct ttm_tt *bochs_ttm_tt_create(struct ttm_buffer_object *bo,
158 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
161 tt->func = &bochs_tt_backend_func;
162 if (ttm_tt_init(tt, bo, page_flags)) {
169 static struct ttm_bo_driver bochs_bo_driver = {
170 .ttm_tt_create = bochs_ttm_tt_create,
171 .init_mem_type = bochs_bo_init_mem_type,
172 .eviction_valuable = ttm_bo_eviction_valuable,
173 .evict_flags = bochs_bo_evict_flags,
175 .verify_access = bochs_bo_verify_access,
176 .io_mem_reserve = &bochs_ttm_io_mem_reserve,
177 .io_mem_free = &bochs_ttm_io_mem_free,
180 int bochs_mm_init(struct bochs_device *bochs)
182 struct ttm_bo_device *bdev = &bochs->ttm.bdev;
185 ret = bochs_ttm_global_init(bochs);
189 ret = ttm_bo_device_init(&bochs->ttm.bdev,
190 bochs->ttm.bo_global_ref.ref.object,
192 bochs->dev->anon_inode->i_mapping,
193 DRM_FILE_PAGE_OFFSET,
196 DRM_ERROR("Error initialising bo driver; %d\n", ret);
200 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
201 bochs->fb_size >> PAGE_SHIFT);
203 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
207 bochs->ttm.initialized = true;
211 void bochs_mm_fini(struct bochs_device *bochs)
213 if (!bochs->ttm.initialized)
216 ttm_bo_device_release(&bochs->ttm.bdev);
217 bochs_ttm_global_release(bochs);
218 bochs->ttm.initialized = false;
221 static void bochs_ttm_placement(struct bochs_bo *bo, int domain)
225 bo->placement.placement = bo->placements;
226 bo->placement.busy_placement = bo->placements;
227 if (domain & TTM_PL_FLAG_VRAM) {
228 bo->placements[c++].flags = TTM_PL_FLAG_WC
229 | TTM_PL_FLAG_UNCACHED
232 if (domain & TTM_PL_FLAG_SYSTEM) {
233 bo->placements[c++].flags = TTM_PL_MASK_CACHING
234 | TTM_PL_FLAG_SYSTEM;
237 bo->placements[c++].flags = TTM_PL_MASK_CACHING
238 | TTM_PL_FLAG_SYSTEM;
240 for (i = 0; i < c; ++i) {
241 bo->placements[i].fpfn = 0;
242 bo->placements[i].lpfn = 0;
244 bo->placement.num_placement = c;
245 bo->placement.num_busy_placement = c;
248 static inline u64 bochs_bo_gpu_offset(struct bochs_bo *bo)
250 return bo->bo.offset;
253 int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr)
255 struct ttm_operation_ctx ctx = { false, false };
261 *gpu_addr = bochs_bo_gpu_offset(bo);
265 bochs_ttm_placement(bo, pl_flag);
266 for (i = 0; i < bo->placement.num_placement; i++)
267 bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT;
268 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
274 *gpu_addr = bochs_bo_gpu_offset(bo);
278 int bochs_bo_unpin(struct bochs_bo *bo)
280 struct ttm_operation_ctx ctx = { false, false };
283 if (!bo->pin_count) {
284 DRM_ERROR("unpin bad %p\n", bo);
292 for (i = 0; i < bo->placement.num_placement; i++)
293 bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
294 ret = ttm_bo_validate(&bo->bo, &bo->placement, &ctx);
301 int bochs_mmap(struct file *filp, struct vm_area_struct *vma)
303 struct drm_file *file_priv;
304 struct bochs_device *bochs;
306 if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
309 file_priv = filp->private_data;
310 bochs = file_priv->minor->dev->dev_private;
311 return ttm_bo_mmap(filp, vma, &bochs->ttm.bdev);
314 /* ---------------------------------------------------------------------- */
316 static int bochs_bo_create(struct drm_device *dev, int size, int align,
317 uint32_t flags, struct bochs_bo **pbochsbo)
319 struct bochs_device *bochs = dev->dev_private;
320 struct bochs_bo *bochsbo;
324 bochsbo = kzalloc(sizeof(struct bochs_bo), GFP_KERNEL);
328 ret = drm_gem_object_init(dev, &bochsbo->gem, size);
334 bochsbo->bo.bdev = &bochs->ttm.bdev;
335 bochsbo->bo.bdev->dev_mapping = dev->anon_inode->i_mapping;
337 bochs_ttm_placement(bochsbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
339 acc_size = ttm_bo_dma_acc_size(&bochs->ttm.bdev, size,
340 sizeof(struct bochs_bo));
342 ret = ttm_bo_init(&bochs->ttm.bdev, &bochsbo->bo, size,
343 ttm_bo_type_device, &bochsbo->placement,
344 align >> PAGE_SHIFT, false, acc_size,
345 NULL, NULL, bochs_bo_ttm_destroy);
353 int bochs_gem_create(struct drm_device *dev, u32 size, bool iskernel,
354 struct drm_gem_object **obj)
356 struct bochs_bo *bochsbo;
361 size = PAGE_ALIGN(size);
365 ret = bochs_bo_create(dev, size, 0, 0, &bochsbo);
367 if (ret != -ERESTARTSYS)
368 DRM_ERROR("failed to allocate GEM object\n");
371 *obj = &bochsbo->gem;
375 int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
376 struct drm_mode_create_dumb *args)
378 struct drm_gem_object *gobj;
382 args->pitch = args->width * ((args->bpp + 7) / 8);
383 args->size = args->pitch * args->height;
385 ret = bochs_gem_create(dev, args->size, false,
390 ret = drm_gem_handle_create(file, gobj, &handle);
391 drm_gem_object_unreference_unlocked(gobj);
395 args->handle = handle;
399 static void bochs_bo_unref(struct bochs_bo **bo)
401 struct ttm_buffer_object *tbo;
411 void bochs_gem_free_object(struct drm_gem_object *obj)
413 struct bochs_bo *bochs_bo = gem_to_bochs_bo(obj);
415 bochs_bo_unref(&bochs_bo);
418 int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
419 uint32_t handle, uint64_t *offset)
421 struct drm_gem_object *obj;
424 obj = drm_gem_object_lookup(file, handle);
428 bo = gem_to_bochs_bo(obj);
429 *offset = bochs_bo_mmap_offset(bo);
431 drm_gem_object_unreference_unlocked(obj);