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