xref: /linux/drivers/accel/ivpu/ivpu_ms.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1*cdfad4dbSTomasz Rusinowicz // SPDX-License-Identifier: GPL-2.0-only OR MIT
2*cdfad4dbSTomasz Rusinowicz /*
3*cdfad4dbSTomasz Rusinowicz  * Copyright (C) 2020-2024 Intel Corporation
4*cdfad4dbSTomasz Rusinowicz  */
5*cdfad4dbSTomasz Rusinowicz 
6*cdfad4dbSTomasz Rusinowicz #include <drm/drm_file.h>
7*cdfad4dbSTomasz Rusinowicz 
8*cdfad4dbSTomasz Rusinowicz #include "ivpu_drv.h"
9*cdfad4dbSTomasz Rusinowicz #include "ivpu_gem.h"
10*cdfad4dbSTomasz Rusinowicz #include "ivpu_jsm_msg.h"
11*cdfad4dbSTomasz Rusinowicz #include "ivpu_ms.h"
12*cdfad4dbSTomasz Rusinowicz #include "ivpu_pm.h"
13*cdfad4dbSTomasz Rusinowicz 
14*cdfad4dbSTomasz Rusinowicz #define MS_INFO_BUFFER_SIZE	  SZ_16K
15*cdfad4dbSTomasz Rusinowicz #define MS_NUM_BUFFERS		  2
16*cdfad4dbSTomasz Rusinowicz #define MS_READ_PERIOD_MULTIPLIER 2
17*cdfad4dbSTomasz Rusinowicz #define MS_MIN_SAMPLE_PERIOD_NS   1000000
18*cdfad4dbSTomasz Rusinowicz 
19*cdfad4dbSTomasz Rusinowicz static struct ivpu_ms_instance *
get_instance_by_mask(struct ivpu_file_priv * file_priv,u64 metric_mask)20*cdfad4dbSTomasz Rusinowicz get_instance_by_mask(struct ivpu_file_priv *file_priv, u64 metric_mask)
21*cdfad4dbSTomasz Rusinowicz {
22*cdfad4dbSTomasz Rusinowicz 	struct ivpu_ms_instance *ms;
23*cdfad4dbSTomasz Rusinowicz 
24*cdfad4dbSTomasz Rusinowicz 	lockdep_assert_held(&file_priv->ms_lock);
25*cdfad4dbSTomasz Rusinowicz 
26*cdfad4dbSTomasz Rusinowicz 	list_for_each_entry(ms, &file_priv->ms_instance_list, ms_instance_node)
27*cdfad4dbSTomasz Rusinowicz 		if (ms->mask == metric_mask)
28*cdfad4dbSTomasz Rusinowicz 			return ms;
29*cdfad4dbSTomasz Rusinowicz 
30*cdfad4dbSTomasz Rusinowicz 	return NULL;
31*cdfad4dbSTomasz Rusinowicz }
32*cdfad4dbSTomasz Rusinowicz 
ivpu_ms_start_ioctl(struct drm_device * dev,void * data,struct drm_file * file)33*cdfad4dbSTomasz Rusinowicz int ivpu_ms_start_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
34*cdfad4dbSTomasz Rusinowicz {
35*cdfad4dbSTomasz Rusinowicz 	struct ivpu_file_priv *file_priv = file->driver_priv;
36*cdfad4dbSTomasz Rusinowicz 	struct drm_ivpu_metric_streamer_start *args = data;
37*cdfad4dbSTomasz Rusinowicz 	struct ivpu_device *vdev = file_priv->vdev;
38*cdfad4dbSTomasz Rusinowicz 	struct ivpu_ms_instance *ms;
39*cdfad4dbSTomasz Rusinowicz 	u64 single_buff_size;
40*cdfad4dbSTomasz Rusinowicz 	u32 sample_size;
41*cdfad4dbSTomasz Rusinowicz 	int ret;
42*cdfad4dbSTomasz Rusinowicz 
43*cdfad4dbSTomasz Rusinowicz 	if (!args->metric_group_mask || !args->read_period_samples ||
44*cdfad4dbSTomasz Rusinowicz 	    args->sampling_period_ns < MS_MIN_SAMPLE_PERIOD_NS)
45*cdfad4dbSTomasz Rusinowicz 		return -EINVAL;
46*cdfad4dbSTomasz Rusinowicz 
47*cdfad4dbSTomasz Rusinowicz 	mutex_lock(&file_priv->ms_lock);
48*cdfad4dbSTomasz Rusinowicz 
49*cdfad4dbSTomasz Rusinowicz 	if (get_instance_by_mask(file_priv, args->metric_group_mask)) {
50*cdfad4dbSTomasz Rusinowicz 		ivpu_err(vdev, "Instance already exists (mask %#llx)\n", args->metric_group_mask);
51*cdfad4dbSTomasz Rusinowicz 		ret = -EALREADY;
52*cdfad4dbSTomasz Rusinowicz 		goto unlock;
53*cdfad4dbSTomasz Rusinowicz 	}
54*cdfad4dbSTomasz Rusinowicz 
55*cdfad4dbSTomasz Rusinowicz 	ms = kzalloc(sizeof(*ms), GFP_KERNEL);
56*cdfad4dbSTomasz Rusinowicz 	if (!ms) {
57*cdfad4dbSTomasz Rusinowicz 		ret = -ENOMEM;
58*cdfad4dbSTomasz Rusinowicz 		goto unlock;
59*cdfad4dbSTomasz Rusinowicz 	}
60*cdfad4dbSTomasz Rusinowicz 
61*cdfad4dbSTomasz Rusinowicz 	ms->mask = args->metric_group_mask;
62*cdfad4dbSTomasz Rusinowicz 
63*cdfad4dbSTomasz Rusinowicz 	ret = ivpu_jsm_metric_streamer_info(vdev, ms->mask, 0, 0, &sample_size, NULL);
64*cdfad4dbSTomasz Rusinowicz 	if (ret)
65*cdfad4dbSTomasz Rusinowicz 		goto err_free_ms;
66*cdfad4dbSTomasz Rusinowicz 
67*cdfad4dbSTomasz Rusinowicz 	single_buff_size = sample_size *
68*cdfad4dbSTomasz Rusinowicz 		((u64)args->read_period_samples * MS_READ_PERIOD_MULTIPLIER);
69*cdfad4dbSTomasz Rusinowicz 	ms->bo = ivpu_bo_create_global(vdev, PAGE_ALIGN(single_buff_size * MS_NUM_BUFFERS),
70*cdfad4dbSTomasz Rusinowicz 				       DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE);
71*cdfad4dbSTomasz Rusinowicz 	if (!ms->bo) {
72*cdfad4dbSTomasz Rusinowicz 		ivpu_err(vdev, "Failed to allocate MS buffer (size %llu)\n", single_buff_size);
73*cdfad4dbSTomasz Rusinowicz 		ret = -ENOMEM;
74*cdfad4dbSTomasz Rusinowicz 		goto err_free_ms;
75*cdfad4dbSTomasz Rusinowicz 	}
76*cdfad4dbSTomasz Rusinowicz 
77*cdfad4dbSTomasz Rusinowicz 	ms->buff_size = ivpu_bo_size(ms->bo) / MS_NUM_BUFFERS;
78*cdfad4dbSTomasz Rusinowicz 	ms->active_buff_vpu_addr = ms->bo->vpu_addr;
79*cdfad4dbSTomasz Rusinowicz 	ms->inactive_buff_vpu_addr = ms->bo->vpu_addr + ms->buff_size;
80*cdfad4dbSTomasz Rusinowicz 	ms->active_buff_ptr = ivpu_bo_vaddr(ms->bo);
81*cdfad4dbSTomasz Rusinowicz 	ms->inactive_buff_ptr = ivpu_bo_vaddr(ms->bo) + ms->buff_size;
82*cdfad4dbSTomasz Rusinowicz 
83*cdfad4dbSTomasz Rusinowicz 	ret = ivpu_jsm_metric_streamer_start(vdev, ms->mask, args->sampling_period_ns,
84*cdfad4dbSTomasz Rusinowicz 					     ms->active_buff_vpu_addr, ms->buff_size);
85*cdfad4dbSTomasz Rusinowicz 	if (ret)
86*cdfad4dbSTomasz Rusinowicz 		goto err_free_bo;
87*cdfad4dbSTomasz Rusinowicz 
88*cdfad4dbSTomasz Rusinowicz 	args->sample_size = sample_size;
89*cdfad4dbSTomasz Rusinowicz 	args->max_data_size = ivpu_bo_size(ms->bo);
90*cdfad4dbSTomasz Rusinowicz 	list_add_tail(&ms->ms_instance_node, &file_priv->ms_instance_list);
91*cdfad4dbSTomasz Rusinowicz 	goto unlock;
92*cdfad4dbSTomasz Rusinowicz 
93*cdfad4dbSTomasz Rusinowicz err_free_bo:
94*cdfad4dbSTomasz Rusinowicz 	ivpu_bo_free(ms->bo);
95*cdfad4dbSTomasz Rusinowicz err_free_ms:
96*cdfad4dbSTomasz Rusinowicz 	kfree(ms);
97*cdfad4dbSTomasz Rusinowicz unlock:
98*cdfad4dbSTomasz Rusinowicz 	mutex_unlock(&file_priv->ms_lock);
99*cdfad4dbSTomasz Rusinowicz 	return ret;
100*cdfad4dbSTomasz Rusinowicz }
101*cdfad4dbSTomasz Rusinowicz 
102*cdfad4dbSTomasz Rusinowicz static int
copy_leftover_bytes(struct ivpu_ms_instance * ms,void __user * user_ptr,u64 user_size,u64 * user_bytes_copied)103*cdfad4dbSTomasz Rusinowicz copy_leftover_bytes(struct ivpu_ms_instance *ms,
104*cdfad4dbSTomasz Rusinowicz 		    void __user *user_ptr, u64 user_size, u64 *user_bytes_copied)
105*cdfad4dbSTomasz Rusinowicz {
106*cdfad4dbSTomasz Rusinowicz 	u64 copy_bytes;
107*cdfad4dbSTomasz Rusinowicz 
108*cdfad4dbSTomasz Rusinowicz 	if (ms->leftover_bytes) {
109*cdfad4dbSTomasz Rusinowicz 		copy_bytes = min(user_size - *user_bytes_copied, ms->leftover_bytes);
110*cdfad4dbSTomasz Rusinowicz 		if (copy_to_user(user_ptr + *user_bytes_copied, ms->leftover_addr, copy_bytes))
111*cdfad4dbSTomasz Rusinowicz 			return -EFAULT;
112*cdfad4dbSTomasz Rusinowicz 
113*cdfad4dbSTomasz Rusinowicz 		ms->leftover_bytes -= copy_bytes;
114*cdfad4dbSTomasz Rusinowicz 		ms->leftover_addr += copy_bytes;
115*cdfad4dbSTomasz Rusinowicz 		*user_bytes_copied += copy_bytes;
116*cdfad4dbSTomasz Rusinowicz 	}
117*cdfad4dbSTomasz Rusinowicz 
118*cdfad4dbSTomasz Rusinowicz 	return 0;
119*cdfad4dbSTomasz Rusinowicz }
120*cdfad4dbSTomasz Rusinowicz 
121*cdfad4dbSTomasz Rusinowicz static int
copy_samples_to_user(struct ivpu_device * vdev,struct ivpu_ms_instance * ms,void __user * user_ptr,u64 user_size,u64 * user_bytes_copied)122*cdfad4dbSTomasz Rusinowicz copy_samples_to_user(struct ivpu_device *vdev, struct ivpu_ms_instance *ms,
123*cdfad4dbSTomasz Rusinowicz 		     void __user *user_ptr, u64 user_size, u64 *user_bytes_copied)
124*cdfad4dbSTomasz Rusinowicz {
125*cdfad4dbSTomasz Rusinowicz 	u64 bytes_written;
126*cdfad4dbSTomasz Rusinowicz 	int ret;
127*cdfad4dbSTomasz Rusinowicz 
128*cdfad4dbSTomasz Rusinowicz 	*user_bytes_copied = 0;
129*cdfad4dbSTomasz Rusinowicz 
130*cdfad4dbSTomasz Rusinowicz 	ret = copy_leftover_bytes(ms, user_ptr, user_size, user_bytes_copied);
131*cdfad4dbSTomasz Rusinowicz 	if (ret)
132*cdfad4dbSTomasz Rusinowicz 		return ret;
133*cdfad4dbSTomasz Rusinowicz 
134*cdfad4dbSTomasz Rusinowicz 	if (*user_bytes_copied == user_size)
135*cdfad4dbSTomasz Rusinowicz 		return 0;
136*cdfad4dbSTomasz Rusinowicz 
137*cdfad4dbSTomasz Rusinowicz 	ret = ivpu_jsm_metric_streamer_update(vdev, ms->mask, ms->inactive_buff_vpu_addr,
138*cdfad4dbSTomasz Rusinowicz 					      ms->buff_size, &bytes_written);
139*cdfad4dbSTomasz Rusinowicz 	if (ret)
140*cdfad4dbSTomasz Rusinowicz 		return ret;
141*cdfad4dbSTomasz Rusinowicz 
142*cdfad4dbSTomasz Rusinowicz 	swap(ms->active_buff_vpu_addr, ms->inactive_buff_vpu_addr);
143*cdfad4dbSTomasz Rusinowicz 	swap(ms->active_buff_ptr, ms->inactive_buff_ptr);
144*cdfad4dbSTomasz Rusinowicz 
145*cdfad4dbSTomasz Rusinowicz 	ms->leftover_bytes = bytes_written;
146*cdfad4dbSTomasz Rusinowicz 	ms->leftover_addr = ms->inactive_buff_ptr;
147*cdfad4dbSTomasz Rusinowicz 
148*cdfad4dbSTomasz Rusinowicz 	return copy_leftover_bytes(ms, user_ptr, user_size, user_bytes_copied);
149*cdfad4dbSTomasz Rusinowicz }
150*cdfad4dbSTomasz Rusinowicz 
ivpu_ms_get_data_ioctl(struct drm_device * dev,void * data,struct drm_file * file)151*cdfad4dbSTomasz Rusinowicz int ivpu_ms_get_data_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
152*cdfad4dbSTomasz Rusinowicz {
153*cdfad4dbSTomasz Rusinowicz 	struct drm_ivpu_metric_streamer_get_data *args = data;
154*cdfad4dbSTomasz Rusinowicz 	struct ivpu_file_priv *file_priv = file->driver_priv;
155*cdfad4dbSTomasz Rusinowicz 	struct ivpu_device *vdev = file_priv->vdev;
156*cdfad4dbSTomasz Rusinowicz 	struct ivpu_ms_instance *ms;
157*cdfad4dbSTomasz Rusinowicz 	u64 bytes_written;
158*cdfad4dbSTomasz Rusinowicz 	int ret;
159*cdfad4dbSTomasz Rusinowicz 
160*cdfad4dbSTomasz Rusinowicz 	if (!args->metric_group_mask)
161*cdfad4dbSTomasz Rusinowicz 		return -EINVAL;
162*cdfad4dbSTomasz Rusinowicz 
163*cdfad4dbSTomasz Rusinowicz 	mutex_lock(&file_priv->ms_lock);
164*cdfad4dbSTomasz Rusinowicz 
165*cdfad4dbSTomasz Rusinowicz 	ms = get_instance_by_mask(file_priv, args->metric_group_mask);
166*cdfad4dbSTomasz Rusinowicz 	if (!ms) {
167*cdfad4dbSTomasz Rusinowicz 		ivpu_err(vdev, "Instance doesn't exist for mask: %#llx\n", args->metric_group_mask);
168*cdfad4dbSTomasz Rusinowicz 		ret = -EINVAL;
169*cdfad4dbSTomasz Rusinowicz 		goto unlock;
170*cdfad4dbSTomasz Rusinowicz 	}
171*cdfad4dbSTomasz Rusinowicz 
172*cdfad4dbSTomasz Rusinowicz 	if (!args->buffer_size) {
173*cdfad4dbSTomasz Rusinowicz 		ret = ivpu_jsm_metric_streamer_update(vdev, ms->mask, 0, 0, &bytes_written);
174*cdfad4dbSTomasz Rusinowicz 		if (ret)
175*cdfad4dbSTomasz Rusinowicz 			goto unlock;
176*cdfad4dbSTomasz Rusinowicz 		args->data_size = bytes_written + ms->leftover_bytes;
177*cdfad4dbSTomasz Rusinowicz 		goto unlock;
178*cdfad4dbSTomasz Rusinowicz 	}
179*cdfad4dbSTomasz Rusinowicz 
180*cdfad4dbSTomasz Rusinowicz 	if (!args->buffer_ptr) {
181*cdfad4dbSTomasz Rusinowicz 		ret = -EINVAL;
182*cdfad4dbSTomasz Rusinowicz 		goto unlock;
183*cdfad4dbSTomasz Rusinowicz 	}
184*cdfad4dbSTomasz Rusinowicz 
185*cdfad4dbSTomasz Rusinowicz 	ret = copy_samples_to_user(vdev, ms, u64_to_user_ptr(args->buffer_ptr),
186*cdfad4dbSTomasz Rusinowicz 				   args->buffer_size, &args->data_size);
187*cdfad4dbSTomasz Rusinowicz unlock:
188*cdfad4dbSTomasz Rusinowicz 	mutex_unlock(&file_priv->ms_lock);
189*cdfad4dbSTomasz Rusinowicz 
190*cdfad4dbSTomasz Rusinowicz 	return ret;
191*cdfad4dbSTomasz Rusinowicz }
192*cdfad4dbSTomasz Rusinowicz 
free_instance(struct ivpu_file_priv * file_priv,struct ivpu_ms_instance * ms)193*cdfad4dbSTomasz Rusinowicz static void free_instance(struct ivpu_file_priv *file_priv, struct ivpu_ms_instance *ms)
194*cdfad4dbSTomasz Rusinowicz {
195*cdfad4dbSTomasz Rusinowicz 	lockdep_assert_held(&file_priv->ms_lock);
196*cdfad4dbSTomasz Rusinowicz 
197*cdfad4dbSTomasz Rusinowicz 	list_del(&ms->ms_instance_node);
198*cdfad4dbSTomasz Rusinowicz 	ivpu_jsm_metric_streamer_stop(file_priv->vdev, ms->mask);
199*cdfad4dbSTomasz Rusinowicz 	ivpu_bo_free(ms->bo);
200*cdfad4dbSTomasz Rusinowicz 	kfree(ms);
201*cdfad4dbSTomasz Rusinowicz }
202*cdfad4dbSTomasz Rusinowicz 
ivpu_ms_stop_ioctl(struct drm_device * dev,void * data,struct drm_file * file)203*cdfad4dbSTomasz Rusinowicz int ivpu_ms_stop_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
204*cdfad4dbSTomasz Rusinowicz {
205*cdfad4dbSTomasz Rusinowicz 	struct ivpu_file_priv *file_priv = file->driver_priv;
206*cdfad4dbSTomasz Rusinowicz 	struct drm_ivpu_metric_streamer_stop *args = data;
207*cdfad4dbSTomasz Rusinowicz 	struct ivpu_ms_instance *ms;
208*cdfad4dbSTomasz Rusinowicz 
209*cdfad4dbSTomasz Rusinowicz 	if (!args->metric_group_mask)
210*cdfad4dbSTomasz Rusinowicz 		return -EINVAL;
211*cdfad4dbSTomasz Rusinowicz 
212*cdfad4dbSTomasz Rusinowicz 	mutex_lock(&file_priv->ms_lock);
213*cdfad4dbSTomasz Rusinowicz 
214*cdfad4dbSTomasz Rusinowicz 	ms = get_instance_by_mask(file_priv, args->metric_group_mask);
215*cdfad4dbSTomasz Rusinowicz 	if (ms)
216*cdfad4dbSTomasz Rusinowicz 		free_instance(file_priv, ms);
217*cdfad4dbSTomasz Rusinowicz 
218*cdfad4dbSTomasz Rusinowicz 	mutex_unlock(&file_priv->ms_lock);
219*cdfad4dbSTomasz Rusinowicz 
220*cdfad4dbSTomasz Rusinowicz 	return ms ? 0 : -EINVAL;
221*cdfad4dbSTomasz Rusinowicz }
222*cdfad4dbSTomasz Rusinowicz 
get_ms_info_bo(struct ivpu_file_priv * file_priv)223*cdfad4dbSTomasz Rusinowicz static inline struct ivpu_bo *get_ms_info_bo(struct ivpu_file_priv *file_priv)
224*cdfad4dbSTomasz Rusinowicz {
225*cdfad4dbSTomasz Rusinowicz 	lockdep_assert_held(&file_priv->ms_lock);
226*cdfad4dbSTomasz Rusinowicz 
227*cdfad4dbSTomasz Rusinowicz 	if (file_priv->ms_info_bo)
228*cdfad4dbSTomasz Rusinowicz 		return file_priv->ms_info_bo;
229*cdfad4dbSTomasz Rusinowicz 
230*cdfad4dbSTomasz Rusinowicz 	file_priv->ms_info_bo = ivpu_bo_create_global(file_priv->vdev, MS_INFO_BUFFER_SIZE,
231*cdfad4dbSTomasz Rusinowicz 						      DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE);
232*cdfad4dbSTomasz Rusinowicz 	return file_priv->ms_info_bo;
233*cdfad4dbSTomasz Rusinowicz }
234*cdfad4dbSTomasz Rusinowicz 
ivpu_ms_get_info_ioctl(struct drm_device * dev,void * data,struct drm_file * file)235*cdfad4dbSTomasz Rusinowicz int ivpu_ms_get_info_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
236*cdfad4dbSTomasz Rusinowicz {
237*cdfad4dbSTomasz Rusinowicz 	struct drm_ivpu_metric_streamer_get_data *args = data;
238*cdfad4dbSTomasz Rusinowicz 	struct ivpu_file_priv *file_priv = file->driver_priv;
239*cdfad4dbSTomasz Rusinowicz 	struct ivpu_device *vdev = file_priv->vdev;
240*cdfad4dbSTomasz Rusinowicz 	struct ivpu_bo *bo;
241*cdfad4dbSTomasz Rusinowicz 	u64 info_size;
242*cdfad4dbSTomasz Rusinowicz 	int ret;
243*cdfad4dbSTomasz Rusinowicz 
244*cdfad4dbSTomasz Rusinowicz 	if (!args->metric_group_mask)
245*cdfad4dbSTomasz Rusinowicz 		return -EINVAL;
246*cdfad4dbSTomasz Rusinowicz 
247*cdfad4dbSTomasz Rusinowicz 	if (!args->buffer_size)
248*cdfad4dbSTomasz Rusinowicz 		return ivpu_jsm_metric_streamer_info(vdev, args->metric_group_mask,
249*cdfad4dbSTomasz Rusinowicz 						     0, 0, NULL, &args->data_size);
250*cdfad4dbSTomasz Rusinowicz 	if (!args->buffer_ptr)
251*cdfad4dbSTomasz Rusinowicz 		return -EINVAL;
252*cdfad4dbSTomasz Rusinowicz 
253*cdfad4dbSTomasz Rusinowicz 	mutex_lock(&file_priv->ms_lock);
254*cdfad4dbSTomasz Rusinowicz 
255*cdfad4dbSTomasz Rusinowicz 	bo = get_ms_info_bo(file_priv);
256*cdfad4dbSTomasz Rusinowicz 	if (!bo) {
257*cdfad4dbSTomasz Rusinowicz 		ret = -ENOMEM;
258*cdfad4dbSTomasz Rusinowicz 		goto unlock;
259*cdfad4dbSTomasz Rusinowicz 	}
260*cdfad4dbSTomasz Rusinowicz 
261*cdfad4dbSTomasz Rusinowicz 	ret = ivpu_jsm_metric_streamer_info(vdev, args->metric_group_mask, bo->vpu_addr,
262*cdfad4dbSTomasz Rusinowicz 					    ivpu_bo_size(bo), NULL, &info_size);
263*cdfad4dbSTomasz Rusinowicz 	if (ret)
264*cdfad4dbSTomasz Rusinowicz 		goto unlock;
265*cdfad4dbSTomasz Rusinowicz 
266*cdfad4dbSTomasz Rusinowicz 	if (args->buffer_size < info_size) {
267*cdfad4dbSTomasz Rusinowicz 		ret = -ENOSPC;
268*cdfad4dbSTomasz Rusinowicz 		goto unlock;
269*cdfad4dbSTomasz Rusinowicz 	}
270*cdfad4dbSTomasz Rusinowicz 
271*cdfad4dbSTomasz Rusinowicz 	if (copy_to_user(u64_to_user_ptr(args->buffer_ptr), ivpu_bo_vaddr(bo), info_size))
272*cdfad4dbSTomasz Rusinowicz 		ret = -EFAULT;
273*cdfad4dbSTomasz Rusinowicz 
274*cdfad4dbSTomasz Rusinowicz 	args->data_size = info_size;
275*cdfad4dbSTomasz Rusinowicz unlock:
276*cdfad4dbSTomasz Rusinowicz 	mutex_unlock(&file_priv->ms_lock);
277*cdfad4dbSTomasz Rusinowicz 
278*cdfad4dbSTomasz Rusinowicz 	return ret;
279*cdfad4dbSTomasz Rusinowicz }
280*cdfad4dbSTomasz Rusinowicz 
ivpu_ms_cleanup(struct ivpu_file_priv * file_priv)281*cdfad4dbSTomasz Rusinowicz void ivpu_ms_cleanup(struct ivpu_file_priv *file_priv)
282*cdfad4dbSTomasz Rusinowicz {
283*cdfad4dbSTomasz Rusinowicz 	struct ivpu_ms_instance *ms, *tmp;
284*cdfad4dbSTomasz Rusinowicz 
285*cdfad4dbSTomasz Rusinowicz 	mutex_lock(&file_priv->ms_lock);
286*cdfad4dbSTomasz Rusinowicz 
287*cdfad4dbSTomasz Rusinowicz 	if (file_priv->ms_info_bo) {
288*cdfad4dbSTomasz Rusinowicz 		ivpu_bo_free(file_priv->ms_info_bo);
289*cdfad4dbSTomasz Rusinowicz 		file_priv->ms_info_bo = NULL;
290*cdfad4dbSTomasz Rusinowicz 	}
291*cdfad4dbSTomasz Rusinowicz 
292*cdfad4dbSTomasz Rusinowicz 	list_for_each_entry_safe(ms, tmp, &file_priv->ms_instance_list, ms_instance_node)
293*cdfad4dbSTomasz Rusinowicz 		free_instance(file_priv, ms);
294*cdfad4dbSTomasz Rusinowicz 
295*cdfad4dbSTomasz Rusinowicz 	mutex_unlock(&file_priv->ms_lock);
296*cdfad4dbSTomasz Rusinowicz }
297*cdfad4dbSTomasz Rusinowicz 
ivpu_ms_cleanup_all(struct ivpu_device * vdev)298*cdfad4dbSTomasz Rusinowicz void ivpu_ms_cleanup_all(struct ivpu_device *vdev)
299*cdfad4dbSTomasz Rusinowicz {
300*cdfad4dbSTomasz Rusinowicz 	struct ivpu_file_priv *file_priv;
301*cdfad4dbSTomasz Rusinowicz 	unsigned long ctx_id;
302*cdfad4dbSTomasz Rusinowicz 
303*cdfad4dbSTomasz Rusinowicz 	mutex_lock(&vdev->context_list_lock);
304*cdfad4dbSTomasz Rusinowicz 
305*cdfad4dbSTomasz Rusinowicz 	xa_for_each(&vdev->context_xa, ctx_id, file_priv)
306*cdfad4dbSTomasz Rusinowicz 		ivpu_ms_cleanup(file_priv);
307*cdfad4dbSTomasz Rusinowicz 
308*cdfad4dbSTomasz Rusinowicz 	mutex_unlock(&vdev->context_list_lock);
309*cdfad4dbSTomasz Rusinowicz }
310