18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * mm/lmkd_dbg_trigger.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2022 Huawei Technologies Co., Ltd.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <linux/atomic.h>
88c2ecf20Sopenharmony_ci#include <linux/fs.h>
98c2ecf20Sopenharmony_ci#include <linux/init.h>
108c2ecf20Sopenharmony_ci#include <linux/kernel.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/oom.h>
138c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
148c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
158c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
168c2ecf20Sopenharmony_ci#include <linux/lowmem_dbg.h>
178c2ecf20Sopenharmony_ci#define PROC_NUMBUF 8
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic int lmkd_oom_score_adj;
208c2ecf20Sopenharmony_cistatic atomic64_t lmkd_no_cma_cnt = ATOMIC64_INIT(0);
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic int lmkd_dbg_trigger_proc_show(struct seq_file *m, void *v)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	seq_printf(m, "lmkd_oom_score_adj: %d\n", lmkd_oom_score_adj);
258c2ecf20Sopenharmony_ci	seq_printf(m, "lmkd_no_cma_cnt: %lld\n",
268c2ecf20Sopenharmony_ci		atomic64_read(&lmkd_no_cma_cnt));
278c2ecf20Sopenharmony_ci	return 0;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic int lmkd_dbg_trigger_proc_open(struct inode *inode, struct file *file)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	return single_open(file, lmkd_dbg_trigger_proc_show, NULL);
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic ssize_t lmkd_dbg_trigger_write(struct file *file, const char __user *buf,
368c2ecf20Sopenharmony_ci	       size_t count, loff_t *ppos)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	char buffer[PROC_NUMBUF];
398c2ecf20Sopenharmony_ci	int oom_score_adj;
408c2ecf20Sopenharmony_ci	int err;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	memset(buffer, 0, sizeof(buffer));
438c2ecf20Sopenharmony_ci	if (count > sizeof(buffer) - 1)
448c2ecf20Sopenharmony_ci		count = sizeof(buffer) - 1;
458c2ecf20Sopenharmony_ci	if (copy_from_user(buffer, buf, count)) {
468c2ecf20Sopenharmony_ci		err = -EFAULT;
478c2ecf20Sopenharmony_ci		goto out;
488c2ecf20Sopenharmony_ci	}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	err = kstrtoint(strstrip(buffer), 0, &oom_score_adj);
518c2ecf20Sopenharmony_ci	if (err)
528c2ecf20Sopenharmony_ci		goto out;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	if (oom_score_adj < OOM_SCORE_ADJ_MIN ||
558c2ecf20Sopenharmony_ci		oom_score_adj > OOM_SCORE_ADJ_MAX) {
568c2ecf20Sopenharmony_ci		err = -EINVAL;
578c2ecf20Sopenharmony_ci		goto out;
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	lmkd_oom_score_adj = oom_score_adj;
618c2ecf20Sopenharmony_ci	lowmem_dbg(oom_score_adj);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ciout:
648c2ecf20Sopenharmony_ci	return err < 0 ? err : count;
658c2ecf20Sopenharmony_ci}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic const struct proc_ops lmkd_dbg_trigger_proc_fops = {
688c2ecf20Sopenharmony_ci	.proc_open		= lmkd_dbg_trigger_proc_open,
698c2ecf20Sopenharmony_ci	.proc_read		= seq_read,
708c2ecf20Sopenharmony_ci	.proc_lseek		= seq_lseek,
718c2ecf20Sopenharmony_ci	.proc_release		= single_release,
728c2ecf20Sopenharmony_ci	.proc_write		= lmkd_dbg_trigger_write,
738c2ecf20Sopenharmony_ci};
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic int __init proc_lmkd_dbg_trigger_init(void)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	proc_create("lmkd_dbg_trigger", 0660, NULL,
788c2ecf20Sopenharmony_ci			&lmkd_dbg_trigger_proc_fops);
798c2ecf20Sopenharmony_ci	return 0;
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cifs_initcall(proc_lmkd_dbg_trigger_init);
838c2ecf20Sopenharmony_ci
84