^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * CMA SysFS Interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2021 Minchan Kim <minchan@kernel.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/cma.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "cma.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static bool experimental;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define CMA_ATTR_RO(_name) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) void cma_sysfs_account_success_pages(struct cma *cma, unsigned long nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) atomic64_add(nr_pages, &cma->nr_pages_succeeded);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) void cma_sysfs_account_fail_pages(struct cma *cma, unsigned long nr_pages)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) atomic64_add(nr_pages, &cma->nr_pages_failed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static inline struct cma *cma_from_kobj(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return container_of(kobj, struct cma_kobject, kobj)->cma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static ssize_t alloc_pages_success_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct kobj_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct cma *cma = cma_from_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return sysfs_emit(buf, "%llu\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) atomic64_read(&cma->nr_pages_succeeded));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) CMA_ATTR_RO(alloc_pages_success);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static ssize_t alloc_pages_fail_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct kobj_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) struct cma *cma = cma_from_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return sysfs_emit(buf, "%llu\n", atomic64_read(&cma->nr_pages_failed));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) CMA_ATTR_RO(alloc_pages_fail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static void cma_kobj_release(struct kobject *kobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct cma *cma = cma_from_kobj(kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct cma_kobject *cma_kobj = cma->cma_kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) kfree(cma_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) cma->cma_kobj = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static struct attribute *cma_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) &alloc_pages_success_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) &alloc_pages_fail_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) ATTRIBUTE_GROUPS(cma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static struct kobj_type cma_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) .release = cma_kobj_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .sysfs_ops = &kobj_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) .default_groups = cma_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) static int __init cma_sysfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct kobject *cma_kobj_root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct cma_kobject *cma_kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct cma *cma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int i, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!experimental)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) cma_kobj_root = kobject_create_and_add("cma", mm_kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (!cma_kobj_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) for (i = 0; i < cma_area_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) cma_kobj = kzalloc(sizeof(*cma_kobj), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!cma_kobj) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) err = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) cma = &cma_areas[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) cma->cma_kobj = cma_kobj;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) cma_kobj->cma = cma;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) err = kobject_init_and_add(&cma_kobj->kobj, &cma_ktype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) cma_kobj_root, "%s", cma->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) kobject_put(&cma_kobj->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) while (--i >= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) cma = &cma_areas[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) kobject_put(&cma->cma_kobj->kobj);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) kobject_put(cma_kobj_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) subsys_initcall(cma_sysfs_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) module_param(experimental, bool, 0400);