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