• 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 void set_frame(struct frame_info *frame_info, int margin)
378 {
379 	if (!frame_info)
380 		return;
381 
382 	atomic_set(&frame_info->frame_state, FRAME_DRAWING);
383 	if (set_frame_margin(frame_info, margin) == SUCC)
384 		set_frame_timestamp(frame_info, FRAME_START);
385 }
386 
reset_frame(struct frame_info * frame_info)387 static void reset_frame(struct frame_info *frame_info)
388 {
389 	if (!frame_info)
390 		return;
391 
392 	if (atomic_read(&frame_info->frame_state) == FRAME_END_STATE) {
393 		pr_debug("[SCHED_RTG]: Frame state is already reset\n");
394 		return;
395 	}
396 
397 	atomic_set(&frame_info->frame_state, FRAME_END_STATE);
398 	set_frame_timestamp(frame_info, FRAME_END);
399 }
400 
update_frame_state(int grp_id,int margin,bool in_frame)401 int update_frame_state(int grp_id, int margin, bool in_frame)
402 {
403 	struct frame_info *frame_info = NULL;
404 
405 	frame_info = lookup_frame_info_by_grp_id(grp_id);
406 	if (!frame_info || !frame_info->rtg)
407 		return -INVALID_RTG_ID;
408 
409 	if (in_frame) {
410 		start_frame_freq(frame_info);
411 		set_frame(frame_info, margin);
412 		trace_rtg_frame_sched(grp_id, "margin", margin);
413 	} else {
414 		reset_frame(frame_info);
415 	}
416 
417 	return SUCC;
418 }
419 
curr_grp_id()420 static inline int curr_grp_id()
421 {
422 	return sched_get_group_id(current);
423 }
424 
ctrl_frame_state(void __user * uarg,bool is_enter)425 static long ctrl_frame_state(void __user *uarg, bool is_enter)
426 {
427 	struct proc_state_data state_data;
428 
429 	if (uarg == NULL)
430 		return -INVALID_ARG;
431 
432 	if (copy_from_user(&state_data, uarg, sizeof(state_data))) {
433 		pr_err("[SCHED_RTG] CMD_ID_FRAME_FREQ copy data failed\n");
434 		return -INVALID_ARG;
435 	}
436 
437 	return update_frame_state(curr_grp_id(), state_data.state_param, is_enter);
438 }
439 
ctrl_begin_frame(int abi,void __user * uarg)440 static long ctrl_begin_frame(int abi, void __user *uarg)
441 {
442 	return ctrl_frame_state(uarg, true);
443 }
444 
ctrl_end_frame(int abi,void __user * uarg)445 static long ctrl_end_frame(int abi, void __user *uarg)
446 {
447 	return ctrl_frame_state(uarg, false);
448 }
449 
stop_frame_freq(int gid)450 static int stop_frame_freq(int gid)
451 {
452 	struct frame_info *frame_info = NULL;
453 
454 	frame_info = lookup_frame_info_by_grp_id(gid);
455 	if (!frame_info)
456 		return -INVALID_RTG_ID;
457 
458 	atomic_set(&frame_info->start_frame_freq, 0);
459 	set_frame_sched_state(frame_info, false);
460 
461 	return 0;
462 }
463 
ctrl_end_scene(int abi,void __user * uarg)464 static long ctrl_end_scene(int abi, void __user *uarg)
465 {
466 	int rtg_id;
467 
468 	if (uarg == NULL)
469 		return -INVALID_ARG;
470 
471 	if (copy_from_user(&rtg_id, uarg, sizeof(int))) {
472 		pr_err("[SCHED_RTG] CMD_ID_END_SCENE copy data failed\n");
473 		return -INVALID_ARG;
474 	}
475 
476 	return stop_frame_freq(rtg_id);
477 }
478 
set_min_util(int gid,int min_util)479 static int set_min_util(int gid, int min_util)
480 {
481 	struct frame_info *frame_info = NULL;
482 
483 	frame_info = lookup_frame_info_by_grp_id(gid);
484 	if (!frame_info)
485 		return -FRAME_ERR_PID;
486 
487 	set_frame_min_util(frame_info, min_util, false);
488 
489 	return SUCC;
490 }
491 
ctrl_set_min_util(int abi,void __user * uarg)492 static long ctrl_set_min_util(int abi, void __user *uarg)
493 {
494 	struct proc_state_data state_data;
495 
496 	if (uarg == NULL)
497 		return -INVALID_ARG;
498 
499 	if (copy_from_user(&state_data, uarg, sizeof(state_data))) {
500 		pr_err("[SCHED_RTG] CMD_ID_SET_MIN_UTIL copy data failed\n");
501 		return -INVALID_ARG;
502 	}
503 
504 	return set_min_util(curr_grp_id(), state_data.state_param);
505 }
506 
set_margin(int grp_id,int margin)507 static int set_margin(int grp_id, int margin)
508 {
509 	struct frame_info *frame_info = NULL;
510 
511 	frame_info = lookup_frame_info_by_grp_id(grp_id);
512 	if (!frame_info)
513 		return -FRAME_ERR_PID;
514 
515 	set_frame_margin(frame_info, margin);
516 
517 	return SUCC;
518 }
519 
ctrl_set_margin(int abi,void __user * uarg)520 static long ctrl_set_margin(int abi, void __user *uarg)
521 {
522 	struct proc_state_data state_data;
523 
524 	if (uarg == NULL)
525 		return -INVALID_ARG;
526 
527 	if (copy_from_user(&state_data, uarg, sizeof(state_data))) {
528 		pr_err("[SCHED_RTG] CMD_ID_SET_MARGIN copy data failed\n");
529 		return -INVALID_ARG;
530 	}
531 
532 	return set_margin(curr_grp_id(), state_data.state_param);
533 }
534 
clear_rtg_frame_thread(struct frame_info * frame_info,bool reset)535 static void clear_rtg_frame_thread(struct frame_info *frame_info, bool reset)
536 {
537 	struct frame_thread_info frame_thread_info;
538 	int i;
539 
540 	if (!reset && frame_info)
541 		frame_thread_info.prio = frame_info->prio;
542 	else
543 		frame_thread_info.prio = NOT_RT_PRIO;
544 	for (i = 0; i < MAX_TID_NUM; i++)
545 		frame_thread_info.thread[i] = -1;
546 	frame_thread_info.thread_num = MAX_TID_NUM;
547 	update_frame_thread_info(frame_info, &frame_thread_info);
548 	if (reset) {
549 		atomic_set(&frame_info->max_rt_thread_num, DEFAULT_MAX_RT_THREAD);
550 		atomic_set(&frame_info->frame_sched_state, 0);
551 		trace_rtg_frame_sched(frame_info->rtg->id, "FRAME_SCHED_ENABLE", 0);
552 	}
553 }
554 
copy_proc_from_rsdata(struct rtg_proc_data * proc_info,const struct rtg_grp_data * rs_data)555 static void copy_proc_from_rsdata(struct rtg_proc_data *proc_info,
556 	const struct rtg_grp_data *rs_data)
557 {
558 	memset(proc_info, 0, sizeof(struct rtg_proc_data));
559 	proc_info->type = VIP;
560 	proc_info->rtcnt = DEFAULT_MAX_RT_THREAD;
561 	if ((rs_data->grp_type > 0) && (rs_data->grp_type < RTG_TYPE_MAX))
562 		proc_info->type = rs_data->grp_type;
563 	if ((rs_data->rt_cnt > 0) && (rs_data->rt_cnt < DEFAULT_MAX_RT_THREAD))
564 		proc_info->rtcnt = rs_data->rt_cnt;
565 }
566 
init_frame_thread_info(struct frame_thread_info * frame_thread_info,const struct rtg_proc_data * proc_info)567 static void init_frame_thread_info(struct frame_thread_info *frame_thread_info,
568 				   const struct rtg_proc_data *proc_info)
569 {
570 	int i;
571 	int type = proc_info->type;
572 
573 	frame_thread_info->prio = (type == NORMAL_TASK ? NOT_RT_PRIO : (type + DEFAULT_RT_PRIO));
574 	for (i = 0; i < MAX_TID_NUM; i++)
575 		frame_thread_info->thread[i] = proc_info->thread[i];
576 	frame_thread_info->thread_num = MAX_TID_NUM;
577 }
578 
parse_create_rtg_grp(const struct rtg_grp_data * rs_data)579 static int parse_create_rtg_grp(const struct rtg_grp_data *rs_data)
580 {
581 	struct rtg_proc_data proc_info;
582 	struct frame_info *frame_info;
583 	struct frame_thread_info frame_thread_info;
584 
585 	copy_proc_from_rsdata(&proc_info, rs_data);
586 	proc_info.rtgid = alloc_multi_frame_info();
587 	frame_info = rtg_frame_info(proc_info.rtgid);
588 	if (!frame_info) {
589 		pr_err("[SCHED_RTG] no free multi frame.\n");
590 		return -NO_FREE_MULTI_FRAME;
591 	}
592 	atomic_set(&frame_info->max_rt_thread_num, proc_info.rtcnt);
593 	if (update_rt_frame_num(frame_info, rs_data->grp_type, ADD_RTG_FRAME)) {
594 		release_multi_frame_info(proc_info.rtgid);
595 		return -NO_RT_FRAME;
596 	}
597 	init_frame_thread_info(&frame_thread_info, &proc_info);
598 	update_frame_thread_info(frame_info, &frame_thread_info);
599 	atomic_set(&frame_info->frame_sched_state, 1);
600 	pr_info("[SCHED_RTG] %s rtgid=%d, type=%d, prio=%d, threadnum=%d, rtnum=%d\n",
601 		__func__, proc_info.rtgid, rs_data->grp_type,
602 		frame_thread_info.prio, frame_thread_info.thread_num, proc_info.rtcnt);
603 
604 	return proc_info.rtgid;
605 }
606 
parse_add_rtg_thread(const struct rtg_grp_data * rs_data)607 static int parse_add_rtg_thread(const struct rtg_grp_data *rs_data)
608 {
609 	struct rtg_proc_data proc_info;
610 	struct frame_info *frame_info;
611 	int add_index;
612 	int add_num;
613 	int prio;
614 	int fail_num = 0;
615 	int i;
616 
617 	if ((rs_data->grp_id <= 0) || (rs_data->grp_id >= MAX_NUM_CGROUP_COLOC_ID))
618 		return -INVALID_ARG;
619 	copy_proc_from_rsdata(&proc_info, rs_data);
620 	frame_info = lookup_frame_info_by_grp_id(rs_data->grp_id);
621 	if (!frame_info) {
622 		pr_err("[SCHED_RTG] grp not created yet.\n");
623 		return -INVALID_ARG;
624 	}
625 	mutex_lock(&frame_info->lock);
626 	add_num = rs_data->tid_num;
627 	if ((frame_info->thread_num < 0) || (add_num < 0)) {
628 		mutex_unlock(&frame_info->lock);
629 		pr_err("[SCHED_RTG] Unexception err: frame_info num < 0.\n");
630 		return -INVALID_RTG_ID;
631 	}
632 	if (frame_info->thread_num + add_num > MAX_TID_NUM) {
633 		mutex_unlock(&frame_info->lock);
634 		return -INVALID_RTG_ID;
635 	}
636 	add_index = frame_info->thread_num;
637 	prio = (proc_info.type == NORMAL_TASK) ? NOT_RT_PRIO : frame_info->prio;
638 	for (i = 0; i < add_num; i++) {
639 		frame_info->thread[add_index] = update_frame_thread(frame_info, prio, prio,
640 								    rs_data->tids[i],
641 								    frame_info->thread[add_index]);
642 		if (frame_info->thread[add_index]) {
643 			atomic_set(&frame_info->thread_prio[add_index], prio);
644 			frame_info->thread_num++;
645 			add_index = frame_info->thread_num;
646 		} else {
647 			fail_num++;
648 		}
649 	}
650 	mutex_unlock(&frame_info->lock);
651 
652 	return fail_num;
653 }
654 
parse_remove_thread(const struct rtg_grp_data * rs_data)655 static int parse_remove_thread(const struct rtg_grp_data *rs_data)
656 {
657 	pr_err("[SCHED_RTG] frame rtg not support remove single yet.\n");
658 
659 	return -INVALID_ARG;
660 }
661 
do_clear_or_destroy_grp(const struct rtg_grp_data * rs_data,bool destroy)662 static int do_clear_or_destroy_grp(const struct rtg_grp_data *rs_data, bool destroy)
663 {
664 	struct frame_info *frame_info;
665 	int type;
666 	int id = rs_data->grp_id;
667 
668 	if (!is_frame_rtg(id)) {
669 		pr_err("[SCHED_RTG] Failed to destroy rtg group %d!\n", id);
670 		return -INVALID_ARG;
671 	}
672 
673 	frame_info = rtg_frame_info(id);
674 	if (!frame_info) {
675 		pr_err("[SCHED_RTG] Failed to destroy rtg group %d: grp not exist.\n", id);
676 		return -INVALID_ARG;
677 	}
678 
679 	type = frame_info->prio - DEFAULT_RT_PRIO;
680 	if (destroy) {
681 		clear_rtg_frame_thread(frame_info, true);
682 		release_multi_frame_info(id);
683 		update_rt_frame_num(frame_info, type, CLEAR_RTG_FRAME);
684 	} else {
685 		clear_rtg_frame_thread(frame_info, false);
686 	}
687 	pr_info("[SCHED_RTG] %s clear frame(id=%d)\n", __func__, id);
688 
689 	return SUCC;
690 }
691 
parse_destroy_grp(const struct rtg_grp_data * rs_data)692 static int parse_destroy_grp(const struct rtg_grp_data *rs_data)
693 {
694 	return do_clear_or_destroy_grp(rs_data, true);
695 }
696 
ctrl_set_rtg(int abi,void __user * uarg)697 long ctrl_set_rtg(int abi, void __user *uarg)
698 {
699 	struct rtg_grp_data rs_data;
700 	long ret;
701 
702 	if (copy_from_user(&rs_data, uarg, sizeof(rs_data))) {
703 		pr_err("[SCHED_RTG] CMD_ID_SET_RTG  copy data failed\n");
704 		return -INVALID_ARG;
705 	}
706 
707 	switch (rs_data.rtg_cmd) {
708 	case CMD_CREATE_RTG_GRP:
709 		ret = parse_create_rtg_grp(&rs_data);
710 		break;
711 	case CMD_ADD_RTG_THREAD:
712 		ret = parse_add_rtg_thread(&rs_data);
713 		break;
714 	case CMD_REMOVE_RTG_THREAD:
715 		ret = parse_remove_thread(&rs_data);
716 		break;
717 	case CMD_CLEAR_RTG_GRP:
718 		ret = -INVALID_ARG;
719 		break;
720 	case CMD_DESTROY_RTG_GRP:
721 		ret = parse_destroy_grp(&rs_data);
722 		break;
723 	default:
724 		return -INVALID_ARG;
725 	}
726 
727 	return ret;
728 }
729 
ctrl_search_rtg(int abi,void __user * uarg)730 static long ctrl_search_rtg(int abi, void __user *uarg)
731 {
732 	struct proc_state_data search_data;
733 
734 	if (copy_from_user(&search_data, uarg, sizeof(search_data))) {
735 		pr_err("[SCHED_RTG] CMD_ID_SEARCH_RTG copy data failed\n");
736 		return -INVALID_ARG;
737 	}
738 
739 	return search_rtg(search_data.state_param);
740 }
741 
do_proc_rtg_ioctl(int abi,struct file * file,unsigned int cmd,unsigned long arg)742 static long do_proc_rtg_ioctl(int abi, struct file *file, unsigned int cmd, unsigned long arg)
743 {
744 	void __user *uarg = (void __user *)(uintptr_t)arg;
745 	unsigned int func_id = _IOC_NR(cmd);
746 #ifdef CONFIG_RTG_AUTHORITY
747 	bool authorized = true;
748 #endif
749 
750 	if (uarg == NULL) {
751 		pr_err("[SCHED_RTG] %s: invalid user uarg\n", __func__);
752 		return -EINVAL;
753 	}
754 
755 	if (_IOC_TYPE(cmd) != RTG_SCHED_IPC_MAGIC) {
756 		pr_err("[SCHED_RTG] %s: RTG_SCHED_IPC_MAGIC fail, TYPE=%d\n",
757 			__func__, _IOC_TYPE(cmd));
758 		return -INVALID_MAGIC;
759 	}
760 
761 	if (!atomic_read(&g_rtg_enable) && (func_id != SET_ENABLE) && (func_id != GET_ENABLE)) {
762 		pr_err("[SCHED_RTG] CMD_ID %x error: Rtg not enabled yet.\n", cmd);
763 		return -RTG_DISABLED;
764 	}
765 
766 	if (func_id >= RTG_CTRL_MAX_NR) {
767 		pr_err("[SCHED_RTG] %s: RTG_MAX_NR fail, _IOC_NR(cmd)=%d, MAX_NR=%d\n",
768 			__func__, _IOC_NR(cmd), RTG_CTRL_MAX_NR);
769 		return -INVALID_CMD;
770 	}
771 
772 #ifdef CONFIG_RTG_AUTHORITY
773 	authorized = check_authorized(func_id, RTG_AUTH_FLAG);
774 	if (!authorized) {
775 		pr_err("[SCHED_RTG] %s: uid not authorized.\n", __func__);
776 		return -INVALID_CMD;
777 	}
778 #endif
779 	if (g_func_array[func_id] != NULL)
780 		return (*g_func_array[func_id])(abi, uarg);
781 
782 	return -EINVAL;
783 }
784 
reset_frame_info(struct frame_info * frame_info)785 static void reset_frame_info(struct frame_info *frame_info)
786 {
787 	int i;
788 	clear_rtg_frame_thread(frame_info, true);
789 	atomic_set(&frame_info->frame_state, -1);
790 	atomic_set(&frame_info->curr_rt_thread_num, 0);
791 	atomic_set(&frame_info->max_rt_thread_num, DEFAULT_MAX_RT_THREAD);
792 	for (i = 0; i < MAX_TID_NUM; i++)
793 		atomic_set(&frame_info->thread_prio[i], 0);
794 }
795 
do_init_proc_state(int rtgid,const int * config,int len)796 static int do_init_proc_state(int rtgid, const int *config, int len)
797 {
798 	struct related_thread_group *grp = NULL;
799 	struct frame_info *frame_info = NULL;
800 
801 	grp = lookup_related_thread_group(rtgid);
802 	if (unlikely(!grp))
803 		return -EINVAL;
804 
805 	frame_info = (struct frame_info *)grp->private_data;
806 	if (!frame_info)
807 		return -EINVAL;
808 
809 	reset_frame_info(frame_info);
810 
811 	if ((config[RTG_FREQ_CYCLE] >= MIN_FREQ_CYCLE) &&
812 		(config[RTG_FREQ_CYCLE] <= MAX_FREQ_CYCLE))
813 		sched_set_group_freq_update_interval(rtgid,
814 				(unsigned int)config[RTG_FREQ_CYCLE]);
815 	else
816 		sched_set_group_freq_update_interval(rtgid,
817 				DEFAULT_FREQ_CYCLE);
818 
819 	if (config[RTG_INVALID_INTERVAL] != INVALID_VALUE)
820 		sched_set_group_util_invalid_interval(rtgid,
821 				config[RTG_INVALID_INTERVAL]);
822 	else
823 		sched_set_group_util_invalid_interval(rtgid,
824 				DEFAULT_INVALID_INTERVAL);
825 
826 	set_frame_max_util(frame_info, g_frame_max_util);
827 
828 	return SUCC;
829 }
830 
init_proc_state(const int * config,int len)831 static int init_proc_state(const int *config, int len)
832 {
833 	int ret;
834 	int id;
835 
836 	if ((config == NULL) || (len != RTG_CONFIG_NUM))
837 		return -INVALID_ARG;
838 
839 	if ((config[RTG_FRAME_MAX_UTIL] > 0) &&
840 		(config[RTG_FRAME_MAX_UTIL] < DEFAULT_MAX_UTIL))
841 		g_frame_max_util = config[RTG_FRAME_MAX_UTIL];
842 
843 	for (id = MULTI_FRAME_ID; id < (MULTI_FRAME_ID + MULTI_FRAME_NUM); id++) {
844 		ret = do_init_proc_state(id, config, len);
845 		if (ret) {
846 			pr_err("[SCHED_RTG] init proc state for FRAME_ID=%d failed, ret=%d\n",
847 			       id, ret);
848 			return ret;
849 		}
850 	}
851 	atomic_set(&g_rt_frame_num, 0);
852 
853 	return SUCC;
854 }
855 
deinit_proc_state(void)856 static void deinit_proc_state(void)
857 {
858 	int id;
859 	struct frame_info *frame_info = NULL;
860 	struct related_thread_group *grp = NULL;
861 
862 	for (id = MULTI_FRAME_ID; id < (MULTI_FRAME_ID + MULTI_FRAME_NUM); id++) {
863 		grp = lookup_related_thread_group(id);
864 		if (unlikely(!grp))
865 			return;
866 
867 		frame_info = (struct frame_info *)grp->private_data;
868 		if (frame_info)
869 			reset_frame_info(frame_info);
870 	}
871 	clear_multi_frame_info();
872 	atomic_set(&g_rt_frame_num, 0);
873 }
874 
proc_rtg_open(struct inode * inode,struct file * filp)875 int proc_rtg_open(struct inode *inode, struct file *filp)
876 {
877 	return SUCC;
878 }
879 
proc_rtg_release(struct inode * inode,struct file * filp)880 static int proc_rtg_release(struct inode *inode, struct file *filp)
881 {
882 	return SUCC;
883 }
884 
proc_rtg_ioctl(struct file * file,unsigned int cmd,unsigned long arg)885 long proc_rtg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
886 {
887 	return do_proc_rtg_ioctl(IOCTL_ABI_AARCH64, file, cmd, arg);
888 }
889 
890 #ifdef CONFIG_COMPAT
proc_rtg_compat_ioctl(struct file * file,unsigned int cmd,unsigned long arg)891 long proc_rtg_compat_ioctl(struct file *file,
892 				  unsigned int cmd, unsigned long arg)
893 {
894 	return do_proc_rtg_ioctl(IOCTL_ABI_ARM32, file, cmd,
895 		(unsigned long)(compat_ptr((compat_uptr_t)arg)));
896 }
897 #endif
898 
899 static const struct file_operations rtg_ctrl_fops = {
900 	.open = proc_rtg_open,
901 	.release = proc_rtg_release,
902 	.unlocked_ioctl = proc_rtg_ioctl,
903 #ifdef CONFIG_COMPAT
904 	.compat_ioctl	= proc_rtg_compat_ioctl,
905 #endif
906 };
907 
908 static struct miscdevice rtg_ctrl_device = {
909 	.minor = MISC_DYNAMIC_MINOR,
910 	.name = "sched_rtg_ctrl",
911 	.fops = &rtg_ctrl_fops,
912 	.mode = 0666,
913 };
914 
rtg_ctrl_dev_init(void)915 static int __init rtg_ctrl_dev_init(void)
916 {
917 	return misc_register(&rtg_ctrl_device);
918 }
919 
rtg_ctrl_dev_exit(void)920 static void __exit rtg_ctrl_dev_exit(void)
921 {
922 	misc_deregister(&rtg_ctrl_device);
923 }
924 
925 module_init(rtg_ctrl_dev_init);
926 module_exit(rtg_ctrl_dev_exit);
927