1ad8b1aafSjsg /*
2ad8b1aafSjsg * Copyright 2020 Advanced Micro Devices, Inc.
3ad8b1aafSjsg *
4ad8b1aafSjsg * Permission is hereby granted, free of charge, to any person obtaining a
5ad8b1aafSjsg * copy of this software and associated documentation files (the "Software"),
6ad8b1aafSjsg * to deal in the Software without restriction, including without limitation
7ad8b1aafSjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8ad8b1aafSjsg * and/or sell copies of the Software, and to permit persons to whom the
9ad8b1aafSjsg * Software is furnished to do so, subject to the following conditions:
10ad8b1aafSjsg *
11ad8b1aafSjsg * The above copyright notice and this permission notice shall be included in
12ad8b1aafSjsg * all copies or substantial portions of the Software.
13ad8b1aafSjsg *
14ad8b1aafSjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15ad8b1aafSjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16ad8b1aafSjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17ad8b1aafSjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18ad8b1aafSjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ad8b1aafSjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20ad8b1aafSjsg * OTHER DEALINGS IN THE SOFTWARE.
21ad8b1aafSjsg *
22ad8b1aafSjsg * Authors: Christian König
23ad8b1aafSjsg */
24ad8b1aafSjsg
251bb76ff1Sjsg #include <linux/iosys-map.h>
265ca02815Sjsg #include <linux/io-mapping.h>
275ca02815Sjsg #include <linux/scatterlist.h>
285ca02815Sjsg
29*f005ef32Sjsg #include <drm/ttm/ttm_bo.h>
30*f005ef32Sjsg #include <drm/ttm/ttm_placement.h>
31ad8b1aafSjsg #include <drm/ttm/ttm_resource.h>
32ad8b1aafSjsg
331bb76ff1Sjsg /**
341bb76ff1Sjsg * ttm_lru_bulk_move_init - initialize a bulk move structure
351bb76ff1Sjsg * @bulk: the structure to init
361bb76ff1Sjsg *
371bb76ff1Sjsg * For now just memset the structure to zero.
381bb76ff1Sjsg */
ttm_lru_bulk_move_init(struct ttm_lru_bulk_move * bulk)391bb76ff1Sjsg void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk)
401bb76ff1Sjsg {
411bb76ff1Sjsg memset(bulk, 0, sizeof(*bulk));
421bb76ff1Sjsg }
431bb76ff1Sjsg EXPORT_SYMBOL(ttm_lru_bulk_move_init);
441bb76ff1Sjsg
451bb76ff1Sjsg /**
461bb76ff1Sjsg * ttm_lru_bulk_move_tail - bulk move range of resources to the LRU tail.
471bb76ff1Sjsg *
481bb76ff1Sjsg * @bulk: bulk move structure
491bb76ff1Sjsg *
501bb76ff1Sjsg * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that
511bb76ff1Sjsg * resource order never changes. Should be called with &ttm_device.lru_lock held.
521bb76ff1Sjsg */
ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move * bulk)531bb76ff1Sjsg void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk)
541bb76ff1Sjsg {
551bb76ff1Sjsg unsigned i, j;
561bb76ff1Sjsg
571bb76ff1Sjsg for (i = 0; i < TTM_NUM_MEM_TYPES; ++i) {
581bb76ff1Sjsg for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) {
591bb76ff1Sjsg struct ttm_lru_bulk_move_pos *pos = &bulk->pos[i][j];
601bb76ff1Sjsg struct ttm_resource_manager *man;
611bb76ff1Sjsg
621bb76ff1Sjsg if (!pos->first)
631bb76ff1Sjsg continue;
641bb76ff1Sjsg
651bb76ff1Sjsg lockdep_assert_held(&pos->first->bo->bdev->lru_lock);
661bb76ff1Sjsg dma_resv_assert_held(pos->first->bo->base.resv);
671bb76ff1Sjsg dma_resv_assert_held(pos->last->bo->base.resv);
681bb76ff1Sjsg
691bb76ff1Sjsg man = ttm_manager_type(pos->first->bo->bdev, i);
701bb76ff1Sjsg list_bulk_move_tail(&man->lru[j], &pos->first->lru,
711bb76ff1Sjsg &pos->last->lru);
721bb76ff1Sjsg }
731bb76ff1Sjsg }
741bb76ff1Sjsg }
751bb76ff1Sjsg EXPORT_SYMBOL(ttm_lru_bulk_move_tail);
761bb76ff1Sjsg
771bb76ff1Sjsg /* Return the bulk move pos object for this resource */
781bb76ff1Sjsg static struct ttm_lru_bulk_move_pos *
ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move * bulk,struct ttm_resource * res)791bb76ff1Sjsg ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res)
801bb76ff1Sjsg {
811bb76ff1Sjsg return &bulk->pos[res->mem_type][res->bo->priority];
821bb76ff1Sjsg }
831bb76ff1Sjsg
841bb76ff1Sjsg /* Move the resource to the tail of the bulk move range */
ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos * pos,struct ttm_resource * res)851bb76ff1Sjsg static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos,
861bb76ff1Sjsg struct ttm_resource *res)
871bb76ff1Sjsg {
881bb76ff1Sjsg if (pos->last != res) {
890774dd8aSjsg if (pos->first == res)
900774dd8aSjsg pos->first = list_next_entry(res, lru);
911bb76ff1Sjsg list_move(&res->lru, &pos->last->lru);
921bb76ff1Sjsg pos->last = res;
931bb76ff1Sjsg }
941bb76ff1Sjsg }
951bb76ff1Sjsg
961bb76ff1Sjsg /* Add the resource to a bulk_move cursor */
ttm_lru_bulk_move_add(struct ttm_lru_bulk_move * bulk,struct ttm_resource * res)971bb76ff1Sjsg static void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk,
981bb76ff1Sjsg struct ttm_resource *res)
991bb76ff1Sjsg {
1001bb76ff1Sjsg struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
1011bb76ff1Sjsg
1021bb76ff1Sjsg if (!pos->first) {
1031bb76ff1Sjsg pos->first = res;
1041bb76ff1Sjsg pos->last = res;
1051bb76ff1Sjsg } else {
1061bb76ff1Sjsg ttm_lru_bulk_move_pos_tail(pos, res);
1071bb76ff1Sjsg }
1081bb76ff1Sjsg }
1091bb76ff1Sjsg
1101bb76ff1Sjsg /* Remove the resource from a bulk_move range */
ttm_lru_bulk_move_del(struct ttm_lru_bulk_move * bulk,struct ttm_resource * res)1111bb76ff1Sjsg static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
1121bb76ff1Sjsg struct ttm_resource *res)
1131bb76ff1Sjsg {
1141bb76ff1Sjsg struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
1151bb76ff1Sjsg
1160774dd8aSjsg if (unlikely(WARN_ON(!pos->first || !pos->last) ||
1170774dd8aSjsg (pos->first == res && pos->last == res))) {
1181bb76ff1Sjsg pos->first = NULL;
1191bb76ff1Sjsg pos->last = NULL;
1201bb76ff1Sjsg } else if (pos->first == res) {
1211bb76ff1Sjsg pos->first = list_next_entry(res, lru);
1221bb76ff1Sjsg } else if (pos->last == res) {
1231bb76ff1Sjsg pos->last = list_prev_entry(res, lru);
1241bb76ff1Sjsg } else {
1251bb76ff1Sjsg list_move(&res->lru, &pos->last->lru);
1261bb76ff1Sjsg }
1271bb76ff1Sjsg }
1281bb76ff1Sjsg
1291bb76ff1Sjsg /* Add the resource to a bulk move if the BO is configured for it */
ttm_resource_add_bulk_move(struct ttm_resource * res,struct ttm_buffer_object * bo)1301bb76ff1Sjsg void ttm_resource_add_bulk_move(struct ttm_resource *res,
1311bb76ff1Sjsg struct ttm_buffer_object *bo)
1321bb76ff1Sjsg {
1331bb76ff1Sjsg if (bo->bulk_move && !bo->pin_count)
1341bb76ff1Sjsg ttm_lru_bulk_move_add(bo->bulk_move, res);
1351bb76ff1Sjsg }
1361bb76ff1Sjsg
1371bb76ff1Sjsg /* Remove the resource from a bulk move if the BO is configured for it */
ttm_resource_del_bulk_move(struct ttm_resource * res,struct ttm_buffer_object * bo)1381bb76ff1Sjsg void ttm_resource_del_bulk_move(struct ttm_resource *res,
1391bb76ff1Sjsg struct ttm_buffer_object *bo)
1401bb76ff1Sjsg {
1411bb76ff1Sjsg if (bo->bulk_move && !bo->pin_count)
1421bb76ff1Sjsg ttm_lru_bulk_move_del(bo->bulk_move, res);
1431bb76ff1Sjsg }
1441bb76ff1Sjsg
1451bb76ff1Sjsg /* Move a resource to the LRU or bulk tail */
ttm_resource_move_to_lru_tail(struct ttm_resource * res)1461bb76ff1Sjsg void ttm_resource_move_to_lru_tail(struct ttm_resource *res)
1471bb76ff1Sjsg {
1481bb76ff1Sjsg struct ttm_buffer_object *bo = res->bo;
1491bb76ff1Sjsg struct ttm_device *bdev = bo->bdev;
1501bb76ff1Sjsg
1511bb76ff1Sjsg lockdep_assert_held(&bo->bdev->lru_lock);
1521bb76ff1Sjsg
1531bb76ff1Sjsg if (bo->pin_count) {
1541bb76ff1Sjsg list_move_tail(&res->lru, &bdev->pinned);
1551bb76ff1Sjsg
1561bb76ff1Sjsg } else if (bo->bulk_move) {
1571bb76ff1Sjsg struct ttm_lru_bulk_move_pos *pos =
1581bb76ff1Sjsg ttm_lru_bulk_move_pos(bo->bulk_move, res);
1591bb76ff1Sjsg
1601bb76ff1Sjsg ttm_lru_bulk_move_pos_tail(pos, res);
1611bb76ff1Sjsg } else {
1621bb76ff1Sjsg struct ttm_resource_manager *man;
1631bb76ff1Sjsg
1641bb76ff1Sjsg man = ttm_manager_type(bdev, res->mem_type);
1651bb76ff1Sjsg list_move_tail(&res->lru, &man->lru[bo->priority]);
1661bb76ff1Sjsg }
1671bb76ff1Sjsg }
1681bb76ff1Sjsg
1691bb76ff1Sjsg /**
1701bb76ff1Sjsg * ttm_resource_init - resource object constructure
1711bb76ff1Sjsg * @bo: buffer object this resources is allocated for
1721bb76ff1Sjsg * @place: placement of the resource
1731bb76ff1Sjsg * @res: the resource object to inistilize
1741bb76ff1Sjsg *
1751bb76ff1Sjsg * Initialize a new resource object. Counterpart of ttm_resource_fini().
1761bb76ff1Sjsg */
ttm_resource_init(struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource * res)1775ca02815Sjsg void ttm_resource_init(struct ttm_buffer_object *bo,
178ad8b1aafSjsg const struct ttm_place *place,
179ad8b1aafSjsg struct ttm_resource *res)
180ad8b1aafSjsg {
1811bb76ff1Sjsg struct ttm_resource_manager *man;
1821bb76ff1Sjsg
1835ca02815Sjsg res->start = 0;
184*f005ef32Sjsg res->size = bo->base.size;
1855ca02815Sjsg res->mem_type = place->mem_type;
1865ca02815Sjsg res->placement = place->flags;
1875ca02815Sjsg res->bus.addr = NULL;
1885ca02815Sjsg res->bus.offset = 0;
1895ca02815Sjsg res->bus.is_iomem = false;
1905ca02815Sjsg res->bus.caching = ttm_cached;
1911bb76ff1Sjsg res->bo = bo;
1921bb76ff1Sjsg
1931bb76ff1Sjsg man = ttm_manager_type(bo->bdev, place->mem_type);
1941bb76ff1Sjsg spin_lock(&bo->bdev->lru_lock);
1951bb76ff1Sjsg if (bo->pin_count)
1961bb76ff1Sjsg list_add_tail(&res->lru, &bo->bdev->pinned);
1971bb76ff1Sjsg else
1981bb76ff1Sjsg list_add_tail(&res->lru, &man->lru[bo->priority]);
199*f005ef32Sjsg man->usage += res->size;
2001bb76ff1Sjsg spin_unlock(&bo->bdev->lru_lock);
201ad8b1aafSjsg }
2025ca02815Sjsg EXPORT_SYMBOL(ttm_resource_init);
203ad8b1aafSjsg
2041bb76ff1Sjsg /**
2051bb76ff1Sjsg * ttm_resource_fini - resource destructor
2061bb76ff1Sjsg * @man: the resource manager this resource belongs to
2071bb76ff1Sjsg * @res: the resource to clean up
2081bb76ff1Sjsg *
2091bb76ff1Sjsg * Should be used by resource manager backends to clean up the TTM resource
2101bb76ff1Sjsg * objects before freeing the underlying structure. Makes sure the resource is
2111bb76ff1Sjsg * removed from the LRU before destruction.
2121bb76ff1Sjsg * Counterpart of ttm_resource_init().
2131bb76ff1Sjsg */
ttm_resource_fini(struct ttm_resource_manager * man,struct ttm_resource * res)2141bb76ff1Sjsg void ttm_resource_fini(struct ttm_resource_manager *man,
2151bb76ff1Sjsg struct ttm_resource *res)
2161bb76ff1Sjsg {
2171bb76ff1Sjsg struct ttm_device *bdev = man->bdev;
2181bb76ff1Sjsg
2191bb76ff1Sjsg spin_lock(&bdev->lru_lock);
2201bb76ff1Sjsg list_del_init(&res->lru);
221*f005ef32Sjsg man->usage -= res->size;
2221bb76ff1Sjsg spin_unlock(&bdev->lru_lock);
2231bb76ff1Sjsg }
2241bb76ff1Sjsg EXPORT_SYMBOL(ttm_resource_fini);
2251bb76ff1Sjsg
ttm_resource_alloc(struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource ** res_ptr)2265ca02815Sjsg int ttm_resource_alloc(struct ttm_buffer_object *bo,
2275ca02815Sjsg const struct ttm_place *place,
2285ca02815Sjsg struct ttm_resource **res_ptr)
229ad8b1aafSjsg {
230ad8b1aafSjsg struct ttm_resource_manager *man =
2315ca02815Sjsg ttm_manager_type(bo->bdev, place->mem_type);
2321bb76ff1Sjsg int ret;
233ad8b1aafSjsg
2341bb76ff1Sjsg ret = man->func->alloc(man, bo, place, res_ptr);
2351bb76ff1Sjsg if (ret)
2361bb76ff1Sjsg return ret;
2371bb76ff1Sjsg
2381bb76ff1Sjsg spin_lock(&bo->bdev->lru_lock);
2391bb76ff1Sjsg ttm_resource_add_bulk_move(*res_ptr, bo);
2401bb76ff1Sjsg spin_unlock(&bo->bdev->lru_lock);
2411bb76ff1Sjsg return 0;
2425ca02815Sjsg }
243ad8b1aafSjsg
ttm_resource_free(struct ttm_buffer_object * bo,struct ttm_resource ** res)2445ca02815Sjsg void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res)
2455ca02815Sjsg {
2465ca02815Sjsg struct ttm_resource_manager *man;
2475ca02815Sjsg
2485ca02815Sjsg if (!*res)
2495ca02815Sjsg return;
2505ca02815Sjsg
2511bb76ff1Sjsg spin_lock(&bo->bdev->lru_lock);
2521bb76ff1Sjsg ttm_resource_del_bulk_move(*res, bo);
2531bb76ff1Sjsg spin_unlock(&bo->bdev->lru_lock);
2545ca02815Sjsg man = ttm_manager_type(bo->bdev, (*res)->mem_type);
2555ca02815Sjsg man->func->free(man, *res);
2565ca02815Sjsg *res = NULL;
257ad8b1aafSjsg }
258ad8b1aafSjsg EXPORT_SYMBOL(ttm_resource_free);
259ad8b1aafSjsg
260ad8b1aafSjsg /**
2611bb76ff1Sjsg * ttm_resource_intersects - test for intersection
2621bb76ff1Sjsg *
2631bb76ff1Sjsg * @bdev: TTM device structure
2641bb76ff1Sjsg * @res: The resource to test
2651bb76ff1Sjsg * @place: The placement to test
2661bb76ff1Sjsg * @size: How many bytes the new allocation needs.
2671bb76ff1Sjsg *
2681bb76ff1Sjsg * Test if @res intersects with @place and @size. Used for testing if evictions
2691bb76ff1Sjsg * are valueable or not.
2701bb76ff1Sjsg *
2711bb76ff1Sjsg * Returns true if the res placement intersects with @place and @size.
2721bb76ff1Sjsg */
ttm_resource_intersects(struct ttm_device * bdev,struct ttm_resource * res,const struct ttm_place * place,size_t size)2731bb76ff1Sjsg bool ttm_resource_intersects(struct ttm_device *bdev,
2741bb76ff1Sjsg struct ttm_resource *res,
2751bb76ff1Sjsg const struct ttm_place *place,
2761bb76ff1Sjsg size_t size)
2771bb76ff1Sjsg {
2781bb76ff1Sjsg struct ttm_resource_manager *man;
2791bb76ff1Sjsg
2801bb76ff1Sjsg if (!res)
2811bb76ff1Sjsg return false;
2821bb76ff1Sjsg
2831bb76ff1Sjsg man = ttm_manager_type(bdev, res->mem_type);
2841bb76ff1Sjsg if (!place || !man->func->intersects)
2851bb76ff1Sjsg return true;
2861bb76ff1Sjsg
2871bb76ff1Sjsg return man->func->intersects(man, res, place, size);
2881bb76ff1Sjsg }
2891bb76ff1Sjsg
2901bb76ff1Sjsg /**
2911bb76ff1Sjsg * ttm_resource_compatible - test for compatibility
2921bb76ff1Sjsg *
2931bb76ff1Sjsg * @bdev: TTM device structure
2941bb76ff1Sjsg * @res: The resource to test
2951bb76ff1Sjsg * @place: The placement to test
2961bb76ff1Sjsg * @size: How many bytes the new allocation needs.
2971bb76ff1Sjsg *
2981bb76ff1Sjsg * Test if @res compatible with @place and @size.
2991bb76ff1Sjsg *
3001bb76ff1Sjsg * Returns true if the res placement compatible with @place and @size.
3011bb76ff1Sjsg */
ttm_resource_compatible(struct ttm_device * bdev,struct ttm_resource * res,const struct ttm_place * place,size_t size)3021bb76ff1Sjsg bool ttm_resource_compatible(struct ttm_device *bdev,
3031bb76ff1Sjsg struct ttm_resource *res,
3041bb76ff1Sjsg const struct ttm_place *place,
3051bb76ff1Sjsg size_t size)
3061bb76ff1Sjsg {
3071bb76ff1Sjsg struct ttm_resource_manager *man;
3081bb76ff1Sjsg
3091bb76ff1Sjsg if (!res || !place)
3101bb76ff1Sjsg return false;
3111bb76ff1Sjsg
3121bb76ff1Sjsg man = ttm_manager_type(bdev, res->mem_type);
3131bb76ff1Sjsg if (!man->func->compatible)
3141bb76ff1Sjsg return true;
3151bb76ff1Sjsg
3161bb76ff1Sjsg return man->func->compatible(man, res, place, size);
3171bb76ff1Sjsg }
3181bb76ff1Sjsg
ttm_resource_places_compat(struct ttm_resource * res,const struct ttm_place * places,unsigned num_placement)3191bb76ff1Sjsg static bool ttm_resource_places_compat(struct ttm_resource *res,
3201bb76ff1Sjsg const struct ttm_place *places,
3211bb76ff1Sjsg unsigned num_placement)
3221bb76ff1Sjsg {
3231bb76ff1Sjsg struct ttm_buffer_object *bo = res->bo;
3241bb76ff1Sjsg struct ttm_device *bdev = bo->bdev;
3251bb76ff1Sjsg unsigned i;
3261bb76ff1Sjsg
3271bb76ff1Sjsg if (res->placement & TTM_PL_FLAG_TEMPORARY)
3281bb76ff1Sjsg return false;
3291bb76ff1Sjsg
3301bb76ff1Sjsg for (i = 0; i < num_placement; i++) {
3311bb76ff1Sjsg const struct ttm_place *heap = &places[i];
3321bb76ff1Sjsg
3331bb76ff1Sjsg if (!ttm_resource_compatible(bdev, res, heap, bo->base.size))
3341bb76ff1Sjsg continue;
3351bb76ff1Sjsg
3361bb76ff1Sjsg if ((res->mem_type == heap->mem_type) &&
3371bb76ff1Sjsg (!(heap->flags & TTM_PL_FLAG_CONTIGUOUS) ||
3381bb76ff1Sjsg (res->placement & TTM_PL_FLAG_CONTIGUOUS)))
3391bb76ff1Sjsg return true;
3401bb76ff1Sjsg }
3411bb76ff1Sjsg return false;
3421bb76ff1Sjsg }
3431bb76ff1Sjsg
3441bb76ff1Sjsg /**
3451bb76ff1Sjsg * ttm_resource_compat - check if resource is compatible with placement
3461bb76ff1Sjsg *
3471bb76ff1Sjsg * @res: the resource to check
3481bb76ff1Sjsg * @placement: the placement to check against
3491bb76ff1Sjsg *
3501bb76ff1Sjsg * Returns true if the placement is compatible.
3511bb76ff1Sjsg */
ttm_resource_compat(struct ttm_resource * res,struct ttm_placement * placement)3521bb76ff1Sjsg bool ttm_resource_compat(struct ttm_resource *res,
3531bb76ff1Sjsg struct ttm_placement *placement)
3541bb76ff1Sjsg {
3551bb76ff1Sjsg if (ttm_resource_places_compat(res, placement->placement,
3561bb76ff1Sjsg placement->num_placement))
3571bb76ff1Sjsg return true;
3581bb76ff1Sjsg
3591bb76ff1Sjsg if ((placement->busy_placement != placement->placement ||
3601bb76ff1Sjsg placement->num_busy_placement > placement->num_placement) &&
3611bb76ff1Sjsg ttm_resource_places_compat(res, placement->busy_placement,
3621bb76ff1Sjsg placement->num_busy_placement))
3631bb76ff1Sjsg return true;
3641bb76ff1Sjsg
3651bb76ff1Sjsg return false;
3661bb76ff1Sjsg }
3671bb76ff1Sjsg
ttm_resource_set_bo(struct ttm_resource * res,struct ttm_buffer_object * bo)3681bb76ff1Sjsg void ttm_resource_set_bo(struct ttm_resource *res,
3691bb76ff1Sjsg struct ttm_buffer_object *bo)
3701bb76ff1Sjsg {
3711bb76ff1Sjsg spin_lock(&bo->bdev->lru_lock);
3721bb76ff1Sjsg res->bo = bo;
3731bb76ff1Sjsg spin_unlock(&bo->bdev->lru_lock);
3741bb76ff1Sjsg }
3751bb76ff1Sjsg
3761bb76ff1Sjsg /**
377ad8b1aafSjsg * ttm_resource_manager_init
378ad8b1aafSjsg *
379ad8b1aafSjsg * @man: memory manager object to init
3801bb76ff1Sjsg * @bdev: ttm device this manager belongs to
3811bb76ff1Sjsg * @size: size of managed resources in arbitrary units
382ad8b1aafSjsg *
383ad8b1aafSjsg * Initialise core parts of a manager object.
384ad8b1aafSjsg */
ttm_resource_manager_init(struct ttm_resource_manager * man,struct ttm_device * bdev,uint64_t size)385ad8b1aafSjsg void ttm_resource_manager_init(struct ttm_resource_manager *man,
3861bb76ff1Sjsg struct ttm_device *bdev,
3871bb76ff1Sjsg uint64_t size)
388ad8b1aafSjsg {
389ad8b1aafSjsg unsigned i;
390ad8b1aafSjsg
391ad8b1aafSjsg mtx_init(&man->move_lock, IPL_NONE);
3921bb76ff1Sjsg man->bdev = bdev;
3931bb76ff1Sjsg man->size = size;
3941bb76ff1Sjsg man->usage = 0;
395ad8b1aafSjsg
396ad8b1aafSjsg for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
397ad8b1aafSjsg INIT_LIST_HEAD(&man->lru[i]);
398ad8b1aafSjsg man->move = NULL;
399ad8b1aafSjsg }
400ad8b1aafSjsg EXPORT_SYMBOL(ttm_resource_manager_init);
401ad8b1aafSjsg
402ad8b1aafSjsg /*
4035ca02815Sjsg * ttm_resource_manager_evict_all
404ad8b1aafSjsg *
405ad8b1aafSjsg * @bdev - device to use
406ad8b1aafSjsg * @man - manager to use
407ad8b1aafSjsg *
4085ca02815Sjsg * Evict all the objects out of a memory manager until it is empty.
409ad8b1aafSjsg * Part of memory manager cleanup sequence.
410ad8b1aafSjsg */
ttm_resource_manager_evict_all(struct ttm_device * bdev,struct ttm_resource_manager * man)4115ca02815Sjsg int ttm_resource_manager_evict_all(struct ttm_device *bdev,
412ad8b1aafSjsg struct ttm_resource_manager *man)
413ad8b1aafSjsg {
414ad8b1aafSjsg struct ttm_operation_ctx ctx = {
415ad8b1aafSjsg .interruptible = false,
416ad8b1aafSjsg .no_wait_gpu = false,
4175ca02815Sjsg .force_alloc = true
418ad8b1aafSjsg };
419ad8b1aafSjsg struct dma_fence *fence;
420ad8b1aafSjsg int ret;
421ad8b1aafSjsg unsigned i;
422ad8b1aafSjsg
423ad8b1aafSjsg /*
424ad8b1aafSjsg * Can't use standard list traversal since we're unlocking.
425ad8b1aafSjsg */
426ad8b1aafSjsg
4275ca02815Sjsg spin_lock(&bdev->lru_lock);
428ad8b1aafSjsg for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
429ad8b1aafSjsg while (!list_empty(&man->lru[i])) {
4305ca02815Sjsg spin_unlock(&bdev->lru_lock);
431ad8b1aafSjsg ret = ttm_mem_evict_first(bdev, man, NULL, &ctx,
432ad8b1aafSjsg NULL);
433ad8b1aafSjsg if (ret)
434ad8b1aafSjsg return ret;
4355ca02815Sjsg spin_lock(&bdev->lru_lock);
436ad8b1aafSjsg }
437ad8b1aafSjsg }
4385ca02815Sjsg spin_unlock(&bdev->lru_lock);
439ad8b1aafSjsg
440ad8b1aafSjsg spin_lock(&man->move_lock);
441ad8b1aafSjsg fence = dma_fence_get(man->move);
442ad8b1aafSjsg spin_unlock(&man->move_lock);
443ad8b1aafSjsg
444ad8b1aafSjsg if (fence) {
445ad8b1aafSjsg ret = dma_fence_wait(fence, false);
446ad8b1aafSjsg dma_fence_put(fence);
447ad8b1aafSjsg if (ret)
448ad8b1aafSjsg return ret;
449ad8b1aafSjsg }
450ad8b1aafSjsg
451ad8b1aafSjsg return 0;
452ad8b1aafSjsg }
4535ca02815Sjsg EXPORT_SYMBOL(ttm_resource_manager_evict_all);
454ad8b1aafSjsg
455ad8b1aafSjsg /**
4561bb76ff1Sjsg * ttm_resource_manager_usage
4571bb76ff1Sjsg *
4581bb76ff1Sjsg * @man: A memory manager object.
4591bb76ff1Sjsg *
4601bb76ff1Sjsg * Return how many resources are currently used.
4611bb76ff1Sjsg */
ttm_resource_manager_usage(struct ttm_resource_manager * man)4621bb76ff1Sjsg uint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man)
4631bb76ff1Sjsg {
4641bb76ff1Sjsg uint64_t usage;
4651bb76ff1Sjsg
4661bb76ff1Sjsg spin_lock(&man->bdev->lru_lock);
4671bb76ff1Sjsg usage = man->usage;
4681bb76ff1Sjsg spin_unlock(&man->bdev->lru_lock);
4691bb76ff1Sjsg return usage;
4701bb76ff1Sjsg }
4711bb76ff1Sjsg EXPORT_SYMBOL(ttm_resource_manager_usage);
4721bb76ff1Sjsg
4731bb76ff1Sjsg /**
474ad8b1aafSjsg * ttm_resource_manager_debug
475ad8b1aafSjsg *
476ad8b1aafSjsg * @man: manager type to dump.
477ad8b1aafSjsg * @p: printer to use for debug.
478ad8b1aafSjsg */
ttm_resource_manager_debug(struct ttm_resource_manager * man,struct drm_printer * p)479ad8b1aafSjsg void ttm_resource_manager_debug(struct ttm_resource_manager *man,
480ad8b1aafSjsg struct drm_printer *p)
481ad8b1aafSjsg {
482ad8b1aafSjsg drm_printf(p, " use_type: %d\n", man->use_type);
483ad8b1aafSjsg drm_printf(p, " use_tt: %d\n", man->use_tt);
484ad8b1aafSjsg drm_printf(p, " size: %llu\n", man->size);
4851bb76ff1Sjsg drm_printf(p, " usage: %llu\n", ttm_resource_manager_usage(man));
4865ca02815Sjsg if (man->func->debug)
4875ca02815Sjsg man->func->debug(man, p);
488ad8b1aafSjsg }
489ad8b1aafSjsg EXPORT_SYMBOL(ttm_resource_manager_debug);
4905ca02815Sjsg
4911bb76ff1Sjsg /**
4921bb76ff1Sjsg * ttm_resource_manager_first
4931bb76ff1Sjsg *
4941bb76ff1Sjsg * @man: resource manager to iterate over
4951bb76ff1Sjsg * @cursor: cursor to record the position
4961bb76ff1Sjsg *
4971bb76ff1Sjsg * Returns the first resource from the resource manager.
4981bb76ff1Sjsg */
4991bb76ff1Sjsg struct ttm_resource *
ttm_resource_manager_first(struct ttm_resource_manager * man,struct ttm_resource_cursor * cursor)5001bb76ff1Sjsg ttm_resource_manager_first(struct ttm_resource_manager *man,
5011bb76ff1Sjsg struct ttm_resource_cursor *cursor)
5021bb76ff1Sjsg {
5031bb76ff1Sjsg struct ttm_resource *res;
5041bb76ff1Sjsg
5051bb76ff1Sjsg lockdep_assert_held(&man->bdev->lru_lock);
5061bb76ff1Sjsg
5071bb76ff1Sjsg for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY;
5081bb76ff1Sjsg ++cursor->priority)
5091bb76ff1Sjsg list_for_each_entry(res, &man->lru[cursor->priority], lru)
5101bb76ff1Sjsg return res;
5111bb76ff1Sjsg
5121bb76ff1Sjsg return NULL;
5131bb76ff1Sjsg }
5141bb76ff1Sjsg
5151bb76ff1Sjsg /**
5161bb76ff1Sjsg * ttm_resource_manager_next
5171bb76ff1Sjsg *
5181bb76ff1Sjsg * @man: resource manager to iterate over
5191bb76ff1Sjsg * @cursor: cursor to record the position
5201bb76ff1Sjsg * @res: the current resource pointer
5211bb76ff1Sjsg *
5221bb76ff1Sjsg * Returns the next resource from the resource manager.
5231bb76ff1Sjsg */
5241bb76ff1Sjsg struct ttm_resource *
ttm_resource_manager_next(struct ttm_resource_manager * man,struct ttm_resource_cursor * cursor,struct ttm_resource * res)5251bb76ff1Sjsg ttm_resource_manager_next(struct ttm_resource_manager *man,
5261bb76ff1Sjsg struct ttm_resource_cursor *cursor,
5271bb76ff1Sjsg struct ttm_resource *res)
5281bb76ff1Sjsg {
5291bb76ff1Sjsg lockdep_assert_held(&man->bdev->lru_lock);
5301bb76ff1Sjsg
5311bb76ff1Sjsg list_for_each_entry_continue(res, &man->lru[cursor->priority], lru)
5321bb76ff1Sjsg return res;
5331bb76ff1Sjsg
5341bb76ff1Sjsg for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY;
5351bb76ff1Sjsg ++cursor->priority)
5361bb76ff1Sjsg list_for_each_entry(res, &man->lru[cursor->priority], lru)
5371bb76ff1Sjsg return res;
5381bb76ff1Sjsg
5391bb76ff1Sjsg return NULL;
5401bb76ff1Sjsg }
5411bb76ff1Sjsg
ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter * iter,struct iosys_map * dmap,pgoff_t i,bus_space_tag_t bst)5425ca02815Sjsg static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter,
5431bb76ff1Sjsg struct iosys_map *dmap,
5445ca02815Sjsg pgoff_t i, bus_space_tag_t bst)
5455ca02815Sjsg {
5465ca02815Sjsg struct ttm_kmap_iter_iomap *iter_io =
5475ca02815Sjsg container_of(iter, typeof(*iter_io), base);
5485ca02815Sjsg void __iomem *addr;
5495ca02815Sjsg
5505ca02815Sjsg retry:
5515ca02815Sjsg while (i >= iter_io->cache.end) {
5525ca02815Sjsg iter_io->cache.sg = iter_io->cache.sg ?
5535ca02815Sjsg sg_next(iter_io->cache.sg) : iter_io->st->sgl;
5545ca02815Sjsg iter_io->cache.i = iter_io->cache.end;
5555ca02815Sjsg iter_io->cache.end += sg_dma_len(iter_io->cache.sg) >>
5565ca02815Sjsg PAGE_SHIFT;
5575ca02815Sjsg iter_io->cache.offs = sg_dma_address(iter_io->cache.sg) -
5585ca02815Sjsg iter_io->start;
5595ca02815Sjsg }
5605ca02815Sjsg
5615ca02815Sjsg if (i < iter_io->cache.i) {
5625ca02815Sjsg iter_io->cache.end = 0;
5635ca02815Sjsg iter_io->cache.sg = NULL;
5645ca02815Sjsg goto retry;
5655ca02815Sjsg }
5665ca02815Sjsg
5675ca02815Sjsg addr = io_mapping_map_local_wc(iter_io->iomap, iter_io->cache.offs +
5685ca02815Sjsg (((resource_size_t)i - iter_io->cache.i)
5695ca02815Sjsg << PAGE_SHIFT));
5701bb76ff1Sjsg iosys_map_set_vaddr_iomem(dmap, addr);
5715ca02815Sjsg }
5725ca02815Sjsg
ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter * iter,struct iosys_map * map,bus_space_tag_t bst)5735ca02815Sjsg static void ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter *iter,
5741bb76ff1Sjsg struct iosys_map *map, bus_space_tag_t bst)
5755ca02815Sjsg {
5765ca02815Sjsg io_mapping_unmap_local(map->vaddr_iomem);
5775ca02815Sjsg }
5785ca02815Sjsg
5795ca02815Sjsg static const struct ttm_kmap_iter_ops ttm_kmap_iter_io_ops = {
5805ca02815Sjsg .map_local = ttm_kmap_iter_iomap_map_local,
5815ca02815Sjsg .unmap_local = ttm_kmap_iter_iomap_unmap_local,
5825ca02815Sjsg .maps_tt = false,
5835ca02815Sjsg };
5845ca02815Sjsg
5855ca02815Sjsg /**
5865ca02815Sjsg * ttm_kmap_iter_iomap_init - Initialize a struct ttm_kmap_iter_iomap
5875ca02815Sjsg * @iter_io: The struct ttm_kmap_iter_iomap to initialize.
5885ca02815Sjsg * @iomap: The struct io_mapping representing the underlying linear io_memory.
5895ca02815Sjsg * @st: sg_table into @iomap, representing the memory of the struct
5905ca02815Sjsg * ttm_resource.
5915ca02815Sjsg * @start: Offset that needs to be subtracted from @st to make
5925ca02815Sjsg * sg_dma_address(st->sgl) - @start == 0 for @iomap start.
5935ca02815Sjsg *
5945ca02815Sjsg * Return: Pointer to the embedded struct ttm_kmap_iter.
5955ca02815Sjsg */
5965ca02815Sjsg struct ttm_kmap_iter *
ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap * iter_io,struct io_mapping * iomap,struct sg_table * st,resource_size_t start)5975ca02815Sjsg ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io,
5985ca02815Sjsg struct io_mapping *iomap,
5995ca02815Sjsg struct sg_table *st,
6005ca02815Sjsg resource_size_t start)
6015ca02815Sjsg {
6025ca02815Sjsg iter_io->base.ops = &ttm_kmap_iter_io_ops;
6035ca02815Sjsg iter_io->iomap = iomap;
6045ca02815Sjsg iter_io->st = st;
6055ca02815Sjsg iter_io->start = start;
6065ca02815Sjsg memset(&iter_io->cache, 0, sizeof(iter_io->cache));
6075ca02815Sjsg
6085ca02815Sjsg return &iter_io->base;
6095ca02815Sjsg }
6105ca02815Sjsg EXPORT_SYMBOL(ttm_kmap_iter_iomap_init);
6115ca02815Sjsg
6125ca02815Sjsg /**
6135ca02815Sjsg * DOC: Linear io iterator
6145ca02815Sjsg *
6155ca02815Sjsg * This code should die in the not too near future. Best would be if we could
6165ca02815Sjsg * make io-mapping use memremap for all io memory, and have memremap
6175ca02815Sjsg * implement a kmap_local functionality. We could then strip a huge amount of
6185ca02815Sjsg * code. These linear io iterators are implemented to mimic old functionality,
6195ca02815Sjsg * and they don't use kmap_local semantics at all internally. Rather ioremap or
6205ca02815Sjsg * friends, and at least on 32-bit they add global TLB flushes and points
6215ca02815Sjsg * of failure.
6225ca02815Sjsg */
6235ca02815Sjsg
ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter * iter,struct iosys_map * dmap,pgoff_t i,bus_space_tag_t bst)6245ca02815Sjsg static void ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter *iter,
6251bb76ff1Sjsg struct iosys_map *dmap,
6265ca02815Sjsg pgoff_t i, bus_space_tag_t bst)
6275ca02815Sjsg {
6285ca02815Sjsg struct ttm_kmap_iter_linear_io *iter_io =
6295ca02815Sjsg container_of(iter, typeof(*iter_io), base);
6305ca02815Sjsg
6315ca02815Sjsg *dmap = iter_io->dmap;
6321bb76ff1Sjsg iosys_map_incr(dmap, i * PAGE_SIZE);
6335ca02815Sjsg }
6345ca02815Sjsg
6355ca02815Sjsg static const struct ttm_kmap_iter_ops ttm_kmap_iter_linear_io_ops = {
6365ca02815Sjsg .map_local = ttm_kmap_iter_linear_io_map_local,
6375ca02815Sjsg .maps_tt = false,
6385ca02815Sjsg };
6395ca02815Sjsg
6405ca02815Sjsg /**
6415ca02815Sjsg * ttm_kmap_iter_linear_io_init - Initialize an iterator for linear io memory
6425ca02815Sjsg * @iter_io: The iterator to initialize
6435ca02815Sjsg * @bdev: The TTM device
6445ca02815Sjsg * @mem: The ttm resource representing the iomap.
6455ca02815Sjsg *
6465ca02815Sjsg * This function is for internal TTM use only. It sets up a memcpy kmap iterator
6475ca02815Sjsg * pointing at a linear chunk of io memory.
6485ca02815Sjsg *
6495ca02815Sjsg * Return: A pointer to the embedded struct ttm_kmap_iter or error pointer on
6505ca02815Sjsg * failure.
6515ca02815Sjsg */
6525ca02815Sjsg struct ttm_kmap_iter *
ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io * iter_io,struct ttm_device * bdev,struct ttm_resource * mem)6535ca02815Sjsg ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io,
6545ca02815Sjsg struct ttm_device *bdev,
6555ca02815Sjsg struct ttm_resource *mem)
6565ca02815Sjsg {
6575ca02815Sjsg int ret;
6585ca02815Sjsg
6595ca02815Sjsg ret = ttm_mem_io_reserve(bdev, mem);
6605ca02815Sjsg if (ret)
6615ca02815Sjsg goto out_err;
6625ca02815Sjsg if (!mem->bus.is_iomem) {
6635ca02815Sjsg ret = -EINVAL;
6645ca02815Sjsg goto out_io_free;
6655ca02815Sjsg }
6665ca02815Sjsg
6675ca02815Sjsg if (mem->bus.addr) {
6681bb76ff1Sjsg iosys_map_set_vaddr(&iter_io->dmap, mem->bus.addr);
6695ca02815Sjsg iter_io->needs_unmap = false;
6705ca02815Sjsg } else {
6715ca02815Sjsg iter_io->needs_unmap = true;
6725ca02815Sjsg memset(&iter_io->dmap, 0, sizeof(iter_io->dmap));
6735ca02815Sjsg if (mem->bus.caching == ttm_write_combined) {
6745ca02815Sjsg #ifdef __linux__
6751bb76ff1Sjsg iosys_map_set_vaddr_iomem(&iter_io->dmap,
6765ca02815Sjsg ioremap_wc(mem->bus.offset,
677*f005ef32Sjsg mem->size));
6785ca02815Sjsg #else
6795ca02815Sjsg if (bus_space_map(bdev->memt, mem->bus.offset,
680*f005ef32Sjsg mem->size, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
6815ca02815Sjsg &iter_io->dmap.bsh)) {
6825ca02815Sjsg ret = -ENOMEM;
6835ca02815Sjsg goto out_io_free;
6845ca02815Sjsg }
685*f005ef32Sjsg iter_io->dmap.size = mem->size;
6861bb76ff1Sjsg iosys_map_set_vaddr_iomem(&iter_io->dmap,
6875ca02815Sjsg bus_space_vaddr(bdev->memt, iter_io->dmap.bsh));
6885ca02815Sjsg #endif
6891bb76ff1Sjsg } else if (mem->bus.caching == ttm_cached) {
6905ca02815Sjsg #ifdef __linux__
6911bb76ff1Sjsg iosys_map_set_vaddr(&iter_io->dmap,
692*f005ef32Sjsg memremap(mem->bus.offset, mem->size,
6935ca02815Sjsg MEMREMAP_WB |
6945ca02815Sjsg MEMREMAP_WT |
6955ca02815Sjsg MEMREMAP_WC));
6965ca02815Sjsg #else
6975ca02815Sjsg if (bus_space_map(bdev->memt, mem->bus.offset,
698*f005ef32Sjsg mem->size, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_PREFETCHABLE,
6995ca02815Sjsg &iter_io->dmap.bsh)) {
7005ca02815Sjsg ret = -ENOMEM;
7015ca02815Sjsg goto out_io_free;
7025ca02815Sjsg }
703*f005ef32Sjsg iter_io->dmap.size = mem->size;
7041bb76ff1Sjsg iosys_map_set_vaddr(&iter_io->dmap,
7055ca02815Sjsg bus_space_vaddr(bdev->memt, iter_io->dmap.bsh));
7065ca02815Sjsg #endif
7075ca02815Sjsg }
7085ca02815Sjsg
7095ca02815Sjsg /* If uncached requested or if mapping cached or wc failed */
7101bb76ff1Sjsg if (iosys_map_is_null(&iter_io->dmap)) {
7115ca02815Sjsg #ifdef __linux__
7121bb76ff1Sjsg iosys_map_set_vaddr_iomem(&iter_io->dmap,
7135ca02815Sjsg ioremap(mem->bus.offset,
714*f005ef32Sjsg mem->size));
7155ca02815Sjsg #else
7165ca02815Sjsg if (bus_space_map(bdev->memt, mem->bus.offset,
717*f005ef32Sjsg mem->size, BUS_SPACE_MAP_LINEAR, &iter_io->dmap.bsh)) {
7185ca02815Sjsg ret = -ENOMEM;
7195ca02815Sjsg goto out_io_free;
7205ca02815Sjsg }
721*f005ef32Sjsg iter_io->dmap.size = mem->size;
7221bb76ff1Sjsg iosys_map_set_vaddr_iomem(&iter_io->dmap,
7235ca02815Sjsg bus_space_vaddr(bdev->memt, iter_io->dmap.bsh));
7245ca02815Sjsg #endif
7255ca02815Sjsg }
7265ca02815Sjsg
7271bb76ff1Sjsg if (iosys_map_is_null(&iter_io->dmap)) {
7285ca02815Sjsg ret = -ENOMEM;
7295ca02815Sjsg goto out_io_free;
7305ca02815Sjsg }
7315ca02815Sjsg }
7325ca02815Sjsg
7335ca02815Sjsg iter_io->base.ops = &ttm_kmap_iter_linear_io_ops;
7345ca02815Sjsg return &iter_io->base;
7355ca02815Sjsg
7365ca02815Sjsg out_io_free:
7375ca02815Sjsg ttm_mem_io_free(bdev, mem);
7385ca02815Sjsg out_err:
7395ca02815Sjsg return ERR_PTR(ret);
7405ca02815Sjsg }
7415ca02815Sjsg
7425ca02815Sjsg /**
7435ca02815Sjsg * ttm_kmap_iter_linear_io_fini - Clean up an iterator for linear io memory
7445ca02815Sjsg * @iter_io: The iterator to initialize
7455ca02815Sjsg * @bdev: The TTM device
7465ca02815Sjsg * @mem: The ttm resource representing the iomap.
7475ca02815Sjsg *
7485ca02815Sjsg * This function is for internal TTM use only. It cleans up a memcpy kmap
7495ca02815Sjsg * iterator initialized by ttm_kmap_iter_linear_io_init.
7505ca02815Sjsg */
7515ca02815Sjsg void
ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io * iter_io,struct ttm_device * bdev,struct ttm_resource * mem)7525ca02815Sjsg ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io *iter_io,
7535ca02815Sjsg struct ttm_device *bdev,
7545ca02815Sjsg struct ttm_resource *mem)
7555ca02815Sjsg {
7561bb76ff1Sjsg if (iter_io->needs_unmap && iosys_map_is_set(&iter_io->dmap)) {
7575ca02815Sjsg #ifdef __linux__
7585ca02815Sjsg if (iter_io->dmap.is_iomem)
7595ca02815Sjsg iounmap(iter_io->dmap.vaddr_iomem);
7605ca02815Sjsg else
7615ca02815Sjsg memunmap(iter_io->dmap.vaddr);
7625ca02815Sjsg #else
7635ca02815Sjsg bus_space_unmap(bdev->memt, iter_io->dmap.bsh,
7645ca02815Sjsg iter_io->dmap.size);
7655ca02815Sjsg #endif
7665ca02815Sjsg }
7675ca02815Sjsg
7685ca02815Sjsg ttm_mem_io_free(bdev, mem);
7695ca02815Sjsg }
7701bb76ff1Sjsg
7711bb76ff1Sjsg #if defined(CONFIG_DEBUG_FS)
7721bb76ff1Sjsg
ttm_resource_manager_show(struct seq_file * m,void * unused)7731bb76ff1Sjsg static int ttm_resource_manager_show(struct seq_file *m, void *unused)
7741bb76ff1Sjsg {
7751bb76ff1Sjsg struct ttm_resource_manager *man =
7761bb76ff1Sjsg (struct ttm_resource_manager *)m->private;
7771bb76ff1Sjsg struct drm_printer p = drm_seq_file_printer(m);
7781bb76ff1Sjsg ttm_resource_manager_debug(man, &p);
7791bb76ff1Sjsg return 0;
7801bb76ff1Sjsg }
7811bb76ff1Sjsg DEFINE_SHOW_ATTRIBUTE(ttm_resource_manager);
7821bb76ff1Sjsg
7831bb76ff1Sjsg #endif
7841bb76ff1Sjsg
7851bb76ff1Sjsg /**
7861bb76ff1Sjsg * ttm_resource_manager_create_debugfs - Create debugfs entry for specified
7871bb76ff1Sjsg * resource manager.
7881bb76ff1Sjsg * @man: The TTM resource manager for which the debugfs stats file be creates
7891bb76ff1Sjsg * @parent: debugfs directory in which the file will reside
7901bb76ff1Sjsg * @name: The filename to create.
7911bb76ff1Sjsg *
7921bb76ff1Sjsg * This function setups up a debugfs file that can be used to look
7931bb76ff1Sjsg * at debug statistics of the specified ttm_resource_manager.
7941bb76ff1Sjsg */
7951bb76ff1Sjsg struct dentry;
ttm_resource_manager_create_debugfs(struct ttm_resource_manager * man,struct dentry * parent,const char * name)7961bb76ff1Sjsg void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man,
7971bb76ff1Sjsg struct dentry * parent,
7981bb76ff1Sjsg const char *name)
7991bb76ff1Sjsg {
8001bb76ff1Sjsg #if defined(CONFIG_DEBUG_FS)
8011bb76ff1Sjsg debugfs_create_file(name, 0444, parent, man, &ttm_resource_manager_fops);
8021bb76ff1Sjsg #endif
8031bb76ff1Sjsg }
8041bb76ff1Sjsg EXPORT_SYMBOL(ttm_resource_manager_create_debugfs);
805