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