• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * rtg control entry
4  *
5  * Copyright (c) 2022-2023 Huawei Technologies Co., Ltd.
6  */
7 
8 #include "rtg.h"
9 #include "rtg_ctrl.h"
10 
11 #include <linux/module.h>
12 #include <linux/device.h>
13 
14 #ifdef CONFIG_AUTHORITY_CTRL
15 #include <linux/sched/auth_ctrl.h>
16 #endif
17 
18 #include <linux/miscdevice.h>
19 #include <linux/compat.h>
20 #include <trace/events/rtg.h>
21 
22 atomic_t g_rtg_enable = ATOMIC_INIT(0);
23 static atomic_t g_rt_frame_num = ATOMIC_INIT(0);
24 static int g_frame_max_util = DEFAULT_MAX_UTIL;
25 static int g_max_rt_frames = DEFAULT_MAX_RT_FRAME;
26 typedef long (*rtg_ctrl_func)(int abi, void __user *arg);
27 
28 static long ctrl_set_enable(int abi, void __user *uarg);
29 static long ctrl_set_rtg(int abi, void __user *uarg);
30 static long ctrl_set_rtg_attr(int abi, void __user *uarg);
31 static long ctrl_begin_frame(int abi, void __user *uarg);
32 static long ctrl_end_frame(int abi, void __user *uarg);
33 static long ctrl_end_scene(int abi, void __user *uarg);
34 static long ctrl_set_min_util(int abi, void __user *uarg);
35 static long ctrl_set_margin(int abi, void __user *uarg);
36 static long ctrl_search_rtg(int abi, void __user *uarg);
37 static long ctrl_get_enable(int abi, void __user *uarg);
38 
39 static rtg_ctrl_func g_func_array[RTG_CTRL_MAX_NR] = {
40 	NULL, /* reserved */
41 	ctrl_set_enable,  // 1
42 	ctrl_set_rtg,
43 	NULL,
44 	ctrl_set_rtg_attr,
45 	ctrl_begin_frame,  // 5
46 	ctrl_end_frame,
47 	ctrl_end_scene,
48 	ctrl_set_min_util,
49 	ctrl_set_margin,
50 	NULL,
51 	NULL,
52 	ctrl_search_rtg,
53 	ctrl_get_enable
54 };
55 
56 static int init_proc_state(const int *config, int len);
57 static void deinit_proc_state(void);
58 
set_enable_config(char * config_str)59 static int set_enable_config(char *config_str)
60 {
61 	char *p = NULL;
62 	char *tmp = NULL;
63 	int value;
64 	int config[RTG_CONFIG_NUM];
65 	int i;
66 	int ret = 0;
67 
68 	for (i = 0; i < RTG_CONFIG_NUM; i++)
69 		config[i] = INVALID_VALUE;
70 	/* eg: key1:value1;key2:value2;key3:value3 */
71 	for (p = strsep(&config_str, ";"); p != NULL;
72 		p = strsep(&config_str, ";")) {
73 		tmp = strsep(&p, ":");
74 		if ((tmp == NULL) || (p == NULL))
75 			continue;
76 		if (kstrtoint((const char *)p, DECIMAL, &value))
77 			return -INVALID_ARG;
78 
79 		if (!strcmp(tmp, "sched_cycle"))
80 			config[RTG_FREQ_CYCLE] = value;
81 		else if (!strcmp(tmp, "frame_max_util"))
82 			config[RTG_FRAME_MAX_UTIL] = value;
83 		else if (!strcmp(tmp, "invalid_interval"))
84 			config[RTG_INVALID_INTERVAL] = value;
85 		else
86 			continue;
87 	}
88 
89 	for (i = 0; i < RTG_CONFIG_NUM; i++)
90 		pr_info("[SCHED_RTG] config[%d] = %d\n", i, config[i]);
91 
92 	ret = init_proc_state(config, RTG_CONFIG_NUM);
93 
94 	return ret;
95 }
96 
rtg_enable(int abi,const struct rtg_enable_data * data)97 static void rtg_enable(int abi, const struct rtg_enable_data *data)
98 {
99 	char temp[MAX_DATA_LEN];
100 	int ret = -1;
101 
102 	if (atomic_read(&g_rtg_enable) == 1) {
103 		pr_info("[SCHED_RTG] already enabled!\n");
104 		return;
105 	}
106 
107 	if ((data->len <= 0) || (data->len >= MAX_DATA_LEN)) {
108 		pr_err("[SCHED_RTG] %s data len invalid\n", __func__);
109 		return;
110 	}
111 
112 #pragma GCC diagnostic push
113 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
114 	switch (abi) {
115 	case IOCTL_ABI_ARM32:
116 		ret = copy_from_user(&temp,
117 			(void __user *)compat_ptr((compat_uptr_t)data->data), data->len);
118 		break;
119 	case IOCTL_ABI_AARCH64:
120 		ret = copy_from_user(&temp, (void __user *)data->data, data->len);
121 		break;
122 	default:
123 		pr_err("[SCHED_RTG] abi format error\n");
124 		break;
125 	}
126 	if (ret) {
127 		pr_err("[SCHED_RTG] %s copy user data failed\n", __func__);
128 		return;
129 	}
130 #pragma GCC diagnostic pop
131 
132 #pragma GCC diagnostic push
133 #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
134 	temp[data->len] = '\0';
135 
136 	if (set_enable_config(&temp) != SUCC) {
137 		pr_err("[SCHED_RTG] %s failed!\n", __func__);
138 		return;
139 	}
140 #pragma GCC diagnostic pop
141 
142 	atomic_set(&g_rtg_enable, 1);
143 	pr_info("[SCHED_RTG] enabled!\n");
144 }
145 
rtg_disable(void)146 static void rtg_disable(void)
147 {
148 	if (atomic_read(&g_rtg_enable) == 0) {
149 		pr_info("[SCHED_RTG] already disabled!\n");
150 		return;
151 	}
152 	pr_info("[SCHED_RTG] disabled!\n");
153 	atomic_set(&g_rtg_enable, 0);
154 	deinit_proc_state();
155 }
156 
is_rt_type(int type)157 static inline bool is_rt_type(int type)
158 {
159 	return (type >= VIP && type < NORMAL_TASK);
160 }
161 
do_update_rt_frame_num(struct frame_info * frame_info,int new_type)162 static int do_update_rt_frame_num(struct frame_info *frame_info, int new_type)
163 {
164 	int old_type;
165 	int ret = SUCC;
166 
167 	mutex_lock(&frame_info->lock);
168 	old_type = frame_info->prio - DEFAULT_RT_PRIO;
169 	if (is_rt_type(new_type) == is_rt_type(old_type))
170 		goto out;
171 
172 	if (is_rt_type(old_type)) {
173 		if (atomic_read(&g_rt_frame_num) > 0)
174 			atomic_dec(&g_rt_frame_num);
175 	} else if (is_rt_type(new_type)) {
176 		if (atomic_read(&g_rt_frame_num) < g_max_rt_frames) {
177 			atomic_inc(&g_rt_frame_num);
178 		} else {
179 			pr_err("[SCHED_RTG]: %s g_max_rt_frames is %d\n",
180 				__func__, g_max_rt_frames);
181 			ret = -INVALID_ARG;
182 		}
183 	}
184 out:
185 	mutex_unlock(&frame_info->lock);
186 
187 	return ret;
188 }
189 
update_rt_frame_num(struct frame_info * frame_info,int new_type,int cmd)190 static int update_rt_frame_num(struct frame_info *frame_info, int new_type, int cmd)
191 {
192 	int ret = SUCC;
193 
194 	switch (cmd) {
195 	case UPDATE_RTG_FRAME:
196 		ret = do_update_rt_frame_num(frame_info, new_type);
197 		break;
198 	case ADD_RTG_FRAME:
199 		if (is_rt_type(new_type)) {
200 			if (atomic_read(&g_rt_frame_num) >= g_max_rt_frames) {
201 				pr_err("[SCHED_RTG] g_max_rt_frames is %d!\n", g_max_rt_frames);
202 				ret = -INVALID_ARG;
203 			} else {
204 				atomic_inc(&g_rt_frame_num);
205 			}
206 		}
207 		break;
208 	case CLEAR_RTG_FRAME:
209 		if ((atomic_read(&g_rt_frame_num) > 0) && is_rt_type(new_type))
210 			atomic_dec(&g_rt_frame_num);
211 		break;
212 	default:
213 		return -INVALID_ARG;
214 	}
215 	trace_rtg_frame_sched(frame_info->rtg->id, "g_rt_frame_num", atomic_read(&g_rt_frame_num));
216 	trace_rtg_frame_sched(frame_info->rtg->id, "g_max_rt_frames", g_max_rt_frames);
217 
218 	return ret;
219 }
220 
ctrl_set_enable(int abi,void __user * uarg)221 static long ctrl_set_enable(int abi, void __user *uarg)
222 {
223 	struct rtg_enable_data rs_enable;
224 
225 	if (copy_from_user(&rs_enable, uarg, sizeof(rs_enable))) {
226 		pr_err("[SCHED_RTG] CMD_ID_SET_ENABLE copy data failed\n");
227 		return -INVALID_ARG;
228 	}
229 	if (rs_enable.enable == 1)
230 		rtg_enable(abi, &rs_enable);
231 	else
232 		rtg_disable();
233 
234 	return SUCC;
235 }
236 
ctrl_get_enable(int abi,void __user * uarg)237 static long ctrl_get_enable(int abi, void __user *uarg)
238 {
239 	return atomic_read(&g_rtg_enable);
240 }
241 
is_valid_type(int type)242 static inline bool is_valid_type(int type)
243 {
244 	return (type >= VIP && type < RTG_TYPE_MAX);
245 }
246 
parse_rtg_attr(const struct rtg_str_data * rs_data)247 static int parse_rtg_attr(const struct rtg_str_data *rs_data)
248 {
249 	char *p = NULL;
250 	char *tmp = NULL;
251 	char *data = NULL;
252 	int value;
253 	struct frame_info *frame_info = NULL;
254 	int rate = -1;
255 	int type = -1;
256 	int ret;
257 
258 	if (rs_data == NULL) {
259 		pr_err("[SCHED_RTG] rtg attr: rs_data is null!\n");
260 		return -INVALID_ARG;
261 	}
262 
263 	data = rs_data->data;
264 	if ((data == NULL) || (rs_data->len <= 0) ||
265 		(rs_data->len > MAX_DATA_LEN)) {
266 		pr_err("[SCHED_RTG] rtg attr: rs_data len err!\n");
267 		return -INVALID_ARG;
268 	}
269 
270 	// eg: rtgId:xx;rate:xx;type:xx;
271 	for (p = strsep(&data, ";"); p != NULL; p = strsep(&data, ";")) {
272 		tmp = strsep(&p, ":");
273 		if ((tmp == NULL) || (p == NULL))
274 			continue;
275 		if (kstrtoint((const char *)p, DECIMAL, &value)) {
276 			pr_err("[SCHED_RTG] rtg attr: rs_data format err!\n");
277 			return -INVALID_ARG;
278 		}
279 		if (!strcmp(tmp, "rtgId")) {
280 			frame_info = rtg_frame_info(value);
281 		} else if (!strcmp(tmp, "rate")) {
282 			rate = value;
283 		} else if (!strcmp(tmp, "type")) {
284 			if (is_valid_type(value)) {
285 				type = value;
286 			} else {
287 				pr_err("[SCHED_RTG] invalid type : %d\n", value);
288 				return -INVALID_ARG;
289 			}
290 		} else {
291 			pr_err("[SCHED_RTG] parse rtg attr failed!\n");
292 			return -INVALID_ARG;
293 		}
294 	}
295 
296 	if (!frame_info) {
297 		pr_err("[SCHED_RTG] rtg attr: invalid args!\n");
298 		return -INVALID_ARG;
299 	}
300 
301 	ret = set_frame_rate(frame_info, rate);
302 	if (ret)
303 		return ret;
304 
305 	if (is_valid_type(type)) {
306 		if (update_rt_frame_num(frame_info, type, UPDATE_RTG_FRAME)) {
307 			pr_err("[SCHED_RTG] set rtg attr failed!\n");
308 			return -INVALID_ARG;
309 		}
310 
311 		set_frame_prio(frame_info, (type == NORMAL_TASK ?
312 			       NOT_RT_PRIO : (type + DEFAULT_RT_PRIO)));
313 	}
314 
315 	return SUCC;
316 }
317 
ctrl_set_rtg_attr(int abi,void __user * uarg)318 static long ctrl_set_rtg_attr(int abi, void __user *uarg)
319 {
320 	struct rtg_str_data rs;
321 	char temp[MAX_DATA_LEN];
322 	int ret;
323 
324 	if (uarg == NULL)
325 		return -INVALID_ARG;
326 
327 	if (copy_from_user(&rs, uarg, sizeof(rs))) {
328 		pr_err("[SCHED_RTG] CMD_ID_SET_RTG_ATTR copy data failed\n");
329 		return -INVALID_ARG;
330 	}
331 	if ((rs.len <= 0) || (rs.len >= MAX_DATA_LEN)) {
332 		pr_err("[SCHED_RTG] CMD_ID_SET_RTG_ATTR data len invalid\n");
333 		return -INVALID_ARG;
334 	}
335 
336 #pragma GCC diagnostic push
337 #pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
338 	switch (abi) {
339 	case IOCTL_ABI_ARM32:
340 		ret = copy_from_user(&temp,
341 			(void __user *)compat_ptr((compat_uptr_t)rs.data), rs.len);
342 		break;
343 	case IOCTL_ABI_AARCH64:
344 		ret = copy_from_user(&temp, (void __user *)rs.data, rs.len);
345 		break;
346 	default:
347 		pr_err("[SCHED_RTG] abi format error\n");
348 		return -INVALID_ARG;
349 	}
350 #pragma GCC diagnostic pop
351 
352 	if (ret) {
353 		pr_err("[SCHED_RTG] CMD_ID_SET_RTG_ATTR copy rs.data failed with ret %d\n", ret);
354 		return -INVALID_ARG;
355 	}
356 
357 #pragma GCC diagnostic push
358 #pragma GCC diagnostic ignored "-Wincompatible-pointer-types"
359 	temp[rs.len] = '\0';
360 	rs.data = &temp;
361 #pragma GCC diagnostic pop
362 
363 	return parse_rtg_attr(&rs);
364 }
365 
start_frame_freq(struct frame_info * frame_info)366 static void start_frame_freq(struct frame_info *frame_info)
367 {
368 	if (!frame_info)
369 		return;
370 
371 	if (atomic_read(&frame_info->start_frame_freq) == 0) {
372 		atomic_set(&frame_info->start_frame_freq, 1);
373 		set_frame_sched_state(frame_info, true);
374 	}
375 }
376 
set_frame(struct frame_info * frame_info,int margin)377 static int set_frame(struct frame_info *frame_info, int margin)
378 {
379 	int ret;
380 	if (!frame_info)
381 		return -INVALID_RTG_ID;
382 
383 	atomic_set(&frame_info->frame_state, FRAME_DRAWING);
384 	ret = set_frame_margin(frame_info, margin);
385 	if (ret)
386 		goto out;
387 
388 	ret = set_frame_timestamp(frame_info, FRAME_START);
389 	if (ret)
390 		goto out;
391 
392 out:
393 	return ret;
394 }
395 
reset_frame(struct frame_info * frame_info)396 static int reset_frame(struct frame_info *frame_info)
397 {
398 	if (!frame_info)
399 		return -INVALID_RTG_ID;
400 
401 	if (atomic_read(&frame_info->frame_state) == FRAME_END_STATE) {
402 		pr_debug("[SCHED_RTG]: Frame state is already reset\n");
403 		return -INVALID_PROC_STATE;
404 	}
405 
406 	atomic_set(&frame_info->frame_state, FRAME_END_STATE);
407 	return set_frame_timestamp(frame_info, FRAME_END);
408 }
409 
update_frame_state(int grp_id,int margin,bool in_frame)410 int update_frame_state(int grp_id, int margin, bool in_frame)
411 {
412 	int ret;
413 	struct frame_info *frame_info = NULL;
414 
415 	frame_info = lookup_frame_info_by_grp_id(grp_id);
416 	if (!frame_info || !frame_info->rtg)
417 		return -INVALID_RTG_ID;
418 
419 	if (in_frame) {
420 		start_frame_freq(frame_info);
421 		ret = set_frame(frame_info, margin);
422 		trace_rtg_frame_sched(grp_id, "margin", margin);
423 	} else {
424 		ret = reset_frame(frame_info);
425 	}
426 
427 	return ret;
428 }
429 
curr_grp_id()430 static inline int curr_grp_id()
431 {
432 	return sched_get_group_id(current);
433 }
434 
ctrl_frame_state(void __user * uarg,bool is_enter)435 static long ctrl_frame_state(void __user *uarg, bool is_enter)
436 {
437 	struct proc_state_data state_data;
438 
439 	if (uarg == NULL)
440 		return -INVALID_ARG;
441 
442 	if (copy_from_user(&state_data, uarg, sizeof(state_data))) {
443 		pr_err("[SCHED_RTG] CMD_ID_FRAME_FREQ copy data failed\n");
444 		return -INVALID_ARG;
445 	}
446 
447 	return update_frame_state(curr_grp_id(), state_data.state_param, is_enter);
448 }
449 
ctrl_begin_frame(int abi,void __user * uarg)450 static long ctrl_begin_frame(int abi, void __user *uarg)
451 {
452 	return ctrl_frame_state(uarg, true);
453 }
454 
ctrl_end_frame(int abi,void __user * uarg)455 static long ctrl_end_frame(int abi, void __user *uarg)
456 {
457 	return ctrl_frame_state(uarg, false);
458 }
459 
stop_frame_freq(int gid)460 static int stop_frame_freq(int gid)
461 {
462 	struct frame_info *frame_info = NULL;
463 
464 	frame_info = lookup_frame_info_by_grp_id(gid);
465 	if (!frame_info)
466 		return -INVALID_RTG_ID;
467 
468 	atomic_set(&frame_info->start_frame_freq, 0);
469 	set_frame_sched_state(frame_info, false);
470 
471 	return 0;
472 }
473 
ctrl_end_scene(int abi,void __user * uarg)474 static long ctrl_end_scene(int abi, void __user *uarg)
475 {
476 	int rtg_id;
477 
478 	if (uarg == NULL)
479 		return -INVALID_ARG;
480 
481 	if (copy_from_user(&rtg_id, uarg, sizeof(int))) {
482 		pr_err("[SCHED_RTG] CMD_ID_END_SCENE copy data failed\n");
483 		return -INVALID_ARG;
484 	}
485 
486 	return stop_frame_freq(rtg_id);
487 }
488 
set_min_util(int gid,int min_util)489 static int set_min_util(int gid, int min_util)
490 {
491 	struct frame_info *frame_info = NULL;
492 
493 	frame_info = lookup_frame_info_by_grp_id(gid);
494 	if (!frame_info)
495 		return -FRAME_ERR_PID;
496 
497 	return set_frame_min_util(frame_info, min_util, false);
498 }
499 
ctrl_set_min_util(int abi,void __user * uarg)500 static long ctrl_set_min_util(int abi, void __user *uarg)
501 {
502 	struct proc_state_data state_data;
503 
504 	if (uarg == NULL)
505 		return -INVALID_ARG;
506 
507 	if (copy_from_user(&state_data, uarg, sizeof(state_data))) {
508 		pr_err("[SCHED_RTG] CMD_ID_SET_MIN_UTIL copy data failed\n");
509 		return -INVALID_ARG;
510 	}
511 
512 	return set_min_util(curr_grp_id(), state_data.state_param);
513 }
514 
set_margin(int grp_id,int margin)515 static int set_margin(int grp_id, int margin)
516 {
517 	struct frame_info *frame_info = NULL;
518 
519 	frame_info = lookup_frame_info_by_grp_id(grp_id);
520 	if (!frame_info)
521 		return -FRAME_ERR_PID;
522 
523 	set_frame_margin(frame_info, margin);
524 
525 	return SUCC;
526 }
527 
ctrl_set_margin(int abi,void __user * uarg)528 static long ctrl_set_margin(int abi, void __user *uarg)
529 {
530 	struct proc_state_data state_data;
531 
532 	if (uarg == NULL)
533 		return -INVALID_ARG;
534 
535 	if (copy_from_user(&state_data, uarg, sizeof(state_data))) {
536 		pr_err("[SCHED_RTG] CMD_ID_SET_MARGIN copy data failed\n");
537 		return -INVALID_ARG;
538 	}
539 
540 	return set_margin(curr_grp_id(), state_data.state_param);
541 }
542 
clear_rtg_frame_thread(struct frame_info * frame_info,bool reset)543 static void clear_rtg_frame_thread(struct frame_info *frame_info, bool reset)
544 {
545 	struct frame_thread_info frame_thread_info;
546 	int i;
547 
548 	if (!reset && frame_info)
549 		frame_thread_info.prio = frame_info->prio;
550 	else
551 		frame_thread_info.prio = NOT_RT_PRIO;
552 	for (i = 0; i < MAX_TID_NUM; i++)
553 		frame_thread_info.thread[i] = -1;
554 	frame_thread_info.thread_num = MAX_TID_NUM;
555 	update_frame_thread_info(frame_info, &frame_thread_info);
556 	if (reset) {
557 		atomic_set(&frame_info->max_rt_thread_num, DEFAULT_MAX_RT_THREAD);
558 		atomic_set(&frame_info->frame_sched_state, 0);
559 		trace_rtg_frame_sched(frame_info->rtg->id, "FRAME_SCHED_ENABLE", 0);
560 	}
561 }
562 
copy_proc_from_rsdata(struct rtg_proc_data * proc_info,const struct rtg_grp_data * rs_data)563 static void copy_proc_from_rsdata(struct rtg_proc_data *proc_info,
564 	const struct rtg_grp_data *rs_data)
565 {
566 	memset(proc_info, 0, sizeof(struct rtg_proc_data));
567 	proc_info->type = VIP;
568 	proc_info->rtcnt = DEFAULT_MAX_RT_THREAD;
569 	if ((rs_data->grp_type > 0) && (rs_data->grp_type < RTG_TYPE_MAX))
570 		proc_info->type = rs_data->grp_type;
571 	if ((rs_data->rt_cnt > 0) && (rs_data->rt_cnt < DEFAULT_MAX_RT_THREAD))
572 		proc_info->rtcnt = rs_data->rt_cnt;
573 }
574 
init_frame_thread_info(struct frame_thread_info * frame_thread_info,const struct rtg_proc_data * proc_info)575 static void init_frame_thread_info(struct frame_thread_info *frame_thread_info,
576 				   const struct rtg_proc_data *proc_info)
577 {
578 	int i;
579 	int type = proc_info->type;
580 
581 	frame_thread_info->prio = (type == NORMAL_TASK ? NOT_RT_PRIO : (type + DEFAULT_RT_PRIO));
582 	for (i = 0; i < MAX_TID_NUM; i++)
583 		frame_thread_info->thread[i] = proc_info->thread[i];
584 	frame_thread_info->thread_num = MAX_TID_NUM;
585 }
586 
parse_create_rtg_grp(const struct rtg_grp_data * rs_data)587 static int parse_create_rtg_grp(const struct rtg_grp_data *rs_data)
588 {
589 	struct rtg_proc_data proc_info;
590 	struct frame_info *frame_info;
591 	struct frame_thread_info frame_thread_info;
592 
593 	copy_proc_from_rsdata(&proc_info, rs_data);
594 	proc_info.rtgid = alloc_multi_frame_info();
595 	frame_info = rtg_frame_info(proc_info.rtgid);
596 	if (!frame_info) {
597 		pr_err("[SCHED_RTG] no free multi frame.\n");
598 		return -NO_FREE_MULTI_FRAME;
599 	}
600 	atomic_set(&frame_info->max_rt_thread_num, proc_info.rtcnt);
601 	if (update_rt_frame_num(frame_info, rs_data->grp_type, ADD_RTG_FRAME)) {
602 		release_multi_frame_info(proc_info.rtgid);
603 		return -NO_RT_FRAME;
604 	}
605 	init_frame_thread_info(&frame_thread_info, &proc_info);
606 	update_frame_thread_info(frame_info, &frame_thread_info);
607 	atomic_set(&frame_info->frame_sched_state, 1);
608 	pr_info("[SCHED_RTG] %s rtgid=%d, type=%d, prio=%d, threadnum=%d, rtnum=%d\n",
609 		__func__, proc_info.rtgid, rs_data->grp_type,
610 		frame_thread_info.prio, frame_thread_info.thread_num, proc_info.rtcnt);
611 
612 	return proc_info.rtgid;
613 }
614 
parse_add_rtg_thread(const struct rtg_grp_data * rs_data)615 static int parse_add_rtg_thread(const struct rtg_grp_data *rs_data)
616 {
617 	struct rtg_proc_data proc_info;
618 	struct frame_info *frame_info;
619 	int add_index;
620 	int add_num;
621 	int prio;
622 	int fail_num = 0;
623 	int i;
624 
625 	if ((rs_data->grp_id <= 0) || (rs_data->grp_id >= MAX_NUM_CGROUP_COLOC_ID))
626 		return -INVALID_ARG;
627 	copy_proc_from_rsdata(&proc_info, rs_data);
628 	frame_info = lookup_frame_info_by_grp_id(rs_data->grp_id);
629 	if (!frame_info) {
630 		pr_err("[SCHED_RTG] grp not created yet.\n");
631 		return -INVALID_ARG;
632 	}
633 	mutex_lock(&frame_info->lock);
634 	add_num = rs_data->tid_num;
635 	if ((frame_info->thread_num < 0) || (add_num < 0)) {
636 		mutex_unlock(&frame_info->lock);
637 		pr_err("[SCHED_RTG] Unexception err: frame_info num < 0.\n");
638 		return -INVALID_RTG_ID;
639 	}
640 	if (frame_info->thread_num + add_num > MAX_TID_NUM) {
641 		mutex_unlock(&frame_info->lock);
642 		return -INVALID_RTG_ID;
643 	}
644 	add_index = frame_info->thread_num;
645 	prio = (proc_info.type == NORMAL_TASK) ? NOT_RT_PRIO : frame_info->prio;
646 	for (i = 0; i < add_num; i++) {
647 		frame_info->thread[add_index] = update_frame_thread(frame_info, prio, prio,
648 								    rs_data->tids[i],
649 								    frame_info->thread[add_index]);
650 		if (frame_info->thread[add_index]) {
651 			atomic_set(&frame_info->thread_prio[add_index], prio);
652 			frame_info->thread_num++;
653 			add_index = frame_info->thread_num;
654 		} else {
655 			fail_num++;
656 		}
657 	}
658 	mutex_unlock(&frame_info->lock);
659 
660 	return fail_num;
661 }
662 
parse_remove_thread(const struct rtg_grp_data * rs_data)663 static int parse_remove_thread(const struct rtg_grp_data *rs_data)
664 {
665 	pr_err("[SCHED_RTG] frame rtg not support remove single yet.\n");
666 
667 	return -INVALID_ARG;
668 }
669 
do_clear_or_destroy_grp(const struct rtg_grp_data * rs_data,bool destroy)670 static int do_clear_or_destroy_grp(const struct rtg_grp_data *rs_data, bool destroy)
671 {
672 	struct frame_info *frame_info;
673 	int type;
674 	int id = rs_data->grp_id;
675 
676 	if (!is_frame_rtg(id)) {
677 		pr_err("[SCHED_RTG] Failed to destroy rtg group %d!\n", id);
678 		return -INVALID_ARG;
679 	}
680 
681 	frame_info = rtg_frame_info(id);
682 	if (!frame_info) {
683 		pr_err("[SCHED_RTG] Failed to destroy rtg group %d: grp not exist.\n", id);
684 		return -INVALID_ARG;
685 	}
686 
687 	type = frame_info->prio - DEFAULT_RT_PRIO;
688 	if (destroy) {
689 		clear_rtg_frame_thread(frame_info, true);
690 		release_multi_frame_info(id);
691 		update_rt_frame_num(frame_info, type, CLEAR_RTG_FRAME);
692 	} else {
693 		clear_rtg_frame_thread(frame_info, false);
694 	}
695 	pr_info("[SCHED_RTG] %s clear frame(id=%d)\n", __func__, id);
696 
697 	return SUCC;
698 }
699 
parse_destroy_grp(const struct rtg_grp_data * rs_data)700 static int parse_destroy_grp(const struct rtg_grp_data *rs_data)
701 {
702 	return do_clear_or_destroy_grp(rs_data, true);
703 }
704 
ctrl_set_rtg(int abi,void __user * uarg)705 long ctrl_set_rtg(int abi, void __user *uarg)
706 {
707 	struct rtg_grp_data rs_data;
708 	long ret;
709 
710 	if (copy_from_user(&rs_data, uarg, sizeof(rs_data))) {
711 		pr_err("[SCHED_RTG] CMD_ID_SET_RTG  copy data failed\n");
712 		return -INVALID_ARG;
713 	}
714 
715 	switch (rs_data.rtg_cmd) {
716 	case CMD_CREATE_RTG_GRP:
717 		ret = parse_create_rtg_grp(&rs_data);
718 		break;
719 	case CMD_ADD_RTG_THREAD:
720 		ret = parse_add_rtg_thread(&rs_data);
721 		break;
722 	case CMD_REMOVE_RTG_THREAD:
723 		ret = parse_remove_thread(&rs_data);
724 		break;
725 	case CMD_CLEAR_RTG_GRP:
726 		ret = -INVALID_ARG;
727 		break;
728 	case CMD_DESTROY_RTG_GRP:
729 		ret = parse_destroy_grp(&rs_data);
730 		break;
731 	default:
732 		return -INVALID_ARG;
733 	}
734 
735 	return ret;
736 }
737 
ctrl_search_rtg(int abi,void __user * uarg)738 static long ctrl_search_rtg(int abi, void __user *uarg)
739 {
740 	struct proc_state_data search_data;
741 
742 	if (copy_from_user(&search_data, uarg, sizeof(search_data))) {
743 		pr_err("[SCHED_RTG] CMD_ID_SEARCH_RTG copy data failed\n");
744 		return -INVALID_ARG;
745 	}
746 
747 	return search_rtg(search_data.state_param);
748 }
749 
do_proc_rtg_ioctl(int abi,struct file * file,unsigned int cmd,unsigned long arg)750 static long do_proc_rtg_ioctl(int abi, struct file *file, unsigned int cmd, unsigned long arg)
751 {
752 	void __user *uarg = (void __user *)(uintptr_t)arg;
753 	unsigned int func_id = _IOC_NR(cmd);
754 #ifdef CONFIG_RTG_AUTHORITY
755 	bool authorized = true;
756 #endif
757 
758 	if (uarg == NULL) {
759 		pr_err("[SCHED_RTG] %s: invalid user uarg\n", __func__);
760 		return -EINVAL;
761 	}
762 
763 	if (_IOC_TYPE(cmd) != RTG_SCHED_IPC_MAGIC) {
764 		pr_err("[SCHED_RTG] %s: RTG_SCHED_IPC_MAGIC fail, TYPE=%d\n",
765 			__func__, _IOC_TYPE(cmd));
766 		return -INVALID_MAGIC;
767 	}
768 
769 	if (!atomic_read(&g_rtg_enable) && (func_id != SET_ENABLE) && (func_id != GET_ENABLE)) {
770 		pr_err("[SCHED_RTG] CMD_ID %x error: Rtg not enabled yet.\n", cmd);
771 		return -RTG_DISABLED;
772 	}
773 
774 	if (func_id >= RTG_CTRL_MAX_NR) {
775 		pr_err("[SCHED_RTG] %s: RTG_MAX_NR fail, _IOC_NR(cmd)=%d, MAX_NR=%d\n",
776 			__func__, _IOC_NR(cmd), RTG_CTRL_MAX_NR);
777 		return -INVALID_CMD;
778 	}
779 
780 #ifdef CONFIG_RTG_AUTHORITY
781 	authorized = check_authorized(func_id, RTG_AUTH_FLAG);
782 	if (!authorized) {
783 		pr_err("[SCHED_RTG] %s: uid not authorized.\n", __func__);
784 		return -INVALID_CMD;
785 	}
786 #endif
787 	if (g_func_array[func_id] != NULL)
788 		return (*g_func_array[func_id])(abi, uarg);
789 
790 	return -EINVAL;
791 }
792 
reset_frame_info(struct frame_info * frame_info)793 static void reset_frame_info(struct frame_info *frame_info)
794 {
795 	int i;
796 	clear_rtg_frame_thread(frame_info, true);
797 	atomic_set(&frame_info->frame_state, -1);
798 	atomic_set(&frame_info->curr_rt_thread_num, 0);
799 	atomic_set(&frame_info->max_rt_thread_num, DEFAULT_MAX_RT_THREAD);
800 	for (i = 0; i < MAX_TID_NUM; i++)
801 		atomic_set(&frame_info->thread_prio[i], 0);
802 }
803 
do_init_proc_state(int rtgid,const int * config,int len)804 static int do_init_proc_state(int rtgid, const int *config, int len)
805 {
806 	struct related_thread_group *grp = NULL;
807 	struct frame_info *frame_info = NULL;
808 
809 	grp = lookup_related_thread_group(rtgid);
810 	if (unlikely(!grp))
811 		return -EINVAL;
812 
813 	frame_info = (struct frame_info *)grp->private_data;
814 	if (!frame_info)
815 		return -EINVAL;
816 
817 	reset_frame_info(frame_info);
818 
819 	if ((config[RTG_FREQ_CYCLE] >= MIN_FREQ_CYCLE) &&
820 		(config[RTG_FREQ_CYCLE] <= MAX_FREQ_CYCLE))
821 		sched_set_group_freq_update_interval(rtgid,
822 				(unsigned int)config[RTG_FREQ_CYCLE]);
823 	else
824 		sched_set_group_freq_update_interval(rtgid,
825 				DEFAULT_FREQ_CYCLE);
826 
827 	if (config[RTG_INVALID_INTERVAL] != INVALID_VALUE)
828 		sched_set_group_util_invalid_interval(rtgid,
829 				config[RTG_INVALID_INTERVAL]);
830 	else
831 		sched_set_group_util_invalid_interval(rtgid,
832 				DEFAULT_INVALID_INTERVAL);
833 
834 	set_frame_max_util(frame_info, g_frame_max_util);
835 
836 	return SUCC;
837 }
838 
init_proc_state(const int * config,int len)839 static int init_proc_state(const int *config, int len)
840 {
841 	int ret;
842 	int id;
843 
844 	if ((config == NULL) || (len != RTG_CONFIG_NUM))
845 		return -INVALID_ARG;
846 
847 	if ((config[RTG_FRAME_MAX_UTIL] > 0) &&
848 		(config[RTG_FRAME_MAX_UTIL] < DEFAULT_MAX_UTIL))
849 		g_frame_max_util = config[RTG_FRAME_MAX_UTIL];
850 
851 	for (id = MULTI_FRAME_ID; id < (MULTI_FRAME_ID + MULTI_FRAME_NUM); id++) {
852 		ret = do_init_proc_state(id, config, len);
853 		if (ret) {
854 			pr_err("[SCHED_RTG] init proc state for FRAME_ID=%d failed, ret=%d\n",
855 			       id, ret);
856 			return ret;
857 		}
858 	}
859 	atomic_set(&g_rt_frame_num, 0);
860 
861 	return SUCC;
862 }
863 
deinit_proc_state(void)864 static void deinit_proc_state(void)
865 {
866 	int id;
867 	struct frame_info *frame_info = NULL;
868 	struct related_thread_group *grp = NULL;
869 
870 	for (id = MULTI_FRAME_ID; id < (MULTI_FRAME_ID + MULTI_FRAME_NUM); id++) {
871 		grp = lookup_related_thread_group(id);
872 		if (unlikely(!grp))
873 			return;
874 
875 		frame_info = (struct frame_info *)grp->private_data;
876 		if (frame_info)
877 			reset_frame_info(frame_info);
878 	}
879 	clear_multi_frame_info();
880 	atomic_set(&g_rt_frame_num, 0);
881 }
882 
proc_rtg_open(struct inode * inode,struct file * filp)883 int proc_rtg_open(struct inode *inode, struct file *filp)
884 {
885 	return SUCC;
886 }
887 
proc_rtg_release(struct inode * inode,struct file * filp)888 static int proc_rtg_release(struct inode *inode, struct file *filp)
889 {
890 	return SUCC;
891 }
892 
proc_rtg_ioctl(struct file * file,unsigned int cmd,unsigned long arg)893 long proc_rtg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
894 {
895 	return do_proc_rtg_ioctl(IOCTL_ABI_AARCH64, file, cmd, arg);
896 }
897 
898 #ifdef CONFIG_COMPAT
proc_rtg_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)899 long proc_rtg_compat_ioctl(struct file *file,
900 				  unsigned int cmd, unsigned long arg)
901 {
902 	return do_proc_rtg_ioctl(IOCTL_ABI_ARM32, file, cmd,
903 		(unsigned long)(compat_ptr((compat_uptr_t)arg)));
904 }
905 #endif
906 
907 static const struct file_operations rtg_ctrl_fops = {
908 	.open = proc_rtg_open,
909 	.release = proc_rtg_release,
910 	.unlocked_ioctl = proc_rtg_ioctl,
911 #ifdef CONFIG_COMPAT
912 	.compat_ioctl	= proc_rtg_compat_ioctl,
913 #endif
914 };
915 
916 static struct miscdevice rtg_ctrl_device = {
917 	.minor = MISC_DYNAMIC_MINOR,
918 	.name = "sched_rtg_ctrl",
919 	.fops = &rtg_ctrl_fops,
920 	.mode = 0666,
921 };
922 
rtg_ctrl_dev_init(void)923 static int __init rtg_ctrl_dev_init(void)
924 {
925 	return misc_register(&rtg_ctrl_device);
926 }
927 
rtg_ctrl_dev_exit(void)928 static void __exit rtg_ctrl_dev_exit(void)
929 {
930 	misc_deregister(&rtg_ctrl_device);
931 }
932 
933 module_init(rtg_ctrl_dev_init);
934 module_exit(rtg_ctrl_dev_exit);
935