xref: /linux/drivers/gpu/drm/xe/xe_drm_client.c (revision 260f6f4fda93c8485c8037865c941b42b9cba5d2)
18f965392STejas Upadhyay // SPDX-License-Identifier: MIT
28f965392STejas Upadhyay /*
38f965392STejas Upadhyay  * Copyright © 2023 Intel Corporation
48f965392STejas Upadhyay  */
5188ced1eSLucas De Marchi #include "xe_drm_client.h"
68f965392STejas Upadhyay 
78f965392STejas Upadhyay #include <drm/drm_print.h>
887d8ecf0SJani Nikula #include <uapi/drm/xe_drm.h>
98f965392STejas Upadhyay #include <linux/kernel.h>
108f965392STejas Upadhyay #include <linux/slab.h>
118f965392STejas Upadhyay #include <linux/types.h>
128f965392STejas Upadhyay 
134f63d712SMatthew Auld #include "xe_assert.h"
1408452333STejas Upadhyay #include "xe_bo.h"
15b27970f3STejas Upadhyay #include "xe_bo_types.h"
168f965392STejas Upadhyay #include "xe_device_types.h"
17188ced1eSLucas De Marchi #include "xe_exec_queue.h"
18188ced1eSLucas De Marchi #include "xe_force_wake.h"
19188ced1eSLucas De Marchi #include "xe_gt.h"
20188ced1eSLucas De Marchi #include "xe_hw_engine.h"
21188ced1eSLucas De Marchi #include "xe_pm.h"
22b27970f3STejas Upadhyay #include "xe_trace.h"
238f965392STejas Upadhyay 
248f965392STejas Upadhyay /**
25188ced1eSLucas De Marchi  * DOC: DRM Client usage stats
26188ced1eSLucas De Marchi  *
27188ced1eSLucas De Marchi  * The drm/xe driver implements the DRM client usage stats specification as
28188ced1eSLucas De Marchi  * documented in :ref:`drm-client-usage-stats`.
29188ced1eSLucas De Marchi  *
30188ced1eSLucas De Marchi  * Example of the output showing the implemented key value pairs and entirety of
31188ced1eSLucas De Marchi  * the currently possible format options:
32188ced1eSLucas De Marchi  *
33188ced1eSLucas De Marchi  * ::
34188ced1eSLucas De Marchi  *
35188ced1eSLucas De Marchi  * 	pos:    0
36188ced1eSLucas De Marchi  * 	flags:  0100002
37188ced1eSLucas De Marchi  * 	mnt_id: 26
38188ced1eSLucas De Marchi  * 	ino:    685
39188ced1eSLucas De Marchi  * 	drm-driver:     xe
40188ced1eSLucas De Marchi  * 	drm-client-id:  3
41188ced1eSLucas De Marchi  * 	drm-pdev:       0000:03:00.0
42188ced1eSLucas De Marchi  * 	drm-total-system:       0
43188ced1eSLucas De Marchi  * 	drm-shared-system:      0
44188ced1eSLucas De Marchi  * 	drm-active-system:      0
45188ced1eSLucas De Marchi  * 	drm-resident-system:    0
46188ced1eSLucas De Marchi  * 	drm-purgeable-system:   0
47188ced1eSLucas De Marchi  * 	drm-total-gtt:  192 KiB
48188ced1eSLucas De Marchi  * 	drm-shared-gtt: 0
49188ced1eSLucas De Marchi  * 	drm-active-gtt: 0
50188ced1eSLucas De Marchi  * 	drm-resident-gtt:       192 KiB
51188ced1eSLucas De Marchi  * 	drm-total-vram0:        23992 KiB
52188ced1eSLucas De Marchi  * 	drm-shared-vram0:       16 MiB
53188ced1eSLucas De Marchi  * 	drm-active-vram0:       0
54188ced1eSLucas De Marchi  * 	drm-resident-vram0:     23992 KiB
55188ced1eSLucas De Marchi  * 	drm-total-stolen:       0
56188ced1eSLucas De Marchi  * 	drm-shared-stolen:      0
57188ced1eSLucas De Marchi  * 	drm-active-stolen:      0
58188ced1eSLucas De Marchi  * 	drm-resident-stolen:    0
59188ced1eSLucas De Marchi  * 	drm-cycles-rcs: 28257900
60188ced1eSLucas De Marchi  * 	drm-total-cycles-rcs:   7655183225
61188ced1eSLucas De Marchi  * 	drm-cycles-bcs: 0
62188ced1eSLucas De Marchi  * 	drm-total-cycles-bcs:   7655183225
63188ced1eSLucas De Marchi  * 	drm-cycles-vcs: 0
64188ced1eSLucas De Marchi  * 	drm-total-cycles-vcs:   7655183225
65188ced1eSLucas De Marchi  * 	drm-engine-capacity-vcs:        2
66188ced1eSLucas De Marchi  * 	drm-cycles-vecs:        0
67188ced1eSLucas De Marchi  * 	drm-total-cycles-vecs:  7655183225
68188ced1eSLucas De Marchi  * 	drm-engine-capacity-vecs:       2
69188ced1eSLucas De Marchi  * 	drm-cycles-ccs: 0
70188ced1eSLucas De Marchi  * 	drm-total-cycles-ccs:   7655183225
71188ced1eSLucas De Marchi  * 	drm-engine-capacity-ccs:        4
72188ced1eSLucas De Marchi  *
73188ced1eSLucas De Marchi  * Possible `drm-cycles-` key names are: `rcs`, `ccs`, `bcs`, `vcs`, `vecs` and
74188ced1eSLucas De Marchi  * "other".
75188ced1eSLucas De Marchi  */
76188ced1eSLucas De Marchi 
77188ced1eSLucas De Marchi /**
788f965392STejas Upadhyay  * xe_drm_client_alloc() - Allocate drm client
798f965392STejas Upadhyay  * @void: No arg
808f965392STejas Upadhyay  *
818f965392STejas Upadhyay  * Allocate drm client struct to track client memory against
828f965392STejas Upadhyay  * same till client life. Call this API whenever new client
838f965392STejas Upadhyay  * has opened xe device.
848f965392STejas Upadhyay  *
858f965392STejas Upadhyay  * Return: pointer to client struct or NULL if can't allocate
868f965392STejas Upadhyay  */
xe_drm_client_alloc(void)878f965392STejas Upadhyay struct xe_drm_client *xe_drm_client_alloc(void)
888f965392STejas Upadhyay {
898f965392STejas Upadhyay 	struct xe_drm_client *client;
908f965392STejas Upadhyay 
918f965392STejas Upadhyay 	client = kzalloc(sizeof(*client), GFP_KERNEL);
928f965392STejas Upadhyay 	if (!client)
938f965392STejas Upadhyay 		return NULL;
948f965392STejas Upadhyay 
958f965392STejas Upadhyay 	kref_init(&client->kref);
968f965392STejas Upadhyay 
97b27970f3STejas Upadhyay #ifdef CONFIG_PROC_FS
98b27970f3STejas Upadhyay 	spin_lock_init(&client->bos_lock);
99b27970f3STejas Upadhyay 	INIT_LIST_HEAD(&client->bos_list);
100b27970f3STejas Upadhyay #endif
1018f965392STejas Upadhyay 	return client;
1028f965392STejas Upadhyay }
1038f965392STejas Upadhyay 
1048f965392STejas Upadhyay /**
1058f965392STejas Upadhyay  * __xe_drm_client_free() - Free client struct
1068f965392STejas Upadhyay  * @kref: The reference
1078f965392STejas Upadhyay  *
1088f965392STejas Upadhyay  * This frees client struct. Call this API when xe device is closed
1098f965392STejas Upadhyay  * by drm client.
1108f965392STejas Upadhyay  *
1118f965392STejas Upadhyay  * Return: void
1128f965392STejas Upadhyay  */
__xe_drm_client_free(struct kref * kref)1138f965392STejas Upadhyay void __xe_drm_client_free(struct kref *kref)
1148f965392STejas Upadhyay {
1158f965392STejas Upadhyay 	struct xe_drm_client *client =
1168f965392STejas Upadhyay 		container_of(kref, typeof(*client), kref);
1178f965392STejas Upadhyay 
1188f965392STejas Upadhyay 	kfree(client);
1198f965392STejas Upadhyay }
12085c6ad1aSTejas Upadhyay 
12185c6ad1aSTejas Upadhyay #ifdef CONFIG_PROC_FS
12285c6ad1aSTejas Upadhyay /**
123b27970f3STejas Upadhyay  * xe_drm_client_add_bo() - Add BO for tracking client mem usage
124b27970f3STejas Upadhyay  * @client: The drm client ptr
125b27970f3STejas Upadhyay  * @bo: The xe BO ptr
126b27970f3STejas Upadhyay  *
127b27970f3STejas Upadhyay  * Add all BO created by individual drm client by calling this function.
128b27970f3STejas Upadhyay  * This helps in tracking client memory usage.
129b27970f3STejas Upadhyay  *
130b27970f3STejas Upadhyay  * Return: void
131b27970f3STejas Upadhyay  */
xe_drm_client_add_bo(struct xe_drm_client * client,struct xe_bo * bo)132b27970f3STejas Upadhyay void xe_drm_client_add_bo(struct xe_drm_client *client,
133b27970f3STejas Upadhyay 			  struct xe_bo *bo)
134b27970f3STejas Upadhyay {
135b27970f3STejas Upadhyay 	XE_WARN_ON(bo->client);
136b27970f3STejas Upadhyay 	XE_WARN_ON(!list_empty(&bo->client_link));
137b27970f3STejas Upadhyay 
138b27970f3STejas Upadhyay 	bo->client = xe_drm_client_get(client);
139f74fd53bSTejas Upadhyay 	spin_lock(&client->bos_lock);
14010ed10c2SMatthew Auld 	list_add_tail(&bo->client_link, &client->bos_list);
141b27970f3STejas Upadhyay 	spin_unlock(&client->bos_lock);
142b27970f3STejas Upadhyay }
143b27970f3STejas Upadhyay 
144b27970f3STejas Upadhyay /**
145b27970f3STejas Upadhyay  * xe_drm_client_remove_bo() - Remove BO for tracking client mem usage
146b27970f3STejas Upadhyay  * @bo: The xe BO ptr
147b27970f3STejas Upadhyay  *
148b27970f3STejas Upadhyay  * Remove all BO removed by individual drm client by calling this function.
149b27970f3STejas Upadhyay  * This helps in tracking client memory usage.
150b27970f3STejas Upadhyay  *
151b27970f3STejas Upadhyay  * Return: void
152b27970f3STejas Upadhyay  */
xe_drm_client_remove_bo(struct xe_bo * bo)153b27970f3STejas Upadhyay void xe_drm_client_remove_bo(struct xe_bo *bo)
154b27970f3STejas Upadhyay {
1554f63d712SMatthew Auld 	struct xe_device *xe = ttm_to_xe_device(bo->ttm.bdev);
156b27970f3STejas Upadhyay 	struct xe_drm_client *client = bo->client;
157b27970f3STejas Upadhyay 
1584f63d712SMatthew Auld 	xe_assert(xe, !kref_read(&bo->ttm.base.refcount));
1594f63d712SMatthew Auld 
160b27970f3STejas Upadhyay 	spin_lock(&client->bos_lock);
1614f63d712SMatthew Auld 	list_del_init(&bo->client_link);
162b27970f3STejas Upadhyay 	spin_unlock(&client->bos_lock);
163b27970f3STejas Upadhyay 
164b27970f3STejas Upadhyay 	xe_drm_client_put(client);
165b27970f3STejas Upadhyay }
166b27970f3STejas Upadhyay 
bo_meminfo(struct xe_bo * bo,struct drm_memory_stats stats[TTM_NUM_MEM_TYPES])16708452333STejas Upadhyay static void bo_meminfo(struct xe_bo *bo,
16808452333STejas Upadhyay 		       struct drm_memory_stats stats[TTM_NUM_MEM_TYPES])
16908452333STejas Upadhyay {
170*ec9223b4SMatthew Brost 	u64 sz = xe_bo_size(bo);
171fbd73b7dSMatthew Auld 	u32 mem_type = bo->ttm.resource->mem_type;
17208452333STejas Upadhyay 
1734f63d712SMatthew Auld 	xe_bo_assert_held(bo);
1744f63d712SMatthew Auld 
17561e738d8SAlex Deucher 	if (drm_gem_object_is_shared_for_memory_stats(&bo->ttm.base))
17608452333STejas Upadhyay 		stats[mem_type].shared += sz;
17708452333STejas Upadhyay 	else
17808452333STejas Upadhyay 		stats[mem_type].private += sz;
17908452333STejas Upadhyay 
18008452333STejas Upadhyay 	if (xe_bo_has_pages(bo)) {
18108452333STejas Upadhyay 		stats[mem_type].resident += sz;
18208452333STejas Upadhyay 
18308452333STejas Upadhyay 		if (!dma_resv_test_signaled(bo->ttm.base.resv,
18408452333STejas Upadhyay 					    DMA_RESV_USAGE_BOOKKEEP))
18508452333STejas Upadhyay 			stats[mem_type].active += sz;
18608452333STejas Upadhyay 		else if (mem_type == XE_PL_SYSTEM)
18708452333STejas Upadhyay 			stats[mem_type].purgeable += sz;
18808452333STejas Upadhyay 	}
18908452333STejas Upadhyay }
19008452333STejas Upadhyay 
show_meminfo(struct drm_printer * p,struct drm_file * file)19108452333STejas Upadhyay static void show_meminfo(struct drm_printer *p, struct drm_file *file)
19208452333STejas Upadhyay {
19308452333STejas Upadhyay 	struct drm_memory_stats stats[TTM_NUM_MEM_TYPES] = {};
19408452333STejas Upadhyay 	struct xe_file *xef = file->driver_priv;
19508452333STejas Upadhyay 	struct ttm_device *bdev = &xef->xe->ttm;
19608452333STejas Upadhyay 	struct ttm_resource_manager *man;
19708452333STejas Upadhyay 	struct xe_drm_client *client;
19808452333STejas Upadhyay 	struct drm_gem_object *obj;
19908452333STejas Upadhyay 	struct xe_bo *bo;
2000083b8e6SMatthew Auld 	LLIST_HEAD(deferred);
20108452333STejas Upadhyay 	unsigned int id;
20208452333STejas Upadhyay 	u32 mem_type;
20308452333STejas Upadhyay 
20408452333STejas Upadhyay 	client = xef->client;
20508452333STejas Upadhyay 
20608452333STejas Upadhyay 	/* Public objects. */
20708452333STejas Upadhyay 	spin_lock(&file->table_lock);
20808452333STejas Upadhyay 	idr_for_each_entry(&file->object_idr, obj, id) {
20908452333STejas Upadhyay 		struct xe_bo *bo = gem_to_xe_bo(obj);
21008452333STejas Upadhyay 
2114f63d712SMatthew Auld 		if (dma_resv_trylock(bo->ttm.base.resv)) {
21208452333STejas Upadhyay 			bo_meminfo(bo, stats);
2134f63d712SMatthew Auld 			xe_bo_unlock(bo);
2144f63d712SMatthew Auld 		} else {
2154f63d712SMatthew Auld 			xe_bo_get(bo);
2164f63d712SMatthew Auld 			spin_unlock(&file->table_lock);
2174f63d712SMatthew Auld 
2184f63d712SMatthew Auld 			xe_bo_lock(bo, false);
2194f63d712SMatthew Auld 			bo_meminfo(bo, stats);
2204f63d712SMatthew Auld 			xe_bo_unlock(bo);
2214f63d712SMatthew Auld 
2224f63d712SMatthew Auld 			xe_bo_put(bo);
2234f63d712SMatthew Auld 			spin_lock(&file->table_lock);
2244f63d712SMatthew Auld 		}
22508452333STejas Upadhyay 	}
22608452333STejas Upadhyay 	spin_unlock(&file->table_lock);
22708452333STejas Upadhyay 
22808452333STejas Upadhyay 	/* Internal objects. */
22908452333STejas Upadhyay 	spin_lock(&client->bos_lock);
23010ed10c2SMatthew Auld 	list_for_each_entry(bo, &client->bos_list, client_link) {
231ab0c5abaSMatthew Auld 		if (!kref_get_unless_zero(&bo->ttm.base.refcount))
23208452333STejas Upadhyay 			continue;
2330083b8e6SMatthew Auld 
2344f63d712SMatthew Auld 		if (dma_resv_trylock(bo->ttm.base.resv)) {
23508452333STejas Upadhyay 			bo_meminfo(bo, stats);
2364f63d712SMatthew Auld 			xe_bo_unlock(bo);
2374f63d712SMatthew Auld 		} else {
2384f63d712SMatthew Auld 			spin_unlock(&client->bos_lock);
2394f63d712SMatthew Auld 
2404f63d712SMatthew Auld 			xe_bo_lock(bo, false);
2414f63d712SMatthew Auld 			bo_meminfo(bo, stats);
2424f63d712SMatthew Auld 			xe_bo_unlock(bo);
2434f63d712SMatthew Auld 
2444f63d712SMatthew Auld 			spin_lock(&client->bos_lock);
2454f63d712SMatthew Auld 			/* The bo ref will prevent this bo from being removed from the list */
2464f63d712SMatthew Auld 			xe_assert(xef->xe, !list_empty(&bo->client_link));
2474f63d712SMatthew Auld 		}
2484f63d712SMatthew Auld 
2490083b8e6SMatthew Auld 		xe_bo_put_deferred(bo, &deferred);
25008452333STejas Upadhyay 	}
25108452333STejas Upadhyay 	spin_unlock(&client->bos_lock);
25208452333STejas Upadhyay 
2530083b8e6SMatthew Auld 	xe_bo_put_commit(&deferred);
2540083b8e6SMatthew Auld 
25508452333STejas Upadhyay 	for (mem_type = XE_PL_SYSTEM; mem_type < TTM_NUM_MEM_TYPES; ++mem_type) {
256a0df2cc8SPriyanka Dandamudi 		if (!xe_mem_type_to_name[mem_type])
25708452333STejas Upadhyay 			continue;
25808452333STejas Upadhyay 
25908452333STejas Upadhyay 		man = ttm_manager_type(bdev, mem_type);
26008452333STejas Upadhyay 
26108452333STejas Upadhyay 		if (man) {
26208452333STejas Upadhyay 			drm_print_memory_stats(p,
26308452333STejas Upadhyay 					       &stats[mem_type],
264bebf2ebdSYunxiang Li 					       DRM_GEM_OBJECT_ACTIVE |
26508452333STejas Upadhyay 					       DRM_GEM_OBJECT_RESIDENT |
26608452333STejas Upadhyay 					       (mem_type != XE_PL_SYSTEM ? 0 :
26708452333STejas Upadhyay 					       DRM_GEM_OBJECT_PURGEABLE),
268a0df2cc8SPriyanka Dandamudi 					       xe_mem_type_to_name[mem_type]);
26908452333STejas Upadhyay 		}
27008452333STejas Upadhyay 	}
27108452333STejas Upadhyay }
27208452333STejas Upadhyay 
any_engine(struct xe_device * xe)273db696095SLucas De Marchi static struct xe_hw_engine *any_engine(struct xe_device *xe)
274db696095SLucas De Marchi {
275db696095SLucas De Marchi 	struct xe_gt *gt;
276db696095SLucas De Marchi 	unsigned long gt_id;
277db696095SLucas De Marchi 
278db696095SLucas De Marchi 	for_each_gt(gt, xe, gt_id) {
279db696095SLucas De Marchi 		struct xe_hw_engine *hwe = xe_gt_any_hw_engine(gt);
280db696095SLucas De Marchi 
281db696095SLucas De Marchi 		if (hwe)
282db696095SLucas De Marchi 			return hwe;
283db696095SLucas De Marchi 	}
284db696095SLucas De Marchi 
285db696095SLucas De Marchi 	return NULL;
286db696095SLucas De Marchi }
287db696095SLucas De Marchi 
force_wake_get_any_engine(struct xe_device * xe,struct xe_hw_engine ** phwe,unsigned int * pfw_ref)288db696095SLucas De Marchi static bool force_wake_get_any_engine(struct xe_device *xe,
289db696095SLucas De Marchi 				      struct xe_hw_engine **phwe,
290db696095SLucas De Marchi 				      unsigned int *pfw_ref)
291db696095SLucas De Marchi {
292db696095SLucas De Marchi 	enum xe_force_wake_domains domain;
293db696095SLucas De Marchi 	unsigned int fw_ref;
294db696095SLucas De Marchi 	struct xe_hw_engine *hwe;
295db696095SLucas De Marchi 	struct xe_force_wake *fw;
296db696095SLucas De Marchi 
297db696095SLucas De Marchi 	hwe = any_engine(xe);
298db696095SLucas De Marchi 	if (!hwe)
299db696095SLucas De Marchi 		return false;
300db696095SLucas De Marchi 
301db696095SLucas De Marchi 	domain = xe_hw_engine_to_fw_domain(hwe);
302db696095SLucas De Marchi 	fw = gt_to_fw(hwe->gt);
303db696095SLucas De Marchi 
304db696095SLucas De Marchi 	fw_ref = xe_force_wake_get(fw, domain);
305db696095SLucas De Marchi 	if (!xe_force_wake_ref_has_domain(fw_ref, domain)) {
306db696095SLucas De Marchi 		xe_force_wake_put(fw, fw_ref);
307db696095SLucas De Marchi 		return false;
308db696095SLucas De Marchi 	}
309db696095SLucas De Marchi 
310db696095SLucas De Marchi 	*phwe = hwe;
311db696095SLucas De Marchi 	*pfw_ref = fw_ref;
312db696095SLucas De Marchi 
313db696095SLucas De Marchi 	return true;
314db696095SLucas De Marchi }
315db696095SLucas De Marchi 
show_run_ticks(struct drm_printer * p,struct drm_file * file)31645bb564dSUmesh Nerlige Ramappa static void show_run_ticks(struct drm_printer *p, struct drm_file *file)
317188ced1eSLucas De Marchi {
318188ced1eSLucas De Marchi 	unsigned long class, i, gt_id, capacity[XE_ENGINE_CLASS_MAX] = { };
319188ced1eSLucas De Marchi 	struct xe_file *xef = file->driver_priv;
320188ced1eSLucas De Marchi 	struct xe_device *xe = xef->xe;
321188ced1eSLucas De Marchi 	struct xe_gt *gt;
322188ced1eSLucas De Marchi 	struct xe_hw_engine *hwe;
323188ced1eSLucas De Marchi 	struct xe_exec_queue *q;
324188ced1eSLucas De Marchi 	u64 gpu_timestamp;
3257fe17fa5SHimal Prasad Ghimiray 	unsigned int fw_ref;
326188ced1eSLucas De Marchi 
3270fd4380cSLucas De Marchi 	/*
32894030a1dSMarcin Bernatowicz 	 * RING_TIMESTAMP registers are inaccessible in VF mode.
32994030a1dSMarcin Bernatowicz 	 * Without drm-total-cycles-*, other keys provide little value.
33094030a1dSMarcin Bernatowicz 	 * Show all or none of the optional "run_ticks" keys in this case.
33194030a1dSMarcin Bernatowicz 	 */
33294030a1dSMarcin Bernatowicz 	if (IS_SRIOV_VF(xe))
33394030a1dSMarcin Bernatowicz 		return;
33494030a1dSMarcin Bernatowicz 
33594030a1dSMarcin Bernatowicz 	/*
3360fd4380cSLucas De Marchi 	 * Wait for any exec queue going away: their cycles will get updated on
3370fd4380cSLucas De Marchi 	 * context switch out, so wait for that to happen
3380fd4380cSLucas De Marchi 	 */
3390fd4380cSLucas De Marchi 	wait_var_event(&xef->exec_queue.pending_removal,
3400fd4380cSLucas De Marchi 		       !atomic_read(&xef->exec_queue.pending_removal));
3410fd4380cSLucas De Marchi 
342188ced1eSLucas De Marchi 	xe_pm_runtime_get(xe);
343db696095SLucas De Marchi 	if (!force_wake_get_any_engine(xe, &hwe, &fw_ref)) {
344db696095SLucas De Marchi 		xe_pm_runtime_put(xe);
345db696095SLucas De Marchi 		return;
346db696095SLucas De Marchi 	}
347188ced1eSLucas De Marchi 
348188ced1eSLucas De Marchi 	/* Accumulate all the exec queues from this client */
349188ced1eSLucas De Marchi 	mutex_lock(&xef->exec_queue.lock);
350fe4f5d4bSMatthew Brost 	xa_for_each(&xef->exec_queue.xa, i, q) {
351fe4f5d4bSMatthew Brost 		xe_exec_queue_get(q);
352fe4f5d4bSMatthew Brost 		mutex_unlock(&xef->exec_queue.lock);
353fe4f5d4bSMatthew Brost 
35445bb564dSUmesh Nerlige Ramappa 		xe_exec_queue_update_run_ticks(q);
355fe4f5d4bSMatthew Brost 
356fe4f5d4bSMatthew Brost 		mutex_lock(&xef->exec_queue.lock);
357fe4f5d4bSMatthew Brost 		xe_exec_queue_put(q);
358fe4f5d4bSMatthew Brost 	}
359188ced1eSLucas De Marchi 	mutex_unlock(&xef->exec_queue.lock);
360188ced1eSLucas De Marchi 
361188ced1eSLucas De Marchi 	gpu_timestamp = xe_hw_engine_read_timestamp(hwe);
362188ced1eSLucas De Marchi 
363db696095SLucas De Marchi 	xe_force_wake_put(gt_to_fw(hwe->gt), fw_ref);
364188ced1eSLucas De Marchi 	xe_pm_runtime_put(xe);
365188ced1eSLucas De Marchi 
366188ced1eSLucas De Marchi 	for (class = 0; class < XE_ENGINE_CLASS_MAX; class++) {
367188ced1eSLucas De Marchi 		const char *class_name;
368188ced1eSLucas De Marchi 
369188ced1eSLucas De Marchi 		for_each_gt(gt, xe, gt_id)
370188ced1eSLucas De Marchi 			capacity[class] += gt->user_engines.instances_per_class[class];
371188ced1eSLucas De Marchi 
372188ced1eSLucas De Marchi 		/*
373188ced1eSLucas De Marchi 		 * Engines may be fused off or not exposed to userspace. Don't
374188ced1eSLucas De Marchi 		 * return anything if this entire class is not available
375188ced1eSLucas De Marchi 		 */
376188ced1eSLucas De Marchi 		if (!capacity[class])
377188ced1eSLucas De Marchi 			continue;
378188ced1eSLucas De Marchi 
379188ced1eSLucas De Marchi 		class_name = xe_hw_engine_class_to_str(class);
380188ced1eSLucas De Marchi 		drm_printf(p, "drm-cycles-%s:\t%llu\n",
38145bb564dSUmesh Nerlige Ramappa 			   class_name, xef->run_ticks[class]);
382188ced1eSLucas De Marchi 		drm_printf(p, "drm-total-cycles-%s:\t%llu\n",
383188ced1eSLucas De Marchi 			   class_name, gpu_timestamp);
384188ced1eSLucas De Marchi 
385188ced1eSLucas De Marchi 		if (capacity[class] > 1)
386188ced1eSLucas De Marchi 			drm_printf(p, "drm-engine-capacity-%s:\t%lu\n",
387188ced1eSLucas De Marchi 				   class_name, capacity[class]);
388188ced1eSLucas De Marchi 	}
389188ced1eSLucas De Marchi }
390188ced1eSLucas De Marchi 
391b27970f3STejas Upadhyay /**
39285c6ad1aSTejas Upadhyay  * xe_drm_client_fdinfo() - Callback for fdinfo interface
39385c6ad1aSTejas Upadhyay  * @p: The drm_printer ptr
39485c6ad1aSTejas Upadhyay  * @file: The drm_file ptr
39585c6ad1aSTejas Upadhyay  *
39675fd04f2SNitin Gote  * This is callback for drm fdinfo interface. Register this callback
39785c6ad1aSTejas Upadhyay  * in drm driver ops for show_fdinfo.
39885c6ad1aSTejas Upadhyay  *
39985c6ad1aSTejas Upadhyay  * Return: void
40085c6ad1aSTejas Upadhyay  */
xe_drm_client_fdinfo(struct drm_printer * p,struct drm_file * file)40185c6ad1aSTejas Upadhyay void xe_drm_client_fdinfo(struct drm_printer *p, struct drm_file *file)
40285c6ad1aSTejas Upadhyay {
40308452333STejas Upadhyay 	show_meminfo(p, file);
40445bb564dSUmesh Nerlige Ramappa 	show_run_ticks(p, file);
40585c6ad1aSTejas Upadhyay }
40685c6ad1aSTejas Upadhyay #endif
407