162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2020 Advanced Micro Devices, 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: Christian König 2362306a36Sopenharmony_ci */ 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include <linux/iosys-map.h> 2662306a36Sopenharmony_ci#include <linux/io-mapping.h> 2762306a36Sopenharmony_ci#include <linux/scatterlist.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <drm/ttm/ttm_bo.h> 3062306a36Sopenharmony_ci#include <drm/ttm/ttm_placement.h> 3162306a36Sopenharmony_ci#include <drm/ttm/ttm_resource.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/** 3462306a36Sopenharmony_ci * ttm_lru_bulk_move_init - initialize a bulk move structure 3562306a36Sopenharmony_ci * @bulk: the structure to init 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * For now just memset the structure to zero. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_civoid ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci memset(bulk, 0, sizeof(*bulk)); 4262306a36Sopenharmony_ci} 4362306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_lru_bulk_move_init); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/** 4662306a36Sopenharmony_ci * ttm_lru_bulk_move_tail - bulk move range of resources to the LRU tail. 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * @bulk: bulk move structure 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that 5162306a36Sopenharmony_ci * resource order never changes. Should be called with &ttm_device.lru_lock held. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_civoid ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci unsigned i, j; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci for (i = 0; i < TTM_NUM_MEM_TYPES; ++i) { 5862306a36Sopenharmony_ci for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { 5962306a36Sopenharmony_ci struct ttm_lru_bulk_move_pos *pos = &bulk->pos[i][j]; 6062306a36Sopenharmony_ci struct ttm_resource_manager *man; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci if (!pos->first) 6362306a36Sopenharmony_ci continue; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci lockdep_assert_held(&pos->first->bo->bdev->lru_lock); 6662306a36Sopenharmony_ci dma_resv_assert_held(pos->first->bo->base.resv); 6762306a36Sopenharmony_ci dma_resv_assert_held(pos->last->bo->base.resv); 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci man = ttm_manager_type(pos->first->bo->bdev, i); 7062306a36Sopenharmony_ci list_bulk_move_tail(&man->lru[j], &pos->first->lru, 7162306a36Sopenharmony_ci &pos->last->lru); 7262306a36Sopenharmony_ci } 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_lru_bulk_move_tail); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* Return the bulk move pos object for this resource */ 7862306a36Sopenharmony_cistatic struct ttm_lru_bulk_move_pos * 7962306a36Sopenharmony_cittm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res) 8062306a36Sopenharmony_ci{ 8162306a36Sopenharmony_ci return &bulk->pos[res->mem_type][res->bo->priority]; 8262306a36Sopenharmony_ci} 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/* Move the resource to the tail of the bulk move range */ 8562306a36Sopenharmony_cistatic void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos, 8662306a36Sopenharmony_ci struct ttm_resource *res) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci if (pos->last != res) { 8962306a36Sopenharmony_ci if (pos->first == res) 9062306a36Sopenharmony_ci pos->first = list_next_entry(res, lru); 9162306a36Sopenharmony_ci list_move(&res->lru, &pos->last->lru); 9262306a36Sopenharmony_ci pos->last = res; 9362306a36Sopenharmony_ci } 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* Add the resource to a bulk_move cursor */ 9762306a36Sopenharmony_cistatic void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk, 9862306a36Sopenharmony_ci struct ttm_resource *res) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (!pos->first) { 10362306a36Sopenharmony_ci pos->first = res; 10462306a36Sopenharmony_ci pos->last = res; 10562306a36Sopenharmony_ci } else { 10662306a36Sopenharmony_ci ttm_lru_bulk_move_pos_tail(pos, res); 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* Remove the resource from a bulk_move range */ 11162306a36Sopenharmony_cistatic void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, 11262306a36Sopenharmony_ci struct ttm_resource *res) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (unlikely(WARN_ON(!pos->first || !pos->last) || 11762306a36Sopenharmony_ci (pos->first == res && pos->last == res))) { 11862306a36Sopenharmony_ci pos->first = NULL; 11962306a36Sopenharmony_ci pos->last = NULL; 12062306a36Sopenharmony_ci } else if (pos->first == res) { 12162306a36Sopenharmony_ci pos->first = list_next_entry(res, lru); 12262306a36Sopenharmony_ci } else if (pos->last == res) { 12362306a36Sopenharmony_ci pos->last = list_prev_entry(res, lru); 12462306a36Sopenharmony_ci } else { 12562306a36Sopenharmony_ci list_move(&res->lru, &pos->last->lru); 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* Add the resource to a bulk move if the BO is configured for it */ 13062306a36Sopenharmony_civoid ttm_resource_add_bulk_move(struct ttm_resource *res, 13162306a36Sopenharmony_ci struct ttm_buffer_object *bo) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci if (bo->bulk_move && !bo->pin_count) 13462306a36Sopenharmony_ci ttm_lru_bulk_move_add(bo->bulk_move, res); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* Remove the resource from a bulk move if the BO is configured for it */ 13862306a36Sopenharmony_civoid ttm_resource_del_bulk_move(struct ttm_resource *res, 13962306a36Sopenharmony_ci struct ttm_buffer_object *bo) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci if (bo->bulk_move && !bo->pin_count) 14262306a36Sopenharmony_ci ttm_lru_bulk_move_del(bo->bulk_move, res); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* Move a resource to the LRU or bulk tail */ 14662306a36Sopenharmony_civoid ttm_resource_move_to_lru_tail(struct ttm_resource *res) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci struct ttm_buffer_object *bo = res->bo; 14962306a36Sopenharmony_ci struct ttm_device *bdev = bo->bdev; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci lockdep_assert_held(&bo->bdev->lru_lock); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (bo->pin_count) { 15462306a36Sopenharmony_ci list_move_tail(&res->lru, &bdev->pinned); 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci } else if (bo->bulk_move) { 15762306a36Sopenharmony_ci struct ttm_lru_bulk_move_pos *pos = 15862306a36Sopenharmony_ci ttm_lru_bulk_move_pos(bo->bulk_move, res); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci ttm_lru_bulk_move_pos_tail(pos, res); 16162306a36Sopenharmony_ci } else { 16262306a36Sopenharmony_ci struct ttm_resource_manager *man; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci man = ttm_manager_type(bdev, res->mem_type); 16562306a36Sopenharmony_ci list_move_tail(&res->lru, &man->lru[bo->priority]); 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/** 17062306a36Sopenharmony_ci * ttm_resource_init - resource object constructure 17162306a36Sopenharmony_ci * @bo: buffer object this resources is allocated for 17262306a36Sopenharmony_ci * @place: placement of the resource 17362306a36Sopenharmony_ci * @res: the resource object to inistilize 17462306a36Sopenharmony_ci * 17562306a36Sopenharmony_ci * Initialize a new resource object. Counterpart of ttm_resource_fini(). 17662306a36Sopenharmony_ci */ 17762306a36Sopenharmony_civoid ttm_resource_init(struct ttm_buffer_object *bo, 17862306a36Sopenharmony_ci const struct ttm_place *place, 17962306a36Sopenharmony_ci struct ttm_resource *res) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci struct ttm_resource_manager *man; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci res->start = 0; 18462306a36Sopenharmony_ci res->size = bo->base.size; 18562306a36Sopenharmony_ci res->mem_type = place->mem_type; 18662306a36Sopenharmony_ci res->placement = place->flags; 18762306a36Sopenharmony_ci res->bus.addr = NULL; 18862306a36Sopenharmony_ci res->bus.offset = 0; 18962306a36Sopenharmony_ci res->bus.is_iomem = false; 19062306a36Sopenharmony_ci res->bus.caching = ttm_cached; 19162306a36Sopenharmony_ci res->bo = bo; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci man = ttm_manager_type(bo->bdev, place->mem_type); 19462306a36Sopenharmony_ci spin_lock(&bo->bdev->lru_lock); 19562306a36Sopenharmony_ci if (bo->pin_count) 19662306a36Sopenharmony_ci list_add_tail(&res->lru, &bo->bdev->pinned); 19762306a36Sopenharmony_ci else 19862306a36Sopenharmony_ci list_add_tail(&res->lru, &man->lru[bo->priority]); 19962306a36Sopenharmony_ci man->usage += res->size; 20062306a36Sopenharmony_ci spin_unlock(&bo->bdev->lru_lock); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_init); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci/** 20562306a36Sopenharmony_ci * ttm_resource_fini - resource destructor 20662306a36Sopenharmony_ci * @man: the resource manager this resource belongs to 20762306a36Sopenharmony_ci * @res: the resource to clean up 20862306a36Sopenharmony_ci * 20962306a36Sopenharmony_ci * Should be used by resource manager backends to clean up the TTM resource 21062306a36Sopenharmony_ci * objects before freeing the underlying structure. Makes sure the resource is 21162306a36Sopenharmony_ci * removed from the LRU before destruction. 21262306a36Sopenharmony_ci * Counterpart of ttm_resource_init(). 21362306a36Sopenharmony_ci */ 21462306a36Sopenharmony_civoid ttm_resource_fini(struct ttm_resource_manager *man, 21562306a36Sopenharmony_ci struct ttm_resource *res) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct ttm_device *bdev = man->bdev; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci spin_lock(&bdev->lru_lock); 22062306a36Sopenharmony_ci list_del_init(&res->lru); 22162306a36Sopenharmony_ci man->usage -= res->size; 22262306a36Sopenharmony_ci spin_unlock(&bdev->lru_lock); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_fini); 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ciint ttm_resource_alloc(struct ttm_buffer_object *bo, 22762306a36Sopenharmony_ci const struct ttm_place *place, 22862306a36Sopenharmony_ci struct ttm_resource **res_ptr) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct ttm_resource_manager *man = 23162306a36Sopenharmony_ci ttm_manager_type(bo->bdev, place->mem_type); 23262306a36Sopenharmony_ci int ret; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci ret = man->func->alloc(man, bo, place, res_ptr); 23562306a36Sopenharmony_ci if (ret) 23662306a36Sopenharmony_ci return ret; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci spin_lock(&bo->bdev->lru_lock); 23962306a36Sopenharmony_ci ttm_resource_add_bulk_move(*res_ptr, bo); 24062306a36Sopenharmony_ci spin_unlock(&bo->bdev->lru_lock); 24162306a36Sopenharmony_ci return 0; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_civoid ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci struct ttm_resource_manager *man; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (!*res) 24962306a36Sopenharmony_ci return; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci spin_lock(&bo->bdev->lru_lock); 25262306a36Sopenharmony_ci ttm_resource_del_bulk_move(*res, bo); 25362306a36Sopenharmony_ci spin_unlock(&bo->bdev->lru_lock); 25462306a36Sopenharmony_ci man = ttm_manager_type(bo->bdev, (*res)->mem_type); 25562306a36Sopenharmony_ci man->func->free(man, *res); 25662306a36Sopenharmony_ci *res = NULL; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_free); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci/** 26162306a36Sopenharmony_ci * ttm_resource_intersects - test for intersection 26262306a36Sopenharmony_ci * 26362306a36Sopenharmony_ci * @bdev: TTM device structure 26462306a36Sopenharmony_ci * @res: The resource to test 26562306a36Sopenharmony_ci * @place: The placement to test 26662306a36Sopenharmony_ci * @size: How many bytes the new allocation needs. 26762306a36Sopenharmony_ci * 26862306a36Sopenharmony_ci * Test if @res intersects with @place and @size. Used for testing if evictions 26962306a36Sopenharmony_ci * are valueable or not. 27062306a36Sopenharmony_ci * 27162306a36Sopenharmony_ci * Returns true if the res placement intersects with @place and @size. 27262306a36Sopenharmony_ci */ 27362306a36Sopenharmony_cibool ttm_resource_intersects(struct ttm_device *bdev, 27462306a36Sopenharmony_ci struct ttm_resource *res, 27562306a36Sopenharmony_ci const struct ttm_place *place, 27662306a36Sopenharmony_ci size_t size) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct ttm_resource_manager *man; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci if (!res) 28162306a36Sopenharmony_ci return false; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci man = ttm_manager_type(bdev, res->mem_type); 28462306a36Sopenharmony_ci if (!place || !man->func->intersects) 28562306a36Sopenharmony_ci return true; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci return man->func->intersects(man, res, place, size); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci/** 29162306a36Sopenharmony_ci * ttm_resource_compatible - test for compatibility 29262306a36Sopenharmony_ci * 29362306a36Sopenharmony_ci * @bdev: TTM device structure 29462306a36Sopenharmony_ci * @res: The resource to test 29562306a36Sopenharmony_ci * @place: The placement to test 29662306a36Sopenharmony_ci * @size: How many bytes the new allocation needs. 29762306a36Sopenharmony_ci * 29862306a36Sopenharmony_ci * Test if @res compatible with @place and @size. 29962306a36Sopenharmony_ci * 30062306a36Sopenharmony_ci * Returns true if the res placement compatible with @place and @size. 30162306a36Sopenharmony_ci */ 30262306a36Sopenharmony_cibool ttm_resource_compatible(struct ttm_device *bdev, 30362306a36Sopenharmony_ci struct ttm_resource *res, 30462306a36Sopenharmony_ci const struct ttm_place *place, 30562306a36Sopenharmony_ci size_t size) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci struct ttm_resource_manager *man; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (!res || !place) 31062306a36Sopenharmony_ci return false; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci man = ttm_manager_type(bdev, res->mem_type); 31362306a36Sopenharmony_ci if (!man->func->compatible) 31462306a36Sopenharmony_ci return true; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return man->func->compatible(man, res, place, size); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistatic bool ttm_resource_places_compat(struct ttm_resource *res, 32062306a36Sopenharmony_ci const struct ttm_place *places, 32162306a36Sopenharmony_ci unsigned num_placement) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci struct ttm_buffer_object *bo = res->bo; 32462306a36Sopenharmony_ci struct ttm_device *bdev = bo->bdev; 32562306a36Sopenharmony_ci unsigned i; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (res->placement & TTM_PL_FLAG_TEMPORARY) 32862306a36Sopenharmony_ci return false; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci for (i = 0; i < num_placement; i++) { 33162306a36Sopenharmony_ci const struct ttm_place *heap = &places[i]; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (!ttm_resource_compatible(bdev, res, heap, bo->base.size)) 33462306a36Sopenharmony_ci continue; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if ((res->mem_type == heap->mem_type) && 33762306a36Sopenharmony_ci (!(heap->flags & TTM_PL_FLAG_CONTIGUOUS) || 33862306a36Sopenharmony_ci (res->placement & TTM_PL_FLAG_CONTIGUOUS))) 33962306a36Sopenharmony_ci return true; 34062306a36Sopenharmony_ci } 34162306a36Sopenharmony_ci return false; 34262306a36Sopenharmony_ci} 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci/** 34562306a36Sopenharmony_ci * ttm_resource_compat - check if resource is compatible with placement 34662306a36Sopenharmony_ci * 34762306a36Sopenharmony_ci * @res: the resource to check 34862306a36Sopenharmony_ci * @placement: the placement to check against 34962306a36Sopenharmony_ci * 35062306a36Sopenharmony_ci * Returns true if the placement is compatible. 35162306a36Sopenharmony_ci */ 35262306a36Sopenharmony_cibool ttm_resource_compat(struct ttm_resource *res, 35362306a36Sopenharmony_ci struct ttm_placement *placement) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci if (ttm_resource_places_compat(res, placement->placement, 35662306a36Sopenharmony_ci placement->num_placement)) 35762306a36Sopenharmony_ci return true; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci if ((placement->busy_placement != placement->placement || 36062306a36Sopenharmony_ci placement->num_busy_placement > placement->num_placement) && 36162306a36Sopenharmony_ci ttm_resource_places_compat(res, placement->busy_placement, 36262306a36Sopenharmony_ci placement->num_busy_placement)) 36362306a36Sopenharmony_ci return true; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci return false; 36662306a36Sopenharmony_ci} 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_civoid ttm_resource_set_bo(struct ttm_resource *res, 36962306a36Sopenharmony_ci struct ttm_buffer_object *bo) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci spin_lock(&bo->bdev->lru_lock); 37262306a36Sopenharmony_ci res->bo = bo; 37362306a36Sopenharmony_ci spin_unlock(&bo->bdev->lru_lock); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/** 37762306a36Sopenharmony_ci * ttm_resource_manager_init 37862306a36Sopenharmony_ci * 37962306a36Sopenharmony_ci * @man: memory manager object to init 38062306a36Sopenharmony_ci * @bdev: ttm device this manager belongs to 38162306a36Sopenharmony_ci * @size: size of managed resources in arbitrary units 38262306a36Sopenharmony_ci * 38362306a36Sopenharmony_ci * Initialise core parts of a manager object. 38462306a36Sopenharmony_ci */ 38562306a36Sopenharmony_civoid ttm_resource_manager_init(struct ttm_resource_manager *man, 38662306a36Sopenharmony_ci struct ttm_device *bdev, 38762306a36Sopenharmony_ci uint64_t size) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci unsigned i; 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci spin_lock_init(&man->move_lock); 39262306a36Sopenharmony_ci man->bdev = bdev; 39362306a36Sopenharmony_ci man->size = size; 39462306a36Sopenharmony_ci man->usage = 0; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) 39762306a36Sopenharmony_ci INIT_LIST_HEAD(&man->lru[i]); 39862306a36Sopenharmony_ci man->move = NULL; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_manager_init); 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci/* 40362306a36Sopenharmony_ci * ttm_resource_manager_evict_all 40462306a36Sopenharmony_ci * 40562306a36Sopenharmony_ci * @bdev - device to use 40662306a36Sopenharmony_ci * @man - manager to use 40762306a36Sopenharmony_ci * 40862306a36Sopenharmony_ci * Evict all the objects out of a memory manager until it is empty. 40962306a36Sopenharmony_ci * Part of memory manager cleanup sequence. 41062306a36Sopenharmony_ci */ 41162306a36Sopenharmony_ciint ttm_resource_manager_evict_all(struct ttm_device *bdev, 41262306a36Sopenharmony_ci struct ttm_resource_manager *man) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci struct ttm_operation_ctx ctx = { 41562306a36Sopenharmony_ci .interruptible = false, 41662306a36Sopenharmony_ci .no_wait_gpu = false, 41762306a36Sopenharmony_ci .force_alloc = true 41862306a36Sopenharmony_ci }; 41962306a36Sopenharmony_ci struct dma_fence *fence; 42062306a36Sopenharmony_ci int ret; 42162306a36Sopenharmony_ci unsigned i; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci /* 42462306a36Sopenharmony_ci * Can't use standard list traversal since we're unlocking. 42562306a36Sopenharmony_ci */ 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci spin_lock(&bdev->lru_lock); 42862306a36Sopenharmony_ci for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { 42962306a36Sopenharmony_ci while (!list_empty(&man->lru[i])) { 43062306a36Sopenharmony_ci spin_unlock(&bdev->lru_lock); 43162306a36Sopenharmony_ci ret = ttm_mem_evict_first(bdev, man, NULL, &ctx, 43262306a36Sopenharmony_ci NULL); 43362306a36Sopenharmony_ci if (ret) 43462306a36Sopenharmony_ci return ret; 43562306a36Sopenharmony_ci spin_lock(&bdev->lru_lock); 43662306a36Sopenharmony_ci } 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci spin_unlock(&bdev->lru_lock); 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci spin_lock(&man->move_lock); 44162306a36Sopenharmony_ci fence = dma_fence_get(man->move); 44262306a36Sopenharmony_ci spin_unlock(&man->move_lock); 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci if (fence) { 44562306a36Sopenharmony_ci ret = dma_fence_wait(fence, false); 44662306a36Sopenharmony_ci dma_fence_put(fence); 44762306a36Sopenharmony_ci if (ret) 44862306a36Sopenharmony_ci return ret; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci return 0; 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_manager_evict_all); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci/** 45662306a36Sopenharmony_ci * ttm_resource_manager_usage 45762306a36Sopenharmony_ci * 45862306a36Sopenharmony_ci * @man: A memory manager object. 45962306a36Sopenharmony_ci * 46062306a36Sopenharmony_ci * Return how many resources are currently used. 46162306a36Sopenharmony_ci */ 46262306a36Sopenharmony_ciuint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci uint64_t usage; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci spin_lock(&man->bdev->lru_lock); 46762306a36Sopenharmony_ci usage = man->usage; 46862306a36Sopenharmony_ci spin_unlock(&man->bdev->lru_lock); 46962306a36Sopenharmony_ci return usage; 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_manager_usage); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci/** 47462306a36Sopenharmony_ci * ttm_resource_manager_debug 47562306a36Sopenharmony_ci * 47662306a36Sopenharmony_ci * @man: manager type to dump. 47762306a36Sopenharmony_ci * @p: printer to use for debug. 47862306a36Sopenharmony_ci */ 47962306a36Sopenharmony_civoid ttm_resource_manager_debug(struct ttm_resource_manager *man, 48062306a36Sopenharmony_ci struct drm_printer *p) 48162306a36Sopenharmony_ci{ 48262306a36Sopenharmony_ci drm_printf(p, " use_type: %d\n", man->use_type); 48362306a36Sopenharmony_ci drm_printf(p, " use_tt: %d\n", man->use_tt); 48462306a36Sopenharmony_ci drm_printf(p, " size: %llu\n", man->size); 48562306a36Sopenharmony_ci drm_printf(p, " usage: %llu\n", ttm_resource_manager_usage(man)); 48662306a36Sopenharmony_ci if (man->func->debug) 48762306a36Sopenharmony_ci man->func->debug(man, p); 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_manager_debug); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci/** 49262306a36Sopenharmony_ci * ttm_resource_manager_first 49362306a36Sopenharmony_ci * 49462306a36Sopenharmony_ci * @man: resource manager to iterate over 49562306a36Sopenharmony_ci * @cursor: cursor to record the position 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * Returns the first resource from the resource manager. 49862306a36Sopenharmony_ci */ 49962306a36Sopenharmony_cistruct ttm_resource * 50062306a36Sopenharmony_cittm_resource_manager_first(struct ttm_resource_manager *man, 50162306a36Sopenharmony_ci struct ttm_resource_cursor *cursor) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct ttm_resource *res; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci lockdep_assert_held(&man->bdev->lru_lock); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY; 50862306a36Sopenharmony_ci ++cursor->priority) 50962306a36Sopenharmony_ci list_for_each_entry(res, &man->lru[cursor->priority], lru) 51062306a36Sopenharmony_ci return res; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci return NULL; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_ci/** 51662306a36Sopenharmony_ci * ttm_resource_manager_next 51762306a36Sopenharmony_ci * 51862306a36Sopenharmony_ci * @man: resource manager to iterate over 51962306a36Sopenharmony_ci * @cursor: cursor to record the position 52062306a36Sopenharmony_ci * @res: the current resource pointer 52162306a36Sopenharmony_ci * 52262306a36Sopenharmony_ci * Returns the next resource from the resource manager. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_cistruct ttm_resource * 52562306a36Sopenharmony_cittm_resource_manager_next(struct ttm_resource_manager *man, 52662306a36Sopenharmony_ci struct ttm_resource_cursor *cursor, 52762306a36Sopenharmony_ci struct ttm_resource *res) 52862306a36Sopenharmony_ci{ 52962306a36Sopenharmony_ci lockdep_assert_held(&man->bdev->lru_lock); 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci list_for_each_entry_continue(res, &man->lru[cursor->priority], lru) 53262306a36Sopenharmony_ci return res; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY; 53562306a36Sopenharmony_ci ++cursor->priority) 53662306a36Sopenharmony_ci list_for_each_entry(res, &man->lru[cursor->priority], lru) 53762306a36Sopenharmony_ci return res; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci return NULL; 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter, 54362306a36Sopenharmony_ci struct iosys_map *dmap, 54462306a36Sopenharmony_ci pgoff_t i) 54562306a36Sopenharmony_ci{ 54662306a36Sopenharmony_ci struct ttm_kmap_iter_iomap *iter_io = 54762306a36Sopenharmony_ci container_of(iter, typeof(*iter_io), base); 54862306a36Sopenharmony_ci void __iomem *addr; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ciretry: 55162306a36Sopenharmony_ci while (i >= iter_io->cache.end) { 55262306a36Sopenharmony_ci iter_io->cache.sg = iter_io->cache.sg ? 55362306a36Sopenharmony_ci sg_next(iter_io->cache.sg) : iter_io->st->sgl; 55462306a36Sopenharmony_ci iter_io->cache.i = iter_io->cache.end; 55562306a36Sopenharmony_ci iter_io->cache.end += sg_dma_len(iter_io->cache.sg) >> 55662306a36Sopenharmony_ci PAGE_SHIFT; 55762306a36Sopenharmony_ci iter_io->cache.offs = sg_dma_address(iter_io->cache.sg) - 55862306a36Sopenharmony_ci iter_io->start; 55962306a36Sopenharmony_ci } 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci if (i < iter_io->cache.i) { 56262306a36Sopenharmony_ci iter_io->cache.end = 0; 56362306a36Sopenharmony_ci iter_io->cache.sg = NULL; 56462306a36Sopenharmony_ci goto retry; 56562306a36Sopenharmony_ci } 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci addr = io_mapping_map_local_wc(iter_io->iomap, iter_io->cache.offs + 56862306a36Sopenharmony_ci (((resource_size_t)i - iter_io->cache.i) 56962306a36Sopenharmony_ci << PAGE_SHIFT)); 57062306a36Sopenharmony_ci iosys_map_set_vaddr_iomem(dmap, addr); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistatic void ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter *iter, 57462306a36Sopenharmony_ci struct iosys_map *map) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci io_mapping_unmap_local(map->vaddr_iomem); 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic const struct ttm_kmap_iter_ops ttm_kmap_iter_io_ops = { 58062306a36Sopenharmony_ci .map_local = ttm_kmap_iter_iomap_map_local, 58162306a36Sopenharmony_ci .unmap_local = ttm_kmap_iter_iomap_unmap_local, 58262306a36Sopenharmony_ci .maps_tt = false, 58362306a36Sopenharmony_ci}; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci/** 58662306a36Sopenharmony_ci * ttm_kmap_iter_iomap_init - Initialize a struct ttm_kmap_iter_iomap 58762306a36Sopenharmony_ci * @iter_io: The struct ttm_kmap_iter_iomap to initialize. 58862306a36Sopenharmony_ci * @iomap: The struct io_mapping representing the underlying linear io_memory. 58962306a36Sopenharmony_ci * @st: sg_table into @iomap, representing the memory of the struct 59062306a36Sopenharmony_ci * ttm_resource. 59162306a36Sopenharmony_ci * @start: Offset that needs to be subtracted from @st to make 59262306a36Sopenharmony_ci * sg_dma_address(st->sgl) - @start == 0 for @iomap start. 59362306a36Sopenharmony_ci * 59462306a36Sopenharmony_ci * Return: Pointer to the embedded struct ttm_kmap_iter. 59562306a36Sopenharmony_ci */ 59662306a36Sopenharmony_cistruct ttm_kmap_iter * 59762306a36Sopenharmony_cittm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, 59862306a36Sopenharmony_ci struct io_mapping *iomap, 59962306a36Sopenharmony_ci struct sg_table *st, 60062306a36Sopenharmony_ci resource_size_t start) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci iter_io->base.ops = &ttm_kmap_iter_io_ops; 60362306a36Sopenharmony_ci iter_io->iomap = iomap; 60462306a36Sopenharmony_ci iter_io->st = st; 60562306a36Sopenharmony_ci iter_io->start = start; 60662306a36Sopenharmony_ci memset(&iter_io->cache, 0, sizeof(iter_io->cache)); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci return &iter_io->base; 60962306a36Sopenharmony_ci} 61062306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_kmap_iter_iomap_init); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci/** 61362306a36Sopenharmony_ci * DOC: Linear io iterator 61462306a36Sopenharmony_ci * 61562306a36Sopenharmony_ci * This code should die in the not too near future. Best would be if we could 61662306a36Sopenharmony_ci * make io-mapping use memremap for all io memory, and have memremap 61762306a36Sopenharmony_ci * implement a kmap_local functionality. We could then strip a huge amount of 61862306a36Sopenharmony_ci * code. These linear io iterators are implemented to mimic old functionality, 61962306a36Sopenharmony_ci * and they don't use kmap_local semantics at all internally. Rather ioremap or 62062306a36Sopenharmony_ci * friends, and at least on 32-bit they add global TLB flushes and points 62162306a36Sopenharmony_ci * of failure. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_cistatic void ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter *iter, 62562306a36Sopenharmony_ci struct iosys_map *dmap, 62662306a36Sopenharmony_ci pgoff_t i) 62762306a36Sopenharmony_ci{ 62862306a36Sopenharmony_ci struct ttm_kmap_iter_linear_io *iter_io = 62962306a36Sopenharmony_ci container_of(iter, typeof(*iter_io), base); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci *dmap = iter_io->dmap; 63262306a36Sopenharmony_ci iosys_map_incr(dmap, i * PAGE_SIZE); 63362306a36Sopenharmony_ci} 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_cistatic const struct ttm_kmap_iter_ops ttm_kmap_iter_linear_io_ops = { 63662306a36Sopenharmony_ci .map_local = ttm_kmap_iter_linear_io_map_local, 63762306a36Sopenharmony_ci .maps_tt = false, 63862306a36Sopenharmony_ci}; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci/** 64162306a36Sopenharmony_ci * ttm_kmap_iter_linear_io_init - Initialize an iterator for linear io memory 64262306a36Sopenharmony_ci * @iter_io: The iterator to initialize 64362306a36Sopenharmony_ci * @bdev: The TTM device 64462306a36Sopenharmony_ci * @mem: The ttm resource representing the iomap. 64562306a36Sopenharmony_ci * 64662306a36Sopenharmony_ci * This function is for internal TTM use only. It sets up a memcpy kmap iterator 64762306a36Sopenharmony_ci * pointing at a linear chunk of io memory. 64862306a36Sopenharmony_ci * 64962306a36Sopenharmony_ci * Return: A pointer to the embedded struct ttm_kmap_iter or error pointer on 65062306a36Sopenharmony_ci * failure. 65162306a36Sopenharmony_ci */ 65262306a36Sopenharmony_cistruct ttm_kmap_iter * 65362306a36Sopenharmony_cittm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, 65462306a36Sopenharmony_ci struct ttm_device *bdev, 65562306a36Sopenharmony_ci struct ttm_resource *mem) 65662306a36Sopenharmony_ci{ 65762306a36Sopenharmony_ci int ret; 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ret = ttm_mem_io_reserve(bdev, mem); 66062306a36Sopenharmony_ci if (ret) 66162306a36Sopenharmony_ci goto out_err; 66262306a36Sopenharmony_ci if (!mem->bus.is_iomem) { 66362306a36Sopenharmony_ci ret = -EINVAL; 66462306a36Sopenharmony_ci goto out_io_free; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci if (mem->bus.addr) { 66862306a36Sopenharmony_ci iosys_map_set_vaddr(&iter_io->dmap, mem->bus.addr); 66962306a36Sopenharmony_ci iter_io->needs_unmap = false; 67062306a36Sopenharmony_ci } else { 67162306a36Sopenharmony_ci iter_io->needs_unmap = true; 67262306a36Sopenharmony_ci memset(&iter_io->dmap, 0, sizeof(iter_io->dmap)); 67362306a36Sopenharmony_ci if (mem->bus.caching == ttm_write_combined) 67462306a36Sopenharmony_ci iosys_map_set_vaddr_iomem(&iter_io->dmap, 67562306a36Sopenharmony_ci ioremap_wc(mem->bus.offset, 67662306a36Sopenharmony_ci mem->size)); 67762306a36Sopenharmony_ci else if (mem->bus.caching == ttm_cached) 67862306a36Sopenharmony_ci iosys_map_set_vaddr(&iter_io->dmap, 67962306a36Sopenharmony_ci memremap(mem->bus.offset, mem->size, 68062306a36Sopenharmony_ci MEMREMAP_WB | 68162306a36Sopenharmony_ci MEMREMAP_WT | 68262306a36Sopenharmony_ci MEMREMAP_WC)); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci /* If uncached requested or if mapping cached or wc failed */ 68562306a36Sopenharmony_ci if (iosys_map_is_null(&iter_io->dmap)) 68662306a36Sopenharmony_ci iosys_map_set_vaddr_iomem(&iter_io->dmap, 68762306a36Sopenharmony_ci ioremap(mem->bus.offset, 68862306a36Sopenharmony_ci mem->size)); 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci if (iosys_map_is_null(&iter_io->dmap)) { 69162306a36Sopenharmony_ci ret = -ENOMEM; 69262306a36Sopenharmony_ci goto out_io_free; 69362306a36Sopenharmony_ci } 69462306a36Sopenharmony_ci } 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci iter_io->base.ops = &ttm_kmap_iter_linear_io_ops; 69762306a36Sopenharmony_ci return &iter_io->base; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ciout_io_free: 70062306a36Sopenharmony_ci ttm_mem_io_free(bdev, mem); 70162306a36Sopenharmony_ciout_err: 70262306a36Sopenharmony_ci return ERR_PTR(ret); 70362306a36Sopenharmony_ci} 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci/** 70662306a36Sopenharmony_ci * ttm_kmap_iter_linear_io_fini - Clean up an iterator for linear io memory 70762306a36Sopenharmony_ci * @iter_io: The iterator to initialize 70862306a36Sopenharmony_ci * @bdev: The TTM device 70962306a36Sopenharmony_ci * @mem: The ttm resource representing the iomap. 71062306a36Sopenharmony_ci * 71162306a36Sopenharmony_ci * This function is for internal TTM use only. It cleans up a memcpy kmap 71262306a36Sopenharmony_ci * iterator initialized by ttm_kmap_iter_linear_io_init. 71362306a36Sopenharmony_ci */ 71462306a36Sopenharmony_civoid 71562306a36Sopenharmony_cittm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io *iter_io, 71662306a36Sopenharmony_ci struct ttm_device *bdev, 71762306a36Sopenharmony_ci struct ttm_resource *mem) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci if (iter_io->needs_unmap && iosys_map_is_set(&iter_io->dmap)) { 72062306a36Sopenharmony_ci if (iter_io->dmap.is_iomem) 72162306a36Sopenharmony_ci iounmap(iter_io->dmap.vaddr_iomem); 72262306a36Sopenharmony_ci else 72362306a36Sopenharmony_ci memunmap(iter_io->dmap.vaddr); 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci ttm_mem_io_free(bdev, mem); 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_cistatic int ttm_resource_manager_show(struct seq_file *m, void *unused) 73262306a36Sopenharmony_ci{ 73362306a36Sopenharmony_ci struct ttm_resource_manager *man = 73462306a36Sopenharmony_ci (struct ttm_resource_manager *)m->private; 73562306a36Sopenharmony_ci struct drm_printer p = drm_seq_file_printer(m); 73662306a36Sopenharmony_ci ttm_resource_manager_debug(man, &p); 73762306a36Sopenharmony_ci return 0; 73862306a36Sopenharmony_ci} 73962306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(ttm_resource_manager); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci#endif 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci/** 74462306a36Sopenharmony_ci * ttm_resource_manager_create_debugfs - Create debugfs entry for specified 74562306a36Sopenharmony_ci * resource manager. 74662306a36Sopenharmony_ci * @man: The TTM resource manager for which the debugfs stats file be creates 74762306a36Sopenharmony_ci * @parent: debugfs directory in which the file will reside 74862306a36Sopenharmony_ci * @name: The filename to create. 74962306a36Sopenharmony_ci * 75062306a36Sopenharmony_ci * This function setups up a debugfs file that can be used to look 75162306a36Sopenharmony_ci * at debug statistics of the specified ttm_resource_manager. 75262306a36Sopenharmony_ci */ 75362306a36Sopenharmony_civoid ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man, 75462306a36Sopenharmony_ci struct dentry * parent, 75562306a36Sopenharmony_ci const char *name) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 75862306a36Sopenharmony_ci debugfs_create_file(name, 0444, parent, man, &ttm_resource_manager_fops); 75962306a36Sopenharmony_ci#endif 76062306a36Sopenharmony_ci} 76162306a36Sopenharmony_ciEXPORT_SYMBOL(ttm_resource_manager_create_debugfs); 762