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