// SPDX-License-Identifier: GPL-2.0 /* * CMA ProcFS Interface * * Copyright (C) 2022 Rockchip Electronics Co., Ltd. */ #include #include #include #include #include #include "../../../mm/cma.h" static void cma_procfs_format_array(char *buf, size_t bufsize, u32 *array, int array_size) { int i = 0; while (--array_size >= 0) { size_t len; char term = (array_size && (++i % 8)) ? ' ' : '\n'; len = snprintf(buf, bufsize, "%08X%c", *array++, term); buf += len; bufsize -= len; } } static void cma_procfs_show_bitmap(struct seq_file *s, struct cma *cma) { int elements = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32)); int size = elements * 9; u32 *array = (u32 *)cma->bitmap; char *buf; buf = kmalloc(size + 1, GFP_KERNEL); if (!buf) return; buf[size] = 0; cma_procfs_format_array(buf, size + 1, array, elements); seq_printf(s, "%s", buf); kfree(buf); } static u64 cma_procfs_used_get(struct cma *cma) { unsigned long flags; unsigned long used; spin_lock_irqsave(&cma->lock, flags); used = bitmap_weight(cma->bitmap, (int)cma_bitmap_maxno(cma)); spin_unlock_irqrestore(&cma->lock, flags); return (u64)used << cma->order_per_bit; } static int cma_procfs_show(struct seq_file *s, void *private) { struct cma *cma = s->private; u64 used = cma_procfs_used_get(cma); seq_printf(s, "Total: %lu KiB\n", cma->count << (PAGE_SHIFT - 10)); seq_printf(s, " Used: %llu KiB\n\n", used << (PAGE_SHIFT - 10)); cma_procfs_show_bitmap(s, cma); return 0; } static int cma_procfs_add_one(struct cma *cma, void *data) { struct proc_dir_entry *root = data; proc_create_single_data(cma->name, 0, root, cma_procfs_show, cma); return 0; } static int rk_cma_procfs_init(void) { struct proc_dir_entry *root = proc_mkdir("rk_cma", NULL); return cma_for_each_area(cma_procfs_add_one, (void *)root); } late_initcall_sync(rk_cma_procfs_init); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jianqun Xu "); MODULE_DESCRIPTION("ROCKCHIP CMA PROCFS Driver"); MODULE_ALIAS("platform:rk-cma");