2021-08-23 12:26:22 +08:00
// SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause
2015-07-30 15:17:43 -04:00
/*
2016-02-14 20:22:17 -08:00
* Copyright ( c ) 2015 , 2016 Intel Corporation .
2015-07-30 15:17:43 -04:00
*/
# include <linux/cdev.h>
# include <linux/device.h>
# include <linux/fs.h>
# include "hfi.h"
# include "device.h"
static struct class * class ;
2015-09-17 13:47:49 -04:00
static struct class * user_class ;
2015-07-30 15:17:43 -04:00
static dev_t hfi1_dev ;
int hfi1_cdev_init ( int minor , const char * name ,
const struct file_operations * fops ,
2015-09-17 13:47:49 -04:00
struct cdev * cdev , struct device * * devp ,
2016-05-19 05:26:44 -07:00
bool user_accessible ,
struct kobject * parent )
2015-07-30 15:17:43 -04:00
{
const dev_t dev = MKDEV ( MAJOR ( hfi1_dev ) , minor ) ;
struct device * device = NULL ;
int ret ;
cdev_init ( cdev , fops ) ;
cdev - > owner = THIS_MODULE ;
2017-03-17 12:48:16 -06:00
cdev_set_parent ( cdev , parent ) ;
2015-07-30 15:17:43 -04:00
kobject_set_name ( & cdev - > kobj , name ) ;
ret = cdev_add ( cdev , dev , 1 ) ;
if ( ret < 0 ) {
pr_err ( " Could not add cdev for minor %d, %s (err %d) \n " ,
minor , name , - ret ) ;
goto done ;
}
2015-09-17 13:47:49 -04:00
if ( user_accessible )
device = device_create ( user_class , NULL , dev , NULL , " %s " , name ) ;
else
device = device_create ( class , NULL , dev , NULL , " %s " , name ) ;
2016-05-19 05:22:03 -07:00
if ( IS_ERR ( device ) ) {
ret = PTR_ERR ( device ) ;
device = NULL ;
pr_err ( " Could not create device for minor %d, %s (err %d) \n " ,
minor , name , - ret ) ;
cdev_del ( cdev ) ;
}
2015-07-30 15:17:43 -04:00
done :
* devp = device ;
return ret ;
}
void hfi1_cdev_cleanup ( struct cdev * cdev , struct device * * devp )
{
struct device * device = * devp ;
if ( device ) {
device_unregister ( device ) ;
* devp = NULL ;
cdev_del ( cdev ) ;
}
}
static const char * hfi1_class_name = " hfi1 " ;
const char * class_name ( void )
{
return hfi1_class_name ;
}
2022-11-23 13:25:20 +01:00
static char * hfi1_devnode ( const struct device * dev , umode_t * mode )
2015-09-17 13:47:49 -04:00
{
if ( mode )
* mode = 0600 ;
return kasprintf ( GFP_KERNEL , " %s " , dev_name ( dev ) ) ;
}
static const char * hfi1_class_name_user = " hfi1_user " ;
2015-09-21 22:18:14 +08:00
static const char * class_name_user ( void )
2015-09-17 13:47:49 -04:00
{
return hfi1_class_name_user ;
}
2022-11-23 13:25:20 +01:00
static char * hfi1_user_devnode ( const struct device * dev , umode_t * mode )
2015-09-17 13:47:49 -04:00
{
if ( mode )
* mode = 0666 ;
return kasprintf ( GFP_KERNEL , " %s " , dev_name ( dev ) ) ;
}
2015-07-30 15:17:43 -04:00
int __init dev_init ( void )
{
int ret ;
ret = alloc_chrdev_region ( & hfi1_dev , 0 , HFI1_NMINORS , DRIVER_NAME ) ;
if ( ret < 0 ) {
pr_err ( " Could not allocate chrdev region (err %d) \n " , - ret ) ;
goto done ;
}
2023-03-13 19:18:35 +01:00
class = class_create ( class_name ( ) ) ;
2015-07-30 15:17:43 -04:00
if ( IS_ERR ( class ) ) {
ret = PTR_ERR ( class ) ;
pr_err ( " Could not create device class (err %d) \n " , - ret ) ;
unregister_chrdev_region ( hfi1_dev , HFI1_NMINORS ) ;
2015-09-17 13:47:49 -04:00
goto done ;
2015-07-30 15:17:43 -04:00
}
2015-09-17 13:47:49 -04:00
class - > devnode = hfi1_devnode ;
2023-03-13 19:18:35 +01:00
user_class = class_create ( class_name_user ( ) ) ;
2015-09-17 13:47:49 -04:00
if ( IS_ERR ( user_class ) ) {
ret = PTR_ERR ( user_class ) ;
pr_err ( " Could not create device class for user accessible files (err %d) \n " ,
- ret ) ;
class_destroy ( class ) ;
class = NULL ;
user_class = NULL ;
unregister_chrdev_region ( hfi1_dev , HFI1_NMINORS ) ;
goto done ;
}
user_class - > devnode = hfi1_user_devnode ;
2015-07-30 15:17:43 -04:00
done :
return ret ;
}
void dev_cleanup ( void )
{
2015-09-17 13:47:49 -04:00
class_destroy ( class ) ;
class = NULL ;
class_destroy ( user_class ) ;
user_class = NULL ;
2015-07-30 15:17:43 -04:00
unregister_chrdev_region ( hfi1_dev , HFI1_NMINORS ) ;
}