xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/bifrost/mali_kbase_trace_gpu_mem.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
2 /*
3  *
4  * (C) COPYRIGHT 2020-2022 ARM Limited. All rights reserved.
5  *
6  * This program is free software and is provided to you under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation, and any use by you of this program is subject to the terms
9  * of such GNU license.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you can access it online at
18  * http://www.gnu.org/licenses/gpl-2.0.html.
19  *
20  */
21 
22 #include <mali_kbase.h>
23 #include <mali_kbase_mem_linux.h>
24 #include <mali_kbase_defs.h>
25 #include <mali_kbase_trace_gpu_mem.h>
26 
27 /**
28  * struct kbase_dma_buf - Object instantiated when a dma-buf imported allocation
29  *                        is mapped to GPU for the first time within a process.
30  *                        Another instantiation is done for the case when that
31  *                        allocation is mapped for the first time to GPU.
32  *
33  * @dma_buf:              Reference to dma_buf been imported.
34  * @dma_buf_node:         Link node to maintain a rb_tree of kbase_dma_buf.
35  * @import_count:         The number of times the dma_buf was imported.
36  */
37 struct kbase_dma_buf {
38 	struct dma_buf *dma_buf;
39 	struct rb_node dma_buf_node;
40 	u32 import_count;
41 };
42 
43 /**
44  * kbase_delete_dma_buf_mapping - Delete a dma buffer mapping.
45  *
46  * @kctx: Pointer to kbase context.
47  * @dma_buf: Pointer to a dma buffer mapping.
48  * @tree: Pointer to root of rb_tree containing the dma_buf's mapped.
49  *
50  * when we un-map any dma mapping we need to remove them from rb_tree,
51  * rb_tree is maintained at kbase_device level and kbase_process level
52  * by passing the root of kbase_device or kbase_process we can remove
53  * the node from the tree.
54  *
55  * Return: true on success.
56  */
kbase_delete_dma_buf_mapping(struct kbase_context * kctx,struct dma_buf * dma_buf,struct rb_root * tree)57 static bool kbase_delete_dma_buf_mapping(struct kbase_context *kctx,
58 					 struct dma_buf *dma_buf,
59 					 struct rb_root *tree)
60 {
61 	struct kbase_dma_buf *buf_node = NULL;
62 	struct rb_node *node = tree->rb_node;
63 	bool mapping_removed = false;
64 
65 	lockdep_assert_held(&kctx->kbdev->dma_buf_lock);
66 
67 	while (node) {
68 		buf_node = rb_entry(node, struct kbase_dma_buf, dma_buf_node);
69 
70 		if (dma_buf == buf_node->dma_buf) {
71 			WARN_ON(!buf_node->import_count);
72 
73 			buf_node->import_count--;
74 
75 			if (!buf_node->import_count) {
76 				rb_erase(&buf_node->dma_buf_node, tree);
77 				kfree(buf_node);
78 				mapping_removed = true;
79 			}
80 
81 			break;
82 		}
83 
84 		if (dma_buf < buf_node->dma_buf)
85 			node = node->rb_left;
86 		else
87 			node = node->rb_right;
88 	}
89 
90 	WARN_ON(!buf_node);
91 	return mapping_removed;
92 }
93 
94 /**
95  * kbase_capture_dma_buf_mapping - capture a dma buffer mapping.
96  *
97  * @kctx: Pointer to kbase context.
98  * @dma_buf: Pointer to a dma buffer mapping.
99  * @root: Pointer to root of rb_tree containing the dma_buf's.
100  *
101  * We maintain a kbase_device level and kbase_process level rb_tree
102  * of all unique dma_buf's mapped to gpu memory. So when attach any
103  * dma_buf add it the rb_tree's. To add the unique mapping we need
104  * check if the mapping is not a duplicate and then add them.
105  *
106  * Return: true on success
107  */
kbase_capture_dma_buf_mapping(struct kbase_context * kctx,struct dma_buf * dma_buf,struct rb_root * root)108 static bool kbase_capture_dma_buf_mapping(struct kbase_context *kctx,
109 					  struct dma_buf *dma_buf,
110 					  struct rb_root *root)
111 {
112 	struct kbase_dma_buf *buf_node = NULL;
113 	struct rb_node *node = root->rb_node;
114 	bool unique_buf_imported = true;
115 
116 	lockdep_assert_held(&kctx->kbdev->dma_buf_lock);
117 
118 	while (node) {
119 		buf_node = rb_entry(node, struct kbase_dma_buf, dma_buf_node);
120 
121 		if (dma_buf == buf_node->dma_buf) {
122 			unique_buf_imported = false;
123 			break;
124 		}
125 
126 		if (dma_buf < buf_node->dma_buf)
127 			node = node->rb_left;
128 		else
129 			node = node->rb_right;
130 	}
131 
132 	if (unique_buf_imported) {
133 		struct kbase_dma_buf *new_buf_node =
134 			kzalloc(sizeof(*new_buf_node), GFP_KERNEL);
135 
136 		if (new_buf_node == NULL) {
137 			dev_err(kctx->kbdev->dev, "Error allocating memory for kbase_dma_buf\n");
138 			/* Dont account for it if we fail to allocate memory */
139 			unique_buf_imported = false;
140 		} else {
141 			struct rb_node **new = &(root->rb_node), *parent = NULL;
142 
143 			new_buf_node->dma_buf = dma_buf;
144 			new_buf_node->import_count = 1;
145 			while (*new) {
146 				struct kbase_dma_buf *new_node;
147 
148 				parent = *new;
149 				new_node = rb_entry(parent, struct kbase_dma_buf,
150 						   dma_buf_node);
151 				if (dma_buf < new_node->dma_buf)
152 					new = &(*new)->rb_left;
153 				else
154 					new = &(*new)->rb_right;
155 			}
156 			rb_link_node(&new_buf_node->dma_buf_node, parent, new);
157 			rb_insert_color(&new_buf_node->dma_buf_node, root);
158 		}
159 	} else if (!WARN_ON(!buf_node)) {
160 		buf_node->import_count++;
161 	}
162 
163 	return unique_buf_imported;
164 }
165 
kbase_remove_dma_buf_usage(struct kbase_context * kctx,struct kbase_mem_phy_alloc * alloc)166 void kbase_remove_dma_buf_usage(struct kbase_context *kctx,
167 				struct kbase_mem_phy_alloc *alloc)
168 {
169 	struct kbase_device *kbdev = kctx->kbdev;
170 	bool dev_mapping_removed, prcs_mapping_removed;
171 
172 	mutex_lock(&kbdev->dma_buf_lock);
173 
174 	dev_mapping_removed = kbase_delete_dma_buf_mapping(
175 		kctx, alloc->imported.umm.dma_buf, &kbdev->dma_buf_root);
176 
177 	prcs_mapping_removed = kbase_delete_dma_buf_mapping(
178 		kctx, alloc->imported.umm.dma_buf, &kctx->kprcs->dma_buf_root);
179 
180 	WARN_ON(dev_mapping_removed && !prcs_mapping_removed);
181 
182 	spin_lock(&kbdev->gpu_mem_usage_lock);
183 	if (dev_mapping_removed)
184 		kbdev->total_gpu_pages -= alloc->nents;
185 
186 	if (prcs_mapping_removed)
187 		kctx->kprcs->total_gpu_pages -= alloc->nents;
188 
189 	if (dev_mapping_removed || prcs_mapping_removed)
190 		kbase_trace_gpu_mem_usage(kbdev, kctx);
191 	spin_unlock(&kbdev->gpu_mem_usage_lock);
192 
193 	mutex_unlock(&kbdev->dma_buf_lock);
194 }
195 
kbase_add_dma_buf_usage(struct kbase_context * kctx,struct kbase_mem_phy_alloc * alloc)196 void kbase_add_dma_buf_usage(struct kbase_context *kctx,
197 				    struct kbase_mem_phy_alloc *alloc)
198 {
199 	struct kbase_device *kbdev = kctx->kbdev;
200 	bool unique_dev_dmabuf, unique_prcs_dmabuf;
201 
202 	mutex_lock(&kbdev->dma_buf_lock);
203 
204 	/* add dma_buf to device and process. */
205 	unique_dev_dmabuf = kbase_capture_dma_buf_mapping(
206 		kctx, alloc->imported.umm.dma_buf, &kbdev->dma_buf_root);
207 
208 	unique_prcs_dmabuf = kbase_capture_dma_buf_mapping(
209 		kctx, alloc->imported.umm.dma_buf, &kctx->kprcs->dma_buf_root);
210 
211 	WARN_ON(unique_dev_dmabuf && !unique_prcs_dmabuf);
212 
213 	spin_lock(&kbdev->gpu_mem_usage_lock);
214 	if (unique_dev_dmabuf)
215 		kbdev->total_gpu_pages += alloc->nents;
216 
217 	if (unique_prcs_dmabuf)
218 		kctx->kprcs->total_gpu_pages += alloc->nents;
219 
220 	if (unique_prcs_dmabuf || unique_dev_dmabuf)
221 		kbase_trace_gpu_mem_usage(kbdev, kctx);
222 	spin_unlock(&kbdev->gpu_mem_usage_lock);
223 
224 	mutex_unlock(&kbdev->dma_buf_lock);
225 }
226