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