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