2005-07-16 05:38:08 +04:00
/*
hwmon . c - part of lm_sensors , Linux kernel modules for hardware monitoring
This file defines the sysfs class " hwmon " , for use by sensors drivers .
Copyright ( C ) 2005 Mark M . Hoffman < mhoffman @ lightlink . com >
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; version 2 of the License .
*/
# include <linux/module.h>
# include <linux/device.h>
# include <linux/err.h>
# include <linux/kdev_t.h>
# include <linux/idr.h>
# include <linux/hwmon.h>
2005-11-07 11:59:43 +03:00
# include <linux/gfp.h>
2006-03-06 01:13:47 +03:00
# include <linux/spinlock.h>
2005-07-16 05:38:08 +04:00
# define HWMON_ID_PREFIX "hwmon"
# define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
static struct class * hwmon_class ;
static DEFINE_IDR ( hwmon_idr ) ;
2006-03-06 01:13:47 +03:00
static DEFINE_SPINLOCK ( idr_lock ) ;
2005-07-16 05:38:08 +04:00
/**
2007-08-21 00:46:20 +04:00
* hwmon_device_register - register w / hwmon
2005-07-16 05:38:08 +04:00
* @ dev : the device to register
*
2007-08-21 00:46:20 +04:00
* hwmon_device_unregister ( ) must be called when the device is no
2005-07-16 05:38:08 +04:00
* longer needed .
*
2007-08-21 00:46:20 +04:00
* Returns the pointer to the new device .
2005-07-16 05:38:08 +04:00
*/
2007-08-21 00:46:20 +04:00
struct device * hwmon_device_register ( struct device * dev )
2005-07-16 05:38:08 +04:00
{
2007-08-21 00:46:20 +04:00
struct device * hwdev ;
2006-03-06 01:13:47 +03:00
int id , err ;
2005-07-16 05:38:08 +04:00
2006-03-06 01:13:47 +03:00
again :
if ( unlikely ( idr_pre_get ( & hwmon_idr , GFP_KERNEL ) = = 0 ) )
2005-07-16 05:38:08 +04:00
return ERR_PTR ( - ENOMEM ) ;
2006-03-06 01:13:47 +03:00
spin_lock ( & idr_lock ) ;
err = idr_get_new ( & hwmon_idr , NULL , & id ) ;
spin_unlock ( & idr_lock ) ;
if ( unlikely ( err = = - EAGAIN ) )
goto again ;
else if ( unlikely ( err ) )
return ERR_PTR ( err ) ;
2005-07-16 05:38:08 +04:00
id = id & MAX_ID_MASK ;
2007-08-21 00:46:20 +04:00
hwdev = device_create ( hwmon_class , dev , MKDEV ( 0 , 0 ) , HWMON_ID_FORMAT , id ) ;
2005-07-16 05:38:08 +04:00
2007-08-21 00:46:20 +04:00
if ( IS_ERR ( hwdev ) ) {
2006-03-06 01:13:47 +03:00
spin_lock ( & idr_lock ) ;
2005-07-16 05:38:08 +04:00
idr_remove ( & hwmon_idr , id ) ;
2006-03-06 01:13:47 +03:00
spin_unlock ( & idr_lock ) ;
}
2005-07-16 05:38:08 +04:00
2007-08-21 00:46:20 +04:00
return hwdev ;
2005-07-16 05:38:08 +04:00
}
/**
* hwmon_device_unregister - removes the previously registered class device
*
2007-08-21 00:46:20 +04:00
* @ dev : the class device to destroy
2005-07-16 05:38:08 +04:00
*/
2007-08-21 00:46:20 +04:00
void hwmon_device_unregister ( struct device * dev )
2005-07-16 05:38:08 +04:00
{
int id ;
2007-08-21 00:46:20 +04:00
if ( likely ( sscanf ( dev - > bus_id , HWMON_ID_FORMAT , & id ) = = 1 ) ) {
device_unregister ( dev ) ;
2006-03-06 01:13:47 +03:00
spin_lock ( & idr_lock ) ;
2005-07-16 05:38:08 +04:00
idr_remove ( & hwmon_idr , id ) ;
2006-03-06 01:13:47 +03:00
spin_unlock ( & idr_lock ) ;
2005-07-16 05:38:08 +04:00
} else
2007-08-21 00:46:20 +04:00
dev_dbg ( dev - > parent ,
2005-07-16 05:38:08 +04:00
" hwmon_device_unregister() failed: bad class ID! \n " ) ;
}
static int __init hwmon_init ( void )
{
hwmon_class = class_create ( THIS_MODULE , " hwmon " ) ;
if ( IS_ERR ( hwmon_class ) ) {
printk ( KERN_ERR " hwmon.c: couldn't create sysfs class \n " ) ;
return PTR_ERR ( hwmon_class ) ;
}
return 0 ;
}
static void __exit hwmon_exit ( void )
{
class_destroy ( hwmon_class ) ;
}
2007-02-14 23:15:04 +03:00
subsys_initcall ( hwmon_init ) ;
2005-07-16 05:38:08 +04:00
module_exit ( hwmon_exit ) ;
EXPORT_SYMBOL_GPL ( hwmon_device_register ) ;
EXPORT_SYMBOL_GPL ( hwmon_device_unregister ) ;
MODULE_AUTHOR ( " Mark M. Hoffman <mhoffman@lightlink.com> " ) ;
MODULE_DESCRIPTION ( " hardware monitoring sysfs/class support " ) ;
MODULE_LICENSE ( " GPL " ) ;