xref: /linux/drivers/gpu/drm/xe/xe_ttm_sys_mgr.c (revision ca220141fa8ebae09765a242076b2b77338106b0)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2021-2022 Intel Corporation
4  * Copyright (C) 2021-2022 Red Hat
5  */
6 
7 #include "xe_ttm_sys_mgr.h"
8 
9 #include <drm/drm_managed.h>
10 
11 #include <drm/ttm/ttm_placement.h>
12 #include <drm/ttm/ttm_range_manager.h>
13 #include <drm/ttm/ttm_tt.h>
14 
15 #include "xe_bo.h"
16 
17 struct xe_ttm_sys_node {
18 	struct ttm_buffer_object *tbo;
19 	struct ttm_range_mgr_node base;
20 };
21 
22 static inline struct xe_ttm_sys_node *
23 to_xe_ttm_sys_node(struct ttm_resource *res)
24 {
25 	return container_of(res, struct xe_ttm_sys_node, base.base);
26 }
27 
28 static int xe_ttm_sys_mgr_new(struct ttm_resource_manager *man,
29 			      struct ttm_buffer_object *tbo,
30 			      const struct ttm_place *place,
31 			      struct ttm_resource **res)
32 {
33 	struct xe_ttm_sys_node *node;
34 	int r;
35 
36 	node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL);
37 	if (!node)
38 		return -ENOMEM;
39 
40 	node->tbo = tbo;
41 	ttm_resource_init(tbo, place, &node->base.base);
42 
43 	if (!(place->flags & TTM_PL_FLAG_TEMPORARY) &&
44 	    ttm_resource_manager_usage(man) > (man->size << PAGE_SHIFT)) {
45 		r = -ENOSPC;
46 		goto err_fini;
47 	}
48 
49 	node->base.mm_nodes[0].start = 0;
50 	node->base.mm_nodes[0].size = PFN_UP(node->base.base.size);
51 	node->base.base.start = XE_BO_INVALID_OFFSET;
52 
53 	*res = &node->base.base;
54 
55 	return 0;
56 
57 err_fini:
58 	ttm_resource_fini(man, &node->base.base);
59 	kfree(node);
60 	return r;
61 }
62 
63 static void xe_ttm_sys_mgr_del(struct ttm_resource_manager *man,
64 			       struct ttm_resource *res)
65 {
66 	struct xe_ttm_sys_node *node = to_xe_ttm_sys_node(res);
67 
68 	ttm_resource_fini(man, res);
69 	kfree(node);
70 }
71 
72 static void xe_ttm_sys_mgr_debug(struct ttm_resource_manager *man,
73 				 struct drm_printer *printer)
74 {
75 	/*
76 	 * This function is called by debugfs entry and would require
77 	 * pm_runtime_{get,put} wrappers around any operation.
78 	 */
79 }
80 
81 static const struct ttm_resource_manager_func xe_ttm_sys_mgr_func = {
82 	.alloc = xe_ttm_sys_mgr_new,
83 	.free = xe_ttm_sys_mgr_del,
84 	.debug = xe_ttm_sys_mgr_debug
85 };
86 
87 static void xe_ttm_sys_mgr_fini(struct drm_device *drm, void *arg)
88 {
89 	struct xe_device *xe = (struct xe_device *)arg;
90 	struct ttm_resource_manager *man = &xe->mem.sys_mgr;
91 	int err;
92 
93 	ttm_resource_manager_set_used(man, false);
94 
95 	err = ttm_resource_manager_evict_all(&xe->ttm, man);
96 	if (err)
97 		return;
98 
99 	ttm_resource_manager_cleanup(man);
100 	ttm_set_driver_manager(&xe->ttm, XE_PL_TT, NULL);
101 }
102 
103 int xe_ttm_sys_mgr_init(struct xe_device *xe)
104 {
105 	struct ttm_resource_manager *man = &xe->mem.sys_mgr;
106 	struct sysinfo si;
107 	u64 gtt_size;
108 
109 	si_meminfo(&si);
110 	/* Potentially restrict amount of TT memory here. */
111 	gtt_size = (u64)si.totalram * si.mem_unit;
112 
113 	man->use_tt = true;
114 	man->func = &xe_ttm_sys_mgr_func;
115 	ttm_resource_manager_init(man, &xe->ttm, gtt_size >> PAGE_SHIFT);
116 	ttm_set_driver_manager(&xe->ttm, XE_PL_TT, man);
117 	ttm_resource_manager_set_used(man, true);
118 	return drmm_add_action_or_reset(&xe->drm, xe_ttm_sys_mgr_fini, xe);
119 }
120