2021-05-05 04:37:28 +03:00
// SPDX-License-Identifier: GPL-2.0
/*
* CMA SysFS Interface
*
* Copyright ( c ) 2021 Minchan Kim < minchan @ kernel . org >
*/
# include <linux/cma.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include "cma.h"
# define CMA_ATTR_RO(_name) \
static struct kobj_attribute _name # # _attr = __ATTR_RO ( _name )
void cma_sysfs_account_success_pages ( struct cma * cma , unsigned long nr_pages )
{
atomic64_add ( nr_pages , & cma - > nr_pages_succeeded ) ;
}
void cma_sysfs_account_fail_pages ( struct cma * cma , unsigned long nr_pages )
{
atomic64_add ( nr_pages , & cma - > nr_pages_failed ) ;
}
2024-02-06 07:57:31 +03:00
void cma_sysfs_account_release_pages ( struct cma * cma , unsigned long nr_pages )
{
atomic64_add ( nr_pages , & cma - > nr_pages_released ) ;
}
2021-05-05 04:37:28 +03:00
static inline struct cma * cma_from_kobj ( struct kobject * kobj )
{
return container_of ( kobj , struct cma_kobject , kobj ) - > cma ;
}
static ssize_t alloc_pages_success_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
{
struct cma * cma = cma_from_kobj ( kobj ) ;
return sysfs_emit ( buf , " %llu \n " ,
atomic64_read ( & cma - > nr_pages_succeeded ) ) ;
}
CMA_ATTR_RO ( alloc_pages_success ) ;
static ssize_t alloc_pages_fail_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
{
struct cma * cma = cma_from_kobj ( kobj ) ;
return sysfs_emit ( buf , " %llu \n " , atomic64_read ( & cma - > nr_pages_failed ) ) ;
}
CMA_ATTR_RO ( alloc_pages_fail ) ;
2024-02-06 07:57:31 +03:00
static ssize_t release_pages_success_show ( struct kobject * kobj ,
struct kobj_attribute * attr , char * buf )
{
struct cma * cma = cma_from_kobj ( kobj ) ;
return sysfs_emit ( buf , " %llu \n " , atomic64_read ( & cma - > nr_pages_released ) ) ;
}
CMA_ATTR_RO ( release_pages_success ) ;
2021-05-05 04:37:28 +03:00
static void cma_kobj_release ( struct kobject * kobj )
{
struct cma * cma = cma_from_kobj ( kobj ) ;
struct cma_kobject * cma_kobj = cma - > cma_kobj ;
kfree ( cma_kobj ) ;
cma - > cma_kobj = NULL ;
}
static struct attribute * cma_attrs [ ] = {
& alloc_pages_success_attr . attr ,
& alloc_pages_fail_attr . attr ,
2024-02-06 07:57:31 +03:00
& release_pages_success_attr . attr ,
2021-05-05 04:37:28 +03:00
NULL ,
} ;
ATTRIBUTE_GROUPS ( cma ) ;
2023-02-21 02:23:31 +03:00
static const struct kobj_type cma_ktype = {
2021-05-05 04:37:28 +03:00
. release = cma_kobj_release ,
. sysfs_ops = & kobj_sysfs_ops ,
. default_groups = cma_groups ,
} ;
static int __init cma_sysfs_init ( void )
{
struct kobject * cma_kobj_root ;
struct cma_kobject * cma_kobj ;
struct cma * cma ;
int i , err ;
cma_kobj_root = kobject_create_and_add ( " cma " , mm_kobj ) ;
if ( ! cma_kobj_root )
return - ENOMEM ;
for ( i = 0 ; i < cma_area_count ; i + + ) {
cma_kobj = kzalloc ( sizeof ( * cma_kobj ) , GFP_KERNEL ) ;
if ( ! cma_kobj ) {
err = - ENOMEM ;
goto out ;
}
cma = & cma_areas [ i ] ;
cma - > cma_kobj = cma_kobj ;
cma_kobj - > cma = cma ;
err = kobject_init_and_add ( & cma_kobj - > kobj , & cma_ktype ,
cma_kobj_root , " %s " , cma - > name ) ;
if ( err ) {
kobject_put ( & cma_kobj - > kobj ) ;
goto out ;
}
}
return 0 ;
out :
while ( - - i > = 0 ) {
cma = & cma_areas [ i ] ;
kobject_put ( & cma - > cma_kobj - > kobj ) ;
}
kobject_put ( cma_kobj_root ) ;
return err ;
}
subsys_initcall ( cma_sysfs_init ) ;