xref: /openbmc/linux/drivers/gpu/drm/ttm/ttm_resource.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1b2458726SChristian König /*
2b2458726SChristian König  * Copyright 2020 Advanced Micro Devices, Inc.
3b2458726SChristian König  *
4b2458726SChristian König  * Permission is hereby granted, free of charge, to any person obtaining a
5b2458726SChristian König  * copy of this software and associated documentation files (the "Software"),
6b2458726SChristian König  * to deal in the Software without restriction, including without limitation
7b2458726SChristian König  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b2458726SChristian König  * and/or sell copies of the Software, and to permit persons to whom the
9b2458726SChristian König  * Software is furnished to do so, subject to the following conditions:
10b2458726SChristian König  *
11b2458726SChristian König  * The above copyright notice and this permission notice shall be included in
12b2458726SChristian König  * all copies or substantial portions of the Software.
13b2458726SChristian König  *
14b2458726SChristian König  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b2458726SChristian König  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b2458726SChristian König  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17b2458726SChristian König  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b2458726SChristian König  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b2458726SChristian König  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b2458726SChristian König  * OTHER DEALINGS IN THE SOFTWARE.
21b2458726SChristian König  *
22b2458726SChristian König  * Authors: Christian König
23b2458726SChristian König  */
24b2458726SChristian König 
257938f421SLucas De Marchi #include <linux/iosys-map.h>
263bf3710eSThomas Hellström #include <linux/io-mapping.h>
273bf3710eSThomas Hellström #include <linux/scatterlist.h>
283bf3710eSThomas Hellström 
29*a3185f91SChristian König #include <drm/ttm/ttm_bo.h>
30*a3185f91SChristian König #include <drm/ttm/ttm_placement.h>
31b2458726SChristian König #include <drm/ttm/ttm_resource.h>
32b2458726SChristian König 
33de3688e4SChristian König /**
346a9b0289SChristian König  * ttm_lru_bulk_move_init - initialize a bulk move structure
356a9b0289SChristian König  * @bulk: the structure to init
366a9b0289SChristian König  *
376a9b0289SChristian König  * For now just memset the structure to zero.
386a9b0289SChristian König  */
ttm_lru_bulk_move_init(struct ttm_lru_bulk_move * bulk)396a9b0289SChristian König void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk)
406a9b0289SChristian König {
416a9b0289SChristian König 	memset(bulk, 0, sizeof(*bulk));
426a9b0289SChristian König }
436a9b0289SChristian König EXPORT_SYMBOL(ttm_lru_bulk_move_init);
446a9b0289SChristian König 
456a9b0289SChristian König /**
466a9b0289SChristian König  * ttm_lru_bulk_move_tail - bulk move range of resources to the LRU tail.
476a9b0289SChristian König  *
486a9b0289SChristian König  * @bulk: bulk move structure
496a9b0289SChristian König  *
506a9b0289SChristian König  * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that
516a9b0289SChristian König  * resource order never changes. Should be called with &ttm_device.lru_lock held.
526a9b0289SChristian König  */
ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move * bulk)536a9b0289SChristian König void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk)
546a9b0289SChristian König {
55b0e2c9eaSChristian König 	unsigned i, j;
566a9b0289SChristian König 
57b0e2c9eaSChristian König 	for (i = 0; i < TTM_NUM_MEM_TYPES; ++i) {
58b0e2c9eaSChristian König 		for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) {
59b0e2c9eaSChristian König 			struct ttm_lru_bulk_move_pos *pos = &bulk->pos[i][j];
606a9b0289SChristian König 			struct ttm_resource_manager *man;
616a9b0289SChristian König 
626a9b0289SChristian König 			if (!pos->first)
636a9b0289SChristian König 				continue;
646a9b0289SChristian König 
656a9b0289SChristian König 			lockdep_assert_held(&pos->first->bo->bdev->lru_lock);
666a9b0289SChristian König 			dma_resv_assert_held(pos->first->bo->base.resv);
676a9b0289SChristian König 			dma_resv_assert_held(pos->last->bo->base.resv);
686a9b0289SChristian König 
69b0e2c9eaSChristian König 			man = ttm_manager_type(pos->first->bo->bdev, i);
70b0e2c9eaSChristian König 			list_bulk_move_tail(&man->lru[j], &pos->first->lru,
716a9b0289SChristian König 					    &pos->last->lru);
726a9b0289SChristian König 		}
736a9b0289SChristian König 	}
746a9b0289SChristian König }
756a9b0289SChristian König EXPORT_SYMBOL(ttm_lru_bulk_move_tail);
766a9b0289SChristian König 
77fee2ede1SChristian König /* Return the bulk move pos object for this resource */
78fee2ede1SChristian König static struct ttm_lru_bulk_move_pos *
ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move * bulk,struct ttm_resource * res)79fee2ede1SChristian König ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res)
806a9b0289SChristian König {
81fee2ede1SChristian König 	return &bulk->pos[res->mem_type][res->bo->priority];
826a9b0289SChristian König }
836a9b0289SChristian König 
84fee2ede1SChristian König /* 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)85fee2ede1SChristian König static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos,
86fee2ede1SChristian König 				       struct ttm_resource *res)
87fee2ede1SChristian König {
88fee2ede1SChristian König 	if (pos->last != res) {
89fee2ede1SChristian König 		if (pos->first == res)
90fee2ede1SChristian König 			pos->first = list_next_entry(res, lru);
91fee2ede1SChristian König 		list_move(&res->lru, &pos->last->lru);
92fee2ede1SChristian König 		pos->last = res;
93fee2ede1SChristian König 	}
94fee2ede1SChristian König }
950f9cd1eaSChristian König 
96fee2ede1SChristian König /* Add the resource to a bulk_move cursor */
ttm_lru_bulk_move_add(struct ttm_lru_bulk_move * bulk,struct ttm_resource * res)97fee2ede1SChristian König static void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk,
98fee2ede1SChristian König 				  struct ttm_resource *res)
99fee2ede1SChristian König {
100fee2ede1SChristian König 	struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
101fee2ede1SChristian König 
102fee2ede1SChristian König 	if (!pos->first) {
103fee2ede1SChristian König 		pos->first = res;
104fee2ede1SChristian König 		pos->last = res;
105fee2ede1SChristian König 	} else {
106fee2ede1SChristian König 		ttm_lru_bulk_move_pos_tail(pos, res);
107fee2ede1SChristian König 	}
108fee2ede1SChristian König }
1090f9cd1eaSChristian König 
110fee2ede1SChristian König /* Remove the resource from a bulk_move range */
ttm_lru_bulk_move_del(struct ttm_lru_bulk_move * bulk,struct ttm_resource * res)111fee2ede1SChristian König static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
112fee2ede1SChristian König 				  struct ttm_resource *res)
113fee2ede1SChristian König {
114fee2ede1SChristian König 	struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
115fee2ede1SChristian König 
116fee2ede1SChristian König 	if (unlikely(WARN_ON(!pos->first || !pos->last) ||
117fee2ede1SChristian König 		     (pos->first == res && pos->last == res))) {
118fee2ede1SChristian König 		pos->first = NULL;
119fee2ede1SChristian König 		pos->last = NULL;
120fee2ede1SChristian König 	} else if (pos->first == res) {
121fee2ede1SChristian König 		pos->first = list_next_entry(res, lru);
122fee2ede1SChristian König 	} else if (pos->last == res) {
123fee2ede1SChristian König 		pos->last = list_prev_entry(res, lru);
124fee2ede1SChristian König 	} else {
125fee2ede1SChristian König 		list_move(&res->lru, &pos->last->lru);
1260f9cd1eaSChristian König 	}
1270f9cd1eaSChristian König }
1280f9cd1eaSChristian König 
1290f9cd1eaSChristian König /* 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)1300f9cd1eaSChristian König void ttm_resource_add_bulk_move(struct ttm_resource *res,
1310f9cd1eaSChristian König 				struct ttm_buffer_object *bo)
1320f9cd1eaSChristian König {
1330f9cd1eaSChristian König 	if (bo->bulk_move && !bo->pin_count)
1340f9cd1eaSChristian König 		ttm_lru_bulk_move_add(bo->bulk_move, res);
1350f9cd1eaSChristian König }
1360f9cd1eaSChristian König 
1370f9cd1eaSChristian König /* 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)1380f9cd1eaSChristian König void ttm_resource_del_bulk_move(struct ttm_resource *res,
1390f9cd1eaSChristian König 				struct ttm_buffer_object *bo)
1400f9cd1eaSChristian König {
1410f9cd1eaSChristian König 	if (bo->bulk_move && !bo->pin_count)
142fee2ede1SChristian König 		ttm_lru_bulk_move_del(bo->bulk_move, res);
143fee2ede1SChristian König }
1446a9b0289SChristian König 
1456a9b0289SChristian König /* Move a resource to the LRU or bulk tail */
ttm_resource_move_to_lru_tail(struct ttm_resource * res)1466a9b0289SChristian König void ttm_resource_move_to_lru_tail(struct ttm_resource *res)
1476a9b0289SChristian König {
1486a9b0289SChristian König 	struct ttm_buffer_object *bo = res->bo;
1496a9b0289SChristian König 	struct ttm_device *bdev = bo->bdev;
1506a9b0289SChristian König 
1516a9b0289SChristian König 	lockdep_assert_held(&bo->bdev->lru_lock);
152fee2ede1SChristian König 
153fee2ede1SChristian König 	if (bo->pin_count) {
154fee2ede1SChristian König 		list_move_tail(&res->lru, &bdev->pinned);
155fee2ede1SChristian König 
156fee2ede1SChristian König 	} else	if (bo->bulk_move) {
157fee2ede1SChristian König 		struct ttm_lru_bulk_move_pos *pos =
158fee2ede1SChristian König 			ttm_lru_bulk_move_pos(bo->bulk_move, res);
159fee2ede1SChristian König 
1606a9b0289SChristian König 		ttm_lru_bulk_move_pos_tail(pos, res);
1616a9b0289SChristian König 	} else {
1626a9b0289SChristian König 		struct ttm_resource_manager *man;
163fee2ede1SChristian König 
1646a9b0289SChristian König 		man = ttm_manager_type(bdev, res->mem_type);
1656a9b0289SChristian König 		list_move_tail(&res->lru, &man->lru[bo->priority]);
1666a9b0289SChristian König 	}
167de3688e4SChristian König }
168de3688e4SChristian König 
169de3688e4SChristian König /**
170de3688e4SChristian König  * ttm_resource_init - resource object constructure
171de3688e4SChristian König  * @bo: buffer object this resources is allocated for
1726a9b0289SChristian König  * @place: placement of the resource
173de3688e4SChristian König  * @res: the resource object to inistilize
1743eb7d96eSChristian König  *
1753eb7d96eSChristian König  * Initialize a new resource object. Counterpart of ttm_resource_fini().
1763eb7d96eSChristian König  */
ttm_resource_init(struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource * res)1773eb7d96eSChristian König void ttm_resource_init(struct ttm_buffer_object *bo,
1780e05fc49SChristian König                        const struct ttm_place *place,
1790e05fc49SChristian König                        struct ttm_resource *res)
1803eb7d96eSChristian König {
181e3c92eb4SSomalapuram Amaranath 	struct ttm_resource_manager *man;
1823eb7d96eSChristian König 
1833eb7d96eSChristian König 	res->start = 0;
1843eb7d96eSChristian König 	res->size = bo->base.size;
1853eb7d96eSChristian König 	res->mem_type = place->mem_type;
1863eb7d96eSChristian König 	res->placement = place->flags;
1873eb7d96eSChristian König 	res->bus.addr = NULL;
188fda8d552SChristian König 	res->bus.offset = 0;
1890e05fc49SChristian König 	res->bus.is_iomem = false;
1900e05fc49SChristian König 	res->bus.caching = ttm_cached;
1910e05fc49SChristian König 	res->bo = bo;
1920f9cd1eaSChristian König 
1930f9cd1eaSChristian König 	man = ttm_manager_type(bo->bdev, place->mem_type);
194fee2ede1SChristian König 	spin_lock(&bo->bdev->lru_lock);
1950f9cd1eaSChristian König 	if (bo->pin_count)
196e3c92eb4SSomalapuram Amaranath 		list_add_tail(&res->lru, &bo->bdev->pinned);
1970e05fc49SChristian König 	else
1983eb7d96eSChristian König 		list_add_tail(&res->lru, &man->lru[bo->priority]);
1993eb7d96eSChristian König 	man->usage += res->size;
2003eb7d96eSChristian König 	spin_unlock(&bo->bdev->lru_lock);
201de3688e4SChristian König }
202de3688e4SChristian König EXPORT_SYMBOL(ttm_resource_init);
203de3688e4SChristian König 
204de3688e4SChristian König /**
205de3688e4SChristian König  * ttm_resource_fini - resource destructor
206de3688e4SChristian König  * @man: the resource manager this resource belongs to
2076a9b0289SChristian König  * @res: the resource to clean up
2086a9b0289SChristian König  *
2096a9b0289SChristian König  * Should be used by resource manager backends to clean up the TTM resource
210de3688e4SChristian König  * objects before freeing the underlying structure. Makes sure the resource is
211de3688e4SChristian König  * removed from the LRU before destruction.
212de3688e4SChristian König  * Counterpart of ttm_resource_init().
213de3688e4SChristian König  */
ttm_resource_fini(struct ttm_resource_manager * man,struct ttm_resource * res)2146a9b0289SChristian König void ttm_resource_fini(struct ttm_resource_manager *man,
2156a9b0289SChristian König 		       struct ttm_resource *res)
2166a9b0289SChristian König {
2176a9b0289SChristian König 	struct ttm_device *bdev = man->bdev;
218e3c92eb4SSomalapuram Amaranath 
2196a9b0289SChristian König 	spin_lock(&bdev->lru_lock);
220de3688e4SChristian König 	list_del_init(&res->lru);
221de3688e4SChristian König 	man->usage -= res->size;
222de3688e4SChristian König 	spin_unlock(&bdev->lru_lock);
223b2458726SChristian König }
224b2458726SChristian König EXPORT_SYMBOL(ttm_resource_fini);
225bfa3357eSChristian König 
ttm_resource_alloc(struct ttm_buffer_object * bo,const struct ttm_place * place,struct ttm_resource ** res_ptr)226b2458726SChristian König int ttm_resource_alloc(struct ttm_buffer_object *bo,
227b2458726SChristian König 		       const struct ttm_place *place,
228d79025c7SChristian König 		       struct ttm_resource **res_ptr)
2290f9cd1eaSChristian König {
230bfa3357eSChristian König 	struct ttm_resource_manager *man =
2310f9cd1eaSChristian König 		ttm_manager_type(bo->bdev, place->mem_type);
2320f9cd1eaSChristian König 	int ret;
2330f9cd1eaSChristian König 
2340f9cd1eaSChristian König 	ret = man->func->alloc(man, bo, place, res_ptr);
2350f9cd1eaSChristian König 	if (ret)
2360f9cd1eaSChristian König 		return ret;
2370f9cd1eaSChristian König 
2380f9cd1eaSChristian König 	spin_lock(&bo->bdev->lru_lock);
239bfa3357eSChristian König 	ttm_resource_add_bulk_move(*res_ptr, bo);
240b2458726SChristian König 	spin_unlock(&bo->bdev->lru_lock);
241bfa3357eSChristian König 	return 0;
242bfa3357eSChristian König }
243bfa3357eSChristian König 
ttm_resource_free(struct ttm_buffer_object * bo,struct ttm_resource ** res)244bfa3357eSChristian König void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res)
245bfa3357eSChristian König {
246bfa3357eSChristian König 	struct ttm_resource_manager *man;
247bfa3357eSChristian König 
248fee2ede1SChristian König 	if (!*res)
2490f9cd1eaSChristian König 		return;
250fee2ede1SChristian König 
251bfa3357eSChristian König 	spin_lock(&bo->bdev->lru_lock);
252bfa3357eSChristian König 	ttm_resource_del_bulk_move(*res, bo);
253bfa3357eSChristian König 	spin_unlock(&bo->bdev->lru_lock);
254b2458726SChristian König 	man = ttm_manager_type(bo->bdev, (*res)->mem_type);
255b2458726SChristian König 	man->func->free(man, *res);
256b2458726SChristian König 	*res = NULL;
25754443270SArunpravin Paneer Selvam }
25854443270SArunpravin Paneer Selvam EXPORT_SYMBOL(ttm_resource_free);
25954443270SArunpravin Paneer Selvam 
26054443270SArunpravin Paneer Selvam /**
26154443270SArunpravin Paneer Selvam  * ttm_resource_intersects - test for intersection
26254443270SArunpravin Paneer Selvam  *
26354443270SArunpravin Paneer Selvam  * @bdev: TTM device structure
26454443270SArunpravin Paneer Selvam  * @res: The resource to test
26554443270SArunpravin Paneer Selvam  * @place: The placement to test
26654443270SArunpravin Paneer Selvam  * @size: How many bytes the new allocation needs.
26754443270SArunpravin Paneer Selvam  *
26854443270SArunpravin Paneer Selvam  * Test if @res intersects with @place and @size. Used for testing if evictions
26954443270SArunpravin Paneer Selvam  * are valueable or not.
27054443270SArunpravin Paneer Selvam  *
27154443270SArunpravin Paneer Selvam  * Returns true if the res placement intersects with @place and @size.
27254443270SArunpravin Paneer Selvam  */
ttm_resource_intersects(struct ttm_device * bdev,struct ttm_resource * res,const struct ttm_place * place,size_t size)27354443270SArunpravin Paneer Selvam bool ttm_resource_intersects(struct ttm_device *bdev,
27454443270SArunpravin Paneer Selvam 			     struct ttm_resource *res,
27554443270SArunpravin Paneer Selvam 			     const struct ttm_place *place,
27654443270SArunpravin Paneer Selvam 			     size_t size)
27754443270SArunpravin Paneer Selvam {
27854443270SArunpravin Paneer Selvam 	struct ttm_resource_manager *man;
27954443270SArunpravin Paneer Selvam 
28054443270SArunpravin Paneer Selvam 	if (!res)
2816d3c900cSArunpravin Paneer Selvam 		return false;
28254443270SArunpravin Paneer Selvam 
28354443270SArunpravin Paneer Selvam 	man = ttm_manager_type(bdev, res->mem_type);
28454443270SArunpravin Paneer Selvam 	if (!place || !man->func->intersects)
28554443270SArunpravin Paneer Selvam 		return true;
28654443270SArunpravin Paneer Selvam 
28754443270SArunpravin Paneer Selvam 	return man->func->intersects(man, res, place, size);
28854443270SArunpravin Paneer Selvam }
28954443270SArunpravin Paneer Selvam 
29054443270SArunpravin Paneer Selvam /**
29154443270SArunpravin Paneer Selvam  * ttm_resource_compatible - test for compatibility
29254443270SArunpravin Paneer Selvam  *
29354443270SArunpravin Paneer Selvam  * @bdev: TTM device structure
29454443270SArunpravin Paneer Selvam  * @res: The resource to test
29554443270SArunpravin Paneer Selvam  * @place: The placement to test
29654443270SArunpravin Paneer Selvam  * @size: How many bytes the new allocation needs.
29754443270SArunpravin Paneer Selvam  *
29854443270SArunpravin Paneer Selvam  * Test if @res compatible with @place and @size.
29954443270SArunpravin Paneer Selvam  *
30054443270SArunpravin Paneer Selvam  * Returns true if the res placement compatible with @place and @size.
30154443270SArunpravin Paneer Selvam  */
ttm_resource_compatible(struct ttm_device * bdev,struct ttm_resource * res,const struct ttm_place * place,size_t size)30254443270SArunpravin Paneer Selvam bool ttm_resource_compatible(struct ttm_device *bdev,
30354443270SArunpravin Paneer Selvam 			     struct ttm_resource *res,
30454443270SArunpravin Paneer Selvam 			     const struct ttm_place *place,
30554443270SArunpravin Paneer Selvam 			     size_t size)
30654443270SArunpravin Paneer Selvam {
30754443270SArunpravin Paneer Selvam 	struct ttm_resource_manager *man;
30854443270SArunpravin Paneer Selvam 
30954443270SArunpravin Paneer Selvam 	if (!res || !place)
3106d3c900cSArunpravin Paneer Selvam 		return false;
31154443270SArunpravin Paneer Selvam 
31254443270SArunpravin Paneer Selvam 	man = ttm_manager_type(bdev, res->mem_type);
31354443270SArunpravin Paneer Selvam 	if (!man->func->compatible)
31454443270SArunpravin Paneer Selvam 		return true;
31554443270SArunpravin Paneer Selvam 
31698cca519SChristian König 	return man->func->compatible(man, res, place, size);
31798cca519SChristian König }
31898cca519SChristian König 
ttm_resource_places_compat(struct ttm_resource * res,const struct ttm_place * places,unsigned num_placement)31998cca519SChristian König static bool ttm_resource_places_compat(struct ttm_resource *res,
32054443270SArunpravin Paneer Selvam 				       const struct ttm_place *places,
32154443270SArunpravin Paneer Selvam 				       unsigned num_placement)
32298cca519SChristian König {
32398cca519SChristian König 	struct ttm_buffer_object *bo = res->bo;
32498cca519SChristian König 	struct ttm_device *bdev = bo->bdev;
32598cca519SChristian König 	unsigned i;
32698cca519SChristian König 
32798cca519SChristian König 	if (res->placement & TTM_PL_FLAG_TEMPORARY)
32898cca519SChristian König 		return false;
32998cca519SChristian König 
33054443270SArunpravin Paneer Selvam 	for (i = 0; i < num_placement; i++) {
33198cca519SChristian König 		const struct ttm_place *heap = &places[i];
33298cca519SChristian König 
33398cca519SChristian König 		if (!ttm_resource_compatible(bdev, res, heap, bo->base.size))
33498cca519SChristian König 			continue;
33598cca519SChristian König 
33698cca519SChristian König 		if ((res->mem_type == heap->mem_type) &&
33798cca519SChristian König 		    (!(heap->flags & TTM_PL_FLAG_CONTIGUOUS) ||
33898cca519SChristian König 		     (res->placement & TTM_PL_FLAG_CONTIGUOUS)))
33998cca519SChristian König 			return true;
34098cca519SChristian König 	}
34198cca519SChristian König 	return false;
34298cca519SChristian König }
34398cca519SChristian König 
34498cca519SChristian König /**
34598cca519SChristian König  * ttm_resource_compat - check if resource is compatible with placement
34698cca519SChristian König  *
34798cca519SChristian König  * @res: the resource to check
34898cca519SChristian König  * @placement: the placement to check against
34998cca519SChristian König  *
35098cca519SChristian König  * Returns true if the placement is compatible.
35198cca519SChristian König  */
ttm_resource_compat(struct ttm_resource * res,struct ttm_placement * placement)35298cca519SChristian König bool ttm_resource_compat(struct ttm_resource *res,
35398cca519SChristian König 			 struct ttm_placement *placement)
35498cca519SChristian König {
35598cca519SChristian König 	if (ttm_resource_places_compat(res, placement->placement,
35698cca519SChristian König 				       placement->num_placement))
35798cca519SChristian König 		return true;
35898cca519SChristian König 
35998cca519SChristian König 	if ((placement->busy_placement != placement->placement ||
36098cca519SChristian König 	     placement->num_busy_placement > placement->num_placement) &&
36198cca519SChristian König 	    ttm_resource_places_compat(res, placement->busy_placement,
36298cca519SChristian König 				       placement->num_busy_placement))
36398cca519SChristian König 		return true;
36498cca519SChristian König 
365fda8d552SChristian König 	return false;
366fda8d552SChristian König }
367fda8d552SChristian König 
ttm_resource_set_bo(struct ttm_resource * res,struct ttm_buffer_object * bo)368fda8d552SChristian König void ttm_resource_set_bo(struct ttm_resource *res,
369fda8d552SChristian König 			 struct ttm_buffer_object *bo)
370fda8d552SChristian König {
371fda8d552SChristian König 	spin_lock(&bo->bdev->lru_lock);
372fda8d552SChristian König 	res->bo = bo;
373b2458726SChristian König 	spin_unlock(&bo->bdev->lru_lock);
374b2458726SChristian König }
375b2458726SChristian König 
376b2458726SChristian König /**
3773f268ef0SChristian König  * ttm_resource_manager_init
37890d4aa20SChristian König  *
379b2458726SChristian König  * @man: memory manager object to init
380b2458726SChristian König  * @bdev: ttm device this manager belongs to
381b2458726SChristian König  * @size: size of managed resources in arbitrary units
382b2458726SChristian König  *
3833f268ef0SChristian König  * Initialise core parts of a manager object.
38490d4aa20SChristian König  */
ttm_resource_manager_init(struct ttm_resource_manager * man,struct ttm_device * bdev,uint64_t size)385b2458726SChristian König void ttm_resource_manager_init(struct ttm_resource_manager *man,
386b2458726SChristian König 			       struct ttm_device *bdev,
387b2458726SChristian König 			       uint64_t size)
388b2458726SChristian König {
3893f268ef0SChristian König 	unsigned i;
39090d4aa20SChristian König 
3910e05fc49SChristian König 	spin_lock_init(&man->move_lock);
392b2458726SChristian König 	man->bdev = bdev;
393b2458726SChristian König 	man->size = size;
394b2458726SChristian König 	man->usage = 0;
395b2458726SChristian König 
396b2458726SChristian König 	for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i)
397b2458726SChristian König 		INIT_LIST_HEAD(&man->lru[i]);
398b2458726SChristian König 	man->move = NULL;
399b2458726SChristian König }
4004ce032d6SChristian König EXPORT_SYMBOL(ttm_resource_manager_init);
401b2458726SChristian König 
402b2458726SChristian König /*
403b2458726SChristian König  * ttm_resource_manager_evict_all
404b2458726SChristian König  *
4054ce032d6SChristian König  * @bdev - device to use
406b2458726SChristian König  * @man - manager to use
407b2458726SChristian König  *
4088af8a109SChristian König  * Evict all the objects out of a memory manager until it is empty.
409b2458726SChristian König  * Part of memory manager cleanup sequence.
410b2458726SChristian König  */
ttm_resource_manager_evict_all(struct ttm_device * bdev,struct ttm_resource_manager * man)411b2458726SChristian König int ttm_resource_manager_evict_all(struct ttm_device *bdev,
412b2458726SChristian König 				   struct ttm_resource_manager *man)
413b2458726SChristian König {
414c44dfe4dSChristian König 	struct ttm_operation_ctx ctx = {
415b2458726SChristian König 		.interruptible = false,
416b2458726SChristian König 		.no_wait_gpu = false,
417b2458726SChristian König 		.force_alloc = true
418b2458726SChristian König 	};
419b2458726SChristian König 	struct dma_fence *fence;
420b2458726SChristian König 	int ret;
421b2458726SChristian König 	unsigned i;
422b2458726SChristian König 
423b2458726SChristian König 	/*
424a1f091f8SChristian König 	 * Can't use standard list traversal since we're unlocking.
425b2458726SChristian König 	 */
426b2458726SChristian König 
427a1f091f8SChristian König 	spin_lock(&bdev->lru_lock);
428b2458726SChristian König 	for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
429b2458726SChristian König 		while (!list_empty(&man->lru[i])) {
430b2458726SChristian König 			spin_unlock(&bdev->lru_lock);
431b2458726SChristian König 			ret = ttm_mem_evict_first(bdev, man, NULL, &ctx,
432a1f091f8SChristian König 						  NULL);
433b2458726SChristian König 			if (ret)
434b2458726SChristian König 				return ret;
435a1f091f8SChristian König 			spin_lock(&bdev->lru_lock);
436b2458726SChristian König 		}
437b2458726SChristian König 	}
438b2458726SChristian König 	spin_unlock(&bdev->lru_lock);
439b2458726SChristian König 
440b2458726SChristian König 	spin_lock(&man->move_lock);
441b2458726SChristian König 	fence = dma_fence_get(man->move);
442b2458726SChristian König 	spin_unlock(&man->move_lock);
443b2458726SChristian König 
444b2458726SChristian König 	if (fence) {
445b2458726SChristian König 		ret = dma_fence_wait(fence, false);
446b2458726SChristian König 		dma_fence_put(fence);
447b2458726SChristian König 		if (ret)
448b2458726SChristian König 			return ret;
449b2458726SChristian König 	}
4504ce032d6SChristian König 
451b2458726SChristian König 	return 0;
452b2458726SChristian König }
4530e05fc49SChristian König EXPORT_SYMBOL(ttm_resource_manager_evict_all);
4540e05fc49SChristian König 
4550e05fc49SChristian König /**
4560e05fc49SChristian König  * ttm_resource_manager_usage
4570e05fc49SChristian König  *
4580e05fc49SChristian König  * @man: A memory manager object.
4590e05fc49SChristian König  *
4600e05fc49SChristian König  * Return how many resources are currently used.
4610e05fc49SChristian König  */
ttm_resource_manager_usage(struct ttm_resource_manager * man)4620e05fc49SChristian König uint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man)
4630e05fc49SChristian König {
4640e05fc49SChristian König 	uint64_t usage;
4650e05fc49SChristian König 
4660e05fc49SChristian König 	spin_lock(&man->bdev->lru_lock);
4670e05fc49SChristian König 	usage = man->usage;
4680e05fc49SChristian König 	spin_unlock(&man->bdev->lru_lock);
4690e05fc49SChristian König 	return usage;
4700e05fc49SChristian König }
471b2458726SChristian König EXPORT_SYMBOL(ttm_resource_manager_usage);
472b2458726SChristian König 
473b2458726SChristian König /**
474b2458726SChristian König  * ttm_resource_manager_debug
475b2458726SChristian König  *
476b2458726SChristian König  * @man: manager type to dump.
477b2458726SChristian König  * @p: printer to use for debug.
478b2458726SChristian König  */
ttm_resource_manager_debug(struct ttm_resource_manager * man,struct drm_printer * p)479b2458726SChristian König void ttm_resource_manager_debug(struct ttm_resource_manager *man,
480b2458726SChristian König 				struct drm_printer *p)
481b2458726SChristian König {
4820e05fc49SChristian König 	drm_printf(p, "  use_type: %d\n", man->use_type);
483b072b9cdSChristian König 	drm_printf(p, "  use_tt: %d\n", man->use_tt);
484b072b9cdSChristian König 	drm_printf(p, "  size: %llu\n", man->size);
485b2458726SChristian König 	drm_printf(p, "  usage: %llu\n", ttm_resource_manager_usage(man));
486b2458726SChristian König 	if (man->func->debug)
4873bf3710eSThomas Hellström 		man->func->debug(man, p);
4885d05b988SChristian König }
4895d05b988SChristian König EXPORT_SYMBOL(ttm_resource_manager_debug);
4905d05b988SChristian König 
4915d05b988SChristian König /**
4925d05b988SChristian König  * ttm_resource_manager_first
4935d05b988SChristian König  *
4945d05b988SChristian König  * @man: resource manager to iterate over
4955d05b988SChristian König  * @cursor: cursor to record the position
4965d05b988SChristian König  *
4975d05b988SChristian König  * Returns the first resource from the resource manager.
4985d05b988SChristian König  */
4995d05b988SChristian König struct ttm_resource *
ttm_resource_manager_first(struct ttm_resource_manager * man,struct ttm_resource_cursor * cursor)5005d05b988SChristian König ttm_resource_manager_first(struct ttm_resource_manager *man,
5015d05b988SChristian König 			   struct ttm_resource_cursor *cursor)
5025d05b988SChristian König {
5035d05b988SChristian König 	struct ttm_resource *res;
5045d05b988SChristian König 
5055d05b988SChristian König 	lockdep_assert_held(&man->bdev->lru_lock);
5065d05b988SChristian König 
5075d05b988SChristian König 	for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY;
5085d05b988SChristian König 	     ++cursor->priority)
5095d05b988SChristian König 		list_for_each_entry(res, &man->lru[cursor->priority], lru)
5105d05b988SChristian König 			return res;
5115d05b988SChristian König 
5125d05b988SChristian König 	return NULL;
5135d05b988SChristian König }
5145d05b988SChristian König 
5155d05b988SChristian König /**
5165d05b988SChristian König  * ttm_resource_manager_next
5175d05b988SChristian König  *
5185d05b988SChristian König  * @man: resource manager to iterate over
5195d05b988SChristian König  * @cursor: cursor to record the position
5205d05b988SChristian König  * @res: the current resource pointer
5215d05b988SChristian König  *
5225d05b988SChristian König  * Returns the next resource from the resource manager.
5235d05b988SChristian König  */
5245d05b988SChristian König struct ttm_resource *
ttm_resource_manager_next(struct ttm_resource_manager * man,struct ttm_resource_cursor * cursor,struct ttm_resource * res)5255d05b988SChristian König ttm_resource_manager_next(struct ttm_resource_manager *man,
5265d05b988SChristian König 			  struct ttm_resource_cursor *cursor,
5275d05b988SChristian König 			  struct ttm_resource *res)
5285d05b988SChristian König {
5295d05b988SChristian König 	lockdep_assert_held(&man->bdev->lru_lock);
5305d05b988SChristian König 
5315d05b988SChristian König 	list_for_each_entry_continue(res, &man->lru[cursor->priority], lru)
5325d05b988SChristian König 		return res;
5335d05b988SChristian König 
5345d05b988SChristian König 	for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY;
5355d05b988SChristian König 	     ++cursor->priority)
5365d05b988SChristian König 		list_for_each_entry(res, &man->lru[cursor->priority], lru)
5375d05b988SChristian König 			return res;
5385d05b988SChristian König 
5393bf3710eSThomas Hellström 	return NULL;
5407938f421SLucas De Marchi }
5413bf3710eSThomas Hellström 
ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter * iter,struct iosys_map * dmap,pgoff_t i)5423bf3710eSThomas Hellström static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter,
5433bf3710eSThomas Hellström 					  struct iosys_map *dmap,
5443bf3710eSThomas Hellström 					  pgoff_t i)
5453bf3710eSThomas Hellström {
5463bf3710eSThomas Hellström 	struct ttm_kmap_iter_iomap *iter_io =
5473bf3710eSThomas Hellström 		container_of(iter, typeof(*iter_io), base);
5483bf3710eSThomas Hellström 	void __iomem *addr;
5493bf3710eSThomas Hellström 
5503bf3710eSThomas Hellström retry:
5513bf3710eSThomas Hellström 	while (i >= iter_io->cache.end) {
5523bf3710eSThomas Hellström 		iter_io->cache.sg = iter_io->cache.sg ?
5533bf3710eSThomas Hellström 			sg_next(iter_io->cache.sg) : iter_io->st->sgl;
5543bf3710eSThomas Hellström 		iter_io->cache.i = iter_io->cache.end;
5553bf3710eSThomas Hellström 		iter_io->cache.end += sg_dma_len(iter_io->cache.sg) >>
5563bf3710eSThomas Hellström 			PAGE_SHIFT;
5573bf3710eSThomas Hellström 		iter_io->cache.offs = sg_dma_address(iter_io->cache.sg) -
5583bf3710eSThomas Hellström 			iter_io->start;
5593bf3710eSThomas Hellström 	}
5603bf3710eSThomas Hellström 
5613bf3710eSThomas Hellström 	if (i < iter_io->cache.i) {
5623bf3710eSThomas Hellström 		iter_io->cache.end = 0;
5633bf3710eSThomas Hellström 		iter_io->cache.sg = NULL;
5643bf3710eSThomas Hellström 		goto retry;
5653bf3710eSThomas Hellström 	}
5663bf3710eSThomas Hellström 
5677938f421SLucas De Marchi 	addr = io_mapping_map_local_wc(iter_io->iomap, iter_io->cache.offs +
5683bf3710eSThomas Hellström 				       (((resource_size_t)i - iter_io->cache.i)
5693bf3710eSThomas Hellström 					<< PAGE_SHIFT));
5703bf3710eSThomas Hellström 	iosys_map_set_vaddr_iomem(dmap, addr);
5717938f421SLucas De Marchi }
5723bf3710eSThomas Hellström 
ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter * iter,struct iosys_map * map)5733bf3710eSThomas Hellström static void ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter *iter,
5743bf3710eSThomas Hellström 					    struct iosys_map *map)
5753bf3710eSThomas Hellström {
5763bf3710eSThomas Hellström 	io_mapping_unmap_local(map->vaddr_iomem);
5773bf3710eSThomas Hellström }
5783bf3710eSThomas Hellström 
5793bf3710eSThomas Hellström static const struct ttm_kmap_iter_ops ttm_kmap_iter_io_ops = {
5803bf3710eSThomas Hellström 	.map_local =  ttm_kmap_iter_iomap_map_local,
5813bf3710eSThomas Hellström 	.unmap_local = ttm_kmap_iter_iomap_unmap_local,
5823bf3710eSThomas Hellström 	.maps_tt = false,
5833bf3710eSThomas Hellström };
5843bf3710eSThomas Hellström 
5853bf3710eSThomas Hellström /**
5863bf3710eSThomas Hellström  * ttm_kmap_iter_iomap_init - Initialize a struct ttm_kmap_iter_iomap
5873bf3710eSThomas Hellström  * @iter_io: The struct ttm_kmap_iter_iomap to initialize.
5883bf3710eSThomas Hellström  * @iomap: The struct io_mapping representing the underlying linear io_memory.
5893bf3710eSThomas Hellström  * @st: sg_table into @iomap, representing the memory of the struct
5903bf3710eSThomas Hellström  * ttm_resource.
5913bf3710eSThomas Hellström  * @start: Offset that needs to be subtracted from @st to make
5923bf3710eSThomas Hellström  * sg_dma_address(st->sgl) - @start == 0 for @iomap start.
5933bf3710eSThomas Hellström  *
5943bf3710eSThomas Hellström  * Return: Pointer to the embedded struct ttm_kmap_iter.
5953bf3710eSThomas Hellström  */
5963bf3710eSThomas Hellström 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)5973bf3710eSThomas Hellström ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io,
5983bf3710eSThomas Hellström 			 struct io_mapping *iomap,
5993bf3710eSThomas Hellström 			 struct sg_table *st,
6003bf3710eSThomas Hellström 			 resource_size_t start)
6013bf3710eSThomas Hellström {
6023bf3710eSThomas Hellström 	iter_io->base.ops = &ttm_kmap_iter_io_ops;
6033bf3710eSThomas Hellström 	iter_io->iomap = iomap;
6043bf3710eSThomas Hellström 	iter_io->st = st;
6053bf3710eSThomas Hellström 	iter_io->start = start;
6063bf3710eSThomas Hellström 	memset(&iter_io->cache, 0, sizeof(iter_io->cache));
6073bf3710eSThomas Hellström 
6083bf3710eSThomas Hellström 	return &iter_io->base;
6093bf3710eSThomas Hellström }
6103bf3710eSThomas Hellström EXPORT_SYMBOL(ttm_kmap_iter_iomap_init);
6113bf3710eSThomas Hellström 
6123bf3710eSThomas Hellström /**
6133bf3710eSThomas Hellström  * DOC: Linear io iterator
6143bf3710eSThomas Hellström  *
6153bf3710eSThomas Hellström  * This code should die in the not too near future. Best would be if we could
6163bf3710eSThomas Hellström  * make io-mapping use memremap for all io memory, and have memremap
6173bf3710eSThomas Hellström  * implement a kmap_local functionality. We could then strip a huge amount of
6183bf3710eSThomas Hellström  * code. These linear io iterators are implemented to mimic old functionality,
6193bf3710eSThomas Hellström  * and they don't use kmap_local semantics at all internally. Rather ioremap or
6203bf3710eSThomas Hellström  * friends, and at least on 32-bit they add global TLB flushes and points
6213bf3710eSThomas Hellström  * of failure.
6227938f421SLucas De Marchi  */
6233bf3710eSThomas Hellström 
ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter * iter,struct iosys_map * dmap,pgoff_t i)6243bf3710eSThomas Hellström static void ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter *iter,
6253bf3710eSThomas Hellström 					      struct iosys_map *dmap,
6263bf3710eSThomas Hellström 					      pgoff_t i)
6273bf3710eSThomas Hellström {
6283bf3710eSThomas Hellström 	struct ttm_kmap_iter_linear_io *iter_io =
6297938f421SLucas De Marchi 		container_of(iter, typeof(*iter_io), base);
6303bf3710eSThomas Hellström 
6313bf3710eSThomas Hellström 	*dmap = iter_io->dmap;
6323bf3710eSThomas Hellström 	iosys_map_incr(dmap, i * PAGE_SIZE);
6333bf3710eSThomas Hellström }
6343bf3710eSThomas Hellström 
6353bf3710eSThomas Hellström static const struct ttm_kmap_iter_ops ttm_kmap_iter_linear_io_ops = {
6363bf3710eSThomas Hellström 	.map_local =  ttm_kmap_iter_linear_io_map_local,
6373bf3710eSThomas Hellström 	.maps_tt = false,
6383bf3710eSThomas Hellström };
6393bf3710eSThomas Hellström 
6403bf3710eSThomas Hellström /**
6413bf3710eSThomas Hellström  * ttm_kmap_iter_linear_io_init - Initialize an iterator for linear io memory
6423bf3710eSThomas Hellström  * @iter_io: The iterator to initialize
6433bf3710eSThomas Hellström  * @bdev: The TTM device
6443bf3710eSThomas Hellström  * @mem: The ttm resource representing the iomap.
6453bf3710eSThomas Hellström  *
6463bf3710eSThomas Hellström  * This function is for internal TTM use only. It sets up a memcpy kmap iterator
6473bf3710eSThomas Hellström  * pointing at a linear chunk of io memory.
6483bf3710eSThomas Hellström  *
6493bf3710eSThomas Hellström  * Return: A pointer to the embedded struct ttm_kmap_iter or error pointer on
6503bf3710eSThomas Hellström  * failure.
6513bf3710eSThomas Hellström  */
6523bf3710eSThomas Hellström 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)6533bf3710eSThomas Hellström ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io,
6543bf3710eSThomas Hellström 			     struct ttm_device *bdev,
6553bf3710eSThomas Hellström 			     struct ttm_resource *mem)
6563bf3710eSThomas Hellström {
6573bf3710eSThomas Hellström 	int ret;
6583bf3710eSThomas Hellström 
6593bf3710eSThomas Hellström 	ret = ttm_mem_io_reserve(bdev, mem);
6603bf3710eSThomas Hellström 	if (ret)
6613bf3710eSThomas Hellström 		goto out_err;
6623bf3710eSThomas Hellström 	if (!mem->bus.is_iomem) {
6633bf3710eSThomas Hellström 		ret = -EINVAL;
6643bf3710eSThomas Hellström 		goto out_io_free;
6657938f421SLucas De Marchi 	}
6663bf3710eSThomas Hellström 
6673bf3710eSThomas Hellström 	if (mem->bus.addr) {
6683bf3710eSThomas Hellström 		iosys_map_set_vaddr(&iter_io->dmap, mem->bus.addr);
6693bf3710eSThomas Hellström 		iter_io->needs_unmap = false;
6703bf3710eSThomas Hellström 	} else {
6717938f421SLucas De Marchi 		iter_io->needs_unmap = true;
6723bf3710eSThomas Hellström 		memset(&iter_io->dmap, 0, sizeof(iter_io->dmap));
673e3c92eb4SSomalapuram Amaranath 		if (mem->bus.caching == ttm_write_combined)
6743bf3710eSThomas Hellström 			iosys_map_set_vaddr_iomem(&iter_io->dmap,
6757938f421SLucas De Marchi 						  ioremap_wc(mem->bus.offset,
676e3c92eb4SSomalapuram Amaranath 							     mem->size));
6773bf3710eSThomas Hellström 		else if (mem->bus.caching == ttm_cached)
6783bf3710eSThomas Hellström 			iosys_map_set_vaddr(&iter_io->dmap,
6793bf3710eSThomas Hellström 					    memremap(mem->bus.offset, mem->size,
6803bf3710eSThomas Hellström 						     MEMREMAP_WB |
6813bf3710eSThomas Hellström 						     MEMREMAP_WT |
6827938f421SLucas De Marchi 						     MEMREMAP_WC));
6837938f421SLucas De Marchi 
6843bf3710eSThomas Hellström 		/* If uncached requested or if mapping cached or wc failed */
685e3c92eb4SSomalapuram Amaranath 		if (iosys_map_is_null(&iter_io->dmap))
6863bf3710eSThomas Hellström 			iosys_map_set_vaddr_iomem(&iter_io->dmap,
6877938f421SLucas De Marchi 						  ioremap(mem->bus.offset,
6883bf3710eSThomas Hellström 							  mem->size));
6893bf3710eSThomas Hellström 
6903bf3710eSThomas Hellström 		if (iosys_map_is_null(&iter_io->dmap)) {
6913bf3710eSThomas Hellström 			ret = -ENOMEM;
6923bf3710eSThomas Hellström 			goto out_io_free;
6933bf3710eSThomas Hellström 		}
6943bf3710eSThomas Hellström 	}
6953bf3710eSThomas Hellström 
6963bf3710eSThomas Hellström 	iter_io->base.ops = &ttm_kmap_iter_linear_io_ops;
6973bf3710eSThomas Hellström 	return &iter_io->base;
6983bf3710eSThomas Hellström 
6993bf3710eSThomas Hellström out_io_free:
7003bf3710eSThomas Hellström 	ttm_mem_io_free(bdev, mem);
7013bf3710eSThomas Hellström out_err:
7023bf3710eSThomas Hellström 	return ERR_PTR(ret);
7033bf3710eSThomas Hellström }
7043bf3710eSThomas Hellström 
7053bf3710eSThomas Hellström /**
7063bf3710eSThomas Hellström  * ttm_kmap_iter_linear_io_fini - Clean up an iterator for linear io memory
7073bf3710eSThomas Hellström  * @iter_io: The iterator to initialize
7083bf3710eSThomas Hellström  * @bdev: The TTM device
7093bf3710eSThomas Hellström  * @mem: The ttm resource representing the iomap.
7103bf3710eSThomas Hellström  *
7113bf3710eSThomas Hellström  * This function is for internal TTM use only. It cleans up a memcpy kmap
7123bf3710eSThomas Hellström  * iterator initialized by ttm_kmap_iter_linear_io_init.
7133bf3710eSThomas Hellström  */
7143bf3710eSThomas Hellström void
ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io * iter_io,struct ttm_device * bdev,struct ttm_resource * mem)7153bf3710eSThomas Hellström ttm_kmap_iter_linear_io_fini(struct ttm_kmap_iter_linear_io *iter_io,
7167938f421SLucas De Marchi 			     struct ttm_device *bdev,
7173bf3710eSThomas Hellström 			     struct ttm_resource *mem)
7183bf3710eSThomas Hellström {
7193bf3710eSThomas Hellström 	if (iter_io->needs_unmap && iosys_map_is_set(&iter_io->dmap)) {
7203bf3710eSThomas Hellström 		if (iter_io->dmap.is_iomem)
7213bf3710eSThomas Hellström 			iounmap(iter_io->dmap.vaddr_iomem);
7223bf3710eSThomas Hellström 		else
7233bf3710eSThomas Hellström 			memunmap(iter_io->dmap.vaddr);
7243bf3710eSThomas Hellström 	}
7258cd9efd1SZack Rusin 
7268cd9efd1SZack Rusin 	ttm_mem_io_free(bdev, mem);
7278cd9efd1SZack Rusin }
7288cd9efd1SZack Rusin 
7298cd9efd1SZack Rusin #if defined(CONFIG_DEBUG_FS)
7308cd9efd1SZack Rusin 
ttm_resource_manager_show(struct seq_file * m,void * unused)7318cd9efd1SZack Rusin static int ttm_resource_manager_show(struct seq_file *m, void *unused)
7328cd9efd1SZack Rusin {
7338cd9efd1SZack Rusin 	struct ttm_resource_manager *man =
7348cd9efd1SZack Rusin 		(struct ttm_resource_manager *)m->private;
7358cd9efd1SZack Rusin 	struct drm_printer p = drm_seq_file_printer(m);
7368cd9efd1SZack Rusin 	ttm_resource_manager_debug(man, &p);
7378cd9efd1SZack Rusin 	return 0;
7388cd9efd1SZack Rusin }
7398cd9efd1SZack Rusin DEFINE_SHOW_ATTRIBUTE(ttm_resource_manager);
7408cd9efd1SZack Rusin 
7418cd9efd1SZack Rusin #endif
7428cd9efd1SZack Rusin 
7438cd9efd1SZack Rusin /**
7448cd9efd1SZack Rusin  * ttm_resource_manager_create_debugfs - Create debugfs entry for specified
7458cd9efd1SZack Rusin  * resource manager.
7468cd9efd1SZack Rusin  * @man: The TTM resource manager for which the debugfs stats file be creates
7478cd9efd1SZack Rusin  * @parent: debugfs directory in which the file will reside
7488cd9efd1SZack Rusin  * @name: The filename to create.
7498cd9efd1SZack Rusin  *
7508cd9efd1SZack Rusin  * This function setups up a debugfs file that can be used to look
7518cd9efd1SZack Rusin  * at debug statistics of the specified ttm_resource_manager.
7528cd9efd1SZack Rusin  */
ttm_resource_manager_create_debugfs(struct ttm_resource_manager * man,struct dentry * parent,const char * name)7538cd9efd1SZack Rusin void ttm_resource_manager_create_debugfs(struct ttm_resource_manager *man,
7548cd9efd1SZack Rusin 					 struct dentry * parent,
7558cd9efd1SZack Rusin 					 const char *name)
7568cd9efd1SZack Rusin {
7578cd9efd1SZack Rusin #if defined(CONFIG_DEBUG_FS)
7588cd9efd1SZack Rusin 	debugfs_create_file(name, 0444, parent, man, &ttm_resource_manager_fops);
759 #endif
760 }
761 EXPORT_SYMBOL(ttm_resource_manager_create_debugfs);
762