xref: /linux/drivers/gpu/drm/xe/xe_pm.c (revision e07aa913161b0338708887a5e78bf57ffdfe67fa)
1dd08ebf6SMatthew Brost // SPDX-License-Identifier: MIT
2dd08ebf6SMatthew Brost /*
3dd08ebf6SMatthew Brost  * Copyright © 2022 Intel Corporation
4dd08ebf6SMatthew Brost  */
5dd08ebf6SMatthew Brost 
6ea9f879dSLucas De Marchi #include "xe_pm.h"
7ea9f879dSLucas De Marchi 
8dd08ebf6SMatthew Brost #include <linux/pm_runtime.h>
9dd08ebf6SMatthew Brost 
10b2d75619SAnshuman Gupta #include <drm/drm_managed.h>
11dd08ebf6SMatthew Brost #include <drm/ttm/ttm_placement.h>
12dd08ebf6SMatthew Brost 
13dd08ebf6SMatthew Brost #include "xe_bo.h"
14dd08ebf6SMatthew Brost #include "xe_bo_evict.h"
15dd08ebf6SMatthew Brost #include "xe_device.h"
16b2d75619SAnshuman Gupta #include "xe_device_sysfs.h"
17dd08ebf6SMatthew Brost #include "xe_ggtt.h"
18ea9f879dSLucas De Marchi #include "xe_gt.h"
1909d88e3bSAnshuman Gupta #include "xe_guc.h"
20dd08ebf6SMatthew Brost #include "xe_irq.h"
21dd08ebf6SMatthew Brost #include "xe_pcode.h"
22dd08ebf6SMatthew Brost 
23dd08ebf6SMatthew Brost /**
24dd08ebf6SMatthew Brost  * DOC: Xe Power Management
25dd08ebf6SMatthew Brost  *
26dd08ebf6SMatthew Brost  * Xe PM shall be guided by the simplicity.
27dd08ebf6SMatthew Brost  * Use the simplest hook options whenever possible.
28dd08ebf6SMatthew Brost  * Let's not reinvent the runtime_pm references and hooks.
29dd08ebf6SMatthew Brost  * Shall have a clear separation of display and gt underneath this component.
30dd08ebf6SMatthew Brost  *
31dd08ebf6SMatthew Brost  * What's next:
32dd08ebf6SMatthew Brost  *
33dd08ebf6SMatthew Brost  * For now s2idle and s3 are only working in integrated devices. The next step
34dd08ebf6SMatthew Brost  * is to iterate through all VRAM's BO backing them up into the system memory
35dd08ebf6SMatthew Brost  * before allowing the system suspend.
36dd08ebf6SMatthew Brost  *
37dd08ebf6SMatthew Brost  * Also runtime_pm needs to be here from the beginning.
38dd08ebf6SMatthew Brost  *
39dd08ebf6SMatthew Brost  * RC6/RPS are also critical PM features. Let's start with GuCRC and GuC SLPC
40dd08ebf6SMatthew Brost  * and no wait boost. Frequency optimizations should come on a next stage.
41dd08ebf6SMatthew Brost  */
42dd08ebf6SMatthew Brost 
43dd08ebf6SMatthew Brost /**
44dd08ebf6SMatthew Brost  * xe_pm_suspend - Helper for System suspend, i.e. S0->S3 / S0->S2idle
45dd08ebf6SMatthew Brost  * @xe: xe device instance
46dd08ebf6SMatthew Brost  *
47dd08ebf6SMatthew Brost  * Return: 0 on success
48dd08ebf6SMatthew Brost  */
49dd08ebf6SMatthew Brost int xe_pm_suspend(struct xe_device *xe)
50dd08ebf6SMatthew Brost {
51dd08ebf6SMatthew Brost 	struct xe_gt *gt;
52dd08ebf6SMatthew Brost 	u8 id;
53dd08ebf6SMatthew Brost 	int err;
54dd08ebf6SMatthew Brost 
55dd08ebf6SMatthew Brost 	for_each_gt(gt, xe, id)
56dd08ebf6SMatthew Brost 		xe_gt_suspend_prepare(gt);
57dd08ebf6SMatthew Brost 
58dd08ebf6SMatthew Brost 	/* FIXME: Super racey... */
59dd08ebf6SMatthew Brost 	err = xe_bo_evict_all(xe);
60dd08ebf6SMatthew Brost 	if (err)
61dd08ebf6SMatthew Brost 		return err;
62dd08ebf6SMatthew Brost 
63dd08ebf6SMatthew Brost 	for_each_gt(gt, xe, id) {
64dd08ebf6SMatthew Brost 		err = xe_gt_suspend(gt);
65dd08ebf6SMatthew Brost 		if (err)
66dd08ebf6SMatthew Brost 			return err;
67dd08ebf6SMatthew Brost 	}
68dd08ebf6SMatthew Brost 
69dd08ebf6SMatthew Brost 	xe_irq_suspend(xe);
70dd08ebf6SMatthew Brost 
71dd08ebf6SMatthew Brost 	return 0;
72dd08ebf6SMatthew Brost }
73dd08ebf6SMatthew Brost 
74dd08ebf6SMatthew Brost /**
75dd08ebf6SMatthew Brost  * xe_pm_resume - Helper for System resume S3->S0 / S2idle->S0
76dd08ebf6SMatthew Brost  * @xe: xe device instance
77dd08ebf6SMatthew Brost  *
78dd08ebf6SMatthew Brost  * Return: 0 on success
79dd08ebf6SMatthew Brost  */
80dd08ebf6SMatthew Brost int xe_pm_resume(struct xe_device *xe)
81dd08ebf6SMatthew Brost {
82dd08ebf6SMatthew Brost 	struct xe_gt *gt;
83dd08ebf6SMatthew Brost 	u8 id;
84dd08ebf6SMatthew Brost 	int err;
85dd08ebf6SMatthew Brost 
86dd08ebf6SMatthew Brost 	for_each_gt(gt, xe, id) {
87dd08ebf6SMatthew Brost 		err = xe_pcode_init(gt);
88dd08ebf6SMatthew Brost 		if (err)
89dd08ebf6SMatthew Brost 			return err;
90dd08ebf6SMatthew Brost 	}
91dd08ebf6SMatthew Brost 
92dd08ebf6SMatthew Brost 	/*
93dd08ebf6SMatthew Brost 	 * This only restores pinned memory which is the memory required for the
94dd08ebf6SMatthew Brost 	 * GT(s) to resume.
95dd08ebf6SMatthew Brost 	 */
96dd08ebf6SMatthew Brost 	err = xe_bo_restore_kernel(xe);
97dd08ebf6SMatthew Brost 	if (err)
98dd08ebf6SMatthew Brost 		return err;
99dd08ebf6SMatthew Brost 
100dd08ebf6SMatthew Brost 	xe_irq_resume(xe);
101dd08ebf6SMatthew Brost 
102dd08ebf6SMatthew Brost 	for_each_gt(gt, xe, id)
103dd08ebf6SMatthew Brost 		xe_gt_resume(gt);
104dd08ebf6SMatthew Brost 
105dd08ebf6SMatthew Brost 	err = xe_bo_restore_user(xe);
106dd08ebf6SMatthew Brost 	if (err)
107dd08ebf6SMatthew Brost 		return err;
108dd08ebf6SMatthew Brost 
109dd08ebf6SMatthew Brost 	return 0;
110dd08ebf6SMatthew Brost }
111dd08ebf6SMatthew Brost 
112ac0be3b5SAnshuman Gupta static bool xe_pm_pci_d3cold_capable(struct pci_dev *pdev)
113ac0be3b5SAnshuman Gupta {
114ac0be3b5SAnshuman Gupta 	struct pci_dev *root_pdev;
115ac0be3b5SAnshuman Gupta 
116ac0be3b5SAnshuman Gupta 	root_pdev = pcie_find_root_port(pdev);
117ac0be3b5SAnshuman Gupta 	if (!root_pdev)
118ac0be3b5SAnshuman Gupta 		return false;
119ac0be3b5SAnshuman Gupta 
120ac0be3b5SAnshuman Gupta 	/* D3Cold requires PME capability and _PR3 power resource */
121ac0be3b5SAnshuman Gupta 	if (!pci_pme_capable(root_pdev, PCI_D3cold) || !pci_pr3_present(root_pdev))
122ac0be3b5SAnshuman Gupta 		return false;
123ac0be3b5SAnshuman Gupta 
124ac0be3b5SAnshuman Gupta 	return true;
125ac0be3b5SAnshuman Gupta }
126ac0be3b5SAnshuman Gupta 
127fddebcbfSAnshuman Gupta static void xe_pm_runtime_init(struct xe_device *xe)
128dd08ebf6SMatthew Brost {
129dd08ebf6SMatthew Brost 	struct device *dev = xe->drm.dev;
130dd08ebf6SMatthew Brost 
131dd08ebf6SMatthew Brost 	pm_runtime_use_autosuspend(dev);
132dd08ebf6SMatthew Brost 	pm_runtime_set_autosuspend_delay(dev, 1000);
133dd08ebf6SMatthew Brost 	pm_runtime_set_active(dev);
134dd08ebf6SMatthew Brost 	pm_runtime_allow(dev);
135dd08ebf6SMatthew Brost 	pm_runtime_mark_last_busy(dev);
136dd08ebf6SMatthew Brost 	pm_runtime_put_autosuspend(dev);
137dd08ebf6SMatthew Brost }
138dd08ebf6SMatthew Brost 
139ac0be3b5SAnshuman Gupta void xe_pm_init(struct xe_device *xe)
140ac0be3b5SAnshuman Gupta {
141ac0be3b5SAnshuman Gupta 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
142ac0be3b5SAnshuman Gupta 
143b2d75619SAnshuman Gupta 	drmm_mutex_init(&xe->drm, &xe->d3cold.lock);
144fddebcbfSAnshuman Gupta 	xe_pm_runtime_init(xe);
145b2d75619SAnshuman Gupta 	xe->d3cold.capable = xe_pm_pci_d3cold_capable(pdev);
146b2d75619SAnshuman Gupta 	xe_device_sysfs_init(xe);
147b2d75619SAnshuman Gupta 	xe_pm_set_vram_threshold(xe, DEFAULT_VRAM_THRESHOLD);
148ac0be3b5SAnshuman Gupta }
149ac0be3b5SAnshuman Gupta 
1505b7e50e2SMatthew Auld void xe_pm_runtime_fini(struct xe_device *xe)
1515b7e50e2SMatthew Auld {
1525b7e50e2SMatthew Auld 	struct device *dev = xe->drm.dev;
1535b7e50e2SMatthew Auld 
1545b7e50e2SMatthew Auld 	pm_runtime_get_sync(dev);
1555b7e50e2SMatthew Auld 	pm_runtime_forbid(dev);
1565b7e50e2SMatthew Auld }
1575b7e50e2SMatthew Auld 
158a00b8f1aSMatthew Auld static void xe_pm_write_callback_task(struct xe_device *xe,
159a00b8f1aSMatthew Auld 				      struct task_struct *task)
160a00b8f1aSMatthew Auld {
161a00b8f1aSMatthew Auld 	WRITE_ONCE(xe->pm_callback_task, task);
162a00b8f1aSMatthew Auld 
163a00b8f1aSMatthew Auld 	/*
164a00b8f1aSMatthew Auld 	 * Just in case it's somehow possible for our writes to be reordered to
165a00b8f1aSMatthew Auld 	 * the extent that something else re-uses the task written in
166a00b8f1aSMatthew Auld 	 * pm_callback_task. For example after returning from the callback, but
167a00b8f1aSMatthew Auld 	 * before the reordered write that resets pm_callback_task back to NULL.
168a00b8f1aSMatthew Auld 	 */
169a00b8f1aSMatthew Auld 	smp_mb(); /* pairs with xe_pm_read_callback_task */
170a00b8f1aSMatthew Auld }
171a00b8f1aSMatthew Auld 
172a00b8f1aSMatthew Auld struct task_struct *xe_pm_read_callback_task(struct xe_device *xe)
173a00b8f1aSMatthew Auld {
174a00b8f1aSMatthew Auld 	smp_mb(); /* pairs with xe_pm_write_callback_task */
175a00b8f1aSMatthew Auld 
176a00b8f1aSMatthew Auld 	return READ_ONCE(xe->pm_callback_task);
177a00b8f1aSMatthew Auld }
178a00b8f1aSMatthew Auld 
179dd08ebf6SMatthew Brost int xe_pm_runtime_suspend(struct xe_device *xe)
180dd08ebf6SMatthew Brost {
181dd08ebf6SMatthew Brost 	struct xe_gt *gt;
182dd08ebf6SMatthew Brost 	u8 id;
183a00b8f1aSMatthew Auld 	int err = 0;
184dd08ebf6SMatthew Brost 
185a00b8f1aSMatthew Auld 	if (xe->d3cold.allowed && xe_device_mem_access_ongoing(xe))
186dd08ebf6SMatthew Brost 		return -EBUSY;
187dd08ebf6SMatthew Brost 
188a00b8f1aSMatthew Auld 	/* Disable access_ongoing asserts and prevent recursive pm calls */
189a00b8f1aSMatthew Auld 	xe_pm_write_callback_task(xe, current);
190a00b8f1aSMatthew Auld 
1919700a1dfSMatthew Auld 	/*
1929700a1dfSMatthew Auld 	 * The actual xe_device_mem_access_put() is always async underneath, so
1939700a1dfSMatthew Auld 	 * exactly where that is called should makes no difference to us. However
1949700a1dfSMatthew Auld 	 * we still need to be very careful with the locks that this callback
1959700a1dfSMatthew Auld 	 * acquires and the locks that are acquired and held by any callers of
1969700a1dfSMatthew Auld 	 * xe_device_mem_access_get(). We already have the matching annotation
1979700a1dfSMatthew Auld 	 * on that side, but we also need it here. For example lockdep should be
1989700a1dfSMatthew Auld 	 * able to tell us if the following scenario is in theory possible:
1999700a1dfSMatthew Auld 	 *
2009700a1dfSMatthew Auld 	 * CPU0                          | CPU1 (kworker)
2019700a1dfSMatthew Auld 	 * lock(A)                       |
2029700a1dfSMatthew Auld 	 *                               | xe_pm_runtime_suspend()
2039700a1dfSMatthew Auld 	 *                               |      lock(A)
2049700a1dfSMatthew Auld 	 * xe_device_mem_access_get()    |
2059700a1dfSMatthew Auld 	 *
2069700a1dfSMatthew Auld 	 * This will clearly deadlock since rpm core needs to wait for
2079700a1dfSMatthew Auld 	 * xe_pm_runtime_suspend() to complete, but here we are holding lock(A)
2089700a1dfSMatthew Auld 	 * on CPU0 which prevents CPU1 making forward progress.  With the
2099700a1dfSMatthew Auld 	 * annotation here and in xe_device_mem_access_get() lockdep will see
2109700a1dfSMatthew Auld 	 * the potential lock inversion and give us a nice splat.
2119700a1dfSMatthew Auld 	 */
2129700a1dfSMatthew Auld 	lock_map_acquire(&xe_device_mem_access_lockdep_map);
2139700a1dfSMatthew Auld 
214a00b8f1aSMatthew Auld 	if (xe->d3cold.allowed) {
215dd08ebf6SMatthew Brost 		err = xe_bo_evict_all(xe);
216dd08ebf6SMatthew Brost 		if (err)
217a00b8f1aSMatthew Auld 			goto out;
218dd08ebf6SMatthew Brost 	}
219dd08ebf6SMatthew Brost 
220dd08ebf6SMatthew Brost 	for_each_gt(gt, xe, id) {
221dd08ebf6SMatthew Brost 		err = xe_gt_suspend(gt);
222dd08ebf6SMatthew Brost 		if (err)
223a00b8f1aSMatthew Auld 			goto out;
224dd08ebf6SMatthew Brost 	}
225dd08ebf6SMatthew Brost 
226dd08ebf6SMatthew Brost 	xe_irq_suspend(xe);
227a00b8f1aSMatthew Auld out:
2289700a1dfSMatthew Auld 	lock_map_release(&xe_device_mem_access_lockdep_map);
229a00b8f1aSMatthew Auld 	xe_pm_write_callback_task(xe, NULL);
230a00b8f1aSMatthew Auld 	return err;
231dd08ebf6SMatthew Brost }
232dd08ebf6SMatthew Brost 
233dd08ebf6SMatthew Brost int xe_pm_runtime_resume(struct xe_device *xe)
234dd08ebf6SMatthew Brost {
235dd08ebf6SMatthew Brost 	struct xe_gt *gt;
236dd08ebf6SMatthew Brost 	u8 id;
237a00b8f1aSMatthew Auld 	int err = 0;
238a00b8f1aSMatthew Auld 
239a00b8f1aSMatthew Auld 	/* Disable access_ongoing asserts and prevent recursive pm calls */
240a00b8f1aSMatthew Auld 	xe_pm_write_callback_task(xe, current);
241dd08ebf6SMatthew Brost 
2429700a1dfSMatthew Auld 	lock_map_acquire(&xe_device_mem_access_lockdep_map);
2439700a1dfSMatthew Auld 
24409d88e3bSAnshuman Gupta 	/*
24509d88e3bSAnshuman Gupta 	 * It can be possible that xe has allowed d3cold but other pcie devices
24609d88e3bSAnshuman Gupta 	 * in gfx card soc would have blocked d3cold, therefore card has not
24709d88e3bSAnshuman Gupta 	 * really lost power. Detecting primary Gt power is sufficient.
24809d88e3bSAnshuman Gupta 	 */
24909d88e3bSAnshuman Gupta 	gt = xe_device_get_gt(xe, 0);
25009d88e3bSAnshuman Gupta 	xe->d3cold.power_lost = xe_guc_in_reset(&gt->uc.guc);
25109d88e3bSAnshuman Gupta 
25209d88e3bSAnshuman Gupta 	if (xe->d3cold.allowed && xe->d3cold.power_lost) {
253dd08ebf6SMatthew Brost 		for_each_gt(gt, xe, id) {
254dd08ebf6SMatthew Brost 			err = xe_pcode_init(gt);
255dd08ebf6SMatthew Brost 			if (err)
256a00b8f1aSMatthew Auld 				goto out;
257dd08ebf6SMatthew Brost 		}
258dd08ebf6SMatthew Brost 
259dd08ebf6SMatthew Brost 		/*
260dd08ebf6SMatthew Brost 		 * This only restores pinned memory which is the memory
261dd08ebf6SMatthew Brost 		 * required for the GT(s) to resume.
262dd08ebf6SMatthew Brost 		 */
263dd08ebf6SMatthew Brost 		err = xe_bo_restore_kernel(xe);
264dd08ebf6SMatthew Brost 		if (err)
265a00b8f1aSMatthew Auld 			goto out;
266dd08ebf6SMatthew Brost 	}
267dd08ebf6SMatthew Brost 
268dd08ebf6SMatthew Brost 	xe_irq_resume(xe);
269dd08ebf6SMatthew Brost 
270dd08ebf6SMatthew Brost 	for_each_gt(gt, xe, id)
271dd08ebf6SMatthew Brost 		xe_gt_resume(gt);
272dd08ebf6SMatthew Brost 
27309d88e3bSAnshuman Gupta 	if (xe->d3cold.allowed && xe->d3cold.power_lost) {
274dd08ebf6SMatthew Brost 		err = xe_bo_restore_user(xe);
275dd08ebf6SMatthew Brost 		if (err)
276a00b8f1aSMatthew Auld 			goto out;
277dd08ebf6SMatthew Brost 	}
278a00b8f1aSMatthew Auld out:
2799700a1dfSMatthew Auld 	lock_map_release(&xe_device_mem_access_lockdep_map);
280a00b8f1aSMatthew Auld 	xe_pm_write_callback_task(xe, NULL);
281a00b8f1aSMatthew Auld 	return err;
282dd08ebf6SMatthew Brost }
283dd08ebf6SMatthew Brost 
284dd08ebf6SMatthew Brost int xe_pm_runtime_get(struct xe_device *xe)
285dd08ebf6SMatthew Brost {
286dd08ebf6SMatthew Brost 	return pm_runtime_get_sync(xe->drm.dev);
287dd08ebf6SMatthew Brost }
288dd08ebf6SMatthew Brost 
289dd08ebf6SMatthew Brost int xe_pm_runtime_put(struct xe_device *xe)
290dd08ebf6SMatthew Brost {
291dd08ebf6SMatthew Brost 	pm_runtime_mark_last_busy(xe->drm.dev);
292dd08ebf6SMatthew Brost 	return pm_runtime_put_autosuspend(xe->drm.dev);
293dd08ebf6SMatthew Brost }
294dd08ebf6SMatthew Brost 
295dd08ebf6SMatthew Brost int xe_pm_runtime_get_if_active(struct xe_device *xe)
296dd08ebf6SMatthew Brost {
297dd08ebf6SMatthew Brost 	return pm_runtime_get_if_active(xe->drm.dev, true);
298dd08ebf6SMatthew Brost }
299c8a74077SAnshuman Gupta 
300c8a74077SAnshuman Gupta void xe_pm_assert_unbounded_bridge(struct xe_device *xe)
301c8a74077SAnshuman Gupta {
302c8a74077SAnshuman Gupta 	struct pci_dev *pdev = to_pci_dev(xe->drm.dev);
303c8a74077SAnshuman Gupta 	struct pci_dev *bridge = pci_upstream_bridge(pdev);
304c8a74077SAnshuman Gupta 
305c8a74077SAnshuman Gupta 	if (!bridge)
306c8a74077SAnshuman Gupta 		return;
307c8a74077SAnshuman Gupta 
308c8a74077SAnshuman Gupta 	if (!bridge->driver) {
309c8a74077SAnshuman Gupta 		drm_warn(&xe->drm, "unbounded parent pci bridge, device won't support any PM support.\n");
310c8a74077SAnshuman Gupta 		device_set_pm_not_required(&pdev->dev);
311c8a74077SAnshuman Gupta 	}
312c8a74077SAnshuman Gupta }
313b2d75619SAnshuman Gupta 
314b2d75619SAnshuman Gupta int xe_pm_set_vram_threshold(struct xe_device *xe, u32 threshold)
315b2d75619SAnshuman Gupta {
316b2d75619SAnshuman Gupta 	struct ttm_resource_manager *man;
317b2d75619SAnshuman Gupta 	u32 vram_total_mb = 0;
318b2d75619SAnshuman Gupta 	int i;
319b2d75619SAnshuman Gupta 
320b2d75619SAnshuman Gupta 	for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i) {
321b2d75619SAnshuman Gupta 		man = ttm_manager_type(&xe->ttm, i);
322b2d75619SAnshuman Gupta 		if (man)
323b2d75619SAnshuman Gupta 			vram_total_mb += DIV_ROUND_UP_ULL(man->size, 1024 * 1024);
324b2d75619SAnshuman Gupta 	}
325b2d75619SAnshuman Gupta 
326b2d75619SAnshuman Gupta 	drm_dbg(&xe->drm, "Total vram %u mb\n", vram_total_mb);
327b2d75619SAnshuman Gupta 
328b2d75619SAnshuman Gupta 	if (threshold > vram_total_mb)
329b2d75619SAnshuman Gupta 		return -EINVAL;
330b2d75619SAnshuman Gupta 
331b2d75619SAnshuman Gupta 	mutex_lock(&xe->d3cold.lock);
332b2d75619SAnshuman Gupta 	xe->d3cold.vram_threshold = threshold;
333b2d75619SAnshuman Gupta 	mutex_unlock(&xe->d3cold.lock);
334b2d75619SAnshuman Gupta 
335b2d75619SAnshuman Gupta 	return 0;
336b2d75619SAnshuman Gupta }
3372ef08b98SAnshuman Gupta 
3382ef08b98SAnshuman Gupta void xe_pm_d3cold_allowed_toggle(struct xe_device *xe)
3392ef08b98SAnshuman Gupta {
3402ef08b98SAnshuman Gupta 	struct ttm_resource_manager *man;
3412ef08b98SAnshuman Gupta 	u32 total_vram_used_mb = 0;
3422ef08b98SAnshuman Gupta 	u64 vram_used;
3432ef08b98SAnshuman Gupta 	int i;
3442ef08b98SAnshuman Gupta 
345*e07aa913SRodrigo Vivi 	if (!xe->d3cold.capable) {
346*e07aa913SRodrigo Vivi 		xe->d3cold.allowed = false;
347*e07aa913SRodrigo Vivi 		return;
348*e07aa913SRodrigo Vivi 	}
349*e07aa913SRodrigo Vivi 
3502ef08b98SAnshuman Gupta 	for (i = XE_PL_VRAM0; i <= XE_PL_VRAM1; ++i) {
3512ef08b98SAnshuman Gupta 		man = ttm_manager_type(&xe->ttm, i);
3522ef08b98SAnshuman Gupta 		if (man) {
3532ef08b98SAnshuman Gupta 			vram_used = ttm_resource_manager_usage(man);
3542ef08b98SAnshuman Gupta 			total_vram_used_mb += DIV_ROUND_UP_ULL(vram_used, 1024 * 1024);
3552ef08b98SAnshuman Gupta 		}
3562ef08b98SAnshuman Gupta 	}
3572ef08b98SAnshuman Gupta 
3582ef08b98SAnshuman Gupta 	mutex_lock(&xe->d3cold.lock);
3592ef08b98SAnshuman Gupta 
3602ef08b98SAnshuman Gupta 	if (total_vram_used_mb < xe->d3cold.vram_threshold)
3612ef08b98SAnshuman Gupta 		xe->d3cold.allowed = true;
3622ef08b98SAnshuman Gupta 	else
3632ef08b98SAnshuman Gupta 		xe->d3cold.allowed = false;
3642ef08b98SAnshuman Gupta 
3652ef08b98SAnshuman Gupta 	mutex_unlock(&xe->d3cold.lock);
3662ef08b98SAnshuman Gupta }
367