162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2013 Red Hat Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1262306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * Authors: Dave Airlie 2362306a36Sopenharmony_ci * Alon Levy 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#include <linux/iosys-map.h> 2762306a36Sopenharmony_ci#include <linux/io-mapping.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "qxl_drv.h" 3062306a36Sopenharmony_ci#include "qxl_object.h" 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic int __qxl_bo_pin(struct qxl_bo *bo); 3362306a36Sopenharmony_cistatic void __qxl_bo_unpin(struct qxl_bo *bo); 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct qxl_bo *bo; 3862306a36Sopenharmony_ci struct qxl_device *qdev; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci bo = to_qxl_bo(tbo); 4162306a36Sopenharmony_ci qdev = to_qxl(bo->tbo.base.dev); 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci qxl_surface_evict(qdev, bo, false); 4462306a36Sopenharmony_ci WARN_ON_ONCE(bo->map_count > 0); 4562306a36Sopenharmony_ci mutex_lock(&qdev->gem.mutex); 4662306a36Sopenharmony_ci list_del_init(&bo->list); 4762306a36Sopenharmony_ci mutex_unlock(&qdev->gem.mutex); 4862306a36Sopenharmony_ci drm_gem_object_release(&bo->tbo.base); 4962306a36Sopenharmony_ci kfree(bo); 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cibool qxl_ttm_bo_is_qxl_bo(struct ttm_buffer_object *bo) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci if (bo->destroy == &qxl_ttm_bo_destroy) 5562306a36Sopenharmony_ci return true; 5662306a36Sopenharmony_ci return false; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_civoid qxl_ttm_placement_from_domain(struct qxl_bo *qbo, u32 domain) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci u32 c = 0; 6262306a36Sopenharmony_ci u32 pflag = 0; 6362306a36Sopenharmony_ci unsigned int i; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (qbo->tbo.base.size <= PAGE_SIZE) 6662306a36Sopenharmony_ci pflag |= TTM_PL_FLAG_TOPDOWN; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci qbo->placement.placement = qbo->placements; 6962306a36Sopenharmony_ci qbo->placement.busy_placement = qbo->placements; 7062306a36Sopenharmony_ci if (domain == QXL_GEM_DOMAIN_VRAM) { 7162306a36Sopenharmony_ci qbo->placements[c].mem_type = TTM_PL_VRAM; 7262306a36Sopenharmony_ci qbo->placements[c++].flags = pflag; 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci if (domain == QXL_GEM_DOMAIN_SURFACE) { 7562306a36Sopenharmony_ci qbo->placements[c].mem_type = TTM_PL_PRIV; 7662306a36Sopenharmony_ci qbo->placements[c++].flags = pflag; 7762306a36Sopenharmony_ci qbo->placements[c].mem_type = TTM_PL_VRAM; 7862306a36Sopenharmony_ci qbo->placements[c++].flags = pflag; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci if (domain == QXL_GEM_DOMAIN_CPU) { 8162306a36Sopenharmony_ci qbo->placements[c].mem_type = TTM_PL_SYSTEM; 8262306a36Sopenharmony_ci qbo->placements[c++].flags = pflag; 8362306a36Sopenharmony_ci } 8462306a36Sopenharmony_ci if (!c) { 8562306a36Sopenharmony_ci qbo->placements[c].mem_type = TTM_PL_SYSTEM; 8662306a36Sopenharmony_ci qbo->placements[c++].flags = 0; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci qbo->placement.num_placement = c; 8962306a36Sopenharmony_ci qbo->placement.num_busy_placement = c; 9062306a36Sopenharmony_ci for (i = 0; i < c; ++i) { 9162306a36Sopenharmony_ci qbo->placements[i].fpfn = 0; 9262306a36Sopenharmony_ci qbo->placements[i].lpfn = 0; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_cistatic const struct drm_gem_object_funcs qxl_object_funcs = { 9762306a36Sopenharmony_ci .free = qxl_gem_object_free, 9862306a36Sopenharmony_ci .open = qxl_gem_object_open, 9962306a36Sopenharmony_ci .close = qxl_gem_object_close, 10062306a36Sopenharmony_ci .pin = qxl_gem_prime_pin, 10162306a36Sopenharmony_ci .unpin = qxl_gem_prime_unpin, 10262306a36Sopenharmony_ci .get_sg_table = qxl_gem_prime_get_sg_table, 10362306a36Sopenharmony_ci .vmap = qxl_gem_prime_vmap, 10462306a36Sopenharmony_ci .vunmap = qxl_gem_prime_vunmap, 10562306a36Sopenharmony_ci .mmap = drm_gem_ttm_mmap, 10662306a36Sopenharmony_ci .print_info = drm_gem_ttm_print_info, 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciint qxl_bo_create(struct qxl_device *qdev, unsigned long size, 11062306a36Sopenharmony_ci bool kernel, bool pinned, u32 domain, u32 priority, 11162306a36Sopenharmony_ci struct qxl_surface *surf, 11262306a36Sopenharmony_ci struct qxl_bo **bo_ptr) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct ttm_operation_ctx ctx = { !kernel, false }; 11562306a36Sopenharmony_ci struct qxl_bo *bo; 11662306a36Sopenharmony_ci enum ttm_bo_type type; 11762306a36Sopenharmony_ci int r; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (kernel) 12062306a36Sopenharmony_ci type = ttm_bo_type_kernel; 12162306a36Sopenharmony_ci else 12262306a36Sopenharmony_ci type = ttm_bo_type_device; 12362306a36Sopenharmony_ci *bo_ptr = NULL; 12462306a36Sopenharmony_ci bo = kzalloc(sizeof(struct qxl_bo), GFP_KERNEL); 12562306a36Sopenharmony_ci if (bo == NULL) 12662306a36Sopenharmony_ci return -ENOMEM; 12762306a36Sopenharmony_ci size = roundup(size, PAGE_SIZE); 12862306a36Sopenharmony_ci r = drm_gem_object_init(&qdev->ddev, &bo->tbo.base, size); 12962306a36Sopenharmony_ci if (unlikely(r)) { 13062306a36Sopenharmony_ci kfree(bo); 13162306a36Sopenharmony_ci return r; 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci bo->tbo.base.funcs = &qxl_object_funcs; 13462306a36Sopenharmony_ci bo->type = domain; 13562306a36Sopenharmony_ci bo->surface_id = 0; 13662306a36Sopenharmony_ci INIT_LIST_HEAD(&bo->list); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (surf) 13962306a36Sopenharmony_ci bo->surf = *surf; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci qxl_ttm_placement_from_domain(bo, domain); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci bo->tbo.priority = priority; 14462306a36Sopenharmony_ci r = ttm_bo_init_reserved(&qdev->mman.bdev, &bo->tbo, type, 14562306a36Sopenharmony_ci &bo->placement, 0, &ctx, NULL, NULL, 14662306a36Sopenharmony_ci &qxl_ttm_bo_destroy); 14762306a36Sopenharmony_ci if (unlikely(r != 0)) { 14862306a36Sopenharmony_ci if (r != -ERESTARTSYS) 14962306a36Sopenharmony_ci dev_err(qdev->ddev.dev, 15062306a36Sopenharmony_ci "object_init failed for (%lu, 0x%08X)\n", 15162306a36Sopenharmony_ci size, domain); 15262306a36Sopenharmony_ci return r; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci if (pinned) 15562306a36Sopenharmony_ci ttm_bo_pin(&bo->tbo); 15662306a36Sopenharmony_ci ttm_bo_unreserve(&bo->tbo); 15762306a36Sopenharmony_ci *bo_ptr = bo; 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ciint qxl_bo_vmap_locked(struct qxl_bo *bo, struct iosys_map *map) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci int r; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci dma_resv_assert_held(bo->tbo.base.resv); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci if (bo->kptr) { 16862306a36Sopenharmony_ci bo->map_count++; 16962306a36Sopenharmony_ci goto out; 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci r = __qxl_bo_pin(bo); 17362306a36Sopenharmony_ci if (r) 17462306a36Sopenharmony_ci return r; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci r = ttm_bo_vmap(&bo->tbo, &bo->map); 17762306a36Sopenharmony_ci if (r) { 17862306a36Sopenharmony_ci __qxl_bo_unpin(bo); 17962306a36Sopenharmony_ci return r; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci bo->map_count = 1; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* TODO: Remove kptr in favor of map everywhere. */ 18462306a36Sopenharmony_ci if (bo->map.is_iomem) 18562306a36Sopenharmony_ci bo->kptr = (void *)bo->map.vaddr_iomem; 18662306a36Sopenharmony_ci else 18762306a36Sopenharmony_ci bo->kptr = bo->map.vaddr; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ciout: 19062306a36Sopenharmony_ci *map = bo->map; 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci} 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ciint qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci int r; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci r = qxl_bo_reserve(bo); 19962306a36Sopenharmony_ci if (r) 20062306a36Sopenharmony_ci return r; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci r = qxl_bo_vmap_locked(bo, map); 20362306a36Sopenharmony_ci qxl_bo_unreserve(bo); 20462306a36Sopenharmony_ci return r; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_civoid *qxl_bo_kmap_atomic_page(struct qxl_device *qdev, 20862306a36Sopenharmony_ci struct qxl_bo *bo, int page_offset) 20962306a36Sopenharmony_ci{ 21062306a36Sopenharmony_ci unsigned long offset; 21162306a36Sopenharmony_ci void *rptr; 21262306a36Sopenharmony_ci int ret; 21362306a36Sopenharmony_ci struct io_mapping *map; 21462306a36Sopenharmony_ci struct iosys_map bo_map; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (bo->tbo.resource->mem_type == TTM_PL_VRAM) 21762306a36Sopenharmony_ci map = qdev->vram_mapping; 21862306a36Sopenharmony_ci else if (bo->tbo.resource->mem_type == TTM_PL_PRIV) 21962306a36Sopenharmony_ci map = qdev->surface_mapping; 22062306a36Sopenharmony_ci else 22162306a36Sopenharmony_ci goto fallback; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci offset = bo->tbo.resource->start << PAGE_SHIFT; 22462306a36Sopenharmony_ci return io_mapping_map_atomic_wc(map, offset + page_offset); 22562306a36Sopenharmony_cifallback: 22662306a36Sopenharmony_ci if (bo->kptr) { 22762306a36Sopenharmony_ci rptr = bo->kptr + (page_offset * PAGE_SIZE); 22862306a36Sopenharmony_ci return rptr; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci ret = qxl_bo_vmap_locked(bo, &bo_map); 23262306a36Sopenharmony_ci if (ret) 23362306a36Sopenharmony_ci return NULL; 23462306a36Sopenharmony_ci rptr = bo_map.vaddr; /* TODO: Use mapping abstraction properly */ 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci rptr += page_offset * PAGE_SIZE; 23762306a36Sopenharmony_ci return rptr; 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_civoid qxl_bo_vunmap_locked(struct qxl_bo *bo) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci dma_resv_assert_held(bo->tbo.base.resv); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci if (bo->kptr == NULL) 24562306a36Sopenharmony_ci return; 24662306a36Sopenharmony_ci bo->map_count--; 24762306a36Sopenharmony_ci if (bo->map_count > 0) 24862306a36Sopenharmony_ci return; 24962306a36Sopenharmony_ci bo->kptr = NULL; 25062306a36Sopenharmony_ci ttm_bo_vunmap(&bo->tbo, &bo->map); 25162306a36Sopenharmony_ci __qxl_bo_unpin(bo); 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ciint qxl_bo_vunmap(struct qxl_bo *bo) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci int r; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci r = qxl_bo_reserve(bo); 25962306a36Sopenharmony_ci if (r) 26062306a36Sopenharmony_ci return r; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci qxl_bo_vunmap_locked(bo); 26362306a36Sopenharmony_ci qxl_bo_unreserve(bo); 26462306a36Sopenharmony_ci return 0; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_civoid qxl_bo_kunmap_atomic_page(struct qxl_device *qdev, 26862306a36Sopenharmony_ci struct qxl_bo *bo, void *pmap) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci if ((bo->tbo.resource->mem_type != TTM_PL_VRAM) && 27162306a36Sopenharmony_ci (bo->tbo.resource->mem_type != TTM_PL_PRIV)) 27262306a36Sopenharmony_ci goto fallback; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci io_mapping_unmap_atomic(pmap); 27562306a36Sopenharmony_ci return; 27662306a36Sopenharmony_ci fallback: 27762306a36Sopenharmony_ci qxl_bo_vunmap_locked(bo); 27862306a36Sopenharmony_ci} 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_civoid qxl_bo_unref(struct qxl_bo **bo) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci if ((*bo) == NULL) 28362306a36Sopenharmony_ci return; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci drm_gem_object_put(&(*bo)->tbo.base); 28662306a36Sopenharmony_ci *bo = NULL; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistruct qxl_bo *qxl_bo_ref(struct qxl_bo *bo) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci drm_gem_object_get(&bo->tbo.base); 29262306a36Sopenharmony_ci return bo; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int __qxl_bo_pin(struct qxl_bo *bo) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci struct ttm_operation_ctx ctx = { false, false }; 29862306a36Sopenharmony_ci struct drm_device *ddev = bo->tbo.base.dev; 29962306a36Sopenharmony_ci int r; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci if (bo->tbo.pin_count) { 30262306a36Sopenharmony_ci ttm_bo_pin(&bo->tbo); 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci qxl_ttm_placement_from_domain(bo, bo->type); 30662306a36Sopenharmony_ci r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); 30762306a36Sopenharmony_ci if (likely(r == 0)) 30862306a36Sopenharmony_ci ttm_bo_pin(&bo->tbo); 30962306a36Sopenharmony_ci if (unlikely(r != 0)) 31062306a36Sopenharmony_ci dev_err(ddev->dev, "%p pin failed\n", bo); 31162306a36Sopenharmony_ci return r; 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic void __qxl_bo_unpin(struct qxl_bo *bo) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci ttm_bo_unpin(&bo->tbo); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/* 32062306a36Sopenharmony_ci * Reserve the BO before pinning the object. If the BO was reserved 32162306a36Sopenharmony_ci * beforehand, use the internal version directly __qxl_bo_pin. 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ciint qxl_bo_pin(struct qxl_bo *bo) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci int r; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci r = qxl_bo_reserve(bo); 32962306a36Sopenharmony_ci if (r) 33062306a36Sopenharmony_ci return r; 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci r = __qxl_bo_pin(bo); 33362306a36Sopenharmony_ci qxl_bo_unreserve(bo); 33462306a36Sopenharmony_ci return r; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* 33862306a36Sopenharmony_ci * Reserve the BO before pinning the object. If the BO was reserved 33962306a36Sopenharmony_ci * beforehand, use the internal version directly __qxl_bo_unpin. 34062306a36Sopenharmony_ci * 34162306a36Sopenharmony_ci */ 34262306a36Sopenharmony_ciint qxl_bo_unpin(struct qxl_bo *bo) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci int r; 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci r = qxl_bo_reserve(bo); 34762306a36Sopenharmony_ci if (r) 34862306a36Sopenharmony_ci return r; 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci __qxl_bo_unpin(bo); 35162306a36Sopenharmony_ci qxl_bo_unreserve(bo); 35262306a36Sopenharmony_ci return 0; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_civoid qxl_bo_force_delete(struct qxl_device *qdev) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci struct qxl_bo *bo, *n; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if (list_empty(&qdev->gem.objects)) 36062306a36Sopenharmony_ci return; 36162306a36Sopenharmony_ci dev_err(qdev->ddev.dev, "Userspace still has active objects !\n"); 36262306a36Sopenharmony_ci list_for_each_entry_safe(bo, n, &qdev->gem.objects, list) { 36362306a36Sopenharmony_ci dev_err(qdev->ddev.dev, "%p %p %lu %lu force free\n", 36462306a36Sopenharmony_ci &bo->tbo.base, bo, (unsigned long)bo->tbo.base.size, 36562306a36Sopenharmony_ci *((unsigned long *)&bo->tbo.base.refcount)); 36662306a36Sopenharmony_ci mutex_lock(&qdev->gem.mutex); 36762306a36Sopenharmony_ci list_del_init(&bo->list); 36862306a36Sopenharmony_ci mutex_unlock(&qdev->gem.mutex); 36962306a36Sopenharmony_ci /* this should unref the ttm bo */ 37062306a36Sopenharmony_ci drm_gem_object_put(&bo->tbo.base); 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ciint qxl_bo_init(struct qxl_device *qdev) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci return qxl_ttm_init(qdev); 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_civoid qxl_bo_fini(struct qxl_device *qdev) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci qxl_ttm_fini(qdev); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ciint qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci int ret; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci if (bo->type == QXL_GEM_DOMAIN_SURFACE && bo->surface_id == 0) { 38962306a36Sopenharmony_ci /* allocate a surface id for this surface now */ 39062306a36Sopenharmony_ci ret = qxl_surface_id_alloc(qdev, bo); 39162306a36Sopenharmony_ci if (ret) 39262306a36Sopenharmony_ci return ret; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci ret = qxl_hw_surface_alloc(qdev, bo); 39562306a36Sopenharmony_ci if (ret) 39662306a36Sopenharmony_ci return ret; 39762306a36Sopenharmony_ci } 39862306a36Sopenharmony_ci return 0; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ciint qxl_surf_evict(struct qxl_device *qdev) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci struct ttm_resource_manager *man; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci man = ttm_manager_type(&qdev->mman.bdev, TTM_PL_PRIV); 40662306a36Sopenharmony_ci return ttm_resource_manager_evict_all(&qdev->mman.bdev, man); 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ciint qxl_vram_evict(struct qxl_device *qdev) 41062306a36Sopenharmony_ci{ 41162306a36Sopenharmony_ci struct ttm_resource_manager *man; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci man = ttm_manager_type(&qdev->mman.bdev, TTM_PL_VRAM); 41462306a36Sopenharmony_ci return ttm_resource_manager_evict_all(&qdev->mman.bdev, man); 41562306a36Sopenharmony_ci} 416