// SPDX-License-Identifier: GPL-2.0 /* * drivers/auth_ctl/auth_qos_debug.c * * Copyright (c) 2022 Huawei Device Co., Ltd. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "auth_ctrl.h" #include "qos_ctrl.h" #define seq_printf_auth(m, x...) \ do { \ if (m) \ seq_printf(m, x); \ else \ printk(x); \ } while (0) static void print_auth_id(struct seq_file *file, const int tgid) { seq_printf_auth(file, "AUTH_PID :%d\n", tgid); } static void print_auth_info(struct seq_file *file, const struct auth_struct *auth) { seq_printf_auth(file, "AUTH_STATUS :%d\n", auth->status); #ifdef CONFIG_RTG_AUTHORITY seq_printf_auth(file, "RTG_FLAG :%04x\n", auth->rtg_auth_flag); #endif #ifdef CONFIG_QOS_AUTHORITY seq_printf_auth(file, "QOS_FLAG :%04x\n", auth->qos_auth_flag); #endif } static void print_qos_count(struct seq_file *file, const struct auth_struct *auth) { int i; for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i) seq_printf_auth(file, "QOS level %d thread nr :%d\n", i, auth->num[i]); } static void print_qos_thread(struct seq_file *file, const struct auth_struct *auth) { struct qos_task_struct *tmp, *next; struct task_struct *p; int i; for (i = QOS_POLICY_MIN_LEVEL; i < NR_QOS; ++i) { seq_printf_auth(file, "QOS level %d threads:", i); list_for_each_entry_safe(tmp, next, &auth->tasks[i], qos_list) { p = container_of(tmp, struct task_struct, qts); seq_printf_auth(file, "%d ", p->pid); } seq_printf_auth(file, "\n"); } } static inline void print_auth_struct(struct seq_file *file, struct auth_struct *auth) { print_auth_info(file, auth); seq_printf_auth(file, "\n"); print_qos_count(file, auth); seq_printf_auth(file, "\n"); #ifdef CONFIG_QOS_CTRL print_qos_thread(file, auth); #endif seq_printf_auth(file, "---------------------------------------------------------\n"); } int authority_printf_handler(int id, void *p, void *para) { struct auth_struct *auth = (struct auth_struct *)p; struct seq_file *file = (struct seq_file *)para; /* * data consistency is not that important here */ seq_printf_auth(file, "\n\n"); print_auth_id(file, id); seq_printf_auth(file, "\n"); /* no need to add refcount here, auth must alive in ua_idr_mutex */ print_auth_struct(file, auth); return 0; } static int sched_auth_debug_show(struct seq_file *file, void *param) { struct idr *ua_idr = get_auth_ctrl_idr(); struct mutex *ua_idr_mutex = get_auth_idr_mutex(); /* * NOTICE: * if mutex in authority_printf_handler, sleep may occur * change ths spin_lock to mutex, or remove mutex in handler */ mutex_lock(ua_idr_mutex); /* will never return 0 here, auth in ua_idr must alive */ idr_for_each(ua_idr, authority_printf_handler, file); mutex_unlock(ua_idr_mutex); return 0; } static int sched_auth_debug_release(struct inode *inode, struct file *file) { seq_release(inode, file); return 0; } static int sched_auth_debug_open(struct inode *inode, struct file *filp) { return single_open(filp, sched_auth_debug_show, NULL); } static const struct proc_ops sched_auth_debug_fops = { .proc_open = sched_auth_debug_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = sched_auth_debug_release, }; int __init init_sched_auth_debug_procfs(void) { struct proc_dir_entry *pe = NULL; pe = proc_create("sched_auth_qos_debug", 0400, NULL, &sched_auth_debug_fops); if (unlikely(!pe)) return -ENOMEM; return 0; }